import html
import re
from telegram import ChatPermissions, Update
from telegram.constants import ParseMode
from telegram.error import BadRequest
from telegram.ext import CommandHandler, ContextTypes, MessageHandler, filters
from telegram.helpers import mention_html
import Database.sql.blacklist_sql as sql
from Database.sql.approve_sql import is_approved
from Mikobot import LOGGER, dispatcher, function
from Mikobot.plugins.connection import connected
from Mikobot.plugins.disable import DisableAbleCommandHandler
from Mikobot.plugins.helper_funcs.alternate import send_message, typing_action
from Mikobot.plugins.helper_funcs.chat_status import check_admin, user_not_admin
from Mikobot.plugins.helper_funcs.extraction import extract_text
from Mikobot.plugins.helper_funcs.misc import split_message
from Mikobot.plugins.helper_funcs.string_handling import extract_time
from Mikobot.plugins.log_channel import loggable
from Mikobot.plugins.warns import warn
BLACKLIST_GROUP = 11
@check_admin(is_user=True)
@typing_action
async def blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
chat = update.effective_chat
user = update.effective_user
args = context.args
conn = await connected(context.bot, update, chat, user.id, need_admin=False)
if conn:
chat_id = conn
chat_obj = await dispatcher.bot.getChat(conn)
chat_name = chat_obj.title
else:
if chat.type == "private":
return
chat_id = update.effective_chat.id
chat_name = chat.title
filter_list = "Current blacklisted words in {}:\n".format(chat_name)
all_blacklisted = sql.get_chat_blacklist(chat_id)
if len(args) > 0 and args[0].lower() == "copy":
for trigger in all_blacklisted:
filter_list += "{}
\n".format(html.escape(trigger))
else:
for trigger in all_blacklisted:
filter_list += " - {}
\n".format(html.escape(trigger))
# for trigger in all_blacklisted:
# filter_list += " - {}
\n".format(html.escape(trigger))
split_text = split_message(filter_list)
for text in split_text:
if filter_list == "Current blacklisted words in {}:\n".format(
html.escape(chat_name),
):
await send_message(
update.effective_message,
"No blacklisted words in {}!".format(html.escape(chat_name)),
parse_mode=ParseMode.HTML,
)
return
await send_message(update.effective_message, text, parse_mode=ParseMode.HTML)
@check_admin(is_user=True)
@typing_action
async def add_blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
msg = update.effective_message
chat = update.effective_chat
user = update.effective_user
words = msg.text.split(None, 1)
conn = await connected(context.bot, update, chat, user.id)
if conn:
chat_id = conn
chat_obj = await dispatcher.bot.getChat(conn)
chat_name = chat_obj.title
else:
chat_id = update.effective_chat.id
if chat.type == "private":
return
else:
chat_name = chat.title
if len(words) > 1:
text = words[1]
to_blacklist = list(
{trigger.strip() for trigger in text.split("\n") if trigger.strip()},
)
for trigger in to_blacklist:
sql.add_to_blacklist(chat_id, trigger.lower())
if len(to_blacklist) == 1:
await send_message(
update.effective_message,
"Added blacklist {}
in chat: {}!".format(
html.escape(to_blacklist[0]),
html.escape(chat_name),
),
parse_mode=ParseMode.HTML,
)
else:
await send_message(
update.effective_message,
"Added blacklist trigger: {}
in {}!".format(
len(to_blacklist),
html.escape(chat_name),
),
parse_mode=ParseMode.HTML,
)
else:
await send_message(
update.effective_message,
"Tell me which words you would like to add in blacklist.",
)
@check_admin(is_user=True)
@typing_action
async def unblacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
msg = update.effective_message
chat = update.effective_chat
user = update.effective_user
words = msg.text.split(None, 1)
conn = await connected(context.bot, update, chat, user.id)
if conn:
chat_id = conn
chat_obj = await dispatcher.bot.getChat(conn)
chat_name = chat_obj.title
else:
chat_id = update.effective_chat.id
if chat.type == "private":
return
else:
chat_name = chat.title
if len(words) > 1:
text = words[1]
to_unblacklist = list(
{trigger.strip() for trigger in text.split("\n") if trigger.strip()},
)
successful = 0
for trigger in to_unblacklist:
success = sql.rm_from_blacklist(chat_id, trigger.lower())
if success:
successful += 1
if len(to_unblacklist) == 1:
if successful:
await send_message(
update.effective_message,
"Removed {}
from blacklist in {}!".format(
html.escape(to_unblacklist[0]),
html.escape(chat_name),
),
parse_mode=ParseMode.HTML,
)
else:
await send_message(
update.effective_message,
"This is not a blacklist trigger!",
)
elif successful == len(to_unblacklist):
await send_message(
update.effective_message,
"Removed {}
from blacklist in {}!".format(
successful,
html.escape(chat_name),
),
parse_mode=ParseMode.HTML,
)
elif not successful:
await send_message(
update.effective_message,
"None of these triggers exist so it can't be removed.",
parse_mode=ParseMode.HTML,
)
else:
await send_message(
update.effective_message,
"Removed {}
from blacklist. {} did not exist, "
"so were not removed.".format(
successful,
len(to_unblacklist) - successful,
),
parse_mode=ParseMode.HTML,
)
else:
await send_message(
update.effective_message,
"Tell me which words you would like to remove from blacklist!",
)
@loggable
@check_admin(is_user=True)
@typing_action
async def blacklist_mode(update: Update, context: ContextTypes.DEFAULT_TYPE):
chat = update.effective_chat
user = update.effective_user
msg = update.effective_message
args = context.args
conn = await connected(context.bot, update, chat, user.id, need_admin=True)
if conn:
chat = await dispatcher.bot.getChat(conn)
chat_id = conn
chat_obj = await dispatcher.bot.getChat(conn)
chat_name = chat_obj.title
else:
if update.effective_message.chat.type == "private":
await send_message(
update.effective_message,
"This command can be only used in group not in PM",
)
return ""
chat = update.effective_chat
chat_id = update.effective_chat.id
chat_name = update.effective_message.chat.title
if args:
if args[0].lower() in ["off", "nothing", "no"]:
settypeblacklist = "do nothing"
sql.set_blacklist_strength(chat_id, 0, "0")
elif args[0].lower() in ["del", "delete"]:
settypeblacklist = "delete blacklisted message"
sql.set_blacklist_strength(chat_id, 1, "0")
elif args[0].lower() == "warn":
settypeblacklist = "warn the sender"
sql.set_blacklist_strength(chat_id, 2, "0")
elif args[0].lower() == "mute":
settypeblacklist = "mute the sender"
sql.set_blacklist_strength(chat_id, 3, "0")
elif args[0].lower() == "kick":
settypeblacklist = "kick the sender"
sql.set_blacklist_strength(chat_id, 4, "0")
elif args[0].lower() == "ban":
settypeblacklist = "ban the sender"
sql.set_blacklist_strength(chat_id, 5, "0")
elif args[0].lower() == "tban":
if len(args) == 1:
teks = """It looks like you tried to set time value for blacklist but you didn't specified time; Try, `/blacklistmode tban `.
Examples of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
await send_message(
update.effective_message, teks, parse_mode="markdown"
)
return ""
restime = await extract_time(msg, args[1])
if not restime:
teks = """Invalid time value!
Example of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
await send_message(
update.effective_message, teks, parse_mode="markdown"
)
return ""
settypeblacklist = "temporarily ban for {}".format(args[1])
sql.set_blacklist_strength(chat_id, 6, str(args[1]))
elif args[0].lower() == "tmute":
if len(args) == 1:
teks = """It looks like you tried to set time value for blacklist but you didn't specified time; try, `/blacklistmode tmute `.
Examples of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
await send_message(
update.effective_message, teks, parse_mode="markdown"
)
return ""
restime = await extract_time(msg, args[1])
if not restime:
teks = """Invalid time value!
Examples of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
await send_message(
update.effective_message, teks, parse_mode="markdown"
)
return ""
settypeblacklist = "temporarily mute for {}".format(args[1])
sql.set_blacklist_strength(chat_id, 7, str(args[1]))
else:
await send_message(
update.effective_message,
"I only understand: off/del/warn/ban/kick/mute/tban/tmute!",
)
return ""
if conn:
text = "Changed blacklist mode: `{}` in *{}*!".format(
settypeblacklist,
chat_name,
)
else:
text = "Changed blacklist mode: `{}`!".format(settypeblacklist)
await send_message(update.effective_message, text, parse_mode="markdown")
return (
"{}:\n"
"Admin: {}\n"
"Changed the blacklist mode. will {}.".format(
html.escape(chat.title),
mention_html(user.id, html.escape(user.first_name)),
settypeblacklist,
)
)
else:
getmode, getvalue = sql.get_blacklist_setting(chat.id)
if getmode == 0:
settypeblacklist = "do nothing"
elif getmode == 1:
settypeblacklist = "delete"
elif getmode == 2:
settypeblacklist = "warn"
elif getmode == 3:
settypeblacklist = "mute"
elif getmode == 4:
settypeblacklist = "kick"
elif getmode == 5:
settypeblacklist = "ban"
elif getmode == 6:
settypeblacklist = "temporarily ban for {}".format(getvalue)
elif getmode == 7:
settypeblacklist = "temporarily mute for {}".format(getvalue)
if conn:
text = "Current blacklistmode: *{}* in *{}*.".format(
settypeblacklist,
chat_name,
)
else:
text = "Current blacklistmode: *{}*.".format(settypeblacklist)
await send_message(
update.effective_message, text, parse_mode=ParseMode.MARKDOWN
)
return ""
def findall(p, s):
i = s.find(p)
while i != -1:
yield i
i = s.find(p, i + 1)
@user_not_admin
async def del_blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
chat = update.effective_chat
message = update.effective_message
user = update.effective_user
bot = context.bot
to_match = await extract_text(message)
if not to_match:
return
if is_approved(chat.id, user.id):
return
getmode, value = sql.get_blacklist_setting(chat.id)
chat_filters = sql.get_chat_blacklist(chat.id)
for trigger in chat_filters:
pattern = r"( |^|[^\w])" + re.escape(trigger) + r"( |$|[^\w])"
if re.search(pattern, to_match, flags=re.IGNORECASE):
try:
if getmode == 0:
return
elif getmode == 1:
try:
await message.delete()
except BadRequest:
pass
elif getmode == 2:
try:
await message.delete()
except BadRequest:
pass
warn(
update.effective_user,
chat,
("Using blacklisted trigger: {}".format(trigger)),
message,
update.effective_user,
)
return
elif getmode == 3:
await message.delete()
await bot.restrict_chat_member(
chat.id,
update.effective_user.id,
permissions=ChatPermissions(can_send_messages=False),
)
await bot.sendMessage(
chat.id,
f"Muted {user.first_name} for using Blacklisted word: {trigger}!",
message_thread_id=(
message.message_thread_id if chat.is_forum else None
),
)
return
elif getmode == 4:
await message.delete()
res = chat.unban_member(update.effective_user.id)
if res:
await bot.sendMessage(
chat.id,
f"Kicked {user.first_name} for using Blacklisted word: {trigger}!",
message_thread_id=(
message.message_thread_id if chat.is_forum else None
),
)
return
elif getmode == 5:
await message.delete()
await chat.ban_member(user.id)
await bot.sendMessage(
chat.id,
f"Banned {user.first_name} for using Blacklisted word: {trigger}",
message_thread_id=(
message.message_thread_id if chat.is_forum else None
),
)
return
elif getmode == 6:
await message.delete()
bantime = await extract_time(message, value)
await chat.ban_member(user.id, until_date=bantime)
await bot.sendMessage(
chat.id,
f"Banned {user.first_name} until '{value}' for using Blacklisted word: {trigger}!",
message_thread_id=(
message.message_thread_id if chat.is_forum else None
),
)
return
elif getmode == 7:
await message.delete()
mutetime = await extract_time(message, value)
await bot.restrict_chat_member(
chat.id,
user.id,
until_date=mutetime,
permissions=ChatPermissions(can_send_messages=False),
)
await bot.sendMessage(
chat.id,
f"Muted {user.first_name} until '{value}' for using Blacklisted word: {trigger}!",
message_thread_id=(
message.message_thread_id if chat.is_forum else None
),
)
return
except BadRequest as excp:
if excp.message != "Message to delete not found":
LOGGER.exception("Error while deleting blacklist message.")
break
async def __import_data__(chat_id, data, message):
# set chat blacklist
blacklist = data.get("blacklist", {})
for trigger in blacklist:
sql.add_to_blacklist(chat_id, trigger)
def __migrate__(old_chat_id, new_chat_id):
sql.migrate_chat(old_chat_id, new_chat_id)
def __chat_settings__(chat_id, user_id):
blacklisted = sql.num_blacklist_chat_filters(chat_id)
return "There are {} blacklisted words.".format(blacklisted)
def __stats__():
return "• {} blacklist triggers, across {} chats.".format(
sql.num_blacklist_filters(),
sql.num_blacklist_filter_chats(),
)
__mod_name__ = "BLACKLIST"
__help__ = """
➠ 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!
➠ *NOTE*: Blacklists do not affect group admins.
» /blacklist: View the current blacklisted words.
Admin only:
» /addblacklist : Add a trigger to the blacklist. Each line is considered one trigger, so using different lines will allow you to add multiple triggers.
» /unblacklist : Remove triggers from the blacklist. Same newline logic applies here, so you can remove multiple triggers at once.
» /blacklistmode : Action to perform when someone sends blacklisted words.
➠ Blacklist sticker is used to stop certain stickers. Whenever a sticker is sent, the message will be deleted immediately.
➠ *NOTE:* Blacklist stickers do not affect the group admin
» /blsticker: See current blacklisted sticker
➠ *Only admin:*
» /addblsticker : Add the sticker trigger to the black list. Can be added via reply sticker
» /unblsticker : Remove triggers from blacklist. The same newline logic applies here, so you can delete multiple triggers at once
» /rmblsticker : Same as above
» /blstickermode : sets up a default action on what to do if users use blacklisted stickers
Note:
» can be https://t.me/addstickers/ or just or reply to the sticker message
"""
BLACKLIST_HANDLER = DisableAbleCommandHandler(
"blacklist", blacklist, admin_ok=True, block=False
)
ADD_BLACKLIST_HANDLER = CommandHandler("addblacklist", add_blacklist, block=False)
UNBLACKLIST_HANDLER = CommandHandler("unblacklist", unblacklist, block=False)
BLACKLISTMODE_HANDLER = CommandHandler("blacklistmode", blacklist_mode, block=False)
BLACKLIST_DEL_HANDLER = MessageHandler(
(filters.TEXT | filters.COMMAND | filters.Sticker.ALL | filters.PHOTO)
& filters.ChatType.GROUPS,
del_blacklist,
block=False,
)
function(BLACKLIST_HANDLER)
function(ADD_BLACKLIST_HANDLER)
function(UNBLACKLIST_HANDLER)
function(BLACKLISTMODE_HANDLER)
function(BLACKLIST_DEL_HANDLER, group=BLACKLIST_GROUP)
__handlers__ = [
BLACKLIST_HANDLER,
ADD_BLACKLIST_HANDLER,
UNBLACKLIST_HANDLER,
BLACKLISTMODE_HANDLER,
(BLACKLIST_DEL_HANDLER, BLACKLIST_GROUP),
]