From 6df4486ca5757f37bad942df9c857a777ca7b31e Mon Sep 17 00:00:00 2001 From: Hafitz Setya <71178188+breakdowns@users.noreply.github.com> Date: Mon, 17 May 2021 15:36:46 +0700 Subject: [PATCH] v4.7.5 (#94) - Added sudo using database NOTE: redeploy recommended to generating database, or you can go to your herokuapp > resources > add-ons > then serach Heroku Postgres > hit Submit Order Form, then copy your database url from DATABASE_URL > Heroku config vars - mirror: Fix for uploading telegram file_name of None type - gdriveTools: Fix infinite loop when hitting rate limits Co-authored-by: Sreeraj V R Co-authored-by: Gautam Kumar Co-authored-by: KenHV --- README.md | 51 ++++++- app.json | 11 +- bot/__init__.py | 47 ++++-- bot/__main__.py | 72 +++++++--- bot/helper/ext_utils/db_handler.py | 78 ++++++++++ .../mirror_utils/upload_utils/gdriveTools.py | 13 +- bot/helper/telegram_helper/bot_commands.py | 4 +- bot/helper/telegram_helper/filters.py | 15 +- bot/modules/authorize.py | 136 ++++++++++++++---- bot/modules/delete.py | 2 +- bot/modules/mirror.py | 4 +- bot/modules/usage.py | 2 +- config_sample.env | 2 +- requirements.txt | 1 + 14 files changed, 359 insertions(+), 79 deletions(-) create mode 100644 bot/helper/ext_utils/db_handler.py diff --git a/README.md b/README.md index 14bc38f..be50bbf 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ This is a Telegram bot writen in Python for mirroring files on the Internet to o ## Additional Features - Mirroring Uptobox.com links to Google Drive (Uptobox account must be premium) -- Sudo support (DWYOR, Sudo User can restart your bot and delete your Drive file) - Get detailed info about replied media - Nyaa.si and Sukebei Torrent search - Speedtest with picture results - Limiting Torrent size support +- Sudo with database support - Check Heroku dynos stats - Custom image support - Racaty.net support @@ -63,11 +63,56 @@ Install Docker by following the [official Docker docs](https://docs.docker.com/e ``` sudo pacman -S docker python ``` - - Install dependencies for running setup scripts: ``` pip3 install -r requirements-cli.txt ``` +## Generate Database +
+ Click here for more details + +**1. The easy way** +- Make new Heroku blank app +- Go to your Heroku blank app +- Go to resources +- In Add-ons search **Heroku Postgres** +- Hit **Submit Order Form** +- Copy your Database URL from Heroku Config Vars > **DATABASE_URL** + +**2. The hard way** +- Install Postgresql: +``` +sudo apt-get update && sudo apt-get install postgresql +``` +- Change to the Postgres user: +``` +sudo su - postgres +``` +- Create a new database user (change YOUR_USER appropriately): +``` +createuser -P -s -e YOUR_USER +``` +This will be followed by you needing to input your password. +- Create a new database table: +``` +createdb -O YOUR_USER YOUR_DB_NAME +``` +Change YOUR_USER and YOUR_DB_NAME appropriately. +- Finally: +``` +psql YOUR_DB_NAME -h YOUR_HOST YOUR_USER +``` +This will allow you to connect to your database via your terminal. By default, YOUR_HOST should be 0.0.0.0:5432. + +You should now be able to build your database URL. This will be: +``` +sqldbtype://username:pw@hostname:port/db_name +``` +Replace sqldbtype with whichever db youre using (eg postgres, mysql, sqllite, etc) repeat for your username, password, hostname (localhost?), port (5432?), and db name. + +**NOTE**: If you deploying on Heroku, no need to generate database manually, because it will automatic generate database + +
## Setting up config file
@@ -86,8 +131,8 @@ Fill up rest of the fields. Meaning of each fields are discussed below: - **DOWNLOAD_DIR**: The path to the local folder where the downloads should be downloaded to - **DOWNLOAD_STATUS_UPDATE_INTERVAL**: A short interval of time in seconds after which the Mirror progress message is updated. (I recommend to keep it `5` seconds at least) - **OWNER_ID**: The Telegram user ID (not username) of the Owner of the bot -- **SUDO_USER**: (Optional field) Multiple Telegram user ID (not username) separate by space. - **AUTHORIZED_CHATS**: Fill user_id and chat_id of you want to authorize. +- **DATABASE_URL**: Your Database URL. See [Generate Database](https://github.com/breakdowns/slam-mirrorbot/tree/master#generate-database) to generate database. (**NOTE**: If you deploying on Heroku, no need to generate database manually, because it will automatic generate database) - **AUTO_DELETE_MESSAGE_DURATION**: Interval of time (in seconds), after which the bot deletes it's message (and command message) which is expected to be viewed instantly. (**Note**: Set to `-1` to never automatically delete messages) - **IS_TEAM_DRIVE**: (Optional field) Set to `True` if `GDRIVE_FOLDER_ID` is from a Team Drive else `False` or Leave it empty. - **USE_SERVICE_ACCOUNTS**: (Optional field) (Leave empty if unsure) Whether to use Service Accounts or not. For this to work see [Using service accounts](https://github.com/breakdowns/slam-mirrorbot#generate-service-accounts-what-is-service-account) section below. diff --git a/app.json b/app.json index 37d07ef..5a1c781 100644 --- a/app.json +++ b/app.json @@ -38,10 +38,6 @@ "description": "The Telegram User ID of the Owner of the Bot. Get it by using /info in @MissRose_bot.", "required": true }, - "SUDO_USER": { - "description": "Multiple Telegram user ID (not username) separate by space.", - "required": false - }, "AUTO_DELETE_MESSAGE_DURATION": { "description": "Interval of time (in seconds), after which the bot deletes it's message (and command message) which is expected to be viewed instantly. Note: Set to -1 to never automatically delete messages.", "required": true @@ -153,5 +149,10 @@ "description": "Fill your URL if you are using extra buttons.", "required": false } - } + }, + "addons": [ + { + "plan": "heroku-postgresql" + } + ] } diff --git a/bot/__init__.py b/bot/__init__.py index 45e6655..8ea0eeb 100644 --- a/bot/__init__.py +++ b/bot/__init__.py @@ -11,6 +11,9 @@ from dotenv import load_dotenv from pyrogram import Client from telegraph import Telegraph +import psycopg2 +from psycopg2 import Error + import socket import faulthandler faulthandler.enable() @@ -26,6 +29,8 @@ logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s handlers=[logging.FileHandler('log.txt'), logging.StreamHandler()], level=logging.INFO) +LOGGER = logging.getLogger(__name__) + load_dotenv('config.env') Interval = [] @@ -34,8 +39,17 @@ Interval = [] def getConfig(name: str): return os.environ[name] - -LOGGER = logging.getLogger(__name__) +def mktable(): + try: + conn = psycopg2.connect(DB_URI) + cur = conn.cursor() + sql = "CREATE TABLE users (uid bigint, sudo boolean DEFAULT FALSE);" + cur.execute(sql) + conn.commit() + LOGGER.info("Table Created!") + except Error as e: + LOGGER.error(e) + exit(1) try: if bool(getConfig('_____REMOVE_THIS_LINE_____')): @@ -65,12 +79,7 @@ status_reply_dict = {} download_dict = {} # Stores list of users and chats the bot is authorized to use in AUTHORIZED_CHATS = set() -if os.path.exists('authorized_chats.txt'): - with open('authorized_chats.txt', 'r+') as f: - lines = f.readlines() - for line in lines: - # LOGGER.info(line.split()) - AUTHORIZED_CHATS.add(int(line.split()[0])) +SUDO_USERS = set() try: achats = getConfig('AUTHORIZED_CHATS') achats = achats.split(" ") @@ -81,13 +90,13 @@ except: try: BOT_TOKEN = getConfig('BOT_TOKEN') + DB_URI = getConfig('DATABASE_URL') parent_id = getConfig('GDRIVE_FOLDER_ID') DOWNLOAD_DIR = getConfig('DOWNLOAD_DIR') if DOWNLOAD_DIR[-1] != '/' or DOWNLOAD_DIR[-1] != '\\': DOWNLOAD_DIR = DOWNLOAD_DIR + '/' DOWNLOAD_STATUS_UPDATE_INTERVAL = int(getConfig('DOWNLOAD_STATUS_UPDATE_INTERVAL')) OWNER_ID = int(getConfig('OWNER_ID')) - SUDO_USER = tuple(filter(lambda x: x, map(int, os.environ.get("SUDO_USER", "").split()))) AUTO_DELETE_MESSAGE_DURATION = int(getConfig('AUTO_DELETE_MESSAGE_DURATION')) TELEGRAM_API = getConfig('TELEGRAM_API') TELEGRAM_HASH = getConfig('TELEGRAM_HASH') @@ -95,6 +104,26 @@ except KeyError as e: LOGGER.error("One or more env variables missing! Exiting now") exit(1) +try: + conn = psycopg2.connect(DB_URI) + cur = conn.cursor() + sql = "SELECT * from users;" + cur.execute(sql) + rows = cur.fetchall() #returns a list ==> (uid, sudo) + for row in rows: + AUTHORIZED_CHATS.add(row[0]) + if row[1]: + SUDO_USERS.add(row[0]) +except Error as e: + if 'relation "users" does not exist' in str(e): + mktable() + else: + LOGGER.error(e) + exit(1) +finally: + cur.close() + conn.close() + LOGGER.info("Generating USER_SESSION_STRING") with Client(':memory:', api_id=int(TELEGRAM_API), api_hash=TELEGRAM_HASH, bot_token=BOT_TOKEN) as app: USER_SESSION_STRING = app.export_session_string() diff --git a/bot/__main__.py b/bot/__main__.py index 793097a..a42c10d 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -10,7 +10,7 @@ import pytz import time from telegram import ParseMode, BotCommand, InlineKeyboardMarkup, InlineKeyboardButton from telegram.ext import CommandHandler, run_async -from bot import dispatcher, updater, botStartTime, AUTHORIZED_CHATS, SUDO_USER, IMAGE_URL +from bot import dispatcher, updater, botStartTime, IMAGE_URL from bot.helper.ext_utils import fs_utils from bot.helper.telegram_helper.bot_commands import BotCommands from bot.helper.telegram_helper.message_utils import * @@ -56,14 +56,6 @@ Type /{BotCommands.HelpCommand} to get a list of available commands update.effective_message.reply_photo(IMAGE_URL, start_string, parse_mode=ParseMode.MARKDOWN) -@run_async -def chat_list(update, context): - chat_list = sudo = '' - chat_list += '\n'.join(str(id) for id in AUTHORIZED_CHATS) - sudo += '\n'.join(str(id) for id in SUDO_USER) - sendMessage(f'Authorized Chats\n{chat_list}\nSudo Users\n{sudo}', context.bot, update) - - @run_async def repo(update, context): button = [ @@ -99,10 +91,10 @@ def log(update, context): @run_async def bot_help(update, context): - help_string = f''' + help_string_adm = f''' /{BotCommands.HelpCommand}: To get this message -/{BotCommands.MirrorCommand} [download_url][magnet_link]: Start mirroring the link to Google Drive +/{BotCommands.MirrorCommand} [download_url][magnet_link]: Start mirroring the link to Google Drive. /{BotCommands.UnzipMirrorCommand} [download_url][magnet_link]: Starts mirroring and if downloaded file is any archive, extracts it to Google Drive @@ -110,6 +102,8 @@ def bot_help(update, context): /{BotCommands.CloneCommand}: Copy file/folder to Google Drive +/{BotCommands.DeleteCommand} [link]: Delete file from Google Drive (Only Owner & Sudo) + /{BotCommands.WatchCommand} [youtube-dl supported link]: Mirror through youtube-dl. Click /{BotCommands.WatchCommand} for more help. /{BotCommands.TarWatchCommand} [youtube-dl supported link]: Mirror through youtube-dl and tar before uploading @@ -124,7 +118,13 @@ def bot_help(update, context): /{BotCommands.AuthorizeCommand}: Authorize a chat or a user to use the bot (Can only be invoked by Owner & Sudo of the bot) -/{BotCommands.AuthListCommand}: See Authorized list & Sudo User (Can only be invoked by Owner & Sudo of the bot) +/{BotCommands.UnAuthorizeCommand}: Unauthorize a chat or a user to use the bot (Can only be invoked by Owner & Sudo of the bot) + +/{BotCommands.AuthorizedUsersCommand}: Show authorized users (Only Owner & Sudo) + +/{BotCommands.AddSudoCommand}: Add sudo user (Only Owner) + +/{BotCommands.RmSudoCommand}: Remove sudo users (Only Owner) /{BotCommands.LogCommand}: Get a log file of the bot. Handy for getting crash reports @@ -144,7 +144,47 @@ def bot_help(update, context): /stickerhelp: Get help for Stickers module. ''' - sendMessage(help_string, context.bot, update) + + help_string = f''' +/{BotCommands.HelpCommand}: To get this message + +/{BotCommands.MirrorCommand} [download_url][magnet_link]: Start mirroring the link to Google Drive. + +/{BotCommands.UnzipMirrorCommand} [download_url][magnet_link]: Starts mirroring and if downloaded file is any archive, extracts it to Google Drive + +/{BotCommands.TarMirrorCommand} [download_url][magnet_link]: Start mirroring and upload the archived (.tar) version of the download + +/{BotCommands.CloneCommand}: Copy file/folder to Google Drive + +/{BotCommands.WatchCommand} [youtube-dl supported link]: Mirror through youtube-dl. Click /{BotCommands.WatchCommand} for more help. + +/{BotCommands.TarWatchCommand} [youtube-dl supported link]: Mirror through youtube-dl and tar before uploading + +/{BotCommands.CancelMirror}: Reply to the message by which the download was initiated and that download will be cancelled + +/{BotCommands.StatusCommand}: Shows a status of all the downloads + +/{BotCommands.ListCommand} [search term]: Searches the search term in the Google Drive, if found replies with the link + +/{BotCommands.StatsCommand}: Show Stats of the machine the bot is hosted on + +/{BotCommands.SpeedCommand}: Check Internet Speed of the Host + +/{BotCommands.RepoCommand}: Get the bot repo. + +/mediainfo: Get detailed info about replied media. + +/tshelp: Get help for Torrent search module. + +/weebhelp: Get help for Anime, Manga, and Character module. + +/stickerhelp: Get help for Stickers module. +''' + + if CustomFilters.sudo_user(update) or CustomFilters.owner_filter(update): + sendMessage(help_string_adm, context.bot, update) + else: + sendMessage(help_string, context.bot, update) botcmds = [ @@ -183,15 +223,14 @@ def main(): ping_handler = CommandHandler(BotCommands.PingCommand, ping, filters=CustomFilters.authorized_chat | CustomFilters.authorized_user) restart_handler = CommandHandler(BotCommands.RestartCommand, restart, - filters=CustomFilters.owner_filter) + filters=CustomFilters.owner_filter | CustomFilters.sudo_user) help_handler = CommandHandler(BotCommands.HelpCommand, bot_help, filters=CustomFilters.authorized_chat | CustomFilters.authorized_user) stats_handler = CommandHandler(BotCommands.StatsCommand, stats, filters=CustomFilters.authorized_chat | CustomFilters.authorized_user) - log_handler = CommandHandler(BotCommands.LogCommand, log, filters=CustomFilters.owner_filter) + log_handler = CommandHandler(BotCommands.LogCommand, log, filters=CustomFilters.owner_filter | CustomFilters.sudo_user) repo_handler = CommandHandler(BotCommands.RepoCommand, repo, filters=CustomFilters.authorized_chat | CustomFilters.authorized_user) - authlist_handler = CommandHandler(BotCommands.AuthListCommand, chat_list, filters=CustomFilters.owner_filter) dispatcher.add_handler(start_handler) dispatcher.add_handler(ping_handler) dispatcher.add_handler(restart_handler) @@ -199,7 +238,6 @@ def main(): dispatcher.add_handler(stats_handler) dispatcher.add_handler(log_handler) dispatcher.add_handler(repo_handler) - dispatcher.add_handler(authlist_handler) updater.start_polling() LOGGER.info("Bot Started!") signal.signal(signal.SIGINT, fs_utils.exit_clean_up) diff --git a/bot/helper/ext_utils/db_handler.py b/bot/helper/ext_utils/db_handler.py new file mode 100644 index 0000000..7e7891f --- /dev/null +++ b/bot/helper/ext_utils/db_handler.py @@ -0,0 +1,78 @@ +import psycopg2 +from psycopg2 import Error +from bot import AUTHORIZED_CHATS, SUDO_USERS, DB_URI, LOGGER + +class DbManger: + def __init__(self): + self.err = False + + def connect(self): + try: + self.conn = psycopg2.connect(DB_URI) + self.cur = self.conn.cursor() + except psycopg2.DatabaseError as error : + LOGGER.error("Error in dbMang : ", error) + self.err = True + + def disconnect(self): + self.cur.close() + self.conn.close() + + def db_auth(self,chat_id: int): + self.connect() + if self.err : + return "There's some error check log for details" + else: + sql = 'INSERT INTO users VALUES ({});'.format(chat_id) + self.cur.execute(sql) + self.conn.commit() + self.disconnect() + AUTHORIZED_CHATS.add(chat_id) + return 'Authorized successfully' + + def db_unauth(self,chat_id: int): + self.connect() + if self.err : + return "There's some error check log for details" + else: + sql = 'DELETE from users where uid = {};'.format(chat_id) + self.cur.execute(sql) + self.conn.commit() + self.disconnect() + AUTHORIZED_CHATS.remove(chat_id) + if chat_id in SUDO_USERS: + SUDO_USERS.remove(chat_id) + return 'Unauthorized successfully' + + def db_addsudo(self,chat_id: int): + self.connect() + if self.err : + return "There's some error check log for details" + else: + if chat_id in AUTHORIZED_CHATS: + sql = 'UPDATE users SET sudo = TRUE where uid = {};'.format(chat_id) + self.cur.execute(sql) + self.conn.commit() + self.disconnect() + SUDO_USERS.add(chat_id) + return 'Successfully promoted as sudo' + else: + sql = 'INSERT INTO users VALUES ({},TRUE);'.format(chat_id) + self.cur.execute(sql) + self.conn.commit() + self.disconnect() + AUTHORIZED_CHATS.add(chat_id) + SUDO_USERS.add(chat_id) + return 'Successfully Authorized and promoted as sudo' + + def db_rmsudo(self,chat_id: int): + self.connect() + if self.err : + return "There's some error check log for details" + else: + sql = 'UPDATE users SET sudo = FALSE where uid = {};'.format(chat_id) + self.cur.execute(sql) + self.conn.commit() + self.disconnect() + SUDO_USERS.remove(chat_id) + return 'Successfully removed from Sudo' diff --git a/bot/helper/mirror_utils/upload_utils/gdriveTools.py b/bot/helper/mirror_utils/upload_utils/gdriveTools.py index 879f4bc..db67646 100644 --- a/bot/helper/mirror_utils/upload_utils/gdriveTools.py +++ b/bot/helper/mirror_utils/upload_utils/gdriveTools.py @@ -128,11 +128,12 @@ class GoogleDriveHelper: global SERVICE_ACCOUNT_INDEX service_account_count = len(os.listdir("accounts")) if SERVICE_ACCOUNT_INDEX == service_account_count - 1: - SERVICE_ACCOUNT_INDEX = 0 + return False SERVICE_ACCOUNT_INDEX += 1 LOGGER.info(f"Switching to {SERVICE_ACCOUNT_INDEX}.json service account") self.__service = self.authorize() - + return True + @retry(wait=wait_exponential(multiplier=2, min=3, max=6), stop=stop_after_attempt(5), retry=retry_if_exception_type(HttpError), before=before_log(LOGGER, logging.DEBUG)) def __set_permission(self, drive_id): @@ -189,7 +190,8 @@ class GoogleDriveHelper: reason = json.loads(err.content).get('error').get('errors')[0].get('reason') if reason == 'userRateLimitExceeded' or reason == 'dailyLimitExceeded': if USE_SERVICE_ACCOUNTS: - self.switchServiceAccount() + if not self.switchServiceAccount(): + return None LOGGER.info(f"Got: {reason}, Trying Again.") return self.upload_file(file_path, file_name, mime_type, parent_id) else: @@ -270,7 +272,8 @@ class GoogleDriveHelper: reason = json.loads(err.content).get('error').get('errors')[0].get('reason') if reason == 'userRateLimitExceeded' or reason == 'dailyLimitExceeded': if USE_SERVICE_ACCOUNTS: - self.switchServiceAccount() + if not self.switchServiceAccount(): + raise err LOGGER.info(f"Got: {reason}, Trying Again.") return self.copyFile(file_id,dest_id) else: @@ -569,7 +572,7 @@ class GoogleDriveHelper: if self.num_of_path > 1: self.edit_telegraph() - msg = f"🔎 Search Results For {fileName} \n📚 Found {len(response['files'])} results" + msg = f"🔎 Found {len(response['files'])} results for {fileName}" buttons = button_build.ButtonMaker() buttons.buildbutton("HERE", f"https://telegra.ph/{self.path[0]}") diff --git a/bot/helper/telegram_helper/bot_commands.py b/bot/helper/telegram_helper/bot_commands.py index c22abad..8ea396a 100644 --- a/bot/helper/telegram_helper/bot_commands.py +++ b/bot/helper/telegram_helper/bot_commands.py @@ -8,9 +8,11 @@ class _BotCommands: self.CancelAllCommand = 'cancelall' self.ListCommand = 'list' self.StatusCommand = 'status' + self.AuthorizedUsersCommand = 'users' self.AuthorizeCommand = 'authorize' self.UnAuthorizeCommand = 'unauthorize' - self.AuthListCommand = 'authlist' + self.AddSudoCommand = 'addsudo' + self.RmSudoCommand = 'rmsudo' self.PingCommand = 'ping' self.RestartCommand = 'restart' self.StatsCommand = 'stats' diff --git a/bot/helper/telegram_helper/filters.py b/bot/helper/telegram_helper/filters.py index 28225ab..792e841 100644 --- a/bot/helper/telegram_helper/filters.py +++ b/bot/helper/telegram_helper/filters.py @@ -1,20 +1,19 @@ from telegram.ext import BaseFilter from telegram import Message -from bot import AUTHORIZED_CHATS, OWNER_ID, SUDO_USER, download_dict, download_dict_lock +from bot import AUTHORIZED_CHATS, SUDO_USERS, OWNER_ID, download_dict, download_dict_lock class CustomFilters: class _OwnerFilter(BaseFilter): def filter(self, message): - id = message.from_user.id - return bool(message.from_user.id == OWNER_ID or id in SUDO_USER) + return bool(message.from_user.id == OWNER_ID) owner_filter = _OwnerFilter() class _AuthorizedUserFilter(BaseFilter): def filter(self, message): id = message.from_user.id - return bool(id in AUTHORIZED_CHATS or id == OWNER_ID or id in SUDO_USER) + return bool(id in AUTHORIZED_CHATS or id == OWNER_ID) authorized_user = _AuthorizedUserFilter() @@ -24,10 +23,16 @@ class CustomFilters: authorized_chat = _AuthorizedChat() + class _SudoUser(BaseFilter): + def filter(self,message): + return bool(message.from_user.id in SUDO_USERS) + + sudo_user = _SudoUser() + class _MirrorOwner(BaseFilter): def filter(self, message: Message): user_id = message.from_user.id - if user_id in SUDO_USER: + if user_id == OWNER_ID: return True args = str(message.text).split(' ') if len(args) > 1: diff --git a/bot/modules/authorize.py b/bot/modules/authorize.py index fedb4d1..d061355 100644 --- a/bot/modules/authorize.py +++ b/bot/modules/authorize.py @@ -1,69 +1,145 @@ from bot.helper.telegram_helper.message_utils import sendMessage from telegram.ext import run_async -from bot import AUTHORIZED_CHATS, dispatcher +from bot import AUTHORIZED_CHATS, SUDO_USERS, dispatcher from telegram.ext import CommandHandler from bot.helper.telegram_helper.filters import CustomFilters from telegram.ext import Filters from telegram import Update from bot.helper.telegram_helper.bot_commands import BotCommands +from bot.helper.ext_utils.db_handler import DbManger @run_async def authorize(update,context): + reply_message = None + message_ = None reply_message = update.message.reply_to_message - msg = '' - with open('authorized_chats.txt', 'a') as file: + message_ = update.message.text.split(' ') + if len(message_) == 2: + chat_id = int(message_[1]) + if chat_id not in AUTHORIZED_CHATS: + msg = DbManger().db_auth(chat_id) + else: + msg = 'User already authorized' + else: if reply_message is None: # Trying to authorize a chat chat_id = update.effective_chat.id if chat_id not in AUTHORIZED_CHATS: - file.write(f'{chat_id}\n') - AUTHORIZED_CHATS.add(chat_id) - msg = 'Chat authorized' + msg = DbManger().db_auth(chat_id) else: msg = 'Already authorized chat' + else: # Trying to authorize someone in specific user_id = reply_message.from_user.id if user_id not in AUTHORIZED_CHATS: - file.write(f'{user_id}\n') - AUTHORIZED_CHATS.add(user_id) - msg = 'Person Authorized to use the bot!' + msg = DbManger().db_auth(user_id) else: - msg = 'Person already authorized' - sendMessage(msg, context.bot, update) + msg = 'User already authorized' + sendMessage(msg, context.bot, update) @run_async def unauthorize(update,context): + reply_message = None + message_ = None reply_message = update.message.reply_to_message - if reply_message is None: - # Trying to unauthorize a chat - chat_id = update.effective_chat.id + message_ = update.message.text.split(' ') + if len(message_) == 2: + chat_id = int(message_[1]) if chat_id in AUTHORIZED_CHATS: - AUTHORIZED_CHATS.remove(chat_id) - msg = 'Chat unauthorized' + msg = DbManger().db_unauth(chat_id) else: - msg = 'Already unauthorized chat' + msg = 'User already unauthorized' else: - # Trying to authorize someone in specific - user_id = reply_message.from_user.id - if user_id in AUTHORIZED_CHATS: - AUTHORIZED_CHATS.remove(user_id) - msg = 'Person unauthorized to use the bot!' + if reply_message is None: + # Trying to unauthorize a chat + chat_id = update.effective_chat.id + if chat_id in AUTHORIZED_CHATS: + msg = DbManger().db_unauth(chat_id) + else: + msg = 'Already unauthorized chat' else: - msg = 'Person already unauthorized!' - with open('authorized_chats.txt', 'a') as file: - file.truncate(0) - for i in AUTHORIZED_CHATS: - file.write(f'{i}\n') + # Trying to authorize someone in specific + user_id = reply_message.from_user.id + if user_id in AUTHORIZED_CHATS: + msg = DbManger().db_unauth(user_id) + else: + msg = 'User already unauthorized' sendMessage(msg, context.bot, update) +@run_async +def addSudo(update,context): + reply_message = None + message_ = None + reply_message = update.message.reply_to_message + message_ = update.message.text.split(' ') + if len(message_) == 2: + chat_id = int(message_[1]) + if chat_id not in SUDO_USERS: + msg = DbManger().db_addsudo(chat_id) + else: + msg = 'Already Sudo' + else: + if reply_message is None: + msg = "Give ID or Reply To message of whom you want to Promote" + else: + # Trying to authorize someone in specific + user_id = reply_message.from_user.id + if user_id not in SUDO_USERS: + msg = DbManger().db_addsudo(user_id) + else: + msg = 'Already Sudo' + sendMessage(msg, context.bot, update) + + +@run_async +def removeSudo(update,context): + reply_message = None + message_ = None + reply_message = update.message.reply_to_message + message_ = update.message.text.split(' ') + if len(message_) == 2: + chat_id = int(message_[1]) + if chat_id in SUDO_USERS: + msg = DbManger().db_rmsudo(chat_id) + else: + msg = 'Not a Sudo' + else: + if reply_message is None: + msg = "Give ID or Reply To message of whom you want to remove from Sudo" + else: + user_id = reply_message.from_user.id + if user_id in SUDO_USERS: + msg = DbManger().db_rmsudo(user_id) + else: + msg = 'Not a Sudo' + sendMessage(msg, context.bot, update) + + +@run_async +def sendAuthChats(update,context): + user = sudo = '' + user += '\n'.join(str(id) for id in AUTHORIZED_CHATS) + sudo += '\n'.join(str(id) for id in SUDO_USERS) + sendMessage(f'Authorized Chats\n{user}\nSudo Users\n{sudo}', context.bot, update) + + +send_auth_handler = CommandHandler(command=BotCommands.AuthorizedUsersCommand, callback=sendAuthChats, + filters=CustomFilters.owner_filter | CustomFilters.sudo_user) authorize_handler = CommandHandler(command=BotCommands.AuthorizeCommand, callback=authorize, - filters=CustomFilters.owner_filter & Filters.group) + filters=CustomFilters.owner_filter | CustomFilters.sudo_user) unauthorize_handler = CommandHandler(command=BotCommands.UnAuthorizeCommand, callback=unauthorize, - filters=CustomFilters.owner_filter & Filters.group) + filters=CustomFilters.owner_filter | CustomFilters.sudo_user) +addsudo_handler = CommandHandler(command=BotCommands.AddSudoCommand, callback=addSudo, + filters=CustomFilters.owner_filter) +removesudo_handler = CommandHandler(command=BotCommands.RmSudoCommand, callback=removeSudo, + filters=CustomFilters.owner_filter) + +dispatcher.add_handler(send_auth_handler) dispatcher.add_handler(authorize_handler) dispatcher.add_handler(unauthorize_handler) - +dispatcher.add_handler(addsudo_handler) +dispatcher.add_handler(removesudo_handler) diff --git a/bot/modules/delete.py b/bot/modules/delete.py index 7eabf7d..8455200 100644 --- a/bot/modules/delete.py +++ b/bot/modules/delete.py @@ -25,5 +25,5 @@ def deletefile(update, context): threading.Thread(target=auto_delete_message, args=(context.bot, update.message, reply_message)).start() -delete_handler = CommandHandler(command=BotCommands.DeleteCommand, callback=deletefile, filters=CustomFilters.owner_filter) +delete_handler = CommandHandler(command=BotCommands.DeleteCommand, callback=deletefile, filters=CustomFilters.owner_filter | CustomFilters.sudo_user) dispatcher.add_handler(delete_handler) diff --git a/bot/modules/mirror.py b/bot/modules/mirror.py index 4df9cb6..730234c 100644 --- a/bot/modules/mirror.py +++ b/bot/modules/mirror.py @@ -59,7 +59,9 @@ class MirrorListener(listeners.MirrorListeners): download = download_dict[self.uid] name = download.name() size = download.size_raw() - m_path = f'{DOWNLOAD_DIR}{self.uid}/{download.name()}' + if name is None: # when pyrogram's media.file_name is of NoneType + name = os.listdir(f'{DOWNLOAD_DIR}{self.uid}')[0] + m_path = f'{DOWNLOAD_DIR}{self.uid}/{name}' if self.isTar: download.is_archiving = True try: diff --git a/bot/modules/usage.py b/bot/modules/usage.py index 50b9eef..cc7247d 100644 --- a/bot/modules/usage.py +++ b/bot/modules/usage.py @@ -77,6 +77,6 @@ def dyno_usage(update, context): dyno_usage_handler = CommandHandler(command=BotCommands.UsageCommand, callback=dyno_usage, - filters=CustomFilters.owner_filter) + filters=CustomFilters.owner_filter | CustomFilters.sudo_user) dispatcher.add_handler(dyno_usage_handler) diff --git a/config_sample.env b/config_sample.env index be90ef4..ca98172 100644 --- a/config_sample.env +++ b/config_sample.env @@ -11,9 +11,9 @@ AUTO_DELETE_MESSAGE_DURATION = 20 IS_TEAM_DRIVE = "" TELEGRAM_API = TELEGRAM_HASH = "" +DATABASE_URL = # Optional config AUTHORIZED_CHATS = "" -SUDO_USER = USE_SERVICE_ACCOUNTS = "" INDEX_URL = "" UPTOBOX_TOKEN = "" diff --git a/requirements.txt b/requirements.txt index 149f542..a0f37ab 100644 --- a/requirements.txt +++ b/requirements.txt @@ -25,3 +25,4 @@ lxml telegraph pytz html-telegraph-poster>=0.2.31 +psycopg2-binary