first commit

This commit is contained in:
MeowcaTheoRange 2024-02-19 16:36:23 -06:00
commit 974aa4706a
4 changed files with 166 additions and 0 deletions

20
.env.example Normal file
View file

@ -0,0 +1,20 @@
# Last.fm
LASTFM_INSTANCE= # ws.audioscrobbler.com
LASTFM_USERNAME= # meowcatheorange
LASTFM_API_KEY= # cccccccccccccccccc...
LASTFM_SHARED_SECRET= # cccccccccccccccccc...
# Cobalt
COBALT_INSTANCE= # co.wuk.sh
# Nextcloud
NEXTCLOUD_INSTANCE= # next.abtmtr.link
NEXTCLOUD_USERNAME= # meowcatheorange
NEXTCLOUD_PASSWORD= # ccccc-ccccc-ccccc-ccccc-ccccc
NEXTCLOUD_FOLDER= # /Music/LastFMDownloader/

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
node_modules/
package-lock.json
.env

124
index.js Normal file
View file

@ -0,0 +1,124 @@
require('dotenv').config();
const process = require('process');
const { Readable } = require('stream');
// const { searchMusics } = require("fix-esm").require('node-youtube-music');
const { GetListByKeyword } = require("youtube-search-api");
const skewered = require("skewered");
const { createClient } = require('fix-esm').require("webdav");
const path = require("path");
function pathGenerator({ url, name, channelName }) {
return path.join(process.env.NEXTCLOUD_FOLDER, `${url}-${skewered(`${name} - ${channelName}`)}.mp3`)
}
async function getVideo() {
const 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]);
// const musics = await searchMusics(`${trackData.artist.name} - ${trackData.name}`);
const videoList = await GetListByKeyword(`${trackData.artist.name} - ${trackData.name}`, false, 1, [
{type: "video"}
]);
const musicVideo = videoList.items[0];
return {
url: musicVideo.id,
name: musicVideo.title,
channelName: musicVideo.channelTitle
};
}
async function checkNextcloud({ url, name, channelName }, nextcloudClient) {
const fileName = pathGenerator({ url, name, channelName });
return await nextcloudClient.exists(fileName);
}
async function downloadFromCobalt({ url, name, channelName }) {
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,
disableMetadata: false
}),
headers: [
["Accept", "application/json"],
["Content-Type", "application/json"],
]
}).then(x => x.json());
let processorURL;
switch (processor.status) {
case 'error':
case 'rate-limit':
throw new Error(`Error! (${processor.text})`);
case 'redirect':
processorURL = processor.audio || processor.url;
break;
case 'picker':
throw new Error("Can't handle picker!");
case 'stream':
const streamProcessor = await fetch(`${processor.url}&p=1`).then(x => x.json());
if (streamProcessor.status === "continue")
processorURL = processor.audio || processor.url;
else processorURL = processor.audio || processor.url;
break;
default:
processorURL = processor.audio || processor.url;
break;
}
const { body } = await fetch(processorURL);
return {
fileStream: Readable.fromWeb(body),
url,
name,
channelName
};
}
async function uploadToNextcloud({ fileStream, url, name, channelName }, nextcloudClient) {
await nextcloudClient.createDirectory(process.env.NEXTCLOUD_FOLDER, {
recursive: true,
});
const fileName = pathGenerator({ url, name, channelName });
fileStream.pipe(nextcloudClient.createWriteStream(fileName));
return fileName;
}
async function main() {
const video = await getVideo();
console.log(video);
const nextcloudClient = createClient(
`https://${process.env.NEXTCLOUD_INSTANCE}/remote.php/dav/files/${process.env.NEXTCLOUD_USERNAME}/`,
{
username: process.env.NEXTCLOUD_USERNAME,
password: process.env.NEXTCLOUD_PASSWORD,
}
);
if (await checkNextcloud(video, nextcloudClient)) return null;
const cobalt = await downloadFromCobalt(video);
console.log(cobalt);
const nextcloud = await uploadToNextcloud(cobalt, nextcloudClient);
console.log(nextcloud);
return nextcloud;
}
main();

19
package.json Normal file
View file

@ -0,0 +1,19 @@
{
"name": "lastfm-downloader",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"dotenv": "^16.4.4",
"fix-esm": "^1.0.1",
"skewered": "^1.0.0",
"webdav": "^5.3.2",
"youtube-search-api": "^1.2.1"
}
}