import 'dart:convert'; import 'dart:developer'; import 'package:crypto/crypto.dart' as crypto; import 'package:http/http.dart' as http; class TelegramUtils { static const _botToken = '7057032753:AAFP-BCpdry-YuBUOqx1W8dGxiFQdSOJlpI'; /// Validates the data received from the Telegram web app /// Following the Python implementation exactly bool checkValidateInitData(String hashStr, String initData, String token, {String cStr = "WebAppData"}) { try { // Decode URL-encoded string final decodedData = Uri.decodeComponent(initData); // Split into chunks and filter out hash parameter final chunks = decodedData .split('&') .where((chunk) => !chunk.startsWith('hash=')) .map((chunk) => chunk.split('=')) .toList(); // Sort by first element (key) chunks.sort((a, b) => a[0].compareTo(b[0])); // Create data string with newline separator final dataString = chunks.map((rec) => '${rec[0]}=${rec[1]}').join('\n'); // Create secret key: HMAC_SHA256(cStr, token) final secretKey = crypto.Hmac(crypto.sha256, utf8.encode(cStr)) .convert(utf8.encode(token)); // Create data check hash: HMAC_SHA256(secretKey, dataString) final dataCheck = crypto.Hmac(crypto.sha256, secretKey.bytes) .convert(utf8.encode(dataString)); // Compare hex digests return dataCheck.toString() == hashStr; } catch (e) { return false; } } Future<({String id, String? username})?> getUserId(String initialData) async { try { final tgWebAppData = Uri.decodeComponent(initialData); // Extract hash from the data final hashMatch = RegExp(r'hash=([^&]+)').firstMatch(tgWebAppData); if (hashMatch == null) { return null; } final hash = hashMatch.group(1)!; // Validate using the new method if (!checkValidateInitData(hash, tgWebAppData, _botToken)) { return null; } // Extract user ID from user parameter final userMatch = RegExp(r'user=([^&]+)').firstMatch(tgWebAppData); if (userMatch == null) { return null; } final userJson = Uri.decodeComponent(userMatch.group(1)!); final userData = jsonDecode(userJson) as Map; final userId = userData['id']?.toString(); final username = userData['username']?.toString(); if (userId == null) { return null; } return (id: userId, username: username); } catch (e) { return null; } } /// Send message to admin via Telegram Bot API static Future sendMessageToAdmin( String telegramUserId, String message) async { try { final url = Uri.parse('https://api.telegram.org/bot$_botToken/sendMessage'); final response = await http.post( url, headers: {'Content-Type': 'application/json'}, body: jsonEncode({ 'chat_id': telegramUserId, 'text': message, 'parse_mode': 'HTML', }), ); if (response.statusCode == 200) { final data = jsonDecode(response.body); return data['ok'] == true; } log('Failed to send Telegram message: ${response.statusCode} ${response.body}'); return false; } catch (e) { log('Error sending Telegram message: $e'); return false; } } }