diff --git a/Desktop/Telegram_Bot/services/telegram_listener.py b/Desktop/Telegram_Bot/services/telegram_listener.py index 9792fc2471739af61de1b24143993f221ed6d4f2..523e5564902db42cdbac4ffc09b90f7055b3831d 100644 --- a/Desktop/Telegram_Bot/services/telegram_listener.py +++ b/Desktop/Telegram_Bot/services/telegram_listener.py @@ -1,11 +1,11 @@ # python import asyncio import csv -import os import json +import os from pathlib import Path -from dotenv import load_dotenv,find_dotenv +from dotenv import load_dotenv, find_dotenv from datetime import datetime from telethon import TelegramClient, events @@ -17,6 +17,7 @@ from telethon.tl.types import InputChannel, Channel, ReactionEmoji, ReactionCust from transformers import pipeline load_dotenv(find_dotenv()) +# load_dotenv(dotenv_path=r"{Path for the env file}") # Please create a .env file. Add the environment variables over there. And never the env file on github or gitlab. API_ID = int(os.getenv("API_ID")) @@ -24,20 +25,19 @@ API_HASH = os.getenv("API_HASH") SESSION = os.getenv("SESSION") INVITE_LINK = os.getenv("INVITE_LINK") - -DATA_DIR = Path(os.getenv("DATA_DIR", "/app/data")) -DATA_DIR.mkdir(parents=True, exist_ok=True) - -timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") -JSON_PATH = DATA_DIR / f"messages_{timestamp}.json" - sentiment_analyzer = pipeline("sentiment-analysis") -# These are the headers for the Json file. +# These are the headers for the csv file. HEADER = ["chat_id", "message_id", "sender_id", "timestamp", "text", "has_media", "media_type", "file_name", "file_size_kb", "views", "reactions", "sentiment"] +timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + +JSON_PATH = Path(f"output/messages_{timestamp}.json") + +# JSON_PATH = Path(r"messages_.json") # e.g., "output/messages.json" + async def list_joined_channels(client): channels = [] async for dialog in client.iter_dialogs(): @@ -65,7 +65,7 @@ async def process_last_messages_for_all(client, process_message, limit): async def handle_all(event): await process_message(event.message) - return channels # optional, if you need the list + return channels async def process_last_message_for_one_channel(client, process_message, target, limit): @@ -95,24 +95,49 @@ def write_csv_row(row_dict): writer.writeheader() writer.writerow(row_dict) - -def write_json_entry(entry): - """Append a single JSON entry to a file.""" +# def write_json_entry(entry): +# """Append a single JSON entry to a file.""" +# try: +# existing_data = [] +# if os.path.exists(JSON_PATH): +# with open(JSON_PATH, "r", encoding="utf-8-sig") as f: +# try: +# existing_data = json.load(f) +# except json.JSONDecodeError: +# existing_data = [] + +# existing_data.append(entry) +# with open(JSON_PATH, "w", encoding="utf-8") as f: +# json.dump(existing_data, f, ensure_ascii=False, indent=4) +# except Exception as e: +# print(f"JSON write error: {e}") + +def write_json_entry_per_post(entry, message_id, sender_id): + """Create a separate JSON file for each post.""" try: - existing_data = [] - if JSON_PATH.exists(): - with open(JSON_PATH, "r", encoding="utf-8-sig") as f: - try: - existing_data = json.load(f) - except json.JSONDecodeError: - existing_data = [] - - existing_data.append(entry) - with open(JSON_PATH, "w", encoding="utf-8") as f: - json.dump(existing_data, f, ensure_ascii=False, indent=4) + os.makedirs("output", exist_ok=True) + json_path = Path(f"output/post_{message_id}_{sender_id}.json") + with open(json_path, "w", encoding="utf-8-sig") as f: + json.dump(entry, f, ensure_ascii=False, indent=4) + print(f"JSON file saved: {json_path}") except Exception as e: - print(f"JSON write error: {e}") + print(f"Error writing JSON for post {message_id}: {e}") +def write_text_file_per_post(message,sender_id): + """Save only the text of a message to a separate .txt file.""" + try: + os.makedirs("output", exist_ok=True) + text_content = message.text or "" + if not text_content.strip(): + return # skip empty or non-text messages + + file_path = Path(f"output/post_{message.id}_{sender_id}.txt") + with open(file_path, "w", encoding="utf-8-sig") as f: + f.write(text_content.strip()) + + print(f"Text file saved: {file_path}") + except Exception as e: + print(f"Error writing text file for post {message.id}: {e}") def safe_serialize_reactions(message): r = getattr(message, "reactions", None) @@ -127,6 +152,7 @@ def safe_serialize_reactions(message): async def process_message_for_csv(message): sentiment = await asyncio.to_thread(sentiment_analyzer, message.text or "") + sender_id = getattr(message, "sender_id", None) row = { "chat_id": message.chat_id, "message_id": message.id, @@ -142,10 +168,11 @@ async def process_message_for_csv(message): "sentiment": sentiment[0]["label"] if sentiment else "" } try: - #write_csv_row(row) - write_json_entry(row) + # write_csv_row(row) + write_json_entry_per_post(row, message.id, sender_id) + write_text_file_per_post(message,sender_id) except Exception as e: - print(f"CSV write error: {e}") + print(f"JSON write error: {e}") def render_reaction_label(r): if isinstance(r, ReactionEmoji): @@ -226,7 +253,8 @@ async def main(): if target: print("Listening to single channel ") - process_last_message_for_one_channel(client, process_message, target, limit= 5) + await process_last_message_for_one_channel(client, process_message, target, limit= 5) + # After collecting else: print("No INVITE_URL provided. Listening to all chats.")