├── .gitignore ├── .travis.yml ├── jest.config.js ├── package.json ├── LICENSE ├── lib ├── ApiRequest.js └── LastFm.js ├── README.md ├── test └── ApiRequest.js ├── .eslintrc.json └── index.d.ts /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8.10.0" 4 | 5 | after_success: 6 | - jest --coverage --coverageReporters=text-lcov | coveralls 7 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | verbose: true, 3 | testMatch: [ 4 | "**/test/**/*.[jt]s?(x)", 5 | "**/?(*.)+(spec|test).[jt]s?(x)" 6 | ] 7 | }; 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lastfm-node-client", 3 | "version": "2.2.0", 4 | "description": "JavaScript library for interfacing with the Last.fm API", 5 | "files": [ 6 | "lib" 7 | ], 8 | "main": "lib/LastFm.js", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/rattletone/lastfm-node-client.git" 12 | }, 13 | "keywords": [ 14 | "last.fm", 15 | "api", 16 | "node", 17 | "javascript", 18 | "library" 19 | ], 20 | "author": "Samuel Taylor ", 21 | "license": "MIT", 22 | "scripts": { 23 | "lint": "eslint", 24 | "test": "jest" 25 | }, 26 | "devDependencies": { 27 | "coveralls": "^3.0.9", 28 | "eslint": "^6.8.0", 29 | "eslint-plugin-jest": "^23.8.2", 30 | "eslint-plugin-node": "^11.0.0", 31 | "jest": "^25.1.0", 32 | "nock": "^11.3.4" 33 | }, 34 | "engines": { 35 | "node": ">=8.10.0" 36 | }, 37 | "types": "index.d.ts" 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Samuel Taylor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE 10 | -------------------------------------------------------------------------------- /lib/ApiRequest.js: -------------------------------------------------------------------------------- 1 | const crypto = require("crypto"); 2 | const https = require("https"); 3 | const querystring = require("querystring"); 4 | 5 | class ApiRequest { 6 | /** 7 | * Create an ApiRequest instance 8 | */ 9 | 10 | constructor() { 11 | this.params = new Map().set("format", "json"); 12 | } 13 | 14 | /** 15 | * Set elements in ApiRequest.params 16 | * @param {Object} params - Object whose entries to set in ApiRequest.params 17 | */ 18 | 19 | set(params) { 20 | Object 21 | .entries(params) 22 | .forEach(([key, value]) => this.params.set(key, value)); 23 | 24 | return this; 25 | } 26 | 27 | /** 28 | * Sign an API request 29 | * @param {string} secret - API secret of an API account 30 | * @returns {ApiRequest} 31 | */ 32 | 33 | sign(secret) { 34 | const paramsObj = {}; 35 | 36 | this.params.forEach((value, key) => paramsObj[key] = value); 37 | 38 | // We must stringify then parse the params object so that the request signature is made from an identical set of paramaters that will be sent in the url 39 | 40 | const paramsObjParsed = querystring.parse(querystring.stringify(paramsObj)); 41 | const paramsStr = Array.from(Object.entries(paramsObjParsed)) 42 | .filter(([key]) => key !== "format" && key !== "callback") 43 | .sort(([a], [b]) => { 44 | for (let i = 0; i < a.length || i < b.length; i++) { 45 | const charCodeA = a.charCodeAt(i) || 0; 46 | const charCodeB = b.charCodeAt(i) || 0; 47 | 48 | if (charCodeA < charCodeB) { 49 | return -1; 50 | } 51 | 52 | if (charCodeA > charCodeB) { 53 | return 1; 54 | } 55 | } 56 | 57 | return 0; 58 | }) 59 | .map(param => param.join("")) 60 | .join(""); 61 | 62 | this.params.set( 63 | "api_sig", 64 | crypto 65 | .createHash("md5") 66 | .update(paramsStr + secret) 67 | .digest("hex") 68 | ); 69 | 70 | return this; 71 | } 72 | 73 | /** 74 | * Send an API request 75 | * @param {string} [method] - HTTP request method of API request 76 | * @param {Function} [callback] - Callback of API request 77 | */ 78 | 79 | send(method, callback) { 80 | callback = callback === undefined ? typeof method === "function" ? method : undefined : typeof callback === "function" ? callback : undefined; 81 | method = typeof method === "string" ? method : undefined; 82 | 83 | if (this.params.has("callback")) { 84 | this.params.delete("callback"); 85 | } 86 | 87 | const paramsObj = {}; 88 | 89 | this.params.forEach((value, key) => paramsObj[key] = value); 90 | 91 | const paramsStr = querystring.stringify(paramsObj); 92 | const options = { 93 | hostname: "ws.audioscrobbler.com", 94 | path: "/2.0" 95 | }; 96 | 97 | if (method === "POST") { 98 | options.method = "POST"; 99 | options.headers = { 100 | "Content-Length": Buffer.byteLength(paramsStr), 101 | "Content-Type": "application/x-www-form-urlencoded" 102 | }; 103 | } 104 | else { 105 | options.path += `?${paramsStr}`; 106 | } 107 | 108 | const apiRequest = new Promise((resolve, reject) => { 109 | const httpRequest = https.request(options, httpResponse => { 110 | let data = ""; 111 | 112 | httpResponse.setEncoding("utf8"); 113 | httpResponse.on("data", chunk => data += chunk); 114 | httpResponse.on("end", () => resolve(data)); 115 | httpResponse.on("error", err => reject(err)); 116 | }); 117 | 118 | httpRequest.on("error", err => reject(err)); 119 | 120 | if (method === "POST") { 121 | httpRequest.write(paramsStr); 122 | } 123 | 124 | httpRequest.end(); 125 | }).then(apiResponse => { 126 | let data; 127 | 128 | try { 129 | data = JSON.parse(apiResponse); 130 | } 131 | catch (err) { 132 | throw new Error("Unable to parse API response to JSON"); 133 | } 134 | 135 | if (data.error) { 136 | throw new Error(data.message); 137 | } 138 | 139 | return data; 140 | }); 141 | 142 | if (callback) { 143 | apiRequest.then(data => callback(null, data), err => callback(err, null)); 144 | 145 | return undefined; 146 | } 147 | 148 | return apiRequest; 149 | } 150 | } 151 | 152 | module.exports = ApiRequest; 153 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Last.Fm Node Client 2 | 3 | [![npm](https://img.shields.io/npm/v/lastfm-node-client.svg)](https://www.npmjs.com/package/lastfm-node-client) 4 | [![Build Status](https://travis-ci.org/rattletone/lastfm-node-client.svg?branch=master)](https://travis-ci.org/rattletone/lastfm-node-client) 5 | [![Coverage Status](https://coveralls.io/repos/github/rattletone/lastfm-node-client/badge.svg?branch=master)](https://coveralls.io/github/rattletone/lastfm-node-client?branch=master) 6 | 7 | This is a Node.js JavaScript library for interfacing with the Last.fm API. 8 | 9 | * **Consistent**: Providing you a uniform set of abstractions that allows you to use the interface predictably and reliably. 10 | * **Versatile**: Adapting it's communication with the API, complying with it's specifications without you needing to adapt your code. 11 | * **Low level**: Delivering you the response as it comes directly from the API, using it's native `format` parameter, to deliver a consistent JSON response. 12 | 13 | See the [Last.Fm API web page](https://www.last.fm/api) for information about the Last.Fm API, including details on how to register an account and get your API key, shared secret, and session key. 14 | 15 | ## Installation 16 | 17 | ```sh 18 | $ npm install lastfm-node-client 19 | ``` 20 | 21 | Node.js **8.10.0** or later is required. 22 | 23 | ## Usage 24 | 25 | First, you must instantiate the LastFm Class with arguments containing the details of your API account. `apiKey` is required, however since many endpoints of the API do not require authentication, `secret` and `sessionKey` are optional. 26 | 27 | ```js 28 | const LastFm = require("lastfm-node-client"); 29 | 30 | const lastFm = new LastFm("API_KEY", "SECRET", "SESSION_KEY"); 31 | ``` 32 | 33 | ### Making Requests 34 | 35 | The Last.fm API is structured into packages and methods, accessed as `Package.method`. The LastFm Class contains directly corresponding methods for each package method, written as `lastFm.packageMethod()`. For example, endpoint `User.getRecentTracks` is accessed as `lastFm.userGetRecentTracks()`. 36 | 37 | Parameters can be passed to the API through the `params` argument as an object that will be sent directly with the request, either as a query for a GET request, or a body for a POST request. The property names will not be transformed or abstracted, and so they must match the endpoint parameters exactly. 38 | 39 | ```js 40 | lastFm.userGetRecentTracks({ 41 | user: "USER" 42 | }); 43 | ``` 44 | 45 | #### Notes 46 | 47 | * `lastFm.authGetToken()` and `lastFm.tagGetTopTags()` do not accept a `params` argument, as endpoints `Auth.getToken` and `Tag.getTopTags` do not require additional parameters. 48 | 49 | * `lastFm.userGetInfo()` params.user and params argument are optional and will default to the authenticated user in accordance with endpoint `User.getInfo`. 50 | 51 | ### Capturing Responses and Handling Errors 52 | 53 | Every method returns a promise of the pending request by default. To access the response, you can chain `.then()` to the method, or use `await`. Errors thrown while making a request or [errors returned by the API](https://www.last.fm/api/errorcodes) will reject the promise. 54 | 55 | Chaining `.then()`: 56 | 57 | ```js 58 | lastFm.userGetRecentTracks({ 59 | user: "USER" 60 | }) 61 | .then(data => { 62 | console.log(data); 63 | }; 64 | ``` 65 | 66 | Using `await`: 67 | 68 | ```js 69 | const data = await lastFm.userGetRecentTracks({ 70 | user: "USER" 71 | }); 72 | 73 | console.log(data); 74 | ``` 75 | 76 | An optional callback can be passed as the last argument. It is invoked with conventional `(err, data)` arguments; `err` being any errors thrown while making a request or [errors returned by the API](https://www.last.fm/api/errorcodes), `data` containing the JSON response of the API upon success. 77 | 78 | ```js 79 | lastFm.userGetRecentTracks({ 80 | user: "USER" 81 | }, 82 | (err, data)) => { 83 | console.log(data); 84 | }); 85 | ``` 86 | 87 | When callback is passed, methods do not return a `promise`, instead return the LastFm instance the method was called on. This allows you to chain requests. 88 | 89 | ## Utility Methods 90 | 91 | These methods do not correspond to an exact API endpoint, but are abstractions of the already provided methods to provide easier usage. 92 | 93 | ### `lastFm.trackScrobbleMany` 94 | 95 | This method takes an array of objects that match the `params` parameter accepted by `lastFm.trackScrobble`. It allows for multiple tracks to be submitted to the API in one request. 96 | 97 | ```js 98 | lastFm.trackScrobbleMany([ 99 | { 100 | artist: "ARTIST", 101 | album: "ALBUM", 102 | track: "TRACK", 103 | timestamp: "TIMESTAMP" 104 | }, 105 | { 106 | artist: "ARTIST", 107 | album: "ALBUM", 108 | track: "TRACK", 109 | timestamp: "TIMESTAMP" 110 | } 111 | ]); 112 | ``` 113 | -------------------------------------------------------------------------------- /test/ApiRequest.js: -------------------------------------------------------------------------------- 1 | const crypto = require("crypto"); 2 | const nock = require("nock"); 3 | const ApiRequest = require("../lib/ApiRequest"); 4 | 5 | describe("apiRequest", () => { 6 | describe("constructor()", () => { 7 | it("sets self `params` property to a `Map`", () => { 8 | const apiRequest = new ApiRequest(); 9 | 10 | expect(apiRequest.params).toBeInstanceOf(Map); 11 | }); 12 | 13 | it("sets `apiRequest.params` \"format\" key to \"json\"", () => { 14 | const apiRequest = new ApiRequest(); 15 | 16 | expect(apiRequest.params.get("format")).toBe("json"); 17 | }); 18 | }); 19 | 20 | describe("set()", () => { 21 | it("sets `apiRequest.params` keys and values of object argument", () => { 22 | const apiRequest = new ApiRequest(); 23 | const params = { 24 | foo: "bar", 25 | baz: "qux" 26 | }; 27 | 28 | apiRequest.set(params); 29 | 30 | expect(Array.from(apiRequest.params)).toStrictEqual(expect.arrayContaining(Object.entries(params))); 31 | }); 32 | }); 33 | 34 | describe("sign()", () => { 35 | it("sets `apiRequest.params` \"api_sig\" key to an md5 hash of all `apiRequest.params` keys and values, excluding format and callback, ordered by `String.prototype.charCodeAt()` return value, and appended with a shared secret", () => { 36 | const apiRequest = new ApiRequest(); 37 | const params = { 38 | aa: "aa", 39 | a: "a", 40 | aaa: "aaa" 41 | }; 42 | 43 | apiRequest.set(params); 44 | 45 | const paramsStr = Array.from(apiRequest.params) 46 | .filter(([key]) => key !== "format" && key !== "callback") 47 | .sort(([a], [b]) => { 48 | for (let i = 0; i < a.length || i < b.length; i++) { 49 | const charCodeA = a.charCodeAt(i) || 0; 50 | const charCodeB = b.charCodeAt(i) || 0; 51 | 52 | if (charCodeA < charCodeB) { 53 | return -1; 54 | } 55 | 56 | if (charCodeA > charCodeB) { 57 | return 1; 58 | } 59 | } 60 | 61 | return 0; 62 | }) 63 | .map(param => param.join("")) 64 | .join(""); 65 | 66 | const secret = "foo"; 67 | const apiSig = crypto 68 | .createHash("md5") 69 | .update(paramsStr + secret) 70 | .digest("hex"); 71 | 72 | apiRequest.sign(secret); 73 | 74 | expect(apiRequest.params.get("api_sig")).toBe(apiSig); 75 | }); 76 | }); 77 | 78 | describe("send()", () => { 79 | it("makes a GET request if \"POST\" is not passed as the first argument", () => { 80 | const apiRequest = new ApiRequest(); 81 | const scope = nock("https://ws.audioscrobbler.com") 82 | .get("/2.0") 83 | .query({ format: "json" }) 84 | .reply(200, {}); 85 | 86 | return apiRequest 87 | .send() 88 | .then(() => expect(scope.isDone()).toBe(true)); 89 | }); 90 | 91 | it("makes a POST request if \"POST\" is passed as the first argument", () => { 92 | const apiRequest = new ApiRequest(); 93 | const scope = nock("https://ws.audioscrobbler.com") 94 | .post("/2.0", { format: "json" }) 95 | .reply(200, {}); 96 | 97 | return apiRequest 98 | .send("POST") 99 | .then(() => expect(scope.isDone()).toBe(true)); 100 | }); 101 | 102 | it("returns promise if function is not passed as the first argument and no second argument is passed, and resolves with the API response", () => { 103 | const apiRequest = new ApiRequest(); 104 | const reply = {}; 105 | 106 | nock("https://ws.audioscrobbler.com") 107 | .get("/2.0") 108 | .query({ format: "json" }) 109 | .reply(200, reply); 110 | 111 | const apiResponse = apiRequest.send("GET"); 112 | 113 | expect(apiResponse).toBeInstanceOf(Promise); 114 | 115 | return expect(apiResponse).resolves.toStrictEqual(reply); 116 | }); 117 | 118 | it("returns promise if function is not passed as the second argument, and resolves with the API response", () => { 119 | const apiRequest = new ApiRequest(); 120 | const reply = {}; 121 | 122 | nock("https://ws.audioscrobbler.com") 123 | .get("/2.0") 124 | .query({ format: "json" }) 125 | .reply(200, reply); 126 | 127 | const apiResponse = apiRequest.send("GET", "GOT"); 128 | 129 | expect(apiResponse).toBeInstanceOf(Promise); 130 | 131 | return expect(apiResponse).resolves.toStrictEqual(reply); 132 | }); 133 | 134 | it("invokes callback if function is passed as the first argument and no second argument is passed, passing `null` and the response as the `err` and `data` paramaters respectively", () => { 135 | const apiRequest = new ApiRequest(); 136 | const reply = {}; 137 | 138 | nock("https://ws.audioscrobbler.com") 139 | .get("/2.0") 140 | .query({ format: "json" }) 141 | .reply(200, reply); 142 | 143 | return new Promise(done => { 144 | apiRequest.send((err, data) => { 145 | expect(err).toBeNull(); 146 | expect(data).toStrictEqual(reply); 147 | done(); 148 | }); 149 | }); 150 | }); 151 | 152 | it("invokes callback if function is passed as the second argument, passing `null` and the response as the `err` and `data` paramaters respectively", () => { 153 | const apiRequest = new ApiRequest(); 154 | const reply = {}; 155 | 156 | nock("https://ws.audioscrobbler.com") 157 | .get("/2.0") 158 | .query({ format: "json" }) 159 | .reply(200, reply); 160 | 161 | return new Promise(done => { 162 | apiRequest.send("GET", (err, data) => { 163 | expect(err).toBeNull(); 164 | expect(data).toStrictEqual(reply); 165 | done(); 166 | }); 167 | }); 168 | }); 169 | 170 | it("throws an error if the reply is an error", () => { 171 | const apiRequest = new ApiRequest(); 172 | const reply = new Error(); 173 | 174 | nock("https://ws.audioscrobbler.com") 175 | .get("/2.0") 176 | .query({ format: "json" }) 177 | .replyWithError(reply); 178 | 179 | return expect(apiRequest.send()).rejects.toStrictEqual(reply); 180 | }); 181 | 182 | it("throws an error if the reply is not JSON", () => { 183 | const apiRequest = new ApiRequest(); 184 | 185 | nock("https://ws.audioscrobbler.com") 186 | .get("/2.0") 187 | .query({ format: "json" }) 188 | .reply(200); 189 | 190 | return expect(apiRequest.send()).rejects.toBeInstanceOf(Error); 191 | }); 192 | 193 | it("throws an error if the reply contains error property", () => { 194 | const apiRequest = new ApiRequest(); 195 | 196 | nock("https://ws.audioscrobbler.com") 197 | .get("/2.0") 198 | .query({ format: "json" }) 199 | .reply(200, { error: "You've met with a terrible fate, haven't you?" }); 200 | 201 | return expect(apiRequest.send()).rejects.toBeInstanceOf(Error); 202 | }); 203 | 204 | it("handles an error with a callback", () => { 205 | const apiRequest = new ApiRequest(); 206 | const reply = new Error(); 207 | 208 | nock("https://ws.audioscrobbler.com") 209 | .get("/2.0") 210 | .query({ format: "json" }) 211 | .replyWithError(reply); 212 | 213 | return new Promise(done => { 214 | apiRequest.send((err, data) => { 215 | expect(err).toStrictEqual(reply); 216 | expect(data).toBeNull(); 217 | done(); 218 | }); 219 | }); 220 | }); 221 | }); 222 | }); 223 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "node", 4 | "jest" 5 | ], 6 | "env": { 7 | "es6": true, 8 | "node": true, 9 | "jest": true 10 | }, 11 | "parserOptions": { 12 | "ecmaVersion": 11 13 | }, 14 | "rules": { 15 | "accessor-pairs": ["error", { "enforceForClassMembers": true }], 16 | "array-bracket-newline": "error", 17 | "array-bracket-spacing": "error", 18 | "array-callback-return": "error", 19 | "array-element-newline": ["error", { "multiline": true }], 20 | "arrow-body-style": "error", 21 | "arrow-parens": ["error", "as-needed"], 22 | "arrow-spacing": "error", 23 | "block-spacing": "error", 24 | "brace-style": ["error", "stroustrup"], 25 | "callback-return": "error", 26 | "camelcase": ["error", { "allow": ["api_"]}], 27 | "capitalized-comments": "error", 28 | "class-methods-use-this": "error", 29 | "comma-dangle": "error", 30 | "comma-spacing": "error", 31 | "comma-style": "error", 32 | "computed-property-spacing": "error", 33 | "consistent-return": "error", 34 | "consistent-this": "error", 35 | "constructor-super": "error", 36 | "curly": "error", 37 | "default-param-last": "error", 38 | "dot-location": ["error", "property"], 39 | "dot-notation": "error", 40 | "eol-last": "error", 41 | "eqeqeq": "error", 42 | "for-direction": "error", 43 | "func-call-spacing": "error", 44 | "func-names": ["error", "as-needed"], 45 | "func-style": "error", 46 | "function-call-argument-newline": ["error", "consistent"], 47 | "function-paren-newline": ["error", "consistent"], 48 | "generator-star-spacing": "error", 49 | "getter-return": "error", 50 | "global-require": "error", 51 | "grouped-accessor-pairs": ["error", "getBeforeSet"], 52 | "handle-callback-err": "error", 53 | "implicit-arrow-linebreak": "error", 54 | "indent": ["error", "tab", { "SwitchCase": 1 }], 55 | "key-spacing": "error", 56 | "keyword-spacing": "error", 57 | "line-comment-position": "error", 58 | "lines-around-comment": [ 59 | "error", 60 | { 61 | "afterBlockComment": true, 62 | "beforeLineComment": true, 63 | "afterLineComment": true, 64 | "allowBlockStart": true, 65 | "allowBlockEnd": true, 66 | "allowObjectStart": true, 67 | "allowObjectEnd": true, 68 | "allowArrayStart": true, 69 | "allowArrayEnd": true, 70 | "allowClassStart": true, 71 | "allowClassEnd": true 72 | } 73 | ], 74 | "lines-between-class-members": "error", 75 | "multiline-comment-style": "error", 76 | "multiline-ternary": ["error", "always-multiline"], 77 | "new-cap": "error", 78 | "new-parens": "error", 79 | "newline-per-chained-call": "error", 80 | "no-array-constructor": "error", 81 | "no-async-promise-executor": "error", 82 | "no-buffer-constructor": "error", 83 | "no-caller": "error", 84 | "no-case-declarations": "error", 85 | "no-class-assign": "error", 86 | "no-compare-neg-zero": "error", 87 | "no-const-assign": "error", 88 | "no-constant-condition": "error", 89 | "no-constructor-return": "error", 90 | "no-control-regex": "error", 91 | "no-debugger": "error", 92 | "no-delete-var": "error", 93 | "no-dupe-args": "error", 94 | "no-dupe-class-members": "error", 95 | "no-dupe-keys": "error", 96 | "no-dupe-else-if": "error", 97 | "no-duplicate-case": "error", 98 | "no-duplicate-imports": "error", 99 | "no-else-return": ["error", { "allowElseIf": false }], 100 | "no-empty": "error", 101 | "no-empty-character-class": "error", 102 | "no-empty-function": "error", 103 | "no-eval": "error", 104 | "no-ex-assign": "error", 105 | "no-extend-native": "error", 106 | "no-extra-bind": "error", 107 | "no-extra-boolean-cast": "error", 108 | "no-extra-label": "error", 109 | "no-extra-parens": "error", 110 | "no-extra-semi": "error", 111 | "no-floating-decimal": "error", 112 | "no-global-assign": "error", 113 | "no-implicit-coercion": "error", 114 | "no-implied-eval": "error", 115 | "no-inline-comments": "error", 116 | "no-invalid-regexp": "error", 117 | "no-invalid-this": "error", 118 | "no-irregular-whitespace": "error", 119 | "no-iterator": "error", 120 | "no-label-var": "error", 121 | "no-lone-blocks": "error", 122 | "no-lonely-if": "error", 123 | "no-misleading-character-class": "error", 124 | "no-mixed-requires": "error", 125 | "no-mixed-spaces-and-tabs": "error", 126 | "no-multi-assign": "error", 127 | "no-multi-spaces": "error", 128 | "no-multi-str": "error", 129 | "no-multiple-empty-lines": "error", 130 | "no-negated-condition": "error", 131 | "no-new": "error", 132 | "no-new-func": "error", 133 | "no-new-object": "error", 134 | "no-new-require": "error", 135 | "no-new-symbol": "error", 136 | "no-new-wrappers": "error", 137 | "no-obj-calls": "error", 138 | "no-octal": "error", 139 | "no-octal-escape": "error", 140 | "no-path-concat": "error", 141 | "no-proto": "error", 142 | "no-prototype-builtins": "error", 143 | "no-regex-spaces": "error", 144 | "no-return-await": "error", 145 | "no-self-assign": "error", 146 | "no-self-compare": "error", 147 | "no-setter-return": "error", 148 | "no-shadow": "error", 149 | "no-shadow-restricted-names": "error", 150 | "no-sparse-arrays": "error", 151 | "no-tabs": ["error", { "allowIndentationTabs": true }], 152 | "no-this-before-super": "error", 153 | "no-throw-literal": "error", 154 | "no-trailing-spaces": "error", 155 | "no-unexpected-multiline": "error", 156 | "no-unmodified-loop-condition": "error", 157 | "no-unneeded-ternary": ["error", { "defaultAssignment": false }], 158 | "no-undef": "error", 159 | "no-undef-init": "error", 160 | "no-unreachable": "error", 161 | "no-unused-expressions": "error", 162 | "no-unused-labels": "error", 163 | "no-unused-vars": "error", 164 | "no-unsafe-finally": "error", 165 | "no-unsafe-negation": "error", 166 | "no-use-before-define": "error", 167 | "no-useless-call": "error", 168 | "no-useless-catch": "error", 169 | "no-useless-computed-key": "error", 170 | "no-useless-concat": "error", 171 | "no-useless-constructor": "error", 172 | "no-useless-escape": "error", 173 | "no-useless-rename": "error", 174 | "no-useless-return": "error", 175 | "no-sync": "error", 176 | "no-var": "error", 177 | "no-whitespace-before-property": "error", 178 | "no-with": "error", 179 | "object-curly-newline": [ 180 | "error", 181 | { 182 | "multiline": true, 183 | "minProperties": 2 184 | } 185 | ], 186 | "object-curly-spacing": [ 187 | "error", 188 | "always", 189 | { 190 | "arraysInObjects": false, 191 | "objectsInObjects": false 192 | } 193 | ], 194 | "object-property-newline": "error", 195 | "object-shorthand": "error", 196 | "one-var": ["error", "never"], 197 | "operator-assignment": "error", 198 | "operator-linebreak": ["error", "before"], 199 | "padded-blocks": ["error", "never"], 200 | "padding-line-between-statements": [ 201 | "error", 202 | { 203 | "blankLine": "always", 204 | "prev": "*", 205 | "next": ["break", "continue", "return", "throw"] 206 | }, 207 | { 208 | "blankLine": "always", 209 | "prev": "*", 210 | "next": "cjs-export" 211 | }, 212 | { 213 | "blankLine": "always", 214 | "prev": ["const", "let"], 215 | "next": "*" 216 | }, 217 | { 218 | "blankLine": "always", 219 | "prev": "directive", 220 | "next": "*" 221 | }, 222 | { 223 | "blankLine": "always", 224 | "prev": ["multiline-block-like", "multiline-const", "multiline-expression", "multiline-let"], 225 | "next": "*" 226 | }, 227 | { 228 | "blankLine": "never", 229 | "prev": "directive", 230 | "next": "directive" 231 | }, 232 | { 233 | "blankLine": "never", 234 | "prev": ["singleline-const", "singleline-let"], 235 | "next": ["const", "let"] 236 | } 237 | ], 238 | "prefer-arrow-callback": "error", 239 | "prefer-const": "error", 240 | "prefer-destructuring": "error", 241 | "prefer-exponentiation-operator": "error", 242 | "prefer-named-capture-group": "error", 243 | "prefer-numeric-literals": "error", 244 | "prefer-object-spread": "error", 245 | "prefer-promise-reject-errors": "error", 246 | "prefer-regex-literals": "error", 247 | "prefer-rest-params": "error", 248 | "prefer-spread": "error", 249 | "prefer-template": "error", 250 | "quote-props": ["error", "as-needed"], 251 | "quotes": ["error", "double"], 252 | "radix": "error", 253 | "require-atomic-updates": "error", 254 | "require-await": "error", 255 | "require-unicode-regexp": "error", 256 | "require-yield": "error", 257 | "rest-spread-spacing": "error", 258 | "semi": ["error", "always", { "omitLastInOneLineBlock": false }], 259 | "semi-spacing": "error", 260 | "semi-style": "error", 261 | "space-before-blocks": "error", 262 | "space-before-function-paren": ["error", "never"], 263 | "space-in-parens": "error", 264 | "space-infix-ops": "error", 265 | "space-unary-ops": "error", 266 | "spaced-comment": "error", 267 | "switch-colon-spacing": "error", 268 | "template-curly-spacing": "error", 269 | "template-tag-spacing": "error", 270 | "unicode-bom": "error", 271 | "use-isnan": "error", 272 | "valid-typeof": "error", 273 | "wrap-iife": ["error", "inside"], 274 | "yield-star-spacing": "error", 275 | "yoda": "error", 276 | "node/no-callback-literal": "error", 277 | "node/no-exports-assign": "error", 278 | "node/no-extraneous-require": "error", 279 | "node/no-missing-require": "error", 280 | "node/no-unpublished-bin": "error", 281 | "node/no-unpublished-require": "error", 282 | "node/no-unsupported-features/es-builtins": "error", 283 | "node/no-unsupported-features/es-syntax": "error", 284 | "node/no-unsupported-features/node-builtins": "error", 285 | "node/process-exit-as-throw": "error", 286 | "node/shebang": "error", 287 | "node/no-deprecated-api": "error", 288 | "node/exports-style": "error", 289 | "node/prefer-global/buffer": "error", 290 | "node/prefer-global/console": "error", 291 | "node/prefer-global/process": "error", 292 | "node/prefer-global/text-decoder": "error", 293 | "node/prefer-global/text-encoder": "error", 294 | "node/prefer-global/url-search-params": "error", 295 | "node/prefer-global/url": "error", 296 | "jest/consistent-test-it": "error", 297 | "jest/expect-expect": "error", 298 | "jest/lowercase-name": "error", 299 | "jest/no-alias-methods": "error", 300 | "jest/no-commented-out-tests": "error", 301 | "jest/no-disabled-tests": "error", 302 | "jest/no-duplicate-hooks": "error", 303 | "jest/no-export": "error", 304 | "jest/no-focused-tests": "error", 305 | "jest/no-identical-title": "error", 306 | "jest/no-jasmine-globals": "error", 307 | "jest/no-jest-import": "error", 308 | "jest/no-mocks-import": "error", 309 | "jest/no-standalone-expect": "error", 310 | "jest/no-test-callback": "error", 311 | "jest/no-test-prefixes": "error", 312 | "jest/prefer-hooks-on-top": "error", 313 | "jest/prefer-strict-equal": "error", 314 | "jest/prefer-to-be-null": "error", 315 | "jest/prefer-to-be-undefined": "error", 316 | "jest/prefer-to-contain": "error", 317 | "jest/prefer-to-have-length": "error", 318 | "jest/prefer-todo": "error", 319 | "jest/require-top-level-describe": "error", 320 | "jest/require-to-throw-message": "error", 321 | "jest/valid-describe": "error", 322 | "jest/valid-expect-in-promise": "error", 323 | "jest/valid-expect": "error", 324 | "jest/valid-title": "error" 325 | }, 326 | "overrides": [ 327 | { 328 | "files": [ 329 | "**/test/**/*.[jt]s?(x)", 330 | "**/?(*.)+(spec|test).[jt]s?(x)" 331 | ], 332 | "rules": { 333 | "no-empty-function": "off", 334 | "no-new": "off" 335 | } 336 | } 337 | ], 338 | "ignorePatterns": [ 339 | "index.d.ts" 340 | ] 341 | } 342 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace LastFm { 2 | export type Callback = (err?: Error, data?: any) => void; 3 | 4 | export type NumericBoolean = 0 | 1; 5 | 6 | export type Period = "7day" | "1month" | "3month" | "6month" | "12month" | "overall"; 7 | 8 | export type MbId = { 9 | /** 10 | * MusicBrainz ID of entity to get info of. 11 | */ 12 | mbid: string; 13 | } 14 | 15 | export type WithMbId = Omit & MbId; 16 | 17 | export type AlbumAddTagsParams = { 18 | /** 19 | * Artist whose album to add tags to 20 | */ 21 | artist: string; 22 | /** 23 | * Album to add tags to 24 | */ 25 | album: string; 26 | /** 27 | * Tags to add to album 28 | */ 29 | tags: string | string[]; 30 | }; 31 | 32 | export type AlbumGetInfoParams = { 33 | /** 34 | * Artist whose album to get info of. 35 | */ 36 | artist: string; 37 | /** 38 | * Album to get info of. 39 | */ 40 | album: string; 41 | /** 42 | * Whether to correct misspelt artist name 43 | */ 44 | autocorrect?: NumericBoolean 45 | /** 46 | * Language to return the biography in. Writen as an ISO 639 alpha-2 code. 47 | */ 48 | lang?: string; 49 | /** 50 | * User whose play count to include 51 | */ 52 | username?: string; 53 | }; 54 | 55 | export type AlbumGetTagsParams = { 56 | /** 57 | * Artist whose album to get tags of. 58 | */ 59 | artist: string; 60 | /** 61 | * Album to get tags of. 62 | */ 63 | album: string; 64 | /** 65 | * User whose tags added to the album to get 66 | */ 67 | user: string; 68 | /** 69 | * Whether to correct misspelt artist name 70 | */ 71 | autocorrect?: NumericBoolean 72 | }; 73 | 74 | export type AlbumGetTopTagsParams = { 75 | /** 76 | * Artist whose album to get top tags of. 77 | */ 78 | artist: string; 79 | /** 80 | * Album to get top tags of. 81 | */ 82 | album: string; 83 | /** 84 | * Whether to correct misspelt artist name 85 | */ 86 | autocorrect?: NumericBoolean 87 | }; 88 | 89 | export type AlbumRemoveTagParams = { 90 | /** 91 | * Artist whose album to remove tag from 92 | */ 93 | artist: string; 94 | /** 95 | * Album to remove tag from 96 | */ 97 | album: string; 98 | /** 99 | * Tag to remove from album 100 | */ 101 | tag: string; 102 | }; 103 | 104 | export type AlbumSearchParams = { 105 | /** 106 | * Album to search for 107 | */ 108 | album: string; 109 | /** 110 | * Number of albums to get per page 111 | */ 112 | limit?: number; 113 | /** 114 | * Page number to get 115 | */ 116 | page?: number; 117 | }; 118 | 119 | export type ArtistAddTagsParams = { 120 | /** 121 | * Artist to add tags to 122 | */ 123 | artist: string; 124 | /** 125 | * Tags to add to artist 126 | */ 127 | tags: string | string[]; 128 | }; 129 | 130 | export type ArtistGetCorrectionParams = { 131 | /** 132 | * Artist to get correction of 133 | */ 134 | artist: string; 135 | }; 136 | 137 | export type ArtistGetInfoParams = { 138 | /** 139 | * Artist to get info of. 140 | */ 141 | artist: string; 142 | /** 143 | * Whether to correct misspelt artist name 144 | */ 145 | autocorrect?: NumericBoolean 146 | /** 147 | * Language to return the biography in. Writen as an ISO 639 alpha-2 code. 148 | */ 149 | lang?: string; 150 | /** 151 | * User whose play count to include 152 | */ 153 | username?: string; 154 | }; 155 | 156 | export type ArtistGetSimilarParams = { 157 | /** 158 | * Artist to get similar to. 159 | */ 160 | artist: string; 161 | /** 162 | * Whether to correct misspelt artist name 163 | */ 164 | autocorrect?: NumericBoolean 165 | /** 166 | * Number of artists to get 167 | */ 168 | limit?: number; 169 | }; 170 | 171 | export type ArtistGetTagsParams = { 172 | /** 173 | * Artist to get tags of. 174 | */ 175 | artist: string; 176 | /** 177 | * User whose tags added to the artist to get 178 | */ 179 | user: string; 180 | /** 181 | * Whether to correct misspelt artist name 182 | */ 183 | autocorrect?: NumericBoolean 184 | }; 185 | 186 | export type ArtistGetTopAlbumsParams = { 187 | /** 188 | * Artist to get top albums of. 189 | */ 190 | artist: string; 191 | /** 192 | * Whether to correct misspelt artist name 193 | */ 194 | autocorrect?: NumericBoolean 195 | /** 196 | * Number of albums to get per page 197 | */ 198 | limit?: number; 199 | /** 200 | * Page number to get 201 | */ 202 | page?: number; 203 | }; 204 | 205 | export type ArtistGetTopTagsParams = { 206 | /** 207 | * Artist to get top tags of. 208 | */ 209 | artist: string; 210 | /** 211 | * Whether to correct misspelt artist name 212 | */ 213 | autocorrect?: NumericBoolean 214 | }; 215 | 216 | export type ArtistGetTopTracksParams = { 217 | /** 218 | * Artist to get top tracks of. 219 | */ 220 | artist: string; 221 | /** 222 | * Whether to correct misspelt artist name 223 | */ 224 | autocorrect?: NumericBoolean 225 | /** 226 | * Number of tracks to get per page 227 | */ 228 | limit?: number; 229 | /** 230 | * Page number to get 231 | */ 232 | page?: number; 233 | }; 234 | 235 | export type ArtistRemoveTagParams = { 236 | /** 237 | * Artist to remove tag from 238 | */ 239 | artist: string; 240 | /** 241 | * Tag to remove from artist 242 | */ 243 | tag: string; 244 | }; 245 | 246 | export type ArtistSearchParams = { 247 | /** 248 | * Artist to search for 249 | */ 250 | artist: string; 251 | /** 252 | * Number of artists to get per page 253 | */ 254 | limit?: number; 255 | /** 256 | * Page number to get 257 | */ 258 | page?: number; 259 | }; 260 | 261 | export type AuthGetMobileSessionParams = { 262 | /** 263 | * Username or email of the account to get a session key for 264 | */ 265 | username: string; 266 | /** 267 | * Password of the account to get a session key for 268 | */ 269 | password: string; 270 | }; 271 | 272 | export type AuthGetSessionParams = { 273 | /** 274 | * Token to authenticate request 275 | */ 276 | token: string; 277 | }; 278 | 279 | export type ChartGetTopArtistsParams = { 280 | /** 281 | * Number of artists to get per page 282 | */ 283 | limit?: number; 284 | /** 285 | * Page number to get 286 | */ 287 | page?: number; 288 | }; 289 | 290 | export type ChartGetTopTagsParams = { 291 | /** 292 | * Number of tags to get per page 293 | */ 294 | limit?: number; 295 | /** 296 | * Page number to get 297 | */ 298 | page?: number; 299 | }; 300 | 301 | export type ChartGetTopTracksParams = { 302 | /** 303 | * Number of tracks to get per page 304 | */ 305 | limit?: number; 306 | /** 307 | * Page number to get 308 | */ 309 | page?: number; 310 | }; 311 | 312 | export type GeoGetTopArtistsParams = { 313 | /** 314 | * Country to get top artists of. Written as an ISO 3166 country name. 315 | */ 316 | country: string; 317 | /** 318 | * Number of artists to get per page 319 | */ 320 | limit?: number; 321 | /** 322 | * Page number to get 323 | */ 324 | page?: number; 325 | }; 326 | 327 | export type GeoGetTopTracksParams = { 328 | /** 329 | * Country to get top tracks of. Written as an ISO 3166 country name. 330 | */ 331 | country: string; 332 | /** 333 | * Location within a country to get top tracks of 334 | */ 335 | location?: string; 336 | /** 337 | * Number of tracks to get per page 338 | */ 339 | limit?: number; 340 | /** 341 | * Page number to get 342 | */ 343 | page?: number; 344 | }; 345 | 346 | export type LibraryGetArtistsParams = { 347 | /** 348 | * User whose library to get artists of 349 | */ 350 | user: string; 351 | /** 352 | * Number of artists to get per page 353 | */ 354 | limit?: number; 355 | /** 356 | * Page number to get 357 | */ 358 | page?: number; 359 | }; 360 | 361 | export type TagGetInfoParams = { 362 | /** 363 | * Tag to get info of 364 | */ 365 | tag: string; 366 | /** 367 | * Language to return the wiki in. Writen as an ISO 639 alpha-2 code. 368 | */ 369 | lang?: string; 370 | }; 371 | 372 | export type TagGetSimilarParams = { 373 | /** 374 | * Tag to get similar to 375 | */ 376 | tag: string; 377 | }; 378 | 379 | export type TagGetTopAlbumsParams = { 380 | /** 381 | * Tag to get top albums of 382 | */ 383 | tag: string; 384 | /** 385 | * Number of albums to get per page 386 | */ 387 | limit?: number; 388 | /** 389 | * Page number to get 390 | */ 391 | page?: number; 392 | }; 393 | 394 | export type TagGetTopArtistsParams = { 395 | /** 396 | * Tag to get top artists of 397 | */ 398 | tag: string; 399 | /** 400 | * Number of artists to get per page 401 | */ 402 | limit?: number; 403 | /** 404 | * Page number to get 405 | */ 406 | page?: number; 407 | }; 408 | 409 | export type TagGetTopTracksParams = { 410 | /** 411 | * Tag to get top tracks of 412 | */ 413 | tag: string; 414 | /** 415 | * Number of tracks to get per page 416 | */ 417 | limit?: number; 418 | /** 419 | * Page number to get 420 | */ 421 | page?: number; 422 | }; 423 | 424 | export type TagGetWeeklyChartListParams = { 425 | /** 426 | * Tag to get weekly charts of 427 | */ 428 | tag: string; 429 | }; 430 | 431 | export type TrackAddTagsParams = { 432 | /** 433 | * Artist whose track to add tags to 434 | */ 435 | artist: string; 436 | /** 437 | * Track to add tags to 438 | */ 439 | track: string; 440 | /** 441 | * Tags to add to track 442 | */ 443 | tags: string | string[]; 444 | }; 445 | 446 | export type TrackGetCorrectionParams = { 447 | /** 448 | * Artist and whose track to get correction of 449 | */ 450 | artist: string; 451 | /** 452 | * Track to get correction of 453 | */ 454 | track: string; 455 | }; 456 | 457 | export type TrackGetInfoParams = { 458 | /** 459 | * Artist whose track to get info of. 460 | */ 461 | artist: string; 462 | /** 463 | * Track to get info of. 464 | */ 465 | track: string; 466 | /** 467 | * Whether to correct misspelt artist and track names 468 | */ 469 | autocorrect?: NumericBoolean 470 | /** 471 | * User whose playcount and whether or not they have loved the track to include 472 | */ 473 | username?: string; 474 | }; 475 | 476 | export type TrackGetSimilarParams = { 477 | /** 478 | * Artist whose track to get similar to. 479 | */ 480 | artist: string; 481 | /** 482 | * Track to get similar to. 483 | */ 484 | track: string; 485 | /** 486 | * Whether to correct misspelt artist and track names 487 | */ 488 | autocorrect?: NumericBoolean 489 | /** 490 | * Number of tracks to get 491 | */ 492 | limit?: number; 493 | }; 494 | 495 | export type TrackGetTagsParams = { 496 | /** 497 | * Artist whose track to get tags of. 498 | */ 499 | artist: string; 500 | /** 501 | * Track to get tags of. 502 | */ 503 | track: string; 504 | /** 505 | * User whose tags added to the track to get 506 | */ 507 | user: string; 508 | /** 509 | * Whether to correct misspelt artist and track names 510 | */ 511 | autocorrect?: NumericBoolean 512 | }; 513 | 514 | export type TrackGetTopTagsParams = { 515 | /** 516 | * Artist whose track to get top tags of. 517 | */ 518 | artist: string; 519 | /** 520 | * Track to get top tags of. 521 | */ 522 | track: string; 523 | /** 524 | * Whether to correct misspelt artist and track names 525 | */ 526 | autocorrect?: NumericBoolean 527 | }; 528 | 529 | export type TrackLoveParams = { 530 | /** 531 | * Artist whose track to love 532 | */ 533 | artist: string; 534 | /** 535 | * Track to love 536 | */ 537 | track: string; 538 | }; 539 | 540 | export type TrackRemoveTagParams = { 541 | /** 542 | * Artist whose track to remove tag from 543 | */ 544 | artist: string; 545 | /** 546 | * Track to remove tag from 547 | */ 548 | track: string; 549 | /** 550 | * Tag to remove from track 551 | */ 552 | tag: string; 553 | }; 554 | 555 | export type TrackScrobbleParams = { 556 | /** 557 | * Artist whose track to scrobble 558 | */ 559 | artist: string; 560 | /** 561 | * Track to scobble 562 | */ 563 | track: string; 564 | /** 565 | * Album the track to scrobble is from 566 | */ 567 | album?: string; 568 | /** 569 | * Artist whose album the track to scrobble is from 570 | */ 571 | albumArist?: string; 572 | /** 573 | * Timestamp to scrobble track at 574 | */ 575 | timestamp: number; 576 | /** 577 | * Number of track to scrobble on the album 578 | */ 579 | trackNumber?: number; 580 | /** 581 | * Length of the track to scrobble in seconds 582 | */ 583 | duration?: number; 584 | /** 585 | * Whether the user chose the track to scrobble 586 | */ 587 | chosenByUser?: NumericBoolean 588 | /** 589 | * Stream ID if track to scrobble is from Last.Fm radio 590 | */ 591 | streamId?: string; 592 | }; 593 | 594 | export type TrackSearchParams = { 595 | /** 596 | * Artist whose track to search for 597 | */ 598 | artist?: string; 599 | /** 600 | * Track to search for 601 | */ 602 | track: string; 603 | /** 604 | * Number of tracks to get per page 605 | */ 606 | limit?: number; 607 | /** 608 | * Page number to get 609 | */ 610 | page?: number; 611 | }; 612 | 613 | export type TrackUnloveParams = { 614 | /** 615 | * Artist whose track to unlove 616 | */ 617 | artist: string; 618 | /** 619 | * Track to unlove 620 | */ 621 | track: string; 622 | }; 623 | 624 | export type TrackUpdateNowPlayingParams = { 625 | /** 626 | * Artist whose track to update now playing with 627 | */ 628 | artist: string; 629 | /** 630 | * Track to update now playing with 631 | */ 632 | track: string; 633 | /** 634 | * Album the track to update now playing with is from 635 | */ 636 | album?: string; 637 | /** 638 | * Artist whose album the track to update now playing with is from 639 | */ 640 | albumArist?: string; 641 | /** 642 | * Number of track to update now playing with on the album 643 | */ 644 | trackNumber?: number; 645 | /** 646 | * Length of the track to update now playing with in seconds 647 | */ 648 | duration?: number; 649 | }; 650 | 651 | export type UserGetFriendsParams = { 652 | /** 653 | * User to get friends of 654 | */ 655 | user: string; 656 | /** 657 | * Whether to include recent tracks of friends 658 | */ 659 | recenttracks?: NumericBoolean 660 | /** 661 | * Number of friends to get per page 662 | */ 663 | limit?: number; 664 | /** 665 | * Page number to get 666 | */ 667 | page?: number; 668 | }; 669 | 670 | export type UserGetInfoParams = { 671 | /** 672 | * User to get info of 673 | */ 674 | user?: string; 675 | }; 676 | 677 | export type UserGetLovedTracksParams = { 678 | /** 679 | * User to get loved tracks of 680 | */ 681 | user: string; 682 | /** 683 | * Number of tracks to get per page 684 | */ 685 | limit?: number; 686 | /** 687 | * Page number to get 688 | */ 689 | page?: number; 690 | }; 691 | 692 | export type UserGetPersonalTagsParams = { 693 | /** 694 | * User whose added tag to get items of 695 | */ 696 | user: string; 697 | /** 698 | * Tag to get items of 699 | */ 700 | tag: string; 701 | /** 702 | * TypE of tag to get items of 703 | */ 704 | taggingtype: "track" | "artist" | "album"; 705 | /** 706 | * Number of items to get per page 707 | */ 708 | limit?: number; 709 | /** 710 | * Page number to get 711 | */ 712 | page?: number; 713 | }; 714 | 715 | export type UserGetRecentTracksParams = { 716 | /** 717 | * User whose recent tracks to get 718 | */ 719 | user: string; 720 | /** 721 | * Whether to include extended data of the artist and whether the user has loved the track or not 722 | */ 723 | extended?: NumericBoolean 724 | /** 725 | * Timestamp to get tracks from 726 | */ 727 | from?: string; 728 | /** 729 | * Timestamp to get tracks to 730 | */ 731 | to?: string; 732 | /** 733 | * Number of tracks to get per page 734 | */ 735 | limit?: number; 736 | /** 737 | * Page number to get 738 | */ 739 | page?: number; 740 | }; 741 | 742 | export type UserGetTopAlbumsParams = { 743 | /** 744 | * User to get top albums of 745 | */ 746 | user: string; 747 | /** 748 | * Time period to get top albums of 749 | */ 750 | period?: Period; 751 | /** 752 | * Number of albums to get per page 753 | */ 754 | limit?: number; 755 | /** 756 | * Page number to get 757 | */ 758 | page?: number; 759 | }; 760 | 761 | export type UserGetTopArtistsParams = { 762 | /** 763 | * User to get top artists of 764 | */ 765 | user: string; 766 | /** 767 | * Time period to get top artists of 768 | */ 769 | period?: Period; 770 | /** 771 | * Number of artists to get per page 772 | */ 773 | limit?: number; 774 | /** 775 | * Page number to get 776 | */ 777 | page?: number; 778 | }; 779 | 780 | export type UserGetTopTagsParams = { 781 | /** 782 | * User to get top tags of 783 | */ 784 | user: string; 785 | /** 786 | * Number of tags to get 787 | */ 788 | limit?: number; 789 | }; 790 | 791 | export type UserGetTopTracksParams = { 792 | /** 793 | * User to get top tracks of 794 | */ 795 | user: string; 796 | /** 797 | * Time period to get top tracks of 798 | */ 799 | period?: Period; 800 | /** 801 | * Number of tracks to get per page 802 | */ 803 | limit?: number; 804 | /** 805 | * Page number to get 806 | */ 807 | page?: number; 808 | }; 809 | 810 | export type UserGetWeeklyAlbumChartParams = { 811 | /** 812 | * User to get weekly album chart of 813 | */ 814 | user: string; 815 | /** 816 | * Timestamp to get weekly album chart from 817 | */ 818 | from?: string; 819 | /** 820 | * Timestamp to get weekly album chart to 821 | */ 822 | to?: string; 823 | }; 824 | 825 | export type UserGetWeeklyArtistChartParams = { 826 | /** 827 | * User to get weekly artist chart of 828 | */ 829 | user: string; 830 | /** 831 | * Timestamp to get weekly artist chart from 832 | */ 833 | from?: string; 834 | /** 835 | * Timestamp to get weekly artist chart to 836 | */ 837 | to?: string; 838 | }; 839 | 840 | export type UserGetWeeklyChartListParams = { 841 | /** 842 | * User to get weekly charts of 843 | */ 844 | user: string; 845 | }; 846 | 847 | export type UserGetWeeklyTrackChartParams = { 848 | /** 849 | * User to get weekly track chart of 850 | */ 851 | user: string; 852 | /** 853 | * Timestamp to get weekly track chart from 854 | */ 855 | from?: string; 856 | /** 857 | * Timestamp to get weekly track chart to 858 | */ 859 | to?: string; 860 | }; 861 | } 862 | 863 | /** 864 | * LastFm API Client 865 | */ 866 | declare class LastFm { 867 | /** 868 | * Create a LastFm instance 869 | */ 870 | constructor(apiKey: string, secret?: string, sessionKey?: string); 871 | 872 | apiKey: string; 873 | secret: string; 874 | sessionKey: string; 875 | 876 | /** 877 | * Add tags to an album 878 | */ 879 | albumAddTags(params: LastFm.AlbumAddTagsParams, callback: LastFm.Callback): this; 880 | albumAddTags(params: LastFm.AlbumAddTagsParams): Promise; 881 | 882 | /** 883 | * Get info of an album 884 | */ 885 | albumGetInfo(params: LastFm.AlbumGetInfoParams, callback: LastFm.Callback): this; 886 | albumGetInfo(params: LastFm.WithMbId, callback: LastFm.Callback): this; 887 | albumGetInfo(params: LastFm.AlbumGetInfoParams): Promise; 888 | albumGetInfo(params: LastFm.WithMbId): Promise; 889 | 890 | /** 891 | * Get tags of an album added by a user 892 | */ 893 | albumGetTags(params: LastFm.AlbumGetTagsParams, callback: LastFm.Callback): this; 894 | albumGetTags(params: LastFm.WithMbId, callback: LastFm.Callback): this; 895 | albumGetTags(params: LastFm.AlbumGetTagsParams): Promise; 896 | albumGetTags(params: LastFm.WithMbId): Promise; 897 | 898 | /** 899 | * Get top tags of an album 900 | */ 901 | albumGetTopTags(params: LastFm.AlbumGetTopTagsParams, callback: LastFm.Callback): this; 902 | albumGetTopTags(params: LastFm.WithMbId, callback: LastFm.Callback): this; 903 | albumGetTopTags(params: LastFm.AlbumGetTopTagsParams): Promise; 904 | albumGetTopTags(params: LastFm.WithMbId): Promise; 905 | 906 | /** 907 | * Remove tag from an album 908 | */ 909 | albumRemoveTag(params: LastFm.AlbumRemoveTagParams, callback: LastFm.Callback): this; 910 | albumRemoveTag(params: LastFm.AlbumRemoveTagParams): Promise; 911 | 912 | /** 913 | * Search for an album 914 | */ 915 | albumSearch(params: LastFm.AlbumSearchParams, callback: LastFm.Callback): this; 916 | albumSearch(params: LastFm.AlbumSearchParams): Promise; 917 | 918 | /** 919 | * Add tags to an artist 920 | */ 921 | artistAddTags(params: LastFm.ArtistAddTagsParams, callback: LastFm.Callback): this; 922 | artistAddTags(params: LastFm.ArtistAddTagsParams): Promise; 923 | 924 | /** 925 | * Get correction of an artist 926 | */ 927 | artistGetCorrection(params: LastFm.ArtistGetCorrectionParams, callback: LastFm.Callback): this; 928 | artistGetCorrection(params: LastFm.ArtistGetCorrectionParams): Promise; 929 | 930 | /** 931 | * Get info of an artist 932 | */ 933 | artistGetInfo(params: LastFm.ArtistGetInfoParams, callback: LastFm.Callback): this; 934 | artistGetInfo(params: LastFm.WithMbId, callback: LastFm.Callback): this; 935 | artistGetInfo(params: LastFm.ArtistGetInfoParams): Promise; 936 | artistGetInfo(params: LastFm.WithMbId): Promise; 937 | 938 | /** 939 | * Get similar to an artist 940 | */ 941 | artistGetSimilar(params: LastFm.ArtistGetSimilarParams, callback: LastFm.Callback): this; 942 | artistGetSimilar(params: LastFm.WithMbId, callback: LastFm.Callback): this; 943 | artistGetSimilar(params: LastFm.ArtistGetSimilarParams): Promise; 944 | artistGetSimilar(params: LastFm.WithMbId): Promise; 945 | 946 | /** 947 | * Get tags of an artist added by a user 948 | */ 949 | artistGetTags(params: LastFm.ArtistGetTagsParams, callback: LastFm.Callback): this; 950 | artistGetTags(params: LastFm.WithMbId, callback: LastFm.Callback): this; 951 | artistGetTags(params: LastFm.ArtistGetTagsParams): Promise; 952 | artistGetTags(params: LastFm.WithMbId): Promise; 953 | 954 | /** 955 | * Get top albums of an artist 956 | */ 957 | artistGetTopAlbums(params: LastFm.ArtistGetTopAlbumsParams, callback: LastFm.Callback): this; 958 | artistGetTopAlbums(params: LastFm.WithMbId, callback: LastFm.Callback): this; 959 | artistGetTopAlbums(params: LastFm.ArtistGetTopAlbumsParams): Promise; 960 | artistGetTopAlbums(params: LastFm.WithMbId): Promise; 961 | 962 | /** 963 | * Get top tags of an artist 964 | */ 965 | artistGetTopTags(params: LastFm.ArtistGetTopTagsParams, callback: LastFm.Callback): this; 966 | artistGetTopTags(params: LastFm.WithMbId, callback: LastFm.Callback): this; 967 | artistGetTopTags(params: LastFm.ArtistGetTopTagsParams): Promise; 968 | artistGetTopTags(params: LastFm.WithMbId): Promise; 969 | 970 | /** 971 | * Get top tracks of an artist 972 | */ 973 | artistGetTopTracks(params: LastFm.ArtistGetTopTracksParams, callback: LastFm.Callback): this; 974 | artistGetTopTracks(params: LastFm.WithMbId, callback: LastFm.Callback): this; 975 | artistGetTopTracks(params: LastFm.ArtistGetTopTracksParams): Promise; 976 | artistGetTopTracks(params: LastFm.WithMbId): Promise; 977 | 978 | /** 979 | * Remove tag from an artist 980 | */ 981 | artistRemoveTag(params: LastFm.ArtistRemoveTagParams, callback: LastFm.Callback): this; 982 | artistRemoveTag(params: LastFm.ArtistRemoveTagParams): Promise; 983 | 984 | /** 985 | * Search for an artist 986 | */ 987 | artistSearch(params: LastFm.ArtistSearchParams, callback: LastFm.Callback): this; 988 | artistSearch(params: LastFm.ArtistSearchParams): Promise; 989 | 990 | /** 991 | * Get a session key for an account 992 | */ 993 | authGetMobileSession(params: LastFm.AuthGetMobileSessionParams, callback: LastFm.Callback): this; 994 | authGetMobileSession(params: LastFm.AuthGetMobileSessionParams): Promise; 995 | 996 | /** 997 | * Get a session key for an account 998 | */ 999 | authGetSession(params: LastFm.AuthGetSessionParams, callback: LastFm.Callback): this; 1000 | authGetSession(params: LastFm.AuthGetSessionParams): Promise; 1001 | 1002 | /** 1003 | * Get a token 1004 | */ 1005 | authGetToken(callback: LastFm.Callback): this; 1006 | 1007 | /** 1008 | * Get the top artists chart 1009 | */ 1010 | chartGetTopArtists(params: LastFm.ChartGetTopArtistsParams, callback: LastFm.Callback): this; 1011 | chartGetTopArtists(params: LastFm.ChartGetTopArtistsParams): Promise; 1012 | 1013 | /** 1014 | * Get the top tags chart 1015 | */ 1016 | chartGetTopTags(params: LastFm.ChartGetTopTagsParams, callback: LastFm.Callback): this; 1017 | chartGetTopTags(params: LastFm.ChartGetTopTagsParams): Promise; 1018 | 1019 | /** 1020 | * Get the top tracks chart 1021 | */ 1022 | chartGetTopTracks(params: LastFm.ChartGetTopTracksParams, callback: LastFm.Callback): this; 1023 | chartGetTopTracks(params: LastFm.ChartGetTopTracksParams): Promise; 1024 | 1025 | /** 1026 | * Get top artists of a country 1027 | */ 1028 | geoGetTopArtists(params: LastFm.GeoGetTopArtistsParams, callback: LastFm.Callback): this; 1029 | geoGetTopArtists(params: LastFm.GeoGetTopArtistsParams): Promise; 1030 | 1031 | /** 1032 | * Get top tracks of a country 1033 | */ 1034 | geoGetTopTracks(params: LastFm.GeoGetTopTracksParams, callback: LastFm.Callback): this; 1035 | geoGetTopTracks(params: LastFm.GeoGetTopTracksParams): Promise; 1036 | 1037 | /** 1038 | * Get artists in library of a user 1039 | */ 1040 | libraryGetArtists(params: LastFm.LibraryGetArtistsParams, callback: LastFm.Callback): this; 1041 | libraryGetArtists(params: LastFm.LibraryGetArtistsParams): Promise; 1042 | 1043 | /** 1044 | * Get info of a tag 1045 | */ 1046 | tagGetInfo(params: LastFm.TagGetInfoParams, callback: LastFm.Callback): this; 1047 | tagGetInfo(params: LastFm.TagGetInfoParams): Promise; 1048 | 1049 | /** 1050 | * Get similar to a tag 1051 | */ 1052 | tagGetSimilar(params: LastFm.TagGetSimilarParams, callback: LastFm.Callback): this; 1053 | tagGetSimilar(params: LastFm.TagGetSimilarParams): Promise; 1054 | 1055 | /** 1056 | * Get top albums of a tag 1057 | */ 1058 | tagGetTopAlbums(params: LastFm.TagGetTopAlbumsParams, callback: LastFm.Callback): this; 1059 | tagGetTopAlbums(params: LastFm.TagGetTopAlbumsParams): Promise; 1060 | 1061 | /** 1062 | * Get top artists of a tag 1063 | */ 1064 | tagGetTopArtists(params: LastFm.TagGetTopArtistsParams, callback: LastFm.Callback): this; 1065 | tagGetTopArtists(params: LastFm.TagGetTopArtistsParams): Promise; 1066 | 1067 | /** 1068 | * Get top tags 1069 | */ 1070 | tagGetTopTags(callback: LastFm.Callback): this; 1071 | 1072 | /** 1073 | * Get top tracks of a tag 1074 | */ 1075 | tagGetTopTracks(params: LastFm.TagGetTopTracksParams, callback: LastFm.Callback): this; 1076 | tagGetTopTracks(params: LastFm.TagGetTopTracksParams): Promise; 1077 | 1078 | /** 1079 | * Get weekly charts of a tag 1080 | */ 1081 | tagGetWeeklyChartList(params: LastFm.TagGetWeeklyChartListParams, callback: LastFm.Callback): this; 1082 | tagGetWeeklyChartList(params: LastFm.TagGetWeeklyChartListParams): Promise; 1083 | 1084 | /** 1085 | * Add tags to a track 1086 | */ 1087 | trackAddTags(params: LastFm.TrackAddTagsParams, callback: LastFm.Callback): this; 1088 | trackAddTags(params: LastFm.TrackAddTagsParams): Promise; 1089 | 1090 | /** 1091 | * Get correction of a track and artist 1092 | */ 1093 | trackGetCorrection(params: LastFm.TrackGetCorrectionParams, callback: LastFm.Callback): this; 1094 | trackGetCorrection(params: LastFm.TrackGetCorrectionParams): Promise; 1095 | 1096 | /** 1097 | * Get info of a track 1098 | */ 1099 | trackGetInfo(params: LastFm.TrackGetInfoParams, callback: LastFm.Callback): this; 1100 | trackGetInfo(params: LastFm.WithMbId, callback: LastFm.Callback): this; 1101 | trackGetInfo(params: LastFm.TrackGetInfoParams): Promise; 1102 | trackGetInfo(params: LastFm.WithMbId): Promise; 1103 | 1104 | /** 1105 | * Get similar to a track 1106 | */ 1107 | trackGetSimilar(params: LastFm.TrackGetSimilarParams, callback: LastFm.Callback): this; 1108 | trackGetSimilar(params: LastFm.WithMbId, callback: LastFm.Callback): this; 1109 | trackGetSimilar(params: LastFm.TrackGetSimilarParams): Promise; 1110 | trackGetSimilar(params: LastFm.WithMbId): Promise; 1111 | 1112 | /** 1113 | * Get tags of a track added by a user 1114 | */ 1115 | trackGetTags(params: LastFm.TrackGetTagsParams, callback: LastFm.Callback): this; 1116 | trackGetTags(params: LastFm.WithMbId, callback: LastFm.Callback): this; 1117 | trackGetTags(params: LastFm.TrackGetTagsParams): Promise; 1118 | trackGetTags(params: LastFm.WithMbId): Promise; 1119 | 1120 | /** 1121 | * Get top tags of a track 1122 | */ 1123 | trackGetTopTags(params: LastFm.TrackGetTopTagsParams, callback: LastFm.Callback): this; 1124 | trackGetTopTags(params: LastFm.WithMbId, callback: LastFm.Callback): this; 1125 | trackGetTopTags(params: LastFm.TrackGetTopTagsParams): Promise; 1126 | trackGetTopTags(params: LastFm.WithMbId): Promise; 1127 | 1128 | /** 1129 | * Love a track 1130 | */ 1131 | trackLove(params: LastFm.TrackLoveParams, callback: LastFm.Callback): this; 1132 | trackLove(params: LastFm.TrackLoveParams): Promise; 1133 | 1134 | /** 1135 | * Remove tag from a track 1136 | */ 1137 | trackRemoveTag(params: LastFm.TrackRemoveTagParams, callback: LastFm.Callback): this; 1138 | trackRemoveTag(params: LastFm.TrackRemoveTagParams): Promise; 1139 | 1140 | /** 1141 | * Scrobble a track 1142 | */ 1143 | trackScrobble(params: LastFm.TrackScrobbleParams, callback: LastFm.Callback): this; 1144 | trackScrobble(params: LastFm.TrackScrobbleParams): Promise; 1145 | 1146 | /** 1147 | * Scrobble many tracks 1148 | */ 1149 | trackScrobbleMany(paramsArr: LastFm.TrackScrobbleParams[], callback: LastFm.Callback): this; 1150 | trackScrobbleMany(paramsArr: LastFm.TrackScrobbleParams[]): Promise; 1151 | 1152 | /** 1153 | * Search for a track 1154 | */ 1155 | trackSearch(params: LastFm.TrackSearchParams, callback: LastFm.Callback): this; 1156 | trackSearch(params: LastFm.TrackSearchParams): Promise; 1157 | 1158 | /** 1159 | * Unlove a track 1160 | */ 1161 | trackUnlove(params: LastFm.TrackUnloveParams, callback: LastFm.Callback): this; 1162 | trackUnlove(params: LastFm.TrackUnloveParams): Promise; 1163 | 1164 | /** 1165 | * Update now playing 1166 | */ 1167 | trackUpdateNowPlaying(params: LastFm.TrackUpdateNowPlayingParams, callback: LastFm.Callback): this; 1168 | trackUpdateNowPlaying(params: LastFm.TrackUpdateNowPlayingParams): Promise; 1169 | 1170 | /** 1171 | * Get friends of a user 1172 | */ 1173 | userGetFriends(params: LastFm.UserGetFriendsParams, callback: LastFm.Callback): this; 1174 | userGetFriends(params: LastFm.UserGetFriendsParams): Promise; 1175 | 1176 | /** 1177 | * Get info of a user 1178 | */ 1179 | userGetInfo(params: LastFm.UserGetInfoParams, callback: LastFm.Callback): this; 1180 | userGetInfo(params: LastFm.UserGetInfoParams): Promise; 1181 | 1182 | /** 1183 | * Get loved tracks of a user 1184 | */ 1185 | userGetLovedTracks(params: LastFm.UserGetLovedTracksParams, callback: LastFm.Callback): this; 1186 | userGetLovedTracks(params: LastFm.UserGetLovedTracksParams): Promise; 1187 | 1188 | /** 1189 | * Get items of a tag added by a user 1190 | */ 1191 | userGetPersonalTags(params: LastFm.UserGetPersonalTagsParams, callback: LastFm.Callback): this; 1192 | userGetPersonalTags(params: LastFm.UserGetPersonalTagsParams): Promise; 1193 | 1194 | /** 1195 | * Get recent tracks of a user 1196 | */ 1197 | userGetRecentTracks(params: LastFm.UserGetRecentTracksParams, callback: LastFm.Callback): this; 1198 | userGetRecentTracks(params: LastFm.UserGetRecentTracksParams): Promise; 1199 | 1200 | /** 1201 | * Get top albums of a user 1202 | */ 1203 | userGetTopAlbums(params: LastFm.UserGetTopAlbumsParams, callback: LastFm.Callback): this; 1204 | userGetTopAlbums(params: LastFm.UserGetTopAlbumsParams): Promise; 1205 | 1206 | /** 1207 | * Get top artists of a user 1208 | */ 1209 | userGetTopArtists(params: LastFm.UserGetTopArtistsParams, callback: LastFm.Callback): this; 1210 | userGetTopArtists(params: LastFm.UserGetTopArtistsParams): Promise; 1211 | 1212 | /** 1213 | * Get top tags of a user 1214 | */ 1215 | userGetTopTags(params: LastFm.UserGetTopTagsParams, callback: LastFm.Callback): this; 1216 | userGetTopTags(params: LastFm.UserGetTopTagsParams): Promise; 1217 | 1218 | /** 1219 | * Get top tracks of a user 1220 | */ 1221 | userGetTopTracks(params: LastFm.UserGetTopTracksParams, callback: LastFm.Callback): this; 1222 | userGetTopTracks(params: LastFm.UserGetTopTracksParams): Promise; 1223 | 1224 | /** 1225 | * Get weekly album chart of a user 1226 | */ 1227 | userGetWeeklyAlbumChart(params: LastFm.UserGetWeeklyAlbumChartParams, callback: LastFm.Callback): this; 1228 | userGetWeeklyAlbumChart(params: LastFm.UserGetWeeklyAlbumChartParams): Promise; 1229 | 1230 | /** 1231 | * Get weekly artist chart of a user 1232 | */ 1233 | userGetWeeklyArtistChart(params: LastFm.UserGetWeeklyArtistChartParams, callback: LastFm.Callback): this; 1234 | userGetWeeklyArtistChart(params: LastFm.UserGetWeeklyArtistChartParams): Promise; 1235 | 1236 | /** 1237 | * Get weekly charts of a user 1238 | */ 1239 | userGetWeeklyChartList(params: LastFm.UserGetWeeklyChartListParams, callback: LastFm.Callback): this; 1240 | userGetWeeklyChartList(params: LastFm.UserGetWeeklyChartListParams): Promise; 1241 | 1242 | /** 1243 | * Get weekly track chart of a user 1244 | */ 1245 | userGetWeeklyTrackChart(params: LastFm.UserGetWeeklyTrackChartParams, callback: LastFm.Callback): this; 1246 | userGetWeeklyTrackChart(params: LastFm.UserGetWeeklyTrackChartParams): Promise; 1247 | } 1248 | 1249 | export = LastFm; 1250 | -------------------------------------------------------------------------------- /lib/LastFm.js: -------------------------------------------------------------------------------- 1 | const ApiRequest = require("./ApiRequest"); 2 | 3 | /** 4 | * Callback for LastFm methods 5 | * @callback callback 6 | * @param {Error} [err] 7 | * @param {Object} [data] 8 | */ 9 | 10 | class LastFm { 11 | /** 12 | * Create a LastFm instance 13 | * @param {string} apiKey 14 | * @param {string} secret 15 | * @param {string} sessionKey 16 | */ 17 | 18 | constructor(apiKey, secret, sessionKey) { 19 | if (typeof apiKey !== "string") { 20 | throw new TypeError("apiKey must be of type string"); 21 | } 22 | 23 | this.apiKey = apiKey; 24 | 25 | if (secret !== undefined) { 26 | if (typeof secret !== "string") { 27 | throw new TypeError("secret must be of type string"); 28 | } 29 | 30 | this.secret = secret; 31 | } 32 | 33 | if (sessionKey !== undefined) { 34 | if (typeof sessionKey !== "string") { 35 | throw new TypeError("sessionKey must be of type string"); 36 | } 37 | 38 | this.sessionKey = sessionKey; 39 | } 40 | } 41 | 42 | /** 43 | * Add tags to an album 44 | * @param {Object} params 45 | * @param {string} params.artist - Artist whose album to add tags to 46 | * @param {string} params.album - Album to add tags to 47 | * @param {(string|string[])} params.tags - Tags to add to album 48 | * @param {callback} [callback] 49 | * @returns {(Promise|LastFm)} 50 | */ 51 | 52 | albumAddTags(params, callback) { 53 | const apiRequest = new ApiRequest() 54 | .set(params) 55 | .set({ 56 | api_key: this.apiKey, 57 | method: "album.addTags", 58 | sk: this.sessionKey 59 | }) 60 | .sign(this.secret) 61 | .send("POST", callback); 62 | 63 | return apiRequest || this; 64 | } 65 | 66 | /** 67 | * Get info of an album 68 | * @param {Object} params 69 | * @param {string} [params.artist] - Artist whose album to get info of. Required unless params.mbid is set. 70 | * @param {string} [params.album] - Album to get info of. Required unless params.mbid is set. 71 | * @param {string} [params.mbid] - MusicBrainz ID of album to get info of. Required unless params.artist and params.album are set. 72 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist name 73 | * @param {string} [params.lang] - Language to return the biography in. Writen as an ISO 639 alpha-2 code. 74 | * @param {string} [params.username] - User whose play count to include 75 | * @param {callback} [callback] 76 | * @returns {(Promise|LastFm)} 77 | */ 78 | 79 | albumGetInfo(params, callback) { 80 | const apiRequest = new ApiRequest() 81 | .set(params) 82 | .set({ 83 | api_key: this.apiKey, 84 | method: "album.getInfo" 85 | }) 86 | .send(callback); 87 | 88 | return apiRequest || this; 89 | } 90 | 91 | /** 92 | * Get tags of an album added by a user 93 | * @param {Object} params 94 | * @param {string} [params.artist] - Artist whose album to get tags of. Required unless params.mbid is set. 95 | * @param {string} [params.album] - Album to get tags of. Required unless params.mbid is set. 96 | * @param {string} [params.mbid] - MusicBrainz ID of album to get tags of. Required unless params.artist and params.album are set. 97 | * @param {string} params.user - User whose tags added to the album to get 98 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist name 99 | * @param {callback} [callback] 100 | * @returns {(Promise|LastFm)} 101 | */ 102 | 103 | albumGetTags(params, callback) { 104 | const apiRequest = new ApiRequest() 105 | .set(params) 106 | .set({ 107 | api_key: this.apiKey, 108 | method: "album.getTags" 109 | }) 110 | .send(callback); 111 | 112 | return apiRequest || this; 113 | } 114 | 115 | /** 116 | * Get top tags of an album 117 | * @param {Object} params 118 | * @param {string} [params.artist] - Artist whose album to get top tags of. Required unless params.mbid is set. 119 | * @param {string} [params.album] - Album to get top tags of. Required unless params.mbid is set. 120 | * @param {string} [params.mbid] - MusicBrainz ID of album to get top tags of. Required unless params.artist and params.album are set. 121 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist name 122 | * @param {callback} [callback] 123 | * @returns {(Promise|LastFm)} 124 | */ 125 | 126 | albumGetTopTags(params, callback) { 127 | const apiRequest = new ApiRequest() 128 | .set(params) 129 | .set({ 130 | api_key: this.apiKey, 131 | method: "album.getTopTags" 132 | }) 133 | .send(callback); 134 | 135 | return apiRequest || this; 136 | } 137 | 138 | /** 139 | * Remove tag from an album 140 | * @param {Object} params 141 | * @param {string} params.artist - Artist whose album to remove tag from 142 | * @param {string} params.album - Album to remove tag from 143 | * @param {string} params.tag - Tag to remove from album 144 | * @param {callback} [callback] 145 | * @returns {(Promise|LastFm)} 146 | */ 147 | 148 | albumRemoveTag(params, callback) { 149 | const apiRequest = new ApiRequest() 150 | .set(params) 151 | .set({ 152 | api_key: this.apiKey, 153 | method: "album.removeTag", 154 | sk: this.sessionKey 155 | }) 156 | .sign(this.secret) 157 | .send("POST", callback); 158 | 159 | return apiRequest || this; 160 | } 161 | 162 | /** 163 | * Search for an album 164 | * @param {Object} params 165 | * @param {string} params.album - Album to search for 166 | * @param {number} [params.limit] - Number of albums to get per page 167 | * @param {number} [params.page] - Page number to get 168 | * @param {callback} [callback] 169 | * @returns {(Promise|LastFm)} 170 | */ 171 | 172 | albumSearch(params, callback) { 173 | const apiRequest = new ApiRequest() 174 | .set(params) 175 | .set({ 176 | api_key: this.apiKey, 177 | method: "album.search" 178 | }) 179 | .send(callback); 180 | 181 | return apiRequest || this; 182 | } 183 | 184 | /** 185 | * Add tags to an artist 186 | * @param {Object} params 187 | * @param {string} params.artist - Artist to add tags to 188 | * @param {(string|string[])} params.tags - Tags to add to artist 189 | * @param {callback} [callback] 190 | * @returns {(Promise|LastFm)} 191 | */ 192 | 193 | artistAddTags(params, callback) { 194 | const apiRequest = new ApiRequest() 195 | .set(params) 196 | .set({ 197 | api_key: this.apiKey, 198 | method: "artist.addTags", 199 | sk: this.sessionKey 200 | }) 201 | .sign(this.secret) 202 | .send("POST", callback); 203 | 204 | return apiRequest || this; 205 | } 206 | 207 | /** 208 | * Get correction of an artist 209 | * @param {Object} params 210 | * @param {string} params.artist - Artist to get correction of 211 | * @param {callback} [callback] 212 | * @returns {(Promise|LastFm)} 213 | */ 214 | 215 | artistGetCorrection(params, callback) { 216 | const apiRequest = new ApiRequest() 217 | .set(params) 218 | .set({ 219 | api_key: this.apiKey, 220 | method: "artist.getCorrection" 221 | }) 222 | .send(callback); 223 | 224 | return apiRequest || this; 225 | } 226 | 227 | /** 228 | * Get info of an artist 229 | * @param {Object} params 230 | * @param {string} [params.artist] - Artist to get info of. Required unless params.mbid is set. 231 | * @param {string} [params.mbid] - MusicBrainz ID of artist to get info of. Required unless params.artist is set. 232 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist name 233 | * @param {string} [params.lang] - Language to return the biography in. Writen as an ISO 639 alpha-2 code. 234 | * @param {string} [params.username] - User whose play count to include 235 | * @param {callback} [callback] 236 | * @returns {(Promise|LastFm)} 237 | */ 238 | 239 | artistGetInfo(params, callback) { 240 | const apiRequest = new ApiRequest() 241 | .set(params) 242 | .set({ 243 | api_key: this.apiKey, 244 | method: "artist.getInfo" 245 | }) 246 | .send(callback); 247 | 248 | return apiRequest || this; 249 | } 250 | 251 | /** 252 | * Get similar to an artist 253 | * @param {Object} params 254 | * @param {string} [params.artist] - Artist to get similar to. Required unless params.mbid is set. 255 | * @param {string} [params.mbid] - MusicBrainz ID of artist to get similar to. Required unless params.artist is set. 256 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist name 257 | * @param {number} [params.limit] - Number of artists to get 258 | * @param {callback} [callback] 259 | * @returns {(Promise|LastFm)} 260 | */ 261 | 262 | artistGetSimilar(params, callback) { 263 | const apiRequest = new ApiRequest() 264 | .set(params) 265 | .set({ 266 | api_key: this.apiKey, 267 | method: "artist.getSimilar" 268 | }) 269 | .send(callback); 270 | 271 | return apiRequest || this; 272 | } 273 | 274 | /** 275 | * Get tags of an artist added by a user 276 | * @param {Object} params 277 | * @param {string} [params.artist] - Artist to get tags of. Required unless params.mbid is set. 278 | * @param {string} [params.mbid] - MusicBrainz ID of artist to get tags of. Required unless params.artist is set. 279 | * @param {string} params.user - User whose tags added to the artist to get 280 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist name 281 | * @param {callback} [callback] 282 | * @returns {(Promise|LastFm)} 283 | */ 284 | 285 | artistGetTags(params, callback) { 286 | const apiRequest = new ApiRequest() 287 | .set(params) 288 | .set({ 289 | api_key: this.apiKey, 290 | method: "artist.getTags" 291 | }) 292 | .send(callback); 293 | 294 | return apiRequest || this; 295 | } 296 | 297 | /** 298 | * Get top albums of an artist 299 | * @param {Object} params 300 | * @param {string} [params.artist] - Artist to get top albums of. Required unless params.mbid is set. 301 | * @param {string} [params.mbid] - MusicBrainz ID of artist to get top albums of. Required unless params.artist is set. 302 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist name 303 | * @param {number} [params.limit] - Number of albums to get per page 304 | * @param {number} [params.page] - Page number to get 305 | * @param {callback} [callback] 306 | * @returns {(Promise|LastFm)} 307 | */ 308 | 309 | artistGetTopAlbums(params, callback) { 310 | const apiRequest = new ApiRequest() 311 | .set(params) 312 | .set({ 313 | api_key: this.apiKey, 314 | method: "artist.getTopAlbums" 315 | }) 316 | .send(callback); 317 | 318 | return apiRequest || this; 319 | } 320 | 321 | /** 322 | * Get top tags of an artist 323 | * @param {Object} params 324 | * @param {string} [params.artist] - Artist to get top tags of. Required unless params.mbid is set. 325 | * @param {string} [params.mbid] - MusicBrainz ID of artist to get top tags of. Required unless params.artist is set. 326 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist name 327 | * @param {callback} [callback] 328 | * @returns {(Promise|LastFm)} 329 | */ 330 | 331 | artistGetTopTags(params, callback) { 332 | const apiRequest = new ApiRequest() 333 | .set(params) 334 | .set({ 335 | api_key: this.apiKey, 336 | method: "artist.getTopTags" 337 | }) 338 | .send(callback); 339 | 340 | return apiRequest || this; 341 | } 342 | 343 | /** 344 | * Get top tracks of an artist 345 | * @param {Object} params 346 | * @param {string} [params.artist] - Artist to get top tracks of. Required unless params.mbid is set. 347 | * @param {string} [params.mbid] - MusicBrainz ID of artist to get top tracks of. Required unless params.artist is set. 348 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist name 349 | * @param {number} [params.limit] - Number of tracks to get per page 350 | * @param {number} [params.page] - Page number to get 351 | * @param {callback} [callback] 352 | * @returns {(Promise|LastFm)} 353 | */ 354 | 355 | artistGetTopTracks(params, callback) { 356 | const apiRequest = new ApiRequest() 357 | .set(params) 358 | .set({ 359 | api_key: this.apiKey, 360 | method: "artist.getTopTracks" 361 | }) 362 | .send(callback); 363 | 364 | return apiRequest || this; 365 | } 366 | 367 | /** 368 | * Remove tag from an artist 369 | * @param {Object} params 370 | * @param {string} params.artist - Artist to remove tag from 371 | * @param {string} params.tag - Tag to remove from artist 372 | * @param {callback} [callback] 373 | * @returns {(Promise|LastFm)} 374 | */ 375 | 376 | artistRemoveTag(params, callback) { 377 | const apiRequest = new ApiRequest() 378 | .set(params) 379 | .set({ 380 | api_key: this.apiKey, 381 | method: "artist.removeTag", 382 | sk: this.sessionKey 383 | }) 384 | .sign(this.secret) 385 | .send("POST", callback); 386 | 387 | return apiRequest || this; 388 | } 389 | 390 | /** 391 | * Search for an artist 392 | * @param {Object} params 393 | * @param {string} params.artist - Artist to search for 394 | * @param {number} [params.limit] - Number of artists to get per page 395 | * @param {number} [params.page] - Page number to get 396 | * @param {callback} [callback] 397 | * @returns {(Promise|LastFm)} 398 | */ 399 | 400 | artistSearch(params, callback) { 401 | const apiRequest = new ApiRequest() 402 | .set(params) 403 | .set({ 404 | api_key: this.apiKey, 405 | method: "artist.search" 406 | }) 407 | .send(callback); 408 | 409 | return apiRequest || this; 410 | } 411 | 412 | /** 413 | * Get a session key for an account 414 | * @param {Object} params 415 | * @param {string} params.username - Username or email of the account to get a session key for 416 | * @param {string} params.password - Password of the account to get a session key for 417 | * @param {callback} [callback] 418 | * @returns {(Promise|LastFm)} 419 | */ 420 | 421 | authGetMobileSession(params, callback) { 422 | const apiRequest = new ApiRequest() 423 | .set(params) 424 | .set({ 425 | api_key: this.apiKey, 426 | method: "auth.getMobileSession" 427 | }) 428 | .sign(this.secret) 429 | .send("POST", callback); 430 | 431 | return apiRequest || this; 432 | } 433 | 434 | /** 435 | * Get a session key for an account 436 | * @param {Object} params 437 | * @param {string} params.token - Token to authenticate request 438 | * @param {callback} [callback] 439 | * @returns {(Promise|LastFm)} 440 | */ 441 | 442 | authGetSession(params, callback) { 443 | const apiRequest = new ApiRequest() 444 | .set(params) 445 | .set({ 446 | api_key: this.apiKey, 447 | method: "auth.getSession" 448 | }) 449 | .sign(this.secret) 450 | .send(callback); 451 | 452 | return apiRequest || this; 453 | } 454 | 455 | /** 456 | * Get a token 457 | * @param {callback} [callback] 458 | * @returns {(Promise|LastFm)} 459 | */ 460 | 461 | authGetToken(callback) { 462 | const apiRequest = new ApiRequest() 463 | .set({ 464 | api_key: this.apiKey, 465 | method: "auth.getToken" 466 | }) 467 | .sign(this.secret) 468 | .send(callback); 469 | 470 | return apiRequest || this; 471 | } 472 | 473 | /** 474 | * Get the top artists chart 475 | * @param {Object} params 476 | * @param {number} [params.limit] - Number of artists to get per page 477 | * @param {number} [params.page] - Page number to get 478 | * @param {callback} [callback] 479 | * @returns {(Promise|LastFm)} 480 | */ 481 | 482 | chartGetTopArtists(params, callback) { 483 | const apiRequest = new ApiRequest() 484 | .set(params) 485 | .set({ 486 | api_key: this.apiKey, 487 | method: "chart.getTopArtists" 488 | }) 489 | .send(callback); 490 | 491 | return apiRequest || this; 492 | } 493 | 494 | /** 495 | * Get the top tags chart 496 | * @param {Object} params 497 | * @param {number} [params.limit] - Number of tags to get per page 498 | * @param {number} [params.page] - Page number to get 499 | * @param {callback} [callback] 500 | * @returns {(Promise|LastFm)} 501 | */ 502 | 503 | chartGetTopTags(params, callback) { 504 | const apiRequest = new ApiRequest() 505 | .set(params) 506 | .set({ 507 | api_key: this.apiKey, 508 | method: "chart.getTopTags" 509 | }) 510 | .send(callback); 511 | 512 | return apiRequest || this; 513 | } 514 | 515 | /** 516 | * Get the top tracks chart 517 | * @param {Object} params 518 | * @param {number} [params.limit] - Number of tracks to get per page 519 | * @param {number} [params.page] - Page number to get 520 | * @param {callback} [callback] 521 | * @returns {(Promise|LastFm)} 522 | */ 523 | 524 | chartGetTopTracks(params, callback) { 525 | const apiRequest = new ApiRequest() 526 | .set(params) 527 | .set({ 528 | api_key: this.apiKey, 529 | method: "chart.getTopTracks" 530 | }) 531 | .send(callback); 532 | 533 | return apiRequest || this; 534 | } 535 | 536 | /** 537 | * Get top artists of a country 538 | * @param {Object} params 539 | * @param {string} params.country - Country to get top artists of. Written as an ISO 3166 country name. 540 | * @param {number} [params.limit] - Number of artists to get per page 541 | * @param {number} [params.page] - Page number to get 542 | * @param {callback} [callback] 543 | * @returns {(Promise|LastFm)} 544 | */ 545 | 546 | geoGetTopArtists(params, callback) { 547 | const apiRequest = new ApiRequest() 548 | .set(params) 549 | .set({ 550 | api_key: this.apiKey, 551 | method: "geo.getTopArtists" 552 | }) 553 | .send(callback); 554 | 555 | return apiRequest || this; 556 | } 557 | 558 | /** 559 | * Get top tracks of a country 560 | * @param {Object} params 561 | * @param {string} params.country - Country to get top tracks of. Written as an ISO 3166 country name. 562 | * @param {string} [params.location] - Location within a country to get top tracks of 563 | * @param {number} [params.limit] - Number of tracks to get per page 564 | * @param {number} [params.page] - Page number to get 565 | * @param {callback} [callback] 566 | * @returns {(Promise|LastFm)} 567 | */ 568 | 569 | geoGetTopTracks(params, callback) { 570 | const apiRequest = new ApiRequest() 571 | .set(params) 572 | .set({ 573 | api_key: this.apiKey, 574 | method: "geo.getTopTracks" 575 | }) 576 | .send(callback); 577 | 578 | return apiRequest || this; 579 | } 580 | 581 | /** 582 | * Get artists in library of a user 583 | * @param {Object} params 584 | * @param {string} params.user - User whose library to get artists of 585 | * @param {number} [params.limit] - Number of artists to get per page 586 | * @param {number} [params.page] - Page number to get 587 | * @param {callback} [callback] 588 | * @returns {(Promise|LastFm)} 589 | */ 590 | 591 | libraryGetArtists(params, callback) { 592 | const apiRequest = new ApiRequest() 593 | .set(params) 594 | .set({ 595 | api_key: this.apiKey, 596 | method: "library.getArtists" 597 | }) 598 | .send(callback); 599 | 600 | return apiRequest || this; 601 | } 602 | 603 | /** 604 | * Get info of a tag 605 | * @param {Object} params 606 | * @param {string} params.tag - Tag to get info of 607 | * @param {string} [params.lang] - Language to return the wiki in. Writen as an ISO 639 alpha-2 code. 608 | * @param {callback} [callback] 609 | * @returns {(Promise|LastFm)} 610 | */ 611 | 612 | tagGetInfo(params, callback) { 613 | const apiRequest = new ApiRequest() 614 | .set(params) 615 | .set({ 616 | api_key: this.apiKey, 617 | method: "tag.getInfo" 618 | }) 619 | .send(callback); 620 | 621 | return apiRequest || this; 622 | } 623 | 624 | /** 625 | * Get similar to a tag 626 | * @param {Object} params 627 | * @param {string} params.tag - Tag to get similar to 628 | * @param {callback} [callback] 629 | * @returns {(Promise|LastFm)} 630 | */ 631 | 632 | tagGetSimilar(params, callback) { 633 | const apiRequest = new ApiRequest() 634 | .set(params) 635 | .set({ 636 | api_key: this.apiKey, 637 | method: "tag.getSimilar" 638 | }) 639 | .send(callback); 640 | 641 | return apiRequest || this; 642 | } 643 | 644 | /** 645 | * Get top albums of a tag 646 | * @param {Object} params 647 | * @param {string} params.tag - Tag to get top albums of 648 | * @param {number} [params.limit] - Number of albums to get per page 649 | * @param {number} [params.page] - Page number to get 650 | * @param {callback} [callback] 651 | * @returns {(Promise|LastFm)} 652 | */ 653 | 654 | tagGetTopAlbums(params, callback) { 655 | const apiRequest = new ApiRequest() 656 | .set(params) 657 | .set({ 658 | api_key: this.apiKey, 659 | method: "tag.getTopAlbums" 660 | }) 661 | .send(callback); 662 | 663 | return apiRequest || this; 664 | } 665 | 666 | /** 667 | * Get top artists of a tag 668 | * @param {Object} params 669 | * @param {string} params.tag - Tag to get top artists of 670 | * @param {number} [params.limit] - Number of artists to get per page 671 | * @param {number} [params.page] - Page number to get 672 | * @param {callback} [callback] 673 | * @returns {(Promise|LastFm)} 674 | */ 675 | 676 | tagGetTopArtists(params, callback) { 677 | const apiRequest = new ApiRequest() 678 | .set(params) 679 | .set({ 680 | api_key: this.apiKey, 681 | method: "tag.getTopArtists" 682 | }) 683 | .send(callback); 684 | 685 | return apiRequest || this; 686 | } 687 | 688 | /** 689 | * Get top tags 690 | * @param {callback} [callback] 691 | * @returns {(Promise|LastFm)} 692 | */ 693 | 694 | tagGetTopTags(callback) { 695 | const apiRequest = new ApiRequest() 696 | .set({ 697 | api_key: this.apiKey, 698 | method: "tag.getTopTags" 699 | }) 700 | .send(callback); 701 | 702 | return apiRequest || this; 703 | } 704 | 705 | /** 706 | * Get top tracks of a tag 707 | * @param {Object} params 708 | * @param {string} params.tag - Tag to get top tracks of 709 | * @param {number} [params.limit] - Number of tracks to get per page 710 | * @param {number} [params.page] - Page number to get 711 | * @param {callback} [callback] 712 | * @returns {(Promise|LastFm)} 713 | */ 714 | 715 | tagGetTopTracks(params, callback) { 716 | const apiRequest = new ApiRequest() 717 | .set(params) 718 | .set({ 719 | api_key: this.apiKey, 720 | method: "tag.getTopTracks" 721 | }) 722 | .send(callback); 723 | 724 | return apiRequest || this; 725 | } 726 | 727 | /** 728 | * Get weekly charts of a tag 729 | * @param {Object} params 730 | * @param {string} params.tag - Tag to get weekly charts of 731 | * @param {callback} [callback] 732 | * @returns {(Promise|LastFm)} 733 | */ 734 | 735 | tagGetWeeklyChartList(params, callback) { 736 | const apiRequest = new ApiRequest() 737 | .set(params) 738 | .set({ 739 | api_key: this.apiKey, 740 | method: "tag.getWeeklyChartList" 741 | }) 742 | .send(callback); 743 | 744 | return apiRequest || this; 745 | } 746 | 747 | /** 748 | * Add tags to a track 749 | * @param {Object} params 750 | * @param {string} params.artist - Artist whose track to add tags to 751 | * @param {string} params.track - Track to add tags to 752 | * @param {(string|string[])} params.tags - Tags to add to track 753 | * @param {callback} [callback] 754 | * @returns {(Promise|LastFm)} 755 | */ 756 | 757 | trackAddTags(params, callback) { 758 | const apiRequest = new ApiRequest() 759 | .set(params) 760 | .set({ 761 | api_key: this.apiKey, 762 | method: "track.addTags", 763 | sk: this.sessionKey 764 | }) 765 | .sign(this.secret) 766 | .send("POST", callback); 767 | 768 | return apiRequest || this; 769 | } 770 | 771 | /** 772 | * Get correction of a track and artist 773 | * @param {Object} params 774 | * @param {string} params.artist - Artist and whose track to get correction of 775 | * @param {string} params.track - Track to get correction of 776 | * @param {callback} [callback] 777 | * @returns {(Promise|LastFm)} 778 | */ 779 | 780 | trackGetCorrection(params, callback) { 781 | const apiRequest = new ApiRequest() 782 | .set(params) 783 | .set({ 784 | api_key: this.apiKey, 785 | method: "track.getCorrection" 786 | }) 787 | .send(callback); 788 | 789 | return apiRequest || this; 790 | } 791 | 792 | /** 793 | * Get info of a track 794 | * @param {Object} params 795 | * @param {string} [params.artist] - Artist whose track to get info of. Required unless params.mbid is set. 796 | * @param {string} [params.track] - Track to get info of. Required unless params.mbid is set. 797 | * @param {string} [params.mbid] - MusicBrainz ID of track to get info of. Required unless params.artist and params.track are set. 798 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist and track names 799 | * @param {string} [params.username] - User whose playcount and whether or not they have loved the track to include 800 | * @param {callback} [callback] 801 | * @returns {(Promise|LastFm)} 802 | */ 803 | 804 | trackGetInfo(params, callback) { 805 | const apiRequest = new ApiRequest() 806 | .set(params) 807 | .set({ 808 | api_key: this.apiKey, 809 | method: "track.getInfo" 810 | }) 811 | .send(callback); 812 | 813 | return apiRequest || this; 814 | } 815 | 816 | /** 817 | * Get similar to a track 818 | * @param {Object} params 819 | * @param {string} [params.artist] - Artist whose track to get similar to. Required unless params.mbid is set. 820 | * @param {string} [params.track] - Track to get similar to. Required unless params.mbid is set. 821 | * @param {string} [params.mbid] - MusicBrainz ID of track to get similar to. Required unless params.artist and params.track are set. 822 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist and track names 823 | * @param {number} [params.limit] - Number of tracks to get 824 | * @param {callback} [callback] 825 | * @returns {(Promise|LastFm)} 826 | */ 827 | 828 | trackGetSimilar(params, callback) { 829 | const apiRequest = new ApiRequest() 830 | .set(params) 831 | .set({ 832 | api_key: this.apiKey, 833 | method: "track.getSimilar" 834 | }) 835 | .send(callback); 836 | 837 | return apiRequest || this; 838 | } 839 | 840 | /** 841 | * Get tags of a track added by a user 842 | * @param {Object} params 843 | * @param {string} [params.artist] - Artist whose track to get tags of. Required unless params.mbid is set. 844 | * @param {string} [params.track] - Track to get tags of. Required unless params.mbid is set. 845 | * @param {string} [params.mbid] - MusicBrainz ID of track to get tags of. Required unless params.artist and params.track are set. 846 | * @param {string} params.user - User whose tags added to the track to get 847 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist and track names 848 | * @param {callback} [callback] 849 | * @returns {(Promise|LastFm)} 850 | */ 851 | 852 | trackGetTags(params, callback) { 853 | const apiRequest = new ApiRequest() 854 | .set(params) 855 | .set({ 856 | api_key: this.apiKey, 857 | method: "track.getTags" 858 | }) 859 | .send(callback); 860 | 861 | return apiRequest || this; 862 | } 863 | 864 | /** 865 | * Get top tags of a track 866 | * @param {Object} params 867 | * @param {string} [params.artist] - Artist whose track to get top tags of. Required unless params.mbid is set. 868 | * @param {string} [params.track] - Track to get top tags of. Required unless params.mbid is set. 869 | * @param {string} [params.mbid] - MusicBrainz ID of track to get top tags of. Required unless params.artist and params.track are set. 870 | * @param {(0|1)} [params.autocorrect] - Whether to correct misspelt artist and track names 871 | * @param {callback} [callback] 872 | * @returns {(Promise|LastFm)} 873 | */ 874 | 875 | trackGetTopTags(params, callback) { 876 | const apiRequest = new ApiRequest() 877 | .set(params) 878 | .set({ 879 | api_key: this.apiKey, 880 | method: "track.getTopTags" 881 | }) 882 | .send(callback); 883 | 884 | return apiRequest || this; 885 | } 886 | 887 | /** 888 | * Love a track 889 | * @param {Object} params 890 | * @param {string} params.artist - Artist whose track to love 891 | * @param {string} params.track - Track to love 892 | * @param {callback} [callback] 893 | * @returns {(Promise|LastFm)} 894 | */ 895 | 896 | trackLove(params, callback) { 897 | const apiRequest = new ApiRequest() 898 | .set(params) 899 | .set({ 900 | api_key: this.apiKey, 901 | method: "track.love", 902 | sk: this.sessionKey 903 | }) 904 | .sign(this.secret) 905 | .send("POST", callback); 906 | 907 | return apiRequest || this; 908 | } 909 | 910 | /** 911 | * Remove tag from a track 912 | * @param {Object} params 913 | * @param {string} params.artist - Artist whose track to remove tag from 914 | * @param {string} params.track - Track to remove tag from 915 | * @param {string} params.tag - Tag to remove from track 916 | * @param {callback} [callback] 917 | * @returns {(Promise|LastFm)} 918 | */ 919 | 920 | trackRemoveTag(params, callback) { 921 | const apiRequest = new ApiRequest() 922 | .set(params) 923 | .set({ 924 | api_key: this.apiKey, 925 | method: "track.removeTag", 926 | sk: this.sessionKey 927 | }) 928 | .sign(this.secret) 929 | .send("POST", callback); 930 | 931 | return apiRequest || this; 932 | } 933 | 934 | /** 935 | * Scrobble a track 936 | * @param {Object} params 937 | * @param {string} params.artist - Artist whose track to scrobble 938 | * @param {string} params.track - Track to scobble 939 | * @param {string} [params.album] - Album the track to scrobble is from 940 | * @param {string} [params.albumArist] - Artist whose album the track to scrobble is from 941 | * @param {number} params.timestamp - Timestamp to scrobble track at 942 | * @param {number} [params.trackNumber] - Number of track to scrobble on the album 943 | * @param {number} [params.duration] - Length of the track to scrobble in seconds 944 | * @param {(0|1)} [params.chosenByUser] - Whether the user chose the track to scrobble 945 | * @param {string} [params.streamId] - Stream ID if track to scrobble is from Last.Fm radio 946 | * @param {callback} [callback] 947 | * @returns {(Promise|LastFm)} 948 | */ 949 | 950 | trackScrobble(params, callback) { 951 | const apiRequest = new ApiRequest() 952 | .set(params) 953 | .set({ 954 | api_key: this.apiKey, 955 | method: "track.scrobble", 956 | sk: this.sessionKey 957 | }) 958 | .sign(this.secret) 959 | .send("POST", callback); 960 | 961 | return apiRequest || this; 962 | } 963 | 964 | /** 965 | * Scrobble many tracks 966 | * @param {Object[]} paramsArr 967 | * @param {string} paramsArr[].artist - Artist whose track to scrobble 968 | * @param {string} paramsArr[].track - Track to scobble 969 | * @param {string} [paramsArr[].album] - Album the track to scrobble is from 970 | * @param {string} [paramsArr[].albumArist] - Artist whose album the track to scrobble is from 971 | * @param {number} paramsArr[].timestamp - Timestamp to scrobble track at 972 | * @param {number} [paramsArr[].trackNumber] - Number of track to scrobble on the album 973 | * @param {number} [paramsArr[].duration] - Length of the track to scrobble in seconds 974 | * @param {(0|1)} [paramsArr[].chosenByUser] - Whether the user chose the track to scrobble 975 | * @param {string} [paramsArr.streamId] - Stream ID if track to scrobble is from Last.Fm radio 976 | * @param {callback} [callback] 977 | * @returns {(Promise|LastFm)} 978 | */ 979 | 980 | trackScrobbleMany(paramsArr, callback) { 981 | const params = {}; 982 | 983 | paramsArr.forEach((paramsObj, i) => Object 984 | .entries(paramsObj) 985 | .forEach(([name, value]) => params[`${name}[${i}]`] = value)); 986 | 987 | return this.trackScrobble(params, callback); 988 | } 989 | 990 | /** 991 | * Search for a track 992 | * @param {Object} params 993 | * @param {string} [params.artist] - Artist whose track to search for 994 | * @param {string} params.track - Track to search for 995 | * @param {number} [params.limit] - Number of tracks to get per page 996 | * @param {number} [params.page] - Page number to get 997 | * @param {callback} [callback] 998 | * @returns {(Promise|LastFm)} 999 | */ 1000 | 1001 | trackSearch(params, callback) { 1002 | const apiRequest = new ApiRequest() 1003 | .set(params) 1004 | .set({ 1005 | api_key: this.apiKey, 1006 | method: "track.search" 1007 | }) 1008 | .send(callback); 1009 | 1010 | return apiRequest || this; 1011 | } 1012 | 1013 | /** 1014 | * Unlove a track 1015 | * @param {Object} params 1016 | * @param {string} params.artist - Artist whose track to unlove 1017 | * @param {string} params.track - Track to unlove 1018 | * @param {callback} [callback] 1019 | * @returns {(Promise|LastFm)} 1020 | */ 1021 | 1022 | trackUnlove(params, callback) { 1023 | const apiRequest = new ApiRequest() 1024 | .set(params) 1025 | .set({ 1026 | api_key: this.apiKey, 1027 | method: "track.unlove", 1028 | sk: this.sessionKey 1029 | }) 1030 | .sign(this.secret) 1031 | .send("POST", callback); 1032 | 1033 | return apiRequest || this; 1034 | } 1035 | 1036 | /** 1037 | * Update now playing 1038 | * @param {Object} params 1039 | * @param {string} params.artist - Artist whose track to update now playing with 1040 | * @param {string} params.track - Track to update now playing with 1041 | * @param {string} [params.album] - Album the track to update now playing with is from 1042 | * @param {string} [params.albumArist] - Artist whose album the track to update now playing with is from 1043 | * @param {number} [params.trackNumber] - Number of track to update now playing with on the album 1044 | * @param {number} [params.duration] - Length of the track to update now playing with in seconds 1045 | * @param {callback} [callback] 1046 | * @returns {(Promise|LastFm)} 1047 | */ 1048 | 1049 | trackUpdateNowPlaying(params, callback) { 1050 | const apiRequest = new ApiRequest() 1051 | .set(params) 1052 | .set({ 1053 | api_key: this.apiKey, 1054 | method: "track.updateNowPlaying", 1055 | sk: this.sessionKey 1056 | }) 1057 | .sign(this.secret) 1058 | .send("POST", callback); 1059 | 1060 | return apiRequest || this; 1061 | } 1062 | 1063 | /** 1064 | * Get friends of a user 1065 | * @param {Object} params 1066 | * @param {string} params.user - User to get friends of 1067 | * @param {(0|1)} [params.recenttracks] - Whether to include recent tracks of friends 1068 | * @param {number} [params.limit] - Number of friends to get per page 1069 | * @param {number} [params.page] - Page number to get 1070 | * @param {callback} [callback] 1071 | * @returns {(Promise|LastFm)} 1072 | */ 1073 | 1074 | userGetFriends(params, callback) { 1075 | const apiRequest = new ApiRequest() 1076 | .set(params) 1077 | .set({ 1078 | api_key: this.apiKey, 1079 | method: "user.getFriends" 1080 | }) 1081 | .send(callback); 1082 | 1083 | return apiRequest || this; 1084 | } 1085 | 1086 | /** 1087 | * Get info of a user 1088 | * @param {Object} [params] 1089 | * @param {string} [params.user] - User to get info of 1090 | * @param {callback} [callback] 1091 | * @returns {(Promise|LastFm)} 1092 | */ 1093 | 1094 | userGetInfo(params, callback) { 1095 | callback = callback === undefined ? typeof params === "function" ? params : undefined : callback; 1096 | params = typeof params === "object" ? params : {}; 1097 | 1098 | const apiRequest = new ApiRequest() 1099 | .set(params) 1100 | .set({ 1101 | api_key: this.apiKey, 1102 | method: "user.getInfo" 1103 | }); 1104 | 1105 | if (!params.user) { 1106 | apiRequest 1107 | .set({ sk: this.sessionKey }) 1108 | .sign(this.secret); 1109 | } 1110 | 1111 | return apiRequest.send(params.user ? "GET" : "POST", callback) || this; 1112 | } 1113 | 1114 | /** 1115 | * Get loved tracks of a user 1116 | * @param {Object} params 1117 | * @param {string} params.user - User to get loved tracks of 1118 | * @param {number} [params.limit] - Number of tracks to get per page 1119 | * @param {number} [params.page] - Page number to get 1120 | * @param {callback} [callback] 1121 | * @returns {(Promise|LastFm)} 1122 | */ 1123 | 1124 | userGetLovedTracks(params, callback) { 1125 | const apiRequest = new ApiRequest() 1126 | .set(params) 1127 | .set({ 1128 | api_key: this.apiKey, 1129 | method: "user.getLovedTracks" 1130 | }) 1131 | .send(callback); 1132 | 1133 | return apiRequest || this; 1134 | } 1135 | 1136 | /** 1137 | * Get items of a tag added by a user 1138 | * @param {Object} params 1139 | * @param {string} params.user - User whose added tag to get items of 1140 | * @param {string} params.tag - Tag to get items of 1141 | * @param {("artist"|"album"|"track")} params.taggingtype - Type of tag to get items of 1142 | * @param {number} [params.limit] - Number of items to get per page 1143 | * @param {number} [params.page] - Page number to get 1144 | * @param {callback} [callback] 1145 | * @returns {(Promise|LastFm)} 1146 | */ 1147 | 1148 | userGetPersonalTags(params, callback) { 1149 | const apiRequest = new ApiRequest() 1150 | .set(params) 1151 | .set({ 1152 | api_key: this.apiKey, 1153 | method: "user.getPersonalTags" 1154 | }) 1155 | .send(callback); 1156 | 1157 | return apiRequest || this; 1158 | } 1159 | 1160 | /** 1161 | * Get recent tracks of a user 1162 | * @param {Object} params 1163 | * @param {string} params.user - User whose recent tracks to get 1164 | * @param {(0|1)} [params.extended] - Whether to include extended data of the artist and whether the user has loved the track or not 1165 | * @param {string} [params.from] - Timestamp to get tracks from 1166 | * @param {string} [params.to] - Timestamp to get tracks to 1167 | * @param {number} [params.limit] - Number of tracks to get per page 1168 | * @param {number} [params.page] - Page number to get 1169 | * @param {callback} [callback] 1170 | * @returns {(Promise|LastFm)} 1171 | */ 1172 | 1173 | userGetRecentTracks(params, callback) { 1174 | const apiRequest = new ApiRequest() 1175 | .set(params) 1176 | .set({ 1177 | api_key: this.apiKey, 1178 | method: "user.getRecentTracks" 1179 | }) 1180 | .send(callback); 1181 | 1182 | return apiRequest || this; 1183 | } 1184 | 1185 | /** 1186 | * Get top albums of a user 1187 | * @param {Object} params 1188 | * @param {string} params.user - User to get top albums of 1189 | * @param {("7day"|"1month"|"3month"|"6month"|"12month"|"overall")} [params.period] - Time period to get top albums of 1190 | * @param {number} [params.limit] - Number of albums to get per page 1191 | * @param {number} [params.page] - Page number to get 1192 | * @param {callback} [callback] 1193 | * @returns {(Promise|LastFm)} 1194 | */ 1195 | 1196 | userGetTopAlbums(params, callback) { 1197 | const apiRequest = new ApiRequest() 1198 | .set(params) 1199 | .set({ 1200 | api_key: this.apiKey, 1201 | method: "user.getTopAlbums" 1202 | }) 1203 | .send(callback); 1204 | 1205 | return apiRequest || this; 1206 | } 1207 | 1208 | /** 1209 | * Get top artists of a user 1210 | * @param {Object} params 1211 | * @param {string} params.user - User to get top artists of 1212 | * @param {("7day"|"1month"|"3month"|"6month"|"12month"|"overall")} [params.period] - Time period to get top artists of 1213 | * @param {number} [params.limit] - Number of artists to get per page 1214 | * @param {number} [params.page] - Page number to get 1215 | * @param {callback} [callback] 1216 | * @returns {(Promise|LastFm)} 1217 | */ 1218 | 1219 | userGetTopArtists(params, callback) { 1220 | const apiRequest = new ApiRequest() 1221 | .set(params) 1222 | .set({ 1223 | api_key: this.apiKey, 1224 | method: "user.getTopArtists" 1225 | }) 1226 | .send(callback); 1227 | 1228 | return apiRequest || this; 1229 | } 1230 | 1231 | /** 1232 | * Get top tags of a user 1233 | * @param {Object} params 1234 | * @param {string} params.user - User to get top tags of 1235 | * @param {number} [params.limit] - Number of tags to get 1236 | * @param {callback} [callback] 1237 | * @returns {(Promise|LastFm)} 1238 | */ 1239 | 1240 | userGetTopTags(params, callback) { 1241 | const apiRequest = new ApiRequest() 1242 | .set(params) 1243 | .set({ 1244 | api_key: this.apiKey, 1245 | method: "user.getTopTags" 1246 | }) 1247 | .send(callback); 1248 | 1249 | return apiRequest || this; 1250 | } 1251 | 1252 | /** 1253 | * Get top tracks of a user 1254 | * @param {Object} params 1255 | * @param {string} params.user - User to get top tracks of 1256 | * @param {("7day"|"1month"|"3month"|"6month"|"12month"|"overall")} [params.period] - Time period to get top tracks of 1257 | * @param {number} [params.limit] - Number of tracks to get per page 1258 | * @param {number} [params.page] - Page number to get 1259 | * @param {callback} [callback] 1260 | * @returns {(Promise|LastFm)} 1261 | */ 1262 | 1263 | userGetTopTracks(params, callback) { 1264 | const apiRequest = new ApiRequest() 1265 | .set(params) 1266 | .set({ 1267 | api_key: this.apiKey, 1268 | method: "user.getTopTracks" 1269 | }) 1270 | .send(callback); 1271 | 1272 | return apiRequest || this; 1273 | } 1274 | 1275 | /** 1276 | * Get weekly album chart of a user 1277 | * @param {Object} params 1278 | * @param {string} params.user - User to get weekly album chart of 1279 | * @param {string} [params.from] - Timestamp to get weekly album chart from 1280 | * @param {string} [params.to] - Timestamp to get weekly album chart to 1281 | * @param {callback} [callback] 1282 | * @returns {(Promise|LastFm)} 1283 | */ 1284 | 1285 | userGetWeeklyAlbumChart(params, callback) { 1286 | const apiRequest = new ApiRequest() 1287 | .set(params) 1288 | .set({ 1289 | api_key: this.apiKey, 1290 | method: "user.getWeeklyAlbumChart" 1291 | }) 1292 | .send(callback); 1293 | 1294 | return apiRequest || this; 1295 | } 1296 | 1297 | /** 1298 | * Get weekly artist chart of a user 1299 | * @param {Object} params 1300 | * @param {string} params.user - User to get weekly artist chart of 1301 | * @param {string} [params.from] - Timestamp to get weekly artist chart from 1302 | * @param {string} [params.to] - Timestamp to get weekly artist chart to 1303 | * @param {callback} [callback] 1304 | * @returns {(Promise|LastFm)} 1305 | */ 1306 | 1307 | userGetWeeklyArtistChart(params, callback) { 1308 | const apiRequest = new ApiRequest() 1309 | .set(params) 1310 | .set({ 1311 | api_key: this.apiKey, 1312 | method: "user.getWeeklyArtistChart" 1313 | }) 1314 | .send(callback); 1315 | 1316 | return apiRequest || this; 1317 | } 1318 | 1319 | /** 1320 | * Get weekly charts of a user 1321 | * @param {Object} params 1322 | * @param {string} params.user - User to get weekly charts of 1323 | * @param {callback} [callback] 1324 | * @returns {(Promise|LastFm)} 1325 | */ 1326 | 1327 | userGetWeeklyChartList(params, callback) { 1328 | const apiRequest = new ApiRequest() 1329 | .set(params) 1330 | .set({ 1331 | api_key: this.apiKey, 1332 | method: "user.getWeeklyChartList" 1333 | }) 1334 | .send(callback); 1335 | 1336 | return apiRequest || this; 1337 | } 1338 | 1339 | /** 1340 | * Get weekly track chart of a user 1341 | * @param {Object} params 1342 | * @param {string} params.user - User to get weekly track chart of 1343 | * @param {string} [params.from] - Timestamp to get weekly track chart from 1344 | * @param {string} [params.to] - Timestamp to get weekly track chart to 1345 | * @param {callback} [callback] 1346 | * @returns {(Promise|LastFm)} 1347 | */ 1348 | 1349 | userGetWeeklyTrackChart(params, callback) { 1350 | const apiRequest = new ApiRequest() 1351 | .set(params) 1352 | .set({ 1353 | api_key: this.apiKey, 1354 | method: "user.getWeeklyTrackChart" 1355 | }) 1356 | .send(callback); 1357 | 1358 | return apiRequest || this; 1359 | } 1360 | } 1361 | 1362 | module.exports = LastFm; 1363 | --------------------------------------------------------------------------------