bandcamp-fetch/README.md
patrickkfkan e6a01cbe85 v1.1.1
2023-10-29 17:37:31 +08:00

997 lines
30 KiB
Markdown

# bandcamp-fetch
Library for scraping Bandcamp content.
Coverage:
- Bandcamp Discover
- Album and track info
- Artists, labels, label artists, discography
- Articles (aka. Bandcamp Daily)
- Shows
- Tags, including releases and highlights by tag
- Search
- Fan collections, wishlists and following artists / genres
Packaged as ESM + CJS hybrid module with typings.
# Installation
```
npm i bandcamp-fetch --save
```
# Usage
```
import bcfetch from 'bandcamp-fetch';
const results = await bcfetch.discovery.discover(...);
```
### User Sessions
When you sign into Bandcamp, a "Cookie" is created to identify the user session. You can pass the value of this cookie to the library and gain access to your private collection as well as high-quality MP3 streams of purchased media:
```
bcfetch.setCookie('xxxx');
const album = await bcfetch.album.getInfo({
albumUrl: '...' // URL of purchased album
});
// Normal quality stream
const streamUrl = album.tracks[0].streamUrl;
// High quality stream - only available when `cookie` is set
const streamUrlHQ = album.tracks[0].streamUrlHQ;
```
Guide: [How to obtain Cookie](https://github.com/patrickkfkan/bandcamp-fetch/wiki/How-to-obtain-Cookie)
### `BandcampFetch`
The library exports a default [BandcampFetch](./docs/api/classes/BandcampFetch.md) instance mainly for backward compatibility with previous versions:
```
// Imports the default `BandcampFetch` instance
import bcfetch from 'bandcamp-fetch';
```
You can also create separate instances. This is useful when you want to support multiple user sessions:
```
import { BandcampFetch } from 'bandcamp-fetch';
const bcfetch1 = new BandcampFetch({
cookie: 'xxxx' // Cookie for user session 1
});
const bcfetch2 = new BandcampFetch();
bcfetch2.setCookie('yyyy'); // Cookie for user sesion 2
```
###
# API
## Discovery API
To access the Discovery API:
```
import bcfetch from 'bandcamp-fetch';
const discovery = bcfetch.discovery;
const options = await discovery.getAvailableOptions();
const results = await discovery.discover(...);
```
**Methods:**
<details>
<summary><code>discover([params])</code></summary>
<br />
[**Example**](examples/discovery/discover.ts) ([output](examples/discovery/discover_output.txt))
<p>Fetches albums through Bandcamp Discover.</p>
**Params**
- `params`: ([DiscoverParams](docs/api/interfaces/DiscoverParams.md)) (*optional* and *all properties optional*)
- `genre`: (string)
- `subgenre`: (string) only valid when `genre` is set to something other than 'all'.
- `location`: (string)
- `sortBy`: (string)
- `artistRecommendationType`: (string) only valid when `sortBy` is 'rec' (artist recommended).
- `format`: (string)
- `time`: (number)
- `page`: (number)
- `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md))
- `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md))
To see what values can be set in `params`, call `getAvailableOptions()`.
**Returns**
Promise resolving to [DiscoverResult](docs/api/interfaces/DiscoverResult.md).
---
</details>
<details>
<summary><code>getAvailableOptions()</code></summary>
<br />
[**Example**](examples/discovery/getAvailableOptions.ts) ([output](examples/discovery/getAvailableOptions_output.txt))
<p>Fetches Bandcamp Discover options that can be used to configure <code>params</code> for passing into <code>discover()</code>.</p>
**Returns**
Promise resolving to [DiscoverOptions](docs/api/interfaces/DiscoverOptions.md).
---
</details>
<details>
<summary><code>sanitizeDiscoverParams([params])</code></summary>
<br />
[**Example**](examples/discovery/sanitizeDiscoverParams.ts) ([output](examples/discovery/sanitizeDiscoverParams_output.txt))
<p>Sanitizes <code>params</code> by setting default values for omitted properties and removing irrelevant or inapplicable ones.</p>
<p>
Note that you don't have to call this method on params passed into <code>discover()</code> as they will be sanitized automatically.
</p>
**Params**
- `params`: ([DiscoverParams](docs/api/interfaces/DiscoverParams.md)) (*optional*) the discover params to sanitize.
**Returns**
Promise resolving to sanitized [DiscoverParams](docs/api/interfaces/DiscoverParams.md).
---
</details>
## Image API
To access the Image API:
```
import bcfetch, { ImageFormatFilter } from 'bandcamp-fetch';
const image = bcfetch.image;
const formats = await image.getFormats(ImageFormatFilter.Album);
```
**Methods:**
<details>
<summary><code>getFormats([filter])</code></summary>
<br />
[**Example**](examples/image/getFormats.ts) ([output](examples/image/getFormats_output.txt))
<p>Fetches the list of image formats used in Bandcamp.</p>
**Params**
- `filter`: ([ImageFormatFilter](docs/api/enums/ImageFormatFilter.md)) (*optional*) if specified, narrows down the result to include only formats applicable to the specified value.
**Returns**
Promise resolving to Array<[ImageFormat](docs/api/interfaces/ImageFormat.md)>.
---
</details>
<details>
<summary><code>getImageFormat(target, [fallbackId])</code></summary>
<br />
<p>Fetches the image format that matches <code>target</code>. If none is found, the result will be <code>null</code>.</p>
**Params**
- `target`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md))
- If target is string or number, the method finds the image format with matching name or Id (as appropriate).
- If target satisfies the [ImageFormat](docs/api/interfaces/ImageFormat.md) interface constraint, then it is returned as is.
- `fallbackId`: (number) (*optional*) if no match is found for `target`, try to obtain format with Id matching `fallbackId`.
**Returns**
Promise resolving to matching [ImageFormat](docs/api/interfaces/ImageFormat.md), or `null` if none matches `target` nor `fallbackId` (if specified).
---
</details>
## Band API
A band can be an artist or label. To access the Band API:
```
import bcfetch from 'bandcamp-fetch';
const band = bcfetch.band;
const info = await band.getInfo(...);
```
**Methods:**
<details>
<summary><code>getInfo(params)</code></summary>
<br />
[**Example**](examples/band/getInfo.ts) ([output](examples/band/getInfo_output.txt))
<p>Fetches information about an artist or label.</p>
**Params**
- `params`: ([BandAPIGetInfoParams](docs/api/interfaces/BandAPIGetInfoParams.md))
- `bandUrl`: (string)
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
- `labelId`: (number) (*optional*)
The method tries to assemble the most complete set of data by scraping the following pages (returning immediately at any point the data becomes complete):
1. The page referred to by `bandUrl`
2. The 'music' page of the artist or label (`bandUrl/music`)
3. The first album or track in the artist's or label's discography
Sometimes, label information is missing for artists even when they do belong to a label. If you know the `labelId` of the label that the artist belongs to, you can specify it in `params`. This will ensure that `label` will not be `null` in the artist info. If you pass a label URL to this function, you can find the `labelId` in the result.
**Returns**
Promise resolving to [Artist](docs/api/interfaces/Artist.md) or [Label](docs/api/interfaces/Label.md).
---
</details>
<details>
<summary><code>getLabelArtists(params)</code></summary>
<br />
[**Example**](examples/band/getLabelArtists.ts) ([output](examples/band/getLabelArtists_output.txt))
<p>Fetches the list of artists belonging to a label.</p>
**Params**
- `params`: ([BandAPIGetLabelArtistsParams](docs/api/interfaces/BandAPIGetLabelArtistsParams.md))
- `labelUrl`: (string)
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
**Returns**
Promise resolving to Array<[LabelArtist](docs/api/README.md#labelartist)>.
---
</details>
<details>
<summary><code>getDiscography(params)</code></summary>
<br />
[**Example**](examples/band/getDiscography.ts) ([output](examples/band/getDiscography_output.txt))
<p>Fetches the list of albums and standalone tracks belonging to an artist or label.</p>
**Params**
- `params`: ([BandAPIGetDiscographyParams](docs/api/interfaces/BandAPIGetDiscographyParams.md))
- `bandUrl`: (string)
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
**Returns**
Promise resolving to Array<[Album](docs/api/interfaces/Album.md) | [Track](docs/api/interfaces/Track.md)>.
---
</details>
## Album API
To access the Album API:
```
import bcfetch from 'bandcamp-fetch';
const album = bcfetch.album;
const info = await album.getInfo(...);
```
**Methods:**
<details>
<summary><code>getInfo(params)</code></summary>
<br />
[**Example**](examples/album/getInfo.ts) ([output](examples/album/getInfo_output.txt))
<p>Fetches info about an album.</p>
**Params**
- `params`: ([AlbumAPIGetInfoParams](docs/api/interfaces/AlbumAPIGetInfoParams.md))
- `albumUrl`: (string)
- `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
- `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
- `includeRawData`: (boolean) (*optional)
**Returns**
Promise resolving to [Album](docs/api/interfaces/Album.md).
> If artist URL is not found in the scraped data, then `artist.url` will be set to the same value as `publisher.url`
---
</details>
## Track API
To access the Track API:
```
import bcfetch from 'bandcamp-fetch';
const track = bcfetch.track;
const info = await track.getInfo(...);
```
**Methods:**
<details>
<summary><code>getInfo(params)</code></summary>
<br />
[**Example**](examples/track/getInfo.ts) ([output](examples/track/getInfo_output.txt))
<p>Fetches info about a track.</p>
**Params**
- `params`: ([TrackAPIGetInfoParams](docs/api/interfaces/Tra))
- `trackUrl`: (string)
- `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
- `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
- `includeRawData`: (boolean) (*optional)
**Returns**
Promise resolving to [Track](docs/api/interfaces/Track.md).
> If artist URL is not found in the scraped data, then `artist.url` will be set to the same value as `publisher.url`
---
</details>
## Tag API
To access the Tag API:
```
import bcfetch from 'bandcamp-fetch';
const tag = bcfetch.tag;
const info = await tag.getInfo(...);
const highlights = await tag.getAlbumHighlights(...);
```
**Methods:**
<details>
<summary><code>getInfo(tagUrl)</code></summary>
<br />
[**Example**](examples/tag/getInfo.ts) ([output](examples/tag/getInfo_output.txt))
<p>Fetches info about a tag.</p>
**Params**
- `tagUrl`: (string)
**Returns**
Promise resolving to [Tag](docs/api/interfaces/Tag.md).
---
</details>
<details>
<summary><code>list()</code></summary>
<br />
[**Example**](examples/tag/list.ts) ([output](examples/tag/list_output.txt))
<p>Fetches the full list of tags.</p>
**Returns**
Promise resolving to [TagList](docs/api/interfaces/TagList.md), which groups results into `tags`(for non-location tags) and `locations` (for location tags).
---
</details>
<details>
<summary><code>getAlbumHighlights(params)</code></summary>
<br />
[**Example**](examples/tag/getAlbumHighlights.ts) ([output](examples/tag/getAlbumHighlights_output.txt))
<p>Fetches album highlights for the tag referred to by <code>params.tagUrl</code>.</p>
Albums are placed in groups. Each group corresponds to a highlight category such as 'new and notable' and 'all-time best selling'.
**Params**
- `params`: ([TagAPIGetAlbumHighlightsParams](docs/api/interfaces/TagAPIGetAlbumHighlightsParams.md))
- `tagUrl`: (string)
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
**Returns**
Promise resolving to Array<[AlbumHighlightsByTag](docs/api/interfaces/AlbumHighlightsByTag.md)>.
---
</details>
<details>
<summary><code>getReleases(params)</code></summary>
<br />
[**Example**](examples/tag/getReleases.ts) ([output](examples/tag/getReleases_output.txt))
<p>Fetches releases matching the tag referred to by <code>params.tagUrl</code>.</p>
**Params**
- `params`: ([TagAPIGetReleasesParams](docs/api/interfaces/TagAPIGetReleasesParams.md))
- `tagUrl`: (string)
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
- `useHardcodedDefaultFilters`: (boolean) (*optional*) if `true`, use hardcoded default values for filters not specified in `params.filters`. If `false` or unspecified, default filter values will be obtained by calling ``getReleasesAvailableFilters`()` (extra query means slower performance).
- `filters`: (object{ string: string | number | Array<string | number >}) (*optional*)
- `page`: (number) (*optional*) 1 if omitted.
#### `params.filters`:
Properties of `params.filters` are not strictly defined. As of this documentation, the curent filters available on Bandcamp are:
- `location`: (number)
- `tags`: (Array&lt;string&gt;) list of tags to match, in addition to the one referred to by `params.tagUrl`.
- `sort`: (string)
- `format`: (string)
Omitted properties are populated with default values obtained from `params.tagUrl`. Possible filter values can be obtained by calling `getReleasesAvailableFilters()`. For `location` and `tag` filters, you may look up additional values not returned by `getReleasesAvailableFilters()` through `getSuggestions()` of the [Autocomplete API](#autocomplete-api).
**Returns**
Promise resolving to [ReleasesByTag](docs/api/interfaces/ReleasesByTag-1.md).
---
</details>
<details>
<summary><code>getReleasesAvailableFilters(tagUrl)</code></summary>
<br />
[**Example**](examples/tag/getReleasesAvailableFilters.ts) ([output](examples/tag/getReleasesAvailableFilters_output.txt))
<p>Fetches the list of possible filter values for <code>getReleases()</code>.</p>
For `location` and `tag` filters, this method does not return an exhaustive list of values. You may use `getSuggestions()` of the [Autocomplete API](#autocomplete-api) to look up additional values.
**Params**
- `tagUrl`: (string) the URL of the tag for which filter values are to be returned.
**Returns**
Promise resolving to Array<[ReleasesByTag.Filter](docs/api/interfaces/ReleasesByTag.Filter.md)>.
---
</details>
## Show API
To access the Show API:
```
import bcfetch from 'bandcamp-fetch';
const show = bcfetch.show;
const list = await show.list(...);
```
**Methods:**
<details>
<summary><code>list(params)</code></summary>
<br />
[**Example**](examples/show/list.ts) ([output](examples/show/list_output.txt))
<p>Fetches the full list of Bandcamp shows.</p>
Each list entry contains basic info about a show. To obtain full details, pass its `url` to `getShow()`.
**Params**
- `params`: ([ShowAPIListParams](docs/api/interfaces/ShowAPIListParams.md)) (*optional*)
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
**Returns**
Promise resolving to Array<[Show](docs/api/interfaces/Show.md)>.
---
</details>
<details>
<summary><code>getShow(params)</code></summary>
<br />
[**Example**](examples/show/getShow.ts) ([output](examples/show/getShow_output.txt))
<p>Fetches full details about the Bandcamp show referred to by <code>params.showUrl</code>.</p>
**Params**
- `params`: ([ShowAPIGetShowParams](docs/api/interfaces/ShowAPIGetShowParams.md))
- `showUrl`: (string)
- `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
- `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
- `showImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
**Returns**
Promise resolving to [Show](docs/api/interfaces/Show.md).
---
</details>
## Article API
To access the Article API:
```
import bcfetch from 'bandcamp-fetch';
const article = bcfetch.article;
const list = await article.list(...);
```
**Methods:**
<details>
<summary><code>getCategories()</code></summary>
<br />
[**Example**](examples/article/getCategories.ts) ([output](examples/article/getCategories_output.txt))
<p>Fetches the list of Bandcamp Daily article categories. Categories are grouped into sections.</p>
**Returns**
Promise resolving to Array<[ArticleCategorySection](docs/api/interfaces/ArticleCategorySection.md)>.
---
</details>
<details>
<summary><code>list(params)</code></summary>
<br />
[**Example**](examples/article/list.ts) ([output](examples/article/list_output.txt))
<p>Fetches the list of Bandcamp Daily articles under the category specified by <code>params.categoryUrl</code> (or all categories if not specified).</p>
**Params**
- `params`: ([ArticleAPIListParams](docs/api/interfaces/ArticleAPIListParams.md)) (*optional* and *all properties optional*)
- `categoryUrl`: (string)
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md))
- `page`: (number)
**Returns**
Promise resolving to [ArticleList](docs/api/interfaces/ArticleList.md).
---
</details>
<details>
<summary><code>getArticle(params)</code></summary>
<br />
[**Example**](examples/article/getArticle.ts) ([output](examples/article/getArticle_output.txt))
<p>Fetches the contents of the Bandcamp Daily article at <code>params.articleUrl</code>.</p>
**Params**
- `params`: ([ArticleAPIGetArticleParams](docs/api/interfaces/ArticleAPIGetArticleParams.md))
- `articleUrl`: (string)
- `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
- `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
- `includeRawData`: (boolean) (*optional*)
**Returns**
Promise resolving to [Article](docs/api/interfaces/Article.md).
---
</details>
## Fan API
To access the Fan API:
```
import bcfetch from 'bandcamp-fetch';
const fan = bcfetch.fan;
const info = await fan.getInfo(...);
const collection = await fan.getCollection(...);
```
**Methods:**
<details>
<summary><code>getInfo(params)</code></summary>
<br />
[**Example**](examples/fan/getInfo.ts) ([output](examples/fan/getInfo_output.txt))
<p>Fetches info about a fan.</p>
**Params**
- `params`: ([FanAPIGetInfoParams](docs/api/interfaces/FanAPIGetInfoParams.md))
- `username`: (string) (*optional*)
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
If `username` is not specified, result will be obtained for the user of the [session](#user-sessions) tied to the `BandcampFetch` instance.
**Returns**
Promise resolving to [Fan](docs/api/interfaces/Fan.md).
---
</details>
<details>
<summary><code>getCollection(params)</code></summary>
<br />
[**Example**](examples/fan/getCollection.ts) ([output](examples/fan/getCollection_output.txt))
<p>Fetches the list of albums and tracks in a fan's collection.</p>
**Params**
- `params`: ([FanAPIGetItemsParams](docs/api/interfaces/FanAPIGetItemsParams.md))
- `target`: (string | [FanItemsContinuation](docs/api/interfaces/FanItemsContinuation.md)) (*optional*) if username (string) is specified, returns the first batch of items in the collection. To obtain further items, call the method again but, instead of username, pass `continuation` from the result of the first call. If there are no further items available, `continuation` will be `null`.
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
If `target` is not specified, result will be obtained for the user of the [session](#user-sessions) tied to the `BandcampFetch` instance.
**Returns**
Promise resolving to ([FanPageItemsResult](docs/api/interfaces/FanPageItemsResult.md) | [FanContinuationItemsResult](docs/api/interfaces/FanContinuationItemsResult.md))<[Album](docs/api/interfaces/Album.md) | [Track](docs/api/interfaces/Track.md)>.
---
</details>
<details>
<summary><code>getWishlist(params)</code></summary>
<br />
[**Example**](examples/fan/getWishlist.ts) ([output](examples/fan/getWishlist_output.txt))
<p>Fetches the list of albums and tracks added to a fan's wishlist.</p>
**Params**
- `params`: ([FanAPIGetItemsParams](docs/api/interfaces/FanAPIGetItemsParams.md))
- `target`: (string | [FanItemsContinuation](docs/api/interfaces/FanItemsContinuation.md)) (*optional*) if username (string) is specified, returns the first batch of items in the wishlist. To obtain further items, call the method again but, instead of username, pass `continuation` from the result of the first call. If there are no further items available, `continuation` will be `null`.
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
If `target` is not specified, result will be obtained for the user of the [session](#user-sessions) tied to the `BandcampFetch` instance.
**Returns**
Promise resolving to ([FanPageItemsResult](docs/api/interfaces/FanPageItemsResult.md) | [FanContinuationItemsResult](docs/api/interfaces/FanContinuationItemsResult.md))<[Album](docs/api/interfaces/Album.md) | [Track](docs/api/interfaces/Track.md)>.
---
</details>
<details>
<summary><code>getFollowingArtistsAndLabels(params)</code></summary>
<br />
[**Example**](examples/fan/getFollowingArtistsAndLabels.ts) ([output](examples/fan/getFollowingArtistsAndLabels_output.txt))
<p>Fetches the list of artists and labels followed by a fan.</p>
**Params**
- `params`: ([FanAPIGetItemsParams](docs/api/interfaces/FanAPIGetItemsParams.md))
- `target`: (string | [FanItemsContinuation](docs/api/interfaces/FanItemsContinuation.md)) (*optional*) if username (string) is specified, returns the first batch of artists and labels. To obtain further items, call the method again but, instead of username, pass `continuation` from the result of the first call. If there are no further items available, `continuation` will be `null`.
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
If `target` is not specified, result will be obtained for the user of the [session](#user-sessions) tied to the `BandcampFetch` instance.
**Returns**
Promise resolving to ([FanPageItemsResult](docs/api/interfaces/FanPageItemsResult.md) | [FanContinuationItemsResult](docs/api/interfaces/FanContinuationItemsResult.md))<[UserKind](docs/api/interfaces/UserKind.md)>.
---
</details>
<details>
<summary><code>getFollowingGenres(params)</code></summary>
<br />
[**Example**](examples/fan/getFollowingGenres.ts) ([output](examples/fan/getFollowingGenres_output.txt))
<p>Fetches the list of genres followed by a fan.</p>
Each genre is actually a Bandcamp tag, so you can, for example, pass its `url` to `getReleases()` of the [Tag API](#tag-api).
**Params**
- `params`: ([FanAPIGetItemsParams](docs/api/interfaces/FanAPIGetItemsParams.md))
- `target`: (string | [FanItemsContinuation](docs/api/interfaces/FanItemsContinuation.md)) (*optional*) if username (string) is specified, returns the first batch of genres. To obtain further items, call the method again but, instead of username, pass `continuation` from the result of the first call. If there are no further items available, `continuation` will be `null`.
- `imageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
If `target` is not specified, result will be obtained for the user of the [session](#user-sessions) tied to the `BandcampFetch` instance.
**Returns**
Promise resolving to ([FanPageItemsResult](docs/api/interfaces/FanPageItemsResult.md) | [FanContinuationItemsResult](docs/api/interfaces/FanContinuationItemsResult.md))<[Tag](docs/api/interfaces/Tag.md)>.
---
</details>
## Search API
To access the Search API:
```
import bcfetch from 'bandcamp-fetch';
const search = bcfetch.search;
const albums = await search.albums(...);
const all = await search.all(...);
```
**Methods:**
<details>
<summary><code>all(params) / artistsAndLabels(params) / albums(params) / tracks(params) / fans(params)</code></summary>
<br />
[**Example**](examples/search/search.ts) ([output](examples/search/search_output.txt))
- `all(params)`: search all item types
- `artistsAndLabels(params)`: search artists and labels
- `albums(params)`: search albums
- `tracks(params)`: search tracks
- `fans(params)`: search fans
**Params**
- `params`: ([SearchAPISearchParams](docs/api/interfaces/SearchAPISearchParams.md))
- `query`: (string)
- `page`: (number) (*optional*) 1 if omitted
- `albumImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
- `artistImageFormat`: (string | number | [ImageFormat](docs/api/interfaces/ImageFormat.md)) (*optional*)
**Returns**
Promise resolving to [SearchResults](docs/api/interfaces/SearchResults.md)&lt;`T`&gt;, where `T` depends on the item type being searched and can be one of:
- Artist ([SearchResultArtist](docs/api/interfaces/SearchResultArtist.md))
- Label ([SearchResultLabel](docs/api/interfaces/SearchResultLabel.md))
- Album ([SearchResultAlbum](docs/api/interfaces/SearchResultAlbum.md))
- Track ([SearchResultTrack](docs/api/interfaces/SearchResultTrack.md))
- Fan ([SearchResultFan](docs/api/interfaces/SearchResultFan.md))
You can use the `type` property to determine the search result item type.
---
</details>
## Autocomplete API
To access the Autocomplete API:
```
import bcfetch from 'bandcamp-fetch';
const autocomplete = bcfetch.autocomplete;
const suggestions = await autocomplete.getSuggestions(...);
```
**Methods:**
<details>
<summary><code>getSuggestions(params)</code></summary>
<br />
[**Example**](examples/autocomplete/getSuggestions.ts) ([output](examples/autocomplete/getSuggestions_output.txt))
<p>Fetches autocomplete suggestions for tags and locations, based on partial and full matches against `params.query`.</p>
The `value` property of returned suggestions can be used to set the `location` or `tags` property (as the case may be) of `params.filters` that is passed into `getReleases()` of the [Tag API](#tag-api).
**Params**
- `params`: ([AutocompleteAPIGetSuggestionsParams](docs/api/interfaces/AutocompleteAPIGetSuggestionsParams.md))
- `query`: (string)
- `itemType`: ([AutocompleteItemType](docs/api/enums/AutocompleteItemType.md)) 'Tag' or 'Location'
- limit: (number) (*optional*) the maximum number of results to return; 5 if omitted.
**Returns**
- If `params.itemType` is `AutocompleteItemType.Tag`, a Promise resolving to Array<[AutocompleteTag](docs/api/interfaces/AutoCompleteTag.md)>.
- If `params.itemType` is `AutocompleteItemType.Location`, a Promise resolving to Array<[AutocompleteLocation](docs/api/interfaces/AutocompleteLocation.md)>.
---
</details>
# Rate Limiting
Each `BandcampFetch` instance comes with a rate limiter, which limits the number of requests made within a specific time period.
Rate limiting is useful when you need to make a large number of queries and don't want to run the risk of getting rejected by the server for making too many requests within a short time interval. If you get a '429 Too Many Requests' error, then you should consider using the rate limiter.
Each API has a limiter-enabled counterpart which you can access in the following manner:
```
import bcfetch from 'bandcamp-fetch';
// Album API - no limiter enabled
const albumAPI = bcfetch.album;
// Album API - limiter enabled
const limiterAlbumAPI = bcfetch.limiter.album;
```
[**Example**](examples/limiter/limiter.ts) ([output](examples/limiter/limiter_output.txt))
The library uses [Bottleneck](https://www.npmjs.com/package/bottleneck) for rate limiting. You can configure the rate limiter like this:
```
bcfetch.limiter.updateSettings({
maxConcurrent: 10, // default: 5
minTime: 100 // default: 200
});
```
`updateSettings()` is just a passthrough function to Bottleneck. Check the [Bottleneck doc](https://www.npmjs.com/package/bottleneck#docs) for the list of options you can set.
# Cache
Each `BandcampFetch` instance has an in-memory cache for two types of data (as defined by [CacheDataType](docs/api/enums/CacheDataType.md)):
1. `CacheDataType.Page` - pages fetched during scraping
2. `CacheDataType.Constants` - image formats and discover options
To access the cache:
```
import bcfetch, { CacheDataType } from 'bandcamp-fetch';
const cache = bcfetch.cache;
cache.setTTL(CacheDataType.Page, 500);
```
**Methods:**
<details>
<summary><code>setTTL(type, ttl)</code></summary>
<br />
<p>Sets the expiry time, in seconds, of cache entries for the given data type.</p>
**Params**
- `type`: ([CacheDataType](docs/api/enums/CacheDataType.md))
- `TTL`: (number) expiry time in seconds (default: 300 for `CacheDataType.Page` and 3600 for `CacheDataType.Constants`)
---
</details>
<details>
<summary><code>setMaxPages(maxPages)</code></summary>
<br />
<p>Sets the maximum number of pages that can be stored in the cache. A negative value means unlimited. Default: 10.</p>
**Params**
- `maxPages`: (number)
---
</details>
<details>
<summary><code>clear([type])</code></summary>
<br />
<p>Clears the cache entries for the specified data type (or all entries if no data type specified).</p>
**Params**
- `type`: ([CacheDataType](docs/api/enums/CacheDataType.md)) (*optional*)
---
</details>
# Changelog
1.1.1
- Fix exports
1.1.0
- Add support for user sessions through cookies. This means you can access your private collection and high-quality MP3 streams of purchased media.
- Add ability to create multiple `BandcampFetch` instances
1.0.2
- Improve parsing of album track info
1.0.1
- Fix limiter throwing private access errors
1.0.0 (breaking changes!)
- Move to TypeScript
- Package as ESM + CJS hybrid module
- Restructure API
- Remove `safe-eval` dependency
0.3.1-b.1
- Add `getFanCollection()` function
0.3.0-b.1
- Add fan functions
0.2.2-b.1
- Add `itemType` option to search params
0.2.1-b.20211020b
- Fix URL sometimes null in result of `getArtistOrLabelInfo()`
0.2.1-b.20211020
- Improve data fetching in `getArtistOrLabelInfo()`
0.2.0-b.20211020
- Adapt to Bandcamp changes since last version
- Add `publisher` and `label` to data fetched by `getAlbumInfo()` and `getTrackInfo()`
- Add `labelId` to data fetched by `getArtistOrLabelInfo(labelUrl)`
- Add `labelId` option to `getArtistOrLabelInfo()` for artist URLs
...(no changelog for earlier versions due to laziness)
# License
MIT