added likes logic

This commit is contained in:
SrGooglo 2023-07-05 19:05:52 +00:00
parent c2bff2a092
commit b2eb2a94fb
6 changed files with 160 additions and 4 deletions

View File

@ -1,11 +1,14 @@
import { Playlist, Track } from "@models"
import { AuthorizationError, PermissionError, NotFoundError } from "@shared-classes/Errors"
import RemoveTracks from "@services/removeTracks"
export default async (req, res) => {
if (!req.session) {
return new AuthorizationError(req, res)
}
let removedTracksIds = []
const removeWithTracks = req.query.remove_with_tracks === "true"
let playlist = await Playlist.findOne({
@ -27,12 +30,11 @@ export default async (req, res) => {
})
if (removeWithTracks) {
await Track.deleteMany({
_id: playlist.tracks,
})
removedTracksIds = await RemoveTracks(playlist.list)
}
return res.json({
success: true,
removedTracksIds,
})
}

View File

@ -1,4 +1,4 @@
import { Playlist, Track } from "@models"
import { Playlist, TrackLike, Track } from "@models"
import { NotFoundError } from "@shared-classes/Errors"
export default async (req, res) => {
@ -37,5 +37,20 @@ export default async (req, res) => {
return orderedIds.findIndex((id) => id === a._id.toString()) - orderedIds.findIndex((id) => id === b._id.toString())
})
if (req.session) {
const likes = await TrackLike.find({
user_id: req.session.user_id,
track_id: [...playlist.list.map((track) => track._id.toString())],
})
playlist.list = playlist.list.map((track) => {
track = track.toObject()
track.liked = likes.findIndex((like) => like.track_id === track._id.toString()) !== -1
return track
})
}
return res.json(playlist)
}

View File

@ -1,5 +1,6 @@
import { Playlist, Track } from "@models"
import { AuthorizationError, NotFoundError, PermissionError, BadRequestError } from "@shared-classes/Errors"
import axios from "axios"
const PlaylistAllowedUpdateFields = [
"title",
@ -23,6 +24,29 @@ const TrackAllowedUpdateFields = [
"public",
]
async function fetchTrackSourceMetadata(track) {
// get headers of source url (X-Amz-Meta-Duration)
const response = await axios({
method: "HEAD",
url: track.source,
}).catch((err) => {
return {
data: null,
headers: null,
}
})
if (response.headers) {
return {
duration: response.headers["x-amz-meta-duration"],
size: response.headers["content-length"],
bitrate: response.headers["x-amz-meta-bitrate"],
}
}
return null
}
async function createOrUpdateTrack(payload) {
if (!payload.title || !payload.source || !payload.publisher) {
throw new Error("title and source and publisher are required")
@ -54,6 +78,12 @@ async function createOrUpdateTrack(payload) {
await track.save()
}
if (!track.metadata) {
track.metadata = await fetchTrackSourceMetadata(track)
await track.save()
}
return track
}

View File

@ -0,0 +1,46 @@
import { TrackLike, Track } from "@models"
import { AuthorizationError, NotFoundError } from "@shared-classes/Errors"
export default async (req, res) => {
if (!req.session) {
return new AuthorizationError(req, res)
}
const { track_id } = req.params
const track = await Track.findById(track_id).catch((err) => {
return null
})
if (!track) {
return new NotFoundError(req, res, "Track not found")
}
let like = await TrackLike.findOne({
track_id: track_id,
user_id: req.session.user_id,
})
if (like) {
await like.delete()
like = null
} else {
like = new TrackLike({
track_id: track_id,
user_id: req.session.user_id,
})
await like.save()
}
global.ws.io.emit("music:self:track:toggle:like", {
track_id: track_id,
user_id: req.session.user_id,
action: like ? "liked" : "unliked",
})
return res.status(200).json({
message: "ok",
action: like ? "liked" : "unliked",
})
}

View File

@ -0,0 +1,14 @@
export default {
name: "TrackLike",
collection: "tracks_likes",
schema: {
user_id: {
type: String,
required: true,
},
track_id: {
type: String,
required: true,
}
}
}

View File

@ -0,0 +1,49 @@
import { Track } from "@models"
const urlRegex = new RegExp(`^https://(.*?)/(.*)$`)
export default async (tracksIds) => {
if (typeof tracksIds === "string") {
tracksIds = [tracksIds]
}
const removedIds = []
// find Tracks
const tracks = await Track.find({
_id: tracksIds,
})
for (const track of tracks) {
const match = urlRegex.exec(track.source)
const bucket = match[2].split("/")[0]
const objectName = match[2].split("/").slice(1).join("/")
try {
// find on storage and remove
await new Promise((resolve, reject) => {
global.storage.removeObject(bucket, objectName, (err) => {
if (err) {
return reject(err)
}
return resolve()
})
}).catch((err) => {
console.error(err)
return false
})
// remove from db
await track.remove()
} catch (error) {
console.error(error)
continue
}
removedIds.push(track._id)
}
return removedIds
}