adding channel downloading and automatic downloading
This commit is contained in:
parent
27c79ab648
commit
283fa7c892
|
@ -171,4 +171,115 @@ exports.playlist = async (ws, req) => {
|
||||||
|
|
||||||
ws.send(`DONE - ${process.env.FRONTEND}/playlist?list=${playlistId}`)
|
ws.send(`DONE - ${process.env.FRONTEND}/playlist?list=${playlistId}`)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.channel = async (ws, req) => {
|
||||||
|
logger.info({ message: `${req.path} ${JSON.stringify(req.query)} ${JSON.stringify(req.headers)}` })
|
||||||
|
|
||||||
|
const channelId = await validate.validateChannelInput(req.query.url)
|
||||||
|
if (channelId.fail) {
|
||||||
|
ws.send(`ERROR - ${channelId.message}`)
|
||||||
|
return ws.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = 'captcha'
|
||||||
|
ws.send('CAPTCHA - Please complete the captcha:')
|
||||||
|
|
||||||
|
ws.on('message', async function(msg) {
|
||||||
|
if (status == 'captcha') {
|
||||||
|
status = 'downloading'
|
||||||
|
const confirm = await captcha.checkCaptcha(msg)
|
||||||
|
|
||||||
|
if (confirm) startDownloading()
|
||||||
|
else {
|
||||||
|
await redis.del(id)
|
||||||
|
ws.send('DATA - You little goofy goober tried to mess with the captcha...')
|
||||||
|
ws.close()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ws.send('DATA - You already sent captcha reply...')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
async function startDownloading() {
|
||||||
|
const instance = await metadata.getInstance()
|
||||||
|
const channel = await metadata.getChannelVideos(instance, channelId)
|
||||||
|
for (video of channel.relatedStreams) {
|
||||||
|
const id = video.url.match(/[?&]v=([^&]+)/)[1]
|
||||||
|
|
||||||
|
const already = await prisma.videos.findFirst({
|
||||||
|
where: {
|
||||||
|
id: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (already) {
|
||||||
|
ws.send(`DATA - Already downloaded ${video.title}`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await redis.get(id)) {
|
||||||
|
ws.send(`DATA - Someone is already downloading ${video.title}, skipping.`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.send(`INFO - Downloading ${video.title}<br><br>`)
|
||||||
|
await redis.set(id, 'downloading')
|
||||||
|
|
||||||
|
const download = await ytdlp.downloadVideo('https://www.youtube.com' + video.url, ws)
|
||||||
|
if (download.fail) {
|
||||||
|
ws.send(`DATA - ${download.message}`)
|
||||||
|
await redis.del(id)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
await redis.del(id)
|
||||||
|
|
||||||
|
const file = fs.readdirSync("./videos").find(f => f.includes(id))
|
||||||
|
if (file) {
|
||||||
|
fs.renameSync(`./videos/${file}`, `./videos/${id}.webm`)
|
||||||
|
ws.send(`DATA - Downloaded ${video.title}`)
|
||||||
|
ws.send(`DATA - Uploading ${video.title}`)
|
||||||
|
|
||||||
|
const videoUrl = await upload.uploadVideo(`./videos/${id}.webm`)
|
||||||
|
ws.send(`DATA - Uploaded ${video.title}`)
|
||||||
|
fs.unlinkSync(`./videos/${id}.webm`)
|
||||||
|
|
||||||
|
await websocket.createDatabaseVideo(id, videoUrl)
|
||||||
|
ws.send(`DATA - Created video page for ${video.title}`)
|
||||||
|
} else {
|
||||||
|
ws.send(`DATA - Failed to find file for ${video.title}. Going to next video`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.send(`DONE - ${process.env.FRONTEND}/channel/${channelId}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.addAutodownload = async (req, res) => {
|
||||||
|
const confirm = await captcha.checkCaptcha(req.query.captcha)
|
||||||
|
if (!confirm) res.status(500).send('You little goofy goober tried to mess with the captcha...')
|
||||||
|
|
||||||
|
const channelId = await validate.validateChannelInput(req.query.url)
|
||||||
|
if (channelId.fail) {
|
||||||
|
res.status(500).send(channelId.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
const already = await prisma.autodownload.findFirst({
|
||||||
|
where: {
|
||||||
|
channel: channelId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (already) {
|
||||||
|
res.status(500).send(`This channel is already being automatically downloaded...`)
|
||||||
|
} else {
|
||||||
|
await prisma.autodownload.create({
|
||||||
|
data: {
|
||||||
|
channel: channelId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
res.send('Perfect! Each time this channel uploads their videos will be downloaded')
|
||||||
|
}
|
||||||
}
|
}
|
7
index.js
7
index.js
|
@ -4,6 +4,7 @@ const express = require('express')
|
||||||
const cors = require('cors')
|
const cors = require('cors')
|
||||||
|
|
||||||
const logger = require('./utils/logger.js')
|
const logger = require('./utils/logger.js')
|
||||||
|
const auto = require('./utils/auto.js')
|
||||||
|
|
||||||
const latestController = require('./controller/latest.js')
|
const latestController = require('./controller/latest.js')
|
||||||
const videoController = require('./controller/video.js')
|
const videoController = require('./controller/video.js')
|
||||||
|
@ -30,6 +31,12 @@ app.get('/transparency/:id', transparencyController.getReport)
|
||||||
|
|
||||||
app.ws('/save', websocketController.save)
|
app.ws('/save', websocketController.save)
|
||||||
app.ws('/saveplaylist', websocketController.playlist)
|
app.ws('/saveplaylist', websocketController.playlist)
|
||||||
|
app.ws('/savechannel', websocketController.channel)
|
||||||
|
app.get('/autodownload', websocketController.addAutodownload)
|
||||||
|
|
||||||
|
setInterval(() => {
|
||||||
|
auto.handleCheck()
|
||||||
|
}, 300000)
|
||||||
|
|
||||||
process.on('uncaughtException', err => {
|
process.on('uncaughtException', err => {
|
||||||
logger.info({ message: `Error: ${err.message}` })
|
logger.info({ message: `Error: ${err.message}` })
|
||||||
|
|
|
@ -34,4 +34,9 @@ model reports {
|
||||||
title String
|
title String
|
||||||
details String
|
details String
|
||||||
date DateTime @default(now())
|
date DateTime @default(now())
|
||||||
|
}
|
||||||
|
|
||||||
|
model autodownload {
|
||||||
|
uuid String @id @default(uuid())
|
||||||
|
channel String
|
||||||
}
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
const logger = require("./logger.js");
|
||||||
|
const metadata = require("./metadata.js")
|
||||||
|
const ytdlp = require("./ytdlp.js")
|
||||||
|
const redis = require("./redis.js")
|
||||||
|
const websocket = require("./websocket.js")
|
||||||
|
|
||||||
|
const { PrismaClient } = require('@prisma/client')
|
||||||
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
|
async function handleCheck() {
|
||||||
|
const channels = await prisma.autodownload.findMany()
|
||||||
|
|
||||||
|
for (c of channels) {
|
||||||
|
await handleDownload(c.channel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDownload(channelId) {
|
||||||
|
logger.info({ message: `Checking ${channelId} for new videos...` })
|
||||||
|
|
||||||
|
const instance = await metadata.getInstance()
|
||||||
|
const channel = await metadata.getChannelVideos(instance, channelId)
|
||||||
|
for (video of channel.relatedStreams) {
|
||||||
|
const id = video.url.match(/[?&]v=([^&]+)/)[1]
|
||||||
|
|
||||||
|
const already = await prisma.videos.findFirst({
|
||||||
|
where: {
|
||||||
|
id: id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (already) continue
|
||||||
|
logger.info({ message: `Starting to download ${video.title}, ${id}` })
|
||||||
|
|
||||||
|
const download = await ytdlp.downloadVideo('https://www.youtube.com' + video.url)
|
||||||
|
if (download.fail) {
|
||||||
|
logger.info({ message: `Failed downloading ${video.title}, ${id} -> ${download.message}` })
|
||||||
|
await redis.del(id)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
await redis.del(id)
|
||||||
|
|
||||||
|
const file = fs.readdirSync("./videos").find(f => f.includes(id))
|
||||||
|
if (file) {
|
||||||
|
fs.renameSync(`./videos/${file}`, `./videos/${id}.webm`)
|
||||||
|
logger.info({ message: `Downloaded ${video.title}, ${id}` })
|
||||||
|
|
||||||
|
const videoUrl = await upload.uploadVideo(`./videos/${id}.webm`)
|
||||||
|
logger.info({ message: `Uploaded ${video.title}, ${id}` })
|
||||||
|
fs.unlinkSync(`./videos/${id}.webm`)
|
||||||
|
|
||||||
|
await websocket.createDatabaseVideo(id, videoUrl)
|
||||||
|
} else {
|
||||||
|
logger.info({ message: `Couldn't find file for ${video.title}, ${id}` })
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { handleCheck }
|
|
@ -8,7 +8,7 @@ async function downloadVideo(url, ws) {
|
||||||
const msg = data.toString().trim()
|
const msg = data.toString().trim()
|
||||||
if (!msg) return
|
if (!msg) return
|
||||||
|
|
||||||
ws.send(`DATA - ${msg}`)
|
if (ws) ws.send(`DATA - ${msg}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
child.on("close", async (code, signal) => {
|
child.on("close", async (code, signal) => {
|
||||||
|
|
Loading…
Reference in New Issue