diff --git a/README.md b/README.md
index 48fc411f..140988cb 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ This is a Telegram Bot written in Python for mirroring files on the Internet to
- Select files from Torrent before downloading using qbittorrent and aria2c.
- Leech (splitting, thumbnail for each user, setting as document or as media for each user).
- Stop duplicates for all tasks except yt-dlp tasks.
-- Zip/Unzip G-Drive links.
+- Leech/Zip/Unzip G-Drive links.
- Counting files/folders from Google Drive link.
- View Link button, extra button to open file index link in broswer instead of direct download.
- Status Pages for unlimited tasks.
@@ -24,7 +24,7 @@ This is a Telegram Bot written in Python for mirroring files on the Internet to
- Search on torrents with Torrent Search API or with variable plugins using qBittorrent search engine
- Docker image support for linux `amd64, arm64/v8, arm/v7, s390x`.
- Update bot at startup and with restart command using `UPSTREAM_REPO`.
-- Qbittorrent seed until reaching specific ratio or time.
+- Bittorrent seed until reaching specific ratio or time.
- Rss feed and filter. Based on this repository [rss-chan](https://github.com/hyPnOtICDo0g/rss-chan).
- Save leech settings including thumbnails in database.
- Mirror/Leech/Clone multi links/files with one command.
@@ -34,7 +34,7 @@ This is a Telegram Bot written in Python for mirroring files on the Internet to
- Custom Name for all links except torrents. For files you should add extension except yt-dlp links.
- Many bugs have been fixed.
-## From Other Repositories
+## From Base and other Repositories
- Mirror direct download links, Torrent, and Telegram files to Google Drive
- Mirror Mega.nz links to Google Drive
- Copy files from someone's Drive to your Drive (Using Autorclone)
@@ -49,11 +49,11 @@ This is a Telegram Bot written in Python for mirroring files on the Internet to
- Shell and Executor
- Add sudo users
- Extract password protected files
-- Extract these filetypes and uploads to Google Drive
+- Extract these filetypes
> ZIP, RAR, TAR, 7z, ISO, WIM, CAB, GZIP, BZIP2, APM, ARJ, CHM, CPIO, CramFS, DEB, DMG, FAT, HFS, LZH, LZMA, LZMA2, MBR, MSI, MSLZ, NSIS, NTFS, RPM, SquashFS, UDF, VHD, XAR, Z, TAR.XZ
- Direct links Supported:
- >mediafire, letsupload.io, hxfile.co, anonfiles.com, bayfiles.com, antfiles, fembed.com, fembed.net, femax20.com, layarkacaxxi.icu, fcdn.stream, sbplay.org, naniplay.com, naniplay.nanime.in, naniplay.nanime.biz, sbembed.com, streamtape.com, streamsb.net, feurl.com, upload.ee, pixeldrain.com, racaty.net, 1fichier.com, 1drv.ms (Only works for file not folder or business account), uptobox.com (Uptobox account must be premium) and solidfiles.com
+ >mediafire, letsupload.io, hxfile.co, anonfiles.com, bayfiles.com, antfiles, fembed.com, fembed.net, femax20.com, layarkacaxxi.icu, fcdn.stream, sbplay.org, naniplay.com, naniplay.nanime.in, naniplay.nanime.biz, sbembed.com, streamtape.com, streamsb.net, feurl.com, upload.ee, pixeldrain.com, racaty.net, 1fichier.com, 1drv.ms (Only works for file not folder or business account), uptobox.com and solidfiles.com
# How to deploy?
@@ -140,7 +140,6 @@ Fill up rest of the fields. Meaning of each field is discussed below:
- `BASE_URL_OF_BOT`: Valid BASE URL where the bot is deployed to use qbittorrent web selection. Format of URL should be `http://myip`, where `myip` is the IP/Domain(public) of your bot or if you have chosen port other than `80` so write it in this format `http://myip:port` (`http` and not `https`). This Var is optional on VPS and required for Heroku specially to avoid app sleeping/idling. For Heroku fill `https://yourappname.herokuapp.com`. Still got idling? You can use http://cron-job.org to ping your Heroku app. `Str`
- `SERVER_PORT`: Only For VPS, which is the **BASE_URL_OF_BOT** Port. `Str`
- `WEB_PINCODE`: If empty or `False` means no more pincode required while qbit web selection. `Bool`
-- `QB_SEED`: QB torrent will be seeded after and while uploading until reaching specific ratio or time, edit `MaxRatio` or `GlobalMaxSeedingMinutes` or both from qbittorrent.conf (`-1` means no limit, but u can cancel manually by gid). **NOTE**: 1. Don't change `MaxRatioAction`, 2. Only works with `/qbmirror` and `/qbzipmirror`. Also you can use this feature for specific torrent while using the bot and leave this variable empty. Default is `False`. `Bool`
- **Qbittorrent NOTE**: If your facing ram exceeded issue then set limit for `MaxConnecs`, decrease `AsyncIOThreadsCount` in qbittorrent config and set limit of `DiskWriteCacheSize` to `32`.
### RSS
@@ -332,7 +331,22 @@ help - All cmds with description
------
+## Bittorrent Seed
+
+- Add `d:ratio:time` perfix along with leech or mirror cmd.
+- Using `d` perfix alone will lead to use global options for aria2c or qbittorrent.
+
+### Qbittorrent
+- Global options: `MaxRatio` and `GlobalMaxSeedingMinutes` in qbittorrent.conf, `-1` means no limit, but you can cancel manually.
+ - **NOTE**: Don't change `MaxRatioAction`.
+
+### Aria2c
+- Global options: `--seed-ratio` (0 means no limit) and `--seed-time` (0 means no seed) in aria.sh.
+
+------
+
## Using Service Accounts for uploading to avoid user rate limit
+
>For Service Account to work, you must set `USE_SERVICE_ACCOUNTS` = "True" in config file or environment variables.
>**NOTE**: Using Service Accounts is only recommended while uploading to a Team Drive.
diff --git a/aria.sh b/aria.sh
index 99714ff9..fd7cf310 100755
--- a/aria.sh
+++ b/aria.sh
@@ -3,12 +3,11 @@ then
TORRENT_TIMEOUT=0
fi
tracker_list=$(curl -Ns https://raw.githubusercontent.com/XIU2/TrackersListCollection/master/all.txt https://ngosang.github.io/trackerslist/trackers_all_http.txt https://newtrackon.com/api/all https://raw.githubusercontent.com/hezhijie0327/Trackerslist/main/trackerslist_tracker.txt | awk '$0' | tr '\n\n' ',')
-aria2c --enable-rpc=true --check-certificate=false --daemon=true \
- --max-connection-per-server=10 --rpc-max-request-size=1024M --quiet=true \
- --bt-stop-timeout=$TORRENT_TIMEOUT --min-split-size=10M --split=10 --allow-overwrite=true \
- --max-overall-download-limit=0 --bt-tracker="[$tracker_list]" --disk-cache=32M \
- --max-overall-upload-limit=1K --max-concurrent-downloads=15 --summary-interval=0 \
- --peer-id-prefix=-qB4430- --user-agent=Wget/1.12 --peer-agent=qBittorrent/4.4.3\
- --bt-enable-lpd=true --seed-time=0 --max-file-not-found=0 --max-tries=20 --follow-torrent=mem \
- --auto-file-renaming=true --reuse-uri=true --http-accept-gzip=true --continue=true \
- --content-disposition-default-utf8=true --netrc-path=/usr/src/app/.netrc --bt-remove-unselected-file=true
+aria2c --allow-overwrite=true --auto-file-renaming=true --bt-enable-lpd=true \
+ --bt-remove-unselected-file=true --bt-stop-timeout=$TORRENT_TIMEOUT --bt-tracker="[$tracker_list]" \
+ --check-certificate=false --continue=true --content-disposition-default-utf8=true --daemon=true \
+ --disk-cache=40M --enable-rpc=true --follow-torrent=mem --force-save=true --http-accept-gzip=true \
+ --max-connection-per-server=10 --max-concurrent-downloads=20 --max-file-not-found=0 --max-tries=20 \
+ --min-split-size=10M --netrc-path=/usr/src/app/.netrc --optimize-concurrent-downloads=true \
+ --peer-id-prefix=-qB4430- --peer-agent=qBittorrent/4.4.3 --quiet=true --reuse-uri=true \
+ --rpc-max-request-size=1024M --seed-ratio=0 --split=10 --summary-interval=0 --user-agent=Wget/1.12
diff --git a/bot/__init__.py b/bot/__init__.py
index 5af19e39..430d6e28 100644
--- a/bot/__init__.py
+++ b/bot/__init__.py
@@ -107,7 +107,7 @@ AUTHORIZED_CHATS = set()
SUDO_USERS = set()
AS_DOC_USERS = set()
AS_MEDIA_USERS = set()
-EXTENSION_FILTER = set()
+EXTENSION_FILTER = set(['.aria2'])
try:
aid = getConfig('AUTHORIZED_CHATS')
@@ -151,19 +151,19 @@ try:
USER_SESSION_STRING = getConfig('USER_SESSION_STRING')
if len(USER_SESSION_STRING) == 0:
raise KeyError
- LOGGER.info("Creating client from USER_SESSION_STRING")
+ log_info("Creating client from USER_SESSION_STRING")
app = Client(name='pyrogram', api_id=int(TELEGRAM_API), api_hash=TELEGRAM_HASH, session_string=USER_SESSION_STRING, parse_mode=enums.ParseMode.HTML, no_updates=True)
with app:
IS_PREMIUM_USER = app.me.is_premium
except:
- LOGGER.info("Creating client from BOT_TOKEN")
+ log_info("Creating client from BOT_TOKEN")
app = Client(name='pyrogram', api_id=int(TELEGRAM_API), api_hash=TELEGRAM_HASH, bot_token=BOT_TOKEN, parse_mode=enums.ParseMode.HTML, no_updates=True)
try:
RSS_USER_SESSION_STRING = getConfig('RSS_USER_SESSION_STRING')
if len(RSS_USER_SESSION_STRING) == 0:
raise KeyError
- LOGGER.info("Creating client from RSS_USER_SESSION_STRING")
+ log_info("Creating client from RSS_USER_SESSION_STRING")
rss_session = Client(name='rss_session', api_id=int(TELEGRAM_API), api_hash=TELEGRAM_HASH, session_string=RSS_USER_SESSION_STRING, parse_mode=enums.ParseMode.HTML, no_updates=True)
except:
rss_session = None
@@ -212,10 +212,8 @@ try:
raise KeyError
LEECH_SPLIT_SIZE = int(LEECH_SPLIT_SIZE)
except:
- if not IS_PREMIUM_USER:
- LEECH_SPLIT_SIZE = 2097152000
- else:
- LEECH_SPLIT_SIZE = 4194304000
+ LEECH_SPLIT_SIZE = 4194304000 if IS_PREMIUM_USER else 2097152000
+MAX_SPLIT_SIZE = 4194304000 if IS_PREMIUM_USER else 2097152000
try:
STATUS_LIMIT = getConfig('STATUS_LIMIT')
if len(STATUS_LIMIT) == 0:
@@ -335,11 +333,6 @@ try:
EQUAL_SPLITS = EQUAL_SPLITS.lower() == 'true'
except:
EQUAL_SPLITS = False
-try:
- QB_SEED = getConfig('QB_SEED')
- QB_SEED = QB_SEED.lower() == 'true'
-except:
- QB_SEED = False
try:
CUSTOM_FILENAME = getConfig('CUSTOM_FILENAME')
if len(CUSTOM_FILENAME) == 0:
diff --git a/bot/__main__.py b/bot/__main__.py
index 1e6fc285..0f621b16 100644
--- a/bot/__main__.py
+++ b/bot/__main__.py
@@ -9,16 +9,13 @@ from telegram.ext import CommandHandler
from bot import bot, dispatcher, updater, botStartTime, IGNORE_PENDING_REQUESTS, LOGGER, Interval, INCOMPLETE_TASK_NOTIFIER, DB_URI, app, main_loop
from .helper.ext_utils.fs_utils import start_cleanup, clean_all, exit_clean_up
-from .helper.ext_utils.telegraph_helper import telegraph
from .helper.ext_utils.bot_utils import get_readable_file_size, get_readable_time
from .helper.ext_utils.db_handler import DbManger
from .helper.telegram_helper.bot_commands import BotCommands
from .helper.telegram_helper.message_utils import sendMessage, sendMarkup, editMessage, sendLogFile
from .helper.telegram_helper.filters import CustomFilters
from .helper.telegram_helper.button_build import ButtonMaker
-
-from .modules import authorize, list, cancel_mirror, mirror_status, mirror, clone, watch, shell, eval, delete, count, leech_settings, search, rss, bt_select
-
+from .modules import authorize, list, cancel_mirror, mirror_status, mirror_leech, clone, ytdlp, shell, eval, delete, count, leech_settings, search, rss, bt_select
def stats(update, context):
@@ -102,148 +99,60 @@ def ping(update, context):
def log(update, context):
sendLogFile(context.bot, update.message)
-
-help_string_telegraph = f'''
-/{BotCommands.HelpCommand}: To get this message
-
-/{BotCommands.MirrorCommand} [download_url][magnet_link]: Start mirroring to Google Drive. Send /{BotCommands.MirrorCommand} for more help
-
-/{BotCommands.ZipMirrorCommand} [download_url][magnet_link]: Start mirroring and upload the file/folder compressed with zip extension
-
-/{BotCommands.UnzipMirrorCommand} [download_url][magnet_link]: Start mirroring and upload the file/folder extracted from any archive extension
-
-/{BotCommands.QbMirrorCommand} [magnet_link][torrent_file][torrent_file_url]: Start Mirroring using qBittorrent. Send /{BotCommands.QbMirrorCommand} for more help
-
-/{BotCommands.QbZipMirrorCommand} [magnet_link][torrent_file][torrent_file_url]: Start mirroring using qBittorrent and upload the file/folder compressed with zip extension
-
-/{BotCommands.QbUnzipMirrorCommand} [magnet_link][torrent_file][torrent_file_url]: Start mirroring using qBittorrent and upload the file/folder extracted from any archive extension
-
-/{BotCommands.LeechCommand} [download_url][magnet_link]: Start leeching to Telegram, Use /{BotCommands.LeechCommand} s to select files before leeching
-
-/{BotCommands.ZipLeechCommand} [download_url][magnet_link]: Start leeching to Telegram and upload the file/folder compressed with zip extension
-
-/{BotCommands.UnzipLeechCommand} [download_url][magnet_link][torent_file]: Start leeching to Telegram and upload the file/folder extracted from any archive extension
-
-/{BotCommands.QbLeechCommand} [magnet_link][torrent_file][torrent_file_url]: Start leeching to Telegram using qBittorrent, Use /{BotCommands.QbLeechCommand} s to select files before leeching
-
-/{BotCommands.QbZipLeechCommand} [magnet_link][torrent_file][torrent_file_url]: Start leeching to Telegram using qBittorrent and upload the file/folder compressed with zip extension
-
-/{BotCommands.QbUnzipLeechCommand} [magnet_link][torrent_file][torrent_file_url]: Start leeching to Telegram using qBittorrent and upload the file/folder extracted from any archive extension
-
-/{BotCommands.CloneCommand} [drive_url][gdtot_url]: Copy file/folder to Google Drive
-
-/{BotCommands.CountCommand} [drive_url][gdtot_url]: Count file/folder of Google Drive
-
-/{BotCommands.DeleteCommand} [drive_url]: Delete file/folder from Google Drive (Only Owner & Sudo)
-
-/{BotCommands.WatchCommand} [yt-dlp supported link]: Mirror yt-dlp supported link. Send /{BotCommands.WatchCommand} for more help
-
-/{BotCommands.ZipWatchCommand} [yt-dlp supported link]: Mirror yt-dlp supported link as zip
-
-/{BotCommands.LeechWatchCommand} [yt-dlp supported link]: Leech yt-dlp supported link
-
-/{BotCommands.LeechZipWatchCommand} [yt-dlp supported link]: Leech yt-dlp supported link as zip
-
-/{BotCommands.LeechSetCommand}: Leech settings
-
-/{BotCommands.SetThumbCommand}: Reply photo to set it as Thumbnail
-
-/{BotCommands.BtSelectCommand}: Reply to an active /cmd which was used to start the bt-download or add gid along with cmd. This command mainly for selection incase you decided to select files from already added torrent. But you can always use /cmd with arg `s` to select files before download start
-
-/{BotCommands.RssListCommand}: List all subscribed rss feed info
-
-/{BotCommands.RssGetCommand}: [Title] [Number](last N links): Force fetch last N links
-
-/{BotCommands.RssSubCommand}: [Title] [Rss Link] f: [filter]: Subscribe new rss feed
-
-/{BotCommands.RssUnSubCommand}: [Title]: Unubscribe rss feed by title
-
-/{BotCommands.RssSettingsCommand}: Rss Settings
-
-/{BotCommands.CancelMirror}: Reply to the message by which the download was initiated and that download will be cancelled
-
-/{BotCommands.CancelAllCommand}: Cancel all downloading tasks
-
-/{BotCommands.ListCommand} [query]: Search in Google Drive(s)
-
-/{BotCommands.SearchCommand} [query]: Search for torrents with API
-
sites: rarbg, 1337x, yts, etzv, tgx, torlock, piratebay, nyaasi, ettv
-/{BotCommands.StatusCommand}: Shows a status of all the downloads
-
-/{BotCommands.StatsCommand}: Show Stats of the machine the bot is hosted on
-'''
-
-help = telegraph.create_page(
- title='Mirror-Leech-Bot Help',
- content=help_string_telegraph,
- )["path"]
-
help_string = f'''
-/{BotCommands.PingCommand}: Check how long it takes to Ping the Bot
-
-/{BotCommands.AuthorizeCommand}: Authorize a chat or a user to use the bot (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.RestartCommand}: Restart and update the bot
-
-/{BotCommands.LogCommand}: Get a log file of the bot. Handy for getting crash reports
-
-/{BotCommands.ShellCommand}: Run commands in Shell (Only Owner)
-
-/{BotCommands.ExecHelpCommand}: Get help for Executor module (Only Owner)
+NOTE: Try each command without any perfix to see more detalis.
+/{BotCommands.MirrorCommand[0]} or /{BotCommands.MirrorCommand[1]}: Start mirroring to Google Drive.
+/{BotCommands.ZipMirrorCommand[0]} or /{BotCommands.ZipMirrorCommand[1]}: Start mirroring and upload the file/folder compressed with zip extension.
+/{BotCommands.UnzipMirrorCommand[0]} or /{BotCommands.UnzipMirrorCommand[1]}: Start mirroring and upload the file/folder extracted from any archive extension.
+/{BotCommands.QbMirrorCommand[0]} or /{BotCommands.QbMirrorCommand[1]}: Start Mirroring to Google Drive using qBittorrent.
+/{BotCommands.QbZipMirrorCommand[0]} or /{BotCommands.QbZipMirrorCommand[1]}: Start mirroring using qBittorrent and upload the file/folder compressed with zip extension.
+/{BotCommands.QbUnzipMirrorCommand[0]} or /{BotCommands.QbUnzipMirrorCommand[1]}: Start mirroring using qBittorrent and upload the file/folder extracted from any archive extension.
+/{BotCommands.YtdlCommand[0]} or /{BotCommands.YtdlCommand[1]}: Mirror yt-dlp supported link.
+/{BotCommands.YtdlZipCommand[0]} or /{BotCommands.YtdlZipCommand[1]}: Mirror yt-dlp supported link as zip.
+/{BotCommands.LeechCommand[0]} or /{BotCommands.LeechCommand[1]}: Start leeching to Telegram.
+/{BotCommands.ZipLeechCommand[0]} or /{BotCommands.ZipLeechCommand[1]}: Start leeching and upload the file/folder compressed with zip extension.
+/{BotCommands.UnzipLeechCommand[0]} or /{BotCommands.UnzipLeechCommand[1]}: Start leeching and upload the file/folder extracted from any archive extension.
+/{BotCommands.QbLeechCommand[0]} or /{BotCommands.QbLeechCommand[1]}: Start leeching using qBittorrent.
+/{BotCommands.QbZipLeechCommand[0]} or /{BotCommands.QbZipLeechCommand[1]}: Start leeching using qBittorrent and upload the file/folder compressed with zip extension.
+/{BotCommands.QbUnzipLeechCommand[0]} or /{BotCommands.QbUnzipLeechCommand[1]}: Start leeching using qBittorrent and upload the file/folder extracted from any archive extension.
+/{BotCommands.YtdlLeechCommand[0]} or /{BotCommands.YtdlLeechCommand[1]}: Leech yt-dlp supported link.
+/{BotCommands.YtdlZipLeechCommand[0]} or /{BotCommands.YtdlZipLeechCommand[1]}: Leech yt-dlp supported link as zip.
+/{BotCommands.CloneCommand} [drive_url]: Copy file/folder to Google Drive.
+/{BotCommands.CountCommand} [drive_url]: Count file/folder of Google Drive.
+/{BotCommands.DeleteCommand} [drive_url]: Delete file/folder from Google Drive (Only Owner & Sudo).
+/{BotCommands.LeechSetCommand} [query]: Leech settings.
+/{BotCommands.SetThumbCommand}: Reply photo to set it as Thumbnail.
+/{BotCommands.BtSelectCommand}: Select files from torrents by gid or reply.
+/{BotCommands.RssListCommand[0]} or /{BotCommands.RssListCommand[1]}: List all subscribed rss feed info (Only Owner & Sudo).
+/{BotCommands.RssGetCommand[0]} or /{BotCommands.RssGetCommand[1]}: Force fetch last N links (Only Owner & Sudo).
+/{BotCommands.RssSubCommand[0]} or /{BotCommands.RssSubCommand[1]}: Subscribe new rss feed (Only Owner & Sudo).
+/{BotCommands.RssUnSubCommand[0]} or /{BotCommands.RssUnSubCommand[1]}: Unubscribe rss feed by title (Only Owner & Sudo).
+/{BotCommands.RssSettingsCommand[0]} or /{BotCommands.RssSettingsCommand[1]} [query]: Rss Settings (Only Owner & Sudo).
+/{BotCommands.CancelMirror}: Cancel task by gid or reply.
+/{BotCommands.CancelAllCommand} [query]: Cancel all [status] tasks.
+/{BotCommands.ListCommand} [query]: Search in Google Drive(s).
+/{BotCommands.SearchCommand} [query]: Search for torrents with API.
+/{BotCommands.StatusCommand}: Shows a status of all the downloads.
+/{BotCommands.StatsCommand}: Show stats of the machine where the bot is hosted in.
+/{BotCommands.PingCommand}: Check how long it takes to Ping the Bot (Only Owner & Sudo).
+/{BotCommands.AuthorizeCommand}: Authorize a chat or a user to use the bot (Only Owner & Sudo).
+/{BotCommands.UnAuthorizeCommand}: Unauthorize a chat or a user to use the bot (Only Owner & Sudo).
+/{BotCommands.AuthorizedUsersCommand}: Show authorized users (Only Owner & Sudo).
+/{BotCommands.AddSudoCommand}: Add sudo user (Only Owner).
+/{BotCommands.RmSudoCommand}: Remove sudo users (Only Owner).
+/{BotCommands.RestartCommand}: Restart and update the bot (Only Owner & Sudo).
+/{BotCommands.LogCommand}: Get a log file of the bot. Handy for getting crash reports (Only Owner & Sudo).
+/{BotCommands.ShellCommand}: Run shell commands (Only Owner).
+/{BotCommands.EvalCommand}: Run Python Code Line | Lines (Only Owner).
+/{BotCommands.ExecCommand}: Run Commands In Exec (Only Owner).
+/{BotCommands.ClearLocalsCommand}: Clear {BotCommands.EvalCommand} or {BotCommands.ExecCommand} locals (Only Owner).
'''
def bot_help(update, context):
- button = ButtonMaker()
- button.buildbutton("Other Commands", f"https://telegra.ph/{help}")
- reply_markup = InlineKeyboardMarkup(button.build_menu(1))
- sendMarkup(help_string, context.bot, update.message, reply_markup)
-
-botcmds = [
-
- (f'{BotCommands.MirrorCommand}', 'Mirror'),
- (f'{BotCommands.ZipMirrorCommand}','Mirror and upload as zip'),
- (f'{BotCommands.UnzipMirrorCommand}','Mirror and extract files'),
- (f'{BotCommands.QbMirrorCommand}','Mirror torrent using qBittorrent'),
- (f'{BotCommands.QbZipMirrorCommand}','Mirror torrent and upload as zip using qb'),
- (f'{BotCommands.QbUnzipMirrorCommand}','Mirror torrent and extract files using qb'),
- (f'{BotCommands.WatchCommand}','Mirror yt-dlp supported link'),
- (f'{BotCommands.ZipWatchCommand}','Mirror yt-dlp supported link as zip'),
- (f'{BotCommands.CloneCommand}','Copy file/folder to Drive'),
- (f'{BotCommands.LeechCommand}','Leech'),
- (f'{BotCommands.ZipLeechCommand}','Leech and upload as zip'),
- (f'{BotCommands.UnzipLeechCommand}','Leech and extract files'),
- (f'{BotCommands.QbLeechCommand}','Leech torrent using qBittorrent'),
- (f'{BotCommands.QbZipLeechCommand}','Leech torrent and upload as zip using qb'),
- (f'{BotCommands.QbUnzipLeechCommand}','Leech torrent and extract using qb'),
- (f'{BotCommands.LeechWatchCommand}','Leech yt-dlp supported link'),
- (f'{BotCommands.LeechZipWatchCommand}','Leech yt-dlp supported link as zip'),
- (f'{BotCommands.CountCommand}','Count file/folder of Drive'),
- (f'{BotCommands.DeleteCommand}','Delete file/folder from Drive'),
- (f'{BotCommands.CancelMirror}','Cancel a task'),
- (f'{BotCommands.CancelAllCommand}','Cancel all downloading tasks'),
- (f'{BotCommands.ListCommand}','Search in Drive'),
- (f'{BotCommands.LeechSetCommand}','Leech settings'),
- (f'{BotCommands.SetThumbCommand}','Set thumbnail'),
- (f'{BotCommands.StatusCommand}','Get mirror status message'),
- (f'{BotCommands.StatsCommand}','Bot usage stats'),
- (f'{BotCommands.PingCommand}','Ping the bot'),
- (f'{BotCommands.RestartCommand}','Restart the bot'),
- (f'{BotCommands.LogCommand}','Get the bot Log'),
- (f'{BotCommands.HelpCommand}','Get detailed help')
- ]
+ sendMessage(help_string, context.bot, update.message)
def main():
- # bot.set_my_commands(botcmds)
start_cleanup()
- notifier_dict = False
if INCOMPLETE_TASK_NOTIFIER and DB_URI is not None:
if notifier_dict := DbManger().get_incomplete_tasks():
for cid, data in notifier_dict.items():
diff --git a/bot/helper/ext_utils/bot_utils.py b/bot/helper/ext_utils/bot_utils.py
index f972cf94..eb4460eb 100644
--- a/bot/helper/ext_utils/bot_utils.py
+++ b/bot/helper/ext_utils/bot_utils.py
@@ -127,35 +127,19 @@ def get_readable_message():
msg += f"\nStatus: {download.status()}"
if download.status() not in [MirrorStatus.STATUS_SPLITTING, MirrorStatus.STATUS_SEEDING]:
msg += f"\n{get_progress_bar_string(download)} {download.progress()}"
- if download.status() in [MirrorStatus.STATUS_DOWNLOADING,
- MirrorStatus.STATUS_WAITING,
- MirrorStatus.STATUS_PAUSED]:
- msg += f"\nDownloaded: {get_readable_file_size(download.processed_bytes())} of {download.size()}"
- elif download.status() == MirrorStatus.STATUS_UPLOADING:
- msg += f"\nUploaded: {get_readable_file_size(download.processed_bytes())} of {download.size()}"
- elif download.status() == MirrorStatus.STATUS_CLONING:
- msg += f"\nCloned: {get_readable_file_size(download.processed_bytes())} of {download.size()}"
- elif download.status() == MirrorStatus.STATUS_ARCHIVING:
- msg += f"\nArchived: {get_readable_file_size(download.processed_bytes())} of {download.size()}"
- elif download.status() == MirrorStatus.STATUS_EXTRACTING:
- msg += f"\nExtracted: {get_readable_file_size(download.processed_bytes())} of {download.size()}"
+ msg += f"\nProcessed: {get_readable_file_size(download.processed_bytes())} of {download.size()}"
msg += f"\nSpeed: {download.speed()} | ETA: {download.eta()}"
- try:
- msg += f"\nSeeders: {download.aria_download().num_seeders}" \
- f" | Peers: {download.aria_download().connections}"
- except:
- pass
- try:
- msg += f"\nSeeders: {download.torrent_info().num_seeds}" \
- f" | Leechers: {download.torrent_info().num_leechs}"
- except:
- pass
+ if hasattr(download, 'seeders_num'):
+ try:
+ msg += f"\nSeeders: {download.seeders_num()} | Leechers: {download.leechers_num()}"
+ except:
+ pass
elif download.status() == MirrorStatus.STATUS_SEEDING:
msg += f"\nSize: {download.size()}"
- msg += f"\nSpeed: {get_readable_file_size(download.torrent_info().upspeed)}/s"
- msg += f" | Uploaded: {get_readable_file_size(download.torrent_info().uploaded)}"
- msg += f"\nRatio: {round(download.torrent_info().ratio, 3)}"
- msg += f" | Time: {get_readable_time(download.torrent_info().seeding_time)}"
+ msg += f"\nSpeed: {download.upload_speed()}"
+ msg += f" | Uploaded: {download.uploaded_bytes()}"
+ msg += f"\nRatio: {download.ratio()}"
+ msg += f" | Time: {download.seeding_time()}"
else:
msg += f"\nSize: {download.size()}"
msg += f"\n/{BotCommands.CancelMirror} {download.gid()}
"
@@ -180,6 +164,12 @@ def get_readable_message():
upspeed_bytes += float(spd.split('K')[0]) * 1024
elif 'MB/s' in spd:
upspeed_bytes += float(spd.split('M')[0]) * 1048576
+ elif download.status() == MirrorStatus.STATUS_SEEDING:
+ spd = download.upload_speed()
+ if 'K' in spd:
+ upspeed_bytes += float(spd.split('K')[0]) * 1024
+ elif 'M' in spd:
+ upspeed_bytes += float(spd.split('M')[0]) * 1048576
bmsg += f"\nDL: {get_readable_file_size(dlspeed_bytes)}/s | UL: {get_readable_file_size(upspeed_bytes)}/s"
if STATUS_LIMIT is not None and tasks > STATUS_LIMIT:
msg += f"Page: {PAGE_NO}/{pages} | Tasks: {tasks}\n"
diff --git a/bot/helper/ext_utils/fs_utils.py b/bot/helper/ext_utils/fs_utils.py
index c75e5da8..365f2be1 100644
--- a/bot/helper/ext_utils/fs_utils.py
+++ b/bot/helper/ext_utils/fs_utils.py
@@ -10,12 +10,7 @@ from math import ceil
from re import split as re_split, I
from .exceptions import NotSupportedExtractionArchive
-from bot import aria2, app, LOGGER, DOWNLOAD_DIR, get_client, LEECH_SPLIT_SIZE, EQUAL_SPLITS, IS_PREMIUM_USER
-
-if IS_PREMIUM_USER:
- MAX_SPLIT_SIZE = 4194304000
-else:
- MAX_SPLIT_SIZE = 2097152000
+from bot import aria2, app, LOGGER, DOWNLOAD_DIR, get_client, LEECH_SPLIT_SIZE, EQUAL_SPLITS, IS_PREMIUM_USER, MAX_SPLIT_SIZE
VIDEO_SUFFIXES = ("M4V", "MP4", "MOV", "FLV", "WMV", "3GP", "MPG", "WEBM", "MKV", "AVI")
@@ -24,6 +19,19 @@ ARCH_EXT = [".tar.bz2", ".tar.gz", ".bz2", ".gz", ".tar.xz", ".tar", ".tbz2", ".
".cpio", ".cramfs", ".deb", ".dmg", ".fat", ".hfs", ".lzh", ".lzma", ".mbr",
".msi", ".mslz", ".nsis", ".ntfs", ".rpm", ".squashfs", ".udf", ".vhd", ".xar"]
+def clean_target(path: str):
+ if ospath.exists(path):
+ LOGGER.info(f"Cleaning Target: {path}")
+ if ospath.isdir(path):
+ try:
+ rmtree(path)
+ except:
+ pass
+ elif ospath.isfile(path):
+ try:
+ osremove(path)
+ except:
+ pass
def clean_download(path: str):
if ospath.exists(path):
@@ -62,11 +70,10 @@ def clean_unwanted(path: str):
LOGGER.info(f"Cleaning unwanted files/folders: {path}")
for dirpath, subdir, files in walk(path, topdown=False):
for filee in files:
- if filee.endswith((".!qB", ".aria2")) or filee.endswith('.parts') and filee.startswith('.'):
+ if filee.endswith(".!qB") or filee.endswith('.parts') and filee.startswith('.'):
osremove(ospath.join(dirpath, filee))
- for folder in subdir:
- if folder == ".unwanted":
- rmtree(ospath.join(dirpath, folder))
+ if dirpath.endswith((".unwanted", "splited_files_mltb")):
+ rmtree(dirpath)
for dirpath, subdir, files in walk(path, topdown=False):
if not listdir(dirpath):
rmdir(dirpath)
@@ -117,6 +124,9 @@ def take_ss(video_file):
return des_dir
def split_file(path, size, file_, dirpath, split_size, listener, start_time=0, i=1, inLoop=False, noMap=False):
+ if listener.seed and not listener.newDir:
+ dirpath = f"{dirpath}/splited_files_mltb"
+ mkdir(dirpath)
parts = ceil(size/LEECH_SPLIT_SIZE)
if EQUAL_SPLITS and not inLoop:
split_size = ceil(size/parts) + 1000
@@ -129,20 +139,29 @@ def split_file(path, size, file_, dirpath, split_size, listener, start_time=0, i
out_path = ospath.join(dirpath, parted_name)
if not noMap:
listener.suproc = Popen(["ffmpeg", "-hide_banner", "-loglevel", "error", "-ss", str(start_time),
- "-i", path, "-fs", str(split_size), "-map", "0", "-map_chapters", "-1", "-c", "copy", out_path])
+ "-i", path, "-fs", str(split_size), "-map", "0", "-map_chapters", "-1",
+ "-c", "copy", out_path])
else:
listener.suproc = Popen(["ffmpeg", "-hide_banner", "-loglevel", "error", "-ss", str(start_time),
- "-i", path, "-fs", str(split_size), "-map_chapters", "-1", "-c", "copy", out_path])
+ "-i", path, "-fs", str(split_size), "-map_chapters", "-1", "-c", "copy",
+ out_path])
listener.suproc.wait()
if listener.suproc.returncode == -9:
return False
elif listener.suproc.returncode != 0 and not noMap:
- LOGGER.warning(f'Retrying without map, -map 0 not working in all situations. Path: {path}')
+ LOGGER.warning(f"Retrying without map, -map 0 not working in all situations. Path: {path}")
try:
osremove(out_path)
except:
pass
return split_file(path, size, file_, dirpath, split_size, listener, start_time, i, True, True)
+ elif listener.suproc.returncode != 0:
+ LOGGER.warning(f"Unable to split this video, if it's size less than {MAX_SPLIT_SIZE} will be uploaded as it is. Path: {path}")
+ try:
+ osremove(out_path)
+ except:
+ pass
+ return "errored"
out_size = get_path_size(out_path)
if out_size > MAX_SPLIT_SIZE:
dif = out_size - MAX_SPLIT_SIZE
@@ -163,7 +182,8 @@ def split_file(path, size, file_, dirpath, split_size, listener, start_time=0, i
i = i + 1
else:
out_path = ospath.join(dirpath, file_ + ".")
- listener.suproc = Popen(["split", "--numeric-suffixes=1", "--suffix-length=3", f"--bytes={split_size}", path, out_path])
+ listener.suproc = Popen(["split", "--numeric-suffixes=1", "--suffix-length=3",
+ f"--bytes={split_size}", path, out_path])
listener.suproc.wait()
if listener.suproc.returncode == -9:
return False
diff --git a/bot/helper/ext_utils/html_helper.py b/bot/helper/ext_utils/html_helper.py
new file mode 100644
index 00000000..0a2c4e8b
--- /dev/null
+++ b/bot/helper/ext_utils/html_helper.py
@@ -0,0 +1,125 @@
+hmtl_content = """
+
+
{file.get('name')}
(folder)
{file.get('name')}
({get_readable_file_size(int(file.get('size', 0)))})
{escape(name)}
\n\nSize: {size}"
+ if self.isLeech:
+ msg += f'\nTotal Files: {folders}'
+ if typ != 0:
+ msg += f'\nCorrupted Files: {typ}'
+ msg += f'\ncc: {self.tag}\n\n'
+ if not files:
+ sendMessage(msg, self.bot, self.message)
+ else:
+ fmsg = ''
+ for index, (link, name) in enumerate(files.items(), start=1):
+ fmsg += f"{index}. {name}\n"
+ if len(fmsg.encode() + msg.encode()) > 4000:
+ sendMessage(msg + fmsg, self.bot, self.message)
+ sleep(1)
+ fmsg = ''
+ if fmsg != '':
+ sendMessage(msg + fmsg, self.bot, self.message)
+ if self.seed:
+ if self.newDir:
+ clean_target(self.newDir)
+ return
+ else:
+ msg += f'\n\nType: {typ}'
+ if typ == "Folder":
+ msg += f'\nSubFolders: {folders}'
+ msg += f'\nFiles: {files}'
+ msg += f'\n\ncc: {self.tag}'
+ buttons = ButtonMaker()
+ buttons.buildbutton("☁️ Drive Link", link)
+ LOGGER.info(f'Done Uploading {name}')
+ if INDEX_URL is not None:
+ url_path = rutils.quote(f'{name}')
+ share_url = f'{INDEX_URL}/{url_path}'
+ if typ == "Folder":
+ share_url += '/'
+ buttons.buildbutton("⚡ Index Link", share_url)
+ else:
+ buttons.buildbutton("⚡ Index Link", share_url)
+ if VIEW_LINK:
+ share_urls = f'{INDEX_URL}/{url_path}?a=view'
+ buttons.buildbutton("🌐 View Link", share_urls)
+ sendMarkup(msg, self.bot, self.message, InlineKeyboardMarkup(buttons.build_menu(2)))
+ if self.seed:
+ if self.isZip:
+ clean_target(f"{self.dir}/{name}")
+ elif self.newDir:
+ clean_target(self.newDir)
+ return
+ clean_download(self.dir)
+ with download_dict_lock:
+ try:
+ del download_dict[self.uid]
+ except Exception as e:
+ LOGGER.error(str(e))
+ count = len(download_dict)
+ if count == 0:
+ self.clean()
+ else:
+ update_all_messages()
+
+ def onDownloadError(self, error):
+ error = error.replace('<', ' ').replace('>', ' ')
+ clean_download(self.dir)
+ if self.newDir:
+ clean_download(self.newDir)
+ with download_dict_lock:
+ try:
+ del download_dict[self.uid]
+ except Exception as e:
+ LOGGER.error(str(e))
+ count = len(download_dict)
+ msg = f"{self.tag} your download has been stopped due to: {error}"
+ sendMessage(msg, self.bot, self.message)
+ if count == 0:
+ self.clean()
+ else:
+ update_all_messages()
+
+ if not self.isPrivate and INCOMPLETE_TASK_NOTIFIER and DB_URI is not None:
+ DbManger().rm_complete_task(self.message.link)
+
+ def onUploadError(self, error):
+ e_str = error.replace('<', '').replace('>', '')
+ clean_download(self.dir)
+ if self.newDir:
+ clean_download(self.newDir)
+ with download_dict_lock:
+ try:
+ del download_dict[self.uid]
+ except Exception as e:
+ LOGGER.error(str(e))
+ count = len(download_dict)
+ sendMessage(f"{self.tag} {e_str}", self.bot, self.message)
+ if count == 0:
+ self.clean()
+ else:
+ update_all_messages()
+
+ if not self.isPrivate and INCOMPLETE_TASK_NOTIFIER and DB_URI is not None:
+ DbManger().rm_complete_task(self.message.link)
diff --git a/bot/modules/mirror.py b/bot/modules/mirror.py
deleted file mode 100644
index fe153ee4..00000000
--- a/bot/modules/mirror.py
+++ /dev/null
@@ -1,546 +0,0 @@
-from base64 import b64encode
-from requests import utils as rutils, get as rget
-from re import match as re_match, search as re_search, split as re_split
-from time import sleep, time
-from os import path as ospath, remove as osremove, listdir, walk
-from shutil import rmtree
-from threading import Thread
-from subprocess import Popen
-from html import escape
-from telegram.ext import CommandHandler
-from telegram import InlineKeyboardMarkup
-
-from bot import Interval, INDEX_URL, VIEW_LINK, aria2, QB_SEED, dispatcher, DOWNLOAD_DIR, \
- download_dict, download_dict_lock, LEECH_SPLIT_SIZE, LOGGER, DB_URI, INCOMPLETE_TASK_NOTIFIER
-from bot.helper.ext_utils.bot_utils import is_url, is_magnet, is_mega_link, is_gdrive_link, get_content_type
-from bot.helper.ext_utils.fs_utils import get_base_name, get_path_size, split_file, clean_download
-from bot.helper.ext_utils.exceptions import DirectDownloadLinkException, NotSupportedExtractionArchive
-from bot.helper.mirror_utils.download_utils.aria2_download import add_aria2c_download
-from bot.helper.mirror_utils.download_utils.gd_downloader import add_gd_download
-from bot.helper.mirror_utils.download_utils.qbit_downloader import QbDownloader
-from bot.helper.mirror_utils.download_utils.mega_downloader import add_mega_download
-from bot.helper.mirror_utils.download_utils.direct_link_generator import direct_link_generator
-from bot.helper.mirror_utils.download_utils.telegram_downloader import TelegramDownloadHelper
-from bot.helper.mirror_utils.status_utils.extract_status import ExtractStatus
-from bot.helper.mirror_utils.status_utils.zip_status import ZipStatus
-from bot.helper.mirror_utils.status_utils.split_status import SplitStatus
-from bot.helper.mirror_utils.status_utils.upload_status import UploadStatus
-from bot.helper.mirror_utils.status_utils.tg_upload_status import TgUploadStatus
-from bot.helper.mirror_utils.upload_utils.gdriveTools import GoogleDriveHelper
-from bot.helper.mirror_utils.upload_utils.pyrogramEngine import TgUploader
-from bot.helper.telegram_helper.bot_commands import BotCommands
-from bot.helper.telegram_helper.filters import CustomFilters
-from bot.helper.telegram_helper.message_utils import sendMessage, sendMarkup, delete_all_messages, update_all_messages
-from bot.helper.telegram_helper.button_build import ButtonMaker
-from bot.helper.ext_utils.db_handler import DbManger
-
-
-class MirrorListener:
- def __init__(self, bot, message, isZip=False, extract=False, isQbit=False, isLeech=False, pswd=None, tag=None, select=False, seed=False):
- self.bot = bot
- self.message = message
- self.uid = self.message.message_id
- self.extract = extract
- self.isZip = isZip
- self.isQbit = isQbit
- self.isLeech = isLeech
- self.pswd = pswd
- self.tag = tag
- self.seed = any([seed, QB_SEED])
- self.select = select
- self.isPrivate = self.message.chat.type in ['private', 'group']
- self.suproc = None
-
- def clean(self):
- try:
- Interval[0].cancel()
- Interval.clear()
- aria2.purge()
- delete_all_messages()
- except:
- pass
-
- def onDownloadStart(self):
- if not self.isPrivate and INCOMPLETE_TASK_NOTIFIER and DB_URI is not None:
- DbManger().add_incomplete_task(self.message.chat.id, self.message.link, self.tag)
-
- def onDownloadComplete(self):
- with download_dict_lock:
- LOGGER.info(f"Download completed: {download_dict[self.uid].name()}")
- download = download_dict[self.uid]
- name = str(download.name()).replace('/', '')
- gid = download.gid()
- if name == "None" or self.isQbit or not ospath.exists(f'{DOWNLOAD_DIR}{self.uid}/{name}'):
- name = listdir(f'{DOWNLOAD_DIR}{self.uid}')[-1]
- m_path = f'{DOWNLOAD_DIR}{self.uid}/{name}'
- size = get_path_size(m_path)
- if self.isZip:
- path = m_path + ".zip"
- with download_dict_lock:
- download_dict[self.uid] = ZipStatus(name, size, gid, self)
- if self.pswd is not None:
- if self.isLeech and int(size) > LEECH_SPLIT_SIZE:
- LOGGER.info(f'Zip: orig_path: {m_path}, zip_path: {path}.0*')
- self.suproc = Popen(["7z", f"-v{LEECH_SPLIT_SIZE}b", "a", "-mx=0", f"-p{self.pswd}", path, m_path])
- else:
- LOGGER.info(f'Zip: orig_path: {m_path}, zip_path: {path}')
- self.suproc = Popen(["7z", "a", "-mx=0", f"-p{self.pswd}", path, m_path])
- elif self.isLeech and int(size) > LEECH_SPLIT_SIZE:
- LOGGER.info(f'Zip: orig_path: {m_path}, zip_path: {path}.0*')
- self.suproc = Popen(["7z", f"-v{LEECH_SPLIT_SIZE}b", "a", "-mx=0", path, m_path])
- else:
- LOGGER.info(f'Zip: orig_path: {m_path}, zip_path: {path}')
- self.suproc = Popen(["7z", "a", "-mx=0", path, m_path])
- self.suproc.wait()
- if self.suproc.returncode == -9:
- return
- elif self.suproc.returncode != 0:
- LOGGER.error('An error occurred while zipping! Uploading anyway')
- path = f'{DOWNLOAD_DIR}{self.uid}/{name}'
- if self.suproc.returncode == 0 and (not self.isQbit or not self.seed or self.isLeech):
- try:
- rmtree(m_path)
- except:
- osremove(m_path)
- elif self.extract:
- try:
- if ospath.isfile(m_path):
- path = get_base_name(m_path)
- LOGGER.info(f"Extracting: {name}")
- with download_dict_lock:
- download_dict[self.uid] = ExtractStatus(name, size, gid, self)
- if ospath.isdir(m_path):
- for dirpath, subdir, files in walk(m_path, topdown=False):
- for file_ in files:
- if file_.endswith((".zip", ".7z")) or re_search(r'\.part0*1\.rar$|\.7z\.0*1$|\.zip\.0*1$', file_) \
- or (file_.endswith(".rar") and not re_search(r'\.part\d+\.rar$', file_)):
- m_path = ospath.join(dirpath, file_)
- if self.pswd is not None:
- self.suproc = Popen(["7z", "x", f"-p{self.pswd}", m_path, f"-o{dirpath}", "-aot"])
- else:
- self.suproc = Popen(["7z", "x", m_path, f"-o{dirpath}", "-aot"])
- self.suproc.wait()
- if self.suproc.returncode == -9:
- return
- elif self.suproc.returncode != 0:
- LOGGER.error('Unable to extract archive splits! Uploading anyway')
- if self.suproc is not None and self.suproc.returncode == 0:
- for file_ in files:
- if file_.endswith((".rar", ".zip", ".7z")) or \
- re_search(r'\.r\d+$|\.7z\.\d+$|\.z\d+$|\.zip\.\d+$', file_):
- del_path = ospath.join(dirpath, file_)
- osremove(del_path)
- path = f'{DOWNLOAD_DIR}{self.uid}/{name}'
- else:
- if self.pswd is not None:
- self.suproc = Popen(["bash", "pextract", m_path, self.pswd])
- else:
- self.suproc = Popen(["bash", "extract", m_path])
- self.suproc.wait()
- if self.suproc.returncode == -9:
- return
- elif self.suproc.returncode == 0:
- LOGGER.info(f"Extracted Path: {path}")
- osremove(m_path)
- else:
- LOGGER.error('Unable to extract archive! Uploading anyway')
- path = f'{DOWNLOAD_DIR}{self.uid}/{name}'
- except NotSupportedExtractionArchive:
- LOGGER.info("Not any valid archive, uploading file as it is.")
- path = f'{DOWNLOAD_DIR}{self.uid}/{name}'
- else:
- path = f'{DOWNLOAD_DIR}{self.uid}/{name}'
- up_name = path.rsplit('/', 1)[-1]
- if self.isLeech and not self.isZip:
- checked = False
- for dirpath, subdir, files in walk(f'{DOWNLOAD_DIR}{self.uid}', topdown=False):
- for file_ in files:
- f_path = ospath.join(dirpath, file_)
- f_size = ospath.getsize(f_path)
- if int(f_size) > LEECH_SPLIT_SIZE:
- if not checked:
- checked = True
- with download_dict_lock:
- download_dict[self.uid] = SplitStatus(up_name, size, gid, self)
- LOGGER.info(f"Splitting: {up_name}")
- res = split_file(f_path, f_size, file_, dirpath, LEECH_SPLIT_SIZE, self)
- if not res:
- return
- osremove(f_path)
- if self.isLeech:
- size = get_path_size(f'{DOWNLOAD_DIR}{self.uid}')
- LOGGER.info(f"Leech Name: {up_name}")
- tg = TgUploader(up_name, self)
- tg_upload_status = TgUploadStatus(tg, size, gid, self)
- with download_dict_lock:
- download_dict[self.uid] = tg_upload_status
- update_all_messages()
- tg.upload()
- else:
- up_path = f'{DOWNLOAD_DIR}{self.uid}/{up_name}'
- size = get_path_size(up_path)
- LOGGER.info(f"Upload Name: {up_name}")
- drive = GoogleDriveHelper(up_name, self)
- upload_status = UploadStatus(drive, size, gid, self)
- with download_dict_lock:
- download_dict[self.uid] = upload_status
- update_all_messages()
- drive.upload(up_name)
-
- def onDownloadError(self, error):
- error = error.replace('<', ' ').replace('>', ' ')
- clean_download(f'{DOWNLOAD_DIR}{self.uid}')
- with download_dict_lock:
- try:
- del download_dict[self.uid]
- except Exception as e:
- LOGGER.error(str(e))
- count = len(download_dict)
- msg = f"{self.tag} your download has been stopped due to: {error}"
- sendMessage(msg, self.bot, self.message)
- if count == 0:
- self.clean()
- else:
- update_all_messages()
-
- if not self.isPrivate and INCOMPLETE_TASK_NOTIFIER and DB_URI is not None:
- DbManger().rm_complete_task(self.message.link)
-
- def onUploadComplete(self, link: str, size, files, folders, typ, name: str):
- if not self.isPrivate and INCOMPLETE_TASK_NOTIFIER and DB_URI is not None:
- DbManger().rm_complete_task(self.message.link)
- msg = f"Name: {escape(name)}
\n\nSize: {size}"
- if self.isLeech:
- msg += f'\nTotal Files: {folders}'
- if typ != 0:
- msg += f'\nCorrupted Files: {typ}'
- msg += f'\ncc: {self.tag}\n\n'
- if not files:
- sendMessage(msg, self.bot, self.message)
- else:
- fmsg = ''
- for index, (link, name) in enumerate(files.items(), start=1):
- fmsg += f"{index}. {name}\n"
- if len(fmsg.encode() + msg.encode()) > 4000:
- sendMessage(msg + fmsg, self.bot, self.message)
- sleep(1)
- fmsg = ''
- if fmsg != '':
- sendMessage(msg + fmsg, self.bot, self.message)
- else:
- msg += f'\n\nType: {typ}'
- if ospath.isdir(f'{DOWNLOAD_DIR}{self.uid}/{name}'):
- msg += f'\nSubFolders: {folders}'
- msg += f'\nFiles: {files}'
- msg += f'\n\ncc: {self.tag}'
- buttons = ButtonMaker()
- buttons.buildbutton("☁️ Drive Link", link)
- LOGGER.info(f'Done Uploading {name}')
- if INDEX_URL is not None:
- url_path = rutils.quote(f'{name}')
- share_url = f'{INDEX_URL}/{url_path}'
- if ospath.isdir(f'{DOWNLOAD_DIR}/{self.uid}/{name}'):
- share_url += '/'
- buttons.buildbutton("⚡ Index Link", share_url)
- else:
- buttons.buildbutton("⚡ Index Link", share_url)
- if VIEW_LINK:
- share_urls = f'{INDEX_URL}/{url_path}?a=view'
- buttons.buildbutton("🌐 View Link", share_urls)
- sendMarkup(msg, self.bot, self.message, InlineKeyboardMarkup(buttons.build_menu(2)))
- if self.isQbit and self.seed and not self.extract:
- if self.isZip:
- try:
- osremove(f'{DOWNLOAD_DIR}{self.uid}/{name}')
- except:
- pass
- return
- clean_download(f'{DOWNLOAD_DIR}{self.uid}')
- with download_dict_lock:
- try:
- del download_dict[self.uid]
- except Exception as e:
- LOGGER.error(str(e))
- count = len(download_dict)
- if count == 0:
- self.clean()
- else:
- update_all_messages()
-
- def onUploadError(self, error):
- e_str = error.replace('<', '').replace('>', '')
- clean_download(f'{DOWNLOAD_DIR}{self.uid}')
- with download_dict_lock:
- try:
- del download_dict[self.uid]
- except Exception as e:
- LOGGER.error(str(e))
- count = len(download_dict)
- sendMessage(f"{self.tag} {e_str}", self.bot, self.message)
- if count == 0:
- self.clean()
- else:
- update_all_messages()
-
- if not self.isPrivate and INCOMPLETE_TASK_NOTIFIER and DB_URI is not None:
- DbManger().rm_complete_task(self.message.link)
-
-def _mirror(bot, message, isZip=False, extract=False, isQbit=False, isLeech=False, pswd=None, multi=0, select=False, seed=False):
- mesg = message.text.split('\n')
- message_args = mesg[0].split(maxsplit=1)
- name_args = mesg[0].split('|', maxsplit=1)
- index = 1
-
- if len(message_args) > 1:
- args = mesg[0].split(maxsplit=3)
- if "s" in [x.strip() for x in args]:
- select = True
- index += 1
- if "d" in [x.strip() for x in args]:
- seed = True
- index += 1
- message_args = mesg[0].split(maxsplit=index)
- if len(message_args) > index:
- link = message_args[index].strip()
- if link.isdigit():
- multi = int(link)
- link = ''
- elif link.startswith(("|", "pswd:")):
- link = ''
- else:
- link = ''
- else:
- link = ''
-
- if len(name_args) > 1:
- name = name_args[1]
- name = name.split(' pswd:')[0]
- name = name.strip()
- else:
- name = ''
-
- link = re_split(r"pswd:|\|", link)[0]
- link = link.strip()
-
- pswd_arg = mesg[0].split(' pswd: ')
- if len(pswd_arg) > 1:
- pswd = pswd_arg[1]
-
- if message.from_user.username:
- tag = f"@{message.from_user.username}"
- else:
- tag = message.from_user.mention_html(message.from_user.first_name)
-
- reply_to = message.reply_to_message
- if reply_to is not None:
- file = None
- media_array = [reply_to.document, reply_to.video, reply_to.audio]
- for i in media_array:
- if i is not None:
- file = i
- break
-
- if not reply_to.from_user.is_bot:
- if reply_to.from_user.username:
- tag = f"@{reply_to.from_user.username}"
- else:
- tag = reply_to.from_user.mention_html(reply_to.from_user.first_name)
-
- if not is_url(link) and not is_magnet(link) or len(link) == 0:
- if file is None:
- reply_text = reply_to.text.split(maxsplit=1)[0].strip()
- if is_url(reply_text) or is_magnet(reply_text):
- link = reply_text
- elif file.mime_type != "application/x-bittorrent" and not isQbit:
- listener = MirrorListener(bot, message, isZip, extract, isQbit, isLeech, pswd, tag)
- Thread(target=TelegramDownloadHelper(listener).add_download, args=(message, f'{DOWNLOAD_DIR}{listener.uid}/', name)).start()
- if multi > 1:
- sleep(4)
- nextmsg = type('nextmsg', (object, ), {'chat_id': message.chat_id, 'message_id': message.reply_to_message.message_id + 1})
- nextmsg = sendMessage(message_args[0], bot, nextmsg)
- nextmsg.from_user.id = message.from_user.id
- multi -= 1
- sleep(4)
- Thread(target=_mirror, args=(bot, nextmsg, isZip, extract, isQbit, isLeech, pswd, multi)).start()
- return
- else:
- link = file.get_file().file_path
-
- if not is_url(link) and not is_magnet(link) and not ospath.exists(link):
- help_msg = "Send link along with command line:"
- if isQbit:
- help_msg += "\n\nBittorrent selection:"
- help_msg += "\n/cmd
s {link} or by replying to {file/link}"
- help_msg += "\n\nQbittorrent seed:"
- help_msg += "\n/qbcmd
d {link} or by replying to {file/link}. "
- help_msg += "Sure you can use seed and select perfix together with qbcmds."
- help_msg += "\n\nMulti links only by replying to first link/file:"
- help_msg += "\n/command
10(number of links/files)"
- else:
- help_msg += "\n/cmd
{link} |newname pswd: xx [zip/unzip]"
- help_msg += "\n\nBy replying to link/file:"
- help_msg += "\n/cmd
|newname pswd: xx [zip/unzip]"
- help_msg += "\n\nDirect link authorization:"
- help_msg += "\n/cmd
{link} |newname pswd: xx\nusername\npassword"
- help_msg += "\n\nBittorrent selection:"
- help_msg += "\n/cmd
s {link} or by replying to {file/link}"
- help_msg += "\n\nMulti links only by replying to first link/file:"
- help_msg += "\n/command
10(number of links/files)"
- return sendMessage(help_msg, bot, message)
-
- LOGGER.info(link)
-
- if not is_mega_link(link) and not isQbit and not is_magnet(link) \
- and not is_gdrive_link(link) and not link.endswith('.torrent'):
- content_type = get_content_type(link)
- if content_type is None or re_match(r'text/html|text/plain', content_type):
- try:
- link = direct_link_generator(link)
- LOGGER.info(f"Generated link: {link}")
- except DirectDownloadLinkException as e:
- LOGGER.info(str(e))
- if str(e).startswith('ERROR:'):
- return sendMessage(str(e), bot, message)
- elif isQbit and not is_magnet(link):
- if link.endswith('.torrent') or "https://api.telegram.org/file/" in link:
- content_type = None
- else:
- content_type = get_content_type(link)
- if content_type is None or re_match(r'application/x-bittorrent|application/octet-stream', content_type):
- try:
- resp = rget(link, timeout=10, headers = {'user-agent': 'Wget/1.12'})
- if resp.status_code == 200:
- file_name = str(time()).replace(".", "") + ".torrent"
- with open(file_name, "wb") as t:
- t.write(resp.content)
- link = str(file_name)
- else:
- return sendMessage(f"{tag} ERROR: link got HTTP response: {resp.status_code}", bot, message)
- except Exception as e:
- error = str(e).replace('<', ' ').replace('>', ' ')
- if error.startswith('No connection adapters were found for'):
- link = error.split("'")[1]
- else:
- LOGGER.error(str(e))
- return sendMessage(tag + " " + error, bot, message)
- else:
- msg = "Qb commands for torrents only. if you are trying to dowload torrent then report."
- return sendMessage(msg, bot, message)
-
-
- listener = MirrorListener(bot, message, isZip, extract, isQbit, isLeech, pswd, tag, select, seed)
-
- if is_gdrive_link(link):
- if not isZip and not extract and not isLeech:
- gmsg = f"Use /{BotCommands.CloneCommand} to clone Google Drive file/folder\n\n"
- gmsg += f"Use /{BotCommands.ZipMirrorCommand} to make zip of Google Drive folder\n\n"
- gmsg += f"Use /{BotCommands.UnzipMirrorCommand} to extracts Google Drive archive folder/file"
- sendMessage(gmsg, bot, message)
- else:
- Thread(target=add_gd_download, args=(link, listener, name)).start()
- elif is_mega_link(link):
- Thread(target=add_mega_download, args=(link, f'{DOWNLOAD_DIR}{listener.uid}/', listener, name)).start()
- elif isQbit and (is_magnet(link) or ospath.exists(link)):
- Thread(target=QbDownloader(listener).add_qb_torrent, args=(link, f'{DOWNLOAD_DIR}{listener.uid}', select)).start()
- else:
- if len(mesg) > 1:
- try:
- ussr = mesg[1]
- except:
- ussr = ''
- try:
- pssw = mesg[2]
- except:
- pssw = ''
- auth = f"{ussr}:{pssw}"
- auth = "Basic " + b64encode(auth.encode()).decode('ascii')
- else:
- auth = ''
- Thread(target=add_aria2c_download, args=(link, f'{DOWNLOAD_DIR}{listener.uid}', listener, name, auth, select)).start()
-
- if multi > 1:
- sleep(4)
- nextmsg = type('nextmsg', (object, ), {'chat_id': message.chat_id, 'message_id': message.reply_to_message.message_id + 1})
- msg = message_args[0]
- if len(mesg) > 2:
- msg += '\n' + mesg[1] + '\n' + mesg[2]
- nextmsg = sendMessage(msg, bot, nextmsg)
- nextmsg.from_user.id = message.from_user.id
- multi -= 1
- sleep(4)
- Thread(target=_mirror, args=(bot, nextmsg, isZip, extract, isQbit, isLeech, pswd, multi, select, seed)).start()
-
-
-def mirror(update, context):
- _mirror(context.bot, update.message)
-
-def unzip_mirror(update, context):
- _mirror(context.bot, update.message, extract=True)
-
-def zip_mirror(update, context):
- _mirror(context.bot, update.message, True)
-
-def qb_mirror(update, context):
- _mirror(context.bot, update.message, isQbit=True)
-
-def qb_unzip_mirror(update, context):
- _mirror(context.bot, update.message, extract=True, isQbit=True)
-
-def qb_zip_mirror(update, context):
- _mirror(context.bot, update.message, True, isQbit=True)
-
-def leech(update, context):
- _mirror(context.bot, update.message, isLeech=True)
-
-def unzip_leech(update, context):
- _mirror(context.bot, update.message, extract=True, isLeech=True)
-
-def zip_leech(update, context):
- _mirror(context.bot, update.message, True, isLeech=True)
-
-def qb_leech(update, context):
- _mirror(context.bot, update.message, isQbit=True, isLeech=True)
-
-def qb_unzip_leech(update, context):
- _mirror(context.bot, update.message, extract=True, isQbit=True, isLeech=True)
-
-def qb_zip_leech(update, context):
- _mirror(context.bot, update.message, True, isQbit=True, isLeech=True)
-
-mirror_handler = CommandHandler(BotCommands.MirrorCommand, mirror,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-unzip_mirror_handler = CommandHandler(BotCommands.UnzipMirrorCommand, unzip_mirror,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-zip_mirror_handler = CommandHandler(BotCommands.ZipMirrorCommand, zip_mirror,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-qb_mirror_handler = CommandHandler(BotCommands.QbMirrorCommand, qb_mirror,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-qb_unzip_mirror_handler = CommandHandler(BotCommands.QbUnzipMirrorCommand, qb_unzip_mirror,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-qb_zip_mirror_handler = CommandHandler(BotCommands.QbZipMirrorCommand, qb_zip_mirror,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-leech_handler = CommandHandler(BotCommands.LeechCommand, leech,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-unzip_leech_handler = CommandHandler(BotCommands.UnzipLeechCommand, unzip_leech,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-zip_leech_handler = CommandHandler(BotCommands.ZipLeechCommand, zip_leech,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-qb_leech_handler = CommandHandler(BotCommands.QbLeechCommand, qb_leech,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-qb_unzip_leech_handler = CommandHandler(BotCommands.QbUnzipLeechCommand, qb_unzip_leech,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-qb_zip_leech_handler = CommandHandler(BotCommands.QbZipLeechCommand, qb_zip_leech,
- filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
-
-dispatcher.add_handler(mirror_handler)
-dispatcher.add_handler(unzip_mirror_handler)
-dispatcher.add_handler(zip_mirror_handler)
-dispatcher.add_handler(qb_mirror_handler)
-dispatcher.add_handler(qb_unzip_mirror_handler)
-dispatcher.add_handler(qb_zip_mirror_handler)
-dispatcher.add_handler(leech_handler)
-dispatcher.add_handler(unzip_leech_handler)
-dispatcher.add_handler(zip_leech_handler)
-dispatcher.add_handler(qb_leech_handler)
-dispatcher.add_handler(qb_unzip_leech_handler)
-dispatcher.add_handler(qb_zip_leech_handler)
diff --git a/bot/modules/mirror_leech.py b/bot/modules/mirror_leech.py
new file mode 100644
index 00000000..609490e6
--- /dev/null
+++ b/bot/modules/mirror_leech.py
@@ -0,0 +1,292 @@
+from base64 import b64encode
+from re import match as re_match, split as re_split
+from time import sleep
+from os import path as ospath
+from threading import Thread
+from telegram.ext import CommandHandler
+
+from bot import dispatcher, DOWNLOAD_DIR, LOGGER
+from bot.helper.ext_utils.bot_utils import is_url, is_magnet, is_mega_link, is_gdrive_link, get_content_type
+from bot.helper.ext_utils.exceptions import DirectDownloadLinkException
+from bot.helper.mirror_utils.download_utils.aria2_download import add_aria2c_download
+from bot.helper.mirror_utils.download_utils.gd_downloader import add_gd_download
+from bot.helper.mirror_utils.download_utils.qbit_downloader import QbDownloader
+from bot.helper.mirror_utils.download_utils.mega_downloader import add_mega_download
+from bot.helper.mirror_utils.download_utils.direct_link_generator import direct_link_generator
+from bot.helper.mirror_utils.download_utils.telegram_downloader import TelegramDownloadHelper
+from bot.helper.telegram_helper.bot_commands import BotCommands
+from bot.helper.telegram_helper.filters import CustomFilters
+from bot.helper.telegram_helper.message_utils import sendMessage
+from .listener import MirrorLeechListener
+
+
+def _mirror_leech(bot, message, isZip=False, extract=False, isQbit=False, isLeech=False, multi=0):
+ mesg = message.text.split('\n')
+ message_args = mesg[0].split(maxsplit=1)
+ name_args = mesg[0].split('|', maxsplit=1)
+ index = 1
+ ratio = None
+ seed_time = None
+ select = False
+ seed = False
+
+ if len(message_args) > 1:
+ args = mesg[0].split(maxsplit=3)
+ for x in args:
+ x = x.strip()
+ if x == 's':
+ select = True
+ index += 1
+ elif x == 'd':
+ seed = True
+ index += 1
+ elif x.startswith('d:'):
+ seed = True
+ index += 1
+ dargs = x.split(':')
+ ratio = dargs[1] if dargs[1] else None
+ if len(dargs) == 3:
+ seed_time = dargs[2] if dargs[2] else None
+ message_args = mesg[0].split(maxsplit=index)
+ if len(message_args) > index:
+ link = message_args[index].strip()
+ if link.isdigit():
+ if multi == 0:
+ multi = int(link)
+ link = ''
+ elif link.startswith(("|", "pswd:")):
+ link = ''
+ else:
+ link = ''
+ else:
+ link = ''
+
+ if len(name_args) > 1:
+ name = name_args[1]
+ name = name.split(' pswd:')[0]
+ name = name.strip()
+ else:
+ name = ''
+
+ link = re_split(r"pswd:|\|", link)[0]
+ link = link.strip()
+
+ pswd_arg = mesg[0].split(' pswd: ')
+ if len(pswd_arg) > 1:
+ pswd = pswd_arg[1]
+ else:
+ pswd = None
+
+ if message.from_user.username:
+ tag = f"@{message.from_user.username}"
+ else:
+ tag = message.from_user.mention_html(message.from_user.first_name)
+
+ reply_to = message.reply_to_message
+ if reply_to is not None:
+ file_ = next((i for i in [reply_to.document, reply_to.video, reply_to.audio, reply_to.photo] if i), None)
+ if not reply_to.from_user.is_bot:
+ if reply_to.from_user.username:
+ tag = f"@{reply_to.from_user.username}"
+ else:
+ tag = reply_to.from_user.mention_html(reply_to.from_user.first_name)
+ if len(link) == 0 or not is_url(link) and not is_magnet(link):
+ if file_ is None:
+ reply_text = reply_to.text.split(maxsplit=1)[0].strip()
+ if is_url(reply_text) or is_magnet(reply_text):
+ link = reply_to.text.strip()
+ elif isinstance(file_, list):
+ link = file_[-1].get_file().file_path
+ elif not isQbit and file_.mime_type != "application/x-bittorrent":
+ listener = MirrorLeechListener(bot, message, isZip, extract, isQbit, isLeech, pswd, tag)
+ Thread(target=TelegramDownloadHelper(listener).add_download, args=(message, f'{DOWNLOAD_DIR}{listener.uid}/', name)).start()
+ if multi > 1:
+ sleep(4)
+ nextmsg = type('nextmsg', (object, ), {'chat_id': message.chat_id, 'message_id': message.reply_to_message.message_id + 1})
+ nextmsg = sendMessage(message.text, bot, nextmsg)
+ nextmsg.from_user.id = message.from_user.id
+ multi -= 1
+ sleep(4)
+ Thread(target=_mirror_leech, args=(bot, nextmsg, isZip, extract, isQbit, isLeech, multi)).start()
+ return
+ else:
+ link = file_.get_file().file_path
+
+ if not is_url(link) and not is_magnet(link) and not ospath.exists(link):
+ help_msg = "Send link along with command line:"
+ if isQbit:
+ help_msg += "\n\nBittorrent selection:"
+ help_msg += "\n/cmd
s {link} or by replying to {file/link}"
+ help_msg += "\n\nQbittorrent seed:"
+ help_msg += "\n/qbcmd
d {link} or by replying to {file/link}.\n"
+ help_msg += "To specify ratio and seed time. Ex: d:0.7:10 (ratio and time) or d:0.7 "
+ help_msg += "(only ratio) or d::10 (only time) where time in minutes"
+ help_msg += "\n\nMulti links only by replying to first link/file:"
+ help_msg += "\n/command
10(number of links/files)"
+ else:
+ help_msg += "\n/cmd
{link} |newname pswd: xx [zip/unzip]"
+ help_msg += "\n\nBy replying to link/file:"
+ help_msg += "\n/cmd
|newname pswd: xx [zip/unzip]"
+ help_msg += "\n\nDirect link authorization:"
+ help_msg += "\n/cmd
{link} |newname pswd: xx\nusername\npassword"
+ help_msg += "\n\nBittorrent selection:"
+ help_msg += "\n/cmd
s {link} or by replying to {file/link}"
+ help_msg += "\n\nBittorrent seed:"
+ help_msg += "\n/qbcmd
d {link} or by replying to {file/link}.\n"
+ help_msg += "To specify ratio and seed time. Ex: d:0.7:10 (ratio and time) or d:0.7 "
+ help_msg += "(only ratio) or d::10 (only time) where time in minutes"
+ help_msg += "\n\nMulti links only by replying to first link/file:"
+ help_msg += "\n/command
10(number of links/files)"
+ return sendMessage(help_msg, bot, message)
+
+ LOGGER.info(link)
+
+ if not is_mega_link(link) and not isQbit and not is_magnet(link) \
+ and not is_gdrive_link(link) and not link.endswith('.torrent'):
+ content_type = get_content_type(link)
+ if content_type is None or re_match(r'text/html|text/plain', content_type):
+ try:
+ link = direct_link_generator(link)
+ LOGGER.info(f"Generated link: {link}")
+ except DirectDownloadLinkException as e:
+ LOGGER.info(str(e))
+ if str(e).startswith('ERROR:'):
+ return sendMessage(str(e), bot, message)
+ elif isQbit and not is_magnet(link):
+ if link.endswith('.torrent') or "https://api.telegram.org/file/" in link:
+ content_type = None
+ else:
+ content_type = get_content_type(link)
+ if content_type is None or re_match(r'application/x-bittorrent|application/octet-stream', content_type):
+ try:
+ resp = rget(link, timeout=10, headers = {'user-agent': 'Wget/1.12'})
+ if resp.status_code == 200:
+ file_name = str(time()).replace(".", "") + ".torrent"
+ with open(file_name, "wb") as t:
+ t.write(resp.content)
+ link = str(file_name)
+ else:
+ return sendMessage(f"{tag} ERROR: link got HTTP response: {resp.status_code}", bot, message)
+ except Exception as e:
+ error = str(e).replace('<', ' ').replace('>', ' ')
+ if error.startswith('No connection adapters were found for'):
+ link = error.split("'")[1]
+ else:
+ LOGGER.error(str(e))
+ return sendMessage(tag + " " + error, bot, message)
+ else:
+ msg = "Qb commands for torrents only. if you are trying to dowload torrent then report."
+ return sendMessage(msg, bot, message)
+
+ listener = MirrorLeechListener(bot, message, isZip, extract, isQbit, isLeech, pswd, tag, select, seed)
+
+ if is_gdrive_link(link):
+ if not isZip and not extract and not isLeech:
+ gmsg = f"Use /{BotCommands.CloneCommand} to clone Google Drive file/folder\n\n"
+ gmsg += f"Use /{BotCommands.ZipMirrorCommand[0]} to make zip of Google Drive folder\n\n"
+ gmsg += f"Use /{BotCommands.UnzipMirrorCommand[0]} to extracts Google Drive archive folder/file"
+ sendMessage(gmsg, bot, message)
+ else:
+ Thread(target=add_gd_download, args=(link, f'{DOWNLOAD_DIR}{listener.uid}', listener, name)).start()
+ elif is_mega_link(link):
+ Thread(target=add_mega_download, args=(link, f'{DOWNLOAD_DIR}{listener.uid}/', listener, name)).start()
+ elif isQbit and (is_magnet(link) or ospath.exists(link)):
+ Thread(target=QbDownloader(listener).add_qb_torrent, args=(link, f'{DOWNLOAD_DIR}{listener.uid}',
+ select, ratio, seed_time)).start()
+ else:
+ if len(mesg) > 1:
+ ussr = mesg[1]
+ if len(mesg) > 2:
+ pssw = mesg[2]
+ else:
+ pssw = ''
+ auth = f"{ussr}:{pssw}"
+ auth = "Basic " + b64encode(auth.encode()).decode('ascii')
+ else:
+ auth = ''
+ Thread(target=add_aria2c_download, args=(link, f'{DOWNLOAD_DIR}{listener.uid}', listener, name,
+ auth, select, ratio, seed_time)).start()
+
+ if multi > 1:
+ sleep(4)
+ nextmsg = type('nextmsg', (object, ), {'chat_id': message.chat_id, 'message_id': message.reply_to_message.message_id + 1})
+ nextmsg = sendMessage(message.text, bot, nextmsg)
+ nextmsg.from_user.id = message.from_user.id
+ multi -= 1
+ sleep(4)
+ Thread(target=_mirror_leech, args=(bot, nextmsg, isZip, extract, isQbit, isLeech, multi)).start()
+
+
+def mirror(update, context):
+ _mirror_leech(context.bot, update.message)
+
+def unzip_mirror(update, context):
+ _mirror_leech(context.bot, update.message, extract=True)
+
+def zip_mirror(update, context):
+ _mirror_leech(context.bot, update.message, True)
+
+def qb_mirror(update, context):
+ _mirror_leech(context.bot, update.message, isQbit=True)
+
+def qb_unzip_mirror(update, context):
+ _mirror_leech(context.bot, update.message, extract=True, isQbit=True)
+
+def qb_zip_mirror(update, context):
+ _mirror_leech(context.bot, update.message, True, isQbit=True)
+
+def leech(update, context):
+ _mirror_leech(context.bot, update.message, isLeech=True)
+
+def unzip_leech(update, context):
+ _mirror_leech(context.bot, update.message, extract=True, isLeech=True)
+
+def zip_leech(update, context):
+ _mirror_leech(context.bot, update.message, True, isLeech=True)
+
+def qb_leech(update, context):
+ _mirror_leech(context.bot, update.message, isQbit=True, isLeech=True)
+
+def qb_unzip_leech(update, context):
+ _mirror_leech(context.bot, update.message, extract=True, isQbit=True, isLeech=True)
+
+def qb_zip_leech(update, context):
+ _mirror_leech(context.bot, update.message, True, isQbit=True, isLeech=True)
+
+mirror_handler = CommandHandler(BotCommands.MirrorCommand, mirror,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+unzip_mirror_handler = CommandHandler(BotCommands.UnzipMirrorCommand, unzip_mirror,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+zip_mirror_handler = CommandHandler(BotCommands.ZipMirrorCommand, zip_mirror,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+qb_mirror_handler = CommandHandler(BotCommands.QbMirrorCommand, qb_mirror,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+qb_unzip_mirror_handler = CommandHandler(BotCommands.QbUnzipMirrorCommand, qb_unzip_mirror,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+qb_zip_mirror_handler = CommandHandler(BotCommands.QbZipMirrorCommand, qb_zip_mirror,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+leech_handler = CommandHandler(BotCommands.LeechCommand, leech,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+unzip_leech_handler = CommandHandler(BotCommands.UnzipLeechCommand, unzip_leech,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+zip_leech_handler = CommandHandler(BotCommands.ZipLeechCommand, zip_leech,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+qb_leech_handler = CommandHandler(BotCommands.QbLeechCommand, qb_leech,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+qb_unzip_leech_handler = CommandHandler(BotCommands.QbUnzipLeechCommand, qb_unzip_leech,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+qb_zip_leech_handler = CommandHandler(BotCommands.QbZipLeechCommand, qb_zip_leech,
+ filters=CustomFilters.authorized_chat | CustomFilters.authorized_user, run_async=True)
+
+dispatcher.add_handler(mirror_handler)
+dispatcher.add_handler(unzip_mirror_handler)
+dispatcher.add_handler(zip_mirror_handler)
+dispatcher.add_handler(qb_mirror_handler)
+dispatcher.add_handler(qb_unzip_mirror_handler)
+dispatcher.add_handler(qb_zip_mirror_handler)
+dispatcher.add_handler(leech_handler)
+dispatcher.add_handler(unzip_leech_handler)
+dispatcher.add_handler(zip_leech_handler)
+dispatcher.add_handler(qb_leech_handler)
+dispatcher.add_handler(qb_unzip_leech_handler)
+dispatcher.add_handler(qb_zip_leech_handler)
diff --git a/bot/modules/search.py b/bot/modules/search.py
index 325ca6cf..159f92e5 100644
--- a/bot/modules/search.py
+++ b/bot/modules/search.py
@@ -1,18 +1,19 @@
from requests import get as rget
-from time import sleep
+from time import time
from threading import Thread
from html import escape
from urllib.parse import quote
from telegram import InlineKeyboardMarkup
from telegram.ext import CommandHandler, CallbackQueryHandler
+from os import remove
from bot import dispatcher, LOGGER, SEARCH_API_LINK, SEARCH_PLUGINS, get_client, SEARCH_LIMIT
-from bot.helper.ext_utils.telegraph_helper import telegraph
-from bot.helper.telegram_helper.message_utils import editMessage, sendMessage, sendMarkup
+from bot.helper.telegram_helper.message_utils import editMessage, sendMessage, sendMarkup, deleteMessage, sendFile
from bot.helper.telegram_helper.filters import CustomFilters
from bot.helper.telegram_helper.bot_commands import BotCommands
from bot.helper.ext_utils.bot_utils import get_readable_file_size
from bot.helper.telegram_helper import button_build
+from bot.helper.ext_utils.html_helper import html_template
if SEARCH_PLUGINS is not None:
PLUGINS = []
@@ -44,8 +45,6 @@ SITES = {
"all": "All"
}
-TELEGRAPH_LIMIT = 300
-
def torser(update, context):
user_id = update.message.from_user.id
@@ -109,12 +108,12 @@ def torserbut(update, context):
editMessage(f"Searching for {key}\nTorrent Site:- {SITES.get(site)}", message)
else:
editMessage(f"Searching for {key}\nTorrent Site:- {site.capitalize()}", message)
- Thread(target=_search, args=(key, site, message, method)).start()
+ Thread(target=_search, args=(context.bot, key, site, message, method)).start()
else:
query.answer()
editMessage("Search has been canceled!", message)
-def _search(key, site, message, method):
+def _search(bot, key, site, message, method):
if method.startswith('api'):
if method == 'apisearch':
LOGGER.info(f"API Searching: {key} from {site}")
@@ -139,20 +138,20 @@ def _search(key, site, message, method):
search_results = resp.json()
if "error" in search_results.keys():
return editMessage(f"No result found for {key}\nTorrent Site:- {SITES.get(site)}", message)
- msg = f"Found {min(search_results['total'], TELEGRAPH_LIMIT)}"
+ cap = f"Found {search_results['total']}"
if method == 'apitrend':
- msg += f" trending result(s)\nTorrent Site:- {SITES.get(site)}"
+ cap += f" trending results\nTorrent Site:- {SITES.get(site)}"
elif method == 'apirecent':
- msg += f" recent result(s)\nTorrent Site:- {SITES.get(site)}"
+ cap += f" recent results\nTorrent Site:- {SITES.get(site)}"
else:
- msg += f" result(s) for {key}\nTorrent Site:- {SITES.get(site)}"
+ cap += f" results for {key}\nTorrent Site:- {SITES.get(site)}"
search_results = search_results['data']
except Exception as e:
return editMessage(str(e), message)
else:
LOGGER.info(f"PLUGINS Searching: {key} from {site}")
client = get_client()
- search = client.search_start(pattern=str(key), plugins=str(site), category='all')
+ search = client.search_start(pattern=key, plugins=site, category='all')
search_id = search.id
while True:
result_status = client.search_status(search_id=search_id)
@@ -164,78 +163,69 @@ def _search(key, site, message, method):
total_results = dict_search_results.total
if total_results == 0:
return editMessage(f"No result found for {key}\nTorrent Site:- {site.capitalize()}", message)
- msg = f"Found {min(total_results, TELEGRAPH_LIMIT)}"
- msg += f" result(s) for {key}\nTorrent Site:- {site.capitalize()}"
- link = _getResult(search_results, key, message, method)
- buttons = button_build.ButtonMaker()
- buttons.buildbutton("🔎 VIEW", link)
- button = InlineKeyboardMarkup(buttons.build_menu(1))
- editMessage(msg, message, button)
+ cap = f"Found {total_results}"
+ cap += f" results for {key}\nTorrent Site:- {site.capitalize()}"
+ hmsg = _getResult(search_results, key, message, method)
+ name = f"{method}_{key}_{site}_{time()}.html"
+ with open(name, "w", encoding='utf-8') as f:
+ f.write(html_template.replace('{msg}', hmsg).replace('{title}', f'{method}_{key}_{site}'))
+ deleteMessage(bot, message)
+ sendFile(bot, message.reply_to_message, name, cap)
+ remove(name)
if not method.startswith('api'):
client.search_delete(search_id=search_id)
def _getResult(search_results, key, message, method):
- telegraph_content = []
if method == 'apirecent':
- msg = "{escape(result['name'])}