-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathaccess.py
268 lines (239 loc) · 11.7 KB
/
access.py
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
"""
This module handles all access restriction logic, including warning processing
"""
from functools import wraps
from telegram import Update
from telegram.ext import CallbackContext
from api.telegram import TelegramAPI
from common.common import BaseClass
from storage.postgres import PostgresDatabase
### HELPER COMMANDS, RESTRICTING VISBILITY TO METHODS ###
base_instance = BaseClass()
logger = base_instance.logger
# change this id to your telegram user id
LIST_OF_ADMINS = [249427415]
def restricted_to_private_messages(func):
"""Restricts the usage of the command only to private messages"""
@wraps(func)
async def wrapped(bot, update: Update, context: CallbackContext, *args, **kwargs):
(_, chat_type, _, context) = bot.telegram.get_chat_info(update, context)
if not chat_type == "private":
logger.info(f"[ACCESS] the invocation was filtered because the chat type wasn't private ({chat_type})")
return
return await func(bot, update, context, *args, **kwargs)
return wrapped
def restricted_to_supergroups(func):
"""Restricts the usage of the command only to supergroups"""
@wraps(func)
async def wrapped(bot, update: Update, context: CallbackContext, *args, **kwargs):
(_, chat_type, _, context) = bot.telegram.get_chat_info(update, context)
if chat_type != "supergroup" and chat_type != "group":
logger.info(f"[ACCESS] the invocation was filtered because the chat type wasn't supergroup ({chat_type})")
return
return await func(bot, update, context, *args, **kwargs)
return wrapped
def restricted_to_admins(func):
"""Restricts the usage of the command to admins of the bot"""
@wraps(func)
async def wrapped(bot, update: Update, context: CallbackContext, *args, **kwargs):
(user_id, _, context) = bot.telegram.get_from_user_info(update, context)
if user_id not in LIST_OF_ADMINS:
logger.info(f"[ACCESS] the invocation was filtered because the user wasn't admin ({user_id})")
return
return await func(bot, update, context, *args, **kwargs)
return wrapped
def restricted_to_not_banned(func):
"""Restricts the usage of the command to admins of the bot"""
@wraps(func)
async def wrapped(bot, update: Update, context: CallbackContext, *args, **kwargs):
(_, user_name, context) = bot.telegram.get_from_user_info(update, context)
if bot.database.is_banned(user_name):
logger.info(f"[ACCESS] the invocation was filtered because the user was banned ({user_name})")
return
return await func(bot, update, context, *args, **kwargs)
return wrapped
def restricted_to_stickerset_owners(func):
"""Restricts the usage of the command to stickerset owners"""
@wraps(func)
async def wrapped(bot, update: Update, context: CallbackContext, *args, **kwargs):
(chat_id, _, _, context) = bot.telegram.get_chat_info(update, context)
(user_id, _, context) = bot.telegram.get_from_user_info(update, context)
stickerset_owner = bot.database.get_stickerset_owner(chat_id)
if not stickerset_owner or int(stickerset_owner) != user_id:
logger.info(f"[ACCESS] the invocation was filtered because the user wasn't stickerset owner ({user_id})")
return
return await func(bot, update, context, *args, **kwargs)
return wrapped
def restricted_to_undefined_stickerset_chats(func):
"""Restricts the usage of the command to chats without defined stickerset owners"""
@wraps(func)
async def wrapped(bot, update: Update, context: CallbackContext, *args, **kwargs):
(chat_id, _, _, context) = bot.telegram.get_chat_info(update, context)
if bot.database.is_stickerset_owner_defined_for_chat(chat_id):
logger.info(f"[ACCESS] the invocation was filtered because the stickerset is defined for the chat ({chat_id})")
return
return await func(bot, update, context, *args, **kwargs)
return wrapped
def restricted_to_defined_stickerset_chats(func):
"""Restricts the usage of the command to chats only with defined stickerset owners"""
@wraps(func)
async def wrapped(bot, update: Update, context: CallbackContext, *args, **kwargs):
(chat_id, _, _, context) = bot.telegram.get_chat_info(update, context)
if not bot.database.is_stickerset_owner_defined_for_chat(chat_id):
logger.info(f"[ACCESS] the invocation was filtered because the stickerset is not defined for the chat ({chat_id})")
return
return await func(bot, update, context, *args, **kwargs)
return wrapped
class WarningsProcessor(BaseClass):
BAN_MESSAGE = (
"@{user_name} you exceeded the limit of {warnings_limit}, so as we warned previously, "
"we permanently ban you from utilizing this bot"
)
def __init__(self, database: PostgresDatabase, telegram: TelegramAPI):
super().__init__()
self.database = database
self.telegram = telegram
async def add_show_stickers_warning(
self,
update: Update,
context: CallbackContext
) -> bool:
"""Adds a warning for using show command too frequently"""
max_show_stickers_interractions = 20
max_warnings_until_ban = 5
(_, user_name, context) = self.telegram.get_from_user_info(update, context)
self.logger.info(f"[WARNING] user {user_name} is passing show stickers warning")
warning_message = (
f'@{user_name}, we\'ve noticed unusual activity from your account, currently there '
f'is a limit of {max_show_stickers_interractions} daily /show executions per '
f'individual. Exceeding this limit will prompt notifications such as this one. '
f'Accumulating {max_warnings_until_ban} warnings of this nature within a single '
f'day may result in permanent suspension from utilizing our bot.'
)
return await self.__add_warning(
"show_stickers",
max_show_stickers_interractions,
"show_stickers_invocations_exceed",
max_warnings_until_ban,
warning_message,
update,
context
)
async def add_give_achievement_warning(
self,
update: Update,
context: CallbackContext
) -> bool:
"""Adds a warning for invoking achievement giving command too frequently"""
max_give_achievement_interractions = 2
max_warnings_until_ban = 10
(_, user_name, context) = self.telegram.get_from_user_info(update, context)
self.logger.info(f"[WARNING] user {user_name} is passing give achievement warning")
warning_message = (
f'Achievements are like rare jewels scattered throughout our lives, precious and '
f'unique. It\'s crucial to cherish their scarcity and significance. That\'s why '
f'we\'ve imposed a limit of {max_give_achievement_interractions} daily executions '
f'per individual. Exceeding this limit will prompt notifications such as this one. '
f'Accumulating {max_warnings_until_ban} warnings of this nature within a single day '
f'may result in permanent suspension from utilizing our bot. @{user_name}, we kindly '
f'ask for your cooperation in adhering to these guidelines.'
)
return await self.__add_warning(
"new_achievement",
max_give_achievement_interractions,
"new_achievement_invocations_exceed",
max_warnings_until_ban,
warning_message,
update,
context
)
async def add_message_format_warning(
self,
update: Update,
context: CallbackContext
) -> bool:
"""Adds a warning for use of inappropriate language in the achievement message"""
max_message_format_interractions = 10
max_warnings_until_ban = 20
(_, user_name, context) = self.telegram.get_from_user_info(update, context)
self.logger.info(f"[WARNING] user {user_name} is passing message format warning")
warning_message = (
f"Sorry, @{user_name}, your request couldn't be processed due to the length of "
f"your message or the characters you used. Currently, the bot supports prompts "
f"up to 90 alphanumeric characters and words no longer than 20 characters. We "
f"are working to extend these limits. For now, please keep your messages within "
f"these parameters to ensure the bot operates smoothly. Repeatedly sending long "
f"messages will lead to further warnings.\n\nIf you exceed "
f"{max_message_format_interractions} such warnings in a day, they may count "
f"towards a potential ban, as it suggests an attempt to disrupt the bot's "
f"functions. Accumulating {max_warnings_until_ban} warnings within a single "
f"day may result in permanent suspension from utilizing our bot."
)
return await self.__add_warning(
"phrase_wrong_achievement_message",
max_message_format_interractions,
"incorrect_message_format",
max_warnings_until_ban,
warning_message,
update,
context
)
async def add_inappropriate_language_warning(
self,
update: Update,
context: CallbackContext
) -> bool:
"""Adds a warning for use of inappropriate language in the achievement message"""
max_warnings_until_ban = 20
(_, user_name, context) = self.telegram.get_from_user_info(update, context)
self.logger.info(f"[WARNING] user {user_name} is passing inappropriate language warning")
warning_message = (
f'@{user_name}, this bot relies on external APIs that also perform profanity checks. '
f'Frequent triggers of these checks could result in the suspension of the accounts '
f'powering our services. We kindly request that you refrain from using inappropriate '
f'language when interacting with the bot. Continued use of such language will result in '
f'similar warnings. Accumulating {max_warnings_until_ban} warnings within a single day '
f'may result in permanent suspension from utilizing our bot.'
)
return await self.__add_warning(
"phrase_achievement_message",
-1,
"inappropriate_language_in_achievement_message",
max_warnings_until_ban,
warning_message,
update,
context
)
async def __add_warning(
self,
interraction_type: str,
max_interractions: int,
warning_type: str,
warnings_limit: int,
warning_message: str,
update: Update,
context: CallbackContext
) -> bool:
(user_id, user_name, context) = self.telegram.get_from_user_info(update, context)
(chat_id, _, _, context) = self.telegram.get_chat_info(update, context)
warnings = 0
if user_id not in LIST_OF_ADMINS:
warnings = self.database.add_warning(
user_id,
chat_id,
interraction_type,
max_interractions,
warning_type
)
if warnings > warnings_limit:
self.database.ban(user_name)
context = await self.telegram.reply_text(
self.BAN_MESSAGE.format(user_name=user_name, warnings_limit=warnings_limit),
update,
context
)
return True
if warnings > 0:
context = await self.telegram.reply_text(warning_message, update, context)
return True
return False