feat: Add conclusion webhook support for final summary notifications (#355)

- Updated README.md to include new configuration options for conclusion webhook.
- Enhanced BrowserFunc.ts with improved error handling during page reloads.
- Implemented conclusionWebhook configuration in config.json.
- Refactored Login.ts to use Playwright types and improved passkey handling.
- Added safeClick method in SearchOnBing.ts to handle click timeouts and overlays.
- Introduced account summary collection in index.ts for reporting.
- Created ConclusionWebhook.ts to send structured summaries to a dedicated webhook.
- Updated TypeScript definitions for better type safety across the project.
This commit is contained in:
Light
2025-09-14 08:29:09 +02:00
committed by GitHub
parent 2e80266ad1
commit b66114d4dd
15 changed files with 637 additions and 91 deletions

View File

@@ -92,9 +92,32 @@ export default class BrowserFunc {
this.bot.log(this.bot.isMobile, 'DASHBOARD-DATA', 'Provided page did not equal dashboard page, redirecting to dashboard page')
await this.goHome(this.bot.homePage)
}
// Reload the page to get new data
await this.bot.homePage.reload({ waitUntil: 'domcontentloaded' })
let lastError: any = null
for (let attempt = 1; attempt <= 2; attempt++) {
try {
// Reload the page to get new data
await this.bot.homePage.reload({ waitUntil: 'domcontentloaded' })
lastError = null
break
} catch (re) {
lastError = re
const msg = (re instanceof Error ? re.message : String(re))
this.bot.log(this.bot.isMobile, 'GET-DASHBOARD-DATA', `Reload failed attempt ${attempt}: ${msg}`, 'warn')
// If page/context closed => bail early after first retry
if (msg.includes('has been closed')) {
if (attempt === 1) {
this.bot.log(this.bot.isMobile, 'GET-DASHBOARD-DATA', 'Page appears closed; trying one navigation fallback', 'warn')
try {
await this.goHome(this.bot.homePage)
} catch {/* ignore */}
} else {
break
}
}
if (attempt === 2 && lastError) throw lastError
await this.bot.utils.wait(1000)
}
}
const scriptContent = await this.bot.homePage.evaluate(() => {
const scripts = Array.from(document.querySelectorAll('script'))
@@ -108,7 +131,7 @@ export default class BrowserFunc {
}
// Extract the dashboard object from the script content
const dashboardData = await this.bot.homePage.evaluate(scriptContent => {
const dashboardData = await this.bot.homePage.evaluate((scriptContent: string) => {
// Extract the dashboard object using regex
const regex = /var dashboard = (\{.*?\});/s
const match = regex.exec(scriptContent)
@@ -272,7 +295,7 @@ export default class BrowserFunc {
const html = await page.content()
const $ = load(html)
const scriptContent = $('script').filter((index, element) => {
const scriptContent = $('script').filter((index: number, element: any) => {
return $(element).text().includes('_w.rewardsQuizRenderInfo')
}).text()
@@ -332,7 +355,7 @@ export default class BrowserFunc {
const html = await page.content()
const $ = load(html)
const element = $('.offer-cta').toArray().find(x => x.attribs.href?.includes(activity.offerId))
const element = $('.offer-cta').toArray().find((x: any) => x.attribs.href?.includes(activity.offerId))
if (element) {
selector = `a[href*="${element.attribs.href}"]`
}

View File

@@ -40,6 +40,24 @@ export default class BrowserUtil {
// Silent fail
}
}
// Handle blocking Bing privacy overlay intercepting clicks (#bnp_overlay_wrapper)
try {
const overlay = await page.locator('#bnp_overlay_wrapper').first()
if (await overlay.isVisible({ timeout: 500 }).catch(()=>false)) {
// Try common dismiss buttons inside overlay
const rejectBtn = await page.locator('#bnp_btn_reject, button[aria-label*="Reject" i]').first()
const acceptBtn = await page.locator('#bnp_btn_accept').first()
if (await rejectBtn.isVisible().catch(()=>false)) {
await rejectBtn.click({ timeout: 500 }).catch(()=>{})
this.bot.log(this.bot.isMobile, 'DISMISS-ALL-MESSAGES', 'Dismissed: Bing Overlay Reject')
} else if (await acceptBtn.isVisible().catch(()=>false)) {
await acceptBtn.click({ timeout: 500 }).catch(()=>{})
this.bot.log(this.bot.isMobile, 'DISMISS-ALL-MESSAGES', 'Dismissed: Bing Overlay Accept (fallback)')
}
await page.waitForTimeout(300)
}
} catch { /* ignore */ }
}
async getLatestTab(page: Page): Promise<Page> {