mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 18:44:16 +00:00
use new items list standart
This commit is contained in:
parent
3990ef45c9
commit
9c9fa4c18b
@ -12,6 +12,7 @@ const AllowedUpdateFields = [
|
|||||||
|
|
||||||
export default class Release {
|
export default class Release {
|
||||||
static async create(payload) {
|
static async create(payload) {
|
||||||
|
console.log(payload)
|
||||||
if (!payload.title) {
|
if (!payload.title) {
|
||||||
throw new OperationError(400, "Release title is required")
|
throw new OperationError(400, "Release title is required")
|
||||||
}
|
}
|
||||||
@ -21,7 +22,7 @@ export default class Release {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ensure list is an array of strings with tracks ids only
|
// ensure list is an array of strings with tracks ids only
|
||||||
playload.list = playload.list.map((item) => {
|
payload.list = payload.list.map((item) => {
|
||||||
if (typeof item !== "string") {
|
if (typeof item !== "string") {
|
||||||
item = item._id
|
item = item._id
|
||||||
}
|
}
|
||||||
|
@ -1,66 +1,96 @@
|
|||||||
import { Track, TrackLike } from "@db_models"
|
import { Track, TrackLike } from "@db_models"
|
||||||
|
|
||||||
export default async (track_id, { user_id = null, onlyList = false } = {}) => {
|
async function fullfillData(list, { user_id = null }) {
|
||||||
if (!track_id) {
|
if (!Array.isArray(list)) {
|
||||||
throw new OperationError(400, "Missing track_id")
|
list = [list]
|
||||||
}
|
}
|
||||||
|
|
||||||
const isMultiple = Array.isArray(track_id) || track_id.includes(",")
|
const trackIds = list.map((track) => {
|
||||||
|
return track._id
|
||||||
|
})
|
||||||
|
|
||||||
if (isMultiple) {
|
// if user_id is provided, fetch likes
|
||||||
const track_ids = Array.isArray(track_id) ? track_id : track_id.split(",")
|
if (user_id) {
|
||||||
|
const tracksLikes = await TrackLike.find({
|
||||||
|
user_id: user_id,
|
||||||
|
track_id: { $in: trackIds },
|
||||||
|
})
|
||||||
|
|
||||||
const tracks = await Track.find({
|
list = list.map(async (track) => {
|
||||||
_id: { $in: track_ids }
|
const trackLike = tracksLikes.find((trackLike) => {
|
||||||
}).lean()
|
return trackLike.track_id.toString() === track._id.toString()
|
||||||
|
})
|
||||||
|
|
||||||
if (user_id) {
|
if (trackLike) {
|
||||||
const trackLikes = await TrackLike.find({
|
track.liked_at = trackLike.created_at
|
||||||
user_id: user_id,
|
track.liked = true
|
||||||
track_id: { $in: track_ids }
|
}
|
||||||
})
|
|
||||||
|
|
||||||
// FIXME: this could be a performance issue when there are a lot of likes
|
return track
|
||||||
// Array.find may not be a good idea
|
})
|
||||||
for (const trackLike of trackLikes) {
|
|
||||||
const track = tracks.find(track => track._id.toString() === trackLike.track_id.toString())
|
|
||||||
|
|
||||||
if (track) {
|
list = await Promise.all(list)
|
||||||
track.liked_at = trackLike.created_at
|
}
|
||||||
track.liked = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (onlyList) {
|
// process some metadata
|
||||||
return tracks
|
list = list.map(async (track) => {
|
||||||
}
|
if (track.metadata) {
|
||||||
|
if (track.metadata.bitrate && track.metadata.bitrate > 9000) {
|
||||||
|
track.metadata.lossless = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return track
|
||||||
total_count: await Track.countDocuments({ _id: { $in: track_ids } }),
|
})
|
||||||
list: tracks,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const track = await Track.findOne({
|
list = await Promise.all(list)
|
||||||
_id: track_id
|
|
||||||
}).lean()
|
|
||||||
|
|
||||||
if (!track) {
|
return list
|
||||||
throw new OperationError(404, "Track not found")
|
}
|
||||||
}
|
|
||||||
|
export default async (track_id, { user_id = null, onlyList = false } = {}) => {
|
||||||
if (user_id) {
|
if (!track_id) {
|
||||||
const trackLike = await TrackLike.findOne({
|
throw new OperationError(400, "Missing track_id")
|
||||||
user_id: user_id,
|
}
|
||||||
track_id: track_id,
|
|
||||||
})
|
const isMultiple = Array.isArray(track_id) || track_id.includes(",")
|
||||||
|
|
||||||
if (trackLike) {
|
if (isMultiple) {
|
||||||
track.liked_at = trackLike.created_at
|
const track_ids = Array.isArray(track_id)
|
||||||
track.liked = true
|
? track_id
|
||||||
}
|
: track_id.split(",")
|
||||||
}
|
|
||||||
|
let tracks = await Track.find({
|
||||||
return track
|
_id: { $in: track_ids },
|
||||||
|
}).lean()
|
||||||
|
|
||||||
|
tracks = await fullfillData(tracks, {
|
||||||
|
user_id,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (onlyList) {
|
||||||
|
return tracks
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
total_count: await Track.countDocuments({
|
||||||
|
_id: { $in: track_ids },
|
||||||
|
}),
|
||||||
|
list: tracks,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let track = await Track.findOne({
|
||||||
|
_id: track_id,
|
||||||
|
}).lean()
|
||||||
|
|
||||||
|
if (!track) {
|
||||||
|
throw new OperationError(404, "Track not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
track = await fullfillData(track, {
|
||||||
|
user_id,
|
||||||
|
})
|
||||||
|
|
||||||
|
return track[0]
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ export default async (user_id, track_id, to) => {
|
|||||||
throw new OperationError(400, "Missing track_id")
|
throw new OperationError(400, "Missing track_id")
|
||||||
}
|
}
|
||||||
|
|
||||||
const track = await Track.findById(track_id)
|
const track = await Track.findById(track_id).catch(() => null)
|
||||||
|
|
||||||
if (!track) {
|
if (!track) {
|
||||||
throw new OperationError(404, "Track not found")
|
throw new OperationError(404, "Track not found")
|
||||||
|
@ -45,8 +45,6 @@ export default async (user_id, track_id, to) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(global.websocket.find)
|
|
||||||
|
|
||||||
const targetSocket = await global.websocket.find.socketByUserId(user_id)
|
const targetSocket = await global.websocket.find.socketByUserId(user_id)
|
||||||
|
|
||||||
if (targetSocket) {
|
if (targetSocket) {
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
import { MusicRelease, Track } from "@db_models"
|
import { MusicRelease, Track } from "@db_models"
|
||||||
|
|
||||||
export default async (req) => {
|
export default async (req) => {
|
||||||
const { limit = 10, trim = 0, order = "desc" } = req.query
|
const { limit = 10, trim = 0, order = "desc" } = req.query
|
||||||
|
|
||||||
const searchQuery = {}
|
const searchQuery = {}
|
||||||
|
|
||||||
const total_length = await MusicRelease.countDocuments(searchQuery)
|
const total_length = await MusicRelease.countDocuments(searchQuery)
|
||||||
|
|
||||||
let result = await MusicRelease.find({
|
let result = await MusicRelease.find({
|
||||||
...searchQuery,
|
...searchQuery,
|
||||||
public: true,
|
public: true,
|
||||||
})
|
})
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.skip(trim)
|
.skip(trim)
|
||||||
.sort({ created_at: order === "desc" ? -1 : 1 })
|
.sort({ created_at: order === "desc" ? -1 : 1 })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
total_length: total_length,
|
total_length: total_length,
|
||||||
has_more: total_length > trim + result.length,
|
has_more: total_length > trim + result.length,
|
||||||
items: result,
|
items: result,
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,16 +1,16 @@
|
|||||||
export default {
|
export default {
|
||||||
middlewares: ["withAuthentication"],
|
middlewares: ["withAuthentication"],
|
||||||
fn: async (req) => {
|
fn: async (req) => {
|
||||||
const { keywords, limit = 10, offset = 0 } = req.query
|
const { keywords, limit = 10, offset = 0 } = req.query
|
||||||
|
|
||||||
const user_id = req.auth.session.user_id
|
const user_id = req.auth.session.user_id
|
||||||
|
|
||||||
let total_length = 0
|
let total_length = 0
|
||||||
let result = []
|
let result = []
|
||||||
|
|
||||||
return {
|
return {
|
||||||
total_length: total_length,
|
total_length: total_length,
|
||||||
items: result,
|
items: result,
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
@ -6,9 +6,8 @@ export default {
|
|||||||
const { track_id } = req.params
|
const { track_id } = req.params
|
||||||
const { video_source, lrc, sync_audio_at } = req.body
|
const { video_source, lrc, sync_audio_at } = req.body
|
||||||
|
|
||||||
let track = await Track.findOne({
|
// check if track exists
|
||||||
_id: track_id,
|
let track = await Track.findById(track_id).catch(() => null)
|
||||||
})
|
|
||||||
|
|
||||||
if (!track) {
|
if (!track) {
|
||||||
throw new OperationError(404, "Track not found")
|
throw new OperationError(404, "Track not found")
|
||||||
@ -22,13 +21,14 @@ export default {
|
|||||||
track_id: track_id,
|
track_id: track_id,
|
||||||
video_source: video_source,
|
video_source: video_source,
|
||||||
lrc: lrc,
|
lrc: lrc,
|
||||||
track: track,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// check if trackLyric exists
|
||||||
let trackLyric = await TrackLyric.findOne({
|
let trackLyric = await TrackLyric.findOne({
|
||||||
track_id: track_id
|
track_id: track_id
|
||||||
}).lean()
|
})
|
||||||
|
|
||||||
|
// if trackLyric exists, update it, else create it
|
||||||
if (!trackLyric) {
|
if (!trackLyric) {
|
||||||
trackLyric = new TrackLyric({
|
trackLyric = new TrackLyric({
|
||||||
track_id: track_id,
|
track_id: track_id,
|
||||||
|
@ -1,73 +1,93 @@
|
|||||||
import {
|
import { TrackLike } from "@db_models"
|
||||||
TrackLike,
|
|
||||||
} from "@db_models"
|
|
||||||
|
|
||||||
import TrackClass from "@classes/track"
|
import TrackClass from "@classes/track"
|
||||||
|
|
||||||
|
const HANDLERS = {
|
||||||
|
track: {
|
||||||
|
model: TrackLike,
|
||||||
|
class: TrackClass,
|
||||||
|
type: "tracks",
|
||||||
|
idField: "track_id",
|
||||||
|
},
|
||||||
|
// release: {
|
||||||
|
// model: ReleaseLike,
|
||||||
|
// class: ReleaseClass,
|
||||||
|
// type: 'releases',
|
||||||
|
// idField: 'release_id'
|
||||||
|
// },
|
||||||
|
// playlist: {
|
||||||
|
// model: PlaylistLike,
|
||||||
|
// class: PlaylistClass,
|
||||||
|
// type: 'playlists',
|
||||||
|
// idField: 'playlist_id'
|
||||||
|
// },
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getLikedItemsFromHandler(config, userId, pagination) {
|
||||||
|
try {
|
||||||
|
// obtain ids data and total items
|
||||||
|
const [total, likes] = await Promise.all([
|
||||||
|
config.model.countDocuments({ user_id: userId }),
|
||||||
|
config.model
|
||||||
|
.find({ user_id: userId })
|
||||||
|
.sort({ created_at: -1 })
|
||||||
|
.limit(pagination.limit)
|
||||||
|
.skip(pagination.offset),
|
||||||
|
])
|
||||||
|
|
||||||
|
const likedAtMap = new Map()
|
||||||
|
const itemIds = []
|
||||||
|
|
||||||
|
for (const like of likes) {
|
||||||
|
const itemId = like[config.idField]
|
||||||
|
|
||||||
|
likedAtMap.set(itemId, like.created_at)
|
||||||
|
itemIds.push(itemId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch track data
|
||||||
|
let processedItems = await config.class.get(itemIds, {
|
||||||
|
onlyList: true,
|
||||||
|
minimalData: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
// mix with likes data
|
||||||
|
processedItems = processedItems.map((item) => {
|
||||||
|
item.liked = true
|
||||||
|
item.liked_at = likedAtMap.get(item._id.toString())
|
||||||
|
return item
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
items: processedItems,
|
||||||
|
total_items: total,
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error processing ${config.type}:`, error)
|
||||||
|
return { items: [], total_items: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// A endpoint to fetch track & playlists & releases likes
|
// A endpoint to fetch track & playlists & releases likes
|
||||||
//
|
//
|
||||||
export default {
|
export default {
|
||||||
middlewares: ["withAuthentication"],
|
middlewares: ["withAuthentication"],
|
||||||
fn: async (req) => {
|
fn: async (req) => {
|
||||||
const user_id = req.auth.session.user_id
|
const userId = req.auth.session.user_id
|
||||||
const { limit, offset } = req.query
|
const { limit = 50, offset = 0 } = req.query
|
||||||
|
|
||||||
const [
|
const activeHandlers = Object.values(HANDLERS)
|
||||||
totalTrackLikes,
|
|
||||||
totalReleasesLikes,
|
|
||||||
totalPlaylistsLikes,
|
|
||||||
] = await Promise.all([
|
|
||||||
TrackLike.countDocuments({ user_id }),
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
])
|
|
||||||
|
|
||||||
let [
|
const results = await Promise.all(
|
||||||
trackLikes,
|
activeHandlers.map((handler) =>
|
||||||
releasesLikes,
|
getLikedItemsFromHandler(handler, userId, { limit, offset }),
|
||||||
playlistsLikes
|
),
|
||||||
] = await Promise.all([
|
)
|
||||||
TrackLike.find({
|
|
||||||
user_id
|
|
||||||
})
|
|
||||||
.limit(limit)
|
|
||||||
.skip(offset),
|
|
||||||
[],
|
|
||||||
[],
|
|
||||||
])
|
|
||||||
|
|
||||||
let [
|
return activeHandlers.reduce((response, handler, index) => {
|
||||||
Tracks,
|
response[handler.type] = results[index]
|
||||||
Releases,
|
return response
|
||||||
Playlists,
|
}, {})
|
||||||
] = await Promise.all([
|
},
|
||||||
TrackClass.get(trackLikes.map(trackLike => trackLike.track_id), {
|
|
||||||
user_id,
|
|
||||||
onlyList: true,
|
|
||||||
}),
|
|
||||||
[],
|
|
||||||
[],
|
|
||||||
])
|
|
||||||
|
|
||||||
Tracks = Tracks.sort((a, b) => b.liked_at - a.liked_at)
|
|
||||||
// Releases = Releases.sort((a, b) => b.liked_at - a.liked_at)
|
|
||||||
// Playlists = Playlists.sort((a, b) => b.liked_at - a.liked_at)
|
|
||||||
|
|
||||||
return {
|
|
||||||
tracks: {
|
|
||||||
list: Tracks,
|
|
||||||
total_items: totalTrackLikes,
|
|
||||||
},
|
|
||||||
releases: {
|
|
||||||
list: Releases,
|
|
||||||
total_items: totalReleasesLikes,
|
|
||||||
},
|
|
||||||
playlists: {
|
|
||||||
list: Playlists,
|
|
||||||
total_items: totalPlaylistsLikes,
|
|
||||||
},
|
|
||||||
total_length: totalTrackLikes + totalReleasesLikes + totalPlaylistsLikes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -16,6 +16,20 @@ export default {
|
|||||||
.limit(req.query.limit ?? 20)
|
.limit(req.query.limit ?? 20)
|
||||||
.sort({ created_at: -1 })
|
.sort({ created_at: -1 })
|
||||||
|
|
||||||
|
// filter tracks has different service than comtymusic
|
||||||
|
activities = activities.map((activity) => {
|
||||||
|
if (activity.payload.service && activity.payload.service !== "default") {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return activity
|
||||||
|
})
|
||||||
|
|
||||||
|
// filter null & undefined tracks
|
||||||
|
activities = activities.filter((activity) => {
|
||||||
|
return activity
|
||||||
|
})
|
||||||
|
|
||||||
// filter undefined tracks_ids
|
// filter undefined tracks_ids
|
||||||
activities = activities.filter((activity) => {
|
activities = activities.filter((activity) => {
|
||||||
return activity.payload && activity.payload.track_id
|
return activity.payload && activity.payload.track_id
|
||||||
|
@ -2,33 +2,33 @@ import { MusicRelease, Track } from "@db_models"
|
|||||||
import TrackClass from "@classes/track"
|
import TrackClass from "@classes/track"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
middlewares: ["withOptionalAuthentication"],
|
middlewares: ["withOptionalAuthentication"],
|
||||||
fn: async (req) => {
|
fn: async (req) => {
|
||||||
const { release_id } = req.params
|
const { release_id } = req.params
|
||||||
const { limit = 50, offset = 0 } = req.query
|
const { limit = 50, offset = 0 } = req.query
|
||||||
|
|
||||||
let release = await MusicRelease.findOne({
|
let release = await MusicRelease.findOne({
|
||||||
_id: release_id
|
_id: release_id,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!release) {
|
if (!release) {
|
||||||
throw new OperationError(404, "Release not found")
|
throw new OperationError(404, "Release not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
release = release.toObject()
|
release = release.toObject()
|
||||||
|
|
||||||
const totalTracks = await Track.countDocuments({
|
const totalTracks = await Track.countDocuments({
|
||||||
_id: release.list
|
_id: release.list,
|
||||||
})
|
})
|
||||||
|
|
||||||
const tracks = await TrackClass.get(release.list, {
|
const tracks = await TrackClass.get(release.list, {
|
||||||
user_id: req.auth?.session?.user_id,
|
user_id: req.auth?.session?.user_id,
|
||||||
onlyList: true
|
onlyList: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
release.listLength = totalTracks
|
release.listLength = totalTracks
|
||||||
release.list = tracks
|
release.items = tracks
|
||||||
|
|
||||||
return release
|
return release
|
||||||
}
|
},
|
||||||
}
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
import { TrackOverride } from "@db_models"
|
||||||
|
|
||||||
|
export default async (req) => {
|
||||||
|
const { track_id } = req.params
|
||||||
|
const { service } = req.query
|
||||||
|
|
||||||
|
const trackOverride = await TrackOverride.findOne({
|
||||||
|
track_id: track_id,
|
||||||
|
service: service,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!trackOverride) {
|
||||||
|
throw new OperationError(404, "Track override not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return trackOverride.override
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
import { TrackOverride } from "@db_models"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
middlewares: ["withAuthentication", "onlyAdmin"],
|
||||||
|
fn: async (req) => {
|
||||||
|
const { track_id } = req.params
|
||||||
|
const { service, override } = req.body
|
||||||
|
|
||||||
|
let trackOverride = await TrackOverride.findOne({
|
||||||
|
track_id: track_id,
|
||||||
|
service: service,
|
||||||
|
}).catch(() => null)
|
||||||
|
|
||||||
|
if (!trackOverride) {
|
||||||
|
trackOverride = new TrackOverride({
|
||||||
|
track_id: track_id,
|
||||||
|
service: service,
|
||||||
|
override: override,
|
||||||
|
})
|
||||||
|
|
||||||
|
await trackOverride.save()
|
||||||
|
} else {
|
||||||
|
trackOverride = await TrackOverride.findOneAndUpdate(
|
||||||
|
{
|
||||||
|
track_id: track_id,
|
||||||
|
service: service,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
override: override,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return trackOverride.override
|
||||||
|
}
|
||||||
|
}
|
@ -8,7 +8,9 @@ export default {
|
|||||||
let results = []
|
let results = []
|
||||||
|
|
||||||
for await (const item of req.body.list) {
|
for await (const item of req.body.list) {
|
||||||
requiredFields(["title", "source"], item)
|
if (!item.source || !item.title) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
const track = await TrackClass.create({
|
const track = await TrackClass.create({
|
||||||
...item,
|
...item,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user