mirror of
https://github.com/ragestudio/comty.js.git
synced 2025-06-09 02:24:18 +00:00
merge from local
This commit is contained in:
parent
fac6a9f0d1
commit
4ebe77a0d7
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "comty.js",
|
"name": "comty.js",
|
||||||
"version": "0.60.3",
|
"version": "0.60.6",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"author": "RageStudio <support@ragestudio.net>",
|
"author": "RageStudio <support@ragestudio.net>",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -22,6 +22,6 @@
|
|||||||
"socket.io-client": "^4.6.1"
|
"socket.io-client": "^4.6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ragestudio/hermes": "^0.1.0"
|
"@ragestudio/hermes": "^1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,27 +8,25 @@ export default async (data, callback) => {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.response.status === 401) {
|
if (data.response) {
|
||||||
// check if the server issue a refresh token on data
|
if (data.response.status === 401) {
|
||||||
if (data.response.data.expired) {
|
// check if the server issue a refresh token on data
|
||||||
try {
|
if (data.response.data.expired) {
|
||||||
console.log(`Session expired, trying to regenerate...`)
|
try {
|
||||||
|
console.log(`Session expired, trying to regenerate...`)
|
||||||
|
|
||||||
await refreshToken()
|
await refreshToken()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
__comty_shared_state.eventBus.emit("session.invalid", error.message)
|
__comty_shared_state.eventBus.emit("session.invalid", error.message)
|
||||||
|
|
||||||
console.error(`Failed to regenerate token: ${error.message}`)
|
console.error(`Failed to regenerate token: ${error.message}`)
|
||||||
|
|
||||||
throw new Error(`Invalid or Expired session`)
|
throw new Error(`Invalid or Expired session`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return await callback()
|
||||||
}
|
}
|
||||||
|
|
||||||
return await callback()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.response.status === 403) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -74,13 +74,13 @@ export async function createWebsockets() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
instance.on("disconnect", () => {
|
instance.on("disconnect", () => {
|
||||||
//console.debug(`[WS-API][${key}] Disconnected`)
|
console.debug(`[WS-API][${key}] Disconnected`)
|
||||||
|
|
||||||
globalThis.__comty_shared_state.eventBus.emit(`${key}:disconnected`)
|
globalThis.__comty_shared_state.eventBus.emit(`${key}:disconnected`)
|
||||||
})
|
})
|
||||||
|
|
||||||
instance.on("reconnect", () => {
|
instance.on("reconnect", () => {
|
||||||
// console.debug(`[WS-API][${key}] Reconnected`)
|
console.debug(`[WS-API][${key}] Reconnected`)
|
||||||
|
|
||||||
globalThis.__comty_shared_state.eventBus.emit(`${key}:reconnected`)
|
globalThis.__comty_shared_state.eventBus.emit(`${key}:reconnected`)
|
||||||
|
|
||||||
@ -88,13 +88,13 @@ export async function createWebsockets() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
instance.on("error", (error) => {
|
instance.on("error", (error) => {
|
||||||
//console.error(`[WS-API][${key}] Error`, error)
|
console.error(`[WS-API][${key}] Error`, error)
|
||||||
|
|
||||||
globalThis.__comty_shared_state.eventBus.emit(`${key}:error`, error)
|
globalThis.__comty_shared_state.eventBus.emit(`${key}:error`, error)
|
||||||
})
|
})
|
||||||
|
|
||||||
instance.onAny((event, ...args) => {
|
instance.onAny((event, ...args) => {
|
||||||
//console.debug(`[WS-API][${key}] Event (${event})`, ...args)
|
console.debug(`[WS-API][${key}] Event (${event})`, ...args)
|
||||||
|
|
||||||
globalThis.__comty_shared_state.eventBus.emit(`${key}:${event}`, ...args)
|
globalThis.__comty_shared_state.eventBus.emit(`${key}:${event}`, ...args)
|
||||||
})
|
})
|
||||||
|
@ -51,7 +51,7 @@ export default class AuthModel {
|
|||||||
static async logout() {
|
static async logout() {
|
||||||
await SessionModel.destroyCurrentSession()
|
await SessionModel.destroyCurrentSession()
|
||||||
|
|
||||||
SessionModel.removeToken()
|
await SessionModel.removeToken()
|
||||||
|
|
||||||
__comty_shared_state.eventBus.emit("auth:logout_success")
|
__comty_shared_state.eventBus.emit("auth:logout_success")
|
||||||
}
|
}
|
||||||
@ -92,6 +92,29 @@ export default class AuthModel {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies the given token and returns the user data associated with it.
|
||||||
|
*
|
||||||
|
* @param {string} [token] - The token to verify. If not provided, the stored token is used.
|
||||||
|
* @return {Promise<Object>} A Promise that resolves with the user data if the token is valid, or false if the token is invalid.
|
||||||
|
* @throws {Error} Throws an error if there was an issue with the request.
|
||||||
|
*/
|
||||||
|
static async authToken(token) {
|
||||||
|
if (!token) {
|
||||||
|
token = await SessionModel.token
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await request({
|
||||||
|
method: "POST",
|
||||||
|
url: "/auth/token",
|
||||||
|
data: {
|
||||||
|
token: token
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return response.data
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the existence of a username by making a GET request to the `/auth/{username}/exists` endpoint.
|
* Validates the existence of a username by making a GET request to the `/auth/{username}/exists` endpoint.
|
||||||
*
|
*
|
||||||
@ -165,4 +188,44 @@ export default class AuthModel {
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates a user account using the provided activation code.
|
||||||
|
*
|
||||||
|
* @param {string} user_id - The ID of the user to activate.
|
||||||
|
* @param {string} code - The activation code sent to the user's email.
|
||||||
|
* @return {Promise<Object>} A promise that resolves with the response data after activation.
|
||||||
|
* @throws {Error} Throws an error if the activation process fails.
|
||||||
|
*/
|
||||||
|
static async activateAccount(user_id, code) {
|
||||||
|
const { data } = await request({
|
||||||
|
method: "post",
|
||||||
|
url: "/auth/activate",
|
||||||
|
data: {
|
||||||
|
code: code,
|
||||||
|
user_id: user_id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resends the activation code to the user.
|
||||||
|
*
|
||||||
|
* @return {Promise<Object>} A promise that resolves with the response data after sending the activation code.
|
||||||
|
* @throws {Error} Throws an error if the resend activation code process fails.
|
||||||
|
* @param user_id
|
||||||
|
*/
|
||||||
|
static async resendActivationCode(user_id) {
|
||||||
|
const { data } = await request({
|
||||||
|
method: "post",
|
||||||
|
url: "/auth/resend-activation-code",
|
||||||
|
data: {
|
||||||
|
user_id: user_id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,7 +1,13 @@
|
|||||||
import request from "../../request"
|
import request from "../../request"
|
||||||
import SessionModel from "../session"
|
|
||||||
|
|
||||||
export default class ChatsService {
|
export default class ChatsService {
|
||||||
|
/**
|
||||||
|
* Retrieves the chat history for a given chat ID.
|
||||||
|
*
|
||||||
|
* @param {string} chat_id - The ID of the chat.
|
||||||
|
* @return {Promise<Object>} The chat history data.
|
||||||
|
* @throws {Error} If the chat_id is not provided.
|
||||||
|
*/
|
||||||
static async getChatHistory(chat_id) {
|
static async getChatHistory(chat_id) {
|
||||||
if (!chat_id) {
|
if (!chat_id) {
|
||||||
throw new Error("chat_id is required")
|
throw new Error("chat_id is required")
|
||||||
@ -15,6 +21,11 @@ export default class ChatsService {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the recent chats for the current user.
|
||||||
|
*
|
||||||
|
* @return {Promise<Object>} The chat history data.
|
||||||
|
*/
|
||||||
static async getRecentChats() {
|
static async getRecentChats() {
|
||||||
const { data } = await request({
|
const { data } = await request({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
14
src/models/music/getters/favouriteFolder.js
Normal file
14
src/models/music/getters/favouriteFolder.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import request from "../../../request"
|
||||||
|
|
||||||
|
export default async ({ limit = 100, offset = 0 } = {}) => {
|
||||||
|
const response = await request({
|
||||||
|
method: "GET",
|
||||||
|
url: "/music/my/folder",
|
||||||
|
params: {
|
||||||
|
limit: limit,
|
||||||
|
offset: offset
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return response.data
|
||||||
|
}
|
33
src/models/music/getters/isItemFavourited.js
Normal file
33
src/models/music/getters/isItemFavourited.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
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
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
import request from "../../request"
|
|
||||||
import pmap from "p-map"
|
|
||||||
import SyncModel from "../sync"
|
|
||||||
|
|
||||||
import Getters from "./getters"
|
import Getters from "./getters"
|
||||||
|
import Setters from "./setters"
|
||||||
|
|
||||||
export default class MusicModel {
|
export default class MusicModel {
|
||||||
|
public static Getters = Getters
|
||||||
|
public static Setters = Setters
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a search based on the provided keywords, with optional parameters for limiting the number of results and pagination.
|
* Performs a search based on the provided keywords, with optional parameters for limiting the number of results and pagination.
|
||||||
*
|
*
|
||||||
@ -96,321 +96,54 @@ export default class MusicModel {
|
|||||||
public static getTrackLyrics = Getters.trackLyrics
|
public static getTrackLyrics = Getters.trackLyrics
|
||||||
|
|
||||||
|
|
||||||
|
public static putTrackLyrics = Setters.putTrackLyrics
|
||||||
//!INCOMPLETE
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves favorite tracks based on specified parameters.
|
* Create or modify a track.
|
||||||
*
|
*
|
||||||
* @param {Object} options - The options for retrieving favorite tracks.
|
* @param {object} TrackManifest - The track manifest.
|
||||||
* @param {boolean} options.useTidal - Whether to use Tidal for retrieving tracks. Defaults to false.
|
* @return {Promise<Object>} The result track data.
|
||||||
* @param {number} options.limit - The maximum number of tracks to retrieve.
|
*/
|
||||||
* @param {number} options.offset - The offset from which to start retrieving tracks.
|
public static putTrack = Setters.putTrack
|
||||||
* @return {Promise<Object>} - An object containing the total length of the tracks and the retrieved tracks.
|
|
||||||
*/
|
|
||||||
static async getFavoriteTracks({ useTidal = false, limit, offset }) {
|
|
||||||
let result = []
|
|
||||||
|
|
||||||
let limitPerRequesters = limit
|
|
||||||
|
|
||||||
if (useTidal) {
|
|
||||||
limitPerRequesters = limitPerRequesters / 2
|
|
||||||
}
|
|
||||||
|
|
||||||
const requesters = [
|
|
||||||
async () => {
|
|
||||||
let { data } = await request({
|
|
||||||
method: "GET",
|
|
||||||
url: `/music/tracks/liked`,
|
|
||||||
params: {
|
|
||||||
limit: limitPerRequesters,
|
|
||||||
offset,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
return data
|
|
||||||
},
|
|
||||||
async () => {
|
|
||||||
if (!useTidal) {
|
|
||||||
return {
|
|
||||||
total_length: 0,
|
|
||||||
tracks: [],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const tidalResult = await SyncModel.tidalCore.getMyFavoriteTracks({
|
|
||||||
limit: limitPerRequesters,
|
|
||||||
offset,
|
|
||||||
})
|
|
||||||
|
|
||||||
return tidalResult
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
result = await pmap(
|
|
||||||
requesters,
|
|
||||||
async requester => {
|
|
||||||
const data = await requester()
|
|
||||||
|
|
||||||
return data
|
|
||||||
},
|
|
||||||
{
|
|
||||||
concurrency: 3,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
let total_length = 0
|
|
||||||
|
|
||||||
result.forEach(result => {
|
|
||||||
total_length += result.total_length
|
|
||||||
})
|
|
||||||
|
|
||||||
let tracks = result.reduce((acc, cur) => {
|
|
||||||
return [...acc, ...cur.tracks]
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
tracks = tracks.sort((a, b) => {
|
|
||||||
return b.liked_at - a.liked_at
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
total_length,
|
|
||||||
tracks,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves favorite playlists based on the specified parameters.
|
* Create or modify a release.
|
||||||
*
|
*
|
||||||
* @param {Object} options - The options for retrieving favorite playlists.
|
* @param {object} ReleaseManifest - The release manifest.
|
||||||
* @param {number} options.limit - The maximum number of playlists to retrieve. Default is 50.
|
* @return {Promise<Object>} The result release data.
|
||||||
* @param {number} options.offset - The offset of playlists to retrieve. Default is 0.
|
*/
|
||||||
* @param {Object} options.services - The services to include for retrieving playlists. Default is an empty object.
|
public static putRelease = Setters.putRelease
|
||||||
* @param {string} options.keywords - The keywords to filter playlists by.
|
|
||||||
* @return {Promise<Object>} - An object containing the total length of the playlists and the playlist items.
|
|
||||||
*/
|
|
||||||
static async getFavoritePlaylists({ limit = 50, offset = 0, services = {}, keywords } = {}) {
|
|
||||||
let result = []
|
|
||||||
|
|
||||||
let limitPerRequesters = limit
|
|
||||||
|
|
||||||
const requesters = [
|
|
||||||
async () => {
|
|
||||||
return await MusicModel.getMyReleases(keywords)
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
if (services["tidal"] === true) {
|
|
||||||
limitPerRequesters = limitPerRequesters / (requesters.length + 1)
|
|
||||||
|
|
||||||
requesters.push(async () => {
|
|
||||||
const _result = await SyncModel.tidalCore.getMyFavoritePlaylists({
|
|
||||||
limit: limitPerRequesters,
|
|
||||||
offset,
|
|
||||||
})
|
|
||||||
|
|
||||||
return _result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
result = await pmap(
|
|
||||||
requesters,
|
|
||||||
async requester => {
|
|
||||||
const data = await requester()
|
|
||||||
|
|
||||||
return data
|
|
||||||
},
|
|
||||||
{
|
|
||||||
concurrency: 3,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
// calculate total length
|
|
||||||
let total_length = 0
|
|
||||||
|
|
||||||
result.forEach(result => {
|
|
||||||
total_length += result.total_length
|
|
||||||
})
|
|
||||||
|
|
||||||
// reduce items
|
|
||||||
let items = result.reduce((acc, cur) => {
|
|
||||||
return [...acc, ...cur.items]
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
|
|
||||||
// sort by created_at
|
|
||||||
items = items.sort((a, b) => {
|
|
||||||
return new Date(b.created_at) - new Date(a.created_at)
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
total_length: total_length,
|
|
||||||
items,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new playlist.
|
* Deletes a release by its ID.
|
||||||
*
|
*
|
||||||
* @param {object} payload - The payload containing the data for the new playlist.
|
* @param {string} id - The ID of the release to delete.
|
||||||
* @return {Promise<Object>} The new playlist data.
|
* @return {Promise<Object>} - A Promise that resolves to the data returned by the API.
|
||||||
*/
|
*/
|
||||||
static async newPlaylist(payload) {
|
public static deleteRelease = Setters.deleteRelease
|
||||||
const { data } = await request({
|
|
||||||
method: "POST",
|
|
||||||
url: `/playlists/new`,
|
|
||||||
data: payload,
|
|
||||||
})
|
|
||||||
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a playlist item in the specified playlist.
|
* Retrieves the favourite tracks of the current user.
|
||||||
*
|
*
|
||||||
* @param {string} playlist_id - The ID of the playlist to update.
|
* @return {Promise<Object>} The favorite tracks data.
|
||||||
* @param {object} item - The updated playlist item to be added.
|
|
||||||
* @return {Promise<Object>} - The updated playlist item.
|
|
||||||
*/
|
*/
|
||||||
static async putPlaylistItem(playlist_id, item) {
|
public static getFavouriteTracks = null
|
||||||
const response = await request({
|
|
||||||
method: "PUT",
|
|
||||||
url: `/playlists/${playlist_id}/items`,
|
|
||||||
data: item,
|
|
||||||
})
|
|
||||||
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a playlist item.
|
* Retrieves the favourite tracks/playlists/releases of the current user.
|
||||||
*
|
*
|
||||||
* @param {string} playlist_id - The ID of the playlist.
|
* @return {Promise<Object>} The favorite playlists data.
|
||||||
* @param {string} item_id - The ID of the item to delete.
|
|
||||||
* @return {Promise<Object>} The data returned by the server after the item is deleted.
|
|
||||||
*/
|
*/
|
||||||
static async deletePlaylistItem(playlist_id, item_id) {
|
public static getFavouriteFolder = Getters.favouriteFolder
|
||||||
const response = await request({
|
|
||||||
method: "DELETE",
|
|
||||||
url: `/playlists/${playlist_id}/items/${item_id}`,
|
|
||||||
})
|
|
||||||
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a playlist.
|
* Toggles the favourite status of a track, playlist or folder.
|
||||||
*
|
*
|
||||||
* @param {number} playlist_id - The ID of the playlist to be deleted.
|
* @param {string} track_id - The ID of the track to toggle the favorite status.
|
||||||
* @return {Promise<Object>} The response data from the server.
|
* @throws {Error} If the track_id is not provided.
|
||||||
|
* @return {Promise<Object>} The response data after toggling the favorite status.
|
||||||
*/
|
*/
|
||||||
static async deletePlaylist(playlist_id) {
|
public static toggleItemFavourite = Setters.toggleItemFavourite
|
||||||
const response = await request({
|
|
||||||
method: "DELETE",
|
|
||||||
url: `/playlists/${playlist_id}`,
|
|
||||||
})
|
|
||||||
|
|
||||||
return response.data
|
public static isItemFavourited = Getters.isItemFavourited
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a PUT request to update or create a release.
|
|
||||||
*
|
|
||||||
* @param {object} payload - The payload data.
|
|
||||||
* @return {Promise<Object>} The response data from the server.
|
|
||||||
*/
|
|
||||||
static async putRelease(payload) {
|
|
||||||
const response = await request({
|
|
||||||
method: "PUT",
|
|
||||||
url: `/releases/release`,
|
|
||||||
data: payload
|
|
||||||
})
|
|
||||||
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes a release by its ID.
|
|
||||||
*
|
|
||||||
* @param {string} id - The ID of the release to delete.
|
|
||||||
* @return {Promise<Object>} - A Promise that resolves to the data returned by the API.
|
|
||||||
*/
|
|
||||||
static async deleteRelease(id) {
|
|
||||||
const response = await request({
|
|
||||||
method: "DELETE",
|
|
||||||
url: `/releases/${id}`
|
|
||||||
})
|
|
||||||
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Refreshes the track cache for a given track ID.
|
|
||||||
*
|
|
||||||
* @param {string} track_id - The ID of the track to refresh the cache for.
|
|
||||||
* @throws {Error} If track_id is not provided.
|
|
||||||
* @return {Promise<Object>} The response data from the API call.
|
|
||||||
*/
|
|
||||||
static async refreshTrackCache(track_id) {
|
|
||||||
if (!track_id) {
|
|
||||||
throw new Error("Track ID is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await request({
|
|
||||||
method: "POST",
|
|
||||||
url: `/tracks/${track_id}/refresh-cache`,
|
|
||||||
})
|
|
||||||
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggles the like status of a track.
|
|
||||||
*
|
|
||||||
* @param {Object} manifest - The manifest object containing track information.
|
|
||||||
* @param {boolean} to - The like status to toggle (true for like, false for unlike).
|
|
||||||
* @throws {Error} Throws an error if the manifest is missing.
|
|
||||||
* @return {Object} The response data from the API.
|
|
||||||
*/
|
|
||||||
static async toggleTrackLike(manifest, to) {
|
|
||||||
if (!manifest) {
|
|
||||||
throw new Error("Manifest is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`Toggling track ${manifest._id} like status to ${to}`)
|
|
||||||
|
|
||||||
const track_id = manifest._id
|
|
||||||
|
|
||||||
switch (manifest.service) {
|
|
||||||
case "tidal": {
|
|
||||||
const response = await SyncModel.tidalCore.toggleTrackLike({
|
|
||||||
track_id,
|
|
||||||
to,
|
|
||||||
})
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
const response = await request({
|
|
||||||
method: to ? "POST" : "DELETE",
|
|
||||||
url: `/tracks/${track_id}/like`,
|
|
||||||
params: {
|
|
||||||
service: manifest.service
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
11
src/models/music/setters/deleteRelease.js
Normal file
11
src/models/music/setters/deleteRelease.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import request from "../../../request"
|
||||||
|
|
||||||
|
export default async (release_id) => {
|
||||||
|
const response = await request({
|
||||||
|
method: "delete",
|
||||||
|
url: `/music/releases/${release_id}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
return response.data
|
||||||
|
}
|
36
src/models/music/setters/index.js
Normal file
36
src/models/music/setters/index.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
async function exportObjs() {
|
||||||
|
if (window) {
|
||||||
|
let paths = {
|
||||||
|
...import.meta.glob("./**.ts"),
|
||||||
|
...import.meta.glob("./**.js"),
|
||||||
|
}
|
||||||
|
|
||||||
|
let fns = {}
|
||||||
|
|
||||||
|
for (const path in paths) {
|
||||||
|
const name = path.split("/").pop().replace(".ts", "").replace(".js", "")
|
||||||
|
const fn = await paths[path]()
|
||||||
|
|
||||||
|
fns[name] = fn.default
|
||||||
|
}
|
||||||
|
|
||||||
|
return fns
|
||||||
|
} else {
|
||||||
|
let objs = {}
|
||||||
|
|
||||||
|
const dirs = fs.readdirSync(__dirname).filter(file => file !== "index.js")
|
||||||
|
|
||||||
|
const fs = require("fs")
|
||||||
|
const path = require("path")
|
||||||
|
|
||||||
|
dirs.forEach((file) => {
|
||||||
|
const model = require(path.join(__dirname, file)).default
|
||||||
|
|
||||||
|
objs[file.replace(".js", "")] = model
|
||||||
|
})
|
||||||
|
|
||||||
|
return objs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default await exportObjs()
|
12
src/models/music/setters/putRelease.js
Normal file
12
src/models/music/setters/putRelease.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import request from "../../../request"
|
||||||
|
|
||||||
|
export default async (release) => {
|
||||||
|
const response = await request({
|
||||||
|
method: "PUT",
|
||||||
|
url: "/music/releases",
|
||||||
|
data: release,
|
||||||
|
})
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
return response.data
|
||||||
|
}
|
12
src/models/music/setters/putTrack.js
Normal file
12
src/models/music/setters/putTrack.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import request from "../../../request"
|
||||||
|
|
||||||
|
export default async (track) => {
|
||||||
|
const response = await request({
|
||||||
|
method: "PUT",
|
||||||
|
url: "/music/tracks",
|
||||||
|
data: track,
|
||||||
|
})
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
return response.data
|
||||||
|
}
|
12
src/models/music/setters/putTrackLyrics.js
Normal file
12
src/models/music/setters/putTrackLyrics.js
Normal file
@ -0,0 +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,
|
||||||
|
})
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
return response.data
|
||||||
|
}
|
36
src/models/music/setters/toggleItemFavourite.js
Normal file
36
src/models/music/setters/toggleItemFavourite.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
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
|
||||||
|
}
|
@ -71,10 +71,14 @@ export default class NFCModel {
|
|||||||
throw new Error("Payload is required")
|
throw new Error("Payload is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window) {
|
||||||
|
payload.origin = window.location.host
|
||||||
|
}
|
||||||
|
|
||||||
const { data } = await request({
|
const { data } = await request({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: `/nfc/tag/register/${serial}`,
|
url: `/nfc/tag/register/${serial}`,
|
||||||
data: payload
|
data: payload,
|
||||||
})
|
})
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
17
src/models/payments/index.js
Normal file
17
src/models/payments/index.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import request from "../../request"
|
||||||
|
|
||||||
|
export default class PaymentsModel {
|
||||||
|
/**
|
||||||
|
* Fetches the current balance from the server.
|
||||||
|
*
|
||||||
|
* @return {object} The balance data received from the server.
|
||||||
|
*/
|
||||||
|
static async fetchBalance() {
|
||||||
|
const response = await request({
|
||||||
|
method: "GET",
|
||||||
|
url: "/payments/balance",
|
||||||
|
})
|
||||||
|
|
||||||
|
return response.data.balance
|
||||||
|
}
|
||||||
|
}
|
@ -254,4 +254,65 @@ export default class Post {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static deletePost = Post.delete
|
static deletePost = Post.delete
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Votes for a poll with the given post ID and option ID.
|
||||||
|
*
|
||||||
|
* @param {Object} options - The options for voting.
|
||||||
|
* @param {string} options.post_id - The ID of the post to vote for.
|
||||||
|
* @param {string} options.option_id - The ID of the option to vote for.
|
||||||
|
* @throws {Error} If the post_id or option_id is not provided.
|
||||||
|
* @return {Promise<Object>} The response data after voting.
|
||||||
|
*/
|
||||||
|
static async votePoll({ post_id, option_id }) {
|
||||||
|
if (!post_id) {
|
||||||
|
throw new Error("post_id is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!option_id) {
|
||||||
|
throw new Error("option_id is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await request({
|
||||||
|
method: "POST",
|
||||||
|
url: `/posts/${post_id}/vote_poll/${option_id}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a vote for a poll with the given post ID and option ID.
|
||||||
|
*
|
||||||
|
* @param {Object} options - The options for deleting a vote.
|
||||||
|
* @param {string} options.post_id - The ID of the post to delete the vote from.
|
||||||
|
* @param {string} options.option_id - The ID of the option to delete the vote from.
|
||||||
|
* @throws {Error} If the post_id or option_id is not provided.
|
||||||
|
* @return {Promise<Object>} The response data after deleting the vote.
|
||||||
|
*/
|
||||||
|
static async deleteVotePoll({ post_id, option_id }) {
|
||||||
|
if (!post_id) {
|
||||||
|
throw new Error("post_id is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!option_id) {
|
||||||
|
throw new Error("option_id is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await request({
|
||||||
|
method: "DELETE",
|
||||||
|
url: `/posts/${post_id}/vote_poll/${option_id}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getTrendings() {
|
||||||
|
const { data } = await request({
|
||||||
|
method: "GET",
|
||||||
|
url: `/posts/trendings`,
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
}
|
}
|
@ -119,25 +119,6 @@ export default class Session {
|
|||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the token validation data from the server.
|
|
||||||
*
|
|
||||||
* @return {Promise<Object>} The token validation data.
|
|
||||||
*/
|
|
||||||
static async getTokenValidation() {
|
|
||||||
const session = await Session.token
|
|
||||||
|
|
||||||
const response = await request({
|
|
||||||
method: "get",
|
|
||||||
url: "/sessions/validate",
|
|
||||||
data: {
|
|
||||||
session: session
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return response.data
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the current session by deleting it from the server.
|
* Destroys the current session by deleting it from the server.
|
||||||
*
|
*
|
||||||
|
96
src/models/spectrum/index.js
Normal file
96
src/models/spectrum/index.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import axios from "axios"
|
||||||
|
import SessionService from "../session"
|
||||||
|
|
||||||
|
export default class Streaming {
|
||||||
|
static apiHostname = process.env.NODE_ENV === "production" ? "https://live.ragestudio.net" : "https://fr01.ragestudio.net:8035"
|
||||||
|
|
||||||
|
static get base() {
|
||||||
|
const baseInstance = axios.create({
|
||||||
|
baseURL: Streaming.apiHostname,
|
||||||
|
headers: {
|
||||||
|
"Accept": "application/json",
|
||||||
|
"ngrok-skip-browser-warning": "any"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (SessionService.token) {
|
||||||
|
baseInstance.defaults.headers.common["Authorization"] = `Bearer ${SessionService.token}`
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseInstance
|
||||||
|
}
|
||||||
|
|
||||||
|
static async serverInfo() {
|
||||||
|
const { data } = await Streaming.base({
|
||||||
|
method: "get",
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
hostname: Streaming.apiHostname
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getOwnProfiles() {
|
||||||
|
const { data } = await Streaming.base({
|
||||||
|
method: "get",
|
||||||
|
url: "/streaming/profiles/self",
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getProfile({ profile_id }) {
|
||||||
|
if (!profile_id) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await Streaming.base({
|
||||||
|
method: "get",
|
||||||
|
url: `/streaming/profiles/${profile_id}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getStream({ profile_id }) {
|
||||||
|
if (!profile_id) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await Streaming.base({
|
||||||
|
method: "get",
|
||||||
|
url: `/streaming/${profile_id}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
static async deleteProfile({ profile_id }) {
|
||||||
|
if (!profile_id) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await Streaming.base({
|
||||||
|
method: "delete",
|
||||||
|
url: `/streaming/profiles/${profile_id}`,
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
static async createOrUpdateStream(update) {
|
||||||
|
const { data } = await Streaming.base({
|
||||||
|
method: "put",
|
||||||
|
url: `/streaming/profiles/self`,
|
||||||
|
data: update,
|
||||||
|
})
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
static async getConnectionStatus({ profile_id }) {
|
||||||
|
console.warn("getConnectionStatus() | Not implemented")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
@ -48,9 +48,7 @@ export default class User {
|
|||||||
const response = await request({
|
const response = await request({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: "/users/self/update",
|
url: "/users/self/update",
|
||||||
data: {
|
data: payload,
|
||||||
update: payload,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return response.data
|
return response.data
|
||||||
|
@ -1,22 +1,6 @@
|
|||||||
function getCurrentHostname() {
|
|
||||||
if (typeof window === "undefined") {
|
|
||||||
return "localhost"
|
|
||||||
}
|
|
||||||
|
|
||||||
return window?.location?.hostname ?? "localhost"
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCurrentProtocol() {
|
|
||||||
if (typeof window === "undefined") {
|
|
||||||
return "http"
|
|
||||||
}
|
|
||||||
|
|
||||||
return window?.location?.protocol ?? "http:"
|
|
||||||
}
|
|
||||||
|
|
||||||
const envOrigins = {
|
const envOrigins = {
|
||||||
"development": `${getCurrentProtocol()}//${getCurrentHostname()}:9000`,
|
"development": `${location.origin}/api`,
|
||||||
"indev": "https://indev_api.comty.app",
|
"indev": "https://indev.comty.app/api",
|
||||||
"production": "https://api.comty.app",
|
"production": "https://api.comty.app",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,6 +22,14 @@ export default {
|
|||||||
{
|
{
|
||||||
namespace: "chats",
|
namespace: "chats",
|
||||||
path: "/chats",
|
path: "/chats",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
namespace: "music",
|
||||||
|
path: "/music",
|
||||||
}
|
}
|
||||||
|
// {
|
||||||
|
// namespace: "payments",
|
||||||
|
// path: "/payments",
|
||||||
|
// }
|
||||||
]
|
]
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user