From 5db0863943882b1091c6b4f81ee07e9d227546b0 Mon Sep 17 00:00:00 2001 From: SrGooglo Date: Wed, 31 May 2023 01:38:02 +0000 Subject: [PATCH] split services --- .../lyrics/routes/get/:track_id.js | 177 ++---------------- .../src/services/findSpotifyId.js | 45 +++++ .../services/getEnhancedLyricsFromTrack.js | 73 ++++++++ 3 files changed, 137 insertions(+), 158 deletions(-) create mode 100644 packages/music_server/src/services/findSpotifyId.js create mode 100644 packages/music_server/src/services/getEnhancedLyricsFromTrack.js diff --git a/packages/music_server/src/controllers/lyrics/routes/get/:track_id.js b/packages/music_server/src/controllers/lyrics/routes/get/:track_id.js index 4ea93ec6..4eac5142 100644 --- a/packages/music_server/src/controllers/lyrics/routes/get/:track_id.js +++ b/packages/music_server/src/controllers/lyrics/routes/get/:track_id.js @@ -1,58 +1,8 @@ -const syncLyricsProvider = `https://spotify-lyric-api.herokuapp.com` -const canvasProvider = `https://api.delitefully.com/api/canvas` import { Track } from "@models" -import axios from "axios" - -const clearQueryRegexs = [ - // remove titles with (feat. Something) - new RegExp(/\(feat\..*\)/, "gi"), - // remplace $ with S - new RegExp(/\$/, "gi"), - // remove special characters - new RegExp(/[\(\)\[\]\$\&\*\#\@\!\%\+\=\_\-\:\;\'\"\,\.]/, "gi"), - // remove words like "official video", "official audio", "official music video" - new RegExp(/official\s(video|audio|music\svideo)/, "gi"), -] - -async function findSpotifyTrack({ - title, - artist, - sessionToken, -} = {}) { - let query = `${title} artist:${artist}` - - // run clear query regexs - for (const regex of clearQueryRegexs) { - query = query.replace(regex, "") - } - - const { data } = await global.comty.instances.default({ - method: "GET", - headers: { - "Authorization": `Bearer ${sessionToken}`, - }, - params: { - query: query, - type: "track", - }, - url: "/sync/spotify/search", - }).catch((error) => { - console.error(error.response.data) - - return null - }) - - if (!data) { - return null - } - - return data.tracks.items[0] -} +import getEnhancedLyricsFromTrack from "@services/getEnhancedLyricsFromTrack" export default async (req, res) => { - const noCache = req.query["no-cache"] === "true" - let track = await Track.findOne({ _id: req.params.track_id, }).catch((error) => { @@ -65,132 +15,43 @@ export default async (req, res) => { }) } - console.log(track) - if (!track.lyricsEnabled) { return res.status(403).json({ error: "Lyrics disabled for this track", }) } - //console.log("Found track", track) + const noCache = req.query["no-cache"] === "true" - track = track.toObject() + let data = null - let lyricData = { - syncType: null, - lines: null, - canvas_url: null, + if (!noCache) { + data = await global.redis.get(`lyrics:${track._id.toString()}`) + + if (data) { + data = JSON.parse(data) + } } - let cachedData = null - try { - if (!noCache) { - cachedData = await global.redis.get(`lyrics:${track._id}`) + if (!data) { + data = await getEnhancedLyricsFromTrack(track, { req }) - if (cachedData) { - lyricData = JSON.parse(cachedData) - } - - if (track.videoCanvas) { - lyricData.canvas_url = track.videoCanvas - } + await global.redis.set(`lyrics:${track._id.toString()}`, JSON.stringify(data), "EX", 60 * 60 * 24 * 30) } - if (!cachedData) { - // no cache, recosntruct lyrics data - - // first check if track has spotify id to fetch the lyrics - // if not present, try to search from spotify api and update the track with the spotify id - if (!track.spotifyId) { - if (!req.session) { - throw new Error("Session not found and track has no spotify id") - } - - console.log("Fetching spotify track") - - const spotifyTrack = await findSpotifyTrack({ - title: track.title, - artist: track.artist, - sessionToken: req.sessionToken, - }) - - console.log(spotifyTrack) - - if (spotifyTrack.id) { - track.spotifyId = spotifyTrack.id - - console.log("Updating track with spotify id") - - const result = await Track.findOneAndUpdate({ - _id: track._id.toString(), - }, { - spotifyId: spotifyTrack.id, - }) - - console.log(result) - } else { - throw new Error("Failed to search spotify id") - } - } - - // ok now we have the spotify id, try to fetch the lyrics - console.log("Fetching lyrics from sync provider, ID:", track.spotifyId) - - let { data } = await axios.get(`${syncLyricsProvider}/?trackid=${track.spotifyId}`) - - lyricData.syncType = data.syncType - lyricData.lines = data.lines - - // so we have the lyrics, now check if track has videoCanvas - // if not present, try to fetch from canvas provider and update the track with the videoCanvas - // handle errors silently - if (track.videoCanvas) { - lyricData.canvas_url = track.videoCanvas - } else { - try { - console.log("Fetching canvas for id", track.spotifyId) - - const { data } = await axios.get(`${canvasProvider}/${track.spotifyId}`) - - lyricData.canvas_url = data.canvas_url - - console.log("Updating track with canvas url") - - await Track.findOneAndUpdate({ - _id: track._id.toString(), - }, { - videoCanvas: data.canvas_url, - }) - } catch (error) { - console.error(error) - } - } - - // force rewrite cache - await global.redis.set(`lyrics:${track._id}`, JSON.stringify(data)) - - // check - // const _cachedData = await global.redis.get(`lyrics:${track._id}`) - - // console.log("Cached data", _cachedData, data) + if (!data.lines) { + return res.status(404).json({ + error: "Lyrics not found", + }) } + + return res.json(data) } catch (error) { console.error(error) return res.status(500).json({ - error: `Failed to generate lyrics for track ${track._id}`, + error: "Failed to generate lyrics", }) } - - if (!lyricData.lines) { - return res.status(404).json({ - error: "Lyrics not found", - }) - } - - //console.log("Lyrics data", lyricData) - - return res.json(lyricData) } \ No newline at end of file diff --git a/packages/music_server/src/services/findSpotifyId.js b/packages/music_server/src/services/findSpotifyId.js new file mode 100644 index 00000000..0b3003ad --- /dev/null +++ b/packages/music_server/src/services/findSpotifyId.js @@ -0,0 +1,45 @@ +const clearQueryRegexs = [ + // remove titles with (feat. Something) + new RegExp(/\(feat\..*\)/, "gi"), + // remplace $ with S + new RegExp(/\$/, "gi"), + // remove special characters + new RegExp(/[\(\)\[\]\$\&\*\#\@\!\%\+\=\_\-\:\;\'\"\,\.]/, "gi"), + // remove words like "official video", "official audio", "official music video" + new RegExp(/official\s(video|audio|music\svideo)/, "gi"), +] + +export default async ({ + title, + artist, + sessionToken, +} = {}) => { + let query = `${title} artist:${artist}` + + // run clear query regexs + for (const regex of clearQueryRegexs) { + query = query.replace(regex, "") + } + + const { data } = await global.comty.instances.default({ + method: "GET", + headers: { + "Authorization": `Bearer ${sessionToken}`, + }, + params: { + query: query, + type: "track", + }, + url: "/sync/spotify/search", + }).catch((error) => { + console.error(error.response.data) + + return null + }) + + if (!data) { + return null + } + + return data.tracks.items[0] +} \ No newline at end of file diff --git a/packages/music_server/src/services/getEnhancedLyricsFromTrack.js b/packages/music_server/src/services/getEnhancedLyricsFromTrack.js new file mode 100644 index 00000000..1aa0a5e5 --- /dev/null +++ b/packages/music_server/src/services/getEnhancedLyricsFromTrack.js @@ -0,0 +1,73 @@ +import findSpotifyId from "@services/findSpotifyId" +import { Track } from "@models" +import axios from "axios" + +const syncLyricsProvider = `https://spotify-lyric-api.herokuapp.com` +const canvasProvider = `https://api.delitefully.com/api/canvas` + +export default async (track, { req }) => { + if (typeof track !== "object") { + throw new Error("Track must be an object") + } + + if (!track._id) { + throw new Error("Track must have an _id") + } + + if (!track.lyricsEnabled) { + throw new Error("Track lyrics are not enabled") + } + + let lyricData = { + syncType: null, + lines: null, + canvas_url: null, + } + + if (!track.spotifyId) { + if (!req.session) { + throw new Error("Session not found and track has no spotify id") + } + + const spotifyId = await findSpotifyId({ + track: track.title, + artist: track.artist, + sessionToken: req.sessionToken, + }, { req }) + + if (!spotifyId) { + throw new Error("Track has no spotify id") + } + + track.spotifyId = spotifyId + + await Track.findOneAndUpdate({ + _id: track._id.toString(), + }, { spotifyId }) + } + + let { data } = await axios.get(`${syncLyricsProvider}/?trackid=${track.spotifyId}`) + + lyricData.syncType = data.syncType + lyricData.lines = data.lines + + if (track.videoCanvas) { + lyricData.canvas_url = track.videoCanvas + } else { + try { + const { data } = await axios.get(`${canvasProvider}/${track.spotifyId}`) + + lyricData.canvas_url = data.canvas_url + + await Track.findOneAndUpdate({ + _id: track._id.toString(), + }, { + videoCanvas: data.canvas_url, + }) + } catch (err) { + //console.log(err.response.data) + } + } + + return lyricData +} \ No newline at end of file