Download app.py from Vvbbnnn/Gvbbn: direct link, hf CLI and curl.
- Browser
- Download file 16.1 kB
-
https://huggingface.co/spaces/Vvbbnnn/Gvbbn/resolve/main/app.py
- Command line
-
hf download hf://spaces/Vvbbnnn/Gvbbn/app.py
-
curl -L -o app.py https://huggingface.co/spaces/Vvbbnnn/Gvbbn/resolve/main/app.py
16.1 kB
| import os | |
| import sys | |
| import logging | |
| import nest_asyncio | |
| import random | |
| import asyncio | |
| import pytz | |
| from flask import Flask | |
| from threading import Thread | |
| from datetime import datetime, timedelta | |
| from pymongo import MongoClient | |
| from apscheduler.schedulers.asyncio import AsyncIOScheduler | |
| from apscheduler.triggers.cron import CronTrigger | |
| from telethon import TelegramClient, events, Button | |
| from telethon.sessions import StringSession | |
| from telethon.tl import functions | |
| import re | |
| # βββββ Utils βββββ | |
| adjectives = ["Silent", "Crazy", "Golden", "Hidden", "Brave", "Fierce", "Mysterious", "Savage", "Royal", "Witty", "Legendary", "Epic", "Noble", "Clever", "Loyal", "Wild", "Electric", "Fearless", "Crimson", "Frozen", "Charming", "Rebel", "Turbo", "Lone", "Radiant", "Raging", "Dusty", "Majestic", "Grumpy", "Shadow"] | |
| nouns = ["Warriors", "Coders", "Friends", "Legends", "Pirates", "Tigers", "Wolves", "Hackers", "Ninjas", "Riders", "Hunters", "Kings", "Queens", "Giants", "Lords", "Champions", "Stormers", "Creators", "Ghosts", "Wizards", "Knights", "Samurais", "Explorers", "Titans", "Outlaws", "Rebels", "Squad", "Troopers", "Dreamers", "Avengers"] | |
| logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(message)s", stream=sys.stdout) | |
| log = logging.getLogger("app") | |
| nest_asyncio.apply() | |
| API_ID = int(os.getenv("API_ID", 3704772)) | |
| API_HASH = os.getenv("API_HASH", "b8e50a035abb851c0dd424e14cac4c06") | |
| BOT_TOKEN = os.getenv("BOT_TOKEN") | |
| MONGO_URI = os.getenv("MONGO_URI") | |
| ADMIN_ID = int(os.getenv("ADMIN_ID", 6574063018)) | |
| client = MongoClient(MONGO_URI) | |
| db = client["telethon_bots"] | |
| accounts = db["accounts"] | |
| plans = db["plans"] | |
| group_logs= db["group_logs"] | |
| bot = TelegramClient("bot", API_ID, API_HASH) | |
| userbots = {} | |
| scheduler = AsyncIOScheduler() | |
| def random_group_name(): | |
| return f"{random.choice(adjectives)} {random.choice(nouns)}" | |
| # Timezone | |
| tz = pytz.timezone("Asia/Kolkata") | |
| # Dummy userbot registry | |
| userbots = {} # Fill this with: {user_id: bot_instance} | |
| import random | |
| def create_plan(account, limit): | |
| now = datetime.now(tz) | |
| end_of_day = now.replace(hour=23, minute=59, second=59, microsecond=0) | |
| times = set() | |
| while len(times) < limit: | |
| # Generate random seconds from now to end of day | |
| delta_seconds = int((end_of_day - now).total_seconds()) | |
| random_offset = random.randint(60, delta_seconds) # at least 1 min from now | |
| random_time = now + timedelta(seconds=random_offset) | |
| times.add(random_time.replace(microsecond=0)) # avoid microsecond collisions | |
| for t in sorted(times): | |
| plans.insert_one({ | |
| "account_id": account["_id"], | |
| "scheduled_time": t.isoformat(), | |
| "created": 0 # optional: placeholder for future use | |
| }) | |
| print(f"β Created {len(times)} random plan(s) for account {account['_id']}") | |
| def apply_plan(): | |
| now = datetime.now(tz) | |
| count = 0 | |
| for plan in plans.find(): | |
| try: | |
| plan_time = datetime.fromisoformat(plan["scheduled_time"]).astimezone(tz) | |
| if plan_time <= now: | |
| continue # Skip past plans | |
| account = accounts.find_one({"_id": plan["account_id"]}) | |
| if not account: | |
| print(f"β οΈ No account found for plan {plan['_id']}") | |
| continue | |
| userbot = userbots.get(account["user_id"]) | |
| if not userbot: | |
| print(f"β οΈ No userbot for account {account['_id']}, skipping...") | |
| continue | |
| async def job_wrapper(ub=userbot, acc=account, pl=plan): | |
| await auto_create_groups(ub, acc, pl) | |
| job_id = f"job_{plan['_id']}" | |
| scheduler.add_job( | |
| job_wrapper, | |
| trigger='date', | |
| run_date=plan_time, | |
| id=job_id, | |
| name=f"AutoGroupPlan_{account['_id']}" | |
| ) | |
| print(f"π Scheduled job for account {account['_id']} at {plan_time.strftime('%H:%M:%S')} (ID: {job_id})") | |
| count += 1 | |
| except Exception as e: | |
| print(f"β Error scheduling plan {plan.get('_id')}: {e}") | |
| print(f"β Applied and scheduled {count} job(s).") | |
| def reset_and_plan(): | |
| print("π Resetting plans and scheduling new ones...") | |
| plans.delete_many({}) | |
| for acc in accounts.find(): | |
| limit = random.randint(3, 5) | |
| create_plan(acc, limit) | |
| apply_plan() | |
| print("β Plans created and scheduled.") | |
| # Schedule reset daily at 00:00 IST | |
| scheduler.add_job(reset_and_plan, CronTrigger(hour=0, minute=0, timezone="Asia/Kolkata"), id="daily_reset_job", replace_existing=True) | |
| # Telethon /reset command | |
| async def handle_reset(event): | |
| sender = await event.get_sender() | |
| if sender.id != ADMIN_ID: | |
| return await event.reply("β You are not authorized to run this command.") | |
| for job in scheduler.get_jobs(): | |
| if job.func.__name__ == "reset_and_plan" or job.id == "daily_reset_job": | |
| job.remove() | |
| reset_and_plan() | |
| scheduler.add_job(reset_and_plan, CronTrigger(hour=0, minute=0, timezone="Asia/Kolkata"), id="daily_reset_job", replace_existing=True) | |
| await event.reply("β Schedule reset and re-planned for tonight 00:00 IST.") | |
| async def handle_stats(event): | |
| tz = pytz.timezone("Asia/Kolkata") | |
| now = datetime.now(tz) | |
| msg = "π **Today's Schedule:**\n\n" | |
| msg += f"ποΈ Date: {now.strftime('%d/%m/%Y')}\n" | |
| msg += f"π Time: {now.strftime('%I:%M %p')} IST\n\n" | |
| plans_today = list(plans.find()) | |
| if not plans_today: | |
| return await event.reply("π No plans found today.") | |
| def fake_strike(text): | |
| return ''.join(c + '\u0336' for c in text) | |
| account_times = {} | |
| for plan in plans_today: | |
| acc = accounts.find_one({"_id": plan["account_id"]}) | |
| if not acc: | |
| continue | |
| name = acc["name"] | |
| time_obj = datetime.fromisoformat(plan["scheduled_time"]).astimezone(tz) | |
| time_str = time_obj.strftime("%I:%M %p") | |
| if name not in account_times: | |
| account_times[name] = [] | |
| if time_obj < now: | |
| mono_strike = fake_strike(time_str) | |
| account_times[name].append(f"`{mono_strike}`") | |
| else: | |
| account_times[name].append(f"`{time_str}`") | |
| for name, times in account_times.items(): | |
| msg += f"π€ **{name}** β {', '.join(times)}\n\n" | |
| next_run = None | |
| for job in scheduler.get_jobs(): | |
| if job.id == "daily_reset_job": | |
| next_run = job.next_run_time | |
| break | |
| if next_run: | |
| msg += f"π Next Reset: `{next_run.astimezone(tz).strftime('%d/%m/%Y %I:%M %p')} IST`" | |
| await event.reply(msg, parse_mode='md') | |
| async def auto_create_groups(userbot, acc_doc, plan_doc=None): | |
| try: | |
| title = random_group_name() | |
| result = await userbot(functions.channels.CreateChannelRequest( | |
| title=title, | |
| about=",", | |
| megagroup=True | |
| )) | |
| group = result.chats[0] | |
| group_id = group.id | |
| for _ in range(4): | |
| await userbot.send_message(group_id, random_group_name()) | |
| await asyncio.sleep(2) | |
| try: | |
| stickers = ["CAACAgUAAxkBAAEKZStlTxkC-cvQJwABvHoUjRacAVIHCFcAAgECAALaTqVVCpx_Lc2ZoLguBA"] | |
| await userbot.send_file(group_id, random.choice(stickers)) | |
| except: | |
| pass | |
| if plan_doc: | |
| plans.update_one({"_id": plan_doc["_id"]}, {"$inc": {"created": 1}}) | |
| # Save for cleanup | |
| group_logs.insert_one({ | |
| "group_id": group_id, | |
| "account_id": acc_doc["_id"], | |
| "created_on": datetime.now(tz).isoformat() | |
| }) | |
| info = await userbot.get_me() | |
| except Exception as e: | |
| await bot.send_message(ADMIN_ID, f"β Group creation failed for {acc_doc['name']}: {e}") | |
| log.error(f"β Group creation failed: {e}") | |
| async def start_userbot(session_str, owner_id): | |
| try: | |
| userbot = TelegramClient(StringSession(session_str), API_ID, API_HASH) | |
| await userbot.start() | |
| info = await userbot.get_me() | |
| if accounts.find_one({"user_id": info.id}): | |
| return None | |
| doc = { | |
| "user_id": info.id, | |
| "name": info.first_name, | |
| "username": info.username or None, | |
| "session": session_str, | |
| "created": 0, | |
| "owner_id": owner_id, | |
| "added_on": datetime.utcnow() | |
| } | |
| accounts.insert_one(doc) | |
| userbots[info.id] = userbot | |
| asyncio.create_task(userbot.run_until_disconnected()) | |
| return info | |
| except Exception as e: | |
| log.info(f"β Failed to add account: {e}") | |
| return None | |
| async def load_all_userbots(): | |
| log.info("π Loading all stored userbots...") | |
| for acc in accounts.find(): | |
| try: | |
| ub = TelegramClient(StringSession(acc["session"]), API_ID, API_HASH) | |
| await ub.start() | |
| userbots[acc["user_id"]] = ub | |
| asyncio.create_task(ub.run_until_disconnected()) | |
| log.info(f"β Loaded: {acc['name']} (@{acc.get('username', 'N/A')})") | |
| except Exception as e: | |
| await bot.send_message(ADMIN_ID, f"β Failed to start {acc['name']}") | |
| log.info(f"β Failed to start {acc['name']}: {e}") | |
| # βββββ Bot Commands βββββ | |
| async def start_cmd(event): | |
| if event.sender_id != ADMIN_ID: | |
| return | |
| await event.reply( | |
| "π Welcome!\n\n" | |
| "/addacc β Add account\n" | |
| "/delacc β Delete an account\n" | |
| "/total β Count of connected accounts\n" | |
| "/stats β View today's schedule\n" | |
| "/reset β Reset and re-plan daily schedule\n" | |
| "/create <account_name> β Create groups for the specified account\n" | |
| "/help β Show this help message" | |
| ) | |
| async def help_cmd(event): | |
| if event.sender_id != ADMIN_ID: | |
| return | |
| await event.reply( | |
| "π οΈ **Bot Commands Help:**\n\n" | |
| "/start β Start the bot and see the available commands\n" | |
| "/addacc β Add a new account to the bot\n" | |
| "/delacc β Delete an existing account\n" | |
| "/total β Get the total count of connected accounts\n" | |
| "/stats β View today's scheduling plan for accounts\n" | |
| "/reset β Reset and plan the schedule for the new day\n" | |
| "/create <account_name> β Create groups for the specified account\n" | |
| "/help β Show this help message\n\n" | |
| "These commands are available to the admin only." | |
| ) | |
| async def addacc_cmd(event): | |
| if event.sender_id != ADMIN_ID: | |
| return | |
| async with bot.conversation(event.chat_id, timeout=60) as conv: | |
| await conv.send_message("βοΈ Send your String Session:") | |
| session_msg = await conv.get_response() | |
| session_str = session_msg.text.strip() | |
| info = await start_userbot(session_str, event.sender_id) | |
| if info: | |
| await conv.send_message(f"β Added: {info.first_name} (@{info.username or 'N/A'})") | |
| else: | |
| await conv.send_message("β οΈ Already added or failed.") | |
| async def total_accounts_cmd(event): | |
| if event.sender_id != ADMIN_ID: | |
| return | |
| count = accounts.count_documents({}) | |
| await event.respond(f"π Total connected: **{count}**") | |
| async def delacc_cmd(event): | |
| if event.sender_id != ADMIN_ID: | |
| return | |
| user_accs = list(accounts.find({"owner_id": ADMIN_ID})) | |
| if not user_accs: | |
| await event.reply("πΆ No accounts.") | |
| return | |
| buttons, row = [], [] | |
| for idx, acc in enumerate(user_accs, 1): | |
| row.append(Button.inline(f"{acc['name']} (@{acc.get('username', 'N/A')})", data=f"del_{acc['user_id']}")) | |
| if idx % 2 == 0: | |
| buttons.append(row) | |
| row = [] | |
| if row: | |
| buttons.append(row) | |
| await event.respond("Select to delete:", buttons=buttons) | |
| async def handle_delete(event): | |
| if event.sender_id != ADMIN_ID: | |
| return | |
| user_id = int(event.data.decode().split("_")[1]) | |
| acc_doc = accounts.find_one({"user_id": user_id}) | |
| if not acc_doc: | |
| await event.answer("Not found.", alert=True) | |
| return | |
| await event.edit(f"β οΈ Confirm delete {acc_doc['name']}?", buttons=[ | |
| [Button.inline("β Confirm", data=f"confdel_{user_id}"), Button.inline("β Cancel", data=b"cancel")] | |
| ]) | |
| async def confirm_delete(event): | |
| if event.sender_id != ADMIN_ID: | |
| return | |
| user_id = int(event.data.decode().split("_")[1]) | |
| acc_doc = accounts.find_one_and_delete({"user_id": user_id}) | |
| if acc_doc: | |
| try: | |
| if user_id in userbots: | |
| await userbots[user_id].disconnect() | |
| del userbots[user_id] | |
| await event.edit(f"β Deleted: {acc_doc['name']}") | |
| await bot.send_message(ADMIN_ID, f"ποΈ Deleted: {acc_doc['name']} (@{acc_doc.get('username', 'N/A')})") | |
| log.info(f"ποΈ Deleted account: {acc_doc['name']} (@{acc_doc.get('username', 'N/A')})") | |
| except Exception as e: | |
| await event.edit(f"Deleted from DB, error stopping: {e}") | |
| else: | |
| await event.edit("β οΈ Not found.") | |
| async def cancel_cb(event): | |
| if event.sender_id != ADMIN_ID: | |
| return | |
| await event.edit("β Cancelled.") | |
| async def pick_create_callback(event): | |
| if event.sender_id != ADMIN_ID: | |
| return | |
| user_id = int(event.data.decode().split("_")[1]) | |
| acc_doc = accounts.find_one({"user_id": user_id}) | |
| if not acc_doc: | |
| await event.answer("Account not found.", alert=True) | |
| return | |
| if user_id not in userbots: | |
| await event.answer("Account is not active.", alert=True) | |
| return | |
| await event.edit(f"β³ Creating groups for {acc_doc['name']}...") | |
| await auto_create_groups(userbots[user_id], acc_doc) | |
| async def create_group_cmd(event): | |
| query = event.pattern_match.group(1).strip() | |
| safe_query = re.escape(query) | |
| matches = list(accounts.find({ | |
| "$or": [ | |
| {"name": {"$regex": safe_query, "$options": "i"}}, | |
| {"username": {"$regex": safe_query, "$options": "i"}} | |
| ] | |
| })) | |
| if not matches: | |
| await event.reply("β No matching account found.") | |
| return | |
| if len(matches) == 1: | |
| acc_doc = matches[0] | |
| user_id = acc_doc["user_id"] | |
| if user_id not in userbots: | |
| await event.reply("β οΈ Account is not active.") | |
| return | |
| await event.reply(f"β³ Creating groups for {acc_doc['name']}...") | |
| await auto_create_groups(userbots[user_id], acc_doc) | |
| else: | |
| buttons = [] | |
| for acc in matches: | |
| label = f"{acc['name']} (@{acc.get('username', 'N/A')})" | |
| buttons.append([Button.inline(label, data=f"pickcreate_{acc['user_id']}")]) | |
| await event.respond("β οΈ Multiple matches found. Select the correct account:", buttons=buttons) | |
| # βββββ Flask App βββββ | |
| app = Flask(__name__) | |
| def home(): | |
| return "β Channel-making bot is running." | |
| def run_flask(): | |
| app.run(host="0.0.0.0", port=7860, use_reloader=False) | |
| # βββββ Main Startup βββββ | |
| async def main(): | |
| Thread(target=run_flask).start() | |
| scheduler.start() | |
| await load_all_userbots() | |
| await bot.start(bot_token=BOT_TOKEN) | |
| log.info("π€ Bot is now running on Hugging Face") | |
| await bot.run_until_disconnected() | |
| if __name__ == "__main__": | |
| asyncio.run(main()) | |