Skip to content
15 changes: 15 additions & 0 deletions examples/searchApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const bandcamp = require('../lib/index')

const body = {
search_text: 'test',
search_filter: 'a',
full_page: false
}

bandcamp.searchApi(body, function (error, searchResults) {
if (error) {
console.log(error)
} else {
console.log(searchResults)
}
})
32 changes: 31 additions & 1 deletion lib/htmlParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,12 @@ exports.parseAlbumInfo = function (html, albumUrl) {
}
}

// Parse pageData.
const scriptWithPageData = $('script[type="application/ld+json"]')
if (scriptWithPageData.length > 0) {
object.pageData = JSON5.parse(scriptWithPageData.text())
}

object.url = albumUrl
// validate through JSON schema
if (ajv.validate('album-info', object)) {
Expand Down Expand Up @@ -385,6 +391,10 @@ exports.parseArtistInfo = function (html, artistUrl) {
selector: '.bio-pic a',
attr: 'href'
},
bannerImage: {
selector: '.desktop-header a img',
attr: 'src'
},
description: 'p#bio-text',
albums: {
listItem: '.music-grid-item',
Expand Down Expand Up @@ -453,14 +463,34 @@ exports.parseArtistInfo = function (html, artistUrl) {
const albums = data.albums.map(mapAlbums)
const mergedAlbums = [...new Set([...albums, ...data.discographyAlbums])]

// Parse raw.
const scriptWithRaw = $('script[data-tralbum]')
if (scriptWithRaw.length > 0) {
data.raw = scriptWithRaw.data('band')
} else {
let raw = this.extractJavascriptObjectVariable(html, 'BandData')
// The only javascript in the variable is the concatenation of the base url
// with the current album path. We nned to do it yourself.
// Ex:
// url: "http://musique.coeurdepirate.com" + "/album/blonde",
raw = raw ? raw.replace('" + "', '') : ''
try {
data.raw = JSON5.parse(raw)
} catch (error) {
console.error(error)
}
}

return {
name: data.name,
location: data.location,
description: data.description,
coverImage: data.coverImage,
bannerImage: data.bannerImage,
albums: mergedAlbums,
shows: data.shows,
bandLinks: data.bandLinks
bandLinks: data.bandLinks,
raw: data.raw
}
}

Expand Down
30 changes: 29 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,46 @@ const urlHelper = require('url')
const htmlParser = require('./htmlParser.js')
const utils = require('./utils.js')

const checkNotFound = function (html) {
return (html.includes('Sorry, that something isn’t here.') || html.includes('<meta property="og:url" content="https://bandcamp.com/">'))
}

exports.search = function (params, cb) {
const url = utils.generateSearchUrl(params)
req(url, function (error, html) {
req({ url, headers: { Cookie: 'identity' } }, function (error, html) {
if (error) {
cb(error, null)
} else {
if (checkNotFound(html)) return cb(new Error('404'), null)
const searchResults = htmlParser.parseSearchResults(html)
cb(null, searchResults)
}
})
}

exports.searchApi = function (body, cb) {
const url = 'https://bandcamp.com/api/bcsearch_public_api/1/autocomplete_elastic'
req({ url, method: 'POST', data: JSON.stringify(body), headers: { 'Content-Type': 'application/json' } }, function (error, json) {
if (error) {
cb(error, null)
} else {
try {
const searchResults = JSON.parse(json)
cb(null, searchResults)
} catch (error) {
cb(error, null)
}
}
})
}

exports.getAlbumsWithTag = function (params, cb) {
const url = utils.generateTagUrl(params)
req(url, function (error, html) {
if (error) {
cb(error, null)
} else {
if (checkNotFound(html)) return cb(new Error('404'), null)
const tagResults = htmlParser.parseTagResults(html)
cb(null, tagResults)
}
Expand All @@ -33,6 +55,7 @@ exports.getAlbumUrls = function (artistUrl, cb) {
if (error) {
cb(error, null)
} else {
if (checkNotFound(html)) return cb(new Error('404'), null)
const albumUrls = htmlParser.parseAlbumUrls(html, artistUrl)
cb(null, albumUrls)
}
Expand All @@ -44,6 +67,7 @@ exports.getAlbumInfo = function (albumUrl, cb) {
if (error) {
cb(error, null)
} else {
if (checkNotFound(html)) return cb(new Error('404'), null)
const albumInfo = htmlParser.parseAlbumInfo(html, albumUrl)
cb(null, albumInfo)
}
Expand All @@ -55,6 +79,7 @@ exports.getAlbumProducts = function (albumUrl, cb) {
if (error) {
cb(error, null)
} else {
if (checkNotFound(html)) return cb(new Error('404'), null)
const products = htmlParser.parseAlbumProducts(html, albumUrl)
cb(null, products)
}
Expand All @@ -67,6 +92,7 @@ exports.getArtistUrls = function (labelUrl, cb) {
if (error) {
cb(error, null)
} else {
if (checkNotFound(html)) return cb(new Error('404'), null)
const artistUrls = htmlParser.parseArtistUrls(html, labelUrl)
cb(null, artistUrls)
}
Expand All @@ -78,6 +104,7 @@ exports.getArtistInfo = function (artistUrl, cb) {
if (error) {
cb(error, null)
} else {
if (checkNotFound(html)) return cb(new Error('404'), null)
const artistInfo = htmlParser.parseArtistInfo(html, artistUrl)
cb(null, artistInfo)
}
Expand All @@ -89,6 +116,7 @@ exports.getTrackInfo = function (trackUrl, cb) {
if (error) {
cb(error, null)
} else {
if (checkNotFound(html)) return cb(new Error('404'), null)
const trackInfo = htmlParser.parseTrackInfo(html, trackUrl)
cb(null, trackInfo)
}
Expand Down
Loading