Ufoptg commited on
Commit
cdce48f
โ€ข
1 Parent(s): 5cdfb43

Upload 87 files

Browse files
This view is limited to 50 files because it contains too many changes. ย  See raw diff
Files changed (50) hide show
  1. Hellbot/__init__.py +60 -0
  2. Hellbot/__main__.py +33 -0
  3. Hellbot/core/__init__.py +19 -0
  4. Hellbot/core/clients.py +232 -0
  5. Hellbot/core/config.py +155 -0
  6. Hellbot/core/database.py +584 -0
  7. Hellbot/core/initializer.py +94 -0
  8. Hellbot/core/logger.py +19 -0
  9. Hellbot/functions/__init__.py +0 -0
  10. Hellbot/functions/admins.py +24 -0
  11. Hellbot/functions/convert.py +98 -0
  12. Hellbot/functions/driver.py +318 -0
  13. Hellbot/functions/formatter.py +94 -0
  14. Hellbot/functions/images.py +389 -0
  15. Hellbot/functions/media.py +192 -0
  16. Hellbot/functions/paste.py +49 -0
  17. Hellbot/functions/scraping.py +528 -0
  18. Hellbot/functions/sticker.py +135 -0
  19. Hellbot/functions/templates.py +466 -0
  20. Hellbot/functions/tools.py +139 -0
  21. Hellbot/functions/utility.py +241 -0
  22. Hellbot/plugins/__init__.py +0 -0
  23. Hellbot/plugins/bot/__init__.py +29 -0
  24. Hellbot/plugins/bot/bot.py +60 -0
  25. Hellbot/plugins/bot/callbacks.py +279 -0
  26. Hellbot/plugins/bot/forcesub.py +226 -0
  27. Hellbot/plugins/bot/inline.py +39 -0
  28. Hellbot/plugins/bot/sessions.py +183 -0
  29. Hellbot/plugins/bot/users.py +82 -0
  30. Hellbot/plugins/btnsG.py +106 -0
  31. Hellbot/plugins/btnsK.py +45 -0
  32. Hellbot/plugins/decorator.py +67 -0
  33. Hellbot/plugins/help.py +132 -0
  34. Hellbot/plugins/user/__init__.py +16 -0
  35. Hellbot/plugins/user/admins.py +510 -0
  36. Hellbot/plugins/user/afk.py +157 -0
  37. Hellbot/plugins/user/anime.py +184 -0
  38. Hellbot/plugins/user/antiflood.py +200 -0
  39. Hellbot/plugins/user/archiver.py +99 -0
  40. Hellbot/plugins/user/autopost.py +143 -0
  41. Hellbot/plugins/user/blacklist.py +78 -0
  42. Hellbot/plugins/user/bot.py +164 -0
  43. Hellbot/plugins/user/carbon.py +73 -0
  44. Hellbot/plugins/user/climate.py +140 -0
  45. Hellbot/plugins/user/clone.py +106 -0
  46. Hellbot/plugins/user/convert.py +216 -0
  47. Hellbot/plugins/user/core.py +321 -0
  48. Hellbot/plugins/user/downloads.py +85 -0
  49. Hellbot/plugins/user/echo.py +91 -0
  50. 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()