diff --git a/telegram_trigger_bot.py b/telegram_trigger_bot.py index 0cb6130..d8b8faf 100644 --- a/telegram_trigger_bot.py +++ b/telegram_trigger_bot.py @@ -7,6 +7,8 @@ import os import sys import subprocess import logging +import json +import zipfile from pathlib import Path from datetime import datetime import glob @@ -55,6 +57,7 @@ class TelegramTriggerBot: url = f"{self.base_url}/setMyCommands" commands = [ {"command": "scrape", "description": "Rulează scraper-ul BTGO"}, + {"command": "zip", "description": "Trimite ultimele fișiere ca ZIP"}, {"command": "status", "description": "Status sistem"}, {"command": "help", "description": "Ajutor comenzi"} ] @@ -153,6 +156,120 @@ class TelegramTriggerBot: logging.error(f"Eroare execuție: {e}") self.send_message(chat_id, f"*EROARE EXECUTIE*\n\n```\n{str(e)}\n```", reply_to_message_id) + def send_zip_files(self, chat_id, reply_to_message_id=None): + """Trimite ultimele fișiere ca arhivă ZIP""" + try: + data_dir = Path('data') + + if not data_dir.exists(): + self.send_message(chat_id, "*EROARE*\n\nDirectorul 'data' nu există!", reply_to_message_id) + return + + # Găsește ultimul fișier solduri + solduri_files = sorted(data_dir.glob('solduri_*.csv'), key=lambda x: x.stat().st_mtime, reverse=True) + + if not solduri_files: + self.send_message(chat_id, "*EROARE*\n\nNu s-au găsit fișiere solduri!", reply_to_message_id) + return + + latest_solduri = solduri_files[0] + solduri_time = latest_solduri.stat().st_mtime + + # Găsește fișierele tranzacții din aceeași sesiune (ultimele 5 minute) + time_window = 300 # 5 minute + transaction_files = [] + + for tf in data_dir.glob('tranzactii_*.csv'): + if abs(tf.stat().st_mtime - solduri_time) <= time_window: + transaction_files.append(tf) + + # Găsește fișierul JSON corespunzător + json_file = data_dir / (latest_solduri.stem + '.json') + accounts_data = [] + + if json_file.exists(): + try: + with open(json_file, 'r', encoding='utf-8') as f: + json_data = json.load(f) + accounts_data = json_data.get('conturi', []) + except Exception as e: + logging.warning(f"Nu s-a putut citi JSON: {e}") + + # Creează arhiva ZIP + timestamp = datetime.now().strftime('%Y-%m-%d_%H-%M-%S') + zip_filename = f'btgo_export_{timestamp}.zip' + zip_path = data_dir / zip_filename + + files_to_zip = [latest_solduri] + transaction_files + if json_file.exists(): + files_to_zip.append(json_file) + + with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf: + for file_path in files_to_zip: + zipf.write(file_path, file_path.name) + + zip_size = zip_path.stat().st_size / (1024 * 1024) # MB + + logging.info(f"Arhivă ZIP creată: {zip_filename} ({zip_size:.2f} MB)") + + # Verifică limita Telegram (50 MB) + if zip_size > 50: + self.send_message( + chat_id, + f"*EROARE*\n\nArhiva ZIP este prea mare ({zip_size:.2f} MB)\n" + f"Limita Telegram: 50 MB", + reply_to_message_id + ) + zip_path.unlink() # Șterge fișierul + return + + # Construiește mesaj cu solduri + caption = f"📦 *BTGO Export (ZIP)*\n\n" + caption += f"Timp: {datetime.fromtimestamp(solduri_time).strftime('%Y-%m-%d %H:%M:%S')}\n" + caption += f"Dimensiune: {zip_size:.2f} MB\n" + caption += f"Fișiere: {len(files_to_zip)}\n\n" + + if accounts_data: + total_ron = sum(acc['sold'] for acc in accounts_data if acc.get('moneda') == 'RON') + caption += "*SOLDURI:*\n" + for acc in accounts_data: + nume = acc['nume_cont'] + sold = acc['sold'] + moneda = acc['moneda'] + caption += f" • {nume}: {sold:,.2f} {moneda}\n" + caption += f"\n*TOTAL: {total_ron:,.2f} RON*" + else: + caption += f"Conturi: {len(transaction_files)}" + + # Trimite ZIP-ul + self.send_message(chat_id, "📦 *Creare arhivă ZIP...*", reply_to_message_id) + + url = f"{self.base_url}/sendDocument" + with open(zip_path, 'rb') as f: + files = {'document': f} + data = { + 'chat_id': chat_id, + 'caption': caption, + 'parse_mode': 'Markdown' + } + if reply_to_message_id: + data['reply_to_message_id'] = reply_to_message_id + + response = requests.post(url, data=data, files=files) + + if response.status_code == 200: + logging.info("✓ ZIP trimis cu succes pe Telegram") + else: + logging.error(f"Eroare trimitere ZIP: {response.text}") + self.send_message(chat_id, f"*EROARE*\n\nNu s-a putut trimite arhiva.", reply_to_message_id) + + # Șterge fișierul ZIP temporar + zip_path.unlink() + + except Exception as e: + logging.error(f"Eroare send_zip_files: {e}", exc_info=True) + self.send_message(chat_id, f"*EROARE*\n\n```\n{str(e)}\n```", reply_to_message_id) + def handle_command(self, message): """Procesează comenzi primite""" chat_id = message['chat']['id'] @@ -185,6 +302,7 @@ class TelegramTriggerBot: welcome_msg += ( "Comenzi disponibile:\n" "`/scrape` - Ruleaza scraper-ul\n" + "`/zip` - Trimite ultimele fisiere ca ZIP\n" "`/status` - Status sistem\n" "`/help` - Ajutor" ) @@ -194,6 +312,10 @@ class TelegramTriggerBot: logging.info(f"Comandă /scrape primită în {context}") self.run_scraper(chat_id, message_id) + elif text == '/zip': + logging.info(f"Comandă /zip primită în {context}") + self.send_zip_files(chat_id, message_id) + elif text == '/status': data_dir = Path('data') csv_count = len(list(data_dir.glob('*.csv'))) @@ -220,13 +342,20 @@ class TelegramTriggerBot: if chat_type in ['group', 'supergroup']: help_msg += "IN GRUP: Toti membrii vad comenzile si rezultatele\n\n" help_msg += ( - "1. Trimite `/scrape` pentru a porni scraper-ul\n" + "*COMENZI:*\n" + "`/scrape` - Ruleaza scraper-ul + trimite fisiere\n" + "`/zip` - Trimite ultimele fisiere ca arhiva ZIP\n" + "`/status` - Informatii sistem\n" + "`/help` - Acest mesaj\n\n" + "*GHID SCRAPER:*\n" + "1. Trimite `/scrape`\n" "2. Asteapta notificarea de 2FA pe telefon\n" "3. Aproba in aplicatia George\n" "4. Primesti fisierele automat\n\n" - "NOTE:\n" + "*NOTE:*\n" "- Scraper-ul ruleaza ~2-3 minute\n" - "- Asigura-te ca VM-ul are browser vizibil" + "- VM-ul trebuie sa aiba browser vizibil\n" + "- `/zip` trimite datele existente (fara scraping)" ) self.send_message(chat_id, help_msg, message_id)