Files
trading_bot_v3/lib/enhanced-screenshot.ts
mindesbunister cf58d41444 🔐 Implement robust session persistence to avoid 'are you human' captcha checks
- Add comprehensive session persistence with cookies, localStorage, and sessionStorage
- Implement stealth browser features to reduce bot detection
- Add smartLogin() method that prioritizes saved sessions over fresh logins
- Create session management utilities (refresh, clear, test validity)
- Update enhanced screenshot service to use session persistence
- Add comprehensive documentation and test script
- Support manual login fallback when captcha is encountered
- Sessions stored in .tradingview-session/ directory for Docker compatibility

This solves the captcha problem by avoiding repeated logins through persistent sessions.
2025-07-12 21:39:53 +02:00

214 lines
7.4 KiB
TypeScript

import { tradingViewAutomation, TradingViewCredentials, NavigationOptions } from './tradingview-automation'
import fs from 'fs/promises'
import path from 'path'
export interface ScreenshotConfig {
symbol: string
timeframe: string
layouts?: string[] // Multiple chart layouts if needed
credentials?: TradingViewCredentials // Optional if using .env
}
export class EnhancedScreenshotService {
async captureWithLogin(config: ScreenshotConfig): Promise<string[]> {
const screenshotFiles: string[] = []
try {
// Ensure screenshots directory exists
const screenshotsDir = path.join(process.cwd(), 'screenshots')
await fs.mkdir(screenshotsDir, { recursive: true })
console.log('Initializing TradingView automation for Docker container...')
// Initialize automation with Docker-optimized settings
await tradingViewAutomation.init()
// Check if already logged in using session persistence
const alreadyLoggedIn = await tradingViewAutomation.isLoggedIn()
if (!alreadyLoggedIn) {
console.log('No active session found...')
// Try to use session persistence first to avoid captcha
const sessionTest = await tradingViewAutomation.testSessionPersistence()
if (sessionTest.isValid) {
console.log('✅ Valid session found - avoiding captcha!')
} else {
console.log('⚠️ No valid session - manual login may be required')
console.log('💡 Using smart login to handle captcha scenario...')
// Use smart login which prioritizes session persistence
const loginSuccess = await tradingViewAutomation.smartLogin(config.credentials)
if (!loginSuccess) {
throw new Error('Smart login failed - manual intervention may be required')
}
}
} else {
console.log('✅ Already logged in using saved session')
}
// Navigate to chart
const navOptions: NavigationOptions = {
symbol: config.symbol,
timeframe: config.timeframe,
waitForChart: true
}
console.log(`Navigating to ${config.symbol} chart...`)
const navSuccess = await tradingViewAutomation.navigateToChart(navOptions)
if (!navSuccess) {
throw new Error('Chart navigation failed')
}
// Wait for chart data to fully load
const chartLoaded = await tradingViewAutomation.waitForChartData()
if (!chartLoaded) {
console.warn('Chart data may not be fully loaded, proceeding with screenshot anyway')
}
// Take screenshot
const timestamp = Date.now()
const filename = `${config.symbol}_${config.timeframe}_${timestamp}_ai.png`
console.log(`Taking screenshot: ${filename}`)
const screenshotFile = await tradingViewAutomation.takeScreenshot(filename)
screenshotFiles.push(screenshotFile)
// If multiple layouts are needed, handle them here
if (config.layouts && config.layouts.length > 0) {
for (const layout of config.layouts) {
// Logic to switch to different layouts would go here
// This depends on your specific TradingView setup
const layoutFilename = `${config.symbol}_${config.timeframe}_${layout}_${timestamp}_ai.png`
const layoutScreenshot = await tradingViewAutomation.takeScreenshot(layoutFilename)
screenshotFiles.push(layoutScreenshot)
}
}
console.log(`Successfully captured ${screenshotFiles.length} screenshot(s)`)
return screenshotFiles
} catch (error) {
console.error('Enhanced screenshot capture failed:', error)
throw error
} finally {
// Always cleanup
await tradingViewAutomation.close()
}
}
async captureQuick(symbol: string, timeframe: string, credentials: TradingViewCredentials): Promise<string | null> {
try {
const config: ScreenshotConfig = {
symbol,
timeframe,
credentials
}
const screenshots = await this.captureWithLogin(config)
return screenshots.length > 0 ? screenshots[0] : null
} catch (error) {
console.error('Quick screenshot capture failed:', error)
return null
}
}
async captureMultipleTimeframes(
symbol: string,
timeframes: string[],
credentials: TradingViewCredentials
): Promise<string[]> {
const allScreenshots: string[] = []
for (const timeframe of timeframes) {
try {
console.log(`Capturing ${symbol} ${timeframe} chart...`)
const screenshot = await this.captureQuick(symbol, timeframe, credentials)
if (screenshot) {
allScreenshots.push(screenshot)
}
} catch (error) {
console.error(`Failed to capture ${symbol} ${timeframe}:`, error)
}
}
return allScreenshots
}
// Method to check if we can access TradingView in Docker environment
async healthCheck(): Promise<{ status: 'ok' | 'error'; message: string }> {
try {
console.log('Performing TradingView health check in Docker...')
await tradingViewAutomation.init()
// Navigate to TradingView homepage to check accessibility
const page = (tradingViewAutomation as any).page
if (!page) {
return { status: 'error', message: 'Failed to initialize browser page in Docker' }
}
await page.goto('https://www.tradingview.com/', {
waitUntil: 'networkidle',
timeout: 30000
})
const currentUrl = await tradingViewAutomation.getCurrentUrl()
if (currentUrl.includes('tradingview.com')) {
return { status: 'ok', message: 'TradingView is accessible from Docker container' }
} else {
return { status: 'error', message: 'TradingView is not accessible from Docker container' }
}
} catch (error) {
return { status: 'error', message: `TradingView health check failed: ${error}` }
} finally {
await tradingViewAutomation.close()
}
}
// Method to verify credentials in Docker environment
async verifyCredentials(credentials?: TradingViewCredentials): Promise<boolean> {
try {
console.log('Verifying TradingView credentials in Docker...')
await tradingViewAutomation.init()
const loginSuccess = await tradingViewAutomation.login(credentials)
return loginSuccess
} catch (error) {
console.error('Credential verification error in Docker:', error)
return false
} finally {
await tradingViewAutomation.close()
}
}
// Backward compatibility method - matches old tradingViewCapture.capture() API
async capture(symbol: string, filename: string, layouts?: string[], timeframe?: string): Promise<string[]> {
try {
console.log(`Starting Playwright-based capture for ${symbol} in Docker container`)
const config: ScreenshotConfig = {
symbol: symbol,
timeframe: timeframe || '5', // Default to 5-minute timeframe
layouts: layouts || []
}
const screenshots = await this.captureWithLogin(config)
// Return full paths to screenshots for backward compatibility
const screenshotsDir = path.join(process.cwd(), 'screenshots')
return screenshots.map(filename => path.join(screenshotsDir, filename))
} catch (error) {
console.error('Backward compatible capture failed:', error)
throw error
}
}
}
export const enhancedScreenshotService = new EnhancedScreenshotService()