From b8781c87853d3246bcd7fa5d3c67e18482be7abb Mon Sep 17 00:00:00 2001
From: Leorio Paradinight <62891774+code-rgb@users.noreply.github.com>
Date: Mon, 8 Feb 2021 22:19:48 +0530
Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20iYTDL=20=20v2.5=20(#134)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
# Improvements
* added regex for faster match
* support for bot mode
* code cleanup
* Faster (switched to pyrogram cuz now it DC id bug fixed)
* Video will now output as mp4 (streamable on TG)
* Improved thumb for videos
* added [Best Audio Option] š 320 kbps
# Upstreams
# fixes
* kang.py
* deepsource fixes
---
requirements.txt | 1 -
userge/core/ext/raw_client.py | 117 +++++-----
userge/plugins/admin/gadmin.py | 4 +-
userge/plugins/bot/opinion.py | 30 +--
userge/plugins/bot/utube_inline.py | 331 ++++++++++++++---------------
userge/plugins/fun/kang.py | 6 +-
userge/plugins/fun/nsfw.py | 88 +++-----
userge/plugins/fun/quote.py | 5 +-
userge/plugins/help.py | 93 ++------
userge/plugins/misc/upload.py | 85 ++++----
userge/plugins/tools/json.py | 4 +-
userge/plugins/utils/currency.py | 4 +-
userge/plugins/utils/translate.py | 4 +-
userge/utils/__init__.py | 6 +-
userge/utils/aiohttp_helper.py | 50 ++---
userge/utils/botapi/XParser.py | 90 --------
userge/utils/botapi/__init__.py | 2 -
userge/utils/botapi/iprogress.py | 87 --------
userge/utils/botapi/rawbotapi.py | 279 ------------------------
userge/utils/progress.py | 32 ++-
20 files changed, 398 insertions(+), 920 deletions(-)
delete mode 100644 userge/utils/botapi/XParser.py
delete mode 100644 userge/utils/botapi/__init__.py
delete mode 100644 userge/utils/botapi/iprogress.py
delete mode 100644 userge/utils/botapi/rawbotapi.py
diff --git a/requirements.txt b/requirements.txt
index 16509ef72..e9e670fcf 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,6 @@ beautifulsoup4>=4.9.1
covid>=2.4.0
cowpy>=1.1.0
dnspython>=2.0.0
-emoji>=0.6.0
gitpython>=3.1.11
google-api-python-client>=1.12.8
google-auth-httplib2>=0.0.4
diff --git a/userge/core/ext/raw_client.py b/userge/core/ext/raw_client.py
index 494c9d86e..b1482fe48 100644
--- a/userge/core/ext/raw_client.py
+++ b/userge/core/ext/raw_client.py
@@ -11,8 +11,9 @@
__all__ = ['RawClient']
import asyncio
-import time
-from typing import Optional, Dict
+from math import floor
+from typing import Optional, Dict, List
+from time import time, perf_counter, sleep
import pyrogram.raw.functions as funcs
import pyrogram.raw.types as types
@@ -29,11 +30,8 @@
class RawClient(Client):
""" userge raw client """
DUAL_MODE = False
- LAST_OUTGOING_TIME = time.time()
-
+ LAST_OUTGOING_TIME = time()
REQ_LOGS: Dict[int, 'ChatReq'] = {}
- DELAY_BET_MSG_REQ = 1
- MSG_REQ_PER_MIN = 20
REQ_LOCK = asyncio.Lock()
def __init__(self, bot: Optional['userge.core.client.UsergeBot'] = None, **kwargs) -> None:
@@ -46,69 +44,92 @@ async def send(self, data: TLObject, retries: int = Session.MAX_RETRIES,
timeout: float = Session.WAIT_TIMEOUT, sleep_threshold: float = None):
key = 0
if isinstance(data, (funcs.messages.SendMessage,
+ funcs.messages.SendMedia,
+ funcs.messages.SendMultiMedia,
funcs.messages.EditMessage,
funcs.messages.ForwardMessages)):
if isinstance(data, funcs.messages.ForwardMessages):
tmp = data.to_peer
else:
tmp = data.peer
- if isinstance(tmp, (types.InputPeerChannel, types.InputPeerChannelFromMessage)):
- key = int(tmp.channel_id)
- elif isinstance(tmp, types.InputPeerChat):
- key = int(tmp.chat_id)
- elif isinstance(tmp, (types.InputPeerUser, types.InputPeerUserFromMessage)):
- key = int(tmp.user_id)
+ if isinstance(data, funcs.messages.SendMedia) and isinstance(
+ data.media, (types.InputMediaUploadedDocument,
+ types.InputMediaUploadedPhoto)):
+ tmp = None
+ if tmp:
+ if isinstance(tmp, (types.InputPeerChannel, types.InputPeerChannelFromMessage)):
+ key = int(tmp.channel_id)
+ elif isinstance(tmp, types.InputPeerChat):
+ key = int(tmp.chat_id)
+ elif isinstance(tmp, (types.InputPeerUser, types.InputPeerUserFromMessage)):
+ key = int(tmp.user_id)
elif isinstance(data, funcs.channels.DeleteMessages):
if isinstance(data.channel, (types.InputChannel, types.InputChannelFromMessage)):
key = int(data.channel.channel_id)
if key:
- async def slp(to_sl: float) -> None:
- if to_sl > 0.1:
- if to_sl > 1:
- _LOG.info(_LOG_STR, to_sl, key)
- else:
- _LOG.debug(_LOG_STR, to_sl, key)
- await asyncio.sleep(to_sl)
async with self.REQ_LOCK:
- if key in self.REQ_LOGS:
- chat_req = self.REQ_LOGS[key]
- else:
- chat_req = self.REQ_LOGS[key] = ChatReq()
- diff = chat_req.small_diff
- if 0 < diff < self.DELAY_BET_MSG_REQ:
- await slp(1 - diff)
- diff = chat_req.big_diff
- if diff >= 60:
- chat_req.reset()
- elif chat_req.count > self.MSG_REQ_PER_MIN:
- await slp(60 - diff)
- chat_req.reset()
- else:
- chat_req.update()
+ try:
+ req = self.REQ_LOGS[key]
+ except KeyError:
+ req = self.REQ_LOGS[key] = ChatReq()
+ async with req.lock:
+ now = perf_counter()
+ req.update(now - 60)
+ if req.has:
+ to_sl = 0.0
+ diff = now - req.last
+ if 0 < diff < 1:
+ to_sl = 1 - diff
+ diff = now - req.first
+ if req.count > 18:
+ to_sl = max(to_sl, 60 - diff)
+ if to_sl > 0:
+ if to_sl > 1:
+ _LOG.info(_LOG_STR, to_sl, key)
+ else:
+ _LOG.debug(_LOG_STR, to_sl, key)
+ await asyncio.sleep(to_sl)
+ now += to_sl
+ count = 0
+ counter = floor(now - 1)
+ for r in self.REQ_LOGS.values():
+ if r.has and r.last > counter:
+ count += 1
+ if count > 25:
+ _LOG.info(_LOG_STR, 1, key)
+ sleep(1)
+ now += 1
+ req.add(now)
return await super().send(data, retries, timeout, sleep_threshold)
class ChatReq:
def __init__(self) -> None:
- self._first = self._last = time.time()
- self._count = 0
+ self._lock = asyncio.Lock()
+ self._logs: List[float] = []
+
+ @property
+ def lock(self):
+ return self._lock
+
+ @property
+ def has(self) -> bool:
+ return len(self._logs) != 0
@property
- def small_diff(self) -> float:
- return time.time() - self._last
+ def first(self) -> float:
+ return self._logs[0]
@property
- def big_diff(self) -> float:
- return time.time() - self._first
+ def last(self) -> Optional[float]:
+ return self._logs[-1]
@property
- def count(self) -> float:
- return self._count
+ def count(self) -> int:
+ return len(self._logs)
- def reset(self) -> None:
- self._first = self._last = time.time()
- self._count = 1
+ def add(self, log: float) -> None:
+ self._logs.append(log)
- def update(self) -> None:
- self._last = time.time()
- self._count += 1
+ def update(self, t: float) -> None:
+ self._logs = [i for i in self._logs if i > t]
\ No newline at end of file
diff --git a/userge/plugins/admin/gadmin.py b/userge/plugins/admin/gadmin.py
index 4e9d069b6..883b2d3c7 100644
--- a/userge/plugins/admin/gadmin.py
+++ b/userge/plugins/admin/gadmin.py
@@ -4,7 +4,6 @@
import os
import time
-from emoji import get_emoji_regexp
from pyrogram.errors import (
FloodWait,
PeerIdInvalid,
@@ -15,6 +14,7 @@
from pyrogram.types import ChatPermissions
from userge import Message, userge
+from userge.utils.functions import get_emoji_regex
CHANNEL = userge.getCLogger(__name__)
@@ -47,7 +47,7 @@ async def promote_usr(message: Message):
)
return
if custom_rank:
- custom_rank = get_emoji_regexp().sub("", custom_rank)
+ custom_rank = get_emoji_regex().sub("", custom_rank)
if len(custom_rank) > 15:
custom_rank = custom_rank[:15]
try:
diff --git a/userge/plugins/bot/opinion.py b/userge/plugins/bot/opinion.py
index fe07d814b..06f1a93c1 100644
--- a/userge/plugins/bot/opinion.py
+++ b/userge/plugins/bot/opinion.py
@@ -2,14 +2,15 @@
# All rights reserved.
+import asyncio
import os
import ujson
from pyrogram import filters
+from pyrogram.errors import BadRequest, FloodWait
from pyrogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
from userge import Config, Message, userge
-from userge.utils import xbot
if not os.path.exists("userge/xcache"):
os.mkdir("userge/xcache")
@@ -84,10 +85,8 @@ async def choice_cb(_, c_q: CallbackQuery):
data[str(opinion_id)] = view_data
with open(PATH, "w") as outfile:
ujson.dump(data, outfile)
-
agree_data += f" {view_data[1]['agree']}"
disagree_data += f" {view_data[1]['disagree']}"
-
opinion_data = [
[
InlineKeyboardButton(agree_data, callback_data=f"op_y_{opinion_id}"),
@@ -95,18 +94,14 @@ async def choice_cb(_, c_q: CallbackQuery):
],
[InlineKeyboardButton("š Stats", callback_data=f"opresult_{opinion_id}")],
]
-
- await xbot.edit_inline_reply_markup(
- c_q.inline_message_id, reply_markup=InlineKeyboardMarkup(opinion_data)
- )
-
- # await userge.bot.edit_inline_reply_markup(
- # c_q.inline_message_id, reply_markup=InlineKeyboardMarkup(opinion_data)
- # )
- # except FloodWait as e:
- # await asyncio.sleep(e.x)
- # except BadRequest:
- # return
+ try:
+ await c_q.edit_message_reply_markup(
+ reply_markup=InlineKeyboardMarkup(opinion_data)
+ )
+ except FloodWait as e:
+ await asyncio.sleep(e.x)
+ except BadRequest:
+ return
@userge.bot.on_callback_query(filters.regex(pattern=r"^opresult_(\d+)$"))
async def choice_result_cb(_, c_q: CallbackQuery):
@@ -124,10 +119,7 @@ async def choice_result_cb(_, c_q: CallbackQuery):
msg += f"ā¢ š¤ `{total} People voted`\n\n"
msg += f"ā¢ š `{agreed}% People Agreed`\n\n"
msg += f"ā¢ š `{disagreed}% People Disagreed`\n\n"
-
- await xbot.edit_inline_text(c_q.inline_message_id, msg)
-
- # await userge.bot.edit_inline_text(c_q.inline_message_id, msg)
+ await c_q.edit_message_text(msg)
else:
a = await userge.get_me()
if a.username:
diff --git a/userge/plugins/bot/utube_inline.py b/userge/plugins/bot/utube_inline.py
index 29e4fb0ca..c0e381698 100644
--- a/userge/plugins/bot/utube_inline.py
+++ b/userge/plugins/bot/utube_inline.py
@@ -1,15 +1,29 @@
+""" Download Youtube Video/ Audio in a User friendly interface """
+# -------------------------- #
+# Modded ytdl by code-rgb
+# -------------------------- #
+
import glob
import os
+from collections import defaultdict
from pathlib import Path
+from re import search
from time import time
-from urllib.parse import parse_qs, urlparse
import ujson
import youtube_dl
from pyrogram import filters
-from pyrogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
+from pyrogram.types import (
+ CallbackQuery,
+ InlineKeyboardButton,
+ InlineKeyboardMarkup,
+ InputMediaAudio,
+ InputMediaPhoto,
+ InputMediaVideo,
+)
from wget import download
from youtube_dl.utils import DownloadError
+from youtubesearchpython import VideosSearch
from userge import Config, Message, pool, userge
from userge.utils import (
@@ -18,9 +32,8 @@
get_response,
humanbytes,
post_to_telegraph,
+ rand_key,
sublists,
- xbot,
- xmedia,
)
from ..misc.upload import upload
@@ -28,15 +41,17 @@
LOGGER = userge.getLogger(__name__)
CHANNEL = userge.getCLogger(__name__)
BASE_YT_URL = "https://www.youtube.com/watch?v="
+YOUTUBE_REGEX = r"(?:(?:https?:)?\/\/)?(?:(?:www|m)\.)?(?:(?:youtube\.com|youtu.be))(?:\/(?:[\w\-]+\?v=|embed\/|v\/)?)([\w\-]+)(?:\S+)?"
PATH = "./userge/xcache/ytsearch.json"
class YT_Search_X:
def __init__(self):
if not os.path.exists(PATH):
- d = {}
- ujson.dump(d, open(PATH, "w"))
- self.db = ujson.load(open(PATH))
+ with open(PATH, "w") as f_x:
+ ujson.dump({}, f_x)
+ with open(PATH) as yt_db:
+ self.db = ujson.load(yt_db)
def store_(self, rnd_id: str, results: dict):
self.db[rnd_id] = results
@@ -58,7 +73,6 @@ async def get_ytthumb(videoid: str):
"mqdefault.jpg",
"default.jpg", # Worst quality
]
-
thumb_link = "https://i.imgur.com/4LwPLai.png"
for qualiy in thumb_quality:
link = f"https://i.ytimg.com/vi/{videoid}/{qualiy}"
@@ -85,16 +99,61 @@ async def iytdl_inline(message: Message):
input_url = reply.text
elif reply.caption:
input_url = reply.caption
-
if not input_url:
return await message.err("Input or reply to a valid youtube URL", del_in=5)
await message.edit(f"š Searching Youtube for: '{input_url}'
")
- bot = await userge.bot.get_me()
- x = await userge.get_inline_bot_results(bot.username, f"ytdl {input_url.strip()}")
- await message.delete()
- await userge.send_inline_bot_result(
- chat_id=message.chat.id, query_id=x.query_id, result_id=x.results[0].id
- )
+ input_url = input_url.strip()
+ if message.client.is_bot:
+ link = get_yt_video_id(input_url)
+ if link is None:
+ search_ = VideosSearch(input_url, limit=15)
+ resp = (search_.result()).get("result")
+ if len(resp) == 0:
+ await message.err(f'No Results found for "{input_url}"', del_in=7)
+ return
+ outdata = await result_formatter(resp)
+ key_ = rand_key()
+ ytsearch_data.store_(key_, outdata)
+ buttons = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text=f"1 / {len(outdata)}",
+ callback_data=f"ytdl_next_{key_}_1",
+ )
+ ],
+ [
+ InlineKeyboardButton(
+ text="š List all",
+ callback_data=f"ytdl_listall_{key_}_1",
+ ),
+ InlineKeyboardButton(
+ text="ā¬ļø Download",
+ callback_data=f'ytdl_download_{outdata[1]["video_id"]}_0',
+ ),
+ ],
+ ]
+ )
+ caption = outdata[1]["message"]
+ photo = outdata[1]["thumb"]
+ else:
+ caption, buttons = await download_button(link, body=True)
+ photo = await get_ytthumb(link)
+
+ await userge.bot.send_photo(
+ message.chat.id,
+ photo=photo,
+ caption=caption,
+ reply_markup=buttons,
+ )
+ await message.delete()
+ else:
+ bot = await userge.bot.get_me()
+ x = await userge.get_inline_bot_results(bot.username, f"ytdl {input_url}")
+ await message.delete()
+ await userge.send_inline_bot_result(
+ chat_id=message.chat.id, query_id=x.query_id, result_id=x.results[0].id
+ )
if userge.has_bot:
@@ -110,26 +169,27 @@ async def ytdl_download_callback(c_q: CallbackQuery):
choice_id = int(choice_id)
if choice_id == 0:
await c_q.answer("š Processing...", show_alert=False)
- await xbot.edit_inline_reply_markup(
- c_q.inline_message_id, reply_markup=(await download_button(yt_code))
+ await c_q.edit_message_reply_markup(
+ reply_markup=(await download_button(yt_code))
)
return
else:
choice_id = None
-
startTime = time()
downtype = c_q.matches[0].group(3)
media_type = "Video" if downtype == "v" else "Audio"
callback_continue = f"Downloading {media_type} Please Wait..."
- callback_continue += f"\n\nFormat Code : {choice_id or 'bestaudio/best'}"
+ frmt_text = choice_id or (
+ "bestaudio/best [mp4]" if downtype == "v" else "320 Kbps"
+ )
+ callback_continue += f"\n\nFormat Code : {frmt_text}"
await c_q.answer(callback_continue, show_alert=True)
upload_msg = await userge.send_message(Config.LOG_CHANNEL_ID, "Uploading...")
yt_url = BASE_YT_URL + yt_code
- await xbot.edit_inline_caption(
- c_q.inline_message_id,
- caption=(
+ await c_q.edit_message_text(
+ text=(
f"**ā¬ļø Downloading {media_type} ...**"
- f"\n\nš [Link]({yt_url})\nš Format Code : {choice_id or 'bestaudio/best'}"
+ f"\n\nš [Link]({yt_url})\nš Format Code : {frmt_text}"
),
)
if downtype == "v":
@@ -139,40 +199,42 @@ async def ytdl_download_callback(c_q: CallbackQuery):
if retcode != 0:
return await upload_msg.edit(str(retcode))
_fpath = ""
+ thumb_pic = None
for _path in glob.glob(os.path.join(Config.DOWN_PATH, str(startTime), "*")):
- if not _path.lower().endswith((".jpg", ".png", ".webp")):
+ if _path.lower().endswith((".jpg", ".png", ".webp")):
+ thumb_pic = _path
+ else:
_fpath = _path
if not _fpath:
await upload_msg.err("nothing found !")
return
- thumb_ = str(download(await get_ytthumb(yt_code))) if downtype == "v" else None
+ if not thumb_pic and downtype == "v":
+ thumb_pic = str(download(await get_ytthumb(yt_code)))
uploaded_media = await upload(
upload_msg,
- Path(_fpath),
- logvid=False,
- custom_thumb=thumb_,
- inline_id=c_q.inline_message_id,
+ path=Path(_fpath),
+ callback=c_q,
+ custom_thumb=thumb_pic,
+ log=False,
)
refresh_vid = await userge.bot.get_messages(
Config.LOG_CHANNEL_ID, uploaded_media.message_id
)
f_id = get_file_id(refresh_vid)
if downtype == "v":
- await xbot.edit_inline_media(
- c_q.inline_message_id,
+ await c_q.edit_message_media(
media=(
- await xmedia.InputMediaVideo(
- file_id=f_id,
+ InputMediaVideo(
+ media=f_id,
caption=f"š¹ [{uploaded_media.caption}]({yt_url})",
)
),
)
else: # Audio
- await xbot.edit_inline_media(
- c_q.inline_message_id,
+ await c_q.edit_message_media(
media=(
- await xmedia.InputMediaAudio(
- file_id=f_id,
+ InputMediaAudio(
+ media=f_id,
caption=f"šµ [{uploaded_media.caption}]({yt_url})",
)
),
@@ -201,11 +263,10 @@ async def ytdl_callback(c_q: CallbackQuery):
del_back = index == 1
await c_q.answer()
back_vid = search_data.get(str(index))
- await xbot.edit_inline_media(
- c_q.inline_message_id,
+ await c_q.edit_message_media(
media=(
- await xmedia.InputMediaPhoto(
- file_id=back_vid.get("thumb"),
+ InputMediaPhoto(
+ media=back_vid.get("thumb"),
caption=back_vid.get("message"),
)
),
@@ -223,11 +284,10 @@ async def ytdl_callback(c_q: CallbackQuery):
return await c_q.answer("That's All Folks !", show_alert=True)
await c_q.answer()
front_vid = search_data.get(str(index))
- await xbot.edit_inline_media(
- c_q.inline_message_id,
+ await c_q.edit_message_media(
media=(
- await xmedia.InputMediaPhoto(
- file_id=front_vid.get("thumb"),
+ InputMediaPhoto(
+ media=front_vid.get("thumb"),
caption=front_vid.get("message"),
)
),
@@ -238,7 +298,6 @@ async def ytdl_callback(c_q: CallbackQuery):
total=total,
),
)
-
elif choosen_btn == "listall":
await c_q.answer("View Changed to: š List", show_alert=False)
list_res = ""
@@ -248,11 +307,10 @@ async def ytdl_callback(c_q: CallbackQuery):
a_title=f"Showing {total} youtube video results for the given query ...",
content=list_res,
)
- await xbot.edit_inline_media(
- c_q.inline_message_id,
+ await c_q.edit_message_media(
media=(
- await xmedia.InputMediaPhoto(
- file_id=search_data.get("1").get("thumb"),
+ InputMediaPhoto(
+ media=search_data.get("1").get("thumb"),
# caption=f"[Click to view]({})",
)
),
@@ -273,16 +331,14 @@ async def ytdl_callback(c_q: CallbackQuery):
]
),
)
-
else: # Detailed
index = 1
await c_q.answer("View Changed to: š° Detailed", show_alert=False)
first = search_data.get(str(index))
- await xbot.edit_inline_media(
- c_q.inline_message_id,
+ await c_q.edit_message_media(
media=(
- await xmedia.InputMediaPhoto(
- file_id=first.get("thumb"),
+ InputMediaPhoto(
+ media=first.get("thumb"),
caption=first.get("message"),
)
),
@@ -306,7 +362,7 @@ def _tubeDl(url: str, starttime, uid=None):
Config.DOWN_PATH, str(starttime), "%(title)s-%(format)s.%(ext)s"
),
"logger": LOGGER,
- "format": "{}+bestaudio/best".format(uid or "bestvideo"),
+ "format": f"{uid or 'bestvideo[ext=mp4]'}+bestaudio[ext=m4a]/best[ext=mp4]",
"writethumbnail": True,
"prefer_ffmpeg": True,
"postprocessors": [
@@ -339,7 +395,7 @@ def _mp3Dl(url: str, starttime, uid):
{
"key": "FFmpegExtractAudio",
"preferredcodec": "mp3",
- "preferredquality": str(uid),
+ "preferredquality": uid or "320",
},
{"key": "EmbedThumbnail"}, # ERROR: Conversion failed!
{"key": "FFmpegMetadata"},
@@ -356,39 +412,12 @@ def _mp3Dl(url: str, starttime, uid):
return dloader
-# initial version: http://stackoverflow.com/a/7936523/617185 \
-# by Mikhail Kashkin (http://stackoverflow.com/users/85739/mikhail-kashkin)
-#
-# Returns Video_ID extracting from the given url of Youtube
-# Examples of URLs:
-# Valid:
-# 'http://youtu.be/_lOT2p_FCvA',
-# 'www.youtube.com/watch?v=_lOT2p_FCvA&feature=feedu',
-# 'http://www.youtube.com/embed/_lOT2p_FCvA',
-# 'http://www.youtube.com/v/_lOT2p_FCvA?version=3&hl=en_US',
-# 'https://www.youtube.com/watch?v=rTHlyTphWP0&index=6&list=PLjeDyYvG6-40qawYNR4juzvSOg-ezZ2a6',
-# 'youtube.com/watch?v=_lOT2p_FCvA',
-#
-# Invalid:
-# 'youtu.be/watch?v=_lOT2p_FCvA'
-
-
def get_yt_video_id(url: str):
- if url.startswith(("youtu", "www")):
- url = "http://" + url
- yt_link = None
- try:
- query = urlparse(url)
- if "youtube" in query.hostname:
- if query.path == "/watch":
- yt_link = parse_qs(query.query)["v"][0]
- if query.path.startswith(("/embed/", "/v/")):
- yt_link = query.path.split("/")[2]
- elif "youtu.be" in query.hostname:
- yt_link = query.path[1:]
- except TypeError:
- pass
- return yt_link
+ # https://regex101.com/r/boXuXb/1
+ match = search(YOUTUBE_REGEX, url)
+ if match:
+ return match.group(1)
+ return
async def result_formatter(results: list):
@@ -409,12 +438,14 @@ async def result_formatter(results: list):
if upld:
out += "āÆ Uploader: "
out += f'{upld.get("name")}'
+ v_deo_id = r.get("id")
output[index] = dict(
message=out,
thumb=thumb,
- video_id=r.get("id"),
- list_view=f'{index}. {r.get("accessibility").get("title")}
',
+ video_id=v_deo_id,
+ list_view=f'{index}. {r.get("accessibility").get("title")}
',
)
+
return output
@@ -450,93 +481,61 @@ def yt_search_btns(
@pool.run_in_thread
def download_button(vid: str, body: bool = False):
- x = youtube_dl.YoutubeDL({"no-playlist": True}).extract_info(
+ vid_data = youtube_dl.YoutubeDL({"no-playlist": True}).extract_info(
BASE_YT_URL + vid, download=False
)
- ###
- (
- format_144,
- format_240,
- format_360,
- format_720,
- format_1080,
- format_1440,
- format_2160,
- ) = [0 for _ in range(7)]
- btn = [
+ buttons = [
[
InlineKeyboardButton(
- "āļø BEST (Video + Audio)", callback_data=f"ytdl_download_{vid}_best_v"
- )
+ "āļø BEST VIDEO", callback_data=f"ytdl_download_{vid}_best_v"
+ ),
+ InlineKeyboardButton(
+ "āļø BEST AUDIO", callback_data=f"ytdl_download_{vid}_best_a"
+ ),
]
]
- audio, format_data = {}, {}
- ###
- for video in x["formats"]:
- if video.get("ext") == "mp4":
- f_note = video.get("format_note")
- fr_id = int(video.get("format_id"))
- if f_note in ("2160p", "2160p60") and fr_id > format_2160:
- format_2160 = fr_id
- if f_note in ("1440p", "1440p60") and fr_id > format_1440:
- format_1440 = fr_id
- if f_note in ("1080p", "1080p60") and fr_id > format_1080:
- format_1080 = fr_id
- if f_note in ("720p", "720p60") and fr_id > format_720:
- format_720 = fr_id
- if f_note in ("360p", "360p60") and fr_id > format_360:
- format_360 = fr_id
- if f_note in ("240p", "240p60") and fr_id > format_240:
- format_240 = fr_id
- if f_note in ("144p", "144p60") and fr_id > format_144:
- format_144 = fr_id
- format_data[
- fr_id
- ] = f'š¹ {f_note} ({humanbytes(video.get("filesize")) or "N/A"})'
-
+ # ------------------------------------------------ #
+ qual_dict = defaultdict(lambda: defaultdict(int))
+ qual_list = ["144p", "360p", "720p", "1080p", "1440p"]
+ audio_dict = {}
+ # ------------------------------------------------ #
+ for video in vid_data["formats"]:
+ fr_note = video.get("format_note")
+ fr_id = int(video.get("format_id"))
+ fr_size = video.get("filesize")
+ for frmt_ in qual_list:
+ if fr_note in (frmt_, frmt_ + "60"):
+ qual_dict[frmt_][fr_id] = fr_size
if video.get("acodec") != "none":
- bitrrate = video.get("abr")
- if bitrrate is not None:
- audio[
- int(bitrrate)
- ] = f'šµ {bitrrate}Kbps ({humanbytes(video.get("filesize")) or "N/A"})'
-
- btn += sublists(
- [
- InlineKeyboardButton(
- format_data.get(qual_), callback_data=f"ytdl_download_{vid}_{qual_}_v"
+ bitrrate = int(video.get("abr", 0))
+ if bitrrate != 0:
+ audio_dict[
+ bitrrate
+ ] = f"šµ {bitrrate}Kbps ({humanbytes(fr_size) or 'N/A'})"
+
+ video_btns = []
+ for frmt in qual_list:
+ frmt_dict = qual_dict[frmt]
+ if len(frmt_dict) != 0:
+ frmt_id = sorted(list(frmt_dict))[-1]
+ frmt_size = humanbytes(frmt_dict.get(frmt_id)) or "N/A"
+ video_btns.append(
+ InlineKeyboardButton(
+ f"š¹ {frmt} ({frmt_size})",
+ callback_data=f"ytdl_download_{vid}_{frmt_id}_v",
+ )
)
- for qual_ in [
- format_144,
- format_240,
- format_360,
- format_720,
- format_1080,
- format_1440,
- format_2160,
- ]
- if qual_ != 0
- ],
- width=2,
- )
- btn += sublists(
+ buttons += sublists(video_btns, width=2)
+ buttons += sublists(
[
InlineKeyboardButton(
- audio.get(key_), callback_data=f"ytdl_download_{vid}_{key_}_a"
+ audio_dict.get(key_), callback_data=f"ytdl_download_{vid}_{key_}_a"
)
- for key_ in sorted(audio.keys())
+ for key_ in sorted(audio_dict.keys())
],
width=2,
)
if body:
- vid_body = f"[{x.get('title')}]({x.get('webpage_url')})"
-
- # ERROR Media Caption Too Long
- # {x.get("description")}
- # āÆ Duration: {x.get('duration')}
- # āÆ Views: {x.get('view_count')}
- # āÆ Upload date: {x.get('upload_date')}
- # āÆ Uploader: [{x.get('uploader')}]({x.get('uploader_url')})
-
- return vid_body, InlineKeyboardMarkup(btn)
- return InlineKeyboardMarkup(btn)
+ vid_body = f"[{vid_data.get('title')}]({vid_data.get('webpage_url')})"
+ return vid_body, InlineKeyboardMarkup(buttons)
+ return InlineKeyboardMarkup(buttons)
diff --git a/userge/plugins/fun/kang.py b/userge/plugins/fun/kang.py
index 3c602318d..372b1ecac 100644
--- a/userge/plugins/fun/kang.py
+++ b/userge/plugins/fun/kang.py
@@ -12,9 +12,9 @@
import os
import random
-import emoji
from bs4 import BeautifulSoup as bs
from PIL import Image
+from pyrogram import emoji
from pyrogram.errors import StickersetInvalid, YouBlockedUser
from pyrogram.raw.functions.messages import GetStickerSet
from pyrogram.raw.types import InputStickerSetShortName
@@ -84,7 +84,9 @@ async def kang_(message: Message):
else:
emoji_ = args[0]
- if emoji_ and emoji_ not in emoji.UNICODE_EMOJI:
+ if emoji_ and emoji_ not in (
+ getattr(emoji, _) for _ in dir(emoji) if not _.startswith("_")
+ ):
emoji_ = None
if not emoji_:
emoji_ = "š¤"
diff --git a/userge/plugins/fun/nsfw.py b/userge/plugins/fun/nsfw.py
index ab83bee10..f52b423e0 100644
--- a/userge/plugins/fun/nsfw.py
+++ b/userge/plugins/fun/nsfw.py
@@ -1,8 +1,14 @@
from pyrogram import filters
-from pyrogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
+from pyrogram.errors import MessageNotModified
+from pyrogram.types import (
+ CallbackQuery,
+ InlineKeyboardButton,
+ InlineKeyboardMarkup,
+ InputMediaPhoto,
+)
from userge import Config, userge
-from userge.utils import get_file_id, xbot, xmedia
+from userge.utils import get_file_id
async def age_verification(msg):
@@ -30,7 +36,6 @@ async def age_verification_true(_, c_q: CallbackQuery):
await c_q.answer("Yes I'm 18+", show_alert=False)
msg = await userge.bot.get_messages("useless_x", 19)
f_id = get_file_id(msg)
-
buttons = [
[
InlineKeyboardButton(
@@ -39,30 +44,16 @@ async def age_verification_true(_, c_q: CallbackQuery):
)
]
]
- await xbot.edit_inline_media(
- c_q.inline_message_id,
- media=(
- await xmedia.InputMediaPhoto(
- file_id=f_id,
+ try:
+ await c_q.edit_message_media(
+ media=InputMediaPhoto(
+ media=f_id,
caption="Set ALLOW_NSFW
= True in Heroku Vars to access this plugin",
- )
- ),
- reply_markup=InlineKeyboardMarkup(buttons),
- )
- # """
- # try:
-
- # await c_q.edit_message_media(
- # media=InputMediaPhoto(
- # media=f_id,
- # caption="Set ALLOW_NSFW
= True in Heroku Vars to access this plugin",
- # ),
- # reply_markup=InlineKeyboardMarkup(buttons),
- # )
-
- # except MessageNotModified:
- # pass
- # """
+ ),
+ reply_markup=InlineKeyboardMarkup(buttons),
+ )
+ except MessageNotModified:
+ pass
@userge.bot.on_callback_query(filters.regex(pattern=r"^age_verification_false"))
async def age_verification_false(_, c_q: CallbackQuery):
@@ -76,7 +67,6 @@ async def age_verification_false(_, c_q: CallbackQuery):
msg = await userge.bot.get_messages("useless_x", 20)
f_id = get_file_id(msg)
img_text = "GO AWAY KID !"
-
buttons = [
[
InlineKeyboardButton(
@@ -85,21 +75,13 @@ async def age_verification_false(_, c_q: CallbackQuery):
)
]
]
- await xbot.edit_inline_media(
- c_q.inline_message_id,
- media=(await xmedia.InputMediaPhoto(file_id=f_id, caption=img_text)),
- reply_markup=InlineKeyboardMarkup(buttons),
- )
-
- # """
- # try:
- # await c_q.edit_message_media(
- # media=InputMediaPhoto(media=f_id, caption=img_text),
- # reply_markup=InlineKeyboardMarkup(buttons),
- # )
- # except MessageNotModified:
- # return
- # """
+ try:
+ await c_q.edit_message_media(
+ media=InputMediaPhoto(media=f_id, caption=img_text),
+ reply_markup=InlineKeyboardMarkup(buttons),
+ )
+ except MessageNotModified:
+ return
@userge.bot.on_callback_query(filters.regex(pattern=r"^chg_of_decision_"))
async def chg_of_decision_(_, c_q: CallbackQuery):
@@ -113,7 +95,6 @@ async def chg_of_decision_(_, c_q: CallbackQuery):
msg = await userge.bot.get_messages("useless_x", 21)
f_id = get_file_id(msg)
img_text = "ARE YOU OLD ENOUGH FOR THIS ?"
-
buttons = [
[
InlineKeyboardButton(
@@ -124,17 +105,10 @@ async def chg_of_decision_(_, c_q: CallbackQuery):
),
]
]
- await xbot.edit_inline_media(
- c_q.inline_message_id,
- media=(await xmedia.InputMediaPhoto(file_id=f_id, caption=img_text)),
- reply_markup=InlineKeyboardMarkup(buttons),
- )
- # """
- # try:
- # await c_q.edit_message_media(
- # media=InputMediaPhoto(media=f_id, caption=img_text),
- # reply_markup=InlineKeyboardMarkup(buttons),
- # )
- # except MessageNotModified:
- # pass
- # """
+ try:
+ await c_q.edit_message_media(
+ media=InputMediaPhoto(media=f_id, caption=img_text),
+ reply_markup=InlineKeyboardMarkup(buttons),
+ )
+ except MessageNotModified:
+ pass
diff --git a/userge/plugins/fun/quote.py b/userge/plugins/fun/quote.py
index 6a30d4c2b..05f6d9628 100644
--- a/userge/plugins/fun/quote.py
+++ b/userge/plugins/fun/quote.py
@@ -46,7 +46,10 @@ async def quotecmd(message: Message):
await message.edit(message.input_str)
else:
args = message.input_str
- quote_list.append(message.message_id) if self_mid else await message.delete()
+ if self_mid:
+ quote_list.append(message.message_id)
+ else:
+ await message.delete()
if not args and len(quote_list) == 0:
await message.err("Reply to a message or provide an input to quote !", del_in=5)
return
diff --git a/userge/plugins/help.py b/userge/plugins/help.py
index 046fbd29b..31443b079 100644
--- a/userge/plugins/help.py
+++ b/userge/plugins/help.py
@@ -24,9 +24,10 @@
from youtubesearchpython import VideosSearch
from userge import Config, Message, get_collection, userge
+from userge.core.ext import RawClient
from userge.utils import get_file_id, get_response
from userge.utils import parse_buttons as pb
-from userge.utils import rand_key, xbot
+from userge.utils import rand_key
from .bot.alive import Bot_Alive
from .bot.gogo import Anime
@@ -198,13 +199,9 @@ async def callback_next_prev(callback_query: CallbackQuery):
)
elif len(pos_list) == 3:
_, buttons = plugin_data(cur_pos, p_num)
- await xbot.edit_inline_reply_markup(
- callback_query.inline_message_id,
- reply_markup=InlineKeyboardMarkup(buttons),
+ await callback_query.edit_message_reply_markup(
+ reply_markup=InlineKeyboardMarkup(buttons)
)
- # await callback_query.edit_message_reply_markup(
- # reply_markup=InlineKeyboardMarkup(buttons)
- # )
@userge.bot.on_callback_query(filters.regex(pattern=r"back\((.+)\)"))
@check_owner
@@ -221,17 +218,10 @@ async def callback_back(callback_query: CallbackQuery):
text, buttons = category_data(cur_pos)
elif len(pos_list) == 4:
text, buttons = plugin_data(cur_pos)
-
- await xbot.edit_inline_text(
- callback_query.inline_message_id,
- text=text,
- reply_markup=InlineKeyboardMarkup(buttons),
+ await callback_query.edit_message_text(
+ text, reply_markup=InlineKeyboardMarkup(buttons)
)
- # await callback_query.edit_message_text(
- # text, reply_markup=InlineKeyboardMarkup(buttons)
- # )
-
@userge.bot.on_callback_query(filters.regex(pattern=r"enter\((.+)\)"))
@check_owner
async def callback_enter(callback_query: CallbackQuery):
@@ -243,17 +233,10 @@ async def callback_enter(callback_query: CallbackQuery):
text, buttons = plugin_data(cur_pos)
elif len(pos_list) == 4:
text, buttons = filter_data(cur_pos)
-
- await xbot.edit_inline_text(
- callback_query.inline_message_id,
- text=text,
- reply_markup=InlineKeyboardMarkup(buttons),
+ await callback_query.edit_message_text(
+ text, reply_markup=InlineKeyboardMarkup(buttons)
)
- # await callback_query.edit_message_text(
- # text, reply_markup=InlineKeyboardMarkup(buttons)
- # )
-
@userge.bot.on_callback_query(
filters.regex(pattern=r"((?:un)?load|(?:en|dis)able)\((.+)\)")
)
@@ -273,52 +256,38 @@ async def callback_manage(callback_query: CallbackQuery):
plg = userge.manager.plugins[pos_list[-1]]
await getattr(plg, task)()
text, buttons = plugin_data(cur_pos)
- await xbot.edit_inline_text(
- callback_query.inline_message_id,
- text=text,
- reply_markup=InlineKeyboardMarkup(buttons),
+ await callback_query.edit_message_text(
+ text, reply_markup=InlineKeyboardMarkup(buttons)
)
- # await callback_query.edit_message_text(
- # text, reply_markup=InlineKeyboardMarkup(buttons)
- # )
@userge.bot.on_callback_query(filters.regex(pattern=r"^mm$"))
@check_owner
async def callback_mm(callback_query: CallbackQuery):
-
- await xbot.edit_inline_text(
- callback_query.inline_message_id,
- text=" šššššš-š š ššš” š šš”šØ ",
+ await callback_query.edit_message_text(
+ " šššššš-š š ššš” š šš”šØ ",
reply_markup=InlineKeyboardMarkup(main_menu_buttons()),
)
- # await callback_query.edit_message_text(
- # " šššššš-š š ššš” š šš”šØ ",
- # reply_markup=InlineKeyboardMarkup(main_menu_buttons()),
- # )
-
@userge.bot.on_callback_query(filters.regex(pattern=r"^chgclnt$"))
@check_owner
async def callback_chgclnt(callback_query: CallbackQuery):
+ if not RawClient.DUAL_MODE:
+ return await callback_query.answer(
+ "you using [BOT MODE], can't change client.", show_alert=True
+ )
if Config.USE_USER_FOR_CLIENT_CHECKS:
Config.USE_USER_FOR_CLIENT_CHECKS = False
- else:
+ elif RawClient.DUAL_MODE:
Config.USE_USER_FOR_CLIENT_CHECKS = True
await SAVED_SETTINGS.update_one(
{"_id": "CURRENT_CLIENT"},
{"$set": {"is_user": Config.USE_USER_FOR_CLIENT_CHECKS}},
upsert=True,
)
-
- await xbot.edit_inline_reply_markup(
- callback_query.inline_message_id,
- reply_markup=InlineKeyboardMarkup(main_menu_buttons()),
+ await callback_query.edit_message_reply_markup(
+ reply_markup=InlineKeyboardMarkup(main_menu_buttons())
)
- # await callback_query.edit_message_reply_markup(
- # reply_markup=InlineKeyboardMarkup(main_menu_buttons())
- # )
-
@userge.bot.on_callback_query(filters.regex(pattern=r"refresh\((.+)\)"))
@check_owner
async def callback_exit(callback_query: CallbackQuery):
@@ -328,21 +297,9 @@ async def callback_exit(callback_query: CallbackQuery):
text, buttons = filter_data(cur_pos)
else:
text, buttons = plugin_data(cur_pos)
-
- response = await xbot.edit_inline_text(
- callback_query.inline_message_id,
- text=text,
- reply_markup=InlineKeyboardMarkup(buttons),
+ await callback_query.edit_message_text(
+ text, reply_markup=InlineKeyboardMarkup(buttons)
)
- errors = response.get("description", None)
- if errors:
- if "not modified:" in errors:
- raise MessageNotModified
- if "MESSAGE_ID_INVALID" in errors:
- raise MessageIdInvalid
- # await callback_query.edit_message_text(
- # text, reply_markup=InlineKeyboardMarkup(buttons)
- # )
def is_filter(name: str) -> bool:
split_ = name.split(".")
@@ -399,10 +356,7 @@ def default_buttons(cur_pos: str):
)
)
if len(cur_pos.split("|")) > 2:
- tmp_btns.append(
- InlineKeyboardButton("š„ Main Menu", callback_data="mm")
- # .encode()
- )
+ tmp_btns.append(InlineKeyboardButton("š„ Main Menu", callback_data="mm"))
tmp_btns.append(
InlineKeyboardButton(
"š Refresh", callback_data=f"refresh({cur_pos})".encode()
@@ -413,8 +367,7 @@ def default_buttons(cur_pos: str):
tmp_btns.append(
InlineKeyboardButton(
f"š© Client for Checks and Sudos : {cur_clnt}",
- callback_data="chgclnt"
- # .encode()
+ callback_data="chgclnt",
)
)
return [tmp_btns]
diff --git a/userge/plugins/misc/upload.py b/userge/plugins/misc/upload.py
index f323d27de..0189afcdf 100644
--- a/userge/plugins/misc/upload.py
+++ b/userge/plugins/misc/upload.py
@@ -1,6 +1,5 @@
""" upload , rename and convert telegram files """
-
import io
import os
import re
@@ -12,18 +11,18 @@
from hachoir.metadata import extractMetadata
from hachoir.parser import createParser
from PIL import Image
-from pyrogram.errors.exceptions import FloodWait
+from pyrogram.errors import FloodWait
+from pyrogram.types import CallbackQuery
from userge import Config, Message, userge
from userge.plugins.misc.download import tg_download, url_download
from userge.utils import humanbytes, progress, take_screen_shot
-from userge.utils.botapi import inline_progress
from userge.utils.exceptions import ProcessCanceled
LOGGER = userge.getLogger(__name__)
CHANNEL = userge.getCLogger(__name__)
-LOGO_PATH = "resources/userge.png"
+LOGO_PATH = "resources/logo_x.png"
@userge.on_cmd(
@@ -159,12 +158,12 @@ def explorer(_path: Path) -> None:
async def upload(
message: Message,
path: Path,
+ callback: CallbackQuery = None,
del_path: bool = False,
extra: str = "",
with_thumb: bool = True,
- logvid: bool = True,
- custom_thumb: str = None,
- inline_id: str = None,
+ custom_thumb: str = "",
+ log: bool = True,
):
if "wt" in message.flags:
with_thumb = False
@@ -172,13 +171,13 @@ async def upload(
"d" not in message.flags
):
return await vid_upload(
- message, path, del_path, extra, with_thumb, logvid, custom_thumb, inline_id
+ message, path, callback, del_path, extra, with_thumb, custom_thumb, log
)
elif path.name.lower().endswith((".mp3", ".flac", ".wav", ".m4a")) and (
"d" not in message.flags
):
return await audio_upload(
- message, path, del_path, extra, with_thumb, logvid, inline_id
+ message, path, callback, del_path, extra, with_thumb, log
)
elif path.name.lower().endswith((".jpg", ".jpeg", ".png", ".bmp")) and (
"d" not in message.flags
@@ -230,15 +229,23 @@ async def doc_upload(
async def vid_upload(
message: Message,
path,
+ callback: CallbackQuery = None,
del_path: bool = False,
extra: str = "",
with_thumb: bool = True,
- logvid: bool = True,
- custom_thumb: str = None,
- inline_id: str = None,
+ custom_thumb: str = "",
+ log: bool = True,
):
str_path = str(path)
- thumb = (custom_thumb or await get_thumb(str_path)) if with_thumb else None
+ thumb = None
+ if with_thumb:
+ if custom_thumb:
+ try:
+ thumb = await check_thumb(custom_thumb)
+ except Exception as e_r:
+ await CHANNEL.log(str(e_r))
+ if not thumb:
+ thumb = await get_thumb(str_path)
duration = 0
metadata = extractMetadata(createParser(str_path))
if metadata and metadata.has("duration"):
@@ -257,16 +264,6 @@ async def vid_upload(
if t_m and t_m.has("height"):
height = t_m.get("height")
try:
- if logvid:
- progress_args = (message, f"uploading {extra}", str_path)
- else:
- progress_args = (
- message,
- inline_id,
- f"uploading {extra}",
- str_path,
- "caption",
- )
msg = await message.client.send_video(
chat_id=message.chat.id,
video=str_path,
@@ -277,8 +274,8 @@ async def vid_upload(
caption=path.name,
parse_mode="html",
disable_notification=True,
- progress=progress if logvid else inline_progress,
- progress_args=progress_args,
+ progress=progress,
+ progress_args=(message, f"uploading {extra}", str_path, callback),
)
except ValueError as e_e:
await sent.edit(f"Skipping `{str_path}` due to {e_e}")
@@ -288,21 +285,30 @@ async def vid_upload(
else:
await sent.delete()
await remove_thumb(thumb)
- if logvid:
+ if log:
await finalize(message, msg, start_t)
if os.path.exists(str_path) and del_path:
os.remove(str_path)
- return msg
+ return msg
+
+
+async def check_thumb(thumb_path: str):
+ f_path = os.path.splitext(thumb_path)
+ if f_path[1] != ".jpg":
+ new_thumb_path = f"{f_path[0]}.jpg"
+ Image.open(thumb_path).convert("RGB").save(new_thumb_path, "JPEG")
+ os.remove(thumb_path)
+ return thumb_path
async def audio_upload(
message: Message,
path,
+ callback: CallbackQuery = None,
del_path: bool = False,
extra: str = "",
with_thumb: bool = True,
- logvid: bool = True,
- inline_id: str = None,
+ log: bool = True,
):
title = None
artist = None
@@ -336,16 +342,6 @@ async def audio_upload(
start_t = datetime.now()
await message.client.send_chat_action(message.chat.id, "upload_audio")
try:
- if logvid:
- progress_args = (message, f"uploading {extra}", str_path)
- else:
- progress_args = (
- message,
- inline_id,
- f"uploading {extra}",
- str_path,
- "caption",
- )
msg = await message.client.send_audio(
chat_id=message.chat.id,
audio=str_path,
@@ -356,8 +352,8 @@ async def audio_upload(
duration=duration,
parse_mode="html",
disable_notification=True,
- progress=progress if logvid else inline_progress,
- progress_args=progress_args,
+ progress=progress,
+ progress_args=(message, f"uploading {extra}", str_path, callback),
)
except ValueError as e_e:
await sent.edit(f"Skipping `{str_path}` due to {e_e}")
@@ -366,13 +362,12 @@ async def audio_upload(
raise u_e
else:
await sent.delete()
- if logvid:
+ if log:
await finalize(message, msg, start_t)
if os.path.exists(str_path) and del_path:
os.remove(str_path)
- finally:
- if os.path.lexists("album_cover.jpg"):
- os.remove("album_cover.jpg")
+ if os.path.lexists("album_cover.jpg"):
+ os.remove("album_cover.jpg")
return msg
diff --git a/userge/plugins/tools/json.py b/userge/plugins/tools/json.py
index 13732b4ce..5b95c04da 100644
--- a/userge/plugins/tools/json.py
+++ b/userge/plugins/tools/json.py
@@ -69,7 +69,7 @@ def dump(self, data, stream=None, **kw):
return stream.getvalue()
-def yamlify(input):
+def yamlify(input_):
yaml = MyYAML()
yaml.indent(mapping=2, sequence=4, offset=2)
- return f"
{yaml.dump(input)}" + return f"
{yaml.dump(input_)}" diff --git a/userge/plugins/utils/currency.py b/userge/plugins/utils/currency.py index 5c8390386..869891853 100644 --- a/userge/plugins/utils/currency.py +++ b/userge/plugins/utils/currency.py @@ -9,9 +9,9 @@ import json import aiohttp -from emoji import get_emoji_regexp from userge import Config, Message, userge +from userge.utils.functions import get_emoji_regex CHANNEL = userge.getCLogger(__name__) LOG = userge.getLogger(__name__) @@ -40,7 +40,7 @@ async def cur_conv(message: Message): ) return - filterinput = get_emoji_regexp().sub("", message.input_str) + filterinput = get_emoji_regex().sub("", message.input_str) curcon = filterinput.upper().split() if len(curcon) == 3: diff --git a/userge/plugins/utils/translate.py b/userge/plugins/utils/translate.py index 70d889d06..adb8ff881 100644 --- a/userge/plugins/utils/translate.py +++ b/userge/plugins/utils/translate.py @@ -9,10 +9,10 @@ import time from json import dumps -from emoji import get_emoji_regexp from googletrans import LANGUAGES, Translator from userge import Config, Message, pool, userge +from userge.utils.functions import get_emoji_regex @userge.on_cmd( @@ -51,7 +51,7 @@ async def translateme(message: Message): src, dest = "auto", list(flags)[0] else: src, dest = "auto", Config.LANG - text = get_emoji_regexp().sub("", text) + text = get_emoji_regex().sub("", text) await message.edit("`Translating ...`") try: reply_text = await _translate_this(text, dest, src) diff --git a/userge/utils/__init__.py b/userge/utils/__init__.py index 463127e79..c72e9e86e 100644 --- a/userge/utils/__init__.py +++ b/userge/utils/__init__.py @@ -1,6 +1,4 @@ from .aiohttp_helper import get_response -from .botapi import XMediaTypes as xmedia -from .botapi import xbot from .functions import ( check_owner, cleanhtml, @@ -13,8 +11,8 @@ rand_key, thumb_from_audio, ) -from .progress import progress # noqa -from .sys_tools import SafeDict, get_import_path, secure_text, terminate # noqa +from .progress import progress +from .sys_tools import SafeDict, get_import_path, secure_text, terminate from .tools import ( get_file_id, humanbytes, diff --git a/userge/utils/aiohttp_helper.py b/userge/utils/aiohttp_helper.py index 326e4221c..09f826bcb 100644 --- a/userge/utils/aiohttp_helper.py +++ b/userge/utils/aiohttp_helper.py @@ -1,40 +1,42 @@ -from aiohttp import ClientTimeout - -from .botapi.rawbotapi import xbot +from aiohttp import ClientSession, ClientTimeout class get_response: @staticmethod # Can be used without initialising async def json(link: str, params: dict = None): - async with xbot.session.get( - link, params=params, timeout=ClientTimeout(total=30) - ) as resp: - if resp.status != 200: - raise ValueError - # Raises an AssertionError if status != 200 - return await resp.json() + async with ClientSession() as session: + async with session.get( + link, params=params, timeout=ClientTimeout(total=30) + ) as resp: + if resp.status != 200: + raise ValueError + # Raises an AssertionError if status != 200 + return await resp.json() @staticmethod async def text(link: str, params: dict = None): - async with xbot.session.get( - link, params=params, timeout=ClientTimeout(total=30) - ) as resp: - if resp.status != 200: - raise ValueError - return await resp.text() + async with ClientSession() as session: + async with session.get( + link, params=params, timeout=ClientTimeout(total=30) + ) as resp: + if resp.status != 200: + raise ValueError + return await resp.text() @staticmethod async def read(link: str, params: dict = None): - async with xbot.session.get( - link, params=params, timeout=ClientTimeout(total=30) - ) as resp: - if resp.status != 200: - raise ValueError - return await resp.read() + async with ClientSession() as session: + async with session.get( + link, params=params, timeout=ClientTimeout(total=30) + ) as resp: + if resp.status != 200: + raise ValueError + return await resp.read() # Just returns the Header @staticmethod async def status(link: str, wait: int = 5): - async with xbot.session.get(link, timeout=ClientTimeout(total=wait)) as resp: - return resp.status + async with ClientSession() as session: + async with session.get(link, timeout=ClientTimeout(total=wait)) as resp: + return resp.status diff --git a/userge/utils/botapi/XParser.py b/userge/utils/botapi/XParser.py deleted file mode 100644 index 85e7c220d..000000000 --- a/userge/utils/botapi/XParser.py +++ /dev/null @@ -1,90 +0,0 @@ -from enum import Enum, auto - -from bs4 import BeautifulSoup as soup -from pyrogram import raw, types -from pyrogram.parser.parser import Parser -from pyrogram.raw.functions.users import GetUsers -from pyrogram.types.messages_and_media.message_entity import MessageEntity - -from userge.core.ext.raw_client import RawClient as userge - - -class AutoName(Enum): - def _generate_next_value_(self, *args): - return self.lower() - - -class MessageEntityType(AutoName): - MENTION = auto() - HASHTAG = auto() - CASHTAG = auto() - BOT_COMMAND = auto() - URL = auto() - EMAIL = auto() - PHONE_NUMBER = auto() - BOLD = auto() - ITALIC = auto() - UNDERLINE = auto() - STRIKETHROUGH = auto() - CODE = auto() - PRE = auto() - TEXT_LINK = auto() - TEXT_MENTION = auto() - BLOCKQUOTE = auto() - - -RAW_ENTITIES_TO_TYPE = { - raw.types.MessageEntityMention: MessageEntityType.MENTION, - raw.types.MessageEntityHashtag: MessageEntityType.HASHTAG, - raw.types.MessageEntityCashtag: MessageEntityType.CASHTAG, - raw.types.MessageEntityBotCommand: MessageEntityType.BOT_COMMAND, - raw.types.MessageEntityUrl: MessageEntityType.URL, - raw.types.MessageEntityEmail: MessageEntityType.EMAIL, - raw.types.MessageEntityBold: MessageEntityType.BOLD, - raw.types.MessageEntityItalic: MessageEntityType.ITALIC, - raw.types.MessageEntityCode: MessageEntityType.CODE, - raw.types.MessageEntityPre: MessageEntityType.PRE, - raw.types.MessageEntityUnderline: MessageEntityType.UNDERLINE, - raw.types.MessageEntityStrike: MessageEntityType.STRIKETHROUGH, - raw.types.MessageEntityBlockquote: MessageEntityType.BLOCKQUOTE, - raw.types.MessageEntityTextUrl: MessageEntityType.TEXT_LINK, - raw.types.MessageEntityMentionName: MessageEntityType.TEXT_MENTION, - raw.types.MessageEntityPhone: MessageEntityType.PHONE_NUMBER, - raw.types.InputMessageEntityMentionName: MessageEntityType.TEXT_MENTION, # <- HACKS -} - - -async def e_gen(entity, client): - entity_type = RAW_ENTITIES_TO_TYPE.get(entity.__class__) - if entity_type is None: - return None - - # language=getattr(entity, "language", None), - return MessageEntity( - type=entity_type.value, - offset=entity.offset, - length=entity.length, - url=getattr(entity, "url", None), - user=(await get_user(entity)), - client=client, - ) - - -async def get_user(entity): - user_id = getattr(getattr(entity, "user_id", None), "user_id", None) - if not user_id: - return - k = await userge.send(GetUsers(id=[await userge.resolve_peer(user_id)])) - return types.User._parse(userge, k[0]) - - -async def mixed_to_html(text: str): - pyro_entity = types.List() - x = Parser(userge) - y = await x.parse(text, mode="combined") - for i in y["entities"]: - ent = await e_gen(i, userge) - if ent: - pyro_entity.append(ent) - out = x.unparse(y["message"], pyro_entity, is_html=True) - return str(soup(out, "html.parser")) diff --git a/userge/utils/botapi/__init__.py b/userge/utils/botapi/__init__.py deleted file mode 100644 index 7af1a6d7d..000000000 --- a/userge/utils/botapi/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .iprogress import inline_progress -from .rawbotapi import XMediaTypes, xbot diff --git a/userge/utils/botapi/iprogress.py b/userge/utils/botapi/iprogress.py deleted file mode 100644 index 6b547e321..000000000 --- a/userge/utils/botapi/iprogress.py +++ /dev/null @@ -1,87 +0,0 @@ -import time -from math import floor -from typing import Dict, Tuple - -import userge -from userge.utils.tools import humanbytes, time_formatter - -from .rawbotapi import xbot - -_TASKS: Dict[str, Tuple[int, int]] = {} - - -async def inline_progress( - current: int, - total: int, - message: "userge.Message", - inline_id: str, - ud_type: str, - file_name: str = "", - edit_type: str = "text", - delay: int = userge.Config.EDIT_SLEEP_TIMEOUT, -) -> None: - """ progress function """ - if message.process_is_canceled: - await message.client.stop_transmission() - task_id = f"{message.chat.id}.{message.message_id}" - if current == total: - if task_id not in _TASKS: - return - del _TASKS[task_id] - if edit_type == "text": - - await xbot.edit_inline_text( - inline_id, text="
Uploading to telegram...
"
- )
-
- else:
-
- await xbot.edit_inline_caption(
- inline_id, caption="Uploading to telegram ...
"
- )
-
- now = time.time()
- if task_id not in _TASKS:
- _TASKS[task_id] = (now, now)
- start, last = _TASKS[task_id]
- elapsed_time = now - start
- if (now - last) >= delay:
- _TASKS[task_id] = (start, now)
- percentage = current * 100 / total
- speed = current / elapsed_time
- time_to_completion = time_formatter(int((total - current) / speed))
- progress_str = (
- "__{}__ : `{}`\n"
- + "```[{}{}]```\n"
- + "**Progress** : `{}%`\n"
- + "**Completed** : `{}`\n"
- + "**Total** : `{}`\n"
- + "**Speed** : `{}/s`\n"
- + "**ETA** : `{}`"
- )
- progress_str = progress_str.format(
- ud_type,
- file_name,
- "".join(
- (
- userge.Config.FINISHED_PROGRESS_STR
- for i in range(floor(percentage / 5))
- )
- ),
- "".join(
- (
- userge.Config.UNFINISHED_PROGRESS_STR
- for i in range(20 - floor(percentage / 5))
- )
- ),
- round(percentage, 2),
- humanbytes(current),
- humanbytes(total),
- humanbytes(speed),
- time_to_completion or "0 s",
- )
-
- if edit_type == "text":
- await xbot.edit_inline_text(inline_id, text=progress_str)
- else:
- await xbot.edit_inline_caption(inline_id, caption=progress_str)
diff --git a/userge/utils/botapi/rawbotapi.py b/userge/utils/botapi/rawbotapi.py
deleted file mode 100644
index b28ee0744..000000000
--- a/userge/utils/botapi/rawbotapi.py
+++ /dev/null
@@ -1,279 +0,0 @@
-import asyncio
-from typing import Optional
-
-import aiohttp
-import ujson
-from pyrogram.types import InlineKeyboardMarkup
-
-from userge.config import Config
-
-from .XParser import mixed_to_html
-
-
-class XBot:
- def __init__(self):
- token = getattr(Config, "BOT_TOKEN", None)
- if not token:
- return
- self.api = "https://api.telegram.org/bot" + token
- self._session: Optional[aiohttp.ClientSession] = None
-
- @staticmethod
- def get_new_session() -> aiohttp.ClientSession:
- return aiohttp.ClientSession(
- json_serialize=ujson.dumps, timeout=aiohttp.ClientTimeout(total=300)
- )
-
- @property
- def session(self) -> Optional[aiohttp.ClientSession]:
- if self._session is None or self._session.closed:
- self._session = self.get_new_session()
- return self._session
-
- async def post_(self, method: str, params: dict):
- session = self.session
- link = f"{self.api}/{method}"
-
- timeout = aiohttp.ClientTimeout(total=30)
-
- try:
- async with session.get(link, params=params, timeout=timeout) as resp:
- data = await resp.json()
- except aiohttp.ClientError as ex:
- await session.close()
- print(ex)
- return
- except asyncio.TimeoutError:
- return
- return data
-
- async def edit_inline_text(
- self,
- inline_message_id: str,
- text: str,
- reply_markup: InlineKeyboardMarkup = None,
- parse_mode: str = "mixed",
- disable_web_page_preview: bool = False,
- ):
- params = {
- "inline_message_id": inline_message_id,
- "text": await mixed_to_html(text)
- if parse_mode.lower() == "mixed"
- else text,
- }
- if reply_markup: # :: Optional ::
- params["reply_markup"] = XBot.InlineKeyboard(reply_markup)
- if disable_web_page_preview:
- params["disable_web_page_preview"] = "True"
- if parse_mode.lower() in ("md", "markdown"):
- params["parse_mode"] = "Markdown"
- elif parse_mode.lower() in ("html", "mixed"):
- params["parse_mode"] = "HTML"
- return await self.post_("editMessageText", params)
-
- async def edit_inline_caption(
- self,
- inline_message_id: str,
- caption: str,
- reply_markup: InlineKeyboardMarkup = None,
- parse_mode: str = "mixed",
- ):
- params = {
- "inline_message_id": inline_message_id,
- "caption": await mixed_to_html(caption)
- if parse_mode.lower() == "mixed"
- else caption,
- }
- if reply_markup: # :: Optional ::
- params["reply_markup"] = XBot.InlineKeyboard(reply_markup)
- if parse_mode.lower() in ("md", "markdown"):
- params["parse_mode"] = "Markdown"
- elif parse_mode.lower() in ("html", "mixed"):
- params["parse_mode"] = "HTML"
- return await self.post_("editMessageCaption", params)
-
- async def edit_inline_media(
- self,
- inline_message_id: str,
- media: str,
- reply_markup: InlineKeyboardMarkup = None,
- ):
- params = {"inline_message_id": inline_message_id, "media": media}
- if reply_markup: # :: Optional ::
- params["reply_markup"] = XBot.InlineKeyboard(reply_markup)
- return await self.post_("editMessageMedia", params)
-
- async def edit_inline_reply_markup(
- self,
- inline_message_id: str,
- reply_markup: InlineKeyboardMarkup = None,
- ):
- params = {
- "inline_message_id": inline_message_id,
- }
- if reply_markup: # :: Optional ::
- params["reply_markup"] = XBot.InlineKeyboard(reply_markup)
- return await self.post_("editMessageReplyMarkup", params)
-
- @staticmethod
- def InlineKeyboard(mkrp):
- if isinstance(mkrp, InlineKeyboardMarkup):
- btn = str(mkrp)
- elif isinstance(mkrp, list):
- btn = str(InlineKeyboardMarkup(mkrp))
- else:
- return None
- buttons = ujson.loads(btn)["inline_keyboard"]
- return ujson.dumps({"inline_keyboard": XBot.clean_markup(buttons)})
-
- @staticmethod
- def clean_markup(btn_array: list):
- a = []
- b = []
- for rows in btn_array:
- for cell in rows:
- b.append({key: val for key, val in cell.items() if key != "_"})
- a.append(b)
- b = []
- return a
-
-
-class XMediaTypes:
- @staticmethod
- async def InputMediaPhoto(
- file_id: str, caption: str = None, parse_mode: str = "mixed"
- ):
- media = {"type": "photo", "media": file_id}
- if caption:
- if parse_mode.lower() == "mixed":
- caption = await mixed_to_html(caption)
- media["caption"] = caption
- if parse_mode.lower() in ("md", "markdown"):
- media["parse_mode"] = "Markdown"
- elif parse_mode.lower() in ("html", "mixed"):
- media["parse_mode"] = "HTML"
- return ujson.dumps(media)
-
- @staticmethod
- async def InputMediaAnimation(
- file_id: str,
- thumb: str = None,
- caption: str = None,
- parse_mode: str = "mixed",
- width: int = None,
- height: int = None,
- duration: int = None,
- ):
- media = {"type": "animation", "media": file_id}
- if caption:
- if parse_mode.lower() == "mixed":
- caption = await mixed_to_html(caption)
- media["caption"] = caption
- if thumb:
- media["thumb"] = thumb
- if width:
- media["width"] = width
- if height:
- media["height"] = height
- if duration:
- media["duration"] = duration
- if parse_mode.lower() in ("md", "markdown"):
- media["parse_mode"] = "Markdown"
- elif parse_mode.lower() in ("html", "mixed"):
- media["parse_mode"] = "HTML"
- return ujson.dumps(media)
-
- @staticmethod
- async def InputMediaDocument(
- file_id: str,
- thumb: str = None,
- caption: str = None,
- parse_mode: str = "mixed",
- disable_content_type_detection: bool = "None",
- ):
- media = {"type": "document", "media": file_id}
- if caption:
- if parse_mode.lower() == "mixed":
- caption = await mixed_to_html(caption)
- media["caption"] = caption
- if thumb:
- media["thumb"] = thumb
- if isinstance(disable_content_type_detection, bool):
- media["disable_content_type_detection"] = disable_content_type_detection
- if parse_mode.lower() in ("md", "markdown"):
- media["parse_mode"] = "Markdown"
- elif parse_mode.lower() in ("html", "mixed"):
- media["parse_mode"] = "HTML"
- return ujson.dumps(media)
-
- @staticmethod
- async def InputMediaAudio(
- file_id: str,
- thumb: str = None,
- caption: str = None,
- parse_mode: str = "mixed",
- performer: str = None,
- title: str = None,
- duration: int = None,
- ):
- media = {"type": "audio", "media": file_id}
- if caption:
- if parse_mode.lower() == "mixed":
- caption = await mixed_to_html(caption)
- media["caption"] = caption
- if thumb:
- media["thumb"] = thumb
- if performer:
- media["performer"] = performer
- if duration:
- media["duration"] = duration
- if title:
- media["title"] = title
- if parse_mode.lower() in ("md", "markdown"):
- media["parse_mode"] = "Markdown"
- elif parse_mode.lower() in ("html", "mixed"):
- media["parse_mode"] = "HTML"
-
- return ujson.dumps(media)
-
- @staticmethod
- async def InputMediaVideo(
- file_id: str,
- thumb: str = None,
- caption: str = None,
- parse_mode: str = "mixed",
- width: int = None,
- height: int = None,
- duration: int = None,
- supports_streaming: bool = True,
- ):
- media = {
- "type": "video",
- "media": file_id,
- "supports_streaming": True,
- }
- if not supports_streaming:
- media["supports_streaming"] = False
- if caption:
- if parse_mode.lower() == "mixed":
- caption = await mixed_to_html(caption)
- media["caption"] = caption
- if thumb:
- media["thumb"] = thumb
- if width:
- media["width"] = width
- if height:
- media["height"] = height
- if duration:
- media["duration"] = duration
-
- if parse_mode.lower() in ("md", "markdown"):
- media["parse_mode"] = "Markdown"
- elif parse_mode.lower() in ("html", "mixed"):
- media["parse_mode"] = "HTML"
-
- return ujson.dumps(media)
-
-
-# bot api class
-xbot = XBot()
diff --git a/userge/utils/progress.py b/userge/utils/progress.py
index 7f4980904..8f5de41ee 100644
--- a/userge/utils/progress.py
+++ b/userge/utils/progress.py
@@ -1,18 +1,10 @@
-# pylint: disable=missing-module-docstring
-#
-# Copyright (C) 2020 by UsergeTeam@Github, < https://github.com/UsergeTeam >.
-#
-# This file is part of < https://github.com/UsergeTeam/Userge > project,
-# and is released under the "GNU v3.0 License Agreement".
-# Please see < https://github.com/uaudith/Userge/blob/master/LICENSE >
-#
-# All rights reserved.
-
+import asyncio
import time
from math import floor
from typing import Dict, Tuple
-from pyrogram.errors.exceptions import FloodWait
+from pyrogram.errors import FloodWait
+from pyrogram.types import CallbackQuery
import userge
@@ -27,6 +19,7 @@ async def progress(
message: "userge.Message",
ud_type: str,
file_name: str = "",
+ c_q: CallbackQuery = None,
delay: int = userge.Config.EDIT_SLEEP_TIMEOUT,
) -> None:
""" progress function """
@@ -38,9 +31,12 @@ async def progress(
return
del _TASKS[task_id]
try:
- await message.try_to_edit("`finalizing process ...`")
+ if c_q:
+ await c_q.edit_message_text("`finalizing process ...`")
+ else:
+ await message.try_to_edit("`finalizing process ...`")
except FloodWait as f_e:
- time.sleep(f_e.x)
+ await asyncio.sleep(f_e.x)
return
now = time.time()
if task_id not in _TASKS:
@@ -80,10 +76,12 @@ async def progress(
humanbytes(current),
humanbytes(total),
humanbytes(speed),
- time_to_completion or "0 s",
+ time_to_completion if time_to_completion else "0 s",
)
-
try:
- await message.try_to_edit(progress_str)
+ if c_q:
+ await c_q.edit_message_text(progress_str)
+ else:
+ await message.try_to_edit(progress_str)
except FloodWait as f_e:
- time.sleep(f_e.x)
+ await asyncio.sleep(f_e.x)