江品陞 Vincent Chiang
vincentchiang@kkbox.com
Lecturer
Developer Advocate @
import { ARTISTS as ENDPOINT } from '../Endpoint';
import Fetcher from './Fetcher';
export default class ArtistFetcher extends Fetcher {
constructor(http, territory = 'TW') {
super(http, territory);
this.artistID = undefined;
}
setArtistID(artistID) {
this.artistID = artistID;
return this;
}
// @example api.artistFetcher.setArtistID('Cnv_K6i5Ft4y41SxLy').fetchMetadata();
fetchMetadata() {
return this.http.get(ENDPOINT + '/' + this.artistID, {
territory: this.territory
});
}
// @example api.artistFetcher.setArtistID('Cnv_K6i5Ft4y41SxLy').fetchAlbums();
fetchAlbums(limit = undefined, offset = undefined) {
return this.http.get(ENDPOINT + '/' + this.artistID + '/albums', {
territory: this.territory,
limit: limit,
offset: offset
});
}
// @example api.artistFetcher.setArtistID('Cnv_K6i5Ft4y41SxLy').fetchTopTracks();
fetchTopTracks(limit = undefined, offset = undefined) {
return this.http.get(ENDPOINT + '/' + this.artistID + '/top-tracks', {
territory: this.territory,
limit: limit,
offset: offset
});
}
// @example api.artistFetcher.setArtistID('Cnv_K6i5Ft4y41SxLy').fetchRelatedArtists();
fetchRelatedArtists(limit = undefined, offset = undefined) {
return this.http.get(ENDPOINT + '/' + this.artistID + '/related-artists', {
territory: this.territory,
limit: limit,
offset: offset
});
}
}
/**
* Fetch KKBOX resources.
*/
export default class Api {
/**
* Need access token to initialize.
*
* @param {string} token - Get via Auth.
* @param {string} [territory = 'TW'] - ['TW', 'HK', 'SG', 'MY', 'JP'] The territory for the fetcher.
* @example new Api(token);
* @example new Api(token, 'TW');
*/
constructor(token, territory = 'TW') {
this.territory = territory;
this.httpClient = undefined;
this.setToken(token);
}
/**
* Set new token and create fetchers with the new token.
*
* @param {string} token - Get via Auth.
* @example api.setToken(token);
*/
setToken(token) {
this.httpClient = new HttpClient(token);
/**
* @type {SearchFetcher}
*/
this.searchFetcher = new SearchFetcher(this.httpClient, this.territory);
/**
* @type {TrackFetcher}
*/
this.trackFetcher = new TrackFetcher(this.httpClient, this.territory);
/**
* @type {AlbumFetcher}
*/
this.albumFetcher = new AlbumFetcher(this.httpClient, this.territory);
/**
* @type {ArtistFetcher}
*/
this.artistFetcher = new ArtistFetcher(this.httpClient, this.territory);
/**
* @type {FeaturedPlaylistFetcher}
*/
this.featuredPlaylistFetcher = new FeaturedPlaylistFetcher(
this.httpClient,
this.territory
);
/**
* @type {FeaturedPlaylistCategoryFetcher}
*/
this.featuredPlaylistCategoryFetcher = new FeaturedPlaylistCategoryFetcher(
this.httpClient,
this.territory
);
/**
* @type {NewReleaseCategoryFetcher}
*/
this.newReleaseCategoryFetcher = new NewReleaseCategoryFetcher(
this.httpClient,
this.territory
);
/**
* @type {NewHitsPlaylistFetcher}
*/
this.newHitsPlaylistFetcher = new NewHitsPlaylistFetcher(
this.httpClient,
this.territory
);
/**
* @type {GenreStationFetcher}
*/
this.genreStationFetcher = new GenreStationFetcher(
this.httpClient,
this.territory
);
/**
* @type {MoodStationFetcher}
*/
this.moodStationFetcher = new MoodStationFetcher(
this.httpClient,
this.territory
);
/**
* @type {ChartFetcher}
*/
this.chartFetcher = new ChartFetcher(this.httpClient, this.territory);
/**
* @type {SharedPlaylistFetcher}
*/
this.sharedPlaylistFetcher = new SharedPlaylistFetcher(
this.httpClient,
this.territory
);
}
}
SDK 可以實現原本 API 做不到的功能
import { SEARCH as ENDPOINT } from '../Endpoint';
import Fetcher from './Fetcher';
/**
* Search API.
* @see https://docs-en.kkbox.codes/v1.1/reference#search
*/
export default class SearchFetcher extends Fetcher {
/**
* Filter what you don't want when search.
*
* @param {Object} [conditions] - search conditions.
* @param {string} conditions.track - track's name.
* @param {string} conditions.album - album's name.
* @param {string} conditions.artist - artist's name.
* @param {string} conditions.playlist - playlist's title.
* @param {string} conditions.availableTerritory - tracks and albums available territory.
* @return {Search}
* @example
* api.searchFetcher
* .setSearchCriteria(q = '飄向北方', type = 'track')
* .filter({artist: '黃明志, G.E.M.鄧紫棋'})
* .fetchSearchResult();
*/
filter(conditions = {}) {
this.filterConditions = conditions;
return this;
}
}
URI Rule
https://widget.kkbox.com/v1/?id={id}&type={type}&terr={territory}&lang={lang}&autoplay={boolean}&loop={boolean}
export default class TrackFetcher extends Fetcher {
/**
* Get KKBOX web widget uri of the track.
* @example https://widget.kkbox.com/v1/?id=8sD5pE4dV0Zqmmler6&type=song
* @return {string}
*/
getWidgetUri() {
return `https://widget.kkbox.com/v1/?id=${this.trackID}&type=song`;
}
}
export default class SharedPlaylistFetcher extends Fetcher {
/**
* Get KKBOX web widget uri of the playlist.
* @example https://widget.kkbox.com/v1/?id=KmjwNXizu5MxHFSloP&type=playlist
* @return {string}
*/
getWidgetUri() {
return `https://widget.kkbox.com/v1/?id=${this.playlistID}&type=playlist`;
}
}
import SearchFetcher from "../api/SearchFetcher";
describe('Search', () => {
const searchFetcher = new SearchFetcher(
httpClient
).setSearchCriteria('Linkin Park');
describe('#fetchSearchResult()', () => {
it('should response status 200', () => {
return searchFetcher.fetchSearchResult().then(response => {
response.status.should.be.exactly(200),
reject => should.not.exists(reject);
});
});
});
describe('#filter()', () => {
it('should get result', () => {
return searchFetcher
.filter({
artist: 'Linkin Park',
album: 'One More Light',
available_territory: 'TW'
})
.fetchSearchResult()
.then(response => {
response.data.tracks.data.length.should.be.greaterThan(0);
});
});
});
});
import { SEARCH as ENDPOINT } from '../Endpoint';
import Fetcher from './Fetcher';
/**
* Search API.
* @see https://docs-en.kkbox.codes/v1.1/reference#search
*/
export default class SearchFetcher extends Fetcher {
/**
* Filter what you don't want when search.
*
* @param {Object} [conditions] - search conditions.
* @param {string} conditions.track - track's name.
* @param {string} conditions.album - album's name.
* @param {string} conditions.artist - artist's name.
* @param {string} conditions.playlist - playlist's title.
* @param {string} conditions.availableTerritory - tracks and albums available territory.
* @return {Search}
* @example
* api.searchFetcher
* .setSearchCriteria('五月天 好好')
* .filter({artist: '五月天'})
* .fetchSearchResult();
*/
filter(conditions = {}) {
this.filterConditions = conditions;
return this;
}
}