Update index.js
Browse files
index.js
CHANGED
|
@@ -3,18 +3,18 @@ const axios = require('axios');
|
|
| 3 |
const dns = require('dns');
|
| 4 |
const http = require('http');
|
| 5 |
|
| 6 |
-
// ---
|
| 7 |
const TELEGRAM_TOKEN = process.env.TELEGRAM_TOKEN;
|
| 8 |
const TELEGRAM_CHAT_ID = process.env.TELEGRAM_CHAT_ID;
|
| 9 |
const SESSION_ID = process.env.SESSION_ID;
|
| 10 |
-
const FIXED_COUNTRY = "
|
| 11 |
|
| 12 |
-
//
|
| 13 |
const ACCOUNTS_TO_WATCH = ['ah_md107', '3z1199'];
|
| 14 |
|
| 15 |
dns.setServers(['8.8.8.8']);
|
| 16 |
|
| 17 |
-
// ---
|
| 18 |
function formatK(num) {
|
| 19 |
if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M';
|
| 20 |
if (num >= 1000) return (num / 1000).toFixed(1) + 'K';
|
|
@@ -22,15 +22,14 @@ function formatK(num) {
|
|
| 22 |
}
|
| 23 |
|
| 24 |
function getBaghdadTime() {
|
| 25 |
-
return new Intl.DateTimeFormat('
|
| 26 |
}
|
| 27 |
|
| 28 |
-
// ุฏุงูุฉ ุชุญููู ุงูู
ุฏู ุฅูู ุณุงุนุงุช ูุฏูุงุฆู
|
| 29 |
function formatDuration(totalMinutes) {
|
| 30 |
-
if (totalMinutes < 60) return `${totalMinutes}
|
| 31 |
const hours = Math.floor(totalMinutes / 60);
|
| 32 |
const minutes = totalMinutes % 60;
|
| 33 |
-
return minutes > 0? `${hours}
|
| 34 |
}
|
| 35 |
|
| 36 |
async function sendToTelegram(text, photoUrl = null, targetLink = null) {
|
|
@@ -49,19 +48,19 @@ async function sendToTelegram(text, photoUrl = null, targetLink = null) {
|
|
| 49 |
await axios.post(`${baseUrl}/sendMessage`, payload, { headers: { 'Host': 'api.telegram.org' } });
|
| 50 |
}
|
| 51 |
} catch (e) {
|
| 52 |
-
console.log("
|
| 53 |
}
|
| 54 |
}
|
| 55 |
|
| 56 |
async function startRadar(username) {
|
| 57 |
let user = username.trim();
|
| 58 |
-
const primaryOptions = { processInitialData: true, enableWebsocketUpgrade: true, sessionId: SESSION_ID, clientParams: { "app_language": "
|
| 59 |
-
const fallbackOptions = { processInitialData: true, enableWebsocketUpgrade: true, sessionId: SESSION_ID, clientParams: { "app_language": "
|
| 60 |
|
| 61 |
let connection = new WebcastPushConnection(user, primaryOptions);
|
| 62 |
let highestHundred = 0, maxViewers = 0, totalLikes = 0, totalShares = 0;
|
| 63 |
let giftersMap = {}, commentersMap = {}, adminsSeen = new Set();
|
| 64 |
-
let bestGift = { name: "
|
| 65 |
let startTime = null;
|
| 66 |
let fastCommentCounter = {};
|
| 67 |
let alertedComments = new Set();
|
|
@@ -70,13 +69,13 @@ async function startRadar(username) {
|
|
| 70 |
const state = await connection.connect();
|
| 71 |
handleConnectionSuccess(state);
|
| 72 |
} catch (err) {
|
| 73 |
-
console.log(`
|
| 74 |
connection = new WebcastPushConnection(user, fallbackOptions);
|
| 75 |
try {
|
| 76 |
const state = await connection.connect();
|
| 77 |
handleConnectionSuccess(state);
|
| 78 |
} catch (fallbackErr) {
|
| 79 |
-
console.log(`
|
| 80 |
setTimeout(() => startRadar(user), 60000);
|
| 81 |
return;
|
| 82 |
}
|
|
@@ -85,37 +84,43 @@ async function startRadar(username) {
|
|
| 85 |
function handleConnectionSuccess(state) {
|
| 86 |
startTime = new Date();
|
| 87 |
let statusEmoji = state.roomInfo.live_room_mode === 4? "๐ค" : "๐ด";
|
| 88 |
-
let statusText = state.roomInfo.live_room_mode === 4? "
|
| 89 |
let liveLink = `https://www.tiktok.com/@${user}/live`;
|
| 90 |
if (state.roomInfo.live_room_mode === 4 && state.roomInfo.owner) {
|
| 91 |
liveLink = `https://www.tiktok.com/@${state.roomInfo.owner.uniqueId}/live`;
|
| 92 |
}
|
| 93 |
-
let msg = `${statusEmoji} <b>${statusText}</b>\n` +
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
sendToTelegram(msg);
|
| 95 |
}
|
| 96 |
|
| 97 |
-
//
|
| 98 |
connection.on('like', (data) => { totalLikes = data.totalLikeCount; });
|
| 99 |
connection.on('social', (data) => { if (data.displayType && data.displayType.includes('share')) totalShares++; });
|
| 100 |
|
| 101 |
-
//
|
| 102 |
const handleBox = (data, type) => {
|
| 103 |
let coins = data.coins |
|
| 104 |
|
| 105 |
| data.diamonds |
|
| 106 |
| data.amount |
|
| 107 |
-
| "
|
| 108 |
let sender = data.nickname |
|
| 109 |
|
| 110 |
| (data.user && data.user.nickname) |
|
| 111 |
-
| '
|
| 112 |
-
sendToTelegram(`๐ฐ <b>
|
| 113 |
};
|
| 114 |
|
| 115 |
-
connection.on('treasureBox', (data) => handleBox(data, "
|
| 116 |
-
connection.on('luckyBox', (data) => handleBox(data, "
|
| 117 |
-
connection.on('chest', (data) => handleBox(data, "
|
| 118 |
-
connection.on('envelope', (data) => handleBox(data, "
|
| 119 |
|
| 120 |
connection.on('chat', (data) => {
|
| 121 |
let text = data.comment.trim();
|
|
@@ -128,7 +133,7 @@ async function startRadar(username) {
|
|
| 128 |
fastCommentCounter[text] = fastCommentCounter[text].filter(ts => now - ts < 60000);
|
| 129 |
if (fastCommentCounter[text].length >= 100 &&!alertedComments.has(text)) {
|
| 130 |
alertedComments.add(text);
|
| 131 |
-
sendToTelegram(`โ ๏ธ <b>
|
| 132 |
setTimeout(() => alertedComments.delete(text), 300000);
|
| 133 |
}
|
| 134 |
}
|
|
@@ -141,16 +146,16 @@ async function startRadar(username) {
|
|
| 141 |
if (currentHundred >= 100 && currentHundred > highestHundred) {
|
| 142 |
highestHundred = currentHundred;
|
| 143 |
let liveLink = `https://www.tiktok.com/@${user}/live`;
|
| 144 |
-
sendToTelegram(`๐ <b>
|
| 145 |
}
|
| 146 |
});
|
| 147 |
|
| 148 |
connection.on('member', (data) => {
|
| 149 |
if (data.isModerator &&!adminsSeen.has(data.uniqueId)) {
|
| 150 |
adminsSeen.add(data.uniqueId);
|
| 151 |
-
sendToTelegram(`๐ก๏ธ <b>
|
| 152 |
}
|
| 153 |
-
if (data.userLevel >= 30) sendToTelegram(`๐ <b>
|
| 154 |
});
|
| 155 |
|
| 156 |
connection.on('gift', (data) => {
|
|
@@ -164,22 +169,22 @@ async function startRadar(username) {
|
|
| 164 |
connection.on('disconnected', () => {
|
| 165 |
const diffMs = startTime? (new Date() - startTime) : 0;
|
| 166 |
const totalMinutes = Math.floor(diffMs / 60000);
|
| 167 |
-
const durationStr = startTime? formatDuration(totalMinutes) : "
|
| 168 |
|
| 169 |
let sortedGifters = Object.values(giftersMap).sort((a, b) => b.coins - a.coins).slice(0, 3);
|
| 170 |
let sortedCommenters = Object.values(commentersMap).sort((a, b) => b.count - a.count).slice(0, 5);
|
| 171 |
-
let endMsg = `๐ <b>
|
| 172 |
|
| 173 |
sortedGifters.forEach((g, i) => {
|
| 174 |
endMsg += `${i === 0? '๐ฅ' : i === 1? '๐ฅ' : '๐ฅ'} <code>${g.name}</code> : <b>${formatK(g.coins)}</b>\n`;
|
| 175 |
});
|
| 176 |
|
| 177 |
-
endMsg += `\n๐ฌ <b>
|
| 178 |
sortedCommenters.forEach((c, i) => {
|
| 179 |
endMsg += `${i+1}. <code>${c.name}</code> (${c.count})\n`;
|
| 180 |
});
|
| 181 |
|
| 182 |
-
if (bestGift.cost > 0) endMsg += `\n๐ <b>
|
| 183 |
sendToTelegram(endMsg, bestGift.icon |
|
| 184 |
|
| 185 |
| null, `https://www.tiktok.com/@${user}/live`);
|
|
|
|
| 3 |
const dns = require('dns');
|
| 4 |
const http = require('http');
|
| 5 |
|
| 6 |
+
// --- System Configuration ---
|
| 7 |
const TELEGRAM_TOKEN = process.env.TELEGRAM_TOKEN;
|
| 8 |
const TELEGRAM_CHAT_ID = process.env.TELEGRAM_CHAT_ID;
|
| 9 |
const SESSION_ID = process.env.SESSION_ID;
|
| 10 |
+
const FIXED_COUNTRY = "Iraq";
|
| 11 |
|
| 12 |
+
// Manual accounts list for monitoring
|
| 13 |
const ACCOUNTS_TO_WATCH = ['ah_md107', '3z1199'];
|
| 14 |
|
| 15 |
dns.setServers(['8.8.8.8']);
|
| 16 |
|
| 17 |
+
// --- Formatting Functions ---
|
| 18 |
function formatK(num) {
|
| 19 |
if (num >= 1000000) return (num / 1000000).toFixed(1) + 'M';
|
| 20 |
if (num >= 1000) return (num / 1000).toFixed(1) + 'K';
|
|
|
|
| 22 |
}
|
| 23 |
|
| 24 |
function getBaghdadTime() {
|
| 25 |
+
return new Intl.DateTimeFormat('en-US', { timeZone: 'Asia/Baghdad', dateStyle: 'medium', timeStyle: 'medium', hour12: true }).format(new Date());
|
| 26 |
}
|
| 27 |
|
|
|
|
| 28 |
function formatDuration(totalMinutes) {
|
| 29 |
+
if (totalMinutes < 60) return `${totalMinutes} Minutes`;
|
| 30 |
const hours = Math.floor(totalMinutes / 60);
|
| 31 |
const minutes = totalMinutes % 60;
|
| 32 |
+
return minutes > 0? `${hours} Hours and ${minutes} Minutes` : `${hours} Hours`;
|
| 33 |
}
|
| 34 |
|
| 35 |
async function sendToTelegram(text, photoUrl = null, targetLink = null) {
|
|
|
|
| 48 |
await axios.post(`${baseUrl}/sendMessage`, payload, { headers: { 'Host': 'api.telegram.org' } });
|
| 49 |
}
|
| 50 |
} catch (e) {
|
| 51 |
+
console.log("Telegram Error");
|
| 52 |
}
|
| 53 |
}
|
| 54 |
|
| 55 |
async function startRadar(username) {
|
| 56 |
let user = username.trim();
|
| 57 |
+
const primaryOptions = { processInitialData: true, enableWebsocketUpgrade: true, sessionId: SESSION_ID, clientParams: { "app_language": "en-US", "device_platform": "web", "tt_target_idc": "useast1a" } };
|
| 58 |
+
const fallbackOptions = { processInitialData: true, enableWebsocketUpgrade: true, sessionId: SESSION_ID, clientParams: { "app_language": "en-US", "device_platform": "web" } };
|
| 59 |
|
| 60 |
let connection = new WebcastPushConnection(user, primaryOptions);
|
| 61 |
let highestHundred = 0, maxViewers = 0, totalLikes = 0, totalShares = 0;
|
| 62 |
let giftersMap = {}, commentersMap = {}, adminsSeen = new Set();
|
| 63 |
+
let bestGift = { name: "None", cost: 0, sender: "", icon: "" };
|
| 64 |
let startTime = null;
|
| 65 |
let fastCommentCounter = {};
|
| 66 |
let alertedComments = new Set();
|
|
|
|
| 69 |
const state = await connection.connect();
|
| 70 |
handleConnectionSuccess(state);
|
| 71 |
} catch (err) {
|
| 72 |
+
console.log(`Connection failed for ${user}, trying fallback...`);
|
| 73 |
connection = new WebcastPushConnection(user, fallbackOptions);
|
| 74 |
try {
|
| 75 |
const state = await connection.connect();
|
| 76 |
handleConnectionSuccess(state);
|
| 77 |
} catch (fallbackErr) {
|
| 78 |
+
console.log(`Fatal: All connections failed for ${user}`);
|
| 79 |
setTimeout(() => startRadar(user), 60000);
|
| 80 |
return;
|
| 81 |
}
|
|
|
|
| 84 |
function handleConnectionSuccess(state) {
|
| 85 |
startTime = new Date();
|
| 86 |
let statusEmoji = state.roomInfo.live_room_mode === 4? "๐ค" : "๐ด";
|
| 87 |
+
let statusText = state.roomInfo.live_room_mode === 4? "Alert: Guest is Live!" : "Live Stream Started";
|
| 88 |
let liveLink = `https://www.tiktok.com/@${user}/live`;
|
| 89 |
if (state.roomInfo.live_room_mode === 4 && state.roomInfo.owner) {
|
| 90 |
liveLink = `https://www.tiktok.com/@${state.roomInfo.owner.uniqueId}/live`;
|
| 91 |
}
|
| 92 |
+
let msg = `${statusEmoji} <b>${statusText}</b>\n` +
|
| 93 |
+
`โโโโโโโโโโโโโโโโโ\n` +
|
| 94 |
+
`๐ค <b>Account:</b> <code>${user}</code>\n` +
|
| 95 |
+
`๐ <b>Country:</b> ${FIXED_COUNTRY}\n` +
|
| 96 |
+
`๐
<b>Time:</b> <code>${getBaghdadTime()}</code>\n` +
|
| 97 |
+
`โโโโโโโโโโโโโโโโโ\n` +
|
| 98 |
+
`๐ <b>Link:</b> <a href="${liveLink}">${liveLink}</a>`;
|
| 99 |
sendToTelegram(msg);
|
| 100 |
}
|
| 101 |
|
| 102 |
+
// Track Likes and Shares (2026 Update)
|
| 103 |
connection.on('like', (data) => { totalLikes = data.totalLikeCount; });
|
| 104 |
connection.on('social', (data) => { if (data.displayType && data.displayType.includes('share')) totalShares++; });
|
| 105 |
|
| 106 |
+
// Handle All Boxes and Interaction Bags
|
| 107 |
const handleBox = (data, type) => {
|
| 108 |
let coins = data.coins |
|
| 109 |
|
| 110 |
| data.diamonds |
|
| 111 |
| data.amount |
|
| 112 |
+
| "N/A";
|
| 113 |
let sender = data.nickname |
|
| 114 |
|
| 115 |
| (data.user && data.user.nickname) |
|
| 116 |
+
| 'Unknown';
|
| 117 |
+
sendToTelegram(`๐ฐ <b>${type} Alert!</b>\n๐ค Live: @${user}\n๐ From: <b>${sender}</b>\n๐ Value: <b>${coins} Coins</b>`);
|
| 118 |
};
|
| 119 |
|
| 120 |
+
connection.on('treasureBox', (data) => handleBox(data, "Treasure Bag"));
|
| 121 |
+
connection.on('luckyBox', (data) => handleBox(data, "Lucky Box"));
|
| 122 |
+
connection.on('chest', (data) => handleBox(data, "Interaction Bag"));
|
| 123 |
+
connection.on('envelope', (data) => handleBox(data, "Interaction Bag"));
|
| 124 |
|
| 125 |
connection.on('chat', (data) => {
|
| 126 |
let text = data.comment.trim();
|
|
|
|
| 133 |
fastCommentCounter[text] = fastCommentCounter[text].filter(ts => now - ts < 60000);
|
| 134 |
if (fastCommentCounter[text].length >= 100 &&!alertedComments.has(text)) {
|
| 135 |
alertedComments.add(text);
|
| 136 |
+
sendToTelegram(`โ ๏ธ <b>Spam Alert @${user}!</b>\n๐ฌ "<code>${text}</code>"\n๐ฅ Repeated 100 times in 1 min!`);
|
| 137 |
setTimeout(() => alertedComments.delete(text), 300000);
|
| 138 |
}
|
| 139 |
}
|
|
|
|
| 146 |
if (currentHundred >= 100 && currentHundred > highestHundred) {
|
| 147 |
highestHundred = currentHundred;
|
| 148 |
let liveLink = `https://www.tiktok.com/@${user}/live`;
|
| 149 |
+
sendToTelegram(`๐ <b>Achievement @${user}:</b> Reached <code>${formatK(currentHundred)}</code> viewers!\n๐ <a href="${liveLink}">Join Live</a>`);
|
| 150 |
}
|
| 151 |
});
|
| 152 |
|
| 153 |
connection.on('member', (data) => {
|
| 154 |
if (data.isModerator &&!adminsSeen.has(data.uniqueId)) {
|
| 155 |
adminsSeen.add(data.uniqueId);
|
| 156 |
+
sendToTelegram(`๐ก๏ธ <b>Moderator Joined @${user}:</b>\n๐ค <code>@${data.uniqueId}</code>`);
|
| 157 |
}
|
| 158 |
+
if (data.userLevel >= 30) sendToTelegram(`๐ <b>VIP Entry (Lvl ${data.userLevel})</b>\n๐ค Live @${user}: <code>@${data.uniqueId}</code>`);
|
| 159 |
});
|
| 160 |
|
| 161 |
connection.on('gift', (data) => {
|
|
|
|
| 169 |
connection.on('disconnected', () => {
|
| 170 |
const diffMs = startTime? (new Date() - startTime) : 0;
|
| 171 |
const totalMinutes = Math.floor(diffMs / 60000);
|
| 172 |
+
const durationStr = startTime? formatDuration(totalMinutes) : "Unknown";
|
| 173 |
|
| 174 |
let sortedGifters = Object.values(giftersMap).sort((a, b) => b.coins - a.coins).slice(0, 3);
|
| 175 |
let sortedCommenters = Object.values(commentersMap).sort((a, b) => b.count - a.count).slice(0, 5);
|
| 176 |
+
let endMsg = `๐ <b>End Summary (@${user})</b>\nโโโโโโโโโโโโโโโโโ\nโฑ๏ธ <b>Duration:</b> ${durationStr} | ๐
<b>Time:</b> ${getBaghdadTime()}\n๐ ๐๏ธ ${formatK(maxViewers)} | โค๏ธ ${formatK(totalLikes)} | ๐ ${totalShares}\nโโโโโโโโโโโโโโโโโ\n๐ <b>Top 3 Supporters:</b>\n`;
|
| 177 |
|
| 178 |
sortedGifters.forEach((g, i) => {
|
| 179 |
endMsg += `${i === 0? '๐ฅ' : i === 1? '๐ฅ' : '๐ฅ'} <code>${g.name}</code> : <b>${formatK(g.coins)}</b>\n`;
|
| 180 |
});
|
| 181 |
|
| 182 |
+
endMsg += `\n๐ฌ <b>Top 5 Active Commenters:</b>\n`;
|
| 183 |
sortedCommenters.forEach((c, i) => {
|
| 184 |
endMsg += `${i+1}. <code>${c.name}</code> (${c.count})\n`;
|
| 185 |
});
|
| 186 |
|
| 187 |
+
if (bestGift.cost > 0) endMsg += `\n๐ <b>Best Gift:</b> ${bestGift.name} from <b>${bestGift.sender}</b>`;
|
| 188 |
sendToTelegram(endMsg, bestGift.icon |
|
| 189 |
|
| 190 |
| null, `https://www.tiktok.com/@${user}/live`);
|