mirror of
https://github.com/imputnet/cobalt.git
synced 2024-12-29 11:06:10 +00:00
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
This commit is contained in:
parent
86d45f63c9
commit
8d275b0213
|
@ -2,7 +2,7 @@
|
||||||
"generic": "что-то пошло совсем не так, поэтому у меня не получилось ничего для тебя достать. ты можешь попробовать ещё раз, но если так и не получится, <a class=\"text-backdrop nowrap\" href=\"{repo}\">напиши об этом</a>.",
|
"generic": "что-то пошло совсем не так, поэтому у меня не получилось ничего для тебя достать. ты можешь попробовать ещё раз, но если так и не получится, <a class=\"text-backdrop nowrap\" href=\"{repo}\">напиши об этом</a>.",
|
||||||
"notSupported": "этот сервис ещё не поддерживается, или с твоей ссылкой что-то не так.",
|
"notSupported": "этот сервис ещё не поддерживается, или с твоей ссылкой что-то не так.",
|
||||||
"brokenLink": "{s} поддерживается, но с твоей ссылкой что-то не так. может быть, ты её не полностью скопировал?",
|
"brokenLink": "{s} поддерживается, но с твоей ссылкой что-то не так. может быть, ты её не полностью скопировал?",
|
||||||
"noLink": "я не умею угадывать, что ты хочешь скачать. попробуй в следующий раз вставить ссылку.",
|
"noLink": "я не могу угадать, что ты хочешь скачать. попробуй в следующий раз вставить ссылку.",
|
||||||
"noRender": "что-то пошло не так, поэтому у меня не получилось срендерить страницу. если это что-то критичное, пожалуйста, <a href=\"https://wukko.me/contacts\">напиши мне об этом</a>. приложи хэш текущего коммита ({s}) с действиями для получения ошибки. можно на русском языке. спасибо :)",
|
"noRender": "что-то пошло не так, поэтому у меня не получилось срендерить страницу. если это что-то критичное, пожалуйста, <a href=\"https://wukko.me/contacts\">напиши мне об этом</a>. приложи хэш текущего коммита ({s}) с действиями для получения ошибки. можно на русском языке. спасибо :)",
|
||||||
"rateLimit": "ты делаешь слишком много запросов. успокойся и попробуй ещё раз через несколько минут.",
|
"rateLimit": "ты делаешь слишком много запросов. успокойся и попробуй ещё раз через несколько минут.",
|
||||||
"noFetch": "мне не удалось получить информацию о твоей ссылке. проверь её и попробуй ещё раз.",
|
"noFetch": "мне не удалось получить информацию о твоей ссылке. проверь её и попробуй ещё раз.",
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"alwaysVisibleButton": "оставлять >> на экране",
|
"alwaysVisibleButton": "оставлять >> на экране",
|
||||||
"downloadPopupButton": "спрашивать, что делать с загрузками",
|
"downloadPopupButton": "спрашивать, что делать с загрузками",
|
||||||
"format": "формат загрузок",
|
"format": "формат загрузок",
|
||||||
"formatInfo": "выбирай webm, если хочешь максимальное качество. webm обычно лучше, чем mp4 в плане качества, но устройства на ios не могут их проигрывать без сторонних приложений. все загрузки \"только аудио\" всегда максимального качества.",
|
"formatInfo": "выбирай webm, если хочешь максимальное качество. webm обычно лучше по качеству, но устройства на ios не могут проигрывать их без сторонних приложений. все загрузки \"только аудио\" всегда максимального качества.",
|
||||||
"theme": "тема",
|
"theme": "тема",
|
||||||
"themeAuto": "авто",
|
"themeAuto": "авто",
|
||||||
"themeLight": "светлая",
|
"themeLight": "светлая",
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
"donateDm": ">> если нет подходящей валюты, или же ты из россии, то напиши мне",
|
"donateDm": ">> если нет подходящей валюты, или же ты из россии, то напиши мне",
|
||||||
"clickToCopy": "нажми, чтобы скопировать",
|
"clickToCopy": "нажми, чтобы скопировать",
|
||||||
"iosDownload": "так как у тебя устройство на ios, тебе нужно зажать кнопку \"скачать\" и выбрать что-то похожее на \"сохранить в галерею\" в появившемся окне.",
|
"iosDownload": "так как у тебя устройство на ios, тебе нужно зажать кнопку \"скачать\" и выбрать что-то похожее на \"сохранить в галерею\" в появившемся окне.",
|
||||||
"normalDownload": "кнопка скачивания открывает новое окно с файлом. ты можешь отключить метод сохранения файла в настройках.",
|
"normalDownload": "кнопка скачивания открывает новое окно с файлом. ты можешь отключить выбор метода сохранения файла в настройках.",
|
||||||
"download": "скачать",
|
"download": "скачать",
|
||||||
"copy": "скопировать ссылку",
|
"copy": "скопировать ссылку",
|
||||||
"github": ">> посмотреть предыдущие изменения на github"
|
"github": ">> посмотреть предыдущие изменения на github"
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit
|
||||||
videoId: patternMatch["videoId"],
|
videoId: patternMatch["videoId"],
|
||||||
lang: lang, quality: quality
|
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()
|
} else throw Error()
|
||||||
case "bilibili":
|
case "bilibili":
|
||||||
if (patternMatch["id"] && patternMatch["id"].length >= 12) {
|
if (patternMatch["id"] && patternMatch["id"].length >= 12) {
|
||||||
|
@ -34,7 +34,7 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit
|
||||||
lang: lang
|
lang: lang
|
||||||
});
|
});
|
||||||
return (!r.error) ? apiJSON(2, {
|
return (!r.error) ? apiJSON(2, {
|
||||||
type: "render", urls: r.urls, lang: lang,
|
type: "render", u: r.urls, lang: lang,
|
||||||
service: host, ip: ip,
|
service: host, ip: ip,
|
||||||
filename: r.filename,
|
filename: r.filename,
|
||||||
salt: process.env.streamSalt, time: r.time
|
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);
|
let r = await youtube(fetchInfo);
|
||||||
return (!r.error) ? apiJSON(2, {
|
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,
|
filename: r.filename, salt: process.env.streamSalt,
|
||||||
isAudioOnly: fetchInfo["isAudioOnly"] ? fetchInfo["isAudioOnly"] : false,
|
isAudioOnly: fetchInfo["isAudioOnly"] ? fetchInfo["isAudioOnly"] : false,
|
||||||
time: r.time,
|
time: r.time,
|
||||||
|
@ -75,8 +75,8 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit
|
||||||
id: patternMatch["id"],
|
id: patternMatch["id"],
|
||||||
title: patternMatch["title"], lang: lang,
|
title: patternMatch["title"], lang: lang,
|
||||||
});
|
});
|
||||||
return (!r.error) ? apiJSON(2, {
|
return (!r.error) ? apiJSON(r.typeId, {
|
||||||
type: "render", urls: r.urls,
|
type: r.type, u: r.urls,
|
||||||
service: host, ip: ip,
|
service: host, ip: ip,
|
||||||
filename: r.filename, salt: process.env.streamSalt
|
filename: r.filename, salt: process.env.streamSalt
|
||||||
}) : apiJSON(0, { t: r.error });
|
}) : apiJSON(0, { t: r.error });
|
||||||
|
|
|
@ -193,7 +193,7 @@ export default function(obj) {
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
<script type="text/javascript">const loc = {noInternet:"${loc(obj.lang, 'apiError', 'noInternet')}"}</script>
|
<script type="text/javascript">const loc = {noInternet:"${loc(obj.lang, 'apiError', 'noInternet')}", noURLReturned: "${loc(obj.lang, 'apiError', 'errorFetch')}"}</script>
|
||||||
<script type="text/javascript" src="cobalt.js"></script>
|
<script type="text/javascript" src="cobalt.js"></script>
|
||||||
</html>`;
|
</html>`;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -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 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"];
|
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) {
|
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 {
|
} else {
|
||||||
return { error: loc(obj.lang, 'apiError', 'nothingToDownload') };
|
return { error: loc(obj.lang, 'apiError', 'nothingToDownload') };
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ export function createStream(obj) {
|
||||||
id: streamUUID,
|
id: streamUUID,
|
||||||
service: obj.service,
|
service: obj.service,
|
||||||
type: obj.type,
|
type: obj.type,
|
||||||
urls: obj.urls,
|
urls: obj.u,
|
||||||
filename: obj.filename,
|
filename: obj.filename,
|
||||||
hmac: ghmac,
|
hmac: ghmac,
|
||||||
ip: iphmac,
|
ip: iphmac,
|
||||||
|
|
|
@ -42,7 +42,8 @@ export async function streamLiveRender(streamInfo, res) {
|
||||||
'-map', '1:a',
|
'-map', '1:a',
|
||||||
];
|
];
|
||||||
args = args.concat(ffmpegArgs[format])
|
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, {
|
const ffmpegProcess = spawn(ffmpeg, args, {
|
||||||
windowsHide: true,
|
windowsHide: true,
|
||||||
stdio: [
|
stdio: [
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { createStream } from "../stream/manage.js";
|
import { createStream } from "../stream/manage.js";
|
||||||
import { execSync } from "child_process";
|
|
||||||
|
|
||||||
export function apiJSON(type, obj) {
|
export function apiJSON(type, obj) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -141,37 +141,43 @@ async function download(url) {
|
||||||
fetch(`/api/json?quality=${localStorage.getItem("quality")}${format}&url=${encodeURIComponent(url)}`).then(async (response) => {
|
fetch(`/api/json?quality=${localStorage.getItem("quality")}${format}&url=${encodeURIComponent(url)}`).then(async (response) => {
|
||||||
let j = await response.json();
|
let j = await response.json();
|
||||||
if (j.status != "error" && j.status != "rate-limit") {
|
if (j.status != "error" && j.status != "rate-limit") {
|
||||||
switch (j.status) {
|
if (j.url) {
|
||||||
case "redirect":
|
switch (j.status) {
|
||||||
changeDownloadButton(2, '>>>')
|
case "redirect":
|
||||||
setTimeout(() => {
|
changeDownloadButton(2, '>>>')
|
||||||
changeDownloadButton(1, '>>')
|
setTimeout(() => {
|
||||||
eid("url-input-area").disabled = false
|
changeDownloadButton(1, '>>')
|
||||||
}, 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 {
|
|
||||||
eid("url-input-area").disabled = false
|
eid("url-input-area").disabled = false
|
||||||
changeDownloadButton(2, '!!')
|
}, 3000)
|
||||||
popup("error", 1, jp.text);
|
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 {
|
} else {
|
||||||
eid("url-input-area").disabled = false
|
eid("url-input-area").disabled = false
|
||||||
|
|
Loading…
Reference in a new issue