diff --git a/.env.sample b/.env.sample deleted file mode 100644 index 79d989c855..0000000000 --- a/.env.sample +++ /dev/null @@ -1,12 +0,0 @@ -# Don't use quotes( " and ' ) - -API_ID= -API_HASH= -SESSION= -REDIS_URI= -REDIS_PASSWORD= - -# [OPTIONAL] - -LOG_CHANNEL= -BOT_TOKEN= diff --git a/.gitignore b/.gitignore index 794eba8b5a..b2f5a9dc07 100644 --- a/.gitignore +++ b/.gitignore @@ -1,44 +1,47 @@ .env *.session-journal *.session -build test* *.mp3 *.webm -*.webp *.mp4 *.tgs *.txt +script* +!runtime.txt +!requirements.txt /*.jpg /*.png /*.mp4 *.log -target/npmlist.json -package-lock.json -ultroid.json -resources/extras/thumbnail.jpg +temp* +resources/downloads/ +push.bat +modules/channels/ +modules/manager/ +localization/strings/ +ultroid*.json # Directories addons/ vcbot/ __pycache__/ venv/ -node_modules/ glitch_me/ src/glitch-me .idea/ .vscode/ temp/ -bin-debug/ -bin-release/ -[Oo]bj/ [Bb]in/ .settings/ *.swf *.air -*.ipa *.apk +*.webp +*.cpp +.vs +env # temporary files *.raw diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index a69d36986a..0000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,23 +0,0 @@ -# Welcome To Contributing Guide -Any contribution done to this repository will be appreciated! 🎉 - -### About Ultroid -- **Ultroid** is Telegram Userbot, which allow you to perform many task easily. -- It's base core is a pip package named [`pyUltroid`](https://GitHub.com/TeamUltroid/pyUltroid). -- This repository, contains Ultroid's official plugin files. -- moreover, Ultroid User also have an option to get more plugins available at [`UltroidAddons`](https://github.com/TeamUltroid/UltroidAddons) - -### Issues -- Search for existing Similar issues. -- You can open a issue first before contributing, If it contain some major changes like `bug fixes` or `feature addition`. -- If you are busy or getting trouble while making changes, you can just open the issue (explaining it). - -### Contributing -- You can [fork](https://github.com/TeamUltroid/Ultroid/fork) this repository. -- You can commits your changes now. -- You can [Git-Squash](https://docs.github.com/en/get-started/using-git/about-git-rebase) your commits, if they are more. [Optional] -- At last, You are ready to [`make a Pull Request`](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request). -- Make sure that, your `Pull Request` contain an explaining title and issue number if it closes any open issue. - -### Thanks -- Congrats! 💫 you have successfully made your Contribution to Ultroid. diff --git a/Dockerfile b/Dockerfile index f78f36cf70..c49b4505d0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,19 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2020-2023 TeamUltroid # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in . -FROM theteamultroid/ultroid:main +FROM python:latest # set timezone ENV TZ=Asia/Kolkata RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone -COPY installer.sh . +ADD . /root/TeamUltroid -RUN bash installer.sh - -# changing workdir WORKDIR "/root/TeamUltroid" +RUN ./ultroid install + # start the bot. -CMD ["bash", "startup"] +CMD ["./ultroid", "start"] \ No newline at end of file diff --git a/README.md b/README.md index b60ac89d0d..b0860bb1bb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- TeamUltroid Logo + TeamUltroid Logo

Ultroid - UserBot @@ -7,7 +7,7 @@ A stable pluggable Telegram userbot + Voice & Video Call music bot, based on Telethon. -[![](https://img.shields.io/badge/Ultroid-v0.8-crimson)](#) +[![](https://img.shields.io/badge/Ultroid-v1-blueviolet)](#) [![Stars](https://img.shields.io/github/stars/TeamUltroid/Ultroid?style=flat-square&color=yellow)](https://github.com/TeamUltroid/Ultroid/stargazers) [![Forks](https://img.shields.io/github/forks/TeamUltroid/Ultroid?style=flat-square&color=orange)](https://github.com/TeamUltroid/Ultroid/fork) [![Size](https://img.shields.io/github/repo-size/TeamUltroid/Ultroid?style=flat-square&color=green)](https://github.com/TeamUltroid/Ultroid/) @@ -33,7 +33,7 @@ # Tutorial - Full Tutorial - [![Full Tutorial](https://img.shields.io/badge/Watch%20Now-blue)](https://www.youtube.com/watch?v=0wAV7pUzhDQ) -- Tutorial to get Redis URL and password - [here.](./resources/extras/redistut.md) +- Tutorial to get Redis URL and password - [here.](./resources/images/redistut.md) --- ## Deploy to Heroku @@ -70,7 +70,7 @@ Get the [Necessary Variables](#Necessary-Variables) and then click the button be `pip(3) install -U -r requirements.txt` - Generate your `SESSION`: - For Linux users: - `bash sessiongen` + `bash ./ultroid session` or `wget -O session.py https://git.io/JY9JI && python3 session.py` - For Termux users: @@ -81,16 +81,15 @@ Get the [Necessary Variables](#Necessary-Variables) and then click the button be (You can either edit and rename the file or make a new file named `.env`.) - Run the bot: - Linux Users: - `bash startup` + `./ultroid start` - Windows Users: `python(3) -m pyUltroid` - --- ## Necessary Variables - `SESSION` - SessionString for your accounts login session. Get it from [here](#Session-String) One of the following database: -- For **Redis** (tutorial [here](./resources/extras/redistut.md)) +- For **Redis** (tutorial [here](./resources/images/redistut.md)) - `REDIS_URI` - Redis endpoint URL, from [redislabs](http://redislabs.com/). - `REDIS_PASSWORD` - Redis endpoint Password, from [redislabs](http://redislabs.com/). - For **MONGODB** @@ -118,5 +117,5 @@ Ultroid is licensed under [GNU Affero General Public License](https://www.gnu.or * [![TeamUltroid-Devs](https://img.shields.io/static/v1?label=Teamultroid&message=devs&color=critical)](https://t.me/UltroidDevs) * [Lonami](https://github.com/LonamiWebs/) for [Telethon.](https://github.com/LonamiWebs/Telethon) * [MarshalX](https://github.com/MarshalX) for [PyTgCalls.](https://github.com/MarshalX/tgcalls) - +* [Dan](https://github.com/delivrance) for [TgCrypto.](https://github.com/pyrogram/tgcrypto) > Made with 💕 by [@TeamUltroid](https://t.me/TeamUltroid). diff --git a/assistant/__init__.py b/assistant/__init__.py deleted file mode 100644 index e98ddeb85d..0000000000 --- a/assistant/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from telethon import Button, custom - -from plugins import ATRA_COL, InlinePlugin -from pyUltroid import * -from pyUltroid import _ult_cache -from pyUltroid._misc import owner_and_sudos -from pyUltroid._misc._assistant import asst_cmd, callback, in_pattern -from pyUltroid.fns.helper import * -from pyUltroid.fns.tools import get_stored_file -from strings import get_languages, get_string - -OWNER_NAME = ultroid_bot.full_name -OWNER_ID = ultroid_bot.uid - -AST_PLUGINS = {} - - -async def setit(event, name, value): - try: - udB.set_key(name, value) - except BaseException as er: - LOGS.exception(er) - return await event.edit("`Something Went Wrong`") - - -def get_back_button(name): - return [Button.inline("« Bᴀᴄᴋ", data=f"{name}")] diff --git a/assistant/games.py b/assistant/games.py deleted file mode 100644 index 2e730bfc47..0000000000 --- a/assistant/games.py +++ /dev/null @@ -1,324 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -""" -• `{i}akinator` | `/akinator` - Start akinator game from Userbot/Assistant - -• `/startgame` - Open Portal for Games -""" - -import asyncio -import operator -import re -import uuid -from html import unescape -from random import choice, shuffle - -from . import LOGS - -try: - import akinator -except ImportError: - akinator = None - LOGS.error("'akinator' not installed.") - -from telethon.errors.rpcerrorlist import ( - BotMethodInvalidError, - ChatSendStickersForbiddenError, -) -from telethon.events import Raw -from telethon.tl.types import InputMediaPoll, Poll, PollAnswer, UpdateMessagePollVote - -from pyUltroid._misc._decorators import ultroid_cmd -from pyUltroid.fns.helper import inline_mention -from pyUltroid.fns.tools import async_searcher - -from . import * - -# -------------------------- Akinator ----------------------- # - -games = {} -aki_photo = "https://graph.org/file/3cc8825c029fd0cab9edc.jpg" - - -@ultroid_cmd(pattern="akinator") -async def akina(e): - if not akinator: - return - sta = akinator.Akinator() - games.update({e.chat_id: {e.id: sta}}) - try: - m = await e.client.inline_query(asst.me.username, f"aki_{e.chat_id}_{e.id}") - await m[0].click(e.chat_id) - except BotMethodInvalidError: - await asst.send_file( - e.chat_id, - aki_photo, - buttons=Button.inline(get_string("aki_2"), data=f"aki_{e.chat_id}_{e.id}"), - ) - except Exception as er: - return await e.eor(f"**ERROR :** `{er}`") - if e.out: - await e.delete() - - -@asst_cmd(pattern="akinator", owner=True) -async def _akokk(e): - await akina(e) - - -@callback(re.compile("aki_(.*)"), owner=True) -async def doai(e): - adt = e.pattern_match.group(1).strip().decode("utf-8") - dt = adt.split("_") - ch = int(dt[0]) - mid = int(dt[1]) - await e.edit(get_string("com_1")) - try: - qu = games[ch][mid].start_game(child_mode=True) - # child mode should be promoted - except KeyError: - return await e.answer(get_string("aki_1"), alert=True) - bts = [Button.inline(o, f"aka_{adt}_{o}") for o in ["Yes", "No", "Idk"]] - cts = [Button.inline(o, f"aka_{adt}_{o}") for o in ["Probably", "Probably Not"]] - - bts = [bts, cts] - # ignored Back Button since it makes the Pagination looks Bad - await e.edit(f"Q. {qu}", buttons=bts) - - -@callback(re.compile("aka_(.*)"), owner=True) -async def okah(e): - mk = e.pattern_match.group(1).decode("utf-8").split("_") - ch = int(mk[0]) - mid = int(mk[1]) - ans = mk[2] - try: - gm = games[ch][mid] - except KeyError: - await e.answer(get_string("aki_3")) - return - text = gm.answer(ans) - if gm.progression >= 80: - gm.win() - gs = gm.first_guess - text = "It's " + gs["name"] + "\n " + gs["description"] - return await e.edit(text, file=gs["absolute_picture_path"]) - bts = [Button.inline(o, f"aka_{ch}_{mid}_{o}") for o in ["Yes", "No", "Idk"]] - cts = [ - Button.inline(o, f"aka_{ch}_{mid}_{o}") for o in ["Probably", "Probably Not"] - ] - - bts = [bts, cts] - await e.edit(text, buttons=bts) - - -@in_pattern(re.compile("aki_?(.*)"), owner=True) -async def eiagx(e): - bts = Button.inline(get_string("aki_2"), data=e.text) - ci = types.InputWebDocument(aki_photo, 0, "image/jpeg", []) - ans = [ - await e.builder.article( - "Akinator", - type="photo", - content=ci, - text="Akinator", - thumb=ci, - buttons=bts, - include_media=True, - ) - ] - await e.answer(ans) - - -# ----------------------- Main Command ------------------- # - -GIMAGES = [ - "https://graph.org/file/1c51015bae5205a65fd69.jpg", - "https://imgwhale.xyz/3xyr322l64j9590", -] - - -@asst_cmd(pattern="startgame", owner=True) -async def magic(event): - buttons = [ - [Button.inline("Trivia Quiz", "trzia")], - [Button.inline("Cancel ❌", "delit")], - ] - await event.reply( - get_string("games_1"), - file=choice(GIMAGES), - buttons=buttons, - ) - - -# -------------------------- Trivia ----------------------- # - -TR_BTS = {} -DIFI_KEYS = ["Easy", "Medium", "Hard"] -TRIVIA_CHATS = {} -POLLS = {} -CONGO_STICKER = [ - "CAADAgADSgIAAladvQrJasZoYBh68AI", - "CAADAgADXhIAAuyZKUl879mlR_dkOwI", - "CAADAgADpQAD9wLID-xfZCDwOI5LAg", - "CAADAgADjAADECECEFZM-SrKO9GgAg", - "CAADAgADSwIAAj-VzArAzNCDiGWAHAI", - "CAADAgADhQADwZxgDIuMHR9IU10iAg", - "CAADAgADiwMAAsSraAuoe2BwYu1sdQI", -] - - -@callback("delit", owner=True) -async def delete_it(event): - await event.delete() - - -@callback(re.compile("ctdown(.*)"), owner=True) -async def ct_spam(e): - n = e.data_match.group(1).decode("utf-8") - await e.answer(f"Wait {n} seconds..", alert=True) - - -@callback(re.compile("trzia(.*)"), owner=True) -async def choose_cata(event): - match = event.data_match.group(1).decode("utf-8") - if not match: - if TR_BTS.get("category"): - buttons = TR_BTS["category"] - else: - req = ( - await async_searcher( - "https://opentdb.com/api_category.php", re_json=True - ) - )["trivia_categories"] - btt = [] - for i in req: - name = i["name"] - if ":" in name: - name = name.split(":")[1] - btt.append(Button.inline(name, f"trziad_{i['id']}")) - buttons = list(zip(btt[::2], btt[1::2])) - if len(btt) % 2 == 1: - buttons.append((btt[-1],)) - buttons.append([Button.inline("Cancel ❌", "delit")]) - TR_BTS.update({"category": buttons}) - text = get_string("games_2") - elif match[0] == "d": - cat = match[1:] - buttons = [[Button.inline(i, f"trziac{cat}_{i}") for i in DIFI_KEYS]] - buttons.append(get_back_button("trzia")) - text = get_string("games_3") - elif match[0] == "c": - m = match[1:] - buttons = [[Button.inline(str(i), f"trziat{m}_{i}") for i in range(10, 70, 20)]] - text = get_string("games_4") - elif match[0] == "t": - m_ = match[1:] - buttons = [ - [Button.inline(str(i), f"trzias{m_}_{i}") for i in [10, 30, 60, 120]] - ] - text = get_string("games_5") - elif match[0] == "s": - chat = event.chat_id - cat, le, nu, in_ = match[2:].split("_") - msg = await event.edit(get_string("games_6").format(le, nu)) - for i in reversed(range(5)): - msg = await msg.edit(buttons=Button.inline(f"{i} ⏰", f"ctdown{i}")) - await asyncio.sleep(1) - await msg.edit( - msg.text + "\n\n• Send /cancel to stop the Quiz...", buttons=None - ) - qsss = await async_searcher( - f"https://opentdb.com/api.php?amount={nu}&category={cat}&difficulty={le.lower()}", - re_json=True, - ) - qs = qsss["results"] - if not qs: - await event.respond("Sorry, No Question Found for the given Criteria..") - await event.delete() - return - TRIVIA_CHATS.update({chat: {}}) - for copper, q in enumerate(qs): - 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.append( - PollAnswer(unescape(a), str(uuid.uuid1()).split("-")[0].encode()) - ) - for a in q["incorrect_answers"] - ] - shuffle(opts) - poll = InputMediaPoll( - Poll( - 0, - f"[{copper+1}]. " + unescape(q["question"]), - answers=opts, - public_voters=True, - quiz=True, - close_period=int(in_), - ), - correct_answers=[ansi], - solution="Join @TeamUltroid", - solution_entities=[], - ) - m_ = await event.client.send_message(chat, file=poll) - POLLS.update({m_.poll.poll.id: {"chat": m_.chat_id, "answer": ansi}}) - await asyncio.sleep(int(in_)) - if not TRIVIA_CHATS[chat]: - await event.respond( - "No-One Got Any Score in the Quiz!\nBetter Luck Next Time!" - ) - else: - try: - await event.respond(file=choice(CONGO_STICKER)) - except ChatSendStickersForbiddenError: - pass - LBD = "🎯 **Scoreboard of the Quiz.**\n\n" - TRC = TRIVIA_CHATS[chat] - if "cancel" in TRC.keys(): - del TRC["cancel"] - for userid, user_score in dict( - sorted(TRC.items(), key=operator.itemgetter(1), reverse=True) - ).items(): - user = inline_mention(await event.client.get_entity(userid)) - LBD += f"••• {user} - {user_score}\n" - await event.respond(LBD) - del TRIVIA_CHATS[chat] - list_ = list(POLLS.copy().keys()) - for key in list_: - if POLLS[key]["chat"] == chat: - del POLLS[key] - return - await event.edit(text, buttons=buttons) - - -@asst.on( - Raw(UpdateMessagePollVote, func=lambda x: TRIVIA_CHATS and POLLS.get(x.poll_id)) -) -async def pollish(eve): - if POLLS.get(eve.poll_id)["chat"] not in TRIVIA_CHATS.keys(): - return - if POLLS[eve.poll_id]["answer"] != eve.options[0]: - return - chat = POLLS.get(eve.poll_id)["chat"] - user = eve.user_id - if not TRIVIA_CHATS.get(chat, {}).get(user): - TRIVIA_CHATS[chat][user] = 1 - else: - TRIVIA_CHATS[chat][user] += 1 - - -@asst_cmd("cancel", owner=True, func=lambda x: TRIVIA_CHATS.get(x.chat_id)) -async def cancelish(event): - chat = TRIVIA_CHATS.get(event.chat_id) - chat.update({"cancel": True}) - await event.respond("Cancelled!") diff --git a/assistant/initial.py b/assistant/initial.py deleted file mode 100644 index f61223b47f..0000000000 --- a/assistant/initial.py +++ /dev/null @@ -1,84 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import re - -from . import * - -STRINGS = { - 1: """🎇 **Thanks for Deploying Ultroid Userbot!** - -• Here, are the Some Basic stuff from, where you can Know, about its Usage.""", - 2: """🎉** About Ultroid** - -🧿 Ultroid is Pluggable and powerful Telethon Userbot, made in Python from Scratch. It is Aimed to Increase Security along with Addition of Other Useful Features. - -❣ Made by **@TeamUltroid**""", - 3: """**💡• FAQs •** - --> [Username Tracker](https://t.me/UltroidUpdates/24) --> [Keeping Custom Addons Repo](https://t.me/UltroidUpdates/28) --> [Disabling Deploy message](https://t.me/UltroidUpdates/27) --> [Setting up TimeZone](https://t.me/UltroidUpdates/22) --> [About Inline PmPermit](https://t.me/UltroidUpdates/21) --> [About Dual Mode](https://t.me/UltroidUpdates/18) --> [Custom Thumbnail](https://t.me/UltroidUpdates/13) --> [About FullSudo](https://t.me/UltroidUpdates/11) --> [Setting Up PmBot](https://t.me/UltroidUpdates/2) --> [Also Check](https://t.me/UltroidUpdates/14) - -**• To Know About Updates** - - Join @TeamUltroid.""", - 4: f"""• `To Know All Available Commands` - - - `{HNDLR}help` - - `{HNDLR}cmds`""", - 5: """• **For Any Other Query or Suggestion** - - Move to **@UltroidSupportChat**. - -• Thanks for Reaching till END.""", -} - - -@callback(re.compile("initft_(\\d+)")) -async def init_depl(e): - CURRENT = int(e.data_match.group(1)) - if CURRENT == 5: - return await e.edit( - STRINGS[5], - buttons=Button.inline("<< Back", "initbk_4"), - link_preview=False, - ) - - await e.edit( - STRINGS[CURRENT], - buttons=[ - Button.inline("<<", f"initbk_{str(CURRENT - 1)}"), - Button.inline(">>", f"initft_{str(CURRENT + 1)}"), - ], - link_preview=False, - ) - - -@callback(re.compile("initbk_(\\d+)")) -async def ineiq(e): - CURRENT = int(e.data_match.group(1)) - if CURRENT == 1: - return await e.edit( - STRINGS[1], - buttons=Button.inline("Start Back >>", "initft_2"), - link_preview=False, - ) - - await e.edit( - STRINGS[CURRENT], - buttons=[ - Button.inline("<<", f"initbk_{str(CURRENT - 1)}"), - Button.inline(">>", f"initft_{str(CURRENT + 1)}"), - ], - link_preview=False, - ) diff --git a/assistant/inlinestuff.py b/assistant/inlinestuff.py deleted file mode 100644 index 97797aa330..0000000000 --- a/assistant/inlinestuff.py +++ /dev/null @@ -1,623 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import base64 -import inspect -from datetime import datetime -from html import unescape -from random import choice -from re import compile as re_compile - -from bs4 import BeautifulSoup as bs -from telethon import Button -from telethon.tl.alltlobjects import LAYER, tlobjects -from telethon.tl.types import DocumentAttributeAudio as Audio -from telethon.tl.types import InputWebDocument as wb - -from pyUltroid.fns.misc import google_search -from pyUltroid.fns.tools import ( - _webupload_cache, - async_searcher, - get_ofox, - saavn_search, - webuploader, -) - -from . import * -from . import _ult_cache - -SUP_BUTTONS = [ - [ - Button.url("• Repo •", url="https://github.com/TeamUltroid/Ultroid"), - Button.url("• Support •", url="t.me/UltroidSupportChat"), - ], -] - -ofox = "https://graph.org/file/231f0049fcd722824f13b.jpg" -gugirl = "https://graph.org/file/0df54ae4541abca96aa11.jpg" -ultpic = "https://graph.org/file/4136aa1650bc9d4109cc5.jpg" - -apis = [ - "QUl6YVN5QXlEQnNZM1dSdEI1WVBDNmFCX3c4SkF5NlpkWE5jNkZV", - "QUl6YVN5QkYwenhMbFlsUE1wOXh3TVFxVktDUVJxOERnZHJMWHNn", - "QUl6YVN5RGRPS253blB3VklRX2xiSDVzWUU0Rm9YakFLSVFWMERR", -] - - -@in_pattern("ofox", owner=True) -async def _(e): - try: - match = e.text.split(" ", maxsplit=1)[1] - except IndexError: - kkkk = e.builder.article( - title="Enter Device Codename", - thumb=wb(ofox, 0, "image/jpeg", []), - text="**OFᴏx🦊Rᴇᴄᴏᴠᴇʀʏ**\n\nYou didn't search anything", - buttons=Button.switch_inline("Sᴇᴀʀᴄʜ Aɢᴀɪɴ", query="ofox ", same_peer=True), - ) - return await e.answer([kkkk]) - device, releases = await get_ofox(match) - if device.get("detail") is None: - fox = [] - fullname = device["full_name"] - codename = device["codename"] - str(device["supported"]) - maintainer = device["maintainer"]["name"] - link = f"https://orangefox.download/device/{codename}" - for data in releases["data"]: - release = data["type"] - version = data["version"] - size = humanbytes(data["size"]) - release_date = datetime.utcfromtimestamp(data["date"]).strftime("%Y-%m-%d") - text = f"[\xad]({ofox})**OʀᴀɴɢᴇFᴏx Rᴇᴄᴏᴠᴇʀʏ Fᴏʀ**\n\n" - text += f"` Fᴜʟʟ Nᴀᴍᴇ: {fullname}`\n" - text += f"` Cᴏᴅᴇɴᴀᴍᴇ: {codename}`\n" - text += f"` Mᴀɪɴᴛᴀɪɴᴇʀ: {maintainer}`\n" - text += f"` Bᴜɪʟᴅ Tʏᴘᴇ: {release}`\n" - text += f"` Vᴇʀsɪᴏɴ: {version}`\n" - text += f"` Sɪᴢᴇ: {size}`\n" - text += f"` Bᴜɪʟᴅ Dᴀᴛᴇ: {release_date}`" - fox.append( - await e.builder.article( - title=f"{fullname}", - description=f"{version}\n{release_date}", - text=text, - thumb=wb(ofox, 0, "image/jpeg", []), - link_preview=True, - buttons=[ - Button.url("Dᴏᴡɴʟᴏᴀᴅ", url=f"{link}"), - Button.switch_inline( - "Sᴇᴀʀᴄʜ Aɢᴀɪɴ", query="ofox ", same_peer=True - ), - ], - ) - ) - await e.answer( - fox, switch_pm="OrangeFox Recovery Search.", switch_pm_param="start" - ) - else: - await e.answer( - [], switch_pm="OrangeFox Recovery Search.", switch_pm_param="start" - ) - - -@in_pattern("fl2lnk ?(.*)", owner=True) -async def _(e): - match = e.pattern_match.group(1) - chat_id, msg_id = match.split(":") - filename = _webupload_cache[int(chat_id)][int(msg_id)] - if "/" in filename: - filename = filename.split("/")[-1] - __cache = f"{chat_id}:{msg_id}" - buttons = [ - [ - Button.inline("anonfiles", data=f"flanonfiles//{__cache}"), - Button.inline("transfer", data=f"fltransfer//{__cache}"), - ], - [ - Button.inline("bayfiles", data=f"flbayfiles//{__cache}"), - Button.inline("x0.at", data=f"flx0.at//{__cache}"), - ], - [ - Button.inline("file.io", data=f"flfile.io//{__cache}"), - Button.inline("siasky", data=f"flsiasky//{__cache}"), - ], - ] - try: - lnk = [ - await e.builder.article( - title=f"Upload {filename}", - text=f"**File:**\n{filename}", - buttons=buttons, - ) - ] - except BaseException as er: - LOGS.exception(er) - lnk = [ - await e.builder.article( - title="fl2lnk", - text="File not found", - ) - ] - await e.answer(lnk, switch_pm="File to Link.", switch_pm_param="start") - - -@callback( - re_compile( - "fl(.*)", - ), - owner=True, -) -async def _(e): - t = (e.data).decode("UTF-8") - data = t[2:] - host = data.split("//")[0] - chat_id, msg_id = data.split("//")[1].split(":") - filename = _webupload_cache[int(chat_id)][int(msg_id)] - if "/" in filename: - filename = filename.split("/")[-1] - await e.edit(f"Uploading `{filename}` on {host}") - link = (await webuploader(chat_id, msg_id, host)).strip().replace("\n", "") - await e.edit(f"Uploaded `{filename}` on {host}.", buttons=Button.url("View", link)) - - -@in_pattern("repo", owner=True) -async def repo(e): - res = [ - await e.builder.article( - title="Ultroid Userbot", - description="Userbot | Telethon", - thumb=wb(ultpic, 0, "image/jpeg", []), - text="• **ULTROID USERBOT** •", - buttons=SUP_BUTTONS, - ), - ] - await e.answer(res, switch_pm="Ultroid Repo.", switch_pm_param="start") - - -@in_pattern("go", owner=True) -async def gsearch(q_event): - try: - match = q_event.text.split(maxsplit=1)[1] - except IndexError: - return await q_event.answer( - [], switch_pm="Google Search. Enter a query!", switch_pm_param="start" - ) - searcher = [] - gresults = await google_search(match) - for i in gresults: - try: - title = i["title"] - link = i["link"] - desc = i["description"] - searcher.append( - await q_event.builder.article( - title=title, - description=desc, - thumb=wb(gugirl, 0, "image/jpeg", []), - text=f"**Gᴏᴏɢʟᴇ Sᴇᴀʀᴄʜ**\n\n**••Tɪᴛʟᴇ••**\n`{title}`\n\n**••Dᴇsᴄʀɪᴘᴛɪᴏɴ••**\n`{desc}`", - link_preview=False, - buttons=[ - [Button.url("Lɪɴᴋ", url=f"{link}")], - [ - Button.switch_inline( - "Sᴇᴀʀᴄʜ Aɢᴀɪɴ", - query="go ", - same_peer=True, - ), - Button.switch_inline( - "Sʜᴀʀᴇ", - query=f"go {match}", - same_peer=False, - ), - ], - ], - ), - ) - except IndexError: - break - await q_event.answer(searcher, switch_pm="Google Search.", switch_pm_param="start") - - -@in_pattern("mods", owner=True) -async def _(e): - try: - quer = e.text.split(" ", maxsplit=1)[1] - except IndexError: - return await e.answer( - [], switch_pm="Mod Apps Search. Enter app name!", switch_pm_param="start" - ) - start = 0 * 3 + 1 - da = base64.b64decode(choice(apis)).decode("ascii") - url = f"https://www.googleapis.com/customsearch/v1?key={da}&cx=25b3b50edb928435b&q={quer}&start={start}" - data = await async_searcher(url, re_json=True) - search_items = data.get("items", []) - modss = [] - for a in search_items: - title = a.get("title") - desc = a.get("snippet") - link = a.get("link") - text = f"**••Tɪᴛʟᴇ••** `{title}`\n\n" - text += f"**Dᴇsᴄʀɪᴘᴛɪᴏɴ** `{desc}`" - modss.append( - await e.builder.article( - title=title, - description=desc, - text=text, - link_preview=True, - buttons=[ - [Button.url("Dᴏᴡɴʟᴏᴀᴅ", url=f"{link}")], - [ - Button.switch_inline( - "Mᴏʀᴇ Mᴏᴅs", - query="mods ", - same_peer=True, - ), - Button.switch_inline( - "Sʜᴀʀᴇ", - query=f"mods {quer}", - same_peer=False, - ), - ], - ], - ), - ) - await e.answer(modss, switch_pm="Search Mod Applications.", switch_pm_param="start") - - -APP_CACHE = {} -RECENTS = {} -PLAY_API = "https://googleplay.onrender.com/api/apps?q=" - - -@in_pattern("app", owner=True) -async def _(e): - try: - f = e.text.split(maxsplit=1)[1].lower() - except IndexError: - get_string("instu_1") - res = [] - if APP_CACHE and RECENTS.get(e.sender_id): - res.extend( - APP_CACHE[a][0] for a in RECENTS[e.sender_id] if APP_CACHE.get(a) - ) - return await e.answer( - res, switch_pm=get_string("instu_2"), switch_pm_param="start" - ) - try: - return await e.answer( - APP_CACHE[f], switch_pm="Application Searcher.", switch_pm_param="start" - ) - except KeyError: - pass - foles = [] - url = PLAY_API + f.replace(" ", "+") - aap = await async_searcher(url, re_json=True) - for z in aap["results"][:50]: - url = "https://play.google.com/store/apps/details?id=" + z["appId"] - name = z["title"] - desc = unescape(z["summary"])[:300].replace("
", "\n") + "..." - dev = z["developer"]["devId"] - text = f"**••Aᴘᴘ Nᴀᴍᴇ••** [{name}]({url})\n" - text += f"**••Dᴇᴠᴇʟᴏᴘᴇʀ••** `{dev}`\n" - text += f"**••Dᴇsᴄʀɪᴘᴛɪᴏɴ••**\n`{desc}`" - foles.append( - await e.builder.article( - title=name, - description=dev, - thumb=wb(z["icon"], 0, "image/jpeg", []), - text=text, - link_preview=True, - buttons=[ - [Button.url("Lɪɴᴋ", url=url)], - [ - Button.switch_inline( - "Mᴏʀᴇ Aᴘᴘs", - query="app ", - same_peer=True, - ), - Button.switch_inline( - "Sʜᴀʀᴇ", - query=f"app {f}", - same_peer=False, - ), - ], - ], - ), - ) - APP_CACHE.update({f: foles}) - if RECENTS.get(e.sender_id): - RECENTS[e.sender_id].append(f) - else: - RECENTS.update({e.sender_id: [f]}) - await e.answer(foles, switch_pm="Application Searcher.", switch_pm_param="start") - - -PISTON_URI = "https://emkc.org/api/v2/piston/" -PISTON_LANGS = {} - - -@in_pattern("run", owner=True) -async def piston_run(event): - try: - lang = event.text.split()[1] - code = event.text.split(maxsplit=2)[2] - except IndexError: - result = await event.builder.article( - title="Bad Query", - description="Usage: [Language] [code]", - thumb=wb( - "https://graph.org/file/e33c57fc5f1044547e4d8.jpg", 0, "image/jpeg", [] - ), - text=f'**Inline Usage**\n\n`@{asst.me.username} run python print("hello world")`\n\n[Language List](https://graph.org/Ultroid-09-01-6)', - ) - return await event.answer([result]) - if not PISTON_LANGS: - se = await async_searcher(f"{PISTON_URI}runtimes", re_json=True) - PISTON_LANGS.update({lang.pop("language"): lang for lang in se}) - if lang in PISTON_LANGS.keys(): - version = PISTON_LANGS[lang]["version"] - else: - result = await event.builder.article( - title="Unsupported Language", - description="Usage: [Language] [code]", - thumb=wb( - "https://graph.org/file/e33c57fc5f1044547e4d8.jpg", 0, "image/jpeg", [] - ), - text=f'**Inline Usage**\n\n`@{asst.me.username} run python print("hello world")`\n\n[Language List](https://graph.org/Ultroid-09-01-6)', - ) - return await event.answer([result]) - output = await async_searcher( - f"{PISTON_URI}execute", - post=True, - json={ - "language": lang, - "version": version, - "files": [{"content": code}], - }, - re_json=True, - ) - - output = output["run"]["output"] or get_string("instu_4") - if len(output) > 3000: - output = f"{output[:3000]}..." - result = await event.builder.article( - title="Result", - description=output, - text=f"• **Language:**\n`{lang}`\n\n• **Code:**\n`{code}`\n\n• **Result:**\n`{output}`", - thumb=wb( - "https://graph.org/file/871ee4a481f58117dccc4.jpg", 0, "image/jpeg", [] - ), - buttons=Button.switch_inline("Fork", query=event.text, same_peer=True), - ) - await event.answer([result], switch_pm="• Piston •", switch_pm_param="start") - - -FDROID_ = {} - - -@in_pattern("fdroid", owner=True) -async def do_magic(event): - try: - match = event.text.split(" ", maxsplit=1)[1].lower() - except IndexError: - return await event.answer( - [], switch_pm="Enter Query to Search", switch_pm_param="start" - ) - if FDROID_.get(match): - return await event.answer( - FDROID_[match], switch_pm=f"• Results for {match}", switch_pm_param="start" - ) - link = "https://search.f-droid.org/?q=" + match.replace(" ", "+") - content = await async_searcher(link, re_content=True) - BSC = bs(content, "html.parser", from_encoding="utf-8") - ress = [] - for dat in BSC.find_all("a", "package-header")[:10]: - image = dat.find("img", "package-icon")["src"] - if image.endswith("/"): - image = "https://graph.org/file/a8dd4a92c5a53a89d0eff.jpg" - title = dat.find("h4", "package-name").text.strip() - desc = dat.find("span", "package-summary").text.strip() - text = f"• **Name :** `{title}`\n\n" - text += f"• **Description :** `{desc}`\n" - text += f"• **License :** `{dat.find('span', 'package-license').text.strip()}`" - imga = wb(image, 0, "image/jpeg", []) - ress.append( - await event.builder.article( - title=title, - type="photo", - description=desc, - text=text, - content=imga, - thumb=imga, - include_media=True, - buttons=[ - Button.inline( - "• Download •", "fd" + dat["href"].split("packages/")[-1] - ), - Button.switch_inline("• Share •", query=event.text), - ], - ) - ) - msg = f"Showing {len(ress)} Results!" if ress else "No Results Found" - FDROID_.update({match: ress}) - await event.answer(ress, switch_pm=msg, switch_pm_param="start") - - -# Thanks to OpenSource -_bearer_collected = [ - "AAAAAAAAAAAAAAAAAAAAALIKKgEAAAAA1DRuS%2BI7ZRKiagD6KHYmreaXomo%3DP5Vaje4UTtEkODg0fX7nCh5laSrchhtLxeyEqxXpv0w9ZKspLD", - "AAAAAAAAAAAAAAAAAAAAAL5iUAEAAAAAmo6FYRjqdKlI3cNziIm%2BHUQB9Xs%3DS31pj0mxARMTOk2g9dvQ1yP9wknvY4FPBPUlE00smJcncw4dPR", - "AAAAAAAAAAAAAAAAAAAAAN6sVgEAAAAAMMjMMWrwgGyv7YQOWN%2FSAsO5SGM%3Dg8MG9Jq93Rlllaok6eht7HvRCruN4Vpzp4NaVsZaaHHWSTzKI8", -] - - -@in_pattern("twitter", owner=True) -async def twitter_search(event): - try: - match = event.text.split(maxsplit=1)[1].lower() - except IndexError: - return await event.answer( - [], switch_pm="Enter Query to Search", switch_pm_param="start" - ) - try: - return await event.answer( - _ult_cache["twitter"][match], - switch_pm="• Twitter Search •", - switch_pm_param="start", - ) - except KeyError: - pass - headers = {"Authorization": f"bearer {choice(_bearer_collected)}"} - res = await async_searcher( - f"https://api.twitter.com/1.1/users/search.json?q={match}", - headers=headers, - re_json=True, - ) - reso = [] - for user in res: - thumb = wb(user["profile_image_url_https"], 0, "image/jpeg", []) - if user.get("profile_banner_url"): - url = user["profile_banner_url"] - text = f"[\xad]({url})• **Name :** `{user['name']}`\n" - else: - text = f"• **Name :** `{user['name']}`\n" - text += f"• **Description :** `{user['description']}`\n" - text += f"• **Username :** `@{user['screen_name']}`\n" - text += f"• **Followers :** `{user['followers_count']}` • **Following :** `{user['friends_count']}`\n" - pro_ = "https://twitter.com/" + user["screen_name"] - text += f"• **Link :** [Click Here]({pro_})\n_" - reso.append( - await event.builder.article( - title=user["name"], - description=user["description"], - url=pro_, - text=text, - thumb=thumb, - ) - ) - swi_ = f"🐦 Showing {len(reso)} Results!" if reso else "No User Found :(" - await event.answer(reso, switch_pm=swi_, switch_pm_param="start") - if _ult_cache.get("twitter"): - _ult_cache["twitter"].update({match: reso}) - else: - _ult_cache.update({"twitter": {match: reso}}) - - -_savn_cache = {} - - -@in_pattern("saavn", owner=True) -async def savn_s(event): - try: - query = event.text.split(maxsplit=1)[1].lower() - except IndexError: - return await event.answer( - [], switch_pm="Enter Query to search 🔍", switch_pm_param="start" - ) - if query in _savn_cache: - return await event.answer( - _savn_cache[query], - switch_pm=f"Showing Results for {query}", - switch_pm_param="start", - ) - results = await saavn_search(query) - swi = "🎵 Saavn Search" if results else "No Results Found!" - res = [] - for song in results: - thumb = wb(song["image"], 0, "image/jpeg", []) - text = f"• **Title :** {song['title']}" - text += f"\n• **Year :** {song['year']}" - text += f"\n• **Lang :** {song['language']}" - text += f"\n• **Artist :** {song['artists']}" - text += f"\n• **Release Date :** {song['release_date']}" - res.append( - await event.builder.article( - title=song["title"], - description=song["artists"], - type="audio", - text=text, - include_media=True, - buttons=Button.switch_inline( - "Search Again 🔍", query="saavn", same_peer=True - ), - thumb=thumb, - content=wb( - song["url"], - 0, - "audio/mp4", - [ - Audio( - title=song["title"], - duration=int(song["duration"]), - performer=song["artists"], - ) - ], - ), - ) - ) - await event.answer(res, switch_pm=swi, switch_pm_param="start") - _savn_cache.update({query: res}) - - -@in_pattern("tl", owner=True) -async def inline_tl(ult): - try: - match = ult.text.split(maxsplit=1)[1] - except IndexError: - text = f"**Telegram TlObjects Searcher.**\n__(Don't use if you don't know what it is!)__\n\n• Example Usage\n`@{asst.me.username} tl GetFullUserRequest`" - return await ult.answer( - [ - await ult.builder.article( - title="How to Use?", - description="Tl Searcher by Ultroid", - url="https://t.me/TeamUltroid", - text=text, - ) - ], - switch_pm="Tl Search 🔍", - switch_pm_param="start", - ) - res = [] - for key in tlobjects.values(): - if match.lower() in key.__name__.lower(): - tyyp = "Function" if "tl.functions." in str(key) else "Type" - text = f"**Name:** `{key.__name__}`\n" - text += f"**Category:** `{tyyp}`\n" - text += f"\n`from {key.__module__} import {key.__name__}`\n\n" - if args := str(inspect.signature(key))[1:][:-1]: - text += "**Parameter:**\n" - for para in args.split(","): - text += " " * 4 + "`" + para + "`\n" - text += f"\n**Layer:** `{LAYER}`" - res.append( - await ult.builder.article( - title=key.__name__, - description=tyyp, - url="https://t.me/TeamUltroid", - text=text[:4000], - ) - ) - mo = f"Showing {len(res)} results!" if res else f"No Results for {match}!" - await ult.answer(res[:50], switch_pm=mo, switch_pm_param="start") - - -InlinePlugin.update( - { - "Pʟᴀʏ Sᴛᴏʀᴇ Aᴘᴘs": "app telegram", - "Mᴏᴅᴅᴇᴅ Aᴘᴘs": "mods minecraft", - "Sᴇᴀʀᴄʜ Oɴ Gᴏᴏɢʟᴇ": "go TeamUltroid", - "WʜɪSᴘᴇʀ": "wspr @username Hello🎉", - "YᴏᴜTᴜʙᴇ Dᴏᴡɴʟᴏᴀᴅᴇʀ": "yt Ed Sheeran Perfect", - "Piston Eval": "run javascript console.log('Hello Ultroid')", - "OʀᴀɴɢᴇFᴏx🦊": "ofox beryllium", - "Tᴡɪᴛᴛᴇʀ Usᴇʀ": "twitter theultroid", - "Fᴅʀᴏɪᴅ Sᴇᴀʀᴄʜ": "fdroid telegram", - "Sᴀᴀᴠɴ sᴇᴀʀᴄʜ": "saavn", - "Tʟ Sᴇᴀʀᴄʜ": "tl", - } -) diff --git a/assistant/localization.py b/assistant/localization.py deleted file mode 100644 index 549ee6aa67..0000000000 --- a/assistant/localization.py +++ /dev/null @@ -1,47 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import re - -from . import ( - Button, - ULTConfig, - callback, - get_back_button, - get_languages, - get_string, - udB, -) - - -@callback("lang", owner=True) -async def setlang(event): - languages = get_languages() - tultd = [ - Button.inline( - f"{languages[ult]['natively']} [{ult.lower()}]", - data=f"set_{ult}", - ) - for ult in languages - ] - buttons = list(zip(tultd[::2], tultd[1::2])) - if len(tultd) % 2 == 1: - buttons.append((tultd[-1],)) - buttons.append([Button.inline("« Back", data="mainmenu")]) - await event.edit(get_string("ast_4"), buttons=buttons) - - -@callback(re.compile(b"set_(.*)"), owner=True) -async def settt(event): - lang = event.data_match.group(1).decode("UTF-8") - languages = get_languages() - ULTConfig.lang = lang - udB.del_key("language") if lang == "en" else udB.set_key("language", lang) - await event.edit( - f"Your language has been set to {languages[lang]['natively']} [{lang}].", - buttons=get_back_button("lang"), - ) diff --git a/assistant/manager/__init__.py b/assistant/manager/__init__.py deleted file mode 100644 index e0aa0a0051..0000000000 --- a/assistant/manager/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from pyUltroid._misc._decorators import ultroid_cmd -from pyUltroid.fns.helper import inline_mention - -from .. import * diff --git a/assistant/manager/_help.py b/assistant/manager/_help.py deleted file mode 100644 index 3c7ab38ed9..0000000000 --- a/assistant/manager/_help.py +++ /dev/null @@ -1,134 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import * - -START = """ -🪅 **Help Menu** 🪅 - -✘ /start : Check I am Alive or not. -✘ /help : Get This Message. -✘ /repo : Get Bot's Repo.. - -🧑‍💻 Join **@TeamUltroid** -""" - -ADMINTOOLS = """✘ **AdminTools** ✘ - -• /pin : Pins the Replied Message -• /pinned : Get Pinned message in chat. -• /unpin : Unpin the Replied message -• /unpin all : Unpin all Pinned Messages. - -• /ban (username/id/reply) : Ban the User -• /unban (username/id/reply) : UnBan the User. - -• /mute (username/id/reply) : Mute the User. -• /unmute (username/id/reply) : Unmute the User. - -• /tban (username/id/reply) (time) : Temporary ban a user -• /tmute (username/id/reply) (time) : temporary Mutes a User. - -• /purge (purge messages) - -• /setgpic (reply photo) : keep Chat Photo of Group. -• /delgpic : remove current chat Photo.""" - -UTILITIES = """ -✘ ** Utilities ** ✘ - -• /info (reply/username/id) : get detailed info of user. -• /id : get chat/user id. -• /tr : Translate Languages.. -• /q : Create Quotes. - -• /paste (reply file/text) : paste content on Spaceb.in -• /meaning (text) : Get Meaning of that Word. -• /google (query) : Search Something on Google.. - -• /suggest (query/reply) : Creates a Yes / No Poll. -""" - -LOCKS = """ -✘ ** Locks ** ✘ - -• /lock (query) : lock particular content in chat. -• /unlock (query) : Unlock some content. - -• All Queries -- `msgs` : for messages. -- `inlines` : for inline queries. -- `media` : for all medias. -- `games` : for games. -- `sticker` : for stickers. -- `polls` : for polls. -- `gif` : for gifs. -- `pin` : for pins. -- `changeinfo` : for change info right. -""" - -MISC = """ -✘ **Misc** ✘ - -• /joke : Get Random Jokes. -• /decide : Decide Something.. - -**✘ Stickertools ✘** -• /kang : add sticker to your pack. -• /listpack : get all of yours pack.. -""" - -STRINGS = {"Admintools": ADMINTOOLS, "locks": LOCKS, "Utils": UTILITIES, "Misc": MISC} - -MNGE = udB.get_key("MNGR_EMOJI") or "•" - - -def get_buttons(): - BTTS = [] - keys = STRINGS.copy() - while keys: - BT = [] - for i in list(keys)[:2]: - text = f"{MNGE} {i} {MNGE}" - BT.append(Button.inline(text, f"hlp_{i}")) - del keys[i] - BTTS.append(BT) - url = f"https://t.me/{asst.me.username}?startgroup=true" - BTTS.append([Button.url("Add me to Group", url)]) - return BTTS - - -@asst_cmd(pattern="help") -async def helpish(event): - if not event.is_private: - url = f"https://t.me/{asst.me.username}?start=start" - return await event.reply( - "Contact me in PM for help!", buttons=Button.url("Click me for Help", url) - ) - if str(event.sender_id) in owner_and_sudos() and ( - udB.get_key("DUAL_MODE") and (udB.get_key("DUAL_HNDLR") == "/") - ): - return - await event.reply(START, buttons=get_buttons()) - - -@callback("mngbtn", owner=True) -async def ehwhshd(e): - buttons = get_buttons() - buttons.append([Button.inline("<< Back", "open")]) - await e.edit(buttons=buttons) - - -@callback("mnghome") -async def home_aja(e): - await e.edit(START, buttons=get_buttons()) - - -@callback(re.compile("hlp_(.*)")) -async def do_something(event): - match = event.pattern_match.group(1).strip().decode("utf-8") - await event.edit(STRINGS[match], buttons=Button.inline("<< Back", "mnghome")) diff --git a/assistant/manager/_on_adds.py b/assistant/manager/_on_adds.py deleted file mode 100644 index a68f72f285..0000000000 --- a/assistant/manager/_on_adds.py +++ /dev/null @@ -1,23 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from telethon import events - -from . import * - - -@asst.on(events.ChatAction(func=lambda x: x.user_added)) -async def dueha(e): - user = await e.get_user() - if not user.is_self: - return - sm = udB.get_key("ON_MNGR_ADD") - if sm == "OFF": - return - if not sm: - sm = "Thanks for Adding me :)" - await e.reply(sm, link_preview=False) diff --git a/assistant/manager/admins.py b/assistant/manager/admins.py deleted file mode 100644 index a8e1ebd154..0000000000 --- a/assistant/manager/admins.py +++ /dev/null @@ -1,50 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import re - -from telethon.errors.rpcerrorlist import UserNotParticipantError - -from pyUltroid import _ult_cache - -from . import * - - -@ultroid_cmd(pattern="d(kick|ban)", manager=True, require="ban_users") -async def dowj(e): - replied = await e.get_reply_message() - if replied: - user = replied.sender_id - else: - return await e.eor("Reply to a message...") - try: - await replied.delete() - if e.pattern_match.group(1).strip() == "kick": - await e.client.kick_participant(e.chat_id, user) - te = "Kicked" - else: - await e.client.edit_permissions(e.chat_id, user, view_messages=False) - te = "Banned" - await e.eor(f"{te} Successfully!") - except Exception as E: - await e.eor(str(E)) - - -@callback(re.compile("cc_(.*)"), func=_ult_cache.get("admin_callback")) -async def callback_(event): - data = event.data_match.group(1).decode("utf-8") - if data not in _ult_cache.get("admin_callback", {}): - return - try: - perm = await event.client.get_permissions(event.chat_id, event.sender_id) - except UserNotParticipantError: - return await event.answer("Join the Group First!", alert=True) - if not perm.is_admin: - return await event.answer("You are not an Admin!", alert=True) - _ult_cache["admin_callback"].update({data: (event.sender, perm)}) - await event.answer("Verification Done!") - await event.delete() diff --git a/assistant/manager/afk.py b/assistant/manager/afk.py deleted file mode 100644 index 659561146e..0000000000 --- a/assistant/manager/afk.py +++ /dev/null @@ -1,110 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from datetime import datetime as dt - -from telethon.events import NewMessage -from telethon.tl.types import ( - Message, - MessageEntityMention, - MessageEntityMentionName, - User, -) -from telethon.utils import get_display_name - -from pyUltroid.fns.helper import inline_mention, time_formatter - -from . import asst, asst_cmd - -AFK = {} - - -@asst_cmd(pattern="afk", func=lambda x: not x.is_private) -async def go_afk(event): - sender = await event.get_sender() - if (not isinstance(sender, User)) or sender.bot: - return - try: - reason = event.text.split(" ", maxsplit=1)[1] - except IndexError: - reason = None - if event.is_reply and not reason: - replied = await event.get_reply_message() - if not reason and replied.text and not replied.media: - reason = replied.text - else: - reason = replied - time_ = dt.now() - if AFK.get(event.chat_id): - AFK[event.chat_id].update({event.sender_id: {"reason": reason, "time": time_}}) - else: - AFK.update( - {event.chat_id: {event.sender_id: {"reason": reason, "time": time_}}} - ) - mention = inline_mention(sender) - msg = f"**{mention} went AFK Now!**" - if reason and not isinstance(reason, str): - await event.reply(reason) - else: - msg += f"\n\n**Reason : ** `{reason}`" - await event.reply(msg) - - -@asst.on(NewMessage(func=lambda x: AFK.get(x.chat_id) and not x.is_private)) -async def make_change(event): - if event.text.startswith("/afk"): - return - sender = await event.get_sender() - if (not isinstance(sender, User)) or sender.bot: - return - chat_ = AFK[event.chat_id] - if event.sender_id in chat_.keys(): - name = get_display_name(event.sender) - cha_send = chat_[event.sender_id] - time_ = time_formatter((dt.now() - cha_send["time"]).seconds * 1000) - msg = f"**{name}** is No Longer AFK!\n**Was AFK for** {time_}" - await event.reply(msg) - del chat_[event.sender_id] - if not chat_: - del AFK[event.chat_id] - ST_SPAM = [] - replied = await event.get_reply_message() - if replied: - name = get_display_name(replied.sender) - if replied.sender_id in chat_.keys(): - s_der = chat_[replied.sender_id] - res_ = s_der["reason"] - time_ = time_formatter((dt.now() - s_der["time"]).seconds * 1000) - msg = f"**{name}** is AFK Currently!\n**From :** {time_}" - if res_ and isinstance(res_, str): - msg += f"\n**Reason :** {res_}" - elif res_ and isinstance(res_, Message): - await event.reply(res_) - await event.reply(msg) - ST_SPAM.append(replied.sender_id) - for ent, text in event.get_entities_text(): - dont_send, entity = None, None - if isinstance(ent, MessageEntityMentionName): - c_id = ent.user_id - elif isinstance(ent, MessageEntityMention): - c_id = text - else: - c_id = None - if c_id: - entity = await event.client.get_entity(c_id) - if entity and entity.id in chat_.keys() and entity.id not in ST_SPAM: - ST_SPAM.append(entity.id) - s_der = chat_[entity.id] - name = get_display_name(entity) - res_ = s_der["reason"] - time_ = time_formatter((dt.now() - s_der["time"]).seconds * 1000) - msg = f"**{name}** is AFK Currently!\n**From :** {time_}" - if res_ and isinstance(res_, str): - msg += f"\n**Reason :** {res_}" - elif res_ and isinstance(res_, Message): - await event.reply(res_) - await event.reply(msg) diff --git a/assistant/manager/misc.py b/assistant/manager/misc.py deleted file mode 100644 index ff721c7d5a..0000000000 --- a/assistant/manager/misc.py +++ /dev/null @@ -1,64 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -import random - -import aiohttp - -from pyUltroid.dB import DEVLIST -from pyUltroid.fns.admins import admin_check - -from . import * - - -@asst_cmd(pattern="decide") -async def dheh(e): - text = ["Yes", "NoU", "Maybe", "IDK"] - text = random.choice(text) - ri = e.reply_to_msg_id or e.id - await e.client.send_message(e.chat_id, text, reply_to=ri) - - -@asst_cmd(pattern="echo( (.*)|$)") -async def oqha(e): - if not await admin_check(e): - return - if match := e.pattern_match.group(1).strip(): - text = match - reply_to = e - elif e.is_reply: - text = (await e.get_reply_message()).text - reply_to = e.reply_to_msg_id - else: - return await e.eor("What to Echo?", time=5) - try: - await e.delete() - except BaseException as ex: - LOGS.error(ex) - await e.client.send_message(e.chat_id, text, reply_to=reply_to) - - -@asst_cmd(pattern="kickme$") -async def doit(e): - if e.sender_id in DEVLIST: - return await eod(e, "`I will Not Kick You, my Developer..`") - try: - await e.client.kick_participant(e.chat_id, e.sender_id) - except Exception as Fe: - return await e.eor(str(Fe), time=5) - await e.eor("Yes, You are right, get out.", time=5) - - -@asst_cmd(pattern="joke$") -async def do_joke(e): - e = await e.get_reply_message() if e.is_reply else e - link = "https://v2.jokeapi.dev/joke/Any?blacklistFlags=nsfw,religious,political,racist,sexist,explicit&type=single" - async with aiohttp.ClientSession() as ses: - async with ses.get(link) as out: - out = await out.json() - await e.reply(out["joke"]) diff --git a/assistant/manager/stickermanager.py b/assistant/manager/stickermanager.py deleted file mode 100644 index a88c018a3c..0000000000 --- a/assistant/manager/stickermanager.py +++ /dev/null @@ -1,180 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import random - -from telethon import errors -from telethon.errors.rpcerrorlist import StickersetInvalidError -from telethon.tl.functions.messages import GetStickerSetRequest as GetSticker -from telethon.tl.functions.messages import UploadMediaRequest -from telethon.tl.functions.stickers import AddStickerToSetRequest as AddSticker -from telethon.tl.functions.stickers import CreateStickerSetRequest -from telethon.tl.types import InputPeerSelf -from telethon.tl.types import InputStickerSetItem as SetItem -from telethon.tl.types import InputStickerSetShortName, User -from telethon.utils import get_display_name, get_input_document - -from pyUltroid.fns.misc import Quotly -from pyUltroid.fns.tools import TgConverter - -from . import LOGS, asst, asst_cmd, udB - - -@asst_cmd( - pattern="kang", -) -async def kang_cmd(ult): - sender = await ult.get_sender() - if not isinstance(sender, User): - return - if not ult.is_reply: - return await ult.eor("`Reply to a sticker/photo..`", time=5) - reply = await ult.get_reply_message() - if sender.username: - pre = sender.username[:4] - else: - pre = random.random_string(length=3) - animated, dl, video = None, None, None - try: - emoji = ult.text.split(maxsplit=1)[1] - except IndexError: - emoji = None - if reply.sticker: - file = get_input_document(reply.sticker) - emoji = emoji or reply.file.emoji - name = reply.file.name - if name.endswith(".tgs"): - animated = True - dl = await reply.download_media() - elif name.endswith(".webm"): - video = True - dl = await reply.download_media() - elif reply.photo: - dl = await reply.download_media() - name = "sticker.webp" - image = TgConverter.resize_photo_sticker(dl) - image.save(name, "WEBP") - elif reply.text: - dl = await Quotly().create_quotly(reply) - else: - return await ult.eor("`Reply to sticker or text to add it in your pack...`") - if not emoji: - emoji = "🏵" - if dl: - upl = await ult.client.upload_file(dl) - file = get_input_document( - await ult.client(UploadMediaRequest(InputPeerSelf(), upl)) - ) - get_ = udB.get_key("STICKERS") or {} - type_ = "anim" if animated else "static" - if not get_.get(ult.sender_id) or not get_.get(ult.sender_id, {}).get(type_): - sn = f"{pre}_{ult.sender_id}" - title = f"{get_display_name(sender)}'s Kang Pack" - if animated: - type_ = "anim" - sn += "_anim" - title += " (Animated)" - elif video: - type_ = "vid" - sn += "_vid" - title += " (Video)" - sn += f"_by_{asst.me.username}" - try: - await asst(GetSticker(InputStickerSetShortName(sn), hash=0)) - sn = sn.replace(str(ult.sender_id), f"{ult.sender_id}_{ult.id}") - except StickersetInvalidError: - pass - try: - pack = await ult.client( - CreateStickerSetRequest( - user_id=sender.id, - title=title, - short_name=sn, - stickers=[SetItem(file, emoji=emoji)], - videos=video, - animated=animated, - software="@TeamUltroid", - ) - ) - except Exception as er: - return await ult.eor(str(er)) - sn = pack.set.short_name - if not get_.get(ult.sender_id): - get_.update({ult.sender_id: {type_: [sn]}}) - else: - get_[ult.sender_id].update({type_: [sn]}) - udB.set_key("STICKERS", get_) - return await ult.reply( - f"**Kanged Successfully!\nEmoji :** {emoji}\n**Link :** [Click Here](https://t.me/addstickers/{sn})" - ) - name = get_[ult.sender_id][type_][-1] - try: - await asst(GetSticker(InputStickerSetShortName(name), hash=0)) - except StickersetInvalidError: - get_[ult.sender_id][type_].remove(name) - try: - await asst( - AddSticker(InputStickerSetShortName(name), SetItem(file, emoji=emoji)) - ) - except (errors.StickerpackStickersTooMuchError, errors.StickersTooMuchError): - sn = f"{pre}{ult.sender_id}_{ult.id}" - title = f"{get_display_name(sender)}'s Kang Pack" - if animated: - sn += "_anim" - title += " (Animated)" - elif video: - sn += "_vid" - title += "(Video)" - sn += f"_by_{asst.me.username}" - try: - pack = await ult.client( - CreateStickerSetRequest( - user_id=sender.id, - title=title, - short_name=sn, - stickers=[SetItem(file, emoji=emoji)], - animated=animated, - ) - ) - except Exception as er: - return await ult.eor(str(er)) - get_[ult.sender_id][type_].append(pack.set.short_name) - udB.set_key("STICKERS", get_) - return await ult.reply( - f"**Created New Kang Pack!\nEmoji :** {emoji}\n**Link :** [Click Here](https://t.me/addstickers/{sn})" - ) - except Exception as er: - LOGS.exception(er) - return await ult.reply(str(er)) - await ult.reply( - f"Sticker Added to Pack Successfully\n**Link :** [Click Here](https://t.me/addstickers/{name})" - ) - - -@asst_cmd(pattern="listpack") -async def do_magic(ult): - ko = udB.get_key("STICKERS") or {} - if not ko.get(ult.sender_id): - return await ult.reply("No Sticker Pack Found!") - al_ = [] - ul = ko[ult.sender_id] - for _ in ul.keys(): - al_.extend(ul[_]) - msg = "• **Stickers Owned by You!**\n\n" - for _ in al_: - try: - pack = await ult.client(GetSticker(InputStickerSetShortName(_), hash=0)) - msg += f"• [{pack.set.title}](https://t.me/addstickers/{_})\n" - except StickerSetInvalidError: - if ul.get("anim") and _ in ul["anim"]: - ul["anim"].remove(_) - elif ul.get("vid") and _ in ul["vid"]: - ul["vid"].remove(_) - else: - ul["static"].remove(_) - udB.set_key("STICKERS", ko) - await ult.reply(msg) diff --git a/assistant/pmbot.py b/assistant/pmbot.py deleted file mode 100644 index 62b06e20af..0000000000 --- a/assistant/pmbot.py +++ /dev/null @@ -1,150 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -# https://github.com/xditya/TeleBot/blob/master/telebot/plugins/mybot/pmbot/incoming.py - -# --------------------------------------- Imports -------------------------------------------- # - -import os - -from telethon.errors.rpcerrorlist import UserNotParticipantError -from telethon.tl.custom import Button -from telethon.tl.functions.channels import GetFullChannelRequest -from telethon.tl.functions.messages import GetFullChatRequest -from telethon.tl.types import Channel, Chat -from telethon.utils import get_display_name - -from pyUltroid.dB.base import KeyManager -from pyUltroid.dB.botchat_db import * -from pyUltroid.fns.helper import inline_mention - -from . import * - -botb = KeyManager("BOTBLS", cast=list) -FSUB = udB.get_key("PMBOT_FSUB") -CACHE = {} -# --------------------------------------- Incoming -------------------------------------------- # - - -@asst_cmd( - load=AST_PLUGINS, - incoming=True, - func=lambda e: e.is_private and not botb.contains(e.sender_id), -) -async def on_new_mssg(event): - who = event.sender_id - # doesn't reply to that user anymore - if event.text.startswith("/") or who == OWNER_ID: - return - if FSUB: - MSG = "" - BTTS = [] - for chat in FSUB: - try: - await event.client.get_permissions(chat, event.sender_id) - except UserNotParticipantError: - if not MSG: - MSG += get_string("pmbot_1") - try: - uri = "" - TAHC_ = await event.client.get_entity(chat) - if hasattr(TAHC_, "username") and TAHC_.username: - uri = f"t.me/{TAHC_.username}" - elif CACHE.get(chat): - uri = CACHE[chat] - else: - if isinstance(TAHC_, Channel): - FUGB = await event.client(GetFullChannelRequest(chat)) - elif isinstance(TAHC_, Chat): - FUGB = await event.client(GetFullChatRequest(chat)) - else: - return - if FUGB.full_chat.exported_invite: - CACHE[chat] = FUGB.full_chat.exported_invite.link - uri = CACHE[chat] - BTTS.append(Button.url(get_display_name(TAHC_), uri)) - except Exception as er: - LOGS.exception(f"Error On PmBot Force Sub!\n - {chat} \n{er}") - if MSG and BTTS: - return await event.reply(MSG, buttons=BTTS) - xx = await event.forward_to(OWNER_ID) - if event.fwd_from: - await xx.reply(f"From {inline_mention(event.sender)} [`{event.sender_id}`]") - add_stuff(xx.id, who) - - -# --------------------------------------- Outgoing -------------------------------------------- # - - -@asst_cmd( - load=AST_PLUGINS, - from_users=[OWNER_ID], - incoming=True, - func=lambda e: e.is_private and e.is_reply, -) -async def on_out_mssg(event): - x = event.reply_to_msg_id - to_user = get_who(x) - if event.text.startswith("/who"): - try: - k = await asst.get_entity(to_user) - photu = await event.client.download_profile_photo(k.id) - await event.reply( - f"• **Name :** {get_display_name(k)}\n• **ID :** `{k.id}`\n• **Link :** {inline_mention(k)}", - file=photu, - ) - if photu: - os.remove(photu) - return - except BaseException as er: - return await event.reply(f"**ERROR : **{str(er)}") - elif event.text.startswith("/"): - return - if to_user: - await asst.send_message(to_user, event.message) - - -# --------------------------------------- Ban/Unban -------------------------------------------- # - - -@asst_cmd( - pattern="ban", - load=AST_PLUGINS, - from_users=[OWNER_ID], - func=lambda x: x.is_private, -) -async def banhammer(event): - if not event.is_reply: - return await event.reply(get_string("pmbot_2")) - target = get_who(event.reply_to_msg_id) - if botb.contains(target): - return await event.reply(get_string("pmbot_3")) - - botb.add(target) - await event.reply(f"#BAN\nUser : {target}") - await asst.send_message(target, get_string("pmbot_4")) - - -@asst_cmd( - pattern="unban", - load=AST_PLUGINS, - from_users=[OWNER_ID], - func=lambda x: x.is_private, -) -async def unbanhammer(event): - if not event.is_reply: - return await event.reply(get_string("pmbot_5")) - target = get_who(event.reply_to_msg_id) - if not botb.contains(target): - return await event.reply(get_string("pmbot_6")) - - botb.remove(target) - await event.reply(f"#UNBAN\nUser : {target}") - await asst.send_message(target, get_string("pmbot_7")) - - -# --------------------------------------- END -------------------------------------------- # diff --git a/assistant/ytdl.py b/assistant/ytdl.py deleted file mode 100644 index 8b1c8a9ade..0000000000 --- a/assistant/ytdl.py +++ /dev/null @@ -1,307 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -import os -import re - -try: - from PIL import Image -except ImportError: - Image = None -from telethon import Button -from telethon.errors.rpcerrorlist import FilePartLengthInvalidError, MediaEmptyError -from telethon.tl.types import DocumentAttributeAudio, DocumentAttributeVideo -from telethon.tl.types import InputWebDocument as wb - -from pyUltroid.fns.helper import ( - bash, - fast_download, - humanbytes, - numerize, - time_formatter, -) -from pyUltroid.fns.ytdl import dler, get_buttons, get_formats - -from . import LOGS, asst, callback, in_pattern, udB - -try: - from youtubesearchpython import VideosSearch -except ImportError: - LOGS.info("'youtubesearchpython' not installed!") - VideosSearch = None - - -ytt = "https://graph.org/file/afd04510c13914a06dd03.jpg" -_yt_base_url = "https://www.youtube.com/watch?v=" -BACK_BUTTON = {} - - -@in_pattern("yt", owner=True) -async def _(event): - try: - string = event.text.split(" ", maxsplit=1)[1] - except IndexError: - fuk = event.builder.article( - title="Search Something", - thumb=wb(ytt, 0, "image/jpeg", []), - text="**YᴏᴜTᴜʙᴇ Sᴇᴀʀᴄʜ**\n\nYou didn't search anything", - buttons=Button.switch_inline( - "Sᴇᴀʀᴄʜ Aɢᴀɪɴ", - query="yt ", - same_peer=True, - ), - ) - await event.answer([fuk]) - return - results = [] - search = VideosSearch(string, limit=50) - nub = search.result() - nibba = nub["result"] - for v in nibba: - ids = v["id"] - link = _yt_base_url + ids - title = v["title"] - duration = v["duration"] - views = v["viewCount"]["short"] - publisher = v["channel"]["name"] - published_on = v["publishedTime"] - description = ( - v["descriptionSnippet"][0]["text"] - if v.get("descriptionSnippet") - and len(v["descriptionSnippet"][0]["text"]) < 500 - else "None" - ) - thumb = f"https://i.ytimg.com/vi/{ids}/hqdefault.jpg" - text = f"**Title: [{title}]({link})**\n\n" - text += f"`Description: {description}\n\n" - text += f"「 Duration: {duration} 」\n" - text += f"「 Views: {views} 」\n" - text += f"「 Publisher: {publisher} 」\n" - text += f"「 Published on: {published_on} 」`" - desc = f"{title}\n{duration}" - file = wb(thumb, 0, "image/jpeg", []) - buttons = [ - [ - Button.inline("Audio", data=f"ytdl:audio:{ids}"), - Button.inline("Video", data=f"ytdl:video:{ids}"), - ], - [ - Button.switch_inline( - "Sᴇᴀʀᴄʜ Aɢᴀɪɴ", - query="yt ", - same_peer=True, - ), - Button.switch_inline( - "Sʜᴀʀᴇ", - query=f"yt {string}", - same_peer=False, - ), - ], - ] - BACK_BUTTON.update({ids: {"text": text, "buttons": buttons}}) - results.append( - await event.builder.article( - type="photo", - title=title, - description=desc, - thumb=file, - content=file, - text=text, - include_media=True, - buttons=buttons, - ), - ) - await event.answer(results[:50]) - - -@callback( - re.compile( - "ytdl:(.*)", - ), - owner=True, -) -async def _(e): - _e = e.pattern_match.group(1).strip().decode("UTF-8") - _lets_split = _e.split(":") - _ytdl_data = await dler(e, _yt_base_url + _lets_split[1]) - _data = get_formats(_lets_split[0], _lets_split[1], _ytdl_data) - _buttons = get_buttons(_data) - _text = ( - "`Select Your Format.`" - if _buttons - else "`Error downloading from YouTube.\nTry Restarting your bot.`" - ) - - await e.edit(_text, buttons=_buttons) - - -@callback( - re.compile( - "ytdownload:(.*)", - ), - owner=True, -) -async def _(event): - url = event.pattern_match.group(1).strip().decode("UTF-8") - lets_split = url.split(":") - vid_id = lets_split[2] - link = _yt_base_url + vid_id - format = lets_split[1] - try: - ext = lets_split[3] - except IndexError: - ext = "mp3" - if lets_split[0] == "audio": - opts = { - "format": "bestaudio", - "addmetadata": True, - "key": "FFmpegMetadata", - "prefer_ffmpeg": True, - "geo_bypass": True, - "outtmpl": f"%(id)s.{ext}", - "logtostderr": False, - "postprocessors": [ - { - "key": "FFmpegExtractAudio", - "preferredcodec": ext, - "preferredquality": format, - }, - {"key": "FFmpegMetadata"}, - ], - } - - ytdl_data = await dler(event, link, opts, True) - title = ytdl_data["title"] - if ytdl_data.get("artist"): - artist = ytdl_data["artist"] - elif ytdl_data.get("creator"): - artist = ytdl_data["creator"] - elif ytdl_data.get("channel"): - artist = ytdl_data["channel"] - views = numerize(ytdl_data.get("view_count")) or 0 - thumb, _ = await fast_download(ytdl_data["thumbnail"], filename=f"{vid_id}.jpg") - - likes = numerize(ytdl_data.get("like_count")) or 0 - duration = ytdl_data.get("duration") or 0 - description = ( - ytdl_data["description"] - if len(ytdl_data["description"]) < 100 - else ytdl_data["description"][:100] - ) - description = description or "None" - filepath = f"{vid_id}.{ext}" - if not os.path.exists(filepath): - filepath = f"{filepath}.{ext}" - size = os.path.getsize(filepath) - file, _ = await event.client.fast_uploader( - filepath, - filename=f"{title}.{ext}", - show_progress=True, - event=event, - to_delete=True, - ) - - attributes = [ - DocumentAttributeAudio( - duration=int(duration), - title=title, - performer=artist, - ), - ] - elif lets_split[0] == "video": - opts = { - "format": str(format), - "addmetadata": True, - "key": "FFmpegMetadata", - "prefer_ffmpeg": True, - "geo_bypass": True, - "outtmpl": f"%(id)s.{ext}", - "logtostderr": False, - "postprocessors": [{"key": "FFmpegMetadata"}], - } - - ytdl_data = await dler(event, link, opts, True) - title = ytdl_data["title"] - if ytdl_data.get("artist"): - artist = ytdl_data["artist"] - elif ytdl_data.get("creator"): - artist = ytdl_data["creator"] - elif ytdl_data.get("channel"): - artist = ytdl_data["channel"] - views = numerize(ytdl_data.get("view_count")) or 0 - thumb, _ = await fast_download(ytdl_data["thumbnail"], filename=f"{vid_id}.jpg") - - try: - Image.open(thumb).save(thumb, "JPEG") - except Exception as er: - LOGS.exception(er) - thumb = None - description = ( - ytdl_data["description"] - if len(ytdl_data["description"]) < 100 - else ytdl_data["description"][:100] - ) - likes = numerize(ytdl_data.get("like_count")) or 0 - hi, wi = ytdl_data.get("height") or 720, ytdl_data.get("width") or 1280 - duration = ytdl_data.get("duration") or 0 - filepath = f"{vid_id}.mkv" - if not os.path.exists(filepath): - filepath = f"{filepath}.webm" - size = os.path.getsize(filepath) - file, _ = await event.client.fast_uploader( - filepath, - filename=f"{title}.mkv", - show_progress=True, - event=event, - to_delete=True, - ) - - attributes = [ - DocumentAttributeVideo( - duration=int(duration), - w=wi, - h=hi, - supports_streaming=True, - ), - ] - description = description if description != "" else "None" - text = f"**Title: [{title}]({_yt_base_url}{vid_id})**\n\n" - text += f"`📝 Description: {description}\n\n" - text += f"「 Duration: {time_formatter(int(duration)*1000)} 」\n" - text += f"「 Artist: {artist} 」\n" - text += f"「 Views: {views} 」\n" - text += f"「 Likes: {likes} 」\n" - text += f"「 Size: {humanbytes(size)} 」`" - button = Button.switch_inline("Search More", query="yt ", same_peer=True) - try: - await event.edit( - text, - file=file, - buttons=button, - attributes=attributes, - thumb=thumb, - ) - except (FilePartLengthInvalidError, MediaEmptyError): - file = await asst.send_message( - udB.get_key("LOG_CHANNEL"), - text, - file=file, - buttons=button, - attributes=attributes, - thumb=thumb, - ) - await event.edit(text, file=file.media, buttons=button) - await bash(f"rm {vid_id}.jpg") - - -@callback(re.compile("ytdl_back:(.*)"), owner=True) -async def ytdl_back(event): - id_ = event.data_match.group(1).decode("utf-8") - if not BACK_BUTTON.get(id_): - return await event.answer("Query Expired! Search again 🔍") - await event.edit(**BACK_BUTTON[id_]) diff --git a/callbacks.py b/callbacks.py new file mode 100644 index 0000000000..e73f3de1d0 --- /dev/null +++ b/callbacks.py @@ -0,0 +1,1277 @@ +# Ultroid - UserBot +# Copyright (C) 2021-2022 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +import ast +import asyncio +import re +import sys, os +import time +from asyncio.exceptions import TimeoutError as AsyncTimeOut +from os import execl, remove +from random import choice + +from bs4 import BeautifulSoup as bs +from core import HNDLR, udB, LOGS, Var +from database.helpers import get_random_color +# try: +# from pyUltroid.fns.gDrive import GDriveManager +# except ImportError: +# GDriveManager = None +from telegraph import upload_file as upl +from telethon import Button, events +from telethon.tl.types import MessageMediaWebPage +from telethon.utils import get_peer_id +from localization import get_string + +from utilities.helper import fast_download, progress +from utilities.tools import Carbon, async_searcher #, get_paste, telegraph_client +#from pyUltroid.startup.loader import Loader +from telethon.tl import types +from . import callback, get_back_button, asst + +# --------------------------------------------------------------------# +# telegraph = telegraph_client() +# GDrive = GDriveManager() if GDriveManager else None +# --------------------------------------------------------------------# + +async def setit(_, key, value): + udB.set_key(key, value) + +def text_to_url(event): + """function to get media url (with|without) Webpage""" + if isinstance(event.media, MessageMediaWebPage): + webpage = event.media.webpage + if not isinstance(webpage, types.WebPageEmpty) and webpage.type in ["photo"]: + return webpage.display_url + return event.text + + +# --------------------------------------------------------------------# + +_buttons = { + "otvars": { + "text": "Other Variables to set for @TeamUltroid:", + "buttons": [ + [ + Button.inline("Tᴀɢ Lᴏɢɢᴇʀ", data="taglog"), + Button.inline("SᴜᴘᴇʀFʙᴀɴ", data="cbs_sfban"), + ], + [ + Button.inline("Sᴜᴅᴏ Mᴏᴅᴇ", data="sudo"), + Button.inline("Hᴀɴᴅʟᴇʀ", data="hhndlr"), + ], + [ + Button.inline("Exᴛʀᴀ Pʟᴜɢɪɴs", data="plg"), + Button.inline("Aᴅᴅᴏɴs", data="eaddon"), + ], + [ + Button.inline("Eᴍᴏᴊɪ ɪɴ Hᴇʟᴘ", data="emoj"), + Button.inline("Sᴇᴛ ɢDʀɪᴠᴇ", data="gdrive"), + ], + [ + Button.inline("Iɴʟɪɴᴇ Pɪᴄ", data="inli_pic"), + Button.inline("Sᴜᴅᴏ HNDLR", data="shndlr"), + ], + [Button.inline("Dᴜᴀʟ Mᴏᴅᴇ", "cbs_oofdm")], + [Button.inline("« Bᴀᴄᴋ", data="setter")], + ], + }, + "sfban": { + "text": "SuperFban Settings:", + "buttons": [ + [Button.inline("FBᴀɴ Gʀᴏᴜᴘ", data="sfgrp")], + [Button.inline("Exᴄʟᴜᴅᴇ Fᴇᴅs", data="abs_sfexf")], + [Button.inline("« Bᴀᴄᴋ", data="cbs_otvars")], + ], + }, + "apauto": { + "text": "This'll auto approve on outgoing messages", + "buttons": [ + [Button.inline("Aᴜᴛᴏ Aᴘᴘʀᴏᴠᴇ ON", data="apon")], + [Button.inline("Aᴜᴛᴏ Aᴘᴘʀᴏᴠᴇ OFF", data="apof")], + [Button.inline("« Bᴀᴄᴋ", data="cbs_pmcstm")], + ], + }, + "alvcstm": { + "text": f"Customise your {HNDLR}alive. Choose from the below options -", + "buttons": [ + [Button.inline("Aʟɪᴠᴇ Tᴇxᴛ", data="abs_alvtx")], + [Button.inline("Aʟɪᴠᴇ ᴍᴇᴅɪᴀ", data="alvmed")], + [Button.inline("Dᴇʟᴇᴛᴇ Aʟɪᴠᴇ Mᴇᴅɪᴀ", data="delmed")], + [Button.inline("« Bᴀᴄᴋ", data="setter")], + ], + }, + "pmcstm": { + "text": "Customise your PMPERMIT Settings -", + "buttons": [ + [ + Button.inline("Pᴍ Tᴇxᴛ", data="pmtxt"), + Button.inline("Pᴍ Mᴇᴅɪᴀ", data="pmmed"), + ], + [ + Button.inline("Aᴜᴛᴏ Aᴘᴘʀᴏᴠᴇ", data="cbs_apauto"), + Button.inline("PMLOGGER", data="pml"), + ], + [ + Button.inline("Sᴇᴛ Wᴀʀɴs", data="swarn"), + Button.inline("Dᴇʟᴇᴛᴇ Pᴍ Mᴇᴅɪᴀ", data="delpmmed"), + ], + [Button.inline("PMPermit Type", data="cbs_pmtype")], + [Button.inline("« Bᴀᴄᴋ", data="cbs_ppmset")], + ], + }, + "pmtype": { + "text": "Select the type of PMPermit needed.", + "buttons": [ + [Button.inline("Inline", data="inpm_in")], + [Button.inline("Normal", data="inpm_no")], + [Button.inline("« Bᴀᴄᴋ", data="cbs_pmcstm")], + ], + }, + "ppmset": { + "text": "PMPermit Settings:", + "buttons": [ + [Button.inline("Tᴜʀɴ PMPᴇʀᴍɪᴛ Oɴ", data="pmon")], + [Button.inline("Tᴜʀɴ PMPᴇʀᴍɪᴛ Oғғ", data="pmoff")], + [Button.inline("Cᴜsᴛᴏᴍɪᴢᴇ PMPᴇʀᴍɪᴛ", data="cbs_pmcstm")], + [Button.inline("« Bᴀᴄᴋ", data="setter")], + ], + }, + "chatbot": { + "text": "From This Feature U can chat with ppls Via ur Assistant Bot.\n[More info](https://t.me/UltroidUpdates/2)", + "buttons": [ + [ + Button.inline("Cʜᴀᴛ Bᴏᴛ Oɴ", data="onchbot"), + Button.inline("Cʜᴀᴛ Bᴏᴛ Oғғ", data="ofchbot"), + ], + [ + Button.inline("Bᴏᴛ Wᴇʟᴄᴏᴍᴇ", data="bwel"), + Button.inline("Bᴏᴛ Wᴇʟᴄᴏᴍᴇ Mᴇᴅɪᴀ", data="botmew"), + ], + [Button.inline("Bᴏᴛ Iɴғᴏ Tᴇxᴛ", data="botinfe")], + [Button.inline("Fᴏʀᴄᴇ Sᴜʙsᴄʀɪʙᴇ", data="pmfs")], + [Button.inline("« Bᴀᴄᴋ", data="setter")], + ], + }, + "vcb": { + "text": "From This Feature U can play songs in group voice chat\n\n[moreinfo](https://t.me/UltroidUpdates/4)", + "buttons": [ + [Button.inline("VC Sᴇssɪᴏɴ", data="abs_vcs")], + [Button.inline("« Bᴀᴄᴋ", data="setter")], + ], + }, + "oofdm": { + "text": "About [Dual Mode](https://t.me/UltroidUpdates/18)", + "buttons": [ + [ + Button.inline("Dᴜᴀʟ Mᴏᴅᴇ Oɴ", "dmof"), + Button.inline("Dᴜᴀʟ Mᴏᴅᴇ Oғғ", "dmof"), + ], + [Button.inline("Dᴜᴀʟ Mᴏᴅᴇ Hɴᴅʟʀ", "dmhn")], + [Button.inline("« Back", data="cbs_otvars")], + ], + }, + "apiset": { + "text": get_string("ast_1"), + "buttons": [ + [Button.inline("Remove.bg API", data="abs_rmbg")], + [Button.inline("DEEP API", data="abs_dapi")], + [Button.inline("OCR API", data="abs_oapi")], + [Button.inline("« Back", data="setter")], + ], + }, +} + +_convo = { + "rmbg": { + "var": "RMBG_API", + "name": "Remove.bg API Key", + "text": get_string("ast_2"), + "back": "cbs_apiset", + }, + "dapi": { + "var": "DEEP_AI", + "name": "Deep AI Api Key", + "text": "Get Your Deep Api from deepai.org and send here.", + "back": "cbs_apiset", + }, + "oapi": { + "var": "OCR_API", + "name": "Ocr Api Key", + "text": "Get Your OCR api from ocr.space and send that Here.", + "back": "cbs_apiset", + }, + "pmlgg": { + "var": "PMLOGGROUP", + "name": "Pm Log Group", + "text": "Send chat id of chat which you want to save as Pm log Group.", + "back": "pml", + }, + "vcs": { + "var": "VC_SESSION", + "name": "Vc Session", + "text": "**Vc session**\nEnter the New session u generated for vc bot.\n\nUse /cancel to terminate the operation.", + "back": "cbs_vcb", + }, + "settag": { + "var": "TAG_LOG", + "name": "Tag Log Group", + "text": f"Make a group, add your assistant and make it admin.\nGet the `{HNDLR}id` of that group and send it here for tag logs.\n\nUse /cancel to cancel.", + "back": "taglog", + }, + "alvtx": { + "var": "ALIVE_TEXT", + "name": "Alive Text", + "text": "**Alive Text**\nEnter the new alive text.\n\nUse /cancel to terminate the operation.", + "back": "cbs_alvcstm", + }, + "sfexf": { + "var": "EXCLUDE_FED", + "name": "Excluded Fed", + "text": "Send the Fed IDs you want to exclude in the ban. Split by a space.\neg`id1 id2 id3`\nSet is as `None` if you dont want any.\nUse /cancel to go back.", + "back": "cbs_sfban", + }, +} + + +TOKEN_FILE = "resources/auths/auth_token.txt" + + +@callback( + re.compile( + "sndplug_(.*)", + ), + owner=True, +) +async def send(eve): + key, name = (eve.data_match.group(1)).decode("UTF-8").split("_") + thumb = "resources/extras/inline.jpg" + await eve.answer("■ Sending ■") + data = f"uh_{key}_" + index = None + if "|" in name: + name, index = name.split("|") + key = "plugins" if key == "Official" else key.lower() + plugin = f"{key}/{name}.py" + _ = f"pasta-{plugin}" + if index is not None: + data += f"|{index}" + _ += f"|{index}" + buttons = [ + [ + Button.inline( + "« Pᴀsᴛᴇ »", + data=_, + ) + ], + [ + Button.inline("« Bᴀᴄᴋ", data=data), + ], + ] + try: + await eve.edit(file=plugin, thumb=thumb, buttons=buttons) + except Exception as er: + await eve.answer(str(er), alert=True) + + +heroku_api, app_name = Var.HEROKU_API, Var.HEROKU_APP_NAME + + +@callback("updatenow", owner=True) +async def update(eve): + repo = Repo() + ac_br = repo.active_branch + ups_rem = repo.remote("upstream") + if heroku_api: + import heroku3 + + try: + heroku = heroku3.from_key(heroku_api) + heroku_app = None + heroku_applications = heroku.apps() + except BaseException as er: + LOGS.exception(er) + return await eve.edit("`Wrong HEROKU_API.`") + for app in heroku_applications: + if app.name == app_name: + heroku_app = app + if not heroku_app: + await eve.edit("`Wrong HEROKU_APP_NAME.`") + repo.__del__() + return + await eve.edit(get_string("clst_1")) + ups_rem.fetch(ac_br) + repo.git.reset("--hard", "FETCH_HEAD") + heroku_git_url = heroku_app.git_url.replace( + "https://", f"https://api:{heroku_api}@" + ) + + if "heroku" in repo.remotes: + remote = repo.remote("heroku") + remote.set_url(heroku_git_url) + else: + remote = repo.create_remote("heroku", heroku_git_url) + try: + remote.push(refspec=f"HEAD:refs/heads/{ac_br}", force=True) + except GitCommandError as error: + await eve.edit(f"`Here is the error log:\n{error}`") + repo.__del__() + return + await eve.edit("`Successfully Updated!\nRestarting, please wait...`") + else: + await eve.edit(get_string("clst_1")) + call_back() + await bash("git pull && pip3 install -r requirements.txt") + execl(sys.executable, sys.executable, "-m", "pyUltroid") + + + + +@callback( + re.compile( + "pasta-(.*)", + ), + owner=True, +) +async def _(e): + ok = (e.data_match.group(1)).decode("UTF-8") + index = None + 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 _: + return await e.answer(key[:30], alert=True) + if ok.startswith("addons"): + key = "Addons" + elif ok.startswith("vcbot"): + key = "VCBot" + else: + key = "Official" + data = f"uh_{key}_" + if index is not None: + data += f"|{index}" + await e.edit( + "", + buttons=[ + [Button.url("Lɪɴᴋ", link), Button.url("Rᴀᴡ", raw)], + [Button.inline("« Bᴀᴄᴋ", data=data)], + ], + ) + + +@callback(re.compile("cbs_(.*)"), owner=True) +async def _edit_to(event): + match = event.data_match.group(1).decode("utf-8") + data = _buttons.get(match) + if not data: + return + await event.edit(data["text"], buttons=data["buttons"], link_preview=False) + + +@callback(re.compile("abs_(.*)"), owner=True) +async def convo_handler(event: events.CallbackQuery): + match = event.data_match.group(1).decode("utf-8") + if not _convo.get(match): + return + await event.delete() + get_ = _convo[match] + back = get_["back"] + async with event.client.conversation(event.sender_id) as conv: + await conv.send_message(get_["text"]) + response = await conv.get_response() + themssg = response.message + try: + themssg = ast.literal_eval(themssg) + except Exception: + pass + if themssg == "/cancel": + return await conv.send_message( + "Cancelled!!", + buttons=get_back_button(back), + ) + await setit(event, get_["var"], themssg) + await conv.send_message( + f"{get_['name']} changed to `{themssg}`", + buttons=get_back_button(back), + ) + + +@callback("authorise", owner=True) +async def _(e): + if not e.is_private: + return + url = GDrive._create_token_file() + await e.edit("Go to the below link and send the code!") + async with asst.conversation(e.sender_id) as conv: + await conv.send_message(url) + code = await conv.get_response() + if GDrive._create_token_file(code=code.text): + await conv.send_message( + "`Success!\nYou are all set to use Google Drive with Ultroid Userbot.`", + buttons=Button.inline("Main Menu", data="setter"), + ) + else: + await conv.send_message("Wrong code! Click authorise again.") + + +@callback("folderid", owner=True, func=lambda x: x.is_private) +async def _(e): + if not e.is_private: + return + msg = ( + "Send your FOLDER ID\n\n" + + "For FOLDER ID:\n" + + "1. Open Google Drive App.\n" + + "2. Create Folder.\n" + + "3. Make that folder public.\n" + + "4. Send link of that folder." + ) + await e.delete() + async with asst.conversation(e.sender_id, timeout=150) as conv: + await conv.send_message(msg) + repl = await conv.get_response() + id = repl.text + if id.startswith("https"): + id = id.split("?id=")[-1] + udB.set_key("GDRIVE_FOLDER_ID", id) + await repl.reply( + "`Success.`", + buttons=get_back_button("gdrive"), + ) + + +@callback("gdrive", owner=True) +async def _(e): + if not e.is_private: + return + await e.edit( + "Click Authorise and send the code.\n\nYou can use your own CLIENT ID and SECRET by [this](https://t.me/UltroidUpdates/37)", + buttons=[ + [ + Button.inline("Folder ID", data="folderid"), + Button.inline("Authorise", data="authorise"), + ], + [Button.inline("« Back", data="cbs_otvars")], + ], + link_preview=False, + ) + + +@callback("dmof", owner=True) +async def rhwhe(e): + if udB.get_key("DUAL_MODE"): + udB.del_key("DUAL_MODE") + key = "Off" + else: + udB.set_key("DUAL_MODE", "True") + key = "On" + Msg = f"Dual Mode : {key}" + await e.edit(Msg, buttons=get_back_button("cbs_otvars")) + + +@callback("dmhn", owner=True) +async def hndlrr(event): + await event.delete() + pru = event.sender_id + var = "DUAL_HNDLR" + name = "Dual Handler" + CH = udB.get_key(var) or "/" + async with event.client.conversation(pru) as conv: + await conv.send_message( + f"Send The Symbol Which u want as Handler/Trigger to use your Assistant bot\nUr Current Handler is [ `{CH}` ]\n\n use /cancel to cancel.", + ) + response = conv.wait_event(events.NewMessage(chats=pru)) + response = await response + themssg = response.message.message + if themssg == "/cancel": + await conv.send_message( + "Cancelled!!", + buttons=get_back_button("cbs_otvars"), + ) + elif len(themssg) > 1: + await conv.send_message( + "Incorrect Handler", + buttons=get_back_button("cbs_otvars"), + ) + else: + await setit(event, var, themssg) + await conv.send_message( + f"{name} changed to {themssg}", + buttons=get_back_button("cbs_otvars"), + ) + + +@callback("emoj", owner=True) +async def emoji(event): + await event.delete() + pru = event.sender_id + var = "EMOJI_IN_HELP" + name = f"Emoji in `{HNDLR}help` menu" + async with event.client.conversation(pru) as conv: + await conv.send_message("Send emoji u want to set 🙃.\n\nUse /cancel to cancel.") + response = conv.wait_event(events.NewMessage(chats=pru)) + response = await response + themssg = response.message.message + if themssg == "/cancel": + await conv.send_message( + "Cancelled!!", + buttons=get_back_button("cbs_otvars"), + ) + elif themssg.startswith(("/", HNDLR)): + await conv.send_message( + "Incorrect Emoji", + buttons=get_back_button("cbs_otvars"), + ) + else: + await setit(event, var, themssg) + await conv.send_message( + f"{name} changed to {themssg}\n", + buttons=get_back_button("cbs_otvars"), + ) + + +@callback("plg", owner=True) +async def pluginch(event): + await event.delete() + pru = event.sender_id + var = "PLUGIN_CHANNEL" + name = "Plugin Channel" + async with event.client.conversation(pru) as conv: + await conv.send_message( + "Send id or username of a channel from where u want to install all plugins\n\nOur Channel~ @ultroidplugins\n\nUse /cancel to cancel.", + ) + response = conv.wait_event(events.NewMessage(chats=pru)) + response = await response + themssg = response.message.message + if themssg == "/cancel": + await conv.send_message( + "Cancelled!!", + buttons=get_back_button("cbs_otvars"), + ) + elif themssg.startswith(("/", HNDLR)): + await conv.send_message( + "Incorrect channel", + buttons=get_back_button("cbs_otvars"), + ) + else: + await setit(event, var, themssg) + await conv.send_message( + f"{name} changed to {themssg}\n After Setting All Things Do Restart", + buttons=get_back_button("cbs_otvars"), + ) + + +@callback("hhndlr", owner=True) +async def hndlrr(event): + await event.delete() + pru = event.sender_id + var = "HNDLR" + name = "Handler/ Trigger" + async with event.client.conversation(pru) as conv: + await conv.send_message( + f"Send The Symbol Which u want as Handler/Trigger to use bot\nUr Current Handler is [ `{HNDLR}` ]\n\n use /cancel to cancel.", + ) + response = conv.wait_event(events.NewMessage(chats=pru)) + response = await response + themssg = response.message.message + if themssg == "/cancel": + await conv.send_message( + "Cancelled!!", + buttons=get_back_button("cbs_otvars"), + ) + elif len(themssg) > 1: + await conv.send_message( + "Incorrect Handler", + buttons=get_back_button("cbs_otvars"), + ) + elif themssg.startswith(("/", "#", "@")): + await conv.send_message( + "This cannot be used as handler", + buttons=get_back_button("cbs_otvars"), + ) + else: + await setit(event, var, themssg) + await conv.send_message( + f"{name} changed to {themssg}", + buttons=get_back_button("cbs_otvars"), + ) + + +@callback("shndlr", owner=True) +async def hndlrr(event): + await event.delete() + pru = event.sender_id + var = "SUDO_HNDLR" + name = "Sudo Handler" + async with event.client.conversation(pru) as conv: + await conv.send_message( + "Send The Symbol Which u want as Sudo Handler/Trigger to use bot\n\n use /cancel to cancel." + ) + + response = conv.wait_event(events.NewMessage(chats=pru)) + response = await response + themssg = response.message.message + if themssg == "/cancel": + await conv.send_message( + "Cancelled!!", + buttons=get_back_button("cbs_otvars"), + ) + elif len(themssg) > 1: + await conv.send_message( + "Incorrect Handler", + buttons=get_back_button("cbs_otvars"), + ) + elif themssg.startswith(("/", "#", "@")): + await conv.send_message( + "This cannot be used as handler", + buttons=get_back_button("cbs_otvars"), + ) + else: + await setit(event, var, themssg) + await conv.send_message( + f"{name} changed to {themssg}", + buttons=get_back_button("cbs_otvars"), + ) + + +@callback("taglog", owner=True) +async def tagloggrr(e): + BUTTON = [ + [Button.inline("SET TAG LOG", data="abs_settag")], + [Button.inline("DELETE TAG LOG", data="deltag")], + get_back_button("cbs_otvars"), + ] + await e.edit( + "Choose Options", + buttons=BUTTON, + ) + + +@callback("deltag", owner=True) +async def _(e): + udB.del_key("TAG_LOG") + await e.answer("Done!!! Tag Logger has been turned Off") + + +@callback("eaddon", owner=True) +async def pmset(event): + BT = ( + [Button.inline("Aᴅᴅᴏɴs Oғғ", data="edof")] + if udB.get_key("ADDONS") + else [Button.inline("Aᴅᴅᴏɴs Oɴ", data="edon")] + ) + + await event.edit( + "ADDONS~ Extra Plugins:", + buttons=[ + BT, + [Button.inline("« Bᴀᴄᴋ", data="cbs_otvars")], + ], + ) + + +@callback("edon", owner=True) +async def eddon(event): + var = "ADDONS" + await setit(event, var, "True") + await event.edit( + "Done! ADDONS has been turned on!!\n\n After Setting All Things Do Restart", + buttons=get_back_button("eaddon"), + ) + + +@callback("edof", owner=True) +async def eddof(event): + udB.set_key("ADDONS", "False") + await event.edit( + "Done! ADDONS has been turned off!! After Setting All Things Do Restart", + buttons=get_back_button("eaddon"), + ) + + +@callback("sudo", owner=True) +async def pmset(event): + BT = ( + [Button.inline("Sᴜᴅᴏ Mᴏᴅᴇ Oғғ", data="ofsudo")] + if udB.get_key("SUDO") + else [Button.inline("Sᴜᴅᴏ Mᴏᴅᴇ Oɴ", data="onsudo")] + ) + + await event.edit( + f"SUDO MODE ~ Some peoples can use ur Bot which u selected. To know More use `{HNDLR}help sudo`", + buttons=[ + BT, + [Button.inline("« Bᴀᴄᴋ", data="cbs_otvars")], + ], + ) + + +@callback("onsudo", owner=True) +async def eddon(event): + var = "SUDO" + await setit(event, var, "True") + await event.edit( + "Done! SUDO MODE has been turned on!!\n\n After Setting All Things Do Restart", + buttons=get_back_button("sudo"), + ) + + +@callback("ofsudo", owner=True) +async def eddof(event): + var = "SUDO" + await setit(event, var, "False") + await event.edit( + "Done! SUDO MODE has been turned off!! After Setting All Things Do Restart", + buttons=get_back_button("sudo"), + ) + + +@callback("sfgrp", owner=True) +async def sfgrp(event): + await event.delete() + name = "FBan Group ID" + var = "FBAN_GROUP_ID" + pru = event.sender_id + async with asst.conversation(pru) as conv: + await conv.send_message( + f"Make a group, add @MissRose_Bot, send `{HNDLR}id`, copy that and send it here.\nUse /cancel to go back.", + ) + response = conv.wait_event(events.NewMessage(chats=pru)) + response = await response + themssg = response.message.message + if themssg == "/cancel": + return await conv.send_message( + "Cancelled!!", + buttons=get_back_button("cbs_sfban"), + ) + await setit(event, var, themssg) + await conv.send_message( + f"{name} changed to {themssg}", + buttons=get_back_button("cbs_sfban"), + ) + + +@callback("alvmed", owner=True) +async def media(event): + await event.delete() + pru = event.sender_id + var = "ALIVE_PIC" + name = "Alive Media" + async with event.client.conversation(pru) as conv: + await conv.send_message( + "**Alive Media**\nSend me a pic/gif/media to set as alive media.\n\nUse /cancel to terminate the operation.", + ) + response = await conv.get_response() + try: + themssg = response.message + if themssg == "/cancel": + return await conv.send_message( + "Operation cancelled!!", + buttons=get_back_button("cbs_alvcstm"), + ) + except BaseException as er: + LOGS.exception(er) + if ( + not (response.text).startswith("/") + and response.text != "" + and (not response.media or isinstance(response.media, MessageMediaWebPage)) + ): + url = text_to_url(response) + elif response.sticker: + url = response.file.id + else: + media = await event.client.download_media(response, "alvpc") + try: + x = upl(media) + url = f"https://graph.org/{x[0]}" + remove(media) + except BaseException as er: + LOGS.exception(er) + return await conv.send_message( + "Terminated.", + buttons=get_back_button("cbs_alvcstm"), + ) + await setit(event, var, url) + await conv.send_message( + f"{name} has been set.", + buttons=get_back_button("cbs_alvcstm"), + ) + + +@callback("delmed", owner=True) +async def dell(event): + try: + udB.del_key("ALIVE_PIC") + return await event.edit( + get_string("clst_5"), buttons=get_back_button("cbs_alabs_vcstm") + ) + except BaseException as er: + LOGS.exception(er) + return await event.edit( + get_string("clst_4"), + buttons=get_back_button("cbs_alabs_vcstm"), + ) + + +@callback("inpm_in", owner=True) +async def inl_on(event): + var = "INLINE_PM" + await setit(event, var, "True") + await event.edit( + "Done!! PMPermit type has been set to inline!", + buttons=[[Button.inline("« Bᴀᴄᴋ", data="cbs_pmtype")]], + ) + + +@callback("inpm_no", owner=True) +async def inl_on(event): + var = "INLINE_PM" + await setit(event, var, "False") + await event.edit( + "Done!! PMPermit type has been set to normal!", + buttons=[[Button.inline("« Bᴀᴄᴋ", data="cbs_pmtype")]], + ) + + +@callback("pmtxt", owner=True) +async def name(event): + await event.delete() + pru = event.sender_id + var = "PM_TEXT" + name = "PM Text" + async with event.client.conversation(pru) as conv: + await conv.send_message( + "**PM Text**\nEnter the new Pmpermit text.\n\nu can use `{name}` `{fullname}` `{count}` `{mention}` `{username}` to get this from user Too\n\nUse /cancel to terminate the operation.", + ) + response = conv.wait_event(events.NewMessage(chats=pru)) + response = await response + themssg = response.message.message + if themssg == "/cancel": + return await conv.send_message( + "Cancelled!!", + buttons=get_back_button("cbs_pmcstm"), + ) + if len(themssg) > 4090: + return await conv.send_message( + "Message too long!\nGive a shorter message please!!", + buttons=get_back_button("cbs_pmcstm"), + ) + await setit(event, var, themssg) + await conv.send_message( + f"{name} changed to {themssg}\n\nAfter Setting All Things Do restart", + buttons=get_back_button("cbs_pmcstm"), + ) + + +@callback("swarn", owner=True) +async def name(event): + m = range(1, 10) + tultd = [Button.inline(f"{x}", data=f"wrns_{x}") for x in m] + lst = list(zip(tultd[::3], tultd[1::3], tultd[2::3])) + lst.append([Button.inline("« Bᴀᴄᴋ", data="cbs_pmcstm")]) + await event.edit( + "Select the number of warnings for a user before getting blocked in PMs.", + buttons=lst, + ) + + +@callback(re.compile(b"wrns_(.*)"), owner=True) +async def set_wrns(event): + value = int(event.data_match.group(1).decode("UTF-8")) + if dn := udB.set_key("PMWARNS", value): + await event.edit( + f"PM Warns Set to {value}.\nNew users will have {value} chances in PMs before getting banned.", + buttons=get_back_button("cbs_pmcstm"), + ) + else: + await event.edit( + f"Something went wrong, please check your {HNDLR}logs!", + buttons=get_back_button("cbs_pmcstm"), + ) + + +@callback("pmmed", owner=True) +async def media(event): + await event.delete() + pru = event.sender_id + var = "PMPIC" + name = "PM Media" + async with event.client.conversation(pru) as conv: + await conv.send_message( + "**PM Media**\nSend me a pic/gif/sticker/link to set as pmpermit media.\n\nUse /cancel to terminate the operation.", + ) + response = await conv.get_response() + try: + themssg = response.message + if themssg == "/cancel": + return await conv.send_message( + "Operation cancelled!!", + buttons=get_back_button("cbs_pmcstm"), + ) + except BaseException as er: + LOGS.exception(er) + media = await event.client.download_media(response, "pmpc") + if ( + not (response.text).startswith("/") + and response.text != "" + and (not response.media or isinstance(response.media, MessageMediaWebPage)) + ): + url = text_to_url(response) + elif response.sticker: + url = response.file.id + else: + try: + x = upl(media) + url = f"https://graph.org/{x[0]}" + remove(media) + except BaseException as er: + LOGS.exception(er) + return await conv.send_message( + "Terminated.", + buttons=get_back_button("cbs_pmcstm"), + ) + await setit(event, var, url) + await conv.send_message( + f"{name} has been set.", + buttons=get_back_button("cbs_pmcstm"), + ) + + +@callback("delpmmed", owner=True) +async def dell(event): + try: + udB.del_key("PMPIC") + return await event.edit( + get_string("clst_5"), buttons=get_back_button("cbs_pmcstm") + ) + except BaseException as er: + LOGS.exception(er) + return await event.edit( + get_string("clst_4"), + buttons=[[Button.inline("« Sᴇᴛᴛɪɴɢs", data="setter")]], + ) + + +@callback("apon", owner=True) +async def apon(event): + var = "AUTOAPPROVE" + await setit(event, var, "True") + await event.edit( + "Done!! AUTOAPPROVE Started!!", + buttons=[[Button.inline("« Bᴀᴄᴋ", data="cbs_apauto")]], + ) + + +@callback("apof", owner=True) +async def apof(event): + try: + udB.set_key("AUTOAPPROVE", "False") + return await event.edit( + "Done! AUTOAPPROVE Stopped!!", + buttons=[[Button.inline("« Bᴀᴄᴋ", data="cbs_apauto")]], + ) + except BaseException as er: + LOGS.exception(er) + return await event.edit( + get_string("clst_4"), + buttons=[[Button.inline("« Sᴇᴛᴛɪɴɢs", data="setter")]], + ) + + +@callback("pml", owner=True) +async def l_vcs(event): + BT = ( + [Button.inline("PMLOGGER OFF", data="pmlogof")] + if udB.get_key("PMLOG") + else [Button.inline("PMLOGGER ON", data="pmlog")] + ) + + await event.edit( + "PMLOGGER This Will Forward Ur Pm to Ur Private Group -", + buttons=[ + BT, + [Button.inline("PᴍLᴏɢɢᴇʀ Gʀᴏᴜᴘ", "abs_pmlgg")], + [Button.inline("« Bᴀᴄᴋ", data="cbs_pmcstm")], + ], + ) + + +@callback("pmlog", owner=True) +async def pmlog(event): + await setit(event, "PMLOG", "True") + await event.edit( + "Done!! PMLOGGER Started!!", + buttons=[[Button.inline("« Bᴀᴄᴋ", data="pml")]], + ) + + +@callback("pmlogof", owner=True) +async def pmlogof(event): + try: + udB.del_key("PMLOG") + return await event.edit( + "Done! PMLOGGER Stopped!!", + buttons=[[Button.inline("« Bᴀᴄᴋ", data="pml")]], + ) + except BaseException as er: + LOGS.exception(er) + return await event.edit( + get_string("clst_4"), + buttons=[[Button.inline("« Sᴇᴛᴛɪɴɢs", data="setter")]], + ) + + +@callback("pmon", owner=True) +async def pmonn(event): + var = "PMSETTING" + await setit(event, var, "True") + await event.edit( + "Done! PMPermit has been turned on!!", + buttons=[[Button.inline("« Bᴀᴄᴋ", data="cbs_ppmset")]], + ) + + +@callback("pmoff", owner=True) +async def pmofff(event): + var = "PMSETTING" + await setit(event, var, "False") + await event.edit( + "Done! PMPermit has been turned off!!", + buttons=[[Button.inline("« Bᴀᴄᴋ", data="cbs_ppmset")]], + ) + + +@callback("botmew", owner=True) +async def hhh(e): + async with e.client.conversation(e.chat_id) as conv: + await conv.send_message("Send Any Media to keep at your Bot's welcome ") + msg = await conv.get_response() + if not msg.media or msg.text.startswith("/"): + return await conv.send_message( + "Terminated!", buttons=get_back_button("cbs_chatbot") + ) + udB.set_key("STARTMEDIA", msg.file.id) + await conv.send_message("Done!", buttons=get_back_button("cbs_chatbot")) + + +@callback("botinfe", owner=True) +async def hhh(e): + async with e.client.conversation(e.chat_id) as conv: + await conv.send_message( + "Send message to set to Display, when user Press Info button in Bot Welcome!\n\nsend `False` to completely remove that button.." + ) + msg = await conv.get_response() + if msg.media or msg.text.startswith("/"): + return await conv.send_message( + "Terminated!", buttons=get_back_button("cbs_chatbot") + ) + udB.set_key("BOT_INFO_START", msg.text) + await conv.send_message("Done!", buttons=get_back_button("cbs_chatbot")) + + +@callback("pmfs", owner=True) +async def heheh(event): + Ll = [] + err = "" + async with event.client.conversation(event.chat_id) as conv: + await conv.send_message( + "• Send The Chat Id(s), which you want user to Join Before using Chat/Pm Bot\n\n• Send /clear to disable PmBot Force sub..\n• • Send /cancel to stop this process.." + ) + await conv.send_message( + "Example : \n`-1001234567\n-100778888`\n\nFor Multiple Chat(s)." + ) + try: + msg = await conv.get_response() + except AsyncTimeOut: + return await conv.send_message("**• TimeUp!**\nStart from /start back.") + if not msg.text or msg.text.startswith("/"): + timyork = "Cancelled!" + if msg.text == "/clear": + udB.del_key("PMBOT_FSUB") + timyork = "Done! Force Subscribe Stopped\nRestart your Bot!" + return await conv.send_message( + "Cancelled!", buttons=get_back_button("cbs_chatbot") + ) + for chat in msg.message.split("\n"): + if chat.startswith("-") or chat.isdigit(): + chat = int(chat) + try: + CHSJSHS = await event.client.get_entity(chat) + Ll.append(get_peer_id(CHSJSHS)) + except Exception as er: + err += f"**{chat}** : {er}\n" + if err: + return await conv.send_message(err) + udB.set_key("PMBOT_FSUB", str(Ll)) + await conv.send_message( + "Done!\nRestart Your Bot.", buttons=get_back_button("cbs_chatbot") + ) + + +@callback("bwel", owner=True) +async def name(event): + await event.delete() + pru = event.sender_id + var = "STARTMSG" + name = "Bot Welcome Message:" + async with event.client.conversation(pru) as conv: + await conv.send_message( + "**BOT WELCOME MSG**\nEnter the msg which u want to show when someone start your assistant Bot.\nYou Can use `{me}` , `{mention}` Parameters Too\nUse /cancel to terminate the operation.", + ) + response = conv.wait_event(events.NewMessage(chats=pru)) + response = await response + themssg = response.message.message + if themssg == "/cancel": + return await conv.send_message( + "Cancelled!!", + buttons=get_back_button("cbs_chatbot"), + ) + await setit(event, var, themssg) + await conv.send_message( + f"{name} changed to {themssg}", + buttons=get_back_button("cbs_chatbot"), + ) + + +@callback("onchbot", owner=True) +async def chon(event): + var = "PMBOT" + await setit(event, var, "True") + Loader(path="assistant/pmbot.py", key="PM Bot").load() + if AST_PLUGINS.get("pmbot"): + for i, e in AST_PLUGINS["pmbot"]: + event.client.remove_event_handler(i) + for i, e in AST_PLUGINS["pmbot"]: + event.client.add_event_handler(i, events.NewMessage(**e)) + await event.edit( + "Done! Now u Can Chat With People Via This Bot", + buttons=[Button.inline("« Bᴀᴄᴋ", data="cbs_chatbot")], + ) + + +@callback("ofchbot", owner=True) +async def chon(event): + var = "PMBOT" + await setit(event, var, "False") + if AST_PLUGINS.get("pmbot"): + for i, e in AST_PLUGINS["pmbot"]: + event.client.remove_event_handler(i) + await event.edit( + "Done! Chat People Via This Bot Stopped.", + buttons=[Button.inline("« Bᴀᴄᴋ", data="cbs_chatbot")], + ) + + +@callback("inli_pic", owner=True) +async def media(event): + await event.delete() + pru = event.sender_id + var = "INLINE_PIC" + name = "Inline Media" + async with event.client.conversation(pru) as conv: + await conv.send_message( + "**Inline Media**\nSend me a pic/gif/ or link to set as inline media.\n\nUse /cancel to terminate the operation.", + ) + response = await conv.get_response() + try: + themssg = response.message + if themssg == "/cancel": + return await conv.send_message( + "Operation cancelled!!", + buttons=get_back_button("setter"), + ) + except BaseException as er: + LOGS.exception(er) + media = await event.client.download_media(response, "inlpic") + if ( + not (response.text).startswith("/") + and response.text != "" + and (not response.media or isinstance(response.media, MessageMediaWebPage)) + ): + url = text_to_url(response) + else: + try: + x = upl(media) + url = f"https://graph.org/{x[0]}" + remove(media) + except BaseException as er: + LOGS.exception(er) + return await conv.send_message( + "Terminated.", + buttons=get_back_button("setter"), + ) + await setit(event, var, url) + await conv.send_message( + f"{name} has been set.", + buttons=get_back_button("setter"), + ) + + +FD_MEDIA = {} + + +@callback(re.compile("fd(.*)"), owner=True) +async def fdroid_dler(event): + uri = event.data_match.group(1).decode("utf-8") + if FD_MEDIA.get(uri): + return await event.edit(file=FD_MEDIA[uri]) + await event.answer("• Starting Download •", alert=True) + await event.edit("• Downloading.. •") + URL = f"https://f-droid.org/packages/{uri}" + conte = await async_searcher(URL, re_content=True) + BSC = bs(conte, "html.parser", from_encoding="utf-8") + dl_ = BSC.find("p", "package-version-download").find("a")["href"] + title = BSC.find("h3", "package-name").text.strip() + thumb = BSC.find("img", "package-icon")["src"] + if thumb.startswith("/"): + thumb = f"https://f-droid.org{thumb}" + thumb, _ = await fast_download(thumb, filename=f"{uri}.png") + s_time = time.time() + file, _ = await fast_download( + dl_, + filename=f"{title}.apk", + progress_callback=lambda d, t: asyncio.get_event_loop().create_task( + progress( + d, + t, + event, + s_time, + "Downloading...", + ) + ), + ) + + time.time() + n_file = await event.client.fast_uploader( + file, show_progress=True, event=event, message="Uploading...", to_delete=True + ) + buttons = Button.switch_inline("Search Back", query="fdroid", same_peer=True) + try: + msg = await event.edit( + f"**• [{title}]({URL}) •**", file=n_file, thumb=thumb, buttons=buttons + ) + except Exception as er: + LOGS.exception(er) + try: + msg = await event.client.edit_message( + await event.get_input_chat(), + event.message_id, + f"**• [{title}]({URL}) •**", + buttons=buttons, + thumb=thumb, + file=n_file, + ) + except Exception as er: + os.remove(thumb) + LOGS.exception(er) + return await event.edit(f"**ERROR**: `{er}`", buttons=buttons) + if msg and hasattr(msg, "media"): + FD_MEDIA.update({uri: msg.media}) + os.remove(thumb) diff --git a/core/README.md b/core/README.md new file mode 100644 index 0000000000..47d9e02424 --- /dev/null +++ b/core/README.md @@ -0,0 +1,5 @@ +# `core` +This directory contains all core functions related to starting Ultroid. +Do not edit contents of the `core` unless you know what you are doing. + +If you want to add plugins, head on to #TODO READ THE DOCS!. \ No newline at end of file diff --git a/core/__init__.py b/core/__init__.py new file mode 100644 index 0000000000..f5bda1c458 --- /dev/null +++ b/core/__init__.py @@ -0,0 +1,60 @@ +# Ultroid - UserBot +# Copyright (C) 2020-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +import sys + +import time, telethonpatch +from .config import Var +from .setup import * +from .client.BaseClient import UltroidClient +from .utils.base import validate_session, update_handlers +from database import udB +from .version import version +from .remote import rm + +start_time = time.time() + +LOGS.info("Connected to %s...", udB.name) + +BOT_MODE = udB.get_config("BOTMODE") +DUAL_MODE = udB.get_config("DUAL_MODE") + +USER_MODE = udB.get_config("USER_MODE") +if USER_MODE or BOT_MODE: + DUAL_MODE = False + +__token = udB.get_config("BOT_TOKEN") +if BOT_MODE and not __token: + LOGS.critical('"BOT_TOKEN" not Found! Please add it, in order to use "BOTMODE"') + sys.exit() +elif not BOT_MODE: + ultroid_bot = UltroidClient( + validate_session(Var.SESSION, LOGS), + app_version=version, + device_model="Ultroid", + ) + +asst = UltroidClient("asst", bot_token=__token) + +if BOT_MODE: + ultroid_bot = asst + if owner_id:= udB.get_config("OWNER_ID"): + try: + ultroid_bot.me = ultroid_bot.run_in_loop( + ultroid_bot.get_entity(owner_id) + ) + except Exception as er: + LOGS.exception(er) + +del __token + +HNDLR = udB.get_key("HNDLR") or "." +DUAL_HNDLR = udB.get_key("DUAL_HNDLR") or "/" +SUDO_HNDLR = udB.get_key("SUDO_HNDLR") or HNDLR + +for _ in ["HNDLR", "DUAL_HNDLR"]: + udB.on(_, "change", update_handlers) diff --git a/core/__main__.py b/core/__main__.py new file mode 100644 index 0000000000..557067fcd9 --- /dev/null +++ b/core/__main__.py @@ -0,0 +1,59 @@ +# Ultroid - UserBot +# Copyright (C) 2020-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +from . import * + +import contextlib +import os +import sys +import time + +from utilities.helper import bash, time_formatter, check_update +from .utils.funcs import process_main, load_plugins +from telethon.errors import SessionRevokedError + +# Option to Auto Update On Restarts.. +# TODO: UPDATE_ON_RESTART + +ultroid_bot.me.phone = None + +if not ultroid_bot.me.bot: + udB.set_key("OWNER_ID", ultroid_bot.me.id) + +LOGS.info("Initialising...") + +if not udB.get_config("BOT_TOKEN"): + with rm.get("autobot", helper=True) as mod: + ultroid_bot.run_in_loop(mod.autopilot()) + + +if HOSTED_ON == "heroku": + rm._http_import("heroku", "core/heroku.py", helper=True) + +ultroid_bot.run_in_loop(load_plugins()) +ultroid_bot.loop.create_task(process_main()) + +with contextlib.suppress(BaseException): + cleanup_cache() + +LOGS.info( + f"Took {time_formatter((time.time() - start_time) * 1000)} to start •ULTROID•" +) +LOGS.info( + """ + ---------------------------------------------------------------------- + Ultroid has been deployed! Visit @TheUltroid for updates!! + ---------------------------------------------------------------------- +""" +) +try: + asst.run() +except SessionRevokedError: + LOGS.info(f"Assistant [@{asst.me.username}]'s session was revoked!") + + # shift loop to bot + ultroid_bot.run() diff --git a/pyUltroid/startup/BaseClient.py b/core/client/BaseClient.py similarity index 69% rename from pyUltroid/startup/BaseClient.py rename to core/client/BaseClient.py index 39d2a883c0..cf950878ad 100644 --- a/pyUltroid/startup/BaseClient.py +++ b/core/client/BaseClient.py @@ -1,36 +1,43 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2020-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in # . +import contextlib import inspect +import os import sys import time +from datetime import datetime from logging import Logger -from telethon import TelegramClient -from telethon import utils as telethon_utils +from telethonpatch import TelegramClient +from telethon import hints, utils from telethon.errors import ( AccessTokenExpiredError, AccessTokenInvalidError, ApiIdInvalidError, AuthKeyDuplicatedError, ) +from telethon.tl.types import User -from ..configs import Var -from . import * +from core.config import Var +from core.setup import LOGS, TelethonLogger +from database import udB +from utilities.helper import fast_download class UltroidClient(TelegramClient): + me: User + def __init__( self, session, - api_id=None, - api_hash=None, + api_id: int = Var.API_ID, # type: ignore + api_hash: str = Var.API_HASH, # type: ignore bot_token=None, - udB=None, logger: Logger = LOGS, log_attempt=True, exit_on_error=True, @@ -42,18 +49,14 @@ def __init__( self._handle_error = exit_on_error self._log_at = log_attempt self.logger = logger - self.udB = udB - kwargs["api_id"] = api_id or Var.API_ID - kwargs["api_hash"] = api_hash or Var.API_HASH + self._thumb = {} kwargs["base_logger"] = TelethonLogger - super().__init__(session, **kwargs) + super().__init__(session, api_id=api_id, api_hash=api_hash, **kwargs) self.run_in_loop(self.start_client(bot_token=bot_token)) self.dc_id = self.session.dc_id def __repr__(self): - return "".format( - self.full_name, self._bot - ) + return f"" @property def __dict__(self): @@ -70,7 +73,7 @@ async def start_client(self, **kwargs): self.logger.critical("API ID and API_HASH combination does not match!") sys.exit() - except (AuthKeyDuplicatedError, EOFError) as er: + except (AuthKeyDuplicatedError, EOFError): if self._handle_error: self.logger.critical("String session expired. Create new!") return sys.exit() @@ -78,7 +81,7 @@ async def start_client(self, **kwargs): except (AccessTokenExpiredError, AccessTokenInvalidError): # AccessTokenError can only occur for Bot account # And at Early Process, Its saved in DB. - self.udB.del_key("BOT_TOKEN") + udB.del_key("BOT_TOKEN") self.logger.critical( "Bot token is expired or invalid. Create new from @Botfather and add in BOT_TOKEN env variable!" ) @@ -115,7 +118,7 @@ async def fast_uploader(self, file, **kwargs): by_bot = self._bot size = os.path.getsize(file) # Don't show progress bar when file size is less than 5MB. - if size < 5 * 2 ** 20: + if size < 5 * 2**20: show_progress = False if use_cache and self._cache and self._cache.get("upload_cache"): for files in self._cache["upload_cache"]: @@ -126,13 +129,11 @@ async def fast_uploader(self, file, **kwargs): and files["by_bot"] == by_bot ): if to_delete: - try: + with contextlib.suppress(FileNotFoundError): os.remove(file) - except FileNotFoundError: - pass return files["raw_file"], time.time() - start_time - from pyUltroid.fns.FastTelethon import upload_file - from pyUltroid.fns.helper import progress + from utilities.FastTelethon import upload_file + from utilities.helper import progress raw_file = None while not raw_file: @@ -161,28 +162,26 @@ async def fast_uploader(self, file, **kwargs): else: self._cache.update({"upload_cache": [cache]}) if to_delete: - try: + with contextlib.suppress(FileNotFoundError): os.remove(file) - except FileNotFoundError: - pass return raw_file, time.time() - start_time async def fast_downloader(self, file, **kwargs): """Download files in a faster way""" # Set to True and pass event to show progress bar. + filename = kwargs.get("filename") show_progress = kwargs.get("show_progress", False) - filename = kwargs.get("filename", "") if show_progress: event = kwargs["event"] # Don't show progress bar when file size is less than 10MB. - if file.size < 10 * 2 ** 20: + if file.size < 10 * 2**20: show_progress = False import mimetypes from telethon.tl.types import DocumentAttributeFilename - from pyUltroid.fns.FastTelethon import download_file - from pyUltroid.fns.helper import progress + from utilities.FastTelethon import download_file + from utilities.helper import progress start_time = time.time() # Auto-generate Filename @@ -190,16 +189,19 @@ async def fast_downloader(self, file, **kwargs): try: if isinstance(file.attributes[-1], DocumentAttributeFilename): filename = file.attributes[-1].file_name - except IndexError: + assert filename != None + except (IndexError, AssertionError): mimetype = file.mime_type filename = ( mimetype.split("/")[0] + "-" - + str(round(start_time)) + + str(datetime.now().strftime("%Y%m%d_%H%M%S")) + mimetypes.guess_extension(mimetype) ) message = kwargs.get("message", f"Downloading {filename}...") - + dirname = os.path.dirname(filename) + if dirname and not os.path.exists(dirname): + os.mkdir(dirname) raw_file = None while not raw_file: with open(filename, "wb") as f: @@ -227,18 +229,14 @@ def run(self): def add_handler(self, func, *args, **kwargs): """Add new event handler, ignoring if exists""" - if func in [_[0] for _ in self.list_event_handlers()]: + if func in list(map(lambda e: e[0], self.list_event_handlers())): return self.add_event_handler(func, *args, **kwargs) - @property - def utils(self): - return telethon_utils - @property def full_name(self): """full name of Client""" - return self.utils.get_display_name(self.me) + return utils.get_display_name(self.me) @property def uid(self): @@ -248,9 +246,42 @@ def uid(self): def to_dict(self): return dict(inspect.getmembers(self)) + # TODO: Remove async def parse_id(self, text): - try: + with contextlib.suppress(ValueError): text = int(text) - except ValueError: - pass return await self.get_peer_id(text) + + async def get_entity( + self: "TelegramClient", entity: "hints.EntitiesLike" + ) -> "hints.Entity": + if isinstance(entity, str) and entity[0] != "+": + with contextlib.suppress(ValueError): + entity = int(entity) + return await super().get_entity(entity) + + async def _get_custom_thumb(self, thumb: str): + with contextlib.suppress(KeyError): + thumb_ = self._thumb[thumb] + # Assume it get expire after 24 hours. + if (datetime.now() - datetime.fromtimestamp(thumb_["time"])).days < 1: + return thumb_["file"] + _exists = os.path.exists(thumb) + path = thumb if _exists else (await fast_download(thumb))[0] + _thumb_ = await self.upload_file(path) + if not _exists: + os.remove(path) + self._thumb[thumb] = {"file": _thumb_, "time": datetime.now().timestamp()} + return _thumb_ + + async def send_file(self, *args, **kwargs): + custom = udB.get_key("CUSTOM_THUMBNAIL") + if custom or custom is None: + thumb = kwargs.get("thumb") + if thumb is None: + kwargs["thumb"] = await self._get_custom_thumb( + udB.get_key("CUSTOM_THUMBNAIL") or "resources/ultroid.webp" + ) + elif thumb and isinstance(thumb, str) and thumb.startswith("http"): + kwargs["thumb"] = await self._get_custom_thumb(thumb) + return await super().send_file(*args, **kwargs) diff --git a/core/config.py b/core/config.py new file mode 100644 index 0000000000..2f049e9cfc --- /dev/null +++ b/core/config.py @@ -0,0 +1,45 @@ +# Ultroid - UserBot +# Copyright (C) 2020-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +import os +from decouple import config +from ast import literal_eval + +class Config: + def __getattr__(self, __name: str): + if __name in self.__dict__: + return self.__dict__[__name] + _data = config(__name, default="") + try: + return literal_eval(_data) + except Exception: + return _data + + API_ID = config("API_ID", cast=int, default=6) + API_HASH = config("API_HASH", default="eb06d4abfb49dc3eeb1aeb98ae0f581e") + + +def detect_platform(): + if os.getenv("DYNO"): + return "heroku" + if os.getenv("RAILWAY_STATIC_URL"): + return "railway" + if os.getenv("RENDER_SERVICE_NAME"): + return "render" + if os.getenv("OKTETO_TOKEN"): + return "okteto" + if os.getenv("KUBERNETES_PORT"): + return "qovery | kubernetes" + if os.getenv("RUNNER_USER") or os.getenv("HOSTNAME"): + return "codespace" if os.getenv("USER") == "codespace" else "github actions" + if os.getenv("ANDROID_ROOT"): + return "termux" + return "fly.io" if os.getenv("FLY_APP_NAME") else "local" + + +HOSTED_ON = detect_platform() +Var = Config() \ No newline at end of file diff --git a/core/decorators/__init__.py b/core/decorators/__init__.py new file mode 100644 index 0000000000..7afc5be32d --- /dev/null +++ b/core/decorators/__init__.py @@ -0,0 +1,51 @@ +# Ultroid - UserBot +# Copyright (C) 2020-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + + +from contextlib import suppress + +from database import udB + +from ._wrappers import eod, eor + +# ----------------------------------------------# +StatsHolder = {} + +def should_allow_sudos(): + return udB.get_key("SUDO") + + +def get_sudos() -> list: + return udB.get_key("SUDOS") or [] # type: ignore + + +def is_sudo(userid): + return userid in get_sudos() + + +def owner_and_sudos(only_full=False): + if only_full: + return [udB.get_config("OWNER_ID"), *fullsudos()] + return [udB.get_config("OWNER_ID"), *get_sudos()] + + +def _parse(key): + with suppress(TypeError): + return int(key) + return key + + +def fullsudos(): + fullsudos = [] + if sudos := udB.get_key("FULLSUDO"): + fullsudos.extend(str(sudos).split()) + owner = udB.get_config("OWNER_ID") + if owner and owner not in fullsudos: + fullsudos.append(owner) + return list(map(_parse, filter(lambda id: id, fullsudos))) + +# ------------------------------------------------ # \ No newline at end of file diff --git a/pyUltroid/_misc/_assistant.py b/core/decorators/_assistant.py similarity index 64% rename from pyUltroid/_misc/_assistant.py rename to core/decorators/_assistant.py index 83afa459d4..7fa980551e 100644 --- a/pyUltroid/_misc/_assistant.py +++ b/core/decorators/_assistant.py @@ -1,5 +1,5 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2020-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in @@ -7,18 +7,24 @@ import inspect import re -from traceback import format_exc +from html import escape +from traceback import format_exc, extract_stack +from pathlib import Path from telethon import Button from telethon.errors import QueryIdInvalidError from telethon.events import CallbackQuery, InlineQuery, NewMessage from telethon.tl.types import InputWebDocument -from .. import LOGS, asst, udB, ultroid_bot -from ..fns.admins import admin_check -from . import append_or_update, owner_and_sudos +from core import LOGS, asst, udB, ultroid_bot +from core.remote import rm +from database._core import InlinePlugin, InlinePaths +from utilities.admins import admin_check + +from . import owner_and_sudos OWNER = ultroid_bot.full_name +CWD = Path.cwd() MSG = f""" **Ultroid - UserBot** @@ -28,29 +34,18 @@ ➖➖➖➖➖➖➖➖➖➖ """ -IN_BTTS = [ - [ - Button.url( - "Repository", - url="https://github.com/TeamUltroid/Ultroid", - ), - Button.url("Support", url="https://t.me/UltroidSupportChat"), - ] -] - # decorator for assistant def asst_cmd(pattern=None, load=None, owner=False, **kwargs): """Decorator for assistant's command""" - name = inspect.stack()[1].filename.split("/")[-1].replace(".py", "") + inspect.stack()[1].filename.split("/")[-1].replace(".py", "") kwargs["forwards"] = False + if pattern: + kwargs["pattern"] = re.compile(f"^/{pattern}") def ult(func): - if pattern: - kwargs["pattern"] = re.compile(f"^/{pattern}") - async def handler(event): if owner and event.sender_id not in owner_and_sudos(): return @@ -60,8 +55,6 @@ async def handler(event): LOGS.exception(er) asst.add_event_handler(handler, NewMessage(**kwargs)) - if load is not None: - append_or_update(load, func, name, kwargs) return ult @@ -70,7 +63,7 @@ def callback(data=None, from_users=[], admins=False, owner=False, **kwargs): """Assistant's callback decorator""" if "me" in from_users: from_users.remove("me") - from_users.append(ultroid_bot.uid) + from_users.append(ultroid_bot.me.id) def ultr(func): async def wrapper(event): @@ -90,12 +83,22 @@ async def wrapper(event): return ultr -def in_pattern(pattern=None, owner=False, **kwargs): +def in_pattern(pattern=None, owner=False, button=None, **kwargs): """Assistant's inline decorator.""" def don(func): async def wrapper(event): if owner and event.sender_id not in owner_and_sudos(): + IN_BTTS = [ + [ + Button.url( + "Repository", + url="https://github.com/TeamUltroid/Ultroid", + ), + Button.url("Support", url="https://t.me/UltroidSupportChat"), + ] + ] + res = [ await event.builder.article( title="Ultroid Userbot", @@ -120,19 +123,30 @@ async def wrapper(event): await func(event) except QueryIdInvalidError: pass - except Exception as er: + except Exception: err = format_exc() - - def error_text(): - return f"**#ERROR #INLINE**\n\nQuery: `{asst.me.username} {pattern}`\n\n**Traceback:**\n`{format_exc()}`" - - LOGS.exception(er) + MakeHtml = f""" +Bot: @{asst.me.username} +

Query:


+
{escape(pattern or '')}

+

Traceback:


+
{escape(err)}
+""" + try: + with rm.get("graph", helper=True, dispose=True) as mod: + graphLink = await mod.make_html_telegraph( + "Inline Error", MakeHtml + ) + except Exception as er: + LOGS.exception(f"Error while pasting inline error: {er}") + LOGS.exception(err) + return try: await event.answer( [ await event.builder.article( title="Unhandled Exception has Occured!", - text=error_text(), + text=graphLink, buttons=Button.url( "Report", "https://t.me/UltroidSupportChat" ), @@ -140,11 +154,17 @@ def error_text(): ] ) except QueryIdInvalidError: - LOGS.exception(err) + msg = f"[An error occurred]" + await asst.send_message(udB.get_config("LOG_CHANNEL"), msg) except Exception as er: + LOGS.exception(err) LOGS.exception(er) - await asst.send_message(udB.get_key("LOG_CHANNEL"), error_text()) asst.add_event_handler(wrapper, InlineQuery(pattern=pattern, **kwargs)) + if button: + InlinePlugin.update(button) + if kwargs.get("add_help") is not False: + _path = extract_stack(limit=2)[0].filename[:-3][len(str(CWD)) + 1 :] + InlinePaths.append(_path.replace("/", ".")) return don diff --git a/pyUltroid/_misc/_decorators.py b/core/decorators/_decorators.py similarity index 60% rename from pyUltroid/_misc/_decorators.py rename to core/decorators/_decorators.py index bc93c9247e..4ea398edb3 100644 --- a/pyUltroid/_misc/_decorators.py +++ b/core/decorators/_decorators.py @@ -1,16 +1,16 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2020-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in # . import asyncio -import inspect import re import sys -from io import BytesIO -from pathlib import Path +import traceback +from functools import wraps +from html import escape from time import gmtime, strftime from traceback import format_exc @@ -32,27 +32,30 @@ UserIsBotError, ) from telethon.events import MessageEdited, NewMessage +from telethon.tl.custom import Message from telethon.utils import get_display_name -from pyUltroid.exceptions import DependencyMissingError -from strings import get_string +from core import * +from core.version import version as ult_ver +from database._core import LIST -from .. import * -from .. import _ignore_eval -from ..dB import DEVLIST -from ..dB._core import LIST, LOADED -from ..fns.admins import admin_check -from ..fns.helper import bash -from ..fns.helper import time_formatter as tf -from ..version import __version__ as pyver -from ..version import ultroid_version as ult_ver -from . import SUDO_M, owner_and_sudos +# from core import _ignore_eval +from database.helpers import DEVLIST +from localization import get_string +from utilities.admins import admin_check +from utilities.helper import bash, check_update +from utilities.helper import time_formatter as tf + +from . import fullsudos, owner_and_sudos, StatsHolder +from . import should_allow_sudos as allow_sudo from ._wrappers import eod MANAGER = udB.get_key("MANAGER") TAKE_EDITS = udB.get_key("TAKE_EDITS") black_list_chats = udB.get_key("BLACKLIST_CHATS") -allow_sudo = SUDO_M.should_allow_sudo + + +_ignore_eval = [] def compile_pattern(data, hndlr): @@ -62,22 +65,27 @@ def compile_pattern(data, hndlr): data = data[1:] if hndlr in [" ", "NO_HNDLR"]: # No Hndlr Feature - return re.compile("^" + data) + return re.compile(f"^{data}") return re.compile("\\" + hndlr + data) -def ultroid_cmd( - pattern=None, manager=False, ultroid_bot=ultroid_bot, asst=asst, **kwargs -): +def ultroid_cmd(pattern=None, manager=False, asst=asst, **kwargs): + reply_req = kwargs.get("replied", False) owner_only = kwargs.get("owner_only", False) groups_only = kwargs.get("groups_only", False) admins_only = kwargs.get("admins_only", False) fullsudo = kwargs.get("fullsudo", False) only_devs = kwargs.get("only_devs", False) + # cmd_key = kwargs.get("cmds_key") func = kwargs.get("func", lambda e: not e.via_bot_id) def decor(dec): - async def wrapp(ult): + @wraps(dec) + async def wrapp(ult: Message): + if not udB.get_key("DISABLE_STATS"): + n_pattern = "".join(str(i) for i in pattern if 97 <= ord(i) <= 122) + count = StatsHolder.get(n_pattern, 0) + StatsHolder[n_pattern] = count + 1 if not ult.out: if owner_only: return @@ -88,38 +96,40 @@ async def wrapp(ult): ult, get_string("py_d1"), ) - if fullsudo and ult.sender_id not in SUDO_M.fullsudos: + if fullsudo and ult.sender_id not in fullsudos(): return await eod(ult, get_string("py_d2"), time=15) + if reply_req and not (await ult.get_reply_message()): + return await eod(ult, "Reply to a message.") chat = ult.chat - if hasattr(chat, "title"): - if ( - "#noub" in chat.title.lower() - and not (chat.admin_rights or chat.creator) - and not (ult.sender_id in DEVLIST) - ): - return + if ( + hasattr(chat, "title") + and "#noub" in chat.title.lower() + and not chat.admin_rights + and not chat.creator + and ult.sender_id not in DEVLIST + ): + return if ult.is_private and (groups_only or admins_only): return await eod(ult, get_string("py_d3")) - elif admins_only and not (chat.admin_rights or chat.creator): + elif admins_only and not chat.admin_rights and not chat.creator: return await eod(ult, get_string("py_d5")) if only_devs and not udB.get_key("I_DEV"): return await eod( ult, - get_string("py_d4").format(HNDLR), + get_string("py_d4", HNDLR), time=10, ) try: await dec(ult) except FloodWaitError as fwerr: await asst.send_message( - udB.get_key("LOG_CHANNEL"), + udB.get_config("LOG_CHANNEL"), f"`FloodWaitError:\n{str(fwerr)}\n\nSleeping for {tf((fwerr.seconds + 10)*1000)}`", ) - await ultroid_bot.disconnect() - await asyncio.sleep(fwerr.seconds + 10) + time.sleep(fwerr.seconds + 10) await ultroid_bot.connect() await asst.send_message( - udB.get_key("LOG_CHANNEL"), + udB.get_config("LOG_CHANNEL"), "`Bot is working again`", ) return @@ -134,7 +144,7 @@ async def wrapp(ult): ult, get_string("py_d7"), ) - except (BotInlineDisabledError, DependencyMissingError) as er: + except (BotInlineDisabledError, ConnectionError) as er: return await eod(ult, f"`{er}`") except ( MessageIdInvalidError, @@ -145,7 +155,7 @@ async def wrapp(ult): except AuthKeyDuplicatedError as er: LOGS.exception(er) await asst.send_message( - udB.get_key("LOG_CHANNEL"), + udB.get_config("LOG_CHANNEL"), "Session String expired, create new session from 👇", buttons=[ Button.url("Bot", "t.me/SessionGeneratorBot?start="), @@ -160,61 +170,69 @@ async def wrapp(ult): raise events.StopPropagation except KeyboardInterrupt: pass - except Exception as e: - LOGS.exception(e) + except Exception: date = strftime("%Y-%m-%d %H:%M:%S", gmtime()) naam = get_display_name(chat) - ftext = "**Ultroid Client Error:** `Forward this to` @UltroidSupportChat\n\n" - ftext += "**Py-Ultroid Version:** `" + str(pyver) - ftext += "`\n**Ultroid Version:** `" + str(ult_ver) - ftext += "`\n**Telethon Version:** `" + str(telever) - ftext += f"`\n**Hosted At:** `{HOSTED_ON}`\n\n" - ftext += "--------START ULTROID CRASH LOG--------" - ftext += "\n**Date:** `" + date - ftext += "`\n**Group:** `" + str(ult.chat_id) + "` " + str(naam) - ftext += "\n**Sender ID:** `" + str(ult.sender_id) - ftext += "`\n**Replied:** `" + str(ult.is_reply) - ftext += "`\n\n**Event Trigger:**`\n" - ftext += str(ult.text) - ftext += "`\n\n**Traceback info:**`\n" - ftext += str(format_exc()) - ftext += "`\n\n**Error text:**`\n" - ftext += str(sys.exc_info()[1]) - ftext += "`\n\n--------END ULTROID CRASH LOG--------" - ftext += "\n\n\n**Last 5 commits:**`\n" - + chat_username = getattr(ult.chat, "username", None) + sender = await ult.get_sender() + replied = await ult.get_reply_message() stdout, stderr = await bash('git log --pretty=format:"%an: %s" -5') result = stdout + (stderr or "") - - ftext += f"{result}`" - - if len(ftext) > 4096: - with BytesIO(ftext.encode()) as file: - file.name = "logs.txt" - error_log = await asst.send_file( - udB.get_key("LOG_CHANNEL"), - file, - caption="**Ultroid Client Error:** `Forward this to` @UltroidSupportChat\n\n", + result = "".join( + [f"
  • {escape(line)}
  • " for line in result.split("\n")] + ) + MakeHtml = f""" + +Report Error +

    +
      +
    • Version: {ult_ver} -  [{HOSTED_ON}]
    • +{'
    • Update Available: True
    • ' if check_update() else ''} +
    • Telethon: {telever}
    • +
    • Date: {date}
    • +
    • Group: {f'@{chat_username}' if chat_username else f'{ult.chat_id}'} [{escape(naam)}]
    • +
    • Sender: {escape(get_display_name(sender))} {ult.sender_id}
    • +
    • Replied:  {f'This message' if replied else 'False'}
    • +

    +

    Trigger:

    +
    {escape(ult.text)}
    +
    +

    Traceback:

    +
    {escape(format_exc())}
    +
    +

    Last 5 Commits:

    +
      {result}
    +""" + try: + ultr = getattr(ult, "_eor", None) or ult + if ultr.out: + await ultr.edit(get_string("py_d9")) + with rm.get("graph", helper=True, dispose=True) as mod: + graphLink = await mod.make_html_telegraph( + "Ultroid Error", MakeHtml ) - else: - error_log = await asst.send_message( - udB.get_key("LOG_CHANNEL"), - ftext, + msg = f"\xad[An error occurred]" + + Msg = await asst.send_message( + udB.get_config("LOG_CHANNEL"), + msg, + parse_mode="html", ) - if ult.out: - await ult.edit( - f"[An error occurred]", - link_preview=False, + await ultr.edit( + f"[An error occurred]", parse_mode="html", ) + except Exception as er: + LOGS.error(f"Error while pasting exception on graph: {er}") + LOGS.exception(er) cmd = None - blacklist_chats = False chats = None + blacklist_chats = bool(black_list_chats) if black_list_chats: - blacklist_chats = True - chats = list(black_list_chats) - _add_new = allow_sudo and HNDLR != SUDO_HNDLR + chats = black_list_chats + + _add_new = allow_sudo() and HNDLR != SUDO_HNDLR if _add_new: if pattern: cmd = compile_pattern(pattern, SUDO_HNDLR) @@ -245,9 +263,13 @@ async def wrapp(ult): if TAKE_EDITS: def func_(x): - return not x.via_bot_id and not (x.is_channel and x.chat.broadcast) + return ( + (x.out or x.sender_id == ultroid_bot.me.id) + and not x.via_bot_id + and not (x.is_channel and x.chat.broadcast) + ) - ultroid_bot.add_event_handler( + ultroid_bot.add_handler( wrapp, MessageEdited( pattern=cmd, @@ -260,7 +282,7 @@ def func_(x): if manager and MANAGER: allow_all = kwargs.get("allow_all", False) allow_pm = kwargs.get("allow_pm", False) - require = kwargs.get("require", None) + require = kwargs.get("require") async def manager_cmd(ult): if not allow_all and not (await admin_check(ult, require=require)): @@ -277,28 +299,27 @@ async def manager_cmd(ult): return await asst.send_message( chat, text, link_preview=False ) - except Exception as er: - LOGS.exception(er) + except Exception as err: + LOGS.exception(err) LOGS.info(f"• MANAGER [{ult.chat_id}]:") LOGS.exception(er) if pattern: cmd = compile_pattern(pattern, "/") - asst.add_event_handler( - manager_cmd, - NewMessage( + _event = NewMessage( pattern=cmd, forwards=False, incoming=True, func=func, chats=chats, blacklist_chats=blacklist_chats, - ), - ) + ) + _event.manager = True + asst.add_handler(manager_cmd, _event) if DUAL_MODE and not (manager and DUAL_HNDLR == "/"): if pattern: cmd = compile_pattern(pattern, DUAL_HNDLR) - asst.add_event_handler( + asst.add_handler( wrapp, NewMessage( pattern=cmd, @@ -309,17 +330,12 @@ async def manager_cmd(ult): blacklist_chats=blacklist_chats, ), ) - file = Path(inspect.stack()[1].filename) - if "addons/" in str(file): - if LOADED.get(file.stem): - LOADED[file.stem].append(wrapp) - else: - LOADED.update({file.stem: [wrapp]}) + if pattern: - if LIST.get(file.stem): - LIST[file.stem].append(pattern) - else: - LIST.update({file.stem: [pattern]}) + file = os.path.basename(traceback.extract_stack(limit=2)[0].filename)[:-3] + if LIST.get(file) is None: + LIST[file] = [] + LIST[file].append(pattern) return wrapp return decor diff --git a/core/decorators/_supporter.py b/core/decorators/_supporter.py new file mode 100644 index 0000000000..e296c30066 --- /dev/null +++ b/core/decorators/_supporter.py @@ -0,0 +1,69 @@ +# Ultroid - UserBot +# Copyright (C) 2020-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . +# +# To Install Other USERBOTs plugin Support +# +# ULTROID Don't Need This Stuffs +# + +import os +import traceback + +from telethon import events, types + +from core import * +from core.config import Config +from core.decorators._decorators import compile_pattern, ultroid_cmd +from core.decorators._wrappers import eod, eor +from database._core import LIST + +from . import get_sudos # ignore: pylint + +ALIVE_NAME = ultroid_bot.me.first_name +BOTLOG_CHATID = BOTLOG = udB.get_config("LOG_CHANNEL") + + +bot = borg = catub = friday = ultroid_bot +catub.cat_cmd = ultroid_cmd # type: ignore + +black_list_chats = udB.get_key("BLACKLIST_CHATS") + + +def admin_cmd(pattern=None, func=None, **args): + args["func"] = lambda e: not e.via_bot_id and func + args["chats"] = black_list_chats + args["blacklist_chats"] = True + args["outgoing"] = True + args["forwards"] = False + if pattern: + args["pattern"] = compile_pattern(pattern, HNDLR) + file = os.path.basename(traceback.extract_stack(limit=2)[0].filename)[:-3] + if LIST.get(file) is None: + LIST[file] = [] + LIST[file].append(pattern) + return events.NewMessage(**args) + + +friday_on_cmd = admin_cmd +register = command = ultroid_cmd + +def sudo_cmd(allow_sudo=True, pattern=None, func=None, **args): + args["func"] = lambda e: not e.via_bot_id and e.sender_id in get_sudos() and func + args["chats"] = black_list_chats + args["blacklist_chats"] = True + args["forwards"] = False + if pattern: + args["pattern"] = compile_pattern(pattern, SUDO_HNDLR) + if allow_sudo: + args["incoming"] = True + return events.NewMessage(**args) + + +edit_or_reply = eor +edit_delete = eod + +CMD_HNDLR = HNDLR diff --git a/pyUltroid/_misc/_wrappers.py b/core/decorators/_wrappers.py similarity index 88% rename from pyUltroid/_misc/_wrappers.py rename to core/decorators/_wrappers.py index ee6dd345d3..adeb42e4b7 100644 --- a/pyUltroid/_misc/_wrappers.py +++ b/core/decorators/_wrappers.py @@ -1,5 +1,5 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2020-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in @@ -11,10 +11,14 @@ from telethon.tl.custom import Message from telethon.tl.types import MessageService +from core.setup import LOGS + # edit or reply -async def eor(event, text=None, time=None, link_preview=False, edit_time=None, **args): +async def eor( + event: Message, text=None, time=None, link_preview=False, edit_time=None, **args +): reply_to = event.reply_to_msg_id or event if event.out and not isinstance(event, MessageService): if edit_time: @@ -28,6 +32,7 @@ async def eor(event, text=None, time=None, link_preview=False, edit_time=None, * reply_to=reply_to, **args ) + else: try: ok = await event.edit(text, link_preview=link_preview, **args) @@ -41,6 +46,8 @@ async def eor(event, text=None, time=None, link_preview=False, edit_time=None, * if time: await sleep(time) return await ok.delete() + event._eor = ok + return ok @@ -52,11 +59,9 @@ async def eod(event, text=None, **kwargs): async def _try_delete(event): try: return await event.delete() - except (MessageDeleteForbiddenError): + except MessageDeleteForbiddenError: pass except BaseException as er: - from . import LOGS - LOGS.error("Error while Deleting Message..") LOGS.exception(er) diff --git a/core/git.py b/core/git.py new file mode 100644 index 0000000000..7750185ba6 --- /dev/null +++ b/core/git.py @@ -0,0 +1,44 @@ +import os +from subprocess import run, PIPE + +class InvalidGitPath(Exception): + ... + +class GitError(Exception): + ... + +class Repo: + """A wrapper class around git commandline""" + + def __init__(self, path: str = ".") -> None: + self._path = path + + def active_branch(self): + return self._run("git rev-parse --abbrev-ref HEAD").strip() + + def remotes(self): + return [remote.strip() for remote in self._run("git remote").split("\n") if remote] + + def fetch_remote(self, remote: str = "origin"): + return self._run(["git", "fetch", remote]) + + def get_remote_url(self, remote: str="origin"): + return self._run(f"git remote get-url {remote}") + + def rev_parse(self, remote: str = "origin"): + return self._run(["git", "rev-parse", remote]) + + def _run(self, cmd): + if not os.path.exists(f"{self._path}/.git"): + raise InvalidGitPath("No git repository initialised on given path.") + if isinstance(cmd, str): + cmd = cmd.split(" ") + proc = run(cmd, cwd=self._path, stdout=PIPE, stderr=PIPE) + if proc.stderr and proc.returncode: + raise GitError(f"Command exited with error: {proc.stderr}, output: {proc.stdout}") + out = proc.stdout or proc.stderr + if out is None: + raise GitError('Unknown Error: command output not found') + return out.decode() + +repo = Repo() \ No newline at end of file diff --git a/core/loader.py b/core/loader.py new file mode 100644 index 0000000000..da80faa8d5 --- /dev/null +++ b/core/loader.py @@ -0,0 +1,72 @@ +# Ultroid - UserBot +# Copyright (C) 2020-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +import contextlib +import glob +import os +from importlib import import_module +from typing import Union, List +from . import LOGS +from collections import deque +from utilities.helper import get_all_files + +PLUGINS = {} + +def __load(func, plugin, key, single): + if func == import_module: + plugin = plugin.replace(".py", "").replace("/", ".").replace("\\", ".") + try: + modl = func(plugin) + except ModuleNotFoundError as er: + LOGS.error(f"{plugin}: '{er.name}' not installed!") + return + except Exception as exc: + LOGS.error(f"pyUltroid - {key} - ERROR - {plugin}") + LOGS.exception(exc) + return + PLUGINS[modl.__name__] = modl + if single: + LOGS.info(f"Successfully loaded {modl.__name__}") + + +def load( + log=True, + func=import_module, + include=None, + exclude=None, + plugins=None, + key="Official", + path: Union[str, List[str]]="modules", +): + _single = isinstance(path, str) and os.path.isfile(path) + if include: + if log: + LOGS.info(f'Including: {"• ".join(include)}') + files = glob.glob(f"{path}/_*.py") + files.extend( + list(filter(lambda file: os.path.exists(f"{path}/{file}.py"), include)) + ) + elif _single: + files = [path] + elif isinstance(path, list): + files = [] + for path in path: + files.extend(get_all_files(path, ".py")) + else: + files = get_all_files(path, ".py") + if exclude: + for path_ in filter(lambda e: not e.startswith("_"), exclude): + with contextlib.suppress(ValueError): + files.remove(f"{path}/{path_}.py") + if plugins: + files.extend(plugins) + if log and not _single: + LOGS.info( + f"• Installing %s Plugins || Count : {len(files)} •", + key, + ) + deque(map(lambda e: __load(func, e, key, _single), files), 0) \ No newline at end of file diff --git a/core/remote.py b/core/remote.py new file mode 100644 index 0000000000..87dc617c45 --- /dev/null +++ b/core/remote.py @@ -0,0 +1,194 @@ +import os, json +import time, sys +import subprocess +from .config import Var +from contextlib import suppress +from logging import getLogger +from contextlib import contextmanager +from utilities.helper import fetch_sync, run_async, fetch +from importlib import import_module + +LOCK_PATH = "./ultroid-lock.json" +Logger = getLogger("Remote") + + +class Remote: + REMOTE_URL = Var.REMOTE_URI or "https://plugins.xditya.me" + MAX_HR = 1 + DEF_CONFIG = {"plugins": {}, "helpers": {}, "manager": {}} + + def __init__(self) -> None: + self._modules = {} + self._deps = [] + self._status_fetch = None + + if os.path.exists(LOCK_PATH): + with open(LOCK_PATH, "r") as file: + try: + self.RemoteConfig: dict = json.load(file) + except json.decoder.JSONDecodeError: + Logger.error("Failed to decode ultroid lock file, creating new...") + self.RemoteConfig = self.DEF_CONFIG + else: + self.RemoteConfig = self.DEF_CONFIG + + def _http_import(self, path: str, save_as=None, helper=False, manager=False): + if not save_as: + save_as = f"{path}.py" + if helper: + _pat = "helpers" + mid = "helper" + elif manager: + _pat = mid = "manager" + else: + _pat, mid = "plugins", "" + in_local = self.RemoteConfig[_pat].get(path) + _exists = os.path.exists(save_as) + + # Last fetched in less than avoided time gap. + if in_local and self.get_status() and _exists: + return save_as + details: dict = fetch_sync(f"{self.REMOTE_URL}/search{mid}/{path}", True) # type: ignore + if not isinstance(details, dict): + Logger.error(details) + return + if details.get("status") == 404: + Logger.debug(f"got 404 response, {details}") + return + if in_local and in_local["version"] == details.get("version") and _exists: + return save_as + if details.get("deps"): + self.__install_deps(details["deps"]) + remote_file = fetch_sync( + f"{self.REMOTE_URL}/get{mid}/{path}", + evaluate=lambda e: e.content if e.status_code == 200 else None, + ) + + if remote_file: + with open(save_as, "wb") as file: + file.write(remote_file) # type: ignore + + with suppress(KeyError): + del details["repo"] + del details["path"] + + self.RemoteConfig[_pat][path] = details + return save_as + + @contextmanager + def get(self, path_: str, save_as=None, force: bool = False, *args, **kwargs): + _save = kwargs.get("_save", True) + _load = kwargs.get("_load", True) + _dispose = kwargs.get("dispose", False) + for key in ["_save", "dispose", "_load"]: + with suppress(KeyError): + del kwargs[key] + if not force: + with suppress(KeyError): + yield self._modules[path_] + return + try: + if _load and (path := self._http_import(path_, save_as, *args, **kwargs)): + path = path[:-3].replace("/", ".").replace("\\", ".") + modl = import_module(path) + self._modules[path_] = modl + yield modl + finally: + if _dispose: + os.remove( + save_as if (save_as and os.path.exists(save_as)) else f"{path_}.py" + ) + if _save: + self.save() + + async_get = run_async(get) + _async_import = run_async(_http_import) + + async def async_import(self, *args, **kwargs): + try: + return await self._async_import(*args, **kwargs) + except Exception as er: + Logger.exception(er) + + def __install_deps(self, deps: list): + # TODO: Improve + proc = [] + for dep in deps: + depc = None + if isinstance(dep, list): + depc, dep = dep + if dep in self._deps: + continue + if not depc: + depc = dep.split("[")[0].split("=")[0] + try: + import_module(depc) + except ModuleNotFoundError: + print(f"Installing {dep}", end="\r") + proc.append( + subprocess.Popen( + [sys.executable, "-m", "pip", "install", dep], + stderr=subprocess.PIPE, + ) + ) + self._deps.append(dep) + for prc in proc: + prc.wait(timeout=10000) + if err:= prc.stderr.read(): + Logger.error(err) + + async def get_all_plugins(self, end): + return await fetch(f"{self.REMOTE_URL}/{end}", re_json=True) + + def get_info(self, id): + return self.RemoteConfig["plugins"].get(id, {}) + + def get_status(self): + if self._status_fetch: + return True + if tim := self.RemoteConfig.get("last_fetched"): + if ((time.time() - tim) / (1000 * 60 * 60)) < self.MAX_HR: + self._status_fetch = True + return True + + def set_status_done(self): + if self.get_status(): + return + self.RemoteConfig["last_fetched"] = time.time() + self.save() + + def fetch_lang( + self, langCode, strings_path="localization/strings", defaultLang="en" + ): + filePath = f"{strings_path}/{langCode}.yml" + if self.get_status() and os.path.exists(filePath): + return + + def evaluate(req): + if req.headers["content-type"] == "application/json": + Logger.error(f"Invalid Response recieved, {req.json()}") + + if langCode != defaultLang and not os.path.exists( + filePath + ): + return self.fetch_lang(defaultLang) + return + + with open(filePath, "wb") as file: + file.write(req.content) + + return filePath + + return fetch_sync( + f"{self.REMOTE_URL}/getlanguage/{langCode}", evaluate=evaluate + ) + + async def getLanguages(self): + return await fetch(f"{self.REMOTE_URL}/getlanguage", re_json=True) + + def save(self): + with open(LOCK_PATH, "w") as file: + json.dump(self.RemoteConfig, file) + + +rm = Remote() diff --git a/core/sessiongen.py b/core/sessiongen.py new file mode 100644 index 0000000000..31803e0643 --- /dev/null +++ b/core/sessiongen.py @@ -0,0 +1,56 @@ +from re import compile +from core.version import version +from telethonpatch import TelegramClient +from telethon.events import NewMessage, CallbackQuery +from telethon.tl.custom import Message, Button +from core.config import Var +from core.decorators._assistant import asst_cmd, callback + + +@asst_cmd("session", owner=True) +async def sessionCommand(event: Message): + await event.reply( + "*Select type of session to generate:*", + buttons=[ + [ + Button.inline("Telethon", "gen_telethon"), + Button.inline("Pyrogram", "gen_pyrogram"), + ] + ], + ) + + +async def generate_session(ult: NewMessage, type: str): + client: TelegramClient = ult.client + if type == "telethon": + from telethon.sessions import StringSession + + new_client = TelegramClient( + StringSession(), + api_id=Var.API_ID, + api_hash=Var.API_HASH, + app_version=version, + ) + else: + from pyrogram import Client + + new_client = Client( + ":memory:", api_id=Var.API_ID, api_hash=Var.API_HASH, in_memory=True + ) + async with client.conversation(ult.chat_id) as conv: + message = await conv.send_message("Please send your phone number:") + phoneNumber = await conv.get_response() + await phoneNumber.delete() + if type == "telethon": + sentCode = await new_client.send_code_request(phoneNumber) + else: + sentCode = await new_client.send_code(phone_number=phoneNumber) + await conv.send_message("Please enter the code in this format:\n6 5 8 5 5 5") + loginCode = await conv.get_response() + await TelegramClient.sign_in(phone=phoneNumber, code=loginCode.message.replace(' ', '')) + + +@callback(compile("gen_(.*)"), owner=True) +async def onGen(event: CallbackQuery.Event): + _type = event.pattern_match.split("_")[-1] + await generate_session(event, _type) diff --git a/core/setup.py b/core/setup.py new file mode 100644 index 0000000000..a65eaa68bb --- /dev/null +++ b/core/setup.py @@ -0,0 +1,68 @@ +# Ultroid - UserBot +# Copyright (C) 2020-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +import os +import platform +import sys +from logging import INFO, WARNING, FileHandler, StreamHandler, basicConfig, getLogger +from .config import HOSTED_ON + +import contextlib +from telethon import __version__ +from telethon.tl.alltlobjects import LAYER + +from core.version import version + + +def _ask_input(): + # Ask for Input even on Vps and other platforms. + def new_input(*args, **kwargs): + raise EOFError(f"args={args}, kwargs={kwargs}") + + __builtins__["input"] = new_input + + +file = f"ultroid{sys.argv[6]}.log" if len(sys.argv) > 6 else "ultroid.log" + +if os.path.exists(file): + os.remove(file) + +LOGS = getLogger("pyUltLogs") +TelethonLogger = getLogger("Telethon") +TelethonLogger.setLevel(WARNING) + +_ask_input() + +_LOG_FORMAT = "%(asctime)s | %(name)s [%(levelname)s] : %(message)s" +basicConfig( + format=_LOG_FORMAT, + level=INFO, + datefmt="%m/%d/%Y, %H:%M:%S", + handlers=[FileHandler(file), StreamHandler()], +) + +with contextlib.suppress(ImportError): + import coloredlogs # type: ignore + + coloredlogs.install(level=None, logger=LOGS, fmt=_LOG_FORMAT) + +LOGS.info( + """ +----------------------------------- +Starting Deployment +----------------------------------- +""" +) + +LOGS.info(f"Python version - {platform.python_version()}") +LOGS.info(f"Telethon Version - {__version__} [Layer: {LAYER}]") +LOGS.info(f"Ultroid Version - {version} [{HOSTED_ON}] [{platform.system()}]") + +try: + from safety.tools import * # type: ignore +except ImportError: + LOGS.error("'safety' package not found!") diff --git a/core/utils/__init__.py b/core/utils/__init__.py new file mode 100644 index 0000000000..5aacaecfc8 --- /dev/null +++ b/core/utils/__init__.py @@ -0,0 +1,38 @@ +import sys, subprocess, re +from ..config import Config + +def isMultiClient(): + if getArg := list(filter(re.compile("--run=(.*)").match, sys.argv)): + runCode = getArg[0].split("=")[-1] + else: + return startMultiClient() + _session = getattr(Config, f"SESSION{runCode}") + _db = _get_db(runCode) + _botToken = getattr(Config, f"BOT_TOKEN{runCode}") + + if not (_db and _session): + return + return runCode, _session, _botToken + + +def _get_db(count): + + _db = None + for key in ["REDIS_URI", "MONGO_URI", "DATABASE_URL"]: + _db = getattr(Config, f"{key}{count}") + if _db: + break + + return _db + +def startMultiClient(): + start = 1 + while True: + _db = _get_db(start) + if _db and getattr(Config, f"SESSION{start}"): + subprocess.call([sys.executable, "-m", "core", f"--run={start}"]) + start += 1 + continue + break + + diff --git a/pyUltroid/startup/utils.py b/core/utils/addons.py similarity index 73% rename from pyUltroid/startup/utils.py rename to core/utils/addons.py index 95246afe79..ea96fdc7a3 100644 --- a/pyUltroid/startup/utils.py +++ b/core/utils/addons.py @@ -1,5 +1,5 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2020-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in @@ -8,6 +8,15 @@ from importlib import util from sys import modules +from core import HNDLR, LOGS, asst, udB, ultroid_bot +from core.config import Var +from core.decorators import _supporter as config +from core.decorators._assistant import asst_cmd, callback, in_pattern +from core.decorators._decorators import ultroid_cmd +from core.decorators._supporter import Config, admin_cmd, sudo_cmd +from core.decorators._wrappers import eod, eor +from database._core import CMD_HELP as HELP + # for addons configPaths = [ @@ -29,27 +38,20 @@ def load_addons(plugin_name): + import core + import modules as m + base_name = plugin_name.split("/")[-1].split("\\")[-1].replace(".py", "") if base_name.startswith("__"): return - from pyUltroid import fns - - from .. import HNDLR, LOGS, asst, udB, ultroid_bot - from .._misc import _supporter as config - from .._misc._assistant import asst_cmd, callback, in_pattern - from .._misc._decorators import ultroid_cmd - from .._misc._supporter import Config, admin_cmd, sudo_cmd - from .._misc._wrappers import eod, eor - from ..configs import Var - from ..dB._core import HELP - name = plugin_name.replace("/", ".").replace("\\", ".").replace(".py", "") spec = util.spec_from_file_location(name, plugin_name) mod = util.module_from_spec(spec) for path in configPaths: modules[path] = config - modules["pyUltroid.functions"] = fns - mod.LOG_CHANNEL = udB.get_key("LOG_CHANNEL") + modules["pyUltroid"] = core + modules["plugins"] = m + mod.LOG_CHANNEL = udB.get_config("LOG_CHANNEL") mod.udB = udB mod.asst = asst mod.tgbot = asst @@ -80,20 +82,20 @@ def load_addons(plugin_name): mod.Redis = udB.get_key mod.admin_cmd = admin_cmd mod.sudo_cmd = sudo_cmd - mod.HELP = HELP.get("Addons", {}) - mod.CMD_HELP = HELP.get("Addons", {}) + mod.HELP = HELP + mod.CMD_HELP = HELP spec.loader.exec_module(mod) modules[name] = mod doc = modules[name].__doc__.format(i=HNDLR) if modules[name].__doc__ else "" if "Addons" in HELP.keys(): - update_cmd = HELP["Addons"] + update_cmd = HELP try: update_cmd.update({base_name: doc}) except BaseException: pass else: try: - HELP.update({"Addons": {base_name: doc}}) - except BaseException as em: + HELP[base_name] = doc + except BaseException: pass diff --git a/core/utils/base.py b/core/utils/base.py new file mode 100644 index 0000000000..15ca26c31a --- /dev/null +++ b/core/utils/base.py @@ -0,0 +1,96 @@ +# Ultroid - UserBot +# Copyright (C) 2020-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +import base64 +import ipaddress +import struct +import sys + +from telethon.sessions.string import _STRUCT_PREFORMAT, CURRENT_VERSION, StringSession + +from ..setup import LOGS + +_PYRO_FORM = {351: ">B?256sI?", 356: ">B?256sQ?", 362: ">BI?256sQ?"} + +# https://github.com/pyrogram/pyrogram/blob/master/docs/source/faq/what-are-the-ip-addresses-of-telegram-data-centers.rst + + +def _pyrogram_session(session): + DC_IPV4 = { + 1: "149.154.175.53", + 2: "149.154.167.51", + 3: "149.154.175.100", + 4: "149.154.167.91", + 5: "91.108.56.130", + } + data_ = struct.unpack( + _PYRO_FORM[len(session)], + base64.urlsafe_b64decode(session + "=" * (-len(session) % 4)), + ) + auth_id = 2 if len(session) in {351, 356} else 3 + dc_id, auth_key = data_[0], data_[auth_id] + return StringSession( + CURRENT_VERSION + + base64.urlsafe_b64encode( + struct.pack( + _STRUCT_PREFORMAT.format(4), + dc_id, + ipaddress.ip_address(DC_IPV4[dc_id]).packed, + 443, + auth_key, + ) + ).decode("ascii") + ) + + +def validate_session(session, logger=LOGS, _exit=True): + from localization import get_string + + if session: + # Telethon Session + if session.startswith(CURRENT_VERSION): + if len(session.strip()) != 353: + logger.exception(get_string("py_c1")) + sys.exit() + return StringSession(session) + + elif len(session) in _PYRO_FORM: + return _pyrogram_session(session) + else: + logger.exception(get_string("py_c1")) + if _exit: + sys.exit() + logger.exception(get_string("py_c2")) + if _exit: + exit() + + +def update_handlers(handlerType, newValue, oldValue): + from core import ultroid_bot, asst + from core.decorators._decorators import compile_pattern + + # TODO: DUAL/Asst going to be different + # Check for old matches to be sure + if handlerType == "DUAL_HNDLR": + clients = [asst, ultroid_bot] + else: + clients = [ultroid_bot if handlerType == "HNDLR" else asst] + + def update(handler): + try: + pattern = handler._pattern + except AttributeError: + return + if not pattern: + return + pattern = pattern.pattern + oldPattern = pattern[len(oldValue) + 1 if oldValue != "NO_HNDLR" else 1 :] + handler.pattern = compile_pattern(oldPattern, newValue).match + + for client in clients: + for _, handler in client.list_event_handlers(): + update(handler) diff --git a/core/utils/funcs.py b/core/utils/funcs.py new file mode 100644 index 0000000000..7c8ed5db12 --- /dev/null +++ b/core/utils/funcs.py @@ -0,0 +1,162 @@ +import asyncio +import os, sys +import time + +from core import LOGS, asst, udB, ultroid_bot +from core.loader import load +from core.remote import rm + +from utilities.helper import unload_plugin +from database._core import PluginChannel +from telethon.events import NewMessage, MessageDeleted + + +async def onNewPlugin(ult): + chat = ult.chat_id + file = await ult.download_media(f"modules/channels/c{chat}/") + from .addons import load_addons + + load_addons(file) + if PluginChannel.get(ult.chat_id) is None: + PluginChannel[ult.chat_id] = {} + PluginChannel[ult.chat_id][ult.id] = file + LOGS.debug(f"Loaded new plugin {file} from {ult.chat_id}") + + from modules.basic._help import _cache + if _cache.get("addons"): + del _cache["addons"] + + +async def onPluginDel(ult): + chat = ult.chat_id + for msg in ult.deleted_ids: + if plugin := PluginChannel[chat].get(msg): + if unload_plugin(plugin): + LOGS.info(f"Successfully Unloaded {plugin}!") + + +async def WasItRestart(key): + try: + chat, _id, sender = key + await (asst if sender == "bot" else ultroid_bot).edit_message( + chat, _id, "__Restarted Successfully.__" + ) + except Exception as er: + LOGS.exception(er) + udB.del_key("_RESTART") + + +async def plug(plugin_channels): + if ultroid_bot._bot: + LOGS.info("Plugin Channels can't be used in 'BOTMODE'") + return + with rm.get("plugin_channel", helper=True, dispose=True) as modl: + await modl.get_from_channels(plugin_channels) + ultroid_bot.add_handler( + onNewPlugin, + NewMessage( + chats=plugin_channels, func=lambda e: e.file and e.file.name.endswith(".py") + ), + ) + ultroid_bot.add_handler( + onPluginDel, + MessageDeleted( + func=lambda ult: PluginChannel.get(ult.chat_id), chats=plugin_channels + ), + ) + + +async def get_notifier(*args): + with rm.get("notifier", helper=True, dispose=True) as modl: + await modl.notify(*args) + + +async def process_main(): + tasks = [] + # Load Plugins + if plugin_channels := udB.get_key("PLUGIN_CHANNEL"): + tasks.append(plug(plugin_channels)) + + # Update Restart message + if res := udB.get_key("_RESTART"): + tasks.append(WasItRestart(res)) + + # Notify: send message + if (init := not udB.get_key("INIT_DEPLOY")) or udB.get_key("NOTIFY"): + tasks.append(get_notifier(init)) + + tz = udB.get_key("TIMEZONE") + if tz and os.environ.get("TZ") != tz and hasattr(time, "tzset"): + with rm.get("timezone", helper=True, dispose=True) as modl: + if modl: + modl.set_timezone(tz) + + # Run: task in background + await asyncio.gather(*tasks) + + +def setup_addons(): + if not os.path.exists("modules/addons"): + os.mkdir("modules/addons") + with open("modules/addons/__init__.py", "w") as file: + file.write("from .. import *") + + +async def load_plugins(): + # TODO: REMOVE + if "no-addons" in sys.argv: + load(path=["modules/basic"]) + return + + # GET: Addons plugins + + plugins = None + load_path = ["modules/basic", "modules/addons", "modules/assistant"] + + async def _fetch(plugs, folder, **kwargs): + return await asyncio.gather( + *[ + rm.async_import(plug, f"modules/{folder}/{plug}.py", **kwargs) + for plug in plugs + ] + ) + + async def fetch_all(end="getallplugins", folder="addons", **kwargs): + plugs = await rm.get_all_plugins(end) + if folder == "addons": + excl = udB.get_key("EXCLUDE_PLUGINS") + if excl and (excl := excl.split(",")): + [plugs.remove(spl) for spl in excl if spl in plugs] + await _fetch(plugs, folder, **kwargs) + load_path.append(f"modules/{folder}") + + if plugins := udB.get_key("PLUGINS"): + setup_addons() + plugins = list(filter(lambda e: e, await _fetch(plugins.split(","), "addons"))) + + elif udB.get_key("LOAD_ALL"): + setup_addons() + await fetch_all() + + if udB.get_config("MANAGER"): + if not os.path.exists("modules/manager"): + os.mkdir("modules/manager") + await fetch_all("getmanager", "manager", manager=True) + + rm.set_status_done() + + load(path=load_path, plugins=plugins) + + if udB.get_config("PMBOT"): + with rm.get("pmbot", helper=True, dispose=True): + LOGS.info("Loaded PMBOT.") + + # if udB.get_config("VCBOT"): + # try: + # with rm.get("setup_vcbot", helper=True, dispose=True) as mod: + # await mod.setup() + # except Exception as er: + # LOGS.exception(er) + + if not udB.get_key("INIT_DEPLOY"): + udB.set_key("INIT_DEPLOY", True) diff --git a/core/version.py b/core/version.py new file mode 100644 index 0000000000..ff7a75f229 --- /dev/null +++ b/core/version.py @@ -0,0 +1 @@ +version = "1.0" \ No newline at end of file diff --git a/database/README.md b/database/README.md new file mode 100644 index 0000000000..bc7f0d63f1 --- /dev/null +++ b/database/README.md @@ -0,0 +1,2 @@ +# `database` +This directory contains all the database related functions and helpers for Ultroid. \ No newline at end of file diff --git a/database/__init__.py b/database/__init__.py new file mode 100644 index 0000000000..2abbe5ce05 --- /dev/null +++ b/database/__init__.py @@ -0,0 +1,12 @@ +""" +new home for all database functions +subfolders: +initialize - all db startup functions +db_functions - all db functions +""" + +from .initialize.get_db import getDatabase +from .initialize.base_db import BaseDatabase + + +udB: BaseDatabase = getDatabase() # type: ignore diff --git a/pyUltroid/dB/_core.py b/database/_core.py similarity index 60% rename from pyUltroid/dB/_core.py rename to database/_core.py index 78f29ad91b..a551688fd2 100644 --- a/pyUltroid/dB/_core.py +++ b/database/_core.py @@ -1,13 +1,13 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2020-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in # . -PLUGINS = [] -ADDONS = [] -HELP = {} -LOADED = {} LIST = {} -VC_HELP = {} +InlinePlugin = {} +InlinePaths = [] # Path to Inline Plugins +CMD_HELP = {} +ult_cache = {} +PluginChannel = {} \ No newline at end of file diff --git a/database/helpers/__init__.py b/database/helpers/__init__.py new file mode 100644 index 0000000000..b1560a9764 --- /dev/null +++ b/database/helpers/__init__.py @@ -0,0 +1,32 @@ +from random import choice + +from database import udB + +from .base import KeyManager + +DEVLIST = [ + 719195224, # @xditya + 1322549723, # @danish_00 + 1903729401, # @its_buddhhu + 1303895686, # @Sipak_OP + 611816596, # @Arnab431 +] + + +def get_random_color(): + return choice( + [ + "DarkCyan", + "DeepSkyBlue", + "DarkTurquoise", + "Cyan", + "LightSkyBlue", + "Turquoise", + "MediumVioletRed", + "Aquamarine", + "Lightcyan", + "Azure", + "Moccasin", + "PowderBlue", + ] + ) diff --git a/pyUltroid/dB/base.py b/database/helpers/base.py similarity index 76% rename from pyUltroid/dB/base.py rename to database/helpers/base.py index de26c1542d..3a426ceef0 100644 --- a/pyUltroid/dB/base.py +++ b/database/helpers/base.py @@ -1,4 +1,4 @@ -from .. import udB +from database import udB class KeyManager: @@ -9,18 +9,22 @@ def __init__(self, key, cast=None) -> None: def get(self): _data = udB.get_key(self._key) if self._cast and not isinstance(_data, self._cast): - return [_data] if self._cast == list else self._cast(_data) + if self._cast == list: + return [_data] + elif self._cast == dict and not _data: + return {} + return self._cast(_data) return _data or (self._cast() if callable(self._cast) else self._cast) - def get_child(self, key): - return self.get()[key] + def get_child(self, key, default=None): + return self.get().get(key, default) def count(self): return len(self.get()) def add(self, item): content = self.get() - if content == None and callable(type(item)): + if content is None and callable(type(item)): content = type(item)() if isinstance(content, dict) and isinstance(item, dict): content.update(item) diff --git a/database/initialize/.gitignore b/database/initialize/.gitignore new file mode 100644 index 0000000000..cb24e83756 --- /dev/null +++ b/database/initialize/.gitignore @@ -0,0 +1,2 @@ +mongodb.py +redisdb.py \ No newline at end of file diff --git a/database/initialize/base_db.py b/database/initialize/base_db.py new file mode 100644 index 0000000000..f73b2ff8a6 --- /dev/null +++ b/database/initialize/base_db.py @@ -0,0 +1,94 @@ +from ast import literal_eval +from collections import deque +from contextlib import suppress + +from core.config import Var + + +class BaseDatabase: + def __init__(self, *args, **kwargs): + self._cache = {} + self._handlers = {} + + def get(self, key): + ... + + def set(self, key, value): + ... + + def delete(self, key): + ... + + @property + def name(self): + return "database" + + @property + def usage(self): + return 0 + + def keys(self): + return [] + + def get_config(self, key): + return getattr(Var, key) or self.get_key(key) + + def get_key(self, key): + if key in self._cache: + return self._cache[key] + value = self._get_data(key) + self._cache.update({key: value}) + return value + + def re_cache(self): + self._cache.clear() + for key in self.keys(): + self._cache.update({key: self.get_key(key)}) + + def del_key(self, key): + if key in self._cache: + del self._cache[key] + self.delete(key) + with suppress(KeyError): + handler, arg, kwargs = self._handlers[key]["delete"] + handler(*arg, **kwargs) + return True + + def _get_data(self, key=None, data=None): + if key: + data = self.get(str(key)) + if data and isinstance(data, str): + with suppress(BaseException): + data = literal_eval(data) + return data + + def on(self, key, method, handler, *args, **kwargs): + if not self._handlers.get(key): + self._handlers[key] = {} + self._handlers[key][method] = (handler, args, kwargs) + + def set_key(self, key, value, only_cache=False): + value = self._get_data(data=value) + self._cache[key] = value + with suppress(KeyError): + handler, arg, kwargs = self._handlers[key]["change"] + handler(key, value, self.get_key(key), *arg, **kwargs) + if only_cache: + return + return self.set(str(key), str(value)) + + def rename(self, key1, key2): + if _ := self.get_key(key1): + self.del_key(key1) + self.set_key(key2, _) + return 0 + return 1 + + def cflush(self): + deque( + map( + lambda key: self.del_key(key), + filter(lambda x: not x.startswith("_"), self.keys()), + ), + 0, + ) diff --git a/database/initialize/get_db.py b/database/initialize/get_db.py new file mode 100644 index 0000000000..53c2a66fcd --- /dev/null +++ b/database/initialize/get_db.py @@ -0,0 +1,33 @@ +from core.config import Var, HOSTED_ON +from core.remote import rm +from core.setup import LOGS + + +def getDatabase(): + args, kwargs = (), {} + + if Var.REDIS_URI or Var.REDIS_HOST: + args = (Var.REDIS_URI or Var.REDISHOST, Var.REDISPORT) + kwargs = { + "password": Var.REDIS_PASSWORD or Var.REDISPASSWORD, + "decode_responses": True, + "socket_timeout": 5, + "retry_on_timeout": True, + } + key = "redisdb" + elif Var.MONGO_URI and not HOSTED_ON == "termux": + args, key = [Var.MONGO_URI], "mongodb" + elif Var.DATABASE_URL: + args, key = [Var.DATABASE_URI], "sql" + elif HOSTED_ON == "termux": + if Var.MONGO_URI: + LOGS.critical("MongoDB is not compatible with termux! kindly use another database.\ncontinuing with localdb.") + args, key = (), "local" + else: + LOGS.critical( + "No DB requirement fullfilled!\nPlease install redis, mongo or sql dependencies...\nTill then using local file as database." + ) + args, key = (), "local" + with rm.get(key, f"database/initialize/{key}.py", helper=True) as db: + if db: + return db.Database(*args, **kwargs) diff --git a/heroku.yml b/heroku.yml index 06f0fb7467..5c4139b20e 100644 --- a/heroku.yml +++ b/heroku.yml @@ -1,3 +1,3 @@ build: docker: - ultroid: Dockerfile + ultroid: Dockerfile \ No newline at end of file diff --git a/install-termux b/install-termux deleted file mode 100644 index 574ed1f12d..0000000000 --- a/install-termux +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in . - -if [ -d "resources" ] -then - echo "Current directory Identified.." -else - apt install git -y - git clone https://github.com/TeamUltroid/Ultroid - cd Ultroid -fi -bash resources/startup/termux.sh diff --git a/strings/README.md b/localization/README.md similarity index 100% rename from strings/README.md rename to localization/README.md diff --git a/localization/__init__.py b/localization/__init__.py new file mode 100644 index 0000000000..68eee7677f --- /dev/null +++ b/localization/__init__.py @@ -0,0 +1,101 @@ +import os, asyncio, time +from glob import glob +from typing import Any, Dict, List, Union + +from contextlib import suppress +from database import udB +from core import LOGS +from core.remote import rm +from utilities.tools import translate +from utilities.tools import safe_load + +_save_ = {} +languages = {} +PATH = "localization/strings/{}.yml" + +def get_lang(): + return udB.get_key("language") or "en" + +def load(lang): + if not os.path.exists("localization/strings"): + os.mkdir("localization/strings") + + rm.fetch_lang(lang) + + file = PATH.format(lang) + if not os.path.exists(file): + file = PATH.format("en") + code = file.split("/")[-1].split("\\")[-1][:-4] + try: + languages[code] = safe_load( + open(file, encoding="UTF-8"), + ) + except Exception as er: + LOGS.info(f"Error in {file[:-4]} language file") + LOGS.exception(er) + + +load(get_lang()) + + +def __get_string(key: str, lang=None) -> Any: + if not lang: + lang = get_lang() + with suppress(KeyError): + return languages[lang][key] + if not languages.get("en"): + load("en") + eng_ = languages.get("en", {}).get(key) + if not eng_: + return f"Warning: could not load any string with the key `{key}`" + try: + return translate_and_update(eng_, lang, key) + except TypeError: + pass + except Exception as er: + LOGS.exception(er) + return eng_ + +def get_string(key: str, *args, **kwargs): + stringResponse = __get_string(key) + if stringResponse and (args or kwargs): + try: + stringResponse = stringResponse.format(*args, **kwargs) + except (IndexError, KeyError) as er: + LOGS.exception(er) + stringResponse = __get_string(key, "en").format(*args, **kwargs) + return stringResponse + + +def translate_and_update(eng_, lang, key): + tr = translate(eng_, target=lang) + if eng_.count("{}") != tr.count("{}"): + tr = eng_ + if languages.get(lang) is None: + languages[lang] = {} + languages[lang][key] = tr + if not _save_.get(lang): + _save_[lang] = 0 + _save_[lang] += 1 + if _save_[lang] > 10: + save_dict_to_yaml(lang) + _save_[lang] = 0 + return tr + + +def save_dict_to_yaml(lang: str): + strings = languages[lang] + path = PATH.format(lang) + text = "" + for key, value in strings.items(): + value = value.replace('"', "'").replace("\n", "\\n") + text += f'{key}: "{value}"\n' + if not text: + return + with open(path, "w") as file: + file.write(text) + + +def get_help(key): + if doc := get_string(f"help_{key}"): + return get_string("cmda") + doc diff --git a/modules/README.md b/modules/README.md new file mode 100644 index 0000000000..b31436591b --- /dev/null +++ b/modules/README.md @@ -0,0 +1,2 @@ +# `plugins` +This directory contains the default plugins which come pre-installed on the first startup of Ultroid. \ No newline at end of file diff --git a/modules/__init__.py b/modules/__init__.py new file mode 100644 index 0000000000..53c55510da --- /dev/null +++ b/modules/__init__.py @@ -0,0 +1,51 @@ +# Ultroid - UserBot +# Copyright (C) 2020-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +import shutil +from random import choice + +from telethon import Button, events +from telethon.tl import functions, types # pylint:ignore + +from localization import get_string +from core import * +from core.decorators._decorators import ultroid_cmd +from utilities.misc import check_filename +from utilities.helper import * +from core.decorators import eor, eod +from core.decorators._assistant import in_pattern, asst_cmd, callback + +LOG_CHANNEL = udB.get_config("LOG_CHANNEL") + + +def inline_pic(get=False): + INLINE_PIC = udB.get_key("INLINE_PIC") + if (INLINE_PIC is None) or get: + # get default if required + return "https://graph.org/file/8cd1817eb8a9be2436b3b.jpg" + elif INLINE_PIC: + return INLINE_PIC + # is False, return None + +udB.on("LOAD_ALL", "delete", lambda: shutil.rmtree("modules/addons")) + +List = [] +Dict = {} +# Credentials variable for saving login credentials(Like Gdrive,OneDrive,etc. login credentials) in local +creds = {} + +# Chats, which needs to be ignore for some cases +# Considerably, there can be many +# Feel Free to Add Any other... + +NOSPAM_CHAT = [ + -1001361294038, # UltroidSupportChat + -1001387666944, # PyrogramChat + -1001109500936, # TelethonChat + -1001050982793, # Python + -1001256902287, # DurovsChat +] diff --git a/modules/assistant/__init__.py b/modules/assistant/__init__.py new file mode 100644 index 0000000000..07b7d134bb --- /dev/null +++ b/modules/assistant/__init__.py @@ -0,0 +1,47 @@ +from telethon.tl.types import InputWebDocument + +from core import asst +from core.decorators._assistant import asst_cmd, callback, in_pattern + +from .. import Button, inline_pic + +AST_PLUGINS = {} + +def get_back_button(name): + return [Button.inline("« Bᴀᴄᴋ", data=f"{name}")] + + +@in_pattern(owner=True, func=lambda x: not x.text) +async def inline_alive(o): + TLINK = inline_pic() or "https://graph.org/file/74d6259983e0642923fdb.jpg" + MSG = "• **Ultroid Userbot •**" + WEB0 = InputWebDocument( + "https://graph.org/file/acd4f5d61369f74c5e7a7.jpg", 0, "image/jpg", [] + ) + RES = [ + await o.builder.article( + type="photo", + text=MSG, + include_media=True, + buttons=[ + [ + Button.url( + "• Repo •", url="https://github.com/TeamUltroid/Ultroid" + ), + Button.url("• Support •", url="t.me/UltroidSupportChat"), + ], + ], + title="Ultroid Userbot", + description="Userbot | Telethon", + url=TLINK, + thumb=WEB0, + content=InputWebDocument(TLINK, 0, "image/jpg", []), + ) + ] + await o.answer( + RES, + private=True, + cache_time=300, + switch_pm="👥 ULTROID PORTAL", + switch_pm_param="start", + ) diff --git a/assistant/callbackstuffs.py b/modules/assistant/settings.py similarity index 98% rename from assistant/callbackstuffs.py rename to modules/assistant/settings.py index 316faa46a6..e3f0f9edb7 100644 --- a/assistant/callbackstuffs.py +++ b/modules/assistant/settings.py @@ -1,18 +1,19 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2021-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in # . import ast -import asyncio +import asyncio, os import re import sys import time from asyncio.exceptions import TimeoutError as AsyncTimeOut from os import execl, remove from random import choice +from localization import get_string from bs4 import BeautifulSoup as bs @@ -20,19 +21,25 @@ from pyUltroid.fns.gDrive import GDriveManager except ImportError: GDriveManager = None + +from core import HNDLR, LOGS, Var from telegraph import upload_file as upl from telethon import Button, events +from core.git import repo +from database import udB + +from core.loader import load from telethon.tl.types import MessageMediaWebPage from telethon.utils import get_peer_id -from pyUltroid.fns.helper import fast_download, progress -from pyUltroid.fns.tools import Carbon, async_searcher, get_paste, telegraph_client -from pyUltroid.startup.loader import Loader +from utilities.helper import fast_download, progress +from utilities.tools import Carbon, async_searcher, bash from . import * +from telethon.tl import types + # --------------------------------------------------------------------# -telegraph = telegraph_client() GDrive = GDriveManager() if GDriveManager else None # --------------------------------------------------------------------# @@ -48,6 +55,16 @@ def text_to_url(event): # --------------------------------------------------------------------# + + +async def setit(event, name, value): + try: + udB.set_key(name, value) + except BaseException as er: + LOGS.exception(er) + return await event.edit("`Something Went Wrong`") + + _buttons = { "otvars": { "text": "Other Variables to set for @TeamUltroid:", @@ -279,7 +296,6 @@ async def send(eve): @callback("updatenow", owner=True) async def update(eve): - repo = Repo() ac_br = repo.active_branch ups_rem = repo.remote("upstream") if heroku_api: @@ -313,7 +329,7 @@ async def update(eve): remote = repo.create_remote("heroku", heroku_git_url) try: remote.push(refspec=f"HEAD:refs/heads/{ac_br}", force=True) - except GitCommandError as error: + except Exception as error: await eve.edit(f"`Here is the error log:\n{error}`") repo.__del__() return @@ -329,10 +345,9 @@ async def update(eve): async def changes(okk): match = okk.data_match.group(1).decode("utf-8") await okk.answer(get_string("clst_3")) - repo = Repo.init() button = [[Button.inline("Update Now", data="updatenow")]] changelog, tl_chnglog = await gen_chlog( - repo, f"HEAD..upstream/{repo.active_branch}" + repo, f"HEAD..upstream/{repo.active_branch()}" ) cli = "\n\nClick the below button to update!" if not match: @@ -1315,4 +1330,4 @@ async def fdroid_dler(event): return await event.edit(f"**ERROR**: `{er}`", buttons=buttons) if msg and hasattr(msg, "media"): FD_MEDIA.update({uri: msg.media}) - os.remove(thumb) + os.remove(thumb) \ No newline at end of file diff --git a/assistant/start.py b/modules/assistant/start.py similarity index 61% rename from assistant/start.py rename to modules/assistant/start.py index f3f16b05b5..acd112a9e9 100644 --- a/assistant/start.py +++ b/modules/assistant/start.py @@ -1,54 +1,61 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2021-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in # . +import contextlib, re from datetime import datetime -from pytz import timezone as tz from telethon import Button, events from telethon.errors.rpcerrorlist import MessageDeleteForbiddenError from telethon.utils import get_display_name -from pyUltroid._misc import SUDO_M, owner_and_sudos -from pyUltroid.dB.base import KeyManager -from pyUltroid.fns.helper import inline_mention -from strings import get_string +from core import LOGS, ultroid_bot, HNDLR, rm +from core.decorators import fullsudos, owner_and_sudos +from core.version import version +from database import udB +from database.helpers import KeyManager +from localization import get_string +from utilities.helper import inline_mention from . import * -Owner_info_msg = udB.get_key("BOT_INFO_START") -custom_info = True -if Owner_info_msg is None: - custom_info = False - Owner_info_msg = f""" -**Owner** - {OWNER_NAME} -**OwnerID** - `{OWNER_ID}` + +async def get_stored_file(event, hash): + keym = KeyManager("FILE_STORE", cast=dict) + msg_id = keym.get_child(hash) + if not msg_id: + return + try: + msg = await asst.get_messages(udB.get_config("LOG_CHANNEL"), ids=msg_id) + except Exception as er: + LOGS.warning(f"FileStore, Error: {er}") + return + if not msg: + return await asst.send_message( + event.chat_id, "__Message was deleted by owner!__", reply_to=event.id + ) + await asst.send_message(event.chat_id, msg.text, file=msg.media, reply_to=event.id) + + +def get_start_message(): + Owner_info_msg = udB.get_key("BOT_INFO_START") + _custom = True + if Owner_info_msg is None: + _custom = False + Owner_info_msg = f""" +**Owner** - {ultroid_bot.full_name} +**OwnerID** - `{ultroid_bot.uid}` **Message Forwards** - {udB.get_key("PMBOT")} -**Ultroid [v{ultroid_version}](https://github.com/TeamUltroid/Ultroid), powered by @TeamUltroid** +**Ultroid [v{version}](https://github.com/TeamUltroid/Ultroid), powered by @TeamUltroid** """ + return Owner_info_msg, _custom -_settings = [ - [ - Button.inline("API Kᴇʏs", data="cbs_apiset"), - Button.inline("Pᴍ Bᴏᴛ", data="cbs_chatbot"), - ], - [ - Button.inline("Aʟɪᴠᴇ", data="cbs_alvcstm"), - Button.inline("PᴍPᴇʀᴍɪᴛ", data="cbs_ppmset"), - ], - [ - Button.inline("Fᴇᴀᴛᴜʀᴇs", data="cbs_otvars"), - Button.inline("VC Sᴏɴɢ Bᴏᴛ", data="cbs_vcb"), - ], - [Button.inline("« Bᴀᴄᴋ", data="mainmenu")], -] - _start = [ [ Button.inline("Lᴀɴɢᴜᴀɢᴇ 🌐", data="lang"), @@ -64,14 +71,15 @@ @callback("ownerinfo") async def own(event): - msg = Owner_info_msg.format( - mention=event.sender.mention, me=inline_mention(ultroid_bot.me) + message, custom = get_start_message() + msg = message.format( + mention=inline_mention(event.sender), me=inline_mention(ultroid_bot.me) ) - if custom_info: + if custom: msg += "\n\n• Powered by **@TeamUltroid**" await event.edit( msg, - buttons=[Button.inline("Close", data="closeit")], + buttons=Button.inline("Close", data="closeit"), link_preview=False, ) @@ -85,7 +93,7 @@ async def closet(lol): @asst_cmd(pattern="start( (.*)|$)", forwards=False, func=lambda x: not x.is_group) -async def ultroid(event): +async def ultroid_handler(event): args = event.pattern_match.group(1).strip() keym = KeyManager("BOT_USERS", cast=list) if not keym.contains(event.sender_id) and event.sender_id not in owner_and_sudos(): @@ -98,49 +106,54 @@ async def ultroid(event): buttons[0].append( Button.mention( "User", await event.client.get_input_entity(event.sender_id) - ) + ) # type: ignore ) await event.client.send_message( - udB.get_key("LOG_CHANNEL"), msg, buttons=buttons + udB.get_config("LOG_CHANNEL"), msg, buttons=buttons ) - if event.sender_id not in SUDO_M.fullsudos: + if event.sender_id not in fullsudos(): ok = "" me = inline_mention(ultroid_bot.me) mention = inline_mention(event.sender) if args and args != "set": await get_stored_file(event, args) - if not udB.get_key("STARTMSG"): + if _starts := udB.get_key("STARTMSG"): + msg = _starts + else: if udB.get_key("PMBOT"): ok = "You can contact my master using this bot!!\n\nSend your Message, I will Deliver it To Master." - await event.reply( - f"Hey there {mention}, this is Ultroid Assistant of {me}!\n\n{ok}", - file=udB.get_key("STARTMEDIA"), - buttons=[Button.inline("Info.", data="ownerinfo")] - if Owner_info_msg - else None, - ) - else: - await event.reply( - udB.get_key("STARTMSG").format(me=me, mention=mention), - file=udB.get_key("STARTMEDIA"), - buttons=[Button.inline("Info.", data="ownerinfo")] - if Owner_info_msg - else None, - ) + msg = f"Hey there {mention}, this is Ultroid Assistant of {me}!\n\n{ok}" + await event.reply( + msg.format(me=me, mention=mention), + file=udB.get_key("STARTMEDIA"), + buttons=( + Button.inline("Info.", data="ownerinfo") + if (get_start_message()[0]) + else None + ), + ) else: name = get_display_name(event.sender) if args == "set": await event.reply( "Choose from the below options -", - buttons=_settings, + buttons=_settings ) + return + elif args == "_manager": + + with contextlib.suppress(ImportError): + from modules.manager._help import START, get_buttons + + await event.reply(START, buttons=get_buttons()) elif args: await get_stored_file(event, args) - else: - await event.reply( - get_string("ast_3").format(name), - buttons=_start, - ) + return + + await event.reply( + get_string("ast_3").format(name), + buttons=_start, + ) @callback("itkkstyo", owner=True) @@ -152,7 +165,7 @@ async def ekekdhdb(e): @callback("mainmenu", owner=True, func=lambda x: not x.is_group) async def ultroid(event): await event.edit( - get_string("ast_3").format(OWNER_NAME), + get_string("ast_3", get_display_name(event.sender)), buttons=_start, ) @@ -172,7 +185,7 @@ async def bdcast(event): keym = KeyManager("BOT_USERS", cast=list) total = keym.count() await event.edit(f"• Broadcast to {total} users.") - async with event.client.conversation(OWNER_ID) as conv: + async with event.client.conversation(event.sender_id) as conv: await conv.send_message( "Enter your broadcast message.\nUse /cancel to stop the broadcast.", ) @@ -183,7 +196,7 @@ async def bdcast(event): fail = 0 await conv.send_message(f"Starting a broadcast to {total} users...") start = datetime.now() - for i in keym.get(): + for i in keym.get(): # type: ignore try: await asst.send_message(int(i), response) success += 1 @@ -200,6 +213,24 @@ async def bdcast(event): ) + +_settings = [ + [ + Button.inline("API Kᴇʏs", data="cbs_apiset"), + Button.inline("Pᴍ Bᴏᴛ", data="cbs_chatbot"), + ], + [ + Button.inline("Aʟɪᴠᴇ", data="cbs_alvcstm"), + Button.inline("PᴍPᴇʀᴍɪᴛ", data="cbs_ppmset"), + ], + [ + Button.inline("Fᴇᴀᴛᴜʀᴇs", data="cbs_otvars"), + Button.inline("VC Sᴏɴɢ Bᴏᴛ", data="cbs_vcb"), + ], + [Button.inline("« Bᴀᴄᴋ", data="mainmenu")], +] + + @callback("setter", owner=True) async def setting(event): await event.edit( @@ -208,9 +239,40 @@ async def setting(event): ) +@callback("lang", owner=True) +async def setlang(event): + languages = await rm.getLanguages() + tultd = [ + Button.inline( + f"{languages[ult]['name']} [{ult.lower()}]", + data=f"set_{ult}", + ) + for ult in languages + ] + buttons = list(zip(tultd[::2], tultd[1::2])) + if len(tultd) % 2 == 1: + buttons.append((tultd[-1],)) + buttons.append([Button.inline("« Back", data="mainmenu")]) + await event.edit(get_string("ast_4"), buttons=buttons) + + +@callback(re.compile(b"set_(.*)"), owner=True) +async def settt(event): + lang = event.data_match.group(1).decode("UTF-8") + languages = await rm.getLanguages() + udB.del_key("language") if lang == "en" else udB.set_key("language", lang) + await event.edit( + f"Your language has been set to {languages[lang]['name']} [{lang}].", + buttons=get_back_button("lang"), + ) + + @callback("tz", owner=True) async def timezone_(event): + from pytz import timezone + await event.delete() + pru = event.sender_id var = "TIMEZONE" name = "Timezone" @@ -227,8 +289,8 @@ async def timezone_(event): buttons=get_back_button("mainmenu"), ) try: - tz(themssg) - await setit(event, var, themssg) + timezone(themssg) + udB.set_key(var, themssg) await conv.send_message( f"{name} changed to {themssg}\n", buttons=get_back_button("mainmenu"), diff --git a/modules/basic/_help.py b/modules/basic/_help.py new file mode 100644 index 0000000000..a9aa7fd5c1 --- /dev/null +++ b/modules/basic/_help.py @@ -0,0 +1,320 @@ +import re +from contextlib import suppress +from inspect import getmembers + +from telethon import Button +from telethon.events import NewMessage +from core.decorators._assistant import callback, in_pattern +from core.loader import PLUGINS +from core.remote import rm +from database._core import CMD_HELP, LIST, InlinePlugin, InlinePaths + +from .. import HNDLR, LOGS, asst, get_string, inline_pic, udB, ultroid_bot, ultroid_cmd + +_cache = {} + + +def split_list(List, index): + new_ = [] + while List: + new_.extend([List[:index]]) + List = List[index:] + return new_ + + +def get_help_buttons(): + row_1 = [Button.inline(get_string("help_4"), data="uh_basic_")] + if filter_modules( + "addons" + ): # (udB.get_config("ADDONS") or udB.get_key("LOAD_ALL")) + row_1.append(Button.inline(get_string("help_5"), data="uh_addons_")) + row_2 = [] + if udB.get_config("VCBOT"): + row_2.append(Button.inline(get_string("help_6"), data="uh_vcbot_")) + if InlinePlugin: + row_2.append(Button.inline(get_string("help_7"), data="inlone")) + if all(len(row) == 1 for row in [row_1, row_2]): + row_1.append(row_2[0]) + row_2.clear() + Markup = [row_1] + if len(row_2) > 1: + Markup.append(row_2) + if udB.get_key("MANAGER"): + button = Button.inline("Manager", "mngbtn") + if len(row_1) == 1: + row_1.append(button) + elif len(row_2) == 1: + row_2.insert(0, button) + else: + Markup.append([button]) + settingButton = Button.url( + get_string("help_9"), + url=f"https://t.me/{asst.me.username}?start=set", + ) + if len(row_2) == 1: + row_2.append(settingButton) + else: + Markup.append([settingButton]) + Markup.append( + [Button.inline(get_string("help_10"), data="close")], + ) + if row_2 and row_2 not in Markup: + Markup.insert(1, row_2) + return Markup + + +def _sort(type, modl): + spli = modl.split(".") + if type in spli and not spli[-1].startswith("_") and modl not in InlinePaths: + return modl.split(".")[-1] + + +def filter_modules(type): + """Get names of loaded plugins""" + return sorted( + list(filter(lambda e: e, map(lambda modl: _sort(type, modl), PLUGINS))) + ) # type:ignore + + +def _get_module(name, type): + check = [type] if type else ["basic", "addons"] + for path in check: + with suppress(KeyError): + return PLUGINS[f"modules.{path}.{name}"] + + +def get_doc_from_module(name, type=""): + if mod := _get_module(name, type): + if not mod.__doc__: + return get_from_funcs(mod, name) + msg = f"Commands available in `{name}`-\n\n" + msg += mod.__doc__.format(i=HNDLR) + msg += "\n ©️ @TeamUltroid" + return msg + + +def get_from_funcs(mod, name): + handlers = list(map(lambda d: d[0], ultroid_bot.list_event_handlers())) + funcs = list( + filter( + lambda d: ( + d[0].endswith(("_func", "_cmd")) and d[1] in handlers and d[1].__doc__ + ), + getmembers(mod), + ) + ) + if not funcs: + return False + msg = f"Command available in `{name}` -" + for cmd in funcs: + msg += f"\n\n• {cmd[1].__doc__.format(*list(HNDLR*len(funcs)))}" + msg += "\n ©️ @TeamUltroid" + return msg + + +def get_doc(module, type=""): + msg = get_doc_from_module(module, type) + if msg: + return msg + _get_info = rm.get_info(module) + if _get_info and (cmds := _get_info.get("cmds")): + msg = f"✘ Commands Available in `{module}` -" + for cmd in cmds: + msg += f"\n\n• `{HNDLR}{cmd}`\n {cmds[cmd]}" + elif help := CMD_HELP.get(module): + msg = f"Plugin Name: {module}\n\n" + msg += help.format(i=HNDLR) + elif help := LIST.get(module): + msg = f"Plugin Name: {module}\n\n" + for cmd in help: + msg += f"- \n{HNDLR}{cmd}\n" + if msg: + msg += "\n ©️ @TeamUltroid" + return msg + + +@ultroid_cmd("help($| (.*))") +async def help_cmd(event: NewMessage.Event): + module = event.pattern_match.group(1).strip() + if not module: + if event.client._bot: + return await event.reply( + get_string("inline_4", ultroid_bot.full_name, len(PLUGINS)), + file=inline_pic(), + buttons=get_help_buttons(), + link_preview=False, + ) + result = await event.client.inline_query(asst.me.username, "ultd") + await result[0].click(event.chat_id, reply_to=event.id) + await event.delete() + return + if msg := get_doc(module): + return await event.eor(msg) + if not LIST.get(module): + return await event.eor(f"`{module}` is not a valid plugin.") + await event.eor(f"`{module} has no default help.`") + + +@in_pattern("ultd", owner=True) +async def inline_handler(event): + text = get_string("inline_4", ultroid_bot.full_name, len(PLUGINS)) + if inline_pic(): + result = await event.builder.photo( + file=inline_pic(), + link_preview=False, + text=text, + buttons=get_help_buttons(), + ) + else: + result = await event.builder.article( + title="Ultroid Help Menu", text=text, buttons=get_help_buttons() + ) + await event.answer([result], private=True, cache_time=300, gallery=True) + + +@callback(re.compile("uh_(.*)"), owner=True) +async def help_func(ult): + key, count = ult.data_match.group(1).decode("utf-8").split("_") + plugs = filter_modules(key) + if key == "vcbot" and not plugs: + return await ult.answer(get_string("help_12"), alert=True) + elif key == "addons" and not plugs: + return await ult.answer(get_string("help_13").format(HNDLR), alert=True) + if "|" in count: + _, count = count.split("|") + count = int(count) if count else 0 + _strings = { + "vcbot": "inline_6", + "addons": "inline_3" if udB.get_key("ADDONS") else "inline_2", + "basic": "inline_1", + } + text = get_string(_strings.get(key, ""), ultroid_bot.full_name, len(plugs)) + await ult.edit(text, buttons=page_num(count, key), link_preview=False) + + +@callback(data="open", owner=True) +async def opner(event): + await event.edit( + get_string("inline_4", + ultroid_bot.full_name, + len(PLUGINS), + ), + buttons=get_help_buttons(), + link_preview=False, + ) + + +@callback(data="close", owner=True) +async def on_plug_in_callback_query_handler(event): + await event.edit( + get_string("inline_5"), + buttons=Button.inline("Oᴘᴇɴ Aɢᴀɪɴ", data="open"), + ) + + +@callback(data="inlone", owner=True) +async def _(e): + if not InlinePlugin: + return await e.answer("You dont have Inline Plugins loaded!", alert=True) + _InButtons = [ + Button.switch_inline(key, query=InlinePlugin[key], same_peer=True) + for key in InlinePlugin + ] + InButtons = split_list(_InButtons, 2) + + button = InButtons.copy() + button.append( + [ + Button.inline("« Bᴀᴄᴋ", data="open"), + ], + ) + await e.edit(buttons=button, link_preview=False) + + +def _get_buttons(key, index): + rows = udB.get_key("HELP_ROWS") or 5 + cols = udB.get_key("HELP_COLUMNS") or 2 + emoji = udB.get_key("EMOJI_IN_HELP") or "✘" + loaded = filter_modules(key) + NList = [] + tl = rows * cols + for cindex, plugs in enumerate(split_list(loaded, tl)): + MList = [] + for ps in split_list(plugs, rows): + MList.extend( + Button.inline( + f"{emoji} {p} {emoji}", data=f"uplugin_{key}_{p}|{cindex}" + ) + for p in ps + ) + NList.append(split_list(MList, cols)) + if _cache.get("help") is None: + _cache["help"] = {} + _cache["help"][key] = NList + return NList + + +def page_num(index, key): + fl_ = _cache.get("help", {}).get(key) or _get_buttons(key, index) + try: + new_ = fl_[index].copy() + except IndexError: + new_ = fl_[0].copy() if fl_ else [] + index = 0 + if index == 0 and len(fl_) == 1: + new_.append([Button.inline("« Bᴀᴄᴋ »", data="open")]) + else: + new_.append( + [ + Button.inline( + "« Pʀᴇᴠɪᴏᴜs", + data=f"uh_{key}_{index-1}", + ), + Button.inline("« Bᴀᴄᴋ »", data="open"), + Button.inline( + "Nᴇxᴛ »", + data=f"uh_{key}_{index+1}", + ), + ] + ) + + return new_ + + +@callback(re.compile("uplugin_(.*)"), owner=True) +async def uptd_plugin(event): + key, file = event.data_match.group(1).decode("utf-8").split("_") + index = None + if "|" in file: + file, index = file.split("|") + help_ = get_doc(file, key) + if not help_: + help_ = f"{file} has no Detailed Help!" + help_ += "\n© @TeamUltroid" + buttons = [] + if inline_pic(): + data = f"sndplug_{key}_{file}" + if index is not None: + data += f"|{index}" + buttons.append( + [ + Button.inline( + "« Sᴇɴᴅ Pʟᴜɢɪɴ »", + data=data, + ) + ] + ) + data = f"uh_{key}_" + if index is not None: + data += f"|{index}" + buttons.append( + [ + Button.inline("« Bᴀᴄᴋ", data=data), + ] + ) + try: + await event.edit(help_, buttons=buttons) + except Exception as er: + LOGS.exception(er) + help = f"Do `{HNDLR}help {key}` to get list of commands." + await event.edit(help, buttons=buttons) diff --git a/modules/basic/_inline.py b/modules/basic/_inline.py new file mode 100644 index 0000000000..0c6e928317 --- /dev/null +++ b/modules/basic/_inline.py @@ -0,0 +1,99 @@ +from .. import in_pattern, LOGS, asst, Message +from telethon.utils import resolve_bot_file_id +from telethon.tl.types import InputWebDocument + +# TODO: UPDATE + +STUFF = {} + +async def add_media_handler(e): + n = e.pattern_match.group(1).strip() + builder = e.builder + if not (n and n.isdigit()): + return + ok = STUFF.get(int(n)) + txt = ok.get("msg") + pic = ok.get("media") + btn = ok.get("button") + if not (pic or txt): + txt = "Hey!" + if pic: + try: + include_media = True + mime_type, _pic = None, None + cont, results = None, None + try: + ext = str(pic).split(".")[-1].lower() + except BaseException: + ext = None + if ext in ["img", "jpg", "png"]: + _type = "photo" + mime_type = "image/jpg" + elif ext in ["mp4", "mkv", "gif"]: + mime_type = "video/mp4" + _type = "gif" + else: + try: + if "telethon.tl.types" in str(type(pic)): + _pic = pic + else: + _pic = resolve_bot_file_id(pic) + except BaseException: + pass + if _pic: + results = [ + await builder.document( + _pic, + title="Ultroid Op", + text=txt, + description="@TeamUltroid", + buttons=btn, + link_preview=False, + ) + ] + else: + _type = "article" + include_media = False + if not results: + if include_media: + cont = InputWebDocument(pic, 0, mime_type, []) + results = [ + await builder.article( + title="Ultroid Op", + type=_type, + text=txt, + description="@TeamUltroid", + include_media=include_media, + buttons=btn, + thumb=cont, + content=cont, + link_preview=False, + ) + ] + return await e.answer(results) + except Exception as er: + LOGS.exception(er) + result = [ + await builder.article("Ultroid Op", text=txt, link_preview=False, buttons=btn) + ] + await e.answer(result) + + + +async def something(e, msg, media, button, reply=True, chat=None): + if e.client._bot: + return await e.reply(msg, file=media, buttons=button) + num = len(STUFF) + 1 + STUFF.update({num: {"msg": msg, "media": media, "button": button}}) + try: + asst.add_handler(add_media_handler, in_pattern("sin(.*)", owner=True)) + res = await e.client.inline_query(asst.me.username, f"sin{num}") + return await res[0].click( + chat or e.chat_id, + reply_to=bool(isinstance(e, Message) and reply), + hide_via=True, + silent=True, + ) + + except Exception as er: + LOGS.exception(er) \ No newline at end of file diff --git a/plugins/_userlogs.py b/modules/basic/_taglogger.py similarity index 63% rename from plugins/_userlogs.py rename to modules/basic/_taglogger.py index 61491445d5..bad9166901 100644 --- a/plugins/_userlogs.py +++ b/modules/basic/_taglogger.py @@ -1,39 +1,26 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2021-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in # . +""" +- TagLogger +""" + import os -import re -from telethon.errors.rpcerrorlist import ( - ChannelPrivateError, - ChatWriteForbiddenError, - MediaCaptionTooLongError, - MediaEmptyError, - MessageTooLongError, - PeerIdInvalidError, - UserNotParticipantError, -) -from telethon.tl.types import MessageEntityMention, MessageEntityMentionName, User +from telethon import events +from telethon.errors import (ChatWriteForbiddenError, MediaCaptionTooLongError, + MediaEmptyError, MessageTooLongError, + PeerIdInvalidError, UserNotParticipantError) +from telethon.tl.custom import Button +from telethon.tl.types import (MessageEntityMention, MessageEntityMentionName, + User) from telethon.utils import get_display_name -from pyUltroid.dB.botchat_db import tag_add, who_tag - -from . import ( - LOG_CHANNEL, - LOGS, - Button, - asst, - callback, - events, - get_string, - inline_mention, - udB, - ultroid_bot, -) +from .. import LOGS, asst, get_string, udB, ultroid_bot CACHE_SPAM = {} TAG_EDITS = {} @@ -42,15 +29,14 @@ @ultroid_bot.on( events.NewMessage( incoming=True, - func=lambda e: (e.mentioned), + func=lambda e: (e.mentioned) and udB.get_key("TAG_LOG"), ), ) async def all_messages_catcher(e): x = await e.get_sender() if isinstance(x, User) and (x.bot or x.verified): return - if not udB.get_key("TAG_LOG"): - return + LOG_CHANNEL = udB.get_config("LOG_CHANNEL") NEEDTOLOG = udB.get_key("TAG_LOG") buttons = await parse_buttons(e) try: @@ -59,7 +45,7 @@ async def all_messages_catcher(e): TAG_EDITS[e.chat_id].update({e.id: {"id": sent.id, "msg": e}}) else: TAG_EDITS.update({e.chat_id: {e.id: {"id": sent.id, "msg": e}}}) - tag_add(sent.id, e.chat_id, e.id) +# tag_add(sent.id, e.chat_id, e.id) except MediaEmptyError as er: LOGS.debug(f"handling {er}.") try: @@ -68,8 +54,9 @@ async def all_messages_catcher(e): if TAG_EDITS.get(e.chat_id): TAG_EDITS[e.chat_id].update({e.id: {"id": sent.id, "msg": e}}) else: - TAG_EDITS.update({e.chat_id: {e.id: {"id": sent.id, "msg": e}}}) - tag_add(sent.id, e.chat_id, e.id) + TAG_EDITS.update( + {e.chat_id: {e.id: {"id": sent.id, "msg": e}}}) +# tag_add(sent.id, e.chat_id, e.id) except Exception as me: if not isinstance(me, (PeerIdInvalidError, ValueError)): LOGS.exception(me) @@ -80,9 +67,11 @@ async def all_messages_catcher(e): NEEDTOLOG, e.message.text, file=media, buttons=buttons ) if TAG_EDITS.get(e.chat_id): - TAG_EDITS[e.chat_id].update({e.id: {"id": sent.id, "msg": e}}) + TAG_EDITS[e.chat_id].update( + {e.id: {"id": sent.id, "msg": e}}) else: - TAG_EDITS.update({e.chat_id: {e.id: {"id": sent.id, "msg": e}}}) + TAG_EDITS.update( + {e.chat_id: {e.id: {"id": sent.id, "msg": e}}}) return os.remove(media) except Exception as er: LOGS.exception(er) @@ -144,9 +133,11 @@ async def upd_edits(event): except Exception as er: return LOGS.exception(er) if TAG_EDITS.get(event.chat_id): - TAG_EDITS[event.chat_id].update({event.id: {"id": sent.id}}) + TAG_EDITS[event.chat_id].update( + {event.id: {"id": sent.id}}) else: - TAG_EDITS.update({event.chat_id: {event.id: {"id": sent.id}}}) + TAG_EDITS.update( + {event.chat_id: {event.id: {"id": sent.id}}}) return d_ = TAG_EDITS[event.chat_id] if not d_.get(event.id): @@ -184,90 +175,23 @@ async def upd_edits(event): except Exception as er: LOGS.exception(er) - @ultroid_bot.on( - events.NewMessage( - outgoing=True, - chats=[udB.get_key("TAG_LOG")], - func=lambda e: e.reply_to, - ) - ) - async def idk(e): - id = e.reply_to_msg_id - chat, msg = who_tag(id) - if chat and msg: - try: - await ultroid_bot.send_message(chat, e.message, reply_to=msg) - except BaseException as er: - LOGS.exception(er) - - -# log for assistant/user joins/add - - -async def when_added_or_joined(event): - user = await event.get_user() - chat = await event.get_chat() - if not (user and user.is_self): - return - if getattr(chat, "username", None): - chat = f"[{chat.title}](https://t.me/{chat.username}/{event.action_message.id})" - else: - chat = f"[{chat.title}](https://t.me/c/{chat.id}/{event.action_message.id})" - key = "bot" if event.client._bot else "user" - buttons = Button.inline( - get_string("userlogs_3"), data=f"leave_ch_{event.chat_id}|{key}" - ) - if event.user_added: - tmp = event.added_by - text = f"#ADD_LOG\n\n{inline_mention(tmp)} just added {inline_mention(user)} to {chat}." - elif event.from_request: - text = f"#APPROVAL_LOG\n\n{inline_mention(user)} just got Chat Join Approval to {chat}." - else: - text = f"#JOIN_LOG\n\n{inline_mention(user)} just joined {chat}." - await asst.send_message(udB.get_key("LOG_CHANNEL"), text, buttons=buttons) - - -asst.add_event_handler( - when_added_or_joined, events.ChatAction(func=lambda x: x.user_added) -) -ultroid_bot.add_event_handler( - when_added_or_joined, - events.ChatAction(func=lambda x: x.user_added or x.user_joined), -) -_client = {"bot": asst, "user": ultroid_bot} - - -@callback( - re.compile( - "leave_ch_(.*)", - ), - from_users=[ultroid_bot.uid], -) -async def leave_ch_at(event): - cht = event.data_match.group(1).decode("UTF-8") - ch_id, client = cht.split("|") - try: - client = _client[client] - except KeyError: - return - try: - name = (await client.get_entity(int(ch_id))).title - await client.delete_dialog(int(ch_id)) - except UserNotParticipantError: - pass - except ChannelPrivateError: - return await event.edit( - "`[CANT_ACCESS_CHAT]` `Maybe already left or got banned.`" - ) - except Exception as er: - LOGS.exception(er) - return await event.answer(str(er)) - await event.edit(get_string("userlogs_5").format(name)) - - -@callback("do_nothing") -async def _(event): - await event.answer() + # TODO: decide whether to keep + + # @ultroid_bot.on( + # events.NewMessage( + # outgoing=True, + # chats=[udB.get_key("TAG_LOG")], + # func=lambda e: e.reply_to, + # ) + # ) + # async def idk(e): + # id = e.reply_to_msg_id + # chat, msg = who_tag(id) + # if chat and msg: + # try: + # await ultroid_bot.send_message(chat, e.message, reply_to=msg) + # except BaseException as er: + # LOGS.exception(er) async def parse_buttons(event): diff --git a/plugins/admintools.py b/modules/basic/admins.py similarity index 80% rename from plugins/admintools.py rename to modules/basic/admins.py index bb4c6d0e71..25d9851997 100644 --- a/plugins/admintools.py +++ b/modules/basic/admins.py @@ -1,28 +1,29 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2021-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in # . -from . import get_help +from localization import get_help -__doc__ = get_help("help_admintools") - -import asyncio +__doc__ = get_help("admins") from telethon.errors import BadRequestError -from telethon.errors.rpcerrorlist import ChatNotModifiedError, UserIdInvalidError +from telethon.errors.rpcerrorlist import UserIdInvalidError from telethon.tl.functions.channels import EditAdminRequest, GetFullChannelRequest -from telethon.tl.functions.messages import GetFullChatRequest, SetHistoryTTLRequest +from telethon.tl.functions.messages import GetFullChatRequest from telethon.tl.types import InputMessagesFilterPinned from telethon.utils import get_display_name -from pyUltroid.dB import DEVLIST -from pyUltroid.fns.admins import ban_time -from pyUltroid.fns.info import get_uinfo +from core import HNDLR +from core.decorators._wrappers import eod, eor +from database.helpers import DEVLIST +from utilities.admins import ban_time +from utilities.helper import inline_mention +from utilities.admins import get_uinfo -from . import HNDLR, LOGS, eod, eor, get_string, inline_mention, types, ultroid_cmd +from .. import LOGS, get_string, types, ultroid_cmd @ultroid_cmd( @@ -35,7 +36,8 @@ async def prmte(ult): xx = await ult.eor(get_string("com_1")) user, rank = await get_uinfo(ult) - rank = rank or "Admin" + if not rank: + rank = "Admin" FullRight = False if not user: return await xx.edit(get_string("pro_1")) @@ -189,11 +191,14 @@ async def kck(ult): except Exception as e: LOGS.exception(e) return - text = get_string("kick_4").format( - inline_mention(user), inline_mention(await ult.get_sender()), ult.chat.title + text = get_string( + "kick_4", + inline_mention(user), + inline_mention(await ult.get_sender()), + ult.chat.title, ) if reason: - text += get_string("ban_5").format(reason) + text += get_string("ban_5", reason) await xx.edit(text) @@ -240,7 +245,7 @@ async def tkicki(e): @ultroid_cmd(pattern="pin$", manager=True, require="pin_messages", fullsudo=True) async def pin(msg): if not msg.is_reply: - return await eor(msg, get_string("pin_1")) + return await msg.eor(get_string("pin_1")) me = await msg.get_reply_message() if me.is_private: text = "`Pinned.`" @@ -249,10 +254,10 @@ async def pin(msg): try: await msg.client.pin_message(msg.chat_id, me.id, notify=False) except BadRequestError: - return await eor(msg, get_string("adm_2")) + return await msg.eor(get_string("adm_2")) except Exception as e: - return await eor(msg, f"**ERROR:**`{e}`") - await eor(msg, text) + return await msg.eor(f"**ERROR:**`{e}`") + await msg.eor(text) @ultroid_cmd( @@ -278,34 +283,6 @@ async def unp(ult): await xx.edit("`Unpinned!`") -@ultroid_cmd( - pattern="tpin( (.*)|$)", - admins_only=True, - manager=True, - require="pin_messages", - fullsudo=True, -) -async def pin_message(ult): - match = ult.pattern_match.group(1).strip() - if not ult.is_reply: - return await ult.eor("`Reply to message..`", time=6) - if not match: - return await ult.eor("`Please provide time..`", time=8) - msg = await ult.eor(get_string("com_1")) - msg_id = ult.reply_to_msg_id - try: - time = ban_time(match) - await ult.client.pin_message(ult.chat_id, msg_id) - await msg.eor(f"`pinned for time` `{time}`", time=8) - except Exception as er: - return await msg.edit(str(er)) - await asyncio.sleep(time) - try: - await ult.client.unpin_message(ult.chat_id, msg_id) - except Exception as er: - LOGS.exception(er) - - @ultroid_cmd(pattern="purge( (.*)|$)", manager=True, require="delete_messages") async def fastpurger(purg): match = purg.pattern_match.group(1).strip() @@ -327,9 +304,9 @@ async def fastpurger(purg): ): await msg.delete() p += 0 - return await eor(purg, f"Purged {p} Messages! ", time=5) + return await purg.eor(f"Purged {p} Messages! ", time=5) if not purg.reply_to_msg_id: - return await eor(purg, get_string("purge_1"), time=10) + return await purg.eor(get_string("purge_1"), time=10) try: await purg.client.delete_messages( purg.chat_id, list(range(purg.reply_to_msg_id, purg.id)) @@ -348,7 +325,7 @@ async def fastpurgerme(purg): try: nnt = int(num) except BaseException: - await eor(purg, get_string("com_3"), time=5) + await purg.eor(get_string("com_3"), time=5) return mp = 0 async for mm in purg.client.iter_messages( @@ -356,11 +333,10 @@ async def fastpurgerme(purg): ): await mm.delete() mp += 1 - await eor(purg, f"Purged {mp} Messages!", time=5) + await purg.eor(f"Purged {mp} Messages!", time=5) return elif not purg.reply_to_msg_id: - return await eod( - purg, + return await purg.eor( "`Reply to a message to purge from or use it like ``purgeme `", time=10, ) @@ -445,28 +421,3 @@ async def get_all_pinned(event): return await eor(x, get_string("listpin_1"), time=5) await x.edit(m + a, parse_mode="html") - - -@ultroid_cmd( - pattern="autodelete( (.*)|$)", - admins_only=True, -) -async def autodelte(ult): - match = ult.pattern_match.group(1).strip() - if not match or match not in ["24h", "7d", "1m", "off"]: - return await ult.eor("`Please Use in Proper Format..`", time=5) - if match == "24h": - tt = 3600 * 24 - elif match == "7d": - tt = 3600 * 24 * 7 - elif match == "1m": - tt = 3600 * 24 * 31 - else: - tt = 0 - try: - await ult.client(SetHistoryTTLRequest(ult.chat_id, period=tt)) - except ChatNotModifiedError: - return await ult.eor( - f"Auto Delete Setting is Already same to `{match}`", time=5 - ) - await ult.eor(f"Auto Delete Status Changed to `{match}` !") diff --git a/plugins/afk.py b/modules/basic/afk.py similarity index 78% rename from plugins/afk.py rename to modules/basic/afk.py index 30028387e8..35e405b955 100644 --- a/plugins/afk.py +++ b/modules/basic/afk.py @@ -1,34 +1,14 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_afk") - - import asyncio +import contextlib +from datetime import datetime as dt from telegraph import upload_file as uf from telethon import events -from pyUltroid.dB.afk_db import add_afk, del_afk, is_afk -from pyUltroid.dB.base import KeyManager - -from . import ( - LOG_CHANNEL, - NOSPAM_CHAT, - Redis, - asst, - get_string, - mediainfo, - udB, - ultroid_bot, - ultroid_cmd, -) +from database.helpers.base import KeyManager + +from .. import (LOG_CHANNEL, NOSPAM_CHAT, asst, get_string, mediainfo, udB, + ultroid_bot, ultroid_cmd) old_afk_msg = [] @@ -94,28 +74,28 @@ async def set_afk(event): async def remove_afk(event): - if event.is_private and udB.get_key("PMSETTING") and not is_approved(event.chat_id): + if event.is_private and udB.get_key( + "PMSETTING") and not is_approved(event.chat_id): return elif "afk" in event.text.lower(): return elif event.chat_id in NOSPAM_CHAT: return if is_afk(): - _, _, _, afk_time = is_afk() + _, _, _, afk_time = is_afk() # type: ignore del_afk() off = await event.reply(get_string("afk_1").format(afk_time)) await asst.send_message(LOG_CHANNEL, get_string("afk_2").format(afk_time)) for x in old_afk_msg: - try: + with contextlib.suppress(BaseException): await x.delete() - except BaseException: - pass await asyncio.sleep(10) await off.delete() async def on_afk(event): - if event.is_private and Redis("PMSETTING") and not is_approved(event.chat_id): + if event.is_private and udB.get_key( + "PMSETTING") and not is_approved(event.chat_id): return elif "afk" in event.text.lower(): return @@ -147,10 +127,8 @@ async def on_afk(event): else: msg1 = await event.reply(get_string("afk_4").format(afk_time)) for x in old_afk_msg: - try: + with contextlib.suppress(BaseException): await x.delete() - except BaseException: - pass old_afk_msg.append(msg1) if msg2: old_afk_msg.append(msg2) @@ -164,3 +142,29 @@ async def on_afk(event): incoming=True, func=lambda e: bool(e.mentioned or e.is_private) ), ) + +# DATABASE FUNCTIONS # + + +def get_stuff(): + return udB.get_key("AFK_DB") or [] + + +def add_afk(msg, media_type, media): + time = dt.now().strftime("%b %d %Y %I:%M:%S%p") + udB.set_key("AFK_DB", [msg, media_type, media, time]) + return + +def get_stuff(): + return udB.get_key("AFK_DB") or [] + +def is_afk(): + if afk := get_stuff(): + start_time = dt.strptime(afk[3], "%b %d %Y %I:%M:%S%p") + afk_since = str(dt.now().replace(microsecond=0) - start_time) + return afk[0], afk[1], afk[2], afk_since + return False + + +def del_afk(): + return udB.del_key("AFK_DB") diff --git a/modules/basic/bot.py b/modules/basic/bot.py new file mode 100644 index 0000000000..566ed73b13 --- /dev/null +++ b/modules/basic/bot.py @@ -0,0 +1,130 @@ +# Ultroid - UserBot +# Copyright (C) 2021-2022 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +import os +import sys +import time +from core import start_time +from core.remote import rm +from core.git import repo +from database.helpers import get_random_color +from utilities.helper import bash, check_update, get_origin_upstream, time_formatter +from utilities.tools import Carbon + +from .. import HOSTED_ON, get_string, udB, ultroid_cmd + + +@ultroid_cmd(pattern="ping$") +async def ping_func(event): + """Show response time of bot.""" + start = time.time() + x = await event.eor("Pong !") + end = round((time.time() - start) * 1000) + uptime = time_formatter((time.time() - start_time) * 1000) + await x.edit(get_string("ping").format(end, uptime)) + + +@ultroid_cmd(pattern="logs( (.*)|$)") +async def logs_func(event): + """Get logs of the bot. + + Args: + open - Send last 4000 characters of logs in a message. + carbon - Send last 2500 characters of logs in carbon image. + graph - Upload Logs on Telegraph""" + arg = event.pattern_match.group(1).strip() + if not arg: + arg = udB.get_key("_LOG_MODE") + elif arg != "file": + udB.set_key("_LOG_MODE", arg) + + file_path = "ultroid.log" + if arg == "open": + with open(file_path, "r") as file: + content = file.read()[-4000:] + return await event.eor(f"`{content}`") + elif arg == "carbon": + event = await event.eor(get_string("com_1")) + with open(file_path, "r") as f: + code = f.read()[-2500:] + file = await Carbon( + file_name="ultroid-logs", + code=code, + backgroundColor=get_random_color(), + ) + if isinstance(file, dict): + return await event.eor(f"`{file}`") + return await event.eor("**Ultroid Logs.**", file=file) + elif arg == "graph": + with rm.get("graph", helper=True, dispose=True) as mod: + client = mod.get_client() + with open(file_path, "r") as file: + title = "Ultroid Logs" + page = client.create_page(title=title, content=[file.read()]) + return await event.eor(f'[Ultroid Logs]({page["url"]})', link_preview=True) + await event.eor(file=file_path) + + +@ultroid_cmd(pattern="restart$") +async def restart_func(event): + """Restart the bot.""" + event = await event.eor("Restarting...") + self_ = "bot" if event.client.me.bot else "user" + udB.set_key("_RESTART", [event.chat_id, event.id, self_]) + if HOSTED_ON == "heroku": + from core.heroku import restart + + msg = restart() + if msg is True: + return + await event.eor(msg) + os.execl(sys.executable, sys.executable, "-m", "core") + + +@ultroid_cmd(pattern="update( (.*)|$)") +async def update_func(e): + """Update the bot to it's latest release. + + Args: + fast/soft - Fetch latest release without updating changed dependencies.""" + xx = await e.eor(get_string("upd_1")) + cmd = e.pattern_match.group(1).strip() + if cmd and ("fast" in cmd or "soft" in cmd): + await bash("git pull -f") + # call_back() + await xx.edit(get_string("upd_7")) + os.execl(sys.executable, sys.executable, "-m", "core") + # return + remote_url = repo.get_remote_url() + if remote_url.endswith(".git"): + remote_url = remote_url[:-4] + m = check_update() + if not m: + branch = repo.active_branch() + return await xx.edit( + f'Your BOT is up-to-date with [{branch}]', + parse_mode="html", + link_preview=False, + ) + org, up = get_origin_upstream() + msg = await xx.eor( + f'[ChangeLogs]\nUpdating...', + parse_mode="html", + link_preview=False, + ) + await update(msg) + + +async def update(eve): + if HOSTED_ON == "heroku": + from core.heroku import update + + return await update(eve) + else: + # call_back() + await bash(f"git pull && {sys.executable} -m pip install -r requirements.txt") + os.execl(sys.executable, sys.executable, "-m", "core") diff --git a/plugins/chats.py b/modules/basic/chats.py similarity index 78% rename from plugins/chats.py rename to modules/basic/chats.py index f484cfa16e..7a50073214 100644 --- a/plugins/chats.py +++ b/modules/basic/chats.py @@ -1,14 +1,15 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2021-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in # . -from . import get_help -__doc__ = get_help("help_chats") +from localization import get_help +__doc__ = get_help("chats") +import contextlib from telethon.errors import ChatAdminRequiredError as no_admin from telethon.tl.functions.channels import ( CreateChannelRequest, @@ -17,6 +18,7 @@ GetFullChannelRequest, UpdateUsernameRequest, ) +from utilities.converter import create_chat_photo from telethon.tl.functions.messages import ( CreateChatRequest, ExportChatInviteRequest, @@ -33,13 +35,10 @@ UserStatusRecently, ) -from . import HNDLR, LOGS, asst, con, get_string, mediainfo, os, types, udB, ultroid_cmd +from .. import HNDLR, LOGS, asst, get_string, mediainfo, os, types, udB, ultroid_cmd -@ultroid_cmd( - pattern="delchat", - groups_only=True, -) +@ultroid_cmd(pattern="delchat", groups_only=True, fullsudo=True) async def _(e): xx = await e.eor(get_string("com_1")) try: @@ -54,7 +53,7 @@ async def _(e): except no_admin: return await xx.eor(get_string("chats_2"), time=10) await e.client.send_message( - int(udB.get_key("LOG_CHANNEL")), get_string("chats_6").format(e.chat_id) + udB.get_config("LOG_CHANNEL"), get_string("chats_6").format(e.chat_id) ) @@ -63,7 +62,7 @@ async def _(e): groups_only=True, manager=True, ) -async def _(e): +async def getlink_func(e): reply = await e.get_reply_message() match = e.pattern_match.group(1).strip() if reply and not isinstance(reply.sender, User): @@ -206,21 +205,20 @@ async def _(ult): else: return await ult.eor("Reply to a Photo or Video..") mediain = mediainfo(reply.media) - if "animated" in mediain: - replfile = await con.convert(replfile, convert_to="mp4") - else: - replfile = await con.convert( - replfile, outname="chatphoto", allowed_formats=["jpg", "png", "mp4"] - ) - file = await ult.client.upload_file(replfile) + cnfile = await create_chat_photo(replfile) + + file = await ult.client.upload_file(cnfile) try: - if "pic" not in mediain: - file = types.InputChatUploadedPhoto(video=file) + isPhoto = cnfile.endswith(("jpg", "png")) + file = types.InputChatUploadedPhoto(file=file if isPhoto else None, video=None if isPhoto else file) await ult.client(EditPhotoRequest(chat, file)) await ult.eor("`Group Photo has Successfully Changed !`", time=5) except Exception as ex: + LOGS.exception(ex) await ult.eor(f"Error occured.\n`{str(ex)}`", time=5) os.remove(replfile) + with contextlib.suppress(FileNotFoundError): + os.remove(cnfile) @ultroid_cmd( @@ -228,9 +226,7 @@ async def _(ult): ) async def _(ult): match = ult.pattern_match.group(1).strip() - chat = ult.chat_id - if not ult.client._bot and match: - chat = match + chat = match if not ult.client._bot and match else ult.chat_id try: await ult.client(EditPhotoRequest(chat, types.InputChatPhotoEmpty())) text = "`Removed Chat Photo..`" @@ -265,91 +261,76 @@ async def _(event): admins_only=True, fullsudo=True, ) -async def _(event): +async def rmusers_cmd(event): + # TODO: Simplify and UPDATE xx = await event.eor(get_string("com_1")) input_str = event.pattern_match.group(1).strip() - p, a, b, c, d, m, n, y, w, o, q, r = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + p, b, c, d, m, n, y, w, o, q, r = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, async for i in event.client.iter_participants(event.chat_id): + kick_req = event.client.kick_participant(event.chat_id, i) + p += 1 # Total Count if isinstance(i.status, UserStatusEmpty): if "empty" in input_str: - try: - await event.client.kick_participant(event.chat_id, i) + with contextlib.suppress(BaseException): + await kick_req c += 1 - except BaseException: - pass else: y += 1 - if isinstance(i.status, UserStatusLastMonth): + elif isinstance(i.status, UserStatusLastMonth): if "month" in input_str: - try: - await event.client.kick_participant(event.chat_id, i) + with contextlib.suppress(BaseException): + await kick_req c += 1 - except BaseException: - pass else: m += 1 - if isinstance(i.status, UserStatusLastWeek): + elif isinstance(i.status, UserStatusLastWeek): if "week" in input_str: - try: - await event.client.kick_participant(event.chat_id, i) + with contextlib.suppress(BaseException): + await kick_req c += 1 - except BaseException: - pass else: w += 1 - if isinstance(i.status, UserStatusOffline): + elif isinstance(i.status, UserStatusOffline): if "offline" in input_str: - try: - await event.client.kick_participant(event.chat_id, i) + with contextlib.suppress(BaseException): + await kick_req c += 1 - except BaseException: - pass else: o += 1 - if isinstance(i.status, UserStatusOnline): + elif isinstance(i.status, UserStatusOnline): if "online" in input_str: - try: - await event.client.kick_participant(event.chat_id, i) + with contextlib.suppress(BaseException): + await kick_req c += 1 - except BaseException: - pass else: q += 1 - if isinstance(i.status, UserStatusRecently): + elif isinstance(i.status, UserStatusRecently): if "recently" in input_str: - try: - await event.client.kick_participant(event.chat_id, i) + with contextlib.suppress(BaseException): + await kick_req c += 1 - except BaseException: - pass else: r += 1 if i.bot: if "bot" in input_str: - try: - await event.client.kick_participant(event.chat_id, i) + with contextlib.suppress(BaseException): + await kick_req c += 1 - except BaseException: - pass else: b += 1 elif i.deleted: if "deleted" in input_str: - try: - await event.client.kick_participant(event.chat_id, i) + with contextlib.suppress(BaseException): + await kick_req c += 1 - except BaseException: - pass else: d += 1 elif i.status is None: if "none" in input_str: - try: - await event.client.kick_participant(event.chat_id, i) + with contextlib.suppress(BaseException): + await kick_req c += 1 - except BaseException: - pass else: n += 1 if input_str: diff --git a/plugins/database.py b/modules/basic/database.py similarity index 52% rename from plugins/database.py rename to modules/basic/database.py index 8e071e4572..6e740ea013 100644 --- a/plugins/database.py +++ b/modules/basic/database.py @@ -1,19 +1,40 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2021-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in # . +""" +• **DataBase Commands, do not use if you don't know what it is.** -from . import get_help +• `{i}setdb key | value` + Set Value in Database. + e.g : + `{i}setdb hi there` + `{i}setdb hi there | ultroid here` + `{i}setdb --extend variable value` or `{i}setdb -e variable value` to add the value to the exiting values in db. -__doc__ = get_help("help_database") +• `{i}getdb key` + Get Key from DB. +• `{i}deldb key` + Delete Key from DB. + +• `{i}rendb old keyname | new keyname` + Update Key Name +""" import re -from . import Redis, eor, get_string, udB, ultroid_cmd +from .. import eor, get_string, udB, ultroid_cmd, LOGS + + +async def _get_cmd(x, varname): + val = udB.get_key(varname) + if val is not None: + return await x.eor(f"**Key** - `{varname}`\n**Value**: `{val}`") + await x.eor( "No such key!", time=5) @ultroid_cmd(pattern="setdb( (.*)|$)", fullsudo=True) @@ -26,33 +47,44 @@ async def _(ult): data = match.split(delim, maxsplit=1) if data[0] in ["--extend", "-e"]: data = data[1].split(maxsplit=1) - data[1] = f"{str(udB.get_key(data[0]))} {data[1]}" + val = udB.get_key(data[0]) + if isinstance(val, str): + data[1] = f"{val} {data[1]}" + elif isinstance(val, list): + val.append(data[1]) + data[1] = val udB.set_key(data[0], data[1]) await ult.eor( f"**DB Key Value Pair Updated\nKey :** `{data[0]}`\n**Value :** `{data[1]}`" ) - except BaseException: + except BaseException as er: + LOGS.exception(er) await ult.eor(get_string("com_7")) -@ultroid_cmd(pattern="deldb( (.*)|$)", fullsudo=True) +@ultroid_cmd(pattern="(del|get)db( (.*)|$)", fullsudo=True) async def _(ult): - key = ult.pattern_match.group(1).strip() + _cmd = ult.pattern_match.group(1) + key = ult.pattern_match.group(2).strip() if not key: return await ult.eor("Give me a key name to delete!", time=5) + if _cmd == "get": + return await _get_cmd(ult, key) _ = key.split(maxsplit=1) try: if _[0] == "-m": for key in _[1].split(): k = udB.del_key(key) key = _[1] + k = 0 else: k = udB.del_key(key) if k == 0: return await ult.eor("`No Such Key.`") await ult.eor(f"`Successfully deleted key {key}`") - except BaseException: + except BaseException as er: + LOGS.exception(er) await ult.eor(get_string("com_7")) @@ -63,7 +95,7 @@ async def _(ult): return await ult.eor("`Provide Keys name to rename..`") delim = " " if re.search("[|]", match) is None else " | " data = match.split(delim) - if Redis(data[0]): + if udB.get_key(data[0]): try: udB.rename(data[0], data[1]) await eor( @@ -73,5 +105,17 @@ async def _(ult): except BaseException: await ult.eor(get_string("com_7")) - else: - await ult.eor("Key not found") + return + await ult.eor("`No such key`") + + +@ultroid_cmd(pattern="getkeys", fullsudo=True) +async def getkeys_cmd(ult): + keys = sorted(udB.keys()) + msg = "".join( + f"• `{i}`" + "\n" + for i in keys + if not i.isdigit() and not i.startswith(("-", "_", "GBAN_REASON_")) + ) + + await ult.eor(f"**List of DB Keys :**\n{msg}") diff --git a/plugins/devtools.py b/modules/basic/devtools.py similarity index 64% rename from plugins/devtools.py rename to modules/basic/devtools.py index bc3cd5a734..3470c37489 100644 --- a/plugins/devtools.py +++ b/modules/basic/devtools.py @@ -1,16 +1,18 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2021-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in +# Please read the GNU Affero General Public License in # . -from . import get_help +from localization import get_help -__doc__ = get_help("help_devtools") +__doc__ = get_help("devtools") +import contextlib import inspect import sys +import time import traceback from io import BytesIO, StringIO from os import remove @@ -18,27 +20,25 @@ from telethon.utils import get_display_name -from pyUltroid import _ignore_eval +from utilities.tools import is_url_ok -from . import * - -# Used for Formatting Eval Code, if installed try: import black except ImportError: black = None -from random import choice -try: - 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 telethon.tl import functions +from os import remove +from telethon.tl import functions +from telethon.tl.types import MessageEntityPre +from core.remote import rm +from database.helpers import get_random_color +from utilities.misc import json_parser +from utilities.tools import Carbon, safe_load +from telethon.errors import RPCError +from .. import * + +Tasks = {} fn = functions @@ -52,9 +52,11 @@ async def _(e): return await xx.edit(f"Error: `{y}`") with open("neo.txt", "r", encoding="utf-8") as neo: p = (neo.read()).replace("\n\n", "") - haa = await Carbon(code=p, file_name="neofetch", backgroundColor=choice(ATRA_COL)) + haa = await Carbon(code=p, file_name="neofetch", backgroundColor=get_random_color()) if isinstance(haa, dict): - await xx.edit(f"`{haa}`") + LOGS.exception(haa) + x, y = await bash("neofetch --stdout") + await xx.edit(f"`{x}`") else: await e.reply(file=haa) await xx.delete() @@ -62,14 +64,18 @@ async def _(e): @ultroid_cmd(pattern="bash", fullsudo=True, only_devs=True) -async def _(event): - carb, rayso, yamlf = None, None, False +async def bash_func(event): + carb, rayso, yamlf = ( + udB.get_key("CARBON_ON_BASH"), + udB.get_key("RAYSO_ON_BASH"), + False, + ) try: cmd = event.text.split(" ", maxsplit=1)[1] if cmd.split()[0] in ["-c", "--carbon"]: cmd = cmd.split(maxsplit=1)[1] carb = True - if cmd.split()[0] in ["-r", "--rayso"]: + elif cmd.split()[0] in ["-r", "--rayso"]: cmd = cmd.split(maxsplit=1)[1] rayso = True except IndexError: @@ -82,7 +88,7 @@ async def _(event): if stderr: err = f"**• ERROR:** \n`{stderr}`\n\n" if stdout: - if (carb or udB.get_key("CARBON_ON_BASH")) and ( + if (carb or rayso) and ( event.is_private or event.chat.admin_rights or event.chat.creator @@ -90,38 +96,18 @@ async def _(event): ): li = await Carbon( code=stdout, + rayso=rayso, file_name="bash", download=True, - backgroundColor=choice(ATRA_COL), + backgroundColor=get_random_color(), ) if isinstance(li, dict): await xx.edit( f"Unknown Response from Carbon: `{li}`\n\nstdout`:{stdout}`\nstderr: `{stderr}`" ) return - url = f"https://graph.org{uf(li)[-1]}" - OUT = f"[\xad]({url}){OUT}" - out = "**• OUTPUT:**" - remove(li) - elif (rayso or udB.get_key("RAYSO_ON_BASH")) and ( - event.is_private - or event.chat.admin_rights - or event.chat.creator - or event.chat.default_banned_rights.embed_links - ): - li = await Carbon( - code=stdout, - file_name="bash", - download=True, - backgroundColor=choice(ATRA_COL), - rayso=True, - ) - if isinstance(li, dict): - await xx.edit( - f"Unknown Response from Carbon: `{li}`\n\nstdout`:{stdout}`\nstderr: `{stderr}`" - ) - return - url = f"https://graph.org{uf(li)[-1]}" + with rm.get("graph", helper=True, dispose=True) as mod: + url = mod.upload_file(li) OUT = f"[\xad]({url}){OUT}" out = "**• OUTPUT:**" remove(li) @@ -153,15 +139,14 @@ async def _(event): event.chat_id, out_file, force_document=True, - thumb=ULTConfig.thumb, allow_cache=False, caption=f"`{cmd}`" if len(cmd) < 998 else None, reply_to=reply_to_id, ) await xx.delete() - else: - await xx.edit(OUT, link_preview=not yamlf) + return + await xx.edit(OUT, link_preview=not yamlf) pp = pprint # ignore: pylint @@ -176,15 +161,14 @@ def _parse_eval(value=None): if not value: return value if hasattr(value, "stringify"): - try: + with contextlib.suppress(TypeError): return value.stringify() - except TypeError: - pass - elif isinstance(value, dict): - try: + if black and isinstance(value, (dict, list)): + with contextlib.suppress(Exception): + return black.format_str(str(value), mode=black.Mode()) + if isinstance(value, dict): + with contextlib.suppress(BaseException): return json_parser(value, indent=1) - except BaseException: - pass elif isinstance(value, list): newlist = "[" for index, child in enumerate(value): @@ -197,7 +181,7 @@ def _parse_eval(value=None): @ultroid_cmd(pattern="eval", fullsudo=True, only_devs=True) -async def _(event): +async def eval_func(event): try: cmd = event.text.split(maxsplit=1)[1] except IndexError: @@ -226,21 +210,28 @@ async def get_(): mode = "g-args" if mode: cmd = await get_() + if ( + event.entities + and len(event.entities) == 1 + and isinstance(event.entities[0], MessageEntityPre) + ): + entity = event.entities[0] + offset = entity.offset + 3 + cmd = event.text[offset : offset + entity.length] if not cmd: return - if not mode == "silent" and not xx: + if mode != "silent" and not xx: xx = await event.eor(get_string("com_1")) if black: - try: + with contextlib.suppress(BaseException): cmd = black.format_str(cmd, mode=black.Mode()) - except BaseException: - # Consider it as Code Error, and move on to be shown ahead. - pass reply_to_id = event.reply_to_msg_id or event - if any(item in cmd for item in KEEP_SAFE().All) and ( - not (event.out or event.sender_id == ultroid_bot.uid) + if ( + any(item in cmd for item in KEEP_SAFE().All) + and not event.out + and event.sender_id != ultroid_bot.uid ): - warning = await event.forward_to(udB.get_key("LOG_CHANNEL")) + warning = await event.forward_to(udB.get_config("LOG_CHANNEL")) await warning.reply( f"Malicious Activities suspected by {inline_mention(await event.get_sender())}" ) @@ -252,10 +243,27 @@ async def get_(): old_stdout = sys.stdout redirected_output = sys.stdout = StringIO() redirected_error = sys.stderr = StringIO() - stdout, stderr, exc, timeg = None, None, None, None + stdout, stderr, exc = None, None, None tima = time.time() try: + # value = await aexec(cmd, event) + # TODO: Eval can be cancelled + # task = asyncio.create_task(aexec(cmd, event)) + # task = asyncio.current_task() + # try: + # task_id = int(list(Tasks.keys())[0]) + # except IndexError: + # task_id = 0 + # task_id += 1 + # task_id = str(task_id) + # Tasks[task_id] = task + # task.add_done_callback(lambda _: Tasks.pop(task_id)) + # await asyncio.wait([task]) + # value = task.result() value = await aexec(cmd, event) + except RPCError as er: + value = None + exc = f"{er.__class__.__name__}: {er}" except Exception: value = None exc = traceback.format_exc() @@ -267,21 +275,22 @@ async def get_(): if value: try: if mode == "gsource": - exc = inspect.getsource(value) + stdout = inspect.getsource(value) elif mode == "g-args": args = inspect.signature(value).parameters.values() name = "" if hasattr(value, "__name__"): name = value.__name__ - exc = f"**{name}**\n\n" + "\n ".join([str(arg) for arg in args]) + stdout = f"**{name}**\n\n" + "\n ".join([str(arg) for arg in args]) except Exception: exc = traceback.format_exc() - evaluation = exc or stderr or stdout or _parse_eval(value) or get_string("instu_4") + err = exc or stderr + evaluation = stdout or _parse_eval(value) if mode == "silent": - if exc: + if err: msg = f"• EVAL ERROR\n\n• CHAT: {get_display_name(event.chat)} [{event.chat_id}]" - msg += f"\n\n∆ CODE:\n{cmd}\n\n∆ ERROR:\n{exc}" - log_chat = udB.get_key("LOG_CHANNEL") + msg += f"\n\n∆ CODE:\n{cmd}\n\n∆ ERROR:\n{err}" + log_chat = udB.get_config("LOG_CHANNEL") if len(msg) > 4000: with BytesIO(msg.encode()) as out_file: out_file.name = "Eval-Error.txt" @@ -292,21 +301,27 @@ async def get_(): return tmt = tima * 1000 timef = time_formatter(tmt) - timeform = timef if not timef == "0s" else f"{tmt:.3f}ms" - final_output = "__►__ **EVAL** (__in {}__)\n```{}``` \n\n __►__ **OUTPUT**: \n```{}``` \n".format( + timeform = timef if timef != "0s" else f"{tmt:.3f}ms" + if isinstance(evaluation, str) and not (await is_url_ok(evaluation, True)): + evaluation = f"```{evaluation}```" + final_output = "__►__ **EVAL** (__in {}__)\n```{}``` ".format( timeform, cmd, - evaluation, ) + if err: + final_output += f"\n\n __►__ **ERROR**: \n`{err}`" + elif not evaluation: + evaluation = get_string("instu_4") + if evaluation: + final_output += f"\n\n __►__ **OUTPUT**: \n{evaluation}" if len(final_output) > 4096: - final_output = evaluation - with BytesIO(str.encode(final_output)) as out_file: + final_output = str(evaluation) + with BytesIO(final_output.encode()) as out_file: out_file.name = "eval.txt" await event.client.send_file( event.chat_id, out_file, force_document=True, - thumb=ULTConfig.thumb, allow_cache=False, caption=f"```{cmd}```" if len(cmd) < 998 else None, reply_to=reply_to_id, @@ -336,51 +351,3 @@ async def aexec(code, event): ) return await locals()["__aexec"](event, event.client) - - -DUMMY_CPP = """#include -using namespace std; - -int main(){ -!code -} -""" - - -@ultroid_cmd(pattern="cpp", only_devs=True) -async def doie(e): - match = e.text.split(" ", maxsplit=1) - try: - match = match[1] - except IndexError: - return await e.eor(get_string("devs_3")) - msg = await e.eor(get_string("com_1")) - if "main(" not in match: - new_m = "".join(" " * 4 + i + "\n" for i in match.split("\n")) - match = DUMMY_CPP.replace("!code", new_m) - open("cpp-ultroid.cpp", "w").write(match) - m = await bash("g++ -o CppUltroid cpp-ultroid.cpp") - o_cpp = f"• **Eval-Cpp**\n`{match}`" - if m[1]: - o_cpp += f"\n\n**• Error :**\n`{m[1]}`" - if len(o_cpp) > 3000: - os.remove("cpp-ultroid.cpp") - if os.path.exists("CppUltroid"): - os.remove("CppUltroid") - with BytesIO(str.encode(o_cpp)) as out_file: - out_file.name = "error.txt" - return await msg.reply(f"`{match}`", file=out_file) - return await eor(msg, o_cpp) - m = await bash("./CppUltroid") - if m[0] != "": - o_cpp += f"\n\n**• Output :**\n`{m[0]}`" - if m[1]: - o_cpp += f"\n\n**• Error :**\n`{m[1]}`" - if len(o_cpp) > 3000: - with BytesIO(str.encode(o_cpp)) as out_file: - out_file.name = "eval.txt" - await msg.reply(f"`{match}`", file=out_file) - else: - await eor(msg, o_cpp) - os.remove("CppUltroid") - os.remove("cpp-ultroid.cpp") diff --git a/modules/basic/downloadupload.py b/modules/basic/downloadupload.py new file mode 100644 index 0000000000..22384ae484 --- /dev/null +++ b/modules/basic/downloadupload.py @@ -0,0 +1,201 @@ +# Ultroid - UserBot +# Copyright (C) 2021-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +from localization import get_help + +__doc__ = get_help("downloadupload") + +import asyncio +import contextlib +import glob +import os +import time +from datetime import datetime as dt + +from requests.exceptions import InvalidSchema, InvalidURL +from telethon.errors.rpcerrorlist import MessageNotModifiedError + +from utilities.helper import time_formatter +from utilities.tools import get_chat_and_msgid, is_url_ok, set_attributes + +from .. import ( + LOGS, + eor, + fast_download, + get_all_files, + get_string, + progress, + ultroid_cmd, +) + + +async def download_from_url(event): + """Download from url""" + queryed = link = event.pattern_match.group(1).strip() + msg = await event.eor(get_string("udl_4")) + if not queryed: + return await eor(msg, get_string("udl_5"), time=5) + try: + link, filename = queryed.split(" | ")[:2] + except ValueError: + filename = None + s_time = time.time() + try: + filename, d = await fast_download( + link, + filename, + progress_callback=lambda d, t: asyncio.get_event_loop().create_task( + progress( + d, + t, + msg, + s_time, + f"Downloading from {link}", + ) + ), + ) + except (InvalidURL, InvalidSchema): + return await msg.eor("`Invalid URL provided :(`", time=5) + await msg.eor(f"`{filename}` `downloaded in {time_formatter(d*1000)}.`") + + +@ultroid_cmd( + pattern="dl( (.*)|$)", +) +async def dl_cmd(event): + query = event.pattern_match.group(1).strip() + silent = "--silent" in query + if silent: + query = query.replace("--silent", "").strip() + if query and "t.me/" in query: + chat, msg = get_chat_and_msgid(query) + if not (chat and msg): + return await event.eor(get_string("gms_1")) + ok = await event.client.get_messages(chat, ids=msg) + elif event.reply_to_msg_id: + ok = await event.get_reply_message() + elif query and await is_url_ok(query): + return await download_from_url(event) + else: + return await event.eor(get_string("cvt_3"), time=8) + xx = await event.eor(get_string("com_1")) + if not (ok and ok.media): + return await xx.eor(get_string("udl_1"), time=5) + s = dt.now() + k = time.time() + if hasattr(ok.media, "document"): + file = ok.media.document + try: + result = await event.client.fast_downloader( + file, + show_progress=not silent, + event=xx, + ) + + except MessageNotModifiedError as err: + return await xx.edit(str(err)) + file_name = result[0].name + else: + d = "resources/downloads/" + file_name = await event.client.download_media( + ok, + d, + progress_callback=lambda d, t: asyncio.get_event_loop().create_task( + progress( + d, + t, + xx, + k, + get_string("com_5"), + ), + ), + ) + e = dt.now() + t = time_formatter(((e - s).seconds) * 1000) + await xx.eor(get_string("udl_2").format(file_name, t)) + + +async def _upload_file( + event, files, stream, msg, delete, thumb, force_doc, progress=True +): + attributes = None + if stream: + try: + attributes = await set_attributes(files) + except KeyError as er: + LOGS.exception(er) + with contextlib.suppress(ValueError, IsADirectoryError): + file, _ = await event.client.fast_uploader( + files, show_progress=progress, event=msg, to_delete=delete + ) + await event.client.send_file( + event.chat_id, + file=file, + supports_streaming=stream, + force_document=force_doc, + attributes=attributes, + thumb=thumb, + caption=f"`Uploaded` `{files}` `in {time_formatter(_*1000)}`", + reply_to=event.reply_to_msg_id or event, + ) + + +@ultroid_cmd( + pattern="ul( (.*)|$)", +) +async def ul_func(event): + msg = await event.eor(get_string("com_1")) + query = event.pattern_match.group(1).strip() + if not query: + return await event.eor("`Error: Provide Path.`") + stream, force_doc, delete, thumb, parallel = (False, True, False, None, None) + if "--stream" in query: + stream = True + force_doc = False + delete = "--delete" in query + parallel = "--parallel" in query + if "--no-thumb" in query: + thumb = False + arguments = ["--stream", "--delete", "--no-thumb", "--parallel"] + if any(item in query for item in arguments): + query = ( + query.replace("--stream", "") + .replace("--delete", "") + .replace("--no-thumb", "") + .replace("--parallel", "") + .strip() + ) + if not event.out and query == ".env": + return await event.eor("`Error: Permission denied.`") + if query.endswith("/"): + query += "*" + results = glob.glob(query) + if not results and os.path.exists(query): + results = [query] + if not results: + # Consider it as previewable link + try: + await event.reply(file=query) + return await event.try_delete() + except Exception as er: + LOGS.exception(er) + return await msg.eor(get_string("ls1")) + for result in results: + files = get_all_files(result) if os.path.isdir(result) else [result] + if parallel: + await asyncio.gather( + *[ + _upload_file( + event, file, stream, msg, delete, thumb, force_doc, False + ) + for file in files + ] + ) + else: + for file in files: + await _upload_file(event, file, stream, msg, delete, thumb, force_doc) + await msg.try_delete() diff --git a/modules/basic/mediainfo.py b/modules/basic/mediainfo.py new file mode 100644 index 0000000000..16d8da455b --- /dev/null +++ b/modules/basic/mediainfo.py @@ -0,0 +1,90 @@ +# Ultroid - UserBot +# Copyright (C) 2021-2022 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +""" +✘ Commands Available - + +• `{i}mediainfo reply-media/file-path/url` + Get mediainfo of file +""" + +import contextlib +import os, json + +from core import rm +from utilities.tools import generate_screenshot, is_url_ok + +from .. import LOGS, bash, get_string, mediainfo, ultroid_cmd + + +@ultroid_cmd(pattern="mediainfo( (.*)|$)") +async def mediainfo_func(event): + r = await event.get_reply_message() + match = event.pattern_match.group(1).strip() + extra = "" + if r and r.media: + xx = mediainfo(r) + murl = json.dumps(json.loads(r.media.to_json()), indent=2) + with rm.get("graph", helper=True, dispose=True) as mod: + url = await mod.make_html_telegraph("Mediainfo", f"
    {murl}
    ") + extra = f"**[{xx}]({url})**\n\n" + e = await event.eor(f"{extra}`Loading More...`", link_preview=False) + + if hasattr(r.media, "document"): + dl = await event.client.fast_downloader( + r.document, + filename=r.file.name, + show_progress=True, + event=event, + message=f"{extra}`Loading More...`", + ) + + naam = dl[0].name + else: + naam = await r.download_media() + elif match and ( + os.path.isfile(match) + or (match.startswith("https://") and (await is_url_ok(match))) + ): + naam, xx = match, "file" + else: + return await event.eor(get_string("cvt_3"), time=5) + out, er = await bash(f"mediainfo '{naam}'") + makehtml = "" + thumb = None + if naam.endswith((".mkv", ".mp4", ".avi")): + thumb = await generate_screenshot(naam) + is_img = naam.endswith((".jpg", ".png")) + if is_img: + thumb = naam + if thumb and os.path.exists(thumb): + with rm.get("graph", helper=True, dispose=True) as mod: + med = mod.upload_file(thumb) + + makehtml += f"
    " + elif is_img: + makehtml += f"
    " + for line in out.split("\n"): + line = line.strip() + if not line: + makehtml += "
    " + elif ":" not in line: + makehtml += f"

    {line}

    " + else: + makehtml += f"

    {line}

    " + try: + with rm.get("graph", helper=True, dispose=True) as mod: + urll = await mod.make_html_telegraph("Mediainfo", makehtml) + except Exception: + LOGS.exception(er) + return + await event.eor(f"{extra}[{get_string('mdi_1')}]({urll})", link_preview=False) + if not match: + os.remove(naam) + if thumb and thumb != naam: + with contextlib.suppress(FileNotFoundError): + os.remove(thumb) diff --git a/plugins/pmpermit.py b/modules/basic/pmpermit.py similarity index 94% rename from plugins/pmpermit.py rename to modules/basic/pmpermit.py index 8749f6ee02..b0e772f725 100644 --- a/plugins/pmpermit.py +++ b/modules/basic/pmpermit.py @@ -1,5 +1,5 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2021-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in @@ -42,27 +42,30 @@ import re from os import remove -from pyUltroid.dB import DEVLIST +from database.helpers import DEVLIST try: from tabulate import tabulate except ImportError: tabulate = None +from core import HNDLR from telethon import events from telethon.errors import MessageNotModifiedError -from telethon.tl.functions.contacts import ( - BlockRequest, - GetBlockedRequest, - UnblockRequest, -) +from telethon.tl import types +from telethon.tl.custom import Button +from telethon.tl.functions.contacts import (BlockRequest, GetBlockedRequest, + UnblockRequest) from telethon.tl.functions.messages import ReportSpamRequest from telethon.utils import get_display_name, resolve_bot_file_id -from pyUltroid.dB.base import KeyManager +from database.helpers.base import KeyManager -from . import * +from .. import (LOGS, asst, callback, get_string, in_pattern, inline_mention, + udB, ultroid_bot, ultroid_cmd) # ========================= CONSTANTS ============================= +OWNER_NAME = ultroid_bot.full_name +OWNER_ID = ultroid_bot.me.id COUNT_PM = {} LASTMSG = {} @@ -156,7 +159,7 @@ async def _(e): func=lambda e: e.is_private, ), ) - async def permitpm(event): + async def permitpmhandler(event): user = await event.get_sender() if user.bot or user.is_self or user.verified or Logm.contains(user.id): return @@ -169,7 +172,8 @@ async def permitpm(event): @ultroid_bot.on( events.NewMessage( outgoing=True, - func=lambda e: e.is_private and e.out and not e.text.startswith(HNDLR), + func=lambda e: e.is_private and e.out and not e.text.startswith( + HNDLR), ), ) async def autoappr(e): @@ -206,16 +210,19 @@ async def autoappr(e): func=lambda e: e.is_private and e.sender_id not in DEVLIST and not e.out - and not e.sender.bot - and not e.sender.is_self - and not e.sender.verified, + # and not e.sender.bot + # and not e.sender.is_self + # and not e.sender.verified, ) ) async def permitpm(event): - inline_pm = Redis("INLINE_PM") or False + sender = await event.get_sender() + if (sender.bot or sender.verified): + return + inline_pm = udB.get_key("INLINE_PM") or False user = event.sender if not keym.contains(user.id) and event.text != UND: - if Redis("MOVE_ARCHIVE"): + if udB.get_key("MOVE_ARCHIVE"): try: await ultroid_bot.edit_folder(user.id, folder=1) except BaseException as er: @@ -408,8 +415,7 @@ async def approvepm(apprvpm): else: return await apprvpm.edit(NO_REPLY) if user.id in DEVLIST: - return await eor( - apprvpm, + return await apprvpm.eor( "Lol, He is my Developer\nHe is auto Approved", ) if not keym.contains(user.id): @@ -419,8 +425,7 @@ async def approvepm(apprvpm): await apprvpm.client.edit_folder(user.id, folder=0) except BaseException: pass - await eod( - apprvpm, + await apprvpm.eor( f"{inline_mention(user, html=True)} approved to PM!", parse_mode="html", ) @@ -430,7 +435,8 @@ async def approvepm(apprvpm): _not_approved[user.id], f"#APPROVED\n\n{inline_mention(user, html=True)} [{user.id}] was approved to PM you!", buttons=[ - Button.inline("Disapprove PM", data=f"disapprove_{user.id}"), + Button.inline( + "Disapprove PM", data=f"disapprove_{user.id}"), Button.inline("Block", data=f"block_{user.id}"), ], parse_mode="html", @@ -440,7 +446,8 @@ async def approvepm(apprvpm): udB.get_key("LOG_CHANNEL"), f"#APPROVED\n\n{inline_mention(user, html=True)} [{user.id}] was approved to PM you!", buttons=[ - Button.inline("Disapprove PM", data=f"disapprove_{user.id}"), + Button.inline( + "Disapprove PM", data=f"disapprove_{user.id}"), Button.inline("Block", data=f"block_{user.id}"), ], parse_mode="html", @@ -459,14 +466,12 @@ async def disapprovepm(e): else: return await e.edit(NO_REPLY) if user.id in DEVLIST: - return await eor( - e, + return await e.eor( "`Lol, He is my Developer\nHe Can't Be DisApproved.`", ) if keym.contains(user.id): keym.remove(user.id) - await eod( - e, + await e.eor( f"{inline_mention(user, html=True)} Disapproved to PM!", parse_mode="html", ) @@ -494,8 +499,7 @@ async def disapprovepm(e): except MessageNotModifiedError: pass else: - await eod( - e, + await e.eor( f"{inline_mention(user, html=True)} was never approved!", parse_mode="html", ) @@ -514,7 +518,7 @@ async def blockpm(block): elif block.is_private: user = block.chat_id else: - return await eor(block, NO_REPLY, time=10) + return await block.eor(NO_REPLY, time=10) await block.client(BlockRequest(user)) aname = await block.client.get_entity(user) @@ -556,20 +560,20 @@ async def unblockpm(event): u_s = await event.client(GetBlockedRequest(0, 0)) count = len(u_s.users) if not count: - return await eor(msg, "__You have not blocked Anyone...__") + return await msg.eor("__You have not blocked Anyone...__") for user in u_s.users: await asyncio.sleep(1) await event.client(UnblockRequest(user.id)) # GetBlockedRequest return 20 users at most. if count < 20: - return await eor(msg, f"__Unblocked {count} Users!__") + return await msg.eor(f"__Unblocked {count} Users!__") while u_s.users: u_s = await event.client(GetBlockedRequest(0, 0)) for user in u_s.users: await asyncio.sleep(3) await event.client(UnblockRequest(user.id)) count += len(u_s.users) - return await eor(msg, f"__Unblocked {count} users.__") + return await msg.eor(f"__Unblocked {count} users.__") try: user = await event.client.parse_id(match) @@ -622,7 +626,12 @@ async def list_approved(event): with open("approved_pms.txt", "w") as list_appr: if tabulate: list_appr.write( - tabulate(users, headers=["UserName", "UserID"], showindex="always") + tabulate( + users, + headers=[ + "UserName", + "UserID"], + showindex="always") ) else: text = "".join(f"[{user[-1]}] - {user[0]}" for user in users) diff --git a/modules/basic/stickers.py b/modules/basic/stickers.py new file mode 100644 index 0000000000..8e44b8d711 --- /dev/null +++ b/modules/basic/stickers.py @@ -0,0 +1,186 @@ +# Ultroid - UserBot +# Copyright (C) 2021-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +import contextlib +import random, string +from secrets import token_hex + +from telethon import errors +from telethon.errors.rpcerrorlist import StickersetInvalidError +from telethon.tl.functions.messages import GetStickerSetRequest as GetSticker +from telethon.tl.functions.messages import UploadMediaRequest +from telethon.tl.functions.stickers import AddStickerToSetRequest as AddSticker +from telethon.tl.functions.stickers import CreateStickerSetRequest +from telethon.tl.types import ( + DocumentAttributeSticker, + InputPeerSelf, + InputStickerSetEmpty, +) +from telethon.errors import StickersetInvalidError, PackShortNameInvalidError +from telethon.tl.types import InputStickerSetItem as SetItem +from telethon.tl.types import InputStickerSetShortName, User +from telethon.utils import get_display_name, get_extension, get_input_document + +from core.remote import rm +from utilities.converter import resize_photo_sticker + +from .. import LOGS, asst, fetch, udB, ultroid_cmd, get_string + + +async def packExists(packId): + source = await fetch(f"https://t.me/addstickers/{packId}") + return ( + not b"""
    + A Telegram user has created the Sticker Set. +
    """ + in source + ) + + +async def GetUniquePackName(): + packName = f"{random.choice(string.ascii_lowercase)}{token_hex(random.randint(4, 8))}_by_{asst.me.username}" + return await GetUniquePackName() if await packExists(packName) else packName + + +# TODO: simplify if possible + + +def getName(sender, packType: str): + title = f"{get_display_name(sender)}'s Kang Pack" + if packType != "static": + title += f" ({packType.capitalize()})" + return title + + +async def AddToNewPack(packType, file, emoji, sender_id, title: str): + sn = await GetUniquePackName() + return await asst( + CreateStickerSetRequest( + user_id=sender_id, + title=title, + short_name=sn, + stickers=[SetItem(file, emoji=emoji)], + software="@TeamUltroid", + ) + ) + + +@ultroid_cmd(pattern="kang", manager=True) +async def kang_func(ult): + """kang (reply message) + Create sticker and add to pack""" + sender = await ult.get_sender() + if not isinstance(sender, User): + return + if not ult.is_reply: + return await ult.eor("`Reply to a message..`", time=5) + try: + emoji = ult.text.split(maxsplit=1)[1] + except IndexError: + emoji = None + reply = await ult.get_reply_message() + ult = await ult.eor(get_string("com_1")) + type_, dl = "static", None + if reply.sticker: + file = get_input_document(reply.sticker) + if not emoji: + emoji = reply.file.emoji + name = reply.file.name + ext = get_extension(reply.media) + attr = list( + filter( + lambda prop: isinstance(prop, DocumentAttributeSticker), + reply.document.attributes, + ) + ) + inPack = attr and not isinstance(attr[0].stickerset, InputStickerSetEmpty) + with contextlib.suppress(KeyError): + type_ = {".webm": "video", ".tgs": "animated"}[ext] + if type_ or not inPack: + dl = await reply.download_media() + elif reply.photo: + dl = await reply.download_media() + name = "sticker.webp" + image = resize_photo_sticker(dl) + image.save(name, "WEBP") + elif reply.text: + with rm.get("quotly", helper=True, dispose=True) as quotly: + dl = await quotly.create_quotly(reply) + else: + return await ult.eor("`Reply to sticker or text to add it in your pack...`") + if not emoji: + emoji = "🏵" + if dl: + upl = await asst.upload_file(dl) + file = get_input_document(await asst(UploadMediaRequest(InputPeerSelf(), upl))) + get_ = udB.get_key("STICKERS") or {} + title = getName(sender, type_) + if not get_.get(ult.sender_id) or not get_.get(ult.sender_id, {}).get(type_): + try: + pack = await AddToNewPack(type_, file, emoji, sender.id, title) + except Exception as er: + return await ult.eor(str(er)) + sn = pack.set.short_name + if not get_.get(ult.sender_id): + get_.update({ult.sender_id: {type_: [sn]}}) + else: + get_[ult.sender_id].update({type_: [sn]}) + udB.set_key("STICKERS", get_) + return await ult.edit( + f"**Kanged Successfully!\nEmoji :** {emoji}\n**Link :** [Click Here](https://t.me/addstickers/{sn})", + link_preview=False + ) + name = get_[ult.sender_id][type_][-1] + try: + await asst(GetSticker(InputStickerSetShortName(name), hash=0)) + except StickersetInvalidError: + get_[ult.sender_id][type_].remove(name) + try: + await asst( + AddSticker(InputStickerSetShortName(name), SetItem(file, emoji=emoji)) + ) + except (errors.StickerpackStickersTooMuchError, errors.StickersTooMuchError): + try: + pack = await AddToNewPack(type_, file, emoji, sender.id, title) + except Exception as er: + return await ult.eor(str(er)) + get_[ult.sender_id][type_].append(pack.set.short_name) + udB.set_key("STICKERS", get_) + return await ult.edit( + f"**Created New Kang Pack!\nEmoji :** {emoji}\n**Link :** [Click Here](https://t.me/addstickers/{sn})", + link_preview=False + ) + except Exception as er: + LOGS.exception(er) + return await ult.edit(str(er)) + await ult.edit( + f"Sticker Added to Pack Successfully\n**Link :** [Click Here](https://t.me/addstickers/{name})", + link_preview=False + ) + + +@ultroid_cmd(pattern="listpack", manager=True) +async def do_magic(ult): + """Get list of sticker packs.""" + ko = udB.get_key("STICKERS") or {} + if not ko.get(ult.sender_id): + return await ult.reply("No Sticker Pack Found!") + al_ = [] + ul = ko[ult.sender_id] + for _ in ul.keys(): + al_.extend(ul[_]) + msg = "• **Stickers Owned by You!**\n\n" + for _ in al_: + try: + pack = await ult.client(GetSticker(InputStickerSetShortName(_), hash=0)) + msg += f"• [{pack.set.title}](https://t.me/addstickers/{_})\n" + except StickersetInvalidError: + for type_ in ["animated", "video", "static"]: + if ul.get(type_) and _ in ul[type_]: + ul[type_].remove(_) + udB.set_key("STICKERS", ko) + await ult.reply(msg) diff --git a/modules/basic/stories.py b/modules/basic/stories.py new file mode 100644 index 0000000000..ea885339ab --- /dev/null +++ b/modules/basic/stories.py @@ -0,0 +1,86 @@ +# Ultroid - UserBot +# Copyright (C) 2021-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +""" +✘ Commands Available - + +• `{i}setstory ` + Set replied media as your story. + +• `{i}storydl ` + Download and upload user stories! +""" + +import os +from contextlib import suppress +from .. import ultroid_cmd, get_string, LOGS +from telethon import TelegramClient +from telethon.tl.types import User, UserFull, InputPeerSelf, InputPrivacyValueAllowAll +from telethon.tl.functions.stories import SendStoryRequest +from telethon.tl.functions.users import GetFullUserRequest +from telethon.events import NewMessage + + +@ultroid_cmd("setstory") +async def setStory(event: NewMessage.Event): + reply = await event.get_reply_message() + if not (reply and (reply.photo or reply.video)): + await event.eor("Please reply to a photo or video!", time=5) + return + msg = await event.eor(get_string("com_1")) + try: + await event.client( + SendStoryRequest( + InputPeerSelf(), + reply.media, + privacy_rules=[ + InputPrivacyValueAllowAll() + ] + ) + ) + await msg.eor("🔥 **Story is Live!**", time=5) + except Exception as er: + await msg.edit(f"__ERROR: {er}__") + LOGS.exception(er) + + +@ultroid_cmd("storydl") +async def downloadUserStories(event: NewMessage.Event): + replied = await event.get_reply_message() + await event.eor(get_string("com_1")) + try: + username = event.text.split(maxsplit=1)[1] + except IndexError: + if replied and isinstance(replied.sender, User): + username = replied.sender_id + else: + return await event.eor( + "Please reply to a user or provide username!" + # get_string("story_1") + ) + with suppress(ValueError): + username = int(username) + try: + full_user: UserFull = ( + await event.client(GetFullUserRequest(id=username)) + ).full_user + except Exception as er: + await event.eor(f"ERROR: __{er}__") + return + stories = full_user.stories + if not (stories and stories.stories): + await event.eor("ERROR: Stories not found!") + return + for story in stories.stories: + client: TelegramClient = event.client + file = await client.download_media(story.media) + await event.reply( + story.caption, + file=file + ) + os.remove(file) + await event.eor("**Uploaded Stories!**", time=5) diff --git a/plugins/sudo.py b/modules/basic/sudo.py similarity index 66% rename from plugins/sudo.py rename to modules/basic/sudo.py index 36f1aeeb35..e9e8519eeb 100644 --- a/plugins/sudo.py +++ b/modules/basic/sudo.py @@ -1,5 +1,5 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2021-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in @@ -19,81 +19,71 @@ from telethon.tl.types import User -from pyUltroid._misc import sudoers +from core import ultroid_bot +from core.decorators import get_sudos, is_sudo +from utilities.helper import inline_mention -from . import get_string, inline_mention, udB, ultroid_bot, ultroid_cmd +from .. import get_string, udB, ultroid_cmd @ultroid_cmd(pattern="addsudo( (.*)|$)", fullsudo=True) -async def _(ult): +async def addsudo_func(ult): inputs = ult.pattern_match.group(1).strip() if ult.reply_to_msg_id: replied_to = await ult.get_reply_message() - id = replied_to.sender_id + id_ = replied_to.sender_id name = await replied_to.get_sender() elif inputs: + id_ = inputs try: - id = await ult.client.parse_id(inputs) - except ValueError: - try: - id = int(inputs) - except ValueError: - id = inputs - try: - name = await ult.client.get_entity(int(id)) + name = await ult.client.get_entity(inputs) except BaseException: name = None elif ult.is_private: - id = ult.chat_id + id_ = ult.chat_id name = await ult.get_chat() else: return await ult.eor(get_string("sudo_1"), time=5) if name and isinstance(name, User) and (name.bot or name.verified): return await ult.eor(get_string("sudo_4")) - name = inline_mention(name) if name else f"`{id}`" - if id == ultroid_bot.uid: + name = inline_mention(name) if name else f"`{id_}`" + if id_ == ultroid_bot.uid: mmm = get_string("sudo_2") - elif id in sudoers(): + elif is_sudo(id_): mmm = f"{name} `is already a SUDO User ...`" else: udB.set_key("SUDO", "True") - key = sudoers() - key.append(id) + key = get_sudos() + key.append(id_) udB.set_key("SUDOS", key) mmm = f"**Added** {name} **as SUDO User**" await ult.eor(mmm, time=5) @ultroid_cmd(pattern="delsudo( (.*)|$)", fullsudo=True) -async def _(ult): +async def delsudo_func(ult): inputs = ult.pattern_match.group(1).strip() if ult.reply_to_msg_id: replied_to = await ult.get_reply_message() - id = replied_to.sender_id + id_ = replied_to.sender_id name = await replied_to.get_sender() elif inputs: + id_ = inputs try: - id = await ult.client.parse_id(inputs) - except ValueError: - try: - id = int(inputs) - except ValueError: - id = inputs - try: - name = await ult.client.get_entity(int(id)) + name = await ult.client.get_entity(id_) except BaseException: name = None elif ult.is_private: - id = ult.chat_id + id_ = ult.chat_id name = await ult.get_chat() else: return await ult.eor(get_string("sudo_1"), time=5) - name = inline_mention(name) if name else f"`{id}`" - if id not in sudoers(): + name = inline_mention(name) if name else f"`{id_}`" + if not is_sudo(id_): mmm = f"{name} `wasn't a SUDO User ...`" else: - key = sudoers() - key.remove(id) + key = get_sudos() + key.remove(id_) udB.set_key("SUDOS", key) mmm = f"**Removed** {name} **from SUDO User(s)**" await ult.eor(mmm, time=5) @@ -102,22 +92,22 @@ async def _(ult): @ultroid_cmd( pattern="listsudo$", ) -async def _(ult): - sudos = sudoers() +async def listsudo_func(ult): + sudos = get_sudos() if not sudos: return await ult.eor(get_string("sudo_3"), time=5) msg = "" for i in sudos: try: - name = await ult.client.get_entity(int(i)) + name = await ult.client.get_entity(i) except BaseException: name = None if name: msg += f"• {inline_mention(name)} ( `{i}` )\n" else: msg += f"• `{i}` -> Invalid User\n" - m = udB.get_key("SUDO") or True - if not m: + m = udB.get_key("SUDO") + if m is not True: m = "[False](https://graph.org/Ultroid-04-06)" return await ult.eor( f"**SUDO MODE : {m}\n\nList of SUDO Users :**\n{msg}", link_preview=False diff --git a/modules/basic/tools.py b/modules/basic/tools.py new file mode 100644 index 0000000000..119a383c56 --- /dev/null +++ b/modules/basic/tools.py @@ -0,0 +1,637 @@ +# Ultroid - UserBot +# Copyright (C) 2021-2022 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +from localization import get_help + +__doc__ = get_help("tools") + +import contextlib +import os +from glob import glob +from io import BytesIO +import html, math + +from database.helpers import get_random_color +from telethon.errors import MessageTooLongError +from telethon.tl import TLObject + +from telethon.tl.functions.channels import InviteToChannelRequest +from telethon.tl.functions.messages import AddChatUserRequest +from telethon.errors import UserBotError +from telethon.utils import get_peer_id +from telethon.tl import functions, types +from telethon.tl.functions.users import GetFullUserRequest +from core.decorators import owner_and_sudos +from core import HNDLR +from core.remote import rm +from utilities.tools import atranslate, json_parser + +from .. import LOGS, get_string, humanbytes, ultroid_cmd + + +@ultroid_cmd(pattern="tr( (.*)|$)", manager=True) +async def tr_func(event): + input_ = event.pattern_match.group(1).strip().split(maxsplit=1) + txt = input_[1] if len(input_) > 1 else None + if input_: + input_ = input_[0] + if txt: + text = txt + elif event.is_reply: + message = await event.get_reply_message() + text = message.message + else: + return await event.eor( + f"`{HNDLR}tr LanguageCode` as reply to a message", time=5 + ) + lan = input_ or "en" + try: + tt, det = await atranslate(text, target=lan, detect=True) + output_str = f"**TRANSLATED** to `{lan}` from `{det}`\n{tt}" + await event.eor(output_str) + except Exception as exc: + LOGS.exception(exc) + await event.eor(str(exc), time=5) + + +@ultroid_cmd( + pattern="id( (.*)|$)", + manager=True, +) +async def id_func(event): + text = f"`Sender ID`: `{event.sender_id}`\n" + if match := event.pattern_match.group(1).strip(): + try: + ids = await event.client.parse_id(match) + except Exception as er: + return await event.eor(str(er)) + if str(ids).startswith("-"): + text += f"`Requested Chat ID`: " + else: + text += f"`Requested User ID`: " + text += f"`{ids}`\n" + if reply := (await event.get_reply_message()): + text += f"`Replied to message ID`: `{reply.id}`\n" + text += f"`Replied to User ID`: `{reply.sender_id}`\n" + text += f"`Current Chat ID`: `{event.chat_id}`" + await event.eor(text) + + +@ultroid_cmd(pattern="json( (.*)|$)") +async def json_func(event): + reply_to_id = None + match = event.pattern_match.group(1).strip() + if event.reply_to_msg_id: + msg = await event.get_reply_message() + reply_to_id = event.reply_to_msg_id + else: + msg = event + reply_to_id = event.message.id + if ( + match + and (event.sender_id in owner_and_sudos(only_full=True)) + and hasattr(msg, match.split()[0].split(".")[0]) + ): + for attr in match.split()[0].split("."): + msg = getattr(msg, attr, None) + if not msg: + break + with contextlib.suppress(Exception): + if hasattr(msg, "to_json"): + msg = msg.to_json(ensure_ascii=False, indent=1) + elif hasattr(msg, "to_dict"): + msg = json_parser(msg.to_dict(), indent=1) + else: + msg = TLObject.stringify(msg) + msg = str(msg) + else: + msg = json_parser(msg.to_json(), indent=1) + if "-t" in match: + with contextlib.suppress(Exception): + data = json_parser(msg) # type: ignore + msg = json_parser( + {key: data[key] for key in data if data.get(key)}, indent=1 + ) + msg = str(msg) + if len(msg) > 4096: + with BytesIO(msg.encode()) as out_file: + out_file.name = "json-ult.txt" + await event.client.send_file( + event.chat_id, + out_file, + force_document=True, + allow_cache=False, + reply_to=reply_to_id, + ) + await event.delete() + return + await event.eor(f"```{msg or None}```") + + +@ultroid_cmd( + pattern="ls($| ?(.*))", +) +async def ls_func(e): + """list files in a directory""" + files = e.pattern_match.group(1).strip() + if not files: + files = "*" + elif files.endswith("/"): + files += "*" + elif "*" not in files: + files += "/*" + files = glob(files) + + if not files: + return await e.eor("`Directory Empty or Incorrect.`", time=5) + pyfiles = [] + jsons = [] + vdos = [] + audios = [] + pics = [] + others = [] + otherfiles = [] + folders = [] + text = [] + apk = [] + exe = [] + zip_ = [] + book = [] + for file in sorted(files): + if os.path.isdir(file): + folders.append(f"📂 {str(file)}") + elif str(file).endswith(".py"): + pyfiles.append(f"🐍 {str(file)}") + elif str(file).endswith(".json"): + jsons.append(f"🔮 {str(file)}") + elif str(file).endswith((".mkv", ".mp4", ".avi", ".gif", "webm")): + vdos.append(f"🎥 {str(file)}") + elif str(file).endswith((".mp3", ".ogg", ".m4a", ".opus")): + audios.append(f"🔊 {str(file)}") + elif str(file).endswith((".jpg", ".jpeg", ".png", ".webp", ".ico")): + pics.append(f"🖼 {str(file)}") + elif str(file).endswith((".txt", ".text", ".log")): + text.append(f"📄 {str(file)}") + elif str(file).endswith((".apk", ".xapk")): + apk.append(f"📲 {str(file)}") + elif str(file).endswith((".exe", ".iso")): + exe.append(f"⚙ {str(file)}") + elif str(file).endswith((".zip", ".rar")): + zip_.append("🗜 " + str(file)) + elif str(file).endswith((".pdf", ".epub")): + book.append("📗 " + str(file)) + elif "." in str(file)[1:]: + others.append("🏷 " + str(file)) + else: + otherfiles.append("📒 " + str(file)) + omk = [ + *sorted(folders), + *sorted(pyfiles), + *sorted(jsons), + *sorted(zip_), + *sorted(vdos), + *sorted(pics), + *sorted(audios), + *sorted(apk), + *sorted(exe), + *sorted(book), + *sorted(text), + *sorted(others), + *sorted(otherfiles), + ] + text = "" + fls, fos = 0, 0 + flc, foc = 0, 0 + for i in omk: + with contextlib.suppress(BaseException): + emoji = i.split()[0] + name = i.split(maxsplit=1)[1] + nam = name.split("/")[-1] + if os.path.isdir(name): + size = 0 + for path, dirs, files in os.walk(name): + for f in files: + fp = os.path.join(path, f) + size += os.path.getsize(fp) + if humanbytes(size): + text += emoji + f" `{nam}`" + " `" + humanbytes(size) + "`\n" + fos += size + else: + text += emoji + f" `{nam}`" + "\n" + foc += 1 + else: + if humanbytes(int(os.path.getsize(name))): + text += ( + emoji + + f" `{nam}`" + + " `" + + humanbytes(int(os.path.getsize(name))) + + "`\n" + ) + fls += int(os.path.getsize(name)) + else: + text += emoji + f" `{nam}`" + "\n" + flc += 1 + tfos, tfls, ttol = humanbytes(fos), humanbytes(fls), humanbytes(fos + fls) + text += f"\n\n`Folders` : `{foc}` : `{tfos}`\n`Files` : `{flc}` : `{tfls}`\n`Total` : `{flc+foc}` : `{ttol}`" + try: + await e.eor(text) + except MessageTooLongError: + with BytesIO(str.encode(text)) as out_file: + out_file.name = "output.txt" + await e.reply(f"`{e.text}`", file=out_file) + await e.delete() + + +# TODO: fix it a bit + + +@ultroid_cmd( + pattern="graph( ?(.*)|$)", +) +async def graph_func(event): + """ + `graph` + `graph list`""" + input_str = event.pattern_match.group(1).strip() + xx = await event.eor(get_string("com_1")) + with rm.get("graph", helper=True, dispose=True) as mod: + upload_file, client = mod.upload_file, mod.get_client() + if event.reply_to_msg_id: + getmsg = await event.get_reply_message() + if getmsg.photo or getmsg.video or getmsg.gif: + getit = await getmsg.download_media() + try: + nn = upload_file(getit) + os.remove(getit) + amsg = f"Uploaded to [Telegraph]({nn}) !" + except Exception as e: + amsg = f"Error - {e}" + return await xx.edit(amsg) + elif getmsg.document: + getit = await getmsg.download_media() + with open(getit, "r") as ab: + cd = ab.read() + os.remove(getit) + elif getmsg.text: + cd = getmsg.text + else: + return await xx.edit("Reply to a Media or Text !") + tcom = input_str or "Ultroid" + makeit = client.create_page(title=tcom, content=[cd]) + war = makeit["url"] + await xx.edit(f"Pasted to Telegraph : [Telegraph]({war})") + return + elif input_str == "list": + res = client.get_page_list() + if not res["total_count"]: + return await xx.edit("`You have not created any telegraph.`") + text = "**Telegraph Pages**\n\n" + for page in res["pages"]: + text += f"- [{page['title']}]({page['url']}) ({page['views']})\n" + await xx.edit(text) + return + await xx.edit("Reply to a Message !") + + +@ultroid_cmd(pattern="q( (.*)|$)", manager=True, allow_pm=True) +async def q_func(event): + match = event.pattern_match.group(1).strip() + if not event.is_reply: + return await event.eor("`Reply to Message..`") + msg = await event.eor(get_string("com_1")) + reply = await event.get_reply_message() + replied_to, reply_ = None, None + if match: + spli_ = match.split(maxsplit=1) + if (spli_[0] in ["r", "reply"]) or ( + spli_[0].isdigit() and int(spli_[0]) in range(1, 21) + ): + if spli_[0].isdigit(): + if not event.client._bot: + reply_ = await event.client.get_messages( + event.chat_id, + min_id=event.reply_to_msg_id - 1, + reverse=True, + limit=int(spli_[0]), + ) + else: + id_ = reply.id + reply_ = [] + for msg_ in range(id_, id_ + int(spli_[0])): + msh = await event.client.get_messages(event.chat_id, ids=msg_) + if msh: + reply_.append(msh) + else: + replied_to = await reply.get_reply_message() + try: + match = spli_[1] + except IndexError: + match = None + user = None + if not reply_: + reply_ = reply + if match: + match = match.split(maxsplit=1) + if match: + if match[0].startswith("@") or match[0].isdigit(): + try: + match_ = await event.client.parse_id(match[0]) + user = await event.client.get_entity(match_) + except ValueError: + pass + match = match[1] if len(match) == 2 else None + else: + match = match[0] + if match == "random": + match = get_random_color() + try: + with rm.get("quotly", helper=True, dispose=True) as mod: + file = await mod.create_quotly( + reply_, bg=match, reply=replied_to, sender=user + ) + except Exception as er: + return await msg.edit(str(er)) + message = await reply.reply("Quotly by Ultroid", file=file) + os.remove(file) + await msg.delete() + return message + + +@ultroid_cmd( + pattern="invite( (.*)|$)", + groups_only=True, +) +async def invite_func(ult): + xx = await ult.eor(get_string("com_1")) + to_add_users = ult.pattern_match.group(1).strip() + add_chat_user = not ult.is_channel and ult.is_group + request = AddChatUserRequest if add_chat_user else InviteToChannelRequest + users = to_add_users.split() + single = len(users) == 1 + + for user_id in users: + try: + if add_chat_user: + kwargs = { + "chat_id": ult.chat_id, + "user_id": await ult.client.parse_id(user_id), + "fwd_limit": 1000000, + } + else: + kwargs = { + "channel": ult.chat_id, + "users": [await ult.client.parse_id(user_id)], + } + await ult.client(request(**kwargs)) + await xx.edit(f"Successfully invited `{user_id}` to `{ult.chat_id}`") + except UserBotError as er: + if single: + await xx.edit( + f"Bots can only be added as Admins in Channel.\nBetter Use `{HNDLR}promote {user_id}`" + ) + continue + LOGS.exception(er) + except Exception as er: + if single: + await xx.edit(str(er)) + continue + LOGS.exception(er) + + +@ultroid_cmd( + pattern="info( (.*)|$)", + manager=True, +) +async def getInfo(event): + user = event.pattern_match.group(1).strip() + if not user: + if event.is_reply: + rpl = await event.get_reply_message() + user = rpl.sender_id + else: + user = event.chat_id + xx = await event.eor(get_string("com_1")) + try: + _ = await event.client.get_entity(user) + except Exception as er: + return await xx.edit(f"**ERROR :** {er}") + if not isinstance(_, types.User): + try: + get_peer_id(_) + photo, capt = await get_chat_info(_, event) + if not photo: + return await xx.eor(capt, parse_mode="html") + await event.client.send_message( + event.chat_id, capt[:1024], file=photo, parse_mode="html" + ) + await xx.delete() + except Exception as er: + await event.eor("**ERROR ON CHATINFO**\n" + str(er)) + return + try: + full_user: types.UserFull = (await event.client(GetFullUserRequest(user))).full_user + except Exception as er: + return await xx.edit(f"ERROR : {er}") + user = _ + user_photos = ( + await event.client.get_profile_photos(user.id, limit=0) + ).total or "NaN" + user_id = user.id + first_name = html.escape(user.first_name) + if first_name is not None: + first_name = first_name.replace("\u2060", "") + last_name = user.last_name + last_name = ( + last_name.replace("\u2060", "") if last_name else ( + "Last Name not found") + ) + user_bio = html.escape(full_user.about or "") + common_chats = full_user.common_chats_count + if user.photo: + dc_id = user.photo.dc_id + else: + dc_id = "Need a Profile Picture to check this" + caption = f"""Exᴛʀᴀᴄᴛᴇᴅ Dᴀᴛᴀ Fʀᴏᴍ Tᴇʟᴇɢʀᴀᴍ's Dᴀᴛᴀʙᴀsᴇ +••Tᴇʟᴇɢʀᴀᴍ ID: {user_id} +••Pᴇʀᴍᴀɴᴇɴᴛ Lɪɴᴋ: Click Here +••Fɪʀsᴛ Nᴀᴍᴇ: {first_name}""" + if not user.bot: + caption += f"\n••Sᴇᴄᴏɴᴅ Nᴀᴍᴇ: {last_name}" + caption += f"""\n••Bɪᴏ: {user_bio} +••Dᴄ ID: {dc_id}""" + if (b_date:= full_user.birthday): + date = f"{b_date.day}-{b_date.month}" + if b_date.year: + date += f"-{b_date.year}" + caption += f"\n••Birthday : {date}" + if full_user.stories: + caption += f"\n••Stories Count : {len(full_user.stories.stories)}" + if user_photos: + caption += f"\n••Nᴏ. Oғ PғPs : {user_photos}" + if not user.bot: + caption += f"\n••Is Rᴇsᴛʀɪᴄᴛᴇᴅ: {user.restricted}" + caption += f"\n••Is Pʀᴇᴍɪᴜᴍ: {user.premium}" + caption += f"""\n••Vᴇʀɪғɪᴇᴅ: {user.verified} +••Is A Bᴏᴛ: {user.bot} +••Gʀᴏᴜᴘs Iɴ Cᴏᴍᴍᴏɴ: {common_chats} +""" + # if chk := is_gbanned(user_id): + # caption += f"""••Gʟᴏʙᴀʟʟʏ Bᴀɴɴᴇᴅ: True + # ••Rᴇᴀsᴏɴ: {chk}""" + await event.client.send_message( + event.chat_id, + caption, + reply_to=event.reply_to_msg_id, + parse_mode="HTML", + file=full_user.profile_photo, + force_document=False, + silent=True, + ) + await xx.delete() + + +async def get_chat_info(chat, event): + if isinstance(chat, types.Channel): + chat_info = await event.client(functions.channels.GetFullChannelRequest(chat)) + elif isinstance(chat, types.Chat): + chat_info = await event.client(functions.messages.GetFullChatRequest(chat)) + else: + return await event.eor("`Use this for Group/Channel.`") + full = chat_info.full_chat + chat_photo = full.chat_photo + broadcast = getattr(chat, "broadcast", False) + chat_type = "Channel" if broadcast else "Group" + chat_title = chat.title + try: + msg_info = await event.client( + functions.messages.GetHistoryRequest( + peer=chat.id, + offset_id=0, + offset_date=None, + add_offset=-0, + limit=0, + max_id=0, + min_id=0, + hash=0, + ) + ) + except Exception as er: + msg_info = None + if not event.client._bot: + LOGS.exception(er) + first_msg_valid = bool( + msg_info and msg_info.messages and msg_info.messages[0].id == 1 + ) + + creator_valid = bool(first_msg_valid and msg_info.users) + creator_id = msg_info.users[0].id if creator_valid else None + creator_firstname = ( + msg_info.users[0].first_name + if creator_valid and msg_info.users[0].first_name is not None + else "Deleted Account" + ) + creator_username = ( + msg_info.users[0].username + if creator_valid and msg_info.users[0].username is not None + else None + ) + created = msg_info.messages[0].date if first_msg_valid else None + if not isinstance(chat.photo, types.ChatPhotoEmpty): + dc_id = chat.photo.dc_id + else: + dc_id = "Null" + + restricted_users = getattr(full, "banned_count", None) + members = getattr(full, "participants_count", chat.participants_count) + admins = getattr(full, "admins_count", None) + banned_users = getattr(full, "kicked_count", None) + members_online = getattr(full, "online_count", 0) + group_stickers = ( + full.stickerset.title if getattr(full, "stickerset", None) else None + ) + messages_viewable = msg_info.count if msg_info else None + messages_sent = getattr(full, "read_inbox_max_id", None) + messages_sent_alt = getattr(full, "read_outbox_max_id", None) + exp_count = getattr(full, "pts", None) + supergroup = "Yes" if getattr(chat, "megagroup", None) else "No" + creator_username = "@{}".format( + creator_username) if creator_username else None + + if admins is None: + try: + participants_admins = await event.client( + functions.channels.GetParticipantsRequest( + channel=chat.id, + filter=types.ChannelParticipantsAdmins(), + offset=0, + limit=0, + hash=0, + ) + ) + admins = participants_admins.count if participants_admins else None + except Exception as e: + LOGS.info(f"Exception: {e}") + caption = "ℹ️ [CHAT INFO]\n" + caption += f"🆔 ID: {chat.id}\n" + if chat_title is not None: + caption += f"📛 {chat_type} name: {chat_title}\n" + if chat.username: + caption += f"🔗 Link: @{chat.username}\n" + else: + caption += f"🗳 {chat_type} type: Private\n" + if creator_username: + caption += f"🖌 Creator: {creator_username}\n" + elif creator_valid: + caption += f'🖌 Creator: {creator_firstname}\n' + if created: + caption += f"🖌 Created: {created.date().strftime('%b %d, %Y')} - {created.time()}\n" + else: + caption += f"🖌 Created: {chat.date.date().strftime('%b %d, %Y')} - {chat.date.time()} ⚠\n" + caption += f"🗡 Data Centre ID: {dc_id}\n" + if exp_count is not None: + chat_level = int((1 + math.sqrt(1 + 7 * exp_count / 14)) / 2) + caption += f"⭐️ {chat_type} level: {chat_level}\n" + if messages_viewable is not None: + caption += f"💬 Viewable messages: {messages_viewable}\n" + if messages_sent: + caption += f"💬 Messages sent: {messages_sent}\n" + elif messages_sent_alt: + caption += f"💬 Messages sent: {messages_sent_alt} ⚠\n" + if members is not None: + caption += f"👥 Members: {members}\n" + if admins: + caption += f"👮 Administrators: {admins}\n" + if full.bot_info: + caption += f"🤖 Bots: {len(full.bot_info)}\n" + if members_online: + caption += f"👀 Currently online: {members_online}\n" + if restricted_users is not None: + caption += f"🔕 Restricted users: {restricted_users}\n" + if banned_users: + caption += f"📨 Banned users: {banned_users}\n" + if group_stickers: + caption += f'📹 {chat_type} stickers: {group_stickers}\n' + if not broadcast: + if getattr(chat, "slowmode_enabled", None): + caption += f"👉 Slow mode: True" + caption += f", 🕐 {full.slowmode_seconds}s\n" + else: + caption += f"🦸‍♂ Supergroup: {supergroup}\n" + if getattr(chat, "restricted", None): + caption += f"🎌 Restricted: {chat.restricted}\n" + rist = chat.restriction_reason[0] + caption += f"> Platform: {rist.platform}\n" + caption += f"> Reason: {rist.reason}\n" + caption += f"> Text: {rist.text}\n\n" + if getattr(chat, "scam", None): + caption += "⚠ Scam: Yes\n" + if getattr(chat, "verified", None): + caption += f"✅ Verified by Telegram: Yes\n\n" + if full.about: + caption += f"🗒 Description: \n{full.about}\n" + return chat_photo, caption diff --git a/plugins/vctools.py b/modules/basic/vctools.py similarity index 60% rename from plugins/vctools.py rename to modules/basic/vctools.py index dcc3c33203..1852d0433a 100644 --- a/plugins/vctools.py +++ b/modules/basic/vctools.py @@ -1,9 +1,10 @@ # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2021-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in # . + """ ✘ Commands Available - @@ -21,20 +22,23 @@ (You must be joined) """ -from telethon.tl.functions.channels import GetFullChannelRequest as getchat -from telethon.tl.functions.phone import CreateGroupCallRequest as startvc -from telethon.tl.functions.phone import DiscardGroupCallRequest as stopvc -from telethon.tl.functions.phone import EditGroupCallTitleRequest as settitle -from telethon.tl.functions.phone import GetGroupCallRequest as getvc -from telethon.tl.functions.phone import InviteToGroupCallRequest as invitetovc -from . import get_string, ultroid_cmd +import contextlib +from telethon.tl.functions.channels import GetFullChannelRequest +from telethon.tl.functions.phone import CreateGroupCallRequest +from telethon.tl.functions.phone import DiscardGroupCallRequest +from telethon.tl.functions.phone import EditGroupCallTitleRequest +from telethon.tl.functions.phone import GetGroupCallRequest +from telethon.tl.functions.phone import InviteToGroupCallRequest + +from .. import get_string, ultroid_cmd, LOGS async def get_call(event): - mm = await event.client(getchat(event.chat_id)) - xx = await event.client(getvc(mm.full_chat.call, limit=1)) - return xx.call + mm = await event.client(GetFullChannelRequest(event.chat_id)) + if mm.full_chat.call: + xx = await event.client(GetGroupCallRequest(mm.full_chat.call, limit=1)) + return xx.call def user_list(l, n): @@ -49,9 +53,12 @@ def user_list(l, n): ) async def _(e): try: - await e.client(stopvc(await get_call(e))) - await e.eor(get_string("vct_4")) + if call := await get_call(e): + await e.client(DiscardGroupCallRequest(call)) + return await e.eor(get_string("vct_4")) + await e.eor("`Voice call is not active.`") except Exception as ex: + LOGS.exception(ex) await e.eor(f"`{ex}`") @@ -67,12 +74,13 @@ async def _(e): if not x.bot: users.append(x.id) hmm = list(user_list(users, 6)) + call = await get_call(e) + if not call: + return await e.eor("`Voice Call is not active.`") for p in hmm: - try: - await e.client(invitetovc(call=await get_call(e), users=p)) - z += 6 - except BaseException: - pass + with contextlib.suppress(BaseException): + await e.client(InviteToGroupCallRequest(call=call, users=p)) + z += len(p) await ok.edit(get_string("vct_5").format(z)) @@ -83,9 +91,10 @@ async def _(e): ) async def _(e): try: - await e.client(startvc(e.chat_id)) + await e.client(CreateGroupCallRequest(e.chat_id)) await e.eor(get_string("vct_1")) except Exception as ex: + LOGS.exception(ex) await e.eor(f"`{ex}`") @@ -98,8 +107,11 @@ async def _(e): title = e.pattern_match.group(1).strip() if not title: return await e.eor(get_string("vct_6"), time=5) + call = await get_call(e) + if not call: + return await e.eor("`Voice Call is not active.`") try: - await e.client(settitle(call=await get_call(e), title=title.strip())) + await e.client(EditGroupCallTitleRequest(call=call, title=title.strip())) await e.eor(get_string("vct_2").format(title)) except Exception as ex: await e.eor(f"`{ex}`") diff --git a/modules/basic/webupload.py b/modules/basic/webupload.py new file mode 100644 index 0000000000..e396062a97 --- /dev/null +++ b/modules/basic/webupload.py @@ -0,0 +1,161 @@ +# Ultroid - UserBot +# Copyright (C) 2021-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in +# . + +""" +✘ Commands Available - + +• `{i}webupload` + Upload files on another server. +""" + +import os, re + + +from .. import Button, asst, get_string, ultroid_cmd, callback, fetch, in_pattern + +_webupload_cache = {} + +@ultroid_cmd( + pattern="webupload( (.*)|$)", +) +async def _(event): + xx = await event.eor(get_string("com_1")) + match = event.pattern_match.group(1).strip() + if event.chat_id not in _webupload_cache: + _webupload_cache.update({int(event.chat_id): {}}) + if match: + if not os.path.exists(match): + return await xx.eor("`File doesn't exist.`") + _webupload_cache[event.chat_id][event.id] = match + elif event.reply_to_msg_id: + reply = await event.get_reply_message() + if reply.photo: + file = await reply.download_media("resources/downloads/") + _webupload_cache[int(event.chat_id)][int(event.id)] = file + else: + file, _ = await event.client.fast_downloader( + reply.document, show_progress=True, event=xx + ) + _webupload_cache[int(event.chat_id)][int(event.id)] = file.name + else: + return await xx.eor("`Reply to file or give file path...`") + if not event.client._bot: + results = await event.client.inline_query( + asst.me.username, f"fl2lnk {event.chat_id}:{event.id}" + ) + await results[0].click(event.chat_id, reply_to=event.reply_to_msg_id) + await xx.delete() + + else: + __cache = f"{event.chat_id}:{event.id}" + buttons = [ + [ + Button.inline("anonfiles", data=f"flanonfiles//{__cache}"), + Button.inline("transfer", data=f"fltransfer//{__cache}"), + ], + [ + Button.inline("bayfiles", data=f"flbayfiles//{__cache}"), + Button.inline("x0.at", data=f"flx0.at//{__cache}"), + ], + [ + Button.inline("file.io", data=f"flfile.io//{__cache}"), + Button.inline("siasky", data=f"flsiasky//{__cache}"), + ], + ] + await xx.edit("**Choose Server to Upload File...**", buttons=buttons) + + +@callback( + re.compile( + "fl(.*)", + ), + owner=True, +) +async def _(e): + t = (e.data).decode("UTF-8") + data = t[2:] + host = data.split("//")[0] + chat_id, msg_id = data.split("//")[1].split(":") + filename = _webupload_cache[int(chat_id)][int(msg_id)] + if "/" in filename: + filename = filename.split("/")[-1] + await e.edit(f"Uploading `{filename}` on {host}") + link = (await webuploader(chat_id, msg_id, host)).strip().replace("\n", "") + await e.edit(f"Uploaded `{filename}` on {host}.", buttons=Button.url("View", link)) + + +@in_pattern("fl2lnk ?(.*)", owner=True) +async def _(e): + match = e.pattern_match.group(1) + chat_id, msg_id = match.split(":") + filename = _webupload_cache[int(chat_id)][int(msg_id)] + if "/" in filename: + filename = filename.split("/")[-1] + __cache = f"{chat_id}:{msg_id}" + buttons = [ + [ + Button.inline("anonfiles", data=f"flanonfiles//{__cache}"), + Button.inline("transfer", data=f"fltransfer//{__cache}"), + ], + [ + Button.inline("bayfiles", data=f"flbayfiles//{__cache}"), + Button.inline("x0.at", data=f"flx0.at//{__cache}"), + ], + [ + Button.inline("file.io", data=f"flfile.io//{__cache}"), + Button.inline("siasky", data=f"flsiasky//{__cache}"), + ], + ] + try: + lnk = [ + await e.builder.article( + title=f"Upload {filename}", + text=f"**File:**\n{filename}", + buttons=buttons, + ) + ] + except BaseException as er: + LOGS.exception(er) + lnk = [ + await e.builder.article( + title="fl2lnk", + text="File not found", + ) + ] + await e.answer(lnk, switch_pm="File to Link.", switch_pm_param="start") + + +async def webuploader(chat_id: int, msg_id: int, uploader: str): + file = _webupload_cache[int(chat_id)][int(msg_id)] # nq + sites = { + "anonfiles": {"url": "https://api.anonfiles.com/upload", "json": True}, + "siasky": {"url": "https://siasky.net/skynet/skyfile", "json": True}, + "file.io": {"url": "https://file.io", "json": True}, + "bayfiles": {"url": "https://api.bayfiles.com/upload", "json": True}, + "x0.at": {"url": "https://x0.at/", "json": False}, + "transfer": {"url": "https://transfer.sh", "json": False}, + } + if uploader and uploader in sites: + url = sites[uploader]["url"] + json = sites[uploader]["json"] + with open(file, "rb") as data: + # todo: add progress bar + status = await fetch( + url, data={"file": data.read()}, method="POST", re_json=json + ) + if isinstance(status, dict): + if "skylink" in status: + return f"https://siasky.net/{status['skylink']}" + if status["status"] == 200 or status["status"] is True: + try: + link = status["link"] + except KeyError: + link = status["data"]["file"]["url"]["short"] + return link + del _webupload_cache[chat_id][msg_id] + return status + diff --git a/okteto-pipeline.yml b/okteto-pipeline.yml index 4b883dbc2b..5cd97ec448 100644 --- a/okteto-pipeline.yml +++ b/okteto-pipeline.yml @@ -1,3 +1,3 @@ -icon: https://raw.githubusercontent.com/TeamUltroid/Ultroid/main/resources/extras/logo_readme.jpg +icon: https://raw.githubusercontent.com/TeamUltroid/Ultroid/main/resources/images/logo_readme.jpg deploy: - - okteto deploy --build -f docker-compose.yml + - okteto deploy --build -f docker-compose.yml diff --git a/plugins/__init__.py b/plugins/__init__.py deleted file mode 100644 index e4314ca9df..0000000000 --- a/plugins/__init__.py +++ /dev/null @@ -1,100 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import asyncio -import os -import time -from random import choice - -import requests -from telethon import Button, events -from telethon.tl import functions, types # pylint:ignore - -from pyUltroid import * -from pyUltroid._misc._assistant import asst_cmd, callback, in_pattern -from pyUltroid._misc._decorators import ultroid_cmd -from pyUltroid._misc._wrappers import eod, eor -from pyUltroid.dB import DEVLIST, ULTROID_IMAGES -from pyUltroid.fns.helper import * -from pyUltroid.fns.misc import * -from pyUltroid.fns.tools import * -from pyUltroid.startup._database import _BaseDatabase as Database -from pyUltroid.version import __version__, ultroid_version -from strings import get_help, get_string - -udB: Database - -Redis = udB.get_key -con = TgConverter -quotly = Quotly() -OWNER_NAME = ultroid_bot.full_name -OWNER_ID = ultroid_bot.uid - -ultroid_bot: UltroidClient -asst: UltroidClient - -LOG_CHANNEL = udB.get_key("LOG_CHANNEL") - - -def inline_pic(): - INLINE_PIC = udB.get_key("INLINE_PIC") - if INLINE_PIC is None: - INLINE_PIC = choice(ULTROID_IMAGES) - elif INLINE_PIC == False: - INLINE_PIC = None - return INLINE_PIC - - -Telegraph = telegraph_client() - -List = [] -Dict = {} -InlinePlugin = {} -N = 0 -cmd = ultroid_cmd -STUFF = {} - -# Chats, which needs to be ignore for some cases -# Considerably, there can be many -# Feel Free to Add Any other... - -NOSPAM_CHAT = [ - -1001361294038, # UltroidSupportChat - -1001387666944, # PyrogramChat - -1001109500936, # TelethonChat - -1001050982793, # Python - -1001256902287, # DurovsChat - -1001473548283, # SharingUserbot -] - -KANGING_STR = [ - "Using Witchery to kang this sticker...", - "Plagiarising hehe...", - "Inviting this sticker over to my pack...", - "Kanging this sticker...", - "Hey that's a nice sticker!\nMind if I kang?!..", - "Hehe me stel ur stiker...", - "Ay look over there (☉。☉)!→\nWhile I kang this...", - "Roses are red violets are blue, kanging this sticker so my pack looks cool", - "Imprisoning this sticker...", - "Mr.Steal-Your-Sticker is stealing this sticker... ", -] - -ATRA_COL = [ - "DarkCyan", - "DeepSkyBlue", - "DarkTurquoise", - "Cyan", - "LightSkyBlue", - "Turquoise", - "MediumVioletRed", - "Aquamarine", - "Lightcyan", - "Azure", - "Moccasin", - "PowderBlue", -] diff --git a/plugins/_chatactions.py b/plugins/_chatactions.py deleted file mode 100644 index 9f7f6965f2..0000000000 --- a/plugins/_chatactions.py +++ /dev/null @@ -1,253 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import asyncio - -from telethon import events -from telethon.errors.rpcerrorlist import UserNotParticipantError -from telethon.tl.functions.channels import GetParticipantRequest -from telethon.utils import get_display_name - -from pyUltroid.dB import stickers -from pyUltroid.dB.echo_db import check_echo -from pyUltroid.dB.forcesub_db import get_forcesetting -from pyUltroid.dB.gban_mute_db import is_gbanned -from pyUltroid.dB.greetings_db import get_goodbye, get_welcome, must_thank -from pyUltroid.dB.nsfw_db import is_profan -from pyUltroid.fns.helper import inline_mention -from pyUltroid.fns.tools import async_searcher, create_tl_btn, get_chatbot_reply - -try: - from ProfanityDetector import detector -except ImportError: - detector = None -from . import LOG_CHANNEL, LOGS, asst, get_string, types, udB, ultroid_bot -from ._inline import something - - -@ultroid_bot.on(events.ChatAction()) -async def Function(event): - try: - await DummyHandler(event) - except Exception as er: - LOGS.exception(er) - - -async def DummyHandler(ult): - # clean chat actions - key = udB.get_key("CLEANCHAT") or [] - if ult.chat_id in key: - try: - await ult.delete() - except BaseException: - pass - - # thank members - if must_thank(ult.chat_id): - chat_count = (await ult.client.get_participants(ult.chat_id, limit=0)).total - if chat_count % 100 == 0: - stik_id = chat_count / 100 - 1 - sticker = stickers[stik_id] - await ult.respond(file=sticker) - # force subscribe - if ( - udB.get_key("FORCESUB") - and ((ult.user_joined or ult.user_added)) - and get_forcesetting(ult.chat_id) - ): - user = await ult.get_user() - if not user.bot: - joinchat = get_forcesetting(ult.chat_id) - try: - await ultroid_bot(GetParticipantRequest(int(joinchat), user.id)) - except UserNotParticipantError: - await ultroid_bot.edit_permissions( - ult.chat_id, user.id, send_messages=False - ) - res = await ultroid_bot.inline_query( - asst.me.username, f"fsub {user.id}_{joinchat}" - ) - await res[0].click(ult.chat_id, reply_to=ult.action_message.id) - - if ult.user_joined or ult.added_by: - user = await ult.get_user() - chat = await ult.get_chat() - # gbans and @UltroidBans checks - if udB.get_key("ULTROID_BANS"): - try: - is_banned = await async_searcher( - "https://bans.ultroid.tech/api/status", - json={"userId": user.id}, - post=True, - re_json=True, - ) - if is_banned["is_banned"]: - await ult.client.edit_permissions( - chat.id, - user.id, - view_messages=False, - ) - await ult.respond( - f'**@UltroidBans:** Banned user detected and banned!\n`{str(is_banned)}`.\nBan reason: {is_banned["reason"]}', - ) - - except BaseException: - pass - reason = is_gbanned(user.id) - if reason and chat.admin_rights: - try: - await ult.client.edit_permissions( - chat.id, - user.id, - view_messages=False, - ) - gban_watch = get_string("can_1").format(inline_mention(user), reason) - await ult.reply(gban_watch) - except Exception as er: - LOGS.exception(er) - - # greetings - elif get_welcome(ult.chat_id): - user = await ult.get_user() - chat = await ult.get_chat() - title = chat.title or "this chat" - count = ( - chat.participants_count - or (await ult.client.get_participants(chat, limit=0)).total - ) - mention = inline_mention(user) - name = user.first_name - fullname = get_display_name(user) - uu = user.username - username = f"@{uu}" if uu else mention - wel = get_welcome(ult.chat_id) - msgg = wel["welcome"] - med = wel["media"] or None - userid = user.id - msg = None - if msgg: - msg = msgg.format( - mention=mention, - group=title, - count=count, - name=name, - fullname=fullname, - username=username, - userid=userid, - ) - if wel.get("button"): - btn = create_tl_btn(wel["button"]) - await something(ult, msg, med, btn) - elif msg: - send = await ult.reply( - msg, - file=med, - ) - await asyncio.sleep(150) - await send.delete() - else: - await ult.reply(file=med) - elif (ult.user_left or ult.user_kicked) and get_goodbye(ult.chat_id): - user = await ult.get_user() - chat = await ult.get_chat() - title = chat.title or "this chat" - count = ( - chat.participants_count - or (await ult.client.get_participants(chat, limit=0)).total - ) - mention = inline_mention(user) - name = user.first_name - fullname = get_display_name(user) - uu = user.username - username = f"@{uu}" if uu else mention - wel = get_goodbye(ult.chat_id) - msgg = wel["goodbye"] - med = wel["media"] - userid = user.id - msg = None - if msgg: - msg = msgg.format( - mention=mention, - group=title, - count=count, - name=name, - fullname=fullname, - username=username, - userid=userid, - ) - if wel.get("button"): - btn = create_tl_btn(wel["button"]) - await something(ult, msg, med, btn) - elif msg: - send = await ult.reply( - msg, - file=med, - ) - await asyncio.sleep(150) - await send.delete() - else: - await ult.reply(file=med) - - -@ultroid_bot.on(events.NewMessage(incoming=True)) -async def chatBot_replies(e): - sender = await e.get_sender() - if not isinstance(sender, types.User) or sender.bot: - return - if check_echo(e.chat_id, e.sender_id): - try: - await e.respond(e) - except Exception as er: - LOGS.exception(er) - key = udB.get_key("CHATBOT_USERS") or {} - if e.text and key.get(e.chat_id) and sender.id in key[e.chat_id]: - msg = await get_chatbot_reply(e.message.message) - if msg: - sleep = udB.get_key("CHATBOT_SLEEP") or 1.5 - await asyncio.sleep(sleep) - await e.reply(msg) - chat = await e.get_chat() - if e.is_group and sender.username: - await uname_stuff(e.sender_id, sender.username, sender.first_name) - elif e.is_private and chat.username: - await uname_stuff(e.sender_id, chat.username, chat.first_name) - if detector and is_profan(e.chat_id) and e.text: - x, y = detector(e.text) - if y: - await e.delete() - - -@ultroid_bot.on(events.Raw(types.UpdateUserName)) -async def uname_change(e): - await uname_stuff(e.user_id, e.usernames[0] if e.usernames else None, e.first_name) - - -async def uname_stuff(id, uname, name): - if udB.get_key("USERNAME_LOG"): - old_ = udB.get_key("USERNAME_DB") or {} - old = old_.get(id) - # Ignore Name Logs - if old and old == uname: - return - if old and uname: - await asst.send_message( - LOG_CHANNEL, - get_string("can_2").format(old, uname), - ) - elif old: - await asst.send_message( - LOG_CHANNEL, - get_string("can_3").format(f"[{name}](tg://user?id={id})", old), - ) - elif uname: - await asst.send_message( - LOG_CHANNEL, - get_string("can_4").format(f"[{name}](tg://user?id={id})", uname), - ) - - old_[id] = uname - udB.set_key("USERNAME_DB", old_) diff --git a/plugins/_help.py b/plugins/_help.py deleted file mode 100644 index 9d7d0aaa01..0000000000 --- a/plugins/_help.py +++ /dev/null @@ -1,136 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from telethon.errors.rpcerrorlist import ( - BotInlineDisabledError, - BotMethodInvalidError, - BotResponseTimeoutError, -) -from telethon.tl.custom import Button - -from pyUltroid.dB._core import HELP, LIST -from pyUltroid.fns.tools import cmd_regex_replace - -from . import HNDLR, LOGS, OWNER_NAME, asst, get_string, inline_pic, udB, ultroid_cmd - -_main_help_menu = [ - [ - Button.inline(get_string("help_4"), data="uh_Official_"), - Button.inline(get_string("help_5"), data="uh_Addons_"), - ], - [ - Button.inline(get_string("help_6"), data="uh_VCBot_"), - Button.inline(get_string("help_7"), data="inlone"), - ], - [ - Button.inline(get_string("help_8"), data="ownr"), - Button.url( - get_string("help_9"), url=f"https://t.me/{asst.me.username}?start=set" - ), - ], - [Button.inline(get_string("help_10"), data="close")], -] - - -@ultroid_cmd(pattern="help( (.*)|$)") -async def _help(ult): - plug = ult.pattern_match.group(1).strip() - chat = await ult.get_chat() - if plug: - try: - if plug in HELP["Official"]: - output = f"**Plugin** - `{plug}`\n" - for i in HELP["Official"][plug]: - output += i - output += "\n© @TeamUltroid" - await ult.eor(output) - elif HELP.get("Addons") and plug in HELP["Addons"]: - output = f"**Plugin** - `{plug}`\n" - for i in HELP["Addons"][plug]: - output += i - output += "\n© @TeamUltroid" - await ult.eor(output) - elif HELP.get("VCBot") and plug in HELP["VCBot"]: - output = f"**Plugin** - `{plug}`\n" - for i in HELP["VCBot"][plug]: - output += i - output += "\n© @TeamUltroid" - await ult.eor(output) - else: - try: - x = get_string("help_11").format(plug) - for d in LIST[plug]: - x += HNDLR + d - x += "\n" - x += "\n© @TeamUltroid" - await ult.eor(x) - except BaseException: - file = None - compare_strings = [] - for file_name in LIST: - compare_strings.append(file_name) - value = LIST[file_name] - for j in value: - j = cmd_regex_replace(j) - compare_strings.append(j) - if j.strip() == plug: - file = file_name - break - if not file: - # the enter command/plugin name is not found - text = f"`{plug}` is not a valid plugin!" - best_match = None - for _ in compare_strings: - if plug in _ and not _.startswith("_"): - best_match = _ - break - if best_match: - text += f"\nDid you mean `{best_match}`?" - return await ult.eor(text) - output = f"**Command** `{plug}` **found in plugin** - `{file}`\n" - if file in HELP["Official"]: - for i in HELP["Official"][file]: - output += i - elif HELP.get("Addons") and file in HELP["Addons"]: - for i in HELP["Addons"][file]: - output += i - elif HELP.get("VCBot") and file in HELP["VCBot"]: - for i in HELP["VCBot"][file]: - output += i - output += "\n© @TeamUltroid" - await ult.eor(output) - except BaseException as er: - LOGS.exception(er) - await ult.eor("Error 🤔 occured.") - else: - try: - results = await ult.client.inline_query(asst.me.username, "ultd") - except BotMethodInvalidError: - z = [] - for x in LIST.values(): - z.extend(x) - cmd = len(z) + 10 - if udB.get_key("MANAGER") and udB.get_key("DUAL_HNDLR") == "/": - _main_help_menu[2:3] = [[Button.inline("• Manager Help •", "mngbtn")]] - return await ult.reply( - get_string("inline_4").format( - OWNER_NAME, - len(HELP["Official"]), - len(HELP["Addons"] if "Addons" in HELP else []), - cmd, - ), - file=inline_pic(), - buttons=_main_help_menu, - ) - except BotResponseTimeoutError: - return await ult.eor( - get_string("help_2").format(HNDLR), - ) - except BotInlineDisabledError: - return await ult.eor(get_string("help_3")) - await results[0].click(chat.id, reply_to=ult.reply_to_msg_id, hide_via=True) - await ult.delete() diff --git a/plugins/_inline.py b/plugins/_inline.py deleted file mode 100644 index 0a75219ddf..0000000000 --- a/plugins/_inline.py +++ /dev/null @@ -1,451 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import re -import time -from datetime import datetime -from os import remove - -from git import Repo -from telethon import Button -from telethon.tl.types import InputWebDocument, Message -from telethon.utils import resolve_bot_file_id - -from pyUltroid._misc._assistant import callback, in_pattern -from pyUltroid.dB._core import HELP, LIST -from pyUltroid.fns.helper import gen_chlog, time_formatter, updater -from pyUltroid.fns.misc import split_list - -from . import ( - HNDLR, - LOGS, - OWNER_NAME, - InlinePlugin, - asst, - get_string, - inline_pic, - split_list, - start_time, - udB, -) -from ._help import _main_help_menu - -# ================================================# - -helps = get_string("inline_1") - -add_ons = udB.get_key("ADDONS") - -zhelps = get_string("inline_3") if add_ons is False else get_string("inline_2") -PLUGINS = HELP.get("Official", []) -ADDONS = HELP.get("Addons", []) -upage = 0 -# ============================================# - -# --------------------BUTTONS--------------------# - -SUP_BUTTONS = [ - [ - Button.url("• Repo •", url="https://github.com/TeamUltroid/Ultroid"), - Button.url("• Support •", url="t.me/UltroidSupportChat"), - ], -] - -# --------------------BUTTONS--------------------# - - -@in_pattern(owner=True, func=lambda x: not x.text) -async def inline_alive(o): - TLINK = inline_pic() or "https://graph.org/file/74d6259983e0642923fdb.jpg" - MSG = "• **Ultroid Userbot •**" - WEB0 = InputWebDocument( - "https://graph.org/file/acd4f5d61369f74c5e7a7.jpg", 0, "image/jpg", [] - ) - RES = [ - await o.builder.article( - type="photo", - text=MSG, - include_media=True, - buttons=SUP_BUTTONS, - title="Ultroid Userbot", - description="Userbot | Telethon", - url=TLINK, - thumb=WEB0, - content=InputWebDocument(TLINK, 0, "image/jpg", []), - ) - ] - await o.answer( - RES, - private=True, - cache_time=300, - switch_pm="👥 ULTROID PORTAL", - switch_pm_param="start", - ) - - -@in_pattern("ultd", owner=True) -async def inline_handler(event): - z = [] - for x in LIST.values(): - z.extend(x) - text = get_string("inline_4").format( - OWNER_NAME, - len(HELP.get("Official", [])), - len(HELP.get("Addons", [])), - len(z), - ) - if inline_pic(): - result = await event.builder.photo( - file=inline_pic(), - link_preview=False, - text=text, - buttons=_main_help_menu, - ) - else: - result = await event.builder.article( - title="Ultroid Help Menu", text=text, buttons=_main_help_menu - ) - await event.answer([result], private=True, cache_time=300, gallery=True) - - -@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" - result = await event.builder.article( - title="Paste", - text="Pasted to Spacebin 🌌", - buttons=[ - [ - Button.url("SpaceBin", url=link), - Button.url("Raw", url=raw), - ], - ], - ) - await event.answer([result]) - - -@callback("ownr", owner=True) -async def setting(event): - z = [] - for x in LIST.values(): - z.extend(x) - await event.edit( - get_string("inline_4").format( - OWNER_NAME, - len(HELP.get("Official", [])), - len(HELP.get("Addons", [])), - len(z), - ), - file=inline_pic(), - link_preview=False, - buttons=[ - [ - Button.inline("•Pɪɴɢ•", data="pkng"), - Button.inline("•Uᴘᴛɪᴍᴇ•", data="upp"), - ], - [ - Button.inline("•Stats•", data="alive"), - Button.inline("•Uᴘᴅᴀᴛᴇ•", data="doupdate"), - ], - [Button.inline("« Bᴀᴄᴋ", data="open")], - ], - ) - - -_strings = {"Official": helps, "Addons": zhelps, "VCBot": get_string("inline_6")} - - -@callback(re.compile("uh_(.*)"), owner=True) -async def help_func(ult): - key, count = ult.data_match.group(1).decode("utf-8").split("_") - if key == "VCBot" and HELP.get("VCBot") is None: - return await ult.answer(get_string("help_12"), alert=True) - elif key == "Addons" and HELP.get("Addons") is None: - return await ult.answer(get_string("help_13").format(HNDLR), alert=True) - if "|" in count: - _, count = count.split("|") - count = int(count) if count else 0 - text = _strings.get(key, "").format(OWNER_NAME, len(HELP.get(key))) - await ult.edit(text, buttons=page_num(count, key), link_preview=False) - - -@callback(re.compile("uplugin_(.*)"), owner=True) -async def uptd_plugin(event): - key, file = event.data_match.group(1).decode("utf-8").split("_") - index = None - if "|" in file: - file, index = file.split("|") - key_ = HELP.get(key, []) - hel_p = f"Plugin Name - `{file}`\n" - help_ = "" - try: - for i in key_[file]: - help_ += i - except BaseException: - if file in LIST: - help_ = get_string("help_11").format(file) - for d in LIST[file]: - help_ += HNDLR + d - help_ += "\n" - if not help_: - help_ = f"{file} has no Detailed Help!" - help_ += "\n© @TeamUltroid" - buttons = [] - if inline_pic(): - data = f"sndplug_{key}_{file}" - if index is not None: - data += f"|{index}" - buttons.append( - [ - Button.inline( - "« Sᴇɴᴅ Pʟᴜɢɪɴ »", - data=data, - ) - ] - ) - data = f"uh_{key}_" - if index is not None: - data += f"|{index}" - buttons.append( - [ - Button.inline("« Bᴀᴄᴋ", data=data), - ] - ) - try: - await event.edit(help_, buttons=buttons) - except Exception as er: - LOGS.exception(er) - help = f"Do `{HNDLR}help {key}` to get list of commands." - await event.edit(help, buttons=buttons) - - -@callback(data="doupdate", owner=True) -async def _(event): - if not await updater(): - return await event.answer(get_string("inline_9"), cache_time=0, alert=True) - if not inline_pic(): - return await event.answer(f"Do '{HNDLR}update' to update..") - repo = Repo.init() - changelog, tl_chnglog = await gen_chlog( - repo, f"HEAD..upstream/{repo.active_branch}" - ) - changelog_str = changelog + "\n\n" + get_string("inline_8") - if len(changelog_str) > 1024: - await event.edit(get_string("upd_4")) - with open("ultroid_updates.txt", "w+") as file: - file.write(tl_chnglog) - await event.edit( - get_string("upd_5"), - file="ultroid_updates.txt", - buttons=[ - [Button.inline("• Uᴘᴅᴀᴛᴇ Nᴏᴡ •", data="updatenow")], - [Button.inline("« Bᴀᴄᴋ", data="ownr")], - ], - ) - remove("ultroid_updates.txt") - else: - await event.edit( - changelog_str, - buttons=[ - [Button.inline("Update Now", data="updatenow")], - [Button.inline("« Bᴀᴄᴋ", data="ownr")], - ], - parse_mode="html", - ) - - -@callback(data="pkng", owner=True) -async def _(event): - start = datetime.now() - end = datetime.now() - ms = (end - start).microseconds - pin = f"🌋Pɪɴɢ = {ms} microseconds" - await event.answer(pin, cache_time=0, alert=True) - - -@callback(data="upp", owner=True) -async def _(event): - uptime = time_formatter((time.time() - start_time) * 1000) - pin = f"🙋Uᴘᴛɪᴍᴇ = {uptime}" - await event.answer(pin, cache_time=0, alert=True) - - -@callback(data="inlone", owner=True) -async def _(e): - _InButtons = [ - Button.switch_inline(_, query=InlinePlugin[_], same_peer=True) - for _ in list(InlinePlugin.keys()) - ] - InButtons = split_list(_InButtons, 2) - - button = InButtons.copy() - button.append( - [ - Button.inline("« Bᴀᴄᴋ", data="open"), - ], - ) - await e.edit(buttons=button, link_preview=False) - - -@callback(data="open", owner=True) -async def opner(event): - z = [] - for x in LIST.values(): - z.extend(x) - await event.edit( - get_string("inline_4").format( - OWNER_NAME, - len(HELP.get("Official", [])), - len(HELP.get("Addons", [])), - len(z), - ), - buttons=_main_help_menu, - link_preview=False, - ) - - -@callback(data="close", owner=True) -async def on_plug_in_callback_query_handler(event): - await event.edit( - get_string("inline_5"), - buttons=Button.inline("Oᴘᴇɴ Aɢᴀɪɴ", data="open"), - ) - - -def page_num(index, key): - rows = udB.get_key("HELP_ROWS") or 5 - cols = udB.get_key("HELP_COLUMNS") or 2 - loaded = HELP.get(key, []) - emoji = udB.get_key("EMOJI_IN_HELP") or "✘" - List = [ - Button.inline(f"{emoji} {x} {emoji}", data=f"uplugin_{key}_{x}|{index}") - for x in sorted(loaded) - ] - all_ = split_list(List, cols) - fl_ = split_list(all_, rows) - try: - new_ = fl_[index] - except IndexError: - new_ = fl_[0] if fl_ else [] - index = 0 - if index == 0 and len(fl_) == 1: - new_.append([Button.inline("« Bᴀᴄᴋ »", data="open")]) - else: - new_.append( - [ - Button.inline( - "« Pʀᴇᴠɪᴏᴜs", - data=f"uh_{key}_{index-1}", - ), - Button.inline("« Bᴀᴄᴋ »", data="open"), - Button.inline( - "Nᴇxᴛ »", - data=f"uh_{key}_{index+1}", - ), - ] - ) - return new_ - - -# --------------------------------------------------------------------------------- # - - -STUFF = {} - - -@in_pattern("stf(.*)", owner=True) -async def ibuild(e): - n = e.pattern_match.group(1).strip() - builder = e.builder - if not (n and n.isdigit()): - return - ok = STUFF.get(int(n)) - txt = ok.get("msg") - pic = ok.get("media") - btn = ok.get("button") - if not (pic or txt): - txt = "Hey!" - if pic: - try: - include_media = True - mime_type, _pic = None, None - cont, results = None, None - try: - ext = str(pic).split(".")[-1].lower() - except BaseException: - ext = None - if ext in ["img", "jpg", "png"]: - _type = "photo" - mime_type = "image/jpg" - elif ext in ["mp4", "mkv", "gif"]: - mime_type = "video/mp4" - _type = "gif" - else: - try: - if "telethon.tl.types" in str(type(pic)): - _pic = pic - else: - _pic = resolve_bot_file_id(pic) - except BaseException: - pass - if _pic: - results = [ - await builder.document( - _pic, - title="Ultroid Op", - text=txt, - description="@TeamUltroid", - buttons=btn, - link_preview=False, - ) - ] - else: - _type = "article" - include_media = False - if not results: - if include_media: - cont = InputWebDocument(pic, 0, mime_type, []) - results = [ - await builder.article( - title="Ultroid Op", - type=_type, - text=txt, - description="@TeamUltroid", - include_media=include_media, - buttons=btn, - thumb=cont, - content=cont, - link_preview=False, - ) - ] - return await e.answer(results) - except Exception as er: - LOGS.exception(er) - result = [ - await builder.article("Ultroid Op", text=txt, link_preview=False, buttons=btn) - ] - await e.answer(result) - - -async def something(e, msg, media, button, reply=True, chat=None): - if e.client._bot: - return await e.reply(msg, file=media, buttons=button) - num = len(STUFF) + 1 - STUFF.update({num: {"msg": msg, "media": media, "button": button}}) - try: - res = await e.client.inline_query(asst.me.username, f"stf{num}") - return await res[0].click( - chat or e.chat_id, - reply_to=bool(isinstance(e, Message) and reply), - hide_via=True, - silent=True, - ) - - except Exception as er: - LOGS.exception(er) diff --git a/plugins/_ultroid.py b/plugins/_ultroid.py deleted file mode 100644 index d2cd7bc6c2..0000000000 --- a/plugins/_ultroid.py +++ /dev/null @@ -1,66 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from telethon.errors import ( - BotMethodInvalidError, - ChatSendInlineForbiddenError, - ChatSendMediaForbiddenError, -) - -from . import LOG_CHANNEL, LOGS, Button, asst, eor, get_string, ultroid_cmd - -REPOMSG = """ -• **ULTROID USERBOT** •\n -• Repo - [Click Here](https://github.com/TeamUltroid/Ultroid) -• Addons - [Click Here](https://github.com/TeamUltroid/UltroidAddons) -• Support - @UltroidSupportChat -""" - -RP_BUTTONS = [ - [ - Button.url(get_string("bot_3"), "https://github.com/TeamUltroid/Ultroid"), - Button.url("Addons", "https://github.com/TeamUltroid/UltroidAddons"), - ], - [Button.url("Support Group", "t.me/UltroidSupportChat")], -] - -ULTSTRING = """🎇 **Thanks for Deploying Ultroid Userbot!** - -• Here, are the Some Basic stuff from, where you can Know, about its Usage.""" - - -@ultroid_cmd( - pattern="repo$", - manager=True, -) -async def repify(e): - try: - q = await e.client.inline_query(asst.me.username, "") - await q[0].click(e.chat_id) - return await e.delete() - except ( - ChatSendInlineForbiddenError, - ChatSendMediaForbiddenError, - BotMethodInvalidError, - ): - pass - except Exception as er: - LOGS.info(f"Error while repo command : {str(er)}") - await e.eor(REPOMSG) - - -@ultroid_cmd(pattern="ultroid$") -async def useUltroid(rs): - button = Button.inline("Start >>", "initft_2") - msg = await asst.send_message( - LOG_CHANNEL, - ULTSTRING, - file="https://graph.org/file/54a917cc9dbb94733ea5f.jpg", - buttons=button, - ) - if not (rs.chat_id == LOG_CHANNEL and rs.client._bot): - await eor(rs, f"**[Click Here]({msg.message_link})**") diff --git a/plugins/_wspr.py b/plugins/_wspr.py deleted file mode 100644 index 19323558ca..0000000000 --- a/plugins/_wspr.py +++ /dev/null @@ -1,204 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import re - -from telethon import Button -from telethon.errors.rpcerrorlist import ( - BotInlineDisabledError, - BotResponseTimeoutError, - MessageNotModifiedError, -) -from telethon.tl import types -from telethon.tl.functions.users import GetFullUserRequest as gu - -from . import ( - HNDLR, - LOGS, - asst, - callback, - get_string, - in_pattern, - inline_mention, - ultroid_bot, - ultroid_cmd, -) - -buddhhu = {} - - -@ultroid_cmd( - pattern="wspr( (.*)|$)", -) -async def _(e): - if e.reply_to_msg_id: - okk = await e.get_reply_message() - put = f"@{okk.sender.username}" if okk.sender.username else okk.sender_id - else: - put = e.pattern_match.group(1).strip() - if put: - try: - results = await e.client.inline_query(asst.me.username, f"msg {put}") - except BotResponseTimeoutError: - return await e.eor( - get_string("help_2").format(HNDLR), - ) - except BotInlineDisabledError: - return await e.eor(get_string("help_3")) - await results[0].click(e.chat_id, reply_to=e.reply_to_msg_id, hide_via=True) - return await e.delete() - await e.eor(get_string("wspr_3")) - - -@in_pattern("wspr", owner=True) -async def _(e): - iuser = e.query.user_id - zzz = e.text.split(maxsplit=2) - try: - query = zzz[1] - if query.isdigit(): - query = int(query) - logi = await ultroid_bot.get_entity(query) - if not isinstance(logi, types.User): - raise ValueError("Invalid Username.") - except IndexError: - sur = await e.builder.article( - title="Give Username", - description="You Didn't Type Username or id.", - text="You Didn't Type Username or id.", - ) - return await e.answer([sur]) - except ValueError as er: - LOGS.exception(er) - sur = await e.builder.article( - title="User Not Found", - description="Make sure username or id is correct.", - text="Make sure username or id is correct.", - ) - return await e.answer([sur]) - try: - desc = zzz[2] - except IndexError: - sur = await e.builder.article( - title="Type ur msg", text="You Didn't Type Your Msg" - ) - return await e.answer([sur]) - button = [ - [ - Button.inline("Secret Msg", data=f"dd_{e.id}"), - Button.inline("Delete Msg", data=f"del_{e.id}"), - ], - [ - Button.switch_inline( - "New", query=f"wspr {logi.username or logi.id}", same_peer=True - ) - ], - ] - us = logi.username or logi.first_name - sur = await e.builder.article( - title=logi.first_name, - description=desc, - text=get_string("wspr_1").format(us), - buttons=button, - ) - buddhhu.update({e.id: [logi.id, iuser, desc]}) - await e.answer([sur]) - - -@in_pattern("msg", owner=True) -async def _(e): - zzz = e.text.split(maxsplit=1) - desc = "Touch me" - try: - query = zzz[1] - if query.isdigit(): - query = int(query) - logi = await ultroid_bot(gu(id=query)) - user = logi.users[0] - mention = inline_mention(user) - x = user.status - if isinstance(x, types.UserStatusOnline): - status = "Online" - elif isinstance(x, types.UserStatusOffline): - status = "Offline" - elif isinstance(x, types.UserStatusRecently): - status = "Last Seen Recently" - elif isinstance(x, types.UserStatusLastMonth): - status = "Last seen months ago" - elif isinstance(x, types.UserStatusLastWeek): - status = "Last seen weeks ago" - else: - status = "Can't Tell" - text = f"**Name:** `{user.first_name}`\n" - text += f"**Id:** `{user.id}`\n" - if user.username: - text += f"**Username:** `{user.username}`\n" - url = f"https://t.me/{user.username}" - else: - text += f"**Mention:** `{mention}`\n" - url = f"tg://user?id={user.id}" - text += f"**Status:** `{status}`\n" - text += f"**About:** `{logi.full_user.about}`" - button = [ - Button.url("Private", url=url), - Button.switch_inline( - "Secret msg", - query=f"wspr {query} Hello 👋", - same_peer=True, - ), - ] - sur = e.builder.article( - title=user.first_name, - description=desc, - text=text, - buttons=button, - ) - except IndexError: - sur = e.builder.article( - title="Give Username", - description="You Didn't Type Username or id.", - text="You Didn't Type Username or id.", - ) - except BaseException as er: - LOGS.exception(er) - name = get_string("wspr_4").format(query) - sur = e.builder.article( - title=name, - text=name, - ) - - await e.answer([sur]) - - -@callback( - re.compile( - "dd_(.*)", - ), -) -async def _(e): - ids = int(e.pattern_match.group(1).strip().decode("UTF-8")) - if buddhhu.get(ids): - if e.sender_id in buddhhu[ids]: - await e.answer(buddhhu[ids][-1], alert=True) - else: - await e.answer("Not For You", alert=True) - else: - await e.answer(get_string("wspr_2"), alert=True) - - -@callback(re.compile("del_(.*)")) -async def _(e): - ids = int(e.pattern_match.group(1).strip().decode("UTF-8")) - if buddhhu.get(ids): - if e.sender_id in buddhhu[ids]: - buddhhu.pop(ids) - try: - await e.edit(get_string("wspr_2")) - except MessageNotModifiedError: - pass - else: - await e.answer(get_string("wspr_5"), alert=True) diff --git a/plugins/antiflood.py b/plugins/antiflood.py deleted file mode 100644 index 4a8cd3766c..0000000000 --- a/plugins/antiflood.py +++ /dev/null @@ -1,121 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_antiflood") - - -import re - -from telethon.events import NewMessage as NewMsg - -from pyUltroid.dB import DEVLIST -from pyUltroid.dB.antiflood_db import get_flood, get_flood_limit, rem_flood, set_flood -from pyUltroid.fns.admins import admin_check - -from . import Button, Redis, asst, callback, eod, get_string, ultroid_bot, ultroid_cmd - -_check_flood = {} - -if Redis("ANTIFLOOD"): - - @ultroid_bot.on( - NewMsg( - chats=list(get_flood().keys()), - ), - ) - async def flood_checm(event): - count = 1 - chat = (await event.get_chat()).title - if event.chat_id in _check_flood.keys(): - if event.sender_id == list(_check_flood[event.chat_id].keys())[0]: - count = _check_flood[event.chat_id][event.sender_id] - _check_flood[event.chat_id] = {event.sender_id: count + 1} - else: - _check_flood[event.chat_id] = {event.sender_id: count} - else: - _check_flood[event.chat_id] = {event.sender_id: count} - if await admin_check(event, silent=True) or getattr(event.sender, "bot", None): - return - if event.sender_id in DEVLIST: - return - if _check_flood[event.chat_id][event.sender_id] >= int( - get_flood_limit(event.chat_id) - ): - try: - name = event.sender.first_name - await event.client.edit_permissions( - event.chat_id, event.sender_id, send_messages=False - ) - del _check_flood[event.chat_id] - await event.reply(f"#AntiFlood\n\n{get_string('antiflood_3')}") - await asst.send_message( - int(Redis("LOG_CHANNEL")), - f"#Antiflood\n\n`Muted `[{name}](tg://user?id={event.sender_id})` in {chat}`", - buttons=Button.inline( - "Unmute", data=f"anti_{event.sender_id}_{event.chat_id}" - ), - ) - except BaseException: - pass - - -@callback( - re.compile( - "anti_(.*)", - ), -) -async def unmuting(e): - ino = (e.data_match.group(1)).decode("UTF-8").split("_") - user = int(ino[0]) - chat = int(ino[1]) - user_name = (await ultroid_bot.get_entity(user)).first_name - chat_title = (await ultroid_bot.get_entity(chat)).title - await ultroid_bot.edit_permissions(chat, user, send_messages=True) - await e.edit( - f"#Antiflood\n\n`Unmuted `[{user_name}](tg://user?id={user})` in {chat_title}`" - ) - - -@ultroid_cmd( - pattern="setflood ?(\\d+)", - admins_only=True, -) -async def setflood(e): - input_ = e.pattern_match.group(1).strip() - if not input_: - return await e.eor("`What?`", time=5) - if not input_.isdigit(): - return await e.eor(get_string("com_3"), time=5) - if m := set_flood(e.chat_id, input_): - return await eod(e, get_string("antiflood_4").format(input_)) - - -@ultroid_cmd( - pattern="remflood$", - admins_only=True, -) -async def remove_flood(e): - hmm = rem_flood(e.chat_id) - try: - del _check_flood[e.chat_id] - except BaseException: - pass - if hmm: - return await e.eor(get_string("antiflood_1"), time=5) - await e.eor(get_string("antiflood_2"), time=5) - - -@ultroid_cmd( - pattern="getflood$", - admins_only=True, -) -async def getflood(e): - if ok := get_flood_limit(e.chat_id): - return await e.eor(get_string("antiflood_5").format(ok), time=5) - await e.eor(get_string("antiflood_2"), time=5) diff --git a/plugins/asstcmd.py b/plugins/asstcmd.py deleted file mode 100644 index 9156bf1672..0000000000 --- a/plugins/asstcmd.py +++ /dev/null @@ -1,107 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_asstcmd") - -import os - -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 - - -@ultroid_cmd(pattern="addcmd( (.*)|$)") -async def ac(e): - wrd = (e.pattern_match.group(1).strip()).lower() - wt = await e.get_reply_message() - if not (wt and wrd): - return await e.eor(get_string("asstcmd_1"), time=5) - if "/" in wrd: - wrd = wrd.replace("/", "") - btn = format_btn(wt.buttons) if wt.buttons else None - if wt and wt.media: - wut = mediainfo(wt.media) - if wut.startswith(("pic", "gif")): - dl = await e.client.download_media(wt.media) - variable = 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 e.client.download_media(wt.media) - variable = uf(dl) - os.remove(dl) - m = f"https://graph.org{variable[0]}" - else: - m = utils.pack_bot_file_id(wt.media) - if wt.text: - txt = wt.text - if not btn: - txt, btn = get_msg_button(wt.text) - add_cmd(wrd, txt, m, btn) - else: - add_cmd(wrd, None, m, btn) - else: - txt = wt.text - if not btn: - txt, btn = get_msg_button(wt.text) - add_cmd(wrd, txt, None, btn) - asst.add_handler( - astcmds, - events.NewMessage( - func=lambda x: x.text.startswith("/") and x.text[1:] in list(list_cmds()) - ), - ) - await e.eor(get_string("asstcmd_4").format(wrd)) - - -@ultroid_cmd(pattern="remcmd( (.*)|$)") -async def rc(e): - wrd = (e.pattern_match.group(1).strip()).lower() - if not wrd: - return await e.eor(get_string("asstcmd_2"), time=5) - wrd = wrd.replace("/", "") - rem_cmd(wrd) - await e.eor(get_string("asstcmd_3").format(wrd)) - - -@ultroid_cmd(pattern="listcmd$") -async def lscmd(e): - if list_cmds(): - ok = get_string("asstcmd_6") - for x in list_cmds(): - ok += f"/{x}" + "\n" - return await e.eor(ok) - return await e.eor(get_string("asstcmd_5")) - - -async def astcmds(e): - xx = (e.text.replace("/", "")).lower().split()[0] - if cmd_reply(xx): - msg, media, bt = cmd_reply(xx) - if bt: - bt = create_tl_btn(bt) - await e.reply(msg, file=media, buttons=bt) - - -if udB.get_key("ASST_CMDS"): - asst.add_handler( - astcmds, - events.NewMessage( - func=lambda x: x.text.startswith("/") and x.text[1:] in list(list_cmds()) - ), - ) diff --git a/plugins/audiotools.py b/plugins/audiotools.py deleted file mode 100644 index ab87e86e90..0000000000 --- a/plugins/audiotools.py +++ /dev/null @@ -1,160 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -import os -import time -from datetime import datetime as dt - -from pyUltroid.fns.tools import set_attributes - -from . import ( - LOGS, - ULTConfig, - bash, - downloader, - eod, - eor, - genss, - get_help, - get_string, - humanbytes, - mediainfo, - stdr, - time_formatter, - ultroid_cmd, - uploader, -) - -__doc__ = get_help("help_audiotools") - - -@ultroid_cmd(pattern="makevoice$") -async def vnc(e): - if not e.reply_to: - return await eod(e, get_string("audiotools_1")) - r = await e.get_reply_message() - if not mediainfo(r.media).startswith(("audio", "video")): - return await eod(e, get_string("spcltool_1")) - xxx = await e.eor(get_string("com_1")) - file, _ = await e.client.fast_downloader( - r.document, - ) - await xxx.edit(get_string("audiotools_2")) - await bash( - f"ffmpeg -i '{file.name}' -map 0:a -codec:a libopus -b:a 100k -vbr on out.opus" - ) - try: - await e.client.send_message( - e.chat_id, file="out.opus", force_document=False, reply_to=r - ) - except Exception as er: - LOGS.exception(er) - return await xxx.edit("`Failed to convert in Voice...`") - await xxx.delete() - os.remove(file.name) - os.remove("out.opus") - - -@ultroid_cmd(pattern="atrim( (.*)|$)") -async def trim_aud(e): - sec = e.pattern_match.group(1).strip() - if not sec or "-" not in sec: - return await eod(e, get_string("audiotools_3")) - a, b = sec.split("-") - if int(a) >= int(b): - return await eod(e, get_string("audiotools_4")) - vido = await e.get_reply_message() - if vido and vido.media and mediainfo(vido.media).startswith(("video", "audio")): - if hasattr(vido.media, "document"): - vfile = vido.media.document - name = vido.file.name - else: - vfile = vido.media - name = "" - if not name: - name = dt.now().isoformat("_", "seconds") + ".mp4" - xxx = await e.eor(get_string("audiotools_5")) - c_time = time.time() - file = await downloader( - f"resources/downloads/{name}", - vfile, - xxx, - c_time, - f"Downloading {name}...", - ) - - o_size = os.path.getsize(file.name) - d_time = time.time() - diff = time_formatter((d_time - c_time) * 1000) - file_name = (file.name).split("/")[-1] - out = file_name.replace(file_name.split(".")[-1], "_trimmed.aac") - if int(b) > int(await genss(file.name)): - os.remove(file.name) - return await eod(xxx, get_string("audiotools_6")) - ss, dd = stdr(int(a)), stdr(int(b)) - xxx = await xxx.edit( - f"Downloaded `{file.name}` of `{humanbytes(o_size)}` in `{diff}`.\n\nNow Trimming Audio from `{ss}` to `{dd}`..." - ) - cmd = f'ffmpeg -i "{file.name}" -preset ultrafast -ss {ss} -to {dd} -vn -acodec copy "{out}" -y' - await bash(cmd) - os.remove(file.name) - f_time = time.time() - mmmm = await uploader(out, out, f_time, xxx, f"Uploading {out}...") - attributes = await set_attributes(out) - - caption = get_string("audiotools_7").format(ss, dd) - await e.client.send_file( - e.chat_id, - mmmm, - thumb=ULTConfig.thumb, - caption=caption, - attributes=attributes, - force_document=False, - reply_to=e.reply_to_msg_id, - ) - await xxx.delete() - else: - await e.eor(get_string("audiotools_1"), time=5) - - -@ultroid_cmd(pattern="extractaudio$") -async def ex_aud(e): - reply = await e.get_reply_message() - if not (reply and reply.media and mediainfo(reply.media).startswith("video")): - return await e.eor(get_string("audiotools_8")) - name = reply.file.name or "video.mp4" - vfile = reply.media.document - msg = await e.eor(get_string("com_1")) - c_time = time.time() - file = await downloader( - f"resources/downloads/{name}", - vfile, - msg, - c_time, - f"Downloading {name}...", - ) - - out_file = f"{file.name}.aac" - cmd = f"ffmpeg -i {file.name} -vn -acodec copy {out_file}" - o, err = await bash(cmd) - os.remove(file.name) - attributes = await set_attributes(out_file) - - f_time = time.time() - try: - fo = await uploader(out_file, out_file, f_time, msg, f"Uploading {out_file}...") - - except FileNotFoundError: - return await eor(msg, get_string("audiotools_9")) - await e.reply( - get_string("audiotools_10"), - file=fo, - thumb=ULTConfig.thumb, - attributes=attributes, - ) - await msg.delete() diff --git a/plugins/autoban.py b/plugins/autoban.py deleted file mode 100644 index 0c3e2e3a37..0000000000 --- a/plugins/autoban.py +++ /dev/null @@ -1,59 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_autoban") - -from telethon import events - -from pyUltroid.dB.base import KeyManager - -from . import LOGS, asst, ultroid_bot, ultroid_cmd - -Keym = KeyManager("DND_CHATS", cast=list) - - -def join_func(e): - return e.user_joined and Keym.contains(e.chat_id) - - -async def dnd_func(event): - for user in event.users: - try: - await (await event.client.kick_participant(event.chat_id, user)).delete() - except Exception as ex: - LOGS.error("Error in DND:") - LOGS.exception(ex) - await event.delete() - - -@ultroid_cmd( - pattern="autokick (on|off)$", - admins_only=True, - manager=True, - require="ban_users", - fullsudo=True, -) -async def _(event): - match = event.pattern_match.group(1) - if match == "on": - if Keym.contains(event.chat_id): - return await event.eor("`Chat already in do not disturb mode.`", time=3) - Keym.add(event.chat_id) - event.client.add_handler(dnd_func, events.ChatAction(func=join_func)) - await event.eor("`Do not disturb mode activated for this chat.`", time=3) - elif match == "off": - if not Keym.contains(event.chat_id): - return await event.eor("`Chat is not in do not disturb mode.`", time=3) - Keym.remove(event.chat_id) - await event.eor("`Do not disturb mode deactivated for this chat.`", time=3) - - -if Keym.get(): - ultroid_bot.add_handler(dnd_func, events.ChatAction(func=join_func)) - asst.add_handler(dnd_func, events.ChatAction(func=join_func)) diff --git a/plugins/autopic.py b/plugins/autopic.py deleted file mode 100644 index a3ca45231b..0000000000 --- a/plugins/autopic.py +++ /dev/null @@ -1,84 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -import asyncio -import os -import random -from random import shuffle - -from telethon.tl.functions.photos import UploadProfilePhotoRequest - -from pyUltroid.fns.helper import download_file -from pyUltroid.fns.tools import get_google_images - -from . import LOGS, get_help, get_string, udB, ultroid_bot, ultroid_cmd - -__doc__ = get_help("help_autopic") - - -@ultroid_cmd(pattern="autopic( (.*)|$)") -async def autopic(e): - search = e.pattern_match.group(1).strip() - if udB.get_key("AUTOPIC") and not search: - udB.del_key("AUTOPIC") - return await e.eor(get_string("autopic_5")) - if not search: - return await e.eor(get_string("autopic_1"), time=5) - e = await e.eor(get_string("com_1")) - gi = googleimagesdownload() - args = { - "keywords": search, - "limit": 50, - "format": "jpg", - "output_directory": "./resources/downloads/", - } - try: - pth = await gi.download(args) - ok = pth[0][search] - except Exception as er: - LOGS.exception(er) - return await e.eor(str(er)) - if not ok: - return await e.eor(get_string("autopic_2").format(search), time=5) - await e.eor(get_string("autopic_3").format(search)) - udB.set_key("AUTOPIC", search) - SLEEP_TIME = udB.get_key("SLEEP_TIME") or 1221 - while True: - for lie in ok: - if udB.get_key("AUTOPIC") != search: - return - file = await e.client.upload_file(lie) - await e.client(UploadProfilePhotoRequest(file)) - await asyncio.sleep(SLEEP_TIME) - shuffle(ok) - - -if search := udB.get_key("AUTOPIC"): - images = {} - sleep = udB.get_key("SLEEP_TIME") or 1221 - - async def autopic_func(): - search = udB.get_key("AUTOPIC") - if images.get(search) is None: - images[search] = await get_google_images(search) - if not images.get(search): - return - img = random.choice(images[search]) - filee = await download_file(img["original"], "resources/downloads/autopic.jpg") - file = await ultroid_bot.upload_file(filee) - await ultroid_bot(UploadProfilePhotoRequest(file)) - os.remove(filee) - - try: - from apscheduler.schedulers.asyncio import AsyncIOScheduler - - schedule = AsyncIOScheduler() - schedule.add_job(autopic_func, "interval", seconds=sleep) - schedule.start() - except ModuleNotFoundError as er: - LOGS.error(f"autopic: '{er.name}' not installed.") diff --git a/plugins/beautify.py b/plugins/beautify.py deleted file mode 100644 index 939da5c256..0000000000 --- a/plugins/beautify.py +++ /dev/null @@ -1,136 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_beautify") - - -import os -import random - -from telethon.utils import get_display_name - -from . import Carbon, ultroid_cmd, get_string, inline_mention - -_colorspath = "resources/colorlist.txt" - -if os.path.exists(_colorspath): - with open(_colorspath, "r") as f: - all_col = f.read().split() -else: - all_col = [] - - -@ultroid_cmd( - pattern="(rc|c)arbon", -) -async def cr_bn(event): - xxxx = await event.eor(get_string("com_1")) - te = event.pattern_match.group(1) - col = random.choice(all_col) if te[0] == "r" else "White" - if event.reply_to_msg_id: - temp = await event.get_reply_message() - if temp.media: - b = await event.client.download_media(temp) - with open(b) as a: - code = a.read() - os.remove(b) - else: - code = temp.message - else: - try: - code = event.text.split(" ", maxsplit=1)[1] - except IndexError: - return await xxxx.eor(get_string("carbon_2")) - xx = await Carbon(code=code, file_name="ultroid_carbon", backgroundColor=col) - if isinstance(xx, dict): - await xxxx.edit(f"`{xx}`") - return - await xxxx.delete() - await event.reply( - f"Carbonised by {inline_mention(event.sender)}", - file=xx, - ) - - -@ultroid_cmd( - pattern="ccarbon( (.*)|$)", -) -async def crbn(event): - match = event.pattern_match.group(1).strip() - if not match: - return await event.eor(get_string("carbon_3")) - msg = await event.eor(get_string("com_1")) - if event.reply_to_msg_id: - temp = await event.get_reply_message() - if temp.media: - b = await event.client.download_media(temp) - with open(b) as a: - code = a.read() - os.remove(b) - else: - code = temp.message - else: - try: - match = match.split(" ", maxsplit=1) - code = match[1] - match = match[0] - except IndexError: - return await msg.eor(get_string("carbon_2")) - xx = await Carbon(code=code, backgroundColor=match) - await msg.delete() - await event.reply( - f"Carbonised by {inline_mention(event.sender)}", - file=xx, - ) - - -RaySoTheme = [ - "meadow", - "breeze", - "raindrop", - "candy", - "crimson", - "falcon", - "sunset", - "midnight", -] - - -@ultroid_cmd(pattern="rayso") -async def pass_on(ult): - spli = ult.text.split() - theme, dark, title, text = None, True, get_display_name(ult.chat), None - if len(spli) > 2: - if spli[1] in RaySoTheme: - theme = spli[1] - dark = spli[2].lower().strip() in ["true", "t"] - elif len(spli) > 1: - if spli[1] in RaySoTheme: - theme = spli[1] - elif spli[1] == "list": - text = "**List of Rayso Themes:**\n" + "\n".join( - [f"- `{th_}`" for th_ in RaySoTheme] - ) - - await ult.eor(text) - return - else: - try: - text = ult.text.split(maxsplit=1)[1] - except IndexError: - pass - if not theme: - theme = random.choice(RaySoTheme) - if ult.is_reply: - msg = await ult.get_reply_message() - text = msg.message - title = get_display_name(msg.sender) - await ult.reply( - file=await Carbon(text, rayso=True, title=title, theme=theme, darkMode=dark) - ) diff --git a/plugins/blacklist.py b/plugins/blacklist.py deleted file mode 100644 index ac31c8d265..0000000000 --- a/plugins/blacklist.py +++ /dev/null @@ -1,69 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_blacklist") - - -from pyUltroid.dB.blacklist_db import ( - add_blacklist, - get_blacklist, - list_blacklist, - rem_blacklist, -) - -from . import events, get_string, udB, ultroid_bot, ultroid_cmd - - -@ultroid_cmd(pattern="blacklist( (.*)|$)", admins_only=True) -async def af(e): - wrd = e.pattern_match.group(1).strip() - chat = e.chat_id - if not (wrd): - return await e.eor(get_string("blk_1"), time=5) - wrd = e.text[11:] - heh = wrd.split(" ") - for z in heh: - add_blacklist(int(chat), z.lower()) - ultroid_bot.add_handler(blacklist, events.NewMessage(incoming=True)) - await e.eor(get_string("blk_2").format(wrd)) - - -@ultroid_cmd(pattern="remblacklist( (.*)|$)", admins_only=True) -async def rf(e): - wrd = e.pattern_match.group(1).strip() - chat = e.chat_id - if not wrd: - return await e.eor(get_string("blk_3"), time=5) - wrd = e.text[14:] - heh = wrd.split(" ") - for z in heh: - rem_blacklist(int(chat), z.lower()) - await e.eor(get_string("blk_4").format(wrd)) - - -@ultroid_cmd(pattern="listblacklist$", admins_only=True) -async def lsnote(e): - if x := list_blacklist(e.chat_id): - sd = get_string("blk_5") - return await e.eor(sd + x) - await e.eor(get_string("blk_6")) - - -async def blacklist(e): - if x := get_blacklist(e.chat_id): - text = e.text.lower().split() - if any((z in text) for z in x): - try: - await e.delete() - except BaseException: - pass - - -if udB.get_key("BLACKLIST_DB"): - ultroid_bot.add_handler(blacklist, events.NewMessage(incoming=True)) diff --git a/plugins/bot.py b/plugins/bot.py deleted file mode 100644 index 6886de72d4..0000000000 --- a/plugins/bot.py +++ /dev/null @@ -1,356 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_bot") - -import os -import sys -import time -from platform import python_version as pyver -from random import choice - -from telethon import __version__ -from telethon.errors.rpcerrorlist import ( - BotMethodInvalidError, - ChatSendMediaForbiddenError, -) - -from pyUltroid.version import __version__ as UltVer - -from . import HOSTED_ON, LOGS - -try: - from git import Repo -except ImportError: - LOGS.error("bot: 'gitpython' module not found!") - Repo = None - -from telethon.utils import resolve_bot_file_id - -from . import ( - ATRA_COL, - LOGS, - OWNER_NAME, - ULTROID_IMAGES, - Button, - Carbon, - Telegraph, - Var, - allcmds, - asst, - bash, - call_back, - callback, - def_logs, - eor, - get_string, - heroku_logs, - in_pattern, - inline_pic, - restart, - shutdown, - start_time, - time_formatter, - udB, - ultroid_cmd, - ultroid_version, - updater, -) - - -def ULTPIC(): - return inline_pic() or choice(ULTROID_IMAGES) - - -buttons = [ - [ - Button.url(get_string("bot_3"), "https://github.com/TeamUltroid/Ultroid"), - Button.url(get_string("bot_4"), "t.me/UltroidSupportChat"), - ] -] - -# Will move to strings -alive_txt = """ -The Ultroid Userbot - - ◍ Version - {} - ◍ Py-Ultroid - {} - ◍ Telethon - {} -""" - -in_alive = "{}\n\n🌀 Ultroid Version -> {}\n🌀 PyUltroid -> {}\n🌀 Python -> {}\n🌀 Uptime -> {}\n🌀 Branch ->[ {} ]\n\n• Join @TeamUltroid" - - -@callback("alive") -async def alive(event): - text = alive_txt.format(ultroid_version, UltVer, __version__) - await event.answer(text, alert=True) - - -@ultroid_cmd( - pattern="alive( (.*)|$)", -) -async def lol(ult): - match = ult.pattern_match.group(1).strip() - inline = None - if match in ["inline", "i"]: - try: - res = await ult.client.inline_query(asst.me.username, "alive") - return await res[0].click(ult.chat_id) - except BotMethodInvalidError: - pass - except BaseException as er: - LOGS.exception(er) - inline = True - pic = udB.get_key("ALIVE_PIC") - if isinstance(pic, list): - pic = choice(pic) - uptime = time_formatter((time.time() - start_time) * 1000) - header = udB.get_key("ALIVE_TEXT") or get_string("bot_1") - y = Repo().active_branch - xx = Repo().remotes[0].config_reader.get("url") - rep = xx.replace(".git", f"/tree/{y}") - kk = f" `[{y}]({rep})` " - if inline: - kk = f"{y}" - parse = "html" - als = in_alive.format( - header, - f"{ultroid_version} [{HOSTED_ON}]", - UltVer, - pyver(), - uptime, - kk, - ) - - if _e := udB.get_key("ALIVE_EMOJI"): - als = als.replace("🌀", _e) - else: - parse = "md" - als = (get_string("alive_1")).format( - header, - OWNER_NAME, - f"{ultroid_version} [{HOSTED_ON}]", - UltVer, - uptime, - pyver(), - __version__, - kk, - ) - - if a := udB.get_key("ALIVE_EMOJI"): - als = als.replace("✵", a) - if pic: - try: - await ult.reply( - als, - file=pic, - parse_mode=parse, - link_preview=False, - buttons=buttons if inline else None, - ) - return await ult.try_delete() - except ChatSendMediaForbiddenError: - pass - except BaseException as er: - LOGS.exception(er) - try: - await ult.reply(file=pic) - await ult.reply( - als, - parse_mode=parse, - buttons=buttons if inline else None, - link_preview=False, - ) - return await ult.try_delete() - except BaseException as er: - LOGS.exception(er) - await eor( - ult, - als, - parse_mode=parse, - link_preview=False, - buttons=buttons if inline else None, - ) - - -@ultroid_cmd(pattern="ping$", chats=[], type=["official", "assistant"]) -async def _(event): - start = time.time() - x = await event.eor("Pong !") - end = round((time.time() - start) * 1000) - uptime = time_formatter((time.time() - start_time) * 1000) - await x.edit(get_string("ping").format(end, uptime)) - - -@ultroid_cmd( - pattern="cmds$", -) -async def cmds(event): - await allcmds(event, Telegraph) - - -heroku_api = Var.HEROKU_API - - -@ultroid_cmd( - pattern="restart$", - fullsudo=True, -) -async def restartbt(ult): - ok = await ult.eor(get_string("bot_5")) - call_back() - who = "bot" if ult.client._bot else "user" - udB.set_key("_RESTART", f"{who}_{ult.chat_id}_{ok.id}") - if heroku_api: - return await restart(ok) - await bash("git pull && pip3 install -r requirements.txt") - if len(sys.argv) > 1: - os.execl(sys.executable, sys.executable, "main.py") - else: - os.execl(sys.executable, sys.executable, "-m", "pyUltroid") - - -@ultroid_cmd( - pattern="shutdown$", - fullsudo=True, -) -async def shutdownbot(ult): - await shutdown(ult) - - -@ultroid_cmd( - pattern="logs( (.*)|$)", - chats=[], -) -async def _(event): - opt = event.pattern_match.group(1).strip() - file = f"ultroid{sys.argv[-1]}.log" if len(sys.argv) > 1 else "ultroid.log" - if opt == "heroku": - await heroku_logs(event) - elif opt == "carbon" and Carbon: - event = await event.eor(get_string("com_1")) - with open(file, "r") as f: - code = f.read()[-2500:] - file = await Carbon( - file_name="ultroid-logs", - code=code, - backgroundColor=choice(ATRA_COL), - ) - if isinstance(file, dict): - await event.eor(f"`{file}`") - return - await event.reply("**Ultroid Logs.**", file=file) - elif opt == "open": - with open("ultroid.log", "r") as f: - file = f.read()[-4000:] - return await event.eor(f"`{file}`") - else: - await def_logs(event, file) - await event.try_delete() - - -@in_pattern("alive", owner=True) -async def inline_alive(ult): - pic = udB.get_key("ALIVE_PIC") - if isinstance(pic, list): - pic = choice(pic) - uptime = time_formatter((time.time() - start_time) * 1000) - header = udB.get_key("ALIVE_TEXT") or get_string("bot_1") - y = Repo().active_branch - xx = Repo().remotes[0].config_reader.get("url") - rep = xx.replace(".git", f"/tree/{y}") - kk = f"{y}" - als = in_alive.format( - header, f"{ultroid_version} [{HOSTED_ON}]", UltVer, pyver(), uptime, kk - ) - - if _e := udB.get_key("ALIVE_EMOJI"): - als = als.replace("🌀", _e) - builder = ult.builder - if pic: - try: - if ".jpg" in pic: - results = [ - await builder.photo( - pic, text=als, parse_mode="html", buttons=buttons - ) - ] - else: - if _pic := resolve_bot_file_id(pic): - pic = _pic - buttons.insert( - 0, [Button.inline(get_string("bot_2"), data="alive")] - ) - results = [ - await builder.document( - pic, - title="Inline Alive", - description="@TeamUltroid", - parse_mode="html", - buttons=buttons, - ) - ] - return await ult.answer(results) - except BaseException as er: - LOGS.exception(er) - result = [ - await builder.article( - "Alive", text=als, parse_mode="html", link_preview=False, buttons=buttons - ) - ] - await ult.answer(result) - - -@ultroid_cmd(pattern="update( (.*)|$)") -async def _(e): - xx = await e.eor(get_string("upd_1")) - if e.pattern_match.group(1).strip() and ( - "fast" in e.pattern_match.group(1).strip() - or "soft" in e.pattern_match.group(1).strip() - ): - await bash("git pull -f && pip3 install -r requirements.txt") - call_back() - await xx.edit(get_string("upd_7")) - os.execl(sys.executable, "python3", "-m", "pyUltroid") - # return - m = await updater() - branch = (Repo.init()).active_branch - if m: - x = await asst.send_file( - udB.get_key("LOG_CHANNEL"), - ULTPIC(), - caption="• **Update Available** •", - force_document=False, - buttons=Button.inline("Changelogs", data="changes"), - ) - Link = x.message_link - await xx.edit( - f'[ChangeLogs]', - parse_mode="html", - link_preview=False, - ) - else: - await xx.edit( - f'Your BOT is up-to-date with [{branch}]', - parse_mode="html", - link_preview=False, - ) - - -@callback("updtavail", owner=True) -async def updava(event): - await event.delete() - await asst.send_file( - udB.get_key("LOG_CHANNEL"), - ULTPIC(), - caption="• **Update Available** •", - force_document=False, - buttons=Button.inline("Changelogs", data="changes"), - ) diff --git a/plugins/broadcast.py b/plugins/broadcast.py deleted file mode 100644 index a10c996d55..0000000000 --- a/plugins/broadcast.py +++ /dev/null @@ -1,216 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -from . import get_help - -__doc__ = get_help("help_broadcast") - -import asyncio -import io - -from telethon.utils import get_display_name - -from pyUltroid.dB.base import KeyManager - -from . import HNDLR, LOGS, eor, get_string, udB, ultroid_bot, ultroid_cmd - -KeyM = KeyManager("BROADCAST", cast=list) - - -@ultroid_cmd( - pattern="addch( (.*)|$)", - allow_sudo=False, -) -async def broadcast_adder(event): - msgg = event.pattern_match.group(1).strip() - x = await event.eor(get_string("bd_1")) - if msgg == "all": - await x.edit(get_string("bd_2")) - chats = [ - e.entity - for e in await event.client.get_dialogs() - if (e.is_group or e.is_channel) - ] - new = 0 - for i in chats: - try: - if ( - i.broadcast - and (i.creator or i.admin_rights) - and not KeyM.contains(i.id) - ): - new += 1 - cid = f"-100{i.id}" - KeyM.add(int(cid)) - except Exception as Ex: - LOGS.exception(Ex) - await x.edit(get_string("bd_3").format(KeyM.count(), new)) - return - if event.reply_to_msg_id: - previous_message = await event.get_reply_message() - raw_text = previous_message.text - lines = raw_text.split("\n") - length = len(lines) - for line_number in range(1, length - 2): - channel_id = lines[line_number][4:-1] - if not KeyM.contains(channel_id): - KeyM.add(channel_id) - await x.edit(get_string("bd_4")) - await asyncio.sleep(3) - await event.delete() - return - chat_id = event.chat_id - if chat_id == udB.get_key("LOG_CHANNEL"): - return - if KeyM.contains(chat_id): - await x.edit(get_string("bd_6")) - elif xx := KeyM.add(chat_id): - await x.edit(get_string("bd_5")) - else: - await x.edit(get_string("sf_8")) - await asyncio.sleep(3) - await x.delete() - - -@ultroid_cmd( - pattern="remch( (.*)|$)", - allow_sudo=False, -) -async def broadcast_remover(event): - chat_id = event.pattern_match.group(1).strip() or event.chat_id - x = await event.eor(get_string("com_1")) - if chat_id == "all": - await x.edit(get_string("bd_8")) - udB.del_key("BROADCAST") - await x.edit("Database cleared.") - return - if KeyM.contains(chat_id): - KeyM.remove(chat_id) - await x.edit(get_string("bd_7")) - else: - await x.edit(get_string("bd_9")) - await asyncio.sleep(3) - await x.delete() - - -@ultroid_cmd( - pattern="listchannels$", -) -async def list_all(event): - x = await event.eor(get_string("com_1")) - channels = KeyM.get() - num = KeyM.count() - if not channels: - return await eor(x, "No chats were added.", time=5) - msg = "Channels in database:\n" - for channel in channels: - name = "" - try: - name = get_display_name(await event.client.get_entity(channel)) - except ValueError: - name = "" - msg += f"=> **{name}** [`{channel}`]\n" - msg += f"\nTotal {num} channels." - if len(msg) > 4096: - MSG = msg.replace("*", "").replace("`", "") - with io.BytesIO(str.encode(MSG)) as out_file: - out_file.name = "channels.txt" - await event.reply( - "Channels in Database", - file=out_file, - force_document=True, - allow_cache=False, - ) - await x.delete() - else: - await x.edit(msg) - - -@ultroid_cmd( - pattern="forward$", - allow_sudo=False, -) -async def forw(event): - if not event.is_reply: - return await event.eor(get_string("ex_1")) - ultroid_bot = event.client - channels = KeyM.get() - x = await event.eor("Sending...") - if not channels: - return await x.edit(f"Please add channels by using `{HNDLR}add` in them.") - error_count = 0 - sent_count = 0 - previous_message = await event.get_reply_message() - error_count = 0 - for channel in channels: - try: - await ultroid_bot.forward_messages(channel, previous_message) - sent_count += 1 - await x.edit( - f"Sent : {sent_count}\nError : {error_count}\nTotal : {len(channels)}", - ) - except Exception: - try: - await ultroid_bot.send_message( - udB.get_key("LOG_CHANNEL"), - f"Error in sending at {channel}.", - ) - except Exception as Em: - LOGS.info(Em) - error_count += 1 - await x.edit( - f"Sent : {sent_count}\nError : {error_count}\nTotal : {len(channels)}", - ) - await x.edit(f"{sent_count} messages sent with {error_count} errors.") - if error_count > 0: - await ultroid_bot.send_message( - udB.get_key("LOG_CHANNEL"), f"{error_count} Errors" - ) - - -@ultroid_cmd( - pattern="broadcast( (.*)|$)", - allow_sudo=False, -) -async def sending(event): - x = await event.eor(get_string("com_1")) - if not event.is_reply: - return await x.edit(get_string("ex_1")) - channels = KeyM.get() - if not channels: - return await x.edit(f"Please add channels by using `{HNDLR}add` in them.") - await x.edit("Sending....") - if event.reply_to_msg_id: - previous_message = await event.get_reply_message() - if previous_message.poll: - return await x.edit(f"Reply `{HNDLR}forward` for polls.") - if previous_message: - error_count = 0 - sent_count = 0 - for channel in channels: - try: - await ultroid_bot.send_message(channel, previous_message) - sent_count += 1 - await x.edit( - f"Sent : {sent_count}\nError : {error_count}\nTotal : {len(channels)}", - ) - except Exception as error: - await ultroid_bot.send_message( - udB.get_key("LOG_CHANNEL"), - f"Error in sending at {channel}.\n\n{error}", - ) - error_count += 1 - await x.edit( - f"Sent : {sent_count}\nError : {error_count}\nTotal : {len(channels)}", - ) - await x.edit(f"{sent_count} messages sent with {error_count} errors.") - if error_count > 0: - await ultroid_bot.send_message( - udB.get_key("LOG_CHANNEL"), - f"{error_count} Errors", - ) diff --git a/plugins/button.py b/plugins/button.py deleted file mode 100644 index 378c145eb9..0000000000 --- a/plugins/button.py +++ /dev/null @@ -1,56 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_button") - -import os - -from telegraph import upload_file as uf -from telethon.utils import pack_bot_file_id - -from pyUltroid.fns.tools import create_tl_btn, get_msg_button - -from . import HNDLR, get_string, mediainfo, ultroid_cmd -from ._inline import something - - -@ultroid_cmd(pattern="button") -async def butt(event): - media, wut, text = None, None, None - if event.reply_to: - wt = await event.get_reply_message() - if wt.text: - text = wt.text - if wt.media: - 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]}" - 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) - os.remove(dl) - media = f"https://graph.org{variable[0]}" - else: - media = pack_bot_file_id(wt.media) - try: - text = event.text.split(maxsplit=1)[1] - except IndexError: - if not text: - return await event.eor( - f"**Please give some text in correct format.**\n\n`{HNDLR}help button`", - ) - text, buttons = get_msg_button(text) - if buttons: - buttons = create_tl_btn(buttons) - await something(event, text, media, buttons) - await event.delete() diff --git a/plugins/calculator.py b/plugins/calculator.py deleted file mode 100644 index 267225f913..0000000000 --- a/plugins/calculator.py +++ /dev/null @@ -1,153 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -from . import get_help - -__doc__ = get_help("help_calculator") - -import re - -from . import Button, asst, callback, get_string, in_pattern, udB, ultroid_cmd - -CALC = {} - -m = [ - "AC", - "C", - "⌫", - "%", - "7", - "8", - "9", - "+", - "4", - "5", - "6", - "-", - "1", - "2", - "3", - "x", - "00", - "0", - ".", - "÷", -] -tultd = [Button.inline(f"{x}", data=f"calc{x}") for x in m] -lst = list(zip(tultd[::4], tultd[1::4], tultd[2::4], tultd[3::4])) -lst.append([Button.inline("=", data="calc=")]) - - -@ultroid_cmd(pattern="calc") -async def icalc(e): - udB.del_key("calc") - if e.client._bot: - return await e.reply(get_string("calc_1"), buttons=lst) - results = await e.client.inline_query(asst.me.username, "calc") - await results[0].click(e.chat_id, silent=True, hide_via=True) - await e.delete() - - -@in_pattern("calc", owner=True) -async def _(e): - calc = e.builder.article("Calc", text=get_string("calc_1"), buttons=lst) - await e.answer([calc]) - - -@callback(re.compile("calc(.*)"), owner=True) -async def _(e): - x = (e.data_match.group(1)).decode() - user = e.query.user_id - get = None - if x == "AC": - if CALC.get(user): - CALC.pop(user) - await e.edit( - get_string("calc_1"), - buttons=[Button.inline(get_string("calc_2"), data="recalc")], - ) - elif x == "C": - if CALC.get(user): - CALC.pop(user) - await e.answer("cleared") - elif x == "⌫": - if CALC.get(user): - get = CALC[user] - if get: - CALC.update({user: get[:-1]}) - await e.answer(str(get[:-1])) - elif x == "%": - if CALC.get(user): - get = CALC[user] - if get: - CALC.update({user: f"{get}/100"}) - await e.answer(str(f"{get}/100")) - elif x == "÷": - if CALC.get(user): - get = CALC[user] - if get: - CALC.update({user: f"{get}/"}) - await e.answer(str(f"{get}/")) - elif x == "x": - if CALC.get(user): - get = CALC[user] - if get: - CALC.update({user: f"{get}*"}) - await e.answer(str(f"{get}*")) - elif x == "=": - if CALC.get(user): - get = CALC[user] - if get: - if get.endswith(("*", ".", "/", "-", "+")): - get = get[:-1] - out = eval(get) - try: - num = float(out) - await e.answer(f"Answer : {num}", cache_time=0, alert=True) - except BaseException: - CALC.pop(user) - await e.answer(get_string("sf_8"), cache_time=0, alert=True) - await e.answer("None") - else: - if CALC.get(user): - get = CALC[user] - if get: - CALC.update({user: get + x}) - return await e.answer(str(get + x)) - CALC.update({user: x}) - await e.answer(str(x)) - - -@callback("recalc", owner=True) -async def _(e): - m = [ - "AC", - "C", - "⌫", - "%", - "7", - "8", - "9", - "+", - "4", - "5", - "6", - "-", - "1", - "2", - "3", - "x", - "00", - "0", - ".", - "÷", - ] - tultd = [Button.inline(f"{x}", data=f"calc{x}") for x in m] - lst = list(zip(tultd[::4], tultd[1::4], tultd[2::4], tultd[3::4])) - lst.append([Button.inline("=", data="calc=")]) - await e.edit(get_string("calc_1"), buttons=lst) diff --git a/plugins/channelhacks.py b/plugins/channelhacks.py deleted file mode 100644 index 712c18b08a..0000000000 --- a/plugins/channelhacks.py +++ /dev/null @@ -1,224 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -from . import get_help - -__doc__ = get_help("help_channelhacks") - - -import asyncio -import io - -from telethon.errors.rpcerrorlist import FloodWaitError -from telethon.utils import get_display_name, get_peer_id - -from pyUltroid.dB.base import KeyManager - -from . import LOGS, asst, eor, events, get_string, udB, ultroid_bot, ultroid_cmd - -ERROR = {} -SourceM = KeyManager("CH_SOURCE", cast=list) -DestiM = KeyManager("CH_DESTINATIONS", cast=list) - - -async def autopost_func(e): - if not udB.get_key("AUTOPOST"): - return - x = SourceM.get() - th = await e.get_chat() - if get_peer_id(th) not in x: - return - y = DestiM.get() - for ys in y: - try: - await e.client.send_message(int(ys), e.message) - except Exception as ex: - try: - ERROR[str(ex)] - except KeyError: - ERROR.update({str(ex): ex}) - Error = f"**Error on AUTOPOST**\n\n`{ex}`" - await asst.send_message(udB.get_key("LOG_CHANNEL"), Error) - - -@ultroid_cmd(pattern="shift (.*)") -async def _(e): - x = e.pattern_match.group(1).strip() - z = await e.eor(get_string("com_1")) - a, b = x.split("|") - try: - c = await e.client.parse_id(a) - except Exception: - await z.edit(get_string("cha_1")) - return - try: - d = await e.client.parse_id(b) - except Exception as er: - LOGS.exception(er) - await z.edit(get_string("cha_1")) - return - async for msg in e.client.iter_messages(int(c), reverse=True): - try: - await asyncio.sleep(2) - await e.client.send_message(int(d), msg) - except FloodWaitError as er: - await asyncio.sleep(er.seconds + 5) - await e.client.send_message(int(d), msg) - except BaseException as er: - LOGS.exception(er) - await z.edit("Done") - - -@ultroid_cmd(pattern="asource (.*)") -async def source(e): - if x := e.pattern_match.group(1).strip(): - try: - y = await e.client.parse_id(x) - except Exception as er: - LOGS.exception(er) - return - else: - y = e.chat_id - if not SourceM.contains(y): - SourceM.add(y) - await e.eor(get_string("cha_2")) - ultroid_bot.add_handler(autopost_func, events.NewMessage()) - else: - await e.eor(get_string("cha_3")) - - -@ultroid_cmd(pattern="dsource( (.*)|$)") -async def dd(event): - chat_id = event.pattern_match.group(1).strip() - x = await event.eor(get_string("com_1")) - if chat_id == "all": - await x.edit(get_string("bd_8")) - udB.del_key("CH_SOURCE") - await x.edit(get_string("cha_4")) - return - if chat_id: - try: - y = await event.client.parse_id(chat_id) - except Exception as er: - LOGS.exception(er) - return - else: - y = event.chat_id - if SourceM.contains(y): - SourceM.remove(y) - await eor(x, get_string("cha_5"), time=5) - else: - await eor(x, "Source channel is already removed from database. ", time=3) - - -@ultroid_cmd(pattern="listsource") -async def list_all(event): - x = await event.eor(get_string("com_1")) - num = SourceM.count() - if not num: - return await eor(x, "No chats were added.", time=5) - msg = get_string("cha_8") - channels = SourceM.get() - for channel in channels: - name = "" - try: - name = get_display_name(await event.client.get_entity(int(channel))) - except BaseException: - name = "" - msg += f"\n=> **{name}** [`{channel}`]" - msg += f"\nTotal {num} channels." - if len(msg) > 4096: - MSG = msg.replace("*", "").replace("`", "") - with io.BytesIO(str.encode(MSG)) as out_file: - out_file.name = "channels.txt" - await event.reply( - "Channels in database", - file=out_file, - force_document=True, - allow_cache=False, - ) - await x.delete() - else: - await x.edit(msg) - - -@ultroid_cmd(pattern="adest (.*)") -async def destination(e): - if x := e.pattern_match.group(1).strip(): - try: - y = await e.client.parse_id(x) - except Exception as er: - LOGS.exception(er) - return - else: - y = e.chat_id - if not DestiM.contains(y): - DestiM.add(y) - await e.eor("Destination added succesfully") - else: - await e.eor("Destination channel already added") - - -@ultroid_cmd(pattern="ddest( (.*)|$)") -async def dd(event): - chat_id = event.pattern_match.group(1).strip() - x = await event.eor(get_string("com_1")) - if chat_id == "all": - await x.edit(get_string("bd_8")) - udB.del_key("CH_DESTINATION") - await x.edit("Destinations database cleared.") - return - if chat_id: - try: - y = await event.client.parse_id(chat_id) - except Exception as er: - LOGS.exception(er) - return - else: - y = event.chat_id - if DestiM.contains(y): - DestiM.remove(y) - await eor(x, "Destination removed from database") - else: - await eor(x, "Destination channel is already removed from database. ", time=5) - - -@ultroid_cmd(pattern="listdest") -async def list_all(event): - ultroid_bot = event.client - x = await event.eor(get_string("com_1")) - channels = DestiM.get() - num = len(channels) - if not num: - return await eor(x, "No chats were added.", time=5) - msg = get_string("cha_7") - for channel in channels: - name = "" - try: - name = get_display_name(await ultroid_bot.get_entity(int(channel))) - except BaseException: - name = "" - msg += f"\n=> **{name}** [`{channel}`]" - msg += f"\nTotal {num} channels." - if len(msg) > 4096: - MSG = msg.replace("*", "").replace("`", "") - with io.BytesIO(str.encode(MSG)) as out_file: - out_file.name = "channels.txt" - await ultroid_bot.send_file( - event.chat_id, - out_file, - force_document=True, - allow_cache=False, - caption="Destination channels in database", - reply_to=event, - ) - await x.delete() - else: - await x.edit(msg) - - -if udB.get_key("AUTOPOST"): - ultroid_bot.add_handler(autopost_func, events.NewMessage()) diff --git a/plugins/chatbot.py b/plugins/chatbot.py deleted file mode 100644 index 705eeb2bd2..0000000000 --- a/plugins/chatbot.py +++ /dev/null @@ -1,89 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_chatbot") - - -from pyUltroid.fns.tools import get_chatbot_reply - -from . import LOGS, eod, get_string, inline_mention, udB, ultroid_cmd - - -@ultroid_cmd(pattern="repai") -async def im_lonely_chat_with_me(event): - if event.reply_to: - message = (await event.get_reply_message()).message - else: - try: - message = event.text.split(" ", 1)[1] - except IndexError: - return await eod(event, get_string("tban_1"), time=10) - reply_ = await get_chatbot_reply(message=message) - await event.eor(reply_) - - -@ultroid_cmd(pattern="addai") -async def add_chatBot(event): - await chat_bot_fn(event, type_="add") - - -@ultroid_cmd(pattern="remai") -async def rem_chatBot(event): - await chat_bot_fn(event, type_="remov") - - -@ultroid_cmd(pattern="listai") -async def lister(event): - key = udB.get_key("CHATBOT_USERS") or {} - users = key.get(event.chat_id, []) - if not users: - return await event.eor(get_string("chab_2"), time=5) - msg = "**Total List Of AI Enabled Users In This Chat :**\n\n" - for i in users: - try: - user = await event.client.get_entity(int(i)) - user = inline_mention(user) - except BaseException: - user = f"`{i}`" - msg += f"• {user}\n" - await event.eor(msg, link_preview=False) - - -async def chat_bot_fn(event, type_): - if event.reply_to: - user_ = (await event.get_reply_message()).sender - else: - temp = event.text.split(maxsplit=1) - try: - user_ = await event.client.get_entity(await event.client.parse_id(temp[1])) - except BaseException as er: - LOGS.exception(er) - user_ = event.chat if event.is_private else None - if not user_: - return await eod( - event, - get_string("chab_1"), - ) - key = udB.get_key("CHATBOT_USERS") or {} - chat = event.chat_id - user = user_.id - if type_ == "add": - if key.get(chat): - if user not in key[chat]: - key[chat].append(user) - else: - key.update({chat: [user]}) - elif type_ == "remov": - if key.get(chat): - if user in key[chat]: - key[chat].remove(user) - if chat in key and not key[chat]: - del key[chat] - udB.set_key("CHATBOT_USERS", key) - await event.eor(f"**ChatBot:**\n{type_}ed {inline_mention(user_)}") diff --git a/plugins/cleanaction.py b/plugins/cleanaction.py deleted file mode 100644 index d6efd0beb9..0000000000 --- a/plugins/cleanaction.py +++ /dev/null @@ -1,48 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_cleanaction") - - -from telethon.utils import get_display_name - -from . import get_string, udB, ultroid_cmd - - -@ultroid_cmd(pattern="addclean$", admins_only=True) -async def _(e): - key = udB.get_key("CLEANCHAT") or [] - if e.chat_id in key: - return await eod(e, get_string("clan_5")) - key.append(e.chat_id) - udB.set_key("CLEANCHAT", key) - await e.eor(get_string("clan_1"), time=5) - - -@ultroid_cmd(pattern="remclean$") -async def _(e): - key = udB.get_key("CLEANCHAT") or [] - if e.chat_id in key: - key.remove(e.chat_id) - udB.set_key("CLEANCHAT", key) - await e.eor(get_string("clan_2"), time=5) - - -@ultroid_cmd(pattern="listclean$") -async def _(e): - if k := udB.get_key("CLEANCHAT"): - o = "" - for x in k: - try: - title = get_display_name(await e.client.get_entity(x)) - except BaseException: - title = get_string("clan_3") - o += f"{x} {title}\n" - return await e.eor(o) - await e.eor(get_string("clan_4"), time=5) diff --git a/plugins/compressor.py b/plugins/compressor.py deleted file mode 100644 index e21e20bc80..0000000000 --- a/plugins/compressor.py +++ /dev/null @@ -1,175 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_compressor") - - -import asyncio -import os -import re -import time -from datetime import datetime as dt - -from telethon.errors.rpcerrorlist import MessageNotModifiedError -from telethon.tl.types import DocumentAttributeVideo - -from pyUltroid.fns.tools import metadata - -from . import ( - ULTConfig, - bash, - downloader, - get_string, - humanbytes, - math, - mediainfo, - time_formatter, - ultroid_cmd, - uploader, -) - - -@ultroid_cmd(pattern="compress( (.*)|$)") -async def _(e): - cr = e.pattern_match.group(1).strip() - crf = 27 - to_stream = False - if cr: - k = e.text.split() - if len(k) == 2: - crf = int(k[1]) if k[1].isdigit() else 27 - elif len(k) > 2: - crf = int(k[1]) if k[1].isdigit() else 27 - to_stream = "stream" in k[2] - vido = await e.get_reply_message() - if vido and vido.media and "video" in mediainfo(vido.media): - if hasattr(vido.media, "document"): - vfile = vido.media.document - name = vido.file.name - else: - vfile = vido.media - name = "" - if not name: - name = "video_" + dt.now().isoformat("_", "seconds") + ".mp4" - xxx = await e.eor(get_string("audiotools_5")) - c_time = time.time() - file = await downloader( - f"resources/downloads/{name}", - vfile, - xxx, - c_time, - f"Downloading {name}...", - ) - - o_size = os.path.getsize(file.name) - d_time = time.time() - diff = time_formatter((d_time - c_time) * 1000) - file_name = (file.name).split("/")[-1] - out = file_name.replace(file_name.split(".")[-1], "compressed.mkv") - await xxx.edit( - f"`Downloaded {file.name} of {humanbytes(o_size)} in {diff}.\nNow Compressing...`" - ) - x, y = await bash( - f'mediainfo --fullscan """{file.name}""" | grep "Frame count"' - ) - if y and y.endswith("NOT_FOUND"): - return await xxx.edit(f"ERROR: `{y}`") - total_frames = x.split(":")[1].split("\n")[0] - progress = f"progress-{c_time}.txt" - with open(progress, "w"): - pass - proce = await asyncio.create_subprocess_shell( - f'ffmpeg -hide_banner -loglevel quiet -progress {progress} -i """{file.name}""" -preset ultrafast -vcodec libx265 -crf {crf} -c:a copy """{out}""" -y', - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - ) - while proce.returncode != 0: - await asyncio.sleep(3) - with open(progress, "r+") as fil: - text = fil.read() - frames = re.findall("frame=(\\d+)", text) - size = re.findall("total_size=(\\d+)", text) - speed = 0 - if len(frames): - elapse = int(frames[-1]) - if len(size): - size = int(size[-1]) - per = elapse * 100 / int(total_frames) - time_diff = time.time() - int(d_time) - speed = round(elapse / time_diff, 2) - if int(speed) != 0: - some_eta = ((int(total_frames) - elapse) / speed) * 1000 - text = f"`Compressing {file_name} at {crf} CRF.\n`" - progress_str = "`[{0}{1}] {2}%\n\n`".format( - "".join("●" for _ in range(math.floor(per / 5))), - "".join("" for _ in range(20 - math.floor(per / 5))), - round(per, 2), - ) - - e_size = f"{humanbytes(size)} of ~{humanbytes((size / per) * 100)}" - eta = f"~{time_formatter(some_eta)}" - try: - await xxx.edit( - text - + progress_str - + "`" - + e_size - + "`" - + "\n\n`" - + eta - + "`" - ) - except MessageNotModifiedError: - pass - os.remove(file.name) - c_size = os.path.getsize(out) - f_time = time.time() - difff = time_formatter((f_time - d_time) * 1000) - await xxx.edit( - f"`Compressed {humanbytes(o_size)} to {humanbytes(c_size)} in {difff}\nTrying to Upload...`" - ) - differ = 100 - ((c_size / o_size) * 100) - caption = f"**Original Size: **`{humanbytes(o_size)}`\n" - 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}...") - if to_stream: - data = await metadata(out) - width = data["width"] - height = data["height"] - duration = data["duration"] - attributes = [ - DocumentAttributeVideo( - duration=duration, w=width, h=height, supports_streaming=True - ) - ] - await e.client.send_file( - e.chat_id, - mmmm, - thumb=ULTConfig.thumb, - caption=caption, - attributes=attributes, - force_document=False, - reply_to=e.reply_to_msg_id, - ) - else: - await e.client.send_file( - e.chat_id, - mmmm, - thumb=ULTConfig.thumb, - caption=caption, - force_document=True, - reply_to=e.reply_to_msg_id, - ) - await xxx.delete() - os.remove(out) - os.remove(progress) - else: - await e.eor(get_string("audiotools_8"), time=5) diff --git a/plugins/converter.py b/plugins/converter.py deleted file mode 100644 index 728349d099..0000000000 --- a/plugins/converter.py +++ /dev/null @@ -1,191 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_converter") - -import os -import time - -from . import LOGS - -try: - import cv2 -except ImportError: - cv2 = None - -try: - from PIL import Image -except ImportError: - LOGS.info(f"{__file__}: PIL not Installed.") - Image = None - -from telegraph import upload_file as uf - -from . import ( - ULTConfig, - bash, - con, - downloader, - get_paste, - get_string, - udB, - ultroid_cmd, - uploader, -) - -opn = [] - - -@ultroid_cmd( - pattern="thumbnail$", -) -async def _(e): - r = await e.get_reply_message() - if r.photo: - dl = await r.download_media() - elif r.document and r.document.thumbs: - dl = await r.download_media(thumb=-1) - else: - return await e.eor("`Reply to Photo or media with thumb...`") - variable = 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) - - -@ultroid_cmd( - pattern="rename( (.*)|$)", -) -async def imak(event): - reply = await event.get_reply_message() - t = time.time() - if not reply: - return await event.eor(get_string("cvt_1")) - inp = event.pattern_match.group(1).strip() - if not inp: - return await event.eor(get_string("cvt_2")) - xx = await event.eor(get_string("com_1")) - if reply.media: - if hasattr(reply.media, "document"): - file = reply.media.document - image = await downloader( - reply.file.name or str(time.time()), - reply.media.document, - xx, - t, - get_string("com_5"), - ) - - file = image.name - else: - file = await event.client.download_media(reply.media) - if os.path.exists(inp): - os.remove(inp) - await bash(f'mv """{file}""" """{inp}"""') - 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")) - await event.reply( - f"`{xxx.name}`", - file=xxx, - force_document=True, - thumb=ULTConfig.thumb, - ) - os.remove(inp) - await xx.delete() - - -conv_keys = { - "img": "png", - "sticker": "webp", - "webp": "webp", - "image": "png", - "webm": "webm", - "gif": "gif", - "json": "json", - "tgs": "tgs", -} - - -@ultroid_cmd( - pattern="convert( (.*)|$)", -) -async def uconverter(event): - xx = await event.eor(get_string("com_1")) - a = await event.get_reply_message() - if a is None: - return await event.eor("`Reply to Photo or media with thumb...`") - input_ = event.pattern_match.group(1).strip() - b = await a.download_media("resources/downloads/") - if not b and (a.document and a.document.thumbs): - b = await a.download_media(thumb=-1) - if not b: - return await xx.edit(get_string("cvt_3")) - try: - convert = conv_keys[input_] - 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) - if file: - await event.client.send_file( - event.chat_id, file, reply_to=event.reply_to_msg_id or event.id - ) - os.remove(file) - await xx.delete() - - -@ultroid_cmd( - pattern="doc( (.*)|$)", -) -async def _(event): - input_str = event.pattern_match.group(1).strip() - if not (input_str and event.is_reply): - return await event.eor(get_string("cvt_1"), time=5) - xx = await event.eor(get_string("com_1")) - a = await event.get_reply_message() - if not a.message: - return await xx.edit(get_string("ex_1")) - with open(input_str, "w") as b: - b.write(str(a.message)) - await xx.edit(f"**Packing into** `{input_str}`") - await event.reply(file=input_str, thumb=ULTConfig.thumb) - await xx.delete() - os.remove(input_str) - - -@ultroid_cmd( - pattern="open( (.*)|$)", -) -async def _(event): - a = await event.get_reply_message() - b = event.pattern_match.group(1).strip() - if not ((a and a.media) or (b and os.path.exists(b))): - return await event.eor(get_string("cvt_7"), time=5) - xx = await event.eor(get_string("com_1")) - rem = None - if not b: - b = await a.download_media() - rem = True - try: - with open(b) as c: - d = c.read() - except UnicodeDecodeError: - return await xx.eor(get_string("cvt_8"), time=5) - try: - await xx.edit(f"```{d}```") - except BaseException: - what, key = await get_paste(d) - await xx.edit( - f"**MESSAGE EXCEEDS TELEGRAM LIMITS**\n\nSo Pasted It On [SPACEBIN](https://spaceb.in/{key})" - ) - if rem: - os.remove(b) diff --git a/plugins/core.py b/plugins/core.py deleted file mode 100644 index e0b3e848ee..0000000000 --- a/plugins/core.py +++ /dev/null @@ -1,124 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -from . import get_help - -__doc__ = get_help("help_core") - - -import os - -from pyUltroid.startup.loader import load_addons - -from . import LOGS, async_searcher, eod, get_string, safeinstall, ultroid_cmd, un_plug - - -@ultroid_cmd(pattern="install", fullsudo=True) -async def install(event): - await safeinstall(event) - - -@ultroid_cmd( - pattern=r"unload( (.*)|$)", -) -async def unload(event): - shortname = event.pattern_match.group(1).strip() - if not shortname: - await event.eor(get_string("core_9")) - return - lsd = os.listdir("addons") - zym = f"{shortname}.py" - if zym in lsd: - try: - un_plug(shortname) - await event.eor(f"**Uɴʟᴏᴀᴅᴇᴅ** `{shortname}` **Sᴜᴄᴄᴇssғᴜʟʟʏ.**", time=3) - except Exception as ex: - LOGS.exception(ex) - return await event.eor(str(ex)) - elif zym in os.listdir("plugins"): - return await event.eor(get_string("core_11"), time=3) - else: - await event.eor(f"**Nᴏ Pʟᴜɢɪɴ Nᴀᴍᴇᴅ** `{shortname}`", time=3) - - -@ultroid_cmd( - pattern=r"uninstall( (.*)|$)", -) -async def uninstall(event): - shortname = event.pattern_match.group(1).strip() - if not shortname: - await event.eor(get_string("core_13")) - return - lsd = os.listdir("addons") - zym = f"{shortname}.py" - if zym in lsd: - try: - un_plug(shortname) - await event.eor(f"**Uɴɪɴsᴛᴀʟʟᴇᴅ** `{shortname}` **Sᴜᴄᴄᴇssғᴜʟʟʏ.**", time=3) - os.remove(f"addons/{shortname}.py") - except Exception as ex: - return await event.eor(str(ex)) - elif zym in os.listdir("plugins"): - return await event.eor(get_string("core_15"), time=3) - else: - return await event.eor(f"**Nᴏ Pʟᴜɢɪɴ Nᴀᴍᴇᴅ** `{shortname}`", time=3) - - -@ultroid_cmd( - pattern=r"load( (.*)|$)", - fullsudo=True, -) -async def load(event): - shortname = event.pattern_match.group(1).strip() - if not shortname: - await event.eor(get_string("core_16")) - return - try: - try: - un_plug(shortname) - except BaseException: - pass - load_addons(f"addons/{shortname}.py") - await event.eor(get_string("core_17").format(shortname), time=3) - except Exception as e: - LOGS.exception(e) - await eod( - event, - get_string("core_18").format(shortname, e), - time=3, - ) - - -@ultroid_cmd(pattern="getaddons( (.*)|$)", fullsudo=True) -async def get_the_addons_lol(event): - thelink = event.pattern_match.group(1).strip() - xx = await event.eor(get_string("com_1")) - fool = get_string("gas_1") - if thelink is None: - return await xx.eor(fool, time=10) - split_thelink = thelink.split("/") - if not ("raw" in thelink and thelink.endswith(".py")): - return await xx.eor(fool, time=10) - name_of_it = split_thelink[-1] - plug = await async_searcher(thelink) - fil = f"addons/{name_of_it}" - await xx.edit("Packing the codes...") - with open(fil, "w", encoding="utf-8") as uult: - uult.write(plug) - await xx.edit("Packed. Now loading the plugin..") - shortname = name_of_it.split(".")[0] - try: - load_addons(fil) - await xx.eor(get_string("core_17").format(shortname), time=15) - except Exception as e: - LOGS.exception(e) - await eod( - xx, - get_string("core_18").format(shortname, e), - time=3, - ) diff --git a/plugins/downloadupload.py b/plugins/downloadupload.py deleted file mode 100644 index e0b7674c9d..0000000000 --- a/plugins/downloadupload.py +++ /dev/null @@ -1,222 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_downloadupload") - -import asyncio -import glob -import os -import time -from datetime import datetime as dt - -from aiohttp.client_exceptions import InvalidURL -from telethon.errors.rpcerrorlist import MessageNotModifiedError - -from pyUltroid.fns.helper import time_formatter -from pyUltroid.fns.tools import get_chat_and_msgid, set_attributes - -from . import ( - LOGS, - ULTConfig, - downloader, - eor, - fast_download, - get_all_files, - get_string, - progress, - time_formatter, - ultroid_cmd, -) - - -@ultroid_cmd( - pattern="download( (.*)|$)", -) -async def down(event): - matched = event.pattern_match.group(1).strip() - msg = await event.eor(get_string("udl_4")) - if not matched: - return await eor(msg, get_string("udl_5"), time=5) - try: - splited = matched.split(" | ") - link = splited[0] - filename = splited[1] - except IndexError: - filename = None - s_time = time.time() - try: - filename, d = await fast_download( - link, - filename, - progress_callback=lambda d, t: asyncio.get_event_loop().create_task( - progress( - d, - t, - msg, - s_time, - f"Downloading from {link}", - ) - ), - ) - except InvalidURL: - return await msg.eor("`Invalid URL provided :(`", time=5) - await msg.eor(f"`{filename}` `downloaded in {time_formatter(d*1000)}.`") - - -@ultroid_cmd( - pattern="dl( (.*)|$)", -) -async def download(event): - match = event.pattern_match.group(1).strip() - if match and "t.me/" in match: - chat, msg = get_chat_and_msgid(match) - if not (chat and msg): - return await event.eor(get_string("gms_1")) - match = "" - ok = await event.client.get_messages(chat, ids=msg) - elif event.reply_to_msg_id: - ok = await event.get_reply_message() - else: - return await event.eor(get_string("cvt_3"), time=8) - xx = await event.eor(get_string("com_1")) - if not (ok and ok.media): - return await xx.eor(get_string("udl_1"), time=5) - s = dt.now() - k = time.time() - if hasattr(ok.media, "document"): - file = ok.media.document - mime_type = file.mime_type - filename = match or ok.file.name - if not filename: - if "audio" in mime_type: - filename = "audio_" + dt.now().isoformat("_", "seconds") + ".ogg" - elif "video" in mime_type: - filename = "video_" + dt.now().isoformat("_", "seconds") + ".mp4" - try: - result = await downloader( - f"resources/downloads/{filename}", - file, - xx, - k, - f"Downloading {filename}...", - ) - - except MessageNotModifiedError as err: - return await xx.edit(str(err)) - file_name = result.name - else: - d = "resources/downloads/" - file_name = await event.client.download_media( - ok, - d, - progress_callback=lambda d, t: asyncio.get_event_loop().create_task( - progress( - d, - t, - xx, - k, - get_string("com_5"), - ), - ), - ) - e = dt.now() - t = time_formatter(((e - s).seconds) * 1000) - await xx.eor(get_string("udl_2").format(file_name, t)) - - -@ultroid_cmd( - pattern="ul( (.*)|$)", -) -async def _(event): - msg = await event.eor(get_string("com_1")) - match = event.pattern_match.group(1) - if match: - match = match.strip() - if not event.out and match == ".env": - return await event.reply("`You can't do this...`") - stream, force_doc, delete, thumb = ( - False, - True, - False, - ULTConfig.thumb, - ) - if "--stream" in match: - stream = True - force_doc = False - if "--delete" in match: - delete = True - if "--no-thumb" in match: - thumb = None - arguments = ["--stream", "--delete", "--no-thumb"] - if any(item in match for item in arguments): - match = ( - match.replace("--stream", "") - .replace("--delete", "") - .replace("--no-thumb", "") - .strip() - ) - if match.endswith("/"): - match += "*" - results = glob.glob(match) - if not results and os.path.exists(match): - results = [match] - if not results: - try: - await event.reply(file=match) - return await event.try_delete() - except Exception as er: - LOGS.exception(er) - return await msg.eor(get_string("ls1")) - for result in results: - if os.path.isdir(result): - c, s = 0, 0 - for files in get_all_files(result): - attributes = None - if stream: - try: - attributes = await set_attributes(files) - except KeyError as er: - LOGS.exception(er) - try: - file, _ = await event.client.fast_uploader( - files, show_progress=True, event=msg, to_delete=delete - ) - await event.client.send_file( - event.chat_id, - file, - supports_streaming=stream, - force_document=force_doc, - thumb=thumb, - attributes=attributes, - caption=f"`Uploaded` `{files}` `in {time_formatter(_*1000)}`", - reply_to=event.reply_to_msg_id or event, - ) - s += 1 - except (ValueError, IsADirectoryError): - c += 1 - break - attributes = None - if stream: - try: - attributes = await set_attributes(result) - except KeyError as er: - LOGS.exception(er) - file, _ = await event.client.fast_uploader( - result, show_progress=True, event=msg, to_delete=delete - ) - await event.client.send_file( - event.chat_id, - file, - supports_streaming=stream, - force_document=force_doc, - thumb=thumb, - attributes=attributes, - caption=f"`Uploaded` `{result}` `in {time_formatter(_*1000)}`", - ) - await msg.try_delete() diff --git a/plugins/echo.py b/plugins/echo.py deleted file mode 100644 index 04c7dd4a0f..0000000000 --- a/plugins/echo.py +++ /dev/null @@ -1,76 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_echo") - - -from telethon.utils import get_display_name - -from pyUltroid.dB.echo_db import add_echo, check_echo, list_echo, rem_echo - -from . import inline_mention, ultroid_cmd - - -@ultroid_cmd(pattern="addecho( (.*)|$)") -async def echo(e): - r = await e.get_reply_message() - if r: - user = r.sender_id - else: - try: - user = e.text.split()[1] - if user.startswith("@"): - ok = await e.client.get_entity(user) - user = ok.id - else: - user = int(user) - except BaseException: - return await e.eor("Reply To A user.", time=5) - if check_echo(e.chat_id, user): - return await e.eor("Echo already activated for this user.", time=5) - add_echo(e.chat_id, user) - ok = await e.client.get_entity(user) - user = inline_mention(ok) - await e.eor(f"Activated Echo For {user}.") - - -@ultroid_cmd(pattern="remecho( (.*)|$)") -async def rm(e): - r = await e.get_reply_message() - if r: - user = r.sender_id - else: - try: - user = e.text.split()[1] - if user.startswith("@"): - ok = await e.client.get_entity(user) - user = ok.id - else: - user = int(user) - except BaseException: - return await e.eor("Reply To A User.", time=5) - if check_echo(e.chat_id, user): - rem_echo(e.chat_id, user) - ok = await e.client.get_entity(user) - user = f"[{get_display_name(ok)}](tg://user?id={ok.id})" - return await e.eor(f"Deactivated Echo For {user}.") - await e.eor("Echo not activated for this user") - - -@ultroid_cmd(pattern="listecho$") -async def lstecho(e): - if k := list_echo(e.chat_id): - user = "**Activated Echo For Users:**\n\n" - for x in k: - ok = await e.client.get_entity(int(x)) - kk = f"[{get_display_name(ok)}](tg://user?id={ok.id})" - user += f"•{kk}" + "\n" - await e.eor(user) - else: - await e.eor("`List is Empty, For echo`", time=5) diff --git a/plugins/extra.py b/plugins/extra.py deleted file mode 100644 index f98ce7a885..0000000000 --- a/plugins/extra.py +++ /dev/null @@ -1,85 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("extra") - -import asyncio - -from . import get_string, ultroid_cmd - - -@ultroid_cmd( - pattern="del$", - manager=True, -) -async def delete_it(delme): - msg_src = await delme.get_reply_message() - if not msg_src: - return - await msg_src.try_delete() - await delme.try_delete() - - -@ultroid_cmd( - pattern="copy$", -) -async def copy(e): - reply = await e.get_reply_message() - if reply: - await reply.reply(reply) - return await e.try_delete() - await e.eor(get_string("ex_1"), time=5) - - -@ultroid_cmd( - pattern="edit", -) -async def editer(edit): - message = edit.text - chat = await edit.get_input_chat() - string = str(message[6:]) - reply = await edit.get_reply_message() - if reply and reply.text: - try: - await reply.edit(string) - await edit.delete() - except BaseException: - pass - else: - i = 1 - async for message in edit.client.iter_messages(chat, from_user="me", limit=2): - if i == 2: - await message.edit(string) - await edit.delete() - break - i += 1 - - -@ultroid_cmd( - pattern="reply$", -) -async def _(e): - if e.reply_to_msg_id: - chat = e.chat_id - try: - msg = (await e.client.get_messages(e.chat_id, limit=1, max_id=e.id))[0] - except IndexError: - return await e.eor( - "`You have previously sent no message to reply again...`", time=5 - ) - except BaseException as er: - return await e.eor(f"**ERROR:** `{er}`") - await asyncio.wait( - [ - e.client.delete_messages(chat, [e.id, msg.id]), - e.client.send_message(chat, msg, reply_to=e.reply_to_msg_id), - ] - ) - else: - await e.try_delete() diff --git a/plugins/fakeaction.py b/plugins/fakeaction.py deleted file mode 100644 index 56762ecaff..0000000000 --- a/plugins/fakeaction.py +++ /dev/null @@ -1,36 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_fakeaction") - -import math -import time - -from pyUltroid.fns.admins import ban_time - -from . import asyncio, get_string, ultroid_cmd - - -@ultroid_cmd( - pattern="f(typing|audio|contact|document|game|location|sticker|photo|round|video)( (.*)|$)" -) -async def _(e): - act = e.pattern_match.group(1).strip() - t = e.pattern_match.group(2) - if act in ["audio", "round", "video"]: - act = f"record-{act}" - if t.isdigit(): - t = int(t) - elif t.endswith(("s", "h", "d", "m")): - t = math.ceil((ban_time(t)) - time.time()) - else: - t = 60 - await e.eor(get_string("fka_1").format(str(t)), time=5) - async with e.client.action(e.chat_id, act): - await asyncio.sleep(t) diff --git a/plugins/fileshare.py b/plugins/fileshare.py deleted file mode 100644 index c73fb521b9..0000000000 --- a/plugins/fileshare.py +++ /dev/null @@ -1,95 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_fileshare") - -import os - -from pyUltroid.dB.filestore_db import del_stored, get_stored_msg, list_all_stored_msgs -from pyUltroid.fns.tools import get_file_link - -from . import HNDLR, asst, get_string, in_pattern, udB, ultroid_bot, ultroid_cmd - - -@ultroid_cmd(pattern="store$") -async def filestoreplg(event): - msg = await event.get_reply_message() - if not msg: - return await event.eor(get_string("fsh_3"), time=10) - # allow storing both messages and media. - filehash = await get_file_link(msg) - link_to_file = f"https://t.me/{asst.me.username}?start={filehash}" - await event.eor( - get_string("fsh_2").format(link_to_file), - link_preview=False, - ) - - -@ultroid_cmd("delstored ?(.*)") -async def _(event): - match = event.pattern_match.group(1) - if not match: - return await event.eor("`Give stored film's link to delete.`", time=5) - match = match.split("?start=") - botusername = match[0].split("/")[-1] - if botusername != asst.me.username: - return await event.eor( - "`Message/Media of provided link was not stored by this bot.`", time=5 - ) - msg_id = get_stored_msg(match[1]) - if not msg_id: - return await event.eor( - "`Message/Media of provided link was already deleted.`", time=5 - ) - del_stored(match[1]) - await ultroid_bot.delete_messages(udB.get_key("LOG_CHANNEL"), int(msg_id)) - await event.eor("__Deleted__") - - -@ultroid_cmd("liststored$") -async def liststored(event): - files = list_all_stored_msgs() - if not files: - return await event.eor(get_string("fsh_4"), time=5) - msg = "**Stored files:**\n" - for c, i in enumerate(files, start=1): - msg += f"`{c}`. https://t.me/{asst.me.username}?start={i}\n" - if len(msg) > 4095: - with open("liststored.txt", "w") as f: - f.write(msg.replace("**", "").replace("`", "")) - await event.reply(get_string("fsh_1"), file="liststored.txt") - os.remove("liststored.txt") - return - await event.eor(msg, link_preview=False) - - -@in_pattern("filestore", owner=True) -async def file_short(event): - all_ = list_all_stored_msgs() - res = [] - if all_: - LOG_CHA = udB.get_key("LOG_CHANNEL") - for msg in all_[:50]: - m_id = get_stored_msg(msg) - if not m_id: - continue - message = await asst.get_messages(LOG_CHA, ids=m_id) - if not message: - continue - if message.media: - res.append(await event.builder.document(title=msg, file=message.media)) - elif message.text: - res.append( - await event.builder.article(title=message.text, text=message.text) - ) - if not res: - title = "You have no stored file :(" - text = f"{title}\n\nRead `{HNDLR}help fileshare` to know how to store." - return await event.answer([await event.builder.article(title=title, text=text)]) - await event.answer(res, switch_pm="• File Store •", switch_pm_param="start") diff --git a/plugins/filter.py b/plugins/filter.py deleted file mode 100644 index d705e31558..0000000000 --- a/plugins/filter.py +++ /dev/null @@ -1,102 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_filter") - -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 ._inline import something - - -@ultroid_cmd(pattern="addfilter( (.*)|$)") -async def af(e): - wrd = (e.pattern_match.group(1).strip()).lower() - wt = await e.get_reply_message() - chat = e.chat_id - if not (wt and wrd): - return await e.eor(get_string("flr_1")) - btn = format_btn(wt.buttons) if wt.buttons else None - if wt and wt.media: - wut = mediainfo(wt.media) - if wut.startswith(("pic", "gif")): - dl = await wt.download_media() - variable = uf(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) - os.remove(dl) - m = f"https://graph.org{variable[0]}" - else: - m = pack_bot_file_id(wt.media) - if wt.text: - txt = wt.text - if not btn: - txt, btn = get_msg_button(wt.text) - add_filter(chat, wrd, txt, m, btn) - else: - add_filter(chat, wrd, None, m, btn) - else: - txt = wt.text - if not btn: - txt, btn = get_msg_button(wt.text) - add_filter(chat, wrd, txt, None, btn) - await e.eor(get_string("flr_4").format(wrd)) - ultroid_bot.add_handler(filter_func, events.NewMessage()) - - -@ultroid_cmd(pattern="remfilter( (.*)|$)") -async def rf(e): - wrd = (e.pattern_match.group(1).strip()).lower() - chat = e.chat_id - if not wrd: - return await e.eor(get_string("flr_3")) - rem_filter(int(chat), wrd) - await e.eor(get_string("flr_5").format(wrd)) - - -@ultroid_cmd(pattern="listfilter$") -async def lsnote(e): - if x := list_filter(e.chat_id): - sd = "Filters Found In This Chats Are\n\n" - return await e.eor(sd + x) - await e.eor(get_string("flr_6")) - - -async def filter_func(e): - if isinstance(e.sender, User) and e.sender.bot: - return - xx = (e.text).lower() - chat = e.chat_id - if x := get_filter(chat): - for c in x: - pat = r"( |^|[^\w])" + re.escape(c) + r"( |$|[^\w])" - if re.search(pat, xx): - if k := x.get(c): - msg = k["msg"] - media = k["media"] - if k.get("button"): - btn = create_tl_btn(k["button"]) - return await something(e, msg, media, btn) - await e.reply(msg, file=media) - - -if udB.get_key("FILTERS"): - ultroid_bot.add_handler(filter_func, events.NewMessage()) diff --git a/plugins/fontgen.py b/plugins/fontgen.py deleted file mode 100644 index b284862e56..0000000000 --- a/plugins/fontgen.py +++ /dev/null @@ -1,60 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import get_help - -__doc__ = get_help("help_fontgen") - -import string - -from . import eod, ultroid_cmd - -_default = string.ascii_letters -Fonts = { - "small caps": "ᴀʙᴄᴅᴇғɢʜɪᴊᴋʟᴍɴᴏᴘϙʀsᴛᴜᴠᴡxʏᴢABCDEFGHIJKLMNOPQRSTUVWXYZ", - "monospace": "𝚊𝚋𝚌𝚍𝚎𝚏𝚐𝚑𝚒𝚓𝚔𝚕𝚖𝚗𝚘𝚙𝚚𝚛𝚜𝚝𝚞𝚟𝚠𝚡𝚢𝚣𝙰𝙱𝙲𝙳𝙴𝙵𝙶𝙷𝙸𝙹𝙺𝙻𝙼𝙽𝙾𝙿𝚀𝚁𝚂𝚃𝚄𝚅𝚆𝚇𝚈𝚉", - "double stroke": "𝕒𝕓𝕔𝕕𝕖𝕗𝕘𝕙𝕚𝕛𝕜𝕝𝕞𝕟𝕠𝕡𝕢𝕣𝕤𝕥𝕦𝕧𝕨𝕩𝕪𝕫𝔸𝔹ℂ𝔻𝔼𝔽𝔾ℍ𝕀𝕁𝕂𝕃𝕄ℕ𝕆ℙℚℝ𝕊𝕋𝕌𝕍𝕎𝕏𝕐ℤ", - "script royal": "𝒶𝒷𝒸𝒹𝑒𝒻𝑔𝒽𝒾𝒿𝓀𝓁𝓂𝓃𝑜𝓅𝓆𝓇𝓈𝓉𝓊𝓋𝓌𝓍𝓎𝓏𝒜ℬ𝒞𝒟ℰℱ𝒢ℋℐ𝒥𝒦ℒℳ𝒩𝒪𝒫𝒬ℛ𝒮𝒯𝒰𝒱𝒲𝒳𝒴𝒵", -} - - -@ultroid_cmd( - pattern="font( (.*)|$)", -) -async def _(e): - input = e.pattern_match.group(1).strip() - reply = await e.get_reply_message() - if not input: - m = "**Available Fonts**\n\n" - for x in Fonts.keys(): - m += f"• `{x}`\n" - return await e.eor(m, time=5) - if not reply: - try: - _ = input.split(":", maxsplit=1) - font = _[0][:-1] - text = _[1] - except IndexError: - return await eod(e, help) - elif not input: - return await eod(e, "`Give font dude :/`") - else: - font = input - text = reply.message - if font not in Fonts.keys(): - return await e.eor(f"`{font} not in font list`.", time=5) - msg = gen_font(text, Fonts[font]) - await e.eor(msg) - - -def gen_font(text, new_font): - new_font = " ".join(new_font).split() - for q in text: - if q in _default: - new = new_font[_default.index(q)] - text = text.replace(q, new) - return text diff --git a/plugins/forcesubscribe.py b/plugins/forcesubscribe.py deleted file mode 100644 index 0f59a5d2e6..0000000000 --- a/plugins/forcesubscribe.py +++ /dev/null @@ -1,179 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}fsub ` - Enable ForceSub in Used Chat ! - -• `{i}checkfsub` - Check/Get Active ForceSub Setting of Used Chat. - -• `{i}remfsub` - Remove ForceSub from Used Chat ! - - Note - You Need to be Admin in Both Channel/Chats - in order to Use ForceSubscribe. -""" - -import re - -from telethon.errors.rpcerrorlist import ChatAdminRequiredError, UserNotParticipantError -from telethon.tl.custom import Button -from telethon.tl.functions.channels import GetParticipantRequest -from telethon.tl.functions.messages import ExportChatInviteRequest -from telethon.tl.types import ( - Channel, - ChannelParticipantBanned, - ChannelParticipantLeft, - User, -) - -from pyUltroid.dB.forcesub_db import add_forcesub, get_forcesetting, rem_forcesub - -from . import ( - LOGS, - asst, - callback, - events, - get_string, - in_pattern, - inline_mention, - udB, - ultroid_bot, - ultroid_cmd, -) - -CACHE = {} - - -@ultroid_cmd(pattern="fsub( (.*)|$)", admins_only=True, groups_only=True) -async def addfor(e): - match = e.pattern_match.group(1).strip() - if not match: - return await e.eor(get_string("fsub_1"), time=5) - try: - match = await e.client.parse_id(match) - except BaseException: - return await e.eor(get_string("fsub_2"), time=5) - add_forcesub(e.chat_id, match) - await e.eor("Added ForceSub in This Chat !") - ultroid_bot.add_handler(force_sub, events.NewMessage(incoming=True)) - - -@ultroid_cmd(pattern="remfsub$") -async def remor(e): - res = rem_forcesub(e.chat_id) - if not res: - return await e.eor(get_string("fsub_3"), time=5) - await e.eor("Removed ForceSub...") - - -@ultroid_cmd(pattern="checkfsub$") -async def getfsr(e): - res = get_forcesetting(e.chat_id) - if not res: - return await e.eor("ForceSub is Not Active In This Chat !", time=5) - cha = await e.client.get_entity(int(res)) - await e.eor(f"**ForceSub Status** : `Active`\n- **{cha.title}** `({res})`") - - -@in_pattern("fsub( (.*)|$)", owner=True) -async def fcall(e): - match = e.pattern_match.group(1).strip() - spli = match.split("_") - user = await ultroid_bot.get_entity(int(spli[0])) - cl = await ultroid_bot.get_entity(int(spli[1])) - text = f"Hi {inline_mention(user)}, You Need to Join" - text += f" {cl.title} in order to Chat in this Group." - el = ( - f"https://t.me/{cl.username}" - if cl.username - else (await ultroid_bot(ExportChatInviteRequest(cl))).link - ) - - res = [ - await e.builder.article( - title="forcesub", - text=text, - buttons=[ - [Button.url(text=get_string("fsub_4"), url=el)], - [Button.inline(get_string("fsub_5"), data=f"unm_{match}")], - ], - ) - ] - await e.answer(res) - - -@callback(re.compile("unm_(.*)")) -async def diesoon(e): - match = (e.data_match.group(1)).decode("UTF-8") - spli = match.split("_") - if e.sender_id != int(spli[0]): - return await e.answer(get_string("fsub_7"), alert=True) - try: - values = await ultroid_bot(GetParticipantRequest(int(spli[1]), int(spli[0]))) - if isinstance(values.participant, ChannelParticipantLeft) or ( - isinstance(values.participant, ChannelParticipantBanned) and values.left - ): - raise UserNotParticipantError("") - except UserNotParticipantError: - return await e.answer( - "Please Join That Channel !\nThen Click This Button !", alert=True - ) - await ultroid_bot.edit_permissions( - e.chat_id, int(spli[0]), send_messages=True, until_date=None - ) - await e.edit(get_string("fsub_8")) - - -async def force_sub(ult): - if not udB.get_key("FORCESUB"): - return - user = await ult.get_sender() - joinchat = get_forcesetting(ult.chat_id) - if (not joinchat) or (isinstance(user, User) and user.bot): - return - if CACHE.get(ult.chat_id): - if CACHE[ult.chat_id].get(user.id): - CACHE[ult.chat_id].update({user.id: CACHE[ult.chat_id][user.id] + 1}) - else: - CACHE[ult.chat_id].update({user.id: 1}) - else: - CACHE.update({ult.chat_id: {user.id: 1}}) - count = CACHE[ult.chat_id][user.id] - if count == 11: - CACHE[ult.chat_id][user.id] = 1 - return - if count in range(2, 11): - return - try: - await ultroid_bot.get_permissions(int(joinchat), user.id) - return - except UserNotParticipantError: - pass - if isinstance(user, Channel): - try: - await ultroid_bot.edit_permissions( - ult.chat_id, user.id, view_messages=False - ) - return - except BaseException as er: - LOGS.exception(er) - try: - await ultroid_bot.edit_permissions(ult.chat_id, user.id, send_messages=False) - except ChatAdminRequiredError: - return - except Exception as e: - await ult.delete() - LOGS.info(e) - res = await ultroid_bot.inline_query(asst.me.username, f"fsub {user.id}_{joinchat}") - await res[0].click(ult.chat_id, reply_to=ult.id) - - -if udB.get_key("FORCESUB"): - ultroid_bot.add_handler(force_sub, events.NewMessage(incoming=True)) diff --git a/plugins/gdrive.py b/plugins/gdrive.py deleted file mode 100644 index 58b726027b..0000000000 --- a/plugins/gdrive.py +++ /dev/null @@ -1,232 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - -• `{i}gdul ` - Reply to file to upload on Google Drive. - Add file name to upload on Google Drive. - -• `{i}gdown | ` - Download from Gdrive link or file id. - -• `{i}gdsearch ` - Search file name on Google Drive and get link. - -• `{i}gdlist` - List all GDrive files. - -• `{i}gdfolder` - Link to your Google Drive Folder. - If added then all files will be uploaded in this folder. -""" - -import os -import time - -from telethon.tl.types import Message - -from pyUltroid.fns.gDrive import GDriveManager -from pyUltroid.fns.helper import time_formatter - -from . import ULTConfig, asst, eod, eor, get_string, ultroid_cmd - - -@ultroid_cmd( - pattern="gdown( (.*)|$)", - fullsudo=True, -) -async def gdown(event): - GDrive = GDriveManager() - match = event.pattern_match.group(1).strip() - if not match: - return await eod(event, "`Give file id or Gdrive link to download from!`") - filename = match.split(" | ")[1].strip() if " | " in match else None - eve = await event.eor(get_string("com_1")) - _start = time.time() - status, response = await GDrive._download_file(eve, match, filename) - if not status: - return await eve.edit(response) - await eve.edit( - f"`Downloaded ``{response}`` in {time_formatter((time.time() - _start)*1000)}`" - ) - - -@ultroid_cmd( - pattern="gdlist$", - fullsudo=True, -) -async def files(event): - GDrive = GDriveManager() - if not os.path.exists(GDrive.token_file): - return await event.eor(get_string("gdrive_6").format(asst.me.username)) - eve = await event.eor(get_string("com_1")) - msg = "" - if files := GDrive._list_files: - msg += f"{len(files.keys())} files found in gdrive.\n\n" - for _ in files: - msg += f"> [{files[_]}]({_})\n" - else: - msg += "Nothing in Gdrive" - if len(msg) < 4096: - await eve.edit(msg, link_preview=False) - else: - with open("drive-files.txt", "w") as f: - f.write( - msg.replace("[", "File Name: ") - .replace("](", "\n» Link: ") - .replace(")\n", "\n\n") - ) - try: - await eve.delete() - except BaseException: - pass - await event.client.send_file( - event.chat_id, - "drive-files.txt", - thumb=ULTConfig.thumb, - reply_to=event, - ) - os.remove("drive-files.txt") - - -@ultroid_cmd( - pattern="gdul( (.*)|$)", - fullsudo=True, -) -async def _(event): - GDrive = GDriveManager() - if not os.path.exists(GDrive.token_file): - return await eod(event, get_string("gdrive_6").format(asst.me.username)) - input_file = event.pattern_match.group(1).strip() or await event.get_reply_message() - if not input_file: - return await eod(event, "`Reply to file or give its location.`") - mone = await event.eor(get_string("com_1")) - if isinstance(input_file, Message): - location = "resources/downloads" - if input_file.photo: - filename = await input_file.download_media(location) - else: - filename = input_file.file.name - if not filename: - filename = str(round(time.time())) - filename = f"{location}/{filename}" - try: - filename, downloaded_in = await event.client.fast_downloader( - file=input_file.media.document, - filename=filename, - show_progress=True, - event=mone, - message=get_string("com_5"), - ) - filename = filename.name - except Exception as e: - return await eor(mone, str(e), time=10) - await mone.edit( - f"`Downloaded to ``{filename}`.`", - ) - else: - filename = input_file.strip() - if not os.path.exists(filename): - return await eod( - mone, - "File Not found in local server. Give me a file path :((", - time=5, - ) - folder_id = None - if os.path.isdir(filename): - files = os.listdir(filename) - if not files: - return await eod( - mone, "`Requested directory is empty. Can't create empty directory.`" - ) - folder_id = GDrive.create_directory(filename) - c = 0 - for files in sorted(files): - file = f"{filename}/{files}" - if not os.path.isdir(file): - try: - await GDrive._upload_file(mone, path=file, folder_id=folder_id) - c += 1 - except Exception as e: - return await mone.edit( - f"Exception occurred while uploading to gDrive {e}" - ) - return await mone.edit( - f"`Uploaded `[{filename}](https://drive.google.com/folderview?id={folder_id})` with {c} files.`" - ) - try: - g_drive_link = await GDrive._upload_file( - mone, - filename, - ) - await mone.edit( - get_string("gdrive_7").format(filename.split("/")[-1], g_drive_link) - ) - except Exception as e: - await mone.edit(f"Exception occurred while uploading to gDrive {e}") - - -@ultroid_cmd( - pattern="gdsearch( (.*)|$)", - fullsudo=True, -) -async def _(event): - GDrive = GDriveManager() - if not os.path.exists(GDrive.token_file): - return await event.eor(get_string("gdrive_6").format(asst.me.username)) - input_str = event.pattern_match.group(1).strip() - if not input_str: - return await event.eor("`Give filename to search on GDrive...`") - eve = await event.eor(f"`Searching for {input_str} in G-Drive...`") - files = GDrive.search(input_str) - msg = "" - if files: - msg += ( - f"{len(files.keys())} files with {input_str} in title found in GDrive.\n\n" - ) - for _ in files: - msg += f"> [{files[_]}]({_})\n" - else: - msg += f"`No files with title {input_str}`" - if len(msg) < 4096: - await eve.eor(msg, link_preview=False) - else: - with open("drive-files.txt", "w") as f: - f.write( - msg.replace("[", "File Name: ") - .replace("](", "\n» Link: ") - .replace(")\n", "\n\n") - ) - try: - await eve.delete() - except BaseException: - pass - await event.client.send_file( - event.chat_id, - f"{input_str}.txt", - thumb=ULTConfig.thumb, - reply_to=event, - ) - os.remove(f"{input_str}.txt") - - -@ultroid_cmd( - pattern="gdfolder$", - fullsudo=True, -) -async def _(event): - GDrive = GDriveManager() - if not os.path.exists(GDrive.token_file): - return await event.eor(get_string("gdrive_6").format(asst.me.username)) - if GDrive.folder_id: - await event.eor( - "`Your G-Drive Folder link : `\n" - + GDrive._create_folder_link(GDrive.folder_id) - ) - else: - await eod(event, "Set FOLDERID from your Assistant bot's Settings ") diff --git a/plugins/giftools.py b/plugins/giftools.py deleted file mode 100644 index f9e2687bea..0000000000 --- a/plugins/giftools.py +++ /dev/null @@ -1,128 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - -•`{i}invertgif` - Make Gif Inverted(negative). - -•`{i}bwgif` - Make Gif black and white - -•`{i}rvgif` - Reverse a gif - -•`{i}vtog` - Reply To Video , It will Create Gif - Video to Gif - -•`{i}gif ` - Send video regarding to query. -""" -import os -import random -import time -from datetime import datetime as dt - -from . import HNDLR, LOGS, bash, downloader, get_string, mediainfo, ultroid_cmd - - -@ultroid_cmd(pattern="(bw|invert)gif$") -async def igif(e): - match = e.pattern_match.group(1).strip() - a = await e.get_reply_message() - if not (a and a.media): - return await e.eor("`Reply To gif only`", time=5) - wut = mediainfo(a.media) - if "gif" not in wut: - return await e.eor("`Reply To Gif Only`", time=5) - xx = await e.eor(get_string("com_1")) - z = await a.download_media() - if match == "bw": - cmd = f'ffmpeg -i "{z}" -vf format=gray ult.gif -y' - else: - cmd = f'ffmpeg -i "{z}" -vf lutyuv="y=negval:u=negval:v=negval" ult.gif -y' - try: - await bash(cmd) - await e.client.send_file(e.chat_id, "ult.gif", supports_streaming=True) - os.remove(z) - os.remove("ult.gif") - await xx.delete() - except Exception as er: - LOGS.info(er) - - -@ultroid_cmd(pattern="rvgif$") -async def reverse_gif(event): - a = await event.get_reply_message() - if not (a and a.media) and "video" not in mediainfo(a.media): - return await event.eor("`Reply To Video only`", time=5) - msg = await event.eor(get_string("com_1")) - file = await a.download_media() - await bash(f'ffmpeg -i "{file}" -vf reverse -af areverse reversed.mp4 -y') - await event.respond("- **Reversed Video/GIF**", file="reversed.mp4") - await msg.delete() - os.remove(file) - os.remove("reversed.mp4") - - -@ultroid_cmd(pattern="gif( (.*)|$)") -async def gifs(ult): - get = ult.pattern_match.group(1).strip() - xx = random.randint(0, 5) - n = 0 - if ";" in get: - try: - n = int(get.split(";")[-1]) - except IndexError: - pass - if not get: - return await ult.eor(f"`{HNDLR}gif `") - m = await ult.eor(get_string("com_2")) - gifs = await ult.client.inline_query("gif", get) - if not n: - await gifs[xx].click( - ult.chat_id, reply_to=ult.reply_to_msg_id, silent=True, hide_via=True - ) - else: - for x in range(n): - await gifs[x].click( - ult.chat_id, reply_to=ult.reply_to_msg_id, silent=True, hide_via=True - ) - await m.delete() - - -@ultroid_cmd(pattern="vtog$") -async def vtogif(e): - a = await e.get_reply_message() - if not (a and a.media): - return await e.eor("`Reply To video only`", time=5) - wut = mediainfo(a.media) - if "video" not in wut: - return await e.eor("`Reply To Video Only`", time=5) - xx = await e.eor(get_string("com_1")) - dur = a.media.document.attributes[0].duration - tt = time.time() - if int(dur) < 120: - z = await a.download_media() - await bash( - f'ffmpeg -i {z} -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 ult.gif -y' - ) - else: - filename = a.file.name - if not filename: - filename = "video_" + dt.now().isoformat("_", "seconds") + ".mp4" - vid = await downloader(filename, a.media.document, xx, tt, get_string("com_5")) - z = vid.name - await bash( - f'ffmpeg -ss 3 -t 100 -i {z} -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 ult.gif' - ) - - await e.client.send_file(e.chat_id, "ult.gif", support_stream=True) - os.remove(z) - os.remove("ult.gif") - await xx.delete() diff --git a/plugins/glitch.py b/plugins/glitch.py deleted file mode 100644 index c59192f991..0000000000 --- a/plugins/glitch.py +++ /dev/null @@ -1,42 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -•`{i}glitch ` - gives a glitchy gif. -""" -import os - -from . import bash, get_string, mediainfo, ultroid_cmd - - -@ultroid_cmd(pattern="glitch$") -async def _(e): - try: - import glitch_me # ignore :pylint - except ModuleNotFoundError: - await bash( - "pip install -e git+https://github.com/1Danish-00/glitch_me.git#egg=glitch_me" - ) - reply = await e.get_reply_message() - if not reply or not reply.media: - return await e.eor(get_string("cvt_3")) - xx = await e.eor(get_string("glitch_1")) - wut = mediainfo(reply.media) - if wut.startswith(("pic", "sticker")): - ok = await reply.download_media() - elif reply.document and reply.document.thumbs: - ok = await reply.download_media(thumb=-1) - else: - return await xx.eor(get_string("com_4")) - cmd = f"glitch_me gif --line_count 200 -f 10 -d 50 '{ok}' ult.gif" - await bash(cmd) - await e.reply(file="ult.gif", force_document=False) - await xx.delete() - os.remove(ok) - os.remove("ult.gif") diff --git a/plugins/globaltools.py b/plugins/globaltools.py deleted file mode 100644 index 074aad9c36..0000000000 --- a/plugins/globaltools.py +++ /dev/null @@ -1,753 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}gban ` -• `{i}ungban` - Ban/Unban Globally. - -• `{i}gstat ` - Check if user is GBanned. - -• `{i}listgban` : List all GBanned users. - -• `{i}gmute` | `{i}ungmute` - Mute/UnMute Globally. - -• `{i}gkick ` `Globally Kick User` -• `{i}gcast ` `Globally Send msg in all grps` - -• `{i}gadmincast ` `Globally broadcast in your admin chats` -• `{i}gucast ` `Globally send msg in all pm users` - -• `{i}gblacklist ` - globally promote user where you are admin - - Set whether To promote only in groups/channels/all. - Eg- `gpromote group boss` ~ promotes user in all grps. - `gpromote @username all sar` ~ promote the user in all group & channel -• `{i}gdemote` - `demote user globally` -""" -import asyncio -import os - -from telethon.errors.rpcerrorlist import ChatAdminRequiredError, FloodWaitError -from telethon.tl.functions.channels import EditAdminRequest -from telethon.tl.functions.contacts import BlockRequest, UnblockRequest -from telethon.tl.types import ChatAdminRights, User - -from pyUltroid.dB import DEVLIST -from pyUltroid.dB.base import KeyManager -from pyUltroid.dB.gban_mute_db import ( - gban, - gmute, - is_gbanned, - is_gmuted, - list_gbanned, - ungban, - ungmute, -) -from pyUltroid.fns.tools import create_tl_btn, format_btn, get_msg_button - -from . import ( - HNDLR, - LOGS, - NOSPAM_CHAT, - OWNER_NAME, - eod, - eor, - get_string, - inline_mention, - ultroid_bot, - ultroid_cmd, -) -from ._inline import something - -_gpromote_rights = ChatAdminRights( - add_admins=False, - invite_users=True, - change_info=False, - ban_users=True, - delete_messages=True, - pin_messages=True, -) - -_gdemote_rights = ChatAdminRights( - add_admins=False, - invite_users=False, - change_info=False, - ban_users=False, - delete_messages=False, - pin_messages=False, -) - -keym = KeyManager("GBLACKLISTS", cast=list) - - -@ultroid_cmd(pattern="gpromote( (.*)|$)", fullsudo=True) -async def _(e): - x = e.pattern_match.group(1).strip() - ultroid_bot = e.client - if not x: - return await e.eor(get_string("schdl_2"), time=5) - user = await e.get_reply_message() - if user: - ev = await e.eor("`Promoting Replied User Globally`") - ok = e.text.split() - key = "all" - if len(ok) > 1 and (("group" in ok[1]) or ("channel" in ok[1])): - key = ok[1] - rank = ok[2] if len(ok) > 2 else "AdMin" - c = 0 - user.id = user.peer_id.user_id if e.is_private else user.from_id.user_id - async for x in e.client.iter_dialogs(): - if ( - "group" in key.lower() - and x.is_group - or "group" not in key.lower() - and "channel" in key.lower() - and x.is_channel - ): - try: - await e.client( - EditAdminRequest( - x.id, - user.id, - _gpromote_rights, - rank, - ), - ) - c += 1 - except BaseException: - pass - elif ( - ("group" not in key.lower() or x.is_group) - and ( - "group" in key.lower() - or "channel" not in key.lower() - or x.is_channel - ) - and ( - "group" in key.lower() - or "channel" in key.lower() - or x.is_group - or x.is_channel - ) - ): - try: - await e.client( - EditAdminRequest( - x.id, - user.id, - _gpromote_rights, - rank, - ), - ) - c += 1 - except Exception as er: - LOGS.info(er) - await eor(ev, f"Promoted The Replied Users in Total : {c} {key} chats") - else: - k = e.text.split() - if not k[1]: - return await eor( - e, "`Give someone's username/id or replied to user.", time=5 - ) - user = k[1] - if user.isdigit(): - user = int(user) - try: - name = await e.client.get_entity(user) - except BaseException: - return await e.eor(f"`No User Found Regarding {user}`", time=5) - ev = await e.eor(f"`Promoting {name.first_name} globally.`") - key = "all" - if len(k) > 2 and (("group" in k[2]) or ("channel" in k[2])): - key = k[2] - rank = k[3] if len(k) > 3 else "AdMin" - c = 0 - async for x in e.client.iter_dialogs(): - if ( - "group" in key.lower() - and x.is_group - or "group" not in key.lower() - and "channel" in key.lower() - and x.is_channel - or "group" not in key.lower() - and "channel" not in key.lower() - and (x.is_group or x.is_channel) - ): - try: - await ultroid_bot( - EditAdminRequest( - x.id, - user, - _gpromote_rights, - rank, - ), - ) - c += 1 - except BaseException: - pass - await eor(ev, f"Promoted {name.first_name} in Total : {c} {key} chats.") - - -@ultroid_cmd(pattern="gdemote( (.*)|$)", fullsudo=True) -async def _(e): - x = e.pattern_match.group(1).strip() - ultroid_bot = e.client - if not x: - return await e.eor(get_string("schdl_2"), time=5) - user = await e.get_reply_message() - if user: - user.id = user.peer_id.user_id if e.is_private else user.from_id.user_id - ev = await e.eor("`Demoting Replied User Globally`") - ok = e.text.split() - key = "all" - if len(ok) > 1 and (("group" in ok[1]) or ("channel" in ok[1])): - key = ok[1] - rank = "Not AdMin" - c = 0 - async for x in e.client.iter_dialogs(): - if ( - "group" in key.lower() - and x.is_group - or "group" not in key.lower() - and "channel" in key.lower() - and x.is_channel - or "group" not in key.lower() - and "channel" not in key.lower() - and (x.is_group or x.is_channel) - ): - try: - await ultroid_bot( - EditAdminRequest( - x.id, - user.id, - _gdemote_rights, - rank, - ), - ) - c += 1 - except BaseException: - pass - await eor(ev, f"Demoted The Replied Users in Total : {c} {key} chats") - else: - k = e.text.split() - if not k[1]: - return await eor( - e, "`Give someone's username/id or replied to user.", time=5 - ) - user = k[1] - if user.isdigit(): - user = int(user) - try: - name = await ultroid_bot.get_entity(user) - except BaseException: - return await e.eor(f"`No User Found Regarding {user}`", time=5) - ev = await e.eor(f"`Demoting {name.first_name} globally.`") - key = "all" - if len(k) > 2 and (("group" in k[2]) or ("channel" in k[2])): - key = k[2] - rank = "Not AdMin" - c = 0 - async for x in ultroid_bot.iter_dialogs(): - if ( - "group" in key.lower() - and x.is_group - or "group" not in key.lower() - and "channel" in key.lower() - and x.is_channel - or "group" not in key.lower() - and "channel" not in key.lower() - and (x.is_group or x.is_channel) - ): - try: - await ultroid_bot( - EditAdminRequest( - x.id, - user, - _gdemote_rights, - rank, - ), - ) - c += 1 - except BaseException: - pass - await eor(ev, f"Demoted {name.first_name} in Total : {c} {key} chats.") - - -@ultroid_cmd(pattern="ungban( (.*)|$)", fullsudo=True) -async def _(e): - xx = await e.eor("`UnGbanning...`") - match = e.pattern_match.group(1).strip() - peer = None - if e.reply_to_msg_id: - userid = (await e.get_reply_message()).sender_id - elif match: - try: - userid = int(match) - except ValueError: - userid = match - try: - userid = (await e.client.get_entity(userid)).id - except Exception as er: - return await xx.edit(f"Failed to get User...\nError: {er}") - elif e.is_private: - userid = e.chat_id - else: - return await xx.eor("`Reply to some msg or add their id.`", time=5) - if not is_gbanned(userid): - return await xx.edit("`User/Channel is not Gbanned...`") - try: - if not peer: - peer = await e.client.get_entity(userid) - name = inline_mention(peer) - except BaseException: - userid = int(userid) - name = str(userid) - chats = 0 - if e.client._dialogs: - dialog = e.client._dialogs - else: - dialog = await e.client.get_dialogs() - e.client._dialogs.extend(dialog) - for ggban in dialog: - if ggban.is_group or ggban.is_channel: - try: - await e.client.edit_permissions(ggban.id, userid, view_messages=True) - chats += 1 - except FloodWaitError as fw: - LOGS.info( - f"[FLOOD_WAIT_ERROR] : on Ungban\nSleeping for {fw.seconds+10}" - ) - await asyncio.sleep(fw.seconds + 10) - try: - await e.client.edit_permissions( - ggban.id, userid, view_messages=True - ) - chats += 1 - except BaseException as er: - LOGS.exception(er) - except (ChatAdminRequiredError, ValueError): - pass - except BaseException as er: - LOGS.exception(er) - ungban(userid) - if isinstance(peer, User): - await e.client(UnblockRequest(userid)) - await xx.edit( - f"`Ungbaned` {name} in {chats} `chats.\nRemoved from gbanwatch.`", - ) - - -@ultroid_cmd(pattern="gban( (.*)|$)", fullsudo=True) -async def _(e): - xx = await e.eor("`Gbanning...`") - reason = "" - if e.reply_to_msg_id: - userid = (await e.get_reply_message()).sender_id - try: - reason = e.text.split(" ", maxsplit=1)[1] - except IndexError: - pass - elif e.pattern_match.group(1).strip(): - usr = e.text.split(maxsplit=2)[1] - try: - userid = await e.client.parse_id(usr) - except ValueError: - userid = usr - try: - reason = e.text.split(maxsplit=2)[2] - except IndexError: - pass - elif e.is_private: - userid = e.chat_id - try: - reason = e.text.split(" ", maxsplit=1)[1] - except IndexError: - pass - else: - return await xx.eor("`Reply to some msg or add their id.`", time=5) - user = None - try: - user = await e.client.get_entity(userid) - name = inline_mention(user) - except BaseException: - userid = int(userid) - name = str(userid) - chats = 0 - if userid == ultroid_bot.uid: - return await xx.eor("`I can't gban myself.`", time=3) - elif userid in DEVLIST: - return await xx.eor("`I can't gban my Developers.`", time=3) - elif is_gbanned(userid): - return await eod( - xx, - "`User is already gbanned and added to gbanwatch.`", - time=4, - ) - if e.client._dialogs: - dialog = e.client._dialogs - else: - dialog = await e.client.get_dialogs() - e.client._dialogs.extend(dialog) - for ggban in dialog: - if ggban.is_group or ggban.is_channel: - try: - await e.client.edit_permissions(ggban.id, userid, view_messages=False) - chats += 1 - except FloodWaitError as fw: - LOGS.info( - f"[FLOOD_WAIT_ERROR] : on GBAN Command\nSleeping for {fw.seconds+10}" - ) - await asyncio.sleep(fw.seconds + 10) - try: - await e.client.edit_permissions( - ggban.id, userid, view_messages=False - ) - chats += 1 - except BaseException as er: - LOGS.exception(er) - except (ChatAdminRequiredError, ValueError): - pass - except BaseException as er: - LOGS.exception(er) - gban(userid, reason) - if isinstance(user, User): - await e.client(BlockRequest(userid)) - gb_msg = f"**#Gbanned** {name} `in {chats} chats and added to gbanwatch!`" - if reason: - gb_msg += f"\n**Reason** : {reason}" - await xx.edit(gb_msg) - - -@ultroid_cmd(pattern="g(admin|)cast( (.*)|$)", fullsudo=True) -async def gcast(event): - text, btn, reply = "", None, None - if xx := event.pattern_match.group(2): - msg, btn = get_msg_button(event.text.split(maxsplit=1)[1]) - elif event.is_reply: - reply = await event.get_reply_message() - msg = reply.text - if reply.buttons: - btn = format_btn(reply.buttons) - else: - msg, btn = get_msg_button(msg) - else: - return await eor( - event, "`Give some text to Globally Broadcast or reply a message..`" - ) - - kk = await event.eor("`Globally Broadcasting Msg...`") - er = 0 - done = 0 - err = "" - if event.client._dialogs: - dialog = event.client._dialogs - else: - dialog = await event.client.get_dialogs() - event.client._dialogs.extend(dialog) - for x in dialog: - if x.is_group: - chat = x.entity.id - if ( - not keym.contains(chat) - and int(f"-100{str(chat)}") not in NOSPAM_CHAT - and ( - ( - event.text[2:7] != "admin" - or (x.entity.admin_rights or x.entity.creator) - ) - ) - ): - try: - if btn: - bt = create_tl_btn(btn) - await something( - event, - msg, - reply.media if reply else None, - bt, - chat=chat, - reply=False, - ) - else: - await event.client.send_message( - chat, msg, file=reply.media if reply else None - ) - done += 1 - except FloodWaitError as fw: - await asyncio.sleep(fw.seconds + 10) - try: - if btn: - bt = create_tl_btn(btn) - await something( - event, - msg, - reply.media if reply else None, - bt, - chat=chat, - reply=False, - ) - else: - await event.client.send_message( - chat, msg, file=reply.media if reply else None - ) - done += 1 - except Exception as rr: - err += f"• {rr}\n" - er += 1 - except BaseException as h: - err += f"• {str(h)}" + "\n" - er += 1 - text += f"Done in {done} chats, error in {er} chat(s)" - if err != "": - open("gcast-error.log", "w+").write(err) - text += f"\nYou can do `{HNDLR}ul gcast-error.log` to know error report." - await kk.edit(text) - - -@ultroid_cmd(pattern="gucast( (.*)|$)", fullsudo=True) -async def gucast(event): - msg, btn, reply = "", None, None - if xx := event.pattern_match.group(1).strip(): - msg, btn = get_msg_button(event.text.split(maxsplit=1)[1]) - elif event.is_reply: - reply = await event.get_reply_message() - msg = reply.text - if reply.buttons: - btn = format_btn(reply.buttons) - else: - msg, btn = get_msg_button(msg) - else: - return await eor( - event, "`Give some text to Globally Broadcast or reply a message..`" - ) - kk = await event.eor("`Globally Broadcasting Msg...`") - er = 0 - done = 0 - if event.client._dialogs: - dialog = event.client._dialogs - else: - dialog = await event.client.get_dialogs() - event.client._dialogs.extend(dialog) - for x in dialog: - if x.is_user and not x.entity.bot: - chat = x.id - if not keym.contains(chat): - try: - if btn: - bt = create_tl_btn(btn) - await something( - event, - msg, - reply.media if reply else None, - bt, - chat=chat, - reply=False, - ) - else: - await event.client.send_message( - chat, msg, file=reply.media if reply else None - ) - done += 1 - except BaseException: - er += 1 - await kk.edit(f"Done in {done} chats, error in {er} chat(s)") - - -@ultroid_cmd(pattern="gkick( (.*)|$)", fullsudo=True) -async def gkick(e): - xx = await e.eor("`Gkicking...`") - if e.reply_to_msg_id: - userid = (await e.get_reply_message()).sender_id - elif e.pattern_match.group(1).strip(): - userid = await e.client.parse_id(e.pattern_match.group(1).strip()) - elif e.is_private: - userid = e.chat_id - else: - return await xx.edit("`Reply to some msg or add their id.`", time=5) - name = (await e.client.get_entity(userid)).first_name - chats = 0 - if userid == ultroid_bot.uid: - return await xx.eor("`I can't gkick myself.`", time=3) - if userid in DEVLIST: - return await xx.eor("`I can't gkick my Developers.`", time=3) - if e.client._dialogs: - dialog = e.client._dialogs - else: - dialog = await e.client.get_dialogs() - e.client._dialogs.extend(dialog) - for gkick in dialog: - if gkick.is_group or gkick.is_channel: - try: - await e.client.kick_participant(gkick.id, userid) - chats += 1 - except BaseException: - pass - await xx.edit(f"`Gkicked` [{name}](tg://user?id={userid}) `in {chats} chats.`") - - -@ultroid_cmd(pattern="gmute( (.*)|$)", fullsudo=True) -async def _(e): - xx = await e.eor("`Gmuting...`") - if e.reply_to_msg_id: - userid = (await e.get_reply_message()).sender_id - elif e.pattern_match.group(1).strip(): - userid = await e.client.parse_id(e.pattern_match.group(1).strip()) - elif e.is_private: - userid = e.chat_id - else: - return await xx.eor("`Reply to some msg or add their id.`", tome=5, time=5) - name = await e.client.get_entity(userid) - chats = 0 - if userid == ultroid_bot.uid: - return await xx.eor("`I can't gmute myself.`", time=3) - if userid in DEVLIST: - return await xx.eor("`I can't gmute my Developers.`", time=3) - if is_gmuted(userid): - return await xx.eor("`User is already gmuted.`", time=4) - if e.client._dialogs: - dialog = e.client._dialogs - else: - dialog = await e.client.get_dialogs() - e.client._dialogs.extend(dialog) - for onmute in dialog: - if onmute.is_group: - try: - await e.client.edit_permissions(onmute.id, userid, send_messages=False) - chats += 1 - except BaseException: - pass - gmute(userid) - await xx.edit(f"`Gmuted` {inline_mention(name)} `in {chats} chats.`") - - -@ultroid_cmd(pattern="ungmute( (.*)|$)", fullsudo=True) -async def _(e): - xx = await e.eor("`UnGmuting...`") - if e.reply_to_msg_id: - userid = (await e.get_reply_message()).sender_id - elif e.pattern_match.group(1).strip(): - userid = await e.client.parse_id(e.pattern_match.group(1).strip()) - elif e.is_private: - userid = e.chat_id - else: - return await xx.eor("`Reply to some msg or add their id.`", time=5) - name = (await e.client.get_entity(userid)).first_name - chats = 0 - if not is_gmuted(userid): - return await xx.eor("`User is not gmuted.`", time=3) - if e.client._dialogs: - dialog = e.client._dialogs - else: - dialog = await e.client.get_dialogs() - e.client._dialogs.extend(dialog) - for hurr in dialog: - if hurr.is_group: - try: - await e.client.edit_permissions(hurr.id, userid, send_messages=True) - chats += 1 - except BaseException: - pass - ungmute(userid) - await xx.edit(f"`Ungmuted` {inline_mention(name)} `in {chats} chats.`") - - -@ultroid_cmd( - pattern="listgban$", -) -async def list_gengbanned(event): - users = list_gbanned() - x = await event.eor(get_string("com_1")) - msg = "" - if not users: - return await x.edit("`You haven't GBanned anyone!`") - for i in users: - try: - name = await event.client.get_entity(int(i)) - except BaseException: - name = i - msg += f"User: {inline_mention(name, html=True)}\n" - reason = users[i] - msg += f"Reason: {reason}\n\n" if reason is not None else "\n" - gbanned_users = f"List of users GBanned by {OWNER_NAME}:\n\n{msg}" - if len(gbanned_users) > 4096: - with open("gbanned.txt", "w") as f: - f.write( - gbanned_users.replace("", "") - .replace("", "") - .replace("", "") - ) - await x.reply( - file="gbanned.txt", - message=f"List of users GBanned by {inline_mention(ultroid_bot.me)}", - ) - os.remove("gbanned.txt") - await x.delete() - else: - await x.edit(gbanned_users, parse_mode="html") - - -@ultroid_cmd( - pattern="gstat( (.*)|$)", -) -async def gstat_(e): - xx = await e.eor(get_string("com_1")) - if e.is_private: - userid = (await e.get_chat()).id - elif e.reply_to_msg_id: - userid = (await e.get_reply_message()).sender_id - elif e.pattern_match.group(1).strip(): - try: - userid = await e.client.parse_id(e.pattern_match.group(1).strip()) - except Exception as err: - return await xx.eor(f"{err}", time=10) - else: - return await xx.eor("`Reply to some msg or add their id.`", time=5) - name = (await e.client.get_entity(userid)).first_name - msg = f"**{name} is " - is_banned = is_gbanned(userid) - reason = list_gbanned().get(userid) - if is_banned: - msg += "Globally Banned" - msg += f" with reason** `{reason}`" if reason else ".**" - else: - msg += "not Globally Banned.**" - await xx.edit(msg) - - -@ultroid_cmd(pattern="gblacklist$") -async def blacklist_(event): - await gblacker(event, "add") - - -@ultroid_cmd(pattern="ungblacklist$") -async def ungblacker(event): - await gblacker(event, "remove") - - -async def gblacker(event, type_): - try: - chat_id = int(event.text.split(maxsplit=1)[1]) - try: - chat_id = (await event.client.get_entity(chat_id)).id - except Exception as e: - return await event.eor(f"**ERROR**\n`{str(e)}`") - except IndexError: - chat_id = event.chat_id - if type_ == "add": - keym.add(chat_id) - elif type_ == "remove": - keym.remove(chat_id) - await event.eor(f"Global Broadcasts: \n{type_}ed {chat_id}") diff --git a/plugins/greetings.py b/plugins/greetings.py deleted file mode 100644 index 7eda1f53b5..0000000000 --- a/plugins/greetings.py +++ /dev/null @@ -1,205 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - ----- Welcomes ---- -• `{i}setwelcome ` - Set welcome message in the current chat. - -• `{i}clearwelcome` - Delete the welcome in the current chat. - -• `{i}getwelcome` - Get the welcome message in the current chat. - ----- GoodByes ---- -• `{i}setgoodbye ` - Set goodbye message in the current chat. - -• `{i}cleargoodbye` - Delete the goodbye in the current chat. - -• `{i}getgoodbye` - Get the goodbye message in the current chat. - -• `{i}thankmembers on/off` - Send a thank you sticker on hitting a members count of 100*x in your groups. -""" -import os - -from telegraph import upload_file as uf -from telethon.utils import pack_bot_file_id - -from pyUltroid.dB.greetings_db import ( - add_goodbye, - add_thanks, - add_welcome, - delete_goodbye, - delete_welcome, - get_goodbye, - get_welcome, - must_thank, - remove_thanks, -) -from pyUltroid.fns.tools import create_tl_btn, format_btn, get_msg_button - -from . import HNDLR, eor, get_string, mediainfo, ultroid_cmd -from ._inline import something - -Note = "\n\nNote: `{mention}`, `{group}`, `{count}`, `{name}`, `{fullname}`, `{username}`, `{userid}` can be used as formatting parameters.\n\n" - - -@ultroid_cmd(pattern="setwelcome", groups_only=True) -async def setwel(event): - x = await event.eor(get_string("com_1")) - r = await event.get_reply_message() - btn = format_btn(r.buttons) if (r and r.buttons) else None - try: - text = event.text.split(maxsplit=1)[1] - except IndexError: - text = r.text if r else None - if r and r.media: - wut = mediainfo(r.media) - if wut.startswith(("pic", "gif")): - dl = await r.download_media() - variable = 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) - os.remove(dl) - m = f"https://graph.org{variable[0]}" - elif wut == "web": - m = None - else: - m = pack_bot_file_id(r.media) - if r.text: - txt = r.text - if not btn: - txt, btn = get_msg_button(r.text) - add_welcome(event.chat_id, txt, m, btn) - else: - add_welcome(event.chat_id, None, m, btn) - await eor(x, get_string("grt_1")) - elif text: - if not btn: - txt, btn = get_msg_button(text) - add_welcome(event.chat_id, txt, None, btn) - await eor(x, get_string("grt_1")) - else: - await eor(x, get_string("grt_3"), time=5) - - -@ultroid_cmd(pattern="clearwelcome$", groups_only=True) -async def clearwel(event): - if not get_welcome(event.chat_id): - return await event.eor(get_string("grt_4"), time=5) - delete_welcome(event.chat_id) - await event.eor(get_string("grt_5"), time=5) - - -@ultroid_cmd(pattern="getwelcome$", groups_only=True) -async def listwel(event): - wel = get_welcome(event.chat_id) - if not wel: - return await event.eor(get_string("grt_4"), time=5) - msgg, med = wel["welcome"], wel["media"] - if wel.get("button"): - btn = create_tl_btn(wel["button"]) - return await something(event, msgg, med, btn) - await event.reply(f"**Welcome Note in this chat**\n\n`{msgg}`", file=med) - await event.delete() - - -@ultroid_cmd(pattern="setgoodbye", groups_only=True) -async def setgb(event): - x = await event.eor(get_string("com_1")) - r = await event.get_reply_message() - btn = format_btn(r.buttons) if (r and r.buttons) else None - try: - text = event.text.split(maxsplit=1)[1] - except IndexError: - text = r.text if r else None - if r and r.media: - wut = mediainfo(r.media) - if wut.startswith(("pic", "gif")): - dl = await r.download_media() - variable = 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) - os.remove(dl) - m = f"https://graph.org{variable[0]}" - elif wut == "web": - m = None - else: - m = pack_bot_file_id(r.media) - if r.text: - txt = r.text - if not btn: - txt, btn = get_msg_button(r.text) - add_goodbye(event.chat_id, txt, m, btn) - else: - add_goodbye(event.chat_id, None, m, btn) - await eor(x, "`Goodbye note saved`") - elif text: - if not btn: - txt, btn = get_msg_button(text) - add_goodbye(event.chat_id, txt, None, btn) - await eor(x, "`Goodbye note saved`") - else: - await eor(x, get_string("grt_7"), time=5) - - -@ultroid_cmd(pattern="cleargoodbye$", groups_only=True) -async def clearwgb(event): - if not get_goodbye(event.chat_id): - return await event.eor(get_string("grt_6"), time=5) - delete_goodbye(event.chat_id) - await event.eor("`Goodbye Note Deleted`", time=5) - - -@ultroid_cmd(pattern="getgoodbye$", groups_only=True) -async def listgd(event): - wel = get_goodbye(event.chat_id) - if not wel: - return await event.eor(get_string("grt_6"), time=5) - msgg = wel["goodbye"] - med = wel["media"] - if wel.get("button"): - btn = create_tl_btn(wel["button"]) - return await something(event, msgg, med, btn) - await event.reply(f"**Goodbye Note in this chat**\n\n`{msgg}`", file=med) - await event.delete() - - -@ultroid_cmd(pattern="thankmembers (on|off)", groups_only=True) -async def thank_set(event): - type_ = event.pattern_match.group(1).strip() - if not type_ or type_ == "": - await eor( - event, - f"**Current Chat Settings:**\n**Thanking Members:** `{must_thank(event.chat_id)}`\n\nUse `{HNDLR}thankmembers on` or `{HNDLR}thankmembers off` to toggle current settings!", - ) - return - chat = event.chat_id - if type_.lower() == "on": - add_thanks(chat) - elif type_.lower() == "off": - remove_thanks(chat) - await eor( - event, - f"**Done! Thank you members has been turned** `{type_.lower()}` **for this chat**!", - ) diff --git a/plugins/imagetools.py b/plugins/imagetools.py deleted file mode 100644 index fa65830b1d..0000000000 --- a/plugins/imagetools.py +++ /dev/null @@ -1,292 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}border ` - To create border around that media.. - Ex - `{i}border 12,22,23` - - `{i}border 12,22,23 ; width (in number)` - -• `{i}grey ` - To make it black nd white. - -• `{i}color ` - To make it Colorfull. - -• `{i}toon ` - To make it toon. - -• `{i}danger ` - To make it look Danger. - -• `{i}negative ` - To make negative image. - -• `{i}blur ` - To make it blurry. - -• `{i}quad ` - create a Vortex. - -• `{i}mirror ` - To create mirror pic. - -• `{i}flip ` - To make it flip. - -• `{i}sketch ` - To draw its sketch. - -• `{i}blue ` - just cool. - -• `{i}csample ` - example : `{i}csample red` - `{i}csample #ffffff` - -• `{i}pixelator ` - Create a Pixelated Image.. -""" -import os - -from . import LOGS, con - -try: - import cv2 -except ImportError: - LOGS.error(f"{__file__}: OpenCv not Installed.") - -import numpy as np - -try: - from PIL import Image -except ImportError: - Image = None - LOGS.info(f"{__file__}: PIL not Installed.") -from telegraph import upload_file as upf -from telethon.errors.rpcerrorlist import ( - ChatSendMediaForbiddenError, - MessageDeleteForbiddenError, -) - -from . import ( - Redis, - async_searcher, - download_file, - get_string, - requests, - udB, - ultroid_cmd, -) - - -@ultroid_cmd(pattern="color$") -async def _(event): - reply = await event.get_reply_message() - if not (reply and reply.media): - return await event.eor("`Reply To a Black and White Image`") - xx = await event.eor("`Coloring image 🎨🖌️...`") - image = await reply.download_media() - img = cv2.VideoCapture(image) - ret, frame = img.read() - cv2.imwrite("ult.jpg", frame) - if udB.get_key("DEEP_API"): - key = Redis("DEEP_API") - else: - key = "quickstart-QUdJIGlzIGNvbWluZy4uLi4K" - r = requests.post( - "https://api.deepai.org/api/colorizer", - files={"image": open("ult.jpg", "rb")}, - headers={"api-key": key}, - ) - os.remove("ult.jpg") - os.remove(image) - if "status" in r.json(): - return await event.edit( - r.json()["status"] + "\nGet api nd set `{i}setdb DEEP_API key`" - ) - r_json = r.json()["output_url"] - await event.client.send_file(event.chat_id, r_json, reply_to=reply) - await xx.delete() - - -@ultroid_cmd(pattern="(grey|blur|negative|danger|mirror|quad|sketch|flip|toon)$") -async def ult_tools(event): - match = event.pattern_match.group(1) - ureply = await event.get_reply_message() - if not (ureply and (ureply.media)): - await event.eor(get_string("cvt_3")) - return - ultt = await ureply.download_media() - xx = await event.eor(get_string("com_1")) - if ultt.endswith(".tgs"): - xx = await xx.edit(get_string("sts_9")) - file = await con.convert(ultt, convert_to="png", outname="ult") - ult = cv2.imread(file) - if match == "grey": - ultroid = cv2.cvtColor(ult, cv2.COLOR_BGR2GRAY) - elif match == "blur": - ultroid = cv2.GaussianBlur(ult, (35, 35), 0) - elif match == "negative": - ultroid = cv2.bitwise_not(ult) - elif match == "danger": - dan = cv2.cvtColor(ult, cv2.COLOR_BGR2RGB) - ultroid = cv2.cvtColor(dan, cv2.COLOR_HSV2BGR) - elif match == "mirror": - ish = cv2.flip(ult, 1) - ultroid = cv2.hconcat([ult, ish]) - elif match == "flip": - trn = cv2.flip(ult, 1) - ish = cv2.rotate(trn, cv2.ROTATE_180) - ultroid = cv2.vconcat([ult, ish]) - elif match == "quad": - ult = cv2.imread(file) - roid = cv2.flip(ult, 1) - mici = cv2.hconcat([ult, roid]) - fr = cv2.flip(mici, 1) - trn = cv2.rotate(fr, cv2.ROTATE_180) - ultroid = cv2.vconcat([mici, trn]) - elif match == "sketch": - gray_image = cv2.cvtColor(ult, cv2.COLOR_BGR2GRAY) - inverted_gray_image = 255 - gray_image - blurred_img = cv2.GaussianBlur(inverted_gray_image, (21, 21), 0) - inverted_blurred_img = 255 - blurred_img - ultroid = cv2.divide(gray_image, inverted_blurred_img, scale=256.0) - elif match == "toon": - height, width, _ = ult.shape - samples = np.zeros([height * width, 3], dtype=np.float32) - count = 0 - for x in range(height): - for y in range(width): - samples[count] = ult[x][y] - count += 1 - _, labels, centers = cv2.kmeans( - samples, - 12, - None, - (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10000, 0.0001), - 5, - cv2.KMEANS_PP_CENTERS, - ) - centers = np.uint8(centers) - ish = centers[labels.flatten()] - ultroid = ish.reshape(ult.shape) - cv2.imwrite("ult.jpg", ultroid) - await ureply.reply( - file="ult.jpg", - force_document=False, - ) - await xx.delete() - os.remove("ult.jpg") - os.remove(file) - - -@ultroid_cmd(pattern="csample (.*)") -async def sampl(ult): - if color := ult.pattern_match.group(1).strip(): - img = Image.new("RGB", (200, 100), f"{color}") - img.save("csample.png") - try: - try: - await ult.delete() - await ult.respond(f"Colour Sample for `{color}` !", file="csample.png") - except MessageDeleteForbiddenError: - await ult.reply(f"Colour Sample for `{color}` !", file="csample.png") - except ChatSendMediaForbiddenError: - await ult.eor("Umm! Sending Media is disabled here!") - - else: - await ult.eor("Wrong Color Name/Hex Code specified!") - - -@ultroid_cmd( - pattern="blue$", -) -async def ultd(event): - ureply = await event.get_reply_message() - xx = await event.eor("`...`") - if not (ureply and (ureply.media)): - await xx.edit(get_string("cvt_3")) - return - ultt = await ureply.download_media() - 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]}" - r = await async_searcher( - f"https://nekobot.xyz/api/imagegen?type=blurpify&image={lnk}", re_json=True - ) - ms = r.get("message") - if not r["success"]: - return await xx.edit(ms) - await download_file(ms, "ult.png") - img = Image.open("ult.png").convert("RGB") - img.save("ult.webp", "webp") - await event.client.send_file( - event.chat_id, - "ult.webp", - force_document=False, - reply_to=event.reply_to_msg_id, - ) - await xx.delete() - os.remove("ult.png") - os.remove("ult.webp") - os.remove(ultt) - - -@ultroid_cmd(pattern="border( (.*)|$)") -async def ok(event): - hm = await event.get_reply_message() - if not (hm and (hm.photo or hm.sticker)): - return await event.eor("`Reply to Sticker or Photo..`") - col = event.pattern_match.group(1).strip() - wh = 20 - if not col: - col = [255, 255, 255] - else: - try: - if ";" in col: - col_ = col.split(";", maxsplit=1) - wh = int(col_[1]) - col = col_[0] - col = [int(col) for col in col.split(",")[:2]] - except ValueError: - return await event.eor("`Not a Valid Input...`") - okla = await hm.download_media() - img1 = cv2.imread(okla) - constant = cv2.copyMakeBorder(img1, wh, wh, wh, wh, cv2.BORDER_CONSTANT, value=col) - cv2.imwrite("output.png", constant) - await event.client.send_file(event.chat.id, "output.png") - os.remove("output.png") - os.remove(okla) - await event.delete() - - -@ultroid_cmd(pattern="pixelator( (.*)|$)") -async def pixelator(event): - reply_message = await event.get_reply_message() - if not (reply_message and (reply_message.photo or reply_message.sticker)): - return await event.eor("`Reply to a photo`") - hw = 50 - try: - hw = int(event.pattern_match.group(1).strip()) - except (ValueError, TypeError): - pass - msg = await event.eor(get_string("com_1")) - image = await reply_message.download_media() - input_ = cv2.imread(image) - height, width = input_.shape[:2] - w, h = (hw, hw) - temp = cv2.resize(input_, (w, h), interpolation=cv2.INTER_LINEAR) - output = cv2.resize(temp, (width, height), interpolation=cv2.INTER_NEAREST) - cv2.imwrite("output.jpg", output) - await msg.respond("• Pixelated by Ultroid", file="output.jpg") - await msg.delete() - os.remove("output.jpg") - os.remove(image) diff --git a/plugins/locks.py b/plugins/locks.py deleted file mode 100644 index 86946648f6..0000000000 --- a/plugins/locks.py +++ /dev/null @@ -1,39 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}lock ` - Lock the Used Setting in Used Group. - -• `{i}unlock ` - UNLOCK the Used Setting in Used Group. -""" -from telethon.tl.functions.messages import EditChatDefaultBannedRightsRequest - -from pyUltroid.fns.admins import lock_unlock - -from . import ultroid_cmd - - -@ultroid_cmd( - pattern="(un|)lock( (.*)|$)", admins_only=True, manager=True, require="change_info" -) -async def un_lock(e): - mat = e.pattern_match.group(2).strip() - if not mat: - return await e.eor("`Give some Proper Input..`", time=5) - lock = e.pattern_match.group(1) == "" - ml = lock_unlock(mat, lock) - if not ml: - return await e.eor("`Incorrect Input`", time=5) - msg = "Locked" if lock else "Unlocked" - try: - await e.client(EditChatDefaultBannedRightsRequest(e.chat_id, ml)) - except Exception as er: - return await e.eor(str(er)) - await e.eor(f"**{msg}** - `{mat}` ! ") diff --git a/plugins/logo.py b/plugins/logo.py deleted file mode 100644 index 69c0866f85..0000000000 --- a/plugins/logo.py +++ /dev/null @@ -1,104 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}logo ` - Generate a logo of the given Text - Or Reply To image , to write ur text on it. - Or Reply To Font File, To write with that font. - -""" -import glob -import os -import random - -from telethon.tl.types import InputMessagesFilterPhotos - -try: - from PIL import Image -except ImportError: - Image = None -from pyUltroid.fns.misc import unsplashsearch -from pyUltroid.fns.tools import LogoHelper - -from . import OWNER_ID, OWNER_NAME, download_file, get_string, mediainfo, ultroid_cmd - - -@ultroid_cmd(pattern="logo( (.*)|$)") -async def logo_gen(event): - xx = await event.eor(get_string("com_1")) - name = event.pattern_match.group(1).strip() - if not name: - return await xx.eor("`Give a name too!`", time=5) - bg_, font_ = None, None - if event.reply_to_msg_id: - temp = await event.get_reply_message() - if temp.media: - if hasattr(temp.media, "document") and ( - ("font" in temp.file.mime_type) - or (".ttf" in temp.file.name) - or (".otf" in temp.file.name) - ): - font_ = await temp.download_media("resources/fonts/") - elif "pic" in mediainfo(temp.media): - bg_ = await temp.download_media() - if not bg_: - if event.client._bot: - SRCH = [ - "blur background", - "background", - "neon lights", - "nature", - "abstract", - "space", - "3d render", - ] - res = await unsplashsearch(random.choice(SRCH), limit=1) - bg_, _ = await download_file(res[0], "resources/downloads/logo.png") - newimg = "resources/downloads/unsplash-temp.jpg" - img_ = Image.open(bg_) - img_.resize((5000, 5000)).save(newimg) - os.remove(bg_) - bg_ = newimg - else: - pics = [] - async for i in event.client.iter_messages( - "@UltroidLogos", filter=InputMessagesFilterPhotos - ): - pics.append(i) - id_ = random.choice(pics) - bg_ = await id_.download_media() - - if not font_: - fpath_ = glob.glob("resources/fonts/*") - font_ = random.choice(fpath_) - if len(name) <= 8: - strke = 10 - elif len(name) >= 9: - strke = 5 - else: - strke = 20 - name = LogoHelper.make_logo( - bg_, - name, - font_, - fill="white", - stroke_width=strke, - stroke_fill="black", - ) - await xx.edit("`Done!`") - await event.client.send_file( - event.chat_id, - file=name, - caption=f"Logo by [{OWNER_NAME}](tg://user?id={OWNER_ID})", - force_document=True, - ) - os.remove(name) - await xx.delete() - if os.path.exists(bg_): - os.remove(bg_) diff --git a/plugins/mediatools.py b/plugins/mediatools.py deleted file mode 100644 index 3c47efe701..0000000000 --- a/plugins/mediatools.py +++ /dev/null @@ -1,146 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}mediainfo //` - To get info about it. - -• `{i}rotate ` - Rotate any video/photo/media.. - Note : for video it should be angle of 90's -""" -import os -import time -from datetime import datetime as dt - -from pyUltroid.fns.misc import rotate_image -from pyUltroid.fns.tools import make_html_telegraph - -from . import ( - LOGS, - Telegraph, - bash, - downloader, - get_string, - is_url_ok, - mediainfo, - ultroid_cmd, -) - -try: - import cv2 -except ImportError: - LOGS.info("WARNING: 'cv2' not found!") - cv2 = None - - -@ultroid_cmd(pattern="mediainfo( (.*)|$)") -async def mi(e): - r = await e.get_reply_message() - match = e.pattern_match.group(1).strip() - taime = time.time() - extra = "" - if r and r.media: - xx = mediainfo(r.media) - murl = r.media.stringify() - url = await make_html_telegraph("Mediainfo", f"
    {murl}
    ") - extra = f"**[{xx}]({url})**\n\n" - e = await e.eor(f"{extra}`Loading More...`", link_preview=False) - - if hasattr(r.media, "document"): - file = r.media.document - mime_type = file.mime_type - filename = r.file.name - if not filename: - if "audio" in mime_type: - filename = "audio_" + dt.now().isoformat("_", "seconds") + ".ogg" - elif "video" in mime_type: - filename = "video_" + dt.now().isoformat("_", "seconds") + ".mp4" - dl = await downloader( - f"resources/downloads/{filename}", - file, - e, - taime, - f"{extra}`Loading More...`", - ) - - naam = dl.name - else: - naam = await r.download_media() - elif match and ( - os.path.isfile(match) - or (match.startswith("https://") and (await is_url_ok(match))) - ): - naam, xx = match, "file" - else: - return await e.eor(get_string("cvt_3"), time=5) - out, er = await bash(f"mediainfo '{naam}'") - if er: - LOGS.info(er) - out = extra or str(er) - return await e.edit(out, link_preview=False) - makehtml = "" - if naam.endswith((".jpg", ".png")): - if os.path.exists(naam): - med = "https://graph.org" + Telegraph.upload_file(naam)[0]["src"] - else: - med = match - makehtml += f"
    " - for line in out.split("\n"): - line = line.strip() - if not line: - makehtml += "
    " - elif ":" not in line: - makehtml += f"

    {line}

    " - else: - makehtml += f"

    {line}

    " - try: - urll = await make_html_telegraph("Mediainfo", makehtml) - except Exception as er: - LOGS.exception(er) - return - await e.eor(f"{extra}[{get_string('mdi_1')}]({urll})", link_preview=False) - if not match: - os.remove(naam) - - -@ultroid_cmd(pattern="rotate( (.*)|$)") -async def rotate_(ult): - match = ult.pattern_match.group(1).strip() - if not ult.is_reply: - return await ult.eor("`Reply to a media...`") - if match: - try: - match = int(match) - except ValueError: - match = None - if not match: - return await ult.eor("`Please provide a valid angle to rotate media..`") - reply = await ult.get_reply_message() - msg = await ult.eor(get_string("com_1")) - photo = reply.game.photo if reply.game else None - if reply.video: - media = await reply.download_media() - file = f"{media}.mp4" - await bash( - f'ffmpeg -i "{media}" -c copy -metadata:s:v:0 rotate={match} "{file}" -y' - ) - elif photo or reply.photo or reply.sticker: - media = await ult.client.download_media(photo or reply) - img = cv2.imread(media) - new_ = rotate_image(img, match) - file = "ult.png" - cv2.imwrite(file, new_) - else: - return await msg.edit("`Unsupported Media..\nReply to Photo/Video`") - if os.path.exists(file): - await ult.client.send_file( - ult.chat_id, file=file, video_note=bool(reply.video_note), reply_to=reply.id - ) - os.remove(media) - await msg.try_delete() diff --git a/plugins/misc.py b/plugins/misc.py deleted file mode 100644 index e82b6702e9..0000000000 --- a/plugins/misc.py +++ /dev/null @@ -1,140 +0,0 @@ -# Ultroid - UserBot -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}eod` - `Get Event of the Today` - -• `{i}pntrst ` - Download and send pinterest pins - -• `{i}gadget ` - Gadget Search from Telegram. - -• `{i}randomuser` - Generate details about a random user. - -• `{i}ascii ` - Convert replied image into html. -""" - -import os -from datetime import datetime as dt - -from bs4 import BeautifulSoup as bs - -try: - from htmlwebshot import WebShot -except ImportError: - WebShot = None -try: - from img2html.converter import Img2HTMLConverter -except ImportError: - Img2HTMLConverter = None - -from . import async_searcher, get_random_user_data, get_string, re, ultroid_cmd - - -@ultroid_cmd(pattern="eod$") -async def diela(e): - m = await e.eor(get_string("com_1")) - li = "https://daysoftheyear.com" - te = "🎊 **Events of the Day**\n\n" - da = dt.now() - month = da.strftime("%b") - li += f"/days/{month}/" + da.strftime("%F").split("-")[2] - ct = await async_searcher(li, re_content=True) - bt = bs(ct, "html.parser", from_encoding="utf-8") - ml = bt.find_all("a", "js-link-target", href=re.compile("daysoftheyear.com/days")) - for eve in ml[:5]: - te += f'• [{eve.text}]({eve["href"]})\n' - await m.edit(te, link_preview=False) - - -@ultroid_cmd( - pattern="pntrst( (.*)|$)", -) -async def pinterest(e): - m = e.pattern_match.group(1).strip() - if not m: - return await e.eor("`Give pinterest link.`", time=3) - soup = await async_searcher( - "https://www.expertstool.com/download-pinterest-video/", - data={"url": m}, - post=True, - ) - try: - _soup = bs(soup, "html.parser").find("table").tbody.find_all("tr") - except BaseException: - return await e.eor("`Wrong link or private pin.`", time=5) - file = _soup[1] if len(_soup) > 1 else _soup[0] - file = file.td.a["href"] - await e.client.send_file(e.chat_id, file, caption=f"Pin:- {m}") - - -@ultroid_cmd(pattern="gadget( (.*)|$)") -async def mobs(e): - mat = e.pattern_match.group(1).strip() - if not mat: - await e.eor("Please Give a Mobile Name to look for.") - query = mat.replace(" ", "%20") - jwala = f"https://gadgets.ndtv.com/search?searchtext={query}" - c = await async_searcher(jwala) - b = bs(c, "html.parser", from_encoding="utf-8") - co = b.find_all("div", "rvw-imgbox") - if not co: - return await e.eor("No Results Found!") - bt = await e.eor(get_string("com_1")) - out = "**📱 Mobile / Gadgets Search**\n\n" - li = co[0].find("a") - imu, title = None, li.find("img")["title"] - cont = await async_searcher(li["href"]) - nu = bs(cont, "html.parser", from_encoding="utf-8") - req = nu.find_all("div", "_pdsd") - imu = nu.find_all( - "img", src=re.compile("https://i.gadgets360cdn.com/products/large/") - ) - if imu: - imu = imu[0]["src"].split("?")[0] + "?downsize=*:420&output-quality=80" - out += f"☑️ **[{title}]({li['href']})**\n\n" - for fp in req: - ty = fp.findNext() - out += f"- **{ty.text}** - `{ty.findNext().text}`\n" - out += "_" - if imu == []: - imu = None - await e.reply(out, file=imu, link_preview=False) - await bt.delete() - - -@ultroid_cmd(pattern="randomuser") -async def _gen_data(event): - x = await event.eor(get_string("com_1")) - msg, pic = await get_random_user_data() - await event.reply(file=pic, message=msg) - await x.delete() - - -@ultroid_cmd( - pattern="ascii( (.*)|$)", -) -async def _(e): - if not Img2HTMLConverter: - return await e.eor("'img2html-converter' not installed!") - if not e.reply_to_msg_id: - return await e.eor(get_string("ascii_1")) - m = await e.eor(get_string("ascii_2")) - img = await (await e.get_reply_message()).download_media() - char = e.pattern_match.group(1).strip() or "■" - converter = Img2HTMLConverter(char=char) - html = converter.convert(img) - shot = WebShot(quality=85) - pic = await shot.create_pic_async(html=html) - await m.delete() - await e.reply(file=pic) - os.remove(pic) - os.remove(img) diff --git a/plugins/mute.py b/plugins/mute.py deleted file mode 100644 index c80d19726e..0000000000 --- a/plugins/mute.py +++ /dev/null @@ -1,210 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}mute ` - Mute user in current chat. - -• `{i}unmute ` - Unmute user in current chat. - -• `{i}dmute ` - Mute user in current chat by deleting msgs. - -• `{i}undmute ` - Unmute dmuted user in current chat. - -• `{i}tmute
    {value}\n" - await uu.edit(a, parse_mode="html") - - -@ultroid_cmd(pattern="wall( (.*)|$)") -async def wall(event): - inp = event.pattern_match.group(1).strip() - if not inp: - return await event.eor("`Give me something to search..`") - nn = await event.eor(get_string("com_1")) - query = f"hd {inp}" - images = await get_google_images(query) - for z in range(5): - await event.client.send_file(event.chat_id, file=images[z]["original"]) - await nn.delete() - - -@ultroid_cmd(pattern="q( (.*)|$)", manager=True, allow_pm=True) -async def quott_(event): - match = event.pattern_match.group(1).strip() - if not event.is_reply: - return await event.eor("`Reply to Message..`") - msg = await event.eor(get_string("com_1")) - reply = await event.get_reply_message() - replied_to, reply_ = None, None - if match: - spli_ = match.split(maxsplit=1) - if (spli_[0] in ["r", "reply"]) or ( - spli_[0].isdigit() and int(spli_[0]) in range(1, 21) - ): - if spli_[0].isdigit(): - if not event.client._bot: - reply_ = await event.client.get_messages( - event.chat_id, - min_id=event.reply_to_msg_id - 1, - reverse=True, - limit=int(spli_[0]), - ) - else: - id_ = reply.id - reply_ = [] - for msg_ in range(id_, id_ + int(spli_[0])): - msh = await event.client.get_messages(event.chat_id, ids=msg_) - if msh: - reply_.append(msh) - else: - replied_to = await reply.get_reply_message() - try: - match = spli_[1] - except IndexError: - match = None - user = None - if not reply_: - reply_ = reply - if match: - match = match.split(maxsplit=1) - if match: - if match[0].startswith("@") or match[0].isdigit(): - try: - match_ = await event.client.parse_id(match[0]) - user = await event.client.get_entity(match_) - except ValueError: - pass - match = match[1] if len(match) == 2 else None - else: - match = match[0] - if match == "random": - match = choice(all_col) - try: - file = await quotly.create_quotly( - reply_, bg=match, reply=replied_to, sender=user - ) - except Exception as er: - return await msg.edit(str(er)) - message = await reply.reply("Quotly by Ultroid", file=file) - os.remove(file) - await msg.delete() - return message diff --git a/plugins/stickertools.py b/plugins/stickertools.py deleted file mode 100644 index 9b8006c7d0..0000000000 --- a/plugins/stickertools.py +++ /dev/null @@ -1,521 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}destroy ` - To destroy the sticker. - -• `{i}tiny ` - To create Tiny stickers. - -• `{i}kang ` - Kang the sticker (add to your pack). - -• `{i}packkang ` - Kang the Complete sticker set (with custom name). - -• `{i}round ` - To extract round sticker. -""" -import glob -import io -import os -import random -from os import remove - -try: - import cv2 -except ImportError: - cv2 = None -try: - import numpy as np -except ImportError: - np = None -try: - from PIL import Image, ImageDraw -except ImportError: - pass - -from telethon.errors import PeerIdInvalidError, YouBlockedUserError -from telethon.tl.functions.messages import UploadMediaRequest -from telethon.tl.types import ( - DocumentAttributeFilename, - DocumentAttributeSticker, - InputPeerSelf, -) -from telethon.utils import get_input_document - -from . import ( - KANGING_STR, - LOGS, - asst, - async_searcher, - bash, - con, - functions, - get_string, - inline_mention, - mediainfo, - quotly, - types, - udB, - ultroid_cmd, -) - - -@ultroid_cmd(pattern="packkang") -async def pack_kangish(_): - _e = await _.get_reply_message() - local = None - try: - cmdtext = _.text.split(maxsplit=1)[1] - except IndexError: - cmdtext = None - if cmdtext and os.path.isdir(cmdtext): - local = True - elif not (_e and _e.sticker and _e.file.mime_type == "image/webp"): - return await _.eor(get_string("sts_4")) - msg = await _.eor(get_string("com_1")) - _packname = cmdtext or f"Ultroid Kang Pack By {_.sender_id}" - typee = None - if not local: - _id = _e.media.document.attributes[1].stickerset.id - _hash = _e.media.document.attributes[1].stickerset.access_hash - _get_stiks = await _.client( - functions.messages.GetStickerSetRequest( - stickerset=types.InputStickerSetID(id=_id, access_hash=_hash), hash=0 - ) - ) - docs = _get_stiks.documents - else: - docs = [] - files = glob.glob(cmdtext + "/*") - exte = files[-1] - if exte.endswith(".tgs"): - typee = "anim" - elif exte.endswith(".webm"): - typee = "vid" - count = 0 - for file in files: - if file.endswith((".tgs", ".webm")): - count += 1 - upl = await asst.upload_file(file) - docs.append(await asst(UploadMediaRequest(InputPeerSelf(), upl))) - if count % 5 == 0: - await msg.edit(f"`Uploaded {count} files.`") - - stiks = [] - for i in docs: - x = get_input_document(i) - stiks.append( - types.InputStickerSetItem( - document=x, - emoji=random.choice(["😐", "👍", "😂"]) - if local - else (i.attributes[1]).alt, - ) - ) - try: - short_name = "ult_" + _packname.replace(" ", "_") + str(_.id) - _r_e_s = await asst( - functions.stickers.CreateStickerSetRequest( - user_id=_.sender_id, - title=_packname, - short_name=f"{short_name}_by_{asst.me.username}", - animated=typee == "anim", - videos=typee == "vid", - stickers=stiks, - ) - ) - except PeerIdInvalidError: - return await msg.eor( - f"Hey {inline_mention(_.sender)} send `/start` to @{asst.me.username} and later try this command again.." - ) - except BaseException as er: - LOGS.exception(er) - return await msg.eor(str(er)) - await msg.eor( - get_string("sts_5").format(f"https://t.me/addstickers/{_r_e_s.set.short_name}"), - ) - - -@ultroid_cmd( - pattern="kang", -) -async def hehe(args): - ultroid_bot = args.client - xx = await args.eor(get_string("com_1")) - user = ultroid_bot.me - username = user.username - username = f"@{username}" if username else user.first_name - message = await args.get_reply_message() - photo = None - is_anim, is_vid = False, False - emoji = None - if not message: - return await xx.eor(get_string("sts_6")) - if message.photo: - photo = io.BytesIO() - photo = await ultroid_bot.download_media(message.photo, photo) - elif message.file and "image" in message.file.mime_type.split("/"): - photo = io.BytesIO() - await ultroid_bot.download_file(message.media.document, photo) - if ( - DocumentAttributeFilename(file_name="sticker.webp") - in message.media.document.attributes - ): - emoji = message.media.document.attributes[1].alt - - elif message.file and "video" in message.file.mime_type.split("/"): - xy = await message.download_media() - if (message.file.duration or 0) <= 10: - is_vid = True - photo = await con.create_webm(xy) - else: - y = cv2.VideoCapture(xy) - heh, lol = y.read() - cv2.imwrite("ult.webp", lol) - photo = "ult.webp" - elif message.file and "tgsticker" in message.file.mime_type: - await ultroid_bot.download_file( - message.media.document, - "AnimatedSticker.tgs", - ) - attributes = message.media.document.attributes - for attribute in attributes: - if isinstance(attribute, DocumentAttributeSticker): - emoji = attribute.alt - is_anim = True - photo = 1 - elif message.message: - photo = await quotly.create_quotly(message) - else: - return await xx.edit(get_string("com_4")) - if not udB.get_key("language") or udB.get_key("language") == "en": - ra = random.choice(KANGING_STR) - else: - ra = get_string("sts_11") - await xx.edit(f"`{ra}`") - if photo: - splat = args.text.split() - pack = 1 - if not emoji: - emoji = "🏵" - if len(splat) == 3: - pack = splat[2] # User sent ultroid_both - emoji = splat[1] - elif len(splat) == 2: - if splat[1].isnumeric(): - pack = int(splat[1]) - else: - emoji = splat[1] - - packname = f"ult_{user.id}_{pack}" - packnick = f"{username}'s Pack {pack}" - cmd = "/newpack" - file = io.BytesIO() - - if is_vid: - packname += "_vid" - packnick += " (Video)" - cmd = "/newvideo" - elif is_anim: - packname += "_anim" - packnick += " (Animated)" - cmd = "/newanimated" - else: - image = con.resize_photo_sticker(photo) - file.name = "sticker.png" - image.save(file, "PNG") - - response = await async_searcher(f"http://t.me/addstickers/{packname}") - htmlstr = response.split("\n") - - if ( - " A Telegram user has created the Sticker Set." - not in htmlstr - ): - async with ultroid_bot.conversation("@Stickers") as conv: - try: - await conv.send_message("/addsticker") - except YouBlockedUserError: - LOGS.info("Unblocking @Stickers for kang...") - await ultroid_bot(functions.contacts.UnblockRequest("stickers")) - await conv.send_message("/addsticker") - await conv.get_response() - await conv.send_message(packname) - x = await conv.get_response() - if x.text.startswith("Alright! Now send me the video sticker."): - await conv.send_file(photo, force_document=True) - x = await conv.get_response() - t = "50" if (is_anim or is_vid) else "120" - while t in x.message: - pack += 1 - packname = f"ult_{user.id}_{pack}" - packnick = f"{username}'s Pack {pack}" - if is_anim: - packname += "_anim" - packnick += " (Animated)" - elif is_vid: - packnick += " (Video)" - packname += "_vid" - await xx.edit(get_string("sts_13").format(pack)) - await conv.send_message("/addsticker") - await conv.get_response() - await conv.send_message(packname) - x = await conv.get_response() - if x.text.startswith("Alright! Now send me the video sticker."): - await conv.send_file(photo, force_document=True) - x = await conv.get_response() - if x.text in ["Invalid pack selected.", "Invalid set selected."]: - await conv.send_message(cmd) - await conv.get_response() - await conv.send_message(packnick) - await conv.get_response() - if is_anim: - await conv.send_file("AnimatedSticker.tgs") - remove("AnimatedSticker.tgs") - else: - if is_vid: - file = photo - else: - file.seek(0) - await conv.send_file(file, force_document=True) - await conv.get_response() - await conv.send_message(emoji) - await conv.get_response() - await conv.send_message("/publish") - if is_anim: - await conv.get_response() - await conv.send_message(f"<{packnick}>") - await conv.get_response() - await conv.send_message("/skip") - await conv.get_response() - await conv.send_message(packname) - await conv.get_response() - await xx.edit( - get_string("sts_7").format(packname), - parse_mode="md", - ) - return - if is_anim: - await conv.send_file("AnimatedSticker.tgs") - remove("AnimatedSticker.tgs") - elif "send me an emoji" not in x.message: - if is_vid: - file = photo - else: - file.seek(0) - await conv.send_file(file, force_document=True) - rsp = await conv.get_response() - if "Sorry, the file type is invalid." in rsp.text: - await xx.edit( - get_string("sts_8"), - ) - return - await conv.send_message(emoji) - await conv.get_response() - await conv.send_message("/done") - await conv.get_response() - await ultroid_bot.send_read_acknowledge(conv.chat_id) - else: - await xx.edit("`Brewing a new Pack...`") - async with ultroid_bot.conversation("Stickers") as conv: - await conv.send_message(cmd) - await conv.get_response() - await conv.send_message(packnick) - await conv.get_response() - if is_anim: - await conv.send_file("AnimatedSticker.tgs") - remove("AnimatedSticker.tgs") - else: - if is_vid: - file = photo - else: - file.seek(0) - await conv.send_file(file, force_document=True) - rsp = await conv.get_response() - if "Sorry, the file type is invalid." in rsp.text: - await xx.edit( - get_string("sts_8"), - ) - return - await conv.send_message(emoji) - await conv.get_response() - await conv.send_message("/publish") - if is_anim: - await conv.get_response() - await conv.send_message(f"<{packnick}>") - - await conv.get_response() - await conv.send_message("/skip") - await conv.get_response() - await conv.send_message(packname) - await conv.get_response() - await ultroid_bot.send_read_acknowledge(conv.chat_id) - await xx.edit( - get_string("sts_12").format(emoji, packname), - parse_mode="md", - ) - try: - os.remove(photo) - except BaseException: - pass - - -@ultroid_cmd( - pattern="round$", -) -async def ultdround(event): - ureply = await event.get_reply_message() - xx = await event.eor(get_string("com_1")) - if not (ureply and (ureply.media)): - await xx.edit(get_string("sts_10")) - return - ultt = await ureply.download_media() - file = await con.convert( - ultt, - convert_to="png", - allowed_formats=["jpg", "jpeg", "png"], - outname="round", - remove_old=True, - ) - img = Image.open(file).convert("RGB") - npImage = np.array(img) - h, w = img.size - alpha = Image.new("L", img.size, 0) - draw = ImageDraw.Draw(alpha) - draw.pieslice([0, 0, h, w], 0, 360, fill=255) - npAlpha = np.array(alpha) - npImage = np.dstack((npImage, npAlpha)) - Image.fromarray(npImage).save("ult.webp") - await event.client.send_file( - event.chat_id, - "ult.webp", - force_document=False, - reply_to=event.reply_to_msg_id, - ) - await xx.delete() - os.remove(file) - os.remove("ult.webp") - - -@ultroid_cmd( - pattern="destroy$", -) -async def ultdestroy(event): - ult = await event.get_reply_message() - if not (ult and ult.media and "animated" in mediainfo(ult.media)): - return await event.eor(get_string("sts_2")) - await event.client.download_media(ult, "ultroid.tgs") - xx = await event.eor(get_string("com_1")) - await bash("lottie_convert.py ultroid.tgs json.json") - with open("json.json") as json: - jsn = json.read() - jsn = ( - jsn.replace("[100]", "[200]") - .replace("[10]", "[40]") - .replace("[-1]", "[-10]") - .replace("[0]", "[15]") - .replace("[1]", "[20]") - .replace("[2]", "[17]") - .replace("[3]", "[40]") - .replace("[4]", "[37]") - .replace("[5]", "[60]") - .replace("[6]", "[70]") - .replace("[7]", "[40]") - .replace("[8]", "[37]") - .replace("[9]", "[110]") - ) - open("json.json", "w").write(jsn) - file = await con.animated_sticker("json.json", "ultroid.tgs") - if file: - await event.client.send_file( - event.chat_id, - file="ultroid.tgs", - force_document=False, - reply_to=event.reply_to_msg_id, - ) - await xx.delete() - os.remove("json.json") - - -@ultroid_cmd( - pattern="tiny$", -) -async def ultiny(event): - reply = await event.get_reply_message() - if not (reply and (reply.media)): - await event.eor(get_string("sts_10")) - return - xx = await event.eor(get_string("com_1")) - ik = await reply.download_media() - im1 = Image.open("resources/extras/ultroid_blank.png") - if ik.endswith(".tgs"): - await con.animated_sticker(ik, "json.json") - with open("json.json") as json: - jsn = json.read() - jsn = jsn.replace("512", "2000") - open("json.json", "w").write(jsn) - await con.animated_sticker("json.json", "ult.tgs") - file = "ult.tgs" - os.remove("json.json") - elif ik.endswith((".gif", ".webm", ".mp4")): - iik = cv2.VideoCapture(ik) - dani, busy = iik.read() - cv2.imwrite("i.png", busy) - fil = "i.png" - im = Image.open(fil) - z, d = im.size - if z == d: - xxx, yyy = 200, 200 - else: - t = z + d - a = z / t - b = d / t - aa = (a * 100) - 50 - bb = (b * 100) - 50 - xxx = 200 + 5 * aa - yyy = 200 + 5 * bb - k = im.resize((int(xxx), int(yyy))) - k.save("k.png", format="PNG", optimize=True) - im2 = Image.open("k.png") - back_im = im1.copy() - back_im.paste(im2, (150, 0)) - back_im.save("o.webp", "WEBP", quality=95) - file = "o.webp" - os.remove(fil) - os.remove("k.png") - else: - im = Image.open(ik) - z, d = im.size - if z == d: - xxx, yyy = 200, 200 - else: - t = z + d - a = z / t - b = d / t - aa = (a * 100) - 50 - bb = (b * 100) - 50 - xxx = 200 + 5 * aa - yyy = 200 + 5 * bb - k = im.resize((int(xxx), int(yyy))) - k.save("k.png", format="PNG", optimize=True) - im2 = Image.open("k.png") - back_im = im1.copy() - back_im.paste(im2, (150, 0)) - back_im.save("o.webp", "WEBP", quality=95) - file = "o.webp" - os.remove("k.png") - if os.path.exists(file): - await event.client.send_file( - event.chat_id, file, reply_to=event.reply_to_msg_id - ) - os.remove(file) - await xx.delete() - os.remove(ik) diff --git a/plugins/tag.py b/plugins/tag.py deleted file mode 100644 index 554a524893..0000000000 --- a/plugins/tag.py +++ /dev/null @@ -1,76 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}tagall` - Tag Top 100 Members of chat. - -• `{i}tagadmins` - Tag Admins of that chat. - -• `{i}tagowner` - Tag Owner of that chat - -• `{i}tagbots` - Tag Bots of that chat. - -• `{i}tagrec` - Tag recently Active Members. - -• `{i}tagon` - Tag online Members(work only if privacy off). - -• `{i}tagoff` - Tag Offline Members(work only if privacy off). -""" - -from telethon.tl.types import ChannelParticipantAdmin as admin -from telethon.tl.types import ChannelParticipantCreator as owner -from telethon.tl.types import UserStatusOffline as off -from telethon.tl.types import UserStatusOnline as onn -from telethon.tl.types import UserStatusRecently as rec - -from . import inline_mention, ultroid_cmd - - -@ultroid_cmd( - pattern="tag(on|off|all|bots|rec|admins|owner)( (.*)|$)", - groups_only=True, -) -async def _(e): - okk = e.text - lll = e.pattern_match.group(2) - o = 0 - nn = 0 - rece = 0 - xx = f"{lll}" if lll else "" - lili = await e.client.get_participants(e.chat_id, limit=99) - for bb in lili: - x = bb.status - y = bb.participant - if isinstance(x, onn): - o += 1 - if "on" in okk: - xx += f"\n{inline_mention(bb)}" - elif isinstance(x, off): - nn += 1 - if "off" in okk and not bb.bot and not bb.deleted: - xx += f"\n{inline_mention(bb)}" - elif isinstance(x, rec): - rece += 1 - if "rec" in okk and not bb.bot and not bb.deleted: - xx += f"\n{inline_mention(bb)}" - if isinstance(y, owner): - xx += f"\n꧁{inline_mention(bb)}꧂" - if isinstance(y, admin) and "admin" in okk and not bb.deleted: - xx += f"\n{inline_mention(bb)}" - if "all" in okk and not bb.bot and not bb.deleted: - xx += f"\n{inline_mention(bb)}" - if "bot" in okk and bb.bot: - xx += f"\n{inline_mention(bb)}" - await e.eor(xx) diff --git a/plugins/tools.py b/plugins/tools.py deleted file mode 100644 index 4171a134ed..0000000000 --- a/plugins/tools.py +++ /dev/null @@ -1,461 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}circle` - Reply to a audio song or gif to get video note. - -• `{i}ls` - Get all the Files inside a Directory. - -• `{i}bots` - Shows the number of bots in the current chat with their perma-link. - -• `{i}hl ` - Embeds the link with a whitespace as message. - -• `{i}id` - Reply a Sticker to Get Its Id - Reply a User to Get His Id - Without Replying You Will Get the Chat's Id - -• `{i}sg ` - Get His Name History of the replied user. - -• `{i}tr <(reply to) a message>` - Get translated message. - -• `{i}webshot ` - Get a screenshot of the webpage. - -• `{i}shorturl ` - shorten any url... -""" -import glob -import io -import os -import secrets -from asyncio.exceptions import TimeoutError as AsyncTimeout - -try: - import cv2 -except ImportError: - cv2 = None - -try: - from playwright.async_api import async_playwright -except ImportError: - async_playwright = None -try: - from htmlwebshot import WebShot -except ImportError: - WebShot = None - -from telethon.errors.rpcerrorlist import MessageTooLongError, YouBlockedUserError -from telethon.tl.types import ( - ChannelParticipantAdmin, - ChannelParticipantsBots, - DocumentAttributeVideo, -) - -from pyUltroid.fns.tools import metadata, translate - -from . import ( - HNDLR, - LOGS, - ULTConfig, - async_searcher, - bash, - check_filename, - con, - download_file, - eor, - get_string, -) -from . import humanbytes as hb -from . import inline_mention, is_url_ok, json_parser, mediainfo, ultroid_cmd - - -@ultroid_cmd(pattern="tr( (.*)|$)", manager=True) -async def _(event): - input = event.pattern_match.group(1).strip().split(maxsplit=1) - txt = input[1] if len(input) > 1 else None - if input: - input = input[0] - if txt: - text = txt - elif event.is_reply: - previous_message = await event.get_reply_message() - text = previous_message.message - else: - return await eor( - event, f"`{HNDLR}tr LanguageCode` as reply to a message", time=5 - ) - lan = input or "en" - try: - tt = translate(text, lang_tgt=lan) - output_str = f"**TRANSLATED** to {lan}\n{tt}" - await event.eor(output_str) - except Exception as exc: - LOGS.exception(exc) - await event.eor(str(exc), time=5) - - -@ultroid_cmd( - pattern="id( (.*)|$)", - manager=True, -) -async def _(event): - ult = event - match = event.pattern_match.group(1).strip() - if match: - try: - ids = await event.client.parse_id(match) - except Exception as er: - return await event.eor(str(er)) - return await event.eor( - f"**Chat ID:** `{event.chat_id}`\n**User ID:** `{ids}`" - ) - data = f"**Current Chat ID:** `{event.chat_id}`" - if event.reply_to_msg_id: - event = await event.get_reply_message() - data += f"\n**From User ID:** `{event.sender_id}`" - if event.media: - bot_api_file_id = event.file.id - data += f"\n**Bot API File ID:** `{bot_api_file_id}`" - data += f"\n**Msg ID:** `{event.id}`" - await ult.eor(data) - - -@ultroid_cmd(pattern="bots( (.*)|$)", groups_only=True, manager=True) -async def _(ult): - mentions = "• **Bots in this Chat**: \n" - if input_str := ult.pattern_match.group(1).strip(): - mentions = f"• **Bots in **{input_str}: \n" - try: - chat = await ult.client.parse_id(input_str) - except Exception as e: - return await ult.eor(str(e)) - else: - chat = ult.chat_id - try: - async for x in ult.client.iter_participants( - chat, - filter=ChannelParticipantsBots, - ): - if isinstance(x.participant, ChannelParticipantAdmin): - mentions += f"\n⚜️ {inline_mention(x)} `{x.id}`" - else: - mentions += f"\n• {inline_mention(x)} `{x.id}`" - except Exception as e: - mentions += f" {str(e)}" + "\n" - await ult.eor(mentions) - - -@ultroid_cmd( - pattern="hl( (.*)|$)", -) -async def _(ult): - input_ = ult.pattern_match.group(1).strip() - if not input_: - return await ult.eor("`Input some link`", time=5) - text = None - if len(input_.split()) > 1: - spli_ = input_.split() - input_ = spli_[0] - text = spli_[1] - if not text: - text = "ㅤㅤㅤㅤㅤㅤㅤ" - await ult.eor(f"[{text}]({input_})", link_preview=False) - - -@ultroid_cmd( - pattern="circle$", -) -async def _(e): - reply = await e.get_reply_message() - if not (reply and reply.media): - return await e.eor("`Reply to a gif or audio file only.`") - if "audio" in mediainfo(reply.media): - msg = await e.eor("`Downloading...`") - try: - bbbb = await reply.download_media(thumb=-1) - except TypeError: - bbbb = ULTConfig.thumb - im = cv2.imread(bbbb) - dsize = (512, 512) - output = cv2.resize(im, dsize, interpolation=cv2.INTER_AREA) - cv2.imwrite("img.jpg", output) - thumb = "img.jpg" - audio, _ = await e.client.fast_downloader(reply.document) - await msg.edit("`Creating video note...`") - await bash( - f'ffmpeg -i "{thumb}" -i "{audio.name}" -preset ultrafast -c:a libmp3lame -ab 64 circle.mp4 -y' - ) - await msg.edit("`Uploading...`") - data = await metadata("circle.mp4") - file, _ = await e.client.fast_uploader("circle.mp4", to_delete=True) - await e.client.send_file( - e.chat_id, - file, - thumb=thumb, - reply_to=reply, - attributes=[ - DocumentAttributeVideo( - duration=min(data["duration"], 60), - w=512, - h=512, - round_message=True, - ) - ], - ) - - await msg.delete() - [os.remove(k) for k in [audio.name, thumb]] - elif mediainfo(reply.media) == "gif" or mediainfo(reply.media).startswith("video"): - msg = await e.eor("**Creating video note**") - file = await reply.download_media("resources/downloads/") - if file.endswith(".webm"): - nfile = await con.ffmpeg_convert(file, "file.mp4") - os.remove(file) - file = nfile - if file: - await e.client.send_file( - e.chat_id, - file, - video_note=True, - thumb=ULTConfig.thumb, - reply_to=reply, - ) - os.remove(file) - await msg.delete() - - else: - await e.eor("`Reply to a gif or audio file only.`") - - -FilesEMOJI = { - "py": "🐍", - "json": "🔮", - ("sh", "bat"): "⌨️", - (".mkv", ".mp4", ".avi", ".gif", "webm"): "🎥", - (".mp3", ".ogg", ".m4a", ".opus"): "🔊", - (".jpg", ".jpeg", ".png", ".webp", ".ico"): "🖼", - (".txt", ".text", ".log"): "📄", - (".apk", ".xapk"): "📲", - (".pdf", ".epub"): "📗", - (".zip", ".rar"): "🗜", - (".exe", ".iso"): "⚙", -} - - -@ultroid_cmd( - pattern="ls( (.*)|$)", -) -async def _(e): - files = e.pattern_match.group(1).strip() - if not files: - files = "*" - elif files.endswith("/"): - files += "*" - elif "*" not in files: - files += "/*" - files = glob.glob(files) - if not files: - return await e.eor("`Directory Empty or Incorrect.`", time=5) - folders = [] - allfiles = [] - for file in sorted(files): - if os.path.isdir(file): - folders.append(f"📂 {file}") - else: - for ext in FilesEMOJI.keys(): - if file.endswith(ext): - allfiles.append(f"{FilesEMOJI[ext]} {file}") - break - else: - if "." in str(file)[1:]: - allfiles.append(f"🏷 {file}") - else: - allfiles.append(f"📒 {file}") - omk = [*sorted(folders), *sorted(allfiles)] - text = "" - fls, fos = 0, 0 - flc, foc = 0, 0 - for i in omk: - try: - emoji = i.split()[0] - name = i.split(maxsplit=1)[1] - nam = name.split("/")[-1] - if os.path.isdir(name): - size = 0 - for path, dirs, files in os.walk(name): - for f in files: - fp = os.path.join(path, f) - size += os.path.getsize(fp) - if hb(size): - text += f"{emoji} `{nam}` `{hb(size)}" + "`\n" - fos += size - else: - text += f"{emoji} `{nam}`" + "\n" - foc += 1 - else: - if hb(int(os.path.getsize(name))): - text += ( - emoji - + f" `{nam}`" - + " `" - + hb(int(os.path.getsize(name))) - + "`\n" - ) - fls += int(os.path.getsize(name)) - else: - text += f"{emoji} `{nam}`" + "\n" - flc += 1 - except BaseException: - pass - tfos, tfls, ttol = hb(fos), hb(fls), hb(fos + fls) - if not hb(fos): - tfos = "0 B" - if not hb(fls): - tfls = "0 B" - if not hb(fos + fls): - ttol = "0 B" - text += f"\n\n`Folders` : `{foc}` : `{tfos}`\n`Files` : `{flc}` : `{tfls}`\n`Total` : `{flc+foc}` : `{ttol}`" - try: - if (flc + foc) > 100: - text = text.replace("`", "") - await e.eor(text) - except MessageTooLongError: - with io.BytesIO(str.encode(text)) as out_file: - out_file.name = "output.txt" - await e.reply(f"`{e.text}`", file=out_file, thumb=ULTConfig.thumb) - await e.delete() - - -@ultroid_cmd( - pattern="sg( (.*)|$)", -) -async def lastname(steal): - mat = steal.pattern_match.group(1).strip() - message = await steal.get_reply_message() - if mat: - try: - user_id = await steal.client.parse_id(mat) - except ValueError: - user_id = mat - elif message: - user_id = message.sender_id - else: - return await steal.eor("`Use this command with reply or give Username/id...`") - chat = "@SangMataInfo_bot" - id = f"/search_id {user_id}" - lol = await steal.eor(get_string("com_1")) - try: - async with steal.client.conversation(chat) as conv: - try: - msg = await conv.send_message(id) - response = await conv.get_response() - respond = await conv.get_response() - responds = await conv.get_response() - except YouBlockedUserError: - return await lol.edit("Please unblock @sangmatainfo_bot and try again") - if ( - (response and response.text == "No records found") - or (respond and respond.text == "No records found") - or (responds and responds.text == "No records found") - ): - await lol.edit("No records found for this user") - await steal.client.delete_messages(conv.chat_id, [msg.id, response.id]) - elif response.text.startswith("🔗"): - await lol.edit(respond.message) - await lol.reply(responds.message) - elif respond.text.startswith("🔗"): - await lol.edit(response.message) - await lol.reply(responds.message) - else: - await lol.edit(respond.message) - await lol.reply(response.message) - await steal.client.delete_messages( - conv.chat_id, - [msg.id, responds.id, respond.id, response.id], - ) - except AsyncTimeout: - await lol.edit("Error: @SangMataInfo_bot is not responding!.") - - -@ultroid_cmd(pattern="webshot( (.*)|$)") -async def webss(event): - xx = await event.eor(get_string("com_1")) - xurl = event.pattern_match.group(1).strip() - if not xurl: - return await xx.eor(get_string("wbs_1"), time=5) - if not (await is_url_ok(xurl)): - return await xx.eor(get_string("wbs_2"), time=5) - path, pic = check_filename("shot.png"), None - if async_playwright: - try: - async with async_playwright() as playwright: - chrome = await playwright.chromium.launch() - page = await chrome.new_page() - await page.goto(xurl) - await page.screenshot(path=path, full_page=True) - pic = path - except Exception as er: - LOGS.exception(er) - await xx.respond(f"Error with playwright:\n`{er}`") - if WebShot and not pic: - try: - shot = WebShot( - quality=88, flags=["--enable-javascript", "--no-stop-slow-scripts"] - ) - pic = await shot.create_pic_async(url=xurl) - except Exception as er: - LOGS.exception(er) - if not pic: - pic, msg = await download_file( - f"https://shot.screenshotapi.net/screenshot?&url={xurl}&output=image&file_type=png&wait_for_event=load", - path, - validate=True, - ) - if msg: - await xx.edit(json_parser(msg, indent=1)) - return - if pic: - await xx.reply( - get_string("wbs_3").format(xurl), - file=pic, - link_preview=False, - force_document=True, - ) - os.remove(pic) - await xx.delete() - - -@ultroid_cmd(pattern="shorturl") -async def magic(event): - try: - match = event.text.split(maxsplit=1)[1].strip() - except IndexError: - return await event.eor("`Provide url to turn into tiny...`") - data = { - "url": match.split()[0], - "id": match[1] if len(match) > 1 else secrets.token_urlsafe(6), - } - data = await async_searcher( - "https://tiny.ultroid.tech/api/new", - data=data, - post=True, - re_json=True, - ) - response = data.get("response", {}) - if not response.get("status"): - return await event.eor(f'**ERROR :** `{response["message"]}`') - await event.eor( - f"• **Ultroid Tiny**\n• Given Url : {url}\n• Shorten Url : {data['response']['tinyUrl']}" - ) diff --git a/plugins/unsplash.py b/plugins/unsplash.py deleted file mode 100644 index c412af2381..0000000000 --- a/plugins/unsplash.py +++ /dev/null @@ -1,36 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• {i}unsplash ; - Unsplash Image Search. -""" - -from pyUltroid.fns.misc import unsplashsearch - -from . import asyncio, download_file, get_string, os, ultroid_cmd - - -@ultroid_cmd(pattern="unsplash( (.*)|$)") -async def searchunsl(ult): - match = ult.pattern_match.group(1).strip() - if not match: - return await ult.eor("Give me Something to Search") - num = 5 - if ";" in match: - num = int(match.split(";")[1]) - match = match.split(";")[0] - tep = await ult.eor(get_string("com_1")) - res = await unsplashsearch(match, limit=num) - if not res: - return await ult.eor(get_string("unspl_1"), time=5) - CL = [download_file(rp, f"{match}-{e}.png") for e, rp in enumerate(res)] - imgs = [z[0] for z in (await asyncio.gather(*CL)) if z] - await ult.respond(f"Uploaded {len(imgs)} Images!", file=imgs) - await tep.delete() - [os.remove(img) for img in imgs] diff --git a/plugins/usage.py b/plugins/usage.py deleted file mode 100644 index 88d4e882b3..0000000000 --- a/plugins/usage.py +++ /dev/null @@ -1,188 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - -• `{i}usage` - Get overall usage. - -• `{i}usage heroku` - Get heroku stats. - -• `{i}usage db` - Get database storage usage. -""" - -import math -import shutil -from random import choice - -from pyUltroid.fns import some_random_headers - -from . import ( - HOSTED_ON, - LOGS, - Var, - async_searcher, - get_string, - humanbytes, - udB, - ultroid_cmd, -) - -HEROKU_API = None -HEROKU_APP_NAME = None - -if HOSTED_ON == "heroku": - heroku_api, app_name = Var.HEROKU_API, Var.HEROKU_APP_NAME - try: - if heroku_api and app_name: - import heroku3 - - Heroku = heroku3.from_key(heroku_api) - app = Heroku.app(app_name) - HEROKU_API = heroku_api - HEROKU_APP_NAME = app_name - except BaseException as er: - LOGS.exception(er) - - -@ultroid_cmd(pattern="usage") -async def usage_finder(event): - x = await event.eor(get_string("com_1")) - try: - opt = event.text.split(" ", maxsplit=1)[1] - except IndexError: - return await x.edit(simple_usage()) - - if opt == "db": - await x.edit(db_usage()) - elif opt == "heroku": - is_hk, hk = await heroku_usage() - await x.edit(hk) - else: - await x.edit(await get_full_usage()) - - -def simple_usage(): - try: - import psutil - except ImportError: - return "Install 'psutil' to use this..." - total, used, free = shutil.disk_usage(".") - cpuUsage = psutil.cpu_percent() - memory = psutil.virtual_memory().percent - disk = psutil.disk_usage("/").percent - upload = humanbytes(psutil.net_io_counters().bytes_sent) - down = humanbytes(psutil.net_io_counters().bytes_recv) - TOTAL = humanbytes(total) - USED = humanbytes(used) - FREE = humanbytes(free) - return get_string("usage_simple").format( - TOTAL, - USED, - FREE, - upload, - down, - cpuUsage, - memory, - disk, - ) - - -async def heroku_usage(): - try: - import psutil - except ImportError: - return ( - False, - "'psutil' not installed!\nPlease Install it to use this.\n`pip3 install psutil`", - ) - if not (HEROKU_API and HEROKU_APP_NAME): - if HOSTED_ON == "heroku": - return False, "Please fill `HEROKU_API` and `HEROKU_APP_NAME`" - return ( - False, - f"`This command is only for Heroku Users, You are using {HOSTED_ON}`", - ) - user_id = Heroku.account().id - headers = { - "User-Agent": choice(some_random_headers), - "Authorization": f"Bearer {heroku_api}", - "Accept": "application/vnd.heroku+json; version=3.account-quotas", - } - her_url = f"https://api.heroku.com/accounts/{user_id}/actions/get-quota" - try: - result = await async_searcher(her_url, headers=headers, re_json=True) - except Exception as er: - return False, str(er) - quota = result["account_quota"] - quota_used = result["quota_used"] - remaining_quota = quota - quota_used - percentage = math.floor(remaining_quota / quota * 100) - minutes_remaining = remaining_quota / 60 - hours = math.floor(minutes_remaining / 60) - minutes = math.floor(minutes_remaining % 60) - App = result["apps"] - try: - App[0]["quota_used"] - except IndexError: - AppQuotaUsed = 0 - AppPercentage = 0 - else: - AppQuotaUsed = App[0]["quota_used"] / 60 - AppPercentage = math.floor(App[0]["quota_used"] * 100 / quota) - AppHours = math.floor(AppQuotaUsed / 60) - AppMinutes = math.floor(AppQuotaUsed % 60) - total, used, free = shutil.disk_usage(".") - _ = shutil.disk_usage("/") - disk = _.used / _.total * 100 - cpuUsage = psutil.cpu_percent() - memory = psutil.virtual_memory().percent - upload = humanbytes(psutil.net_io_counters().bytes_sent) - down = humanbytes(psutil.net_io_counters().bytes_recv) - TOTAL = humanbytes(total) - USED = humanbytes(used) - FREE = humanbytes(free) - return True, get_string("usage").format( - Var.HEROKU_APP_NAME, - AppHours, - AppMinutes, - AppPercentage, - hours, - minutes, - percentage, - TOTAL, - USED, - FREE, - upload, - down, - cpuUsage, - memory, - disk, - ) - - -def db_usage(): - if udB.name == "Mongo": - total = 512 - elif udB.name == "Redis": - total = 30 - elif udB.name == "SQL": - total = 20 - total = total * (2**20) - used = udB.usage - a = f"{humanbytes(used)}/{humanbytes(total)}" - b = f"{str(round((used / total) * 100, 2))}%" - return f"**{udB.name}**\n\n**Storage Used**: `{a}`\n**Usage percentage**: **{b}**" - - -async def get_full_usage(): - is_hk, hk = await heroku_usage() - her = hk if is_hk else "" - rd = db_usage() - return her + "\n\n" + rd diff --git a/plugins/utilities.py b/plugins/utilities.py deleted file mode 100644 index ab4961fee0..0000000000 --- a/plugins/utilities.py +++ /dev/null @@ -1,742 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}kickme` : Leaves the group. - -• `{i}date` : Show Calender. - -• `{i}listreserved` - List all usernames (channels/groups) you own. - -• `{i}stats` : See your profile stats. - -• `{i}paste` - `Include long text / Reply to text file.` - -• `{i}info ` - Reply to someone's msg. - -• `{i}invite ` - Add user to the chat. - -• `{i}rmbg ` - Remove background from that picture. - -• `{i}telegraph ` - Upload media/text to telegraph. - -• `{i}json ` - Get the json encoding of the message. - -• `{i}suggest or ` - Create a Yes/No poll for the replied suggestion. - -• `{i}ipinfo ` : Get info about that IP address. - -• `{i}cpy ` - Copy the replied message, with formatting. Expires in 24hrs. -• `{i}pst` - Paste the copied message, with formatting. - -• `{i}thumb ` : Download the thumbnail of the replied file. - -• `{i}getmsg ` - Get messages from chats with forward/copy restrictions. -""" - -import calendar -import html -import io -import os -import pathlib -import time -from datetime import datetime as dt - -try: - from PIL import Image -except ImportError: - Image = None - -from pyUltroid._misc._assistant import asst_cmd -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 telethon.errors.rpcerrorlist import ChatForwardsRestrictedError, UserBotError -from telethon.events import NewMessage -from telethon.tl.custom import Dialog -from telethon.tl.functions.channels import ( - GetAdminedPublicChannelsRequest, - InviteToChannelRequest, - LeaveChannelRequest, -) -from telethon.tl.functions.contacts import GetBlockedRequest -from telethon.tl.functions.messages import AddChatUserRequest, GetAllStickersRequest -from telethon.tl.functions.users import GetFullUserRequest -from telethon.tl.types import ( - Channel, - Chat, - InputMediaPoll, - Poll, - PollAnswer, - TLObject, - User, -) -from telethon.utils import get_peer_id - -from pyUltroid.fns.info import get_chat_info - -from . import ( - HNDLR, - LOGS, - Image, - ReTrieveFile, - Telegraph, - asst, - async_searcher, - bash, - check_filename, - eod, - eor, - get_paste, - get_string, - inline_mention, - json_parser, - mediainfo, - udB, - ultroid_cmd, -) - -# =================================================================# - -TMP_DOWNLOAD_DIRECTORY = "resources/downloads/" - -_copied_msg = {} - - -@ultroid_cmd(pattern="kickme$", fullsudo=True) -async def leave(ult): - await ult.eor(f"`{ult.client.me.first_name} has left this group, bye!!.`") - await ult.client(LeaveChannelRequest(ult.chat_id)) - - -@ultroid_cmd( - pattern="date$", -) -async def date(event): - m = dt.now().month - y = dt.now().year - d = dt.now().strftime("Date - %B %d, %Y\nTime- %H:%M:%S") - k = calendar.month(y, m) - await event.eor(f"`{k}\n\n{d}`") - - -@ultroid_cmd( - pattern="listreserved$", -) -async def _(event): - result = await event.client(GetAdminedPublicChannelsRequest()) - if not result.chats: - return await event.eor("`No username Reserved`") - output_str = "".join( - f"- {channel_obj.title} @{channel_obj.username} \n" - for channel_obj in result.chats - ) - await event.eor(output_str) - - -@ultroid_cmd( - pattern="stats$", -) -async def stats( - event: NewMessage.Event, -): - ok = await event.eor("`Collecting stats...`") - start_time = time.time() - private_chats = 0 - bots = 0 - groups = 0 - broadcast_channels = 0 - admin_in_groups = 0 - creator_in_groups = 0 - admin_in_broadcast_channels = 0 - creator_in_channels = 0 - unread_mentions = 0 - unread = 0 - dialog: Dialog - async for dialog in event.client.iter_dialogs(): - entity = dialog.entity - if isinstance(entity, Channel) and entity.broadcast: - broadcast_channels += 1 - if entity.creator or entity.admin_rights: - admin_in_broadcast_channels += 1 - if entity.creator: - creator_in_channels += 1 - - elif (isinstance(entity, Channel) and entity.megagroup) or isinstance( - entity, Chat - ): - groups += 1 - if entity.creator or entity.admin_rights: - admin_in_groups += 1 - if entity.creator: - creator_in_groups += 1 - - elif isinstance(entity, User): - private_chats += 1 - if entity.bot: - bots += 1 - - unread_mentions += dialog.unread_mentions_count - unread += dialog.unread_count - stop_time = time.time() - start_time - try: - ct = (await event.client(GetBlockedRequest(1, 0))).count - except AttributeError: - ct = 0 - try: - sp = await event.client(GetAllStickersRequest(0)) - sp_count = len(sp.sets) - except BaseException: - sp_count = 0 - full_name = inline_mention(event.client.me) - response = f"🔸 **Stats for {full_name}** \n\n" - response += f"**Private Chats:** {private_chats} \n" - response += f"** •• **`Users: {private_chats - bots}` \n" - response += f"** •• **`Bots: {bots}` \n" - response += f"**Groups:** {groups} \n" - response += f"**Channels:** {broadcast_channels} \n" - response += f"**Admin in Groups:** {admin_in_groups} \n" - response += f"** •• **`Creator: {creator_in_groups}` \n" - response += f"** •• **`Admin Rights: {admin_in_groups - creator_in_groups}` \n" - response += f"**Admin in Channels:** {admin_in_broadcast_channels} \n" - response += f"** •• **`Creator: {creator_in_channels}` \n" - response += f"** •• **`Admin Rights: {admin_in_broadcast_channels - creator_in_channels}` \n" - response += f"**Unread:** {unread} \n" - response += f"**Unread Mentions:** {unread_mentions} \n" - response += f"**Blocked Users:** {ct}\n" - response += f"**Total Stickers Pack Installed :** `{sp_count}`\n\n" - response += f"**__It Took:__** {stop_time:.02f}s \n" - await ok.edit(response) - - -@ultroid_cmd(pattern="paste( (.*)|$)", manager=True, allow_all=True) -async def _(event): - try: - input_str = event.text.split(maxsplit=1)[1] - except IndexError: - input_str = None - xx = await event.eor("` 《 Pasting... 》 `") - downloaded_file_name = None - if input_str: - message = input_str - elif event.reply_to_msg_id: - previous_message = await event.get_reply_message() - if previous_message.media: - downloaded_file_name = await event.client.download_media( - previous_message, - "./resources/downloads", - ) - with open(downloaded_file_name, "r") as fd: - message = fd.read() - os.remove(downloaded_file_name) - else: - message = previous_message.message - else: - message = None - if not message: - 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" - reply_text = ( - f"• **Pasted to SpaceBin :** [Space]({link})\n• **Raw Url :** : [Raw]({raw})" - ) - try: - if event.client._bot: - return await xx.eor(reply_text) - ok = await event.client.inline_query(asst.me.username, f"pasta-{key}") - await ok[0].click(event.chat_id, reply_to=event.reply_to_msg_id, hide_via=True) - await xx.delete() - except BaseException as e: - LOGS.exception(e) - await xx.edit(reply_text) - - -@ultroid_cmd( - pattern="info( (.*)|$)", - manager=True, -) -async def _(event): - if match := event.pattern_match.group(1).strip(): - try: - user = await event.client.parse_id(match) - except Exception as er: - return await event.eor(str(er)) - elif event.is_reply: - rpl = await event.get_reply_message() - user = rpl.sender_id - else: - user = event.chat_id - xx = await event.eor(get_string("com_1")) - try: - _ = await event.client.get_entity(user) - except Exception as er: - return await xx.edit(f"**ERROR :** {er}") - if not isinstance(_, User): - try: - peer = get_peer_id(_) - photo, capt = await get_chat_info(_, event) - if is_gbanned(peer): - capt += "\n• Is Gbanned: True" - if not photo: - return await xx.eor(capt, parse_mode="html") - await event.client.send_message( - event.chat_id, capt[:1024], file=photo, parse_mode="html" - ) - await xx.delete() - except Exception as er: - await event.eor("**ERROR ON CHATINFO**\n" + str(er)) - return - try: - full_user = (await event.client(GetFullUserRequest(user))).full_user - except Exception as er: - return await xx.edit(f"ERROR : {er}") - user = _ - user_photos = ( - await event.client.get_profile_photos(user.id, limit=0) - ).total or "NaN" - user_id = user.id - first_name = html.escape(user.first_name) - if first_name is not None: - first_name = first_name.replace("\u2060", "") - last_name = user.last_name - last_name = ( - last_name.replace("\u2060", "") if last_name else ("Last Name not found") - ) - user_bio = full_user.about - if user_bio is not None: - user_bio = html.escape(full_user.about) - common_chats = full_user.common_chats_count - if user.photo: - dc_id = user.photo.dc_id - else: - dc_id = "Need a Profile Picture to check this" - caption = """Exᴛʀᴀᴄᴛᴇᴅ Dᴀᴛᴀ Fʀᴏᴍ Tᴇʟᴇɢʀᴀᴍ's Dᴀᴛᴀʙᴀsᴇ -••Tᴇʟᴇɢʀᴀᴍ ID: {} -••Pᴇʀᴍᴀɴᴇɴᴛ Lɪɴᴋ: Click Here -••Fɪʀsᴛ Nᴀᴍᴇ: {} -••Sᴇᴄᴏɴᴅ Nᴀᴍᴇ: {} -••Bɪᴏ: {} -••Dᴄ ID: {} -••Nᴏ. Oғ PғPs : {} -••Is Rᴇsᴛʀɪᴄᴛᴇᴅ: {} -••Vᴇʀɪғɪᴇᴅ: {} -••Is Pʀᴇᴍɪᴜᴍ: {} -••Is A Bᴏᴛ: {} -••Gʀᴏᴜᴘs Iɴ Cᴏᴍᴍᴏɴ: {} -""".format( - user_id, - user_id, - first_name, - last_name, - user_bio, - dc_id, - user_photos, - user.restricted, - user.verified, - user.premium, - user.bot, - common_chats, - ) - if chk := is_gbanned(user_id): - caption += f"""••Gʟᴏʙᴀʟʟʏ Bᴀɴɴᴇᴅ: True -••Rᴇᴀsᴏɴ: {chk}""" - await event.client.send_message( - event.chat_id, - caption, - reply_to=event.reply_to_msg_id, - parse_mode="HTML", - file=full_user.profile_photo, - force_document=False, - silent=True, - ) - await xx.delete() - - -@ultroid_cmd( - pattern="invite( (.*)|$)", - groups_only=True, -) -async def _(ult): - xx = await ult.eor(get_string("com_1")) - to_add_users = ult.pattern_match.group(1).strip() - if not ult.is_channel and ult.is_group: - for user_id in to_add_users.split(" "): - try: - await ult.client( - AddChatUserRequest( - chat_id=ult.chat_id, - user_id=await ult.client.parse_id(user_id), - fwd_limit=1000000, - ), - ) - await xx.edit(f"Successfully invited `{user_id}` to `{ult.chat_id}`") - except Exception as e: - await xx.edit(str(e)) - else: - for user_id in to_add_users.split(" "): - try: - await ult.client( - InviteToChannelRequest( - channel=ult.chat_id, - users=[await ult.client.parse_id(user_id)], - ), - ) - await xx.edit(f"Successfully invited `{user_id}` to `{ult.chat_id}`") - except UserBotError: - await xx.edit( - f"Bots can only be added as Admins in Channel.\nBetter Use `{HNDLR}promote {user_id}`" - ) - except Exception as e: - await xx.edit(str(e)) - - -@ultroid_cmd( - pattern="rmbg($| (.*))", -) -async def abs_rmbg(event): - RMBG_API = udB.get_key("RMBG_API") - if not RMBG_API: - return await event.eor( - "Get your API key from [here](https://www.remove.bg/) for this plugin to work.", - ) - match = event.pattern_match.group(1).strip() - reply = await event.get_reply_message() - if match and os.path.exists(match): - dl = match - elif reply and reply.media: - if reply.document and reply.document.thumbs: - dl = await reply.download_media(thumb=-1) - else: - dl = await reply.download_media() - else: - return await eod( - event, f"Use `{HNDLR}rmbg` as reply to a pic to remove its background." - ) - if not (dl and dl.endswith(("webp", "jpg", "png", "jpeg"))): - os.remove(dl) - return await event.eor(get_string("com_4")) - if dl.endswith("webp"): - file = f"{dl}.png" - Image.open(dl).save(file) - os.remove(dl) - dl = file - xx = await event.eor("`Sending to remove.bg`") - dn, out = await ReTrieveFile(dl) - os.remove(dl) - if not dn: - dr = out["errors"][0] - de = dr.get("detail", "") - return await xx.edit( - f"**ERROR ~** `{dr['title']}`,\n`{de}`", - ) - zz = Image.open(out) - if zz.mode != "RGB": - zz.convert("RGB") - wbn = check_filename("ult-rmbg.webp") - zz.save(wbn, "webp") - await event.client.send_file( - event.chat_id, - out, - force_document=True, - reply_to=reply, - ) - await event.client.send_file(event.chat_id, wbn, reply_to=reply) - os.remove(out) - os.remove(wbn) - await xx.delete() - - -@ultroid_cmd( - pattern="telegraph( (.*)|$)", -) -async def telegraphcmd(event): - xx = await event.eor(get_string("com_1")) - match = event.pattern_match.group(1).strip() or "Ultroid" - reply = await event.get_reply_message() - if not reply: - return await xx.eor("`Reply to Message.`") - if not reply.media and reply.message: - content = reply.message - else: - getit = await reply.download_media() - dar = mediainfo(reply.media) - if dar == "sticker": - file = f"{getit}.png" - Image.open(getit).save(file) - os.remove(getit) - getit = file - elif dar.endswith("animated"): - file = f"{getit}.gif" - await bash(f"lottie_convert.py '{getit}' {file}") - os.remove(getit) - getit = file - if "document" not in dar: - try: - nn = f"https://graph.org{uf(getit)[0]}" - amsg = f"Uploaded to [Telegraph]({nn}) !" - except Exception as e: - amsg = f"Error : {e}" - os.remove(getit) - return await xx.eor(amsg) - content = pathlib.Path(getit).read_text() - os.remove(getit) - makeit = Telegraph.create_page(title=match, content=[content]) - await xx.eor( - f"Pasted to Telegraph : [Telegraph]({makeit['url']})", link_preview=False - ) - - -@ultroid_cmd(pattern="json( (.*)|$)") -async def _(event): - reply_to_id = None - match = event.pattern_match.group(1).strip() - if event.reply_to_msg_id: - msg = await event.get_reply_message() - reply_to_id = event.reply_to_msg_id - else: - msg = event - reply_to_id = event.message.id - if match and hasattr(msg, match.split()[0]): - msg = getattr(msg, match.split()[0]) - try: - if hasattr(msg, "to_json"): - msg = msg.to_json(ensure_ascii=False, indent=1) - elif hasattr(msg, "to_dict"): - msg = json_parser(msg.to_dict(), indent=1) - else: - msg = TLObject.stringify(msg) - except Exception: - pass - msg = str(msg) - else: - msg = json_parser(msg.to_json(), indent=1) - if "-t" in match: - try: - data = json_parser(msg) - msg = json_parser( - {key: data[key] for key in data.keys() if data[key]}, indent=1 - ) - except Exception: - pass - if len(msg) > 4096: - with io.BytesIO(str.encode(msg)) as out_file: - out_file.name = "json-ult.txt" - await event.client.send_file( - event.chat_id, - out_file, - force_document=True, - allow_cache=False, - reply_to=reply_to_id, - ) - await event.delete() - else: - await event.eor(f"```{msg or None}```") - - -@ultroid_cmd(pattern="suggest( (.*)|$)", manager=True) -async def sugg(event): - sll = event.text.split(maxsplit=1) - try: - text = sll[1] - except IndexError: - text = None - if not (event.is_reply or text): - return await eod( - event, - "`Please reply to a message to make a suggestion poll!`", - ) - if event.is_reply and not text: - reply = await event.get_reply_message() - if reply.text and len(reply.text) < 35: - text = reply.text - else: - text = "Do you Agree to Replied Suggestion ?" - reply_to = event.reply_to_msg_id if event.is_reply else event.id - try: - await event.client.send_file( - event.chat_id, - file=InputMediaPoll( - poll=Poll( - id=12345, - question=text, - answers=[PollAnswer("Yes", b"1"), PollAnswer("No", b"2")], - ), - ), - reply_to=reply_to, - ) - except Exception as e: - return await eod(event, f"`Oops, you can't send polls here!\n\n{e}`") - await event.delete() - - -@ultroid_cmd(pattern="ipinfo( (.*)|$)") -async def ipinfo(event): - ip = event.text.split() - ipaddr = "" - try: - ipaddr = f"/{ip[1]}" - except IndexError: - ipaddr = "" - det = await async_searcher(f"https://ipinfo.io{ipaddr}/geo", re_json=True) - try: - ip = det["ip"] - city = det["city"] - region = det["region"] - country = det["country"] - cord = det["loc"] - try: - zipc = det["postal"] - except KeyError: - zipc = "None" - tz = det["timezone"] - await eor( - event, - """ -**IP Details Fetched.** - -**IP:** `{}` -**City:** `{}` -**Region:** `{}` -**Country:** `{}` -**Co-ordinates:** `{}` -**Postal Code:** `{}` -**Time Zone:** `{}` -""".format( - ip, - city, - region, - country, - cord, - zipc, - tz, - ), - ) - except BaseException: - err = det["error"]["title"] - msg = det["error"]["message"] - await event.eor(f"ERROR:\n{err}\n{msg}", time=5) - - -@ultroid_cmd( - pattern="cpy$", -) -async def copp(event): - msg = await event.get_reply_message() - if not msg: - return await event.eor(f"Use `{HNDLR}cpy` as reply to a message!", time=5) - _copied_msg["CLIPBOARD"] = msg - await event.eor(f"Copied. Use `{HNDLR}pst` to paste!", time=10) - - -@asst_cmd(pattern="pst$") -async def pepsodent(event): - await toothpaste(event) - - -@ultroid_cmd( - pattern="pst$", -) -async def colgate(event): - await toothpaste(event) - - -async def toothpaste(event): - try: - await event.respond(_copied_msg["CLIPBOARD"]) - except KeyError: - return await eod( - event, - f"Nothing was copied! Use `{HNDLR}cpy` as reply to a message first!", - ) - except Exception as ex: - return await event.eor(str(ex), time=5) - await event.delete() - - -@ultroid_cmd(pattern="thumb$") -async def thumb_dl(event): - reply = await event.get_reply_message() - if not (reply and reply.file): - return await eod(event, get_string("th_1"), time=5) - if not reply.file.media.thumbs: - return await eod(event, get_string("th_2")) - await event.eor(get_string("com_1")) - x = await event.get_reply_message() - m = await x.download_media(thumb=-1) - await event.reply(file=m) - os.remove(m) - - -@ultroid_cmd(pattern="getmsg( ?(.*)|$)") -async def get_restriced_msg(event): - match = event.pattern_match.group(1).strip() - if not match: - await event.eor("`Please provide a link!`", time=5) - return - xx = await event.eor(get_string("com_1")) - chat, msg = get_chat_and_msgid(match) - if not (chat and msg): - return await event.eor( - f"{get_string('gms_1')}!\nEg: `https://t.me/TeamUltroid/3 or `https://t.me/c/1313492028/3`" - ) - try: - message = await event.client.get_messages(chat, ids=msg) - except BaseException as er: - return await event.eor(f"**ERROR**\n`{er}`") - try: - await event.client.send_message(event.chat_id, message) - await xx.try_delete() - return - except ChatForwardsRestrictedError: - pass - if message.media: - thumb = None - if message.document.thumbs: - thumb = await message.download_media(thumb=-1) - media, _ = await event.client.fast_downloader( - message.document, - show_progress=True, - event=xx, - message=f"Downloading {message.file.name}...", - ) - await xx.edit("`Uploading...`") - uploaded, _ = await event.client.fast_uploader( - media.name, event=xx, show_progress=True, to_delete=True - ) - typ = not bool(message.video) - await event.reply( - message.text, - file=uploaded, - supports_streaming=typ, - force_document=typ, - thumb=thumb, - attributes=message.document.attributes, - ) - await xx.delete() - if thumb: - os.remove(thumb) diff --git a/plugins/variables.py b/plugins/variables.py deleted file mode 100644 index c35c33b5ad..0000000000 --- a/plugins/variables.py +++ /dev/null @@ -1,94 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}get var ` - Get value of the given variable name. - -• `{i}get type ` - Get variable type. - -• `{i}get db ` - Get db value of the given key. - -• `{i}get keys` - Get all redis keys. -""" - -import os - -from . import eor, get_string, udB, ultroid_cmd - - -@ultroid_cmd(pattern="get($| (.*))", fullsudo=True) -async def get_var(event): - try: - opt = event.text.split(maxsplit=2)[1] - except IndexError: - return await event.eor(f"what to get?\nRead `{HNDLR}help variables`") - x = await event.eor(get_string("com_1")) - if opt != "keys": - try: - varname = event.text.split(maxsplit=2)[2] - except IndexError: - return await eor(x, "Such a var doesn't exist!", time=5) - if opt == "var": - c = 0 - # try redis - val = udB.get_key(varname) - if val is not None: - c += 1 - await x.edit( - f"**Variable** - `{varname}`\n**Value**: `{val}`\n**Type**: Redis Key." - ) - # try env vars - val = os.getenv(varname) - if val is not None: - c += 1 - await x.edit( - f"**Variable** - `{varname}`\n**Value**: `{val}`\n**Type**: Env Var." - ) - - if c == 0: - await eor(x, "Such a var doesn't exist!", time=5) - - elif opt == "type": - c = 0 - # try redis - val = udB.get_key(varname) - if val is not None: - c += 1 - await x.edit(f"**Variable** - `{varname}`\n**Type**: Redis Key.") - # try env vars - val = os.getenv(varname) - if val is not None: - c += 1 - await x.edit(f"**Variable** - `{varname}`\n**Type**: Env Var.") - - if c == 0: - await eor(x, "Such a var doesn't exist!", time=5) - - elif opt == "db": - val = udB.get(varname) - if val is not None: - await x.edit(f"**Key** - `{varname}`\n**Value**: `{val}`") - else: - await eor(x, "No such key!", time=5) - - elif opt == "keys": - keys = sorted(udB.keys()) - msg = "".join( - f"• `{i}`" + "\n" - for i in keys - if not i.isdigit() - and not i.startswith("-") - and not i.startswith("_") - and not i.startswith("GBAN_REASON_") - ) - - await x.edit(f"**List of DB Keys :**\n{msg}") diff --git a/plugins/videotools.py b/plugins/videotools.py deleted file mode 100644 index 77e5578271..0000000000 --- a/plugins/videotools.py +++ /dev/null @@ -1,139 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -•`{i}sample ` - Creates Short sample of video.. - -• `{i}vshots ` - Creates screenshot of video.. - -• `{i}vtrim - in seconds` - Crop a Lengthy video.. -""" - -import glob -import os - -from pyUltroid.fns.tools import set_attributes - -from . import ( - ULTConfig, - bash, - duration_s, - eod, - genss, - get_string, - mediainfo, - stdr, - ultroid_cmd, -) - - -@ultroid_cmd(pattern="sample( (.*)|$)") -async def gen_sample(e): - sec = e.pattern_match.group(1).strip() - stime = int(sec) if sec and sec.isdigit() else 30 - vido = await e.get_reply_message() - if vido and vido.media and "video" in mediainfo(vido.media): - msg = await e.eor(get_string("com_1")) - file, _ = await e.client.fast_downloader( - vido.document, show_progress=True, event=msg - ) - file_name = (file.name).split("/")[-1] - out = file_name.replace(file_name.split(".")[-1], "_sample.mkv") - xxx = await msg.edit(f"Generating Sample of `{stime}` seconds...") - ss, dd = await duration_s(file.name, stime) - cmd = f'ffmpeg -i "{file.name}" -preset ultrafast -ss {ss} -to {dd} -codec copy -map 0 "{out}" -y' - await bash(cmd) - os.remove(file.name) - attributes = await set_attributes(out) - mmmm, _ = await e.client.fast_uploader( - out, show_progress=True, event=xxx, to_delete=True - ) - caption = f"A Sample Video Of `{stime}` seconds" - await e.client.send_file( - e.chat_id, - mmmm, - thumb=ULTConfig.thumb, - caption=caption, - attributes=attributes, - force_document=False, - reply_to=e.reply_to_msg_id, - ) - await xxx.delete() - else: - await e.eor(get_string("audiotools_8"), time=5) - - -@ultroid_cmd(pattern="vshots( (.*)|$)") -async def gen_shots(e): - ss = e.pattern_match.group(1).strip() - shot = int(ss) if ss and ss.isdigit() else 5 - vido = await e.get_reply_message() - if vido and vido.media and "video" in mediainfo(vido.media): - msg = await e.eor(get_string("com_1")) - file, _ = await e.client.fast_downloader( - vido.document, show_progress=True, event=msg - ) - xxx = await msg.edit(f"Generating `{shot}` screenshots...") - await bash("rm -rf ss && mkdir ss") - cmd = f'ffmpeg -i "{file.name}" -vf fps=0.009 -vframes {shot} "ss/pic%01d.png"' - await bash(cmd) - os.remove(file.name) - pic = glob.glob("ss/*") - text = f"Uploaded {len(pic)}/{shot} screenshots" - if not pic: - text = "`Failed to Take Screenshots..`" - pic = None - await e.respond(text, file=pic) - await bash("rm -rf ss") - await xxx.delete() - - -@ultroid_cmd(pattern="vtrim( (.*)|$)") -async def gen_sample(e): - sec = e.pattern_match.group(1).strip() - if not sec or "-" not in sec: - return await eod(e, get_string("audiotools_3")) - a, b = sec.split("-") - if int(a) >= int(b): - return await eod(e, get_string("audiotools_4")) - vido = await e.get_reply_message() - if vido and vido.media and "video" in mediainfo(vido.media): - msg = await e.eor(get_string("audiotools_5")) - file, _ = await e.client.fast_downloader( - vido.document, show_progress=True, event=msg - ) - file_name = (file.name).split("/")[-1] - out = file_name.replace(file_name.split(".")[-1], "_trimmed.mkv") - if int(b) > int(await genss(file.name)): - os.remove(file.name) - return await eod(msg, get_string("audiotools_6")) - ss, dd = stdr(int(a)), stdr(int(b)) - xxx = await msg.edit(f"Trimming Video from `{ss}` to `{dd}`...") - cmd = f'ffmpeg -i "{file.name}" -preset ultrafast -ss {ss} -to {dd} -codec copy -map 0 "{out}" -y' - await bash(cmd) - os.remove(file.name) - attributes = await set_attributes(out) - mmmm, _ = await e.client.fast_uploader( - out, show_progress=True, event=msg, to_delete=True - ) - caption = f"Trimmed Video From `{ss}` To `{dd}`" - await e.client.send_file( - e.chat_id, - mmmm, - thumb=ULTConfig.thumb, - caption=caption, - attributes=attributes, - force_document=False, - reply_to=e.reply_to_msg_id, - ) - await xxx.delete() - else: - await e.eor(get_string("audiotools_8"), time=5) diff --git a/plugins/warn.py b/plugins/warn.py deleted file mode 100644 index 83b4e4f7df..0000000000 --- a/plugins/warn.py +++ /dev/null @@ -1,180 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - -•`{i}warn ` - Gives Warn. - -•`{i}resetwarn ` - To reset All Warns. - -•`{i}warns ` - To Get List of Warnings of a user. - -•`{i}setwarn | ` - Set Number in warn count for warnings - After putting " | " mark put action like ban/mute/kick - Its Default 3 kick - Example : `setwarn 5 | mute` - -""" - -from pyUltroid.dB.warn_db import add_warn, reset_warn, warns - -from . import eor, get_string, inline_mention, udB, ultroid_cmd - - -@ultroid_cmd( - pattern="warn( (.*)|$)", - manager=True, - groups_only=True, - admins_only=True, -) -async def warn(e): - ultroid_bot = e.client - reply = await e.get_reply_message() - if len(e.text) > 5 and " " not in e.text[5]: - return - if reply: - user = reply.sender_id - reason = e.text[5:] if e.pattern_match.group(1).strip() else "unknown" - else: - try: - user = e.text.split()[1] - if user.startswith("@"): - ok = await ultroid_bot.get_entity(user) - user = ok.id - else: - user = int(user) - except BaseException: - return await e.eor("Reply To A User", time=5) - try: - reason = e.text.split(maxsplit=2)[-1] - except BaseException: - reason = "unknown" - count, r = warns(e.chat_id, user) - r = f"{r}|$|{reason}" if r else reason - try: - x = udB.get_key("SETWARN") - number, action = int(x.split()[0]), x.split()[1] - except BaseException: - number, action = 3, "kick" - if ("ban" or "kick" or "mute") not in action: - action = "kick" - if count + 1 >= number: - if "ban" in action: - try: - await ultroid_bot.edit_permissions(e.chat_id, user, view_messages=False) - except BaseException: - return await e.eor("`Something Went Wrong.`", time=5) - elif "kick" in action: - try: - await ultroid_bot.kick_participant(e.chat_id, user) - except BaseException: - return await e.eor("`Something Went Wrong.`", time=5) - elif "mute" in action: - try: - await ultroid_bot.edit_permissions( - e.chat_id, user, until_date=None, send_messages=False - ) - except BaseException: - return await e.eor("`Something Went Wrong.`", time=5) - add_warn(e.chat_id, user, count + 1, r) - c, r = warns(e.chat_id, user) - ok = await ultroid_bot.get_entity(user) - user = inline_mention(ok) - r = r.split("|$|") - text = f"User {user} Got {action} Due to {count+1} Warns.\n\n" - for x in range(c): - text += f"•**{x+1}.** {r[x]}\n" - await e.eor(text) - return reset_warn(e.chat_id, ok.id) - add_warn(e.chat_id, user, count + 1, r) - ok = await ultroid_bot.get_entity(user) - user = inline_mention(ok) - await eor( - e, - f"**WARNING :** {count+1}/{number}\n**To :**{user}\n**Be Careful !!!**\n\n**Reason** : {reason}", - ) - - -@ultroid_cmd( - pattern="resetwarn( (.*)|$)", - manager=True, - groups_only=True, - admins_only=True, -) -async def rwarn(e): - reply = await e.get_reply_message() - if reply: - user = reply.sender_id - else: - try: - user = e.text.split()[1] - if user.startswith("@"): - ok = await e.client.get_entity(user) - user = ok.id - else: - user = int(user) - except BaseException: - return await e.eor("Reply To user") - reset_warn(e.chat_id, user) - ok = await e.client.get_entity(user) - user = inline_mention(ok) - await e.eor(f"Cleared All Warns of {user}.") - - -@ultroid_cmd( - pattern="warns( (.*)|$)", - manager=True, - groups_only=True, - admins_only=True, -) -async def twarns(e): - reply = await e.get_reply_message() - if reply: - user = reply.from_id.user_id - else: - try: - user = e.text.split()[1] - if user.startswith("@"): - ok = await e.client.get_entity(user) - user = ok.id - else: - user = int(user) - except BaseException: - return await e.eor("Reply To A User", time=5) - c, r = warns(e.chat_id, user) - if c and r: - ok = await e.client.get_entity(user) - user = inline_mention(ok) - r = r.split("|$|") - text = f"User {user} Got {c} Warns.\n\n" - for x in range(c): - text += f"•**{x+1}.** {r[x]}\n" - await e.eor(text) - else: - await e.eor("`No Warnings`") - - -@ultroid_cmd(pattern="setwarn( (.*)|$)", manager=True) -async def warnset(e): - ok = e.pattern_match.group(1).strip() - if not ok: - return await e.eor("stuff") - if "|" in ok: - try: - number, action = int(ok.split()[0]), ok.split()[1] - except BaseException: - return await e.eor(get_string("schdl_2"), time=5) - if ("ban" or "kick" or "mute") not in action: - return await e.eor("`Only mute / ban / kick option suported`", time=5) - udB.set_key("SETWARN", f"{number} {action}") - await e.eor(f"Done Your Warn Count is now {number} and Action is {action}") - else: - await e.eor(get_string("schdl_2"), time=5) diff --git a/plugins/webupload.py b/plugins/webupload.py deleted file mode 100644 index b807ecd96a..0000000000 --- a/plugins/webupload.py +++ /dev/null @@ -1,69 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -""" -✘ Commands Available - - -• `{i}webupload` - Upload files on another server. -""" - -import os - -from pyUltroid.fns.tools import _webupload_cache - -from . import Button, asst, get_string, ultroid_cmd - - -@ultroid_cmd( - pattern="webupload( (.*)|$)", -) -async def _(event): - xx = await event.eor(get_string("com_1")) - match = event.pattern_match.group(1).strip() - if event.chat_id not in _webupload_cache: - _webupload_cache.update({int(event.chat_id): {}}) - if match: - if not os.path.exists(match): - return await xx.eor("`File doesn't exist.`") - _webupload_cache[event.chat_id][event.id] = match - elif event.reply_to_msg_id: - reply = await event.get_reply_message() - if reply.photo: - file = await reply.download_media("resources/downloads/") - _webupload_cache[int(event.chat_id)][int(event.id)] = file - else: - file, _ = await event.client.fast_downloader( - reply.document, show_progress=True, event=xx - ) - _webupload_cache[int(event.chat_id)][int(event.id)] = file.name - else: - return await xx.eor("`Reply to file or give file path...`") - if not event.client._bot: - results = await event.client.inline_query( - asst.me.username, f"fl2lnk {event.chat_id}:{event.id}" - ) - await results[0].click(event.chat_id, reply_to=event.reply_to_msg_id) - await xx.delete() - - else: - __cache = f"{event.chat_id}:{event.id}" - buttons = [ - [ - Button.inline("anonfiles", data=f"flanonfiles//{__cache}"), - Button.inline("transfer", data=f"fltransfer//{__cache}"), - ], - [ - Button.inline("bayfiles", data=f"flbayfiles//{__cache}"), - Button.inline("x0.at", data=f"flx0.at//{__cache}"), - ], - [ - Button.inline("file.io", data=f"flfile.io//{__cache}"), - Button.inline("siasky", data=f"flsiasky//{__cache}"), - ], - ] - await xx.edit("**Choose Server to Upload File...**", buttons=buttons) diff --git a/plugins/words.py b/plugins/words.py deleted file mode 100644 index 6b4f8d670c..0000000000 --- a/plugins/words.py +++ /dev/null @@ -1,115 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}meaning ` - Get the meaning of the word. - -• `{i}synonym ` - Get all synonyms. - -• `{i}antonym ` - Get all antonyms. - -• `{i}ud ` - Fetch word defenition from urbandictionary. -""" -import io - -from pyUltroid.fns.misc import get_synonyms_or_antonyms -from pyUltroid.fns.tools import async_searcher - -from . import get_string, ultroid_cmd - - -@ultroid_cmd(pattern="meaning( (.*)|$)", manager=True) -async def mean(event): - wrd = event.pattern_match.group(1).strip() - if not wrd: - return await event.eor(get_string("wrd_4")) - url = f"https://api.dictionaryapi.dev/api/v2/entries/en/{wrd}" - out = await async_searcher(url, re_json=True) - try: - return await event.eor(f'**{out["title"]}**') - except (KeyError, TypeError): - pass - defi = out[0]["meanings"][0]["definitions"][0] - ex = defi["example"] if defi.get("example") else "None" - text = get_string("wrd_1").format(wrd, defi["definition"], ex) - if defi.get("synonyms"): - text += ( - f"\n\n• **{get_string('wrd_5')} :**" - + "".join(f" {a}," for a in defi["synonyms"])[:-1][:10] - ) - if defi.get("antonyms"): - text += ( - f"\n\n**{get_string('wrd_6')} :**" - + "".join(f" {a}," for a in defi["antonyms"])[:-1][:10] - ) - if len(text) > 4096: - with io.BytesIO(str.encode(text)) as fle: - fle.name = f"{wrd}-meanings.txt" - await event.reply( - file=fle, - force_document=True, - caption=f"Meanings of {wrd}", - ) - await event.delete() - else: - await event.eor(text) - - -@ultroid_cmd( - pattern="(syno|anto)nym", -) -async def mean(event): - task = event.pattern_match.group(1) + "nyms" - try: - wrd = event.text.split(maxsplit=1)[1] - except IndexError: - return await event.eor("Give Something to search..") - try: - ok = await get_synonyms_or_antonyms(wrd, task) - x = get_string("wrd_2" if task == "synonyms" else "wrd_3").format(wrd) - for c, i in enumerate(ok, start=1): - x += f"**{c}.** `{i}`\n" - if len(x) > 4096: - with io.BytesIO(str.encode(x)) as fle: - fle.name = f"{wrd}-{task}.txt" - await event.client.send_file( - event.chat_id, - fle, - force_document=True, - allow_cache=False, - caption=f"{task} of {wrd}", - reply_to=event.reply_to_msg_id, - ) - await event.delete() - else: - await event.eor(x) - except Exception as e: - await event.eor( - get_string("wrd_7" if task == "synonyms" else "wrd_8").format(e) - ) - - -@ultroid_cmd(pattern="ud (.*)") -async def _(event): - word = event.pattern_match.group(1).strip() - if not word: - return await event.eor(get_string("autopic_1")) - out = await async_searcher( - "http://api.urbandictionary.com/v0/define", params={"term": word}, re_json=True - ) - try: - out = out["list"][0] - except IndexError: - return await event.eor(get_string("autopic_2").format(word)) - await event.eor( - get_string("wrd_1").format(out["word"], out["definition"], out["example"]), - ) diff --git a/plugins/writer.py b/plugins/writer.py deleted file mode 100644 index fccbc8491c..0000000000 --- a/plugins/writer.py +++ /dev/null @@ -1,85 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -""" -✘ Commands Available - - -• `{i}write ` - It will write on a paper. - -• `{i}image ` - Write a image from html or any text. -""" - -import os - -from htmlwebshot import WebShot -from PIL import Image, ImageDraw, ImageFont - -from . import async_searcher, eod, get_string, text_set, ultroid_cmd - - -@ultroid_cmd(pattern="gethtml( (.*)|$)") -async def ghtml(e): - if txt := e.pattern_match.group(1).strip(): - link = e.text.split(maxsplit=1)[1] - else: - return await eod(e, "`Either reply to any file or give any text`") - k = await async_searcher(link) - with open("file.html", "w+") as f: - f.write(k) - await e.reply(file="file.html") - - -@ultroid_cmd(pattern="image( (.*)|$)") -async def f2i(e): - txt = e.pattern_match.group(1).strip() - html = None - if txt: - html = e.text.split(maxsplit=1)[1] - elif e.reply_to: - r = await e.get_reply_message() - if r.media: - html = await e.client.download_media(r.media) - elif r.text: - html = r.text - if not html: - return await eod(e, "`Either reply to any file or give any text`") - html = html.replace("\n", "
    ") - shot = WebShot(quality=85) - css = "body {background: white;} p {color: red;}" - pic = await shot.create_pic_async(html=html, css=css) - await e.reply(file=pic, force_document=True) - os.remove(pic) - if os.path.exists(html): - os.remove(html) - - -@ultroid_cmd(pattern="write( (.*)|$)") -async def writer(e): - if e.reply_to: - reply = await e.get_reply_message() - text = reply.message - elif e.pattern_match.group(1).strip(): - text = e.text.split(maxsplit=1)[1] - else: - return await eod(e, get_string("writer_1")) - k = await e.eor(get_string("com_1")) - img = Image.open("resources/extras/template.jpg") - draw = ImageDraw.Draw(img) - font = ImageFont.truetype("resources/fonts/assfont.ttf", 30) - x, y = 150, 140 - lines = text_set(text) - line_height = font.getsize("hg")[1] - for line in lines: - draw.text((x, y), line, fill=(1, 22, 55), font=font) - y = y + line_height - 5 - file = "ult.jpg" - img.save(file) - await e.reply(file=file) - os.remove(file) - await k.delete() diff --git a/plugins/youtube.py b/plugins/youtube.py deleted file mode 100644 index e961972eaf..0000000000 --- a/plugins/youtube.py +++ /dev/null @@ -1,85 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - - -• `{i}yta <(youtube/any) link>` - Download audio from the link. - -• `{i}ytv <(youtube/any) link>` - Download video from the link. - -• `{i}ytsa <(youtube) search query>` - Search and download audio from youtube. - -• `{i}ytsv <(youtube) search query>` - Search and download video from youtube. -""" -from pyUltroid.fns.ytdl import download_yt, get_yt_link - -from . import get_string, requests, ultroid_cmd - - -@ultroid_cmd( - pattern="yt(a|v|sa|sv) ?(.*)", -) -async def download_from_youtube_(event): - ytd = { - "prefer_ffmpeg": True, - "addmetadata": True, - "geo-bypass": True, - "nocheckcertificate": True, - } - opt = event.pattern_match.group(1).strip() - xx = await event.eor(get_string("com_1")) - if opt == "a": - ytd["format"] = "bestaudio" - ytd["outtmpl"] = "%(id)s.m4a" - url = event.pattern_match.group(2) - if not url: - return await xx.eor(get_string("youtube_1")) - try: - requests.get(url) - except BaseException: - return await xx.eor(get_string("youtube_2")) - elif opt == "v": - ytd["format"] = "best" - ytd["outtmpl"] = "%(id)s.mp4" - ytd["postprocessors"] = [{"key": "FFmpegMetadata"}] - url = event.pattern_match.group(2) - if not url: - return await xx.eor(get_string("youtube_3")) - try: - requests.get(url) - except BaseException: - return await xx.eor(get_string("youtube_4")) - elif opt == "sa": - ytd["format"] = "bestaudio" - ytd["outtmpl"] = "%(id)s.m4a" - try: - query = event.text.split(" ", 1)[1] - except IndexError: - return await xx.eor(get_string("youtube_5")) - url = get_yt_link(query) - if not url: - return await xx.edit(get_string("unspl_1")) - await xx.eor(get_string("youtube_6")) - elif opt == "sv": - ytd["format"] = "best" - ytd["outtmpl"] = "%(id)s.mp4" - ytd["postprocessors"] = [{"key": "FFmpegMetadata"}] - try: - query = event.text.split(" ", 1)[1] - except IndexError: - return await xx.eor(get_string("youtube_7")) - url = get_yt_link(query) - if not url: - return await xx.edit(get_string("unspl_1")) - await xx.eor(get_string("youtube_8")) - else: - return - await download_yt(xx, url, ytd) diff --git a/plugins/ziptools.py b/plugins/ziptools.py deleted file mode 100644 index b1a425f6dc..0000000000 --- a/plugins/ziptools.py +++ /dev/null @@ -1,168 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -""" -✘ Commands Available - -• `{i}zip ` - zip the replied file - To set password on zip: `{i}zip ` reply to file - -• `{i}unzip ` - unzip the replied file. - -• `{i}azip ` - add file to batch for batch upload zip - -• `{i}dozip` - upload batch zip the files u added from `{i}azip` - To set Password: `{i}dozip ` - -""" -import os -import time - -from . import ( - HNDLR, - ULTConfig, - asyncio, - bash, - downloader, - get_all_files, - get_string, - ultroid_cmd, - uploader, -) - - -@ultroid_cmd(pattern="zip( (.*)|$)") -async def zipp(event): - reply = await event.get_reply_message() - t = time.time() - if not reply: - await event.eor(get_string("zip_1")) - return - xx = await event.eor(get_string("com_1")) - if reply.media: - if hasattr(reply.media, "document"): - file = reply.media.document - image = await downloader( - reply.file.name, reply.media.document, xx, t, get_string("com_5") - ) - file = image.name - else: - file = await event.download_media(reply) - inp = file.replace(file.split(".")[-1], "zip") - if event.pattern_match.group(1).strip(): - await bash( - f"zip -r --password {event.pattern_match.group(1).strip()} {inp} {file}" - ) - else: - await bash(f"zip -r {inp} {file}") - k = time.time() - xxx = await uploader(inp, inp, k, xx, get_string("com_6")) - await event.client.send_file( - event.chat_id, - xxx, - force_document=True, - thumb=ULTConfig.thumb, - caption=f"`{xxx.name}`", - reply_to=reply, - ) - os.remove(inp) - os.remove(file) - await xx.delete() - - -@ultroid_cmd(pattern="unzip( (.*)|$)") -async def unzipp(event): - reply = await event.get_reply_message() - file = event.pattern_match.group(1).strip() - t = time.time() - if not ((reply and reply.media) or file): - await event.eor(get_string("zip_1")) - return - xx = await event.eor(get_string("com_1")) - if reply.media: - if not hasattr(reply.media, "document"): - return await xx.edit(get_string("zip_3")) - file = reply.media.document - if not reply.file.name.endswith(("zip", "rar", "exe")): - return await xx.edit(get_string("zip_3")) - image = await downloader( - reply.file.name, reply.media.document, xx, t, get_string("com_5") - ) - file = image.name - if os.path.isdir("unzip"): - await bash("rm -rf unzip") - os.mkdir("unzip") - await bash(f"7z x {file} -aoa -ounzip") - await asyncio.sleep(4) - ok = get_all_files("unzip") - for x in ok: - k = time.time() - xxx = await uploader(x, x, k, xx, get_string("com_6")) - await event.client.send_file( - event.chat_id, - xxx, - force_document=True, - thumb=ULTConfig.thumb, - caption=f"`{xxx.name}`", - ) - await xx.delete() - - -@ultroid_cmd(pattern="addzip$") -async def azipp(event): - reply = await event.get_reply_message() - t = time.time() - if not (reply and reply.media): - await event.eor(get_string("zip_1")) - return - xx = await event.eor(get_string("com_1")) - if not os.path.isdir("zip"): - os.mkdir("zip") - if reply.media: - if hasattr(reply.media, "document"): - file = reply.media.document - image = await downloader( - f"zip/{reply.file.name}", - reply.media.document, - xx, - t, - get_string("com_5"), - ) - - file = image.name - else: - file = await event.download_media(reply.media, "zip/") - await xx.edit( - f"Downloaded `{file}` succesfully\nNow Reply To Other Files To Add And Zip all at once" - ) - - -@ultroid_cmd(pattern="dozip( (.*)|$)") -async def do_zip(event): - if not os.path.isdir("zip"): - return await event.eor(get_string("zip_2").format(HNDLR)) - xx = await event.eor(get_string("com_1")) - if event.pattern_match.group(1).strip(): - await bash( - f"zip -r --password {event.pattern_match.group(1).strip()} ultroid.zip zip/*" - ) - else: - await bash("zip -r ultroid.zip zip/*") - k = time.time() - xxx = await uploader("ultroid.zip", "ultroid.zip", k, xx, get_string("com_6")) - await event.client.send_file( - event.chat_id, - xxx, - force_document=True, - thumb=ULTConfig.thumb, - ) - await bash("rm -rf zip") - os.remove("ultroid.zip") - await xx.delete() diff --git a/pyUltroid/__init__.py b/pyUltroid/__init__.py deleted file mode 100644 index b104de6da8..0000000000 --- a/pyUltroid/__init__.py +++ /dev/null @@ -1,108 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import os -import sys - -from .version import __version__ - -run_as_module = __package__ in sys.argv or sys.argv[0] == "-m" - - -class ULTConfig: - lang = "en" - thumb = "resources/extras/ultroid.jpg" - - -if run_as_module: - import time - - from .configs import Var - from .startup import * - from .startup._database import UltroidDB - from .startup.BaseClient import UltroidClient - from .startup.connections import validate_session, vc_connection - from .startup.funcs import _version_changes, autobot, enable_inline, update_envs - from .version import ultroid_version - - if not os.path.exists("./plugins"): - LOGS.error( - "'plugins' folder not found!\nMake sure that, you are on correct path." - ) - exit() - - start_time = time.time() - _ult_cache = {} - _ignore_eval = [] - - udB = UltroidDB() - update_envs() - - LOGS.info(f"Connecting to {udB.name}...") - if udB.ping(): - LOGS.info(f"Connected to {udB.name} Successfully!") - - BOT_MODE = udB.get_key("BOTMODE") - DUAL_MODE = udB.get_key("DUAL_MODE") - - USER_MODE = udB.get_key("USER_MODE") - if USER_MODE: - DUAL_MODE = False - - if BOT_MODE: - if DUAL_MODE: - udB.del_key("DUAL_MODE") - DUAL_MODE = False - ultroid_bot = None - - if not udB.get_key("BOT_TOKEN"): - LOGS.critical( - '"BOT_TOKEN" not Found! Please add it, in order to use "BOTMODE"' - ) - - sys.exit() - else: - ultroid_bot = UltroidClient( - validate_session(Var.SESSION, LOGS), - udB=udB, - app_version=ultroid_version, - device_model="Ultroid", - ) - ultroid_bot.run_in_loop(autobot()) - - if USER_MODE: - asst = ultroid_bot - else: - asst = UltroidClient(None, bot_token=udB.get_key("BOT_TOKEN"), udB=udB) - - if BOT_MODE: - ultroid_bot = asst - if udB.get_key("OWNER_ID"): - try: - ultroid_bot.me = ultroid_bot.run_in_loop( - ultroid_bot.get_entity(udB.get_key("OWNER_ID")) - ) - except Exception as er: - LOGS.exception(er) - elif not asst.me.bot_inline_placeholder and asst._bot: - ultroid_bot.run_in_loop(enable_inline(ultroid_bot, asst.me.username)) - - vcClient = vc_connection(udB, ultroid_bot) - - _version_changes(udB) - - HNDLR = udB.get_key("HNDLR") or "." - DUAL_HNDLR = udB.get_key("DUAL_HNDLR") or "/" - SUDO_HNDLR = udB.get_key("SUDO_HNDLR") or HNDLR -else: - print("pyUltroid 2022 © TeamUltroid") - - from logging import getLogger - - LOGS = getLogger("pyUltroid") - - ultroid_bot = asst = udB = vcClient = None diff --git a/pyUltroid/__main__.py b/pyUltroid/__main__.py deleted file mode 100644 index c5249e8691..0000000000 --- a/pyUltroid/__main__.py +++ /dev/null @@ -1,110 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from . import * - - -def main(): - import os - import sys - import time - - from .fns.helper import bash, time_formatter, updater - from .startup.funcs import ( - WasItRestart, - autopilot, - customize, - fetch_ann, - plug, - ready, - startup_stuff, - ) - from .startup.loader import load_other_plugins - - try: - from apscheduler.schedulers.asyncio import AsyncIOScheduler - except ImportError: - AsyncIOScheduler = None - - # Option to Auto Update On Restarts.. - if ( - udB.get_key("UPDATE_ON_RESTART") - and os.path.exists(".git") - and ultroid_bot.run_in_loop(updater()) - ): - ultroid_bot.run_in_loop(bash("bash installer.sh")) - - os.execl(sys.executable, sys.executable, "-m", "pyUltroid") - - ultroid_bot.run_in_loop(startup_stuff()) - - ultroid_bot.me.phone = None - - if not ultroid_bot.me.bot: - udB.set_key("OWNER_ID", ultroid_bot.uid) - - LOGS.info("Initialising...") - - ultroid_bot.run_in_loop(autopilot()) - - pmbot = udB.get_key("PMBOT") - manager = udB.get_key("MANAGER") - addons = udB.get_key("ADDONS") or Var.ADDONS - vcbot = udB.get_key("VCBOT") or Var.VCBOT - if HOSTED_ON == "okteto": - vcbot = False - - if (HOSTED_ON == "termux" or udB.get_key("LITE_DEPLOY")) and udB.get_key( - "EXCLUDE_OFFICIAL" - ) is None: - _plugins = "autocorrect autopic audiotools compressor forcesubscribe fedutils gdrive glitch instagram nsfwfilter nightmode pdftools profanityfilter writer youtube" - udB.set_key("EXCLUDE_OFFICIAL", _plugins) - - load_other_plugins(addons=addons, pmbot=pmbot, manager=manager, vcbot=vcbot) - - suc_msg = """ - ---------------------------------------------------------------------- - Ultroid has been deployed! Visit @TheUltroid for updates!! - ---------------------------------------------------------------------- - """ - - # for channel plugins - plugin_channels = udB.get_key("PLUGIN_CHANNEL") - - # Customize Ultroid Assistant... - ultroid_bot.run_in_loop(customize()) - - # Load Addons from Plugin Channels. - if plugin_channels: - ultroid_bot.run_in_loop(plug(plugin_channels)) - - # Send/Ignore Deploy Message.. - if not udB.get_key("LOG_OFF"): - ultroid_bot.run_in_loop(ready()) - if AsyncIOScheduler: - scheduler = AsyncIOScheduler() - scheduler.add_job(fetch_ann, "interval", minutes=12 * 60) - scheduler.start() - - # Edit Restarting Message (if It's restarting) - ultroid_bot.run_in_loop(WasItRestart(udB)) - - try: - cleanup_cache() - except BaseException: - pass - - LOGS.info( - f"Took {time_formatter((time.time() - start_time)*1000)} to start •ULTROID•" - ) - LOGS.info(suc_msg) - - -if __name__ == "__main__": - main() - - asst.run() diff --git a/pyUltroid/_misc/__init__.py b/pyUltroid/_misc/__init__.py deleted file mode 100644 index d90f66adcc..0000000000 --- a/pyUltroid/_misc/__init__.py +++ /dev/null @@ -1,74 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -from .. import * - -CMD_HELP = {} -# ----------------------------------------------# - - -class _SudoManager: - def __init__(self): - self.db = None - self.owner = None - self._owner_sudos = [] - - def _init_db(self): - if not self.db: - from .. import udB - - self.db = udB - return self.db - - def get_sudos(self): - db = self._init_db() - SUDOS = db.get_key("SUDOS") - return SUDOS or [] - - @property - def should_allow_sudo(self): - db = self._init_db() - return db.get_key("SUDO") - - def owner_and_sudos(self): - if not self.owner: - db = self._init_db() - self.owner = db.get_key("OWNER_ID") - return [self.owner, *self.get_sudos()] - - @property - def fullsudos(self): - db = self._init_db() - fsudos = db.get("FULLSUDO") - if not self.owner: - self.owner = db.get_key("OWNER_ID") - if not fsudos: - return [self.owner] - fsudos = fsudos.split() - fsudos.append(self.owner) - return [int(_) for _ in fsudos] - - def is_sudo(self, id_): - return bool(id_ in self.get_sudos()) - - -SUDO_M = _SudoManager() -owner_and_sudos = SUDO_M.owner_and_sudos -sudoers = SUDO_M.get_sudos -is_sudo = SUDO_M.is_sudo - -# ------------------------------------------------ # - - -def append_or_update(load, func, name, arggs): - if isinstance(load, list): - return load.append(func) - if isinstance(load, dict): - if load.get(name): - return load[name].append((func, arggs)) - return load.update({name: [(func, arggs)]}) diff --git a/pyUltroid/_misc/_supporter.py b/pyUltroid/_misc/_supporter.py deleted file mode 100644 index 43c1503e24..0000000000 --- a/pyUltroid/_misc/_supporter.py +++ /dev/null @@ -1,126 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . -# -# To Install Other USERBOTs plugin Support -# -# ULTROID Don't Need This Stuffs -# - -import inspect -import os -from pathlib import Path - -from telethon import events, types - -from pyUltroid._misc._decorators import compile_pattern, ultroid_cmd -from pyUltroid._misc._wrappers import eod, eor - -from .. import * -from ..dB._core import LIST -from . import CMD_HELP, SUDO_M # ignore: pylint - -ALIVE_NAME = ultroid_bot.me.first_name -BOTLOG_CHATID = BOTLOG = udB.get_key("LOG_CHANNEL") - - -bot = borg = catub = friday = ultroid_bot -catub.cat_cmd = ultroid_cmd - -black_list_chats = udB.get_key("BLACKLIST_CHATS") - - -def admin_cmd(pattern=None, command=None, **args): - args["func"] = lambda e: not e.via_bot_id - args["chats"] = black_list_chats - args["blacklist_chats"] = True - args["outgoing"] = True - args["forwards"] = False - if pattern: - args["pattern"] = compile_pattern(pattern, HNDLR) - file = Path(inspect.stack()[1].filename) - if LIST.get(file.stem): - LIST[file.stem].append(pattern) - else: - LIST.update({file.stem: [pattern]}) - return events.NewMessage(**args) - - -friday_on_cmd = admin_cmd -command = ultroid_cmd -register = ultroid_cmd - - -def sudo_cmd(allow_sudo=True, pattern=None, command=None, **args): - args["func"] = lambda e: not e.via_bot_id - args["chats"] = black_list_chats - args["blacklist_chats"] = True - args["forwards"] = False - if pattern: - args["pattern"] = compile_pattern(pattern, SUDO_HNDLR) - if allow_sudo: - args["from_users"] = SUDO_M.get_sudos - args["incoming"] = True - return events.NewMessage(**args) - - -edit_or_reply = eor -edit_delete = eod - - -ENV = bool(os.environ.get("ENV", False)) - - -class Config((object)): - if ENV: - from .. import asst, udB - - LOGGER = True - LOCATION = os.environ.get("LOCATION", None) - OPEN_WEATHER_MAP_APPID = os.environ.get("OPEN_WEATHER_MAP_APPID", None) - SUDO_COMMAND_HAND_LER = SUDO_HNDLR - TMP_DOWNLOAD_DIRECTORY = os.environ.get( - "TMP_DOWNLOAD_DIRECTORY", "resources/downloads/" - ) - TEMP_DOWNLOAD_DIRECTORY = TMP_DOWNLOAD_DIRECTORY - TEMP_DIR = TMP_DOWNLOAD_DIRECTORY - TELEGRAPH_SHORT_NAME = os.environ.get("TELEGRAPH_SHORT_NAME", "Ultroid") - OCR_SPACE_API_KEY = os.environ.get("OCR_SPACE_API_KEY", None) - TG_BOT_USER_NAME_BF_HER = asst.me.username - UB_BLACK_LIST_CHAT = [ - int(blacklist) for blacklist in udB.get_key("BLACKLIST_CHATS") - ] - MAX_ANTI_FLOOD_MESSAGES = 10 - ANTI_FLOOD_WARN_MODE = types.ChatBannedRights( - until_date=None, view_messages=None, send_messages=True - ) - REM_BG_API_KEY = os.environ.get("REM_BG_API_KEY", None) - GITHUB_ACCESS_TOKEN = os.environ.get("GITHUB_ACCESS_TOKEN", None) - GIT_REPO_NAME = os.environ.get("GIT_REPO_NAME", None) - PRIVATE_GROUP_BOT_API_ID = BOTLOG - PM_LOGGR_BOT_API_ID = BOTLOG - DB_URI = os.environ.get("DATABASE_URL", None) - HANDLR = HNDLR - SUDO_USERS = SUDO_M.get_sudos() - CHANNEL_ID = int(os.environ.get("CHANNEL_ID", -100)) - BLACKLIST_CHAT = UB_BLACK_LIST_CHAT - MONGO_URI = os.environ.get("MONGO_URI", None) - ALIVE_PHOTTO = os.environ.get("ALIVE_PHOTTO", None) - ALIVE_PIC = os.environ.get("ALIVE_PIC", None) - ALIVE_MSG = os.environ.get("ALIVE_MSG", None) - DEFAULT_BIO = os.environ.get("DEFAULT_BIO", None) - BIO_MSG = os.environ.get("BIO_MSG", None) - LYDIA_API = os.environ.get("LYDIA_API", None) - PLUGIN_CHANNEL = int(os.environ.get("PLUGIN_CHANNEL", -69)) - PM_DATA = os.environ.get("PM_DATA", "ENABLE") - DEEP_AI = os.environ.get("DEEP_AI", None) - TAG_LOG = os.environ.get("TAG_LOG", None) - - else: - DB_URI = None - - -CMD_HNDLR = HNDLR diff --git a/pyUltroid/configs.py b/pyUltroid/configs.py deleted file mode 100644 index e8515cc62e..0000000000 --- a/pyUltroid/configs.py +++ /dev/null @@ -1,55 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import sys - -from decouple import config - -try: - from dotenv import load_dotenv - - load_dotenv() -except ImportError: - pass - - -class Var: - # mandatory - API_ID = ( - int(sys.argv[1]) if len(sys.argv) > 1 else config("API_ID", default=6, cast=int) - ) - API_HASH = ( - sys.argv[2] - if len(sys.argv) > 2 - else config("API_HASH", default="eb06d4abfb49dc3eeb1aeb98ae0f581e") - ) - SESSION = sys.argv[3] if len(sys.argv) > 3 else config("SESSION", default=None) - REDIS_URI = ( - sys.argv[4] - if len(sys.argv) > 4 - else (config("REDIS_URI", default=None) or config("REDIS_URL", default=None)) - ) - REDIS_PASSWORD = ( - sys.argv[5] if len(sys.argv) > 5 else config("REDIS_PASSWORD", default=None) - ) - # extras - BOT_TOKEN = config("BOT_TOKEN", default=None) - LOG_CHANNEL = config("LOG_CHANNEL", default=0, cast=int) - HEROKU_APP_NAME = config("HEROKU_APP_NAME", default=None) - HEROKU_API = config("HEROKU_API", default=None) - VC_SESSION = config("VC_SESSION", default=None) - ADDONS = config("ADDONS", default=False, cast=bool) - VCBOT = config("VCBOT", default=False, cast=bool) - # for railway - REDISPASSWORD = config("REDISPASSWORD", default=None) - REDISHOST = config("REDISHOST", default=None) - REDISPORT = config("REDISPORT", default=None) - REDISUSER = config("REDISUSER", default=None) - # for sql - DATABASE_URL = config("DATABASE_URL", default=None) - # for MONGODB users - MONGO_URI = config("MONGO_URI", default=None) diff --git a/pyUltroid/dB/__init__.py b/pyUltroid/dB/__init__.py deleted file mode 100644 index 4359b80a85..0000000000 --- a/pyUltroid/dB/__init__.py +++ /dev/null @@ -1,65 +0,0 @@ -from .. import run_as_module - -if not run_as_module: - from ..exceptions import RunningAsFunctionLibError - - raise RunningAsFunctionLibError( - "You are running 'pyUltroid' as a functions lib, not as run module. You can't access this folder.." - ) - -from .. import * - -DEVLIST = [ - 719195224, # @xditya - 1322549723, # @danish_00 - 1903729401, # @its_buddhhu - 1303895686, # @Sipak_OP - 611816596, # @Arnab431 - 1318486004, # @sppidy - 803243487, # @hellboi_atul -] - -ULTROID_IMAGES = [ - f"https://graph.org/file/{_}.jpg" - for _ in [ - "ec250c66268b62ee4ade6", - "3c25230ae30d246194eba", - "b01715a61b9e876c0d45d", - "4ceaf720a96a24527ecff", - "a96223b574f29f3f0d184", - "6e081d339a01cc6190393", - ] -] - -stickers = [ - "CAADAQADeAIAAm_BZBQh8owdViocCAI", - "CAADAQADegIAAm_BZBQ6j8GpKtnrSgI", - "CAADAQADfAIAAm_BZBQpqC84n9JNXgI", - "CAADAQADfgIAAm_BZBSxLmTyuHvlzgI", - "CAADAQADgAIAAm_BZBQ3TZaueMkS-gI", - "CAADAQADggIAAm_BZBTPcbJMorVVsQI", - "CAADAQADhAIAAm_BZBR3lnMZRdsYxAI", - "CAADAQADhgIAAm_BZBQGQRx4iaM4pQI", - "CAADAQADiAIAAm_BZBRRF-cjJi_QywI", - "CAADAQADigIAAm_BZBQQJwfzkqLM0wI", - "CAADAQADjAIAAm_BZBQSl5GSAT0viwI", - "CAADAQADjgIAAm_BZBQ2xU688gfHhQI", - "CAADAQADkAIAAm_BZBRGuPNgVvkoHQI", - "CAADAQADpgIAAm_BZBQAAZr0SJ5EKtQC", - "CAADAQADkgIAAm_BZBTvuxuayqvjhgI", - "CAADAQADlAIAAm_BZBSMZdWN2Yew1AI", - "CAADAQADlQIAAm_BZBRXyadiwWGNkwI", - "CAADAQADmAIAAm_BZBQDoB15A1jS1AI", - "CAADAQADmgIAAm_BZBTnOLQ8_d72vgI", - "CAADAQADmwIAAm_BZBTve1kgdG0Y5gI", - "CAADAQADnAIAAm_BZBQUMyFiylJSqQI", - "CAADAQADnQIAAm_BZBSMAe2V4pwhNgI", - "CAADAQADngIAAm_BZBQ06D92QL_vywI", - "CAADAQADnwIAAm_BZBRw7UAbr6vtEgI", - "CAADAQADoAIAAm_BZBRkv9DnGPXh_wI", - "CAADAQADoQIAAm_BZBQwI2NgQdyKlwI", - "CAADAQADogIAAm_BZBRPHJF3XChVLgI", - "CAADAQADowIAAm_BZBThpas7rZD6DAI", - "CAADAQADpAIAAm_BZBQcC2DpZcCw1wI", - "CAADAQADpQIAAm_BZBQKruTcEU4ntwI", -] diff --git a/pyUltroid/dB/afk_db.py b/pyUltroid/dB/afk_db.py deleted file mode 100644 index fa87f25291..0000000000 --- a/pyUltroid/dB/afk_db.py +++ /dev/null @@ -1,33 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from datetime import datetime as dt - -from .. import udB - - -def get_stuff(): - return udB.get_key("AFK_DB") or [] - - -def add_afk(msg, media_type, media): - time = dt.now().strftime("%b %d %Y %I:%M:%S%p") - udB.set_key("AFK_DB", [msg, media_type, media, time]) - return - - -def is_afk(): - afk = get_stuff() - if afk: - start_time = dt.strptime(afk[3], "%b %d %Y %I:%M:%S%p") - afk_since = str(dt.now().replace(microsecond=0) - start_time) - return afk[0], afk[1], afk[2], afk_since - return False - - -def del_afk(): - return udB.del_key("AFK_DB") diff --git a/pyUltroid/dB/antiflood_db.py b/pyUltroid/dB/antiflood_db.py deleted file mode 100644 index 062fff1cbb..0000000000 --- a/pyUltroid/dB/antiflood_db.py +++ /dev/null @@ -1,32 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -from .. import udB - - -def get_flood(): - return udB.get_key("ANTIFLOOD") or {} - - -def set_flood(chat_id, limit): - omk = get_flood() - omk.update({chat_id: limit}) - return udB.set_key("ANTIFLOOD", omk) - - -def get_flood_limit(chat_id): - omk = get_flood() - if chat_id in omk.keys(): - return omk[chat_id] - - -def rem_flood(chat_id): - omk = get_flood() - if chat_id in omk.keys(): - del omk[chat_id] - return udB.set_key("ANTIFLOOD", omk) diff --git a/pyUltroid/dB/asstcmd_db.py b/pyUltroid/dB/asstcmd_db.py deleted file mode 100644 index faf1975515..0000000000 --- a/pyUltroid/dB/asstcmd_db.py +++ /dev/null @@ -1,39 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -from .. import udB - - -def get_stuff(): - return udB.get_key("ASST_CMDS") or {} - - -def add_cmd(cmd, msg, media, button): - ok = get_stuff() - ok.update({cmd: {"msg": msg, "media": media, "button": button}}) - return udB.set_key("ASST_CMDS", ok) - - -def rem_cmd(cmd): - ok = get_stuff() - if ok.get(cmd): - ok.pop(cmd) - return udB.set_key("ASST_CMDS", ok) - - -def cmd_reply(cmd): - ok = get_stuff() - if ok.get(cmd): - okk = ok[cmd] - return okk["msg"], okk["media"], okk["button"] if ok.get("button") else None - return - - -def list_cmds(): - ok = get_stuff() - return ok.keys() diff --git a/pyUltroid/dB/blacklist_chat_db.py b/pyUltroid/dB/blacklist_chat_db.py deleted file mode 100644 index e8bd874037..0000000000 --- a/pyUltroid/dB/blacklist_chat_db.py +++ /dev/null @@ -1,15 +0,0 @@ -from .. import udB - - -def add_black_chat(chat_id): - chat = udB.get_key("BLACKLIST_CHATS") or [] - if chat_id not in chat: - chat.append(chat_id) - return udB.set_key("BLACKLIST_CHATS", chat) - - -def rem_black_chat(chat_id): - chat = udB.get_key("BLACKLIST_CHATS") or [] - if chat_id in chat: - chat.remove(chat_id) - return udB.set_key("BLACKLIST_CHATS", chat) diff --git a/pyUltroid/dB/blacklist_db.py b/pyUltroid/dB/blacklist_db.py deleted file mode 100644 index a163082122..0000000000 --- a/pyUltroid/dB/blacklist_db.py +++ /dev/null @@ -1,44 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from .. import udB - - -def get_stuff(): - return udB.get_key("BLACKLIST_DB") or {} - - -def add_blacklist(chat, word): - ok = get_stuff() - if ok.get(chat): - for z in word.split(): - if z not in ok[chat]: - ok[chat].append(z) - else: - ok.update({chat: [word]}) - return udB.set_key("BLACKLIST_DB", ok) - - -def rem_blacklist(chat, word): - ok = get_stuff() - if ok.get(chat) and word in ok[chat]: - ok[chat].remove(word) - return udB.set_key("BLACKLIST_DB", ok) - - -def list_blacklist(chat): - ok = get_stuff() - if ok.get(chat): - txt = "".join(f"👉`{z}`\n" for z in ok[chat]) - if txt: - return txt - - -def get_blacklist(chat): - ok = get_stuff() - if ok.get(chat): - return ok[chat] diff --git a/pyUltroid/dB/botchat_db.py b/pyUltroid/dB/botchat_db.py deleted file mode 100644 index e2275d7a70..0000000000 --- a/pyUltroid/dB/botchat_db.py +++ /dev/null @@ -1,41 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -from .. import udB - - -def get_stuff(): - return udB.get_key("BOTCHAT") or {} - - -def add_stuff(msg_id, user_id): - ok = get_stuff() - ok.update({msg_id: user_id}) - return udB.set_key("BOTCHAT", ok) - - -def get_who(msg_id): - ok = get_stuff() - if ok.get(msg_id): - return ok[msg_id] - - -def tag_add(msg, chat, user): - ok = get_stuff() - if not ok.get("TAG"): - ok.update({"TAG": {msg: [chat, user]}}) - else: - ok["TAG"].update({msg: [chat, user]}) - return udB.set_key("BOTCHAT", ok) - - -def who_tag(msg): - ok = get_stuff() - if ok.get("TAG") and ok["TAG"].get(msg): - return ok["TAG"][msg] - return False, False diff --git a/pyUltroid/dB/echo_db.py b/pyUltroid/dB/echo_db.py deleted file mode 100644 index 6b72a49289..0000000000 --- a/pyUltroid/dB/echo_db.py +++ /dev/null @@ -1,43 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from .. import udB - - -def get_stuff(): - return udB.get_key("ECHO") or {} - - -def add_echo(chat, user): - x = get_stuff() - if k := x.get(int(chat)): - if user not in k: - k.append(int(user)) - x.update({int(chat): k}) - else: - x.update({int(chat): [int(user)]}) - return udB.set_key("ECHO", x) - - -def rem_echo(chat, user): - x = get_stuff() - if k := x.get(int(chat)): - if user in k: - k.remove(int(user)) - x.update({int(chat): k}) - return udB.set_key("ECHO", x) - - -def check_echo(chat, user): - x = get_stuff() - if (k := x.get(int(chat))) and int(user) in k: - return True - - -def list_echo(chat): - x = get_stuff() - return x.get(int(chat)) diff --git a/pyUltroid/dB/filestore_db.py b/pyUltroid/dB/filestore_db.py deleted file mode 100644 index 11a19999bd..0000000000 --- a/pyUltroid/dB/filestore_db.py +++ /dev/null @@ -1,35 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from .. import udB - - -def get_stored(): - return udB.get_key("FILE_STORE") or {} - - -def store_msg(hash, msg_id): - all = get_stored() - all.update({hash: msg_id}) - return udB.set_key("FILE_STORE", all) - - -def list_all_stored_msgs(): - all = get_stored() - return list(all.keys()) - - -def get_stored_msg(hash): - all = get_stored() - if all.get(hash): - return all[hash] - - -def del_stored(hash): - all = get_stored() - all.pop(hash) - return udB.set_key("FILE_STORE", all) diff --git a/pyUltroid/dB/filter_db.py b/pyUltroid/dB/filter_db.py deleted file mode 100644 index 957648b76d..0000000000 --- a/pyUltroid/dB/filter_db.py +++ /dev/null @@ -1,47 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from .. import udB - - -def get_stuff(): - return udB.get_key("FILTERS") or {} - - -def add_filter(chat, word, msg, media, button): - ok = get_stuff() - if ok.get(chat): - ok[chat].update({word: {"msg": msg, "media": media, "button": button}}) - else: - ok.update({chat: {word: {"msg": msg, "media": media, "button": button}}}) - udB.set_key("FILTERS", ok) - - -def rem_filter(chat, word): - ok = get_stuff() - if ok.get(chat) and ok[chat].get(word): - ok[chat].pop(word) - udB.set_key("FILTERS", ok) - - -def rem_all_filter(chat): - ok = get_stuff() - if ok.get(chat): - ok.pop(chat) - udB.set_key("FILTERS", ok) - - -def get_filter(chat): - ok = get_stuff() - if ok.get(chat): - return ok[chat] - - -def list_filter(chat): - ok = get_stuff() - if ok.get(chat): - return "".join(f"👉 `{z}`\n" for z in ok[chat]) diff --git a/pyUltroid/dB/forcesub_db.py b/pyUltroid/dB/forcesub_db.py deleted file mode 100644 index 69c5466f9d..0000000000 --- a/pyUltroid/dB/forcesub_db.py +++ /dev/null @@ -1,35 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -from .. import udB - - -def get_chats(): - return udB.get_key("FORCESUB") or {} - - -def add_forcesub(chat_id, chattojoin): - omk = get_chats() - omk.update({chat_id: chattojoin}) - return udB.set_key("FORCESUB", omk) - - -def get_forcesetting(chat_id): - omk = get_chats() - if chat_id in omk.keys(): - return omk[chat_id] - - -def rem_forcesub(chat_id): - omk = get_chats() - if chat_id in omk.keys(): - try: - del omk[chat_id] - return udB.set_key("FORCESUB", omk) - except KeyError: - return False diff --git a/pyUltroid/dB/gban_mute_db.py b/pyUltroid/dB/gban_mute_db.py deleted file mode 100644 index 7f1c3ffafc..0000000000 --- a/pyUltroid/dB/gban_mute_db.py +++ /dev/null @@ -1,52 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from .. import udB - - -def list_gbanned(): - return udB.get_key("GBAN") or {} - - -def gban(user, reason): - ok = list_gbanned() - ok.update({int(user): reason or "No Reason. "}) - return udB.set_key("GBAN", ok) - - -def ungban(user): - ok = list_gbanned() - if ok.get(int(user)): - del ok[int(user)] - return udB.set_key("GBAN", ok) - - -def is_gbanned(user): - ok = list_gbanned() - if ok.get(int(user)): - return ok[int(user)] - - -def gmute(user): - ok = list_gmuted() - ok.append(int(user)) - return udB.set_key("GMUTE", ok) - - -def ungmute(user): - ok = list_gmuted() - if user in ok: - ok.remove(int(user)) - return udB.set_key("GMUTE", ok) - - -def is_gmuted(user): - return int(user) in list_gmuted() - - -def list_gmuted(): - return udB.get_key("GMUTE") or [] diff --git a/pyUltroid/dB/greetings_db.py b/pyUltroid/dB/greetings_db.py deleted file mode 100644 index dc14909d06..0000000000 --- a/pyUltroid/dB/greetings_db.py +++ /dev/null @@ -1,66 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from .. import udB - - -def get_stuff(key=None): - return udB.get_key(key) or {} - - -def add_welcome(chat, msg, media, button): - ok = get_stuff("WELCOME") - ok.update({chat: {"welcome": msg, "media": media, "button": button}}) - return udB.set_key("WELCOME", ok) - - -def get_welcome(chat): - ok = get_stuff("WELCOME") - return ok.get(chat) - - -def delete_welcome(chat): - ok = get_stuff("WELCOME") - if ok.get(chat): - ok.pop(chat) - return udB.set_key("WELCOME", ok) - - -def add_goodbye(chat, msg, media, button): - ok = get_stuff("GOODBYE") - ok.update({chat: {"goodbye": msg, "media": media, "button": button}}) - return udB.set_key("GOODBYE", ok) - - -def get_goodbye(chat): - ok = get_stuff("GOODBYE") - return ok.get(chat) - - -def delete_goodbye(chat): - ok = get_stuff("GOODBYE") - if ok.get(chat): - ok.pop(chat) - return udB.set_key("GOODBYE", ok) - - -def add_thanks(chat): - x = get_stuff("THANK_MEMBERS") - x.update({chat: True}) - return udB.set_key("THANK_MEMBERS", x) - - -def remove_thanks(chat): - x = get_stuff("THANK_MEMBERS") - if x.get(chat): - x.pop(chat) - return udB.set_key("THANK_MEMBERS", x) - - -def must_thank(chat): - x = get_stuff("THANK_MEMBERS") - return x.get(chat) diff --git a/pyUltroid/dB/mute_db.py b/pyUltroid/dB/mute_db.py deleted file mode 100644 index 564a0e5b50..0000000000 --- a/pyUltroid/dB/mute_db.py +++ /dev/null @@ -1,34 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from .. import udB - - -def get_muted(): - return udB.get_key("MUTE") or {} - - -def mute(chat, id): - ok = get_muted() - if ok.get(chat): - if id not in ok[chat]: - ok[chat].append(id) - else: - ok.update({chat: [id]}) - return udB.set_key("MUTE", ok) - - -def unmute(chat, id): - ok = get_muted() - if ok.get(chat) and id in ok[chat]: - ok[chat].remove(id) - return udB.set_key("MUTE", ok) - - -def is_muted(chat, id): - ok = get_muted() - return bool(ok.get(chat) and id in ok[chat]) diff --git a/pyUltroid/dB/notes_db.py b/pyUltroid/dB/notes_db.py deleted file mode 100644 index 02b900b929..0000000000 --- a/pyUltroid/dB/notes_db.py +++ /dev/null @@ -1,47 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from .. import udB - - -def get_stuff(): - return udB.get_key("NOTE") or {} - - -def add_note(chat, word, msg, media, button): - ok = get_stuff() - if ok.get(int(chat)): - ok[int(chat)].update({word: {"msg": msg, "media": media, "button": button}}) - else: - ok.update({int(chat): {word: {"msg": msg, "media": media, "button": button}}}) - udB.set_key("NOTE", ok) - - -def rem_note(chat, word): - ok = get_stuff() - if ok.get(int(chat)) and ok[int(chat)].get(word): - ok[int(chat)].pop(word) - return udB.set_key("NOTE", ok) - - -def rem_all_note(chat): - ok = get_stuff() - if ok.get(int(chat)): - ok.pop(int(chat)) - return udB.set_key("NOTE", ok) - - -def get_notes(chat, word): - ok = get_stuff() - if ok.get(int(chat)) and ok[int(chat)].get(word): - return ok[int(chat)][word] - - -def list_note(chat): - ok = get_stuff() - if ok.get(int(chat)): - return "".join(f"👉 #{z}\n" for z in ok[chat]) diff --git a/pyUltroid/dB/nsfw_db.py b/pyUltroid/dB/nsfw_db.py deleted file mode 100644 index 8f9749c139..0000000000 --- a/pyUltroid/dB/nsfw_db.py +++ /dev/null @@ -1,51 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -from .. import udB - - -def get_stuff(key="NSFW"): - return udB.get_key(key) or {} - - -def nsfw_chat(chat, action): - x = get_stuff() - x.update({chat: action}) - return udB.set_key("NSFW", x) - - -def rem_nsfw(chat): - x = get_stuff() - if x.get(chat): - x.pop(chat) - return udB.set_key("NSFW", x) - - -def is_nsfw(chat): - x = get_stuff() - if x.get(chat): - return x[chat] - - -def profan_chat(chat, action): - x = get_stuff("PROFANITY") - x.update({chat: action}) - return udB.set_key("PROFANITY", x) - - -def rem_profan(chat): - x = get_stuff("PROFANITY") - if x.get(chat): - x.pop(chat) - return udB.set_key("PROFANITY", x) - - -def is_profan(chat): - x = get_stuff("PROFANITY") - if x.get(chat): - return x[chat] diff --git a/pyUltroid/dB/snips_db.py b/pyUltroid/dB/snips_db.py deleted file mode 100644 index 244baf6358..0000000000 --- a/pyUltroid/dB/snips_db.py +++ /dev/null @@ -1,36 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from .. import udB - - -def get_all_snips(): - return udB.get_key("SNIP") or {} - - -def add_snip(word, msg, media, button): - ok = get_all_snips() - ok.update({word: {"msg": msg, "media": media, "button": button}}) - udB.set_key("SNIP", ok) - - -def rem_snip(word): - ok = get_all_snips() - if ok.get(word): - ok.pop(word) - udB.set_key("SNIP", ok) - - -def get_snips(word): - ok = get_all_snips() - if ok.get(word): - return ok[word] - return False - - -def list_snip(): - return "".join(f"👉 ${z}\n" for z in get_all_snips()) diff --git a/pyUltroid/dB/vc_sudos.py b/pyUltroid/dB/vc_sudos.py deleted file mode 100644 index 5e85656929..0000000000 --- a/pyUltroid/dB/vc_sudos.py +++ /dev/null @@ -1,29 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from .. import udB - - -def get_vcsudos(): - return udB.get_key("VC_SUDOS") or [] - - -def is_vcsudo(id): - return id in get_vcsudos() - - -def add_vcsudo(id): - sudos = get_vcsudos() - sudos.append(id) - return udB.set_key("VC_SUDOS", sudos) - - -def del_vcsudo(id): - if is_vcsudo(id): - sudos = get_vcsudos() - sudos.remove(id) - return udB.set_key("VC_SUDOS", sudos) diff --git a/pyUltroid/dB/warn_db.py b/pyUltroid/dB/warn_db.py deleted file mode 100644 index 0d49e79b41..0000000000 --- a/pyUltroid/dB/warn_db.py +++ /dev/null @@ -1,39 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -from .. import udB - - -def get_stuff(): - return udB.get_key("WARNS") or {} - - -def add_warn(chat, user, count, reason): - x = get_stuff() - try: - x[chat].update({user: [count, reason]}) - except BaseException: - x.update({chat: {user: [count, reason]}}) - return udB.set_key("WARNS", x) - - -def warns(chat, user): - x = get_stuff() - try: - count, reason = x[chat][user][0], x[chat][user][1] - return count, reason - except BaseException: - return 0, None - - -def reset_warn(chat, user): - x = get_stuff() - try: - x[chat].pop(user) - return udB.set_key("WARNS", x) - except BaseException: - return diff --git a/pyUltroid/exceptions.py b/pyUltroid/exceptions.py deleted file mode 100644 index c53ea7d3c6..0000000000 --- a/pyUltroid/exceptions.py +++ /dev/null @@ -1,22 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -""" -Exceptions which can be raised by py-Ultroid Itself. -""" - - -class pyUltroidError(Exception): - ... - - -class DependencyMissingError(ImportError): - ... - - -class RunningAsFunctionLibError(pyUltroidError): - ... diff --git a/pyUltroid/fns/gDrive.py b/pyUltroid/fns/gDrive.py deleted file mode 100644 index e97d18028a..0000000000 --- a/pyUltroid/fns/gDrive.py +++ /dev/null @@ -1,238 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import time -from io import FileIO -from logging import WARNING -from mimetypes import guess_type - -from apiclient.http import LOGGER, MediaFileUpload, MediaIoBaseDownload -from googleapiclient.discovery import build, logger -from httplib2 import Http -from oauth2client.client import OOB_CALLBACK_URN, OAuth2WebServerFlow -from oauth2client.client import logger as _logger -from oauth2client.file import Storage - -from .. import udB -from .helper import humanbytes, time_formatter - -for log in [LOGGER, logger, _logger]: - log.setLevel(WARNING) - - -class GDriveManager: - def __init__(self): - self._flow = {} - self.gdrive_creds = { - "oauth_scope": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - ], - "dir_mimetype": "application/vnd.google-apps.folder", - "redirect_uri": OOB_CALLBACK_URN, - } - self.auth_token = udB.get_key("GDRIVE_AUTH_TOKEN") - self.folder_id = udB.get_key("GDRIVE_FOLDER_ID") - self.token_file = "resources/auth/gdrive_creds.json" - - @staticmethod - def _create_download_link(fileId: str): - return f"https://drive.google.com/uc?id={fileId}&export=download" - - @staticmethod - def _create_folder_link(folderId: str): - return f"https://drive.google.com/folderview?id={folderId}" - - def _create_token_file(self, code: str = None): - if code and self._flow: - _auth_flow = self._flow["_"] - credentials = _auth_flow.step2_exchange(code) - Storage(self.token_file).put(credentials) - return udB.set_key("GDRIVE_AUTH_TOKEN", str(open(self.token_file).read())) - try: - _auth_flow = OAuth2WebServerFlow( - udB.get_key("GDRIVE_CLIENT_ID") - or "458306970678-jhfbv6o5sf1ar63o1ohp4c0grblp8qba.apps.googleusercontent.com", - udB.get_key("GDRIVE_CLIENT_SECRET") - or "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", - self.gdrive_creds["oauth_scope"], - redirect_uri=self.gdrive_creds["redirect_uri"], - ) - self._flow["_"] = _auth_flow - except KeyError: - return "Fill GDRIVE client credentials" - return _auth_flow.step1_get_authorize_url() - - @property - def _http(self): - storage = Storage(self.token_file) - creds = storage.get() - http = Http() - http.redirect_codes = http.redirect_codes - {308} - creds.refresh(http) - return creds.authorize(http) - - @property - def _build(self): - return build("drive", "v2", http=self._http, cache_discovery=False) - - def _set_permissions(self, fileId: str): - _permissions = { - "role": "reader", - "type": "anyone", - "value": None, - "withLink": True, - } - self._build.permissions().insert( - fileId=fileId, body=_permissions, supportsAllDrives=True - ).execute(http=self._http) - - async def _upload_file( - self, event, path: str, filename: str = None, folder_id: str = None - ): - last_txt = "" - if not filename: - filename = path.split("/")[-1] - mime_type = guess_type(path)[0] or "application/octet-stream" - media_body = MediaFileUpload(path, mimetype=mime_type, resumable=True) - body = { - "title": filename, - "description": "Uploaded using Ultroid Userbot", - "mimeType": mime_type, - } - if folder_id: - body["parents"] = [{"id": folder_id}] - elif self.folder_id: - body["parents"] = [{"id": self.folder_id}] - upload = self._build.files().insert( - body=body, media_body=media_body, supportsAllDrives=True - ) - start = time.time() - _status = None - while not _status: - _progress, _status = upload.next_chunk(num_retries=3) - if _progress: - diff = time.time() - start - completed = _progress.resumable_progress - total_size = _progress.total_size - percentage = round((completed / total_size) * 100, 2) - speed = round(completed / diff, 2) - eta = round((total_size - completed) / speed, 2) * 1000 - crnt_txt = ( - f"`Uploading {filename} to GDrive...\n\n" - + f"Status: {humanbytes(completed)}/{humanbytes(total_size)} »» {percentage}%\n" - + f"Speed: {humanbytes(speed)}/s\n" - + f"ETA: {time_formatter(eta)}`" - ) - if round((diff % 10.00) == 0) or last_txt != crnt_txt: - await event.edit(crnt_txt) - last_txt = crnt_txt - fileId = _status.get("id") - try: - self._set_permissions(fileId=fileId) - except BaseException: - pass - _url = self._build.files().get(fileId=fileId, supportsAllDrives=True).execute() - return _url.get("webContentLink") - - async def _download_file(self, event, fileId: str, filename: str = None): - last_txt = "" - if fileId.startswith("http"): - if "=download" in fileId: - fileId = fileId.split("=")[1][:-7] - elif "/view" in fileId: - fileId = fileId.split("/")[::-1][1] - try: - if not filename: - filename = ( - self._build.files() - .get(fileId=fileId, supportsAllDrives=True) - .execute()["title"] - ) - downloader = self._build.files().get_media( - fileId=fileId, supportsAllDrives=True - ) - except Exception as ex: - return False, str(ex) - with FileIO(filename, "wb") as file: - start = time.time() - download = MediaIoBaseDownload(file, downloader) - _status = None - while not _status: - _progress, _status = download.next_chunk(num_retries=3) - if _progress: - diff = time.time() - start - completed = _progress.resumable_progress - total_size = _progress.total_size - percentage = round((completed / total_size) * 100, 2) - speed = round(completed / diff, 2) - eta = round((total_size - completed) / speed, 2) * 1000 - crnt_txt = ( - f"`Downloading {filename} from GDrive...\n\n" - + f"Status: {humanbytes(completed)}/{humanbytes(total_size)} »» {percentage}%\n" - + f"Speed: {humanbytes(speed)}/s\n" - + f"ETA: {time_formatter(eta)}`" - ) - if round((diff % 10.00) == 0) or last_txt != crnt_txt: - await event.edit(crnt_txt) - last_txt = crnt_txt - return True, filename - - @property - def _list_files(self): - _items = ( - self._build.files() - .list( - supportsTeamDrives=True, - includeTeamDriveItems=True, - spaces="drive", - fields="nextPageToken, items(id, title, mimeType)", - pageToken=None, - ) - .execute() - ) - _files = {} - for files in _items["items"]: - if files["mimeType"] == self.gdrive_creds["dir_mimetype"]: - _files[self._create_folder_link(files["id"])] = files["title"] - else: - _files[self._create_download_link(files["id"])] = files["title"] - return _files - - def create_directory(self, directory): - body = { - "title": directory, - "mimeType": self.gdrive_creds["dir_mimetype"], - } - if self.folder_id: - body["parents"] = [{"id": self.folder_id}] - file = self._build.files().insert(body=body, supportsAllDrives=True).execute() - fileId = file.get("id") - self._set_permissions(fileId=fileId) - return fileId - - def search(self, title): - query = f"title contains '{title}'" - if self.folder_id: - query = f"'{self.folder_id}' in parents and (title contains '{title}')" - _items = ( - self._build.files() - .list( - supportsTeamDrives=True, - includeTeamDriveItems=True, - q=query, - spaces="drive", - fields="nextPageToken, items(id, title, mimeType)", - pageToken=None, - ) - .execute() - ) - _files = {} - for files in _items["items"]: - _files[self._create_download_link(files["id"])] = files["title"] - return _files diff --git a/pyUltroid/fns/helper.py b/pyUltroid/fns/helper.py deleted file mode 100644 index d9396d1413..0000000000 --- a/pyUltroid/fns/helper.py +++ /dev/null @@ -1,619 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import asyncio -import math -import os -import re -import sys -import time -from traceback import format_exc -from urllib.parse import unquote -from urllib.request import urlretrieve - -from .. import run_as_module - -if run_as_module: - from ..configs import Var - - -try: - from aiohttp import ClientSession as aiohttp_client -except ImportError: - aiohttp_client = None - try: - import requests - except ImportError: - requests = None - -try: - import heroku3 -except ImportError: - heroku3 = None - -try: - from git import Repo - from git.exc import GitCommandError, InvalidGitRepositoryError, NoSuchPathError -except ImportError: - Repo = None - - -import asyncio -import multiprocessing -from concurrent.futures import ThreadPoolExecutor -from functools import partial, wraps - -from telethon.helpers import _maybe_await -from telethon.tl import types -from telethon.utils import get_display_name - -from .._misc import CMD_HELP -from .._misc._wrappers import eod, eor -from ..exceptions import DependencyMissingError -from . import * - -if run_as_module: - from ..dB._core import ADDONS, HELP, LIST, LOADED - -from ..version import ultroid_version -from .FastTelethon import download_file as downloadable -from .FastTelethon import upload_file as uploadable - - -def run_async(function): - @wraps(function) - async def wrapper(*args, **kwargs): - return await asyncio.get_event_loop().run_in_executor( - ThreadPoolExecutor(max_workers=multiprocessing.cpu_count() * 5), - partial(function, *args, **kwargs), - ) - - return wrapper - - -# ~~~~~~~~~~~~~~~~~~~~ small funcs ~~~~~~~~~~~~~~~~~~~~ # - - -def make_mention(user, custom=None): - if user.username: - return f"@{user.username}" - return inline_mention(user, custom=custom) - - -def inline_mention(user, custom=None, html=False): - mention_text = get_display_name(user) or "Deleted Account" if not custom else custom - if isinstance(user, types.User): - if html: - return f"{mention_text}" - return f"[{mention_text}](tg://user?id={user.id})" - if isinstance(user, types.Channel) and user.username: - if html: - return f"{mention_text}" - return f"[{mention_text}](https://t.me/{user.username})" - return mention_text - - -# ----------------- Load \\ Unloader ---------------- # - - -def un_plug(shortname): - from .. import asst, ultroid_bot - - try: - all_func = LOADED[shortname] - for client in [ultroid_bot, asst]: - for x, _ in client.list_event_handlers(): - if x in all_func: - client.remove_event_handler(x) - del LOADED[shortname] - del LIST[shortname] - ADDONS.remove(shortname) - except (ValueError, KeyError): - name = f"addons.{shortname}" - for client in [ultroid_bot, asst]: - for i in reversed(range(len(client._event_builders))): - ev, cb = client._event_builders[i] - if cb.__module__ == name: - del client._event_builders[i] - try: - del LOADED[shortname] - del LIST[shortname] - ADDONS.remove(shortname) - except KeyError: - pass - - -if run_as_module: - - async def safeinstall(event): - from .. import HNDLR - from ..startup.utils import load_addons - - if not event.reply_to: - return await eod( - event, f"Please use `{HNDLR}install` as reply to a .py file." - ) - ok = await eor(event, "`Installing...`") - reply = await event.get_reply_message() - if not ( - reply.media - and hasattr(reply.media, "document") - and reply.file.name - and reply.file.name.endswith(".py") - ): - return await eod(ok, "`Please reply to any python plugin`") - plug = reply.file.name.replace(".py", "") - if plug in list(LOADED): - return await eod(ok, f"Plugin `{plug}` is already installed.") - sm = reply.file.name.replace("_", "-").replace("|", "-") - dl = await reply.download_media(f"addons/{sm}") - if event.text[9:] != "f": - read = open(dl).read() - for dan in KEEP_SAFE().All: - if re.search(dan, read): - os.remove(dl) - return await ok.edit( - f"**Installation Aborted.**\n**Reason:** Occurance of `{dan}` in `{reply.file.name}`.\n\nIf you trust the provider and/or know what you're doing, use `{HNDLR}install f` to force install.", - ) - try: - load_addons(dl) # dl.split("/")[-1].replace(".py", "")) - except BaseException: - os.remove(dl) - return await eor(ok, f"**ERROR**\n\n`{format_exc()}`", time=30) - plug = sm.replace(".py", "") - if plug in HELP: - output = "**Plugin** - `{}`\n".format(plug) - for i in HELP[plug]: - output += i - output += "\n© @TeamUltroid" - await eod(ok, f"✓ `Ultroid - Installed`: `{plug}` ✓\n\n{output}") - elif plug in CMD_HELP: - output = f"Plugin Name-{plug}\n\n✘ Commands Available-\n\n" - output += str(CMD_HELP[plug]) - await eod(ok, f"✓ `Ultroid - Installed`: `{plug}` ✓\n\n{output}") - else: - try: - x = f"Plugin Name-{plug}\n\n✘ Commands Available-\n\n" - for d in LIST[plug]: - x += HNDLR + d + "\n" - await eod(ok, f"✓ `Ultroid - Installed`: `{plug}` ✓\n\n`{x}`") - except BaseException: - await eod(ok, f"✓ `Ultroid - Installed`: `{plug}` ✓") - - async def heroku_logs(event): - """ - post heroku logs - """ - from .. import LOGS - - xx = await eor(event, "`Processing...`") - if not (Var.HEROKU_API and Var.HEROKU_APP_NAME): - return await xx.edit( - "Please set `HEROKU_APP_NAME` and `HEROKU_API` in vars." - ) - try: - app = (heroku3.from_key(Var.HEROKU_API)).app(Var.HEROKU_APP_NAME) - except BaseException as se: - LOGS.info(se) - return await xx.edit( - "`HEROKU_API` and `HEROKU_APP_NAME` is wrong! Kindly re-check in config vars." - ) - await xx.edit("`Downloading Logs...`") - ok = app.get_log() - with open("ultroid-heroku.log", "w") as log: - log.write(ok) - await event.client.send_file( - event.chat_id, - file="ultroid-heroku.log", - thumb=ULTConfig.thumb, - caption="**Ultroid Heroku Logs.**", - ) - - os.remove("ultroid-heroku.log") - await xx.delete() - - async def def_logs(ult, file): - await ult.respond( - "**Ultroid Logs.**", - file=file, - thumb=ULTConfig.thumb, - ) - - async def updateme_requirements(): - """Update requirements..""" - await bash( - f"{sys.executable} -m pip install --no-cache-dir -r requirements.txt" - ) - - @run_async - def gen_chlog(repo, diff): - """Generate Changelogs...""" - UPSTREAM_REPO_URL = ( - Repo().remotes[0].config_reader.get("url").replace(".git", "") - ) - ac_br = repo.active_branch.name - ch_log = tldr_log = "" - ch = f"Ultroid {ultroid_version} updates for [{ac_br}]:" - ch_tl = f"Ultroid {ultroid_version} updates for {ac_br}:" - d_form = "%d/%m/%y || %H:%M" - for c in repo.iter_commits(diff): - ch_log += f"\n\n💬 {c.count()} 🗓 [{c.committed_datetime.strftime(d_form)}]\n[{c.summary}] 👨‍💻 {c.author}" - tldr_log += f"\n\n💬 {c.count()} 🗓 [{c.committed_datetime.strftime(d_form)}]\n[{c.summary}] 👨‍💻 {c.author}" - if ch_log: - return str(ch + ch_log), str(ch_tl + tldr_log) - return ch_log, tldr_log - - -# --------------------------------------------------------------------- # - - -async def bash(cmd, run_code=0): - """ - run any command in subprocess and get output or error.""" - process = await asyncio.create_subprocess_shell( - cmd, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - ) - stdout, stderr = await process.communicate() - err = stderr.decode().strip() or None - out = stdout.decode().strip() - if not run_code and err: - if match := re.match("\/bin\/sh: (.*): ?(\w+): not found", err): - return out, f"{match.group(2).upper()}_NOT_FOUND" - return out, err - - -# ---------------------------UPDATER-------------------------------- # -# Will add in class - - -async def updater(): - from .. import LOGS - - try: - off_repo = Repo().remotes[0].config_reader.get("url").replace(".git", "") - except Exception as er: - LOGS.exception(er) - return - try: - repo = Repo() - except NoSuchPathError as error: - LOGS.info(f"`directory {error} is not found`") - Repo().__del__() - return - except GitCommandError as error: - LOGS.info(f"`Early failure! {error}`") - Repo().__del__() - return - except InvalidGitRepositoryError: - repo = Repo.init() - origin = repo.create_remote("upstream", off_repo) - origin.fetch() - repo.create_head("main", origin.refs.main) - repo.heads.main.set_tracking_branch(origin.refs.main) - repo.heads.main.checkout(True) - ac_br = repo.active_branch.name - repo.create_remote("upstream", off_repo) if "upstream" not in repo.remotes else None - ups_rem = repo.remote("upstream") - ups_rem.fetch(ac_br) - changelog, tl_chnglog = await gen_chlog(repo, f"HEAD..upstream/{ac_br}") - return bool(changelog) - - -# ----------------Fast Upload/Download---------------- -# @1danish_00 @new-dev0 @buddhhu - - -async def uploader(file, name, taime, event, msg): - with open(file, "rb") as f: - result = await uploadable( - client=event.client, - file=f, - filename=name, - progress_callback=lambda d, t: asyncio.get_event_loop().create_task( - progress( - d, - t, - event, - taime, - msg, - ), - ), - ) - return result - - -async def downloader(filename, file, event, taime, msg): - with open(filename, "wb") as fk: - result = await downloadable( - client=event.client, - location=file, - out=fk, - progress_callback=lambda d, t: asyncio.get_event_loop().create_task( - progress( - d, - t, - event, - taime, - msg, - ), - ), - ) - return result - - -# ~~~~~~~~~~~~~~~Async Searcher~~~~~~~~~~~~~~~ -# @buddhhu - - -async def async_searcher( - url: str, - post: bool = False, - head: bool = False, - headers: dict = None, - evaluate=None, - object: bool = False, - re_json: bool = False, - re_content: bool = False, - *args, - **kwargs, -): - if aiohttp_client: - async with aiohttp_client(headers=headers) as client: - method = client.head if head else (client.post if post else client.get) - data = await method(url, *args, **kwargs) - if evaluate: - return await evaluate(data) - if re_json: - return await data.json() - if re_content: - return await data.read() - if head or object: - return data - return await data.text() - # elif requests: - # method = requests.head if head else (requests.post if post else requests.get) - # data = method(url, headers=headers, *args, **kwargs) - # if re_json: - # return data.json() - # if re_content: - # return data.content - # if head or object: - # return data - # return data.text - else: - raise DependencyMissingError("install 'aiohttp' to use this.") - - -# ~~~~~~~~~~~~~~~~~~~~DDL Downloader~~~~~~~~~~~~~~~~~~~~ -# @buddhhu @new-dev0 - - -async def download_file(link, name, validate=False): - """for files, without progress callback with aiohttp""" - - async def _download(content): - if validate and "application/json" in content.headers.get("Content-Type"): - return None, await content.json() - with open(name, "wb") as file: - file.write(await content.read()) - return name, "" - - return await async_searcher(link, evaluate=_download) - - -async def fast_download(download_url, filename=None, progress_callback=None): - if not aiohttp_client: - return await download_file(download_url, filename)[0], None - async with aiohttp_client() as session: - async with session.get(download_url, timeout=None) as response: - if not filename: - filename = unquote(download_url.rpartition("/")[-1]) - total_size = int(response.headers.get("content-length", 0)) or None - downloaded_size = 0 - start_time = time.time() - with open(filename, "wb") as f: - async for chunk in response.content.iter_chunked(1024): - if chunk: - f.write(chunk) - downloaded_size += len(chunk) - if progress_callback and total_size: - await _maybe_await( - progress_callback(downloaded_size, total_size) - ) - return filename, time.time() - start_time - - -# --------------------------Media Funcs-------------------------------- # - - -def mediainfo(media): - xx = str((str(media)).split("(", maxsplit=1)[0]) - m = "" - if xx == "MessageMediaDocument": - mim = media.document.mime_type - if mim == "application/x-tgsticker": - m = "sticker animated" - elif "image" in mim: - if mim == "image/webp": - m = "sticker" - elif mim == "image/gif": - m = "gif as doc" - else: - m = "pic as doc" - elif "video" in mim: - if "DocumentAttributeAnimated" in str(media): - m = "gif" - elif "DocumentAttributeVideo" in str(media): - i = str(media.document.attributes[0]) - if "supports_streaming=True" in i: - m = "video" - m = "video as doc" - else: - m = "video" - elif "audio" in mim: - m = "audio" - else: - m = "document" - elif xx == "MessageMediaPhoto": - m = "pic" - elif xx == "MessageMediaWebPage": - m = "web" - return m - - -# ------------------Some Small Funcs---------------- - - -def time_formatter(milliseconds): - minutes, seconds = divmod(int(milliseconds / 1000), 60) - hours, minutes = divmod(minutes, 60) - days, hours = divmod(hours, 24) - weeks, days = divmod(days, 7) - tmp = ( - ((str(weeks) + "w:") if weeks else "") - + ((str(days) + "d:") if days else "") - + ((str(hours) + "h:") if hours else "") - + ((str(minutes) + "m:") if minutes else "") - + ((str(seconds) + "s") if seconds else "") - ) - if not tmp: - return "0s" - - if tmp.endswith(":"): - return tmp[:-1] - return tmp - - -def humanbytes(size): - if not size: - return "0 B" - for unit in ["", "K", "M", "G", "T"]: - if size < 1024: - break - size /= 1024 - if isinstance(size, int): - size = f"{size}{unit}B" - elif isinstance(size, float): - size = f"{size:.2f}{unit}B" - return size - - -def numerize(number): - if not number: - return None - unit = "" - for unit in ["", "K", "M", "B", "T"]: - if number < 1000: - break - number /= 1000 - if isinstance(number, int): - number = f"{number}{unit}" - elif isinstance(number, float): - number = f"{number:.2f}{unit}" - return number - - -No_Flood = {} - - -async def progress(current, total, event, start, type_of_ps, file_name=None): - now = time.time() - if No_Flood.get(event.chat_id): - if No_Flood[event.chat_id].get(event.id): - if (now - No_Flood[event.chat_id][event.id]) < 1.1: - return - else: - No_Flood[event.chat_id].update({event.id: now}) - else: - No_Flood.update({event.chat_id: {event.id: now}}) - diff = time.time() - start - if round(diff % 10.00) == 0 or current == total: - percentage = current * 100 / total - speed = current / diff - time_to_completion = round((total - current) / speed) * 1000 - progress_str = "`[{0}{1}] {2}%`\n\n".format( - "".join("●" for i in range(math.floor(percentage / 5))), - "".join("" for i in range(20 - math.floor(percentage / 5))), - round(percentage, 2), - ) - - tmp = ( - progress_str - + "`{0} of {1}`\n\n`✦ Speed: {2}/s`\n\n`✦ ETA: {3}`\n\n".format( - humanbytes(current), - humanbytes(total), - humanbytes(speed), - time_formatter(time_to_completion), - ) - ) - if file_name: - await event.edit( - "`✦ {}`\n\n`File Name: {}`\n\n{}".format(type_of_ps, file_name, tmp) - ) - else: - await event.edit("`✦ {}`\n\n{}".format(type_of_ps, tmp)) - - -# ------------------System\\Heroku stuff---------------- -# @xditya @sppidy @techierror - - -async def restart(ult=None): - if Var.HEROKU_APP_NAME and Var.HEROKU_API: - try: - Heroku = heroku3.from_key(Var.HEROKU_API) - app = Heroku.apps()[Var.HEROKU_APP_NAME] - if ult: - await ult.edit("`Restarting your app, please wait for a minute!`") - app.restart() - except BaseException as er: - if ult: - return await eor( - ult, - "`HEROKU_API` or `HEROKU_APP_NAME` is wrong! Kindly re-check in config vars.", - ) - LOGS.exception(er) - else: - if len(sys.argv) == 1: - os.execl(sys.executable, sys.executable, "-m", "pyUltroid") - else: - os.execl( - sys.executable, - sys.executable, - "-m", - "pyUltroid", - sys.argv[1], - sys.argv[2], - sys.argv[3], - sys.argv[4], - sys.argv[5], - sys.argv[6], - ) - - -async def shutdown(ult): - from .. import HOSTED_ON, LOGS - - ult = await eor(ult, "Shutting Down") - if HOSTED_ON == "heroku": - if not (Var.HEROKU_APP_NAME and Var.HEROKU_API): - return await ult.edit("Please Fill `HEROKU_APP_NAME` and `HEROKU_API`") - dynotype = os.getenv("DYNO").split(".")[0] - try: - Heroku = heroku3.from_key(Var.HEROKU_API) - app = Heroku.apps()[Var.HEROKU_APP_NAME] - await ult.edit("`Shutting Down your app, please wait for a minute!`") - app.process_formation()[dynotype].scale(0) - except BaseException as e: - LOGS.exception(e) - return await ult.edit( - "`HEROKU_API` and `HEROKU_APP_NAME` is wrong! Kindly re-check in config vars." - ) - else: - sys.exit() diff --git a/pyUltroid/fns/info.py b/pyUltroid/fns/info.py deleted file mode 100644 index f57b8b0bbd..0000000000 --- a/pyUltroid/fns/info.py +++ /dev/null @@ -1,182 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - - -# -----------------Random Stuff-------------- - -import math - -from telethon.tl import functions, types - -from .. import LOGS - -# ----------- -# @buddhhu - - -async def get_uinfo(e): - user, data = None, None - reply = await e.get_reply_message() - if reply: - user = await e.client.get_entity(reply.sender_id) - data = e.pattern_match.group(1) - else: - ok = e.pattern_match.group(1).split(maxsplit=1) - if len(ok) > 1: - data = ok[1] - try: - user = await e.client.get_entity(await e.client.parse_id(ok[0])) - except IndexError: - pass - except ValueError as er: - await e.eor(str(er)) - return None, None - return user, data - - -# Random stuffs dk who added - - -async def get_chat_info(chat, event): - if isinstance(chat, types.Channel): - chat_info = await event.client(functions.channels.GetFullChannelRequest(chat)) - elif isinstance(chat, types.Chat): - chat_info = await event.client(functions.messages.GetFullChatRequest(chat)) - else: - return await event.eor("`Use this for Group/Channel.`") - full = chat_info.full_chat - chat_photo = full.chat_photo - broadcast = getattr(chat, "broadcast", False) - chat_type = "Channel" if broadcast else "Group" - chat_title = chat.title - try: - msg_info = await event.client( - functions.messages.GetHistoryRequest( - peer=chat.id, - offset_id=0, - offset_date=None, - add_offset=-0, - limit=0, - max_id=0, - min_id=0, - hash=0, - ) - ) - except Exception as er: - msg_info = None - if not event.client._bot: - LOGS.exception(er) - first_msg_valid = bool( - msg_info and msg_info.messages and msg_info.messages[0].id == 1 - ) - - creator_valid = bool(first_msg_valid and msg_info.users) - creator_id = msg_info.users[0].id if creator_valid else None - creator_firstname = ( - msg_info.users[0].first_name - if creator_valid and msg_info.users[0].first_name is not None - else "Deleted Account" - ) - creator_username = ( - msg_info.users[0].username - if creator_valid and msg_info.users[0].username is not None - else None - ) - created = msg_info.messages[0].date if first_msg_valid else None - if not isinstance(chat.photo, types.ChatPhotoEmpty): - dc_id = chat.photo.dc_id - else: - dc_id = "Null" - - restricted_users = getattr(full, "banned_count", None) - members = getattr(full, "participants_count", chat.participants_count) - admins = getattr(full, "admins_count", None) - banned_users = getattr(full, "kicked_count", None) - members_online = getattr(full, "online_count", 0) - group_stickers = ( - full.stickerset.title if getattr(full, "stickerset", None) else None - ) - messages_viewable = msg_info.count if msg_info else None - messages_sent = getattr(full, "read_inbox_max_id", None) - messages_sent_alt = getattr(full, "read_outbox_max_id", None) - exp_count = getattr(full, "pts", None) - supergroup = "Yes" if getattr(chat, "megagroup", None) else "No" - creator_username = "@{}".format(creator_username) if creator_username else None - - if admins is None: - try: - participants_admins = await event.client( - functions.channels.GetParticipantsRequest( - channel=chat.id, - filter=types.ChannelParticipantsAdmins(), - offset=0, - limit=0, - hash=0, - ) - ) - admins = participants_admins.count if participants_admins else None - except Exception as e: - LOGS.info(f"Exception: {e}") - caption = "ℹ️ [CHAT INFO]\n" - caption += f"🆔 ID: {chat.id}\n" - if chat_title is not None: - caption += f"📛 {chat_type} name: {chat_title}\n" - if chat.username: - caption += f"🔗 Link: @{chat.username}\n" - else: - caption += f"🗳 {chat_type} type: Private\n" - if creator_username: - caption += f"🖌 Creator: {creator_username}\n" - elif creator_valid: - caption += f'🖌 Creator: {creator_firstname}\n' - if created: - caption += f"🖌 Created: {created.date().strftime('%b %d, %Y')} - {created.time()}\n" - else: - caption += f"🖌 Created: {chat.date.date().strftime('%b %d, %Y')} - {chat.date.time()} ⚠\n" - caption += f"🗡 Data Centre ID: {dc_id}\n" - if exp_count is not None: - chat_level = int((1 + math.sqrt(1 + 7 * exp_count / 14)) / 2) - caption += f"⭐️ {chat_type} level: {chat_level}\n" - if messages_viewable is not None: - caption += f"💬 Viewable messages: {messages_viewable}\n" - if messages_sent: - caption += f"💬 Messages sent: {messages_sent}\n" - elif messages_sent_alt: - caption += f"💬 Messages sent: {messages_sent_alt} ⚠\n" - if members is not None: - caption += f"👥 Members: {members}\n" - if admins: - caption += f"👮 Administrators: {admins}\n" - if full.bot_info: - caption += f"🤖 Bots: {len(full.bot_info)}\n" - if members_online: - caption += f"👀 Currently online: {members_online}\n" - if restricted_users is not None: - caption += f"🔕 Restricted users: {restricted_users}\n" - if banned_users: - caption += f"📨 Banned users: {banned_users}\n" - if group_stickers: - caption += f'📹 {chat_type} stickers: {group_stickers}\n' - if not broadcast: - if getattr(chat, "slowmode_enabled", None): - caption += f"👉 Slow mode: True" - caption += f", 🕐 {full.slowmode_seconds}s\n" - else: - caption += f"🦸‍♂ Supergroup: {supergroup}\n" - if getattr(chat, "restricted", None): - caption += f"🎌 Restricted: {chat.restricted}\n" - rist = chat.restriction_reason[0] - caption += f"> Platform: {rist.platform}\n" - caption += f"> Reason: {rist.reason}\n" - caption += f"> Text: {rist.text}\n\n" - if getattr(chat, "scam", None): - caption += "⚠ Scam: Yes\n" - if getattr(chat, "verified", None): - caption += f"✅ Verified by Telegram: Yes\n\n" - if full.about: - caption += f"🗒 Description: \n{full.about}\n" - return chat_photo, caption diff --git a/pyUltroid/fns/misc.py b/pyUltroid/fns/misc.py deleted file mode 100644 index 6438570c9c..0000000000 --- a/pyUltroid/fns/misc.py +++ /dev/null @@ -1,458 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import base64 -import os -import random -import re -import string -from logging import WARNING -from random import choice, randrange, shuffle -from traceback import format_exc - -from pyUltroid.exceptions import DependencyMissingError - -try: - from aiohttp import ContentTypeError -except ImportError: - ContentTypeError = None - -from telethon.tl import types -from telethon.utils import get_display_name, get_peer_id - -from .. import * -from .._misc._wrappers import eor - -if run_as_module: - from ..dB import DEVLIST - from ..dB._core import LIST - -from . import some_random_headers -from .helper import async_searcher -from .tools import check_filename, json_parser - -try: - import aiohttp -except ImportError: - aiohttp = None - -try: - from PIL import Image -except ImportError: - Image = None - -try: - import cv2 -except ImportError: - cv2 = None -try: - import numpy as np -except ImportError: - np = None - -try: - from bs4 import BeautifulSoup -except ImportError: - BeautifulSoup = None - - -async def randomchannel( - tochat, channel, range1, range2, caption=None, client=ultroid_bot -): - do = randrange(range1, range2) - async for x in client.iter_messages(channel, add_offset=do, limit=1): - caption = caption or x.text - try: - await client.send_message(tochat, caption, file=x.media) - except BaseException: - pass - - -# -------------------------------------------------- - - -async def YtDataScraper(url: str): - to_return = {} - data = json_parser( - BeautifulSoup( - await async_searcher(url), - "html.parser", - ) - .find_all("script")[41] - .text[20:-1] - )["contents"] - _common_data = data["twoColumnWatchNextResults"]["results"]["results"]["contents"] - common_data = _common_data[0]["videoPrimaryInfoRenderer"] - try: - description_data = _common_data[1]["videoSecondaryInfoRenderer"]["description"][ - "runs" - ] - except (KeyError, IndexError): - description_data = [{"text": "U hurrr from here"}] - description = "".join( - description_datum["text"] for description_datum in description_data - ) - to_return["title"] = common_data["title"]["runs"][0]["text"] - to_return["views"] = ( - common_data["viewCount"]["videoViewCountRenderer"]["shortViewCount"][ - "simpleText" - ] - or common_data["viewCount"]["videoViewCountRenderer"]["viewCount"]["simpleText"] - ) - to_return["publish_date"] = common_data["dateText"]["simpleText"] - to_return["likes"] = ( - common_data["videoActions"]["menuRenderer"]["topLevelButtons"][0][ - "toggleButtonRenderer" - ]["defaultText"]["simpleText"] - # or like_dislike[0]["toggleButtonRenderer"]["defaultText"]["accessibility"][ - # "accessibilityData" - # ]["label"] - ) - to_return["description"] = description - return to_return - - -# -------------------------------------------------- - - -async def google_search(query): - query = query.replace(" ", "+") - _base = "https://google.com" - headers = { - "Cache-Control": "no-cache", - "Connection": "keep-alive", - "User-Agent": choice(some_random_headers), - } - con = await async_searcher(_base + "/search?q=" + query, headers=headers) - soup = BeautifulSoup(con, "html.parser") - result = [] - pdata = soup.find_all("a", href=re.compile("url=")) - for data in pdata: - if not data.find("div"): - continue - try: - result.append( - { - "title": data.find("div").text, - "link": data["href"].split("&url=")[1].split("&ved=")[0], - "description": data.find_all("div")[-1].text, - } - ) - except BaseException as er: - LOGS.exception(er) - return result - - -# ---------------------------------------------------- - - -async def allcmds(event, telegraph): - txt = "" - for z in LIST.keys(): - txt += f"PLUGIN NAME: {z}\n" - for zz in LIST[z]: - txt += HNDLR + zz + "\n" - txt += "\n\n" - t = telegraph.create_page(title="Ultroid All Cmds", content=[txt]) - await eor(event, f"All Ultroid Cmds : [Click Here]({t['url']})", link_preview=False) - - -async def ReTrieveFile(input_file_name): - if not aiohttp: - raise DependencyMissingError("This function needs 'aiohttp' to be installed.") - RMBG_API = udB.get_key("RMBG_API") - headers = {"X-API-Key": RMBG_API} - files = {"image_file": open(input_file_name, "rb").read()} - async with aiohttp.ClientSession() as ses: - async with ses.post( - "https://api.remove.bg/v1.0/removebg", headers=headers, data=files - ) as out: - contentType = out.headers.get("content-type") - if "image" not in contentType: - return False, (await out.json()) - - name = check_filename("ult-rmbg.png") - with open(name, "wb") as file: - file.write(await out.read()) - return True, name - - -# ---------------- Unsplash Search ---------------- -# @New-Dev0 - - -async def unsplashsearch(query, limit=None, shuf=True): - query = query.replace(" ", "-") - link = "https://unsplash.com/s/photos/" + query - extra = await async_searcher(link, re_content=True) - res = BeautifulSoup(extra, "html.parser", from_encoding="utf-8") - all_ = res.find_all("img", srcset=re.compile("images.unsplash.com/photo")) - if shuf: - shuffle(all_) - return list(map(lambda e: e['src'], all_[:limit])) - - -# ---------------- Random User Gen ---------------- -# @xditya - - -async def get_random_user_data(): - base_url = "https://randomuser.me/api/" - cc = await async_searcher( - "https://random-data-api.com/api/business_credit_card/random_card", re_json=True - ) - card = ( - "**CARD_ID:** " - + str(cc["credit_card_number"]) - + f" {cc['credit_card_expiry_date']}\n" - + f"**C-ID :** {cc['id']}" - ) - data_ = (await async_searcher(base_url, re_json=True))["results"][0] - _g = data_["gender"] - gender = "🤵🏻‍♂" if _g == "male" else "🤵🏻‍♀" - name = data_["name"] - loc = data_["location"] - dob = data_["dob"] - msg = """ -{} **Name:** {}.{} {} -**Street:** {} {} -**City:** {} -**State:** {} -**Country:** {} -**Postal Code:** {} -**Email:** {} -**Phone:** {} -**Card:** {} -**Birthday:** {} -""".format( - gender, - name["title"], - name["first"], - name["last"], - loc["street"]["number"], - loc["street"]["name"], - loc["city"], - loc["state"], - loc["country"], - loc["postcode"], - data_["email"], - data_["phone"], - card, - dob["date"][:10], - ) - pic = data_["picture"]["large"] - return msg, pic - - -# Dictionary (Synonyms and Antonyms) - - -async def get_synonyms_or_antonyms(word, type_of_words): - if type_of_words not in ["synonyms", "antonyms"]: - return "Dude! Please give a corrent type of words you want." - s = await async_searcher( - f"https://tuna.thesaurus.com/pageData/{word}", re_json=True - ) - li_1 = [ - y - for x in [ - s["data"]["definitionData"]["definitions"][0][type_of_words], - s["data"]["definitionData"]["definitions"][1][type_of_words], - ] - for y in x - ] - return [y["term"] for y in li_1] - - -# Quotly - - -class Quotly: - _API = "https://bot.lyo.su/quote/generate" - _entities = { - types.MessageEntityPhone: "phone_number", - types.MessageEntityMention: "mention", - types.MessageEntityBold: "bold", - types.MessageEntityCashtag: "cashtag", - types.MessageEntityStrike: "strikethrough", - types.MessageEntityHashtag: "hashtag", - types.MessageEntityEmail: "email", - types.MessageEntityMentionName: "text_mention", - types.MessageEntityUnderline: "underline", - types.MessageEntityUrl: "url", - types.MessageEntityTextUrl: "text_link", - types.MessageEntityBotCommand: "bot_command", - types.MessageEntityCode: "code", - types.MessageEntityPre: "pre", - types.MessageEntitySpoiler: "spoiler", - } - - 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"] - ) - os.remove(file) - os.remove(file_) - return uri - - if reply and reply.raw_text: - reply = { - "name": get_display_name(reply.sender) or "Deleted Account", - "text": reply.raw_text, - "chatId": reply.chat_id, - } - else: - reply = {} - is_fwd = event.fwd_from - name = None - last_name = None - if sender and sender.id not in DEVLIST: - id_ = get_peer_id(sender) - elif not is_fwd: - id_ = event.sender_id - sender = await event.get_sender() - else: - id_, sender = None, None - name = is_fwd.from_name - if is_fwd.from_id: - id_ = get_peer_id(is_fwd.from_id) - try: - sender = await event.client.get_entity(id_) - except ValueError: - pass - if sender: - name = get_display_name(sender) - if hasattr(sender, "last_name"): - last_name = sender.last_name - entities = [] - if event.entities: - for entity in event.entities: - if type(entity) in self._entities: - enti_ = entity.to_dict() - del enti_["_"] - enti_["type"] = self._entities[type(entity)] - entities.append(enti_) - text = event.raw_text - if isinstance(event, types.MessageService): - if isinstance(event.action, types.MessageActionGameScore): - text = f"scored {event.action.score}" - rep = await event.get_reply_message() - if rep and rep.game: - text += f" in {rep.game.title}" - elif isinstance(event.action, types.MessageActionPinMessage): - text = "pinned a message." - # TODO: Are there any more events with sender? - message = { - "entities": entities, - "chatId": id_, - "avatar": True, - "from": { - "id": id_, - "first_name": (name or (sender.first_name if sender else None)) - or "Deleted Account", - "last_name": last_name, - "username": sender.username if sender else None, - "language_code": "en", - "title": name, - "name": name or "Deleted Account", - "type": type_, - }, - "text": text, - "replyMessage": reply, - } - if event.document and event.document.thumbs: - file_ = await event.download_media(thumb=-1) - uri = await telegraph(file_) - message["media"] = {"url": uri} - - return message - - async def create_quotly( - self, - event, - url="https://bot.lyo.su/quote/generate", - reply={}, - bg=None, - sender=None, - file_name="quote.webp", - ): - """Create quotely's quote.""" - if not isinstance(event, list): - event = [event] - from .. import udB - - if udB.get_key("OQAPI"): - url = Quotly._API - if not bg: - bg = "#1b1429" - content = { - "type": "quote", - "format": "webp", - "backgroundColor": bg, - "width": 512, - "height": 768, - "scale": 2, - "messages": [ - await self._format_quote(message, reply=reply, sender=sender) - for message in event - ], - } - try: - request = await async_searcher(url, post=True, json=content, re_json=True) - except ContentTypeError as er: - if url != self._API: - return await self.create_quotly( - event, - url=self._API, - bg=bg, - sender=sender, - reply=reply, - file_name=file_name, - ) - raise er - if request.get("ok"): - with open(file_name, "wb") as file: - image = base64.decodebytes(request["result"]["image"].encode("utf-8")) - file.write(image) - return file_name - raise Exception(str(request)) - - -def split_list(List, index): - new_ = [] - while List: - new_.extend([List[:index]]) - List = List[index:] - return new_ - - -# https://stackoverflow.com/questions/9041681/opencv-python-rotate-image-by-x-degrees-around-specific-point - - -def rotate_image(image, angle): - if not cv2: - raise DependencyMissingError("This function needs 'cv2' to be installed!") - image_center = tuple(np.array(image.shape[1::-1]) / 2) - rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0) - return cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR) - - -def random_string(length=3): - """Generate random string of 'n' Length""" - return "".join(random.choices(string.ascii_uppercase, k=length)) - - -setattr(random, "random_string", random_string) diff --git a/pyUltroid/fns/ytdl.py b/pyUltroid/fns/ytdl.py deleted file mode 100644 index b1a1648ae7..0000000000 --- a/pyUltroid/fns/ytdl.py +++ /dev/null @@ -1,269 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import glob -import os -import re -import time - -from telethon import Button - -try: - from youtubesearchpython import Playlist, VideosSearch -except ImportError: - Playlist, VideosSearch = None, None - -from yt_dlp import YoutubeDL - -from .. import LOGS, udB -from .helper import download_file, humanbytes, run_async, time_formatter -from .tools import set_attributes - - -async def ytdl_progress(k, start_time, event): - if k["status"] == "error": - return await event.edit("error") - while k["status"] == "downloading": - text = ( - f"`Downloading: {k['filename']}\n" - + f"Total Size: {humanbytes(k['total_bytes'])}\n" - + f"Downloaded: {humanbytes(k['downloaded_bytes'])}\n" - + f"Speed: {humanbytes(k['speed'])}/s\n" - + f"ETA: {time_formatter(k['eta']*1000)}`" - ) - if round((time.time() - start_time) % 10.0) == 0: - try: - await event.edit(text) - except Exception as ex: - LOGS.error(f"ytdl_progress: {ex}") - - -def get_yt_link(query): - search = VideosSearch(query, limit=1).result() - try: - return search["result"][0]["link"] - except IndexError: - return - - -async def download_yt(event, link, ytd): - reply_to = event.reply_to_msg_id or event - info = await dler(event, link, ytd, download=True) - if not info: - return - if info.get("_type", None) == "playlist": - total = info["playlist_count"] - for num, file in enumerate(info["entries"]): - num += 1 - id_ = file["id"] - thumb = id_ + ".jpg" - title = file["title"] - await download_file( - file.get("thumbnail", None) or file["thumbnails"][-1]["url"], thumb - ) - ext = "." + ytd["outtmpl"]["default"].split(".")[-1] - if ext == ".m4a": - ext = ".mp3" - id = None - for x in glob.glob(f"{id_}*"): - if not x.endswith("jpg"): - id = x - if not id: - return - ext = "." + id.split(".")[-1] - file = title + ext - try: - os.rename(id, file) - except FileNotFoundError: - try: - os.rename(id + ext, file) - except FileNotFoundError as er: - if os.path.exists(id): - file = id - else: - raise er - if file.endswith(".part"): - os.remove(file) - os.remove(thumb) - await event.client.send_message( - event.chat_id, - f"`[{num}/{total}]` `Invalid Video format.\nIgnoring that...`", - ) - return - attributes = await set_attributes(file) - res, _ = await event.client.fast_uploader( - file, show_progress=True, event=event, to_delete=True - ) - from_ = info["extractor"].split(":")[0] - caption = f"`[{num}/{total}]` `{title}`\n\n`from {from_}`" - await event.client.send_file( - event.chat_id, - file=res, - caption=caption, - attributes=attributes, - supports_streaming=True, - thumb=thumb, - reply_to=reply_to, - ) - os.remove(thumb) - try: - await event.delete() - except BaseException: - pass - return - title = info["title"] - if len(title) > 20: - title = title[:17] + "..." - id_ = info["id"] - thumb = id_ + ".jpg" - await download_file( - info.get("thumbnail", None) or f"https://i.ytimg.com/vi/{id_}/hqdefault.jpg", - thumb, - ) - ext = "." + ytd["outtmpl"]["default"].split(".")[-1] - for _ext in [".m4a", ".mp3", ".opus"]: - if ext == _ext: - ext = _ext - break - id = None - for x in glob.glob(f"{id_}*"): - if not x.endswith("jpg"): - id = x - if not id: - return - ext = "." + id.split(".")[-1] - file = title + ext - try: - os.rename(id, file) - except FileNotFoundError: - os.rename(id + ext, file) - attributes = await set_attributes(file) - res, _ = await event.client.fast_uploader( - file, show_progress=True, event=event, to_delete=True - ) - caption = f"`{info['title']}`" - await event.client.send_file( - event.chat_id, - file=res, - caption=caption, - attributes=attributes, - supports_streaming=True, - thumb=thumb, - reply_to=reply_to, - ) - os.remove(thumb) - try: - await event.delete() - except BaseException: - pass - - -# ---------------YouTube Downloader Inline--------------- -# @New-Dev0 @buddhhu @1danish-00 - - -def get_formats(type, id, data): - if type == "audio": - audio = [] - for _quality in ["64", "128", "256", "320"]: - _audio = {} - _audio.update( - { - "ytid": id, - "type": "audio", - "id": _quality, - "quality": _quality + "KBPS", - } - ) - audio.append(_audio) - return audio - if type == "video": - video = [] - size = 0 - for vid in data["formats"]: - if vid["format_id"] == "251": - size += vid["filesize"] if vid.get("filesize") else 0 - if vid["vcodec"] != "none": - _id = int(vid["format_id"]) - _quality = str(vid["width"]) + "×" + str(vid["height"]) - _size = size + (vid["filesize"] if vid.get("filesize") else 0) - _ext = "mkv" if vid["ext"] == "webm" else "mp4" - if _size < 2147483648: # Telegram's Limit of 2GB - _video = {} - _video.update( - { - "ytid": id, - "type": "video", - "id": str(_id) + "+251", - "quality": _quality, - "size": _size, - "ext": _ext, - } - ) - video.append(_video) - return video - return [] - - -def get_buttons(listt): - id = listt[0]["ytid"] - butts = [ - Button.inline( - text=f"[{x['quality']}" - + (f" {humanbytes(x['size'])}]" if x.get("size") else "]"), - data=f"ytdownload:{x['type']}:{x['id']}:{x['ytid']}" - + (f":{x['ext']}" if x.get("ext") else ""), - ) - for x in listt - ] - buttons = list(zip(butts[::2], butts[1::2])) - if len(butts) % 2 == 1: - buttons.append((butts[-1],)) - buttons.append([Button.inline("« Back", f"ytdl_back:{id}")]) - return buttons - - -async def dler(event, url, opts: dict = {}, download=False): - await event.edit("`Getting Data...`") - if "quiet" not in opts: - opts["quiet"] = True - opts["username"] = udB.get_key("YT_USERNAME") - opts["password"] = udB.get_key("YT_PASSWORD") - if download: - await ytdownload(url, opts) - try: - return await extract_info(url, opts) - except Exception as e: - await event.edit(f"{type(e)}: {e}") - return - - -@run_async -def ytdownload(url, opts): - try: - return YoutubeDL(opts).download([url]) - except Exception as ex: - LOGS.error(ex) - - -@run_async -def extract_info(url, opts): - return YoutubeDL(opts).extract_info(url=url, download=False) - - -@run_async -def get_videos_link(url): - to_return = [] - regex = re.search(r"\?list=([(\w+)\-]*)", url) - if not regex: - return to_return - playlist_id = regex.group(1) - videos = Playlist(playlist_id) - for vid in videos.videos: - link = re.search(r"\?v=([(\w+)\-]*)", vid["link"]).group(1) - to_return.append(f"https://youtube.com/watch?v={link}") - return to_return diff --git a/pyUltroid/loader.py b/pyUltroid/loader.py deleted file mode 100644 index 79e8374ba2..0000000000 --- a/pyUltroid/loader.py +++ /dev/null @@ -1,77 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import contextlib -import glob -import os -from importlib import import_module -from logging import Logger - -from . import LOGS -from .fns.tools import get_all_files - - -class Loader: - def __init__(self, path="plugins", key="Official", logger: Logger = LOGS): - self.path = path - self.key = key - self._logger = logger - - def load( - self, - log=True, - func=import_module, - include=None, - exclude=None, - after_load=None, - load_all=False, - ): - _single = os.path.isfile(self.path) - if include: - if log: - self._logger.info("Including: {}".format("• ".join(include))) - files = glob.glob(f"{self.path}/_*.py") - for file in include: - path = f"{self.path}/{file}.py" - if os.path.exists(path): - files.append(path) - elif _single: - files = [self.path] - else: - if load_all: - files = get_all_files(self.path, ".py") - else: - files = glob.glob(f"{self.path}/*.py") - if exclude: - for path in exclude: - if not path.startswith("_"): - with contextlib.suppress(ValueError): - files.remove(f"{self.path}/{path}.py") - if log and not _single: - self._logger.info( - f"• Installing {self.key} Plugins || Count : {len(files)} •" - ) - for plugin in sorted(files): - if func == import_module: - plugin = plugin.replace(".py", "").replace("/", ".").replace("\\", ".") - try: - modl = func(plugin) - except ModuleNotFoundError as er: - modl = None - self._logger.error(f"{plugin}: '{er.name}' not installed!") - continue - except Exception as exc: - modl = None - self._logger.error(f"pyUltroid - {self.key} - ERROR - {plugin}") - self._logger.exception(exc) - continue - if _single and log: - self._logger.info(f"Successfully Loaded {plugin}!") - if callable(after_load): - if func == import_module: - plugin = plugin.split(".")[-1] - after_load(self, modl, plugin_name=plugin) diff --git a/pyUltroid/startup/__init__.py b/pyUltroid/startup/__init__.py deleted file mode 100644 index 30c3e92f3d..0000000000 --- a/pyUltroid/startup/__init__.py +++ /dev/null @@ -1,99 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import os -import platform -import sys -from logging import INFO, WARNING, FileHandler, StreamHandler, basicConfig, getLogger - -from .. import run_as_module -from ._extra import _ask_input - -if run_as_module: - from ..configs import Var -else: - Var = None - - -def where_hosted(): - if os.getenv("DYNO"): - return "heroku" - if os.getenv("RAILWAY_STATIC_URL"): - return "railway" - if os.getenv("OKTETO_TOKEN"): - return "okteto" - if os.getenv("KUBERNETES_PORT"): - return "qovery | kubernetes" - if os.getenv("RUNNER_USER") or os.getenv("HOSTNAME"): - if os.getenv("USER") == "codespace": - return "codespace" - return "github actions" - if os.getenv("ANDROID_ROOT"): - return "termux" - if os.getenv("FLY_APP_NAME"): - return "fly.io" - return "local" - - -if run_as_module: - from telethon import __version__ - from telethon.tl.alltlobjects import LAYER - - from ..version import __version__ as __pyUltroid__ - from ..version import ultroid_version - - file = f"ultroid{sys.argv[6]}.log" if len(sys.argv) > 6 else "ultroid.log" - - if os.path.exists(file): - os.remove(file) - - HOSTED_ON = where_hosted() - LOGS = getLogger("pyUltLogs") - TelethonLogger = getLogger("Telethon") - TelethonLogger.setLevel(INFO) - - _, v, __ = platform.python_version_tuple() - - if int(v) < 10: - from ._extra import _fix_logging - - _fix_logging(FileHandler) - - _ask_input() - - _LOG_FORMAT = "%(asctime)s | %(name)s [%(levelname)s] : %(message)s" - basicConfig( - format=_LOG_FORMAT, - level=INFO, - datefmt="%m/%d/%Y, %H:%M:%S", - handlers=[FileHandler(file), StreamHandler()], - ) - try: - - import coloredlogs - - coloredlogs.install(level=None, logger=LOGS, fmt=_LOG_FORMAT) - except ImportError: - pass - - LOGS.info( - """ - ----------------------------------- - Starting Deployment - ----------------------------------- - """ - ) - - LOGS.info(f"Python version - {platform.python_version()}") - LOGS.info(f"py-Ultroid Version - {__pyUltroid__}") - LOGS.info(f"Telethon Version - {__version__} [Layer: {LAYER}]") - LOGS.info(f"Ultroid Version - {ultroid_version} [{HOSTED_ON}]") - - try: - from safety.tools import * - except ImportError: - LOGS.error("'safety' package not found!") diff --git a/pyUltroid/startup/_database.py b/pyUltroid/startup/_database.py deleted file mode 100644 index 1d368b27ef..0000000000 --- a/pyUltroid/startup/_database.py +++ /dev/null @@ -1,352 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import ast -import os -import sys - -from .. import run_as_module -from . import * - -if run_as_module: - from ..configs import Var - - -Redis = MongoClient = psycopg2 = Database = None -if Var.REDIS_URI or Var.REDISHOST: - try: - from redis import Redis - except ImportError: - LOGS.info("Installing 'redis' for database.") - os.system(f"{sys.executable} -m pip install -q redis hiredis") - from redis import Redis -elif Var.MONGO_URI: - try: - from pymongo import MongoClient - except ImportError: - LOGS.info("Installing 'pymongo' for database.") - os.system(f"{sys.executable} -m pip install -q pymongo[srv]") - from pymongo import MongoClient -elif Var.DATABASE_URL: - try: - import psycopg2 - except ImportError: - LOGS.info("Installing 'pyscopg2' for database.") - os.system(f"{sys.executable} -m pip install -q psycopg2-binary") - import psycopg2 -else: - try: - from localdb import Database - except ImportError: - LOGS.info("Using local file as database.") - os.system(f"{sys.executable} -m pip install -q localdb.json") - from localdb import Database - -# --------------------------------------------------------------------------------------------- # - - -class _BaseDatabase: - def __init__(self, *args, **kwargs): - self._cache = {} - - def get_key(self, key): - if key in self._cache: - return self._cache[key] - value = self._get_data(key) - self._cache.update({key: value}) - return value - - def re_cache(self): - self._cache.clear() - for key in self.keys(): - self._cache.update({key: self.get_key(key)}) - - def ping(self): - return 1 - - @property - def usage(self): - return 0 - - def keys(self): - return [] - - def del_key(self, key): - if key in self._cache: - del self._cache[key] - self.delete(key) - return True - - def _get_data(self, key=None, data=None): - if key: - data = self.get(str(key)) - if data and isinstance(data, str): - try: - data = ast.literal_eval(data) - except BaseException: - pass - return data - - def set_key(self, key, value, cache_only=False): - value = self._get_data(data=value) - self._cache[key] = value - if cache_only: - return - return self.set(str(key), str(value)) - - def rename(self, key1, key2): - _ = self.get_key(key1) - if _: - self.del_key(key1) - self.set_key(key2, _) - return 0 - return 1 - - -class MongoDB(_BaseDatabase): - def __init__(self, key, dbname="UltroidDB"): - self.dB = MongoClient(key, serverSelectionTimeoutMS=5000) - self.db = self.dB[dbname] - super().__init__() - - def __repr__(self): - return f"" - - @property - def name(self): - return "Mongo" - - @property - def usage(self): - return self.db.command("dbstats")["dataSize"] - - def ping(self): - if self.dB.server_info(): - return True - - def keys(self): - return self.db.list_collection_names() - - def set(self, key, value): - if key in self.keys(): - self.db[key].replace_one({"_id": key}, {"value": str(value)}) - else: - self.db[key].insert_one({"_id": key, "value": str(value)}) - return True - - def delete(self, key): - self.db.drop_collection(key) - - def get(self, key): - if x := self.db[key].find_one({"_id": key}): - return x["value"] - - def flushall(self): - self.dB.drop_database("UltroidDB") - self._cache.clear() - return True - - -# --------------------------------------------------------------------------------------------- # - -# Thanks to "Akash Pattnaik" / @BLUE-DEVIL1134 -# for SQL Implementation in Ultroid. -# -# Please use https://elephantsql.com/ ! - - -class SqlDB(_BaseDatabase): - def __init__(self, url): - self._url = url - self._connection = None - self._cursor = None - try: - self._connection = psycopg2.connect(dsn=url) - self._connection.autocommit = True - self._cursor = self._connection.cursor() - self._cursor.execute( - "CREATE TABLE IF NOT EXISTS Ultroid (ultroidCli varchar(70))" - ) - except Exception as error: - LOGS.exception(error) - LOGS.info("Invaid SQL Database") - if self._connection: - self._connection.close() - sys.exit() - super().__init__() - - @property - def name(self): - return "SQL" - - @property - def usage(self): - self._cursor.execute( - "SELECT pg_size_pretty(pg_relation_size('Ultroid')) AS size" - ) - data = self._cursor.fetchall() - return int(data[0][0].split()[0]) - - def keys(self): - self._cursor.execute( - "SELECT column_name FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'ultroid'" - ) # case sensitive - data = self._cursor.fetchall() - return [_[0] for _ in data] - - def get(self, variable): - try: - self._cursor.execute(f"SELECT {variable} FROM Ultroid") - except psycopg2.errors.UndefinedColumn: - return None - data = self._cursor.fetchall() - if not data: - return None - if len(data) >= 1: - for i in data: - if i[0]: - return i[0] - - def set(self, key, value): - try: - self._cursor.execute(f"ALTER TABLE Ultroid DROP COLUMN IF EXISTS {key}") - except (psycopg2.errors.UndefinedColumn, psycopg2.errors.SyntaxError): - pass - except BaseException as er: - LOGS.exception(er) - self._cache.update({key: value}) - self._cursor.execute(f"ALTER TABLE Ultroid ADD {key} TEXT") - self._cursor.execute(f"INSERT INTO Ultroid ({key}) values (%s)", (str(value),)) - return True - - def delete(self, key): - try: - self._cursor.execute(f"ALTER TABLE Ultroid DROP COLUMN {key}") - except psycopg2.errors.UndefinedColumn: - return False - return True - - def flushall(self): - self._cache.clear() - self._cursor.execute("DROP TABLE Ultroid") - self._cursor.execute( - "CREATE TABLE IF NOT EXISTS Ultroid (ultroidCli varchar(70))" - ) - return True - - -# --------------------------------------------------------------------------------------------- # - - -class RedisDB(_BaseDatabase): - def __init__( - self, - host, - port, - password, - platform="", - logger=LOGS, - *args, - **kwargs, - ): - if host and ":" in host: - spli_ = host.split(":") - host = spli_[0] - port = int(spli_[-1]) - if host.startswith("http"): - logger.error("Your REDIS_URI should not start with http !") - import sys - - sys.exit() - elif not host or not port: - logger.error("Port Number not found") - import sys - - sys.exit() - kwargs["host"] = host - kwargs["password"] = password - kwargs["port"] = port - - if platform.lower() == "qovery" and not host: - var, hash_, host, password = "", "", "", "" - for vars_ in os.environ: - if vars_.startswith("QOVERY_REDIS_") and vars.endswith("_HOST"): - var = vars_ - if var: - hash_ = var.split("_", maxsplit=2)[1].split("_")[0] - if hash: - kwargs["host"] = os.environ.get(f"QOVERY_REDIS_{hash_}_HOST") - kwargs["port"] = os.environ.get(f"QOVERY_REDIS_{hash_}_PORT") - kwargs["password"] = os.environ.get(f"QOVERY_REDIS_{hash_}_PASSWORD") - self.db = Redis(**kwargs) - self.set = self.db.set - self.get = self.db.get - self.keys = self.db.keys - self.delete = self.db.delete - super().__init__() - - @property - def name(self): - return "Redis" - - @property - def usage(self): - return sum(self.db.memory_usage(x) for x in self.keys()) - - -# --------------------------------------------------------------------------------------------- # - - -class LocalDB(_BaseDatabase): - def __init__(self): - self.db = Database("ultroid") - self.get = self.db.get - self.set = self.db.set - self.delete = self.db.delete - super().__init__() - - @property - def name(self): - return "LocalDB" - - def keys(self): - return self._cache.keys() - - def __repr__(self): - return f"" - - -def UltroidDB(): - _er = False - from .. import HOSTED_ON - - try: - if Redis: - return RedisDB( - host=Var.REDIS_URI or Var.REDISHOST, - password=Var.REDIS_PASSWORD or Var.REDISPASSWORD, - port=Var.REDISPORT, - platform=HOSTED_ON, - decode_responses=True, - socket_timeout=5, - retry_on_timeout=True, - ) - elif MongoClient: - return MongoDB(Var.MONGO_URI) - elif psycopg2: - return SqlDB(Var.DATABASE_URL) - else: - LOGS.critical( - "No DB requirement fullfilled!\nPlease install redis, mongo or sql dependencies...\nTill then using local file as database." - ) - return LocalDB() - except BaseException as err: - LOGS.exception(err) - exit() - - -# --------------------------------------------------------------------------------------------- # diff --git a/pyUltroid/startup/_extra.py b/pyUltroid/startup/_extra.py deleted file mode 100644 index d58c105252..0000000000 --- a/pyUltroid/startup/_extra.py +++ /dev/null @@ -1,28 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -# https://bugs.python.org/issue26789 -# 'open' not defined has been fixed in Python3.10 -# for other older versions, something need to be done. - - -def _fix_logging(handler): - handler._builtin_open = open - - def _new_open(self): - open_func = self._builtin_open - return open_func(self.baseFilename, self.mode) - - setattr(handler, "_open", _new_open) - - -def _ask_input(): - # Ask for Input even on Vps and other platforms. - def new_input(*args, **kwargs): - raise EOFError("args=" + str(args) + ", kwargs=" + str(kwargs)) - - __builtins__["input"] = new_input diff --git a/pyUltroid/startup/connections.py b/pyUltroid/startup/connections.py deleted file mode 100644 index fd9086aca8..0000000000 --- a/pyUltroid/startup/connections.py +++ /dev/null @@ -1,94 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import base64 -import ipaddress -import struct -import sys - -from telethon.errors.rpcerrorlist import AuthKeyDuplicatedError -from telethon.sessions.string import _STRUCT_PREFORMAT, CURRENT_VERSION, StringSession - -from ..configs import Var -from . import * -from .BaseClient import UltroidClient - -_PYRO_FORM = {351: ">B?256sI?", 356: ">B?256sQ?", 362: ">BI?256sQ?"} - -# https://github.com/pyrogram/pyrogram/blob/master/docs/source/faq/what-are-the-ip-addresses-of-telegram-data-centers.rst - -DC_IPV4 = { - 1: "149.154.175.53", - 2: "149.154.167.51", - 3: "149.154.175.100", - 4: "149.154.167.91", - 5: "91.108.56.130", -} - - -def validate_session(session, logger=LOGS, _exit=True): - from strings import get_string - - if session: - # Telethon Session - if session.startswith(CURRENT_VERSION): - if len(session.strip()) != 353: - logger.exception(get_string("py_c1")) - sys.exit() - return StringSession(session) - - # Pyrogram Session - elif len(session) in _PYRO_FORM.keys(): - data_ = struct.unpack( - _PYRO_FORM[len(session)], - base64.urlsafe_b64decode(session + "=" * (-len(session) % 4)), - ) - if len(session) in [351, 356]: - auth_id = 2 - else: - auth_id = 3 - dc_id, auth_key = data_[0], data_[auth_id] - return StringSession( - CURRENT_VERSION - + base64.urlsafe_b64encode( - struct.pack( - _STRUCT_PREFORMAT.format(4), - dc_id, - ipaddress.ip_address(DC_IPV4[dc_id]).packed, - 443, - auth_key, - ) - ).decode("ascii") - ) - else: - logger.exception(get_string("py_c1")) - if _exit: - sys.exit() - logger.exception(get_string("py_c2")) - if _exit: - sys.exit() - - -def vc_connection(udB, ultroid_bot): - from strings import get_string - - VC_SESSION = Var.VC_SESSION or udB.get_key("VC_SESSION") - if VC_SESSION and VC_SESSION != Var.SESSION: - LOGS.info("Starting up VcClient.") - try: - return UltroidClient( - validate_session(VC_SESSION, _exit=False), - log_attempt=False, - exit_on_error=False, - ) - except (AuthKeyDuplicatedError, EOFError): - LOGS.info(get_string("py_c3")) - udB.del_key("VC_SESSION") - except Exception as er: - LOGS.info("While creating Client for VC.") - LOGS.exception(er) - return ultroid_bot diff --git a/pyUltroid/startup/funcs.py b/pyUltroid/startup/funcs.py deleted file mode 100644 index f5b26ad662..0000000000 --- a/pyUltroid/startup/funcs.py +++ /dev/null @@ -1,560 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import asyncio -import os -import random -import shutil -import time -from random import randint - -from ..configs import Var - -try: - from pytz import timezone -except ImportError: - timezone = None - -from telethon.errors import ( - ChannelsTooMuchError, - ChatAdminRequiredError, - MessageIdInvalidError, - MessageNotModifiedError, - UserNotParticipantError, -) -from telethon.tl.custom import Button -from telethon.tl.functions.channels import ( - CreateChannelRequest, - EditAdminRequest, - EditPhotoRequest, - InviteToChannelRequest, -) -from telethon.tl.functions.contacts import UnblockRequest -from telethon.tl.types import ( - ChatAdminRights, - ChatPhotoEmpty, - InputChatUploadedPhoto, - InputMessagesFilterDocument, -) -from telethon.utils import get_peer_id -from decouple import config, RepositoryEnv -from .. import LOGS, ULTConfig -from ..fns.helper import download_file, inline_mention, updater - -db_url = 0 - - -async def autoupdate_local_database(): - from .. import Var, asst, udB, ultroid_bot - - global db_url - db_url = ( - udB.get_key("TGDB_URL") or Var.TGDB_URL or ultroid_bot._cache.get("TGDB_URL") - ) - if db_url: - _split = db_url.split("/") - _channel = _split[-2] - _id = _split[-1] - try: - await asst.edit_message( - int(_channel) if _channel.isdigit() else _channel, - message=_id, - file="database.json", - text="**Do not delete this file.**", - ) - except MessageNotModifiedError: - return - except MessageIdInvalidError: - pass - try: - LOG_CHANNEL = ( - udB.get_key("LOG_CHANNEL") - or Var.LOG_CHANNEL - or asst._cache.get("LOG_CHANNEL") - or "me" - ) - msg = await asst.send_message( - LOG_CHANNEL, "**Do not delete this file.**", file="database.json" - ) - asst._cache["TGDB_URL"] = msg.message_link - udB.set_key("TGDB_URL", msg.message_link) - except Exception as ex: - LOGS.error(f"Error on autoupdate_local_database: {ex}") - - -def update_envs(): - """Update Var. attributes to udB""" - from .. import udB - _envs = [*list(os.environ)] - if ".env" in os.listdir("."): - [_envs.append(_) for _ in list(RepositoryEnv(config._find_file(".")).data)] - for envs in _envs: - if ( - envs in ["LOG_CHANNEL", "BOT_TOKEN", "BOTMODE", "DUAL_MODE", "language"] - or envs in udB.keys() - ): - if _value := os.environ.get(envs): - udB.set_key(envs, _value) - else: - udB.set_key(envs, config.config.get(envs)) - - -async def startup_stuff(): - from .. import udB - - x = ["resources/auth", "resources/downloads"] - for x in x: - if not os.path.isdir(x): - os.mkdir(x) - - CT = udB.get_key("CUSTOM_THUMBNAIL") - if CT: - path = "resources/extras/thumbnail.jpg" - ULTConfig.thumb = path - try: - await download_file(CT, path) - except Exception as er: - LOGS.exception(er) - elif CT is False: - ULTConfig.thumb = None - GT = udB.get_key("GDRIVE_AUTH_TOKEN") - if GT: - with open("resources/auth/gdrive_creds.json", "w") as t_file: - t_file.write(GT) - - if udB.get_key("AUTH_TOKEN"): - udB.del_key("AUTH_TOKEN") - - MM = udB.get_key("MEGA_MAIL") - MP = udB.get_key("MEGA_PASS") - if MM and MP: - with open(".megarc", "w") as mega: - mega.write(f"[Login]\nUsername = {MM}\nPassword = {MP}") - - TZ = udB.get_key("TIMEZONE") - if TZ and timezone: - try: - timezone(TZ) - os.environ["TZ"] = TZ - time.tzset() - except AttributeError as er: - LOGS.debug(er) - except BaseException: - LOGS.critical( - "Incorrect Timezone ,\nCheck Available Timezone From Here https://graph.org/Ultroid-06-18-2\nSo Time is Default UTC" - ) - os.environ["TZ"] = "UTC" - time.tzset() - - -async def autobot(): - from .. import udB, ultroid_bot - - if udB.get_key("BOT_TOKEN"): - return - await ultroid_bot.start() - LOGS.info("MAKING A TELEGRAM BOT FOR YOU AT @BotFather, Kindly Wait") - who = ultroid_bot.me - name = who.first_name + "'s Bot" - if who.username: - username = who.username + "_bot" - else: - username = "ultroid_" + (str(who.id))[5:] + "_bot" - bf = "@BotFather" - await ultroid_bot(UnblockRequest(bf)) - await ultroid_bot.send_message(bf, "/cancel") - await asyncio.sleep(1) - await ultroid_bot.send_message(bf, "/newbot") - await asyncio.sleep(1) - isdone = (await ultroid_bot.get_messages(bf, limit=1))[0].text - if isdone.startswith("That I cannot do.") or "20 bots" in isdone: - LOGS.critical( - "Please make a Bot from @BotFather and add it's token in BOT_TOKEN, as an env var and restart me." - ) - import sys - - sys.exit(1) - await ultroid_bot.send_message(bf, name) - await asyncio.sleep(1) - isdone = (await ultroid_bot.get_messages(bf, limit=1))[0].text - if not isdone.startswith("Good."): - await ultroid_bot.send_message(bf, "My Assistant Bot") - await asyncio.sleep(1) - isdone = (await ultroid_bot.get_messages(bf, limit=1))[0].text - if not isdone.startswith("Good."): - LOGS.critical( - "Please make a Bot from @BotFather and add it's token in BOT_TOKEN, as an env var and restart me." - ) - import sys - - sys.exit(1) - await ultroid_bot.send_message(bf, username) - await asyncio.sleep(1) - isdone = (await ultroid_bot.get_messages(bf, limit=1))[0].text - await ultroid_bot.send_read_acknowledge("botfather") - if isdone.startswith("Sorry,"): - ran = randint(1, 100) - username = "ultroid_" + (str(who.id))[6:] + str(ran) + "_bot" - await ultroid_bot.send_message(bf, username) - await asyncio.sleep(1) - isdone = (await ultroid_bot.get_messages(bf, limit=1))[0].text - if isdone.startswith("Done!"): - token = isdone.split("`")[1] - udB.set_key("BOT_TOKEN", token) - await enable_inline(ultroid_bot, username) - LOGS.info( - f"Done. Successfully created @{username} to be used as your assistant bot!" - ) - else: - LOGS.info( - "Please Delete Some Of your Telegram bots at @Botfather or Set Var BOT_TOKEN with token of a bot" - ) - - import sys - - sys.exit(1) - - -async def autopilot(): - from .. import asst, udB, ultroid_bot - - channel = udB.get_key("LOG_CHANNEL") - new_channel = None - if channel: - try: - chat = await ultroid_bot.get_entity(channel) - except BaseException as err: - LOGS.exception(err) - udB.del_key("LOG_CHANNEL") - channel = None - if not channel: - - async def _save(exc): - udB._cache["LOG_CHANNEL"] = ultroid_bot.me.id - await asst.send_message( - ultroid_bot.me.id, f"Failed to Create Log Channel due to {exc}.." - ) - - if ultroid_bot._bot: - msg_ = "'LOG_CHANNEL' not found! Add it in order to use 'BOTMODE'" - LOGS.error(msg_) - return await _save(msg_) - LOGS.info("Creating a Log Channel for You!") - try: - r = await ultroid_bot( - CreateChannelRequest( - title="My Ultroid Logs", - about="My Ultroid Log Group\n\n Join @TeamUltroid", - megagroup=True, - ), - ) - except ChannelsTooMuchError as er: - LOGS.critical( - "You Are in Too Many Channels & Groups , Leave some And Restart The Bot" - ) - return await _save(str(er)) - except BaseException as er: - LOGS.exception(er) - LOGS.info( - "Something Went Wrong , Create A Group and set its id on config var LOG_CHANNEL." - ) - - return await _save(str(er)) - new_channel = True - chat = r.chats[0] - channel = get_peer_id(chat) - udB.set_key("LOG_CHANNEL", channel) - assistant = True - try: - await ultroid_bot.get_permissions(int(channel), asst.me.username) - except UserNotParticipantError: - try: - await ultroid_bot(InviteToChannelRequest(int(channel), [asst.me.username])) - except BaseException as er: - LOGS.info("Error while Adding Assistant to Log Channel") - LOGS.exception(er) - assistant = False - except BaseException as er: - assistant = False - LOGS.exception(er) - if assistant and new_channel: - try: - achat = await asst.get_entity(int(channel)) - except BaseException as er: - achat = None - LOGS.info("Error while getting Log channel from Assistant") - LOGS.exception(er) - if achat and not achat.admin_rights: - rights = ChatAdminRights( - add_admins=True, - invite_users=True, - change_info=True, - ban_users=True, - delete_messages=True, - pin_messages=True, - anonymous=False, - manage_call=True, - ) - try: - await ultroid_bot( - EditAdminRequest( - int(channel), asst.me.username, rights, "Assistant" - ) - ) - except ChatAdminRequiredError: - LOGS.info( - "Failed to promote 'Assistant Bot' in 'Log Channel' due to 'Admin Privileges'" - ) - except BaseException as er: - LOGS.info("Error while promoting assistant in Log Channel..") - LOGS.exception(er) - if isinstance(chat.photo, ChatPhotoEmpty): - photo, _ = await download_file( - "https://graph.org/file/27c6812becf6f376cbb10.jpg", "channelphoto.jpg" - ) - ll = await ultroid_bot.upload_file(photo) - try: - await ultroid_bot( - EditPhotoRequest(int(channel), InputChatUploadedPhoto(ll)) - ) - except BaseException as er: - LOGS.exception(er) - os.remove(photo) - - -# customize assistant - - -async def customize(): - from .. import asst, udB, ultroid_bot - - rem = None - try: - chat_id = udB.get_key("LOG_CHANNEL") - if asst.me.photo: - return - LOGS.info("Customising Ur Assistant Bot in @BOTFATHER") - UL = f"@{asst.me.username}" - if not ultroid_bot.me.username: - sir = ultroid_bot.me.first_name - else: - sir = f"@{ultroid_bot.me.username}" - file = random.choice( - [ - "https://graph.org/file/92cd6dbd34b0d1d73a0da.jpg", - "https://graph.org/file/a97973ee0425b523cdc28.jpg", - "resources/extras/ultroid_assistant.jpg", - ] - ) - if not os.path.exists(file): - file, _ = await download_file(file, "profile.jpg") - rem = True - msg = await asst.send_message( - chat_id, "**Auto Customisation** Started on @Botfather" - ) - await asyncio.sleep(1) - await ultroid_bot.send_message("botfather", "/cancel") - await asyncio.sleep(1) - await ultroid_bot.send_message("botfather", "/setuserpic") - await asyncio.sleep(1) - isdone = (await ultroid_bot.get_messages("botfather", limit=1))[0].text - if isdone.startswith("Invalid bot"): - LOGS.info("Error while trying to customise assistant, skipping...") - return - await ultroid_bot.send_message("botfather", UL) - await asyncio.sleep(1) - await ultroid_bot.send_file("botfather", file) - await asyncio.sleep(2) - await ultroid_bot.send_message("botfather", "/setabouttext") - await asyncio.sleep(1) - await ultroid_bot.send_message("botfather", UL) - await asyncio.sleep(1) - await ultroid_bot.send_message( - "botfather", f"✨ Hello ✨!! I'm Assistant Bot of {sir}" - ) - await asyncio.sleep(2) - await ultroid_bot.send_message("botfather", "/setdescription") - await asyncio.sleep(1) - await ultroid_bot.send_message("botfather", UL) - await asyncio.sleep(1) - await ultroid_bot.send_message( - "botfather", - f"✨ Powerful Ultroid Assistant Bot ✨\n✨ Master ~ {sir} ✨\n\n✨ Powered By ~ @TeamUltroid ✨", - ) - await asyncio.sleep(2) - await msg.edit("Completed **Auto Customisation** at @BotFather.") - if rem: - os.remove(file) - LOGS.info("Customisation Done") - except Exception as e: - LOGS.exception(e) - - -async def plug(plugin_channels): - from .. import ultroid_bot - from .utils import load_addons - - if ultroid_bot._bot: - LOGS.info("Plugin Channels can't be used in 'BOTMODE'") - return - if os.path.exists("addons") and not os.path.exists("addons/.git"): - shutil.rmtree("addons") - if not os.path.exists("addons"): - os.mkdir("addons") - if not os.path.exists("addons/__init__.py"): - with open("addons/__init__.py", "w") as f: - f.write("from plugins import *\n\nbot = ultroid_bot") - LOGS.info("• Loading Plugins from Plugin Channel(s) •") - for chat in plugin_channels: - LOGS.info(f"{'•'*4} {chat}") - try: - async for x in ultroid_bot.iter_messages( - chat, search=".py", filter=InputMessagesFilterDocument, wait_time=10 - ): - plugin = "addons/" + x.file.name.replace("_", "-").replace("|", "-") - if not os.path.exists(plugin): - await asyncio.sleep(0.6) - if x.text == "#IGNORE": - continue - plugin = await x.download_media(plugin) - try: - load_addons(plugin) - except Exception as e: - LOGS.info(f"Ultroid - PLUGIN_CHANNEL - ERROR - {plugin}") - LOGS.exception(e) - os.remove(plugin) - except Exception as er: - LOGS.exception(er) - - -# some stuffs - - -async def fetch_ann(): - from .. import asst, udB - from ..fns.tools import async_searcher - - get_ = udB.get_key("OLDANN") or [] - chat_id = udB.get_key("LOG_CHANNEL") - - try: - updts = await async_searcher( - "https://ultroid-api.vercel.app/announcements", post=True, re_json=True - ) - for upt in updts: - key = list(upt.keys())[0] - if key not in get_: - cont = upt[key] - if isinstance(cont, dict) and cont.get("lang"): - if cont["lang"] != (udB.get_key("language") or "en"): - continue - cont = cont["msg"] - if isinstance(cont, str): - await asst.send_message(chat_id, cont) - elif isinstance(cont, dict) and cont.get("chat"): - await asst.forward_messages(chat_id, cont["msg_id"], cont["chat"]) - else: - LOGS.info(cont) - LOGS.info( - "Invalid Type of Announcement Detected!\nMake sure you are on latest version.." - ) - get_.append(key) - udB.set_key("OLDANN", get_) - except Exception as er: - LOGS.exception(er) - - -async def ready(): - from .. import asst, udB, ultroid_bot - - chat_id = udB.get_key("LOG_CHANNEL") - spam_sent = None - if not udB.get_key("INIT_DEPLOY"): # Detailed Message at Initial Deploy - MSG = """🎇 **Thanks for Deploying Ultroid Userbot!** -• Here, are the Some Basic stuff from, where you can Know, about its Usage.""" - PHOTO = "https://graph.org/file/54a917cc9dbb94733ea5f.jpg" - BTTS = Button.inline("• Click to Start •", "initft_2") - udB.set_key("INIT_DEPLOY", "Done") - else: - MSG = f"**Ultroid has been deployed!**\n➖➖➖➖➖➖➖➖➖➖\n**UserMode**: {inline_mention(ultroid_bot.me)}\n**Assistant**: @{asst.me.username}\n➖➖➖➖➖➖➖➖➖➖\n**Support**: @TeamUltroid\n➖➖➖➖➖➖➖➖➖➖" - BTTS, PHOTO = None, None - prev_spam = udB.get_key("LAST_UPDATE_LOG_SPAM") - if prev_spam: - try: - await ultroid_bot.delete_messages(chat_id, int(prev_spam)) - except Exception as E: - LOGS.info("Error while Deleting Previous Update Message :" + str(E)) - if await updater(): - BTTS = Button.inline("Update Available", "updtavail") - - try: - spam_sent = await asst.send_message(chat_id, MSG, file=PHOTO, buttons=BTTS) - except ValueError as e: - try: - await (await ultroid_bot.send_message(chat_id, str(e))).delete() - spam_sent = await asst.send_message(chat_id, MSG, file=PHOTO, buttons=BTTS) - except Exception as g: - LOGS.info(g) - except Exception as el: - LOGS.info(el) - try: - spam_sent = await ultroid_bot.send_message(chat_id, MSG) - except Exception as ef: - LOGS.exception(ef) - if spam_sent and not spam_sent.media: - udB.set_key("LAST_UPDATE_LOG_SPAM", spam_sent.id) - await fetch_ann() - - -async def WasItRestart(udb): - key = udb.get_key("_RESTART") - if not key: - return - from .. import asst, ultroid_bot - - try: - data = key.split("_") - who = asst if data[0] == "bot" else ultroid_bot - await who.edit_message( - int(data[1]), int(data[2]), "__Restarted Successfully.__" - ) - except Exception as er: - LOGS.exception(er) - udb.del_key("_RESTART") - - -def _version_changes(udb): - for _ in [ - "BOT_USERS", - "BOT_BLS", - "VC_SUDOS", - "SUDOS", - "CLEANCHAT", - "LOGUSERS", - "PLUGIN_CHANNEL", - "CH_SOURCE", - "CH_DESTINATION", - "BROADCAST", - ]: - key = udb.get_key(_) - if key and str(key)[0] != "[": - key = udb.get(_) - new_ = [ - int(z) if z.isdigit() or (z.startswith("-") and z[1:].isdigit()) else z - for z in key.split() - ] - udb.set_key(_, new_) - - -async def enable_inline(ultroid_bot, username): - bf = "BotFather" - await ultroid_bot.send_message(bf, "/setinline") - await asyncio.sleep(1) - await ultroid_bot.send_message(bf, f"@{username}") - await asyncio.sleep(1) - await ultroid_bot.send_message(bf, "Search") - await ultroid_bot.send_read_acknowledge(bf) diff --git a/pyUltroid/startup/loader.py b/pyUltroid/startup/loader.py deleted file mode 100644 index edf15a1d9f..0000000000 --- a/pyUltroid/startup/loader.py +++ /dev/null @@ -1,140 +0,0 @@ -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in -# . - -import os -import subprocess -import sys -from shutil import rmtree - -from decouple import config -from git import Repo - -from .. import * -from ..dB._core import HELP -from ..loader import Loader -from . import * -from .utils import load_addons - - -def _after_load(loader, module, plugin_name=""): - if not module or plugin_name.startswith("_"): - return - from strings import get_help - - if doc_ := get_help(plugin_name) or module.__doc__: - try: - doc = doc_.format(i=HNDLR) - except Exception as er: - loader._logger.exception(er) - loader._logger.info(f"Error in {plugin_name}: {module}") - return - if loader.key in HELP.keys(): - update_cmd = HELP[loader.key] - try: - update_cmd.update({plugin_name: doc}) - except BaseException as er: - loader._logger.exception(er) - else: - try: - HELP.update({loader.key: {plugin_name: doc}}) - except BaseException as em: - loader._logger.exception(em) - - -def load_other_plugins(addons=None, pmbot=None, manager=None, vcbot=None): - - # for official - _exclude = udB.get_key("EXCLUDE_OFFICIAL") or config("EXCLUDE_OFFICIAL", None) - _exclude = _exclude.split() if _exclude else [] - - # "INCLUDE_ONLY" was added to reduce Big List in "EXCLUDE_OFFICIAL" Plugin - _in_only = udB.get_key("INCLUDE_ONLY") or config("INCLUDE_ONLY", None) - _in_only = _in_only.split() if _in_only else [] - Loader().load(include=_in_only, exclude=_exclude, after_load=_after_load) - - # for assistant - if not USER_MODE and not udB.get_key("DISABLE_AST_PLUGINS"): - _ast_exc = ["pmbot"] - if _in_only and "games" not in _in_only: - _ast_exc.append("games") - Loader(path="assistant").load( - log=False, exclude=_ast_exc, after_load=_after_load - ) - - # for addons - if addons: - if url := udB.get_key("ADDONS_URL"): - subprocess.run(f"git clone -q {url} addons", shell=True) - if os.path.exists("addons") and not os.path.exists("addons/.git"): - rmtree("addons") - if not os.path.exists("addons"): - subprocess.run( - f"git clone -q -b {Repo().active_branch} https://github.com/TeamUltroid/UltroidAddons.git addons", - shell=True, - ) - else: - subprocess.run("cd addons && git pull -q && cd ..", shell=True) - - if not os.path.exists("addons"): - subprocess.run( - "git clone -q https://github.com/TeamUltroid/UltroidAddons.git addons", - shell=True, - ) - if os.path.exists("addons/addons.txt"): - # generally addons req already there so it won't take much time - # subprocess.run( - # "rm -rf /usr/local/lib/python3.*/site-packages/pip/_vendor/.wh*" - # ) - subprocess.run( - f"{sys.executable} -m pip install --no-cache-dir -q -r ./addons/addons.txt", - shell=True, - ) - - _exclude = udB.get_key("EXCLUDE_ADDONS") - _exclude = _exclude.split() if _exclude else [] - _in_only = udB.get_key("INCLUDE_ADDONS") - _in_only = _in_only.split() if _in_only else [] - - Loader(path="addons", key="Addons").load( - func=load_addons, - include=_in_only, - exclude=_exclude, - after_load=_after_load, - load_all=True, - ) - - if not USER_MODE: - # group manager - if manager: - Loader(path="assistant/manager", key="Group Manager").load() - - # chat via assistant - if pmbot: - Loader(path="assistant/pmbot.py").load(log=False) - - # vc bot - if vcbot and not vcClient._bot: - try: - import pytgcalls # ignore: pylint - - if os.path.exists("vcbot"): - if os.path.exists("vcbot/.git"): - subprocess.run("cd vcbot && git pull", shell=True) - else: - rmtree("vcbot") - if not os.path.exists("vcbot"): - subprocess.run( - "git clone https://github.com/TeamUltroid/VcBot vcbot", shell=True - ) - try: - if not os.path.exists("vcbot/downloads"): - os.mkdir("vcbot/downloads") - Loader(path="vcbot", key="VCBot").load(after_load=_after_load) - except FileNotFoundError as e: - LOGS.error(f"{e} Skipping VCBot Installation.") - except ModuleNotFoundError: - LOGS.error("'pytgcalls' not installed!\nSkipping loading of VCBOT.") diff --git a/pyUltroid/version.py b/pyUltroid/version.py deleted file mode 100644 index 8c7b646d77..0000000000 --- a/pyUltroid/version.py +++ /dev/null @@ -1,2 +0,0 @@ -__version__ = "2023.02.20" -ultroid_version = "0.8" diff --git a/requirements.txt b/requirements.txt index 9ca5b3894f..123f5dbe06 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,12 @@ # Important Requirements here. -https://github.com/New-dev0/Telethon/archive/platy.zip +requests +# https://github.com/TeamUltroid/Telethon/archive/ultroid.zip +telethon +https://github.com/New-dev0/Telethon-Patch/archive/main.zip python-decouple -python-dotenv +# telethon-patch +tgcrypto +enhancer +lottie +cryptography==3.4.8 diff --git a/resources/README.md b/resources/README.md new file mode 100644 index 0000000000..a93ada4274 --- /dev/null +++ b/resources/README.md @@ -0,0 +1,2 @@ +# `resources` +This directory contains various resource files, including images to render on various platforms for Ultroid. \ No newline at end of file diff --git a/resources/colorlist.txt b/resources/colorlist.txt deleted file mode 100644 index 6e3f3c3491..0000000000 --- a/resources/colorlist.txt +++ /dev/null @@ -1,148 +0,0 @@ -AliceBlue -AntiqueWhite -Aqua -Aquamarine -Azure -Beige -Bisque -Black -BlanchedAlmond -Blue -BlueViolet -Brown -BurlyWood -CadetBlue -Chartreuse -Chocolate -Coral -CornflowerBlue -Cornsilk -Crimson -Cyan -DarkBlue -DarkCyan -DarkGoldenRod -DarkGray -DarkGreen -DarkGrey -DarkKhaki -DarkMagenta -DarkOliveGreen -DarkOrange -DarkOrchid -DarkRed -DarkSalmon -DarkSeaGreen -DarkSlateBlue -DarkSlateGray -DarkSlateGrey -DarkTurquoise -DarkViolet -DeepPink -DeepSkyBlue -DimGray -DimGrey -DodgerBlue -FireBrick -FloralWhite -ForestGreen -Fuchsia -Gainsboro -GhostWhite -Gold -GoldenRod -Gray -Green -GreenYellow -Grey -HoneyDew -HotPink -IndianRed -Indigo -Ivory -Khaki -Lavender -LavenderBlush -LawnGreen -LemonChiffon -LightBlue -LightCoral -LightCyan -LightGoldenRodYellow -LightGray -LightGreen -LightGrey -LightPink -LightSalmon -LightSeaGreen -LightSkyBlue -LightSlateGray -LightSlateGrey -LightSteelBlue -LightYellow -Lime -LimeGreen -Linen -Magenta -Maroon -MediumAquaMarine -MediumBlue -MediumOrchid -MediumPurple -MediumSeaGreen -MediumSlateBlue -MediumSpringGreen -MediumTurquoise -MediumVioletRed -MidnightBlue -MintCream -MistyRose -Moccasin -NavajoWhite -Navy -OldLace -Olive -OliveDrab -Orange -OrangeRed -Orchid -PaleGoldenRod -PaleGreen -PaleTurquoise -PaleVioletRed -PapayaWhip -PeachPuff -Peru -Pink -Plum -PowderBlue -Purple -RebeccaPurple -Red -RosyBrown -RoyalBlue -SaddleBrown -Salmon -SandyBrown -SeaGreen -SeaShell -Sienna -Silver -SkyBlue -SlateBlue -SlateGray -SlateGrey -Snow -SpringGreen -SteelBlue -Tan -Teal -Thistle -Tomato -Turquoise -Violet -Wheat -White -WhiteSmoke -Yellow -YellowGreen \ No newline at end of file diff --git a/resources/startup/_termux.py b/resources/extras/_termux.py similarity index 84% rename from resources/startup/_termux.py rename to resources/extras/_termux.py index 6efe89cc65..efde4105d5 100644 --- a/resources/startup/_termux.py +++ b/resources/extras/_termux.py @@ -1,6 +1,6 @@ # /usr/bin/python3 # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2020-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # Please read the GNU Affero General Public License in @@ -10,7 +10,12 @@ from os import path, system from time import sleep -from colorama import Back, Fore, Style +try: + from colorama import Back, Fore, Style +except ModuleNotFoundError: + print("Installing colorama...") + system("pip install -q colorama") + from colorama import Back, Fore, Style # clear screen @@ -45,19 +50,19 @@ def clear(): COPYRIGHT = f"©️ TeamUltroid {datetime.now().year}" -HEADER = f"""{Fore.MAGENTA} +HEADER = f""" ╔╗ ╔╗╔╗ ╔╗ ╔╗ ║║ ║║║║ ╔╝╚╗ ║║ ║║ ║║║║ ╚╗╔╝╔═╗╔══╗╔╗╔═╝║ ║║ ║║║║ ║║ ║╔╝║╔╗║╠╣║╔╗║ ║╚═╝║║╚╗ ║╚╗║║ ║╚╝║║║║╚╝║ -╚═══╝╚═╝ ╚═╝╚╝ ╚══╝╚╝╚══╝\n{Fore.RESET} +╚═══╝╚═╝ ╚═╝╚╝ ╚══╝╚╝╚══╝\n """ INFO_TEXT = f""" {Fore.GREEN}# Important points to know. -{Fore.YELLOW}1. This script will just install basic requirements because of which some command whose requirements are missing won't work. You can view all optional requirements in (./resources/startup/optional-requirements.txt) +{Fore.YELLOW}1. This script will just install basic requirements because of which some command whose requirements are missing won't work. You can view all optional requirements in (./resources/extras/optional-requirements.txt) 2. You can install that requirement whenever you want with 'pip install' (a very basic python+bash knowledge is required.) @@ -91,7 +96,7 @@ def ask_and_wait(text, header: bool = False): def with_header(text): - return HEADER + "\n\n" + text + return Fore.MAGENTA + HEADER + Fore.RESET + "\n\n" + text def yes_no_apt(): @@ -149,13 +154,13 @@ def ask_and_wait_opt(): ) if yes_no_apt(): print(f"Installing {opt}...") - system(f"pip install {opt}") + system(f"pip install -q {opt}") else: print(f"{Fore.YELLOW}- Discarded {opt}.\n") elif strm == "i": names = " ".join(OPT_PACKAGES.keys()) print(f"{Fore.YELLOW}Installing all packages...") - system(f"pip install {names}") + system(f"pip install -q {names}") elif strm != "s": print("Invalid Input\n* Enter Again...") ask_and_wait_opt() @@ -181,15 +186,7 @@ def ask_make_env(): print( f""" -{Fore.BLACK}{Back.WHITE} _____________ - ▄▄ ▄▄ ▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄▄ -█ █ █ █ █ █ █ ▄ █ █ █ █ █ -█ █ █ █ █ █▄ ▄█ █ █ █ █ ▄ █ █ ▄ █ -█ █▄█ █ █ █ █ █ █▄▄█▄█ █ █ █ █ █ █ █ -█ █ █▄▄▄ █ █ █ ▄▄ █ █▄█ █ █ █▄█ █ -█ █ █ █ █ █ █ █ █ █ █ █ -█▄▄▄▄▄▄▄█▄▄▄▄▄▄▄█ █▄▄▄█ █▄▄▄█ █▄█▄▄▄▄▄▄▄█▄▄▄█▄▄▄▄▄▄█ -{Style.RESET_ALL} +{Fore.BLACK}{Back.WHITE}{HEADER}{Style.RESET_ALL} {Fore.GREEN}- ULTROID Termux Installation - The Main Aim of this script is to deploy Ultroid with basic requirements and save your phone resources. {Fore.RESET} @@ -208,7 +205,7 @@ def ask_make_env(): print(with_header("Installing Mandatory requirements...")) all_ = " ".join(MANDATORY_REQS) -system(f"pip install {all_}") +system(f"pip install -q {all_}") clear() print( @@ -230,7 +227,7 @@ def ask_make_env(): {Fore.YELLOW}# Installing other non mandatory requirements. (You can Install them, if you want command using them to work!){Fore.RESET} -{'- '.join(list(OPT_PACKAGES.keys()))} +{'\n- '.join(list(OPT_PACKAGES.keys()))} Enter [ A = Ask for each, I = Install all, S = Skip, E = Exit]""" ) @@ -242,7 +239,7 @@ def ask_make_env(): inp = input("").strip().lower() if inp in ["yes", "y"]: print(f"{Fore.GREEN}*Spoking the Magical Mantras*") - system("pip install coloredlogs") + system("pip install -q coloredlogs") else: print("Skipped!") @@ -251,9 +248,10 @@ def ask_make_env(): print(with_header("# Do you want to move toward creating .env file ? [y/N] ")) ask_make_env() +clear() print(with_header(f"\n{Fore.GREEN}You are all Done! 🥳")) sleep(0.2) -print(f"Use 'bash startup' to try running Ultroid.{Fore.RESET}") +print(f"Use './ultroid start' to try running Ultroid.{Fore.RESET}") sleep(0.5) print( "\nYou can head over to @UltroidSupportChat, if you get stuck somewhere, and need help." @@ -261,4 +259,4 @@ def ask_make_env(): sleep(0.5) print("\nMade with ❤️ by @TeamUltroid...") -system("pip3 uninstall -q colorama -y") +system("pip uninstall -q colorama -y") diff --git a/resources/extras/inline.jpg b/resources/extras/inline.jpg deleted file mode 100644 index 18fff739cd..0000000000 Binary files a/resources/extras/inline.jpg and /dev/null differ diff --git a/resources/startup/locals.py b/resources/extras/locals.py similarity index 82% rename from resources/startup/locals.py rename to resources/extras/locals.py index 2a89268ac9..aa826fc775 100644 --- a/resources/startup/locals.py +++ b/resources/extras/locals.py @@ -1,6 +1,6 @@ # /usr/bin/python3 # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2020-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # Please read the GNU Affero General Public License in @@ -21,7 +21,6 @@ def start(): - clear_screen() check_for_py() @@ -32,10 +31,7 @@ def start(): os.system("git clone https://github.com/TeamUltroid/Ultroid") print("\n\nDone") os.chdir("Ultroid") - clear_screen() - print(a) - print("\n\nLet's start!\n") - + print_with_clear(a, "\n\nLet's start!\n") # generate session if needed. sessionisneeded = input( "Do you want to generate a new session, or have an old session string? [generate/skip]", @@ -60,21 +56,20 @@ def start(): all_done = "# Ultroid Environment Variables.\n# Do not delete this file.\n\n" for i in varrs: all_done += do_input(i) - clear_screen() - print(a) - print("\n\nHere are the things you've entered.\nKindly check.") + print_with_clear(a, "\n\nHere are the things you've entered.\nKindly check.") print(all_done) isitdone = input("\n\nIs it all correct? [y/n]") if isitdone == "y" or isitdone != "n": - # https://github.com/TeamUltroid/Ultroid/blob/31b9eb1f4f8059e0ae66adb74cb6e8174df12eac/resources/startup/locals.py#L35 + # https://github.com/TeamUltroid/Ultroid/blob/31b9eb1f4f8059e0ae66adb74cb6e8174df12eac/resources/extras/locals.py#L35 f = open(".env", "w") f.write(all_done) else: print("Oh, let's redo these then.") start() - clear_screen() - print("\nCongrats. All done!\nTime to start the bot!") - print("\nInstalling requirements... This might take a while...") + print_with_clear( + "\nCongrats. All done!\nTime to start the bot!", + "\nInstalling requirements... This might take a while...", + ) os.system("pip3 install --no-cache-dir -r requirements.txt") ask = input( "Enter 'yes/y' to Install other requirements, required for local deployment." @@ -82,16 +77,20 @@ def start(): if ask.lower().startswith("y"): print("Started Installing...") os.system( - "pip3 install --no-cache-dir -r resources/startup/optional-requirements.txt" + "pip3 install --no-cache-dir -r resources/extras/optional-requirements.txt" ) else: print("Skipped!") - clear_screen() - print(a) - print("\nStarting Ultroid...") + print_with_clear(a, "\nStarting Ultroid...") os.system("sh startup") +def print_with_clear(arg0, arg1): + clear_screen() + print(arg0) + print(arg1) + + def do_input(var): val = input(f"Enter your {var}: ") return f"{var}={val}\n" @@ -127,7 +126,7 @@ def check_for_py(): def gen_session(): print("\nProcessing...") - # https://github.com/TeamUltroid/Ultroid/main/resources/startup/locals.py#L35 + # https://github.com/TeamUltroid/Ultroid/main/resources/extras/locals.py#L35 os.system("python3 resources/session/ssgen.py") diff --git a/resources/extras/logo_readme.jpg b/resources/extras/logo_readme.jpg deleted file mode 100644 index 891354e83f..0000000000 Binary files a/resources/extras/logo_readme.jpg and /dev/null differ diff --git a/resources/extras/redistut.md b/resources/extras/redistut.md deleted file mode 100644 index 62dab63e27..0000000000 --- a/resources/extras/redistut.md +++ /dev/null @@ -1,17 +0,0 @@ -# Tutorial To Get Redis DB URL and Password -![Redis](https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white) - -## Process For Creating DB :- -- Go To [Redis.com](Https://redis.com) and click "`Try Free`" in Top Right Corner. -- Fill All The Required Details Like email, first and last name, password, etc. -- Tick Below "I agree the corresponding...Privacy Policy." and Click "Get Started". -- Now Check Your Email, and click the "Activate Now" sent by redislabs via email. -- Now Login and Chose Free Plan in "Fixed Size" Area and Write any name in "Subscription Area". -- On the Next Page Write Database Name and click Activate. - -> Congrats! Your DB has been created 🥳 - -## Process For Getting DB Credentials:- -- Wait 5 mins after DB creation. -- Then There Would Be 2 Things Named "`Endpoint`" and "`Access Control & Security`". -- Copy Both Of Them and Paste Endpoint url in `REDIS_URI` and "Access ...Security" in `REDIS_PASSWORD`. diff --git a/resources/extras/teamultroid.jpg b/resources/extras/teamultroid.jpg deleted file mode 100644 index 1903ecf3a5..0000000000 Binary files a/resources/extras/teamultroid.jpg and /dev/null differ diff --git a/resources/extras/template.jpg b/resources/extras/template.jpg deleted file mode 100644 index 7b884031dc..0000000000 Binary files a/resources/extras/template.jpg and /dev/null differ diff --git a/resources/extras/ultroid.jpg b/resources/extras/ultroid.jpg deleted file mode 100644 index 3824b5e8de..0000000000 Binary files a/resources/extras/ultroid.jpg and /dev/null differ diff --git a/resources/extras/ultroid_assistant.jpg b/resources/extras/ultroid_assistant.jpg deleted file mode 100644 index 17744604e2..0000000000 Binary files a/resources/extras/ultroid_assistant.jpg and /dev/null differ diff --git a/resources/extras/ultroid_blank.png b/resources/extras/ultroid_blank.png deleted file mode 100644 index 5972e18ec8..0000000000 Binary files a/resources/extras/ultroid_blank.png and /dev/null differ diff --git a/resources/fonts/0.ttf b/resources/fonts/0.ttf deleted file mode 100644 index 00c56493df..0000000000 Binary files a/resources/fonts/0.ttf and /dev/null differ diff --git a/resources/fonts/1.ttf b/resources/fonts/1.ttf deleted file mode 100644 index 1ff7ebff03..0000000000 Binary files a/resources/fonts/1.ttf and /dev/null differ diff --git a/resources/fonts/10.ttf b/resources/fonts/10.ttf deleted file mode 100644 index 880a9d4fae..0000000000 Binary files a/resources/fonts/10.ttf and /dev/null differ diff --git a/resources/fonts/11.otf b/resources/fonts/11.otf deleted file mode 100644 index a7699afd42..0000000000 Binary files a/resources/fonts/11.otf and /dev/null differ diff --git a/resources/fonts/12.otf b/resources/fonts/12.otf deleted file mode 100644 index ed75711619..0000000000 Binary files a/resources/fonts/12.otf and /dev/null differ diff --git a/resources/fonts/2.ttf b/resources/fonts/2.ttf deleted file mode 100644 index 23d266d3d2..0000000000 Binary files a/resources/fonts/2.ttf and /dev/null differ diff --git a/resources/fonts/3.ttf b/resources/fonts/3.ttf deleted file mode 100644 index d86936fabc..0000000000 Binary files a/resources/fonts/3.ttf and /dev/null differ diff --git a/resources/fonts/4.ttf b/resources/fonts/4.ttf deleted file mode 100644 index 1fc959adbf..0000000000 Binary files a/resources/fonts/4.ttf and /dev/null differ diff --git a/resources/fonts/5.ttf b/resources/fonts/5.ttf deleted file mode 100644 index 91c8f91a69..0000000000 Binary files a/resources/fonts/5.ttf and /dev/null differ diff --git a/resources/fonts/6.ttf b/resources/fonts/6.ttf deleted file mode 100644 index 18f9aee08d..0000000000 Binary files a/resources/fonts/6.ttf and /dev/null differ diff --git a/resources/fonts/7.ttf b/resources/fonts/7.ttf deleted file mode 100644 index c9193c0498..0000000000 Binary files a/resources/fonts/7.ttf and /dev/null differ diff --git a/resources/fonts/8.ttf b/resources/fonts/8.ttf deleted file mode 100644 index ead147007c..0000000000 Binary files a/resources/fonts/8.ttf and /dev/null differ diff --git a/resources/fonts/9.ttf b/resources/fonts/9.ttf deleted file mode 100644 index cd994c29cf..0000000000 Binary files a/resources/fonts/9.ttf and /dev/null differ diff --git a/resources/fonts/DroidSansMono.ttf b/resources/fonts/DroidSansMono.ttf deleted file mode 100644 index b7bf5b4aa8..0000000000 Binary files a/resources/fonts/DroidSansMono.ttf and /dev/null differ diff --git a/resources/fonts/Quivira.otf b/resources/fonts/Quivira.otf deleted file mode 100644 index 8064cae278..0000000000 Binary files a/resources/fonts/Quivira.otf and /dev/null differ diff --git a/resources/fonts/Roboto-Italic.ttf b/resources/fonts/Roboto-Italic.ttf deleted file mode 100644 index f0f33dbdfa..0000000000 Binary files a/resources/fonts/Roboto-Italic.ttf and /dev/null differ diff --git a/resources/fonts/Roboto-Medium.ttf b/resources/fonts/Roboto-Medium.ttf deleted file mode 100644 index 8798341989..0000000000 Binary files a/resources/fonts/Roboto-Medium.ttf and /dev/null differ diff --git a/resources/fonts/Roboto-Regular.ttf b/resources/fonts/Roboto-Regular.ttf deleted file mode 100644 index 7d9a6c4c32..0000000000 Binary files a/resources/fonts/Roboto-Regular.ttf and /dev/null differ diff --git a/resources/fonts/assfont.ttf b/resources/fonts/assfont.ttf deleted file mode 100644 index 1070aacda9..0000000000 Binary files a/resources/fonts/assfont.ttf and /dev/null differ diff --git a/resources/fonts/default.ttf b/resources/fonts/default.ttf deleted file mode 100644 index 114e6c1968..0000000000 Binary files a/resources/fonts/default.ttf and /dev/null differ diff --git a/resources/session/ssgen.py b/resources/session/ssgen.py index 8c9f1ba9c7..341b2306e4 100644 --- a/resources/session/ssgen.py +++ b/resources/session/ssgen.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2020-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in @@ -55,11 +55,11 @@ def get_api_id_and_hash(): def telethon_session(): try: spinner("tele") - import telethon + x = "\bFound an existing installation of Telethon...\nSuccessfully Imported.\n\n" except ImportError: print("Installing Telethon...") - os.system("pip uninstall telethon -y && pip install -U telethon") + os.system("pip install -U telethon") x = "\bDone. Installed and imported Telethon." clear_screen() @@ -122,8 +122,6 @@ def pyro_session(): print("Installing Pyrogram...") os.system("pip install pyrogram tgcrypto") x = "\bDone. Installed and imported Pyrogram." - from pyrogram import Client - clear_screen() print(ULTROID) print(x) @@ -132,7 +130,7 @@ def pyro_session(): API_ID, API_HASH = get_api_id_and_hash() print("Enter phone number when asked.\n\n") try: - with Client(name="ultroid", api_id=API_ID, api_hash=API_HASH, in_memory=True) as pyro: + with Client(":memory:", api_id=API_ID, api_hash=API_HASH) as pyro: ss = pyro.export_session_string() pyro.send_message( "me", @@ -141,8 +139,10 @@ def pyro_session(): print("Session has been sent to your saved messages!") exit(0) except Exception as er: - print("Unexpected error occurred while creating session, make sure to validate your inputs.") - print(er) + print( + "Unexpected error occurred while creating session, make sure to validate your inputs." + ) + print(er) def main(): diff --git a/resources/startup/optional-requirements.txt b/resources/startup/optional-requirements.txt deleted file mode 100644 index a521454495..0000000000 --- a/resources/startup/optional-requirements.txt +++ /dev/null @@ -1,32 +0,0 @@ -# Required only for Local Deploys -# ------------------------------------------------------ # - -akinator -apscheduler -aiohttp -bs4 -enhancer>=0.3.4 -git+https://github.com/New-dev0/instagrapi.git@39df1b1#egg=instagrapi -git+https://github.com/buddhhu/img2html.git@c44170d#egg=img2html -heroku3 -gitpython -google-api-python-client -htmlwebshot -lottie -lxml -numpy>=1.21.2 -oauth2client -opencv-python-headless -pillow>=7.0.0 -profanitydetector -psutil -pypdf2>=1.26.0 -pytz -qrcode -requests -tabulate -git+https://github.com/xditya/telegraph.git@41fd800#egg=telegraph -tgcrypto -youtube-search-python -yt-dlp -# -------------------------------------------------------# diff --git a/resources/startup/termux.sh b/resources/startup/termux.sh deleted file mode 100644 index 4d608e46bd..0000000000 --- a/resources/startup/termux.sh +++ /dev/null @@ -1,19 +0,0 @@ -printf "Updating System..\n\n" -pkg update -y -apt update -apt upgrade -y - -python_not_installed="$(python -c 'exit()')" - -# Install Python if n0t installed.. -if [ python_not_installed ] -then - printf "Installing Python..\nThis may take some long...\n" - pkg install python3 -y -fi - -printf "*Putting some magical effect...*" -pip install -q colorama - -printf "Running up Installation tool.\n" -python resources/startup/_termux.py diff --git a/resources/ultroid.webp b/resources/ultroid.webp new file mode 100644 index 0000000000..6cf9cc194f Binary files /dev/null and b/resources/ultroid.webp differ diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000000..544d75abe5 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,49 @@ + +## Scripts + +This directory contains the various shellscripts for Ultroid.
    Do not run them directly, instead, use the ```ultroid``` file with arguments. + +## Shell scripts +* `installer.sh` - Script to install Ultroid +* `install-termux` - Script to install Ultroid in termux +* `session` - Script to generator String Session +* `startup` - Script to start Ultroid + +## `installer.sh` +Installs Ultroid in machine. Use custom flags to define installation configs or don't provide any flags to use default configs + +```bash +./ultroid install [Options] +``` +### Options +``` + --help: Show message containing usage of the script + --dir: Install Ultroid in a custom or specified directory, Default is current directory/Ultroid + --branch: Clone custom or specificed Ultroid repo branch like main or dev, Default is main + --env-file: Path to .env file, required only if using any env file other than .env + --no-root: Install Ultroid without root access +``` + +## `install-termux` +```bash +./ultroid termux +``` +Installs Ultroid in termux. + +## `session` +Generates string session of telethon or pyrogram. +```bash +./ultroid session +``` + +## `start` +Starts the bot. +```bash +./ultroid start [Options] +``` + +### Options +``` + --help: Show the help message + --http-server: Start a http server serving files over http, default port: 8000 +``` diff --git a/scripts/unix/install-termux b/scripts/unix/install-termux new file mode 100755 index 0000000000..c95c454e74 --- /dev/null +++ b/scripts/unix/install-termux @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# Ultroid - UserBot +# Copyright (C) 2020-2023 TeamUltroid +# +# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +# PLease read the GNU Affero General Public License in . + +if [ -d "resources" ] +then + echo "Current directory Identified.." +else + apt install git -y + git clone https://github.com/TeamUltroid/Ultroid + cd Ultroid +fi + +printf "Updating System..\n\n" +pkg update -y +apt update +apt upgrade -y + +python_not_installed="$(python -c 'exit()')" + +# Install Python if n0t installed.. +if [ python_not_installed ] +then + printf "Installing Python..\nThis may take some long...\n" + pkg install python3 -y +fi + +printf "*Putting some magical effect...*" +pip install -q colorama + +printf "Running up Installation tool.\n" +python resources/extras/_termux.py diff --git a/installer.sh b/scripts/unix/installer old mode 100644 new mode 100755 similarity index 51% rename from installer.sh rename to scripts/unix/installer index 5c2b8f00f3..5eb1869a45 --- a/installer.sh +++ b/scripts/unix/installer @@ -3,12 +3,12 @@ REPO="https://github.com/TeamUltroid/Ultroid.git" CURRENT_DIR="$(pwd)" ENV_FILE_PATH=".env" -DIR="/root/TeamUltroid" +DIR="$CURRENT_DIR/Ultroid" while [ $# -gt 0 ]; do case "$1" in --dir=*) - DIR="${1#*=}" || DIR="/root/TeamUltroid" + CUSTOM_DIR="${1#*=}" ;; --branch=*) BRANCH="${1#*=}" || BRANCH="main" @@ -17,7 +17,7 @@ while [ $# -gt 0 ]; do ENV_FILE_PATH="${1#*=}" || ENV_FILE_PATH=".env" ;; --no-root) - NO_ROOT=true + NO_ROOT="true" ;; *) echo "Unknown parameter passed: $1" @@ -29,9 +29,25 @@ done check_dependencies() { # check if debian - echo "Checking dependencies..." + echo -e "\nChecking dependencies..." # read file with root access - if ! [[ $(ls -l "/etc/sudoers" | cut -d " " -f1) =~ "r" ]]; then + # check NO_ROOT + if [[ $NO_ROOT == "true" ]]; then + echo -e "\nRoot access not found. Checking if dependencies are installed." >&2 + if ! [ -x "$(command -v python3)" ] || ! [ -x "$(command -v python)" ]; then + echo -e "Python3 isn't installed. Please install python3.8 or higher to run this bot." >&2 + exit 1 + fi + if [ $(python3 -c "import sys; print(sys.version_info[1])") -lt 8 ] || [ $(python -c "import sys; print(sys.version_info[1])") -lt 8 ]; then + echo -e "Python 3.8 or higher is required to run this bot." >&2 + exit 1 + fi + # check if any of ffmpeg, mediainfo, neofetch, git is not installed + if ! command -v ffmpeg &>/dev/null || ! command -v mediainfo &>/dev/null || ! command -v neofetch &>/dev/null || ! command -v git &>/dev/null; then + echo -e "Some dependencies aren't installed. Please install ffmpeg, mediainfo, neofetch and git to run this bot." >&2 + exit 1 + fi + elif ! [[ $(ls -l "/etc/sudoers" | cut -d " " -f1) =~ "r" ]]; then # check dependencies if installed echo -e "Root access not found. Checking if dependencies are installed." >&2 if ! [ -x "$(command -v python3)" ] || ! [ -x "$(command -v python)" ]; then @@ -48,20 +64,61 @@ check_dependencies() { exit 1 fi fi - if [ -x "$(command -v apt-get)" ]; then - echo -e "Installing dependencies..." - # check if any of ffmpeg, mediainfo, neofetch, git is not installed via dpkg - if dpkg -l | grep -q ffmpeg || dpkg -l | grep -q mediainfo || dpkg -l | grep -q neofetch || dpkg -l | grep -q git; then - sudo apt-get -qq -o=Dpkg::Use-Pty=0 update - sudo apt-get install -qq -o=Dpkg::Use-Pty=0 python3 python3-pip ffmpeg mediainfo neofetch git -y - fi - elif [ -x "$(command -v pacman)" ]; then - echo -e "Installing dependencies..." + if [[ $machine == "Linux" ]]; then + if [ -x "$(command -v apt-get)" ]; then + echo -e "\nInstalling dependencies..." + # check if any of ffmpeg, mediainfo, neofetch, git is not installed via dpkg + if dpkg -l | grep -q ffmpeg || dpkg -l | grep -q mediainfo || dpkg -l | grep -q neofetch || dpkg -l | grep -q git; then + sudo apt-get -qq -o=Dpkg::Use-Pty=0 update + sudo apt-get install -qq -o=Dpkg::Use-Pty=0 python3 python3-pip ffmpeg mediainfo neofetch git -y + fi + elif [ -x "$(command -v pacman)" ]; then + echo -e "\nInstalling dependencies..." + if pacman -Q | grep -q ffmpeg || pacman -Q | grep -q mediainfo || pacman -Q | grep -q neofetch || pacman -Q | grep -q git; then + sudo pacman -Sy python python-pip git ffmpeg mediainfo neofetch --noconfirm + fi + elif [ -x "$(command -v dnf)" ]; then + echo -e "\nInstalling dependencies..." + if dnf list installed | grep -q ffmpeg || dnf list installed | grep -q mediainfo || dnf list installed | grep -q neofetch || dnf list installed | grep -q git; then + sudo dnf install python3 python3-pip ffmpeg mediainfo neofetch git -y + fi + elif [ -x "$(command -v yum)" ]; then + echo -e "\nInstalling dependencies..." + if yum list installed | grep -q ffmpeg || yum list installed | grep -q mediainfo || yum list installed | grep -q neofetch || yum list installed | grep -q git; then + sudo yum install python3 python3-pip ffmpeg mediainfo neofetch git -y + fi + elif [ -x "$(command -v zypper)" ]; then + echo -e "\nInstalling dependencies..." + if zypper search -i | grep -q ffmpeg || zypper search -i | grep -q mediainfo || zypper search -i | grep -q neofetch || zypper search -i | grep -q git; then + sudo zypper install python3 python3-pip ffmpeg mediainfo neofetch git -y + fi + elif [ -x "$(command -v apk)" ]; then + echo -e "\nInstalling dependencies..." + if apk info | grep -q ffmpeg || apk info | grep -q mediainfo || apk info | grep -q neofetch || apk info | grep -q git; then + sudo apk add python3 python3-pip ffmpeg mediainfo neofetch git + fi + fi + elif [[ $machine == "Darwin" ]]; then + if ! [ -x "$(command -v brew)" ]; then + echo -e "Homebrew isn't installed. Please install homebrew to run this bot." >&2 + exit 1 + fi + echo -e "\nInstalling dependencies..." + if brew list | grep -q ffmpeg || brew list | grep -q mediainfo || brew list | grep -q neofetch || brew list | grep -q git; then + brew install python ffmpeg mediainfo neofetch git + fi + elif [[ $machine == "MinGw" ]]; then + echo -e "\nInstalling dependencies..." if pacman -Q | grep -q ffmpeg || pacman -Q | grep -q mediainfo || pacman -Q | grep -q neofetch || pacman -Q | grep -q git; then - sudo pacman -Sy python python-pip git ffmpeg mediainfo neofetch --noconfirm + pacman -Sy python python-pip git ffmpeg mediainfo neofetch --noconfirm + fi + elif [[ $machine == "Cygwin" ]]; then + echo -e "\nInstalling dependencies..." + if pacman -Q | grep -q ffmpeg || pacman -Q | grep -q mediainfo || pacman -Q | grep -q neofetch || pacman -Q | grep -q git; then + pacman -Sy python python-pip git ffmpeg mediainfo neofetch --noconfirm fi else - echo -e "Unknown OS. Checking if dependecies are installed" >&2 + echo -e "$machine isn't supported. Please install ffmpeg, mediainfo, neofetch and git to run this bot." >&2 if ! [ -x "$(command -v python3)" ] || ! [ -x "$(command -v python)" ]; then echo -e "Python3 isn't installed. Please install python3.8 or higher to run this bot." >&2 exit 1 @@ -99,7 +156,6 @@ check_python() { clone_repo() { # check if pyultroid, startup, plugins folders exist - cd $DIR if [ -d $DIR ]; then if [ -d $DIR/.git ]; then echo -e "Updating Ultroid ${BRANCH}... " @@ -140,21 +196,13 @@ clone_repo() { install_requirements() { pip3 install -q --upgrade pip - echo -e "\n\nInstalling requirements... " + echo -e "\nInstalling requirements... " pip3 install -q --no-cache-dir -r $DIR/requirements.txt pip3 install -q -r $DIR/resources/startup/optional-requirements.txt } -railways_dep() { - if [ $RAILWAY_STATIC_URL ]; then - echo -e "Installing YouTube dependency... " - pip3 install -q yt-dlp - fi -} - misc_install() { - if [ $SETUP_PLAYWRIGHT ] - then + if [ $SETUP_PLAYWRIGHT ]; then echo -e "Installing playwright." pip3 install playwright playwright install @@ -170,12 +218,12 @@ misc_install() { echo -e "Cloning VCBOT.." git clone https://github.com/TeamUltroid/VcBot $DIR/vcbot fi - pip3 install pytgcalls==3.0.0.dev23 && pip3 install av -q --no-binary av + pip3 install pytgcalls >=3.0.0.dev21 && pip3 install av -q --no-binary av fi } dep_install() { - echo -e "\n\nInstalling DB Requirement..." + echo -e "\nInstalling DB Requirement..." if [ $MONGO_URI ]; then echo -e " Installing MongoDB Requirements..." pip3 install -q pymongo[srv] @@ -189,12 +237,20 @@ dep_install() { } main() { - echo -e "Starting Ultroid Setup..." - if [ -d "pyUltroid" ] && [ -d "resources" ] && [ -d "plugins" ]; then - DIR=$CURRENT_DIR + if [[ $machine == UNKNOWN* ]]; then + echo -e "Please run this script on Linux or Mac or MinGW(or Git Bash for windows) or Cygwin." + exit 1 + fi + if [ $CUSTOM_DIR ]; then + DIR=$CUSTOM_DIR + echo -e "Using custom directory: $DIR" + elif ! [ $CUSTOM_DIR ]; then + if [ -d "core" ] && [ -d "database" ] && [ -d "utilities" ]; then + DIR=$CURRENT_DIR + echo $DIR + fi fi - if [ -f $ENV_FILE_PATH ] - then + if [ -f $ENV_FILE_PATH ]; then set -a source <(cat $ENV_FILE_PATH | sed -e '/^#/d;/^\s*$/d' -e "s/'/'\\\''/g" -e "s/=\(.*\)/='\1'/g") set +a @@ -202,40 +258,38 @@ main() { fi (check_dependencies) (check_python) - (clone_repo) + #(clone_repo) (install_requirements) - (railways_dep) (dep_install) (misc_install) - echo -e "\n\nSetup Completed." + echo -e "\nInstallation Completed." } +echo -e "\nStarting Ultroid Setup..." +unameOut="$(uname -s)" +case "${unameOut}" in +Linux*) machine=Linux ;; +Darwin*) machine=Mac ;; +CYGWIN*) machine=Cygwin ;; +MINGW*) machine=MinGw ;; +*) machine="UNKNOWN:${unameOut}" ;; +esac +echo -e "\nDetected OS: $machine" + if [ $NO_ROOT ]; then - echo -e "Running with non root" + echo -e "\nInstalling without root." main - return 0 + exit 0 elif [ -t 0 ]; then - unameOut="$(uname -s)" - case "${unameOut}" in - Linux*) machine=Linux;; - Darwin*) machine=Mac;; - CYGWIN*) machine=Cygwin;; - MINGW*) machine=MinGw;; - *) machine="UNKNOWN:${unameOut}" - esac - if machine != "Linux"; then - echo -e "This script is only for Linux. Please use the Windows installer." - exit 1 - fi # check if sudo is installed if ! command -v sudo &>/dev/null; then - echo -e "Sudo isn't installed. Please install sudo to run this bot." + echo -e "\nSudo isn't installed. Please install sudo or run with --no-root to install Ultroid." exit 1 fi - sudo echo "Sudo permission granted." + sudo echo "\nSudo permission granted." main else - echo "Not an interactive terminal, skipping sudo." + echo "\nSkipping root." # run main function main -fi +fi \ No newline at end of file diff --git a/resources/session/session.sh b/scripts/unix/session old mode 100644 new mode 100755 similarity index 96% rename from resources/session/session.sh rename to scripts/unix/session index 00e9c5f421..05de0841e8 --- a/resources/session/session.sh +++ b/scripts/unix/session @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid +# Copyright (C) 2020-2023 TeamUltroid # # This file is a part of < https://github.com/TeamUltroid/Ultroid/ > # PLease read the GNU Affero General Public License in . diff --git a/startup b/scripts/unix/startup old mode 100644 new mode 100755 similarity index 67% rename from startup rename to scripts/unix/startup index 7a67cf141a..4888088502 --- a/startup +++ b/scripts/unix/startup @@ -15,5 +15,10 @@ echo " Visit @TheUltroid for updates!! " +# check if --no-http-server is passed +if [ "$1" == "--http-server" ]; then + # start the http server + wget https://gist.githubusercontent.com/mauler/593caee043f5fe4623732b4db5145a82/raw/972eb768159f0324d12d5d52b67b8e2841f4da73/http_server_auth.py -O /opt/server.py && python3 /opt/server.py -u admin -p pass -d . -b 0.0.0.0 & +fi if [ -f .env ] ; then set -o allexport; source .env; set +o allexport ; fi -if [ $SESSION1 ] ; then wget https://gist.github.com/1Danish-00/6554f034549197e5824972b01f631e0c/raw/main.py && python3 main.py ; else python3 -m pyUltroid ; fi +if [ $SESSION1 ] ; then wget https://gist.github.com/1Danish-00/6554f034549197e5824972b01f631e0c/raw/main.py && python3 main.py ; else python3 -m core ; fi \ No newline at end of file diff --git a/scripts/windows/session.bat b/scripts/windows/session.bat new file mode 100644 index 0000000000..1a030475e5 --- /dev/null +++ b/scripts/windows/session.bat @@ -0,0 +1,28 @@ +:: Ultroid - UserBot +:: Copyright (C) 2020-2023 TeamUltroid +:: +:: This file is a part of https://github.com/TeamUltroid/Ultroid/ +:: PLease read the GNU Affero General Public License in https://www.github.com/TeamUltroid/Ultroid/blob/main/LICENSE/. + +@echo off +cls +::: _ _ _ _ _ _ +::: | | | | | | (_) | | +::: | | | | | |_ _ __ ___ _ __| | +::: | | | | | __| '__/ _ \| |/ _ | +::: | |__| | | |_| | | (_) | | (_| | +::: \____/|_|\__|_| \___/|_|\__,_| +for /f "delims=: tokens=*" %%A in ('findstr /b ::: "%~f0"') do @echo(%%A + +echo Starting dependency installation in $sec seconds... + +echo Installing Dependencies. +if exist resources/session/ssgen.py goto sessionStart +echo Fetching ssgen.py from GitHub... +curl https://raw.githubusercontent.com/TeamUltroid/Ultroid/main/resources/session/ssgen.py -o resources/session/ssgen.py + +:sessionStart +cls +python resources/session/ssgen.py + +exit /b 1 \ No newline at end of file diff --git a/scripts/windows/startup.bat b/scripts/windows/startup.bat new file mode 100644 index 0000000000..73181d9db9 --- /dev/null +++ b/scripts/windows/startup.bat @@ -0,0 +1,29 @@ +::!/usr/bin/env bash +:: Ultroid - UserBot +:: Copyright (C) 2021-2022 TeamUltroid +:: +:: This file is a part of < https://github.com/TeamUltroid/Ultroid/ > +:: PLease read the GNU Affero General Public License in . + +@echo off + +::: _ _ _ _ _ _ +::: | | | | | | (_) | | +::: | | | | | |_ _ __ ___ _ __| | +::: | | | | | __| '__/ _ \| |/ _ | +::: | |__| | | |_| | | (_) | | (_| | +::: \____/|_|\__|_| \___/|_|\__,_| +::: +::: Visit @TheUltroid for updates!! + +for /f "delims=: tokens=*" %%A in ('findstr /b ::: "%~f0"') do @echo(%%A + +pip show telethon >nul 2>&1 || goto install + +:install +pip install -r requirements.txt +pip install -r resources/extras/optional-requirements.txt +echo Installed all dependencies +echo Starting Ultroid. + +python -m core \ No newline at end of file diff --git a/sessiongen b/sessiongen deleted file mode 100644 index 5cb46e24de..0000000000 --- a/sessiongen +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env bash -# Ultroid - UserBot -# Copyright (C) 2021-2022 TeamUltroid -# -# This file is a part of < https://github.com/TeamUltroid/Ultroid/ > -# PLease read the GNU Affero General Public License in . - -bash resources/session/session.sh diff --git a/strings/__init__.py b/strings/__init__.py deleted file mode 100644 index 30e79706b4..0000000000 --- a/strings/__init__.py +++ /dev/null @@ -1,82 +0,0 @@ -import os -import sys -from glob import glob -from typing import Any, Dict, List, Union - -from pyUltroid import * -from pyUltroid.fns.tools import translate - -try: - from yaml import safe_load -except ModuleNotFoundError: - from pyUltroid.fns.tools import safe_load - -ULTConfig.lang = udB.get_key("language") or os.getenv("LANGUAGE", "en") - -languages = {} -PATH = "strings/strings/{}.yml" - - -def load(file): - if not file.endswith(".yml"): - return - elif not os.path.exists(file): - file = PATH.format("en") - code = file.split("/")[-1].split("\\")[-1][:-4] - try: - languages[code] = safe_load( - open(file, encoding="UTF-8"), - ) - except Exception as er: - LOGS.info(f"Error in {file[:-4]} language file") - LOGS.exception(er) - - -load(PATH.format(ULTConfig.lang)) - - -def get_string(key: str, _res: bool = True) -> Any: - lang = ULTConfig.lang or "en" - try: - return languages[lang][key] - except KeyError: - try: - en_ = languages["en"][key] - tr = translate(en_, lang_tgt=lang).replace("\ N", "\n") - if en_.count("{}") != tr.count("{}"): - tr = en_ - if languages.get(lang): - languages[lang][key] = tr - else: - languages.update({lang: {key: tr}}) - return tr - except KeyError: - if not _res: - return - return f"Warning: could not load any string with the key `{key}`" - except TypeError: - pass - except Exception as er: - LOGS.exception(er) - if not _res: - return None - return languages["en"].get(key) or f"Failed to load language string '{key}'" - - -def get_help(key): - doc = get_string(f"help_{key}", _res=False) - if doc: - return get_string("cmda") + doc - - -def get_languages() -> Dict[str, Union[str, List[str]]]: - for file in glob("strings/strings/*yml"): - load(file) - return { - code: { - "name": languages[code]["name"], - "natively": languages[code]["natively"], - "authors": languages[code]["authors"], - } - for code in languages - } diff --git a/strings/strings/ar.yml b/strings/strings/ar.yml deleted file mode 100644 index 15cb5d9869..0000000000 --- a/strings/strings/ar.yml +++ /dev/null @@ -1,599 +0,0 @@ -name: Arabic -natively: العربية - -authors: - - klanrali - - memtma - -# commons -com_1: "`جـاري المعالجه...`" -com_2: "`جـاري البحث...`" -com_3: "`ادخال غير صحيح`" -com_4: "`ملف وسائط غير مدعوم..`" -com_5: "جاري التنزيل..." -com_6: "جاري الرفع..." -com_7: "`حدث خطأ.`" - -# user logs -userlogs_1: "رقم تعريف المجموعة الذي قمت بضبطه في سجل المنشن غير صحيح ، من فضلك قم بتصحيحه" -userlogs_2: "قم بإضافتي لمجوعة سجل المنشن لتحصل علي السجلات" -userlogs_3: "مغادرة المجموعة" -userlogs_4: "البوت المساعد لا يمكنه ارسال الرسائل في المجموعة.\nقم باضافته لتحصل علي السجلات.." -userlogs_5: "غادر `{}`" - -# chat actions -can_1: "#مستخدم_محظور انضم.\n\n**المستخدم** : {}\n**سبب الحظر**: {}\n\n`تم حظره.`" -can_2: "∆ #تغير_اسم_المستخدم\n\n@{} تم تغير اسم المستخدم الي @{}" -can_3: "∆ #تغير_اسم_المستخدم\n\n{} قام بحذف اسم المستخدم الخاص به. (@{})" -can_4: "∆ #تغير_اسم_المستخدم\n\n{}'s اسم المستخدم الجديد --> @{}" - -# help -help_1: "`{}` عـذرا ليس صالحآ يـوجد هنـاك خطأ!" -help_2: "عذرا لم يستجيب البوت .\nارسل امر اعاده تشغيل للأفضليه `{}restart`" -help_3: "`يرجى تشغيل وضع الاونلاين المباشر من خلال بوت فاذر` @Botfather." -help_4: "• اضافات" -help_5: "اضافات اخري •" -help_6: "••المحادثات الصوتية" -help_7: "اضافات انلاين••" -help_8: "⚙️ ادوات المالك" -help_9: "الاعدادات ⚙️" -help_10: "••اغلاق••" -help_11: "اسم الإضافة-{}\n\n✘ الاوامر المتاحة -\n\n" -help_12: "المكالمة الصوتية غير فعالة!" -help_13: "قم بارسال '{}setdb ADDONS True' لتحميل الاضافات الرسمية" - -# admintools -adm_1: "`لم استطع ان اتعرف عليه!`" -adm_2: "`حسنا.. اعتقد اني ليس لدي اي حقوق هنا!`" -adm_3: "`قم بإرسال الوقت ايضا..`" -pro_1: "`قم بالرد علي مستخدم لترقيته!`" -pro_2: "{} `الان مسؤول في مجموعة {} ولقبه {}.`" -de_1: "`قم بالرد علي مستخدم لازالة ترقيته!`" -de_2: "{} `لم يعد مسؤول في {}`" -ban_1: "`قم بالرد علي مستخدم او قم بوضع اسم المستخدم الخاص به لحظره!`" -ban_2: " `هاها، لا استطيع حظر مطوري 😂`" -ban_3: "`ليس لدي حقوق حظر المستخدمين.`" -ban_4: "{} **تم حظره بواسطة** {} **في** `{}`" -ban_5: "\n**السبب**: `{}`" -tban_1: "`قم بالرد علي احد او قم بارسال رقمه التعريفي...`" -tban_2: "`تم حظر` {} `بنجاح في {} لمدة {}`" -unban_1: "`قم بالرد على مستخدم او ارسل اسم مستخدم لإلغاء حظره!`" -unban_2: "`ليس لدي حقوق لإلغاء حظر المستخدم.`" -unban_3: "{} **تم الغاء حظره بواسطة** {} **في** `{}`" -kick_1: "`ليس لدي حقوق لطرد مستخدم.`" -kick_2: " `هاها, لا يمكنني طرد مطوري`😂" -kick_3: "`لا يمكنني طرده ابدا...`" -kick_4: "{} **تم طرده بواسطة** {} **في** `{}`" -pin_1: "`قم بالرد علي رسالة لتثبيتها!`" -pinned_1: "لم يتم العثور على رسالة مثبتة!" -pinned_2: "الرسالة المثبتة في هذه المجموعة هي [here]({})." -unpin_1: "اما ان تقوم بالرد على رسالة, او استخدم `{}unpin all`" -listpin_1: "لا يوجد رساله مثبتة في هذه المجموعة!" -purge_1: "`قم بالرد علي رسالة لبدأ الحذف من عندها.`" -purgeall_1: "`قم بالرد علي رسالة احدهم للحذف.`" -purgeall_2: "تم حذف جميع رسائل {} بنجاح" - -# autopic -autopic_1: "حسنا هيا اعطني بعض النصوص .." -autopic_2: "عذرا لايوجد نتائج للبحث لـ `{}`" -autopic_3: " حصلت على بعض من النتائج `{}` التي تتعلق في بحثك !\nجاري بدء تشغيل التلقائي !" - -# inline -inline_1: "[ألترويد للمساعدة](t.me/UltroidSupportChat)\n\n\n**قائمه المساعدة {}.\n\n -الأضافات ~ {}**" -inline_2: "[ألترويد للمساعدة](t.me/UltroidSupportChat)\n\n**قائمه المساعدة {}.\n\n -الاضافات ~ {}**" -inline_3: "[ألترويد للمساعدة](t.me/UltroidSupportChat)\n\n\n**قائمه المساعدة {}.\n\n -الاضافات ~ {}\n\n -اذهب واضف `الأضافات` متنوع مع القيمة.**" -inline_4: "** البـوت {}\n\n القـائمـه الرئـيسيـة \n\n الأضـافات ~ {}\n الأضـافات ~ {}\n جـميع التعلـيقات ~ {}**" -inline_5: "**┇ تـــم غــلـق الــقــائـــمــة ✅**" - -# tagnotif -tagnot_1: "{} ┇قــام بــعــمــل تــــاك لــك ⤴️ فــي {}\n\n```{}```\n\n[📨Message📨]({})" -tagnot_2: "{} ┇قــام بــعــمــل تــــاك لــك ⤴️ فــي {}\n\n [📨Message📨]({})" - -# whisper -wspr_1: "@{} ┇رســالــة ســريــة لــك 📩.\n┇قــم بــحــذف رســالــتــك بــعــد إن تــم قــرائــتــهــا ❗️.\n┇وإلا لــن يــتــم تــحــديــث الــرســالــة التــالــيــة ⚠️." -wspr_2: "┇تــم حــذف الــرســالــة ✅" -wspr_3: "اضف رقم تعريفي او اسم مستخدم ايضا" -wspr_4: "المستخدم {} غير موجود\n ابحث مجددا" -wspr_5: "لا يمكنك فعل هذا" - -# afk -afk_1: "`┇ لــم يــعــد نــشــط ! 📵\n\n -Was away for ~ {}`" -afk_2: "#AFK\nSet AFK mode to False.\nWas AFK for {}`" -afk_3: "┇لــســتُ نــشــطــاً حــالــيــاً 💤.\nLast seen {} ago.`\n\n**Reason:** `{}`" -afk_4: "`┇لــســتُ نــشــطــاً حــالــيــاً 💤.\n\nLast seen {} ago.`" -afk_5: "`┇جــاري الــغــاء النــشــاط 💤.`\n\n**Reason:** `{}`" -afk_6: "┇جــاري الــغــاء النــشــاط 💤." - -# bot -alive_1: "**🤖┇بــوت مــســتــخــدم ULTROID 🔱...**\n\n -**{}**\n\n -┏━━━━━━━━━━━━━━━━━━━━━\n -┣ **┇المــالــك ⬺** - `{}`\n -┣ **┇الإصــدار ⬺** - `{}`\n -┣ **┇مــدة الــتــشــغــيــل ⬺** - `{}`\n -┣ **┇بــايــثــون ⬺** - `{}`\n -┣ **┇تــلــيــثــون ⬺** - `{}`\n -┣ **┇الــفــرع ⬺** - `{}`\n -┗━━━━━━━━━━━━━━━━━━━━━" -log: "**┇هــيــروكــو** ســجــلات ULTROID 🔱 .\nتــلــصــق [هــنــا ]({}) أيــضــاً!" -ping: "**Pong !!** `{}ms`\n**┇وقـــت الــتــشــغــيــل ** - `{}`" -usage: "**⚙️ Dyno إســتــعــمــال الــ ⚙️**:\n\n - -> `Dyno إســتــعــمــال الـ for` **{}**:\n - • `{}`**h** `{}`**m** -**|** [`{}`**%**]\n\n - -> `┇حــصــة الــ Dyno المـتـبـقـيـة هـذا الـشـهـر`:\n - • `{}`**h** `{}`**m** -**|** [`{}`**%**]\n\n -**┇المــســاحــة الــكــلــيــة لـلـقــرص - {}\n\n** -┇الــمــســتــخــدم- {} الــخــالــيــة - {}\n\n -**📊┇الــبــيــانــات الــمــســتــخــدمــة📊\n\nUpload- {}\nDown- {}\n\n** -**CPU- {}%\nRAM- {}%\nDISK- {}%**" -shutdown: "┇الـى الـلـقــاء 👋 {}.\n`┇يــتــم الإطــفــاء ...🚫`" - -# broadcast -bd_1: "`┇يــتــم الاضــافــة الــى قــاعــدة الــبــيــانــات ♻️...`" -bd_2: "`┇يــتــم الــمــحــاولــة لإضــافــة كــل قــنــوات الــمــشــرف الــى قــاعــدة الــبــيــانــات ♻️...`" -bd_3: "**┇تــم ✅.**\n┇الــمــحــادثــات المــوجــودة فــي قــاعــدة الــبــيــانــات بــالــفــعــل 📍: {}\n┇الــمُــضــافــة حــديــثــاً 📅 : {}" -bd_4: "┇تــم إضــافــة الــقــنــوات ! ✅" -bd_5: "`┇تــم الإضــافــة الــى قــاعــدة الــبــيــانــات ! ✅`" -bd_6: "`┇الــقــنــاة مــوجــودة فــي قــاعــدة الــبــيــانــات بــالــفــعــل ! 📍`" - -# carbon -carbon_1: "┇يــتــم الــمــعــالــجــة ♻️" -carbon_2: "┇تــم عــمــل الــكــاربــون بــواســطــة [{}](tg://user?id={})" - -# chats -chats_1: "`┇يــتــم الــمــعــالــجــة ... ♻️`" -chats_2: "`┇لا يــمــكــن حــذف هــذه الــمــحــادثــة ⛔️`" -chats_3: "`┇انــا لــســت مــشــرف ❗️`" -chats_4: "┇ #تــم_الحــذف\n┇تــم حــذف {}" -chats_5: " ┇تــم صــنــع مــجــمــوعــتــك ✅[{}]({}) " -chats_6: "┇إنــضــم ⚜️ @TeamUltroid" - -# converter -cvt_1: "┇قــم بــالــرد عــلــى أي مــيــديــا / مــلــف نــصــي ❕." -cvt_2: "┇اكــتــب إســم وإمــتــداد الــمــلــف 📝" -cvt_3: "`┇يــتــم الــمــعــالــجــة ♻️...`" -cvt_4: "┇قــم بــالــرد عــلــى أي مــيــديــا❕" - -# core -core_1: "┇تــم الــعــثــور عــلــى وِحــدة ✅" -core_2: "{}.py ┇إســتــخــدم .Paste لــعــمــلــيــة الــلــصــق ❕" -core_3: "┇إبــحــث مــرة أخــرى ؟ ⚠️" -core_4: "┇تــم الــعــثــور عــلــى وِحــدة {} " -core_5: "{}.py ┇إســتــخــدم .Paste لــعــمــلــيــة الــلــصــق ❕" -core_6: "┇لــم يــتــم الــعــثــور عــلــى الــوحــدة {}.py " -core_7: "┇لا تــوجــد هــكــذا وحــدة ❌" -core_8: "┇لا تــوجــد وحــدة بــهــذا الإســم {}.py" -core_9: "`┇اكــتــب اســم الإضــافــة الــمُــراد إزالــتــهــا 🔰`" -core_10: "**┇تــمــت ازالــة** `{}` ** بــنــجــاح ✅**" -core_11: "**┇لا يــمــكــنــك إزالــة الإضــافــات الــرســمــيــة 🚫**" -core_12: "**┇لا تــوجــد إضــافــة بــإســم ** `{}`" -core_13: "`┇اكــتــب اســم الإضــافــة الــمُــراد إلــغــاء تــثــبــيــتــهــا 💢`" -core_14: "**┇تــم إلــغــاء تــثــبــيــت** `{}` **بــنــجــاح ✅**" -core_15: "**┇لا يــمــكــنــك إلــغــاء تــثــبــيــت الإضــافــات الــرســمــيــة 🚫**" -core_16: "`┇اكــتــب اســم الإضــافــة الــمُــراد إضــافــتــهــا 🔰`" -core_17: "**┇تــم إضافة** `{}` بــنــجــاح ✅" -core_18: "**┇تــعــذر إضــافــة ** `{}` **┇بــســبــب الــخــطــأ ⚠️**\n`{}`" - -# fedutils -sf_1: "بــدء الــ a Mass-FedBan..." -sf_2: "`عـذرآ لـم يتم تحـديد أي مسـتخدم 🚹!`" -sf_3: "عذرا لايمگـنك حـظر مطـوري أنـت جـديـد ✖️" -sf_4: "`- يـبـدو أن Rose لا تـسـتجـيـب ، أو أن المـكون الإضـافي يعـمل بشـكل سـيء ⚠️`" -sf_5: "يـمكنـك فقـط اسـتخـدام أوامـر التعليـقات مـرة واحـدة كـل 5 دقـائـق 🔄" -sf_6: "- حـاول مـرة أخـرى بـعد 5 دقائـق 5️⃣." -sf_7: "- تـعـذر جـمـع FedAdminList. 🚫 يرجـى أعاده الـمحاولة 🔄 ({} / 3) ..." -sf_8: "يـوجد هنـاك خطأ ⛔" -sf_9: "- تـعـذر جـمـع FedAdminList 🚫." -sf_10: "- FBaning in {} ألفـدراليـه 🚸." -sf_11: "- عذرا معـرف المـجموعـه المحدد غيـر صحيح ❌." -sf_12: "{} مسـتبعد ‼️." -sf_13: "خـطـأ في إزالـة مـلف FedAdmin ✖️.\n{}" -sf_14: "SuperFBan. أكتـمل .\nأجمـالي الاخطاء - {}.\nالـمسـتبـعد - {}.\n المتـأثر {} feds.\n#TB" -sf_15: "بـدء الــ a Mass-UnFedBan..." -sf_16: "SuperFBan. أكتـمل .\nأجمـالي الاخطاء - {}.\nالـمسـتبـعد - {}.\n المتـأثر {} feds.\n#TB" -sf_17: "`اعطنـي معـرف شخـص , او الـرد على الشخـص للـتحقق مـن أخطائـه.`" -sf_18: "قـائمه المحـظورين ⛔ {} تـم حظـره فـي .\n\nبأستـخدام Ultroid ⚠️." -sf_19: "خـطأ 🚫\n فـك الحـظر مـن @MissRose_Bot `ثـم حاول مجـددآ !" -sf_20: "`جـاري اسـتـخراج المعـلومـات 🚻...`" -sf_21: "\n\nFedInfo المستخرج بواسطة Ultroid" - -# gdrive -gdrive_1: "`┇انــت مــصــرح لــك بــالــفــعــل مــع Google Drive ✅`" -gdrive_2: "┇أذهــب [هــنــا](https://console.developers.google.com/flows/enableapi?apiid=drive) واحــصــل عــلــى GDRIVE_CLIENT_ID و GDRIVE_CLIENT_SECRET الــخــاص بــك\n\n" -gdrive_3: "┇ايــدي الــعــمــيــل خــاطــئ ⚠️" -gdrive_4: "`┇حــدث خــطــأ مــا ❗️ارســل `/auth` مــجــدداً . \n┇اذا حــدث نــفــس الــخــطــأ مــجدداً ؟ راســل `@TeamUltroid" -gdrive_5: "`┇نجحت العملية ! ✅\n┇انــت جــاهــز لاســتــخــدام Google Drive مــع Ultroid Userbot 🔱.`" -gdrive_6: "`┇اذهب الى `{}` وارسل ``/auth`." -gdrive_7: "**┇تــم رفــع الــمــلــف عــلــى G-Drive بــنــجــاح ✅ :**\n\n[{}]({})" - -# pmpermit -pmperm_1: "🤖┇مــن فــضــلــك , انــتــظــر الإجــابــة , او ســيــتــم حــظــرك والابــلاغ عــنــك كــ ازعــاج 💙" -pmperm_2: "🤖┇انــت تــســبــب ازعــاج لــ مــحــادثــة ســيــدي الــخــاصــة , وهــذا شــيء لا يــعــجــبــنــي ⚠️" -pmperm_3: "┇قــم بــالــرد عــلــى رســالــة شــخــص مــا لــتــجــربــة هــذا الامــر فــي الــمــحــادثــة الــخــاصــة ♥️" - -# updater -upd_1: "`┇جــاري الــتــحــقــق مــن وجــود تــحــديــثــات , انــتــظر رجــاءً ... ♥️`" -upd_2: "`┇أوبــس .. الــمــحــدث غــيــر قــادر عــلــى الاســتــكــمــال بــســبــب بــعــض الــمــشــاكــل.`\n\n**┇تــتــبــع الــســجــل:**\n" -upd_3: "**┇يــتــوفــر تــحــديــث جــديــد لــ [[{}]]({}/tree/{}):\n\n**┇ســجــل الــتــغــيــيــرات \n\n{}" -upd_4: "`┇حــجــم ســجــل الــتــغــيــيــرات كــبــيــر جــداً , اعــرض الــمــلــف لــرؤيــتــه `" -upd_6: "\n`┇بــوتــك` **بــأخــر تــحــديــث** `بـــ` **[[{}]]({}/tree/{})**\n" -upd_5: "اضغط علي الزر بالاسفل للتحديث." -upd_7: "`جار التحديث السريع...`" - -# upload download -udl_1: "`┇قــم بــالــرد عــلــى الــمــلــف / الــمــيــديــا الــمــراد تــحــمــيــلــهــا ♻️`" -udl_2: "┇تــم الــتــنــزيــل بــنــجــاح ✅\nلـــ\n`{}`\nفــي `{}`" -udl_3: "`┇ضــع مــســار مــحــدد لــلــمــلــف ⚠️`" -udl_4: "`جار محاولة التنزيل...`" -udl_5: "`لقد نسيت ان تعطيني رابط :(`" -udl_6: "`هذا المسار فارغ.`" -udl_7: "`لا يمكنك فعل هذا!`" - -# words -wrd_1: "**┇الــكــلــمــة ** - `{}`\n\n**┇مــعــنــاهــا** - \n" -wrd_2: "**┇الــكــلــمــة ** - `{}`\n\n**┇مــرادفــهــا** - \n" -wrd_3: "**┇الــكــلــمــة ** - `{}`\n\n**┇مــعــاكــســهــا ** - \n" -wrd_4: "`قم بإعطاء كلمة لمعرفة معناها..`" -wrd_5: "مرادفات" -wrd_6: "مضادات" -wrd_7: "لم يتم ايجاد مرادفات!!\n\n`{}`" -wrd_8: "لم يتم إيجاد مضادات!!\n\n`{}`" - -# ---------------------------------------------------# - -# assisant -ast_1: "┇اخــتــر أي API تــريــد اعــداده ♻️" -ast_2: "**remove.bg API**\n┇ادخــل مــفــتــاح الــ API الــخــاص بــك مــن remove.bg.\n\n┇اســتــخــدم /cancel لأنــهــاء الــعــمــلــيــة ⚠️" -ast_3: "┇مــرحــبــاً {}.↴┇مــن فــضــلــك تــصــفــح مــن خــلال الــخــيــارات " - -# Akinator -aki_1: "تم إنهاء اللعبة...." -aki_2: "بدأ اللعبة" -aki_3: "انتهي الوقت !" - -ascii_1: "`قم بالرد علي صورة.`" -ascii_2: "`جار التحويل ل html...`" -audiotools_1: "قم بالرد علي ملف صوتي او فيديو.." -audiotools_2: "تم التنزيل بنجاح، جار التحويل الي رسالة صوتية" -audiotools_3: "`ارسل الوقت بالصيغة المحددة للقص`" -audiotools_4: "`بيانات غير صحيحة`" -audiotools_5: "`جار محاولة التنزيل...`" -audiotools_6: "`مدة القص غير صحيحة`" -audiotools_7: "تم قص الملف الصوتي من `{}` الي `{}`" -audiotools_8: "قم بالرد علي فيديو..`" -audiotools_9: "`لم يتم ايجاد صوت...`" -audiotools_10: "`تم استخراج الصوت من الفيديو...`" - -asstcmd_1: "`استخدم هذا الامر مع رسالة وكلمة لاستخدم امر.`" -asstcmd_2: "`ارسل الامر الذي تريد حذفه.`" -asstcmd_3: "تم حذف الامر: `/{}`." -asstcmd_4: "تم حفظ الامر : `/{}`." -asstcmd_5: "لم يتم إيجاد اوامر" -asstcmd_6: "**كل أوامر مساعد ألترويد**\n\n" -act_1: "تم تفعيل خاصية التصحيح التلقائي" -act_2: "تم تعطيل خاصية التصحيح التلقائي" -autopic_4: "انت لم تكن تستخدم خاصية الصورة التلقائية !!" -autopic_5: "تم ايقاف الصورة التلقائية!" -inline_6: "**قائمة مساعدة المحادثة الصوتية ل {}**\n**الاوامر المتاحة:** `{}`\n\n@TeamUltroid" -inline_7: "قم بارسال .help {} لتحصل علي قائمة الأوامر." -inline_8: "اضغط علي الزر بالاسفل للتحديث!" -inline_9: "انت بالفعل علي اخر اصدار" - -bot_1: "مرحبا، انا علي قيد الحياة." -bot_2: "احصائيات" -bot_3: "Repo" -bot_4: "مجموعة المساعدة" -bot_5: "• `جار إعادة التشغيل...`" -usage_simple: "**مساحة الذاكرة**: `{}`\n**المستخدم**: `{}`\n**المتاح**: `{}`\n\n**📊 البيانات المستخدمة 📊**\n**رفع**: `{}`\n**تنزيل**: `{}`\n\n**CPU**: `{}%`\n**RAM**: `{}%`\n**الذاكرة**: `{}%`" -blk_1: "`قم بإعطاء كلمة لحظرها..`" -blk_2: "تم حظر كلمة : `{}` هنا." -blk_3: "`قم بإعطاء كلمة لالغاء حظرها..`" -blk_4: "تم الغاء حظر كلمة : `{}` هنا." -blk_5: "الكلمات المحظورة في هذه المجموعة هي :\n\n" -blk_6: "لا يوجد كلمات محظورة هنا" -bd_7: "تم الحذف من قاعدة البيانات" -bd_8: "`جار الحذف...`" -bd_9: "تم بالفعل حذف القناة من قاعدة البيانات. " -calc_1: "• الآلة الحاسبة الخصة بألترويد •" -calc_2: "فتح الآلة الحاسبة مجددا" -cha_1: "قناة غير صحيحة" -cha_2: "تم اضافة المصدر بنجاح" -cha_3: "تم اضافة قناة المصدر بالفعل" -cha_4: "تم حذف قاعدة بيانات المصدر." -cha_5: "تم حذف المصد من قاعدة البيانات" -cha_6: "تم بالفعل حذف القناة من قاعدة البيانات." -cha_7: "القنوات المقصودة في قاعدة البيانات:" -cha_8: "قنوات المصدر في قاعدة البيانات:" -carbon_3: "`قم بإعطاء لون معين لعمل الصورة...`" -chab_1: "قم بالرد علي مستخدم او قم بإعطاء اسم مستخدم لتفعيل بوت الذكاء الاصطناعي له!" -chab_2: "`لم يتم تفعيل الذكاء الاصطناعي لاي مستخدم.`" -chab_3: "**جميع المستخدمين الذين تم تفعيل الذكاء الاصطناعي لهم فيي هذه المحادثة :**\n\n" -clan_1: "تم تفعيل حذف رسائل الانضمام والمغادرة في هذه المجموعة" -clan_2: "تم تعطيل حذف رسائل الانضمام والمغادرة في هذه المجموعة" -clan_3: "`رقم تعريف غير صحيح`" -clan_4: "`لم يتم إضافة اي محادثات`" -clan_5: "حذف رسائل الانضمام والمغادرة مفعلة في هذه المجموعة." -cvt_5: "هذه الملف ليس به صورة مصغرة.`" -cvt_6: "تم اضافة [هذه]({}) كصورة مصغرة" -cvt_7: "`قم بالرد علي ملف يمكن قراءته`" -cvt_8: "`لا يمكن قراءة هذا الملف.`" -eod_1: "🎊 **حدث اليوم**\n\n" -eod_2: "• **حدث يوم {}/2022**\n\n" -devs_1: "`يم يتم إعطاء امر`" -devs_2: "`قم بإعطاء امر بايثون`" -devs_3: "`قم بإعطاء كود بلغة C++..`" -dm_1: "`قم باعطاء اسم مسخدم او رقم تعريفي للارسال له.`" -dm_2: "`قم بإعطاء نص او قم بالرد علي نص لارساله`" -dm_3: "⚜️ تم ارسال الرسالة! ⚜️" -dm_4: "خطأ : {}\nاقرأ الاستخدام : `{}مساعدة اخري`" -dm_5: "`قم بالتحقق من الرسائل الشخصية.`" -dm_6: "`لم يتم العثور علي رسالة لإرسالها :(`" -echo_1: "**تم تفعيل صدي الصوت لهذا المستخدم:**\n\n" -fka_1: "جار بدأ الفعل المزيف لمدة {} ثانية." -sf_22: "لم يتم تحديد المستخدم." -sf_23: "**خطأ**\n `قم بإلغاء حظر` @MissRose_Bot `وحاول مجددا!" - -antiflood_1: "`تم تعطيل مضاد الرسائل الكثيرة`" -antiflood_2: "`لا يوجد حد لعدد الرسائل في هذه المجموعة.`" -antiflood_3: "`تم كتمك.`" -antiflood_4: "`تم تحديد عدد رسائل الكتم ل {} في هذه المجموعة.`" -antiflood_5: "`حد عدد الرسائل في هذه المجموعة هو {}.`" - -flr_1: "`استخدم هذا الامر مع كلمة لاستخدامها كفلتر للرد...`" -flr_2: "الفلترات الموجودة في هذه المجموعة\n\n" -flr_3: "`حدد الفلتر المراد حذفه..`" -flr_4: "تم حفظ الفلتر `{}`." -flr_5: "تم حذف الفلتر `{}`." -flr_6: "لا يوجد فلترات هنا" -fgn_1: "**الخطوط المتاحة**\n\n" - -fsub_1: "حدد القناة التي تريد ان يشترك فيها المستخدم !" -fsub_2: "ارسل اسم مستخدم القناة او رقمها التعريفي" -fsub_3: "لم يتم تفعيل الاشتراك الاجباري في هذه المجموعة !" -fsub_4: "اشترك في القناة" -fsub_5: "الغاء كتمي" -fsub_6: "من فضلك اشترك بتلك القناة !\nثم اضغط علي الزر !" -fsub_7: "هذه الرسالة ليست لك" -fsub_8: "شكرا لك علي انضمامكم ! " - -ex_1: "`قم بالرد علي رسالة..`" -gas_1: "قم بإرسال رابط مباشر!" -grt_1: "`تم حفظ رسالة الترحيب`" -grt_2: "من فضلك استخدم هذا الامر في المجموعات وليس في الرسائل الخاصة!" -grt_3: "`قم بالرد علي الرسالة التي تريد تعيينها كرسالة ترحيب`" -grt_4: "`لم يتم تعيين رسالة ترحيب!`" -grt_5: "`تم حذف رسالة الترحيب`" -grt_6: "`لم يتم تعيين رسالة وداع!`" -grt_7: "`قم بالرد علي الرسالة التي تريد تعيينها كرسالة وداع`" -glitch_1: "`من فضلك انتظر...`" -mdi_1: "معلومات مشروحة اكثر" - -nightm_1: "قم بكتابة الوقت بالصيغة الصحيحة" -nightm_2: "تم تعيين الوقت بنجاح" -nightm_3: "تم تفعيل الوضع الليلي في هذه المجموعة" -nightm_4: "تم تعطيل الوضع الليلي في هذه المجموعة" -nightm_5: "حدث خطأ" - -schdl_1: "`تم جدولة الرسالة بنجاح`" -schdl_2: "`صيغة غير صحيحة`" - -srch_1: "`ابحث عن من؟ قم بتحديد اسم مستخدم!!`" -srch_2: "`لم يتم العثور علي مستخدم بهذا الاسم...`" -srch_3: "`لم يتم العثور علي الاغنية...`" -snip_1: "قم بتحديد كلمة لتعيين رد لها وقم بالرد علي رسالة." -snip_2: "حدد الكلمة التي تريد حذفها..." -snip_3: "لا يوجد كلمات بردود معينة هنا." -spcltool_1: "قم بالرد علي ملف صوتي او فيديو" -spcltool_2: "`تم.. الان قم بالرد علي فيديو لاضافة هذا الصوت له`" -spcltool_3: "قم بالرد علي فيديو" -spcltool_4: "`اولا قم بالرد علي ملف صوتي ب .raw`" -spcltool_5: "تم التنزيل بنجاح, جار اضافة الصوت للفيديو" -spcltool_6: "`اكتب التاريخ بهذه الصيغة يوم/شهر/سنة`" -spcltool_7: "`عيد ميلاد سعيد 🎉🎊`" -spcltool_8: "عن ماذا تريد ان تبحث؟.." -spcltool_9: "لم يتم العثور علي اي شئ" -sudo_1: "`قم بالرد علي رسالة او اضف رقمها التعريفي/اسم المستخدم.`" -sudo_2: "لا يمكن إضافة نفسك كمستخدم نظير..." -sudo_3: "`لم يتم تعيين اي مستخدم نظير ...`" -sudo_4: "`لا يمكن تعيين بوت كمستخدم نظير.`" -unspl_1: "لا يوجد نتائج !" - -# VCTools -vct_1: "`تم بدأ المحادثة الصوتية...`" -vct_2: "**تم تغيير عنوان المحادثه الصوتية ل** `{}` بنجاح" -vct_3: "`جار دعوة الاعضاء للمشاركة في المحادثة الصوتية...`" -vct_4: "`تم ايقاف المحادثه الصوتية...`" -vct_5: "`تم دعوة {} مستخدمين`" -vct_6: "لم يتم العثور علي مدخلات!" - -prof_1: "`تم تشغيل خاصية حظر الكلمات الخارجة لهذه المجموعة!`" -prof_2: "`تم ايقاف خاصية حظر الكلمات الخارجة لهذه المجموعة!`" - -notes_1: "`استخدم هذا الامر بالرد علي رسالة مع تحديد اسم.`" -notes_2: "تم حفظ الملاحظة : `#{}`." -notes_3: "`حدد اسم الملاحظة التي تريد حذفها.`" -notes_4: "الملاحظات الموجودة في هذه المجموعة هي\n\n" -notes_5: "لا يوجد ملاحظات هنا" - -sts_1: "`لم تكتب اي شئ, ستذهب وايفو بعيدا.`" -sts_2: "`قم بالرد علي ملصق متحرك...`" -sts_3: "**من فضلك اختر من {} **" -sts_4: "`قم بالرد علي ملصق غير متحرك.`" -sts_5: "**تم سرقة مجموعة الملصقات بنجاح**.\n**المجموعة التي تم سرقتها:** [link]({})" -sts_6: "`قم بالرد علي رسالة/ملف وسائط...`" -sts_7: "`تم إضافة الملصق لمجموعة مختلفة !\nمجموعة الملصقات هذه تم انشاءها مؤخرا!\nيمكنك إيجاد مجموعة الملصقات` [هنا](t.me/addstickers/{})" -sts_8: "`فشل اضافة الملصق, استخدم بوت` @Stickers `لاضافة الملصق يدويا.`" -sts_9: "`اوه ملصق متحرك 👀...`" -sts_10: "`قم بالرد علي ملف وسائط...`" -sts_11: "جار سرقة الملصق..." -sts_12: "`تم سرقة الملصق!`\n`Emoji` : {}\n`مجموعة الملصقات` [هنا](t.me/addstickers/{})" -sts_13: "`جار تغيير مجموعة الملصقات {} بسبب المساحة الغير كافية`" - -whs_1: "<• قم بالرد علي ملف صوتي •>" -whs_2: "`جار محاولة التعرف على الاغنيه....`" -whs_3: "فشل التعرف علي الاغنية :(" -whs_4: "**تم التعرف علي الاغنية!**\nاسمها: __{}__" -wbl_1: "`حدد اسم الملف من فضلك..`" -writer_1: "`قم باعطاء نص ايضا`" - -wbs_1: "`قم بإرسال رابط من فضلك!`" -wbs_2: "رابط غير صحيح!" -wbs_3: "**تم انشاء صورة الرابط**\n**الرابط**: {}" - -# YouTube -youtube_1: "قم باعطاء رابط (يوتيوب) مباشر ليتم التنزيل منه!" -youtube_2: "`قم باعطاء رابط ملف صوتي مباشر ليتم التنزيل منه`" -youtube_3: "قم باعطاء رابط (يوتيوب) مباشر ليتم التنزيل منه!" -youtube_4: "`قم باعطاء رابط فيديو مباشر ليتم التنزيل منه`" -youtube_5: "قم بإعطاء امر بحث (يوتيوب) ليتم تنزيل ملف الصوت منه!" -youtube_6: "`جار تنزيل الاغنية...`" -youtube_7: "قم بإعطاء امر بحث (يوتيوب) ليتم تنزيل الفيديو منه!" -youtube_8: "`جار تنزيل فيديو الاغنية...`" - -zip_1: "قم بالرد علي ملف." -zip_2: "اولا اضف كل الملفات عن طريق `{}addzip` ثم قم بعمل zip لضغط كل الملفات في وقت واحد." -zip_3: "`قم بالرد فقط علي ملف zip`" - -fsh_1: "**قائمة الملفات المخزنة.:**" -fsh_2: "**تم تخزين الملف!**\n\n**رابط يمكن مشاركته:** {}" -fsh_3: "`قم بالرد علي رسالة لعمل رابط يمكن مشاركته!`" -fsh_4: "**لا يوجد ملفات مخزنة!**" - -instu_1: "بحث عن تطبيق. ادخل اسم التطبيق!" -instu_2: "ما تم البحث عنه مؤخراً.." -instu_3: "ادخل ما تريد البحث عنه" -instu_4: "تم بنجاح" - -# games -games_1: "اختر اللعبة 🎮" -games_2: "اختر مجال الاسئلة!" -games_3: "اختر مستوي صعوبة الاسئلة" -games_4: "اختر عدد الاسئله.." -games_5: "اختر الوقت بين الأسئلة..." -games_6: "**• سيبدأ الاختبار في ٥ ثواني.** \n**• المستوي :** {}\n**• السؤال :** {}" - -# callback stuff -clst_1: "`جار بناء البوت، من فضل انتظر حتي يكتمل البناء.`" -clst_2: "`تم التحديث بنجاح!\nجار اعادة التشغيل, من فضلك انتظر...`" -clst_3: "■ جار الحصول علي سجل التغييرات..." -clst_4: "عفوا حدث خطأ..." -clst_5: "تم!" - -# pmbot -pmbot_1: "**يجب ان تنضم للمجموعة/المجموعات بالاسفل لتقوم بمحادثة سيدي!\n\n**" -pmbot_2: "من فضلك قم بالرد علي احدهم لتقوم بحظره." -pmbot_3: "هذا المستخدم محظور بالفعل!" -pmbot_4: "`وداعا! لقد تم حظرك.`\n**كل الرسائل التي سترسلها الان لن تصل.**" -pmbot_5: "من فضلك قم بالرد علي احدهم لالغاء حظره." -pmbot_6: "هذ المستخدم لم يتم حظره ابدا!" -pmbot_7: "`مبروك! تم الغاء حظرك.`" - -# vcbot -vcbot_1: "`تم مغادرة المحادثة الصوتية.`" -vcbot_2: "**حدث خطأ:**\n{}" -vcbot_3: "• تم تغيير مستوي الصوت ل `{}%` •" -vcbot_4: "`قم بتحديد مستوي الصوت بين 1 و 200!`" -vcbot_5: "`جار اعادة الانضمام للمحادثة الصوتية.`" -vcbot_6: "انت لم تتصل بمحادثة صوتية!" -vcbot_7: "`من فضلك انتظر... سيستغرق هذا بعض الوقت.`" -vcbot_8: "ارسل قائمة تشغيل يوتيوب فقط" -vcbot_9: "أتمازحني?\nماذا تريدني أن اشغل؟" -vcbot_10: "تم حذف المجموعة من قائمة المصرح لهم!" -vcbot_11: "`جار الحصول على قائمة مستخدمي بوت المحادثة الصوتية...`" -vcbot_12: "`تم كتم الصوت في هذه المجموعة.`" -vcbot_13: "`تم متابعة التشغيل في هذه المجموعة.`" -vcbot_14: "`تم ايقاف التشغيل مؤقتا في هذه المجموعة.`" -vcbot_15: "من فضلك قم بتحديد اسم اغنية او قم بالرد علي ملف فيديو !" -vcbot_16: "هذه المجموعة ليست في قائمة المصرح لهم..." -vcbot_17: "`قم بالرد علي رسالة مستخدم او قم بارسال رقمها التعريفي/اسم المستخدم...`" -vcbot_18: "• قائمة المصرح لهم فارغة.." -vcbot_19: "تم بالفعل التصريح لهذه المجموعة!" -vcbot_20: "`جاري التنزيل والتحويل...`" -vcbot_21: "• لا يوجد شيء في قائمة الانتظار!" -vcbot_22: "`تم حذف كل قائمة الانتظار`" - -help_echo: "• `{i} addecho <الرد على أي شخص>`\n ابدأ رسالة صدى تلقائي للمستخدم المردل.\n\n• `{i} remecho <الرد على أي شخص>`\n أطفئه\n\n• `{i} listecho <الرد على أي شخص>`\n للحصول على قائمة." -help_mediatools: "-\n\n• `{i} mediaInfo <الرد على الوسائط>`\n للحصول على معلومات حول هذا الموضوع.\n\n• `{i} تدوير <درجة/زاوية> <الرد على الوسائط>` `\n تدوير أي فيديو/صور/وسائط ..\n ملاحظة: بالنسبة للفيديو ، يجب أن تكون زاوية التسعينيات" -help_mute: "-\n\n• `{i} كتم <الرد على msg/ user id>`\n كتم المستخدم في الدردشة الحالية.\n\n• `{i} unmute <الرد على msg/ user id>`\n Unmuction User في الدردشة الحالية.\n\n• `{i} dmute <الرد على msg/ user id>`\n كتم المستخدم في الدردشة الحالية عن طريق حذف msgs.\n\n• `{i} unding ` `\n Unmute dmated المستخدم في الدردشة الحالية.\n\n• `{i} tmute