Skip to content

Commit 3c05824

Browse files
committed
Adding token extractor
1 parent 336c056 commit 3c05824

2 files changed

Lines changed: 83 additions & 7 deletions

File tree

src/helper/token.helper.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import axios from 'axios';
2+
import * as cheerio from 'cheerio';
3+
import { v1_base_url } from '../utils/base_v1.js';
4+
5+
export default async function extractToken(url) {
6+
try {
7+
const { data: html } = await axios.get(url, {
8+
headers: {
9+
Referer: `https://${v1_base_url}/`
10+
}
11+
});
12+
13+
const $ = cheerio.load(html);
14+
const results = {};
15+
16+
// 1. Meta tag
17+
const meta = $('meta[name="_gg_fb"]').attr('content');
18+
if (meta) results.meta = meta;
19+
20+
// 2. Data attribute
21+
const dpi = $('[data-dpi]').attr('data-dpi');
22+
if (dpi) results.dataDpi = dpi;
23+
24+
// 3. Nonce from empty script
25+
const nonceScript = $('script[nonce]').filter((i, el) => {
26+
return $(el).text().includes('empty nonce script');
27+
}).attr('nonce');
28+
if (nonceScript) results.nonce = nonceScript;
29+
30+
// 4. JS string assignment: window.<key> = "value";
31+
const stringAssignRegex = /window\.(\w+)\s*=\s*["']([\w-]+)["']/g;
32+
const stringMatches = [...html.matchAll(stringAssignRegex)];
33+
for (const [_, key, value] of stringMatches) {
34+
results[`window.${key}`] = value;
35+
}
36+
37+
// 5. JS object assignment: window.<key> = { ... };
38+
const objectAssignRegex = /window\.(\w+)\s*=\s*(\{[\s\S]*?\});/g;
39+
const matches = [...html.matchAll(objectAssignRegex)];
40+
for (const [_, varName, rawObj] of matches) {
41+
try {
42+
const parsedObj = eval('(' + rawObj + ')');
43+
if (parsedObj && typeof parsedObj === 'object') {
44+
const stringValues = Object.values(parsedObj).filter(val => typeof val === 'string');
45+
const concatenated = stringValues.join('');
46+
if (concatenated.length >= 20) {
47+
results[`window.${varName}`] = concatenated;
48+
}
49+
}
50+
} catch (e) {
51+
// Skip invalid object
52+
}
53+
}
54+
55+
// 6. HTML comment: <!-- _is_th:... -->
56+
$('*').contents().each(function () {
57+
if (this.type === 'comment') {
58+
const match = this.data.trim().match(/^_is_th:([\w-]+)$/);
59+
if (match) {
60+
results.commentToken = match[1].trim();
61+
}
62+
}
63+
});
64+
65+
const token = Object.values(results)[0];
66+
return token || null;
67+
} catch (err) {
68+
console.error('Error:', err.message);
69+
return null;
70+
}
71+
}

src/parsers/decryptors/decrypt_v1.decryptor.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import axios from "axios";
22
import CryptoJS from "crypto-js";
33
import { v1_base_url } from "../../utils/base_v1.js";
44
import { fallback_1, fallback_2 } from "../../utils/fallback.js";
5+
import extractToken from "../../helper/token.helper.js";
56

67
export async function decryptSources_v1(epID, id, name, type) {
78
try {
@@ -25,15 +26,13 @@ export async function decryptSources_v1(epID, id, name, type) {
2526
let rawSourceData = {};
2627

2728
try {
28-
const { data } = await axios.get(`${baseUrl}/getSources?id=${sourceId}`);
29+
const token = await extractToken(`${baseUrl}/${sourceId}?k=1&autoPlay=0&oa=0&asi=1`);
30+
const { data } = await axios.get(`${baseUrl}/getSources?id=${sourceId}&_k=${token}`);
2931
rawSourceData = data;
30-
3132
const encrypted = rawSourceData?.sources;
3233
if (!encrypted) throw new Error("Encrypted source missing");
33-
3434
const decrypted = CryptoJS.AES.decrypt(encrypted, key.trim()).toString(CryptoJS.enc.Utf8);
3535
if (!decrypted) throw new Error("Failed to decrypt source");
36-
3736
decryptedSources = JSON.parse(decrypted);
3837
} catch (decryptionError) {
3938
try {
@@ -62,9 +61,15 @@ export async function decryptSources_v1(epID, id, name, type) {
6261
);
6362

6463
decryptedSources = [{ file: fallback_data.sources.file }];
65-
rawSourceData.tracks = fallback_data.tracks ?? [];
66-
rawSourceData.intro = fallback_data.intro ?? null;
67-
rawSourceData.outro = fallback_data.outro ?? null;
64+
if (!rawSourceData.tracks || rawSourceData.tracks.length === 0) {
65+
rawSourceData.tracks = fallback_data.tracks ?? [];
66+
}
67+
if (!rawSourceData.intro) {
68+
rawSourceData.intro = fallback_data.intro ?? null;
69+
}
70+
if (!rawSourceData.outro) {
71+
rawSourceData.outro = fallback_data.outro ?? null;
72+
}
6873
} catch (fallbackError) {
6974
throw new Error("Fallback failed: " + fallbackError.message);
7075
}

0 commit comments

Comments
 (0)