//dotenv require('dotenv').config(); //ffmpeg var ffmpeg = require('fluent-ffmpeg'); //nextcloud client const { Client, Server, GetFilesRecursivelyCommand, CommandStatus } = require("nextcloud-node-client"); const server = new Server({ basicAuth: { password: process.env.nextcloud_PASSWD, username: process.env.nextcloud_ID, }, url: process.env.nextcloud_URL, }); //built-in const path = require("path"); const fs = require('fs').promises; const util = require('util'); // const { pipeline } = require('stream'); // const pump = util.promisify(pipeline); //uuid const { v1: uuidv1, v4: uuidv4, } = require('uuid'); //short-uuid const short = require('short-uuid'); //moment const moment = require("moment-timezone"); //fastify const fastify = require("fastify")({ logger: false, }); fastify.register(require("fastify-static"), { root: path.join(__dirname, "public"), prefix: "/" }); fastify.register(require("fastify-formbody")); fastify.register(require("fastify-multipart")); fastify.register(require("point-of-view"), { engine: { handlebars: require("handlebars") } }); //socket.io var io = require("socket.io")(fastify.server, { pingInterval: 1000, pingTimeout: 3000 }); //get '/' fastify.get("/", async function (request, reply) { //get list let list = await fs.readdir(process.env.userdata); list.reverse(); // console.log(list); let folders = []; for (const item of list) { let json = await fs.readFile(process.env.userdata + item + '/fields.json') .catch((err) => { console.error(err); }); if (json != undefined) { var fields = JSON.parse(json.toString('utf8')); folders.push({ foldername: item, group: fields.group, title: fields.title, comment: fields.comment, anchor: fields.anchor }); } } // console.log(folders); // reply.view("/src/pages/parade.html", { list: folders }); }); //get '/en/' fastify.get("/en/", async function (request, reply) { reply.view("/src/pages/parade.en.html", {}); }); //get '/list' fastify.get("/list", async function (request, reply) { //get list let list = await fs.readdir(process.env.userdata); list.reverse(); // console.log(list); let folders = []; for (const item of list) { let json = await fs.readFile(process.env.userdata + item + '/fields.json') .catch((err) => { console.error(err); }); if (json != undefined) { var fields = JSON.parse(json.toString('utf8')); folders.push({ foldername: item, group: fields.group, title: fields.title, comment: fields.comment, anchor: fields.anchor }); } } // console.log(folders); // reply.send(folders); }); //get '/short' fastify.get("/short", function (request, reply) { let shorts = []; for (var idx = 0; idx < 100; idx++) { shorts.push(short.generate()); } reply.send(shorts); }); //get '/uploads/:foldername/:filename' fastify.get("/uploads/:foldername/:filename", async function (request, reply) { //get file & send var file = await fs.readFile(process.env.userdata + request.params.foldername + '/' + request.params.filename); reply.send(file); }); //get '/live fastify.get("/live", function (request, reply) { reply.view("/src/pages/live.html", {}); }); //get '/preview/:foldername' --> request.params.foldername fastify.get("/preview/:foldername", function (request, reply) { reply.view("/src/pages/preview.html", {}); }); //get '/entries' fastify.get("/entries", async function (request, reply) { //get list let list = await fs.readdir(process.env.userdata); reply.send(list); }); //get '/fields' fastify.get("/fields", async function (request, reply) { //get list let list = await fs.readdir(process.env.userdata); //list.reverse(); // console.log(list); let folders = []; for (const item of list) { let json = await fs.readFile(process.env.userdata + item + '/fields.json') .catch((err) => { console.error(err); }); if (json != undefined) { var fields = JSON.parse(json.toString('utf8')); folders.push({ foldername: item, group: fields.group, title: fields.title, comment: fields.comment, anchor: fields.anchor }); } } reply.send(folders); }); //get '/delete' fastify.get("/delete/:foldername/:pass", async function (request, reply) { //get pw var fields = JSON.parse((await fs.readFile(process.env.userdata + request.params.foldername + '/fields.json')).toString('utf8')); var res = false; if (fields.pass == request.params.pass) { // console.log('good pass'); //ok. let's move it to trashbin. (mv ../sound-parade.trash) // await fs.rename(process.env.userdata + request.params.foldername, '/media/storage/public/sound-parade.trash/' + request.params.foldername); const client = new Client(server); const folder = await client.getFolder(process.env.userdata_nextcloud + request.params.foldername); await folder.move(process.env.userdata_nextcloud_trash + request.params.foldername); // res = true; } else { // console.log('wrong pass'); } reply.send({ result: res }); }); //post on '/' fastify.post("/", async function (request, reply) { console.log("-- h.."); // got the event. // stores files to tmp dir and return paths const files = await request.saveRequestFiles().catch(err => { console.error(err); }); let audiofile = files.find(f => f.fieldname == 'audiofile'); let pixelfile = files.find(f => f.fieldname == 'pixels'); let tmpdir = path.dirname(audiofile.filepath); // console.log(audiofile.fields.message.value); console.log("-- hi."); // got all files. //conversion needed? var conversion = false; if (path.extname(audiofile.filename) !== ".mp3") { conversion = true; console.log("-- well.."); //conversion. is scheduled. } else { console.log("-- good"); //no conversion_ } //upload const client = new Client(server); console.log("-- ready"); //file server opened //create unique folder ==> timestamp + uuid const folder = await client.createFolder(process.env.userdata_nextcloud + moment().tz('Asia/Seoul').format('YYYYMMDD-HHmmss-') + uuidv1()); // const json = await folder.createFile("fields.json", Buffer.from(JSON.stringify({ group: audiofile.fields.group.value, title: audiofile.fields.title.value, comment: audiofile.fields.comment.value, pass: audiofile.fields.pass.value, anchor: short.generate() }))); const image = await folder.createFile("pixels.png", await fs.readFile(pixelfile.filepath)); // if (conversion) { console.log('---- hi conv'); //save original file as is. + we have scheduled a conversion. let afile = await fs.readFile(audiofile.filepath) .catch(err => { console.error(err); }); // if (afile != undefined) { const file = await folder.createFile(audiofile.filename, afile) .catch(err => { console.error(err); console.log('---- createFile err.'); console.log('afile', afile); }); } else { console.log('afile == undef!'); } console.log('---- yes conv'); // } else { console.log('---- no conv'); //rename & save original file. const file = await folder.createFile("audio.mp3", await fs.readFile(audiofile.filepath).catch(err => console.error(err))); } console.log("-- saved"); //saved in file server. //conversion needed? var converted = false; if (conversion) { console.log("-- mp3..."); //converting to mp3... function converter() { return new Promise((resolve, reject) => { // let outputFile = tmpdir + "/converted.mp3"; // --> https://stackoverflow.com/a/36109219 (a quick tip on fluent-ffmpeg) ffmpeg() .addInput(audiofile.filepath) .on("error", function(err) { console.log("-- err:", err); reject(err); }) .on("end", function() { console.log("-- fine."); //conversion succeesful converted = true; resolve(outputFile); }) .outputOptions('-b:a 192000') .output(outputFile) .run(); }); } await converter().catch((err) => { console.error(err); }); if (converted) { const file = await folder.createFile("audio.mp3", await fs.readFile(tmpdir + '/converted.mp3')); console.log("-- done"); } } console.log("-- well done"); reply.send('done!'); //reply.redirect('/submit'); }); //socket.io //var score = require("./public/score.json"); // //there will be 16 rooms called: "room0", "room1", ... , "room15" //if any other room is requested.. well, we will simply reject. var roommax = 16; // io.on("connection", function(socket) { console.log("someone connected."); socket.on("disconnect", function() { console.log("someone disconnected."); }); socket.on("room", function(room, fn) { // parseInt(room) if (room >= 0 && room < roommax) { socket.join("room" + room); fn(true); } else { fn(false); } }); socket.on("flow", function(req) { io.emit("flow", req); }); socket.on("info", async (fn) => { //get list let list = await fs.readdir(process.env.userdata); //list.reverse(); // console.log(list); let folders = []; for (const item of list) { var fields = JSON.parse((await fs.readFile(process.env.userdata + item + '/fields.json')).toString('utf8')); folders.push({ foldername: item, group: fields.group, title: fields.title, comment: fields.comment, anchor: fields.anchor }); } fn(folders); }); }); // var pointer = 0; // pointer : 0 ~ (length-1) var looper; (looper = function(timeout) { setTimeout(async function() { //pointer = 20; // console.log(score[pointer]); // for (var index = 0; index < roommax; index++) { // NOTE: 'pointer' must be 'remembered' since 'pointer' will increase almost immediately! pass as argument => 'pointed' // NOTE: 'index' is same => 'indexed' setTimeout(function(pointed, indexed) { // io.to("room" + indexed).emit("post", score[pointed]); io.to("room" + indexed).emit("post", pointed); // }, score[pointer].object.showtime * index, pointer, index); }, 30000 * index, pointer, index); } //var timegap = 10000 + Math.random()*(40000); var timegap = 1000 + Math.random()*(40000); console.log(timegap); //get # list let list = await fs.readdir(process.env.userdata); console.log(list.length); //loop over... pointer++; if (pointer >= list.length) pointer = 0; looper(timegap); }, timeout); })(1000); //listen fastify.listen(process.env.port, function (err, address) { if (err) { fastify.log.error(err) process.exit(1) } console.log(`Your app is listening on ${address}`) fastify.log.info(`server listening on ${address}`) });