-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathirisrp.py
More file actions
469 lines (383 loc) · 21.4 KB
/
Copy pathirisrp.py
File metadata and controls
469 lines (383 loc) · 21.4 KB
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
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
# На модуль распространяется лицензия "GNU General Public License v3.0"
# https://github.com/all-licenses/GNU-General-Public-License-v3.0
# meta developer: @PyModule
# meta fhsdesc: fun, rp, rpgame
# requires: toml
import os
from hikka import loader, utils
import pickle
from telethon.tl.types import Channel
import toml
# noinspection PyCallingNonCallable
@loader.tds
class IrisRP(loader.Module):
"""РП команды как в боте Ирис."""
def __init__(self):
self.config = loader.ModuleConfig(
loader.ConfigValue(
"action_decoration",
'normal | без стилей',
lambda: "Декорация для действия РП-команды",
validator=loader.validators.Choice(
[
"normal | без стилей",
"bold | полужирный",
"italic | курсив",
"underlined | подчёркнутый",
"strikethrough | зачёркнутый",
"spoiler | скрытый",
]
),
),
loader.ConfigValue(
"replica_decoration",
'normal | без стилей',
lambda: "Декорация для реплики РП-команды",
validator=loader.validators.Choice(
[
"normal | без стилей",
"bold | полужирный",
"italic | курсив",
"underlined | подчёркнутый",
"strikethrough | зачёркнутый",
"spoiler | скрытый",
]
),
),
loader.ConfigValue(
"speech_bubble",
'💬',
lambda: "Эмодзи речевого пузыря для «с репликой»",
validator=loader.validators.String()
)
)
strings = {'name': 'IrisRP'}
async def client_ready(self, client, db):
self.db = db
if not self.db.get("RPMod", "exlist", False):
self.db.set("RPMod", "exlist", [])
if not self.db.get("RPMod", "status", False):
self.db.get("RPMod", "status", 1)
if not self.db.get("RPMod", "rpcomands", False):
self.db.set("RPMod", "rpcomands", {})
if not self.db.get("RPMod", "rpemoji", False):
self.db.set("RPMod", "rpemoji", {})
if not self.db.get("RPMod", "nrpcommands", False):
if self.db.get("RPMod", "rpcomands", False):
commands_old = self.db.get("RPMod", "rpcomands")
emoji_old = self.db.get("RPMod", "rpemoji")
commands_new = {}
for key in commands_old:
try:
commands_new[key] = [commands_old[key], emoji_old[key]]
except KeyError:
commands_new[key] = [commands_old[key], '']
self.db.set("RPMod", "nrpcommands", commands_new)
else:
self.db.set("RPMod", "nrpcommands", {})
if not self.db.get("RPMod", "useraccept", False):
self.db.set("RPMod", "useraccept", {"chats": [], "users": []})
elif isinstance(type(self.db.get("RPMod", "useraccept")), list):
self.db.set(
"RPMod",
"useraccept",
{"chats": [], "users": self.db.get("RPMod", "useraccept")},
)
async def addrpcmd(self, message):
"""[команда (1-3 слова)] / [действие] / (эмодзи) - Создать РП команду."""
args = utils.get_args_raw(message)
dict_rp = self.db.get("RPMod", "nrpcommands", {})
if not args or not args.strip():
await utils.answer(message, "<emoji document_id=5774077015388852135>❌</emoji> <b>Вы не указали никаких данных.</b>")
return
try:
if '/' not in args:
await utils.answer(message, "<emoji document_id=5774077015388852135>❌</emoji> <b>Неверный формат. Используйте: команда / действие / эмодзи</b>")
return
parts = [part.strip() for part in args.split("/", maxsplit=2)]
if len(parts) < 2:
await utils.answer(message, "<emoji document_id=5774077015388852135>❌</emoji> <b>Неверный формат. Используйте: команда / действие / эмодзи</b>")
return
key_rp = parts[0].casefold()
words_count = len(key_rp.split())
if words_count < 1 or words_count > 3:
await utils.answer(message, "<emoji document_id=5774077015388852135>❌</emoji> <b>Команда должна содержать от 1 до 3 слов.</b>")
return
value_rp = parts[1]
if not value_rp.strip():
await utils.answer(message, "<emoji document_id=5774077015388852135>❌</emoji> <b>Вы не указали действие команды.</b>")
return
if key_rp == "all":
await utils.answer(message, '<emoji document_id=5774077015388852135>❌</emoji> <b>РП-команды не могут называться "all"</b>')
return
lenght_args = args.split("/")
count_emoji = 0
if len(lenght_args) >= 3:
emoji_rp = str(message.text.split("/", maxsplit=2)[2]).strip()
count_emoji = 1
if not emoji_rp or not emoji_rp.strip():
await utils.answer(message, "<emoji document_id=5774077015388852135>❌</emoji> <b>Вы не указали эмодзи.</b>")
return
dict_rp[key_rp] = [value_rp, emoji_rp.strip()]
self.db.set("RPMod", "nrpcommands", dict_rp)
response = f"<emoji document_id=5774022692642492953>✅</emoji> <b>Команда <code>{key_rp}</code> успешно добавлена"
if emoji_rp:
response += f" с эмодзи {emoji_rp}"
response += ".</b>"
await utils.answer(message, response)
except Exception as e:
await utils.answer(message, "<emoji document_id=5774077015388852135>❌</emoji> <b>Неверный формат. Используйте: команда (1-3 слова) / действие / эмодзи</b>")
async def delrpcmd(self, message):
"""[команда / all] - Удалить РП команду."""
dict_rp = self.db.get("RPMod", "nrpcommands")
args = utils.get_args_raw(message)
key_rp = str(args)
if key_rp == "all":
dict_rp.clear()
self.db.set("RPMod", "nrpcommands", dict_rp)
await utils.answer(message, "<emoji document_id=5774022692642492953>✅</emoji> <b>Все РП команды успешно очищены.</b>")
return
elif not key_rp or not key_rp.strip():
await utils.answer(message, "<emoji document_id=5774077015388852135>❌</emoji> <b>Вы не указали команду для удаления.</b>")
else:
try:
dict_rp.pop(key_rp)
self.db.set("RPMod", "nrpcommands", dict_rp)
await utils.answer(message, f"<emoji document_id=5774022692642492953>✅</emoji> <b>Команда <code>{key_rp}</code> успешно удалена.</b>")
except KeyError:
await utils.answer(message, f"<emoji document_id=5774077015388852135>❌</emoji> <b>Команда <code>{key_rp}</code> не найдена.</b>")
async def rptogglecmd(self, message):
"""- Включить/Выключить РП команды."""
status = self.db.get("RPMod", "status")
if status == 1:
self.db.set("RPMod", "status", 2)
await utils.answer(message, "<emoji document_id=5253959125838090076>👁</emoji> <b>РП команды теперь выключены.</b>")
else:
self.db.set("RPMod", "status", 1)
await utils.answer(message, "<emoji document_id=5253959125838090076>👁</emoji> <b>РП команды теперь включены.</b>")
async def rplistcmd(self, message):
"""- Список все ваших команд."""
com = self.db.get("RPMod", "nrpcommands")
coms_amount = len(com)
com_list = f"<emoji document_id=5253959125838090076>👁</emoji> <b>У вас {coms_amount} команд.</b>"
if len(com) == 0:
await utils.answer(message, f"<emoji document_id=5253959125838090076>👁</emoji> <b>У вас {coms_amount} команд.</b>")
return
for i in com:
if com[i][1] != '':
com_list += f"\n• <b><code>{i}</code> - {com[i][0]} |</b> {com[i][1]}"
else:
com_list += f"\n• <b><code>{i}</code> - {com[i][0]}</b>"
await utils.answer(message, com_list)
async def rpbackcmd(self, message):
"""(all) - Сохранить или загрузить список РП команд. All используется для замены всех команд."""
commands = self.db.get("RPMod", "nrpcommands")
mes_id = message.to_id
me = await self.client.get_me()
file_name = f"IrisRP_{me.id}.toml"
reply = await message.get_reply_message()
args = utils.get_args_raw(message)
replace_commands = "all" in args
if not reply:
try:
await message.delete()
with open(file_name, "w") as f:
toml.dump(commands, f)
await message.client.send_file(mes_id, file_name)
os.remove(file_name)
except Exception as e:
await utils.answer(message, f"<emoji document_id=5774077015388852135>❌</emoji> <b>Ошибка при создании бэкапа:</b>\n<code>{e}</code>")
else:
if not reply.document:
await utils.answer(message, "<emoji document_id=5774077015388852135>❌</emoji> <b>В ответе нет файла.</b>")
return
try:
await reply.download_media(file_name)
with open(file_name, "r") as f:
try:
data = toml.load(f)
except toml.TomlDecodeError:
os.remove(file_name)
return await utils.answer(message, "<emoji document_id=5774077015388852135>❌</emoji> <b>Файл поврежден или не является бэкапом.</b>")
for key in data.keys():
if not isinstance(data[key], list) or len(data[key]) != 2:
os.remove(file_name)
return await utils.answer(message, "<emoji document_id=5774077015388852135>❌</emoji> <b>Неверный формат бэкапа.</b>")
if replace_commands:
self.db.set("RPMod", "nrpcommands", data)
os.remove(file_name)
await utils.answer(message, "<emoji document_id=5774022692642492953>✅</emoji> <b>РП команды успешно заменены из бэкапа.</b>")
else:
updated_commands = {**commands, **data}
self.db.set("RPMod", "nrpcommands", updated_commands)
os.remove(file_name)
await utils.answer(message, "<emoji document_id=5774022692642492953>✅</emoji> <b>РП команды успешно добавлены из бэкапа.</b>")
except Exception as e:
if os.path.exists(file_name):
os.remove(file_name)
await utils.answer(message, f"<emoji document_id=5774077015388852135>❌</emoji> <b>Ошибка при загрузке бэкапа:</b>\n<code>{e}</code>")
async def rpacmd(self, message):
"""(ID/Reply) - Разрешить или запретить доступ к РП командам. Для подробностей напишите .rpa"""
reply = await message.get_reply_message()
args = utils.get_args_raw(message)
user_a = self.db.get("RPMod", "useraccept")
if not reply and not args and message.is_group:
chat = message.chat
if chat.id not in user_a["chats"]:
user_a["chats"].append(chat.id)
return await utils.answer(message, f"<emoji document_id=5774022692642492953>✅</emoji> <b>Доступ к РП-командам включен для чата {chat.title}</b>")
else:
user_a["chats"].remove(chat.id)
return await utils.answer(message, f"<emoji document_id=5774022692642492953>✅</emoji> <b>Доступ к РП-командам отключен для чата {chat.title}</b>")
elif args.lower() in ("-l", "л", "list", "список"):
sms = "<b><emoji document_id=5253959125838090076>👁</emoji> Список доступов к РП командам:</b>"
if not user_a["chats"] and not user_a["users"]:
return await utils.answer(message,"<emoji document_id=6028435952299413210>ℹ</emoji> <b>Нет ни пользователей, ни чатов с доступом к РП-командам</b>")
if user_a["chats"]:
sms += "\n\n<emoji document_id=6037421444789440735>💬</emoji> <b>Чаты с доступом:</b>"
for chat_id in user_a["chats"]:
try:
chat = await message.client.get_entity(int(chat_id))
sms += f"\n• <b>{chat.title}</b> (<code>{chat_id}</code>)"
except:
sms += f"\n• <code>{chat_id}</code>"
else:
sms += "\n\n<emoji document_id=6028435952299413210>ℹ</emoji> <b>Нет чатов с доступом</b>"
if user_a["users"]:
sms += "\n\n<emoji document_id=6035084557378654059>👤</emoji> <b>Пользователи с доступом:</b>"
for user_id in user_a["users"]:
try:
user = await message.client.get_entity(int(user_id))
sms += f"\n• <b>{user.first_name}</b> (<code>{user_id}</code>)"
except:
sms += f"\n• <code>{user_id}</code>"
else:
sms += "\n\n<emoji document_id=6028435952299413210>ℹ</emoji> <b>Нет пользователей с доступом</b>"
await utils.answer(message, sms)
elif args or reply:
try:
target_id = int(args) if args and args.isdigit() else reply.sender_id
entity = await message.client.get_entity(target_id)
is_channel = isinstance(entity, Channel)
target_name = entity.title if is_channel else entity.first_name
if is_channel:
if target_id in user_a["chats"]:
user_a["chats"].remove(target_id)
msg = f"<emoji document_id=5774022692642492953>✅</emoji> <b>Доступ отключен для чата {target_name}</b>"
else:
user_a["chats"].append(target_id)
msg = f"<emoji document_id=5774022692642492953>✅</emoji> <b>Доступ включен для чата {target_name}</b>"
else:
if target_id in user_a["users"]:
user_a["users"].remove(target_id)
msg = f"<emoji document_id=5774022692642492953>✅</emoji> <b>Доступ отключен для пользователя {target_name}</b>"
else:
user_a["users"].append(target_id)
msg = f"<emoji document_id=5774022692642492953>✅</emoji> <b>Доступ включен для пользователя {target_name}</b>"
self.db.set("RPMod", "useraccept", user_a)
await utils.answer(message, msg)
except Exception as e:
await utils.answer(
message,
f"<emoji document_id=5774077015388852135>❌</emoji> <b>Ошибка:</b> {str(e)}"
)
else:
await utils.answer(
message,
"<blockquote><emoji document_id=6028435952299413210>ℹ</emoji> <b>Используйте:</b></blockquote>\n"
"<code>.rpa</code> <b>в чате - для управления доступом чата.</b>\n"
"<code>.rpa [ID]</code> <b>- для управления по ID.</b>\n"
"<code>.rpa</code> <b>в ответ на сообщение - для управления пользователем.</b>\n"
"<code>.rpa -l</code> <b>- чтобы показать список доступов.</b>"
)
async def watcher(self, message):
try:
status = self.db.get("RPMod", "status", 0)
commands = self.db.get("RPMod", "nrpcommands", {})
users_accept = self.db.get("RPMod", "useraccept", {"users": [], "chats": []})
if status != 1:
return
me_id = (await message.client.get_me()).id
if (message.sender_id not in users_accept["users"] and
message.sender_id != me_id and
message.chat_id not in users_accept["chats"]):
return
me = await message.client.get_entity(message.sender_id)
text = message.text or ""
lines = text.splitlines()
if not lines:
return
words = lines[0].split()
if not words:
return
found_command = None
for i in range(min(3, len(words)), 0, -1):
possible_command = " ".join(words[:i]).casefold()
if possible_command in commands:
found_command = possible_command
remaining_text = " ".join(words[i:]) if i < len(words) else ""
break
if not found_command:
return
if len(words) > 1 and words[-1].startswith("@"):
target_mention = words[-1][1:]
try:
if target_mention.isdigit():
user = await message.client.get_entity(int(target_mention))
else:
user = await message.client.get_entity(target_mention)
remaining_text = " ".join(words[len(found_command.split()):-1])
except:
reply = await message.get_reply_message()
if reply:
user = await message.client.get_entity(reply.sender_id)
else:
return
else:
reply = await message.get_reply_message()
if reply:
user = await message.client.get_entity(reply.sender_id)
else:
return
command = commands[found_command]
replica = ""
if len(lines) > 1:
replica = "\n".join(lines[1:])
action_decoration = self.config.get('action_decoration', '')
replica_decoration = self.config.get('replica_decoration', '')
bubble = self.config.get('speech_bubble', '💬')
s1 = {
'bold': ("<b>", "</b>"),
'italic': ("<i>", "</i>"),
'underline': ("<u>", "</u>"),
'strikethrough': ("<s>", "</s>"),
'spoiler': ("<spoiler>", "</spoiler>")
}.get(action_decoration, ("", ""))
s2 = {
'bold': ("<b>", "</b>"),
'italic': ("<i>", "</i>"),
'underline': ("<u>", "</u>"),
'strikethrough': ("<s>", "</s>"),
'spoiler': ("<spoiler>", "</spoiler>")
}.get(replica_decoration, ("", ""))
rp_message = []
if command[1]:
rp_message.append(f"{command[1]} | ")
rp_message.append(
f"<a href='tg://user?id={me.id}'>{me.first_name}</a> "
f"{s1[0]}{command[0]}{s1[1]} "
f"<a href='tg://user?id={user.id}'>{user.first_name}</a>"
)
if remaining_text:
rp_message.append(remaining_text)
if replica:
rp_message.append(f"\n{bubble} <b>С репликой:</b> {s2[0]}{replica}{s2[1]}")
await utils.answer(message, "".join(rp_message))
except Exception as e:
pass
@staticmethod
def merge_dict(d1, d2):
d_all = {**d1, **d2}
for key in d_all:
d_all[key] = {**d1[key], **d_all[key]}
return d_all