Added Qbittorrent
use /mirror qb to mirror with qbitorrent and use /mirror qbs to select files before downloading Signed-off-by: anas <e.anastayyar@gmail.com>
This commit is contained in:
parent
82cb9b2212
commit
0bfba523f0
|
|
@ -1,8 +1,10 @@
|
|||
FROM breakdowns/mega-sdk-python:latest
|
||||
FROM anasty17/megasdk:latest
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
RUN chmod 777 /usr/src/app
|
||||
|
||||
RUN apt-get install -y xz-utils neofetch unzip && apt-get autoremove -y
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip3 install --no-cache-dir -r requirements.txt
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
import time
|
||||
import requests
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv('config.env')
|
||||
|
||||
url = os.environ.get("BASE_URL_OF_BOT")
|
||||
while True:
|
||||
time.sleep(1000)
|
||||
status = requests.get(url).status_code
|
||||
21
aria.sh
21
aria.sh
|
|
@ -1,15 +1,10 @@
|
|||
export MAX_DOWNLOAD_SPEED=0
|
||||
tracker_list=$(curl -Ns https://raw.githubusercontent.com/XIU2/TrackersListCollection/master/all.txt https://ngosang.github.io/trackerslist/trackers_all_http.txt https://raw.githubusercontent.com/DeSireFire/animeTrackerList/master/AT_all.txt https://raw.githubusercontent.com/hezhijie0327/Trackerslist/main/trackerslist_combine.txt | awk '$0' | tr '\n' ',')
|
||||
export MAX_CONCURRENT_DOWNLOADS=7
|
||||
|
||||
aria2c --enable-rpc --rpc-listen-all=false --check-certificate=false \
|
||||
aria2c --enable-rpc --check-certificate=false \
|
||||
--max-connection-per-server=10 --rpc-max-request-size=1024M \
|
||||
--bt-tracker="[$tracker_list]" --bt-max-peers=0 --bt-tracker-connect-timeout=300 --bt-stop-timeout=1200 --min-split-size=10M \
|
||||
--follow-torrent=mem --split=10 \
|
||||
--daemon=true --allow-overwrite=true --max-overall-download-limit=$MAX_DOWNLOAD_SPEED \
|
||||
--max-overall-upload-limit=1K --max-concurrent-downloads=$MAX_CONCURRENT_DOWNLOADS \
|
||||
--bt-stop-timeout=1200 --min-split-size=10M --follow-torrent=mem --split=10 \
|
||||
--daemon=true --allow-overwrite=true --max-overall-download-limit=0 \
|
||||
--max-overall-upload-limit=1K --max-concurrent-downloads=15 --continue=true \
|
||||
--peer-id-prefix=-qB4360- --user-agent=qBittorrent/4.3.6 --peer-agent=qBittorrent/4.3.6 \
|
||||
--disk-cache=64M --file-allocation=prealloc --continue=true \
|
||||
--max-file-not-found=0 --max-tries=20 --auto-file-renaming=true \
|
||||
--bt-enable-lpd=true --seed-time=0.01 --seed-ratio=1.0 \
|
||||
--content-disposition-default-utf8=true --http-accept-gzip=true --reuse-uri=true --netrc-path=/usr/src/app/.netrc
|
||||
--disk-cache=64M --bt-enable-lpd=true --seed-time=0 --max-file-not-found=0 \
|
||||
--max-tries=20 --auto-file-renaming=true --reuse-uri=true --http-accept-gzip=true \
|
||||
--content-disposition-default-utf8=true --netrc-path=/usr/src/app/.netrc
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import random
|
|||
import string
|
||||
|
||||
import aria2p
|
||||
import qbittorrentapi as qba
|
||||
import telegram.ext as tg
|
||||
from dotenv import load_dotenv
|
||||
from pyrogram import Client
|
||||
|
|
@ -66,6 +67,18 @@ aria2 = aria2p.API(
|
|||
)
|
||||
)
|
||||
|
||||
|
||||
def get_client() -> qba.TorrentsAPIMixIn:
|
||||
qb_client = qba.Client(host="localhost", port=8090, username="admin", password="adminadmin")
|
||||
try:
|
||||
qb_client.auth_log_in()
|
||||
qb_client.application.set_preferences({"disk_cache":64, "incomplete_files_ext":True, "max_connec":3000, "max_connec_per_torrent":300, "async_io_thread":32})
|
||||
return qb_client
|
||||
except qba.LoginFailed as e:
|
||||
LOGGER.error(str(e))
|
||||
return None
|
||||
|
||||
|
||||
DOWNLOAD_DIR = None
|
||||
BOT_TOKEN = None
|
||||
|
||||
|
|
@ -313,6 +326,31 @@ try:
|
|||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
BASE_URL = getConfig('BASE_URL_OF_BOT')
|
||||
if len(BASE_URL) == 0:
|
||||
BASE_URL = None
|
||||
except KeyError:
|
||||
logging.warning('BASE_URL_OF_BOT not provided!')
|
||||
BASE_URL = None
|
||||
|
||||
try:
|
||||
IS_VPS = getConfig('IS_VPS')
|
||||
if IS_VPS.lower() == 'true':
|
||||
IS_VPS = True
|
||||
else:
|
||||
IS_VPS = False
|
||||
except KeyError:
|
||||
IS_VPS = False
|
||||
|
||||
try:
|
||||
SERVER_PORT = getConfig('SERVER_PORT')
|
||||
if len(SERVER_PORT) == 0:
|
||||
SERVER_PORT = None
|
||||
except KeyError:
|
||||
logging.warning('SERVER_PORT not provided!')
|
||||
SERVER_PORT = None
|
||||
|
||||
updater = tg.Updater(token=BOT_TOKEN)
|
||||
bot = updater.bot
|
||||
dispatcher = updater.dispatcher
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import shutil, psutil
|
||||
import signal
|
||||
import os
|
||||
import asyncio
|
||||
|
||||
from pyrogram import idle
|
||||
from bot import app
|
||||
|
|
@ -8,7 +9,8 @@ from sys import executable
|
|||
|
||||
from telegram import ParseMode
|
||||
from telegram.ext import CommandHandler
|
||||
from bot import bot, dispatcher, updater, botStartTime, IGNORE_PENDING_REQUESTS
|
||||
from wserver import start_server_async
|
||||
from bot import bot, dispatcher, updater, botStartTime, IGNORE_PENDING_REQUESTS, IS_VPS, SERVER_PORT
|
||||
from bot.helper.ext_utils import fs_utils
|
||||
from bot.helper.telegram_helper.bot_commands import BotCommands
|
||||
from bot.helper.telegram_helper.message_utils import *
|
||||
|
|
@ -201,6 +203,10 @@ botcmds = [
|
|||
|
||||
def main():
|
||||
fs_utils.start_cleanup()
|
||||
|
||||
if IS_VPS:
|
||||
asyncio.get_event_loop().run_until_complete(start_server_async(SERVER_PORT))
|
||||
|
||||
# Check if the bot is restarting
|
||||
if os.path.isfile(".restartmsg"):
|
||||
with open(".restartmsg") as f:
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class MirrorStatus:
|
|||
STATUS_CLONING = "Cloning...♻️"
|
||||
STATUS_WAITING = "Queued...📝"
|
||||
STATUS_FAILED = "Failed 🚫. Cleaning Download..."
|
||||
STATUS_PAUSE = "Paused...⭕️"
|
||||
STATUS_ARCHIVING = "Archiving...🔐"
|
||||
STATUS_EXTRACTING = "Extracting...📂"
|
||||
|
||||
|
|
@ -76,6 +77,7 @@ def getDownloadByGid(gid):
|
|||
return dl
|
||||
return None
|
||||
|
||||
|
||||
def getAllDownload():
|
||||
with download_dict_lock:
|
||||
for dlDetails in list(download_dict.values()):
|
||||
|
|
@ -84,6 +86,7 @@ def getAllDownload():
|
|||
return dlDetails
|
||||
return None
|
||||
|
||||
|
||||
def get_progress_bar_string(status):
|
||||
completed = status.processed_bytes() / 8
|
||||
total = status.size_raw() / 8
|
||||
|
|
@ -134,6 +137,11 @@ def get_readable_message():
|
|||
f" | <b>Peers:</b> {download.aria_download().connections}"
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
msg += f"\n<b>Seeders:</b> {download.torrent_info().num_seeds}" \
|
||||
f" | <b>Leechers:</b> {download.torrent_info().num_leechs}"
|
||||
except:
|
||||
pass
|
||||
msg += f"\n<b>To Stop:</b> <code>/{BotCommands.CancelMirror} {download.gid()}</code>"
|
||||
msg += "\n\n"
|
||||
if STATUS_LIMIT is not None:
|
||||
|
|
@ -151,6 +159,7 @@ def get_readable_message():
|
|||
return msg, button
|
||||
return msg, ""
|
||||
|
||||
|
||||
def flip(update, context):
|
||||
query = update.callback_query
|
||||
query.answer()
|
||||
|
|
@ -171,6 +180,7 @@ def flip(update, context):
|
|||
PAGE_NO -= 1
|
||||
message_utils.update_all_messages()
|
||||
|
||||
|
||||
def get_readable_time(seconds: int) -> str:
|
||||
result = ''
|
||||
(days, remainder) = divmod(seconds, 86400)
|
||||
|
|
@ -196,12 +206,15 @@ def is_url(url: str):
|
|||
return True
|
||||
return False
|
||||
|
||||
|
||||
def is_gdrive_link(url: str):
|
||||
return "drive.google.com" in url
|
||||
|
||||
|
||||
def is_mega_link(url: str):
|
||||
return "mega.nz" in url or "mega.co.nz" in url
|
||||
|
||||
|
||||
def get_mega_link_type(url: str):
|
||||
if "folder" in url:
|
||||
return "folder"
|
||||
|
|
@ -211,12 +224,14 @@ def get_mega_link_type(url: str):
|
|||
return "folder"
|
||||
return "file"
|
||||
|
||||
|
||||
def is_magnet(url: str):
|
||||
magnet = re.findall(MAGNET_REGEX, url)
|
||||
if magnet:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def new_thread(fn):
|
||||
"""To use as decorator to make a function call threaded.
|
||||
Needs import
|
||||
|
|
@ -229,6 +244,7 @@ def new_thread(fn):
|
|||
|
||||
return wrapper
|
||||
|
||||
|
||||
next_handler = CallbackQueryHandler(flip, pattern="nex", run_async=True)
|
||||
previous_handler = CallbackQueryHandler(flip, pattern="pre", run_async=True)
|
||||
dispatcher.add_handler(next_handler)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import sys
|
||||
from bot import aria2, LOGGER, DOWNLOAD_DIR
|
||||
from bot import aria2, LOGGER, DOWNLOAD_DIR, get_client
|
||||
import shutil
|
||||
import os
|
||||
import pathlib
|
||||
|
|
@ -23,6 +23,7 @@ def start_cleanup():
|
|||
|
||||
def clean_all():
|
||||
aria2.remove_all(True)
|
||||
get_client().torrents_delete(torrent_hashes="all", delete_files=True)
|
||||
try:
|
||||
shutil.rmtree(DOWNLOAD_DIR)
|
||||
except FileNotFoundError:
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ class MegaDownloadHelper:
|
|||
if smsg:
|
||||
msg1 = "File/Folder is already available in Drive.\nHere are the search results:"
|
||||
sendMarkup(msg1, listener.bot, listener.update, button)
|
||||
executor.continue_event.set()
|
||||
return
|
||||
if MEGA_LIMIT is not None or TAR_UNZIP_LIMIT is not None:
|
||||
limit = None
|
||||
|
|
@ -193,10 +194,12 @@ class MegaDownloadHelper:
|
|||
if 'G' in limit[1] or 'g' in limit[1]:
|
||||
if api.getSize(node) > limitint * 1024**3:
|
||||
sendMessage(msg3, listener.bot, listener.update)
|
||||
executor.continue_event.set()
|
||||
return
|
||||
elif 'T' in limit[1] or 't' in limit[1]:
|
||||
if api.getSize(node) > limitint * 1024**4:
|
||||
sendMessage(msg3, listener.bot, listener.update)
|
||||
executor.continue_event.set()
|
||||
return
|
||||
with download_dict_lock:
|
||||
download_dict[listener.uid] = MegaDownloadStatus(mega_listener, listener)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,198 @@
|
|||
import os
|
||||
import random
|
||||
import string
|
||||
import time
|
||||
import logging
|
||||
|
||||
import qbittorrentapi as qba
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
from torrentool.api import Torrent
|
||||
from telegram import InlineKeyboardMarkup
|
||||
from telegram.ext import CallbackQueryHandler
|
||||
|
||||
from bot import download_dict, download_dict_lock, BASE_URL, dispatcher, get_client
|
||||
from bot.helper.mirror_utils.status_utils.qbit_download_status import QbDownloadStatus
|
||||
from bot.helper.telegram_helper.message_utils import *
|
||||
from bot.helper.ext_utils.bot_utils import setInterval, new_thread, MirrorStatus
|
||||
from bot.helper.telegram_helper import button_build
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class qbittorrent:
|
||||
|
||||
|
||||
def __init__(self):
|
||||
self.update_interval = 1.5
|
||||
self.meta_time = time.time()
|
||||
|
||||
@new_thread
|
||||
def add_torrent(self, link, dire, listener, qbitsel):
|
||||
self.client = get_client()
|
||||
self.listener = listener
|
||||
is_file = False
|
||||
count = 0
|
||||
pincode = ""
|
||||
markup = None
|
||||
try:
|
||||
if os.path.exists(link):
|
||||
is_file = True
|
||||
self.ext_hash = get_hash_file(link)
|
||||
else:
|
||||
self.ext_hash = get_hash_magnet(link)
|
||||
tor_info = self.client.torrents_info(torrent_hashes=self.ext_hash)
|
||||
if len(tor_info) > 0:
|
||||
sendMessage("This torrent is already in list.", listener.bot, listener.update)
|
||||
return
|
||||
if is_file:
|
||||
op = self.client.torrents_add(torrent_files=[link], save_path=dire)
|
||||
os.remove(link)
|
||||
else:
|
||||
op = self.client.torrents_add(link, save_path=dire)
|
||||
if op.lower() == "ok.":
|
||||
LOGGER.info(f"QbitDownload started: {self.ext_hash}")
|
||||
tor_info = self.client.torrents_info(torrent_hashes=self.ext_hash)
|
||||
if len(tor_info) == 0:
|
||||
while True:
|
||||
if time.time() - self.meta_time >= 300:
|
||||
sendMessage("The torrent was not added. report when u see this error", listener.bot, listener.update)
|
||||
return False
|
||||
tor_info = self.client.torrents_info(torrent_hashes=self.ext_hash)
|
||||
if len(tor_info) > 0:
|
||||
break
|
||||
else:
|
||||
sendMessage("This is an unsupported/invalid link.", listener.bot, listener.update)
|
||||
return
|
||||
gid = ''.join(random.SystemRandom().choices(string.ascii_letters + string.digits, k=14))
|
||||
self.updater = setInterval(self.update_interval, self.update)
|
||||
tor_info = tor_info[0]
|
||||
if BASE_URL is not None and qbitsel:
|
||||
if not is_file and (tor_info.state == "checkingResumeData" or tor_info.state == "metaDL"):
|
||||
meta = sendMessage("Downloading Metadata...Please wait then you can select files or mirror torrent file if it have low seeders", listener.bot, listener.update)
|
||||
while True:
|
||||
tor_info = self.client.torrents_info(torrent_hashes=self.ext_hash)
|
||||
if len(tor_info) == 0:
|
||||
deleteMessage(listener.bot, meta)
|
||||
return False
|
||||
tor_info = tor_info[0]
|
||||
if tor_info.state == "metaDL" or tor_info.state == "checkingResumeData":
|
||||
time.sleep(1)
|
||||
else:
|
||||
break
|
||||
deleteMessage(listener.bot, meta)
|
||||
for n in str(self.ext_hash):
|
||||
if n.isdigit():
|
||||
pincode += str(n)
|
||||
count += 1
|
||||
if count == 4:
|
||||
break
|
||||
URL = f"{BASE_URL}/slam/files/{self.ext_hash}"
|
||||
pindata = f"pin {gid} {pincode}"
|
||||
donedata = f"done {gid} {self.ext_hash}"
|
||||
buttons = button_build.ButtonMaker()
|
||||
buttons.buildbutton("Select Files", URL)
|
||||
buttons.sbutton("Pincode", pindata)
|
||||
buttons.sbutton("Done Selecting", donedata)
|
||||
QBBUTTONS = InlineKeyboardMarkup(buttons.build_menu(2))
|
||||
msg = "Your download paused. Choose files then press Done Selecting button to start downloading."
|
||||
markup = sendMarkup(msg, listener.bot, listener.update, QBBUTTONS)
|
||||
self.client.torrents_pause(torrent_hashes=self.ext_hash)
|
||||
with download_dict_lock:
|
||||
download_dict[listener.uid] = QbDownloadStatus(gid, listener, self.ext_hash, self.client, markup)
|
||||
else:
|
||||
with download_dict_lock:
|
||||
download_dict[listener.uid] = QbDownloadStatus(gid, listener, self.ext_hash, self.client ,markup)
|
||||
sendStatusMessage(listener.update, listener.bot)
|
||||
except qba.UnsupportedMediaType415Error as e:
|
||||
LOGGER.error(str(e))
|
||||
sendMessage("This is an unsupported/invalid link. {str(e)}", listener.bot, listener.update)
|
||||
except Exception as e:
|
||||
LOGGER.error(str(e))
|
||||
sendMessage(str(e), listener.bot, listener.update)
|
||||
self.client.torrents_delete(torrent_hashes=self.ext_hash)
|
||||
|
||||
|
||||
def update(self):
|
||||
tor_info = self.client.torrents_info(torrent_hashes=self.ext_hash)
|
||||
if len(tor_info) == 0:
|
||||
self.updater.cancel()
|
||||
return
|
||||
else:
|
||||
tor_info = tor_info[0]
|
||||
if tor_info.state == "metaDL":
|
||||
if time.time() - self.meta_time > 600:
|
||||
self.client.torrents_delete(torrent_hashes=self.ext_hash)
|
||||
self.listener.onDownloadError("Dead Torrent!")
|
||||
self.updater.cancel()
|
||||
return
|
||||
elif tor_info.state == "error":
|
||||
self.client.torrents_delete(torrent_hashes=self.ext_hash)
|
||||
self.listener.onDownloadError("Error. IDK why, report in support group")
|
||||
self.updater.cancel()
|
||||
return
|
||||
elif tor_info.state == "uploading" or tor_info.state.lower().endswith("up"):
|
||||
self.client.torrents_pause(torrent_hashes=self.ext_hash)
|
||||
self.listener.onDownloadComplete()
|
||||
self.client.torrents_delete(torrent_hashes=self.ext_hash, delete_files=True)
|
||||
self.updater.cancel()
|
||||
|
||||
|
||||
def get_confirm(update, context):
|
||||
query = update.callback_query
|
||||
user_id = query.from_user.id
|
||||
data = query.data
|
||||
data = data.split(" ")
|
||||
qdl = None
|
||||
with download_dict_lock:
|
||||
for dl in download_dict.values():
|
||||
if dl.status() == MirrorStatus.STATUS_PAUSE:
|
||||
if dl.gid() == data[1]:
|
||||
qdl = dl
|
||||
break
|
||||
if qdl is not None:
|
||||
if user_id != qdl.listen().message.from_user.id:
|
||||
query.answer(text="Don't waste your time!", show_alert=True)
|
||||
return
|
||||
if data[0] == "pin":
|
||||
query.answer(text=data[2], show_alert=True)
|
||||
elif data[0] == "done":
|
||||
query.answer()
|
||||
qdl.qbclient().torrents_resume(torrent_hashes=data[2])
|
||||
sendStatusMessage(qdl.listen().update, qdl.listen().bot)
|
||||
deleteMessage(context.bot, qdl.mark())
|
||||
else:
|
||||
query.answer(text="This task has been cancelled!", show_alert=True)
|
||||
query.delete_message()
|
||||
|
||||
|
||||
def get_hash_magnet(mgt):
|
||||
if mgt.startswith('magnet:'):
|
||||
_, _, _, _, query, _ = urlparse(mgt)
|
||||
|
||||
qs = parse_qs(query)
|
||||
v = qs.get('xt', None)
|
||||
|
||||
if v == None or v == []:
|
||||
LOGGER.error('Invalid magnet URI: no "xt" query parameter.')
|
||||
return False
|
||||
|
||||
v = v[0]
|
||||
if not v.startswith('urn:btih:'):
|
||||
LOGGER.error('Invalid magnet URI: "xt" value not valid for BitTorrent.')
|
||||
return False
|
||||
|
||||
mgt = v[len('urn:btih:'):]
|
||||
return mgt.lower()
|
||||
|
||||
|
||||
def get_hash_file(path):
|
||||
tr = Torrent.from_file(path)
|
||||
mgt = tr.magnet_link
|
||||
return get_hash_magnet(mgt)
|
||||
|
||||
|
||||
pin_handler = CallbackQueryHandler(get_confirm, pattern="pin", run_async=True)
|
||||
done_handler = CallbackQueryHandler(get_confirm, pattern="done", run_async=True)
|
||||
dispatcher.add_handler(pin_handler)
|
||||
dispatcher.add_handler(done_handler)
|
||||
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
from bot import DOWNLOAD_DIR, LOGGER, get_client
|
||||
from bot.helper.ext_utils.bot_utils import MirrorStatus, get_readable_file_size, get_readable_time
|
||||
from .status import Status
|
||||
|
||||
|
||||
class QbDownloadStatus(Status):
|
||||
|
||||
def __init__(self, gid, listener, qbhash, client, markup):
|
||||
super().__init__()
|
||||
self.__gid = gid
|
||||
self.__hash = qbhash
|
||||
self.__client = client
|
||||
self.__markup = markup
|
||||
self.__uid = listener.uid
|
||||
self.__listener = listener
|
||||
self.message = listener.message
|
||||
self.is_extracting = False
|
||||
self.is_archiving = False
|
||||
|
||||
|
||||
def progress(self):
|
||||
"""
|
||||
Calculates the progress of the mirror (upload or download)
|
||||
:return: returns progress in percentage
|
||||
"""
|
||||
return f'{round(self.torrent_info().progress*100,2)}%'
|
||||
|
||||
def size_raw(self):
|
||||
"""
|
||||
Gets total size of the mirror file/folder
|
||||
:return: total size of mirror
|
||||
"""
|
||||
return self.torrent_info().total_size
|
||||
|
||||
def processed_bytes(self):
|
||||
return self.torrent_info().downloaded
|
||||
|
||||
def speed(self):
|
||||
return f"{get_readable_file_size(self.torrent_info().dlspeed)}/s"
|
||||
|
||||
def name(self):
|
||||
return self.torrent_info().name
|
||||
|
||||
def path(self):
|
||||
return f"{DOWNLOAD_DIR}{self.__uid}"
|
||||
|
||||
def size(self):
|
||||
return get_readable_file_size(self.torrent_info().total_size)
|
||||
|
||||
def eta(self):
|
||||
return get_readable_time(self.torrent_info().eta)
|
||||
|
||||
def status(self):
|
||||
download = self.torrent_info().state
|
||||
if download == "queuedDL":
|
||||
status = MirrorStatus.STATUS_WAITING
|
||||
elif download == "metaDL":
|
||||
status = MirrorStatus.STATUS_DOWNLOADING + " (Metadata)"
|
||||
elif download == "pausedDL":
|
||||
status = MirrorStatus.STATUS_PAUSE
|
||||
else:
|
||||
status = MirrorStatus.STATUS_DOWNLOADING
|
||||
return status
|
||||
|
||||
def torrent_info(self):
|
||||
tor_info = self.__client.torrents_info(torrent_hashes=self.__hash)
|
||||
if len(tor_info) == 0:
|
||||
return None
|
||||
else:
|
||||
return tor_info[0]
|
||||
|
||||
def download(self):
|
||||
return self
|
||||
|
||||
def uid(self):
|
||||
return self.__uid
|
||||
|
||||
def gid(self):
|
||||
return self.__gid
|
||||
|
||||
def listen(self):
|
||||
return self.__listener
|
||||
|
||||
def qbclient(self):
|
||||
return self.__client
|
||||
|
||||
def mark(self):
|
||||
return self.__markup
|
||||
|
||||
def cancel_download(self):
|
||||
LOGGER.info(f"Cancelling Download: {self.name()}")
|
||||
self.__listener.onDownloadError('Download stopped by user!')
|
||||
self.__client.torrents_delete(torrent_hashes=self.__hash)
|
||||
|
||||
|
|
@ -4,8 +4,8 @@ from telegram.update import Update
|
|||
import psutil, shutil
|
||||
import time
|
||||
from bot import AUTO_DELETE_MESSAGE_DURATION, LOGGER, bot, \
|
||||
status_reply_dict, status_reply_dict_lock, download_dict, download_dict_lock, botStartTime
|
||||
from bot.helper.ext_utils.bot_utils import get_readable_message, get_readable_file_size, get_readable_time, MirrorStatus
|
||||
status_reply_dict, status_reply_dict_lock, download_dict, download_dict_lock, botStartTime, Interval, DOWNLOAD_STATUS_UPDATE_INTERVAL
|
||||
from bot.helper.ext_utils.bot_utils import get_readable_message, get_readable_file_size, get_readable_time, MirrorStatus, setInterval
|
||||
from telegram.error import TimedOut, BadRequest
|
||||
|
||||
|
||||
|
|
@ -108,6 +108,8 @@ def update_all_messages():
|
|||
|
||||
|
||||
def sendStatusMessage(msg, bot):
|
||||
if len(Interval) == 0:
|
||||
Interval.append(setInterval(DOWNLOAD_STATUS_UPDATE_INTERVAL, update_all_messages))
|
||||
total, used, free = shutil.disk_usage('.')
|
||||
free = get_readable_file_size(free)
|
||||
currentTime = get_readable_time(time.time() - botStartTime)
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ def cancel_mirror(update, context):
|
|||
elif not mirror_message:
|
||||
sendMessage(msg, context.bot, update)
|
||||
return
|
||||
if dl.status() == "Archiving...🔐":
|
||||
if dl.status() == MirrorStatus.STATUS_ARCHIVING:
|
||||
sendMessage("Archival in Progress, You Can't Cancel It.", context.bot, update)
|
||||
elif dl.status() == "Extracting...📂":
|
||||
elif dl.status() == MirrorStatus.STATUS_EXTRACTING:
|
||||
sendMessage("Extract in Progress, You Can't Cancel It.", context.bot, update)
|
||||
else:
|
||||
dl.download().cancel_download()
|
||||
|
|
@ -54,16 +54,15 @@ def cancel_mirror(update, context):
|
|||
|
||||
def cancel_all(update, context):
|
||||
count = 0
|
||||
gid = 1
|
||||
gid = 0
|
||||
while True:
|
||||
dl = getAllDownload()
|
||||
if dl:
|
||||
if dl.gid() == gid:
|
||||
continue
|
||||
else:
|
||||
if dl.gid() != gid:
|
||||
gid = dl.gid()
|
||||
dl.download().cancel_download()
|
||||
count += 1
|
||||
sleep(0.3)
|
||||
else:
|
||||
break
|
||||
sendMessage(f'{count} Download(s) has been Cancelled!', context.bot, update)
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ from bot.helper.telegram_helper.message_utils import *
|
|||
from bot.helper.telegram_helper.filters import CustomFilters
|
||||
from bot.helper.telegram_helper.bot_commands import BotCommands
|
||||
from bot.helper.mirror_utils.status_utils.clone_status import CloneStatus
|
||||
from bot import dispatcher, LOGGER, CLONE_LIMIT, STOP_DUPLICATE, download_dict, download_dict_lock, Interval, DOWNLOAD_STATUS_UPDATE_INTERVAL
|
||||
from bot.helper.ext_utils.bot_utils import get_readable_file_size, setInterval
|
||||
from bot import dispatcher, LOGGER, CLONE_LIMIT, STOP_DUPLICATE, download_dict, download_dict_lock, Interval
|
||||
from bot.helper.ext_utils.bot_utils import get_readable_file_size
|
||||
import random
|
||||
import string
|
||||
|
||||
|
|
@ -50,8 +50,6 @@ def cloneNode(update, context):
|
|||
clone_status = CloneStatus(drive, clonesize, update, gid)
|
||||
with download_dict_lock:
|
||||
download_dict[update.message.message_id] = clone_status
|
||||
if len(Interval) == 0:
|
||||
Interval.append(setInterval(DOWNLOAD_STATUS_UPDATE_INTERVAL, update_all_messages))
|
||||
sendStatusMessage(update, context.bot)
|
||||
result, button = drive.clone(link)
|
||||
with download_dict_lock:
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ from telegram.ext import CommandHandler
|
|||
from telegram import InlineKeyboardMarkup
|
||||
|
||||
from bot import Interval, INDEX_URL, BUTTON_FOUR_NAME, BUTTON_FOUR_URL, BUTTON_FIVE_NAME, BUTTON_FIVE_URL, BUTTON_SIX_NAME, BUTTON_SIX_URL, BLOCK_MEGA_FOLDER, BLOCK_MEGA_LINKS, VIEW_LINK, aria2
|
||||
from bot import dispatcher, DOWNLOAD_DIR, DOWNLOAD_STATUS_UPDATE_INTERVAL, download_dict, download_dict_lock, SHORTENER, SHORTENER_API, TAR_UNZIP_LIMIT
|
||||
from bot import dispatcher, DOWNLOAD_DIR, download_dict, download_dict_lock, SHORTENER, SHORTENER_API, TAR_UNZIP_LIMIT
|
||||
from bot.helper.ext_utils import fs_utils, bot_utils
|
||||
from bot.helper.ext_utils.bot_utils import setInterval, get_mega_link_type
|
||||
from bot.helper.ext_utils.bot_utils import get_mega_link_type
|
||||
from bot.helper.ext_utils.exceptions import DirectDownloadLinkException, NotSupportedExtractionArchive
|
||||
from bot.helper.mirror_utils.download_utils.aria2_download import AriaDownloadHelper
|
||||
from bot.helper.mirror_utils.download_utils.mega_downloader import MegaDownloadHelper
|
||||
from bot.helper.mirror_utils.download_utils.qbit_downloader import qbittorrent
|
||||
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 import listeners
|
||||
|
|
@ -235,8 +236,15 @@ def _mirror(bot, update, isTar=False, extract=False):
|
|||
mesg = update.message.text.split('\n')
|
||||
message_args = mesg[0].split(' ')
|
||||
name_args = mesg[0].split('|')
|
||||
qbit = False
|
||||
qbitsel = False
|
||||
try:
|
||||
link = message_args[1]
|
||||
if link == "qb" or link == "qbs":
|
||||
qbit = True
|
||||
if link == "qbs":
|
||||
qbitsel = True
|
||||
link = message_args[2]
|
||||
print(link)
|
||||
if link.startswith("|") or link.startswith("pswd: "):
|
||||
link = ''
|
||||
|
|
@ -281,11 +289,13 @@ def _mirror(bot, update, isTar=False, extract=False):
|
|||
tg_downloader = TelegramDownloadHelper(listener)
|
||||
ms = update.message
|
||||
tg_downloader.add_download(ms, f'{DOWNLOAD_DIR}{listener.uid}/', name)
|
||||
if len(Interval) == 0:
|
||||
Interval.append(setInterval(DOWNLOAD_STATUS_UPDATE_INTERVAL, update_all_messages))
|
||||
return
|
||||
else:
|
||||
link = file.get_file().file_path
|
||||
if qbit:
|
||||
file.get_file().download(custom_path=f"/usr/src/app/{file.file_name}")
|
||||
link = f"/usr/src/app/{file.file_name}"
|
||||
else:
|
||||
link = file.get_file().file_path
|
||||
else:
|
||||
tag = None
|
||||
if not bot_utils.is_url(link) and not bot_utils.is_magnet(link):
|
||||
|
|
@ -333,8 +343,6 @@ def _mirror(bot, update, isTar=False, extract=False):
|
|||
download_status = DownloadStatus(drive, size, listener, gid)
|
||||
with download_dict_lock:
|
||||
download_dict[listener.uid] = download_status
|
||||
if len(Interval) == 0:
|
||||
Interval.append(setInterval(DOWNLOAD_STATUS_UPDATE_INTERVAL, update_all_messages))
|
||||
sendStatusMessage(update, bot)
|
||||
drive.download(link)
|
||||
|
||||
|
|
@ -347,11 +355,14 @@ def _mirror(bot, update, isTar=False, extract=False):
|
|||
else:
|
||||
mega_dl = MegaDownloadHelper()
|
||||
mega_dl.add_download(link, f'{DOWNLOAD_DIR}/{listener.uid}/', listener)
|
||||
|
||||
elif qbit and (bot_utils.is_magnet(link) or os.path.exists(link)):
|
||||
qbit = qbittorrent()
|
||||
qbit.add_torrent(link, f'{DOWNLOAD_DIR}{listener.uid}/', listener, qbitsel)
|
||||
|
||||
else:
|
||||
ariaDlManager.add_download(link, f'{DOWNLOAD_DIR}/{listener.uid}/', listener, name)
|
||||
sendStatusMessage(update, bot)
|
||||
if len(Interval) == 0:
|
||||
Interval.append(setInterval(DOWNLOAD_STATUS_UPDATE_INTERVAL, update_all_messages))
|
||||
|
||||
|
||||
def mirror(update, context):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
from telegram.ext import CommandHandler
|
||||
from telegram import Bot, Update
|
||||
from bot import Interval, DOWNLOAD_DIR, DOWNLOAD_STATUS_UPDATE_INTERVAL, dispatcher, LOGGER
|
||||
from bot.helper.ext_utils.bot_utils import setInterval
|
||||
from bot.helper.telegram_helper.message_utils import update_all_messages, sendMessage, sendStatusMessage
|
||||
from bot import DOWNLOAD_DIR, dispatcher, LOGGER
|
||||
from bot.helper.telegram_helper.message_utils import sendMessage, sendStatusMessage
|
||||
from .mirror import MirrorListener
|
||||
from bot.helper.mirror_utils.download_utils.youtube_dl_download_helper import YoutubeDLHelper
|
||||
from bot.helper.telegram_helper.bot_commands import BotCommands
|
||||
|
|
@ -50,8 +49,6 @@ def _watch(bot: Bot, update, isTar=False):
|
|||
ydl = YoutubeDLHelper(listener)
|
||||
threading.Thread(target=ydl.add_download,args=(link, f'{DOWNLOAD_DIR}{listener.uid}', qual, name)).start()
|
||||
sendStatusMessage(update, bot)
|
||||
if len(Interval) == 0:
|
||||
Interval.append(setInterval(DOWNLOAD_STATUS_UPDATE_INTERVAL, update_all_messages))
|
||||
|
||||
|
||||
def watchTar(update, context):
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ BLOCK_MEGA_LINKS = ""
|
|||
STOP_DUPLICATE = ""
|
||||
SHORTENER = ""
|
||||
SHORTENER_API = ""
|
||||
#Qbittorrent
|
||||
IS_VPS = ""
|
||||
SERVER_PORT = "80" #For VPS
|
||||
BASE_URL_OF_BOT = ""
|
||||
# If you want to use Credentials externally from Index Links, fill these vars with the direct links
|
||||
# These are optional, if you don't know, simply leave them, don't fill anything in them.
|
||||
ACCOUNTS_ZIP_URL = ""
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
build:
|
||||
docker:
|
||||
worker: Dockerfile
|
||||
web: Dockerfile
|
||||
run:
|
||||
worker: bash start.sh
|
||||
web: bash start.sh
|
||||
|
|
|
|||
|
|
@ -0,0 +1,140 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# (c) YashDK [yash-dk@github]
|
||||
|
||||
from anytree import NodeMixin, RenderTree, PreOrderIter
|
||||
import qbittorrentapi as qba
|
||||
|
||||
SIZE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']
|
||||
|
||||
class TorNode(NodeMixin):
|
||||
def __init__(self, name, is_folder=False, is_file=False, parent=None, progress=None, size=None, priority=None, file_id=None):
|
||||
super().__init__()
|
||||
self.name = name
|
||||
self.is_folder = is_folder
|
||||
self.is_file = is_file
|
||||
|
||||
if parent is not None:
|
||||
self.parent = parent
|
||||
if progress is not None:
|
||||
self.progress = progress
|
||||
if size is not None:
|
||||
self.size = size
|
||||
if priority is not None:
|
||||
self.priority = priority
|
||||
if file_id is not None:
|
||||
self.file_id = file_id
|
||||
|
||||
|
||||
def get_folders(path):
|
||||
path_seperator = "/"
|
||||
folders = path.split(path_seperator)
|
||||
return folders
|
||||
|
||||
|
||||
def make_tree(res):
|
||||
"""This function takes the list of all the torrent files. The files are name hierarchically.
|
||||
Felt a need to document to save time.
|
||||
|
||||
Args:
|
||||
res (list): Torrent files list.
|
||||
|
||||
Returns:
|
||||
TorNode: Parent node of the tree constructed and can be used further.
|
||||
"""
|
||||
parent = TorNode("Torrent")
|
||||
#nodes = dict()
|
||||
l = 0
|
||||
|
||||
for i in res:
|
||||
# Get the hierarchy of the folders by splitting based on '/'
|
||||
folders = get_folders(i.name)
|
||||
# Check if the file is alone for if its in folder
|
||||
if len(folders) > 1:
|
||||
# Enter here if in folder
|
||||
|
||||
# Set the parent
|
||||
previous_node = parent
|
||||
|
||||
# Traverse till second last assuming the last is a file.
|
||||
for j in range(len(folders)-1):
|
||||
current_node = None
|
||||
|
||||
if previous_node is not None:
|
||||
# As we are traversing the folder from top to bottom we are searching
|
||||
# the first folder (folders list) under the parent node in first iteration.
|
||||
# If the node is found then it becomes the current node else the current node
|
||||
# is left None.
|
||||
for k in previous_node.children:
|
||||
if k.name == folders[j]:
|
||||
current_node = k
|
||||
break
|
||||
else:
|
||||
# think its useless afterall
|
||||
for k in parent.children:
|
||||
if k.name == folders[j]:
|
||||
current_node = k
|
||||
break
|
||||
|
||||
# if the node is not found then create the folder node
|
||||
# if the node is found then use it as base for the next
|
||||
if current_node is None:
|
||||
previous_node = TorNode(folders[j],parent=previous_node,is_folder=True)
|
||||
else:
|
||||
previous_node = current_node
|
||||
# at this point the previous_node will contain the deepest folder in it so add the file to it
|
||||
TorNode(folders[-1],is_file=True,parent=previous_node,progress=i.progress,size=i.size,priority=i.priority,file_id=l)
|
||||
l += 1
|
||||
else:
|
||||
# at the file to the parent if no folders are there
|
||||
TorNode(folders[-1],is_file=True,parent=parent,progress=i.progress,size=i.size,priority=i.priority,file_id=l)
|
||||
l += 1
|
||||
|
||||
|
||||
return parent
|
||||
|
||||
|
||||
def print_tree(parent):
|
||||
for pre, _, node in RenderTree(parent):
|
||||
treestr = u"%s%s" % (pre, node.name)
|
||||
print(treestr.ljust(8), node.is_folder, node.is_file)
|
||||
|
||||
|
||||
def create_list(par, msg):
|
||||
if par.name != ".unwanted":
|
||||
msg[0] += "<ul>"
|
||||
for i in par.children:
|
||||
if i.is_folder:
|
||||
msg[0] += "<li>"
|
||||
if i.name != ".unwanted":
|
||||
msg[0] += f"<input type=\"checkbox\" name=\"foldernode_{msg[1]}\"> <label for=\"{i.name}\">{i.name}</label>"
|
||||
create_list(i,msg)
|
||||
msg[0] += "</li>"
|
||||
msg[1] += 1
|
||||
else:
|
||||
msg[0] += "<li>"
|
||||
if i.priority == 0:
|
||||
msg[0] += f"<input type=\"checkbox\" name=\"filenode_{i.file_id}\"> <label for=\"filenode_{i.file_id}\">{i.name} - {get_readable_file_size(i.size)}</label>"
|
||||
msg[0] += f"<input type=\"hidden\" value=\"off\" name=\"filenode_{i.file_id}\">"
|
||||
|
||||
else:
|
||||
msg[0] += f"<input type=\"checkbox\" checked name=\"filenode_{i.file_id}\"> <label for=\"filenode_{i.file_id}\">{i.name} - {get_readable_file_size(i.size)}</label>"
|
||||
msg[0] += f"<input type=\"hidden\" value=\"off\" name=\"filenode_{i.file_id}\">"
|
||||
|
||||
|
||||
msg[0] += "</li>"
|
||||
|
||||
if par.name != ".unwanted":
|
||||
msg[0] += "</ul>"
|
||||
|
||||
def get_readable_file_size(size_in_bytes) -> str:
|
||||
if size_in_bytes is None:
|
||||
return '0B'
|
||||
index = 0
|
||||
while size_in_bytes >= 1024:
|
||||
size_in_bytes /= 1024
|
||||
index += 1
|
||||
try:
|
||||
return f'{round(size_in_bytes, 2)}{SIZE_UNITS[index]}'
|
||||
except IndexError:
|
||||
return 'File too large'
|
||||
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
aiohttp
|
||||
anytree
|
||||
aria2p
|
||||
appdirs
|
||||
beautifulsoup4
|
||||
|
|
@ -8,6 +9,7 @@ gitpython
|
|||
google-api-python-client
|
||||
google-auth-httplib2
|
||||
google-auth-oauthlib
|
||||
gunicorn
|
||||
heroku3
|
||||
js2py
|
||||
lk21
|
||||
|
|
@ -19,9 +21,12 @@ pyrogram
|
|||
python-dotenv
|
||||
python-magic
|
||||
python-telegram-bot
|
||||
qbittorrent-api
|
||||
requests
|
||||
speedtest-cli
|
||||
telegraph
|
||||
tenacity
|
||||
TgCrypto
|
||||
torrentool
|
||||
youtube_dl
|
||||
urllib3
|
||||
|
|
|
|||
2
start.sh
2
start.sh
|
|
@ -8,4 +8,4 @@ if [[ -n $ACCOUNTS_ZIP_URL ]]; then
|
|||
rm accounts.zip
|
||||
fi
|
||||
|
||||
./aria.sh; python3 -m bot
|
||||
gunicorn wserver:start_server --bind 0.0.0.0:$PORT --worker-class aiohttp.GunicornWebWorker & qbittorrent-nox -d --webui-port=8090 & python3 alive.py & ./aria.sh; python3 -m bot
|
||||
|
|
|
|||
|
|
@ -0,0 +1,309 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# (c) YashDK [yash-dk@github]
|
||||
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
import qbittorrentapi as qba
|
||||
import asyncio
|
||||
|
||||
from aiohttp import web
|
||||
import nodes
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
routes = web.RouteTableDef()
|
||||
|
||||
page = """
|
||||
<html>
|
||||
<head>
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=" crossorigin="anonymous"></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
body {
|
||||
padding: 20px;
|
||||
}
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 5px 20px;
|
||||
}
|
||||
li {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
|
||||
p { font-size: 12px; margin: 24px;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Slam-mirror-bot : <a href="#">Github</a></h1>
|
||||
<form action="{form_url}" method="POST">
|
||||
|
||||
{My_content}
|
||||
|
||||
<input type="submit" name="Select these files ;)">
|
||||
</form>
|
||||
|
||||
<script>
|
||||
$('input[type="checkbox"]').change(function(e) {
|
||||
|
||||
var checked = $(this).prop("checked"),
|
||||
container = $(this).parent(),
|
||||
siblings = container.siblings();
|
||||
/*
|
||||
$(this).attr('value', function(index, attr){
|
||||
return attr == 'yes' ? 'noo' : 'yes';
|
||||
});
|
||||
*/
|
||||
container.find('input[type="checkbox"]').prop({
|
||||
indeterminate: false,
|
||||
checked: checked
|
||||
});
|
||||
|
||||
function checkSiblings(el) {
|
||||
|
||||
var parent = el.parent().parent(),
|
||||
all = true;
|
||||
|
||||
el.siblings().each(function() {
|
||||
let returnValue = all = ($(this).children('input[type="checkbox"]').prop("checked") === checked);
|
||||
return returnValue;
|
||||
});
|
||||
|
||||
if (all && checked) {
|
||||
|
||||
parent.children('input[type="checkbox"]').prop({
|
||||
indeterminate: false,
|
||||
checked: checked
|
||||
});
|
||||
|
||||
checkSiblings(parent);
|
||||
|
||||
} else if (all && !checked) {
|
||||
|
||||
parent.children('input[type="checkbox"]').prop("checked", checked);
|
||||
parent.children('input[type="checkbox"]').prop("indeterminate", (parent.find('input[type="checkbox"]:checked').length > 0));
|
||||
checkSiblings(parent);
|
||||
|
||||
} else {
|
||||
|
||||
el.parents("li").children('input[type="checkbox"]').prop({
|
||||
indeterminate: true,
|
||||
checked: false
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
checkSiblings(container);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
"""
|
||||
|
||||
code_page = """
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
|
||||
<title>
|
||||
Slam Torrent Files
|
||||
</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<form action="{form_url}">
|
||||
<div class="form-group">
|
||||
<label for="pin_code">Pin Code</label>
|
||||
<input type="text" class="form-control" name="pin_code" placeholder="Enter code to access the torrent">
|
||||
<small class="form-text text-muted">Dont mess around. You download will get messed up.</small>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
@routes.get('/slam/files/{hash_id}')
|
||||
async def list_torrent_contents(request):
|
||||
|
||||
torr = request.match_info["hash_id"]
|
||||
|
||||
gets = request.query
|
||||
|
||||
if not "pin_code" in gets.keys():
|
||||
rend_page = code_page.replace("{form_url}",f"/slam/files/{torr}")
|
||||
return web.Response(text=rend_page,content_type='text/html')
|
||||
|
||||
|
||||
client = qba.Client(host="localhost",port="8090",username="admin",password="adminadmin")
|
||||
client.auth_log_in()
|
||||
try:
|
||||
res = client.torrents_files(torrent_hash=torr)
|
||||
except qba.NotFound404Error:
|
||||
raise web.HTTPNotFound()
|
||||
count = 0
|
||||
passw = ""
|
||||
for n in str(torr):
|
||||
if n.isdigit():
|
||||
passw += str(n)
|
||||
count += 1
|
||||
if count == 4:
|
||||
break
|
||||
if isinstance(passw, bool):
|
||||
raise web.HTTPNotFound()
|
||||
pincode = passw
|
||||
if gets["pin_code"] != pincode:
|
||||
return web.Response(text="Incorrect pin code")
|
||||
|
||||
|
||||
par = nodes.make_tree(res)
|
||||
|
||||
cont = ["",0]
|
||||
nodes.create_list(par,cont)
|
||||
|
||||
rend_page = page.replace("{My_content}",cont[0])
|
||||
rend_page = rend_page.replace("{form_url}",f"/slam/files/{torr}?pin_code={pincode}")
|
||||
client.auth_log_out()
|
||||
return web.Response(text=rend_page,content_type='text/html')
|
||||
|
||||
|
||||
async def re_verfiy(paused, resumed, client, torr):
|
||||
|
||||
paused = paused.strip()
|
||||
resumed = resumed.strip()
|
||||
if paused:
|
||||
paused = paused.split("|")
|
||||
if resumed:
|
||||
resumed = resumed.split("|")
|
||||
k = 0
|
||||
while True:
|
||||
|
||||
res = client.torrents_files(torrent_hash=torr)
|
||||
verify = True
|
||||
|
||||
for i in res:
|
||||
if str(i.id) in paused:
|
||||
if i.priority == 0:
|
||||
continue
|
||||
else:
|
||||
verify = False
|
||||
break
|
||||
|
||||
if str(i.id) in resumed:
|
||||
if i.priority != 0:
|
||||
continue
|
||||
else:
|
||||
verify = False
|
||||
break
|
||||
|
||||
|
||||
if not verify:
|
||||
LOGGER.info("Reverification Failed :- correcting stuff")
|
||||
# reconnect and issue the request again
|
||||
client.auth_log_out()
|
||||
client = qba.Client(host="localhost",port="8090",username="admin",password="adminadmin")
|
||||
client.auth_log_in()
|
||||
try:
|
||||
client.torrents_file_priority(torrent_hash=torr,file_ids=paused,priority=0)
|
||||
except:
|
||||
LOGGER.error("Errored in reverification paused")
|
||||
try:
|
||||
client.torrents_file_priority(torrent_hash=torr,file_ids=resumed,priority=1)
|
||||
except:
|
||||
LOGGER.error("Errored in reverification resumed")
|
||||
client.auth_log_out()
|
||||
else:
|
||||
break
|
||||
k += 1
|
||||
if k >= 2:
|
||||
# avoid an infite loop here
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@routes.post('/slam/files/{hash_id}')
|
||||
async def set_priority(request):
|
||||
|
||||
torr = request.match_info["hash_id"]
|
||||
client = qba.Client(host="localhost",port="8090",username="admin",password="adminadmin")
|
||||
client.auth_log_in()
|
||||
|
||||
data = await request.post()
|
||||
resume = ""
|
||||
pause = ""
|
||||
data = dict(data)
|
||||
|
||||
for i in data.keys():
|
||||
if i.find("filenode") != -1:
|
||||
node_no = i.split("_")[-1]
|
||||
|
||||
if data[i] == "on":
|
||||
resume += f"{node_no}|"
|
||||
else:
|
||||
pause += f"{node_no}|"
|
||||
|
||||
pause = pause.strip("|")
|
||||
resume = resume.strip("|")
|
||||
LOGGER.info(f"Paused {pause} of {torr}")
|
||||
LOGGER.info(f"Resumed {resume} of {torr}")
|
||||
|
||||
try:
|
||||
client.torrents_file_priority(torrent_hash=torr,file_ids=pause,priority=0)
|
||||
except qba.NotFound404Error:
|
||||
raise web.HTTPNotFound()
|
||||
except:
|
||||
LOGGER.info("Errored in paused")
|
||||
|
||||
try:
|
||||
client.torrents_file_priority(torrent_hash=torr,file_ids=resume,priority=1)
|
||||
except qba.NotFound404Error:
|
||||
raise web.HTTPNotFound()
|
||||
except:
|
||||
LOGGER.info("Errored in resumed")
|
||||
|
||||
await asyncio.sleep(2)
|
||||
if not await re_verfiy(pause,resume,client,torr):
|
||||
LOGGER.error("The torrent choose errored reverification failed")
|
||||
client.auth_log_out()
|
||||
return await list_torrent_contents(request)
|
||||
|
||||
@routes.get('/')
|
||||
async def homepage(request):
|
||||
|
||||
return web.Response(text="<h1>See slam-mirror-bot <a href=\"#\">@GitHub</a>By Slam</h1>",content_type="text/html")
|
||||
|
||||
async def e404_middleware(app, handler):
|
||||
|
||||
async def middleware_handler(request):
|
||||
|
||||
try:
|
||||
response = await handler(request)
|
||||
if response.status == 404:
|
||||
return web.Response(text="<h1>404: Page not found</h2><br><h3>Slam</h3>",content_type="text/html")
|
||||
return response
|
||||
except web.HTTPException as ex:
|
||||
if ex.status == 404:
|
||||
return web.Response(text="<h1>404: Page not found</h2><br><h3>Slam</h3>",content_type="text/html")
|
||||
raise
|
||||
return middleware_handler
|
||||
|
||||
async def start_server():
|
||||
|
||||
app = web.Application(middlewares=[e404_middleware])
|
||||
app.add_routes(routes)
|
||||
return app
|
||||
|
||||
async def start_server_async(port = 8080):
|
||||
|
||||
app = web.Application(middlewares=[e404_middleware])
|
||||
app.add_routes(routes)
|
||||
runner = web.AppRunner(app)
|
||||
await runner.setup()
|
||||
await web.TCPSite(runner,"0.0.0.0", port).start()
|
||||
Loading…
Reference in New Issue