mirror of
https://github.com/anasty17/mirror-leech-telegram-bot.git
synced 2025-01-08 12:07:33 +08:00
Minor Changes
Signed-off-by: anasty17 <e.anastayyar@gmail.com>
This commit is contained in:
parent
59cc026843
commit
023c595469
@ -184,7 +184,6 @@ Fill up rest of the fields. Meaning of each field is discussed below. **NOTE**:
|
||||
- `SUDO_USERS`: Fill user_id of users whom you want to give sudo permission. Separate them by space. `Int`
|
||||
- `DEFAULT_UPLOAD`: Whether `rc` to upload to `RCLONE_PATH` or `gd` to upload to `GDRIVE_ID`. Default is `gd`. Read More [HERE](https://github.com/anasty17/mirror-leech-telegram-bot/tree/master#upload).`Str`
|
||||
- `STATUS_UPDATE_INTERVAL`: Time in seconds after which the progress/status message will be updated. Recommended `10` seconds at least. `Int`
|
||||
- `AUTO_DELETE_MESSAGE_DURATION`: Interval of time (in seconds), after which the bot deletes it's message and command message which is expected to be viewed instantly. **NOTE**: Set to `-1` to disable auto message deletion. `Int`
|
||||
- `STATUS_LIMIT`: Limit the no. of tasks shown in status message with buttons. Default is `10`. **NOTE**: Recommended limit is `4` tasks. `Int`
|
||||
- `EXTENSION_FILTER`: File extensions that won't upload/clone. Separate them by space. `Str`
|
||||
- `INCOMPLETE_TASK_NOTIFIER`: Get incomplete task messages after restart. Require database and superGroup. Default is `False`. `Bool`
|
||||
|
@ -263,12 +263,6 @@ if len(STATUS_UPDATE_INTERVAL) == 0:
|
||||
else:
|
||||
STATUS_UPDATE_INTERVAL = int(STATUS_UPDATE_INTERVAL)
|
||||
|
||||
AUTO_DELETE_MESSAGE_DURATION = environ.get("AUTO_DELETE_MESSAGE_DURATION", "")
|
||||
if len(AUTO_DELETE_MESSAGE_DURATION) == 0:
|
||||
AUTO_DELETE_MESSAGE_DURATION = 30
|
||||
else:
|
||||
AUTO_DELETE_MESSAGE_DURATION = int(AUTO_DELETE_MESSAGE_DURATION)
|
||||
|
||||
YT_DLP_OPTIONS = environ.get("YT_DLP_OPTIONS", "")
|
||||
if len(YT_DLP_OPTIONS) == 0:
|
||||
YT_DLP_OPTIONS = ""
|
||||
@ -367,7 +361,6 @@ if len(RCLONE_SERVE_PASS) == 0:
|
||||
config_dict = {
|
||||
"AS_DOCUMENT": AS_DOCUMENT,
|
||||
"AUTHORIZED_CHATS": AUTHORIZED_CHATS,
|
||||
"AUTO_DELETE_MESSAGE_DURATION": AUTO_DELETE_MESSAGE_DURATION,
|
||||
"BASE_URL": BASE_URL,
|
||||
"BASE_URL_PORT": BASE_URL_PORT,
|
||||
"BOT_TOKEN": BOT_TOKEN,
|
||||
|
@ -15,12 +15,15 @@ def _get_combined_info(result, start_time):
|
||||
hosts = result[0].get("hosts")
|
||||
bytesLoaded = 0
|
||||
bytesTotal = 0
|
||||
status = ""
|
||||
for res in result:
|
||||
st = res.get("status", "").lower()
|
||||
if st and st != "finished":
|
||||
status = st
|
||||
bytesLoaded += res.get("bytesLoaded", 0)
|
||||
bytesTotal += res.get("bytesTotal", 0)
|
||||
if not status:
|
||||
status = "UnknownError"
|
||||
try:
|
||||
speed = bytesLoaded / (time() - start_time)
|
||||
eta = (bytesTotal - bytesLoaded) / speed
|
||||
|
@ -92,12 +92,11 @@ async def deleteMessage(message):
|
||||
|
||||
|
||||
async def auto_delete_message(cmd_message=None, bot_message=None):
|
||||
if config_dict["AUTO_DELETE_MESSAGE_DURATION"] != -1:
|
||||
await sleep(config_dict["AUTO_DELETE_MESSAGE_DURATION"])
|
||||
if cmd_message is not None:
|
||||
await deleteMessage(cmd_message)
|
||||
if bot_message is not None:
|
||||
await deleteMessage(bot_message)
|
||||
await sleep(60)
|
||||
if cmd_message is not None:
|
||||
await deleteMessage(cmd_message)
|
||||
if bot_message is not None:
|
||||
await deleteMessage(bot_message)
|
||||
|
||||
|
||||
async def delete_status():
|
||||
|
@ -56,7 +56,6 @@ START = 0
|
||||
STATE = "view"
|
||||
handler_dict = {}
|
||||
default_values = {
|
||||
"AUTO_DELETE_MESSAGE_DURATION": 30,
|
||||
"DOWNLOAD_DIR": "/usr/src/app/downloads/",
|
||||
"LEECH_SPLIT_SIZE": MAX_SPLIT_SIZE,
|
||||
"RSS_DELAY": 600,
|
||||
@ -176,9 +175,6 @@ async def edit_variable(_, message, pre_message, key):
|
||||
value = False
|
||||
if key == "INCOMPLETE_TASK_NOTIFIER" and DATABASE_URL:
|
||||
await DbManger().trunc_table("tasks")
|
||||
elif key == "RSS_DELAY":
|
||||
value = int(value)
|
||||
addJob(value)
|
||||
elif key == "DOWNLOAD_DIR":
|
||||
if not value.endswith("/"):
|
||||
value += "/"
|
||||
@ -253,6 +249,8 @@ async def edit_variable(_, message, pre_message, key):
|
||||
await rclone_serve_booter()
|
||||
elif key in ["JD_EMAIL", "JD_PASS"]:
|
||||
jdownloader.initiate()
|
||||
elif key == "RSS_DELAY":
|
||||
addJob()
|
||||
|
||||
|
||||
async def edit_aria(_, message, pre_message, key):
|
||||
@ -774,12 +772,6 @@ async def load_config():
|
||||
STATUS_UPDATE_INTERVAL, update_status_message, key
|
||||
)
|
||||
|
||||
AUTO_DELETE_MESSAGE_DURATION = environ.get("AUTO_DELETE_MESSAGE_DURATION", "")
|
||||
if len(AUTO_DELETE_MESSAGE_DURATION) == 0:
|
||||
AUTO_DELETE_MESSAGE_DURATION = 30
|
||||
else:
|
||||
AUTO_DELETE_MESSAGE_DURATION = int(AUTO_DELETE_MESSAGE_DURATION)
|
||||
|
||||
YT_DLP_OPTIONS = environ.get("YT_DLP_OPTIONS", "")
|
||||
if len(YT_DLP_OPTIONS) == 0:
|
||||
YT_DLP_OPTIONS = ""
|
||||
@ -938,7 +930,6 @@ async def load_config():
|
||||
{
|
||||
"AS_DOCUMENT": AS_DOCUMENT,
|
||||
"AUTHORIZED_CHATS": AUTHORIZED_CHATS,
|
||||
"AUTO_DELETE_MESSAGE_DURATION": AUTO_DELETE_MESSAGE_DURATION,
|
||||
"BASE_URL": BASE_URL,
|
||||
"BASE_URL_PORT": BASE_URL_PORT,
|
||||
"BOT_TOKEN": BOT_TOKEN,
|
||||
@ -995,6 +986,7 @@ async def load_config():
|
||||
if DATABASE_URL:
|
||||
await DbManger().update_config(config_dict)
|
||||
await gather(initiate_search_tools(), start_from_queued(), rclone_serve_booter())
|
||||
addJob()
|
||||
|
||||
|
||||
bot.add_handler(
|
||||
|
@ -9,6 +9,7 @@ from bot.helper.telegram_helper.message_utils import (
|
||||
sendMessage,
|
||||
auto_delete_message,
|
||||
deleteMessage,
|
||||
editMessage,
|
||||
)
|
||||
from bot.helper.ext_utils.status_utils import getTaskByGid, getAllTasks, MirrorStatus
|
||||
from bot.helper.ext_utils.bot_utils import new_task
|
||||
@ -79,26 +80,30 @@ async def cancel_all(status):
|
||||
return True
|
||||
|
||||
|
||||
def create_cancel_buttons():
|
||||
buttons = button_build.ButtonMaker()
|
||||
buttons.ibutton("Downloading", f"canall ms {MirrorStatus.STATUS_DOWNLOADING}")
|
||||
buttons.ibutton("Uploading", f"canall ms {MirrorStatus.STATUS_UPLOADING}")
|
||||
buttons.ibutton("Seeding", f"canall ms {MirrorStatus.STATUS_SEEDING}")
|
||||
buttons.ibutton("Spltting", f"canall ms {MirrorStatus.STATUS_SPLITTING}")
|
||||
buttons.ibutton("Cloning", f"canall ms {MirrorStatus.STATUS_CLONING}")
|
||||
buttons.ibutton("Extracting", f"canall ms {MirrorStatus.STATUS_EXTRACTING}")
|
||||
buttons.ibutton("Archiving", f"canall ms {MirrorStatus.STATUS_ARCHIVING}")
|
||||
buttons.ibutton("QueuedDl", f"canall ms {MirrorStatus.STATUS_QUEUEDL}")
|
||||
buttons.ibutton("QueuedUp", f"canall ms {MirrorStatus.STATUS_QUEUEUP}")
|
||||
buttons.ibutton("Paused", f"canall ms {MirrorStatus.STATUS_PAUSED}")
|
||||
buttons.ibutton("All", "canall ms all")
|
||||
buttons.ibutton("Close", "canall close")
|
||||
return buttons.build_menu(2)
|
||||
|
||||
|
||||
async def cancell_all_buttons(_, message):
|
||||
async with task_dict_lock:
|
||||
count = len(task_dict)
|
||||
if count == 0:
|
||||
await sendMessage(message, "No active tasks!")
|
||||
return
|
||||
buttons = button_build.ButtonMaker()
|
||||
buttons.ibutton("Downloading", f"canall {MirrorStatus.STATUS_DOWNLOADING}")
|
||||
buttons.ibutton("Uploading", f"canall {MirrorStatus.STATUS_UPLOADING}")
|
||||
buttons.ibutton("Seeding", f"canall {MirrorStatus.STATUS_SEEDING}")
|
||||
buttons.ibutton("Spltting", f"canall {MirrorStatus.STATUS_SPLITTING}")
|
||||
buttons.ibutton("Cloning", f"canall {MirrorStatus.STATUS_CLONING}")
|
||||
buttons.ibutton("Extracting", f"canall {MirrorStatus.STATUS_EXTRACTING}")
|
||||
buttons.ibutton("Archiving", f"canall {MirrorStatus.STATUS_ARCHIVING}")
|
||||
buttons.ibutton("QueuedDl", f"canall {MirrorStatus.STATUS_QUEUEDL}")
|
||||
buttons.ibutton("QueuedUp", f"canall {MirrorStatus.STATUS_QUEUEUP}")
|
||||
buttons.ibutton("Paused", f"canall {MirrorStatus.STATUS_PAUSED}")
|
||||
buttons.ibutton("All", "canall all")
|
||||
buttons.ibutton("Close", "canall close")
|
||||
button = buttons.build_menu(2)
|
||||
button = create_cancel_buttons()
|
||||
can_msg = await sendMessage(message, "Choose tasks to cancel.", button)
|
||||
await auto_delete_message(message, can_msg)
|
||||
|
||||
@ -112,6 +117,18 @@ async def cancel_all_update(_, query):
|
||||
if data[1] == "close":
|
||||
await deleteMessage(reply_to)
|
||||
await deleteMessage(message)
|
||||
elif data[1] == "back":
|
||||
button = create_cancel_buttons()
|
||||
await editMessage(message, "Choose tasks to cancel.", button)
|
||||
elif data[1] == "ms":
|
||||
buttons = button_build.ButtonMaker()
|
||||
buttons.ibutton("Yes!", f"canall {data[2]}")
|
||||
buttons.ibutton("Back", "canall back all")
|
||||
buttons.ibutton("Close", "canall close")
|
||||
button = buttons.build_menu(2)
|
||||
await editMessage(
|
||||
message, f"Are you sure you want to cancel all {data[2]} tasks", button
|
||||
)
|
||||
else:
|
||||
res = await cancel_all(data[1])
|
||||
if not res:
|
||||
|
@ -182,7 +182,7 @@ async def rssSub(_, message, pre_event):
|
||||
if scheduler.state == 2:
|
||||
scheduler.resume()
|
||||
elif is_sudo and not scheduler.running:
|
||||
addJob(config_dict["RSS_DELAY"])
|
||||
addJob()
|
||||
scheduler.start()
|
||||
|
||||
|
||||
@ -229,7 +229,7 @@ async def rssUpdate(_, message, pre_event, state):
|
||||
if scheduler.state == 2:
|
||||
scheduler.resume()
|
||||
elif is_sudo and not scheduler.running:
|
||||
addJob(config_dict["RSS_DELAY"])
|
||||
addJob()
|
||||
scheduler.start()
|
||||
if is_sudo and DATABASE_URL and user_id != message.from_user.id:
|
||||
await DbManger().rss_update(user_id)
|
||||
@ -578,7 +578,7 @@ Timeout: 60 sec. Argument -c for command and options
|
||||
if scheduler.state == 2:
|
||||
scheduler.resume()
|
||||
elif not scheduler.running:
|
||||
addJob(config_dict["RSS_DELAY"])
|
||||
addJob()
|
||||
scheduler.start()
|
||||
if DATABASE_URL:
|
||||
await DbManger().rss_update_all()
|
||||
@ -613,7 +613,7 @@ Timeout: 60 sec. Argument -c for command and options
|
||||
elif data[1] == "start":
|
||||
if not scheduler.running:
|
||||
await query.answer()
|
||||
addJob(config_dict["RSS_DELAY"])
|
||||
addJob()
|
||||
scheduler.start()
|
||||
await updateRssMenu(query)
|
||||
else:
|
||||
@ -712,10 +712,10 @@ async def rssMonitor():
|
||||
scheduler.pause()
|
||||
|
||||
|
||||
def addJob(delay):
|
||||
def addJob():
|
||||
scheduler.add_job(
|
||||
rssMonitor,
|
||||
trigger=IntervalTrigger(seconds=delay),
|
||||
trigger=IntervalTrigger(seconds=config_dict["RSS_DELAY"]),
|
||||
id="0",
|
||||
name="RSS",
|
||||
misfire_grace_time=15,
|
||||
@ -725,7 +725,7 @@ def addJob(delay):
|
||||
)
|
||||
|
||||
|
||||
addJob(config_dict["RSS_DELAY"])
|
||||
addJob()
|
||||
scheduler.start()
|
||||
bot.add_handler(
|
||||
MessageHandler(
|
||||
|
@ -37,7 +37,7 @@ async def mirror_status(_, message):
|
||||
if count == 0:
|
||||
currentTime = get_readable_time(time() - botStartTime)
|
||||
free = get_readable_file_size(disk_usage(DOWNLOAD_DIR).free)
|
||||
msg = f"No Active Tasks!\nEach user can get status for his tasks by me or user_id after cmd: /{BotCommands.StatusCommand} me"
|
||||
msg = f"No Active Tasks!\nEach user can get status for his tasks by adding me or user_id after cmd: /{BotCommands.StatusCommand} me"
|
||||
msg += (
|
||||
f"\n<b>CPU:</b> {cpu_percent()}% | <b>FREE:</b> {free}"
|
||||
f"\n<b>RAM:</b> {virtual_memory().percent}% | <b>UPTIME:</b> {currentTime}"
|
||||
|
@ -15,7 +15,6 @@ SUDO_USERS = "" # Require restart after changing it
|
||||
STATUS_LIMIT = "10"
|
||||
DEFAULT_UPLOAD = "gd"
|
||||
STATUS_UPDATE_INTERVAL = "10"
|
||||
AUTO_DELETE_MESSAGE_DURATION = "30"
|
||||
FILELION_API = ""
|
||||
STREAMWISH_API = ""
|
||||
EXTENSION_FILTER = ""
|
||||
|
@ -1,11 +1,12 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import time
|
||||
from hashlib import sha256
|
||||
from hmac import new
|
||||
from json import dumps, loads, JSONDecodeError
|
||||
from time import time
|
||||
from urllib.parse import quote
|
||||
import base64
|
||||
import requests
|
||||
from base64 import b64encode, b64decode
|
||||
from requests import get, post
|
||||
from requests.exceptions import RequestException
|
||||
from Crypto.Cipher import AES
|
||||
|
||||
from .exception import (
|
||||
@ -850,7 +851,7 @@ class Jddevice:
|
||||
if (
|
||||
self.__direct_connection_enabled
|
||||
and self.__direct_connection_info is not None
|
||||
and time.time() >= self.__direct_connection_cooldown
|
||||
and time() >= self.__direct_connection_cooldown
|
||||
):
|
||||
return self.__direct_connect(path, http_action, params, action_url)
|
||||
response = self.myjd.request_api(path, http_action, params, action_url)
|
||||
@ -858,14 +859,14 @@ class Jddevice:
|
||||
raise (MYJDConnectionException("No connection established\n"))
|
||||
if (
|
||||
self.__direct_connection_enabled
|
||||
and time.time() >= self.__direct_connection_cooldown
|
||||
and time() >= self.__direct_connection_cooldown
|
||||
):
|
||||
self.__refresh_direct_connections()
|
||||
return response["data"]
|
||||
|
||||
def __direct_connect(self, path, http_action, params, action_url):
|
||||
for conn in self.__direct_connection_info:
|
||||
if time.time() > conn["cooldown"]:
|
||||
if time() > conn["cooldown"]:
|
||||
connection = conn["conn"]
|
||||
api = "http://" + connection["ip"] + ":" + str(connection["port"])
|
||||
response = self.myjd.request_api(
|
||||
@ -877,9 +878,9 @@ class Jddevice:
|
||||
self.__direct_connection_consecutive_failures = 0
|
||||
return response["data"]
|
||||
else:
|
||||
conn["cooldown"] = time.time() + 60
|
||||
conn["cooldown"] = time() + 60
|
||||
self.__direct_connection_consecutive_failures += 1
|
||||
self.__direct_connection_cooldown = time.time() + (
|
||||
self.__direct_connection_cooldown = time() + (
|
||||
60 * self.__direct_connection_consecutive_failures
|
||||
)
|
||||
response = self.myjd.request_api(path, http_action, params, action_url)
|
||||
@ -903,7 +904,7 @@ class Myjdapi:
|
||||
This functions initializates the myjdapi object.
|
||||
|
||||
"""
|
||||
self.__request_id = int(time.time() * 1000)
|
||||
self.__request_id = int(time() * 1000)
|
||||
self.__api_url = "https://api.jdownloader.org"
|
||||
self.__app_key = "http://git.io/vmcsk"
|
||||
self.__api_version = 1
|
||||
@ -941,7 +942,7 @@ class Myjdapi:
|
||||
:return: secret hash
|
||||
|
||||
"""
|
||||
secret_hash = hashlib.sha256()
|
||||
secret_hash = sha256()
|
||||
secret_hash.update(
|
||||
email.lower().encode("utf-8")
|
||||
+ password.encode("utf-8")
|
||||
@ -958,10 +959,10 @@ class Myjdapi:
|
||||
old_token = self.__login_secret
|
||||
else:
|
||||
old_token = self.__server_encryption_token
|
||||
new_token = hashlib.sha256()
|
||||
new_token = sha256()
|
||||
new_token.update(old_token + bytearray.fromhex(self.__session_token))
|
||||
self.__server_encryption_token = new_token.digest()
|
||||
new_token = hashlib.sha256()
|
||||
new_token = sha256()
|
||||
new_token.update(self.__device_secret + bytearray.fromhex(self.__session_token))
|
||||
self.__device_encryption_token = new_token.digest()
|
||||
|
||||
@ -972,7 +973,7 @@ class Myjdapi:
|
||||
:param key:
|
||||
:param data:
|
||||
"""
|
||||
signature = hmac.new(key, data.encode("utf-8"), hashlib.sha256)
|
||||
signature = new(key, data.encode("utf-8"), sha256)
|
||||
return signature.hexdigest()
|
||||
|
||||
def __decrypt(self, secret_token, data):
|
||||
@ -985,7 +986,7 @@ class Myjdapi:
|
||||
init_vector = secret_token[: len(secret_token) // 2]
|
||||
key = secret_token[len(secret_token) // 2 :]
|
||||
decryptor = AES.new(key, AES.MODE_CBC, init_vector)
|
||||
return UNPAD(decryptor.decrypt(base64.b64decode(data)))
|
||||
return UNPAD(decryptor.decrypt(b64decode(data)))
|
||||
|
||||
def __encrypt(self, secret_token, data):
|
||||
"""
|
||||
@ -998,14 +999,14 @@ class Myjdapi:
|
||||
init_vector = secret_token[: len(secret_token) // 2]
|
||||
key = secret_token[len(secret_token) // 2 :]
|
||||
encryptor = AES.new(key, AES.MODE_CBC, init_vector)
|
||||
encrypted_data = base64.b64encode(encryptor.encrypt(data))
|
||||
encrypted_data = b64encode(encryptor.encrypt(data))
|
||||
return encrypted_data.decode("utf-8")
|
||||
|
||||
def update_request_id(self):
|
||||
"""
|
||||
Updates Request_Id
|
||||
"""
|
||||
self.__request_id = int(time.time())
|
||||
self.__request_id = int(time())
|
||||
|
||||
def connect(self, email, password):
|
||||
"""Establish connection to api
|
||||
@ -1163,7 +1164,7 @@ class Myjdapi:
|
||||
)
|
||||
]
|
||||
query = query[0] + "&".join(query[1:])
|
||||
encrypted_response = requests.get(api + query, timeout=3, verify=False)
|
||||
encrypted_response = get(api + query, timeout=3, verify=False)
|
||||
else:
|
||||
params_request = []
|
||||
if params is not None:
|
||||
@ -1171,7 +1172,7 @@ class Myjdapi:
|
||||
if isinstance(param, (str, list)):
|
||||
params_request += [param]
|
||||
elif isinstance(param, (dict, bool)):
|
||||
params_request += [json.dumps(param)]
|
||||
params_request += [dumps(param)]
|
||||
else:
|
||||
params_request += [str(param)]
|
||||
params_request = {
|
||||
@ -1180,33 +1181,33 @@ class Myjdapi:
|
||||
"params": params_request,
|
||||
"rid": self.__request_id,
|
||||
}
|
||||
data = json.dumps(params_request)
|
||||
data = dumps(params_request)
|
||||
# Removing quotes around null elements.
|
||||
data = data.replace('"null"', "null")
|
||||
data = data.replace("'null'", "null")
|
||||
encrypted_data = self.__encrypt(self.__device_encryption_token, data)
|
||||
request_url = api + action + path if action is not None else api + path
|
||||
try:
|
||||
encrypted_response = requests.post(
|
||||
encrypted_response = post(
|
||||
request_url,
|
||||
headers={"Content-Type": "application/aesjson-jd; charset=utf-8"},
|
||||
data=encrypted_data,
|
||||
timeout=3,
|
||||
verify=False,
|
||||
)
|
||||
except requests.exceptions.RequestException as e:
|
||||
except RequestException as e:
|
||||
return None
|
||||
if encrypted_response.status_code != 200:
|
||||
try:
|
||||
error_msg = json.loads(encrypted_response.text)
|
||||
except json.JSONDecodeError:
|
||||
error_msg = loads(encrypted_response.text)
|
||||
except JSONDecodeError:
|
||||
try:
|
||||
error_msg = json.loads(
|
||||
error_msg = loads(
|
||||
self.__decrypt(
|
||||
self.__device_encryption_token, encrypted_response.text
|
||||
)
|
||||
)
|
||||
except json.JSONDecodeError as exc:
|
||||
except JSONDecodeError as exc:
|
||||
raise MYJDDecodeException(
|
||||
"Failed to decode response: {}", encrypted_response.text
|
||||
) from exc
|
||||
@ -1238,7 +1239,7 @@ class Myjdapi:
|
||||
response = self.__decrypt(
|
||||
self.__device_encryption_token, encrypted_response.text
|
||||
)
|
||||
jsondata = json.loads(response.decode("utf-8"))
|
||||
jsondata = loads(response.decode("utf-8"))
|
||||
if jsondata["rid"] != self.__request_id:
|
||||
self.update_request_id()
|
||||
return None
|
||||
|
Loading…
Reference in New Issue
Block a user