From 8d275b0213de2bbc7d30b8ac11f6e32a67b6ee96 Mon Sep 17 00:00:00 2001 From: wukko Date: Fri, 22 Jul 2022 14:05:36 +0600 Subject: [PATCH] reddit is back! - fixed reddit support (i had no idea older posts had a different naming pattern for media files) - improved russian localisation - now frontend handles more unexpected api errors in case something goes absolutely wrong --- src/i18n/ru/apiError.json | 2 +- src/i18n/ru/settings.json | 2 +- src/i18n/ru/strings.json | 2 +- src/modules/match.js | 10 +++--- src/modules/pageRender.js | 2 +- src/modules/services/reddit.js | 13 ++++++- src/modules/stream/manage.js | 2 +- src/modules/stream/types.js | 3 +- src/modules/sub/utils.js | 1 - src/static/cobalt.js | 64 +++++++++++++++++++--------------- 10 files changed, 59 insertions(+), 42 deletions(-) diff --git a/src/i18n/ru/apiError.json b/src/i18n/ru/apiError.json index 5bc82704..74948019 100644 --- a/src/i18n/ru/apiError.json +++ b/src/i18n/ru/apiError.json @@ -2,7 +2,7 @@ "generic": "что-то пошло совсем не так, поэтому у меня не получилось ничего для тебя достать. ты можешь попробовать ещё раз, но если так и не получится, напиши об этом.", "notSupported": "этот сервис ещё не поддерживается, или с твоей ссылкой что-то не так.", "brokenLink": "{s} поддерживается, но с твоей ссылкой что-то не так. может быть, ты её не полностью скопировал?", - "noLink": "я не умею угадывать, что ты хочешь скачать. попробуй в следующий раз вставить ссылку.", + "noLink": "я не могу угадать, что ты хочешь скачать. попробуй в следующий раз вставить ссылку.", "noRender": "что-то пошло не так, поэтому у меня не получилось срендерить страницу. если это что-то критичное, пожалуйста, напиши мне об этом. приложи хэш текущего коммита ({s}) с действиями для получения ошибки. можно на русском языке. спасибо :)", "rateLimit": "ты делаешь слишком много запросов. успокойся и попробуй ещё раз через несколько минут.", "noFetch": "мне не удалось получить информацию о твоей ссылке. проверь её и попробуй ещё раз.", diff --git a/src/i18n/ru/settings.json b/src/i18n/ru/settings.json index f6805e26..ca301031 100644 --- a/src/i18n/ru/settings.json +++ b/src/i18n/ru/settings.json @@ -3,7 +3,7 @@ "alwaysVisibleButton": "оставлять >> на экране", "downloadPopupButton": "спрашивать, что делать с загрузками", "format": "формат загрузок", - "formatInfo": "выбирай webm, если хочешь максимальное качество. webm обычно лучше, чем mp4 в плане качества, но устройства на ios не могут их проигрывать без сторонних приложений. все загрузки \"только аудио\" всегда максимального качества.", + "formatInfo": "выбирай webm, если хочешь максимальное качество. webm обычно лучше по качеству, но устройства на ios не могут проигрывать их без сторонних приложений. все загрузки \"только аудио\" всегда максимального качества.", "theme": "тема", "themeAuto": "авто", "themeLight": "светлая", diff --git a/src/i18n/ru/strings.json b/src/i18n/ru/strings.json index 6e529ff2..2d676290 100644 --- a/src/i18n/ru/strings.json +++ b/src/i18n/ru/strings.json @@ -11,7 +11,7 @@ "donateDm": ">> если нет подходящей валюты, или же ты из россии, то напиши мне", "clickToCopy": "нажми, чтобы скопировать", "iosDownload": "так как у тебя устройство на ios, тебе нужно зажать кнопку \"скачать\" и выбрать что-то похожее на \"сохранить в галерею\" в появившемся окне.", - "normalDownload": "кнопка скачивания открывает новое окно с файлом. ты можешь отключить метод сохранения файла в настройках.", + "normalDownload": "кнопка скачивания открывает новое окно с файлом. ты можешь отключить выбор метода сохранения файла в настройках.", "download": "скачать", "copy": "скопировать ссылку", "github": ">> посмотреть предыдущие изменения на github" diff --git a/src/modules/match.js b/src/modules/match.js index 0eb4ebc3..945fdf17 100644 --- a/src/modules/match.js +++ b/src/modules/match.js @@ -25,7 +25,7 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit videoId: patternMatch["videoId"], lang: lang, quality: quality }); - return (!r.error) ? apiJSON(2, { type: "bridge", urls: r.url, filename: r.filename, service: host, ip: ip, salt: process.env.streamSalt }) : apiJSON(0, { t: r.error }); + return (!r.error) ? apiJSON(2, { type: "bridge", u: r.url, filename: r.filename, service: host, ip: ip, salt: process.env.streamSalt }) : apiJSON(0, { t: r.error }); } else throw Error() case "bilibili": if (patternMatch["id"] && patternMatch["id"].length >= 12) { @@ -34,7 +34,7 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit lang: lang }); return (!r.error) ? apiJSON(2, { - type: "render", urls: r.urls, lang: lang, + type: "render", u: r.urls, lang: lang, service: host, ip: ip, filename: r.filename, salt: process.env.streamSalt, time: r.time @@ -62,7 +62,7 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit } let r = await youtube(fetchInfo); return (!r.error) ? apiJSON(2, { - type: r.type, urls: r.urls, service: host, ip: ip, + type: r.type, u: r.urls, service: host, ip: ip, filename: r.filename, salt: process.env.streamSalt, isAudioOnly: fetchInfo["isAudioOnly"] ? fetchInfo["isAudioOnly"] : false, time: r.time, @@ -75,8 +75,8 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit id: patternMatch["id"], title: patternMatch["title"], lang: lang, }); - return (!r.error) ? apiJSON(2, { - type: "render", urls: r.urls, + return (!r.error) ? apiJSON(r.typeId, { + type: r.type, u: r.urls, service: host, ip: ip, filename: r.filename, salt: process.env.streamSalt }) : apiJSON(0, { t: r.error }); diff --git a/src/modules/pageRender.js b/src/modules/pageRender.js index 158f785d..a8d09f3f 100644 --- a/src/modules/pageRender.js +++ b/src/modules/pageRender.js @@ -193,7 +193,7 @@ export default function(obj) { - + `; } catch (err) { diff --git a/src/modules/services/reddit.js b/src/modules/services/reddit.js index a7986c31..7787dd9f 100644 --- a/src/modules/services/reddit.js +++ b/src/modules/services/reddit.js @@ -7,7 +7,18 @@ export default async function(obj) { let req = await got.get(`https://www.reddit.com/r/${obj.sub}/comments/${obj.id}/${obj.name}.json`, { headers: { "user-agent": genericUserAgent } }); let data = (JSON.parse(req.body))[0]["data"]["children"][0]["data"]; if ("reddit_video" in data["secure_media"] && data["secure_media"]["reddit_video"]["duration"] * 1000 < maxVideoDuration) { - return { urls: [data["secure_media"]["reddit_video"]["fallback_url"].split('?')[0], `${data["secure_media"]["reddit_video"]["fallback_url"].split('_')[0]}_audio.mp4`], filename: `reddit_${data["secure_media"]["reddit_video"]["fallback_url"].split('/')[3]}.mp4` }; + let video = data["secure_media"]["reddit_video"]["fallback_url"].split('?')[0], + audio = video.match('.mp4') ? `${video.split('_')[0]}_audio.mp4` : `${data["secure_media"]["reddit_video"]["fallback_url"].split('DASH')[0]}audio`; + try { + await got.head(audio, { headers: { "user-agent": genericUserAgent } }); + } catch (err) { + audio = '' + } + if (audio.length > 0) { + return { typeId: 2, type: "render", urls: [video, audio], filename: `reddit_${data["secure_media"]["reddit_video"]["fallback_url"].split('/')[3]}.mp4` }; + } else { + return { typeId: 1, urls: video}; + } } else { return { error: loc(obj.lang, 'apiError', 'nothingToDownload') }; } diff --git a/src/modules/stream/manage.js b/src/modules/stream/manage.js index 8a43bd85..9b56478e 100644 --- a/src/modules/stream/manage.js +++ b/src/modules/stream/manage.js @@ -15,7 +15,7 @@ export function createStream(obj) { id: streamUUID, service: obj.service, type: obj.type, - urls: obj.urls, + urls: obj.u, filename: obj.filename, hmac: ghmac, ip: iphmac, diff --git a/src/modules/stream/types.js b/src/modules/stream/types.js index d2b6f8e3..2ae847e3 100644 --- a/src/modules/stream/types.js +++ b/src/modules/stream/types.js @@ -42,7 +42,8 @@ export async function streamLiveRender(streamInfo, res) { '-map', '1:a', ]; args = args.concat(ffmpegArgs[format]) - args.push('-t', msToTime(streamInfo.time), '-f', format, 'pipe:5'); + if (streamInfo.time) args.push('-t', msToTime(streamInfo.time)); + args.push('-f', format, 'pipe:5'); const ffmpegProcess = spawn(ffmpeg, args, { windowsHide: true, stdio: [ diff --git a/src/modules/sub/utils.js b/src/modules/sub/utils.js index ac7916c6..86c1ab9e 100644 --- a/src/modules/sub/utils.js +++ b/src/modules/sub/utils.js @@ -1,5 +1,4 @@ import { createStream } from "../stream/manage.js"; -import { execSync } from "child_process"; export function apiJSON(type, obj) { try { diff --git a/src/static/cobalt.js b/src/static/cobalt.js index 01acf897..ade79ffc 100644 --- a/src/static/cobalt.js +++ b/src/static/cobalt.js @@ -141,37 +141,43 @@ async function download(url) { fetch(`/api/json?quality=${localStorage.getItem("quality")}${format}&url=${encodeURIComponent(url)}`).then(async (response) => { let j = await response.json(); if (j.status != "error" && j.status != "rate-limit") { - switch (j.status) { - case "redirect": - changeDownloadButton(2, '>>>') - setTimeout(() => { - changeDownloadButton(1, '>>') - eid("url-input-area").disabled = false - }, 3000) - if (localStorage.getItem("downloadPopup") == "true") { - popup('download', 1, j.url) - } else { - window.open(j.url, '_blank'); - } - break; - case "stream": - changeDownloadButton(2, '?..') - fetch(`${j.url}&p=1&origin=front`).then(async (response) => { - let jp = await response.json(); - if (jp.status == "continue") { - changeDownloadButton(2, '>>>') - window.location.href = j.url - setTimeout(() => { - changeDownloadButton(1, '>>') - eid("url-input-area").disabled = false - }, 5000) - } else { + if (j.url) { + switch (j.status) { + case "redirect": + changeDownloadButton(2, '>>>') + setTimeout(() => { + changeDownloadButton(1, '>>') eid("url-input-area").disabled = false - changeDownloadButton(2, '!!') - popup("error", 1, jp.text); + }, 3000) + if (localStorage.getItem("downloadPopup") == "true") { + popup('download', 1, j.url) + } else { + window.open(j.url, '_blank'); } - }).catch((error) => internetError()); - break; + break; + case "stream": + changeDownloadButton(2, '?..') + fetch(`${j.url}&p=1&origin=front`).then(async (response) => { + let jp = await response.json(); + if (jp.status == "continue") { + changeDownloadButton(2, '>>>') + window.location.href = j.url + setTimeout(() => { + changeDownloadButton(1, '>>') + eid("url-input-area").disabled = false + }, 5000) + } else { + eid("url-input-area").disabled = false + changeDownloadButton(2, '!!') + popup("error", 1, jp.text); + } + }).catch((error) => internetError()); + break; + } + } else { + eid("url-input-area").disabled = false + changeDownloadButton(2, '!!') + popup("error", 1, loc.noURLReturned); } } else { eid("url-input-area").disabled = false