diff --git a/Modules/webSubManager.js b/Modules/webSubManager.js new file mode 100644 index 0000000..0fd242d --- /dev/null +++ b/Modules/webSubManager.js @@ -0,0 +1,32 @@ +import { error } from './logManager'; + + +export async function subbWebSub(callback, topic, hub) { + const options = { + method: 'POST', + mode: 'cors', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ 'hub.mode': 'subscribe', 'hub.topic': topic, 'hub.callback': callback, 'hub.verify': 'sync' }), + }; + + return await fetch(hub, options) + .then(res => { + res.status === 204 ? true : false; + }) + .catch(err => error(err)); +} + +export async function unsubWebSub(callback, topic, hub) { + const options = { + method: 'POST', + mode: 'cors', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ 'hub.mode': 'unsubscribe', 'hub.topic': topic, 'hub.callback': callback, 'hub.verify': 'sync' }), + }; + + return await fetch(hub, options) + .then(res => { + res.status === 204 ? true : false; + }) + .catch(err => error(err)); +} \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index 52c412b..20a4629 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/config.json.sample b/config.json.sample index d086a72..39cf91f 100644 --- a/config.json.sample +++ b/config.json.sample @@ -1,4 +1,5 @@ { + "port": 3000, "subs": [ "Bitcoin", "ethereum", @@ -8,5 +9,12 @@ "discord": { "avatar_url": "https://aostia.me/portfolio/assets/avatar.png", "webhook": "https://discord.com/api/webhooks/id/token" + }, + "youtube": { + "callback": "https://news.chromatic.moe/youtube/callback", + "channels": [ + "UCeeFfhMcJa1kjtfZAGskOCA", + "UCXuqSBlHAE6Xw-yeJA0Tunw" + ] } } \ No newline at end of file diff --git a/index.js b/index.js index 6946035..5ed3af5 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,21 @@ import { exec } from 'child_process'; +import express from 'express'; +import cors from 'cors'; const { log } = require('./Modules/logManager'); const { get } = require('./Modules/fetchManager'); const { createCron } = require('./Modules/cronManager'); const { generateHtml } = require('./Modules/htmlManager'); +const { subbWebSub, unsubWebSub } = require('./Modules/webSubManager'); + +const { port, subs, youtube, discord } = require('./config.json'); + +const app = express(); +app.use(express.json()); +app.set('trust proxy', 1); +app.use(cors({ + origin: '*', +})); -const { subs, discord } = require('./config.json'); async function main() { const posts = []; @@ -38,5 +49,21 @@ async function main() { discord.webhook ? exec(`curl -X POST -F 'payload_json={"username":"ChromaNews","avatar_url":"${discord.avatar_url}","content":"New weekly news!"}' -F 'file1=@index.html' ${discord.webhook}`) : log('No webhook found.'); } -main(); -createCron('monday 0 0', main); \ No newline at end of file +for (const channel of youtube.channels) subbWebSub(youtube.callback, `https://www.youtube.com/feeds/videos.xml?channel_id=${channel}`, 'https://pubsubhubbub.appspot.com/subscribe'); + +createCron('monday 0 0', main); + +app.get((youtube.callback).replace(/^.*\/\/[^/]+/, ''), (req, res) => { + log('YouTube callback received.'); + res.send('ok'); +}); + +app.listen(port, async () => { + log(`running on port ${port}`); +}); + +process.on('SIGINT', function() { + console.log('Stopping server...'); + for (const channel of youtube.channels) unsubWebSub(youtube.callback, `https://www.youtube.com/feeds/videos.xml?channel_id=${channel}`, 'https://pubsubhubbub.appspot.com/subscribe'); + process.exit(); +}); \ No newline at end of file diff --git a/package.json b/package.json index 46ae404..72ed942 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,8 @@ "typescript": "^5.0.0" }, "dependencies": { + "cors": "^2.8.5", + "express": "^4.18.2", "form-data": "^4.0.0", "node-cron": "^3.0.3", "pino": "^8.19.0"