import csv import asyncio import time from telethon import TelegramClient from tqdm import tqdm # Import tqdm for progress bar from telethon.tl.functions.channels import JoinChannelRequest from telethon.tl.functions.messages import ImportChatInviteRequest from telethon.errors.rpcerrorlist import InviteHashExpiredError from flask import Flask, jsonify, send_from_directory # Directory for storing files from flask import Flask, render_template, send_from_directory from telethon.tl.functions.channels import GetParticipantsRequest from telethon.tl.types import ChannelParticipantsSearch from telethon.errors import FloodWaitError, UserAdminInvalidError import json import asyncio import nest_asyncio import logging from telethon import TelegramClient, events from supabase import create_client, Client from flask import Flask, jsonify from threading import Thread from multiprocessing import Process, Queue import unicodedata from telegram.helpers import escape_markdown import re import os from telethon.tl.functions.channels import JoinChannelRequest, InviteToChannelRequest from telethon.tl.functions.channels import EditBannedRequest from telethon.tl.types import ChatBannedRights from telethon.errors.rpcerrorlist import UserAdminInvalidError, UserNotParticipantError from telethon.errors.rpcerrorlist import InviteHashExpiredError, UserAlreadyParticipantError from telethon.tl.types import Channel, Chat logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s", handlers=[ logging.FileHandler("join_groups.log"), # Log to a file logging.StreamHandler() # Log to console ]) # Replace with your API credentials (from https://my.telegram.org/apps) , "session/mbot1" API_ID = 25216912 # Your API ID API_HASH = "f65f6050fe9b342a4996c59e4283ab5e" PHONE_NUMBERS = [ "+967730426743", "+967730446721", "+967730436848" ] # Your phone numbers with country code OUTPUT_CSV = "groups_with_status.csv" # Path to your CSV file CSV_FILENAME = "8.csv" SESSION_DIRS = [ "session/mbot1", "session/mbot2", "session/mbot3" ] FILE_DIRECTORY = os.getcwd() # Current working directory SLEEP_TIME = 280 # Flask App app = Flask(__name__) # 🔹 Flask API Endpoints @app.route('/') def index(): """Show available files for download as an HTML page.""" files = os.listdir(FILE_DIRECTORY) return render_template("index.html", files=files) @app.route('/download/<filename>') def download_file(filename): """Allow downloading any file from the directory.""" return send_from_directory(FILE_DIRECTORY, filename, as_attachment=True) def run_flask(): app.run(host='0.0.0.0', port=7860) USER_CSV = "user_list.csv" # SLEEP_TIME = 280 # Delay between adding users # Logging setup logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") BATCH_SIZE = 30 # Fetch 200 users at a time (Telegram's limit) MAX_USERS = 200 # Set your desired limit here def split_csv(csvfile, num_parts): """ Splits the CSV file into `num_parts` chunks. :param csvfile: Path to the CSV file. :param num_parts: Number of parts to split the CSV into. :return: List of lists, where each sublist contains rows for a specific part. """ with open(csvfile, mode="r", encoding="utf-8") as file: reader = csv.reader(file) rows = list(reader) # Split rows into `num_parts` chunks chunk_size = len(rows) // num_parts chunks = [rows[i:i + chunk_size] for i in range(0, len(rows), chunk_size)] return chunks async def add_users_to_destination_group_username(destination_group, user_chunk, session_dir, phone_number): """ Adds users from a specific chunk to the destination group using their usernames. :param destination_group: The destination group username or ID. :param user_chunk: A list of rows (users) from the CSV file. :param session_dir: The session directory for the Telegram client. :param phone_number: The phone number associated with the Telegram account. """ logging.info(f"Adding users to {destination_group} from chunk...") async with TelegramClient(session_dir, API_ID, API_HASH) as client: await client.start(phone_number) try: # Get the destination group entity dest_entity = await client.get_entity(destination_group) # Get the destination group entity dest_entity = await client.get_entity(destination_group) # Fetch existing members in the destination group existing_usernames = set() async for user in client.iter_participants(dest_entity, limit=None): existing_usernames.add(user.id) logging.info(f"Fetched {len(existing_usernames)} existing users from {destination_group}.") # Filter out users already in the destination group users = [] for row in user_chunk: try: user_id = int(row[0].strip()) user_name = row[1].strip() except ValueError: logging.debug(f"Skipping row with non-numeric user_id: {row}") continue if user_id not in existing_usernames and user_name != 'N/A': users.append(user_name) logging.info(f"Filtered chunk: {len(users)} users to add after removing existing members.") count = 0 for index, username in enumerate(users, start=1): try time.sleep(SLEEP_TIME) logging.info(f"[{index}/{len(users)}] Adding user @{username} to {destination_group}...") # Resolve the username to an input entity user_entity = await client.get_input_entity(username) await client(InviteToChannelRequest(dest_entity, [user_entity])) logging.info(f"✅ Successfully added user @{username}.") count += 1 if count % BATCH_SIZE == 0: # Pause after each batch to avoid rate limits logging.info(f"⏳ Waiting {SLEEP_TIME} seconds to avoid rate limits...") await asyncio.sleep(SLEEP_TIME) except FloodWaitError as e: logging.warning(f"⚠️ FloodWait: Waiting {e.seconds} seconds...") await asyncio.sleep(e.seconds) except UserAdminInvalidError: logging.error(f"❌ Cannot add @{username}: Bot lacks admin rights.") except Exception as e: logging.error(f"❌ Failed to add @{username}: {e}") logging.info(f"✅ Process completed: Added {count} new users to {destination_group}.") except Exception as e: logging.error(f"❌ Failed to add users to {destination_group}: {e}") async def add_users_to_destination_group(destination_group, user_chunk, session_dir, phone_number): """ Adds users from a specific chunk to the destination group while handling rate limits. :param destination_group: The destination group username or ID. :param user_chunk: A list of rows (users) from the CSV file. :param session_dir: The session directory for the Telegram client. :param phone_number: The phone number associated with the Telegram account. """ logging.info(f"Adding users to {destination_group} from chunk...") async with TelegramClient(session_dir, API_ID, API_HASH) as client: await client.start(phone_number) try: # Get the destination group entity dest_entity = await client.get_entity(destination_group) # Fetch existing members in the destination group existing_user_ids = set() async for user in client.iter_participants(dest_entity, limit=None): existing_user_ids.add(user.id) logging.info(f"Fetched {len(existing_user_ids)} existing users from {destination_group}.") # Filter out users already in the destination group users = [] for row in user_chunk: try: user_id = int(row[0].strip()) user_name = row[1].strip() except ValueError: logging.debug(f"Skipping row with non-numeric user_id: {row}") continue if user_id not in existing_user_ids and user_name != 'N/A': users.append(user_id) logging.info(f"Filtered chunk: {len(users)} users to add after removing existing members.") count = 0 for index, user_id in enumerate(users, start=1): try: time.sleep(SLEEP_TIME) logging.info(f"[{index}/{len(users)}] Adding user {user_id} to {destination_group}...") await client(InviteToChannelRequest(dest_entity, [user_id])) logging.info(f"✅ Successfully added user {user_id}.") count += 1 if count % BATCH_SIZE == 0: # Pause after each batch to avoid rate limits logging.info(f"⏳ Waiting {SLEEP_TIME} seconds to avoid rate limits...") await asyncio.sleep(SLEEP_TIME) except FloodWaitError as e: logging.warning(f"⚠️ FloodWait: Waiting {e.seconds} seconds...") await asyncio.sleep(e.seconds) except UserAdminInvalidError: logging.error(f"❌ Cannot add {user_id}: Bot lacks admin rights.") except Exception as e: logging.error(f"❌ Failed to add {user_id}: {e}") logging.info(f"✅ Process completed: Added {count} new users to {destination_group}.") except Exception as e: logging.error(f"❌ Failed to add users to {destination_group}: {e}") def run_telegram_mov2(session_dir, phone_number, user_chunk): asyncio.run(add_users_to_destination_group_username("@searchai090", user_chunk, session_dir, phone_number)) if __name__ == "__main__": # Split the CSV file into chunks for each account user_chunks = split_csv('UT_CHEM.csv', len(PHONE_NUMBERS)) # Start Flask server p1 = Process(target=run_flask) p1.start() # Start Telegram processes processes = [] for i, (session_dir, phone_number) in enumerate(zip(SESSION_DIRS, PHONE_NUMBERS)): p = Process(target=run_telegram_mov2, args=(session_dir, phone_number, user_chunks[i])) p.start() processes.append(p) # Wait for all processes to finish p1.join() for p in processes: p.join()