File size: 12,749 Bytes
1036b06
11ae35a
87abec5
 
11ae35a
 
 
 
83fe5dc
11ae35a
ca4eb6d
 
9db4ada
83fe5dc
f0f9ad9
11ae35a
 
 
ca4eb6d
 
 
 
 
 
 
c15d499
89ad488
ca4eb6d
89ad488
 
6cef7ec
ca4eb6d
 
 
 
 
c62ca93
ca4eb6d
 
 
83fe5dc
ca4eb6d
af1662b
 
 
ca4eb6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1036b06
89ad488
 
 
1036b06
ca4eb6d
 
 
 
89ad488
ca4eb6d
 
 
 
 
 
 
 
6cef7ec
ca4eb6d
 
 
 
 
89ad488
ca4eb6d
 
c62ca93
ca4eb6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89ad488
ca4eb6d
 
 
 
 
c62ca93
ca4eb6d
 
 
83fe5dc
ca4eb6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c62ca93
ca4eb6d
 
 
83fe5dc
ca4eb6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6cef7ec
87abec5
ca4eb6d
 
 
 
 
 
 
 
89ad488
ca4eb6d
 
 
 
 
 
 
c62ca93
ca4eb6d
 
 
83fe5dc
ca4eb6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6cef7ec
ca4eb6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89ad488
ca4eb6d
 
 
 
bb1bfd1
1036b06
ca4eb6d
 
 
bb1bfd1
ca4eb6d
 
 
bb1bfd1
 
ca4eb6d
 
 
 
 
89ad488
 
 
 
 
 
 
 
 
 
 
ca4eb6d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9da6fea
709df35
096ee5f
709df35
9da6fea
d5348c6
 
 
 
 
 
 
 
 
 
 
bb1bfd1
 
d5348c6
af1662b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
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"\n<b>Reason for last warn</b>:\n{reason}"
                if reason
                else "\n"
                     f"{(await mention_html(user_first_name, user_id))} has been <b>{action}!</b>"
            ),
            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"\n<b>Reason for last warn</b>:\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 <b>{num_warns}/{warn_settings['warn_limit']}</b> warns!\n\n<b>Reasons:</b>\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 <b>{num_warns}</b> 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\n<b>Error:</b>\n</code>{err}</code>",
            )

    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"<b>Current Warnings:</b> {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"<b>Warn Limit:</b> <code>{settings['warn_limit']}</code>\n"
            f"<b>Warn Mode:</b> <code>{settings['warn_mode']}</code>"
        ),
    )
    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: <code>ban</code>,<code>kick</code>,<code>mute</code>"
                ),
            )
            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 `<reason>`: Warn a user.
• /dwarn `<reason>`: Warn a user by reply, and delete their message.
• /swarn `<reason>`: 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 `<ban/kick/mute>`: Set the chat's warn mode.
• /warnlimit `<number>`: 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."""