Spaces:
Running
Running
Upload 87 files
Browse filesThis view is limited to 50 files because it contains too many changes. ย
See raw diff
- Hellbot/__init__.py +60 -0
- Hellbot/__main__.py +33 -0
- Hellbot/core/__init__.py +19 -0
- Hellbot/core/clients.py +232 -0
- Hellbot/core/config.py +155 -0
- Hellbot/core/database.py +584 -0
- Hellbot/core/initializer.py +94 -0
- Hellbot/core/logger.py +19 -0
- Hellbot/functions/__init__.py +0 -0
- Hellbot/functions/admins.py +24 -0
- Hellbot/functions/convert.py +98 -0
- Hellbot/functions/driver.py +318 -0
- Hellbot/functions/formatter.py +94 -0
- Hellbot/functions/images.py +389 -0
- Hellbot/functions/media.py +192 -0
- Hellbot/functions/paste.py +49 -0
- Hellbot/functions/scraping.py +528 -0
- Hellbot/functions/sticker.py +135 -0
- Hellbot/functions/templates.py +466 -0
- Hellbot/functions/tools.py +139 -0
- Hellbot/functions/utility.py +241 -0
- Hellbot/plugins/__init__.py +0 -0
- Hellbot/plugins/bot/__init__.py +29 -0
- Hellbot/plugins/bot/bot.py +60 -0
- Hellbot/plugins/bot/callbacks.py +279 -0
- Hellbot/plugins/bot/forcesub.py +226 -0
- Hellbot/plugins/bot/inline.py +39 -0
- Hellbot/plugins/bot/sessions.py +183 -0
- Hellbot/plugins/bot/users.py +82 -0
- Hellbot/plugins/btnsG.py +106 -0
- Hellbot/plugins/btnsK.py +45 -0
- Hellbot/plugins/decorator.py +67 -0
- Hellbot/plugins/help.py +132 -0
- Hellbot/plugins/user/__init__.py +16 -0
- Hellbot/plugins/user/admins.py +510 -0
- Hellbot/plugins/user/afk.py +157 -0
- Hellbot/plugins/user/anime.py +184 -0
- Hellbot/plugins/user/antiflood.py +200 -0
- Hellbot/plugins/user/archiver.py +99 -0
- Hellbot/plugins/user/autopost.py +143 -0
- Hellbot/plugins/user/blacklist.py +78 -0
- Hellbot/plugins/user/bot.py +164 -0
- Hellbot/plugins/user/carbon.py +73 -0
- Hellbot/plugins/user/climate.py +140 -0
- Hellbot/plugins/user/clone.py +106 -0
- Hellbot/plugins/user/convert.py +216 -0
- Hellbot/plugins/user/core.py +321 -0
- Hellbot/plugins/user/downloads.py +85 -0
- Hellbot/plugins/user/echo.py +91 -0
- Hellbot/plugins/user/eval.py +272 -0
Hellbot/__init__.py
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import time
|
3 |
+
from platform import python_version
|
4 |
+
|
5 |
+
import heroku3
|
6 |
+
from pyrogram import __version__ as pyrogram_version
|
7 |
+
|
8 |
+
from .core import LOGS, Config
|
9 |
+
|
10 |
+
START_TIME = time.time()
|
11 |
+
|
12 |
+
|
13 |
+
__version__ = {
|
14 |
+
"hellbot": "3.0",
|
15 |
+
"pyrogram": pyrogram_version,
|
16 |
+
"python": python_version(),
|
17 |
+
}
|
18 |
+
|
19 |
+
|
20 |
+
try:
|
21 |
+
if Config.HEROKU_APIKEY is not None and Config.HEROKU_APPNAME is not None:
|
22 |
+
HEROKU_APP = heroku3.from_key(Config.HEROKU_APIKEY).apps()[
|
23 |
+
Config.HEROKU_APPNAME
|
24 |
+
]
|
25 |
+
else:
|
26 |
+
HEROKU_APP = None
|
27 |
+
except Exception as e:
|
28 |
+
LOGS.error(f"Heroku Api - {e}")
|
29 |
+
HEROKU_APP = None
|
30 |
+
|
31 |
+
|
32 |
+
if Config.API_HASH is None:
|
33 |
+
LOGS.error("Please set your API_HASH !")
|
34 |
+
quit(1)
|
35 |
+
|
36 |
+
if Config.API_ID == 0:
|
37 |
+
LOGS.error("Please set your API_ID !")
|
38 |
+
quit(1)
|
39 |
+
|
40 |
+
if Config.BOT_TOKEN is None:
|
41 |
+
LOGS.error("Please set your BOT_TOKEN !")
|
42 |
+
quit(1)
|
43 |
+
|
44 |
+
if Config.DATABASE_URL is None:
|
45 |
+
LOGS.error("Please set your DATABASE_URL !")
|
46 |
+
quit(1)
|
47 |
+
|
48 |
+
if Config.LOGGER_ID == 0:
|
49 |
+
LOGS.error("Please set your LOGGER_ID !")
|
50 |
+
quit(1)
|
51 |
+
|
52 |
+
if Config.OWNER_ID == 0:
|
53 |
+
LOGS.error("Please set your OWNER_ID !")
|
54 |
+
quit(1)
|
55 |
+
|
56 |
+
if not os.path.isdir(Config.DWL_DIR):
|
57 |
+
os.makedirs(Config.DWL_DIR)
|
58 |
+
|
59 |
+
if not os.path.isdir(Config.TEMP_DIR):
|
60 |
+
os.makedirs(Config.TEMP_DIR)
|
Hellbot/__main__.py
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram import idle
|
2 |
+
|
3 |
+
from Hellbot import __version__
|
4 |
+
from Hellbot.core import (
|
5 |
+
Config,
|
6 |
+
ForcesubSetup,
|
7 |
+
GachaBotsSetup,
|
8 |
+
TemplateSetup,
|
9 |
+
UserSetup,
|
10 |
+
db,
|
11 |
+
hellbot,
|
12 |
+
)
|
13 |
+
from Hellbot.functions.tools import initialize_git
|
14 |
+
from Hellbot.functions.utility import BList, Flood, TGraph
|
15 |
+
|
16 |
+
|
17 |
+
async def main():
|
18 |
+
await hellbot.startup()
|
19 |
+
await db.connect()
|
20 |
+
await UserSetup()
|
21 |
+
await ForcesubSetup()
|
22 |
+
await GachaBotsSetup()
|
23 |
+
await TemplateSetup()
|
24 |
+
await Flood.updateFromDB()
|
25 |
+
await BList.updateBlacklists()
|
26 |
+
await TGraph.setup()
|
27 |
+
await initialize_git(Config.PLUGINS_REPO)
|
28 |
+
await hellbot.start_message(__version__)
|
29 |
+
await idle()
|
30 |
+
|
31 |
+
|
32 |
+
if __name__ == "__main__":
|
33 |
+
hellbot.run(main())
|
Hellbot/core/__init__.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from .clients import hellbot
|
2 |
+
from .config import ENV, Config, Limits, Symbols
|
3 |
+
from .database import db
|
4 |
+
from .initializer import ForcesubSetup, GachaBotsSetup, TemplateSetup, UserSetup
|
5 |
+
from .logger import LOGS
|
6 |
+
|
7 |
+
__all__ = [
|
8 |
+
"hellbot",
|
9 |
+
"ENV",
|
10 |
+
"Config",
|
11 |
+
"Limits",
|
12 |
+
"Symbols",
|
13 |
+
"db",
|
14 |
+
"ForcesubSetup",
|
15 |
+
"GachaBotsSetup",
|
16 |
+
"TemplateSetup",
|
17 |
+
"UserSetup",
|
18 |
+
"LOGS",
|
19 |
+
]
|
Hellbot/core/clients.py
ADDED
@@ -0,0 +1,232 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import asyncio
|
2 |
+
import glob
|
3 |
+
import importlib
|
4 |
+
import os
|
5 |
+
import sys
|
6 |
+
from pathlib import Path
|
7 |
+
|
8 |
+
import pyroaddon # pylint: disable=unused-import
|
9 |
+
from pyrogram import Client
|
10 |
+
from pyrogram.enums import ParseMode
|
11 |
+
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
|
12 |
+
|
13 |
+
from .config import ENV, Config, Symbols
|
14 |
+
from .database import db
|
15 |
+
from .logger import LOGS
|
16 |
+
|
17 |
+
|
18 |
+
class HellClient(Client):
|
19 |
+
def __init__(self) -> None:
|
20 |
+
self.users: list[Client] = []
|
21 |
+
self.bot: Client = Client(
|
22 |
+
name="HellBot",
|
23 |
+
api_id=Config.API_ID,
|
24 |
+
api_hash=Config.API_HASH,
|
25 |
+
bot_token=Config.BOT_TOKEN,
|
26 |
+
plugins=dict(root="Hellbot.plugins.bot"),
|
27 |
+
)
|
28 |
+
|
29 |
+
async def start_user(self) -> None:
|
30 |
+
sessions = await db.get_all_sessions()
|
31 |
+
for i, session in enumerate(sessions):
|
32 |
+
try:
|
33 |
+
client = Client(
|
34 |
+
name=f"HellUser#{i + 1}",
|
35 |
+
api_id=Config.API_ID,
|
36 |
+
api_hash=Config.API_HASH,
|
37 |
+
session_string=session["session"],
|
38 |
+
)
|
39 |
+
await client.start()
|
40 |
+
me = await client.get_me()
|
41 |
+
self.users.append(client)
|
42 |
+
LOGS.info(
|
43 |
+
f"{Symbols.arrow_right * 2} Started User {i + 1}: '{me.first_name}' {Symbols.arrow_left * 2}"
|
44 |
+
)
|
45 |
+
is_in_logger = await self.validate_logger(client)
|
46 |
+
if not is_in_logger:
|
47 |
+
LOGS.warning(
|
48 |
+
f"Client #{i+1}: '{me.first_name}' is not in Logger Group! Check and add manually for proper functioning."
|
49 |
+
)
|
50 |
+
try:
|
51 |
+
await client.join_chat("https://t.me/+wQyUMn4891Q2OTVh") # Channel
|
52 |
+
except:
|
53 |
+
pass
|
54 |
+
# try:
|
55 |
+
# await client.join_chat("https://t.me/+P4Ekwk7P7Rk3NzA9") # Group
|
56 |
+
# except:
|
57 |
+
# pass
|
58 |
+
except Exception as e:
|
59 |
+
LOGS.error(f"{i + 1}: {e}")
|
60 |
+
continue
|
61 |
+
|
62 |
+
async def start_bot(self) -> None:
|
63 |
+
await self.bot.start()
|
64 |
+
me = await self.bot.get_me()
|
65 |
+
LOGS.info(
|
66 |
+
f"{Symbols.arrow_right * 2} Started HellBot Client: '{me.username}' {Symbols.arrow_left * 2}"
|
67 |
+
)
|
68 |
+
|
69 |
+
async def load_plugin(self) -> None:
|
70 |
+
count = 0
|
71 |
+
files = glob.glob("Hellbot/plugins/user/*.py")
|
72 |
+
unload = await db.get_env(ENV.unload_plugins) or ""
|
73 |
+
unload = unload.split(" ")
|
74 |
+
for file in files:
|
75 |
+
with open(file) as f:
|
76 |
+
path = Path(f.name)
|
77 |
+
shortname = path.stem.replace(".py", "")
|
78 |
+
if shortname in unload:
|
79 |
+
os.remove(Path(f"Hellbot/plugins/user/{shortname}.py"))
|
80 |
+
continue
|
81 |
+
if shortname.startswith("__"):
|
82 |
+
continue
|
83 |
+
fpath = Path(f"Hellbot/plugins/user/{shortname}.py")
|
84 |
+
name = "Hellbot.plugins.user." + shortname
|
85 |
+
spec = importlib.util.spec_from_file_location(name, fpath)
|
86 |
+
load = importlib.util.module_from_spec(spec)
|
87 |
+
spec.loader.exec_module(load)
|
88 |
+
sys.modules["Hellbot.plugins.user." + shortname] = load
|
89 |
+
count += 1
|
90 |
+
f.close()
|
91 |
+
LOGS.info(
|
92 |
+
f"{Symbols.bullet * 3} Loaded User Plugin: '{count}' {Symbols.bullet * 3}"
|
93 |
+
)
|
94 |
+
|
95 |
+
async def validate_logger(self, client: Client) -> bool:
|
96 |
+
try:
|
97 |
+
await client.get_chat_member(Config.LOGGER_ID, "me")
|
98 |
+
return True
|
99 |
+
except Exception:
|
100 |
+
return await self.join_logger(client)
|
101 |
+
|
102 |
+
async def join_logger(self, client: Client) -> bool:
|
103 |
+
try:
|
104 |
+
invite_link = await self.bot.export_chat_invite_link(Config.LOGGER_ID)
|
105 |
+
await client.join_chat(invite_link)
|
106 |
+
return True
|
107 |
+
except Exception:
|
108 |
+
return False
|
109 |
+
|
110 |
+
async def start_message(self, version: dict) -> None:
|
111 |
+
await self.bot.send_animation(
|
112 |
+
Config.LOGGER_ID,
|
113 |
+
"https://te.legra.ph/file/8deca5343c64d9db9401f.mp4",
|
114 |
+
f"**{Symbols.check_mark} ๐ง๐พ๐
๐
๐ก๐๐ ๐๐ ๐๐๐ ๐ฎ๐๐
๐๐๐พ!**\n\n"
|
115 |
+
f"**{Symbols.triangle_right} ๐ข๐
๐๐พ๐๐๐:** `{len(self.users)}`\n"
|
116 |
+
f"**{Symbols.triangle_right} ๐ฏ๐
๐๐๐๐๐:** `{len(Config.CMD_MENU)}`\n"
|
117 |
+
f"**{Symbols.triangle_right} ๐ข๐๐๐๐บ๐๐ฝ๐:** `{len(Config.CMD_INFO)}`\n"
|
118 |
+
f"**{Symbols.triangle_right} ๐ฒ๐๐บ๐ ๐ด๐๐พ๐๐:** `{len(Config.STAN_USERS)}`\n"
|
119 |
+
f"**{Symbols.triangle_right} ๐ ๐๐๐ ๐ด๐๐พ๐๐:** `{len(Config.AUTH_USERS)}`\n\n"
|
120 |
+
f"**{Symbols.triangle_right} ๐ง๐พ๐
๐
๐ก๐๐ ๐ต๐พ๐๐๐๐๐:** `{version['hellbot']}`\n"
|
121 |
+
f"**{Symbols.triangle_right} ๐ฏ๐๐๐๐๐๐บ๐ ๐ต๐พ๐๐๐๐๐:** `{version['pyrogram']}`\n"
|
122 |
+
f"**{Symbols.triangle_right} ๐ฏ๐๐๐๐๐ ๐ต๐พ๐๐๐๐๐:** `{version['python']}`\n\n"
|
123 |
+
f"**</> @HellBot_Networks**",
|
124 |
+
parse_mode=ParseMode.MARKDOWN,
|
125 |
+
disable_notification=True,
|
126 |
+
reply_markup=InlineKeyboardMarkup(
|
127 |
+
[
|
128 |
+
[
|
129 |
+
InlineKeyboardButton("๐ซ Start Me", url=f"https://t.me/{self.bot.me.username}?start=start"),
|
130 |
+
InlineKeyboardButton("๐ Repo", url="https://github.com/The-HellBot/HellBot"),
|
131 |
+
],
|
132 |
+
[
|
133 |
+
InlineKeyboardButton("๐ HellBot Networks ๐", url="https://t.me/hellbot_networks"),
|
134 |
+
],
|
135 |
+
]
|
136 |
+
),
|
137 |
+
)
|
138 |
+
|
139 |
+
async def startup(self) -> None:
|
140 |
+
LOGS.info(
|
141 |
+
f"{Symbols.bullet * 3} Starting HellBot Client & User {Symbols.bullet * 3}"
|
142 |
+
)
|
143 |
+
await self.start_bot()
|
144 |
+
await self.start_user()
|
145 |
+
await self.load_plugin()
|
146 |
+
|
147 |
+
|
148 |
+
class CustomMethods(HellClient):
|
149 |
+
async def input(self, message: Message) -> str:
|
150 |
+
"""Get the input from the user"""
|
151 |
+
if len(message.command) < 2:
|
152 |
+
output = ""
|
153 |
+
|
154 |
+
else:
|
155 |
+
try:
|
156 |
+
output = message.text.split(" ", 1)[1].strip() or ""
|
157 |
+
except IndexError:
|
158 |
+
output = ""
|
159 |
+
|
160 |
+
return output
|
161 |
+
|
162 |
+
async def edit(
|
163 |
+
self,
|
164 |
+
message: Message,
|
165 |
+
text: str,
|
166 |
+
parse_mode: ParseMode = ParseMode.DEFAULT,
|
167 |
+
no_link_preview: bool = True,
|
168 |
+
) -> Message:
|
169 |
+
"""Edit or Reply to a message, if possible"""
|
170 |
+
if message.from_user and message.from_user.id in Config.STAN_USERS:
|
171 |
+
if message.reply_to_message:
|
172 |
+
return await message.reply_to_message.reply_text(
|
173 |
+
text,
|
174 |
+
parse_mode=parse_mode,
|
175 |
+
disable_web_page_preview=no_link_preview,
|
176 |
+
)
|
177 |
+
return await message.reply_text(
|
178 |
+
text, parse_mode=parse_mode, disable_web_page_preview=no_link_preview
|
179 |
+
)
|
180 |
+
return await message.edit_text(
|
181 |
+
text, parse_mode=parse_mode, disable_web_page_preview=no_link_preview
|
182 |
+
)
|
183 |
+
|
184 |
+
async def _delete(self, message: Message, delay: int = 0) -> None:
|
185 |
+
"""Delete a message after a certain period of time"""
|
186 |
+
await asyncio.sleep(delay)
|
187 |
+
await message.delete()
|
188 |
+
|
189 |
+
async def delete(
|
190 |
+
self, message: Message, text: str, delete: int = 10, in_background: bool = True
|
191 |
+
) -> None:
|
192 |
+
"""Edit a message and delete it after a certain period of time"""
|
193 |
+
to_del = await self.edit(message, text)
|
194 |
+
if in_background:
|
195 |
+
asyncio.create_task(self._delete(to_del, delete))
|
196 |
+
else:
|
197 |
+
await self._delete(to_del, delete)
|
198 |
+
|
199 |
+
async def error(self, message: Message, text: str, delete: int = 10) -> None:
|
200 |
+
"""Edit an error message and delete it after a certain period of time if mentioned"""
|
201 |
+
to_del = await self.edit(message, f"{Symbols.cross_mark} **Error:** \n\n{text}")
|
202 |
+
if delete:
|
203 |
+
asyncio.create_task(self._delete(to_del, delete))
|
204 |
+
|
205 |
+
async def _log(self, tag: str, text: str, file: str = None) -> None:
|
206 |
+
"""Log a message to the Logger Group"""
|
207 |
+
msg = f"**#{tag.upper()}**\n\n{text}"
|
208 |
+
try:
|
209 |
+
if file:
|
210 |
+
try:
|
211 |
+
await self.bot.send_document(Config.LOGGER_ID, file, caption=msg)
|
212 |
+
except:
|
213 |
+
await self.bot.send_message(
|
214 |
+
Config.LOGGER_ID, msg, disable_web_page_preview=True
|
215 |
+
)
|
216 |
+
else:
|
217 |
+
await self.bot.send_message(
|
218 |
+
Config.LOGGER_ID, msg, disable_web_page_preview=True
|
219 |
+
)
|
220 |
+
except Exception as e:
|
221 |
+
raise Exception(f"{Symbols.cross_mark} LogErr: {e}")
|
222 |
+
|
223 |
+
async def check_and_log(self, tag: str, text: str, file: str = None) -> None:
|
224 |
+
"""Check if :
|
225 |
+
\n-> the Logger Group is available
|
226 |
+
\n-> the logging is enabled"""
|
227 |
+
status = await db.get_env(ENV.is_logger)
|
228 |
+
if status and status.lower() == "true":
|
229 |
+
await self._log(tag, text, file)
|
230 |
+
|
231 |
+
|
232 |
+
hellbot = CustomMethods()
|
Hellbot/core/config.py
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from os import getenv
|
2 |
+
|
3 |
+
from dotenv import load_dotenv
|
4 |
+
from pyrogram import filters
|
5 |
+
|
6 |
+
load_dotenv()
|
7 |
+
|
8 |
+
|
9 |
+
class Config:
|
10 |
+
# editable configs
|
11 |
+
API_HASH = getenv("API_HASH", None)
|
12 |
+
API_ID = int(getenv("API_ID", 0))
|
13 |
+
BOT_TOKEN = getenv("BOT_TOKEN", None)
|
14 |
+
DATABASE_URL = getenv("DATABASE_URL", None)
|
15 |
+
HANDLERS = getenv("HANDLERS", ". ! ?").strip().split()
|
16 |
+
LOGGER_ID = int(getenv("LOGGER_ID", 0))
|
17 |
+
OWNER_ID = int(getenv("OWNER_ID", 0))
|
18 |
+
|
19 |
+
# heroku related configs
|
20 |
+
HEROKU_APPNAME = getenv("HEROKU_APPNAME", None)
|
21 |
+
HEROKU_APIKEY = getenv("HEROKU_APIKEY", None)
|
22 |
+
|
23 |
+
# github related configs
|
24 |
+
PLUGINS_REPO = getenv("PLUGINS_REPO", "The-HellBot/Plugins")
|
25 |
+
DEPLOY_REPO = getenv("DEPLOY_REPO", "The-HellBot/Hellbot")
|
26 |
+
|
27 |
+
# storage dir: you may or may not edit
|
28 |
+
DWL_DIR = "./downloads/"
|
29 |
+
TEMP_DIR = "./temp/"
|
30 |
+
CHROME_BIN = getenv("CHROME_BIN", "/app/.chrome-for-testing/chrome-linux64/chrome")
|
31 |
+
CHROME_DRIVER = getenv(
|
32 |
+
"CHROME_DRIVER", "/app/.chrome-for-testing/chromedriver-linux64/chromedriver"
|
33 |
+
)
|
34 |
+
FONT_PATH = "./Hellbot/resources/fonts/Montserrat.ttf"
|
35 |
+
|
36 |
+
# users config: do not edit
|
37 |
+
AUTH_USERS = filters.user()
|
38 |
+
BANNED_USERS = filters.user()
|
39 |
+
GACHA_BOTS = filters.user()
|
40 |
+
MUTED_USERS = filters.user()
|
41 |
+
DEVS = filters.user([1432756163, 1874070588, 1533682758])
|
42 |
+
STAN_USERS = filters.user()
|
43 |
+
FORCESUBS = filters.chat()
|
44 |
+
|
45 |
+
# Global config: do not edit
|
46 |
+
AFK_CACHE = {}
|
47 |
+
BOT_CMD_INFO = {}
|
48 |
+
BOT_CMD_MENU = {}
|
49 |
+
BOT_HELP = {}
|
50 |
+
CMD_INFO = {}
|
51 |
+
CMD_MENU = {}
|
52 |
+
HELP_DICT = {}
|
53 |
+
TEMPLATES = {}
|
54 |
+
|
55 |
+
|
56 |
+
class ENV:
|
57 |
+
"""Database ENV Names"""
|
58 |
+
|
59 |
+
airing_template = "AIRING_TEMPLATE"
|
60 |
+
airpollution_template = "AIRPOLLUTION_TEMPLATE"
|
61 |
+
alive_pic = "ALIVE_PIC"
|
62 |
+
alive_template = "ALIVE_TEMPLATE"
|
63 |
+
anilist_user_template = "ANILIST_USER_TEMPLATE"
|
64 |
+
anime_template = "ANIME_TEMPLATE"
|
65 |
+
btn_in_help = "BUTTONS_IN_HELP"
|
66 |
+
character_template = "CHARACTER_TEMPLATE"
|
67 |
+
chat_info_template = "CHAT_INFO_TEMPLATE"
|
68 |
+
climate_api = "CLIMATE_API"
|
69 |
+
climate_template = "CLIMATE_TEMPLATE"
|
70 |
+
command_template = "COMMAND_TEMPLATE"
|
71 |
+
currency_api = "CURRENCY_API"
|
72 |
+
custom_pmpermit = "CUSTOM_PMPERMIT"
|
73 |
+
gban_template = "GBAN_TEMPLATE"
|
74 |
+
github_user_template = "GITHUB_USER_TEMPLATE"
|
75 |
+
help_emoji = "HELP_EMOJI"
|
76 |
+
help_template = "HELP_TEMPLATE"
|
77 |
+
is_logger = "IS_LOGGER"
|
78 |
+
lyrics_api = "LYRICS_API"
|
79 |
+
manga_template = "MANGA_TEMPLATE"
|
80 |
+
ocr_api = "OCR_API"
|
81 |
+
ping_pic = "PING_PIC"
|
82 |
+
ping_template = "PING_TEMPLATE"
|
83 |
+
pm_logger = "PM_LOGGER"
|
84 |
+
pm_max_spam = "PM_MAX_SPAM"
|
85 |
+
pmpermit = "PMPERMIT"
|
86 |
+
pmpermit_pic = "PMPERMIT_PIC"
|
87 |
+
remove_bg_api = "REMOVE_BG_API"
|
88 |
+
thumbnail_url = "THUMBNAIL_URL"
|
89 |
+
statistics_template = "STATISTICS_TEMPLATE"
|
90 |
+
sticker_packname = "STICKER_PACKNAME"
|
91 |
+
tag_logger = "TAG_LOGGER"
|
92 |
+
telegraph_account = "TELEGRAPH_ACCOUNT"
|
93 |
+
time_zone = "TIME_ZONE"
|
94 |
+
unload_plugins = "UNLOAD_PLUGINS"
|
95 |
+
unsplash_api = "UNSPLASH_API"
|
96 |
+
usage_template = "USAGE_TEMPLATE"
|
97 |
+
user_info_template = "USER_INFO_TEMPLATE"
|
98 |
+
|
99 |
+
|
100 |
+
class Limits:
|
101 |
+
AdminRoleLength = 16
|
102 |
+
AdminsLimit = 50
|
103 |
+
BioLength = 70
|
104 |
+
BotDescriptionLength = 512
|
105 |
+
BotInfoLength = 120
|
106 |
+
BotsLimit = 20
|
107 |
+
CaptionLength = 1024
|
108 |
+
ChannelGroupsLimit = 500
|
109 |
+
ChatTitleLength = 128
|
110 |
+
FileNameLength = 60
|
111 |
+
MessageLength = 4096
|
112 |
+
NameLength = 64
|
113 |
+
PremiumBioLength = 140
|
114 |
+
PremiumCaptionLength = 2048
|
115 |
+
PremiumChannelGroupsLimit = 1000
|
116 |
+
StickerAniamtedLimit = 50
|
117 |
+
StickerPackNameLength = 64
|
118 |
+
StickerStaticLimit = 120
|
119 |
+
|
120 |
+
|
121 |
+
class Symbols:
|
122 |
+
anchor = "โ"
|
123 |
+
arrow_left = "ยซ"
|
124 |
+
arrow_right = "ยป"
|
125 |
+
back = "๐ back"
|
126 |
+
bullet = "โข"
|
127 |
+
check_mark = "โ"
|
128 |
+
close = "๐๏ธ"
|
129 |
+
cross_mark = "โ"
|
130 |
+
diamond_1 = "โ"
|
131 |
+
diamond_2 = "โ"
|
132 |
+
next = "โค next"
|
133 |
+
previous = "prev โค"
|
134 |
+
radio_select = "โ"
|
135 |
+
radio_unselect = "ใ"
|
136 |
+
triangle_left = "โ"
|
137 |
+
triangle_right = "โธ"
|
138 |
+
|
139 |
+
|
140 |
+
os_configs = [
|
141 |
+
"API_HASH",
|
142 |
+
"API_ID",
|
143 |
+
"BOT_TOKEN",
|
144 |
+
"DATABASE_URL",
|
145 |
+
"DEPLOY_REPO",
|
146 |
+
"HANDLERS",
|
147 |
+
"HEROKU_APIKEY",
|
148 |
+
"HEROKU_APPNAME",
|
149 |
+
"LOGGER_ID",
|
150 |
+
"OWNER_ID",
|
151 |
+
"PLUGINS_REPO",
|
152 |
+
]
|
153 |
+
all_env: list[str] = [
|
154 |
+
value for key, value in ENV.__dict__.items() if not key.startswith("__")
|
155 |
+
]
|
Hellbot/core/database.py
ADDED
@@ -0,0 +1,584 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import datetime
|
2 |
+
import time
|
3 |
+
|
4 |
+
from motor import motor_asyncio
|
5 |
+
from motor.core import AgnosticClient
|
6 |
+
|
7 |
+
from .config import Config, Symbols
|
8 |
+
from .logger import LOGS
|
9 |
+
|
10 |
+
|
11 |
+
class Database:
|
12 |
+
def __init__(self, uri: str) -> None:
|
13 |
+
self.client: AgnosticClient = motor_asyncio.AsyncIOMotorClient(uri)
|
14 |
+
self.db = self.client["Hellbot"]
|
15 |
+
|
16 |
+
self.afk = self.db["afk"]
|
17 |
+
self.antiflood = self.db["antiflood"]
|
18 |
+
self.autopost = self.db["autopost"]
|
19 |
+
self.blacklist = self.db["blacklist"]
|
20 |
+
self.echo = self.db["echo"]
|
21 |
+
self.env = self.db["env"]
|
22 |
+
self.filter = self.db["filter"]
|
23 |
+
self.forcesub = self.db["forcesub"]
|
24 |
+
self.gachabots = self.db["gachabots"]
|
25 |
+
self.gban = self.db["gban"]
|
26 |
+
self.gmute = self.db["gmute"]
|
27 |
+
self.greetings = self.db["greetings"]
|
28 |
+
self.mute = self.db["mute"]
|
29 |
+
self.pmpermit = self.db["pmpermit"]
|
30 |
+
self.session = self.db["session"]
|
31 |
+
self.snips = self.db["snips"]
|
32 |
+
self.stan_users = self.db["stan_users"]
|
33 |
+
|
34 |
+
async def connect(self):
|
35 |
+
try:
|
36 |
+
await self.client.admin.command("ping")
|
37 |
+
LOGS.info(
|
38 |
+
f"{Symbols.bullet * 3} Database Connection Established! {Symbols.bullet * 3}"
|
39 |
+
)
|
40 |
+
except Exception as e:
|
41 |
+
LOGS.info(f"{Symbols.cross_mark} DatabaseErr: {e} ")
|
42 |
+
quit(1)
|
43 |
+
|
44 |
+
def get_datetime(self) -> str:
|
45 |
+
return datetime.datetime.now().strftime("%d/%m/%Y - %H:%M")
|
46 |
+
|
47 |
+
async def set_env(self, name: str, value: str) -> None:
|
48 |
+
await self.env.update_one(
|
49 |
+
{"name": name}, {"$set": {"value": value}}, upsert=True
|
50 |
+
)
|
51 |
+
|
52 |
+
async def get_env(self, name: str) -> str | None:
|
53 |
+
if await self.is_env(name):
|
54 |
+
data = await self.env.find_one({"name": name})
|
55 |
+
return data["value"]
|
56 |
+
return None
|
57 |
+
|
58 |
+
async def rm_env(self, name: str) -> None:
|
59 |
+
await self.env.delete_one({"name": name})
|
60 |
+
|
61 |
+
async def is_env(self, name: str) -> bool:
|
62 |
+
if await self.env.find_one({"name": name}):
|
63 |
+
return True
|
64 |
+
return False
|
65 |
+
|
66 |
+
async def get_all_env(self) -> list:
|
67 |
+
return [i async for i in self.env.find({})]
|
68 |
+
|
69 |
+
async def is_stan(self, client: int, user_id: int) -> bool:
|
70 |
+
if await self.stan_users.find_one({"client": client, "user_id": user_id}):
|
71 |
+
return True
|
72 |
+
return False
|
73 |
+
|
74 |
+
async def add_stan(self, client: int, user_id: int) -> bool:
|
75 |
+
if await self.is_stan(client, user_id):
|
76 |
+
return False
|
77 |
+
await self.stan_users.insert_one(
|
78 |
+
{"client": client, "user_id": user_id, "date": self.get_datetime()}
|
79 |
+
)
|
80 |
+
return True
|
81 |
+
|
82 |
+
async def rm_stan(self, client: int, user_id: int) -> bool:
|
83 |
+
if not await self.is_stan(client, user_id):
|
84 |
+
return False
|
85 |
+
await self.stan_users.delete_one({"client": client, "user_id": user_id})
|
86 |
+
return True
|
87 |
+
|
88 |
+
async def get_stans(self, client: int) -> list:
|
89 |
+
return [i async for i in self.stan_users.find({"client": client})]
|
90 |
+
|
91 |
+
async def get_all_stans(self) -> list:
|
92 |
+
return [i async for i in self.stan_users.find({})]
|
93 |
+
|
94 |
+
async def is_session(self, user_id: int) -> bool:
|
95 |
+
if await self.session.find_one({"user_id": user_id}):
|
96 |
+
return True
|
97 |
+
return False
|
98 |
+
|
99 |
+
async def update_session(self, user_id: int, session: str) -> None:
|
100 |
+
await self.session.update_one(
|
101 |
+
{"user_id": user_id},
|
102 |
+
{"$set": {"session": session, "date": self.get_datetime()}},
|
103 |
+
upsert=True,
|
104 |
+
)
|
105 |
+
|
106 |
+
async def rm_session(self, user_id: int) -> None:
|
107 |
+
await self.session.delete_one({"user_id": user_id})
|
108 |
+
|
109 |
+
async def get_session(self, user_id: int):
|
110 |
+
if not await self.is_session(user_id):
|
111 |
+
return False
|
112 |
+
data = await self.session.find_one({"user_id": user_id})
|
113 |
+
return data
|
114 |
+
|
115 |
+
async def get_all_sessions(self) -> list:
|
116 |
+
return [i async for i in self.session.find({})]
|
117 |
+
|
118 |
+
async def is_gbanned(self, user_id: int) -> bool:
|
119 |
+
if await self.gban.find_one({"user_id": user_id}):
|
120 |
+
return True
|
121 |
+
return False
|
122 |
+
|
123 |
+
async def add_gban(self, user_id: int, reason: str) -> bool:
|
124 |
+
if await self.is_gbanned(user_id):
|
125 |
+
return False
|
126 |
+
await self.gban.insert_one(
|
127 |
+
{"user_id": user_id, "reason": reason, "date": self.get_datetime()}
|
128 |
+
)
|
129 |
+
return True
|
130 |
+
|
131 |
+
async def rm_gban(self, user_id: int):
|
132 |
+
if not await self.is_gbanned(user_id):
|
133 |
+
return None
|
134 |
+
reason = (await self.gban.find_one({"user_id": user_id}))["reason"]
|
135 |
+
await self.gban.delete_one({"user_id": user_id})
|
136 |
+
return reason
|
137 |
+
|
138 |
+
async def get_gban(self) -> list:
|
139 |
+
return [i async for i in self.gban.find({})]
|
140 |
+
|
141 |
+
async def get_gban_user(self, user_id: int) -> dict | None:
|
142 |
+
if not await self.is_gbanned(user_id):
|
143 |
+
return None
|
144 |
+
return await self.gban.find_one({"user_id": user_id})
|
145 |
+
|
146 |
+
async def is_gmuted(self, user_id: int) -> bool:
|
147 |
+
if await self.gmute.find_one({"user_id": user_id}):
|
148 |
+
return True
|
149 |
+
return False
|
150 |
+
|
151 |
+
async def add_gmute(self, user_id: int, reason: str) -> bool:
|
152 |
+
if await self.is_gmuted(user_id):
|
153 |
+
return False
|
154 |
+
await self.gmute.insert_one(
|
155 |
+
{"user_id": user_id, "reason": reason, "date": self.get_datetime()}
|
156 |
+
)
|
157 |
+
return True
|
158 |
+
|
159 |
+
async def rm_gmute(self, user_id: int):
|
160 |
+
if not await self.is_gmuted(user_id):
|
161 |
+
return None
|
162 |
+
reason = (await self.gmute.find_one({"user_id": user_id}))["reason"]
|
163 |
+
await self.gmute.delete_one({"user_id": user_id})
|
164 |
+
return reason
|
165 |
+
|
166 |
+
async def get_gmute(self) -> list:
|
167 |
+
return [i async for i in self.gmute.find({})]
|
168 |
+
|
169 |
+
async def add_mute(self, client: int, user_id: int, chat_id: int, reason: str):
|
170 |
+
await self.mute.update_one(
|
171 |
+
{"client": client, "user_id": user_id, "chat_id": chat_id},
|
172 |
+
{"$set": {"reason": reason, "date": self.get_datetime()}},
|
173 |
+
upsert=True,
|
174 |
+
)
|
175 |
+
|
176 |
+
async def rm_mute(self, client: int, user_id: int, chat_id: int) -> str:
|
177 |
+
reason = (await self.get_mute(client, user_id, chat_id))["reason"]
|
178 |
+
await self.mute.delete_one({"client": client, "user_id": user_id, "chat_id": chat_id})
|
179 |
+
return reason
|
180 |
+
|
181 |
+
async def is_muted(self, client: int, user_id: int, chat_id: int) -> bool:
|
182 |
+
if await self.get_mute(client, user_id, chat_id):
|
183 |
+
return True
|
184 |
+
return False
|
185 |
+
|
186 |
+
async def get_mute(self, client: int, user_id: int, chat_id: int):
|
187 |
+
data = await self.mute.find_one({"client": client, "user_id": user_id, "chat_id": chat_id})
|
188 |
+
return data
|
189 |
+
|
190 |
+
async def set_afk(
|
191 |
+
self, user_id: int, reason: str, media: int, media_type: str
|
192 |
+
) -> None:
|
193 |
+
await self.afk.update_one(
|
194 |
+
{"user_id": user_id},
|
195 |
+
{
|
196 |
+
"$set": {
|
197 |
+
"reason": reason,
|
198 |
+
"time": time.time(),
|
199 |
+
"media": media,
|
200 |
+
"media_type": media_type,
|
201 |
+
}
|
202 |
+
},
|
203 |
+
upsert=True,
|
204 |
+
)
|
205 |
+
|
206 |
+
async def get_afk(self, user_id: int):
|
207 |
+
data = await self.afk.find_one({"user_id": user_id})
|
208 |
+
return data
|
209 |
+
|
210 |
+
async def is_afk(self, user_id: int) -> bool:
|
211 |
+
if await self.afk.find_one({"user_id": user_id}):
|
212 |
+
return True
|
213 |
+
return False
|
214 |
+
|
215 |
+
async def rm_afk(self, user_id: int) -> None:
|
216 |
+
await self.afk.delete_one({"user_id": user_id})
|
217 |
+
|
218 |
+
async def set_flood(self, client_chat: tuple[int, int], settings: dict):
|
219 |
+
await self.antiflood.update_one(
|
220 |
+
{"client": client_chat[0], "chat": client_chat[1]},
|
221 |
+
{"$set": settings},
|
222 |
+
upsert=True,
|
223 |
+
)
|
224 |
+
|
225 |
+
async def get_flood(self, client_chat: tuple[int, int]):
|
226 |
+
data = await self.antiflood.find_one(
|
227 |
+
{"client": client_chat[0], "chat": client_chat[1]}
|
228 |
+
)
|
229 |
+
return data or {}
|
230 |
+
|
231 |
+
async def is_flood(self, client_chat: tuple[int, int]) -> bool:
|
232 |
+
data = await self.get_flood(client_chat)
|
233 |
+
|
234 |
+
if not data:
|
235 |
+
return False
|
236 |
+
|
237 |
+
if data["limit"] == 0:
|
238 |
+
return False
|
239 |
+
|
240 |
+
return True
|
241 |
+
|
242 |
+
async def get_all_floods(self) -> list:
|
243 |
+
return [i async for i in self.antiflood.find({})]
|
244 |
+
|
245 |
+
async def set_autopost(self, client: int, from_channel: int, to_channel: int):
|
246 |
+
await self.autopost.update_one(
|
247 |
+
{"client": client},
|
248 |
+
{
|
249 |
+
"$push": {
|
250 |
+
"autopost": {
|
251 |
+
"from_channel": from_channel,
|
252 |
+
"to_channel": to_channel,
|
253 |
+
"date": self.get_datetime(),
|
254 |
+
}
|
255 |
+
}
|
256 |
+
},
|
257 |
+
upsert=True,
|
258 |
+
)
|
259 |
+
|
260 |
+
async def get_autopost(self, client: int, from_channel: int):
|
261 |
+
data = await self.autopost.find_one(
|
262 |
+
{
|
263 |
+
"client": client,
|
264 |
+
"autopost": {"$elemMatch": {"from_channel": from_channel}},
|
265 |
+
}
|
266 |
+
)
|
267 |
+
return data
|
268 |
+
|
269 |
+
async def is_autopost(
|
270 |
+
self, client: int, from_channel: int, to_channel: int = None
|
271 |
+
) -> bool:
|
272 |
+
if to_channel:
|
273 |
+
data = await self.autopost.find_one(
|
274 |
+
{
|
275 |
+
"client": client,
|
276 |
+
"autopost": {
|
277 |
+
"$elemMatch": {
|
278 |
+
"from_channel": from_channel,
|
279 |
+
"to_channel": to_channel,
|
280 |
+
}
|
281 |
+
},
|
282 |
+
}
|
283 |
+
)
|
284 |
+
else:
|
285 |
+
data = await self.autopost.find_one(
|
286 |
+
{
|
287 |
+
"client": client,
|
288 |
+
"autopost": {"$elemMatch": {"from_channel": from_channel}},
|
289 |
+
}
|
290 |
+
)
|
291 |
+
return True if data else False
|
292 |
+
|
293 |
+
async def rm_autopost(self, client: int, from_channel: int, to_channel: int):
|
294 |
+
await self.autopost.update_one(
|
295 |
+
{"client": client},
|
296 |
+
{
|
297 |
+
"$pull": {
|
298 |
+
"autopost": {
|
299 |
+
"from_channel": from_channel,
|
300 |
+
"to_channel": to_channel,
|
301 |
+
}
|
302 |
+
}
|
303 |
+
},
|
304 |
+
)
|
305 |
+
|
306 |
+
async def get_all_autoposts(self, client: int) -> list:
|
307 |
+
return [i async for i in self.autopost.find({"client": client})]
|
308 |
+
|
309 |
+
async def add_blacklist(self, client: int, chat: int, blacklist: str):
|
310 |
+
await self.blacklist.update_one(
|
311 |
+
{"client": client, "chat": chat},
|
312 |
+
{"$push": {"blacklist": blacklist}},
|
313 |
+
upsert=True,
|
314 |
+
)
|
315 |
+
|
316 |
+
async def rm_blacklist(self, client: int, chat: int, blacklist: str):
|
317 |
+
await self.blacklist.update_one(
|
318 |
+
{"client": client, "chat": chat},
|
319 |
+
{"$pull": {"blacklist": blacklist}},
|
320 |
+
)
|
321 |
+
|
322 |
+
async def is_blacklist(self, client: int, chat: int, blacklist: str) -> bool:
|
323 |
+
blacklists = await self.get_all_blacklists(client, chat)
|
324 |
+
if blacklist in blacklists:
|
325 |
+
return True
|
326 |
+
return False
|
327 |
+
|
328 |
+
async def get_all_blacklists(self, client: int, chat: int) -> list:
|
329 |
+
data = await self.blacklist.find_one({"client": client, "chat": chat})
|
330 |
+
|
331 |
+
if not data:
|
332 |
+
return []
|
333 |
+
|
334 |
+
return data["blacklist"]
|
335 |
+
|
336 |
+
async def get_blacklist_clients(self) -> list:
|
337 |
+
return [i async for i in self.blacklist.find({})]
|
338 |
+
|
339 |
+
async def set_echo(self, client: int, chat: int, user: int):
|
340 |
+
await self.echo.update_one(
|
341 |
+
{"client": client, "chat": chat},
|
342 |
+
{"$push": {"echo": user}},
|
343 |
+
upsert=True,
|
344 |
+
)
|
345 |
+
|
346 |
+
async def rm_echo(self, client: int, chat: int, user: int):
|
347 |
+
await self.echo.update_one(
|
348 |
+
{"client": client, "chat": chat},
|
349 |
+
{"$pull": {"echo": user}},
|
350 |
+
)
|
351 |
+
|
352 |
+
async def is_echo(self, client: int, chat: int, user: int) -> bool:
|
353 |
+
data = await self.get_all_echo(client, chat)
|
354 |
+
if user in data:
|
355 |
+
return True
|
356 |
+
return False
|
357 |
+
|
358 |
+
async def get_all_echo(self, client: int, chat: int) -> list:
|
359 |
+
data = await self.echo.find_one({"client": client, "chat": chat})
|
360 |
+
|
361 |
+
if not data:
|
362 |
+
return []
|
363 |
+
|
364 |
+
return data["echo"]
|
365 |
+
|
366 |
+
async def set_filter(self, client: int, chat: int, keyword: str, msgid: int):
|
367 |
+
await self.filter.update_one(
|
368 |
+
{"client": client, "chat": chat},
|
369 |
+
{"$push": {"filter": {"keyword": keyword, "msgid": msgid}}},
|
370 |
+
upsert=True,
|
371 |
+
)
|
372 |
+
|
373 |
+
async def rm_filter(self, client: int, chat: int, keyword: str):
|
374 |
+
await self.filter.update_one(
|
375 |
+
{"client": client, "chat": chat},
|
376 |
+
{"$pull": {"filter": {"keyword": keyword}}},
|
377 |
+
)
|
378 |
+
|
379 |
+
async def rm_all_filters(self, client: int, chat: int):
|
380 |
+
await self.filter.delete_one({"client": client, "chat": chat})
|
381 |
+
|
382 |
+
async def is_filter(self, client: int, chat: int, keyword: str) -> bool:
|
383 |
+
data = await self.get_filter(client, chat, keyword)
|
384 |
+
return True if data else False
|
385 |
+
|
386 |
+
async def get_filter(self, client: int, chat: int, keyword: str):
|
387 |
+
data = await self.filter.find_one(
|
388 |
+
{
|
389 |
+
"client": client,
|
390 |
+
"chat": chat,
|
391 |
+
"filter": {"$elemMatch": {"keyword": keyword}},
|
392 |
+
}
|
393 |
+
)
|
394 |
+
return data
|
395 |
+
|
396 |
+
async def get_all_filters(self, client: int, chat: int) -> list:
|
397 |
+
data = await self.filter.find_one({"client": client, "chat": chat})
|
398 |
+
|
399 |
+
if not data:
|
400 |
+
return []
|
401 |
+
|
402 |
+
return data["filter"]
|
403 |
+
|
404 |
+
async def set_snip(self, client: int, chat: int, keyword: str, msgid: int):
|
405 |
+
await self.snips.update_one(
|
406 |
+
{"client": client, "chat": chat},
|
407 |
+
{"$push": {"snips": {"keyword": keyword, "msgid": msgid}}},
|
408 |
+
upsert=True,
|
409 |
+
)
|
410 |
+
|
411 |
+
async def rm_snip(self, client: int, chat: int, keyword: str):
|
412 |
+
await self.snips.update_one(
|
413 |
+
{"client": client, "chat": chat},
|
414 |
+
{"$pull": {"snips": {"keyword": keyword}}},
|
415 |
+
)
|
416 |
+
|
417 |
+
async def rm_all_snips(self, client: int, chat: int):
|
418 |
+
await self.snips.delete_one({"client": client, "chat": chat})
|
419 |
+
|
420 |
+
async def is_snip(self, client: int, chat: int, keyword: str) -> bool:
|
421 |
+
data = await self.get_snip(client, chat, keyword)
|
422 |
+
return True if data else False
|
423 |
+
|
424 |
+
async def get_snip(self, client: int, chat: int, keyword: str):
|
425 |
+
data = await self.snips.find_one(
|
426 |
+
{
|
427 |
+
"client": client,
|
428 |
+
"chat": chat,
|
429 |
+
"snips": {"$elemMatch": {"keyword": keyword}},
|
430 |
+
}
|
431 |
+
)
|
432 |
+
return data
|
433 |
+
|
434 |
+
async def get_all_snips(self, client: int, chat: int) -> list:
|
435 |
+
data = await self.snips.find_one({"client": client, "chat": chat})
|
436 |
+
|
437 |
+
if not data:
|
438 |
+
return []
|
439 |
+
|
440 |
+
return data["snips"]
|
441 |
+
|
442 |
+
async def add_pmpermit(self, client: int, user: int):
|
443 |
+
await self.pmpermit.update_one(
|
444 |
+
{"client": client, "user": user},
|
445 |
+
{"$set": {"date": self.get_datetime()}},
|
446 |
+
upsert=True,
|
447 |
+
)
|
448 |
+
|
449 |
+
async def rm_pmpermit(self, client: int, user: int):
|
450 |
+
await self.pmpermit.delete_one({"client": client, "user": user})
|
451 |
+
|
452 |
+
async def is_pmpermit(self, client: int, user: int) -> bool:
|
453 |
+
data = await self.get_pmpermit(client, user)
|
454 |
+
return True if data else False
|
455 |
+
|
456 |
+
async def get_pmpermit(self, client: int, user: int):
|
457 |
+
data = await self.pmpermit.find_one({"client": client, "user": user})
|
458 |
+
return data
|
459 |
+
|
460 |
+
async def get_all_pmpermits(self, client: int) -> list:
|
461 |
+
return [i async for i in self.pmpermit.find({"client": client})]
|
462 |
+
|
463 |
+
async def set_welcome(self, client: int, chat: int, message: int):
|
464 |
+
await self.greetings.update_one(
|
465 |
+
{"client": client, "chat": chat, "welcome": True},
|
466 |
+
{"$set": {"message": message}},
|
467 |
+
upsert=True,
|
468 |
+
)
|
469 |
+
|
470 |
+
async def rm_welcome(self, client: int, chat: int):
|
471 |
+
await self.greetings.delete_one(
|
472 |
+
{"client": client, "chat": chat, "welcome": True}
|
473 |
+
)
|
474 |
+
|
475 |
+
async def is_welcome(self, client: int, chat: int) -> bool:
|
476 |
+
data = await self.get_welcome(client, chat)
|
477 |
+
return True if data else False
|
478 |
+
|
479 |
+
async def get_welcome(self, client: int, chat: int):
|
480 |
+
data = await self.greetings.find_one(
|
481 |
+
{"client": client, "chat": chat, "welcome": True}
|
482 |
+
)
|
483 |
+
return data
|
484 |
+
|
485 |
+
async def set_goodbye(self, client: int, chat: int, message: int):
|
486 |
+
await self.greetings.update_one(
|
487 |
+
{"client": client, "chat": chat, "welcome": False},
|
488 |
+
{"$set": {"message": message}},
|
489 |
+
upsert=True,
|
490 |
+
)
|
491 |
+
|
492 |
+
async def rm_goodbye(self, client: int, chat: int):
|
493 |
+
await self.greetings.delete_one(
|
494 |
+
{"client": client, "chat": chat, "welcome": False}
|
495 |
+
)
|
496 |
+
|
497 |
+
async def is_goodbye(self, client: int, chat: int) -> bool:
|
498 |
+
data = await self.get_goodbye(client, chat)
|
499 |
+
return True if data else False
|
500 |
+
|
501 |
+
async def get_goodbye(self, client: int, chat: int):
|
502 |
+
data = await self.greetings.find_one(
|
503 |
+
{"client": client, "chat": chat, "welcome": False}
|
504 |
+
)
|
505 |
+
return data
|
506 |
+
|
507 |
+
async def get_all_greetings(self, client: int) -> list:
|
508 |
+
return [i async for i in self.greetings.find({"client": client})]
|
509 |
+
|
510 |
+
async def add_forcesub(self, chat: int, must_join: int):
|
511 |
+
await self.forcesub.update_one(
|
512 |
+
{"chat": chat},
|
513 |
+
{"$push": {"must_join": must_join}},
|
514 |
+
upsert=True,
|
515 |
+
)
|
516 |
+
|
517 |
+
async def rm_forcesub(self, chat: int, must_join: int) -> int:
|
518 |
+
await self.forcesub.update_one(
|
519 |
+
{"chat": chat},
|
520 |
+
{"$pull": {"must_join": must_join}},
|
521 |
+
)
|
522 |
+
data = await self.forcesub.find_one({"chat": chat})
|
523 |
+
return len(data["must_join"])
|
524 |
+
|
525 |
+
async def rm_all_forcesub(self, in_chat: int):
|
526 |
+
await self.forcesub.delete_one({"chat": in_chat})
|
527 |
+
|
528 |
+
async def is_forcesub(self, chat: int, must_join: int) -> bool:
|
529 |
+
data = await self.get_forcesub(chat)
|
530 |
+
if must_join in data["must_join"]:
|
531 |
+
return True
|
532 |
+
return False
|
533 |
+
|
534 |
+
async def get_forcesub(self, in_chat: int):
|
535 |
+
data = await self.forcesub.find_one({"chat": in_chat})
|
536 |
+
return data
|
537 |
+
|
538 |
+
async def get_all_forcesubs(self) -> list:
|
539 |
+
return [i async for i in self.forcesub.find({})]
|
540 |
+
|
541 |
+
async def add_gachabot(
|
542 |
+
self, client: int, bot: tuple[int, str], catch_command: str, chat_id: int
|
543 |
+
):
|
544 |
+
await self.gachabots.update_one(
|
545 |
+
{"client": client, "bot": bot[0]},
|
546 |
+
{
|
547 |
+
"$set": {
|
548 |
+
"username": bot[1],
|
549 |
+
"catch_command": catch_command,
|
550 |
+
"chat_id": chat_id,
|
551 |
+
"date": self.get_datetime(),
|
552 |
+
}
|
553 |
+
},
|
554 |
+
upsert=True,
|
555 |
+
)
|
556 |
+
|
557 |
+
async def rm_gachabot(self, client: int, bot: int, chat_id: int = None):
|
558 |
+
if chat_id:
|
559 |
+
await self.gachabots.delete_one(
|
560 |
+
{"client": client, "bot": bot, "chat_id": chat_id}
|
561 |
+
)
|
562 |
+
else:
|
563 |
+
await self.gachabots.delete_one({"client": client, "bot": bot})
|
564 |
+
|
565 |
+
async def is_gachabot(self, client: int, bot: int, chat_id: int) -> bool:
|
566 |
+
data = await self.get_gachabot(client, bot, chat_id)
|
567 |
+
return True if data else False
|
568 |
+
|
569 |
+
async def get_gachabot(self, client: int, bot: int, chat_id: int):
|
570 |
+
data = await self.gachabots.find_one(
|
571 |
+
{"client": client, "bot": bot, "chat_id": chat_id}
|
572 |
+
)
|
573 |
+
|
574 |
+
return data
|
575 |
+
|
576 |
+
async def get_all_gachabots(self, client: int) -> list:
|
577 |
+
return [i async for i in self.gachabots.find({"client": client})]
|
578 |
+
|
579 |
+
async def get_all_gachabots_id(self) -> list:
|
580 |
+
data = await self.gachabots.distinct("bot")
|
581 |
+
return data
|
582 |
+
|
583 |
+
|
584 |
+
db = Database(Config.DATABASE_URL)
|
Hellbot/core/initializer.py
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sys
|
2 |
+
from .clients import hellbot
|
3 |
+
from .config import Config, Symbols
|
4 |
+
from .database import db
|
5 |
+
from .logger import LOGS
|
6 |
+
|
7 |
+
|
8 |
+
async def _AuthUsers() -> None:
|
9 |
+
temp_list = []
|
10 |
+
temp_list.append(Config.OWNER_ID)
|
11 |
+
temp_list.extend([(await client.get_me()).id for client in hellbot.users])
|
12 |
+
|
13 |
+
stan_users = await db.get_all_stans()
|
14 |
+
for user in stan_users:
|
15 |
+
temp_list.append(user["user_id"])
|
16 |
+
|
17 |
+
users = list(set(temp_list))
|
18 |
+
for user in users:
|
19 |
+
Config.AUTH_USERS.add(user)
|
20 |
+
|
21 |
+
temp_list = None
|
22 |
+
LOGS.info(
|
23 |
+
f"{Symbols.arrow_right * 2} Added Authorized Users {Symbols.arrow_left * 2}"
|
24 |
+
)
|
25 |
+
|
26 |
+
|
27 |
+
async def _StanUsers() -> None:
|
28 |
+
users = await db.get_all_stans()
|
29 |
+
for user in users:
|
30 |
+
Config.STAN_USERS.add(user["user_id"])
|
31 |
+
|
32 |
+
LOGS.info(f"{Symbols.arrow_right * 2} Added Stan Users {Symbols.arrow_left * 2}")
|
33 |
+
|
34 |
+
|
35 |
+
async def _GbanUsers() -> None:
|
36 |
+
users = await db.get_gban()
|
37 |
+
for user in users:
|
38 |
+
Config.BANNED_USERS.add(user["user_id"])
|
39 |
+
|
40 |
+
LOGS.info(
|
41 |
+
f"{Symbols.arrow_right * 2} Added {len(users)} Gbanned Users {Symbols.arrow_left * 2}"
|
42 |
+
)
|
43 |
+
|
44 |
+
musers = await db.get_gmute()
|
45 |
+
for user in musers:
|
46 |
+
Config.MUTED_USERS.add(user["user_id"])
|
47 |
+
|
48 |
+
LOGS.info(
|
49 |
+
f"{Symbols.arrow_right * 2} Added {len(musers)} Gmuted Users {Symbols.arrow_left * 2}"
|
50 |
+
)
|
51 |
+
|
52 |
+
|
53 |
+
async def UserSetup() -> None:
|
54 |
+
"""Initialize Users Config"""
|
55 |
+
LOGS.info(f"{Symbols.bullet * 3} Setting Up Users {Symbols.bullet * 3}")
|
56 |
+
await _AuthUsers()
|
57 |
+
await _StanUsers()
|
58 |
+
await _GbanUsers()
|
59 |
+
|
60 |
+
|
61 |
+
async def ForcesubSetup() -> None:
|
62 |
+
"""Initialize Forcesub Config"""
|
63 |
+
chats = await db.get_all_forcesubs()
|
64 |
+
for chat in chats:
|
65 |
+
if chat not in Config.FORCESUBS:
|
66 |
+
Config.FORCESUBS.add(chat["chat"])
|
67 |
+
|
68 |
+
|
69 |
+
async def GachaBotsSetup() -> None:
|
70 |
+
"""Initialize GachaBots Config"""
|
71 |
+
bots = await db.get_all_gachabots_id()
|
72 |
+
for bot in bots:
|
73 |
+
Config.GACHA_BOTS.add(bot)
|
74 |
+
|
75 |
+
|
76 |
+
async def TemplateSetup() -> None:
|
77 |
+
"""Initialize Templates Config"""
|
78 |
+
module_name = "temp_module"
|
79 |
+
module = sys.modules.get(module_name)
|
80 |
+
if module is None:
|
81 |
+
module = type(sys)(module_name)
|
82 |
+
|
83 |
+
with open("Hellbot/functions/templates.py", "r", encoding="utf-8") as file:
|
84 |
+
exec(file.read(), module.__dict__)
|
85 |
+
|
86 |
+
global_vars = module.__dict__
|
87 |
+
|
88 |
+
var_n_value: dict[str, str] = {
|
89 |
+
var_name: global_vars[var_name][0]
|
90 |
+
for var_name in global_vars
|
91 |
+
if var_name.isupper() and not callable(global_vars[var_name])
|
92 |
+
}
|
93 |
+
|
94 |
+
Config.TEMPLATES = var_n_value
|
Hellbot/core/logger.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import logging
|
2 |
+
from logging.handlers import RotatingFileHandler
|
3 |
+
|
4 |
+
logging.basicConfig(
|
5 |
+
format="[%(asctime)s]:[%(name)s]:[%(levelname)s] - %(message)s",
|
6 |
+
level=logging.INFO,
|
7 |
+
datefmt="%H:%M:%S",
|
8 |
+
handlers=[
|
9 |
+
RotatingFileHandler(
|
10 |
+
"HellBot.log", maxBytes=(1024 * 1024 * 5), backupCount=10, encoding="utf-8"
|
11 |
+
),
|
12 |
+
logging.StreamHandler(),
|
13 |
+
],
|
14 |
+
)
|
15 |
+
|
16 |
+
|
17 |
+
logging.getLogger("pyrogram").setLevel(logging.ERROR)
|
18 |
+
|
19 |
+
LOGS = logging.getLogger("HellBot")
|
Hellbot/functions/__init__.py
ADDED
File without changes
|
Hellbot/functions/admins.py
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram.enums import ChatMembersFilter, ChatMemberStatus, ChatType
|
2 |
+
from pyrogram.types import Chat
|
3 |
+
|
4 |
+
from Hellbot.core import hellbot
|
5 |
+
|
6 |
+
|
7 |
+
async def get_admins(chat_id: int) -> list:
|
8 |
+
admins = []
|
9 |
+
async for x in hellbot.bot.get_chat_members(
|
10 |
+
chat_id, filter=ChatMembersFilter.ADMINISTRATORS
|
11 |
+
):
|
12 |
+
admins.append(x.user.id)
|
13 |
+
return admins
|
14 |
+
|
15 |
+
|
16 |
+
async def is_user_admin(chat: Chat, user_id: int) -> bool:
|
17 |
+
if chat.type in [ChatType.PRIVATE, ChatType.BOT]:
|
18 |
+
return True
|
19 |
+
|
20 |
+
status = (await chat.get_member(user_id)).status
|
21 |
+
if status in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR]:
|
22 |
+
return True
|
23 |
+
|
24 |
+
return False
|
Hellbot/functions/convert.py
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import time
|
3 |
+
|
4 |
+
from pyrogram.types import Message
|
5 |
+
from PIL import Image
|
6 |
+
from Hellbot.core import Config
|
7 |
+
|
8 |
+
from .tools import runcmd
|
9 |
+
|
10 |
+
|
11 |
+
async def convert_to_gif(file: str, is_video: bool = False) -> str:
|
12 |
+
resultFileName = f"gif_{round(time.time())}.mp4"
|
13 |
+
|
14 |
+
if is_video:
|
15 |
+
cmd = f"ffmpeg -i '{file}' -c copy '{resultFileName}'"
|
16 |
+
else:
|
17 |
+
cmd = f"lottie_convert.py '{file}' '{resultFileName}'"
|
18 |
+
|
19 |
+
await runcmd(cmd)
|
20 |
+
|
21 |
+
return resultFileName
|
22 |
+
|
23 |
+
|
24 |
+
async def tgs_to_png(file: str) -> str:
|
25 |
+
resultFileName = f"png_{round(time.time())}.png"
|
26 |
+
|
27 |
+
cmd = f"lottie_convert.py '{file}' '{resultFileName}'"
|
28 |
+
|
29 |
+
await runcmd(cmd)
|
30 |
+
|
31 |
+
return resultFileName
|
32 |
+
|
33 |
+
|
34 |
+
async def image_to_sticker(file: str, max_size: tuple = (512, 512)) -> tuple[bool, str]:
|
35 |
+
try:
|
36 |
+
with Image.open(file) as img:
|
37 |
+
original_width, original_height = img.size
|
38 |
+
|
39 |
+
new_width = min(original_width, max_size[0])
|
40 |
+
new_height = min(original_height, max_size[1])
|
41 |
+
|
42 |
+
if original_width > max_size[0] or original_height > max_size[1]:
|
43 |
+
img = img.resize((new_width, new_height), Image.LANCZOS)
|
44 |
+
|
45 |
+
file_name = f"sticker_{int(time.time())}.png"
|
46 |
+
img.save(file_name, "PNG")
|
47 |
+
|
48 |
+
return True, file_name
|
49 |
+
|
50 |
+
except Exception as e:
|
51 |
+
return False, str(e)
|
52 |
+
|
53 |
+
|
54 |
+
async def video_to_png(
|
55 |
+
file: str, duration: float, output: str = None
|
56 |
+
) -> tuple[str, bool]:
|
57 |
+
resultFileName = output or f"{os.path.basename(file)}.png"
|
58 |
+
cut_at = duration // 2
|
59 |
+
|
60 |
+
cmd = f"ffmpeg -ss {cut_at} -i '{file}' -vframes 1 '{resultFileName}'"
|
61 |
+
|
62 |
+
_, err, _, _ = await runcmd(cmd)
|
63 |
+
if err:
|
64 |
+
return err, False
|
65 |
+
|
66 |
+
return resultFileName, True
|
67 |
+
|
68 |
+
|
69 |
+
async def video_to_sticker(file: Message) -> tuple[str, bool]:
|
70 |
+
try:
|
71 |
+
if file.animation:
|
72 |
+
width, height = file.animation.width, file.animation.height
|
73 |
+
elif file.video:
|
74 |
+
width, height = file.video.width, file.video.height
|
75 |
+
else:
|
76 |
+
return "Unsupported media type.", False
|
77 |
+
|
78 |
+
file_path = await file.download(Config.TEMP_DIR)
|
79 |
+
output_path = os.path.join(Config.TEMP_DIR, "videoSticker.webm")
|
80 |
+
|
81 |
+
if height > width:
|
82 |
+
scale_params = f"scale=-1:512"
|
83 |
+
else:
|
84 |
+
scale_params = f"scale=512:-1"
|
85 |
+
|
86 |
+
cmd = (
|
87 |
+
f"ffmpeg -i {file_path} "
|
88 |
+
f"-vf fps=30,{scale_params} -t 3 -c:v libvpx-vp9 -b:v 256k -an -pix_fmt yuv420p -auto-alt-ref 0 -loop 0 "
|
89 |
+
f"-f webm {output_path}"
|
90 |
+
)
|
91 |
+
|
92 |
+
await runcmd(cmd)
|
93 |
+
os.remove(file_path)
|
94 |
+
|
95 |
+
return output_path, True
|
96 |
+
|
97 |
+
except Exception as e:
|
98 |
+
return f"Error during conversion: {e}", False
|
Hellbot/functions/driver.py
ADDED
@@ -0,0 +1,318 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import datetime
|
2 |
+
import json
|
3 |
+
import random
|
4 |
+
import re
|
5 |
+
import time
|
6 |
+
import urllib.parse
|
7 |
+
from urllib.parse import quote_plus
|
8 |
+
|
9 |
+
import httpx
|
10 |
+
import requests
|
11 |
+
from pytz import country_names, country_timezones, timezone
|
12 |
+
from selenium import webdriver
|
13 |
+
from selenium.webdriver.chrome.options import Options
|
14 |
+
from selenium.webdriver.chrome.service import Service
|
15 |
+
from selenium.webdriver.common.by import By
|
16 |
+
|
17 |
+
from Hellbot.core import ENV, Config, db
|
18 |
+
|
19 |
+
from .formatter import format_text
|
20 |
+
|
21 |
+
|
22 |
+
class ChromeDriver:
|
23 |
+
def __init__(self) -> None:
|
24 |
+
self.carbon_theme = [
|
25 |
+
"3024-night",
|
26 |
+
"a11y-dark",
|
27 |
+
"blackboard",
|
28 |
+
"base16-dark",
|
29 |
+
"base16-light",
|
30 |
+
"cobalt",
|
31 |
+
"duotone-dark",
|
32 |
+
"hopscotch",
|
33 |
+
"lucario",
|
34 |
+
"material",
|
35 |
+
"monokai",
|
36 |
+
"night-owl",
|
37 |
+
"nord",
|
38 |
+
"oceanic-next",
|
39 |
+
"one-light",
|
40 |
+
"one-dark",
|
41 |
+
"panda-syntax",
|
42 |
+
"paraiso-dark",
|
43 |
+
"seti",
|
44 |
+
"shades-of-purple",
|
45 |
+
"solarized+dark",
|
46 |
+
"solarized+light",
|
47 |
+
"synthwave-84",
|
48 |
+
"twilight",
|
49 |
+
"verminal",
|
50 |
+
"vscode",
|
51 |
+
"yeti",
|
52 |
+
"zenburn",
|
53 |
+
]
|
54 |
+
|
55 |
+
def get(self):
|
56 |
+
if not Config.CHROME_BIN:
|
57 |
+
return (
|
58 |
+
None,
|
59 |
+
"ChromeBinaryErr: No binary path found! Install Chromium or Google Chrome.",
|
60 |
+
)
|
61 |
+
|
62 |
+
try:
|
63 |
+
options = Options()
|
64 |
+
options.binary_location = Config.CHROME_BIN
|
65 |
+
options.add_argument("--disable-dev-shm-usage")
|
66 |
+
options.add_argument("--ignore-certificate-errors")
|
67 |
+
options.add_argument("--disable-gpu")
|
68 |
+
options.add_argument("--headless=new")
|
69 |
+
options.add_argument("--test-type")
|
70 |
+
options.add_argument("--no-sandbox")
|
71 |
+
options.add_argument("--window-size=1920x1080")
|
72 |
+
options.add_experimental_option(
|
73 |
+
"prefs", {"download.default_directory": "./"}
|
74 |
+
)
|
75 |
+
service = Service(Config.CHROME_DRIVER)
|
76 |
+
driver = webdriver.Chrome(options, service)
|
77 |
+
return driver, None
|
78 |
+
except Exception as e:
|
79 |
+
return None, f"ChromeDriverErr: {e}"
|
80 |
+
|
81 |
+
def close(self, driver: webdriver.Chrome):
|
82 |
+
driver.close()
|
83 |
+
driver.quit()
|
84 |
+
|
85 |
+
@property
|
86 |
+
def get_random_carbon(self) -> str:
|
87 |
+
url = "https://carbon.now.sh/?l=auto"
|
88 |
+
url += f"&t={random.choice(self.carbon_theme)}"
|
89 |
+
url += f"&bg=rgba%28{random.randint(1, 255)}%2C{random.randint(1, 255)}%2C{random.randint(1, 255)}%2C1%29"
|
90 |
+
url += "&code="
|
91 |
+
return url
|
92 |
+
|
93 |
+
async def generate_carbon(
|
94 |
+
self, driver: webdriver.Chrome, code: str, is_random: bool = False
|
95 |
+
) -> str:
|
96 |
+
filename = f"{round(time.time())}"
|
97 |
+
BASE_URL = (
|
98 |
+
self.get_random_carbon
|
99 |
+
if is_random
|
100 |
+
else "https://carbon.now.sh/?l=auto&code="
|
101 |
+
)
|
102 |
+
|
103 |
+
driver.get(BASE_URL + format_text(quote_plus(code)))
|
104 |
+
driver.command_executor._commands["send_command"] = (
|
105 |
+
"POST",
|
106 |
+
"/session/$sessionId/chromium/send_command",
|
107 |
+
)
|
108 |
+
params = {
|
109 |
+
"cmd": "Page.setDownloadBehavior",
|
110 |
+
"params": {"behavior": "allow", "downloadPath": Config.DWL_DIR},
|
111 |
+
}
|
112 |
+
driver.execute("send_command", params)
|
113 |
+
|
114 |
+
driver.find_element(By.XPATH, "//button[@id='export-menu']").click()
|
115 |
+
driver.find_element(By.XPATH, "//input[@title='filename']").send_keys(filename)
|
116 |
+
driver.find_element(By.XPATH, "//button[@id='export-png']").click()
|
117 |
+
|
118 |
+
return f"{Config.DWL_DIR}/{filename}.png"
|
119 |
+
|
120 |
+
|
121 |
+
class ClimateDriver:
|
122 |
+
def __init__(self) -> None:
|
123 |
+
self.weather_api = "https://api.openweathermap.org/data/2.5/weather?lat={0}&lon={1}&appid={2}&units=metric"
|
124 |
+
self.location_api = (
|
125 |
+
"https://api.openweathermap.org/geo/1.0/direct?q={0}&limit=1&appid={1}"
|
126 |
+
)
|
127 |
+
self.pollution_api = "http://api.openweathermap.org/data/2.5/air_pollution?lat={0}&lon={1}&appid={2}"
|
128 |
+
self.AQI_DICT = {
|
129 |
+
1: "Good",
|
130 |
+
2: "Fair",
|
131 |
+
3: "Moderate",
|
132 |
+
4: "Poor",
|
133 |
+
5: "Very Poor",
|
134 |
+
}
|
135 |
+
|
136 |
+
async def fetchLocation(self, city: str, apiKey: str):
|
137 |
+
response = httpx.get(self.location_api.format(city, apiKey))
|
138 |
+
if response.status_code == 200:
|
139 |
+
data = response.json()
|
140 |
+
if data:
|
141 |
+
return data[0]["lat"], data[0]["lon"]
|
142 |
+
return None, None
|
143 |
+
|
144 |
+
async def fetchWeather(self, city: str, apiKey: str):
|
145 |
+
lattitude, longitude = await self.fetchLocation(city, apiKey)
|
146 |
+
if not lattitude and not longitude:
|
147 |
+
return None
|
148 |
+
|
149 |
+
response = httpx.get(self.weather_api.format(lattitude, longitude, apiKey))
|
150 |
+
if response.status_code == 200:
|
151 |
+
return response.json()
|
152 |
+
return None
|
153 |
+
|
154 |
+
async def fetchAirPollution(self, city: str, apiKey: str):
|
155 |
+
lattitude, longitude = await self.fetchLocation(city, apiKey)
|
156 |
+
if not lattitude and not longitude:
|
157 |
+
return None
|
158 |
+
|
159 |
+
response = httpx.get(self.pollution_api.format(lattitude, longitude, apiKey))
|
160 |
+
if response.status_code == 200:
|
161 |
+
return response.json()
|
162 |
+
return None
|
163 |
+
|
164 |
+
async def getTime(self, timestamp: int) -> str:
|
165 |
+
tz = await db.get_env(ENV.time_zone) or "Asia/Kolkata"
|
166 |
+
tz = timezone(tz)
|
167 |
+
return datetime.datetime.fromtimestamp(timestamp, tz=tz).strftime("%I:%M %p")
|
168 |
+
|
169 |
+
def getCountry(self, country_code: str) -> str:
|
170 |
+
return country_names.get(country_code, "Unknown")
|
171 |
+
|
172 |
+
def getCountryTimezone(self, country_code: str) -> str:
|
173 |
+
timezones = country_timezones.get(country_code, [])
|
174 |
+
if timezones:
|
175 |
+
return ", ".join(timezones)
|
176 |
+
return "Unknown"
|
177 |
+
|
178 |
+
def getWindData(self, windSpeed: str, windDegree: str) -> str:
|
179 |
+
dirs = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"]
|
180 |
+
ix = round(windDegree / (360.00 / len(dirs)))
|
181 |
+
kmph = str(float(windSpeed) * 3.6) + " km/h"
|
182 |
+
return f"[{dirs[ix % len(dirs)]}] {kmph}"
|
183 |
+
|
184 |
+
|
185 |
+
class YoutubeDriver:
|
186 |
+
def __init__(self, search_terms: str, max_results: int = 5):
|
187 |
+
self.base_url = "https://youtube.com/results?search_query={0}"
|
188 |
+
self.search_terms = search_terms
|
189 |
+
self.max_results = max_results
|
190 |
+
self.videos = self._search()
|
191 |
+
|
192 |
+
def _search(self):
|
193 |
+
encoded_search = urllib.parse.quote_plus(self.search_terms)
|
194 |
+
response = requests.get(self.base_url.format(encoded_search)).text
|
195 |
+
|
196 |
+
while "ytInitialData" not in response:
|
197 |
+
response = requests.get(self.base_url.format(encoded_search)).text
|
198 |
+
|
199 |
+
results = self._parse_html(response)
|
200 |
+
|
201 |
+
if self.max_results is not None and len(results) > self.max_results:
|
202 |
+
return results[: self.max_results]
|
203 |
+
|
204 |
+
return results
|
205 |
+
|
206 |
+
def _parse_html(self, response: str):
|
207 |
+
results = []
|
208 |
+
start = response.index("ytInitialData") + len("ytInitialData") + 3
|
209 |
+
end = response.index("};", start) + 1
|
210 |
+
json_str = response[start:end]
|
211 |
+
data = json.loads(json_str)
|
212 |
+
|
213 |
+
videos = data["contents"]["twoColumnSearchResultsRenderer"]["primaryContents"][
|
214 |
+
"sectionListRenderer"
|
215 |
+
]["contents"][0]["itemSectionRenderer"]["contents"]
|
216 |
+
|
217 |
+
for video in videos:
|
218 |
+
res = {}
|
219 |
+
if "videoRenderer" in video.keys():
|
220 |
+
video_data = video.get("videoRenderer", {})
|
221 |
+
_id = video_data.get("videoId", None)
|
222 |
+
|
223 |
+
res["id"] = _id
|
224 |
+
res["thumbnail"] = f"https://i.ytimg.com/vi/{_id}/hqdefault.jpg"
|
225 |
+
res["title"] = (
|
226 |
+
video_data.get("title", {}).get("runs", [[{}]])[0].get("text", None)
|
227 |
+
)
|
228 |
+
res["channel"] = (
|
229 |
+
video_data.get("longBylineText", {})
|
230 |
+
.get("runs", [[{}]])[0]
|
231 |
+
.get("text", None)
|
232 |
+
)
|
233 |
+
res["duration"] = video_data.get("lengthText", {}).get("simpleText", 0)
|
234 |
+
res["views"] = video_data.get("viewCountText", {}).get(
|
235 |
+
"simpleText", "Unknown"
|
236 |
+
)
|
237 |
+
res["publish_time"] = video_data.get("publishedTimeText", {}).get(
|
238 |
+
"simpleText", "Unknown"
|
239 |
+
)
|
240 |
+
res["url_suffix"] = (
|
241 |
+
video_data.get("navigationEndpoint", {})
|
242 |
+
.get("commandMetadata", {})
|
243 |
+
.get("webCommandMetadata", {})
|
244 |
+
.get("url", None)
|
245 |
+
)
|
246 |
+
|
247 |
+
results.append(res)
|
248 |
+
return results
|
249 |
+
|
250 |
+
def to_dict(self, clear_cache=True) -> list[dict]:
|
251 |
+
result = self.videos
|
252 |
+
if clear_cache:
|
253 |
+
self.videos = []
|
254 |
+
return result
|
255 |
+
|
256 |
+
@staticmethod
|
257 |
+
def check_url(url: str) -> tuple[bool, str]:
|
258 |
+
if "&" in url:
|
259 |
+
url = url[: url.index("&")]
|
260 |
+
|
261 |
+
if "?si=" in url:
|
262 |
+
url = url[: url.index("?si=")]
|
263 |
+
|
264 |
+
youtube_regex = (
|
265 |
+
r"(https?://)?(www\.)?"
|
266 |
+
r"(youtube|youtu|youtube-nocookie)\.(com|be)/"
|
267 |
+
r'(video|embed|shorts/|watch\?v=|v/|e/|u/\\w+/|\\w+/)?([^"&?\\s]{11})'
|
268 |
+
)
|
269 |
+
match = re.match(youtube_regex, url)
|
270 |
+
if match:
|
271 |
+
return True, match.group(6)
|
272 |
+
else:
|
273 |
+
return False, "Invalid YouTube URL!"
|
274 |
+
|
275 |
+
@staticmethod
|
276 |
+
def song_options() -> dict:
|
277 |
+
return {
|
278 |
+
"format": "bestaudio",
|
279 |
+
"addmetadata": True,
|
280 |
+
"key": "FFmpegMetadata",
|
281 |
+
"prefer_ffmpeg": True,
|
282 |
+
"geo_bypass": True,
|
283 |
+
"nocheckcertificate": True,
|
284 |
+
"postprocessors": [
|
285 |
+
{
|
286 |
+
"key": "FFmpegExtractAudio",
|
287 |
+
"preferredcodec": "mp3",
|
288 |
+
"preferredquality": "480",
|
289 |
+
}
|
290 |
+
],
|
291 |
+
"outtmpl": "%(id)s",
|
292 |
+
"quiet": True,
|
293 |
+
"logtostderr": False,
|
294 |
+
}
|
295 |
+
|
296 |
+
@staticmethod
|
297 |
+
def video_options() -> dict:
|
298 |
+
return {
|
299 |
+
"format": "best",
|
300 |
+
"addmetadata": True,
|
301 |
+
"key": "FFmpegMetadata",
|
302 |
+
"prefer_ffmpeg": True,
|
303 |
+
"geo_bypass": True,
|
304 |
+
"nocheckcertificate": True,
|
305 |
+
"postprocessors": [
|
306 |
+
{
|
307 |
+
"key": "FFmpegVideoConvertor",
|
308 |
+
"preferedformat": "mp4",
|
309 |
+
}
|
310 |
+
],
|
311 |
+
"outtmpl": "%(id)s.mp4",
|
312 |
+
"quiet": True,
|
313 |
+
"logtostderr": False,
|
314 |
+
}
|
315 |
+
|
316 |
+
|
317 |
+
Driver = ChromeDriver()
|
318 |
+
Climate = ClimateDriver()
|
Hellbot/functions/formatter.py
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import math
|
2 |
+
import re
|
3 |
+
|
4 |
+
|
5 |
+
def format_text(text: str) -> str:
|
6 |
+
emoji_pattern = re.compile(
|
7 |
+
"["
|
8 |
+
"\U0001F600-\U0001F64F" # emoticons
|
9 |
+
"\U0001F300-\U0001F5FF" # symbols & pictographs
|
10 |
+
"\U0001F680-\U0001F6FF" # transport & map symbols
|
11 |
+
"\U0001F700-\U0001F77F" # alchemical symbols
|
12 |
+
"\U0001F780-\U0001F7FF" # Geometric Shapes Extended
|
13 |
+
"\U0001F800-\U0001F8FF" # Supplemental Arrows-C
|
14 |
+
"\U0001F900-\U0001F9FF" # Supplemental Symbols and Pictographs
|
15 |
+
"\U0001FA00-\U0001FA6F" # Chess Symbols
|
16 |
+
"\U0001FA70-\U0001FAFF" # Symbols and Pictographs Extended-A
|
17 |
+
"\U00002702-\U000027B0" # Dingbats
|
18 |
+
"\U000024C2-\U0001F251" # enclosed characters
|
19 |
+
"]+",
|
20 |
+
flags=re.UNICODE,
|
21 |
+
)
|
22 |
+
|
23 |
+
return re.sub(emoji_pattern, "", text)
|
24 |
+
|
25 |
+
|
26 |
+
def superscript(text: str) -> str:
|
27 |
+
superscript_digits = str.maketrans("0123456789", "โฐยนยฒยณโดโตโถโทโธโน")
|
28 |
+
return text.translate(superscript_digits)
|
29 |
+
|
30 |
+
|
31 |
+
def subscript(text: str) -> str:
|
32 |
+
subscript_digits = str.maketrans("0123456789", "โโโโโโ
โโโโ")
|
33 |
+
return text.translate(subscript_digits)
|
34 |
+
|
35 |
+
|
36 |
+
def readable_time(seconds: int) -> str:
|
37 |
+
count = 0
|
38 |
+
out_time = ""
|
39 |
+
time_list = []
|
40 |
+
time_suffix_list = ["secs", "mins", "hrs", "days"]
|
41 |
+
|
42 |
+
while count < 4:
|
43 |
+
count += 1
|
44 |
+
remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)
|
45 |
+
if seconds == 0 and remainder == 0:
|
46 |
+
break
|
47 |
+
time_list.append(int(result))
|
48 |
+
seconds = int(remainder)
|
49 |
+
|
50 |
+
for x in range(len(time_list)):
|
51 |
+
time_list[x] = str(time_list[x]) + time_suffix_list[x]
|
52 |
+
|
53 |
+
if len(time_list) == 4:
|
54 |
+
out_time += time_list.pop() + ", "
|
55 |
+
|
56 |
+
time_list.reverse()
|
57 |
+
out_time += " ".join(time_list)
|
58 |
+
|
59 |
+
return out_time or "0 secs"
|
60 |
+
|
61 |
+
|
62 |
+
def humanbytes(size: int):
|
63 |
+
if not size:
|
64 |
+
return ""
|
65 |
+
power = 2**10
|
66 |
+
number = 0
|
67 |
+
dict_power_n = {0: " ", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"}
|
68 |
+
while size > power:
|
69 |
+
size /= power
|
70 |
+
number += 1
|
71 |
+
return str(round(size, 2)) + " " + dict_power_n[number] + "B"
|
72 |
+
|
73 |
+
|
74 |
+
def add_to_dict(data: dict, keys: list, value: str | int | bool = None) -> None:
|
75 |
+
current_level = data
|
76 |
+
for key in keys[:-1]:
|
77 |
+
current_level = current_level.setdefault(key, {})
|
78 |
+
current_level[keys[-1]] = value
|
79 |
+
|
80 |
+
|
81 |
+
def get_from_dict(data: dict, key: list):
|
82 |
+
current_level = data
|
83 |
+
for k in key:
|
84 |
+
current_level = current_level[k]
|
85 |
+
return current_level
|
86 |
+
|
87 |
+
|
88 |
+
def limit_per_page(limit: int) -> int:
|
89 |
+
return math.ceil(limit / 10)
|
90 |
+
|
91 |
+
|
92 |
+
def secs_to_mins(secs: int) -> str:
|
93 |
+
mins, secs = divmod(secs, 60)
|
94 |
+
return f"{mins}:{secs}"
|
Hellbot/functions/images.py
ADDED
@@ -0,0 +1,389 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import calendar
|
2 |
+
import logging
|
3 |
+
import os
|
4 |
+
import random
|
5 |
+
import textwrap
|
6 |
+
import time
|
7 |
+
|
8 |
+
import httpx
|
9 |
+
from icrawler.builtin import BingImageCrawler
|
10 |
+
from PIL import Image, ImageDraw, ImageEnhance, ImageFont, ImageOps
|
11 |
+
from unidecode import unidecode
|
12 |
+
|
13 |
+
from .formatter import format_text, limit_per_page
|
14 |
+
|
15 |
+
|
16 |
+
def convert_to_png(image: str) -> str:
|
17 |
+
output_img = f"png_{round(time.time())}.png"
|
18 |
+
|
19 |
+
img = Image.open(image)
|
20 |
+
img.save(output_img, "PNG")
|
21 |
+
img.close()
|
22 |
+
|
23 |
+
os.remove(image)
|
24 |
+
return output_img
|
25 |
+
|
26 |
+
|
27 |
+
def add_rounded_corners(img: Image.Image, radius: int = 80):
|
28 |
+
circle = Image.new("L", (radius * 2, radius * 2), 0)
|
29 |
+
|
30 |
+
draw = ImageDraw.Draw(circle)
|
31 |
+
draw.ellipse((0, 0, radius * 2, radius * 2), fill=255)
|
32 |
+
|
33 |
+
alpha = Image.new("L", img.size, 255)
|
34 |
+
w, h = img.size
|
35 |
+
|
36 |
+
alpha.paste(circle.crop((0, 0, radius, radius)), (0, 0))
|
37 |
+
alpha.paste(circle.crop((radius, 0, radius * 2, radius)), (w - radius, 0))
|
38 |
+
alpha.paste(circle.crop((0, radius, radius, radius * 2)), (0, h - radius))
|
39 |
+
alpha.paste(
|
40 |
+
circle.crop((radius, radius, radius * 2, radius * 2)), (w - radius, h - radius)
|
41 |
+
)
|
42 |
+
|
43 |
+
img.putalpha(alpha)
|
44 |
+
|
45 |
+
return img
|
46 |
+
|
47 |
+
|
48 |
+
def generate_alive_image(
|
49 |
+
username: str, profile_pic: str, del_img: bool, font_path: str
|
50 |
+
) -> str:
|
51 |
+
if not profile_pic.endswith(".png"):
|
52 |
+
profile_pic = convert_to_png(profile_pic)
|
53 |
+
|
54 |
+
img = Image.open(profile_pic).convert("RGBA")
|
55 |
+
img_rotated = img.rotate(45, expand=True)
|
56 |
+
|
57 |
+
width, height = img_rotated.size
|
58 |
+
left = width / 2 - 480 / 2
|
59 |
+
top = height / 2 - 480 / 2
|
60 |
+
right = width / 2 + 480 / 2
|
61 |
+
bottom = height / 2 + 480 / 2
|
62 |
+
|
63 |
+
cropped_img = img_rotated.crop((left, top, right, bottom))
|
64 |
+
|
65 |
+
img_rotated = ImageOps.fit(
|
66 |
+
cropped_img, (480, 480), method=0, bleed=0.0, centering=(0.5, 0.5)
|
67 |
+
)
|
68 |
+
|
69 |
+
img_rounded = add_rounded_corners(img_rotated)
|
70 |
+
|
71 |
+
img = img_rounded.rotate(-45, expand=True)
|
72 |
+
|
73 |
+
background = Image.open("./Hellbot/resources/images/hellbot_alive.png").convert(
|
74 |
+
"RGBA"
|
75 |
+
)
|
76 |
+
|
77 |
+
background.paste(img, (383, 445), img)
|
78 |
+
draw = ImageDraw.Draw(background)
|
79 |
+
|
80 |
+
text = format_text(username[:25] + ("..." if len(username) > 25 else ""))
|
81 |
+
|
82 |
+
font_size = width // 15
|
83 |
+
font = ImageFont.truetype(font_path, font_size, encoding="utf-8")
|
84 |
+
|
85 |
+
text_length = draw.textlength(text, font)
|
86 |
+
position = ((background.width - text_length) / 2, background.height - 145)
|
87 |
+
draw.text(
|
88 |
+
position,
|
89 |
+
unidecode(text),
|
90 |
+
(255, 255, 255),
|
91 |
+
font,
|
92 |
+
)
|
93 |
+
|
94 |
+
output_img = f"alive_{int(time.time())}.png"
|
95 |
+
background.save(output_img, "PNG")
|
96 |
+
background.close()
|
97 |
+
|
98 |
+
if del_img:
|
99 |
+
os.remove(profile_pic)
|
100 |
+
|
101 |
+
return output_img
|
102 |
+
|
103 |
+
|
104 |
+
async def get_wallpapers(
|
105 |
+
access: str,
|
106 |
+
limit: int,
|
107 |
+
query: str = "",
|
108 |
+
isRandom: bool = False,
|
109 |
+
) -> list[str]:
|
110 |
+
headers = {"Authorization": f"Client-ID {access}"}
|
111 |
+
|
112 |
+
if isRandom:
|
113 |
+
api = f"https://api.unsplash.com/photos/random?count={limit}"
|
114 |
+
response = httpx.get(api, headers=headers)
|
115 |
+
results = response.json()
|
116 |
+
urls = [i["urls"]["raw"] for i in results]
|
117 |
+
else:
|
118 |
+
api = f"https://api.unsplash.com/search/photos?query={query}&page={limit_per_page(limit)}"
|
119 |
+
response = httpx.get(api, headers=headers)
|
120 |
+
result = response.json()
|
121 |
+
urls = [i["urls"]["raw"] for i in result["results"]]
|
122 |
+
|
123 |
+
random.shuffle(urls)
|
124 |
+
|
125 |
+
return urls[:limit]
|
126 |
+
|
127 |
+
|
128 |
+
async def deep_fry(img: Image.Image) -> Image.Image:
|
129 |
+
colours = (
|
130 |
+
(random.randint(50, 200), random.randint(40, 170), random.randint(40, 190)),
|
131 |
+
(random.randint(190, 255), random.randint(170, 240), random.randint(180, 250)),
|
132 |
+
)
|
133 |
+
|
134 |
+
img = img.copy().convert("RGB")
|
135 |
+
img = img.convert("RGB")
|
136 |
+
|
137 |
+
width, height = img.width, img.height
|
138 |
+
|
139 |
+
img = img.resize(
|
140 |
+
(
|
141 |
+
int(width ** random.uniform(0.8, 0.9)),
|
142 |
+
int(height ** random.uniform(0.8, 0.9)),
|
143 |
+
),
|
144 |
+
resample=Image.LANCZOS,
|
145 |
+
)
|
146 |
+
|
147 |
+
img = img.resize(
|
148 |
+
(
|
149 |
+
int(width ** random.uniform(0.85, 0.95)),
|
150 |
+
int(height ** random.uniform(0.85, 0.95)),
|
151 |
+
),
|
152 |
+
resample=Image.BILINEAR,
|
153 |
+
)
|
154 |
+
|
155 |
+
img = img.resize(
|
156 |
+
(
|
157 |
+
int(width ** random.uniform(0.89, 0.98)),
|
158 |
+
int(height ** random.uniform(0.89, 0.98)),
|
159 |
+
),
|
160 |
+
resample=Image.BICUBIC,
|
161 |
+
)
|
162 |
+
|
163 |
+
img = img.resize((width, height), resample=Image.BICUBIC)
|
164 |
+
img = ImageOps.posterize(img, random.randint(3, 7))
|
165 |
+
|
166 |
+
overlay = img.split()[0]
|
167 |
+
overlay = ImageEnhance.Contrast(overlay).enhance(random.uniform(1.0, 2.0))
|
168 |
+
overlay = ImageEnhance.Brightness(overlay).enhance(random.uniform(1.0, 2.0))
|
169 |
+
overlay = ImageOps.colorize(overlay, colours[0], colours[1])
|
170 |
+
|
171 |
+
img = Image.blend(img, overlay, random.uniform(0.1, 0.4))
|
172 |
+
img = ImageEnhance.Sharpness(img).enhance(random.randint(5, 300))
|
173 |
+
|
174 |
+
return img
|
175 |
+
|
176 |
+
|
177 |
+
async def make_logo(background: str, text: str, font_path: str) -> str:
|
178 |
+
if not background.endswith(".png"):
|
179 |
+
background = convert_to_png(background)
|
180 |
+
|
181 |
+
bg = Image.open(background).convert("RGBA")
|
182 |
+
bgWidth, bgHeight = bg.size
|
183 |
+
|
184 |
+
text = format_text(text)
|
185 |
+
font_size = bgWidth // len(text)
|
186 |
+
font = ImageFont.truetype(font_path, font_size, encoding="utf-8")
|
187 |
+
|
188 |
+
draw = ImageDraw.Draw(bg)
|
189 |
+
text_length = draw.textlength(text, font)
|
190 |
+
|
191 |
+
x = (bgWidth - text_length) // 2
|
192 |
+
y = (bgHeight - font_size) // 2
|
193 |
+
|
194 |
+
draw.text(
|
195 |
+
(x, y),
|
196 |
+
unidecode(text),
|
197 |
+
(255, 255, 255),
|
198 |
+
font,
|
199 |
+
stroke_fill=(0, 0, 0),
|
200 |
+
stroke_width=2,
|
201 |
+
)
|
202 |
+
|
203 |
+
output_img = f"logo_{int(time.time())}.png"
|
204 |
+
bg.save(output_img, "PNG")
|
205 |
+
bg.close()
|
206 |
+
|
207 |
+
os.remove(background)
|
208 |
+
|
209 |
+
return output_img
|
210 |
+
|
211 |
+
|
212 |
+
async def draw_meme(
|
213 |
+
image_path: str, upper_text: str = "", lower_text: str = ""
|
214 |
+
) -> list[str]:
|
215 |
+
image = Image.open(image_path)
|
216 |
+
width, height = image.size
|
217 |
+
|
218 |
+
draw = ImageDraw.Draw(image)
|
219 |
+
font_size = int((30 / 500) * width)
|
220 |
+
font = ImageFont.truetype("./Hellbot/resources/fonts/Montserrat.ttf", font_size)
|
221 |
+
|
222 |
+
curr_height, padding = 20, 5
|
223 |
+
for utext in textwrap.wrap(upper_text, 25):
|
224 |
+
upper_width = draw.textlength(utext, font=font)
|
225 |
+
draw.text(
|
226 |
+
((width - upper_width) / 2, curr_height),
|
227 |
+
unidecode(utext),
|
228 |
+
(255, 255, 255),
|
229 |
+
font,
|
230 |
+
stroke_width=3,
|
231 |
+
stroke_fill=(0, 0, 0),
|
232 |
+
)
|
233 |
+
curr_height += font_size + padding
|
234 |
+
|
235 |
+
curr_height = height - font_size
|
236 |
+
for ltext in reversed(textwrap.wrap(lower_text, 25)):
|
237 |
+
lower_width = draw.textlength(ltext, font=font)
|
238 |
+
draw.text(
|
239 |
+
((width - lower_width) / 2, curr_height - font_size),
|
240 |
+
ltext,
|
241 |
+
(255, 255, 255),
|
242 |
+
font,
|
243 |
+
stroke_width=3,
|
244 |
+
stroke_fill=(0, 0, 0),
|
245 |
+
)
|
246 |
+
curr_height -= font_size + padding
|
247 |
+
|
248 |
+
filename = f"meme_{int(time.time())}"
|
249 |
+
image.save(f"{filename}.png", "PNG", optimize=True)
|
250 |
+
image.save(f"{filename}.webp", "WEBP", optimize=True)
|
251 |
+
image.close()
|
252 |
+
|
253 |
+
return [f"{filename}.png", f"{filename}.webp"]
|
254 |
+
|
255 |
+
|
256 |
+
async def remove_bg(api_key: str, image: str) -> str:
|
257 |
+
response = httpx.post(
|
258 |
+
"https://api.remove.bg/v1.0/removebg",
|
259 |
+
files={"image_file": open(image, "rb")},
|
260 |
+
data={"size": "auto"},
|
261 |
+
headers={"X-Api-Key": api_key},
|
262 |
+
)
|
263 |
+
filename = f"removedbg_{int(time.time())}.png"
|
264 |
+
|
265 |
+
if response.is_success:
|
266 |
+
with open(filename, "wb") as f:
|
267 |
+
f.write(response.content)
|
268 |
+
else:
|
269 |
+
raise Exception(
|
270 |
+
f"RemoveBGError: [{response.status_code}] {response.content.decode('utf-8')}"
|
271 |
+
)
|
272 |
+
|
273 |
+
return filename
|
274 |
+
|
275 |
+
|
276 |
+
def create_gradient(
|
277 |
+
size: tuple[int, int],
|
278 |
+
color_start: tuple[int, int, int],
|
279 |
+
color_end: tuple[int, int, int],
|
280 |
+
) -> Image.Image:
|
281 |
+
gradient = Image.new("RGB", (size))
|
282 |
+
draw = ImageDraw.Draw(gradient)
|
283 |
+
|
284 |
+
for x in range(size[0]):
|
285 |
+
r = int(color_start[0] + (color_end[0] - color_start[0]) * (x / size[0]))
|
286 |
+
g = int(color_start[1] + (color_end[1] - color_start[1]) * (x / size[0]))
|
287 |
+
b = int(color_start[2] + (color_end[2] - color_start[2]) * (x / size[0]))
|
288 |
+
|
289 |
+
draw.line([(x, 0), (x, size[1])], fill=(r, g, b))
|
290 |
+
|
291 |
+
return gradient
|
292 |
+
|
293 |
+
|
294 |
+
async def create_calendar(year: int, month: int) -> str:
|
295 |
+
cal = calendar.monthcalendar(year, month)
|
296 |
+
month_name = calendar.month_name[month]
|
297 |
+
|
298 |
+
calendar_image = create_gradient((500, 500), (140, 200, 250), (0, 150, 200))
|
299 |
+
draw = ImageDraw.Draw(calendar_image)
|
300 |
+
|
301 |
+
month_font = ImageFont.truetype("./Hellbot/resources/fonts/Montserrat.ttf", 40)
|
302 |
+
month_x = (
|
303 |
+
calendar_image.width - draw.textlength(f"{month_name} {year}", month_font)
|
304 |
+
) // 2
|
305 |
+
month_y = 30
|
306 |
+
draw.text(
|
307 |
+
(month_x, month_y),
|
308 |
+
f"{month_name} {year}",
|
309 |
+
(43, 255, 136),
|
310 |
+
month_font,
|
311 |
+
stroke_width=2,
|
312 |
+
stroke_fill=(255, 40, 40),
|
313 |
+
)
|
314 |
+
|
315 |
+
week_font = ImageFont.truetype("./Hellbot/resources/fonts/Montserrat.ttf", 23)
|
316 |
+
weekdays_text = " ".join([day[:3] for day in calendar.day_name])
|
317 |
+
textsize = draw.textlength(weekdays_text, week_font)
|
318 |
+
draw.text(
|
319 |
+
((calendar_image.width - textsize) // 2, month_y + 80),
|
320 |
+
weekdays_text,
|
321 |
+
(150, 190, 200),
|
322 |
+
week_font,
|
323 |
+
stroke_width=2,
|
324 |
+
stroke_fill=(200, 150, 250),
|
325 |
+
)
|
326 |
+
|
327 |
+
scale_factor = 1.5
|
328 |
+
cell_size = 30
|
329 |
+
padding = 15
|
330 |
+
|
331 |
+
font = ImageFont.truetype("./Hellbot/resources/fonts/Montserrat.ttf", 30)
|
332 |
+
|
333 |
+
for week_num, week in enumerate(cal):
|
334 |
+
for day_num, day in enumerate(week):
|
335 |
+
x = int(day_num * (cell_size + padding) * scale_factor)
|
336 |
+
y = int((week_num + 3) * (cell_size + padding) * scale_factor)
|
337 |
+
|
338 |
+
cell_width = int(cell_size * scale_factor)
|
339 |
+
cell_height = int(cell_size * scale_factor)
|
340 |
+
|
341 |
+
text_x = (
|
342 |
+
int(x + (cell_width - draw.textlength(str(day), font=font)) // 2)
|
343 |
+
+ cell_size
|
344 |
+
)
|
345 |
+
text_y = (
|
346 |
+
int(y + (cell_height - draw.textlength(str(day), font=font)) // 2) - 55
|
347 |
+
)
|
348 |
+
|
349 |
+
if day != 0:
|
350 |
+
draw.text(
|
351 |
+
(text_x, text_y),
|
352 |
+
str(day),
|
353 |
+
(240, 200, 100),
|
354 |
+
font,
|
355 |
+
stroke_width=1,
|
356 |
+
stroke_fill=(0, 0, 0),
|
357 |
+
)
|
358 |
+
|
359 |
+
filename = f"calendar_{int(time.time())}.png"
|
360 |
+
calendar_image.save(filename, "PNG")
|
361 |
+
calendar_image.close()
|
362 |
+
|
363 |
+
return filename
|
364 |
+
|
365 |
+
|
366 |
+
async def create_thumbnail(photo: str, xy: tuple[int, int], file_size: int):
|
367 |
+
img = Image.open(photo)
|
368 |
+
img.thumbnail(xy)
|
369 |
+
|
370 |
+
size_in_bytes = file_size * 1024
|
371 |
+
quality = 90
|
372 |
+
|
373 |
+
while True:
|
374 |
+
img.save(photo, "JPEG", quality=quality, optimize=True)
|
375 |
+
if os.path.getsize(photo) <= size_in_bytes:
|
376 |
+
break
|
377 |
+
|
378 |
+
quality -= 5
|
379 |
+
|
380 |
+
return photo
|
381 |
+
|
382 |
+
|
383 |
+
async def download_images(query: str, limit: int) -> list[str]:
|
384 |
+
offset = random.randint(0, 20)
|
385 |
+
|
386 |
+
crawler = BingImageCrawler(log_level=logging.ERROR)
|
387 |
+
crawler.crawl(query, offset=offset, max_num=limit)
|
388 |
+
|
389 |
+
return [os.path.join("images", image) for image in os.listdir("images")]
|
Hellbot/functions/media.py
ADDED
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from typing import Union
|
3 |
+
|
4 |
+
import requests
|
5 |
+
from pyrogram import Client
|
6 |
+
from pyrogram.file_id import FileId
|
7 |
+
from pyrogram.raw.functions.messages import UploadMedia
|
8 |
+
from pyrogram.raw.types import (
|
9 |
+
DocumentAttributeFilename,
|
10 |
+
InputDocument,
|
11 |
+
InputMediaUploadedDocument,
|
12 |
+
)
|
13 |
+
from pyrogram.types import Animation, Audio, Document, Message, Photo, Sticker, Video
|
14 |
+
|
15 |
+
from Hellbot.core import Symbols
|
16 |
+
|
17 |
+
|
18 |
+
async def get_metedata(media: Union[Animation, Audio, Document, Photo, Sticker, Video]):
|
19 |
+
output = "๐ MetaData:\n\n"
|
20 |
+
if isinstance(media, Animation):
|
21 |
+
output += f"<b>{Symbols.diamond_2} File ID:</b> <code>{media.file_id}</code>\n"
|
22 |
+
output += f"<b>{Symbols.diamond_2} Width:</b> <code>{media.width}</code>\n"
|
23 |
+
output += f"<b>{Symbols.diamond_2} Height:</b> <code>{media.height}</code>\n"
|
24 |
+
output += (
|
25 |
+
f"<b>{Symbols.diamond_2} Duration:</b> <code>{media.duration}</code>\n"
|
26 |
+
)
|
27 |
+
output += (
|
28 |
+
f"<b>{Symbols.diamond_2} File Name:</b> <code>{media.file_name}</code>\n"
|
29 |
+
)
|
30 |
+
output += (
|
31 |
+
f"<b>{Symbols.diamond_2} Mime Type:</b> <code>{media.mime_type}</code>\n"
|
32 |
+
)
|
33 |
+
output += (
|
34 |
+
f"<b>{Symbols.diamond_2} File Size:</b> <code>{media.file_size}</code>\n"
|
35 |
+
)
|
36 |
+
output += f"<b>{Symbols.diamond_2} Date:</b> <code>{media.date}</code>\n"
|
37 |
+
output += f"<b>{Symbols.diamond_2} File Type:</b> <code>Animation</code>\n"
|
38 |
+
elif isinstance(media, Audio):
|
39 |
+
output += f"<b>{Symbols.diamond_2} File ID:</b> <code>{media.file_id}</code>\n"
|
40 |
+
output += (
|
41 |
+
f"<b>{Symbols.diamond_2} Duration:</b> <code>{media.duration}</code>\n"
|
42 |
+
)
|
43 |
+
output += (
|
44 |
+
f"<b>{Symbols.diamond_2} Performer:</b> <code>{media.performer}</code>\n"
|
45 |
+
)
|
46 |
+
output += f"<b>{Symbols.diamond_2} Title:</b> <code>{media.title}</code>\n"
|
47 |
+
output += (
|
48 |
+
f"<b>{Symbols.diamond_2} File Name:</b> <code>{media.file_name}</code>\n"
|
49 |
+
)
|
50 |
+
output += (
|
51 |
+
f"<b>{Symbols.diamond_2} Mime Type:</b> <code>{media.mime_type}</code>\n"
|
52 |
+
)
|
53 |
+
output += (
|
54 |
+
f"<b>{Symbols.diamond_2} File Size:</b> <code>{media.file_size}</code>\n"
|
55 |
+
)
|
56 |
+
output += f"<b>{Symbols.diamond_2} Date:</b> <code>{media.date}</code>\n"
|
57 |
+
output += f"<b>{Symbols.diamond_2} File Type:</b> <code>Audio</code>\n"
|
58 |
+
elif isinstance(media, Document):
|
59 |
+
output += f"<b>{Symbols.diamond_2} File ID:</b> <code>{media.file_id}</code>\n"
|
60 |
+
output += (
|
61 |
+
f"<b>{Symbols.diamond_2} File Name:</b> <code>{media.file_name}</code>\n"
|
62 |
+
)
|
63 |
+
output += (
|
64 |
+
f"<b>{Symbols.diamond_2} Mime Type:</b> <code>{media.mime_type}</code>\n"
|
65 |
+
)
|
66 |
+
output += (
|
67 |
+
f"<b>{Symbols.diamond_2} File Size:</b> <code>{media.file_size}</code>\n"
|
68 |
+
)
|
69 |
+
output += f"<b>{Symbols.diamond_2} Date:</b> <code>{media.date}</code>\n"
|
70 |
+
output += f"<b>{Symbols.diamond_2} File Type:</b> <code>Document</code>\n"
|
71 |
+
elif isinstance(media, Photo):
|
72 |
+
output += f"<b>{Symbols.diamond_2} File ID:</b> <code>{media.file_id}</code>\n"
|
73 |
+
output += f"<b>{Symbols.diamond_2} Width:</b> <code>{media.width}</code>\n"
|
74 |
+
output += f"<b>{Symbols.diamond_2} Height:</b> <code>{media.height}</code>\n"
|
75 |
+
output += f"<b>{Symbols.diamond_2} File Name:</b> <code>photo.jpg</code>\n"
|
76 |
+
output += f"<b>{Symbols.diamond_2} Mime Type:</b> <code>image/jpeg</code>\n"
|
77 |
+
output += (
|
78 |
+
f"<b>{Symbols.diamond_2} File Size:</b> <code>{media.file_size}</code>\n"
|
79 |
+
)
|
80 |
+
output += f"<b>{Symbols.diamond_2} Date:</b> <code>{media.date}</code>\n"
|
81 |
+
output += f"<b>{Symbols.diamond_2} File Type:</b> <code>Photo</code>\n"
|
82 |
+
elif isinstance(media, Sticker):
|
83 |
+
output += f"<b>{Symbols.diamond_2} File ID:</b> <code>{media.file_id}</code>\n"
|
84 |
+
output += f"<b>{Symbols.diamond_2} Width:</b> <code>{media.width}</code>\n"
|
85 |
+
output += f"<b>{Symbols.diamond_2} Height:</b> <code>{media.height}</code>\n"
|
86 |
+
output += (
|
87 |
+
f"<b>{Symbols.diamond_2} File Name:</b> <code>{media.file_name}</code>\n"
|
88 |
+
)
|
89 |
+
output += (
|
90 |
+
f"<b>{Symbols.diamond_2} Mime Type:</b> <code>{media.mime_type}</code>\n"
|
91 |
+
)
|
92 |
+
output += (
|
93 |
+
f"<b>{Symbols.diamond_2} File Size:</b> <code>{media.file_size}</code>\n"
|
94 |
+
)
|
95 |
+
output += f"<b>{Symbols.diamond_2} Date:</b> <code>{media.date}</code>\n"
|
96 |
+
output += f"<b>{Symbols.diamond_2} Emoji:</b> <code>{media.emoji}</code>\n"
|
97 |
+
output += (
|
98 |
+
f"<b>{Symbols.diamond_2} Set Name:</b> <code>{media.set_name}</code>\n"
|
99 |
+
)
|
100 |
+
output += f"<b>{Symbols.diamond_2} File Type:</b> <code>Sticker</code>\n"
|
101 |
+
elif isinstance(media, Video):
|
102 |
+
output += f"<b>{Symbols.diamond_2} File ID:</b> <code>{media.file_id}</code>\n"
|
103 |
+
output += f"<b>{Symbols.diamond_2} Width:</b> <code>{media.width}</code>\n"
|
104 |
+
output += f"<b>{Symbols.diamond_2} Height:</b> <code>{media.height}</code>\n"
|
105 |
+
output += (
|
106 |
+
f"<b>{Symbols.diamond_2} Duration:</b> <code>{media.duration}</code>\n"
|
107 |
+
)
|
108 |
+
output += (
|
109 |
+
f"<b>{Symbols.diamond_2} File Name:</b> <code>{media.file_name}</code>\n"
|
110 |
+
)
|
111 |
+
output += (
|
112 |
+
f"<b>{Symbols.diamond_2} Mime Type:</b> <code>{media.mime_type}</code>\n"
|
113 |
+
)
|
114 |
+
output += (
|
115 |
+
f"<b>{Symbols.diamond_2} File Size:</b> <code>{media.file_size}</code>\n"
|
116 |
+
)
|
117 |
+
output += f"<b>{Symbols.diamond_2} Date:</b> <code>{media.date}</code>\n"
|
118 |
+
output += f"<b>{Symbols.diamond_2} File Type:</b> <code>Video</code>\n"
|
119 |
+
else:
|
120 |
+
return None
|
121 |
+
|
122 |
+
return output
|
123 |
+
|
124 |
+
|
125 |
+
def get_media_text_ocr(filename: str, api_key: str, language: str = "eng") -> dict:
|
126 |
+
payload = {
|
127 |
+
"isOverlayRequired": False,
|
128 |
+
"apikey": api_key,
|
129 |
+
"language": language,
|
130 |
+
}
|
131 |
+
|
132 |
+
with open(filename, "rb") as f:
|
133 |
+
r = requests.post(
|
134 |
+
"https://api.ocr.space/parse/image",
|
135 |
+
files={filename: f},
|
136 |
+
data=payload,
|
137 |
+
)
|
138 |
+
|
139 |
+
return r.json()
|
140 |
+
|
141 |
+
|
142 |
+
async def upload_media(client: Client, chat_id: int, file: str) -> InputDocument:
|
143 |
+
media = await client.invoke(
|
144 |
+
UploadMedia(
|
145 |
+
peer=(await client.resolve_peer(chat_id)),
|
146 |
+
media=InputMediaUploadedDocument(
|
147 |
+
file=(await client.save_file(file)),
|
148 |
+
mime_type=client.guess_mime_type(file) or "application/zip",
|
149 |
+
attributes=[
|
150 |
+
DocumentAttributeFilename(file_name=os.path.basename(file))
|
151 |
+
],
|
152 |
+
force_file=True,
|
153 |
+
),
|
154 |
+
),
|
155 |
+
)
|
156 |
+
|
157 |
+
return InputDocument(
|
158 |
+
id=media.document.id,
|
159 |
+
access_hash=media.document.access_hash,
|
160 |
+
file_reference=media.document.file_reference,
|
161 |
+
)
|
162 |
+
|
163 |
+
|
164 |
+
async def get_media_from_id(file_id: str) -> InputDocument:
|
165 |
+
file = FileId.decode(file_id)
|
166 |
+
|
167 |
+
return InputDocument(
|
168 |
+
id=file.media_id,
|
169 |
+
access_hash=file.access_hash,
|
170 |
+
file_reference=file.file_reference,
|
171 |
+
)
|
172 |
+
|
173 |
+
|
174 |
+
async def get_media_fileid(message: Message) -> str | None:
|
175 |
+
file_id = None
|
176 |
+
if message.photo:
|
177 |
+
file_id = message.photo.file_id
|
178 |
+
elif message.animation:
|
179 |
+
file_id = message.animation.file_id
|
180 |
+
elif message.audio:
|
181 |
+
file_id = message.audio.file_id
|
182 |
+
elif message.document:
|
183 |
+
file_id = message.document.file_id
|
184 |
+
elif message.video:
|
185 |
+
file_id = message.video.file_id
|
186 |
+
elif message.sticker:
|
187 |
+
file_id = message.sticker.file_id
|
188 |
+
elif message.video_note:
|
189 |
+
file_id = message.video_note.file_id
|
190 |
+
elif message.voice:
|
191 |
+
file_id = message.voice.file_id
|
192 |
+
return file_id
|
Hellbot/functions/paste.py
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import uuid
|
2 |
+
|
3 |
+
import requests
|
4 |
+
|
5 |
+
from .utility import TGraph
|
6 |
+
|
7 |
+
|
8 |
+
def post_to_telegraph(
|
9 |
+
title: str,
|
10 |
+
content: str,
|
11 |
+
author: str = "[ ๐ง๐พ๐
๐
๐ก๐๐ ]",
|
12 |
+
url: str = "https://t.me/Its_HellBot",
|
13 |
+
) -> str:
|
14 |
+
content = content.replace("\n", "<br>")
|
15 |
+
try:
|
16 |
+
response = TGraph.telegraph.create_page(
|
17 |
+
title=title,
|
18 |
+
html_content=content,
|
19 |
+
author_name=author,
|
20 |
+
author_url=url,
|
21 |
+
)
|
22 |
+
except Exception:
|
23 |
+
rnd_key = uuid.uuid4().hex[:8]
|
24 |
+
title = f"{title}_{rnd_key}"
|
25 |
+
response = TGraph.telegraph.create_page(
|
26 |
+
title=title,
|
27 |
+
html_content=content,
|
28 |
+
author_name=author,
|
29 |
+
author_url=url,
|
30 |
+
)
|
31 |
+
|
32 |
+
return f"https://te.legra.ph/{response['path']}"
|
33 |
+
|
34 |
+
|
35 |
+
def spaceBin(data: str, extension: str = "none") -> str:
|
36 |
+
data = {
|
37 |
+
"content": data,
|
38 |
+
"extension": extension,
|
39 |
+
}
|
40 |
+
|
41 |
+
resp = requests.post("https://spaceb.in/api/v1/documents/", data)
|
42 |
+
|
43 |
+
try:
|
44 |
+
result = resp.json()
|
45 |
+
url = f"https://spaceb.in/{result['payload']['id']}"
|
46 |
+
except Exception:
|
47 |
+
url = ""
|
48 |
+
|
49 |
+
return url
|
Hellbot/functions/scraping.py
ADDED
@@ -0,0 +1,528 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import calendar
|
2 |
+
import time
|
3 |
+
|
4 |
+
import httpx
|
5 |
+
from bs4 import BeautifulSoup
|
6 |
+
from urllib.parse import quote, urlparse
|
7 |
+
from Hellbot.core import Symbols
|
8 |
+
|
9 |
+
from .paste import post_to_telegraph
|
10 |
+
from .templates import (
|
11 |
+
airing_templates,
|
12 |
+
anilist_user_templates,
|
13 |
+
anime_template,
|
14 |
+
character_templates,
|
15 |
+
manga_templates,
|
16 |
+
)
|
17 |
+
|
18 |
+
anime_query = """query ($id: Int,$search: String) {
|
19 |
+
Page (perPage: 10) {
|
20 |
+
media (id: $id, type: ANIME,search: $search) {
|
21 |
+
id
|
22 |
+
title {
|
23 |
+
romaji
|
24 |
+
english
|
25 |
+
native
|
26 |
+
}
|
27 |
+
type
|
28 |
+
format
|
29 |
+
status
|
30 |
+
description (asHtml: false)
|
31 |
+
episodes
|
32 |
+
duration
|
33 |
+
countryOfOrigin
|
34 |
+
source
|
35 |
+
trailer{
|
36 |
+
id
|
37 |
+
site
|
38 |
+
}
|
39 |
+
genres
|
40 |
+
tags {
|
41 |
+
name
|
42 |
+
}
|
43 |
+
isAdult
|
44 |
+
averageScore
|
45 |
+
studios (isMain: true){
|
46 |
+
nodes{
|
47 |
+
name
|
48 |
+
}
|
49 |
+
}
|
50 |
+
nextAiringEpisode{
|
51 |
+
episode
|
52 |
+
}
|
53 |
+
siteUrl
|
54 |
+
}
|
55 |
+
}
|
56 |
+
}"""
|
57 |
+
|
58 |
+
|
59 |
+
manga_query = """query ($id: Int,$search: String) {
|
60 |
+
Page (perPage: 10) {
|
61 |
+
media (id: $id, type: MANGA,search: $search) {
|
62 |
+
id
|
63 |
+
title {
|
64 |
+
romaji
|
65 |
+
english
|
66 |
+
native
|
67 |
+
}
|
68 |
+
type
|
69 |
+
format
|
70 |
+
status
|
71 |
+
description (asHtml: false)
|
72 |
+
chapters
|
73 |
+
volumes
|
74 |
+
countryOfOrigin
|
75 |
+
source
|
76 |
+
genres
|
77 |
+
isAdult
|
78 |
+
averageScore
|
79 |
+
siteUrl
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}"""
|
83 |
+
|
84 |
+
|
85 |
+
character_query = """query ($id: Int, $search: String) {
|
86 |
+
Page {
|
87 |
+
characters (id: $id, search: $search) {
|
88 |
+
id
|
89 |
+
name {
|
90 |
+
full
|
91 |
+
native
|
92 |
+
}
|
93 |
+
image {
|
94 |
+
large
|
95 |
+
}
|
96 |
+
description
|
97 |
+
gender
|
98 |
+
dateOfBirth {
|
99 |
+
year
|
100 |
+
month
|
101 |
+
day
|
102 |
+
}
|
103 |
+
age
|
104 |
+
bloodType
|
105 |
+
siteUrl
|
106 |
+
favourites
|
107 |
+
media {
|
108 |
+
nodes {
|
109 |
+
title {
|
110 |
+
romaji
|
111 |
+
english
|
112 |
+
native
|
113 |
+
}
|
114 |
+
type
|
115 |
+
format
|
116 |
+
siteUrl
|
117 |
+
}
|
118 |
+
}
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}"""
|
122 |
+
|
123 |
+
|
124 |
+
airing_query = """query ($id: Int, $idMal:Int, $search: String) {
|
125 |
+
Media (id: $id, idMal: $idMal, search: $search, type: ANIME) {
|
126 |
+
id
|
127 |
+
title {
|
128 |
+
romaji
|
129 |
+
english
|
130 |
+
native
|
131 |
+
}
|
132 |
+
status
|
133 |
+
episodes
|
134 |
+
countryOfOrigin
|
135 |
+
nextAiringEpisode {
|
136 |
+
airingAt
|
137 |
+
timeUntilAiring
|
138 |
+
episode
|
139 |
+
}
|
140 |
+
}
|
141 |
+
}"""
|
142 |
+
|
143 |
+
|
144 |
+
anilist_user_query = """query($id: Int, $search: String) {
|
145 |
+
User(id: $id, name: $search) {
|
146 |
+
id
|
147 |
+
name
|
148 |
+
siteUrl
|
149 |
+
statistics {
|
150 |
+
anime {
|
151 |
+
count
|
152 |
+
meanScore
|
153 |
+
minutesWatched
|
154 |
+
episodesWatched
|
155 |
+
}
|
156 |
+
manga {
|
157 |
+
count
|
158 |
+
meanScore
|
159 |
+
chaptersRead
|
160 |
+
volumesRead
|
161 |
+
}
|
162 |
+
}
|
163 |
+
}
|
164 |
+
}"""
|
165 |
+
|
166 |
+
|
167 |
+
def is_valid_url(text: str) -> bool:
|
168 |
+
try:
|
169 |
+
result = urlparse(text)
|
170 |
+
return all([result.scheme, result.netloc])
|
171 |
+
except ValueError:
|
172 |
+
return False
|
173 |
+
|
174 |
+
|
175 |
+
def post_request(query: str, search_term: str):
|
176 |
+
url = "https://graphql.anilist.co"
|
177 |
+
variables = {"search": search_term}
|
178 |
+
r = httpx.post(url, json={"query": query, "variables": variables})
|
179 |
+
if r.status_code != 200:
|
180 |
+
return None
|
181 |
+
return r.json()
|
182 |
+
|
183 |
+
|
184 |
+
def get_country_flag(country: str) -> str:
|
185 |
+
base = ord('๐ฆ')
|
186 |
+
emoji_flag = "".join(chr(base + ord(letter) - ord("A")) for letter in country)
|
187 |
+
return emoji_flag
|
188 |
+
|
189 |
+
|
190 |
+
def get_date(data: dict) -> str:
|
191 |
+
try:
|
192 |
+
year = data["year"] or ""
|
193 |
+
if not year and not data["month"]:
|
194 |
+
return "N/A"
|
195 |
+
day = data["day"]
|
196 |
+
if 10 <= day % 100 <= 20:
|
197 |
+
day = f"{day}th"
|
198 |
+
else:
|
199 |
+
day_dict = {1: "st", 2: "nd", 3: "rd"}
|
200 |
+
day = f"{day}{day_dict.get(day % 10, 'th')}"
|
201 |
+
month_name = calendar.month_name[int(data["month"])]
|
202 |
+
return f"{day} {month_name} {year}"
|
203 |
+
except:
|
204 |
+
return "N/A"
|
205 |
+
|
206 |
+
|
207 |
+
def search_anime_filler(search_term: str):
|
208 |
+
BASE = "https://www.animefillerlist.com/shows/"
|
209 |
+
|
210 |
+
response = httpx.get(BASE).text
|
211 |
+
soup = BeautifulSoup(response, "html.parser")
|
212 |
+
div = soup.findAll("div", {"class": "Group"})
|
213 |
+
|
214 |
+
index = {}
|
215 |
+
for i in div:
|
216 |
+
li = i.findAll("li")
|
217 |
+
for j in li:
|
218 |
+
index[j.text] = j.a["href"].split("/")[-1]
|
219 |
+
|
220 |
+
results = {}
|
221 |
+
keys = list(index.keys())
|
222 |
+
for i in range(len(keys)):
|
223 |
+
if search_term.lower() in keys[i].lower():
|
224 |
+
results[keys[i]] = index[keys[i]]
|
225 |
+
|
226 |
+
for result in results.keys():
|
227 |
+
data = []
|
228 |
+
response = httpx.get(BASE + results[result]).text
|
229 |
+
soup = BeautifulSoup(response, "html.parser")
|
230 |
+
base_div = soup.find("div", {"id": "Condensed"})
|
231 |
+
|
232 |
+
if not base_div:
|
233 |
+
continue
|
234 |
+
|
235 |
+
divs = base_div.findAll("div")
|
236 |
+
for div in divs:
|
237 |
+
heading = div.find("span", {"class": "Label"}).text
|
238 |
+
episodes = div.find("span", {"class": "Episodes"}).text
|
239 |
+
data.append((heading, episodes))
|
240 |
+
|
241 |
+
yield result, data
|
242 |
+
|
243 |
+
|
244 |
+
async def get_filler_info(search_term: str) -> str:
|
245 |
+
animes = search_anime_filler(search_term)
|
246 |
+
message = ""
|
247 |
+
|
248 |
+
for anime in animes:
|
249 |
+
html_message = f"<strong>{Symbols.check_mark} {anime[0]} Filler Guide:</strong>\n\n"
|
250 |
+
|
251 |
+
for data in anime[1]:
|
252 |
+
html_message += (
|
253 |
+
f"<h3>{Symbols.bullet} {data[0]}:</h3> \n<code>{data[1]}</code>\n\n"
|
254 |
+
)
|
255 |
+
|
256 |
+
paste = post_to_telegraph(anime[0] + " Filler Guide", html_message)
|
257 |
+
message += f"{Symbols.anchor} [{anime[0]}]({paste})\n"
|
258 |
+
|
259 |
+
return message
|
260 |
+
|
261 |
+
|
262 |
+
def search_watch_order(anime: str):
|
263 |
+
response = httpx.get(f"https://www.animechrono.com/search?q={quote(anime)}")
|
264 |
+
soup = BeautifulSoup(response.text, "html.parser")
|
265 |
+
|
266 |
+
item_div = soup.find("div", {"class": "search-result-items"})
|
267 |
+
animes = item_div.find_all("a", {"class": "list-item search w-inline-block"})
|
268 |
+
|
269 |
+
for anime in animes:
|
270 |
+
name = anime.find("h1", "h1 search").text
|
271 |
+
yield name, anime["href"]
|
272 |
+
|
273 |
+
|
274 |
+
async def get_watch_order(search_term: str) -> str:
|
275 |
+
animes = search_watch_order(search_term)
|
276 |
+
message = ""
|
277 |
+
|
278 |
+
for anime in animes:
|
279 |
+
message += f"**{Symbols.anchor} {anime[0]}:** \n"
|
280 |
+
response = httpx.get("https://www.animechrono.com" + anime[1]).text
|
281 |
+
soup = BeautifulSoup(response, "html.parser")
|
282 |
+
|
283 |
+
elements = soup.find_all("h2", {"class": "heading-5"})
|
284 |
+
for element in elements:
|
285 |
+
message += f" {Symbols.bullet} `{element.text}`\n"
|
286 |
+
message += "\n"
|
287 |
+
|
288 |
+
return message
|
289 |
+
|
290 |
+
|
291 |
+
async def get_anime_info(search_term: str) -> tuple[str, str]:
|
292 |
+
data = post_request(anime_query, search_term)
|
293 |
+
if not data:
|
294 |
+
return "", ""
|
295 |
+
|
296 |
+
data = data["data"]["Page"]["media"][0]
|
297 |
+
english_title = data["title"]["english"]
|
298 |
+
native_title = data["title"]["native"]
|
299 |
+
if not english_title:
|
300 |
+
english_title = data["title"]["romaji"]
|
301 |
+
flag = get_country_flag(data["countryOfOrigin"])
|
302 |
+
name = f"**[{flag}] {english_title} ({native_title})**"
|
303 |
+
|
304 |
+
anime_id = data["id"]
|
305 |
+
score = data["averageScore"] if data["averageScore"] else "N/A"
|
306 |
+
source = str(data["source"]).title() if data["source"] else "N/A"
|
307 |
+
mtype = str(data["type"]).title() if data["type"] else "N/A"
|
308 |
+
synopsis = data["description"]
|
309 |
+
|
310 |
+
episodes = data["episodes"]
|
311 |
+
if not episodes:
|
312 |
+
try:
|
313 |
+
episodes = data["nextAiringEpisode"]["episode"] - 1
|
314 |
+
except:
|
315 |
+
episodes = "N/A"
|
316 |
+
|
317 |
+
duration = data["duration"] if data["duration"] else "N/A"
|
318 |
+
status = str(data["status"]).title() if data["status"] else "N/A"
|
319 |
+
format = str(data["format"]).title() if data["format"] else "N/A"
|
320 |
+
genre = ", ".join(data["genres"]) if data["genres"] else "N/A"
|
321 |
+
tags = ", ".join([i["name"] for i in data["tags"][:5]]) if data["tags"] else "N/A"
|
322 |
+
studio = data["studios"]["nodes"][0]["name"] if data["studios"]["nodes"] else "N/A"
|
323 |
+
siteurl = f"[Anilist Website]({data['siteUrl']})" if data["siteUrl"] else "N/A"
|
324 |
+
isAdult = data["isAdult"]
|
325 |
+
|
326 |
+
trailer = "N/A"
|
327 |
+
if data["trailer"] and data["trailer"]["site"] == "youtube":
|
328 |
+
trailer = f"[Youtube](https://youtu.be/{data['trailer']['id']})"
|
329 |
+
|
330 |
+
response = httpx.get(f"https://img.anili.st/media/{anime_id}").content
|
331 |
+
banner = f"anime_{anime_id}.jpg"
|
332 |
+
with open(banner, "wb") as f:
|
333 |
+
f.write(response)
|
334 |
+
|
335 |
+
description = post_to_telegraph(name, synopsis)
|
336 |
+
|
337 |
+
message = await anime_template(
|
338 |
+
name=name,
|
339 |
+
score=score,
|
340 |
+
source=source,
|
341 |
+
mtype=mtype,
|
342 |
+
episodes=episodes,
|
343 |
+
duration=duration,
|
344 |
+
status=status,
|
345 |
+
format=format,
|
346 |
+
genre=genre,
|
347 |
+
studio=studio,
|
348 |
+
trailer=trailer,
|
349 |
+
siteurl=siteurl,
|
350 |
+
description=description,
|
351 |
+
tags=tags,
|
352 |
+
isAdult=isAdult,
|
353 |
+
)
|
354 |
+
|
355 |
+
return message, banner
|
356 |
+
|
357 |
+
|
358 |
+
async def get_manga_info(search_term: str) -> tuple[str, str]:
|
359 |
+
data = post_request(manga_query, search_term)
|
360 |
+
if not data:
|
361 |
+
return "", ""
|
362 |
+
|
363 |
+
data = data["data"]["Page"]["media"][0]
|
364 |
+
english_title = data["title"]["english"]
|
365 |
+
native_title = data["title"]["native"]
|
366 |
+
if not english_title:
|
367 |
+
english_title = data["title"]["romaji"]
|
368 |
+
flag = get_country_flag(data["countryOfOrigin"])
|
369 |
+
name = f"**[{flag}] {english_title} ({native_title})**"
|
370 |
+
|
371 |
+
manga_id = data["id"]
|
372 |
+
score = data["averageScore"] if data["averageScore"] else "N/A"
|
373 |
+
source = str(data["source"]).title() if data["source"] else "N/A"
|
374 |
+
mtype = str(data["type"]).title() if data["type"] else "N/A"
|
375 |
+
synopsis = data["description"]
|
376 |
+
|
377 |
+
chapters = data["chapters"] if data["chapters"] else "N/A"
|
378 |
+
volumes = data["volumes"] if data["volumes"] else "N/A"
|
379 |
+
status = str(data["status"]).title() if data["status"] else "N/A"
|
380 |
+
format = str(data["format"]).title() if data["format"] else "N/A"
|
381 |
+
genre = ", ".join(data["genres"]) if data["genres"] else "N/A"
|
382 |
+
siteurl = f"[Anilist Website]({data['siteUrl']})" if data["siteUrl"] else "N/A"
|
383 |
+
isAdult = data["isAdult"]
|
384 |
+
|
385 |
+
response = httpx.get(f"https://img.anili.st/media/{manga_id}").content
|
386 |
+
banner = f"manga_{manga_id}.jpg"
|
387 |
+
with open(banner, "wb") as f:
|
388 |
+
f.write(response)
|
389 |
+
|
390 |
+
description = post_to_telegraph(name, synopsis)
|
391 |
+
|
392 |
+
message = await manga_templates(
|
393 |
+
name=name,
|
394 |
+
score=score,
|
395 |
+
source=source,
|
396 |
+
mtype=mtype,
|
397 |
+
chapters=chapters,
|
398 |
+
volumes=volumes,
|
399 |
+
status=status,
|
400 |
+
format=format,
|
401 |
+
genre=genre,
|
402 |
+
siteurl=siteurl,
|
403 |
+
description=description,
|
404 |
+
isAdult=isAdult,
|
405 |
+
)
|
406 |
+
|
407 |
+
return message, banner
|
408 |
+
|
409 |
+
|
410 |
+
async def get_character_info(search_term: str) -> tuple[str, str]:
|
411 |
+
data = post_request(character_query, search_term)
|
412 |
+
if not data:
|
413 |
+
return "", ""
|
414 |
+
|
415 |
+
data = data["data"]["Page"]["characters"][0]
|
416 |
+
name = f"**{data['name']['full']} ({data['name']['native']})**"
|
417 |
+
char_id = data["id"]
|
418 |
+
|
419 |
+
description = data["description"].split("\n\n", 1)[0]
|
420 |
+
gender = data["gender"] if data["gender"] else "N/A"
|
421 |
+
date_of_birth = get_date(data["dateOfBirth"])
|
422 |
+
age = data["age"] if data["age"] else "N/A"
|
423 |
+
blood_type = data["bloodType"] if data["bloodType"] else "N/A"
|
424 |
+
siteurl = f"[Anilist Website]({data['siteUrl']})" if data["siteUrl"] else "N/A"
|
425 |
+
favorites = data["favourites"] if data["favourites"] else "N/A"
|
426 |
+
|
427 |
+
cameo = data["media"]["nodes"][0] if data["media"]["nodes"] else {}
|
428 |
+
if cameo:
|
429 |
+
role_in = f"\nโฐโข **๐ฑ๐๐
๐พ ๐จ๐:** [{cameo['title']['romaji']}]({cameo['siteUrl']})"
|
430 |
+
else:
|
431 |
+
role_in = ""
|
432 |
+
|
433 |
+
response = httpx.get(data["image"]["large"]).content
|
434 |
+
banner = f"character_{char_id}.jpg"
|
435 |
+
with open(banner, "wb") as f:
|
436 |
+
f.write(response)
|
437 |
+
|
438 |
+
message = await character_templates(
|
439 |
+
name=name,
|
440 |
+
gender=gender,
|
441 |
+
date_of_birth=date_of_birth,
|
442 |
+
age=age,
|
443 |
+
blood_type=blood_type,
|
444 |
+
favorites=favorites,
|
445 |
+
siteurl=siteurl,
|
446 |
+
role_in=role_in,
|
447 |
+
description=description,
|
448 |
+
)
|
449 |
+
|
450 |
+
return message, banner
|
451 |
+
|
452 |
+
|
453 |
+
async def get_airing_info(search_term: str) -> tuple[str, str]:
|
454 |
+
data = post_request(airing_query, search_term)
|
455 |
+
if not data:
|
456 |
+
return "", ""
|
457 |
+
|
458 |
+
data = data["data"]["Media"]
|
459 |
+
english_title = data["title"]["english"]
|
460 |
+
native_title = data["title"]["native"]
|
461 |
+
if not english_title:
|
462 |
+
english_title = data["title"]["romaji"]
|
463 |
+
flag = get_country_flag(data["countryOfOrigin"])
|
464 |
+
name = f"**[{flag}] {english_title} ({native_title})**"
|
465 |
+
|
466 |
+
episode = data["episodes"]
|
467 |
+
if not episode:
|
468 |
+
try:
|
469 |
+
episode = data["nextAiringEpisode"]["episode"]
|
470 |
+
except:
|
471 |
+
episode = "N/A"
|
472 |
+
|
473 |
+
response = httpx.get(f"https://img.anili.st/media/{data['id']}").content
|
474 |
+
banner = f"airing_{data['id']}.jpg"
|
475 |
+
with open(banner, "wb") as f:
|
476 |
+
f.write(response)
|
477 |
+
|
478 |
+
status = str(data["status"]).title() if data["status"] else "N/A"
|
479 |
+
next_date = data["nextAiringEpisode"]["airingAt"] if data["nextAiringEpisode"] else ""
|
480 |
+
|
481 |
+
airing_info = ""
|
482 |
+
if next_date:
|
483 |
+
airing_info = f"\n**๐๏ธ {time.ctime(next_date)}**"
|
484 |
+
|
485 |
+
message = await airing_templates(
|
486 |
+
name=name,
|
487 |
+
status=status,
|
488 |
+
episode=episode,
|
489 |
+
airing_info=airing_info,
|
490 |
+
)
|
491 |
+
|
492 |
+
return message, banner
|
493 |
+
|
494 |
+
|
495 |
+
async def get_anilist_user_info(search_term: str) -> tuple[str, str]:
|
496 |
+
data = post_request(anilist_user_query, search_term)
|
497 |
+
if not data:
|
498 |
+
return "", ""
|
499 |
+
|
500 |
+
data = data["data"]["User"]
|
501 |
+
user_id = data["id"]
|
502 |
+
name = data['name']
|
503 |
+
siteurl = f"[Anilist Website]({data['siteUrl']})" if data["siteUrl"] else "N/A"
|
504 |
+
|
505 |
+
response = httpx.get(f"https://img.anili.st/user/{user_id}").content
|
506 |
+
banner = f"aniuser_{user_id}.jpg"
|
507 |
+
with open(banner, "wb") as f:
|
508 |
+
f.write(response)
|
509 |
+
|
510 |
+
anime_stats = data["statistics"]["anime"]
|
511 |
+
manga_stats = data["statistics"]["manga"]
|
512 |
+
|
513 |
+
anime = (
|
514 |
+
anime_stats["count"] or 0,
|
515 |
+
anime_stats["meanScore"] or 0,
|
516 |
+
anime_stats["minutesWatched"] or 0,
|
517 |
+
anime_stats["episodesWatched"] or 0,
|
518 |
+
)
|
519 |
+
manga = (
|
520 |
+
manga_stats["count"] or 0,
|
521 |
+
manga_stats["meanScore"] or 0,
|
522 |
+
manga_stats["chaptersRead"] or 0,
|
523 |
+
manga_stats["volumesRead"] or 0,
|
524 |
+
)
|
525 |
+
|
526 |
+
message = await anilist_user_templates(name, anime, manga, siteurl)
|
527 |
+
|
528 |
+
return message, banner
|
Hellbot/functions/sticker.py
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Tuple
|
2 |
+
|
3 |
+
from emoji import EMOJI_DATA
|
4 |
+
from pyrogram import Client
|
5 |
+
from pyrogram.raw.functions.messages import GetStickerSet
|
6 |
+
from pyrogram.raw.functions.stickers import AddStickerToSet, CreateStickerSet, RemoveStickerFromSet
|
7 |
+
from pyrogram.raw import base, types
|
8 |
+
from pyrogram.types import Message
|
9 |
+
|
10 |
+
from .media import get_media_from_id, upload_media
|
11 |
+
|
12 |
+
|
13 |
+
def is_emoji(text: str) -> bool:
|
14 |
+
return any(c in EMOJI_DATA for c in text)
|
15 |
+
|
16 |
+
|
17 |
+
def get_emoji_and_id(message: Message) -> Tuple[int, str]:
|
18 |
+
pack_id = None
|
19 |
+
pack_emoji = None
|
20 |
+
|
21 |
+
for command in message.command:
|
22 |
+
if command.isdigit():
|
23 |
+
pack_id = int(command)
|
24 |
+
elif is_emoji(command):
|
25 |
+
pack_emoji = command
|
26 |
+
|
27 |
+
if pack_id is None:
|
28 |
+
pack_id = 1
|
29 |
+
|
30 |
+
if pack_emoji is None:
|
31 |
+
sticker = message.reply_to_message.sticker
|
32 |
+
try:
|
33 |
+
pack_emoji = sticker.emoji if sticker and sticker.emoji else "๐"
|
34 |
+
except:
|
35 |
+
pack_emoji = "๐"
|
36 |
+
|
37 |
+
return pack_id, pack_emoji
|
38 |
+
|
39 |
+
|
40 |
+
def check_sticker_data(replied: Message) -> Tuple[str | None, bool, bool, bool, int]:
|
41 |
+
pack_type = None
|
42 |
+
is_animated = False
|
43 |
+
is_video = False
|
44 |
+
is_static = False
|
45 |
+
pack_limit = 50
|
46 |
+
|
47 |
+
if replied.sticker:
|
48 |
+
if replied.sticker.is_animated:
|
49 |
+
pack_type, is_animated = "animated", True
|
50 |
+
elif replied.sticker.is_video:
|
51 |
+
pack_type, is_video = "video", True
|
52 |
+
else:
|
53 |
+
pack_type, is_static, pack_limit = "static", True, 120
|
54 |
+
|
55 |
+
elif replied.photo:
|
56 |
+
pack_type, is_static, pack_limit = "static", True, 120
|
57 |
+
|
58 |
+
elif replied.video or replied.animation:
|
59 |
+
pack_type, is_video = "video", True
|
60 |
+
|
61 |
+
elif replied.document:
|
62 |
+
mime_type = replied.document.mime_type.lower()
|
63 |
+
if mime_type.startswith("video/"):
|
64 |
+
pack_type, is_video = "video", True
|
65 |
+
elif mime_type.startswith("image/"):
|
66 |
+
pack_type, is_static, pack_limit = "static", True, 120
|
67 |
+
elif mime_type in ["application/x-tgsticker", "application/x-bad-tgsticker"]:
|
68 |
+
pack_type, is_animated = "animated", True
|
69 |
+
|
70 |
+
return pack_type, is_animated, is_video, is_static, pack_limit
|
71 |
+
|
72 |
+
|
73 |
+
async def create_sticker(
|
74 |
+
client: Client,
|
75 |
+
chat_id: int,
|
76 |
+
file: str,
|
77 |
+
emoji: str,
|
78 |
+
) -> types.InputStickerSetItem:
|
79 |
+
sticker = await upload_media(client, chat_id, file)
|
80 |
+
|
81 |
+
return types.InputStickerSetItem(
|
82 |
+
document=sticker,
|
83 |
+
emoji=emoji,
|
84 |
+
)
|
85 |
+
|
86 |
+
|
87 |
+
async def remove_sticker(client: Client, stickerid: str) -> base.messages.StickerSet:
|
88 |
+
sticker = await get_media_from_id(stickerid)
|
89 |
+
return await client.invoke(RemoveStickerFromSet(sticker=sticker))
|
90 |
+
|
91 |
+
|
92 |
+
async def get_sticker_set(client: Client, name: str) -> base.messages.StickerSet | None:
|
93 |
+
try:
|
94 |
+
return await client.invoke(
|
95 |
+
GetStickerSet(
|
96 |
+
stickerset=types.InputStickerSetShortName(short_name=name),
|
97 |
+
hash=0,
|
98 |
+
)
|
99 |
+
)
|
100 |
+
except:
|
101 |
+
return None
|
102 |
+
|
103 |
+
|
104 |
+
async def add_sticker(
|
105 |
+
client: Client,
|
106 |
+
stickerset: base.messages.StickerSet,
|
107 |
+
sticker: base.InputStickerSetItem,
|
108 |
+
) -> base.messages.StickerSet:
|
109 |
+
return await client.invoke(
|
110 |
+
AddStickerToSet(
|
111 |
+
stickerset=types.InputStickerSetShortName(short_name=stickerset.set.short_name),
|
112 |
+
sticker=sticker,
|
113 |
+
)
|
114 |
+
)
|
115 |
+
|
116 |
+
|
117 |
+
async def new_sticker_set(
|
118 |
+
client: Client,
|
119 |
+
user_id: int,
|
120 |
+
title: str,
|
121 |
+
short_name: str,
|
122 |
+
stickers: list[base.InputStickerSetItem],
|
123 |
+
animated: bool,
|
124 |
+
video: bool,
|
125 |
+
) -> base.messages.StickerSet:
|
126 |
+
return await client.invoke(
|
127 |
+
CreateStickerSet(
|
128 |
+
user_id=(await client.resolve_peer(user_id)),
|
129 |
+
title=title,
|
130 |
+
short_name=short_name,
|
131 |
+
stickers=stickers,
|
132 |
+
animated=animated,
|
133 |
+
videos=video,
|
134 |
+
)
|
135 |
+
)
|
Hellbot/functions/templates.py
ADDED
@@ -0,0 +1,466 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import random
|
2 |
+
|
3 |
+
from Hellbot import __version__
|
4 |
+
from Hellbot.core import ENV, db
|
5 |
+
|
6 |
+
ALIVE_TEMPLATES = [
|
7 |
+
(
|
8 |
+
"โขโโโโโโโโโโโโโโโโโข\n"
|
9 |
+
"โข ๐แดสส๐แดแด ๐s ๐สษชแด แด โข\n"
|
10 |
+
"โญโโโโโโโโโโโโโโโโโข\n"
|
11 |
+
"โฐโข แดแดกษดแดส ยป {owner}\n"
|
12 |
+
"โฐโข แดสสแดษขสแดแด ยป {pyrogram}\n"
|
13 |
+
"โฐโข สแดสสสแดแด ยป {hellbot}\n"
|
14 |
+
"โฐโข แดสแดสแดษด ยป {python}\n"
|
15 |
+
"โฐโข แดแดแดษชแดแด ยป {uptime}\n"
|
16 |
+
"โฐโโโโโโโโโโโโโโโโโข\n"
|
17 |
+
"๐ก๐ ยฉ @HellBot_Networks\n"
|
18 |
+
"โขโโโโโโโโโโโโโโโโโข\n"
|
19 |
+
),
|
20 |
+
]
|
21 |
+
|
22 |
+
PING_TEMPLATES = [
|
23 |
+
"""**๐ ๐ฏ๐๐๐!**
|
24 |
+
|
25 |
+
โ **ัฯััโ:** {speed} m/s
|
26 |
+
โ **ฯ
ฯัฮนะผั:** {uptime}
|
27 |
+
โ **ฯฯฮทัั:** {owner}""",
|
28 |
+
]
|
29 |
+
|
30 |
+
HELP_MENU_TEMPLATES = [
|
31 |
+
"""**๐ ๐ง๐พ๐
๐ ๐ฌ๐พ๐๐ ๐ฟ๐๐:** {owner}
|
32 |
+
|
33 |
+
__๐ ๐ซ๐๐บ๐ฝ๐พ๐ฝ__ **{plugins} ๐๐
๐๐๐๐๐** __๐๐๐๐ ๐บ ๐๐๐๐บ๐
๐๐ฟ__ **{commands} ๐ผ๐๐๐๐บ๐๐ฝ๐.**
|
34 |
+
|
35 |
+
**๐ Page:** __{current}/{last}__""",
|
36 |
+
]
|
37 |
+
|
38 |
+
COMMAND_MENU_TEMPLATES = [
|
39 |
+
"""**๐ฏ๐
๐๐๐๐ ๐ฅ๐๐
๐พ:** `{file}`
|
40 |
+
**๐ฏ๐
๐๐๐๐ ๐จ๐๐ฟ๐:** __{info} ๐__
|
41 |
+
|
42 |
+
**๐ ๐ซ๐๐บ๐ฝ๐พ๐ฝ ๐ข๐๐๐๐บ๐๐ฝ๐:** `{commands}`""",
|
43 |
+
]
|
44 |
+
|
45 |
+
ANIME_TEMPLATES = [
|
46 |
+
"""
|
47 |
+
{name}
|
48 |
+
|
49 |
+
โญโโโโโโโโโโโโโโโโโข
|
50 |
+
โฐโข **๐ฒ๐ผ๐๐๐พ:** `{score}`
|
51 |
+
โฐโข **๐ฒ๐๐๐๐ผ๐พ:** `{source}`
|
52 |
+
โฐโข **๐ณ๐๐๐พ:** `{mtype}`
|
53 |
+
โฐโข **๐ค๐๐๐๐๐ฝ๐พ๐:** `{episodes}`
|
54 |
+
โฐโข **๐ฃ๐๐๐บ๐๐๐๐:** `{duration} minutes`
|
55 |
+
โฐโข **๐ฒ๐๐บ๐๐๐:** `{status}`
|
56 |
+
โฐโข **๐ฅ๐๐๐๐บ๐:** `{format}`
|
57 |
+
โฐโข **๐ฆ๐พ๐๐๐พ:** `{genre}`
|
58 |
+
โฐโข **๐ณ๐บ๐๐:** `{tags}`
|
59 |
+
โฐโข **๐ ๐ฝ๐๐
๐ ๐ฑ๐บ๐๐พ๐ฝ:** `{isAdult}`
|
60 |
+
โฐโข **๐ฒ๐๐๐ฝ๐๐:** `{studio}`
|
61 |
+
โฐโข **๐ณ๐๐บ๐๐
๐พ๐:** {trailer}
|
62 |
+
โฐโข **๐ถ๐พ๐ป๐๐๐๐พ:** {siteurl}
|
63 |
+
โฐโข **๐ฒ๐๐๐๐๐๐๐:** [๐ข๐
๐๐ผ๐ ๐ง๐พ๐๐พ]({description})
|
64 |
+
โฐโโโโโโโโโโโโโโโโโข
|
65 |
+
"""
|
66 |
+
]
|
67 |
+
|
68 |
+
MANGA_TEMPLATES = [
|
69 |
+
"""
|
70 |
+
{name}
|
71 |
+
|
72 |
+
โญโโโโโโโโโโโโโโโโโข
|
73 |
+
โฐโข **๐ฒ๐ผ๐๐๐พ:** `{score}`
|
74 |
+
โฐโข **๐ฒ๐๐๐๐ผ๐พ:** `{source}`
|
75 |
+
โฐโข **๐ณ๐๐๐พ:** `{mtype}`
|
76 |
+
โฐโข **๐ข๐๐บ๐๐๐พ๐๐:** `{chapters}`
|
77 |
+
โฐโข **๐ต๐๐
๐๐๐พ๐:** `{volumes}`
|
78 |
+
โฐโข **๐ฒ๐๐บ๐๐๐:** `{status}`
|
79 |
+
โฐโข **๐ฅ๐๐๐๐บ๐:** `{format}`
|
80 |
+
โฐโข **๐ฆ๐พ๐๐๐พ:** `{genre}`
|
81 |
+
โฐโข **๐ ๐ฝ๐๐
๐ ๐ฑ๐บ๐๐พ๐ฝ:** `{isAdult}`
|
82 |
+
โฐโข **๐ถ๐พ๐ป๐๐๐๐พ:** {siteurl}
|
83 |
+
โฐโข **๐ฒ๐๐๐๐๐๐๐:** [๐ข๐
๐๐ผ๐ ๐ง๐พ๐๐พ]({description})
|
84 |
+
โฐโโโโโโโโโโโโโโโโโข
|
85 |
+
"""
|
86 |
+
]
|
87 |
+
|
88 |
+
CHARACTER_TEMPLATES = [
|
89 |
+
"""
|
90 |
+
{name}
|
91 |
+
|
92 |
+
โญโโโโโโโโโโโโโโโโโข
|
93 |
+
โฐโข **๐ฆ๐พ๐๐ฝ๐พ๐:** `{gender}`
|
94 |
+
โฐโข **๐ฃ๐บ๐๐พ ๐๐ฟ ๐ก๐๐๐๐:** `{date_of_birth}`
|
95 |
+
โฐโข **๐ ๐๐พ:** `{age}`
|
96 |
+
โฐโข **๐ก๐
๐๐๐ฝ ๐ณ๐๐๐พ:** `{blood_type}`
|
97 |
+
โฐโข **๐ฅ๐บ๐๐๐๐๐๐๐พ๐:** `{favorites}`
|
98 |
+
โฐโข **๐ถ๐พ๐ป๐๐๐๐พ:** {siteurl}{role_in}
|
99 |
+
โฐโโโโโโโโโโโโโโโโโข
|
100 |
+
{description}
|
101 |
+
"""
|
102 |
+
]
|
103 |
+
|
104 |
+
AIRING_TEMPLATES = [
|
105 |
+
"""
|
106 |
+
{name}
|
107 |
+
|
108 |
+
โญโโโโโโโโโโโโโโโโโข
|
109 |
+
โฐโข **๐ฒ๐๐บ๐๐๐:** `{status}`
|
110 |
+
โฐโข **๐ค๐๐๐๐๐ฝ๐พ:** `{episode}`
|
111 |
+
โฐโโโโโโโโโโโโโโโโโข{airing_info}
|
112 |
+
"""
|
113 |
+
]
|
114 |
+
|
115 |
+
ANILIST_USER_TEMPLATES = [
|
116 |
+
"""
|
117 |
+
**๐ซ {name}**
|
118 |
+
|
119 |
+
โญโโโโ ๐ ๐๐๐๐พ โโโโโโข
|
120 |
+
โฐโข **๐ข๐๐๐๐:** `{anime_count}`
|
121 |
+
โฐโข **๐ฒ๐ผ๐๐๐พ:** `{anime_score}`
|
122 |
+
โฐโข **๐ฌ๐๐๐๐๐พ๐ ๐ฒ๐๐พ๐๐:** `{minutes}`
|
123 |
+
โฐโข **๐ค๐๐๐๐๐ฝ๐พ๐ ๐ถ๐บ๐๐ผ๐๐พ๐ฝ:** `{episodes}`
|
124 |
+
โฐโโโโโโโโโโโโโโโโโข
|
125 |
+
โญโโโโ ๐ฌ๐บ๐๐๐บ โโโโโโข
|
126 |
+
โฐโข **๐ข๐๐๐๐:** `{manga_count}`
|
127 |
+
โฐโข **๐ฒ๐ผ๐๐๐พ:** `{manga_score}`
|
128 |
+
โฐโข **๐ข๐๐บ๐๐๐พ๐๐:** `{chapters}`
|
129 |
+
โฐโข **๐ต๐๐
๐๐๐พ๐:** `{volumes}`
|
130 |
+
โฐโโโโโโโโโโโโโโโโโข
|
131 |
+
|
132 |
+
๐ถ๐พ๐ป๐๐๐๐พ: {siteurl}
|
133 |
+
"""
|
134 |
+
]
|
135 |
+
|
136 |
+
CLIMATE_TEMPLATES = [
|
137 |
+
"""
|
138 |
+
๐ {city_name}, {country}
|
139 |
+
|
140 |
+
โญโโโโโโโโโโโโโโโโโข
|
141 |
+
โฐโข **๐ถ๐พ๐บ๐๐๐พ๐:** {weather}
|
142 |
+
โฐโข **๐ณ๐๐๐พ๐๐๐๐พ:** {timezone}
|
143 |
+
โฐโข **๐ฒ๐๐๐๐๐๐พ:** {sunrise}
|
144 |
+
โฐโข **๐ฒ๐๐๐๐พ๐:** {sunset}
|
145 |
+
โฐโข **๐ถ๐๐๐ฝ:** {wind}
|
146 |
+
โฐโข **๐ณ๐พ๐๐๐พ๐๐บ๐๐๐๐พ:** {temperature}ยฐC
|
147 |
+
โฐโข **๐ฅ๐พ๐พ๐
๐ ๐
๐๐๐พ:** {feels_like}ยฐC
|
148 |
+
โฐโข **๐ฌ๐๐๐๐๐๐:** {temp_min}ยฐC
|
149 |
+
โฐโข **๐ฌ๐บ๐๐๐๐๐:** {temp_max}ยฐC
|
150 |
+
โฐโข **๐ฏ๐๐พ๐๐๐๐๐พ:** {pressure} hPa
|
151 |
+
โฐโข **๐ง๐๐๐๐ฝ๐๐๐:** {humidity}%
|
152 |
+
โฐโข **๐ต๐๐๐๐ป๐๐
๐๐๐:** {visibility} m
|
153 |
+
โฐโข **๐ข๐
๐๐๐ฝ๐:** {clouds}%
|
154 |
+
โฐโโโโโโโโโโโโโโโโโข
|
155 |
+
"""
|
156 |
+
]
|
157 |
+
|
158 |
+
AIR_POLLUTION_TEMPLATES = [
|
159 |
+
"""
|
160 |
+
๐ {city_name}
|
161 |
+
|
162 |
+
โญโโโโโโโโโโโโโโโโโข
|
163 |
+
โฐโข **๐ ๐ฐ๐จ:** {aqi}
|
164 |
+
โฐโข **๐ข๐บ๐๐ป๐๐ ๐ฌ๐๐๐๐๐๐ฝ๐พ:** {co}
|
165 |
+
โฐโข **๐ญ๐๐๐๐๐๐๐พ๐ ๐ฌ๐๐๐๐๐๐ฝ๐พ:** {no}
|
166 |
+
โฐโข **๐ญ๐๐๐๐๐๐พ๐ ๐ฃ๐๐๐๐๐ฝ๐พ:** {no2}
|
167 |
+
โฐโข **๐ฎ๐๐๐๐พ:** {o3}
|
168 |
+
โฐโข **๐ฒ๐๐
๐๐๐๐ ๐ฃ๐๐๐๐๐ฝ๐พ:** {so2}
|
169 |
+
โฐโข **๐ ๐๐๐๐๐๐บ:** {nh3}
|
170 |
+
โฐโข **๐ฅ๐๐๐พ ๐ฏ๐บ๐๐๐๐ผ๐
๐พ๐ (PM{sub2_5}):** {pm2_5}
|
171 |
+
โฐโข **๐ข๐๐บ๐๐๐พ ๐ฏ๐บ๐๐๐๐ผ๐
๐พ๐ (PM{sub10}):** {pm10}
|
172 |
+
โฐโโโโโโโโโโโโโโโโโข
|
173 |
+
"""
|
174 |
+
]
|
175 |
+
|
176 |
+
GITHUB_USER_TEMPLATES = [
|
177 |
+
"""
|
178 |
+
๐ {username} ({git_id})
|
179 |
+
|
180 |
+
โญโโโโโโโโ {id_type} โโโโโโโโโข
|
181 |
+
โฐโข **๐ญ๐บ๐๐พ:** [{name}]({profile_url})
|
182 |
+
โฐโข **๐ก๐
๐๐:** {blog}
|
183 |
+
โฐโข **๐ข๐๐๐๐บ๐๐:** {company}
|
184 |
+
โฐโข **๐ค๐๐บ๐๐
:** {email}
|
185 |
+
โฐโข **๐ซ๐๐ผ๐บ๐๐๐๐:** {location}
|
186 |
+
โฐโข **๐ฑ๐พ๐๐:** {public_repos}
|
187 |
+
โฐโข **๐ฆ๐๐๐๐:** {public_gists}
|
188 |
+
โฐโข **๐ฅ๐๐
๐
๐๐๐พ๐๐:** {followers}
|
189 |
+
โฐโข **๐ฅ๐๐
๐
๐๐๐๐๐:** {following}
|
190 |
+
โฐโข **๐ ๐ผ๐ผ๐๐๐๐ ๐ผ๐๐พ๐บ๐๐พ๐ฝ:** {created_at}
|
191 |
+
โฐโโโโโโโโโโโโโโโโโข
|
192 |
+
|
193 |
+
**๐ซ ๐ก๐๐:** {bio}
|
194 |
+
"""
|
195 |
+
]
|
196 |
+
|
197 |
+
STATISTICS_TEMPLATES = [
|
198 |
+
"""
|
199 |
+
๐ {name}
|
200 |
+
|
201 |
+
โญโโโโโโโโ ๐ข๐๐บ๐๐๐พ๐
๐ โโโโโโโโโข
|
202 |
+
โฐโข **๐ณ๐๐๐บ๐
:** `{channels}`
|
203 |
+
โฐโข **๐ ๐ฝ๐๐๐:** `{ch_admin}`
|
204 |
+
โฐโข **๐ฎ๐๐๐พ๐:** `{ch_owner}`
|
205 |
+
|
206 |
+
โญโโโโโโโโ ๐ฆ๐๐๐๐๐ โโโโโโโโโข
|
207 |
+
โฐโข **๐ณ๐๐๐บ๐
:** `{groups}`
|
208 |
+
โฐโข **๐ ๐ฝ๐๐๐:** `{gc_admin}`
|
209 |
+
โฐโข **๐ฎ๐๐๐พ๐:** `{gc_owner}`
|
210 |
+
|
211 |
+
โญโโโโโโโโ ๐ฎ๐๐๐พ๐๐ โโโโโโโโโข
|
212 |
+
โฐโข **๐ฏ๐๐๐๐บ๐๐พ:** `{users}`
|
213 |
+
โฐโข **๐ก๐๐๐:** `{bots}`
|
214 |
+
โฐโข **๐ด๐๐๐พ๐บ๐ฝ ๐ฌ๐พ๐๐๐บ๐๐พ๐:** `{unread_msg}`
|
215 |
+
โฐโข **๐ด๐๐๐พ๐บ๐ฝ ๐ฌ๐พ๐๐๐๐๐๐:** `{unread_mention}`
|
216 |
+
|
217 |
+
โ **๐ณ๐๐๐พ ๐ณ๐บ๐๐พ๐:** `{time_taken}`
|
218 |
+
"""
|
219 |
+
]
|
220 |
+
|
221 |
+
GBAN_TEMPLATES = [
|
222 |
+
"""
|
223 |
+
โญโโโโโโโโ {gtype} โโโโโโโโโข
|
224 |
+
โฐโข **๐ต๐๐ผ๐๐๐:** {name}
|
225 |
+
โฐโข **๐ฒ๐๐ผ๐ผ๐พ๐๐:** {success}
|
226 |
+
โฐโข **๐ฅ๐บ๐๐
๐พ๐ฝ:** {failed}
|
227 |
+
โฐโข **๐ฑ๐พ๐บ๐๐๐:** {reason}
|
228 |
+
โฐโโโโโโโโโโโโโโโโโข
|
229 |
+
"""
|
230 |
+
]
|
231 |
+
|
232 |
+
USAGE_TEMPLATES = [
|
233 |
+
"""
|
234 |
+
**๐ ๐ฃ๐๐๐ & ๐ฃ๐๐๐ ๐ด๐๐บ๐๐พ:**
|
235 |
+
|
236 |
+
**โข ๐ฃ๐๐๐ ๐ด๐๐บ๐๐พ ๐ฟ๐๐** `{appName}`
|
237 |
+
โ __{appHours}hrs {appMinutes}mins__ | __{appPercentage}%__
|
238 |
+
|
239 |
+
**โข ๐ฃ๐๐๐ ๐๐พ๐๐บ๐๐๐๐๐ ๐๐๐๐ ๐๐๐๐๐:**
|
240 |
+
โ __{hours}hrs {minutes}mins__ | __{percentage}%__
|
241 |
+
|
242 |
+
**โข ๐ฃ๐๐๐ ๐ด๐๐บ๐๐พ:**
|
243 |
+
โ __{diskUsed}GB__ / __{diskTotal}GB__ | __{diskPercent}%__
|
244 |
+
|
245 |
+
**โข ๐ฌ๐พ๐๐๐๐ ๐ด๐๐บ๐๐พ:**
|
246 |
+
โ __{memoryUsed}GB__ / __{memoryTotal}GB__ | __{memoryPercent}%__
|
247 |
+
"""
|
248 |
+
]
|
249 |
+
|
250 |
+
USER_INFO_TEMPLATES = [
|
251 |
+
"""
|
252 |
+
**๐ ๐ด๐๐พ๐ ๐จ๐๐ฟ๐ ๐๐ฟ {mention}:**
|
253 |
+
|
254 |
+
**โข ๐ฅ๐๐๐๐ ๐ญ๐บ๐๐พ:** `{firstName}`
|
255 |
+
**โข ๐ซ๐บ๐๐ ๐ญ๐บ๐๐พ:** `{lastName}`
|
256 |
+
**โข ๐ด๐๐พ๐๐จ๐ฃ:** `{userId}`
|
257 |
+
|
258 |
+
**โข ๐ข๐๐๐๐๐ ๐ฆ๐๐๐๐๐:** `{commonGroups}`
|
259 |
+
**โข ๐ฃ๐ข-๐จ๐ฃ:** `{dcId}`
|
260 |
+
**โข ๐ฏ๐๐ผ๐๐๐๐พ๐:** `{totalPictures}`
|
261 |
+
**โข ๐ฑ๐พ๐๐๐๐๐ผ๐๐พ๐ฝ:** `{isRestricted}`
|
262 |
+
**โข ๐ต๐พ๐๐๐ฟ๐๐พ๐ฝ:** `{isVerified}`
|
263 |
+
**โข ๐ก๐๐:** `{isBot}`
|
264 |
+
**โข ๐ก๐๐:** `{bio}`
|
265 |
+
|
266 |
+
**</> @HellBot_Networks**
|
267 |
+
"""
|
268 |
+
]
|
269 |
+
|
270 |
+
CHAT_INFO_TEMPLATES = [
|
271 |
+
"""
|
272 |
+
**๐ ๐ข๐๐บ๐ ๐จ๐๐ฟ๐:**
|
273 |
+
|
274 |
+
**โข ๐ข๐๐บ๐ ๐ญ๐บ๐๐พ:** `{chatName}`
|
275 |
+
**โข ๐ข๐๐บ๐ ๐จ๐ฃ:** `{chatId}`
|
276 |
+
**โข ๐ข๐๐บ๐ ๐ซ๐๐๐:** {chatLink}
|
277 |
+
**โข ๐ฎ๐๐๐พ๐:** {chatOwner}
|
278 |
+
**โข ๐ฃ๐ข-๐จ๐ฃ:** `{dcId}`
|
279 |
+
**โข ๐ฌ๐พ๐๐ป๐พ๐๐:** `{membersCount}`
|
280 |
+
**โข ๐ ๐ฝ๐๐๐๐:** `{adminsCount}`
|
281 |
+
**โข ๐ก๐๐๐:** `{botsCount}`
|
282 |
+
**โข ๐ฃ๐พ๐๐ผ๐๐๐๐๐๐๐:** `{description}`
|
283 |
+
|
284 |
+
**</> @HellBot_Networks**
|
285 |
+
"""
|
286 |
+
]
|
287 |
+
|
288 |
+
|
289 |
+
async def alive_template(owner: str, uptime: str) -> str:
|
290 |
+
template = await db.get_env(ENV.alive_template)
|
291 |
+
if template:
|
292 |
+
message = template
|
293 |
+
else:
|
294 |
+
message = random.choice(ALIVE_TEMPLATES)
|
295 |
+
return message.format(
|
296 |
+
owner=owner,
|
297 |
+
pyrogram=__version__["pyrogram"],
|
298 |
+
hellbot=__version__["hellbot"],
|
299 |
+
python=__version__["python"],
|
300 |
+
uptime=uptime,
|
301 |
+
)
|
302 |
+
|
303 |
+
|
304 |
+
async def ping_template(speed: float, uptime: str, owner: str) -> str:
|
305 |
+
template = await db.get_env(ENV.ping_template)
|
306 |
+
if template:
|
307 |
+
message = template
|
308 |
+
else:
|
309 |
+
message = random.choice(PING_TEMPLATES)
|
310 |
+
return message.format(speed=speed, uptime=uptime, owner=owner)
|
311 |
+
|
312 |
+
|
313 |
+
async def help_template(
|
314 |
+
owner: str, cmd_n_plgn: tuple[int, int], page: tuple[int, int]
|
315 |
+
) -> str:
|
316 |
+
template = await db.get_env(ENV.help_template)
|
317 |
+
if template:
|
318 |
+
message = template
|
319 |
+
else:
|
320 |
+
message = random.choice(HELP_MENU_TEMPLATES)
|
321 |
+
return message.format(
|
322 |
+
owner=owner,
|
323 |
+
commands=cmd_n_plgn[0],
|
324 |
+
plugins=cmd_n_plgn[1],
|
325 |
+
current=page[0],
|
326 |
+
last=page[1],
|
327 |
+
)
|
328 |
+
|
329 |
+
|
330 |
+
async def command_template(file: str, info: str, commands: str) -> str:
|
331 |
+
template = await db.get_env(ENV.command_template)
|
332 |
+
if template:
|
333 |
+
message = template
|
334 |
+
else:
|
335 |
+
message = random.choice(COMMAND_MENU_TEMPLATES)
|
336 |
+
return message.format(file=file, info=info, commands=commands)
|
337 |
+
|
338 |
+
|
339 |
+
async def anime_template(**kwargs) -> str:
|
340 |
+
template = await db.get_env(ENV.anime_template)
|
341 |
+
if template:
|
342 |
+
message = template
|
343 |
+
else:
|
344 |
+
message = random.choice(ANIME_TEMPLATES)
|
345 |
+
return message.format(**kwargs)
|
346 |
+
|
347 |
+
|
348 |
+
async def manga_templates(**kwargs) -> str:
|
349 |
+
template = await db.get_env(ENV.manga_template)
|
350 |
+
if template:
|
351 |
+
message = template
|
352 |
+
else:
|
353 |
+
message = random.choice(MANGA_TEMPLATES)
|
354 |
+
return message.format(**kwargs)
|
355 |
+
|
356 |
+
|
357 |
+
async def character_templates(**kwargs) -> str:
|
358 |
+
template = await db.get_env(ENV.character_template)
|
359 |
+
if template:
|
360 |
+
message = template
|
361 |
+
else:
|
362 |
+
message = random.choice(CHARACTER_TEMPLATES)
|
363 |
+
return message.format(**kwargs)
|
364 |
+
|
365 |
+
|
366 |
+
async def airing_templates(**kwargs) -> str:
|
367 |
+
template = await db.get_env(ENV.airing_template)
|
368 |
+
if template:
|
369 |
+
message = template
|
370 |
+
else:
|
371 |
+
message = random.choice(AIRING_TEMPLATES)
|
372 |
+
return message.format(**kwargs)
|
373 |
+
|
374 |
+
|
375 |
+
async def anilist_user_templates(
|
376 |
+
name: str, anime: tuple, manga: tuple, siteurl: str
|
377 |
+
) -> str:
|
378 |
+
template = await db.get_env(ENV.anilist_user_template)
|
379 |
+
if template:
|
380 |
+
message = template
|
381 |
+
else:
|
382 |
+
message = random.choice(ANILIST_USER_TEMPLATES)
|
383 |
+
return message.format(
|
384 |
+
name=name,
|
385 |
+
anime_count=anime[0],
|
386 |
+
anime_score=anime[1],
|
387 |
+
minutes=anime[2],
|
388 |
+
episodes=anime[3],
|
389 |
+
manga_count=manga[0],
|
390 |
+
manga_score=manga[1],
|
391 |
+
chapters=manga[2],
|
392 |
+
volumes=manga[3],
|
393 |
+
siteurl=siteurl,
|
394 |
+
)
|
395 |
+
|
396 |
+
|
397 |
+
async def climate_templates(**kwargs) -> str:
|
398 |
+
template = await db.get_env(ENV.climate_template)
|
399 |
+
if template:
|
400 |
+
message = template
|
401 |
+
else:
|
402 |
+
message = random.choice(CLIMATE_TEMPLATES)
|
403 |
+
return message.format(**kwargs)
|
404 |
+
|
405 |
+
|
406 |
+
async def airpollution_templates(**kwargs) -> str:
|
407 |
+
template = await db.get_env(ENV.airpollution_template)
|
408 |
+
if template:
|
409 |
+
message = template
|
410 |
+
else:
|
411 |
+
message = random.choice(AIR_POLLUTION_TEMPLATES)
|
412 |
+
return message.format(**kwargs)
|
413 |
+
|
414 |
+
|
415 |
+
async def statistics_templates(**kwargs) -> str:
|
416 |
+
template = await db.get_env(ENV.statistics_template)
|
417 |
+
if template:
|
418 |
+
message = template
|
419 |
+
else:
|
420 |
+
message = random.choice(STATISTICS_TEMPLATES)
|
421 |
+
return message.format(**kwargs)
|
422 |
+
|
423 |
+
|
424 |
+
async def github_user_templates(**kwargs) -> str:
|
425 |
+
template = await db.get_env(ENV.github_user_template)
|
426 |
+
if template:
|
427 |
+
message = template
|
428 |
+
else:
|
429 |
+
message = random.choice(GITHUB_USER_TEMPLATES)
|
430 |
+
return message.format(**kwargs)
|
431 |
+
|
432 |
+
|
433 |
+
async def gban_templates(**kwargs) -> str:
|
434 |
+
template = await db.get_env(ENV.gban_template)
|
435 |
+
if template:
|
436 |
+
message = template
|
437 |
+
else:
|
438 |
+
message = random.choice(GBAN_TEMPLATES)
|
439 |
+
return message.format(**kwargs)
|
440 |
+
|
441 |
+
|
442 |
+
async def usage_templates(**kwargs) -> str:
|
443 |
+
template = await db.get_env(ENV.usage_template)
|
444 |
+
if template:
|
445 |
+
message = template
|
446 |
+
else:
|
447 |
+
message = random.choice(USAGE_TEMPLATES)
|
448 |
+
return message.format(**kwargs)
|
449 |
+
|
450 |
+
|
451 |
+
async def user_info_templates(**kwargs) -> str:
|
452 |
+
template = await db.get_env(ENV.user_info_template)
|
453 |
+
if template:
|
454 |
+
message = template
|
455 |
+
else:
|
456 |
+
message = random.choice(USER_INFO_TEMPLATES)
|
457 |
+
return message.format(**kwargs)
|
458 |
+
|
459 |
+
|
460 |
+
async def chat_info_templates(**kwargs) -> str:
|
461 |
+
template = await db.get_env(ENV.chat_info_template)
|
462 |
+
if template:
|
463 |
+
message = template
|
464 |
+
else:
|
465 |
+
message = random.choice(CHAT_INFO_TEMPLATES)
|
466 |
+
return message.format(**kwargs)
|
Hellbot/functions/tools.py
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import asyncio
|
2 |
+
import contextlib
|
3 |
+
import math
|
4 |
+
import os
|
5 |
+
import shlex
|
6 |
+
import shutil
|
7 |
+
import time
|
8 |
+
|
9 |
+
from git import Repo
|
10 |
+
from git.exc import GitCommandError, InvalidGitRepositoryError, NoSuchPathError
|
11 |
+
from pyrogram.types import Message
|
12 |
+
|
13 |
+
from Hellbot.core import Config, Symbols
|
14 |
+
|
15 |
+
from .formatter import humanbytes, readable_time
|
16 |
+
|
17 |
+
|
18 |
+
async def progress(
|
19 |
+
current: int, total: int, message: Message, start: float, process: str
|
20 |
+
):
|
21 |
+
now = time.time()
|
22 |
+
diff = now - start
|
23 |
+
if round(diff % 10.00) == 0 or current == total:
|
24 |
+
percentage = current * 100 / total
|
25 |
+
speed = current / diff
|
26 |
+
elapsed_time = round(diff) * 1000
|
27 |
+
complete_time = round((total - current) / speed) * 1000
|
28 |
+
estimated_total_time = elapsed_time + complete_time
|
29 |
+
progress_str = "**[{0}{1}] : {2}%\n**".format(
|
30 |
+
"".join(["โ" for i in range(math.floor(percentage / 10))]),
|
31 |
+
"".join(["โ" for i in range(10 - math.floor(percentage / 10))]),
|
32 |
+
round(percentage, 2),
|
33 |
+
)
|
34 |
+
msg = (
|
35 |
+
progress_str
|
36 |
+
+ "__{0}__ **๐๐ฟ** __{1}__\n**๐ฒ๐๐พ๐พ๐ฝ:** __{2}/s__\n**๐ค๐ณ๐ :** __{3}__".format(
|
37 |
+
humanbytes(current),
|
38 |
+
humanbytes(total),
|
39 |
+
humanbytes(speed),
|
40 |
+
readable_time(estimated_total_time / 1000),
|
41 |
+
)
|
42 |
+
)
|
43 |
+
await message.edit_text(f"**{process} ...**\n\n{msg}")
|
44 |
+
|
45 |
+
|
46 |
+
async def get_files_from_directory(directory: str) -> list:
|
47 |
+
all_files = []
|
48 |
+
for path, _, files in os.walk(directory):
|
49 |
+
for file in files:
|
50 |
+
all_files.append(os.path.join(path, file))
|
51 |
+
return all_files
|
52 |
+
|
53 |
+
|
54 |
+
async def runcmd(cmd: str) -> tuple[str, str, int, int]:
|
55 |
+
args = shlex.split(cmd)
|
56 |
+
process = await asyncio.create_subprocess_exec(
|
57 |
+
*args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
|
58 |
+
)
|
59 |
+
stdout, stderr = await process.communicate()
|
60 |
+
return (
|
61 |
+
stdout.decode("utf-8", "replace").strip(),
|
62 |
+
stderr.decode("utf-8", "replace").strip(),
|
63 |
+
process.returncode,
|
64 |
+
process.pid,
|
65 |
+
)
|
66 |
+
|
67 |
+
|
68 |
+
async def update_dotenv(key: str, value: str) -> None:
|
69 |
+
with open(".env", "r") as file:
|
70 |
+
data = file.readlines()
|
71 |
+
|
72 |
+
for index, line in enumerate(data):
|
73 |
+
if line.startswith(f"{key}="):
|
74 |
+
data[index] = f"{key}={value}\n"
|
75 |
+
break
|
76 |
+
|
77 |
+
with open(".env", "w") as file:
|
78 |
+
file.writelines(data)
|
79 |
+
|
80 |
+
|
81 |
+
async def restart(
|
82 |
+
update: bool = False,
|
83 |
+
clean_up: bool = False,
|
84 |
+
shutdown: bool = False,
|
85 |
+
):
|
86 |
+
try:
|
87 |
+
shutil.rmtree(Config.DWL_DIR)
|
88 |
+
shutil.rmtree(Config.TEMP_DIR)
|
89 |
+
except BaseException:
|
90 |
+
pass
|
91 |
+
|
92 |
+
if clean_up:
|
93 |
+
os.system(f"mkdir {Config.DWL_DIR}")
|
94 |
+
os.system(f"mkdir {Config.TEMP_DIR}")
|
95 |
+
return
|
96 |
+
|
97 |
+
if shutdown:
|
98 |
+
return os.system(f"kill -9 {os.getpid()}")
|
99 |
+
|
100 |
+
cmd = (
|
101 |
+
"git pull && pip3 install -U -r requirements.txt && bash start.sh"
|
102 |
+
if update
|
103 |
+
else "bash start.sh"
|
104 |
+
)
|
105 |
+
|
106 |
+
os.system(f"kill -9 {os.getpid()} && {cmd}")
|
107 |
+
|
108 |
+
|
109 |
+
async def gen_changelogs(repo: Repo, branch: str) -> str:
|
110 |
+
changelogs = ""
|
111 |
+
commits = list(repo.iter_commits(branch))[:5]
|
112 |
+
for index, commit in enumerate(commits):
|
113 |
+
changelogs += f"**{Symbols.triangle_right} {index + 1}.** `{commit.summary}`\n"
|
114 |
+
|
115 |
+
return changelogs
|
116 |
+
|
117 |
+
|
118 |
+
async def initialize_git(git_repo: str):
|
119 |
+
force = False
|
120 |
+
try:
|
121 |
+
repo = Repo()
|
122 |
+
except NoSuchPathError as pathErr:
|
123 |
+
repo.__del__()
|
124 |
+
return False, pathErr, force
|
125 |
+
except GitCommandError as gitErr:
|
126 |
+
repo.__del__()
|
127 |
+
return False, gitErr, force
|
128 |
+
except InvalidGitRepositoryError:
|
129 |
+
repo = Repo.init()
|
130 |
+
origin = repo.create_remote("upstream", f"https://github.com/{git_repo}")
|
131 |
+
origin.fetch()
|
132 |
+
repo.create_head("master", origin.refs.master)
|
133 |
+
repo.heads.master.set_tracking_branch(origin.refs.master)
|
134 |
+
repo.heads.master.checkout(True)
|
135 |
+
force = True
|
136 |
+
with contextlib.suppress(BaseException):
|
137 |
+
repo.create_remote("upstream", f"https://github.com/{git_repo}")
|
138 |
+
|
139 |
+
return True, repo, force
|
Hellbot/functions/utility.py
ADDED
@@ -0,0 +1,241 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import asyncio
|
2 |
+
import os
|
3 |
+
import time
|
4 |
+
|
5 |
+
from pyrogram import Client
|
6 |
+
from pyrogram.enums import ChatType
|
7 |
+
from pyrogram.errors import FloodWait
|
8 |
+
from pyrogram.types import Message
|
9 |
+
from telegraph import Telegraph
|
10 |
+
|
11 |
+
from Hellbot.core import ENV, LOGS, db
|
12 |
+
|
13 |
+
from .formatter import readable_time
|
14 |
+
|
15 |
+
|
16 |
+
class TelegraphAPI:
|
17 |
+
def __init__(self) -> None:
|
18 |
+
self.shortname: str = "TheHellbot"
|
19 |
+
self.telegraph: Telegraph = None
|
20 |
+
|
21 |
+
async def setup(self):
|
22 |
+
shortname = await db.get_env(ENV.telegraph_account) or self.shortname
|
23 |
+
|
24 |
+
try:
|
25 |
+
self.telegraph = Telegraph(domain="telegra.ph")
|
26 |
+
self.telegraph.create_account(shortname)
|
27 |
+
except:
|
28 |
+
LOGS.warning("Failed to setup Telegraph API")
|
29 |
+
|
30 |
+
|
31 |
+
class Gcast:
|
32 |
+
def __init__(self) -> None:
|
33 |
+
self.file_name = "gcast_{0}.txt"
|
34 |
+
self.complete_msg = "**๐ ๐ฆ๐ผ๐บ๐๐ ๐ข๐๐๐๐
๐พ๐๐พ๐ฝ!** \n\n**๐ฌ๐พ๐๐๐บ๐๐พ:** [click here]({0})\n**๐ข๐๐๐๐:** `{1} {2}`\n**๐ฅ๐๐๐๐บ๐๐ฝ ๐๐บ๐:** `{3}`\n**๐ณ๐๐๐พ ๐๐บ๐๐พ๐:** `{4}`"
|
35 |
+
|
36 |
+
async def _send_msg(self, chat_id: int, msg: Message, tag: bool):
|
37 |
+
await msg.forward(chat_id) if tag else await msg.copy(chat_id)
|
38 |
+
|
39 |
+
async def start(self, message: Message, client: Client, mode: str, tag: bool):
|
40 |
+
link = message.link
|
41 |
+
status = "Enabled" if tag else "Removed"
|
42 |
+
start = time.time()
|
43 |
+
|
44 |
+
if mode == "all":
|
45 |
+
uCount, uFileName = await self.users(message, client, tag)
|
46 |
+
gCount, gFileName = await self.groups(message, client, tag)
|
47 |
+
count = uCount + gCount
|
48 |
+
with open(uFileName, "a", encoding="utf-8") as file1, open(
|
49 |
+
gFileName, "r", encoding="utf-8"
|
50 |
+
) as file2:
|
51 |
+
file1.write(file2.read())
|
52 |
+
file2.close()
|
53 |
+
file1.close()
|
54 |
+
os.remove(gFileName)
|
55 |
+
fileName = uFileName
|
56 |
+
elif mode == "groups":
|
57 |
+
count, fileName = await self.groups(message, client, tag)
|
58 |
+
elif mode == "users":
|
59 |
+
count, fileName = await self.users(message, client, tag)
|
60 |
+
else:
|
61 |
+
return None
|
62 |
+
|
63 |
+
end = time.time()
|
64 |
+
outStr = self.complete_msg.format(
|
65 |
+
link, count, mode, status, readable_time(int(end - start))
|
66 |
+
)
|
67 |
+
|
68 |
+
return fileName, outStr
|
69 |
+
|
70 |
+
async def groups(self, message: Message, client: Client, tag: bool):
|
71 |
+
filename = self.file_name.format(round(time.time()))
|
72 |
+
count = 0
|
73 |
+
|
74 |
+
with open(filename, "w", encoding="utf-8") as f:
|
75 |
+
f.write("Group ID | Error\n\n")
|
76 |
+
async for dialog in client.get_dialogs():
|
77 |
+
if dialog.chat.type == ChatType.SUPERGROUP:
|
78 |
+
try:
|
79 |
+
await self._send_msg(dialog.chat.id, message, tag)
|
80 |
+
count += 1
|
81 |
+
except FloodWait as fw:
|
82 |
+
await asyncio.sleep(fw.value)
|
83 |
+
await self._send_msg(dialog.chat.id, message, tag)
|
84 |
+
count += 1
|
85 |
+
except Exception as e:
|
86 |
+
f.write(f"{dialog.chat.id} | {e}\n")
|
87 |
+
|
88 |
+
f.close()
|
89 |
+
|
90 |
+
return count, filename
|
91 |
+
|
92 |
+
async def users(self, message: Message, client: Client, tag: bool):
|
93 |
+
filename = self.file_name.format(round(time.time()))
|
94 |
+
count = 0
|
95 |
+
|
96 |
+
with open(filename, "w", encoding="utf-8") as f:
|
97 |
+
f.write("User ID | Error\n\n")
|
98 |
+
async for dialog in client.get_dialogs():
|
99 |
+
if dialog.chat.type == ChatType.PRIVATE:
|
100 |
+
try:
|
101 |
+
await self._send_msg(dialog.chat.id, message, tag)
|
102 |
+
count += 1
|
103 |
+
except FloodWait as fw:
|
104 |
+
await asyncio.sleep(fw.value)
|
105 |
+
await self._send_msg(dialog.chat.id, message, tag)
|
106 |
+
count += 1
|
107 |
+
except Exception as e:
|
108 |
+
f.write(f"{dialog.chat.id} | {e}\n")
|
109 |
+
|
110 |
+
f.close()
|
111 |
+
|
112 |
+
return count, filename
|
113 |
+
|
114 |
+
|
115 |
+
class AntiFlood:
|
116 |
+
def __init__(self) -> None:
|
117 |
+
self.FloodCount = {}
|
118 |
+
self.settings = {}
|
119 |
+
self.client_chats = {}
|
120 |
+
|
121 |
+
def updateSettings(self, client: int, chat: int, data: dict):
|
122 |
+
mode = data.get("mode", "mute")
|
123 |
+
mtime = data.get("time", 0)
|
124 |
+
limit = data.get("limit", 5)
|
125 |
+
|
126 |
+
self.settings[client] = {chat: {"mode": mode, "time": mtime, "limit": limit}}
|
127 |
+
|
128 |
+
def getSettings(self, client: int, chat: int) -> tuple[str, int, int]:
|
129 |
+
mode = "mute"
|
130 |
+
mtime = 0
|
131 |
+
limit = 5
|
132 |
+
|
133 |
+
cli_settings: dict = self.settings.get(client, None)
|
134 |
+
if cli_settings:
|
135 |
+
chat_settings: dict = cli_settings.get(chat, None)
|
136 |
+
if chat_settings:
|
137 |
+
mode = chat_settings.get("mode", "mute")
|
138 |
+
mtime = chat_settings.get("time", 0)
|
139 |
+
limit = chat_settings.get("limit", 5)
|
140 |
+
|
141 |
+
return mode, int(mtime), limit
|
142 |
+
|
143 |
+
def updateFlood(self, client: int, chat: int, user: int, count: int):
|
144 |
+
self.FloodCount[client] = {chat: {"last_user": user, "count": count}}
|
145 |
+
|
146 |
+
def getLastUser(self, client: int, chat: int) -> tuple[int, int]:
|
147 |
+
try:
|
148 |
+
cli_dict: dict = self.FloodCount[client]
|
149 |
+
except KeyError:
|
150 |
+
self.FloodCount[client] = {}
|
151 |
+
cli_dict: dict = self.FloodCount[client]
|
152 |
+
|
153 |
+
try:
|
154 |
+
chat_dict: dict = cli_dict[chat]
|
155 |
+
except KeyError:
|
156 |
+
cli_dict[chat] = {}
|
157 |
+
chat_dict: dict = cli_dict[chat]
|
158 |
+
|
159 |
+
last_user: int = chat_dict.get("last_user", 0)
|
160 |
+
count: int = chat_dict.get("count", 0)
|
161 |
+
|
162 |
+
return last_user, count
|
163 |
+
|
164 |
+
async def updateFromDB(self):
|
165 |
+
floods = await db.get_all_floods()
|
166 |
+
for flood in floods:
|
167 |
+
client = flood["client"]
|
168 |
+
chat = flood["chat"]
|
169 |
+
mode = flood.get("mode", "mute")
|
170 |
+
mtime = flood.get("time", 0)
|
171 |
+
limit = flood.get("limit", 5)
|
172 |
+
settings = {"mode": mode, "time": mtime, "limit": limit}
|
173 |
+
|
174 |
+
self.updateSettings(client, chat, settings)
|
175 |
+
try:
|
176 |
+
self.client_chats[client].append(chat)
|
177 |
+
except KeyError:
|
178 |
+
self.client_chats[client] = [chat]
|
179 |
+
|
180 |
+
def check_client_chat(self, client: int, chat: int) -> bool:
|
181 |
+
try:
|
182 |
+
chats = self.client_chats[client]
|
183 |
+
except KeyError:
|
184 |
+
return False
|
185 |
+
|
186 |
+
if chat in chats:
|
187 |
+
return True
|
188 |
+
|
189 |
+
return False
|
190 |
+
|
191 |
+
|
192 |
+
class Blacklists:
|
193 |
+
def __init__(self) -> None:
|
194 |
+
self.blacklists = {}
|
195 |
+
|
196 |
+
async def updateBlacklists(self):
|
197 |
+
datas = await db.get_blacklist_clients()
|
198 |
+
for data in datas:
|
199 |
+
client = data["client"]
|
200 |
+
chats = data.get("chats", [])
|
201 |
+
for chat in chats:
|
202 |
+
blacklists = data["blacklist"]
|
203 |
+
self.blacklists[client] = {chat: blacklists}
|
204 |
+
|
205 |
+
async def addBlacklist(self, client: int, chat: int, text: str):
|
206 |
+
try:
|
207 |
+
self.blacklists[client][chat].append(text)
|
208 |
+
except KeyError:
|
209 |
+
self.blacklists[client] = {chat: [text]}
|
210 |
+
|
211 |
+
await db.add_blacklist(client, chat, text)
|
212 |
+
|
213 |
+
async def rmBlacklist(self, client: int, chat: int, text: str):
|
214 |
+
try:
|
215 |
+
self.blacklists[client][chat].remove(text)
|
216 |
+
except KeyError:
|
217 |
+
return
|
218 |
+
|
219 |
+
await db.rm_blacklist(client, chat, text)
|
220 |
+
|
221 |
+
def getBlacklists(self, client: int, chat: int) -> list:
|
222 |
+
try:
|
223 |
+
return self.blacklists[client][chat]
|
224 |
+
except KeyError:
|
225 |
+
return []
|
226 |
+
|
227 |
+
def check_client_chat(self, client: int, chat: int) -> bool:
|
228 |
+
try:
|
229 |
+
chats = self.blacklists[client]
|
230 |
+
except KeyError:
|
231 |
+
return False
|
232 |
+
|
233 |
+
if chat in chats:
|
234 |
+
return True
|
235 |
+
|
236 |
+
return False
|
237 |
+
|
238 |
+
|
239 |
+
Flood = AntiFlood()
|
240 |
+
BList = Blacklists()
|
241 |
+
TGraph = TelegraphAPI()
|
Hellbot/plugins/__init__.py
ADDED
File without changes
|
Hellbot/plugins/bot/__init__.py
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from Hellbot.core.clients import hellbot
|
2 |
+
from Hellbot.core.config import Config, Symbols
|
3 |
+
from Hellbot.core.database import db
|
4 |
+
from Hellbot.plugins.help import BotHelp
|
5 |
+
|
6 |
+
|
7 |
+
START_MSG = """
|
8 |
+
๐ **๐ฆ๐๐พ๐พ๐๐๐๐๐, {0} - ๐๐บ๐๐๐๐๐๐ ๐๐ฟ ๐ง๐พ๐
๐
๐ป๐๐!** ๐น ๐จ ๐บ๐ ๐๐๐๐ ๐๐๐๐๐๐ ๐ผ๐๐๐๐บ๐๐๐๐, ๐๐๐พ **๐ง๐พ๐
๐
๐ป๐๐ ๐ ๐๐๐๐๐๐บ๐๐!** ๐
|
9 |
+
|
10 |
+
๐ง๐พ๐๐พ ๐๐ ๐๐พ๐๐๐พ, ๐๐๐๐ฝ๐พ, ๐บ๐๐ฝ ๐ช ๐๐๐
๐พ๐บ๐๐ ๐๐๐พ ๐๐๐๐พ๐ ๐๐ฟ ๐ง๐พ๐
๐
๐ก๐๐ ๐บ๐ ๐๐๐๐ ๐ผ๐๐๐๐บ๐๐ฝ! ๐
|
11 |
+
๐ถ๐๐พ๐๐๐พ๐ ๐๐'๐ ๐ผ๐๐พ๐บ๐๐๐๐, ๐ฝ๐พ๐
๐พ๐๐๐๐, ๐๐ ๐๐๐ฝ๐บ๐๐๐๐ ๐๐๐๐ ๐๐๐พ๐๐ป๐๐, ๐จ'๐๐พ ๐๐๐ ๐๐๐๐ ๐ป๐บ๐ผ๐.
|
12 |
+
๐ข๐๐๐๐๐ฝ๐พ๐ ๐๐พ ๐๐๐๐ ๐๐พ๐๐๐๐๐บ๐
๐๐๐ฝ๐พ๐๐๐ผ๐ ๐คญ ๐๐ ๐๐๐พ ๐๐พ๐บ๐
๐ ๐๐ฟ ๐๐
๐๐๐๐บ๐๐พ ๐๐๐พ๐๐ป๐๐ ๐๐บ๐๐๐พ๐๐.
|
13 |
+
|
14 |
+
๐ ๐ซ๐พ๐'๐ ๐พ๐๐ป๐บ๐๐ ๐๐ ๐๐๐๐ ๐พ๐๐๐ผ ๐๐๐๐๐๐พ๐ ๐๐๐๐พ๐๐๐พ๐!
|
15 |
+
๐จ๐ฟ ๐๐๐ ๐พ๐๐พ๐ ๐๐พ๐พ๐ฝ ๐บ๐๐๐๐๐๐บ๐๐ผ๐พ ๐๐ ๐ผ๐๐บ๐๐พ โจ ๐๐๐พ ๐๐๐๐๐
๐
๐๐ฟ ๐๐๐
๐พ๐บ๐๐๐๐๐ ๐ง๐พ๐
๐
๐ป๐๐'๐ ๐๐๐๐๐, ๐๐๐๐ ๐๐๐๐๐๐ ๐๐พ.
|
16 |
+
๐ถ๐พ'๐๐พ ๐บ๐ป๐๐๐ ๐๐ ๐ผ๐๐๐๐๐พ๐ ๐๐พ๐ ๐๐พ๐๐๐๐๐ ๐ ๐๐ ๐๐๐พ ๐๐๐พ๐๐ป๐๐ ๐๐๐๐๐พ๐๐๐พ!
|
17 |
+
|
18 |
+
๐ซ ๐ฌ๐บ๐ ๐๐๐๐ ๐ผ๐๐๐๐บ๐๐ฝ๐ ๐ป๐พ ๐๐๐๐ฟ๐ ๐บ๐๐ฝ ๐๐๐๐ ๐๐พ๐๐๐๐๐๐ ๐
๐พ๐๐พ๐๐ฝ๐บ๐๐.
|
19 |
+
**๐ถ๐พ๐
๐ผ๐๐๐พ ๐๐ ๐ง๐พ๐
๐
๐ป๐๐ ๐ ๐๐๐๐๐๐บ๐๐ โ ๐๐๐พ๐๐พ ๐ง๐พ๐
๐
๐ป๐๐'๐ ๐
๐พ๐๐บ๐ผ๐ ๐
๐๐๐พ๐ ๐๐ ๐ค!**
|
20 |
+
"""
|
21 |
+
|
22 |
+
HELP_MSG = """
|
23 |
+
**โ๏ธ ๐ง๐พ๐
๐:**
|
24 |
+
|
25 |
+
__ยป All commands are categorized and you can use these buttons below to navigate each category and get respective commands.__
|
26 |
+
__ยป Feel free to contact us if you need any help regarding the bot.__
|
27 |
+
|
28 |
+
**โค๏ธ @HellBot_Networks ๐ฎ๐ณ**
|
29 |
+
"""
|
Hellbot/plugins/bot/bot.py
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import heroku3
|
2 |
+
from pyrogram import filters
|
3 |
+
from pyrogram.types import InlineKeyboardMarkup, Message
|
4 |
+
|
5 |
+
from Hellbot import HEROKU_APP
|
6 |
+
from Hellbot.core import LOGS
|
7 |
+
from Hellbot.functions.tools import restart
|
8 |
+
|
9 |
+
from ..btnsG import gen_bot_help_buttons, start_button
|
10 |
+
from . import HELP_MSG, START_MSG, BotHelp, Config, hellbot
|
11 |
+
|
12 |
+
|
13 |
+
@hellbot.bot.on_message(filters.command("start") & Config.AUTH_USERS)
|
14 |
+
async def start_pm(_, message: Message):
|
15 |
+
btns = start_button()
|
16 |
+
|
17 |
+
await message.reply_text(
|
18 |
+
START_MSG.format(message.from_user.mention),
|
19 |
+
disable_web_page_preview=True,
|
20 |
+
reply_markup=InlineKeyboardMarkup(btns),
|
21 |
+
)
|
22 |
+
|
23 |
+
|
24 |
+
@hellbot.bot.on_message(filters.command("help") & Config.AUTH_USERS)
|
25 |
+
async def help_pm(_, message: Message):
|
26 |
+
btns = await gen_bot_help_buttons()
|
27 |
+
|
28 |
+
await message.reply_text(
|
29 |
+
HELP_MSG,
|
30 |
+
disable_web_page_preview=True,
|
31 |
+
reply_markup=InlineKeyboardMarkup(btns),
|
32 |
+
)
|
33 |
+
|
34 |
+
|
35 |
+
@hellbot.bot.on_message(filters.command("restart") & Config.AUTH_USERS)
|
36 |
+
async def restart_clients(_, message: Message):
|
37 |
+
await message.reply_text("Restarted Bot Successfully โ
")
|
38 |
+
try:
|
39 |
+
if HEROKU_APP:
|
40 |
+
try:
|
41 |
+
heroku = heroku3.from_key(Config.HEROKU_APIKEY)
|
42 |
+
app = heroku.apps()[Config.HEROKU_APPNAME]
|
43 |
+
app.restart()
|
44 |
+
except:
|
45 |
+
await restart()
|
46 |
+
else:
|
47 |
+
await restart()
|
48 |
+
except Exception as e:
|
49 |
+
LOGS.error(e)
|
50 |
+
|
51 |
+
|
52 |
+
BotHelp("Others").add(
|
53 |
+
"start", "To start the bot and get the main menu."
|
54 |
+
).add(
|
55 |
+
"help", "To get the help menu with all the command for this assistant bot."
|
56 |
+
).add(
|
57 |
+
"restart", "To restart the bot."
|
58 |
+
).info(
|
59 |
+
"Some basic commands of the bot."
|
60 |
+
).done()
|
Hellbot/plugins/bot/callbacks.py
ADDED
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram import filters
|
2 |
+
from pyrogram.enums import ParseMode
|
3 |
+
from pyrogram.types import CallbackQuery, InlineKeyboardButton, InlineKeyboardMarkup
|
4 |
+
|
5 |
+
from Hellbot.functions.templates import command_template, help_template
|
6 |
+
|
7 |
+
from ..btnsG import gen_bot_help_buttons, gen_inline_help_buttons, start_button
|
8 |
+
from . import HELP_MSG, START_MSG, Config, Symbols, hellbot
|
9 |
+
|
10 |
+
|
11 |
+
async def check_auth_click(cb: CallbackQuery) -> bool:
|
12 |
+
if cb.from_user.id not in Config.AUTH_USERS:
|
13 |
+
await cb.answer(
|
14 |
+
"You are not authorized to use this bot. \n\n</> @Its_HellBot",
|
15 |
+
show_alert=True,
|
16 |
+
)
|
17 |
+
return False
|
18 |
+
return True
|
19 |
+
|
20 |
+
|
21 |
+
@hellbot.bot.on_callback_query(filters.regex(r"auth_close"))
|
22 |
+
async def auth_close_cb(_, cb: CallbackQuery):
|
23 |
+
if await check_auth_click(cb):
|
24 |
+
await cb.message.delete()
|
25 |
+
|
26 |
+
|
27 |
+
@hellbot.bot.on_callback_query(filters.regex(r"close"))
|
28 |
+
async def close_cb(_, cb: CallbackQuery):
|
29 |
+
await cb.message.delete()
|
30 |
+
|
31 |
+
|
32 |
+
@hellbot.bot.on_callback_query(filters.regex(r"bot_help_menu"))
|
33 |
+
async def bot_help_menu_cb(_, cb: CallbackQuery):
|
34 |
+
if not await check_auth_click(cb):
|
35 |
+
return
|
36 |
+
|
37 |
+
plugin = str(cb.data.split(":")[1])
|
38 |
+
|
39 |
+
try:
|
40 |
+
buttons = [
|
41 |
+
InlineKeyboardButton(f"{Symbols.bullet} {i}", f"bot_help_cmd:{plugin}:{i}")
|
42 |
+
for i in sorted(Config.BOT_HELP[plugin]["commands"])
|
43 |
+
]
|
44 |
+
except KeyError:
|
45 |
+
await cb.answer("No description provided for this plugin!", show_alert=True)
|
46 |
+
return
|
47 |
+
|
48 |
+
buttons = [buttons[i : i + 2] for i in range(0, len(buttons), 2)]
|
49 |
+
buttons.append([InlineKeyboardButton(Symbols.back, "help_data:bothelp")])
|
50 |
+
|
51 |
+
caption = (
|
52 |
+
f"**๐ฏ๐
๐๐๐๐ ๐ฅ๐๐
๐พ:** `{plugin}`\n"
|
53 |
+
f"**๐ฏ๐
๐๐๐๐ ๐จ๐๐ฟ๐:** __{Config.BOT_HELP[plugin]['info']} ๐__\n\n"
|
54 |
+
f"**๐ ๐ซ๐๐บ๐ฝ๐พ๐ฝ ๐ข๐๐๐๐บ๐๐ฝ๐:** `{len(sorted(Config.BOT_HELP[plugin]['commands']))}`"
|
55 |
+
)
|
56 |
+
|
57 |
+
try:
|
58 |
+
await cb.edit_message_text(
|
59 |
+
caption,
|
60 |
+
disable_web_page_preview=True,
|
61 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
62 |
+
)
|
63 |
+
except Exception:
|
64 |
+
# handles MessageNotModified error
|
65 |
+
pass
|
66 |
+
|
67 |
+
|
68 |
+
@hellbot.bot.on_callback_query(filters.regex(r"bot_help_cmd"))
|
69 |
+
async def bot_help_cmd_cb(_, cb: CallbackQuery):
|
70 |
+
if not await check_auth_click(cb):
|
71 |
+
return
|
72 |
+
|
73 |
+
result = ""
|
74 |
+
plugin = str(cb.data.split(":")[1])
|
75 |
+
command = str(cb.data.split(":")[2])
|
76 |
+
cmd_dict = Config.BOT_HELP[plugin]["commands"][command]
|
77 |
+
|
78 |
+
result += f"**{Symbols.radio_select} ๐ข๐๐๐๐บ๐๐ฝ:** `/{cmd_dict['command']}`"
|
79 |
+
result += (
|
80 |
+
f"\n\n**{Symbols.arrow_right} ๐ฃ๐พ๐๐ผ๐๐๐๐๐๐๐:** __{cmd_dict['description']}__"
|
81 |
+
)
|
82 |
+
result += f"\n\n**<\\> @Its_HellBot ๐**"
|
83 |
+
|
84 |
+
buttons = [
|
85 |
+
[
|
86 |
+
InlineKeyboardButton(Symbols.back, f"bot_help_menu:{plugin}"),
|
87 |
+
InlineKeyboardButton(Symbols.close, "help_data:botclose"),
|
88 |
+
]
|
89 |
+
]
|
90 |
+
|
91 |
+
try:
|
92 |
+
await cb.edit_message_text(
|
93 |
+
result,
|
94 |
+
ParseMode.MARKDOWN,
|
95 |
+
True,
|
96 |
+
InlineKeyboardMarkup(buttons),
|
97 |
+
)
|
98 |
+
except Exception:
|
99 |
+
# handles MessageNotModified error
|
100 |
+
pass
|
101 |
+
|
102 |
+
|
103 |
+
@hellbot.bot.on_callback_query(filters.regex(r"help_page"))
|
104 |
+
async def help_page_cb(_, cb: CallbackQuery):
|
105 |
+
if not await check_auth_click(cb):
|
106 |
+
return
|
107 |
+
|
108 |
+
page = int(cb.data.split(":")[1])
|
109 |
+
buttons, max_page = await gen_inline_help_buttons(page, sorted(Config.CMD_MENU))
|
110 |
+
|
111 |
+
caption = await help_template(
|
112 |
+
cb.from_user.mention,
|
113 |
+
(len(Config.CMD_INFO), len(Config.CMD_MENU)),
|
114 |
+
(page + 1, max_page),
|
115 |
+
)
|
116 |
+
|
117 |
+
try:
|
118 |
+
await cb.edit_message_text(
|
119 |
+
caption,
|
120 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
121 |
+
)
|
122 |
+
except Exception:
|
123 |
+
# handles MessageNotModified error
|
124 |
+
pass
|
125 |
+
|
126 |
+
|
127 |
+
@hellbot.bot.on_callback_query(filters.regex(r"help_menu"))
|
128 |
+
async def help_menu_cb(_, cb: CallbackQuery):
|
129 |
+
if not await check_auth_click(cb):
|
130 |
+
return
|
131 |
+
|
132 |
+
page = int(cb.data.split(":")[1])
|
133 |
+
plugin = str(cb.data.split(":")[2])
|
134 |
+
|
135 |
+
try:
|
136 |
+
buttons = [
|
137 |
+
InlineKeyboardButton(
|
138 |
+
f"{Symbols.bullet} {i}", f"help_cmd:{page}:{plugin}:{i}"
|
139 |
+
)
|
140 |
+
for i in sorted(Config.HELP_DICT[plugin]["commands"])
|
141 |
+
]
|
142 |
+
except KeyError:
|
143 |
+
await cb.answer("No description provided for this plugin!", show_alert=True)
|
144 |
+
return
|
145 |
+
|
146 |
+
buttons = [buttons[i : i + 2] for i in range(0, len(buttons), 2)]
|
147 |
+
buttons.append([InlineKeyboardButton(Symbols.back, f"help_page:{page}")])
|
148 |
+
|
149 |
+
caption = await command_template(
|
150 |
+
plugin,
|
151 |
+
Config.HELP_DICT[plugin]["info"],
|
152 |
+
len(sorted(Config.HELP_DICT[plugin]["commands"])),
|
153 |
+
)
|
154 |
+
|
155 |
+
try:
|
156 |
+
await cb.edit_message_text(
|
157 |
+
caption,
|
158 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
159 |
+
)
|
160 |
+
except Exception:
|
161 |
+
# handles MessageNotModified error
|
162 |
+
pass
|
163 |
+
|
164 |
+
|
165 |
+
@hellbot.bot.on_callback_query(filters.regex(r"help_cmd"))
|
166 |
+
async def help_cmd_cb(_, cb: CallbackQuery):
|
167 |
+
if not await check_auth_click(cb):
|
168 |
+
return
|
169 |
+
|
170 |
+
page = int(cb.data.split(":")[1])
|
171 |
+
plugin = str(cb.data.split(":")[2])
|
172 |
+
command = str(cb.data.split(":")[3])
|
173 |
+
result = ""
|
174 |
+
cmd_dict = Config.HELP_DICT[plugin]["commands"][command]
|
175 |
+
|
176 |
+
if cmd_dict["parameters"] is None:
|
177 |
+
result += f"**{Symbols.radio_select} ๐ข๐๐๐๐บ๐๐ฝ:** `{Config.HANDLERS[0]}{cmd_dict['command']}`"
|
178 |
+
else:
|
179 |
+
result += f"**{Symbols.radio_select} ๐ข๐๐๐๐บ๐๐ฝ:** `{Config.HANDLERS[0]}{cmd_dict['command']} {cmd_dict['parameters']}`"
|
180 |
+
|
181 |
+
if cmd_dict["description"]:
|
182 |
+
result += (
|
183 |
+
f"\n\n**{Symbols.arrow_right} ๐ฃ๐พ๐๐ผ๐๐๐๐๐๐๐:** __{cmd_dict['description']}__"
|
184 |
+
)
|
185 |
+
|
186 |
+
if cmd_dict["example"]:
|
187 |
+
result += f"\n\n**{Symbols.arrow_right} ๐ค๐๐บ๐๐๐
๐พ:** `{Config.HANDLERS[0]}{cmd_dict['example']}`"
|
188 |
+
|
189 |
+
if cmd_dict["note"]:
|
190 |
+
result += f"\n\n**{Symbols.arrow_right} ๐ญ๐๐๐พ:** __{cmd_dict['note']}__"
|
191 |
+
|
192 |
+
result += f"\n\n**<\\> @Its_HellBot ๐**"
|
193 |
+
|
194 |
+
buttons = [
|
195 |
+
[
|
196 |
+
InlineKeyboardButton(Symbols.back, f"help_menu:{page}:{plugin}"),
|
197 |
+
InlineKeyboardButton(Symbols.close, "help_data:c"),
|
198 |
+
]
|
199 |
+
]
|
200 |
+
|
201 |
+
try:
|
202 |
+
await cb.edit_message_text(
|
203 |
+
result,
|
204 |
+
ParseMode.MARKDOWN,
|
205 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
206 |
+
)
|
207 |
+
except Exception:
|
208 |
+
# handles MessageNotModified error
|
209 |
+
pass
|
210 |
+
|
211 |
+
|
212 |
+
@hellbot.bot.on_callback_query(filters.regex(r"help_data"))
|
213 |
+
async def help_close_cb(_, cb: CallbackQuery):
|
214 |
+
if not await check_auth_click(cb):
|
215 |
+
return
|
216 |
+
|
217 |
+
action = str(cb.data.split(":")[1])
|
218 |
+
if action == "c":
|
219 |
+
await cb.edit_message_text(
|
220 |
+
"**๐ง๐พ๐
๐ ๐ฌ๐พ๐๐ ๐ข๐
๐๐๐พ๐ฝ!**",
|
221 |
+
reply_markup=InlineKeyboardMarkup(
|
222 |
+
[[InlineKeyboardButton("Reopen", "help_data:reopen")]]
|
223 |
+
),
|
224 |
+
)
|
225 |
+
elif action == "reopen":
|
226 |
+
buttons, pages = await gen_inline_help_buttons(0, sorted(Config.CMD_MENU))
|
227 |
+
caption = await help_template(
|
228 |
+
cb.from_user.mention,
|
229 |
+
(len(Config.CMD_INFO), len(Config.CMD_MENU)),
|
230 |
+
(1, pages),
|
231 |
+
)
|
232 |
+
await cb.edit_message_text(
|
233 |
+
caption,
|
234 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
235 |
+
)
|
236 |
+
elif action == "botclose":
|
237 |
+
await cb.message.delete()
|
238 |
+
elif action == "bothelp":
|
239 |
+
buttons = await gen_bot_help_buttons()
|
240 |
+
await cb.edit_message_text(
|
241 |
+
HELP_MSG,
|
242 |
+
disable_web_page_preview=True,
|
243 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
244 |
+
)
|
245 |
+
elif action == "source":
|
246 |
+
buttons = [
|
247 |
+
[
|
248 |
+
InlineKeyboardButton("๐ Deploy", url="https://github.com/The-HellBot/HellBot"),
|
249 |
+
InlineKeyboardButton("Plugins ๐", url="https://github.com/The-HellBot/Plugins"),
|
250 |
+
],
|
251 |
+
[
|
252 |
+
InlineKeyboardButton("ะฝัโโะฒฯั ฮทััฯฯัะบ ๐ฎ๐ณ", url="https://t.me/HellBot_Networks"),
|
253 |
+
],
|
254 |
+
[
|
255 |
+
InlineKeyboardButton("๐๏ธ Support", url="https://t.me/HellBot_Chats"),
|
256 |
+
InlineKeyboardButton("Updates ๐ฃ", url="https://t.me/Its_HellBot"),
|
257 |
+
],
|
258 |
+
[
|
259 |
+
InlineKeyboardButton("๐", "help_data:start"),
|
260 |
+
InlineKeyboardButton(Symbols.close, "help_data:botclose"),
|
261 |
+
],
|
262 |
+
]
|
263 |
+
await cb.edit_message_text(
|
264 |
+
"__ยป The source code is available on GitHub. You can find the link below.__\n"
|
265 |
+
"__ยป Every project available under The-HellBot are open-source and free to use and modify to your needs.__\n"
|
266 |
+
"__ยป Anyone pretending to be the developer of this bot and selling the code, is a scammer.__\n\n"
|
267 |
+
"__ยป Please consider giving a star to the repository if you liked the project.__\n"
|
268 |
+
"__ยป Feel free to contact us if you need any help regarding the source code.__\n\n"
|
269 |
+
"**โค๏ธ @HellBot_Networks ๐ฎ๐ณ**",
|
270 |
+
disable_web_page_preview=True,
|
271 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
272 |
+
)
|
273 |
+
elif action == "start":
|
274 |
+
buttons = start_button()
|
275 |
+
await cb.edit_message_text(
|
276 |
+
START_MSG.format(cb.from_user.mention),
|
277 |
+
disable_web_page_preview=True,
|
278 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
279 |
+
)
|
Hellbot/plugins/bot/forcesub.py
ADDED
@@ -0,0 +1,226 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram import Client, filters
|
2 |
+
from pyrogram.errors import ChatAdminRequired, UserNotParticipant
|
3 |
+
from pyrogram.types import (
|
4 |
+
CallbackQuery,
|
5 |
+
ChatPermissions,
|
6 |
+
InlineKeyboardButton,
|
7 |
+
InlineKeyboardMarkup,
|
8 |
+
Message,
|
9 |
+
)
|
10 |
+
|
11 |
+
from Hellbot.core import LOGS
|
12 |
+
from Hellbot.functions.admins import is_user_admin
|
13 |
+
|
14 |
+
from ..btnsG import gen_inline_keyboard
|
15 |
+
from . import BotHelp, Config, Symbols, db, hellbot
|
16 |
+
|
17 |
+
|
18 |
+
@hellbot.bot.on_message(filters.command("forcesub") & Config.AUTH_USERS & filters.group)
|
19 |
+
async def force_sub(client: Client, message: Message):
|
20 |
+
if len(message.command) < 2:
|
21 |
+
return await message.reply_text("Give a channel username with command!")
|
22 |
+
|
23 |
+
try:
|
24 |
+
is_admin = await is_user_admin(message.chat, client.me.id)
|
25 |
+
if not is_admin:
|
26 |
+
return await message.reply_text(f"To use forcesub i must be an admin in {must_join}!")
|
27 |
+
except UserNotParticipant:
|
28 |
+
return await message.reply_text(f"To use forcesub i must be an admin in {must_join}!")
|
29 |
+
|
30 |
+
must_join = message.command[1]
|
31 |
+
try:
|
32 |
+
chat = await client.get_chat(must_join)
|
33 |
+
except Exception as e:
|
34 |
+
return await message.reply_text(f"**Error:**\n`{e}`")
|
35 |
+
|
36 |
+
if not await is_user_admin(chat, client.me.id):
|
37 |
+
return await message.reply_text("Make me admin in that channel first!")
|
38 |
+
|
39 |
+
await db.add_forcesub(message.chat.id, chat.id)
|
40 |
+
await message.reply_text(
|
41 |
+
f"**๐ ๐ข๐๐บ๐ ๐ฅ๐๐๐ผ๐พ๐๐๐ป ๐ค๐๐บ๐ป๐
๐พ๐ฝ!** \n\n"
|
42 |
+
f"__Users must join__ {chat.title} (`{chat.id}`) __to chat here!__"
|
43 |
+
)
|
44 |
+
|
45 |
+
if message.chat.id not in Config.FORCESUBS:
|
46 |
+
Config.FORCESUBS.add(message.chat.id)
|
47 |
+
|
48 |
+
|
49 |
+
@hellbot.bot.on_message(filters.command("unforcesub") & Config.AUTH_USERS)
|
50 |
+
async def unforce_sub(client: Client, message: Message):
|
51 |
+
if len(message.command) < 2:
|
52 |
+
return await message.reply_text(
|
53 |
+
"Give a channel username with command or give 'all' to remove all forcesubs from this chat!"
|
54 |
+
)
|
55 |
+
|
56 |
+
if not await is_user_admin(message.chat, client.me.id):
|
57 |
+
return await message.reply_text("To use forcesub i must be an admin!")
|
58 |
+
|
59 |
+
if "all" == message.command[1].lower():
|
60 |
+
await db.rm_all_forcesub(message.chat.id)
|
61 |
+
Config.FORCESUBS.remove(message.chat.id)
|
62 |
+
return await message.reply_text(f"**๐ Forcesub disabled!**")
|
63 |
+
|
64 |
+
try:
|
65 |
+
if await db.is_forcesub(message.chat.id, int(message.command[1])):
|
66 |
+
remaining = await db.rm_forcesub(message.chat.id, int(message.command[1]))
|
67 |
+
if remaining:
|
68 |
+
return await message.reply_text(
|
69 |
+
f"**๐ Removed Forcesub `{message.command[1]}`!**\n\n**Remaining Forcesub(s) in this chat:** `{remaining}`"
|
70 |
+
)
|
71 |
+
else:
|
72 |
+
Config.FORCESUBS.remove(message.chat.id)
|
73 |
+
return await message.reply_text(
|
74 |
+
f"**๐ Removed Forcesub `{message.command[1]}`!**"
|
75 |
+
)
|
76 |
+
else:
|
77 |
+
return await message.reply_text(f"**๐ This chat is not forcesub enabled!**")
|
78 |
+
except Exception as e:
|
79 |
+
return await message.reply_text(f"**Error:**\n`{e}`")
|
80 |
+
|
81 |
+
|
82 |
+
@hellbot.bot.on_message(filters.command("listforcesub") & Config.AUTH_USERS)
|
83 |
+
async def list_force_subs(client: Client, message: Message):
|
84 |
+
if not await is_user_admin(message.chat, client.me.id):
|
85 |
+
return await message.reply_text("To use forcesub i must be an admin!")
|
86 |
+
|
87 |
+
all_forcesubs = Config.FORCESUBS
|
88 |
+
|
89 |
+
text = ""
|
90 |
+
if len(all_forcesubs) > 0:
|
91 |
+
for forcesub in all_forcesubs:
|
92 |
+
try:
|
93 |
+
chat = await client.get_chat(forcesub["chat"])
|
94 |
+
text += f"**๐ {chat.title}** (`{chat.id}`)\n"
|
95 |
+
except:
|
96 |
+
text += f"**๐ {forcesub['chat']}** - `Invalid Chat!`\n"
|
97 |
+
else:
|
98 |
+
text = "**๐ No Forcesub Enabled in Bot!**"
|
99 |
+
|
100 |
+
await message.reply_text(text)
|
101 |
+
|
102 |
+
|
103 |
+
@hellbot.bot.on_message(filters.command("getforcesub") & Config.AUTH_USERS)
|
104 |
+
async def getforcesub(client: Client, message: Message):
|
105 |
+
if len(message.command) < 2:
|
106 |
+
chat = message.chat
|
107 |
+
else:
|
108 |
+
try:
|
109 |
+
chat = await client.get_chat(message.command[1])
|
110 |
+
except:
|
111 |
+
return await message.reply_text(f"**Invalid Channel Username/ID!**")
|
112 |
+
|
113 |
+
mustjoins = await db.get_forcesub(chat.id)
|
114 |
+
if mustjoins:
|
115 |
+
text = f"**This chat has {len(mustjoins['must_join'])} forcesub(s):**\n"
|
116 |
+
for must_join in mustjoins["must_join"]:
|
117 |
+
try:
|
118 |
+
chat = await client.get_chat(must_join)
|
119 |
+
text += f"**๐ {chat.title}** (`{chat.id}`)\n"
|
120 |
+
except:
|
121 |
+
text += f"**๐ {must_join}** - `Invalid Chat!`\n"
|
122 |
+
else:
|
123 |
+
text = "**๐ No Forcesub Enabled in This Chat!**"
|
124 |
+
|
125 |
+
await message.reply_text(text)
|
126 |
+
|
127 |
+
|
128 |
+
@hellbot.bot.on_message(
|
129 |
+
filters.group
|
130 |
+
& filters.incoming
|
131 |
+
& filters.new_chat_members
|
132 |
+
& ~filters.bot
|
133 |
+
& ~filters.service
|
134 |
+
& ~Config.AUTH_USERS
|
135 |
+
& ~filters.me
|
136 |
+
)
|
137 |
+
async def handle_force_sub(client: Client, message: Message):
|
138 |
+
if message.chat.id not in Config.FORCESUBS:
|
139 |
+
return
|
140 |
+
|
141 |
+
if not is_user_admin(message.chat, client.me.id):
|
142 |
+
return
|
143 |
+
|
144 |
+
btns_list = []
|
145 |
+
mustjoins = await db.get_forcesub(message.chat.id)
|
146 |
+
|
147 |
+
for i, must_join in enumerate(mustjoins["must_join"]):
|
148 |
+
try:
|
149 |
+
await client.get_chat_member(must_join, message.from_user.id)
|
150 |
+
except UserNotParticipant:
|
151 |
+
invite_link = await client.export_chat_invite_link(must_join)
|
152 |
+
btns_list.append((f"Join {i}", invite_link, "url"))
|
153 |
+
continue
|
154 |
+
except ChatAdminRequired:
|
155 |
+
continue
|
156 |
+
except Exception as e:
|
157 |
+
LOGS.warning(e)
|
158 |
+
continue
|
159 |
+
|
160 |
+
if len(btns_list) == 0:
|
161 |
+
return
|
162 |
+
|
163 |
+
join_btns = gen_inline_keyboard(btns_list, 2)
|
164 |
+
join_btns.append(
|
165 |
+
[
|
166 |
+
InlineKeyboardButton("Unmute ๐ฃ๏ธ", f"forcesub:unmute:{message.from_user.id}:{message.chat.id}")
|
167 |
+
]
|
168 |
+
)
|
169 |
+
await message.reply_text(
|
170 |
+
f"**๐ Welcome to {message.chat.title}!**\n\n"
|
171 |
+
f"To be able to chat here, you must follow the instructions below:\n"
|
172 |
+
f" {Symbols.anchor} __Click the buttons below to join our important channels.__"
|
173 |
+
f" {Symbols.anchor} __After joining all channels, press the unmute button below.__"
|
174 |
+
f" {Symbols.anchor} __Then you can chat here.__",
|
175 |
+
disable_web_page_preview=True,
|
176 |
+
reply_markup=InlineKeyboardMarkup(join_btns),
|
177 |
+
)
|
178 |
+
|
179 |
+
|
180 |
+
@hellbot.bot.on_callback_query(filters.regex(r"forcesub"))
|
181 |
+
async def forcesub_cb(client: Client, cb: CallbackQuery):
|
182 |
+
data = cb.data.split(":")
|
183 |
+
if data[1] == "unmute":
|
184 |
+
try:
|
185 |
+
if not int(data[3]) == cb.message.chat.id:
|
186 |
+
return await cb.answer(
|
187 |
+
"**This is not for this chat!**", show_alert=True
|
188 |
+
)
|
189 |
+
|
190 |
+
must_join = await db.get_forcesub(cb.message.chat.id)
|
191 |
+
for chat in must_join["must_join"]:
|
192 |
+
try:
|
193 |
+
await client.get_chat_member(int(chat), cb.from_user.id)
|
194 |
+
except UserNotParticipant:
|
195 |
+
return await cb.answer(
|
196 |
+
"**You must join all channels first!**", show_alert=True
|
197 |
+
)
|
198 |
+
except ChatAdminRequired:
|
199 |
+
return await cb.answer(
|
200 |
+
"I'm not admin in some of the channels! Ask owner to make me admin.",
|
201 |
+
show_alert=True,
|
202 |
+
)
|
203 |
+
except Exception as e:
|
204 |
+
return await cb.answer(f"**Error:**\n`{e}`")
|
205 |
+
|
206 |
+
permissions = ChatPermissions(can_send_messages=True)
|
207 |
+
await cb.message.chat.restrict_member(int(data[2]), permissions)
|
208 |
+
except Exception as e:
|
209 |
+
return await cb.answer(f"**Error:**\n`{e}`")
|
210 |
+
|
211 |
+
await cb.answer("**๐ Unmuted!**", show_alert=True)
|
212 |
+
return await cb.message.delete()
|
213 |
+
|
214 |
+
|
215 |
+
BotHelp("ForceSub").add(
|
216 |
+
"forcesub",
|
217 |
+
"This command is used to force users to join some channels to chat in group.",
|
218 |
+
).add(
|
219 |
+
"unforcesub", "This command is used to remove channels from forcesub in group."
|
220 |
+
).add(
|
221 |
+
"listforcesub", "This command is used to list all forcesub in bot."
|
222 |
+
).add(
|
223 |
+
"getforcesub", "This command is used to get forcesub in group."
|
224 |
+
).info(
|
225 |
+
"ForceSub ๐"
|
226 |
+
).done()
|
Hellbot/plugins/bot/inline.py
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram import filters
|
2 |
+
from pyrogram.types import (
|
3 |
+
InlineKeyboardMarkup,
|
4 |
+
InlineQuery,
|
5 |
+
InlineQueryResultArticle,
|
6 |
+
InputTextMessageContent,
|
7 |
+
)
|
8 |
+
|
9 |
+
from Hellbot.functions.templates import help_template
|
10 |
+
|
11 |
+
from ..btnsG import gen_inline_help_buttons
|
12 |
+
from . import Config, hellbot
|
13 |
+
|
14 |
+
|
15 |
+
@hellbot.bot.on_inline_query(filters.regex(r"help_menu"))
|
16 |
+
async def help_inline(_, query: InlineQuery):
|
17 |
+
if not query.from_user.id in Config.AUTH_USERS:
|
18 |
+
return
|
19 |
+
no_of_plugins = len(Config.CMD_MENU)
|
20 |
+
no_of_commands = len(Config.CMD_INFO)
|
21 |
+
buttons, pages = await gen_inline_help_buttons(0, sorted(Config.CMD_MENU))
|
22 |
+
caption = await help_template(
|
23 |
+
query.from_user.mention, (no_of_commands, no_of_plugins), (1, pages)
|
24 |
+
)
|
25 |
+
await query.answer(
|
26 |
+
results=[
|
27 |
+
(
|
28 |
+
InlineQueryResultArticle(
|
29 |
+
"HellBot Help Menu ๐",
|
30 |
+
InputTextMessageContent(
|
31 |
+
caption,
|
32 |
+
disable_web_page_preview=True,
|
33 |
+
),
|
34 |
+
description="Inline Query for Help Menu of HellBot",
|
35 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
36 |
+
)
|
37 |
+
)
|
38 |
+
],
|
39 |
+
)
|
Hellbot/plugins/bot/sessions.py
ADDED
@@ -0,0 +1,183 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram import Client, filters
|
2 |
+
from pyrogram.errors import SessionPasswordNeeded
|
3 |
+
from pyrogram.types import (
|
4 |
+
CallbackQuery,
|
5 |
+
InlineKeyboardButton,
|
6 |
+
InlineKeyboardMarkup,
|
7 |
+
Message,
|
8 |
+
ReplyKeyboardRemove,
|
9 |
+
)
|
10 |
+
|
11 |
+
from ..btnsG import gen_inline_keyboard, start_button
|
12 |
+
from ..btnsK import session_keyboard
|
13 |
+
from . import START_MSG, BotHelp, Config, Symbols, db, hellbot
|
14 |
+
|
15 |
+
|
16 |
+
@hellbot.bot.on_message(
|
17 |
+
filters.command("session") & Config.AUTH_USERS & filters.private
|
18 |
+
)
|
19 |
+
async def session_menu(_, message: Message):
|
20 |
+
await message.reply_text(
|
21 |
+
"**๐ ๐ฏ๐
๐พ๐บ๐๐พ ๐ผ๐๐๐๐๐พ ๐บ๐ ๐๐๐๐๐๐ ๐ฟ๐๐๐ ๐ป๐พ๐
๐๐:**",
|
22 |
+
reply_markup=session_keyboard(),
|
23 |
+
)
|
24 |
+
|
25 |
+
|
26 |
+
@hellbot.bot.on_message(filters.regex(r"New ๐ซ") & Config.AUTH_USERS & filters.private)
|
27 |
+
async def new_session(_, message: Message):
|
28 |
+
await message.reply_text(
|
29 |
+
"**๐ฎ๐๐บ๐!** ๐ซ๐พ๐'๐ ๐๐พ๐๐๐ ๐บ ๐๐พ๐ ๐๐พ๐๐๐๐๐",
|
30 |
+
reply_markup=ReplyKeyboardRemove(),
|
31 |
+
)
|
32 |
+
|
33 |
+
phone_number = await hellbot.bot.ask(
|
34 |
+
message.chat.id,
|
35 |
+
"**1.** ๐ค๐๐๐พ๐ ๐๐๐๐ ๐๐พ๐
๐พ๐๐๐บ๐ ๐บ๐ผ๐ผ๐๐๐๐ ๐๐๐๐๐พ ๐๐๐๐ป๐พ๐ ๐๐ ๐บ๐ฝ๐ฝ ๐๐๐พ ๐๐พ๐๐๐๐๐: \n\n__๐ฒ๐พ๐๐ฝ /cancel ๐๐ ๐ผ๐บ๐๐ผ๐พ๐
๐๐๐พ ๐๐๐พ๐๐บ๐๐๐๐.__",
|
36 |
+
filters=filters.text,
|
37 |
+
timeout=120,
|
38 |
+
)
|
39 |
+
|
40 |
+
if phone_number.text == "/cancel":
|
41 |
+
return await message.reply_text("**๐ข๐บ๐๐ผ๐พ๐
๐
๐พ๐ฝ!**")
|
42 |
+
elif not phone_number.text.startswith("+") and not phone_number.text[1:].isdigit():
|
43 |
+
return await message.reply_text(
|
44 |
+
"**๐ค๐๐๐๐!** ๐ฏ๐๐๐๐พ ๐๐๐๐ป๐พ๐ ๐๐๐๐ ๐ป๐พ ๐๐ ๐ฝ๐๐๐๐๐ ๐บ๐๐ฝ ๐๐๐๐๐
๐ฝ ๐ผ๐๐๐๐บ๐๐ ๐ผ๐๐๐๐๐๐ ๐ผ๐๐ฝ๐พ."
|
45 |
+
)
|
46 |
+
|
47 |
+
try:
|
48 |
+
client = Client(
|
49 |
+
name="Hellbot",
|
50 |
+
api_id=Config.API_ID,
|
51 |
+
api_hash=Config.API_HASH,
|
52 |
+
in_memory=True,
|
53 |
+
)
|
54 |
+
await client.connect()
|
55 |
+
|
56 |
+
code = await client.send_code(phone_number.text)
|
57 |
+
ask_otp = await hellbot.bot.ask(
|
58 |
+
message.chat.id,
|
59 |
+
"**2.** ๐ค๐๐๐พ๐ ๐๐๐พ ๐ฎ๐ณ๐ฏ ๐๐พ๐๐ ๐๐ ๐๐๐๐ ๐๐พ๐
๐พ๐๐๐บ๐ ๐บ๐ผ๐ผ๐๐๐๐ ๐ป๐ ๐๐พ๐๐บ๐๐บ๐๐๐๐ ๐พ๐๐พ๐๐ ๐๐๐๐ป๐พ๐ ๐๐๐๐ ๐บ ๐๐๐บ๐ผ๐พ. \n\n**๐ค๐๐บ๐๐๐
๐พ:** `2 4 1 7 4`\n\n__๐ฒ๐พ๐๐ฝ /cancel ๐๐ ๐ผ๐บ๐๐ผ๐พ๐
๐๐๐พ ๐๐๐พ๐๐บ๐๐๐๐.__",
|
60 |
+
filters=filters.text,
|
61 |
+
timeout=300,
|
62 |
+
)
|
63 |
+
if ask_otp.text == "/cancel":
|
64 |
+
return await message.reply_text("**๐ข๐บ๐๐ผ๐พ๐
๐
๐พ๐ฝ!**")
|
65 |
+
otp = ask_otp.text.replace(" ", "")
|
66 |
+
|
67 |
+
try:
|
68 |
+
await client.sign_in(phone_number.text, code.phone_code_hash, otp)
|
69 |
+
except SessionPasswordNeeded:
|
70 |
+
two_step_pass = await hellbot.bot.ask(
|
71 |
+
message.chat.id,
|
72 |
+
"**3.** ๐ค๐๐๐พ๐ ๐๐๐๐ ๐๐๐ ๐๐๐พ๐ ๐๐พ๐๐๐ฟ๐๐ผ๐บ๐๐๐๐ ๐๐บ๐๐๐๐๐๐ฝ: \n\n__๐ฒ๐พ๐๐ฝ /cancel ๐๐ ๐ผ๐บ๐๐ผ๐พ๐
๐๐๐พ ๐๐๐พ๐๐บ๐๐๐๐.__",
|
73 |
+
filters=filters.text,
|
74 |
+
timeout=120,
|
75 |
+
)
|
76 |
+
if two_step_pass.text == "/cancel":
|
77 |
+
return await message.reply_text("**๐ข๐บ๐๐ผ๐พ๐
๐
๐พ๐ฝ!**")
|
78 |
+
await client.check_password(two_step_pass.text)
|
79 |
+
|
80 |
+
session_string = await client.export_session_string()
|
81 |
+
await message.reply_text(
|
82 |
+
f"**๐ฒ๐๐ผ๐ผ๐พ๐๐!** ๐ธ๐๐๐ ๐๐พ๐๐๐๐๐ ๐๐๐๐๐๐ ๐๐ ๐๐พ๐๐พ๐๐บ๐๐พ๐ฝ. ๐ ๐ฝ๐ฝ๐๐๐ ๐๐ ๐๐ ๐ฝ๐บ๐๐บ๐ป๐บ๐๐พ..."
|
83 |
+
)
|
84 |
+
user_id = (await client.get_me()).id
|
85 |
+
await db.update_session(user_id, session_string)
|
86 |
+
await client.disconnect()
|
87 |
+
await message.reply_text(
|
88 |
+
"**๐ฒ๐๐ผ๐ผ๐พ๐๐!** ๐ฒ๐พ๐๐๐๐๐ ๐๐๐๐๐๐ ๐บ๐ฝ๐ฝ๐พ๐ฝ ๐๐ ๐ฝ๐บ๐๐บ๐ป๐บ๐๐พ. ๐ธ๐๐ ๐ผ๐บ๐ ๐๐๐ ๐๐๐พ ๐ง๐พ๐
๐
๐ก๐๐ ๐๐ ๐๐๐๐ ๐บ๐ผ๐ผ๐๐๐๐ ๐บ๐ฟ๐๐พ๐ ๐๐พ๐๐๐บ๐๐๐๐๐ ๐๐๐พ ๐ป๐๐.\n\n**๐ญ๐ฎ๐ณ๐ค:** ๐ฅ๐๐ ๐๐พ๐ผ๐๐๐๐๐ ๐๐๐๐๐๏ฟฝ๏ฟฝ๏ฟฝ๐พ๐ ๐๐๐ป๐๐ฝ๐ ๐๐๐
๐
๐๐บ๐๐พ ๐๐๐พ ๐บ๐ผ๐ผ๐พ๐๐ ๐๐ ๐๐๐๐ ๐๐พ๐๐๐๐๐ ๐๐๐๐๐๐. ๐ญ๐๐ ๐พ๐๐พ๐ ๐๐๐ ๐๐ ๐๐๐พ ๐ป๐๐."
|
89 |
+
)
|
90 |
+
except TimeoutError:
|
91 |
+
await message.reply_text(
|
92 |
+
"**๐ณ๐๐๐พ๐๐๐๐ค๐๐๐๐!** ๐ธ๐๐ ๐๐๐๐ ๐
๐๐๐๐พ๐ ๐๐๐บ๐ ๐พ๐๐ผ๐๐พ๐ผ๐๐พ๐ฝ ๐๐ ๐ผ๐๐๐๐
๐พ๐๐พ ๐๐๐พ ๐๐๐๐ผ๐พ๐๐. ๐ฏ๐
๐พ๐บ๐๐พ ๐๐๐ ๐บ๐๐บ๐๐."
|
93 |
+
)
|
94 |
+
except Exception as e:
|
95 |
+
await message.reply_text(f"**๐ค๐๐๐๐!** {e}")
|
96 |
+
|
97 |
+
|
98 |
+
@hellbot.bot.on_message(
|
99 |
+
filters.regex(r"Delete โ") & Config.AUTH_USERS & filters.private
|
100 |
+
)
|
101 |
+
async def delete_session(_, message: Message):
|
102 |
+
all_sessions = await db.get_all_sessions()
|
103 |
+
if not all_sessions:
|
104 |
+
return await message.reply_text("๐ญ๐ ๐๐พ๐๐๐๐๐๐ ๐ฟ๐๐๐๐ฝ ๐๐ ๐ฝ๐บ๐๐บ๐ป๐บ๐๐พ.")
|
105 |
+
|
106 |
+
collection = []
|
107 |
+
for i in all_sessions:
|
108 |
+
collection.append((i["user_id"], f"rm_session:{i['user_id']}"))
|
109 |
+
|
110 |
+
buttons = gen_inline_keyboard(collection, 2)
|
111 |
+
buttons.append([InlineKeyboardButton("Cancel โ", "auth_close")])
|
112 |
+
|
113 |
+
await message.reply_text(
|
114 |
+
"**๐ข๐๐๐๐๐พ ๐บ ๐๐พ๐๐๐๐๐ ๐๐ ๐ฝ๐พ๐
๐พ๐๐พ:**",
|
115 |
+
reply_markup=InlineKeyboardMarkup(buttons),
|
116 |
+
)
|
117 |
+
|
118 |
+
|
119 |
+
@hellbot.bot.on_callback_query(filters.regex(r"rm_session"))
|
120 |
+
async def rm_session_cb(client: Client, cb: CallbackQuery):
|
121 |
+
collection = []
|
122 |
+
user_id = int(cb.data.split(":")[1])
|
123 |
+
all_sessions = await db.get_all_sessions()
|
124 |
+
|
125 |
+
if not all_sessions:
|
126 |
+
return await cb.message.delete()
|
127 |
+
|
128 |
+
try:
|
129 |
+
owner = await client.get_users(Config.OWNER_ID)
|
130 |
+
owner_id = owner.id
|
131 |
+
owner_name = owner.first_name
|
132 |
+
except:
|
133 |
+
owner_id = Config.OWNER_ID
|
134 |
+
owner_name = "๐ฎ๐๐๐พ๐"
|
135 |
+
if cb.from_user.id not in [user_id, owner_id]:
|
136 |
+
return await cb.answer(
|
137 |
+
f"๐ ๐ผ๐ผ๐พ๐๐ ๐๐พ๐๐๐๐๐ผ๐๐พ๐ฝ ๐๐ ๐บ๐๐๐๐๐พ๐ ๐๐๐พ๐๐. Only {owner_name} and session client can delete this session!",
|
138 |
+
show_alert=True,
|
139 |
+
)
|
140 |
+
|
141 |
+
await db.rm_session(user_id)
|
142 |
+
await cb.answer("**๐ฒ๐๐ผ๐ผ๐พ๐๐!** ๐ฒ๐พ๐๐๐๐๐ ๐ฝ๐พ๐
๐พ๐๐พ๐ฝ ๐ฟ๐๐๐ ๐ฝ๐บ๐๐บ๐ป๐บ๐๐พ. \n__Restart the bot to apply changes.__", show_alert=True)
|
143 |
+
|
144 |
+
for i in all_sessions:
|
145 |
+
collection.append((i["user_id"], f"rm_session:{i['user_id']}"))
|
146 |
+
|
147 |
+
buttons = gen_inline_keyboard(collection, 2)
|
148 |
+
buttons.append([InlineKeyboardButton("Cancel โ", "auth_close")])
|
149 |
+
|
150 |
+
await cb.message.edit_reply_markup(InlineKeyboardMarkup(buttons))
|
151 |
+
|
152 |
+
|
153 |
+
@hellbot.bot.on_message(filters.regex(r"List ๐") & Config.AUTH_USERS & filters.private)
|
154 |
+
async def list_sessions(_, message: Message):
|
155 |
+
all_sessions = await db.get_all_sessions()
|
156 |
+
if not all_sessions:
|
157 |
+
return await message.reply_text("๐ญ๐ ๐๐พ๐๐๐๐๐๐ ๐ฟ๐๐๐๐ฝ ๐๐ ๐ฝ๐บ๐๐บ๐ป๐บ๐๐พ.")
|
158 |
+
|
159 |
+
text = f"**{Symbols.cross_mark} ๐ซ๐๐๐ ๐๐ฟ ๐๐พ๐๐๐๐๐๐:**\n\n"
|
160 |
+
for i, session in enumerate(all_sessions):
|
161 |
+
text += f"[{'0' if i <= 9 else ''}{i+1}] {Symbols.bullet} **๐ด๐๐พ๐ ๐จ๐ฃ:** `{session['user_id']}`\n"
|
162 |
+
|
163 |
+
await message.reply_text(text)
|
164 |
+
|
165 |
+
|
166 |
+
@hellbot.bot.on_message(filters.regex(r"Home ๐ ") & filters.private & Config.AUTH_USERS)
|
167 |
+
async def go_home(_, message: Message):
|
168 |
+
await message.reply_text(
|
169 |
+
"**Home ๐ **",
|
170 |
+
reply_markup=ReplyKeyboardRemove(),
|
171 |
+
)
|
172 |
+
await message.reply_text(
|
173 |
+
START_MSG.format(message.from_user.mention),
|
174 |
+
disable_web_page_preview=True,
|
175 |
+
reply_markup=InlineKeyboardMarkup(start_button()),
|
176 |
+
)
|
177 |
+
|
178 |
+
|
179 |
+
BotHelp("Sessions").add(
|
180 |
+
"session", "This command is packed with tools to manage userbot sessions."
|
181 |
+
).info(
|
182 |
+
"Session ๐"
|
183 |
+
).done()
|
Hellbot/plugins/bot/users.py
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram import Client, filters
|
2 |
+
from pyrogram.types import Message
|
3 |
+
|
4 |
+
from . import BotHelp, Config, Symbols, hellbot
|
5 |
+
|
6 |
+
|
7 |
+
@hellbot.bot.on_message(
|
8 |
+
filters.command("addauth") & Config.AUTH_USERS
|
9 |
+
)
|
10 |
+
async def addauth(client: Client, message: Message):
|
11 |
+
if not message.reply_to_message:
|
12 |
+
if len(message.command) < 2:
|
13 |
+
return await message.reply_text(
|
14 |
+
"Reply to a user or give me a userid/username to add them as an auth user!"
|
15 |
+
)
|
16 |
+
try:
|
17 |
+
user = await client.get_users(message.command[1])
|
18 |
+
except Exception:
|
19 |
+
return await message.reply_text(
|
20 |
+
"Give me a valid userid/username to add them as an auth user!"
|
21 |
+
)
|
22 |
+
else:
|
23 |
+
user = message.reply_to_message.from_user
|
24 |
+
|
25 |
+
if user.is_self:
|
26 |
+
return await message.reply_text("I can't add myself as an auth user!")
|
27 |
+
|
28 |
+
if user.id in Config.AUTH_USERS:
|
29 |
+
return await message.reply_text(f"**{user.mention} is already authorized**")
|
30 |
+
|
31 |
+
Config.AUTH_USERS.add(user.id)
|
32 |
+
await message.reply_text(f"**Added {user.mention} to auth users!**")
|
33 |
+
|
34 |
+
|
35 |
+
@hellbot.bot.on_message(
|
36 |
+
filters.command("delauth") & Config.AUTH_USERS
|
37 |
+
)
|
38 |
+
async def delauth(client: Client, message: Message):
|
39 |
+
if not message.reply_to_message:
|
40 |
+
if len(message.command) < 2:
|
41 |
+
return await message.reply_text(
|
42 |
+
"Reply to a user or give me a userid/username to add them as an auth user!"
|
43 |
+
)
|
44 |
+
try:
|
45 |
+
user = await client.get_users(message.command[1])
|
46 |
+
except Exception:
|
47 |
+
return await message.reply_text(
|
48 |
+
"Give me a valid userid/username to add them as an auth user!"
|
49 |
+
)
|
50 |
+
else:
|
51 |
+
user = message.reply_to_message.from_user
|
52 |
+
|
53 |
+
if user.id in Config.AUTH_USERS:
|
54 |
+
Config.AUTH_USERS.remove(user.id)
|
55 |
+
await message.reply_text(f"**Removed {user.mention} from auth users!**")
|
56 |
+
else:
|
57 |
+
await message.reply_text(f"**{user.mention} is not authorized**")
|
58 |
+
|
59 |
+
|
60 |
+
@hellbot.bot.on_message(
|
61 |
+
filters.command("authlist") & Config.AUTH_USERS
|
62 |
+
)
|
63 |
+
async def authlist(client: Client, message: Message):
|
64 |
+
text = "**๐ Authorized Users:**\n\n"
|
65 |
+
for i, userid in enumerate(Config.AUTH_USERS):
|
66 |
+
try:
|
67 |
+
user = await client.get_users(userid)
|
68 |
+
text += f" {Symbols.anchor} {user.mention} (`{user.id}`)\n"
|
69 |
+
except:
|
70 |
+
text += f" {Symbols.anchor} Auth User #{i+1} (`{userid}`)\n"
|
71 |
+
|
72 |
+
await message.reply_text(text)
|
73 |
+
|
74 |
+
|
75 |
+
BotHelp("Users").add(
|
76 |
+
"addauth",
|
77 |
+
"This command is used to add a user as an authorized user. An authorized user can create and manage userbot session!",
|
78 |
+
).add("delauth", "This command is used to remove a user from authorized users.").add(
|
79 |
+
"authlist", "This command is used to list all authorized users."
|
80 |
+
).info(
|
81 |
+
"Users Command ๐"
|
82 |
+
).done()
|
Hellbot/plugins/btnsG.py
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# G: Glass Buttons
|
2 |
+
|
3 |
+
from math import ceil
|
4 |
+
|
5 |
+
from pyrogram.types import InlineKeyboardButton
|
6 |
+
|
7 |
+
from Hellbot.core import ENV, Symbols, db, Config
|
8 |
+
|
9 |
+
|
10 |
+
def gen_inline_keyboard(collection: list, row: int = 2) -> list[list[InlineKeyboardButton]]:
|
11 |
+
keyboard = []
|
12 |
+
for i in range(0, len(collection), row):
|
13 |
+
kyb = []
|
14 |
+
for x in collection[i : i + row]:
|
15 |
+
button = btn(*x)
|
16 |
+
kyb.append(button)
|
17 |
+
keyboard.append(kyb)
|
18 |
+
return keyboard
|
19 |
+
|
20 |
+
|
21 |
+
def btn(text, value, type="callback_data") -> InlineKeyboardButton:
|
22 |
+
return InlineKeyboardButton(text, **{type: value})
|
23 |
+
|
24 |
+
|
25 |
+
async def gen_inline_help_buttons(page: int, plugins: list) -> tuple[list, int]:
|
26 |
+
buttons = []
|
27 |
+
column = await db.get_env(ENV.btn_in_help) or 5
|
28 |
+
column = int(column)
|
29 |
+
emoji = await db.get_env(ENV.help_emoji) or "โง"
|
30 |
+
pairs = list(map(list, zip(plugins[::2], plugins[1::2])))
|
31 |
+
|
32 |
+
if len(plugins) % 2 == 1:
|
33 |
+
pairs.append([plugins[-1]])
|
34 |
+
|
35 |
+
max_pages = ceil(len(pairs) / column)
|
36 |
+
pairs = [pairs[i : i + column] for i in range(0, len(pairs), column)]
|
37 |
+
|
38 |
+
for pair in pairs[page]:
|
39 |
+
btn_pair = []
|
40 |
+
for i, plugin in enumerate(pair):
|
41 |
+
if i % 2 == 0:
|
42 |
+
btn_pair.append(
|
43 |
+
InlineKeyboardButton(f"{emoji} {plugin}", f"help_menu:{page}:{plugin}")
|
44 |
+
)
|
45 |
+
else:
|
46 |
+
btn_pair.append(
|
47 |
+
InlineKeyboardButton(f"{plugin} {emoji}", f"help_menu:{page}:{plugin}")
|
48 |
+
)
|
49 |
+
buttons.append(btn_pair)
|
50 |
+
|
51 |
+
buttons.append(
|
52 |
+
[
|
53 |
+
InlineKeyboardButton(
|
54 |
+
Symbols.previous, f"help_page:{(max_pages - 1) if page == 0 else (page - 1)}",
|
55 |
+
),
|
56 |
+
InlineKeyboardButton(
|
57 |
+
Symbols.close, "help_data:c"
|
58 |
+
),
|
59 |
+
InlineKeyboardButton(
|
60 |
+
Symbols.next, f"help_page:{0 if page == (max_pages - 1) else (page + 1)}",
|
61 |
+
),
|
62 |
+
]
|
63 |
+
)
|
64 |
+
|
65 |
+
return buttons, max_pages
|
66 |
+
|
67 |
+
|
68 |
+
async def gen_bot_help_buttons() -> list[list[InlineKeyboardButton]]:
|
69 |
+
buttons = []
|
70 |
+
plugins = sorted(Config.BOT_CMD_MENU)
|
71 |
+
emoji = await db.get_env(ENV.help_emoji) or "โง"
|
72 |
+
pairs = list(map(list, zip(plugins[::2], plugins[1::2])))
|
73 |
+
|
74 |
+
if len(plugins) % 2 == 1:
|
75 |
+
pairs.append([plugins[-1]])
|
76 |
+
|
77 |
+
for pair in pairs:
|
78 |
+
btn_pair = []
|
79 |
+
for i, plugin in enumerate(pair):
|
80 |
+
if i % 2 == 0:
|
81 |
+
btn_pair.append(
|
82 |
+
InlineKeyboardButton(f"{emoji} {plugin}", f"bot_help_menu:{plugin}")
|
83 |
+
)
|
84 |
+
else:
|
85 |
+
btn_pair.append(
|
86 |
+
InlineKeyboardButton(f"{plugin} {emoji}", f"bot_help_menu:{plugin}")
|
87 |
+
)
|
88 |
+
buttons.append(btn_pair)
|
89 |
+
|
90 |
+
buttons.append(
|
91 |
+
[
|
92 |
+
InlineKeyboardButton("๐ ", "help_data:start"),
|
93 |
+
InlineKeyboardButton(Symbols.close, "help_data:botclose"),
|
94 |
+
]
|
95 |
+
)
|
96 |
+
|
97 |
+
return buttons
|
98 |
+
|
99 |
+
|
100 |
+
def start_button() -> list[list[InlineKeyboardButton]]:
|
101 |
+
return [
|
102 |
+
[
|
103 |
+
InlineKeyboardButton("โ๏ธ Help", "help_data:bothelp"),
|
104 |
+
InlineKeyboardButton("Source ๐ฆ", "help_data:source"),
|
105 |
+
]
|
106 |
+
]
|
Hellbot/plugins/btnsK.py
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# K: Keyboard Buttons
|
2 |
+
|
3 |
+
from pyrogram.types import KeyboardButton, ReplyKeyboardMarkup
|
4 |
+
|
5 |
+
|
6 |
+
def gen_keyboard(collection: list, row: int = 2) -> list[list[KeyboardButton]]:
|
7 |
+
keyboard = []
|
8 |
+
for i in range(0, len(collection), row):
|
9 |
+
kyb = []
|
10 |
+
for x in collection[i : i + row]:
|
11 |
+
kyb.append(KeyboardButton(x))
|
12 |
+
keyboard.append(kyb)
|
13 |
+
return keyboard
|
14 |
+
|
15 |
+
|
16 |
+
def session_keyboard() -> ReplyKeyboardMarkup:
|
17 |
+
return ReplyKeyboardMarkup(
|
18 |
+
[
|
19 |
+
[
|
20 |
+
KeyboardButton("New ๐ซ"),
|
21 |
+
KeyboardButton("Delete โ"),
|
22 |
+
],
|
23 |
+
[
|
24 |
+
KeyboardButton("List ๐"),
|
25 |
+
KeyboardButton("Home ๐ "),
|
26 |
+
],
|
27 |
+
],
|
28 |
+
resize_keyboard=True,
|
29 |
+
)
|
30 |
+
|
31 |
+
|
32 |
+
def start_keyboard() -> ReplyKeyboardMarkup:
|
33 |
+
return ReplyKeyboardMarkup(
|
34 |
+
[
|
35 |
+
[
|
36 |
+
KeyboardButton("๐ Session"),
|
37 |
+
KeyboardButton("Force Sub โจ"),
|
38 |
+
],
|
39 |
+
[
|
40 |
+
KeyboardButton("๐ฅ Users"),
|
41 |
+
KeyboardButton("Others ๐ฃ"),
|
42 |
+
],
|
43 |
+
],
|
44 |
+
resize_keyboard=True,
|
45 |
+
)
|
Hellbot/plugins/decorator.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram import Client, filters
|
2 |
+
from pyrogram.enums import ChatType
|
3 |
+
from pyrogram.handlers import MessageHandler
|
4 |
+
from pyrogram.types import Message
|
5 |
+
|
6 |
+
from Hellbot.core import Config, db, hellbot
|
7 |
+
from Hellbot.functions.admins import is_user_admin
|
8 |
+
|
9 |
+
|
10 |
+
def on_message(
|
11 |
+
command: str | list[str],
|
12 |
+
group: int = 0,
|
13 |
+
chat_type: list[ChatType] = None,
|
14 |
+
admin_only: bool = False,
|
15 |
+
allow_stan: bool = False,
|
16 |
+
):
|
17 |
+
if allow_stan:
|
18 |
+
_filter = (
|
19 |
+
filters.command(command, Config.HANDLERS)
|
20 |
+
& (filters.me | Config.STAN_USERS)
|
21 |
+
& ~filters.forwarded
|
22 |
+
& ~filters.via_bot
|
23 |
+
)
|
24 |
+
else:
|
25 |
+
_filter = (
|
26 |
+
filters.command(command, Config.HANDLERS)
|
27 |
+
& filters.me
|
28 |
+
& ~filters.forwarded
|
29 |
+
& ~filters.via_bot
|
30 |
+
)
|
31 |
+
|
32 |
+
def decorator(func):
|
33 |
+
async def wrapper(client: Client, message: Message):
|
34 |
+
if client.me.id != message.from_user.id:
|
35 |
+
if not await db.is_stan(client.me.id, message.from_user.id):
|
36 |
+
return
|
37 |
+
|
38 |
+
if admin_only and not message.chat.type == ChatType.PRIVATE:
|
39 |
+
if not await is_user_admin(message.chat, client.me.id):
|
40 |
+
return await hellbot.edit(message, "๐จ ๐บ๐ ๐๐๐ ๐บ๐ ๐บ๐ฝ๐๐๐ ๐๐พ๐๐พ!")
|
41 |
+
|
42 |
+
if chat_type and message.chat.type not in chat_type:
|
43 |
+
return await hellbot.edit(message, "๐ข๐บ๐'๐ ๐๐๐พ ๐๐๐๐ ๐ผ๐๐๐๐บ๐๐ฝ ๐๐พ๐๐พ!")
|
44 |
+
|
45 |
+
await func(client, message)
|
46 |
+
message.continue_propagation()
|
47 |
+
|
48 |
+
for user in hellbot.users:
|
49 |
+
user.add_handler(MessageHandler(wrapper, _filter), group)
|
50 |
+
|
51 |
+
return wrapper
|
52 |
+
|
53 |
+
return decorator
|
54 |
+
|
55 |
+
|
56 |
+
def custom_handler(filters: filters.Filter, group: int = 0):
|
57 |
+
def decorator(func):
|
58 |
+
async def wrapper(client: Client, message: Message):
|
59 |
+
await func(client, message)
|
60 |
+
message.continue_propagation()
|
61 |
+
|
62 |
+
for user in hellbot.users:
|
63 |
+
user.add_handler(MessageHandler(wrapper, filters), group)
|
64 |
+
|
65 |
+
return wrapper
|
66 |
+
|
67 |
+
return decorator
|
Hellbot/plugins/help.py
ADDED
@@ -0,0 +1,132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from Hellbot.core.config import Config, Symbols
|
2 |
+
|
3 |
+
|
4 |
+
class HelpMenu:
|
5 |
+
def __init__(self, file: str) -> None:
|
6 |
+
self.filename = file
|
7 |
+
self.command_dict = {}
|
8 |
+
self.command_info = ""
|
9 |
+
|
10 |
+
def add(
|
11 |
+
self,
|
12 |
+
command: str,
|
13 |
+
parameters: str = None,
|
14 |
+
description: str = None,
|
15 |
+
example: str = None,
|
16 |
+
note: str = None,
|
17 |
+
):
|
18 |
+
self.command_dict[command] = {
|
19 |
+
"command": command,
|
20 |
+
"parameters": parameters,
|
21 |
+
"description": description,
|
22 |
+
"example": example,
|
23 |
+
"note": note,
|
24 |
+
}
|
25 |
+
return self
|
26 |
+
|
27 |
+
def info(self, command_info: str):
|
28 |
+
self.command_info = command_info
|
29 |
+
return self
|
30 |
+
|
31 |
+
def get_menu(self) -> str:
|
32 |
+
result = f"**๐ฏ๐
๐๐๐๐ ๐ฅ๐๐
๐พ:** `{self.filename}`"
|
33 |
+
if self.command_info:
|
34 |
+
result += f"\n**๐ฏ๐
๐๐๐๐ ๐จ๐๐ฟ๐:** __{self.command_info} ๐__"
|
35 |
+
result += "\n\n"
|
36 |
+
for command in self.command_dict:
|
37 |
+
command = self.command_dict[command]
|
38 |
+
result += f"**{Symbols.radio_select} ๐ข๐๐๐๐บ๐๐ฝ:** `{Config.HANDLERS[0]}{command['command']}"
|
39 |
+
if command["parameters"]:
|
40 |
+
result += f" {command['parameters']}`\n"
|
41 |
+
else:
|
42 |
+
result += "`\n"
|
43 |
+
if command["description"]:
|
44 |
+
result += (
|
45 |
+
f"**{Symbols.arrow_right} ๐ฃ๐พ๐๐ผ๐๐๐๐๐๐๐:** __{command['description']}__\n"
|
46 |
+
)
|
47 |
+
if command["example"]:
|
48 |
+
result += f"**{Symbols.arrow_right} ๐ค๐๐บ๐๐๐
๐พ:** `{Config.HANDLERS[0]}{command['example']}`\n"
|
49 |
+
if command["note"]:
|
50 |
+
result += f"**{Symbols.arrow_right} ๐ญ๐๐๐พ:** __{command['note']}__\n"
|
51 |
+
|
52 |
+
result += "\n"
|
53 |
+
|
54 |
+
Config.CMD_INFO[command["command"]] = {
|
55 |
+
"command": f"{command['command']} {command['parameters'] if command['parameters'] else ''}",
|
56 |
+
"description": command["description"],
|
57 |
+
"example": command["example"],
|
58 |
+
"note": command["note"],
|
59 |
+
"plugin": self.filename,
|
60 |
+
}
|
61 |
+
|
62 |
+
return result
|
63 |
+
|
64 |
+
def done(self) -> None:
|
65 |
+
Config.HELP_DICT[self.filename] = {
|
66 |
+
"commands": self.command_dict,
|
67 |
+
"info": self.command_info,
|
68 |
+
}
|
69 |
+
Config.CMD_MENU[self.filename] = self.get_menu()
|
70 |
+
|
71 |
+
|
72 |
+
class BotHelp:
|
73 |
+
def __init__(self, file: str) -> None:
|
74 |
+
self.category = file
|
75 |
+
self.command_dict = {}
|
76 |
+
self.command_info = ""
|
77 |
+
|
78 |
+
def add(self, command: str, description: str):
|
79 |
+
self.command_dict[command] = {"command": command, "description": description}
|
80 |
+
return self
|
81 |
+
|
82 |
+
def info(self, command_info: str):
|
83 |
+
self.command_info = command_info
|
84 |
+
return self
|
85 |
+
|
86 |
+
def get_menu(self) -> str:
|
87 |
+
result = f"**๐ฏ๐
๐๐๐๐ ๐ข๐บ๐๐พ๐๐๐๐:** `{self.category}`"
|
88 |
+
if self.command_info:
|
89 |
+
result += f"\n**๐ฏ๐
๐๐๐๐ ๐จ๐๐ฟ๐:** __{self.command_info}__"
|
90 |
+
result += "\n\n"
|
91 |
+
for command in self.command_dict:
|
92 |
+
command = self.command_dict[command]
|
93 |
+
result += f"**{Symbols.radio_select} ๐ข๐๐๐๐บ๐๐ฝ:** `/{command['command']}`\n"
|
94 |
+
if command["description"]:
|
95 |
+
result += (
|
96 |
+
f"**{Symbols.arrow_right} ๐ฃ๐พ๐๐ผ๐๐๐๐๐๐๐:** __{command['description']}__\n"
|
97 |
+
)
|
98 |
+
result += "\n"
|
99 |
+
|
100 |
+
Config.BOT_CMD_INFO[command["command"]] = {
|
101 |
+
"command": command["command"],
|
102 |
+
"description": command["description"],
|
103 |
+
"category": self.category,
|
104 |
+
}
|
105 |
+
|
106 |
+
return result
|
107 |
+
|
108 |
+
def done(self) -> None:
|
109 |
+
Config.BOT_HELP[self.category] = {
|
110 |
+
"commands": self.command_dict,
|
111 |
+
"info": self.command_info,
|
112 |
+
}
|
113 |
+
Config.BOT_CMD_MENU[self.category] = self.get_menu()
|
114 |
+
|
115 |
+
|
116 |
+
# example usage of HelpMenu class
|
117 |
+
"""
|
118 |
+
HelpMenu("example").add(
|
119 |
+
"example", "<text>", "description of command", "example of command", "note of command"
|
120 |
+
).info(
|
121 |
+
"information of plugin"
|
122 |
+
).done()
|
123 |
+
"""
|
124 |
+
|
125 |
+
# example usage of BotHelp class
|
126 |
+
"""
|
127 |
+
BotHelp("example").add(
|
128 |
+
"example", "description of command"
|
129 |
+
).info(
|
130 |
+
"information of category"
|
131 |
+
).done()
|
132 |
+
"""
|
Hellbot/plugins/user/__init__.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram.enums import ChatType
|
2 |
+
|
3 |
+
from Hellbot.core.clients import hellbot
|
4 |
+
from Hellbot.core.config import Config, Symbols
|
5 |
+
from Hellbot.core.database import db
|
6 |
+
from Hellbot.plugins.decorator import custom_handler, on_message
|
7 |
+
from Hellbot.plugins.help import HelpMenu
|
8 |
+
|
9 |
+
handler = Config.HANDLERS[0]
|
10 |
+
bot = hellbot.bot
|
11 |
+
|
12 |
+
bot_only = [ChatType.BOT]
|
13 |
+
group_n_channel = [ChatType.GROUP, ChatType.SUPERGROUP, ChatType.CHANNEL]
|
14 |
+
group_only = [ChatType.GROUP, ChatType.SUPERGROUP]
|
15 |
+
private_n_bot = [ChatType.PRIVATE, ChatType.BOT]
|
16 |
+
private_only = [ChatType.PRIVATE]
|
Hellbot/plugins/user/admins.py
ADDED
@@ -0,0 +1,510 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import asyncio
|
2 |
+
|
3 |
+
from pyrogram import Client, filters
|
4 |
+
from pyrogram.types import ChatPermissions, ChatPrivileges, Message
|
5 |
+
|
6 |
+
from Hellbot.core import LOGS
|
7 |
+
|
8 |
+
from . import HelpMenu, custom_handler, db, group_only, handler, hellbot, on_message
|
9 |
+
|
10 |
+
|
11 |
+
@on_message(
|
12 |
+
"promote",
|
13 |
+
chat_type=group_only,
|
14 |
+
admin_only=True,
|
15 |
+
allow_stan=True,
|
16 |
+
)
|
17 |
+
async def promote(client: Client, message: Message):
|
18 |
+
if len(message.command) < 2 and not message.reply_to_message:
|
19 |
+
return await hellbot.delete(
|
20 |
+
message, "๐ญ๐พ๐พ๐ฝ ๐บ ๐๐๐พ๐๐๐บ๐๐พ/๐๐ฝ ๐๐ ๐๐พ๐๐
๐ ๐๐ ๐บ ๐๐๐พ๐ ๐๐ ๐๐๐๐๐๐๐พ ๐๐๐พ๐!"
|
21 |
+
)
|
22 |
+
|
23 |
+
if message.reply_to_message:
|
24 |
+
user = message.reply_to_message.from_user
|
25 |
+
title = await hellbot.input(message)
|
26 |
+
else:
|
27 |
+
user = await client.get_users(message.command[1])
|
28 |
+
title = (await hellbot.input(message)).split(" ", 1)[1].strip() or ""
|
29 |
+
|
30 |
+
try:
|
31 |
+
privileges = ChatPrivileges(
|
32 |
+
can_manage_chat=True,
|
33 |
+
can_delete_messages=True,
|
34 |
+
can_manage_video_chats=True,
|
35 |
+
can_restrict_members=False,
|
36 |
+
can_promote_members=False,
|
37 |
+
can_change_info=False,
|
38 |
+
can_invite_users=True,
|
39 |
+
can_pin_messages=True,
|
40 |
+
is_anonymous=False,
|
41 |
+
)
|
42 |
+
await message.chat.promote_member(user.id, privileges)
|
43 |
+
await client.set_administrator_title(message.chat.id, user.id, title)
|
44 |
+
except Exception as e:
|
45 |
+
return await hellbot.error(message, e)
|
46 |
+
|
47 |
+
await hellbot.delete(message, f"**๐ซ ๐ฏ๐๐๐๐๐๐พ๐ฝ {user.mention} ๐๐๐ผ๐ผ๐พ๐๐๐ฟ๐๐
๐
๐!**")
|
48 |
+
await hellbot.check_and_log(
|
49 |
+
"promote",
|
50 |
+
f"**Promoted User**\n\n**User:** {user.mention}\n**User ID:** `{user.id}`\n**Admin:** `{message.from_user.mention}`\n**Group:** `{message.chat.title}`\n**Group ID:** `{message.chat.id}`",
|
51 |
+
)
|
52 |
+
|
53 |
+
|
54 |
+
@on_message(
|
55 |
+
"demote",
|
56 |
+
chat_type=group_only,
|
57 |
+
admin_only=True,
|
58 |
+
allow_stan=True,
|
59 |
+
)
|
60 |
+
async def demote(client: Client, message: Message):
|
61 |
+
if len(message.command) < 2 and not message.reply_to_message:
|
62 |
+
return await hellbot.delete(
|
63 |
+
message, "๐ญ๐พ๐พ๐ฝ ๐บ ๐๐๐พ๐๐๐บ๐๐พ/๐๐ฝ ๐๐ ๐๐พ๐๐
๐ ๐๐ ๐บ ๐๐๐พ๐ ๐๐ ๐ฝ๐พ๐๐๐๐พ ๐๐๐พ๐!"
|
64 |
+
)
|
65 |
+
|
66 |
+
if message.reply_to_message:
|
67 |
+
user = message.reply_to_message.from_user
|
68 |
+
else:
|
69 |
+
user = await client.get_users(message.command[1])
|
70 |
+
try:
|
71 |
+
privileges = ChatPrivileges(
|
72 |
+
can_manage_chat=False,
|
73 |
+
can_delete_messages=False,
|
74 |
+
can_manage_video_chats=False,
|
75 |
+
can_restrict_members=False,
|
76 |
+
can_promote_members=False,
|
77 |
+
can_change_info=False,
|
78 |
+
can_invite_users=False,
|
79 |
+
can_pin_messages=False,
|
80 |
+
is_anonymous=False,
|
81 |
+
)
|
82 |
+
await message.chat.promote_member(user.id, privileges)
|
83 |
+
except Exception as e:
|
84 |
+
return await hellbot.error(message, e)
|
85 |
+
|
86 |
+
await hellbot.delete(message, f"**๐ ๐ฃ๐พ๐๐๐๐พ๐ฝ {user.mention} ๐๐๐ผ๐ผ๐พ๐๐๐ฟ๐๐
๐
๐!**")
|
87 |
+
await hellbot.check_and_log(
|
88 |
+
"demote",
|
89 |
+
f"**Demoted User**\n\n**User:** {user.mention}\n**User ID:** `{user.id}`\n**Admin:** `{message.from_user.mention}`\n**Group:** `{message.chat.title}`\n**Group ID:** `{message.chat.id}`",
|
90 |
+
)
|
91 |
+
|
92 |
+
|
93 |
+
@on_message(
|
94 |
+
["ban", "dban"],
|
95 |
+
chat_type=group_only,
|
96 |
+
admin_only=True,
|
97 |
+
allow_stan=True,
|
98 |
+
)
|
99 |
+
async def ban(client: Client, message: Message):
|
100 |
+
if message.reply_to_message:
|
101 |
+
user = message.reply_to_message.from_user
|
102 |
+
if len(message.command) < 2:
|
103 |
+
reason = None
|
104 |
+
else:
|
105 |
+
reason = await hellbot.input(message)
|
106 |
+
if message.command[0][0].lower() == "d":
|
107 |
+
await message.reply_to_message.delete()
|
108 |
+
elif len(message.command) == 2:
|
109 |
+
user = await client.get_users(message.command[1])
|
110 |
+
reason = None
|
111 |
+
elif len(message.command) > 2:
|
112 |
+
user = await client.get_users(message.command[1])
|
113 |
+
reason = (await hellbot.input(message)).split(" ", 1)[1].strip()
|
114 |
+
else:
|
115 |
+
return await hellbot.delete(
|
116 |
+
message, "๐ญ๐พ๐พ๐ฝ ๐บ ๐๐๐พ๐๐๐บ๐๐พ/๐๐ฝ ๐๐ ๐๐พ๐๐
๐ ๐๐ ๐บ ๐๐๐พ๐ ๐๐ ๐ป๐บ๐ ๐๐๐พ๐!"
|
117 |
+
)
|
118 |
+
|
119 |
+
try:
|
120 |
+
await message.chat.ban_member(user.id)
|
121 |
+
except Exception as e:
|
122 |
+
return await hellbot.error(message, e)
|
123 |
+
|
124 |
+
reason = reason if reason else "Not Specified"
|
125 |
+
await hellbot.delete(
|
126 |
+
message,
|
127 |
+
f"**โ ๏ธ ๐ก๐บ๐๐๐พ๐ฝ {user.mention} ๐๐๐ผ๐ผ๐พ๐๐๐ฟ๐๐
๐
๐!**\n**๐ฑ๐พ๐บ๐๐๐:** `{reason}`",
|
128 |
+
30,
|
129 |
+
)
|
130 |
+
await hellbot.check_and_log(
|
131 |
+
"ban",
|
132 |
+
f"**Banned User**\n\n**User:** {user.mention}\n**User ID:** `{user.id}`\n**Reason:** `{reason}`\n**Admin:** `{message.from_user.mention}`\n**Group:** `{message.chat.title}`\n**Group ID:** `{message.chat.id}`",
|
133 |
+
)
|
134 |
+
|
135 |
+
|
136 |
+
@on_message(
|
137 |
+
"unban",
|
138 |
+
chat_type=group_only,
|
139 |
+
admin_only=True,
|
140 |
+
allow_stan=True,
|
141 |
+
)
|
142 |
+
async def unban(client: Client, message: Message):
|
143 |
+
if len(message.command) < 2 and not message.reply_to_message:
|
144 |
+
return await hellbot.delete(
|
145 |
+
message, "๐ญ๐พ๐พ๐ฝ ๐บ ๐๐๐พ๐๐๐บ๐๐พ/๐๐ฝ ๐๐ ๐๐พ๐๐
๐ ๐๐ ๐บ ๐๐๐พ๐ ๐๐ ๐๐๐ป๐บ๐ ๐๐๐พ๐!"
|
146 |
+
)
|
147 |
+
|
148 |
+
if message.reply_to_message:
|
149 |
+
user = message.reply_to_message.from_user
|
150 |
+
else:
|
151 |
+
user = await client.get_users(message.command[1])
|
152 |
+
|
153 |
+
try:
|
154 |
+
await message.chat.unban_member(user.id)
|
155 |
+
except Exception as e:
|
156 |
+
return await hellbot.error(message, e)
|
157 |
+
|
158 |
+
await hellbot.delete(message, f"**๐ค ๐ด๐๐ป๐บ๐๐๐พ๐ฝ {user.mention} ๐ฒ๐๐ผ๐ผ๐พ๐๐๐ฟ๐๐
๐
๐!**", 30)
|
159 |
+
await hellbot.check_and_log(
|
160 |
+
"unban",
|
161 |
+
f"**Unbanned User**\n\n**User:** {user.mention}\n**User ID:** `{user.id}`\n**Admin:** `{message.from_user.mention}`\n**Group:** `{message.chat.title}`\n**Group ID:** `{message.chat.id}`",
|
162 |
+
)
|
163 |
+
|
164 |
+
|
165 |
+
@on_message(
|
166 |
+
["kick", "dkick"],
|
167 |
+
chat_type=group_only,
|
168 |
+
admin_only=True,
|
169 |
+
allow_stan=True,
|
170 |
+
)
|
171 |
+
async def kick(client: Client, message: Message):
|
172 |
+
if message.reply_to_message:
|
173 |
+
user = message.reply_to_message.from_user
|
174 |
+
if len(message.command) < 2:
|
175 |
+
reason = None
|
176 |
+
else:
|
177 |
+
reason = await hellbot.input(message)
|
178 |
+
if message.command[0][0].lower() == "d":
|
179 |
+
await message.reply_to_message.delete()
|
180 |
+
elif len(message.command) == 2:
|
181 |
+
user = await client.get_users(message.command[1])
|
182 |
+
reason = None
|
183 |
+
elif len(message.command) > 2:
|
184 |
+
user = await client.get_users(message.command[1])
|
185 |
+
reason = (await hellbot.input(message)).split(" ", 1)[1].strip()
|
186 |
+
else:
|
187 |
+
return await hellbot.delete(
|
188 |
+
message, "๐ญ๐พ๐พ๐ฝ ๐บ ๐๐๐พ๐๐๐บ๐๐พ/๐๐ฝ ๐๐ ๐๐พ๐๐
๐ ๐๐ ๐บ ๐๐๐พ๐ ๐๐ ๐๐๐ผ๐ ๐๐๐พ๐!"
|
189 |
+
)
|
190 |
+
|
191 |
+
try:
|
192 |
+
await message.chat.ban_member(user.id)
|
193 |
+
except Exception as e:
|
194 |
+
return await hellbot.error(message, e)
|
195 |
+
|
196 |
+
reason = reason if reason else "Not Specified"
|
197 |
+
await hellbot.delete(
|
198 |
+
message,
|
199 |
+
f"**๐ ๐ช๐๐ผ๐๐พ๐ฝ {user.mention} ๐ฒ๐๐ผ๐ผ๐พ๐๐๐ฟ๐๐
๐
๐!**\n**๐ฑ๐พ๐บ๐๐๐:** `{reason}`",
|
200 |
+
30,
|
201 |
+
)
|
202 |
+
await hellbot.check_and_log(
|
203 |
+
"kick",
|
204 |
+
f"**Kicked User**\n\n**User:** {user.mention}\n**User ID:** `{user.id}`\n**Reason:** `{reason}`\n**Admin:** `{message.from_user.mention}`\n**Group:** `{message.chat.title}`\n**Group ID:** `{message.chat.id}`",
|
205 |
+
)
|
206 |
+
await asyncio.sleep(5)
|
207 |
+
await message.chat.unban_member(user.id)
|
208 |
+
|
209 |
+
|
210 |
+
@on_message(
|
211 |
+
"mute",
|
212 |
+
chat_type=group_only,
|
213 |
+
admin_only=True,
|
214 |
+
allow_stan=True,
|
215 |
+
)
|
216 |
+
async def mute(client: Client, message: Message):
|
217 |
+
if message.reply_to_message:
|
218 |
+
user = message.reply_to_message.from_user
|
219 |
+
if len(message.command) < 2:
|
220 |
+
reason = None
|
221 |
+
else:
|
222 |
+
reason = await hellbot.input(message)
|
223 |
+
elif len(message.command) == 2:
|
224 |
+
user = await client.get_users(message.command[1])
|
225 |
+
reason = None
|
226 |
+
elif len(message.command) > 2:
|
227 |
+
user = await client.get_users(message.command[1])
|
228 |
+
reason = (await hellbot.input(message)).split(" ", 1)[1].strip()
|
229 |
+
else:
|
230 |
+
return await hellbot.delete(
|
231 |
+
message, "๐ญ๐พ๐พ๐ฝ ๐บ ๐๐๐พ๐๐๐บ๐๐พ/๐๐ฝ ๐๐ ๐๐พ๐๐
๐ ๐๐ ๐บ ๐๐๐พ๐ ๐๐ ๐๐๐๐พ ๐๐๐พ๐!"
|
232 |
+
)
|
233 |
+
|
234 |
+
try:
|
235 |
+
permissions = ChatPermissions(
|
236 |
+
can_send_messages=False,
|
237 |
+
)
|
238 |
+
await message.chat.restrict_member(user.id, permissions)
|
239 |
+
except Exception as e:
|
240 |
+
return await hellbot.error(message, e)
|
241 |
+
|
242 |
+
reason = reason if reason else "Not Specified"
|
243 |
+
await hellbot.delete(
|
244 |
+
message,
|
245 |
+
f"**๐ค ๐ฌ๐๐๐พ๐ฝ {user.mention} ๐ฒ๐๐ผ๐ผ๐พ๐๐๐ฟ๐๐
๐
๐!**\n**๐ฑ๐พ๐บ๐๐๐:** `{reason}`",
|
246 |
+
30,
|
247 |
+
)
|
248 |
+
await hellbot.check_and_log(
|
249 |
+
"mute",
|
250 |
+
f"**Muted User**\n\n**User:** {user.mention}\n**User ID:** `{user.id}`\n**Reason:** `{reason}`\n**Admin:** `{message.from_user.mention}`\n**Group:** `{message.chat.title}`\n**Group ID:** `{message.chat.id}`",
|
251 |
+
)
|
252 |
+
|
253 |
+
|
254 |
+
@on_message(
|
255 |
+
"unmute",
|
256 |
+
chat_type=group_only,
|
257 |
+
admin_only=True,
|
258 |
+
allow_stan=True,
|
259 |
+
)
|
260 |
+
async def unmute(client: Client, message: Message):
|
261 |
+
if len(message.command) < 2 and not message.reply_to_message:
|
262 |
+
return await hellbot.delete(
|
263 |
+
message, "๐ญ๐พ๐พ๐ฝ ๐บ ๐๐๐พ๐๐๐บ๐๐พ/๐๐ฝ ๐๐ ๐๐พ๐๐
๐ ๐๐ ๐บ ๐๐๐พ๐ ๐๐ ๐๐๐๐๐๐พ ๐๐๐พ๐!"
|
264 |
+
)
|
265 |
+
|
266 |
+
if message.reply_to_message:
|
267 |
+
user = message.reply_to_message.from_user
|
268 |
+
else:
|
269 |
+
user = await client.get_users(message.command[1])
|
270 |
+
|
271 |
+
try:
|
272 |
+
permissions = ChatPermissions(
|
273 |
+
can_send_messages=True,
|
274 |
+
)
|
275 |
+
await message.chat.restrict_member(user.id, permissions)
|
276 |
+
except Exception as e:
|
277 |
+
return await hellbot.error(message, e)
|
278 |
+
|
279 |
+
await hellbot.delete(message, f"**๐ ๐ด๐๐๐๐๐พ๐ฝ {user.mention} ๐ฒ๐๐ผ๐ผ๐พ๐๐๐ฟ๐๐
๐
๐!**", 30)
|
280 |
+
await hellbot.check_and_log(
|
281 |
+
"unmute",
|
282 |
+
f"**Unmuted User**\n\n**User:** {user.mention}\n**User ID:** `{user.id}`\n**Admin:** `{message.from_user.mention}`\n**Group:** `{message.chat.title}`\n**Group ID:** `{message.chat.id}`",
|
283 |
+
)
|
284 |
+
|
285 |
+
|
286 |
+
@on_message("dmute", allow_stan=True)
|
287 |
+
async def dmute(client: Client, message: Message):
|
288 |
+
if message.reply_to_message:
|
289 |
+
user = message.reply_to_message.from_user
|
290 |
+
if len(message.command) < 2:
|
291 |
+
reason = None
|
292 |
+
else:
|
293 |
+
reason = await hellbot.input(message)
|
294 |
+
elif len(message.command) == 2:
|
295 |
+
user = await client.get_users(message.command[1])
|
296 |
+
reason = None
|
297 |
+
elif len(message.command) > 2:
|
298 |
+
user = await client.get_users(message.command[1])
|
299 |
+
reason = (await hellbot.input(message)).split(" ", 1)[1].strip()
|
300 |
+
else:
|
301 |
+
return await hellbot.delete(
|
302 |
+
message, "๐ญ๐พ๐พ๐ฝ ๐บ ๐๐๐พ๐๐๐บ๐๐พ/๐๐ฝ ๐๐ ๐๐พ๐๐
๐ ๐๐ ๐บ ๐๐๐พ๐ ๐๐ ๐๐๐๐พ ๐๐๐พ๐!"
|
303 |
+
)
|
304 |
+
|
305 |
+
if await db.is_muted(client.me.id, user.id, message.chat.id):
|
306 |
+
return await hellbot.delete(message, "This user is already dmuted.")
|
307 |
+
|
308 |
+
reason = reason if reason else "Not Specified"
|
309 |
+
await db.add_mute(client.me.id, user.id, message.chat.id, reason)
|
310 |
+
await hellbot.delete(
|
311 |
+
message,
|
312 |
+
f"**๐ค ๐ฌ๐๐๐พ๐ฝ {user.mention} ๐ฒ๐๐ผ๐ผ๐พ๐๐๐ฟ๐๐
๐
๐!**\n**๐ฑ๐พ๐บ๐๐๐:** `{reason}`",
|
313 |
+
30,
|
314 |
+
)
|
315 |
+
await hellbot.check_and_log(
|
316 |
+
"dmute",
|
317 |
+
f"**D-Muted User**\n\n**User:** {user.mention}\n**User ID:** `{user.id}`\n**Reason:** `{reason}`\n**Admin:** `{message.from_user.mention}`\n**Group:** `{message.chat.title or message.chat.first_name}`\n**Group ID:** `{message.chat.id}`",
|
318 |
+
)
|
319 |
+
|
320 |
+
|
321 |
+
@on_message("undmute", allow_stan=True)
|
322 |
+
async def undmute(client: Client, message: Message):
|
323 |
+
if len(message.command) < 2 and not message.reply_to_message:
|
324 |
+
return await hellbot.delete(
|
325 |
+
message, "๐ญ๐พ๐พ๐ฝ ๐บ ๐๐๐พ๐๐๐บ๐๐พ/๐๐ฝ ๐๐ ๐๐พ๐๐
๐ ๐๐ ๐บ ๐๐๐พ๐ ๐๐ ๐๐๐๐๐๐พ ๐๐๐พ๐!"
|
326 |
+
)
|
327 |
+
|
328 |
+
if message.reply_to_message:
|
329 |
+
user = message.reply_to_message.from_user
|
330 |
+
else:
|
331 |
+
user = await client.get_users(message.command[1])
|
332 |
+
|
333 |
+
if not await db.is_muted(client.me.id, user.id, message.chat.id):
|
334 |
+
return await hellbot.delete(message, "๐ณ๐๐พ ๐๐๐พ๐ ๐๐ ๐๐๐ ๐๐๐๐พ๐ฝ!")
|
335 |
+
|
336 |
+
reason = await db.rm_mute(client.me.id, user.id, message.chat.id)
|
337 |
+
await hellbot.delete(
|
338 |
+
message,
|
339 |
+
f"**๐ ๐ด๐๐๐๐๐พ๐ฝ {user.mention} ๐ฒ๐๐ผ๐ผ๐พ๐๐๐ฟ๐๐
๐
๐!**\n\n**Mute reason was:** `{reason}`",
|
340 |
+
30,
|
341 |
+
)
|
342 |
+
await hellbot.check_and_log(
|
343 |
+
"unmute",
|
344 |
+
f"**D-Unmuted User**\n\n**User:** {user.mention}\n**User ID:** `{user.id}`\n**Admin:** `{message.from_user.mention}`\n**Group:** `{message.chat.title}`\n**Group ID:** `{message.chat.id}`",
|
345 |
+
)
|
346 |
+
|
347 |
+
|
348 |
+
@on_message(
|
349 |
+
"pin",
|
350 |
+
chat_type=group_only,
|
351 |
+
admin_only=True,
|
352 |
+
allow_stan=True,
|
353 |
+
)
|
354 |
+
async def pin(_, message: Message):
|
355 |
+
if not message.reply_to_message:
|
356 |
+
return await hellbot.delete(message, "๐ญ๐พ๐พ๐ฝ ๐บ ๐๐พ๐๐
๐ ๐๐ ๐๐๐ ๐บ ๐๐พ๐๐๐บ๐๐พ!")
|
357 |
+
|
358 |
+
try:
|
359 |
+
await message.reply_to_message.pin()
|
360 |
+
except Exception as e:
|
361 |
+
return await hellbot.error(message, e)
|
362 |
+
|
363 |
+
await hellbot.delete(
|
364 |
+
message,
|
365 |
+
f"**๐ ๐ฏ๐๐๐๐พ๐ฝ [๐ฌ๐พ๐๐๐บ๐๐พ]({message.reply_to_message.link}) ๐๐ {message.chat.title}!**",
|
366 |
+
30,
|
367 |
+
)
|
368 |
+
await hellbot.check_and_log(
|
369 |
+
"pin",
|
370 |
+
f"**Pinned Message**\n\n**Message:** [Click Here]({message.reply_to_message.link})\n**Admin:** `{message.from_user.mention}`\n**Group:** `{message.chat.title}`\n**Group ID:** `{message.chat.id}`",
|
371 |
+
)
|
372 |
+
|
373 |
+
|
374 |
+
@on_message(
|
375 |
+
"unpin",
|
376 |
+
chat_type=group_only,
|
377 |
+
admin_only=True,
|
378 |
+
allow_stan=True,
|
379 |
+
)
|
380 |
+
async def unpin(_, message: Message):
|
381 |
+
if not message.reply_to_message:
|
382 |
+
return await hellbot.delete(message, "๐ญ๐พ๐พ๐ฝ ๐บ ๐๐พ๐๐
๐ ๐๐ ๐๐๐๐๐ ๐บ ๐๐พ๐๐๐บ๐๐พ!")
|
383 |
+
|
384 |
+
try:
|
385 |
+
await message.reply_to_message.unpin()
|
386 |
+
except Exception as e:
|
387 |
+
return await hellbot.error(message, e)
|
388 |
+
|
389 |
+
await hellbot.delete(
|
390 |
+
message,
|
391 |
+
f"**๐ ๐ด๐๐๐๐๐๐พ๐ฝ [๐ฌ๐พ๐๐๐บ๐๐พ]({message.reply_to_message.link}) ๐๐ {message.chat.title}!**",
|
392 |
+
30,
|
393 |
+
)
|
394 |
+
await hellbot.check_and_log(
|
395 |
+
"unpin",
|
396 |
+
f"**Unpinned Message**\n\n**Message:** [Click Here]({message.reply_to_message.link})\n**Admin:** `{message.from_user.mention}`\n**Group:** `{message.chat.title}`\n**Group ID:** `{message.chat.id}`",
|
397 |
+
)
|
398 |
+
|
399 |
+
|
400 |
+
@on_message(
|
401 |
+
"zombies",
|
402 |
+
chat_type=group_only,
|
403 |
+
admin_only=True,
|
404 |
+
allow_stan=True,
|
405 |
+
)
|
406 |
+
async def zombies(_, message: Message):
|
407 |
+
hell = await hellbot.edit(message, "โ ๏ธ ๐ฃ๐พ๐๐พ๐ผ๐๐๐๐ ๐๐๐๐ป๐๐พ๐...")
|
408 |
+
ded_users = []
|
409 |
+
async for members in message.chat.get_members():
|
410 |
+
if members.user.is_deleted:
|
411 |
+
ded_users.append(members.user.id)
|
412 |
+
|
413 |
+
if not ded_users:
|
414 |
+
return await hell.edit(
|
415 |
+
"๐ซก ๐ฃ๐๐'๐ ๐๐บ๐๐พ ๐บ๐๐ ๐๐๐๐ป๐๐พ๐ ๐๐ ๐๐๐๐ ๐๐๐๐๐. **๐ฆ๐๐๐๐๐' ๐ผ๐
๐พ๐บ๐ ๐ ๐ฅ!**"
|
416 |
+
)
|
417 |
+
|
418 |
+
if len(message.command) > 1 and message.command[1].lower() == "clean":
|
419 |
+
await hell.edit(
|
420 |
+
f"โ ๏ธ ๐ฅ๐๐๐๐ฝ {len(ded_users)} ๐๐๐๐ป๐๐พ๐... **๐ซ ๐ณ๐๐๐พ ๐๐ ๐๐๐๐๐พ ๐๐๐พ๐!**"
|
421 |
+
)
|
422 |
+
failed = 0
|
423 |
+
success = 0
|
424 |
+
for user in ded_users:
|
425 |
+
try:
|
426 |
+
await message.chat.ban_member(user)
|
427 |
+
success += 1
|
428 |
+
except Exception as e:
|
429 |
+
LOGS.error(e)
|
430 |
+
failed += 1
|
431 |
+
|
432 |
+
await hell.edit(f"**๐ฏ๐๐๐๐พ๐ฝ {success} ๐๐๐๐ป๐๐พ๐!**\n`{failed}` holds immunity!")
|
433 |
+
else:
|
434 |
+
await hell.edit(
|
435 |
+
f"**โ ๏ธ ๐ฅ๐๐๐๐ฝ {len(ded_users)} ๐๐๐๐ป๐๐พ๐!**\n\n__Use__ `{handler}zombies clean` __to kill them!__"
|
436 |
+
)
|
437 |
+
|
438 |
+
|
439 |
+
@custom_handler(filters.incoming)
|
440 |
+
async def multiple_handler(client: Client, message: Message):
|
441 |
+
if not message.from_user:
|
442 |
+
return
|
443 |
+
|
444 |
+
if await db.is_muted(client.me.id, message.from_user.id, message.chat.id):
|
445 |
+
try:
|
446 |
+
await message.delete()
|
447 |
+
except:
|
448 |
+
pass
|
449 |
+
|
450 |
+
elif await db.is_gmuted(message.from_user.id):
|
451 |
+
try:
|
452 |
+
await message.delete()
|
453 |
+
except:
|
454 |
+
pass
|
455 |
+
|
456 |
+
elif await db.is_echo(client.me.id, message.chat.id, message.from_user.id):
|
457 |
+
await message.copy(message.chat.id, reply_to_message_id=message.id)
|
458 |
+
|
459 |
+
|
460 |
+
HelpMenu("admin").add(
|
461 |
+
"promote",
|
462 |
+
"<๐๐๐พ๐๐๐บ๐๐พ/๐๐ฝ/reply> <๐๐๐๐
๐พ>",
|
463 |
+
"Promote a user to admin.",
|
464 |
+
"promote @ForGo10God hellboy",
|
465 |
+
).add(
|
466 |
+
"demote", "<username/id/reply>", "Demote a user from admin.", "demote @ForGo10God"
|
467 |
+
).add(
|
468 |
+
"ban",
|
469 |
+
"<username/id/reply> <reason>",
|
470 |
+
"Ban a user from the group.",
|
471 |
+
"ban @ForGo10God",
|
472 |
+
"You can also use dban to delete the message of the user.",
|
473 |
+
).add(
|
474 |
+
"unban", "<username/id/reply>", "Unban a user from the group.", "unban @ForGo10God"
|
475 |
+
).add(
|
476 |
+
"kick",
|
477 |
+
"<username/id/reply> <reason>",
|
478 |
+
"Kick a user from the group.",
|
479 |
+
"kick @ForGo10God",
|
480 |
+
"You can also use dkick to delete the message of the user.",
|
481 |
+
).add(
|
482 |
+
"mute",
|
483 |
+
"<username/id/reply> <reason>",
|
484 |
+
"Mute a user in the group",
|
485 |
+
"mute @ForGo10God",
|
486 |
+
"You can also use dmute to delete the message of the user.",
|
487 |
+
).add(
|
488 |
+
"unmute", "<username/id/reply>", "Unmute a user in the group.", "unmute @ForGo10God"
|
489 |
+
).add(
|
490 |
+
"dmute",
|
491 |
+
"<username/id/reply>",
|
492 |
+
"Mute a user by deleting their new messages in the group.",
|
493 |
+
"dmute @ForGo10God",
|
494 |
+
"Need delete message permission for proper functioning.",
|
495 |
+
).add(
|
496 |
+
"undmute",
|
497 |
+
"<username/id/reply>",
|
498 |
+
"Unmute a user who's muted using 'dmute' command in the group.",
|
499 |
+
"undmute @ForGo10God",
|
500 |
+
).add(
|
501 |
+
"pin", "<reply>", "Pin the replied message in the group."
|
502 |
+
).add(
|
503 |
+
"unpin", "<reply>", "Unpin the replied pinned message in the group."
|
504 |
+
).add(
|
505 |
+
"zombies",
|
506 |
+
"clean",
|
507 |
+
"Finds the total number of deleted users present in that group and ban them.",
|
508 |
+
).info(
|
509 |
+
"Admin Menu"
|
510 |
+
).done()
|
Hellbot/plugins/user/afk.py
ADDED
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import random
|
3 |
+
import time
|
4 |
+
|
5 |
+
from pyrogram import Client, filters
|
6 |
+
from pyrogram.enums import MessageMediaType
|
7 |
+
from pyrogram.types import Message
|
8 |
+
|
9 |
+
from Hellbot.core import Config, db, hellbot
|
10 |
+
from Hellbot.functions.formatter import add_to_dict, get_from_dict, readable_time
|
11 |
+
|
12 |
+
from . import HelpMenu, custom_handler, group_only, on_message
|
13 |
+
|
14 |
+
afk_quotes = [
|
15 |
+
"๐ถโโ๏ธ Taking a break, be back soon!",
|
16 |
+
"โณ AFK - Away From the Keyboard momentarily.",
|
17 |
+
"๐ Stepped away, but I'll return shortly.",
|
18 |
+
"๐ Gone for a moment, not forgotten.",
|
19 |
+
"๐ฟ Taking a breather, back in a bit.",
|
20 |
+
"๐ต Away for a while, feel free to leave a message!",
|
21 |
+
"โฐ On a short break, back shortly.",
|
22 |
+
"๐ Away from the screen, catching a breath.",
|
23 |
+
"๐ค Offline for a moment, but still here in spirit.",
|
24 |
+
"๐ Exploring the real world, back in a moment!",
|
25 |
+
"๐ต Taking a tea break, back shortly!",
|
26 |
+
"๐ Resting my keyboard, back after a short nap.",
|
27 |
+
"๐ถโโ๏ธ Stepping away for a moment of peace.",
|
28 |
+
"๐ต AFK but humming along, back shortly!",
|
29 |
+
"๐ Taking a sunshine break, back soon!",
|
30 |
+
"๐ Away, catching some waves of relaxation.",
|
31 |
+
"๐ช Temporarily closed, be back in a bit!",
|
32 |
+
"๐ธ Taking a moment to smell the digital roses.",
|
33 |
+
"๐ Stepped into the real world for a while.",
|
34 |
+
]
|
35 |
+
|
36 |
+
|
37 |
+
@on_message("afk")
|
38 |
+
async def afk(_, message: Message):
|
39 |
+
if await db.is_afk(message.from_user.id):
|
40 |
+
return await hellbot.delete(message, "๐ ๐จ'๐ ๐บ๐
๐๐พ๐บ๐ฝ๐ ๐ ๐ฅ๐ช!")
|
41 |
+
|
42 |
+
media_type = None
|
43 |
+
media = None
|
44 |
+
|
45 |
+
if message.reply_to_message and message.reply_to_message.media:
|
46 |
+
if message.reply_to_message.media == MessageMediaType.ANIMATION:
|
47 |
+
media_type = "animation"
|
48 |
+
elif message.reply_to_message.media == MessageMediaType.AUDIO:
|
49 |
+
media_type = "audio"
|
50 |
+
elif message.reply_to_message.media == MessageMediaType.PHOTO:
|
51 |
+
media_type = "photo"
|
52 |
+
elif message.reply_to_message.media == MessageMediaType.STICKER:
|
53 |
+
media_type = "sticker"
|
54 |
+
elif message.reply_to_message.media == MessageMediaType.VIDEO:
|
55 |
+
media_type = "video"
|
56 |
+
elif message.reply_to_message.media == MessageMediaType.VOICE:
|
57 |
+
media_type = "voice"
|
58 |
+
|
59 |
+
media = await message.reply_to_message.forward(Config.LOGGER_ID)
|
60 |
+
|
61 |
+
reason = await hellbot.input(message)
|
62 |
+
reason = reason if reason else "Not specified"
|
63 |
+
|
64 |
+
await db.set_afk(
|
65 |
+
message.from_user.id, reason, media.id if media else None, media_type
|
66 |
+
)
|
67 |
+
await hellbot.delete(message, "๐ซก ๐ฆ๐๐๐๐ ๐ ๐ฅ๐ช! ๐ฒ๐พ๐พ ๐๐บ'๐
๐
๐
๐บ๐๐พ๐.")
|
68 |
+
await hellbot.check_and_log(
|
69 |
+
"afk",
|
70 |
+
f"Going AFK! \n\n**Reason:** `{reason}`",
|
71 |
+
)
|
72 |
+
add_to_dict(Config.AFK_CACHE, [message.from_user.id, message.chat.id])
|
73 |
+
|
74 |
+
|
75 |
+
@custom_handler(filters.incoming & ~filters.bot & ~filters.service)
|
76 |
+
async def afk_watch(client: Client, message: Message):
|
77 |
+
afk_data = await db.get_afk(client.me.id)
|
78 |
+
if not afk_data:
|
79 |
+
return
|
80 |
+
|
81 |
+
if message.from_user.id == afk_data["user_id"]:
|
82 |
+
return
|
83 |
+
|
84 |
+
if message.chat.type in group_only:
|
85 |
+
if not message.mentioned:
|
86 |
+
return
|
87 |
+
|
88 |
+
afk_time = readable_time(round(time.time() - afk_data["time"]))
|
89 |
+
caption = f"**{random.choice(afk_quotes)}**\n\n**๐ซ ๐ฑ๐พ๐บ๐๐๐:** {afk_data['reason']}\n**โฐ ๐ ๐ฅ๐ช ๐ฅ๐๐๐:** `{afk_time}`"
|
90 |
+
|
91 |
+
if afk_data["media_type"] == "animation":
|
92 |
+
media = await client.get_messages(Config.LOGGER_ID, afk_data["media"])
|
93 |
+
sent = await client.send_animation(
|
94 |
+
message.chat.id, media.animation.file_id, caption, True
|
95 |
+
)
|
96 |
+
|
97 |
+
elif afk_data["media_type"] in ["audio", "photo", "video", "voice"]:
|
98 |
+
sent = await client.copy_message(
|
99 |
+
message.chat.id,
|
100 |
+
Config.LOGGER_ID,
|
101 |
+
afk_data["media"],
|
102 |
+
caption,
|
103 |
+
reply_to_message_id=message.id,
|
104 |
+
)
|
105 |
+
|
106 |
+
elif afk_data["media_type"] == "sticker":
|
107 |
+
media = await client.get_messages(Config.LOGGER_ID, afk_data["media"])
|
108 |
+
await client.download_media(media, "afk.png")
|
109 |
+
sent = await message.reply_photo("afk.png", caption=caption)
|
110 |
+
os.remove("afk.png")
|
111 |
+
|
112 |
+
else:
|
113 |
+
sent = await message.reply_text(caption)
|
114 |
+
|
115 |
+
link = message.link if message.chat.type in group_only else "No DM Link"
|
116 |
+
|
117 |
+
await hellbot.check_and_log(
|
118 |
+
"afk",
|
119 |
+
f"{message.from_user.mention} mentioned you when you were AFK! \n\n**Link:** {link}",
|
120 |
+
)
|
121 |
+
try:
|
122 |
+
data = get_from_dict(Config.AFK_CACHE, [afk_data["user_id"], message.chat.id])
|
123 |
+
if data:
|
124 |
+
await client.delete_messages(message.chat.id, data)
|
125 |
+
add_to_dict(Config.AFK_CACHE, [afk_data["user_id"], message.chat.id], sent.id)
|
126 |
+
except KeyError:
|
127 |
+
add_to_dict(Config.AFK_CACHE, [afk_data["user_id"], message.chat.id], sent.id)
|
128 |
+
|
129 |
+
|
130 |
+
@custom_handler(filters.outgoing, 2)
|
131 |
+
async def remove_afk(_, message: Message):
|
132 |
+
if await db.is_afk(message.from_user.id):
|
133 |
+
if "afk" in message.text:
|
134 |
+
return
|
135 |
+
|
136 |
+
data = await db.get_afk(message.from_user.id)
|
137 |
+
total_afk_time = readable_time(round(time.time() - data["time"]))
|
138 |
+
|
139 |
+
hell = await message.reply_text(
|
140 |
+
f"๐ซก **๐ก๐บ๐ผ๐ ๐๐ ๐๐๐๐๐๐บ๐
๐๐๐๐
๐ฝ! \n\nโ Was away for:** `{total_afk_time}`"
|
141 |
+
)
|
142 |
+
await message.delete()
|
143 |
+
|
144 |
+
await db.rm_afk(message.from_user.id)
|
145 |
+
await hellbot.check_and_log(
|
146 |
+
"afk",
|
147 |
+
f"Returned from AFK! \n\n**Time:** `{total_afk_time}`\n**Link:** {hell.link}",
|
148 |
+
)
|
149 |
+
|
150 |
+
|
151 |
+
HelpMenu("afk").add(
|
152 |
+
"afk",
|
153 |
+
"<reason>",
|
154 |
+
"Set your status as AFK. When someone mentions' you, the bot will tell them you're currently Offline! You can also use a media by replying to it.",
|
155 |
+
"afk good night!",
|
156 |
+
"To unset afk you can send a message to any chat and it'll automaticslly get disabled! You can use 'afk' in your message to bypass automatic disabling of afk.",
|
157 |
+
).info("Away From Keyboard").done()
|
Hellbot/plugins/user/anime.py
ADDED
@@ -0,0 +1,184 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
from pyrogram.errors import ChatSendMediaForbidden
|
4 |
+
from pyrogram.types import Message
|
5 |
+
|
6 |
+
from Hellbot.core import hellbot
|
7 |
+
from Hellbot.functions.scraping import (
|
8 |
+
get_airing_info,
|
9 |
+
get_anilist_user_info,
|
10 |
+
get_anime_info,
|
11 |
+
get_character_info,
|
12 |
+
get_filler_info,
|
13 |
+
get_manga_info,
|
14 |
+
get_watch_order,
|
15 |
+
)
|
16 |
+
|
17 |
+
from . import HelpMenu, on_message
|
18 |
+
|
19 |
+
|
20 |
+
@on_message("anime", allow_stan=True)
|
21 |
+
async def anime(_, message: Message):
|
22 |
+
if len(message.command) < 2:
|
23 |
+
return await hellbot.delete(message, "Give me an anime name to search!")
|
24 |
+
|
25 |
+
query = await hellbot.input(message)
|
26 |
+
hell = await hellbot.edit(message, "Searching ...")
|
27 |
+
caption, photo = await get_anime_info(query)
|
28 |
+
|
29 |
+
try:
|
30 |
+
await message.reply_photo(photo, caption=caption)
|
31 |
+
await hell.delete()
|
32 |
+
except ChatSendMediaForbidden:
|
33 |
+
await hell.edit(caption, disable_web_page_preview=True)
|
34 |
+
|
35 |
+
if os.path.exists(photo):
|
36 |
+
os.remove(photo)
|
37 |
+
|
38 |
+
|
39 |
+
@on_message("manga", allow_stan=True)
|
40 |
+
async def manga(_, message: Message):
|
41 |
+
if len(message.command) < 2:
|
42 |
+
return await hellbot.delete(message, "Give me a manga name to search!")
|
43 |
+
|
44 |
+
query = await hellbot.input(message)
|
45 |
+
hell = await hellbot.edit(message, "Searching ...")
|
46 |
+
caption, photo = await get_manga_info(query)
|
47 |
+
|
48 |
+
try:
|
49 |
+
await message.reply_photo(photo, caption=caption)
|
50 |
+
await hell.delete()
|
51 |
+
except ChatSendMediaForbidden:
|
52 |
+
await hell.edit(caption, disable_web_page_preview=True)
|
53 |
+
|
54 |
+
if os.path.exists(photo):
|
55 |
+
os.remove(photo)
|
56 |
+
|
57 |
+
|
58 |
+
@on_message("character", allow_stan=True)
|
59 |
+
async def character(_, message: Message):
|
60 |
+
if len(message.command) < 2:
|
61 |
+
return await hellbot.delete(message, "Give me a character name to search!")
|
62 |
+
|
63 |
+
query = await hellbot.input(message)
|
64 |
+
hell = await hellbot.edit(message, "Searching ...")
|
65 |
+
caption, photo = await get_character_info(query)
|
66 |
+
|
67 |
+
try:
|
68 |
+
await message.reply_photo(photo, caption=caption)
|
69 |
+
await hell.delete()
|
70 |
+
except ChatSendMediaForbidden:
|
71 |
+
await hell.edit(caption, disable_web_page_preview=True)
|
72 |
+
|
73 |
+
if os.path.exists(photo):
|
74 |
+
os.remove(photo)
|
75 |
+
|
76 |
+
|
77 |
+
@on_message("airing", allow_stan=True)
|
78 |
+
async def airing(_, message: Message):
|
79 |
+
if len(message.command) < 2:
|
80 |
+
return await hellbot.delete(message, "Give me an anime name to search!")
|
81 |
+
|
82 |
+
query = await hellbot.input(message)
|
83 |
+
hell = await hellbot.edit(message, "Searching ...")
|
84 |
+
caption, photo = await get_airing_info(query)
|
85 |
+
|
86 |
+
try:
|
87 |
+
await message.reply_photo(photo, caption=caption)
|
88 |
+
await hell.delete()
|
89 |
+
except ChatSendMediaForbidden:
|
90 |
+
await hell.edit(caption, disable_web_page_preview=True)
|
91 |
+
|
92 |
+
if os.path.exists(photo):
|
93 |
+
os.remove(photo)
|
94 |
+
|
95 |
+
|
96 |
+
@on_message(["anilistuser", "aniuser"], allow_stan=True)
|
97 |
+
async def anilist_user(_, message: Message):
|
98 |
+
if len(message.command) < 2:
|
99 |
+
return await hellbot.delete(message, "Give me an anilist username to search!")
|
100 |
+
|
101 |
+
query = await hellbot.input(message)
|
102 |
+
hell = await hellbot.edit(message, "Searching ...")
|
103 |
+
caption, photo = await get_anilist_user_info(query)
|
104 |
+
|
105 |
+
try:
|
106 |
+
await message.reply_photo(photo, caption=caption)
|
107 |
+
await hell.delete()
|
108 |
+
except ChatSendMediaForbidden:
|
109 |
+
await hell.edit(caption, disable_web_page_preview=True)
|
110 |
+
|
111 |
+
if os.path.exists(photo):
|
112 |
+
os.remove(photo)
|
113 |
+
|
114 |
+
|
115 |
+
@on_message(["filler", "canon"], allow_stan=True)
|
116 |
+
async def fillers(_, message: Message):
|
117 |
+
if len(message.command) < 2:
|
118 |
+
return await hellbot.delete(message, "Give me an anime name to search!")
|
119 |
+
|
120 |
+
query = await hellbot.input(message)
|
121 |
+
hell = await hellbot.edit(message, "Searching ...")
|
122 |
+
|
123 |
+
caption = await get_filler_info(query)
|
124 |
+
if caption == "":
|
125 |
+
return await hellbot.delete(hell, "No results found!")
|
126 |
+
|
127 |
+
await hell.edit(caption, disable_web_page_preview=True)
|
128 |
+
|
129 |
+
|
130 |
+
@on_message("watchorder", allow_stan=True)
|
131 |
+
async def watch_order(_, message: Message):
|
132 |
+
if len(message.command) < 2:
|
133 |
+
return await hellbot.delete(message, "Give me an anime name to search!")
|
134 |
+
|
135 |
+
query = await hellbot.input(message)
|
136 |
+
hell = await hellbot.edit(message, "Searching ...")
|
137 |
+
|
138 |
+
caption = await get_watch_order(query)
|
139 |
+
if caption == "":
|
140 |
+
return await hellbot.delete(hell, "No results found!")
|
141 |
+
|
142 |
+
await hell.edit(caption, disable_web_page_preview=True)
|
143 |
+
|
144 |
+
|
145 |
+
HelpMenu("anime").add(
|
146 |
+
"anime",
|
147 |
+
"<name>",
|
148 |
+
"Get a detailed information about the mentioned anime.",
|
149 |
+
"anime one piece",
|
150 |
+
).add(
|
151 |
+
"manga",
|
152 |
+
"<name>",
|
153 |
+
"Get a detailed information about the mentioned manga.",
|
154 |
+
"manga one piece",
|
155 |
+
).add(
|
156 |
+
"character",
|
157 |
+
"<name>",
|
158 |
+
"Get a detailed information about the mentioned character.",
|
159 |
+
"character monkey d luffy",
|
160 |
+
).add(
|
161 |
+
"airing",
|
162 |
+
"<name>",
|
163 |
+
"Get a detailed airing information about the mentioned anime.",
|
164 |
+
"airing one piece",
|
165 |
+
).add(
|
166 |
+
"anilistuser",
|
167 |
+
"<username>",
|
168 |
+
"Get a detailed information about the mentioned anilist user.",
|
169 |
+
"anilistuser meizhellboy",
|
170 |
+
"You can also use 'aniuser' as alias",
|
171 |
+
).add(
|
172 |
+
"filler",
|
173 |
+
"<name>",
|
174 |
+
"Get the list of filler/canon episodes about the mentioned anime.",
|
175 |
+
"filler one piece",
|
176 |
+
"You can also use 'canon' as alias",
|
177 |
+
).add(
|
178 |
+
"watchorder",
|
179 |
+
"<name>",
|
180 |
+
"Get the watch order about the mentioned anime.",
|
181 |
+
"watchorder one piece",
|
182 |
+
).info(
|
183 |
+
"Anime Menu"
|
184 |
+
).done()
|
Hellbot/plugins/user/antiflood.py
ADDED
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import asyncio
|
2 |
+
import datetime
|
3 |
+
import time
|
4 |
+
|
5 |
+
from pyrogram import Client, filters
|
6 |
+
from pyrogram.types import ChatPermissions, Message
|
7 |
+
|
8 |
+
from Hellbot.core import Config, Symbols, db
|
9 |
+
from Hellbot.functions.utility import Flood
|
10 |
+
|
11 |
+
from . import HelpMenu, custom_handler, group_only, hellbot, on_message
|
12 |
+
|
13 |
+
|
14 |
+
@on_message("setflood", chat_type=group_only, admin_only=True, allow_stan=True)
|
15 |
+
async def setflood(client: Client, message: Message):
|
16 |
+
count = 5
|
17 |
+
mtime = 0
|
18 |
+
mode = "mute"
|
19 |
+
|
20 |
+
try:
|
21 |
+
time_data = "N/A"
|
22 |
+
if len(message.command) == 2:
|
23 |
+
count = int(message.command[1])
|
24 |
+
elif len(message.command) == 3:
|
25 |
+
count = int(message.command[1])
|
26 |
+
mode = message.command[2]
|
27 |
+
elif len(message.command) >= 4:
|
28 |
+
count = int(message.command[1])
|
29 |
+
mode = message.command[2]
|
30 |
+
time_data = message.command[3]
|
31 |
+
if time_data.endswith(("d", "day", "days")):
|
32 |
+
mtime = int(time_data.split("d")[0].strip()) * 24 * 60 * 60
|
33 |
+
elif time_data.endswith(("h", "hrs", "hour", "hours")):
|
34 |
+
mtime = int(time_data.split("h")[0].strip()) * 60 * 60
|
35 |
+
elif time_data.endswith(("m", "mins", "minute", "minutes")):
|
36 |
+
mtime = int(time_data.split("m")[0].strip()) * 60
|
37 |
+
else:
|
38 |
+
return await hellbot.error(
|
39 |
+
message,
|
40 |
+
"Please pass time in correct format!\n\nExample: 12d or 12h or 12m",
|
41 |
+
)
|
42 |
+
except Exception as e:
|
43 |
+
return await hellbot.error(message, str(e))
|
44 |
+
|
45 |
+
if mode.lower() not in ["mute", "kick", "ban"]:
|
46 |
+
return await hellbot.error(
|
47 |
+
message, "**Invalid mode! Choose one: **\n`mute`, `kick`, `ban`"
|
48 |
+
)
|
49 |
+
|
50 |
+
settings = {
|
51 |
+
"mode": mode,
|
52 |
+
"limit": count,
|
53 |
+
"time": mtime,
|
54 |
+
}
|
55 |
+
|
56 |
+
await db.set_flood((client.me.id, message.chat.id), settings)
|
57 |
+
Flood.updateSettings(client.me.id, message.chat.id, settings)
|
58 |
+
|
59 |
+
if count == 0:
|
60 |
+
return await hellbot.delete(message, "Antiflood disabled!")
|
61 |
+
|
62 |
+
await hellbot.delete(
|
63 |
+
message,
|
64 |
+
f"**Antiflood enabled!**\n\n**{Symbols.triangle_right} Mode:** `{mode}`\n**{Symbols.triangle_right} Limit:** `{count}`\n**{Symbols.triangle_right} Time:** `{time_data}`",
|
65 |
+
20,
|
66 |
+
)
|
67 |
+
|
68 |
+
|
69 |
+
@custom_handler(
|
70 |
+
filters.all
|
71 |
+
& filters.group
|
72 |
+
& filters.incoming
|
73 |
+
& ~filters.bot
|
74 |
+
& ~Config.AUTH_USERS
|
75 |
+
& ~filters.me
|
76 |
+
& ~filters.service
|
77 |
+
)
|
78 |
+
async def antiflood(client: Client, message: Message):
|
79 |
+
mode, mtime, limit = Flood.getSettings(client.me.id, message.chat.id)
|
80 |
+
|
81 |
+
if limit == 0:
|
82 |
+
return
|
83 |
+
if not Flood.check_client_chat(client.me.id, message.chat.id):
|
84 |
+
return
|
85 |
+
|
86 |
+
last_user, count = Flood.getLastUser(client.me.id, message.chat.id)
|
87 |
+
|
88 |
+
if last_user == message.from_user.id:
|
89 |
+
if (count + 1) >= limit:
|
90 |
+
template = (
|
91 |
+
"**๐คซ ๐ ๐๐๐๐ฅ๐
๐๐๐ฝ {mode}!!** \n\n"
|
92 |
+
"**{symbol} ๐ด๐๐พ๐:** `{mention}`\n"
|
93 |
+
"**{symbol} ๐ณ๐๐
๐
๐ฃ๐บ๐๐พ:** `๐๏ธ {till_date}`\n"
|
94 |
+
)
|
95 |
+
hell = await message.reply_text("Flood Detected!")
|
96 |
+
|
97 |
+
if mode == "mute":
|
98 |
+
permission = ChatPermissions(can_send_messages=False)
|
99 |
+
until_date = datetime.datetime.fromtimestamp(time.time() + mtime)
|
100 |
+
try:
|
101 |
+
await client.restrict_chat_member(
|
102 |
+
message.chat.id,
|
103 |
+
message.from_user.id,
|
104 |
+
permission,
|
105 |
+
until_date,
|
106 |
+
)
|
107 |
+
except Exception as e:
|
108 |
+
return await hellbot.error(
|
109 |
+
hell, f"__Error in Antiflood while trying to mute!__\n{str(e)}"
|
110 |
+
)
|
111 |
+
|
112 |
+
Flood.updateFlood(
|
113 |
+
client.me.id, message.chat.id, message.from_user.id, 0
|
114 |
+
)
|
115 |
+
till_date = "Forever" if mtime == 0 else until_date.ctime()
|
116 |
+
|
117 |
+
return await hell.edit(
|
118 |
+
template.format(
|
119 |
+
mode=mode.title(),
|
120 |
+
symbol=Symbols.triangle_right,
|
121 |
+
mention=message.from_user.mention,
|
122 |
+
till_date=till_date,
|
123 |
+
)
|
124 |
+
)
|
125 |
+
|
126 |
+
elif mode == "kick":
|
127 |
+
try:
|
128 |
+
await client.ban_chat_member(message.chat.id, message.from_user.id)
|
129 |
+
except Exception as e:
|
130 |
+
return await hellbot.error(
|
131 |
+
hell, f"__Error in Antiflood while trying to kick!__\n{str(e)}"
|
132 |
+
)
|
133 |
+
|
134 |
+
await hell.edit(
|
135 |
+
template.format(
|
136 |
+
mode=mode.title(),
|
137 |
+
symbol=Symbols.triangle_right,
|
138 |
+
mention=message.from_user.mention,
|
139 |
+
till_date="Kicked Users can join back after 5 seconds!",
|
140 |
+
)
|
141 |
+
)
|
142 |
+
Flood.updateFlood(
|
143 |
+
client.me.id, message.chat.id, message.from_user.id, 0
|
144 |
+
)
|
145 |
+
await asyncio.sleep(5)
|
146 |
+
await client.unban_chat_member(message.chat.id, message.from_user.id)
|
147 |
+
return
|
148 |
+
|
149 |
+
elif mode == "ban":
|
150 |
+
until_date = datetime.datetime.fromtimestamp(time.time() + mtime)
|
151 |
+
try:
|
152 |
+
await client.ban_chat_member(
|
153 |
+
message.chat.id,
|
154 |
+
message.from_user.id,
|
155 |
+
until_date,
|
156 |
+
)
|
157 |
+
except Exception as e:
|
158 |
+
return await hellbot.error(
|
159 |
+
hell, f"__Error in Antiflood while trying to ban!__\n{str(e)}"
|
160 |
+
)
|
161 |
+
|
162 |
+
Flood.updateFlood(
|
163 |
+
client.me.id, message.chat.id, message.from_user.id, 0
|
164 |
+
)
|
165 |
+
till_date = "Forever" if mtime == 0 else until_date.ctime()
|
166 |
+
|
167 |
+
return await hell.edit(
|
168 |
+
template.format(
|
169 |
+
mode=mode.title(),
|
170 |
+
symbol=Symbols.triangle_right,
|
171 |
+
mention=message.from_user.mention,
|
172 |
+
till_date=till_date,
|
173 |
+
)
|
174 |
+
)
|
175 |
+
else:
|
176 |
+
return
|
177 |
+
else:
|
178 |
+
count += 1
|
179 |
+
Flood.updateFlood(
|
180 |
+
client.me.id, message.chat.id, message.from_user.id, count
|
181 |
+
)
|
182 |
+
return
|
183 |
+
else:
|
184 |
+
Flood.updateFlood(client.me.id, message.chat.id, message.from_user.id, 1)
|
185 |
+
|
186 |
+
|
187 |
+
HelpMenu("antiflood").add(
|
188 |
+
"setflood",
|
189 |
+
"<limit> <mode> <time>",
|
190 |
+
"Set antiflood in the chat! All arguments are optional, bydefault limit is 5 and mode is permanent mute.",
|
191 |
+
"setflood 10 ban 1d",
|
192 |
+
"Mode can be mute, kick or ban. Time can be xd (days), xh (hours) or xm (minutes) where x is number.",
|
193 |
+
).add(
|
194 |
+
"setflood 0",
|
195 |
+
None,
|
196 |
+
"Disable antiflood in the chat!",
|
197 |
+
"setflood 0",
|
198 |
+
).info(
|
199 |
+
"Control Flood in the chat!"
|
200 |
+
).done()
|
Hellbot/plugins/user/archiver.py
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import time
|
3 |
+
import zipfile
|
4 |
+
|
5 |
+
from pyrogram.types import Message
|
6 |
+
|
7 |
+
from Hellbot.functions.formatter import readable_time
|
8 |
+
from Hellbot.functions.tools import get_files_from_directory, progress
|
9 |
+
|
10 |
+
from . import Config, HelpMenu, hellbot, on_message
|
11 |
+
|
12 |
+
|
13 |
+
@on_message("zip", allow_stan=True)
|
14 |
+
async def zip_files(_, message: Message):
|
15 |
+
if not message.reply_to_message:
|
16 |
+
return await hellbot.delete(message, "Reply to a message to zip it.")
|
17 |
+
|
18 |
+
media = message.reply_to_message.media
|
19 |
+
if not media:
|
20 |
+
return await hellbot.delete(message, "Reply to a media message to zip it.")
|
21 |
+
|
22 |
+
hell = await hellbot.edit(message, "`Zipping...`")
|
23 |
+
start = time.time()
|
24 |
+
download_path = await message.reply_to_message.download(
|
25 |
+
f"{Config.TEMP_DIR}temp_{round(time.time())}",
|
26 |
+
progress=progress,
|
27 |
+
progress_args=(hell, start, "๐ฆ Zipping"),
|
28 |
+
)
|
29 |
+
|
30 |
+
zip_path = Config.TEMP_DIR + f"zipped_{int(time.time())}.zip"
|
31 |
+
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zip_file:
|
32 |
+
zip_file.write(download_path)
|
33 |
+
|
34 |
+
await hellbot.delete(hell, "Zipped Successfully.")
|
35 |
+
await message.reply_document(
|
36 |
+
zip_path,
|
37 |
+
caption=f"**Zipped in {readable_time(time.time() - start)}.**",
|
38 |
+
progress=progress,
|
39 |
+
progress_args=(hell, start, "โฌ๏ธ Uploading"),
|
40 |
+
)
|
41 |
+
|
42 |
+
os.remove(zip_path)
|
43 |
+
os.remove(download_path)
|
44 |
+
|
45 |
+
|
46 |
+
@on_message("unzip", allow_stan=True)
|
47 |
+
async def unzip_file(_, message: Message):
|
48 |
+
if not message.reply_to_message:
|
49 |
+
return await hellbot.delete(message, "Reply to a message to unzip it.")
|
50 |
+
|
51 |
+
media = message.reply_to_message.media
|
52 |
+
if not media:
|
53 |
+
return await hellbot.delete(message, "Reply to a media message to unzip it.")
|
54 |
+
|
55 |
+
hell = await hellbot.edit(message, "`Unzipping...`")
|
56 |
+
start = time.time()
|
57 |
+
download_path = await message.reply_to_message.download(
|
58 |
+
f"{Config.TEMP_DIR}temp_{round(time.time())}",
|
59 |
+
progress=progress,
|
60 |
+
progress_args=(hell, start, "๐ฆ Unzipping"),
|
61 |
+
)
|
62 |
+
|
63 |
+
with zipfile.ZipFile(download_path, "r") as zip_file:
|
64 |
+
if not os.path.isdir(Config.TEMP_DIR + "unzipped/"):
|
65 |
+
os.mkdir(Config.TEMP_DIR + "unzipped/")
|
66 |
+
zip_file.extractall(Config.TEMP_DIR + "unzipped/")
|
67 |
+
|
68 |
+
await hellbot.delete(hell, "Unzipped Successfully.")
|
69 |
+
files = await get_files_from_directory(Config.TEMP_DIR + "unzipped/")
|
70 |
+
|
71 |
+
for file in files:
|
72 |
+
if os.path.exists(file):
|
73 |
+
try:
|
74 |
+
await message.reply_document(
|
75 |
+
file,
|
76 |
+
caption=f"**Unzipped {os.path.basename(file)}.**",
|
77 |
+
force_document=True,
|
78 |
+
progress=progress,
|
79 |
+
progress_args=(hell, start, "โฌ๏ธ Uploading"),
|
80 |
+
)
|
81 |
+
except Exception as e:
|
82 |
+
await message.reply_text(f"**{file}:** `{e}`")
|
83 |
+
continue
|
84 |
+
os.remove(file)
|
85 |
+
|
86 |
+
os.remove(download_path)
|
87 |
+
|
88 |
+
|
89 |
+
HelpMenu("archiver").add(
|
90 |
+
"zip",
|
91 |
+
"<reply to a media>",
|
92 |
+
"Zip the replied media and upload it in the chat.",
|
93 |
+
).add(
|
94 |
+
"unzip",
|
95 |
+
"<reply to a zip file>",
|
96 |
+
"Unzip the replied zip file and upload it in the chat.",
|
97 |
+
).info(
|
98 |
+
"Manage Archives"
|
99 |
+
).done()
|
Hellbot/plugins/user/autopost.py
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram import Client, filters
|
2 |
+
from pyrogram.types import Message
|
3 |
+
|
4 |
+
from Hellbot.core import Symbols
|
5 |
+
|
6 |
+
from . import HelpMenu, custom_handler, db, group_n_channel, hellbot, on_message
|
7 |
+
|
8 |
+
|
9 |
+
@on_message("autopost", chat_type=group_n_channel, allow_stan=True)
|
10 |
+
async def autopost(client: Client, message: Message):
|
11 |
+
if len(message.command) != 2:
|
12 |
+
return await hellbot.delete(
|
13 |
+
message, "Wrong usage of command.\nCheck help menu for more info."
|
14 |
+
)
|
15 |
+
|
16 |
+
hell = await hellbot.edit(message, "Starting Autopost in this group/channel...")
|
17 |
+
|
18 |
+
post_from = message.command[1]
|
19 |
+
_chat = await client.get_chat(post_from)
|
20 |
+
|
21 |
+
if not _chat:
|
22 |
+
return await hellbot.delete(hell, "Invalid chat/channel id.")
|
23 |
+
|
24 |
+
if _chat.type not in group_n_channel:
|
25 |
+
return await hellbot.delete(
|
26 |
+
hell, "You can only autopost in groups and channels."
|
27 |
+
)
|
28 |
+
|
29 |
+
if _chat.id == message.chat.id:
|
30 |
+
return await hellbot.delete(
|
31 |
+
hell, "You can't autopost in the same group/channel."
|
32 |
+
)
|
33 |
+
|
34 |
+
if _chat.id in await db.is_autopost(client.me.id, _chat.id, message.chat.id):
|
35 |
+
return await hellbot.delete(
|
36 |
+
hell, "This group/channel is already in autopost list."
|
37 |
+
)
|
38 |
+
|
39 |
+
await db.set_autopost(client.me.id, _chat.id, message.chat.id)
|
40 |
+
|
41 |
+
await hellbot.delete(
|
42 |
+
hell, f"Autopost started from {_chat.title} to {message.chat.title}."
|
43 |
+
)
|
44 |
+
await hellbot.check_and_log(
|
45 |
+
"autopost start",
|
46 |
+
f"**AutoPost From:** {_chat.title} \n**AutoPost To:** {message.chat.title}\n**AutoPost By:** {client.me.mention}",
|
47 |
+
)
|
48 |
+
|
49 |
+
|
50 |
+
@on_message("stopautopost", chat_type=group_n_channel, allow_stan=True)
|
51 |
+
async def stop_autopost(client: Client, message: Message):
|
52 |
+
if len(message.command) != 2:
|
53 |
+
return await hellbot.delete(
|
54 |
+
message, "Wrong usage of command.\nCheck help menu for more info."
|
55 |
+
)
|
56 |
+
|
57 |
+
hell = await hellbot.edit(message, "Stopping Autopost in this group/channel...")
|
58 |
+
|
59 |
+
post_from = message.command[1]
|
60 |
+
_chat = await client.get_chat(post_from)
|
61 |
+
|
62 |
+
if not _chat:
|
63 |
+
return await hellbot.delete(hell, "Invalid chat/channel id.")
|
64 |
+
|
65 |
+
if _chat.type not in group_n_channel:
|
66 |
+
return await hellbot.delete(
|
67 |
+
hell, "You can only autopost in groups and channels."
|
68 |
+
)
|
69 |
+
|
70 |
+
if _chat.id not in await db.is_autopost(client.me.id, _chat.id, message.chat.id):
|
71 |
+
return await hellbot.delete(hell, "This group/channel is not in autopost list.")
|
72 |
+
|
73 |
+
await db.rm_autopost(client.me.id, _chat.id, message.chat.id)
|
74 |
+
|
75 |
+
await hellbot.delete(
|
76 |
+
hell, f"Autopost stopped from {_chat.title} to {message.chat.title}."
|
77 |
+
)
|
78 |
+
await hellbot.check_and_log(
|
79 |
+
"autopost stop",
|
80 |
+
f"**AutoPost From:** {_chat.title} \n**AutoPost To:** {message.chat.title}\n**AutoPost By:** {client.me.mention}",
|
81 |
+
)
|
82 |
+
|
83 |
+
|
84 |
+
@on_message("autoposts", chat_type=group_n_channel, allow_stan=True)
|
85 |
+
async def autoposts(client: Client, message: Message):
|
86 |
+
hell = await hellbot.edit(message, "Getting autopost list...")
|
87 |
+
|
88 |
+
data = await db.get_all_autoposts(client.me.id)
|
89 |
+
if not data:
|
90 |
+
return await hellbot.delete(hell, "No autoposts found.")
|
91 |
+
|
92 |
+
text = f"**๐ ๐ผ๐๐๐๐พ ๐ ๐๐๐๐๐๐๐๐ ๐ฟ๐๐: {client.me.mention}**\n\n"
|
93 |
+
for i in data:
|
94 |
+
from_chat = await client.get_chat(i["from_channel"])
|
95 |
+
to_chat = await client.get_chat(i["to_channel"])
|
96 |
+
|
97 |
+
from_chat_name = (
|
98 |
+
f"{from_chat.title} [{from_chat.id}]" if from_chat else i["from_channel"]
|
99 |
+
)
|
100 |
+
to_chat_name = f"{to_chat.title} [{to_chat.id}]" if to_chat else i["to_channel"]
|
101 |
+
|
102 |
+
text += f" {Symbols.anchor} **From:** {from_chat_name}\n"
|
103 |
+
text += f" {Symbols.anchor} **To:** {to_chat_name}\n"
|
104 |
+
text += f" {Symbols.anchor} **Date:** {i['date']}\n\n"
|
105 |
+
|
106 |
+
await hellbot.edit(hell, text)
|
107 |
+
|
108 |
+
|
109 |
+
@custom_handler(filters.incoming & filters.group & filters.channel & ~filters.service)
|
110 |
+
async def handle_autopost(client: Client, message: Message):
|
111 |
+
if not await db.is_autopost(client.me.id, message.chat.id):
|
112 |
+
return
|
113 |
+
|
114 |
+
data = await db.get_autopost(client.me.id, message.chat.id)
|
115 |
+
if not data:
|
116 |
+
return
|
117 |
+
|
118 |
+
from_chat = await client.get_chat(data["from_channel"])
|
119 |
+
if not from_chat:
|
120 |
+
return
|
121 |
+
|
122 |
+
if message.chat.id != data["to_channel"]:
|
123 |
+
return
|
124 |
+
|
125 |
+
await message.copy(int(data["to_channel"]))
|
126 |
+
|
127 |
+
|
128 |
+
HelpMenu("autopost").add(
|
129 |
+
"autopost",
|
130 |
+
"<channel id>",
|
131 |
+
"Start autoposting in current group/channel from the mentioned chatid/username of channel.",
|
132 |
+
"autopost @Its_HellBot",
|
133 |
+
"This module will post all incoming post from the target channel to the current chat without forward tag!",
|
134 |
+
).add(
|
135 |
+
"stopautopost",
|
136 |
+
"<channel id>",
|
137 |
+
"Stops autoposting in current chroup/channel from the mentioned chatid/username of channel.",
|
138 |
+
"stopautopost @Its_HellBot",
|
139 |
+
).add(
|
140 |
+
"autoposts", None, "Get all active autoposts!", "autoposts"
|
141 |
+
).info(
|
142 |
+
"AutoPost Module"
|
143 |
+
).done()
|
Hellbot/plugins/user/blacklist.py
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import re
|
2 |
+
|
3 |
+
from pyrogram import Client, filters
|
4 |
+
from pyrogram.types import Message
|
5 |
+
|
6 |
+
from Hellbot.core import Config, Symbols
|
7 |
+
from Hellbot.functions.utility import BList
|
8 |
+
|
9 |
+
from . import HelpMenu, custom_handler, db, hellbot, on_message
|
10 |
+
|
11 |
+
|
12 |
+
@on_message("blacklist", admin_only=True, allow_stan=True)
|
13 |
+
async def blacklist(client: Client, message: Message):
|
14 |
+
if len(message.command) < 2:
|
15 |
+
return await hellbot.delete(message, "Give me something to blacklist.")
|
16 |
+
|
17 |
+
text = await hellbot.input(message)
|
18 |
+
|
19 |
+
if await db.is_blacklist(client.me.id, message.chat.id, text):
|
20 |
+
return await hellbot.delete(message, f"**Already blacklisted** `{text}`")
|
21 |
+
|
22 |
+
await BList.addBlacklist(client.me.id, message.chat.id, text)
|
23 |
+
await hellbot.delete(message, f"**Blacklisted:** `{text}`")
|
24 |
+
|
25 |
+
|
26 |
+
@on_message("unblacklist", admin_only=True, allow_stan=True)
|
27 |
+
async def unblacklist(client: Client, message: Message):
|
28 |
+
if len(message.command) < 2:
|
29 |
+
return await hellbot.delete(message, "Give me something to unblacklist.")
|
30 |
+
|
31 |
+
text = await hellbot.input(message)
|
32 |
+
|
33 |
+
if not await db.is_blacklist(client.me.id, message.chat.id, text):
|
34 |
+
return await hellbot.delete(message, f"`{text}` does not exist in blacklist.")
|
35 |
+
|
36 |
+
await BList.rmBlacklist(client.me.id, message.chat.id, text)
|
37 |
+
await hellbot.delete(message, f"**Unblacklisted:** `{text}`")
|
38 |
+
|
39 |
+
|
40 |
+
@on_message("blacklists", admin_only=True, allow_stan=True)
|
41 |
+
async def blacklists(client: Client, message: Message):
|
42 |
+
blacklists = await db.get_all_blacklists(client.me.id, message.chat.id)
|
43 |
+
|
44 |
+
if not blacklists:
|
45 |
+
return await hellbot.delete(message, "No blacklists found.")
|
46 |
+
|
47 |
+
text = f"**{Symbols.bullet} ๐ก๐
๐บ๐ผ๐๐
๐๐๐๐ ๐๐ {message.chat.title}:**\n\n"
|
48 |
+
for i in blacklists:
|
49 |
+
text += f" {Symbols.anchor} `{i}`\n"
|
50 |
+
|
51 |
+
await hellbot.edit(message, text)
|
52 |
+
|
53 |
+
|
54 |
+
@custom_handler(filters.text & filters.incoming & ~Config.AUTH_USERS & ~filters.service)
|
55 |
+
async def handle_blacklists(client: Client, message: Message):
|
56 |
+
if BList.check_client_chat(client.me.id, message.chat.id):
|
57 |
+
blacklists = BList.getBlacklists(client.me.id, message.chat.id)
|
58 |
+
for blacklist in blacklists:
|
59 |
+
pattern = r"( |^|[^\w])" + re.escape(blacklist) + r"( |$|[^\w])"
|
60 |
+
if re.search(pattern, message.text, flags=re.IGNORECASE):
|
61 |
+
try:
|
62 |
+
await message.delete()
|
63 |
+
except Exception:
|
64 |
+
await BList.rmBlacklist(client.me.id, message.chat.id, blacklist)
|
65 |
+
|
66 |
+
|
67 |
+
HelpMenu("blacklist").add(
|
68 |
+
"blacklist",
|
69 |
+
"<text>",
|
70 |
+
"Add the text to blacklist. If the text is sent in the chat it will be deleted.",
|
71 |
+
"blacklist hello",
|
72 |
+
).add(
|
73 |
+
"unblacklist", "<text>", "Remove the text from blacklist.", "unblacklist hello"
|
74 |
+
).add(
|
75 |
+
"blacklists", None, "List all the blacklisted words in the chat.", "blacklists"
|
76 |
+
).info(
|
77 |
+
"Blacklist Module"
|
78 |
+
).done()
|
Hellbot/plugins/user/bot.py
ADDED
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import random
|
3 |
+
import time
|
4 |
+
|
5 |
+
from pyrogram import Client
|
6 |
+
from pyrogram.types import Message
|
7 |
+
|
8 |
+
from Hellbot import START_TIME
|
9 |
+
from Hellbot.core import ENV
|
10 |
+
from Hellbot.functions.formatter import readable_time
|
11 |
+
from Hellbot.functions.images import generate_alive_image
|
12 |
+
from Hellbot.functions.templates import alive_template, ping_template
|
13 |
+
|
14 |
+
from . import Config, HelpMenu, db, hellbot, on_message
|
15 |
+
|
16 |
+
|
17 |
+
@on_message("alive", allow_stan=True)
|
18 |
+
async def alive(client: Client, message: Message):
|
19 |
+
hell = await hellbot.edit(message, "Processing ...")
|
20 |
+
|
21 |
+
img = await db.get_env(ENV.alive_pic)
|
22 |
+
if not img:
|
23 |
+
if message.from_user.photo:
|
24 |
+
user_pfp = await client.download_media(message.from_user.photo.big_file_id)
|
25 |
+
del_path = True
|
26 |
+
else:
|
27 |
+
user_pfp = "./Hellbot/resources/images/hellbot_logo.png"
|
28 |
+
del_path = False
|
29 |
+
img = [
|
30 |
+
generate_alive_image(
|
31 |
+
message.from_user.first_name, user_pfp, del_path, Config.FONT_PATH
|
32 |
+
)
|
33 |
+
]
|
34 |
+
else:
|
35 |
+
img = img.split(" ")
|
36 |
+
|
37 |
+
img = random.choice(img)
|
38 |
+
uptime = readable_time(time.time() - START_TIME)
|
39 |
+
caption = await alive_template(client.me.first_name, uptime)
|
40 |
+
|
41 |
+
if img.endswith(".mp4"):
|
42 |
+
await message.reply_video(img, caption=caption)
|
43 |
+
else:
|
44 |
+
await message.reply_photo(img, caption=caption)
|
45 |
+
await hell.delete()
|
46 |
+
|
47 |
+
try:
|
48 |
+
os.remove(img)
|
49 |
+
except:
|
50 |
+
pass
|
51 |
+
|
52 |
+
|
53 |
+
@on_message("ping", allow_stan=True)
|
54 |
+
async def ping(client: Client, message: Message):
|
55 |
+
start_time = time.time()
|
56 |
+
hell = await hellbot.edit(message, "**Pong ~**")
|
57 |
+
uptime = readable_time(time.time() - START_TIME)
|
58 |
+
img = await db.get_env(ENV.ping_pic)
|
59 |
+
end_time = time.time()
|
60 |
+
speed = end_time - start_time
|
61 |
+
caption = await ping_template(round(speed, 3), uptime, client.me.mention)
|
62 |
+
if img:
|
63 |
+
img = random.choice(img.split(" "))
|
64 |
+
if img.endswith(".mp4"):
|
65 |
+
await message.reply_video(
|
66 |
+
img,
|
67 |
+
caption=caption,
|
68 |
+
)
|
69 |
+
else:
|
70 |
+
await message.reply_photo(
|
71 |
+
img,
|
72 |
+
caption=caption,
|
73 |
+
)
|
74 |
+
await hell.delete()
|
75 |
+
return
|
76 |
+
await hellbot.edit(hell, caption, no_link_preview=True)
|
77 |
+
|
78 |
+
|
79 |
+
@on_message("history", allow_stan=True)
|
80 |
+
async def history(client: Client, message: Message):
|
81 |
+
if not message.reply_to_message:
|
82 |
+
if len(message.command) < 2:
|
83 |
+
return await hellbot.delete(
|
84 |
+
message, "Either reply to an user or give me a username to get history."
|
85 |
+
)
|
86 |
+
try:
|
87 |
+
user = await client.get_users(message.command[1])
|
88 |
+
except Exception as e:
|
89 |
+
return await hellbot.error(message, f"`{str(e)}`")
|
90 |
+
else:
|
91 |
+
user = message.reply_to_message.from_user
|
92 |
+
|
93 |
+
hell = await hellbot.edit(message, "Processing ...")
|
94 |
+
|
95 |
+
try:
|
96 |
+
response = await client.ask("@SangMata_BOT", f"{user.id}", timeout=60)
|
97 |
+
except Exception as e:
|
98 |
+
return await hellbot.error(hell, f"`{str(e)}`")
|
99 |
+
|
100 |
+
if "you have used up your quota for today" in response.text:
|
101 |
+
return await hellbot.delete(
|
102 |
+
hell,
|
103 |
+
f"Your quota of using SangMata Bot is over. Wait till 00:00 UTC before using it again.",
|
104 |
+
)
|
105 |
+
|
106 |
+
try:
|
107 |
+
await response.delete()
|
108 |
+
await response.request.delete()
|
109 |
+
except:
|
110 |
+
pass
|
111 |
+
|
112 |
+
await hellbot.edit(hell, response.text)
|
113 |
+
|
114 |
+
|
115 |
+
@on_message("template", allow_stan=True)
|
116 |
+
async def template_example(_, message: Message):
|
117 |
+
variable_names = list(Config.TEMPLATES.keys())
|
118 |
+
if len(message.command) < 2:
|
119 |
+
return await hellbot.delete(
|
120 |
+
message,
|
121 |
+
f"__Give a template name to get template example.__\n\n**Available Templates:**\n`{'`, `'.join(variable_names)}`",
|
122 |
+
30,
|
123 |
+
)
|
124 |
+
|
125 |
+
if message.command[1].upper() not in variable_names:
|
126 |
+
return await hellbot.delete(
|
127 |
+
message,
|
128 |
+
f"__Invalid template name:__ `{message.command[1].upper()}`\n\n**Available Templates:**\n`{'`, `'.join(variable_names)}`",
|
129 |
+
30,
|
130 |
+
)
|
131 |
+
|
132 |
+
await hellbot.edit(
|
133 |
+
message,
|
134 |
+
f"**{message.command[1].upper()} Template Example:**\n\n```{Config.TEMPLATES[message.command[1].upper()]}```"
|
135 |
+
)
|
136 |
+
|
137 |
+
|
138 |
+
HelpMenu("bot").add(
|
139 |
+
"alive",
|
140 |
+
None,
|
141 |
+
"Get the alive message of the bot.",
|
142 |
+
"alive",
|
143 |
+
"You can also customize alive message with suitable variables for it.",
|
144 |
+
).add(
|
145 |
+
"ping",
|
146 |
+
None,
|
147 |
+
"Check the ping speed and uptime of bot.",
|
148 |
+
"ping",
|
149 |
+
"You can also customize ping message by adding a media to it.",
|
150 |
+
).add(
|
151 |
+
"history",
|
152 |
+
"<reply to user>/<username/id>",
|
153 |
+
"Get the username, name history of an user.",
|
154 |
+
"history @ForGo10_God",
|
155 |
+
"This command uses SangMata Bot to get the history.",
|
156 |
+
).add(
|
157 |
+
"template",
|
158 |
+
"<template name>",
|
159 |
+
"Get the example of a template.",
|
160 |
+
"template alive_templates",
|
161 |
+
"This command is used to get the example of a template and a list of customisable templates.",
|
162 |
+
).info(
|
163 |
+
"Alive Menu"
|
164 |
+
).done()
|
Hellbot/plugins/user/carbon.py
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import asyncio
|
2 |
+
import os
|
3 |
+
|
4 |
+
from pyrogram.types import Message
|
5 |
+
|
6 |
+
from Hellbot.functions.driver import Driver
|
7 |
+
|
8 |
+
from . import HelpMenu, hellbot, on_message
|
9 |
+
|
10 |
+
|
11 |
+
@on_message("carbon", allow_stan=True)
|
12 |
+
async def carbon(_, message: Message):
|
13 |
+
if len(message.command) < 2:
|
14 |
+
return await hellbot.delete(message, "Give me some code to make carbon.")
|
15 |
+
|
16 |
+
code = await hellbot.input(message)
|
17 |
+
hell = await hellbot.edit(message, "**[ 50% ]** __Making carbon...__")
|
18 |
+
|
19 |
+
driver, resp = Driver.get()
|
20 |
+
if not driver:
|
21 |
+
return await hellbot.error(message, resp)
|
22 |
+
|
23 |
+
await hell.edit("**[ 75% ]** __Making carbon...__")
|
24 |
+
image = await Driver.generate_carbon(driver, code)
|
25 |
+
await asyncio.sleep(4)
|
26 |
+
|
27 |
+
await hell.edit("**[ 100% ]** __Uploading carbon...__")
|
28 |
+
Driver.close(driver)
|
29 |
+
|
30 |
+
await hell.reply_photo(image, caption=f"**๐ข๐บ๐๐ป๐๐๐พ๐ฝ:**\n`{code}`")
|
31 |
+
await hell.delete()
|
32 |
+
os.remove(image)
|
33 |
+
|
34 |
+
|
35 |
+
@on_message("karbon", allow_stan=True)
|
36 |
+
async def karbon(_, message: Message):
|
37 |
+
if len(message.command) < 2:
|
38 |
+
return await hellbot.delete(message, "Give me some code to make karbon.")
|
39 |
+
|
40 |
+
code = await hellbot.input(message)
|
41 |
+
hell = await hellbot.edit(message, "**[ 50% ]** __Making karbon...__")
|
42 |
+
|
43 |
+
driver, resp = Driver.get()
|
44 |
+
if not driver:
|
45 |
+
return await hellbot.error(message, resp)
|
46 |
+
|
47 |
+
await hell.edit("**[ 75% ]** __Making karbon...__")
|
48 |
+
image = await Driver.generate_carbon(driver, code, True)
|
49 |
+
await asyncio.sleep(4)
|
50 |
+
|
51 |
+
await hell.edit("**[ 100% ]** __Uploading karbon...__")
|
52 |
+
Driver.close(driver)
|
53 |
+
|
54 |
+
await hell.reply_photo(image, caption=f"**๐ข๐บ๐๐ป๐๐๐พ๐ฝ:**\n`{code}`")
|
55 |
+
await hell.delete()
|
56 |
+
os.remove(image)
|
57 |
+
|
58 |
+
|
59 |
+
HelpMenu("carbon").add(
|
60 |
+
"carbon",
|
61 |
+
"<code snippet>",
|
62 |
+
"Makes carbon of given code snippet.",
|
63 |
+
"carbon print('Hello World!')",
|
64 |
+
"The style is fixed and cannot be changed.",
|
65 |
+
).add(
|
66 |
+
"karbon",
|
67 |
+
"<code snippet>",
|
68 |
+
"Makes carbon of given code snippet.",
|
69 |
+
"karbon print('Hello World!')",
|
70 |
+
"The style is randomly choosed.",
|
71 |
+
).info(
|
72 |
+
"Carbon is a code snippet sharing service. You can make carbon of your code and share it with others."
|
73 |
+
).done()
|
Hellbot/plugins/user/climate.py
ADDED
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram.types import Message
|
2 |
+
|
3 |
+
from Hellbot.core import ENV
|
4 |
+
from Hellbot.functions.driver import Climate
|
5 |
+
from Hellbot.functions.formatter import subscript, superscript
|
6 |
+
from Hellbot.functions.templates import airpollution_templates, climate_templates
|
7 |
+
|
8 |
+
from . import HelpMenu, db, hellbot, on_message
|
9 |
+
|
10 |
+
|
11 |
+
@on_message("climate", allow_stan=True)
|
12 |
+
async def climate(_, message: Message):
|
13 |
+
if len(message.command) < 2:
|
14 |
+
city = "Delhi"
|
15 |
+
else:
|
16 |
+
city = await hellbot.input(message)
|
17 |
+
|
18 |
+
hell = await hellbot.edit(message, f"**Fetching climate data for `{city}`**")
|
19 |
+
|
20 |
+
apiKey = await db.get_env(ENV.climate_api)
|
21 |
+
if not apiKey:
|
22 |
+
return await hellbot.delete(
|
23 |
+
hell, f"**Climate API not found!** Setup `{ENV.climate_api}` first."
|
24 |
+
)
|
25 |
+
|
26 |
+
data = await Climate.fetchWeather(city, apiKey)
|
27 |
+
if not data:
|
28 |
+
return await hellbot.delete(hell, f"**Climate data not found for `{city}`**")
|
29 |
+
|
30 |
+
city_name = data["name"]
|
31 |
+
country = Climate.getCountry(data["sys"]["country"])
|
32 |
+
weather = data["weather"][0]["main"]
|
33 |
+
timezone = Climate.getCountryTimezone(data["sys"]["country"])
|
34 |
+
sunrise = await Climate.getTime(data["sys"]["sunrise"])
|
35 |
+
sunset = await Climate.getTime(data["sys"]["sunset"])
|
36 |
+
wind = Climate.getWindData(data["wind"]["speed"], data["wind"]["deg"])
|
37 |
+
temperature = data["main"]["temp"]
|
38 |
+
feels_like = data["main"]["feels_like"]
|
39 |
+
temp_min = data["main"]["temp_min"]
|
40 |
+
temp_max = data["main"]["temp_max"]
|
41 |
+
pressure = data["main"]["pressure"]
|
42 |
+
humidity = data["main"]["humidity"]
|
43 |
+
visibility = data["visibility"]
|
44 |
+
clouds = data["clouds"]["all"]
|
45 |
+
|
46 |
+
await hell.edit(
|
47 |
+
await climate_templates(
|
48 |
+
city_name=city_name,
|
49 |
+
country=country,
|
50 |
+
weather=weather,
|
51 |
+
timezone=timezone,
|
52 |
+
sunrise=sunrise,
|
53 |
+
sunset=sunset,
|
54 |
+
wind=wind,
|
55 |
+
temperature=temperature,
|
56 |
+
feels_like=feels_like,
|
57 |
+
temp_min=temp_min,
|
58 |
+
temp_max=temp_max,
|
59 |
+
pressure=pressure,
|
60 |
+
humidity=humidity,
|
61 |
+
visibility=visibility,
|
62 |
+
clouds=clouds,
|
63 |
+
),
|
64 |
+
disable_web_page_preview=True,
|
65 |
+
)
|
66 |
+
|
67 |
+
|
68 |
+
@on_message("airpollution", allow_stan=True)
|
69 |
+
async def airpollution(_, message: Message):
|
70 |
+
if len(message.command) < 2:
|
71 |
+
city = "Delhi"
|
72 |
+
else:
|
73 |
+
city = await hellbot.input(message)
|
74 |
+
|
75 |
+
hell = await hellbot.edit(message, f"**Fetching air pollution data for `{city}`**")
|
76 |
+
|
77 |
+
apiKey = await db.get_env(ENV.climate_api)
|
78 |
+
if not apiKey:
|
79 |
+
return await hellbot.delete(
|
80 |
+
hell, f"**Climate API not found!** Setup `{ENV.climate_api}` first."
|
81 |
+
)
|
82 |
+
|
83 |
+
data = await Climate.fetchAirPollution(city, apiKey)
|
84 |
+
if not data:
|
85 |
+
return await hellbot.delete(
|
86 |
+
hell, f"**Air pollution data not found for `{city}`**"
|
87 |
+
)
|
88 |
+
|
89 |
+
data = data["list"][0]
|
90 |
+
ugm3 = superscript("ยตg/mยณ")
|
91 |
+
sub2_5 = subscript("2.5")
|
92 |
+
sub10 = subscript("10")
|
93 |
+
|
94 |
+
city_name = city.upper()
|
95 |
+
aqi_index = data["main"]["aqi"]
|
96 |
+
aqi_cond = Climate.AQI_DICT[aqi_index]
|
97 |
+
aqi = f"{aqi_index} ({aqi_cond})"
|
98 |
+
co = f"{data['components']['co']} {ugm3}"
|
99 |
+
no = f"{data['components']['no']} {ugm3}"
|
100 |
+
no2 = f"{data['components']['no2']} {ugm3}"
|
101 |
+
o3 = f"{data['components']['o3']} {ugm3}"
|
102 |
+
so2 = f"{data['components']['so2']} {ugm3}"
|
103 |
+
nh3 = f"{data['components']['nh3']} {ugm3}"
|
104 |
+
pm2_5 = data["components"]["pm2_5"]
|
105 |
+
pm10 = data["components"]["pm10"]
|
106 |
+
|
107 |
+
await hell.edit(
|
108 |
+
await airpollution_templates(
|
109 |
+
city_name=city_name,
|
110 |
+
aqi=aqi,
|
111 |
+
co=co,
|
112 |
+
no=no,
|
113 |
+
no2=no2,
|
114 |
+
o3=o3,
|
115 |
+
so2=so2,
|
116 |
+
nh3=nh3,
|
117 |
+
pm2_5=pm2_5,
|
118 |
+
pm10=pm10,
|
119 |
+
sub2_5=sub2_5,
|
120 |
+
sub10=sub10,
|
121 |
+
),
|
122 |
+
disable_web_page_preview=True,
|
123 |
+
)
|
124 |
+
|
125 |
+
|
126 |
+
HelpMenu("climate").add(
|
127 |
+
"climate",
|
128 |
+
"<city name>",
|
129 |
+
"Get climate data of a city.",
|
130 |
+
"climate Delhi",
|
131 |
+
"City name is optional. Bydefault Delhi's climate data will be fetched.",
|
132 |
+
).add(
|
133 |
+
"airpollution",
|
134 |
+
"<city name>",
|
135 |
+
"Get air pollution data of a city.",
|
136 |
+
"airpollution Delhi",
|
137 |
+
"City name is optional. Bydefault Delhi's air pollution data will be fetched.",
|
138 |
+
).info(
|
139 |
+
"Get the API Key from [here](https://openweathermap.org/price)"
|
140 |
+
).done()
|
Hellbot/plugins/user/clone.py
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
from pyrogram import Client
|
4 |
+
from pyrogram.raw.functions.users import GetFullUser
|
5 |
+
from pyrogram.types import Message
|
6 |
+
|
7 |
+
from . import HelpMenu, db, hellbot, on_message
|
8 |
+
|
9 |
+
|
10 |
+
@on_message("clone", allow_stan=True)
|
11 |
+
async def clone(client: Client, message: Message):
|
12 |
+
if not message.reply_to_message:
|
13 |
+
return await hellbot.delete(
|
14 |
+
message, "Reply to a user's message to clone their profile."
|
15 |
+
)
|
16 |
+
|
17 |
+
replied_user = message.reply_to_message.from_user
|
18 |
+
if replied_user.is_self:
|
19 |
+
return await hellbot.delete(message, "I can't clone myself!")
|
20 |
+
|
21 |
+
hell = await hellbot.edit(message, "Cloning ...")
|
22 |
+
|
23 |
+
try:
|
24 |
+
meh = await client.resolve_peer(client.me.id)
|
25 |
+
fullUser = await client.invoke(GetFullUser(id=meh))
|
26 |
+
about = fullUser.full_user.about or ""
|
27 |
+
except:
|
28 |
+
about = ""
|
29 |
+
|
30 |
+
first_name = client.me.first_name
|
31 |
+
last_name = client.me.last_name or ""
|
32 |
+
|
33 |
+
await db.set_env("CLONE_FIRST_NAME", first_name)
|
34 |
+
await db.set_env("CLONE_LAST_NAME", last_name)
|
35 |
+
await db.set_env("CLONE_ABOUT", about)
|
36 |
+
|
37 |
+
try:
|
38 |
+
targetUser = await client.resolve_peer(replied_user.id)
|
39 |
+
repliedFullUser = await client.invoke(GetFullUser(id=targetUser))
|
40 |
+
await client.update_profile(
|
41 |
+
first_name=replied_user.first_name,
|
42 |
+
last_name=replied_user.last_name or "",
|
43 |
+
about=repliedFullUser.full_user.about or "",
|
44 |
+
)
|
45 |
+
except:
|
46 |
+
await client.update_profile(
|
47 |
+
first_name=replied_user.first_name,
|
48 |
+
last_name=replied_user.last_name or "",
|
49 |
+
)
|
50 |
+
|
51 |
+
try:
|
52 |
+
profile_pic = await client.download_media(replied_user.photo.big_file_id)
|
53 |
+
await client.set_profile_photo(photo=profile_pic)
|
54 |
+
os.remove(profile_pic)
|
55 |
+
except:
|
56 |
+
pass
|
57 |
+
|
58 |
+
await hell.edit("**๐ ๐ง๐พ๐
๐
๐ ๐๐ ๐ฟ๐๐๐พ๐๐ฝ!**")
|
59 |
+
await hellbot.check_and_log(
|
60 |
+
"clone",
|
61 |
+
f"**Cloned {replied_user.mention}** ({replied_user.id}) \n\n**By:** {first_name}",
|
62 |
+
)
|
63 |
+
|
64 |
+
|
65 |
+
@on_message("revert", allow_stan=True)
|
66 |
+
async def revert(client: Client, message: Message):
|
67 |
+
first_name = await db.get_env("CLONE_FIRST_NAME")
|
68 |
+
last_name = await db.get_env("CLONE_LAST_NAME")
|
69 |
+
about = await db.get_env("CLONE_ABOUT")
|
70 |
+
|
71 |
+
if not first_name:
|
72 |
+
return await hellbot.delete(message, "I'm not cloned yet.")
|
73 |
+
|
74 |
+
hell = await hellbot.edit(message, "Reverting ...")
|
75 |
+
|
76 |
+
await client.update_profile(first_name, last_name, about)
|
77 |
+
|
78 |
+
async for photos in client.get_chat_photos("me", 1):
|
79 |
+
await client.delete_profile_photos(photos.file_id)
|
80 |
+
|
81 |
+
await db.rm_env("CLONE_FIRST_NAME")
|
82 |
+
await db.rm_env("CLONE_LAST_NAME")
|
83 |
+
await db.rm_env("CLONE_ABOUT")
|
84 |
+
|
85 |
+
await hell.edit("**Reverted back!**")
|
86 |
+
await hellbot.check_and_log(
|
87 |
+
"revert",
|
88 |
+
f"**Reverted to my original profile.** \n\n**By:** {first_name}",
|
89 |
+
)
|
90 |
+
|
91 |
+
|
92 |
+
HelpMenu("clone").add(
|
93 |
+
"clone",
|
94 |
+
"<reply to user's message>",
|
95 |
+
"Clone the profile of replied user.",
|
96 |
+
"clone",
|
97 |
+
"You can revert back to last profile only. Clone with precaution.",
|
98 |
+
).add(
|
99 |
+
"revert",
|
100 |
+
None,
|
101 |
+
"Revert back to original profile.",
|
102 |
+
"revert",
|
103 |
+
"You can revert back to last profile only. Clone with precaution.",
|
104 |
+
).info(
|
105 |
+
"Clone Menu"
|
106 |
+
).done()
|
Hellbot/plugins/user/convert.py
ADDED
@@ -0,0 +1,216 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import time
|
3 |
+
|
4 |
+
from pyrogram.types import Message
|
5 |
+
|
6 |
+
from Hellbot.functions.convert import convert_to_gif
|
7 |
+
from Hellbot.functions.tools import runcmd
|
8 |
+
|
9 |
+
from . import HelpMenu, hellbot, on_message, Config
|
10 |
+
|
11 |
+
|
12 |
+
@on_message("stog", allow_stan=True)
|
13 |
+
async def sticker_to_gif(_, message: Message):
|
14 |
+
if not message.reply_to_message or not message.reply_to_message.sticker:
|
15 |
+
return await hellbot.delete(
|
16 |
+
message, "Reply to an animated/video sticker to convert it to gif."
|
17 |
+
)
|
18 |
+
|
19 |
+
hell = await hellbot.edit(message, "Converting ...")
|
20 |
+
|
21 |
+
replied_sticker = message.reply_to_message.sticker
|
22 |
+
|
23 |
+
if replied_sticker.is_animated:
|
24 |
+
is_video = False
|
25 |
+
elif replied_sticker.is_video:
|
26 |
+
is_video = True
|
27 |
+
else:
|
28 |
+
return await hellbot.delete(hell, "Reply to an animated/video sticker.")
|
29 |
+
|
30 |
+
dwl_path = await message.reply_to_message.download(Config.TEMP_DIR)
|
31 |
+
gif_path = await convert_to_gif(dwl_path, is_video)
|
32 |
+
|
33 |
+
await message.reply_animation(gif_path)
|
34 |
+
await hellbot.delete(hell, "Converted to gif successfully!")
|
35 |
+
|
36 |
+
os.remove(dwl_path)
|
37 |
+
os.remove(gif_path)
|
38 |
+
|
39 |
+
|
40 |
+
@on_message("stoi", allow_stan=True)
|
41 |
+
async def sticker_to_image(_, message: Message):
|
42 |
+
if not message.reply_to_message or not message.reply_to_message.sticker:
|
43 |
+
return await hellbot.delete(
|
44 |
+
message, "Reply to an sticker to convert it to image."
|
45 |
+
)
|
46 |
+
|
47 |
+
hell = await hellbot.edit(message, "Converting ...")
|
48 |
+
fileName = f"image_{round(time.time())}.png"
|
49 |
+
dwl_path = await message.reply_to_message.download(f"{Config.TEMP_DIR}{fileName}")
|
50 |
+
|
51 |
+
await message.reply_photo(dwl_path)
|
52 |
+
await hellbot.delete(hell, "Converted to image successfully!")
|
53 |
+
|
54 |
+
os.remove(dwl_path)
|
55 |
+
|
56 |
+
|
57 |
+
@on_message("itos", allow_stan=True)
|
58 |
+
async def image_to_sticker(_, message: Message):
|
59 |
+
if not message.reply_to_message or not message.reply_to_message.photo:
|
60 |
+
return await hellbot.delete(
|
61 |
+
message, "Reply to an image to convert it to sticker."
|
62 |
+
)
|
63 |
+
|
64 |
+
hell = await hellbot.edit(message, "Converting ...")
|
65 |
+
fileName = f"sticker_{round(time.time())}.webp"
|
66 |
+
dwl_path = await message.reply_to_message.download(f"{Config.TEMP_DIR}{fileName}")
|
67 |
+
|
68 |
+
await message.reply_sticker(dwl_path)
|
69 |
+
await hellbot.delete(hell, "Converted to sticker successfully!")
|
70 |
+
|
71 |
+
os.remove(dwl_path)
|
72 |
+
|
73 |
+
|
74 |
+
@on_message("ftoi", allow_stan=True)
|
75 |
+
async def file_to_image(_, message: Message):
|
76 |
+
if not message.reply_to_message or not message.reply_to_message.document:
|
77 |
+
return await hellbot.delete(message, "Reply to a file to convert it to image.")
|
78 |
+
|
79 |
+
if message.reply_to_message.document.mime_type.split("/")[0] != "image":
|
80 |
+
return await hellbot.delete(message, "Reply to an image file.")
|
81 |
+
|
82 |
+
hell = await hellbot.edit(message, "Converting ...")
|
83 |
+
fileName = f"image_{round(time.time())}.png"
|
84 |
+
dwl_path = await message.reply_to_message.download(f"{Config.TEMP_DIR}{fileName}")
|
85 |
+
|
86 |
+
await message.reply_photo(dwl_path)
|
87 |
+
await hellbot.delete(hell, "Converted to image successfully!")
|
88 |
+
|
89 |
+
os.remove(dwl_path)
|
90 |
+
|
91 |
+
|
92 |
+
@on_message("itof", allow_stan=True)
|
93 |
+
async def image_to_file(_, message: Message):
|
94 |
+
if not message.reply_to_message or not message.reply_to_message.photo:
|
95 |
+
return await hellbot.delete(message, "Reply to an image to convert it to file.")
|
96 |
+
|
97 |
+
hell = await hellbot.edit(message, "Converting ...")
|
98 |
+
fileName = f"file_{round(time.time())}.png"
|
99 |
+
dwl_path = await message.reply_to_message.download(f"{Config.TEMP_DIR}{fileName}")
|
100 |
+
|
101 |
+
await message.reply_document(dwl_path)
|
102 |
+
await hellbot.delete(hell, "Converted to file successfully!")
|
103 |
+
|
104 |
+
os.remove(dwl_path)
|
105 |
+
|
106 |
+
|
107 |
+
@on_message("tovoice", allow_stan=True)
|
108 |
+
async def media_to_voice(_, message: Message):
|
109 |
+
if not message.reply_to_message or not message.reply_to_message.media:
|
110 |
+
return await hellbot.delete(message, "Reply to a media to convert it to voice.")
|
111 |
+
|
112 |
+
hell = await hellbot.edit(message, "Converting ...")
|
113 |
+
dwl_path = await message.reply_to_message.download(f"{Config.TEMP_DIR}")
|
114 |
+
voice_path = f"{round(time.time())}.ogg"
|
115 |
+
|
116 |
+
cmd_list = [
|
117 |
+
"ffmpeg",
|
118 |
+
"-i",
|
119 |
+
dwl_path,
|
120 |
+
"-map",
|
121 |
+
"0:a",
|
122 |
+
"-codec:a",
|
123 |
+
"libopus",
|
124 |
+
"-b:a",
|
125 |
+
"100k",
|
126 |
+
"-vbr",
|
127 |
+
"on",
|
128 |
+
voice_path,
|
129 |
+
]
|
130 |
+
|
131 |
+
_, err, _, _ = await runcmd(" ".join(cmd_list))
|
132 |
+
|
133 |
+
if os.path.exists(voice_path):
|
134 |
+
await message.reply_voice(voice_path)
|
135 |
+
await hellbot.delete(hell, "Converted to voice successfully!")
|
136 |
+
os.remove(voice_path)
|
137 |
+
else:
|
138 |
+
await hellbot.error(hell, f"`{err}`")
|
139 |
+
|
140 |
+
os.remove(dwl_path)
|
141 |
+
|
142 |
+
|
143 |
+
@on_message("tomp3", allow_stan=True)
|
144 |
+
async def media_to_mp3(_, message: Message):
|
145 |
+
if not message.reply_to_message or not message.reply_to_message.media:
|
146 |
+
return await hellbot.delete(message, "Reply to a media to convert it to mp3.")
|
147 |
+
|
148 |
+
hell = await hellbot.edit(message, "Converting ...")
|
149 |
+
dwl_path = await message.reply_to_message.download(f"{Config.TEMP_DIR}")
|
150 |
+
mp3_path = f"{round(time.time())}.mp3"
|
151 |
+
|
152 |
+
cmd_list = [
|
153 |
+
"ffmpeg",
|
154 |
+
"-i",
|
155 |
+
dwl_path,
|
156 |
+
"-vn",
|
157 |
+
mp3_path,
|
158 |
+
]
|
159 |
+
|
160 |
+
_, stderr, _, _ = await runcmd(" ".join(cmd_list))
|
161 |
+
|
162 |
+
if os.path.exists(mp3_path):
|
163 |
+
await message.reply_audio(mp3_path)
|
164 |
+
await hellbot.delete(hell, "Converted to mp3 successfully!")
|
165 |
+
os.remove(mp3_path)
|
166 |
+
else:
|
167 |
+
await hellbot.error(hell, f"`{stderr}`")
|
168 |
+
|
169 |
+
os.remove(dwl_path)
|
170 |
+
|
171 |
+
|
172 |
+
HelpMenu("convert").add(
|
173 |
+
"stog", #Bugged: to-be-fixed
|
174 |
+
"<reply>",
|
175 |
+
"Converts animated sticker to gif.",
|
176 |
+
None,
|
177 |
+
"Only animated sticker and video sticker can be converted to gif.",
|
178 |
+
).add(
|
179 |
+
"stoi",
|
180 |
+
"<reply>",
|
181 |
+
"Converts sticker to image.",
|
182 |
+
None,
|
183 |
+
"Only static stickers can be converted to image.",
|
184 |
+
).add(
|
185 |
+
"itos",
|
186 |
+
"<reply>",
|
187 |
+
"Converts image to sticker.",
|
188 |
+
None,
|
189 |
+
"Only images can be converted to sticker.",
|
190 |
+
).add(
|
191 |
+
"ftoi",
|
192 |
+
"<reply>",
|
193 |
+
"Converts file to image.",
|
194 |
+
None,
|
195 |
+
"Only image files can be converted to image.",
|
196 |
+
).add(
|
197 |
+
"itof",
|
198 |
+
"<reply>",
|
199 |
+
"Converts image to file.",
|
200 |
+
None,
|
201 |
+
"Only images can be converted to file.",
|
202 |
+
).add(
|
203 |
+
"tovoice",
|
204 |
+
"<reply>",
|
205 |
+
"Converts media to voice.",
|
206 |
+
None,
|
207 |
+
"Only video/audio can be converted to voice.",
|
208 |
+
).add(
|
209 |
+
"tomp3",
|
210 |
+
"<reply>",
|
211 |
+
"Converts media to mp3.",
|
212 |
+
None,
|
213 |
+
"Only video/audio can be converted to mp3.",
|
214 |
+
).info(
|
215 |
+
"Converts media to other formats."
|
216 |
+
).done()
|
Hellbot/plugins/user/core.py
ADDED
@@ -0,0 +1,321 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import importlib
|
2 |
+
import os
|
3 |
+
import sys
|
4 |
+
from pathlib import Path
|
5 |
+
|
6 |
+
from pyrogram import Client
|
7 |
+
from pyrogram.enums import MessagesFilter, ParseMode
|
8 |
+
from pyrogram.types import Message
|
9 |
+
|
10 |
+
from Hellbot.core import ENV, Config, Symbols
|
11 |
+
|
12 |
+
from . import HelpMenu, bot, db, handler, hellbot, on_message
|
13 |
+
|
14 |
+
|
15 |
+
@on_message("help", allow_stan=True)
|
16 |
+
async def help(client: Client, message: Message):
|
17 |
+
hell = await hellbot.edit(message, "**Processing...**")
|
18 |
+
if len(message.command) == 1:
|
19 |
+
try:
|
20 |
+
result = await client.get_inline_bot_results(bot.me.username, "help_menu")
|
21 |
+
await client.send_inline_bot_result(
|
22 |
+
message.chat.id,
|
23 |
+
result.query_id,
|
24 |
+
result.results[0].id,
|
25 |
+
True,
|
26 |
+
)
|
27 |
+
return await hell.delete()
|
28 |
+
except Exception as e:
|
29 |
+
await hellbot.error(hell, str(e), 20)
|
30 |
+
return
|
31 |
+
|
32 |
+
plugin = await hellbot.input(message)
|
33 |
+
if plugin.lower() in Config.CMD_MENU:
|
34 |
+
try:
|
35 |
+
await hellbot.edit(
|
36 |
+
hell, Config.CMD_MENU[plugin.lower()], ParseMode.MARKDOWN
|
37 |
+
)
|
38 |
+
return
|
39 |
+
except Exception as e:
|
40 |
+
await hellbot.error(hell, str(e), 20)
|
41 |
+
return
|
42 |
+
|
43 |
+
available_plugins = f"{Symbols.bullet} **๐ ๐๐บ๐๐
๐บ๐ป๐
๐พ ๐๐
๐๐๐๐๐:**\n\n"
|
44 |
+
for i in sorted(list(Config.CMD_MENU.keys())):
|
45 |
+
available_plugins += f"`{i}`, "
|
46 |
+
available_plugins = available_plugins[:-2]
|
47 |
+
available_plugins += (
|
48 |
+
f"\n\n๐ฃ๐ `{handler}help <plugin name>` ๐๐ ๐๐พ๐ ๐ฝ๐พ๐๐บ๐๐
๐พ๐ฝ ๐๐๐ฟ๐ ๐๐ฟ ๐๐๐บ๐ ๐๐
๐๐๐๐."
|
49 |
+
)
|
50 |
+
await hellbot.edit(hell, available_plugins, ParseMode.MARKDOWN)
|
51 |
+
|
52 |
+
|
53 |
+
@on_message("repo", allow_stan=True)
|
54 |
+
async def repo(_, message: Message):
|
55 |
+
REPO_TEXT = (
|
56 |
+
"__๐ ๐ฑ๐พ๐๐:__ [Github](https://github.com/The-HellBot/HellBot)\n\n"
|
57 |
+
"__๐ Updates:__ @Its_HellBot\n"
|
58 |
+
"__๐ Support:__ @HellBot_Chats\n\n"
|
59 |
+
"**By ยฉ๏ธ @HellBot_Networks**"
|
60 |
+
)
|
61 |
+
await hellbot.edit(message, REPO_TEXT, no_link_preview=True)
|
62 |
+
|
63 |
+
|
64 |
+
@on_message("plinfo", allow_stan=True)
|
65 |
+
async def plugin_info(_, message: Message):
|
66 |
+
plugin = await hellbot.input(message)
|
67 |
+
if plugin.lower() in Config.CMD_MENU:
|
68 |
+
try:
|
69 |
+
await hellbot.edit(
|
70 |
+
message, Config.CMD_MENU[plugin.lower()], ParseMode.MARKDOWN
|
71 |
+
)
|
72 |
+
return
|
73 |
+
except Exception as e:
|
74 |
+
await hellbot.error(message, str(e), 20)
|
75 |
+
return
|
76 |
+
await hellbot.error(message, f"**Invalid Plugin Name:** `{plugin}`", 20)
|
77 |
+
|
78 |
+
|
79 |
+
@on_message("cmdinfo", allow_stan=True)
|
80 |
+
async def command_info(_, message: Message):
|
81 |
+
cmd = await hellbot.input(message)
|
82 |
+
if cmd.lower() in Config.CMD_INFO:
|
83 |
+
try:
|
84 |
+
cmd_dict = Config.CMD_INFO[cmd.lower()]
|
85 |
+
template = (
|
86 |
+
f"**๐ ๐ฏ๐
๐๐๐๐:** `{cmd_dict['plugin']}.py`\n\n"
|
87 |
+
f"**{Symbols.anchor} ๐ข๐๐๐๐บ๐๐ฝ:** `{cmd_dict['command']}`\n"
|
88 |
+
f"**{Symbols.anchor} ๐ฃ๐พ๐๐ผ๐๐๐๐๐๐๐:** __{cmd_dict['description']}__\n"
|
89 |
+
f"**{Symbols.anchor} ๐ค๐๐บ๐๐๐
๐พ:** `{cmd_dict['example']}`\n"
|
90 |
+
f"**{Symbols.anchor} ๐ญ๐๐๐พ:** __{cmd_dict['note']}__\n"
|
91 |
+
)
|
92 |
+
await hellbot.edit(message, template, ParseMode.MARKDOWN)
|
93 |
+
return
|
94 |
+
except Exception as e:
|
95 |
+
await hellbot.error(message, str(e), 20)
|
96 |
+
return
|
97 |
+
await hellbot.error(message, f"**Invalid Command Name:** `{cmd}`", 20)
|
98 |
+
|
99 |
+
|
100 |
+
@on_message("send", allow_stan=True)
|
101 |
+
async def send_plugin(client: Client, message: Message):
|
102 |
+
if len(message.command) < 2:
|
103 |
+
return await hellbot.delete(message, "Give me a plugin name to send.")
|
104 |
+
|
105 |
+
plugin = message.command[1].lower().replace(".py", "").strip()
|
106 |
+
if plugin not in Config.CMD_MENU:
|
107 |
+
return await hellbot.delete(message, f"**Invalid Plugin Name:** `{plugin}`")
|
108 |
+
|
109 |
+
try:
|
110 |
+
await client.send_document(
|
111 |
+
message.chat.id,
|
112 |
+
f"./Hellbot/plugins/user/{plugin}.py",
|
113 |
+
caption=f"**๐ ๐ฏ๐
๐๐๐๐:** `{plugin}.py`",
|
114 |
+
)
|
115 |
+
await hellbot.delete(message, f"**Sent:** `{plugin}.py`")
|
116 |
+
except Exception as e:
|
117 |
+
await hellbot.error(message, str(e), 20)
|
118 |
+
|
119 |
+
|
120 |
+
@on_message("install", allow_stan=True)
|
121 |
+
async def install_plugins(_, message: Message):
|
122 |
+
if not message.reply_to_message or not message.reply_to_message.document:
|
123 |
+
return await hellbot.delete(message, "Reply to a plugin to install it.")
|
124 |
+
|
125 |
+
hell = await hellbot.edit(message, "**Installing...**")
|
126 |
+
plugin_path = await message.reply_to_message.download("./Hellbot/plugins/user/")
|
127 |
+
|
128 |
+
if not plugin_path.endswith(".py"):
|
129 |
+
os.remove(plugin_path)
|
130 |
+
return await hellbot.error(hell, "**Invalid Plugin:** Not a python file.", 20)
|
131 |
+
|
132 |
+
plugin = plugin_path.split("/")[-1].replace(".py", "").strip()
|
133 |
+
if plugin in Config.CMD_MENU:
|
134 |
+
os.remove(plugin_path)
|
135 |
+
return await hellbot.error(
|
136 |
+
hell, f"**Plugin Already Installed:** `{plugin}.py`", 20
|
137 |
+
)
|
138 |
+
|
139 |
+
if "(" in plugin:
|
140 |
+
os.remove(plugin_path)
|
141 |
+
return await hellbot.error(
|
142 |
+
hell, f"**Plugin Already Installed:** `{plugin}.py`", 20
|
143 |
+
)
|
144 |
+
|
145 |
+
try:
|
146 |
+
shortname = Path(plugin_path).stem.replace(".py", "")
|
147 |
+
path = Path(f"Hellbot/plugins/user/{shortname}.py")
|
148 |
+
name = "Hellbot.plugins.user." + shortname
|
149 |
+
spec = importlib.util.spec_from_file_location(name, path)
|
150 |
+
load = importlib.util.module_from_spec(spec)
|
151 |
+
spec.loader.exec_module(load)
|
152 |
+
sys.modules["Hellbot.plugins.user." + shortname] = load
|
153 |
+
await hellbot.edit(hell, f"**Installed:** `{plugin}.py`")
|
154 |
+
except Exception as e:
|
155 |
+
await hellbot.error(hell, str(e), 20)
|
156 |
+
os.remove(plugin_path)
|
157 |
+
|
158 |
+
|
159 |
+
@on_message("uninstall", allow_stan=True)
|
160 |
+
async def uninstall_plugins(_, message: Message):
|
161 |
+
if len(message.command) < 2:
|
162 |
+
return await hellbot.delete(message, "Give me a plugin name to uninstall.")
|
163 |
+
|
164 |
+
plugin = message.command[1].lower().replace(".py", "").strip()
|
165 |
+
if plugin not in Config.CMD_MENU:
|
166 |
+
return await hellbot.delete(message, f"**Invalid Plugin Name:** `{plugin}`")
|
167 |
+
|
168 |
+
try:
|
169 |
+
os.remove(f"./Hellbot/plugins/user/{plugin}.py")
|
170 |
+
for i in Config.HELP_DICT[plugin]["commands"]:
|
171 |
+
cmd = i["command"]
|
172 |
+
for i in hellbot.users:
|
173 |
+
i.remove_handler(cmd)
|
174 |
+
del Config.CMD_INFO[cmd]
|
175 |
+
del Config.HELP_DICT[plugin]
|
176 |
+
del Config.CMD_MENU[plugin]
|
177 |
+
await hellbot.delete(message, f"**Uninstalled:** `{plugin}.py`")
|
178 |
+
except Exception as e:
|
179 |
+
await hellbot.error(message, str(e), 20)
|
180 |
+
|
181 |
+
|
182 |
+
@on_message("installall", allow_stan=True)
|
183 |
+
async def installall(client: Client, message: Message):
|
184 |
+
if len(message.command) < 2:
|
185 |
+
return await hellbot.delete(
|
186 |
+
message, "Give me channel username to install plugins."
|
187 |
+
)
|
188 |
+
|
189 |
+
try:
|
190 |
+
chat = await client.get_chat(message.command[1])
|
191 |
+
except Exception as e:
|
192 |
+
return await hellbot.delete(message, f"**Invalid Channel Username:** `{e}`")
|
193 |
+
|
194 |
+
hell = await hellbot.edit(message, f"**Installing plugins from {chat.title}...**")
|
195 |
+
finalStr = f"{Symbols.check_mark} **๐ฏ๐
๐๐๐๐๐ ๐จ๐๐๐๐บ๐
๐
๐พ๐ฝ: {chat.title}**\n\n"
|
196 |
+
count = 0
|
197 |
+
|
198 |
+
async for msg in client.search_messages(chat.id, filter=MessagesFilter.DOCUMENT):
|
199 |
+
if msg.document.file_name.endswith(".py"):
|
200 |
+
dwl_path = await msg.download("./Hellbot/plugins/user/")
|
201 |
+
plugin = dwl_path.split("/")[-1].replace(".py", "").strip()
|
202 |
+
if plugin in Config.CMD_MENU:
|
203 |
+
os.remove(dwl_path)
|
204 |
+
finalStr += (
|
205 |
+
f" {Symbols.anchor} `{plugin}.py` - **๐ ๐
๐๐พ๐บ๐ฝ๐ ๐จ๐๐๐๐บ๐
๐
๐พ๐ฝ!**\n"
|
206 |
+
)
|
207 |
+
continue
|
208 |
+
if "(" in plugin:
|
209 |
+
os.remove(dwl_path)
|
210 |
+
finalStr += (
|
211 |
+
f" {Symbols.anchor} `{plugin}.py` - **๐ ๐
๐๐พ๐บ๐ฝ๐ ๐จ๐๐๐๐บ๐
๐
๐พ๐ฝ!**\n"
|
212 |
+
)
|
213 |
+
continue
|
214 |
+
try:
|
215 |
+
shortname = Path(dwl_path).stem.replace(".py", "")
|
216 |
+
path = Path(f"Hellbot/plugins/user/{shortname}.py")
|
217 |
+
name = "Hellbot.plugins.user." + shortname
|
218 |
+
spec = importlib.util.spec_from_file_location(name, path)
|
219 |
+
load = importlib.util.module_from_spec(spec)
|
220 |
+
spec.loader.exec_module(load)
|
221 |
+
sys.modules["Hellbot.plugins.user." + shortname] = load
|
222 |
+
count += 1
|
223 |
+
finalStr += f" {Symbols.anchor} `{plugin}.py` - **๐จ๐๐๐๐บ๐
๐
๐พ๐ฝ!**\n"
|
224 |
+
except Exception as e:
|
225 |
+
os.remove(dwl_path)
|
226 |
+
finalStr += (
|
227 |
+
f" {Symbols.anchor} `{plugin}.py` - **๐ค๐๐๐๐ ๐จ๐๐๐๐บ๐
๐
๐๐๐!**\n"
|
228 |
+
)
|
229 |
+
continue
|
230 |
+
|
231 |
+
finalStr += f"\n**๐ ๐ณ๐๐๐บ๐
๐ฏ๐
๐๐๐๐๐ ๐จ๐๐๐๐บ๐
๐
๐พ๐ฝ:** `{count}`"
|
232 |
+
await hell.edit(finalStr, ParseMode.MARKDOWN, disable_web_page_preview=True)
|
233 |
+
|
234 |
+
|
235 |
+
@on_message("unload", allow_stan=True)
|
236 |
+
async def unload_plugins(_, message: Message):
|
237 |
+
if len(message.command) < 2:
|
238 |
+
return await hellbot.delete(message, "Give me a plugin name to unload.")
|
239 |
+
|
240 |
+
plugin = message.command[1].lower().replace(".py", "").strip()
|
241 |
+
if plugin not in Config.CMD_MENU:
|
242 |
+
return await hellbot.delete(message, f"**Invalid Plugin Name:** `{plugin}`")
|
243 |
+
|
244 |
+
unloaded = await db.get_env(ENV.unload_plugins) or ""
|
245 |
+
unloaded = unloaded.split(" ")
|
246 |
+
if plugin in unloaded:
|
247 |
+
return await hellbot.delete(message, f"**Already Unloaded:** `{plugin}.py`")
|
248 |
+
|
249 |
+
unloaded.append(plugin)
|
250 |
+
await db.set_env(ENV.unload_plugins, " ".join(unloaded))
|
251 |
+
await hellbot.delete(
|
252 |
+
message, f"**Unloaded:** `{plugin}.py` \n\n__Restart the bot to see changes.__"
|
253 |
+
)
|
254 |
+
|
255 |
+
|
256 |
+
@on_message("load", allow_stan=True)
|
257 |
+
async def load_plugins(_, message: Message):
|
258 |
+
if len(message.command) < 2:
|
259 |
+
return await hellbot.delete(message, "Give me a plugin name to load.")
|
260 |
+
|
261 |
+
plugin = message.command[1].lower().replace(".py", "").strip()
|
262 |
+
unloaded = await db.get_env(ENV.unload_plugins) or ""
|
263 |
+
unloaded = unloaded.split(" ")
|
264 |
+
if plugin not in unloaded:
|
265 |
+
return await hellbot.delete(message, f"**Already Loaded:** `{plugin}.py`")
|
266 |
+
|
267 |
+
unloaded.remove(plugin)
|
268 |
+
await db.set_env(ENV.unload_plugins, " ".join(unloaded))
|
269 |
+
await hellbot.delete(
|
270 |
+
message, f"**Loaded:** `{plugin}.py` \n\n__Restart the bot to see changes.__"
|
271 |
+
)
|
272 |
+
|
273 |
+
|
274 |
+
HelpMenu("help").add(
|
275 |
+
"help",
|
276 |
+
"<plugin name>",
|
277 |
+
"Get the detailed help menu for that mentioned plugin or get the whole help menu instead.",
|
278 |
+
"help alive",
|
279 |
+
).add("repo", None, "Get the repo link of the bot.", "repo").add(
|
280 |
+
"plinfo",
|
281 |
+
"<plugin name>",
|
282 |
+
"Get the detailed info of the mentioned plugin.",
|
283 |
+
"plinfo alive",
|
284 |
+
).add(
|
285 |
+
"cmdinfo",
|
286 |
+
"<command name>",
|
287 |
+
"Get the detailed info of the mentioned command.",
|
288 |
+
"cmdinfo alive",
|
289 |
+
).add(
|
290 |
+
"send", "<plugin name>", "Send the mentioned plugin.", "send alive"
|
291 |
+
).add(
|
292 |
+
"install",
|
293 |
+
"<reply to plugin>",
|
294 |
+
"Install the replied plugin.",
|
295 |
+
None,
|
296 |
+
"Do not install plugins from untrusted sources, they can be a malware. We're not responsible for any damage caused by them.",
|
297 |
+
).add(
|
298 |
+
"uninstall",
|
299 |
+
"<plugin name>",
|
300 |
+
"Uninstall the mentioned plugin.",
|
301 |
+
"uninstall alive",
|
302 |
+
"This will remove all the commands of that plugin from the bot till a restart is initiated.",
|
303 |
+
).add(
|
304 |
+
"installall",
|
305 |
+
"<channel username>",
|
306 |
+
"Install all the plugins from the mentioned channel.",
|
307 |
+
"installall @plugins_for_hellbot",
|
308 |
+
"Do not install plugins from untrusted sources, they can be a malware. We're not responsible for any damage caused by them.",
|
309 |
+
).add(
|
310 |
+
"unload",
|
311 |
+
"<plugin name>",
|
312 |
+
"Unload the mentioned plugin.",
|
313 |
+
"unload alive",
|
314 |
+
"This will remove all the commands of that plugin from the bot permanently.",
|
315 |
+
).add(
|
316 |
+
"load",
|
317 |
+
"<plugin name>",
|
318 |
+
"Load the mentioned plugin.",
|
319 |
+
"load alive",
|
320 |
+
"This will load all the commands of that plugin to the bot that was previously unloaded permanently.",
|
321 |
+
)
|
Hellbot/plugins/user/downloads.py
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import time
|
2 |
+
|
3 |
+
from pyrogram.types import Message
|
4 |
+
from pySmartDL import SmartDL
|
5 |
+
|
6 |
+
from Hellbot.core import LOGS, Symbols
|
7 |
+
from Hellbot.functions.formatter import readable_time
|
8 |
+
from Hellbot.functions.tools import progress
|
9 |
+
|
10 |
+
from . import Config, HelpMenu, hellbot, on_message
|
11 |
+
|
12 |
+
|
13 |
+
@on_message("download", allow_stan=True)
|
14 |
+
async def download(_, message: Message):
|
15 |
+
hell = await hellbot.edit(message, "Starting to download...")
|
16 |
+
if message.reply_to_message and message.reply_to_message.media:
|
17 |
+
start_time = time.time()
|
18 |
+
try:
|
19 |
+
dwl_path = await message.reply_to_message.download(
|
20 |
+
Config.DWL_DIR,
|
21 |
+
progress=progress,
|
22 |
+
progress_args=(
|
23 |
+
hell,
|
24 |
+
start_time,
|
25 |
+
"โฌ๏ธ Downloading",
|
26 |
+
),
|
27 |
+
)
|
28 |
+
except Exception as e:
|
29 |
+
return await hellbot.error(hell, f"`{e}`", 10)
|
30 |
+
|
31 |
+
await hell.edit(
|
32 |
+
f"**Downloaded to** `{dwl_path}` **in** {readable_time(round(time.time() - start_time))} seconds.**"
|
33 |
+
)
|
34 |
+
|
35 |
+
elif len(message.command) > 2:
|
36 |
+
dwl_url = (await hellbot.input(message)).split(" ")
|
37 |
+
start_time = time.time()
|
38 |
+
try:
|
39 |
+
dl = SmartDL(dwl_url, Config.DWL_DIR, progress_bar=False)
|
40 |
+
dl.start(blocking=False)
|
41 |
+
while not dl.isFinished():
|
42 |
+
display_msg = ""
|
43 |
+
downloaded_size = dl.get_dl_size(human=True)
|
44 |
+
file_size = dl.filesize or "Unknown"
|
45 |
+
diff = time.time() - start_time
|
46 |
+
speed = dl.get_speed(human=True)
|
47 |
+
dl_percentage = round((dl.get_progress() * 100), 2)
|
48 |
+
eta = dl.get_eta(human=True)
|
49 |
+
try:
|
50 |
+
current_msg = (
|
51 |
+
f"**โฌ๏ธ Downloading...**\n\n"
|
52 |
+
f"**{Symbols.anchor} URL:** `{dwl_url}`\n"
|
53 |
+
f"**{Symbols.anchor} Downloaded:** `{downloaded_size}` of `{file_size}`\n"
|
54 |
+
f"**{Symbols.anchor} Speed:** `{speed}`\n"
|
55 |
+
f"**{Symbols.anchor} ETA:** `{eta}`\n"
|
56 |
+
f"**{Symbols.anchor} Progress:** `{dl_percentage}%`"
|
57 |
+
)
|
58 |
+
if round(diff % 10.00) == 0 and current_msg != display_msg:
|
59 |
+
await hell.edit(current_msg)
|
60 |
+
display_msg = current_msg
|
61 |
+
except Exception as e:
|
62 |
+
LOGS.warning(f"PySmartDl: {str(e)}")
|
63 |
+
|
64 |
+
end_time = readable_time(round(time.time() - start_time))
|
65 |
+
if dl.isSuccessful():
|
66 |
+
await hell.edit(
|
67 |
+
f"**Downloaded to** `{dl.get_dest()}` **in** `{end_time}` **seconds.**"
|
68 |
+
)
|
69 |
+
else:
|
70 |
+
await hellbot.error(hell, f"**Failed to download** `{len(dwl_url)} url(s)`")
|
71 |
+
except Exception as e:
|
72 |
+
return await hellbot.error(hell, f"`{e}`", 10)
|
73 |
+
else:
|
74 |
+
return await hellbot.delete(
|
75 |
+
message, "Reply to a media message or pass direct urls to download it."
|
76 |
+
)
|
77 |
+
|
78 |
+
|
79 |
+
HelpMenu("downloads").add(
|
80 |
+
"download",
|
81 |
+
"<reply to media> or <direct link>",
|
82 |
+
"Download media to server.",
|
83 |
+
"download https://example.com/file.mp4",
|
84 |
+
"You can pass multiple urls to download it on my server.",
|
85 |
+
).info("Downloader").done()
|
Hellbot/plugins/user/echo.py
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pyrogram import Client
|
2 |
+
from pyrogram.types import Message
|
3 |
+
|
4 |
+
from Hellbot.core import Symbols
|
5 |
+
|
6 |
+
from . import HelpMenu, db, hellbot, on_message
|
7 |
+
|
8 |
+
|
9 |
+
@on_message("echo", allow_stan=True)
|
10 |
+
async def echo(client: Client, message: Message):
|
11 |
+
if message.reply_to_message:
|
12 |
+
user = message.reply_to_message.from_user.id
|
13 |
+
elif len(message.command) > 1:
|
14 |
+
user = (await client.get_users(message.command[1])).id
|
15 |
+
else:
|
16 |
+
return await hellbot.delete(
|
17 |
+
message, "Reply to an user or pass me a user id to start echoing!"
|
18 |
+
)
|
19 |
+
|
20 |
+
if await db.is_echo(client.me.id, message.chat.id, user):
|
21 |
+
return await hellbot.delete(message, "Echo is already enabled for this user!")
|
22 |
+
|
23 |
+
await db.set_echo(client.me.id, message.chat.id, user)
|
24 |
+
await hellbot.delete(message, "Echo enabled for this user!")
|
25 |
+
|
26 |
+
|
27 |
+
@on_message("unecho", allow_stan=True)
|
28 |
+
async def unecho(client: Client, message: Message):
|
29 |
+
if message.reply_to_message:
|
30 |
+
user = message.reply_to_message.from_user.id
|
31 |
+
elif len(message.command) > 1:
|
32 |
+
user = (await client.get_users(message.command[1])).id
|
33 |
+
else:
|
34 |
+
return await hellbot.delete(
|
35 |
+
message, "Reply to an user or pass me a user id to stop echoing!"
|
36 |
+
)
|
37 |
+
|
38 |
+
if not await db.is_echo(client.me.id, message.chat.id, user):
|
39 |
+
return await hellbot.delete(message, "Echo is already disabled for this user!")
|
40 |
+
|
41 |
+
await db.rm_echo(client.me.id, message.chat.id, user)
|
42 |
+
await hellbot.delete(message, "Echo disabled for this user!")
|
43 |
+
|
44 |
+
|
45 |
+
@on_message("listecho", allow_stan=True)
|
46 |
+
async def listecho(client: Client, message: Message):
|
47 |
+
echos = await db.get_all_echo(client.me.id, message.chat.id)
|
48 |
+
if not echos:
|
49 |
+
return await hellbot.delete(message, "No echos in this chat!")
|
50 |
+
|
51 |
+
text = "**๐ซ๐๐๐ ๐๐ฟ ๐ค๐ผ๐๐ ๐๐ ๐๐๐๐ ๐ผ๐๐บ๐:**\n\n"
|
52 |
+
for echo in echos:
|
53 |
+
text += f" {Symbols.anchor} `{echo}`\n"
|
54 |
+
|
55 |
+
await hellbot.edit(message, text)
|
56 |
+
|
57 |
+
|
58 |
+
@on_message(["resend", "copy"], allow_stan=True)
|
59 |
+
async def reSend(_, message: Message):
|
60 |
+
if message.reply_to_message:
|
61 |
+
await message.reply_to_message.copy(
|
62 |
+
message.chat.id, reply_to_message_id=message.reply_to_message.id
|
63 |
+
)
|
64 |
+
await message.delete()
|
65 |
+
|
66 |
+
|
67 |
+
HelpMenu("echo").add(
|
68 |
+
"echo",
|
69 |
+
"<reply> or <userid>",
|
70 |
+
"Echo every message of the replied user in present chat!",
|
71 |
+
"echo @ForGo10God",
|
72 |
+
"Echo works on text and sticker messages only!",
|
73 |
+
).add(
|
74 |
+
"unecho",
|
75 |
+
"<reply> or <userid>",
|
76 |
+
"Stop echoing messages of the replied user in present chat!",
|
77 |
+
"unecho @ForGo10God",
|
78 |
+
).add(
|
79 |
+
"listecho",
|
80 |
+
None,
|
81 |
+
"List all the users whose messages are being echoed in present chat!",
|
82 |
+
"listecho",
|
83 |
+
).add(
|
84 |
+
"resend",
|
85 |
+
"<reply>",
|
86 |
+
"Resend the replied message!",
|
87 |
+
"resend",
|
88 |
+
"An alias of 'copy' is also available!",
|
89 |
+
).info(
|
90 |
+
"Is it Echoing?"
|
91 |
+
).done()
|
Hellbot/plugins/user/eval.py
ADDED
@@ -0,0 +1,272 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import io
|
2 |
+
import re
|
3 |
+
import subprocess
|
4 |
+
import sys
|
5 |
+
import traceback
|
6 |
+
|
7 |
+
import bs4
|
8 |
+
import requests
|
9 |
+
from pyrogram import Client
|
10 |
+
from pyrogram.errors import MessageTooLong
|
11 |
+
from pyrogram.types import Message
|
12 |
+
from speedtest import Speedtest
|
13 |
+
|
14 |
+
from . import HelpMenu, hellbot, on_message
|
15 |
+
|
16 |
+
|
17 |
+
async def aexec(code, client, message):
|
18 |
+
exec(
|
19 |
+
"async def __aexec(client, message): "
|
20 |
+
+ "".join(f"\n {l_}" for l_ in code.split("\n"))
|
21 |
+
)
|
22 |
+
return await locals()["__aexec"](client, message)
|
23 |
+
|
24 |
+
|
25 |
+
@on_message("eval", allow_stan=True)
|
26 |
+
async def runeval(client: Client, message: Message):
|
27 |
+
if len(message.command) < 2:
|
28 |
+
return await hellbot.delete(message, "No python code provided!")
|
29 |
+
|
30 |
+
reply_to = message.reply_to_message or message
|
31 |
+
|
32 |
+
code = await hellbot.input(message)
|
33 |
+
hell = await hellbot.edit(message, "`running...`")
|
34 |
+
|
35 |
+
old_stderr = sys.stderr
|
36 |
+
old_stdout = sys.stdout
|
37 |
+
redirected_output = sys.stdout = io.StringIO()
|
38 |
+
redirected_error = sys.stderr = io.StringIO()
|
39 |
+
stdout, stderr, exc = None, None, None
|
40 |
+
|
41 |
+
try:
|
42 |
+
await aexec(code, client, message)
|
43 |
+
except Exception:
|
44 |
+
exc = traceback.format_exc()
|
45 |
+
|
46 |
+
evaluation = ""
|
47 |
+
stdout = redirected_output.getvalue()
|
48 |
+
stderr = redirected_error.getvalue()
|
49 |
+
sys.stdout = old_stdout
|
50 |
+
sys.stderr = old_stderr
|
51 |
+
|
52 |
+
if exc:
|
53 |
+
evaluation = exc
|
54 |
+
elif stderr:
|
55 |
+
evaluation = stderr
|
56 |
+
elif stdout:
|
57 |
+
evaluation = stdout
|
58 |
+
else:
|
59 |
+
evaluation = "Success"
|
60 |
+
|
61 |
+
heading = f"**๐ค๐๐บ๐
:**\n```python\n{code}```\n\n"
|
62 |
+
output = f"**๐ฎ๐๐๐๐๐:**\n`{evaluation.strip()}`"
|
63 |
+
final_output = heading + output
|
64 |
+
|
65 |
+
try:
|
66 |
+
await reply_to.reply_text(final_output, disable_web_page_preview=True)
|
67 |
+
except MessageTooLong:
|
68 |
+
with io.BytesIO(str.encode(output)) as out_file:
|
69 |
+
out_file.name = "eval.txt"
|
70 |
+
await reply_to.reply_document(out_file, caption=heading)
|
71 |
+
|
72 |
+
await hell.delete()
|
73 |
+
|
74 |
+
|
75 |
+
@on_message(["exec", "term"], allow_stan=True)
|
76 |
+
async def runterm(client: Client, message: Message):
|
77 |
+
if len(message.command) < 2:
|
78 |
+
return await hellbot.delete(message, "No shell code provided!")
|
79 |
+
|
80 |
+
reply_to = message.reply_to_message or message
|
81 |
+
|
82 |
+
cmd = await hellbot.input(message)
|
83 |
+
hell = await hellbot.edit(message, "`running...`")
|
84 |
+
|
85 |
+
if "\n" in cmd:
|
86 |
+
code = cmd.split("\n")
|
87 |
+
output = ""
|
88 |
+
for x in code:
|
89 |
+
shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", x)
|
90 |
+
try:
|
91 |
+
process = subprocess.Popen(
|
92 |
+
shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
93 |
+
)
|
94 |
+
except Exception as err:
|
95 |
+
print(err)
|
96 |
+
await hell.edit(f"**Error:** \n`{err}`")
|
97 |
+
output += f"**{code}**\n"
|
98 |
+
output += process.stdout.read()[:-1].decode("utf-8")
|
99 |
+
output += "\n"
|
100 |
+
else:
|
101 |
+
shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", cmd)
|
102 |
+
for a in range(len(shell)):
|
103 |
+
shell[a] = shell[a].replace('"', "")
|
104 |
+
try:
|
105 |
+
process = subprocess.Popen(
|
106 |
+
shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
107 |
+
)
|
108 |
+
except Exception as err:
|
109 |
+
exc_type, exc_obj, exc_tb = sys.exc_info()
|
110 |
+
errors = traceback.format_exception(exc_type, exc_obj, exc_tb)
|
111 |
+
await hell.edit("**Error:**\n`{}`".format("".join(errors)))
|
112 |
+
return
|
113 |
+
output = process.stdout.read()[:-1].decode("utf-8")
|
114 |
+
|
115 |
+
if str(output) == "\n":
|
116 |
+
return await hell.edit(f"**๐ฎ๐๐๐๐๐:** __๐ญ๐ ๐๐๐๐๐๐!__")
|
117 |
+
else:
|
118 |
+
try:
|
119 |
+
await reply_to.reply_text(
|
120 |
+
f"**{client.me.id}@hellbot:~$** `{cmd}`\n\n**๐ฎ๐๐๐๐๐:**\n```\n{output}```"
|
121 |
+
)
|
122 |
+
except MessageTooLong:
|
123 |
+
with io.BytesIO(str.encode(output)) as out_file:
|
124 |
+
out_file.name = "exec.txt"
|
125 |
+
await reply_to.reply_document(
|
126 |
+
out_file,
|
127 |
+
caption=f"**{client.me.id}@hellbot:~$** `{cmd}`",
|
128 |
+
)
|
129 |
+
|
130 |
+
await hell.delete()
|
131 |
+
|
132 |
+
|
133 |
+
@on_message(["sh", "shell"], allow_stan=True)
|
134 |
+
async def runshell(_, message: Message):
|
135 |
+
if len(message.command) < 2:
|
136 |
+
return await hellbot.delete(message, "No shell code provided!")
|
137 |
+
|
138 |
+
code = await hellbot.input(message)
|
139 |
+
hell = await hellbot.edit(message, "`executing...`")
|
140 |
+
|
141 |
+
result = subprocess.run(code, shell=True, capture_output=True, text=True)
|
142 |
+
output = result.stdout + result.stderr
|
143 |
+
|
144 |
+
heading = f"**๐ฒ๐๐พ๐
๐
:**\n```sh\n{code}```\n\n"
|
145 |
+
output = f"**๐ฎ๐๐๐๐๐:**\n`{output.strip()}`"
|
146 |
+
final_output = heading + output
|
147 |
+
|
148 |
+
try:
|
149 |
+
await message.reply_text(final_output, disable_web_page_preview=True)
|
150 |
+
except MessageTooLong:
|
151 |
+
with io.BytesIO(str.encode(output)) as out_file:
|
152 |
+
out_file.name = "shell.txt"
|
153 |
+
await message.reply_document(out_file, caption=heading)
|
154 |
+
|
155 |
+
await hell.delete()
|
156 |
+
|
157 |
+
|
158 |
+
@on_message("fext", allow_stan=True)
|
159 |
+
async def file_extention(_, message: Message):
|
160 |
+
BASE_URL = "https://www.fileext.com/file-extension/{0}.html"
|
161 |
+
if len(message.command) < 2:
|
162 |
+
return await hellbot.delete(message, "No file extention provided!")
|
163 |
+
|
164 |
+
extention = message.command[1]
|
165 |
+
hell = await hellbot.edit(message, "`getting information...`")
|
166 |
+
|
167 |
+
response = requests.get(BASE_URL.format(extention))
|
168 |
+
if response.status_code == 200:
|
169 |
+
soup = bs4.BeautifulSoup(response.content, "html.parser")
|
170 |
+
details = soup.find_all("td", {"colspan": "3"})[-1].text
|
171 |
+
await hell.edit(f"**๐ฅ๐๐
๐พ ๐ค๐๐๐พ๐๐๐๐๐:** `{extention}`\n\n**๐ฃ๐พ๐๐บ๐๐
๐:**\n`{details}`")
|
172 |
+
else:
|
173 |
+
await hell.edit(f"**๐ฅ๐๐
๐พ ๐ค๐๐๐พ๐๐๐๐๐:** `{extention}`\n\n**๐ฃ๐พ๐๐บ๐๐
๐:**\n`Not Found`")
|
174 |
+
|
175 |
+
|
176 |
+
@on_message("pypi", allow_stan=True)
|
177 |
+
async def pypi(_, message: Message):
|
178 |
+
BASE_URL = "https://pypi.org/pypi/{0}/json"
|
179 |
+
if len(message.command) < 2:
|
180 |
+
return await hellbot.delete(message, "No package name provided!")
|
181 |
+
|
182 |
+
package = message.command[1]
|
183 |
+
hell = await hellbot.edit(message, "`getting information...`")
|
184 |
+
|
185 |
+
response = requests.get(BASE_URL.format(package))
|
186 |
+
if response.status_code == 200:
|
187 |
+
data = response.json()
|
188 |
+
info = data["info"]
|
189 |
+
name = info["name"]
|
190 |
+
url = info["package_url"]
|
191 |
+
version = info["version"]
|
192 |
+
summary = info["summary"]
|
193 |
+
await hell.edit(f"**๐ฏ๐บ๐ผ๐๐บ๐๐พ:** [{name}]({url}) (`{version}`)\n\n**๐ฃ๐พ๐๐บ๐๐
๐:** `{summary}`")
|
194 |
+
else:
|
195 |
+
await hell.edit(f"**๐ฏ๐บ๐ผ๐๐บ๐๐พ:** `{package}`\n\n**๐ฃ๐พ๐๐บ๐๐
๐:** `Not Found`")
|
196 |
+
|
197 |
+
|
198 |
+
@on_message("speedtest", allow_stan=True)
|
199 |
+
async def speed_test(_, message: Message):
|
200 |
+
hell = await hellbot.edit(message, "`testing speed...`")
|
201 |
+
|
202 |
+
speed = Speedtest()
|
203 |
+
speed.get_best_server()
|
204 |
+
|
205 |
+
await hell.edit("`calculating download speed...`")
|
206 |
+
speed.download()
|
207 |
+
|
208 |
+
await hell.edit("`calculating upload speed...`")
|
209 |
+
speed.upload()
|
210 |
+
|
211 |
+
await hell.edit("`finising up...`")
|
212 |
+
speed.results.share()
|
213 |
+
result = speed.results.dict()
|
214 |
+
|
215 |
+
form = """**๐ฒ๐๐พ๐พ๐ฝ๐ณ๐พ๐๐ ๐ฑ๐พ๐๐๐
๐๐ ๐**
|
216 |
+
|
217 |
+
**โง ๐จ๐ฒ๐ฏ:** `{0}, {1}`
|
218 |
+
**โง ๐ฏ๐๐๐:** `{2}`
|
219 |
+
**โง ๐ฒ๐พ๐๐๐พ๐:** `{3}, {4}`
|
220 |
+
**โง ๐ฒ๐๐๐๐๐๐:** `{5}`
|
221 |
+
"""
|
222 |
+
|
223 |
+
await message.reply_photo(
|
224 |
+
result["share"],
|
225 |
+
caption=form.format(
|
226 |
+
result["client"]["isp"],
|
227 |
+
result["client"]["country"],
|
228 |
+
result["ping"],
|
229 |
+
result["server"]["name"],
|
230 |
+
result["server"]["country"],
|
231 |
+
result["server"]["sponsor"],
|
232 |
+
)
|
233 |
+
)
|
234 |
+
await hell.delete()
|
235 |
+
|
236 |
+
|
237 |
+
HelpMenu("eval").add(
|
238 |
+
"eval",
|
239 |
+
"<python code>",
|
240 |
+
"Execute the python code and get results.",
|
241 |
+
"eval print('hello world')",
|
242 |
+
"Use this command with caution! Using this command senselessly and getting yourself in trouble is not Hellbot's responsibility!"
|
243 |
+
).add(
|
244 |
+
"exec",
|
245 |
+
"<linux command>",
|
246 |
+
"Execute the linux command and get results.",
|
247 |
+
"exec ls -a",
|
248 |
+
"Use this command with caution! Using this command senselessly and getting yourself in trouble is not Hellbot's responsibility!"
|
249 |
+
).add(
|
250 |
+
"shell",
|
251 |
+
"<shell script>",
|
252 |
+
"Execute the shell script and get results.",
|
253 |
+
"shell echo hello world",
|
254 |
+
"Use this command with caution! Using this command senselessly and getting yourself in trouble is not Hellbot's responsibility!"
|
255 |
+
).add(
|
256 |
+
"fext",
|
257 |
+
"<file extention>",
|
258 |
+
"Get the details of the file extention.",
|
259 |
+
"fext py",
|
260 |
+
).add(
|
261 |
+
"pypi",
|
262 |
+
"<package name>",
|
263 |
+
"Get the details of the package from pypi.",
|
264 |
+
"pypi pyrogram",
|
265 |
+
).add(
|
266 |
+
"speedtest",
|
267 |
+
None,
|
268 |
+
"Test the speed of server and client.",
|
269 |
+
"speedtest",
|
270 |
+
).info(
|
271 |
+
"Execute python, linux and shell scripts."
|
272 |
+
).done()
|