diff --git a/assistant/callbackstuffs.py b/assistant/callbackstuffs.py
index 0495c8246..15598fee2 100644
--- a/assistant/callbackstuffs.py
+++ b/assistant/callbackstuffs.py
@@ -20,8 +20,8 @@
from pyUltroid.fns.gDrive import GDriveManager
except ImportError:
GDriveManager = None
-from telegraph import upload_file as upl
from telethon import Button, events
+from catbox import CatboxUploader
from telethon.tl.types import MessageMediaWebPage
from telethon.utils import get_peer_id
@@ -34,9 +34,9 @@
# --------------------------------------------------------------------#
telegraph = telegraph_client()
GDrive = GDriveManager() if GDriveManager else None
+uploader = CatboxUploader()
# --------------------------------------------------------------------#
-
def text_to_url(event):
"""function to get media url (with|without) Webpage"""
if isinstance(event.media, MessageMediaWebPage):
@@ -322,9 +322,9 @@ async def update(eve):
await eve.edit(get_string("clst_1"))
call_back()
await bash("git pull && pip3 install -r requirements.txt")
+ await bash("pip3 install -r requirements.txt --break-system-packages")
execl(sys.executable, sys.executable, "-m", "pyUltroid")
-
@callback(re.compile("changes(.*)"), owner=True)
async def changes(okk):
match = okk.data_match.group(1).decode("utf-8")
@@ -384,11 +384,14 @@ async def _(e):
if "|" in ok:
ok, index = ok.split("|")
with open(ok, "r") as hmm:
- _, key = await get_paste(hmm.read())
- link = f"https://spaceb.in/{key}"
- raw = f"https://spaceb.in/api/v1/documents/{key}/raw"
- if not _:
+ _, data = await get_paste(hmm.read())
+ if not data.get("link"):
return await e.answer(key[:30], alert=True)
+ if not key.startswith("http"):
+ link, raw = data["link"], data["raw"]
+ else:
+ link = key
+ raw = f"{key}/raw"
if ok.startswith("addons"):
key = "Addons"
elif ok.startswith("vcbot"):
@@ -830,8 +833,7 @@ async def media(event):
else:
media = await event.client.download_media(response, "alvpc")
try:
- x = upl(media)
- url = f"https://graph.org/{x[0]}"
+ url = uploader.upload_file(media)
remove(media)
except BaseException as er:
LOGS.exception(er)
@@ -969,8 +971,7 @@ async def media(event):
url = response.file.id
else:
try:
- x = upl(media)
- url = f"https://graph.org/{x[0]}"
+ url = uploader.upload_file(media)
remove(media)
except BaseException as er:
LOGS.exception(er)
@@ -1239,8 +1240,7 @@ async def media(event):
url = text_to_url(response)
else:
try:
- x = upl(media)
- url = f"https://graph.org/{x[0]}"
+ url = uploader.upload_file(media)
remove(media)
except BaseException as er:
LOGS.exception(er)
diff --git a/assistant/games.py b/assistant/games.py
index fef75c0cb..e2b86eacc 100644
--- a/assistant/games.py
+++ b/assistant/games.py
@@ -14,23 +14,28 @@
"""
import asyncio
-import re
+import re, uuid, operator
from random import choice, shuffle
-from akipy.async_akipy import Akinator, akipyLOGS
+from akipy.async_akipy import Akinator
from telethon.errors.rpcerrorlist import BotMethodInvalidError
from telethon.events import Raw
from telethon.tl.types import InputMediaPoll, Poll, PollAnswer, UpdateMessagePollVote
from pyUltroid._misc._decorators import ultroid_cmd
+from logging import getLogger
+from html import unescape
+from telethon.tl.types import TextWithEntities
from pyUltroid.fns.helper import inline_mention
from pyUltroid.fns.tools import async_searcher
+from telethon.errors import ChatSendStickersForbiddenError
from . import * # Ensure this import matches your project structure
games = {}
aki_photo = "https://graph.org/file/3cc8825c029fd0cab9edc.jpg"
+akipyLOGS = getLogger("akipy")
@ultroid_cmd(pattern="akinator")
async def akina(e):
@@ -133,11 +138,7 @@ async def eiagx(e):
# ----------------------- Main Command ------------------- #
-GIMAGES = [
- "https://graph.org/file/1c51015bae5205a65fd69.jpg",
- "https://imgwhale.xyz/3xyr322l64j9590",
-]
-
+GIMAGE = "https://graph.org/file/1c51015bae5205a65fd69.jpg"
@asst_cmd(pattern="startgame", owner=True)
async def magic(event):
@@ -147,7 +148,7 @@ async def magic(event):
]
await event.reply(
get_string("games_1"),
- file=choice(GIMAGES),
+ file=GIMAGE,
buttons=buttons,
)
@@ -243,10 +244,10 @@ async def choose_cata(event):
if TRIVIA_CHATS[chat].get("cancel") is not None:
break
ansi = str(uuid.uuid1()).split("-")[0].encode()
- opts = [PollAnswer(unescape(q["correct_answer"]), ansi)]
+ opts = [PollAnswer(TextWithEntities(unescape(q["correct_answer"]), entities=[]), ansi)]
[
opts.append(
- PollAnswer(unescape(a), str(uuid.uuid1()).split("-")[0].encode())
+ PollAnswer(TextWithEntities(unescape(a), entities=[]), str(uuid.uuid1()).split("-")[0].encode())
)
for a in q["incorrect_answers"]
]
@@ -254,7 +255,10 @@ async def choose_cata(event):
poll = InputMediaPoll(
Poll(
0,
- f"[{copper+1}]. " + unescape(q["question"]),
+ TextWithEntities(
+ f"[{copper+1}]. " + unescape(q["question"]),
+ entities=[]
+ ),
answers=opts,
public_voters=True,
quiz=True,
@@ -298,13 +302,22 @@ async def choose_cata(event):
@asst.on(
Raw(UpdateMessagePollVote, func=lambda x: TRIVIA_CHATS and POLLS.get(x.poll_id))
)
-async def pollish(eve):
+async def pollish(eve: UpdateMessagePollVote):
if POLLS.get(eve.poll_id)["chat"] not in TRIVIA_CHATS.keys():
return
+ if not eve.options:
+ # Consider as correct answer if no options selected
+ chat = POLLS.get(eve.poll_id)["chat"]
+ user = eve.peer.user_id
+ if not TRIVIA_CHATS.get(chat, {}).get(user):
+ TRIVIA_CHATS[chat][user] = 1
+ else:
+ TRIVIA_CHATS[chat][user] += 1
+ return
if POLLS[eve.poll_id]["answer"] != eve.options[0]:
return
chat = POLLS.get(eve.poll_id)["chat"]
- user = eve.user_id
+ user = eve.peer.user_id
if not TRIVIA_CHATS.get(chat, {}).get(user):
TRIVIA_CHATS[chat][user] = 1
else:
diff --git a/plugins/__init__.py b/plugins/__init__.py
index 173db5398..82ef3187a 100644
--- a/plugins/__init__.py
+++ b/plugins/__init__.py
@@ -25,6 +25,7 @@
from pyUltroid.startup._database import _BaseDatabase as Database
from pyUltroid.version import __version__, ultroid_version
from strings import get_help, get_string
+from catbox import CatboxUploader
udB: Database
@@ -50,6 +51,9 @@ def inline_pic():
Telegraph = telegraph_client()
+cat_uploader = CatboxUploader()
+
+upload_file = cat_uploader.upload_file
List = []
Dict = {}
@@ -84,6 +88,7 @@ def inline_pic():
"Mr.Steal-Your-Sticker is stealing this sticker... ",
]
+
ATRA_COL = [
"DarkCyan",
"DeepSkyBlue",
diff --git a/plugins/_inline.py b/plugins/_inline.py
index 93cc81e4a..211e723ff 100644
--- a/plugins/_inline.py
+++ b/plugins/_inline.py
@@ -115,8 +115,12 @@ async def inline_handler(event):
@in_pattern("pasta", owner=True)
async def _(event):
ok = event.text.split("-")[1]
- link = f"https://spaceb.in/{ok}"
- raw = f"https://spaceb.in/api/v1/documents/{ok}/raw"
+ if not ok.startswith("http"):
+ link = f"https://spaceb.in/{ok}"
+ raw = f"https://spaceb.in/api/v1/documents/{ok}/raw"
+ else:
+ link = ok
+ raw = f"{ok}/raw"
result = await event.builder.article(
title="Paste",
text="Pasted to Spacebin 🌌",
diff --git a/plugins/afk.py b/plugins/afk.py
index 67f5d08ed..74e06eb77 100644
--- a/plugins/afk.py
+++ b/plugins/afk.py
@@ -12,7 +12,6 @@
import asyncio
-from telegraph import upload_file as uf
from telethon import events
from pyUltroid.dB.afk_db import add_afk, del_afk, is_afk
@@ -28,6 +27,7 @@
udB,
ultroid_bot,
ultroid_cmd,
+ upload_file
)
old_afk_msg = []
@@ -50,8 +50,7 @@ async def set_afk(event):
media_type = mediainfo(reply.media)
if media_type.startswith(("pic", "gif")):
file = await event.client.download_media(reply.media)
- iurl = uf(file)
- media = f"https://graph.org{iurl[0]}"
+ media = upload_file(file)
else:
media = reply.file.id
await event.eor("`Done`", time=2)
diff --git a/plugins/asstcmd.py b/plugins/asstcmd.py
index b84c717bc..02a9945c1 100644
--- a/plugins/asstcmd.py
+++ b/plugins/asstcmd.py
@@ -13,14 +13,9 @@
from pyUltroid.dB.asstcmd_db import add_cmd, cmd_reply, list_cmds, rem_cmd
from pyUltroid.fns.tools import create_tl_btn, format_btn, get_msg_button
-
-try:
- from telegraph import upload_file as uf
-except ImportError:
- uf = None
from telethon import events, utils
-from . import asst, get_string, mediainfo, udB, ultroid_cmd
+from . import asst, get_string, mediainfo, udB, ultroid_cmd, upload_file
@ultroid_cmd(pattern="addcmd( (.*)|$)")
@@ -36,16 +31,14 @@ async def ac(e):
wut = mediainfo(wt.media)
if wut.startswith(("pic", "gif")):
dl = await e.client.download_media(wt.media)
- variable = uf(dl)
+ m = upload_file(dl)
os.remove(dl)
- m = f"https://graph.org{variable[0]}"
elif wut == "video":
if wt.media.document.size > 8 * 1000 * 1000:
return await e.eor(get_string("com_4"), time=5)
dl = await e.client.download_media(wt.media)
- variable = uf(dl)
+ m = upload_file(dl)
os.remove(dl)
- m = f"https://graph.org{variable[0]}"
else:
m = utils.pack_bot_file_id(wt.media)
if wt.text:
diff --git a/plugins/audiotools.py b/plugins/audiotools.py
index 2ae4e9921..40343bbc8 100644
--- a/plugins/audiotools.py
+++ b/plugins/audiotools.py
@@ -26,8 +26,7 @@
mediainfo,
stdr,
time_formatter,
- ultroid_cmd,
- uploader,
+ ultroid_cmd
)
__doc__ = get_help("help_audiotools")
@@ -104,13 +103,15 @@ async def trim_aud(e):
await bash(cmd)
os.remove(file.name)
f_time = time.time()
- mmmm = await uploader(out, out, f_time, xxx, f"Uploading {out}...")
+ n_file, _ = await e.client.fast_uploader(
+ out, show_progress=True, event=e, message="Uploading...", to_delete=True
+ )
attributes = await set_attributes(out)
caption = get_string("audiotools_7").format(ss, dd)
await e.client.send_file(
e.chat_id,
- mmmm,
+ n_file,
thumb=ULTConfig.thumb,
caption=caption,
attributes=attributes,
@@ -147,13 +148,15 @@ async def ex_aud(e):
f_time = time.time()
try:
- fo = await uploader(out_file, out_file, f_time, msg, f"Uploading {out_file}...")
+ n_file, _ = await e.client.fast_uploader(
+ out_file, show_progress=True, event=e, message="Uploading...", to_delete=True
+ )
except FileNotFoundError:
return await eor(msg, get_string("audiotools_9"))
await e.reply(
get_string("audiotools_10"),
- file=fo,
+ file=n_file,
thumb=ULTConfig.thumb,
attributes=attributes,
)
diff --git a/plugins/bot.py b/plugins/bot.py
index e10bd09e9..a4febdc90 100644
--- a/plugins/bot.py
+++ b/plugins/bot.py
@@ -211,6 +211,7 @@ async def restartbt(ult):
if heroku_api:
return await restart(ok)
await bash("git pull && pip3 install -r requirements.txt")
+ await bash("pip3 install -r requirements.txt --break-system-packages")
if len(sys.argv) > 1:
os.execl(sys.executable, sys.executable, "main.py")
else:
@@ -324,6 +325,7 @@ async def _(e):
or "soft" in e.pattern_match.group(1).strip()
):
await bash("git pull -f && pip3 install -r requirements.txt")
+ await bash("pip3 install -r requirements.txt --break-system-packages")
call_back()
await xx.edit(get_string("upd_7"))
os.execl(sys.executable, "python3", "-m", "pyUltroid")
diff --git a/plugins/button.py b/plugins/button.py
index ef61d2990..ef1fbb2a8 100644
--- a/plugins/button.py
+++ b/plugins/button.py
@@ -11,7 +11,7 @@
import os
-from telegraph import upload_file as uf
+from . import upload_file as uf
from telethon.utils import pack_bot_file_id
from pyUltroid.fns.tools import create_tl_btn, get_msg_button
@@ -31,15 +31,13 @@ async def butt(event):
wut = mediainfo(wt.media)
if wut and wut.startswith(("pic", "gif")):
dl = await wt.download_media()
- variable = uf(dl)
- media = f"https://graph.org{variable[0]}"
+ media = uf(dl)
elif wut == "video":
if wt.media.document.size > 8 * 1000 * 1000:
return await event.eor(get_string("com_4"), time=5)
dl = await wt.download_media()
- variable = uf(dl)
+ media = uf(dl)
os.remove(dl)
- media = f"https://graph.org{variable[0]}"
else:
media = pack_bot_file_id(wt.media)
try:
diff --git a/plugins/compressor.py b/plugins/compressor.py
index abd6d157e..a221d8f16 100644
--- a/plugins/compressor.py
+++ b/plugins/compressor.py
@@ -139,7 +139,9 @@ async def _(e):
caption += f"**Compressed Size: **`{humanbytes(c_size)}`\n"
caption += f"**Compression Ratio: **`{differ:.2f}%`\n"
caption += f"\n**Time Taken To Compress: **`{difff}`"
- mmmm = await uploader(out, out, f_time, xxx, f"Uploading {out}...")
+ n_file, _ = await e.client.fast_uploader(
+ out, show_progress=True, event=e, message="Uploading...", to_delete=True
+ )
if to_stream:
data = await metadata(out)
width = data["width"]
@@ -152,7 +154,7 @@ async def _(e):
]
await e.client.send_file(
e.chat_id,
- mmmm,
+ n_file,
thumb=ULTConfig.thumb,
caption=caption,
attributes=attributes,
@@ -162,7 +164,7 @@ async def _(e):
else:
await e.client.send_file(
e.chat_id,
- mmmm,
+ n_file,
thumb=ULTConfig.thumb,
caption=caption,
force_document=True,
diff --git a/plugins/converter.py b/plugins/converter.py
index b68dd2736..201ff76b9 100644
--- a/plugins/converter.py
+++ b/plugins/converter.py
@@ -25,7 +25,7 @@
LOGS.info(f"{__file__}: PIL not Installed.")
Image = None
-from telegraph import upload_file as uf
+from . import upload_file as uf
from . import (
ULTConfig,
@@ -53,9 +53,8 @@ async def _(e):
dl = await r.download_media(thumb=-1)
else:
return await e.eor("`Reply to Photo or media with thumb...`")
- variable = uf(dl)
+ nn = uf(dl)
os.remove(dl)
- nn = f"https://graph.org{variable[0]}"
udB.set_key("CUSTOM_THUMBNAIL", str(nn))
await bash(f"wget {nn} -O resources/extras/ultroid.jpg")
await e.eor(get_string("cvt_6").format(nn), link_preview=False)
@@ -93,10 +92,12 @@ async def imak(event):
if not os.path.exists(inp) or os.path.exists(inp) and not os.path.getsize(inp):
os.rename(file, inp)
k = time.time()
- xxx = await uploader(inp, inp, k, xx, get_string("com_6"))
+ n_file, _ = await event.client.fast_uploader(
+ inp, show_progress=True, event=event, message="Uploading...", to_delete=True
+ )
await event.reply(
- f"`{xxx.name}`",
- file=xxx,
+ f"`{n_file.name}`",
+ file=n_file,
force_document=True,
thumb=ULTConfig.thumb,
)
@@ -135,14 +136,18 @@ async def uconverter(event):
except KeyError:
return await xx.edit(get_string("sts_3").format("gif/img/sticker/webm"))
file = await con.convert(b, outname="ultroid", convert_to=convert)
+ print(file)
+
if file:
await event.client.send_file(
event.chat_id, file, reply_to=event.reply_to_msg_id or event.id
)
os.remove(file)
+ else:
+ await xx.edit("`Failed to convert`")
+ return
await xx.delete()
-
@ultroid_cmd(
pattern="doc( (.*)|$)",
)
@@ -183,9 +188,9 @@ async def _(event):
try:
await xx.edit(f"```{d}```")
except BaseException:
- what, key = await get_paste(d)
+ what, data = await get_paste(d)
await xx.edit(
- f"**MESSAGE EXCEEDS TELEGRAM LIMITS**\n\nSo Pasted It On [SPACEBIN](https://spaceb.in/{key})"
+ f"**MESSAGE EXCEEDS TELEGRAM LIMITS**\n\nSo Pasted It On [SPACEBIN]({data['link']})"
)
if rem:
os.remove(b)
diff --git a/plugins/devtools.py b/plugins/devtools.py
index fb3f72b4b..40af9a798 100644
--- a/plugins/devtools.py
+++ b/plugins/devtools.py
@@ -33,10 +33,8 @@
from yaml import safe_load
except ImportError:
from pyUltroid.fns.tools import safe_load
-try:
- from telegraph import upload_file as uf
-except ImportError:
- uf = None
+
+from . import upload_file as uf
from telethon.tl import functions
fn = functions
@@ -99,7 +97,7 @@ async def _(event):
f"Unknown Response from Carbon: `{li}`\n\nstdout`:{stdout}`\nstderr: `{stderr}`"
)
return
- url = f"https://graph.org{uf(li)[-1]}"
+ url = uf(li)
OUT = f"[\xad]({url}){OUT}"
out = "**• OUTPUT:**"
remove(li)
@@ -121,7 +119,7 @@ async def _(event):
f"Unknown Response from Carbon: `{li}`\n\nstdout`:{stdout}`\nstderr: `{stderr}`"
)
return
- url = f"https://graph.org{uf(li)[-1]}"
+ url = uf(li)
OUT = f"[\xad]({url}){OUT}"
out = "**• OUTPUT:**"
remove(li)
diff --git a/plugins/filter.py b/plugins/filter.py
index 95294b01a..b33076913 100644
--- a/plugins/filter.py
+++ b/plugins/filter.py
@@ -12,14 +12,13 @@
import os
import re
-from telegraph import upload_file as uf
from telethon.tl.types import User
from telethon.utils import pack_bot_file_id
from pyUltroid.dB.filter_db import add_filter, get_filter, list_filter, rem_filter
from pyUltroid.fns.tools import create_tl_btn, format_btn, get_msg_button
-from . import events, get_string, mediainfo, udB, ultroid_bot, ultroid_cmd
+from . import events, get_string, mediainfo, udB, ultroid_bot, ultroid_cmd, upload_file
from ._inline import something
@@ -35,15 +34,14 @@ async def af(e):
wut = mediainfo(wt.media)
if wut.startswith(("pic", "gif")):
dl = await wt.download_media()
- variable = uf(dl)
- m = f"https://graph.org{variable[0]}"
+ m = upload_file(dl)
+ os.remove(dl)
elif wut == "video":
if wt.media.document.size > 8 * 1000 * 1000:
return await e.eor(get_string("com_4"), time=5)
dl = await wt.download_media()
- variable = uf(dl)
+ m = upload_file(dl)
os.remove(dl)
- m = f"https://graph.org{variable[0]}"
else:
m = pack_bot_file_id(wt.media)
if wt.text:
diff --git a/plugins/greetings.py b/plugins/greetings.py
index 7f126e1a5..27053eff3 100644
--- a/plugins/greetings.py
+++ b/plugins/greetings.py
@@ -32,7 +32,7 @@
"""
import os
-from telegraph import upload_file as uf
+from . import upload_file as uf
from telethon.utils import pack_bot_file_id
from pyUltroid.dB.greetings_db import (
@@ -67,16 +67,14 @@ async def setwel(event):
wut = mediainfo(r.media)
if wut.startswith(("pic", "gif")):
dl = await r.download_media()
- variable = uf(dl)
+ m = uf(dl)
os.remove(dl)
- m = f"https://graph.org{variable[0]}"
elif wut == "video":
if r.media.document.size > 8 * 1000 * 1000:
return await eor(x, get_string("com_4"), time=5)
dl = await r.download_media()
- variable = uf(dl)
+ m = uf(dl)
os.remove(dl)
- m = f"https://graph.org{variable[0]}"
elif wut == "web":
m = None
else:
@@ -132,16 +130,14 @@ async def setgb(event):
wut = mediainfo(r.media)
if wut.startswith(("pic", "gif")):
dl = await r.download_media()
- variable = uf(dl)
+ m = uf(dl)
os.remove(dl)
- m = f"https://graph.org{variable[0]}"
elif wut == "video":
if r.media.document.size > 8 * 1000 * 1000:
return await eor(x, get_string("com_4"), time=5)
dl = await r.download_media()
- variable = uf(dl)
+ m = uf(dl)
os.remove(dl)
- m = f"https://graph.org{variable[0]}"
elif wut == "web":
m = None
else:
diff --git a/plugins/imagetools.py b/plugins/imagetools.py
index a0757bcff..22fd01182 100644
--- a/plugins/imagetools.py
+++ b/plugins/imagetools.py
@@ -68,7 +68,8 @@
except ImportError:
Image = None
LOGS.info(f"{__file__}: PIL not Installed.")
-from telegraph import upload_file as upf
+
+from . import upload_file as upf
from telethon.errors.rpcerrorlist import (
ChatSendMediaForbiddenError,
MessageDeleteForbiddenError,
@@ -217,8 +218,7 @@ async def ultd(event):
if ultt.endswith(".tgs"):
await xx.edit(get_string("sts_9"))
file = await con.convert(ultt, convert_to="png", outname="ult")
- got = upf(file)
- lnk = f"https://graph.org{got[0]}"
+ lnk = upf(file)
r = await async_searcher(
f"https://nekobot.xyz/api/imagegen?type=blurpify&image={lnk}", re_json=True
)
diff --git a/plugins/mediatools.py b/plugins/mediatools.py
index fd0ab43b4..4e8667b8f 100644
--- a/plugins/mediatools.py
+++ b/plugins/mediatools.py
@@ -27,6 +27,7 @@
bash,
downloader,
get_string,
+ upload_file,
is_url_ok,
mediainfo,
ultroid_cmd,
@@ -87,7 +88,7 @@ async def mi(e):
makehtml = ""
if naam.endswith((".jpg", ".png")):
if os.path.exists(naam):
- med = "https://graph.org" + Telegraph.upload_file(naam)[0]["src"]
+ med = upload_file(naam)
else:
med = match
makehtml += f"
"
diff --git a/plugins/notes.py b/plugins/notes.py
index 5553782f7..4bceefeb6 100644
--- a/plugins/notes.py
+++ b/plugins/notes.py
@@ -22,7 +22,7 @@
"""
import os
-from telegraph import upload_file as uf
+from . import upload_file as uf
from telethon.utils import pack_bot_file_id
from pyUltroid.dB.notes_db import add_note, get_notes, list_note, rem_note
@@ -46,16 +46,14 @@ async def an(e):
wut = mediainfo(wt.media)
if wut.startswith(("pic", "gif")):
dl = await wt.download_media()
- variable = uf(dl)
+ m = uf(dl)
os.remove(dl)
- m = f"https://graph.org{variable[0]}"
elif wut == "video":
if wt.media.document.size > 8 * 1000 * 1000:
return await e.eor(get_string("com_4"), time=5)
dl = await wt.download_media()
- variable = uf(dl)
+ m = uf(dl)
os.remove(dl)
- m = f"https://graph.org{variable[0]}"
else:
m = pack_bot_file_id(wt.media)
if wt.text:
diff --git a/plugins/polls.py b/plugins/polls.py
index 2fb71e5dc..95423a684 100644
--- a/plugins/polls.py
+++ b/plugins/polls.py
@@ -18,7 +18,7 @@
Get the quiz poll where answerno is the number of option which is correct
"""
-from telethon.tl.types import InputMediaPoll, Poll, PollAnswer
+from telethon.tl.types import InputMediaPoll, Poll, PollAnswer, TextWithEntities
from . import get_string, ultroid_cmd
@@ -57,10 +57,10 @@ async def uri_poll(e):
if len(option) <= 1:
return await e.eor("`Options Should be More than 1..`", time=5)
m = await e.eor(get_string("com_1"))
- OUT = [PollAnswer(option[on], str(on).encode()) for on in range(len(option))]
+ OUT = [PollAnswer(TextWithEntities(option[on], entities=[]), str(on).encode()) for on in range(len(option))]
await e.respond(
file=InputMediaPoll(
- Poll(20, ques, OUT, multiple_choice=mpp, public_voters=publ, quiz=quizo),
+ Poll(20, TextWithEntities(ques, entities=[]), OUT, multiple_choice=mpp, public_voters=publ, quiz=quizo),
correct_answers=karzo,
),
)
diff --git a/plugins/search.py b/plugins/search.py
index b80e34f04..020e08c02 100644
--- a/plugins/search.py
+++ b/plugins/search.py
@@ -152,8 +152,10 @@ async def reverse(event):
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0",
},
)
+ with open("response.html", "w") as f:
+ f.write(response)
xx = bs(response, "html.parser")
- div = xx.find_all("div", {"class": "r5a77d"})[0]
+ div = xx.find_all("div", {"class": "kb0PBd"})[0]
alls = div.find("a")
link = alls["href"]
text = alls.text
diff --git a/plugins/snips.py b/plugins/snips.py
index 6b11f27ec..a7c7aae1f 100644
--- a/plugins/snips.py
+++ b/plugins/snips.py
@@ -21,7 +21,7 @@
"""
import os
-from telegraph import upload_file as uf
+from . import upload_file as uf
from telethon.utils import pack_bot_file_id
from pyUltroid._misc import sudoers
@@ -45,16 +45,14 @@ async def an(e):
wut = mediainfo(wt.media)
if wut.startswith(("pic", "gif")):
dl = await wt.download_media()
- variable = uf(dl)
+ m = uf(dl)
os.remove(dl)
- m = f"https://graph.org{variable[0]}"
elif wut == "video":
if wt.media.document.size > 8 * 1000 * 1000:
return await e.eor(get_string("com_4"), time=5)
dl = await wt.download_media()
- variable = uf(dl)
+ m = uf(dl)
os.remove(dl)
- m = f"https://graph.org{variable[0]}"
else:
m = pack_bot_file_id(wt.media)
if wt.text:
diff --git a/plugins/specialtools.py b/plugins/specialtools.py
index 6971c58ff..52a448be7 100644
--- a/plugins/specialtools.py
+++ b/plugins/specialtools.py
@@ -36,10 +36,11 @@
from datetime import datetime as dt
from random import choice
-import pytz
+import pytz, asyncio
from bs4 import BeautifulSoup as bs
from telethon.tl.types import DocumentAttributeVideo
-
+from requests import Session
+from cloudscraper import create_scraper
from pyUltroid.fns.tools import get_google_images, metadata
from . import (
@@ -59,7 +60,7 @@
from .beautify import all_col
File = []
-
+scraper = create_scraper()
@ultroid_cmd(
pattern="getaudio$",
@@ -250,6 +251,7 @@ async def hbd(event):
reply_to=event.reply_to_msg_id,
)
+session = Session()
@ultroid_cmd(pattern="sticker( (.*)|$)")
async def _(event):
@@ -257,23 +259,61 @@ async def _(event):
if not x:
return await event.eor("`Give something to search`")
uu = await event.eor(get_string("com_1"))
- z = bs(
- await async_searcher(f"https://combot.org/telegram/stickers?q={x}"),
- "html.parser",
- )
-
- packs = z.find_all("div", "sticker-pack__header")
- sticks = {
- c.a["href"]: c.find("div", {"class": "sticker-pack__title"}).text for c in packs
+
+ headers = {
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
-
- if not sticks:
- return await uu.edit(get_string("spcltool_9"))
- a = "SᴛɪᴄᴋEʀs Aᴠᴀɪʟᴀʙʟᴇ ~\n\n"
- for _, value in sticks.items():
- a += f"{value}\n"
- await uu.edit(a, parse_mode="html")
-
+
+ max_retries = 3
+ retry_count = 0
+
+ while retry_count < max_retries:
+ try:
+ response = scraper.get(
+ f"https://combot.org/telegram/stickers?q={x}",
+ headers=headers
+ ).content
+
+ # Check if response contains Cloudflare challenge
+ if "Just a moment..." in response.decode():
+ retry_count += 1
+ await asyncio.sleep(2) # Wait before retry
+ continue
+
+ z = bs(response, "html.parser")
+ packs = z.find_all("a", {"class": "stickerset__title"})
+
+ if not packs:
+ return await uu.edit(get_string("spcltool_9"))
+
+ break # Success - exit loop
+
+ except Exception as er:
+ retry_count += 1
+ await asyncio.sleep(2)
+ continue
+
+ if retry_count >= max_retries:
+ return await uu.edit("`Failed to fetch stickers after multiple retries`")
+ try:
+ sticks = {}
+ for pack in packs:
+ href = pack.get("href")
+ title = pack.text.strip()
+ if href:
+ href = f"https://t.me/addstickers/{href.split('/')[-1]}"
+ sticks[href] = title
+
+ if not sticks:
+ return await uu.edit(get_string("spcltool_9"))
+
+ a = "SᴛɪᴄᴋEʀs Aᴠᴀɪʟᴀʙʟᴇ ~\n\n"
+ for href, title in sticks.items():
+ a += f"{title}\n"
+ await uu.edit(a, parse_mode="html")
+
+ except Exception as e:
+ await uu.edit(f"`Error: {str(e)}`\nTry again later.")
@ultroid_cmd(pattern="wall( (.*)|$)")
async def wall(event):
diff --git a/plugins/twitter.py b/plugins/twitter.py
index 81dbe534a..06613cee2 100644
--- a/plugins/twitter.py
+++ b/plugins/twitter.py
@@ -81,8 +81,10 @@ async def twitter_details(event):
msg = await event.eor("🔍 `Getting tweet details...`")
try:
client = await get_client()
- if "twitter.com" in match or "x.com" in match:
- tweet_id = match.split("/")[-1].split("?")[0]
+ from urllib.parse import urlparse
+ parsed_url = urlparse(match)
+ if parsed_url.hostname in ["twitter.com", "x.com"]:
+ tweet_id = parsed_url.path.split("/")[-1].split("?")[0]
else:
tweet_id = match
diff --git a/plugins/utilities.py b/plugins/utilities.py
index 11d826890..f8b62f643 100644
--- a/plugins/utilities.py
+++ b/plugins/utilities.py
@@ -67,10 +67,7 @@
from pyUltroid.dB.gban_mute_db import is_gbanned
from pyUltroid.fns.tools import get_chat_and_msgid
-try:
- from telegraph import upload_file as uf
-except ImportError:
- uf = None
+from . import upload_file as uf
from telethon.errors.rpcerrorlist import ChatForwardsRestrictedError, UserBotError
from telethon.errors import MessageTooLongError
@@ -266,18 +263,16 @@ async def _(event):
return await xx.eor(
"`Reply to a Message/Document or Give me Some Text !`", time=5
)
- done, key = await get_paste(message)
- if not done:
- return await xx.eor(key)
- link = f"https://spaceb.in/{key}"
- raw = f"https://spaceb.in/api/v1/documents/{key}/raw"
+ done, data = await get_paste(message)
+ if not done and data.get("error"):
+ return await xx.eor(data["error"])
reply_text = (
- f"• **Pasted to SpaceBin :** [Space]({link})\n• **Raw Url :** : [Raw]({raw})"
+ f"• **Pasted to SpaceBin :** [Space]({data['link']})\n• **Raw Url :** : [Raw]({data['raw']})"
)
try:
if event.client._bot:
return await xx.eor(reply_text)
- ok = await event.client.inline_query(asst.me.username, f"pasta-{key}")
+ ok = await event.client.inline_query(asst.me.username, f"pasta-{data['link']}")
await ok[0].click(event.chat_id, reply_to=event.reply_to_msg_id, hide_via=True)
await xx.delete()
except BaseException as e:
@@ -506,7 +501,7 @@ async def telegraphcmd(event):
getit = file
if "document" not in dar:
try:
- nn = f"https://graph.org{uf(getit)[0]}"
+ nn = uf(getit)
amsg = f"Uploaded to [Telegraph]({nn}) !"
except Exception as e:
amsg = f"Error : {e}"
diff --git a/plugins/writer.py b/plugins/writer.py
index 4e9f812ff..9b9ea3d4e 100644
--- a/plugins/writer.py
+++ b/plugins/writer.py
@@ -74,7 +74,8 @@ async def writer(e):
font = ImageFont.truetype("resources/fonts/assfont.ttf", 30)
x, y = 150, 140
lines = text_set(text)
- line_height = font.getsize("hg")[1]
+ bbox = font.getbbox("hg")
+ line_height = bbox[3] - bbox[1]
for line in lines:
draw.text((x, y), line, fill=(1, 22, 55), font=font)
y = y + line_height - 5
diff --git a/plugins/ziptools.py b/plugins/ziptools.py
index c7006dad7..ab2674c19 100644
--- a/plugins/ziptools.py
+++ b/plugins/ziptools.py
@@ -63,13 +63,15 @@ async def zipp(event):
else:
await bash(f"zip -r {inp} {file}")
k = time.time()
- xxx = await uploader(inp, inp, k, xx, get_string("com_6"))
+ n_file, _ = await event.client.fast_uploader(
+ inp, show_progress=True, event=event, message="Uploading...", to_delete=True
+ )
await event.client.send_file(
event.chat_id,
- xxx,
+ n_file,
force_document=True,
thumb=ULTConfig.thumb,
- caption=f"`{xxx.name}`",
+ caption=f"`{n_file.name}`",
reply_to=reply,
)
os.remove(inp)
@@ -104,13 +106,15 @@ async def unzipp(event):
ok = get_all_files("unzip")
for x in ok:
k = time.time()
- xxx = await uploader(x, x, k, xx, get_string("com_6"))
+ n_file, _ = await event.client.fast_uploader(
+ x, show_progress=True, event=event, message="Uploading...", to_delete=True
+ )
await event.client.send_file(
event.chat_id,
- xxx,
+ n_file,
force_document=True,
thumb=ULTConfig.thumb,
- caption=f"`{xxx.name}`",
+ caption=f"`{n_file.name}`",
)
await xx.delete()
diff --git a/pyUltroid/fns/misc.py b/pyUltroid/fns/misc.py
index 69ce9e94a..85369b1b6 100644
--- a/pyUltroid/fns/misc.py
+++ b/pyUltroid/fns/misc.py
@@ -13,6 +13,7 @@
from logging import WARNING
from random import choice, randrange, shuffle
from traceback import format_exc
+from catbox import CatboxUploader
from pyUltroid.exceptions import DependencyMissingError
@@ -59,6 +60,7 @@
except ImportError:
BeautifulSoup = None
+uploader = CatboxUploader()
async def randomchannel(
tochat, channel, range1, range2, caption=None, client=ultroid_bot
@@ -295,15 +297,7 @@ async def _format_quote(self, event, reply=None, sender=None, type_="private"):
async def telegraph(file_):
file = file_ + ".png"
Image.open(file_).save(file, "PNG")
- files = {"file": open(file, "rb").read()}
- uri = (
- "https://graph.org"
- + (
- await async_searcher(
- "https://graph.org/upload", post=True, data=files, re_json=True
- )
- )[0]["src"]
- )
+ uri = uploader.upload_file(file)
os.remove(file)
os.remove(file_)
return uri
diff --git a/pyUltroid/fns/tools.py b/pyUltroid/fns/tools.py
index 6785fae64..3c23f2186 100644
--- a/pyUltroid/fns/tools.py
+++ b/pyUltroid/fns/tools.py
@@ -9,9 +9,9 @@
import math
import os
import random
-import re
+import re, subprocess
import secrets
-import ssl
+import ssl, html
from io import BytesIO
from json.decoder import JSONDecodeError
from traceback import format_exc
@@ -118,8 +118,12 @@ async def metadata(file):
raise DependencyMissingError(
f"'{_}' is not installed!\nInstall it to use this command."
)
+
data = {}
- _info = json.loads(out)["media"]["track"]
+ _info = json.loads(out)["media"]
+ if not _info:
+ return {}
+ _info = _info["track"]
info = _info[0]
if info.get("Format") in ["GIF", "PNG"]:
return {
@@ -385,95 +389,109 @@ def make_logo(imgpath, text, funt, **args):
async def get_paste(data: str, extension: str = "txt"):
- ssl_context = ssl.create_default_context(cafile=certifi.where())
- json = {"content": data, "extension": extension}
- key = await async_searcher(
- url="https://spaceb.in/api/v1/documents/",
- json=json,
- ssl=ssl_context,
- post=True,
- re_json=True,
- )
try:
- return True, key["payload"]["id"]
- except KeyError:
- if "the length must be between 2 and 400000." in key["error"]:
- return await get_paste(data[-400000:], extension=extension)
- return False, key["error"]
- except Exception as e:
- LOGS.info(e)
- return None, str(e)
-
+ url = "https://spaceb.in/api/"
+ res = await async_searcher(url, json={"content": data, "extension": extension}, post=True, re_json=True)
+ return True, {
+ "link": f"https://spaceb.in/{res['payload']['id']}",
+ "raw": f"https://spaceb.in/{res['payload']['id']}/raw"
+ }
+ except Exception:
+ try:
+ url = "https://dpaste.org/api/"
+ data = {
+ 'format': 'json',
+ 'content': data.encode('utf-8'),
+ 'lexer': extension,
+ 'expires': '604800', # expire in week
+ }
+ res = await async_searcher(url, data=data, post=True, re_json=True)
+ return True, {
+ "link": res["url"],
+ "raw": f'{res["url"]}/raw'
+ }
+ except Exception as e:
+ LOGS.info(e)
+ return None, {
+ "link": None,
+ "raw": None,
+ "error": str(e)
+ }
-# --------------------------------------
# https://stackoverflow.com/a/74563494
async def get_google_images(query):
- soup = BeautifulSoup(
- await async_searcher(
- "https://google.com/search",
- params={"q": query, "tbm": "isch"},
- headers={"User-Agent": random.choice(some_random_headers)},
- ),
- "lxml",
- )
- google_images = []
- all_script_tags = soup.select("script")
- matched_images_data = "".join(
- re.findall(r"AF_initDataCallback\(([^<]+)\);", str(all_script_tags))
- )
- matched_images_data_fix = json.dumps(matched_images_data)
- matched_images_data_json = json.loads(matched_images_data_fix)
- matched_google_image_data = re.findall(
- r"\"b-GRID_STATE0\"(.*)sideChannel:\s?{}}", matched_images_data_json
- )
- matched_google_images_thumbnails = ", ".join(
- re.findall(
- r"\[\"(https\:\/\/encrypted-tbn0\.gstatic\.com\/images\?.*?)\",\d+,\d+\]",
- str(matched_google_image_data),
- )
- ).split(", ")
- thumbnails = [
- bytes(bytes(thumbnail, "ascii").decode("unicode-escape"), "ascii").decode(
- "unicode-escape"
- )
- for thumbnail in matched_google_images_thumbnails
- ]
- removed_matched_google_images_thumbnails = re.sub(
- r"\[\"(https\:\/\/encrypted-tbn0\.gstatic\.com\/images\?.*?)\",\d+,\d+\]",
- "",
- str(matched_google_image_data),
- )
- matched_google_full_resolution_images = re.findall(
- r"(?:'|,),\[\"(https:|http.*?)\",\d+,\d+\]",
- removed_matched_google_images_thumbnails,
- )
- full_res_images = [
- bytes(bytes(img, "ascii").decode("unicode-escape"), "ascii").decode(
- "unicode-escape"
- )
- for img in matched_google_full_resolution_images
+ """Get image results from Google Custom Search API.
+
+ Args:
+ query (str): Search query string
+
+ Returns:
+ list: List of dicts containing image info (title, link, source, thumbnail, original)
+ """
+ LOGS.info(f"Searching Google Images for: {query}")
+
+ # Google Custom Search API credentials
+ google_keys = [
+ {
+ "key": "AIzaSyAj75v6vHWLJdJaYcj44tLz7bdsrh2g7Y0",
+ "cx": "712a54749d99a449e"
+ },
+ {
+ "key": "AIzaSyDFQQwPLCzcJ9FDao-B7zDusBxk8GoZ0HY",
+ "cx": "001bbd139705f44a6"
+ },
+ {
+ "key": "AIzaSyD0sRNZUa8-0kq9LAREDAFKLNO1HPmikRU",
+ "cx": "4717c609c54e24250"
+ }
]
- for index, (metadata, thumbnail, original) in enumerate(
- zip(soup.select(".isv-r.PNCib.MSM1fd.BUooTd"), thumbnails, full_res_images),
- start=1,
- ):
- google_images.append(
- {
- "title": metadata.select_one(".VFACy.kGQAp.sMi44c.lNHeqe.WGvvNb")[
- "title"
- ],
- "link": metadata.select_one(".VFACy.kGQAp.sMi44c.lNHeqe.WGvvNb")[
- "href"
- ],
- "source": metadata.select_one(".fxgdke").text,
- "thumbnail": thumbnail,
- "original": original,
- }
+ key_index = random.randint(0, len(google_keys) - 1)
+ GOOGLE_API_KEY = google_keys[key_index]["key"]
+ GOOGLE_CX = google_keys[key_index]["cx"]
+ try:
+ # Construct API URL
+ url = (
+ "https://www.googleapis.com/customsearch/v1"
+ f"?q={quote(query)}"
+ f"&cx={GOOGLE_CX}"
+ f"&key={GOOGLE_API_KEY}"
+ "&searchType=image"
+ "&num=10" # Number of results
)
- random.shuffle(google_images)
- return google_images
+
+ # Make API request
+ response = await async_searcher(url, re_json=True)
+ print("response")
+ if not response or "items" not in response:
+ LOGS.error("No results from Google Custom Search API")
+ return []
+
+ # Process results
+ google_images = []
+ for item in response["items"]:
+ try:
+ google_images.append({
+ "title": item.get("title", ""),
+ "link": item.get("contextLink", ""), # Page containing image
+ "source": item.get("displayLink", ""),
+ "thumbnail": item.get("image", {}).get("thumbnailLink", item["link"]),
+ "original": item["link"] # Original image URL
+ })
+ except Exception as e:
+ LOGS.warning(f"Failed to process image result: {str(e)}")
+ continue
+
+ # Randomize results order
+ random.shuffle(google_images)
+
+ LOGS.info(f"Found {len(google_images)} images for query: {query}")
+ return google_images
+
+ except Exception as e:
+ LOGS.exception(f"Error in get_google_images: {str(e)}")
+ return []
# Thanks https://t.me/ImSafone for ChatBotApi
@@ -672,7 +690,7 @@ async def get_file_link(msg):
async def get_stored_file(event, hash):
- from .. import udB
+ from .. import udB, asst
msg_id = get_stored_msg(hash)
if not msg_id:
@@ -689,37 +707,22 @@ async def get_stored_file(event, hash):
await asst.send_message(event.chat_id, msg.text, file=msg.media, reply_to=event.id)
-def _package_rpc(text, lang_src="auto", lang_tgt="auto"):
- GOOGLE_TTS_RPC = ["MkEWBc"]
- parameter = [[text.strip(), lang_src, lang_tgt, True], [1]]
- escaped_parameter = json.dumps(parameter, separators=(",", ":"))
- rpc = [[[random.choice(GOOGLE_TTS_RPC), escaped_parameter, None, "generic"]]]
- espaced_rpc = json.dumps(rpc, separators=(",", ":"))
- freq = "f.req={}&".format(quote(espaced_rpc))
- return freq
-
+def translate(text, lang_tgt="en", lang_src="auto", timeout=60, detect=False):
+ pattern = r'(?s)class="(?:t0|result-container)">(.*?)<'
+ escaped_text = quote(text.encode("utf8"))
+ url = "https://translate.google.com/m?tl=%s&sl=%s&q=%s" % (
+ lang_tgt,
+ lang_src,
+ escaped_text,
+ )
+ response = requests.get(url, timeout=timeout).content
+ result = response.decode("utf8")
+ result = re.findall(pattern, result)
+ if not result:
+ return ""
+ text = html.unescape(result[0])
+ return (text, None) if detect else text
-def translate(*args, **kwargs):
- headers = {
- "Referer": "https://translate.google.co.in",
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) "
- "AppleWebKit/537.36 (KHTML, like Gecko) "
- "Chrome/47.0.2526.106 Safari/537.36",
- "Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
- }
- x = requests.post(
- "https://translate.google.co.in/_/TranslateWebserverUi/data/batchexecute",
- headers=headers,
- data=_package_rpc(*args, **kwargs),
- ).text
- response = ""
- data = json.loads(json.loads(x[4:])[0][2])[1][0][0]
- subind = data[-2]
- if not subind:
- subind = data[-1]
- for i in subind:
- response += i[0]
- return response
def cmd_regex_replace(cmd):
@@ -751,50 +754,83 @@ class TgConverter:
@staticmethod
async def animated_sticker(file, out_path="sticker.tgs", throw=False, remove=False):
"""Convert to/from animated sticker."""
- if out_path.endswith("webp"):
- er, out = await bash(
- f"lottie_convert.py --webp-quality 100 --webp-skip-frames 100 '{file}' '{out_path}'"
- )
- else:
- er, out = await bash(f"lottie_convert.py '{file}' '{out_path}'")
- if er and throw:
- raise LottieException(er)
- if remove:
- os.remove(file)
- if os.path.exists(out_path):
- return out_path
+ LOGS.info(f"Converting animated sticker: {file} -> {out_path}")
+ try:
+ if out_path.endswith("webp"):
+ er, out = await bash(
+ f"lottie_convert.py --webp-quality 100 --webp-skip-frames 100 '{file}' '{out_path}'"
+ )
+ else:
+ er, out = await bash(f"lottie_convert.py '{file}' '{out_path}'")
+
+ if er:
+ LOGS.error(f"Error in animated_sticker conversion: {er}")
+ if throw:
+ raise LottieException(er)
+ if remove and os.path.exists(file):
+ os.remove(file)
+ LOGS.info(f"Removed original file: {file}")
+ if os.path.exists(out_path):
+ LOGS.info(f"Successfully converted to {out_path}")
+ return out_path
+ LOGS.error(f"Output file not created: {out_path}")
+ return None
+ except Exception as e:
+ LOGS.exception(f"Unexpected error in animated_sticker: {str(e)}")
+ if throw:
+ raise
@staticmethod
async def animated_to_gif(file, out_path="gif.gif"):
"""Convert animated sticker to gif."""
- await bash(
- f"lottie_convert.py '{_unquote_text(file)}' '{_unquote_text(out_path)}'"
- )
- return out_path
+ LOGS.info(f"Converting to gif: {file} -> {out_path}")
+ try:
+ er, out = await bash(
+ f"lottie_convert.py '{_unquote_text(file)}' '{_unquote_text(out_path)}'"
+ )
+ if er:
+ LOGS.error(f"Error in animated_to_gif conversion: {er}")
+ if os.path.exists(out_path):
+ LOGS.info("Successfully converted to gif")
+ return out_path
+ LOGS.error("Gif conversion failed - output file not created")
+ return None
+ except Exception as e:
+ LOGS.exception(f"Unexpected error in animated_to_gif: {str(e)}")
+ return None
@staticmethod
def resize_photo_sticker(photo):
"""Resize the given photo to 512x512 (for creating telegram sticker)."""
- image = Image.open(photo)
- if (image.width and image.height) < 512:
- size1 = image.width
- size2 = image.height
- if image.width > image.height:
- scale = 512 / size1
- size1new = 512
- size2new = size2 * scale
+ LOGS.info(f"Resizing photo for sticker: {photo}")
+ try:
+ image = Image.open(photo)
+ original_size = (image.width, image.height)
+
+ if (image.width and image.height) < 512:
+ size1 = image.width
+ size2 = image.height
+ if image.width > image.height:
+ scale = 512 / size1
+ size1new = 512
+ size2new = size2 * scale
+ else:
+ scale = 512 / size2
+ size1new = size1 * scale
+ size2new = 512
+ size1new = math.floor(size1new)
+ size2new = math.floor(size2new)
+ sizenew = (size1new, size2new)
+ image = image.resize(sizenew)
else:
- scale = 512 / size2
- size1new = size1 * scale
- size2new = 512
- size1new = math.floor(size1new)
- size2new = math.floor(size2new)
- sizenew = (size1new, size2new)
- image = image.resize(sizenew)
- else:
- maxsize = (512, 512)
- image.thumbnail(maxsize)
- return image
+ maxsize = (512, 512)
+ image.thumbnail(maxsize)
+
+ LOGS.info(f"Resized image from {original_size} to {image.size}")
+ return image
+ except Exception as e:
+ LOGS.exception(f"Error in resize_photo_sticker: {str(e)}")
+ raise
@staticmethod
async def ffmpeg_convert(input_, output, remove=False):
@@ -803,9 +839,11 @@ async def ffmpeg_convert(input_, output, remove=False):
input_, name=output[:-5], remove=remove
)
if output.endswith(".gif"):
- await bash(f"ffmpeg -i '{input_}' -an -sn -c:v copy '{output}.mp4' -y")
+ out, er = await bash(f"ffmpeg -i '{input_}' -an -sn -c:v copy '{output}.mp4' -y")
+ LOGS.info(f"FFmpeg output: {out}, Error: {er}")
else:
- await bash(f"ffmpeg -i '{input_}' '{output}' -y")
+ out, er = await bash(f"ffmpeg -i '{input_}' '{output}' -y")
+ LOGS.info(f"FFmpeg output: {out}, Error: {er}")
if remove:
os.remove(input_)
if os.path.exists(output):
@@ -813,35 +851,80 @@ async def ffmpeg_convert(input_, output, remove=False):
@staticmethod
async def create_webm(file, name="video", remove=False):
- _ = await metadata(file)
- name += ".webm"
- h, w = _["height"], _["width"]
- if h == w and h != 512:
- h, w = 512, 512
- if h != 512 or w != 512:
- if h > w:
- h, w = 512, -1
- if w > h:
- h, w = -1, 512
- await bash(
- f'ffmpeg -i "{file}" -preset fast -an -to 00:00:03 -crf 30 -bufsize 256k -b:v {_["bitrate"]} -vf "scale={w}:{h},fps=30" -c:v libvpx-vp9 "{name}" -y'
- )
- if remove:
- os.remove(file)
- return name
+ LOGS.info(f"Creating webm: {file} -> {name}.webm")
+ try:
+ _ = await metadata(file)
+ name += ".webm"
+ h, w = _["height"], _["width"]
+
+ if h == w and h != 512:
+ h, w = 512, 512
+ if h != 512 or w != 512:
+ if h > w:
+ h, w = 512, -1
+ if w > h:
+ h, w = -1, 512
+
+ await bash(
+ f'ffmpeg -i "{file}" -preset fast -an -to 00:00:03 -crf 30 -bufsize 256k -b:v {_["bitrate"]} -vf "scale={w}:{h},fps=30" -c:v libvpx-vp9 "{name}" -y'
+ )
+
+ if remove and os.path.exists(file):
+ os.remove(file)
+ LOGS.info(f"Removed original file: {file}")
+
+ if os.path.exists(name):
+ LOGS.info(f"Successfully created webm: {name}")
+ return name
+
+ LOGS.error(f"Webm creation failed - output file not created: {name}")
+ return None
+ except Exception as e:
+ LOGS.exception(f"Error in create_webm: {str(e)}")
+ return None
@staticmethod
def to_image(input_, name, remove=False):
+ """Convert video/gif to image using first frame."""
+ LOGS.info(f"Converting to image: {input_} -> {name}")
try:
- import cv2
- except ImportError:
- raise DependencyMissingError("This function needs 'cv2' to be installed.")
- img = cv2.VideoCapture(input_)
- ult, roid = img.read()
- cv2.imwrite(name, roid)
- if remove:
- os.remove(input_)
- return name
+ if not input_:
+ LOGS.error("Input file is None")
+ return None
+
+ if not os.path.exists(input_):
+ LOGS.error(f"Input file does not exist: {input_}")
+ return None
+
+ try:
+ import cv2
+ except ImportError:
+ raise DependencyMissingError("This function needs 'cv2' to be installed.")
+
+ img = cv2.VideoCapture(input_)
+ success, frame = img.read()
+
+ if not success:
+ LOGS.error(f"Failed to read frame from {input_}")
+ return None
+
+ cv2.imwrite(name, frame)
+ img.release()
+
+ if not os.path.exists(name):
+ LOGS.error(f"Failed to save image: {name}")
+ return None
+
+ if remove and os.path.exists(input_):
+ os.remove(input_)
+ LOGS.info(f"Removed original file: {input_}")
+
+ LOGS.info(f"Successfully converted to image: {name}")
+ return name
+
+ except Exception as e:
+ LOGS.exception(f"Error in to_image conversion: {str(e)}")
+ return None
@staticmethod
async def convert(
@@ -851,9 +934,21 @@ async def convert(
allowed_formats=[],
remove_old=True,
):
+ """Convert between different file formats."""
+ LOGS.info(f"Converting {input_file} to {convert_to or allowed_formats}")
+
+ if not input_file:
+ LOGS.error("Input file is None")
+ return None
+
+ if not os.path.exists(input_file):
+ LOGS.error(f"Input file does not exist: {input_file}")
+ return None
+
if "." in input_file:
ext = input_file.split(".")[-1].lower()
else:
+ LOGS.error("Input file has no extension")
return input_file
if (
@@ -866,60 +961,90 @@ async def convert(
def recycle_type(exte):
return convert_to == exte or exte in allowed_formats
- # Sticker to Something
- if ext == "tgs":
- for extn in ["webp", "json", "png", "mp4", "gif"]:
- if recycle_type(extn):
- name = outname + "." + extn
- return await TgConverter.animated_sticker(
- input_file, name, remove=remove_old
+ try:
+ # Sticker to Something
+ if ext == "tgs":
+ for extn in ["webp", "json", "png", "mp4", "gif"]:
+ if recycle_type(extn):
+ name = outname + "." + extn
+ result = await TgConverter.animated_sticker(
+ input_file, name, remove=remove_old
+ )
+ if result:
+ return result
+ if recycle_type("webm"):
+ gif_file = await TgConverter.convert(
+ input_file, convert_to="gif", remove_old=remove_old
)
- if recycle_type("webm"):
- input_file = await TgConverter.convert(
- input_file, convert_to="gif", remove_old=remove_old
- )
- return await TgConverter.create_webm(input_file, outname, remove=True)
- # Json -> Tgs
- elif ext == "json":
- if recycle_type("tgs"):
- name = outname + ".tgs"
- return await TgConverter.animated_sticker(
- input_file, name, remove=remove_old
- )
- # Video to Something
- elif ext in ["webm", "mp4", "gif"]:
- for exte in ["webm", "mp4", "gif"]:
- if recycle_type(exte):
- name = outname + "." + exte
- return await TgConverter.ffmpeg_convert(
+ if gif_file:
+ return await TgConverter.create_webm(gif_file, outname, remove=True)
+
+ # Json -> Tgs
+ elif ext == "json":
+ if recycle_type("tgs"):
+ name = outname + ".tgs"
+ return await TgConverter.animated_sticker(
input_file, name, remove=remove_old
)
- for exte in ["png", "jpg", "jpeg", "webp"]:
- if recycle_type(exte):
- name = outname + "." + exte
- return TgConverter.to_image(input_file, name, remove=remove_old)
- # Image to Something
- elif ext in ["jpg", "jpeg", "png", "webp"]:
- for extn in ["png", "webp", "ico"]:
- if recycle_type(extn):
- img = Image.open(input_file)
- name = outname + "." + extn
- img.save(name, extn.upper())
- if remove_old:
- os.remove(input_file)
- return name
- for extn in ["webm", "gif", "mp4"]:
- if recycle_type(extn):
- name = outname + "." + extn
- if extn == "webm":
- input_file = await TgConverter.convert(
- input_file,
- convert_to="png",
- remove_old=remove_old,
+
+ # Video to Something
+ elif ext in ["webm", "mp4", "gif"]:
+ for exte in ["webm", "mp4", "gif"]:
+ if recycle_type(exte):
+ name = outname + "." + exte
+ result = await TgConverter.ffmpeg_convert(
+ input_file, name, remove=remove_old
)
- return await TgConverter.ffmpeg_convert(
- input_file, name, remove=True if extn == "webm" else remove_old
- )
+ if result:
+ return result
+
+ for exte in ["png", "jpg", "jpeg", "webp"]:
+ if recycle_type(exte):
+ name = outname + "." + exte
+ result = TgConverter.to_image(input_file, name, remove=remove_old)
+ if result:
+ return result
+
+ # Image to Something
+ elif ext in ["jpg", "jpeg", "png", "webp"]:
+ for extn in ["png", "webp", "ico"]:
+ if recycle_type(extn):
+ try:
+ img = Image.open(input_file)
+ name = outname + "." + extn
+ img.save(name, extn.upper())
+ if remove_old and os.path.exists(input_file):
+ os.remove(input_file)
+ LOGS.info(f"Removed original file: {input_file}")
+ return name
+ except Exception as e:
+ LOGS.error(f"Failed to convert image to {extn}: {str(e)}")
+ continue
+
+ for extn in ["webm", "gif", "mp4"]:
+ if recycle_type(extn):
+ name = outname + "." + extn
+ if extn == "webm":
+ png_file = await TgConverter.convert(
+ input_file,
+ convert_to="png",
+ remove_old=remove_old,
+ )
+ if png_file:
+ return await TgConverter.ffmpeg_convert(
+ png_file, name, remove=True
+ )
+ else:
+ return await TgConverter.ffmpeg_convert(
+ input_file, name, remove=remove_old
+ )
+
+ LOGS.error(f"No valid conversion found for {input_file} to {convert_to or allowed_formats}")
+ return None
+
+ except Exception as e:
+ LOGS.exception(f"Error in convert: {str(e)}")
+ return None
def _get_value(stri):
diff --git a/pyUltroid/startup/BaseClient.py b/pyUltroid/startup/BaseClient.py
index 763159ce0..603121b52 100644
--- a/pyUltroid/startup/BaseClient.py
+++ b/pyUltroid/startup/BaseClient.py
@@ -128,6 +128,7 @@ async def fast_uploader(self, file, **kwargs):
with contextlib.suppress(FileNotFoundError):
os.remove(file)
return files["raw_file"], time.time() - start_time
+
from pyUltroid.fns.FastTelethon import upload_file
from pyUltroid.fns.helper import progress
diff --git a/pyUltroid/version.py b/pyUltroid/version.py
index 2bd0e369e..791e5438e 100644
--- a/pyUltroid/version.py
+++ b/pyUltroid/version.py
@@ -1,2 +1,2 @@
-__version__ = "2025.02.19"
-ultroid_version = "2.0"
+__version__ = "2025.02.23"
+ultroid_version = "2.1"
diff --git a/requirements.txt b/requirements.txt
index 30d2f6483..6231f9924 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,6 +1,11 @@
# Important Requirements here.
telethon
-# https://github.com/TeamUltroid/Telethon/archive/ultroid.zip
https://github.com/New-dev0/Telethon-Patch/archive/main.zip
python-decouple
python-dotenv
+telegraph
+enhancer
+requests
+aiohttp
+catbox-uploader
+cloudscraper
\ No newline at end of file
diff --git a/resources/startup/locals.py b/resources/startup/locals.py
index 94b1f68af..024cef332 100644
--- a/resources/startup/locals.py
+++ b/resources/startup/locals.py
@@ -76,6 +76,7 @@ def start():
print("\nCongrats. All done!\nTime to start the bot!")
print("\nInstalling requirements... This might take a while...")
os.system("pip3 install --no-cache-dir -r requirements.txt")
+ os.system("pip3 install -r requirements.txt --break-system-packages")
ask = input(
"Enter 'yes/y' to Install other requirements, required for local deployment."
)
diff --git a/resources/startup/optional-requirements.txt b/resources/startup/optional-requirements.txt
index 224c30080..2d5fe5806 100644
--- a/resources/startup/optional-requirements.txt
+++ b/resources/startup/optional-requirements.txt
@@ -1,7 +1,7 @@
# Required only for Local Deploys
# ------------------------------------------------------ #
-git+https://github.com/ufoptg/akipy.git
+akipy
apscheduler
aiohttp
bs4