Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import asyncio | |
| from telethon.sync import TelegramClient | |
| from telethon.errors import FloodWaitError | |
| from telethon.tl.types import ChannelParticipantsAdmins | |
| # π Your fixed API credentials | |
| api_id = 29716085 | |
| api_hash = '75073ce12878f4e510bbaae6642a9752' | |
| # Get user's channels | |
| async def fetch_channels(session_name): | |
| async with TelegramClient(session_name, api_id, api_hash) as client: | |
| dialogs = await client.get_dialogs(limit=100) | |
| channels = [d for d in dialogs if d.is_channel] | |
| return [(ch.name, ch.id) for ch in channels] | |
| # Remove non-admin, non-whitelisted users | |
| async def remove_members(session_name, channel_id, allowed_user_ids_str): | |
| output = [] | |
| allowed_ids = {int(uid.strip()) for uid in allowed_user_ids_str.split(',') if uid.strip().isdigit()} | |
| async with TelegramClient(session_name, api_id, api_hash) as client: | |
| me = await client.get_me() | |
| output.append(f"Logged in as: {me.username or me.first_name} (ID: {me.id})") | |
| channel = await client.get_entity(channel_id) | |
| output.append(f"Selected Channel: {channel.title}") | |
| admins = await client.get_participants(channel, filter=ChannelParticipantsAdmins) | |
| admin_ids = {admin.id for admin in admins} | |
| exclude_ids = admin_ids.union({me.id}, allowed_ids) | |
| output.append(f"Total admins (including you): {len(admin_ids)}") | |
| output.append(f"Starting to remove members (excluding {len(exclude_ids)} allowed users)...") | |
| total_removed = 0 | |
| async for user in client.iter_participants(channel): | |
| if user.id in exclude_ids: | |
| continue | |
| try: | |
| await client.kick_participant(channel, user.id) | |
| output.append(f"Removed: {user.first_name or user.username} (ID: {user.id})") | |
| total_removed += 1 | |
| except FloodWaitError as e: | |
| output.append(f"FloodWait: Need to wait {e.seconds} seconds.") | |
| await asyncio.sleep(e.seconds) | |
| try: | |
| await client.kick_participant(channel, user.id) | |
| output.append(f"Retried and removed: {user.first_name or user.username} (ID: {user.id})") | |
| total_removed += 1 | |
| except Exception as e2: | |
| output.append(f"Retry failed for {user.id}: {e2}") | |
| except Exception as e: | |
| output.append(f"Could not remove {user.id}: {e}") | |
| output.append(f"\nβ Done. Total members removed: {total_removed}") | |
| return "\n".join(output) | |
| # Wrappers | |
| def list_channels(session_name): | |
| return asyncio.run(fetch_channels(session_name)) | |
| def cleanup_members(session_name, channel_id, allowed_users): | |
| return asyncio.run(remove_members(session_name, channel_id, allowed_users)) | |
| # Gradio UI | |
| with gr.Blocks() as app: | |
| gr.Markdown("## π§Ή Telegram Channel Cleaner (Telethon + Gradio)") | |
| session_name = gr.Textbox(label="Session Name", placeholder="e.g., mysession") | |
| get_channels_btn = gr.Button("π₯ Fetch Channels") | |
| channel_dropdown = gr.Dropdown(label="Select Channel", choices=[], interactive=True) | |
| allowed_users = gr.Textbox( | |
| label="Allowed User IDs (comma-separated)", | |
| placeholder="e.g., 12345678,87654321" | |
| ) | |
| run_button = gr.Button("π Run Cleanup") | |
| output_log = gr.Textbox(label="Output Log", lines=20, interactive=False) | |
| def populate_channels(session_name): | |
| try: | |
| channels = list_channels(session_name) | |
| return gr.update(choices=[(name, id) for name, id in channels], value=None) | |
| except Exception as e: | |
| return gr.update(choices=[], value=None), f"β Error: {e}" | |
| get_channels_btn.click( | |
| populate_channels, | |
| inputs=[session_name], | |
| outputs=[channel_dropdown] | |
| ) | |
| run_button.click( | |
| cleanup_members, | |
| inputs=[session_name, channel_dropdown, allowed_users], | |
| outputs=[output_log] | |
| ) | |
| app.launch() | |