from datetime import datetime, timedelta
from pyrogram import filters
from pyrogram.errors import RPCError
from pyrogram.types import (CallbackQuery, ChatPermissions,
InlineKeyboardButton, InlineKeyboardMarkup,
Message)
from Powers import TIME_ZONE
from Powers.bot_class import Gojo
from Powers.database.rules_db import Rules
from Powers.database.users_db import Users
from Powers.database.warns_db import Warns, WarnSettings
from Powers.supports import get_support_staff
from Powers.utils.caching import ADMIN_CACHE, admin_cache_reload
from Powers.utils.custom_filters import admin_filter, command, restrict_filter
from Powers.utils.extract_user import extract_user
from Powers.utils.parser import mention_html
@Gojo.on_message(
command(["warn", "swarn", "dwarn"]) & restrict_filter,
)
async def warn(c: Gojo, m: Message):
if m.reply_to_message:
r_id = m.reply_to_message.id
reason = m.text.split(None, 1)[1] if len(m.text.split()) >= 2 else None
else:
r_id = m.id
reason = m.text.split(None, 2)[2] if len(m.text.split()) >= 3 else None
if len(m.command) <= 1 and not m.reply_to_message:
await m.reply_text("I can't warn nothing! Tell me user whom I should warn")
return
user_id, user_first_name, _ = await extract_user(c, m)
if user_id == c.me.id:
await m.reply_text("Huh, why would I warn myself?")
return
SUPPORT_STAFF = get_support_staff()
if user_id in SUPPORT_STAFF:
await m.reply_text(
text="This user is in my support staff, cannot restrict them."
)
return
try:
admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
except KeyError:
admins_group = {i[0] for i in (await admin_cache_reload(m, "warn_user"))}
if user_id in admins_group:
await m.reply_text("This user is admin in this chat, I can't warn them!")
return
warn_db = Warns(m.chat.id)
warn_settings_db = WarnSettings(m.chat.id)
_, num = warn_db.warn_user(user_id, reason)
warn_settings = warn_settings_db.get_warnings_settings()
if num >= warn_settings["warn_limit"]:
timeee = datetime.now(TIME_ZONE) + timedelta(minutes=45)
if warn_settings["warn_mode"] == "kick" or warn_settings[
"warn_mode"
] not in ["ban", "mute"]:
await m.chat.ban_member(user_id, until_date=timeee)
action = "kicked"
elif warn_settings["warn_mode"] == "ban":
await m.chat.ban_member(user_id)
action = "banned"
else:
await m.chat.restrict_member(user_id, ChatPermissions())
action = "muted"
await m.reply_text(
(
f"Warnings {num}/{warn_settings['warn_limit']}!"
f"\nReason for last warn:\n{reason}"
if reason
else "\n"
f"{(await mention_html(user_first_name, user_id))} has been {action}!"
),
reply_to_message_id=r_id,
)
await m.stop_propagation()
if rules := Rules(m.chat.id).get_rules():
kb = InlineKeyboardButton(
"Rules 📋",
url=f"https://t.me/{c.me.username}?start=rules_{m.chat.id}",
)
else:
kb = InlineKeyboardButton(
"Kick ⚠️",
callback_data=f"warn.kick.{user_id}",
)
if m.text.split()[0] == "/swarn":
await m.delete()
await m.stop_propagation()
if m.text.split()[0] == "/dwarn":
if not m.reply_to_message:
await m.reply_text("Reply to a message to delete it and ban the user!")
await m.stop_propagation()
await m.reply_to_message.delete()
txt = f"{(await mention_html(user_first_name, user_id))} has {num}/{warn_settings['warn_limit']} warnings!"
txt += f"\nReason for last warn:\n{reason}" if reason else ""
await m.reply_text(
txt,
reply_markup=InlineKeyboardMarkup(
[
[
InlineKeyboardButton(
"Remove Warn ❌",
callback_data=f"warn.remove.{user_id}",
),
]
+ [kb],
],
),
reply_to_message_id=r_id,
)
await m.stop_propagation()
@Gojo.on_message(command("resetwarns") & restrict_filter)
async def reset_warn(c: Gojo, m: Message):
if len(m.command) <= 1 and not m.reply_to_message:
await m.reply_text("I can't warn nothing! Tell me user whom I should warn")
return
user_id, user_first_name, _ = await extract_user(c, m)
if user_id == c.me.id:
await m.reply_text("Huh, why would I warn myself?")
return
SUPPORT_STAFF = get_support_staff()
if user_id in SUPPORT_STAFF:
await m.reply_text(
"They are support users, cannot be restriced, how am I then supposed to unrestrict them?",
)
return
try:
admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
except KeyError:
admins_group = {i[0] for i in (await admin_cache_reload(m, "reset_warns"))}
if user_id in admins_group:
await m.reply_text("This user is admin in this chat, I can't warn them!")
return
warn_db = Warns(m.chat.id)
warn_db.reset_warns(user_id)
await m.reply_text(
f"Warnings have been reset for {(await mention_html(user_first_name, user_id))}",
)
return
@Gojo.on_message(command("warns") & filters.group)
async def list_warns(c: Gojo, m: Message):
user_id, user_first_name, _ = await extract_user(c, m)
if user_id == c.me.id:
await m.reply_text("Huh, why would I warn myself?")
return
SUPPORT_STAFF = get_support_staff()
if user_id in SUPPORT_STAFF:
await m.reply_text("This user has no warns!")
return
try:
admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
except KeyError:
admins_group = {i[0] for i in (await admin_cache_reload(m, "warns"))}
if user_id in admins_group:
await m.reply_text(
"This user is admin in this chat, they don't have any warns!",
)
return
warn_db = Warns(m.chat.id)
warn_settings_db = WarnSettings(m.chat.id)
warns, num_warns = warn_db.get_warns(user_id)
warn_settings = warn_settings_db.get_warnings_settings()
if not warns:
await m.reply_text("This user has no warns!")
return
msg = f"{(await mention_html(user_first_name, user_id))} has {num_warns}/{warn_settings['warn_limit']} warns!\n\nReasons:\n"
msg += "\n".join([("- No reason" if i is None else f" - {i}") for i in warns])
await m.reply_text(msg)
return
@Gojo.on_message(
command(["rmwarn", "removewarn"]) & restrict_filter,
)
async def remove_warn(c: Gojo, m: Message):
if len(m.command) <= 1 and not m.reply_to_message:
await m.reply_text(
"I can't remove warns of nothing! Tell me user whose warn should be removed!",
)
return
user_id, user_first_name, _ = await extract_user(c, m)
if user_id == c.me.id:
await m.reply_text("Huh, why would I warn myself?")
return
SUPPORT_STAFF = get_support_staff()
if user_id in SUPPORT_STAFF:
await m.reply_text("This user has no warns!")
return
try:
admins_group = {i[0] for i in ADMIN_CACHE[m.chat.id]}
except KeyError:
admins_group = {i[0] for i in (await admin_cache_reload(m, "rmwarn"))}
if user_id in admins_group:
await m.reply_text(
"This user is admin in this chat, they don't have any warns!",
)
return
warn_db = Warns(m.chat.id)
warns, _ = warn_db.get_warns(user_id)
if not warns:
await m.reply_text("This user has no warnings!")
return
_, num_warns = warn_db.remove_warn(user_id)
await m.reply_text(
(
f"{(await mention_html(user_first_name, user_id))} now has {num_warns} warnings!\n"
"Their last warn was removed."
),
)
return
@Gojo.on_callback_query(filters.regex("^warn."))
async def remove_last_warn_btn(c: Gojo, q: CallbackQuery):
try:
admins_group = {i[0] for i in ADMIN_CACHE[q.message.chat.id]}
except KeyError:
admins_group = {i[0] for i in (await admin_cache_reload(q, "warn_btn"))}
if q.from_user.id not in admins_group:
await q.answer("You are not allowed to use this!", show_alert=True)
return
args = q.data.split(".")
action = args[1]
user_id = int(args[2])
chat_id = int(q.message.chat.id)
user = Users.get_user_info(user_id)
user_first_name = user["name"]
if action == "kick":
try:
timee = datetime.now(TIME_ZONE) + timedelta(minutes=45)
await c.ban_chat_member(chat_id, user_id, until_date=timee)
await q.message.edit_text(
(
f"Admin {(await mention_html(q.from_user.first_name, q.from_user.id))} "
"kicked user they can't join the chat for 45 minutes"
f"{(await mention_html(user_first_name, user_id))} for last warning!"
),
)
warn_db = Warns(q.message.chat.id)
warn_db.reset_warns(user_id)
except RPCError as err:
await q.message.edit_text(
f"🛑 Failed to Kick\nError:\n{err}",
)
elif action == "remove":
warn_db = Warns(q.message.chat.id)
_, num_warns = warn_db.remove_warn(user_id)
await q.message.edit_text(
(
f"Admin {(await mention_html(q.from_user.first_name, q.from_user.id))} "
"removed last warn for "
f"{(await mention_html(user_first_name, user_id))}\n"
f"Current Warnings: {num_warns}"
),
)
await q.answer()
return
@Gojo.on_message(command(["warnings", "warnsettings"]) & admin_filter)
async def get_settings(_, m: Message):
warn_settings_db = WarnSettings(m.chat.id)
settings = warn_settings_db.get_warnings_settings()
await m.reply_text(
(
"This group has these following settings:\n"
f"Warn Limit: {settings['warn_limit']}
\n"
f"Warn Mode: {settings['warn_mode']}
"
),
)
return
@Gojo.on_message(command("warnmode") & admin_filter)
async def warnmode(_, m: Message):
warn_settings_db = WarnSettings(m.chat.id)
if len(m.text.split()) > 1:
wm = (m.text.split(None, 1)[1]).lower()
if wm not in ("kick", "ban", "mute"):
await m.reply_text(
(
"Please choose a valid warn mode!"
"Valid options are: ban
,kick
,mute
"
),
)
return
warnmode_var = warn_settings_db.set_warnmode(wm)
await m.reply_text(f"Warn Mode has been set to: {warnmode_var}")
return
warnmode_var = warn_settings_db.get_warnmode()
await m.reply_text(f"This chats current Warn Mode is: {warnmode_var}")
return
@Gojo.on_message(command("warnlimit") & admin_filter)
async def warnlimit(_, m: Message):
warn_settings_db = WarnSettings(m.chat.id)
if len(m.text.split()) > 1:
wl = int(m.text.split(None, 1)[1])
if not isinstance(wl, int):
await m.reply_text("Warn Limit can only be a number!")
return
warnlimit_var = warn_settings_db.set_warnlimit(wl)
await m.reply_text(f"Warn Limit has been set to: {warnlimit_var}")
return
warnlimit_var = warn_settings_db.get_warnlimit()
await m.reply_text(f"This chats current Warn Limit is: {warnlimit_var}")
return
__PLUGIN__ = "warnings"
__alt_name__ = ["warn", "warning", "warns"]
__HELP__ = """
**Warns**
**Admin commands:**
• /warn ``: Warn a user.
• /dwarn ``: Warn a user by reply, and delete their message.
• /swarn ``: Silently warn a user, and delete your message.
• /warns: See a user's warnings.
• /rmwarn: Remove a user's latest warning.
• /resetwarn: Reset all of a user's warnings to 0.
• /warnings: Get the chat's warning settings.
• /warnmode ``: Set the chat's warn mode.
• /warnlimit ``: Set the number of warnings before users are punished.
**IF THE USER IS KICKED THEN THEY WILL BE TEMPORARILY BANNED FOR 45 MINUTES**
**Examples:**
`/warn @user`: this warns a user in the chat."""