UNPKG

@chez14/mal-api-lite

Version:
212 lines (205 loc) 6.12 kB
'use strict'; var crypto = require('crypto'); var got = require('got'); var url = require('url'); function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } var got__default = /*#__PURE__*/_interopDefault(got); // src/client.ts // src/constants.ts var PKG_VERSION = "1.2.9"; // src/client.ts var MALClient = class { clientId; clientSecret; accessToken; refreshToken; got; gotOAuth; PKCEChallangeGenerateSize = 32; userAgent = "@chez14/mal-api-lite"; malApiBaseUrl = "https://api.myanimelist.net/v2/"; malOAuthUrl = "https://myanimelist.net/v1/oauth2/"; /** * Create MAL API Client * * @param param0 Your trusty configuration */ constructor({ clientId, clientSecret, accessToken, refreshToken, gotOptions, gotOAuthOptions }) { if ((!clientSecret || !clientId) && !(accessToken || refreshToken)) { throw new Error( "You need to provide both (`clientSecret` and `clientId`) OR one of (`accessToken` or `refreshToken`)" ); } this.clientId = clientId; this.clientSecret = clientSecret; this.accessToken = accessToken; this.refreshToken = refreshToken; this.userAgent += ` v${PKG_VERSION}`; this.got = got__default.default.extend({ prefixUrl: this.malApiBaseUrl, responseType: "json", headers: { "user-agent": this.userAgent }, hooks: { beforeRequest: [ (options) => { if (this.accessToken) { options.headers.authorization = `Bearer ${this.accessToken}`; } else { options.headers["X-MAL-CLIENT-ID"] = this.clientId; } } ] }, ...gotOptions }); this.gotOAuth = got__default.default.extend({ prefixUrl: this.malOAuthUrl, headers: { "user-agent": this.userAgent }, responseType: "json", ...gotOAuthOptions }); } /** * Get Access Token & Refresh Token from given Authorization Code. * * @param authCode Authorization code * @param codeVerifier PKCE Code Challenge * @param redirectUri Redirect url, specified on on previous step */ async resolveAuthCode(authCode, codeVerifier, redirectUri) { if (!this.clientSecret || !this.clientId) { throw new Error("clientSecret and clientId must be filled to use this function!"); } const resp = await this.gotOAuth.post("token", { form: { client_id: this.clientId, client_secret: this.clientSecret, grant_type: "authorization_code", code: authCode, redirect_uri: redirectUri, code_verifier: codeVerifier } }); const { access_token, refresh_token } = resp.body; this.accessToken = access_token; this.refreshToken = refresh_token; return resp.body; } /** * Generate OAuth URL to gain access to user account on MyAnimeList platform. * Will require clientId and clientSecret from custructor. * * @param codeChallenge PKCE Code Challenge * @param redirectUri If you have more than one Redirect URL, please specify * the url you use. * @param state Your app state * @param codeChallengeMethod Only accept "plain". Don't change unless you * know what you're doing! */ getOAuthURL(redirectUri, codeChallenge, state) { if (!this.clientId) { throw new Error("clientId must be filled to use this function!"); } if (!codeChallenge) { codeChallenge = crypto.randomBytes(this.PKCEChallangeGenerateSize).toString("base64url"); } const query = { response_type: "code", client_id: this.clientId, state, redirect_uri: redirectUri, code_challenge: codeChallenge, code_challenge_method: "plain" }; const urlBuilder = new url.URL("authorize", this.gotOAuth.defaults.options.prefixUrl); Object.keys(query).forEach((key) => { if (query[key]) { urlBuilder.searchParams.append(key, query[key]); } }); return { url: urlBuilder.toString(), codeChallenge, state }; } /** * Refresh your access token with refresh token. * * @param refreshToken Custom refresh token */ async resolveRefreshToken(refreshToken) { if (!refreshToken) { refreshToken = this.refreshToken; } if (!refreshToken) { throw Error("No refreshToken provided."); } const resp = await this.gotOAuth.post("token", { form: { client_id: this.clientId, client_secret: this.clientSecret, grant_type: "refresh_token", refresh_token: refreshToken } }); const { access_token, refresh_token } = resp.body; this.accessToken = access_token; this.refreshToken = refresh_token; return resp.body; } preprocessParam(param) { if ((param == null ? void 0 : param.fields) && Array.isArray(param.fields)) { param.fields = param.fields.join(","); } return param; } /** * Do HTTP GET stuffs. * * @param resource Url to call * @param param Parameter body */ async get(resource, param) { param = this.preprocessParam(param); const response = await this.got.get(resource, { searchParams: param }); return response.body; } /** * Do HTTP POST stuffs. * * @param resource Url to call * @param param Parameter body */ async post(resource, param) { param = this.preprocessParam(param); const response = await this.got.post(resource, { form: param }); return response.body; } /** * Do HTTP PATCH stuffs. * * @param resource Url to call * @param param Parameter body */ async patch(resource, param) { param = this.preprocessParam(param); const response = await this.got.patch(resource, { form: param }); return response.body; } /** * Do HTTP DELETE stuffs. * * @param resource Url to call * @param param Parameter body (discouraged) */ async delete(resource) { const response = await this.got.delete(resource); return response.body; } }; exports.MALClient = MALClient; //# sourceMappingURL=index.cjs.map //# sourceMappingURL=index.cjs.map