commit
49958906c4
@ -0,0 +1,2 @@
|
||||
node_modules/
|
||||
.env
|
@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
@ -0,0 +1,20 @@
|
||||
https://discord.com/api/oauth2/authorize?client_id=1046007531811655690&permissions=2147813440&scope=bot
|
||||
|
||||
|
||||
|
||||
# Spotify Downloader - Discord Bot
|
||||
|
||||
An example of the Spotify-DL JavaScript wrapper of [clspotify](https://notabug.org/proprietary-is-bad/clspotify).
|
||||
|
||||
## Installation
|
||||
|
||||
Be sure to get a working install of clspotify. Then, clone the repository and run ``npm i``.
|
||||
|
||||
## Usage
|
||||
|
||||
Put a Discord token and the path to your clspotify install in the ``.env`` file, like this:
|
||||
|
||||
```.env
|
||||
DISCORD_TOKEN="YOUR TOKEN HERE"
|
||||
CLSPOTIFY_PATH="/home/username/clspotify"
|
||||
```
|
@ -0,0 +1,155 @@
|
||||
import fs from 'fs'
|
||||
import Eris from "eris"
|
||||
import spDl from 'spotify-dl'
|
||||
import fetch from 'node-fetch'
|
||||
import {FormData, File} from 'formdata-node'
|
||||
import archiver from 'archiver'
|
||||
import * as dotenv from 'dotenv'
|
||||
dotenv.config()
|
||||
|
||||
const FILES_GAY_USER = process.env.FILES_GAY_USER??null
|
||||
const FILES_GAY_PASS = process.env.FILES_GAY_PASS??null
|
||||
const DISCORD_TOKEN = process.env.DISCORD_TOKEN
|
||||
const CLSPOTIFY_PATH = process.env.CLSPOTIFY_PATH
|
||||
let FILES_GAY_SESSION
|
||||
|
||||
if (!CLSPOTIFY_PATH) {
|
||||
console.log('Please set the CLSPOTIFY_PATH environment variable.')
|
||||
process.exit()
|
||||
}
|
||||
|
||||
async function getFilesGaySession() {
|
||||
if (!FILES_GAY_USER || !FILES_GAY_PASS) {
|
||||
console.log('Not logged into files.gay. Uploading anonymously.')
|
||||
return
|
||||
}
|
||||
let loginReq = await fetch("https://files.gay/login", {
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
body: `username=${encodeURIComponent(FILES_GAY_USER)}&password=${encodeURIComponent(FILES_GAY_PASS)}`,
|
||||
method: "POST",
|
||||
redirect: 'manual'
|
||||
})
|
||||
|
||||
let responseCookies = Object.fromEntries(loginReq.headers.raw()['set-cookie'].join('; ').split(';').map(e => e.trim().split('=')))
|
||||
|
||||
FILES_GAY_SESSION = responseCookies.session
|
||||
return FILES_GAY_SESSION
|
||||
}
|
||||
|
||||
function generateRandomId(length = 50) {
|
||||
let chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
||||
let str = ''
|
||||
for (let i = 0; i < length; i++) {
|
||||
str += chars.charAt(Math.floor(Math.random() * chars.length))
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
if (!fs.existsSync('rips')) await fs.mkdirSync('rips')
|
||||
const ripsPath = fs.realpathSync('rips')
|
||||
|
||||
// Replace TOKEN with your bot account's token
|
||||
const bot = new Eris(DISCORD_TOKEN, {
|
||||
intents: [
|
||||
"guildMessages"
|
||||
]
|
||||
});
|
||||
|
||||
bot.on("ready", async () => { // When the bot is ready
|
||||
await getFilesGaySession() // Get the files.gay session
|
||||
console.log("Ready!"); // Log "Ready!"
|
||||
});
|
||||
|
||||
bot.on("error", (err) => {
|
||||
console.error(err); // or your preferred logger
|
||||
});
|
||||
|
||||
bot.on("messageCreate", async (msg) => {
|
||||
if (!msg.content.trim().startsWith('!')) return
|
||||
let command = msg.content.trim().split(' ')
|
||||
if(command[0]==='!dl') { // If the message content is "!dl"
|
||||
if (command.length>2) {
|
||||
bot.createMessage(msg.channel.id, "This command takes only one argument! ``!dl <link-to-spotify-album>``")
|
||||
return
|
||||
}
|
||||
let url = command[1]
|
||||
let urlObj
|
||||
try {
|
||||
urlObj = new URL(url)
|
||||
} catch (error) {
|
||||
bot.createMessage(msg.channel.id, "Your second argument is not a valid URL!")
|
||||
return
|
||||
}
|
||||
if (!url.host==='open.spotify.com') {
|
||||
bot.createMessage(msg.channel.id, "Your second argument is not a Spotify URL!")
|
||||
return
|
||||
}
|
||||
urlObj.search = ''
|
||||
url = urlObj.href
|
||||
|
||||
let sentMessage = await bot.createMessage(msg.channel.id, "Downloading!")
|
||||
|
||||
async function editMsg(newText) {
|
||||
return await bot.editMessage(sentMessage.channel.id, sentMessage.id, newText)
|
||||
}
|
||||
|
||||
let randomId = generateRandomId()
|
||||
const albumFolderPath = `${ripsPath}/${randomId}`
|
||||
await fs.promises.mkdir(albumFolderPath)
|
||||
|
||||
await spDl(url, albumFolderPath, {
|
||||
clspotifyPath: CLSPOTIFY_PATH,
|
||||
onProgress: (dat) => {
|
||||
if (dat.percent===100) return
|
||||
let text = `${dat.percent}%`
|
||||
let newSong = dat.complete[dat.complete.length-1]
|
||||
if (newSong) {
|
||||
text += ` - Finished downloading "${newSong.name}"`
|
||||
}
|
||||
editMsg(text)
|
||||
}
|
||||
})
|
||||
|
||||
await editMsg('Finished downloading.\nCompressing to .zip file')
|
||||
|
||||
const zipFilePath = `${ripsPath}/${randomId}.zip`
|
||||
|
||||
const output = fs.createWriteStream(zipFilePath)
|
||||
const archive = archiver('zip', {
|
||||
zlib: { level: 9 } // Sets the compression level.
|
||||
})
|
||||
archive.on('error', function(err) {
|
||||
throw err;
|
||||
})
|
||||
archive.pipe(output)
|
||||
output.on('close', async () => {
|
||||
fs.promises.rm(albumFolderPath, {recursive: true})
|
||||
await editMsg(`Finished downloading.\nCompressed. The zip file is ${new Intl.NumberFormat().format(Math.round(archive.pointer() / 1000000))} Megabytes.\nUploading to files.gay`)
|
||||
const form = new FormData()
|
||||
const file = new File([await fs.promises.readFile(zipFilePath)], "album.zip")
|
||||
form.set('file', file)
|
||||
|
||||
let filesGayHeaders = {}
|
||||
if (FILES_GAY_SESSION) filesGayHeaders.cookie = `session=${FILES_GAY_SESSION}`
|
||||
|
||||
let uploadReq = await fetch("https://files.gay/upload?json=1", {
|
||||
headers: filesGayHeaders,
|
||||
method: "POST",
|
||||
body: form
|
||||
})
|
||||
let respJson = await uploadReq.json()
|
||||
if (!respJson.success) {
|
||||
await editMsg('Something went wrong uploading the file. :(')
|
||||
return
|
||||
}
|
||||
await editMsg(`Finished! Download at: https://files.gay/f/${respJson.data.id}/dl`)
|
||||
await fs.promises.rm(zipFilePath)
|
||||
})
|
||||
archive.directory(albumFolderPath, false)
|
||||
archive.finalize()
|
||||
}
|
||||
});
|
||||
|
||||
bot.connect();
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "discord-spot",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"archiver": "^5.3.1",
|
||||
"dotenv": "^16.0.3",
|
||||
"eris": "^0.17.1",
|
||||
"formdata-node": "^5.0.0",
|
||||
"node-fetch": "^3.3.0",
|
||||
"spotify-dl": "git+https://git.gay/h/spotify-dl.git"
|
||||
}
|
||||
}
|
Loading…
Reference in new issue