Add fan functions

This commit is contained in:
patrickkfkan 2022-06-23 20:09:44 +08:00
parent 8e02d3574a
commit efdecf813c
12 changed files with 1756 additions and 5 deletions

View File

@ -286,6 +286,46 @@ Fetches the list of tags matching `params.q`. Results include both partial and f
- q: the string to match - q: the string to match
- limit: the maximum number of results to return - limit: the maximum number of results to return
### `getFanInfo(username, [options])`
[**Example**](examples/getFanInfo.js) ([output](examples/getFanInfo_output.txt))
Fetches information about a fan.
- `username`
- `options` (optional)
- imageFormat
### `getFanWishlist(usernameOrContinuationToken, [options])`
[**Example**](examples/getFanWishlist.js) ([output](examples/getFanWishlist_output.txt))
Fetches the list of albums / tracks added to a fan's wishlist.
- `usernameOrContinuationToken`: if username is provided, returns the first batch of wishlist items. To obtain further items, call the function again but, instead of username, pass `continuationToken` from the result of the first call. If there are no further items available, `continuationToken` will be `null`.
- `options` (optional)
- imageFormat
### `getFanFollowingArtistsAndLabels(usernameOrContinuationToken, [options])`
[**Example**](examples/getFanFollowingArtistsAndLabels.js) ([output](examples/getFanFollowingArtistsAndLabels_output.txt))
Fetches the list of artists and labels followed by a fan.
- `usernameOrContinuationToken`: if username is provided, returns the first batch of artists and labels. To obtain further items, call the function again but, instead of username, pass `continuationToken` from the result of the first call. If there are no further items available, `continuationToken` will be `null`.
- `options` (optional)
- imageFormat
### `getFanFollowingGenres(usernameOrContinuationToken, [options])`
[**Example**](examples/getFanFollowingGenres.js) ([output](examples/getFanFollowingGenres_output.txt))
Fetches the list of genres followed by a fan. Each genre is actually a Bandcamp tag, so you can, for example, pass its `url` value to `getReleasesByTag()`.
- `usernameOrContinuationToken`: if username is provided, returns the first batch of genres. To obtain further items, call the function again but, instead of username, pass `continuationToken` from the result of the first call. If there are no further items available, `continuationToken` will be `null`.
- `options` (optional)
- imageFormat
## Rate Limiting ## Rate Limiting
The API functions can be called with rate limiting like this: The API functions can be called with rate limiting like this:

View File

@ -0,0 +1,19 @@
const bcfetch = require('../lib');
const util = require('util');
const username = 'patrickkfkan';
const options = {
imageFormat: 'bio_featured'
}
bcfetch.getFanFollowingArtistsAndLabels(username, options).then( async (results) => {
console.log(util.inspect(results, false, null, false));
if (results.continuationToken) {
console.log('Fetching more with continuation token...');
const moreResults = await bcfetch.getFanFollowingArtistsAndLabels(results.continuationToken);
console.log(util.inspect(moreResults, false, null, false));
}
});

View File

@ -0,0 +1,402 @@
{
items: [
{
name: 'M. Ward',
url: 'https://m-ward.bandcamp.com',
location: 'Portland, Oregon',
imageUrl: 'https://f4.bcbits.com/img/18177684_28.jpg'
},
{
name: 'Allison Crutchfield',
url: 'https://allisoncrutchfield.bandcamp.com',
location: 'Philadelphia, Pennsylvania',
imageUrl: 'https://f4.bcbits.com/img/8598378_28.jpg'
},
{
name: 'Coco Hames',
url: 'https://cocohames.bandcamp.com',
location: 'Memphis, Tennessee',
imageUrl: 'https://f4.bcbits.com/img/9197807_28.jpg'
},
{
name: 'Neutral Milk Hotel',
url: 'https://neutralmilkhotel.bandcamp.com',
location: '',
imageUrl: 'https://f4.bcbits.com/img/13466114_28.jpg'
},
{
name: 'Spoon',
url: 'https://spoontheband.bandcamp.com',
location: 'Austin, Texas',
imageUrl: 'https://f4.bcbits.com/img/21448647_28.jpg'
},
{
name: 'Crooked Fingers',
url: 'https://crookedfingers.bandcamp.com',
location: 'North Carolina',
imageUrl: 'https://f4.bcbits.com/img/13404323_28.jpg'
},
{
name: 'The Rock*A*Teens',
url: 'https://therockateens.bandcamp.com',
location: 'Atlanta, Georgia',
imageUrl: 'https://f4.bcbits.com/img/13223966_28.jpg'
},
{
name: 'The Essex Green',
url: 'https://theessexgreen.bandcamp.com',
location: 'Brooklyn, New York',
imageUrl: 'https://f4.bcbits.com/img/13167432_28.jpg'
},
{
name: 'She & Him',
url: 'https://sheandhim.bandcamp.com',
location: 'Los Angeles, California',
imageUrl: 'https://f4.bcbits.com/img/28704726_28.jpg'
},
{
name: 'Ought',
url: 'https://ought.bandcamp.com',
location: 'Montréal, Québec',
imageUrl: 'https://f4.bcbits.com/img/11617874_28.jpg'
},
{
name: 'Spider Bags',
url: 'https://spiderbags.bandcamp.com',
location: 'Chapel Hill, North Carolina',
imageUrl: 'https://f4.bcbits.com/img/6370483_28.jpg'
},
{
name: 'Tracyanne & Danny',
url: 'https://tracyanneanddanny.bandcamp.com',
location: 'UK',
imageUrl: 'https://f4.bcbits.com/img/12612375_28.jpg'
},
{
name: 'Fucked Up',
url: 'https://fuckedup.bandcamp.com',
location: 'Toronto, Ontario',
imageUrl: 'https://f4.bcbits.com/img/7029567_28.jpg'
},
{
name: "Swearin'",
url: 'https://swearin.bandcamp.com',
location: 'Philadelphia, Pennsylvania',
imageUrl: 'https://f4.bcbits.com/img/19671909_28.jpg'
},
{
name: 'The Spinanes',
url: 'https://thespinanes.bandcamp.com',
location: 'Portland, Oregon',
imageUrl: 'https://f4.bcbits.com/img/14533028_28.jpg'
},
{
name: 'Telekinesis',
url: 'https://telekinesis.bandcamp.com',
location: 'Seattle, Washington',
imageUrl: 'https://f4.bcbits.com/img/14904916_28.jpg'
},
{
name: 'The Broken West',
url: 'https://thebrokenwest.bandcamp.com',
location: 'Los Angeles, California',
imageUrl: 'https://f4.bcbits.com/img/16185383_28.jpg'
},
{
name: 'Titus Andronicus',
url: 'https://titusandronicus.bandcamp.com',
location: '',
imageUrl: 'https://f4.bcbits.com/img/15982887_28.jpg'
},
{
name: 'SACRED//PAWS',
url: 'https://sacredpaws.bandcamp.com',
location: 'Glasgow, UK',
imageUrl: 'https://f4.bcbits.com/img/41645_28.jpg'
},
{
name: 'Imperial Teen',
url: 'https://imperialteen.bandcamp.com',
location: 'San Francisco, California',
imageUrl: 'https://f4.bcbits.com/img/16255829_28.jpg'
},
{
name: 'Ex Hex',
url: 'https://exhexband.bandcamp.com',
location: 'Washington, D.C.',
imageUrl: 'https://f4.bcbits.com/img/15244159_28.jpg'
},
{
name: 'Apex Manor',
url: 'https://apexmanor.bandcamp.com',
location: 'Los Angeles, California',
imageUrl: 'https://f4.bcbits.com/img/15921186_28.jpg'
},
{
name: 'David Kilgour',
url: 'https://davidkilgour.bandcamp.com',
location: 'Dunedin',
imageUrl: 'https://f4.bcbits.com/img/6370477_28.jpg'
},
{
name: 'Gauche',
url: 'https://g-a-u-c-h-e.bandcamp.com',
location: 'Washington, D.C.',
imageUrl: 'https://f4.bcbits.com/img/16153963_28.jpg'
},
{
name: 'Eric Bachmann',
url: 'https://ericbachmann.bandcamp.com',
location: 'North Carolina',
imageUrl: 'https://f4.bcbits.com/img/17551127_28.jpg'
},
{
name: 'Little Scream',
url: 'https://littlescream.bandcamp.com',
location: 'Montréal, Québec',
imageUrl: 'https://f4.bcbits.com/img/5272073_28.jpg'
},
{
name: 'The Love Language',
url: 'https://thelovelanguage.bandcamp.com',
location: 'Chapel Hill, North Carolina',
imageUrl: 'https://f4.bcbits.com/img/13444279_28.jpg'
},
{
name: 'Richard Buckner',
url: 'https://richardbuckner.bandcamp.com',
location: 'New York, New York',
imageUrl: 'https://f4.bcbits.com/img/17863325_28.jpg'
},
{
name: 'Polvo',
url: 'https://polvonc.bandcamp.com',
location: 'Chapel Hill, North Carolina',
imageUrl: 'https://f4.bcbits.com/img/18801929_28.jpg'
},
{
name: 'Martin Frawley',
url: 'https://martinfrawley.bandcamp.com',
location: 'Australia',
imageUrl: 'https://f4.bcbits.com/img/18908062_28.jpg'
},
{
name: 'The Music Tapes',
url: 'https://themusictapes.bandcamp.com',
location: 'Athens, Georgia',
imageUrl: 'https://f4.bcbits.com/img/17776773_28.jpg'
},
{
name: 'Mt. Wilson Repeater',
url: 'https://mtwilsonrptr.bandcamp.com',
location: '',
imageUrl: 'https://f4.bcbits.com/img/19621062_28.jpg'
},
{
name: 'Sweet Spirit',
url: 'https://sweetspirittheband.bandcamp.com',
location: 'Austin, Texas',
imageUrl: 'https://f4.bcbits.com/img/19349627_28.jpg'
},
{
name: 'Jade Hairpins',
url: 'https://jadehairpins.bandcamp.com',
location: '',
imageUrl: 'https://f4.bcbits.com/img/18584374_28.jpg'
},
{
name: 'Archers of Loaf',
url: 'https://archersofloaf.bandcamp.com',
location: 'North Carolina',
imageUrl: 'https://f4.bcbits.com/img/5368479_28.jpg'
},
{
name: 'Mikal Cronin',
url: 'https://mikalcronin.bandcamp.com',
location: 'Los Angeles, California',
imageUrl: 'https://f4.bcbits.com/img/16983063_28.jpg'
},
{
name: 'Lou Barlow',
url: 'https://loubarlow.bandcamp.com',
location: 'Massachusetts',
imageUrl: 'https://f4.bcbits.com/img/23720984_28.jpg'
},
{
name: 'Sneaks',
url: 'https://sneaks.bandcamp.com',
location: 'Washington, D.C.',
imageUrl: 'https://f4.bcbits.com/img/19714164_28.jpg'
},
{
name: 'H.C. McEntire',
url: 'https://hcmcentire.bandcamp.com',
location: 'Durham, North Carolina',
imageUrl: 'https://f4.bcbits.com/img/20946952_28.jpg'
},
{
name: 'William Tyler',
url: 'https://williamtyler.bandcamp.com',
location: 'Los Angeles, California',
imageUrl: 'https://f4.bcbits.com/img/18844022_28.jpg'
},
{
name: 'The Clientele',
url: 'https://theclientele.bandcamp.com',
location: 'London, UK',
imageUrl: 'https://f4.bcbits.com/img/10580560_28.jpg'
},
{
name: 'Bob Mould',
url: 'https://bobmould.bandcamp.com',
location: 'San Francisco, California',
imageUrl: 'https://f4.bcbits.com/img/20299197_28.jpg'
},
{
name: 'Mike Krol',
url: 'https://mikekrol.bandcamp.com',
location: 'Los Angeles, California',
imageUrl: 'https://f4.bcbits.com/img/10450062_28.jpg'
},
{
name: 'Fruit Bats',
url: 'https://fruit-bats.bandcamp.com',
location: '',
imageUrl: 'https://f4.bcbits.com/img/23214991_28.jpg'
},
{
name: 'The Clean',
url: 'https://theclean.bandcamp.com',
location: 'New Zealand',
imageUrl: 'https://f4.bcbits.com/img/23754516_28.jpg'
}
],
total: 68,
continuationToken: { fanId: 8563805, token: '1655975469:2121405720' }
}
Fetching more with continuation token...
{
items: [
{
name: 'Will Butler',
url: 'https://willbutler.bandcamp.com',
location: 'Brooklyn, New York',
imageUrl: 'https://f4.bcbits.com/img/24918652_21.jpg'
},
{
name: 'Teenage Fanclub',
url: 'https://teenage-fanclub.bandcamp.com',
location: 'Glasgow, UK',
imageUrl: 'https://f4.bcbits.com/img/24101151_21.jpg'
},
{
name: 'Cable Ties',
url: 'https://cableties.bandcamp.com',
location: 'Melbourne, Australia',
imageUrl: 'https://f4.bcbits.com/img/8448159_21.jpg'
},
{
name: 'Reigning Sound',
url: 'https://reigningsound.bandcamp.com',
location: 'Asheville, North Carolina',
imageUrl: 'https://f4.bcbits.com/img/23915882_21.jpg'
},
{
name: 'Hiss Golden Messenger',
url: 'https://hissgoldenmessenger.bandcamp.com',
location: 'North Carolina',
imageUrl: 'https://f4.bcbits.com/img/24016536_21.jpg'
},
{
name: 'Torres',
url: 'https://torrestorrestorres.bandcamp.com',
location: 'New York, New York',
imageUrl: 'https://f4.bcbits.com/img/24864649_21.jpg'
},
{
name: 'DAWN',
url: 'https://dawnrichard.bandcamp.com',
location: 'Los Angeles, California',
imageUrl: 'https://f4.bcbits.com/img/23711418_21.jpg'
},
{
name: 'Caribou',
url: 'https://caribouband.bandcamp.com',
location: 'London, UK',
imageUrl: 'https://f4.bcbits.com/img/18041279_21.jpg'
},
{
name: 'A Giant Dog',
url: 'https://agiantdog.bandcamp.com',
location: 'Austin, Texas',
imageUrl: 'https://f4.bcbits.com/img/651146_21.jpg'
},
{
name: 'Mac McCaughan',
url: 'https://macmccaughan.bandcamp.com',
location: 'Chapel Hill, North Carolina',
imageUrl: 'https://f4.bcbits.com/img/4961611_21.jpg'
},
{
name: 'The Magnetic Fields',
url: 'https://themagneticfields.bandcamp.com',
location: 'New York, New York',
imageUrl: 'https://f4.bcbits.com/img/14275749_21.jpg'
},
{
name: 'Carson McHone',
url: 'https://carsonmchone.bandcamp.com',
location: 'Austin, Texas',
imageUrl: 'https://f4.bcbits.com/img/26448389_21.jpg'
},
{
name: 'Destroyer',
url: 'https://destroyer.bandcamp.com',
location: 'Vancouver, British Columbia',
imageUrl: 'https://f4.bcbits.com/img/27319221_21.jpg'
},
{
name: 'Ibibio Sound Machine',
url: 'https://ibibiosoundmachine.bandcamp.com',
location: 'UK',
imageUrl: 'https://f4.bcbits.com/img/27398052_21.jpg'
},
{
name: 'Superchunk',
url: 'https://superchunk.bandcamp.com',
location: 'Chapel Hill, North Carolina',
imageUrl: 'https://f4.bcbits.com/img/26971728_21.jpg'
},
{
name: 'Hollie Cook',
url: 'https://holliecook.bandcamp.com',
location: 'London, UK',
imageUrl: 'https://f4.bcbits.com/img/28056444_21.jpg'
},
{
name: 'Redd Kross',
url: 'https://reddkross.bandcamp.com',
location: 'Hawthorne, California',
imageUrl: 'https://f4.bcbits.com/img/28555577_21.jpg'
},
{
name: 'Friendship',
url: 'https://friendshipphl.bandcamp.com',
location: 'Philadelphia, Pennsylvania',
imageUrl: 'https://f4.bcbits.com/img/28727388_21.jpg'
},
{
name: 'Tall Dwarfs',
url: 'https://talldwarfs.bandcamp.com',
location: 'New Zealand',
imageUrl: 'https://f4.bcbits.com/img/28914236_21.jpg'
},
{
name: 'The Mountain Goats',
url: 'https://themountaingoats.bandcamp.com',
location: 'Durham, North Carolina',
imageUrl: 'https://f4.bcbits.com/img/28851781_21.jpg'
}
],
continuationToken: { fanId: 8563805, token: '1655975366:3856108936' }
}

View File

@ -0,0 +1,19 @@
const bcfetch = require('../lib');
const util = require('util');
const username = 'patrickkfkan';
const options = {
imageFormat: 'art_tags_large'
}
bcfetch.getFanFollowingGenres(username, options).then( async (results) => {
console.log(util.inspect(results, false, null, false));
if (results.continuationToken) {
console.log('Fetching more with continuation token...');
const moreResults = await bcfetch.getFanFollowingGenres(results.continuationToken);
console.log(util.inspect(moreResults, false, null, false));
}
});

View File

@ -0,0 +1,492 @@
{
items: [
{
type: 'tag',
name: 'alt-country',
value: 'alt-country',
url: 'http://bandcamp.com/tag/alt-country',
imageUrls: [
'https://f4.bcbits.com/img/a2812018975_9.jpg',
'https://f4.bcbits.com/img/a4021760960_9.jpg',
'https://f4.bcbits.com/img/a3180368360_9.jpg',
'https://f4.bcbits.com/img/a4249304312_9.jpg'
]
},
{
type: 'tag',
name: 'alternative',
value: 'alternative',
url: 'http://bandcamp.com/tag/alternative',
imageUrls: [
'https://f4.bcbits.com/img/a170407559_9.jpg',
'https://f4.bcbits.com/img/a3131938012_9.jpg',
'https://f4.bcbits.com/img/a249396355_9.jpg',
'https://f4.bcbits.com/img/a2449560999_9.jpg'
]
},
{
type: 'tag',
name: 'americana',
value: 'americana',
url: 'http://bandcamp.com/tag/americana',
imageUrls: [
'https://f4.bcbits.com/img/a464276499_9.jpg',
'https://f4.bcbits.com/img/a2640171700_9.jpg',
'https://f4.bcbits.com/img/a1096304773_9.jpg',
'https://f4.bcbits.com/img/a243223324_9.jpg'
]
},
{
type: 'tag',
name: 'bluegrass',
value: 'bluegrass',
url: 'http://bandcamp.com/tag/bluegrass',
imageUrls: [
'https://f4.bcbits.com/img/a1809221678_9.jpg',
'https://f4.bcbits.com/img/a1307988683_9.jpg',
'https://f4.bcbits.com/img/a3331001123_9.jpg',
'https://f4.bcbits.com/img/a2518135234_9.jpg'
]
},
{
type: 'tag',
name: 'blues',
value: 'blues',
url: 'http://bandcamp.com/tag/blues',
imageUrls: [
'https://f4.bcbits.com/img/a1569928325_9.jpg',
'https://f4.bcbits.com/img/a464276499_9.jpg',
'https://f4.bcbits.com/img/a1629143589_9.jpg',
'https://f4.bcbits.com/img/a3729345272_9.jpg'
]
},
{
type: 'tag',
name: 'blues rock',
value: 'blues-rock',
url: 'http://bandcamp.com/tag/blues-rock',
imageUrls: [
'https://f4.bcbits.com/img/a1933779616_9.jpg',
'https://f4.bcbits.com/img/a3261738963_9.jpg',
'https://f4.bcbits.com/img/a3863213642_9.jpg',
'https://f4.bcbits.com/img/a2567029617_9.jpg'
]
},
{
type: 'tag',
name: 'britpop',
value: 'britpop',
url: 'http://bandcamp.com/tag/britpop',
imageUrls: [
'https://f4.bcbits.com/img/a3480175917_9.jpg',
'https://f4.bcbits.com/img/a784126120_9.jpg',
'https://f4.bcbits.com/img/a2644607321_9.jpg',
'https://f4.bcbits.com/img/a979340940_9.jpg'
]
},
{
type: 'tag',
name: 'comedy',
value: 'comedy',
url: 'http://bandcamp.com/tag/comedy',
imageUrls: [
'https://f4.bcbits.com/img/a2417971529_9.jpg',
'https://f4.bcbits.com/img/a1433758941_9.jpg',
'https://f4.bcbits.com/img/a450963178_9.jpg',
'https://f4.bcbits.com/img/a1684468871_9.jpg'
]
},
{
type: 'tag',
name: 'country',
value: 'country',
url: 'http://bandcamp.com/tag/country',
imageUrls: [
'https://f4.bcbits.com/img/a2269776116_9.jpg',
'https://f4.bcbits.com/img/a4073383153_9.jpg',
'https://f4.bcbits.com/img/a1374205961_9.jpg',
'https://f4.bcbits.com/img/a387546155_9.jpg'
]
},
{
type: 'tag',
name: 'country blues',
value: 'country-blues',
url: 'http://bandcamp.com/tag/country-blues',
imageUrls: [
'https://f4.bcbits.com/img/a2668431628_9.jpg',
'https://f4.bcbits.com/img/a976206506_9.jpg',
'https://f4.bcbits.com/img/a1402311003_9.jpg',
'https://f4.bcbits.com/img/a1934752360_9.jpg'
]
},
{
type: 'tag',
name: 'country folk',
value: 'country-folk',
url: 'http://bandcamp.com/tag/country-folk',
imageUrls: [
'https://f4.bcbits.com/img/a2369233251_9.jpg',
'https://f4.bcbits.com/img/a3432467807_9.jpg',
'https://f4.bcbits.com/img/a633308688_9.jpg',
'https://f4.bcbits.com/img/a4161975053_9.jpg'
]
},
{
type: 'tag',
name: 'country rock',
value: 'country-rock',
url: 'http://bandcamp.com/tag/country-rock',
imageUrls: [
'https://f4.bcbits.com/img/a3432467807_9.jpg',
'https://f4.bcbits.com/img/a2621845460_9.jpg',
'https://f4.bcbits.com/img/a1404033992_9.jpg',
'https://f4.bcbits.com/img/a3388514058_9.jpg'
]
},
{
type: 'tag',
name: 'crust punk',
value: 'crust-punk',
url: 'http://bandcamp.com/tag/crust-punk',
imageUrls: [
'https://f4.bcbits.com/img/a3468490381_9.jpg',
'https://f4.bcbits.com/img/a2468512644_9.jpg',
'https://f4.bcbits.com/img/a2490597736_9.jpg',
'https://f4.bcbits.com/img/a1933880040_9.jpg'
]
},
{
type: 'tag',
name: 'dream pop',
value: 'dream-pop',
url: 'http://bandcamp.com/tag/dream-pop',
imageUrls: [
'https://f4.bcbits.com/img/a2127751780_9.jpg',
'https://f4.bcbits.com/img/a3307224930_9.jpg',
'https://f4.bcbits.com/img/a2151856429_9.jpg',
'https://f4.bcbits.com/img/a2340015657_9.jpg'
]
},
{
type: 'tag',
name: 'electric blues',
value: 'electric-blues',
url: 'http://bandcamp.com/tag/electric-blues',
imageUrls: [
'https://f4.bcbits.com/img/a2272366912_9.jpg',
'https://f4.bcbits.com/img/a3261738963_9.jpg',
'https://f4.bcbits.com/img/a3762950636_9.jpg',
'https://f4.bcbits.com/img/a557154008_9.jpg'
]
},
{
type: 'tag',
name: 'electronic',
value: 'electronic',
url: 'http://bandcamp.com/tag/electronic',
imageUrls: [
'https://f4.bcbits.com/img/a2959214773_9.jpg',
'https://f4.bcbits.com/img/a457848067_9.jpg',
'https://f4.bcbits.com/img/a693931791_9.jpg',
'https://f4.bcbits.com/img/a1806928460_9.jpg'
]
},
{
type: 'tag',
name: 'emo',
value: 'emo',
url: 'http://bandcamp.com/tag/emo',
imageUrls: [
'https://f4.bcbits.com/img/a465346081_9.jpg',
'https://f4.bcbits.com/img/a3727718257_9.jpg',
'https://f4.bcbits.com/img/a2673308805_9.jpg',
'https://f4.bcbits.com/img/a786227558_9.jpg'
]
},
{
type: 'tag',
name: 'film music',
value: 'film-music',
url: 'http://bandcamp.com/tag/film-music',
imageUrls: [
'https://f4.bcbits.com/img/a1742290515_9.jpg',
'https://f4.bcbits.com/img/a50784949_9.jpg',
'https://f4.bcbits.com/img/a1075802195_9.jpg',
'https://f4.bcbits.com/img/a244758941_9.jpg'
]
},
{
type: 'tag',
name: 'flamenco',
value: 'flamenco',
url: 'http://bandcamp.com/tag/flamenco',
imageUrls: [
'https://f4.bcbits.com/img/a885121826_9.jpg',
'https://f4.bcbits.com/img/a3664761073_9.jpg',
'https://f4.bcbits.com/img/a174589227_9.jpg',
'https://f4.bcbits.com/img/a757919155_9.jpg'
]
},
{
type: 'tag',
name: 'folk punk',
value: 'folk-punk',
url: 'http://bandcamp.com/tag/folk-punk',
imageUrls: [
'https://f4.bcbits.com/img/a1705673353_9.jpg',
'https://f4.bcbits.com/img/a1760380718_9.jpg',
'https://f4.bcbits.com/img/a3775824951_9.jpg',
'https://f4.bcbits.com/img/a18440001_9.jpg'
]
}
],
total: 45,
continuationToken: { fanId: 8563805, token: 'folk-punk' }
}
Fetching more with continuation token...
{
items: [
{
type: 'tag',
name: 'grunge',
value: 'grunge',
url: 'http://bandcamp.com/tag/grunge',
imageUrls: [
'https://f4.bcbits.com/img/a3259891097_3.jpg',
'https://f4.bcbits.com/img/a3310898310_3.jpg',
'https://f4.bcbits.com/img/a964923157_3.jpg',
'https://f4.bcbits.com/img/a951544653_3.jpg'
]
},
{
type: 'tag',
name: 'hardcore punk',
value: 'hardcore-punk',
url: 'http://bandcamp.com/tag/hardcore-punk',
imageUrls: [
'https://f4.bcbits.com/img/a360503158_3.jpg',
'https://f4.bcbits.com/img/a2239018039_3.jpg',
'https://f4.bcbits.com/img/a2901862961_3.jpg',
'https://f4.bcbits.com/img/a1281987747_3.jpg'
]
},
{
type: 'tag',
name: 'hillbilly',
value: 'hillbilly',
url: 'http://bandcamp.com/tag/hillbilly',
imageUrls: [
'https://f4.bcbits.com/img/a990859061_3.jpg',
'https://f4.bcbits.com/img/a1053103475_3.jpg',
'https://f4.bcbits.com/img/a2758289864_3.jpg',
'https://f4.bcbits.com/img/a1616427371_3.jpg'
]
},
{
type: 'tag',
name: 'hip-hop/rap',
value: 'hip-hop-rap',
url: 'http://bandcamp.com/tag/hip-hop-rap',
imageUrls: [
'https://f4.bcbits.com/img/a1431155242_3.jpg',
'https://f4.bcbits.com/img/a2461990826_3.jpg',
'https://f4.bcbits.com/img/a2738953678_3.jpg',
'https://f4.bcbits.com/img/a4279135532_3.jpg'
]
},
{
type: 'tag',
name: 'honky tonk',
value: 'honky-tonk',
url: 'http://bandcamp.com/tag/honky-tonk',
imageUrls: [
'https://f4.bcbits.com/img/a359008077_3.jpg',
'https://f4.bcbits.com/img/a1169969255_3.jpg',
'https://f4.bcbits.com/img/a1603431406_3.jpg',
'https://f4.bcbits.com/img/a3299835395_3.jpg'
]
},
{
type: 'tag',
name: 'jangle pop',
value: 'jangle-pop',
url: 'http://bandcamp.com/tag/jangle-pop',
imageUrls: [
'https://f4.bcbits.com/img/a4007205205_3.jpg',
'https://f4.bcbits.com/img/a3813877843_3.jpg',
'https://f4.bcbits.com/img/a3282444573_3.jpg',
'https://f4.bcbits.com/img/a4250417365_3.jpg'
]
},
{
type: 'tag',
name: 'jazz',
value: 'jazz',
url: 'http://bandcamp.com/tag/jazz',
imageUrls: [
'https://f4.bcbits.com/img/a3082595015_3.jpg',
'https://f4.bcbits.com/img/a3992958598_3.jpg',
'https://f4.bcbits.com/img/a3843612070_3.jpg',
'https://f4.bcbits.com/img/a1485592402_3.jpg'
]
},
{
type: 'tag',
name: 'latin',
value: 'latin',
url: 'http://bandcamp.com/tag/latin',
imageUrls: [
'https://f4.bcbits.com/img/a2558489987_3.jpg',
'https://f4.bcbits.com/img/a602153856_3.jpg',
'https://f4.bcbits.com/img/a1505469867_3.jpg',
'https://f4.bcbits.com/img/a3210602209_3.jpg'
]
},
{
type: 'tag',
name: 'math rock',
value: 'math-rock',
url: 'http://bandcamp.com/tag/math-rock',
imageUrls: [
'https://f4.bcbits.com/img/a2239335029_3.jpg',
'https://f4.bcbits.com/img/a361777070_3.jpg',
'https://f4.bcbits.com/img/a3671783114_3.jpg',
'https://f4.bcbits.com/img/a1802582472_3.jpg'
]
},
{
type: 'tag',
name: 'no wave',
value: 'no-wave',
url: 'http://bandcamp.com/tag/no-wave',
imageUrls: [
'https://f4.bcbits.com/img/a1629143589_3.jpg',
'https://f4.bcbits.com/img/a4286540031_3.jpg',
'https://f4.bcbits.com/img/a3992958598_3.jpg',
'https://f4.bcbits.com/img/a2964482710_3.jpg'
]
},
{
type: 'tag',
name: 'outlaw',
value: 'outlaw',
url: 'http://bandcamp.com/tag/outlaw',
imageUrls: [
'https://f4.bcbits.com/img/a1365344659_3.jpg',
'https://f4.bcbits.com/img/a1738994864_3.jpg',
'https://f4.bcbits.com/img/a443791610_3.jpg',
'https://f4.bcbits.com/img/a3305307372_3.jpg'
]
},
{
type: 'tag',
name: 'pop',
value: 'pop',
url: 'http://bandcamp.com/tag/pop',
imageUrls: [
'https://f4.bcbits.com/img/a2658112646_3.jpg',
'https://f4.bcbits.com/img/a2489732443_3.jpg',
'https://f4.bcbits.com/img/a3211077482_3.jpg',
'https://f4.bcbits.com/img/a461932149_3.jpg'
]
},
{
type: 'tag',
name: 'pop punk',
value: 'pop-punk',
url: 'http://bandcamp.com/tag/pop-punk',
imageUrls: [
'https://f4.bcbits.com/img/a113286790_3.jpg',
'https://f4.bcbits.com/img/a1144344500_3.jpg',
'https://f4.bcbits.com/img/a3487200283_3.jpg',
'https://f4.bcbits.com/img/a3823255125_3.jpg'
]
},
{
type: 'tag',
name: 'punk',
value: 'punk',
url: 'http://bandcamp.com/tag/punk',
imageUrls: [
'https://f4.bcbits.com/img/a1760380718_3.jpg',
'https://f4.bcbits.com/img/a2926724195_3.jpg',
'https://f4.bcbits.com/img/a895482160_3.jpg',
'https://f4.bcbits.com/img/a2402040528_3.jpg'
]
},
{
type: 'tag',
name: 'punk rock',
value: 'punk-rock',
url: 'http://bandcamp.com/tag/punk-rock',
imageUrls: [
'https://f4.bcbits.com/img/a1705673353_3.jpg',
'https://f4.bcbits.com/img/a2436204662_3.jpg',
'https://f4.bcbits.com/img/a3764892689_3.jpg',
'https://f4.bcbits.com/img/a2901862961_3.jpg'
]
},
{
type: 'tag',
name: 'reggaeton',
value: 'reggaeton',
url: 'http://bandcamp.com/tag/reggaeton',
imageUrls: [
'https://f4.bcbits.com/img/a1257468602_3.jpg',
'https://f4.bcbits.com/img/a736673855_3.jpg',
'https://f4.bcbits.com/img/a3975370626_3.jpg',
'https://f4.bcbits.com/img/a1656797036_3.jpg'
]
},
{
type: 'tag',
name: 'roots',
value: 'roots',
url: 'http://bandcamp.com/tag/roots',
imageUrls: [
'https://f4.bcbits.com/img/a580053174_3.jpg',
'https://f4.bcbits.com/img/a2384940752_3.jpg',
'https://f4.bcbits.com/img/a2576819959_3.jpg',
'https://f4.bcbits.com/img/a1998317371_3.jpg'
]
},
{
type: 'tag',
name: 'salsa',
value: 'salsa',
url: 'http://bandcamp.com/tag/salsa',
imageUrls: [
'https://f4.bcbits.com/img/a3844333998_3.jpg',
'https://f4.bcbits.com/img/a3210602209_3.jpg',
'https://f4.bcbits.com/img/a3139930816_3.jpg',
'https://f4.bcbits.com/img/a362432432_3.jpg'
]
},
{
type: 'tag',
name: 'singer-songwriter',
value: 'singer-songwriter',
url: 'http://bandcamp.com/tag/singer-songwriter',
imageUrls: [
'https://f4.bcbits.com/img/a3813877843_3.jpg',
'https://f4.bcbits.com/img/a2298793356_3.jpg',
'https://f4.bcbits.com/img/a2642176051_3.jpg',
'https://f4.bcbits.com/img/a1051407307_3.jpg'
]
},
{
type: 'tag',
name: 'soundtrack',
value: 'soundtrack',
url: 'http://bandcamp.com/tag/soundtrack',
imageUrls: [
'https://f4.bcbits.com/img/a3439861516_3.jpg',
'https://f4.bcbits.com/img/a1469772142_3.jpg',
'https://f4.bcbits.com/img/a434097210_3.jpg',
'https://f4.bcbits.com/img/a2854475053_3.jpg'
]
}
],
continuationToken: { fanId: 8563805, token: 'soundtrack' }
}

12
examples/getFanInfo.js Normal file
View File

@ -0,0 +1,12 @@
const bcfetch = require('../lib');
const util = require('util');
const username = 'patrickkfkan';
const options = {
imageFormat: 'bio_screen'
}
bcfetch.getFanInfo(username, options).then( results => {
console.log(util.inspect(results, false, null, false));
});

View File

@ -0,0 +1,13 @@
{
type: 'fan',
name: 'patrickkfkan',
username: 'patrickkfkan',
url: 'https://bandcamp.com/patrickkfkan',
description: 'Hello there!',
location: 'Hong Kong',
websiteUrl: 'http://www.google.com',
imageUrl: 'https://f4.bcbits.com/img/29024471_20.jpg',
followingGenresCount: 45,
followingArtistsAndLabelsCount: 68,
wishlistItemCount: 24
}

View File

@ -0,0 +1,19 @@
const bcfetch = require('../lib');
const util = require('util');
const username = 'patrickkfkan';
const options = {
imageFormat: 'art_app_large'
}
bcfetch.getFanWishlist(username, options).then( async (results) => {
console.log(util.inspect(results, false, null, false));
if (results.continuationToken) {
console.log('Fetching more with continuation token...');
const moreResults = await bcfetch.getFanWishlist(results.continuationToken);
console.log(util.inspect(moreResults, false, null, false));
}
});

View File

@ -0,0 +1,381 @@
{
items: [
{
type: 'album',
name: 'Silver Sash',
url: 'https://glitterhouserecords.bandcamp.com/album/silver-sash',
imageUrl: 'https://f4.bcbits.com/img/a1068361756_16.jpg',
featuredTrack: {
position: 3,
name: 'Duat Hawk',
artist: 'Wovenhand',
duration: 205.24,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=1665518602&ts=1655983089&t=57118d83b2b2dd9686c99239b1c82922e59ff80b'
},
artist: {
name: 'Wovenhand',
url: 'https://glitterhouserecords.bandcamp.com'
}
},
{
type: 'album',
name: 'Sylvie (2022)',
url: 'https://sylvie-music.bandcamp.com/album/sylvie-2022-2',
imageUrl: 'https://f4.bcbits.com/img/a2220580996_16.jpg',
featuredTrack: {
position: 1,
name: 'Falls On Me',
artist: 'Sylvie',
duration: 299.453,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=1840839102&ts=1655983089&t=8b4ca0f5fe87a9b4b4ed2bed51dd01e9c5b10486'
},
artist: { name: 'Sylvie', url: 'https://sylvie-music.bandcamp.com' }
},
{
type: 'album',
name: 'Songs From My Bucket',
url: 'https://margocilker.bandcamp.com/album/songs-from-my-bucket',
imageUrl: 'https://f4.bcbits.com/img/a3875199563_16.jpg',
featuredTrack: {
position: 3,
name: 'Skateboard Song',
artist: 'Margo Cilker',
duration: 239.799,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=2599779818&ts=1655983089&t=90eabed1822b2426cc36e5ffc91860279fa53fec'
},
artist: { name: 'Margo Cilker', url: 'https://margocilker.bandcamp.com' }
},
{
type: 'album',
name: 'Chicamacomico',
url: 'https://americanaquarium.bandcamp.com/album/chicamacomico',
imageUrl: 'https://f4.bcbits.com/img/a3942062080_16.jpg',
featuredTrack: {
position: 4,
name: 'The First Year',
artist: 'American Aquarium',
duration: 192.013,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=1867095022&ts=1655983089&t=73d76a25d7e2bafe05a33ed55838cd8fc76a791e'
},
artist: {
name: 'American Aquarium',
url: 'https://americanaquarium.bandcamp.com'
}
},
{
type: 'album',
name: 'Heavy Denim',
url: 'https://nickdittmeier.bandcamp.com/album/heavy-denim',
imageUrl: 'https://f4.bcbits.com/img/a392062975_16.jpg',
featuredTrack: {
position: 1,
name: 'I Suppose',
artist: 'Nick Dittmeier & the Sawdusters',
duration: 173.977,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=291756392&ts=1655983089&t=dac9452150ffb9bc156fe9c146c2109844ecc889'
},
artist: {
name: 'Nick Dittmeier & the Sawdusters',
url: 'https://nickdittmeier.bandcamp.com'
}
},
{
type: 'album',
name: 'Highway Sounds',
url: 'https://kassivalazza.bandcamp.com/album/highway-sounds',
imageUrl: 'https://f4.bcbits.com/img/a3803986383_16.jpg',
featuredTrack: {
position: 1,
name: 'Little Flowers',
artist: 'Kassi Valazza',
duration: 306.92,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=3662293078&ts=1655983089&t=5bf4a3c8c68149f8a86049a52d141f195b051dfc'
},
artist: {
name: 'Kassi Valazza',
url: 'https://kassivalazza.bandcamp.com'
}
},
{
type: 'album',
name: 'LIVE with LOOPER No.1',
url: 'https://markus-k.bandcamp.com/album/live-with-looper-no-1',
imageUrl: 'https://f4.bcbits.com/img/a3261738963_16.jpg',
featuredTrack: {
position: 1,
name: 'We Merge',
artist: 'Markus K',
duration: 228.87,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=3271952930&ts=1655983089&t=d04ddb62fd86b5e2a6884ccb39107f4effd0e5f6'
},
artist: { name: 'Markus K', url: 'https://markus-k.bandcamp.com' }
},
{
type: 'album',
name: 'Visions of the Country',
url: 'https://gnomelife.bandcamp.com/album/visions-of-the-country',
imageUrl: 'https://f4.bcbits.com/img/a1359892761_16.jpg',
featuredTrack: {
position: 5,
name: 'Blue Crystal Fire',
artist: 'Robbie Basho',
duration: 287.546,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=2254598059&ts=1655983089&t=f94b64f12878f766d9a14e8a964002a43b46a123'
},
artist: { name: 'Robbie Basho', url: 'https://gnomelife.bandcamp.com' }
},
{
type: 'album',
name: 'Pohorylle',
url: 'https://margocilker.bandcamp.com/album/pohorylle',
imageUrl: 'https://f4.bcbits.com/img/a880076195_16.jpg',
featuredTrack: {
position: 1,
name: 'That River',
artist: 'Margo Cilker',
duration: 189.187,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=895429532&ts=1655983089&t=951036b766857e03317d8e720c81df576b79d27a'
},
artist: { name: 'Margo Cilker', url: 'https://margocilker.bandcamp.com' }
},
{
type: 'album',
name: 'Cruel Country',
url: 'https://wilcohq.bandcamp.com/album/cruel-country',
imageUrl: 'https://f4.bcbits.com/img/a452127673_16.jpg',
featuredTrack: {
position: 14,
name: 'Falling Apart (Right Now)',
artist: 'Wilco',
duration: 198.52,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=3385090483&ts=1655983089&t=cbd6fbd2900a87a85c73d7d9f316d7826711f917'
},
artist: { name: 'Wilco', url: 'https://wilcohq.bandcamp.com' }
},
{
type: 'album',
name: 'Live at Red Rocks - Morrison, CO - 8/1/2021',
url: 'https://jasonisbell.bandcamp.com/album/live-at-red-rocks-morrison-co-8-1-2021',
imageUrl: 'https://f4.bcbits.com/img/a863538884_16.jpg',
featuredTrack: {
position: 21,
name: 'Tour Of Duty',
artist: 'Jason Isbell and the 400 Unit',
duration: 228.867,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=2971595025&ts=1655983089&t=59596727b495c213825254c1437ea123892dc09f'
},
artist: {
name: 'Jason Isbell and the 400 Unit',
url: 'https://jasonisbell.bandcamp.com'
}
},
{
type: 'album',
name: 'Wild Creatures',
url: 'https://nekocaseofficial.bandcamp.com/album/wild-creatures',
imageUrl: 'https://f4.bcbits.com/img/a3745965981_16.jpg',
featuredTrack: {
position: 1,
name: "I'm An Animal",
artist: 'Neko Case',
duration: 136.987,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=535802350&ts=1655983089&t=b52861815f82e98e6674696b6d0d4575b728f44c'
},
artist: {
name: 'Neko Case',
url: 'https://nekocaseofficial.bandcamp.com'
}
},
{
type: 'album',
name: "Cover Charge: NC Artists Go Under Cover to Benefit Cat's Cradle",
url: 'https://covercharge.bandcamp.com/album/cover-charge-nc-artists-go-under-cover-to-benefit-cats-cradle',
imageUrl: 'https://f4.bcbits.com/img/a2768267036_16.jpg',
featuredTrack: {
position: 1,
name: "Can't Stop the World",
artist: 'Cover Charge',
duration: 205.213,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=206849315&ts=1655983089&t=0628dd04ff2f75ced8233be6ad48571225c915e3'
},
artist: { name: 'Cover Charge', url: 'https://covercharge.bandcamp.com' }
},
{
type: 'album',
name: 'Anything But Country',
url: 'https://legendsofcountry.bandcamp.com/album/anything-but-country',
imageUrl: 'https://f4.bcbits.com/img/a1262555298_16.jpg',
featuredTrack: {
position: 4,
name: "Everything's Going South",
artist: 'Legends Of Country',
duration: 180.156,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=2932389502&ts=1655983089&t=cbb49d079d9202ff991fc30e1785377e22109a94'
},
artist: {
name: 'Legends Of Country',
url: 'https://legendsofcountry.bandcamp.com'
}
},
{
type: 'album',
name: 'Outsiders',
url: 'https://annativel.bandcamp.com/album/outsiders',
imageUrl: 'https://f4.bcbits.com/img/a420888783_16.jpg',
featuredTrack: {
position: 1,
name: 'Outsiders',
artist: 'Anna Tivel',
duration: 234.747,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=157662870&ts=1655983089&t=a2b53536e3f8c926f5228319fa9ff66b83cffea0'
},
artist: { name: 'Anna Tivel', url: 'https://annativel.bandcamp.com' }
},
{
type: 'album',
name: 'Conversations with My Other Voice',
url: 'https://buickaudra.bandcamp.com/album/conversations-with-my-other-voice',
imageUrl: 'https://f4.bcbits.com/img/a4196155980_16.jpg',
featuredTrack: {
position: 3,
name: 'Afraid of Flying',
artist: 'Buick Audra',
duration: 216.757,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=425192694&ts=1655983089&t=f60ec11c0658b91e46b866872a4efe2b04fbd0bb'
},
artist: { name: 'Buick Audra', url: 'https://buickaudra.bandcamp.com' }
},
{
type: 'album',
name: 'The New Faith',
url: 'https://jakeblountmusic.bandcamp.com/album/the-new-faith',
imageUrl: 'https://f4.bcbits.com/img/a1096304773_16.jpg',
featuredTrack: {
position: 3,
name: 'Didnt It Rain',
artist: 'Jake Blount',
duration: 185.987,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=4237361807&ts=1655983089&t=cdaf63e67d215ccbe8558c267a2fa05f7c564522'
},
artist: {
name: 'Jake Blount',
url: 'https://jakeblountmusic.bandcamp.com'
}
},
{
type: 'album',
name: "Crow's Pine",
url: 'https://lobbyartrecs.bandcamp.com/album/crows-pine-2',
imageUrl: 'https://f4.bcbits.com/img/a2270982070_16.jpg',
featuredTrack: {
position: 5,
name: 'Ivory Tower',
artist: 'Bob Driftwood',
duration: 322.479,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=4191030128&ts=1655983089&t=ba54bc1473e2631c332b031bd44671d4d52dc08f'
},
artist: {
name: 'Bob Driftwood',
url: 'https://lobbyartrecs.bandcamp.com'
}
},
{
type: 'album',
name: 'Family',
url: 'https://thesilosofficial.bandcamp.com/album/family',
imageUrl: 'https://f4.bcbits.com/img/a877614212_16.jpg',
featuredTrack: {
position: 1,
name: 'My Favorite Animal',
artist: 'The Silos',
duration: 300.595,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=918323024&ts=1655983089&t=69296988b86c76ced9a3fe8dc3b35f7e386f90d1'
},
artist: {
name: 'The Silos',
url: 'https://thesilosofficial.bandcamp.com'
}
},
{
type: 'album',
name: 'Raging in the Dark',
url: 'https://jrcarroll.bandcamp.com/album/raging-in-the-dark',
imageUrl: 'https://f4.bcbits.com/img/a1293600_16.jpg',
featuredTrack: {
position: 4,
name: 'Red Fern',
artist: 'J.R. Carroll',
duration: 225.533,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=85757439&ts=1655983089&t=63cd45959e796be77027a6998e3d8e2754f09b20'
},
artist: { name: 'J.R. Carroll', url: 'https://jrcarroll.bandcamp.com' }
}
],
total: 24,
continuationToken: { fanId: 8563805, token: '1655929842:735158920:a::' }
}
Fetching more with continuation token...
{
items: [
{
type: 'album',
name: 'Live from Boston',
url: 'https://davehause.bandcamp.com/album/live-from-boston',
imageUrl: 'https://f4.bcbits.com/img/a2436594456_9.jpg',
featuredTrack: {
position: 4,
name: 'Saboteurs (Live from Boston 4.08.2022)',
artist: 'Dave Hause',
duration: 294.458,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=3843751680&ts=1655983090&t=68a6dfeb68dc6aa77968464352cecf6c755aaa81'
},
artist: { name: 'Dave Hause', url: 'https://davehause.bandcamp.com' }
},
{
type: 'track',
name: "T'es belle",
url: 'https://musique.coeurdepirate.com/track/tes-belle',
imageUrl: 'https://f4.bcbits.com/img/a774650359_9.jpg',
featuredTrack: {
position: null,
name: "T'es belle",
artist: 'Cœur de pirate',
duration: 176.373,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=3387079907&ts=1655983090&t=2102a4d867d367db18b79f1b24b30abcc0ab4074'
},
artist: {
name: 'Cœur de pirate',
url: 'https://coeurdepirate.bandcamp.com'
}
},
{
type: 'album',
name: '痛みの永遠',
url: 'https://macroblank.bandcamp.com/album/--21',
imageUrl: 'https://f4.bcbits.com/img/a1957926096_9.jpg',
featuredTrack: {
position: 1,
name: 'あなたを許すのは難しい',
artist: 'Macroblank',
duration: 358.142,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=4273244916&ts=1655983090&t=fd50e91ebbd038b88e7adc98bab963470f95c859'
},
artist: { name: 'Macroblank', url: 'https://macroblank.bandcamp.com' }
},
{
type: 'album',
name: 'False Light',
url: 'https://whiteward.bandcamp.com/album/false-light',
imageUrl: 'https://f4.bcbits.com/img/a2447867317_9.jpg',
featuredTrack: {
position: 1,
name: 'Leviathan',
artist: 'White Ward',
duration: 797.115,
streamUrl: 'https://bandcamp.com/stream_redirect?enc=mp3-128&track_id=2599650567&ts=1655983090&t=90ee7e742cb369de99d948af4594ac0585a010e7'
},
artist: { name: 'White Ward', url: 'https://whiteward.bandcamp.com' }
}
],
continuationToken: null
}

View File

@ -432,6 +432,85 @@ async function searchLocation(params) {
.then( json => parser.parseSearchLocationResults(json)); .then( json => parser.parseSearchLocationResults(json));
} }
async function getFanInfo(username, options = {}) {
const imageConstants = await _getImageConstants();
const fanPageUrl = utils.getFanPageUrl(username);
const opts = {
imageBaseUrl: imageConstants.baseUrl,
imageFormat: await _parseImageFormatArg(options.imageFormat, 20),
};
return _fetchPage(fanPageUrl)
.then( html => parser.parseFanInfo(html, opts) );
}
async function _commonGetFanItems(usernameOrContinuationToken, options, getOpts) {
const {defaultImageFormat, continuationUrl, parsePageFn, parseContinuationFn} = getOpts;
const imageConstants = await _getImageConstants();
const opts = {
imageBaseUrl: imageConstants.baseUrl,
imageFormat: await _parseImageFormatArg(options.imageFormat, defaultImageFormat),
};
if (typeof usernameOrContinuationToken === 'string') {
const fanPageUrl = utils.getFanPageUrl(usernameOrContinuationToken);
return _fetchPage(fanPageUrl)
.then( html => parsePageFn(html, opts) );
}
else if (typeof usernameOrContinuationToken === 'object' && usernameOrContinuationToken.fanId && usernameOrContinuationToken.token) {
const postData = {
fan_id: usernameOrContinuationToken.fanId,
older_than_token: usernameOrContinuationToken.token,
count: 20
};
return _fetchPage(continuationUrl, true, _getPostFetchOptions(postData))
.then( json => parseContinuationFn(json, usernameOrContinuationToken, opts));
}
else {
throw new Error('Invalid argument');
}
}
async function getFanWishlist(usernameOrContinuationToken, options = {}) {
try {
return await _commonGetFanItems(usernameOrContinuationToken, options, {
defaultImageFormat: 9,
continuationUrl: utils.getFanWishlistContinuationUrl(),
parsePageFn: parser.parseFanWishlistFromPage,
parseContinuationFn: parser.parseFanWishlistFromContinuation
});
} catch (error) {
throw new Error('getFanWishlist(): ' + error.message);
}
}
async function getFanFollowingArtistsAndLabels(usernameOrContinuationToken, options = {}) {
try {
return await _commonGetFanItems(usernameOrContinuationToken, options, {
defaultImageFormat: 21,
continuationUrl: utils.getFanFollowingBandsContinuationUrl(),
parsePageFn: parser.parseFanFollowingBandsFromPage,
parseContinuationFn: parser.parseFanFollowingBandsFromContinuation
});
} catch (error) {
throw new Error('getFanFollowingArtistsAndLabels(): ' + error.message);
}
}
async function getFanFollowingGenres(usernameOrContinuationToken, options = {}) {
try {
return await _commonGetFanItems(usernameOrContinuationToken, options, {
defaultImageFormat: 3,
continuationUrl: utils.getFanFollowingGenresContinuationUrl(),
parsePageFn: parser.parseFanFollowingGenresFromPage,
parseContinuationFn: parser.parseFanFollowingGenresFromContinuation
});
} catch (error) {
throw new Error('getFanFollowingGenres(): ' + error.message);
}
}
async function _fetchPage(url, json = false, fetchOptions = null) { async function _fetchPage(url, json = false, fetchOptions = null) {
return _cache.getOrSet('page', url + (json ? ':json' : ':html') + (fetchOptions ? ':' + JSON.stringify(fetchOptions) : ''), () => { return _cache.getOrSet('page', url + (json ? ':json' : ':html') + (fetchOptions ? ':' + JSON.stringify(fetchOptions) : ''), () => {
const doFetch = fetchOptions ? fetch(url, fetchOptions) : fetch(url); const doFetch = fetchOptions ? fetch(url, fetchOptions) : fetch(url);
@ -489,7 +568,11 @@ const _exportFn = {
getReleasesByTagFilterOptions, getReleasesByTagFilterOptions,
getReleasesByTag, getReleasesByTag,
searchTag, searchTag,
searchLocation searchLocation,
getFanInfo,
getFanWishlist,
getFanFollowingArtistsAndLabels,
getFanFollowingGenres
}; };
// Bottleneck limiter // Bottleneck limiter

View File

@ -1254,6 +1254,250 @@ function parseSearchLocationResults(json) {
} }
} }
function parseFanInfo(html, opts) {
const $ = cheerio.load(html);
const blob = decode($('#pagedata[data-blob]').attr('data-blob'));
const parsed = JSON.parse(blob);
const fanData = parsed.fan_data || {};
const fanId = fanData.fan_id;
if (!fanId) {
return null;
}
const result = {
type: 'fan',
name: fanData.name || null,
username: fanData.username || null,
url: fanData.trackpipe_url,
description: fanData.bio || null,
location: fanData.location || null,
websiteUrl: fanData.website_url || null,
imageUrl: '',
followingGenresCount: fanData.following_genres_count || 0,
followingArtistsAndLabelsCount: fanData.following_bands_count || 0,
wishlistItemCount: 0
};
if (parsed.wishlist_data) {
result.wishlistItemCount = parsed.wishlist_data.item_count || 0;
}
if (fanData.photo && fanData.photo.image_id) {
result.imageUrl = opts.imageBaseUrl + '/img/' + fanData.photo.image_id + '_' + opts.imageFormat.id + '.jpg';
}
return result;
}
function _commonParseFanPageItems(html, opts, parseOpts) {
/**
* parseOpts: {
* itemType: 'wishlist' / 'following_genres' / 'following_bands'
* parseFn: <function>
* }
*/
const _getSequenceOrPending = (o) => {
return Array.isArray(o.sequence) && o.sequence.length > 0 ? o.sequence :
Array.isArray(o.pending_sequence) && o.pending_sequence.length > 0 ? o.pending_sequence : [];
};
const $ = cheerio.load(html);
const blob = decode($('#pagedata[data-blob]').attr('data-blob'));
const parsed = JSON.parse(blob);
const result = {
items: [],
total: 0,
continuationToken: null
};
const itemListData = parsed[`${parseOpts.itemType}_data`];
const itemCache = parsed.item_cache ? parsed.item_cache[parseOpts.itemType] : null;
if (itemListData && itemCache) {
const tracklists = parsed.tracklists ? parsed.tracklists[parseOpts.itemType] : null;
const sequence = _getSequenceOrPending(itemListData);
const parseFn = parseOpts.parseFn;
sequence.forEach(itemKey => {
const parsedItem = parseFn(itemCache[itemKey], opts, tracklists);
if (parsedItem) {
result.items.push(parsedItem);
}
});
result.total = itemListData.item_count;
const fanId = parsed.fan_data && parsed.fan_data.fan_id ? parsed.fan_data.fan_id : null;
if (itemListData.item_count > sequence.length && itemListData.last_token && fanId) {
result.continuationToken = {
fanId,
token: itemListData.last_token
};
}
}
return result;
}
function _commonParseFanContinuationItems(json, continuationToken, opts, parseOpts) {
/**
* parseOpts: {
* listKey: 'items' / 'followeers'
* parseFn: <function>
* }
*/
const items = json[parseOpts.listKey] || [];
const tracklists = json.tracklists || null;
const parseFn = parseOpts.parseFn;
const result = {
items: [],
continuationToken: null
};
items.forEach( data => {
const parsedItem = parseFn(data, opts, tracklists);
if (parsedItem) {
result.items.push(parsedItem);
}
});
if (json.more_available && json.last_token) {
result.continuationToken = {
fanId: continuationToken.fanId,
token: json.last_token
};
}
return result;
}
function parseFanWishlistFromPage(html, opts) {
return _commonParseFanPageItems(html, opts, {
itemType: 'wishlist',
parseFn: _parseFanWishlistItem
});
}
function parseFanWishlistFromContinuation(json, continuationToken, opts) {
return _commonParseFanContinuationItems(json, continuationToken, opts, {
listKey: 'items',
parseFn: _parseFanWishlistItem
});
}
function _parseFanWishlistItem(data, opts, tracklists) {
if (!data) {
return null;
}
const mediaItem = {
type: 'unknown',
name: data.item_title,
url: data.item_url,
imageUrl: '',
featuredTrack: null,
artist: {
name: data.band_name
}
};
if (data.tralbum_type === 'a') {
mediaItem.type = 'album';
}
else if (data.tralbum_type === 't') {
mediaItem.type = 'track';
}
if (data.item_art_id) {
mediaItem.imageUrl = opts.imageBaseUrl + '/img/a' + data.item_art_id + '_' + opts.imageFormat.id + '.jpg';
}
if (data.url_hints && data.url_hints.subdomain) {
mediaItem.artist.url = 'https://' + data.url_hints.subdomain + '.bandcamp.com';
}
const itemKey = (data.tralbum_type && data.item_id) ? `${data.tralbum_type}${data.item_id}` : null;
if (itemKey && tracklists && Array.isArray(tracklists[itemKey]) && tracklists[itemKey].length > 0) {
const featuredTrackData = tracklists[itemKey][0];
mediaItem.featuredTrack = {
position: featuredTrackData.track_number,
name: featuredTrackData.title,
artist: featuredTrackData.artist,
duration: featuredTrackData.duration,
streamUrl: featuredTrackData.file ? featuredTrackData.file['mp3-128'] : null
};
}
return mediaItem;
}
function parseFanFollowingBandsFromPage(html, opts) {
return _commonParseFanPageItems(html, opts, {
itemType: 'following_bands',
parseFn: _parseFanFollowingBand
});
}
function parseFanFollowingBandsFromContinuation(json, continuationToken, opts) {
return _commonParseFanContinuationItems(json, continuationToken, opts, {
listKey: 'followeers',
parseFn: _parseFanFollowingBand
});
}
function _parseFanFollowingBand(data, opts) {
if (!data) {
return null;
}
const band = {
name: data.name || null,
url: null,
location: data.location || '',
imageUrl: ''
}
if (data.url_hints && data.url_hints.subdomain) {
band.url = 'https://' + data.url_hints.subdomain + '.bandcamp.com';
}
if (data.image_id) {
band.imageUrl = opts.imageBaseUrl + '/img/' + data.image_id + '_' + opts.imageFormat.id + '.jpg';
}
return band;
}
function parseFanFollowingGenresFromPage(html, opts) {
return _commonParseFanPageItems(html, opts, {
itemType: 'following_genres',
parseFn: _parseFanFollowingGenre
});
}
function parseFanFollowingGenresFromContinuation(json, continuationToken, opts) {
return _commonParseFanContinuationItems(json, continuationToken, opts, {
listKey: 'followeers',
parseFn: _parseFanFollowingGenre
});
}
function _parseFanFollowingGenre(data, opts) {
if (!data) {
return null;
}
const genre = {
type: 'tag',
name: data.display_name,
value: data.token,
url: data.tag_page_url,
imageUrls: []
};
if (Array.isArray(data.art_ids)) {
data.art_ids.forEach(artId => {
genre.imageUrls.push(opts.imageBaseUrl + '/img/a' + artId + '_' + opts.imageFormat.id + '.jpg')
})
}
return genre;
}
function _parseBackToLabelLink($) { function _parseBackToLabelLink($) {
let labelLink = $('.back-to-label-link'); let labelLink = $('.back-to-label-link');
if (labelLink.length) { if (labelLink.length) {
@ -1318,5 +1562,12 @@ module.exports = {
parseReleasesByTagFilterOptions, parseReleasesByTagFilterOptions,
parseReleasesByTag, parseReleasesByTag,
parseSearchTagResults, parseSearchTagResults,
parseSearchLocationResults parseSearchLocationResults,
parseFanInfo,
parseFanWishlistFromPage,
parseFanWishlistFromContinuation,
parseFanFollowingBandsFromPage,
parseFanFollowingBandsFromContinuation,
parseFanFollowingGenresFromPage,
parseFanFollowingGenresFromContinuation
}; };

View File

@ -168,6 +168,22 @@ function getSearchLocationUrl() {
return 'https://bandcamp.com/api/location/1/geoname_search'; return 'https://bandcamp.com/api/location/1/geoname_search';
} }
function getFanPageUrl(username) {
return getSiteUrl() + '/' + username;
}
function getFanWishlistContinuationUrl() {
return 'https://bandcamp.com/api/fancollection/1/wishlist_items';
}
function getFanFollowingBandsContinuationUrl() {
return 'https://bandcamp.com/api/fancollection/1/following_bands';
}
function getFanFollowingGenresContinuationUrl() {
return 'https://bandcamp.com/api/fancollection/1/following_genres';
}
module.exports = { module.exports = {
getUrl, getUrl,
getSiteUrl, getSiteUrl,
@ -189,5 +205,9 @@ module.exports = {
getReleasesByTagUrl, getReleasesByTagUrl,
getDigDeeperUrl, getDigDeeperUrl,
getSearchTagUrl, getSearchTagUrl,
getSearchLocationUrl getSearchLocationUrl,
getFanPageUrl,
getFanWishlistContinuationUrl,
getFanFollowingBandsContinuationUrl,
getFanFollowingGenresContinuationUrl
}; };