From f0c9a6122f7971f95ad930becd319f19986322cd Mon Sep 17 00:00:00 2001 From: Tzahi12345 Date: Mon, 2 Jan 2023 02:01:19 -0500 Subject: [PATCH] Added nfty and gotify notifications support --- backend/config.js | 12 +- backend/consts.js | 32 ++++ backend/notifications.js | 84 ++++++++- backend/package-lock.json | 216 ++++++++++++++++++++++- backend/package.json | 1 + backend/utils.js | 5 + src/app/app.component.html | 2 +- src/app/settings/settings.component.html | 52 ++++++ 8 files changed, 395 insertions(+), 9 deletions(-) diff --git a/backend/config.js b/backend/config.js index 7b1908e..b497b38 100644 --- a/backend/config.js +++ b/backend/config.js @@ -198,7 +198,10 @@ const DEFAULT_CONFIG = { "download_only_mode": false, "allow_autoplay": true, "enable_downloads_manager": true, - "allow_playlist_categorization": true + "allow_playlist_categorization": true, + "enable_notifications": true, + "enable_all_notifications": true, + "allowed_notification_types": [], }, "API": { "use_API_key": false, @@ -210,7 +213,12 @@ const DEFAULT_CONFIG = { "twitch_client_secret": "", "twitch_auto_download_chat": false, "use_sponsorblock_API": false, - "generate_NFO_files": false + "generate_NFO_files": false, + "use_ntfy_API": false, + "ntfy_topic_URL": "", + "use_gotify_API": false, + "gotify_server_URL": "", + "gotify_app_token": "" }, "Themes": { "default_theme": "default", diff --git a/backend/consts.js b/backend/consts.js index bf1ed47..7ee3060 100644 --- a/backend/consts.js +++ b/backend/consts.js @@ -80,6 +80,18 @@ exports.CONFIG_ITEMS = { 'key': 'ytdl_allow_playlist_categorization', 'path': 'YoutubeDLMaterial.Extra.allow_playlist_categorization' }, + 'ytdl_enable_notifications': { + 'key': 'ytdl_enable_notifications', + 'path': 'YoutubeDLMaterial.Extra.enable_notifications' + }, + 'ytdl_enable_all_notifications': { + 'key': 'ytdl_enable_all_notifications', + 'path': 'YoutubeDLMaterial.Extra.enable_all_notifications' + }, + 'ytdl_allowed_notification_types': { + 'key': 'ytdl_allowed_notification_types', + 'path': 'YoutubeDLMaterial.Extra.allowed_notification_types' + }, // API 'ytdl_use_api_key': { @@ -122,6 +134,26 @@ exports.CONFIG_ITEMS = { 'key': 'ytdl_generate_nfo_files', 'path': 'YoutubeDLMaterial.API.generate_NFO_files' }, + 'ytdl_use_ntfy_API': { + 'key': 'ytdl_use_ntfy_API', + 'path': 'YoutubeDLMaterial.API.use_ntfy_API' + }, + 'ytdl_ntfy_topic_url': { + 'key': 'ytdl_ntfy_topic_url', + 'path': 'YoutubeDLMaterial.API.ntfy_topic_URL' + }, + 'ytdl_use_gotify_API': { + 'key': 'ytdl_use_gotify_API', + 'path': 'YoutubeDLMaterial.API.use_gotify_API' + }, + 'ytdl_gotify_server_url': { + 'key': 'ytdl_gotify_server_url', + 'path': 'YoutubeDLMaterial.API.gotify_server_URL' + }, + 'ytdl_gotify_app_token': { + 'key': 'ytdl_gotify_app_token', + 'path': 'YoutubeDLMaterial.API.gotify_app_token' + }, // Themes diff --git a/backend/notifications.js b/backend/notifications.js index a3cfe12..4eae17b 100644 --- a/backend/notifications.js +++ b/backend/notifications.js @@ -1,14 +1,54 @@ -const { uuid } = require('uuidv4'); const db_api = require('./db'); const config_api = require('./config'); +const logger = require('./logger'); +const utils = require('./utils'); + +const { uuid } = require('uuidv4'); +const fetch = require('node-fetch'); +const { gotify } = require("gotify"); + +const NOTIFICATION_TYPE_TO_TITLE = { + task_finished: 'Task finished', + download_complete: 'Download complete', + download_error: 'Download error' +} + +const NOTIFICATION_TYPE_TO_BODY = { + task_finished: (notification) => notification['data']['task_title'], + download_complete: (notification) => notification['data']['file_title'], + download_error: (notification) => notification['data']['download_url'] +} + +const NOTIFICATION_TYPE_TO_URL = { + task_finished: () => {return `${utils.getBaseURL()}/#/tasks`}, + download_complete: (notification) => {return `${utils.getBaseURL()}/#/player;uid=${notification['data']['file_uid']}`}, + download_error: () => {return `${utils.getBaseURL()}/#/tasks`}, +} + +const NOTIFICATION_TYPE_TO_THUMBNAIL = { + download_complete: (notification) => notification['data']['file_thumbnail'] +} exports.sendNotification = async (notification) => { - // TODO: hook into third party service + // info necessary if we are using 3rd party APIs + const type = notification['type']; + const title = NOTIFICATION_TYPE_TO_TITLE[type]; + const body = NOTIFICATION_TYPE_TO_BODY[type](notification); + const url = NOTIFICATION_TYPE_TO_URL[type](notification); + const thumbnail = NOTIFICATION_TYPE_TO_THUMBNAIL[type](notification); + + if (config_api.getConfigItem('ytdl_use_ntfy_API') && config_api.getConfigItem('ytdl_ntfy_topic_url')) { + sendNtfyNotification(body, title, type, url, thumbnail); + } + if (config_api.getConfigItem('ytdl_use_gotify_API') && config_api.getConfigItem('ytdl_gotify_server_url') && config_api.getConfigItem('ytdl_gotify_app_token')) { + sendGotifyNotification(body, title, type, url, thumbnail); + } await db_api.insertRecordIntoTable('notifications', notification); return notification; } exports.sendTaskNotification = async (task_obj, confirmed) => { + if (!notificationEnabled('task_finished')) return; // workaround for tasks which are user_uid agnostic const user_uid = config_api.getConfigItem('ytdl_multi_user_mode') ? 'admin' : null; await db_api.removeAllRecords('notifications', {"data.task_key": task_obj.key}); @@ -18,12 +58,14 @@ exports.sendTaskNotification = async (task_obj, confirmed) => { } exports.sendDownloadNotification = async (file, user_uid) => { - const data = {file_uid: file.uid, file_title: file.title}; + if (!notificationEnabled('download_complete')) return; + const data = {file_uid: file.uid, file_title: file.title, file_thumbnail: file.thumbnailURL}; const notification = exports.createNotification('download_complete', ['play'], data, user_uid); return await exports.sendNotification(notification); } exports.sendDownloadErrorNotification = async (download, user_uid) => { + if (!notificationEnabled('download_error')) return; const data = {download_uid: download.uid, download_url: download.url}; const notification = exports.createNotification('download_error', ['view_download_error', 'retry_download'], data, user_uid); return await exports.sendNotification(notification); @@ -41,3 +83,39 @@ exports.createNotification = (type, actions, data, user_uid) => { } return notification; } + +function notificationEnabled(type) { + return config_api.getConfigItem('ytdl_enable_notifications') && (config_api.getConfigItem('ytdl_enable_all_notifications') || config_api.getConfigItem('ytdl_allowed_notification_types').includes(type)); +} + +function sendNtfyNotification(body, title, type, url, thumbnail) { + logger.verbose('Sending notification to ntfy'); + fetch(config_api.getConfigItem('ytdl_ntfy_topic_url'), { + method: 'POST', + body: body, + headers: { + 'Title': title, + 'Tags': type, + 'Click': url, + 'Attach': thumbnail + } + }); +} + +async function sendGotifyNotification(body, title, type, url, thumbnail) { + logger.verbose('Sending notification to gotify'); + await gotify({ + server: config_api.getConfigItem('ytdl_gotify_server_url'), + app: config_api.getConfigItem('ytdl_gotify_app_token'), + title: title, + message: body, + tag: type, + priority: 5, // Keeping default from docs, may want to change this, + extras: { + "client::notification": { + click: { url: url }, + bigImageUrl: thumbnail + } + } + }); +} \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index 738b6f4..03bea2c 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -51,6 +51,43 @@ "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz", "integrity": "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==" }, + "@sindresorhus/is": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz", + "integrity": "sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==" + }, + "@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "requires": { + "defer-to-connect": "^2.0.0" + } + }, + "@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "requires": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==" + }, + "@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "requires": { + "@types/node": "*" + } + }, "@types/ldapjs": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/@types/ldapjs/-/ldapjs-2.2.2.tgz", @@ -64,6 +101,14 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.0.tgz", "integrity": "sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA==" }, + "@types/responselike": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", + "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", + "requires": { + "@types/node": "*" + } + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -144,7 +189,7 @@ "append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" }, "archiver": { "version": "5.3.1", @@ -420,6 +465,29 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, + "cacheable-lookup": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-2.0.1.tgz", + "integrity": "sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg==", + "requires": { + "@types/keyv": "^3.1.1", + "keyv": "^4.0.0" + } + }, + "cacheable-request": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", + "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + } + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -467,6 +535,21 @@ } } }, + "clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "requires": { + "mimic-response": "^1.0.0" + }, + "dependencies": { + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + } + } + }, "color": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", @@ -687,6 +770,19 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==" }, + "decompress-response": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-5.0.0.tgz", + "integrity": "sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw==", + "requires": { + "mimic-response": "^2.0.0" + } + }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==" + }, "define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", @@ -745,6 +841,11 @@ } } }, + "duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==" + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1108,6 +1209,36 @@ "is-glob": "^4.0.1" } }, + "got": { + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/got/-/got-10.7.0.tgz", + "integrity": "sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg==", + "requires": { + "@sindresorhus/is": "^2.0.0", + "@szmarczak/http-timer": "^4.0.0", + "@types/cacheable-request": "^6.0.1", + "cacheable-lookup": "^2.0.0", + "cacheable-request": "^7.0.1", + "decompress-response": "^5.0.0", + "duplexer3": "^0.1.4", + "get-stream": "^5.0.0", + "lowercase-keys": "^2.0.0", + "mimic-response": "^2.1.0", + "p-cancelable": "^2.0.0", + "p-event": "^4.0.0", + "responselike": "^2.0.0", + "to-readable-stream": "^2.0.0", + "type-fest": "^0.10.0" + } + }, + "gotify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gotify/-/gotify-1.1.0.tgz", + "integrity": "sha512-f3PUh08i+1JCJuzv9CRYuIx1QOb9DoWXRvWaPttgiZEG7XtetDQVv6S9cr6suPNKkZI4ry8dqdU2qdb9AiPinw==", + "requires": { + "got": "10.7.0" + } + }, "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", @@ -1174,6 +1305,11 @@ "zero-fill": "^2.2.3" } }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, "http-errors": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", @@ -1331,6 +1467,11 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1416,6 +1557,14 @@ "safe-buffer": "^5.0.1" } }, + "keyv": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", + "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", + "requires": { + "json-buffer": "3.0.1" + } + }, "kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -1621,6 +1770,11 @@ "steno": "^0.4.1" } }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -1701,6 +1855,11 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1990,6 +2149,11 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, + "normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==" + }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -2058,6 +2222,19 @@ "require-at": "^1.0.6" } }, + "p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==" + }, + "p-event": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "requires": { + "p-timeout": "^3.1.0" + } + }, "p-finally": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", @@ -2079,6 +2256,21 @@ "p-limit": "^3.0.2" } }, + "p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "requires": { + "p-finally": "^1.0.0" + }, + "dependencies": { + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" + } + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2181,7 +2373,7 @@ "pause": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", - "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" }, "performance-now": { "version": "2.1.0", @@ -2360,6 +2552,14 @@ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" }, + "responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "requires": { + "lowercase-keys": "^2.0.0" + } + }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -2657,6 +2857,11 @@ "thenify": ">= 3.1.0 < 4" } }, + "to-readable-stream": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-2.1.0.tgz", + "integrity": "sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w==" + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2712,6 +2917,11 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "type-fest": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz", + "integrity": "sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==" + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -2724,7 +2934,7 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "universalify": { "version": "1.0.0", diff --git a/backend/package.json b/backend/package.json index b50d93e..2ba0ef3 100644 --- a/backend/package.json +++ b/backend/package.json @@ -29,6 +29,7 @@ "express": "^4.17.3", "fluent-ffmpeg": "^2.1.2", "fs-extra": "^9.0.0", + "gotify": "^1.1.0", "jsonwebtoken": "^8.5.1", "lowdb": "^1.0.0", "md5": "^2.2.1", diff --git a/backend/utils.js b/backend/utils.js index 4ba96eb..3301829 100644 --- a/backend/utils.js +++ b/backend/utils.js @@ -537,6 +537,10 @@ function getArchiveFolder(type, user_uid = null, sub = null) { } } +function getBaseURL() { + return `${config_api.getConfigItem('ytdl_url')}:${config_api.getConfigItem('ytdl_port')}` +} + // objects function File(id, title, thumbnailURL, isAudio, duration, url, uploader, size, path, upload_date, description, view_count, height, abr) { @@ -588,5 +592,6 @@ module.exports = { searchObjectByString: searchObjectByString, stripPropertiesFromObject: stripPropertiesFromObject, getArchiveFolder: getArchiveFolder, + getBaseURL: getBaseURL, File: File } diff --git a/src/app/app.component.html b/src/app/app.component.html index 910c352..44e97be 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -11,7 +11,7 @@
- + diff --git a/src/app/settings/settings.component.html b/src/app/settings/settings.component.html index 6490cc0..0abfbd7 100644 --- a/src/app/settings/settings.component.html +++ b/src/app/settings/settings.component.html @@ -360,6 +360,58 @@
+ + + +
+
+
+ Enable notifications +
+
+ Enable all notifications +
+
+ + Allowed notification types + + Download complete + Download error + Task finished + + +
+
+ Use ntfy API +
+
+ + ntfy topic URL + + See docs here. + +
+
+ Use gotify API +
+
+ + Gotify server URL + + See docs here. + +
+
+ + Gotify app token + + See docs here. + +
+
+
+
+