From e035e6bde4f0ea6f50e878e8ab9fbea59b1daf1b Mon Sep 17 00:00:00 2001 From: SrGooglo Date: Sat, 10 May 2025 02:35:38 +0000 Subject: [PATCH] Revamp Music API, add E2E, update Spectrum and User Music model: new method structure, updated API endpoints (tracks, releases, lyrics, library). E2E (wip): new model for encryption key pair management. Spectrum: updated API to support new spectrum api. User: added public key management. Session, Auth, Radio: minor API enhancements. --- src/index.js | 1 - src/models/auth/index.js | 2 +- src/models/e2e/index.js | 30 ++ src/models/music/getters/featuredPlaylists.ts | 11 - src/models/music/getters/isItemFavorited.js | 25 ++ src/models/music/getters/isItemFavourited.js | 33 --- .../{favouriteFolder.js => library.js} | 32 +- src/models/music/getters/myReleases.ts | 36 +-- src/models/music/getters/playlistData.ts | 11 - src/models/music/getters/playlistItem.ts | 11 - src/models/music/getters/playlists.ts | 29 -- src/models/music/getters/releases.ts | 39 +-- src/models/music/getters/trackLyrics.ts | 36 +-- src/models/music/getters/tracks.ts | 39 +-- src/models/music/index.js | 169 ++--------- src/models/music/setters/putTrackLyrics.js | 16 +- .../music/setters/toggleItemFavorite.js | 26 ++ .../music/setters/toggleItemFavourite.js | 36 --- src/models/radio/getters/trendings.js | 10 + src/models/radio/index.js | 2 + src/models/session/index.js | 277 +++++++++--------- src/models/spectrum/index.js | 80 ++++- src/models/user/index.js | 35 ++- 23 files changed, 453 insertions(+), 533 deletions(-) create mode 100644 src/models/e2e/index.js delete mode 100644 src/models/music/getters/featuredPlaylists.ts create mode 100644 src/models/music/getters/isItemFavorited.js delete mode 100644 src/models/music/getters/isItemFavourited.js rename src/models/music/getters/{favouriteFolder.js => library.js} (58%) delete mode 100644 src/models/music/getters/playlistData.ts delete mode 100644 src/models/music/getters/playlistItem.ts delete mode 100644 src/models/music/getters/playlists.ts create mode 100644 src/models/music/setters/toggleItemFavorite.js delete mode 100644 src/models/music/setters/toggleItemFavourite.js create mode 100644 src/models/radio/getters/trendings.js diff --git a/src/index.js b/src/index.js index c9778b9..fa02a77 100755 --- a/src/index.js +++ b/src/index.js @@ -42,7 +42,6 @@ export function createClient({ mainOrigin: origin, baseRequest: null, ws: null, - rest: null, version: pkg.version, addons: new AddonsManager(), }) diff --git a/src/models/auth/index.js b/src/models/auth/index.js index 7abcd9a..11fbd73 100755 --- a/src/models/auth/index.js +++ b/src/models/auth/index.js @@ -35,7 +35,7 @@ export default class AuthModel { SessionModel.refreshToken = response.data.refreshToken if (typeof callback === "function") { - await callback() + await callback(response.data) } __comty_shared_state.eventBus.emit("auth:login_success") diff --git a/src/models/e2e/index.js b/src/models/e2e/index.js new file mode 100644 index 0000000..817673d --- /dev/null +++ b/src/models/e2e/index.js @@ -0,0 +1,30 @@ +import SessionModel from "../session" +import request from "../../request" + +export default class E2EModel { + static async getKeyPair() { + const response = await request({ + method: "GET", + url: "/users/self/keypair", + }) + + return response.data + } + + // WARNING: updating keypair makes all decryption fail + static async updateKeyPair(str, { imSure = false } = {}) { + if (imSure !== true) { + throw new Error( + "Missing confirmation to update the keypair. Use `imSure = true` to proceed.", + ) + } + + const response = await request({ + method: "POST", + url: "/users/self/keypair", + data: { str: str }, + }) + + return response.data + } +} diff --git a/src/models/music/getters/featuredPlaylists.ts b/src/models/music/getters/featuredPlaylists.ts deleted file mode 100644 index 6cbf0c7..0000000 --- a/src/models/music/getters/featuredPlaylists.ts +++ /dev/null @@ -1,11 +0,0 @@ -import request from "../../../request" - -export default async () => { - const response = await request({ - method: "GET", - url: "/music/playlists/featured", - }) - - // @ts-ignore - return response.data -} \ No newline at end of file diff --git a/src/models/music/getters/isItemFavorited.js b/src/models/music/getters/isItemFavorited.js new file mode 100644 index 0000000..f2ae2a7 --- /dev/null +++ b/src/models/music/getters/isItemFavorited.js @@ -0,0 +1,25 @@ +import request from "../../../request" + +export default async (type, item_id) => { + if (!type) { + throw new Error("type is required") + } + + if (!item_id) { + throw new Error("item_id is required") + } + + type = type.toLowerCase() + + const response = await request({ + method: "GET", + url: `/music/my/library/favorite`, + params: { + kind: type, + item_id: item_id, + }, + }) + + // @ts-ignore + return response.data +} diff --git a/src/models/music/getters/isItemFavourited.js b/src/models/music/getters/isItemFavourited.js deleted file mode 100644 index 4278b72..0000000 --- a/src/models/music/getters/isItemFavourited.js +++ /dev/null @@ -1,33 +0,0 @@ -import request from "../../../request" - -const typeToNamespace = { - track: "tracks", - //playlist: "playlists", - //release: "releases", -} - -export default async (type, track_id) => { - if (!type) { - throw new Error("type is required") - } - - if (!track_id) { - throw new Error("track_id is required") - } - - type = type.toLowerCase() - - type = typeToNamespace[type] - - if (!type) { - throw new Error(`Unsupported type: ${type}`) - } - - const response = await request({ - method: "GET", - url: `/music/${type}/${track_id}/is_favourite`, - }) - - // @ts-ignore - return response.data -} \ No newline at end of file diff --git a/src/models/music/getters/favouriteFolder.js b/src/models/music/getters/library.js similarity index 58% rename from src/models/music/getters/favouriteFolder.js rename to src/models/music/getters/library.js index 269063a..9d24fa0 100644 --- a/src/models/music/getters/favouriteFolder.js +++ b/src/models/music/getters/library.js @@ -2,24 +2,24 @@ import request from "../../../request" import processAddons from "../../../helpers/processWithAddons" import standartListMerge from "../../../utils/standartListMerge" -export default async ({ limit = 100, offset = 0, order = "desc" }) => { - const addons = - __comty_shared_state.addons.getByOperation("getFavoriteFolder") +export default async ({ limit = 100, offset = 0, order = "desc", kind }) => { + const addons = __comty_shared_state.addons.getByOperation("getMyLibrary") const dividedLimit = limit / (addons.length + 1) const { data } = await request({ method: "GET", - url: "/music/my/folder", + url: "/music/my/library", params: { limit: dividedLimit, offset: offset, order: order, + kind: kind, }, }) let results = await processAddons({ - operation: "getFavoriteFolder", + operation: "getMyLibrary", initialData: data, fnArguments: [{ limit: dividedLimit, offset: offset, order: order }], normalizeAddonResult: ({ currentData, addonResult }) => { @@ -27,16 +27,18 @@ export default async ({ limit = 100, offset = 0, order = "desc" }) => { }, }) - // sort by liked_at - results.tracks.items.sort((a, b) => { - if (a.liked_at > b.liked_at) { - return -1 - } - if (a.liked_at < b.liked_at) { - return 1 - } - return 0 - }) + // sort tracks by liked_at + if (results.tracks) { + results.tracks.items.sort((a, b) => { + if (a.liked_at > b.liked_at) { + return -1 + } + if (a.liked_at < b.liked_at) { + return 1 + } + return 0 + }) + } return results } diff --git a/src/models/music/getters/myReleases.ts b/src/models/music/getters/myReleases.ts index 999a4bc..9d35799 100644 --- a/src/models/music/getters/myReleases.ts +++ b/src/models/music/getters/myReleases.ts @@ -1,26 +1,22 @@ import request from "../../../request" type Arguments = { - limit: Number - offset: Number - keywords: String + limit: Number + offset: Number + keywords: String } -export default async ({ - limit, - offset, - keywords, -}: Arguments) => { - const response = await request({ - method: "GET", - url: "/music/releases/self", - params: { - limit: limit, - offset: offset, - keywords: keywords, - } - }) +export default async ({ limit, offset, keywords }: Arguments) => { + const response = await request({ + method: "GET", + url: "/music/my/releases", + params: { + limit: limit, + offset: offset, + keywords: keywords, + }, + }) - // @ts-ignore - return response.data -} \ No newline at end of file + // @ts-ignore + return response.data +} diff --git a/src/models/music/getters/playlistData.ts b/src/models/music/getters/playlistData.ts deleted file mode 100644 index 558ba03..0000000 --- a/src/models/music/getters/playlistData.ts +++ /dev/null @@ -1,11 +0,0 @@ -import request from "../../../request" - -export default async (id: String) => { - const response = await request({ - method: "GET", - url: `/music/playlists/${id}/data`, - }) - - // @ts-ignore - return response.data -} \ No newline at end of file diff --git a/src/models/music/getters/playlistItem.ts b/src/models/music/getters/playlistItem.ts deleted file mode 100644 index f36a3f7..0000000 --- a/src/models/music/getters/playlistItem.ts +++ /dev/null @@ -1,11 +0,0 @@ -import request from "../../../request" - -export default async (id: String) => { - const response = await request({ - method: "GET", - url: `/music/playlists/${id}/items`, - }) - - // @ts-ignore - return response.data -} \ No newline at end of file diff --git a/src/models/music/getters/playlists.ts b/src/models/music/getters/playlists.ts deleted file mode 100644 index 4f71138..0000000 --- a/src/models/music/getters/playlists.ts +++ /dev/null @@ -1,29 +0,0 @@ -import request from "../../../request" - -type Arguments = { - keywords: String - user_id: String - limit: Number - offset: Number -} - -export default async ({ - keywords, - user_id, - limit, - offset, -}: Arguments) => { - const response = await request({ - method: "GET", - url: "/music/playlists", - params: { - keywords: keywords, - user_id: user_id, - limit: limit, - offset: offset, - } - }) - - // @ts-ignore - return response.data -} \ No newline at end of file diff --git a/src/models/music/getters/releases.ts b/src/models/music/getters/releases.ts index 44ed170..c774add 100644 --- a/src/models/music/getters/releases.ts +++ b/src/models/music/getters/releases.ts @@ -1,29 +1,22 @@ import request from "../../../request" type Arguments = { - keywords: String - user_id: String - limit: Number - offset: Number + user_id: String + limit: Number + page: Number } -export default async ({ - keywords, - user_id, - limit, - offset, -}: Arguments) => { - const response = await request({ - method: "GET", - url: "/music/releases", - params: { - keywords: keywords, - user_id: user_id, - limit: limit, - offset: offset, - } - }) +export default async ({ user_id, limit, page }: Arguments) => { + const response = await request({ + method: "GET", + url: "/music/releases", + params: { + user_id: user_id, + limit: limit, + page: page, + }, + }) - // @ts-ignore - return response.data -} \ No newline at end of file + // @ts-ignore + return response.data +} diff --git a/src/models/music/getters/trackLyrics.ts b/src/models/music/getters/trackLyrics.ts index 57dc59e..7ed23e4 100644 --- a/src/models/music/getters/trackLyrics.ts +++ b/src/models/music/getters/trackLyrics.ts @@ -1,31 +1,31 @@ import request from "../../../request" type RequestOptions = { - preferTranslation?: Boolean + preferTranslation?: Boolean } type RequestParams = { - translate_lang?: String + translate_lang?: String } export default async ( - id: String, - options: RequestOptions = { - preferTranslation: false, - } + id: String, + options: RequestOptions = { + preferTranslation: false, + }, ) => { - const requestParams: RequestParams = Object() + const requestParams: RequestParams = Object() - if (options.preferTranslation) { - requestParams.translate_lang = app.cores.settings.get("app:language") - } + if (options.preferTranslation) { + requestParams.translate_lang = app.cores.settings.get("app:language") + } - const response = await request({ - method: "GET", - url: `/music/lyrics/${id}`, - params: requestParams - }) + const response = await request({ + method: "GET", + url: `/music/tracks/${id}/lyrics`, + params: requestParams, + }) - // @ts-ignore - return response.data -} \ No newline at end of file + // @ts-ignore + return response.data +} diff --git a/src/models/music/getters/tracks.ts b/src/models/music/getters/tracks.ts index cf12636..2e0c075 100644 --- a/src/models/music/getters/tracks.ts +++ b/src/models/music/getters/tracks.ts @@ -1,29 +1,22 @@ import request from "../../../request" type Arguments = { - keywords: String - user_id: String - limit: Number - offset: Number + user_id: String + limit: Number + page: Number } -export default async ({ - keywords, - user_id, - limit, - offset, -}: Arguments) => { - const response = await request({ - method: "GET", - url: "/music/tracks", - params: { - keywords: keywords, - user_id: user_id, - limit: limit, - offset: offset, - } - }) +export default async ({ user_id, limit, page }: Arguments) => { + const response = await request({ + method: "GET", + url: "/music/tracks", + params: { + user_id: user_id, + limit: limit, + page: page, + }, + }) - // @ts-ignore - return response.data -} \ No newline at end of file + // @ts-ignore + return response.data +} diff --git a/src/models/music/index.js b/src/models/music/index.js index 12173e5..5052503 100755 --- a/src/models/music/index.js +++ b/src/models/music/index.js @@ -2,150 +2,37 @@ import Getters from "./getters" import Setters from "./setters" export default class MusicModel { - static Getters = Getters - static Setters = Setters + static Getters = Getters + static Setters = Setters - /** - * Performs a search based on the provided keywords, with optional parameters for limiting the number of results and pagination. - * - * @param {string} keywords - The keywords to search for. - * @param {object} options - An optional object containing additional parameters. - * @param {number} options.limit - The maximum number of results to return. Defaults to 5. - * @param {number} options.offset - The offset to start returning results from. Defaults to 0. - * @param {boolean} options.useTidal - Whether to use Tidal for the search. Defaults to false. - * @return {Promise} The search results. - */ - static search = Getters.search + // track related methods + static getMyTracks = null + static getAllTracks = Getters.tracks + static getTrackData = Getters.trackData + static putTrack = Setters.putTrack + static deleteTrack = null - /** - * Retrieves playlist items based on the provided parameters. - * - * @param {Object} options - The options object. - * @param {string} options.playlist_id - The ID of the playlist. - * @param {string} options.service - The service from which to retrieve the playlist items. - * @param {number} options.limit - The maximum number of items to retrieve. - * @param {number} options.offset - The number of items to skip before retrieving. - * @return {Promise} Playlist items data. - */ - static getPlaylistItems = Getters.PlaylistItems + // lyrics related methods + static getTrackLyrics = Getters.trackLyrics + static putTrackLyrics = Setters.putTrackLyrics - /** - * Retrieves playlist data based on the provided parameters. - * - * @param {Object} options - The options object. - * @param {string} options.playlist_id - The ID of the playlist. - * @param {string} options.service - The service to use. - * @param {number} options.limit - The maximum number of items to retrieve. - * @param {number} options.offset - The offset for pagination. - * @return {Promise} Playlist data. - */ - static getPlaylistData = Getters.PlaylistData + // release related methods + static getMyReleases = Getters.myReleases + static getAllReleases = Getters.releases + static getReleaseData = Getters.releaseData + static putRelease = Setters.putRelease + static deleteRelease = Setters.deleteRelease - /** - * Retrieves releases based on the provided parameters. - * If user_id is not provided, it will retrieve self authenticated user releases. - * - * @param {object} options - The options for retrieving releases. - * @param {string} options.user_id - The ID of the user. - * @param {string[]} options.keywords - The keywords to filter releases by. - * @param {number} options.limit - The maximum number of releases to retrieve. - * @param {number} options.offset - The offset for paginated results. - * @return {Promise} - A promise that resolves to the retrieved releases. - */ - static getReleases = Getters.releases + // library related methods + static getMyLibrary = Getters.library + static toggleItemFavorite = Setters.toggleItemFavorite + static isItemFavorited = Getters.isItemFavorited - /** - * Retrieves self releases. - * - * @param {object} options - The options for retrieving my releases. - * @param {number} options.limit - The maximum number of releases to retrieve. - * @param {number} options.offset - The offset for paginated results. - * @return {Promise} - A promise that resolves to the retrieved releases. - */ - static getMyReleases = Getters.myReleases + // other methods + static getRecentyPlayed = Getters.recentlyPlayed + static search = Getters.search - /** - * Retrieves release data by ID. - * - * @param {number} id - The ID of the release. - * @return {Promise} The release data. - */ - static getReleaseData = Getters.releaseData - - /** - * Retrieves track data for a given ID. - * - * @param {string} id - The ID of the track or multiple IDs separated by commas. - * @return {Promise} The track data. - */ - static getTrackData = Getters.trackData - - /** - * Retrieves the official featured playlists. - * - * @return {Promise} The data containing the featured playlists. - */ - static getFeaturedPlaylists = Getters.featuredPlaylists - - /** - * Retrieves track lyrics for a given ID. - * - * @param {string} id - The ID of the track. - * @return {Promise} The track lyrics. - */ - static getTrackLyrics = Getters.trackLyrics - - - static putTrackLyrics = Setters.putTrackLyrics - - /** - * Create or modify a track. - * - * @param {object} TrackManifest - The track manifest. - * @return {Promise} The result track data. - */ - static putTrack = Setters.putTrack - - /** - * Create or modify a release. - * - * @param {object} ReleaseManifest - The release manifest. - * @return {Promise} The result release data. - */ - static putRelease = Setters.putRelease - - /** - * Deletes a release by its ID. - * - * @param {string} id - The ID of the release to delete. - * @return {Promise} - A Promise that resolves to the data returned by the API. - */ - static deleteRelease = Setters.deleteRelease - - /** - * Retrieves the favourite tracks of the current user. - * - * @return {Promise} The favorite tracks data. - */ - static getFavouriteTracks = null - - /** - * Retrieves the favourite tracks/playlists/releases of the current user. - * - * @return {Promise} The favorite playlists data. - */ - static getFavouriteFolder = Getters.favouriteFolder - - /** - * Toggles the favourite status of a track, playlist or folder. - * - * @param {string} track_id - The ID of the track to toggle the favorite status. - * @throws {Error} If the track_id is not provided. - * @return {Promise} The response data after toggling the favorite status. - */ - static toggleItemFavourite = Setters.toggleItemFavourite - - static isItemFavourited = Getters.isItemFavourited - - static getRecentyPlayed = Getters.recentlyPlayed -} \ No newline at end of file + // aliases + static toggleItemFavourite = MusicModel.toggleItemFavorite + static isItemFavourited = MusicModel.isItemFavorited +} diff --git a/src/models/music/setters/putTrackLyrics.js b/src/models/music/setters/putTrackLyrics.js index fdfc19d..ed1a04a 100644 --- a/src/models/music/setters/putTrackLyrics.js +++ b/src/models/music/setters/putTrackLyrics.js @@ -1,12 +1,12 @@ import request from "../../../request" export default async (track_id, data) => { - const response = await request({ - method: "put", - url: `/music/lyrics/${track_id}`, - data: data, - }) + const response = await request({ + method: "put", + url: `/music/tracks/${track_id}/lyrics`, + data: data, + }) - // @ts-ignore - return response.data -} \ No newline at end of file + // @ts-ignore + return response.data +} diff --git a/src/models/music/setters/toggleItemFavorite.js b/src/models/music/setters/toggleItemFavorite.js new file mode 100644 index 0000000..b06d287 --- /dev/null +++ b/src/models/music/setters/toggleItemFavorite.js @@ -0,0 +1,26 @@ +import request from "../../../request" + +export default async (type, item_id, to) => { + if (!type) { + throw new Error("type is required") + } + + if (!item_id) { + throw new Error("item_id is required") + } + + type = type.toLowerCase() + + const response = await request({ + method: "PUT", + url: `/music/my/library/favorite`, + data: { + item_id: item_id, + kind: type, + to: to, + }, + }) + + // @ts-ignore + return response.data +} diff --git a/src/models/music/setters/toggleItemFavourite.js b/src/models/music/setters/toggleItemFavourite.js deleted file mode 100644 index 23d6584..0000000 --- a/src/models/music/setters/toggleItemFavourite.js +++ /dev/null @@ -1,36 +0,0 @@ -import request from "../../../request" - -const typeToNamespace = { - track: "tracks", - //playlist: "playlists", - //release: "releases", -} - -export default async (type, track_id, to) => { - if (!type) { - throw new Error("type is required") - } - - if (!track_id) { - throw new Error("track_id is required") - } - - type = type.toLowerCase() - - type = typeToNamespace[type] - - if (!type) { - throw new Error(`Unsupported type: ${type}`) - } - - const response = await request({ - method: "post", - url: `/music/${type}/${track_id}/favourite`, - data: { - to: to, - } - }) - - // @ts-ignore - return response.data -} \ No newline at end of file diff --git a/src/models/radio/getters/trendings.js b/src/models/radio/getters/trendings.js new file mode 100644 index 0000000..9970930 --- /dev/null +++ b/src/models/radio/getters/trendings.js @@ -0,0 +1,10 @@ +import request from "../../../request" + +export default async () => { + const { data } = await request({ + method: "GET", + url: "/music/radio/trendings", + }) + + return data +} diff --git a/src/models/radio/index.js b/src/models/radio/index.js index fe04939..9e7e5d4 100644 --- a/src/models/radio/index.js +++ b/src/models/radio/index.js @@ -1,5 +1,7 @@ import getRadioList from "./getters/list" +import getTrendings from "./getters/trendings" export default class Radio { static getRadioList = getRadioList + static getTrendings = getTrendings } diff --git a/src/models/session/index.js b/src/models/session/index.js index c15fbbf..8880486 100755 --- a/src/models/session/index.js +++ b/src/models/session/index.js @@ -3,163 +3,168 @@ import request from "../../request" import Storage from "../../helpers/withStorage" export default class Session { - static storageTokenKey = "token" - static storageRefreshTokenKey = "refreshToken" + static storageTokenKey = "token" + static storageRefreshTokenKey = "refreshToken" - /** - * Retrieves the token from the storage engine. - * - * @return {type} description of return value - */ - static get token() { - return Storage.engine.get(this.storageTokenKey) - } + /** + * Retrieves the token from the storage engine. + * + * @return {type} description of return value + */ + static get token() { + return Storage.engine.get(this.storageTokenKey) + } - /** - * Sets the token in the storage engine. - * - * @param {string} token - The token to be set. - * @return {Promise} A promise that resolves when the token is successfully set. - */ - static set token(token) { - return Storage.engine.set(this.storageTokenKey, token) - } + /** + * Sets the token in the storage engine. + * + * @param {string} token - The token to be set. + * @return {Promise} A promise that resolves when the token is successfully set. + */ + static set token(token) { + return Storage.engine.set(this.storageTokenKey, token) + } - /** - * Retrieves the refresh token from the storage engine. - * - * @return {string} The refresh token stored in the storage engine. - */ - static get refreshToken() { - return Storage.engine.get(this.storageRefreshTokenKey) - } + /** + * Retrieves the refresh token from the storage engine. + * + * @return {string} The refresh token stored in the storage engine. + */ + static get refreshToken() { + return Storage.engine.get(this.storageRefreshTokenKey) + } - /** - * Sets the refresh token in the storage engine. - * - * @param {string} token - The refresh token to be set. - * @return {Promise} A promise that resolves when the refresh token is successfully set. - */ - static set refreshToken(token) { - return Storage.engine.set(this.storageRefreshTokenKey, token) - } + /** + * Sets the refresh token in the storage engine. + * + * @param {string} token - The refresh token to be set. + * @return {Promise} A promise that resolves when the refresh token is successfully set. + */ + static set refreshToken(token) { + return Storage.engine.set(this.storageRefreshTokenKey, token) + } - /** - * Retrieves the roles from the decoded token object. - * - * @return {Array|undefined} The roles if they exist, otherwise undefined. - */ - static get roles() { - return this.getDecodedToken()?.roles - } + /** + * Retrieves the roles from the decoded token object. + * + * @return {Array|undefined} The roles if they exist, otherwise undefined. + */ + static get roles() { + return this.getDecodedToken()?.roles + } - /** - * Retrieves the user ID from the decoded token object. - * - * @return {string|undefined} The user ID if it exists, otherwise undefined. - */ - static get user_id() { - return this.getDecodedToken()?.user_id - } + /** + * Retrieves the user ID from the decoded token object. + * + * @return {string|undefined} The user ID if it exists, otherwise undefined. + */ + static get user_id() { + return this.getDecodedToken()?.user_id + } - /** - * Retrieves the session UUID from the decoded token object. - * - * @return {string} The session UUID if it exists, otherwise undefined. - */ - static get session_uuid() { - return this.getDecodedToken()?.session_uuid - } + /** + * Retrieves the session UUID from the decoded token object. + * + * @return {string} The session UUID if it exists, otherwise undefined. + */ + static get session_uuid() { + return this.getDecodedToken()?.session_uuid + } - /** - * Retrieves the decoded token from the session storage. - * - * @return {Object|null} The decoded token object if it exists, otherwise null. - */ - static getDecodedToken() { - const token = this.token + /** + * Retrieves the decoded token from the session storage. + * + * @return {Object|null} The decoded token object if it exists, otherwise null. + */ + static getDecodedToken() { + const token = this.token - return token && jwtDecode(token) - } + return token && jwtDecode(token) + } - /** - * Removes the token from the storage engine. - * - * @return {Promise} A promise that resolves when the token is successfully removed. - */ - static removeToken() { - return Storage.engine.remove(Session.storageTokenKey) - } + /** + * Removes the token from the storage engine. + * + * @return {Promise} A promise that resolves when the token is successfully removed. + */ + static removeToken() { + return Storage.engine.remove(Session.storageTokenKey) + } - /** - * Retrieves all sessions from the server. - * - * @return {Promise} The data of all sessions. - */ - static async getAllSessions() { - const response = await request({ - method: "get", - url: "/sessions/all" - }) + /** + * Retrieves all sessions from the server. + * + * @return {Promise} The data of all sessions. + */ + static async getAllSessions() { + const response = await request({ + method: "get", + url: "/sessions/all", + }) - return response.data - } + return response.data + } - /** - * Retrieves the current session from the server. - * - * @return {Promise} The data of the current session. - */ - static async getCurrentSession() { - const response = await request({ - method: "get", - url: "/sessions/current" - }) + /** + * Retrieves the current session from the server. + * + * @return {Promise} The data of the current session. + */ + static async getCurrentSession() { + const response = await request({ + method: "get", + url: "/sessions/current", + }) - return response.data - } + return response.data + } - /** - * Destroys the current session by deleting it from the server. - * - * @return {Promise} The response data from the server after deleting the session. - */ - static async destroyCurrentSession() { - const token = await Session.token - const session = await Session.getDecodedToken() + /** + * Destroys the current session by deleting it from the server. + * + * @return {Promise} The response data from the server after deleting the session. + */ + static async destroyCurrentSession() { + const token = await Session.token + const session = await Session.getDecodedToken() - if (!session || !token) { - return false - } + if (!session || !token) { + return false + } - const response = await request({ - method: "delete", - url: "/sessions/current" - }).catch((error) => { - console.error(error) + const response = await request({ + method: "delete", + url: "/sessions/current", + }).catch((error) => { + console.error(error) - return false - }) + return false + }) - Session.removeToken() + Session.removeToken() - __comty_shared_state.eventBus.emit("session.destroyed") + __comty_shared_state.eventBus.emit("session.destroyed") - return response.data - } + return response.data + } - static async destroyAllSessions() { - throw new Error("Not implemented") - } + static async destroyAll() { + const response = await request({ + method: "delete", + url: "/sessions/all", + }) - /** - * Retrieves the validity of the current token. - * - * @return {boolean} The validity status of the current token. - */ - static async isCurrentTokenValid() { - const health = await Session.getTokenValidation() + return response.data + } - return health.valid - } -} \ No newline at end of file + /** + * Retrieves the validity of the current token. + * + * @return {boolean} The validity status of the current token. + */ + static async isCurrentTokenValid() { + const health = await Session.getTokenValidation() + + return health.valid + } +} diff --git a/src/models/spectrum/index.js b/src/models/spectrum/index.js index 2110a9b..9304fe6 100644 --- a/src/models/spectrum/index.js +++ b/src/models/spectrum/index.js @@ -1,8 +1,8 @@ import axios from "axios" +import { RTEngineClient } from "linebridge-client/src" + import SessionModel from "../session" import UserModel from "../user" -import { RTEngineClient } from "linebridge-client/src" -//import { RTEngineClient } from "../../../../linebridge/client/src" async function injectUserDataOnList(list) { if (!Array.isArray(list)) { @@ -73,7 +73,7 @@ export default class Streaming { const { data } = await Streaming.base({ method: "get", - url: `/streaming/${stream_id}`, + url: `/stream/${stream_id}/data`, }) return data @@ -81,37 +81,51 @@ export default class Streaming { static async getOwnProfiles() { const { data } = await Streaming.base({ - method: "get", + method: "GET", url: "/streaming/profiles/self", }) return data } - static async getProfile({ profile_id }) { + static async getProfile(profile_id) { if (!profile_id) { return null } const { data } = await Streaming.base({ - method: "get", + method: "GET", url: `/streaming/profiles/${profile_id}`, }) return data } - static async createOrUpdateProfile(update) { + static async createProfile(payload) { const { data } = await Streaming.base({ - method: "put", - url: `/streaming/profiles/self`, + method: "POST", + url: "/streaming/profiles/new", + data: payload, + }) + + return data + } + + static async updateProfile(profile_id, update) { + if (!profile_id) { + return null + } + + const { data } = await Streaming.base({ + method: "PUT", + url: `/streaming/profiles/${profile_id}`, data: update, }) return data } - static async deleteProfile({ profile_id }) { + static async deleteProfile(profile_id) { if (!profile_id) { return null } @@ -124,6 +138,36 @@ export default class Streaming { return data } + static async addRestreamToProfile(profileId, restreamData) { + if (!profileId) { + console.error("profileId is required to add a restream") + return null + } + + const { data } = await Streaming.base({ + method: "put", + url: `/streaming/profiles/${profileId}/restreams`, + data: restreamData, + }) + + return data + } + + static async deleteRestreamFromProfile(profileId, restreamIndexData) { + if (!profileId) { + console.error("profileId is required to delete a restream") + return null + } + + const { data } = await Streaming.base({ + method: "delete", + url: `/streaming/profiles/${profileId}/restreams`, + data: restreamIndexData, + }) + + return data + } + static async list({ limit, offset } = {}) { let { data } = await Streaming.base({ method: "get", @@ -145,11 +189,7 @@ export default class Streaming { return null } - const client = new RTEngineClient({ - ...params, - url: Streaming.apiHostname, - token: SessionModel.token, - }) + const client = Streaming.createWebsocket(params) client._destroy = client.destroy @@ -171,4 +211,14 @@ export default class Streaming { return client } + + static createWebsocket(params = {}) { + const client = new RTEngineClient({ + ...params, + url: Streaming.apiHostname, + token: SessionModel.token, + }) + + return client + } } diff --git a/src/models/user/index.js b/src/models/user/index.js index 1b387e6..d7bebe2 100755 --- a/src/models/user/index.js +++ b/src/models/user/index.js @@ -14,7 +14,15 @@ export default class User { let { username, user_id, basic = false } = payload if (!username && !user_id) { - user_id = SessionModel.user_id + const response = await request({ + method: "GET", + url: `/users/self`, + params: { + basic, + }, + }) + + return response.data } if (username && !user_id) { @@ -132,4 +140,29 @@ export default class User { return data } + + static async getPublicKey(user_id) { + if (!user_id) { + user_id = SessionModel.user_id + } + + const { data } = await request({ + method: "GET", + url: `/users/${user_id}/public-key`, + }) + + return data + } + + static async updatePublicKey(public_key) { + const { data } = await request({ + method: "PUT", + url: `/users/self/public-key`, + data: { + public_key: public_key, + }, + }) + + return data + } }