Implement song tagging
This commit is contained in:
parent
e70ce4a9ca
commit
eb9263972e
2 changed files with 78 additions and 30 deletions
107
index.js
107
index.js
|
@ -1,5 +1,5 @@
|
|||
require('dotenv').config();
|
||||
const { Readable } = require("stream");
|
||||
const { Readable, PassThrough } = require("stream");
|
||||
const { finished } = require("stream/promises");
|
||||
const { searchMusics } = require('fix-esm').require("node-youtube-music");
|
||||
const { GetListByKeyword } = require("youtube-search-api");
|
||||
|
@ -9,9 +9,10 @@ const path = require("path");
|
|||
const { readFileSync, writeFileSync } = require("fs");
|
||||
const io = require('socket.io-client');
|
||||
const { program } = require('commander');
|
||||
const NodeID3 = require('node-id3');
|
||||
|
||||
function pathGenerator({ url, name, channelName }) {
|
||||
return path.join(process.env.NEXTCLOUD_FOLDER, `${url}-${skewered(`${name} - ${channelName}`)}.mp3`)
|
||||
return `${url}-${skewered(`${name} - ${channelName}`)}.mp3`;
|
||||
}
|
||||
|
||||
function checkLastSong({ name, channelName }) {
|
||||
|
@ -28,6 +29,7 @@ function writeLastSong({ name, channelName }) {
|
|||
|
||||
async function getVideo({ msName, msArtist }) {
|
||||
let trackData;
|
||||
let tags;
|
||||
|
||||
if (msName != null && msArtist != null) {
|
||||
trackData = {
|
||||
|
@ -40,6 +42,17 @@ async function getVideo({ msName, msArtist }) {
|
|||
trackData = await fetch(
|
||||
`https://${process.env.LASTFM_INSTANCE}/2.0/?method=user.getrecenttracks&user=${process.env.LASTFM_USERNAME}&api_key=${process.env.LASTFM_API_KEY}&format=json&limit=1&extended=1`
|
||||
).then(x => x.json()).then(data => data.recenttracks.track[0]);
|
||||
|
||||
tags = {
|
||||
title: trackData.name,
|
||||
artist: trackData.artist.name,
|
||||
album: trackData.album["#text"],
|
||||
APIC: "./cover.png",
|
||||
userDefinedUrl: [{
|
||||
description: "Last.FM page",
|
||||
url: trackData.url
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
if (checkLastSong({
|
||||
|
@ -68,8 +81,6 @@ async function getVideo({ msName, msArtist }) {
|
|||
return skewered(song.title).includes(skewered(trackData.name));
|
||||
});
|
||||
|
||||
console.log(youtubeMusicVideo);
|
||||
|
||||
if (youtubeMusicVideo == null) {
|
||||
const videoList = await GetListByKeyword(`${trackData.artist.name} - ${trackData.name}`, false, 1, [
|
||||
{type: "video"}
|
||||
|
@ -91,7 +102,11 @@ async function getVideo({ msName, msArtist }) {
|
|||
|
||||
selectedVideo.channelName = selectedVideo.channelName.replace(/\s-\sTopic/ig, "");
|
||||
|
||||
return selectedVideo;
|
||||
return {
|
||||
tags,
|
||||
...selectedVideo,
|
||||
albumCover: trackData.image.at(-1)["#text"]
|
||||
};
|
||||
}
|
||||
|
||||
async function checkNextcloud({ url, name, channelName }, nextcloudClient) {
|
||||
|
@ -100,13 +115,12 @@ async function checkNextcloud({ url, name, channelName }, nextcloudClient) {
|
|||
return await nextcloudClient.exists(fileName);
|
||||
}
|
||||
|
||||
async function downloadFromCobalt({ url, name, channelName }) {
|
||||
async function downloadFromCobalt({ url }) {
|
||||
const processor = await fetch(`https://${process.env.COBALT_INSTANCE}/api/json`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
url: `https://youtu.be/${url}`,
|
||||
vCodec: "h264",
|
||||
vQuality: "144",
|
||||
aFormat: "mp3",
|
||||
filenamePattern: "basic",
|
||||
isAudioOnly: true,
|
||||
|
@ -142,23 +156,37 @@ async function downloadFromCobalt({ url, name, channelName }) {
|
|||
break;
|
||||
}
|
||||
|
||||
const { body } = await fetch(processorURL);
|
||||
const body = Buffer.from(await fetch(processorURL).then(x => x.arrayBuffer()));
|
||||
|
||||
return {
|
||||
fileStream: Readable.fromWeb(body),
|
||||
url,
|
||||
name,
|
||||
channelName
|
||||
};
|
||||
return body;
|
||||
}
|
||||
|
||||
async function uploadToNextcloud({ fileStream, url, name, channelName }, nextcloudClient) {
|
||||
await nextcloudClient.createDirectory(process.env.NEXTCLOUD_FOLDER, {
|
||||
async function downloadAlbumCover({ albumCover }) {
|
||||
const body = Buffer.from(await fetch(albumCover).then(x => x.arrayBuffer()));
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
function applyTags({ fileStream, tags }) {
|
||||
const body = NodeID3.update(tags, fileStream);
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
async function uploadToNextcloud({ fileStream, url, name, channelName, tags, albumCover }, nextcloudClient) {
|
||||
await nextcloudClient.createDirectory(path.join(process.env.NEXTCLOUD_FOLDER, tags.album), {
|
||||
recursive: true,
|
||||
});
|
||||
|
||||
const fileBufferStream = new PassThrough().end(fileStream);
|
||||
|
||||
const albumBufferStream = new PassThrough().end(albumCover);
|
||||
|
||||
const fileName = pathGenerator({ url, name, channelName });
|
||||
await finished(fileStream.pipe(nextcloudClient.createWriteStream(fileName)));
|
||||
|
||||
await finished(fileBufferStream.pipe(nextcloudClient.createWriteStream(path.join(process.env.NEXTCLOUD_FOLDER, fileName))));
|
||||
|
||||
await finished(albumBufferStream.pipe(nextcloudClient.createWriteStream(path.join(process.env.NEXTCLOUD_FOLDER, "cover.png"))));
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
@ -182,7 +210,6 @@ async function main() {
|
|||
msName: options.song,
|
||||
msArtist: options.artist
|
||||
});
|
||||
console.log(video);
|
||||
|
||||
if (video == null) return dismantle(socket);
|
||||
|
||||
|
@ -201,23 +228,43 @@ async function main() {
|
|||
password: process.env.NOTIFICATION_SERVER_PASSWORD
|
||||
})
|
||||
|
||||
const cobalt = await downloadFromCobalt(video);
|
||||
console.log(cobalt);
|
||||
const albumCover = await downloadAlbumCover(video);
|
||||
|
||||
socket.emit('nodeMessage', {
|
||||
message: `Nextcloud upload running - ${cobalt.name} from ${cobalt.channelName}`,
|
||||
password: process.env.NOTIFICATION_SERVER_PASSWORD
|
||||
});
|
||||
|
||||
const nextcloud = await uploadToNextcloud(cobalt, nextcloudClient);
|
||||
console.log(nextcloud);
|
||||
|
||||
socket.emit('nodeMessage', {
|
||||
message: `Nextcloud upload finished - ${cobalt.name} from ${cobalt.channelName}`,
|
||||
message: `Cobalt download starting - ${video.name} from ${video.channelName}`,
|
||||
password: process.env.NOTIFICATION_SERVER_PASSWORD
|
||||
})
|
||||
|
||||
|
||||
const cobalt = await downloadFromCobalt(video);
|
||||
|
||||
socket.emit('nodeMessage', {
|
||||
message: `Cobalt download finished - ${video.name} from ${video.channelName}`,
|
||||
password: process.env.NOTIFICATION_SERVER_PASSWORD
|
||||
});
|
||||
|
||||
const taggedMusic = applyTags({
|
||||
fileStream: cobalt,
|
||||
tags: video.tags
|
||||
});
|
||||
|
||||
socket.emit('nodeMessage', {
|
||||
message: `Nextcloud upload running - ${video.name} from ${video.channelName}`,
|
||||
password: process.env.NOTIFICATION_SERVER_PASSWORD
|
||||
});
|
||||
|
||||
const nextcloud = await uploadToNextcloud(
|
||||
{
|
||||
...video,
|
||||
fileStream: taggedMusic,
|
||||
albumCover: albumCover
|
||||
},
|
||||
nextcloudClient
|
||||
);
|
||||
|
||||
socket.emit('nodeMessage', {
|
||||
message: `Nextcloud upload finished - ${tags.name} from ${tags.channelName}`,
|
||||
password: process.env.NOTIFICATION_SERVER_PASSWORD
|
||||
})
|
||||
|
||||
return dismantle(socket);
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"dotenv": "^16.4.4",
|
||||
"express": "^4.18.2",
|
||||
"fix-esm": "^1.0.1",
|
||||
"node-id3": "^0.2.6",
|
||||
"node-notifier": "^10.0.1",
|
||||
"node-youtube-music": "^0.10.3",
|
||||
"skewered": "^1.0.0",
|
||||
|
|
Loading…
Reference in a new issue