tiktok is back!

- added support for tiktok (images won't work, they're only accessible through the app)
- hopefully main input bar is now not rounded on ios, i fucking hate apple
- if service is not supported, a correlating error will appear, not generic one
- removed duplicates from config that are present in package json already
- tiny bit of clean up
This commit is contained in:
wukko
2022-07-28 22:03:17 +06:00
parent a4a9af6120
commit 1b4872c1de
12 changed files with 86 additions and 41 deletions

View File

@@ -21,11 +21,12 @@ export async function getJSON(originalURL, ip, lang, format, quality) {
if (host && host.length < 20 && host in patterns && patterns[host]["enabled"]) {
for (let i in patterns[host]["patterns"]) {
patternMatch = new UrlPattern(patterns[host]["patterns"][i]).match(cleanURL(url, host).split(".com/")[1]);
if (patternMatch) break;
}
if (patternMatch) {
return await match(host, patternMatch, url, ip, lang, format, quality);
} else throw Error()
} else throw Error()
} return apiJSON(0, { t: errorUnsupported(lang) } )
} return apiJSON(0, { t: errorUnsupported(lang) } )
} else {
return apiJSON(0, { t: errorUnsupported(lang) } )
}

View File

@@ -1,14 +1,15 @@
import loadJson from "./sub/loadJSON.js";
const config = loadJson("./src/config.json");
const packageJson = loadJson("./package.json");
export const
services = loadJson("./src/modules/services/_config.json"),
appName = config.appName,
version = config.version,
appName = packageJson.name,
version = packageJson.version,
streamLifespan = config.streamLifespan,
maxVideoDuration = config.maxVideoDuration,
genericUserAgent = config.genericUserAgent,
repo = config.repo,
repo = packageJson["bugs"]["url"].replace('/issues', ''),
authorInfo = config.authorInfo,
supportedLanguages = config.supportedLanguages,
quality = config.quality,

View File

@@ -6,6 +6,7 @@ import reddit from "./services/reddit.js";
import twitter from "./services/twitter.js";
import youtube from "./services/youtube.js";
import vk from "./services/vk.js";
import tiktok from "./services/tiktok.js";
export default async function (host, patternMatch, url, ip, lang, format, quality) {
try {
@@ -19,13 +20,16 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit
return (!r.error) ? apiJSON(1, { u: r.split('?')[0] }) : apiJSON(0, { t: r.error })
} else throw Error()
case "vk":
if (patternMatch["userId"] && patternMatch["videoId"] && patternMatch["userId"].length <= 10 && patternMatch["videoId"].length == 9) {
if (patternMatch["userId"] && patternMatch["videoId"] &&
patternMatch["userId"].length <= 10 && patternMatch["videoId"].length == 9) {
let r = await vk({
userId: patternMatch["userId"],
videoId: patternMatch["videoId"],
lang: lang, quality: quality
});
return (!r.error) ? apiJSON(2, { type: "bridge", lang: lang, u: 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", lang: lang, 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) {
@@ -69,7 +73,8 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit
}) : apiJSON(0, { t: r.error });
} else throw Error()
case "reddit":
if (patternMatch["sub"] && patternMatch["id"] && patternMatch["title"] && patternMatch["sub"].length <= 22 && patternMatch["id"].length <= 10 && patternMatch["title"].length <= 96) {
if (patternMatch["sub"] && patternMatch["id"] && patternMatch["title"] &&
patternMatch["sub"].length <= 22 && patternMatch["id"].length <= 10 && patternMatch["title"].length <= 96) {
let r = await reddit({
sub: patternMatch["sub"],
id: patternMatch["id"],
@@ -81,6 +86,19 @@ export default async function (host, patternMatch, url, ip, lang, format, qualit
filename: r.filename, salt: process.env.streamSalt
}) : apiJSON(0, { t: r.error });
} else throw Error()
case "tiktok":
if ((patternMatch["user"] && patternMatch["type"] == "video" && patternMatch["postId"] && patternMatch["postId"].length <= 21) ||
(patternMatch["id"] && patternMatch["id"].length <= 13)) {
let r = await tiktok({
postId: patternMatch["postId"],
id: patternMatch["id"], lang: lang,
});
return (!r.error) ? apiJSON(2, {
type: "bridge", u: r.urls, lang: lang,
service: host, ip: ip,
filename: r.filename, salt: process.env.streamSalt
}) : apiJSON(0, { t: r.error });
} else throw Error()
default:
return apiJSON(0, { t: errorUnsupported(lang) })
}

View File

@@ -163,7 +163,7 @@ export default function(obj) {
<div id="theme-switcher" class="switch-container small-padding">
<div class="subtitle">${loc(obj.lang, 'DownloadPopupDescription')}</div>
<div class="switches">
<a id="pd-download" class="switch full space-right" target="_blank"">${loc(obj.lang, 'Download')}</a>
<a id="pd-download" class="switch full space-right" target="_blank" href="/">${loc(obj.lang, 'Download')}</a>
<div id="pd-copy" class="switch full">${loc(obj.lang, 'CopyURL')}</div>
</div>
</div>

View File

@@ -66,7 +66,7 @@
"enabled": false
},
"tiktok": {
"patterns": [":pageid/:type/:postid", ":id"],
"enabled": false
"patterns": [":user/:type/:postId", ":id"],
"enabled": true
}
}

View File

@@ -0,0 +1,30 @@
import got from "got";
import loc from "../../localization/manager.js";
import { genericUserAgent} from "../config.js";
import { unicodeDecode } from "../sub/utils.js";
export default async function(obj) {
try {
if (!obj.postId) {
let html = await got.get(`https://vt.tiktok.com/${obj.id}`, { headers: { "user-agent": genericUserAgent } });
html.on('error', (err) => {
return { error: loc(obj.lang, 'ErrorCantConnectToServiceAPI', 'tiktok') };
});
html = html.body
obj.postId = html.split('video/')[1].split('?')[0]
}
let url = `https://tiktok.com/@video/video/${obj.postId}`
let html = await got.get(url, { headers: { "user-agent": genericUserAgent } });
html.on('error', (err) => {
return { error: loc(obj.lang, 'ErrorCantConnectToServiceAPI', 'tiktok') };
});
html = html.body;
if (html.includes(',"preloadList":[{"url":"')) {
return { urls: unicodeDecode(html.split(',"preloadList":[{"url":"')[1].split('","id":"')[0].trim()), filename: `tiktok_${obj.postId}.mp4` };
} else {
return { error: loc(obj.lang, 'ErrorEmptyDownload') };
}
} catch (e) {
return { error: loc(obj.lang, 'ErrorBadFetch') };
}
}

View File

@@ -16,10 +16,10 @@ export async function streamDefault(streamInfo, res) {
isStream: true
});
stream.pipe(res).on('error', (err) => {
throw Error("File stream pipe error.");
internalError(res);
});
stream.on('error', (err) => {
throw Error("File stream error.")
internalError(res);
});
} catch (e) {
internalError(res);

View File

@@ -35,7 +35,7 @@ export function msToTime(d) {
return r;
}
export function cleanURL(url, host) {
url = url.replace('}', '').replace('{', '').replace(')', '').replace('(', '').replace(' ', '');
url = url.replace('}', '').replace('{', '').replace(')', '').replace('(', '').replace(' ', '').replace('@', '');
if (url.includes('youtube.com/shorts/')) {
url = url.split('?')[0].replace('shorts/', 'watch?v=');
}
@@ -51,4 +51,9 @@ export function cleanURL(url, host) {
}
export function languageCode(req) {
return req.header('Accept-Language') ? req.header('Accept-Language').slice(0, 2) : "en"
}
export function unicodeDecode(str) {
return str.replace(/\\u[\dA-F]{4}/gi, (unicode) => {
return String.fromCharCode(parseInt(unicode.replace(/\\u/g, ""), 16));
});
}