Skip to content

Commit 9652cfe

Browse files
committed
hack snaptik + WIP tiktok bulk
1 parent 78c2f52 commit 9652cfe

File tree

5 files changed

+208
-31
lines changed

5 files changed

+208
-31
lines changed

scripts/content-scripts/scripts/ufs_global_webpage_context.js

Lines changed: 144 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,21 @@ const UsefulScriptGlobalPageContext = {
181181
},
182182
},
183183
Utils: {
184+
// https://stackoverflow.com/a/38552302/11898496
185+
parseJwt(token) {
186+
var base64Url = token.split(".")[1];
187+
var base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
188+
var jsonPayload = decodeURIComponent(
189+
window
190+
.atob(base64)
191+
.split("")
192+
.map(function (c) {
193+
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
194+
})
195+
.join("")
196+
);
197+
return JSON.parse(jsonPayload);
198+
},
184199
copyToClipboard(text) {
185200
// Check if Clipboard API is supported
186201
if (!navigator.clipboard) {
@@ -924,23 +939,149 @@ const UsefulScriptGlobalPageContext = {
924939
Tiktok: {
925940
downloadTiktokVideoFromId: async function (videoId) {
926941
for (let api of [
942+
"https://api22-normal-c-useast2a.tiktokv.com/aweme/v1/feed/?aweme_id=",
943+
"https://api16-normal-useast5.us.tiktokv.com/aweme/v1/feed/?aweme_id=",
927944
"https://api16-normal-c-useast1a.tiktokv.com/aweme/v1/feed/?aweme_id=",
928945
"https://api2.musical.ly/aweme/v1/feed/?aweme_id=",
929946
]) {
930947
try {
931-
let data = await fetch(api + videoId);
948+
const ts = Math.round(Date.now() / 1000);
949+
const parameters = {
950+
aweme_id: videoId,
951+
// version_name: appVersion,
952+
// version_code: manifestAppVersion,
953+
// build_number: appVersion,
954+
// manifest_version_code: manifestAppVersion,
955+
// update_version_code: manifestAppVersion,
956+
// openudid: UTIL.ranGen("0123456789abcdef", 16),
957+
// uuid: UTIL.ranGen("0123456789", 16),
958+
_rticket: ts * 1000,
959+
ts: ts,
960+
device_brand: "Google",
961+
device_type: "Pixel 4",
962+
device_platform: "android",
963+
resolution: "1080*1920",
964+
dpi: 420,
965+
os_version: "10",
966+
os_api: "29",
967+
carrier_region: "US",
968+
sys_region: "US",
969+
region: "US",
970+
app_name: "trill",
971+
app_language: "en",
972+
language: "en",
973+
timezone_name: "America/New_York",
974+
timezone_offset: "-14400",
975+
channel: "googleplay",
976+
ac: "wifi",
977+
mcc_mnc: "310260",
978+
is_my_cn: 0,
979+
aid: 1180,
980+
ssmix: "a",
981+
as: "a1qwert123",
982+
cp: "cbfhckdckkde1",
983+
};
984+
const params = Object.keys(parameters)
985+
.map((key) => `&${key}=${parameters[key]}`)
986+
.join("");
987+
let data = await fetch(api + videoId + "&" + params);
932988
let json = await data.json();
933989
console.log(json);
934990
let item = json.aweme_list.find((a) => a.aweme_id == videoId);
935991
if (!item) throw Error("Không tìm thấy video");
936992
let url =
937993
item?.video?.play_addr?.url_list?.[0] ||
938994
item?.video?.download_addr?.url_list?.[0];
939-
return url;
995+
if (url) return url;
940996
} catch (e) {
941-
console.error(e);
997+
console.log("ERROR: " + e);
942998
}
943999
}
1000+
return null;
1001+
},
1002+
CACHE: {
1003+
snapTikToken: null,
1004+
},
1005+
downloadTiktokVideoFromUrl: async function (url) {
1006+
try {
1007+
let token = UsefulScriptGlobalPageContext.Tiktok.CACHE.snapTikToken;
1008+
if (!token) {
1009+
let token = await UsefulScriptGlobalPageContext.SnapTik.getToken();
1010+
if (!token) throw Error("Không tìm thấy token snaptik");
1011+
UsefulScriptGlobalPageContext.Tiktok.CACHE.snapTikToken = token;
1012+
}
1013+
1014+
let data = new FormData();
1015+
data.append("url", url);
1016+
data.append("token", token);
1017+
1018+
let res = await fetch("https://snaptik.app/abc2.php", {
1019+
method: "POST",
1020+
body: data,
1021+
});
1022+
let text = await res.text();
1023+
let result = UsefulScriptGlobalPageContext.SnapTik.decode(text);
1024+
return result;
1025+
} catch (e) {
1026+
console.log("ERROR: " + e);
1027+
}
1028+
},
1029+
},
1030+
SnapTik: {
1031+
getToken: async () => {
1032+
let res = await fetch("https://snaptik.app/");
1033+
let text = await res.text();
1034+
let token = text.match(/name="token" value="(.+?)"/)?.[1];
1035+
return token;
1036+
},
1037+
decode: (encoded) => {
1038+
function b(d, e, f) {
1039+
var g =
1040+
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/".split(
1041+
""
1042+
);
1043+
var h = g.slice(0, e);
1044+
var i = g.slice(0, f);
1045+
var j = d
1046+
.split("")
1047+
.reverse()
1048+
.reduce(function (a, b, c) {
1049+
if (h.indexOf(b) !== -1)
1050+
return (a += h.indexOf(b) * Math.pow(e, c));
1051+
}, 0);
1052+
var k = "";
1053+
while (j > 0) {
1054+
k = i[j % f] + k;
1055+
j = (j - (j % f)) / f;
1056+
}
1057+
return k || 0;
1058+
}
1059+
function c(h, u, n, t, e, r) {
1060+
r = "";
1061+
for (var i = 0, len = h.length; i < len; i++) {
1062+
var s = "";
1063+
while (h[i] !== n[e]) {
1064+
s += h[i];
1065+
i++;
1066+
}
1067+
for (var j = 0; j < n.length; j++)
1068+
s = s.replace(new RegExp(n[j], "g"), j);
1069+
r += String.fromCharCode(b(s, e, 10) - t);
1070+
}
1071+
return decodeURIComponent(escape(r));
1072+
}
1073+
1074+
let params = encoded.match(/}\((.*?)\)\)/)?.[1];
1075+
params = params.split(",").map((_) => {
1076+
if (!isNaN(Number(_))) return Number(_);
1077+
if (_.startsWith('"')) return _.slice(1, -1);
1078+
return _;
1079+
});
1080+
1081+
let result = c(...params);
1082+
let jwt = result.match(/d\?token=(.*?)\&dl=1/)?.[1];
1083+
let payload = UsefulScriptGlobalPageContext.Utils.parseJwt(jwt);
1084+
return payload?.url;
9441085
},
9451086
},
9461087
};

scripts/helpers/utils.js

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -355,22 +355,6 @@ export const JSONUtils = {
355355
},
356356
};
357357

358-
// https://stackoverflow.com/a/38552302/11898496
359-
export function parseJwt(token) {
360-
var base64Url = token.split(".")[1];
361-
var base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
362-
var jsonPayload = decodeURIComponent(
363-
window
364-
.atob(base64)
365-
.split("")
366-
.map(function (c) {
367-
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
368-
})
369-
.join("")
370-
);
371-
return JSON.parse(jsonPayload);
372-
}
373-
374358
//#endregion
375359

376360
// #region Snap Utils (snaptik, snapinsta)
@@ -408,9 +392,9 @@ export function popupCenter({ url, title, w, h }) {
408392
title,
409393
`
410394
scrollbars=yes,
411-
width=${w},
412-
height=${h},
413-
top=${top},
395+
width=${w},
396+
height=${h},
397+
top=${top},
414398
left=${left}
415399
`
416400
);

scripts/net-request-rules/rules.json

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,18 @@
3232
{
3333
"header": "referer",
3434
"operation": "set",
35-
"value": "https://www.snaptikvideo.com/"
35+
"value": "https://snaptik.app"
3636
},
3737
{
3838
"header": "origin",
3939
"operation": "set",
40-
"value": "https://www.snaptikvideo.com"
40+
"value": "https://snaptik.app"
4141
}
4242
]
4343
},
4444
"condition": {
4545
"domain": "extension://*",
46-
"urlFilter": "https://api.snaptikvideo.com/st-tik/tiktok/dl",
46+
"urlFilter": "https://snaptik.app/abc2.php",
4747
"resourceTypes": ["xmlhttprequest"]
4848
}
4949
},
@@ -142,5 +142,46 @@
142142
"urlFilter": "https://*.tiktok.com/*",
143143
"resourceTypes": ["xmlhttprequest"]
144144
}
145+
},
146+
{
147+
"id": 7,
148+
"priority": 1,
149+
"action": {
150+
"type": "modifyHeaders",
151+
"requestHeaders": [
152+
{
153+
"header": "User-Agent",
154+
"operation": "set",
155+
"value": "com.ss.android.ugc.trill/2613 (Linux; U; Android 10; en_US; Pixel 4; Build/QQ3A.200805.001; Cronet/58.0.2991.0)"
156+
},
157+
{
158+
"header": "Sec-Fetch-Dest",
159+
"operation": "set",
160+
"value": "document"
161+
},
162+
{
163+
"header": "Sec-Fetch-Mode",
164+
"operation": "set",
165+
"value": "navigate"
166+
},
167+
{
168+
"header": "Sec-Fetch-Site",
169+
"operation": "set",
170+
"value": "cross-site"
171+
},
172+
{
173+
"header": "referer",
174+
"operation": "remove"
175+
},
176+
{
177+
"header": "origin",
178+
"operation": "remove"
179+
}
180+
]
181+
},
182+
"condition": {
183+
"urlFilter": "*://api22-normal-c-useast2a.tiktokv.com/*",
184+
"resourceTypes": ["main_frame", "xmlhttprequest"]
185+
}
145186
}
146187
]

scripts/tiktok_batchDownload.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,21 +142,31 @@ export default {
142142

143143
async function getLinkVideos(videoUrls) {
144144
if (!videoUrls.length) return;
145-
const ids = videoUrls.map((url) => url.split("/").at(-1));
146-
const queue = [...ids];
145+
const getId = (url) => url.split("/").at(-1);
146+
const queue = [...videoUrls];
147147
const links = [];
148148
downloadBtn.disabled = true;
149149

150150
while (queue.length) {
151-
let progress = `[${ids.length - queue.length + 1}/${ids.length}]`;
151+
let progress = `[${videoUrls.length - queue.length + 1}/${
152+
videoUrls.length
153+
}]`;
152154
try {
153155
console.log(`${progress} Đang tìm link cho video ${queue[0]}`);
154156
progressDiv.innerText = `${progress} Đang tìm link video ${queue[0]}...`;
155157
downloadBtn.innerText = `Đang get link ${progress}...`;
156-
const link =
158+
let link =
157159
await UsefulScriptGlobalPageContext.Tiktok.downloadTiktokVideoFromId(
158-
queue[0]
160+
getId(queue[0])
159161
);
162+
163+
if (!link) {
164+
link =
165+
await UsefulScriptGlobalPageContext.Tiktok.downloadTiktokVideoFromUrl(
166+
queue[0]
167+
);
168+
}
169+
160170
if (link) {
161171
resultTxt.hidden = false;
162172
resultTxt.value += link + "\n";

scripts/tiktok_downloadWatchingVideo.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ export default {
4747

4848
if (!link) alert("Không tìm được link video");
4949
else {
50-
UsefulScriptGlobalPageContext.Utils.downloadBlobUrl(
50+
setLoadingText("Đang tải video...");
51+
await UsefulScriptGlobalPageContext.Utils.downloadBlobUrl(
5152
link,
5253
"tiktok_video.mp4"
5354
);

0 commit comments

Comments
 (0)