const cron = require("node-cron"); const fs = require('fs'); const express = require('express'); const app = express(); const app_serve = express(); const mysql = require('mysql2') const SendSeekable = require('send-seekable'); const WebSocket = require('ws'); const pool = mysql.createPool({ keepAliveInitialDelay: 10000, enableKeepAlive: true, }) const db = mysql.createConnection({ host: 'mc.andyxie.cn', user: 'instrunet', password: 'Moyingren2015', database: "instrunet_data", pool: pool, }) const nodemailer = require('nodemailer') const bodyParser = require("body-parser"); const nrc = require('node-run-cmd') const https = require("node:https"); const {WebSocketServer} = require("ws"); const http = require("node:http"); const {OpenCC} = require("opencc"); const converter = new OpenCC('s2t.json') app.use(bodyParser.json({"limit": "200mb"})); app.use(express.json()); app_serve.use(bodyParser.json({"limit": "200mb"})); app_serve.use(express.json()); app_serve.use(SendSeekable) const transporter = nodemailer.createTransport({ host: 'smtp.qq.com', port: 465, secure: true, auth: { user: '3095864740@qq.com', pass: 'caemyuagapsadfff', } }) app.post('/submit', function (req, res) { let uuid = crypto.randomUUID() db.connect(function (err) { if (err) { console.log(err) } }) res.header("Access-Control-Allow-Origin", "*"); let albumCover = null; try { fetch(req.body.file).then(res => { res.arrayBuffer().then(r => fs.writeFileSync("./" + uuid, Buffer.from(r))); }) fetch(req.body.albumCover).then(res=>{ res.arrayBuffer().then(r=>{ albumCover = r }) }) res.end("api_success"); } catch (err) { res.status(500).send("Server Error"); return } const callback = function (d) { console.log(d.toString()); } const errcb = function (d) { console.log(d.toString()); } let kind_of = []; switch (req.body.kind) { case 0: kind_of[0] = `audio-separator ./${uuid} --model_filename UVR-MDX-NET-Inst_HQ_5.onnx --mdx_segment_size 4000 --mdx_overlap 0.75 --output_format mp3 --mdx_batch_size 300 --output_dir output` kind_of[1] = `./output/${uuid}_(Instrumental)_UVR-MDX-NET-Inst_HQ_5.mp3` kind_of[2] = `${uuid}_(Instrumental)_UVR-MDX-NET-Inst_HQ_5.mp3` kind_of[3] = `./output/${uuid}_(Vocals)_UVR-MDX-NET-Inst_HQ_5.mp3` break; case 1: kind_of[0] = `audio-separator ./${uuid} --model_filename UVR_MDXNET_KARA.onnx --mdx_segment_size 4000 --mdx_overlap 0.75 --output_format mp3 --mdx_batch_size 300 --output_dir output` kind_of[1] = `./output/${uuid}_(Instrumental)_UVR_MDXNET_KARA.mp3` kind_of[2] = `${uuid}_(Instrumental)_UVR_MDXNET_KARA.mp3` kind_of[3] = `./output/${uuid}_(Vocals)_UVR_MDXNET_KARA.mp3` break; case 3: kind_of[0] = `audio-separator ./${uuid} --model_filename kuielab_a_bass.onnx --mdx_segment_size 4000 --mdx_overlap 0.75 --output_format mp3 --mdx_batch_size 300 --output_dir output` kind_of[1] = `./output/${uuid}_(Bass)_kuielab_a_bass.mp3` kind_of[2] = `${uuid}_(Bass)_kuielab_a_bass.mp3` kind_of[3] = `./output/${uuid}_(No Bass)_kuielab_a_bass.mp3` break; case 4: kind_of[0] = `audio-separator ./${uuid} --model_filename kuielab_a_drums.onnx --mdx_segment_size 4000 --mdx_overlap 0.75 --output_format mp3 --mdx_batch_size 300 --output_dir output` kind_of[1] = `./output/${uuid}_(Drums)_kuielab_a_drums.mp3` kind_of[2] = `${uuid}_(Drums)_kuielab_a_drums.mp3` kind_of[3] = `./output/${uuid}_(No Drums)_kuielab_a_drums.mp3` break; } nrc.run([kind_of[0]], { onData: callback, onError: errcb }).then(() => { db.execute(("INSERT INTO instrunet_entry (uuid, song_name, album_name, link_to, databinary, artist,kind, albumcover) VALUES (?,?,?,?,?,?,?,?)"), [uuid, req.body.name, req.body.albumName, req.body.link, fs.readFileSync(kind_of[1]), req.body.artist, req.body.kind, albumCover]) db.unprepare(() => { }) fs.rm(kind_of[1], (err) => { if (err) { console.log(err); } }) fs.rm(kind_of[3], (err) => { if (err) { console.log(err); } }) fs.rm(uuid, (err) => { if (err) { console.log(err); } }) if (req.body.email !== undefined) { console.log(req.body.email) transporter.sendMail({ from: '"xiey0" ', to: req.body.email, subject: "你的音频已处理完成。", text: "你的音频已处理完成。", html: fs.readFileSync("./Template.html", "utf8").toString().replace("{song_name}", req.body.name).replace("{href_link}", "https://andyxie.cn:4000/player?play="+uuid) }).then((result) => { console.log("Message sent: %s", result.messageId) }) } }) }) app.options('/submit', function (req, res) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Content-Type"); res.end() }) app.post('/search_api', async function (req, res) { async function OnFetched(err, rows) { try { db.execute(`SELECT uuid, song_name, album_name, artist, kind FROM instrunet_entry WHERE song_name like '%${(req.body.searchStr)}%' or album_name like '%${(req.body.searchStr)}%' or artist like '%${(req.body.searchStr)}%'`, (err, result) => { res.header("Access-Control-Allow-Origin", "*"); res.end(JSON.stringify(result) === JSON.stringify(rows) ? JSON.stringify(rows) : JSON.stringify(rows.concat(result))); }) } catch (e) { console.log(e) } } db.execute(`SELECT uuid, song_name, album_name, artist, kind FROM instrunet_entry WHERE song_name like '%${await converter.convertPromise(req.body.searchStr)}%' or album_name like '%${await converter.convertPromise(req.body.searchStr)}%' or artist like '%${await converter.convertPromise(req.body.searchStr)}%'`, OnFetched) db.unprepare() }) app.options('/search_api', function (req, res) { res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Content-Type"); res.end() }) app.get("/getSingle", function (req, res) { if (req.query.id) { db.execute(`SELECT song_name, album_name, artist, kind, albumcover FROM instrunet_entry WHERE uuid = "${req.query.id}"`, function (err, rows) { if (err) { console.log(err); } res.contentType("application/json"); res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Content-Type"); res.end(JSON.stringify(rows[0])); }) } else { res.contentType("application/json"); res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Content-Type"); res.end("{}") } }) var availCache = {} cron.schedule('* */12 * * *', () => { availCache = {} }) app_serve.get('/:uuid', function (req, res, next) { let uuid = req.params.uuid; function Provider(err, rows) { try { res.contentType("audio/mp3"); res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Content-Type"); res.header("Access-Control-Allow-Origin", "*"); res.header('Content-Disposition', `attachment; filename="${encodeURI(rows[0].song_name)}"`); /** @type {ArrayBuffer}*/ availCache[uuid] = rows[0].databinary res.sendSeekable(availCache[uuid]) } catch (e) { console.log(e) console.log("Triggered err"); } } if (availCache[uuid] !== undefined) { db.execute(`SELECT song_name FROM instrunet_entry WHERE uuid = '${uuid}'`, (err, rows) => { res.contentType("audio/mp3"); res.header("Access-Control-Allow-Origin", "*"); res.header("Access-Control-Allow-Headers", "Content-Type"); res.header("Access-Control-Allow-Origin", "*"); res.header('Content-Disposition', `attachment; filename="${encodeURI(rows[0].song_name)}"`); res.sendSeekable(availCache[uuid]) }) } else { db.execute(`SELECT song_name, databinary FROM instrunet_entry WHERE uuid = '${uuid}'`, Provider) db.unprepare() } }) // TODO Always use HTTPS before publishing. // https.createServer({ // key: fs.readFileSync('andyxie.cn.key'), cert: fs.readFileSync('andyxie.cn.pem') // }, app).listen(8080) // // // // https.createServer({ // key: fs.readFileSync('andyxie.cn.key'), cert: fs.readFileSync('andyxie.cn.pem') // // }, app_serve).listen(8079) app.listen(8080) app_serve.listen(8079)