UNPKG

crunchyroll-js-api

Version:
1,558 lines (1,375 loc) 127 kB
/******/ var __webpack_modules__ = ({ /***/ "./src/config.js": /*!***********************!*\ !*** ./src/config.js ***! \***********************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ production: 'cr-production', vilo: 'https://static.crunchyroll.com/vilos', clientId: 'xunihvedbt3mbisuhevt', clientSecret: '1kIS5dyTvjE0_rqaA3YeAh0bUXUmxW11', clientIdSso: 'ltccxd10yl6cqcn1acx1', url: 'https://www.crunchyroll.com', urlBeta: 'https://beta-api.crunchyroll.com', urlSso: 'https://sso.crunchyroll.com', urlStatic: 'https://static.crunchyroll.com', urlDrm: 'https://cr-play-service.prd.crunchyrollsvc.com', urlPl: 'https://pl.crunchyroll.com', urlLicense: 'https://cr-license-proxy.prd.crunchyrollsvc.com', accountingId: 'crunchyroll', castId: '4D84B31C', urlEec: 'https://eec.crunchyroll.com', appConfig: 'app-config-default-production.json', versionName: '3.70.4', appId: 'cr-android', osReleaseVersion: '13', contentTypes: ['series', 'movie_listing', 'episode'], sortByValues: ['popularity', 'newly_added', 'alphabetical'], ratingContentTypes: ['1s', '2s', '3s', '4s', '5s'], ratingEpisodeTypes: ['up', 'down'], }); /***/ }), /***/ "./src/error.js": /*!**********************!*\ !*** ./src/error.js ***! \**********************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /** * Class to handel custom errors */ class CrunchyrollError extends Error { constructor(message, code = null, context = null, status = null, statusText = null) { super(message) this.code = code this.context = context this.httpStatus = status this.httpStatusText = statusText Object.setPrototypeOf(this, CrunchyrollError.prototype) } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (CrunchyrollError); /***/ }), /***/ "./src/localStore.js": /*!***************************!*\ !*** ./src/localStore.js ***! \***************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./utils.js */ "./src/utils.js"); /* harmony import */ var _services_auth_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./services/auth.js */ "./src/services/auth.js"); /* harmony import */ var _services_index_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./services/index.js */ "./src/services/index.js"); /* harmony import */ var _services_account_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./services/account.js */ "./src/services/account.js"); /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./error.js */ "./src/error.js"); /** @type {import('./types.js').Storage} */ const storage = { credential: null, device: null, token: null, cms: null, account: null } /** * @type {Function} * @param {Object} data */ let externalSaveData = null /** * @type {Function} * @returns {Object} */ let externalLoadData = null /** * @param {Object} jsonData * @returns {Object} */ function fromJSON(jsonData) { return swapObjectJson(jsonData, _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toCamel) } /** * @param {Object} jsonData * @returns {Object} */ function toJSON(jsonData) { return swapObjectJson(jsonData, _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toSnake) } /** * @param {Object} [data] * @returns {Promise} */ async function saveToken(data) { if (data) { storage.token = fromJSON(data) storage.token.token = `${storage.token.tokenType} ${storage.token.accessToken}` } else { storage.token = null } await saveToLocal() } /** * @returns {Promise<String>} */ async function getAuthToken() { let tokenObj = null if (storage.token && storage.token.accessToken) { const now = new Date() const diff = (now.getTime() - (new Date(storage.token.createdDate)).getTime()) / 1000 if (diff < (storage.token.expiresIn - 5)) { tokenObj = storage.token } } if (!tokenObj) { let data = null if (storage.token && storage.token.refreshToken) { data = await _services_auth_js__WEBPACK_IMPORTED_MODULE_1__["default"].getRefreshToken({ ...storage.token, device: storage.device }) } else if (storage.credential) { data = await _services_auth_js__WEBPACK_IMPORTED_MODULE_1__["default"].getToken({ ...storage.credential, device: storage.device }) } await saveToken(data) tokenObj = storage.token } if (!tokenObj) { throw new _error_js__WEBPACK_IMPORTED_MODULE_4__["default"]('No auth token found.') } return tokenObj.token } /** * @param {String} profileId * @returns {Promise<import('./types').TokenObj>} */ async function switchProfile(profileId) { const data = await _services_auth_js__WEBPACK_IMPORTED_MODULE_1__["default"].switchProfile({ ...storage.token, device: storage.device, profileId }) await saveToken(data) return storage.token } /** * @returns {Promise<import('./types').TokenObj>} */ async function getToken() { await getAuthToken() return storage.token } /** * @returns {Promise} */ async function revokeToken() { if (storage.token) { await _services_auth_js__WEBPACK_IMPORTED_MODULE_1__["default"].revokeRefreshToken(storage.token) } storage.token = null await saveToLocal() } /** * @returns {Promise<import('./types').CmsObj>} */ async function getCms() { let cms = null if (storage.cms && storage.cms.bucket) { const now = new Date() if (new Date(storage.cms.expires) > now) { cms = storage.cms } } if (!cms) { cms = await _services_index_js__WEBPACK_IMPORTED_MODULE_2__["default"].getIndexConfig({ token: await getAuthToken() }) storage.cms = fromJSON(cms.cms) cms = storage.cms await saveToLocal() } return cms } /** * @returns {Promise<import('./types').AccountObj>} */ async function getAccount() { if (!storage.account || !storage.account.accountId) { const account = await _services_account_js__WEBPACK_IMPORTED_MODULE_3__["default"].getAccountId({ token: await getAuthToken() }) storage.account = fromJSON(account) await saveToLocal() } return storage.account } /** * Return basic params to query api * @param {import('./types').Profile} profile * @returns {Promise<import('./types').AccountAuth>} */ async function getContentParam(profile) { const tokenObj = await getToken() return { ...tokenObj, locale: profile.preferred_communication_language, audioLanguage: profile.preferred_content_audio_language, } } /** * @todo maybe add a extra field to save locale, and return profile.preferredContentSubtitleLanguage too */ async function getLocale() { return 'es-419' } /** * Load from persistence data * @returns {Promise} */ async function loadFromLocal() { let data = null const authData = await authDataFile() try { if (externalLoadData) { data = await externalLoadData() } else { const data64 = window.localStorage.getItem(authData) if (data64) { data = atob(data64) } } } catch (_e) { // #if process.env.NODE_COMPILING !== 'true' // const fs = (await import('fs')).default // if (fs.existsSync(authData)) { // data = fs.readFileSync(authData, 'utf-8') // } // #endif } if (data) { const jsonData = JSON.parse(data) Object.assign(storage, fromJSON(jsonData)) } } /** * Save to persistence data * @returns {Promise} */ async function saveToLocal() { const authData = await authDataFile() const data = JSON.stringify(toJSON(storage), null, '\t') try { if (externalSaveData) { await externalSaveData(data) } else { window.localStorage.setItem(authData, btoa(data)) } } catch (_e) { // #if process.env.NODE_COMPILING !== 'true' // const fs = (await import('fs')).default // fs.writeFileSync(authData, data) // #endif } } /** * @param {Object} jsonData * @param {Function} func * @returns {Object} */ function swapObjectJson(jsonData, func) { let out if (jsonData) { if (Array.isArray(jsonData)) { out = [] for (const item of jsonData) { out.push(swapObjectJson(item, func)) } } else if (typeof jsonData === 'object' || Object.prototype.isPrototypeOf.call(jsonData, Object)) { out = {} for (const key of Object.keys(jsonData)) { out[func(key)] = swapObjectJson(jsonData[key], func) } } else { out = jsonData } } else { out = jsonData } return out } /** * Disk file with credential data * @returns {Promise<String>} */ async function authDataFile() { let out = 'crunchyData' // #if process.env.NODE_COMPILING !== 'true' // const path = (await import('path')).default // out = path.resolve('.') + '/authData.json' // #endif return out } /** * Set function to save and load data from external storage * @param {{save: Function, load: Function}} obj */ function setExternalStorage({ save, load }) { if (load !== undefined) { externalLoadData = load } if (save !== undefined) { externalSaveData = save } } /** * Set credentials of an account * @param {Storage} newData * @returns {Promise} */ async function setNewData(newData) { Object.assign(storage, newData) await saveToLocal() } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ storage, getAuthToken, getToken, getLocale, getCms, getContentParam, loadFromLocal, saveToLocal, authDataFile, getAccount, saveToken, setExternalStorage, setNewData, switchProfile, revokeToken, }); /***/ }), /***/ "./src/logger.js": /*!***********************!*\ !*** ./src/logger.js ***! \***********************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); let LEVEL = 'info', COLOR_ACTIVE = true if (process && process.env && process.env.LOG_LEVEL) { LEVEL = process.env.LOG_LEVEL } /** @type {{ info: Function, error: Function, debug: Function, setLevel: Function, activeColor: Function, }} */ const logger = { info: () => { }, error: () => { }, debug: () => { }, setLevel: () => { }, /** * @param {Boolean} active */ activeColor: active => { COLOR_ACTIVE = active }, } if (!console.debug) { console.debug = console.log } if (!console.info) { console.info = console.log } if (!console.error) { console.error = console.log } /** * @param {Object} obj */ const formatObj = obj => { let extra = '' const keys = Object.keys(obj) if (keys.length) { if (keys.length === 2 && keys.includes('message') && keys.includes('stack')) { /** @type {Error} */ const err = obj extra = `\n message:${err.name}\n stack:${err.stack}` } else { extra = '\n' + JSON.stringify(obj, null, ' ') } } else if (obj instanceof Error) { extra = `\n message:${obj.name}\n stack:${obj.stack}` } else if (obj instanceof Set) { extra = '[' + Array.from(obj).toString() + ']' } return extra } const colors = { debug: '\x1b[33m', info: '\x1b[32m', error: '\x1b[31m', reset: '\x1b[0m' } /** * @param {any} message * @param {String} level */ const getMessage = (message, level) => { if (!(typeof (message) === 'string' || message instanceof String)) { message = formatObj(message) } const error = new Error(); /** @type {String} */ const callerFile = error.stack.split('\n')[3] let color = colors[level], resetColor = colors['reset'] if (!COLOR_ACTIVE) { color = resetColor = '' } const date = new Date().toISOString() return `${date} ${color}${level.toUpperCase()} ${message} ${(callerFile || '').trim()} ${resetColor}` } /** * @param {String} newLevel */ function configBrowserLogger(newLevel) { if (!newLevel) { newLevel = LEVEL } logger.debug = () => { } logger.info = () => { } logger.error = () => { } /*eslint-disable */ switch (newLevel) { case 'silent': break; case 'debug': logger.debug = msg => { console.debug(getMessage(msg, 'debug')) }; case 'info': logger.info = msg => { console.info(getMessage(msg, 'info')) }; case 'error': logger.error = msg => { console.error(getMessage(msg, 'error')) }; break; } return logger } logger.setLevel = configBrowserLogger logger.setLevel() /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (logger); /***/ }), /***/ "./src/services/account.js": /*!*********************************!*\ !*** ./src/services/account.js ***! \*********************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils.js */ "./src/utils.js"); /* harmony import */ var _logger_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../logger.js */ "./src/logger.js"); /** * Return account info * @param {Object} obj * @param {String} obj.token * @returns {Promise<import('../types').Account>} */ async function getAccountId({ token }) { const fnName = 'getAccountId' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `/accounts/v1/me` const reqConfig = { method: 'get', headers: { Authorization: token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * Return profile info * @deprecated * @param {Object} obj * @param {String} obj.token * @returns {Promise<import('../types').Profile>} */ async function getProfile({ token }) { const fnName = 'getProfile' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `/accounts/v1/me/profile` const reqConfig = { method: 'get', headers: { Authorization: token }, } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * Return user names, idk what it is * @param {Object} obj * @param {String} obj.token * @returns {Promise<{usernames: Array<String>}>} */ async function getUsernames({ token }) { const fnName = 'getAccountId' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `/accounts/v1/usernames` const reqConfig = { method: 'get', headers: { Authorization: token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * Update profile * @param {Object} obj * @param {String} obj.token * @param {import('../types').Profile} obj.data * @returns {Promise} */ async function updateProfile({ token, data }) { const fnName = 'updateProfile' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `/accounts/v1/me/profile` const reqConfig = { method: 'patch', headers: { Authorization: token, 'Content-Type': 'application/json', }, body: JSON.stringify(data), } // @ts-expect-error await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * Update profile * @param {Object} obj * @param {String} obj.token * @param {import('../types').ProfileCreate} obj.data * @returns {Promise} */ async function createMultiProfile({ token, data }) { const fnName = 'createMultiProfile' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `/accounts/v1/me/multiprofile` const reqConfig = { method: 'post', headers: { Authorization: token, 'Content-Type': 'application/json', }, body: JSON.stringify(data), } // @ts-expect-error await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * Delete profile * @param {Object} obj * @param {String} obj.token * @param {String} obj.profileId * @returns {Promise} */ async function deleteMultiProfile({ token, profileId }) { const fnName = 'deleteMultiProfile' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `/accounts/v1/me/multiprofile/${profileId}` const reqConfig = { method: 'delete', headers: { Authorization: token, 'Content-Type': 'application/json', }, } // @ts-expect-error await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * Return profile info * @param {Object} obj * @param {String} obj.token * @returns {Promise<import('../types').ProfileResponse>} */ async function getMultiProfiles({ token }) { const fnName = 'getMultiProfiles' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `/accounts/v1/me/multiprofile` const reqConfig = { method: 'get', headers: { Authorization: token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * Update profile * @param {Object} obj * @param {String} obj.token * @param {import('../types').Profile} obj.data * @param {String} obj.profileId * @returns {Promise} */ async function updateMultiProfile({ token, data, profileId }) { const fnName = 'updateMultiProfile' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `/accounts/v1/me/multiprofile/${profileId}` const reqConfig = { method: 'patch', headers: { Authorization: token, 'Content-Type': 'application/json', }, body: JSON.stringify(data), } // @ts-expect-error await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * Return profile info * @param {Object} obj * @param {String} obj.token * @param {String} obj.profileId * @returns {Promise<import('../types').Profile>} */ async function getMultiProfile({ token, profileId }) { const fnName = 'getMultiProfiles' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `/accounts/v1/me/multiprofile/${profileId}` const reqConfig = { method: 'get', headers: { Authorization: token }, } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ createMultiProfile, deleteMultiProfile, getAccountId, getProfile, getMultiProfile, getMultiProfiles, getUsernames, updateProfile, updateMultiProfile }); /***/ }), /***/ "./src/services/assets.js": /*!********************************!*\ !*** ./src/services/assets.js ***! \********************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils.js */ "./src/utils.js"); /* harmony import */ var _logger_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../logger.js */ "./src/logger.js"); /** * Return Avatar list * @param {{token: String, lang: String}} obj * @returns {Promise<{items: Array<import('../types.js').AssesItem>}>} */ async function getAvatar({ token, lang }) { const fnName = 'getAvatar' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `/assets/v2/${lang}/avatar` const reqConfig = { method: 'get', headers: { Authorization: token }, } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * Return Aallpaper list * @param {{token: String, lang: String}} obj * @returns {Promise<{items: Array<import('../types.js').AssesItem>}>} */ async function getWallpaper({ token, lang }) { const fnName = 'getWallpaper' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `/assets/v2/${lang}/wallpaper` const reqConfig = { method: 'get', headers: { Authorization: token }, } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ getAvatar, getWallpaper, }); /***/ }), /***/ "./src/services/auth.js": /*!******************************!*\ !*** ./src/services/auth.js ***! \******************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils.js */ "./src/utils.js"); /* harmony import */ var _logger_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../logger.js */ "./src/logger.js"); /* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../config.js */ "./src/config.js"); /** * Return hardcode credentials to login * @returns {String} */ function getBasicToken() { const credenciales = `${_config_js__WEBPACK_IMPORTED_MODULE_2__["default"].clientId}:${_config_js__WEBPACK_IMPORTED_MODULE_2__["default"].clientSecret}` let buff = Buffer.from(credenciales) let base64data = buff.toString('base64') return base64data } /** * Get device code for easy login * @returns {Promise<import('../types').DeviceCode>} */ async function getDeviceCode() { const fnName = 'getDeviceCode' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const basicToken = getBasicToken() const body = { grant_type: 'client_id' } const url = `/auth/v1/device/code` const reqConfig = { method: 'post', body: await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(body), headers: { Authorization: `Basic ${basicToken}`, 'Content-Type': 'application/x-www-form-urlencoded', 'etp-anonymous-id': null, }, } // @ts-expect-error const token = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) if (token) { token.created_date = new Date().toISOString() } return token } /** * Get access token from device code * @param {Object} obj * @param {import('../types.js').Device} obj.device Device * @param {String} obj.deviceCode login type * @returns {Promise<import('../types').Token>} */ async function getDeviceAuth({ device, deviceCode }) { const fnName = 'getDeviceAuth' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const basicToken = getBasicToken() const body = { device_id: device.id, device_name: device.name, device_type: device.type, device_code: deviceCode, } const url = `/auth/v1/device/token` const reqConfig = { method: 'post', body: JSON.stringify(body), headers: { Authorization: `Basic ${basicToken}`, 'Content-Type': 'application/json', }, } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * Make out system login * @param {Object} obj * @param {import('../types.js').Device} obj.device Device * @param {Object} obj.credentials login type * @param {String} obj.grantType login type * @param {String} [obj.scope] * @returns {Promise<import('../types').Token>} */ async function _makeLogin({ device, credentials, grantType, scope }) { const fnName = '_makeLogin' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const basicToken = getBasicToken() const body = { grant_type: grantType, scope: scope || 'offline_access', device_id: device.id, device_name: device.name, device_type: device.type, ...credentials, } const url = `/auth/v1/token` const reqConfig = { method: 'post', body: await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(body), headers: { Authorization: `Basic ${basicToken}`, 'Content-Type': 'application/x-www-form-urlencoded', 'ETP-Anonymous-ID': null, }, } // @ts-expect-error const token = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) if (token) { token.created_date = new Date().toISOString() } return token } /** * Make out system login * @param {Object} obj * @param {import('../types.js').Device} obj.device Device * @param {String} [obj.scope] * @param {String} obj.username user's email * @param {String} obj.password user's password * @returns {Promise<import('../types').Token>} */ async function getToken({ device, scope, username, password }) { const fnName = 'getToken' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) return _makeLogin({ device, scope, grantType: 'password', credentials: { username, password }, }) } /** * Make out system login * @param {Object} obj * @param {import('../types.js').Device} obj.device Device * @param {String} [obj.scope] * @param {String} obj.phone user's phone * @param {String} obj.verification_code * @returns {Promise<import('../types').Token>} */ async function getTokenWithPhone({ device, scope, phone, verification_code }) { const fnName = 'getTokenWithPhone' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) return _makeLogin({ device, scope, grantType: 'phone', credentials: { phone_number: phone, verification_code }, }) } /** * Make out system login * @param {Object} obj * @param {import('../types.js').Device} obj.device Device * @param {String} [obj.scope] * @param {String} obj.code * @param {String} obj.code_verifier * @returns {Promise<import('../types').Token>} */ async function getTokenWithCode({ device, scope, code, code_verifier }) { const fnName = 'getTokenWithCode' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) return _makeLogin({ device, scope, grantType: 'authorization_code', credentials: { code, code_verifier: code_verifier }, }) } /** * Refresh access token. * @param {Object} obj * @param {import('../types.js').Device} obj.device Device * @param {String} [obj.scope] * @param {String} obj.refreshToken refresh token from login * @returns {Promise<import('../types').Token>} */ async function getRefreshToken({ device, scope, refreshToken }) { const fnName = 'getRefreshToken' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) return _makeLogin({ device, scope, grantType: 'refresh_token', credentials: { refresh_token: refreshToken }, }) } /** * Switch profile * @param {Object} obj * @param {import('../types.js').Device} obj.device Device * @param {String} [obj.scope] * @param {String} obj.refreshToken refresh token from login * @param {String} obj.profileId profile id for switch * @returns {Promise<import('../types').Token>} */ async function switchProfile({ device, scope, refreshToken, profileId }) { const fnName = 'switchProfile' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) return _makeLogin({ device, scope, grantType: 'refresh_token_profile_id', credentials: { refresh_token: refreshToken, profile_id: profileId }, }) } /** * revoke access token. * @param {{refreshToken: String}} obj * @returns {Promise<{status: String}>} */ async function revokeRefreshToken({ refreshToken }) { const fnName = 'revokeRefreshToken' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const basicToken = getBasicToken() const body = { token: refreshToken } const url = `/auth/v1/revoke` const reqConfig = { method: 'post', body: await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(body), headers: { Authorization: `Basic ${basicToken}`, 'Content-Type': 'application/x-www-form-urlencoded', 'ETP-Anonymous-ID': null, }, } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ getDeviceCode, getDeviceAuth, getToken, getTokenWithPhone, getTokenWithCode, getRefreshToken, revokeRefreshToken, switchProfile, }); /***/ }), /***/ "./src/services/cms.js": /*!*****************************!*\ !*** ./src/services/cms.js ***! \*****************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils.js */ "./src/utils.js"); /* harmony import */ var _logger_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../logger.js */ "./src/logger.js"); /* harmony import */ var _config_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../config.js */ "./src/config.js"); /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.episodeId * @returns {Promise<Object>} */ async function getEpisode({ account, episodeId }) { const fnName = 'getEpisode' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/episodes/${episodeId}?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.seasonId * @returns {Promise<Object>} */ async function getEpisodes({ account, seasonId }) { const fnName = 'getEpisodes' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/seasons/${seasonId}/episodes?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.movieId * @returns {Promise<Object>} */ async function getMovie({ account, movieId }) { const fnName = 'getMovie' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/movies/${movieId}?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.movieListingId * @returns {Promise<Object>} */ async function getMovieListing({ account, movieListingId }) { const fnName = 'getMovieListing' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/movie_listings/${movieListingId}?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.movieListingId * @returns {Promise<Object>} */ async function getMovieListingExtras({ account, movieListingId }) { const fnName = 'getMovieListingExtras' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/movie_listings/${movieListingId}/extra_videos?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.movieListingId * @returns {Promise<Object>} */ async function getMovies({ account, movieListingId }) { const fnName = 'getMovies' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/movie_listings/${movieListingId}/movies?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {Array<String>} obj.objectIds * @param {Boolean} obj.ratings * @returns {Promise<{total: Number, data: Array<Object>, meta: Object}>} */ async function getObjects({ account, objectIds, ratings }) { const fnName = 'getObjects' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].addParam(queryData, 'ratings', ratings) const query = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/objects/${objectIds.join(',')}?${query}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.seasonId * @returns {Promise<Object>} */ async function getSeason({ account, seasonId }) { const fnName = 'getSeason' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/seasons/${seasonId}?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.seasonId * @returns {Promise<Object>} */ async function getSeasonExtras({ account, seasonId }) { const fnName = 'getSeasonExtras' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/seasons/${seasonId}/extra_videos?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.serieId * @returns {Promise<Object>} */ async function getSeasons({ account, serieId }) { const fnName = 'getSeasons' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/series/${serieId}/seasons?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.serieId * @returns {Promise<Object>} */ async function getSeries({ account, serieId }) { const fnName = 'getSeries' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/series/${serieId}?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @deprecated * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.streamUrl * @returns {Promise<Object>} */ async function getStreamsWithURL({ account, streamUrl }) { const fnName = 'getStreamsWithURL' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `${streamUrl}?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @deprecated * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.contentId * @returns {Promise<Object>} */ async function getStreams({ account, contentId }) { const fnName = 'getStreams' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/cms/videos/${contentId}/streams?${queryStr}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.contentId * @returns {Promise<Object>} */ async function getSkiptEvents({ account, contentId }) { const fnName = 'getSkiptEvents' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const url = `${_config_js__WEBPACK_IMPORTED_MODULE_2__["default"].urlStatic}/skip-events/production/${contentId}.json` const reqConfig = { method: 'get', headers: { Authorization: account.token }, baseUrlIncluded: true, } let out = null try { // @ts-expect-error out = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } catch (e) { // ignore any error } return out } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ getEpisode, getEpisodes, getMovie, getMovieListing, getMovieListingExtras, getMovies, getObjects, getSeason, getSeasonExtras, getSeasons, getSeries, getStreamsWithURL, getStreams, getSkiptEvents, }); /***/ }), /***/ "./src/services/content.js": /*!*********************************!*\ !*** ./src/services/content.js ***! \*********************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../utils.js */ "./src/utils.js"); /* harmony import */ var _logger_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../logger.js */ "./src/logger.js"); /* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../error.js */ "./src/error.js"); /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.listId * @param {String} obj.contentId * @returns {Promise} */ async function addItemToCustomList({ account, listId, contentId }) { const fnName = 'addItemToCustomList' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/${account.accountId}/custom-lists/${listId}?${queryStr}` const reqConfig = { method: 'post', headers: { Authorization: account.token, 'Content-Type': 'application/json', }, body: JSON.stringify({ content_id: contentId }) } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.listId * @param {String} obj.contentId * @param {String} obj.location * @param {String} obj.refContentId * @returns {Promise} */ async function changeCustomListItemPosition({ account, listId, contentId, location, refContentId }) { const fnName = 'changeCustomListItemPosition' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/${account.accountId}/custom-lists/${listId}/${contentId}/position?${queryStr}` if (!['after', 'before'].includes(location)) { throw new _error_js__WEBPACK_IMPORTED_MODULE_2__["default"](`Wrong location`) } const reqConfig = { method: 'put', headers: { Authorization: account.token, 'Content-Type': 'application/json', }, body: JSON.stringify({ location: location, ref_content_id: refContentId }) } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.listId * @param {String} [obj.page] * @param {String} [obj.pageSize] * @param {String} [obj.sort] manual, date_added * @param {String} [obj.order] asc, desc * @returns {Promise<Object>} */ async function getCustomListItems({ account, listId, page, pageSize, sort, order }) { const fnName = 'getCustomListItems' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].addParam(queryData, 'page', page) _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].addParam(queryData, 'page_size', pageSize) if (sort && !['manual', 'date_added'].includes(sort)) { throw new _error_js__WEBPACK_IMPORTED_MODULE_2__["default"]('Wrong sort value') } _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].addParam(queryData, 'sort_by', sort) if (order && !['asc', 'desc'].includes(order)) { throw new _error_js__WEBPACK_IMPORTED_MODULE_2__["default"]('Wrong order value') } _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].addParam(queryData, 'order', order) const query = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/${account.accountId}/custom-lists/${listId}?${query}` const reqConfig = { method: 'get', headers: { Authorization: account.token } } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.listId * @param {String} obj.contentId * @returns {Promise} */ async function deleteCustomListItem({ account, listId, contentId }) { const fnName = 'deleteCustomListItem' _logger_js__WEBPACK_IMPORTED_MODULE_1__["default"].debug(fnName) const queryData = { locale: account.locale, preferred_audio_language: account.audioLanguage } const queryStr = await _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].toURLSearchParams(queryData) const url = `/content/v2/${account.accountId}/custom-lists/${listId}/${contentId}?${queryStr}` const reqConfig = { method: 'delete', headers: { Authorization: account.token, 'Content-Type': 'application/json', }, } // @ts-expect-error return _utils_js__WEBPACK_IMPORTED_MODULE_0__["default"].makeRequest(fnName, url, reqConfig) } /** * @param {Object} obj * @param {import('../types').AccountAuth} obj.account * @param {String} obj.title * @returns {Promise<{data: Array<import('../types').CustomListResponse>}>} */ async function createPrivateCustomList({ account, title }) { const fnName = 'c