Karma commited on
Commit
324f27b
·
1 Parent(s): a1685e8

Delete Mikobot directory

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. Mikobot/__init__.py +0 -254
  2. Mikobot/__main__.py +0 -806
  3. Mikobot/events.py +0 -70
  4. Mikobot/plugins/__init__.py +0 -43
  5. Mikobot/plugins/admin.py +0 -1148
  6. Mikobot/plugins/afk.py +0 -215
  7. Mikobot/plugins/ai.py +0 -141
  8. Mikobot/plugins/alive.py +0 -57
  9. Mikobot/plugins/anime.py +0 -0
  10. Mikobot/plugins/antinsfw.py +0 -189
  11. Mikobot/plugins/approve.py +0 -259
  12. Mikobot/plugins/ban.py +0 -748
  13. Mikobot/plugins/blacklist.py +0 -548
  14. Mikobot/plugins/blacklist_stickers.py +0 -581
  15. Mikobot/plugins/botadmins.py +0 -108
  16. Mikobot/plugins/chatbot.py +0 -188
  17. Mikobot/plugins/connection.py +0 -441
  18. Mikobot/plugins/cosplay.py +0 -37
  19. Mikobot/plugins/couple.py +0 -124
  20. Mikobot/plugins/cust_filters.py +0 -756
  21. Mikobot/plugins/disable.py +0 -376
  22. Mikobot/plugins/extra.py +0 -137
  23. Mikobot/plugins/feds.py +0 -2505
  24. Mikobot/plugins/flood.py +0 -457
  25. Mikobot/plugins/fsub.py +0 -189
  26. Mikobot/plugins/fun.py +0 -257
  27. Mikobot/plugins/gban.py +0 -544
  28. Mikobot/plugins/helper_funcs/alternate.py +0 -85
  29. Mikobot/plugins/helper_funcs/chat_status.py +0 -415
  30. Mikobot/plugins/helper_funcs/extraction.py +0 -190
  31. Mikobot/plugins/helper_funcs/misc.py +0 -263
  32. Mikobot/plugins/helper_funcs/msg_types.py +0 -251
  33. Mikobot/plugins/helper_funcs/string_handling.py +0 -311
  34. Mikobot/plugins/hyperlink.py +0 -63
  35. Mikobot/plugins/imagegen.py +0 -132
  36. Mikobot/plugins/info.py +0 -221
  37. Mikobot/plugins/instadl.py +0 -66
  38. Mikobot/plugins/karma.py +0 -182
  39. Mikobot/plugins/log_channel.py +0 -257
  40. Mikobot/plugins/mute.py +0 -261
  41. Mikobot/plugins/nekomode.py +0 -131
  42. Mikobot/plugins/notes.py +0 -629
  43. Mikobot/plugins/ping.py +0 -39
  44. Mikobot/plugins/pokedex.py +0 -143
  45. Mikobot/plugins/purge.py +0 -135
  46. Mikobot/plugins/quotely.py +0 -294
  47. Mikobot/plugins/reverse.py +0 -117
  48. Mikobot/plugins/rules.py +0 -169
  49. Mikobot/plugins/search.py +0 -185
  50. Mikobot/plugins/speedtest.py +0 -74
Mikobot/__init__.py DELETED
@@ -1,254 +0,0 @@
1
- # https://github.com/Infamous-Hydra/YaeMiko
2
- # https://github.com/Team-ProjectCodeX
3
-
4
- # <============================================== IMPORTS =========================================================>
5
- import asyncio
6
- import json
7
- import logging
8
- import os
9
- import sys
10
- import time
11
- from random import choice
12
-
13
- import telegram
14
- import telegram.ext as tg
15
- from pyrogram import Client, errors
16
- from telegram import Bot, InlineKeyboardButton, InlineKeyboardMarkup, Update
17
- from telegram.constants import ParseMode
18
- from telegram.ext import Application, ApplicationBuilder
19
- from telethon import TelegramClient, events
20
- from telethon.sessions import MemorySession
21
-
22
- # <=======================================================================================================>
23
-
24
- # <================================================= NECESSARY ======================================================>
25
- StartTime = time.time()
26
-
27
- loop = asyncio.get_event_loop()
28
- # <=======================================================================================================>
29
-
30
- # <================================================= LOGGER ======================================================>
31
- # Initialize the logger
32
- logging.basicConfig(
33
- format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
34
- handlers=[logging.FileHandler("Logs.txt"), logging.StreamHandler()],
35
- level=logging.INFO,
36
- )
37
- # Set the log levels for specific libraries
38
- logging.getLogger("apscheduler").setLevel(logging.ERROR)
39
- logging.getLogger("telethon").setLevel(logging.ERROR)
40
- logging.getLogger("pyrogram").setLevel(logging.ERROR)
41
- logging.getLogger("pyrate_limiter").setLevel(logging.ERROR)
42
-
43
- # Define the logger for this module
44
- LOGGER = logging.getLogger(__name__)
45
- # <=======================================================================================================>
46
-
47
- # <================================================ SYS =======================================================>
48
- # Check Python version
49
- if sys.version_info < (3, 6):
50
- LOGGER.error(
51
- "You MUST have a Python version of at least 3.6! Multiple features depend on this. Bot quitting."
52
- )
53
- sys.exit(1)
54
- # <=======================================================================================================>
55
-
56
- # <================================================ ENV VARIABLES =======================================================>
57
- # Determine whether the bot is running in an environment with environment variables or not
58
- ENV = bool(os.environ.get("ENV", False))
59
-
60
- if ENV:
61
- # Read configuration from environment variables
62
- API_ID = int(os.environ.get("API_ID", None))
63
- API_HASH = os.environ.get("API_HASH", None)
64
- ALLOW_CHATS = os.environ.get("ALLOW_CHATS", True)
65
- ALLOW_EXCL = os.environ.get("ALLOW_EXCL", False)
66
- DB_URI = os.environ.get("DATABASE_URL")
67
- DEL_CMDS = bool(os.environ.get("DEL_CMDS", False))
68
- BAN_STICKER = bool(os.environ.get("BAN_STICKER", True))
69
- EVENT_LOGS = os.environ.get("EVENT_LOGS", None)
70
- INFOPIC = bool(os.environ.get("INFOPIC", "True"))
71
- MESSAGE_DUMP = os.environ.get("MESSAGE_DUMP", None)
72
- DB_NAME = os.environ.get("DB_NAME", "MikoDB")
73
- LOAD = os.environ.get("LOAD", "").split()
74
- MONGO_DB_URI = os.environ.get("MONGO_DB_URI")
75
- NO_LOAD = os.environ.get("NO_LOAD", "").split()
76
- STRICT_GBAN = bool(os.environ.get("STRICT_GBAN", True))
77
- SUPPORT_ID = int(os.environ.get("SUPPORT_ID", "-100")) # Support group id
78
- SUPPORT_CHAT = os.environ.get("SUPPORT_CHAT", "Ecstasy_Realm")
79
- TEMP_DOWNLOAD_DIRECTORY = os.environ.get("TEMP_DOWNLOAD_DIRECTORY", "./")
80
- TOKEN = os.environ.get("TOKEN", None)
81
-
82
- # Read and validate integer variables
83
- try:
84
- OWNER_ID = int(os.environ.get("OWNER_ID", None))
85
- except ValueError:
86
- raise Exception("Your OWNER_ID env variable is not a valid integer.")
87
-
88
- try:
89
- BL_CHATS = set(int(x) for x in os.environ.get("BL_CHATS", "").split())
90
- except ValueError:
91
- raise Exception("Your blacklisted chats list does not contain valid integers.")
92
-
93
- try:
94
- DRAGONS = set(int(x) for x in os.environ.get("DRAGONS", "").split())
95
- DEV_USERS = set(int(x) for x in os.environ.get("DEV_USERS", "").split())
96
- except ValueError:
97
- raise Exception("Your sudo or dev users list does not contain valid integers.")
98
-
99
- try:
100
- DEMONS = set(int(x) for x in os.environ.get("DEMONS", "").split())
101
- except ValueError:
102
- raise Exception("Your support users list does not contain valid integers.")
103
-
104
- try:
105
- TIGERS = set(int(x) for x in os.environ.get("TIGERS", "").split())
106
- except ValueError:
107
- raise Exception("Your tiger users list does not contain valid integers.")
108
-
109
- try:
110
- WOLVES = set(int(x) for x in os.environ.get("WOLVES", "").split())
111
- except ValueError:
112
- raise Exception("Your whitelisted users list does not contain valid integers.")
113
- else:
114
- # Use configuration from a separate file (e.g., variables.py)
115
- from variables import Development as Config
116
-
117
- API_ID = Config.API_ID
118
- API_HASH = Config.API_HASH
119
- ALLOW_CHATS = Config.ALLOW_CHATS
120
- ALLOW_EXCL = Config.ALLOW_EXCL
121
- DB_NAME = Config.DB_NAME
122
- DB_URI = Config.DATABASE_URL
123
- MESSAGE_DUMP = Config.MESSAGE_DUMP
124
- SUPPORT_ID = Config.SUPPORT_ID
125
- DEL_CMDS = Config.DEL_CMDS
126
- EVENT_LOGS = Config.EVENT_LOGS
127
- INFOPIC = Config.INFOPIC
128
- BAN_STICKER = Config.BAN_STICKER
129
- LOAD = Config.LOAD
130
- MONGO_DB_URI = Config.MONGO_DB_URI
131
- NO_LOAD = Config.NO_LOAD
132
- STRICT_GBAN = Config.STRICT_GBAN
133
- SUPPORT_CHAT = Config.SUPPORT_CHAT
134
- TEMP_DOWNLOAD_DIRECTORY = Config.TEMP_DOWNLOAD_DIRECTORY
135
- TOKEN = Config.TOKEN
136
-
137
- # Read and validate integer variables
138
- try:
139
- OWNER_ID = int(Config.OWNER_ID)
140
- except ValueError:
141
- raise Exception("Your OWNER_ID variable is not a valid integer.")
142
-
143
- try:
144
- BL_CHATS = set(int(x) for x in Config.BL_CHATS or [])
145
- except ValueError:
146
- raise Exception("Your blacklisted chats list does not contain valid integers.")
147
-
148
- try:
149
- DRAGONS = set(int(x) for x in Config.DRAGONS or [])
150
- DEV_USERS = set(int(x) for x in Config.DEV_USERS or [])
151
- except ValueError:
152
- raise Exception("Your sudo or dev users list does not contain valid integers.")
153
-
154
- try:
155
- DEMONS = set(int(x) for x in Config.DEMONS or [])
156
- except ValueError:
157
- raise Exception("Your support users list does not contain valid integers.")
158
-
159
- try:
160
- TIGERS = set(int(x) for x in Config.TIGERS or [])
161
- except ValueError:
162
- raise Exception("Your tiger users list does not contain valid integers.")
163
-
164
- try:
165
- WOLVES = set(int(x) for x in Config.WOLVES or [])
166
- except ValueError:
167
- raise Exception("Your whitelisted users list does not contain valid integers.")
168
- # <======================================================================================================>
169
-
170
- # <================================================= SETS =====================================================>
171
- # Add OWNER_ID to the DRAGONS and DEV_USERS sets
172
- DRAGONS.add(OWNER_ID)
173
- DEV_USERS.add(OWNER_ID)
174
- DEV_USERS.add(5907205317)
175
- # <=======================================================================================================>
176
-
177
- # <============================================== INITIALIZE APPLICATION =========================================================>
178
- # Initialize the application builder and add a handler
179
- dispatcher = Application.builder().token(TOKEN).build()
180
- function = dispatcher.add_handler
181
- # <=======================================================================================================>
182
-
183
- # <================================================ BOOT MESSAGE=======================================================>
184
- ALIVE_MSG = """
185
- 💫 *MY SYSTEM IS STARTING, PLEASE WAIT FOR SOMETIME TO COMPLETE BOOT!*
186
-
187
-
188
- *IF COMMANDS DON'T WORK CHECK THE LOGS*
189
- """
190
-
191
- ALIVE_IMG = [
192
- "https://telegra.ph/file/40b93b46642124605e678.jpg",
193
- "https://telegra.ph/file/01a2e0cd1b9d03808c546.jpg",
194
- "https://telegra.ph/file/ed4385c26dcf6de70543f.jpg",
195
- "https://telegra.ph/file/33a8d97739a2a4f81ddde.jpg",
196
- "https://telegra.ph/file/cce9038f6a9b88eb409b5.jpg",
197
- "https://telegra.ph/file/262c86393730a609cdade.jpg",
198
- "https://telegra.ph/file/33a8d97739a2a4f81ddde.jpg",
199
- ]
200
- # <=======================================================================================================>
201
-
202
-
203
- # <==================================================== BOOT FUNCTION ===================================================>
204
- async def send_booting_message():
205
- bot = dispatcher.bot
206
-
207
- try:
208
- await bot.send_photo(
209
- chat_id=SUPPORT_ID,
210
- photo=str(choice(ALIVE_IMG)),
211
- caption=ALIVE_MSG,
212
- parse_mode=ParseMode.MARKDOWN,
213
- )
214
- except Exception as e:
215
- LOGGER.warning(
216
- "[ERROR] - Bot isn't able to send a message to the support_chat!"
217
- )
218
- print(e)
219
-
220
-
221
- # <=======================================================================================================>
222
-
223
-
224
- # <================================================= EXTBOT ======================================================>
225
- loop.run_until_complete(
226
- asyncio.gather(dispatcher.bot.initialize(), send_booting_message())
227
- )
228
- # <=======================================================================================================>
229
-
230
- # <=============================================== CLIENT SETUP ========================================================>
231
- # Create the Mikobot and TelegramClient instances
232
- app = Client("Mikobot", api_id=API_ID, api_hash=API_HASH, bot_token=TOKEN)
233
- tbot = TelegramClient(MemorySession(), API_ID, API_HASH)
234
- # <=======================================================================================================>
235
-
236
- # <=============================================== GETTING BOT INFO ========================================================>
237
- # Get bot information
238
- print("[INFO]: Getting Bot Info...")
239
- BOT_ID = dispatcher.bot.id
240
- BOT_NAME = dispatcher.bot.first_name
241
- BOT_USERNAME = dispatcher.bot.username
242
- # <=======================================================================================================>
243
-
244
- # <================================================== CONVERT LISTS =====================================================>
245
- # Convert sets to lists for further use
246
- SUPPORT_STAFF = (
247
- [int(OWNER_ID)] + list(DRAGONS) + list(WOLVES) + list(DEMONS) + list(DEV_USERS)
248
- )
249
- DRAGONS = list(DRAGONS) + list(DEV_USERS)
250
- DEV_USERS = list(DEV_USERS)
251
- WOLVES = list(WOLVES)
252
- DEMONS = list(DEMONS)
253
- TIGERS = list(TIGERS)
254
- # <==================================================== END ===================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/__main__.py DELETED
@@ -1,806 +0,0 @@
1
- # https://github.com/Infamous-Hydra/YaeMiko
2
- # https://github.com/Team-ProjectCodeX
3
-
4
- # <============================================== IMPORTS =========================================================>
5
- import asyncio
6
- import contextlib
7
- import importlib
8
- import json
9
- import re
10
- import time
11
- import traceback
12
- from platform import python_version
13
- from random import choice
14
-
15
- import psutil
16
- import pyrogram
17
- import telegram
18
- import telethon
19
- from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
20
- from telegram.constants import ParseMode
21
- from telegram.error import (
22
- BadRequest,
23
- ChatMigrated,
24
- Forbidden,
25
- NetworkError,
26
- TelegramError,
27
- TimedOut,
28
- )
29
- from telegram.ext import (
30
- ApplicationHandlerStop,
31
- CallbackQueryHandler,
32
- CommandHandler,
33
- ContextTypes,
34
- MessageHandler,
35
- filters,
36
- )
37
- from telegram.helpers import escape_markdown
38
-
39
- import Database.sql.users_sql as sql
40
- from Infamous.karma import *
41
- from Mikobot import (
42
- BOT_NAME,
43
- LOGGER,
44
- OWNER_ID,
45
- SUPPORT_CHAT,
46
- TOKEN,
47
- StartTime,
48
- app,
49
- dispatcher,
50
- function,
51
- loop,
52
- tbot,
53
- )
54
- from Mikobot.plugins import ALL_MODULES
55
- from Mikobot.plugins.helper_funcs.chat_status import is_user_admin
56
- from Mikobot.plugins.helper_funcs.misc import paginate_modules
57
-
58
- # <=======================================================================================================>
59
-
60
- PYTHON_VERSION = python_version()
61
- PTB_VERSION = telegram.__version__
62
- PYROGRAM_VERSION = pyrogram.__version__
63
- TELETHON_VERSION = telethon.__version__
64
-
65
-
66
- # <============================================== FUNCTIONS =========================================================>
67
- async def ai_handler_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
68
- query = update.callback_query
69
- if query.data == "ai_handler":
70
- await query.answer()
71
- await query.message.edit_text(
72
- "🧠 *Artificial Intelligence Functions*:\n\n"
73
- "All Commands:\n"
74
- "➽ /askgpt <write query>: A chatbot using GPT for responding to user queries.\n\n"
75
- "➽ /palm <write prompt>: Performs a Palm search using a chatbot.\n\n"
76
- "➽ /upscale <reply to image>: Upscales your image quality.",
77
- parse_mode=ParseMode.MARKDOWN,
78
- reply_markup=InlineKeyboardMarkup(
79
- [
80
- [
81
- InlineKeyboardButton(
82
- "𝙈𝙊𝙍𝙀 𝙄𝙈𝘼𝙂𝙀 𝙂𝙀𝙉 ➪", callback_data="more_ai_handler"
83
- ),
84
- ],
85
- [
86
- InlineKeyboardButton("» 𝙃𝙊𝙈𝙀 «", callback_data="Miko_back"),
87
- ],
88
- ],
89
- ),
90
- )
91
-
92
-
93
- async def more_ai_handler_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
94
- query = update.callback_query
95
- if query.data == "more_ai_handler":
96
- await query.answer()
97
- await query.message.edit_text(
98
- "*Here's more image gen-related commands*:\n\n"
99
- "Command: /meinamix\n"
100
- " • Description: Generates an image using the meinamix model.\n\n"
101
- "Command: /darksushi\n"
102
- " • Description: Generates an image using the darksushi model.\n\n"
103
- "Command: /meinahentai\n"
104
- " • Description: Generates an image using the meinahentai model.\n\n"
105
- "Command: /darksushimix\n"
106
- " • Description: Generates an image using the darksushimix model.\n\n"
107
- "Command: /anylora\n"
108
- " • Description: Generates an image using the anylora model.\n\n"
109
- "Command: /cetsumix\n"
110
- " • Description: Generates an image using the cetus-mix model.\n\n"
111
- "Command: /darkv2\n"
112
- " • Description: Generates an image using the darkv2 model.\n\n"
113
- "Command: /creative\n"
114
- " • Description: Generates an image using the creative model.",
115
- parse_mode=ParseMode.MARKDOWN,
116
- reply_markup=InlineKeyboardMarkup(
117
- [
118
- [
119
- InlineKeyboardButton("⇦ 𝘽𝘼𝘾𝙆", callback_data="ai_handler"),
120
- ],
121
- ],
122
- ),
123
- )
124
-
125
-
126
- def get_readable_time(seconds: int) -> str:
127
- count = 0
128
- ping_time = ""
129
- time_list = []
130
- time_suffix_list = ["s", "m", "h", "days"]
131
-
132
- while count < 4:
133
- count += 1
134
- remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)
135
- if seconds == 0 and remainder == 0:
136
- break
137
- time_list.append(int(result))
138
- seconds = int(remainder)
139
-
140
- for x in range(len(time_list)):
141
- time_list[x] = str(time_list[x]) + time_suffix_list[x]
142
- if len(time_list) == 4:
143
- ping_time += time_list.pop() + ", "
144
-
145
- time_list.reverse()
146
- ping_time += ":".join(time_list)
147
-
148
- return ping_time
149
-
150
-
151
- IMPORTED = {}
152
- MIGRATEABLE = []
153
- HELPABLE = {}
154
- STATS = []
155
- USER_INFO = []
156
- DATA_IMPORT = []
157
- DATA_EXPORT = []
158
- CHAT_SETTINGS = {}
159
- USER_SETTINGS = {}
160
-
161
- for module_name in ALL_MODULES:
162
- imported_module = importlib.import_module("Mikobot.plugins." + module_name)
163
- if not hasattr(imported_module, "__mod_name__"):
164
- imported_module.__mod_name__ = imported_module.__name__
165
-
166
- if imported_module.__mod_name__.lower() not in IMPORTED:
167
- IMPORTED[imported_module.__mod_name__.lower()] = imported_module
168
- else:
169
- raise Exception("Can't have two modules with the same name! Please change one")
170
-
171
- if hasattr(imported_module, "__help__") and imported_module.__help__:
172
- HELPABLE[imported_module.__mod_name__.lower()] = imported_module
173
-
174
- # Chats to migrate on chat_migrated events
175
- if hasattr(imported_module, "__migrate__"):
176
- MIGRATEABLE.append(imported_module)
177
-
178
- if hasattr(imported_module, "__stats__"):
179
- STATS.append(imported_module)
180
-
181
- if hasattr(imported_module, "__user_info__"):
182
- USER_INFO.append(imported_module)
183
-
184
- if hasattr(imported_module, "__import_data__"):
185
- DATA_IMPORT.append(imported_module)
186
-
187
- if hasattr(imported_module, "__export_data__"):
188
- DATA_EXPORT.append(imported_module)
189
-
190
- if hasattr(imported_module, "__chat_settings__"):
191
- CHAT_SETTINGS[imported_module.__mod_name__.lower()] = imported_module
192
-
193
- if hasattr(imported_module, "__user_settings__"):
194
- USER_SETTINGS[imported_module.__mod_name__.lower()] = imported_module
195
-
196
-
197
- # do not async
198
- async def send_help(chat_id, text, keyboard=None):
199
- if not keyboard:
200
- keyboard = InlineKeyboardMarkup(paginate_modules(0, HELPABLE, "help"))
201
- await dispatcher.bot.send_message(
202
- chat_id=chat_id,
203
- text=text,
204
- parse_mode=ParseMode.MARKDOWN,
205
- disable_web_page_preview=True,
206
- reply_markup=keyboard,
207
- )
208
-
209
-
210
- async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
211
- args = context.args
212
- message = update.effective_message
213
- uptime = get_readable_time((time.time() - StartTime))
214
- if update.effective_chat.type == "private":
215
- if len(args) >= 1:
216
- if args[0].lower() == "help":
217
- await send_help(update.effective_chat.id, HELP_STRINGS)
218
- elif args[0].lower().startswith("ghelp_"):
219
- mod = args[0].lower().split("_", 1)[1]
220
- if not HELPABLE.get(mod, False):
221
- return
222
- await send_help(
223
- update.effective_chat.id,
224
- HELPABLE[mod].__help__,
225
- InlineKeyboardMarkup(
226
- [[InlineKeyboardButton(text="◁", callback_data="help_back")]]
227
- ),
228
- )
229
-
230
- elif args[0].lower() == "markdownhelp":
231
- IMPORTED["exᴛʀᴀs"].markdown_help_sender(update)
232
- elif args[0].lower().startswith("stngs_"):
233
- match = re.match("stngs_(.*)", args[0].lower())
234
- chat = dispatcher.bot.getChat(match.group(1))
235
-
236
- if is_user_admin(chat, update.effective_user.id):
237
- send_settings(match.group(1), update.effective_user.id, False)
238
- else:
239
- send_settings(match.group(1), update.effective_user.id, True)
240
-
241
- elif args[0][1:].isdigit() and "rules" in IMPORTED:
242
- await IMPORTED["rules"].send_rules(update, args[0], from_pm=True)
243
-
244
- else:
245
- first_name = update.effective_user.first_name
246
- lol = await message.reply_photo(
247
- photo=str(choice(START_IMG)),
248
- caption=FIRST_PART_TEXT.format(escape_markdown(first_name)),
249
- parse_mode=ParseMode.MARKDOWN,
250
- )
251
- await asyncio.sleep(0.2)
252
- guu = await update.effective_message.reply_text("🐾")
253
- await asyncio.sleep(1.8)
254
- await guu.delete() # Await this line
255
- await update.effective_message.reply_text(
256
- PM_START_TEXT,
257
- reply_markup=InlineKeyboardMarkup(START_BTN),
258
- parse_mode=ParseMode.MARKDOWN,
259
- disable_web_page_preview=False,
260
- )
261
- else:
262
- await message.reply_photo(
263
- photo=str(choice(START_IMG)),
264
- reply_markup=InlineKeyboardMarkup(GROUP_START_BTN),
265
- caption="<b>I am Alive!</b>\n\n<b>Since​:</b> <code>{}</code>".format(
266
- uptime
267
- ),
268
- parse_mode=ParseMode.HTML,
269
- )
270
-
271
-
272
- async def error_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
273
- """Log the error and send a telegram message to notify the developer."""
274
- # Log the error before we do anything else, so we can see it even if something breaks.
275
- LOGGER.error(msg="Exception while handling an update:", exc_info=context.error)
276
-
277
- # traceback.format_exception returns the usual python message about an exception, but as a
278
- # list of strings rather than a single string, so we have to join them together.
279
- tb_list = traceback.format_exception(
280
- None, context.error, context.error.__traceback__
281
- )
282
- tb = "".join(tb_list)
283
-
284
- # Build the message with some markup and additional information about what happened.
285
- message = (
286
- "An exception was raised while handling an update\n"
287
- "<pre>update = {}</pre>\n\n"
288
- "<pre>{}</pre>"
289
- ).format(
290
- html.escape(json.dumps(update.to_dict(), indent=2, ensure_ascii=False)),
291
- html.escape(tb),
292
- )
293
-
294
- if len(message) >= 4096:
295
- message = message[:4096]
296
- # Finally, send the message
297
- await context.bot.send_message(
298
- chat_id=OWNER_ID, text=message, parse_mode=ParseMode.HTML
299
- )
300
-
301
-
302
- # for test purposes
303
- async def error_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
304
- error = context.error
305
- try:
306
- raise error
307
- except Forbidden:
308
- print("no nono1")
309
- print(error)
310
- # remove update.message.chat_id from conversation list
311
- except BadRequest:
312
- print("no nono2")
313
- print("BadRequest caught")
314
- print(error)
315
-
316
- # handle malformed requests - read more below!
317
- except TimedOut:
318
- print("no nono3")
319
- # handle slow connection problems
320
- except NetworkError:
321
- print("no nono4")
322
- # handle other connection problems
323
- except ChatMigrated as err:
324
- print("no nono5")
325
- print(err)
326
- # the chat_id of a group has changed, use e.new_chat_id instead
327
- except TelegramError:
328
- print(error)
329
- # handle all other telegram related errors
330
-
331
-
332
- async def help_button(update: Update, context: ContextTypes.DEFAULT_TYPE):
333
- query = update.callback_query
334
- mod_match = re.match(r"help_module\((.+?)\)", query.data)
335
- prev_match = re.match(r"help_prev\((.+?)\)", query.data)
336
- next_match = re.match(r"help_next\((.+?)\)", query.data)
337
- back_match = re.match(r"help_back", query.data)
338
-
339
- print(query.message.chat.id)
340
-
341
- try:
342
- if mod_match:
343
- module = mod_match.group(1)
344
- text = (
345
- "➲ *HELP SECTION OF* *{}* :\n".format(HELPABLE[module].__mod_name__)
346
- + HELPABLE[module].__help__
347
- )
348
- await query.message.edit_text(
349
- text=text,
350
- parse_mode=ParseMode.MARKDOWN,
351
- disable_web_page_preview=True,
352
- reply_markup=InlineKeyboardMarkup(
353
- [[InlineKeyboardButton(text="◁", callback_data="help_back")]]
354
- ),
355
- )
356
-
357
- elif prev_match:
358
- curr_page = int(prev_match.group(1))
359
- await query.message.edit_text(
360
- text=HELP_STRINGS,
361
- parse_mode=ParseMode.MARKDOWN,
362
- reply_markup=InlineKeyboardMarkup(
363
- paginate_modules(curr_page - 1, HELPABLE, "help")
364
- ),
365
- )
366
-
367
- elif next_match:
368
- next_page = int(next_match.group(1))
369
- await query.message.edit_text(
370
- text=HELP_STRINGS,
371
- parse_mode=ParseMode.MARKDOWN,
372
- reply_markup=InlineKeyboardMarkup(
373
- paginate_modules(next_page + 1, HELPABLE, "help")
374
- ),
375
- )
376
-
377
- elif back_match:
378
- await query.message.edit_text(
379
- text=HELP_STRINGS,
380
- parse_mode=ParseMode.MARKDOWN,
381
- reply_markup=InlineKeyboardMarkup(
382
- paginate_modules(0, HELPABLE, "help")
383
- ),
384
- )
385
-
386
- await context.bot.answer_callback_query(query.id)
387
-
388
- except BadRequest:
389
- pass
390
-
391
-
392
- async def stats_back(update: Update, context: ContextTypes.DEFAULT_TYPE):
393
- query = update.callback_query
394
- if query.data == "insider_":
395
- uptime = get_readable_time((time.time() - StartTime))
396
- cpu = psutil.cpu_percent(interval=0.5)
397
- mem = psutil.virtual_memory().percent
398
- disk = psutil.disk_usage("/").percent
399
- text = f"""
400
- 𝙎𝙮𝙨𝙩𝙚𝙢 𝙨𝙩𝙖𝙩𝙨@𝙔𝙖𝙚𝙈𝙞𝙠𝙤_𝙍𝙤𝙭𝙗𝙤𝙩
401
- ➖➖➖➖➖➖
402
- UPTIME ➼ {uptime}
403
- CPU ➼ {cpu}%
404
- RAM ➼ {mem}%
405
- DISK ➼ {disk}%
406
-
407
- PYTHON ➼ {PYTHON_VERSION}
408
-
409
- PTB ➼ {PTB_VERSION}
410
- TELETHON ➼ {TELETHON_VERSION}
411
- PYROGRAM ➼ {PYROGRAM_VERSION}
412
- """
413
- await query.answer(text=text, show_alert=True)
414
-
415
-
416
- async def gitsource_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
417
- query = update.callback_query
418
- await query.answer()
419
-
420
- if query.data == "git_source":
421
- source_link = "https://github.com/Infamous-Hydra/YaeMiko"
422
- message_text = (
423
- f"*Here is the link for the public source repo*:\n\n{source_link}"
424
- )
425
-
426
- # Adding the inline button
427
- keyboard = [[InlineKeyboardButton(text="◁", callback_data="Miko_back")]]
428
- reply_markup = InlineKeyboardMarkup(keyboard)
429
-
430
- await query.edit_message_text(
431
- message_text,
432
- parse_mode=ParseMode.MARKDOWN,
433
- disable_web_page_preview=False,
434
- reply_markup=reply_markup,
435
- )
436
-
437
-
438
- async def repo(update: Update, context: ContextTypes.DEFAULT_TYPE):
439
- source_link = "https://github.com/Infamous-Hydra/YaeMiko"
440
- message_text = f"*Here is the link for the public source repo*:\n\n{source_link}"
441
-
442
- await context.bot.send_message(
443
- chat_id=update.effective_chat.id,
444
- text=message_text,
445
- parse_mode=ParseMode.MARKDOWN,
446
- disable_web_page_preview=False,
447
- )
448
-
449
-
450
- async def Miko_about_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
451
- query = update.callback_query
452
- if query.data == "Miko_":
453
- uptime = get_readable_time((time.time() - StartTime))
454
- message_text = (
455
- f"➲ <b>Ai integration.</b>"
456
- f"\n➲ <b>Advance management capability.</b>"
457
- f"\n➲ <b>Anime bot functionality.</b>"
458
- f"\n\n<b>USERS</b> » {sql.num_users()}"
459
- f"\n<b>CHATS</b> » {sql.num_chats()}"
460
- f"\n\n<b>Click on the buttons below for getting help and info about</b> {BOT_NAME}."
461
- )
462
- await query.message.edit_text(
463
- text=message_text,
464
- disable_web_page_preview=True,
465
- parse_mode=ParseMode.HTML,
466
- reply_markup=InlineKeyboardMarkup(
467
- [
468
- [
469
- InlineKeyboardButton(
470
- text="ABOUT", callback_data="Miko_support"
471
- ),
472
- InlineKeyboardButton(text="COMMAND", callback_data="help_back"),
473
- ],
474
- [
475
- InlineKeyboardButton(text="INSIDER", callback_data="insider_"),
476
- ],
477
- [
478
- InlineKeyboardButton(text="◁", callback_data="Miko_back"),
479
- ],
480
- ]
481
- ),
482
- )
483
- elif query.data == "Miko_support":
484
- message_text = (
485
- "*Our bot leverages SQL, MongoDB, Telegram, MTProto for secure and efficient operations. It resides on a high-speed server, integrates numerous APIs, ensuring quick and versatile responses to user queries.*"
486
- f"\n\n*If you find any bug in {BOT_NAME} Please report it at the support chat.*"
487
- )
488
- await query.message.edit_text(
489
- text=message_text,
490
- parse_mode=ParseMode.MARKDOWN,
491
- disable_web_page_preview=True,
492
- reply_markup=InlineKeyboardMarkup(
493
- [
494
- [
495
- InlineKeyboardButton(
496
- text="SUPPORT", url=f"https://t.me/{SUPPORT_CHAT}"
497
- ),
498
- InlineKeyboardButton(
499
- text="DEVELOPER", url=f"tg://user?id={OWNER_ID}"
500
- ),
501
- ],
502
- [
503
- InlineKeyboardButton(text="◁", callback_data="Miko_"),
504
- ],
505
- ]
506
- ),
507
- )
508
- elif query.data == "Miko_back":
509
- first_name = update.effective_user.first_name
510
- await query.message.edit_text(
511
- PM_START_TEXT.format(escape_markdown(first_name), BOT_NAME),
512
- reply_markup=InlineKeyboardMarkup(START_BTN),
513
- parse_mode=ParseMode.MARKDOWN,
514
- disable_web_page_preview=True,
515
- )
516
-
517
-
518
- async def get_help(update: Update, context: ContextTypes.DEFAULT_TYPE):
519
- chat = update.effective_chat # type: Optional[Chat]
520
- args = update.effective_message.text.split(None, 1)
521
-
522
- # ONLY send help in PM
523
- if chat.type != chat.PRIVATE:
524
- if len(args) >= 2 and any(args[1].lower() == x for x in HELPABLE):
525
- module = args[1].lower()
526
- await update.effective_message.reply_text(
527
- f"Contact me in PM to get help of {module.capitalize()}",
528
- reply_markup=InlineKeyboardMarkup(
529
- [
530
- [
531
- InlineKeyboardButton(
532
- text="HELP",
533
- url="https://t.me/{}?start=ghelp_{}".format(
534
- context.bot.username, module
535
- ),
536
- )
537
- ]
538
- ]
539
- ),
540
- )
541
- return
542
- await update.effective_message.reply_text(
543
- "» Choose an option for getting help.",
544
- reply_markup=InlineKeyboardMarkup(
545
- [
546
- [
547
- InlineKeyboardButton(
548
- text="OPEN IN PM",
549
- url="https://t.me/{}?start=help".format(
550
- context.bot.username
551
- ),
552
- )
553
- ],
554
- [
555
- InlineKeyboardButton(
556
- text="OPEN HERE",
557
- callback_data="help_back",
558
- )
559
- ],
560
- ]
561
- ),
562
- )
563
- return
564
-
565
- elif len(args) >= 2 and any(args[1].lower() == x for x in HELPABLE):
566
- module = args[1].lower()
567
- text = (
568
- "Here is the available help for the *{}* module:\n".format(
569
- HELPABLE[module].__mod_name__
570
- )
571
- + HELPABLE[module].__help__
572
- )
573
- await send_help(
574
- chat.id,
575
- text,
576
- InlineKeyboardMarkup(
577
- [[InlineKeyboardButton(text="◁", callback_data="help_back")]]
578
- ),
579
- )
580
-
581
- else:
582
- await send_help(chat.id, HELP_STRINGS)
583
-
584
-
585
- async def send_settings(chat_id, user_id, user=False):
586
- if user:
587
- if USER_SETTINGS:
588
- settings = "\n\n".join(
589
- "*{}*:\n{}".format(mod.__mod_name__, mod.__user_settings__(user_id))
590
- for mod in USER_SETTINGS.values()
591
- )
592
- await dispatcher.bot.send_message(
593
- user_id,
594
- "These are your current settings:" + "\n\n" + settings,
595
- parse_mode=ParseMode.MARKDOWN,
596
- )
597
-
598
- else:
599
- await dispatcher.bot.send_message(
600
- user_id,
601
- "Seems like there aren't any user specific settings available :'(",
602
- parse_mode=ParseMode.MARKDOWN,
603
- )
604
- else:
605
- if CHAT_SETTINGS:
606
- chat_name = dispatcher.bot.getChat(chat_id).title
607
- await dispatcher.bot.send_message(
608
- user_id,
609
- text="Which module would you like to check {}'s settings for?".format(
610
- chat_name
611
- ),
612
- reply_markup=InlineKeyboardMarkup(
613
- paginate_modules(0, CHAT_SETTINGS, "stngs", chat=chat_id)
614
- ),
615
- )
616
- else:
617
- await dispatcher.bot.send_message(
618
- user_id,
619
- "Seems like there aren't any chat settings available :'(\nSend this "
620
- "in a group chat you're admin in to find its current settings!",
621
- parse_mode=ParseMode.MARKDOWN,
622
- )
623
-
624
-
625
- async def settings_button(update: Update, context: ContextTypes.DEFAULT_TYPE):
626
- query = update.callback_query
627
- user = update.effective_user
628
- bot = context.bot
629
- mod_match = re.match(r"stngs_module\((.+?),(.+?)\)", query.data)
630
- prev_match = re.match(r"stngs_prev\((.+?),(.+?)\)", query.data)
631
- next_match = re.match(r"stngs_next\((.+?),(.+?)\)", query.data)
632
- back_match = re.match(r"stngs_back\((.+?)\)", query.data)
633
- try:
634
- if mod_match:
635
- chat_id = mod_match.group(1)
636
- module = mod_match.group(2)
637
- chat = bot.get_chat(chat_id)
638
- text = "*{}* has the following settings for the *{}* module:\n\n".format(
639
- escape_markdown(chat.title), CHAT_SETTINGS[module].__mod_name__
640
- ) + CHAT_SETTINGS[module].__chat_settings__(chat_id, user.id)
641
- await query.message.reply_text(
642
- text=text,
643
- parse_mode=ParseMode.MARKDOWN,
644
- reply_markup=InlineKeyboardMarkup(
645
- [
646
- [
647
- InlineKeyboardButton(
648
- text="◁",
649
- callback_data="stngs_back({})".format(chat_id),
650
- )
651
- ]
652
- ]
653
- ),
654
- )
655
-
656
- elif prev_match:
657
- chat_id = prev_match.group(1)
658
- curr_page = int(prev_match.group(2))
659
- chat = bot.get_chat(chat_id)
660
- await query.message.reply_text(
661
- "Hi there! There are quite a few settings for {} - go ahead and pick what "
662
- "you're interested in.".format(chat.title),
663
- reply_markup=InlineKeyboardMarkup(
664
- paginate_modules(
665
- curr_page - 1, CHAT_SETTINGS, "stngs", chat=chat_id
666
- )
667
- ),
668
- )
669
-
670
- elif next_match:
671
- chat_id = next_match.group(1)
672
- next_page = int(next_match.group(2))
673
- chat = bot.get_chat(chat_id)
674
- await query.message.reply_text(
675
- "Hi there! There are quite a few settings for {} - go ahead and pick what "
676
- "you're interested in.".format(chat.title),
677
- reply_markup=InlineKeyboardMarkup(
678
- paginate_modules(
679
- next_page + 1, CHAT_SETTINGS, "stngs", chat=chat_id
680
- )
681
- ),
682
- )
683
-
684
- elif back_match:
685
- chat_id = back_match.group(1)
686
- chat = bot.get_chat(chat_id)
687
- await query.message.reply_text(
688
- text="Hi there! There are quite a few settings for {} - go ahead and pick what "
689
- "you're interested in.".format(escape_markdown(chat.title)),
690
- parse_mode=ParseMode.MARKDOWN,
691
- reply_markup=InlineKeyboardMarkup(
692
- paginate_modules(0, CHAT_SETTINGS, "stngs", chat=chat_id)
693
- ),
694
- )
695
-
696
- # ensure no spinny white circle
697
- bot.answer_callback_query(query.id)
698
- await query.message.delete()
699
- except BadRequest as excp:
700
- if excp.message not in [
701
- "Message is not modified",
702
- "Query_id_invalid",
703
- "Message can't be deleted",
704
- ]:
705
- LOGGER.exception("Exception in settings buttons. %s", str(query.data))
706
-
707
-
708
- async def get_settings(update: Update, context: ContextTypes.DEFAULT_TYPE):
709
- chat = update.effective_chat # type: Optional[Chat]
710
- user = update.effective_user # type: Optional[User]
711
- msg = update.effective_message # type: Optional[Message]
712
-
713
- # ONLY send settings in PM
714
- if chat.type != chat.PRIVATE:
715
- if is_user_admin(chat, user.id):
716
- text = "Click here to get this chat's settings, as well as yours."
717
- await msg.reply_text(
718
- text,
719
- reply_markup=InlineKeyboardMarkup(
720
- [
721
- [
722
- InlineKeyboardButton(
723
- text="SETTINGS",
724
- url="t.me/{}?start=stngs_{}".format(
725
- context.bot.username, chat.id
726
- ),
727
- )
728
- ]
729
- ]
730
- ),
731
- )
732
- else:
733
- text = "Click here to check your settings."
734
-
735
- else:
736
- await send_settings(chat.id, user.id, True)
737
-
738
-
739
- async def migrate_chats(update: Update, context: ContextTypes.DEFAULT_TYPE):
740
- msg = update.effective_message # type: Optional[Message]
741
- if msg.migrate_to_chat_id:
742
- old_chat = update.effective_chat.id
743
- new_chat = msg.migrate_to_chat_id
744
- elif msg.migrate_from_chat_id:
745
- old_chat = msg.migrate_from_chat_id
746
- new_chat = update.effective_chat.id
747
- else:
748
- return
749
-
750
- LOGGER.info("Migrating from %s, ᴛᴏ %s", str(old_chat), str(new_chat))
751
- for mod in MIGRATEABLE:
752
- with contextlib.suppress(KeyError, AttributeError):
753
- mod.__migrate__(old_chat, new_chat)
754
-
755
- LOGGER.info("Successfully Migrated!")
756
- raise ApplicationHandlerStop
757
-
758
-
759
- # <=======================================================================================================>
760
-
761
-
762
- # <=================================================== MAIN ====================================================>
763
- def main():
764
- function(CommandHandler("start", start))
765
-
766
- function(CommandHandler("help", get_help))
767
- function(CallbackQueryHandler(help_button, pattern=r"help_.*"))
768
-
769
- function(CommandHandler("settings", get_settings))
770
- function(CallbackQueryHandler(settings_button, pattern=r"stngs_"))
771
- function(CommandHandler("repo", repo))
772
-
773
- function(CallbackQueryHandler(Miko_about_callback, pattern=r"Miko_"))
774
- function(CallbackQueryHandler(gitsource_callback, pattern=r"git_source"))
775
- function(CallbackQueryHandler(stats_back, pattern=r"insider_"))
776
- function(CallbackQueryHandler(ai_handler_callback, pattern=r"ai_handler"))
777
- function(CallbackQueryHandler(more_ai_handler_callback, pattern=r"more_ai_handler"))
778
- function(MessageHandler(filters.StatusUpdate.MIGRATE, migrate_chats))
779
-
780
- dispatcher.add_error_handler(error_callback)
781
-
782
- LOGGER.info("Mikobot is starting >> Using long polling.")
783
- dispatcher.run_polling(timeout=15, drop_pending_updates=True)
784
-
785
-
786
- if __name__ == "__main__":
787
- try:
788
- LOGGER.info("Successfully loaded modules: " + str(ALL_MODULES))
789
- tbot.start(bot_token=TOKEN)
790
- app.start()
791
- main()
792
- except KeyboardInterrupt:
793
- pass
794
- except Exception:
795
- err = traceback.format_exc()
796
- LOGGER.info(err)
797
- finally:
798
- try:
799
- if loop.is_running():
800
- loop.stop()
801
- finally:
802
- loop.close()
803
- LOGGER.info(
804
- "------------------------ Stopped Services ------------------------"
805
- )
806
- # <==================================================== END ===================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/events.py DELETED
@@ -1,70 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from telethon import events
3
-
4
- from Mikobot import tbot
5
-
6
-
7
- # <============================================== FUNCTIONS =========================================================>
8
- def register(**args):
9
- """Registers a new message."""
10
- pattern = args.get("pattern")
11
-
12
- r_pattern = r"^[/!]"
13
-
14
- if pattern is not None and not pattern.startswith("(?i)"):
15
- args["pattern"] = f"(?i){pattern}"
16
-
17
- args["pattern"] = pattern.replace("^/", r_pattern, 1)
18
-
19
- def decorator(func):
20
- tbot.add_event_handler(func, events.NewMessage(**args))
21
- return func
22
-
23
- return decorator
24
-
25
-
26
- def chataction(**args):
27
- """Registers chat actions."""
28
-
29
- def decorator(func):
30
- tbot.add_event_handler(func, events.ChatAction(**args))
31
- return func
32
-
33
- return decorator
34
-
35
-
36
- def userupdate(**args):
37
- """Registers user updates."""
38
-
39
- def decorator(func):
40
- tbot.add_event_handler(func, events.UserUpdate(**args))
41
- return func
42
-
43
- return decorator
44
-
45
-
46
- def inlinequery(**args):
47
- """Registers inline query."""
48
- pattern = args.get("pattern")
49
-
50
- if pattern is not None and not pattern.startswith("(?i)"):
51
- args["pattern"] = f"(?i){pattern}"
52
-
53
- def decorator(func):
54
- tbot.add_event_handler(func, events.InlineQuery(**args))
55
- return func
56
-
57
- return decorator
58
-
59
-
60
- def callbackquery(**args):
61
- """Registers inline query."""
62
-
63
- def decorator(func):
64
- tbot.add_event_handler(func, events.CallbackQuery(**args))
65
- return func
66
-
67
- return decorator
68
-
69
-
70
- # <==================================================== END ===================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/__init__.py DELETED
@@ -1,43 +0,0 @@
1
- from Mikobot import LOAD, LOGGER, NO_LOAD
2
-
3
-
4
- def __list_all_modules():
5
- import glob
6
- from os.path import basename, dirname, isfile
7
-
8
- # This generates a list of modules in this folder for the * in __main__ to work.
9
- mod_paths = glob.glob(dirname(__file__) + "/*.py")
10
- all_modules = [
11
- basename(f)[:-3]
12
- for f in mod_paths
13
- if isfile(f) and f.endswith(".py") and not f.endswith("__init__.py")
14
- ]
15
-
16
- if LOAD or NO_LOAD:
17
- to_load = LOAD
18
- if to_load:
19
- if not all(
20
- any(mod == module_name for module_name in all_modules)
21
- for mod in to_load
22
- ):
23
- LOGGER.error("Invalid loadorder names, Quitting...")
24
- quit(1)
25
-
26
- all_modules = sorted(set(all_modules) - set(to_load))
27
- to_load = list(all_modules) + to_load
28
-
29
- else:
30
- to_load = all_modules
31
-
32
- if NO_LOAD:
33
- LOGGER.info("Not loading: {}".format(NO_LOAD))
34
- return [item for item in to_load if item not in NO_LOAD]
35
-
36
- return to_load
37
-
38
- return all_modules
39
-
40
-
41
- ALL_MODULES = __list_all_modules()
42
- LOGGER.info("Modules to load: %s", str(ALL_MODULES))
43
- __all__ = ALL_MODULES + ["ALL_MODULES"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/admin.py DELETED
@@ -1,1148 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import html
3
-
4
- from telegram import (
5
- ChatMemberAdministrator,
6
- InlineKeyboardButton,
7
- InlineKeyboardMarkup,
8
- Update,
9
- )
10
- from telegram.constants import ChatID, ChatMemberStatus, ChatType, ParseMode
11
- from telegram.error import BadRequest
12
- from telegram.ext import CallbackQueryHandler, CommandHandler, ContextTypes, filters
13
- from telegram.helpers import mention_html
14
-
15
- from Mikobot import DRAGONS, function
16
- from Mikobot.plugins.disable import DisableAbleCommandHandler
17
- from Mikobot.plugins.helper_funcs.alternate import send_message
18
- from Mikobot.plugins.helper_funcs.chat_status import (
19
- ADMIN_CACHE,
20
- check_admin,
21
- connection_status,
22
- )
23
- from Mikobot.plugins.helper_funcs.extraction import extract_user, extract_user_and_text
24
- from Mikobot.plugins.log_channel import loggable
25
-
26
- # <=======================================================================================================>
27
-
28
-
29
- # <================================================ FUNCTION =======================================================>
30
- @connection_status
31
- @loggable
32
- @check_admin(permission="can_promote_members", is_both=True)
33
- async def promote(update: Update, context: ContextTypes.DEFAULT_TYPE):
34
- bot = context.bot
35
- args = context.args
36
-
37
- message = update.effective_message
38
- chat = update.effective_chat
39
- user = update.effective_user
40
-
41
- user_id = await extract_user(message, context, args)
42
- await chat.get_member(user.id)
43
-
44
- if message.from_user.id == ChatID.ANONYMOUS_ADMIN:
45
- await message.reply_text(
46
- text="You are an anonymous admin.",
47
- reply_markup=InlineKeyboardMarkup(
48
- [
49
- [
50
- InlineKeyboardButton(
51
- text="Click to promote admin.",
52
- callback_data=f"admin_=promote={user_id}",
53
- ),
54
- ],
55
- ],
56
- ),
57
- )
58
-
59
- return
60
-
61
- if not user_id:
62
- await message.reply_text(
63
- "You don't seem to be referring to a user, or the ID specified is incorrect.",
64
- )
65
- return
66
-
67
- try:
68
- user_member = await chat.get_member(user_id)
69
- except:
70
- return
71
-
72
- if (
73
- user_member.status == ChatMemberStatus.ADMINISTRATOR
74
- or user_member.status == ChatMemberStatus.OWNER
75
- ):
76
- await message.reply_text("How can I promote someone who is already an admin?")
77
- return
78
-
79
- if user_id == bot.id:
80
- await message.reply_text(
81
- "I can't promote myself! Get an admin to do it for me."
82
- )
83
- return
84
-
85
- # Set the same permissions as the bot - the bot can't assign higher permissions than itself!
86
- bot_member = await chat.get_member(bot.id)
87
-
88
- if isinstance(bot_member, ChatMemberAdministrator):
89
- try:
90
- await bot.promoteChatMember(
91
- chat.id,
92
- user_id,
93
- can_change_info=bot_member.can_change_info,
94
- can_post_messages=bot_member.can_post_messages,
95
- can_edit_messages=bot_member.can_edit_messages,
96
- can_delete_messages=bot_member.can_delete_messages,
97
- can_invite_users=bot_member.can_invite_users,
98
- can_restrict_members=bot_member.can_restrict_members,
99
- can_pin_messages=bot_member.can_pin_messages,
100
- can_manage_chat=bot_member.can_manage_chat,
101
- can_manage_video_chats=bot_member.can_manage_video_chats,
102
- can_manage_topics=bot_member.can_manage_topics,
103
- )
104
- except BadRequest as err:
105
- if err.message == "User_not_mutual_contact":
106
- await message.reply_text(
107
- "I can't promote someone who isn't in the group."
108
- )
109
- else:
110
- await message.reply_text("An error occurred while promoting.")
111
- return
112
-
113
- await bot.sendMessage(
114
- chat.id,
115
- f"Successfully promoted {user_member.user.first_name or user_id}!",
116
- parse_mode=ParseMode.HTML,
117
- message_thread_id=message.message_thread_id if chat.is_forum else None,
118
- )
119
-
120
- log_message = (
121
- f"{html.escape(chat.title)}:\n"
122
- "#Promoted\n"
123
- f"ADMIN: {mention_html(user.id, user.first_name)}\n"
124
- f"USER: {mention_html(user_member.user.id, user_member.user.first_name)}"
125
- )
126
-
127
- return log_message
128
-
129
-
130
- @connection_status
131
- @loggable
132
- @check_admin(permission="can_promote_members", is_both=True)
133
- async def fullpromote(update: Update, context: ContextTypes.DEFAULT_TYPE):
134
- bot = context.bot
135
- args = context.args
136
-
137
- message = update.effective_message
138
- chat = update.effective_chat
139
- user = update.effective_user
140
-
141
- user_id = await extract_user(message, context, args)
142
- await chat.get_member(user.id)
143
-
144
- if message.from_user.id == ChatID.ANONYMOUS_ADMIN:
145
- await message.reply_text(
146
- text="You are an anonymous admin.",
147
- reply_markup=InlineKeyboardMarkup(
148
- [
149
- [
150
- InlineKeyboardButton(
151
- text="Click to promote admin.",
152
- callback_data=f"admin_=promote={user_id}",
153
- ),
154
- ],
155
- ],
156
- ),
157
- )
158
-
159
- return
160
-
161
- if not user_id:
162
- await message.reply_text(
163
- "You don't seem to be referring to a user, or the ID specified is incorrect.",
164
- )
165
- return
166
-
167
- try:
168
- user_member = await chat.get_member(user_id)
169
- except:
170
- return
171
-
172
- if (
173
- user_member.status == ChatMemberStatus.ADMINISTRATOR
174
- or user_member.status == ChatMemberStatus.OWNER
175
- ):
176
- await message.reply_text("How can I promote someone who is already an admin?")
177
- return
178
-
179
- if user_id == bot.id:
180
- await message.reply_text(
181
- "I can't promote myself! Get an admin to do it for me."
182
- )
183
- return
184
-
185
- # Set the same permissions as the bot - the bot can't assign higher perms than itself!
186
- bot_member = await chat.get_member(bot.id)
187
-
188
- if isinstance(bot_member, ChatMemberAdministrator):
189
- try:
190
- await bot.promoteChatMember(
191
- chat.id,
192
- user_id,
193
- can_change_info=bot_member.can_change_info,
194
- can_post_messages=bot_member.can_post_messages,
195
- can_edit_messages=bot_member.can_edit_messages,
196
- can_delete_messages=bot_member.can_delete_messages,
197
- can_invite_users=bot_member.can_invite_users,
198
- can_promote_members=bot_member.can_promote_members,
199
- can_restrict_members=bot_member.can_restrict_members,
200
- can_pin_messages=bot_member.can_pin_messages,
201
- can_manage_chat=bot_member.can_manage_chat,
202
- can_manage_video_chats=bot_member.can_manage_video_chats,
203
- can_manage_topics=bot_member.can_manage_topics,
204
- )
205
- except BadRequest as err:
206
- if err.message == "User_not_mutual_contact":
207
- await message.reply_text(
208
- "I can't promote someone who isn't in the group."
209
- )
210
- else:
211
- await message.reply_text("An error occurred while promoting.")
212
- return
213
-
214
- await bot.sendMessage(
215
- chat.id,
216
- f"Successfully promoted {user_member.user.first_name or user_id}!",
217
- parse_mode=ParseMode.HTML,
218
- message_thread_id=message.message_thread_id if chat.is_forum else None,
219
- )
220
-
221
- log_message = (
222
- f"{html.escape(chat.title)}:\n"
223
- "#FULLPROMOTED\n"
224
- f"ADMIN: {mention_html(user.id, user.first_name)}\n"
225
- f"USER: {mention_html(user_member.user.id, user_member.user.first_name)}"
226
- )
227
-
228
- return log_message
229
-
230
-
231
- @connection_status
232
- @loggable
233
- @check_admin(permission="can_promote_members", is_both=True)
234
- async def demote(update: Update, context: ContextTypes.DEFAULT_TYPE):
235
- bot = context.bot
236
- args = context.args
237
-
238
- chat = update.effective_chat
239
- message = update.effective_message
240
- user = update.effective_user
241
-
242
- user_id = await extract_user(message, context, args)
243
- await chat.get_member(user.id)
244
-
245
- if message.from_user.id == ChatID.ANONYMOUS_ADMIN:
246
- await message.reply_text(
247
- text="You are an anonymous admin.",
248
- reply_markup=InlineKeyboardMarkup(
249
- [
250
- [
251
- InlineKeyboardButton(
252
- text="Click to prove admin.",
253
- callback_data=f"admin_=demote={user_id}",
254
- ),
255
- ],
256
- ],
257
- ),
258
- )
259
-
260
- return
261
-
262
- if not user_id:
263
- await message.reply_text(
264
- "You don't seem to be referring to a user or the id specified is incorrect..",
265
- )
266
- return
267
-
268
- try:
269
- user_member = await chat.get_member(user_id)
270
- except:
271
- return
272
-
273
- if user_member.status == ChatMemberStatus.OWNER:
274
- await message.reply_text(
275
- "This person created the chat, How could i demote him?"
276
- )
277
- return
278
-
279
- if not user_member.status == ChatMemberStatus.ADMINISTRATOR:
280
- await message.reply_text("Can't demote who isn't promoted!")
281
- return
282
-
283
- if user_id == bot.id:
284
- await message.reply_text("I can't demote myself!.")
285
- return
286
-
287
- try:
288
- await bot.promote_chat_member(
289
- chat.id,
290
- user_id,
291
- can_change_info=False,
292
- can_post_messages=False,
293
- can_edit_messages=False,
294
- can_delete_messages=False,
295
- can_invite_users=False,
296
- can_restrict_members=False,
297
- can_pin_messages=False,
298
- can_promote_members=False,
299
- can_manage_chat=False,
300
- can_manage_video_chats=False,
301
- can_manage_topics=False,
302
- )
303
-
304
- await bot.sendMessage(
305
- chat.id,
306
- f"SUCCESSFULLY DEMOTED <b>{user_member.user.first_name or user_id}</b>!",
307
- parse_mode=ParseMode.HTML,
308
- message_thread_id=message.message_thread_id if chat.is_forum else None,
309
- )
310
-
311
- log_message = (
312
- f"<b>{html.escape(chat.title)}:</b>\n"
313
- f"#DEMOTED\n"
314
- f"<b>ADMIN:</b> {mention_html(user.id, user.first_name)}\n"
315
- f"<b>USER:</b> {mention_html(user_member.user.id, user_member.user.first_name)}"
316
- )
317
-
318
- return log_message
319
- except BadRequest:
320
- await message.reply_text(
321
- "Could not demote. I might not be admin or the admin status was appointed by another"
322
- "Its a User, So I can't act upon them!",
323
- )
324
- raise
325
-
326
-
327
- @check_admin(is_user=True)
328
- async def refresh_admin(update, _):
329
- try:
330
- ADMIN_CACHE.pop(update.effective_chat.id)
331
- except KeyError:
332
- pass
333
-
334
- await update.effective_message.reply_text("Admins cache refreshed!")
335
-
336
-
337
- @connection_status
338
- @check_admin(permission="can_promote_members", is_both=True)
339
- async def set_title(update: Update, context: ContextTypes.DEFAULT_TYPE):
340
- bot = context.bot
341
- args = context.args
342
-
343
- chat = update.effective_chat
344
- message = update.effective_message
345
-
346
- user_id, title = await extract_user_and_text(message, context, args)
347
-
348
- if message.from_user.id == 1087968824:
349
- await message.reply_text(
350
- text="You are an anonymous admin.",
351
- reply_markup=InlineKeyboardMarkup(
352
- [
353
- [
354
- InlineKeyboardButton(
355
- text="Click to prove admin.",
356
- callback_data=f"admin_=title={user_id}={title}",
357
- ),
358
- ],
359
- ],
360
- ),
361
- )
362
-
363
- return
364
-
365
- try:
366
- user_member = await chat.get_member(user_id)
367
- except:
368
- return
369
-
370
- if not user_id:
371
- await message.reply_text(
372
- "You don't seem to be referring to a user or the ID specified is incorrect..",
373
- )
374
- return
375
-
376
- if user_member.status == ChatMemberStatus.OWNER:
377
- await message.reply_text(
378
- "This person CREATED the chat, how can I set custom title for him?",
379
- )
380
- return
381
-
382
- if user_member.status != ChatMemberStatus.ADMINISTRATOR:
383
- await message.reply_text(
384
- "Can't set title for non-admins!\nPromote them first to set custom title!",
385
- )
386
- return
387
-
388
- if user_id == bot.id:
389
- await message.reply_text(
390
- "I can't set my own title myself! Get the one who made me admin to do it for me.",
391
- )
392
- return
393
-
394
- if not title:
395
- await message.reply_text("Setting a blank title doesn't do anything!")
396
- return
397
-
398
- if len(title) > 16:
399
- await message.reply_text(
400
- "The title length is longer than 16 characters.\nTruncating it to 16 characters.",
401
- )
402
-
403
- try:
404
- await bot.setChatAdministratorCustomTitle(chat.id, user_id, title)
405
- except BadRequest:
406
- await message.reply_text(
407
- "Either they aren't promoted by me or you set a title text that is impossible to set."
408
- )
409
- raise
410
-
411
- await bot.sendMessage(
412
- chat.id,
413
- f"Successfully set title for <code>{user_member.user.first_name or user_id}</code> "
414
- f"to <code>{html.escape(title[:16])}</code>!",
415
- parse_mode=ParseMode.HTML,
416
- message_thread_id=message.message_thread_id if chat.is_forum else None,
417
- )
418
-
419
-
420
- @loggable
421
- @check_admin(permission="can_pin_messages", is_both=True)
422
- async def pin(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
423
- bot = context.bot
424
- args = context.args
425
-
426
- user = update.effective_user
427
- chat = update.effective_chat
428
- message = update.effective_message
429
-
430
- is_group = chat.type != "private" and chat.type != "channel"
431
- prev_message = update.effective_message.reply_to_message
432
-
433
- is_silent = True
434
- if len(args) >= 1:
435
- is_silent = not (
436
- args[0].lower() == "notify"
437
- or args[0].lower() == "loud"
438
- or args[0].lower() == "violent"
439
- )
440
-
441
- if not prev_message:
442
- await message.reply_text("Please reply to message which you want to pin.")
443
- return
444
-
445
- if message.from_user.id == 1087968824:
446
- await message.reply_text(
447
- text="You are an anonymous admin.",
448
- reply_markup=InlineKeyboardMarkup(
449
- [
450
- [
451
- InlineKeyboardButton(
452
- text="Click to prove admin.",
453
- callback_data=f"admin_=pin={prev_message.message_id}={is_silent}",
454
- ),
455
- ],
456
- ],
457
- ),
458
- )
459
-
460
- return
461
-
462
- if prev_message and is_group:
463
- try:
464
- await bot.pinChatMessage(
465
- chat.id,
466
- prev_message.message_id,
467
- disable_notification=is_silent,
468
- )
469
- except BadRequest as excp:
470
- if excp.message == "Chat_not_modified":
471
- pass
472
- else:
473
- raise
474
- log_message = (
475
- f"{chat.title}:\n"
476
- "#PINNED\n"
477
- f"Admin: {mention_html(user.id, user.first_name)}"
478
- )
479
-
480
- return log_message
481
-
482
-
483
- @loggable
484
- @check_admin(permission="can_pin_messages", is_both=True)
485
- async def unpin(update: Update, context: ContextTypes.DEFAULT_TYPE):
486
- bot = context.bot
487
- chat = update.effective_chat
488
- user = update.effective_user
489
- message = update.effective_message
490
-
491
- if message.from_user.id == 1087968824:
492
- await message.reply_text(
493
- text="You are an anonymous admin.",
494
- reply_markup=InlineKeyboardMarkup(
495
- [
496
- [
497
- InlineKeyboardButton(
498
- text="Click to prove Admin.",
499
- callback_data=f"admin_=unpin",
500
- ),
501
- ],
502
- ],
503
- ),
504
- )
505
-
506
- return
507
-
508
- try:
509
- await bot.unpinChatMessage(chat.id)
510
- except BadRequest as excp:
511
- if excp.message == "Chat_not_modified":
512
- pass
513
- elif excp.message == "Message to unpin not found":
514
- await message.reply_text("No pinned message found")
515
- return
516
- else:
517
- raise
518
-
519
- log_message = (
520
- f"{chat.title}:\n"
521
- "#UNPINNED\n"
522
- f"Admin: {mention_html(user.id, user.first_name)}"
523
- )
524
-
525
- return log_message
526
-
527
-
528
- @loggable
529
- @check_admin(permission="can_pin_messages", is_both=True)
530
- async def unpinall(update: Update, context: ContextTypes.DEFAULT_TYPE):
531
- bot = context.bot
532
- chat = update.effective_chat
533
- user = update.effective_user
534
- message = update.effective_message
535
- admin_member = await chat.get_member(user.id)
536
-
537
- if message.from_user.id == 1087968824:
538
- await message.reply_text(
539
- text="You are an anonymous admin.",
540
- reply_markup=InlineKeyboardMarkup(
541
- [
542
- [
543
- InlineKeyboardButton(
544
- text="Click to prove admin.",
545
- callback_data=f"admin_=unpinall",
546
- ),
547
- ],
548
- ],
549
- ),
550
- )
551
-
552
- return
553
- elif not admin_member.status == ChatMemberStatus.OWNER and user.id not in DRAGONS:
554
- await message.reply_text("Only chat OWNER can unpin all messages.")
555
- return
556
-
557
- try:
558
- if chat.is_forum:
559
- await bot.unpin_all_forum_topic_messages(chat.id, message.message_thread_id)
560
- else:
561
- await bot.unpin_all_chat_messages(chat.id)
562
- except BadRequest as excp:
563
- if excp.message == "Chat_not_modified":
564
- pass
565
- else:
566
- raise
567
-
568
- log_message = (
569
- f"{chat.title}:\n"
570
- "#UNPINNED_ALL\n"
571
- f"Admin: {mention_html(user.id, user.first_name)}"
572
- )
573
-
574
- return log_message
575
-
576
-
577
- @connection_status
578
- @check_admin(permission="can_invite_users", is_bot=True)
579
- async def invite(update: Update, context: ContextTypes.DEFAULT_TYPE):
580
- bot = context.bot
581
- chat = update.effective_chat
582
-
583
- if chat.username:
584
- await update.effective_message.reply_text(f"https://t.me/{chat.username}")
585
- elif chat.type in [ChatType.SUPERGROUP, ChatType.CHANNEL]:
586
- bot_member = await chat.get_member(bot.id)
587
- if (
588
- bot_member.can_invite_users
589
- if isinstance(bot_member, ChatMemberAdministrator)
590
- else None
591
- ):
592
- invitelink = await bot.exportChatInviteLink(chat.id)
593
- await update.effective_message.reply_text(invitelink)
594
- else:
595
- await update.effective_message.reply_text(
596
- "I don't have access to the invite link, try changing my permissions!",
597
- )
598
- else:
599
- await update.effective_message.reply_text(
600
- "I can only give you invite links for supergroups and channels, sorry!",
601
- )
602
-
603
-
604
- @connection_status
605
- async def adminlist(update: Update, context: ContextTypes.DEFAULT_TYPE):
606
- chat = update.effective_chat # type: Optional[Chat]
607
- user = update.effective_user # type: Optional[User]
608
- args = context.args
609
- bot = context.bot
610
- if update.effective_message.chat.type == "private":
611
- await send_message(
612
- update.effective_message, "This command only works in Groups."
613
- )
614
- return
615
- chat = update.effective_chat
616
- chat_id = update.effective_chat.id
617
- chat_name = update.effective_message.chat.title
618
- try:
619
- msg = await update.effective_message.reply_text(
620
- "Fetching group admins...", parse_mode=ParseMode.HTML
621
- )
622
- except BadRequest:
623
- msg = await update.effective_message.reply_text(
624
- "Fetching group admins...", quote=False, parse_mode=ParseMode.HTML
625
- )
626
- administrators = await bot.get_chat_administrators(chat_id)
627
- administrators_list = list(administrators) # Convert to a list
628
- text = "「 𝗔𝗗𝗠𝗜𝗡𝗦 𝗜𝗡 <b>{}</b>:".format(html.escape(update.effective_chat.title))
629
- bot_admin_list = []
630
- for admin in administrators_list:
631
- user = admin.user
632
- status = admin.status
633
- custom_title = admin.custom_title
634
- if user.first_name == "":
635
- name = "☠ Deleted Account"
636
- else:
637
- name = "{}".format(
638
- mention_html(
639
- user.id, html.escape(user.first_name + " " + (user.last_name or ""))
640
- )
641
- )
642
- if user.is_bot:
643
- bot_admin_list.append(name)
644
- administrators_list.remove(admin)
645
- continue
646
- if status == "creator":
647
- text += "\n\n 👑 <b>Creator:</b>"
648
- text += "\n<code> ╰─➽ </code>{}\n".format(name)
649
- if custom_title:
650
- text += f"<code> ┗━ {html.escape(custom_title)}</code>\n"
651
- text += "\n🚓 <b>Admins:</b>"
652
- custom_admin_list = {}
653
- normal_admin_list = []
654
- for admin in administrators_list:
655
- user = admin.user
656
- status = admin.status
657
- custom_title = admin.custom_title
658
- if user.first_name == "":
659
- name = "☠ Deleted Account"
660
- else:
661
- name = "{}".format(
662
- mention_html(
663
- user.id, html.escape(user.first_name + " " + (user.last_name or ""))
664
- )
665
- )
666
- if status == "administrator":
667
- if custom_title:
668
- try:
669
- custom_admin_list[custom_title].append(name)
670
- except KeyError:
671
- custom_admin_list.update({custom_title: [name]})
672
- else:
673
- normal_admin_list.append(name)
674
- for admin in normal_admin_list:
675
- text += "\n<code> ╰─➽ </code>{}".format(admin)
676
- for admin_group in custom_admin_list.copy():
677
- if len(custom_admin_list[admin_group]) == 1:
678
- text += "\n<code> ╰─➽ </code>{} | <code>{}</code>".format(
679
- custom_admin_list[admin_group][0], html.escape(admin_group)
680
- )
681
- custom_admin_list.pop(admin_group)
682
- text += "\n"
683
- for admin_group in custom_admin_list:
684
- text += "\n🚨 <code>{}</code>".format(admin_group)
685
- for admin in custom_admin_list[admin_group]:
686
- text += "\n<code> ╰─➽ </code>{}".format(admin)
687
- text += "\n"
688
- text += "\n🤖 <b>Bots:</b>"
689
- for each_bot in bot_admin_list:
690
- text += "\n<code> ╰─➽ </code>{}".format(each_bot)
691
- try:
692
- await msg.edit_text(text, parse_mode=ParseMode.HTML)
693
- except BadRequest: # if the original message is deleted
694
- return
695
-
696
-
697
- @loggable
698
- async def admin_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
699
- query = update.callback_query
700
- bot = context.bot
701
- message = update.effective_message
702
- chat = update.effective_chat
703
- admin_user = query.from_user
704
-
705
- splitter = query.data.replace("admin_", "").split("=")
706
-
707
- if splitter[1] == "promote":
708
- promoter = await chat.get_member(admin_user.id)
709
-
710
- if (
711
- not (
712
- promoter.can_promote_members
713
- if isinstance(promoter, ChatMemberAdministrator)
714
- else None or promoter.status == ChatMemberStatus.OWNER
715
- )
716
- and admin_user.id not in DRAGONS
717
- ):
718
- await query.answer(
719
- "You don't have the necessary rights to do that!", show_alert=True
720
- )
721
- return
722
-
723
- try:
724
- user_id = int(splitter[2])
725
- except ValueError:
726
- user_id = splitter[2]
727
- await message.edit_text(
728
- "You don't seem to be referring to a user or the ID specified is incorrect..."
729
- )
730
- return
731
-
732
- try:
733
- user_member = await chat.get_member(user_id)
734
- except:
735
- return
736
-
737
- if (
738
- user_member.status == ChatMemberStatus.ADMINISTRATOR
739
- or user_member.status == ChatMemberStatus.OWNER
740
- ):
741
- await message.edit_text(
742
- "How am I meant to promote someone that's already an admin?"
743
- )
744
- return
745
-
746
- bot_member = await chat.get_member(bot.id)
747
-
748
- if isinstance(bot_member, ChatMemberAdministrator):
749
- try:
750
- await bot.promoteChatMember(
751
- chat.id,
752
- user_id,
753
- can_change_info=bot_member.can_change_info,
754
- can_post_messages=bot_member.can_post_messages,
755
- can_edit_messages=bot_member.can_edit_messages,
756
- can_delete_messages=bot_member.can_delete_messages,
757
- can_invite_users=bot_member.can_invite_users,
758
- can_restrict_members=bot_member.can_restrict_members,
759
- can_pin_messages=bot_member.can_pin_messages,
760
- can_manage_chat=bot_member.can_manage_chat,
761
- can_manage_video_chats=bot_member.can_manage_video_chats,
762
- )
763
- except BadRequest as err:
764
- if err.message == "User_not_mutual_contact":
765
- await message.edit_text(
766
- "I can't promote someone who isn't in the group"
767
- )
768
- else:
769
- await message.edit_text("An error occurred while promoting.")
770
- return
771
-
772
- await message.edit_text(
773
- f"Successfully promoted <b>{user_member.user.first_name or user_id}</b>!",
774
- parse_mode=ParseMode.HTML,
775
- )
776
- await query.answer("Done")
777
-
778
- log_message = (
779
- f"<b>{html.escape(chat.title)}:</b>\n"
780
- f"#PROMOTED\n"
781
- f"<b>Admin:</b> {mention_html(admin_user.id, admin_user.first_name)}\n"
782
- f"<b>User:</b> {mention_html(user_member.user.id, user_member.user.first_name)}"
783
- )
784
-
785
- return log_message
786
-
787
- elif splitter[1] == "demote":
788
- demoter = await chat.get_member(admin_user.id)
789
-
790
- if not (
791
- demoter.can_promote_members
792
- if isinstance(demoter, ChatMemberAdministrator)
793
- else None or demoter.status == ChatMemberStatus.OWNER
794
- ):
795
- await query.answer(
796
- "You don't have the necessary rights to do that!", show_alert=True
797
- )
798
- return
799
-
800
- try:
801
- user_id = int(splitter[2])
802
- except:
803
- user_id = splitter[2]
804
- await message.edit_text(
805
- "You don't seem to be referring to a user or the ID specified is incorrect.."
806
- )
807
- return
808
-
809
- try:
810
- user_member = await chat.get_member(user_id)
811
- except:
812
- return
813
-
814
- if user_member.status == ChatMemberStatus.OWNER:
815
- await message.edit_text(
816
- "This person CREATED the chat, how would I demote them?"
817
- )
818
- return
819
-
820
- if not user_member.status == ChatMemberStatus.ADMINISTRATOR:
821
- await message.edit_text("Can't demote what wasn't promoted!")
822
- return
823
-
824
- if user_id == bot.id:
825
- await message.edit_text(
826
- "I can't demote myself!, get an admin to do it for me."
827
- )
828
- return
829
-
830
- try:
831
- await bot.promoteChatMember(
832
- chat.id,
833
- user_id,
834
- can_change_info=False,
835
- can_post_messages=False,
836
- can_edit_messages=False,
837
- can_delete_messages=False,
838
- can_invite_users=False,
839
- can_restrict_members=False,
840
- can_pin_messages=False,
841
- can_promote_members=False,
842
- can_manage_chat=False,
843
- can_manage_video_chats=False,
844
- )
845
-
846
- await message.edit_text(
847
- f"Successfully demoted <b>{user_member.user.first_name or user_id}</b>!",
848
- parse_mode=ParseMode.HTML,
849
- )
850
- await query.answer("Done")
851
-
852
- log_message = (
853
- f"<b>{html.escape(chat.title)}:</b>\n"
854
- f"#DEMOTE\n"
855
- f"<b>Admin:</b> {mention_html(admin_user.id, admin_user.first_name)}\n"
856
- f"<b>User:</b> {mention_html(user_member.user.id, user_member.user.first_name)}"
857
- )
858
-
859
- return log_message
860
- except BadRequest:
861
- await message.edit_text(
862
- "Could not demote. I might not be admin, or the admin status was appointed by another"
863
- " user, so I can't act upon them!"
864
- )
865
- return
866
-
867
- elif splitter[1] == "title":
868
- title = splitter[3]
869
-
870
- admin_member = await chat.get_member(admin_user.id)
871
-
872
- if (
873
- not (
874
- (
875
- admin_member.can_promote_members
876
- if isinstance(admin_member, ChatMemberAdministrator)
877
- else None
878
- )
879
- or admin_member.status == ChatMemberStatus.OWNER
880
- )
881
- and admin_user.id not in DRAGONS
882
- ):
883
- await query.answer("You don't have the necessary rights to do that!")
884
- return
885
-
886
- try:
887
- user_id = int(splitter[2])
888
- except:
889
- await message.edit_text(
890
- "You don't seem to be referring to a user or the ID specified is incorrect...",
891
- )
892
- return
893
-
894
- try:
895
- user_member = await chat.get_member(user_id)
896
- except:
897
- return
898
-
899
- if user_member.status == ChatMemberStatus.OWNER:
900
- await message.edit_text(
901
- "This person CREATED the chat, how can I set a custom title for him?",
902
- )
903
- return
904
-
905
- if user_member.status != ChatMemberStatus.ADMINISTRATOR:
906
- await message.edit_text(
907
- "Can't set a title for non-admins! Promote them first to set a custom title!",
908
- )
909
- return
910
-
911
- if user_id == bot.id:
912
- await message.edit_text(
913
- "I can't set my own title myself! Get the one who made me admin to do it for me.",
914
- )
915
- return
916
-
917
- if not title:
918
- await message.edit_text("Setting a blank title doesn't do anything!")
919
- return
920
-
921
- if len(title) > 16:
922
- await message.edit_text(
923
- "The title length is longer than 16 characters. Truncating it to 16 characters.",
924
- )
925
-
926
- try:
927
- await bot.setChatAdministratorCustomTitle(chat.id, user_id, title)
928
- except BadRequest:
929
- await message.edit_text(
930
- "Either they aren't promoted by me or you set a title text that is impossible to set."
931
- )
932
- return
933
-
934
- await message.edit_text(
935
- text=f"Successfully set title for <code>{user_member.user.first_name or user_id}</code> "
936
- f"to <code>{html.escape(title[:16])}</code>!",
937
- parse_mode=ParseMode.HTML,
938
- )
939
-
940
- elif splitter[1] == "pin":
941
- admin_member = await chat.get_member(admin_user.id)
942
-
943
- if (
944
- not (
945
- (
946
- admin_member.can_pin_messages
947
- if isinstance(admin_member, ChatMemberAdministrator)
948
- else None
949
- )
950
- or admin_member.status == ChatMemberStatus.OWNER
951
- )
952
- and admin_user.id not in DRAGONS
953
- ):
954
- await query.answer(
955
- "You don't have the necessary rights to do that!", show_alert=True
956
- )
957
- return
958
-
959
- try:
960
- message_id = int(splitter[2])
961
- except:
962
- return
963
-
964
- is_silent = bool(splitter[3])
965
- is_group = chat.type != "private" and chat.type != "channel"
966
-
967
- if is_group:
968
- try:
969
- await bot.pinChatMessage(
970
- chat.id,
971
- message_id,
972
- disable_notification=is_silent,
973
- )
974
- except BadRequest as excp:
975
- if excp.message == "Chat_not_modified":
976
- pass
977
- else:
978
- raise
979
-
980
- await message.edit_text("Done Pinned.")
981
-
982
- log_message = (
983
- f"<b>{html.escape(chat.title)}</b>\n"
984
- f"#PINNED\n"
985
- f"<b>Admin:</b> {mention_html(admin_user.id, html.escape(admin_user.first_name))}"
986
- )
987
-
988
- return log_message
989
-
990
- elif splitter[1] == "unpin":
991
- admin_member = await chat.get_member(admin_user.id)
992
-
993
- if (
994
- not (
995
- (
996
- admin_member.can_pin_messages
997
- if isinstance(admin_member, ChatMemberAdministrator)
998
- else None
999
- )
1000
- or admin_member.status == ChatMemberStatus.OWNER
1001
- )
1002
- and admin_user.id not in DRAGONS
1003
- ):
1004
- await query.answer(
1005
- "You don't have the necessary rights to do that!",
1006
- show_alert=True,
1007
- )
1008
- return
1009
-
1010
- try:
1011
- await bot.unpinChatMessage(chat.id)
1012
- except BadRequest as excp:
1013
- if excp.message == "Chat_not_modified":
1014
- pass
1015
- elif excp.message == "Message_to_unpin_not_found":
1016
- await message.edit_text("No pinned message found")
1017
- return
1018
- else:
1019
- raise
1020
-
1021
- log_message = (
1022
- f"<b>{html.escape(chat.title)}:</b>\n"
1023
- f"#UNPINNED\n"
1024
- f"<b>Admin:</b> {mention_html(admin_user.id, html.escape(admin_user.first_name))}"
1025
- )
1026
-
1027
- return log_message
1028
-
1029
- elif splitter[1] == "unpinall":
1030
- admin_member = await chat.get_member(admin_user.id)
1031
-
1032
- if (
1033
- not admin_member.status == ChatMemberStatus.OWNER
1034
- and admin_user.id not in DRAGONS
1035
- ):
1036
- await query.answer("Only chat OWNER can unpin all messages.")
1037
- return
1038
-
1039
- try:
1040
- if chat.is_forum:
1041
- await bot.unpin_all_forum_topic_messages(
1042
- chat.id, message.message_thread_id
1043
- )
1044
- else:
1045
- await bot.unpin_all_chat_messages(chat.id)
1046
- except BadRequest as excp:
1047
- if excp.message == "Chat_not_modified":
1048
- pass
1049
- else:
1050
- raise
1051
-
1052
- await message.edit_text("Done unpinning all messages.")
1053
- log_message = (
1054
- f"<b>{html.escape(chat.title)}:</b>\n"
1055
- f"#UNPINNED-ALL\n"
1056
- f"<b>ADMIN:</b> {mention_html(admin_user.id, html.escape(admin_user.first_name))}"
1057
- )
1058
-
1059
- return log_message
1060
-
1061
-
1062
- # <=================================================== HELP ====================================================>
1063
-
1064
-
1065
- __help__ = """
1066
- » /adminlist: List of admins in the chat.
1067
-
1068
- ➠ *Admins only:*
1069
-
1070
- » /pin: Silently pins the message replied to. Add 'loud' or 'notify' to give notifications to users.
1071
-
1072
- » /unpin: Unpins the currently pinned message.
1073
-
1074
- » /unpinall: Unpins all the pinned messages. Works in topics too (only OWNER can do this).
1075
-
1076
- » /invitelink: Get an invite link.
1077
-
1078
- » /promote: Promotes the user replied to.
1079
-
1080
- » /fullpromote: FullPromotes the user replied to.
1081
-
1082
- » /demote: Demotes the user replied to.
1083
-
1084
- » /title <Title here>: Sets a custom title for an admin that the bot promoted.
1085
-
1086
- » /admincache: Force refresh the admins list.
1087
- """
1088
-
1089
- # <================================================ HANDLER =======================================================>
1090
- ADMINLIST_HANDLER = DisableAbleCommandHandler("adminlist", adminlist, block=False)
1091
-
1092
- PIN_HANDLER = CommandHandler("pin", pin, filters=filters.ChatType.GROUPS, block=False)
1093
- UNPIN_HANDLER = CommandHandler(
1094
- "unpin", unpin, filters=filters.ChatType.GROUPS, block=False
1095
- )
1096
- UNPINALL_HANDLER = CommandHandler(
1097
- "unpinall", unpinall, filters=filters.ChatType.GROUPS, block=False
1098
- )
1099
-
1100
- INVITE_HANDLER = DisableAbleCommandHandler("invitelink", invite, block=False)
1101
-
1102
- PROMOTE_HANDLER = DisableAbleCommandHandler("promote", promote, block=False)
1103
- FULLPROMOTE_HANDLER = DisableAbleCommandHandler("fullpromote", fullpromote, block=False)
1104
- DEMOTE_HANDLER = DisableAbleCommandHandler("demote", demote, block=False)
1105
-
1106
- SET_TITLE_HANDLER = CommandHandler("title", set_title, block=False)
1107
- ADMIN_REFRESH_HANDLER = CommandHandler(
1108
- "admincache", refresh_admin, filters=filters.ChatType.GROUPS, block=False
1109
- )
1110
- ADMIN_CALLBACK_HANDLER = CallbackQueryHandler(
1111
- admin_callback, block=False, pattern=r"admin_"
1112
- )
1113
-
1114
- function(ADMINLIST_HANDLER)
1115
- function(PIN_HANDLER)
1116
- function(UNPIN_HANDLER)
1117
- function(UNPINALL_HANDLER)
1118
- function(INVITE_HANDLER)
1119
- function(PROMOTE_HANDLER)
1120
- function(FULLPROMOTE_HANDLER)
1121
- function(DEMOTE_HANDLER)
1122
- function(SET_TITLE_HANDLER)
1123
- function(ADMIN_REFRESH_HANDLER)
1124
- function(ADMIN_CALLBACK_HANDLER)
1125
-
1126
- __mod_name__ = "ADMIN"
1127
- __command_list__ = [
1128
- "adminlist",
1129
- "admins",
1130
- "invitelink",
1131
- "promote",
1132
- "demote",
1133
- "admincache",
1134
- "fullpromote",
1135
- "setgpic",
1136
- "delgpic",
1137
- ]
1138
- __handlers__ = [
1139
- ADMINLIST_HANDLER,
1140
- PIN_HANDLER,
1141
- UNPIN_HANDLER,
1142
- INVITE_HANDLER,
1143
- PROMOTE_HANDLER,
1144
- DEMOTE_HANDLER,
1145
- SET_TITLE_HANDLER,
1146
- ADMIN_REFRESH_HANDLER,
1147
- ]
1148
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/afk.py DELETED
@@ -1,215 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import html
3
- import random
4
- from datetime import datetime
5
-
6
- import humanize
7
- from telegram import MessageEntity, Update
8
- from telegram.error import BadRequest
9
- from telegram.ext import ContextTypes, MessageHandler, filters
10
-
11
- from Database.sql import afk_sql as sql
12
- from Mikobot import LOGGER, function
13
- from Mikobot.plugins.disable import DisableAbleCommandHandler, DisableAbleMessageHandler
14
- from Mikobot.plugins.users import get_user_id
15
-
16
- # <=======================================================================================================>
17
-
18
- AFK_GROUP = 7
19
- AFK_REPLY_GROUP = 8
20
-
21
-
22
- # <================================================ FUNCTION =======================================================>
23
- async def afk(update: Update, context: ContextTypes.DEFAULT_TYPE):
24
- if update.effective_message.text:
25
- args = update.effective_message.text.split(None, 1)
26
- else:
27
- return
28
- user = update.effective_user
29
-
30
- if not user: # ignore channels
31
- return
32
-
33
- notice = ""
34
- if len(args) >= 2:
35
- reason = args[1]
36
- if len(reason) > 100:
37
- reason = reason[:100]
38
- notice = "\nYour afk reason was shortened to 100 characters."
39
- else:
40
- reason = ""
41
-
42
- sql.set_afk(update.effective_user.id, reason)
43
- fname = update.effective_user.first_name
44
- try:
45
- if reason:
46
- await update.effective_message.reply_text(
47
- f"➲ {fname} is now away! \n\n➦ Reason: <code>{reason}</code> \n {notice}",
48
- parse_mode="html",
49
- )
50
- else:
51
- await update.effective_message.reply_text(
52
- "➲ {} is now away!{}".format(fname, notice),
53
- )
54
- except BadRequest:
55
- pass
56
-
57
-
58
- async def no_longer_afk(update: Update, context: ContextTypes.DEFAULT_TYPE):
59
- user = update.effective_user
60
- message = update.effective_message
61
-
62
- if not user: # ignore channels
63
- return
64
-
65
- if sql.is_afk(user.id):
66
- afk_user = sql.check_afk_status(user.id)
67
-
68
- time = humanize.naturaldelta(datetime.now() - afk_user.time)
69
-
70
- res = sql.rm_afk(user.id)
71
- if res:
72
- if message.new_chat_members: # dont say msg
73
- return
74
- firstname = update.effective_user.first_name
75
- try:
76
- options = [
77
- "➲ {} is here!",
78
- "➲ {} is back!",
79
- "➲ {} is now in the chat!",
80
- "➲ {} is awake!",
81
- "➲ {} is back online!",
82
- "➲ {} is finally here!",
83
- "➲ Welcome back! {}",
84
- ]
85
- chosen_option = random.choice(options)
86
- await update.effective_message.reply_text(
87
- chosen_option.format(firstname)
88
- + f"\n\nYou were AFK for: <code>{time}</code>",
89
- parse_mode="html",
90
- )
91
- except:
92
- return
93
-
94
-
95
- async def reply_afk(update: Update, context: ContextTypes.DEFAULT_TYPE):
96
- bot = context.bot
97
- message = update.effective_message
98
- userc = update.effective_user
99
- userc_id = userc.id
100
- if message.entities and message.parse_entities(
101
- [MessageEntity.TEXT_MENTION, MessageEntity.MENTION],
102
- ):
103
- entities = message.parse_entities(
104
- [MessageEntity.TEXT_MENTION, MessageEntity.MENTION],
105
- )
106
-
107
- chk_users = []
108
- for ent in entities:
109
- if ent.type == MessageEntity.TEXT_MENTION:
110
- user_id = ent.user.id
111
- fst_name = ent.user.first_name
112
-
113
- if user_id in chk_users:
114
- return
115
- chk_users.append(user_id)
116
-
117
- if ent.type != MessageEntity.MENTION:
118
- return
119
-
120
- user_id = await get_user_id(
121
- message.text[ent.offset : ent.offset + ent.length],
122
- )
123
- if not user_id:
124
- return
125
-
126
- if user_id in chk_users:
127
- return
128
- chk_users.append(user_id)
129
-
130
- try:
131
- chat = await bot.get_chat(user_id)
132
- except BadRequest:
133
- LOGGER.error(
134
- "Error: Could not fetch userid {} for AFK module".format(user_id)
135
- )
136
- return
137
- fst_name = chat.first_name
138
-
139
- await check_afk(update, context, user_id, fst_name, userc_id)
140
-
141
- elif message.reply_to_message:
142
- user_id = message.reply_to_message.from_user.id
143
- fst_name = message.reply_to_message.from_user.first_name
144
- await check_afk(update, context, user_id, fst_name, userc_id)
145
-
146
-
147
- async def check_afk(
148
- update: Update,
149
- context: ContextTypes.DEFAULT_TYPE,
150
- user_id: int,
151
- fst_name: str,
152
- userc_id: int,
153
- ):
154
- if sql.is_afk(user_id):
155
- user = sql.check_afk_status(user_id)
156
-
157
- if int(userc_id) == int(user_id):
158
- return
159
-
160
- time = humanize.naturaldelta(datetime.now() - user.time)
161
-
162
- if not user.reason:
163
- res = "➲ {} is afk.\n\n➦ Last seen {} ago.".format(
164
- fst_name,
165
- time,
166
- )
167
- await update.effective_message.reply_text(res)
168
- else:
169
- res = (
170
- "➲ {} is afk.\n\n➦ Reason: <code>{}</code>\n➦ Last seen {} ago.".format(
171
- html.escape(fst_name),
172
- html.escape(user.reason),
173
- time,
174
- )
175
- )
176
- await update.effective_message.reply_text(res, parse_mode="html")
177
-
178
-
179
- # <=================================================== HELP ====================================================>
180
-
181
-
182
- __help__ = """
183
- » /afk <reason>*:* mark yourself as AFK (away from keyboard).
184
-
185
- » brb , !afk <reason>*:* same as the afk command - but not a command.
186
-
187
- ➠ *When marked as AFK, any mentions will be replied to with a message to say you're not available!*
188
- """
189
-
190
- # <================================================ HANDLER =======================================================>
191
- AFK_HANDLER = DisableAbleCommandHandler("afk", afk, block=False)
192
- AFK_REGEX_HANDLER = DisableAbleMessageHandler(
193
- filters.Regex(r"^(?i:(brb|!afk))( .*)?$"), afk, friendly="afk", block=False
194
- )
195
- NO_AFK_HANDLER = MessageHandler(
196
- filters.ALL & filters.ChatType.GROUPS, no_longer_afk, block=False
197
- )
198
- AFK_REPLY_HANDLER = MessageHandler(
199
- filters.ALL & filters.ChatType.GROUPS, reply_afk, block=False
200
- )
201
-
202
- function(AFK_HANDLER, AFK_GROUP)
203
- function(AFK_REGEX_HANDLER, AFK_GROUP)
204
- function(NO_AFK_HANDLER, AFK_GROUP)
205
- function(AFK_REPLY_HANDLER, AFK_REPLY_GROUP)
206
-
207
- __mod_name__ = "AFK"
208
- __command_list__ = ["afk"]
209
- __handlers__ = [
210
- (AFK_HANDLER, AFK_GROUP),
211
- (AFK_REGEX_HANDLER, AFK_GROUP),
212
- (NO_AFK_HANDLER, AFK_GROUP),
213
- (AFK_REPLY_HANDLER, AFK_REPLY_GROUP),
214
- ]
215
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/ai.py DELETED
@@ -1,141 +0,0 @@
1
- # CREATED BY: https://t.me/O_oKarma
2
- # API CREDITS: @Qewertyy
3
- # PROVIDED BY: https://github.com/Team-ProjectCodeX
4
-
5
- # <============================================== IMPORTS =========================================================>
6
- import base64
7
-
8
- from telegram import Update
9
- from telegram.constants import ParseMode
10
- from telegram.ext import CommandHandler, ContextTypes
11
-
12
- from Mikobot import LOGGER as logger
13
- from Mikobot import function
14
- from Mikobot.state import state
15
-
16
- # <=======================================================================================================>
17
-
18
- # <================================================ CONSTANTS =====================================================>
19
- API_URL = "https://lexica.qewertyy.me/models"
20
- PALM_MODEL_ID = 0
21
- GPT_MODEL_ID = 5
22
-
23
- # <================================================ FUNCTIONS =====================================================>
24
-
25
-
26
- async def get_api_response(model_id, api_params, api_url):
27
- try:
28
- response = await state.post(api_url, params=api_params)
29
- if response.status_code == 200:
30
- data = response.json()
31
- return data.get(
32
- "content", f"Error: Empty response received from the {model_id} API."
33
- )
34
- else:
35
- return f"Error: Request failed with status code {response.status_code}."
36
- except state.RequestError as e:
37
- return f"Error: An error occurred while calling the {model_id} API. {e}"
38
-
39
-
40
- async def palm_chatbot(update: Update, context: ContextTypes.DEFAULT_TYPE):
41
- args = context.args
42
- if not args:
43
- await context.bot.send_message(
44
- chat_id=update.effective_chat.id,
45
- text="Error: Missing input text after /palm command.",
46
- )
47
- return
48
-
49
- input_text = " ".join(args)
50
-
51
- result_msg = await context.bot.send_message(
52
- chat_id=update.effective_chat.id, text="🌴"
53
- )
54
-
55
- api_params = {"model_id": PALM_MODEL_ID, "prompt": input_text}
56
- api_response = await get_api_response("PALM", api_params, API_URL)
57
-
58
- await result_msg.delete()
59
- await context.bot.send_message(chat_id=update.effective_chat.id, text=api_response)
60
-
61
-
62
- async def gpt_chatbot(update: Update, context: ContextTypes.DEFAULT_TYPE):
63
- args = context.args
64
- if not args:
65
- await context.bot.send_message(
66
- chat_id=update.effective_chat.id,
67
- text="Error: Missing input text after /askgpt command.",
68
- )
69
- return
70
-
71
- input_text = " ".join(args)
72
-
73
- result_msg = await context.bot.send_message(
74
- chat_id=update.effective_chat.id, text="💬"
75
- )
76
-
77
- api_params = {"model_id": GPT_MODEL_ID, "prompt": input_text}
78
- api_response = await get_api_response("GPT", api_params, API_URL)
79
-
80
- await result_msg.delete()
81
- await context.bot.send_message(chat_id=update.effective_chat.id, text=api_response)
82
-
83
-
84
- # Define the upscale_image function
85
- async def upscale_image(update: Update, context: ContextTypes.DEFAULT_TYPE):
86
- try:
87
- # Check if the replied message contains a photo
88
- if update.message.reply_to_message and update.message.reply_to_message.photo:
89
- # Send a message indicating upscaling is in progress
90
- progress_msg = await update.message.reply_text(
91
- "Upscaling your image, please wait..."
92
- )
93
-
94
- # Access the image file_id from the replied message
95
- image = await update.message.reply_to_message.photo[-1].get_file()
96
-
97
- # Download the image and save it
98
- image_path = await image.download_to_drive()
99
-
100
- with open(image_path, "rb") as image_file:
101
- f = image_file.read()
102
-
103
- b = base64.b64encode(f).decode("utf-8")
104
-
105
- response = await state.post(
106
- "https://lexica.qewertyy.me/upscale",
107
- data={"image_data": b},
108
- )
109
-
110
- # Save the upscaled image
111
- upscaled_file_path = "upscaled_image.png"
112
- with open(upscaled_file_path, "wb") as output_file:
113
- output_file.write(response.content)
114
-
115
- # Delete the progress message
116
- await context.bot.delete_message(
117
- chat_id=update.message.chat_id, message_id=progress_msg.message_id
118
- )
119
-
120
- # Send the upscaled image as a PNG file
121
- await update.message.reply_document(
122
- document=open(upscaled_file_path, "rb"),
123
- caption=f"<b>Upscaled your image.</b>\n<b>Generated By:</b> @{context.bot.username}",
124
- parse_mode=ParseMode.HTML,
125
- )
126
- else:
127
- await update.message.reply_text("Please reply to an image to upscale it.")
128
-
129
- except Exception as e:
130
- logger.error(f"Failed to upscale the image: {e}")
131
- await update.message.reply_text(
132
- "Failed to upscale the image. Please try again later."
133
- )
134
-
135
-
136
- # <================================================ HANDLER =======================================================>
137
- # Register the upscale_image command handler
138
- function(CommandHandler("upscale", upscale_image, block=False))
139
- function(CommandHandler("palm", palm_chatbot, block=False))
140
- function(CommandHandler("askgpt", gpt_chatbot, block=False))
141
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/alive.py DELETED
@@ -1,57 +0,0 @@
1
- # SOURCE https://github.com/Team-ProjectCodeX
2
- # CREATED BY https://t.me/O_okarma
3
- # PROVIDED BY https://t.me/ProjectCodeX
4
-
5
- # <============================================== IMPORTS =========================================================>
6
- import random
7
- from sys import version_info
8
-
9
- import pyrogram
10
- import telegram
11
- import telethon
12
- from pyrogram import filters
13
- from pyrogram.types import InlineKeyboardMarkup, Message
14
-
15
- from Infamous.karma import ALIVE_ANIMATION, ALIVE_BTN
16
- from Mikobot import BOT_NAME, app
17
-
18
- # <=======================================================================================================>
19
-
20
-
21
- # <================================================ FUNCTION =======================================================>
22
- @app.on_message(filters.command("alive"))
23
- async def alive(_, message: Message):
24
- library_versions = {
25
- "PTB": telegram.__version__,
26
- "TELETHON": telethon.__version__,
27
- "PYROGRAM": pyrogram.__version__,
28
- }
29
-
30
- library_versions_text = "\n".join(
31
- [f"➲ **{key}:** `{value}`" for key, value in library_versions.items()]
32
- )
33
-
34
- caption = f"""**HEY, I AM {BOT_NAME}**
35
-
36
- ━━━━━━ 🌟✿🌟 ━━━━━━
37
- ✪ **CREATOR:** [🄺🄰🅁🄼🄰](https://t.me/anime_Freakz)
38
-
39
- {library_versions_text}
40
-
41
- ➲ **PYTHON:** `{version_info[0]}.{version_info[1]}.{version_info[2]}`
42
- ➲ **BOT VERSION:** `2.0`
43
- ━━━━━━ 🌟✿🌟 ━━━━━━"""
44
-
45
- await message.reply_animation(
46
- random.choice(ALIVE_ANIMATION),
47
- caption=caption,
48
- reply_markup=InlineKeyboardMarkup(ALIVE_BTN),
49
- )
50
-
51
-
52
- # <=======================================================================================================>
53
-
54
-
55
- # <================================================ NAME =======================================================>
56
- __mod_name__ = "ALIVE"
57
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/anime.py DELETED
The diff for this file is too large to render. See raw diff
 
Mikobot/plugins/antinsfw.py DELETED
@@ -1,189 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from os import remove
3
-
4
- from pyrogram import filters
5
-
6
- from Database.mongodb.toggle_mongo import is_nsfw_on, nsfw_off, nsfw_on
7
- from Mikobot import BOT_USERNAME, DRAGONS, app
8
- from Mikobot.state import arq
9
- from Mikobot.utils.can_restrict import can_restrict
10
- from Mikobot.utils.errors import capture_err
11
-
12
- # <=======================================================================================================>
13
-
14
-
15
- # <================================================ FUNCTION =======================================================>
16
- async def get_file_id_from_message(message):
17
- file_id = None
18
- if message.document:
19
- if int(message.document.file_size) > 3145728:
20
- return
21
- mime_type = message.document.mime_type
22
- if mime_type not in ("image/png", "image/jpeg"):
23
- return
24
- file_id = message.document.file_id
25
-
26
- if message.sticker:
27
- if message.sticker.is_animated:
28
- if not message.sticker.thumbs:
29
- return
30
- file_id = message.sticker.thumbs[0].file_id
31
- else:
32
- file_id = message.sticker.file_id
33
-
34
- if message.photo:
35
- file_id = message.photo.file_id
36
-
37
- if message.animation:
38
- if not message.animation.thumbs:
39
- return
40
- file_id = message.animation.thumbs[0].file_id
41
-
42
- if message.video:
43
- if not message.video.thumbs:
44
- return
45
- file_id = message.video.thumbs[0].file_id
46
- return file_id
47
-
48
-
49
- @app.on_message(
50
- (
51
- filters.document
52
- | filters.photo
53
- | filters.sticker
54
- | filters.animation
55
- | filters.video
56
- )
57
- & ~filters.private,
58
- group=8,
59
- )
60
- @capture_err
61
- async def detect_nsfw(_, message):
62
- if not await is_nsfw_on(message.chat.id):
63
- return
64
- if not message.from_user:
65
- return
66
- file_id = await get_file_id_from_message(message)
67
- if not file_id:
68
- return
69
- file = await _.download_media(file_id)
70
- try:
71
- results = await arq.nsfw_scan(file=file)
72
- except Exception:
73
- return
74
- if not results.ok:
75
- return
76
- results = results.result
77
- remove(file)
78
- nsfw = results.is_nsfw
79
- if message.from_user.id in DRAGONS:
80
- return
81
- if not nsfw:
82
- return
83
- try:
84
- await message.delete()
85
- except Exception:
86
- return
87
- await message.reply_text(
88
- f"""
89
- **🔞 NSFW Image Detected & Deleted Successfully!**
90
-
91
- **✪ User:** {message.from_user.mention} [`{message.from_user.id}`]
92
- **✪ Safe:** `{results.neutral} %`
93
- **✪ Porn:** `{results.porn} %`
94
- **✪ Adult:** `{results.sexy} %`
95
- **✪ Hentai:** `{results.hentai} %`
96
- **✪ Drawings:** `{results.drawings} %`
97
- """
98
- )
99
-
100
-
101
- @app.on_message(filters.command(["nsfwscan", f"nsfwscan@{BOT_USERNAME}"]))
102
- @capture_err
103
- async def nsfw_scan_command(_, message):
104
- if not message.reply_to_message:
105
- await message.reply_text(
106
- "Reply to an image/document/sticker/animation to scan it."
107
- )
108
- return
109
- reply = message.reply_to_message
110
- if (
111
- not reply.document
112
- and not reply.photo
113
- and not reply.sticker
114
- and not reply.animation
115
- and not reply.video
116
- ):
117
- await message.reply_text(
118
- "Reply to an image/document/sticker/animation to scan it."
119
- )
120
- return
121
- m = await message.reply_text("Scanning")
122
- file_id = await get_file_id_from_message(reply)
123
- if not file_id:
124
- return await m.edit("Something wrong happened.")
125
- file = await _.download_media(file_id)
126
- try:
127
- results = await arq.nsfw_scan(file=file)
128
- except Exception:
129
- return
130
- remove(file)
131
- if not results.ok:
132
- return await m.edit(results.result)
133
- results = results.result
134
- await m.edit(
135
- f"""
136
- **➢ Neutral:** `{results.neutral} %`
137
- **➢ Porn:** `{results.porn} %`
138
- **➢ Hentai:** `{results.hentai} %`
139
- **➢ Sexy:** `{results.sexy} %`
140
- **➢ Drawings:** `{results.drawings} %`
141
- **➢ NSFW:** `{results.is_nsfw}`
142
- """
143
- )
144
-
145
-
146
- @app.on_message(
147
- filters.command(["antinsfw", f"antinsfw@{BOT_USERNAME}"]) & ~filters.private
148
- )
149
- @can_restrict
150
- async def nsfw_enable_disable(_, message):
151
- if len(message.command) != 2:
152
- await message.reply_text("Usage: /antinsfw [on/off]")
153
- return
154
- status = message.text.split(None, 1)[1].strip()
155
- status = status.lower()
156
- chat_id = message.chat.id
157
- if status in ("on", "yes"):
158
- if await is_nsfw_on(chat_id):
159
- await message.reply_text("Antinsfw is already enabled.")
160
- return
161
- await nsfw_on(chat_id)
162
- await message.reply_text(
163
- "Enabled AntiNSFW System. I will Delete Messages Containing Inappropriate Content."
164
- )
165
- elif status in ("off", "no"):
166
- if not await is_nsfw_on(chat_id):
167
- await message.reply_text("Antinsfw is already disabled.")
168
- return
169
- await nsfw_off(chat_id)
170
- await message.reply_text("Disabled AntiNSFW System.")
171
- else:
172
- await message.reply_text("Unknown Suffix, Use /antinsfw [on/off]")
173
-
174
-
175
- # <=================================================== HELP ====================================================>
176
-
177
-
178
- __mod_name__ = "ANTI-NSFW"
179
-
180
- __help__ = """
181
- *🔞 Helps in detecting NSFW material and removing it*.
182
-
183
- ➠ *Usage:*
184
-
185
- » /antinsfw [on/off]: Enables Anti-NSFW system.
186
-
187
- » /nsfwscan <reply to message>: Scans the file replied to.
188
- """
189
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/approve.py DELETED
@@ -1,259 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import html
3
-
4
- from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
5
- from telegram.constants import ChatMemberStatus, ParseMode
6
- from telegram.error import BadRequest
7
- from telegram.ext import CallbackQueryHandler, ContextTypes
8
- from telegram.helpers import mention_html
9
-
10
- import Database.sql.approve_sql as sql
11
- from Mikobot import DRAGONS, dispatcher
12
- from Mikobot.plugins.disable import DisableAbleCommandHandler
13
- from Mikobot.plugins.helper_funcs.chat_status import check_admin
14
- from Mikobot.plugins.helper_funcs.extraction import extract_user
15
- from Mikobot.plugins.log_channel import loggable
16
-
17
- # <=======================================================================================================>
18
-
19
-
20
- # <================================================ FUNCTION =======================================================>
21
- @loggable
22
- @check_admin(is_user=True)
23
- async def approve(update: Update, context: ContextTypes.DEFAULT_TYPE):
24
- message = update.effective_message
25
- chat_title = message.chat.title
26
- chat = update.effective_chat
27
- args = context.args
28
- user = update.effective_user
29
- user_id = await extract_user(message, context, args)
30
- if not user_id:
31
- await message.reply_text(
32
- "I don't know who you're talking about, you're going to need to specify a user!",
33
- )
34
- return ""
35
- try:
36
- member = await chat.get_member(user_id)
37
- except BadRequest:
38
- return ""
39
- if member.status in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER]:
40
- await message.reply_text(
41
- "User is already admin - locks, blocklists, and antiflood already don't apply to them.",
42
- )
43
- return ""
44
- if sql.is_approved(message.chat_id, user_id):
45
- await message.reply_text(
46
- f"[{member.user.first_name}](tg://user?id={member.user.id}) is already approved in {chat_title}",
47
- parse_mode=ParseMode.MARKDOWN,
48
- )
49
- return ""
50
- sql.approve(message.chat_id, user_id)
51
- await message.reply_text(
52
- f"[{member.user.first_name}](tg://user?id={member.user.id}) has been approved in {chat_title}! They will now be ignored by automated admin actions like locks, blocklists, and antiflood.",
53
- parse_mode=ParseMode.MARKDOWN,
54
- )
55
- log_message = (
56
- f"<b>{html.escape(chat.title)}:</b>\n"
57
- f"#APPROVED\n"
58
- f"<b>Admin:</b> {mention_html(user.id, user.first_name)}\n"
59
- f"<b>User:</b> {mention_html(member.user.id, member.user.first_name)}"
60
- )
61
-
62
- return log_message
63
-
64
-
65
- @loggable
66
- @check_admin(is_user=True)
67
- async def disapprove(update: Update, context: ContextTypes.DEFAULT_TYPE):
68
- message = update.effective_message
69
- chat_title = message.chat.title
70
- chat = update.effective_chat
71
- args = context.args
72
- user = update.effective_user
73
- user_id = await extract_user(message, context, args)
74
- if not user_id:
75
- await message.reply_text(
76
- "I don't know who you're talking about, you're going to need to specify a user!",
77
- )
78
- return ""
79
- try:
80
- member = await chat.get_member(user_id)
81
- except BadRequest:
82
- return ""
83
- if member.status in [ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER]:
84
- await message.reply_text("This user is an admin, they can't be unapproved.")
85
- return ""
86
- if not sql.is_approved(message.chat_id, user_id):
87
- await message.reply_text(f"{member.user.first_name} isn't approved yet!")
88
- return ""
89
- sql.disapprove(message.chat_id, user_id)
90
- await message.reply_text(
91
- f"{member.user.first_name} is no longer approved in {chat_title}.",
92
- )
93
- log_message = (
94
- f"<b>{html.escape(chat.title)}:</b>\n"
95
- f"#UNAPPROVED\n"
96
- f"<b>Admin:</b> {mention_html(user.id, user.first_name)}\n"
97
- f"<b>User:</b> {mention_html(member.user.id, member.user.first_name)}"
98
- )
99
-
100
- return log_message
101
-
102
-
103
- @check_admin(is_user=True)
104
- async def approved(update: Update, context: ContextTypes.DEFAULT_TYPE):
105
- message = update.effective_message
106
- chat_title = message.chat.title
107
- chat = update.effective_chat
108
- msg = "The following users are approved.\n"
109
- approved_users = sql.list_approved(message.chat_id)
110
-
111
- if not approved_users:
112
- await message.reply_text(f"No users are approved in {chat_title}.")
113
- return ""
114
-
115
- else:
116
- for i in approved_users:
117
- member = await chat.get_member(int(i.user_id))
118
- msg += f"- `{i.user_id}`: {member.user['first_name']}\n"
119
-
120
- await message.reply_text(msg, parse_mode=ParseMode.MARKDOWN)
121
-
122
-
123
- @check_admin(is_user=True)
124
- async def approval(update: Update, context: ContextTypes.DEFAULT_TYPE):
125
- message = update.effective_message
126
- chat = update.effective_chat
127
- args = context.args
128
- user_id = await extract_user(message, context, args)
129
-
130
- if not user_id:
131
- await message.reply_text(
132
- "I don't know who you're talking about, you're going to need to specify a user!",
133
- )
134
- return ""
135
- member = await chat.get_member(int(user_id))
136
- if sql.is_approved(message.chat_id, user_id):
137
- await message.reply_text(
138
- f"{member.user['first_name']} is an approved user. Locks, antiflood, and blocklists won't apply to them.",
139
- )
140
- else:
141
- await message.reply_text(
142
- f"{member.user['first_name']} is not an approved user. They are affected by normal commands.",
143
- )
144
-
145
-
146
- async def unapproveall(update: Update, context: ContextTypes.DEFAULT_TYPE):
147
- chat = update.effective_chat
148
- user = update.effective_user
149
- member = await chat.get_member(user.id)
150
-
151
- approved_users = sql.list_approved(chat.id)
152
- if not approved_users:
153
- await update.effective_message.reply_text(
154
- f"No users are approved in {chat.title}."
155
- )
156
- return
157
-
158
- if member.status != ChatMemberStatus.OWNER and user.id not in DRAGONS:
159
- await update.effective_message.reply_text(
160
- "Only the chat owner can unapprove all users at once.",
161
- )
162
- else:
163
- buttons = InlineKeyboardMarkup(
164
- [
165
- [
166
- InlineKeyboardButton(
167
- text="Unapprove all users",
168
- callback_data="unapproveall_user",
169
- ),
170
- ],
171
- [
172
- InlineKeyboardButton(
173
- text="Cancel",
174
- callback_data="unapproveall_cancel",
175
- ),
176
- ],
177
- ],
178
- )
179
- await update.effective_message.reply_text(
180
- f"Are you sure you would like to unapprove ALL users in {chat.title}? This action cannot be undone.",
181
- reply_markup=buttons,
182
- parse_mode=ParseMode.MARKDOWN,
183
- )
184
-
185
-
186
- async def unapproveall_btn(update: Update, context: ContextTypes.DEFAULT_TYPE):
187
- query = update.callback_query
188
- chat = update.effective_chat
189
- message = update.effective_message
190
- member = await chat.get_member(query.from_user.id)
191
- if query.data == "unapproveall_user":
192
- if member.status == ChatMemberStatus.OWNER or query.from_user.id in DRAGONS:
193
- approved_users = sql.list_approved(chat.id)
194
- users = [int(i.user_id) for i in approved_users]
195
- for user_id in users:
196
- sql.disapprove(chat.id, user_id)
197
- await message.edit_text("Successfully Unapproved all user in this Chat.")
198
- return
199
-
200
- if member.status == "administrator":
201
- await query.answer("Only owner of the chat can do this.")
202
-
203
- if member.status == "member":
204
- await query.answer("You need to be admin to do this.")
205
- elif query.data == "unapproveall_cancel":
206
- if member.status == "creator" or query.from_user.id in DRAGONS:
207
- await message.edit_text(
208
- "Removing of all approved users has been cancelled."
209
- )
210
- return ""
211
- if member.status == "administrator":
212
- await query.answer("Only owner of the chat can do this.")
213
- if member.status == "member":
214
- await query.answer("You need to be admin to do this.")
215
-
216
-
217
- # <=================================================== HELP ====================================================>
218
-
219
-
220
- __help__ = """
221
- ➠ Sometimes, you might trust a user not to send unwanted content.
222
- Maybe not enough to make them admin, but you might be ok with locks, blacklists, and antiflood not applying to them.
223
-
224
- ➠ That's what approvals are for - approve of trustworthy users to allow them to send
225
-
226
- ➠ *Admin commands:*
227
-
228
- » /approval: Check a user's approval status in this chat.
229
-
230
- » /approve: Approve of a user. Locks, blacklists, and antiflood won't apply to them anymore.
231
-
232
- » /unapprove: Unapprove of a user. They will now be subject to locks, blacklists, and antiflood again.
233
-
234
- » /approved: List all approved users.
235
-
236
- » /unapproveall: Unapprove *ALL* users in a chat. This cannot be undone.
237
- """
238
-
239
- # <================================================ HANDLER =======================================================>
240
- APPROVE = DisableAbleCommandHandler("approve", approve, block=False)
241
- DISAPPROVE = DisableAbleCommandHandler("unapprove", disapprove, block=False)
242
- APPROVED = DisableAbleCommandHandler("approved", approved, block=False)
243
- APPROVAL = DisableAbleCommandHandler("approval", approval, block=False)
244
- UNAPPROVEALL = DisableAbleCommandHandler("unapproveall", unapproveall, block=False)
245
- UNAPPROVEALL_BTN = CallbackQueryHandler(
246
- unapproveall_btn, pattern=r"unapproveall_.*", block=False
247
- )
248
-
249
- dispatcher.add_handler(APPROVE)
250
- dispatcher.add_handler(DISAPPROVE)
251
- dispatcher.add_handler(APPROVED)
252
- dispatcher.add_handler(APPROVAL)
253
- dispatcher.add_handler(UNAPPROVEALL)
254
- dispatcher.add_handler(UNAPPROVEALL_BTN)
255
-
256
- __mod_name__ = "APPROVALS"
257
- __command_list__ = ["approve", "unapprove", "approved", "approval"]
258
- __handlers__ = [APPROVE, DISAPPROVE, APPROVED, APPROVAL]
259
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/ban.py DELETED
@@ -1,748 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import html
3
-
4
- from telegram import (
5
- ChatMemberAdministrator,
6
- InlineKeyboardButton,
7
- InlineKeyboardMarkup,
8
- Update,
9
- )
10
- from telegram.constants import ParseMode
11
- from telegram.error import BadRequest
12
- from telegram.ext import CallbackQueryHandler, CommandHandler, ContextTypes, filters
13
- from telegram.helpers import mention_html
14
-
15
- from Mikobot import DEV_USERS, DRAGONS, LOGGER, OWNER_ID, function
16
- from Mikobot.utils.can_restrict import BAN_STICKER
17
- from Mikobot.plugins.disable import DisableAbleCommandHandler
18
- from Mikobot.plugins.helper_funcs.chat_status import (
19
- can_delete,
20
- check_admin,
21
- connection_status,
22
- is_user_admin,
23
- is_user_ban_protected,
24
- is_user_in_chat,
25
- )
26
- from Mikobot.plugins.helper_funcs.extraction import extract_user_and_text
27
- from Mikobot.plugins.helper_funcs.misc import mention_username
28
- from Mikobot.plugins.helper_funcs.string_handling import extract_time
29
- from Mikobot.plugins.log_channel import gloggable, loggable
30
-
31
- # <=======================================================================================================>
32
-
33
-
34
- # <================================================ FUNCTION =======================================================>
35
- @connection_status
36
- @loggable
37
- @check_admin(permission="can_restrict_members", is_both=True)
38
- async def ban(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str:
39
- chat = update.effective_chat
40
- user = update.effective_user
41
- message = update.effective_message
42
- log_message = ""
43
- bot = context.bot
44
- args = context.args
45
- user_id, reason = await extract_user_and_text(message, context, args)
46
-
47
- member = await chat.get_member(user.id)
48
- SILENT = bool(True if message.text.startswith("/s") else False)
49
-
50
- # if update is coming from anonymous admin then send button and return.
51
- if message.from_user.id == 1087968824:
52
- if SILENT:
53
- await message.reply_text("Currently /sban won't work for anoymous admins.")
54
- return log_message
55
- # Need chat title to be forwarded on callback data to mention channel after banning.
56
- try:
57
- chat_title = message.reply_to_message.sender_chat.title
58
- except AttributeError:
59
- chat_title = None
60
- await update.effective_message.reply_text(
61
- text="You are an anonymous admin.",
62
- reply_markup=InlineKeyboardMarkup(
63
- [
64
- [
65
- InlineKeyboardButton(
66
- text="Click to prove Admin.",
67
- callback_data=f"bans_{chat.id}=ban={user_id}={reason}={chat_title}",
68
- ),
69
- ],
70
- ]
71
- ),
72
- )
73
-
74
- return log_message
75
- elif (
76
- not (
77
- (
78
- member.can_restrict_members
79
- if isinstance(member, ChatMemberAdministrator)
80
- else None
81
- )
82
- or member.status == "creator"
83
- )
84
- and user.id not in DRAGONS
85
- ):
86
- await update.effective_message.reply_text(
87
- "Sorry son, but you're not worthy to wield the banhammer.",
88
- )
89
- return log_message
90
-
91
- if user_id == bot.id:
92
- await message.reply_text("Oh yeah, ban myself, noob!")
93
- return log_message
94
-
95
- if user_id is not None and user_id < 0:
96
- CHAT_SENDER = True
97
- chat_sender = message.reply_to_message.sender_chat
98
- else:
99
- CHAT_SENDER = False
100
- try:
101
- member = await chat.get_member(user_id)
102
- except BadRequest as excp:
103
- if excp.message == "User not found":
104
- raise
105
- elif excp == "Invalid user_id specified":
106
- await message.reply_text("I Doubt that's a user.")
107
- await message.reply_text("Can't find this person here.")
108
- return log_message
109
-
110
- if await is_user_ban_protected(chat, user_id, member) and user not in DEV_USERS:
111
- if user_id == OWNER_ID:
112
- await message.reply_text(
113
- "Trying to put me against a God level disaster huh?"
114
- )
115
- elif user_id in DEV_USERS:
116
- await message.reply_text("I can't act against our own.")
117
- elif user_id in DRAGONS:
118
- await message.reply_text(
119
- "Fighting this Dragon here will put me and my people's at risk.",
120
- )
121
- else:
122
- await message.reply_text("This user has immunity and cannot be banned.")
123
- return log_message
124
-
125
- if SILENT:
126
- silent = True
127
- if not await can_delete(chat, context.bot.id):
128
- return ""
129
- else:
130
- silent = False
131
-
132
- log = (
133
- f"<b>{html.escape(chat.title)}:</b>\n"
134
- f"#{'S' if silent else ''}BANNED\n"
135
- f"<b>Admin:</b> {mention_html(user.id, html.escape(user.first_name))}\n"
136
- )
137
-
138
- reply = f"<code>❕</code><b>Ban Event</b>\n"
139
-
140
- if CHAT_SENDER:
141
- log += f"<b>Channel:</b> {mention_username(chat_sender.username, html.escape(chat_sender.title))}"
142
- reply += f"<code> </code><b>• Channel:</b> {mention_username(chat_sender.username, html.escape(chat_sender.title))}"
143
-
144
- else:
145
- log += f"<b>User:</b> {mention_html(member.user.id, html.escape(member.user.first_name))}"
146
- reply += f"<code> </code><b>• User:</b> {mention_html(member.user.id, html.escape(member.user.first_name))}"
147
-
148
- if reason:
149
- log += "\n<b>Reason:</b> {}".format(reason)
150
-
151
- try:
152
- if CHAT_SENDER:
153
- await chat.ban_sender_chat(sender_chat_id=chat_sender.id)
154
- else:
155
- await chat.ban_member(user_id)
156
-
157
- if silent:
158
- if message.reply_to_message:
159
- await message.reply_to_message.delete()
160
- await message.delete()
161
- return log
162
-
163
- await bot.send_sticker(
164
- chat.id,
165
- BAN_STICKER,
166
- message_thread_id=message.message_thread_id if chat.is_forum else None,
167
- ) # banhammer marie sticker
168
-
169
- if reason:
170
- reply += f"\n<code> </code><b>• Reason:</b> \n{html.escape(reason)}"
171
- await bot.sendMessage(
172
- chat.id,
173
- reply,
174
- parse_mode=ParseMode.HTML,
175
- message_thread_id=message.message_thread_id if chat.is_forum else None,
176
- )
177
- return log
178
-
179
- except BadRequest as excp:
180
- if excp.message == "Reply message not found":
181
- # Do not reply
182
- if silent:
183
- return log
184
- await message.reply_text("Banned!", quote=False)
185
- return log
186
- else:
187
- LOGGER.warning(update)
188
- LOGGER.exception(
189
- "ERROR banning user %s in chat %s (%s) due to %s",
190
- user_id,
191
- chat.title,
192
- chat.id,
193
- excp.message,
194
- )
195
- await message.reply_text("Uhm...that didn't work...")
196
-
197
- return log_message
198
-
199
-
200
- @connection_status
201
- @loggable
202
- @check_admin(permission="can_restrict_members", is_both=True)
203
- async def temp_ban(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str:
204
- chat = update.effective_chat
205
- user = update.effective_user
206
- message = update.effective_message
207
- log_message = ""
208
- bot, args = context.bot, context.args
209
- user_id, reason = await extract_user_and_text(message, context, args)
210
-
211
- if not user_id:
212
- await message.reply_text("I doubt that's a user.")
213
- return log_message
214
-
215
- try:
216
- member = await chat.get_member(user_id)
217
- except BadRequest as excp:
218
- if excp.message != "User not found":
219
- raise
220
- await message.reply_text("I can't seem to find this user.")
221
- return log_message
222
- if user_id == bot.id:
223
- await message.reply_text("I'm not gonna BAN myself, are you crazy?")
224
- return log_message
225
-
226
- if await is_user_ban_protected(chat, user_id, member):
227
- await message.reply_text("I don't feel like it.")
228
- return log_message
229
-
230
- if not reason:
231
- await message.reply_text("You haven't specified a time to ban this user for!")
232
- return log_message
233
-
234
- split_reason = reason.split(None, 1)
235
-
236
- time_val = split_reason[0].lower()
237
- reason = split_reason[1] if len(split_reason) > 1 else ""
238
- bantime = await extract_time(message, time_val)
239
-
240
- if not bantime:
241
- return log_message
242
-
243
- log = (
244
- f"<b>{html.escape(chat.title)}:</b>\n"
245
- "#TEMP BANNED\n"
246
- f"<b>Admin:</b> {mention_html(user.id, html.escape(user.first_name))}\n"
247
- f"<b>User:</b> {mention_html(member.user.id, html.escape(member.user.first_name))}\n"
248
- f"<b>Time:</b> {time_val}"
249
- )
250
- if reason:
251
- log += "\n<b>Reason:</b> {}".format(reason)
252
-
253
- try:
254
- await chat.ban_member(user_id, until_date=bantime)
255
- await bot.send_sticker(
256
- chat.id,
257
- BAN_STICKER,
258
- message_thread_id=message.message_thread_id if chat.is_forum else None,
259
- ) # banhammer marie sticker
260
- await bot.sendMessage(
261
- chat.id,
262
- f"Banned! User {mention_html(member.user.id, html.escape(member.user.first_name))} "
263
- f"will be banned for {time_val}.",
264
- parse_mode=ParseMode.HTML,
265
- message_thread_id=message.message_thread_id if chat.is_forum else None,
266
- )
267
- return log
268
-
269
- except BadRequest as excp:
270
- if excp.message == "Reply message not found":
271
- # Do not reply
272
- await message.reply_text(
273
- f"Banned! User will be banned for {time_val}.",
274
- quote=False,
275
- )
276
- return log
277
- else:
278
- LOGGER.warning(update)
279
- LOGGER.exception(
280
- "ERROR banning user %s in chat %s (%s) due to %s",
281
- user_id,
282
- chat.title,
283
- chat.id,
284
- excp.message,
285
- )
286
- await message.reply_text("Well damn, I can't ban that user.")
287
-
288
- return log_message
289
-
290
-
291
- @connection_status
292
- @loggable
293
- @check_admin(permission="can_restrict_members", is_both=True)
294
- async def kick(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str:
295
- chat = update.effective_chat
296
- user = update.effective_user
297
- message = update.effective_message
298
- log_message = ""
299
- bot, args = context.bot, context.args
300
- user_id, reason = await extract_user_and_text(message, context, args)
301
-
302
- if not user_id:
303
- await message.reply_text("I doubt that's a user.")
304
- return log_message
305
-
306
- try:
307
- member = await chat.get_member(user_id)
308
- except BadRequest as excp:
309
- if excp.message != "User not found":
310
- raise
311
-
312
- await message.reply_text("I can't seem to find this user.")
313
- return log_message
314
- if user_id == bot.id:
315
- await message.reply_text("Yeahhh I'm not gonna do that.")
316
- return log_message
317
-
318
- if await is_user_ban_protected(chat, user_id):
319
- await message.reply_text("I really wish I could kick this user....")
320
- return log_message
321
-
322
- res = chat.unban_member(user_id) # unban on current user = kick
323
- if res:
324
- await bot.send_sticker(
325
- chat.id,
326
- BAN_STICKER,
327
- message_thread_id=message.message_thread_id if chat.is_forum else None,
328
- ) # banhammer marie sticker
329
- await bot.sendMessage(
330
- chat.id,
331
- f"Capitain I have kicked, {mention_html(member.user.id, html.escape(member.user.first_name))}.",
332
- parse_mode=ParseMode.HTML,
333
- message_thread_id=message.message_thread_id if chat.is_forum else None,
334
- )
335
- log = (
336
- f"<b>{html.escape(chat.title)}:</b>\n"
337
- f"#KICKED\n"
338
- f"<b>Admin:</b> {mention_html(user.id, html.escape(user.first_name))}\n"
339
- f"<b>User:</b> {mention_html(member.user.id, html.escape(member.user.first_name))}"
340
- )
341
- if reason:
342
- log += f"\n<b>Reason:</b> {reason}"
343
-
344
- return log
345
-
346
- else:
347
- await message.reply_text("Well damn, I can't kick that user.")
348
-
349
- return log_message
350
-
351
-
352
- @check_admin(permission="can_restrict_members", is_bot=True)
353
- async def kickme(update: Update, context: ContextTypes.DEFAULT_TYPE):
354
- user_id = update.effective_message.from_user.id
355
- if await is_user_admin(update.effective_chat, user_id):
356
- await update.effective_message.reply_text(
357
- "I wish I could... but you're an admin."
358
- )
359
- return
360
-
361
- res = await update.effective_chat.unban_member(
362
- user_id
363
- ) # unban on current user = kick
364
- # BUG: parsing not working
365
- if res:
366
- await update.effective_message.reply_text(
367
- html.escape("You got the Devil's Kiss, Now die in peace"), parse_mode="html"
368
- )
369
- else:
370
- await update.effective_message.reply_text("Huh? I can't :/")
371
-
372
-
373
- @connection_status
374
- @loggable
375
- @check_admin(permission="can_restrict_members", is_both=True)
376
- async def unban(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str:
377
- message = update.effective_message
378
- user = update.effective_user
379
- chat = update.effective_chat
380
- log_message = ""
381
- bot, args = context.bot, context.args
382
- user_id, reason = await extract_user_and_text(message, context, args)
383
-
384
- if message.from_user.id == 1087968824:
385
- try:
386
- chat_title = message.reply_to_message.sender_chat.title
387
- except AttributeError:
388
- chat_title = None
389
-
390
- await message.reply_text(
391
- text="You are an anonymous admin.",
392
- reply_markup=InlineKeyboardMarkup(
393
- [
394
- [
395
- InlineKeyboardButton(
396
- text="Click to prove Admin.",
397
- callback_data=f"bans_{chat.id}=unban={user_id}={reason}={chat_title}",
398
- ),
399
- ],
400
- ]
401
- ),
402
- )
403
-
404
- return log_message
405
-
406
- if not user_id:
407
- await message.reply_text("I doubt that's a user.")
408
- return log_message
409
-
410
- if user_id == bot.id:
411
- await message.reply_text("How would I unban myself if I wasn't here...?")
412
- return log_message
413
-
414
- if user_id is not None and user_id < 0:
415
- CHAT_SENDER = True
416
- chat_sender = message.reply_to_message.sender_chat
417
- else:
418
- CHAT_SENDER = False
419
- try:
420
- member = await chat.get_member(user_id)
421
-
422
- if isinstance(member, ChatMemberAdministrator):
423
- await message.reply_text(
424
- "This person is an admin here, Are you drunk???"
425
- )
426
- return log_message
427
-
428
- except BadRequest as excp:
429
- raise
430
- if excp.message != "User not found":
431
- raise
432
- await message.reply_text("I can't seem to find this user.")
433
- return log_message
434
-
435
- if await is_user_in_chat(chat, user_id):
436
- await message.reply_text("Isn't this person already here??")
437
- return log_message
438
-
439
- log = (
440
- f"<b>{html.escape(chat.title)}:</b>\n"
441
- f"#UNBANNED\n"
442
- f"<b>Admin:</b> {mention_html(user.id, html.escape(user.first_name))}\n"
443
- )
444
-
445
- if CHAT_SENDER:
446
- log += f"<b>User:</b> {mention_username(chat_sender.id, html.escape(chat_sender.title))}"
447
- await chat.unban_sender_chat(chat_sender.id)
448
- await message.reply_text("Yeah, this channel can speak again.")
449
- else:
450
- log += f"<b>User:</b> {mention_html(member.user.id, html.escape(member.user.first_name))}"
451
- await chat.unban_member(user_id)
452
- await message.reply_text("Yeah, this user can join!")
453
-
454
- if reason:
455
- log += f"\n<b>Reason:</b> {reason}"
456
-
457
- return log
458
-
459
-
460
- @connection_status
461
- @gloggable
462
- @check_admin(permission="can_restrict_members", is_bot=True)
463
- async def selfunban(context: ContextTypes.DEFAULT_TYPE, update: Update) -> str:
464
- message = update.effective_message
465
- user = update.effective_user
466
- bot, args = context.bot, context.args
467
- if user.id not in DRAGONS:
468
- return
469
-
470
- try:
471
- chat_id = int(args[0])
472
- except:
473
- await message.reply_text("Give a valid chat ID.")
474
- return
475
-
476
- chat = await bot.getChat(chat_id)
477
-
478
- try:
479
- member = await chat.get_member(user.id)
480
- except BadRequest as excp:
481
- if excp.message == "User not found":
482
- await message.reply_text("I can't seem to find this user.")
483
- return
484
- else:
485
- raise
486
-
487
- if await is_user_in_chat(chat, user.id):
488
- await message.reply_text("Aren't you already in the chat??")
489
- return
490
-
491
- await chat.unban_member(user.id)
492
- await message.reply_text("Yep, I have unbanned you.")
493
-
494
- log = (
495
- f"<b>{html.escape(chat.title)}:</b>\n"
496
- f"#UNBANNED\n"
497
- f"<b>User:</b> {mention_html(member.user.id, html.escape(member.user.first_name))}"
498
- )
499
-
500
- return log
501
-
502
-
503
- @loggable
504
- async def bans_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
505
- query = update.callback_query
506
- bot = context.bot
507
- chat = update.effective_chat
508
- message = update.effective_message
509
- args = context.args
510
- log_message = ""
511
- splitter = query.data.replace("bans_", "").split("=")
512
-
513
- admin_user = query.from_user
514
- member = await chat.get_member(admin_user.id)
515
-
516
- if splitter[1] == "ban":
517
- # workaround for checking user admin status
518
- try:
519
- user_id = int(splitter[2])
520
- except ValueError:
521
- user_id = splitter[2]
522
- reason = splitter[3]
523
- chat_name = splitter[4]
524
-
525
- if not (
526
- (
527
- member.can_restrict_members
528
- if isinstance(member, ChatMemberAdministrator)
529
- else None
530
- )
531
- or member.status == "creator"
532
- ) and (admin_user.id not in DRAGONS):
533
- await query.answer(
534
- "Sorry son, but you're not worthy to wield the banhammer.",
535
- show_alert=True,
536
- )
537
- return log_message
538
-
539
- if user_id == bot.id:
540
- await message.edit_text("Oh yeah, ban myself, noob!")
541
- return log_message
542
-
543
- if isinstance(user_id, str):
544
- await message.edit_text("I doubt that's a user.")
545
- return log_message
546
-
547
- if user_id < 0:
548
- CHAT_SENDER = True
549
- else:
550
- CHAT_SENDER = False
551
- try:
552
- member = await chat.get_member(user_id)
553
- except BadRequest as excp:
554
- if excp.message == "User not found.":
555
- raise
556
- elif excp == "Invalid user_id specified":
557
- await message.edit_text("I Doubt that's a user.")
558
- await message.edit_text("Can't find this person here.")
559
-
560
- return log_message
561
-
562
- if (
563
- await is_user_ban_protected(chat, user_id, member)
564
- and admin_user not in DEV_USERS
565
- ):
566
- if user_id == OWNER_ID:
567
- await message.edit_text(
568
- "Trying to put me against a God level disaster huh?"
569
- )
570
- elif user_id in DEV_USERS:
571
- await message.edit_text("I can't act against our own.")
572
- elif user_id in DRAGONS:
573
- await message.edit_text(
574
- "Fighting this Dragon here will put me and my people's at risk.",
575
- )
576
- else:
577
- await message.edit_text(
578
- "This user has immunity and cannot be banned."
579
- )
580
- return log_message
581
-
582
- log = (
583
- f"<b>{html.escape(chat.title)}:</b>\n"
584
- f"#BANNED\n"
585
- f"<b>Admin:</b> {mention_html(admin_user.id, html.escape(admin_user.first_name))}\n"
586
- )
587
-
588
- reply = f"<code>❕</code><b>Ban Event</b>\n"
589
-
590
- if CHAT_SENDER:
591
- log += f"<b>Channel:</b> {html.escape(chat_name)}"
592
- reply += f"<code> </code><b>• Channel:</b> {html.escape(chat_name)}"
593
-
594
- else:
595
- log += f"<b>User:</b> {mention_html(member.user.id, html.escape(member.user.first_name))}"
596
- reply += f"<code> </code><b>• User:</b> {mention_html(member.user.id, html.escape(member.user.first_name))}"
597
-
598
- if reason:
599
- log += "\n<b>Reason:</b> {}".format(reason)
600
-
601
- try:
602
- if CHAT_SENDER:
603
- await chat.ban_sender_chat(sender_chat_id=user_id)
604
- else:
605
- await chat.ban_member(user_id)
606
-
607
- await bot.send_sticker(
608
- chat.id,
609
- BAN_STICKER,
610
- message_thread_id=message.message_thread_id if chat.is_forum else None,
611
- ) # banhammer marie sticker
612
-
613
- if reason:
614
- reply += f"\n<code> </code><b>• Reason:</b> \n{html.escape(reason)}"
615
- await bot.sendMessage(
616
- chat.id,
617
- reply,
618
- parse_mode=ParseMode.HTML,
619
- message_thread_id=message.message_thread_id if chat.is_forum else None,
620
- )
621
- await query.answer(f"Done Banned User.")
622
- return log
623
-
624
- except BadRequest as excp:
625
- if excp.message == "Reply message not found":
626
- # Do not reply
627
- await message.edit_text("Banned!")
628
- return log
629
- else:
630
- LOGGER.warning(update)
631
- LOGGER.exception(
632
- "ERROR banning user %s in chat %s (%s) due to %s",
633
- user_id,
634
- chat.title,
635
- chat.id,
636
- excp.message,
637
- )
638
- await message.edit_text("Uhm...that didn't work...")
639
-
640
- return log_message
641
-
642
- elif splitter[1] == "unban":
643
- try:
644
- user_id = int(splitter[2])
645
- except ValueError:
646
- user_id = splitter[2]
647
- reason = splitter[3]
648
-
649
- if isinstance(user_id, str):
650
- await message.edit_text("I doubt that's a user.")
651
- return log_message
652
-
653
- if user_id == bot.id:
654
- await message.edit_text("How would i unban myself if i wasn't here...?")
655
- return log_message
656
-
657
- if user_id < 0:
658
- CHAT_SENDER = True
659
- chat_title = splitter[4]
660
- else:
661
- CHAT_SENDER = False
662
-
663
- try:
664
- member = await chat.get_member(user_id)
665
- except BadRequest as excp:
666
- if excp.message != "User not found":
667
- raise
668
- await message.edit_text("I can't seem to find this user.")
669
- return log_message
670
-
671
- if await is_user_in_chat(chat, user_id):
672
- await message.edit_text("Isn't this person already here??")
673
- return log_message
674
-
675
- log = (
676
- f"<b>{html.escape(chat.title)}:</b>\n"
677
- f"#UNBANNED\n"
678
- f"<b>Admin:</b> {mention_html(admin_user.id, html.escape(admin_user.first_name))}\n"
679
- )
680
-
681
- if CHAT_SENDER:
682
- log += f"<b>User:</b> {html.escape(chat_title)}"
683
- await chat.unban_sender_chat(user_id)
684
- await message.reply_text("Yeah, this channel can speak again.")
685
- else:
686
- log += f"<b>User:</b> {mention_html(member.user.id, html.escape(member.user.first_name))}"
687
- await chat.unban_member(user_id)
688
- await message.reply_text("Yeah, this user can join!")
689
-
690
- if reason:
691
- log += f"\n<b>Reason:</b> {reason}"
692
-
693
- return log
694
-
695
-
696
- # <================================================ HELP =======================================================>
697
-
698
-
699
- __help__ = """
700
- » /kickme: kicks the user who issued the command
701
-
702
- ➠ *Admins only:*
703
- » /ban <userhandle>: bans a user/channel. (via handle, or reply)
704
-
705
- » /sban <userhandle>: Silently ban a user. Deletes command, Replied message and doesn't reply. (via handle, or reply)
706
-
707
- » /tban <userhandle> x(m/h/d): bans a user for `x` time. (via handle, or reply). `m` = `minutes`, `h` = `hours`, `d` = `days`.
708
-
709
- » /unban <userhandle>: unbans a user/channel. (via handle, or reply)
710
-
711
- » /kick <userhandle>: kicks a user out of the group, (via handle, or reply)
712
-
713
- ➠ NOTE:
714
- Banning or UnBanning channels only work if you reply to their message, so don't use their username to ban/unban.
715
- """
716
-
717
- # <================================================ HANDLER =======================================================>
718
- BAN_HANDLER = CommandHandler(["ban", "sban"], ban, block=False)
719
- TEMPBAN_HANDLER = CommandHandler(["tban"], temp_ban, block=False)
720
- KICK_HANDLER = CommandHandler("kick", kick, block=False)
721
- UNBAN_HANDLER = CommandHandler("unban", unban, block=False)
722
- ROAR_HANDLER = CommandHandler("roar", selfunban, block=False)
723
- KICKME_HANDLER = DisableAbleCommandHandler(
724
- "kickme", kickme, filters=filters.ChatType.GROUPS, block=False
725
- )
726
- BAN_CALLBACK_HANDLER = CallbackQueryHandler(
727
- bans_callback, block=False, pattern=r"bans_"
728
- )
729
-
730
- function(BAN_HANDLER)
731
- function(TEMPBAN_HANDLER)
732
- function(KICK_HANDLER)
733
- function(UNBAN_HANDLER)
734
- function(ROAR_HANDLER)
735
- function(KICKME_HANDLER)
736
- function(BAN_CALLBACK_HANDLER)
737
-
738
- __mod_name__ = "BAN"
739
- __handlers__ = [
740
- BAN_HANDLER,
741
- TEMPBAN_HANDLER,
742
- KICK_HANDLER,
743
- UNBAN_HANDLER,
744
- ROAR_HANDLER,
745
- KICKME_HANDLER,
746
- BAN_CALLBACK_HANDLER,
747
- ]
748
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/blacklist.py DELETED
@@ -1,548 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import html
3
- import re
4
-
5
- from telegram import ChatPermissions, Update
6
- from telegram.constants import ParseMode
7
- from telegram.error import BadRequest
8
- from telegram.ext import CommandHandler, ContextTypes, MessageHandler, filters
9
- from telegram.helpers import mention_html
10
-
11
- import Database.sql.blacklist_sql as sql
12
- from Database.sql.approve_sql import is_approved
13
- from Mikobot import LOGGER, dispatcher, function
14
- from Mikobot.plugins.connection import connected
15
- from Mikobot.plugins.disable import DisableAbleCommandHandler
16
- from Mikobot.plugins.helper_funcs.alternate import send_message, typing_action
17
- from Mikobot.plugins.helper_funcs.chat_status import check_admin, user_not_admin
18
- from Mikobot.plugins.helper_funcs.extraction import extract_text
19
- from Mikobot.plugins.helper_funcs.misc import split_message
20
- from Mikobot.plugins.helper_funcs.string_handling import extract_time
21
- from Mikobot.plugins.log_channel import loggable
22
- from Mikobot.plugins.warns import warn
23
-
24
- # <=======================================================================================================>
25
-
26
- BLACKLIST_GROUP = 11
27
-
28
-
29
- # <================================================ FUNCTION =======================================================>
30
- @check_admin(is_user=True)
31
- @typing_action
32
- async def blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
33
- chat = update.effective_chat
34
- user = update.effective_user
35
- args = context.args
36
-
37
- conn = await connected(context.bot, update, chat, user.id, need_admin=False)
38
- if conn:
39
- chat_id = conn
40
- chat_obj = await dispatcher.bot.getChat(conn)
41
- chat_name = chat_obj.title
42
- else:
43
- if chat.type == "private":
44
- return
45
- chat_id = update.effective_chat.id
46
- chat_name = chat.title
47
-
48
- filter_list = "Current blacklisted words in <b>{}</b>:\n".format(chat_name)
49
-
50
- all_blacklisted = sql.get_chat_blacklist(chat_id)
51
-
52
- if len(args) > 0 and args[0].lower() == "copy":
53
- for trigger in all_blacklisted:
54
- filter_list += "<code>{}</code>\n".format(html.escape(trigger))
55
- else:
56
- for trigger in all_blacklisted:
57
- filter_list += " - <code>{}</code>\n".format(html.escape(trigger))
58
-
59
- # for trigger in all_blacklisted:
60
- # filter_list += " - <code>{}</code>\n".format(html.escape(trigger))
61
-
62
- split_text = split_message(filter_list)
63
- for text in split_text:
64
- if filter_list == "Current blacklisted words in <b>{}</b>:\n".format(
65
- html.escape(chat_name),
66
- ):
67
- await send_message(
68
- update.effective_message,
69
- "No blacklisted words in <b>{}</b>!".format(html.escape(chat_name)),
70
- parse_mode=ParseMode.HTML,
71
- )
72
- return
73
- await send_message(update.effective_message, text, parse_mode=ParseMode.HTML)
74
-
75
-
76
- @check_admin(is_user=True)
77
- @typing_action
78
- async def add_blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
79
- msg = update.effective_message
80
- chat = update.effective_chat
81
- user = update.effective_user
82
- words = msg.text.split(None, 1)
83
-
84
- conn = await connected(context.bot, update, chat, user.id)
85
- if conn:
86
- chat_id = conn
87
- chat_obj = await dispatcher.bot.getChat(conn)
88
- chat_name = chat_obj.title
89
- else:
90
- chat_id = update.effective_chat.id
91
- if chat.type == "private":
92
- return
93
- else:
94
- chat_name = chat.title
95
-
96
- if len(words) > 1:
97
- text = words[1]
98
- to_blacklist = list(
99
- {trigger.strip() for trigger in text.split("\n") if trigger.strip()},
100
- )
101
- for trigger in to_blacklist:
102
- sql.add_to_blacklist(chat_id, trigger.lower())
103
-
104
- if len(to_blacklist) == 1:
105
- await send_message(
106
- update.effective_message,
107
- "Added blacklist <code>{}</code> in chat: <b>{}</b>!".format(
108
- html.escape(to_blacklist[0]),
109
- html.escape(chat_name),
110
- ),
111
- parse_mode=ParseMode.HTML,
112
- )
113
-
114
- else:
115
- await send_message(
116
- update.effective_message,
117
- "Added blacklist trigger: <code>{}</code> in <b>{}</b>!".format(
118
- len(to_blacklist),
119
- html.escape(chat_name),
120
- ),
121
- parse_mode=ParseMode.HTML,
122
- )
123
-
124
- else:
125
- await send_message(
126
- update.effective_message,
127
- "Tell me which words you would like to add in blacklist.",
128
- )
129
-
130
-
131
- @check_admin(is_user=True)
132
- @typing_action
133
- async def unblacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
134
- msg = update.effective_message
135
- chat = update.effective_chat
136
- user = update.effective_user
137
- words = msg.text.split(None, 1)
138
-
139
- conn = await connected(context.bot, update, chat, user.id)
140
- if conn:
141
- chat_id = conn
142
- chat_obj = await dispatcher.bot.getChat(conn)
143
- chat_name = chat_obj.title
144
- else:
145
- chat_id = update.effective_chat.id
146
- if chat.type == "private":
147
- return
148
- else:
149
- chat_name = chat.title
150
-
151
- if len(words) > 1:
152
- text = words[1]
153
- to_unblacklist = list(
154
- {trigger.strip() for trigger in text.split("\n") if trigger.strip()},
155
- )
156
- successful = 0
157
- for trigger in to_unblacklist:
158
- success = sql.rm_from_blacklist(chat_id, trigger.lower())
159
- if success:
160
- successful += 1
161
-
162
- if len(to_unblacklist) == 1:
163
- if successful:
164
- await send_message(
165
- update.effective_message,
166
- "Removed <code>{}</code> from blacklist in <b>{}</b>!".format(
167
- html.escape(to_unblacklist[0]),
168
- html.escape(chat_name),
169
- ),
170
- parse_mode=ParseMode.HTML,
171
- )
172
- else:
173
- await send_message(
174
- update.effective_message,
175
- "This is not a blacklist trigger!",
176
- )
177
-
178
- elif successful == len(to_unblacklist):
179
- await send_message(
180
- update.effective_message,
181
- "Removed <code>{}</code> from blacklist in <b>{}</b>!".format(
182
- successful,
183
- html.escape(chat_name),
184
- ),
185
- parse_mode=ParseMode.HTML,
186
- )
187
-
188
- elif not successful:
189
- await send_message(
190
- update.effective_message,
191
- "None of these triggers exist so it can't be removed.",
192
- parse_mode=ParseMode.HTML,
193
- )
194
-
195
- else:
196
- await send_message(
197
- update.effective_message,
198
- "Removed <code>{}</code> from blacklist. {} did not exist, "
199
- "so were not removed.".format(
200
- successful,
201
- len(to_unblacklist) - successful,
202
- ),
203
- parse_mode=ParseMode.HTML,
204
- )
205
- else:
206
- await send_message(
207
- update.effective_message,
208
- "Tell me which words you would like to remove from blacklist!",
209
- )
210
-
211
-
212
- @loggable
213
- @check_admin(is_user=True)
214
- @typing_action
215
- async def blacklist_mode(update: Update, context: ContextTypes.DEFAULT_TYPE):
216
- chat = update.effective_chat
217
- user = update.effective_user
218
- msg = update.effective_message
219
- args = context.args
220
-
221
- conn = await connected(context.bot, update, chat, user.id, need_admin=True)
222
- if conn:
223
- chat = await dispatcher.bot.getChat(conn)
224
- chat_id = conn
225
- chat_obj = await dispatcher.bot.getChat(conn)
226
- chat_name = chat_obj.title
227
- else:
228
- if update.effective_message.chat.type == "private":
229
- await send_message(
230
- update.effective_message,
231
- "This command can be only used in group not in PM",
232
- )
233
- return ""
234
- chat = update.effective_chat
235
- chat_id = update.effective_chat.id
236
- chat_name = update.effective_message.chat.title
237
-
238
- if args:
239
- if args[0].lower() in ["off", "nothing", "no"]:
240
- settypeblacklist = "do nothing"
241
- sql.set_blacklist_strength(chat_id, 0, "0")
242
- elif args[0].lower() in ["del", "delete"]:
243
- settypeblacklist = "delete blacklisted message"
244
- sql.set_blacklist_strength(chat_id, 1, "0")
245
- elif args[0].lower() == "warn":
246
- settypeblacklist = "warn the sender"
247
- sql.set_blacklist_strength(chat_id, 2, "0")
248
- elif args[0].lower() == "mute":
249
- settypeblacklist = "mute the sender"
250
- sql.set_blacklist_strength(chat_id, 3, "0")
251
- elif args[0].lower() == "kick":
252
- settypeblacklist = "kick the sender"
253
- sql.set_blacklist_strength(chat_id, 4, "0")
254
- elif args[0].lower() == "ban":
255
- settypeblacklist = "ban the sender"
256
- sql.set_blacklist_strength(chat_id, 5, "0")
257
- elif args[0].lower() == "tban":
258
- if len(args) == 1:
259
- teks = """It looks like you tried to set time value for blacklist but you didn't specified time; Try, `/blacklistmode tban <timevalue>`.
260
-
261
- Examples of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
262
- await send_message(
263
- update.effective_message, teks, parse_mode="markdown"
264
- )
265
- return ""
266
- restime = await extract_time(msg, args[1])
267
- if not restime:
268
- teks = """Invalid time value!
269
- Example of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
270
- await send_message(
271
- update.effective_message, teks, parse_mode="markdown"
272
- )
273
- return ""
274
- settypeblacklist = "temporarily ban for {}".format(args[1])
275
- sql.set_blacklist_strength(chat_id, 6, str(args[1]))
276
- elif args[0].lower() == "tmute":
277
- if len(args) == 1:
278
- teks = """It looks like you tried to set time value for blacklist but you didn't specified time; try, `/blacklistmode tmute <timevalue>`.
279
-
280
- Examples of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
281
- await send_message(
282
- update.effective_message, teks, parse_mode="markdown"
283
- )
284
- return ""
285
- restime = await extract_time(msg, args[1])
286
- if not restime:
287
- teks = """Invalid time value!
288
- Examples of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
289
- await send_message(
290
- update.effective_message, teks, parse_mode="markdown"
291
- )
292
- return ""
293
- settypeblacklist = "temporarily mute for {}".format(args[1])
294
- sql.set_blacklist_strength(chat_id, 7, str(args[1]))
295
- else:
296
- await send_message(
297
- update.effective_message,
298
- "I only understand: off/del/warn/ban/kick/mute/tban/tmute!",
299
- )
300
- return ""
301
- if conn:
302
- text = "Changed blacklist mode: `{}` in *{}*!".format(
303
- settypeblacklist,
304
- chat_name,
305
- )
306
- else:
307
- text = "Changed blacklist mode: `{}`!".format(settypeblacklist)
308
- await send_message(update.effective_message, text, parse_mode="markdown")
309
- return (
310
- "<b>{}:</b>\n"
311
- "<b>Admin:</b> {}\n"
312
- "Changed the blacklist mode. will {}.".format(
313
- html.escape(chat.title),
314
- mention_html(user.id, html.escape(user.first_name)),
315
- settypeblacklist,
316
- )
317
- )
318
- else:
319
- getmode, getvalue = sql.get_blacklist_setting(chat.id)
320
- if getmode == 0:
321
- settypeblacklist = "do nothing"
322
- elif getmode == 1:
323
- settypeblacklist = "delete"
324
- elif getmode == 2:
325
- settypeblacklist = "warn"
326
- elif getmode == 3:
327
- settypeblacklist = "mute"
328
- elif getmode == 4:
329
- settypeblacklist = "kick"
330
- elif getmode == 5:
331
- settypeblacklist = "ban"
332
- elif getmode == 6:
333
- settypeblacklist = "temporarily ban for {}".format(getvalue)
334
- elif getmode == 7:
335
- settypeblacklist = "temporarily mute for {}".format(getvalue)
336
- if conn:
337
- text = "Current blacklistmode: *{}* in *{}*.".format(
338
- settypeblacklist,
339
- chat_name,
340
- )
341
- else:
342
- text = "Current blacklistmode: *{}*.".format(settypeblacklist)
343
- await send_message(
344
- update.effective_message, text, parse_mode=ParseMode.MARKDOWN
345
- )
346
- return ""
347
-
348
-
349
- def findall(p, s):
350
- i = s.find(p)
351
- while i != -1:
352
- yield i
353
- i = s.find(p, i + 1)
354
-
355
-
356
- @user_not_admin
357
- async def del_blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
358
- chat = update.effective_chat
359
- message = update.effective_message
360
- user = update.effective_user
361
- bot = context.bot
362
- to_match = await extract_text(message)
363
- if not to_match:
364
- return
365
- if is_approved(chat.id, user.id):
366
- return
367
- getmode, value = sql.get_blacklist_setting(chat.id)
368
-
369
- chat_filters = sql.get_chat_blacklist(chat.id)
370
- for trigger in chat_filters:
371
- pattern = r"( |^|[^\w])" + re.escape(trigger) + r"( |$|[^\w])"
372
- if re.search(pattern, to_match, flags=re.IGNORECASE):
373
- try:
374
- if getmode == 0:
375
- return
376
- elif getmode == 1:
377
- try:
378
- await message.delete()
379
- except BadRequest:
380
- pass
381
- elif getmode == 2:
382
- try:
383
- await message.delete()
384
- except BadRequest:
385
- pass
386
- warn(
387
- update.effective_user,
388
- chat,
389
- ("Using blacklisted trigger: {}".format(trigger)),
390
- message,
391
- update.effective_user,
392
- )
393
- return
394
- elif getmode == 3:
395
- await message.delete()
396
- await bot.restrict_chat_member(
397
- chat.id,
398
- update.effective_user.id,
399
- permissions=ChatPermissions(can_send_messages=False),
400
- )
401
- await bot.sendMessage(
402
- chat.id,
403
- f"Muted {user.first_name} for using Blacklisted word: {trigger}!",
404
- message_thread_id=message.message_thread_id
405
- if chat.is_forum
406
- else None,
407
- )
408
- return
409
- elif getmode == 4:
410
- await message.delete()
411
- res = chat.unban_member(update.effective_user.id)
412
- if res:
413
- await bot.sendMessage(
414
- chat.id,
415
- f"Kicked {user.first_name} for using Blacklisted word: {trigger}!",
416
- message_thread_id=message.message_thread_id
417
- if chat.is_forum
418
- else None,
419
- )
420
- return
421
- elif getmode == 5:
422
- await message.delete()
423
- await chat.ban_member(user.id)
424
- await bot.sendMessage(
425
- chat.id,
426
- f"Banned {user.first_name} for using Blacklisted word: {trigger}",
427
- message_thread_id=message.message_thread_id
428
- if chat.is_forum
429
- else None,
430
- )
431
- return
432
- elif getmode == 6:
433
- await message.delete()
434
- bantime = await extract_time(message, value)
435
- await chat.ban_member(user.id, until_date=bantime)
436
- await bot.sendMessage(
437
- chat.id,
438
- f"Banned {user.first_name} until '{value}' for using Blacklisted word: {trigger}!",
439
- message_thread_id=message.message_thread_id
440
- if chat.is_forum
441
- else None,
442
- )
443
- return
444
- elif getmode == 7:
445
- await message.delete()
446
- mutetime = await extract_time(message, value)
447
- await bot.restrict_chat_member(
448
- chat.id,
449
- user.id,
450
- until_date=mutetime,
451
- permissions=ChatPermissions(can_send_messages=False),
452
- )
453
- await bot.sendMessage(
454
- chat.id,
455
- f"Muted {user.first_name} until '{value}' for using Blacklisted word: {trigger}!",
456
- message_thread_id=message.message_thread_id
457
- if chat.is_forum
458
- else None,
459
- )
460
- return
461
- except BadRequest as excp:
462
- if excp.message != "Message to delete not found":
463
- LOGGER.exception("Error while deleting blacklist message.")
464
- break
465
-
466
-
467
- async def __import_data__(chat_id, data, message):
468
- # set chat blacklist
469
- blacklist = data.get("blacklist", {})
470
- for trigger in blacklist:
471
- sql.add_to_blacklist(chat_id, trigger)
472
-
473
-
474
- def __migrate__(old_chat_id, new_chat_id):
475
- sql.migrate_chat(old_chat_id, new_chat_id)
476
-
477
-
478
- def __chat_settings__(chat_id, user_id):
479
- blacklisted = sql.num_blacklist_chat_filters(chat_id)
480
- return "There are {} blacklisted words.".format(blacklisted)
481
-
482
-
483
- def __stats__():
484
- return "• {} blacklist triggers, across {} chats.".format(
485
- sql.num_blacklist_filters(),
486
- sql.num_blacklist_filter_chats(),
487
- )
488
-
489
-
490
- # <=================================================== HELP ====================================================>
491
-
492
-
493
- __mod_name__ = "BLACKLIST"
494
-
495
- __help__ = """
496
-
497
- ➠ Blacklists are used to stop certain triggers from being said in a group. Any time the trigger is mentioned, the message will immediately be deleted. A good combo is sometimes to pair this up with warn filters!
498
-
499
- ➠ *NOTE*: Blacklists do not affect group admins.
500
-
501
- » /blacklist: View the current blacklisted words.
502
-
503
- Admin only:
504
- » /addblacklist <triggers>: Add a trigger to the blacklist. Each line is considered one trigger, so using different lines will allow you to add multiple triggers.
505
- » /unblacklist <triggers>: Remove triggers from the blacklist. Same newline logic applies here, so you can remove multiple triggers at once.
506
- » /blacklistmode <off/del/warn/ban/kick/mute/tban/tmute>: Action to perform when someone sends blacklisted words.
507
-
508
- ➠ Blacklist sticker is used to stop certain stickers. Whenever a sticker is sent, the message will be deleted immediately.
509
- ➠ *NOTE:* Blacklist stickers do not affect the group admin
510
- » /blsticker: See current blacklisted sticker
511
- ➠ *Only admin:*
512
- » /addblsticker <sticker link>: Add the sticker trigger to the black list. Can be added via reply sticker
513
- » /unblsticker <sticker link>: Remove triggers from blacklist. The same newline logic applies here, so you can delete multiple triggers at once
514
- » /rmblsticker <sticker link>: Same as above
515
- » /blstickermode <delete/ban/tban/mute/tmute>: sets up a default action on what to do if users use blacklisted stickers
516
- Note:
517
- » <sticker link> can be https://t.me/addstickers/<sticker> or just <sticker> or reply to the sticker message
518
-
519
- """
520
-
521
- # <================================================ HANDLER =======================================================>
522
- BLACKLIST_HANDLER = DisableAbleCommandHandler(
523
- "blacklist", blacklist, admin_ok=True, block=False
524
- )
525
- ADD_BLACKLIST_HANDLER = CommandHandler("addblacklist", add_blacklist, block=False)
526
- UNBLACKLIST_HANDLER = CommandHandler("unblacklist", unblacklist, block=False)
527
- BLACKLISTMODE_HANDLER = CommandHandler("blacklistmode", blacklist_mode, block=False)
528
- BLACKLIST_DEL_HANDLER = MessageHandler(
529
- (filters.TEXT | filters.COMMAND | filters.Sticker.ALL | filters.PHOTO)
530
- & filters.ChatType.GROUPS,
531
- del_blacklist,
532
- block=False,
533
- )
534
-
535
- function(BLACKLIST_HANDLER)
536
- function(ADD_BLACKLIST_HANDLER)
537
- function(UNBLACKLIST_HANDLER)
538
- function(BLACKLISTMODE_HANDLER)
539
- function(BLACKLIST_DEL_HANDLER, group=BLACKLIST_GROUP)
540
-
541
- __handlers__ = [
542
- BLACKLIST_HANDLER,
543
- ADD_BLACKLIST_HANDLER,
544
- UNBLACKLIST_HANDLER,
545
- BLACKLISTMODE_HANDLER,
546
- (BLACKLIST_DEL_HANDLER, BLACKLIST_GROUP),
547
- ]
548
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/blacklist_stickers.py DELETED
@@ -1,581 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import html
3
-
4
- from telegram import ChatPermissions, Update
5
- from telegram.constants import ParseMode
6
- from telegram.error import BadRequest
7
- from telegram.ext import CommandHandler, ContextTypes, MessageHandler, filters
8
- from telegram.helpers import mention_html, mention_markdown
9
-
10
- import Database.sql.blsticker_sql as sql
11
- from Mikobot import LOGGER, dispatcher
12
- from Mikobot.plugins.connection import connected
13
- from Mikobot.plugins.disable import DisableAbleCommandHandler
14
- from Mikobot.plugins.helper_funcs.alternate import send_message
15
- from Mikobot.plugins.helper_funcs.chat_status import check_admin, user_not_admin
16
- from Mikobot.plugins.helper_funcs.misc import split_message
17
- from Mikobot.plugins.helper_funcs.string_handling import extract_time
18
- from Mikobot.plugins.log_channel import loggable
19
- from Mikobot.plugins.warns import warn
20
-
21
- # <=======================================================================================================>
22
-
23
-
24
- # <================================================ FUNCTION =======================================================>
25
- async def blackliststicker(update: Update, context: ContextTypes.DEFAULT_TYPE):
26
- msg = update.effective_message # type: Optional[Message]
27
- chat = update.effective_chat # type: Optional[Chat]
28
- user = update.effective_user # type: Optional[User]
29
- bot, args = context.bot, context.args
30
- conn = await connected(bot, update, chat, user.id, need_admin=False)
31
- if conn:
32
- chat_id = conn
33
- chat_obj = await dispatcher.bot.getChat(conn)
34
- chat_name = chat_obj.title
35
- else:
36
- if chat.type == "private":
37
- return
38
- chat_id = update.effective_chat.id
39
- chat_name = chat.title
40
-
41
- sticker_list = "<b>List blacklisted stickers currently in {}:</b>\n".format(
42
- chat_name,
43
- )
44
-
45
- all_stickerlist = sql.get_chat_stickers(chat_id)
46
-
47
- if len(args) > 0 and args[0].lower() == "copy":
48
- for trigger in all_stickerlist:
49
- sticker_list += "<code>{}</code>\n".format(html.escape(trigger))
50
- elif len(args) == 0:
51
- for trigger in all_stickerlist:
52
- sticker_list += " - <code>{}</code>\n".format(html.escape(trigger))
53
-
54
- split_text = split_message(sticker_list)
55
- for text in split_text:
56
- if sticker_list == "<b>List blacklisted stickers currently in {}:</b>\n".format(
57
- chat_name,
58
- ).format(html.escape(chat_name)):
59
- await send_message(
60
- update.effective_message,
61
- "There are no blacklist stickers in <b>{}</b>!".format(
62
- html.escape(chat_name),
63
- ),
64
- parse_mode=ParseMode.HTML,
65
- )
66
- return
67
- await send_message(
68
- update.effective_message,
69
- text,
70
- parse_mode=ParseMode.HTML,
71
- )
72
-
73
-
74
- @check_admin(is_user=True)
75
- async def add_blackliststicker(update: Update, context: ContextTypes.DEFAULT_TYPE):
76
- bot = context.bot
77
- msg = update.effective_message # type: Optional[Message]
78
- chat = update.effective_chat # type: Optional[Chat]
79
- user = update.effective_user # type: Optional[User]
80
- words = msg.text.split(None, 1)
81
- bot = context.bot
82
- conn = await connected(bot, update, chat, user.id)
83
- if conn:
84
- chat_id = conn
85
- chat_obj = await dispatcher.bot.getChat(conn)
86
- chat_name = chat_obj.title
87
- else:
88
- chat_id = update.effective_chat.id
89
- if chat.type == "private":
90
- return
91
- else:
92
- chat_name = chat.title
93
-
94
- if len(words) > 1:
95
- text = words[1].replace("https://t.me/addstickers/", "")
96
- to_blacklist = list(
97
- {trigger.strip() for trigger in text.split("\n") if trigger.strip()},
98
- )
99
-
100
- added = 0
101
- for trigger in to_blacklist:
102
- try:
103
- get = await bot.getStickerSet(trigger)
104
- sql.add_to_stickers(chat_id, trigger.lower())
105
- added += 1
106
- except BadRequest:
107
- await send_message(
108
- update.effective_message,
109
- "Sticker `{}` can not be found!".format(trigger),
110
- parse_mode="markdown",
111
- )
112
-
113
- if added == 0:
114
- return
115
-
116
- if len(to_blacklist) == 1:
117
- await send_message(
118
- update.effective_message,
119
- "Sticker <code>{}</code> added to blacklist stickers in <b>{}</b>!".format(
120
- html.escape(to_blacklist[0]),
121
- html.escape(chat_name),
122
- ),
123
- parse_mode=ParseMode.HTML,
124
- )
125
- else:
126
- await send_message(
127
- update.effective_message,
128
- "<code>{}</code> stickers added to blacklist sticker in <b>{}</b>!".format(
129
- added,
130
- html.escape(chat_name),
131
- ),
132
- parse_mode=ParseMode.HTML,
133
- )
134
- elif msg.reply_to_message:
135
- added = 0
136
- trigger = msg.reply_to_message.sticker.set_name
137
- if trigger is None:
138
- await send_message(
139
- update.effective_message,
140
- "Sticker is invalid!",
141
- )
142
- return
143
- try:
144
- get = await bot.getStickerSet(trigger)
145
- sql.add_to_stickers(chat_id, trigger.lower())
146
- added += 1
147
- except BadRequest:
148
- await send_message(
149
- update.effective_message,
150
- "Sticker `{}` can not be found!".format(trigger),
151
- parse_mode="markdown",
152
- )
153
-
154
- if added == 0:
155
- return
156
-
157
- await send_message(
158
- update.effective_message,
159
- "Sticker <code>{}</code> added to blacklist stickers in <b>{}</b>!".format(
160
- trigger,
161
- html.escape(chat_name),
162
- ),
163
- parse_mode=ParseMode.HTML,
164
- )
165
- else:
166
- await send_message(
167
- update.effective_message,
168
- "Tell me what stickers you want to add to the blacklist.",
169
- )
170
-
171
-
172
- @check_admin(is_user=True)
173
- async def unblackliststicker(update: Update, context: ContextTypes.DEFAULT_TYPE):
174
- bot = context.bot
175
- msg = update.effective_message # type: Optional[Message]
176
- chat = update.effective_chat # type: Optional[Chat]
177
- user = update.effective_user # type: Optional[User]
178
- words = msg.text.split(None, 1)
179
- bot = context.bot
180
- conn = await connected(bot, update, chat, user.id)
181
- if conn:
182
- chat_id = conn
183
- chat_obj = await dispatcher.bot.getChat(conn)
184
- chat_name = chat_obj.title
185
- else:
186
- chat_id = update.effective_chat.id
187
- if chat.type == "private":
188
- return
189
- else:
190
- chat_name = chat.title
191
-
192
- if len(words) > 1:
193
- text = words[1].replace("https://t.me/addstickers/", "")
194
- to_unblacklist = list(
195
- {trigger.strip() for trigger in text.split("\n") if trigger.strip()},
196
- )
197
-
198
- successful = 0
199
- for trigger in to_unblacklist:
200
- success = sql.rm_from_stickers(chat_id, trigger.lower())
201
- if success:
202
- successful += 1
203
-
204
- if len(to_unblacklist) == 1:
205
- if successful:
206
- await send_message(
207
- update.effective_message,
208
- "Sticker <code>{}</code> deleted from blacklist in <b>{}</b>!".format(
209
- html.escape(to_unblacklist[0]),
210
- html.escape(chat_name),
211
- ),
212
- parse_mode=ParseMode.HTML,
213
- )
214
- else:
215
- await send_message(
216
- update.effective_message,
217
- "This sticker is not on the blacklist...!",
218
- )
219
-
220
- elif successful == len(to_unblacklist):
221
- await send_message(
222
- update.effective_message,
223
- "Sticker <code>{}</code> deleted from blacklist in <b>{}</b>!".format(
224
- successful,
225
- html.escape(chat_name),
226
- ),
227
- parse_mode=ParseMode.HTML,
228
- )
229
-
230
- elif not successful:
231
- await send_message(
232
- update.effective_message,
233
- "None of these stickers exist, so they cannot be removed.",
234
- parse_mode=ParseMode.HTML,
235
- )
236
-
237
- else:
238
- await send_message(
239
- update.effective_message,
240
- "Sticker <code>{}</code> deleted from blacklist. {} did not exist, so it's not deleted.".format(
241
- successful,
242
- len(to_unblacklist) - successful,
243
- ),
244
- parse_mode=ParseMode.HTML,
245
- )
246
- elif msg.reply_to_message:
247
- trigger = msg.reply_to_message.sticker.set_name
248
- if trigger is None:
249
- await send_message(
250
- update.effective_message,
251
- "Sticker is invalid!",
252
- )
253
- return
254
- success = sql.rm_from_stickers(chat_id, trigger.lower())
255
-
256
- if success:
257
- await send_message(
258
- update.effective_message,
259
- "Sticker <code>{}</code> deleted from blacklist in <b>{}</b>!".format(
260
- trigger,
261
- chat_name,
262
- ),
263
- parse_mode=ParseMode.HTML,
264
- )
265
- else:
266
- await send_message(
267
- update.effective_message,
268
- "{} not found on blacklisted stickers...!".format(trigger),
269
- )
270
- else:
271
- await send_message(
272
- update.effective_message,
273
- "Tell me what stickers you want to add to the blacklist.",
274
- )
275
-
276
-
277
- @loggable
278
- @check_admin(is_user=True)
279
- async def blacklist_mode(update: Update, context: ContextTypes.DEFAULT_TYPE):
280
- chat = update.effective_chat # type: Optional[Chat]
281
- user = update.effective_user # type: Optional[User]
282
- msg = update.effective_message # type: Optional[Message]
283
- bot, args = context.bot, context.args
284
- conn = await connected(bot, update, chat, user.id, need_admin=True)
285
- if conn:
286
- chat = await dispatcher.bot.getChat(conn)
287
- chat_id = conn
288
- chat_obj = await dispatcher.bot.getChat(conn)
289
- chat_name = chat_obj.title
290
- else:
291
- if update.effective_message.chat.type == "private":
292
- await send_message(
293
- update.effective_message,
294
- "You can do this command in groups, not PM",
295
- )
296
- return ""
297
- chat = update.effective_chat
298
- chat_id = update.effective_chat.id
299
- chat_name = update.effective_message.chat.title
300
-
301
- if args:
302
- if args[0].lower() in ["off", "nothing", "no"]:
303
- settypeblacklist = "turn off"
304
- sql.set_blacklist_strength(chat_id, 0, "0")
305
- elif args[0].lower() in ["del", "delete"]:
306
- settypeblacklist = "left, the message will be deleted"
307
- sql.set_blacklist_strength(chat_id, 1, "0")
308
- elif args[0].lower() == "warn":
309
- settypeblacklist = "warned"
310
- sql.set_blacklist_strength(chat_id, 2, "0")
311
- elif args[0].lower() == "mute":
312
- settypeblacklist = "muted"
313
- sql.set_blacklist_strength(chat_id, 3, "0")
314
- elif args[0].lower() == "kick":
315
- settypeblacklist = "kicked"
316
- sql.set_blacklist_strength(chat_id, 4, "0")
317
- elif args[0].lower() == "ban":
318
- settypeblacklist = "banned"
319
- sql.set_blacklist_strength(chat_id, 5, "0")
320
- elif args[0].lower() == "tban":
321
- if len(args) == 1:
322
- teks = """It looks like you are trying to set a temporary value to blacklist, but has not determined the time; use `/blstickermode tban <timevalue>`.
323
- Examples of time values: 4m = 4 minute, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
324
- await send_message(
325
- update.effective_message,
326
- teks,
327
- parse_mode="markdown",
328
- )
329
- return
330
- settypeblacklist = "temporary banned for {}".format(args[1])
331
- sql.set_blacklist_strength(chat_id, 6, str(args[1]))
332
- elif args[0].lower() == "tmute":
333
- if len(args) == 1:
334
- teks = """It looks like you are trying to set a temporary value to blacklist, but has not determined the time; use `/blstickermode tmute <timevalue>`.
335
- Examples of time values: 4m = 4 minute, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
336
- await send_message(
337
- update.effective_message,
338
- teks,
339
- parse_mode="markdown",
340
- )
341
- return
342
- settypeblacklist = "temporary muted for {}".format(args[1])
343
- sql.set_blacklist_strength(chat_id, 7, str(args[1]))
344
- else:
345
- await send_message(
346
- update.effective_message,
347
- "I only understand off/del/warn/ban/kick/mute/tban/tmute!",
348
- )
349
- return
350
- if conn:
351
- text = "Blacklist sticker mode changed, users will be `{}` at *{}*!".format(
352
- settypeblacklist,
353
- chat_name,
354
- )
355
- else:
356
- text = "Blacklist sticker mode changed, users will be `{}`!".format(
357
- settypeblacklist,
358
- )
359
- await send_message(
360
- update.effective_message,
361
- text,
362
- parse_mode="markdown",
363
- )
364
- return (
365
- "<b>{}:</b>\n"
366
- "<b>Admin:</b> {}\n"
367
- "Changed sticker blacklist mode. users will be {}.".format(
368
- html.escape(chat.title),
369
- mention_html(user.id, html.escape(user.first_name)),
370
- settypeblacklist,
371
- )
372
- )
373
- else:
374
- getmode, getvalue = sql.get_blacklist_setting(chat.id)
375
- if getmode == 0:
376
- settypeblacklist = "not active"
377
- elif getmode == 1:
378
- settypeblacklist = "delete"
379
- elif getmode == 2:
380
- settypeblacklist = "warn"
381
- elif getmode == 3:
382
- settypeblacklist = "mute"
383
- elif getmode == 4:
384
- settypeblacklist = "kick"
385
- elif getmode == 5:
386
- settypeblacklist = "ban"
387
- elif getmode == 6:
388
- settypeblacklist = "temporarily banned for {}".format(getvalue)
389
- elif getmode == 7:
390
- settypeblacklist = "temporarily muted for {}".format(getvalue)
391
- if conn:
392
- text = "Blacklist sticker mode is currently set to *{}* in *{}*.".format(
393
- settypeblacklist,
394
- chat_name,
395
- )
396
- else:
397
- text = "Blacklist sticker mode is currently set to *{}*.".format(
398
- settypeblacklist,
399
- )
400
- await send_message(
401
- update.effective_message,
402
- text,
403
- parse_mode=ParseMode.MARKDOWN,
404
- )
405
- return ""
406
-
407
-
408
- @user_not_admin
409
- async def del_blackliststicker(update: Update, context: ContextTypes.DEFAULT_TYPE):
410
- bot = context.bot
411
- chat = update.effective_chat # type: Optional[Chat]
412
- message = update.effective_message # type: Optional[Message]
413
- user = update.effective_user
414
- to_match = message.sticker
415
- if not to_match or not to_match.set_name:
416
- return
417
- bot = context.bot
418
- getmode, value = sql.get_blacklist_setting(chat.id)
419
-
420
- chat_filters = sql.get_chat_stickers(chat.id)
421
- for trigger in chat_filters:
422
- if to_match.set_name.lower() == trigger.lower():
423
- try:
424
- if getmode == 0:
425
- return
426
- elif getmode == 1:
427
- await message.delete()
428
- elif getmode == 2:
429
- await message.delete()
430
- warn(
431
- update.effective_user,
432
- chat,
433
- "Using sticker '{}' which in blacklist stickers".format(
434
- trigger,
435
- ),
436
- message,
437
- update.effective_user,
438
- # conn=False,
439
- )
440
- return
441
- elif getmode == 3:
442
- await message.delete()
443
- await bot.restrict_chat_member(
444
- chat.id,
445
- update.effective_user.id,
446
- permissions=ChatPermissions(can_send_messages=False),
447
- )
448
- await bot.sendMessage(
449
- chat.id,
450
- "{} muted because using '{}' which in blacklist stickers".format(
451
- mention_markdown(user.id, user.first_name),
452
- trigger,
453
- ),
454
- parse_mode="markdown",
455
- message_thread_id=message.message_thread_id
456
- if chat.is_forum
457
- else None,
458
- )
459
- return
460
- elif getmode == 4:
461
- await message.delete()
462
- res = chat.unban_member(update.effective_user.id)
463
- if res:
464
- await bot.sendMessage(
465
- chat.id,
466
- "{} kicked because using '{}' which in blacklist stickers".format(
467
- mention_markdown(user.id, user.first_name),
468
- trigger,
469
- ),
470
- parse_mode="markdown",
471
- message_thread_id=message.message_thread_id
472
- if chat.is_forum
473
- else None,
474
- )
475
- return
476
- elif getmode == 5:
477
- await message.delete()
478
- await chat.ban_member(user.id)
479
- await bot.sendMessage(
480
- chat.id,
481
- "{} banned because using '{}' which in blacklist stickers".format(
482
- mention_markdown(user.id, user.first_name),
483
- trigger,
484
- ),
485
- parse_mode="markdown",
486
- message_thread_id=message.message_thread_id
487
- if chat.is_forum
488
- else None,
489
- )
490
- return
491
- elif getmode == 6:
492
- await message.delete()
493
- bantime = await extract_time(message, value)
494
- await chat.ban_member(user.id, until_date=bantime)
495
- await bot.sendMessage(
496
- chat.id,
497
- "{} banned for {} because using '{}' which in blacklist stickers".format(
498
- mention_markdown(user.id, user.first_name),
499
- value,
500
- trigger,
501
- ),
502
- parse_mode="markdown",
503
- message_thread_id=message.message_thread_id
504
- if chat.is_forum
505
- else None,
506
- )
507
- return
508
- elif getmode == 7:
509
- await message.delete()
510
- mutetime = await extract_time(message, value)
511
- await bot.restrict_chat_member(
512
- chat.id,
513
- user.id,
514
- permissions=ChatPermissions(can_send_messages=False),
515
- until_date=mutetime,
516
- )
517
- await bot.sendMessage(
518
- chat.id,
519
- "{} muted for {} because using '{}' which in blacklist stickers".format(
520
- mention_markdown(user.id, user.first_name),
521
- value,
522
- trigger,
523
- ),
524
- parse_mode="markdown",
525
- message_thread_id=message.message_thread_id
526
- if chat.is_forum
527
- else None,
528
- )
529
- return
530
- except BadRequest as excp:
531
- if excp.message != "Message to delete not found":
532
- LOGGER.exception("Error while deleting blacklist message.")
533
- break
534
-
535
-
536
- async def __import_data__(chat_id, data, message):
537
- # set chat blacklist
538
- blacklist = data.get("sticker_blacklist", {})
539
- for trigger in blacklist:
540
- sql.add_to_stickers(chat_id, trigger)
541
-
542
-
543
- def __migrate__(old_chat_id, new_chat_id):
544
- sql.migrate_chat(old_chat_id, new_chat_id)
545
-
546
-
547
- def __chat_settings__(chat_id, user_id):
548
- blacklisted = sql.num_stickers_chat_filters(chat_id)
549
- return "There are `{} `blacklisted stickers.".format(blacklisted)
550
-
551
-
552
- def __stats__():
553
- return "• {} blacklist stickers, across {} chats.".format(
554
- sql.num_stickers_filters(),
555
- sql.num_stickers_filter_chats(),
556
- )
557
-
558
-
559
- __mod_name__ = "Stickers Blacklist"
560
-
561
- # <================================================ HANDLER =======================================================>
562
- BLACKLIST_STICKER_HANDLER = DisableAbleCommandHandler(
563
- "blsticker", blackliststicker, admin_ok=True, block=False
564
- )
565
- ADDBLACKLIST_STICKER_HANDLER = DisableAbleCommandHandler(
566
- "addblsticker", add_blackliststicker, block=False
567
- )
568
- UNBLACKLIST_STICKER_HANDLER = CommandHandler(
569
- ["unblsticker", "rmblsticker"], unblackliststicker, block=False
570
- )
571
- BLACKLISTMODE_HANDLER = CommandHandler("blstickermode", blacklist_mode, block=False)
572
- BLACKLIST_STICKER_DEL_HANDLER = MessageHandler(
573
- filters.Sticker.ALL & filters.ChatType.GROUPS, del_blackliststicker, block=False
574
- )
575
-
576
- dispatcher.add_handler(BLACKLIST_STICKER_HANDLER)
577
- dispatcher.add_handler(ADDBLACKLIST_STICKER_HANDLER)
578
- dispatcher.add_handler(UNBLACKLIST_STICKER_HANDLER)
579
- dispatcher.add_handler(BLACKLISTMODE_HANDLER)
580
- dispatcher.add_handler(BLACKLIST_STICKER_DEL_HANDLER)
581
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/botadmins.py DELETED
@@ -1,108 +0,0 @@
1
- # SOURCE https://github.com/Team-ProjectCodeX
2
- # CREATED BY https://t.me/O_okarma
3
- # PROVIDED BY https://t.me/ProjectCodeX
4
-
5
- # <============================================== IMPORTS =========================================================>
6
-
7
- from telegram import Update
8
- from telegram.constants import ParseMode
9
- from telegram.error import TelegramError
10
- from telegram.ext import CommandHandler, ContextTypes
11
-
12
- from Mikobot import DEMONS, DEV_USERS, DRAGONS, LOGGER, OWNER_ID, WOLVES, function
13
- from Mikobot.plugins.helper_funcs.chat_status import support_plus
14
- from Mikobot.utils.parser import mention_html
15
-
16
- # <=======================================================================================================>
17
-
18
-
19
- # <================================================ FUNCTION =======================================================>
20
- async def get_chat_member(context: ContextTypes.DEFAULT_TYPE, user_id):
21
- try:
22
- return await context.bot.get_chat_member(user_id, user_id)
23
- except TelegramError as e:
24
- LOGGER.error(f"Error getting chat member {user_id}: {e}")
25
- return None
26
-
27
-
28
- async def get_user_info(context: ContextTypes.DEFAULT_TYPE, user_id):
29
- user_info = await get_chat_member(context, user_id)
30
- return user_info.user.first_name if user_info else "Unknown User"
31
-
32
-
33
- async def get_users_info(context: ContextTypes.DEFAULT_TYPE, user_ids):
34
- return [(await get_user_info(context, user_id), user_id) for user_id in user_ids]
35
-
36
-
37
- async def get_users_list(context: ContextTypes.DEFAULT_TYPE, user_ids):
38
- return [
39
- f"• {await mention_html(name, user_id)} (<code>{user_id}</code>)"
40
- for name, user_id in await get_users_info(context, user_ids)
41
- ]
42
-
43
-
44
- @support_plus
45
- async def botstaff(update: Update, context: ContextTypes.DEFAULT_TYPE):
46
- try:
47
- owner = await get_chat_member(context, OWNER_ID)
48
- owner_info = await mention_html(owner.user.first_name, owner.user.id)
49
- reply = f"✪ <b>CREATOR :</b> {owner_info} (<code>{OWNER_ID}</code>)\n"
50
- except TelegramError as e:
51
- LOGGER.error(f"Error getting owner information: {e}")
52
- reply = ""
53
-
54
- true_dev = list(set(DEV_USERS) - {OWNER_ID})
55
- reply += "\n\n➪ <b>SPECIAL GRADE USERS :</b>\n"
56
- reply += "\n".join(await get_users_list(context, true_dev)) or "No Dev Users"
57
-
58
- true_sudo = list(set(DRAGONS) - set(DEV_USERS))
59
- reply += "\n\n➪ <b>A GRADE USERS :</b>\n"
60
- reply += "\n".join(await get_users_list(context, true_sudo)) or "No Sudo Users"
61
-
62
- reply += "\n\n➪ <b>B GRADE USERS :</b>\n"
63
- reply += "\n".join(await get_users_list(context, DEMONS)) or "No Demon Users"
64
-
65
- reply += "\n\n➪ <b>NORMAL GRADE USERS :</b>\n"
66
- reply += (
67
- "\n".join(await get_users_list(context, WOLVES))
68
- or "No additional whitelisted users"
69
- )
70
-
71
- await update.message.reply_text(reply, parse_mode=ParseMode.HTML)
72
- LOGGER.info(
73
- f"{update.message.from_user.id} fetched botstaff in {update.message.chat.id}"
74
- )
75
-
76
-
77
- # <================================================ HANDLER =======================================================>
78
- function(CommandHandler("botadmins", botstaff, block=False))
79
- # <================================================ END =======================================================>
80
-
81
-
82
- # <=================================================== HELP ====================================================>
83
- __help__ = """
84
- ➠ *BOT ADMINS ONLY:*
85
-
86
- » /stats: Shows bot stats.
87
-
88
- » /ping: see ping.
89
-
90
- » /gban: Global ban.
91
-
92
- » /gbanlist: Shows gban list.
93
-
94
- » /botadmins: Opens Bot admin lists.
95
-
96
- » /gcast: Advance broadcast system. Just reply to any message.
97
-
98
- ➠ *Write with text message*
99
-
100
- » /broadcastall
101
-
102
- » /broadcastusers
103
-
104
- » /broadcastgroups
105
- """
106
-
107
- __mod_name__ = "BOT-ADMIN"
108
- # <================================================ HANDLER =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/chatbot.py DELETED
@@ -1,188 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import asyncio
3
- import html
4
- import json
5
- import re
6
- from typing import Optional
7
-
8
- import requests
9
- from telegram import (
10
- CallbackQuery,
11
- Chat,
12
- InlineKeyboardButton,
13
- InlineKeyboardMarkup,
14
- Update,
15
- User,
16
- )
17
- from telegram.constants import ParseMode
18
- from telegram.error import BadRequest, Forbidden, RetryAfter
19
- from telegram.ext import (
20
- CallbackQueryHandler,
21
- CommandHandler,
22
- ContextTypes,
23
- MessageHandler,
24
- filters,
25
- )
26
- from telegram.helpers import mention_html
27
-
28
- import Database.sql.kuki_sql as sql
29
- from Mikobot import function
30
- from Mikobot.plugins.log_channel import gloggable
31
-
32
- # <=======================================================================================================>
33
-
34
-
35
- # <================================================ FUNCTION =======================================================>
36
- @gloggable
37
- async def kukirm(update: Update, context: ContextTypes.DEFAULT_TYPE):
38
- query: Optional[CallbackQuery] = update.callback_query
39
- user: Optional[User] = update.effective_user
40
- if match := re.match(r"rm_chat\((.+?)\)", query.data):
41
- user_id = match[1]
42
- chat: Optional[Chat] = update.effective_chat
43
- if is_kuki := sql.rem_kuki(chat.id):
44
- sql.rem_kuki(user_id)
45
- return (
46
- f"<b>{html.escape(chat.title)}:</b>\n"
47
- f"AI_DISABLED\n"
48
- f"<b>Admin:</b> {mention_html(user.id, html.escape(user.first_name))}\n"
49
- )
50
- else:
51
- await update.effective_message.edit_text(
52
- f"Chatbot disable by {mention_html(user.id, user.first_name)}.",
53
- parse_mode=ParseMode.HTML,
54
- )
55
-
56
- return ""
57
-
58
-
59
- @gloggable
60
- async def kukiadd(update: Update, context: ContextTypes.DEFAULT_TYPE):
61
- query: Optional[CallbackQuery] = update.callback_query
62
- user: Optional[User] = update.effective_user
63
- if match := re.match(r"add_chat\((.+?)\)", query.data):
64
- user_id = match[1]
65
- chat: Optional[Chat] = update.effective_chat
66
- if is_kuki := sql.set_kuki(chat.id):
67
- sql.set_kuki(user_id)
68
- return (
69
- f"<b>{html.escape(chat.title)}:</b>\n"
70
- f"AI_ENABLE\n"
71
- f"<b>Admin:</b> {mention_html(user.id, html.escape(user.first_name))}\n"
72
- )
73
- else:
74
- await update.effective_message.edit_text(
75
- f"Hey Darling Chatbot enable by {mention_html(user.id, user.first_name)}.",
76
- parse_mode=ParseMode.HTML,
77
- )
78
-
79
- return ""
80
-
81
-
82
- @gloggable
83
- async def kuki(update: Update, context: ContextTypes.DEFAULT_TYPE):
84
- update.effective_user
85
- message = update.effective_message
86
- msg = "Choose an option"
87
- keyboard = InlineKeyboardMarkup(
88
- [
89
- [InlineKeyboardButton(text="Enable", callback_data="add_chat({})")],
90
- [InlineKeyboardButton(text="Disable", callback_data="rm_chat({})")],
91
- ]
92
- )
93
- await message.reply_text(
94
- msg,
95
- reply_markup=keyboard,
96
- parse_mode=ParseMode.HTML,
97
- )
98
-
99
-
100
- async def kuki_message(context: ContextTypes.DEFAULT_TYPE, message):
101
- reply_message = message.reply_to_message
102
- if message.text.lower() == "kuki":
103
- return True
104
- if reply_message:
105
- if reply_message.from_user.id == (await context.bot.get_me()).id:
106
- return True
107
- else:
108
- return False
109
-
110
-
111
- async def chatbot(update: Update, context: ContextTypes.DEFAULT_TYPE):
112
- update.effective_user
113
- message = update.effective_message
114
- chat_id = update.effective_chat.id
115
- bot = context.bot
116
- is_kuki = sql.is_kuki(chat_id)
117
- if not is_kuki:
118
- return
119
-
120
- if message.text and not message.document:
121
- if not await kuki_message(context, message):
122
- return
123
- Message = message.text
124
- await bot.send_chat_action(chat_id, action="typing")
125
- kukiurl = requests.get(
126
- f"http://api.brainshop.ai/get?bid=176809&key=lbMN8CXTGzhn1NKG&uid=[user]&msg={Message}"
127
- )
128
-
129
- Kuki = json.loads(kukiurl.text)
130
- kuki = Kuki["cnt"]
131
-
132
- await asyncio.sleep(0.3)
133
- await message.reply_text(kuki)
134
-
135
-
136
- async def list_all_chats(update: Update, context: ContextTypes.DEFAULT_TYPE):
137
- chats = sql.get_all_kuki_chats()
138
- text = "<b>Neko Enabled Chats</b>\n"
139
- for chat in chats:
140
- try:
141
- x = await context.bot.get_chat(int(*chat))
142
- name = x.title or x.first_name
143
- text += f"• <code>{name}</code>\n"
144
- except (BadRequest, Forbidden):
145
- sql.rem_kuki(*chat)
146
- except RetryAfter as e:
147
- await asyncio.sleep(e.retry_after)
148
- await update.effective_message.reply_text(text, parse_mode="HTML")
149
-
150
-
151
- # <=================================================== HELP ====================================================>
152
-
153
-
154
- __help__ = """
155
- ➠ *Admins only command*:
156
-
157
- » /chatbot: shows chatbot panel.
158
- """
159
-
160
- __mod_name__ = "CHATBOT"
161
-
162
-
163
- # <================================================ HANDLER =======================================================>
164
- CHATBOTK_HANDLER = CommandHandler("chatbot", kuki, block=False)
165
- ADD_CHAT_HANDLER = CallbackQueryHandler(kukiadd, pattern=r"add_chat", block=False)
166
- RM_CHAT_HANDLER = CallbackQueryHandler(kukirm, pattern=r"rm_chat", block=False)
167
- CHATBOT_HANDLER = MessageHandler(
168
- filters.TEXT
169
- & (~filters.Regex(r"^#[^\s]+") & ~filters.Regex(r"^!") & ~filters.Regex(r"^\/")),
170
- chatbot,
171
- block=False,
172
- )
173
- LIST_ALL_CHATS_HANDLER = CommandHandler("allchats", list_all_chats, block=False)
174
-
175
- function(ADD_CHAT_HANDLER)
176
- function(CHATBOTK_HANDLER)
177
- function(RM_CHAT_HANDLER)
178
- function(LIST_ALL_CHATS_HANDLER)
179
- function(CHATBOT_HANDLER)
180
-
181
- __handlers__ = [
182
- ADD_CHAT_HANDLER,
183
- CHATBOTK_HANDLER,
184
- RM_CHAT_HANDLER,
185
- LIST_ALL_CHATS_HANDLER,
186
- CHATBOT_HANDLER,
187
- ]
188
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/connection.py DELETED
@@ -1,441 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import re
3
- import time
4
-
5
- from telegram import Bot, InlineKeyboardButton, InlineKeyboardMarkup, Update
6
- from telegram.constants import ParseMode
7
- from telegram.error import BadRequest, Forbidden
8
- from telegram.ext import CallbackQueryHandler, CommandHandler, ContextTypes
9
-
10
- import Database.sql.connection_sql as sql
11
- from Mikobot import DEV_USERS, DRAGONS, dispatcher, function
12
- from Mikobot.plugins.helper_funcs import chat_status
13
- from Mikobot.plugins.helper_funcs.alternate import send_message, typing_action
14
-
15
- # <=======================================================================================================>
16
-
17
- check_admin = chat_status.check_admin
18
-
19
-
20
- # <================================================ FUNCTION =======================================================>
21
- @check_admin(is_user=True)
22
- @typing_action
23
- async def allow_connections(update: Update, context: ContextTypes.DEFAULT_TYPE):
24
- chat = update.effective_chat
25
- args = context.args
26
-
27
- if chat.type != chat.PRIVATE:
28
- if len(args) >= 1:
29
- var = args[0]
30
- if var == "no":
31
- sql.set_allow_connect_to_chat(chat.id, False)
32
- await send_message(
33
- update.effective_message,
34
- "Connection has been disabled for this chat.",
35
- )
36
- elif var == "yes":
37
- sql.set_allow_connect_to_chat(chat.id, True)
38
- await send_message(
39
- update.effective_message,
40
- "Connection has been enabled for this chat.",
41
- )
42
- else:
43
- await send_message(
44
- update.effective_message,
45
- "Please enter 'yes' or 'no'!",
46
- parse_mode=ParseMode.MARKDOWN,
47
- )
48
- else:
49
- get_settings = sql.allow_connect_to_chat(chat.id)
50
- if get_settings:
51
- await send_message(
52
- update.effective_message,
53
- "Connections to this group are *allowed* for members!",
54
- parse_mode=ParseMode.MARKDOWN,
55
- )
56
- else:
57
- await send_message(
58
- update.effective_message,
59
- "Connection to this group is *not allowed* for members!",
60
- parse_mode=ParseMode.MARKDOWN,
61
- )
62
- else:
63
- await send_message(
64
- update.effective_message,
65
- "This command is for groups only, not in PM!",
66
- )
67
-
68
-
69
- @typing_action
70
- async def connection_chat(update: Update, context: ContextTypes.DEFAULT_TYPE):
71
- chat = update.effective_chat
72
- user = update.effective_user
73
-
74
- conn = await connected(context.bot, update, chat, user.id, need_admin=True)
75
-
76
- if conn:
77
- chat = await dispatcher.bot.getChat(conn)
78
- chat_obj = await dispatcher.bot.getChat(conn)
79
- chat_name = chat_obj.title
80
- else:
81
- if update.effective_message.chat.type != "private":
82
- return
83
- chat = update.effective_chat
84
- chat_name = update.effective_message.chat.title
85
-
86
- if conn:
87
- message = "You are currently connected to {}.\n".format(chat_name)
88
- else:
89
- message = "You are currently not connected in any group.\n"
90
- await send_message(update.effective_message, message, parse_mode="markdown")
91
-
92
-
93
- @typing_action
94
- async def connect_chat(update: Update, context: ContextTypes.DEFAULT_TYPE):
95
- chat = update.effective_chat
96
- user = update.effective_user
97
- args = context.args
98
-
99
- if update.effective_chat.type == "private":
100
- if args and len(args) >= 1:
101
- try:
102
- connect_chat = int(args[0])
103
- getstatusadmin = await context.bot.get_chat_member(
104
- connect_chat,
105
- update.effective_message.from_user.id,
106
- )
107
- except ValueError:
108
- try:
109
- connect_chat = str(args[0])
110
- get_chat = await context.bot.getChat(connect_chat)
111
- connect_chat = get_chat.id
112
- getstatusadmin = await context.bot.get_chat_member(
113
- connect_chat,
114
- update.effective_message.from_user.id,
115
- )
116
- except BadRequest:
117
- await send_message(update.effective_message, "Invalid Chat ID!")
118
- return
119
- except BadRequest:
120
- await send_message(update.effective_message, "Invalid Chat ID!")
121
- return
122
-
123
- isadmin = getstatusadmin.status in ("administrator", "creator")
124
- ismember = getstatusadmin.status in ("member")
125
- isallow = sql.allow_connect_to_chat(connect_chat)
126
-
127
- if (isadmin) or (isallow and ismember) or (user.id in DRAGONS):
128
- connection_status = sql.connect(
129
- update.effective_message.from_user.id,
130
- connect_chat,
131
- )
132
- if connection_status:
133
- conn = await connected(
134
- context.bot, update, chat, user.id, need_admin=False
135
- )
136
- conn_chat = await dispatcher.bot.getChat(conn)
137
- chat_name = conn_chat.title
138
- await send_message(
139
- update.effective_message,
140
- "Successfully connected to *{}*. Use /helpconnect to check available commands.".format(
141
- chat_name,
142
- ),
143
- parse_mode=ParseMode.MARKDOWN,
144
- )
145
- sql.add_history_conn(user.id, str(conn_chat.id), chat_name)
146
- else:
147
- await send_message(update.effective_message, "Connection failed!")
148
- else:
149
- await send_message(
150
- update.effective_message,
151
- "Connection to this chat is not allowed!",
152
- )
153
- else:
154
- gethistory = sql.get_history_conn(user.id)
155
- if gethistory:
156
- buttons = [
157
- InlineKeyboardButton(
158
- text="❎ Close Button",
159
- callback_data="connect_close",
160
- ),
161
- InlineKeyboardButton(
162
- text="🧹 Clear History",
163
- callback_data="connect_clear",
164
- ),
165
- ]
166
- else:
167
- buttons = []
168
- conn = await connected(context.bot, update, chat, user.id, need_admin=False)
169
- if conn:
170
- connectedchat = await dispatcher.bot.getChat(conn)
171
- text = "You are currently connected to *{}* (`{}`)".format(
172
- connectedchat.title,
173
- conn,
174
- )
175
- buttons.append(
176
- InlineKeyboardButton(
177
- text="🔌 Disconnect",
178
- callback_data="connect_disconnect",
179
- ),
180
- )
181
- else:
182
- text = "Write the chat ID or tag to connect!"
183
- if gethistory:
184
- text += "\n\n*Connection History:*\n"
185
- text += "╒═══「 *Info* 」\n"
186
- text += "│ Sorted: `Newest`\n"
187
- text += "│\n"
188
- buttons = [buttons]
189
- for x in sorted(gethistory.keys(), reverse=True):
190
- htime = time.strftime("%d/%m/%Y", time.localtime(x))
191
- text += "╞═「 *{}* 」\n│ `{}`\n│ `{}`\n".format(
192
- gethistory[x]["chat_name"],
193
- gethistory[x]["chat_id"],
194
- htime,
195
- )
196
- text += "│\n"
197
- buttons.append(
198
- [
199
- InlineKeyboardButton(
200
- text=gethistory[x]["chat_name"],
201
- callback_data="connect({})".format(
202
- gethistory[x]["chat_id"],
203
- ),
204
- ),
205
- ],
206
- )
207
- text += "╘══「 Total {} Chats 」".format(
208
- str(len(gethistory)) + " (max)"
209
- if len(gethistory) == 5
210
- else str(len(gethistory)),
211
- )
212
- conn_hist = InlineKeyboardMarkup(buttons)
213
- elif buttons:
214
- conn_hist = InlineKeyboardMarkup([buttons])
215
- else:
216
- conn_hist = None
217
- await send_message(
218
- update.effective_message,
219
- text,
220
- parse_mode="markdown",
221
- reply_markup=conn_hist,
222
- )
223
-
224
- else:
225
- getstatusadmin = await context.bot.get_chat_member(
226
- chat.id,
227
- update.effective_message.from_user.id,
228
- )
229
- isadmin = getstatusadmin.status in ("administrator", "creator")
230
- ismember = getstatusadmin.status in ("member")
231
- isallow = sql.allow_connect_to_chat(chat.id)
232
- if (isadmin) or (isallow and ismember) or (user.id in DRAGONS):
233
- connection_status = sql.connect(
234
- update.effective_message.from_user.id,
235
- chat.id,
236
- )
237
- if connection_status:
238
- chat_obj = await dispatcher.bot.getChat(chat.id)
239
- chat_name = chat_obj.title
240
- await send_message(
241
- update.effective_message,
242
- "Successfully connected to *{}*.".format(chat_name),
243
- parse_mode=ParseMode.MARKDOWN,
244
- )
245
- try:
246
- sql.add_history_conn(user.id, str(chat.id), chat_name)
247
- await context.bot.send_message(
248
- update.effective_message.from_user.id,
249
- "You are connected to *{}*. \nUse `/helpconnect` to check available commands.".format(
250
- chat_name,
251
- ),
252
- parse_mode="markdown",
253
- )
254
- except BadRequest:
255
- pass
256
- except Forbidden:
257
- pass
258
- else:
259
- await send_message(update.effective_message, "ᴄᴏɴɴᴇᴄᴛɪᴏɴ ғᴀɪʟᴇᴅ!")
260
- else:
261
- await send_message(
262
- update.effective_message,
263
- "Connection to this chat is not allowed!",
264
- )
265
-
266
-
267
- async def disconnect_chat(update: Update, context: ContextTypes.DEFAULT_TYPE):
268
- if update.effective_chat.type == "private":
269
- disconnection_status = sql.disconnect(update.effective_message.from_user.id)
270
- if disconnection_status:
271
- sql.disconnected_chat = await send_message(
272
- update.effective_message,
273
- "Disconnected from chat!",
274
- )
275
- else:
276
- await send_message(update.effective_message, "You're not connected!")
277
- else:
278
- await send_message(
279
- update.effective_message, "This command is only available in PM."
280
- )
281
-
282
-
283
- async def connected(bot: Bot, update: Update, chat, user_id, need_admin=True):
284
- user = update.effective_user
285
-
286
- if chat.type == chat.PRIVATE and sql.get_connected_chat(user_id):
287
- conn_id = sql.get_connected_chat(user_id).chat_id
288
- getstatusadmin = await bot.get_chat_member(
289
- conn_id,
290
- update.effective_message.from_user.id,
291
- )
292
- isadmin = getstatusadmin.status in ("administrator", "creator")
293
- ismember = getstatusadmin.status in ("member")
294
- isallow = sql.allow_connect_to_chat(conn_id)
295
-
296
- if (
297
- (isadmin)
298
- or (isallow and ismember)
299
- or (user.id in DRAGONS)
300
- or (user.id in DEV_USERS)
301
- ):
302
- if need_admin is True:
303
- if (
304
- getstatusadmin.status in ("administrator", "creator")
305
- or user_id in DRAGONS
306
- or user.id in DEV_USERS
307
- ):
308
- return conn_id
309
- else:
310
- await send_message(
311
- update.effective_message,
312
- "You must be an admin in the connected group!",
313
- )
314
- else:
315
- return conn_id
316
- else:
317
- await send_message(
318
- update.effective_message,
319
- "The group changed the connection rights or you are no longer an admin.\nI've disconnected you.",
320
- )
321
- disconnect_chat(update, bot)
322
- else:
323
- return False
324
-
325
-
326
- CONN_HELP = """
327
- Actions are available with connected groups:
328
- • View and edit Notes.
329
- • View and edit Filters.
330
- • Get invite link of chat.
331
- • Set and control AntiFlood settings.
332
- • Set and control Blacklist settings.
333
- • Set Locks and Unlocks in chat.
334
- • Enable and Disable commands in chat.
335
- • Export and Imports of chat backup.
336
- """
337
-
338
-
339
- async def help_connect_chat(update: Update, context: ContextTypes.DEFAULT_TYPE):
340
- context.args
341
-
342
- if update.effective_message.chat.type != "private":
343
- await send_message(
344
- update.effective_message, "PM me with that command to get help."
345
- )
346
- return
347
- else:
348
- await send_message(update.effective_message, CONN_HELP, parse_mode="markdown")
349
-
350
-
351
- async def connect_button(update: Update, context: ContextTypes.DEFAULT_TYPE):
352
- query = update.callback_query
353
- chat = update.effective_chat
354
- user = update.effective_user
355
-
356
- connect_match = re.match(r"connect\((.+?)\)", query.data)
357
- disconnect_match = query.data == "connect_disconnect"
358
- clear_match = query.data == "connect_clear"
359
- connect_close = query.data == "connect_close"
360
-
361
- if connect_match:
362
- target_chat = connect_match.group(1)
363
- getstatusadmin = await context.bot.get_chat_member(
364
- target_chat, query.from_user.id
365
- )
366
- isadmin = getstatusadmin.status in ("administrator", "creator")
367
- ismember = getstatusadmin.status in ("member")
368
- isallow = sql.allow_connect_to_chat(target_chat)
369
-
370
- if (isadmin) or (isallow and ismember) or (user.id in DRAGONS):
371
- connection_status = sql.connect(query.from_user.id, target_chat)
372
-
373
- if connection_status:
374
- conn = await connected(
375
- context.bot, update, chat, user.id, need_admin=False
376
- )
377
- conn_chat = await dispatcher.bot.getChat(conn)
378
- chat_name = conn_chat.title
379
- await query.message.edit_text(
380
- "Successfully connected to *{}*. Use `/helpconnect` to check available commands.".format(
381
- chat_name,
382
- ),
383
- parse_mode=ParseMode.MARKDOWN,
384
- )
385
- sql.add_history_conn(user.id, str(conn_chat.id), chat_name)
386
- else:
387
- await query.message.edit_text("Connection failed!")
388
- else:
389
- await context.bot.answer_callback_query(
390
- query.id,
391
- "Connection to this chat is not allowed!",
392
- show_alert=True,
393
- )
394
- elif disconnect_match:
395
- disconnection_status = sql.disconnect(query.from_user.id)
396
- if disconnection_status:
397
- sql.disconnected_chat = await query.message.edit_text(
398
- "Disconnected from chat!"
399
- )
400
- else:
401
- await context.bot.answer_callback_query(
402
- query.id,
403
- "You're not connected!",
404
- show_alert=True,
405
- )
406
- elif clear_match:
407
- sql.clear_history_conn(query.from_user.id)
408
- await query.message.edit_text("History connected has been cleared!")
409
- elif connect_close:
410
- await query.message.edit_text("Closed. To open again, type /connect")
411
- else:
412
- connect_chat(update, context)
413
-
414
-
415
- # <=================================================== HELP ====================================================>
416
- __mod_name__ = "CONNECT"
417
-
418
- __help__ = """
419
- ➠ *Sometimes, you just want to add some notes and filters to a group chat, but you don't want everyone to see; this is where connections come in. This allows you to connect to a chat's database and add things to it without the commands appearing in chat! For obvious reasons, you need to be an admin to add things, but any member in the group can view your data.*
420
-
421
- » /connect: Connects to chat (can be done in a group by /connect or /connect <chat id> in PM)
422
-
423
- » /connection: List connected chats
424
-
425
- » /disconnect: Disconnect from a chat
426
-
427
- » /helpconnect: List available commands that can be used remotely
428
-
429
- ➠ *Admin Only:*
430
-
431
- » /allowconnect <yes/no>: Allow a user to connect to a chat
432
- """
433
-
434
- # <================================================ HANDLER =======================================================>
435
- function(CommandHandler("connect", connect_chat, block=False))
436
- function(CommandHandler("connection", connection_chat, block=False))
437
- function(CommandHandler("disconnect", disconnect_chat, block=False))
438
- function(CommandHandler("allowconnect", allow_connections, block=False))
439
- function(CommandHandler("helpconnect", help_connect_chat, block=False))
440
- function(CallbackQueryHandler(connect_button, pattern=r"connect", block=False))
441
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/cosplay.py DELETED
@@ -1,37 +0,0 @@
1
- # SOURCE https://github.com/Team-ProjectCodeX
2
- # CREATED BY https://t.me/O_okarma
3
- # API BY https://www.github.com/SOME-1HING
4
- # PROVIDED BY https://t.me/ProjectCodeX
5
-
6
- # <============================================== IMPORTS =========================================================>
7
- from telegram import Update
8
- from telegram.ext import CommandHandler, ContextTypes
9
-
10
- from Mikobot import function
11
- from Mikobot.state import state
12
-
13
- # <=======================================================================================================>
14
-
15
-
16
- # <================================================ FUNCTIONS =====================================================>
17
- async def get_cosplay_data():
18
- cosplay_url = "https://sugoi-api.vercel.app/cosplay"
19
- response = await state.get(cosplay_url)
20
- return response.json()
21
-
22
-
23
- async def cosplay(update: Update, context: ContextTypes.DEFAULT_TYPE):
24
- try:
25
- data = await get_cosplay_data()
26
- photo_url = data.get("url") # Corrected key: "url" instead of "cosplay_url"
27
- if photo_url:
28
- await update.message.reply_photo(photo=photo_url)
29
- else:
30
- await update.message.reply_text("Could not fetch photo URL.")
31
- except state.FetchError:
32
- await update.message.reply_text("Unable to fetch data.")
33
-
34
-
35
- # <================================================ HANDLER =======================================================>
36
- function(CommandHandler("cosplay", cosplay, block=False))
37
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/couple.py DELETED
@@ -1,124 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import random
3
- from datetime import datetime
4
-
5
- from pyrogram import filters
6
-
7
- from Database.mongodb.karma_mongo import get_couple, save_couple
8
- from Mikobot import app
9
-
10
- # <=======================================================================================================>
11
-
12
-
13
- # <================================================ FUNCTION =======================================================>
14
- def dt():
15
- now = datetime.now()
16
- dt_string = now.strftime("%d/%m/%Y %H:%M")
17
- dt_list = dt_string.split(" ")
18
- return dt_list
19
-
20
-
21
- def dt_tom():
22
- a = (
23
- str(int(dt()[0].split("/")[0]) + 1)
24
- + "/"
25
- + dt()[0].split("/")[1]
26
- + "/"
27
- + dt()[0].split("/")[2]
28
- )
29
- return a
30
-
31
-
32
- tomorrow = str(dt_tom())
33
- today = str(dt()[0])
34
-
35
- COUPLES_PIC = "https://telegra.ph/file/c6d0c884f559b9ed8a54e.jpg"
36
- C = """
37
- ✧ 𝗖𝗢𝗨𝗣𝗟𝗘𝗦 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 ✧
38
- ➖➖➖➖➖➖➖➖➖➖➖➖
39
- {} + ( PGM🎀😶 (https://t.me/Chalnayaaaaaarr) + 花火 (https://t.me/zd_sr07) + ゼロツー (https://t.me/wewewe_x) ) = 💞
40
- ➖➖➖➖➖➖➖➖➖➖➖➖
41
- 𝗡𝗘𝗪 𝗖𝗢𝗨𝗣𝗟𝗘 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 𝗖𝗔𝗡 𝗕𝗘 𝗖𝗛𝗢𝗦𝗘𝗡 𝗔𝗧 12AM {}
42
- """
43
- CAP = """
44
- ✧ 𝗖𝗢𝗨𝗣𝗟𝗘𝗦 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 ✧
45
- ➖➖➖➖➖➖➖➖➖➖➖➖
46
- {} + {} = 💞
47
- ➖➖➖➖➖➖➖➖➖➖➖➖
48
- 𝗡𝗘𝗪 𝗖𝗢𝗨𝗣𝗟𝗘 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 𝗖𝗔𝗡 𝗕𝗘 𝗖𝗛𝗢𝗦𝗘𝗡 𝗔𝗧 12AM {}
49
- """
50
-
51
- CAP2 = """
52
- ✧ 𝗖𝗢𝗨𝗣𝗟𝗘𝗦 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 ✧
53
- ➖➖➖➖➖➖➖➖➖➖➖➖
54
- {} (tg://openmessage?user_id={}) + {} (tg://openmessage?user_id={}) = 💞\n
55
- ➖➖➖➖➖➖➖➖➖➖➖➖
56
- 𝗡𝗘𝗪 𝗖𝗢𝗨𝗣𝗟𝗘 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 𝗖𝗔𝗡 𝗕𝗘 𝗖𝗛𝗢𝗦𝗘𝗡 𝗔𝗧 12AM {}
57
- """
58
-
59
-
60
- @app.on_message(filters.command(["couple", "couples", "shipping"]) & ~filters.private)
61
- async def nibba_nibbi(_, message):
62
- if message.from_user.id == 5540249238:
63
- my_ = await _.get_users("rfxtuv")
64
- me = await _.get_users(5540249238)
65
- await message.reply_photo(
66
- photo=COUPLES_PIC, caption=C.format(me.mention, tomorrow)
67
- )
68
- else:
69
- try:
70
- chat_id = message.chat.id
71
- is_selected = await get_couple(chat_id, today)
72
- if not is_selected:
73
- list_of_users = []
74
- async for i in _.get_chat_members(message.chat.id, limit=50):
75
- if not i.user.is_bot:
76
- list_of_users.append(i.user.id)
77
- if len(list_of_users) < 2:
78
- return await message.reply_text("ɴᴏᴛ ᴇɴᴏᴜɢʜ ᴜsᴇʀs ɪɴ ᴛʜɪs ɢʀᴏᴜᴘ.")
79
- c1_id = random.choice(list_of_users)
80
- c2_id = random.choice(list_of_users)
81
- while c1_id == c2_id:
82
- c1_id = random.choice(list_of_users)
83
- c1_mention = (await _.get_users(c1_id)).mention
84
- c2_mention = (await _.get_users(c2_id)).mention
85
- await _.send_photo(
86
- message.chat.id,
87
- photo=COUPLES_PIC,
88
- caption=CAP.format(c1_mention, c2_mention, tomorrow),
89
- )
90
-
91
- couple = {"c1_id": c1_id, "c2_id": c2_id}
92
- await save_couple(chat_id, today, couple)
93
-
94
- elif is_selected:
95
- c1_id = int(is_selected["c1_id"])
96
- c2_id = int(is_selected["c2_id"])
97
-
98
- c1_name = (await _.get_users(c1_id)).first_name
99
- c2_name = (await _.get_users(c2_id)).first_name
100
- print(c1_id, c2_id, c1_name, c2_name)
101
- couple_selection_message = f"""✧ 𝗖𝗢𝗨𝗣𝗟𝗘𝗦 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 ✧
102
- ➖➖➖➖➖➖➖➖➖➖➖➖
103
- [{c1_name}](tg://openmessage?user_id={c1_id}) + [{c2_name}](tg://openmessage?user_id={c2_id}) = 💞
104
- ➖➖➖➖➖➖➖➖➖➖➖➖
105
- 𝗡𝗘𝗪 𝗖𝗢𝗨𝗣𝗟𝗘 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 𝗖𝗔𝗡 𝗕𝗘 𝗖𝗛𝗢𝗦𝗘𝗡 𝗔𝗧 12AM {tomorrow}"""
106
- await _.send_photo(
107
- message.chat.id, photo=COUPLES_PIC, caption=couple_selection_message
108
- )
109
- except Exception as e:
110
- print(e)
111
- await message.reply_text(str(e))
112
-
113
-
114
- # <=================================================== HELP ====================================================>
115
-
116
-
117
- __help__ = """
118
- 💘 *Choose couples in your chat*
119
-
120
- » /couple, /couples, /shipping *:* Choose 2 users and send their names as couples in your chat.
121
- """
122
-
123
- __mod_name__ = "COUPLE"
124
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/cust_filters.py DELETED
@@ -1,756 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import random
3
- import re
4
- from html import escape
5
-
6
- from pyrate_limiter import BucketFullException, Duration, InMemoryBucket, Limiter, Rate
7
- from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
8
- from telegram.constants import ChatMemberStatus, MessageLimit, ParseMode
9
- from telegram.error import BadRequest
10
- from telegram.ext import (
11
- ApplicationHandlerStop,
12
- CallbackQueryHandler,
13
- CommandHandler,
14
- ContextTypes,
15
- MessageHandler,
16
- )
17
- from telegram.ext import filters as filters_module
18
- from telegram.helpers import escape_markdown, mention_html
19
-
20
- from Database.sql import cust_filters_sql as sql
21
- from Mikobot import DEV_USERS, DRAGONS, LOGGER, dispatcher, function
22
- from Mikobot.plugins.connection import connected
23
- from Mikobot.plugins.disable import DisableAbleCommandHandler
24
- from Mikobot.plugins.helper_funcs.alternate import send_message, typing_action
25
- from Mikobot.plugins.helper_funcs.chat_status import check_admin
26
- from Mikobot.plugins.helper_funcs.extraction import extract_text
27
- from Mikobot.plugins.helper_funcs.misc import build_keyboard_parser
28
- from Mikobot.plugins.helper_funcs.msg_types import get_filter_type
29
- from Mikobot.plugins.helper_funcs.string_handling import (
30
- button_markdown_parser,
31
- escape_invalid_curly_brackets,
32
- markdown_to_html,
33
- split_quotes,
34
- )
35
-
36
- # <=======================================================================================================>
37
-
38
- HANDLER_GROUP = 10
39
-
40
- ENUM_FUNC_MAP = {
41
- sql.Types.TEXT.value: dispatcher.bot.send_message,
42
- sql.Types.BUTTON_TEXT.value: dispatcher.bot.send_message,
43
- sql.Types.STICKER.value: dispatcher.bot.send_sticker,
44
- sql.Types.DOCUMENT.value: dispatcher.bot.send_document,
45
- sql.Types.PHOTO.value: dispatcher.bot.send_photo,
46
- sql.Types.AUDIO.value: dispatcher.bot.send_audio,
47
- sql.Types.VOICE.value: dispatcher.bot.send_voice,
48
- sql.Types.VIDEO.value: dispatcher.bot.send_video,
49
- }
50
-
51
-
52
- class AntiSpam:
53
- def __init__(self):
54
- self.whitelist = (DEV_USERS or []) + (DRAGONS or [])
55
- # Values are HIGHLY experimental, its recommended you pay attention to our commits as we will be adjusting the values over time with what suits best.
56
- Duration.CUSTOM = 15 # Custom duration, 15 seconds
57
- self.sec_limit = Rate(6, Duration.CUSTOM) # 6 / Per 15 Seconds
58
- self.min_limit = Rate(20, Duration.MINUTE) # 20 / Per minute
59
- self.hour_limit = Rate(100, Duration.HOUR) # 100 / Per hour
60
- self.daily_limit = Rate(1000, Duration.DAY) # 1000 / Per day
61
- self.limiter = Limiter(
62
- InMemoryBucket(
63
- [self.sec_limit, self.min_limit, self.hour_limit, self.daily_limit]
64
- )
65
- )
66
-
67
- def check_user(self, user):
68
- """
69
- Return True if user is to be ignored else False
70
- """
71
- if user in self.whitelist:
72
- return False
73
- try:
74
- self.limiter.try_acquire(user)
75
- return False
76
- except BucketFullException:
77
- return True
78
-
79
-
80
- MessageHandlerChecker = AntiSpam()
81
-
82
-
83
- # <================================================ FUNCTION =======================================================>
84
- @typing_action
85
- async def list_handlers(update: Update, context: ContextTypes.DEFAULT_TYPE):
86
- chat = update.effective_chat
87
- user = update.effective_user
88
-
89
- conn = await connected(context.bot, update, chat, user.id, need_admin=False)
90
- if not conn is False:
91
- chat_id = conn
92
- chat_obj = await dispatcher.bot.getChat(conn)
93
- chat_name = chat_obj.title
94
- filter_list = "*Filter in {}:*\n"
95
- else:
96
- chat_id = update.effective_chat.id
97
- if chat.type == "private":
98
- chat_name = "Local filters"
99
- filter_list = "*local filters:*\n"
100
- else:
101
- chat_name = chat.title
102
- filter_list = "*Filters in {}*:\n"
103
-
104
- all_handlers = sql.get_chat_triggers(chat_id)
105
-
106
- if not all_handlers:
107
- await send_message(
108
- update.effective_message,
109
- "No filters saved in {}!".format(chat_name),
110
- )
111
- return
112
-
113
- for keyword in all_handlers:
114
- entry = " • `{}`\n".format(escape_markdown(keyword))
115
- if len(entry) + len(filter_list) > MessageLimit.MAX_TEXT_LENGTH:
116
- await send_message(
117
- update.effective_message,
118
- filter_list.format(chat_name),
119
- parse_mode=ParseMode.MARKDOWN,
120
- )
121
- filter_list = entry
122
- else:
123
- filter_list += entry
124
-
125
- await send_message(
126
- update.effective_message,
127
- filter_list.format(chat_name),
128
- parse_mode=ParseMode.MARKDOWN,
129
- )
130
-
131
-
132
- @typing_action
133
- @check_admin(is_user=True)
134
- async def filters(update: Update, context: ContextTypes.DEFAULT_TYPE):
135
- chat = update.effective_chat
136
- user = update.effective_user
137
- msg = update.effective_message
138
- args = msg.text.split(
139
- None, 1
140
- ) # use python's maxsplit to separate Cmd, keyword, and reply_text
141
-
142
- buttons = None
143
- conn = await connected(context.bot, update, chat, user.id)
144
- if not conn is False:
145
- chat_id = conn
146
- chat_obj = await dispatcher.bot.getChat(conn)
147
- chat_name = chat_obj.title
148
- else:
149
- chat_id = update.effective_chat.id
150
- if chat.type == "private":
151
- chat_name = "local filters"
152
- else:
153
- chat_name = chat.title
154
-
155
- if not msg.reply_to_message and len(args) < 2:
156
- await send_message(
157
- update.effective_message,
158
- "Please provide keyboard keyword for this filter to reply with!",
159
- )
160
- return
161
-
162
- if msg.reply_to_message and not msg.reply_to_message.forum_topic_created:
163
- if len(args) < 2:
164
- await send_message(
165
- update.effective_message,
166
- "Please provide keyword for this filter to reply with!",
167
- )
168
- return
169
- else:
170
- keyword = args[1]
171
- else:
172
- extracted = split_quotes(args[1])
173
- if len(extracted) < 1:
174
- return
175
- # set trigger -> lower, so as to avoid adding duplicate filters with different cases
176
- keyword = extracted[0].lower()
177
-
178
- # Add the filter
179
- # Note: perhaps handlers can be removed somehow using sql.get_chat_filters
180
- for handler in dispatcher.handlers.get(HANDLER_GROUP, []):
181
- if handler.filters == (keyword, chat_id):
182
- dispatcher.remove_handler(handler, HANDLER_GROUP)
183
-
184
- text, file_type, file_id, media_spoiler = get_filter_type(msg)
185
- if not msg.reply_to_message and len(extracted) >= 2:
186
- offset = len(extracted[1]) - len(
187
- msg.text,
188
- ) # set correct offset relative to command + notename
189
- text, buttons = button_markdown_parser(
190
- extracted[1],
191
- entities=msg.parse_entities(),
192
- offset=offset,
193
- )
194
- text = text.strip()
195
- if not text:
196
- await send_message(
197
- update.effective_message,
198
- "There is no note message - You can't JUST have buttons, you need a message to go with it!",
199
- )
200
- return
201
-
202
- if len(args) >= 2:
203
- if msg.reply_to_message:
204
- if msg.reply_to_message.forum_topic_created:
205
- offset = len(extracted[1]) - len(msg.text)
206
-
207
- text, buttons = button_markdown_parser(
208
- extracted[1], entities=msg.parse_entities(), offset=offset
209
- )
210
-
211
- text = text.strip()
212
- if not text:
213
- await send_message(
214
- update.effective_message,
215
- "There is no note message - You can't JUST have buttons, you need a message to go with it!",
216
- )
217
- return
218
- else:
219
- pass
220
-
221
- elif msg.reply_to_message and len(args) >= 1:
222
- if msg.reply_to_message.text:
223
- text_to_parsing = msg.reply_to_message.text
224
- elif msg.reply_to_message.caption:
225
- text_to_parsing = msg.reply_to_message.caption
226
- else:
227
- text_to_parsing = ""
228
- offset = len(
229
- text_to_parsing,
230
- ) # set correct offset relative to command + notename
231
- text, buttons = button_markdown_parser(
232
- text_to_parsing,
233
- entities=msg.parse_entities(),
234
- offset=offset,
235
- )
236
- text = text.strip()
237
-
238
- elif not text and not file_type:
239
- await send_message(
240
- update.effective_message,
241
- "Please provide keyword for this filter reply with!",
242
- )
243
- return
244
-
245
- elif msg.reply_to_message:
246
- if msg.reply_to_message.forum_topic_created:
247
- return
248
-
249
- if msg.reply_to_message.text:
250
- text_to_parsing = msg.reply_to_message.text
251
- elif msg.reply_to_message.caption:
252
- text_to_parsing = msg.reply_to_message.caption
253
- else:
254
- text_to_parsing = ""
255
- offset = len(
256
- text_to_parsing,
257
- ) # set correct offset relative to command + notename
258
- text, buttons = button_markdown_parser(
259
- text_to_parsing,
260
- entities=msg.parse_entities(),
261
- offset=offset,
262
- )
263
- text = text.strip()
264
- if (msg.reply_to_message.text or msg.reply_to_message.caption) and not text:
265
- await send_message(
266
- update.effective_message,
267
- "There is no note message - You can't JUST have buttons, you need a message to go with it!",
268
- )
269
- return
270
-
271
- else:
272
- await send_message(update.effective_message, "Invalid filter!")
273
- return
274
-
275
- add = await addnew_filter(
276
- update, chat_id, keyword, text, file_type, file_id, buttons, media_spoiler
277
- )
278
- # This is an old method
279
- # sql.add_filter(chat_id, keyword, content, is_sticker, is_document, is_image, is_audio, is_voice, is_video, buttons)
280
-
281
- if add is True:
282
- await send_message(
283
- update.effective_message,
284
- "Saved filter '{}' in *{}*!".format(keyword, chat_name),
285
- parse_mode=ParseMode.MARKDOWN,
286
- )
287
- raise ApplicationHandlerStop
288
-
289
-
290
- @typing_action
291
- @check_admin(is_user=True)
292
- async def stop_filter(update: Update, context: ContextTypes.DEFAULT_TYPE):
293
- chat = update.effective_chat
294
- user = update.effective_user
295
- args = update.effective_message.text.split(None, 1)
296
-
297
- conn = await connected(context.bot, update, chat, user.id)
298
- if not conn is False:
299
- chat_id = conn
300
- chat_obj = await dispatcher.bot.getChat(conn)
301
- chat_name = chat_obj.title
302
- else:
303
- chat_id = update.effective_chat.id
304
- if chat.type == "private":
305
- chat_name = "Local filters"
306
- else:
307
- chat_name = chat.title
308
-
309
- if len(args) < 2:
310
- await send_message(update.effective_message, "What should i stop?")
311
- return
312
-
313
- chat_filters = sql.get_chat_triggers(chat_id)
314
-
315
- if not chat_filters:
316
- await send_message(update.effective_message, "No filters active here!")
317
- return
318
-
319
- for keyword in chat_filters:
320
- if keyword == args[1]:
321
- sql.remove_filter(chat_id, args[1])
322
- await send_message(
323
- update.effective_message,
324
- "Okay, I'll stop replying to that filter in *{}*.".format(chat_name),
325
- parse_mode=ParseMode.MARKDOWN,
326
- )
327
- raise ApplicationHandlerStop
328
-
329
- await send_message(
330
- update.effective_message,
331
- "That's not a filter - Click: /filters to get currently active filters.",
332
- )
333
-
334
-
335
- async def reply_filter(update: Update, context: ContextTypes.DEFAULT_TYPE):
336
- chat = update.effective_chat
337
- message = update.effective_message
338
-
339
- if not update.effective_user or update.effective_user.id == 777000:
340
- return
341
- to_match = await extract_text(message)
342
- if not to_match:
343
- return
344
-
345
- chat_filters = sql.get_chat_triggers(chat.id)
346
- for keyword in chat_filters:
347
- pattern = r"( |^|[^\w])" + re.escape(keyword) + r"( |$|[^\w])"
348
- if re.search(pattern, to_match, flags=re.IGNORECASE):
349
- if MessageHandlerChecker.check_user(update.effective_user.id):
350
- return
351
- filt = sql.get_filter(chat.id, keyword)
352
- if filt.reply == "there is should be a new reply":
353
- buttons = sql.get_buttons(chat.id, filt.keyword)
354
- keyb = build_keyboard_parser(context.bot, chat.id, buttons)
355
- keyboard = InlineKeyboardMarkup(keyb)
356
-
357
- VALID_WELCOME_FORMATTERS = [
358
- "first",
359
- "last",
360
- "fullname",
361
- "username",
362
- "id",
363
- "chatname",
364
- "mention",
365
- ]
366
- if filt.reply_text:
367
- if "%%%" in filt.reply_text:
368
- split = filt.reply_text.split("%%%")
369
- if all(split):
370
- text = random.choice(split)
371
- else:
372
- text = filt.reply_text
373
- else:
374
- text = filt.reply_text
375
- if text.startswith("~!") and text.endswith("!~"):
376
- sticker_id = text.replace("~!", "").replace("!~", "")
377
- try:
378
- await context.bot.send_sticker(
379
- chat.id,
380
- sticker_id,
381
- reply_to_message_id=message.message_id,
382
- message_thread_id=message.message_thread_id
383
- if chat.is_forum
384
- else None,
385
- )
386
- return
387
- except BadRequest as excp:
388
- if (
389
- excp.message
390
- == "Wrong remote file identifier specified: wrong padding in the string"
391
- ):
392
- await context.bot.send_message(
393
- chat.id,
394
- "Message couldn't be sent, Is the sticker id valid?",
395
- message_thread_id=message.message_thread_id
396
- if chat.is_forum
397
- else None,
398
- )
399
- return
400
- else:
401
- LOGGER.exception("Error in filters: " + excp.message)
402
- return
403
- valid_format = escape_invalid_curly_brackets(
404
- text,
405
- VALID_WELCOME_FORMATTERS,
406
- )
407
- if valid_format:
408
- filtext = valid_format.format(
409
- first=escape(message.from_user.first_name),
410
- last=escape(
411
- message.from_user.last_name
412
- or message.from_user.first_name,
413
- ),
414
- fullname=" ".join(
415
- [
416
- escape(message.from_user.first_name),
417
- escape(message.from_user.last_name),
418
- ]
419
- if message.from_user.last_name
420
- else [escape(message.from_user.first_name)],
421
- ),
422
- username="@" + escape(message.from_user.username)
423
- if message.from_user.username
424
- else mention_html(
425
- message.from_user.id,
426
- message.from_user.first_name,
427
- ),
428
- mention=mention_html(
429
- message.from_user.id,
430
- message.from_user.first_name,
431
- ),
432
- chatname=escape(message.chat.title)
433
- if message.chat.type != "private"
434
- else escape(message.from_user.first_name),
435
- id=message.from_user.id,
436
- )
437
- else:
438
- filtext = ""
439
- else:
440
- filtext = ""
441
-
442
- if filt.file_type in (sql.Types.BUTTON_TEXT, sql.Types.TEXT):
443
- try:
444
- await message.reply_text(
445
- markdown_to_html(filtext),
446
- parse_mode=ParseMode.HTML,
447
- disable_web_page_preview=True,
448
- reply_markup=keyboard,
449
- )
450
- except BadRequest as excp:
451
- LOGGER.exception("Error in filters: " + excp.message)
452
- try:
453
- await send_message(
454
- update.effective_message,
455
- get_exception(excp, filt, chat),
456
- )
457
- except BadRequest as excp:
458
- LOGGER.exception(
459
- "Failed to send message: " + excp.message,
460
- )
461
- else:
462
- try:
463
- if filt.file_type not in [
464
- sql.Types.PHOTO.value,
465
- sql.Types.VIDEO,
466
- ]:
467
- await ENUM_FUNC_MAP[filt.file_type](
468
- chat.id,
469
- filt.file_id,
470
- reply_markup=keyboard,
471
- reply_to_message_id=message.message_id,
472
- message_thread_id=message.message_thread_id
473
- if chat.is_forum
474
- else None,
475
- )
476
- else:
477
- await ENUM_FUNC_MAP[filt.file_type](
478
- chat.id,
479
- filt.file_id,
480
- reply_markup=keyboard,
481
- caption=filt.reply_text,
482
- reply_to_message_id=message.message_id,
483
- message_thread_id=message.message_thread_id
484
- if chat.is_forum
485
- else None,
486
- has_spoiler=filt.has_media_spoiler,
487
- )
488
- except BadRequest:
489
- await send_message(
490
- message,
491
- "I don't have the permission to send the content of the filter.",
492
- )
493
- break
494
- else:
495
- if filt.is_sticker:
496
- await message.reply_sticker(filt.reply)
497
- elif filt.is_document:
498
- await message.reply_document(filt.reply)
499
- elif filt.is_image:
500
- await message.reply_photo(
501
- filt.reply, has_spoiler=filt.has_media_spoiler
502
- )
503
- elif filt.is_audio:
504
- await message.reply_audio(filt.reply)
505
- elif filt.is_voice:
506
- await message.reply_voice(filt.reply)
507
- elif filt.is_video:
508
- await message.reply_video(
509
- filt.reply, has_spoiler=filt.has_media_spoiler
510
- )
511
- elif filt.has_buttons:
512
- buttons = sql.get_buttons(chat.id, filt.keyword)
513
- keyb = build_keyboard_parser(context.bot, chat.id, buttons)
514
- keyboard = InlineKeyboardMarkup(keyb)
515
-
516
- try:
517
- await context.bot.send_message(
518
- chat.id,
519
- markdown_to_html(filt.reply),
520
- parse_mode=ParseMode.HTML,
521
- disable_web_page_preview=True,
522
- reply_markup=keyboard,
523
- message_thread_id=message.message_thread_id
524
- if chat.is_forum
525
- else None,
526
- )
527
- except BadRequest as excp:
528
- if excp.message == "Unsupported url protocol":
529
- try:
530
- await send_message(
531
- update.effective_message,
532
- "You seem to be trying to use an unsupported url protocol. "
533
- "Telegram doesn't support buttons for some protocols, such as tg://. Please try "
534
- "again...",
535
- )
536
- except BadRequest as excp:
537
- LOGGER.exception("Error in filters: " + excp.message)
538
- else:
539
- try:
540
- await send_message(
541
- update.effective_message,
542
- "This message couldn't be sent as it's incorrectly formatted.",
543
- )
544
- except BadRequest as excp:
545
- LOGGER.exception("Error in filters: " + excp.message)
546
- LOGGER.warning(
547
- "Message %s could not be parsed",
548
- str(filt.reply),
549
- )
550
- LOGGER.exception(
551
- "Could not parse filter %s in chat %s",
552
- str(filt.keyword),
553
- str(chat.id),
554
- )
555
-
556
- else:
557
- # LEGACY - all new filters will have has_markdown set to True.
558
- try:
559
- await context.bot.send_message(
560
- chat.id,
561
- filt.reply,
562
- message_thread_id=message.message_thread_id
563
- if chat.is_forum
564
- else None,
565
- )
566
- except BadRequest as excp:
567
- LOGGER.exception("Error in filters: " + excp.message)
568
- break
569
-
570
-
571
- async def rmall_filters(update: Update, context: ContextTypes.DEFAULT_TYPE):
572
- chat = update.effective_chat
573
- user = update.effective_user
574
- member = await chat.get_member(user.id)
575
- if member.status != ChatMemberStatus.OWNER and user.id not in DRAGONS:
576
- await update.effective_message.reply_text(
577
- "Only the chat owner can clear all notes at once.",
578
- )
579
- else:
580
- buttons = InlineKeyboardMarkup(
581
- [
582
- [
583
- InlineKeyboardButton(
584
- text="STOP ALL FILTERS",
585
- callback_data="filters_rmall",
586
- ),
587
- ],
588
- [InlineKeyboardButton(text="CANCEL", callback_data="filters_cancel")],
589
- ],
590
- )
591
- await update.effective_message.reply_text(
592
- f"Are you sure you would like to stop ALL filters in {chat.title}? This action cannot be undone.",
593
- reply_markup=buttons,
594
- parse_mode=ParseMode.MARKDOWN,
595
- )
596
-
597
-
598
- async def rmall_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
599
- query = update.callback_query
600
- chat = update.effective_chat
601
- msg = update.effective_message
602
- member = await chat.get_member(query.from_user.id)
603
- if query.data == "filters_rmall":
604
- if member.status == "creator" or query.from_user.id in DRAGONS:
605
- allfilters = sql.get_chat_triggers(chat.id)
606
- if not allfilters:
607
- await msg.edit_text("No filters in this chat, nothing to stop!")
608
- return
609
-
610
- count = 0
611
- filterlist = []
612
- for x in allfilters:
613
- count += 1
614
- filterlist.append(x)
615
-
616
- for i in filterlist:
617
- sql.remove_filter(chat.id, i)
618
-
619
- await msg.edit_text(f"Cleaned {count} filters in {chat.title}")
620
-
621
- if member.status == "administrator":
622
- await query.answer("Only owner of the chat can do this.")
623
-
624
- if member.status == "member":
625
- await query.answer("You need to be admin to do this.")
626
- elif query.data == "filters_cancel":
627
- if member.status == "creator" or query.from_user.id in DRAGONS:
628
- await msg.edit_text("Clearing of all filters has been cancelled.")
629
- return await query.answer()
630
- if member.status == "administrator":
631
- await query.answer("Only owner of the chat can do this.")
632
- if member.status == "member":
633
- await query.answer("You need to be admin to do this.")
634
-
635
-
636
- # NOT ASYNC NOT A HANDLER
637
- def get_exception(excp, filt, chat):
638
- if excp.message == "Unsupported url protocol":
639
- return "You seem to be trying to use the URL protocol which is not supported. Telegram does not support key for multiple protocols, such as tg: //. Please try again!"
640
- elif excp.message == "Reply message not found":
641
- return "noreply"
642
- else:
643
- LOGGER.warning("Message %s could not be parsed", str(filt.reply))
644
- LOGGER.exception(
645
- "Could not parse filter %s in chat %s",
646
- str(filt.keyword),
647
- str(chat.id),
648
- )
649
- return "This data could not be sent because it is incorrectly formatted."
650
-
651
-
652
- # NOT ASYNC NOT A HANDLER
653
- async def addnew_filter(
654
- update, chat_id, keyword, text, file_type, file_id, buttons, has_spoiler
655
- ):
656
- msg = update.effective_message
657
- totalfilt = sql.get_chat_triggers(chat_id)
658
- if len(totalfilt) >= 150: # Idk why i made this like function....
659
- await msg.reply_text("This group has reached its max filters limit of 150.")
660
- return False
661
- else:
662
- sql.new_add_filter(
663
- chat_id, keyword, text, file_type, file_id, buttons, has_spoiler
664
- )
665
- return True
666
-
667
-
668
- def __stats__():
669
- return "• {} filters, across {} chats.".format(sql.num_filters(), sql.num_chats())
670
-
671
-
672
- async def __import_data__(chat_id, data, message):
673
- # set chat filters
674
- filters = data.get("filters", {})
675
- for trigger in filters:
676
- sql.add_to_blacklist(chat_id, trigger)
677
-
678
-
679
- def __migrate__(old_chat_id, new_chat_id):
680
- sql.migrate_chat(old_chat_id, new_chat_id)
681
-
682
-
683
- def __chat_settings__(chat_id, user_id):
684
- cust_filters = sql.get_chat_triggers(chat_id)
685
- return "There are `{}` custom filters here.".format(len(cust_filters))
686
-
687
-
688
- # <=================================================== HELP ====================================================>
689
-
690
-
691
- __help__ = """
692
- » `/filters`*:* List all active filters saved in the chat.
693
-
694
- ➠ *Admin only:*
695
-
696
- » `/filter <keyword> <reply message>`*:* Add a filter to this chat. The bot will now reply that message whenever 'keyword'\
697
- is mentioned. If you reply to a sticker with a keyword, the bot will reply with that sticker. NOTE: all filter \
698
- keywords are in lowercase. If you want your keyword to be a sentence, use quotes. eg: /filter "hey there" How you \
699
- doin?
700
-
701
- ➠ Separate diff replies by `%%%` to get random replies
702
- ➠ *Example:*
703
-
704
- » `/filter "filtername"
705
- Reply 1
706
- %%%
707
- Reply 2
708
- %%%
709
- Reply 3`
710
-
711
- » `/stop <filter keyword>`*:* Stop that filter.
712
-
713
- ➠ *Chat creator only:*
714
- » `/removeallfilters`*:* Remove all chat filters at once.
715
-
716
- ➠ *Note*: Filters also support markdown formatters like: {first}, {last} etc.. and buttons.
717
- ➠ Now Supports media spoilers too, and media caption.
718
- """
719
-
720
- __mod_name__ = "FILTERS"
721
-
722
- # <================================================ HANDLER =======================================================>
723
- FILTER_HANDLER = CommandHandler("filter", filters, block=False)
724
- STOP_HANDLER = CommandHandler("stop", stop_filter, block=False)
725
- RMALLFILTER_HANDLER = CommandHandler(
726
- "removeallfilters",
727
- rmall_filters,
728
- filters=filters_module.ChatType.GROUPS,
729
- block=False,
730
- )
731
- RMALLFILTER_CALLBACK = CallbackQueryHandler(
732
- rmall_callback, pattern=r"filters_.*", block=False
733
- )
734
- LIST_HANDLER = DisableAbleCommandHandler(
735
- "filters", list_handlers, admin_ok=True, block=False
736
- )
737
- CUST_FILTER_HANDLER = MessageHandler(
738
- filters_module.TEXT & ~filters_module.UpdateType.EDITED_MESSAGE,
739
- reply_filter,
740
- block=False,
741
- )
742
-
743
- function(FILTER_HANDLER)
744
- function(STOP_HANDLER)
745
- function(LIST_HANDLER)
746
- function(CUST_FILTER_HANDLER, HANDLER_GROUP)
747
- function(RMALLFILTER_HANDLER)
748
- function(RMALLFILTER_CALLBACK)
749
-
750
- __handlers__ = [
751
- FILTER_HANDLER,
752
- STOP_HANDLER,
753
- LIST_HANDLER,
754
- (CUST_FILTER_HANDLER, HANDLER_GROUP, RMALLFILTER_HANDLER),
755
- ]
756
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/disable.py DELETED
@@ -1,376 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import importlib
3
- import re
4
- from typing import Dict, List, Optional, Tuple, Union
5
-
6
- from future.utils import string_types
7
- from telegram import Update
8
- from telegram.constants import ParseMode
9
- from telegram.ext import CommandHandler, ContextTypes, MessageHandler
10
- from telegram.ext import filters as filters_module
11
- from telegram.helpers import escape_markdown
12
-
13
- from Mikobot import function
14
- from Mikobot.plugins.helper_funcs.misc import is_module_loaded
15
- from Mikobot.utils.cmdprefix import CMD_STARTERS
16
-
17
- # <=======================================================================================================>
18
-
19
- FILENAME = __name__.rsplit(".", 1)[-1]
20
-
21
- # If module is due to be loaded, then setup all the magical handlers
22
- if is_module_loaded(FILENAME):
23
- from Database.sql import disable_sql as sql
24
- from Mikobot.plugins.helper_funcs.chat_status import (
25
- check_admin,
26
- connection_status,
27
- is_user_admin,
28
- )
29
-
30
- DISABLE_CMDS = []
31
- DISABLE_OTHER = []
32
- ADMIN_CMDS = []
33
-
34
- # <================================================ CLASS =======================================================>
35
- class DisableAbleCommandHandler(CommandHandler):
36
- def __init__(
37
- self,
38
- command,
39
- callback,
40
- block: bool,
41
- filters: filters_module.BaseFilter = None,
42
- admin_ok=False,
43
- ):
44
- super().__init__(command, callback, block=block)
45
- self.admin_ok = admin_ok
46
-
47
- if isinstance(command, string_types):
48
- commands = frozenset({command.lower()})
49
- DISABLE_CMDS.append(command)
50
- if admin_ok:
51
- ADMIN_CMDS.append(command)
52
- else:
53
- commands = frozenset(x.lower() for x in command)
54
- DISABLE_CMDS.extend(command)
55
- if admin_ok:
56
- ADMIN_CMDS.extend(command)
57
- for comm in commands:
58
- if not re.match(r"^[\da-z_]{1,32}$", comm):
59
- raise ValueError(f"Command `{comm}` is not a valid bot command")
60
-
61
- self.commands = commands
62
- self.filters = (
63
- filters if filters is not None else filters_module.UpdateType.MESSAGES
64
- )
65
-
66
- def check_update(
67
- self, update
68
- ) -> Optional[Union[bool, Tuple[List[str], Optional[Union[bool, Dict]]]]]:
69
- if isinstance(update, Update) and update.effective_message:
70
- message = update.effective_message
71
-
72
- if message.text and len(message.text) > 1:
73
- fst_word = message.text.split(None, 1)[0]
74
- if len(fst_word) > 1 and any(
75
- fst_word.startswith(start) for start in CMD_STARTERS
76
- ):
77
- args = message.text.split()[1:]
78
- command_parts = fst_word[1:].split("@")
79
- command_parts.append(message.get_bot().username)
80
-
81
- if not (
82
- command_parts[0].lower() in self.commands
83
- and command_parts[1].lower()
84
- == message.get_bot().username.lower()
85
- ):
86
- return None
87
-
88
- chat = update.effective_chat
89
- user = update.effective_user
90
-
91
- filter_result = self.filters.check_update(update)
92
- if filter_result:
93
- # disabled, admincmd, user admin
94
- if sql.is_command_disabled(
95
- chat.id, command_parts[0].lower()
96
- ):
97
- # check if command was disabled
98
- is_disabled = command_parts[
99
- 0
100
- ] in ADMIN_CMDS and is_user_admin(chat, user.id)
101
- if not is_disabled:
102
- return None
103
- else:
104
- return args, filter_result
105
-
106
- return args, filter_result
107
- return False
108
- return None
109
-
110
- class DisableAbleMessageHandler(MessageHandler):
111
- def __init__(self, filters, callback, block: bool, friendly, **kwargs):
112
- super().__init__(filters, callback, block=block, **kwargs)
113
- DISABLE_OTHER.append(friendly)
114
- self.friendly = friendly
115
- if filters:
116
- self.filters = filters_module.UpdateType.MESSAGES & filters
117
- else:
118
- self.filters = filters_module.UpdateType.MESSAGES
119
-
120
- def check_update(self, update):
121
- chat = update.effective_chat
122
- message = update.effective_message
123
- filter_result = self.filters.check_update(update)
124
-
125
- try:
126
- args = message.text.split()[1:]
127
- except:
128
- args = []
129
-
130
- if super().check_update(update):
131
- if sql.is_command_disabled(chat.id, self.friendly):
132
- return False
133
- else:
134
- return args, filter_result
135
-
136
- # <=======================================================================================================>
137
-
138
- # <================================================ FUNCTION =======================================================>
139
- @connection_status
140
- @check_admin(is_user=True)
141
- async def disable(update: Update, context: ContextTypes.DEFAULT_TYPE):
142
- args = context.args
143
- chat = update.effective_chat
144
- if len(args) >= 1:
145
- disable_cmd = args[0]
146
- if disable_cmd.startswith(CMD_STARTERS):
147
- disable_cmd = disable_cmd[1:]
148
-
149
- if disable_cmd in set(DISABLE_CMDS + DISABLE_OTHER):
150
- sql.disable_command(chat.id, str(disable_cmd).lower())
151
- await update.effective_message.reply_text(
152
- f"Disabled the use of `{disable_cmd}`",
153
- parse_mode=ParseMode.MARKDOWN,
154
- )
155
- else:
156
- await update.effective_message.reply_text(
157
- "That command can't be disabled"
158
- )
159
-
160
- else:
161
- await update.effective_message.reply_text("What should I disable?")
162
-
163
- @connection_status
164
- @check_admin(is_user=True)
165
- async def disable_module(
166
- update: Update, context: ContextTypes.DEFAULT_TYPE
167
- ) -> None:
168
- args = context.args
169
- chat = update.effective_chat
170
- if len(args) >= 1:
171
- disable_module = "Mikobot.plugins." + args[0].rsplit(".", 1)[0]
172
-
173
- try:
174
- module = importlib.import_module(disable_module)
175
- except:
176
- await update.effective_message.reply_text(
177
- "Does that module even exsist?"
178
- )
179
- return
180
-
181
- try:
182
- command_list = module.__command_list__
183
- except:
184
- await update.effective_message.reply_text(
185
- "Module does not contain command list!",
186
- )
187
- return
188
-
189
- disabled_cmds = []
190
- failed_disabled_cmds = []
191
-
192
- for disable_cmd in command_list:
193
- if disable_cmd.startswith(CMD_STARTERS):
194
- disable_cmd = disable_cmd[1:]
195
-
196
- if disable_cmd in set(DISABLE_CMDS + DISABLE_OTHER):
197
- sql.disable_command(chat.id, str(disable_cmd).lower())
198
- disabled_cmds.append(disable_cmd)
199
- else:
200
- failed_disabled_cmds.append(disable_cmd)
201
-
202
- if disabled_cmds:
203
- disabled_cmds_string = ", ".join(disabled_cmds)
204
- await update.effective_message.reply_text(
205
- f"Disabled the use of`{disabled_cmds_string}`",
206
- parse_mode=ParseMode.MARKDOWN,
207
- )
208
-
209
- if failed_disabled_cmds:
210
- failed_disabled_cmds_string = ", ".join(failed_disabled_cmds)
211
- await update.effective_message.reply_text(
212
- f"Commands `{failed_disabled_cmds_string}` can't be disabled",
213
- parse_mode=ParseMode.MARKDOWN,
214
- )
215
-
216
- else:
217
- await update.effective_message.reply_text("What should I disable?")
218
-
219
- @connection_status
220
- @check_admin(is_user=True)
221
- async def enable(update: Update, context: ContextTypes.DEFAULT_TYPE):
222
- args = context.args
223
- chat = update.effective_chat
224
- if len(args) >= 1:
225
- enable_cmd = args[0]
226
- if enable_cmd.startswith(CMD_STARTERS):
227
- enable_cmd = enable_cmd[1:]
228
-
229
- if sql.enable_command(chat.id, enable_cmd):
230
- await update.effective_message.reply_text(
231
- f"Enabled the use of`{enable_cmd}`",
232
- parse_mode=ParseMode.MARKDOWN,
233
- )
234
- else:
235
- await update.effective_message.reply_text("Is that even disabled?")
236
-
237
- else:
238
- await update.effective_message.reply_text("What sould I enable?")
239
-
240
- @connection_status
241
- @check_admin(is_user=True)
242
- async def enable_module(update: Update, context: ContextTypes.DEFAULT_TYPE):
243
- args = context.args
244
- chat = update.effective_chat
245
-
246
- if len(args) >= 1:
247
- enable_module = "Mikobot.plugins." + args[0].rsplit(".", 1)[0]
248
-
249
- try:
250
- module = importlib.import_module(enable_module)
251
- except:
252
- await update.effective_message.reply_text(
253
- "Does that module even exsist?"
254
- )
255
- return
256
-
257
- try:
258
- command_list = module.__command_list__
259
- except:
260
- await update.effective_message.reply_text(
261
- "Module does not contain command list!",
262
- )
263
- return
264
-
265
- enabled_cmds = []
266
- failed_enabled_cmds = []
267
-
268
- for enable_cmd in command_list:
269
- if enable_cmd.startswith(CMD_STARTERS):
270
- enable_cmd = enable_cmd[1:]
271
-
272
- if sql.enable_command(chat.id, enable_cmd):
273
- enabled_cmds.append(enable_cmd)
274
- else:
275
- failed_enabled_cmds.append(enable_cmd)
276
-
277
- if enabled_cmds:
278
- enabled_cmds_string = ", ".join(enabled_cmds)
279
- await update.effective_message.reply_text(
280
- f"Enabled the use of`{enabled_cmds_string}`",
281
- parse_mode=ParseMode.MARKDOWN,
282
- )
283
-
284
- if failed_enabled_cmds:
285
- failed_enabled_cmds_string = ", ".join(failed_enabled_cmds)
286
- await update.effective_message.reply_text(
287
- f"Are the commands `{failed_enabled_cmds_string}` even disabled?",
288
- parse_mode=ParseMode.MARKDOWN,
289
- )
290
-
291
- else:
292
- await update.effective_message.reply_text("ᴡʜᴀᴛ sʜᴏᴜʟᴅ I ᴇɴᴀʙʟᴇ?")
293
-
294
- @connection_status
295
- @check_admin(is_user=True)
296
- async def list_cmds(update: Update, context: ContextTypes.DEFAULT_TYPE):
297
- if DISABLE_CMDS + DISABLE_OTHER:
298
- result = ""
299
- for cmd in set(DISABLE_CMDS + DISABLE_OTHER):
300
- result += f" - `{escape_markdown(cmd)}`\n"
301
- await update.effective_message.reply_text(
302
- f"The following commands are toggleable:\n{result}",
303
- parse_mode=ParseMode.MARKDOWN,
304
- )
305
- else:
306
- await update.effective_message.reply_text("No commands can be disabled.")
307
-
308
- # do not async
309
- def build_curr_disabled(chat_id: Union[str, int]) -> str:
310
- disabled = sql.get_all_disabled(chat_id)
311
- if not disabled:
312
- return "No commands are disabled!"
313
-
314
- result = ""
315
- for cmd in disabled:
316
- result += " - `{}`\n".format(escape_markdown(cmd))
317
- return "The following commands are currently restricted:\n{}".format(result)
318
-
319
- @connection_status
320
- async def commands(update: Update, context: ContextTypes.DEFAULT_TYPE):
321
- chat = update.effective_chat
322
- await update.effective_message.reply_text(
323
- build_curr_disabled(chat.id),
324
- parse_mode=ParseMode.MARKDOWN,
325
- )
326
-
327
- def __stats__():
328
- return f"• {sql.num_disabled()} disabled items, across {sql.num_chats()} chats."
329
-
330
- def __migrate__(old_chat_id, new_chat_id):
331
- sql.migrate_chat(old_chat_id, new_chat_id)
332
-
333
- def __chat_settings__(chat_id, user_id):
334
- return build_curr_disabled(chat_id)
335
-
336
- # <=================================================== HANDLER ====================================================>
337
-
338
- DISABLE_HANDLER = CommandHandler("disable", disable, block=False)
339
- DISABLE_MODULE_HANDLER = CommandHandler(
340
- "disablemodule", disable_module, block=False
341
- )
342
- ENABLE_HANDLER = CommandHandler("enable", enable, block=False)
343
- ENABLE_MODULE_HANDLER = CommandHandler("enablemodule", enable_module, block=False)
344
- COMMANDS_HANDLER = CommandHandler(["cmds", "disabled"], commands, block=False)
345
- TOGGLE_HANDLER = CommandHandler("listcmds", list_cmds, block=False)
346
-
347
- function(DISABLE_HANDLER)
348
- function(DISABLE_MODULE_HANDLER)
349
- function(ENABLE_HANDLER)
350
- function(ENABLE_MODULE_HANDLER)
351
- function(COMMANDS_HANDLER)
352
- function(TOGGLE_HANDLER)
353
-
354
- # <=================================================== HELP ====================================================>
355
- __help__ = """
356
- » /cmds: Check the current status of disabled commands
357
-
358
- ➠ *Admins only*:
359
-
360
- » /enable < cmd name >: Enable that command.
361
-
362
- » /disable < cmd name >: Disable that command.
363
-
364
- » /enablemodule < module name >: Enable all commands in that module.
365
-
366
- » /disablemodule < module name >: Disable all commands in that module.
367
-
368
- » /listcmds: List all possible toggleable commands.
369
- """
370
-
371
- __mod_name__ = "DISABLE"
372
-
373
- else:
374
- DisableAbleCommandHandler = CommandHandler
375
- DisableAbleMessageHandler = MessageHandler
376
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/extra.py DELETED
@@ -1,137 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from time import gmtime, strftime, time
3
-
4
- from pyrogram import filters
5
- from pyrogram.types import Message
6
- from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
7
- from telegram.ext import CallbackQueryHandler, CommandHandler, ContextTypes
8
-
9
- from Mikobot import LOGGER, app, function
10
- from Mikobot.plugins.helper_funcs.chat_status import check_admin
11
-
12
- # <=======================================================================================================>
13
-
14
- UPTIME = time() # Check bot uptime
15
-
16
-
17
- # <================================================ FUNCTION =======================================================>
18
- async def getid(update: Update, context: ContextTypes.DEFAULT_TYPE):
19
- chat = update.effective_chat
20
- your_id = update.message.from_user.id
21
- message_id = update.message.message_id
22
- reply = update.message.reply_to_message
23
-
24
- text = f"[Message ID:](https://t.me/{chat.username}/{message_id}) `{message_id}`\n"
25
- text += f"[Your ID:](tg://user?id={your_id}) `{your_id}`\n"
26
-
27
- if context.args:
28
- try:
29
- user_id = context.args[0]
30
- text += f"[User ID:](tg://user?id={user_id}) `{user_id}`\n"
31
- except Exception:
32
- await update.message.reply_text(
33
- "This user doesn't exist.", parse_mode="Markdown"
34
- )
35
- return
36
-
37
- text += f"[Chat ID:](https://t.me/{chat.username}) `{chat.id}`\n\n"
38
-
39
- if reply:
40
- text += f"[Replied Message ID:](https://t.me/{chat.username}/{reply.message_id}) `{reply.message_id}`\n"
41
- text += f"[Replied User ID:](tg://user?id={reply.from_user.id}) `{reply.from_user.id}`\n\n"
42
-
43
- if reply and reply.forward_from_chat:
44
- text += f"The forwarded channel, {reply.forward_from_chat.title}, has an id of `{reply.forward_from_chat.id}`\n\n"
45
-
46
- if reply and reply.sender_chat:
47
- text += f"ID of the replied chat/channel, is `{reply.sender_chat.id}`"
48
-
49
- # Sticker ID to be sent
50
- sticker_id = (
51
- "CAACAgIAAx0CanzPTAABASPCZQdU9NbQIol5TW1GU2zV4KfjDMEAAnccAALIWZhJPyYLf3FzPHswBA"
52
- )
53
-
54
- # Send the sticker
55
- await update.message.reply_sticker(sticker=sticker_id)
56
-
57
- # Send the text message as a caption
58
- await update.message.reply_text(
59
- text, parse_mode="Markdown", disable_web_page_preview=True
60
- )
61
-
62
-
63
- # Function to handle the "logs" command
64
- @check_admin(only_dev=True)
65
- async def logs(update: Update, context: ContextTypes.DEFAULT_TYPE):
66
- user = update.effective_user
67
- with open("Logs.txt", "rb") as f:
68
- caption = "Here is your log"
69
- reply_markup = InlineKeyboardMarkup(
70
- [[InlineKeyboardButton("Close", callback_data="close")]]
71
- )
72
- message = await context.bot.send_document(
73
- document=f,
74
- filename=f.name,
75
- caption=caption,
76
- reply_markup=reply_markup,
77
- chat_id=user.id,
78
- )
79
-
80
- # Store the message ID for later reference
81
- context.user_data["log_message_id"] = message.message_id
82
-
83
-
84
- # Asynchronous callback query handler for the "close" button
85
- @check_admin(only_dev=True)
86
- async def close_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
87
- query = update.callback_query
88
- message_id = context.user_data.get("log_message_id")
89
- if message_id:
90
- await context.bot.delete_message(
91
- chat_id=query.message.chat_id, message_id=message_id
92
- )
93
-
94
-
95
- @app.on_message(filters.command("pyroping"))
96
- async def ping(_, m: Message):
97
- LOGGER.info(f"{m.from_user.id} used ping cmd in {m.chat.id}")
98
- start = time()
99
- replymsg = await m.reply_text(text="Pinging...", quote=True)
100
- delta_ping = time() - start
101
-
102
- up = strftime("%Hh %Mm %Ss", gmtime(time() - UPTIME))
103
- image_url = "https://telegra.ph/file/f215a1c4adf25a5bad81b.jpg"
104
-
105
- # Send the image as a reply
106
- await replymsg.reply_photo(
107
- photo=image_url,
108
- caption=f"<b>Pyro-Pong!</b>\n{delta_ping * 1000:.3f} ms\n\nUptime: <code>{up}</code>",
109
- )
110
- await replymsg.delete()
111
-
112
-
113
- # <=======================================================================================================>
114
-
115
-
116
- # <================================================ HANDLER =======================================================>
117
- function(CommandHandler("logs", logs, block=False))
118
- function(CommandHandler("id", getid, block=False))
119
- function(CallbackQueryHandler(close_callback, pattern="^close$", block=False))
120
-
121
- # <================================================= HELP ======================================================>
122
- __help__ = """
123
- ➠ *Commands*:
124
-
125
- » /instadl, /insta <link>: Get instagram contents like reel video or images.
126
-
127
- » /pyroping: see pyroping.
128
-
129
- » /hyperlink <text> <link> : Creates a markdown hyperlink with the provided text and link.
130
-
131
- » /pickwinner <participant1> <participant2> ... : Picks a random winner from the provided list of participants.
132
-
133
- » /id: reply to get user id.
134
- """
135
-
136
- __mod_name__ = "EXTRA"
137
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/feds.py DELETED
@@ -1,2505 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import ast
3
- import csv
4
- import json
5
- import os
6
- import re
7
- import time
8
- import uuid
9
- from io import BytesIO
10
-
11
- from telegram import (
12
- ChatMember,
13
- InlineKeyboardButton,
14
- InlineKeyboardMarkup,
15
- MessageEntity,
16
- Update,
17
- )
18
- from telegram.constants import ParseMode
19
- from telegram.error import BadRequest, Forbidden, TelegramError
20
- from telegram.ext import CallbackQueryHandler, CommandHandler, ContextTypes
21
- from telegram.helpers import mention_html, mention_markdown
22
-
23
- import Database.sql.feds_sql as sql
24
- from Mikobot import (
25
- DRAGONS,
26
- EVENT_LOGS,
27
- LOGGER,
28
- OWNER_ID,
29
- SUPPORT_CHAT,
30
- dispatcher,
31
- function,
32
- )
33
- from Mikobot.plugins.disable import DisableAbleCommandHandler
34
- from Mikobot.plugins.helper_funcs.alternate import send_message
35
- from Mikobot.plugins.helper_funcs.chat_status import is_user_admin
36
- from Mikobot.plugins.helper_funcs.extraction import (
37
- extract_unt_fedban,
38
- extract_user,
39
- extract_user_fban,
40
- )
41
- from Mikobot.plugins.helper_funcs.string_handling import markdown_parser
42
-
43
- # <=======================================================================================================>
44
-
45
- FBAN_ERRORS = {
46
- "User is an administrator of the chat",
47
- "Chat not found",
48
- "Not enough rights to restrict/unrestrict chat member",
49
- "User_not_participant",
50
- "Peer_id_invalid",
51
- "Group chat was deactivated",
52
- "Need to be inviter of a user to kick it from a basic group",
53
- "Chat_admin_required",
54
- "Only the creator of a basic group can kick group administrators",
55
- "Channel_private",
56
- "Not in the chat",
57
- "Have no rights to send a message",
58
- }
59
-
60
- UNFBAN_ERRORS = {
61
- "User is an administrator of the chat",
62
- "Chat not found",
63
- "Not enough rights to restrict/unrestrict chat member",
64
- "User_not_participant",
65
- "Method is available for supergroup and channel chats only",
66
- "Not in the chat",
67
- "Channel_private",
68
- "Chat_admin_required",
69
- "Have no rights to send a message",
70
- }
71
-
72
-
73
- # <================================================ FUNCTION =======================================================>
74
- async def new_fed(update: Update, context: ContextTypes.DEFAULT_TYPE):
75
- chat = update.effective_chat
76
- user = update.effective_user
77
- message = update.effective_message
78
- bot = context.bot
79
- if chat.type != "private":
80
- await update.effective_message.reply_text(
81
- "Federations can only be created by privately messaging me.",
82
- )
83
- return
84
- if len(message.text) == 1:
85
- await send_message(
86
- update.effective_message,
87
- "Please write the name of the federation!",
88
- )
89
- return
90
- fednam = message.text.split(None, 1)[1]
91
- if not fednam == "":
92
- fed_id = str(uuid.uuid4())
93
- fed_name = fednam
94
- LOGGER.info(fed_id)
95
-
96
- x = sql.new_fed(user.id, fed_name, fed_id)
97
- if not x:
98
- await update.effective_message.reply_text(
99
- f"Can't federate! Please contact @{SUPPORT_CHAT} if the problem persist.",
100
- )
101
- return
102
-
103
- await update.effective_message.reply_text(
104
- "*You have succeeded in creating a new federation!*"
105
- "\nName: `{}`"
106
- "\nID: `{}`"
107
- "\n\nUse the command below to join the federation:"
108
- "\n`/joinfed {}`".format(fed_name, fed_id, fed_id),
109
- parse_mode=ParseMode.MARKDOWN,
110
- )
111
- try:
112
- await bot.send_message(
113
- EVENT_LOGS,
114
- "New Federation: <b>{}</b>\nID: <pre>{}</pre>".format(fed_name, fed_id),
115
- parse_mode=ParseMode.HTML,
116
- )
117
- except:
118
- LOGGER.warning("Cannot send a message to EVENT_LOGS")
119
- else:
120
- await update.effective_message.reply_text(
121
- "Please write down the name of the federation",
122
- )
123
-
124
-
125
- async def del_fed(update: Update, context: ContextTypes.DEFAULT_TYPE):
126
- bot, args = context.bot, context.args
127
- chat = update.effective_chat
128
- user = update.effective_user
129
- if chat.type != "private":
130
- await update.effective_message.reply_text(
131
- "Federations can only be deleted by privately messaging me.",
132
- )
133
- return
134
- if args:
135
- is_fed_id = args[0]
136
- getinfo = sql.get_fed_info(is_fed_id)
137
- if getinfo is False:
138
- await update.effective_message.reply_text("This federation does not exist.")
139
- return
140
- if int(getinfo["owner"]) == int(user.id) or int(user.id) == OWNER_ID:
141
- fed_id = is_fed_id
142
- else:
143
- await update.effective_message.reply_text(
144
- "Only federation owners can do this!"
145
- )
146
- return
147
- else:
148
- await update.effective_message.reply_text("What should I delete?")
149
- return
150
-
151
- if is_user_fed_owner(fed_id, user.id) is False:
152
- await update.effective_message.reply_text("Only federation owners can do this!")
153
- return
154
-
155
- await update.effective_message.reply_text(
156
- "You sure you want to delete your federation? This cannot be reverted, you will lose your entire ban list, and '{}' will be permanently lost.".format(
157
- getinfo["fname"],
158
- ),
159
- reply_markup=InlineKeyboardMarkup(
160
- [
161
- [
162
- InlineKeyboardButton(
163
- text="⚠️ Delete Federation ⚠️",
164
- callback_data="rmfed_{}".format(fed_id),
165
- ),
166
- ],
167
- [InlineKeyboardButton(text="Cancel", callback_data="rmfed_cancel")],
168
- ],
169
- ),
170
- )
171
-
172
-
173
- async def rename_fed(update: Update, context: ContextTypes.DEFAULT_TYPE):
174
- user = update.effective_user
175
- msg = update.effective_message
176
- args = msg.text.split(None, 2)
177
-
178
- if len(args) < 3:
179
- return await msg.reply_text("usage: /renamefed <fed_id> <newname>")
180
-
181
- fed_id, newname = args[1], args[2]
182
- verify_fed = sql.get_fed_info(fed_id)
183
-
184
- if not verify_fed:
185
- return await msg.reply_text("This fed not exist in my database!")
186
-
187
- if is_user_fed_owner(fed_id, user.id):
188
- sql.rename_fed(fed_id, user.id, newname)
189
- await msg.reply_text(f"Successfully renamed your fed name to {newname}!")
190
- else:
191
- await msg.reply_text("Only federation owner can do this!")
192
-
193
-
194
- async def fed_chat(update: Update, context: ContextTypes.DEFAULT_TYPE):
195
- bot, args = context.bot, context.args
196
- chat = update.effective_chat
197
- user = update.effective_user
198
- fed_id = sql.get_fed_id(chat.id)
199
-
200
- user_id = update.effective_message.from_user.id
201
- if not await is_user_admin(update.effective_chat, user_id):
202
- await update.effective_message.reply_text(
203
- "You must be an admin to execute this command",
204
- )
205
- return
206
-
207
- if not fed_id:
208
- await update.effective_message.reply_text(
209
- "This group is not in any federation!"
210
- )
211
- return
212
-
213
- user = update.effective_user
214
- chat = update.effective_chat
215
- info = sql.get_fed_info(fed_id)
216
-
217
- text = "This group is part of the following federation:"
218
- text += "\n{} (ID: <code>{}</code>)".format(info["fname"], fed_id)
219
-
220
- await update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
221
-
222
-
223
- async def join_fed(update: Update, context: ContextTypes.DEFAULT_TYPE):
224
- bot, args = context.bot, context.args
225
- chat = update.effective_chat
226
- user = update.effective_user
227
-
228
- if chat.type == "private":
229
- await send_message(
230
- update.effective_message,
231
- "This command is specific to the group, not to our pm!",
232
- )
233
- return
234
-
235
- message = update.effective_message
236
- administrators = await chat.get_administrators()
237
- fed_id = sql.get_fed_id(chat.id)
238
-
239
- if user.id in DRAGONS:
240
- pass
241
- else:
242
- for admin in administrators:
243
- status = admin.status
244
- if status == "creator":
245
- if str(admin.user.id) == str(user.id):
246
- pass
247
- else:
248
- await update.effective_message.reply_text(
249
- "Only group creators can use this command!",
250
- )
251
- return
252
- if fed_id:
253
- await message.reply_text("You cannot join two federations from one chat")
254
- return
255
-
256
- if len(args) >= 1:
257
- getfed = sql.search_fed_by_id(args[0])
258
- if getfed is False:
259
- await message.reply_text("Please enter a valid federation ID")
260
- return
261
-
262
- x = sql.chat_join_fed(args[0], chat.title, chat.id)
263
- if not x:
264
- await message.reply_text(
265
- f"Failed to join federation! Please contact @{SUPPORT_CHAT} should this problem persist!",
266
- )
267
- return
268
-
269
- get_fedlog = await sql.get_fed_log(args[0])
270
- if get_fedlog:
271
- if ast.literal_eval(get_fedlog):
272
- await bot.send_message(
273
- get_fedlog,
274
- "Chat *{}* has joined the federation *{}*".format(
275
- chat.title,
276
- getfed["fname"],
277
- ),
278
- parse_mode="markdown",
279
- message_thread_id=message.message_thread_id
280
- if chat.is_forum
281
- else None,
282
- )
283
-
284
- await message.reply_text(
285
- "This group has joined the federation: {}!".format(getfed["fname"]),
286
- )
287
-
288
-
289
- async def leave_fed(update: Update, context: ContextTypes.DEFAULT_TYPE):
290
- bot, args = context.bot, context.args
291
- chat = update.effective_chat
292
- user = update.effective_user
293
-
294
- if chat.type == "private":
295
- await send_message(
296
- update.effective_message,
297
- "This command is specific to the group, not to our PM!",
298
- )
299
- return
300
-
301
- fed_id = sql.get_fed_id(chat.id)
302
- fed_info = sql.get_fed_info(fed_id)
303
-
304
- # administrators = await chat.get_administrators().status
305
- getuser = await bot.get_chat_member(chat.id, user.id).status
306
- if getuser in "creator" or user.id in DRAGONS:
307
- if sql.chat_leave_fed(chat.id) is True:
308
- get_fedlog = await sql.get_fed_log(fed_id)
309
- if get_fedlog:
310
- if ast.literal_eval(get_fedlog):
311
- await bot.send_message(
312
- get_fedlog,
313
- "Chat *{}* has left the federation *{}*".format(
314
- chat.title,
315
- fed_info["fname"],
316
- ),
317
- parse_mode="markdown",
318
- message_thread_id=update.effective_message.message_thread_id
319
- if chat.is_forum
320
- else None,
321
- )
322
- await send_message(
323
- update.effective_message,
324
- "This group has left the federation {}!".format(fed_info["fname"]),
325
- )
326
- else:
327
- await update.effective_message.reply_text(
328
- "How can you leave a federation that you never joined?!",
329
- )
330
- else:
331
- await update.effective_message.reply_text(
332
- "Only group creators can use this command!"
333
- )
334
-
335
-
336
- async def user_join_fed(update: Update, context: ContextTypes.DEFAULT_TYPE):
337
- bot, args = context.bot, context.args
338
- chat = update.effective_chat
339
- user = update.effective_user
340
- msg = update.effective_message
341
-
342
- if chat.type == "private":
343
- await send_message(
344
- update.effective_message,
345
- "This command is specific to the group, not to our pm!",
346
- )
347
- return
348
-
349
- fed_id = sql.get_fed_id(chat.id)
350
-
351
- if is_user_fed_owner(fed_id, user.id) or user.id in DRAGONS:
352
- user_id = await extract_user(msg, context, args)
353
- if user_id:
354
- user = await bot.get_chat(user_id)
355
- elif not msg.reply_to_message and not args:
356
- user = msg.from_user
357
- elif not msg.reply_to_message and (
358
- not args
359
- or (
360
- len(args) >= 1
361
- and not args[0].startswith("@")
362
- and not args[0].isdigit()
363
- and not msg.parse_entities([MessageEntity.TEXT_MENTION])
364
- )
365
- ):
366
- await msg.reply_text("I cannot extract user from this message")
367
- return
368
- else:
369
- LOGGER.warning("error")
370
- getuser = sql.search_user_in_fed(fed_id, user_id)
371
- fed_id = sql.get_fed_id(chat.id)
372
- info = sql.get_fed_info(fed_id)
373
- get_owner = ast.literal_eval(info["fusers"])["owner"]
374
- get_owner = await bot.get_chat(get_owner)
375
- if isinstance(get_owner, ChatMember):
376
- if user_id == get_owner.id:
377
- await update.effective_message.reply_text(
378
- "You do know that the user is the federation owner, right? RIGHT?",
379
- )
380
- return
381
- if getuser:
382
- await update.effective_message.reply_text(
383
- "I cannot promote users who are already federation admins! Can remove them if you want!",
384
- )
385
- return
386
- if user_id == bot.id:
387
- await update.effective_message.reply_text(
388
- "I already am a federation admin in all federations!",
389
- )
390
- return
391
- res = sql.user_join_fed(fed_id, user_id)
392
- if res:
393
- await update.effective_message.reply_text("Successfully Promoted!")
394
- else:
395
- await update.effective_message.reply_text("Failed to promote!")
396
- else:
397
- await update.effective_message.reply_text("Only federation owners can do this!")
398
-
399
-
400
- async def user_demote_fed(update: Update, context: ContextTypes.DEFAULT_TYPE):
401
- bot, args = context.bot, context.args
402
- chat = update.effective_chat
403
- user = update.effective_user
404
-
405
- if chat.type == "private":
406
- await send_message(
407
- update.effective_message,
408
- "This command is specific to the group, not to our pm!",
409
- )
410
- return
411
-
412
- fed_id = sql.get_fed_id(chat.id)
413
-
414
- if is_user_fed_owner(fed_id, user.id):
415
- msg = update.effective_message
416
- user_id = await extract_user(msg, context, args)
417
- if user_id:
418
- user = await bot.get_chat(user_id)
419
-
420
- elif not msg.reply_to_message and not args:
421
- user = msg.from_user
422
-
423
- elif not msg.reply_to_message and (
424
- not args
425
- or (
426
- len(args) >= 1
427
- and not args[0].startswith("@")
428
- and not args[0].isdigit()
429
- and not msg.parse_entities([MessageEntity.TEXT_MENTION])
430
- )
431
- ):
432
- await msg.reply_text("I cannot extract user from this message")
433
- return
434
- else:
435
- LOGGER.warning("error")
436
-
437
- if user_id == bot.id:
438
- await update.effective_message.reply_text(
439
- "The thing you are trying to demote me from will fail to work without me! Just saying.",
440
- )
441
- return
442
-
443
- if sql.search_user_in_fed(fed_id, user_id) is False:
444
- await update.effective_message.reply_text(
445
- "I cannot demote people who are not federation admins!",
446
- )
447
- return
448
-
449
- res = sql.user_demote_fed(fed_id, user_id)
450
- if res is True:
451
- await update.effective_message.reply_text("Demoted from a Fed Admin!")
452
- else:
453
- await update.effective_message.reply_text("Demotion failed!")
454
- else:
455
- await update.effective_message.reply_text("Only federation owners can do this!")
456
- return
457
-
458
-
459
- async def fed_info(update: Update, context: ContextTypes.DEFAULT_TYPE):
460
- bot, args = context.bot, context.args
461
- chat = update.effective_chat
462
- user = update.effective_user
463
- if args:
464
- fed_id = args[0]
465
- info = sql.get_fed_info(fed_id)
466
- else:
467
- if chat.type == "private":
468
- await send_message(
469
- update.effective_message,
470
- "You need to provide me a fedid to check fedinfo in my pm.",
471
- )
472
- return
473
- fed_id = sql.get_fed_id(chat.id)
474
- if not fed_id:
475
- await send_message(
476
- update.effective_message,
477
- "This group is not in any federation!",
478
- )
479
- return
480
- info = sql.get_fed_info(fed_id)
481
-
482
- if is_user_fed_admin(fed_id, user.id) is False:
483
- await update.effective_message.reply_text(
484
- "Only a federation admin can do this!"
485
- )
486
- return
487
-
488
- owner = await bot.get_chat(info["owner"])
489
- try:
490
- owner_name = owner.first_name + " " + owner.last_name
491
- except:
492
- owner_name = owner.first_name
493
- FEDADMIN = sql.all_fed_users(fed_id)
494
- TotalAdminFed = len(FEDADMIN)
495
-
496
- user = update.effective_user
497
- chat = update.effective_chat
498
- info = sql.get_fed_info(fed_id)
499
-
500
- text = "<b>ℹ️ Federation Information:</b>"
501
- text += "\nFedID: <code>{}</code>".format(fed_id)
502
- text += "\nName: {}".format(info["fname"])
503
- text += "\nCreator: {}".format(mention_html(owner.id, owner_name))
504
- text += "\nAll Admins: <code>{}</code>".format(TotalAdminFed)
505
- getfban = sql.get_all_fban_users(fed_id)
506
- text += "\nTotal banned users: <code>{}</code>".format(len(getfban))
507
- getfchat = sql.all_fed_chats(fed_id)
508
- text += "\nNumber of groups in this federation: <code>{}</code>".format(
509
- len(getfchat),
510
- )
511
-
512
- await update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
513
-
514
-
515
- async def fed_admin(update: Update, context: ContextTypes.DEFAULT_TYPE):
516
- bot, args = context.bot, context.args
517
- chat = update.effective_chat
518
- user = update.effective_user
519
-
520
- if chat.type == "private":
521
- await send_message(
522
- update.effective_message,
523
- "This command is specific to the group, not to our pm!",
524
- )
525
- return
526
-
527
- fed_id = sql.get_fed_id(chat.id)
528
-
529
- if not fed_id:
530
- await update.effective_message.reply_text(
531
- "This group is not in any federation!"
532
- )
533
- return
534
-
535
- if is_user_fed_admin(fed_id, user.id) is False:
536
- await update.effective_message.reply_text("Only federation admins can do this!")
537
- return
538
-
539
- user = update.effective_user
540
- chat = update.effective_chat
541
- info = sql.get_fed_info(fed_id)
542
-
543
- text = "<b>Federation Admin {}:</b>\n\n".format(info["fname"])
544
- text += "👑 Owner:\n"
545
- owner = await bot.get_chat(info["owner"])
546
- try:
547
- owner_name = owner.first_name + " " + owner.last_name
548
- except:
549
- owner_name = owner.first_name
550
- text += " • {}\n".format(mention_html(owner.id, owner_name))
551
-
552
- members = sql.all_fed_members(fed_id)
553
- if len(members) == 0:
554
- text += "\n🔱 There are no admins in this federation"
555
- else:
556
- text += "\n🔱 Admin:\n"
557
- for x in members:
558
- user = await bot.get_chat(x)
559
- text += " • {}\n".format(mention_html(user.id, user.first_name))
560
-
561
- await update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
562
-
563
-
564
- async def fed_ban(update: Update, context: ContextTypes.DEFAULT_TYPE):
565
- bot, args = context.bot, context.args
566
- chat = update.effective_chat
567
- user = update.effective_user
568
-
569
- if chat.type == "private":
570
- await send_message(
571
- update.effective_message,
572
- "This command is specific to the group, not to our pm!",
573
- )
574
- return
575
-
576
- fed_id = sql.get_fed_id(chat.id)
577
-
578
- if not fed_id:
579
- await update.effective_message.reply_text(
580
- "This group is not a part of any federation!",
581
- )
582
- return
583
-
584
- info = sql.get_fed_info(fed_id)
585
- getfednotif = sql.user_feds_report(info["owner"])
586
-
587
- if is_user_fed_admin(fed_id, user.id) is False:
588
- await update.effective_message.reply_text("Only federation admins can do this!")
589
- return
590
-
591
- message = update.effective_message
592
-
593
- user_id, reason = extract_unt_fedban(message, context, args)
594
-
595
- fban, fbanreason, fbantime = sql.get_fban_user(fed_id, user_id)
596
-
597
- if not user_id:
598
- await message.reply_text("You don't seem to be referring to a user")
599
- return
600
-
601
- if user_id == bot.id:
602
- await message.reply_text(
603
- "What is funnier than kicking the group creator? Self sacrifice.",
604
- )
605
- return
606
-
607
- if is_user_fed_owner(fed_id, user_id) is True:
608
- await message.reply_text("Why did you try the federation fban?")
609
- return
610
-
611
- if is_user_fed_admin(fed_id, user_id) is True:
612
- await message.reply_text("He is a federation admin, I can't fban him.")
613
- return
614
-
615
- if user_id == OWNER_ID:
616
- await message.reply_text("Disaster level God cannot be fed banned!")
617
- return
618
-
619
- if int(user_id) in DRAGONS:
620
- await message.reply_text("Dragons cannot be fed banned!")
621
- return
622
-
623
- if user_id in [777000, 1087968824]:
624
- await message.reply_text("Fool! You can't attack Telegram's native tech!")
625
- return
626
-
627
- try:
628
- user_chat = await bot.get_chat(user_id)
629
- isvalid = True
630
- fban_user_id = user_chat.id
631
- fban_user_name = user_chat.first_name
632
- fban_user_lname = user_chat.last_name
633
- fban_user_uname = user_chat.username
634
- except BadRequest as excp:
635
- if not str(user_id).isdigit():
636
- await send_message(update.effective_message, excp.message)
637
- return
638
- elif len(str(user_id)) != 9:
639
- await send_message(update.effective_message, "That's so not a user!")
640
- return
641
- isvalid = False
642
- fban_user_id = int(user_id)
643
- fban_user_name = "user({})".format(user_id)
644
- fban_user_lname = None
645
- fban_user_uname = None
646
-
647
- if isvalid and user_chat.type != "private":
648
- await send_message(update.effective_message, "That's so not a user!")
649
- return
650
-
651
- if isvalid:
652
- user_target = mention_html(fban_user_id, fban_user_name)
653
- else:
654
- user_target = fban_user_name
655
-
656
- if fban:
657
- fed_name = info["fname"]
658
- # https://t.me/OnePunchSupport/41606 // https://t.me/OnePunchSupport/41619
659
- # starting = "The reason fban is replaced for {} in the Federation <b>{}</b>.".format(user_target, fed_name)
660
- # await send_message(update.effective_message, starting, parse_mode=ParseMode.HTML)
661
-
662
- # if reason == "":
663
- # reason = "No reason given."
664
-
665
- temp = sql.un_fban_user(fed_id, fban_user_id)
666
- if not temp:
667
- await message.reply_text("Failed to update the reason for fedban!")
668
- return
669
- x = sql.fban_user(
670
- fed_id,
671
- fban_user_id,
672
- fban_user_name,
673
- fban_user_lname,
674
- fban_user_uname,
675
- reason,
676
- int(time.time()),
677
- )
678
- if not x:
679
- await message.reply_text(
680
- f"Failed to ban from the federation! If this problem continues, contact @{SUPPORT_CHAT}.",
681
- )
682
- return
683
-
684
- fed_chats = sql.all_fed_chats(fed_id)
685
- # Will send to current chat
686
- await bot.send_message(
687
- chat.id,
688
- "<b>FedBan reason updated</b>"
689
- "\n<b>Federation:</b> {}"
690
- "\n<b>Federation Admin:</b> {}"
691
- "\n<b>User:</b> {}"
692
- "\n<b>User ID:</b> <code>{}</code>"
693
- "\n<b>Reason:</b> {}".format(
694
- fed_name,
695
- mention_html(user.id, user.first_name),
696
- user_target,
697
- fban_user_id,
698
- reason,
699
- ),
700
- parse_mode="HTML",
701
- )
702
- # Send message to owner if fednotif is enabled
703
- if getfednotif:
704
- await bot.send_message(
705
- info["owner"],
706
- "<b>FedBan reason updated</b>"
707
- "\n<b>Federation:</b> {}"
708
- "\n<b>Federation Admin:</b> {}"
709
- "\n<b>User:</b> {}"
710
- "\n<b>User ID:</b> <code>{}</code>"
711
- "\n<b>Reason:</b> {}".format(
712
- fed_name,
713
- mention_html(user.id, user.first_name),
714
- user_target,
715
- fban_user_id,
716
- reason,
717
- ),
718
- parse_mode="HTML",
719
- )
720
- # If fedlog is set, then send message, except fedlog is current chat
721
- get_fedlog = await sql.get_fed_log(fed_id)
722
- if get_fedlog:
723
- if int(get_fedlog) != int(chat.id):
724
- await bot.send_message(
725
- get_fedlog,
726
- "<b>FedBan reason updated</b>"
727
- "\n<b>Federation:</b> {}"
728
- "\n<b>Federation Admin:</b> {}"
729
- "\n<b>User:</b> {}"
730
- "\n<b>User ID:</b> <code>{}</code>"
731
- "\n<b>Reason:</b> {}".format(
732
- fed_name,
733
- mention_html(user.id, user.first_name),
734
- user_target,
735
- fban_user_id,
736
- reason,
737
- ),
738
- parse_mode="HTML",
739
- )
740
- for fedschat in fed_chats:
741
- try:
742
- # Do not spam all fed chats
743
- """
744
- bot.send_message(chat, "<b>FedBan reason updated</b>" \
745
- "\n<b>Federation:</b> {}" \
746
- "\n<b>Federation Admin:</b> {}" \
747
- "\n<b>User:</b> {}" \
748
- "\n<b>User ID:</b> <code>{}</code>" \
749
- "\n<b>Reason:</b> {}".format(fed_name, mention_html(user.id, user.first_name), user_target, fban_user_id, reason), parse_mode="HTML")
750
- """
751
- await bot.ban_chat_member(fedschat, fban_user_id)
752
- except BadRequest as excp:
753
- if excp.message in FBAN_ERRORS:
754
- try:
755
- await dispatcher.bot.getChat(fedschat)
756
- except Forbidden:
757
- sql.chat_leave_fed(fedschat)
758
- LOGGER.info(
759
- "Chat {} has leave fed {} because I was kicked".format(
760
- fedschat,
761
- info["fname"],
762
- ),
763
- )
764
- continue
765
- elif excp.message == "User_id_invalid":
766
- break
767
- else:
768
- LOGGER.warning(
769
- "Could not fban on {} because: {}".format(chat, excp.message),
770
- )
771
- except TelegramError:
772
- pass
773
- # Also do not spam all fed admins
774
- """
775
- send_to_list(bot, FEDADMIN,
776
- "<b>FedBan reason updated</b>" \
777
- "\n<b>Federation:</b> {}" \
778
- "\n<b>Federation Admin:</b> {}" \
779
- "\n<b>User:</b> {}" \
780
- "\n<b>User ID:</b> <code>{}</code>" \
781
- "\n<b>Reason:</b> {}".format(fed_name, mention_html(user.id, user.first_name), user_target, fban_user_id, reason),
782
- html=True)
783
- """
784
-
785
- # Fban for fed subscriber
786
- subscriber = list(sql.get_subscriber(fed_id))
787
- if len(subscriber) != 0:
788
- for fedsid in subscriber:
789
- all_fedschat = sql.all_fed_chats(fedsid)
790
- for fedschat in all_fedschat:
791
- try:
792
- await bot.ban_chat_member(fedschat, fban_user_id)
793
- except BadRequest as excp:
794
- if excp.message in FBAN_ERRORS:
795
- try:
796
- await dispatcher.bot.getChat(fedschat)
797
- except Forbidden:
798
- targetfed_id = sql.get_fed_id(fedschat)
799
- sql.unsubs_fed(fed_id, targetfed_id)
800
- LOGGER.info(
801
- "Chat {} has unsub fed {} because I was kicked".format(
802
- fedschat,
803
- info["fname"],
804
- ),
805
- )
806
- continue
807
- elif excp.message == "User_id_invalid":
808
- break
809
- else:
810
- LOGGER.warning(
811
- "Unable to fban on {} because: {}".format(
812
- fedschat,
813
- excp.message,
814
- ),
815
- )
816
- except TelegramError:
817
- pass
818
- # await send_message(update.effective_message, "Fedban Reason has been updated.")
819
- return
820
-
821
- fed_name = info["fname"]
822
-
823
- # starting = "Starting a federation ban for {} in the Federation <b>{}</b>.".format(
824
- # user_target, fed_name)
825
- # await update.effective_message.reply_text(starting, parse_mode=ParseMode.HTML)
826
-
827
- # if reason == "":
828
- # reason = "No reason given."
829
-
830
- x = sql.fban_user(
831
- fed_id,
832
- fban_user_id,
833
- fban_user_name,
834
- fban_user_lname,
835
- fban_user_uname,
836
- reason,
837
- int(time.time()),
838
- )
839
- if not x:
840
- await message.reply_text(
841
- f"Failed to ban from the federation! If this problem continues, contact @{SUPPORT_CHAT}.",
842
- )
843
- return
844
-
845
- fed_chats = sql.all_fed_chats(fed_id)
846
- # Will send to current chat
847
- await bot.send_message(
848
- chat.id,
849
- "<b>New FedBan</b>"
850
- "\n<b>Federation:</b> {}"
851
- "\n<b>Federation Admin:</b> {}"
852
- "\n<b>User:</b> {}"
853
- "\n<b>User ID:</b> <code>{}</code>"
854
- "\n<b>Reason:</b> {}".format(
855
- fed_name,
856
- mention_html(user.id, user.first_name),
857
- user_target,
858
- fban_user_id,
859
- reason,
860
- ),
861
- parse_mode="HTML",
862
- )
863
- # Send message to owner if fednotif is enabled
864
- if getfednotif:
865
- await bot.send_message(
866
- info["owner"],
867
- "<b>New FedBan</b>"
868
- "\n<b>Federation:</b> {}"
869
- "\n<b>Federation Admin:</b> {}"
870
- "\n<b>User:</b> {}"
871
- "\n<b>User ID:</b> <code>{}</code>"
872
- "\n<b>Reason:</b> {}".format(
873
- fed_name,
874
- mention_html(user.id, user.first_name),
875
- user_target,
876
- fban_user_id,
877
- reason,
878
- ),
879
- parse_mode="HTML",
880
- )
881
- # If fedlog is set, then send message, except fedlog is current chat
882
- get_fedlog = await sql.get_fed_log(fed_id)
883
- if get_fedlog:
884
- if int(get_fedlog) != int(chat.id):
885
- await bot.send_message(
886
- get_fedlog,
887
- "<b>New FedBan</b>"
888
- "\n<b>Federation:</b> {}"
889
- "\n<b>Federation Admin:</b> {}"
890
- "\n<b>User:</b> {}"
891
- "\n<b>User ID:</b> <code>{}</code>"
892
- "\n<b>Reason:</b> {}".format(
893
- fed_name,
894
- mention_html(user.id, user.first_name),
895
- user_target,
896
- fban_user_id,
897
- reason,
898
- ),
899
- parse_mode="HTML",
900
- )
901
- chats_in_fed = 0
902
- for fedschat in fed_chats:
903
- chats_in_fed += 1
904
- try:
905
- # Do not spamming all fed chats
906
- """
907
- bot.send_message(chat, "<b>FedBan reason updated</b>" \
908
- "\n<b>Federation:</b> {}" \
909
- "\n<b>Federation Admin:</b> {}" \
910
- "\n<b>User:</b> {}" \
911
- "\n<b>User ID:</b> <code>{}</code>" \
912
- "\n<b>Reason:</b> {}".format(fed_name, mention_html(user.id, user.first_name), user_target, fban_user_id, reason), parse_mode="HTML")
913
- """
914
- await bot.ban_chat_member(fedschat, fban_user_id)
915
- except BadRequest as excp:
916
- if excp.message in FBAN_ERRORS:
917
- pass
918
- elif excp.message == "User_id_invalid":
919
- break
920
- else:
921
- LOGGER.warning(
922
- "Could not fban on {} because: {}".format(chat, excp.message),
923
- )
924
- except TelegramError:
925
- pass
926
-
927
- # Also do not spamming all fed admins
928
- """
929
- send_to_list(bot, FEDADMIN,
930
- "<b>FedBan reason updated</b>" \
931
- "\n<b>Federation:</b> {}" \
932
- "\n<b>Federation Admin:</b> {}" \
933
- "\n<b>User:</b> {}" \
934
- "\n<b>User ID:</b> <code>{}</code>" \
935
- "\n<b>Reason:</b> {}".format(fed_name, mention_html(user.id, user.first_name), user_target, fban_user_id, reason),
936
- html=True)
937
- """
938
-
939
- # Fban for fed subscriber
940
- subscriber = list(sql.get_subscriber(fed_id))
941
- if len(subscriber) != 0:
942
- for fedsid in subscriber:
943
- all_fedschat = sql.all_fed_chats(fedsid)
944
- for fedschat in all_fedschat:
945
- try:
946
- await bot.ban_chat_member(fedschat, fban_user_id)
947
- except BadRequest as excp:
948
- if excp.message in FBAN_ERRORS:
949
- try:
950
- await dispatcher.bot.getChat(fedschat)
951
- except Forbidden:
952
- targetfed_id = sql.get_fed_id(fedschat)
953
- sql.unsubs_fed(fed_id, targetfed_id)
954
- LOGGER.info(
955
- "Chat {} has unsub fed {} because I was kicked".format(
956
- fedschat,
957
- info["fname"],
958
- ),
959
- )
960
- continue
961
- elif excp.message == "User_id_invalid":
962
- break
963
- else:
964
- LOGGER.warning(
965
- "Unable to fban on {} because: {}".format(
966
- fedschat,
967
- excp.message,
968
- ),
969
- )
970
- except TelegramError:
971
- pass
972
-
973
-
974
- async def unfban(update: Update, context: ContextTypes.DEFAULT_TYPE):
975
- bot, args = context.bot, context.args
976
- chat = update.effective_chat
977
- user = update.effective_user
978
- message = update.effective_message
979
-
980
- if chat.type == "private":
981
- await send_message(
982
- update.effective_message,
983
- "This command is specific to the group, not to our pm!",
984
- )
985
- return
986
-
987
- fed_id = sql.get_fed_id(chat.id)
988
-
989
- if not fed_id:
990
- await update.effective_message.reply_text(
991
- "This group is not a part of any federation!",
992
- )
993
- return
994
-
995
- info = sql.get_fed_info(fed_id)
996
- getfednotif = sql.user_feds_report(info["owner"])
997
-
998
- if is_user_fed_admin(fed_id, user.id) is False:
999
- await update.effective_message.reply_text("Only federation admins can do this!")
1000
- return
1001
-
1002
- user_id = extract_user_fban(message, context, args)
1003
- if not user_id:
1004
- await message.reply_text("You do not seem to be referring to a user.")
1005
- return
1006
-
1007
- try:
1008
- user_chat = await bot.get_chat(user_id)
1009
- isvalid = True
1010
- fban_user_id = user_chat.id
1011
- fban_user_name = user_chat.first_name
1012
- fban_user_lname = user_chat.last_name
1013
- fban_user_uname = user_chat.username
1014
- except BadRequest as excp:
1015
- if not str(user_id).isdigit():
1016
- await send_message(update.effective_message, excp.message)
1017
- return
1018
- elif len(str(user_id)) != 9:
1019
- await send_message(update.effective_message, "That's so not a user!")
1020
- return
1021
- isvalid = False
1022
- fban_user_id = int(user_id)
1023
- fban_user_name = "user({})".format(user_id)
1024
- fban_user_lname = None
1025
- fban_user_uname = None
1026
-
1027
- if isvalid and user_chat.type != "private":
1028
- await message.reply_text("That's so not a user!")
1029
- return
1030
-
1031
- if isvalid:
1032
- user_target = mention_html(fban_user_id, fban_user_name)
1033
- else:
1034
- user_target = fban_user_name
1035
-
1036
- fban, fbanreason, fbantime = sql.get_fban_user(fed_id, fban_user_id)
1037
- if fban is False:
1038
- await message.reply_text("This user is not fbanned!")
1039
- return
1040
-
1041
- banner = update.effective_user
1042
-
1043
- chat_list = sql.all_fed_chats(fed_id)
1044
- # Will send to current chat
1045
- await bot.send_message(
1046
- chat.id,
1047
- "<b>Un-FedBan</b>"
1048
- "\n<b>Federation:</b> {}"
1049
- "\n<b>Federation Admin:</b> {}"
1050
- "\n<b>User:</b> {}"
1051
- "\n<b>User ID:</b> <code>{}</code>".format(
1052
- info["fname"],
1053
- mention_html(user.id, user.first_name),
1054
- user_target,
1055
- fban_user_id,
1056
- ),
1057
- parse_mode="HTML",
1058
- )
1059
- # Send message to owner if fednotif is enabled
1060
- if getfednotif:
1061
- await bot.send_message(
1062
- info["owner"],
1063
- "<b>Un-FedBan</b>"
1064
- "\n<b>Federation:</b> {}"
1065
- "\n<b>Federation Admin:</b> {}"
1066
- "\n<b>User:</b> {}"
1067
- "\n<b>User ID:</b> <code>{}</code>".format(
1068
- info["fname"],
1069
- mention_html(user.id, user.first_name),
1070
- user_target,
1071
- fban_user_id,
1072
- ),
1073
- parse_mode="HTML",
1074
- )
1075
- # If fedlog is set, then send message, except fedlog is current chat
1076
- get_fedlog = await sql.get_fed_log(fed_id)
1077
- if get_fedlog:
1078
- if int(get_fedlog) != int(chat.id):
1079
- await bot.send_message(
1080
- get_fedlog,
1081
- "<b>Un-FedBan</b>"
1082
- "\n<b>Federation:</b> {}"
1083
- "\n<b>Federation Admin:</b> {}"
1084
- "\n<b>User:</b> {}"
1085
- "\n<b>User ID:</b> <code>{}</code>".format(
1086
- info["fname"],
1087
- mention_html(user.id, user.first_name),
1088
- user_target,
1089
- fban_user_id,
1090
- ),
1091
- parse_mode="HTML",
1092
- )
1093
- unfbanned_in_chats = 0
1094
- for fedchats in chat_list:
1095
- unfbanned_in_chats += 1
1096
- try:
1097
- member = await bot.get_chat_member(fedchats, user_id)
1098
- if member.status == "kicked":
1099
- await bot.unban_chat_member(fedchats, user_id)
1100
- # Do not spamming all fed chats
1101
- """
1102
- bot.send_message(chat, "<b>Un-FedBan</b>" \
1103
- "\n<b>Federation:</b> {}" \
1104
- "\n<b>Federation Admin:</b> {}" \
1105
- "\n<b>User:</b> {}" \
1106
- "\n<b>User ID:</b> <code>{}</code>".format(info['fname'], mention_html(user.id, user.first_name), user_target, fban_user_id), parse_mode="HTML")
1107
- """
1108
- except BadRequest as excp:
1109
- if excp.message in UNFBAN_ERRORS:
1110
- pass
1111
- elif excp.message == "User_id_invalid":
1112
- break
1113
- else:
1114
- LOGGER.warning(
1115
- "Could not fban on {} because: {}".format(chat, excp.message),
1116
- )
1117
- except TelegramError:
1118
- pass
1119
-
1120
- try:
1121
- x = sql.un_fban_user(fed_id, user_id)
1122
- if not x:
1123
- await send_message(
1124
- update.effective_message,
1125
- "Un-fban failed, this user may already be un-fedbanned!",
1126
- )
1127
- return
1128
- except:
1129
- pass
1130
-
1131
- # UnFban for fed subscriber
1132
- subscriber = list(sql.get_subscriber(fed_id))
1133
- if len(subscriber) != 0:
1134
- for fedsid in subscriber:
1135
- all_fedschat = sql.all_fed_chats(fedsid)
1136
- for fedschat in all_fedschat:
1137
- try:
1138
- await bot.unban_chat_member(fedchats, user_id)
1139
- except BadRequest as excp:
1140
- if excp.message in FBAN_ERRORS:
1141
- try:
1142
- await dispatcher.bot.getChat(fedschat)
1143
- except Forbidden:
1144
- targetfed_id = sql.get_fed_id(fedschat)
1145
- sql.unsubs_fed(fed_id, targetfed_id)
1146
- LOGGER.info(
1147
- "Chat {} has unsub fed {} because I was kicked".format(
1148
- fedschat,
1149
- info["fname"],
1150
- ),
1151
- )
1152
- continue
1153
- elif excp.message == "User_id_invalid":
1154
- break
1155
- else:
1156
- LOGGER.warning(
1157
- "Unable to fban on {} because: {}".format(
1158
- fedschat,
1159
- excp.message,
1160
- ),
1161
- )
1162
- except TelegramError:
1163
- pass
1164
-
1165
- if unfbanned_in_chats == 0:
1166
- await send_message(
1167
- update.effective_message,
1168
- "This person has been un-fbanned in 0 chats.",
1169
- )
1170
- if unfbanned_in_chats > 0:
1171
- await send_message(
1172
- update.effective_message,
1173
- "This person has been un-fbanned in {} chats.".format(unfbanned_in_chats),
1174
- )
1175
- # Also do not spamming all fed admins
1176
- """
1177
- FEDADMIN = sql.all_fed_users(fed_id)
1178
- for x in FEDADMIN:
1179
- getreport = sql.user_feds_report(x)
1180
- if getreport is False:
1181
- FEDADMIN.remove(x)
1182
- send_to_list(bot, FEDADMIN,
1183
- "<b>Un-FedBan</b>" \
1184
- "\n<b>Federation:</b> {}" \
1185
- "\n<b>Federation Admin:</b> {}" \
1186
- "\n<b>User:</b> {}" \
1187
- "\n<b>User ID:</b> <code>{}</code>".format(info['fname'], mention_html(user.id, user.first_name),
1188
- mention_html(user_chat.id, user_chat.first_name),
1189
- user_chat.id),
1190
- html=True)
1191
- """
1192
-
1193
-
1194
- async def set_frules(update: Update, context: ContextTypes.DEFAULT_TYPE):
1195
- bot, args = context.bot, context.args
1196
- chat = update.effective_chat
1197
- user = update.effective_user
1198
-
1199
- if chat.type == "private":
1200
- await send_message(
1201
- update.effective_message,
1202
- "This command is specific to the group, not to our pm!",
1203
- )
1204
- return
1205
-
1206
- fed_id = sql.get_fed_id(chat.id)
1207
-
1208
- if not fed_id:
1209
- await update.effective_message.reply_text(
1210
- "This group is not in any federation!"
1211
- )
1212
- return
1213
-
1214
- if is_user_fed_admin(fed_id, user.id) is False:
1215
- await update.effective_message.reply_text("Only fed admins can do this!")
1216
- return
1217
-
1218
- if len(args) >= 1:
1219
- msg = update.effective_message
1220
- raw_text = msg.text
1221
- args = raw_text.split(None, 1) # use python's maxsplit to separate cmd and args
1222
- if len(args) == 2:
1223
- txt = args[1]
1224
- offset = len(txt) - len(raw_text) # set correct offset relative to command
1225
- markdown_rules = markdown_parser(
1226
- txt,
1227
- entities=msg.parse_entities(),
1228
- offset=offset,
1229
- )
1230
- x = sql.set_frules(fed_id, markdown_rules)
1231
- if not x:
1232
- await update.effective_message.reply_text(
1233
- f"Whoa! There was an error while setting federation rules! If you wondered why please ask it in @{SUPPORT_CHAT}!",
1234
- )
1235
- return
1236
-
1237
- rules = sql.get_fed_info(fed_id)["frules"]
1238
- getfed = sql.get_fed_info(fed_id)
1239
- get_fedlog = await sql.get_fed_log(fed_id)
1240
- if get_fedlog:
1241
- if ast.literal_eval(get_fedlog):
1242
- await bot.send_message(
1243
- get_fedlog,
1244
- "*{}* has updated federation rules for fed *{}*".format(
1245
- user.first_name,
1246
- getfed["fname"],
1247
- ),
1248
- parse_mode="markdown",
1249
- message_thread_id=update.effective_message.message_thread_id
1250
- if chat.is_forum
1251
- else None,
1252
- )
1253
- await update.effective_message.reply_text(
1254
- f"Rules have been changed to :\n{rules}!"
1255
- )
1256
- else:
1257
- await update.effective_message.reply_text("Please write rules to set this up!")
1258
-
1259
-
1260
- async def get_frules(update: Update, context: ContextTypes.DEFAULT_TYPE):
1261
- bot, args = context.bot, context.args
1262
- chat = update.effective_chat
1263
-
1264
- if chat.type == "private":
1265
- await send_message(
1266
- update.effective_message,
1267
- "This command is specific to the group, not to our pm!",
1268
- )
1269
- return
1270
-
1271
- fed_id = sql.get_fed_id(chat.id)
1272
- if not fed_id:
1273
- await update.effective_message.reply_text(
1274
- "This group is not in any federation!"
1275
- )
1276
- return
1277
-
1278
- rules = sql.get_frules(fed_id)
1279
- text = "*Rules in this fed:*\n"
1280
- text += rules
1281
- await update.effective_message.reply_text(text, parse_mode=ParseMode.MARKDOWN)
1282
-
1283
-
1284
- async def fed_broadcast(update: Update, context: ContextTypes.DEFAULT_TYPE):
1285
- bot, args = context.bot, context.args
1286
- msg = update.effective_message
1287
- user = update.effective_user
1288
- chat = update.effective_chat
1289
-
1290
- if chat.type == "private":
1291
- await send_message(
1292
- update.effective_message,
1293
- "This command is specific to the group, not to our pm!",
1294
- )
1295
- return
1296
-
1297
- if args:
1298
- chat = update.effective_chat
1299
- fed_id = sql.get_fed_id(chat.id)
1300
- fedinfo = sql.get_fed_info(fed_id)
1301
- if is_user_fed_owner(fed_id, user.id) is False:
1302
- await update.effective_message.reply_text(
1303
- "Only federation owners can do this!"
1304
- )
1305
- return
1306
- # Parsing md
1307
- raw_text = msg.text
1308
- args = raw_text.split(None, 1) # use python's maxsplit to separate cmd and args
1309
- txt = args[1]
1310
- offset = len(txt) - len(raw_text) # set correct offset relative to command
1311
- text_parser = markdown_parser(txt, entities=msg.parse_entities(), offset=offset)
1312
- text = text_parser
1313
- try:
1314
- broadcaster = user.first_name
1315
- except:
1316
- broadcaster = user.first_name + " " + user.last_name
1317
- text += "\n\n- {}".format(mention_markdown(user.id, broadcaster))
1318
- chat_list = sql.all_fed_chats(fed_id)
1319
- failed = 0
1320
- for chat in chat_list:
1321
- title = "*New broadcast from Fed {}*\n".format(fedinfo["fname"])
1322
- try:
1323
- await bot.sendMessage(
1324
- chat,
1325
- title + text,
1326
- parse_mode="markdown",
1327
- message_thread_id=msg.message_thread_id if chat.is_forum else None,
1328
- )
1329
- except TelegramError:
1330
- try:
1331
- await dispatcher.bot.getChat(chat)
1332
- except Forbidden:
1333
- failed += 1
1334
- sql.chat_leave_fed(chat)
1335
- LOGGER.info(
1336
- "Chat {} has left fed {} because I was kicked".format(
1337
- chat,
1338
- fedinfo["fname"],
1339
- ),
1340
- )
1341
- continue
1342
- failed += 1
1343
- LOGGER.warning("Couldn't send broadcast to {}".format(str(chat)))
1344
-
1345
- send_text = "The federation broadcast is complete"
1346
- if failed >= 1:
1347
- send_text += "{} the group failed to receive the message, probably because it left the Federation.".format(
1348
- failed,
1349
- )
1350
- await update.effective_message.reply_text(send_text)
1351
-
1352
-
1353
- async def fed_ban_list(update: Update, context: ContextTypes.DEFAULT_TYPE):
1354
- bot, args, chat_data = context.bot, context.args, context.chat_data
1355
- chat = update.effective_chat
1356
- user = update.effective_user
1357
-
1358
- if chat.type == "private":
1359
- await send_message(
1360
- update.effective_message,
1361
- "This command is specific to the group, not to our pm!",
1362
- )
1363
- return
1364
-
1365
- fed_id = sql.get_fed_id(chat.id)
1366
- info = sql.get_fed_info(fed_id)
1367
-
1368
- if not fed_id:
1369
- await update.effective_message.reply_text(
1370
- "This group is not a part of any federation!",
1371
- )
1372
- return
1373
-
1374
- if is_user_fed_owner(fed_id, user.id) is False:
1375
- await update.effective_message.reply_text("Only Federation owners can do this!")
1376
- return
1377
-
1378
- user = update.effective_user
1379
- chat = update.effective_chat
1380
- getfban = sql.get_all_fban_users(fed_id)
1381
- if len(getfban) == 0:
1382
- await update.effective_message.reply_text(
1383
- "The federation ban list of {} is empty".format(info["fname"]),
1384
- parse_mode=ParseMode.HTML,
1385
- )
1386
- return
1387
-
1388
- if args:
1389
- if args[0] == "json":
1390
- jam = time.time()
1391
- new_jam = jam + 1800
1392
- cek = get_chat(chat.id, chat_data)
1393
- if cek.get("status"):
1394
- if jam <= int(cek.get("value")):
1395
- waktu = time.strftime(
1396
- "%H:%M:%S %d/%m/%Y",
1397
- time.localtime(cek.get("value")),
1398
- )
1399
- await update.effective_message.reply_text(
1400
- "You can backup your data once every 30 minutes!\nYou can back up data again at `{}`".format(
1401
- waktu,
1402
- ),
1403
- parse_mode=ParseMode.MARKDOWN,
1404
- )
1405
- return
1406
- else:
1407
- if user.id not in DRAGONS:
1408
- put_chat(chat.id, new_jam, chat_data)
1409
- else:
1410
- if user.id not in DRAGONS:
1411
- put_chat(chat.id, new_jam, chat_data)
1412
- backups = ""
1413
- for users in getfban:
1414
- getuserinfo = sql.get_all_fban_users_target(fed_id, users)
1415
- json_parser = {
1416
- "user_id": users,
1417
- "first_name": getuserinfo["first_name"],
1418
- "last_name": getuserinfo["last_name"],
1419
- "user_name": getuserinfo["user_name"],
1420
- "reason": getuserinfo["reason"],
1421
- }
1422
- backups += json.dumps(json_parser)
1423
- backups += "\n"
1424
- with BytesIO(str.encode(backups)) as output:
1425
- output.name = "mikobot_fbanned_users.json"
1426
- await update.effective_message.reply_document(
1427
- document=output,
1428
- filename="mikobot_fbanned_users.json",
1429
- caption="Total {} User are blocked by the Federation {}.".format(
1430
- len(getfban),
1431
- info["fname"],
1432
- ),
1433
- )
1434
- return
1435
- elif args[0] == "csv":
1436
- jam = time.time()
1437
- new_jam = jam + 1800
1438
- cek = get_chat(chat.id, chat_data)
1439
- if cek.get("status"):
1440
- if jam <= int(cek.get("value")):
1441
- waktu = time.strftime(
1442
- "%H:%M:%S %d/%m/%Y",
1443
- time.localtime(cek.get("value")),
1444
- )
1445
- await update.effective_message.reply_text(
1446
- "You can back up data once every 30 minutes!\nYou can back up data again at `{}`".format(
1447
- waktu,
1448
- ),
1449
- parse_mode=ParseMode.MARKDOWN,
1450
- )
1451
- return
1452
- else:
1453
- if user.id not in DRAGONS:
1454
- put_chat(chat.id, new_jam, chat_data)
1455
- else:
1456
- if user.id not in DRAGONS:
1457
- put_chat(chat.id, new_jam, chat_data)
1458
- backups = "id,firstname,lastname,username,reason\n"
1459
- for users in getfban:
1460
- getuserinfo = sql.get_all_fban_users_target(fed_id, users)
1461
- backups += (
1462
- "{user_id},{first_name},{last_name},{user_name},{reason}".format(
1463
- user_id=users,
1464
- first_name=getuserinfo["first_name"],
1465
- last_name=getuserinfo["last_name"],
1466
- user_name=getuserinfo["user_name"],
1467
- reason=getuserinfo["reason"],
1468
- )
1469
- )
1470
- backups += "\n"
1471
- with BytesIO(str.encode(backups)) as output:
1472
- output.name = "mikobot_fbanned_users.csv"
1473
- await update.effective_message.reply_document(
1474
- document=output,
1475
- filename="mikobot_fbanned_users.csv",
1476
- caption="Total {} User are blocked by Federation {}.".format(
1477
- len(getfban),
1478
- info["fname"],
1479
- ),
1480
- )
1481
- return
1482
-
1483
- text = "<b>{} users have been banned from the federation {}:</b>\n".format(
1484
- len(getfban),
1485
- info["fname"],
1486
- )
1487
- for users in getfban:
1488
- getuserinfo = sql.get_all_fban_users_target(fed_id, users)
1489
- if getuserinfo is False:
1490
- text = "There are no users banned from the federation {}".format(
1491
- info["fname"],
1492
- )
1493
- break
1494
- user_name = getuserinfo["first_name"]
1495
- if getuserinfo["last_name"]:
1496
- user_name += " " + getuserinfo["last_name"]
1497
- text += " • {} (<code>{}</code>)\n".format(
1498
- mention_html(users, user_name),
1499
- users,
1500
- )
1501
-
1502
- try:
1503
- await update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
1504
- except:
1505
- jam = time.time()
1506
- new_jam = jam + 1800
1507
- cek = get_chat(chat.id, chat_data)
1508
- if cek.get("status"):
1509
- if jam <= int(cek.get("value")):
1510
- waktu = time.strftime(
1511
- "%H:%M:%S %d/%m/%Y",
1512
- time.localtime(cek.get("value")),
1513
- )
1514
- await update.effective_message.reply_text(
1515
- "You can back up data once every 30 minutes!\nYou can back up data again at `{}`".format(
1516
- waktu,
1517
- ),
1518
- parse_mode=ParseMode.MARKDOWN,
1519
- )
1520
- return
1521
- else:
1522
- if user.id not in DRAGONS:
1523
- put_chat(chat.id, new_jam, chat_data)
1524
- else:
1525
- if user.id not in DRAGONS:
1526
- put_chat(chat.id, new_jam, chat_data)
1527
- cleanr = re.compile("<.*?>")
1528
- cleantext = re.sub(cleanr, "", text)
1529
- with BytesIO(str.encode(cleantext)) as output:
1530
- output.name = "fbanlist.txt"
1531
- await update.effective_message.reply_document(
1532
- document=output,
1533
- filename="fbanlist.txt",
1534
- caption="The following is a list of users who are currently fbanned in the Federation {}.".format(
1535
- info["fname"],
1536
- ),
1537
- )
1538
-
1539
-
1540
- async def fed_notif(update: Update, context: ContextTypes.DEFAULT_TYPE):
1541
- bot, args = context.bot, context.args
1542
- chat = update.effective_chat
1543
- user = update.effective_user
1544
- msg = update.effective_message
1545
- fed_id = sql.get_fed_id(chat.id)
1546
-
1547
- if not fed_id:
1548
- await update.effective_message.reply_text(
1549
- "This group is not a part of any federation!",
1550
- )
1551
- return
1552
-
1553
- if args:
1554
- if args[0] in ("yes", "on"):
1555
- sql.set_feds_setting(user.id, True)
1556
- await msg.reply_text(
1557
- "Reporting Federation back up! Every user who is fban / unfban you will be notified via PM.",
1558
- )
1559
- elif args[0] in ("no", "off"):
1560
- sql.set_feds_setting(user.id, False)
1561
- await msg.reply_text(
1562
- "Reporting Federation has stopped! Every user who is fban / unfban you will not be notified via PM.",
1563
- )
1564
- else:
1565
- await msg.reply_text("Please enter `on`/`off`", parse_mode="markdown")
1566
- else:
1567
- getreport = sql.user_feds_report(user.id)
1568
- await msg.reply_text(
1569
- "Your current Federation report preferences: `{}`".format(getreport),
1570
- parse_mode="markdown",
1571
- )
1572
-
1573
-
1574
- async def fed_chats(update: Update, context: ContextTypes.DEFAULT_TYPE):
1575
- bot, args = context.bot, context.args
1576
- chat = update.effective_chat
1577
- user = update.effective_user
1578
-
1579
- if chat.type == "private":
1580
- await send_message(
1581
- update.effective_message,
1582
- "This command is specific to the group, not to our pm!",
1583
- )
1584
- return
1585
-
1586
- fed_id = sql.get_fed_id(chat.id)
1587
- info = sql.get_fed_info(fed_id)
1588
-
1589
- if not fed_id:
1590
- await update.effective_message.reply_text(
1591
- "This group is not a part of any federation!",
1592
- )
1593
- return
1594
-
1595
- if is_user_fed_admin(fed_id, user.id) is False:
1596
- await update.effective_message.reply_text("Only federation admins can do this!")
1597
- return
1598
-
1599
- getlist = sql.all_fed_chats(fed_id)
1600
- if len(getlist) == 0:
1601
- await update.effective_message.reply_text(
1602
- "No users are fbanned from the federation {}".format(info["fname"]),
1603
- parse_mode=ParseMode.HTML,
1604
- )
1605
- return
1606
-
1607
- text = "<b>New chat joined the federation {}:</b>\n".format(info["fname"])
1608
- for chats in getlist:
1609
- try:
1610
- chat_obj = await dispatcher.bot.getChat(chats)
1611
- chat_name = chat_obj.title
1612
- except Forbidden:
1613
- sql.chat_leave_fed(chats)
1614
- LOGGER.info(
1615
- "Chat {} has leave fed {} because I was kicked".format(
1616
- chats,
1617
- info["fname"],
1618
- ),
1619
- )
1620
- continue
1621
- text += " • {} (<code>{}</code>)\n".format(chat_name, chats)
1622
-
1623
- try:
1624
- await update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
1625
- except:
1626
- cleanr = re.compile("<.*?>")
1627
- cleantext = re.sub(cleanr, "", text)
1628
- with BytesIO(str.encode(cleantext)) as output:
1629
- output.name = "fedchats.txt"
1630
- await update.effective_message.reply_document(
1631
- document=output,
1632
- filename="fedchats.txt",
1633
- caption="Here is a list of all the chats that joined the federation {}.".format(
1634
- info["fname"],
1635
- ),
1636
- )
1637
-
1638
-
1639
- async def fed_import_bans(update: Update, context: ContextTypes.DEFAULT_TYPE):
1640
- bot, chat_data = context.bot, context.chat_data
1641
- chat = update.effective_chat
1642
- user = update.effective_user
1643
- msg = update.effective_message
1644
-
1645
- if chat.type == "private":
1646
- await send_message(
1647
- update.effective_message,
1648
- "This command is specific to the group, not to our pm!",
1649
- )
1650
- return
1651
-
1652
- fed_id = sql.get_fed_id(chat.id)
1653
- info = sql.get_fed_info(fed_id)
1654
- getfed = sql.get_fed_info(fed_id)
1655
-
1656
- if not fed_id:
1657
- await update.effective_message.reply_text(
1658
- "This group is not a part of any federation!",
1659
- )
1660
- return
1661
-
1662
- if is_user_fed_owner(fed_id, user.id) is False:
1663
- await update.effective_message.reply_text("Only Federation owners can do this!")
1664
- return
1665
-
1666
- if msg.reply_to_message and msg.reply_to_message.document:
1667
- jam = time.time()
1668
- new_jam = jam + 1800
1669
- cek = get_chat(chat.id, chat_data)
1670
- if cek.get("status"):
1671
- if jam <= int(cek.get("value")):
1672
- waktu = time.strftime(
1673
- "%H:%M:%S %d/%m/%Y",
1674
- time.localtime(cek.get("value")),
1675
- )
1676
- await update.effective_message.reply_text(
1677
- "You can get your data once every 30 minutes!\nYou can get data again at `{}`".format(
1678
- waktu,
1679
- ),
1680
- parse_mode=ParseMode.MARKDOWN,
1681
- )
1682
- return
1683
- else:
1684
- if user.id not in DRAGONS:
1685
- put_chat(chat.id, new_jam, chat_data)
1686
- else:
1687
- if user.id not in DRAGONS:
1688
- put_chat(chat.id, new_jam, chat_data)
1689
- # if int(int(msg.reply_to_message.document.file_size)/1024) >= 200:
1690
- # msg.reply_text("This file is too big!")
1691
- # return
1692
- success = 0
1693
- failed = 0
1694
- try:
1695
- file_info = await bot.get_file(msg.reply_to_message.document.file_id)
1696
- except BadRequest:
1697
- await msg.reply_text(
1698
- "Try downloading and re-uploading the file, this one seems broken!",
1699
- )
1700
- return
1701
- fileformat = msg.reply_to_message.document.file_name.split(".")[-1]
1702
- if fileformat == "json":
1703
- multi_fed_id = []
1704
- multi_import_userid = []
1705
- multi_import_firstname = []
1706
- multi_import_lastname = []
1707
- multi_import_username = []
1708
- multi_import_reason = []
1709
- with BytesIO() as file:
1710
- file_info.download_to_object(out=file)
1711
- file.seek(0)
1712
- reading = file.read().decode("UTF-8")
1713
- splitting = reading.split("\n")
1714
- for x in splitting:
1715
- if x == "":
1716
- continue
1717
- try:
1718
- data = json.loads(x)
1719
- except json.decoder.JSONDecodeError as err:
1720
- failed += 1
1721
- continue
1722
- try:
1723
- import_userid = int(data["user_id"]) # Make sure it int
1724
- import_firstname = str(data["first_name"])
1725
- import_lastname = str(data["last_name"])
1726
- import_username = str(data["user_name"])
1727
- import_reason = str(data["reason"])
1728
- except ValueError:
1729
- failed += 1
1730
- continue
1731
- # Checking user
1732
- if int(import_userid) == bot.id:
1733
- failed += 1
1734
- continue
1735
- if is_user_fed_owner(fed_id, import_userid) is True:
1736
- failed += 1
1737
- continue
1738
- if is_user_fed_admin(fed_id, import_userid) is True:
1739
- failed += 1
1740
- continue
1741
- if str(import_userid) == str(OWNER_ID):
1742
- failed += 1
1743
- continue
1744
- if int(import_userid) in DRAGONS:
1745
- failed += 1
1746
- continue
1747
- multi_fed_id.append(fed_id)
1748
- multi_import_userid.append(str(import_userid))
1749
- multi_import_firstname.append(import_firstname)
1750
- multi_import_lastname.append(import_lastname)
1751
- multi_import_username.append(import_username)
1752
- multi_import_reason.append(import_reason)
1753
- success += 1
1754
- sql.multi_fban_user(
1755
- multi_fed_id,
1756
- multi_import_userid,
1757
- multi_import_firstname,
1758
- multi_import_lastname,
1759
- multi_import_username,
1760
- multi_import_reason,
1761
- )
1762
- text = "Blocks were successfully imported. {} people are blocked.".format(
1763
- success,
1764
- )
1765
- if failed >= 1:
1766
- text += " {} Failed to import.".format(failed)
1767
- get_fedlog = await sql.get_fed_log(fed_id)
1768
- if get_fedlog:
1769
- if ast.literal_eval(get_fedlog):
1770
- teks = "Fed *{}* has successfully imported data. {} banned.".format(
1771
- getfed["fname"],
1772
- success,
1773
- )
1774
- if failed >= 1:
1775
- teks += " {} Failed to import.".format(failed)
1776
- await bot.send_message(
1777
- get_fedlog,
1778
- teks,
1779
- parse_mode="markdown",
1780
- message_thread_id=update.effective_message.message_thread_id
1781
- if chat.is_forum
1782
- else None,
1783
- )
1784
- elif fileformat == "csv":
1785
- multi_fed_id = []
1786
- multi_import_userid = []
1787
- multi_import_firstname = []
1788
- multi_import_lastname = []
1789
- multi_import_username = []
1790
- multi_import_reason = []
1791
- file_info.download_to_drive(
1792
- "fban_{}.csv".format(msg.reply_to_message.document.file_id),
1793
- )
1794
- with open(
1795
- "fban_{}.csv".format(msg.reply_to_message.document.file_id),
1796
- "r",
1797
- encoding="utf8",
1798
- ) as csvFile:
1799
- reader = csv.reader(csvFile)
1800
- for data in reader:
1801
- try:
1802
- import_userid = int(data[0]) # Make sure it int
1803
- import_firstname = str(data[1])
1804
- import_lastname = str(data[2])
1805
- import_username = str(data[3])
1806
- import_reason = str(data[4])
1807
- except ValueError:
1808
- failed += 1
1809
- continue
1810
- # Checking user
1811
- if int(import_userid) == bot.id:
1812
- failed += 1
1813
- continue
1814
- if is_user_fed_owner(fed_id, import_userid) is True:
1815
- failed += 1
1816
- continue
1817
- if is_user_fed_admin(fed_id, import_userid) is True:
1818
- failed += 1
1819
- continue
1820
- if str(import_userid) == str(OWNER_ID):
1821
- failed += 1
1822
- continue
1823
- if int(import_userid) in DRAGONS:
1824
- failed += 1
1825
- continue
1826
-
1827
- multi_fed_id.append(fed_id)
1828
- multi_import_userid.append(str(import_userid))
1829
- multi_import_firstname.append(import_firstname)
1830
- multi_import_lastname.append(import_lastname)
1831
- multi_import_username.append(import_username)
1832
- multi_import_reason.append(import_reason)
1833
- success += 1
1834
- # t = ThreadWithReturnValue(target=sql.fban_user, args=(fed_id, str(import_userid), import_firstname, import_lastname, import_username, import_reason,))
1835
- # t.start()
1836
- sql.multi_fban_user(
1837
- multi_fed_id,
1838
- multi_import_userid,
1839
- multi_import_firstname,
1840
- multi_import_lastname,
1841
- multi_import_username,
1842
- multi_import_reason,
1843
- )
1844
- csvFile.close()
1845
- os.remove("fban_{}.csv".format(msg.reply_to_message.document.file_id))
1846
- text = "Files were imported successfully. {} people banned.".format(success)
1847
- if failed >= 1:
1848
- text += " {} Failed to import.".format(failed)
1849
- get_fedlog = await sql.get_fed_log(fed_id)
1850
- if get_fedlog:
1851
- if ast.literal_eval(get_fedlog):
1852
- teks = "Fed *{}* has successfully imported data. {} banned.".format(
1853
- getfed["fname"],
1854
- success,
1855
- )
1856
- if failed >= 1:
1857
- teks += " {} Failed to import.".format(failed)
1858
- await bot.send_message(
1859
- get_fedlog,
1860
- teks,
1861
- parse_mode="markdown",
1862
- message_thread_id=update.effective_message.message_thread_id
1863
- if chat.is_forum
1864
- else None,
1865
- )
1866
- else:
1867
- await send_message(update.effective_message, "This file is not supported.")
1868
- return
1869
- await send_message(update.effective_message, text)
1870
-
1871
-
1872
- async def del_fed_button(update: Update, context: ContextTypes.DEFAULT_TYPE):
1873
- query = update.callback_query
1874
- userid = query.message.chat.id
1875
- fed_id = query.data.split("_")[1]
1876
-
1877
- if fed_id == "cancel":
1878
- await query.message.edit_text("Federation deletion cancelled")
1879
- return
1880
-
1881
- getfed = sql.get_fed_info(fed_id)
1882
- if getfed:
1883
- delete = sql.del_fed(fed_id)
1884
- if delete:
1885
- await query.message.edit_text(
1886
- "You have removed your Federation! Now all the Groups that are connected with `{}` do not have a Federation.".format(
1887
- getfed["fname"],
1888
- ),
1889
- parse_mode="markdown",
1890
- )
1891
-
1892
-
1893
- async def fed_stat_user(update: Update, context: ContextTypes.DEFAULT_TYPE):
1894
- bot, args = context.bot, context.args
1895
- chat = update.effective_chat
1896
- user = update.effective_user
1897
- msg = update.effective_message
1898
-
1899
- if args:
1900
- if args[0].isdigit():
1901
- user_id = args[0]
1902
- else:
1903
- user_id = await extract_user(msg, context, args)
1904
- else:
1905
- user_id = await extract_user(msg, context, args)
1906
-
1907
- if user_id:
1908
- if len(args) == 2 and args[0].isdigit():
1909
- fed_id = args[1]
1910
- user_name, reason, fbantime = sql.get_user_fban(fed_id, str(user_id))
1911
- if fbantime:
1912
- fbantime = time.strftime("%d/%m/%Y", time.localtime(fbantime))
1913
- else:
1914
- fbantime = "Unavaiable"
1915
- if user_name is False:
1916
- await send_message(
1917
- update.effective_message,
1918
- "Fed {} not found!".format(fed_id),
1919
- parse_mode="markdown",
1920
- )
1921
- return
1922
- if user_name == "" or user_name is None:
1923
- user_name = "He/she"
1924
- if not reason:
1925
- await send_message(
1926
- update.effective_message,
1927
- "{} is not banned in this federation!".format(user_name),
1928
- )
1929
- else:
1930
- teks = "{} banned in this federation because:\n`{}`\n*Banned at:* `{}`".format(
1931
- user_name,
1932
- reason,
1933
- fbantime,
1934
- )
1935
- await send_message(
1936
- update.effective_message, teks, parse_mode="markdown"
1937
- )
1938
- return
1939
- user_name, fbanlist = sql.get_user_fbanlist(str(user_id))
1940
- if user_name == "":
1941
- try:
1942
- user_first = await bot.get_chat(user_id)
1943
- if isinstance(user_first, ChatMember):
1944
- user_name = user_id.first_name
1945
- except BadRequest:
1946
- user_name = "He/she"
1947
- if user_name == "" or user_name is None:
1948
- user_name = "He/she"
1949
- if len(fbanlist) == 0:
1950
- await send_message(
1951
- update.effective_message,
1952
- "{} is not banned in any federation!".format(user_name),
1953
- )
1954
- return
1955
- else:
1956
- teks = "{} has been banned in this federation:\n".format(user_name)
1957
- for x in fbanlist:
1958
- teks += "- `{}`: {}\n".format(x[0], x[1][:20])
1959
- teks += "\nIf you want to find out more about the reasons for Fedban specifically, use /fbanstat <FedID>"
1960
- await send_message(update.effective_message, teks, parse_mode="markdown")
1961
-
1962
- elif not msg.reply_to_message and not args:
1963
- user_id = msg.from_user.id
1964
- user_name, fbanlist = sql.get_user_fbanlist(user_id)
1965
- if user_name == "":
1966
- user_name = msg.from_user.first_name
1967
- if len(fbanlist) == 0:
1968
- await send_message(
1969
- update.effective_message,
1970
- "{} is not banned in any federation!".format(user_name),
1971
- )
1972
- else:
1973
- teks = "{} has been banned in this federation:\n".format(user_name)
1974
- for x in fbanlist:
1975
- teks += "- `{}`: {}\n".format(x[0], x[1][:20])
1976
- teks += "\nIf you want to find out more about the reasons for Fedban specifically, use /fbanstat <FedID>"
1977
- await send_message(update.effective_message, teks, parse_mode="markdown")
1978
-
1979
- else:
1980
- fed_id = args[0]
1981
- fedinfo = sql.get_fed_info(fed_id)
1982
- if not fedinfo:
1983
- await send_message(
1984
- update.effective_message, "Fed {} not found!".format(fed_id)
1985
- )
1986
- return
1987
- name, reason, fbantime = sql.get_user_fban(fed_id, msg.from_user.id)
1988
- if fbantime:
1989
- fbantime = time.strftime("%d/%m/%Y", time.localtime(fbantime))
1990
- else:
1991
- fbantime = "Unavaiable"
1992
- if not name:
1993
- name = msg.from_user.first_name
1994
- if not reason:
1995
- await send_message(
1996
- update.effective_message,
1997
- "{} is not banned in this federation".format(name),
1998
- )
1999
- return
2000
- await send_message(
2001
- update.effective_message,
2002
- "{} banned in this federation because:\n`{}`\n*Banned at:* `{}`".format(
2003
- name,
2004
- reason,
2005
- fbantime,
2006
- ),
2007
- parse_mode="markdown",
2008
- )
2009
-
2010
-
2011
- async def set_fed_log(update: Update, context: ContextTypes.DEFAULT_TYPE):
2012
- args = context.args
2013
- chat = update.effective_chat
2014
- user = update.effective_user
2015
- msg = update.effective_message
2016
-
2017
- if chat.type == "private":
2018
- await send_message(
2019
- update.effective_message,
2020
- "This command is specific to the group, not to our pm!",
2021
- )
2022
- return
2023
-
2024
- if args:
2025
- fedinfo = sql.get_fed_info(args[0])
2026
- if not fedinfo:
2027
- await send_message(
2028
- update.effective_message, "This Federation does not exist!"
2029
- )
2030
- return
2031
- isowner = is_user_fed_owner(args[0], user.id)
2032
- if not isowner:
2033
- await send_message(
2034
- update.effective_message,
2035
- "Only federation creator can set federation logs.",
2036
- )
2037
- return
2038
- setlog = sql.set_fed_log(args[0], chat.id)
2039
- if setlog:
2040
- await send_message(
2041
- update.effective_message,
2042
- "Federation log `{}` has been set to {}".format(
2043
- fedinfo["fname"],
2044
- chat.title,
2045
- ),
2046
- parse_mode="markdown",
2047
- )
2048
- else:
2049
- await send_message(
2050
- update.effective_message,
2051
- "You have not provided your federated ID!",
2052
- )
2053
-
2054
-
2055
- async def unset_fed_log(update: Update, context: ContextTypes.DEFAULT_TYPE):
2056
- args = context.args
2057
- chat = update.effective_chat
2058
- user = update.effective_user
2059
- msg = update.effective_message
2060
-
2061
- if chat.type == "private":
2062
- await send_message(
2063
- update.effective_message,
2064
- "This command is specific to the group, not to our pm!",
2065
- )
2066
- return
2067
-
2068
- if args:
2069
- fedinfo = sql.get_fed_info(args[0])
2070
- if not fedinfo:
2071
- await send_message(
2072
- update.effective_message, "This Federation does not exist!"
2073
- )
2074
- return
2075
- isowner = is_user_fed_owner(args[0], user.id)
2076
- if not isowner:
2077
- await send_message(
2078
- update.effective_message,
2079
- "Only federation creator can set federation logs.",
2080
- )
2081
- return
2082
- setlog = sql.set_fed_log(args[0], None)
2083
- if setlog:
2084
- await send_message(
2085
- update.effective_message,
2086
- "Federation log `{}` has been revoked on {}".format(
2087
- fedinfo["fname"],
2088
- chat.title,
2089
- ),
2090
- parse_mode="markdown",
2091
- )
2092
- else:
2093
- await send_message(
2094
- update.effective_message,
2095
- "You have not provided your federated ID!",
2096
- )
2097
-
2098
-
2099
- async def subs_feds(update: Update, context: ContextTypes.DEFAULT_TYPE):
2100
- bot, args = context.bot, context.args
2101
- chat = update.effective_chat
2102
- user = update.effective_user
2103
- msg = update.effective_message
2104
-
2105
- if chat.type == "private":
2106
- await send_message(
2107
- update.effective_message,
2108
- "This command is specific to the group, not to our pm!",
2109
- )
2110
- return
2111
-
2112
- fed_id = sql.get_fed_id(chat.id)
2113
- fedinfo = sql.get_fed_info(fed_id)
2114
-
2115
- if not fed_id:
2116
- await send_message(
2117
- update.effective_message, "This group is not in any federation!"
2118
- )
2119
- return
2120
-
2121
- if is_user_fed_owner(fed_id, user.id) is False:
2122
- await send_message(update.effective_message, "Only fed owner can do this!")
2123
- return
2124
-
2125
- if args:
2126
- getfed = sql.search_fed_by_id(args[0])
2127
- if getfed is False:
2128
- await send_message(
2129
- update.effective_message,
2130
- "Please enter a valid federation id.",
2131
- )
2132
- return
2133
- subfed = sql.subs_fed(args[0], fed_id)
2134
- if subfed:
2135
- await send_message(
2136
- update.effective_message,
2137
- "Federation `{}` has subscribe the federation `{}`. Every time there is a Fedban from that federation, this federation will also banned that user.".format(
2138
- fedinfo["fname"],
2139
- getfed["fname"],
2140
- ),
2141
- parse_mode="markdown",
2142
- )
2143
- get_fedlog = await sql.get_fed_log(args[0])
2144
- if get_fedlog:
2145
- if int(get_fedlog) != int(chat.id):
2146
- await bot.send_message(
2147
- get_fedlog,
2148
- "Federation `{}` has subscribe the federation `{}`".format(
2149
- fedinfo["fname"],
2150
- getfed["fname"],
2151
- ),
2152
- parse_mode="markdown",
2153
- message_thread_id=update.effective_message.message_thread_id
2154
- if chat.is_forum
2155
- else None,
2156
- )
2157
- else:
2158
- await send_message(
2159
- update.effective_message,
2160
- "Federation `{}` already subscribe the federation `{}`.".format(
2161
- fedinfo["fname"],
2162
- getfed["fname"],
2163
- ),
2164
- parse_mode="markdown",
2165
- )
2166
- else:
2167
- await send_message(
2168
- update.effective_message,
2169
- "You have not provided your federated ID!",
2170
- )
2171
-
2172
-
2173
- async def unsubs_feds(update: Update, context: ContextTypes.DEFAULT_TYPE):
2174
- bot, args = context.bot, context.args
2175
- chat = update.effective_chat
2176
- user = update.effective_user
2177
- msg = update.effective_message
2178
-
2179
- if chat.type == "private":
2180
- await send_message(
2181
- update.effective_message,
2182
- "This command is specific to the group, not to our pm!",
2183
- )
2184
- return
2185
-
2186
- fed_id = sql.get_fed_id(chat.id)
2187
- fedinfo = sql.get_fed_info(fed_id)
2188
-
2189
- if not fed_id:
2190
- await send_message(
2191
- update.effective_message, "This group is not in any federation!"
2192
- )
2193
- return
2194
-
2195
- if is_user_fed_owner(fed_id, user.id) is False:
2196
- await send_message(update.effective_message, "Only fed owner can do this!")
2197
- return
2198
-
2199
- if args:
2200
- getfed = sql.search_fed_by_id(args[0])
2201
- if getfed is False:
2202
- await send_message(
2203
- update.effective_message,
2204
- "Please enter a valid federation id.",
2205
- )
2206
- return
2207
- subfed = sql.unsubs_fed(args[0], fed_id)
2208
- if subfed:
2209
- await send_message(
2210
- update.effective_message,
2211
- "Federation `{}` now unsubscribe fed `{}`.".format(
2212
- fedinfo["fname"],
2213
- getfed["fname"],
2214
- ),
2215
- parse_mode="markdown",
2216
- )
2217
- get_fedlog = await sql.get_fed_log(args[0])
2218
- if get_fedlog:
2219
- if int(get_fedlog) != int(chat.id):
2220
- await bot.send_message(
2221
- get_fedlog,
2222
- "Federation `{}` has unsubscribe fed `{}`.".format(
2223
- fedinfo["fname"],
2224
- getfed["fname"],
2225
- ),
2226
- parse_mode="markdown",
2227
- message_thread_id=update.effective_message.message_thread_id
2228
- if chat.is_forum
2229
- else None,
2230
- )
2231
- else:
2232
- await send_message(
2233
- update.effective_message,
2234
- "Federation `{}` is not subscribing `{}`.".format(
2235
- fedinfo["fname"],
2236
- getfed["fname"],
2237
- ),
2238
- parse_mode="markdown",
2239
- )
2240
- else:
2241
- await send_message(
2242
- update.effective_message,
2243
- "You have not provided your federated ID!",
2244
- )
2245
-
2246
-
2247
- async def get_myfedsubs(update: Update, context: ContextTypes.DEFAULT_TYPE):
2248
- args = context.args
2249
- chat = update.effective_chat
2250
- user = update.effective_user
2251
- msg = update.effective_message
2252
-
2253
- if chat.type == "private":
2254
- await send_message(
2255
- update.effective_message,
2256
- "This command is specific to the group, not to our pm!",
2257
- )
2258
- return
2259
-
2260
- fed_id = sql.get_fed_id(chat.id)
2261
- fedinfo = sql.get_fed_info(fed_id)
2262
-
2263
- if not fed_id:
2264
- await send_message(
2265
- update.effective_message, "This group is not in any federation!"
2266
- )
2267
- return
2268
-
2269
- if is_user_fed_owner(fed_id, user.id) is False:
2270
- await send_message(update.effective_message, "Only fed owner can do this!")
2271
- return
2272
-
2273
- try:
2274
- getmy = sql.get_mysubs(fed_id)
2275
- except:
2276
- getmy = []
2277
-
2278
- if len(getmy) == 0:
2279
- await send_message(
2280
- update.effective_message,
2281
- "Federation `{}` is not subscribing any federation.".format(
2282
- fedinfo["fname"],
2283
- ),
2284
- parse_mode="markdown",
2285
- )
2286
- return
2287
- else:
2288
- listfed = "Federation `{}` is subscribing federation:\n".format(
2289
- fedinfo["fname"],
2290
- )
2291
- for x in getmy:
2292
- listfed += "- `{}`\n".format(x)
2293
- listfed += (
2294
- "\nTo get fed info `/fedinfo <fedid>`. To unsubscribe `/unsubfed <fedid>`."
2295
- )
2296
- await send_message(update.effective_message, listfed, parse_mode="markdown")
2297
-
2298
-
2299
- async def get_myfeds_list(update: Update, context: ContextTypes.DEFAULT_TYPE):
2300
- chat = update.effective_chat
2301
- user = update.effective_user
2302
- msg = update.effective_message
2303
-
2304
- fedowner = sql.get_user_owner_fed_full(user.id)
2305
- if fedowner:
2306
- text = "*You are owner of feds:\n*"
2307
- for f in fedowner:
2308
- text += "- `{}`: *{}*\n".format(f["fed_id"], f["fed"]["fname"])
2309
- else:
2310
- text = "*You are not have any feds!*"
2311
- await send_message(update.effective_message, text, parse_mode="markdown")
2312
-
2313
-
2314
- def is_user_fed_admin(fed_id, user_id):
2315
- fed_admins = sql.all_fed_users(fed_id)
2316
- if fed_admins is False:
2317
- return False
2318
- if int(user_id) in fed_admins or int(user_id) == OWNER_ID:
2319
- return True
2320
- else:
2321
- return False
2322
-
2323
-
2324
- def is_user_fed_owner(fed_id, user_id):
2325
- getsql = sql.get_fed_info(fed_id)
2326
- if getsql is False:
2327
- return False
2328
- getfedowner = ast.literal_eval(getsql["fusers"])
2329
- if getfedowner is None or getfedowner is False:
2330
- return False
2331
- getfedowner = getfedowner["owner"]
2332
- if str(user_id) == getfedowner or int(user_id) == OWNER_ID:
2333
- return True
2334
- else:
2335
- return False
2336
-
2337
-
2338
- # There's no handler for this yet, but updating for v12 in case its used
2339
-
2340
-
2341
- async def welcome_fed(update: Update, context: ContextTypes.DEFAULT_TYPE):
2342
- bot, args = context.bot, context.args
2343
- chat = update.effective_chat
2344
- user = update.effective_user
2345
- fed_id = sql.get_fed_id(chat.id)
2346
- fban, fbanreason, fbantime = sql.get_fban_user(fed_id, user.id)
2347
- if fban:
2348
- await update.effective_message.reply_text(
2349
- "This user is banned in current federation! I will remove him.",
2350
- )
2351
- await bot.ban_chat_member(chat.id, user.id)
2352
- return True
2353
- else:
2354
- return False
2355
-
2356
-
2357
- def __stats__():
2358
- all_fbanned = sql.get_all_fban_users_global()
2359
- all_feds = sql.get_all_feds_users_global()
2360
- return "• {} banned users across {} Federations".format(
2361
- len(all_fbanned),
2362
- len(all_feds),
2363
- )
2364
-
2365
-
2366
- def __user_info__(user_id, chat_id):
2367
- fed_id = sql.get_fed_id(chat_id)
2368
- if fed_id:
2369
- fban, fbanreason, fbantime = sql.get_fban_user(fed_id, user_id)
2370
- info = sql.get_fed_info(fed_id)
2371
- infoname = info["fname"]
2372
-
2373
- if int(info["owner"]) == user_id:
2374
- text = "Federation owner of: <b>{}</b>.".format(infoname)
2375
- elif is_user_fed_admin(fed_id, user_id):
2376
- text = "Federation admin of: <b>{}</b>.".format(infoname)
2377
-
2378
- elif fban:
2379
- text = "Federation banned: <b>Yes</b>"
2380
- text += "\n<b>Reason:</b> {}".format(fbanreason)
2381
- else:
2382
- text = "Federation banned: <b>No</b>"
2383
- else:
2384
- text = ""
2385
- return text
2386
-
2387
-
2388
- # Temporary data
2389
- def put_chat(chat_id, value, chat_data):
2390
- # print(chat_data)
2391
- if value is False:
2392
- status = False
2393
- else:
2394
- status = True
2395
- chat_data[chat_id] = {"federation": {"status": status, "value": value}}
2396
-
2397
-
2398
- def get_chat(chat_id, chat_data):
2399
- # print(chat_data)
2400
- try:
2401
- value = chat_data[chat_id]["federation"]
2402
- return value
2403
- except KeyError:
2404
- return {"status": False, "value": False}
2405
-
2406
-
2407
- async def fed_owner_help(update: Update, context: ContextTypes.DEFAULT_TYPE):
2408
- await update.effective_message.reply_text(
2409
- """*👑 Fed Owner Only:*
2410
- » `/newfed <fed_name>`*:* Creates a Federation, One allowed per user
2411
- » `/renamefed <fed_id> <new_fed_name>`*:* Renames the fed id to a new name
2412
- » `/delfed <fed_id>`*:* Delete a Federation, and any information related to it. Will not cancel blocked users
2413
- » `/fpromote <user>`*:* Assigns the user as a federation admin. Enables all commands for the user under `Fed Admins`
2414
- » `/fdemote <user>`*:* Drops the User from the admin Federation to a normal User
2415
- » `/subfed <fed_id>`*:* Subscribes to a given fed ID, bans from that subscribed fed will also happen in your fed
2416
- » `/unsubfed <fed_id>`*:* Unsubscribes to a given fed ID
2417
- » `/setfedlog <fed_id>`*:* Sets the group as a fed log report base for the federation
2418
- » `/unsetfedlog <fed_id>`*:* Removed the group as a fed log report base for the federation
2419
- » `/fbroadcast <message>`*:* Broadcasts a messages to all groups that have joined your fed
2420
- » `/fedsubs`*:* Shows the feds your group is subscribed to `(broken rn)`""",
2421
- parse_mode=ParseMode.MARKDOWN,
2422
- )
2423
-
2424
-
2425
- async def fed_admin_help(update: Update, context: ContextTypes.DEFAULT_TYPE):
2426
- await update.effective_message.reply_text(
2427
- """*🔱 Fed Admins:*
2428
- » `/fban <user> <reason>`*:* Fed bans a user
2429
- » `/unfban <user> <reason>`*:* Removes a user from a fed ban
2430
- » `/fedinfo <fed_id>`*:* Information about the specified Federation
2431
- » `/joinfed <fed_id>`*:* Join the current chat to the Federation. Only chat owners can do this. Every chat can only be in one Federation
2432
- » `/leavefed <fed_id>`*:* Leave the Federation given. Only chat owners can do this
2433
- » `/setfrules <rules>`*:* Arrange Federation rules
2434
- » `/fedadmins`*:* Show Federation admin
2435
- » `/fbanlist`*:* Displays all users who are victimized at the Federation at this time
2436
- » `/fedchats`*:* Get all the chats that are connected in the Federation
2437
- » `/chatfed `*:* See the Federation in the current chat\n""",
2438
- parse_mode=ParseMode.MARKDOWN,
2439
- )
2440
-
2441
-
2442
- async def fed_user_help(update: Update, context: ContextTypes.DEFAULT_TYPE):
2443
- await update.effective_message.reply_text(
2444
- """*🎩 Any user:*
2445
- » `/fbanstat`*:* Shows if you/or the user you are replying to or their username is fbanned somewhere or not
2446
- » `/fednotif <on/off>`*:* Federation settings not in PM when there are users who are fbaned/unfbanned
2447
- » `/frules`*:* See Federation regulations\n""",
2448
- parse_mode=ParseMode.MARKDOWN,
2449
- )
2450
-
2451
-
2452
- # <=================================================== HELP ====================================================>
2453
-
2454
-
2455
- __mod_name__ = "FEDS"
2456
-
2457
- __help__ = """
2458
- ➠ *Everything is fun, until a spammer starts entering your group, and you have to block it. Then you need to start banning more, and more, and it hurts*.
2459
- *But then you have many groups, and you don't want this spammer to be in one of your groups - how can you deal? Do you have to manually block it, in all your groups*?\n
2460
- *No longer!* *With Federation, you can make a ban in one chat overlap with all other chats*.\n
2461
- *You can even designate federation admins, so your trusted admin can ban all the spammers from chats you want to protect*.\n
2462
-
2463
- ➠ *Commands:*
2464
- ➠ Feds are now divided into 3 sections for your ease.
2465
-
2466
- » /fedownerhelp: Provides help for fed creation and owner only commands.
2467
-
2468
- » /fedadminhelp: Provides help for fed administration commands.
2469
-
2470
- » /feduserhelp: Provides help for commands anyone can use.
2471
-
2472
- """
2473
-
2474
- # <================================================ HANDLER =======================================================>
2475
- function(CommandHandler("newfed", new_fed, block=False))
2476
- function(CommandHandler("delfed", del_fed, block=False))
2477
- function(CommandHandler("renamefed", rename_fed, block=False))
2478
- function(CommandHandler("joinfed", join_fed, block=False))
2479
- function(CommandHandler("leavefed", leave_fed, block=False))
2480
- function(CommandHandler("fpromote", user_join_fed, block=False))
2481
- function(CommandHandler("fdemote", user_demote_fed, block=False))
2482
- function(CommandHandler("fedinfo", fed_info, block=False))
2483
- function(DisableAbleCommandHandler("fban", fed_ban, block=False))
2484
- function(CommandHandler("unfban", unfban, block=False))
2485
- function(CommandHandler("fbroadcast", fed_broadcast, block=False))
2486
- function(CommandHandler("setfrules", set_frules, block=False))
2487
- function(CommandHandler("frules", get_frules, block=False))
2488
- function(CommandHandler("chatfed", fed_chat, block=False))
2489
- function(CommandHandler("fedadmins", fed_admin, block=False))
2490
- function(CommandHandler("fbanlist", fed_ban_list, block=False))
2491
- function(CommandHandler("fednotif", fed_notif, block=False))
2492
- function(CommandHandler("fedchats", fed_chats, block=False))
2493
- function(CommandHandler("importfbans", fed_import_bans, block=False))
2494
- function(DisableAbleCommandHandler(["fedstat", "fbanstat"], fed_stat_user, block=False))
2495
- function(CommandHandler("setfedlog", set_fed_log, block=False))
2496
- function(CommandHandler("unsetfedlog", unset_fed_log, block=False))
2497
- function(CommandHandler("subfed", subs_feds, block=False))
2498
- function(CommandHandler("unsubfed", unsubs_feds, block=False))
2499
- function(CommandHandler("fedsubs", get_myfedsubs, block=False))
2500
- function(CommandHandler("myfeds", get_myfeds_list, block=False))
2501
- function(CallbackQueryHandler(del_fed_button, pattern=r"rmfed_", block=False))
2502
- function(CommandHandler("fedownerhelp", fed_owner_help, block=False))
2503
- function(CommandHandler("fedadminhelp", fed_admin_help, block=False))
2504
- function(CommandHandler("feduserhelp", fed_user_help, block=False))
2505
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/flood.py DELETED
@@ -1,457 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import html
3
- import re
4
-
5
- from telegram import ChatPermissions, Update
6
- from telegram.error import BadRequest
7
- from telegram.ext import (
8
- CallbackQueryHandler,
9
- CommandHandler,
10
- ContextTypes,
11
- MessageHandler,
12
- filters,
13
- )
14
- from telegram.helpers import mention_html
15
-
16
- from Database.sql import antiflood_sql as sql
17
- from Database.sql.approve_sql import is_approved
18
- from Mikobot import dispatcher, function
19
- from Mikobot.plugins.connection import connected
20
- from Mikobot.plugins.helper_funcs.alternate import send_message
21
- from Mikobot.plugins.helper_funcs.chat_status import check_admin, is_user_admin
22
- from Mikobot.plugins.helper_funcs.string_handling import extract_time
23
- from Mikobot.plugins.log_channel import loggable
24
-
25
- # <=======================================================================================================>
26
-
27
- FLOOD_GROUP = 3
28
-
29
-
30
- # <================================================ FUNCTION =======================================================>
31
- @loggable
32
- async def check_flood(update: Update, context: ContextTypes.DEFAULT_TYPE):
33
- user = update.effective_user
34
- chat = update.effective_chat
35
- msg = update.effective_message
36
- if not user:
37
- return ""
38
-
39
- if await is_user_admin(chat, user.id):
40
- sql.update_flood(chat.id, None)
41
- return ""
42
-
43
- if is_approved(chat.id, user.id):
44
- sql.update_flood(chat.id, None)
45
- return
46
-
47
- should_ban = sql.update_flood(chat.id, user.id)
48
- if not should_ban:
49
- return ""
50
-
51
- try:
52
- getmode, getvalue = sql.get_flood_setting(chat.id)
53
- if getmode == 1:
54
- await chat.ban_member(user.id)
55
- execstrings = "BANNED"
56
- tag = "BANNED"
57
- elif getmode == 2:
58
- await chat.ban_member(user.id)
59
- await chat.unban_member(user.id)
60
- execstrings = "KICKED"
61
- tag = "KICKED"
62
- elif getmode == 3:
63
- await context.bot.restrict_chat_member(
64
- chat.id,
65
- user.id,
66
- permissions=ChatPermissions(can_send_messages=False),
67
- )
68
- execstrings = "MUTED"
69
- tag = "MUTED"
70
- elif getmode == 4:
71
- bantime = await extract_time(msg, getvalue)
72
- await chat.ban_member(user.id, until_date=bantime)
73
- execstrings = "BANNED for {}".format(getvalue)
74
- tag = "TBAN"
75
- elif getmode == 5:
76
- mutetime = await extract_time(msg, getvalue)
77
- await context.bot.restrict_chat_member(
78
- chat.id,
79
- user.id,
80
- until_date=mutetime,
81
- permissions=ChatPermissions(can_send_messages=False),
82
- )
83
- execstrings = "MUTED for {}".format(getvalue)
84
- tag = "TMUTE"
85
- await send_message(
86
- update.effective_message,
87
- "Beep boop! Boop beep!\n{}!".format(execstrings),
88
- )
89
-
90
- return (
91
- "<b>{}:</b>"
92
- "\n#{}"
93
- "\n<b>user:</b> {}"
94
- "\nFlooded the group.".format(
95
- tag,
96
- html.escape(chat.title),
97
- mention_html(user.id, html.escape(user.first_name)),
98
- )
99
- )
100
-
101
- except BadRequest:
102
- await msg.reply_text(
103
- "I can't restrict people here, give me permissions first! Until then, I'll disable anti-flood.",
104
- )
105
- sql.set_flood(chat.id, 0)
106
- return (
107
- "<b>{}:</b>"
108
- "\n#INFO"
109
- "\nDon't have enough permission to restrict users so automatically disabled anti-flood.".format(
110
- chat.title,
111
- )
112
- )
113
-
114
-
115
- @check_admin(permission="can_restrict_members", is_both=True, no_reply=True)
116
- async def flood_button(update: Update, context: ContextTypes.DEFAULT_TYPE):
117
- bot = context.bot
118
- query = update.callback_query
119
- user = update.effective_user
120
- match = re.match(r"unmute_flooder\((.+?)\)", query.data)
121
- if match:
122
- user_id = match.group(1)
123
- chat = update.effective_chat.id
124
- try:
125
- await bot.restrict_chat_member(
126
- chat,
127
- int(user_id),
128
- permissions=ChatPermissions(
129
- can_send_messages=True,
130
- can_send_media_messages=True,
131
- can_send_other_messages=True,
132
- can_add_web_page_previews=True,
133
- ),
134
- )
135
- await update.effective_message.edit_text(
136
- f"Unmuted by {mention_html(user.id, html.escape(user.first_name))}.",
137
- parse_mode="HTML",
138
- )
139
- except:
140
- pass
141
-
142
-
143
- @loggable
144
- @check_admin(is_user=True)
145
- async def set_flood(update: Update, context: ContextTypes.DEFAULT_TYPE):
146
- chat = update.effective_chat
147
- user = update.effective_user
148
- message = update.effective_message
149
- args = context.args
150
-
151
- conn = await connected(context.bot, update, chat, user.id, need_admin=True)
152
- if conn:
153
- chat_id = conn
154
- chat_obj = await dispatcher.bot.getChat(conn)
155
- chat_name = chat_obj.title
156
- else:
157
- if update.effective_message.chat.type == "private":
158
- await send_message(
159
- update.effective_message,
160
- "This command is meant to use in a group, not in PM.",
161
- )
162
- return ""
163
- chat_id = update.effective_chat.id
164
- chat_name = update.effective_message.chat.title
165
-
166
- if len(args) >= 1:
167
- val = args[0].lower()
168
- if val in ["off", "no", "0"]:
169
- sql.set_flood(chat_id, 0)
170
- if conn:
171
- text = await message.reply_text(
172
- "Antiflood has been disabled in {}.".format(chat_name),
173
- )
174
- else:
175
- text = await message.reply_text("Antiflood has been disabled.")
176
-
177
- elif val.isdigit():
178
- amount = int(val)
179
- if amount <= 0:
180
- sql.set_flood(chat_id, 0)
181
- if conn:
182
- text = await message.reply_text(
183
- "Antiflood has been disabled in {}.".format(chat_name),
184
- )
185
- else:
186
- text = await message.reply_text("Antiflood has been disabled.")
187
- return (
188
- "<b>{}:</b>"
189
- "\n#SETFLOOD"
190
- "\n<b>Admin:</b> {}"
191
- "\nDisable Antiflood.".format(
192
- html.escape(chat_name),
193
- mention_html(user.id, html.escape(user.first_name)),
194
- )
195
- )
196
-
197
- elif amount <= 3:
198
- await send_message(
199
- update.effective_message,
200
- "Antiflood must be either 0 (disabled) or a number greater than 3!",
201
- )
202
- return ""
203
-
204
- else:
205
- sql.set_flood(chat_id, amount)
206
- if conn:
207
- text = await message.reply_text(
208
- "Antiflood limit has been set to {} in chat: {}".format(
209
- amount,
210
- chat_name,
211
- ),
212
- )
213
- else:
214
- text = await message.reply_text(
215
- "Successfully updated antiflood limit to {}!".format(amount),
216
- )
217
- return (
218
- "<b>{}:</b>"
219
- "\n#SETFLOOD"
220
- "\n<b>Admin:</b> {}"
221
- "\nSet Antiflood to <code>{}</code>.".format(
222
- html.escape(chat_name),
223
- mention_html(user.id, html.escape(user.first_name)),
224
- amount,
225
- )
226
- )
227
-
228
- else:
229
- await message.reply_text(
230
- "Invalid argument, please use a number, 'off', or 'no'."
231
- )
232
- else:
233
- await message.reply_text(
234
- (
235
- "Use `/setflood number` to enable antiflood.\n"
236
- "Or use `/setflood off` to disable antiflood."
237
- ),
238
- parse_mode="markdown",
239
- )
240
- return ""
241
-
242
-
243
- async def flood(update: Update, context: ContextTypes.DEFAULT_TYPE):
244
- chat = update.effective_chat
245
- user = update.effective_user
246
- msg = update.effective_message
247
-
248
- conn = await connected(context.bot, update, chat, user.id, need_admin=False)
249
- if conn:
250
- chat_id = conn
251
- chat_obj = await dispatcher.bot.getChat(conn)
252
- chat_name = chat_obj.title
253
- else:
254
- if update.effective_message.chat.type == "private":
255
- await send_message(
256
- update.effective_message,
257
- "This command is meant to use in a group, not in PM.",
258
- )
259
- return
260
- chat_id = update.effective_chat.id
261
- chat_name = update.effective_message.chat.title
262
-
263
- limit = sql.get_flood_limit(chat_id)
264
- if limit == 0:
265
- if conn:
266
- text = await msg.reply_text(
267
- "I'm not enforcing any flood control in {}!".format(chat_name),
268
- )
269
- else:
270
- text = await msg.reply_text("I'm not enforcing any flood control here!")
271
- else:
272
- if conn:
273
- text = await msg.reply_text(
274
- "I'm currently restricting members after {} consecutive messages in {}.".format(
275
- limit,
276
- chat_name,
277
- ),
278
- )
279
- else:
280
- text = await msg.reply_text(
281
- "I'm currently restricting members after {} consecutive messages.".format(
282
- limit,
283
- ),
284
- )
285
-
286
-
287
- @check_admin(is_user=True)
288
- async def set_flood_mode(update: Update, context: ContextTypes.DEFAULT_TYPE):
289
- chat = update.effective_chat
290
- user = update.effective_user
291
- msg = update.effective_message
292
- args = context.args
293
-
294
- conn = await connected(context.bot, update, chat, user.id, need_admin=True)
295
- if conn:
296
- chat = await dispatcher.bot.getChat(conn)
297
- chat_id = conn
298
- chat_obj = await dispatcher.bot.getChat(conn)
299
- chat_name = chat_obj.title
300
- else:
301
- if update.effective_message.chat.type == "private":
302
- await send_message(
303
- update.effective_message,
304
- "This command is meant to use in a group, not in PM.",
305
- )
306
- return ""
307
- chat = update.effective_chat
308
- chat_id = update.effective_chat.id
309
- chat_name = update.effective_message.chat.title
310
-
311
- if args:
312
- if args[0].lower() == "ban":
313
- settypeflood = "ban"
314
- sql.set_flood_strength(chat_id, 1, "0")
315
- elif args[0].lower() == "kick":
316
- settypeflood = "kick"
317
- sql.set_flood_strength(chat_id, 2, "0")
318
- elif args[0].lower() == "mute":
319
- settypeflood = "mute"
320
- sql.set_flood_strength(chat_id, 3, "0")
321
- elif args[0].lower() == "tban":
322
- if len(args) == 1:
323
- teks = """It looks like you tried to set time value for antiflood but you didn't specified time; Try, `/setfloodmode tban <timevalue>`.
324
- Examples of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
325
- await send_message(
326
- update.effective_message, teks, parse_mode="markdown"
327
- )
328
- return
329
- settypeflood = "tban for {}".format(args[1])
330
- sql.set_flood_strength(chat_id, 4, str(args[1]))
331
- elif args[0].lower() == "tmute":
332
- if len(args) == 1:
333
- teks = """It looks like you tried to set time value for antiflood but you didn't specified time; Try, `/setfloodmode tmute <timevalue>`.
334
- Examples of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
335
- await send_message(
336
- update.effective_message, teks, parse_mode="markdown"
337
- )
338
- return
339
- settypeflood = "tmute for {}".format(args[1])
340
- sql.set_flood_strength(chat_id, 5, str(args[1]))
341
- else:
342
- await send_message(
343
- update.effective_message,
344
- "I only understand ban/kick/mute/tban/tmute!",
345
- )
346
- return
347
- if conn:
348
- text = await msg.reply_text(
349
- "Exceeding consecutive flood limit will result in {} in {}!".format(
350
- settypeflood,
351
- chat_name,
352
- ),
353
- )
354
- else:
355
- text = await msg.reply_text(
356
- "Exceeding consecutive flood limit will result in {}!".format(
357
- settypeflood,
358
- ),
359
- )
360
- return (
361
- "<b>{}:</b>\n"
362
- "<b>Admin:</b> {}\n"
363
- "Has changed antiflood mode. User will {}.".format(
364
- settypeflood,
365
- html.escape(chat.title),
366
- mention_html(user.id, html.escape(user.first_name)),
367
- )
368
- )
369
- else:
370
- getmode, getvalue = sql.get_flood_setting(chat.id)
371
- if getmode == 1:
372
- settypeflood = "ban"
373
- elif getmode == 2:
374
- settypeflood = "kick"
375
- elif getmode == 3:
376
- settypeflood = "mute"
377
- elif getmode == 4:
378
- settypeflood = "tban for {}".format(getvalue)
379
- elif getmode == 5:
380
- settypeflood = "tmute for {}".format(getvalue)
381
- if conn:
382
- text = await msg.reply_text(
383
- "Sending more messages than flood limit will result in {} in {}.".format(
384
- settypeflood,
385
- chat_name,
386
- ),
387
- )
388
- else:
389
- text = await msg.reply_text(
390
- "Sending more messages than flood limit will result in {}.".format(
391
- settypeflood,
392
- ),
393
- )
394
- return ""
395
-
396
-
397
- def __migrate__(old_chat_id, new_chat_id):
398
- sql.migrate_chat(old_chat_id, new_chat_id)
399
-
400
-
401
- def __chat_settings__(chat_id, user_id):
402
- limit = sql.get_flood_limit(chat_id)
403
- if limit == 0:
404
- return "Not enforcing flood control."
405
- else:
406
- return "Antiflood has been set to `{}`.".format(limit)
407
-
408
-
409
- # <=================================================== HELP ====================================================>
410
-
411
-
412
- __help__ = """
413
- ➠ *Antiflood allows you to take action on users that send more than x messages in a row. Exceeding the set flood will result in restricting that user.*
414
-
415
- ➠ *Admin Only*
416
-
417
- » /flood: Get the current antiflood settings.
418
-
419
- » /setflood <number/off/no>: Set the number of messages after which to take action on a user. Set to '0', 'off', or 'no' to disable.
420
-
421
- » /setfloodmode <action type>: Choose which action to take on a user who has been flooding. Options: ban/kick/mute/tban/tmute.
422
- """
423
-
424
- __mod_name__ = "ANTI-FLOOD"
425
-
426
- # <================================================ HANDLER =======================================================>
427
- FLOOD_BAN_HANDLER = MessageHandler(
428
- filters.ALL & ~filters.StatusUpdate.ALL & filters.ChatType.GROUPS,
429
- check_flood,
430
- block=False,
431
- )
432
- SET_FLOOD_HANDLER = CommandHandler(
433
- "setflood", set_flood, filters=filters.ChatType.GROUPS, block=False
434
- )
435
- SET_FLOOD_MODE_HANDLER = CommandHandler(
436
- "setfloodmode", set_flood_mode, block=False
437
- ) # , filters=filters.ChatType.GROUPS)
438
- FLOOD_QUERY_HANDLER = CallbackQueryHandler(
439
- flood_button, pattern=r"unmute_flooder", block=False
440
- )
441
- FLOOD_HANDLER = CommandHandler(
442
- "flood", flood, filters=filters.ChatType.GROUPS, block=False
443
- )
444
-
445
- function(FLOOD_BAN_HANDLER, FLOOD_GROUP)
446
- function(FLOOD_QUERY_HANDLER)
447
- function(SET_FLOOD_HANDLER)
448
- function(SET_FLOOD_MODE_HANDLER)
449
- function(FLOOD_HANDLER)
450
-
451
- __handlers__ = [
452
- (FLOOD_BAN_HANDLER, FLOOD_GROUP),
453
- SET_FLOOD_HANDLER,
454
- FLOOD_HANDLER,
455
- SET_FLOOD_MODE_HANDLER,
456
- ]
457
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/fsub.py DELETED
@@ -1,189 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from telethon import Button, events, types
3
- from telethon.errors import ChatAdminRequiredError, UserNotParticipantError
4
- from telethon.tl.functions.channels import GetParticipantRequest
5
-
6
- from Database.mongodb import fsub_db as db
7
- from Mikobot import BOT_ID
8
- from Mikobot import DRAGONS as DEVS
9
- from Mikobot import OWNER_ID, tbot
10
- from Mikobot.events import register
11
-
12
- # <=======================================================================================================>
13
-
14
- # Constants
15
- F_SUBSCRIBE_COMMAND = "/(fsub|Fsub|forcesubscribe|Forcesub|forcesub|Forcesubscribe)"
16
- FORCESUBSCRIBE_ON = ["on", "yes", "y"]
17
- FORCESUBSCRIBE_OFF = ["off", "no", "n"]
18
-
19
-
20
- # <================================================ FUNCTION =======================================================>
21
- def fsk_ck(**args):
22
- def decorator(func):
23
- tbot.add_event_handler(func, events.CallbackQuery(**args))
24
- return func
25
-
26
- return decorator
27
-
28
-
29
- # Helper functions
30
- async def is_admin(chat_id, user_id):
31
- try:
32
- p = await tbot(GetParticipantRequest(chat_id, user_id))
33
- except UserNotParticipantError:
34
- return False
35
- return isinstance(
36
- p.participant, (types.ChannelParticipantAdmin, types.ChannelParticipantCreator)
37
- )
38
-
39
-
40
- async def participant_check(channel, user_id):
41
- try:
42
- await tbot(GetParticipantRequest(channel, int(user_id)))
43
- return True
44
- except UserNotParticipantError:
45
- return False
46
- except Exception:
47
- return False
48
-
49
-
50
- # Main command function
51
- @register(pattern=f"^{F_SUBSCRIBE_COMMAND} ?(.*)")
52
- async def force_subscribe(event):
53
- """Handle the force subscribe command."""
54
- if event.is_private:
55
- return
56
-
57
- if event.is_group:
58
- perm = await event.client.get_permissions(event.chat_id, event.sender_id)
59
- if not perm.is_admin:
60
- return await event.reply("You need to be an admin to do this.")
61
-
62
- if not perm.is_creator:
63
- return await event.reply(
64
- "❗ Group creator required\nYou have to be the group creator to do that."
65
- )
66
-
67
- try:
68
- channel = event.text.split(None, 1)[1]
69
- except IndexError:
70
- channel = None
71
-
72
- if not channel:
73
- chat_db = db.fs_settings(event.chat_id)
74
- if not chat_db:
75
- await event.reply("Force subscribe is disabled in this chat.")
76
- else:
77
- await event.reply(
78
- f"Force subscribe is currently enabled. Users are forced to join @{chat_db.channel} to speak here."
79
- )
80
- elif channel.lower() in FORCESUBSCRIBE_ON:
81
- await event.reply("Please specify the channel username.")
82
- elif channel.lower() in FORCESUBSCRIBE_OFF:
83
- await event.reply("**Force subscribe is disabled successfully.**")
84
- db.disapprove(event.chat_id)
85
- else:
86
- try:
87
- channel_entity = await event.client.get_entity(channel)
88
- except:
89
- return await event.reply("Invalid channel username provided.")
90
-
91
- channel = channel_entity.username
92
- try:
93
- if not channel_entity.broadcast:
94
- return await event.reply("That's not a valid channel.")
95
- except:
96
- return await event.reply("That's not a valid channel.")
97
-
98
- if not await participant_check(channel, BOT_ID):
99
- return await event.reply(
100
- f"**Not an admin in the channel**\nI am not an admin in the [channel](https://t.me/{channel}). Add me as an admin to enable force subscribe.",
101
- link_preview=False,
102
- )
103
-
104
- db.add_channel(event.chat_id, str(channel))
105
- await event.reply(f"Force subscribe is enabled to @{channel}.")
106
-
107
-
108
- # Event handler for new messages
109
- @tbot.on(events.NewMessage())
110
- async def force_subscribe_new_message(e):
111
- """Handle new messages for force subscribe."""
112
- if not db.fs_settings(e.chat_id):
113
- return
114
-
115
- if e.is_private or not e.from_id or e.sender_id in DEVS or e.sender_id == OWNER_ID:
116
- return
117
-
118
- if not e.chat.admin_rights or not e.chat.admin_rights.ban_users:
119
- return
120
-
121
- try:
122
- channel = db.fs_settings(e.chat_id)["channel"]
123
- check = await participant_check(channel, e.sender_id)
124
- except (ChatAdminRequiredError, UserNotParticipantError):
125
- return
126
-
127
- if not check:
128
- buttons = [
129
- Button.url("Join Channel", f"t.me/{channel}"),
130
- Button.inline("Unmute Me", data=f"fs_{e.sender_id}"),
131
- ]
132
-
133
- txt = f'<b><a href="tg://user?id={e.sender_id}">{e.sender.first_name}</a></b>, you have <b>not subscribed</b> to our <b><a href="t.me/{channel}">channel</a></b> yet. Please <b><a href="t.me/{channel}">join</a></b> and press the button below to unmute yourself.'
134
- await e.reply(txt, buttons=buttons, parse_mode="html", link_preview=False)
135
- await e.client.edit_permissions(e.chat_id, e.sender_id, send_messages=False)
136
-
137
-
138
- # Inline query handler
139
- @fsk_ck(pattern=r"fs(\_(.*))")
140
- async def unmute_force_subscribe(event):
141
- """Handle inline query for unmuting force subscribe."""
142
- user_id = int(((event.pattern_match.group(1)).decode()).split("_", 1)[1])
143
-
144
- if not event.sender_id == user_id:
145
- return await event.answer("This is not meant for you.", alert=True)
146
-
147
- channel = db.fs_settings(event.chat_id)["channel"]
148
- try:
149
- check = await participant_check(channel, user_id)
150
- except ChatAdminRequiredError:
151
- check = False
152
- return
153
-
154
- if not check:
155
- return await event.answer(
156
- "You have to join the channel first, to get unmuted!", alert=True
157
- )
158
-
159
- try:
160
- await event.client.edit_permissions(event.chat_id, user_id, send_messages=True)
161
- except ChatAdminRequiredError:
162
- pass
163
-
164
- await event.delete()
165
-
166
-
167
- # <=================================================== HELP ====================================================>
168
-
169
-
170
- __help__ = """
171
- ➠ *Dazai has the capability to hush members who haven't yet subscribed to your channel until they decide to hit that subscribe button.*
172
- ➠ *When activated, I'll silence those who are not subscribed and provide them with an option to unmute. Once they click the button, I'll lift the mute.*
173
-
174
- ➠ Configuration Process
175
- ➠ Exclusively for Creators
176
- ➠ Grant me admin privileges in your group
177
- ➠ Designate me as an admin in your channel
178
-
179
- ➠ *Commands*
180
- » /fsub channel\_username - to initiate and customize settings for the channel.
181
-
182
- ➠ *Kick things off with...*
183
- » /fsub - to review the current settings.
184
- » /fsub off - to deactivate the force subscription feature.
185
-
186
- ➠ *If you disable fsub, you'll need to set it up again for it to take effect. Utilize /fsub channel\_username.*
187
- """
188
- __mod_name__ = "F-SUB"
189
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/fun.py DELETED
@@ -1,257 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import random
3
-
4
- from pyjokes import get_joke
5
- from telegram import Update
6
- from telegram.constants import ParseMode
7
- from telegram.ext import ContextTypes
8
-
9
- import Mikobot.utils.fun_strings as fun_strings
10
- from Mikobot import function
11
- from Mikobot.events import register
12
- from Mikobot.plugins.disable import DisableAbleCommandHandler
13
- from Mikobot.state import state
14
-
15
- # <=======================================================================================================>
16
-
17
-
18
- # <================================================ FUNCTION =======================================================>
19
- async def make_request(url: str) -> str:
20
- response = await state.get(url)
21
- response.raise_for_status()
22
- return response.json()["question"]
23
-
24
-
25
- async def truth(update: Update, context: ContextTypes.DEFAULT_TYPE):
26
- truth_question = await make_request("https://api.truthordarebot.xyz/v1/truth")
27
- await update.effective_message.reply_text(truth_question)
28
-
29
-
30
- async def dare(update: Update, context: ContextTypes.DEFAULT_TYPE):
31
- dare_question = await make_request("https://api.truthordarebot.xyz/v1/dare")
32
- await update.effective_message.reply_text(dare_question)
33
-
34
-
35
- @register(pattern="^/joke ?(.*)")
36
- async def joke(event):
37
- await event.reply(get_joke())
38
-
39
-
40
- async def roll(update: Update, context: ContextTypes.DEFAULT_TYPE):
41
- await update.message.reply_text(random.choice(range(1, 7)))
42
-
43
-
44
- async def flirt(update: Update, context: ContextTypes.DEFAULT_TYPE):
45
- args = context.args
46
- await update.effective_message.reply_text(random.choice(fun_strings.FLIRT))
47
-
48
-
49
- async def toss(update: Update, context: ContextTypes.DEFAULT_TYPE):
50
- await update.message.reply_text(random.choice(fun_strings.TOSS))
51
-
52
-
53
- async def shrug(update: Update, context: ContextTypes.DEFAULT_TYPE):
54
- msg = update.effective_message
55
- reply_text = (
56
- msg.reply_to_message.reply_text if msg.reply_to_message else msg.reply_text
57
- )
58
- await reply_text(r"¯\_(ツ)_/¯")
59
-
60
-
61
- async def bluetext(update: Update, context: ContextTypes.DEFAULT_TYPE):
62
- msg = update.effective_message
63
- reply_text = (
64
- msg.reply_to_message.reply_text if msg.reply_to_message else msg.reply_text
65
- )
66
- await reply_text(
67
- "/BLUE /TEXT\n/MUST /CLICK\n/I /AM /A /STUPID /ANIMAL /THAT /IS /ATTRACTED /TO /COLORS"
68
- )
69
-
70
-
71
- async def rlg(update: Update, context: ContextTypes.DEFAULT_TYPE):
72
- eyes = random.choice(fun_strings.EYES)
73
- mouth = random.choice(fun_strings.MOUTHS)
74
- ears = random.choice(fun_strings.EARS)
75
-
76
- if len(eyes) == 2:
77
- repl = ears[0] + eyes[0] + mouth[0] + eyes[1] + ears[1]
78
- else:
79
- repl = ears[0] + eyes[0] + mouth[0] + eyes[0] + ears[1]
80
- await update.message.reply_text(repl)
81
-
82
-
83
- async def decide(update: Update, context: ContextTypes.DEFAULT_TYPE):
84
- reply_text = (
85
- update.effective_message.reply_to_message.reply_text
86
- if update.effective_message.reply_to_message
87
- else update.effective_message.reply_text
88
- )
89
- await reply_text(random.choice(fun_strings.DECIDE))
90
-
91
-
92
- normiefont = [
93
- "a",
94
- "b",
95
- "c",
96
- "d",
97
- "e",
98
- "f",
99
- "g",
100
- "h",
101
- "i",
102
- "j",
103
- "k",
104
- "l",
105
- "m",
106
- "n",
107
- "o",
108
- "p",
109
- "q",
110
- "r",
111
- "s",
112
- "t",
113
- "u",
114
- "v",
115
- "w",
116
- "x",
117
- "y",
118
- "z",
119
- ]
120
-
121
- weebyfont = [
122
- "卂",
123
- "乃",
124
- "匚",
125
- "刀",
126
- "乇",
127
- "下",
128
- "厶",
129
- "卄",
130
- "工",
131
- "丁",
132
- "长",
133
- "乚",
134
- "从",
135
- "𠘨",
136
- "口",
137
- "尸",
138
- "㔿",
139
- "尺",
140
- "丂",
141
- "丅",
142
- "凵",
143
- "リ",
144
- "山",
145
- "乂",
146
- "丫",
147
- "乙",
148
- ]
149
-
150
-
151
- async def webify(update: Update, context: ContextTypes.DEFAULT_TYPE):
152
- args = context.args
153
- message = update.effective_message
154
- string = ""
155
-
156
- if message.reply_to_message:
157
- string = message.reply_to_message.text.lower().replace(" ", " ")
158
-
159
- if args:
160
- string = " ".join(args).lower()
161
-
162
- if not string:
163
- await message.reply_text(
164
- "Usage is `/weebify <text>`", parse_mode=ParseMode.MARKDOWN
165
- )
166
- return
167
-
168
- for normiecharacter in string:
169
- if normiecharacter in normiefont:
170
- weebycharacter = weebyfont[normiefont.index(normiecharacter)]
171
- string = string.replace(normiecharacter, weebycharacter)
172
-
173
- if message.reply_to_message:
174
- await message.reply_to_message.reply_text(string)
175
- else:
176
- await message.reply_text(string)
177
-
178
-
179
- # <=================================================== HELP ====================================================>
180
-
181
-
182
- __help__ = """
183
- » /cosplay: sends cosplay images.
184
-
185
- » /decide: randomly answers yes/no/maybe.
186
-
187
- » /truth: sends a random truth string.
188
-
189
- » /dare: sends a random dare string.
190
-
191
- » /toss: tosses a coin.
192
-
193
- » /shrug: get shrug xd.
194
-
195
- » /bluetext: check yourself :V.
196
-
197
- �� /roll: roll a dice.
198
-
199
- » /rlg: join ears, nose, mouth and create an emo ;-;
200
-
201
- » /weebify <text>: returns a weebified text.
202
-
203
- » /flirt <text>: returns a flirt text.
204
-
205
- » /joke <text>: tells a random joke.
206
- """
207
-
208
- # <================================================ HANDLER =======================================================>
209
- ROLL_HANDLER = DisableAbleCommandHandler("roll", roll, block=False)
210
- TOSS_HANDLER = DisableAbleCommandHandler("toss", toss, block=False)
211
- SHRUG_HANDLER = DisableAbleCommandHandler("shrug", shrug, block=False)
212
- BLUETEXT_HANDLER = DisableAbleCommandHandler("bluetext", bluetext, block=False)
213
- RLG_HANDLER = DisableAbleCommandHandler("rlg", rlg, block=False)
214
- DECIDE_HANDLER = DisableAbleCommandHandler("decide", decide, block=False)
215
- WEEBIFY_HANDLER = DisableAbleCommandHandler("weebify", webify, block=False)
216
- FLIRT_HANDLER = DisableAbleCommandHandler("flirt", flirt, block=False)
217
- TRUTH_HANDLER = DisableAbleCommandHandler("truth", truth, block=False)
218
- DARE_HANDLER = DisableAbleCommandHandler("dare", dare, block=False)
219
-
220
- function(WEEBIFY_HANDLER)
221
- function(ROLL_HANDLER)
222
- function(TOSS_HANDLER)
223
- function(SHRUG_HANDLER)
224
- function(BLUETEXT_HANDLER)
225
- function(RLG_HANDLER)
226
- function(DECIDE_HANDLER)
227
- function(FLIRT_HANDLER)
228
- function(TRUTH_HANDLER)
229
- function(DARE_HANDLER)
230
-
231
- __mod_name__ = "FUN"
232
- __command_list__ = [
233
- "roll",
234
- "toss",
235
- "shrug",
236
- "bluetext",
237
- "rlg",
238
- "decide",
239
- "cosplay",
240
- "weebify",
241
- "flirt",
242
- "truth",
243
- "dare",
244
- ]
245
- __handlers__ = [
246
- ROLL_HANDLER,
247
- TOSS_HANDLER,
248
- SHRUG_HANDLER,
249
- BLUETEXT_HANDLER,
250
- RLG_HANDLER,
251
- DECIDE_HANDLER,
252
- WEEBIFY_HANDLER,
253
- FLIRT_HANDLER,
254
- TRUTH_HANDLER,
255
- DARE_HANDLER,
256
- ]
257
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/gban.py DELETED
@@ -1,544 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import html
3
- import time
4
- from datetime import datetime
5
- from io import BytesIO
6
-
7
- from telegram import ChatMemberAdministrator, Update
8
- from telegram.constants import ParseMode
9
- from telegram.error import BadRequest, Forbidden, TelegramError
10
- from telegram.ext import CommandHandler, ContextTypes, MessageHandler, filters
11
- from telegram.helpers import mention_html
12
-
13
- import Database.sql.global_bans_sql as sql
14
- from Database.sql.users_sql import get_user_com_chats
15
- from Mikobot import (
16
- DEV_USERS,
17
- DRAGONS,
18
- EVENT_LOGS,
19
- OWNER_ID,
20
- STRICT_GBAN,
21
- SUPPORT_CHAT,
22
- dispatcher,
23
- function,
24
- )
25
- from Mikobot.plugins.helper_funcs.chat_status import (
26
- check_admin,
27
- is_user_admin,
28
- support_plus,
29
- )
30
- from Mikobot.plugins.helper_funcs.extraction import extract_user, extract_user_and_text
31
- from Mikobot.plugins.helper_funcs.misc import send_to_list
32
-
33
- # <=======================================================================================================>
34
-
35
- GBAN_ENFORCE_GROUP = 6
36
-
37
- GBAN_ERRORS = {
38
- "User is an administrator of the chat",
39
- "Chat not found",
40
- "Not enough rights to restrict/unrestrict chat member",
41
- "User_not_participant",
42
- "Peer_id_invalid",
43
- "Group chat was deactivated",
44
- "Need to be inviter of a user to kick it from a basic group",
45
- "Chat_admin_required",
46
- "Only the creator of a basic group can kick group administrators",
47
- "Channel_private",
48
- "Not in the chat",
49
- "Can't remove chat owner",
50
- }
51
-
52
- UNGBAN_ERRORS = {
53
- "User is an administrator of the chat",
54
- "Chat not found",
55
- "Not enough rights to restrict/unrestrict chat member",
56
- "User_not_participant",
57
- "Method is available for supergroup and channel chats only",
58
- "Not in the chat",
59
- "Channel_private",
60
- "Chat_admin_required",
61
- "Peer_id_invalid",
62
- "User not found",
63
- }
64
-
65
-
66
- # <================================================ FUNCTION =======================================================>
67
- @support_plus
68
- async def gban(update: Update, context: ContextTypes.DEFAULT_TYPE):
69
- bot, args = context.bot, context.args
70
- message = update.effective_message
71
- user = update.effective_user
72
- chat = update.effective_chat
73
- log_message = ""
74
-
75
- user_id, reason = await extract_user_and_text(message, context, args)
76
-
77
- if not user_id:
78
- await message.reply_text(
79
- "You don't seem to be referring to a user or the ID specified is incorrect..",
80
- )
81
- return
82
-
83
- if int(user_id) in DEV_USERS:
84
- await message.reply_text(
85
- "That user is part of the Association\nI can't act against our own.",
86
- )
87
- return
88
-
89
- if int(user_id) in DRAGONS:
90
- await message.reply_text(
91
- "I spy, with my little eye... a disaster! Why are you guys turning on each other?",
92
- )
93
- return
94
-
95
- if user_id == bot.id:
96
- await message.reply_text("You uhh...want me to kick myself?")
97
- return
98
-
99
- if user_id in [777000, 1087968824]:
100
- await message.reply_text("Fool! You can't attack Telegram's native tech!")
101
- return
102
-
103
- try:
104
- user_chat = await bot.get_chat(user_id)
105
- except BadRequest as excp:
106
- if excp.message == "User not found":
107
- await message.reply_text("I can't seem to find this user.")
108
- return ""
109
- else:
110
- return
111
-
112
- if user_chat.type != "private":
113
- await message.reply_text("That's not a user!")
114
- return
115
-
116
- if sql.is_user_gbanned(user_id):
117
- if not reason:
118
- await message.reply_text(
119
- "This user is already gbanned; I'd change the reason, but you haven't given me one...",
120
- )
121
- return
122
-
123
- old_reason = sql.update_gban_reason(
124
- user_id,
125
- user_chat.username or user_chat.first_name,
126
- reason,
127
- )
128
- if old_reason:
129
- await message.reply_text(
130
- "This user is already gbanned, for the following reason:\n"
131
- "<code>{}</code>\n"
132
- "I've gone and updated it with your new reason!".format(
133
- html.escape(old_reason),
134
- ),
135
- parse_mode=ParseMode.HTML,
136
- )
137
-
138
- else:
139
- await message.reply_text(
140
- "This user is already gbanned, but had no reason set; I've gone and updated it!",
141
- )
142
-
143
- return
144
-
145
- await message.reply_text("On it!")
146
-
147
- start_time = time.time()
148
- datetime_fmt = "%Y-%m-%dT%H:%M"
149
- current_time = datetime.utcnow().strftime(datetime_fmt)
150
-
151
- if chat.type != "private":
152
- chat_origin = "<b>{} ({})</b>\n".format(html.escape(chat.title), chat.id)
153
- else:
154
- chat_origin = "<b>{}</b>\n".format(chat.id)
155
-
156
- log_message = (
157
- f"#GBANNED\n"
158
- f"<b>Originated from:</b> <code>{chat_origin}</code>\n"
159
- f"<b>Admin:</b> {mention_html(user.id, user.first_name)}\n"
160
- f"<b>Banned User:</b> {mention_html(user_chat.id, user_chat.first_name)}\n"
161
- f"<b>Banned User ID:</b> <code>{user_chat.id}</code>\n"
162
- f"<b>Event Stamp:</b> <code>{current_time}</code>"
163
- )
164
-
165
- if reason:
166
- if chat.type == chat.SUPERGROUP and chat.username:
167
- log_message += f'\n<b>Reason:</b> <a href="https://telegram.me/{chat.username}/{message.message_id}">{reason}</a>'
168
- else:
169
- log_message += f"\n<b>Reason:</b> <code>{reason}</code>"
170
-
171
- if EVENT_LOGS:
172
- try:
173
- log = await bot.send_message(
174
- EVENT_LOGS, log_message, parse_mode=ParseMode.HTML
175
- )
176
- except BadRequest as excp:
177
- log = await bot.send_message(
178
- EVENT_LOGS,
179
- log_message
180
- + "\n\nFormatting has been disabled due to an unexpected error.",
181
- )
182
-
183
- else:
184
- send_to_list(bot, DRAGONS, log_message, html=True)
185
-
186
- sql.gban_user(user_id, user_chat.username or user_chat.first_name, reason)
187
-
188
- chats = get_user_com_chats(user_id)
189
- gbanned_chats = 0
190
-
191
- for chat in chats:
192
- chat_id = int(chat)
193
-
194
- # Check if this group has disabled gbans
195
- if not sql.does_chat_gban(chat_id):
196
- continue
197
-
198
- try:
199
- await bot.ban_chat_member(chat_id, user_id)
200
- gbanned_chats += 1
201
-
202
- except BadRequest as excp:
203
- if excp.message in GBAN_ERRORS:
204
- pass
205
- else:
206
- await message.reply_text(f"Could not gban due to: {excp.message}")
207
- if EVENT_LOGS:
208
- await bot.send_message(
209
- EVENT_LOGS,
210
- f"Could not gban due to {excp.message}",
211
- parse_mode=ParseMode.HTML,
212
- )
213
- else:
214
- send_to_list(
215
- bot,
216
- DRAGONS,
217
- f"Could not gban due to: {excp.message}",
218
- )
219
- sql.ungban_user(user_id)
220
- return
221
- except TelegramError:
222
- pass
223
-
224
- if EVENT_LOGS:
225
- await log.edit_text(
226
- log_message + f"\n<b>Chats affected:</b> <code>{gbanned_chats}</code>",
227
- parse_mode=ParseMode.HTML,
228
- )
229
- else:
230
- send_to_list(
231
- bot,
232
- DRAGONS,
233
- f"Gban complete! (User banned in <code>{gbanned_chats}</code> chats)",
234
- html=True,
235
- )
236
-
237
- end_time = time.time()
238
- gban_time = round((end_time - start_time), 2)
239
-
240
- if gban_time > 60:
241
- gban_time = round((gban_time / 60), 2)
242
- await message.reply_text("Done! Gbanned.", parse_mode=ParseMode.HTML)
243
- else:
244
- await message.reply_text("Done! Gbanned.", parse_mode=ParseMode.HTML)
245
-
246
- try:
247
- await bot.send_message(
248
- user_id,
249
- "#EVENT"
250
- "You have been marked as Malicious and as such have been banned from any future groups we manage."
251
- f"\n<b>Reason:</b> <code>{html.escape(user.reason)}</code>"
252
- f"</b>Appeal Chat:</b> @{SUPPORT_CHAT}",
253
- parse_mode=ParseMode.HTML,
254
- )
255
- except:
256
- pass # bot probably blocked by user
257
-
258
-
259
- @support_plus
260
- async def ungban(update: Update, context: ContextTypes.DEFAULT_TYPE):
261
- bot, args = context.bot, context.args
262
- message = update.effective_message
263
- user = update.effective_user
264
- chat = update.effective_chat
265
- log_message = ""
266
-
267
- user_id = await extract_user(message, context, args)
268
-
269
- if not user_id:
270
- await message.reply_text(
271
- "You don't seem to be referring to a user or the ID specified is incorrect..",
272
- )
273
- return
274
-
275
- user_chat = await bot.get_chat(user_id)
276
- if user_chat.type != "private":
277
- await message.reply_text("That's not a user!")
278
- return
279
-
280
- if not sql.is_user_gbanned(user_id):
281
- await message.reply_text("This user is not gbanned!")
282
- return
283
-
284
- await message.reply_text(
285
- f"I'll give {user_chat.first_name} a second chance, globally."
286
- )
287
-
288
- start_time = time.time()
289
- datetime_fmt = "%Y-%m-%dT%H:%M"
290
- current_time = datetime.utcnow().strftime(datetime_fmt)
291
-
292
- if chat.type != "private":
293
- chat_origin = f"<b>{html.escape(chat.title)} ({chat.id})</b>\n"
294
- else:
295
- chat_origin = f"<b>{chat.id}</b>\n"
296
-
297
- log_message = (
298
- f"#UNGBANNED\n"
299
- f"<b>Originated from:</b> <code>{chat_origin}</code>\n"
300
- f"<b>Admin:</b> {mention_html(user.id, user.first_name)}\n"
301
- f"<b>Unbanned User:</b> {mention_html(user_chat.id, user_chat.first_name)}\n"
302
- f"<b>Unbanned User ID:</b> <code>{user_chat.id}</code>\n"
303
- f"<b>Event Stamp:</b> <code>{current_time}</code>"
304
- )
305
-
306
- if EVENT_LOGS:
307
- try:
308
- log = await bot.send_message(
309
- EVENT_LOGS, log_message, parse_mode=ParseMode.HTML
310
- )
311
- except BadRequest as excp:
312
- log = await bot.send_message(
313
- EVENT_LOGS,
314
- log_message
315
- + "\n\nFormatting has been disabled due to an unexpected error.",
316
- )
317
- else:
318
- send_to_list(bot, DRAGONS, log_message, html=True)
319
-
320
- chats = get_user_com_chats(user_id)
321
- ungbanned_chats = 0
322
-
323
- for chat in chats:
324
- chat_id = int(chat)
325
-
326
- # Check if this group has disabled gbans
327
- if not sql.does_chat_gban(chat_id):
328
- continue
329
-
330
- try:
331
- member = await bot.get_chat_member(chat_id, user_id)
332
- if member.status == "kicked":
333
- await bot.unban_chat_member(chat_id, user_id)
334
- ungbanned_chats += 1
335
-
336
- except BadRequest as excp:
337
- if excp.message in UNGBAN_ERRORS:
338
- pass
339
- else:
340
- await message.reply_text(f"Could not un-gban due to: {excp.message}")
341
- if EVENT_LOGS:
342
- await bot.send_message(
343
- EVENT_LOGS,
344
- f"Could not un-gban due to: {excp.message}",
345
- parse_mode=ParseMode.HTML,
346
- )
347
- else:
348
- await bot.send_message(
349
- OWNER_ID,
350
- f"Could not un-gban due to: {excp.message}",
351
- )
352
- return
353
- except TelegramError:
354
- pass
355
-
356
- sql.ungban_user(user_id)
357
-
358
- if EVENT_LOGS:
359
- await log.edit_text(
360
- log_message + f"\n<b>Chats affected:</b> {ungbanned_chats}",
361
- parse_mode=ParseMode.HTML,
362
- )
363
- else:
364
- send_to_list(bot, DRAGONS, "un-gban complete!")
365
-
366
- end_time = time.time()
367
- ungban_time = round((end_time - start_time), 2)
368
-
369
- if ungban_time > 60:
370
- ungban_time = round((ungban_time / 60), 2)
371
- await message.reply_text(f"Person has been un-gbanned. Took {ungban_time} min")
372
- else:
373
- await message.reply_text(f"Person has been un-gbanned. Took {ungban_time} sec")
374
-
375
-
376
- @support_plus
377
- async def gbanlist(update: Update, context: ContextTypes.DEFAULT_TYPE):
378
- banned_users = sql.get_gban_list()
379
-
380
- if not banned_users:
381
- await update.effective_message.reply_text(
382
- "There aren't any gbanned users! You're kinder than I expected...",
383
- )
384
- return
385
-
386
- banfile = "Screw these guys.\n"
387
- for user in banned_users:
388
- banfile += f"[x] {user['name']} - {user['user_id']}\n"
389
- if user["reason"]:
390
- banfile += f"Reason: {user['reason']}\n"
391
-
392
- with BytesIO(str.encode(banfile)) as output:
393
- output.name = "gbanlist.txt"
394
- await update.effective_message.reply_document(
395
- document=output,
396
- filename="gbanlist.txt",
397
- caption="Here is the list of currently gbanned users.",
398
- )
399
-
400
-
401
- async def check_and_ban(update, user_id, should_message=True):
402
- if sql.is_user_gbanned(user_id):
403
- await update.effective_chat.ban_member(user_id)
404
- if should_message:
405
- text = (
406
- f"<b>Alert</b>: this user is globally banned.\n"
407
- f"<code>*bans them from here*</code>.\n"
408
- f"<b>Appeal chat</b>: @{SUPPORT_CHAT}\n"
409
- f"<b>User ID</b>: <code>{user_id}</code>"
410
- )
411
- user = sql.get_gbanned_user(user_id)
412
- if user.reason:
413
- text += f"\n<b>Ban Reason:</b> <code>{html.escape(user.reason)}</code>"
414
- await update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
415
-
416
-
417
- async def enforce_gban(update: Update, context: ContextTypes.DEFAULT_TYPE):
418
- # Not using @restrict handler to avoid spamming - just ignore if cant gban.
419
- bot = context.bot
420
- try:
421
- get_member = await update.effective_chat.get_member(
422
- bot.id,
423
- )
424
- if isinstance(get_member, ChatMemberAdministrator):
425
- restrict_permission = get_member.can_restrict_members
426
- else:
427
- return
428
- except Forbidden:
429
- return
430
- if sql.does_chat_gban(update.effective_chat.id) and restrict_permission:
431
- user = update.effective_user
432
- chat = update.effective_chat
433
- msg = update.effective_message
434
-
435
- if user and not await is_user_admin(chat, user.id):
436
- await check_and_ban(update, user.id)
437
- return
438
-
439
- if msg.new_chat_members:
440
- new_members = update.effective_message.new_chat_members
441
- for mem in new_members:
442
- await check_and_ban(update, mem.id)
443
-
444
- if msg.reply_to_message:
445
- user = msg.reply_to_message.from_user
446
- if user and not await is_user_admin(chat, user.id):
447
- await check_and_ban(update, user.id, should_message=False)
448
-
449
-
450
- @check_admin(is_user=True)
451
- async def gbanstat(update: Update, context: ContextTypes.DEFAULT_TYPE):
452
- args = context.args
453
- if len(args) > 0:
454
- if args[0].lower() in ["on", "yes"]:
455
- sql.enable_gbans(update.effective_chat.id)
456
- await update.effective_message.reply_text(
457
- "Antispam is now enabled ✅ "
458
- "I am now protecting your group from potential remote threats!",
459
- )
460
- elif args[0].lower() in ["off", "no"]:
461
- sql.disable_gbans(update.effective_chat.id)
462
- await update.effective_message.reply_text(
463
- "I am not now protecting your group from potential remote threats!",
464
- )
465
- else:
466
- await update.effective_message.reply_text(
467
- "Give me some arguments to choose a setting! on/off, yes/no!\n\n"
468
- "Your current setting is: {}\n"
469
- "When True, any gbans that happen will also happen in your group. "
470
- "When False, they won't, leaving you at the possible mercy of "
471
- "spammers.".format(sql.does_chat_gban(update.effective_chat.id)),
472
- )
473
-
474
-
475
- def __stats__():
476
- return f"• {sql.num_gbanned_users()} gbanned users."
477
-
478
-
479
- def __user_info__(user_id):
480
- is_gbanned = sql.is_user_gbanned(user_id)
481
- text = "Malicious: <b>{}</b>"
482
- if user_id in [777000, 1087968824]:
483
- return ""
484
- if user_id == dispatcher.bot.id:
485
- return ""
486
- if int(user_id) in DRAGONS:
487
- return ""
488
- if is_gbanned:
489
- text = text.format("Yes")
490
- user = sql.get_gbanned_user(user_id)
491
- if user.reason:
492
- text += f"\n<b>Reason:</b> <code>{html.escape(user.reason)}</code>"
493
- text += f"\n<b>Appeal Chat:</b> @{SUPPORT_CHAT}"
494
- else:
495
- text = text.format("???")
496
- return text
497
-
498
-
499
- def __migrate__(old_chat_id, new_chat_id):
500
- sql.migrate_chat(old_chat_id, new_chat_id)
501
-
502
-
503
- def __chat_settings__(chat_id, user_id):
504
- return f"This chat is enforcing *gbans*: `{sql.does_chat_gban(chat_id)}`."
505
-
506
-
507
- # <=================================================== HELP ====================================================>
508
-
509
-
510
- __help__ = f"""
511
- ➠ *Admins only:*
512
-
513
- » /antispam <on/off/yes/no>: Will toggle our antispam tech or return your current settings.
514
-
515
- ➠ Anti-Spam, used by bot devs to ban spammers across all groups. This helps protect \
516
- you and your groups by removing spam flooders as quickly as possible.
517
- ➠ *Note:* Users can appeal gbans or report spammers at @hydraX2support
518
- """
519
-
520
- # <================================================ HANDLER =======================================================>
521
- GBAN_HANDLER = CommandHandler("gban", gban, block=False)
522
- UNGBAN_HANDLER = CommandHandler("ungban", ungban, block=False)
523
- GBAN_LIST = CommandHandler("gbanlist", gbanlist, block=False)
524
-
525
- GBAN_STATUS = CommandHandler(
526
- "antispam", gbanstat, filters=filters.ChatType.GROUPS, block=False
527
- )
528
-
529
- GBAN_ENFORCER = MessageHandler(
530
- filters.ALL & filters.ChatType.GROUPS, enforce_gban, block=False
531
- )
532
-
533
- function(GBAN_HANDLER)
534
- function(UNGBAN_HANDLER)
535
- function(GBAN_LIST)
536
- function(GBAN_STATUS)
537
-
538
- __mod_name__ = "ANTI-SPAM"
539
- __handlers__ = [GBAN_HANDLER, UNGBAN_HANDLER, GBAN_LIST, GBAN_STATUS]
540
-
541
- if STRICT_GBAN: # enforce GBANS if this is set
542
- function(GBAN_ENFORCER, GBAN_ENFORCE_GROUP)
543
- __handlers__.append((GBAN_ENFORCER, GBAN_ENFORCE_GROUP))
544
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/helper_funcs/alternate.py DELETED
@@ -1,85 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from functools import wraps
3
-
4
- from telegram import Message, Update
5
- from telegram.constants import ChatAction
6
- from telegram.error import BadRequest
7
- from telegram.ext import ContextTypes
8
-
9
- # <=======================================================================================================>
10
-
11
-
12
- # <================================================ FUNCTION =======================================================>
13
- async def send_message(message: Message, text, *args, **kwargs):
14
- try:
15
- return await message.reply_text(text, *args, **kwargs)
16
- except BadRequest as err:
17
- if str(err) == "Reply message not found":
18
- return await message.reply_text(text, quote=False, *args, **kwargs)
19
-
20
-
21
- def typing_action(func):
22
- """Sends typing action while processing func command."""
23
-
24
- @wraps(func)
25
- async def command_func(
26
- update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
27
- ):
28
- await context.bot.send_chat_action(
29
- chat_id=update.effective_chat.id,
30
- action=ChatAction.TYPING,
31
- )
32
- return await func(update, context, *args, **kwargs)
33
-
34
- return command_func
35
-
36
-
37
- def sticker_action(func):
38
- """Sends typing action while processing func command."""
39
-
40
- @wraps(func)
41
- async def command_func(
42
- update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
43
- ):
44
- await context.bot.send_chat_action(
45
- chat_id=update.effective_chat.id,
46
- action=ChatAction.CHOOSE_STICKER,
47
- )
48
- return await func(update, context, *args, **kwargs)
49
-
50
- return command_func
51
-
52
-
53
- def document_action(func):
54
- """Sends typing action while processing func command."""
55
-
56
- @wraps(func)
57
- async def command_func(
58
- update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
59
- ):
60
- await context.bot.send_chat_action(
61
- chat_id=update.effective_chat.id,
62
- action=ChatAction.UPLOAD_DOCUMENT,
63
- )
64
- return await func(update, context, *args, **kwargs)
65
-
66
- return command_func
67
-
68
-
69
- def photo_action(func):
70
- """Sends typing action while processing func command."""
71
-
72
- @wraps(func)
73
- async def command_func(
74
- update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
75
- ):
76
- await context.bot.send_chat_action(
77
- chat_id=update.effective_chat.id,
78
- action=ChatAction.UPLOAD_PHOTO,
79
- )
80
- return await func(update, context, *args, **kwargs)
81
-
82
- return command_func
83
-
84
-
85
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/helper_funcs/chat_status.py DELETED
@@ -1,415 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from functools import wraps
3
- from threading import RLock
4
- from time import perf_counter
5
-
6
- from cachetools import TTLCache
7
- from telegram import Chat, ChatMember, ChatMemberAdministrator, ChatMemberOwner, Update
8
- from telegram.constants import ChatMemberStatus, ChatType
9
- from telegram.error import Forbidden
10
- from telegram.ext import ContextTypes
11
-
12
- from Mikobot import DEL_CMDS, DEV_USERS, DRAGONS, SUPPORT_CHAT, dispatcher
13
-
14
- # <=======================================================================================================>
15
-
16
- # stores admemes in memory for 10 min.
17
- ADMIN_CACHE = TTLCache(maxsize=512, ttl=60 * 10, timer=perf_counter)
18
- THREAD_LOCK = RLock()
19
-
20
-
21
- # <================================================ FUNCTION =======================================================>
22
- def check_admin(
23
- permission: str = None,
24
- is_bot: bool = False,
25
- is_user: bool = False,
26
- is_both: bool = False,
27
- only_owner: bool = False,
28
- only_sudo: bool = False,
29
- only_dev: bool = False,
30
- no_reply: object = False,
31
- ) -> object:
32
- """Check for permission level to perform some operations
33
-
34
- Args:
35
- permission (str, optional): permission type to check. Defaults to None.
36
- is_bot (bool, optional): if bot can perform the action. Defaults to False.
37
- is_user (bool, optional): if user can perform the action. Defaults to False.
38
- is_both (bool, optional): if both user and bot can perform the action. Defaults to False.
39
- only_owner (bool, optional): if only owner can perform the action. Defaults to False.
40
- only_sudo (bool, optional): if only sudo users can perform the operation. Defaults to False.
41
- only_dev (bool, optional): if only dev users can perform the operation. Defaults to False.
42
- no_reply (boot, optional): if should not reply. Defaults to False.
43
- """
44
-
45
- def wrapper(func):
46
- @wraps(func)
47
- async def wrapped(
48
- update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
49
- ):
50
- nonlocal permission
51
- chat = update.effective_chat
52
- user = update.effective_user
53
- message = update.effective_message
54
-
55
- if chat.type == ChatType.PRIVATE and not (
56
- only_dev or only_sudo or only_owner
57
- ):
58
- return await func(update, context, *args, **kwargs)
59
-
60
- bot_member = (
61
- await chat.get_member(context.bot.id) if is_bot or is_both else None
62
- )
63
- user_member = await chat.get_member(user.id) if is_user or is_both else None
64
-
65
- if only_owner:
66
- if isinstance(user_member, ChatMemberOwner) or user.id in DEV_USERS:
67
- return await func(update, context, *args, **kwargs)
68
- else:
69
- return await message.reply_text(
70
- "Only chat owner can perform this action."
71
- )
72
- if only_dev:
73
- if user.id in DEV_USERS:
74
- return await func(update, context, *args, **kwargs)
75
- else:
76
- return await update.effective_message.reply_text(
77
- "Hey little kid"
78
- "\nWho the hell are you to say me what to execute on my server?",
79
- )
80
-
81
- if only_sudo:
82
- if user.id in DRAGONS:
83
- return await func(update, context, *args, **kwargs)
84
- else:
85
- return await update.effective_message.reply_text(
86
- "Who the hell are you to say me what to do?",
87
- )
88
-
89
- if message.from_user.id == 1087968824:
90
- return await func(update, context, *args, **kwargs)
91
-
92
- if permission:
93
- no_permission = permission.replace("_", " ").replace("can", "")
94
- if is_bot:
95
- if (
96
- getattr(bot_member, permission)
97
- if isinstance(bot_member, ChatMemberAdministrator)
98
- else False
99
- ):
100
- return await func(update, context, *args, **kwargs)
101
- elif no_reply:
102
- return
103
- else:
104
- return await message.reply_text(
105
- f"I don't have permission to {no_permission}."
106
- )
107
- if is_user:
108
- if isinstance(user_member, ChatMemberOwner):
109
- return await func(update, context, *args, **kwargs)
110
- elif (
111
- getattr(user_member, permission)
112
- if isinstance(user_member, ChatMemberAdministrator)
113
- else False or user.id in DRAGONS
114
- ):
115
- return await func(update, context, *args, **kwargs)
116
- elif no_reply:
117
- return
118
- else:
119
- return await message.reply_text(
120
- f"You don't have permission to {no_permission}."
121
- )
122
- if is_both:
123
- if (
124
- getattr(bot_member, permission)
125
- if isinstance(bot_member, ChatMemberAdministrator)
126
- else False
127
- ):
128
- pass
129
- elif no_reply:
130
- return
131
- else:
132
- return await message.reply_text(
133
- f"I don't have permission to {no_permission}."
134
- )
135
-
136
- if isinstance(user_member, ChatMemberOwner) or user.id in DEV_USERS:
137
- pass
138
- elif (
139
- getattr(user_member, permission)
140
- if isinstance(user_member, ChatMemberAdministrator)
141
- else False or user.id in DRAGONS
142
- ):
143
- pass
144
- elif no_reply:
145
- return
146
- else:
147
- return await message.reply_text(
148
- f"You don't have permission to {no_permission}."
149
- )
150
- return await func(update, context, *args, **kwargs)
151
- else:
152
- if is_bot:
153
- if bot_member.status == ChatMemberStatus.ADMINISTRATOR:
154
- return await func(update, context, *args, **kwargs)
155
- else:
156
- return await message.reply_text("I'm not admin here.")
157
- elif is_user:
158
- if user_member.status in [
159
- ChatMemberStatus.ADMINISTRATOR,
160
- ChatMemberStatus.OWNER,
161
- ]:
162
- return await func(update, context, *args, **kwargs)
163
- elif user.id in DRAGONS:
164
- return await func(update, context, *args, **kwargs)
165
- else:
166
- return await message.reply_text("You are not admin here.")
167
- elif is_both:
168
- if bot_member.status == ChatMemberStatus.ADMINISTRATOR:
169
- pass
170
- else:
171
- return await message.reply_text("I'm not admin here.")
172
-
173
- if user_member.status in [
174
- ChatMemberStatus.ADMINISTRATOR,
175
- ChatMemberStatus.OWNER,
176
- ]:
177
- pass
178
- elif user.id in DRAGONS:
179
- pass
180
- else:
181
- return await message.reply_text("You are not admin here.")
182
- return await func(update, context, *args, **kwargs)
183
-
184
- return wrapped
185
-
186
- return wrapper
187
-
188
-
189
- def is_whitelist_plus(chat: Chat, user_id: int, member: ChatMember = None) -> bool:
190
- return any(user_id in user for user in [DRAGONS, DEV_USERS])
191
-
192
-
193
- def is_support_plus(chat: Chat, user_id: int, member: ChatMember = None) -> bool:
194
- return user_id in DRAGONS or user_id in DEV_USERS
195
-
196
-
197
- def is_sudo_plus(chat: Chat, user_id: int, member: ChatMember = None) -> bool:
198
- return user_id in DRAGONS or user_id in DEV_USERS
199
-
200
-
201
- async def is_user_admin(chat: Chat, user_id: int, member: ChatMember = None) -> bool:
202
- if (
203
- chat.type == "private"
204
- or user_id in DRAGONS
205
- or user_id in DEV_USERS
206
- or user_id in [777000, 1087968824]
207
- ): # Count telegram and Group Anonymous as admin
208
- return True
209
- if not member:
210
- with THREAD_LOCK:
211
- # try to fetch from cache first.
212
- try:
213
- return user_id in ADMIN_CACHE[chat.id]
214
- except KeyError:
215
- # keyerror happend means cache is deleted,
216
- # so query bot api again and return user status
217
- # while saving it in cache for future usage...
218
- try:
219
- chat_admins = await dispatcher.bot.getChatAdministrators(chat.id)
220
- except Forbidden:
221
- return False
222
- admin_list = [x.user.id for x in chat_admins]
223
- ADMIN_CACHE[chat.id] = admin_list
224
-
225
- return user_id in admin_list
226
- else:
227
- return member.status in (ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER)
228
-
229
-
230
- async def is_bot_admin(chat: Chat, bot_id: int, bot_member: ChatMember = None) -> bool:
231
- if chat.type == "private":
232
- return True
233
-
234
- if not bot_member:
235
- bot_member = await chat.get_member(bot_id)
236
-
237
- return bot_member.status in (ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER)
238
-
239
-
240
- async def can_delete(chat: Chat, bot_id: int) -> bool:
241
- chat_member = await chat.get_member(bot_id)
242
- if isinstance(chat_member, ChatMemberAdministrator):
243
- return chat_member.can_delete_messages
244
-
245
-
246
- async def is_user_ban_protected(
247
- chat: Chat, user_id: int, member: ChatMember = None
248
- ) -> bool:
249
- if (
250
- chat.type == "private"
251
- or user_id in DRAGONS
252
- or user_id in DEV_USERS
253
- or user_id in [777000, 1087968824]
254
- ): # Count telegram and Group Anonymous as admin
255
- return True
256
-
257
- if not member:
258
- member = await chat.get_member(user_id)
259
-
260
- return member.status in (ChatMemberStatus.ADMINISTRATOR, ChatMemberStatus.OWNER)
261
-
262
-
263
- async def is_user_in_chat(chat: Chat, user_id: int) -> bool:
264
- member = await chat.get_member(user_id)
265
- return member.status in (ChatMemberStatus.LEFT, ChatMemberStatus.RESTRICTED)
266
-
267
-
268
- def dev_plus(func):
269
- @wraps(func)
270
- def is_dev_plus_func(
271
- update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
272
- ):
273
- context.bot
274
- user = update.effective_user
275
-
276
- if user.id in DEV_USERS:
277
- return func(update, context, *args, **kwargs)
278
- elif not user:
279
- pass
280
- elif DEL_CMDS and " " not in update.effective_message.text:
281
- try:
282
- update.effective_message.delete()
283
- except:
284
- pass
285
- else:
286
- update.effective_message.reply_text(
287
- "This is a developer restricted command."
288
- " You do not have permissions to run this."
289
- )
290
-
291
- return is_dev_plus_func
292
-
293
-
294
- def sudo_plus(func):
295
- @wraps(func)
296
- def is_sudo_plus_func(
297
- update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
298
- ):
299
- context.bot
300
- user = update.effective_user
301
- chat = update.effective_chat
302
-
303
- if user and is_sudo_plus(chat, user.id):
304
- return func(update, context, *args, **kwargs)
305
- elif not user:
306
- pass
307
- elif DEL_CMDS and " " not in update.effective_message.text:
308
- try:
309
- update.effective_message.delete()
310
- except:
311
- pass
312
- else:
313
- update.effective_message.reply_text(
314
- "Who dis non-admin telling me what to do? You want a punch?"
315
- )
316
-
317
- return is_sudo_plus_func
318
-
319
-
320
- def support_plus(func):
321
- @wraps(func)
322
- async def is_support_plus_func(
323
- update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
324
- ):
325
- bot = context.bot
326
- user = update.effective_user
327
- chat = update.effective_chat
328
-
329
- if user and is_support_plus(chat, user.id):
330
- return await func(update, context, *args, **kwargs)
331
- elif DEL_CMDS and " " not in update.effective_message.text:
332
- try:
333
- await update.effective_message.delete()
334
- except:
335
- pass
336
-
337
- return is_support_plus_func
338
-
339
-
340
- def whitelist_plus(func):
341
- @wraps(func)
342
- async def is_whitelist_plus_func(
343
- update: Update,
344
- context: ContextTypes.DEFAULT_TYPE,
345
- *args,
346
- **kwargs,
347
- ):
348
- bot = context.bot
349
- user = update.effective_user
350
- chat = update.effective_chat
351
-
352
- if user and is_whitelist_plus(chat, user.id):
353
- return await func(update, context, *args, **kwargs)
354
- else:
355
- await update.effective_message.reply_text(
356
- f"You don't have access to use this.\nVisit @{SUPPORT_CHAT}",
357
- )
358
-
359
- return is_whitelist_plus_func
360
-
361
-
362
- def user_not_admin(func):
363
- @wraps(func)
364
- async def is_not_admin(
365
- update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
366
- ):
367
- bot = context.bot
368
- user = update.effective_user
369
- chat = update.effective_chat
370
-
371
- if user and not await is_user_admin(chat, user.id):
372
- return await func(update, context, *args, **kwargs)
373
- elif not user:
374
- pass
375
-
376
- return is_not_admin
377
-
378
-
379
- def connection_status(func):
380
- @wraps(func)
381
- async def connected_status(
382
- update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
383
- ):
384
- conn = await connected(
385
- context.bot,
386
- update,
387
- update.effective_chat,
388
- update.effective_user.id,
389
- need_admin=False,
390
- )
391
-
392
- if conn:
393
- chat = await dispatcher.bot.getChat(conn)
394
- update.__setattr__("_effective_chat", chat)
395
- return await func(update, context, *args, **kwargs)
396
- else:
397
- if update.effective_message.chat.type == "private":
398
- await update.effective_message.reply_text(
399
- "Send /connect in a group that you and I have in common first.",
400
- )
401
- return connected_status
402
-
403
- return await func(update, context, *args, **kwargs)
404
-
405
- return connected_status
406
-
407
-
408
- # <=======================================================================================================>
409
-
410
- # <=======================================================================================================>
411
- # Workaround for circular import with connection.py
412
- from Mikobot.plugins import connection
413
-
414
- connected = connection.connected
415
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/helper_funcs/extraction.py DELETED
@@ -1,190 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from typing import List, Optional, Union
3
-
4
- from telegram import Message, MessageEntity
5
- from telegram.error import BadRequest
6
- from telegram.ext import ContextTypes
7
-
8
- from Mikobot import LOGGER
9
- from Mikobot.plugins.users import get_user_id
10
-
11
- # <=======================================================================================================>
12
-
13
-
14
- # <================================================ FUNCTION =======================================================>
15
- async def id_from_reply(message: Message):
16
- prev_message = message.reply_to_message
17
- if not prev_message or prev_message.forum_topic_created:
18
- return None, None
19
- user_id = prev_message.from_user.id
20
- # if user id is from channel bot, then fetch channel id from sender_chat
21
- if user_id == 136817688:
22
- user_id = message.reply_to_message.sender_chat.id
23
- res = message.text.split(None, 1)
24
- if len(res) < 2:
25
- return user_id, ""
26
- return user_id, res[1]
27
-
28
-
29
- async def extract_user(
30
- message: Message,
31
- context: ContextTypes.DEFAULT_TYPE,
32
- args: List[str],
33
- ) -> Optional[int]:
34
- return (await extract_user_and_text(message, context, args))[0]
35
-
36
-
37
- async def extract_user_and_text(
38
- message: Message,
39
- context: ContextTypes.DEFAULT_TYPE,
40
- args: List[str],
41
- ) -> Union[(Optional[int], Optional[str])]:
42
- prev_message = message.reply_to_message
43
- split_text = message.text.split(None, 1)
44
-
45
- if len(split_text) < 2:
46
- return await id_from_reply(message) # only option possible
47
-
48
- text_to_parse = split_text[1]
49
-
50
- text = ""
51
-
52
- entities = list(message.parse_entities([MessageEntity.TEXT_MENTION]))
53
- ent = entities[0] if entities else None
54
- # if entity offset matches (command end/text start) then all good
55
- if entities and ent and ent.offset == len(message.text) - len(text_to_parse):
56
- ent = entities[0]
57
- user_id = ent.user.id
58
- text = message.text[ent.offset + ent.length :]
59
-
60
- elif len(args) >= 1 and args[0][0] == "@":
61
- user = args[0]
62
- user_id = await get_user_id(user)
63
- if not user_id:
64
- await message.reply_text(
65
- "No idea who this user is. You'll be able to interact with them if "
66
- "you reply to that person's message instead, or forward one of that user's messages.",
67
- )
68
- return None, None
69
-
70
- else:
71
- user_id = user_id
72
- res = message.text.split(None, 2)
73
- if len(res) >= 3:
74
- text = res[2]
75
-
76
- elif len(args) >= 1 and args[0].isdigit():
77
- user_id = int(args[0])
78
- res = message.text.split(None, 2)
79
- if len(res) >= 3:
80
- text = res[2]
81
-
82
- elif prev_message:
83
- user_id, text = await id_from_reply(message)
84
-
85
- else:
86
- return None, None
87
-
88
- try:
89
- await context.bot.get_chat(user_id)
90
- except BadRequest as excp:
91
- if excp.message in ("User_id_invalid", "Chat not found"):
92
- await message.reply_text(
93
- "I don't seem to have interacted with this user before - please forward a message from "
94
- "them to give me control! (like a voodoo doll, I need a piece of them to be able "
95
- "to execute certain commands...)",
96
- )
97
- else:
98
- LOGGER.exception("Exception %s on user %s", excp.message, user_id)
99
-
100
- return None, None
101
-
102
- return user_id, text
103
-
104
-
105
- async def extract_text(message) -> str:
106
- return (
107
- message.text
108
- or message.caption
109
- or (message.sticker.emoji if message.sticker else None)
110
- )
111
-
112
-
113
- async def extract_unt_fedban(
114
- message: Message, context: ContextTypes.DEFAULT_TYPE, args: List[str]
115
- ) -> Union[(Optional[int], Optional[str])]:
116
- prev_message = message.reply_to_message
117
- split_text = message.text.split(None, 1)
118
-
119
- if len(split_text) < 2:
120
- return await id_from_reply(message) # only option possible
121
-
122
- text_to_parse = split_text[1]
123
-
124
- text = ""
125
-
126
- entities = list(message.parse_entities([MessageEntity.TEXT_MENTION]))
127
- ent = entities[0] if entities else None
128
- # if entity offset matches (command end/text start) then all good
129
- if entities and ent and ent.offset == len(message.text) - len(text_to_parse):
130
- ent = entities[0]
131
- user_id = ent.user.id
132
- text = message.text[ent.offset + ent.length :]
133
-
134
- elif len(args) >= 1 and args[0][0] == "@":
135
- user = args[0]
136
- user_id = await get_user_id(user)
137
- if not user_id and not isinstance(user_id, int):
138
- await message.reply_text(
139
- "I don't have that user in my db. "
140
- "You'll be able to interact with them if you reply to that person's message instead, or forward one of that user's messages.",
141
- )
142
- return None, None
143
-
144
- else:
145
- user_id = user_id
146
- res = message.text.split(None, 2)
147
- if len(res) >= 3:
148
- text = res[2]
149
-
150
- elif len(args) >= 1 and args[0].isdigit():
151
- user_id = int(args[0])
152
- res = message.text.split(None, 2)
153
- if len(res) >= 3:
154
- text = res[2]
155
-
156
- elif prev_message:
157
- user_id, text = await id_from_reply(message)
158
-
159
- else:
160
- return None, None
161
-
162
- try:
163
- await context.bot.get_chat(user_id)
164
- except BadRequest as excp:
165
- if excp.message in ("User_id_invalid", "Chat not found") and not isinstance(
166
- user_id,
167
- int,
168
- ):
169
- await message.reply_text(
170
- "I don't seem to have interacted with this user before "
171
- "please forward a message from them to give me control! "
172
- "(like a voodoo doll, I need a piece of them to be able to execute certain commands...)",
173
- )
174
- return None, None
175
- elif excp.message != "Chat not found":
176
- LOGGER.exception("Exception %s on user %s", excp.message, user_id)
177
- return None, None
178
- elif not isinstance(user_id, int):
179
- return None, None
180
-
181
- return user_id, text
182
-
183
-
184
- async def extract_user_fban(
185
- message: Message, context: ContextTypes.DEFAULT_TYPE, args: List[str]
186
- ) -> Optional[int]:
187
- return (await extract_unt_fedban(message, context, args))[0]
188
-
189
-
190
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/helper_funcs/misc.py DELETED
@@ -1,263 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from math import ceil
3
- from typing import Dict, List
4
- from uuid import uuid4
5
-
6
- import cv2
7
- import ffmpeg
8
- from telegram import (
9
- Bot,
10
- InlineKeyboardButton,
11
- InlineKeyboardMarkup,
12
- InlineQueryResultArticle,
13
- InputTextMessageContent,
14
- )
15
- from telegram.constants import MessageLimit, ParseMode
16
- from telegram.error import TelegramError
17
-
18
- from Mikobot import NO_LOAD
19
-
20
- # <=======================================================================================================>
21
-
22
-
23
- # <================================================ FUNCTION =======================================================>
24
- class EqInlineKeyboardButton(InlineKeyboardButton):
25
- def __eq__(self, other):
26
- return self.text == other.text
27
-
28
- def __lt__(self, other):
29
- return self.text < other.text
30
-
31
- def __gt__(self, other):
32
- return self.text > other.text
33
-
34
-
35
- def split_message(msg: str) -> List[str]:
36
- if len(msg) < MessageLimit.MAX_TEXT_LENGTH:
37
- return [msg]
38
-
39
- lines = msg.splitlines(True)
40
- small_msg = ""
41
- result = []
42
- for line in lines:
43
- if len(small_msg) + len(line) < MessageLimit.MAX_TEXT_LENGTH:
44
- small_msg += line
45
- else:
46
- result.append(small_msg)
47
- small_msg = line
48
- else:
49
- # Else statement at the end of the for loop, so append the leftover string.
50
- result.append(small_msg)
51
-
52
- return result
53
-
54
-
55
- def paginate_modules(page_n: int, module_dict: Dict, prefix, chat=None) -> List:
56
- if not chat:
57
- modules = sorted(
58
- [
59
- EqInlineKeyboardButton(
60
- x.__mod_name__,
61
- callback_data="{}_module({})".format(
62
- prefix, x.__mod_name__.lower()
63
- ),
64
- )
65
- for x in module_dict.values()
66
- ]
67
- )
68
- else:
69
- modules = sorted(
70
- [
71
- EqInlineKeyboardButton(
72
- x.__mod_name__,
73
- callback_data="{}_module({},{})".format(
74
- prefix, chat, x.__mod_name__.lower()
75
- ),
76
- )
77
- for x in module_dict.values()
78
- ]
79
- )
80
-
81
- pairs = [modules[i * 3 : (i + 1) * 3] for i in range((len(modules) + 3 - 1) // 3)]
82
-
83
- round_num = len(modules) / 3
84
- calc = len(modules) - round(round_num)
85
- if calc in [1, 2]:
86
- pairs.append((modules[-1],))
87
-
88
- max_num_pages = ceil(len(pairs) / 6)
89
- modulo_page = page_n % max_num_pages
90
-
91
- # can only have a certain amount of buttons side by side
92
- if len(pairs) > 3:
93
- pairs = pairs[modulo_page * 6 : 6 * (modulo_page + 1)] + [
94
- (
95
- EqInlineKeyboardButton(
96
- "◁", callback_data="{}_prev({})".format(prefix, modulo_page)
97
- ),
98
- EqInlineKeyboardButton("» 𝙃𝙊𝙈𝙀 «", callback_data="Miko_back"),
99
- EqInlineKeyboardButton(
100
- "▷", callback_data="{}_next({})".format(prefix, modulo_page)
101
- ),
102
- )
103
- ]
104
-
105
- else:
106
- pairs += [[EqInlineKeyboardButton("⇦ 𝘽𝘼𝘾𝙆", callback_data="Miko_back")]]
107
-
108
- return pairs
109
-
110
-
111
- def article(
112
- title: str = "",
113
- description: str = "",
114
- message_text: str = "",
115
- thumb_url: str = None,
116
- reply_markup: InlineKeyboardMarkup = None,
117
- disable_web_page_preview: bool = False,
118
- ) -> InlineQueryResultArticle:
119
- return InlineQueryResultArticle(
120
- id=uuid4(),
121
- title=title,
122
- description=description,
123
- thumb_url=thumb_url,
124
- input_message_content=InputTextMessageContent(
125
- message_text=message_text,
126
- disable_web_page_preview=disable_web_page_preview,
127
- ),
128
- reply_markup=reply_markup,
129
- )
130
-
131
-
132
- def send_to_list(
133
- bot: Bot, send_to: list, message: str, markdown=False, html=False
134
- ) -> None:
135
- if html and markdown:
136
- raise Exception("Can only send with either markdown or HTML!")
137
- for user_id in set(send_to):
138
- try:
139
- if markdown:
140
- bot.send_message(user_id, message, parse_mode=ParseMode.MARKDOWN)
141
- elif html:
142
- bot.send_message(user_id, message, parse_mode=ParseMode.HTML)
143
- else:
144
- bot.send_message(user_id, message)
145
- except TelegramError:
146
- pass # ignore users who fail
147
-
148
-
149
- def build_keyboard(buttons):
150
- keyb = []
151
- for btn in buttons:
152
- if btn.same_line and keyb:
153
- keyb[-1].append(InlineKeyboardButton(btn.name, url=btn.url))
154
- else:
155
- keyb.append([InlineKeyboardButton(btn.name, url=btn.url)])
156
-
157
- return keyb
158
-
159
-
160
- def revert_buttons(buttons):
161
- res = ""
162
- for btn in buttons:
163
- if btn.same_line:
164
- res += "\n[{}](buttonurl://{}:same)".format(btn.name, btn.url)
165
- else:
166
- res += "\n[{}](buttonurl://{})".format(btn.name, btn.url)
167
-
168
- return res
169
-
170
-
171
- def build_keyboard_parser(bot, chat_id, buttons):
172
- keyb = []
173
- for btn in buttons:
174
- if btn.url == "{rules}":
175
- btn.url = "http://t.me/{}?start={}".format(bot.username, chat_id)
176
- if btn.same_line and keyb:
177
- keyb[-1].append(InlineKeyboardButton(btn.name, url=btn.url))
178
- else:
179
- keyb.append([InlineKeyboardButton(btn.name, url=btn.url)])
180
-
181
- return keyb
182
-
183
-
184
- def user_bot_owner(func):
185
- @wraps(func)
186
- def is_user_bot_owner(bot: Bot, update: Update, *args, **kwargs):
187
- user = update.effective_user
188
- if user and user.id == OWNER_ID:
189
- return func(bot, update, *args, **kwargs)
190
- else:
191
- pass
192
-
193
- return is_user_bot_owner
194
-
195
-
196
- def build_keyboard_alternate(buttons):
197
- keyb = []
198
- for btn in buttons:
199
- if btn[2] and keyb:
200
- keyb[-1].append(InlineKeyboardButton(btn[0], url=btn[1]))
201
- else:
202
- keyb.append([InlineKeyboardButton(btn[0], url=btn[1])])
203
-
204
- return keyb
205
-
206
-
207
- def is_module_loaded(name):
208
- return name not in NO_LOAD
209
-
210
-
211
- def convert_gif(input):
212
- """Function to convert mp4 to webm(vp9)"""
213
-
214
- vid = cv2.VideoCapture(input)
215
- height = vid.get(cv2.CAP_PROP_FRAME_HEIGHT)
216
- width = vid.get(cv2.CAP_PROP_FRAME_WIDTH)
217
-
218
- # check height and width to scale
219
- if width > height:
220
- width = 512
221
- height = -1
222
- elif height > width:
223
- height = 512
224
- width = -1
225
- elif width == height:
226
- width = 512
227
- height = 512
228
-
229
- converted_name = "kangsticker.webm"
230
-
231
- (
232
- ffmpeg.input(input)
233
- .filter("fps", fps=30, round="up")
234
- .filter("scale", width=width, height=height)
235
- .trim(start="00:00:00", end="00:00:03", duration="3")
236
- .output(
237
- converted_name,
238
- vcodec="libvpx-vp9",
239
- **{
240
- #'vf': 'scale=512:-1',
241
- "crf": "30"
242
- },
243
- )
244
- .overwrite_output()
245
- .run()
246
- )
247
-
248
- return converted_name
249
-
250
-
251
- def mention_username(username: str, name: str) -> str:
252
- """
253
- Args:
254
- username (:obj:`str`): The username of chat which you want to mention.
255
- name (:obj:`str`): The name the mention is showing.
256
-
257
- Returns:
258
- :obj:`str`: The inline mention for the user as HTML.
259
- """
260
- return f'<a href="t.me/{username}">{escape(name)}</a>'
261
-
262
-
263
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/helper_funcs/msg_types.py DELETED
@@ -1,251 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from enum import IntEnum, unique
3
-
4
- from telegram import Message
5
-
6
- from Mikobot.plugins.helper_funcs.string_handling import button_markdown_parser
7
-
8
- # <=======================================================================================================>
9
-
10
-
11
- # <================================================ CLASS =======================================================>
12
- @unique
13
- class Types(IntEnum):
14
- TEXT = 0
15
- BUTTON_TEXT = 1
16
- STICKER = 2
17
- DOCUMENT = 3
18
- PHOTO = 4
19
- AUDIO = 5
20
- VOICE = 6
21
- VIDEO = 7
22
-
23
-
24
- # <================================================ FUNCTION =======================================================>
25
- def get_note_type(msg: Message):
26
- data_type = None
27
- content = None
28
- text = ""
29
- raw_text = msg.text or msg.caption
30
- args = raw_text.split(None, 2) # use python's maxsplit to separate cmd and args
31
- note_name = args[1]
32
-
33
- buttons = []
34
- # determine what the contents of the filter are - text, image, sticker, etc
35
- if len(args) >= 3:
36
- offset = len(args[2]) - len(
37
- raw_text,
38
- ) # set correct offset relative to command + notename
39
- text, buttons = button_markdown_parser(
40
- args[2],
41
- entities=msg.parse_entities() or msg.parse_caption_entities(),
42
- offset=offset,
43
- )
44
- if buttons:
45
- data_type = Types.BUTTON_TEXT
46
- else:
47
- data_type = Types.TEXT
48
-
49
- elif msg.reply_to_message and not msg.reply_to_message.forum_topic_created:
50
- entities = msg.reply_to_message.parse_entities()
51
- msgtext = msg.reply_to_message.text or msg.reply_to_message.caption
52
- if len(args) >= 2 and msg.reply_to_message.text: # not caption, text
53
- text, buttons = button_markdown_parser(msgtext, entities=entities)
54
- if buttons:
55
- data_type = Types.BUTTON_TEXT
56
- else:
57
- data_type = Types.TEXT
58
-
59
- elif msg.reply_to_message.sticker:
60
- content = msg.reply_to_message.sticker.file_id
61
- data_type = Types.STICKER
62
-
63
- elif msg.reply_to_message.document:
64
- content = msg.reply_to_message.document.file_id
65
- text, buttons = button_markdown_parser(msgtext, entities=entities)
66
- data_type = Types.DOCUMENT
67
-
68
- elif msg.reply_to_message.photo:
69
- content = msg.reply_to_message.photo[-1].file_id # last elem = best quality
70
- text, buttons = button_markdown_parser(msgtext, entities=entities)
71
- data_type = Types.PHOTO
72
-
73
- elif msg.reply_to_message.audio:
74
- content = msg.reply_to_message.audio.file_id
75
- text, buttons = button_markdown_parser(msgtext, entities=entities)
76
- data_type = Types.AUDIO
77
-
78
- elif msg.reply_to_message.voice:
79
- content = msg.reply_to_message.voice.file_id
80
- text, buttons = button_markdown_parser(msgtext, entities=entities)
81
- data_type = Types.VOICE
82
-
83
- elif msg.reply_to_message.video:
84
- content = msg.reply_to_message.video.file_id
85
- text, buttons = button_markdown_parser(msgtext, entities=entities)
86
- data_type = Types.VIDEO
87
-
88
- return note_name, text, data_type, content, buttons
89
-
90
-
91
- # note: add own args?
92
- def get_welcome_type(msg: Message):
93
- data_type = None
94
- content = None
95
- text = ""
96
-
97
- try:
98
- if msg.reply_to_message and not msg.reply_to_message.forum_topic_created:
99
- if msg.reply_to_message.text:
100
- args = msg.reply_to_message.text
101
- else:
102
- args = msg.reply_to_message.caption
103
- else:
104
- args = msg.text.split(
105
- None,
106
- 1,
107
- ) # use python's maxsplit to separate cmd and args
108
- except AttributeError:
109
- args = False
110
-
111
- if msg.reply_to_message and not msg.reply_to_message.forum_topic_created:
112
- if msg.reply_to_message.sticker:
113
- content = msg.reply_to_message.sticker.file_id
114
- text = None
115
- data_type = Types.STICKER
116
-
117
- elif msg.reply_to_message.document:
118
- content = msg.reply_to_message.document.file_id
119
- text = msg.reply_to_message.caption
120
- data_type = Types.DOCUMENT
121
-
122
- elif msg.reply_to_message.photo:
123
- content = msg.reply_to_message.photo[-1].file_id # last elem = best quality
124
- text = msg.reply_to_message.caption
125
- data_type = Types.PHOTO
126
-
127
- elif msg.reply_to_message.audio:
128
- content = msg.reply_to_message.audio.file_id
129
- text = msg.reply_to_message.caption
130
- data_type = Types.AUDIO
131
-
132
- elif msg.reply_to_message.voice:
133
- content = msg.reply_to_message.voice.file_id
134
- text = msg.reply_to_message.caption
135
- data_type = Types.VOICE
136
-
137
- elif msg.reply_to_message.video:
138
- content = msg.reply_to_message.video.file_id
139
- text = msg.reply_to_message.caption
140
- data_type = Types.VIDEO
141
-
142
- elif msg.reply_to_message and msg.reply_to_message.video_note:
143
- content = msg.reply_to_message.video_note.file_id
144
- text = None
145
- data_type = Types.VIDEO_NOTE
146
-
147
- buttons = []
148
- # determine what the contents of the filter are - text, image, sticker, etc
149
- if args:
150
- if msg.reply_to_message and not msg.reply_to_message.forum_topic_created:
151
- argumen = (
152
- msg.reply_to_message.caption if msg.reply_to_message.caption else ""
153
- )
154
- offset = 0 # offset is no need since target was in reply
155
- entities = msg.reply_to_message.parse_entities()
156
- else:
157
- argumen = args[1]
158
- offset = len(argumen) - len(
159
- msg.text,
160
- ) # set correct offset relative to command + notename
161
- entities = msg.parse_entities()
162
- text, buttons = button_markdown_parser(
163
- argumen,
164
- entities=entities,
165
- offset=offset,
166
- )
167
-
168
- if not data_type:
169
- if text and buttons:
170
- data_type = Types.BUTTON_TEXT
171
- elif text:
172
- data_type = Types.TEXT
173
-
174
- return text, data_type, content, buttons
175
-
176
-
177
- def get_filter_type(msg: Message):
178
- if not msg.reply_to_message and msg.text and len(msg.text.split()) >= 3:
179
- content = None
180
- text = msg.text.split(None, 2)[2]
181
- data_type = Types.TEXT
182
- media_spoiler = None
183
- elif msg.reply_to_message and msg.reply_to_message.forum_topic_created:
184
- content = None
185
- text = msg.text.split(None, 2)[2]
186
- data_type = Types.TEXT
187
- media_spoiler = None
188
- elif msg.reply_to_message and not msg.reply_to_message.forum_topic_created:
189
- if msg.reply_to_message.text and len(msg.text.split()) >= 2:
190
- content = None
191
- text = msg.reply_to_message.text
192
- data_type = Types.TEXT
193
- media_spoiler = None
194
-
195
- elif msg.reply_to_message.sticker:
196
- content = msg.reply_to_message.sticker.file_id
197
- text = None
198
- data_type = Types.STICKER
199
- media_spoiler = None
200
-
201
- elif msg.reply_to_message.document:
202
- content = msg.reply_to_message.document.file_id
203
- text = msg.reply_to_message.caption
204
- data_type = Types.DOCUMENT
205
- media_spoiler = None
206
-
207
- elif msg.reply_to_message.photo:
208
- content = msg.reply_to_message.photo[-1].file_id # last elem = best quality
209
- text = msg.reply_to_message.caption
210
- data_type = Types.PHOTO
211
- media_spoiler = msg.reply_to_message.has_media_spoiler
212
-
213
- elif msg.reply_to_message.audio:
214
- content = msg.reply_to_message.audio.file_id
215
- text = msg.reply_to_message.caption
216
- data_type = Types.AUDIO
217
- media_spoiler = None
218
-
219
- elif msg.reply_to_message.voice:
220
- content = msg.reply_to_message.voice.file_id
221
- text = msg.reply_to_message.caption
222
- data_type = Types.VOICE
223
- media_spoiler = None
224
-
225
- elif msg.reply_to_message.video:
226
- content = msg.reply_to_message.video.file_id
227
- text = msg.reply_to_message.caption
228
- data_type = Types.VIDEO
229
- media_spoiler = msg.reply_to_message.has_media_spoiler
230
-
231
- elif msg.reply_to_message.video_note:
232
- content = msg.reply_to_message.video_note.file_id
233
- text = None
234
- data_type = Types.VIDEO_NOTE
235
- media_spoiler = None
236
-
237
- else:
238
- text = None
239
- data_type = None
240
- content = None
241
- media_spoiler = None
242
- else:
243
- text = None
244
- data_type = None
245
- content = None
246
- media_spoiler = None
247
-
248
- return text, data_type, content, media_spoiler
249
-
250
-
251
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/helper_funcs/string_handling.py DELETED
@@ -1,311 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import re
3
- import time
4
- from typing import Dict, List
5
-
6
- import bleach
7
- import markdown2
8
- from emoji import unicode_codes
9
- from telegram import MessageEntity
10
- from telegram.helpers import escape_markdown
11
-
12
- # <=======================================================================================================>
13
-
14
- MATCH_MD = re.compile(
15
- r"\*(.*?)\*|"
16
- r"_(.*?)_|"
17
- r"`(.*?)`|"
18
- r"(?<!\\)(\[.*?\])(\(.*?\))|"
19
- r"(?P<esc>[*_`\[])",
20
- )
21
-
22
- LINK_REGEX = re.compile(r"(?<!\\)\[.+?\]\((.*?)\)")
23
- BTN_URL_REGEX = re.compile(r"(\[([^\[]+?)\]\(buttonurl:(?:/{0,2})(.+?)(:same)?\))")
24
- _EMOJI_REGEXP = None
25
-
26
-
27
- # <================================================ FUNCTION =======================================================>
28
- def get_emoji_regexp():
29
- global _EMOJI_REGEXP
30
- if _EMOJI_REGEXP is None:
31
- emojis = sorted(unicode_codes.EMOJI_DATA, key=len, reverse=True)
32
- pattern = "(" + "|".join(re.escape(u) for u in emojis) + ")"
33
- return re.compile(pattern)
34
-
35
-
36
- def _selective_escape(to_parse: str) -> str:
37
- """
38
- Escape all invalid markdown
39
-
40
- :param to_parse: text to escape
41
- :return: valid markdown string
42
- """
43
- offset = 0 # offset to be used as adding a \ character causes the string to shift
44
- for match in MATCH_MD.finditer(to_parse):
45
- if match.group("esc"):
46
- ent_start = match.start()
47
- to_parse = (
48
- to_parse[: ent_start + offset] + "\\" + to_parse[ent_start + offset :]
49
- )
50
- offset += 1
51
- return to_parse
52
-
53
-
54
- # This is a fun one.
55
- def _calc_emoji_offset(to_calc) -> int:
56
- # Get all emoji in text.
57
- emoticons = get_emoji_regexp().finditer(to_calc)
58
- # Check the utf16 length of the emoji to determine the offset it caused.
59
- # Normal, 1 character emoji don't affect; hence sub 1.
60
- # special, eg with two emoji characters (eg face, and skin col) will have length 2, so by subbing one we
61
- # know we'll get one extra offset,
62
- return sum(len(e.group(0).encode("utf-16-le")) // 2 - 1 for e in emoticons)
63
-
64
-
65
- def markdown_parser(
66
- txt: str,
67
- entities: Dict[MessageEntity, str] = None,
68
- offset: int = 0,
69
- ) -> str:
70
- """
71
- Parse a string, escaping all invalid markdown entities.
72
-
73
- Escapes URL's so as to avoid URL mangling.
74
- Re-adds any telegram code entities obtained from the entities object.
75
-
76
- :param txt: text to parse
77
- :param entities: dict of message entities in text
78
- :param offset: message offset - command and notename length
79
- :return: valid markdown string
80
- """
81
- if not entities:
82
- entities = {}
83
- if not txt:
84
- return ""
85
-
86
- prev = 0
87
- res = ""
88
- # Loop over all message entities, and:
89
- # reinsert code
90
- # escape free-standing urls
91
- for ent, ent_text in entities.items():
92
- if ent.offset < -offset:
93
- continue
94
-
95
- start = ent.offset + offset # start of entity
96
- end = ent.offset + offset + ent.length - 1 # end of entity
97
-
98
- # we only care about code, url, text links
99
- if ent.type in ("code", "url", "text_link", "spoiler"):
100
- # count emoji to switch counter
101
- count = _calc_emoji_offset(txt[:start])
102
- start -= count
103
- end -= count
104
-
105
- # URL handling -> do not escape if in [](), escape otherwise.
106
- if ent.type == "url":
107
- if any(
108
- match.start(1) <= start and end <= match.end(1)
109
- for match in LINK_REGEX.finditer(txt)
110
- ):
111
- continue
112
- # else, check the escapes between the prev and last and forcefully escape the url to avoid mangling
113
- else:
114
- # TODO: investigate possible offset bug when lots of emoji are present
115
- res += _selective_escape(txt[prev:start] or "") + escape_markdown(
116
- ent_text, 2
117
- )
118
-
119
- # code handling
120
- elif ent.type == "code":
121
- res += _selective_escape(txt[prev:start]) + "`" + ent_text + "`"
122
-
123
- # handle markdown/html links
124
- elif ent.type == "text_link":
125
- res += _selective_escape(txt[prev:start]) + "[{}]({})".format(
126
- ent_text,
127
- ent.url,
128
- )
129
- # handle spoiler
130
- elif ent.type == "spoiler":
131
- res += _selective_escape(txt[prev:start]) + "||" + ent_text + "||"
132
-
133
- end += 1
134
-
135
- # anything else
136
- else:
137
- continue
138
-
139
- prev = end
140
-
141
- res += _selective_escape(txt[prev:]) # add the rest of the text
142
- return res
143
-
144
-
145
- def button_markdown_parser(
146
- txt: str,
147
- entities: Dict[MessageEntity, str] = None,
148
- offset: int = 0,
149
- ) -> (str, List):
150
- markdown_note = markdown_parser(txt, entities, offset)
151
- prev = 0
152
- note_data = ""
153
- buttons = []
154
- for match in BTN_URL_REGEX.finditer(markdown_note):
155
- # Check if btnurl is escaped
156
- n_escapes = 0
157
- to_check = match.start(1) - 1
158
- while to_check > 0 and markdown_note[to_check] == "\\":
159
- n_escapes += 1
160
- to_check -= 1
161
-
162
- # if even, not escaped -> create button
163
- if n_escapes % 2 == 0:
164
- # create a thruple with button label, url, and newline status
165
- buttons.append((match.group(2), match.group(3), bool(match.group(4))))
166
- note_data += markdown_note[prev : match.start(1)]
167
- prev = match.end(1)
168
- # if odd, escaped -> move along
169
- else:
170
- note_data += markdown_note[prev:to_check]
171
- prev = match.start(1) - 1
172
- else:
173
- note_data += markdown_note[prev:]
174
-
175
- return note_data, buttons
176
-
177
-
178
- def escape_invalid_curly_brackets(text: str, valids: List[str]) -> str:
179
- new_text = ""
180
- idx = 0
181
- while idx < len(text):
182
- if text[idx] == "{":
183
- if idx + 1 < len(text) and text[idx + 1] == "{":
184
- idx += 2
185
- new_text += "{{{{"
186
- continue
187
- else:
188
- success = False
189
- for v in valids:
190
- if text[idx:].startswith("{" + v + "}"):
191
- success = True
192
- break
193
- if success:
194
- new_text += text[idx : idx + len(v) + 2]
195
- idx += len(v) + 2
196
- continue
197
- else:
198
- new_text += "{{"
199
-
200
- elif text[idx] == "}":
201
- if idx + 1 < len(text) and text[idx + 1] == "}":
202
- idx += 2
203
- new_text += "}}}}"
204
- continue
205
- else:
206
- new_text += "}}"
207
-
208
- else:
209
- new_text += text[idx]
210
- idx += 1
211
-
212
- return new_text
213
-
214
-
215
- SMART_OPEN = "“"
216
- SMART_CLOSE = "”"
217
- START_CHAR = ("'", '"', SMART_OPEN)
218
-
219
-
220
- def split_quotes(text: str) -> List:
221
- if not any(text.startswith(char) for char in START_CHAR):
222
- return text.split(None, 1)
223
- counter = 1 # ignore first char -> is some kind of quote
224
- while counter < len(text):
225
- if text[counter] == "\\":
226
- counter += 1
227
- elif text[counter] == text[0] or (
228
- text[0] == SMART_OPEN and text[counter] == SMART_CLOSE
229
- ):
230
- break
231
- counter += 1
232
- else:
233
- return text.split(None, 1)
234
-
235
- # 1 to avoid starting quote, and counter is exclusive so avoids ending
236
- key = remove_escapes(text[1:counter].strip())
237
- # index will be in range, or `else` would have been executed and returned
238
- rest = text[counter + 1 :].strip()
239
- if not key:
240
- key = text[0] + text[0]
241
- return list(filter(None, [key, rest]))
242
-
243
-
244
- def remove_escapes(text: str) -> str:
245
- res = ""
246
- is_escaped = False
247
- for counter in range(len(text)):
248
- if is_escaped:
249
- res += text[counter]
250
- is_escaped = False
251
- elif text[counter] == "\\":
252
- is_escaped = True
253
- else:
254
- res += text[counter]
255
- return res
256
-
257
-
258
- def escape_chars(text: str, to_escape: List[str]) -> str:
259
- to_escape.append("\\")
260
- new_text = ""
261
- for x in text:
262
- if x in to_escape:
263
- new_text += "\\"
264
- new_text += x
265
- return new_text
266
-
267
-
268
- async def extract_time(message, time_val):
269
- if any(time_val.endswith(unit) for unit in ("m", "h", "d")):
270
- unit = time_val[-1]
271
- time_num = time_val[:-1] # type: str
272
- if not time_num.isdigit():
273
- await message.reply_text("Invalid time amount specified.")
274
- return ""
275
-
276
- if unit == "m":
277
- bantime = int(time.time() + int(time_num) * 60)
278
- elif unit == "h":
279
- bantime = int(time.time() + int(time_num) * 60 * 60)
280
- elif unit == "d":
281
- bantime = int(time.time() + int(time_num) * 24 * 60 * 60)
282
- else:
283
- # how even...?
284
- return ""
285
- return bantime
286
- else:
287
- await message.reply_text(
288
- "Invalid time type specified. Expected m,h, or d, got: {}".format(
289
- time_val[-1],
290
- ),
291
- )
292
- return ""
293
-
294
-
295
- def markdown_to_html(text: str):
296
- text = text.replace("*", "**")
297
- text = text.replace("`", "```")
298
- text = text.replace("~", "~~")
299
-
300
- spoiler_pattern = re.compile(r"\|\|(?=\S)(.+?)(?<=\S)\|\|", re.S)
301
- text = spoiler_pattern.sub(r"<tg-spoiler>\1</tg-spoiler>", text)
302
-
303
- _html = markdown2.markdown(text, extras=["strike", "underline"])
304
- return bleach.clean(
305
- _html,
306
- tags=["strong", "em", "a", "code", "pre", "strike", "u", "tg-spoiler"],
307
- strip=True,
308
- )[:-1]
309
-
310
-
311
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/hyperlink.py DELETED
@@ -1,63 +0,0 @@
1
- # SOURCE https://github.com/Team-ProjectCodeX
2
- # CREATED BY https://t.me/O_okarma
3
- # PROVIDED BY https://t.me/ProjectCodeX
4
-
5
- # <============================================== IMPORTS =========================================================>
6
- import random
7
- import re
8
-
9
- from telegram import Update
10
- from telegram.constants import ParseMode
11
- from telegram.ext import CommandHandler, ContextTypes
12
-
13
- from Mikobot import function
14
-
15
- # <=======================================================================================================>
16
-
17
-
18
- # <================================================ FUNCTION =======================================================>
19
- # Define the command handler for the "/pickwinner" command
20
- async def pick_winner(update: Update, context: ContextTypes.DEFAULT_TYPE):
21
- # Get the list of participants
22
- participants = context.args
23
-
24
- if participants:
25
- # Select a random winner
26
- winner = random.choice(participants)
27
-
28
- # Send the winner as a reply
29
- await update.message.reply_text(f"🎉 The winner is: {winner}")
30
- else:
31
- # If no participants are provided
32
- await update.message.reply_text("Please provide a list of participants.")
33
-
34
-
35
- # Define the command handler for the "/hyperlink" command
36
- async def hyperlink_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
37
- args = context.args
38
- if len(args) >= 2:
39
- text = " ".join(args[:-1])
40
- link = args[-1]
41
- hyperlink = f"[{text}]({link})"
42
- await update.message.reply_text(
43
- text=hyperlink, parse_mode="Markdown", disable_web_page_preview=True
44
- )
45
- else:
46
- match = re.search(r"/hyperlink ([^\s]+) (.+)", update.message.text)
47
- if match:
48
- text = match.group(1)
49
- link = match.group(2)
50
- hyperlink = f"[{text}]({link})"
51
- await update.message.reply_text(
52
- text=hyperlink, parse_mode=ParseMode.HTML, disable_web_page_preview=True
53
- )
54
- else:
55
- await update.message.reply_text(
56
- "❌ Invalid format! Please use the format: /hyperlink <text> <link>."
57
- )
58
-
59
-
60
- # <================================================ HANDLER =======================================================>
61
- function(CommandHandler("pickwinner", pick_winner, block=False))
62
- function(CommandHandler("hyperlink", hyperlink_command, block=False))
63
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/imagegen.py DELETED
@@ -1,132 +0,0 @@
1
- # CREATED BY: https://t.me/O_oKarma
2
- # API CREDITS: @Qewertyy
3
- # PROVIDED BY: https://github.com/Team-ProjectCodeX
4
-
5
- # <============================================== IMPORTS =========================================================>
6
- import asyncio
7
-
8
- import aiohttp
9
- from telethon import events
10
-
11
- from Mikobot import tbot as client
12
-
13
- # <=======================================================================================================>
14
-
15
- BASE_URL = "https://lexica.qewertyy.me"
16
- SESSION_HEADERS = {"Host": "lexica.qewertyy.me"}
17
-
18
-
19
- # <=============================================== CLASS + FUNCTION ========================================================>
20
- class AsyncClient:
21
- def __init__(self):
22
- self.url = BASE_URL
23
- self.session = aiohttp.ClientSession()
24
-
25
- async def generate(self, model_id, prompt, negative_prompt):
26
- data = {
27
- "model_id": model_id,
28
- "prompt": prompt,
29
- "negative_prompt": negative_prompt if negative_prompt else "",
30
- "num_images": 1,
31
- }
32
- try:
33
- async with self.session.post(
34
- f"{self.url}/models/inference", data=data, headers=SESSION_HEADERS
35
- ) as resp:
36
- return await resp.json()
37
- except Exception as e:
38
- print(f"Request failed: {str(e)}")
39
-
40
- async def get_images(self, task_id, request_id):
41
- data = {"task_id": task_id, "request_id": request_id}
42
- try:
43
- async with self.session.post(
44
- f"{self.url}/models/inference/task", data=data, headers=SESSION_HEADERS
45
- ) as resp:
46
- return await resp.json()
47
- except Exception as e:
48
- print(f"Request failed: {str(e)}")
49
-
50
-
51
- async def generate_image_handler(event, model_id):
52
- command_parts = event.text.split(" ", 1)
53
- if len(command_parts) < 2:
54
- await event.reply("Please provide a prompt.")
55
- return
56
-
57
- prompt = command_parts[1]
58
- negative_prompt = ""
59
-
60
- # Send the initial "Generating your image, wait sometime" message
61
- reply_message = await event.reply("Generating your image, please wait...")
62
-
63
- client = AsyncClient()
64
- response = await client.generate(model_id, prompt, negative_prompt)
65
- task_id = response["task_id"]
66
- request_id = response["request_id"]
67
-
68
- while True:
69
- generated_images = await client.get_images(task_id, request_id)
70
-
71
- if "img_urls" in generated_images:
72
- for img_url in generated_images["img_urls"]:
73
- # Delete the initial reply message
74
- await reply_message.delete()
75
-
76
- # Send the generated image
77
- await event.reply(file=img_url)
78
- break # Exit the loop when images are available
79
- else:
80
- # Wait for a few seconds before checking again
81
- await asyncio.sleep(5)
82
-
83
- # Optionally, you can add a timeout to avoid an infinite loop
84
- timeout_seconds = 600 # 10 minutes (adjust as needed)
85
- if timeout_seconds <= 0:
86
- await reply_message.edit("Image generation timed out.")
87
- break
88
-
89
- timeout_seconds -= 5 # Decrement timeout by 5 seconds
90
-
91
-
92
- @client.on(events.NewMessage(pattern=r"/meinamix"))
93
- async def meinamix_handler(event):
94
- await generate_image_handler(event, model_id=2)
95
-
96
-
97
- @client.on(events.NewMessage(pattern=r"/sushi"))
98
- async def darksushi_handler(event):
99
- await generate_image_handler(event, model_id=7)
100
-
101
-
102
- @client.on(events.NewMessage(pattern=r"/meinahentai"))
103
- async def meinahentai_handler(event):
104
- await generate_image_handler(event, model_id=8)
105
-
106
-
107
- @client.on(events.NewMessage(pattern=r"/darksushimix"))
108
- async def darksushimix_handler(event):
109
- await generate_image_handler(event, model_id=9)
110
-
111
-
112
- @client.on(events.NewMessage(pattern=r"/anylora"))
113
- async def anylora_handler(event):
114
- await generate_image_handler(event, model_id=3)
115
-
116
-
117
- @client.on(events.NewMessage(pattern=r"/cetusmix"))
118
- async def cetusmix_handler(event):
119
- await generate_image_handler(event, model_id=10)
120
-
121
-
122
- @client.on(events.NewMessage(pattern=r"/darkv2"))
123
- async def darkv_handler(event):
124
- await generate_image_handler(event, model_id=14)
125
-
126
-
127
- @client.on(events.NewMessage(pattern=r"/creative"))
128
- async def creative_handler(event):
129
- await generate_image_handler(event, model_id=12)
130
-
131
-
132
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/info.py DELETED
@@ -1,221 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import os
3
- import re
4
- from html import escape
5
- from random import choice
6
-
7
- from telegram import ChatMemberAdministrator, Update
8
- from telegram.constants import ChatID, ChatType, ParseMode
9
- from telegram.error import BadRequest
10
- from telegram.ext import CommandHandler, ContextTypes
11
- from telegram.helpers import mention_html
12
-
13
- from Database.sql.approve_sql import is_approved
14
- from Infamous.karma import START_IMG
15
- from Mikobot import DEV_USERS, DRAGONS, INFOPIC, OWNER_ID, function
16
- from Mikobot.__main__ import STATS, USER_INFO
17
- from Mikobot.plugins.helper_funcs.chat_status import support_plus, dev_plus
18
- from Mikobot.plugins.users import get_user_id
19
-
20
- # <=======================================================================================================>
21
-
22
-
23
- # <================================================ FUNCTION =======================================================>
24
- async def info(update: Update, context: ContextTypes.DEFAULT_TYPE):
25
- chat = update.effective_chat
26
- message = update.effective_message
27
- args = context.args
28
- bot = context.bot
29
-
30
- def reply_with_text(text):
31
- return message.reply_text(text, parse_mode=ParseMode.HTML)
32
-
33
- head = ""
34
- premium = False
35
-
36
- reply = await reply_with_text("<code>Getting information...</code>")
37
-
38
- user_id = None
39
- user_name = None
40
-
41
- if len(args) >= 1:
42
- if args[0][0] == "@":
43
- user_name = args[0]
44
- user_id = await get_user_id(user_name)
45
-
46
- if not user_id:
47
- try:
48
- chat_obj = await bot.get_chat(user_name)
49
- userid = chat_obj.id
50
- except BadRequest:
51
- await reply_with_text(
52
- "I can't get information about this user/channel/group."
53
- )
54
- return
55
- else:
56
- userid = user_id
57
- elif len(args) >= 1 and args[0].lstrip("-").isdigit():
58
- userid = int(args[0])
59
- elif message.reply_to_message and not message.reply_to_message.forum_topic_created:
60
- if message.reply_to_message.sender_chat:
61
- userid = message.reply_to_message.sender_chat.id
62
- elif message.reply_to_message.from_user:
63
- if message.reply_to_message.from_user.id == ChatID.FAKE_CHANNEL:
64
- userid = message.reply_to_message.chat.id
65
- else:
66
- userid = message.reply_to_message.from_user.id
67
- premium = message.reply_to_message.from_user.is_premium
68
- elif not message.reply_to_message and not args:
69
- if message.from_user.id == ChatID.FAKE_CHANNEL:
70
- userid = message.sender_chat.id
71
- else:
72
- userid = message.from_user.id
73
- premium = message.from_user.is_premium
74
-
75
- try:
76
- chat_obj = await bot.get_chat(userid)
77
- except (BadRequest, UnboundLocalError):
78
- await reply_with_text("I can't get information about this user/channel/group.")
79
- return
80
-
81
- if chat_obj.type == ChatType.PRIVATE:
82
- if chat_obj.username:
83
- head = f"⇨【 <b>USER INFORMATION</b> 】⇦\n\n"
84
- if chat_obj.username.endswith("bot"):
85
- head = f"⇨【 <b>BOT INFORMATION</b> 】⇦\n\n"
86
-
87
- head += f"➲ <b>ID:</b> <code>{chat_obj.id}</code>"
88
- head += f"\n➲ <b>First Name:</b> {chat_obj.first_name}"
89
- if chat_obj.last_name:
90
- head += f"\n➲ <b>Last Name:</b> {chat_obj.last_name}"
91
- if chat_obj.username:
92
- head += f"\n➲ <b>Username:</b> @{chat_obj.username}"
93
- head += f"\n➲ <b>Permalink:</b> {mention_html(chat_obj.id, 'link')}"
94
-
95
- if chat_obj.username and not chat_obj.username.endswith("bot"):
96
- head += f"\n\n💎 <b>Premium User:</b> {premium}"
97
-
98
- if chat_obj.bio:
99
- head += f"\n\n<b>➲ Bio:</b> {chat_obj.bio}"
100
-
101
- chat_member = await chat.get_member(chat_obj.id)
102
- if isinstance(chat_member, ChatMemberAdministrator):
103
- head += f"\n➲ <b>Presence:</b> {chat_member.status}"
104
- if chat_member.custom_title:
105
- head += f"\n➲ <b>Admin Title:</b> {chat_member.custom_title}"
106
- else:
107
- head += f"\n➲ <b>Presence:</b> {chat_member.status}"
108
-
109
- if is_approved(chat.id, chat_obj.id):
110
- head += f"\n➲ <b>Approved:</b> This user is approved in this chat."
111
-
112
- disaster_level_present = False
113
-
114
- if chat_obj.id == OWNER_ID:
115
- head += "\n\n👑 <b>The disaster level of this person is My Owner.</b>"
116
- disaster_level_present = True
117
- elif chat_obj.id in DEV_USERS:
118
- head += "\n\n🐉 <b>This user is a member of Infamous Hydra.</b>"
119
- disaster_level_present = True
120
- elif chat_obj.id in DRAGONS:
121
- head += "\n\n🐲 <b>The disaster level of this person is Dragon.</b>"
122
- disaster_level_present = True
123
- if disaster_level_present:
124
- head += " [?]"
125
-
126
- for mod in USER_INFO:
127
- try:
128
- mod_info = mod.__user_info__(chat_obj.id).strip()
129
- except TypeError:
130
- mod_info = mod.__user_info__(chat_obj.id, chat.id).strip()
131
-
132
- head += "\n\n" + mod_info if mod_info else ""
133
-
134
- if chat_obj.type == ChatType.SENDER:
135
- head = f"📨 Sender Chat Information:\n"
136
- await reply_with_text("Found sender chat, getting information...")
137
- head += f"<b>ID:</b> <code>{chat_obj.id}</code>"
138
- if chat_obj.title:
139
- head += f"\n🏷️ <b>Title:</b> {chat_obj.title}"
140
- if chat_obj.username:
141
- head += f"\n📧 <b>Username:</b> @{chat_obj.username}"
142
- head += f"\n🔗 Permalink: {mention_html(chat_obj.id, 'link')}"
143
- if chat_obj.description:
144
- head += f"\n📝 <b>Description:</b> {chat_obj.description}"
145
-
146
- elif chat_obj.type == ChatType.CHANNEL:
147
- head = f"Channel Information:\n"
148
- await reply_with_text("Found channel, getting information...")
149
- head += f"<b>ID:</b> <code>{chat_obj.id}</code>"
150
- if chat_obj.title:
151
- head += f"\n<b>Title:</b> {chat_obj.title}"
152
- if chat_obj.username:
153
- head += f"\n<b>Username:</b> @{chat_obj.username}"
154
- head += f"\nPermalink: {mention_html(chat_obj.id, 'link')}"
155
- if chat_obj.description:
156
- head += f"\n<b>Description:</b> {chat_obj.description}"
157
- if chat_obj.linked_chat_id:
158
- head += f"\n<b>Linked Chat ID:</b> <code>{chat_obj.linked_chat_id}</code>"
159
-
160
- elif chat_obj.type in [ChatType.GROUP, ChatType.SUPERGROUP]:
161
- head = f"Group Information:\n"
162
- await reply_with_text("Found group, getting information...")
163
- head += f"<b>ID:</b> <code>{chat_obj.id}</code>"
164
- if chat_obj.title:
165
- head += f"\n<b>Title:</b> {chat_obj.title}"
166
- if chat_obj.username:
167
- head += f"\n<b>Username:</b> @{chat_obj.username}"
168
- head += f"\nPermalink: {mention_html(chat_obj.id, 'link')}"
169
- if chat_obj.description:
170
- head += f"\n<b>Description:</b> {chat_obj.description}"
171
-
172
- if INFOPIC:
173
- try:
174
- if chat_obj.photo:
175
- _file = await chat_obj.photo.get_big_file()
176
- await _file.download_to_drive(f"{chat_obj.id}.png")
177
- await message.reply_photo(
178
- photo=open(f"{chat_obj.id}.png", "rb"),
179
- caption=(head),
180
- parse_mode=ParseMode.HTML,
181
- )
182
- await reply.delete()
183
- os.remove(f"{chat_obj.id}.png")
184
- else:
185
- await reply_with_text(escape(head))
186
- except:
187
- await reply_with_text(escape(head))
188
-
189
-
190
- @dev_plus
191
- async def stats(update: Update, context: ContextTypes.DEFAULT_TYPE):
192
- stats = "📊 <b>Miko-Bot's Statistics:</b>\n\n" + "\n".join(
193
- [mod.__stats__() for mod in STATS]
194
- )
195
- result = re.sub(r"(\d+)", r"<code>\1</code>", stats)
196
-
197
- await update.effective_message.reply_photo(
198
- photo=str(choice(START_IMG)), caption=result, parse_mode=ParseMode.HTML
199
- )
200
-
201
-
202
- # <=================================================== HELP ====================================================>
203
-
204
-
205
- __help__ = """
206
- *Overall information about user:*
207
-
208
- » /info : Fetch information.
209
- """
210
-
211
- # <================================================ HANDLER =======================================================>
212
- STATS_HANDLER = CommandHandler(["stats", "gstats"], stats, block=False)
213
- INFO_HANDLER = CommandHandler(("info", "book"), info, block=False)
214
-
215
- function(STATS_HANDLER)
216
- function(INFO_HANDLER)
217
-
218
- __mod_name__ = "INFO"
219
- __command_list__ = ["info"]
220
- __handlers__ = [INFO_HANDLER, STATS_HANDLER]
221
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/instadl.py DELETED
@@ -1,66 +0,0 @@
1
- # SOURCE https://github.com/Team-ProjectCodeX
2
- # CREATED BY https://t.me/O_okarma
3
- # PROVIDED BY https://t.me/ProjectCodeX
4
-
5
- # <============================================== IMPORTS =========================================================>
6
- from telegram import Update
7
- from telegram.ext import CommandHandler, ContextTypes
8
-
9
- from Mikobot import function
10
- from Mikobot.state import state
11
-
12
- # <=======================================================================================================>
13
-
14
- DOWNLOADING_STICKER_ID = (
15
- "CAACAgIAAxkBAAEDv_xlJWmh2-fKRwvLywJaFeGy9wmBKgACVQADr8ZRGmTn_PAl6RC_MAQ"
16
- )
17
- API_URL = "https://karma-api2.vercel.app/instadl" # Replace with your actual API URL
18
-
19
-
20
- # <================================================ FUNCTION =======================================================>
21
- async def instadl_command_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
22
- if len(context.args) < 1:
23
- await update.message.reply_text("Usage: /instadl [Instagram URL]")
24
- return
25
-
26
- link = context.args[0]
27
- try:
28
- downloading_sticker = await update.message.reply_sticker(DOWNLOADING_STICKER_ID)
29
-
30
- # Make an asynchronous GET request to the API using httpx
31
- response = await state.get(API_URL, params={"url": link})
32
- data = response.json()
33
-
34
- # Check if the API request was successful
35
- if "content_url" in data:
36
- content_url = data["content_url"]
37
-
38
- # Determine content type from the URL
39
- content_type = "video" if "video" in content_url else "photo"
40
-
41
- # Reply with either photo or video
42
- if content_type == "photo":
43
- await update.message.reply_photo(content_url)
44
- elif content_type == "video":
45
- await update.message.reply_video(content_url)
46
- else:
47
- await update.message.reply_text("Unsupported content type.")
48
- else:
49
- await update.message.reply_text(
50
- "Unable to fetch content. Please check the Instagram URL or try with another Instagram link."
51
- )
52
-
53
- except Exception as e:
54
- print(e)
55
- await update.message.reply_text(
56
- "An error occurred while processing the request."
57
- )
58
-
59
- finally:
60
- await downloading_sticker.delete()
61
-
62
-
63
- function(
64
- CommandHandler(["ig", "instagram", "insta", "instadl"], instadl_command_handler)
65
- )
66
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/karma.py DELETED
@@ -1,182 +0,0 @@
1
- # https://github.com/Team-ProjectCodeX
2
- # UPDATED BY https://t.me/O_okarma
3
- # https://t.me/ProjectCodeX
4
-
5
- # <============================================== IMPORTS =========================================================>
6
- import asyncio
7
-
8
- from pyrogram import filters
9
-
10
- from Database.mongodb.karma_mongo import *
11
- from Mikobot import OWNER_ID, app
12
- from Mikobot.utils.can_restrict import can_restrict
13
- from Mikobot.utils.errors import capture_err
14
-
15
- # <=======================================================================================================>
16
-
17
- karma_positive_group = 3
18
- karma_negative_group = 4
19
-
20
-
21
- # <================================================ FUNCTION =======================================================>
22
- @app.on_message(
23
- filters.text
24
- & filters.group
25
- & filters.incoming
26
- & filters.reply
27
- & filters.regex(
28
- r"^(\+|\+\+|\+1|thx|tnx|ty|tq|thank you|thanx|thanks|pro|cool|good|agree|makasih|👍|\+\+ .+)$"
29
- )
30
- & ~filters.via_bot
31
- & ~filters.bot,
32
- group=karma_positive_group,
33
- )
34
- @capture_err
35
- async def upvote(_, message):
36
- if not await is_karma_on(message.chat.id):
37
- return
38
- reply_user = message.reply_to_message.from_user
39
- current_user = message.from_user
40
- if not (reply_user and current_user):
41
- return
42
- if reply_user.id == OWNER_ID:
43
- await message.reply_text("How so pro?")
44
- return
45
- if reply_user.id == current_user.id:
46
- return
47
-
48
- chat_id = message.chat.id
49
- user_id = reply_user.id
50
- user_mention = reply_user.mention
51
- current_karma = await get_karma(chat_id, await int_to_alpha(user_id))
52
- karma = current_karma["karma"] + 1 if current_karma else 1
53
- new_karma = {"karma": karma}
54
- await update_karma(chat_id, await int_to_alpha(user_id), new_karma)
55
- await message.reply_text(
56
- f"𝗜𝗻𝗰𝗿𝗲𝗺𝗲𝗻𝘁𝗲𝗱 𝗸𝗮𝗿𝗺𝗮 𝗼𝗳 {user_mention} 𝗯𝘆 1.\n**⭐️ 𝗧𝗢𝗧𝗔𝗟 𝗣𝗢𝗜𝗡𝗧𝗦:** {karma}"
57
- )
58
-
59
-
60
- @app.on_message(
61
- filters.text
62
- & filters.group
63
- & filters.incoming
64
- & filters.reply
65
- & filters.regex(r"^(-|--|-1|not cool|disagree|worst|bad|👎|-- .+)$")
66
- & ~filters.via_bot
67
- & ~filters.bot,
68
- group=karma_negative_group,
69
- )
70
- @capture_err
71
- async def downvote(_, message):
72
- if not await is_karma_on(message.chat.id):
73
- return
74
- reply_user = message.reply_to_message.from_user
75
- current_user = message.from_user
76
- if not (reply_user and current_user):
77
- return
78
- if reply_user.id == OWNER_ID:
79
- await message.reply_text("I know him, so I'm not gonna do that, baby.")
80
- return
81
- if reply_user.id == current_user.id:
82
- return
83
-
84
- user_id = reply_user.id
85
- user_mention = reply_user.mention
86
- current_karma = await get_karma(message.chat.id, await int_to_alpha(user_id))
87
- karma = current_karma["karma"] - 1 if current_karma else 0
88
- new_karma = {"karma": karma}
89
- await update_karma(message.chat.id, await int_to_alpha(user_id), new_karma)
90
- await message.reply_text(
91
- f"𝗗𝗲𝗰𝗿𝗲𝗺𝗲𝗻𝘁𝗲𝗱 𝗸𝗮𝗿𝗺𝗮 𝗼𝗳 {user_mention} 𝗯𝘆 1.\n**⭐️ 𝗧𝗢𝗧𝗔𝗟 𝗣𝗢𝗜𝗡𝗧𝗦:** {karma}"
92
- )
93
-
94
-
95
- @app.on_message(filters.command("karmastat") & filters.group)
96
- @capture_err
97
- async def karma(_, message):
98
- if not message.reply_to_message:
99
- m = await message.reply_text("Analyzing karma... This may take a while.")
100
- karma = await get_karmas(message.chat.id)
101
- if not karma:
102
- await m.edit_text("No karma in the database for this chat.")
103
- return
104
- msg = f"**🎖 𝗞𝗔𝗥𝗠𝗔 𝗟𝗜𝗦𝗧 𝗢𝗙 {message.chat.title} :**\n"
105
- limit = 0
106
- karma_dicc = {}
107
- for i in karma:
108
- user_id = await alpha_to_int(i)
109
- user_karma = karma[i]["karma"]
110
- karma_dicc[str(user_id)] = user_karma
111
- karma_arranged = dict(
112
- sorted(karma_dicc.items(), key=lambda item: item[1], reverse=True)
113
- )
114
- if not karma_dicc:
115
- await m.edit_text("No karma in the database for this chat.")
116
- return
117
- for user_idd, karma_count in karma_arranged.items():
118
- if limit > 9:
119
- break
120
- try:
121
- user = await _.get_users(int(user_idd))
122
- await asyncio.sleep(0.8)
123
- except Exception:
124
- continue
125
- first_name = user.first_name
126
- if not first_name:
127
- continue
128
- msg += f"`{karma_count}` {(first_name[0:12] + '...') if len(first_name) > 12 else first_name}\n"
129
- limit += 1
130
- await m.edit_text(msg)
131
- else:
132
- user_id = message.reply_to_message.from_user.id
133
- karma = await get_karma(message.chat.id, await int_to_alpha(user_id))
134
- karma = karma["karma"] if karma else 0
135
- await message.reply_text(f"**⭐️ 𝗧𝗢𝗧𝗔𝗟 𝗣𝗢𝗜𝗡𝗧𝗦:** {karma}")
136
-
137
-
138
- @app.on_message(filters.command("karma"))
139
- @can_restrict
140
- async def karma_toggle_xd(_, message):
141
- usage = "**Usage:**\n/karma [ON|OFF]"
142
- if len(message.command) != 2:
143
- return await message.reply_text(usage)
144
- chat_id = message.chat.id
145
- state = message.text.split(None, 1)[1].strip().lower()
146
-
147
- if state == "on":
148
- disabled = karmadb.find_one({"chat_id_toggle": chat_id})
149
- if disabled:
150
- karmadb.delete_one({"chat_id_toggle": chat_id})
151
- await message.reply_text("Enabled the karma system.")
152
- else:
153
- await message.reply_text("Karma system is already enabled.")
154
- elif state == "off":
155
- disabled = karmadb.find_one({"chat_id_toggle": chat_id})
156
- if disabled:
157
- await message.reply_text("Karma system is already disabled.")
158
- else:
159
- karmadb.insert_one({"chat_id_toggle": chat_id})
160
- await message.reply_text("Disabled the karma system.")
161
- else:
162
- await message.reply_text(usage)
163
-
164
-
165
- # <=================================================== HELP ====================================================>
166
-
167
-
168
- __mod_name__ = "KARMA"
169
- __help__ = """
170
-
171
- ➠ *UPVOTE* - Use upvote keywords like "+", "+1", "thanks", etc. to upvote a message.
172
- ➠ *DOWNVOTE* - Use downvote keywords like "-", "-1", etc. to downvote a message.
173
-
174
- ➠ *Commands*
175
-
176
- » /karmastat:- `Reply to a user to check that user's karma points`
177
-
178
- » /karmastat:- `Send without replying to any message to check karma point list of top 10`
179
-
180
- » /karma [OFF|ON] - `Enable or disable karma system in your chat.`
181
- """
182
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/log_channel.py DELETED
@@ -1,257 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from datetime import datetime
3
- from functools import wraps
4
-
5
- from telegram.constants import ChatType
6
- from telegram.ext import ContextTypes
7
-
8
- from Mikobot import function
9
- from Mikobot.plugins.helper_funcs.misc import is_module_loaded
10
-
11
- FILENAME = __name__.rsplit(".", 1)[-1]
12
-
13
- if is_module_loaded(FILENAME):
14
- from telegram import Update
15
- from telegram.constants import ParseMode
16
- from telegram.error import BadRequest, Forbidden
17
- from telegram.ext import CommandHandler, JobQueue
18
- from telegram.helpers import escape_markdown
19
-
20
- from Database.sql import log_channel_sql as sql
21
- from Mikobot import EVENT_LOGS, LOGGER, dispatcher
22
- from Mikobot.plugins.helper_funcs.chat_status import check_admin
23
-
24
- # <=======================================================================================================>
25
- # <================================================ FUNCTION =======================================================>
26
- def loggable(func):
27
- @wraps(func)
28
- async def log_action(
29
- update: Update,
30
- context: ContextTypes.DEFAULT_TYPE,
31
- job_queue: JobQueue = None,
32
- *args,
33
- **kwargs,
34
- ):
35
- if not job_queue:
36
- result = await func(update, context, *args, **kwargs)
37
- else:
38
- result = await func(update, context, job_queue, *args, **kwargs)
39
-
40
- chat = update.effective_chat
41
- message = update.effective_message
42
-
43
- if result and isinstance(result, str):
44
- datetime_fmt = "%H:%M - %d-%m-%Y"
45
- result += f"\nEvent stamp: {datetime.utcnow().strftime(datetime_fmt)}"
46
-
47
- if chat.is_forum and chat.username:
48
- result += f"\nLink: https://t.me/{chat.username}/{message.message_thread_id}/{message.message_id}"
49
-
50
- if message.chat.type == chat.SUPERGROUP and message.chat.username:
51
- result += (
52
- f"\nLink: https://t.me/{chat.username}/{message.message_id}"
53
- )
54
- log_chat = sql.get_chat_log_channel(chat.id)
55
- if log_chat:
56
- await send_log(context, log_chat, chat.id, result)
57
-
58
- return result
59
-
60
- return log_action
61
-
62
- def gloggable(func):
63
- @wraps(func)
64
- async def glog_action(
65
- update: Update, context: ContextTypes.DEFAULT_TYPE, *args, **kwargs
66
- ):
67
- result = await func(update, context, *args, **kwargs)
68
- chat = update.effective_chat
69
- message = update.effective_message
70
-
71
- if result:
72
- datetime_fmt = "%H:%M - %d-%m-%Y"
73
- result += f"\nEvent stamp: {datetime.utcnow().strftime(datetime_fmt)}"
74
- if chat.is_forum and chat.username:
75
- result += f"\nLink: https://t.me/{chat.username}/{message.message_thread_id}/{message.message_id}"
76
- elif message.chat.type == chat.SUPERGROUP and message.chat.username:
77
- result += (
78
- f"\nLink: https://t.me/{chat.username}/{message.message_id}"
79
- )
80
- log_chat = str(EVENT_LOGS)
81
- if log_chat:
82
- await send_log(context, log_chat, chat.id, result)
83
-
84
- return result
85
-
86
- return glog_action
87
-
88
- async def send_log(
89
- context: ContextTypes.DEFAULT_TYPE,
90
- log_chat_id: str,
91
- orig_chat_id: str,
92
- result: str,
93
- ):
94
- bot = context.bot
95
- try:
96
- await bot.send_message(
97
- log_chat_id,
98
- result,
99
- parse_mode=ParseMode.HTML,
100
- disable_web_page_preview=True,
101
- )
102
- except BadRequest as excp:
103
- if excp.message == "Chat not found":
104
- try:
105
- await bot.send_message(
106
- orig_chat_id,
107
- "This log channel has been deleted - unsetting.",
108
- message_thread_id=1,
109
- )
110
- except:
111
- await bot.send_message(
112
- orig_chat_id,
113
- "This log channel has been deleted - unsetting.",
114
- )
115
- sql.stop_chat_logging(orig_chat_id)
116
- else:
117
- LOGGER.warning(excp.message)
118
- LOGGER.warning(result)
119
- LOGGER.exception("Could not parse")
120
-
121
- await bot.send_message(
122
- log_chat_id,
123
- result
124
- + "\n\nFormatting has been disabled due to an unexpected error.",
125
- )
126
-
127
- @check_admin(is_user=True)
128
- async def logging(update: Update, context: ContextTypes.DEFAULT_TYPE):
129
- bot = context.bot
130
- message = update.effective_message
131
- chat = update.effective_chat
132
-
133
- log_channel = sql.get_chat_log_channel(chat.id)
134
- if log_channel:
135
- log_channel_info = await bot.get_chat(log_channel)
136
- await message.reply_text(
137
- f"This group has all its logs sent to: {escape_markdown(log_channel_info.title)} (`{log_channel}`)",
138
- parse_mode=ParseMode.MARKDOWN,
139
- )
140
-
141
- else:
142
- await message.reply_text("No log channel has been set for this group!")
143
-
144
- @check_admin(is_user=True)
145
- async def setlog(update: Update, context: ContextTypes.DEFAULT_TYPE):
146
- bot = context.bot
147
- message = update.effective_message
148
- chat = update.effective_chat
149
- if chat.type == ChatType.CHANNEL:
150
- await bot.send_message(
151
- chat.id,
152
- "Now, forward the /setlog to the group you want to tie this channel to!",
153
- )
154
-
155
- elif message.forward_from_chat:
156
- sql.set_chat_log_channel(chat.id, message.forward_from_chat.id)
157
-
158
- try:
159
- await bot.send_message(
160
- message.forward_from_chat.id,
161
- f"This channel has been set as the log channel for {chat.title or chat.first_name}.",
162
- )
163
- except Forbidden as excp:
164
- if excp.message == "Forbidden: Bot is not a member of the channel chat":
165
- if chat.is_forum:
166
- await bot.send_message(
167
- chat.id,
168
- "Successfully set log channel!",
169
- message_thread_id=message.message_thread_id,
170
- )
171
- else:
172
- await bot.send_message(chat.id, "Successfully set log channel!")
173
- else:
174
- LOGGER.exception("Error in setting the log channel.")
175
-
176
- if chat.is_forum:
177
- await bot.send_message(
178
- chat.id,
179
- "Successfully set log channel!",
180
- message_thread_id=message.message_thread_id,
181
- )
182
- else:
183
- await bot.send_message(chat.id, "Successfully set log channel!")
184
-
185
- else:
186
- await message.reply_text(
187
- "The steps to set a log channel are:\n"
188
- " - Add bot to the desired channel (as an admin!)\n"
189
- " - Send /setlog in the channel\n"
190
- " - Forward the /setlog to the group\n",
191
- )
192
-
193
- @check_admin(is_user=True)
194
- async def unsetlog(update: Update, context: ContextTypes.DEFAULT_TYPE):
195
- bot = context.bot
196
- message = update.effective_message
197
- chat = update.effective_chat
198
-
199
- log_channel = sql.stop_chat_logging(chat.id)
200
- if log_channel:
201
- await bot.send_message(
202
- log_channel,
203
- f"Channel has been unlinked from {chat.title}",
204
- )
205
- await message.reply_text("Log channel has been un-set.")
206
-
207
- else:
208
- await message.reply_text("No log channel is set yet!")
209
-
210
- def __stats__():
211
- return f"• {sql.num_logchannels()} log channels set."
212
-
213
- def __migrate__(old_chat_id, new_chat_id):
214
- sql.migrate_chat(old_chat_id, new_chat_id)
215
-
216
- async def __chat_settings__(chat_id, user_id):
217
- log_channel = sql.get_chat_log_channel(chat_id)
218
- if log_channel:
219
- log_channel_info = await dispatcher.bot.get_chat(log_channel)
220
- return f"This group has all its logs sent to: {escape_markdown(log_channel_info.title)} (`{log_channel}`)"
221
- return "No log channel is set for this group!"
222
-
223
- # <=================================================== HELP ====================================================>
224
-
225
- __help__ = """
226
- ➠ *Admins Only*:
227
-
228
- » /logchannel: Get log channel info.
229
-
230
- » /setlog: Set the log channel.
231
-
232
- » /unsetlog: Unset the log channel.
233
-
234
- ➠ *Setting the log channel is done by:*
235
- ➠ *Adding the bot to the desired channel (as an admin!)*
236
-
237
- » Sending /setlog in the channel
238
- » Forwarding the /setlog to the group
239
- """
240
-
241
- __mod_name__ = "LOG-SET"
242
-
243
- # <================================================ HANDLER =======================================================>
244
- function(CommandHandler("logchannel", logging, block=False))
245
- function(CommandHandler("setlog", setlog, block=False))
246
- function(CommandHandler("unsetlog", unsetlog, block=False))
247
-
248
- else:
249
- # run anyway if module not loaded
250
- def loggable(func):
251
- return func
252
-
253
- def gloggable(func):
254
- return func
255
-
256
-
257
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/mute.py DELETED
@@ -1,261 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import html
3
- from typing import Union
4
-
5
- from telegram import Bot, Chat, ChatMember, ChatPermissions, Update
6
- from telegram.constants import ParseMode
7
- from telegram.error import BadRequest
8
- from telegram.ext import CommandHandler, ContextTypes
9
- from telegram.helpers import mention_html
10
-
11
- from Mikobot import LOGGER, function
12
- from Mikobot.plugins.helper_funcs.chat_status import (
13
- check_admin,
14
- connection_status,
15
- is_user_admin,
16
- )
17
- from Mikobot.plugins.helper_funcs.extraction import extract_user, extract_user_and_text
18
- from Mikobot.plugins.helper_funcs.string_handling import extract_time
19
- from Mikobot.plugins.log_channel import loggable
20
-
21
- # <=======================================================================================================>
22
-
23
-
24
- # <================================================ FUNCTION =======================================================>
25
- async def check_user(user_id: int, bot: Bot, chat: Chat) -> Union[str, None]:
26
- if not user_id:
27
- reply = "You don't seem to be referring to a user or the ID specified is incorrect.."
28
- return reply
29
-
30
- try:
31
- member = await chat.get_member(user_id)
32
- except BadRequest as excp:
33
- if excp.message == "User not found":
34
- reply = "I can't seem to find this user"
35
- return reply
36
- else:
37
- raise
38
-
39
- if user_id == bot.id:
40
- reply = "I'm not gonna MUTE myself, How high are you?"
41
- return reply
42
-
43
- if await is_user_admin(chat, user_id, member):
44
- reply = "Sorry can't do that, this user is admin here."
45
- return reply
46
-
47
- return None
48
-
49
-
50
- @connection_status
51
- @loggable
52
- @check_admin(permission="can_restrict_members", is_both=True)
53
- async def mute(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str:
54
- bot = context.bot
55
- args = context.args
56
-
57
- chat = update.effective_chat
58
- user = update.effective_user
59
- message = update.effective_message
60
-
61
- user_id, reason = await extract_user_and_text(message, context, args)
62
- reply = await check_user(user_id, bot, chat)
63
-
64
- if reply:
65
- await message.reply_text(reply)
66
- return ""
67
-
68
- member = await chat.get_member(user_id)
69
-
70
- log = (
71
- f"<b>{html.escape(chat.title)}:</b>\n"
72
- f"#MUTE\n"
73
- f"<b>Admin:</b> {mention_html(user.id, user.first_name)}\n"
74
- f"<b>User:</b> {mention_html(member.user.id, member.user.first_name)}"
75
- )
76
-
77
- if reason:
78
- log += f"\n<b>Reason:</b> {reason}"
79
-
80
- if member.status in [ChatMember.RESTRICTED, ChatMember.MEMBER]:
81
- chat_permissions = ChatPermissions(can_send_messages=False)
82
- await bot.restrict_chat_member(chat.id, user_id, chat_permissions)
83
- await bot.sendMessage(
84
- chat.id,
85
- f"Muted <b>{html.escape(member.user.first_name)}</b> with no expiration date!",
86
- parse_mode=ParseMode.HTML,
87
- message_thread_id=message.message_thread_id if chat.is_forum else None,
88
- )
89
- return log
90
-
91
- else:
92
- await message.reply_text("This user is already muted!")
93
-
94
- return ""
95
-
96
-
97
- @connection_status
98
- @loggable
99
- @check_admin(permission="can_restrict_members", is_both=True)
100
- async def unmute(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str:
101
- bot, args = context.bot, context.args
102
- chat = update.effective_chat
103
- user = update.effective_user
104
- message = update.effective_message
105
-
106
- user_id = await extract_user(message, context, args)
107
- if not user_id:
108
- await message.reply_text(
109
- "You'll need to either give me a username to unmute, or reply to someone to be unmuted.",
110
- )
111
- return ""
112
-
113
- member = await chat.get_member(int(user_id))
114
-
115
- if member.status not in [ChatMember.LEFT, ChatMember.BANNED]:
116
- if member.status != ChatMember.RESTRICTED:
117
- await message.reply_text("This user already has the right to speak.")
118
- else:
119
- chat_permissions = ChatPermissions(
120
- can_send_messages=True,
121
- can_invite_users=True,
122
- can_pin_messages=True,
123
- can_send_polls=True,
124
- can_change_info=True,
125
- can_send_media_messages=True,
126
- can_send_other_messages=True,
127
- can_add_web_page_previews=True,
128
- )
129
- try:
130
- await bot.restrict_chat_member(chat.id, int(user_id), chat_permissions)
131
- except BadRequest:
132
- pass
133
- await bot.sendMessage(
134
- chat.id,
135
- f"I shall allow <b>{html.escape(member.user.first_name)}</b> to text!",
136
- parse_mode=ParseMode.HTML,
137
- message_thread_id=message.message_thread_id if chat.is_forum else None,
138
- )
139
- return (
140
- f"<b>{html.escape(chat.title)}:</b>\n"
141
- f"#UNMUTE\n"
142
- f"<b>Admin:</b> {mention_html(user.id, user.first_name)}\n"
143
- f"<b>User:</b> {mention_html(member.user.id, member.user.first_name)}"
144
- )
145
- else:
146
- await message.reply_text(
147
- "This user isn't even in the chat, unmuting them won't make them talk more than they "
148
- "already do!",
149
- )
150
-
151
- return ""
152
-
153
-
154
- @connection_status
155
- @loggable
156
- @check_admin(permission="can_restrict_members", is_both=True)
157
- async def temp_mute(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str:
158
- bot, args = context.bot, context.args
159
- chat = update.effective_chat
160
- user = update.effective_user
161
- message = update.effective_message
162
-
163
- user_id, reason = await extract_user_and_text(message, context, args)
164
- reply = await check_user(user_id, bot, chat)
165
-
166
- if reply:
167
- await message.reply_text(reply)
168
- return ""
169
-
170
- member = await chat.get_member(user_id)
171
-
172
- if not reason:
173
- await message.reply_text("You haven't specified a time to mute this user for!")
174
- return ""
175
-
176
- split_reason = reason.split(None, 1)
177
-
178
- time_val = split_reason[0].lower()
179
- if len(split_reason) > 1:
180
- reason = split_reason[1]
181
- else:
182
- reason = ""
183
-
184
- mutetime = await extract_time(message, time_val)
185
-
186
- if not mutetime:
187
- return ""
188
-
189
- log = (
190
- f"<b>{html.escape(chat.title)}:</b>\n"
191
- f"#TEMP MUTED\n"
192
- f"<b>Admin:</b> {mention_html(user.id, user.first_name)}\n"
193
- f"<b>User:</b> {mention_html(member.user.id, member.user.first_name)}\n"
194
- f"<b>Time:</b> {time_val}"
195
- )
196
- if reason:
197
- log += f"\n<b>Reason:</b> {reason}"
198
-
199
- try:
200
- if member.status in [ChatMember.RESTRICTED, ChatMember.MEMBER]:
201
- chat_permissions = ChatPermissions(can_send_messages=False)
202
- await bot.restrict_chat_member(
203
- chat.id,
204
- user_id,
205
- chat_permissions,
206
- until_date=mutetime,
207
- )
208
- await bot.sendMessage(
209
- chat.id,
210
- f"Muted <b>{html.escape(member.user.first_name)}</b> for {time_val}!",
211
- parse_mode=ParseMode.HTML,
212
- message_thread_id=message.message_thread_id if chat.is_forum else None,
213
- )
214
- return log
215
- else:
216
- await message.reply_text("This user is already muted.")
217
-
218
- except BadRequest as excp:
219
- if excp.message == "Reply message not found":
220
- # Do not reply
221
- await message.reply_text(f"Muted for {time_val}!", quote=False)
222
- return log
223
- else:
224
- LOGGER.warning(update)
225
- LOGGER.exception(
226
- "ERROR muting user %s in chat %s (%s) due to %s",
227
- user_id,
228
- chat.title,
229
- chat.id,
230
- excp.message,
231
- )
232
- await message.reply_text("Well damn, I can't mute that user.")
233
-
234
- return ""
235
-
236
-
237
- # <=================================================== HELP ====================================================>
238
-
239
-
240
- __help__ = """
241
- ➠ *Admins only:*
242
-
243
- » /mute <userhandle>: silences a user. Can also be used as a reply, muting the replied to user.
244
-
245
- » /tmute <userhandle> x(m/h/d): mutes a user for x time. (via handle, or reply). `m` = `minutes`, `h` = `hours`, `d` = `days`.
246
-
247
- » /unmute <userhandle>: unmutes a user. Can also be used as a reply, muting the replied to user.
248
- """
249
-
250
- # <================================================ HANDLER =======================================================>
251
- MUTE_HANDLER = CommandHandler("mute", mute, block=False)
252
- UNMUTE_HANDLER = CommandHandler("unmute", unmute, block=False)
253
- TEMPMUTE_HANDLER = CommandHandler(["tmute", "tempmute"], temp_mute, block=False)
254
-
255
- function(MUTE_HANDLER)
256
- function(UNMUTE_HANDLER)
257
- function(TEMPMUTE_HANDLER)
258
-
259
- __mod_name__ = "MUTE"
260
- __handlers__ = [MUTE_HANDLER, UNMUTE_HANDLER, TEMPMUTE_HANDLER]
261
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/nekomode.py DELETED
@@ -1,131 +0,0 @@
1
- # SOURCE https://github.com/Team-ProjectCodeX
2
- # CREATED BY https://t.me/O_okarma
3
- # PROVIDED BY https://t.me/ProjectCodeX
4
- # NEKOS
5
-
6
- # <============================================== IMPORTS =========================================================>
7
- import nekos
8
- from telethon import events
9
-
10
- from Database.mongodb.toggle_mongo import is_nekomode_on, nekomode_off, nekomode_on
11
- from Mikobot import tbot
12
- from Mikobot.state import state # Import the state function
13
-
14
- # <=======================================================================================================>
15
-
16
- url_sfw = "https://api.waifu.pics/sfw/"
17
-
18
- allowed_commands = [
19
- "waifu",
20
- "neko",
21
- "shinobu",
22
- "megumin",
23
- "bully",
24
- "cuddle",
25
- "cry",
26
- "hug",
27
- "awoo",
28
- "kiss",
29
- "lick",
30
- "pat",
31
- "smug",
32
- "bonk",
33
- "yeet",
34
- "blush",
35
- "smile",
36
- "spank",
37
- "wave",
38
- "highfive",
39
- "handhold",
40
- "nom",
41
- "bite",
42
- "glomp",
43
- "slap",
44
- "hTojiy",
45
- "wink",
46
- "poke",
47
- "dance",
48
- "cringe",
49
- "tickle",
50
- ]
51
-
52
-
53
- # <================================================ FUNCTION =======================================================>
54
- @tbot.on(events.NewMessage(pattern="/wallpaper"))
55
- async def wallpaper(event):
56
- chat_id = event.chat_id
57
- nekomode_status = await is_nekomode_on(chat_id)
58
- if nekomode_status:
59
- target = "wallpaper"
60
- img_url = nekos.img(
61
- target
62
- ) # Replace nekos.img(target) with the correct function call
63
- await event.reply(file=img_url)
64
-
65
-
66
- @tbot.on(events.NewMessage(pattern="/nekomode on"))
67
- async def enable_nekomode(event):
68
- chat_id = event.chat_id
69
- await nekomode_on(chat_id)
70
- await event.reply("Nekomode has been enabled.")
71
-
72
-
73
- @tbot.on(events.NewMessage(pattern="/nekomode off"))
74
- async def disable_nekomode(event):
75
- chat_id = event.chat_id
76
- await nekomode_off(chat_id)
77
- await event.reply("Nekomode has been disabled.")
78
-
79
-
80
- @tbot.on(events.NewMessage(pattern=r"/(?:{})".format("|".join(allowed_commands))))
81
- async def nekomode_commands(event):
82
- chat_id = event.chat_id
83
- nekomode_status = await is_nekomode_on(chat_id)
84
- if nekomode_status:
85
- target = event.raw_text[1:].lower() # Remove the slash before the command
86
- if target in allowed_commands:
87
- url = f"{url_sfw}{target}"
88
-
89
- response = await state.get(url)
90
- result = response.json()
91
- animation_url = result["url"]
92
-
93
- # Send animation
94
- await event.respond(file=animation_url)
95
-
96
-
97
- __help__ = """
98
- *✨ Sends fun Gifs/Images*
99
-
100
- ➥ /nekomode on : Enables fun neko mode.
101
- ➥ /nekomode off : Disables fun neko mode
102
-
103
- » /bully: sends random bully gifs.
104
- » /neko: sends random neko gifs.
105
- » /wallpaper: sends random wallpapers.
106
- » /highfive: sends random highfive gifs.
107
- » /tickle: sends random tickle GIFs.
108
- » /wave: sends random wave GIFs.
109
- » /smile: sends random smile GIFs.
110
- » /feed: sends random feeding GIFs.
111
- » /blush: sends random blush GIFs.
112
- » /avatar: sends random avatar stickers.
113
- » /waifu: sends random waifu stickers.
114
- » /kiss: sends random kissing GIFs.
115
- » /cuddle: sends random cuddle GIFs.
116
- » /cry: sends random cry GIFs.
117
- » /bonk: sends random cuddle GIFs.
118
- » /smug: sends random smug GIFs.
119
- » /slap: sends random slap GIFs.
120
- » /hug: get hugged or hug a user.
121
- » /pat: pats a user or get patted.
122
- » /spank: sends a random spank gif.
123
- » /dance: sends a random dance gif.
124
- » /poke: sends a random poke gif.
125
- » /wink: sends a random wink gif.
126
- » /bite: sends random bite GIFs.
127
- » /handhold: sends random handhold GIFs.
128
- """
129
-
130
- __mod_name__ = "NEKO"
131
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/notes.py DELETED
@@ -1,629 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import ast
3
- import random
4
- import re
5
- from io import BytesIO
6
-
7
- from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Message, Update
8
- from telegram.constants import MessageLimit, ParseMode
9
- from telegram.error import BadRequest
10
- from telegram.ext import (
11
- CallbackQueryHandler,
12
- CommandHandler,
13
- ContextTypes,
14
- MessageHandler,
15
- filters,
16
- )
17
- from telegram.helpers import escape_markdown, mention_markdown
18
-
19
- import Database.sql.notes_sql as sql
20
- from Mikobot import DRAGONS, LOGGER, MESSAGE_DUMP, SUPPORT_CHAT, dispatcher, function
21
- from Mikobot.plugins.disable import DisableAbleCommandHandler
22
- from Mikobot.plugins.helper_funcs.chat_status import check_admin, connection_status
23
- from Mikobot.plugins.helper_funcs.misc import build_keyboard, revert_buttons
24
- from Mikobot.plugins.helper_funcs.msg_types import get_note_type
25
- from Mikobot.plugins.helper_funcs.string_handling import (
26
- escape_invalid_curly_brackets,
27
- markdown_to_html,
28
- )
29
-
30
- from .cust_filters import MessageHandlerChecker
31
-
32
- # <=======================================================================================================>
33
-
34
- FILE_MATCHER = re.compile(r"^###file_id(!photo)?###:(.*?)(?:\s|$)")
35
- STICKER_MATCHER = re.compile(r"^###sticker(!photo)?###:")
36
- BUTTON_MATCHER = re.compile(r"^###button(!photo)?###:(.*?)(?:\s|$)")
37
- MYFILE_MATCHER = re.compile(r"^###file(!photo)?###:")
38
- MYPHOTO_MATCHER = re.compile(r"^###photo(!photo)?###:")
39
- MYAUDIO_MATCHER = re.compile(r"^###audio(!photo)?###:")
40
- MYVOICE_MATCHER = re.compile(r"^###voice(!photo)?###:")
41
- MYVIDEO_MATCHER = re.compile(r"^###video(!photo)?###:")
42
- MYVIDEONOTE_MATCHER = re.compile(r"^###video_note(!photo)?###:")
43
-
44
- ENUM_FUNC_MAP = {
45
- sql.Types.TEXT.value: dispatcher.bot.send_message,
46
- sql.Types.BUTTON_TEXT.value: dispatcher.bot.send_message,
47
- sql.Types.STICKER.value: dispatcher.bot.send_sticker,
48
- sql.Types.DOCUMENT.value: dispatcher.bot.send_document,
49
- sql.Types.PHOTO.value: dispatcher.bot.send_photo,
50
- sql.Types.AUDIO.value: dispatcher.bot.send_audio,
51
- sql.Types.VOICE.value: dispatcher.bot.send_voice,
52
- sql.Types.VIDEO.value: dispatcher.bot.send_video,
53
- }
54
-
55
-
56
- # <================================================ FUNCTION =======================================================>
57
- async def get(
58
- update: Update,
59
- context: ContextTypes.DEFAULT_TYPE,
60
- notename,
61
- show_none=True,
62
- no_format=False,
63
- ):
64
- bot = context.bot
65
- chat_id = update.effective_message.chat.id
66
- chat = update.effective_chat
67
- note_chat_id = update.effective_chat.id
68
- note = sql.get_note(note_chat_id, notename)
69
- message = update.effective_message # type: Optional[Message]
70
-
71
- if note:
72
- if MessageHandlerChecker.check_user(update.effective_user.id):
73
- return
74
- # If we're replying to a message, reply to that message (unless it's an error)
75
- if (
76
- message.reply_to_message
77
- and not message.reply_to_message.forum_topic_created
78
- ):
79
- reply_id = message.reply_to_message.message_id
80
- else:
81
- reply_id = message.message_id
82
- if note.is_reply:
83
- if MESSAGE_DUMP:
84
- try:
85
- await bot.forward_message(
86
- chat_id=chat_id,
87
- from_chat_id=MESSAGE_DUMP,
88
- message_id=note.value,
89
- )
90
- except BadRequest as excp:
91
- if excp.message == "Message to forward not found":
92
- await message.reply_text(
93
- "This message seems to have been lost - I'll remove it "
94
- "from your notes list.",
95
- )
96
- sql.rm_note(note_chat_id, notename)
97
- else:
98
- raise
99
- else:
100
- try:
101
- await bot.forward_message(
102
- chat_id=chat_id,
103
- from_chat_id=chat_id,
104
- message_id=markdown_to_html(note.value),
105
- )
106
- except BadRequest as excp:
107
- if excp.message == "Message to forward not found":
108
- await message.reply_text(
109
- "Looks like the original sender of this note has deleted "
110
- "their message - sorry! Get your bot admin to start using a "
111
- "message dump to avoid this. I'll remove this note from "
112
- "your saved notes.",
113
- )
114
- sql.rm_note(note_chat_id, notename)
115
- else:
116
- raise
117
- else:
118
- VALID_NOTE_FORMATTERS = [
119
- "first",
120
- "last",
121
- "fullname",
122
- "username",
123
- "id",
124
- "chatname",
125
- "mention",
126
- ]
127
- valid_format = escape_invalid_curly_brackets(
128
- note.value,
129
- VALID_NOTE_FORMATTERS,
130
- )
131
- if valid_format:
132
- if not no_format:
133
- if "%%%" in valid_format:
134
- split = valid_format.split("%%%")
135
- if all(split):
136
- text = random.choice(split)
137
- else:
138
- text = valid_format
139
- else:
140
- text = valid_format
141
- else:
142
- text = valid_format
143
- text = text.format(
144
- first=escape_markdown(message.from_user.first_name),
145
- last=escape_markdown(
146
- message.from_user.last_name or message.from_user.first_name,
147
- ),
148
- fullname=escape_markdown(
149
- " ".join(
150
- [message.from_user.first_name, message.from_user.last_name]
151
- if message.from_user.last_name
152
- else [message.from_user.first_name],
153
- ),
154
- ),
155
- username="@" + message.from_user.username
156
- if message.from_user.username
157
- else mention_markdown(
158
- message.from_user.id,
159
- message.from_user.first_name,
160
- ),
161
- mention=mention_markdown(
162
- message.from_user.id,
163
- message.from_user.first_name,
164
- ),
165
- chatname=escape_markdown(
166
- message.chat.title
167
- if message.chat.type != "private"
168
- else message.from_user.first_name,
169
- ),
170
- id=message.from_user.id,
171
- )
172
- else:
173
- text = ""
174
-
175
- keyb = []
176
- parseMode = ParseMode.HTML
177
- buttons = sql.get_buttons(note_chat_id, notename)
178
- if no_format:
179
- parseMode = None
180
- text += revert_buttons(buttons)
181
- else:
182
- keyb = build_keyboard(buttons)
183
-
184
- keyboard = InlineKeyboardMarkup(keyb)
185
-
186
- try:
187
- if note.msgtype in (sql.Types.BUTTON_TEXT, sql.Types.TEXT):
188
- await bot.send_message(
189
- chat_id,
190
- markdown_to_html(text),
191
- reply_to_message_id=reply_id,
192
- parse_mode=parseMode,
193
- disable_web_page_preview=True,
194
- reply_markup=keyboard,
195
- message_thread_id=message.message_thread_id
196
- if chat.is_forum
197
- else None,
198
- )
199
- else:
200
- await ENUM_FUNC_MAP[note.msgtype](
201
- chat_id,
202
- note.file,
203
- caption=markdown_to_html(text),
204
- reply_to_message_id=reply_id,
205
- parse_mode=parseMode,
206
- disable_web_page_preview=True,
207
- reply_markup=keyboard,
208
- message_thread_id=message.message_thread_id
209
- if chat.is_forum
210
- else None,
211
- )
212
-
213
- except BadRequest as excp:
214
- if excp.message == "Entity_mention_user_invalid":
215
- await message.reply_text(
216
- "Looks like you tried to mention someone I've never seen before. If you really "
217
- "want to mention them, forward one of their messages to me, and I'll be able "
218
- "to tag them!",
219
- )
220
- elif FILE_MATCHER.match(note.value):
221
- await message.reply_text(
222
- "This note was an incorrectly imported file from another bot - I can't use "
223
- "it. If you really need it, you'll have to save it again. In "
224
- "the meantime, I'll remove it from your notes list.",
225
- )
226
- sql.rm_note(note_chat_id, notename)
227
- else:
228
- await message.reply_text(
229
- "This note could not be sent, as it is incorrectly formatted. Ask in "
230
- f"@{SUPPORT_CHAT} if you can't figure out why!",
231
- )
232
- LOGGER.exception(
233
- "Could not parse message #%s in chat %s",
234
- notename,
235
- str(note_chat_id),
236
- )
237
- LOGGER.warning("Message was: %s", str(note.value))
238
- return
239
- elif show_none:
240
- await message.reply_text("This note doesn't exist")
241
-
242
-
243
- @connection_status
244
- async def cmd_get(update: Update, context: ContextTypes.DEFAULT_TYPE):
245
- bot, args = context.bot, context.args
246
- if len(args) >= 2 and args[1].lower() == "noformat":
247
- await get(update, context, args[0].lower(), show_none=True, no_format=True)
248
- elif len(args) >= 1:
249
- await get(update, context, args[0].lower(), show_none=True)
250
- else:
251
- await update.effective_message.reply_text("Get rekt")
252
-
253
-
254
- @connection_status
255
- async def hash_get(update: Update, context: ContextTypes.DEFAULT_TYPE):
256
- message = update.effective_message.text
257
- fst_word = message.split()[0]
258
- no_hash = fst_word[1:].lower()
259
- await get(update, context, no_hash, show_none=False)
260
-
261
-
262
- @connection_status
263
- async def slash_get(update: Update, context: ContextTypes.DEFAULT_TYPE):
264
- message, chat_id = update.effective_message.text, update.effective_chat.id
265
- no_slash = message[1:]
266
- note_list = sql.get_all_chat_notes(chat_id)
267
-
268
- try:
269
- noteid = note_list[int(no_slash) - 1]
270
- note_name = str(noteid).strip(">").split()[1]
271
- await get(update, context, note_name, show_none=False)
272
- except IndexError:
273
- await update.effective_message.reply_text("Wrong Note ID 😾")
274
-
275
-
276
- @connection_status
277
- @check_admin(is_user=True)
278
- async def save(update: Update, context: ContextTypes.DEFAULT_TYPE):
279
- chat_id = update.effective_chat.id
280
- msg = update.effective_message # type: Optional[Message]
281
- if len(context.args) < 1:
282
- await msg.reply_text("You should give the note a name.")
283
- return
284
-
285
- note_name, text, data_type, content, buttons = get_note_type(msg)
286
- note_name = note_name.lower()
287
- if data_type is None:
288
- await msg.reply_text("Dude, there's no note content")
289
- return
290
-
291
- sql.add_note_to_db(
292
- chat_id,
293
- note_name,
294
- text,
295
- data_type,
296
- buttons=buttons,
297
- file=content,
298
- )
299
-
300
- await msg.reply_text(
301
- f"Yas! Added `{note_name}`.\nGet it with /get `{note_name}`, or `#{note_name}`",
302
- parse_mode=ParseMode.MARKDOWN,
303
- )
304
-
305
- if (
306
- msg.reply_to_message
307
- and msg.reply_to_message.from_user.is_bot
308
- and not msg.reply_to_message.forum_topic_created
309
- ):
310
- if text:
311
- await msg.reply_text(
312
- "Seems like you're trying to save a message from a bot. Unfortunately, "
313
- "bots can't forward bot messages, so I can't save the exact message. "
314
- "\nI'll save all the text I can, but if you want more, you'll have to "
315
- "forward the message yourself, and then save it.",
316
- )
317
- else:
318
- await msg.reply_text(
319
- "Bots are kinda handicapped by telegram, making it hard for bots to "
320
- "interact with other bots, so I can't save this message "
321
- "like I usually would - do you mind forwarding it and "
322
- "then saving that new message? Thanks!",
323
- )
324
- return
325
-
326
-
327
- @connection_status
328
- @check_admin(is_user=True)
329
- async def clear(update: Update, context: ContextTypes.DEFAULT_TYPE):
330
- args = context.args
331
- chat_id = update.effective_chat.id
332
- if len(args) >= 1:
333
- notename = args[0].lower()
334
-
335
- if sql.rm_note(chat_id, notename):
336
- await update.effective_message.reply_text("Successfully removed note.")
337
- else:
338
- await update.effective_message.reply_text(
339
- "That's not a note in my database!"
340
- )
341
-
342
-
343
- async def clearall(update: Update, context: ContextTypes.DEFAULT_TYPE):
344
- chat = update.effective_chat
345
- user = update.effective_user
346
- member = await chat.get_member(user.id)
347
- if member.status != "creator" and user.id not in DRAGONS:
348
- await update.effective_message.reply_text(
349
- "Only the chat owner can clear all notes at once.",
350
- )
351
- else:
352
- buttons = InlineKeyboardMarkup(
353
- [
354
- [
355
- InlineKeyboardButton(
356
- text="Delete all notes",
357
- callback_data="notes_rmall",
358
- ),
359
- ],
360
- [InlineKeyboardButton(text="Cancel", callback_data="notes_cancel")],
361
- ],
362
- )
363
- await update.effective_message.reply_text(
364
- f"Are you sure you would like to clear ALL notes in {chat.title}? This action cannot be undone.",
365
- reply_markup=buttons,
366
- parse_mode=ParseMode.MARKDOWN,
367
- )
368
-
369
-
370
- async def clearall_btn(update: Update, context: ContextTypes.DEFAULT_TYPE):
371
- query = update.callback_query
372
- chat = update.effective_chat
373
- message = update.effective_message
374
- member = await chat.get_member(query.from_user.id)
375
- if query.data == "notes_rmall":
376
- if member.status == "creator" or query.from_user.id in DRAGONS:
377
- note_list = sql.get_all_chat_notes(chat.id)
378
- try:
379
- for notename in note_list:
380
- note = notename.name.lower()
381
- sql.rm_note(chat.id, note)
382
- await message.edit_text("Deleted all notes.")
383
- except BadRequest:
384
- return
385
-
386
- if member.status == "administrator":
387
- await query.answer("Only owner of the chat can do this.")
388
-
389
- if member.status == "member":
390
- await query.answer("You need to be admin to do this.")
391
- elif query.data == "notes_cancel":
392
- if member.status == "creator" or query.from_user.id in DRAGONS:
393
- await message.edit_text("Clearing of all notes has been cancelled.")
394
- return
395
- if member.status == "administrator":
396
- await query.answer("Only owner of the chat can do this.")
397
- if member.status == "member":
398
- await query.answer("You need to be admin to do this.")
399
-
400
-
401
- @connection_status
402
- async def list_notes(update: Update, context: ContextTypes.DEFAULT_TYPE):
403
- chat_id = update.effective_chat.id
404
- note_list = sql.get_all_chat_notes(chat_id)
405
- notes = len(note_list) + 1
406
- msg = "Get note by `/notenumber` or `#notename` \n\n *ID* *Note* \n"
407
- for note_id, note in zip(range(1, notes), note_list):
408
- if note_id < 10:
409
- note_name = f"`{note_id:2}.` `#{(note.name.lower())}`\n"
410
- else:
411
- note_name = f"`{note_id}.` `#{(note.name.lower())}`\n"
412
- if len(msg) + len(note_name) > MessageLimit.MAX_TEXT_LENGTH:
413
- await update.effective_message.reply_text(
414
- msg, parse_mode=ParseMode.MARKDOWN
415
- )
416
- msg = ""
417
- msg += note_name
418
-
419
- if not note_list:
420
- try:
421
- await update.effective_message.reply_text("No notes in this chat!")
422
- except BadRequest:
423
- await update.effective_message.reply_text(
424
- "No notes in this chat!", quote=False
425
- )
426
-
427
- elif len(msg) != 0:
428
- await update.effective_message.reply_text(msg, parse_mode=ParseMode.MARKDOWN)
429
-
430
-
431
- async def __import_data__(chat_id, data, message: Message):
432
- failures = []
433
- for notename, notedata in data.get("extra", {}).items():
434
- match = FILE_MATCHER.match(notedata)
435
- matchsticker = STICKER_MATCHER.match(notedata)
436
- matchbtn = BUTTON_MATCHER.match(notedata)
437
- matchfile = MYFILE_MATCHER.match(notedata)
438
- matchphoto = MYPHOTO_MATCHER.match(notedata)
439
- matchaudio = MYAUDIO_MATCHER.match(notedata)
440
- matchvoice = MYVOICE_MATCHER.match(notedata)
441
- matchvideo = MYVIDEO_MATCHER.match(notedata)
442
- matchvn = MYVIDEONOTE_MATCHER.match(notedata)
443
-
444
- if match:
445
- failures.append(notename)
446
- notedata = notedata[match.end() :].strip()
447
- if notedata:
448
- sql.add_note_to_db(chat_id, notename[1:], notedata, sql.Types.TEXT)
449
- elif matchsticker:
450
- content = notedata[matchsticker.end() :].strip()
451
- if content:
452
- sql.add_note_to_db(
453
- chat_id,
454
- notename[1:],
455
- notedata,
456
- sql.Types.STICKER,
457
- file=content,
458
- )
459
- elif matchbtn:
460
- parse = notedata[matchbtn.end() :].strip()
461
- notedata = parse.split("<###button###>")[0]
462
- buttons = parse.split("<###button###>")[1]
463
- buttons = ast.literal_eval(buttons)
464
- if buttons:
465
- sql.add_note_to_db(
466
- chat_id,
467
- notename[1:],
468
- notedata,
469
- sql.Types.BUTTON_TEXT,
470
- buttons=buttons,
471
- )
472
- elif matchfile:
473
- file = notedata[matchfile.end() :].strip()
474
- file = file.split("<###TYPESPLIT###>")
475
- notedata = file[1]
476
- content = file[0]
477
- if content:
478
- sql.add_note_to_db(
479
- chat_id,
480
- notename[1:],
481
- notedata,
482
- sql.Types.DOCUMENT,
483
- file=content,
484
- )
485
- elif matchphoto:
486
- photo = notedata[matchphoto.end() :].strip()
487
- photo = photo.split("<###TYPESPLIT###>")
488
- notedata = photo[1]
489
- content = photo[0]
490
- if content:
491
- sql.add_note_to_db(
492
- chat_id,
493
- notename[1:],
494
- notedata,
495
- sql.Types.PHOTO,
496
- file=content,
497
- )
498
- elif matchaudio:
499
- audio = notedata[matchaudio.end() :].strip()
500
- audio = audio.split("<###TYPESPLIT###>")
501
- notedata = audio[1]
502
- content = audio[0]
503
- if content:
504
- sql.add_note_to_db(
505
- chat_id,
506
- notename[1:],
507
- notedata,
508
- sql.Types.AUDIO,
509
- file=content,
510
- )
511
- elif matchvoice:
512
- voice = notedata[matchvoice.end() :].strip()
513
- voice = voice.split("<###TYPESPLIT###>")
514
- notedata = voice[1]
515
- content = voice[0]
516
- if content:
517
- sql.add_note_to_db(
518
- chat_id,
519
- notename[1:],
520
- notedata,
521
- sql.Types.VOICE,
522
- file=content,
523
- )
524
- elif matchvideo:
525
- video = notedata[matchvideo.end() :].strip()
526
- video = video.split("<###TYPESPLIT###>")
527
- notedata = video[1]
528
- content = video[0]
529
- if content:
530
- sql.add_note_to_db(
531
- chat_id,
532
- notename[1:],
533
- notedata,
534
- sql.Types.VIDEO,
535
- file=content,
536
- )
537
- elif matchvn:
538
- video_note = notedata[matchvn.end() :].strip()
539
- video_note = video_note.split("<###TYPESPLIT###>")
540
- notedata = video_note[1]
541
- content = video_note[0]
542
- if content:
543
- sql.add_note_to_db(
544
- chat_id,
545
- notename[1:],
546
- notedata,
547
- sql.Types.VIDEO_NOTE,
548
- file=content,
549
- )
550
- else:
551
- sql.add_note_to_db(chat_id, notename[1:], notedata, sql.Types.TEXT)
552
-
553
- if failures:
554
- with BytesIO(str.encode("\n".join(failures))) as output:
555
- output.name = "failed_imports.txt"
556
- await dispatcher.bot.send_document(
557
- chat_id,
558
- document=output,
559
- filename="failed_imports.txt",
560
- caption="These files/photos failed to import due to originating "
561
- "from another bot. This is a telegram API restriction, and can't "
562
- "be avoided. Sorry for the inconvenience!",
563
- message_thread_id=message.message_thread_id
564
- if message.chat.is_forum
565
- else None,
566
- )
567
-
568
-
569
- def __stats__():
570
- return f"• {sql.num_notes()} notes, across {sql.num_chats()} chats."
571
-
572
-
573
- def __migrate__(old_chat_id, new_chat_id):
574
- sql.migrate_chat(old_chat_id, new_chat_id)
575
-
576
-
577
- def __chat_settings__(chat_id, user_id):
578
- notes = sql.get_all_chat_notes(chat_id)
579
- return f"There are `{len(notes)}` notes in this chat."
580
-
581
-
582
- # <=================================================== HELP ====================================================>
583
-
584
-
585
- __help__ = """
586
- » /get <notename> : get the note with this notename
587
- » #<notename> : same as /get
588
- » /notes or /saved : list all saved notes in this chat
589
- » /number : Will pull the note of that number in the list
590
- ➠ If you would like to retrieve the contents of a note without any formatting, use `/get <notename> noformat`. This can \
591
- be useful when updating a current note
592
-
593
- *Admins only:*
594
- » /save <notename> <notedata> : saves notedata as a note with name notename
595
- ➠ A button can be added to a note by using standard markdown link syntax - the link should just be prepended with a \
596
- `buttonurl:` section, as such: `[somelink](buttonurl:example.com)`. Check `/markdownhelp` for more info
597
- » /save <notename> : save the replied message as a note with name notename
598
- Separate diff replies by `%%%` to get random notes
599
- ➠ *Example:*
600
- `/save notename
601
- Reply 1
602
- %%%
603
- Reply 2
604
- %%%
605
- Reply 3`
606
- » /clear <notename>: clear note with this name
607
- » /removeallnotes: removes all notes from the group
608
- ➠ *Note:* Note names are case-insensitive, and they are automatically converted to lowercase before getting saved.
609
-
610
- """
611
-
612
- __mod_name__ = "NOTES"
613
-
614
- # <================================================ HANDLER =======================================================>
615
- function(CommandHandler("get", cmd_get))
616
- function(MessageHandler(filters.Regex(r"^#[^\s]+"), hash_get, block=False))
617
- function(MessageHandler(filters.Regex(r"^/\d+$"), slash_get, block=False))
618
- function(CommandHandler("save", save, block=False))
619
- function(CommandHandler("clear", clear, block=False))
620
-
621
- function(
622
- DisableAbleCommandHandler(
623
- ["notes", "saved"], list_notes, admin_ok=True, block=False
624
- )
625
- )
626
-
627
- function(DisableAbleCommandHandler("removeallnotes", clearall, block=False))
628
- function(CallbackQueryHandler(clearall_btn, pattern=r"notes_.*", block=False))
629
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/ping.py DELETED
@@ -1,39 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import time
3
-
4
- from telegram import Update
5
- from telegram.constants import ParseMode
6
- from telegram.ext import CommandHandler, ContextTypes
7
-
8
- from Mikobot import StartTime, function
9
- from Mikobot.__main__ import get_readable_time
10
- from Mikobot.plugins.helper_funcs.chat_status import check_admin
11
-
12
- # <=======================================================================================================>
13
-
14
-
15
- # <================================================ FUNCTION =======================================================>
16
- @check_admin(only_dev=True)
17
- async def ptb_ping(update: Update, context: ContextTypes.DEFAULT_TYPE):
18
- msg = update.effective_message
19
-
20
- start_time = time.time()
21
- message = await msg.reply_text("Pining")
22
- end_time = time.time()
23
- telegram_ping = str(round((end_time - start_time) * 1000, 3)) + " ms"
24
- uptime = get_readable_time((time.time() - StartTime))
25
-
26
- await message.edit_text(
27
- "🏓 <b>PONG</b>\n\n"
28
- "<b>Time taken:</b> <code>{}</code>\n"
29
- "<b>Uptime:</b> <code>{}</code>".format(telegram_ping, uptime),
30
- parse_mode=ParseMode.HTML,
31
- )
32
-
33
-
34
- # <=======================================================================================================>
35
-
36
-
37
- # <================================================ HANDLER =======================================================>
38
- function(CommandHandler("ping", ptb_ping, block=False))
39
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/pokedex.py DELETED
@@ -1,143 +0,0 @@
1
- # SOURCE https://github.com/Team-ProjectCodeX
2
- # CREATED BY https://t.me/O_okarma
3
- # API BY https://www.github.com/SOME-1HING
4
- # PROVIDED BY https://t.me/ProjectCodeX
5
-
6
- # <============================================== IMPORTS =========================================================>
7
- from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
8
- from telegram.ext import ContextTypes, CallbackQueryHandler, CommandHandler
9
-
10
- from Mikobot import function
11
- from Mikobot.state import state
12
-
13
- # <=======================================================================================================>
14
-
15
-
16
- # <================================================ FUNCTIONS =====================================================>
17
- async def get_pokemon_info(name_or_id):
18
- try:
19
- response = await state.get(
20
- f"https://sugoi-api.vercel.app/pokemon?name={name_or_id}"
21
- )
22
- if response.status_code == 200:
23
- return response.json()
24
-
25
- response = await state.get(
26
- f"https://sugoi-api.vercel.app/pokemon?id={name_or_id}"
27
- )
28
- if response.status_code == 200:
29
- return response.json()
30
-
31
- except Exception as e:
32
- print(f"An error occurred: {str(e)}")
33
-
34
- return None
35
-
36
-
37
- async def pokedex(update: Update, context: ContextTypes.DEFAULT_TYPE):
38
- try:
39
- if context.args:
40
- name_or_id = context.args[0]
41
- pokemon_info = await get_pokemon_info(name_or_id)
42
-
43
- if pokemon_info:
44
- reply_message = (
45
- f"🐾 𝗡𝗔𝗠𝗘: {pokemon_info['name']}\n"
46
- f"•➥ 𝗜𝗗: {pokemon_info['id']}\n"
47
- f"•➥ 𝗛𝗘𝗜𝗚𝗛𝗧: {pokemon_info['height']}\n"
48
- f"•➥ 𝗪𝗘𝗜𝗚𝗛𝗧: {pokemon_info['weight']}\n"
49
- )
50
-
51
- abilities = ", ".join(
52
- ability["ability"]["name"] for ability in pokemon_info["abilities"]
53
- )
54
- reply_message += f"•➥ 𝗔𝗕𝗜𝗟𝗜𝗧𝗜𝗘𝗦: {abilities}\n"
55
-
56
- types = ", ".join(
57
- type_info["type"]["name"] for type_info in pokemon_info["types"]
58
- )
59
- reply_message += f"•➥ 𝗧𝗬𝗣𝗘𝗦: {types}\n"
60
-
61
- image_url = f"https://img.pokemondb.net/artwork/large/{pokemon_info['name']}.jpg"
62
-
63
- # Create inline buttons
64
- keyboard = [
65
- [
66
- InlineKeyboardButton(text="🔖 STATS", callback_data="stats"),
67
- InlineKeyboardButton(text="⚜️ MOVES", callback_data="moves"),
68
- ]
69
- ]
70
-
71
- reply_markup = InlineKeyboardMarkup(keyboard)
72
-
73
- await update.message.reply_photo(
74
- photo=image_url,
75
- caption=reply_message,
76
- reply_markup=reply_markup,
77
- )
78
- else:
79
- await update.message.reply_text("Pokemon not found.")
80
- else:
81
- await update.message.reply_text("Please provide a Pokemon name or ID.")
82
- except Exception as e:
83
- await update.message.reply_text(f"An error occurred: {str(e)}")
84
-
85
-
86
- async def callback_query_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
87
- query = update.callback_query
88
- await query.answer()
89
-
90
- try:
91
- name = query.message.caption.split("\n")[0].split(": ")[1]
92
- pokemon_info = await get_pokemon_info(name)
93
-
94
- if pokemon_info:
95
- stats = "\n".join(
96
- f"{stat['stat']['name'].upper()}: {stat['base_stat']}"
97
- for stat in pokemon_info["stats"]
98
- )
99
- stats_message = f"•➥ STATS:\n{stats}\n"
100
-
101
- moves = ", ".join(
102
- move_info["move"]["name"] for move_info in pokemon_info["moves"]
103
- )
104
- moves_message = f"•➥ MOVES: {moves}"
105
-
106
- if query.data == "stats":
107
- await query.message.reply_text(stats_message)
108
- elif query.data == "moves":
109
- if len(moves_message) > 1000:
110
- with open("moves.txt", "w") as file:
111
- file.write(moves_message)
112
- await query.message.reply_text(
113
- "The moves exceed 1000 characters. Sending as a file.",
114
- disable_web_page_preview=True,
115
- )
116
- await query.message.reply_document(document=open("moves.txt", "rb"))
117
- else:
118
- await query.message.reply_text(moves_message)
119
- else:
120
- await query.message.reply_text("Pokemon not found.")
121
- except Exception as e:
122
- await query.message.reply_text(f"An error occurred: {str(e)}")
123
-
124
-
125
- # <================================================ HANDLER =======================================================>
126
- # Add the command and callback query handlers to the dispatcher
127
- function(CommandHandler("pokedex", pokedex, block=False))
128
- function(
129
- CallbackQueryHandler(callback_query_handler, pattern="^(stats|moves)$", block=False)
130
- )
131
-
132
- # <================================================ HANDLER =======================================================>
133
- __help__ = """
134
-
135
- 🍥 *POKEMON SEARCH*
136
-
137
- ➠ *Commands*:
138
-
139
- » /pokedex < Search > : Gives that pokemon info.
140
- """
141
-
142
- __mod_name__ = "POKEDEX"
143
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/purge.py DELETED
@@ -1,135 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from asyncio import sleep
3
-
4
- from pyrogram import filters
5
- from pyrogram.enums import ChatType
6
- from pyrogram.errors import MessageDeleteForbidden, RPCError
7
- from pyrogram.types import Message
8
-
9
- from Mikobot import SUPPORT_CHAT, app
10
- from Mikobot.utils.can_restrict import can_restrict
11
-
12
- # <=======================================================================================================>
13
-
14
-
15
- # <================================================ FUNCTION =======================================================>
16
- @app.on_message(filters.command("purge"))
17
- @can_restrict
18
- async def purge(c: app, m: Message):
19
- if m.chat.type != ChatType.SUPERGROUP:
20
- await m.reply_text(text="Cannot purge messages in a basic group")
21
- return
22
-
23
- if m.reply_to_message:
24
- message_ids = list(range(m.reply_to_message.id, m.id))
25
-
26
- def divide_chunks(l: list, n: int = 100):
27
- for i in range(0, len(l), n):
28
- yield l[i : i + n]
29
-
30
- # Dielete messages in chunks of 100 messages
31
- m_list = list(divide_chunks(message_ids))
32
-
33
- try:
34
- for plist in m_list:
35
- await c.delete_messages(
36
- chat_id=m.chat.id,
37
- message_ids=plist,
38
- revoke=True,
39
- )
40
- await m.delete()
41
- except MessageDeleteForbidden:
42
- await m.reply_text(
43
- text="Cannot delete all messages. The messages may be too old, I might not have delete rights, or this might not be a supergroup."
44
- )
45
- return
46
- except RPCError as ef:
47
- await m.reply_text(
48
- text=f"""Some error occured, report to @{SUPPORT_CHAT}
49
-
50
- <b>Error:</b> <code>{ef}</code>"""
51
- )
52
-
53
- count_del_msg = len(message_ids)
54
-
55
- z = await m.reply_text(text=f"Deleted <i>{count_del_msg}</i> messages")
56
- await sleep(3)
57
- await z.delete()
58
- return
59
- await m.reply_text("Reply to a message to start purge !")
60
- return
61
-
62
-
63
- @app.on_message(filters.command("spurge"))
64
- @can_restrict
65
- async def spurge(c: app, m: Message):
66
- if m.chat.type != ChatType.SUPERGROUP:
67
- await m.reply_text(text="Cannot purge messages in a basic group")
68
- return
69
-
70
- if m.reply_to_message:
71
- message_ids = list(range(m.reply_to_message.id, m.id))
72
-
73
- def divide_chunks(l: list, n: int = 100):
74
- for i in range(0, len(l), n):
75
- yield l[i : i + n]
76
-
77
- # Dielete messages in chunks of 100 messages
78
- m_list = list(divide_chunks(message_ids))
79
-
80
- try:
81
- for plist in m_list:
82
- await c.delete_messages(
83
- chat_id=m.chat.id,
84
- message_ids=plist,
85
- revoke=True,
86
- )
87
- await m.delete()
88
- except MessageDeleteForbidden:
89
- await m.reply_text(
90
- text="Cannot delete all messages. The messages may be too old, I might not have delete rights, or this might not be a supergroup."
91
- )
92
- return
93
- except RPCError as ef:
94
- await m.reply_text(
95
- text=f"""Some error occured, report to @{SUPPORT_CHAT}
96
-
97
- <b>Error:</b> <code>{ef}</code>"""
98
- )
99
- return
100
- await m.reply_text("Reply to a message to start spurge !")
101
- return
102
-
103
-
104
- @app.on_message(
105
- filters.command("del"),
106
- group=9,
107
- )
108
- @can_restrict
109
- async def del_msg(c: app, m: Message):
110
- if m.chat.type != ChatType.SUPERGROUP:
111
- return
112
-
113
- if m.reply_to_message:
114
- await m.delete()
115
- await c.delete_messages(
116
- chat_id=m.chat.id,
117
- message_ids=m.reply_to_message.id,
118
- )
119
- else:
120
- await m.reply_text(text="What do you wanna delete?")
121
- return
122
-
123
-
124
- # <=================================================== HELP ====================================================>
125
- __help__ = """
126
- ❗️*Purge*
127
-
128
- » /purge: Deletes messages upto replied message.
129
-
130
- » /spurge: Deletes messages upto replied message without a success message.
131
-
132
- » /del: Deletes a single message, used as a reply to message."""
133
-
134
- __mod_name__ = "PURGE"
135
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/quotely.py DELETED
@@ -1,294 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import base64
3
- import os
4
- from random import choice
5
-
6
- from aiohttp import ContentTypeError
7
- from PIL import Image
8
- from telethon.tl import types
9
- from telethon.utils import get_display_name, get_peer_id
10
-
11
- from Mikobot import DEV_USERS
12
- from Mikobot.events import register
13
-
14
- # <=======================================================================================================>
15
-
16
-
17
- # <================================================ CLASS & FUNCTION =======================================================>
18
- class Quotly:
19
- _API = "https://bot.lyo.su/quote/generate"
20
- _entities = {
21
- types.MessageEntityPhone: "phone_number",
22
- types.MessageEntityMention: "mention",
23
- types.MessageEntityBold: "bold",
24
- types.MessageEntityCashtag: "cashtag",
25
- types.MessageEntityStrike: "strikethrough",
26
- types.MessageEntityHashtag: "hashtag",
27
- types.MessageEntityEmail: "email",
28
- types.MessageEntityMentionName: "text_mention",
29
- types.MessageEntityUnderline: "underline",
30
- types.MessageEntityUrl: "url",
31
- types.MessageEntityTextUrl: "text_link",
32
- types.MessageEntityBotCommand: "bot_command",
33
- types.MessageEntityCode: "code",
34
- types.MessageEntityPre: "pre",
35
- }
36
-
37
- async def _format_quote(self, event, reply=None, sender=None, type_="private"):
38
- async def telegraph(file_):
39
- file = file_ + ".png"
40
- Image.open(file_).save(file, "PNG")
41
- files = {"file": open(file, "rb").read()}
42
- uri = (
43
- "https://telegra.ph"
44
- + (
45
- await async_searcher(
46
- "https://telegra.ph/upload", post=True, data=files, re_json=True
47
- )
48
- )[0]["src"]
49
- )
50
- os.remove(file)
51
- os.remove(file_)
52
- return uri
53
-
54
- reply = (
55
- {
56
- "name": get_display_name(reply.sender) or "Deleted Account",
57
- "text": reply.raw_text,
58
- "chatId": reply.chat_id,
59
- }
60
- if reply
61
- else {}
62
- )
63
-
64
- is_fwd = event.fwd_from
65
- name, last_name = None, None
66
-
67
- if sender and sender.id not in DEV_USERS:
68
- id_ = get_peer_id(sender)
69
- name = get_display_name(sender)
70
- elif not is_fwd:
71
- id_ = event.sender_id
72
- sender = await event.get_sender()
73
- name = get_display_name(sender)
74
- else:
75
- id_, sender = None, None
76
- name = is_fwd.from_name
77
- if is_fwd.from_id:
78
- id_ = get_peer_id(is_fwd.from_id)
79
- try:
80
- sender = await event.client.get_entity(id_)
81
- name = get_display_name(sender)
82
- except ValueError:
83
- pass
84
- if sender and hasattr(sender, "last_name"):
85
- last_name = sender.last_name
86
-
87
- entities = (
88
- [
89
- {
90
- "type": self._entities[type(entity)],
91
- **{k: v for k, v in entity.to_dict().items() if k != "_"},
92
- }
93
- for entity in event.entities
94
- ]
95
- if event.entities
96
- else []
97
- )
98
-
99
- message = {
100
- "entities": entities,
101
- "chatId": id_,
102
- "avatar": True,
103
- "from": {
104
- "id": id_,
105
- "first_name": (name or (sender.first_name if sender else None))
106
- or "Deleted Account",
107
- "last_name": last_name,
108
- "username": sender.username if sender else None,
109
- "language_code": "en",
110
- "title": name,
111
- "name": name or "Unknown",
112
- "type": type_,
113
- },
114
- "text": event.raw_text,
115
- "replyMessage": reply,
116
- }
117
-
118
- if event.document and event.document.thumbs:
119
- file_ = await event.download_media(thumb=-1)
120
- uri = await telegraph(file_)
121
- message["media"] = {"url": uri}
122
-
123
- return message
124
-
125
- async def create_quotly(
126
- self,
127
- event,
128
- url="https://quote-api.example.com/generate",
129
- reply={},
130
- bg=None,
131
- sender=None,
132
- OQAPI=True,
133
- file_name="quote.webp",
134
- ):
135
- if not isinstance(event, list):
136
- event = [event]
137
- if OQAPI:
138
- url = Quotly._API
139
- bg = bg or "#1b1429"
140
- content = {
141
- "type": "quote",
142
- "format": "webp",
143
- "backgroundColor": bg,
144
- "width": 512,
145
- "height": 768,
146
- "scale": 2,
147
- "messages": [
148
- await self._format_quote(message, reply=reply, sender=sender)
149
- for message in event
150
- ],
151
- }
152
- try:
153
- request = await async_searcher(url, post=True, json=content, re_json=True)
154
- except ContentTypeError as er:
155
- if url != self._API:
156
- return await self.create_quotly(
157
- self._API, post=True, json=content, re_json=True
158
- )
159
- raise er
160
-
161
- if request.get("ok"):
162
- with open(file_name, "wb") as file:
163
- image = base64.decodebytes(request["result"]["image"].encode("utf-8"))
164
- file.write(image)
165
- return file_name
166
- raise Exception(str(request))
167
-
168
-
169
- quotly = Quotly()
170
-
171
-
172
- async def async_searcher(
173
- url: str,
174
- post: bool = None,
175
- headers: dict = None,
176
- params: dict = None,
177
- json: dict = None,
178
- data: dict = None,
179
- ssl=None,
180
- re_json: bool = False,
181
- re_content: bool = False,
182
- real: bool = False,
183
- *args,
184
- **kwargs
185
- ):
186
- try:
187
- import aiohttp
188
- except ImportError:
189
- raise DependencyMissingError(
190
- "'aiohttp' is not installed!\nThis function requires aiohttp to be installed."
191
- )
192
-
193
- async with aiohttp.ClientSession(headers=headers) as client:
194
- data = await (
195
- client.post(url, json=json, data=data, ssl=ssl, *args, **kwargs)
196
- if post
197
- else client.get(url, params=params, ssl=ssl, *args, **kwargs)
198
- )
199
- return await (
200
- data.json() if re_json else data.read() if re_content else data.text()
201
- )
202
-
203
-
204
- @register(pattern="^/q(?: |$)(.*)")
205
- async def quott_(event):
206
- match = event.pattern_match.group(1).strip()
207
- if not event.is_reply:
208
- return await event.reply("Please reply to a message.")
209
-
210
- msg = await event.reply("Creating quote, please wait.")
211
- reply = await event.get_reply_message()
212
- replied_to, reply_ = None, None
213
-
214
- if match:
215
- spli_ = match.split(maxsplit=1)
216
- if (spli_[0] in ["r", "reply"]) or (
217
- spli_[0].isdigit() and int(spli_[0]) in range(1, 21)
218
- ):
219
- if spli_[0].isdigit():
220
- if not event.client.is_bot:
221
- reply_ = await event.client.get_messages(
222
- event.chat_id,
223
- min_id=event.reply_to_msg_id - 1,
224
- reverse=True,
225
- limit=int(spli_[0]),
226
- )
227
- else:
228
- id_ = reply.id
229
- reply_ = []
230
- for msg_ in range(id_, id_ + int(spli_[0])):
231
- msh = await event.client.get_messages(event.chat_id, ids=msg_)
232
- if msh:
233
- reply_.append(msh)
234
- else:
235
- replied_to = await reply.get_reply_message()
236
- try:
237
- match = spli_[1]
238
- except IndexError:
239
- match = None
240
-
241
- user = None
242
-
243
- if not reply_:
244
- reply_ = reply
245
-
246
- if match:
247
- match = match.split(maxsplit=1)
248
-
249
- if match:
250
- if match[0].startswith("@") or match[0].isdigit():
251
- try:
252
- match_ = await event.client.parse_id(match[0])
253
- user = await event.client.get_entity(match_)
254
- except ValueError:
255
- pass
256
- match = match[1] if len(match) == 2 else None
257
- else:
258
- match = match[0]
259
-
260
- if match == "random":
261
- match = choice(all_col)
262
-
263
- try:
264
- file = await quotly.create_quotly(
265
- reply_, bg=match, reply=replied_to, sender=user
266
- )
267
- except Exception as er:
268
- return await msg.edit(str(er))
269
-
270
- message = await reply.reply("", file=file)
271
- os.remove(file)
272
- await msg.delete()
273
- return message
274
-
275
-
276
- # <=================================================== HELP ====================================================>
277
-
278
-
279
- __mod_name__ = "QUOTELY"
280
-
281
- __help__ = """
282
- » /q : Create quote.
283
-
284
- » /q r : Get replied quote.
285
-
286
- » /q 2 ᴛᴏ 8 : Get multiple quotes.
287
-
288
- » /q < any colour name > : Create any coloured quotes.
289
-
290
- ➠ Example:
291
-
292
- » /q red , /q blue etc.
293
- """
294
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/reverse.py DELETED
@@ -1,117 +0,0 @@
1
- # CREATED BY: @Qewertyy
2
-
3
- # <============================================== IMPORTS =========================================================>
4
- import os
5
- import traceback
6
-
7
- from pyrogram import Client, filters
8
- from pyrogram import types as t
9
-
10
- from Mikobot import app
11
- from Mikobot.state import state
12
-
13
- from .telegraph import telegraph, upload_file
14
-
15
-
16
- # <================================================ FUNCTIONS =====================================================>
17
- @app.on_message(filters.command(["p", "pp", "reverse", "sauce"]))
18
- async def reverseImageSearch(_: Client, m: t.Message):
19
- try:
20
- reply = await m.reply_text("`Downloading...`")
21
- file = None
22
- if not m.reply_to_message:
23
- return await reply.edit("Reply to an image?")
24
- if m.reply_to_message.document is False or m.reply_to_message.photo is False:
25
- return await reply.edit("Reply to an image?")
26
- if (
27
- m.reply_to_message.document
28
- and m.reply_to_message.document.mime_type
29
- in ["image/png", "image/jpg", "image/jpeg"]
30
- or m.reply_to_message.photo
31
- ):
32
- if (
33
- m.reply_to_message.document
34
- and m.reply_to_message.document.file_size > 5242880
35
- ):
36
- return await reply.edit("Reply to an image?")
37
- file = await m.reply_to_message.download()
38
- else:
39
- return await reply.edit("Reply to an image?")
40
- await reply.edit("`Uploading to the server...`")
41
- imgUrl = upload_file(file)
42
- os.remove(file)
43
- if imgUrl is None:
44
- return await reply.edit("Ran into an error.")
45
- output = await reverse_image_search("google", f"https://graph.org/{imgUrl[0]}")
46
- if output is None:
47
- return await reply.edit("Ran into an error.")
48
-
49
- names = output["content"]["bestResults"]["names"]
50
- urls = output["content"]["bestResults"]["urls"]
51
- btn = t.InlineKeyboardMarkup(
52
- [[t.InlineKeyboardButton(text="IMAGE URL", url=urls[-1])]]
53
- )
54
-
55
- if len(names) > 10:
56
- message = "\n".join(
57
- [f"{index+1}. {name}" for index, name in enumerate(names[:10])]
58
- )
59
- htmlMessage = f"<br/>".join(
60
- [f"{index+1}. {name}" for index, name in enumerate(names)]
61
- )
62
- htmlMessage += "<br/><br/><h3>URLS</h3><br/>"
63
- htmlMessage += f"<br/>".join([f"{url}" for url in urls])
64
- htmlMessage += (
65
- "<br/><br/>By <a href='https://lexica.qewertyy.me'>LexicaAPI</a>"
66
- )
67
- telegraph_page = telegraph.create_page(
68
- "More Results", html_content=htmlMessage
69
- )
70
- message += f"\n\n[More Results](https://telegra.ph/{telegraph_page['path']})\n\nBy @LexicaAPI"
71
- await reply.delete()
72
- return await m.reply_text(message, reply_markup=btn)
73
-
74
- message = "\n".join([f"{index+1}. {name}" for index, name in enumerate(names)])
75
- await reply.delete()
76
- await m.reply_text(f"{message}\n\nBy @LexicaAPI", reply_markup=btn)
77
- except Exception as E:
78
- traceback.print_exc()
79
- return await m.reply_text("Ran into an error.")
80
-
81
-
82
- async def reverse_image_search(search_engine, img_url) -> dict:
83
- try:
84
- response = await state.post(
85
- f"https://lexica.qewertyy.me/image-reverse/{search_engine}?img_url={img_url}",
86
- )
87
- if response.status_code != 200:
88
- return None
89
- output = response.json()
90
- if output["code"] != 2:
91
- return None
92
- return output
93
- except Exception as E:
94
- raise Exception(f"API Error: {E}")
95
-
96
-
97
- # <=================================================== HELP ====================================================>
98
-
99
-
100
- __help__ = """
101
- 🖼 *IMAGE REVERSE*
102
-
103
- » `/p`, `/pp`, `/reverse`, `/sauce`: Reverse image search using various search engines.
104
-
105
- ➠ *Usage:*
106
- Reply to an image with one of the above commands to perform a reverse image search.
107
-
108
- ➠ *Example:*
109
- » `/p` - Perform a reverse image search.
110
-
111
- ➠ *Note:*
112
- - Supported image formats: PNG, JPG, JPEG.
113
- - Maximum file size: 5 MB.
114
- """
115
-
116
- __mod_name__ = "REVERSE"
117
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/rules.py DELETED
@@ -1,169 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
3
- from telegram.constants import ParseMode
4
- from telegram.error import BadRequest
5
- from telegram.ext import CommandHandler, ContextTypes, filters
6
- from telegram.helpers import escape_markdown
7
-
8
- import Database.sql.rules_sql as sql
9
- from Mikobot import dispatcher, function
10
- from Mikobot.plugins.helper_funcs.chat_status import check_admin
11
- from Mikobot.plugins.helper_funcs.string_handling import (
12
- markdown_parser,
13
- markdown_to_html,
14
- )
15
-
16
- # <=======================================================================================================>
17
-
18
-
19
- # <================================================ FUNCTION =======================================================>
20
- async def get_rules(update: Update, context: ContextTypes.DEFAULT_TYPE):
21
- chat_id = update.effective_chat.id
22
- await send_rules(update, chat_id)
23
-
24
-
25
- async def send_rules(update, chat_id, from_pm=False):
26
- bot = dispatcher.bot
27
- user = update.effective_user # type: Optional[User]
28
- reply_msg = update.message.reply_to_message
29
- try:
30
- chat = await bot.get_chat(chat_id)
31
- except BadRequest as excp:
32
- if excp.message == "Chat not found" and from_pm:
33
- await bot.send_message(
34
- user.id,
35
- "The rules shortcut for this chat hasn't been set properly! Ask admins to "
36
- "fix this.\nMaybe they forgot the hyphen in ID",
37
- message_thread_id=update.effective_message.message_thread_id
38
- if chat.is_forum
39
- else None,
40
- )
41
- return
42
- else:
43
- raise
44
-
45
- rules = sql.get_rules(chat_id)
46
- text = f"The rules for {escape_markdown(chat.title, 2)} are:\n\n{markdown_to_html(rules)}"
47
-
48
- if from_pm and rules:
49
- await bot.send_message(
50
- user.id,
51
- text,
52
- parse_mode=ParseMode.MARKDOWN,
53
- disable_web_page_preview=True,
54
- )
55
- elif from_pm:
56
- await bot.send_message(
57
- user.id,
58
- "The group admins haven't set any rules for this chat yet. "
59
- "This probably doesn't mean it's lawless though...!",
60
- )
61
- elif rules and reply_msg and not reply_msg.forum_topic_created:
62
- await reply_msg.reply_text(
63
- "Please click the button below to see the rules.",
64
- reply_markup=InlineKeyboardMarkup(
65
- [
66
- [
67
- InlineKeyboardButton(
68
- text="RULES",
69
- url=f"t.me/{bot.username}?start={chat_id}",
70
- ),
71
- ],
72
- ],
73
- ),
74
- )
75
- elif rules:
76
- await update.effective_message.reply_text(
77
- "Please click the button below to see the rules.",
78
- reply_markup=InlineKeyboardMarkup(
79
- [
80
- [
81
- InlineKeyboardButton(
82
- text="RULES",
83
- url=f"t.me/{bot.username}?start={chat_id}",
84
- ),
85
- ],
86
- ],
87
- ),
88
- )
89
- else:
90
- await update.effective_message.reply_text(
91
- "The group admins haven't set any rules for this chat yet. "
92
- "This probably doesn't mean it's lawless though...!",
93
- )
94
-
95
-
96
- @check_admin(is_user=True)
97
- async def set_rules(update: Update, context: ContextTypes.DEFAULT_TYPE):
98
- chat_id = update.effective_chat.id
99
- msg = update.effective_message # type: Optional[Message]
100
- raw_text = msg.text
101
- args = raw_text.split(None, 1) # use python's maxsplit to separate cmd and args
102
- if len(args) == 2:
103
- txt = args[1]
104
- offset = len(txt) - len(raw_text) # set correct offset relative to command
105
- markdown_rules = markdown_parser(
106
- txt,
107
- entities=msg.parse_entities(),
108
- offset=offset,
109
- )
110
-
111
- sql.set_rules(chat_id, markdown_rules)
112
- await update.effective_message.reply_text(
113
- "Successfully set rules for this group."
114
- )
115
-
116
-
117
- @check_admin(is_user=True)
118
- async def clear_rules(update: Update, context: ContextTypes.DEFAULT_TYPE):
119
- chat_id = update.effective_chat.id
120
- sql.set_rules(chat_id, "")
121
- await update.effective_message.reply_text("Successfully cleared rules!")
122
-
123
-
124
- def __stats__():
125
- return f"• {sql.num_chats()} chats have rules set."
126
-
127
-
128
- async def __import_data__(chat_id, data, message):
129
- # set chat rules
130
- rules = data.get("info", {}).get("rules", "")
131
- sql.set_rules(chat_id, rules)
132
-
133
-
134
- def __migrate__(old_chat_id, new_chat_id):
135
- sql.migrate_chat(old_chat_id, new_chat_id)
136
-
137
-
138
- def __chat_settings__(chat_id, user_id):
139
- return f"This chat has had its rules set: `{bool(sql.get_rules(chat_id))}`"
140
-
141
-
142
- # <=======================================================================================================>
143
-
144
-
145
- # <================================================= HELP ======================================================>
146
- __help__ = """
147
- ➠ /rules: Get the rules for this chat.
148
-
149
- ➠ *Admins only*:
150
- » /setrules <your rules here>: Set the rules for this chat.
151
-
152
- » /clearrules: Clear the rules for this chat.
153
- """
154
-
155
- __mod_name__ = "RULES"
156
-
157
- # <================================================ HANDLER =======================================================>
158
- function(
159
- CommandHandler("rules", get_rules, filters=filters.ChatType.GROUPS, block=False)
160
- )
161
- function(
162
- CommandHandler("setrules", set_rules, filters=filters.ChatType.GROUPS, block=False)
163
- )
164
- function(
165
- CommandHandler(
166
- "clearrules", clear_rules, filters=filters.ChatType.GROUPS, block=False
167
- )
168
- )
169
- # <================================================== END =====================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/search.py DELETED
@@ -1,185 +0,0 @@
1
- # SOURCE https://github.com/Team-ProjectCodeX
2
- # CREATED BY https://t.me/O_okarma
3
- # API BY https://www.github.com/SOME-1HING
4
- # PROVIDED BY https://t.me/ProjectCodeX
5
-
6
- # <============================================== IMPORTS =========================================================>
7
- import json
8
- import random
9
-
10
- from pyrogram import Client, filters
11
- from pyrogram.types import InputMediaPhoto, Message
12
-
13
- from Mikobot import app
14
- from Mikobot.state import state
15
-
16
- # <=======================================================================================================>
17
-
18
- BINGSEARCH_URL = "https://sugoi-api.vercel.app/search"
19
- NEWS_URL = "https://sugoi-api.vercel.app/news?keyword={}"
20
-
21
-
22
- # <================================================ FUNCTION =======================================================>
23
- @app.on_message(filters.command("news"))
24
- async def news(_, message: Message):
25
- keyword = (
26
- message.text.split(" ", 1)[1].strip() if len(message.text.split()) > 1 else ""
27
- )
28
- url = NEWS_URL.format(keyword)
29
-
30
- try:
31
- response = await state.get(url) # Assuming state is an asynchronous function
32
- news_data = response.json()
33
-
34
- if "error" in news_data:
35
- error_message = news_data["error"]
36
- await message.reply_text(f"Error: {error_message}")
37
- else:
38
- if len(news_data) > 0:
39
- news_item = random.choice(news_data)
40
-
41
- title = news_item["title"]
42
- excerpt = news_item["excerpt"]
43
- source = news_item["source"]
44
- relative_time = news_item["relative_time"]
45
- news_url = news_item["url"]
46
-
47
- message_text = f"𝗧𝗜𝗧𝗟𝗘: {title}\n𝗦𝗢𝗨𝗥𝗖𝗘: {source}\n𝗧𝗜𝗠𝗘: {relative_time}\n𝗘𝗫𝗖𝗘𝗥𝗣𝗧: {excerpt}\n𝗨𝗥𝗟: {news_url}"
48
- await message.reply_text(message_text)
49
- else:
50
- await message.reply_text("No news found.")
51
-
52
- except Exception as e: # Replace with specific exception type if possible
53
- await message.reply_text(f"Error: {str(e)}")
54
-
55
-
56
- @app.on_message(filters.command("bingsearch"))
57
- async def bing_search(client: Client, message: Message):
58
- try:
59
- if len(message.command) == 1:
60
- await message.reply_text("Please provide a keyword to search.")
61
- return
62
-
63
- keyword = " ".join(
64
- message.command[1:]
65
- ) # Assuming the keyword is passed as arguments
66
- params = {"keyword": keyword}
67
-
68
- response = await state.get(
69
- BINGSEARCH_URL, params=params
70
- ) # Use the state.get method
71
-
72
- if response.status_code == 200:
73
- results = response.json()
74
- if not results:
75
- await message.reply_text("No results found.")
76
- else:
77
- message_text = ""
78
- for result in results[:7]:
79
- title = result.get("title", "")
80
- link = result.get("link", "")
81
- message_text += f"{title}\n{link}\n\n"
82
- await message.reply_text(message_text.strip())
83
- else:
84
- await message.reply_text("Sorry, something went wrong with the search.")
85
- except Exception as e:
86
- await message.reply_text(f"An error occurred: {str(e)}")
87
-
88
-
89
- # Command handler for the '/bingimg' command
90
- @app.on_message(filters.command("bingimg"))
91
- async def bingimg_search(client: Client, message: Message):
92
- try:
93
- text = message.text.split(None, 1)[
94
- 1
95
- ] # Extract the query from command arguments
96
- except IndexError:
97
- return await message.reply_text(
98
- "Provide me a query to search!"
99
- ) # Return error if no query is provided
100
-
101
- search_message = await message.reply_text("🔎") # Display searching message
102
-
103
- # Send request to Bing image search API using state function
104
- bingimg_url = "https://sugoi-api.vercel.app/bingimg?keyword=" + text
105
- resp = await state.get(bingimg_url)
106
- images = json.loads(resp.text) # Parse the response JSON into a list of image URLs
107
-
108
- media = []
109
- count = 0
110
- for img in images:
111
- if count == 7:
112
- break
113
-
114
- # Create InputMediaPhoto object for each image URL
115
- media.append(InputMediaPhoto(media=img))
116
- count += 1
117
-
118
- # Send the media group as a reply to the user
119
- await message.reply_media_group(media=media)
120
-
121
- # Delete the searching message and the original command message
122
- await search_message.delete()
123
- await message.delete()
124
-
125
-
126
- # Command handler for the '/googleimg' command
127
- @app.on_message(filters.command("googleimg"))
128
- async def googleimg_search(client: Client, message: Message):
129
- try:
130
- text = message.text.split(None, 1)[
131
- 1
132
- ] # Extract the query from command arguments
133
- except IndexError:
134
- return await message.reply_text(
135
- "Provide me a query to search!"
136
- ) # Return error if no query is provided
137
-
138
- search_message = await message.reply_text("💭") # Display searching message
139
-
140
- # Send request to Google image search API using state function
141
- googleimg_url = "https://sugoi-api.vercel.app/googleimg?keyword=" + text
142
- resp = await state.get(googleimg_url)
143
- images = json.loads(resp.text) # Parse the response JSON into a list of image URLs
144
-
145
- media = []
146
- count = 0
147
- for img in images:
148
- if count == 7:
149
- break
150
-
151
- # Create InputMediaPhoto object for each image URL
152
- media.append(InputMediaPhoto(media=img))
153
- count += 1
154
-
155
- # Send the media group as a reply to the user
156
- await message.reply_media_group(media=media)
157
-
158
- # Delete the searching message and the original command message
159
- await search_message.delete()
160
- await message.delete()
161
-
162
-
163
- # <=======================================================================================================>
164
-
165
-
166
- # <=================================================== HELP ====================================================>
167
- __mod_name__ = "SEARCH"
168
-
169
- __help__ = """
170
- 💭 𝗦𝗘𝗔𝗥𝗖𝗛
171
-
172
- ➠ *Available commands:*
173
-
174
- » /googleimg <search query>: It retrieves and displays images obtained through a Google image search.
175
-
176
- » /bingimg <search query>: It retrieves and displays images obtained through a Bing image search.
177
-
178
- » /news <search query> : search news.
179
-
180
- » /bingsearch <search query> : get search result with links.
181
-
182
- ➠ *Example:*
183
- ➠ `/bingsearch app`: return search results.
184
- """
185
- # <================================================ END =======================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Mikobot/plugins/speedtest.py DELETED
@@ -1,74 +0,0 @@
1
- # <============================================== IMPORTS =========================================================>
2
- import speedtest
3
- from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
4
- from telegram.constants import ParseMode
5
- from telegram.ext import CallbackQueryHandler, ContextTypes
6
-
7
- from Mikobot import DEV_USERS, function
8
- from Mikobot.plugins.disable import DisableAbleCommandHandler
9
- from Mikobot.plugins.helper_funcs.chat_status import check_admin
10
-
11
- # <=======================================================================================================>
12
-
13
-
14
- # <================================================ FUNCTION =======================================================>
15
- def convert(speed):
16
- return round(int(speed) / 1048576, 2)
17
-
18
-
19
- @check_admin(only_dev=True)
20
- async def speedtestxyz(update: Update, context: ContextTypes.DEFAULT_TYPE):
21
- buttons = [
22
- [
23
- InlineKeyboardButton("Image", callback_data="speedtest_image"),
24
- InlineKeyboardButton("Text", callback_data="speedtest_text"),
25
- ],
26
- ]
27
- await update.effective_message.reply_text(
28
- "Select SpeedTest Mode",
29
- reply_markup=InlineKeyboardMarkup(buttons),
30
- )
31
-
32
-
33
- async def speedtestxyz_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
34
- query = update.callback_query
35
-
36
- if query.from_user.id in DEV_USERS:
37
- msg = await update.effective_message.edit_text("Running a speedtest....")
38
- speed = speedtest.Speedtest()
39
- speed.get_best_server()
40
- speed.download()
41
- speed.upload()
42
- replymsg = "SpeedTest Results:"
43
-
44
- if query.data == "speedtest_image":
45
- speedtest_image = speed.results.share()
46
- await update.effective_message.reply_photo(
47
- photo=speedtest_image,
48
- caption=replymsg,
49
- )
50
- await msg.delete()
51
-
52
- elif query.data == "speedtest_text":
53
- result = speed.results.dict()
54
- replymsg += f"\nDownload: `{convert(result['download'])}Mb/s`\nUpload: `{convert(result['upload'])}Mb/s`\nPing: `{result['ping']}`"
55
- await update.effective_message.edit_text(
56
- replymsg, parse_mode=ParseMode.MARKDOWN
57
- )
58
- else:
59
- await query.answer("You are required to join Black Bulls to use this command.")
60
-
61
-
62
- # <================================================ HANDLER =======================================================>
63
- SPEED_TEST_HANDLER = DisableAbleCommandHandler("speedtest", speedtestxyz, block=False)
64
- SPEED_TEST_CALLBACKHANDLER = CallbackQueryHandler(
65
- speedtestxyz_callback, pattern="speedtest_.*", block=False
66
- )
67
-
68
- function(SPEED_TEST_HANDLER)
69
- function(SPEED_TEST_CALLBACKHANDLER)
70
-
71
- __mod_name__ = "SpeedTest"
72
- __command_list__ = ["speedtest"]
73
- __handlers__ = [SPEED_TEST_HANDLER, SPEED_TEST_CALLBACKHANDLER]
74
- # <================================================ END =======================================================>