Empty / scraper.ts
r.go
test
9770efd
// index.ts
import Signer from "tiktok-signature";
import axios, { AxiosResponse } from "axios";
import querystring from "querystring";
import { Browser, Page, BrowserContext } from "playwright";
import { exec } from 'child_process';
import { promisify } from 'util';
// import {DateTime} from 'luxon';
// Promisify exec for easier async/await usage
const execPromise = promisify(exec);
const TT_REQ_USER_AGENT =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.56";
const queryParams = {
WebIdLastTime: "1739192062",
aid: "1988",
app_language: "en",
app_name: "tiktok_web",
browser_language: "en-US",
browser_name: "Mozilla",
browser_online: "true",
browser_platform: "Win32",
// Notice we use the decoded version for readability.
browser_version:
"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0",
channel: "tiktok_web",
cookie_enabled: "true",
count: "35",
coverFormat: "2",
cursor: "0",
device_id: "7469772981536687624",
device_platform: "web_pc",
focus_state: "true",
from_page: "user",
history_len: "8",
is_fullscreen: "false",
is_page_visible: "true",
language: "en",
os: "windows",
priority_region: "RO",
referer: "https://www.tiktok.com/business-suite/messages?from=homepage&lang=en",
region: "RO",
root_referer: "https://www.tiktok.com/business-suite/messages?from=homepage&lang=en",
screen_height: "1080",
screen_width: "1920",
secUid:
"MS4wLjABAAAAAbt3ELTXRAMA0RVzgFjvOPEhWIKyDmY9pxPKUj5nJGIatb9xH7lTeIsU_322Sc0p",
tz_name: "Europe/Bucharest",
verifyFp: "verify_m6z21ydc_1d2kIOvr_Re3f_4Fit_AmQz_HL2g9Rui8xZp",
webcast_language: "en",
msToken:
"Gv-tA8UBoR9MrpShqSMLW5jqxKbjgqn1NJx3h2AWw3AYNZl3eKUG3855040l0RcW0Ap6uoknQRj5Iq7YuaSFeDqwAh0dubDNHQSaoYgziHNyXVdnDqIAz1WdoQx_mXEM860DcE64CXvr9nzcrBaiimxfwA==",
"X-Bogus": "DFSzswVuXEvANePAtkyrUO0EsCa-",
_signature: "_02B4Z6wo000019pWL7AAAIDCIaUS-UMYoj.aVisAAJFF2a"
};
const TT_REQ_PERM_URL =
`https://www.tiktok.com/api/post/item_list/?${new URLSearchParams(queryParams).toString()}`;
const parsedUrl = new URL(TT_REQ_PERM_URL);
const parsedQuery = querystring.parse(parsedUrl.search.slice(1));
interface SignerInterface {
init(): Promise<void>;
sign(url: string): Promise<{ "x-tt-params": string; signed_url: string }>;
navigator(): Promise<{ user_agent: string }>;
browser: Browser;
context: BrowserContext;
}
// Create a signer instance.
const signer: SignerInterface = new Signer(null, TT_REQ_USER_AGENT);
// Initialize the signer.
(async function () {
await signer.init();
})();
async function main(username: string): Promise<void> {
try {
const options = {
method: "GET",
url: "https://www.tiktok.com/@" + username,
};
const response = await axios(options);
const data: string = response.data;
const secUidMatch = data.match(/"secUid":"(.*?)"/);
const SEC_UID = secUidMatch ? secUidMatch[1] : "No secUid found";
console.log(SEC_UID)
const PARAMS = {
count: 30,
device_id: "7165118680723998211",
secUid: SEC_UID,
cursor: 0,
};
// Merge parsedQuery with PARAMS.
const mergedParams = { ...parsedQuery, ...PARAMS };
const qsObject = new URLSearchParams(mergedParams as any);
const qs = qsObject.toString();
const unsignedUrl = `https://www.tiktok.com/api/post/item_list/?${qs}`;
const signature = await signer.sign(unsignedUrl);
const navigatorData = await signer.navigator();
const { "x-tt-params": xTtParams, signed_url } = signature;
const { user_agent: userAgent } = navigatorData;
const res = await testApiReq({ userAgent, xTtParams, signed_url });
if(res.data.length == 0) {
throw new Error("No data")
}
console.log(JSON.stringify({...res.data, error: false}));
} catch (e) {
console.log(
JSON.stringify({ error: true, errorlog: String(e).trim() })
// return
);
}
}
async function twitch(fun: string): Promise<void> {
try {
if (!signer.context) {
console.log(
JSON.stringify({
error: true,
online: false,
errorlog: "Browser not initialized, please wait a moment",
})
);
return;
}
const p: Page = await signer.context.newPage();
await p.goto("https://www.twitch.tv/" + fun);
await p.waitForLoadState('networkidle')
const CheckUserStatus = await p.evaluate(() => {
try {
document.getElementsByClassName("home__lower-content")[0].remove()
const OfflineCheck = document.getElementsByClassName(
"channel-status-info channel-status-info--offline"
)[0]?.getElementsByTagName("p")[0].textContent;
const OnlineCheck = document.getElementsByClassName(
"tw-channel-status-text-indicator"
)[0];
console.log(OnlineCheck, OfflineCheck);
if (!OfflineCheck && !OnlineCheck) {
return { online: false, error: true, errorlog: "User not Found" };
} else if (OfflineCheck) {
return { online: false, error: false };
} else if (OnlineCheck) {
const getText = (selector: string): string => {
const element = document.querySelector(selector);
return element instanceof HTMLElement ? element.innerText : "";
};
const viewers = getText(
"p[data-a-target='animated-channel-viewers-count']"
);
const streamTime = getText(".live-time").split("\n")[0];
const title = getText('[data-a-target="stream-title"]');
const game = getText("a[data-a-target=stream-game-link] span");
if (!viewers && !streamTime && !title && !game) {
return { online: false, error: true };
}
return {
online: true,
viewers,
streamTime,
title,
game,
error: false,
};
}
} catch (e) {
return { online: false, error: true, errorlog: String(e) };
}
});
await p.close();
console.log(JSON.stringify(CheckUserStatus));
} catch (e) {
console.log(
JSON.stringify({ error: true, online: false, errorlog: String(e).trim() })
);
}
}
async function kick(fun: string): Promise<void> {
try {
const curlCommand = `curl_chrome116 'https://kick.com/api/v1/channels/${encodeURIComponent(fun)}'`;
const v = await execPromise(curlCommand.trim());
let k = (JSON.parse(v.stdout));
let u = k.livestream
if(!u) {
console.log(JSON.stringify({error: false, online: false}))
return
}
console.log(JSON.stringify({error: false, online: true, ...u}))
return;
} catch (e) {
console.log(
JSON.stringify({ error: true, online: false, errorlog: String(e).trim() })
);
}
}
interface TestApiReqParams {
userAgent: string;
xTtParams: string;
signed_url: string;
}
/**
* Makes an API request using axios.
*/
async function testApiReq({
userAgent,
xTtParams,
signed_url,
}: TestApiReqParams): Promise<AxiosResponse<any>> {
const options = {
method: "GET",
headers: {
"user-agent": userAgent,
"x-tt-params": xTtParams,
},
url: signed_url,
};
return axios(options);
}
// if(true) {
// kick("akibell")
// // process.exit(0)
// }
process.stdin.on("data", (data: Buffer) => {
// return;
try {
const fun = data.toString().trim().split(" ");
switch (fun[0]) {
case "twitch":
twitch(fun.slice(1).join(" "));
break;
case "kick":
kick(fun.slice(1).join(" "));
break;
default:
// if (fun.length > 1) {
main(fun.join(" "));
// }
}
} catch (e) {
console.log(JSON.stringify({ error: true, errorlog: String(e) }));
}
});