diff --git a/README.md b/README.md index 76aab2ca683..0a1b5c90332 100644 --- a/README.md +++ b/README.md @@ -18,18 +18,25 @@ # Features supported: ## Additional Features - Get detailed info about replied media (Only for Telegram file) -- Nyaa.si and Sukebei Torrent search - Speedtest with picture results - Stop duplicate cloning Google Drive & mirroring Mega support - Limiting size Torrent/Direct, Mega, cloning Google Drive support - Sudo with Database support - Multiple Trackers support - Check Heroku dynos stats +- Heroku config support +- Updater (Only for Heroku) - Extracting **tar.xz** support +- Create Tar Google Drive folder - Custom image support - Counting file/folder - Shell and Executor - View Link button +- Torrent search supported: +``` +nyaa, sukebei, 1337x, piratebay, tgx, +yts, eztv, torlock, rarbg +``` - Direct links supported: ``` letsupload.io, hxfile.co, anonfiles.com, fembed.com, femax20.com, layarkacaxxi.icu, @@ -129,6 +136,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) - **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) +- **UPSTREAM_REPO**: Link for Bot Upstream Repo, if you want default update, fill ```https://github.com/breakdowns/slam-mirrorbot```. +- **UPSTREAM_BRANCH**: Link for Bot Upstream Repo (Recommended using master branch) ### Optional Field - **AUTHORIZED_CHATS**: Fill user_id and chat_id of you want to authorize. - **IS_TEAM_DRIVE**: Set to `True` if `GDRIVE_FOLDER_ID` is from a Team Drive else `False` or Leave it empty. diff --git a/app.json b/app.json index 0a8452ed729..2dc55fc68d8 100644 --- a/app.json +++ b/app.json @@ -74,6 +74,16 @@ "description": "Add the Heroku app name here.", "required": true }, + "UPSTREAM_REPO": { + "description": "Link for Bot Upstream Repo, If you want default update, Fill https://github.com/breakdowns/slam-mirrorbot.", + "value": "https://github.com/breakdowns/slam-mirrorbot", + "required": true + }, + "UPSTREAM_BRANCH": { + "description": "Branch name for Upstream Repo (Recommended using master branch).", + "value": "master", + "required": true + }, "UPTOBOX_TOKEN": { "description": "Uptobox premium token to mirror uptobox links. Get it from https://uptobox.com/my_account.", "required": false diff --git a/bot/__init__.py b/bot/__init__.py index c0650155df9..74220aa3465 100644 --- a/bot/__init__.py +++ b/bot/__init__.py @@ -100,6 +100,8 @@ def mktable(): AUTO_DELETE_MESSAGE_DURATION = int(getConfig('AUTO_DELETE_MESSAGE_DURATION')) TELEGRAM_API = getConfig('TELEGRAM_API') TELEGRAM_HASH = getConfig('TELEGRAM_HASH') + UPSTREAM_REPO = getConfig('UPSTREAM_REPO') + UPSTREAM_BRANCH = getConfig('UPSTREAM_BRANCH') except KeyError as e: LOGGER.error("One or more env variables missing! Exiting now") exit(1) diff --git a/bot/__main__.py b/bot/__main__.py index 4e118ede68f..08287e39fcd 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -1,6 +1,7 @@ import shutil, psutil import signal import os +import importlib from pyrogram import idle from bot import app @@ -18,7 +19,11 @@ from .helper.ext_utils.bot_utils import get_readable_file_size, get_readable_time from .helper.telegram_helper.filters import CustomFilters from bot.helper.telegram_helper import button_build -from .modules import authorize, list, cancel_mirror, mirror_status, mirror, clone, watch, shell, eval, search, delete, speedtest, usage, mediainfo, count +from bot.modules import ALL_MODULES # Auto Load all modules without name problems + +for module in ALL_MODULES: + imported_module = importlib.import_module("bot.modules." + module) + importlib.reload(imported_module) now=datetime.now(pytz.timezone('Asia/Jakarta')) @@ -129,13 +134,17 @@ def bot_help(update, context): /{BotCommands.LogCommand}: Get a log file of the bot. Handy for getting crash reports +/{BotCommands.ConfigMenuCommand}: Get Info Menu about bot config (Owner Only). + +/{BotCommands.UpdateCommand}: Update Bot from Upstream Repo. (Owner Only). + /{BotCommands.UsageCommand}: To see Heroku Dyno Stats (Owner & Sudo only). /{BotCommands.SpeedCommand}: Check Internet Speed of the Host -/shell: Run commands in Shell (Terminal). +/{BotCommands.MediaInfoCommand}: Get detailed info about replied media (Only for Telegram file). -/mediainfo: Get detailed info about replied media (Only for Telegram file). +/{BotCommands.ShellCommand}: Run commands in Shell (Terminal). /tshelp: Get help for Torrent search module. ''' @@ -167,7 +176,7 @@ def bot_help(update, context): /{BotCommands.SpeedCommand}: Check Internet Speed of the Host -/mediainfo: Get detailed info about replied media (Only for Telegram file). +/{BotCommands.MediaInfoCommand}: Get detailed info about replied media (Only for Telegram file). /tshelp: Get help for Torrent search module. ''' @@ -193,6 +202,7 @@ def bot_help(update, context): BotCommand(f'{BotCommands.StatusCommand}','Get Mirror Status message'), BotCommand(f'{BotCommands.StatsCommand}','Bot Usage Stats'), BotCommand(f'{BotCommands.HelpCommand}','Get Detailed Help'), +BotCommand(f'{BotCommands.MediaInfoCommand}','Get detailed info about replied media'), BotCommand(f'{BotCommands.SpeedCommand}','Check Speed of the host'), BotCommand(f'{BotCommands.LogCommand}','Bot Log [owner/sudo only]'), BotCommand(f'{BotCommands.RestartCommand}','Restart bot [owner/sudo only]')] diff --git a/bot/helper/__init__.py b/bot/helper/__init__.py index ceafed0e638..66f1f237746 100644 --- a/bot/helper/__init__.py +++ b/bot/helper/__init__.py @@ -1,8 +1,78 @@ import asyncio import os import shlex +import heroku3 + +from functools import wraps +from pyrogram.types import Message from typing import Tuple from html_telegraph_poster import TelegraphPoster +from bot import HEROKU_API_KEY, HEROKU_APP_NAME + +# Implement by https://github.com/jusidama18 +# Setting Message + +def get_text(message: Message) -> [None, str]: + """Extract Text From Commands""" + text_to_return = message.text + if message.text is None: + return None + if " " in text_to_return: + try: + return message.text.split(None, 1)[1] + except IndexError: + return None + else: + return None + +# Preparing For Setting Config +# Implement by https://github.com/jusidama18 and Based on this https://github.com/DevsExpo/FridayUserbot/blob/master/plugins/heroku_helpers.py + +heroku_client = None +if HEROKU_API_KEY: + heroku_client = heroku3.from_key(HEROKU_API_KEY) + +def check_heroku(func): + @wraps(func) + async def heroku_cli(client, message): + heroku_app = None + if not heroku_client: + await message.reply_text("`Please Add HEROKU_API_KEY Key For This To Function To Work!`", parse_mode="markdown") + elif not HEROKU_APP_NAME: + await message.reply_text("`Please Add HEROKU_APP_NAME For This To Function To Work!`", parse_mode="markdown") + if HEROKU_APP_NAME and heroku_client: + try: + heroku_app = heroku_client.app(HEROKU_APP_NAME) + except: + await message.reply_text(message, "`Heroku Api Key And App Name Doesn't Match!`", parse_mode="markdown") + if heroku_app: + await func(client, message, heroku_app) + + return heroku_cli + +# Preparing For Update Bot +# Implement by https://github.com/jusidama18 and Based on this https://github.com/DevsExpo/FridayUserbot/blob/master/plugins/updater.py + +def fetch_heroku_git_url(api_key, app_name): + if not api_key: + return None + if not app_name: + return None + heroku = heroku3.from_key(api_key) + try: + heroku_applications = heroku.apps() + except: + return None + heroku_app = None + for app in heroku_applications: + if app.name == app_name: + heroku_app = app + break + if not heroku_app: + return None + return heroku_app.git_url.replace("https://", "https://api:" + api_key + "@") + +HEROKU_URL = fetch_heroku_git_url(HEROKU_API_KEY, HEROKU_APP_NAME) def post_to_telegraph(a_title: str, content: str) -> str: """ Create a Telegram Post using HTML Content """ diff --git a/bot/helper/telegram_helper/bot_commands.py b/bot/helper/telegram_helper/bot_commands.py index ed7c575e53a..1dc82aa9ee4 100644 --- a/bot/helper/telegram_helper/bot_commands.py +++ b/bot/helper/telegram_helper/bot_commands.py @@ -25,5 +25,9 @@ def __init__(self): self.TarWatchCommand = 'tarwatch' self.DeleteCommand = 'del' self.UsageCommand = 'usage' + self.MediaInfoCommand = 'mediainfo' + self.ConfigMenuCommand = 'config' + self.ShellCommand = 'shell' + self.UpdateCommand = 'update' BotCommands = _BotCommands() diff --git a/bot/modules/__init__.py b/bot/modules/__init__.py index e69de29bb2d..05a98be7b84 100644 --- a/bot/modules/__init__.py +++ b/bot/modules/__init__.py @@ -0,0 +1,18 @@ +'''Methods Directory.''' +# Module folder for modules using Telegram. +# For easier development. + +def __list_all_modules(): + from os.path import dirname, basename, isfile + import glob + # This generates a list of modules in this folder for the * in __main__ to work. + mod_paths = glob.glob(dirname(__file__) + "/*.py") + return [ + basename(f)[:-3] for f in mod_paths if isfile(f) + and f.endswith(".py") + and not f.endswith('__init__.py') + ] + + +ALL_MODULES = sorted(__list_all_modules()) +__all__ = ALL_MODULES + ["ALL_MODULES"] diff --git a/bot/modules/config.py b/bot/modules/config.py new file mode 100644 index 00000000000..e99df04436e --- /dev/null +++ b/bot/modules/config.py @@ -0,0 +1,210 @@ +# Implement by https://github.com/jusidama18 +# Based on this https://github.com/DevsExpo/FridayUserbot/blob/master/plugins/heroku_helpers.py + +from pyrogram import filters, types, emoji +from bot.helper.telegram_helper.bot_commands import BotCommands +from bot import app, OWNER_ID +from bot.helper import get_text, check_heroku +from bot.modules import ALL_MODULES +from bot import * + +# Add Variable + +@app.on_message(filters.command('setvar') & filters.user(OWNER_ID)) +@check_heroku +async def set_varr(client, message, app_): + msg_ = await message.reply_text("`Please Wait!`") + heroku_var = app_.config() + _var = get_text(message) + if not _var: + await msg_.edit("`Here is Usage Syntax: /setvar KEY VALUE`", parse_mode="markdown") + return + if not " " in _var: + await msg_.edit("`Variable VALUE needed !`", parse_mode="markdown") + return + var_ = _var.split(" ", 1) + if len(var_) > 2: + await msg_.edit("`Here is Usage Syntax: /setvar KEY VALUE`", parse_mode="markdown") + return + _varname, _varvalue = var_ + await msg_.edit(f"`Variable {_varname} Added With Value {_varvalue}!`") + heroku_var[_varname] = _varvalue + +# Delete Variable + +@app.on_message(filters.command('delvar') & filters.user(OWNER_ID)) +@check_heroku +async def del_varr(client, message, app_): + msg_ = await message.reply_text("`Please Wait!`", parse_mode="markdown") + heroku_var = app_.config() + _var = get_text(message) + if not _var: + await msg_.edit("`Give Var Name As Input!`", parse_mode="markdown") + return + if not _var in heroku_var: + await msg_.edit("`This Var Doesn't Exists!`", parse_mode="markdown") + return + await msg_.edit(f"`Sucessfully Deleted {_var} Var!`", parse_mode="markdown") + del heroku_var[_var] + +# CONFIG LIST # + +__header__='📕 **Page** **{}**\n\n' + +@app.on_message(filters.command(BotCommands.ConfigMenuCommand) & filters.user(OWNER_ID)) +async def config_menu(_, message): + await message.reply( + f"**Hello {message.from_user.mention}**,\n\n**If you want to add or set Variable in Heroku use** `/setvar`\n\n**If you want to delete Variable in Heroku use `/delvar`**\n\n**WARNING! Very Recommended to do this command in private since it's contain bot info.**\n\n**Here's This is Slam-MirrorBot Current Configs**\n\n\n", + reply_markup=types.InlineKeyboardMarkup( + [[types.InlineKeyboardButton(f"{emoji.CROSS_MARK}", callback_data='docs_end'), types.InlineKeyboardButton(f"BOT CONFIG", callback_data='docs_1')]] + ) + ) + +@app.on_callback_query(filters.regex('^docs_') & filters.user(OWNER_ID)) +async def config_button(_, query): + data = query.data.split('_')[1] + if data == '1': + return await query.message.edit( + __header__.format(data) + + f"**[ Telegram Config ]**\n\n**Bot Token:** `{BOT_TOKEN}`\n\n**Telegram API:** `{TELEGRAM_API}`\n\n**Telegram HASH:** `{TELEGRAM_HASH}`\n\n**Telegraph Token:** `{telegraph_token}`\n\n\n", + reply_markup=types.InlineKeyboardMarkup( + [ + [ + types.InlineKeyboardButton(f"{emoji.LEFT_ARROW}", callback_data='docs_10'), + types.InlineKeyboardButton(f"{emoji.CROSS_MARK}", callback_data='docs_end'), + types.InlineKeyboardButton(f"{emoji.RIGHT_ARROW}", callback_data='docs_2') + ] + ] + ) + ) + elif data == '2': + return await query.message.edit( + __header__.format(data) + + f"**[ Drive and Index Config ]**\n**Drive Folder:** `{parent_id}`\n\n**Using Team Drive:** `{IS_TEAM_DRIVE}`\n\n**Using Service Account:** `{USE_SERVICE_ACCOUNTS}`\n\n**Index Url:** `{INDEX_URL}`\n\n\n", + reply_markup=types.InlineKeyboardMarkup( + [ + [ + types.InlineKeyboardButton(f"{emoji.LEFT_ARROW}", callback_data='docs_1'), + types.InlineKeyboardButton(f"{emoji.CROSS_MARK}", callback_data='docs_end'), + types.InlineKeyboardButton(f"{emoji.RIGHT_ARROW}", callback_data='docs_3') + ] + ] + ) + ) + elif data == '3': + return await query.message.edit( + __header__.format(data) + + f"**[ Mega and Uptobox Config ]**\n\n**Mega API:** `{MEGA_API_KEY}`\n\n**Mega Email:** `{MEGA_EMAIL_ID}`\n\n**Mega Password:** `{MEGA_PASSWORD}`\n\n**Uptobox Token:** `{UPTOBOX_TOKEN}`\n\n\n", + reply_markup=types.InlineKeyboardMarkup( + [ + [ + types.InlineKeyboardButton(f"{emoji.LEFT_ARROW}", callback_data='docs_2'), + types.InlineKeyboardButton(f"{emoji.CROSS_MARK}", callback_data='docs_end'), + types.InlineKeyboardButton(f"{emoji.RIGHT_ARROW}", callback_data='docs_4') + ] + ] + ) + ) + elif data == '4': + return await query.message.edit( + __header__.format(data) + + f"**[ Stop Duplicate Config ]**\n\n**Mirror:** `{STOP_DUPLICATE_MIRROR}`\n\n**Clone:** `{STOP_DUPLICATE_CLONE}`\n\n**Mega:** `{STOP_DUPLICATE_MEGA}`\n\n**[ Block Mega Config ]**\n\n**Folder:** `{BLOCK_MEGA_FOLDER}`\n\n**Link:** `{BLOCK_MEGA_LINKS}`\n\n\n", + reply_markup=types.InlineKeyboardMarkup( + [ + [ + types.InlineKeyboardButton(f"{emoji.LEFT_ARROW}", callback_data='docs_3'), + types.InlineKeyboardButton(f"{emoji.CROSS_MARK}", callback_data='docs_end'), + types.InlineKeyboardButton(f"{emoji.RIGHT_ARROW}", callback_data='docs_5') + ] + ] + ) + ) + elif data == '5': + return await query.message.edit( + __header__.format(data) + + f"**[ Limit Size Config ]**\n\n**Torrent and Direct:** `{TORRENT_DIRECT_LIMIT}`\n\n**Clone:** `{CLONE_LIMIT}`\n\n**Mega:** `{MEGA_LIMIT}`\n\n\n", + reply_markup=types.InlineKeyboardMarkup( + [ + [ + types.InlineKeyboardButton(f"{emoji.LEFT_ARROW}", callback_data='docs_4'), + types.InlineKeyboardButton(f"{emoji.CROSS_MARK}", callback_data='docs_end'), + types.InlineKeyboardButton(f"{emoji.RIGHT_ARROW}", callback_data='docs_6') + ] + ] + ) + ) + elif data == '6': + user = sudo = '' + user += '\n'.join(str(id) for id in AUTHORIZED_CHATS) + sudo += '\n'.join(str(id) for id in SUDO_USERS) + return await query.message.edit( + __header__.format(data) + + f"**[ User ID Config ]**\n\n**Owner ID:** `{OWNER_ID}`\n\n**Authorized Chat:**\n`{user}`\n\n**Sudo Users:**\n`{sudo}`\n\n\n", + reply_markup=types.InlineKeyboardMarkup( + [ + [ + types.InlineKeyboardButton(f"{emoji.LEFT_ARROW}", callback_data='docs_5'), + types.InlineKeyboardButton(f"{emoji.CROSS_MARK}", callback_data='docs_end'), + types.InlineKeyboardButton(f"{emoji.RIGHT_ARROW}", callback_data='docs_7') + ] + ] + ) + ) + elif data == '7': + return await query.message.edit( + __header__.format(data) + + f"**[ Button Config ]**\n\n**Button Four Name:** `{BUTTON_FOUR_NAME}`\n\n**Button Four Url:** `{BUTTON_FOUR_URL}`\n\n**Button Five Name:** `{BUTTON_FIVE_NAME}`\n\n**Button Five Url:** `{BUTTON_FIVE_URL}`\n\n**Button Six Name:** `{BUTTON_SIX_NAME}`\n\n**Button Six Url:** `{BUTTON_SIX_URL}`\n\n\n", + reply_markup=types.InlineKeyboardMarkup( + [ + [ + types.InlineKeyboardButton(f"{emoji.LEFT_ARROW}", callback_data='docs_6'), + types.InlineKeyboardButton(f"{emoji.CROSS_MARK}", callback_data='docs_end'), + types.InlineKeyboardButton(f"{emoji.RIGHT_ARROW}", callback_data='docs_8') + ] + ] + ) + ) + elif data == '8': + return await query.message.edit( + __header__.format(data) + + f"**[ Heroku Config ]**\n\n**Heroku Name:** `{HEROKU_APP_NAME}`\n\n**Heroku API:** `{HEROKU_API_KEY}`\n\n**[ Upstream Config ]**\n\n**Upstream Repo :** `{UPSTREAM_REPO}`\n\n**Upstream Branch :** `{UPSTREAM_BRANCH}`\n\n**[ Shortener Config ]**\n\n**Shortener Name:** `{SHORTENER}`\n\n**Shortener API:** `{SHORTENER_API}`\n\n\n", + reply_markup=types.InlineKeyboardMarkup( + [ + [ + types.InlineKeyboardButton(f"{emoji.LEFT_ARROW}", callback_data='docs_7'), + types.InlineKeyboardButton(f"{emoji.CROSS_MARK}", callback_data='docs_end'), + types.InlineKeyboardButton(f"{emoji.RIGHT_ARROW}", callback_data='docs_9') + ] + ] + ) + ) + elif data == '9': + return await query.message.edit( + __header__.format(data) + + f" **[ Others Config ]**\n\n**Ignore Pending Request:** `{IGNORE_PENDING_REQUESTS}`\n\n**Image Url:** `{IMAGE_URL}`\n\n**Directory:** `{DOWNLOAD_DIR}`\n\n**Status Interval:** `{DOWNLOAD_STATUS_UPDATE_INTERVAL}`\n\n**View Link:** `{VIEW_LINK}`\n\n**Database Url:** `{DB_URI}`\n\n**Delete Message Duration:** `{AUTO_DELETE_MESSAGE_DURATION}`\n\n\n", + reply_markup=types.InlineKeyboardMarkup( + [ + [ + types.InlineKeyboardButton(f"{emoji.LEFT_ARROW}", callback_data='docs_8'), + types.InlineKeyboardButton(f"{emoji.CROSS_MARK}", callback_data='docs_end'), + types.InlineKeyboardButton(f"{emoji.RIGHT_ARROW}", callback_data='docs_10') + ] + ] + ) + ) + elif data == '10': + return await query.message.edit( + __header__.format(data) + + f" **[ Module Config ]**\n\n**All Module:** \n`{ALL_MODULES}`\n\n\n", + reply_markup=types.InlineKeyboardMarkup( + [ + [ + types.InlineKeyboardButton(f"{emoji.LEFT_ARROW}", callback_data='docs_9'), + types.InlineKeyboardButton(f"{emoji.CROSS_MARK}", callback_data='docs_end'), + types.InlineKeyboardButton(f"{emoji.RIGHT_ARROW}", callback_data='docs_1') + ] + ] + ) + ) + elif data == 'end': + return await query.message.delete() diff --git a/bot/modules/count.py b/bot/modules/count.py index 829f3fa44c6..fd845a6695d 100644 --- a/bot/modules/count.py +++ b/bot/modules/count.py @@ -1,3 +1,6 @@ +# Implement By https://github.com/anasty17 +# © https://github.com/breakdowns/slam-mirrorbot + from telegram.ext import CommandHandler from bot.helper.mirror_utils.upload_utils.gdriveTools import GoogleDriveHelper from bot.helper.telegram_helper.message_utils import deleteMessage, sendMessage diff --git a/bot/modules/mediainfo.py b/bot/modules/mediainfo.py index b8946f465a8..9843a8da038 100644 --- a/bot/modules/mediainfo.py +++ b/bot/modules/mediainfo.py @@ -6,9 +6,10 @@ from pyrogram import filters from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup from bot import app +from bot.helper.telegram_helper.bot_commands import BotCommands from bot.helper import post_to_telegraph, runcmd, safe_filename -@app.on_message(filters.command(['mediainfo'])) +@app.on_message(filters.command(BotCommands.MediaInfoCommand)) async def mediainfo(client, message): reply = message.reply_to_message if not reply: diff --git a/bot/modules/search.py b/bot/modules/search.py index 3242e710955..34a443f456d 100644 --- a/bot/modules/search.py +++ b/bot/modules/search.py @@ -262,13 +262,13 @@ async def next(self, client, message): RESULT_STR_EZTV = ( "➲Name: `{Name}`\n" "➲Size: {Size}\n" - "➲Seeders: {Seeds}\n" + "➲Seeders: {Seeders}\n" "➲Torrent: `{Torrent}`\n" ) RESULT_STR_TORLOCK = ( "➲Name: `{Name}`\n" "➲Size: {Size}\n" - "➲Seeders: {Seeds} || ➲Leechers: {Peers}\n" + "➲Seeders: {Seeders} || ➲Leechers: {Leechers}\n" "➲Torrent: `{Torrent}`\n" ) RESULT_STR_RARBG = ( diff --git a/bot/modules/shell.py b/bot/modules/shell.py index 2d8548bd395..38364b3856f 100644 --- a/bot/modules/shell.py +++ b/bot/modules/shell.py @@ -3,6 +3,7 @@ from telegram import ParseMode from telegram.ext import CommandHandler from bot.helper.telegram_helper.filters import CustomFilters +from bot.helper.telegram_helper.bot_commands import BotCommands def shell(update, context): @@ -37,5 +38,6 @@ def shell(update, context): message.reply_text(reply, parse_mode=ParseMode.MARKDOWN) -SHELL_HANDLER = CommandHandler(('sh', 'shell', 'term', 'terminal'), shell, filters=CustomFilters.owner_filter, run_async=True) +SHELL_HANDLER = CommandHandler(BotCommands.ShellCommand, shell, + filters=CustomFilters.owner_filter, run_async=True) dispatcher.add_handler(SHELL_HANDLER) diff --git a/bot/modules/updater.py b/bot/modules/updater.py new file mode 100644 index 00000000000..a857f273018 --- /dev/null +++ b/bot/modules/updater.py @@ -0,0 +1,82 @@ +# Implement by https://github.com/jusidama18 +# Based on this https://github.com/DevsExpo/FridayUserbot/blob/master/plugins/updater.py + +import sys +import subprocess +import heroku3 + +from datetime import datetime +from os import environ, execle, path, remove + +from git import Repo +from git.exc import GitCommandError, InvalidGitRepositoryError, NoSuchPathError + +from pyrogram import filters + +from bot import app, OWNER_ID, UPSTREAM_REPO, UPSTREAM_BRANCH +from bot.helper import runcmd, get_text, HEROKU_URL +from bot.helper.telegram_helper.bot_commands import BotCommands + +REPO_ = UPSTREAM_REPO +BRANCH_ = UPSTREAM_BRANCH + +# Update Command + +@app.on_message(filters.command(BotCommands.UpdateCommand) & filters.user(OWNER_ID)) +async def update_it(client, message): + msg_ = await message.reply_text("`Updating Please Wait!`") + try: + repo = Repo() + except GitCommandError: + return await msg_.edit( + "**Invalid Git Command. Please Report This Bug To [Support Group](https://t.me/SlamMirrorSupport)**" + ) + except InvalidGitRepositoryError: + repo = Repo.init() + if "upstream" in repo.remotes: + origin = repo.remote("upstream") + else: + origin = repo.create_remote("upstream", REPO_) + origin.fetch() + repo.create_head(UPSTREAM_BRANCH, origin.refs.master) + repo.heads.master.set_tracking_branch(origin.refs.master) + repo.heads.master.checkout(True) + if repo.active_branch.name != UPSTREAM_BRANCH: + return await msg_.edit( + f"`Seems Like You Are Using Custom Branch - {repo.active_branch.name}! Please Switch To {UPSTREAM_BRANCH} To Make This Updater Function!`" + ) + try: + repo.create_remote("upstream", REPO_) + except BaseException: + pass + ups_rem = repo.remote("upstream") + ups_rem.fetch(UPSTREAM_BRANCH) + if not HEROKU_URL: + try: + ups_rem.pull(UPSTREAM_BRANCH) + except GitCommandError: + repo.git.reset("--hard", "FETCH_HEAD") + await runcmd("pip3 install --no-cache-dir -r requirements.txt") + await msg_.edit("`Updated Sucessfully! Give Me Some Time To Restart!`") + with open("./aria.sh", 'rb') as file: + script = file.read() + subprocess.call("./aria.sh", shell=True) + args = [sys.executable, "-m", "bot"] + execle(sys.executable, *args, environ) + exit() + return + else: + await msg_.edit("`Heroku Detected! Pushing, Please wait!`") + ups_rem.fetch(UPSTREAM_BRANCH) + repo.git.reset("--hard", "FETCH_HEAD") + if "heroku" in repo.remotes: + remote = repo.remote("heroku") + remote.set_url(HEROKU_URL) + else: + remote = repo.create_remote("heroku", HEROKU_URL) + try: + remote.push(refspec="HEAD:refs/heads/master", force=True) + except BaseException as error: + await msg_.edit(f"**Updater Error** \nTraceBack : `{error}`") + return repo.__del__() + await msg_.edit(f"`Updated Sucessfully! \n\nCheck your config with` `/{BotCommands.ConfigMenuCommand}`") diff --git a/config_sample.env b/config_sample.env index ccd2d28fb75..101461dc5b4 100644 --- a/config_sample.env +++ b/config_sample.env @@ -12,6 +12,8 @@ IS_TEAM_DRIVE = "" TELEGRAM_API = TELEGRAM_HASH = "" DATABASE_URL = "" +UPSTREAM_REPO = "https://github.com/breakdowns/slam-mirrorbot" +UPSTREAM_BRANCH = "master" # Optional config AUTHORIZED_CHATS = "" IGNORE_PENDING_REQUESTS = "" @@ -28,11 +30,11 @@ STOP_DUPLICATE_CLONE = "" STOP_DUPLICATE_MEGA = "" SHORTENER = "" SHORTENER_API = "" +IMAGE_URL = "https://telegra.ph/file/db03910496f06094f1f7a.jpg" # To use limit leave space between number and unit. Available units is (gb or GB, tb or TB) TORRENT_DIRECT_LIMIT = "" CLONE_LIMIT = "" MEGA_LIMIT = "" -IMAGE_URL = "https://telegra.ph/file/db03910496f06094f1f7a.jpg" # Fill only if you deploying with heroku-cli and Goorm IDE HEROKU_API_KEY = "" HEROKU_APP_NAME = "" diff --git a/requirements.txt b/requirements.txt index 74b0460958d..76114b34a4b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ aria2p appdirs beautifulsoup4 feedparser +gitpython google-api-python-client google-auth-httplib2 google-auth-oauthlib