| | |
| | 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__) |
| |
|
| | |
| | bot = Client( |
| | name="Professor-Bot", |
| | api_id=API_ID, |
| | api_hash=API_HASH, |
| | bot_token=BOT_TOKEN, |
| | plugins=dict(root="plugins") |
| | ) |
| |
|
| | |
| | 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/<chat_id>') |
| | 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/<file_id>') |
| | 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/<user_id>') |
| | 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/<chat_id>') |
| | 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) |