This commit is contained in:
NAME
2026-05-13 11:49:16 +00:00
parent a7ba436169
commit 31129e23f6
4 changed files with 70 additions and 46 deletions
+4 -3
View File
@@ -1,12 +1,12 @@
// sqs.module.ts // sqs.module.ts
import { Module, Global } from '@nestjs/common'; import {Global, Module} from '@nestjs/common';
import { SqsService } from './sqs.service'; import {SqsService} from './sqs.service';
import {SqsPostService} from "./sqs.post.service"; import {SqsPostService} from "./sqs.post.service";
import {SqsPosterWorker} from "./sqs.poster.worker"; import {SqsPosterWorker} from "./sqs.poster.worker";
import {XPosterRouterService} from "../x-poster/x-poster.router.service";
import {XPosterModule} from "../x-poster/x-poster.module"; import {XPosterModule} from "../x-poster/x-poster.module";
import {FacebookApi} from "../x-poster/facebook.api"; import {FacebookApi} from "../x-poster/facebook.api";
import {NotifyService} from "../notify.service"; import {NotifyService} from "../notify.service";
import {XCacheService} from "../x-cache/x-cache.service";
@Global() @Global()
@Module({ @Module({
@@ -17,6 +17,7 @@ import {NotifyService} from "../notify.service";
SqsPosterWorker, SqsPosterWorker,
FacebookApi, FacebookApi,
NotifyService, NotifyService,
XCacheService,
], ],
exports: [SqsService], exports: [SqsService],
}) })
+9 -4
View File
@@ -5,6 +5,7 @@ import {SUPPORT_SOCIAL_PROVIDERS, XPosterRouterService, XStrategy} from "../x-po
import {rand} from "../helper"; import {rand} from "../helper";
import {FacebookApi} from "../x-poster/facebook.api"; import {FacebookApi} from "../x-poster/facebook.api";
import {NotifyService} from "../notify.service"; import {NotifyService} from "../notify.service";
import {XCacheService} from "../x-cache/x-cache.service";
@Injectable() @Injectable()
export class SqsPosterWorker { export class SqsPosterWorker {
@@ -15,6 +16,7 @@ export class SqsPosterWorker {
private readonly xRouterService: XPosterRouterService, private readonly xRouterService: XPosterRouterService,
private readonly facebookApi: FacebookApi, private readonly facebookApi: FacebookApi,
private readonly notifyService: NotifyService, private readonly notifyService: NotifyService,
private readonly xCacheService: XCacheService,
) { ) {
} }
@@ -23,10 +25,13 @@ export class SqsPosterWorker {
await this.notifyService.sendMessageToTele(`🚀 Worker started for ${await this.sqs.getQueueName()}`) await this.notifyService.sendMessageToTele(`🚀 Worker started for ${await this.sqs.getQueueName()}`)
//check cookie //check cookie
this.xRouterService.verifyCookie().catch((err) => { if (!await this.xCacheService.isXCookiesAlive()) {
console.error(`SqsPosterWorker_verifyCookie`); this.xRouterService.verifyCookie().catch((err) => {
console.error(err); console.error(`SqsPosterWorker_verifyCookie`);
}); console.error(err);
});
}
let ReceiptHandle = ''; let ReceiptHandle = '';
while (true) { while (true) {
+56 -38
View File
@@ -3,6 +3,8 @@ import {HttpException, Injectable, Logger, OnModuleDestroy, OnModuleInit,} from
import {Browser, BrowserContext, chromium, Page} from 'playwright'; import {Browser, BrowserContext, chromium, Page} from 'playwright';
import {rand} from "../helper"; import {rand} from "../helper";
import {getAccount} from "./utils/x-headers.util"; import {getAccount} from "./utils/x-headers.util";
import {XCacheService} from "../x-cache/x-cache.service";
import {NotifyService} from "../notify.service";
export interface BrowserAccount { export interface BrowserAccount {
accountId: string; accountId: string;
@@ -35,6 +37,12 @@ export class XBrowserService implements OnModuleInit, OnModuleDestroy {
private readonly MAX_CONTEXTS = 5; private readonly MAX_CONTEXTS = 5;
private readonly CONTEXT_TTL_MS = 15 * 60 * 1000; // 15 phút private readonly CONTEXT_TTL_MS = 15 * 60 * 1000; // 15 phút
constructor(
private readonly xCacheService: XCacheService,
private readonly notifyService: NotifyService,
) {
}
async onModuleInit() { async onModuleInit() {
// Lazy launch chỉ mở khi cần // Lazy launch chỉ mở khi cần
setInterval(() => this.cleanupStaleContexts(), 60_000); setInterval(() => this.cleanupStaleContexts(), 60_000);
@@ -141,7 +149,7 @@ export class XBrowserService implements OnModuleInit, OnModuleDestroy {
return ctx.newPage(); return ctx.newPage();
} }
async verifyCookie() { async verifyCookie(sendNotiWhenAlive = false): Promise<boolean> {
const page = await this.newPage(); const page = await this.newPage();
try { try {
@@ -151,25 +159,8 @@ export class XBrowserService implements OnModuleInit, OnModuleDestroy {
}); });
await page.waitForTimeout(2000 + (Math.random() + Math.random()) * 3000); await page.waitForTimeout(2000 + (Math.random() + Math.random()) * 3000);
await page.mouse.wheel(0, rand(300, 500)); await page.mouse.wheel(0, rand(300, 500));
// Detect login/challenge screen return await this.isCookieLive(page, sendNotiWhenAlive);
if (page.url().includes('/home')) {
this.logger.log('Cookies live');
return true;
// return {
// success: false,
// error: 'Redirected to login',
// needsRelogin: true,
// };
}
const isLoggedIn = await page
.locator('[data-testid="SideNav_AccountSwitcher_Button"], [data-testid="AppTabBar_Home_Link"]')
.first()
.isVisible()
.catch(() => false);
this.logger.log(`🔐 Session restore: ${isLoggedIn ? 'LOGGED IN' : 'GUEST (cookie có thể expired)'}`);
// await page.close();
return isLoggedIn;
} catch (er) { } catch (er) {
this.logger.error(`Browser verify cookie fail: ${er.message}`); this.logger.error(`Browser verify cookie fail: ${er.message}`);
return false; return false;
@@ -178,6 +169,49 @@ export class XBrowserService implements OnModuleInit, OnModuleDestroy {
} }
} }
async isCookieLive(page: Page, sendNotiWhenAlive = false): Promise<boolean> {
this.logger.debug('isCookieLive?');
if (page.url().includes('/home')) {
this.logger.log('Cookies live');
await this.xCacheService.setStateXCookiesIsSillALive();
if (sendNotiWhenAlive) {
await this.notifyService.sendMessageToTele('✅Verify cookie pass')
}
return true;
}
const isLoggedIn = await page
.locator('[data-testid="SideNav_AccountSwitcher_Button"], [data-testid="AppTabBar_Home_Link"]')
.first()
.isVisible()
.catch(() => false);
this.logger.log(`🔐 Session restore: ${isLoggedIn ? 'LOGGED IN' : 'GUEST (cookie có thể expired)'}`);
if (isLoggedIn) {
await this.xCacheService.setStateXCookiesIsSillALive();
if (sendNotiWhenAlive) {
await this.notifyService.sendMessageToTele('✅Verify cookie pass')
}
} else {
await this.xCacheService.setStateXCookiesIsDie();
await this.notifyService.sendUrgentMessageToTele('❌Cookie đã hết hạn vui lòng cập nhập để sử dụng.')
}
return isLoggedIn;
}
// async actVerifyCookie(): Promise<any> {
// this.logger.debug('==> actVerifyCookie');
// // const isAlive = await this.cookieSvc.verifyCookie();
// const isAlive = await this.verifyCookie();
// if (!isAlive) {
// await this.xCacheService.setStateXCookiesIsDie();
// await this.notifyService.sendUrgentMessageToTele('❌Cookie đã hết hạn vui lòng cập nhập để sử dụng.')
// }
// await this.xCacheService.setStateXCookiesIsSillALive();
// await this.notifyService.sendMessageToTele('✅Verify cookie pass')
//
// return isAlive;
// }
async likeTweet(tweetUrl: string) { async likeTweet(tweetUrl: string) {
let page: Page | null = null; let page: Page | null = null;
@@ -285,12 +319,7 @@ export class XBrowserService implements OnModuleInit, OnModuleDestroy {
}; };
} }
const isLoggedIn = await page await this.isCookieLive(page, false);
.locator('[data-testid="SideNav_AccountSwitcher_Button"], [data-testid="AppTabBar_Home_Link"]')
.first()
.isVisible()
.catch(() => false);
this.logger.debug(`postTweet: ${isLoggedIn ? 'LOGGED IN' : 'LOGGED OUT'}`);
await page.mouse.wheel(200, rand(300, 800)); await page.mouse.wheel(200, rand(300, 800));
await page.waitForTimeout(rand(2000, 5000)); await page.waitForTimeout(rand(2000, 5000));
@@ -364,13 +393,7 @@ export class XBrowserService implements OnModuleInit, OnModuleDestroy {
await page.waitForTimeout(rand(2000, 4000)); await page.waitForTimeout(rand(2000, 4000));
const isLoggedIn = await page await this.isCookieLive(page, false);
.locator('[data-testid="SideNav_AccountSwitcher_Button"], [data-testid="AppTabBar_Home_Link"]')
.first()
.isVisible()
.catch(() => false);
this.logger.debug(`postQuote: ${isLoggedIn ? 'LOGGED IN' : 'LOGGED OUT'}`);
// ===== CHECK LOGIN ===== // ===== CHECK LOGIN =====
if (await page.locator('input[name="text"]').count()) { if (await page.locator('input[name="text"]').count()) {
@@ -520,12 +543,7 @@ export class XBrowserService implements OnModuleInit, OnModuleDestroy {
this.logger.debug(`đợi UI ổn...`) this.logger.debug(`đợi UI ổn...`)
await page.waitForSelector('article', {timeout: 7000}); await page.waitForSelector('article', {timeout: 7000});
const isLoggedIn = await page await this.isCookieLive(page, false);
.locator('[data-testid="SideNav_AccountSwitcher_Button"], [data-testid="AppTabBar_Home_Link"]')
.first()
.isVisible()
.catch(() => false);
this.logger.debug(`postReply: ${isLoggedIn ? 'LOGGED IN' : 'LOGGED OUT'}`);
// scroll nhẹ // scroll nhẹ
this.logger.debug(`scroll nhẹ ...`) this.logger.debug(`scroll nhẹ ...`)
+1 -1
View File
@@ -93,8 +93,8 @@ export class XPosterRouterService {
if (['cookie', 'browser'].includes(method)) { if (['cookie', 'browser'].includes(method)) {
if (!canUseCookie) { if (!canUseCookie) {
await this.notifyService.sendUrgentMessageToTele('❌ Vui lòng cập nhập cookie để sử dụng ');
this.logger.error('Cookie đã hết hạn, vui lòng cập nhập'); this.logger.error('Cookie đã hết hạn, vui lòng cập nhập');
await this.notifyService.sendUrgentMessageToTele('❌ Vui lòng cập nhập cookie để sử dụng ');
continue; continue;
} }
} }