vk fixes and new changelog system
This commit is contained in:
parent
fbb2f2d200
commit
c6d1761b11
18 changed files with 179 additions and 45 deletions
|
@ -47,8 +47,8 @@ You can translate cobalt to any language you want on [cobalt's crowdin](https://
|
||||||
- You can add wordplays or puns if it feels natural to do so.
|
- You can add wordplays or puns if it feels natural to do so.
|
||||||
- Even though I love cursing, keep that to minimum in translations, and do **NOT** use any offensive words.
|
- Even though I love cursing, keep that to minimum in translations, and do **NOT** use any offensive words.
|
||||||
- Check if there are issues in UI with your localization, and optimize it accordingly, or open an issue.
|
- Check if there are issues in UI with your localization, and optimize it accordingly, or open an issue.
|
||||||
- Add "(in english)" translated to your language at the end of `ChangelogLastCommit` and `ChangelogLastMajor`. Those are always kept exclusively in English, due to how often changelog changes.
|
- Add "(in english)" translated to your language at the end of `ChangelogLastCommit`, `ChangelogLastMajor`, and `ChangelogOlder`. Those are always kept exclusively in English (for now), due to how often changelog changes.
|
||||||
- Example of translation to Russian: `"ChangelogLastCommit": "последний коммит (на английском)"`
|
- Sample translation to Russian: `"ChangelogLastCommit": "последний коммит (на английском)"`
|
||||||
- Be nice.
|
- Be nice.
|
||||||
|
|
||||||
## Host an instance yourself
|
## Host an instance yourself
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "cobalt",
|
"name": "cobalt",
|
||||||
"description": "save what you love",
|
"description": "save what you love",
|
||||||
"version": "3.5",
|
"version": "3.5.2",
|
||||||
"author": "wukko",
|
"author": "wukko",
|
||||||
"exports": "./src/cobalt.js",
|
"exports": "./src/cobalt.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { Bright, Cyan } from "./modules/sub/consoleText.js";
|
||||||
import stream from "./modules/stream/stream.js";
|
import stream from "./modules/stream/stream.js";
|
||||||
import loc from "./localization/manager.js";
|
import loc from "./localization/manager.js";
|
||||||
import { buildFront } from "./modules/build.js";
|
import { buildFront } from "./modules/build.js";
|
||||||
|
import { changelogHistory } from "./modules/pageRender/onDemand.js";
|
||||||
|
|
||||||
const commitHash = shortCommit();
|
const commitHash = shortCommit();
|
||||||
const app = express();
|
const app = express();
|
||||||
|
@ -91,8 +92,27 @@ if (fs.existsSync('./.env')) {
|
||||||
res.status(j.status).json(j.body);
|
res.status(j.status).json(j.body);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'onDemand':
|
||||||
|
if (req.query.blockId) {
|
||||||
|
let blockId = req.query.blockId.slice(0, 3)
|
||||||
|
let r, j;
|
||||||
|
switch(blockId) {
|
||||||
|
case "0":
|
||||||
|
r = changelogHistory();
|
||||||
|
j = r ? apiJSON(3, { t: r }) : apiJSON(0, { t: "couldn't render this block" })
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
let j = apiJSON(0, { t: "wrong response type" })
|
j = apiJSON(0, { t: "couldn't find a block with this id" })
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res.status(j.status).json(j.body);
|
||||||
|
} else {
|
||||||
|
let j = apiJSON(0, { t: "no block id" })
|
||||||
|
res.status(j.status).json(j.body);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
let j = apiJSON(0, { t: "unknown response type" })
|
||||||
res.status(j.status).json(j.body);
|
res.status(j.status).json(j.body);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
"internetExplorerRedirect": {
|
"internetExplorerRedirect": {
|
||||||
"newNT": ["6.1", "6.2", "6.3", "10.0"],
|
"newNT": ["6.1", "6.2", "6.3", "10.0"],
|
||||||
"old": "https://mypal-browser.org/",
|
"old": "https://mypal-browser.org/",
|
||||||
"new": "https://www.mozilla.org/firefox/new/"
|
"new": "https://vivaldi.com/"
|
||||||
},
|
},
|
||||||
"donations": {
|
"donations": {
|
||||||
"crypto": {
|
"crypto": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
let isIOS = navigator.userAgent.toLowerCase().match("iphone os");
|
let isIOS = navigator.userAgent.toLowerCase().match("iphone os");
|
||||||
let isFirefox = navigator.userAgent.toLowerCase().match("firefox/");
|
let isFirefox = navigator.userAgent.toLowerCase().match("firefox/");
|
||||||
let version = 7;
|
let version = 8;
|
||||||
let regex = new RegExp(/https:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_\+.~#?&\/\/=]*)/);
|
let regex = new RegExp(/https:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()!@:%_\+.~#?&\/\/=]*)/);
|
||||||
|
|
||||||
let switchers = {
|
let switchers = {
|
||||||
|
@ -330,6 +330,25 @@ async function download(url) {
|
||||||
}
|
}
|
||||||
}).catch((error) => internetError());
|
}).catch((error) => internetError());
|
||||||
}
|
}
|
||||||
|
async function loadOnDemand(elementId, blockId) {
|
||||||
|
let store = eid(elementId).innerHTML;
|
||||||
|
eid(elementId).innerHTML = "..."
|
||||||
|
await fetch(`/api/onDemand?blockId=${blockId}`).then(async (r) => {
|
||||||
|
let j = await r.json();
|
||||||
|
if (j.status == "success" && j.status != "rate-limit") {
|
||||||
|
if (j.text) {
|
||||||
|
eid(elementId).innerHTML = j.text;
|
||||||
|
} else {
|
||||||
|
throw new Error()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Error()
|
||||||
|
}
|
||||||
|
}).catch((error) => {
|
||||||
|
eid(elementId).innerHTML = store;
|
||||||
|
internetError()
|
||||||
|
});
|
||||||
|
}
|
||||||
window.onload = () => {
|
window.onload = () => {
|
||||||
loadSettings();
|
loadSettings();
|
||||||
detectColorScheme();
|
detectColorScheme();
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
{
|
|
||||||
"ContentTitle": "ui revamp and usability imporvements (3.5)",
|
|
||||||
"Content": "new features:\n- cobalt now lets you paste the link in your clipboard and download the file in a single press of a button. if your clipboard's latest content isn't a valid url, cobalt won't process or paste it. you can also hide the clipboard button in settings if you want to.\nunfortunately, the clipboard feature is not available to firefox users because mozilla didn't add proper support for clipboard api.\n\n- there's now a button to quickly clean the input area, right next to download button. it's really useful in case when you want to quickly save a bunch of videos and don't want to bother selecting text.\n\n- keyboard shortcuts! you love them, i love them, and now we can use them to perform quick actions in cobalt. use ctrl+v combo to paste the link without focusing the input area; press escape key to close the active popup or clean the input area; and if you didn't know, you can also press enter to download content from the link.\n\nnew looks:\n- main box has been revamped. it has lost its border, thick padding, and now feels light and fresh.\n\n- download button is now prettier, and has been tuned to make >> look just like the logo.\n\n- buttons on the bottom now actually look like buttons and are way more descriptive. no more #@+?$ bullshit. it's way easier to see and understand what each of them does.\n\n- bottom buttons are also prettier and easier to use on a phone. they're bigger and stretch out to sides, making them easier to press.\n\nfixes:\n- it's now impossible to overlap multiple popups at once. no more mess if you decide to explore popups while waiting for request to process.\n\n- popup tabs have been slightly moved down to prevent popup content overlapping.\n\n- ui scalability has been improved.",
|
|
||||||
"FollowTwitter": "follow cobalt's twitter account for polls, updates, and more: <a class=\"text-backdrop\" href=\"https://twitter.com/justusecobalt\" target=\"_blank\">@justusecobalt</a>"
|
|
||||||
}
|
|
|
@ -59,7 +59,7 @@
|
||||||
"DonateSubtitle": "help me pay for hosting",
|
"DonateSubtitle": "help me pay for hosting",
|
||||||
"DonateDescription": "i don't really like crypto in its current state, but it's the only reliable way for me to receive money and pay for anything abroad.",
|
"DonateDescription": "i don't really like crypto in its current state, but it's the only reliable way for me to receive money and pay for anything abroad.",
|
||||||
"LinkGitHubIssues": ">> report issues and check out the source code on github",
|
"LinkGitHubIssues": ">> report issues and check out the source code on github",
|
||||||
"LinkGitHubChanges": ">> see previous changes and contribute on github",
|
"LinkGitHubChanges": ">> see previous commits and contribute on github",
|
||||||
"LinkDonateContact": ">> let me know if currency you want to donate isn't listed",
|
"LinkDonateContact": ">> let me know if currency you want to donate isn't listed",
|
||||||
"NoScriptMessage": "{appName} uses javascript for api requests and interactive interface. you have to allow javascript to use this site. i don't have any ads or trackers, pinky promise.",
|
"NoScriptMessage": "{appName} uses javascript for api requests and interactive interface. you have to allow javascript to use this site. i don't have any ads or trackers, pinky promise.",
|
||||||
"DownloadPopupDescriptionIOS": "because you have an ios device, you have to press and hold the download button and then select \"download video\" in appeared popup to save the video. this will be required for as long as apple forces safari webview upon all browser developers on ios.",
|
"DownloadPopupDescriptionIOS": "because you have an ios device, you have to press and hold the download button and then select \"download video\" in appeared popup to save the video. this will be required for as long as apple forces safari webview upon all browser developers on ios.",
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
"SettingsAudioTab": "audio",
|
"SettingsAudioTab": "audio",
|
||||||
"SettingsOtherTab": "other",
|
"SettingsOtherTab": "other",
|
||||||
"ChangelogLastCommit": "last commit",
|
"ChangelogLastCommit": "last commit",
|
||||||
"ChangelogLastMajor": "last major update",
|
"ChangelogLastMajor": "last update",
|
||||||
"AccessibilityModeToggle": "toggle download mode",
|
"AccessibilityModeToggle": "toggle download mode",
|
||||||
"DonateLinksDescription": "donation links open in a new tab. this is the best way to donate money, if you want me to receive it directly.",
|
"DonateLinksDescription": "donation links open in a new tab. this is the best way to donate money, if you want me to receive it directly.",
|
||||||
"SettingsAudioFormatBest": "best",
|
"SettingsAudioFormatBest": "best",
|
||||||
|
@ -98,6 +98,9 @@
|
||||||
"ErrorNoUrlReturned": "server didn't return a download link. this should never happen. reload the page and try again, but if it doesn't help, {ContactLink}.",
|
"ErrorNoUrlReturned": "server didn't return a download link. this should never happen. reload the page and try again, but if it doesn't help, {ContactLink}.",
|
||||||
"ErrorUnknownStatus": "i received a response i can't process. most likely something with status is wrong. this should never happen. reload the page and try again, but if it doesn't help, {ContactLink}.",
|
"ErrorUnknownStatus": "i received a response i can't process. most likely something with status is wrong. this should never happen. reload the page and try again, but if it doesn't help, {ContactLink}.",
|
||||||
"PasteFromClipboard": "paste from clipboard",
|
"PasteFromClipboard": "paste from clipboard",
|
||||||
"SettingsDisableClipboard": "hide clipboard button"
|
"SettingsDisableClipboard": "hide clipboard button",
|
||||||
|
"FollowTwitter": "follow {appName}'s twitter account for polls, updates, and more: <a class=\"text-backdrop\" href=\"https://twitter.com/justusecobalt\" target=\"_blank\">@justusecobalt</a>",
|
||||||
|
"ChangelogOlder": "previous updates",
|
||||||
|
"ChangelogPressToExpand": "press to load"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,6 +98,9 @@
|
||||||
"ErrorNoUrlReturned": "я не получил ссылку для скачивания от сервера. такого происходить не должно. перезагрузи страницу, а если не поможет, то {ContactLink}.",
|
"ErrorNoUrlReturned": "я не получил ссылку для скачивания от сервера. такого происходить не должно. перезагрузи страницу, а если не поможет, то {ContactLink}.",
|
||||||
"ErrorUnknownStatus": "сервер ответил мне чем-то непонятным. такого происходить не должно. перезагрузи страницу, а если не поможет, то {ContactLink}.",
|
"ErrorUnknownStatus": "сервер ответил мне чем-то непонятным. такого происходить не должно. перезагрузи страницу, а если не поможет, то {ContactLink}.",
|
||||||
"PasteFromClipboard": "вставить из буфера обмена",
|
"PasteFromClipboard": "вставить из буфера обмена",
|
||||||
"SettingsDisableClipboard": "скрыть кнопку буфера обмена"
|
"SettingsDisableClipboard": "скрыть кнопку буфера обмена",
|
||||||
|
"FollowTwitter": "а ещё, в твиттере {appName} есть опросы, новости, и многое другое: <a class=\"text-backdrop\" href=\"https://twitter.com/justusecobalt\" target=\"_blank\">@justusecobalt</a>",
|
||||||
|
"ChangelogOlder": "предыдущие обновления (на английском)",
|
||||||
|
"ChangelogPressToExpand": "нажми, чтобы загрузить"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import loadJson from "../modules/sub/loadJSON.js";
|
||||||
const locPath = './src/localization/languages'
|
const locPath = './src/localization/languages'
|
||||||
|
|
||||||
let loc = {}
|
let loc = {}
|
||||||
let changelog = loadJson('./src/localization/changelog.json')
|
|
||||||
|
|
||||||
export function loadLoc() {
|
export function loadLoc() {
|
||||||
fs.readdir(locPath, (err, files) => {
|
fs.readdir(locPath, (err, files) => {
|
||||||
|
@ -30,7 +29,6 @@ export function replaceAll(lang, str, string, replacement) {
|
||||||
}
|
}
|
||||||
export default function(lang, string, replacement) {
|
export default function(lang, string, replacement) {
|
||||||
try {
|
try {
|
||||||
if (lang === "changelog") return replaceBase(changelog[string]);
|
|
||||||
if (!Object.keys(loc).includes(lang)) lang = 'en';
|
if (!Object.keys(loc).includes(lang)) lang = 'en';
|
||||||
let str = loc[lang]["strings"];
|
let str = loc[lang]["strings"];
|
||||||
if (str && str[string]) {
|
if (str && str[string]) {
|
||||||
|
|
10
src/modules/changelog/changelog.json
Normal file
10
src/modules/changelog/changelog.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"current": {
|
||||||
|
"title": "vk clips support, improved changelog system, and less bugs (3.5.2)",
|
||||||
|
"content": "new features: \n- added support for vk clips. {appName} now lets you download even more cringy videos!\n- added update history right to the changelog menu. it's not loaded by default to minimize page load time, but can be loaded upon pressing a button. probably someone will enjoy this.\n- as you've just read, cobalt now has on-demand blocks. they're rendered on server upon request and exist to prevent any unnecessary clutter by default. the first feature to use on-demand rendering is history of updates in changelog tab.\n\nchanges:\n- moved twitter entry to about tab and made it localized.\n- added clarity to what services exactly are supported in about tab.\n\nbug fixes:\n- cobalt should no longer crash to firefox users if they love to play around with user-agent switching.\n- vk videos of any resolution and aspect ratio should now be downloadable.\n- vk quality picking has been fixed after vk broke it for parsers on their side."
|
||||||
|
},
|
||||||
|
"history": [{
|
||||||
|
"title": "ui revamp and usability imporvements (3.5)",
|
||||||
|
"content": "new features:\n- {appName} now lets you paste the link in your clipboard and download the file in a single press of a button.if your clipboard's latest content isn't a valid url, {appName} won't process or paste it. you can also hide the clipboard button in settings if you want to.\nunfortunately, the clipboard feature is not available to firefox users because mozilla didn't add proper support for clipboard api.\n- there's now a button to quickly clean the input area, right next to download button. it's really useful in case when you want to quickly save a bunch of videos and don't want to bother selecting text.\n- keyboard shortcuts! you love them, i love them, and now we can use them to perform quick actions in {appName}. use ctrl+v combo to paste the link without focusing the input area; press escape key to close the active popup or clean the input area; and if you didn't know, you can also press enter to download content from the link.\n\nnew looks:\n- main box has been revamped. it has lost its border, thick padding, and now feels light and fresh.\n- download button is now prettier, and has been tuned to make >> look just like the logo.\n- buttons on the bottom now actually look like buttons and are way more descriptive. no more #@+?$ bullshit. it's way easier to see and understand what each of them does.\n- bottom buttons are prettier and easier to use on a phone. they're bigger and stretch out to sides, making them easier to press.\n\nfixes:\n- it's now impossible to overlap multiple popups at once. no more mess if you decide to explore popups while waiting for request to process.\n- popup tabs have been slightly moved down to prevent popup content overlapping.\n- ui scalability has been improved."
|
||||||
|
}]
|
||||||
|
}
|
24
src/modules/changelog/changelogManager.js
Normal file
24
src/modules/changelog/changelogManager.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { replaceBase } from "../../localization/manager.js";
|
||||||
|
import loadJSON from "../sub/loadJSON.js";
|
||||||
|
|
||||||
|
let changelog = loadJSON('./src/modules/changelog/changelog.json')
|
||||||
|
|
||||||
|
export default function(string) {
|
||||||
|
try {
|
||||||
|
switch (string) {
|
||||||
|
case "title":
|
||||||
|
return replaceBase(changelog["current"]["title"]);
|
||||||
|
case "content":
|
||||||
|
return replaceBase(changelog["current"]["content"]);
|
||||||
|
case "history":
|
||||||
|
return changelog["history"].map((i) => {
|
||||||
|
return {
|
||||||
|
title: replaceBase(i["title"]),
|
||||||
|
content: replaceBase(i["content"])
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return `!!CHANGELOG_${string}!!`
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ const names = {
|
||||||
"✨": "sparkles",
|
"✨": "sparkles",
|
||||||
"🪅": "pinata",
|
"🪅": "pinata",
|
||||||
"🪄": "magic_wand",
|
"🪄": "magic_wand",
|
||||||
"🐲": "dragon_face_wukko",
|
"🐲": "dragon_face",
|
||||||
"💸": "money_with_wings",
|
"💸": "money_with_wings",
|
||||||
"⚙️": "gear",
|
"⚙️": "gear",
|
||||||
"☹️": "frowning_face",
|
"☹️": "frowning_face",
|
||||||
|
|
|
@ -29,6 +29,7 @@ export default async function (host, patternMatch, url, lang, obj) {
|
||||||
break;
|
break;
|
||||||
case "vk":
|
case "vk":
|
||||||
r = await vk({
|
r = await vk({
|
||||||
|
url: url,
|
||||||
userId: patternMatch["userId"],
|
userId: patternMatch["userId"],
|
||||||
videoId: patternMatch["videoId"],
|
videoId: patternMatch["videoId"],
|
||||||
lang: lang, quality: obj.quality
|
lang: lang, quality: obj.quality
|
||||||
|
|
11
src/modules/pageRender/onDemand.js
Normal file
11
src/modules/pageRender/onDemand.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import changelogManager from "../changelog/changelogManager.js"
|
||||||
|
|
||||||
|
export function changelogHistory() { // blockId 0
|
||||||
|
let history = changelogManager("history");
|
||||||
|
let render = ``;
|
||||||
|
|
||||||
|
for (let i in history) {
|
||||||
|
render += `<div id="popup-desc" class="changelog-subtitle">${history[i]["title"]}</div><div id="popup-desc" class="desc-padding">${history[i]["content"]}</div>`
|
||||||
|
}
|
||||||
|
return render;
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ import { services, appName, authorInfo, version, quality, repo, donations, suppo
|
||||||
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 emoji from "../emoji.js";
|
import emoji from "../emoji.js";
|
||||||
|
import changelogManager from "../changelog/changelogManager.js";
|
||||||
|
|
||||||
let s = services;
|
let s = services;
|
||||||
let com = getCommitInfo();
|
let com = getCommitInfo();
|
||||||
|
@ -83,6 +84,8 @@ export default function(obj) {
|
||||||
text: loc(obj.lang, 'AboutSummary')
|
text: loc(obj.lang, 'AboutSummary')
|
||||||
}, {
|
}, {
|
||||||
text: `${loc(obj.lang, 'AboutSupportedServices')} ${enabledServices}.`
|
text: `${loc(obj.lang, 'AboutSupportedServices')} ${enabledServices}.`
|
||||||
|
}, {
|
||||||
|
text: `${loc(obj.lang, 'FollowTwitter')}`
|
||||||
}, {
|
}, {
|
||||||
text: backdropLink(repo, loc(obj.lang, 'LinkGitHubIssues')),
|
text: backdropLink(repo, loc(obj.lang, 'LinkGitHubIssues')),
|
||||||
classes: ["bottom-link"]
|
classes: ["bottom-link"]
|
||||||
|
@ -101,13 +104,11 @@ export default function(obj) {
|
||||||
text: `<div class="category-title">${loc(obj.lang, 'ChangelogLastMajor')}</div>`,
|
text: `<div class="category-title">${loc(obj.lang, 'ChangelogLastMajor')}</div>`,
|
||||||
raw: true
|
raw: true
|
||||||
}, {
|
}, {
|
||||||
text: loc('changelog', 'ContentTitle'),
|
text: changelogManager("title"),
|
||||||
classes: ["changelog-subtitle"],
|
classes: ["changelog-subtitle"],
|
||||||
nopadding: true
|
nopadding: true
|
||||||
}, {
|
}, {
|
||||||
text: loc('changelog', 'FollowTwitter')
|
text: changelogManager("content")
|
||||||
}, {
|
|
||||||
text: loc('changelog', 'Content')
|
|
||||||
}, {
|
}, {
|
||||||
text: `<div class="category-title">${loc(obj.lang, 'ChangelogLastCommit')}</div>`,
|
text: `<div class="category-title">${loc(obj.lang, 'ChangelogLastCommit')}</div>`,
|
||||||
raw: true
|
raw: true
|
||||||
|
@ -120,6 +121,12 @@ export default function(obj) {
|
||||||
}, {
|
}, {
|
||||||
text: backdropLink(`${repo}/commits`, loc(obj.lang, 'LinkGitHubChanges')),
|
text: backdropLink(`${repo}/commits`, loc(obj.lang, 'LinkGitHubChanges')),
|
||||||
classes: ["bottom-link"]
|
classes: ["bottom-link"]
|
||||||
|
}, {
|
||||||
|
text: `<div class="category-title">${loc(obj.lang, 'ChangelogOlder')}</div>`,
|
||||||
|
raw: true
|
||||||
|
}, {
|
||||||
|
text: `<div id="changelog-history"><button class="switch bottom-margin" onclick="loadOnDemand('changelog-history', '0')">${loc(obj.lang, "ChangelogPressToExpand")}</button></div>`,
|
||||||
|
raw: true
|
||||||
}]
|
}]
|
||||||
})
|
})
|
||||||
}, {
|
}, {
|
||||||
|
|
|
@ -6,13 +6,31 @@ import selectQuality from "../stream/selectQuality.js";
|
||||||
|
|
||||||
export default async function(obj) {
|
export default async function(obj) {
|
||||||
try {
|
try {
|
||||||
let html = await got.get(`https://vk.com/video-${obj.userId}_${obj.videoId}`, { headers: { "user-agent": genericUserAgent } });
|
let html;
|
||||||
|
let isClip = obj.url.includes("vk.com/clip");
|
||||||
|
|
||||||
|
if (isClip) {
|
||||||
|
html = await got.post("https://vk.com/al_video.php?act=show", {
|
||||||
|
headers: {
|
||||||
|
"user-agent": genericUserAgent,
|
||||||
|
"referer": `https://vk.com/clips-${obj.userId}?z=clip-${obj.userId}_${obj.videoId}`
|
||||||
|
},
|
||||||
|
body: `_nol={"0":"clips-${obj.userId}","z":"clip-${obj.userId}_${obj.videoId}"}&act=show&al=1&autoplay=0&list=&module=&video=-${obj.userId}_${obj.videoId}`
|
||||||
|
});
|
||||||
html.on('error', (err) => {
|
html.on('error', (err) => {
|
||||||
return false;
|
return { error: loc(obj.lang, 'ErrorCouldntFetch', 'vk') };
|
||||||
});
|
});
|
||||||
html = html.body;
|
html = html.body;
|
||||||
|
} else {
|
||||||
|
html = await got.get(`https://vk.com/video-${obj.userId}_${obj.videoId}`, { headers: { "user-agent": genericUserAgent } });
|
||||||
|
html.on('error', (err) => {
|
||||||
|
return { error: loc(obj.lang, 'ErrorCouldntFetch', 'vk') };
|
||||||
|
});
|
||||||
|
html = html.body;
|
||||||
|
}
|
||||||
|
|
||||||
if (html.includes(`{"lang":`)) {
|
if (html.includes(`{"lang":`)) {
|
||||||
let js = JSON.parse('{"lang":' + html.split(`{"lang":`)[1].split(']);')[0]);
|
let js = isClip ? JSON.parse('{"lang":' + html.split(`{"lang":`)[1].split(']],"static":')[0]) : JSON.parse('{"lang":' + html.split(`{"lang":`)[1].split(']);')[0]);
|
||||||
if (js["mvData"]["is_active_live"] == '0') {
|
if (js["mvData"]["is_active_live"] == '0') {
|
||||||
if (js["mvData"]["duration"] <= maxVideoDuration / 1000) {
|
if (js["mvData"]["duration"] <= maxVideoDuration / 1000) {
|
||||||
let mpd = JSON.parse(xml2json(js["player"]["params"][0]["manifest"], { compact: true, spaces: 4 }));
|
let mpd = JSON.parse(xml2json(js["player"]["params"][0]["manifest"], { compact: true, spaces: 4 }));
|
||||||
|
@ -22,13 +40,27 @@ export default async function(obj) {
|
||||||
repr = mpd["MPD"]["Period"]["AdaptationSet"][0]["Representation"];
|
repr = mpd["MPD"]["Period"]["AdaptationSet"][0]["Representation"];
|
||||||
}
|
}
|
||||||
let attr = repr[repr.length - 1]["_attributes"];
|
let attr = repr[repr.length - 1]["_attributes"];
|
||||||
let selectedQuality = `url${attr["height"]}`;
|
let selectedQuality;
|
||||||
|
let qualities = Object.keys(services.vk.quality_match);
|
||||||
|
for (let i in qualities) {
|
||||||
|
if (qualities[i] == attr["height"]) {
|
||||||
|
selectedQuality = `url${attr["height"]}`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (qualities[i] == attr["width"]) {
|
||||||
|
selectedQuality = `url${attr["width"]}`;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
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 userRepr = repr[services.vk.representation_match[userQuality]]["_attributes"];
|
||||||
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][`url${userQuality}`],
|
||||||
|
filename: `vk_${obj.userId}_${obj.videoId}_${userRepr["width"]}x${userRepr['height']}.mp4`,
|
||||||
|
audioFilename: loc(obj.lang, 'ErrorEmptyDownload')
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
return { error: loc(obj.lang, 'ErrorEmptyDownload') };
|
return { error: loc(obj.lang, 'ErrorEmptyDownload') };
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"vk": {
|
"vk": {
|
||||||
"patterns": ["video-:userId_:videoId"],
|
"alias": "vk clips, vk video",
|
||||||
|
"patterns": ["video-:userId_:videoId", "clip-:userId_:videoId", "clips-:userId?z=clip-:userId_:videoId"],
|
||||||
"quality_match": {
|
"quality_match": {
|
||||||
"2160": 7,
|
"2160": 7,
|
||||||
"1440": 6,
|
"1440": 6,
|
||||||
|
@ -27,6 +28,16 @@
|
||||||
"240": 0,
|
"240": 0,
|
||||||
"144": 4
|
"144": 4
|
||||||
},
|
},
|
||||||
|
"representation_match": {
|
||||||
|
"2160": 7,
|
||||||
|
"1440": 6,
|
||||||
|
"1080": 5,
|
||||||
|
"720": 4,
|
||||||
|
"480": 3,
|
||||||
|
"360": 2,
|
||||||
|
"240": 1,
|
||||||
|
"144": 0
|
||||||
|
},
|
||||||
"quality": {
|
"quality": {
|
||||||
"1080": "hig",
|
"1080": "hig",
|
||||||
"720": "mid",
|
"720": "mid",
|
||||||
|
@ -35,7 +46,7 @@
|
||||||
"enabled": true
|
"enabled": true
|
||||||
},
|
},
|
||||||
"youtube": {
|
"youtube": {
|
||||||
"alias": "youtube, youtube music",
|
"alias": "youtube, youtube music, youtube shorts",
|
||||||
"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"],
|
||||||
"bestAudio": "opus",
|
"bestAudio": "opus",
|
||||||
|
|
|
@ -6,43 +6,43 @@ export default function(r, host, ip, audioFormat, isAudioOnly) {
|
||||||
if (!isAudioOnly) {
|
if (!isAudioOnly) {
|
||||||
switch (host) {
|
switch (host) {
|
||||||
case "twitter":
|
case "twitter":
|
||||||
return apiJSON(1, { u: r.urls })
|
return apiJSON(1, { u: r.urls });
|
||||||
case "vk":
|
case "vk":
|
||||||
return apiJSON(2, {
|
return apiJSON(2, {
|
||||||
type: "bridge", u: r.urls, service: host, ip: ip,
|
type: "bridge", u: r.urls, service: host, ip: ip,
|
||||||
filename: r.filename, salt: process.env.streamSalt
|
filename: r.filename, salt: process.env.streamSalt
|
||||||
})
|
});
|
||||||
case "bilibili":
|
case "bilibili":
|
||||||
return apiJSON(2, {
|
return apiJSON(2, {
|
||||||
type: "render", u: r.urls, service: host, ip: ip,
|
type: "render", u: r.urls, service: host, ip: ip,
|
||||||
filename: r.filename, salt: process.env.streamSalt,
|
filename: r.filename, salt: process.env.streamSalt,
|
||||||
time: r.time
|
time: r.time
|
||||||
})
|
});
|
||||||
case "youtube":
|
case "youtube":
|
||||||
return apiJSON(2, {
|
return apiJSON(2, {
|
||||||
type: r.type, u: 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,
|
||||||
time: r.time,
|
time: r.time,
|
||||||
})
|
});
|
||||||
case "reddit":
|
case "reddit":
|
||||||
return apiJSON(r.typeId, {
|
return apiJSON(r.typeId, {
|
||||||
type: r.type, u: 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
|
||||||
})
|
});
|
||||||
case "tiktok":
|
case "tiktok":
|
||||||
return apiJSON(2, {
|
return apiJSON(2, {
|
||||||
type: "bridge", u: r.urls, service: host, ip: ip,
|
type: "bridge", u: r.urls, service: host, ip: ip,
|
||||||
filename: r.filename, salt: process.env.streamSalt
|
filename: r.filename, salt: process.env.streamSalt
|
||||||
})
|
});
|
||||||
case "douyin":
|
case "douyin":
|
||||||
return apiJSON(2, {
|
return apiJSON(2, {
|
||||||
type: "bridge", u: r.urls, service: host, ip: ip,
|
type: "bridge", u: r.urls, service: host, ip: ip,
|
||||||
filename: r.filename, salt: process.env.streamSalt
|
filename: r.filename, salt: process.env.streamSalt
|
||||||
})
|
});
|
||||||
case "tumblr":
|
case "tumblr":
|
||||||
return apiJSON(1, { u: r.urls })
|
return apiJSON(1, { u: r.urls });
|
||||||
case "vimeo":
|
case "vimeo":
|
||||||
return apiJSON(1, { u: r.urls })
|
return apiJSON(1, { u: r.urls });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (host == "reddit" && r.typeId == 1 || audioIgnore.includes(host)) return apiJSON(0, { t: r.audioFilename });
|
if (host == "reddit" && r.typeId == 1 || audioIgnore.includes(host)) return apiJSON(0, { t: r.audioFilename });
|
||||||
|
|
Loading…
Reference in a new issue