spotify-service-rg
Version:
This is a Angular service for connecting to and using Spotify API.
394 lines • 36 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common/http";
export class SpotifyRgService {
/**
* @param {?} http
*/
constructor(http) {
this.http = http;
this.baseUrl = "https://api.spotify.com/v1";
}
/**
* @return {?}
*/
login() {
window.location.href = 'https://accounts.spotify.com/authorize' +
'?response_type=token' +
'&client_id=' + this.clientId +
(this.scopes ? '&scope=' + encodeURIComponent(this.scopes) : '') +
'&redirect_uri=' + encodeURIComponent(this.callBackUrl);
}
//Setters for the configuration properties
/**
* @param {?} clientId
* @return {?}
*/
setClientId(clientId) {
this.clientId = clientId;
}
/**
* @param {?} callBackUrl
* @return {?}
*/
setCallBackUrl(callBackUrl) {
this.callBackUrl = callBackUrl;
}
/**
* @param {?} scopes
* @return {?}
*/
setScopes(scopes) {
this.scopes = scopes;
}
/**
* @param {?} token
* @return {?}
*/
setToken(token) {
this.token = token;
}
/**
* \@description Returns track
* @param {?} trackId
* @return {?}
*/
getTrack(trackId) {
return this.apiGet("/tracks/" + trackId, null, this.getHeaders());
}
/**
* \@description Returns tracks
* @param {?} trackIds
* @return {?}
*/
getTracks(trackIds) {
/** @type {?} */
const t = encodeURIComponent(trackIds);
return this.apiGet("/tracks/?ids=" + t, null, this.getHeaders());
}
/**
* \@description Returns album
* @param {?} albumId
* @return {?}
*/
getAlbum(albumId) {
return this.apiGet("/albums/" + albumId, null, this.getHeaders());
}
/**
* \@description Returns albums
* @param {?} albumIds
* @return {?}
*/
getAlbums(albumIds) {
/** @type {?} */
const a = encodeURIComponent(albumIds);
return this.apiGet("/albums/?ids=" + a, null, this.getHeaders());
}
/**
* \@description Returns albums tracks
* @param {?} albumId
* @return {?}
*/
getAlbumsTracks(albumId) {
return this.apiGet("/albums/" + albumId + "/tracks", null, this.getHeaders());
}
/**
* \@description Returns artist
* @param {?} artistId Artists spotify ID.
* @return {?}
*/
getArtist(artistId) {
return this.apiGet("/artists/" + artistId, null, this.getHeaders());
}
/**
* \@description Returns artists
* @param {?} artistIds
* @return {?}
*/
getArtists(artistIds) {
/** @type {?} */
const a = encodeURIComponent(artistIds);
return this.apiGet("/artists/?ids=" + a, null, this.getHeaders());
}
/**
* \@description Returns artists albums
* @param {?} artistId Artists Spotify ID.
* @return {?}
*/
getArtistsAlbums(artistId) {
return this.apiGet("/artists/" + artistId + "/albums", null, this.getHeaders());
}
/**
* \@description Returns artists top tracks
* @param {?} artistId Artists Spotify ID.
* @param {?=} countryCode Country code in 2 char Format. For example FI. Defaults to extracting country code from token.
* @return {?}
*/
getArtistsTopTracks(artistId, countryCode) {
/** @type {?} */
var countryCode = (countryCode != null && countryCode.length == 2) ? countryCode : "from_token";
return this.apiGet("/artists/" + artistId + "/top-tracks?country=" + countryCode, null, this.getHeaders());
}
/**
* \@description Returns the user assosiated with auth token
* @param {?} userId The Spotify User id
* @return {?}
*/
getUserById(userId) {
return this.apiGet('/users/' + userId, null, this.getHeaders());
}
/**
* \@description Returns the user assosiated with auth token
* @return {?}
*/
getUser() {
return this.apiGet('/me', null, this.getHeaders());
}
/**
* \@description Returns current users top tracks
* @param {?} timeRange The range of time results are returned from. Use short_term, medium_term or long_term. Defaults to long_term.
* @param {?=} count Amount of tracks returned. Max value 50. Defaults to 50.
* @return {?}
*/
getUsersTopTracks(timeRange, count) {
/** @type {?} */
const params = {
//set backup default values
'time_range': timeRange == null ? 'long_term' : timeRange,
'limit': count == null ? '50' : count
};
return this.apiGet("/me/top/tracks", params, this.getHeaders());
}
/**
* \@description Returns users playlists
* @param {?} userId Users Spotify Id
* @return {?}
*/
getUsersPlaylists(userId) {
return this.apiGet('/users/' + userId + '/playlists', null, this.getHeaders());
}
/**
* \@description Returns recommendations based on seeds. Max 5 seeds allowed (thats total so for example 3 artists and 2 tracks)
* @param {?} seedArtists Comma separated list of artist seed Ids
* @param {?} seedTracks Comma separated list of track seed Ids
* @return {?}
*/
getRecommendedTracks(seedArtists, seedTracks) {
/** @type {?} */
const sA = encodeURIComponent(seedArtists);
/** @type {?} */
const sT = encodeURIComponent(seedTracks);
return this.apiGet('/recommendations?limit=50&seed_artists=' + sA + '&seed_tracks=' + sT, null, this.getHeaders());
}
/**
* \@description Get a list of new album releases featured in Spotify
* @param {?=} countryCode Country code in 2 char Format. If not set searches from all.
* @param {?=} count Amount of results returned. Defaults to 20.
* @return {?}
*/
getNewReleases(countryCode, count) {
/** @type {?} */
var query = "";
if (countryCode != null && countryCode != "") {
query += "?country=" + countryCode;
}
if (count != null && count != "") {
query += (query.length == 0) ? "?" : "&";
query += "limit=" + count;
}
return this.apiGet('/browse/new-releases' + query, null, this.getHeaders());
}
/**
* \@description Get a list of Spotify featured playlists
* @param {?=} countryCode Country code in 2 char Format. If not set searches from all.
* @param {?=} count Amount of results returned. Defaults to 20.
* @return {?}
*/
getFeaturedPlaylists(countryCode, count) {
/** @type {?} */
var query = "";
if (countryCode != null && countryCode != "") {
query += "?country=" + countryCode;
}
if (count != null && count != "") {
query += (query.length == 0) ? "?" : "&";
query += "limit=" + count;
}
return this.apiGet('/browse/featured-playlists' + query, null, this.getHeaders());
}
/**
* \@description Get a single category used to tag items in Spotify
* @param {?} categoryId Spotifys Category Id
* @return {?}
*/
getCategory(categoryId) {
return this.apiGet('/browse/categories/' + categoryId, null, this.getHeaders());
}
/**
* \@description Get a list of categories used to tag items in Spotify
* @param {?=} countryCode Country code in 2 char Format. If not set searches from all.
* @param {?=} count Amount of results returned. Defaults to 20.
* @return {?}
*/
getCategories(countryCode, count) {
/** @type {?} */
var query = "";
if (countryCode != null && countryCode != "") {
query += "?country=" + countryCode;
}
if (count != null && count != "") {
query += (query.length == 0) ? "?" : "&";
query += "limit=" + count;
}
return this.apiGet('/browse/categories' + query, null, this.getHeaders());
}
/**
* \@description Get a list of Spotify playlists tagged with a particular category.
* @param {?} categoryId The Spotify category ID for the category.
* @param {?=} countryCode Country code in 2 char Format. If not set searches from all.
* @param {?=} count Amount of results returned. Defaults to 20.
* @return {?}
*/
getCategorysPlaylists(categoryId, countryCode, count) {
/** @type {?} */
var query = "";
if (countryCode != null && countryCode != "") {
query += "?country=" + countryCode;
}
if (count != null && count != "") {
query += (query.length == 0) ? "?" : "&";
query += "limit=" + count;
}
return this.apiGet('/browse/categories/' + categoryId + '/playlists' + query, null, this.getHeaders());
}
/**
* \@description Creates a playlist
* @param {?} userId Users spotify ID.
* @param {?} name A name for the playlist .
* @param {?} description A description for the playlist.
* @param {?} isPublic Defines if a playlist is public or private
* @return {?}
*/
createPlayList(userId, name, description, isPublic) {
/** @type {?} */
var body = {
"name": name,
"description": description,
"public": isPublic
};
return this.apiPost('/me/playlists?user_id=' + userId, body, this.getHeaders());
}
/**
* \@description Adds tracks to playlist
* @param {?} playListId
* @param {?} trackUris Array of spotify track uris. Max 100 tracks can be added at a time.
* @return {?}
*/
addTracksToPlaylist(playListId, trackUris) {
/** @type {?} */
var body = {
"uris": trackUris,
};
return this.apiPost('/playlists/' + playListId + '/tracks', body, this.getHeaders());
}
/**
* \@description Returns Spotify Catalog information about artists, albums, tracks or playlists that match a keyword string.
* @param {?} query Search word.
* @param {?} types
* @param {?} count The count is applied within each type, not on the total response. So count 3 with type album,track returns 3 albums and 3 tracks. Max 50.
* @return {?}
*/
search(query, types, count) {
/** @type {?} */
const q = encodeURIComponent(query);
/** @type {?} */
const t = encodeURIComponent(types);
return this.apiGet('/search?q=' + q + '&type=' + t + '&limit=' + count, null, this.getHeaders());
}
/**
* @private
* @param {?} endpoint
* @param {?} params
* @param {?} headers
* @return {?}
*/
apiGet(endpoint, params, headers) {
return this.http.get(this.baseUrl + endpoint, {
params: params,
headers: headers,
withCredentials: false
}).toPromise();
}
/**
* @private
* @param {?} endpoint
* @param {?} data
* @param {?} headers
* @return {?}
*/
apiPost(endpoint, data, headers) {
return this.http.post(this.baseUrl + endpoint, data, {
headers: headers,
})
.toPromise();
}
/**
* @private
* @return {?}
*/
getHeaders() {
return {
'Authorization': 'Bearer ' + this.token,
'Accept': 'application/json',
'Content-Type': 'application/json'
};
}
}
SpotifyRgService.decorators = [
{ type: Injectable, args: [{
providedIn: 'root'
},] }
];
/** @nocollapse */
SpotifyRgService.ctorParameters = () => [
{ type: HttpClient }
];
/** @nocollapse */ SpotifyRgService.ngInjectableDef = i0.defineInjectable({ factory: function SpotifyRgService_Factory() { return new SpotifyRgService(i0.inject(i1.HttpClient)); }, token: SpotifyRgService, providedIn: "root" });
if (false) {
/**
* @type {?}
* @private
*/
SpotifyRgService.prototype.baseUrl;
/**
* @type {?}
* @private
*/
SpotifyRgService.prototype.token;
/**
* @type {?}
* @private
*/
SpotifyRgService.prototype.scopes;
/**
* @type {?}
* @private
*/
SpotifyRgService.prototype.callBackUrl;
/**
* @type {?}
* @private
*/
SpotifyRgService.prototype.clientId;
/**
* @type {?}
* @private
*/
SpotifyRgService.prototype.http;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BvdGlmeS1yZy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vc3BvdGlmeS1zZXJ2aWNlLXJnLyIsInNvdXJjZXMiOlsibGliL3Nwb3RpZnktcmcuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7OztBQU9sRCxNQUFNLE9BQU8sZ0JBQWdCOzs7O0lBUTNCLFlBQTZCLElBQWdCO1FBQWhCLFNBQUksR0FBSixJQUFJLENBQVk7UUFOckMsWUFBTyxHQUFXLDRCQUE0QixDQUFDO0lBTU4sQ0FBQzs7OztJQUUzQyxLQUFLO1FBQ1YsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEdBQUcsd0NBQXdDO1lBQzdELHNCQUFzQjtZQUN0QixhQUFhLEdBQUcsSUFBSSxDQUFDLFFBQVE7WUFDN0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxTQUFTLEdBQUcsa0JBQWtCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDaEUsZ0JBQWdCLEdBQUcsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQzVELENBQUM7Ozs7OztJQUdNLFdBQVcsQ0FBQyxRQUFnQjtRQUNqQyxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztJQUMzQixDQUFDOzs7OztJQUNNLGNBQWMsQ0FBQyxXQUFtQjtRQUN2QyxJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztJQUNqQyxDQUFDOzs7OztJQUNNLFNBQVMsQ0FBQyxNQUFjO1FBQzdCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0lBQ3ZCLENBQUM7Ozs7O0lBQ00sUUFBUSxDQUFDLEtBQWE7UUFDM0IsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7SUFDckIs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Q2pCLENBQUM7Ozs7O0lBRU8sVUFBVTtRQUNoQixPQUFPO1lBQ0wsZUFBZSxFQUFFLFNBQVMsR0FBRyxJQUFJLENBQUMsS0FBSztZQUN2QyxRQUFRLEVBQUUsa0JBQWtCO1lBQzVCLGNBQWMsRUFBRSxrQkFBa0I7U0FDbkMsQ0FBQTtJQUNILENBQUM7OztZQXRSRixVQUFVLFNBQUM7Z0JBQ1YsVUFBVSxFQUFFLE1BQU07YUFDbkI7Ozs7WUFOUSxVQUFVOzs7Ozs7OztJQVNqQixtQ0FBdUQ7Ozs7O0lBQ3ZELGlDQUFzQjs7Ozs7SUFDdEIsa0NBQXVCOzs7OztJQUN2Qix1Q0FBNEI7Ozs7O0lBQzVCLG9DQUF5Qjs7Ozs7SUFFYixnQ0FBaUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgdG9Qcm9taXNlIH0gZnJvbSAncnhqcy9vcGVyYXRvci90b1Byb21pc2UnO1xuXG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIFNwb3RpZnlSZ1NlcnZpY2Uge1xuXG4gIHByaXZhdGUgYmFzZVVybDogc3RyaW5nID0gXCJodHRwczovL2FwaS5zcG90aWZ5LmNvbS92MVwiO1xuICBwcml2YXRlIHRva2VuOiBzdHJpbmc7XG4gIHByaXZhdGUgc2NvcGVzOiBzdHJpbmc7XG4gIHByaXZhdGUgY2FsbEJhY2tVcmw6IHN0cmluZztcbiAgcHJpdmF0ZSBjbGllbnRJZDogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgaHR0cDogSHR0cENsaWVudCkgeyB9XG5cbiAgcHVibGljIGxvZ2luKCkge1xuICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gJ2h0dHBzOi8vYWNjb3VudHMuc3BvdGlmeS5jb20vYXV0aG9yaXplJyArXG4gICAgICAnP3Jlc3BvbnNlX3R5cGU9dG9rZW4nICtcbiAgICAgICcmY2xpZW50X2lkPScgKyB0aGlzLmNsaWVudElkICtcbiAgICAgICh0aGlzLnNjb3BlcyA/ICcmc2NvcGU9JyArIGVuY29kZVVSSUNvbXBvbmVudCh0aGlzLnNjb3BlcykgOiAnJykgK1xuICAgICAgJyZyZWRpcmVjdF91cmk9JyArIGVuY29kZVVSSUNvbXBvbmVudCh0aGlzLmNhbGxCYWNrVXJsKTtcbiAgfVxuXG4gIC8vU2V0dGVycyBmb3IgdGhlIGNvbmZpZ3VyYXRpb24gcHJvcGVydGllc1xuICBwdWJsaWMgc2V0Q2xpZW50SWQoY2xpZW50SWQ6IHN0cmluZykge1xuICAgIHRoaXMuY2xpZW50SWQgPSBjbGllbnRJZDtcbiAgfVxuICBwdWJsaWMgc2V0Q2FsbEJhY2tVcmwoY2FsbEJhY2tVcmw6IHN0cmluZykge1xuICAgIHRoaXMuY2FsbEJhY2tVcmwgPSBjYWxsQmFja1VybDtcbiAgfVxuICBwdWJsaWMgc2V0U2NvcGVzKHNjb3Blczogc3RyaW5nKSB7XG4gICAgdGhpcy5zY29wZXMgPSBzY29wZXM7XG4gIH1cbiAgcHVibGljIHNldFRva2VuKHRva2VuOiBzdHJpbmcpIHtcbiAgICB0aGlzLnRva2VuID0gdG9rZW47XG4gIH1cblxuICAvKiogQGRlc2NyaXB0aW9uIFJldHVybnMgdHJhY2tcbiAqIEBwYXJhbSBhcnRpc3RJZCBUcmFja3MgU3BvdGlmeSBJRFxuICovXG4gIHB1YmxpYyBnZXRUcmFjayh0cmFja0lkOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5hcGlHZXQoXCIvdHJhY2tzL1wiICsgdHJhY2tJZCwgbnVsbCwgdGhpcy5nZXRIZWFkZXJzKCkpO1xuICB9XG5cbiAgLyoqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIHRyYWNrc1xuICAqIEBwYXJhbSBhcnRpc3RJZCBDb21tYSBzZXBhcmF0ZWQgbGlzdCBvZiB0cmFjayBJRCdzIGluIGEgc3RyaW5nLlxuICAqL1xuICBwdWJsaWMgZ2V0VHJhY2tzKHRyYWNrSWRzOiBzdHJpbmcpIHtcbiAgICBjb25zdCB0ID0gZW5jb2RlVVJJQ29tcG9uZW50KHRyYWNrSWRzKTtcbiAgICByZXR1cm4gdGhpcy5hcGlHZXQoXCIvdHJhY2tzLz9pZHM9XCIgKyB0LCBudWxsLCB0aGlzLmdldEhlYWRlcnMoKSk7XG4gIH1cblxuICAvKiogQGRlc2NyaXB0aW9uIFJldHVybnMgYWxidW1cbiAgKiBAcGFyYW0gYXJ0aXN0SWQgQWxidW1zIFNwb3RpZnkgSUQuXG4gICovXG4gIHB1YmxpYyBnZXRBbGJ1bShhbGJ1bUlkOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5hcGlHZXQoXCIvYWxidW1zL1wiICsgYWxidW1JZCwgbnVsbCwgdGhpcy5nZXRIZWFkZXJzKCkpO1xuICB9XG5cbiAgLyoqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIGFsYnVtc1xuICAqIEBwYXJhbSBhcnRpc3RJZCBDb21tYSBzZXBhcmF0ZWQgbGlzdCBvZiBhbGJ1bSBJRCdzIGluIGEgc3RyaW5nLi5cbiAgKi9cbiAgcHVibGljIGdldEFsYnVtcyhhbGJ1bUlkczogc3RyaW5nKSB7XG4gICAgY29uc3QgYSA9IGVuY29kZVVSSUNvbXBvbmVudChhbGJ1bUlkcyk7XG4gICAgcmV0dXJuIHRoaXMuYXBpR2V0KFwiL2FsYnVtcy8/aWRzPVwiICsgYSwgbnVsbCwgdGhpcy5nZXRIZWFkZXJzKCkpO1xuICB9XG5cbiAgLyoqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIGFsYnVtcyB0cmFja3NcbiAgKiBAcGFyYW0gYXJ0aXN0SWQgQWxidW1zIFNwb3RpZnkgSUQuXG4gICovXG4gIHB1YmxpYyBnZXRBbGJ1bXNUcmFja3MoYWxidW1JZDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMuYXBpR2V0KFwiL2FsYnVtcy9cIiArIGFsYnVtSWQgKyBcIi90cmFja3NcIiwgbnVsbCwgdGhpcy5nZXRIZWFkZXJzKCkpO1xuICB9XG5cbiAgLyoqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIGFydGlzdFxuICAqIEBwYXJhbSBhcnRpc3RJZCBBcnRpc3RzIHNwb3RpZnkgSUQuXG4gICovXG4gIHB1YmxpYyBnZXRBcnRpc3QoYXJ0aXN0SWQ6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmFwaUdldChcIi9hcnRpc3RzL1wiICsgYXJ0aXN0SWQsIG51bGwsIHRoaXMuZ2V0SGVhZGVycygpKTtcbiAgfVxuXG4gIC8qKiBAZGVzY3JpcHRpb24gUmV0dXJucyBhcnRpc3RzXG4gICogQHBhcmFtIGFydGlzdElkIENvbW1hIHNlcGFyYXRlZCBsaXN0IG9mIGFydGlzdCBJRCdzIGluIGEgc3RyaW5nLlxuICAqL1xuICBwdWJsaWMgZ2V0QXJ0aXN0cyhhcnRpc3RJZHM6IHN0cmluZykge1xuICAgIGNvbnN0IGEgPSBlbmNvZGVVUklDb21wb25lbnQoYXJ0aXN0SWRzKTtcbiAgICByZXR1cm4gdGhpcy5hcGlHZXQoXCIvYXJ0aXN0cy8/aWRzPVwiICsgYSwgbnVsbCwgdGhpcy5nZXRIZWFkZXJzKCkpO1xuICB9XG5cbiAgLyoqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIGFydGlzdHMgYWxidW1zXG4gICogQHBhcmFtIGFydGlzdElkIEFydGlzdHMgU3BvdGlmeSBJRC5cbiAgKi9cbiAgcHVibGljIGdldEFydGlzdHNBbGJ1bXMoYXJ0aXN0SWQ6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmFwaUdldChcIi9hcnRpc3RzL1wiICsgYXJ0aXN0SWQgKyBcIi9hbGJ1bXNcIiwgbnVsbCwgdGhpcy5nZXRIZWFkZXJzKCkpO1xuICB9XG5cbiAgLyoqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIGFydGlzdHMgdG9wIHRyYWNrc1xuICAqIEBwYXJhbSBhcnRpc3RJZCBBcnRpc3RzIFNwb3RpZnkgSUQuXG4gICogQHBhcmFtIGNvdW50cnlDb2RlIENvdW50cnkgY29kZSBpbiAyIGNoYXIgRm9ybWF0LiBGb3IgZXhhbXBsZSBGSS4gRGVmYXVsdHMgdG8gZXh0cmFjdGluZyBjb3VudHJ5IGNvZGUgZnJvbSB0b2tlbi5cbiAgKi9cbiAgcHVibGljIGdldEFydGlzdHNUb3BUcmFja3MoYXJ0aXN0SWQ6IHN0cmluZywgY291bnRyeUNvZGU/OiBzdHJpbmcpIHtcbiAgICB2YXIgY291bnRyeUNvZGUgPSAoY291bnRyeUNvZGUgIT0gbnVsbCAmJiBjb3VudHJ5Q29kZS5sZW5ndGggPT0gMikgPyBjb3VudHJ5Q29kZSA6IFwiZnJvbV90b2tlblwiO1xuICAgIHJldHVybiB0aGlzLmFwaUdldChcIi9hcnRpc3RzL1wiICsgYXJ0aXN0SWQgKyBcIi90b3AtdHJhY2tzP2NvdW50cnk9XCIgKyBjb3VudHJ5Q29kZSwgbnVsbCwgdGhpcy5nZXRIZWFkZXJzKCkpO1xuICB9XG5cbiAgLyoqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIHRoZSB1c2VyIGFzc29zaWF0ZWQgd2l0aCBhdXRoIHRva2VuXG4gICogQHBhcmFtIHVzZXJJZCBUaGUgU3BvdGlmeSBVc2VyIGlkXG4gICovXG4gIHB1YmxpYyBnZXRVc2VyQnlJZCh1c2VySWQ6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmFwaUdldCgnL3VzZXJzLycgKyB1c2VySWQsIG51bGwsIHRoaXMuZ2V0SGVhZGVycygpKTtcbiAgfVxuXG4gIC8qKiBAZGVzY3JpcHRpb24gUmV0dXJucyB0aGUgdXNlciBhc3Nvc2lhdGVkIHdpdGggYXV0aCB0b2tlblxuICAqL1xuICBwdWJsaWMgZ2V0VXNlcigpIHtcbiAgICByZXR1cm4gdGhpcy5hcGlHZXQoJy9tZScsIG51bGwsIHRoaXMuZ2V0SGVhZGVycygpKTtcbiAgfVxuXG4gIC8qKiBAZGVzY3JpcHRpb24gUmV0dXJucyBjdXJyZW50IHVzZXJzIHRvcCB0cmFja3NcbiAgKiBAcGFyYW0gdGltZVJhbmdlIFRoZSByYW5nZSBvZiB0aW1lIHJlc3VsdHMgYXJlIHJldHVybmVkIGZyb20uIFVzZSBzaG9ydF90ZXJtLCBtZWRpdW1fdGVybSBvciBsb25nX3Rlcm0uIERlZmF1bHRzIHRvIGxvbmdfdGVybS5cbiAgKiBAcGFyYW0gY291bnQgQW1vdW50IG9mIHRyYWNrcyByZXR1cm5lZC4gTWF4IHZhbHVlIDUwLiBEZWZhdWx0cyB0byA1MC4gXG4gICovXG4gIHB1YmxpYyBnZXRVc2Vyc1RvcFRyYWNrcyh0aW1lUmFuZ2UsIGNvdW50Pzogc3RyaW5nKTogYW55IHtcbiAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAvL3NldCBiYWNrdXAgZGVmYXVsdCB2YWx1ZXNcbiAgICAgICd0aW1lX3JhbmdlJzogdGltZVJhbmdlID09IG51bGwgPyAnbG9uZ190ZXJtJyA6IHRpbWVSYW5nZSxcbiAgICAgICdsaW1pdCc6IGNvdW50ID09IG51bGwgPyAnNTAnIDogY291bnRcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYXBpR2V0KFwiL21lL3RvcC90cmFja3NcIiwgcGFyYW1zLCB0aGlzLmdldEhlYWRlcnMoKSk7XG4gIH1cblxuICAvKiogQGRlc2NyaXB0aW9uIFJldHVybnMgdXNlcnMgcGxheWxpc3RzXG4gICogQHBhcmFtIHVzZXJJZCBVc2VycyBTcG90aWZ5IElkXG4gICovXG4gIHB1YmxpYyBnZXRVc2Vyc1BsYXlsaXN0cyh1c2VySWQ6IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmFwaUdldCgnL3VzZXJzLycgKyB1c2VySWQgKyAnL3BsYXlsaXN0cycsIG51bGwsIHRoaXMuZ2V0SGVhZGVycygpKTtcbiAgfVxuXG4gIC8qKiBAZGVzY3JpcHRpb24gUmV0dXJucyByZWNvbW1lbmRhdGlvbnMgYmFzZWQgb24gc2VlZHMuIE1heCA1IHNlZWRzIGFsbG93ZWQgKHRoYXRzIHRvdGFsIHNvIGZvciBleGFtcGxlIDMgYXJ0aXN0cyBhbmQgMiB0cmFja3MpXG4gICogQHBhcmFtIHNlZWRBcnRpc3RzIENvbW1hIHNlcGFyYXRlZCBsaXN0IG9mIGFydGlzdCBzZWVkIElkc1xuICAqIEBwYXJhbSBzZWVkVHJhY2tzIENvbW1hIHNlcGFyYXRlZCBsaXN0IG9mIHRyYWNrIHNlZWQgSWRzXG4gICovXG4gIHB1YmxpYyBnZXRSZWNvbW1lbmRlZFRyYWNrcyhzZWVkQXJ0aXN0czogc3RyaW5nLCBzZWVkVHJhY2tzOiBzdHJpbmcpOiBhbnkge1xuICAgIGNvbnN0IHNBID0gZW5jb2RlVVJJQ29tcG9uZW50KHNlZWRBcnRpc3RzKTtcbiAgICBjb25zdCBzVCA9IGVuY29kZVVSSUNvbXBvbmVudChzZWVkVHJhY2tzKTtcbiAgICByZXR1cm4gdGhpcy5hcGlHZXQoJy9yZWNvbW1lbmRhdGlvbnM/bGltaXQ9NTAmc2VlZF9hcnRpc3RzPScgKyBzQSArICcmc2VlZF90cmFja3M9JyArIHNULCBudWxsLCB0aGlzLmdldEhlYWRlcnMoKSk7XG4gIH1cblxuICAvKiogQGRlc2NyaXB0aW9uIEdldCBhIGxpc3Qgb2YgbmV3IGFsYnVtIHJlbGVhc2VzIGZlYXR1cmVkIGluIFNwb3RpZnkgXG4gICogQHBhcmFtIGNvdW50cnlDb2RlIENvdW50cnkgY29kZSBpbiAyIGNoYXIgRm9ybWF0LiBJZiBub3Qgc2V0IHNlYXJjaGVzIGZyb20gYWxsLlxuICAqIEBwYXJhbSBjb3VudCBBbW91bnQgb2YgcmVzdWx0cyByZXR1cm5lZC4gRGVmYXVsdHMgdG8gMjAuXG4gICovXG4gIHB1YmxpYyBnZXROZXdSZWxlYXNlcyhjb3VudHJ5Q29kZT86IHN0cmluZywgY291bnQ/OiBzdHJpbmcpIHtcbiAgICB2YXIgcXVlcnkgPSBcIlwiO1xuICAgIGlmIChjb3VudHJ5Q29kZSAhPSBudWxsICYmIGNvdW50cnlDb2RlICE9IFwiXCIpIHtcbiAgICAgIHF1ZXJ5ICs9IFwiP2NvdW50cnk9XCIgKyBjb3VudHJ5Q29kZTtcbiAgICB9XG4gICAgaWYgKGNvdW50ICE9IG51bGwgJiYgY291bnQgIT0gXCJcIikge1xuICAgICAgcXVlcnkgKz0gKHF1ZXJ5Lmxlbmd0aCA9PSAwKSA/IFwiP1wiIDogXCImXCI7XG4gICAgICBxdWVyeSArPSBcImxpbWl0PVwiICsgY291bnQ7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmFwaUdldCgnL2Jyb3dzZS9uZXctcmVsZWFzZXMnICsgcXVlcnksIG51bGwsIHRoaXMuZ2V0SGVhZGVycygpKTtcbiAgfVxuXG4gIC8qKiBAZGVzY3JpcHRpb24gR2V0IGEgbGlzdCBvZiBTcG90aWZ5IGZlYXR1cmVkIHBsYXlsaXN0c1xuICAqIEBwYXJhbSBjb3VudHJ5Q29kZSBDb3VudHJ5IGNvZGUgaW4gMiBjaGFyIEZvcm1hdC4gSWYgbm90IHNldCBzZWFyY2hlcyBmcm9tIGFsbC5cbiAgKiBAcGFyYW0gY291bnQgQW1vdW50IG9mIHJlc3VsdHMgcmV0dXJuZWQuIERlZmF1bHRzIHRvIDIwLlxuICAqL1xuICBwdWJsaWMgZ2V0RmVhdHVyZWRQbGF5bGlzdHMoY291bnRyeUNvZGU/OiBzdHJpbmcsIGNvdW50Pzogc3RyaW5nKSB7XG4gICAgdmFyIHF1ZXJ5ID0gXCJcIjtcbiAgICBpZiAoY291bnRyeUNvZGUgIT0gbnVsbCAmJiBjb3VudHJ5Q29kZSAhPSBcIlwiKSB7XG4gICAgICBxdWVyeSArPSBcIj9jb3VudHJ5PVwiICsgY291bnRyeUNvZGU7XG4gICAgfVxuICAgIGlmIChjb3VudCAhPSBudWxsICYmIGNvdW50ICE9IFwiXCIpIHtcbiAgICAgIHF1ZXJ5ICs9IChxdWVyeS5sZW5ndGggPT0gMCkgPyBcIj9cIiA6IFwiJlwiO1xuICAgICAgcXVlcnkgKz0gXCJsaW1pdD1cIiArIGNvdW50O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5hcGlHZXQoJy9icm93c2UvZmVhdHVyZWQtcGxheWxpc3RzJyArIHF1ZXJ5LCBudWxsLCB0aGlzLmdldEhlYWRlcnMoKSk7XG4gIH1cblxuICAvKiogQGRlc2NyaXB0aW9uIEdldCBhIHNpbmdsZSBjYXRlZ29yeSB1c2VkIHRvIHRhZyBpdGVtcyBpbiBTcG90aWZ5IFxuICAqIEBwYXJhbSBjYXRlZ29yeUlkIFNwb3RpZnlzIENhdGVnb3J5IElkXG4gICovXG4gIHB1YmxpYyBnZXRDYXRlZ29yeShjYXRlZ29yeUlkOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5hcGlHZXQoJy9icm93c2UvY2F0ZWdvcmllcy8nK2NhdGVnb3J5SWQsIG51bGwsIHRoaXMuZ2V0SGVhZGVycygpKTtcbiAgfVxuXG5cbiAgLyoqIEBkZXNjcmlwdGlvbiBHZXQgYSBsaXN0IG9mIGNhdGVnb3JpZXMgdXNlZCB0byB0YWcgaXRlbXMgaW4gU3BvdGlmeVxuICAqIEBwYXJhbSBjb3VudHJ5Q29kZSBDb3VudHJ5IGNvZGUgaW4gMiBjaGFyIEZvcm1hdC4gSWYgbm90IHNldCBzZWFyY2hlcyBmcm9tIGFsbC5cbiAgKiBAcGFyYW0gY291bnQgQW1vdW50IG9mIHJlc3VsdHMgcmV0dXJuZWQuIERlZmF1bHRzIHRvIDIwLlxuICAqL1xuICBwdWJsaWMgZ2V0Q2F0ZWdvcmllcyhjb3VudHJ5Q29kZT86IHN0cmluZywgY291bnQ/OiBzdHJpbmcpIHtcbiAgICB2YXIgcXVlcnkgPSBcIlwiO1xuICAgIGlmIChjb3VudHJ5Q29kZSAhPSBudWxsICYmIGNvdW50cnlDb2RlICE9IFwiXCIpIHtcbiAgICAgIHF1ZXJ5ICs9IFwiP2NvdW50cnk9XCIgKyBjb3VudHJ5Q29kZTtcbiAgICB9XG4gICAgaWYgKGNvdW50ICE9IG51bGwgJiYgY291bnQgIT0gXCJcIikge1xuICAgICAgcXVlcnkgKz0gKHF1ZXJ5Lmxlbmd0aCA9PSAwKSA/IFwiP1wiIDogXCImXCI7XG4gICAgICBxdWVyeSArPSBcImxpbWl0PVwiICsgY291bnQ7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmFwaUdldCgnL2Jyb3dzZS9jYXRlZ29yaWVzJyArIHF1ZXJ5LCBudWxsLCB0aGlzLmdldEhlYWRlcnMoKSk7XG4gIH1cblxuICAvKiogQGRlc2NyaXB0aW9uIEdldCBhIGxpc3Qgb2YgU3BvdGlmeSBwbGF5bGlzdHMgdGFnZ2VkIHdpdGggYSBwYXJ0aWN1bGFyIGNhdGVnb3J5LlxuICAqIEBwYXJhbSBjYXRlZ29yeUlkIFRoZSBTcG90aWZ5IGNhdGVnb3J5IElEIGZvciB0aGUgY2F0ZWdvcnkuXG4gICogQHBhcmFtIGNvdW50cnlDb2RlIENvdW50cnkgY29kZSBpbiAyIGNoYXIgRm9ybWF0LiBJZiBub3Qgc2V0IHNlYXJjaGVzIGZyb20gYWxsLlxuICAqIEBwYXJhbSBjb3VudCBBbW91bnQgb2YgcmVzdWx0cyByZXR1cm5lZC4gRGVmYXVsdHMgdG8gMjAuXG4gICovXG4gIHB1YmxpYyBnZXRDYXRlZ29yeXNQbGF5bGlzdHMoY2F0ZWdvcnlJZDogc3RyaW5nLCBjb3VudHJ5Q29kZT86IHN0cmluZywgY291bnQ/OiBzdHJpbmcpIHtcbiAgICB2YXIgcXVlcnkgPSBcIlwiO1xuICAgIGlmIChjb3VudHJ5Q29kZSAhPSBudWxsICYmIGNvdW50cnlDb2RlICE9IFwiXCIpIHtcbiAgICAgIHF1ZXJ5ICs9IFwiP2NvdW50cnk9XCIgKyBjb3VudHJ5Q29kZTtcbiAgICB9XG4gICAgaWYgKGNvdW50ICE9IG51bGwgJiYgY291bnQgIT0gXCJcIikge1xuICAgICAgcXVlcnkgKz0gKHF1ZXJ5Lmxlbmd0aCA9PSAwKSA/IFwiP1wiIDogXCImXCI7XG4gICAgICBxdWVyeSArPSBcImxpbWl0PVwiICsgY291bnQ7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmFwaUdldCgnL2Jyb3dzZS9jYXRlZ29yaWVzLycrY2F0ZWdvcnlJZCsnL3BsYXlsaXN0cycgKyBxdWVyeSwgbnVsbCwgdGhpcy5nZXRIZWFkZXJzKCkpO1xuICB9XG5cbiAgLyoqIEBkZXNjcmlwdGlvbiBDcmVhdGVzIGEgcGxheWxpc3QgXG4gICogQHBhcmFtIHVzZXJJZCBVc2VycyBzcG90aWZ5IElELlxuICAqIEBwYXJhbSBuYW1lIEEgbmFtZSBmb3IgdGhlIHBsYXlsaXN0IC5cbiAgKiBAcGFyYW0gZGVzY3JpcHRpb24gQSBkZXNjcmlwdGlvbiBmb3IgdGhlIHBsYXlsaXN0LlxuICAqIEBwYXJhbSBpc1B1YmxpYyBEZWZpbmVzIGlmIGEgcGxheWxpc3QgaXMgcHVibGljIG9yIHByaXZhdGVcbiAgKi9cbiAgcHVibGljIGNyZWF0ZVBsYXlMaXN0KHVzZXJJZDogbnVtYmVyLCBuYW1lOiBzdHJpbmcsIGRlc2NyaXB0aW9uOiBzdHJpbmcsIGlzUHVibGljOiBib29sZWFuKSB7XG4gICAgdmFyIGJvZHkgPSB7XG4gICAgICBcIm5hbWVcIjogbmFtZSxcbiAgICAgIFwiZGVzY3JpcHRpb25cIjogZGVzY3JpcHRpb24sXG4gICAgICBcInB1YmxpY1wiOiBpc1B1YmxpY1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5hcGlQb3N0KCcvbWUvcGxheWxpc3RzP3VzZXJfaWQ9JyArIHVzZXJJZCwgYm9keSwgdGhpcy5nZXRIZWFkZXJzKCkpXG4gIH1cblxuICAvKiogQGRlc2NyaXB0aW9uIEFkZHMgdHJhY2tzIHRvIHBsYXlsaXN0XG4gICogQHBhcmFtIHBsYXlsaXN0SWQgUGxheWxpc3QgSUQuXG4gICogQHBhcmFtIHRyYWNrVXJpcyBBcnJheSBvZiBzcG90aWZ5IHRyYWNrIHVyaXMuIE1heCAxMDAgdHJhY2tzIGNhbiBiZSBhZGRlZCBhdCBhIHRpbWUuXG4gICovXG4gIHB1YmxpYyBhZGRUcmFja3NUb1BsYXlsaXN0KHBsYXlMaXN0SWQ6IHN0cmluZywgdHJhY2tVcmlzOiBzdHJpbmdbXSkge1xuICAgIHZhciBib2R5ID0ge1xuICAgICAgXCJ1cmlzXCI6IHRyYWNrVXJpcyxcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuYXBpUG9zdCgnL3BsYXlsaXN0cy8nICsgcGxheUxpc3RJZCArICcvdHJhY2tzJywgYm9keSwgdGhpcy5nZXRIZWFkZXJzKCkpO1xuICB9XG5cbiAgLyoqIEBkZXNjcmlwdGlvbiBSZXR1cm5zIFNwb3RpZnkgQ2F0YWxvZyBpbmZvcm1hdGlvbiBhYm91dCBhcnRpc3RzLCBhbGJ1bXMsIHRyYWNrcyBvciBwbGF5bGlzdHMgdGhhdCBtYXRjaCBhIGtleXdvcmQgc3RyaW5nLlxuICAqIEBwYXJhbSBxdWVyeSBTZWFyY2ggd29yZC5cbiAgKiBAcGFyYW0gdHlwZSBBIGNvbW1hLXNlcGFyYXRlZCBsaXN0IG9mIGl0ZW0gdHlwZXMgdG8gc2VhcmNoIGFjcm9zcy4gVmFsaWQgdHlwZXMgYXJlIGFsYnVtLCBhcnRpc3QsIHBsYXlsaXN0LCBhbmQgdHJhY2suXG4gICogQHBhcmFtIGNvdW50IFRoZSBjb3VudCBpcyBhcHBsaWVkIHdpdGhpbiBlYWNoIHR5cGUsIG5vdCBvbiB0aGUgdG90YWwgcmVzcG9uc2UuIFNvIGNvdW50IDMgd2l0aCB0eXBlIGFsYnVtLHRyYWNrIHJldHVybnMgMyBhbGJ1bXMgYW5kIDMgdHJhY2tzLiBNYXggNTAuXG4gICovXG4gIHB1YmxpYyBzZWFyY2gocXVlcnk6IHN0cmluZywgdHlwZXM6IHN0cmluZywgY291bnQ6IHN0cmluZykge1xuICAgIGNvbnN0IHEgPSBlbmNvZGVVUklDb21wb25lbnQocXVlcnkpO1xuICAgIGNvbnN0IHQgPSBlbmNvZGVVUklDb21wb25lbnQodHlwZXMpO1xuICAgIHJldHVybiB0aGlzLmFwaUdldCgnL3NlYXJjaD9xPScgKyBxICsgJyZ0eXBlPScgKyB0ICsgJyZsaW1pdD0nICsgY291bnQsIG51bGwsIHRoaXMuZ2V0SGVhZGVycygpKTtcbiAgfVxuXG5cbiAgcHJpdmF0ZSBhcGlHZXQoZW5kcG9pbnQ6IHN0cmluZywgcGFyYW1zLCBoZWFkZXJzKSB7XG4gICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQodGhpcy5iYXNlVXJsICsgZW5kcG9pbnQsIHtcbiAgICAgIHBhcmFtczogcGFyYW1zLFxuICAgICAgaGVhZGVyczogaGVhZGVycyxcbiAgICAgIHdpdGhDcmVkZW50aWFsczogZmFsc2VcbiAgICB9KS50b1Byb21pc2UoKVxuICB9XG5cbiAgcHJpdmF0ZSBhcGlQb3N0KGVuZHBvaW50OiBzdHJpbmcsIGRhdGEsIGhlYWRlcnMpIHtcbiAgICByZXR1cm4gdGhpcy5odHRwLnBvc3QodGhpcy5iYXNlVXJsICsgZW5kcG9pbnQsIGRhdGEsIHtcbiAgICAgIGhlYWRlcnM6IGhlYWRlcnMsXG4gICAgfSlcbiAgICAgIC50b1Byb21pc2UoKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0SGVhZGVycygpIHtcbiAgICByZXR1cm4ge1xuICAgICAgJ0F1dGhvcml6YXRpb24nOiAnQmVhcmVyICcgKyB0aGlzLnRva2VuLFxuICAgICAgJ0FjY2VwdCc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICdDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbidcbiAgICB9XG4gIH1cbn1cbiJdfQ==