import os
import asyncio
from telethon.errors import SessionPasswordNeededError, FloodWaitError
from telethon import TelegramClient, functions
from colorama import Fore, Style, init
from pyfiglet import Figlet
# Initialize colorama
init(autoreset=True)
# Define the ASCII logo with color
ascii_logo = f"""
{Fore.CYAN}⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣴⣾⣿⣿⣿⡄
{Fore.BLUE}⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣶⣿⣿⡿⠿⠛⢙⣿⣿⠃
{Fore.MAGENTA}⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣶⣾⣿⣿⠿⠛⠋⠁⠀⠀⠀⣸⣿⣿⠀
{Fore.YELLOW}⠀⠀⠀⠀⣀⣤⣴⣾⣿⣿⡿⠟⠛⠉⠀⠀⣠⣤⠞⠁⠀⠀⣿⣿⡇⠀
{Fore.LIGHTGREEN_EX}⠀⣴⣾⣿⣿⡿⠿⠛⠉⠀⠀⠀⢀⣠⣶⣿⠟⠁⠀⠀⠀⢸⣿⣿⠀⠀
{Fore.CYAN}⠸⣿⣿⣿⣧⣄⣀⠀⠀⣀⣴⣾⣿⣿⠟⠁⠀⠀⠀⠀⠀⣼⣿⡿⠀⠀
{Fore.CYAN}⠀⠈⠙⠻⠿⣿⣿⣿⣿⣿⣿⣿⠟⠁⠀⠀⠀⠀⠀⠀⢠⣿⣿⠇⠀⠀
{Fore.CYAN}⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡇⠀⣀⣄⡀⠀⠀⠀⠀⢸⣿⣿⠀⠀⠀
{Fore.CYAN}⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣠⣾⣿⣿⣿⣦⡀⠀⠀⣿⣿⡏⠀⠀⠀
{Fore.CYAN}⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⡿⠋⠈⠻⣿⣿⣦⣸⣿⣿⠁⠀⠀⠀
{Fore.CYAN}⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠛⠁⠀⠀⠀⠀⠈⠻⣿⣿⣿⠏⠀⠀⠀⠀
{Style.RESET_ALL}
"""
def print_logo():
"""Function to print the ASCII logo."""
print(ascii_logo)
def ascii_title():
"""Function to print the ASCII art title with color."""
f = Figlet(font='slant') # You can change 'slant' to another font
ascii_banner = f.renderText("Telegram Tools")
print(f"{Fore.LIGHTBLUE_EX}{ascii_banner}{Style.RESET_ALL}") # Yellow color
for the title
def list_sessions(sessions_dir):
"""List all session files in the specified directory."""
if not os.path.exists(sessions_dir):
print(f"{Fore.RED}The directory '{sessions_dir}' does not exist.")
return []
return [f for f in os.listdir(sessions_dir) if f.endswith('.session')]
async def delete_chat(client, chat):
"""Delete the entire chat."""
await client.delete_dialog(chat)
async def delete_all_chats(client):
"""Delete all individual chats."""
async for dialog in client.iter_dialogs():
if dialog.entity and dialog.entity.__class__.__name__ == 'User' and not
dialog.entity.bot:
chat_name = dialog.entity.title if hasattr(dialog.entity, 'title') else
dialog.entity.first_name
try:
await delete_chat(client, dialog.entity)
print(f"{Fore.LIGHTGREEN_EX}Successfully deleted chat: {Fore.CYAN}
{chat_name}")
except Exception as e:
print(f"{Fore.RED}Error deleting chat {chat_name}: {Fore.YELLOW}
{e}")
async def find_chat(client, query):
"""Find a chat by name, username, or ID."""
matches = []
async for dialog in client.iter_dialogs():
entity = dialog.entity
if entity and entity.__class__.__name__ == 'User' and not entity.bot:
name = entity.first_name if entity.first_name else ''
full_name = f"{entity.first_name} {entity.last_name}" if
entity.last_name else name
username = entity.username if entity.username else ''
# Match by name, full name, or username
if query.lower() in full_name.lower() or query.lower() in
username.lower():
matches.append((entity, full_name, username))
return matches
async def clear_individual_chats(sessions, sessions_dir, api_id, api_hash):
"""Handle clearing individual chats."""
while True:
print(f"\n{Fore.LIGHTYELLOW_EX}Choose sessions:{Style.RESET_ALL}")
print(f"{Fore.LIGHTCYAN_EX}A. All sessions{Style.RESET_ALL}")
for idx, session in enumerate(sessions):
print(f"{Fore.CYAN}{idx + 1}. {session}")
print(f"{Fore.LIGHTRED_EX}B. Back to home menu{Style.RESET_ALL}")
# Instruction message in white
print(f"{Fore.YELLOW}If you want to select multiple sessions:")
print(f"{Fore.WHITE}-Enter numbers separated by commas[,]
{Fore.LIGHTGREEN_EX}e.g (1,3,5,8)")
print(f"-Enter a range of sessions using hyphen[-] {Fore.LIGHTGREEN_EX}e.g
(1-5 or 5-1)")
print(f"-For all sessions selection {Fore.LIGHTGREEN_EX}'A'")
print(f"{Style.RESET_ALL}")
selected_session = input(f"{Fore.LIGHTYELLOW_EX}Select Session(s) ➣
{Style.RESET_ALL}").lower()
if selected_session == 'a':
selected_sessions = sessions
elif selected_session == 'b':
print(f"{Fore.YELLOW}Returning to home menu.{Style.RESET_ALL}")
return # Return to the home menu
else:
try:
selected_sessions = []
# Check if it's a comma-separated list of numbers
if ',' in selected_session:
selected_indices = [int(num.strip()) - 1 for num in
selected_session.split(',')]
# Check if it's a hyphen-separated range (ascending or descending)
elif '-' in selected_session:
start, end = map(int, selected_session.split('-'))
if start > end:
selected_indices = list(range(start - 1, end - 2, -1)) #
Descending range
else:
selected_indices = list(range(start - 1, end)) # Ascending
range
# If it's a single number
else:
selected_indices = [int(selected_session.strip()) - 1]
# Check if all selected indices are valid
invalid_indices = [index for index in selected_indices if not (0 <=
index < len(sessions))]
if invalid_indices:
print(f"{Fore.RED}Invalid session numbers: {', '.join(str(i +
1) for i in invalid_indices)}. Please try again.{Style.RESET_ALL}")
continue # Return to the selection menu
else:
# Fetch the selected sessions based on indices
selected_sessions = [sessions[i] for i in selected_indices]
except ValueError:
print(f"{Fore.RED}Invalid input. Please enter valid number(s) or
'A' or 'B'.{Style.RESET_ALL}")
continue # Return to the selection menu
# Here you can perform the task with selected_sessions
print(f"Selected sessions: {selected_sessions}")
# Display the selected sessions in yellow before proceeding
print(f"\n{Fore.LIGHTYELLOW_EX}Selected Sessions:{Style.RESET_ALL}")
for session in selected_sessions:
print(f"{Fore.YELLOW}{session}{Style.RESET_ALL}")
# Proceed to the next step with the selected sessions
await individual_chats_menu(selected_sessions, sessions_dir, api_id,
api_hash)
async def individual_chats_menu(sessions, sessions_dir, api_id, api_hash):
"""Menu for handling individual chats."""
while True:
print(f"\n{Fore.LIGHTYELLOW_EX}Choose an option ➣")
print(f"{Fore.GREEN}1. Delete individual chat")
print(f"{Fore.GREEN}2. Delete all individual chats")
print(f"{Fore.LIGHTRED_EX}B. Back to session selection")
choice = input(f"{Fore.LIGHTYELLOW_EX}Choose an option ➣{Style.RESET_ALL}
").lower()
if choice == '1':
query = input(f"{Fore.YELLOW}Type username, name, or ID:
{Style.RESET_ALL} ")
result = await process_individual_chats(sessions, sessions_dir, api_id,
api_hash, 'individual', query)
if not result:
continue # Go back to the menu if deletion was cancelled
elif choice == '2':
result = await process_individual_chats(sessions, sessions_dir, api_id,
api_hash, 'all')
if not result:
continue # Go back to the menu if deletion was cancelled
elif choice == 'b':
print(f"{Fore.YELLOW}Returning to session selection.")
break # Return to session selection
else:
print(f"{Fore.RED}Invalid choice. Please try again.")
async def process_individual_chats(sessions, sessions_dir, api_id, api_hash,
delete_type, query=None):
"""Process sessions to delete individual chats."""
for session_file in sessions:
session_path = os.path.join(sessions_dir, session_file)
async with TelegramClient(session_path, api_id, api_hash) as client:
print(f"{Fore.WHITE}Connected to: {session_file}")
if delete_type == 'individual' and query:
try:
matches = await find_chat(client, query)
if matches:
if len(matches) > 1:
print(f"{Fore.LIGHTCYAN_EX}Multiple matches found for
'{query}':")
for idx, (entity, name, username) in
enumerate(matches):
print(f"{idx + 1}. {name} (Username: {username})")
selected = input(f"{Fore.YELLOW}Select a user to delete
by number (1-{len(matches)}):{Style.RESET_ALL} ")
try:
selected_idx = int(selected) - 1
if 0 <= selected_idx < len(matches):
chat = matches[selected_idx][0]
confirm = input(f"{Fore.YELLOW}Are you sure
want to delete the chat with {matches[selected_idx][1]}?
({Fore.GREEN}y{Fore.YELLOW}/{Fore.RED}n{Fore.YELLOW}):{Style.RESET_ALL} ").lower()
if confirm == 'y':
await delete_chat(client, chat)
print(f"{Fore.LIGHTGREEN_EX}Successfully
deleted chat with {Fore.CYAN}{matches[selected_idx][1]}.")
else:
print(f"{Fore.WHITE}Deletion cancelled.")
return False # Return to the menu if
deletion was cancelled
else:
print(f"{Fore.RED}Invalid selection. Please try
again.")
except ValueError:
print(f"{Fore.RED}Invalid input. Please enter a
number.")
else:
chat = matches[0][0]
confirm = input(f"{Fore.YELLOW}Are you sure want to
delete the chat with {matches[0][1]}?
({Fore.GREEN}y{Fore.YELLOW}/{Fore.RED}n{Fore.YELLOW}):{Style.RESET_ALL} ").lower()
if confirm == 'y':
await delete_chat(client, chat)
print(f"{Fore.LIGHTGREEN_EX}Successfully deleted
chat with {Fore.CYAN}{matches[0][1]}.")
else:
print(f"{Fore.WHITE}Deletion cancelled.")
return False # Return to the menu if deletion was
cancelled
else:
print(f"{Fore.RED}No chat found with '{query}'. Please try
again.")
return False # Return to the menu if no matches were found
except Exception as e:
print(f"{Fore.RED}Error finding or deleting chat: {Fore.YELLOW}
{e}")
elif delete_type == 'all':
confirm = input(f"{Fore.YELLOW}Are you sure want to delete all
individual chats in {session_file}?
({Fore.GREEN}y{Fore.YELLOW}/{Fore.RED}n{Fore.YELLOW}):{Style.RESET_ALL} ").lower()
if confirm == 'y':
await delete_all_chats(client)
print(f"{Fore.LIGHTGREEN_EX}All individual chats deleted.")
else:
print(f"{Fore.WHITE}Cancelled deleting all chats.")
return False # Return to previous step if 'n'
return True # If the process completes successfully, return True
async def delete_leave_channels_groups(sessions, sessions_dir, api_id, api_hash):
"""Menu for deleting and leaving channels and groups."""
while True:
print(f"\n{Fore.LIGHTYELLOW_EX}Choose sessions:{Style.RESET_ALL}")
print(f"{Fore.LIGHTCYAN_EX}A. All sessions{Style.RESET_ALL}")
for idx, session in enumerate(sessions):
print(f"{Fore.CYAN}{idx + 1}. {session}")
print(f"{Fore.LIGHTRED_EX}B. Back to home menu{Style.RESET_ALL}")
# Instruction message in white
print(f"{Fore.YELLOW}If you want to select multiple sessions:")
print(f"{Fore.WHITE}-Enter numbers separated by commas[,]
{Fore.LIGHTGREEN_EX}e.g (1,3,5,8)")
print(f"-Enter a range of sessions using hyphen[-] {Fore.LIGHTGREEN_EX}e.g
(1-5 or 5-1)")
print(f"-For all sessions selection {Fore.LIGHTGREEN_EX}'A'")
print(f"{Style.RESET_ALL}")
selected_session = input(f"{Fore.LIGHTYELLOW_EX}Select Session(s) ➣
{Style.RESET_ALL}").lower()
if selected_session == 'a':
selected_sessions = sessions
elif selected_session == 'b':
print(f"{Fore.YELLOW}Returning to home menu.{Style.RESET_ALL}")
return # Return to the home menu
else:
try:
selected_sessions = []
# Check if it's a comma-separated list of numbers
if ',' in selected_session:
selected_indices = [int(num.strip()) - 1 for num in
selected_session.split(',')]
# Check if it's a hyphen-separated range (ascending or descending)
elif '-' in selected_session:
start, end = map(int, selected_session.split('-'))
if start > end:
selected_indices = list(range(start - 1, end - 2, -1)) #
Descending range
else:
selected_indices = list(range(start - 1, end)) # Ascending
range
# If it's a single number
else:
selected_indices = [int(selected_session.strip()) - 1]
# Check if all selected indices are valid
invalid_indices = [index for index in selected_indices if not (0 <=
index < len(sessions))]
if invalid_indices:
print(f"{Fore.RED}Invalid session numbers: {', '.join(str(i +
1) for i in invalid_indices)}. Please try again.{Style.RESET_ALL}")
continue # Return to the selection menu
else:
# Fetch the selected sessions based on indices
selected_sessions = [sessions[i] for i in selected_indices]
except ValueError:
print(f"{Fore.RED}Invalid input. Please enter valid number(s) or
'A' or 'B'.{Style.RESET_ALL}")
continue # Return to the selection menu
# Display the selected sessions in yellow before proceeding
print(f"\n{Fore.LIGHTYELLOW_EX}Selected Sessions:{Style.RESET_ALL}")
for session in selected_sessions:
print(f"{Fore.YELLOW}{session}{Style.RESET_ALL}")
# Proceed to the next step with the selected sessions
await channels_groups_menu(selected_sessions, sessions_dir, api_id,
api_hash)
async def channels_groups_menu(sessions, sessions_dir, api_id, api_hash):
"""Menu for handling channels and groups."""
while True:
print(f"\n{Fore.LIGHTYELLOW_EX}Choose an option ➣{Style.RESET_ALL}")
print(f"{Fore.GREEN}1. Delete individual channel/group{Style.RESET_ALL}")
print(f"{Fore.GREEN}2. Delete all channels/groups{Style.RESET_ALL}")
print(f"{Fore.LIGHTRED_EX}B. Back to session selection{Style.RESET_ALL}")
choice = input(f"{Fore.LIGHTYELLOW_EX}Choose an option ➣
{Style.RESET_ALL}").lower()
if choice == '1':
query = input(f"{Fore.YELLOW}Type channel/group name or ID:
{Style.RESET_ALL}")
result = await process_channels_groups(sessions, sessions_dir, api_id,
api_hash, 'individual', query)
if not result:
continue # Go back to the menu if deletion was cancelled
elif choice == '2':
result = await process_channels_groups(sessions, sessions_dir, api_id,
api_hash, 'all')
if not result:
continue # Go back to the menu if deletion was cancelled
elif choice == 'b':
print(f"{Fore.YELLOW}Returning to session selection.{Style.RESET_ALL}")
break # Return to session selection
else:
print(f"{Fore.RED}Invalid choice. Please try again.{Style.RESET_ALL}")
async def process_channels_groups(sessions, sessions_dir, api_id, api_hash,
delete_type, query=None):
"""Process sessions to delete channels and groups."""
for session_file in sessions:
session_path = os.path.join(sessions_dir, session_file)
async with TelegramClient(session_path, api_id, api_hash) as client:
print(f"{Fore.WHITE}Connected to: {session_file}")
if delete_type == 'individual' and query:
try:
async for dialog in client.iter_dialogs():
if (dialog.is_channel or dialog.is_group) and query.lower()
in dialog.name.lower():
confirm = input(f"{Fore.YELLOW}Are you sure want to
leave and delete the channel/group '{dialog.name}'?
({Fore.GREEN}y{Fore.YELLOW}/{Fore.RED}n{Fore.YELLOW}): {Style.RESET_ALL}").lower()
if confirm == 'y':
await client.delete_dialog(dialog.entity)
print(f"{Fore.LIGHTGREEN_EX}Left and deleted:
{dialog.name} in session {session_file}.{Style.RESET_ALL}")
else:
print(f"{Fore.WHITE}Cancelled deleting
{dialog.name}.{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}Error deleting channel/group {query} in
session {session_file}: {e}.{Style.RESET_ALL}")
return False
elif delete_type == 'all':
confirm = input(f"{Fore.YELLOW}Are you sure want to leave and
delete all channels/groups? ({Fore.GREEN}y{Fore.YELLOW}/{Fore.RED}n{Fore.YELLOW}):
{Style.RESET_ALL}").lower()
if confirm == 'y':
async for dialog in client.iter_dialogs():
if dialog.is_channel or dialog.is_group:
try:
await client.delete_dialog(dialog.entity)
print(f"{Fore.LIGHTGREEN_EX}Left and deleted:
{dialog.name}{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}Error leaving and deleting
{dialog.name}: {e}{Style.RESET_ALL}")
print(f"{Fore.LIGHTGREEN_EX}Left and deleted all channels and
groups in session {session_file}.{Style.RESET_ALL}")
else:
print(f"{Fore.WHITE}Cancelled deleting channels and groups.
{Style.RESET_ALL}")
return False # Return to previous step if 'n'
return True # If the process completes successfully, return True
from colorama import Fore, Style
async def delete_leave_bots(sessions, sessions_dir, api_id, api_hash):
"""Menu for deleting and leaving bots."""
while True:
print(f"\n{Fore.LIGHTYELLOW_EX}Choose sessions:{Style.RESET_ALL}")
print(f"{Fore.LIGHTCYAN_EX}A. All sessions{Style.RESET_ALL}")
for idx, session in enumerate(sessions):
print(f"{Fore.CYAN}{idx + 1}. {session}")
print(f"{Fore.LIGHTRED_EX}B. Back to home menu{Style.RESET_ALL}")
# Instruction message in white
print(f"{Fore.YELLOW}If you want to select multiple sessions:")
print(f"{Fore.WHITE}-Enter numbers separated by commas[,]
{Fore.LIGHTGREEN_EX}e.g (1,3,5,8)")
print(f"-Enter a range of sessions using hyphen[-] {Fore.LIGHTGREEN_EX}e.g
(1-5 or 5-1)")
print(f"-For all sessions selection {Fore.LIGHTGREEN_EX}'A'")
print(f"{Style.RESET_ALL}")
selected_session = input(f"{Fore.LIGHTYELLOW_EX}Select Session(s) ➣
{Style.RESET_ALL}").lower()
if selected_session == 'a':
selected_sessions = sessions
elif selected_session == 'b':
print(f"{Fore.YELLOW}Returning to home menu.{Style.RESET_ALL}")
return # Return to the home menu
else:
try:
selected_sessions = []
# Check if it's a comma-separated list of numbers
if ',' in selected_session:
selected_indices = [int(num.strip()) - 1 for num in
selected_session.split(',')]
# Check if it's a hyphen-separated range (ascending or descending)
elif '-' in selected_session:
start, end = map(int, selected_session.split('-'))
if start > end:
selected_indices = list(range(start - 1, end - 2, -1)) #
Descending range
else:
selected_indices = list(range(start - 1, end)) # Ascending
range
# If it's a single number
else:
selected_indices = [int(selected_session.strip()) - 1]
# Check if all selected indices are valid
invalid_indices = [index for index in selected_indices if not (0 <=
index < len(sessions))]
if invalid_indices:
print(f"{Fore.RED}Invalid session numbers: {', '.join(str(i +
1) for i in invalid_indices)}. Please try again.{Style.RESET_ALL}")
continue # Return to the selection menu
else:
# Fetch the selected sessions based on indices
selected_sessions = [sessions[i] for i in selected_indices]
except ValueError:
print(f"{Fore.RED}Invalid input. Please enter valid number(s) or
'A' or 'B'.{Style.RESET_ALL}")
continue # Return to the selection menu
# Display the selected sessions in yellow before proceeding
print(f"\n{Fore.LIGHTYELLOW_EX}Selected Sessions:{Style.RESET_ALL}")
for session in selected_sessions:
print(f"{Fore.YELLOW}{session}{Style.RESET_ALL}")
# Proceed to the next step with the selected sessions
await bots_menu(selected_sessions, sessions_dir, api_id, api_hash)
async def bots_menu(sessions, sessions_dir, api_id, api_hash):
"""Menu for handling bots."""
while True:
print(f"\n{Fore.LIGHTYELLOW_EX}Choose an option ➣{Style.RESET_ALL}")
print(f"{Fore.GREEN}1. Delete individual bot{Style.RESET_ALL}")
print(f"{Fore.GREEN}2. Delete all bots{Style.RESET_ALL}")
print(f"{Fore.LIGHTRED_EX}B. Back to session selection{Style.RESET_ALL}")
choice = input(f"{Fore.LIGHTYELLOW_EX}Choose an option ➣
{Style.RESET_ALL}").lower()
if choice == '1':
query = input(f"{Fore.YELLOW}Type bot username or name:
{Style.RESET_ALL}")
result = await process_bots(sessions, sessions_dir, api_id, api_hash,
'individual', query)
if not result:
continue # Go back to the menu if deletion was cancelled
elif choice == '2':
result = await process_bots(sessions, sessions_dir, api_id, api_hash,
'all')
if not result:
continue # Go back to the menu if deletion was cancelled
elif choice == 'b':
print(f"{Fore.YELLOW}Returning to session selection.{Style.RESET_ALL}")
break # Return to session selection
else:
print(f"{Fore.RED}Invalid choice. Please try again.{Style.RESET_ALL}")
async def process_bots(sessions, sessions_dir, api_id, api_hash, delete_type,
query=None):
"""Process sessions to delete bots."""
for session_file in sessions:
session_path = os.path.join(sessions_dir, session_file)
async with TelegramClient(session_path, api_id, api_hash) as client:
print(f"{Fore.WHITE}Connected to: {session_file}")
if delete_type == 'individual' and query:
try:
async for dialog in client.iter_dialogs():
if dialog.entity.__class__.__name__ == 'User' and
dialog.entity.bot and query.lower() in dialog.entity.username.lower():
confirm = input(f"{Fore.YELLOW}Are you sure want to
delete the bot '{dialog.entity.username}'?
({Fore.GREEN}y{Fore.YELLOW}/{Fore.RED}n{Fore.YELLOW}): {Style.RESET_ALL}").lower()
if confirm == 'y':
await client.delete_dialog(dialog.entity)
print(f"{Fore.LIGHTGREEN_EX}Successfully deleted
bot: {dialog.entity.username} in session {session_file}.{Style.RESET_ALL}")
else:
print(f"{Fore.WHITE}Cancelled deleting bot
{dialog.entity.username}.{Style.RESET_ALL}")
return False
except Exception as e:
print(f"{Fore.RED}Error deleting bot {query} in session
{session_file}: {e}.{Style.RESET_ALL}")
return False
elif delete_type == 'all':
confirm = input(f"{Fore.YELLOW}Are you sure want to delete all
bots? ({Fore.GREEN}y{Fore.YELLOW}/{Fore.RED}n{Fore.YELLOW}):
{Style.RESET_ALL}").lower()
if confirm == 'y':
async for dialog in client.iter_dialogs():
if dialog.entity.__class__.__name__ == 'User' and
dialog.entity.bot:
try:
await client.delete_dialog(dialog.entity)
print(f"{Fore.LIGHTGREEN_EX}Successfully deleted
bot: {dialog.entity.username}{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}Error deleting bot
{dialog.entity.username}: {e}{Style.RESET_ALL}")
print(f"{Fore.LIGHTGREEN_EX}Successfully deleted all bots in
session {session_file}.{Style.RESET_ALL}")
else:
print(f"{Fore.WHITE}Cancelled deleting bots.{Style.RESET_ALL}")
return False # Return to previous step if 'n'
return True # If the process completes successfully, return True
async def delete_all_contacts_menu(sessions, sessions_dir, api_id, api_hash):
"""Handle deleting all contacts for selected sessions."""
while True:
print(f"\n{Fore.LIGHTYELLOW_EX}Choose sessions to delete all contacts from:
{Style.RESET_ALL}")
print(f"{Fore.LIGHTCYAN_EX}A. All sessions{Style.RESET_ALL}")
for idx, session in enumerate(sessions):
print(f"{Fore.CYAN}{idx + 1}. {session}")
print(f"{Fore.LIGHTRED_EX}B. Back to home menu{Style.RESET_ALL}")
# Instruction message in white
print(f"{Fore.YELLOW}If you want to select multiple sessions:")
print(f"{Fore.WHITE}-Enter numbers separated by commas[,]
{Fore.LIGHTGREEN_EX}e.g (1,3,5,8)")
print(f"-Enter a range of sessions using hyphen[-] {Fore.LIGHTGREEN_EX}e.g
(1-5 or 5-1)")
print(f"-For all sessions selection {Fore.LIGHTGREEN_EX}'A'")
print(f"{Style.RESET_ALL}")
selected_session = input(f"{Fore.LIGHTYELLOW_EX}Select Session(s) ➣
{Style.RESET_ALL}").lower()
if selected_session == 'a':
selected_sessions = sessions
elif selected_session == 'b':
print(f"{Fore.YELLOW}Returning to home menu.{Style.RESET_ALL}")
return # Return to the home menu
else:
try:
selected_sessions = []
# Check if it's a comma-separated list of numbers
if ',' in selected_session:
selected_indices = [int(num.strip()) - 1 for num in
selected_session.split(',')]
# Check if it's a hyphen-separated range (ascending or descending)
elif '-' in selected_session:
start, end = map(int, selected_session.split('-'))
if start > end:
selected_indices = list(range(start - 1, end - 2, -1)) #
Descending range
else:
selected_indices = list(range(start - 1, end)) # Ascending
range
# If it's a single number
else:
selected_indices = [int(selected_session.strip()) - 1]
# Check if all selected indices are valid
invalid_indices = [index for index in selected_indices if not (0 <=
index < len(sessions))]
if invalid_indices:
print(f"{Fore.RED}Invalid session numbers: {', '.join(str(i +
1) for i in invalid_indices)}. Please try again.{Style.RESET_ALL}")
continue # Return to the selection menu
else:
# Fetch the selected sessions based on indices
selected_sessions = [sessions[i] for i in selected_indices]
except ValueError:
print(f"{Fore.RED}Invalid input. Please enter valid number(s) or
'A' or 'B'.{Style.RESET_ALL}")
continue # Return to the selection menu
# Display the selected sessions in yellow before proceeding
print(f"\n{Fore.LIGHTYELLOW_EX}Selected Sessions:{Style.RESET_ALL}")
for session in selected_sessions:
print(f"{Fore.YELLOW}{session}{Style.RESET_ALL}")
# Proceed to the next step with the selected sessions
await delete_all_contacts(selected_sessions, sessions_dir, api_id,
api_hash)
async def delete_all_contacts(sessions, sessions_dir, api_id, api_hash):
"""Delete all contacts from the selected sessions."""
for session_file in sessions:
session_path = os.path.join(sessions_dir, session_file)
async with TelegramClient(session_path, api_id, api_hash) as client:
print(f"{Fore.WHITE}Connected to: {session_file}")
try:
contacts = await
client(functions.contacts.GetContactsRequest(hash=0))
if contacts.users:
# Show the number of contacts found
number_of_contacts = len(contacts.users)
print(f"\n{Fore.LIGHTGREEN_EX}{number_of_contacts} contact(s)
{Fore.WHITE}found in {session_file}.")
if number_of_contacts > 100:
print(f"{Fore.LIGHTBLACK_EX}The number of contacts exceeds
50. Bot can only delete maximum 50 contacts at once")
print(f"{Fore.LIGHTBLACK_EX}If you delete more than 50
contacts, you need to try multiple times or wait for a while before retrying")
confirm = input(f"{Fore.YELLOW}Are you sure want to delete all
contacts in {session_file}? ({Fore.GREEN}y{Fore.YELLOW}/{Fore.RED}n{Fore.YELLOW}):
{Style.RESET_ALL} ").lower()
if confirm == 'y':
for user in contacts.users:
while True:
try:
await
client(functions.contacts.DeleteContactsRequest(id=[user.id]))
print(f"{Fore.LIGHTGREEN_EX}Deleted contact:
{user.first_name} {user.last_name or ''}")
break # Break the loop if the contact is
successfully deleted
except FloodWaitError as e:
print(f"{Fore.RED}Rate limited: Must wait
{e.seconds} seconds before retrying.")
time.sleep(e.seconds) # Wait for the required
time before retrying
# Prompt user whether to wait or return to main
menu
while True:
choice = input(f"{Fore.YELLOW}Do you want
to wait or try again later?\n1. Wait\n2. Try again later\nChoose an option (1/2):
")
if choice == '1':
print(f"{Fore.RED}Waiting for
{e.seconds} seconds...")
await asyncio.sleep(e.seconds) # Wait
for the flood wait duration
break # Exit this inner loop and retry
deletion
elif choice == '2':
print("{Fore.YELLOW}Returning to the
main menu.")
return # Exit completely and return to
the main menu
else:
print("{Fore.RED}Invalid input. Please
enter 1 to wait or 2 to try again later.")
except Exception as e:
print(f"{Fore.RED}Error deleting contact
{user.first_name}: {Fore.YELLOW}{e}")
break # Break the loop on other exceptions
print(f"{Fore.LIGHTGREEN_EX}All contacts deleted for
{session_file}.")
else:
print(f"{Fore.WHITE}Cancelled deleting contacts in
{session_file}.")
else:
print(f"{Fore.LIGHTWHITE_EX}No contacts found in
{session_file}.")
except Exception as e:
print(f"{Fore.RED}Error accessing contacts for {session_file}:
{Fore.YELLOW}{e}")
async def delete_contact(client, user):
"""Delete a single contact and handle rate limits."""
while True:
try:
await client(functions.contacts.DeleteContactsRequest(id=[user.id]))
print(f"{Fore.LIGHTGREEN_EX}Deleted contact: {Fore.CYAN}
{user.first_name} {user.last_name or ''}{Style.RESET_ALL}")
break # Exit loop after successful deletion
except FloodWaitError as e:
print(f"{Fore.RED}Rate limited: Must wait {Fore.LIGHTCYAN_EX}
{e.seconds} seconds{Fore.RED} before retrying.{Style.RESET_ALL}")
# Ask the user if they want to wait or return to the main menu
while True:
choice = input(f"{Fore.LIGHTYELLOW_EX}Do you want to wait or try
again later?\n{Fore.CYAN}1. Wait\n{Fore.CYAN}2. Try again later\
n{Fore.YELLOW}Choose an option (1/2): {Style.RESET_ALL}")
if choice == '1':
print(f"{Fore.LIGHTCYAN_EX}Waiting for {e.seconds} seconds...
{Style.RESET_ALL}")
await asyncio.sleep(e.seconds) # Wait for the rate limit
period
break # Retry after the wait
elif choice == '2':
print(f"{Fore.YELLOW}Returning to the main menu.
{Style.RESET_ALL}")
return # Exit completely and return to the main menu
else:
print(f"{Fore.RED}Invalid input. Please enter
{Fore.CYAN}1{Fore.RED} to wait or {Fore.CYAN}2{Fore.RED} to try again later.
{Style.RESET_ALL}")
except Exception as e:
print(f"{Fore.RED}Error deleting contact {Fore.CYAN}{user.first_name}
{Fore.RED}: {Fore.YELLOW}{e}{Style.RESET_ALL}")
break # Break loop on unknown error
async def main():
ascii_title() # Show the title at the start
print_logo() # Show the logo after the title
print(Fore.LIGHTCYAN_EX + "Developed By: SI THU LIN" + Style.RESET_ALL)
print('')
# Add the notice text with purple color
print(Fore.LIGHTBLACK_EX + "Go to link for Guide" + Style.RESET_ALL)
print(Fore.LIGHTBLUE_EX + "https://t.me/guide" + Style.RESET_ALL)
print('')
api_id = 123456 # Replace with your actual API ID (as an integer)
api_hash = 'abcdef1234567890abcdef1234567890' # Replace with your actual API
Hash (as a string)
while True:
sessions_dir = input(f"{Fore.WHITE}Enter the {Fore.LIGHTYELLOW_EX}'Folder
Name' {Fore.WHITE}containing the session files: {Style.RESET_ALL}").strip() or
"sessions"
sessions = list_sessions(sessions_dir)
if sessions:
break
else:
print(f"{Fore.RED}No session files found in '{sessions_dir}'. Please
try again.{Style.RESET_ALL}")
while True:
print(f"\n{Fore.LIGHTWHITE_EX}====.🤖.< Menu>.🤖.====")
print(f"\n{Fore.LIGHTCYAN_EX}[1]{Fore.LIGHTGREEN_EX} ▶️ Clear Individual
Chats{Style.RESET_ALL}")
print(f"{Fore.LIGHTCYAN_EX}[2]{Fore.LIGHTGREEN_EX} ▶️ Delete & Leave
(Channels, Groups){Style.RESET_ALL}")
print(f"{Fore.LIGHTCYAN_EX}[3]{Fore.LIGHTGREEN_EX} ▶️ Delete & Leave (Bots)
{Style.RESET_ALL}")
print(f"{Fore.LIGHTCYAN_EX}[4]{Fore.LIGHTGREEN_EX} ▶️ Delete All
Contacts{Style.RESET_ALL}")
print(f"{Fore.LIGHTRED_EX}[E]{Fore.GREEN} ▶️
{Fore.LIGHTRED_EX}Exit{Style.RESET_ALL}")
choice = input(Fore.LIGHTYELLOW_EX + "Choose an option ➣ " +
Style.RESET_ALL).lower()
if choice == '1':
await clear_individual_chats(sessions, sessions_dir, api_id, api_hash)
elif choice == '2':
await delete_leave_channels_groups(sessions, sessions_dir, api_id,
api_hash)
elif choice == '3':
await delete_leave_bots(sessions, sessions_dir, api_id, api_hash)
elif choice == '4':
await delete_all_contacts_menu(sessions, sessions_dir, api_id,
api_hash)
elif choice == 'e':
print(Fore.LIGHTGREEN_EX + "GOOD BYE." + Style.RESET_ALL)
break
else:
print(Fore.RED + "Invalid choice. Please try again." + Style.RESET_ALL)
if __name__ == "__main__":
asyncio.run(main())