mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-12 03:54:16 +00:00
split services
This commit is contained in:
parent
6eb69a8ef8
commit
5db0863943
@ -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 { Track } from "@models"
|
||||||
import axios from "axios"
|
import getEnhancedLyricsFromTrack from "@services/getEnhancedLyricsFromTrack"
|
||||||
|
|
||||||
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]
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const noCache = req.query["no-cache"] === "true"
|
|
||||||
|
|
||||||
let track = await Track.findOne({
|
let track = await Track.findOne({
|
||||||
_id: req.params.track_id,
|
_id: req.params.track_id,
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
@ -65,132 +15,43 @@ export default async (req, res) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(track)
|
|
||||||
|
|
||||||
if (!track.lyricsEnabled) {
|
if (!track.lyricsEnabled) {
|
||||||
return res.status(403).json({
|
return res.status(403).json({
|
||||||
error: "Lyrics disabled for this track",
|
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 = {
|
if (!noCache) {
|
||||||
syncType: null,
|
data = await global.redis.get(`lyrics:${track._id.toString()}`)
|
||||||
lines: null,
|
|
||||||
canvas_url: null,
|
if (data) {
|
||||||
|
data = JSON.parse(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let cachedData = null
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!noCache) {
|
if (!data) {
|
||||||
cachedData = await global.redis.get(`lyrics:${track._id}`)
|
data = await getEnhancedLyricsFromTrack(track, { req })
|
||||||
|
|
||||||
if (cachedData) {
|
await global.redis.set(`lyrics:${track._id.toString()}`, JSON.stringify(data), "EX", 60 * 60 * 24 * 30)
|
||||||
lyricData = JSON.parse(cachedData)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (track.videoCanvas) {
|
|
||||||
lyricData.canvas_url = track.videoCanvas
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cachedData) {
|
if (!data.lines) {
|
||||||
// no cache, recosntruct lyrics data
|
return res.status(404).json({
|
||||||
|
error: "Lyrics not found",
|
||||||
// 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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res.json(data)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
|
||||||
return res.status(500).json({
|
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)
|
|
||||||
}
|
}
|
45
packages/music_server/src/services/findSpotifyId.js
Normal file
45
packages/music_server/src/services/findSpotifyId.js
Normal file
@ -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]
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user