/**
* Telegram WebView Injection Scripts
*
* JavaScript code injected into Telegram Web (web.telegram.org) to:
* 1. Show consent popup for user approval
* 2. Extract chat list and messages
* 3. Track progress during export
* 4. Send data back to React Native
*
* Telegram Web uses its own internal API which we can intercept.
*
* @reference ChatGPT implementation: src/utils/webviewScripts/chatgpt.ts
*
* NOTE: Telegram also has official Bot API and MTProto API for backend integration
* See: https://core.telegram.org/api
*/
/**
* Consent Popup Script
* Shows user consent UI before exporting data
*/
export declare const TELEGRAM_CONSENT_POPUP_SCRIPT = "\n(function() {\n try {\n const existing = document.getElementById('onairos-consent-overlay');\n if (existing) existing.remove();\n \n const overlay = document.createElement('div');\n overlay.id = 'onairos-consent-overlay';\n overlay.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.7);\n z-index: 999999;\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n `;\n \n const popup = document.createElement('div');\n popup.style.cssText = `\n background: white;\n border-radius: 16px;\n padding: 32px;\n max-width: 400px;\n width: 90%;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n `;\n \n popup.innerHTML = `\n
\n
\u2708\uFE0F
\n
\n Export Telegram Data?\n
\n
\n Allow Onairos to export your recent Telegram messages for analysis?\n
\n
\n \n \n
\n
\n `;\n \n overlay.appendChild(popup);\n document.body.appendChild(overlay);\n \n document.getElementById('onairos-deny').onclick = () => {\n overlay.remove();\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_CONSENT',\n status: 'denied'\n }));\n };\n \n document.getElementById('onairos-allow').onclick = () => {\n document.getElementById('onairos-allow').innerHTML = '\u23F3 Starting...';\n document.getElementById('onairos-allow').disabled = true;\n \n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_CONSENT',\n status: 'allowed'\n }));\n \n setTimeout(() => overlay.remove(), 500);\n };\n } catch (error) {\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_CONSENT',\n status: 'error',\n message: error.message\n }));\n }\n})();\ntrue;\n";
/**
* Export Script - Telegram Web data extraction
*
* ============================================================
* TELEGRAM MTProto API REFERENCE (used internally by Telegram Web)
* ============================================================
*
* Method: messages.getDialogs
* - Returns user's dialog list (chats, groups, channels)
* - Parameters: flags, exclude_pinned, folder_id, offset_date, offset_id,
* offset_peer, limit, hash
* - Returns: messages.Dialogs (dialogs, messages, chats, users arrays)
*
* Method: messages.getHistory
* - Returns messages from a peer (chat/user/channel)
* - Parameters: peer, offset_id, offset_date, add_offset, limit, max_id, min_id, hash
* - Returns: messages.Messages
*
* Telegram Web stores MTProto responses in IndexedDB:
* - 'tweb' database (Telegram Web K)
* - Contains: dialogs, messages, users, chats stores
*
* @see https://core.telegram.org/method/messages.getDialogs
* @see https://core.telegram.org/method/messages.getHistory
* ============================================================
*/
export declare const TELEGRAM_EXPORT_SCRIPT = "\n(function() {\n try {\n console.log('\uD83D\uDD04 [TELEGRAM] Script version: SDK_V2_MTPROTO');\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'DEBUG_LOG',\n message: 'Telegram Script version: SDK_V2_MTPROTO loaded'\n }));\n \n if (!document.body) {\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_EXPORT_ERROR',\n message: 'Page not ready'\n }));\n return;\n }\n\n // ============================================================\n // TELEGRAM WEB EXTRACTION CONFIG\n // Based on MTProto API Layer 214+\n // ============================================================\n const TELEGRAM_CONFIG = {\n // Telegram Web URLs\n webUrl: 'https://web.telegram.org',\n \n // IndexedDB database names used by different Telegram Web versions\n // These databases cache MTProto API responses\n indexedDBConfig: {\n // Telegram Web K (most common, what web.telegram.org/k/ uses)\n k: {\n dbName: 'tweb',\n stores: {\n dialogs: 'dialogs', // From messages.getDialogs\n messages: 'messages', // From messages.getHistory\n users: 'users', // User entities\n chats: 'chats', // Chat/Channel entities\n peers: 'peers', // Peer mappings\n session: 'session', // Auth session\n }\n },\n // Telegram Web A (React version)\n a: {\n dbName: 'telegram-t',\n stores: {\n chats: 'chats',\n messages: 'messages',\n }\n },\n // Alternative storage (keyval)\n keyval: {\n dbName: 'keyval-store',\n stores: {}\n }\n },\n \n // MTProto entity types (from API)\n entityTypes: {\n User: 'User',\n Chat: 'Chat', // Basic group\n Channel: 'Channel', // Channel or Supergroup\n },\n \n // Check if user is logged in\n // Telegram Web stores auth keys in localStorage\n isLoggedIn: () => {\n // DC auth keys (MTProto data centers)\n const dc2AuthKey = localStorage.getItem('dc2_auth_key');\n const userAuth = localStorage.getItem('user_auth');\n \n // Alternative: check for session in IndexedDB\n // Or check DOM for chat list presence\n const hasChats = document.querySelector('[class*=\"chat-list\"]') ||\n document.querySelector('[class*=\"ChatList\"]') ||\n document.querySelector('.dialogs-container') ||\n document.querySelector('[class*=\"LeftColumn\"]');\n \n return !!(dc2AuthKey || userAuth || hasChats);\n },\n \n // Extract user ID from cached auth data\n getUserId: () => {\n try {\n // Primary: user_auth localStorage key\n const userAuth = localStorage.getItem('user_auth');\n if (userAuth) {\n const parsed = JSON.parse(userAuth);\n return parsed.id || parsed.user_id;\n }\n \n // Fallback: Check dc_auth_* pattern\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.includes('user')) {\n try {\n const val = JSON.parse(localStorage.getItem(key));\n if (val && val.id) return val.id;\n } catch (e) {}\n }\n }\n \n // Mini App context (if opened as webapp)\n if (window.Telegram && window.Telegram.WebApp) {\n return window.Telegram.WebApp.initDataUnsafe?.user?.id;\n }\n } catch (e) {\n console.log('[TELEGRAM] Could not extract user ID:', e.message);\n }\n return null;\n }\n };\n // ============================================================\n\n console.log('\uD83D\uDE80 [TELEGRAM] Starting MTProto data extraction...');\n\n (async () => {\n try {\n // STEP 1: Check login status\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_EXPORT_PROGRESS',\n stage: 'checking_auth',\n progress: 5,\n message: 'Checking MTProto authentication...'\n }));\n\n const isLoggedIn = TELEGRAM_CONFIG.isLoggedIn();\n console.log('[TELEGRAM] Logged in:', isLoggedIn);\n \n if (!isLoggedIn) {\n throw new Error('User not logged in to Telegram Web. Please log in first.');\n }\n\n const userId = TELEGRAM_CONFIG.getUserId();\n console.log('[TELEGRAM] User ID:', userId);\n\n // STEP 2: Read from IndexedDB (cached MTProto responses)\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_EXPORT_PROGRESS',\n stage: 'fetching_dialogs',\n progress: 15,\n message: 'Reading dialogs from cache (messages.getDialogs)...'\n }));\n\n let dialogs = [];\n let messages = [];\n let users = [];\n let chats = [];\n \n // Try to read from IndexedDB - Telegram Web caches MTProto responses here\n console.log('[TELEGRAM] Reading IndexedDB cache...');\n \n const dbConfigs = [\n TELEGRAM_CONFIG.indexedDBConfig.k,\n TELEGRAM_CONFIG.indexedDBConfig.a,\n ];\n \n for (const dbConfig of dbConfigs) {\n if (dialogs.length > 0) break;\n \n try {\n const dbRequest = indexedDB.open(dbConfig.dbName);\n \n await new Promise((resolve, reject) => {\n dbRequest.onerror = () => {\n console.log('[TELEGRAM] Cannot open DB:', dbConfig.dbName);\n resolve();\n };\n \n dbRequest.onsuccess = async () => {\n const db = dbRequest.result;\n const storeNames = [...db.objectStoreNames];\n console.log('[TELEGRAM] Opened DB:', dbConfig.dbName, 'Stores:', storeNames);\n \n // Read dialogs (from messages.getDialogs cache)\n if (storeNames.includes('dialogs') || storeNames.includes('chats')) {\n const storeName = storeNames.includes('dialogs') ? 'dialogs' : 'chats';\n try {\n const tx = db.transaction(storeName, 'readonly');\n const store = tx.objectStore(storeName);\n const getAllReq = store.getAll();\n \n await new Promise((res, rej) => {\n getAllReq.onsuccess = () => {\n dialogs = getAllReq.result || [];\n console.log('[TELEGRAM] Found', dialogs.length, 'dialogs in', storeName);\n res();\n };\n getAllReq.onerror = () => res();\n });\n } catch (e) {\n console.log('[TELEGRAM] Error reading dialogs:', e.message);\n }\n }\n \n // Read messages (from messages.getHistory cache)\n if (storeNames.includes('messages')) {\n try {\n const tx = db.transaction('messages', 'readonly');\n const store = tx.objectStore('messages');\n const getAllReq = store.getAll();\n \n await new Promise((res, rej) => {\n getAllReq.onsuccess = () => {\n messages = getAllReq.result || [];\n console.log('[TELEGRAM] Found', messages.length, 'messages');\n res();\n };\n getAllReq.onerror = () => res();\n });\n } catch (e) {\n console.log('[TELEGRAM] Error reading messages:', e.message);\n }\n }\n \n // Read users (entity cache)\n if (storeNames.includes('users')) {\n try {\n const tx = db.transaction('users', 'readonly');\n const store = tx.objectStore('users');\n const getAllReq = store.getAll();\n \n await new Promise((res, rej) => {\n getAllReq.onsuccess = () => {\n users = getAllReq.result || [];\n console.log('[TELEGRAM] Found', users.length, 'users');\n res();\n };\n getAllReq.onerror = () => res();\n });\n } catch (e) {}\n }\n \n // Read chats/channels (entity cache)\n if (storeNames.includes('chats') && storeNames.includes('dialogs')) {\n try {\n const tx = db.transaction('chats', 'readonly');\n const store = tx.objectStore('chats');\n const getAllReq = store.getAll();\n \n await new Promise((res, rej) => {\n getAllReq.onsuccess = () => {\n chats = getAllReq.result || [];\n console.log('[TELEGRAM] Found', chats.length, 'chats/channels');\n res();\n };\n getAllReq.onerror = () => res();\n });\n } catch (e) {}\n }\n \n db.close();\n resolve();\n };\n });\n \n } catch (dbError) {\n console.log('[TELEGRAM] DB error:', dbConfig.dbName, dbError.message);\n }\n }\n\n // Fallback: Scrape from DOM if IndexedDB didn't work\n if (dialogs.length === 0) {\n console.log('[TELEGRAM] IndexedDB empty, falling back to DOM scraping...');\n \n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_EXPORT_PROGRESS',\n stage: 'scraping_dom',\n progress: 30,\n message: 'Reading visible chats from UI...'\n }));\n \n // Extract chat list from DOM (matches Telegram Web K structure)\n const chatElements = document.querySelectorAll(\n '[data-peer-id], ' +\n '.chatlist-chat, ' +\n '[class*=\"ListItem\"][class*=\"Chat\"], ' +\n '.Dialog, ' +\n '[class*=\"chat-list\"] > div'\n );\n \n chatElements.forEach((el, idx) => {\n const peerId = el.getAttribute('data-peer-id');\n const titleEl = el.querySelector(\n '.peer-title, ' +\n '[class*=\"title\"]:not([class*=\"subtitle\"]), ' +\n '.name, ' +\n '[class*=\"ListItem-title\"]'\n );\n const lastMsgEl = el.querySelector(\n '.last-message, ' +\n '[class*=\"subtitle\"], ' +\n '[class*=\"LastMessage\"]'\n );\n const unreadBadge = el.querySelector(\n '.unread-count, ' +\n '[class*=\"badge\"], ' +\n '[class*=\"unread\"]'\n );\n \n if (titleEl) {\n const unreadCount = unreadBadge ? parseInt(unreadBadge.textContent) || 0 : 0;\n \n dialogs.push({\n id: peerId || 'chat-' + idx,\n title: titleEl.textContent?.trim() || 'Unknown Chat',\n lastMessage: lastMsgEl?.textContent?.trim() || '',\n type: 'Chat', // MTProto entity type\n unreadCount: unreadCount,\n pinned: el.classList.contains('pinned') || el.hasAttribute('data-pinned'),\n });\n }\n });\n \n console.log('[TELEGRAM] Scraped', dialogs.length, 'dialogs from DOM');\n }\n\n // STEP 3: Extract messages from visible chat (if any chat is open)\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_EXPORT_PROGRESS',\n stage: 'extracting_messages',\n progress: 50,\n message: 'Extracting messages (messages.getHistory)...'\n }));\n\n if (messages.length === 0) {\n // Scrape messages from currently open chat\n const messageElements = document.querySelectorAll(\n '[data-message-id], ' +\n '.message, ' +\n '.bubble, ' +\n '[class*=\"Message\"]:not([class*=\"MessageList\"])'\n );\n \n messageElements.forEach((el, idx) => {\n const msgId = el.getAttribute('data-message-id') || \n el.getAttribute('data-mid') || \n 'msg-' + idx;\n \n // Check if outgoing (user's message)\n const isOutgoing = el.classList.contains('out') || \n el.classList.contains('is-out') ||\n el.getAttribute('data-is-out') === 'true' ||\n el.closest('.bubbles-group-out') !== null;\n \n const textEl = el.querySelector(\n '.text-content, ' +\n '.message-content, ' +\n '[class*=\"text-entity\"], ' +\n '.translatable-message'\n );\n const timeEl = el.querySelector(\n '.time, ' +\n '.time-inner, ' +\n '[class*=\"MessageMeta\"] time, ' +\n '.message-time'\n );\n \n // Get message text\n const text = textEl?.textContent?.trim() || '';\n \n // Only extract outgoing messages (user's own messages)\n if (text && isOutgoing) {\n // Try to extract Unix timestamp\n let timestamp = null;\n if (timeEl) {\n const timeAttr = timeEl.getAttribute('datetime') || \n timeEl.getAttribute('data-timestamp');\n if (timeAttr) {\n timestamp = new Date(timeAttr).getTime() / 1000; // Unix timestamp\n }\n }\n \n messages.push({\n id: msgId,\n text: text,\n timestamp: timestamp || timeEl?.textContent?.trim() || '',\n date: timestamp, // MTProto uses 'date' field\n out: true, // MTProto uses 'out' boolean\n type: 'text',\n fromId: userId,\n });\n }\n });\n \n console.log('[TELEGRAM] Scraped', messages.length, 'outgoing messages from DOM');\n }\n\n // STEP 4: Process and format data to match MTProto structure\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_EXPORT_PROGRESS',\n stage: 'processing',\n progress: 75,\n message: 'Processing MTProto data...'\n }));\n\n // Format dialogs to match messages.Dialogs structure\n const formattedDialogs = dialogs.slice(0, 100).map((dialog, idx) => {\n // Determine entity type (User, Chat, Channel)\n let type = dialog._ || dialog.type || 'Chat';\n if (dialog.megagroup || dialog.broadcast) {\n type = 'Channel';\n } else if (dialog.first_name || dialog.last_name) {\n type = 'User';\n }\n \n return {\n // Dialog fields (from messages.getDialogs)\n id: dialog.id || dialog.peerId || dialog.peer?.user_id || dialog.peer?.chat_id || dialog.peer?.channel_id,\n title: dialog.title || dialog.name || \n (dialog.first_name ? (dialog.first_name + ' ' + (dialog.last_name || '')).trim() : 'Unknown'),\n type: type,\n \n // Dialog metadata\n unreadCount: dialog.unread_count || dialog.unreadCount || 0,\n pinned: dialog.pinned || false,\n folderId: dialog.folder_id || 0, // 0=main, 1=archived\n topMessageId: dialog.top_message,\n readInboxMaxId: dialog.read_inbox_max_id,\n readOutboxMaxId: dialog.read_outbox_max_id,\n \n // Last message date (Unix timestamp)\n lastMessageDate: dialog.date || dialog.lastMessageDate,\n };\n });\n\n // Format messages to match messages.Messages structure\n const userMessages = messages\n .filter(msg => msg.out || msg.isOutgoing || msg.fromId === userId)\n .slice(0, 500)\n .map(msg => ({\n // Message fields (from messages.getHistory)\n id: msg.id || msg.mid,\n chatId: msg.peer_id || msg.peerId || msg.chatId,\n text: msg.message || msg.text || '',\n \n // MTProto timestamp (Unix)\n date: msg.date || Math.floor(new Date(msg.timestamp).getTime() / 1000),\n timestamp: msg.date || msg.timestamp,\n \n // Message metadata\n type: msg.media ? (msg.media._ || 'media') : 'text',\n fromId: msg.from_id || msg.fromId || userId,\n out: true, // These are all outgoing\n \n // Reply info\n replyToMsgId: msg.reply_to?.reply_to_msg_id,\n }));\n\n console.log('\u2705 [TELEGRAM] MTProto extraction complete:', {\n dialogs: formattedDialogs.length,\n messages: userMessages.length,\n users: users.length,\n chats: chats.length,\n });\n\n // STEP 5: Send results (matching messages.Dialogs + messages.Messages structure)\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_EXPORT_COMPLETE',\n status: 'success',\n data: {\n // Main data (from messages.getDialogs + messages.getHistory)\n dialogs: formattedDialogs,\n messages: userMessages,\n \n // Entity caches (users/chats referenced in dialogs/messages)\n users: users.slice(0, 100).map(u => ({\n id: u.id,\n firstName: u.first_name,\n lastName: u.last_name,\n username: u.username,\n })),\n chats: chats.slice(0, 100).map(c => ({\n id: c.id,\n title: c.title,\n type: c._ || c.type,\n })),\n \n // Summary\n summary: {\n dialogCount: formattedDialogs.length,\n messageCount: userMessages.length,\n },\n \n // User info\n userId: userId,\n },\n success: true\n }));\n\n } catch (error) {\n console.error('\u274C [TELEGRAM] Export failed:', error.message);\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_EXPORT_ERROR',\n status: 'error',\n message: 'MTProto extraction failed: ' + error.message,\n success: false\n }));\n }\n })();\n\n } catch (error) {\n console.error('\u274C [TELEGRAM] Init error:', error.message);\n window.ReactNativeWebView.postMessage(JSON.stringify({\n type: 'TELEGRAM_EXPORT_ERROR',\n status: 'error',\n message: 'Script initialization error: ' + error.message,\n success: false\n }));\n }\n})();\ntrue;\n";
export declare const TELEGRAM_SUCCESS_SCRIPT = "\n(function() {\n console.log('\u2705 Telegram export successful!');\n})();\ntrue;\n";
export declare const TELEGRAM_ERROR_SCRIPT = "\n(function() {\n console.log('\u274C Telegram export failed!');\n})();\ntrue;\n";
//# sourceMappingURL=telegram.d.ts.map