Update bot.js
Browse files
bot.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
| 1 |
/**
|
| 2 |
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 3 |
-
* โ TikTok Radar Pro - Telegram Bot v4.
|
| 4 |
* โ ุจูุช ุงุญุชุฑุงูู ูุฑุงูุจ ุจุซ TikTok ููุฑุณู ุงูุฅุญุตุงุฆูุงุช ููููุงุฉ โ
|
| 5 |
* โ ู
ุน ุฃุฒุฑุงุฑ ุชูุงุนููุฉ + ุฌุณุฑ Cloudflare + ูุจุถ ุฏุงุฎูู + ูุธุงู
ู
ูุงูุญุฉ ุฅุฒุนุงุฌ โ
|
|
|
|
| 6 |
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 7 |
*/
|
| 8 |
|
|
@@ -25,15 +26,12 @@ const CONFIG = {
|
|
| 25 |
TELEGRAM_CHAT_ID: cleanEnv(process.env.TELEGRAM_CHAT_ID, ''),
|
| 26 |
PROXY_URL: cleanEnv(process.env.PROXY_URL, '').replace(/\/$/, ''),
|
| 27 |
REPORT_INTERVAL_MINUTES: parseInt(cleanEnv(process.env.REPORT_INTERVAL, '10')) || 10,
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
SHOW_TOP_CHAT: true, // ุนุฑุถ ุฃูู
ุฑุณุงุฆู ุงูุฏุฑุฏุดุฉ
|
| 35 |
-
TOP_CHAT_LIMIT: 5, // ุนุฏุฏ ุฑุณุงุฆู ุงูุฏุฑุฏุดุฉ ุงูู
ูู
ุฉ
|
| 36 |
-
SPAM_KEYWORDS: ['spam', 'scam', 'fake', 'click', 'link'], // ููู
ุงุช ุณุจุงู
|
| 37 |
};
|
| 38 |
|
| 39 |
console.log('[Config] Loaded settings:');
|
|
@@ -54,12 +52,16 @@ let totalShares = 0;
|
|
| 54 |
let totalGifts = 0;
|
| 55 |
let totalFollows = 0;
|
| 56 |
let totalComments = 0;
|
|
|
|
|
|
|
| 57 |
let giftersMap = {};
|
| 58 |
let likersMap = {};
|
| 59 |
let sharersMap = {};
|
| 60 |
let followersMap = {};
|
| 61 |
let chattersMap = {};
|
| 62 |
let moderatorsMap = {};
|
|
|
|
|
|
|
| 63 |
let topChatMessages = [];
|
| 64 |
let startTime = null;
|
| 65 |
let lastReportTime = null;
|
|
@@ -67,7 +69,6 @@ let tiktokConnection = null;
|
|
| 67 |
let reconnectTimer = null;
|
| 68 |
let reportInterval = null;
|
| 69 |
let lastMessageId = null;
|
| 70 |
-
let lastStatusMessageId = null;
|
| 71 |
let reconnectAttempt = 0;
|
| 72 |
let lastReconnectNotify = 0;
|
| 73 |
|
|
@@ -78,14 +79,15 @@ const cooldowns = {
|
|
| 78 |
like: new Map(),
|
| 79 |
follow: new Map(),
|
| 80 |
share: new Map(),
|
|
|
|
|
|
|
| 81 |
};
|
| 82 |
|
| 83 |
-
// PK System
|
| 84 |
let pkActive = false;
|
| 85 |
let pkInfo = {
|
| 86 |
opponentName: '',
|
| 87 |
-
|
| 88 |
-
theirLikes: 0,
|
| 89 |
ourScore: 0,
|
| 90 |
theirScore: 0,
|
| 91 |
startTime: null,
|
|
@@ -162,14 +164,14 @@ function isOnCooldown(type, key, duration) {
|
|
| 162 |
function isSpamMessage(text) {
|
| 163 |
if (!text) return true;
|
| 164 |
const lower = text.toLowerCase();
|
| 165 |
-
return CONFIG.SPAM_KEYWORDS.some(kw => lower.includes(kw));
|
| 166 |
}
|
| 167 |
|
| 168 |
function cleanChatMessage(text) {
|
| 169 |
if (!text) return '';
|
| 170 |
let cleaned = text.replace(/https?:\/\/\S+/gi, '[ุฑุงุจุท]');
|
| 171 |
-
cleaned = cleaned.replace(/(.)(?=\1{
|
| 172 |
-
if (cleaned.length >
|
| 173 |
return cleaned.trim();
|
| 174 |
}
|
| 175 |
|
|
@@ -226,9 +228,7 @@ async function sendTelegram(text, photoUrl = null, buttons = null, parseMode = '
|
|
| 226 |
function getMainButtons() {
|
| 227 |
const liveLink = `https://www.tiktok.com/@${CONFIG.TIKTOK_USERNAME}/live`;
|
| 228 |
return [
|
| 229 |
-
[
|
| 230 |
-
{ text: '๐ด ุฏุฎูู ุงูุจุซ ุงูู
ุจุงุดุฑ', url: liveLink },
|
| 231 |
-
],
|
| 232 |
[
|
| 233 |
{ text: '๐ ุชูุฑูุฑ ููุฑู', callback_data: 'report_now' },
|
| 234 |
{ text: '๐ ููุญุฉ ุงูุดุฑู', callback_data: 'top_gifters' },
|
|
@@ -241,6 +241,10 @@ function getMainButtons() {
|
|
| 241 |
{ text: 'โ๏ธ ุญุงูุฉ PK', callback_data: 'pk_status' },
|
| 242 |
{ text: '๐ ุฅุญุตุงุฆูุงุช', callback_data: 'deep_stats' },
|
| 243 |
],
|
|
|
|
|
|
|
|
|
|
|
|
|
| 244 |
[
|
| 245 |
{ text: isConnected ? '๐ด ูุทุน ุงูุงุชุตุงู' : '๐ข ุงูุงุชุตุงู', callback_data: isConnected ? 'disconnect' : 'connect' },
|
| 246 |
],
|
|
@@ -250,27 +254,19 @@ function getMainButtons() {
|
|
| 250 |
function getPKButtons() {
|
| 251 |
const liveLink = `https://www.tiktok.com/@${CONFIG.TIKTOK_USERNAME}/live`;
|
| 252 |
return [
|
| 253 |
-
[
|
| 254 |
-
{ text: '๐ ุฏุนู
ุงูุจุซ ุงูุขู', url: liveLink },
|
| 255 |
-
],
|
| 256 |
[
|
| 257 |
{ text: '๐ ุชุญุฏูุซ ุงููุชูุฌุฉ', callback_data: 'pk_update' },
|
| 258 |
{ text: '๐ ุฏุงุนู
ูู ุงูุฌููุฉ', callback_data: 'pk_gifters' },
|
| 259 |
],
|
| 260 |
-
[
|
| 261 |
-
{ text: 'โฌ
๏ธ ุงููุงุฆู
ุฉ ุงูุฑุฆูุณูุฉ', callback_data: 'main_menu' },
|
| 262 |
-
],
|
| 263 |
];
|
| 264 |
}
|
| 265 |
|
| 266 |
function getDisconnectedButtons() {
|
| 267 |
return [
|
| 268 |
-
[
|
| 269 |
-
|
| 270 |
-
],
|
| 271 |
-
[
|
| 272 |
-
{ text: '๐ ุงูุชูุฑูุฑ ุงูููุงุฆู', callback_data: 'final_report' },
|
| 273 |
-
],
|
| 274 |
];
|
| 275 |
}
|
| 276 |
|
|
@@ -289,8 +285,10 @@ function getStatsButtons() {
|
|
| 289 |
{ text: '๐ฎ ุงูู
ุดุฑููู', callback_data: 'moderators' },
|
| 290 |
],
|
| 291 |
[
|
| 292 |
-
{ text: '
|
|
|
|
| 293 |
],
|
|
|
|
| 294 |
];
|
| 295 |
}
|
| 296 |
|
|
@@ -314,11 +312,7 @@ async function handleCallback(callbackData) {
|
|
| 314 |
disconnectRadar();
|
| 315 |
await sendTelegram(
|
| 316 |
`๐ด ุชู
ูุทุน ุงูุงุชุตุงู\nโฐ ${getBaghdadTime()}`,
|
| 317 |
-
null,
|
| 318 |
-
getDisconnectedButtons(),
|
| 319 |
-
'HTML',
|
| 320 |
-
null,
|
| 321 |
-
true
|
| 322 |
);
|
| 323 |
}
|
| 324 |
break;
|
|
@@ -331,72 +325,37 @@ async function handleCallback(callbackData) {
|
|
| 331 |
}
|
| 332 |
break;
|
| 333 |
|
| 334 |
-
case 'top_gifters':
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
case '
|
| 339 |
-
|
| 340 |
-
|
|
|
|
| 341 |
|
| 342 |
-
case '
|
| 343 |
-
|
| 344 |
-
break;
|
| 345 |
-
|
| 346 |
-
case 'top_followers':
|
| 347 |
-
await sendTopFollowersReport();
|
| 348 |
-
break;
|
| 349 |
-
|
| 350 |
-
case 'top_chat':
|
| 351 |
-
await sendTopChatReport();
|
| 352 |
-
break;
|
| 353 |
-
|
| 354 |
-
case 'top_active':
|
| 355 |
-
await sendTopActiveReport();
|
| 356 |
-
break;
|
| 357 |
-
|
| 358 |
-
case 'moderators':
|
| 359 |
-
await sendModeratorsReport();
|
| 360 |
-
break;
|
| 361 |
-
|
| 362 |
-
case 'deep_stats':
|
| 363 |
-
await sendDeepStatsReport();
|
| 364 |
-
break;
|
| 365 |
|
| 366 |
case 'pk_update':
|
| 367 |
-
if (pkActive) {
|
| 368 |
-
|
| 369 |
-
} else {
|
| 370 |
-
await sendTelegram('โ๏ธ ูุง ููุฌุฏ ุฌููุฉ PK ูุดุทุฉ ุญุงููุงู', null, getMainButtons(), 'HTML', null, true);
|
| 371 |
-
}
|
| 372 |
break;
|
| 373 |
|
| 374 |
case 'pk_status':
|
| 375 |
-
if (pkActive) {
|
| 376 |
-
|
| 377 |
-
} else {
|
| 378 |
-
await sendTelegram('โ๏ธ ูุง ููุฌุฏ ุฌููุฉ PK ูุดุทุฉ ุญุงููุงู', null, getMainButtons(), 'HTML', null, true);
|
| 379 |
-
}
|
| 380 |
-
break;
|
| 381 |
-
|
| 382 |
-
case 'pk_gifters':
|
| 383 |
-
await sendPKGiftersReport();
|
| 384 |
break;
|
| 385 |
|
| 386 |
-
case '
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
|
| 390 |
-
case 'main_menu':
|
| 391 |
-
await sendTelegram('๐ก ุงููุงุฆู
ุฉ ุงูุฑุฆูุณูุฉ', null, getMainButtons(), 'HTML', null, true);
|
| 392 |
-
break;
|
| 393 |
|
| 394 |
default:
|
| 395 |
console.log(`[Callback] Unknown: ${callbackData}`);
|
| 396 |
}
|
| 397 |
}
|
| 398 |
|
| 399 |
-
// Poll for callback queries
|
| 400 |
async function pollCallbacks() {
|
| 401 |
let offset = 0;
|
| 402 |
const urls = [];
|
|
@@ -441,33 +400,23 @@ async function pollCallbacks() {
|
|
| 441 |
// โโโโโโโ๏ธ ุงูุชูุงุฑูุฑ ูุงูุฅุดุนุงุฑุงุช โโโโโโโโ
|
| 442 |
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 443 |
function getTopGifters(top = 5) {
|
| 444 |
-
return Object.values(giftersMap)
|
| 445 |
-
.sort((a, b) => b.coins - a.coins)
|
| 446 |
-
.slice(0, top);
|
| 447 |
}
|
| 448 |
|
| 449 |
function getTopLikers(top = 5) {
|
| 450 |
-
return Object.values(likersMap)
|
| 451 |
-
.sort((a, b) => b.count - a.count)
|
| 452 |
-
.slice(0, top);
|
| 453 |
}
|
| 454 |
|
| 455 |
function getTopSharers(top = 5) {
|
| 456 |
-
return Object.values(sharersMap)
|
| 457 |
-
.sort((a, b) => b.count - a.count)
|
| 458 |
-
.slice(0, top);
|
| 459 |
}
|
| 460 |
|
| 461 |
function getTopFollowers(top = 5) {
|
| 462 |
-
return Object.values(followersMap)
|
| 463 |
-
.sort((a, b) => b.count - a.count)
|
| 464 |
-
.slice(0, top);
|
| 465 |
}
|
| 466 |
|
| 467 |
function getTopChatters(top = 5) {
|
| 468 |
-
return Object.values(chattersMap)
|
| 469 |
-
.sort((a, b) => b.count - a.count)
|
| 470 |
-
.slice(0, top);
|
| 471 |
}
|
| 472 |
|
| 473 |
function getTopActiveUsers(top = 5) {
|
|
@@ -475,95 +424,93 @@ function getTopActiveUsers(top = 5) {
|
|
| 475 |
[...Object.values(giftersMap), ...Object.values(likersMap), ...Object.values(sharersMap),
|
| 476 |
...Object.values(followersMap), ...Object.values(chattersMap)].forEach(u => {
|
| 477 |
const key = u.id || u.name;
|
| 478 |
-
if (!allUsers[key]) {
|
| 479 |
-
allUsers[key] = { name: u.name, score: 0 };
|
| 480 |
-
}
|
| 481 |
allUsers[key].score += (u.coins || 0) + (u.count || 0) * 10;
|
| 482 |
});
|
| 483 |
-
return Object.values(allUsers)
|
| 484 |
-
.sort((a, b) => b.score - a.score)
|
| 485 |
-
.slice(0, top);
|
| 486 |
}
|
| 487 |
|
| 488 |
function getModeratorsList() {
|
| 489 |
-
return Object.values(moderatorsMap)
|
| 490 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 491 |
}
|
| 492 |
|
| 493 |
function formatTopGifters(top = 5) {
|
| 494 |
const list = getTopGifters(top);
|
| 495 |
if (list.length === 0) return 'ูุง ููุฌุฏ ุฏุงุนู
ูู ูู ูุฐุง ุงูุจุซ';
|
| 496 |
const medals = ['๐ฅ', '๐ฅ', '๐ฅ', '๐
', '๐', '๐', '๐ต', '๐', '๐
', '๐ฅ'];
|
| 497 |
-
return list
|
| 498 |
-
.map((g, i) => `${medals[i] || '๐
'} ${escapeHtml(g.name)} ยป ${formatK(g.coins)} ๐`)
|
| 499 |
-
.join('\n');
|
| 500 |
}
|
| 501 |
|
| 502 |
function formatTopLikers(top = 5) {
|
| 503 |
const list = getTopLikers(top);
|
| 504 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุนุฌุจูู ู
ุณุฌููู';
|
| 505 |
const medals = ['๐ฅ', '๐ฅ', '๐ฅ', '๐
', '๐'];
|
| 506 |
-
return list
|
| 507 |
-
.map((g, i) => `${medals[i] || 'โค๏ธ'} ${escapeHtml(g.name)} ยป ${formatK(g.count)} โค๏ธ`)
|
| 508 |
-
.join('\n');
|
| 509 |
}
|
| 510 |
|
| 511 |
function formatTopSharers(top = 5) {
|
| 512 |
const list = getTopSharers(top);
|
| 513 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุดุงุฑููู ู
ุณุฌููู';
|
| 514 |
-
return list
|
| 515 |
-
.map((g, i) => `${i + 1}. ${escapeHtml(g.name)} ยป ${formatK(g.count)} โช๏ธ`)
|
| 516 |
-
.join('\n');
|
| 517 |
}
|
| 518 |
|
| 519 |
function formatTopFollowers(top = 5) {
|
| 520 |
const list = getTopFollowers(top);
|
| 521 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุชุงุจุนูู ุฌุฏุฏ ู
ุณุฌููู';
|
| 522 |
-
return list
|
| 523 |
-
.map((g, i) => `${i + 1}. ${escapeHtml(g.name)} โ`)
|
| 524 |
-
.join('\n');
|
| 525 |
}
|
| 526 |
|
| 527 |
function formatTopChatters(top = 5) {
|
| 528 |
const list = getTopChatters(top);
|
| 529 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุชูุงุนููู ูู ุงูุฏุฑุฏุดุฉ';
|
| 530 |
-
return list
|
| 531 |
-
.map((g, i) => `${i + 1}. ${escapeHtml(g.name)} ยป ${formatK(g.count)} ๐ฌ`)
|
| 532 |
-
.join('\n');
|
| 533 |
}
|
| 534 |
|
| 535 |
function formatTopActive(top = 5) {
|
| 536 |
const list = getTopActiveUsers(top);
|
| 537 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุชูุงุนููู ุจุนุฏ';
|
| 538 |
const medals = ['๐', '๐ฅ', '๐ฅ', 'โญ', 'โจ'];
|
| 539 |
-
return list
|
| 540 |
-
.map((g, i) => `${medals[i] || '๐น'} ${escapeHtml(g.name)} ยป ${formatK(g.score)} ููุทุฉ`)
|
| 541 |
-
.join('\n');
|
| 542 |
}
|
| 543 |
|
| 544 |
function formatModerators() {
|
| 545 |
const list = getModeratorsList();
|
| 546 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุดุฑููู ุฏุฎููุง ุงูุจุซ';
|
| 547 |
-
return list
|
| 548 |
-
.map((m, i) => `${i + 1}. ๐ฎ ${escapeHtml(m.name)}${m.isModerator ? ' [ู
ุดุฑู]' : ''}`)
|
| 549 |
-
.join('\n');
|
| 550 |
}
|
| 551 |
|
| 552 |
function formatTopChatMessages() {
|
| 553 |
-
if (topChatMessages.length === 0) return 'ูุง ุชูุฌุฏ ุฑุณุงุฆู
|
| 554 |
return topChatMessages
|
| 555 |
-
.
|
|
|
|
| 556 |
.join('\n');
|
| 557 |
}
|
| 558 |
|
| 559 |
function formatPKGifters() {
|
| 560 |
-
const list = Object.values(pkInfo.pkGifts || {})
|
| 561 |
-
.sort((a, b) => b.coins - a.coins)
|
| 562 |
-
.slice(0, 5);
|
| 563 |
if (list.length === 0) return 'ูุง ููุฌุฏ ุฏุงุนู
ูู ูู ุงูุฌููุฉ';
|
| 564 |
-
return list
|
| 565 |
-
|
| 566 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 567 |
}
|
| 568 |
|
| 569 |
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
@@ -587,7 +534,9 @@ async function sendPeriodicReport() {
|
|
| 587 |
`โช๏ธ <b>ุงูู
ุดุงุฑูุงุช:</b> ${formatK(totalShares)}\n` +
|
| 588 |
`โ <b>ุงูู
ุชุงุจุนูู ุงูุฌุฏุฏ:</b> ${formatK(totalFollows)}\n` +
|
| 589 |
`๐ฌ <b>ุงูุชุนูููุงุช:</b> ${formatK(totalComments)}\n` +
|
| 590 |
-
`๐ <b>ุงููุฏุงูุง:</b> ${formatK(totalGifts)} ๐\n
|
|
|
|
|
|
|
| 591 |
`๐ <b>ุฃูุถู ุงูุฏุงุนู
ูู:</b>\n${topGifterText}\n\n` +
|
| 592 |
`โค๏ธ <b>ุฃูุซุฑ ุงูู
ุนุฌุจูู:</b>\n${topLikerText}\n` +
|
| 593 |
`โโโโโโโโโโโโโโโโโโโ`;
|
|
@@ -597,40 +546,36 @@ async function sendPeriodicReport() {
|
|
| 597 |
}
|
| 598 |
|
| 599 |
async function sendTopGiftersReport() {
|
| 600 |
-
const topGifterText = formatTopGifters(10);
|
| 601 |
const msg = `๐ <b>ููุญุฉ ุงูุดุฑู - ุฃูุถู ุงูุฏุงุนู
ูู</b>\n` +
|
| 602 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 603 |
-
`${
|
| 604 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 605 |
`๐ ุฅุฌู
ุงูู ุงููุฏุงูุง: ${formatK(totalGifts)}`;
|
| 606 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 607 |
}
|
| 608 |
|
| 609 |
async function sendTopLikersReport() {
|
| 610 |
-
const text = formatTopLikers(10);
|
| 611 |
const msg = `โค๏ธ <b>ุฃูุซุฑ ุงูู
ุนุฌุจูู</b>\n` +
|
| 612 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 613 |
-
`${
|
| 614 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 615 |
`โค๏ธ ุฅุฌู
ุงูู ุงูุฅุนุฌุงุจุงุช: ${formatK(totalLikes)}`;
|
| 616 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 617 |
}
|
| 618 |
|
| 619 |
async function sendTopSharersReport() {
|
| 620 |
-
const text = formatTopSharers(10);
|
| 621 |
const msg = `โช๏ธ <b>ุฃูุซุฑ ุงูู
ุดุงุฑููู</b>\n` +
|
| 622 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 623 |
-
`${
|
| 624 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 625 |
`โช๏ธ ุฅุฌู
ุงูู ุงูู
ุดุงุฑูุงุช: ${formatK(totalShares)}`;
|
| 626 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 627 |
}
|
| 628 |
|
| 629 |
async function sendTopFollowersReport() {
|
| 630 |
-
const text = formatTopFollowers(10);
|
| 631 |
const msg = `โ <b>ุงูู
ุชุงุจุนูู ุงูุฌุฏุฏ</b>\n` +
|
| 632 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 633 |
-
`${
|
| 634 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 635 |
`โ ุฅุฌู
ุงูู ุงูู
ุชุงุจุนูู: ${formatK(totalFollows)}`;
|
| 636 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
|
@@ -641,7 +586,7 @@ async function sendTopChatReport() {
|
|
| 641 |
const messages = formatTopChatMessages();
|
| 642 |
const msg = `๐ฌ <b>ุฃูู
ุงูุชุนูููุงุช ูุงูู
ุชูุงุนููู</b>\n` +
|
| 643 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 644 |
-
`<b>๐ ุฃ
|
| 645 |
`<b>๐ฅ ุฃูุซุฑ ุงูู
ุชูุงุนููู:</b>\n${chatters}\n` +
|
| 646 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 647 |
`๐ฌ ุฅุฌู
ุงูู ุงูุชุนูููุงุช: ${formatK(totalComments)}`;
|
|
@@ -649,20 +594,18 @@ async function sendTopChatReport() {
|
|
| 649 |
}
|
| 650 |
|
| 651 |
async function sendTopActiveReport() {
|
| 652 |
-
const text = formatTopActive(10);
|
| 653 |
const msg = `๐ฅ <b>ุฃูุซุฑ ุงูู
ุชูุงุนููู ุดุงู
ูุงู</b>\n` +
|
| 654 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 655 |
-
`${
|
| 656 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 657 |
`๐ ุงูููุงุท = ุงููุฏุงูุง + ุงูุชูุงุนูุงุช ร 10`;
|
| 658 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 659 |
}
|
| 660 |
|
| 661 |
async function sendModeratorsReport() {
|
| 662 |
-
const text = formatModerators();
|
| 663 |
const msg = `๐ฎ <b>ุงูู
ุดุฑููู ูุงูุฃุนุถุงุก ุงูู
ู
ูุฒูู</b>\n` +
|
| 664 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 665 |
-
`${
|
| 666 |
`โโโโโโโโโโโโโโโโโโโ`;
|
| 667 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 668 |
}
|
|
@@ -684,11 +627,15 @@ async function sendDeepStatsReport() {
|
|
| 684 |
`โช๏ธ <b>ุงูู
ุดุงุฑูุงุช:</b> ${formatK(totalShares)}\n` +
|
| 685 |
`โ <b>ุงูู
ุชุงุจุนูู:</b> ${formatK(totalFollows)}\n` +
|
| 686 |
`๐ฌ <b>ุงูุชุนูููุงุช:</b> ${formatK(totalComments)}\n` +
|
| 687 |
-
`๐ <b>ุงููุฏุงูุง:</b> ${formatK(totalGifts)} ๐\n
|
|
|
|
|
|
|
| 688 |
`๐ฅ <b>ุนุฏุฏ ุงูุฏุงุนู
ูู:</b> ${Object.keys(giftersMap).length}\n` +
|
| 689 |
`๐ฌ <b>ุนุฏุฏ ุงูู
ุชูุงุนููู:</b> ${Object.keys(chattersMap).length}\n` +
|
| 690 |
`โ <b>ุนุฏุฏ ุงูู
ุชุงุจุนูู ุงูุฌุฏุฏ:</b> ${Object.keys(followersMap).length}\n` +
|
| 691 |
`๐ฎ <b>ุนุฏุฏ ุงูู
ุดุฑููู:</b> ${Object.keys(moderatorsMap).length}\n` +
|
|
|
|
|
|
|
| 692 |
`โโโโโโโโโโโโโโโโโโโ`;
|
| 693 |
await sendTelegram(msg, null, getMainButtons(), 'HTML', null, true);
|
| 694 |
}
|
|
@@ -714,18 +661,41 @@ async function sendPKGiftersReport() {
|
|
| 714 |
await sendTelegram('โ๏ธ ูุง ููุฌุฏ ุฌููุฉ PK ูุดุทุฉ', null, getMainButtons(), 'HTML', null, true);
|
| 715 |
return;
|
| 716 |
}
|
| 717 |
-
const pkGifters = formatPKGifters();
|
| 718 |
const msg = `โ๏ธ <b>ุฏุงุนู
ูู ุฌููุฉ PK</b>\n` +
|
| 719 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 720 |
-
`${
|
| 721 |
`โโโโโโโโโโโโโโโโโโโ`;
|
| 722 |
await sendTelegram(msg, null, getPKButtons(), 'HTML', null, true);
|
| 723 |
}
|
| 724 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 725 |
async function sendFinalReport() {
|
| 726 |
const duration = formatDuration(startTime);
|
| 727 |
const topGifterText = formatTopGifters(5);
|
| 728 |
const topActiveText = formatTopActive(5);
|
|
|
|
|
|
|
| 729 |
const avgViewers = viewerHistory.length > 0
|
| 730 |
? Math.round(viewerHistory.reduce((a, b) => a + b.viewers, 0) / viewerHistory.length)
|
| 731 |
: 0;
|
|
@@ -741,9 +711,13 @@ async function sendFinalReport() {
|
|
| 741 |
`โช๏ธ <b>ุฅุฌู
ุงูู ุงูู
ุดุงุฑูุงุช:</b> ${formatK(totalShares)}\n` +
|
| 742 |
`โ <b>ุฅุฌู
ุงูู ุงูู
ุชุงุจุนูู:</b> ${formatK(totalFollows)}\n` +
|
| 743 |
`๐ฌ <b>ุฅุฌู
ุงูู ุงูุชุนูููุงุช:</b> ${formatK(totalComments)}\n` +
|
| 744 |
-
`๐ <b>ุฅุฌู
ุงูู ุงููุฏุงูุง:</b> ${formatK(totalGifts)} ๐\n
|
|
|
|
|
|
|
| 745 |
`๐ <b>ููุญุฉ ุงูุดุฑู (ุงูุฏุงุนู
ูู):</b>\n${topGifterText}\n\n` +
|
| 746 |
-
`๐ฅ <b>ุฃูุซุฑ ุงูู
ุชูุงุนููู:</b>\n${topActiveText}\n` +
|
|
|
|
|
|
|
| 747 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 748 |
`๐ค ุงูุจูุช ูู ูุถุน ุงูุงูุชุธุงุฑ...`;
|
| 749 |
await sendTelegram(msg, null, getDisconnectedButtons(), 'HTML', null, false);
|
|
@@ -754,13 +728,11 @@ async function sendFinalReport() {
|
|
| 754 |
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 755 |
async function notifyLike(nickname, likeCount, userId) {
|
| 756 |
if (!isLive) return;
|
| 757 |
-
if (!likersMap[userId]) {
|
| 758 |
-
likersMap[userId] = { id: userId, name: nickname, count: 0 };
|
| 759 |
-
}
|
| 760 |
likersMap[userId].count += likeCount;
|
| 761 |
totalLikes += likeCount;
|
| 762 |
|
| 763 |
-
if (pkActive) pkInfo.
|
| 764 |
|
| 765 |
if (likeCount >= CONFIG.LIKE_BATCH_THRESHOLD) {
|
| 766 |
if (isOnCooldown('like', userId, 30000)) return;
|
|
@@ -775,17 +747,13 @@ async function notifyGift(nickname, giftName, diamondCount, repeatCount, totalCo
|
|
| 775 |
if (!isLive) return;
|
| 776 |
if (isOnCooldown('gift', userId, CONFIG.GIFT_COOLDOWN_MS)) return;
|
| 777 |
|
| 778 |
-
if (!giftersMap[userId]) {
|
| 779 |
-
giftersMap[userId] = { id: userId, name: nickname, coins: 0 };
|
| 780 |
-
}
|
| 781 |
giftersMap[userId].coins += totalCost;
|
| 782 |
totalGifts += totalCost;
|
| 783 |
|
| 784 |
if (pkActive) {
|
| 785 |
pkInfo.ourScore += totalCost;
|
| 786 |
-
if (!pkInfo.pkGifts[userId]) {
|
| 787 |
-
pkInfo.pkGifts[userId] = { id: userId, name: nickname, coins: 0 };
|
| 788 |
-
}
|
| 789 |
pkInfo.pkGifts[userId].coins += totalCost;
|
| 790 |
}
|
| 791 |
|
|
@@ -805,9 +773,7 @@ async function notifyFollow(nickname, userId) {
|
|
| 805 |
if (!isLive) return;
|
| 806 |
if (isOnCooldown('follow', userId, 10000)) return;
|
| 807 |
|
| 808 |
-
if (!followersMap[userId]) {
|
| 809 |
-
followersMap[userId] = { id: userId, name: nickname, count: 0 };
|
| 810 |
-
}
|
| 811 |
followersMap[userId].count++;
|
| 812 |
totalFollows++;
|
| 813 |
|
|
@@ -821,9 +787,7 @@ async function notifyShare(nickname, userId) {
|
|
| 821 |
if (!isLive) return;
|
| 822 |
if (isOnCooldown('share', userId, 15000)) return;
|
| 823 |
|
| 824 |
-
if (!sharersMap[userId]) {
|
| 825 |
-
sharersMap[userId] = { id: userId, name: nickname, count: 0 };
|
| 826 |
-
}
|
| 827 |
sharersMap[userId].count++;
|
| 828 |
totalShares++;
|
| 829 |
|
|
@@ -833,31 +797,32 @@ async function notifyShare(nickname, userId) {
|
|
| 833 |
);
|
| 834 |
}
|
| 835 |
|
| 836 |
-
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
|
| 840 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 841 |
|
| 842 |
if (!text || isSpamMessage(text)) return;
|
| 843 |
-
if (isOnCooldown('chat', userId, CONFIG.CHAT_COOLDOWN_MS)) return;
|
| 844 |
|
| 845 |
-
if (!chattersMap[userId]) {
|
| 846 |
-
chattersMap[userId] = { id: userId, name: nickname, count: 0 };
|
| 847 |
-
}
|
| 848 |
chattersMap[userId].count++;
|
| 849 |
totalComments++;
|
| 850 |
|
| 851 |
topChatMessages.unshift({ name: nickname, text: text, time: Date.now() });
|
| 852 |
-
if (topChatMessages.length >
|
| 853 |
-
topChatMessages = topChatMessages.slice(0, CONFIG.TOP_CHAT_LIMIT * 2);
|
| 854 |
-
}
|
| 855 |
|
| 856 |
-
|
| 857 |
-
const isImportant = text.length > 20 || importantKeywords.some(kw => text.toLowerCase().includes(kw));
|
| 858 |
|
| 859 |
-
|
| 860 |
-
|
|
|
|
|
|
|
|
|
|
| 861 |
`๐ฌ <b>${escapeHtml(nickname)}:</b> ${escapeHtml(text)}`,
|
| 862 |
null, null, 'HTML', null, true
|
| 863 |
);
|
|
@@ -866,15 +831,15 @@ async function notifyChat(data) {
|
|
| 866 |
|
| 867 |
async function notifyModerator(data) {
|
| 868 |
if (!isLive) return;
|
| 869 |
-
const userId = data.userId;
|
| 870 |
-
const nickname = data.nickname || data.uniqueId;
|
| 871 |
|
| 872 |
if (!moderatorsMap[userId]) {
|
| 873 |
moderatorsMap[userId] = {
|
| 874 |
id: userId,
|
| 875 |
name: nickname,
|
| 876 |
joinTime: Date.now(),
|
| 877 |
-
isModerator: data.isModerator || false,
|
| 878 |
};
|
| 879 |
await sendTelegram(
|
| 880 |
`๐ฎโจ <b>${escapeHtml(nickname)}</b> ุฏุฎู ุงูุจุซ${data.isModerator ? ' [ู
ุดุฑู]' : ''}!`,
|
|
@@ -883,12 +848,73 @@ async function notifyModerator(data) {
|
|
| 883 |
}
|
| 884 |
}
|
| 885 |
|
| 886 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 887 |
pkActive = true;
|
| 888 |
pkInfo = {
|
| 889 |
-
opponentName: opponentName
|
| 890 |
-
|
| 891 |
-
theirLikes: 0,
|
| 892 |
ourScore: 0,
|
| 893 |
theirScore: 0,
|
| 894 |
startTime: new Date(),
|
|
@@ -899,13 +925,17 @@ async function notifyPKStart(opponentName) {
|
|
| 899 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 900 |
`๐ฅ <b>ุงูู
ูุงูุณ:</b> ${escapeHtml(opponentName)}\n\n` +
|
| 901 |
`ุงูููุฒ ูุญุชุงุฌ ูููุฉ ุงูุฃุจุทุงู! ุดุฏูุง ุงูุญูู.. ๐`;
|
| 902 |
-
|
| 903 |
}
|
| 904 |
|
| 905 |
-
|
|
|
|
| 906 |
pkActive = false;
|
|
|
|
| 907 |
const bar = generateProgressBar(pkInfo.ourScore, pkInfo.theirScore, 10);
|
| 908 |
-
const
|
|
|
|
|
|
|
| 909 |
const pkGifters = formatPKGifters();
|
| 910 |
|
| 911 |
const msg = `๐โ๏ธ <b>ุงูุชูุช ุงูู
ูุงุฌูุฉ!</b>\n` +
|
|
@@ -916,19 +946,25 @@ async function notifyPKEnd(winner) {
|
|
| 916 |
`${bar}\n\n` +
|
| 917 |
`๐ <b>ุฏุงุนู
ูู ุงูุฌููุฉ:</b>\n${pkGifters}\n\n` +
|
| 918 |
`โจ ุดูุฑุงู ููู ู
ู ุณุงูู
ูู ูุฐู ุงูุฌููุฉ!`;
|
| 919 |
-
|
| 920 |
|
| 921 |
-
pkInfo = {
|
| 922 |
-
|
| 923 |
-
|
| 924 |
-
|
| 925 |
-
|
| 926 |
-
|
| 927 |
-
|
| 928 |
-
|
| 929 |
-
|
|
|
|
|
|
|
|
|
|
| 930 |
}
|
| 931 |
|
|
|
|
|
|
|
|
|
|
| 932 |
async function notifyStreamStart(state) {
|
| 933 |
isLive = true;
|
| 934 |
const roomInfo = state.roomInfo || {};
|
|
@@ -978,6 +1014,7 @@ function createConnection() {
|
|
| 978 |
}
|
| 979 |
|
| 980 |
function setupEvents(connection) {
|
|
|
|
| 981 |
connection.on('roomUser', (data) => {
|
| 982 |
const viewers = data.viewerCount || 0;
|
| 983 |
if (viewers > maxViewers) maxViewers = viewers;
|
|
@@ -985,56 +1022,72 @@ function setupEvents(connection) {
|
|
| 985 |
if (viewerHistory.length > 200) viewerHistory.shift();
|
| 986 |
});
|
| 987 |
|
|
|
|
| 988 |
connection.on('like', (data) => {
|
| 989 |
const likes = data.likeCount || 0;
|
| 990 |
-
const userId = data.userId;
|
| 991 |
const nickname = data.nickname || data.uniqueId;
|
| 992 |
notifyLike(nickname, likes, userId);
|
| 993 |
});
|
| 994 |
|
| 995 |
-
|
| 996 |
-
|
|
|
|
| 997 |
const nickname = data.nickname || data.uniqueId;
|
| 998 |
-
|
| 999 |
-
|
| 1000 |
-
|
| 1001 |
-
|
| 1002 |
-
|
| 1003 |
-
|
| 1004 |
-
|
|
|
|
|
|
|
| 1005 |
});
|
| 1006 |
|
|
|
|
| 1007 |
connection.on('chat', (data) => {
|
| 1008 |
-
|
| 1009 |
});
|
| 1010 |
|
|
|
|
| 1011 |
connection.on('member', (data) => {
|
| 1012 |
notifyModerator(data);
|
| 1013 |
});
|
| 1014 |
|
|
|
|
| 1015 |
connection.on('gift', (data) => {
|
| 1016 |
if (data.giftType === 1 && !data.repeatEnd) return;
|
| 1017 |
const giftCost = (data.diamondCount || 0) * (data.repeatCount || 1);
|
| 1018 |
-
const userId = data.userId;
|
| 1019 |
const nickname = data.nickname || data.uniqueId;
|
| 1020 |
notifyGift(nickname, data.giftName || 'Gift', data.diamondCount || 0, data.repeatCount || 1, giftCost, userId);
|
| 1021 |
});
|
| 1022 |
|
| 1023 |
-
|
| 1024 |
-
|
|
|
|
|
|
|
| 1025 |
});
|
| 1026 |
|
| 1027 |
-
|
| 1028 |
-
|
| 1029 |
-
|
| 1030 |
-
|
| 1031 |
});
|
| 1032 |
|
| 1033 |
-
|
| 1034 |
-
|
| 1035 |
-
|
|
|
|
| 1036 |
});
|
| 1037 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1038 |
connection.on('streamEnd', async () => {
|
| 1039 |
isConnected = false;
|
| 1040 |
isLive = false;
|
|
@@ -1043,6 +1096,14 @@ function setupEvents(connection) {
|
|
| 1043 |
reconnectTimer = setTimeout(startRadar, 60000);
|
| 1044 |
});
|
| 1045 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1046 |
connection.on('error', (err) => {
|
| 1047 |
console.error(`[TikTok] Error: ${err.message}`);
|
| 1048 |
});
|
|
@@ -1058,35 +1119,16 @@ async function startRadar() {
|
|
| 1058 |
reconnectAttempt++;
|
| 1059 |
|
| 1060 |
if (reconnectAttempt === 1) {
|
| 1061 |
-
maxViewers = 0;
|
| 1062 |
-
|
| 1063 |
-
|
| 1064 |
-
|
| 1065 |
-
totalFollows = 0;
|
| 1066 |
-
totalComments = 0;
|
| 1067 |
-
giftersMap = {};
|
| 1068 |
-
likersMap = {};
|
| 1069 |
-
sharersMap = {};
|
| 1070 |
-
followersMap = {};
|
| 1071 |
-
chattersMap = {};
|
| 1072 |
-
moderatorsMap = {};
|
| 1073 |
topChatMessages = [];
|
| 1074 |
viewerHistory = [];
|
| 1075 |
pkActive = false;
|
| 1076 |
-
pkInfo = {
|
| 1077 |
-
|
| 1078 |
-
|
| 1079 |
-
theirLikes: 0,
|
| 1080 |
-
ourScore: 0,
|
| 1081 |
-
theirScore: 0,
|
| 1082 |
-
startTime: null,
|
| 1083 |
-
pkGifts: {},
|
| 1084 |
-
};
|
| 1085 |
-
cooldowns.chat.clear();
|
| 1086 |
-
cooldowns.gift.clear();
|
| 1087 |
-
cooldowns.like.clear();
|
| 1088 |
-
cooldowns.follow.clear();
|
| 1089 |
-
cooldowns.share.clear();
|
| 1090 |
}
|
| 1091 |
|
| 1092 |
try {
|
|
@@ -1152,9 +1194,7 @@ function disconnectRadar() {
|
|
| 1152 |
isConnected = false;
|
| 1153 |
isLive = false;
|
| 1154 |
if (tiktokConnection) {
|
| 1155 |
-
try {
|
| 1156 |
-
tiktokConnection.disconnect();
|
| 1157 |
-
} catch (e) {}
|
| 1158 |
tiktokConnection = null;
|
| 1159 |
}
|
| 1160 |
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
@@ -1177,19 +1217,20 @@ function startPeriodicReports() {
|
|
| 1177 |
}
|
| 1178 |
|
| 1179 |
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1180 |
-
// โโโโโโโ๏ธ ุงูุฎุงุฏู
ุงูุฏุงุฎูู
|
| 1181 |
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1182 |
const server = http.createServer((req, res) => {
|
| 1183 |
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
| 1184 |
const status = isLive ? '๐ด LIVE' : isConnected ? '๐ก CONNECTING' : 'โช WAITING';
|
| 1185 |
-
|
|
|
|
| 1186 |
});
|
| 1187 |
|
| 1188 |
const PORT = process.env.PORT || 7860;
|
| 1189 |
server.listen(PORT, '0.0.0.0', () => {
|
| 1190 |
console.log(`
|
| 1191 |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1192 |
-
โ TikTok Radar Pro - Telegram Bot v4.
|
| 1193 |
โ โ
|
| 1194 |
โ ๐ค Telegram Bot Active โ
|
| 1195 |
โ ๐ก TikTok: @${CONFIG.TIKTOK_USERNAME.padEnd(45, ' ')}โ
|
|
@@ -1199,6 +1240,7 @@ server.listen(PORT, '0.0.0.0', () => {
|
|
| 1199 |
โ โ
|
| 1200 |
โ โจ Features: Anti-Spam | Smart Cooldowns | Deep Stats โ
|
| 1201 |
โ ๐ Gifts | โค๏ธ Likes | โช๏ธ Shares | ๐ฌ Chat | โ๏ธ PK โ
|
|
|
|
| 1202 |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1203 |
`);
|
| 1204 |
|
|
|
|
| 1 |
/**
|
| 2 |
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 3 |
+
* โ TikTok Radar Pro - Telegram Bot v4.2 (Royal Edition) โ
|
| 4 |
* โ ุจูุช ุงุญุชุฑุงูู ูุฑุงูุจ ุจุซ TikTok ููุฑุณู ุงูุฅุญุตุงุฆูุงุช ููููุงุฉ โ
|
| 5 |
* โ ู
ุน ุฃุฒุฑุงุฑ ุชูุงุนููุฉ + ุฌุณุฑ Cloudflare + ูุจุถ ุฏุงุฎูู + ูุธุงู
ู
ูุงูุญุฉ ุฅุฒุนุงุฌ โ
|
| 6 |
+
* โ + ุตูุงุฏูู ุงููุฏุงูุง + ุญููุจุฉ ุงูุนู
ูุงุช โ
|
| 7 |
* โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 8 |
*/
|
| 9 |
|
|
|
|
| 26 |
TELEGRAM_CHAT_ID: cleanEnv(process.env.TELEGRAM_CHAT_ID, ''),
|
| 27 |
PROXY_URL: cleanEnv(process.env.PROXY_URL, '').replace(/\/$/, ''),
|
| 28 |
REPORT_INTERVAL_MINUTES: parseInt(cleanEnv(process.env.REPORT_INTERVAL, '10')) || 10,
|
| 29 |
+
CHAT_COOLDOWN_MS: 3000,
|
| 30 |
+
GIFT_COOLDOWN_MS: 2000,
|
| 31 |
+
LIKE_BATCH_THRESHOLD: 50,
|
| 32 |
+
SHOW_TOP_CHAT: true,
|
| 33 |
+
TOP_CHAT_LIMIT: 10,
|
| 34 |
+
SPAM_KEYWORDS: ['spam', 'scam', 'fake', 'click here', 'free money', 'earn now'],
|
|
|
|
|
|
|
|
|
|
| 35 |
};
|
| 36 |
|
| 37 |
console.log('[Config] Loaded settings:');
|
|
|
|
| 52 |
let totalGifts = 0;
|
| 53 |
let totalFollows = 0;
|
| 54 |
let totalComments = 0;
|
| 55 |
+
let totalEnvelopes = 0;
|
| 56 |
+
let totalCoinsGiven = 0;
|
| 57 |
let giftersMap = {};
|
| 58 |
let likersMap = {};
|
| 59 |
let sharersMap = {};
|
| 60 |
let followersMap = {};
|
| 61 |
let chattersMap = {};
|
| 62 |
let moderatorsMap = {};
|
| 63 |
+
let envelopeWinnersMap = {};
|
| 64 |
+
let coinPurseWinnersMap = {};
|
| 65 |
let topChatMessages = [];
|
| 66 |
let startTime = null;
|
| 67 |
let lastReportTime = null;
|
|
|
|
| 69 |
let reconnectTimer = null;
|
| 70 |
let reportInterval = null;
|
| 71 |
let lastMessageId = null;
|
|
|
|
| 72 |
let reconnectAttempt = 0;
|
| 73 |
let lastReconnectNotify = 0;
|
| 74 |
|
|
|
|
| 79 |
like: new Map(),
|
| 80 |
follow: new Map(),
|
| 81 |
share: new Map(),
|
| 82 |
+
envelope: new Map(),
|
| 83 |
+
coinPurse: new Map(),
|
| 84 |
};
|
| 85 |
|
| 86 |
+
// PK / Battle System
|
| 87 |
let pkActive = false;
|
| 88 |
let pkInfo = {
|
| 89 |
opponentName: '',
|
| 90 |
+
opponentUserId: '',
|
|
|
|
| 91 |
ourScore: 0,
|
| 92 |
theirScore: 0,
|
| 93 |
startTime: null,
|
|
|
|
| 164 |
function isSpamMessage(text) {
|
| 165 |
if (!text) return true;
|
| 166 |
const lower = text.toLowerCase();
|
| 167 |
+
return CONFIG.SPAM_KEYWORDS.some(kw => lower.includes(kw.toLowerCase()));
|
| 168 |
}
|
| 169 |
|
| 170 |
function cleanChatMessage(text) {
|
| 171 |
if (!text) return '';
|
| 172 |
let cleaned = text.replace(/https?:\/\/\S+/gi, '[ุฑุงุจุท]');
|
| 173 |
+
cleaned = cleaned.replace(/(.)(?=\1{5,})/g, '');
|
| 174 |
+
if (cleaned.length > 120) cleaned = cleaned.substring(0, 120) + '...';
|
| 175 |
return cleaned.trim();
|
| 176 |
}
|
| 177 |
|
|
|
|
| 228 |
function getMainButtons() {
|
| 229 |
const liveLink = `https://www.tiktok.com/@${CONFIG.TIKTOK_USERNAME}/live`;
|
| 230 |
return [
|
| 231 |
+
[{ text: '๐ด ุฏุฎูู ุงูุจุซ ุงูู
ุจุงุดุฑ', url: liveLink }],
|
|
|
|
|
|
|
| 232 |
[
|
| 233 |
{ text: '๐ ุชูุฑูุฑ ููุฑู', callback_data: 'report_now' },
|
| 234 |
{ text: '๐ ููุญุฉ ุงูุดุฑู', callback_data: 'top_gifters' },
|
|
|
|
| 241 |
{ text: 'โ๏ธ ุญุงูุฉ PK', callback_data: 'pk_status' },
|
| 242 |
{ text: '๐ ุฅุญุตุงุฆูุงุช', callback_data: 'deep_stats' },
|
| 243 |
],
|
| 244 |
+
[
|
| 245 |
+
{ text: '๐ ุงูุตูุงุฏูู', callback_data: 'envelopes' },
|
| 246 |
+
{ text: '๐ฐ ุงูุนู
ูุงุช', callback_data: 'coin_purse' },
|
| 247 |
+
],
|
| 248 |
[
|
| 249 |
{ text: isConnected ? '๐ด ูุทุน ุงูุงุชุตุงู' : '๐ข ุงูุงุชุตุงู', callback_data: isConnected ? 'disconnect' : 'connect' },
|
| 250 |
],
|
|
|
|
| 254 |
function getPKButtons() {
|
| 255 |
const liveLink = `https://www.tiktok.com/@${CONFIG.TIKTOK_USERNAME}/live`;
|
| 256 |
return [
|
| 257 |
+
[{ text: '๐ ุฏุนู
ุงูุจุซ ุงูุขู', url: liveLink }],
|
|
|
|
|
|
|
| 258 |
[
|
| 259 |
{ text: '๐ ุชุญุฏูุซ ุงููุชูุฌุฉ', callback_data: 'pk_update' },
|
| 260 |
{ text: '๐ ุฏุงุนู
ูู ุงูุฌููุฉ', callback_data: 'pk_gifters' },
|
| 261 |
],
|
| 262 |
+
[{ text: 'โฌ
๏ธ ุงููุงุฆู
ุฉ ุงูุฑุฆูุณูุฉ', callback_data: 'main_menu' }],
|
|
|
|
|
|
|
| 263 |
];
|
| 264 |
}
|
| 265 |
|
| 266 |
function getDisconnectedButtons() {
|
| 267 |
return [
|
| 268 |
+
[{ text: '๐ ุฅุนุงุฏุฉ ุงูุงุชุตุงู', callback_data: 'connect' }],
|
| 269 |
+
[{ text: '๐ ุงูุชูุฑูุฑ ุงูููุงุฆู', callback_data: 'final_report' }],
|
|
|
|
|
|
|
|
|
|
|
|
|
| 270 |
];
|
| 271 |
}
|
| 272 |
|
|
|
|
| 285 |
{ text: '๐ฎ ุงูู
ุดุฑููู', callback_data: 'moderators' },
|
| 286 |
],
|
| 287 |
[
|
| 288 |
+
{ text: '๐ ุงูุตูุงุฏูู', callback_data: 'envelopes' },
|
| 289 |
+
{ text: '๐ฐ ุงูุนู
ูุงุช', callback_data: 'coin_purse' },
|
| 290 |
],
|
| 291 |
+
[{ text: 'โฌ
๏ธ ุงููุงุฆู
ุฉ ุงูุฑุฆูุณูุฉ', callback_data: 'main_menu' }],
|
| 292 |
];
|
| 293 |
}
|
| 294 |
|
|
|
|
| 312 |
disconnectRadar();
|
| 313 |
await sendTelegram(
|
| 314 |
`๐ด ุชู
ูุทุน ุงูุงุชุตุงู\nโฐ ${getBaghdadTime()}`,
|
| 315 |
+
null, getDisconnectedButtons(), 'HTML', null, true
|
|
|
|
|
|
|
|
|
|
|
|
|
| 316 |
);
|
| 317 |
}
|
| 318 |
break;
|
|
|
|
| 325 |
}
|
| 326 |
break;
|
| 327 |
|
| 328 |
+
case 'top_gifters': await sendTopGiftersReport(); break;
|
| 329 |
+
case 'top_likers': await sendTopLikersReport(); break;
|
| 330 |
+
case 'top_sharers': await sendTopSharersReport(); break;
|
| 331 |
+
case 'top_followers': await sendTopFollowersReport(); break;
|
| 332 |
+
case 'top_chat': await sendTopChatReport(); break;
|
| 333 |
+
case 'top_active': await sendTopActiveReport(); break;
|
| 334 |
+
case 'moderators': await sendModeratorsReport(); break;
|
| 335 |
+
case 'deep_stats': await sendDeepStatsReport(); break;
|
| 336 |
|
| 337 |
+
case 'envelopes': await sendEnvelopesReport(); break;
|
| 338 |
+
case 'coin_purse': await sendCoinPurseReport(); break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 339 |
|
| 340 |
case 'pk_update':
|
| 341 |
+
if (pkActive) { await sendPKUpdate(); }
|
| 342 |
+
else { await sendTelegram('โ๏ธ ูุง ููุฌุฏ ุฌููุฉ PK ูุดุทุฉ ุญุงููุงู', null, getMainButtons(), 'HTML', null, true); }
|
|
|
|
|
|
|
|
|
|
| 343 |
break;
|
| 344 |
|
| 345 |
case 'pk_status':
|
| 346 |
+
if (pkActive) { await sendPKUpdate(); }
|
| 347 |
+
else { await sendTelegram('โ๏ธ ูุง ููุฌุฏ ุฌููุฉ PK ูุดุทุฉ ุญุงููุงู', null, getMainButtons(), 'HTML', null, true); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 348 |
break;
|
| 349 |
|
| 350 |
+
case 'pk_gifters': await sendPKGiftersReport(); break;
|
| 351 |
+
case 'final_report': await sendFinalReport(); break;
|
| 352 |
+
case 'main_menu': await sendTelegram('๐ก ุงููุงุฆู
ุฉ ุงูุฑุฆูุณูุฉ', null, getMainButtons(), 'HTML', null, true); break;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 353 |
|
| 354 |
default:
|
| 355 |
console.log(`[Callback] Unknown: ${callbackData}`);
|
| 356 |
}
|
| 357 |
}
|
| 358 |
|
|
|
|
| 359 |
async function pollCallbacks() {
|
| 360 |
let offset = 0;
|
| 361 |
const urls = [];
|
|
|
|
| 400 |
// โโโโโโโ๏ธ ุงูุชูุงุฑูุฑ ูุงูุฅุดุนุงุฑุงุช โโโโโโโโ
|
| 401 |
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 402 |
function getTopGifters(top = 5) {
|
| 403 |
+
return Object.values(giftersMap).sort((a, b) => b.coins - a.coins).slice(0, top);
|
|
|
|
|
|
|
| 404 |
}
|
| 405 |
|
| 406 |
function getTopLikers(top = 5) {
|
| 407 |
+
return Object.values(likersMap).sort((a, b) => b.count - a.count).slice(0, top);
|
|
|
|
|
|
|
| 408 |
}
|
| 409 |
|
| 410 |
function getTopSharers(top = 5) {
|
| 411 |
+
return Object.values(sharersMap).sort((a, b) => b.count - a.count).slice(0, top);
|
|
|
|
|
|
|
| 412 |
}
|
| 413 |
|
| 414 |
function getTopFollowers(top = 5) {
|
| 415 |
+
return Object.values(followersMap).sort((a, b) => b.count - a.count).slice(0, top);
|
|
|
|
|
|
|
| 416 |
}
|
| 417 |
|
| 418 |
function getTopChatters(top = 5) {
|
| 419 |
+
return Object.values(chattersMap).sort((a, b) => b.count - a.count).slice(0, top);
|
|
|
|
|
|
|
| 420 |
}
|
| 421 |
|
| 422 |
function getTopActiveUsers(top = 5) {
|
|
|
|
| 424 |
[...Object.values(giftersMap), ...Object.values(likersMap), ...Object.values(sharersMap),
|
| 425 |
...Object.values(followersMap), ...Object.values(chattersMap)].forEach(u => {
|
| 426 |
const key = u.id || u.name;
|
| 427 |
+
if (!allUsers[key]) allUsers[key] = { name: u.name, score: 0 };
|
|
|
|
|
|
|
| 428 |
allUsers[key].score += (u.coins || 0) + (u.count || 0) * 10;
|
| 429 |
});
|
| 430 |
+
return Object.values(allUsers).sort((a, b) => b.score - a.score).slice(0, top);
|
|
|
|
|
|
|
| 431 |
}
|
| 432 |
|
| 433 |
function getModeratorsList() {
|
| 434 |
+
return Object.values(moderatorsMap).sort((a, b) => b.joinTime - a.joinTime);
|
| 435 |
+
}
|
| 436 |
+
|
| 437 |
+
function getTopEnvelopeWinners(top = 5) {
|
| 438 |
+
return Object.values(envelopeWinnersMap).sort((a, b) => b.count - a.count).slice(0, top);
|
| 439 |
+
}
|
| 440 |
+
|
| 441 |
+
function getTopCoinPurseWinners(top = 5) {
|
| 442 |
+
return Object.values(coinPurseWinnersMap).sort((a, b) => b.coins - a.coins).slice(0, top);
|
| 443 |
}
|
| 444 |
|
| 445 |
function formatTopGifters(top = 5) {
|
| 446 |
const list = getTopGifters(top);
|
| 447 |
if (list.length === 0) return 'ูุง ููุฌุฏ ุฏุงุนู
ูู ูู ูุฐุง ุงูุจุซ';
|
| 448 |
const medals = ['๐ฅ', '๐ฅ', '๐ฅ', '๐
', '๐', '๐', '๐ต', '๐', '๐
', '๐ฅ'];
|
| 449 |
+
return list.map((g, i) => `${medals[i] || '๐
'} ${escapeHtml(g.name)} ยป ${formatK(g.coins)} ๐`).join('\n');
|
|
|
|
|
|
|
| 450 |
}
|
| 451 |
|
| 452 |
function formatTopLikers(top = 5) {
|
| 453 |
const list = getTopLikers(top);
|
| 454 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุนุฌุจูู ู
ุณุฌููู';
|
| 455 |
const medals = ['๐ฅ', '๐ฅ', '๐ฅ', '๐
', '๐'];
|
| 456 |
+
return list.map((g, i) => `${medals[i] || 'โค๏ธ'} ${escapeHtml(g.name)} ยป ${formatK(g.count)} โค๏ธ`).join('\n');
|
|
|
|
|
|
|
| 457 |
}
|
| 458 |
|
| 459 |
function formatTopSharers(top = 5) {
|
| 460 |
const list = getTopSharers(top);
|
| 461 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุดุงุฑููู ู
ุณุฌููู';
|
| 462 |
+
return list.map((g, i) => `${i + 1}. ${escapeHtml(g.name)} ยป ${formatK(g.count)} โช๏ธ`).join('\n');
|
|
|
|
|
|
|
| 463 |
}
|
| 464 |
|
| 465 |
function formatTopFollowers(top = 5) {
|
| 466 |
const list = getTopFollowers(top);
|
| 467 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุชุงุจุนูู ุฌุฏุฏ ู
ุณุฌููู';
|
| 468 |
+
return list.map((g, i) => `${i + 1}. ${escapeHtml(g.name)} โ`).join('\n');
|
|
|
|
|
|
|
| 469 |
}
|
| 470 |
|
| 471 |
function formatTopChatters(top = 5) {
|
| 472 |
const list = getTopChatters(top);
|
| 473 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุชูุงุนููู ูู ุงูุฏุฑุฏุดุฉ';
|
| 474 |
+
return list.map((g, i) => `${i + 1}. ${escapeHtml(g.name)} ยป ${formatK(g.count)} ๐ฌ`).join('\n');
|
|
|
|
|
|
|
| 475 |
}
|
| 476 |
|
| 477 |
function formatTopActive(top = 5) {
|
| 478 |
const list = getTopActiveUsers(top);
|
| 479 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุชูุงุนููู ุจุนุฏ';
|
| 480 |
const medals = ['๐', '๐ฅ', '๐ฅ', 'โญ', 'โจ'];
|
| 481 |
+
return list.map((g, i) => `${medals[i] || '๐น'} ${escapeHtml(g.name)} ยป ${formatK(g.score)} ููุทุฉ`).join('\n');
|
|
|
|
|
|
|
| 482 |
}
|
| 483 |
|
| 484 |
function formatModerators() {
|
| 485 |
const list = getModeratorsList();
|
| 486 |
if (list.length === 0) return 'ูุง ููุฌุฏ ู
ุดุฑููู ุฏุฎููุง ุงูุจุซ';
|
| 487 |
+
return list.map((m, i) => `${i + 1}. ๐ฎ ${escapeHtml(m.name)}${m.isModerator ? ' [ู
ุดุฑู]' : ''}`).join('\n');
|
|
|
|
|
|
|
| 488 |
}
|
| 489 |
|
| 490 |
function formatTopChatMessages() {
|
| 491 |
+
if (topChatMessages.length === 0) return 'ูุง ุชูุฌุฏ ุฑุณุงุฆู ุจุนุฏ';
|
| 492 |
return topChatMessages
|
| 493 |
+
.slice(0, CONFIG.TOP_CHAT_LIMIT)
|
| 494 |
+
.map((msg, i) => `๐ฌ <b>${escapeHtml(msg.name)}:</b> ${escapeHtml(msg.text)}`)
|
| 495 |
.join('\n');
|
| 496 |
}
|
| 497 |
|
| 498 |
function formatPKGifters() {
|
| 499 |
+
const list = Object.values(pkInfo.pkGifts || {}).sort((a, b) => b.coins - a.coins).slice(0, 5);
|
|
|
|
|
|
|
| 500 |
if (list.length === 0) return 'ูุง ููุฌุฏ ุฏุงุนู
ูู ูู ุงูุฌููุฉ';
|
| 501 |
+
return list.map((g, i) => `${i + 1}. ${escapeHtml(g.name)} ยป ${formatK(g.coins)} ๐`).join('\n');
|
| 502 |
+
}
|
| 503 |
+
|
| 504 |
+
function formatEnvelopeWinners(top = 10) {
|
| 505 |
+
const list = getTopEnvelopeWinners(top);
|
| 506 |
+
if (list.length === 0) return 'ูุง ููุฌุฏ ูุงุฆุฒูู ุจุงูุตูุงุฏูู ุจุนุฏ';
|
| 507 |
+
return list.map((w, i) => `${i + 1}. ๐ ${escapeHtml(w.name)} ยป ${formatK(w.count)} ุตูุฏูู`).join('\n');
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
+
function formatCoinPurseWinners(top = 10) {
|
| 511 |
+
const list = getTopCoinPurseWinners(top);
|
| 512 |
+
if (list.length === 0) return 'ูุง ููุฌุฏ ูุงุฆุฒูู ุจุญููุจุฉ ุงูุนู
ูุงุช ุจุนุฏ';
|
| 513 |
+
return list.map((w, i) => `${i + 1}. ๐ฐ ${escapeHtml(w.name)} ยป ${formatK(w.coins)} ุนู
ูุฉ`).join('\n');
|
| 514 |
}
|
| 515 |
|
| 516 |
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
|
|
| 534 |
`โช๏ธ <b>ุงูู
ุดุงุฑูุงุช:</b> ${formatK(totalShares)}\n` +
|
| 535 |
`โ <b>ุงูู
ุชุงุจุนูู ุงูุฌุฏุฏ:</b> ${formatK(totalFollows)}\n` +
|
| 536 |
`๐ฌ <b>ุงูุชุนูููุงุช:</b> ${formatK(totalComments)}\n` +
|
| 537 |
+
`๐ <b>ุงููุฏุงูุง:</b> ${formatK(totalGifts)} ๐\n` +
|
| 538 |
+
`๐ฆ <b>ุงูุตูุงุฏูู:</b> ${formatK(totalEnvelopes)}\n` +
|
| 539 |
+
`๐ฐ <b>ุงูุนู
ูุงุช ุงูู
ูุฒุนุฉ:</b> ${formatK(totalCoinsGiven)}\n\n` +
|
| 540 |
`๐ <b>ุฃูุถู ุงูุฏุงุนู
ูู:</b>\n${topGifterText}\n\n` +
|
| 541 |
`โค๏ธ <b>ุฃูุซุฑ ุงูู
ุนุฌุจูู:</b>\n${topLikerText}\n` +
|
| 542 |
`โโโโโโโโโโโโโโโโโโโ`;
|
|
|
|
| 546 |
}
|
| 547 |
|
| 548 |
async function sendTopGiftersReport() {
|
|
|
|
| 549 |
const msg = `๐ <b>ููุญุฉ ุงูุดุฑู - ุฃูุถู ุงูุฏุงุนู
ูู</b>\n` +
|
| 550 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 551 |
+
`${formatTopGifters(10)}\n` +
|
| 552 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 553 |
`๐ ุฅุฌู
ุงูู ุงููุฏุงูุง: ${formatK(totalGifts)}`;
|
| 554 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 555 |
}
|
| 556 |
|
| 557 |
async function sendTopLikersReport() {
|
|
|
|
| 558 |
const msg = `โค๏ธ <b>ุฃูุซุฑ ุงูู
ุนุฌุจูู</b>\n` +
|
| 559 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 560 |
+
`${formatTopLikers(10)}\n` +
|
| 561 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 562 |
`โค๏ธ ุฅุฌู
ุงูู ุงูุฅุนุฌุงุจุงุช: ${formatK(totalLikes)}`;
|
| 563 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 564 |
}
|
| 565 |
|
| 566 |
async function sendTopSharersReport() {
|
|
|
|
| 567 |
const msg = `โช๏ธ <b>ุฃูุซุฑ ุงูู
ุดุงุฑููู</b>\n` +
|
| 568 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 569 |
+
`${formatTopSharers(10)}\n` +
|
| 570 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 571 |
`โช๏ธ ุฅุฌู
ุงูู ุงูู
ุดุงุฑูุงุช: ${formatK(totalShares)}`;
|
| 572 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 573 |
}
|
| 574 |
|
| 575 |
async function sendTopFollowersReport() {
|
|
|
|
| 576 |
const msg = `โ <b>ุงูู
ุชุงุจุนูู ุงูุฌุฏุฏ</b>\n` +
|
| 577 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 578 |
+
`${formatTopFollowers(10)}\n` +
|
| 579 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 580 |
`โ ุฅุฌู
ุงูู ุงูู
ุชุงุจุนูู: ${formatK(totalFollows)}`;
|
| 581 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
|
|
|
| 586 |
const messages = formatTopChatMessages();
|
| 587 |
const msg = `๐ฌ <b>ุฃูู
ุงูุชุนูููุงุช ูุงูู
ุชูุงุนููู</b>\n` +
|
| 588 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 589 |
+
`<b>๐ ุฃุญุฏุซ ุงูุฑุณุงุฆู:</b>\n${messages}\n\n` +
|
| 590 |
`<b>๐ฅ ุฃูุซุฑ ุงูู
ุชูุงุนููู:</b>\n${chatters}\n` +
|
| 591 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 592 |
`๐ฌ ุฅุฌู
ุงูู ุงูุชุนูููุงุช: ${formatK(totalComments)}`;
|
|
|
|
| 594 |
}
|
| 595 |
|
| 596 |
async function sendTopActiveReport() {
|
|
|
|
| 597 |
const msg = `๐ฅ <b>ุฃูุซุฑ ุงูู
ุชูุงุนููู ุดุงู
ูุงู</b>\n` +
|
| 598 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 599 |
+
`${formatTopActive(10)}\n` +
|
| 600 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 601 |
`๐ ุงูููุงุท = ุงููุฏุงูุง + ุงูุชูุงุนูุงุช ร 10`;
|
| 602 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 603 |
}
|
| 604 |
|
| 605 |
async function sendModeratorsReport() {
|
|
|
|
| 606 |
const msg = `๐ฎ <b>ุงูู
ุดุฑููู ูุงูุฃุนุถุงุก ุงูู
ู
ูุฒูู</b>\n` +
|
| 607 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 608 |
+
`${formatModerators()}\n` +
|
| 609 |
`โโโโโโโโโโโโโโโโโโโ`;
|
| 610 |
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 611 |
}
|
|
|
|
| 627 |
`โช๏ธ <b>ุงูู
ุดุงุฑูุงุช:</b> ${formatK(totalShares)}\n` +
|
| 628 |
`โ <b>ุงูู
ุชุงุจุนูู:</b> ${formatK(totalFollows)}\n` +
|
| 629 |
`๐ฌ <b>ุงูุชุนูููุงุช:</b> ${formatK(totalComments)}\n` +
|
| 630 |
+
`๐ <b>ุงููุฏุงูุง:</b> ${formatK(totalGifts)} ๐\n` +
|
| 631 |
+
`๐ฆ <b>ุงูุตูุงุฏูู:</b> ${formatK(totalEnvelopes)}\n` +
|
| 632 |
+
`๐ฐ <b>ุงูุนู
ูุงุช ุงูู
ูุฒุนุฉ:</b> ${formatK(totalCoinsGiven)}\n\n` +
|
| 633 |
`๐ฅ <b>ุนุฏุฏ ุงูุฏุงุนู
ูู:</b> ${Object.keys(giftersMap).length}\n` +
|
| 634 |
`๐ฌ <b>ุนุฏุฏ ุงูู
ุชูุงุนููู:</b> ${Object.keys(chattersMap).length}\n` +
|
| 635 |
`โ <b>ุนุฏุฏ ุงูู
ุชุงุจุนูู ุงูุฌุฏุฏ:</b> ${Object.keys(followersMap).length}\n` +
|
| 636 |
`๐ฎ <b>ุนุฏุฏ ุงูู
ุดุฑููู:</b> ${Object.keys(moderatorsMap).length}\n` +
|
| 637 |
+
`๐ <b>ูุงุฆุฒูู ุงูุตูุงุฏูู:</b> ${Object.keys(envelopeWinnersMap).length}\n` +
|
| 638 |
+
`๐ฐ <b>ูุงุฆุฒูู ุงูุนู
ูุงุช:</b> ${Object.keys(coinPurseWinnersMap).length}\n` +
|
| 639 |
`โโโโโโโโโโโโโโโโโโโ`;
|
| 640 |
await sendTelegram(msg, null, getMainButtons(), 'HTML', null, true);
|
| 641 |
}
|
|
|
|
| 661 |
await sendTelegram('โ๏ธ ูุง ููุฌุฏ ุฌููุฉ PK ูุดุทุฉ', null, getMainButtons(), 'HTML', null, true);
|
| 662 |
return;
|
| 663 |
}
|
|
|
|
| 664 |
const msg = `โ๏ธ <b>ุฏุงุนู
ูู ุฌููุฉ PK</b>\n` +
|
| 665 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 666 |
+
`${formatPKGifters()}\n` +
|
| 667 |
`โโโโโโโโโโโโโโโโโโโ`;
|
| 668 |
await sendTelegram(msg, null, getPKButtons(), 'HTML', null, true);
|
| 669 |
}
|
| 670 |
|
| 671 |
+
async function sendEnvelopesReport() {
|
| 672 |
+
const winners = formatEnvelopeWinners(10);
|
| 673 |
+
const msg = `๐๐ฆ <b>ุตูุงุฏูู ุงููุฏุงูุง - ุงููุงุฆุฒูู</b>\n` +
|
| 674 |
+
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 675 |
+
`${winners}\n` +
|
| 676 |
+
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 677 |
+
`๐ฆ ุฅุฌู
ุงูู ุงูุตูุงุฏูู: ${formatK(totalEnvelopes)}\n` +
|
| 678 |
+
`๐ฅ ุนุฏุฏ ุงููุงุฆุฒูู: ${Object.keys(envelopeWinnersMap).length}`;
|
| 679 |
+
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 680 |
+
}
|
| 681 |
+
|
| 682 |
+
async function sendCoinPurseReport() {
|
| 683 |
+
const winners = formatCoinPurseWinners(10);
|
| 684 |
+
const msg = `๐ฐ๐ <b>ุญููุจุฉ ุงูุนู
ูุงุช - ุงููุงุฆุฒูู</b>\n` +
|
| 685 |
+
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 686 |
+
`${winners}\n` +
|
| 687 |
+
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 688 |
+
`๐ฐ ุฅุฌู
ุงูู ุงูุนู
ูุงุช ุงูู
ูุฒุนุฉ: ${formatK(totalCoinsGiven)}\n` +
|
| 689 |
+
`๐ฅ ุนุฏุฏ ุงููุงุฆุฒูู: ${Object.keys(coinPurseWinnersMap).length}`;
|
| 690 |
+
await sendTelegram(msg, null, getStatsButtons(), 'HTML', null, true);
|
| 691 |
+
}
|
| 692 |
+
|
| 693 |
async function sendFinalReport() {
|
| 694 |
const duration = formatDuration(startTime);
|
| 695 |
const topGifterText = formatTopGifters(5);
|
| 696 |
const topActiveText = formatTopActive(5);
|
| 697 |
+
const envelopeWinners = formatEnvelopeWinners(5);
|
| 698 |
+
const coinWinners = formatCoinPurseWinners(5);
|
| 699 |
const avgViewers = viewerHistory.length > 0
|
| 700 |
? Math.round(viewerHistory.reduce((a, b) => a + b.viewers, 0) / viewerHistory.length)
|
| 701 |
: 0;
|
|
|
|
| 711 |
`โช๏ธ <b>ุฅุฌู
ุงูู ุงูู
ุดุงุฑูุงุช:</b> ${formatK(totalShares)}\n` +
|
| 712 |
`โ <b>ุฅุฌู
ุงูู ุงูู
ุชุงุจุนูู:</b> ${formatK(totalFollows)}\n` +
|
| 713 |
`๐ฌ <b>ุฅุฌู
ุงูู ุงูุชุนูููุงุช:</b> ${formatK(totalComments)}\n` +
|
| 714 |
+
`๐ <b>ุฅุฌู
ุงูู ุงููุฏุงูุง:</b> ${formatK(totalGifts)} ๐\n` +
|
| 715 |
+
`๐ฆ <b>ุฅุฌู
ุงูู ุงูุตูุงุฏู๏ฟฝ๏ฟฝ:</b> ${formatK(totalEnvelopes)}\n` +
|
| 716 |
+
`๐ฐ <b>ุฅุฌู
ุงูู ุงูุนู
ูุงุช:</b> ${formatK(totalCoinsGiven)}\n\n` +
|
| 717 |
`๐ <b>ููุญุฉ ุงูุดุฑู (ุงูุฏุงุนู
ูู):</b>\n${topGifterText}\n\n` +
|
| 718 |
+
`๐ฅ <b>ุฃูุซุฑ ุงูู
ุชูุงุนููู:</b>\n${topActiveText}\n\n` +
|
| 719 |
+
`๐ <b>ูุงุฆุฒูู ุงูุตูุงุฏูู:</b>\n${envelopeWinners}\n\n` +
|
| 720 |
+
`๐ฐ <b>ูุงุฆุฒูู ุงูุนู
ูุงุช:</b>\n${coinWinners}\n` +
|
| 721 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 722 |
`๐ค ุงูุจูุช ูู ูุถุน ุงูุงูุชุธุงุฑ...`;
|
| 723 |
await sendTelegram(msg, null, getDisconnectedButtons(), 'HTML', null, false);
|
|
|
|
| 728 |
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 729 |
async function notifyLike(nickname, likeCount, userId) {
|
| 730 |
if (!isLive) return;
|
| 731 |
+
if (!likersMap[userId]) likersMap[userId] = { id: userId, name: nickname, count: 0 };
|
|
|
|
|
|
|
| 732 |
likersMap[userId].count += likeCount;
|
| 733 |
totalLikes += likeCount;
|
| 734 |
|
| 735 |
+
if (pkActive) pkInfo.ourScore += likeCount;
|
| 736 |
|
| 737 |
if (likeCount >= CONFIG.LIKE_BATCH_THRESHOLD) {
|
| 738 |
if (isOnCooldown('like', userId, 30000)) return;
|
|
|
|
| 747 |
if (!isLive) return;
|
| 748 |
if (isOnCooldown('gift', userId, CONFIG.GIFT_COOLDOWN_MS)) return;
|
| 749 |
|
| 750 |
+
if (!giftersMap[userId]) giftersMap[userId] = { id: userId, name: nickname, coins: 0 };
|
|
|
|
|
|
|
| 751 |
giftersMap[userId].coins += totalCost;
|
| 752 |
totalGifts += totalCost;
|
| 753 |
|
| 754 |
if (pkActive) {
|
| 755 |
pkInfo.ourScore += totalCost;
|
| 756 |
+
if (!pkInfo.pkGifts[userId]) pkInfo.pkGifts[userId] = { id: userId, name: nickname, coins: 0 };
|
|
|
|
|
|
|
| 757 |
pkInfo.pkGifts[userId].coins += totalCost;
|
| 758 |
}
|
| 759 |
|
|
|
|
| 773 |
if (!isLive) return;
|
| 774 |
if (isOnCooldown('follow', userId, 10000)) return;
|
| 775 |
|
| 776 |
+
if (!followersMap[userId]) followersMap[userId] = { id: userId, name: nickname, count: 0 };
|
|
|
|
|
|
|
| 777 |
followersMap[userId].count++;
|
| 778 |
totalFollows++;
|
| 779 |
|
|
|
|
| 787 |
if (!isLive) return;
|
| 788 |
if (isOnCooldown('share', userId, 15000)) return;
|
| 789 |
|
| 790 |
+
if (!sharersMap[userId]) sharersMap[userId] = { id: userId, name: nickname, count: 0 };
|
|
|
|
|
|
|
| 791 |
sharersMap[userId].count++;
|
| 792 |
totalShares++;
|
| 793 |
|
|
|
|
| 797 |
);
|
| 798 |
}
|
| 799 |
|
| 800 |
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 801 |
+
// โโโโโโโ๏ธ ู
ุนุงูุฌุฉ ุงูุฏุฑุฏุดุฉ - ุจุฏูู ุญุธุฑ ููุชุฎุฒูู โโโโโโโโ
|
| 802 |
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 803 |
+
function handleChat(data) {
|
| 804 |
+
if (!isLive) return;
|
| 805 |
+
const userId = data.userId || data.uniqueId;
|
| 806 |
+
const nickname = data.nickname || data.uniqueId || 'ู
ุฌููู';
|
| 807 |
+
const rawText = data.comment || data.message || '';
|
| 808 |
+
const text = cleanChatMessage(rawText);
|
| 809 |
|
| 810 |
if (!text || isSpamMessage(text)) return;
|
|
|
|
| 811 |
|
| 812 |
+
if (!chattersMap[userId]) chattersMap[userId] = { id: userId, name: nickname, count: 0 };
|
|
|
|
|
|
|
| 813 |
chattersMap[userId].count++;
|
| 814 |
totalComments++;
|
| 815 |
|
| 816 |
topChatMessages.unshift({ name: nickname, text: text, time: Date.now() });
|
| 817 |
+
if (topChatMessages.length > 50) topChatMessages = topChatMessages.slice(0, 50);
|
|
|
|
|
|
|
| 818 |
|
| 819 |
+
if (isOnCooldown('chat', userId, CONFIG.CHAT_COOLDOWN_MS)) return;
|
|
|
|
| 820 |
|
| 821 |
+
const importantKeywords = ['ุณุคุงู', 'ุฌูุงุจ', 'ููุง', 'ู
ุฑุญุจุง', 'ุชูุงุนู', 'ุฏุนู
', 'pk', 'ุจูุฌ', 'ุชุตููุช'];
|
| 822 |
+
const isImportant = text.length > 25 || importantKeywords.some(kw => text.toLowerCase().includes(kw));
|
| 823 |
+
|
| 824 |
+
if (isImportant) {
|
| 825 |
+
sendTelegram(
|
| 826 |
`๐ฌ <b>${escapeHtml(nickname)}:</b> ${escapeHtml(text)}`,
|
| 827 |
null, null, 'HTML', null, true
|
| 828 |
);
|
|
|
|
| 831 |
|
| 832 |
async function notifyModerator(data) {
|
| 833 |
if (!isLive) return;
|
| 834 |
+
const userId = data.userId || data.uniqueId;
|
| 835 |
+
const nickname = data.nickname || data.uniqueId || 'ู
ุฌููู';
|
| 836 |
|
| 837 |
if (!moderatorsMap[userId]) {
|
| 838 |
moderatorsMap[userId] = {
|
| 839 |
id: userId,
|
| 840 |
name: nickname,
|
| 841 |
joinTime: Date.now(),
|
| 842 |
+
isModerator: data.isModerator || data.userDetails?.isModerator || false,
|
| 843 |
};
|
| 844 |
await sendTelegram(
|
| 845 |
`๐ฎโจ <b>${escapeHtml(nickname)}</b> ุฏุฎู ุงูุจุซ${data.isModerator ? ' [ู
ุดุฑู]' : ''}!`,
|
|
|
|
| 848 |
}
|
| 849 |
}
|
| 850 |
|
| 851 |
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 852 |
+
// โโโโโโโ๏ธ ู
ุนุงูุฌุฉ ุงูุตูุงุฏูู (Envelope) โโโโโโโโ
|
| 853 |
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 854 |
+
function handleEnvelope(data) {
|
| 855 |
+
if (!isLive) return;
|
| 856 |
+
const userId = data.userId || data.uniqueId;
|
| 857 |
+
const nickname = data.nickname || data.uniqueId || 'ู
ุฌููู';
|
| 858 |
+
const envelopeId = data.envelopeId || data.giftId || 'unknown';
|
| 859 |
+
|
| 860 |
+
totalEnvelopes++;
|
| 861 |
+
|
| 862 |
+
if (!envelopeWinnersMap[userId]) {
|
| 863 |
+
envelopeWinnersMap[userId] = { id: userId, name: nickname, count: 0 };
|
| 864 |
+
}
|
| 865 |
+
envelopeWinnersMap[userId].count++;
|
| 866 |
+
|
| 867 |
+
if (isOnCooldown('envelope', envelopeId, 5000)) return;
|
| 868 |
+
|
| 869 |
+
sendTelegram(
|
| 870 |
+
`๐๐ฆ <b>${escapeHtml(nickname)}</b> ุญุตู ุนูู ุตูุฏูู ูุฏุงูุง! ๐`,
|
| 871 |
+
null, null, 'HTML', null, true
|
| 872 |
+
);
|
| 873 |
+
}
|
| 874 |
+
|
| 875 |
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 876 |
+
// โโโโโโโ๏ธ ู
ุนุงูุฌุฉ ุญููุจุฉ ุงูุนู
ูุงุช (Coin Purse) โโโโโโโโ
|
| 877 |
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 878 |
+
function handleCoinPurse(data) {
|
| 879 |
+
if (!isLive) return;
|
| 880 |
+
const userId = data.userId || data.uniqueId;
|
| 881 |
+
const nickname = data.nickname || data.uniqueId || 'ู
ุฌููู';
|
| 882 |
+
const coins = data.coins || data.diamondCount || data.amount || 1;
|
| 883 |
+
const purseId = data.purseId || data.giftId || 'unknown';
|
| 884 |
+
|
| 885 |
+
totalCoinsGiven += coins;
|
| 886 |
+
|
| 887 |
+
if (!coinPurseWinnersMap[userId]) {
|
| 888 |
+
coinPurseWinnersMap[userId] = { id: userId, name: nickname, coins: 0 };
|
| 889 |
+
}
|
| 890 |
+
coinPurseWinnersMap[userId].coins += coins;
|
| 891 |
+
|
| 892 |
+
if (isOnCooldown('coinPurse', purseId, 5000)) return;
|
| 893 |
+
|
| 894 |
+
sendTelegram(
|
| 895 |
+
`๐ฐ๐ <b>${escapeHtml(nickname)}</b> ุญุตู ุนูู <b>${formatK(coins)}</b> ุนู
ูุฉ ู
ู ุญููุจุฉ ุงูุนู
ูุงุช! โจ`,
|
| 896 |
+
null, null, 'HTML', null, true
|
| 897 |
+
);
|
| 898 |
+
}
|
| 899 |
+
|
| 900 |
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 901 |
+
// โโโโโโโ๏ธ ู
ุนุงูุฌุฉ PK / Battle โโโโโโโโ
|
| 902 |
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 903 |
+
function handleBattleStart(data) {
|
| 904 |
+
const battleUsers = data.battleUsers || [];
|
| 905 |
+
let opponentName = 'ู
ุฌููู';
|
| 906 |
+
let opponentUserId = '';
|
| 907 |
+
|
| 908 |
+
if (battleUsers.length >= 2) {
|
| 909 |
+
const opponent = battleUsers.find(u => u.userId !== data.userId) || battleUsers[1];
|
| 910 |
+
opponentName = opponent.nickname || opponent.uniqueId || 'ู
ุฌููู';
|
| 911 |
+
opponentUserId = opponent.userId || '';
|
| 912 |
+
}
|
| 913 |
+
|
| 914 |
pkActive = true;
|
| 915 |
pkInfo = {
|
| 916 |
+
opponentName: opponentName,
|
| 917 |
+
opponentUserId: opponentUserId,
|
|
|
|
| 918 |
ourScore: 0,
|
| 919 |
theirScore: 0,
|
| 920 |
startTime: new Date(),
|
|
|
|
| 925 |
`โโโโโโโโโโโโโโโโโโโ\n` +
|
| 926 |
`๐ฅ <b>ุงูู
ูุงูุณ:</b> ${escapeHtml(opponentName)}\n\n` +
|
| 927 |
`ุงูููุฒ ูุญุชุงุฌ ูููุฉ ุงูุฃุจุทุงู! ุดุฏูุง ุงูุญูู.. ๐`;
|
| 928 |
+
sendTelegram(msg, null, getPKButtons(), 'HTML', null, false);
|
| 929 |
}
|
| 930 |
|
| 931 |
+
function handleBattleEnd(data) {
|
| 932 |
+
if (!pkActive) return;
|
| 933 |
pkActive = false;
|
| 934 |
+
|
| 935 |
const bar = generateProgressBar(pkInfo.ourScore, pkInfo.theirScore, 10);
|
| 936 |
+
const winner = data.winnerUserId === CONFIG.TIKTOK_USERNAME ? 'ูุญู' :
|
| 937 |
+
data.winnerUserId === pkInfo.opponentUserId ? pkInfo.opponentName : 'ุชุนุงุฏู';
|
| 938 |
+
const result = winner === 'ุชุนุงุฏู' ? '๐ค ุชุนุงุฏู' : winner === 'ูุญู' ? '๐ ูุฒูุง!' : '๐ข ุฎุณุฑูุง';
|
| 939 |
const pkGifters = formatPKGifters();
|
| 940 |
|
| 941 |
const msg = `๐โ๏ธ <b>ุงูุชูุช ุงูู
ูุงุฌูุฉ!</b>\n` +
|
|
|
|
| 946 |
`${bar}\n\n` +
|
| 947 |
`๐ <b>ุฏุงุนู
ูู ุงูุฌููุฉ:</b>\n${pkGifters}\n\n` +
|
| 948 |
`โจ ุดูุฑุงู ููู ู
ู ุณุงูู
ูู ูุฐู ุงูุฌููุฉ!`;
|
| 949 |
+
sendTelegram(msg, null, getMainButtons(), 'HTML', null, false);
|
| 950 |
|
| 951 |
+
pkInfo = { opponentName: '', opponentUserId: '', ourScore: 0, theirScore: 0, startTime: null, pkGifts: {} };
|
| 952 |
+
}
|
| 953 |
+
|
| 954 |
+
function handleBattleUpdate(data) {
|
| 955 |
+
if (!pkActive) return;
|
| 956 |
+
const battleUsers = data.battleUsers || [];
|
| 957 |
+
if (battleUsers.length >= 2) {
|
| 958 |
+
const us = battleUsers.find(u => u.userId !== pkInfo.opponentUserId) || battleUsers[0];
|
| 959 |
+
const them = battleUsers.find(u => u.userId === pkInfo.opponentUserId) || battleUsers[1];
|
| 960 |
+
pkInfo.ourScore = us?.points || pkInfo.ourScore;
|
| 961 |
+
pkInfo.theirScore = them?.points || pkInfo.theirScore;
|
| 962 |
+
}
|
| 963 |
}
|
| 964 |
|
| 965 |
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 966 |
+
// โโโโโโโ๏ธ ุฅุดุนุงุฑุงุช ุงูุจุซ โโโโโโโโ
|
| 967 |
+
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 968 |
async function notifyStreamStart(state) {
|
| 969 |
isLive = true;
|
| 970 |
const roomInfo = state.roomInfo || {};
|
|
|
|
| 1014 |
}
|
| 1015 |
|
| 1016 |
function setupEvents(connection) {
|
| 1017 |
+
// Room User
|
| 1018 |
connection.on('roomUser', (data) => {
|
| 1019 |
const viewers = data.viewerCount || 0;
|
| 1020 |
if (viewers > maxViewers) maxViewers = viewers;
|
|
|
|
| 1022 |
if (viewerHistory.length > 200) viewerHistory.shift();
|
| 1023 |
});
|
| 1024 |
|
| 1025 |
+
// Like
|
| 1026 |
connection.on('like', (data) => {
|
| 1027 |
const likes = data.likeCount || 0;
|
| 1028 |
+
const userId = data.userId || data.uniqueId;
|
| 1029 |
const nickname = data.nickname || data.uniqueId;
|
| 1030 |
notifyLike(nickname, likes, userId);
|
| 1031 |
});
|
| 1032 |
|
| 1033 |
+
// Social = Follow + Share
|
| 1034 |
+
connection.on('social', (data) => {
|
| 1035 |
+
const userId = data.userId || data.uniqueId;
|
| 1036 |
const nickname = data.nickname || data.uniqueId;
|
| 1037 |
+
const displayType = data.displayType || '';
|
| 1038 |
+
|
| 1039 |
+
if (displayType.includes('follow') || displayType.includes('ู
ุชุงุจ')) {
|
| 1040 |
+
notifyFollow(nickname, userId);
|
| 1041 |
+
} else if (displayType.includes('share') || displayType.includes('ู
ุดุงุฑ')) {
|
| 1042 |
+
notifyShare(nickname, userId);
|
| 1043 |
+
} else {
|
| 1044 |
+
notifyFollow(nickname, userId);
|
| 1045 |
+
}
|
| 1046 |
});
|
| 1047 |
|
| 1048 |
+
// Chat
|
| 1049 |
connection.on('chat', (data) => {
|
| 1050 |
+
handleChat(data);
|
| 1051 |
});
|
| 1052 |
|
| 1053 |
+
// Member
|
| 1054 |
connection.on('member', (data) => {
|
| 1055 |
notifyModerator(data);
|
| 1056 |
});
|
| 1057 |
|
| 1058 |
+
// Gift
|
| 1059 |
connection.on('gift', (data) => {
|
| 1060 |
if (data.giftType === 1 && !data.repeatEnd) return;
|
| 1061 |
const giftCost = (data.diamondCount || 0) * (data.repeatCount || 1);
|
| 1062 |
+
const userId = data.userId || data.uniqueId;
|
| 1063 |
const nickname = data.nickname || data.uniqueId;
|
| 1064 |
notifyGift(nickname, data.giftName || 'Gift', data.diamondCount || 0, data.repeatCount || 1, giftCost, userId);
|
| 1065 |
});
|
| 1066 |
|
| 1067 |
+
// Envelope - ุตูุงุฏูู ุงููุฏุงูุง
|
| 1068 |
+
connection.on('envelope', (data) => {
|
| 1069 |
+
console.log('[Envelope] event:', JSON.stringify(data).substring(0, 300));
|
| 1070 |
+
handleEnvelope(data);
|
| 1071 |
});
|
| 1072 |
|
| 1073 |
+
// Subscribe / Coin Purse - ุญููุจุฉ ุงูุนู
ูุงุช
|
| 1074 |
+
connection.on('subscribe', (data) => {
|
| 1075 |
+
console.log('[Subscribe/CoinPurse] event:', JSON.stringify(data).substring(0, 300));
|
| 1076 |
+
handleCoinPurse(data);
|
| 1077 |
});
|
| 1078 |
|
| 1079 |
+
// PK / Battle events
|
| 1080 |
+
connection.on('linkMicBattle', (data) => {
|
| 1081 |
+
console.log('[Battle] linkMicBattle event:', JSON.stringify(data).substring(0, 200));
|
| 1082 |
+
handleBattleStart(data);
|
| 1083 |
});
|
| 1084 |
|
| 1085 |
+
connection.on('linkMicArmies', (data) => {
|
| 1086 |
+
console.log('[Battle] linkMicArmies event:', JSON.stringify(data).substring(0, 200));
|
| 1087 |
+
handleBattleUpdate(data);
|
| 1088 |
+
});
|
| 1089 |
+
|
| 1090 |
+
// Stream End
|
| 1091 |
connection.on('streamEnd', async () => {
|
| 1092 |
isConnected = false;
|
| 1093 |
isLive = false;
|
|
|
|
| 1096 |
reconnectTimer = setTimeout(startRadar, 60000);
|
| 1097 |
});
|
| 1098 |
|
| 1099 |
+
// Disconnected
|
| 1100 |
+
connection.on('disconnected', () => {
|
| 1101 |
+
console.log('[TikTok] Disconnected from stream');
|
| 1102 |
+
isConnected = false;
|
| 1103 |
+
isLive = false;
|
| 1104 |
+
});
|
| 1105 |
+
|
| 1106 |
+
// Error
|
| 1107 |
connection.on('error', (err) => {
|
| 1108 |
console.error(`[TikTok] Error: ${err.message}`);
|
| 1109 |
});
|
|
|
|
| 1119 |
reconnectAttempt++;
|
| 1120 |
|
| 1121 |
if (reconnectAttempt === 1) {
|
| 1122 |
+
maxViewers = 0; totalLikes = 0; totalShares = 0; totalGifts = 0;
|
| 1123 |
+
totalFollows = 0; totalComments = 0; totalEnvelopes = 0; totalCoinsGiven = 0;
|
| 1124 |
+
giftersMap = {}; likersMap = {}; sharersMap = {}; followersMap = {};
|
| 1125 |
+
chattersMap = {}; moderatorsMap = {}; envelopeWinnersMap = {}; coinPurseWinnersMap = {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1126 |
topChatMessages = [];
|
| 1127 |
viewerHistory = [];
|
| 1128 |
pkActive = false;
|
| 1129 |
+
pkInfo = { opponentName: '', opponentUserId: '', ourScore: 0, theirScore: 0, startTime: null, pkGifts: {} };
|
| 1130 |
+
cooldowns.chat.clear(); cooldowns.gift.clear(); cooldowns.like.clear();
|
| 1131 |
+
cooldowns.follow.clear(); cooldowns.share.clear(); cooldowns.envelope.clear(); cooldowns.coinPurse.clear();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1132 |
}
|
| 1133 |
|
| 1134 |
try {
|
|
|
|
| 1194 |
isConnected = false;
|
| 1195 |
isLive = false;
|
| 1196 |
if (tiktokConnection) {
|
| 1197 |
+
try { tiktokConnection.disconnect(); } catch (e) {}
|
|
|
|
|
|
|
| 1198 |
tiktokConnection = null;
|
| 1199 |
}
|
| 1200 |
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
|
|
| 1217 |
}
|
| 1218 |
|
| 1219 |
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1220 |
+
// โโโโโโโ๏ธ ุงูุฎุงุฏู
ุงูุฏุงุฎูู โโโโโโโโ
|
| 1221 |
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1222 |
const server = http.createServer((req, res) => {
|
| 1223 |
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
|
| 1224 |
const status = isLive ? '๐ด LIVE' : isConnected ? '๐ก CONNECTING' : 'โช WAITING';
|
| 1225 |
+
const pkStatus = pkActive ? ' | โ๏ธ PK' : '';
|
| 1226 |
+
res.end(`TikTok Radar Bot v4.2 | ${status}${pkStatus} | ${getBaghdadTime()} | @${CONFIG.TIKTOK_USERNAME}`);
|
| 1227 |
});
|
| 1228 |
|
| 1229 |
const PORT = process.env.PORT || 7860;
|
| 1230 |
server.listen(PORT, '0.0.0.0', () => {
|
| 1231 |
console.log(`
|
| 1232 |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1233 |
+
โ TikTok Radar Pro - Telegram Bot v4.2 (Royal Edition) โ
|
| 1234 |
โ โ
|
| 1235 |
โ ๐ค Telegram Bot Active โ
|
| 1236 |
โ ๐ก TikTok: @${CONFIG.TIKTOK_USERNAME.padEnd(45, ' ')}โ
|
|
|
|
| 1240 |
โ โ
|
| 1241 |
โ โจ Features: Anti-Spam | Smart Cooldowns | Deep Stats โ
|
| 1242 |
โ ๐ Gifts | โค๏ธ Likes | โช๏ธ Shares | ๐ฌ Chat | โ๏ธ PK โ
|
| 1243 |
+
โ ๐ฆ Envelopes | ๐ฐ Coin Purse โ
|
| 1244 |
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1245 |
`);
|
| 1246 |
|