clean up
This commit is contained in:
parent
a5e081e2bf
commit
e11ee6fb62
24 changed files with 106 additions and 115 deletions
|
@ -61,7 +61,7 @@ Take English or Russian localization from [this directory](https://github.com/wu
|
||||||
- [ ] Add an option to keep watermark on TikTok videos
|
- [ ] Add an option to keep watermark on TikTok videos
|
||||||
|
|
||||||
### Other
|
### Other
|
||||||
- [ ] Remake video quality picking (do it more like I did in Vimeo module)
|
- [ ] Remake video quality picking
|
||||||
- [ ] Add support for emoji in localization
|
- [ ] Add support for emoji in localization
|
||||||
- [ ] Language picker in settings
|
- [ ] Language picker in settings
|
||||||
- [ ] Make cobalt fully PWA compatible (add a service worker)
|
- [ ] Make cobalt fully PWA compatible (add a service worker)
|
||||||
|
@ -96,8 +96,6 @@ Setup script installs all needed `npm` dependencies, but you have to install `No
|
||||||
## Disclaimer
|
## Disclaimer
|
||||||
This is my passion project, so update scheduele depends solely on my motivation. Don't expect any consistency in that.
|
This is my passion project, so update scheduele depends solely on my motivation. Don't expect any consistency in that.
|
||||||
|
|
||||||
## Third party stuff
|
|
||||||
[Fluent Emoji](https://github.com/microsoft/fluentui-emoji) by Microsoft.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
cobalt is under [AGPL-3.0](https://github.com/wukko/cobalt/blob/current/LICENSE).
|
cobalt is under [AGPL-3.0](https://github.com/wukko/cobalt/blob/current/LICENSE).
|
||||||
|
[Fluent Emoji](https://github.com/microsoft/fluentui-emoji) by Microsoft is under [MIT](https://github.com/microsoft/fluentui-emoji/blob/main/LICENSE).
|
||||||
|
|
|
@ -50,7 +50,7 @@ if (fs.existsSync('./.env')) {
|
||||||
try {
|
try {
|
||||||
decodeURIComponent(req.path)
|
decodeURIComponent(req.path)
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch (e) {
|
||||||
return res.redirect(process.env.selfURL);
|
return res.redirect(process.env.selfURL);
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
|
|
|
@ -51,7 +51,7 @@ function changeDownloadButton(action, text) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.addEventListener("keydown", function (event) {
|
document.addEventListener("keydown", (event) => {
|
||||||
if (event.key == "Tab") {
|
if (event.key == "Tab") {
|
||||||
eid("download-button").value = '>>'
|
eid("download-button").value = '>>'
|
||||||
eid("download-button").style.padding = '0 1rem'
|
eid("download-button").style.padding = '0 1rem'
|
||||||
|
@ -257,7 +257,7 @@ async function download(url) {
|
||||||
}
|
}
|
||||||
}).catch((error) => internetError());
|
}).catch((error) => internetError());
|
||||||
}
|
}
|
||||||
window.onload = function () {
|
window.onload = () => {
|
||||||
loadSettings();
|
loadSettings();
|
||||||
detectColorScheme();
|
detectColorScheme();
|
||||||
changeDownloadButton(0, '>>');
|
changeDownloadButton(0, '>>');
|
||||||
|
@ -274,6 +274,6 @@ window.onload = function () {
|
||||||
eid("url-input-area").addEventListener("keyup", (event) => {
|
eid("url-input-area").addEventListener("keyup", (event) => {
|
||||||
if (event.key === 'Enter') eid("download-button").click();
|
if (event.key === 'Enter') eid("download-button").click();
|
||||||
})
|
})
|
||||||
document.onkeydown = function(event) {
|
document.onkeydown = (event) => {
|
||||||
if (event.key === 'Escape') hideAllPopups();
|
if (event.key === 'Escape') hideAllPopups();
|
||||||
};
|
};
|
|
@ -59,7 +59,7 @@
|
||||||
"SettingsEnableDownloadPopup": "спрашивать, как сохранять",
|
"SettingsEnableDownloadPopup": "спрашивать, как сохранять",
|
||||||
"AccessibilityEnableDownloadPopup": "спрашивать, что делать с загрузками",
|
"AccessibilityEnableDownloadPopup": "спрашивать, что делать с загрузками",
|
||||||
"SettingsFormatDescription": "выбирай webm, если хочешь максимальное качество. webm обычно лучше по качеству, но устройства на ios не могут проигрывать их без сторонних приложений.",
|
"SettingsFormatDescription": "выбирай webm, если хочешь максимальное качество. webm обычно лучше по качеству, но устройства на ios не могут проигрывать их без сторонних приложений.",
|
||||||
"SettingsQualityDescription": "если выбранное разрешение недоступно, то выбирается ближайшее к нему. если ты хочешь твитнуть загруженное видео, то выбирай комбинацию из mp4 и 720p. такие видео твиттер обычно воспринимает намного лучше.",
|
"SettingsQualityDescription": "если выбранное разрешение недоступно, то выбирается ближайшее к нему. если ты хочешь твитнуть загруженное видео, то выбирай комбинацию из mp4 и 720p. твиттер такие видео обычно воспринимает намного лучше.",
|
||||||
"DonateSubtitle": "помоги мне платить за хостинг",
|
"DonateSubtitle": "помоги мне платить за хостинг",
|
||||||
"DonateDescription": "я не люблю крипто в его текущем состоянии, но у меня нет другого надёжного способа оплаты хостинга.",
|
"DonateDescription": "я не люблю крипто в его текущем состоянии, но у меня нет другого надёжного способа оплаты хостинга.",
|
||||||
"LinkGitHubIssues": ">> сообщай о проблемах и смотри исходный код на github",
|
"LinkGitHubIssues": ">> сообщай о проблемах и смотри исходный код на github",
|
||||||
|
|
|
@ -29,10 +29,10 @@ export async function getJSON(originalURL, ip, lang, format, quality, audioForma
|
||||||
}
|
}
|
||||||
if (patternMatch) {
|
if (patternMatch) {
|
||||||
return await match(host, patternMatch, url, ip, lang, format, quality, audioFormat, isAudioOnly);
|
return await match(host, patternMatch, url, ip, lang, format, quality, audioFormat, isAudioOnly);
|
||||||
} return apiJSON(0, { t: errorUnsupported(lang) } )
|
} return apiJSON(0, { t: errorUnsupported(lang) })
|
||||||
} return apiJSON(0, { t: errorUnsupported(lang) } )
|
} return apiJSON(0, { t: errorUnsupported(lang) })
|
||||||
} else {
|
} else {
|
||||||
return apiJSON(0, { t: errorUnsupported(lang) } )
|
return apiJSON(0, { t: errorUnsupported(lang) })
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return apiJSON(0, { t: loc(lang, 'ErrorSomethingWentWrong') });
|
return apiJSON(0, { t: loc(lang, 'ErrorSomethingWentWrong') });
|
||||||
|
|
|
@ -6,7 +6,7 @@ export async function buildFront() {
|
||||||
entryPoints: ['src/front/cobalt.js', 'src/front/cobalt.css'],
|
entryPoints: ['src/front/cobalt.js', 'src/front/cobalt.css'],
|
||||||
outdir: `min/`,
|
outdir: `min/`,
|
||||||
minify: true,
|
minify: true,
|
||||||
loader: {".js": "js", ".css": "css"}
|
loader: { ".js": "js", ".css": "css" }
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -3,17 +3,17 @@ const config = loadJson("./src/config.json");
|
||||||
const packageJson = loadJson("./package.json");
|
const packageJson = loadJson("./package.json");
|
||||||
|
|
||||||
export const
|
export const
|
||||||
services = loadJson("./src/modules/servicesConfig.json"),
|
services = loadJson("./src/modules/servicesConfig.json"),
|
||||||
appName = packageJson.name,
|
appName = packageJson.name,
|
||||||
version = packageJson.version,
|
version = packageJson.version,
|
||||||
streamLifespan = config.streamLifespan,
|
streamLifespan = config.streamLifespan,
|
||||||
maxVideoDuration = config.maxVideoDuration,
|
maxVideoDuration = config.maxVideoDuration,
|
||||||
genericUserAgent = config.genericUserAgent,
|
genericUserAgent = config.genericUserAgent,
|
||||||
repo = packageJson["bugs"]["url"].replace('/issues', ''),
|
repo = packageJson["bugs"]["url"].replace('/issues', ''),
|
||||||
authorInfo = config.authorInfo,
|
authorInfo = config.authorInfo,
|
||||||
supportedLanguages = config.supportedLanguages,
|
supportedLanguages = config.supportedLanguages,
|
||||||
quality = config.quality,
|
quality = config.quality,
|
||||||
internetExplorerRedirect = config.internetExplorerRedirect,
|
internetExplorerRedirect = config.internetExplorerRedirect,
|
||||||
donations = config.donations,
|
donations = config.donations,
|
||||||
ffmpegArgs = config.ffmpegArgs,
|
ffmpegArgs = config.ffmpegArgs,
|
||||||
supportedAudio = config.supportedAudio
|
supportedAudio = config.supportedAudio
|
||||||
|
|
|
@ -17,7 +17,7 @@ let sizing = {
|
||||||
}
|
}
|
||||||
export default function(emoji, size, disablePadding) {
|
export default function(emoji, size, disablePadding) {
|
||||||
if (!size) size = 22;
|
if (!size) size = 22;
|
||||||
let padding = size != 22 ? `margin-right:${sizing[size] ? sizing[size] : "0.4"}rem;`: ``;
|
let padding = size != 22 ? `margin-right:${sizing[size] ? sizing[size] : "0.4"}rem;` : ``;
|
||||||
if (disablePadding) padding = 'margin-right:0!important;';
|
if (disablePadding) padding = 'margin-right:0!important;';
|
||||||
if (!names[emoji]) emoji = "❓";
|
if (!names[emoji]) emoji = "❓";
|
||||||
return `<img class="emoji" height="${size}" width="${size}" style="${padding}" alt="${emoji}" src="emoji/${names[emoji]}.svg">`
|
return `<img class="emoji" height="${size}" width="${size}" style="${padding}" alt="${emoji}" src="emoji/${names[emoji]}.svg">`
|
||||||
|
|
|
@ -42,7 +42,7 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit
|
||||||
break;
|
break;
|
||||||
case "youtube":
|
case "youtube":
|
||||||
let fetchInfo = {
|
let fetchInfo = {
|
||||||
id: patternMatch["id"].slice(0,11),
|
id: patternMatch["id"].slice(0, 11),
|
||||||
lang: lang, quality: quality,
|
lang: lang, quality: quality,
|
||||||
format: "webm"
|
format: "webm"
|
||||||
};
|
};
|
||||||
|
@ -87,7 +87,7 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit
|
||||||
break;
|
break;
|
||||||
case "vimeo":
|
case "vimeo":
|
||||||
r = await vimeo({
|
r = await vimeo({
|
||||||
id: patternMatch["id"], quality: quality,
|
id: patternMatch["id"].slice(0, 11), quality: quality,
|
||||||
lang: lang
|
lang: lang
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -40,9 +40,9 @@ export function popup(obj) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return `
|
return `
|
||||||
${!obj.embed ? `<div id="popup-${obj.name}" class="popup center box${classes.length > 0 ? ' ' + classes.join(' ') : ''}" style="visibility: hidden;">`: ''}
|
${!obj.embed ? `<div id="popup-${obj.name}" class="popup center box${classes.length > 0 ? ' ' + classes.join(' ') : ''}" style="visibility: hidden;">` : ''}
|
||||||
<div id="popup-header" class="popup-header">
|
<div id="popup-header" class="popup-header">
|
||||||
${!obj.embed ? `<button id="popup-close" class="button mono" onclick="popup('${obj.name}', 0)" ${obj.header.closeAria ? `aria-label="${obj.header.closeAria}"` : ''}>x</button>`: ''}
|
${!obj.embed ? `<button id="popup-close" class="button mono" onclick="popup('${obj.name}', 0)" ${obj.header.closeAria ? `aria-label="${obj.header.closeAria}"` : ''}>x</button>` : ''}
|
||||||
${obj.header.aboveTitle ? `<a id="popup-above-title" href="${obj.header.aboveTitle.url}">${obj.header.aboveTitle.text}</a>` : ''}
|
${obj.header.aboveTitle ? `<a id="popup-above-title" href="${obj.header.aboveTitle.url}">${obj.header.aboveTitle.text}</a>` : ''}
|
||||||
${obj.header.title ? `<div id="popup-title">${obj.header.title}</div>` : ''}
|
${obj.header.title ? `<div id="popup-title">${obj.header.title}</div>` : ''}
|
||||||
${obj.header.subtitle ? `<div id="popup-subtitle">${obj.header.subtitle}</div>` : ''}
|
${obj.header.subtitle ? `<div id="popup-subtitle">${obj.header.subtitle}</div>` : ''}
|
||||||
|
@ -51,7 +51,7 @@ export function popup(obj) {
|
||||||
${obj.footer ? `<div id="popup-footer" class="popup-footer">
|
${obj.footer ? `<div id="popup-footer" class="popup-footer">
|
||||||
<a id="popup-bottom" class="popup-footer-content" href="${obj.footer.url}">${obj.footer.text}</a>
|
<a id="popup-bottom" class="popup-footer-content" href="${obj.footer.url}">${obj.footer.text}</a>
|
||||||
</div>` : ''}
|
</div>` : ''}
|
||||||
${!obj.embed ? `</div>`: ''}`
|
${!obj.embed ? `</div>` : ''}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function multiPagePopup(obj) {
|
export function multiPagePopup(obj) {
|
||||||
|
@ -68,7 +68,7 @@ export function multiPagePopup(obj) {
|
||||||
<div id="popup-content">${obj.header ? `<div id="popup-header" class="popup-header">
|
<div id="popup-content">${obj.header ? `<div id="popup-header" class="popup-header">
|
||||||
${obj.header.aboveTitle ? `<a id="popup-above-title" href="${obj.header.aboveTitle.url}">${obj.header.aboveTitle.text}</a>` : ''}
|
${obj.header.aboveTitle ? `<a id="popup-above-title" href="${obj.header.aboveTitle.url}">${obj.header.aboveTitle.text}</a>` : ''}
|
||||||
${obj.header.title ? `<div id="popup-title">${obj.header.title}</div>` : ''}
|
${obj.header.title ? `<div id="popup-title">${obj.header.title}</div>` : ''}
|
||||||
${obj.header.subtitle ? `<div id="popup-subtitle">${obj.header.subtitle}</div>` : ''}</div>`: ''}${tabContent}</div>
|
${obj.header.subtitle ? `<div id="popup-subtitle">${obj.header.subtitle}</div>` : ''}</div>` : ''}${tabContent}</div>
|
||||||
<div id="popup-tabs" class="switches popup-tabs">${tabs}</div>
|
<div id="popup-tabs" class="switches popup-tabs">${tabs}</div>
|
||||||
</div>`
|
</div>`
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
import { backdropLink, checkbox, footerButtons, multiPagePopup, popup, settingsCategory, switcher } from "./elements.js";
|
||||||
import { services, appName, authorInfo, version, quality, repo, donations, supportedAudio } from "../config.js";
|
import { services, appName, authorInfo, version, quality, repo, donations, supportedAudio } from "../config.js";
|
||||||
import { getCommitInfo } from "../sub/currentCommit.js";
|
import { getCommitInfo } from "../sub/currentCommit.js";
|
||||||
import loc from "../../localization/manager.js";
|
import loc from "../../localization/manager.js";
|
||||||
import { backdropLink, checkbox, footerButtons, multiPagePopup, popup, settingsCategory, switcher } from "./elements.js";
|
|
||||||
import emoji from "../emoji.js";
|
import emoji from "../emoji.js";
|
||||||
|
|
||||||
let s = services;
|
let s = services;
|
||||||
|
@ -16,7 +16,7 @@ let enabledServices = Object.keys(s).filter((p) => {
|
||||||
let donate = ``
|
let donate = ``
|
||||||
let donateLinks = ``
|
let donateLinks = ``
|
||||||
let audioFormats = supportedAudio.map((p) => {
|
let audioFormats = supportedAudio.map((p) => {
|
||||||
return {"action": p}
|
return { "action": p }
|
||||||
})
|
})
|
||||||
audioFormats.unshift({ "action": "best" })
|
audioFormats.unshift({ "action": "best" })
|
||||||
for (let i in donations["other"]) {
|
for (let i in donations["other"]) {
|
||||||
|
@ -183,19 +183,19 @@ export default function(obj) {
|
||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
}) + `${!isIOS ? checkbox("downloadPopup", loc(obj.lang, 'SettingsEnableDownloadPopup'), loc(obj.lang, 'AccessibilityEnableDownloadPopup')) : ''}`
|
}) + `${!isIOS ? checkbox("downloadPopup", loc(obj.lang, 'SettingsEnableDownloadPopup'), loc(obj.lang, 'AccessibilityEnableDownloadPopup')) : ''}`
|
||||||
+ settingsCategory({
|
+ settingsCategory({
|
||||||
name: "youtube",
|
name: "youtube",
|
||||||
body: switcher({
|
body: switcher({
|
||||||
name: "ytFormat",
|
name: "ytFormat",
|
||||||
subtitle: loc(obj.lang, 'SettingsFormatSubtitle'),
|
subtitle: loc(obj.lang, 'SettingsFormatSubtitle'),
|
||||||
explanation: loc(obj.lang, 'SettingsFormatDescription'),
|
explanation: loc(obj.lang, 'SettingsFormatDescription'),
|
||||||
items: [{
|
items: [{
|
||||||
"action": "mp4"
|
"action": "mp4"
|
||||||
}, {
|
}, {
|
||||||
"action": "webm"
|
"action": "webm"
|
||||||
}]
|
}]
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
}, {
|
}, {
|
||||||
name: "audio",
|
name: "audio",
|
||||||
title: `${emoji("🎶")} ${loc(obj.lang, 'SettingsAudioTab')}`,
|
title: `${emoji("🎶")} ${loc(obj.lang, 'SettingsAudioTab')}`,
|
||||||
|
@ -221,10 +221,10 @@ export default function(obj) {
|
||||||
items: [{
|
items: [{
|
||||||
"action": "auto",
|
"action": "auto",
|
||||||
"text": loc(obj.lang, 'SettingsThemeAuto')
|
"text": loc(obj.lang, 'SettingsThemeAuto')
|
||||||
},{
|
}, {
|
||||||
"action": "dark",
|
"action": "dark",
|
||||||
"text": loc(obj.lang, 'SettingsThemeDark')
|
"text": loc(obj.lang, 'SettingsThemeDark')
|
||||||
},{
|
}, {
|
||||||
"action": "light",
|
"action": "light",
|
||||||
"text": loc(obj.lang, 'SettingsThemeLight')
|
"text": loc(obj.lang, 'SettingsThemeLight')
|
||||||
}]
|
}]
|
||||||
|
@ -264,21 +264,21 @@ export default function(obj) {
|
||||||
</div>
|
</div>
|
||||||
<footer id="footer" style="visibility: hidden;">
|
<footer id="footer" style="visibility: hidden;">
|
||||||
${footerButtons([{
|
${footerButtons([{
|
||||||
name: "about",
|
name: "about",
|
||||||
type: "popup",
|
type: "popup",
|
||||||
icon: "?",
|
icon: "?",
|
||||||
aria: loc(obj.lang, 'AccessibilityOpenAbout')
|
aria: loc(obj.lang, 'AccessibilityOpenAbout')
|
||||||
}, {
|
}, {
|
||||||
name: "settings",
|
name: "settings",
|
||||||
type: "popup",
|
type: "popup",
|
||||||
icon: "+",
|
icon: "+",
|
||||||
aria: loc(obj.lang, 'AccessibilityOpenSettings')
|
aria: loc(obj.lang, 'AccessibilityOpenSettings')
|
||||||
}, {
|
}, {
|
||||||
name: "audioMode",
|
name: "audioMode",
|
||||||
type: "toggle",
|
type: "toggle",
|
||||||
icon: emoji("✨", 22, 1),
|
icon: emoji("✨", 22, 1),
|
||||||
aria: loc(obj.lang, 'AccessibilityModeToggle')
|
aria: loc(obj.lang, 'AccessibilityModeToggle')
|
||||||
}]
|
}]
|
||||||
)}
|
)}
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default async function(obj) {
|
||||||
let audio = streamData["data"]["dash"]["audio"].filter((a) => {
|
let audio = streamData["data"]["dash"]["audio"].filter((a) => {
|
||||||
if (!a["baseUrl"].includes("https://upos-sz-mirrorcosov.bilivideo.com/")) return true;
|
if (!a["baseUrl"].includes("https://upos-sz-mirrorcosov.bilivideo.com/")) return true;
|
||||||
}).sort((a, b) => Number(b.bandwidth) - Number(a.bandwidth));
|
}).sort((a, b) => Number(b.bandwidth) - Number(a.bandwidth));
|
||||||
return { urls: [video[0]["baseUrl"], audio[0]["baseUrl"]], time: streamData.data.timelength, audioFilename: `bilibili_${obj.id}_audio`, filename: `bilibili_${obj.id}_${video[0]["width"]}x${video[0]["height"]}.mp4` };
|
return { urls: [video[0]["baseUrl"], audio[0]["baseUrl"]], time: streamData.data.timelength, audioFilename: `bilibili_${obj.id}_audio`, filename: `bilibili_${obj.id}_${video[0]["width"]}x${video[0]["height"]}.mp4` };
|
||||||
} else {
|
} else {
|
||||||
return { error: loc(obj.lang, 'ErrorLengthLimit', maxVideoDuration / 60000) };
|
return { error: loc(obj.lang, 'ErrorLengthLimit', maxVideoDuration / 60000) };
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,16 @@ export default async function(obj) {
|
||||||
obj.postId = html.body.split('video/')[1].split('/?')[0]
|
obj.postId = html.body.split('video/')[1].split('/?')[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let iteminfo = await got.get(`https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=${obj.postId}`, {headers: {
|
let iteminfo = await got.get(`https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=${obj.postId}`, {
|
||||||
'authority': 'www.iesdouyin.com',
|
headers: {
|
||||||
'user-agent': genericUserAgent,
|
'authority': 'www.iesdouyin.com',
|
||||||
'content-type': 'application/x-www-form-urlencoded',
|
'user-agent': genericUserAgent,
|
||||||
'accept': '*/*',
|
'content-type': 'application/x-www-form-urlencoded',
|
||||||
'referer': `https://www.iesdouyin.com/share/video/${obj.postId}/?region=CN&u_code=15b9142gf&titleType=title&utm_source=copy_link&utm_campaign=client_share&utm_medium=android&app=aweme`,
|
'accept': '*/*',
|
||||||
'accept-language': 'zh-CN,zh;q=0.9,en-GB;q=0.8,en;q=0.7'
|
'referer': `https://www.iesdouyin.com/share/video/${obj.postId}/?region=CN&u_code=15b9142gf&titleType=title&utm_source=copy_link&utm_campaign=client_share&utm_medium=android&app=aweme`,
|
||||||
}});
|
'accept-language': 'zh-CN,zh;q=0.9,en-GB;q=0.8,en;q=0.7'
|
||||||
|
}
|
||||||
|
});
|
||||||
iteminfo.on('error', (err) => {
|
iteminfo.on('error', (err) => {
|
||||||
return { error: loc(obj.lang, 'ErrorCantConnectToServiceAPI', 'douyin') };
|
return { error: loc(obj.lang, 'ErrorCantConnectToServiceAPI', 'douyin') };
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,7 +18,7 @@ export default async function(obj) {
|
||||||
if (audio.length > 0) {
|
if (audio.length > 0) {
|
||||||
return { typeId: 2, type: "render", urls: [video, audio], audioFilename: `reddit_${id}_audio`, filename: `reddit_${id}.mp4` };
|
return { typeId: 2, type: "render", urls: [video, audio], audioFilename: `reddit_${id}_audio`, filename: `reddit_${id}.mp4` };
|
||||||
} else {
|
} else {
|
||||||
return { typeId: 1, urls: video, audioFilename: loc(obj.lang, 'ErrorEmptyDownload')};
|
return { typeId: 1, urls: video, audioFilename: loc(obj.lang, 'ErrorEmptyDownload') };
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return { error: loc(obj.lang, 'ErrorEmptyDownload') };
|
return { error: loc(obj.lang, 'ErrorEmptyDownload') };
|
||||||
|
|
|
@ -31,7 +31,7 @@ async function fetchTweetInfo(obj) {
|
||||||
return cantConnect;
|
return cantConnect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export default async function (obj) {
|
export default async function(obj) {
|
||||||
let nothing = { error: loc(obj.lang, 'ErrorEmptyDownload') }
|
let nothing = { error: loc(obj.lang, 'ErrorEmptyDownload') }
|
||||||
try {
|
try {
|
||||||
let parsbod = await fetchTweetInfo(obj);
|
let parsbod = await fetchTweetInfo(obj);
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default async function(obj) {
|
||||||
let selectedQuality = `url${attr["height"]}`;
|
let selectedQuality = `url${attr["height"]}`;
|
||||||
|
|
||||||
let maxQuality = js["player"]["params"][0][selectedQuality].split('type=')[1].slice(0, 1)
|
let maxQuality = js["player"]["params"][0][selectedQuality].split('type=')[1].slice(0, 1)
|
||||||
let userQuality = selectQuality('vk', obj.quality, Object.entries(services.vk.quality_match).reduce((r, [k, v]) => { r[v] = k; return r;})[maxQuality])
|
let userQuality = selectQuality('vk', obj.quality, Object.entries(services.vk.quality_match).reduce((r, [k, v]) => { r[v] = k; return r; })[maxQuality])
|
||||||
let id = js["player"]["params"][0][selectedQuality].split("id=")[1]
|
let id = js["player"]["params"][0][selectedQuality].split("id=")[1]
|
||||||
if (selectedQuality in js["player"]["params"][0]) {
|
if (selectedQuality in js["player"]["params"][0]) {
|
||||||
return { urls: js["player"]["params"][0][selectedQuality].replace(`type=${maxQuality}`, `type=${services.vk.quality_match[userQuality]}`), filename: `vk_${id}_${attr['width']}x${attr['height']}.mp4`, audioFilename: loc(obj.lang, 'ErrorEmptyDownload') };
|
return { urls: js["player"]["params"][0][selectedQuality].replace(`type=${maxQuality}`, `type=${services.vk.quality_match[userQuality]}`), filename: `vk_${id}_${attr['width']}x${attr['height']}.mp4`, audioFilename: loc(obj.lang, 'ErrorEmptyDownload') };
|
||||||
|
|
|
@ -3,7 +3,7 @@ import loc from "../../localization/manager.js";
|
||||||
import { maxVideoDuration, quality as mq } from "../config.js";
|
import { maxVideoDuration, quality as mq } from "../config.js";
|
||||||
import selectQuality from "../stream/selectQuality.js";
|
import selectQuality from "../stream/selectQuality.js";
|
||||||
|
|
||||||
export default async function (obj) {
|
export default async function(obj) {
|
||||||
try {
|
try {
|
||||||
let info = await ytdl.getInfo(obj.id);
|
let info = await ytdl.getInfo(obj.id);
|
||||||
if (info) {
|
if (info) {
|
||||||
|
@ -41,18 +41,24 @@ export default async function (obj) {
|
||||||
if (!obj.isAudioOnly && videoMatch.length > 0) {
|
if (!obj.isAudioOnly && videoMatch.length > 0) {
|
||||||
if (video.length > 0 && audio.length > 0) {
|
if (video.length > 0 && audio.length > 0) {
|
||||||
if (videoMatch[0]["hasVideo"] && videoMatch[0]["hasAudio"]) {
|
if (videoMatch[0]["hasVideo"] && videoMatch[0]["hasAudio"]) {
|
||||||
return { type: "bridge", urls: videoMatch[0]["url"], time: videoMatch[0]["approxDurationMs"],
|
return {
|
||||||
filename: `youtube_${obj.id}_${videoMatch[0]["width"]}x${videoMatch[0]["height"]}.${obj.format}` };
|
type: "bridge", urls: videoMatch[0]["url"], time: videoMatch[0]["approxDurationMs"],
|
||||||
|
filename: `youtube_${obj.id}_${videoMatch[0]["width"]}x${videoMatch[0]["height"]}.${obj.format}`
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
return { type: "render", urls: [videoMatch[0]["url"], audio[0]["url"]], time: videoMatch[0]["approxDurationMs"],
|
return {
|
||||||
filename: `youtube_${obj.id}_${videoMatch[0]["width"]}x${videoMatch[0]["height"]}.${obj.format}` };
|
type: "render", urls: [videoMatch[0]["url"], audio[0]["url"]], time: videoMatch[0]["approxDurationMs"],
|
||||||
|
filename: `youtube_${obj.id}_${videoMatch[0]["width"]}x${videoMatch[0]["height"]}.${obj.format}`
|
||||||
|
};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return { error: loc(obj.lang, 'ErrorBadFetch') };
|
return { error: loc(obj.lang, 'ErrorBadFetch') };
|
||||||
}
|
}
|
||||||
} else if (!obj.isAudioOnly) {
|
} else if (!obj.isAudioOnly) {
|
||||||
return { type: "render", urls: [video[0]["url"], audio[0]["url"]], time: video[0]["approxDurationMs"],
|
return {
|
||||||
filename: `youtube_${obj.id}_${video[0]["width"]}x${video[0]["height"]}.${video[0]["container"]}` };
|
type: "render", urls: [video[0]["url"], audio[0]["url"]], time: video[0]["approxDurationMs"],
|
||||||
|
filename: `youtube_${obj.id}_${video[0]["width"]}x${video[0]["height"]}.${video[0]["container"]}`
|
||||||
|
};
|
||||||
} else if (audio.length > 0) {
|
} else if (audio.length > 0) {
|
||||||
return { type: "bridge", isAudioOnly: true, urls: audio[0]["url"], audioFilename: `youtube_${obj.id}_audio` };
|
return { type: "bridge", isAudioOnly: true, urls: audio[0]["url"], audioFilename: `youtube_${obj.id}_audio` };
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"youtube": {
|
"youtube": {
|
||||||
|
"alias": "youtube, youtube music",
|
||||||
"patterns": ["watch?v=:id"],
|
"patterns": ["watch?v=:id"],
|
||||||
"quality_match": ["2160", "1440", "1080", "720", "480", "360", "240", "144"],
|
"quality_match": ["2160", "1440", "1080", "720", "480", "360", "240", "144"],
|
||||||
"quality": {
|
"quality": {
|
||||||
|
@ -49,18 +50,10 @@
|
||||||
},
|
},
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"youtube music": {
|
|
||||||
"patterns": ["watch?v=:id"],
|
|
||||||
"enabled": true
|
|
||||||
},
|
|
||||||
"tumblr": {
|
"tumblr": {
|
||||||
"patterns": ["post/:id", "blog/view/:user/:id"],
|
"patterns": ["post/:id", "blog/view/:user/:id"],
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"instagram": {
|
|
||||||
"patterns": [":type/:id"],
|
|
||||||
"enabled": false
|
|
||||||
},
|
|
||||||
"tiktok": {
|
"tiktok": {
|
||||||
"patterns": [":user/video/:postId", ":id", "t/:id"],
|
"patterns": [":user/video/:postId", ":id", "t/:id"],
|
||||||
"enabled": true
|
"enabled": true
|
||||||
|
|
|
@ -2,23 +2,23 @@ export let testers = {
|
||||||
"twitter": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length < 20),
|
"twitter": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length < 20),
|
||||||
|
|
||||||
"vk": (patternMatch) => (patternMatch["userId"] && patternMatch["videoId"] &&
|
"vk": (patternMatch) => (patternMatch["userId"] && patternMatch["videoId"] &&
|
||||||
patternMatch["userId"].length <= 10 && patternMatch["videoId"].length == 9),
|
patternMatch["userId"].length <= 10 && patternMatch["videoId"].length == 9),
|
||||||
|
|
||||||
"bilibili": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length >= 12),
|
"bilibili": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length >= 12),
|
||||||
|
|
||||||
"youtube": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length >= 11),
|
"youtube": (patternMatch) => (patternMatch["id"] && patternMatch["id"].length >= 11),
|
||||||
|
|
||||||
"reddit": (patternMatch) => (patternMatch["sub"] && patternMatch["id"] && patternMatch["title"] &&
|
"reddit": (patternMatch) => (patternMatch["sub"] && patternMatch["id"] && patternMatch["title"] &&
|
||||||
patternMatch["sub"].length <= 22 && patternMatch["id"].length <= 10 && patternMatch["title"].length <= 96),
|
patternMatch["sub"].length <= 22 && patternMatch["id"].length <= 10 && patternMatch["title"].length <= 96),
|
||||||
|
|
||||||
"tiktok": (patternMatch) => ((patternMatch["user"] && patternMatch["postId"] && patternMatch["postId"].length <= 21) ||
|
"tiktok": (patternMatch) => ((patternMatch["user"] && patternMatch["postId"] && patternMatch["postId"].length <= 21) ||
|
||||||
(patternMatch["id"] && patternMatch["id"].length <= 13)),
|
(patternMatch["id"] && patternMatch["id"].length <= 13)),
|
||||||
|
|
||||||
"douyin": (patternMatch) => ((patternMatch["postId"] && patternMatch["postId"].length <= 21) ||
|
"douyin": (patternMatch) => ((patternMatch["postId"] && patternMatch["postId"].length <= 21) ||
|
||||||
(patternMatch["id"] && patternMatch["id"].length <= 13)),
|
(patternMatch["id"] && patternMatch["id"].length <= 13)),
|
||||||
|
|
||||||
"tumblr": (patternMatch) => ((patternMatch["id"] && patternMatch["id"].length < 21) ||
|
"tumblr": (patternMatch) => ((patternMatch["id"] && patternMatch["id"].length < 21) ||
|
||||||
(patternMatch["id"] && patternMatch["id"].length < 21 && patternMatch["user"] && patternMatch["user"].length <= 32)),
|
(patternMatch["id"] && patternMatch["id"].length < 21 && patternMatch["user"] && patternMatch["user"].length <= 32)),
|
||||||
|
|
||||||
"vimeo": (patternMatch) => ((patternMatch["id"] && patternMatch["id"].length <= 11)),
|
"vimeo": (patternMatch) => ((patternMatch["id"] && patternMatch["id"].length <= 11)),
|
||||||
};
|
};
|
|
@ -7,7 +7,7 @@ import { execSync } from "child_process";
|
||||||
let envPath = './.env';
|
let envPath = './.env';
|
||||||
let q = `${Cyan('?')} \x1b[1m`;
|
let q = `${Cyan('?')} \x1b[1m`;
|
||||||
let ob = { streamSalt: randomBytes(64).toString('hex') }
|
let ob = { streamSalt: randomBytes(64).toString('hex') }
|
||||||
let rl = createInterface({ input: process.stdin,output: process.stdout });
|
let rl = createInterface({ input: process.stdin, output: process.stdout });
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`${Cyan("Welcome to cobalt!")}\n${Bright("We'll get you up and running in no time.\nLet's start by creating a ")}${Cyan(".env")}${Bright(" file. You can always change it later.")}`
|
`${Cyan("Welcome to cobalt!")}\n${Bright("We'll get you up and running in no time.\nLet's start by creating a ")}${Cyan(".env")}${Bright(" file. You can always change it later.")}`
|
||||||
|
@ -46,7 +46,7 @@ let final = () => {
|
||||||
}
|
}
|
||||||
console.log(Bright("\nI've created a .env file with selfURL, port, and stream salt."))
|
console.log(Bright("\nI've created a .env file with selfURL, port, and stream salt."))
|
||||||
console.log(`${Bright("Now I'll run")} ${Cyan("npm install")} ${Bright("to install all dependencies. It shouldn't take long.\n\n")}`)
|
console.log(`${Bright("Now I'll run")} ${Cyan("npm install")} ${Bright("to install all dependencies. It shouldn't take long.\n\n")}`)
|
||||||
execSync('npm install',{stdio:[0,1,2]});
|
execSync('npm install', { stdio: [0, 1, 2] });
|
||||||
console.log(`\n\n${Green("All done!\n")}`)
|
console.log(`\n\n${Green("All done!\n")}`)
|
||||||
console.log("You can re-run this script any time to update the configuration.")
|
console.log("You can re-run this script any time to update the configuration.")
|
||||||
console.log("\nYou're now ready to start the main project.\nHave fun!")
|
console.log("\nYou're now ready to start the main project.\nHave fun!")
|
||||||
|
|
|
@ -1,22 +1,19 @@
|
||||||
import { services, quality as mq } from "../config.js";
|
import { services, quality as mq } from "../config.js";
|
||||||
|
|
||||||
function closest(goal, array) {
|
function closest(goal, array) {
|
||||||
return array.sort().reduce(function(prev, curr) {
|
return array.sort().reduce(function (prev, curr) {
|
||||||
return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
|
return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function(service, quality, maxQuality) {
|
export default function(service, quality, maxQuality) {
|
||||||
if (quality == "max") {
|
if (quality == "max") return maxQuality;
|
||||||
return maxQuality
|
|
||||||
}
|
|
||||||
|
|
||||||
quality = parseInt(mq[quality])
|
quality = parseInt(mq[quality])
|
||||||
maxQuality = parseInt(maxQuality)
|
maxQuality = parseInt(maxQuality)
|
||||||
|
|
||||||
if (quality >= maxQuality || quality == maxQuality) {
|
if (quality >= maxQuality || quality == maxQuality) return maxQuality;
|
||||||
return maxQuality
|
|
||||||
}
|
|
||||||
if (quality < maxQuality) {
|
if (quality < maxQuality) {
|
||||||
if (services[service]["quality"][quality]) {
|
if (services[service]["quality"][quality]) {
|
||||||
return quality
|
return quality
|
||||||
|
|
|
@ -55,27 +55,22 @@ export async function streamLiveRender(streamInfo, res) {
|
||||||
ffmpegProcess.on('error', (err) => {
|
ffmpegProcess.on('error', (err) => {
|
||||||
ffmpegProcess.kill();
|
ffmpegProcess.kill();
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
|
||||||
});
|
});
|
||||||
video.pipe(ffmpegProcess.stdio[3]).on('error', (err) => {
|
video.pipe(ffmpegProcess.stdio[3]).on('error', (err) => {
|
||||||
ffmpegProcess.kill();
|
ffmpegProcess.kill();
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
|
||||||
});
|
});
|
||||||
audio.pipe(ffmpegProcess.stdio[4]).on('error', (err) => {
|
audio.pipe(ffmpegProcess.stdio[4]).on('error', (err) => {
|
||||||
ffmpegProcess.kill();
|
ffmpegProcess.kill();
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
|
||||||
});
|
});
|
||||||
audio.on('error', (err) => {
|
audio.on('error', (err) => {
|
||||||
ffmpegProcess.kill();
|
ffmpegProcess.kill();
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
|
||||||
});
|
});
|
||||||
video.on('error', (err) => {
|
video.on('error', (err) => {
|
||||||
ffmpegProcess.kill();
|
ffmpegProcess.kill();
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
res.end();
|
res.end();
|
||||||
|
|
Loading…
Reference in a new issue