# app.py from flask import Flask, render_template, jsonify, request from pyrogram import Client import os import psutil import time import shutil import asyncio from utils import get_settings, save_group_settings, get_size, humanbytes, get_time, admin_check from database.users_chats_db import db from database.ia_filterdb import Media, get_search_results, get_file_details, save_file from database.filters_mdb import add_filter, get_filters, delete_filter, del_all from database.gfilters_mdb import add_gfilter, get_gfilters, delete_gfilter, del_allg from database.connections_mdb import add_connection, all_connections, if_active, delete_connection, make_active, make_inactive from info import ADMINS, LOG_CHANNEL, CHANNELS, DATABASE_URL, DATABASE_NAME, CACHE_TIME, API_ID, API_HASH, BOT_TOKEN, UPTIME, WEB_SUPPORT, LOG_MSG from pymongo import MongoClient app = Flask(__name__) # Initialize Pyrogram Client bot = Client( name="Professor-Bot", api_id=API_ID, api_hash=API_HASH, bot_token=BOT_TOKEN, plugins=dict(root="plugins") ) # Initialize MongoDB Client mongo_client = MongoClient(DATABASE_URL) mongo_db = mongo_client[DATABASE_NAME] @app.route('/') def dashboard(): return render_template('dashboard.html') @app.route('/api/system-info') def system_info(): uptime = time.time() - UPTIME uptime_str = get_time(uptime) storage = shutil.disk_usage("/") return jsonify({ "os": { "name": os.name, "version": os.uname().version }, "uptime": uptime_str, "storage": { "total": storage.total, "free": storage.free } }) @app.route('/api/bot-stats') def bot_stats(): loop = asyncio.get_event_loop() total_files = loop.run_until_complete(Media.count_documents()) total_users = loop.run_until_complete(db.total_users_count()) total_chats = loop.run_until_complete(db.total_chat_count()) monsize = loop.run_until_complete(db.get_db_size()) free = 536870912 - monsize monsize = get_size(monsize) free = get_size(free) return jsonify({ "total_files": total_files, "total_users": total_users, "total_chats": total_chats, "storage_used": monsize, "storage_free": free }) @app.route('/api/filters') def get_filters_api(): chat_id = request.args.get('chat_id') if not chat_id: return jsonify({"error": "Chat ID is required"}), 400 loop = asyncio.get_event_loop() filters = loop.run_until_complete(get_filters(chat_id)) return jsonify({"filters": filters}) @app.route('/api/add-filter', methods=['POST']) def add_filter_api(): chat_id = request.form.get('chat_id') text = request.form.get('text') reply_text = request.form.get('reply_text') btn = request.form.get('btn') file = request.form.get('file') alert = request.form.get('alert') if not chat_id or not text or not reply_text: return jsonify({"error": "Chat ID, text, and reply text are required"}), 400 loop = asyncio.get_event_loop() loop.run_until_complete(add_filter(chat_id, text, reply_text, btn, file, alert)) return jsonify({"message": "Filter added successfully"}) @app.route('/api/delete-filter', methods=['POST']) def delete_filter_api(): chat_id = request.form.get('chat_id') text = request.form.get('text') if not chat_id or not text: return jsonify({"error": "Chat ID and text are required"}), 400 loop = asyncio.get_event_loop() loop.run_until_complete(delete_filter(request, text, chat_id)) return jsonify({"message": "Filter deleted successfully"}) @app.route('/api/gfilters') def get_gfilters_api(): gfilters = 'gfilters' loop = asyncio.get_event_loop() filters = loop.run_until_complete(get_gfilters(gfilters)) return jsonify({"filters": filters}) @app.route('/api/add-gfilter', methods=['POST']) def add_gfilter_api(): gfilters = 'gfilters' text = request.form.get('text') reply_text = request.form.get('reply_text') btn = request.form.get('btn') file = request.form.get('file') alert = request.form.get('alert') if not text or not reply_text: return jsonify({"error": "Text and reply text are required"}), 400 loop = asyncio.get_event_loop() loop.run_until_complete(add_gfilter(gfilters, text, reply_text, btn, file, alert)) return jsonify({"message": "Global filter added successfully"}) @app.route('/api/delete-gfilter', methods=['POST']) def delete_gfilter_api(): gfilters = 'gfilters' text = request.form.get('text') if not text: return jsonify({"error": "Text is required"}), 400 loop = asyncio.get_event_loop() loop.run_until_complete(delete_gfilter(request, text, gfilters)) return jsonify({"message": "Global filter deleted successfully"}) @app.route('/api/users') def get_users_api(): loop = asyncio.get_event_loop() users = loop.run_until_complete(db.get_all_users()) user_list = [] loop.run_until_complete(asyncio.gather(*(user_list.append({ "id": user['id'], "name": user['name'], "ban_status": user['ban_status'] }) for user in users))) return jsonify({"users": user_list}) @app.route('/api/chats') def get_chats_api(): loop = asyncio.get_event_loop() chats = loop.run_until_complete(db.get_all_chats()) chat_list = [] loop.run_until_complete(asyncio.gather(*(chat_list.append({ "id": chat['id'], "title": chat['title'], "username": chat['username'], "chat_status": chat['chat_status'] }) for chat in chats))) return jsonify({"chats": chat_list}) @app.route('/api/files') def get_files_api(): loop = asyncio.get_event_loop() files = loop.run_until_complete(Media.find().to_list(None)) file_list = [] for file in files: file_list.append({ "file_id": file['file_id'], "file_name": file['file_name'], "file_size": file['file_size'], "file_type": file['file_type'], "mime_type": file['mime_type'], "caption": file['caption'] }) return jsonify({"files": file_list}) @app.route('/api/add-file', methods=['POST']) def add_file_api(): if 'fileUpload' not in request.files: return jsonify({"error": "No file part"}), 400 file = request.files['fileUpload'] if file.filename == '': return jsonify({"error": "No selected file"}), 400 if file: file_path = os.path.join("/app/uploads", file.filename) file.save(file_path) loop = asyncio.get_event_loop() file_id, file_ref = loop.run_until_complete(save_file(file_path)) os.remove(file_path) return jsonify({"file_id": file_id, "file_ref": file_ref, "message": "File uploaded successfully"}) return jsonify({"error": "Failed to upload file"}), 500 @app.route('/api/delete-file', methods=['POST']) def delete_file_api(): file_id = request.form.get('file_id') if not file_id: return jsonify({"error": "File ID is required"}), 400 loop = asyncio.get_event_loop() result = loop.run_until_complete(Media.collection.delete_one({'_id': file_id})) if result.deleted_count: return jsonify({"message": "File deleted successfully"}) else: return jsonify({"error": "File not found"}), 404 @app.route('/api/settings/') def get_settings_api(chat_id): loop = asyncio.get_event_loop() settings = loop.run_until_complete(get_settings(chat_id)) return jsonify({"settings": settings}) @app.route('/api/save-settings', methods=['POST']) def save_settings_api(): chat_id = request.form.get('chat_id') setting_key = request.form.get('setting_key') setting_value = request.form.get('setting_value') if not chat_id or not setting_key or not setting_value: return jsonify({"error": "Chat ID, setting key, and setting value are required"}), 400 loop = asyncio.get_event_loop() loop.run_until_complete(save_group_settings(chat_id, setting_key, setting_value)) return jsonify({"message": "Settings saved successfully"}) @app.route('/api/ban-user', methods=['POST']) def ban_user_api(): user_id = request.form.get('user_id') ban_reason = request.form.get('ban_reason', "No Reason") if not user_id: return jsonify({"error": "User ID is required"}), 400 loop = asyncio.get_event_loop() loop.run_until_complete(db.ban_user(int(user_id), ban_reason)) temp.BANNED_USERS.append(int(user_id)) return jsonify({"message": "User banned successfully"}) @app.route('/api/unban-user', methods=['POST']) def unban_user_api(): user_id = request.form.get('user_id') if not user_id: return jsonify({"error": "User ID is required"}), 400 loop = asyncio.get_event_loop() loop.run_until_complete(db.remove_ban(int(user_id))) temp.BANNED_USERS.remove(int(user_id)) return jsonify({"message": "User unbanned successfully"}) @app.route('/api/disable-chat', methods=['POST']) def disable_chat_api(): chat_id = request.form.get('chat_id') reason = request.form.get('reason', "No Reason") if not chat_id: return jsonify({"error": "Chat ID is required"}), 400 loop = asyncio.get_event_loop() loop.run_until_complete(db.disable_chat(int(chat_id), reason)) temp.BANNED_CHATS.append(int(chat_id)) return jsonify({"message": "Chat disabled successfully"}) @app.route('/api/enable-chat', methods=['POST']) def enable_chat_api(): chat_id = request.form.get('chat_id') if not chat_id: return jsonify({"error": "Chat ID is required"}), 400 loop = asyncio.get_event_loop() loop.run_until_complete(db.re_enable_chat(int(chat_id))) temp.BANNED_CHATS.remove(int(chat_id)) return jsonify({"message": "Chat enabled successfully"}) @app.route('/api/upload-file', methods=['POST']) def upload_file_api(): if 'fileUpload' not in request.files: return jsonify({"error": "No file part"}), 400 file = request.files['fileUpload'] if file.filename == '': return jsonify({"error": "No selected file"}), 400 if file: file_path = os.path.join("/app/uploads", file.filename) file.save(file_path) loop = asyncio.get_event_loop() file_id, file_ref = loop.run_until_complete(save_file(file_path)) os.remove(file_path) return jsonify({"file_id": file_id, "file_ref": file_ref, "message": "File uploaded successfully"}) return jsonify({"error": "Failed to upload file"}), 500 @app.route('/api/download-file/') def download_file_api(file_id): loop = asyncio.get_event_loop() file_details = loop.run_until_complete(get_file_details(file_id)) if not file_details: return jsonify({"error": "File not found"}), 404 file = file_details[0] return jsonify({ "file_name": file['file_name'], "file_size": file['file_size'], "file_type": file['file_type'], "mime_type": file['mime_type'], "caption": file['caption'] }) @app.route('/api/search-files', methods=['GET']) def search_files_api(): query = request.args.get('query') file_type = request.args.get('file_type') if not query: return jsonify({"error": "Query is required"}), 400 loop = asyncio.get_event_loop() files, next_offset, total = loop.run_until_complete(get_search_results(query, file_type=file_type)) file_list = [] for file in files: file_list.append({ "file_id": file['file_id'], "file_name": file['file_name'], "file_size": file['file_size'], "file_type": file['file_type'], "mime_type": file['mime_type'], "caption": file['caption'] }) return jsonify({"files": file_list, "next_offset": next_offset, "total": total}) @app.route('/api/broadcast', methods=['POST']) def broadcast_api(): message_text = request.form.get('message_text') if not message_text: return jsonify({"error": "Message text is required"}), 400 loop = asyncio.get_event_loop() users = loop.run_until_complete(db.get_all_users()) total_users = loop.run_until_complete(db.total_users_count()) done = 0 blocked = 0 deleted = 0 failed = 0 success = 0 async def handle_user(user): nonlocal success, blocked, deleted, failed, done try: await bot.send_message(user['id'], message_text) success += 1 except UserIsBlocked: blocked += 1 except InputUserDeactivated: deleted += 1 except Exception as e: failed += 1 done += 1 loop.run_until_complete(asyncio.gather(*(handle_user(user) for user in users))) return jsonify({ "total_users": total_users, "completed": done, "success": success, "blocked": blocked, "deleted": deleted, "failed": failed }) @app.route('/api/ban-users') def ban_users_api(): loop = asyncio.get_event_loop() users = loop.run_until_complete(db.get_all_users()) banned_users = [] loop.run_until_complete(asyncio.gather(*(banned_users.append({ "id": user['id'], "name": user['name'], "ban_reason": user['ban_status']['ban_reason'] }) for user in users if user['ban_status']['is_banned']))) return jsonify({"banned_users": banned_users}) @app.route('/api/banned-chats') def banned_chats_api(): loop = asyncio.get_event_loop() chats = loop.run_until_complete(db.get_all_chats()) banned_chats = [] loop.run_until_complete(asyncio.gather(*(banned_chats.append({ "id": chat['id'], "title": chat['title'], "username": chat['username'], "reason": chat['chat_status']['reason'] }) for chat in chats if chat['chat_status']['is_disabled']))) return jsonify({"banned_chats": banned_chats}) @app.route('/api/user-info/') def user_info_api(user_id): try: loop = asyncio.get_event_loop() user = loop.run_until_complete(bot.get_users(int(user_id))) return jsonify({ "first_name": user.first_name, "last_name": user.last_name, "username": user.username, "id": user.id, "dc_id": user.dc_id }) except Exception as e: return jsonify({"error": str(e)}), 500 @app.route('/api/chat-info/') def chat_info_api(chat_id): try: loop = asyncio.get_event_loop() chat = loop.run_until_complete(bot.get_chat(int(chat_id))) members_count = loop.run_until_complete(bot.get_chat_members_count(int(chat_id))) return jsonify({ "title": chat.title, "username": chat.username, "id": chat.id, "members_count": members_count }) except Exception as e: return jsonify({"error": str(e)}), 500 @app.route('/api/restart-bot', methods=['POST']) def restart_bot_api(): admin_id = request.form.get('admin_id') if not admin_id or int(admin_id) not in ADMINS: return jsonify({"error": "Unauthorized access"}), 401 loop = asyncio.get_event_loop() loop.run_until_complete(bot.stop()) loop.run_until_complete(bot.start()) return jsonify({"message": "Bot restarted successfully"}) @app.route('/api/add-connection', methods=['POST']) def add_connection_api(): group_id = request.form.get('group_id') user_id = request.form.get('user_id') if not group_id or not user_id: return jsonify({"error": "Group ID and User ID are required"}), 400 loop = asyncio.get_event_loop() result = loop.run_until_complete(add_connection(group_id, user_id)) if result: return jsonify({"message": "Connection added successfully"}) else: return jsonify({"error": "Connection already exists"}), 400 @app.route('/api/delete-connection', methods=['POST']) def delete_connection_api(): group_id = request.form.get('group_id') user_id = request.form.get('user_id') if not group_id or not user_id: return jsonify({"error": "Group ID and User ID are required"}), 400 loop = asyncio.get_event_loop() result = loop.run_until_complete(delete_connection(user_id, group_id)) if result: return jsonify({"message": "Connection deleted successfully"}) else: return jsonify({"error": "Connection not found"}), 404 @app.route('/api/group-stats') def group_stats_api(): chat_id = request.args.get('chat_id') if not chat_id: return jsonify({"error": "Chat ID is required"}), 400 loop = asyncio.get_event_loop() chat = loop.run_until_complete(db.get_chat(chat_id)) if not chat: return jsonify({"error": "Chat not found"}), 404 return jsonify({ "chat_id": chat['id'], "title": chat['title'], "username": chat['username'], "chat_status": chat['chat_status'] }) @app.route('/api/bot-status') def bot_status(): cpu_usage = psutil.cpu_percent() ram_usage = psutil.virtual_memory().percent total_storage, used_storage, free_storage = shutil.disk_usage("/") return jsonify({ "cpu_usage": cpu_usage, "ram_usage": ram_usage, "total_storage": humanbytes(total_storage), "used_storage": humanbytes(used_storage), "free_storage": humanbytes(free_storage), "uptime": get_time(time.time() - UPTIME) }) @app.route('/api/connections') def connections_api(): user_id = request.args.get('user_id') if not user_id: return jsonify({"error": "User ID is required"}), 400 loop = asyncio.get_event_loop() groupids = loop.run_until_complete(all_connections(str(user_id))) if groupids is None: return jsonify({"connections": []}) connections = [] for groupid in groupids: try: loop = asyncio.get_event_loop() ttl = loop.run_until_complete(bot.get_chat(int(groupid))) title = ttl.title active = loop.run_until_complete(if_active(str(user_id), str(groupid))) connections.append({ "group_id": groupid, "title": title, "active": active }) except Exception as e: print(f"Error fetching chat info: {e}") return jsonify({"connections": connections}) if __name__ == '__main__': bot.run() app.run(host='0.0.0.0', port=7860, debug=False)