Karma commited on
Commit
097c654
·
2 Parent(s): b9c2de7 681cb31

Merge pull request #149 from Infamous-Hydra/Miko3.0

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. Database/mongodb/afk_db.py +53 -0
  2. Database/mongodb/blacklistdb.py +51 -0
  3. Database/mongodb/locale_db.py +22 -0
  4. Database/mongodb/sangmata_db.py +42 -0
  5. Database/mongodb/users_chats_db.py +111 -0
  6. Database/sql/afk_sql.py +1 -1
  7. Database/sql/antichannel_sql.py +88 -0
  8. Database/sql/antiflood_sql.py +49 -23
  9. Database/sql/antilinkedchannel_sql.py +142 -0
  10. Database/sql/approve_sql.py +25 -1
  11. Database/sql/blacklist_sql.py +29 -6
  12. Database/sql/blacklistusers_sql.py +25 -4
  13. Database/sql/blsticker_sql.py +29 -6
  14. Database/sql/cleaner_sql.py +225 -0
  15. Database/sql/connection_sql.py +37 -11
  16. Database/sql/cust_filters_sql.py +135 -30
  17. Database/sql/disable_sql.py +25 -1
  18. Database/sql/fontsql.py +2361 -0
  19. Database/sql/forceSubscribe_sql.py +46 -0
  20. Database/sql/locks_sql.py +292 -0
  21. Database/sql/log_channel_sql.py +24 -0
  22. Database/sql/nightmode_sql.py +42 -0
  23. Database/sql/notes_sql.py +31 -8
  24. Database/sql/raid_sql.py +73 -0
  25. Database/sql/remind_sql.py +140 -0
  26. Database/sql/reporting_sql.py +115 -0
  27. Database/sql/userinfo_sql.py +26 -2
  28. Database/sql/users_sql.py +28 -5
  29. Database/sql/warns_sql.py +31 -17
  30. Database/sql/welcome_sql.py +98 -19
  31. Dockerfile +1 -1
  32. Infamous/karma.py +2 -3
  33. Mikobot/__init__.py +3 -3
  34. Mikobot/__main__.py +286 -66
  35. Mikobot/elevated_users.json +8 -0
  36. Mikobot/plugins/afk.py +6 -0
  37. Mikobot/plugins/ai.py +2 -2
  38. Mikobot/plugins/alive.py +2 -2
  39. Mikobot/plugins/anime.py +134 -112
  40. Mikobot/plugins/approve.py +0 -9
  41. Mikobot/plugins/ban.py +1 -9
  42. Mikobot/plugins/blacklist.py +15 -25
  43. Mikobot/plugins/blacklist_stickers.py +15 -21
  44. Mikobot/plugins/botadmins.py +1 -1
  45. Mikobot/plugins/bug.py +45 -0
  46. Mikobot/plugins/{chatbot.py → chatbot.py.txt} +0 -0
  47. Mikobot/plugins/connection.py +5 -3
  48. Mikobot/plugins/couple.py +43 -25
  49. Mikobot/plugins/cust_filters.py +42 -33
  50. Mikobot/plugins/disasters.py +129 -0
Database/mongodb/afk_db.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from Database.mongodb.db import dbname
2
+
3
+ usersdb = dbname.users
4
+ cleandb = dbname.cleanmode
5
+ cleanmode = {}
6
+
7
+
8
+ async def is_cleanmode_on(chat_id: int) -> bool:
9
+ mode = cleanmode.get(chat_id)
10
+ if not mode:
11
+ user = await cleandb.find_one({"chat_id": chat_id})
12
+ if not user:
13
+ cleanmode[chat_id] = True
14
+ return True
15
+ cleanmode[chat_id] = False
16
+ return False
17
+ return mode
18
+
19
+
20
+ async def cleanmode_on(chat_id: int):
21
+ cleanmode[chat_id] = True
22
+ user = await cleandb.find_one({"chat_id": chat_id})
23
+ if user:
24
+ return await cleandb.delete_one({"chat_id": chat_id})
25
+
26
+
27
+ async def cleanmode_off(chat_id: int):
28
+ cleanmode[chat_id] = False
29
+ user = await cleandb.find_one({"chat_id": chat_id})
30
+ if not user:
31
+ return await cleandb.insert_one({"chat_id": chat_id})
32
+
33
+
34
+ async def is_afk(user_id: int) -> bool:
35
+ user = await usersdb.find_one({"user_id": user_id})
36
+ return (True, user["reason"]) if user else (False, {})
37
+
38
+
39
+ async def add_afk(user_id: int, mode):
40
+ await usersdb.update_one(
41
+ {"user_id": user_id}, {"$set": {"reason": mode}}, upsert=True
42
+ )
43
+
44
+
45
+ async def remove_afk(user_id: int):
46
+ user = await usersdb.find_one({"user_id": user_id})
47
+ if user:
48
+ return await usersdb.delete_one({"user_id": user_id})
49
+
50
+
51
+ async def get_afk_users() -> list:
52
+ users = usersdb.find({"user_id": {"$gt": 0}})
53
+ return list(await users.to_list(length=1000000000)) if users else []
Database/mongodb/blacklistdb.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import codecs
2
+ import pickle
3
+ from typing import List
4
+
5
+ from Database.mongodb.db import dbname
6
+
7
+ blacklist_filtersdb = dbname.blacklistFilters
8
+
9
+
10
+ def obj_to_str(obj):
11
+ if not obj:
12
+ return False
13
+ string = codecs.encode(pickle.dumps(obj), "base64").decode()
14
+ return string
15
+
16
+
17
+ def str_to_obj(string: str):
18
+ obj = pickle.loads(codecs.decode(string.encode(), "base64"))
19
+ return obj
20
+
21
+
22
+ async def get_blacklisted_words(chat_id: int) -> List[str]:
23
+ _filters = await blacklist_filtersdb.find_one({"chat_id": chat_id})
24
+ if not _filters:
25
+ return []
26
+ return _filters["filters"]
27
+
28
+
29
+ async def save_blacklist_filter(chat_id: int, word: str):
30
+ word = word.lower().strip()
31
+ _filters = await get_blacklisted_words(chat_id)
32
+ _filters.append(word)
33
+ await blacklist_filtersdb.update_one(
34
+ {"chat_id": chat_id},
35
+ {"$set": {"filters": _filters}},
36
+ upsert=True,
37
+ )
38
+
39
+
40
+ async def delete_blacklist_filter(chat_id: int, word: str) -> bool:
41
+ filtersd = await get_blacklisted_words(chat_id)
42
+ word = word.lower().strip()
43
+ if word in filtersd:
44
+ filtersd.remove(word)
45
+ await blacklist_filtersdb.update_one(
46
+ {"chat_id": chat_id},
47
+ {"$set": {"filters": filtersd}},
48
+ upsert=True,
49
+ )
50
+ return True
51
+ return False
Database/mongodb/locale_db.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Iterable
2
+
3
+ from pyrogram.enums import ChatType
4
+
5
+ from Database.mongodb.db import dbname
6
+
7
+ localesdb = dbname.locale # DB for localization
8
+
9
+ group_types: Iterable[ChatType] = (ChatType.GROUP, ChatType.SUPERGROUP)
10
+
11
+
12
+ async def set_db_lang(chat_id: int, chat_type: str, lang_code: str):
13
+ await localesdb.update_one(
14
+ {"chat_id": chat_id},
15
+ {"$set": {"lang": lang_code, "chat_type": chat_type.value}},
16
+ upsert=True,
17
+ )
18
+
19
+
20
+ async def get_db_lang(chat_id: int) -> str:
21
+ ul = await localesdb.find_one({"chat_id": chat_id})
22
+ return ul["lang"] if ul else {}
Database/mongodb/sangmata_db.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from Database.mongodb.db import dbname
2
+
3
+ matadb = dbname["sangmata"]
4
+
5
+
6
+ # Get Data User
7
+ async def cek_userdata(user_id: int) -> bool:
8
+ user = await matadb.find_one({"user_id": user_id})
9
+ return bool(user)
10
+
11
+
12
+ async def get_userdata(user_id: int) -> bool:
13
+ user = await matadb.find_one({"user_id": user_id})
14
+ return user["username"], user["first_name"], user["last_name"]
15
+
16
+
17
+ async def add_userdata(user_id: int, username, first_name, last_name):
18
+ await matadb.update_one(
19
+ {"user_id": user_id},
20
+ {
21
+ "$set": {
22
+ "username": username,
23
+ "first_name": first_name,
24
+ "last_name": last_name,
25
+ }
26
+ },
27
+ upsert=True,
28
+ )
29
+
30
+
31
+ # Enable Mata MissKaty in Selected Chat
32
+ async def is_sangmata_on(chat_id: int) -> bool:
33
+ chat = await matadb.find_one({"chat_id_toggle": chat_id})
34
+ return bool(chat)
35
+
36
+
37
+ async def sangmata_on(chat_id: int) -> bool:
38
+ await matadb.insert_one({"chat_id_toggle": chat_id})
39
+
40
+
41
+ async def sangmata_off(chat_id: int):
42
+ await matadb.delete_one({"chat_id_toggle": chat_id})
Database/mongodb/users_chats_db.py ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from async_pymongo import AsyncClient
2
+
3
+ from Mikobot import DB_NAME, MONGO_DB_URI
4
+
5
+
6
+ class UsersData:
7
+ def __init__(self, uri, database_name):
8
+ self._client = AsyncClient(uri)
9
+ self.db = self._client[database_name]
10
+ self.col = self.db["userlist"]
11
+ self.grp = self.db["groups"]
12
+
13
+ @staticmethod
14
+ def new_user(id, name):
15
+ return dict(
16
+ id=id,
17
+ name=name,
18
+ ban_status=dict(
19
+ is_banned=False,
20
+ ban_reason="",
21
+ ),
22
+ )
23
+
24
+ @staticmethod
25
+ def new_group(id, title):
26
+ return dict(
27
+ id=id,
28
+ title=title,
29
+ chat_status=dict(
30
+ is_disabled=False,
31
+ reason="",
32
+ ),
33
+ )
34
+
35
+ async def add_user(self, id, name):
36
+ user = self.new_user(id, name)
37
+ await self.col.insert_one(user)
38
+
39
+ async def is_user_exist(self, id):
40
+ user = await self.col.find_one({"id": int(id)})
41
+ return bool(user)
42
+
43
+ async def total_users_count(self):
44
+ return await self.col.count_documents({})
45
+
46
+ async def remove_ban(self, id):
47
+ return await self.col.delete_one({"_id": id})
48
+
49
+ async def ban_user(self, user_id, ban_reason="No Reason"):
50
+ return await self.col.insert_one({"_id": user_id, "reason": ban_reason})
51
+
52
+ async def get_ban_status(self, id):
53
+ user = await self.col.find_one({"_id": int(id)})
54
+ if user:
55
+ return True, user
56
+ return False, None
57
+
58
+ async def get_all_users(self):
59
+ return self.col.find({})
60
+
61
+ async def delete_user(self, user_id):
62
+ await self.col.delete_many({"id": int(user_id)})
63
+
64
+ async def is_chat_exist(self, id):
65
+ user = await self.grp.find_one({"id": int(id)})
66
+ return bool(user)
67
+
68
+ async def get_banned(self):
69
+ users = self.col.find({"ban_status.is_banned": True})
70
+ chats = self.grp.find({"chat_status.is_disabled": True})
71
+ b_chats = [chat["id"] async for chat in chats]
72
+ b_users = [user["id"] async for user in users]
73
+ return b_users, b_chats
74
+
75
+ async def add_chat(self, chat, title):
76
+ chat = self.new_group(chat, title)
77
+ await self.grp.insert_one(chat)
78
+
79
+ async def get_chat(self, chat):
80
+ chat = await self.grp.find_one({"id": int(chat)})
81
+ return chat.get("chat_status") if chat else False
82
+
83
+ async def re_enable_chat(self, id):
84
+ chat_status = dict(
85
+ is_disabled=False,
86
+ reason="",
87
+ )
88
+ await self.grp.update_one(
89
+ {"id": int(id)}, {"$set": {"chat_status": chat_status}}
90
+ )
91
+
92
+ async def disable_chat(self, chat, reason="No Reason"):
93
+ chat_status = dict(
94
+ is_disabled=True,
95
+ reason=reason,
96
+ )
97
+ await self.grp.update_one(
98
+ {"id": int(chat)}, {"$set": {"chat_status": chat_status}}
99
+ )
100
+
101
+ async def total_chat_count(self):
102
+ return await self.grp.count_documents({})
103
+
104
+ async def get_all_chats(self):
105
+ return self.grp.find({})
106
+
107
+ async def get_db_size(self):
108
+ return (await self.db.command("dbstats"))["dataSize"]
109
+
110
+
111
+ db = UsersData(MONGO_DB_URI, DB_NAME)
Database/sql/afk_sql.py CHANGED
@@ -7,7 +7,7 @@ from Database.sql import BASE, SESSION
7
 
8
 
9
  class AFK(BASE):
10
- __tablename__ = "afk_users"
11
 
12
  user_id = Column(BigInteger, primary_key=True)
13
  is_afk = Column(Boolean)
 
7
 
8
 
9
  class AFK(BASE):
10
+ __tablename__ = "afk_user"
11
 
12
  user_id = Column(BigInteger, primary_key=True)
13
  is_afk = Column(Boolean)
Database/sql/antichannel_sql.py ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
+ import threading
26
+
27
+ from sqlalchemy import Boolean, Column
28
+ from sqlalchemy.sql.sqltypes import String
29
+
30
+ from Database.sql import BASE, SESSION
31
+
32
+
33
+ class AntiChannelSettings(BASE):
34
+ __tablename__ = "anti_channel_settings"
35
+
36
+ chat_id = Column(String(14), primary_key=True)
37
+ setting = Column(Boolean, default=False, nullable=False)
38
+
39
+ def __init__(self, chat_id: int, disabled: bool):
40
+ self.chat_id = str(chat_id)
41
+ self.setting = disabled
42
+
43
+ def __repr__(self):
44
+ return "<ᴀɴᴛɪғʟᴏᴏᴅ sᴇᴛᴛɪɴɢ {} ({})>".format(self.chat_id, self.setting)
45
+
46
+
47
+ AntiChannelSettings.__table__.create(checkfirst=True)
48
+ ANTICHANNEL_SETTING_LOCK = threading.RLock()
49
+
50
+
51
+ def enable_antichannel(chat_id: int):
52
+ with ANTICHANNEL_SETTING_LOCK:
53
+ chat = SESSION.query(AntiChannelSettings).get(str(chat_id))
54
+ if not chat:
55
+ chat = AntiChannelSettings(str(chat_id), True)
56
+
57
+ chat.setting = True
58
+ SESSION.add(chat)
59
+ SESSION.commit()
60
+
61
+
62
+ def disable_antichannel(chat_id: int):
63
+ with ANTICHANNEL_SETTING_LOCK:
64
+ chat = SESSION.query(AntiChannelSettings).get(str(chat_id))
65
+ if not chat:
66
+ chat = AntiChannelSettings(str(chat_id), False)
67
+
68
+ chat.setting = False
69
+ SESSION.add(chat)
70
+ SESSION.commit()
71
+
72
+
73
+ def antichannel_status(chat_id: int) -> bool:
74
+ with ANTICHANNEL_SETTING_LOCK:
75
+ d = SESSION.query(AntiChannelSettings).get(str(chat_id))
76
+ if not d:
77
+ return False
78
+ return d.setting
79
+
80
+
81
+ def migrate_chat(old_chat_id, new_chat_id):
82
+ with ANTICHANNEL_SETTING_LOCK:
83
+ chat = SESSION.query(AntiChannelSettings).get(str(old_chat_id))
84
+ if chat:
85
+ chat.chat_id = new_chat_id
86
+ SESSION.add(chat)
87
+
88
+ SESSION.commit()
Database/sql/antiflood_sql.py CHANGED
@@ -1,6 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
 
3
- from sqlalchemy import BigInteger, Column, Integer, String, UnicodeText
4
 
5
  from Database.sql import BASE, SESSION
6
 
@@ -13,20 +37,20 @@ class FloodControl(BASE):
13
  __tablename__ = "antiflood"
14
  chat_id = Column(String(14), primary_key=True)
15
  user_id = Column(BigInteger)
16
- count = Column(Integer, default=DEF_COUNT)
17
- limit = Column(Integer, default=DEF_LIMIT)
18
 
19
  def __init__(self, chat_id):
20
  self.chat_id = str(chat_id) # ensure string
21
 
22
  def __repr__(self):
23
- return "<flood control for %s>" % self.chat_id
24
 
25
 
26
  class FloodSettings(BASE):
27
  __tablename__ = "antiflood_settings"
28
  chat_id = Column(String(14), primary_key=True)
29
- flood_type = Column(Integer, default=1)
30
  value = Column(UnicodeText, default="0")
31
 
32
  def __init__(self, chat_id, flood_type=1, value="0"):
@@ -35,7 +59,7 @@ class FloodSettings(BASE):
35
  self.value = value
36
 
37
  def __repr__(self):
38
- return "<{} will executing {} for flood.>".format(self.chat_id, self.flood_type)
39
 
40
 
41
  FloodControl.__table__.create(checkfirst=True)
@@ -63,37 +87,40 @@ def set_flood(chat_id, amount):
63
 
64
 
65
  def update_flood(chat_id: str, user_id) -> bool:
66
- if str(chat_id) in CHAT_FLOOD:
67
- curr_user_id, count, limit = CHAT_FLOOD.get(str(chat_id), DEF_OBJ)
68
-
69
- if limit == 0: # no antiflood
70
- return False
71
 
72
- if user_id != curr_user_id or user_id is None: # other user
73
- CHAT_FLOOD[str(chat_id)] = (user_id, DEF_COUNT, limit)
74
- return False
75
 
76
- count += 1
77
- if count > limit: # too many msgs, kick
78
- CHAT_FLOOD[str(chat_id)] = (None, DEF_COUNT, limit)
79
- return True
80
 
81
- # default -> update
82
- CHAT_FLOOD[str(chat_id)] = (user_id, count, limit)
83
  return False
84
 
 
 
 
 
 
 
 
 
 
85
 
86
  def get_flood_limit(chat_id):
87
  return CHAT_FLOOD.get(str(chat_id), DEF_OBJ)[2]
88
 
89
 
90
  def set_flood_strength(chat_id, flood_type, value):
91
- # for flood_type
92
  # 1 = ban
93
  # 2 = kick
94
  # 3 = mute
95
  # 4 = tban
96
  # 5 = tmute
 
97
  with INSERTION_FLOOD_SETTINGS_LOCK:
98
  curr_setting = SESSION.query(FloodSettings).get(str(chat_id))
99
  if not curr_setting:
@@ -115,8 +142,7 @@ def get_flood_setting(chat_id):
115
  setting = SESSION.query(FloodSettings).get(str(chat_id))
116
  if setting:
117
  return setting.flood_type, setting.value
118
- else:
119
- return 1, "0"
120
 
121
  finally:
122
  SESSION.close()
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import threading
26
 
27
+ from sqlalchemy import BigInteger, Column, String, UnicodeText
28
 
29
  from Database.sql import BASE, SESSION
30
 
 
37
  __tablename__ = "antiflood"
38
  chat_id = Column(String(14), primary_key=True)
39
  user_id = Column(BigInteger)
40
+ count = Column(BigInteger, default=DEF_COUNT)
41
+ limit = Column(BigInteger, default=DEF_LIMIT)
42
 
43
  def __init__(self, chat_id):
44
  self.chat_id = str(chat_id) # ensure string
45
 
46
  def __repr__(self):
47
+ return "<ғʟᴏᴏᴅ ᴄᴏɴᴛʀᴏʟ ғᴏʀ %s>" % self.chat_id
48
 
49
 
50
  class FloodSettings(BASE):
51
  __tablename__ = "antiflood_settings"
52
  chat_id = Column(String(14), primary_key=True)
53
+ flood_type = Column(BigInteger, default=1)
54
  value = Column(UnicodeText, default="0")
55
 
56
  def __init__(self, chat_id, flood_type=1, value="0"):
 
59
  self.value = value
60
 
61
  def __repr__(self):
62
+ return "<{} ᴡɪʟʟ ᴇxᴇᴄᴜᴛɪɴɢ {} ғᴏʀ ғʟᴏᴏᴅ.>".format(self.chat_id, self.flood_type)
63
 
64
 
65
  FloodControl.__table__.create(checkfirst=True)
 
87
 
88
 
89
  def update_flood(chat_id: str, user_id) -> bool:
90
+ if str(chat_id) not in CHAT_FLOOD:
91
+ return
 
 
 
92
 
93
+ curr_user_id, count, limit = CHAT_FLOOD.get(str(chat_id), DEF_OBJ)
 
 
94
 
95
+ if limit == 0: # no antiflood
96
+ return False
 
 
97
 
98
+ if user_id != curr_user_id or user_id is None: # other user
99
+ CHAT_FLOOD[str(chat_id)] = (user_id, DEF_COUNT, limit)
100
  return False
101
 
102
+ count += 1
103
+ if count > limit: # too many msgs, kick
104
+ CHAT_FLOOD[str(chat_id)] = (None, DEF_COUNT, limit)
105
+ return True
106
+
107
+ # default -> update
108
+ CHAT_FLOOD[str(chat_id)] = (user_id, count, limit)
109
+ return False
110
+
111
 
112
  def get_flood_limit(chat_id):
113
  return CHAT_FLOOD.get(str(chat_id), DEF_OBJ)[2]
114
 
115
 
116
  def set_flood_strength(chat_id, flood_type, value):
117
+ # ғᴏʀ ғʟᴏᴏᴅ_ᴛʏᴘᴇ
118
  # 1 = ban
119
  # 2 = kick
120
  # 3 = mute
121
  # 4 = tban
122
  # 5 = tmute
123
+ # 6 = ᴅᴍᴜᴛᴇ sᴏᴏɴ
124
  with INSERTION_FLOOD_SETTINGS_LOCK:
125
  curr_setting = SESSION.query(FloodSettings).get(str(chat_id))
126
  if not curr_setting:
 
142
  setting = SESSION.query(FloodSettings).get(str(chat_id))
143
  if setting:
144
  return setting.flood_type, setting.value
145
+ return 1, "0"
 
146
 
147
  finally:
148
  SESSION.close()
Database/sql/antilinkedchannel_sql.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
+ import threading
26
+
27
+ from sqlalchemy import Boolean, Column
28
+ from sqlalchemy.sql.sqltypes import String
29
+
30
+ from Database.sql import BASE, SESSION
31
+
32
+
33
+ class AntiLinkedChannelSettings(BASE):
34
+ __tablename__ = "anti_linked_channel_settings"
35
+
36
+ chat_id = Column(String(14), primary_key=True)
37
+ setting = Column(Boolean, default=False, nullable=False)
38
+
39
+ def __init__(self, chat_id: int, disabled: bool):
40
+ self.chat_id = str(chat_id)
41
+ self.setting = disabled
42
+
43
+ def __repr__(self):
44
+ return "<Antilinked setting {} ({})>".format(self.chat_id, self.setting)
45
+
46
+
47
+ class AntiPinChannelSettings(BASE):
48
+ __tablename__ = "anti_pin_channel_settings"
49
+
50
+ chat_id = Column(String(14), primary_key=True)
51
+ setting = Column(Boolean, default=False, nullable=False)
52
+
53
+ def __init__(self, chat_id: int, disabled: bool):
54
+ self.chat_id = str(chat_id)
55
+ self.setting = disabled
56
+
57
+ def __repr__(self):
58
+ return "<ᴀɴᴛɪᴘɪɴ sᴇᴛᴛɪɴɢ {} ({})>".format(self.chat_id, self.setting)
59
+
60
+
61
+ AntiLinkedChannelSettings.__table__.create(checkfirst=True)
62
+ ANTI_LINKED_CHANNEL_SETTING_LOCK = threading.RLock()
63
+
64
+ AntiPinChannelSettings.__table__.create(checkfirst=True)
65
+ ANTI_PIN_CHANNEL_SETTING_LOCK = threading.RLock()
66
+
67
+
68
+ def enable_linked(chat_id: int):
69
+ with ANTI_LINKED_CHANNEL_SETTING_LOCK:
70
+ chat = SESSION.query(AntiLinkedChannelSettings).get(str(chat_id))
71
+ if not chat:
72
+ chat = AntiLinkedChannelSettings(chat_id, True)
73
+
74
+ chat.setting = True
75
+ SESSION.add(chat)
76
+ SESSION.commit()
77
+
78
+
79
+ def enable_pin(chat_id: int):
80
+ with ANTI_PIN_CHANNEL_SETTING_LOCK:
81
+ chat = SESSION.query(AntiPinChannelSettings).get(str(chat_id))
82
+ if not chat:
83
+ chat = AntiPinChannelSettings(chat_id, True)
84
+
85
+ chat.setting = True
86
+ SESSION.add(chat)
87
+ SESSION.commit()
88
+
89
+
90
+ def disable_linked(chat_id: int):
91
+ with ANTI_LINKED_CHANNEL_SETTING_LOCK:
92
+ chat = SESSION.query(AntiLinkedChannelSettings).get(str(chat_id))
93
+ if not chat:
94
+ chat = AntiLinkedChannelSettings(chat_id, False)
95
+
96
+ chat.setting = False
97
+ SESSION.add(chat)
98
+ SESSION.commit()
99
+
100
+
101
+ def disable_pin(chat_id: int):
102
+ with ANTI_PIN_CHANNEL_SETTING_LOCK:
103
+ chat = SESSION.query(AntiPinChannelSettings).get(str(chat_id))
104
+ if not chat:
105
+ chat = AntiPinChannelSettings(chat_id, False)
106
+
107
+ chat.setting = False
108
+ SESSION.add(chat)
109
+ SESSION.commit()
110
+
111
+
112
+ def status_linked(chat_id: int) -> bool:
113
+ with ANTI_LINKED_CHANNEL_SETTING_LOCK:
114
+ d = SESSION.query(AntiLinkedChannelSettings).get(str(chat_id))
115
+ if not d:
116
+ return False
117
+ return d.setting
118
+
119
+
120
+ def status_pin(chat_id: int) -> bool:
121
+ with ANTI_PIN_CHANNEL_SETTING_LOCK:
122
+ d = SESSION.query(AntiPinChannelSettings).get(str(chat_id))
123
+ if not d:
124
+ return False
125
+ return d.setting
126
+
127
+
128
+ def migrate_chat(old_chat_id, new_chat_id):
129
+ with ANTI_LINKED_CHANNEL_SETTING_LOCK:
130
+ chat = SESSION.query(AntiLinkedChannelSettings).get(str(old_chat_id))
131
+ if chat:
132
+ chat.chat_id = new_chat_id
133
+ SESSION.add(chat)
134
+
135
+ SESSION.commit()
136
+ with ANTI_PIN_CHANNEL_SETTING_LOCK:
137
+ chat = SESSION.query(AntiPinChannelSettings).get(str(old_chat_id))
138
+ if chat:
139
+ chat.chat_id = new_chat_id
140
+ SESSION.add(chat)
141
+
142
+ SESSION.commit()
Database/sql/approve_sql.py CHANGED
@@ -1,3 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
 
3
  from sqlalchemy import BigInteger, Column, String
@@ -15,7 +39,7 @@ class Approvals(BASE):
15
  self.user_id = user_id
16
 
17
  def __repr__(self):
18
- return "<Approve %s>" % self.user_id
19
 
20
 
21
  Approvals.__table__.create(checkfirst=True)
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import threading
26
 
27
  from sqlalchemy import BigInteger, Column, String
 
39
  self.user_id = user_id
40
 
41
  def __repr__(self):
42
+ return "<ᴀᴘᴘʀᴏᴠᴇ %s>" % self.user_id
43
 
44
 
45
  Approvals.__table__.create(checkfirst=True)
Database/sql/blacklist_sql.py CHANGED
@@ -1,6 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
 
3
- from sqlalchemy import Column, Integer, String, UnicodeText, distinct, func
4
 
5
  from Database.sql import BASE, SESSION
6
 
@@ -15,7 +39,7 @@ class BlackListFilters(BASE):
15
  self.trigger = trigger
16
 
17
  def __repr__(self):
18
- return "<Blacklist filter '%s' for %s>" % (self.trigger, self.chat_id)
19
 
20
  def __eq__(self, other):
21
  return bool(
@@ -28,7 +52,7 @@ class BlackListFilters(BASE):
28
  class BlacklistSettings(BASE):
29
  __tablename__ = "blacklist_settings"
30
  chat_id = Column(String(14), primary_key=True)
31
- blacklist_type = Column(Integer, default=1)
32
  value = Column(UnicodeText, default="0")
33
 
34
  def __init__(self, chat_id, blacklist_type=1, value="0"):
@@ -37,7 +61,7 @@ class BlacklistSettings(BASE):
37
  self.value = value
38
 
39
  def __repr__(self):
40
- return "<{} will executing {} for blacklist trigger.>".format(
41
  self.chat_id,
42
  self.blacklist_type,
43
  )
@@ -146,8 +170,7 @@ def get_blacklist_setting(chat_id):
146
  setting = CHAT_SETTINGS_BLACKLISTS.get(str(chat_id))
147
  if setting:
148
  return setting["blacklist_type"], setting["value"]
149
- else:
150
- return 1, "0"
151
 
152
  finally:
153
  SESSION.close()
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import threading
26
 
27
+ from sqlalchemy import BigInteger, Column, String, UnicodeText, distinct, func
28
 
29
  from Database.sql import BASE, SESSION
30
 
 
39
  self.trigger = trigger
40
 
41
  def __repr__(self):
42
+ return "<ʙʟᴀᴄᴋʟɪsᴛ ғɪʟᴛᴇʀ '%s' ғᴏʀ %s>" % (self.trigger, self.chat_id)
43
 
44
  def __eq__(self, other):
45
  return bool(
 
52
  class BlacklistSettings(BASE):
53
  __tablename__ = "blacklist_settings"
54
  chat_id = Column(String(14), primary_key=True)
55
+ blacklist_type = Column(BigInteger, default=1)
56
  value = Column(UnicodeText, default="0")
57
 
58
  def __init__(self, chat_id, blacklist_type=1, value="0"):
 
61
  self.value = value
62
 
63
  def __repr__(self):
64
+ return "<{} ᴡɪʟʟ ᴇxᴇᴄᴜᴛɪɴɢ {} ғᴏʀ ʙʟᴀᴄᴋʟɪsᴛ ᴛʀɪɢɢᴇʀ.>".format(
65
  self.chat_id,
66
  self.blacklist_type,
67
  )
 
170
  setting = CHAT_SETTINGS_BLACKLISTS.get(str(chat_id))
171
  if setting:
172
  return setting["blacklist_type"], setting["value"]
173
+ return 1, "0"
 
174
 
175
  finally:
176
  SESSION.close()
Database/sql/blacklistusers_sql.py CHANGED
@@ -1,3 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
 
3
  from sqlalchemy import Column, String, UnicodeText
@@ -46,10 +70,7 @@ def unblacklist_user(user_id):
46
 
47
  def get_reason(user_id):
48
  user = SESSION.query(BlacklistUsers).get(str(user_id))
49
- rep = ""
50
- if user:
51
- rep = user.reason
52
-
53
  SESSION.close()
54
  return rep
55
 
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import threading
26
 
27
  from sqlalchemy import Column, String, UnicodeText
 
70
 
71
  def get_reason(user_id):
72
  user = SESSION.query(BlacklistUsers).get(str(user_id))
73
+ rep = user.reason if user else ""
 
 
 
74
  SESSION.close()
75
  return rep
76
 
Database/sql/blsticker_sql.py CHANGED
@@ -1,6 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
 
3
- from sqlalchemy import Column, Integer, String, UnicodeText, distinct, func
4
 
5
  from Database.sql import BASE, SESSION
6
 
@@ -15,7 +39,7 @@ class StickersFilters(BASE):
15
  self.trigger = trigger
16
 
17
  def __repr__(self):
18
- return "<Stickers filter '%s' for %s>" % (self.trigger, self.chat_id)
19
 
20
  def __eq__(self, other):
21
  return bool(
@@ -28,7 +52,7 @@ class StickersFilters(BASE):
28
  class StickerSettings(BASE):
29
  __tablename__ = "blsticker_settings"
30
  chat_id = Column(String(14), primary_key=True)
31
- blacklist_type = Column(Integer, default=1)
32
  value = Column(UnicodeText, default="0")
33
 
34
  def __init__(self, chat_id, blacklist_type=1, value="0"):
@@ -37,7 +61,7 @@ class StickerSettings(BASE):
37
  self.value = value
38
 
39
  def __repr__(self):
40
- return "<{} will executing {} for blacklist trigger.>".format(
41
  self.chat_id,
42
  self.blacklist_type,
43
  )
@@ -146,8 +170,7 @@ def get_blacklist_setting(chat_id):
146
  setting = CHAT_BLSTICK_BLACKLISTS.get(str(chat_id))
147
  if setting:
148
  return setting["blacklist_type"], setting["value"]
149
- else:
150
- return 1, "0"
151
 
152
  finally:
153
  SESSION.close()
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import threading
26
 
27
+ from sqlalchemy import BigInteger, Column, String, UnicodeText, distinct, func
28
 
29
  from Database.sql import BASE, SESSION
30
 
 
39
  self.trigger = trigger
40
 
41
  def __repr__(self):
42
+ return "<sᴛɪᴄᴋᴇʀs ғɪʟᴛᴇʀ '%s' ғᴏʀ %s>" % (self.trigger, self.chat_id)
43
 
44
  def __eq__(self, other):
45
  return bool(
 
52
  class StickerSettings(BASE):
53
  __tablename__ = "blsticker_settings"
54
  chat_id = Column(String(14), primary_key=True)
55
+ blacklist_type = Column(BigInteger, default=1)
56
  value = Column(UnicodeText, default="0")
57
 
58
  def __init__(self, chat_id, blacklist_type=1, value="0"):
 
61
  self.value = value
62
 
63
  def __repr__(self):
64
+ return "<{} ᴡɪʟʟ ᴇxᴇᴄᴜᴛɪɴɢ {} ғᴏʀ ʙʟᴀᴄᴋʟɪsᴛ ᴛʀɪɢɢᴇʀ.>".format(
65
  self.chat_id,
66
  self.blacklist_type,
67
  )
 
170
  setting = CHAT_BLSTICK_BLACKLISTS.get(str(chat_id))
171
  if setting:
172
  return setting["blacklist_type"], setting["value"]
173
+ return 1, "0"
 
174
 
175
  finally:
176
  SESSION.close()
Database/sql/cleaner_sql.py ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
+ import threading
26
+
27
+ from sqlalchemy import Boolean, Column, UnicodeText
28
+
29
+ from Database.sql import BASE, SESSION
30
+
31
+
32
+ class CleanerBlueTextChatSettings(BASE):
33
+ __tablename__ = "cleaner_bluetext_chat_setting"
34
+ chat_id = Column(UnicodeText, primary_key=True)
35
+ is_enable = Column(Boolean, default=False)
36
+
37
+ def __init__(self, chat_id, is_enable):
38
+ self.chat_id = chat_id
39
+ self.is_enable = is_enable
40
+
41
+ def __repr__(self):
42
+ return "ᴄʟᴇᴀɴ ʙʟᴜᴇ ᴛᴇxᴛ ғᴏʀ {}".format(self.chat_id)
43
+
44
+
45
+ class CleanerBlueTextChat(BASE):
46
+ __tablename__ = "cleaner_bluetext_chat_ignore_commands"
47
+ chat_id = Column(UnicodeText, primary_key=True)
48
+ command = Column(UnicodeText, primary_key=True)
49
+
50
+ def __init__(self, chat_id, command):
51
+ self.chat_id = chat_id
52
+ self.command = command
53
+
54
+
55
+ class CleanerBlueTextGlobal(BASE):
56
+ __tablename__ = "cleaner_bluetext_global_ignore_commands"
57
+ command = Column(UnicodeText, primary_key=True)
58
+
59
+ def __init__(self, command):
60
+ self.command = command
61
+
62
+
63
+ CleanerBlueTextChatSettings.__table__.create(checkfirst=True)
64
+ CleanerBlueTextChat.__table__.create(checkfirst=True)
65
+ CleanerBlueTextGlobal.__table__.create(checkfirst=True)
66
+
67
+ CLEANER_CHAT_SETTINGS = threading.RLock()
68
+ CLEANER_CHAT_LOCK = threading.RLock()
69
+ CLEANER_GLOBAL_LOCK = threading.RLock()
70
+
71
+ CLEANER_CHATS = {}
72
+ GLOBAL_IGNORE_COMMANDS = set()
73
+
74
+
75
+ def set_cleanbt(chat_id, is_enable):
76
+ with CLEANER_CHAT_SETTINGS:
77
+ curr = SESSION.query(CleanerBlueTextChatSettings).get(str(chat_id))
78
+
79
+ if not curr:
80
+ curr = CleanerBlueTextChatSettings(str(chat_id), is_enable)
81
+ else:
82
+ curr.is_enabled = is_enable
83
+
84
+ if str(chat_id) not in CLEANER_CHATS:
85
+ CLEANER_CHATS.setdefault(
86
+ str(chat_id), {"setting": False, "commands": set()}
87
+ )
88
+
89
+ CLEANER_CHATS[str(chat_id)]["setting"] = is_enable
90
+
91
+ SESSION.add(curr)
92
+ SESSION.commit()
93
+
94
+
95
+ def chat_ignore_command(chat_id, ignore):
96
+ ignore = ignore.lower()
97
+ with CLEANER_CHAT_LOCK:
98
+ ignored = SESSION.query(CleanerBlueTextChat).get((str(chat_id), ignore))
99
+
100
+ if not ignored:
101
+ if str(chat_id) not in CLEANER_CHATS:
102
+ CLEANER_CHATS.setdefault(
103
+ str(chat_id), {"setting": False, "commands": set()}
104
+ )
105
+
106
+ CLEANER_CHATS[str(chat_id)]["commands"].add(ignore)
107
+
108
+ ignored = CleanerBlueTextChat(str(chat_id), ignore)
109
+ SESSION.add(ignored)
110
+ SESSION.commit()
111
+ return True
112
+ SESSION.close()
113
+ return False
114
+
115
+
116
+ def chat_unignore_command(chat_id, unignore):
117
+ unignore = unignore.lower()
118
+ with CLEANER_CHAT_LOCK:
119
+ unignored = SESSION.query(CleanerBlueTextChat).get((str(chat_id), unignore))
120
+
121
+ if unignored:
122
+ if str(chat_id) not in CLEANER_CHATS:
123
+ CLEANER_CHATS.setdefault(
124
+ str(chat_id), {"setting": False, "commands": set()}
125
+ )
126
+ if unignore in CLEANER_CHATS.get(str(chat_id)).get("commands"):
127
+ CLEANER_CHATS[str(chat_id)]["commands"].remove(unignore)
128
+
129
+ SESSION.delete(unignored)
130
+ SESSION.commit()
131
+ return True
132
+
133
+ SESSION.close()
134
+ return False
135
+
136
+
137
+ def global_ignore_command(command):
138
+ command = command.lower()
139
+ with CLEANER_GLOBAL_LOCK:
140
+ ignored = SESSION.query(CleanerBlueTextGlobal).get(str(command))
141
+
142
+ if not ignored:
143
+ GLOBAL_IGNORE_COMMANDS.add(command)
144
+
145
+ ignored = CleanerBlueTextGlobal(str(command))
146
+ SESSION.add(ignored)
147
+ SESSION.commit()
148
+ return True
149
+
150
+ SESSION.close()
151
+ return False
152
+
153
+
154
+ def global_unignore_command(command):
155
+ command = command.lower()
156
+ with CLEANER_GLOBAL_LOCK:
157
+ unignored = SESSION.query(CleanerBlueTextGlobal).get(str(command))
158
+
159
+ if unignored:
160
+ if command in GLOBAL_IGNORE_COMMANDS:
161
+ GLOBAL_IGNORE_COMMANDS.remove(command)
162
+
163
+ SESSION.delete(command)
164
+ SESSION.commit()
165
+ return True
166
+
167
+ SESSION.close()
168
+ return False
169
+
170
+
171
+ def is_command_ignored(chat_id, command):
172
+ if command.lower() in GLOBAL_IGNORE_COMMANDS:
173
+ return True
174
+
175
+ if str(chat_id) in CLEANER_CHATS and command.lower() in CLEANER_CHATS.get(
176
+ str(chat_id)
177
+ ).get("commands"):
178
+ return True
179
+
180
+ return False
181
+
182
+
183
+ def is_enabled(chat_id):
184
+ if str(chat_id) in CLEANER_CHATS:
185
+ return CLEANER_CHATS.get(str(chat_id)).get("setting")
186
+
187
+ return False
188
+
189
+
190
+ def get_all_ignored(chat_id):
191
+ if str(chat_id) in CLEANER_CHATS:
192
+ LOCAL_IGNORE_COMMANDS = CLEANER_CHATS.get(str(chat_id)).get("commands")
193
+ else:
194
+ LOCAL_IGNORE_COMMANDS = set()
195
+
196
+ return GLOBAL_IGNORE_COMMANDS, LOCAL_IGNORE_COMMANDS
197
+
198
+
199
+ def __load_cleaner_list():
200
+ global GLOBAL_IGNORE_COMMANDS
201
+ global CLEANER_CHATS
202
+
203
+ try:
204
+ GLOBAL_IGNORE_COMMANDS = {
205
+ x.command for x in SESSION.query(CleanerBlueTextGlobal).all()
206
+ }
207
+ finally:
208
+ SESSION.close()
209
+
210
+ try:
211
+ for x in SESSION.query(CleanerBlueTextChatSettings).all():
212
+ CLEANER_CHATS.setdefault(x.chat_id, {"setting": False, "commands": set()})
213
+ CLEANER_CHATS[x.chat_id]["setting"] = x.is_enable
214
+ finally:
215
+ SESSION.close()
216
+
217
+ try:
218
+ for x in SESSION.query(CleanerBlueTextChat).all():
219
+ CLEANER_CHATS.setdefault(x.chat_id, {"setting": False, "commands": set()})
220
+ CLEANER_CHATS[x.chat_id]["commands"].add(x.command)
221
+ finally:
222
+ SESSION.close()
223
+
224
+
225
+ __load_cleaner_list()
Database/sql/connection_sql.py CHANGED
@@ -1,3 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
  import time
3
  from typing import Union
@@ -17,8 +41,9 @@ class ChatAccessConnectionSettings(BASE):
17
  self.allow_connect_to_chat = str(allow_connect_to_chat)
18
 
19
  def __repr__(self):
20
- return "<Chat access settings ({}) is {}>".format(
21
- self.chat_id, self.allow_connect_to_chat
 
22
  )
23
 
24
 
@@ -46,7 +71,7 @@ class ConnectionHistory(BASE):
46
  self.conn_time = int(conn_time)
47
 
48
  def __repr__(self):
49
- return "<connection user {} history {}>".format(self.user_id, self.chat_id)
50
 
51
 
52
  ChatAccessConnectionSettings.__table__.create(checkfirst=True)
@@ -113,9 +138,8 @@ def disconnect(user_id):
113
  SESSION.delete(disconnect)
114
  SESSION.commit()
115
  return True
116
- else:
117
- SESSION.close()
118
- return False
119
 
120
 
121
  def add_history_conn(user_id, chat_id, chat_name):
@@ -128,13 +152,15 @@ def add_history_conn(user_id, chat_id, chat_name):
128
  .filter(ConnectionHistory.user_id == str(user_id))
129
  .count()
130
  )
131
- getchat_id = {}
132
- for x in HISTORY_CONNECT[int(user_id)]:
133
- getchat_id[HISTORY_CONNECT[int(user_id)][x]["chat_id"]] = x
 
 
134
  if chat_id in getchat_id:
135
  todeltime = getchat_id[str(chat_id)]
136
  delold = SESSION.query(ConnectionHistory).get(
137
- (int(user_id), str(chat_id))
138
  )
139
  if delold:
140
  SESSION.delete(delold)
@@ -146,7 +172,7 @@ def add_history_conn(user_id, chat_id, chat_name):
146
  for x in todel:
147
  chat_old = HISTORY_CONNECT[int(user_id)][x]["chat_id"]
148
  delold = SESSION.query(ConnectionHistory).get(
149
- (int(user_id), str(chat_old))
150
  )
151
  if delold:
152
  SESSION.delete(delold)
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import threading
26
  import time
27
  from typing import Union
 
41
  self.allow_connect_to_chat = str(allow_connect_to_chat)
42
 
43
  def __repr__(self):
44
+ return "<ᴄʜᴀᴛ ᴀᴄᴄᴇss sᴇᴛᴛɪɴɢs ({}) is {}>".format(
45
+ self.chat_id,
46
+ self.allow_connect_to_chat,
47
  )
48
 
49
 
 
71
  self.conn_time = int(conn_time)
72
 
73
  def __repr__(self):
74
+ return "<ᴄᴏɴɴᴇᴄᴛɪᴏɴ ᴜsᴇʀ {} ʜɪsᴛᴏʀʏ {}>".format(self.user_id, self.chat_id)
75
 
76
 
77
  ChatAccessConnectionSettings.__table__.create(checkfirst=True)
 
138
  SESSION.delete(disconnect)
139
  SESSION.commit()
140
  return True
141
+ SESSION.close()
142
+ return False
 
143
 
144
 
145
  def add_history_conn(user_id, chat_id, chat_name):
 
152
  .filter(ConnectionHistory.user_id == str(user_id))
153
  .count()
154
  )
155
+ getchat_id = {
156
+ HISTORY_CONNECT[int(user_id)][x]["chat_id"]: x
157
+ for x in HISTORY_CONNECT[int(user_id)]
158
+ }
159
+
160
  if chat_id in getchat_id:
161
  todeltime = getchat_id[str(chat_id)]
162
  delold = SESSION.query(ConnectionHistory).get(
163
+ (int(user_id), str(chat_id)),
164
  )
165
  if delold:
166
  SESSION.delete(delold)
 
172
  for x in todel:
173
  chat_old = HISTORY_CONNECT[int(user_id)][x]["chat_id"]
174
  delold = SESSION.query(ConnectionHistory).get(
175
+ (int(user_id), str(chat_old)),
176
  )
177
  if delold:
178
  SESSION.delete(delold)
Database/sql/cust_filters_sql.py CHANGED
@@ -11,30 +11,80 @@ class CustomFilters(BASE):
11
  chat_id = Column(String(14), primary_key=True)
12
  keyword = Column(UnicodeText, primary_key=True, nullable=False)
13
  reply = Column(UnicodeText, nullable=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  reply_text = Column(UnicodeText)
15
  file_type = Column(Integer, nullable=False, default=1)
16
  file_id = Column(UnicodeText, default=None)
17
- has_buttons = Column(Boolean, nullable=False, default=False)
18
- # NOTE: Here for legacy purposes, to ensure older filters don't mess up.
19
- has_media_spoiler = Column(Boolean, nullable=False, default=False)
20
 
21
  def __init__(
22
  self,
23
- chat_id: int | str,
24
- keyword: str,
25
- reply: str,
26
- reply_text: str,
27
- has_buttons: bool,
28
- has_media_spoiler: bool,
29
- file_type: int,
30
- file_id: str,
 
 
 
 
 
31
  ):
32
  self.chat_id = str(chat_id) # ensure string
33
  self.keyword = keyword
34
  self.reply = reply
35
- self.reply_text = reply_text
 
 
 
 
 
36
  self.has_buttons = has_buttons
37
- self.has_media_spoiler = has_media_spoiler
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  self.file_type = file_type
39
  self.file_id = file_id
40
 
@@ -45,7 +95,7 @@ class CustomFilters(BASE):
45
  return bool(
46
  isinstance(other, CustomFilters)
47
  and self.chat_id == other.chat_id
48
- and self.keyword == other.keyword,
49
  )
50
 
51
 
@@ -81,6 +131,62 @@ def get_all_filters():
81
  SESSION.close()
82
 
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  def new_add_filter(
85
  chat_id, keyword, reply_text, file_type, file_id, buttons, media_spoiler
86
  ):
@@ -106,8 +212,13 @@ def new_add_filter(
106
  str(chat_id),
107
  keyword,
108
  reply="there is should be a new reply",
 
 
 
 
 
 
109
  has_buttons=bool(buttons),
110
- has_media_spoiler=media_spoiler,
111
  reply_text=reply_text,
112
  file_type=file_type.value,
113
  file_id=file_id,
@@ -168,7 +279,7 @@ def get_chat_filters(chat_id):
168
  SESSION.close()
169
 
170
 
171
- def get_filter(chat_id, keyword) -> CustomFilters:
172
  try:
173
  return SESSION.query(CustomFilters).get((str(chat_id), keyword))
174
  finally:
@@ -248,21 +359,14 @@ def __migrate_filters():
248
  else:
249
  file_type = Types.TEXT
250
 
 
251
  if file_type == Types.TEXT:
252
  filt = CustomFilters(
253
- str(x.chat_id),
254
- x.keyword,
255
- x.reply,
256
- file_type.value,
257
- None,
258
  )
259
  else:
260
  filt = CustomFilters(
261
- str(x.chat_id),
262
- x.keyword,
263
- None,
264
- file_type.value,
265
- x.reply,
266
  )
267
 
268
  SESSION.add(filt)
@@ -282,10 +386,11 @@ def migrate_chat(old_chat_id, new_chat_id):
282
  for filt in chat_filters:
283
  filt.chat_id = str(new_chat_id)
284
  SESSION.commit()
285
- old_filt = CHAT_FILTERS.get(str(old_chat_id))
286
- if old_filt:
287
- CHAT_FILTERS[str(new_chat_id)] = old_filt
288
- del CHAT_FILTERS[str(old_chat_id)]
 
289
 
290
  with BUTTON_LOCK:
291
  chat_buttons = (
 
11
  chat_id = Column(String(14), primary_key=True)
12
  keyword = Column(UnicodeText, primary_key=True, nullable=False)
13
  reply = Column(UnicodeText, nullable=False)
14
+ is_sticker = Column(Boolean, nullable=False, default=False)
15
+ is_document = Column(Boolean, nullable=False, default=False)
16
+ is_image = Column(Boolean, nullable=False, default=False)
17
+ is_audio = Column(Boolean, nullable=False, default=False)
18
+ is_voice = Column(Boolean, nullable=False, default=False)
19
+ is_video = Column(Boolean, nullable=False, default=False)
20
+
21
+ has_buttons = Column(Boolean, nullable=False, default=False)
22
+ # NOTE: Here for legacy purposes, to ensure older filters don't mess up.
23
+ has_markdown = Column(Boolean, nullable=False, default=False)
24
+
25
+ # NEW FILTER
26
+ # alter table cust_filters add column reply_text text;
27
+ # alter table cust_filters add column file_type integer default 1;
28
+ # alter table cust_filters add column file_id text;
29
  reply_text = Column(UnicodeText)
30
  file_type = Column(Integer, nullable=False, default=1)
31
  file_id = Column(UnicodeText, default=None)
 
 
 
32
 
33
  def __init__(
34
  self,
35
+ chat_id,
36
+ keyword,
37
+ reply,
38
+ is_sticker=False,
39
+ is_document=False,
40
+ is_image=False,
41
+ is_audio=False,
42
+ is_voice=False,
43
+ is_video=False,
44
+ has_buttons=False,
45
+ reply_text=None,
46
+ file_type=1,
47
+ file_id=None,
48
  ):
49
  self.chat_id = str(chat_id) # ensure string
50
  self.keyword = keyword
51
  self.reply = reply
52
+ self.is_sticker = is_sticker
53
+ self.is_document = is_document
54
+ self.is_image = is_image
55
+ self.is_audio = is_audio
56
+ self.is_voice = is_voice
57
+ self.is_video = is_video
58
  self.has_buttons = has_buttons
59
+ self.has_markdown = True
60
+
61
+ self.reply_text = reply_text
62
+ self.file_type = file_type
63
+ self.file_id = file_id
64
+
65
+ def __repr__(self):
66
+ return "<Permissions for %s>" % self.chat_id
67
+
68
+ def __eq__(self, other):
69
+ return bool(
70
+ isinstance(other, CustomFilters)
71
+ and self.chat_id == other.chat_id
72
+ and self.keyword == other.keyword
73
+ )
74
+
75
+
76
+ class NewCustomFilters(BASE):
77
+ __tablename__ = "cust_filters_new"
78
+ chat_id = Column(String(14), primary_key=True)
79
+ keyword = Column(UnicodeText, primary_key=True, nullable=False)
80
+ text = Column(UnicodeText)
81
+ file_type = Column(Integer, nullable=False, default=1)
82
+ file_id = Column(UnicodeText, default=None)
83
+
84
+ def __init__(self, chat_id, keyword, text, file_type, file_id):
85
+ self.chat_id = str(chat_id) # ensure string
86
+ self.keyword = keyword
87
+ self.text = text
88
  self.file_type = file_type
89
  self.file_id = file_id
90
 
 
95
  return bool(
96
  isinstance(other, CustomFilters)
97
  and self.chat_id == other.chat_id
98
+ and self.keyword == other.keyword
99
  )
100
 
101
 
 
131
  SESSION.close()
132
 
133
 
134
+ def add_filter(
135
+ chat_id,
136
+ keyword,
137
+ reply,
138
+ is_sticker=False,
139
+ is_document=False,
140
+ is_image=False,
141
+ is_audio=False,
142
+ is_voice=False,
143
+ is_video=False,
144
+ buttons=None,
145
+ ):
146
+ global CHAT_FILTERS
147
+
148
+ if buttons is None:
149
+ buttons = []
150
+
151
+ with CUST_FILT_LOCK:
152
+ prev = SESSION.query(CustomFilters).get((str(chat_id), keyword))
153
+ if prev:
154
+ with BUTTON_LOCK:
155
+ prev_buttons = (
156
+ SESSION.query(Buttons)
157
+ .filter(Buttons.chat_id == str(chat_id), Buttons.keyword == keyword)
158
+ .all()
159
+ )
160
+ for btn in prev_buttons:
161
+ SESSION.delete(btn)
162
+ SESSION.delete(prev)
163
+
164
+ filt = CustomFilters(
165
+ str(chat_id),
166
+ keyword,
167
+ reply,
168
+ is_sticker,
169
+ is_document,
170
+ is_image,
171
+ is_audio,
172
+ is_voice,
173
+ is_video,
174
+ bool(buttons),
175
+ )
176
+
177
+ if keyword not in CHAT_FILTERS.get(str(chat_id), []):
178
+ CHAT_FILTERS[str(chat_id)] = sorted(
179
+ CHAT_FILTERS.get(str(chat_id), []) + [keyword],
180
+ key=lambda x: (-len(x), x),
181
+ )
182
+
183
+ SESSION.add(filt)
184
+ SESSION.commit()
185
+
186
+ for b_name, url, same_line in buttons:
187
+ add_note_button_to_db(chat_id, keyword, b_name, url, same_line)
188
+
189
+
190
  def new_add_filter(
191
  chat_id, keyword, reply_text, file_type, file_id, buttons, media_spoiler
192
  ):
 
212
  str(chat_id),
213
  keyword,
214
  reply="there is should be a new reply",
215
+ is_sticker=False,
216
+ is_document=False,
217
+ is_image=False,
218
+ is_audio=False,
219
+ is_voice=False,
220
+ is_video=False,
221
  has_buttons=bool(buttons),
 
222
  reply_text=reply_text,
223
  file_type=file_type.value,
224
  file_id=file_id,
 
279
  SESSION.close()
280
 
281
 
282
+ def get_filter(chat_id, keyword):
283
  try:
284
  return SESSION.query(CustomFilters).get((str(chat_id), keyword))
285
  finally:
 
359
  else:
360
  file_type = Types.TEXT
361
 
362
+ print(str(x.chat_id), x.keyword, x.reply, file_type.value)
363
  if file_type == Types.TEXT:
364
  filt = CustomFilters(
365
+ str(x.chat_id), x.keyword, x.reply, file_type.value, None
 
 
 
 
366
  )
367
  else:
368
  filt = CustomFilters(
369
+ str(x.chat_id), x.keyword, None, file_type.value, x.reply
 
 
 
 
370
  )
371
 
372
  SESSION.add(filt)
 
386
  for filt in chat_filters:
387
  filt.chat_id = str(new_chat_id)
388
  SESSION.commit()
389
+ try:
390
+ CHAT_FILTERS[str(new_chat_id)] = CHAT_FILTERS[str(old_chat_id)]
391
+ except KeyError:
392
+ pass
393
+ del CHAT_FILTERS[str(old_chat_id)]
394
 
395
  with BUTTON_LOCK:
396
  chat_buttons = (
Database/sql/disable_sql.py CHANGED
@@ -1,3 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
 
3
  from sqlalchemy import Column, String, UnicodeText, distinct, func
@@ -15,7 +39,7 @@ class Disable(BASE):
15
  self.command = command
16
 
17
  def __repr__(self):
18
- return "Disabled cmd {} in {}".format(self.command, self.chat_id)
19
 
20
 
21
  Disable.__table__.create(checkfirst=True)
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import threading
26
 
27
  from sqlalchemy import Column, String, UnicodeText, distinct, func
 
39
  self.command = command
40
 
41
  def __repr__(self):
42
+ return "ᴅɪsᴀʙʟᴇᴅ ᴄᴍᴅ {} in {}".format(self.command, self.chat_id)
43
 
44
 
45
  Disable.__table__.create(checkfirst=True)
Database/sql/fontsql.py ADDED
@@ -0,0 +1,2361 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class Fonts:
2
+ def typewriter(text):
3
+ style = {
4
+ "a": "𝚊",
5
+ "b": "𝚋",
6
+ "c": "𝚌",
7
+ "d": "𝚍",
8
+ "e": "𝚎",
9
+ "f": "𝚏",
10
+ "g": "𝚐",
11
+ "h": "𝚑",
12
+ "i": "𝚒",
13
+ "j": "𝚓",
14
+ "k": "𝚔",
15
+ "l": "𝚕",
16
+ "m": "𝚖",
17
+ "n": "𝚗",
18
+ "o": "𝚘",
19
+ "p": "𝚙",
20
+ "q": "𝚚",
21
+ "r": "𝚛",
22
+ "s": "𝚜",
23
+ "t": "𝚝",
24
+ "u": "𝚞",
25
+ "v": "𝚟",
26
+ "w": "𝚠",
27
+ "x": "𝚡",
28
+ "y": "𝚢",
29
+ "z": "𝚣",
30
+ "A": "𝙰",
31
+ "B": "𝙱",
32
+ "C": "𝙲",
33
+ "D": "𝙳",
34
+ "E": "𝙴",
35
+ "F": "𝙵",
36
+ "G": "𝙶",
37
+ "H": "𝙷",
38
+ "I": "𝙸",
39
+ "J": "𝙹",
40
+ "K": "𝙺",
41
+ "L": "𝙻",
42
+ "M": "𝙼",
43
+ "N": "𝙽",
44
+ "O": "𝙾",
45
+ "P": "𝙿",
46
+ "Q": "𝚀",
47
+ "R": "𝚁",
48
+ "S": "𝚂",
49
+ "T": "𝚃",
50
+ "U": "𝚄",
51
+ "V": "𝚅",
52
+ "W": "𝚆",
53
+ "X": "𝚇",
54
+ "Y": "𝚈",
55
+ "Z": "𝚉",
56
+ }
57
+ for i, j in style.items():
58
+ text = text.replace(i, j)
59
+ return text
60
+
61
+ def outline(text):
62
+ style = {
63
+ "a": "𝕒",
64
+ "b": "𝕓",
65
+ "c": "𝕔",
66
+ "d": "𝕕",
67
+ "e": "𝕖",
68
+ "f": "𝕗",
69
+ "g": "𝕘",
70
+ "h": "𝕙",
71
+ "i": "𝕚",
72
+ "j": "𝕛",
73
+ "k": "𝕜",
74
+ "l": "𝕝",
75
+ "m": "𝕞",
76
+ "n": "𝕟",
77
+ "o": "𝕠",
78
+ "p": "𝕡",
79
+ "q": "𝕢",
80
+ "r": "𝕣",
81
+ "s": "𝕤",
82
+ "t": "𝕥",
83
+ "u": "𝕦",
84
+ "v": "𝕧",
85
+ "w": "𝕨",
86
+ "x": "𝕩",
87
+ "y": "𝕪",
88
+ "z": "𝕫",
89
+ "A": "𝔸",
90
+ "B": "𝔹",
91
+ "C": "ℂ",
92
+ "D": "𝔻",
93
+ "E": "𝔼",
94
+ "F": "𝔽",
95
+ "G": "𝔾",
96
+ "H": "ℍ",
97
+ "I": "𝕀",
98
+ "J": "𝕁",
99
+ "K": "𝕂",
100
+ "L": "𝕃",
101
+ "M": "𝕄",
102
+ "N": "ℕ",
103
+ "O": "𝕆",
104
+ "P": "ℙ",
105
+ "Q": "ℚ",
106
+ "R": "ℝ",
107
+ "S": "𝕊",
108
+ "T": "𝕋",
109
+ "U": "𝕌",
110
+ "V": "𝕍",
111
+ "W": "𝕎",
112
+ "X": "𝕏",
113
+ "Y": "𝕐",
114
+ "Z": "ℤ",
115
+ "0": "𝟘",
116
+ "1": "𝟙",
117
+ "2": "𝟚",
118
+ "3": "𝟛",
119
+ "4": "𝟜",
120
+ "5": "𝟝",
121
+ "6": "𝟞",
122
+ "7": "𝟟",
123
+ "8": "𝟠",
124
+ "9": "𝟡",
125
+ }
126
+ for i, j in style.items():
127
+ text = text.replace(i, j)
128
+ return text
129
+
130
+ def serief(text):
131
+ style = {
132
+ "a": "𝐚",
133
+ "b": "𝐛",
134
+ "c": "𝐜",
135
+ "d": "𝐝",
136
+ "e": "𝐞",
137
+ "f": "𝐟",
138
+ "g": "𝐠",
139
+ "h": "𝐡",
140
+ "i": "𝐢",
141
+ "j": "𝐣",
142
+ "k": "𝐤",
143
+ "l": "𝐥",
144
+ "m": "𝐦",
145
+ "n": "𝐧",
146
+ "o": "𝐨",
147
+ "p": "𝐩",
148
+ "q": "𝐪",
149
+ "r": "𝐫",
150
+ "s": "𝐬",
151
+ "t": "𝐭",
152
+ "u": "𝐮",
153
+ "v": "𝐯",
154
+ "w": "𝐰",
155
+ "x": "𝐱",
156
+ "y": "𝐲",
157
+ "z": "𝐳",
158
+ "A": "𝐀",
159
+ "B": "𝐁",
160
+ "C": "𝐂",
161
+ "D": "𝐃",
162
+ "E": "𝐄",
163
+ "F": "𝐅",
164
+ "G": "𝐆",
165
+ "H": "𝐇",
166
+ "I": "𝐈",
167
+ "J": "𝐉",
168
+ "K": "𝐊",
169
+ "L": "𝐋",
170
+ "M": "𝐌",
171
+ "N": "𝐍",
172
+ "O": "𝐎",
173
+ "P": "𝐏",
174
+ "Q": "𝐐",
175
+ "R": "𝐑",
176
+ "S": "𝐒",
177
+ "T": "𝐓",
178
+ "U": "𝐔",
179
+ "V": "𝐕",
180
+ "W": "𝐖",
181
+ "X": "𝐗",
182
+ "Y": "𝐘",
183
+ "Z": "𝐙",
184
+ "0": "𝟎",
185
+ "1": "𝟏",
186
+ "2": "𝟐",
187
+ "3": "𝟑",
188
+ "4": "𝟒",
189
+ "5": "𝟓",
190
+ "6": "𝟔",
191
+ "7": "𝟕",
192
+ "8": "𝟖",
193
+ "9": "𝟗",
194
+ }
195
+ for i, j in style.items():
196
+ text = text.replace(i, j)
197
+ return text
198
+
199
+ def bold_cool(text):
200
+ style = {
201
+ "a": "𝒂",
202
+ "b": "𝒃",
203
+ "c": "𝒄",
204
+ "d": "𝒅",
205
+ "e": "𝒆",
206
+ "f": "𝒇",
207
+ "g": "𝒈",
208
+ "h": "𝒉",
209
+ "i": "𝒊",
210
+ "j": "𝒋",
211
+ "k": "𝒌",
212
+ "l": "𝒍",
213
+ "m": "𝒎",
214
+ "n": "𝒏",
215
+ "o": "𝒐",
216
+ "p": "𝒑",
217
+ "q": "𝒒",
218
+ "r": "𝒓",
219
+ "s": "𝒔",
220
+ "t": "𝒕",
221
+ "u": "𝒖",
222
+ "v": "𝒗",
223
+ "w": "𝒘",
224
+ "x": "𝒙",
225
+ "y": "𝒚",
226
+ "z": "𝒛",
227
+ "A": "𝑨",
228
+ "B": "𝑩",
229
+ "C": "𝑪",
230
+ "D": "𝑫",
231
+ "E": "𝑬",
232
+ "F": "𝑭",
233
+ "G": "𝑮",
234
+ "H": "𝑯",
235
+ "I": "𝑰",
236
+ "J": "𝑱",
237
+ "K": "𝑲",
238
+ "L": "𝑳",
239
+ "M": "𝑴",
240
+ "N": "𝑵",
241
+ "O": "𝑶",
242
+ "P": "𝑷",
243
+ "Q": "𝑸",
244
+ "R": "𝑹",
245
+ "S": "𝑺",
246
+ "T": "𝑻",
247
+ "U": "𝑼",
248
+ "V": "𝑽",
249
+ "W": "𝑾",
250
+ "X": "𝑿",
251
+ "Y": "𝒀",
252
+ "Z": "𝒁",
253
+ }
254
+ for i, j in style.items():
255
+ text = text.replace(i, j)
256
+ return text
257
+
258
+ def cool(text):
259
+ style = {
260
+ "a": "𝑎",
261
+ "b": "𝑏",
262
+ "c": "𝑐",
263
+ "d": "𝑑",
264
+ "e": "𝑒",
265
+ "f": "𝑓",
266
+ "g": "𝑔",
267
+ "h": "ℎ",
268
+ "i": "𝑖",
269
+ "j": "𝑗",
270
+ "k": "𝑘",
271
+ "l": "𝑙",
272
+ "m": "𝑚",
273
+ "n": "𝑛",
274
+ "o": "𝑜",
275
+ "p": "𝑝",
276
+ "q": "𝑞",
277
+ "r": "𝑟",
278
+ "s": "𝑠",
279
+ "t": "𝑡",
280
+ "u": "𝑢",
281
+ "v": "𝑣",
282
+ "w": "𝑤",
283
+ "x": "𝑥",
284
+ "y": "𝑦",
285
+ "z": "𝑧",
286
+ "A": "𝐴",
287
+ "B": "𝐵",
288
+ "C": "𝐶",
289
+ "D": "𝐷",
290
+ "E": "𝐸",
291
+ "F": "𝐹",
292
+ "G": "𝐺",
293
+ "H": "𝐻",
294
+ "I": "𝐼",
295
+ "J": "𝐽",
296
+ "K": "𝐾",
297
+ "L": "𝐿",
298
+ "M": "𝑀",
299
+ "N": "𝑁",
300
+ "O": "𝑂",
301
+ "P": "𝑃",
302
+ "Q": "𝑄",
303
+ "R": "𝑅",
304
+ "S": "𝑆",
305
+ "T": "𝑇",
306
+ "U": "𝑈",
307
+ "V": "𝑉",
308
+ "W": "𝑊",
309
+ "X": "𝑋",
310
+ "Y": "𝑌",
311
+ "Z": "𝑍",
312
+ }
313
+ for i, j in style.items():
314
+ text = text.replace(i, j)
315
+ return text
316
+
317
+ def smallcap(text):
318
+ style = {
319
+ "a": "ᴀ",
320
+ "b": "ʙ",
321
+ "c": "ᴄ",
322
+ "d": "ᴅ",
323
+ "e": "ᴇ",
324
+ "f": "ғ",
325
+ "g": "ɢ",
326
+ "h": "ʜ",
327
+ "i": "ɪ",
328
+ "j": "J",
329
+ "k": "ᴋ",
330
+ "l": "ʟ",
331
+ "m": "ᴍ",
332
+ "n": "ɴ",
333
+ "o": "ᴏ",
334
+ "p": "ᴘ",
335
+ "q": "ǫ",
336
+ "r": "ʀ",
337
+ "s": "s",
338
+ "t": "ᴛ",
339
+ "u": "ᴜ",
340
+ "v": "ᴠ",
341
+ "w": "ᴡ",
342
+ "x": "x",
343
+ "y": "ʏ",
344
+ "z": "ᴢ",
345
+ "A": "A",
346
+ "B": "B",
347
+ "C": "C",
348
+ "D": "D",
349
+ "E": "E",
350
+ "F": "F",
351
+ "G": "G",
352
+ "H": "H",
353
+ "I": "I",
354
+ "J": "J",
355
+ "K": "K",
356
+ "L": "L",
357
+ "M": "M",
358
+ "N": "N",
359
+ "O": "O",
360
+ "P": "P",
361
+ "Q": "Q",
362
+ "R": "R",
363
+ "S": "S",
364
+ "T": "T",
365
+ "U": "U",
366
+ "V": "V",
367
+ "W": "W",
368
+ "X": "X",
369
+ "Y": "Y",
370
+ "Z": "Z",
371
+ "0": "𝟶",
372
+ "1": "𝟷",
373
+ "2": "𝟸",
374
+ "3": "𝟹",
375
+ "4": "𝟺",
376
+ "5": "𝟻",
377
+ "6": "𝟼",
378
+ "7": "𝟽",
379
+ "8": "𝟾",
380
+ "9": "𝟿",
381
+ }
382
+ for i, j in style.items():
383
+ text = text.replace(i, j)
384
+ return text
385
+
386
+ def script(text):
387
+ style = {
388
+ "a": "𝒶",
389
+ "b": "𝒷",
390
+ "c": "𝒸",
391
+ "d": "𝒹",
392
+ "e": "ℯ",
393
+ "f": "𝒻",
394
+ "g": "ℊ",
395
+ "h": "𝒽",
396
+ "i": "𝒾",
397
+ "j": "𝒿",
398
+ "k": "𝓀",
399
+ "l": "𝓁",
400
+ "m": "𝓂",
401
+ "n": "𝓃",
402
+ "o": "ℴ",
403
+ "p": "𝓅",
404
+ "q": "𝓆",
405
+ "r": "𝓇",
406
+ "s": "��",
407
+ "t": "𝓉",
408
+ "u": "𝓊",
409
+ "v": "𝓋",
410
+ "w": "𝓌",
411
+ "x": "𝓍",
412
+ "y": "𝓎",
413
+ "z": "𝓏",
414
+ "A": "𝒜",
415
+ "B": "ℬ",
416
+ "C": "𝒞",
417
+ "D": "𝒟",
418
+ "E": "ℰ",
419
+ "F": "ℱ",
420
+ "G": "𝒢",
421
+ "H": "ℋ",
422
+ "I": "ℐ",
423
+ "J": "𝒥",
424
+ "K": "𝒦",
425
+ "L": "ℒ",
426
+ "M": "ℳ",
427
+ "N": "𝒩",
428
+ "O": "𝒪",
429
+ "P": "𝒫",
430
+ "Q": "𝒬",
431
+ "R": "ℛ",
432
+ "S": "𝒮",
433
+ "T": "𝒯",
434
+ "U": "𝒰",
435
+ "V": "𝒱",
436
+ "W": "𝒲",
437
+ "X": "𝒳",
438
+ "Y": "𝒴",
439
+ "Z": "𝒵",
440
+ }
441
+ for i, j in style.items():
442
+ text = text.replace(i, j)
443
+ return text
444
+
445
+ def bold_script(text):
446
+ style = {
447
+ "a": "𝓪",
448
+ "b": "𝓫",
449
+ "c": "𝓬",
450
+ "d": "𝓭",
451
+ "e": "𝓮",
452
+ "f": "𝓯",
453
+ "g": "𝓰",
454
+ "h": "𝓱",
455
+ "i": "𝓲",
456
+ "j": "𝓳",
457
+ "k": "𝓴",
458
+ "l": "𝓵",
459
+ "m": "𝓶",
460
+ "n": "𝓷",
461
+ "o": "𝓸",
462
+ "p": "𝓹",
463
+ "q": "𝓺",
464
+ "r": "𝓻",
465
+ "s": "𝓼",
466
+ "t": "𝓽",
467
+ "u": "𝓾",
468
+ "v": "𝓿",
469
+ "w": "𝔀",
470
+ "x": "𝔁",
471
+ "y": "𝔂",
472
+ "z": "𝔃",
473
+ "A": "𝓐",
474
+ "B": "𝓑",
475
+ "C": "𝓒",
476
+ "D": "𝓓",
477
+ "E": "𝓔",
478
+ "F": "𝓕",
479
+ "G": "𝓖",
480
+ "H": "𝓗",
481
+ "I": "𝓘",
482
+ "J": "𝓙",
483
+ "K": "𝓚",
484
+ "L": "𝓛",
485
+ "M": "𝓜",
486
+ "N": "𝓝",
487
+ "O": "𝓞",
488
+ "P": "𝓟",
489
+ "Q": "𝓠",
490
+ "R": "𝓡",
491
+ "S": "𝓢",
492
+ "T": "𝓣",
493
+ "U": "𝓤",
494
+ "V": "𝓥",
495
+ "W": "𝓦",
496
+ "X": "𝓧",
497
+ "Y": "𝓨",
498
+ "Z": "𝓩",
499
+ }
500
+ for i, j in style.items():
501
+ text = text.replace(i, j)
502
+ return text
503
+
504
+ def tiny(text):
505
+ style = {
506
+ "a": "ᵃ",
507
+ "b": "ᵇ",
508
+ "c": "ᶜ",
509
+ "d": "ᵈ",
510
+ "e": "ᵉ",
511
+ "f": "ᶠ",
512
+ "g": "ᵍ",
513
+ "h": "ʰ",
514
+ "i": "ⁱ",
515
+ "j": "ʲ",
516
+ "k": "ᵏ",
517
+ "l": "ˡ",
518
+ "m": "ᵐ",
519
+ "n": "ⁿ",
520
+ "o": "ᵒ",
521
+ "p": "ᵖ",
522
+ "q": "ᵠ",
523
+ "r": "ʳ",
524
+ "s": "ˢ",
525
+ "t": "ᵗ",
526
+ "u": "ᵘ",
527
+ "v": "ᵛ",
528
+ "w": "ʷ",
529
+ "x": "ˣ",
530
+ "y": "ʸ",
531
+ "z": "ᶻ",
532
+ "A": "ᵃ",
533
+ "B": "ᵇ",
534
+ "C": "ᶜ",
535
+ "D": "ᵈ",
536
+ "E": "ᵉ",
537
+ "F": "ᶠ",
538
+ "G": "ᵍ",
539
+ "H": "ʰ",
540
+ "I": "ⁱ",
541
+ "J": "ʲ",
542
+ "K": "ᵏ",
543
+ "L": "ˡ",
544
+ "M": "ᵐ",
545
+ "N": "ⁿ",
546
+ "O": "ᵒ",
547
+ "P": "ᵖ",
548
+ "Q": "ᵠ",
549
+ "R": "ʳ",
550
+ "S": "ˢ",
551
+ "T": "ᵗ",
552
+ "U": "ᵘ",
553
+ "V": "ᵛ",
554
+ "W": "ʷ",
555
+ "X": "ˣ",
556
+ "Y": "ʸ",
557
+ "Z": "ᶻ",
558
+ }
559
+ for i, j in style.items():
560
+ text = text.replace(i, j)
561
+ return text
562
+
563
+ def comic(text):
564
+ style = {
565
+ "a": "ᗩ",
566
+ "b": "ᗷ",
567
+ "c": "ᑕ",
568
+ "d": "ᗪ",
569
+ "e": "ᗴ",
570
+ "f": "ᖴ",
571
+ "g": "ᘜ",
572
+ "h": "ᕼ",
573
+ "i": "I",
574
+ "j": "ᒍ",
575
+ "k": "K",
576
+ "l": "ᒪ",
577
+ "m": "ᗰ",
578
+ "n": "ᑎ",
579
+ "o": "O",
580
+ "p": "ᑭ",
581
+ "q": "ᑫ",
582
+ "r": "ᖇ",
583
+ "s": "Տ",
584
+ "t": "T",
585
+ "u": "ᑌ",
586
+ "v": "ᐯ",
587
+ "w": "ᗯ",
588
+ "x": "᙭",
589
+ "y": "Y",
590
+ "z": "ᘔ",
591
+ "A": "ᗩ",
592
+ "B": "ᗷ",
593
+ "C": "ᑕ",
594
+ "D": "ᗪ",
595
+ "E": "ᗴ",
596
+ "F": "ᖴ",
597
+ "G": "ᘜ",
598
+ "H": "ᕼ",
599
+ "I": "I",
600
+ "J": "ᒍ",
601
+ "K": "K",
602
+ "L": "ᒪ",
603
+ "M": "ᗰ",
604
+ "N": "ᑎ",
605
+ "O": "O",
606
+ "P": "ᑭ",
607
+ "Q": "ᑫ",
608
+ "R": "ᖇ",
609
+ "S": "Տ",
610
+ "T": "T",
611
+ "U": "ᑌ",
612
+ "V": "���",
613
+ "W": "ᗯ",
614
+ "X": "᙭",
615
+ "Y": "Y",
616
+ "Z": "ᘔ",
617
+ }
618
+ for i, j in style.items():
619
+ text = text.replace(i, j)
620
+ return text
621
+
622
+ def san(text):
623
+ style = {
624
+ "a": "𝗮",
625
+ "b": "𝗯",
626
+ "c": "𝗰",
627
+ "d": "𝗱",
628
+ "e": "𝗲",
629
+ "f": "𝗳",
630
+ "g": "𝗴",
631
+ "h": "𝗵",
632
+ "i": "𝗶",
633
+ "j": "𝗷",
634
+ "k": "𝗸",
635
+ "l": "𝗹",
636
+ "m": "𝗺",
637
+ "n": "𝗻",
638
+ "o": "𝗼",
639
+ "p": "𝗽",
640
+ "q": "𝗾",
641
+ "r": "𝗿",
642
+ "s": "𝘀",
643
+ "t": "𝘁",
644
+ "u": "𝘂",
645
+ "v": "𝘃",
646
+ "w": "𝘄",
647
+ "x": "𝘅",
648
+ "y": "𝘆",
649
+ "z": "𝘇",
650
+ "A": "𝗔",
651
+ "B": "𝗕",
652
+ "C": "𝗖",
653
+ "D": "𝗗",
654
+ "E": "𝗘",
655
+ "F": "𝗙",
656
+ "G": "𝗚",
657
+ "H": "𝗛",
658
+ "I": "𝗜",
659
+ "J": "𝗝",
660
+ "K": "𝗞",
661
+ "L": "𝗟",
662
+ "M": "𝗠",
663
+ "N": "𝗡",
664
+ "O": "𝗢",
665
+ "P": "𝗣",
666
+ "Q": "𝗤",
667
+ "R": "𝗥",
668
+ "S": "𝗦",
669
+ "T": "𝗧",
670
+ "U": "𝗨",
671
+ "V": "𝗩",
672
+ "W": "𝗪",
673
+ "X": "𝗫",
674
+ "Y": "𝗬",
675
+ "Z": "𝗭",
676
+ "0": "𝟬",
677
+ "1": "𝟭",
678
+ "2": "𝟮",
679
+ "3": "𝟯",
680
+ "4": "𝟰",
681
+ "5": "𝟱",
682
+ "6": "𝟲",
683
+ "7": "𝟳",
684
+ "8": "𝟴",
685
+ "9": "𝟵",
686
+ }
687
+ for i, j in style.items():
688
+ text = text.replace(i, j)
689
+ return text
690
+
691
+ def slant_san(text):
692
+ style = {
693
+ "a": "𝙖",
694
+ "b": "𝙗",
695
+ "c": "𝙘",
696
+ "d": "𝙙",
697
+ "e": "𝙚",
698
+ "f": "𝙛",
699
+ "g": "𝙜",
700
+ "h": "𝙝",
701
+ "i": "𝙞",
702
+ "j": "𝙟",
703
+ "k": "𝙠",
704
+ "l": "𝙡",
705
+ "m": "𝙢",
706
+ "n": "𝙣",
707
+ "o": "𝙤",
708
+ "p": "𝙥",
709
+ "q": "𝙦",
710
+ "r": "𝙧",
711
+ "s": "𝙨",
712
+ "t": "𝙩",
713
+ "u": "𝙪",
714
+ "v": "𝙫",
715
+ "w": "𝙬",
716
+ "x": "𝙭",
717
+ "y": "𝙮",
718
+ "z": "𝙯",
719
+ "A": "𝘼",
720
+ "B": "𝘽",
721
+ "C": "𝘾",
722
+ "D": "𝘿",
723
+ "E": "𝙀",
724
+ "F": "𝙁",
725
+ "G": "𝙂",
726
+ "H": "𝙃",
727
+ "I": "𝙄",
728
+ "J": "𝙅",
729
+ "K": "𝙆",
730
+ "L": "𝙇",
731
+ "M": "𝙈",
732
+ "N": "𝙉",
733
+ "O": "𝙊",
734
+ "P": "𝙋",
735
+ "Q": "𝙌",
736
+ "R": "𝙍",
737
+ "S": "𝙎",
738
+ "T": "𝙏",
739
+ "U": "𝙐",
740
+ "V": "𝙑",
741
+ "W": "𝙒",
742
+ "X": "𝙓",
743
+ "Y": "𝙔",
744
+ "Z": "𝙕",
745
+ }
746
+ for i, j in style.items():
747
+ text = text.replace(i, j)
748
+ return text
749
+
750
+ def slant(text):
751
+ style = {
752
+ "a": "𝘢",
753
+ "b": "𝘣",
754
+ "c": "𝘤",
755
+ "d": "𝘥",
756
+ "e": "𝘦",
757
+ "f": "𝘧",
758
+ "g": "𝘨",
759
+ "h": "𝘩",
760
+ "i": "𝘪",
761
+ "j": "𝘫",
762
+ "k": "𝘬",
763
+ "l": "𝘭",
764
+ "m": "𝘮",
765
+ "n": "𝘯",
766
+ "o": "𝘰",
767
+ "p": "𝘱",
768
+ "q": "𝘲",
769
+ "r": "𝘳",
770
+ "s": "𝘴",
771
+ "t": "𝘵",
772
+ "u": "𝘶",
773
+ "v": "𝘷",
774
+ "w": "𝘸",
775
+ "x": "𝘹",
776
+ "y": "𝘺",
777
+ "z": "𝘻",
778
+ "A": "𝘈",
779
+ "B": "𝘉",
780
+ "C": "𝘊",
781
+ "D": "𝘋",
782
+ "E": "𝘌",
783
+ "F": "𝘍",
784
+ "G": "𝘎",
785
+ "H": "𝘏",
786
+ "I": "𝘐",
787
+ "J": "𝘑",
788
+ "K": "𝘒",
789
+ "L": "𝘓",
790
+ "M": "𝘔",
791
+ "N": "𝘕",
792
+ "O": "𝘖",
793
+ "P": "𝘗",
794
+ "Q": "𝘘",
795
+ "R": "𝘙",
796
+ "S": "𝘚",
797
+ "T": "𝘛",
798
+ "U": "𝘜",
799
+ "V": "𝘝",
800
+ "W": "𝘞",
801
+ "X": "𝘟",
802
+ "Y": "𝘠",
803
+ "Z": "𝘡",
804
+ }
805
+ for i, j in style.items():
806
+ text = text.replace(i, j)
807
+ return text
808
+
809
+ def sim(text):
810
+ style = {
811
+ "a": "𝖺",
812
+ "b": "𝖻",
813
+ "c": "𝖼",
814
+ "d": "𝖽",
815
+ "e": "𝖾",
816
+ "f": "𝖿",
817
+ "g": "𝗀",
818
+ "h": "𝗁",
819
+ "i": "𝗂",
820
+ "j": "𝗃",
821
+ "k": "𝗄",
822
+ "l": "𝗅",
823
+ "m": "𝗆",
824
+ "n": "𝗇",
825
+ "o": "𝗈",
826
+ "p": "𝗉",
827
+ "q": "𝗊",
828
+ "r": "𝗋",
829
+ "s": "𝗌",
830
+ "t": "𝗍",
831
+ "u": "𝗎",
832
+ "v": "𝗏",
833
+ "w": "𝗐",
834
+ "x": "𝗑",
835
+ "y": "𝗒",
836
+ "z": "𝗓",
837
+ "A": "𝖠",
838
+ "B": "𝖡",
839
+ "C": "𝖢",
840
+ "D": "𝖣",
841
+ "E": "𝖤",
842
+ "F": "𝖥",
843
+ "G": "𝖦",
844
+ "H": "𝖧",
845
+ "I": "𝖨",
846
+ "J": "𝖩",
847
+ "K": "𝖪",
848
+ "L": "𝖫",
849
+ "M": "𝖬",
850
+ "N": "𝖭",
851
+ "O": "𝖮",
852
+ "P": "𝖯",
853
+ "Q": "𝖰",
854
+ "R": "𝖱",
855
+ "S": "𝖲",
856
+ "T": "𝖳",
857
+ "U": "𝖴",
858
+ "V": "𝖵",
859
+ "W": "𝖶",
860
+ "X": "𝖷",
861
+ "Y": "𝖸",
862
+ "Z": "𝖹",
863
+ }
864
+ for i, j in style.items():
865
+ text = text.replace(i, j)
866
+ return text
867
+
868
+ def circles(text):
869
+ style = {
870
+ "a": "Ⓐ︎",
871
+ "b": "Ⓑ︎",
872
+ "c": "Ⓒ︎",
873
+ "d": "Ⓓ︎",
874
+ "e": "Ⓔ︎",
875
+ "f": "Ⓕ︎",
876
+ "g": "Ⓖ︎",
877
+ "h": "Ⓗ︎",
878
+ "i": "Ⓘ︎",
879
+ "j": "Ⓙ︎",
880
+ "k": "Ⓚ︎",
881
+ "l": "Ⓛ︎",
882
+ "m": "Ⓜ︎",
883
+ "n": "Ⓝ︎",
884
+ "o": "Ⓞ︎",
885
+ "p": "Ⓟ︎",
886
+ "q": "Ⓠ︎",
887
+ "r": "Ⓡ︎",
888
+ "s": "Ⓢ︎",
889
+ "t": "Ⓣ︎",
890
+ "u": "Ⓤ︎",
891
+ "v": "Ⓥ︎",
892
+ "w": "Ⓦ︎",
893
+ "x": "Ⓧ︎",
894
+ "y": "Ⓨ︎",
895
+ "z": "Ⓩ︎",
896
+ "A": "Ⓐ︎",
897
+ "B": "Ⓑ︎",
898
+ "C": "Ⓒ︎",
899
+ "D": "Ⓓ︎",
900
+ "E": "Ⓔ︎",
901
+ "F": "Ⓕ︎",
902
+ "G": "Ⓖ︎",
903
+ "H": "Ⓗ︎",
904
+ "I": "Ⓘ︎",
905
+ "J": "Ⓙ︎",
906
+ "K": "Ⓚ︎",
907
+ "L": "Ⓛ︎",
908
+ "M": "Ⓜ︎",
909
+ "N": "Ⓝ︎",
910
+ "O": "Ⓞ︎",
911
+ "P": "Ⓟ︎",
912
+ "Q": "Ⓠ︎",
913
+ "R": "Ⓡ︎",
914
+ "S": "Ⓢ︎",
915
+ "T": "Ⓣ︎",
916
+ "U": "Ⓤ︎",
917
+ "V": "Ⓥ︎",
918
+ "W": "Ⓦ︎",
919
+ "X": "Ⓧ︎",
920
+ "Y": "Ⓨ︎",
921
+ "Z": "Ⓩ︎",
922
+ "0": "⓪",
923
+ "1": "①",
924
+ "2": "②",
925
+ "3": "③",
926
+ "4": "④",
927
+ "5": "⑤",
928
+ "6": "⑥",
929
+ "7": "⑦",
930
+ "8": "⑧",
931
+ "9": "⑨",
932
+ }
933
+ for i, j in style.items():
934
+ text = text.replace(i, j)
935
+ return text
936
+
937
+ def dark_circle(text):
938
+ style = {
939
+ "a": "🅐︎",
940
+ "b": "🅑︎",
941
+ "c": "🅒︎",
942
+ "d": "🅓︎",
943
+ "e": "🅔︎",
944
+ "f": "🅕︎",
945
+ "g": "🅖︎",
946
+ "h": "🅗︎",
947
+ "i": "🅘︎",
948
+ "j": "🅙︎",
949
+ "k": "🅚︎",
950
+ "l": "🅛︎",
951
+ "m": "🅜︎",
952
+ "n": "🅝︎",
953
+ "o": "🅞︎",
954
+ "p": "🅟︎",
955
+ "q": "🅠︎",
956
+ "r": "🅡︎",
957
+ "s": "🅢︎",
958
+ "t": "🅣︎",
959
+ "u": "🅤︎",
960
+ "v": "🅥︎",
961
+ "w": "🅦︎",
962
+ "x": "🅧︎",
963
+ "y": "🅨︎",
964
+ "z": "🅩︎",
965
+ "A": "🅐︎",
966
+ "B": "🅑︎",
967
+ "C": "🅒︎",
968
+ "D": "🅓︎",
969
+ "E": "🅔︎",
970
+ "F": "🅕︎",
971
+ "G": "🅖︎",
972
+ "H": "🅗︎",
973
+ "I": "🅘︎",
974
+ "J": "🅙︎",
975
+ "K": "🅚︎",
976
+ "L": "🅛︎",
977
+ "M": "🅜︎",
978
+ "N": "🅝︎",
979
+ "O": "🅞︎",
980
+ "P": "🅟︎",
981
+ "Q": "🅠︎",
982
+ "R": "🅡︎",
983
+ "S": "🅢︎",
984
+ "T": "🅣︎",
985
+ "U": "🅤︎",
986
+ "V": "🅥︎",
987
+ "W": "🅦︎",
988
+ "X": "🅧︎",
989
+ "Y": "🅨︎",
990
+ "Z": "🅩",
991
+ "0": "⓿",
992
+ "1": "➊",
993
+ "2": "➋",
994
+ "3": "➌",
995
+ "4": "➍",
996
+ "5": "➎",
997
+ "6": "➏",
998
+ "7": "➐",
999
+ "8": "➑",
1000
+ "9": "➒",
1001
+ }
1002
+ for i, j in style.items():
1003
+ text = text.replace(i, j)
1004
+ return text
1005
+
1006
+ def gothic(text):
1007
+ style = {
1008
+ "a": "𝔞",
1009
+ "b": "𝔟",
1010
+ "c": "𝔠",
1011
+ "d": "𝔡",
1012
+ "e": "𝔢",
1013
+ "f": "𝔣",
1014
+ "g": "𝔤",
1015
+ "h": "𝔥",
1016
+ "i": "𝔦",
1017
+ "j": "𝔧",
1018
+ "k": "𝔨",
1019
+ "l": "𝔩",
1020
+ "m": "𝔪",
1021
+ "n": "𝔫",
1022
+ "o": "𝔬",
1023
+ "p": "𝔭",
1024
+ "q": "𝔮",
1025
+ "r": "𝔯",
1026
+ "s": "𝔰",
1027
+ "t": "𝔱",
1028
+ "u": "𝔲",
1029
+ "v": "𝔳",
1030
+ "w": "𝔴",
1031
+ "x": "𝔵",
1032
+ "y": "𝔶",
1033
+ "z": "𝔷",
1034
+ "A": "𝔄",
1035
+ "B": "𝔅",
1036
+ "C": "ℭ",
1037
+ "D": "𝔇",
1038
+ "E": "𝔈",
1039
+ "F": "𝔉",
1040
+ "G": "𝔊",
1041
+ "H": "ℌ",
1042
+ "I": "ℑ",
1043
+ "J": "𝔍",
1044
+ "K": "𝔎",
1045
+ "L": "𝔏",
1046
+ "M": "𝔐",
1047
+ "N": "𝔑",
1048
+ "O": "𝔒",
1049
+ "P": "𝔓",
1050
+ "Q": "𝔔",
1051
+ "R": "ℜ",
1052
+ "S": "𝔖",
1053
+ "T": "𝔗",
1054
+ "U": "𝔘",
1055
+ "V": "𝔙",
1056
+ "W": "𝔚",
1057
+ "X": "𝔛",
1058
+ "Y": "𝔜",
1059
+ "Z": "ℨ",
1060
+ }
1061
+ for i, j in style.items():
1062
+ text = text.replace(i, j)
1063
+ return text
1064
+
1065
+ def bold_gothic(text):
1066
+ style = {
1067
+ "a": "𝖆",
1068
+ "b": "𝖇",
1069
+ "c": "𝖈",
1070
+ "d": "𝖉",
1071
+ "e": "𝖊",
1072
+ "f": "𝖋",
1073
+ "g": "𝖌",
1074
+ "h": "𝖍",
1075
+ "i": "𝖎",
1076
+ "j": "𝖏",
1077
+ "k": "𝖐",
1078
+ "l": "𝖑",
1079
+ "m": "𝖒",
1080
+ "n": "𝖓",
1081
+ "o": "𝖔",
1082
+ "p": "𝖕",
1083
+ "q": "𝖖",
1084
+ "r": "𝖗",
1085
+ "s": "𝖘",
1086
+ "t": "𝖙",
1087
+ "u": "𝖚",
1088
+ "v": "𝖛",
1089
+ "w": "𝖜",
1090
+ "x": "𝖝",
1091
+ "y": "𝖞",
1092
+ "z": "𝖟",
1093
+ "A": "𝕬",
1094
+ "B": "𝕭",
1095
+ "C": "𝕮",
1096
+ "D": "𝕺",
1097
+ "E": "𝕰",
1098
+ "F": "𝕱",
1099
+ "G": "𝕲",
1100
+ "H": "𝕳",
1101
+ "I": "𝕴",
1102
+ "J": "𝕵",
1103
+ "K": "𝕶",
1104
+ "L": "𝕷",
1105
+ "M": "𝕸",
1106
+ "N": "𝕹",
1107
+ "O": "𝕺",
1108
+ "P": "𝕻",
1109
+ "Q": "𝕼",
1110
+ "R": "𝕽",
1111
+ "S": "𝕾",
1112
+ "T": "𝕿",
1113
+ "U": "𝖀",
1114
+ "V": "𝖁",
1115
+ "W": "𝖂",
1116
+ "X": "𝖃",
1117
+ "Y": "𝖄",
1118
+ "Z": "𝖅",
1119
+ }
1120
+ for i, j in style.items():
1121
+ text = text.replace(i, j)
1122
+ return text
1123
+
1124
+ def cloud(text):
1125
+ style = {
1126
+ "a": "a͜͡",
1127
+ "b": "b͜͡",
1128
+ "c": "c͜͡",
1129
+ "d": "d͜͡",
1130
+ "e": "e͜͡",
1131
+ "f": "f͜͡",
1132
+ "g": "g͜͡",
1133
+ "h": "h͜͡",
1134
+ "i": "i͜͡",
1135
+ "j": "j͜͡",
1136
+ "k": "k͜͡",
1137
+ "l": "l͜͡",
1138
+ "m": "m͜͡",
1139
+ "n": "n͜͡",
1140
+ "o": "o͜͡",
1141
+ "p": "p͜͡",
1142
+ "q": "q͜͡",
1143
+ "r": "r͜͡",
1144
+ "s": "s͜͡",
1145
+ "t": "t͜͡",
1146
+ "u": "u͜͡",
1147
+ "v": "v͜͡",
1148
+ "w": "w͜͡",
1149
+ "x": "x͜͡",
1150
+ "y": "y͜͡",
1151
+ "z": "z͜͡",
1152
+ "A": "A͜͡",
1153
+ "B": "B͜͡",
1154
+ "C": "C͜͡",
1155
+ "D": "D͜͡",
1156
+ "E": "E͜͡",
1157
+ "F": "F͜͡",
1158
+ "G": "G͜͡",
1159
+ "H": "H͜͡",
1160
+ "I": "I͜͡",
1161
+ "J": "J͜͡",
1162
+ "K": "K͜͡",
1163
+ "L": "L͜͡",
1164
+ "M": "M͜͡",
1165
+ "N": "N͜͡",
1166
+ "O": "O͜͡",
1167
+ "P": "P͜͡",
1168
+ "Q": "Q͜͡",
1169
+ "R": "R͜͡",
1170
+ "S": "S͜͡",
1171
+ "T": "T͜͡",
1172
+ "U": "U͜͡",
1173
+ "V": "V͜͡",
1174
+ "W": "W͜͡",
1175
+ "X": "X͜͡",
1176
+ "Y": "Y͜͡",
1177
+ "Z": "Z͜͡",
1178
+ }
1179
+ for i, j in style.items():
1180
+ text = text.replace(i, j)
1181
+ return text
1182
+
1183
+ def happy(text):
1184
+ style = {
1185
+ "a": "ă̈",
1186
+ "b": "b̆̈",
1187
+ "c": "c̆̈",
1188
+ "d": "d̆̈",
1189
+ "e": "ĕ̈",
1190
+ "f": "f̆̈",
1191
+ "g": "ğ̈",
1192
+ "h": "h̆̈",
1193
+ "i": "ĭ̈",
1194
+ "j": "j̆̈",
1195
+ "k": "k̆̈",
1196
+ "l": "l̆̈",
1197
+ "m": "m̆̈",
1198
+ "n": "n̆̈",
1199
+ "o": "ŏ̈",
1200
+ "p": "p̆̈",
1201
+ "q": "q̆̈",
1202
+ "r": "r̆̈",
1203
+ "s": "s̆̈",
1204
+ "t": "t̆̈",
1205
+ "u": "ŭ̈",
1206
+ "v": "v̆̈",
1207
+ "w": "w̆̈",
1208
+ "x": "x̆̈",
1209
+ "y": "y̆̈",
1210
+ "z": "z̆̈",
1211
+ "A": "Ă̈",
1212
+ "B": "B̆̈",
1213
+ "C": "C̆̈",
1214
+ "D": "D̆̈",
1215
+ "E": "Ĕ̈",
1216
+ "F": "F̆̈",
1217
+ "G": "Ğ̈",
1218
+ "H": "H̆̈",
1219
+ "I": "Ĭ̈",
1220
+ "J": "J̆̈",
1221
+ "K": "K̆̈",
1222
+ "L": "L̆̈",
1223
+ "M": "M̆̈",
1224
+ "N": "N̆̈",
1225
+ "O": "Ŏ̈",
1226
+ "P": "P̆̈",
1227
+ "Q": "Q̆̈",
1228
+ "R": "R̆̈",
1229
+ "S": "S̆̈",
1230
+ "T": "T̆̈",
1231
+ "U": "Ŭ̈",
1232
+ "V": "V̆̈",
1233
+ "W": "W̆̈",
1234
+ "X": "X̆̈",
1235
+ "Y": "Y̆̈",
1236
+ "Z": "Z̆̈",
1237
+ }
1238
+ for i, j in style.items():
1239
+ text = text.replace(i, j)
1240
+ return text
1241
+
1242
+ def sad(text):
1243
+ style = {
1244
+ "a": "ȃ̈",
1245
+ "b": "b̑̈",
1246
+ "c": "c̑̈",
1247
+ "d": "d̑̈",
1248
+ "e": "ȇ̈",
1249
+ "f": "f̑̈",
1250
+ "g": "g̑̈",
1251
+ "h": "h̑̈",
1252
+ "i": "ȋ̈",
1253
+ "j": "j̑̈",
1254
+ "k": "k̑̈",
1255
+ "l": "l̑̈",
1256
+ "m": "m̑̈",
1257
+ "n": "n̑̈",
1258
+ "o": "ȏ̈",
1259
+ "p": "p̑̈",
1260
+ "q": "q̑̈",
1261
+ "r": "ȓ̈",
1262
+ "s": "s̑̈",
1263
+ "t": "t̑̈",
1264
+ "u": "ȗ̈",
1265
+ "v": "v̑̈",
1266
+ "w": "w̑̈",
1267
+ "x": "x̑̈",
1268
+ "y": "y̑̈",
1269
+ "z": "z̑̈",
1270
+ "A": "Ȃ̈",
1271
+ "B": "B̑̈",
1272
+ "C": "C̑̈",
1273
+ "D": "D̑̈",
1274
+ "E": "Ȇ̈",
1275
+ "F": "F̑̈",
1276
+ "G": "G̑̈",
1277
+ "H": "H̑̈",
1278
+ "I": "Ȋ̈",
1279
+ "J": "J̑̈",
1280
+ "K": "K̑̈",
1281
+ "L": "L̑̈",
1282
+ "M": "M̑̈",
1283
+ "N": "N̑̈",
1284
+ "O": "Ȏ̈",
1285
+ "P": "P̑̈",
1286
+ "Q": "Q̑̈",
1287
+ "R": "Ȓ̈",
1288
+ "S": "S̑̈",
1289
+ "T": "T̑̈",
1290
+ "U": "Ȗ̈",
1291
+ "V": "V̑̈",
1292
+ "W": "W̑̈",
1293
+ "X": "X̑̈",
1294
+ "Y": "Y̑̈",
1295
+ "Z": "Z̑̈",
1296
+ }
1297
+ for i, j in style.items():
1298
+ text = text.replace(i, j)
1299
+ return text
1300
+
1301
+ def special(text):
1302
+ style = {
1303
+ "a": "🇦 ",
1304
+ "b": "🇧 ",
1305
+ "c": "🇨 ",
1306
+ "d": "🇩 ",
1307
+ "e": "🇪 ",
1308
+ "f": "🇫 ",
1309
+ "g": "🇬 ",
1310
+ "h": "🇭 ",
1311
+ "i": "🇮 ",
1312
+ "j": "🇯 ",
1313
+ "k": "🇰 ",
1314
+ "l": "🇱 ",
1315
+ "m": "🇲 ",
1316
+ "n": "🇳 ",
1317
+ "o": "🇴 ",
1318
+ "p": "🇵 ",
1319
+ "q": "🇶 ",
1320
+ "r": "🇷 ",
1321
+ "s": "🇸 ",
1322
+ "t": "🇹 ",
1323
+ "u": "🇺 ",
1324
+ "v": "🇻 ",
1325
+ "w": "🇼 ",
1326
+ "x": "🇽 ",
1327
+ "y": "🇾 ",
1328
+ "z": "🇿 ",
1329
+ "A": "🇦 ",
1330
+ "B": "🇧 ",
1331
+ "C": "🇨 ",
1332
+ "D": "🇩 ",
1333
+ "E": "🇪 ",
1334
+ "F": "🇫 ",
1335
+ "G": "🇬 ",
1336
+ "H": "🇭 ",
1337
+ "I": "🇮 ",
1338
+ "J": "🇯 ",
1339
+ "K": "🇰 ",
1340
+ "L": "🇱 ",
1341
+ "M": "🇲 ",
1342
+ "N": "🇳 ",
1343
+ "O": "🇴 ",
1344
+ "P": "🇵 ",
1345
+ "Q": "🇶 ",
1346
+ "R": "🇷 ",
1347
+ "S": "🇸 ",
1348
+ "T": "🇹 ",
1349
+ "U": "🇺 ",
1350
+ "V": "🇻 ",
1351
+ "W": "🇼 ",
1352
+ "X": "🇽 ",
1353
+ "Y": "🇾 ",
1354
+ "Z": "🇿 ",
1355
+ }
1356
+ for i, j in style.items():
1357
+ text = text.replace(i, j)
1358
+ return text
1359
+
1360
+ def square(text):
1361
+ style = {
1362
+ "a": "🄰",
1363
+ "b": "🄱",
1364
+ "c": "🄲",
1365
+ "d": "🄳",
1366
+ "e": "🄴",
1367
+ "f": "🄵",
1368
+ "g": "🄶",
1369
+ "h": "🄷",
1370
+ "i": "🄸",
1371
+ "j": "🄹",
1372
+ "k": "🄺",
1373
+ "l": "🄻",
1374
+ "m": "🄼",
1375
+ "n": "🄽",
1376
+ "o": "🄾",
1377
+ "p": "🄿",
1378
+ "q": "🅀",
1379
+ "r": "🅁",
1380
+ "s": "🅂",
1381
+ "t": "🅃",
1382
+ "u": "🅄",
1383
+ "v": "🅅",
1384
+ "w": "🅆",
1385
+ "x": "🅇",
1386
+ "y": "🅈",
1387
+ "z": "🅉",
1388
+ "A": "🄰",
1389
+ "B": "🄱",
1390
+ "C": "🄲",
1391
+ "D": "🄳",
1392
+ "E": "🄴",
1393
+ "F": "🄵",
1394
+ "G": "🄶",
1395
+ "H": "🄷",
1396
+ "I": "🄸",
1397
+ "J": "🄹",
1398
+ "K": "🄺",
1399
+ "L": "🄻",
1400
+ "M": "🄼",
1401
+ "N": "🄽",
1402
+ "O": "🄾",
1403
+ "P": "🄿",
1404
+ "Q": "🅀",
1405
+ "R": "🅁",
1406
+ "S": "🅂",
1407
+ "T": "🅃",
1408
+ "U": "🅄",
1409
+ "V": "🅅",
1410
+ "W": "🅆",
1411
+ "X": "🅇",
1412
+ "Y": "🅈",
1413
+ "Z": "🅉",
1414
+ }
1415
+ for i, j in style.items():
1416
+ text = text.replace(i, j)
1417
+ return text
1418
+
1419
+ def dark_square(text):
1420
+ style = {
1421
+ "a": "🅰︎",
1422
+ "b": "🅱︎",
1423
+ "c": "🅲︎",
1424
+ "d": "🅳︎",
1425
+ "e": "🅴︎",
1426
+ "f": "🅵︎",
1427
+ "g": "🅶︎",
1428
+ "h": "🅷︎",
1429
+ "i": "🅸︎",
1430
+ "j": "🅹︎",
1431
+ "k": "🅺︎",
1432
+ "l": "🅻︎",
1433
+ "m": "🅼︎",
1434
+ "n": "🅽︎",
1435
+ "o": "🅾︎",
1436
+ "p": "🅿︎",
1437
+ "q": "🆀︎",
1438
+ "r": "🆁︎",
1439
+ "s": "🆂︎",
1440
+ "t": "🆃︎",
1441
+ "u": "🆄︎",
1442
+ "v": "🆅︎",
1443
+ "w": "🆆︎",
1444
+ "x": "🆇︎",
1445
+ "y": "🆈︎",
1446
+ "z": "🆉︎",
1447
+ "A": "🅰︎",
1448
+ "B": "🅱︎",
1449
+ "C": "🅲︎",
1450
+ "D": "🅳︎",
1451
+ "E": "🅴︎",
1452
+ "F": "🅵︎",
1453
+ "G": "🅶︎",
1454
+ "H": "🅷︎",
1455
+ "I": "🅸︎",
1456
+ "J": "🅹︎",
1457
+ "K": "🅺︎",
1458
+ "L": "🅻︎",
1459
+ "M": "🅼︎",
1460
+ "N": "🅽︎",
1461
+ "O": "🅾︎",
1462
+ "P": "🅿︎",
1463
+ "Q": "🆀︎",
1464
+ "R": "🆁︎",
1465
+ "S": "🆂︎",
1466
+ "T": "🆃︎",
1467
+ "U": "🆄︎",
1468
+ "V": "🆅︎",
1469
+ "W": "🆆︎",
1470
+ "X": "🆇︎",
1471
+ "Y": "🆈︎",
1472
+ "Z": "🆉︎",
1473
+ }
1474
+ for i, j in style.items():
1475
+ text = text.replace(i, j)
1476
+ return text
1477
+
1478
+ def andalucia(text):
1479
+ style = {
1480
+ "a": "ꪖ",
1481
+ "b": "᥇",
1482
+ "c": "ᥴ",
1483
+ "d": "ᦔ",
1484
+ "e": "ꫀ",
1485
+ "f": "ᠻ",
1486
+ "g": "ᧁ",
1487
+ "h": "ꫝ",
1488
+ "i": "𝓲",
1489
+ "j": "𝓳",
1490
+ "k": "𝘬",
1491
+ "l": "ꪶ",
1492
+ "m": "ꪑ",
1493
+ "n": "ꪀ",
1494
+ "o": "ꪮ",
1495
+ "p": "ρ",
1496
+ "q": "𝘲",
1497
+ "r": "𝘳",
1498
+ "s": "𝘴",
1499
+ "t": "𝓽",
1500
+ "u": "ꪊ",
1501
+ "v": "ꪜ",
1502
+ "w": "᭙",
1503
+ "x": "᥊",
1504
+ "y": "ꪗ",
1505
+ "z": "ɀ",
1506
+ "A": "ꪖ",
1507
+ "B": "᥇",
1508
+ "C": "ᥴ",
1509
+ "D": "ᦔ",
1510
+ "E": "ꫀ",
1511
+ "F": "ᠻ",
1512
+ "G": "ᧁ",
1513
+ "H": "ꫝ",
1514
+ "I": "𝓲",
1515
+ "J": "𝓳",
1516
+ "K": "𝘬",
1517
+ "L": "ꪶ",
1518
+ "M": "ꪑ",
1519
+ "N": "ꪀ",
1520
+ "O": "ꪮ",
1521
+ "P": "ρ",
1522
+ "Q": "𝘲",
1523
+ "R": "𝘳",
1524
+ "S": "𝘴",
1525
+ "T": "𝓽",
1526
+ "U": "ꪊ",
1527
+ "V": "ꪜ",
1528
+ "W": "᭙",
1529
+ "X": "᥊",
1530
+ "Y": "ꪗ",
1531
+ "Z": "ɀ",
1532
+ }
1533
+ for i, j in style.items():
1534
+ text = text.replace(i, j)
1535
+ return text
1536
+
1537
+ def manga(text):
1538
+ style = {
1539
+ "a": "卂",
1540
+ "b": "乃",
1541
+ "c": "匚",
1542
+ "d": "ᗪ",
1543
+ "e": "乇",
1544
+ "f": "千",
1545
+ "g": "ᘜ",
1546
+ "h": "卄",
1547
+ "i": "|",
1548
+ "j": "フ",
1549
+ "k": "Ҝ",
1550
+ "l": "ㄥ",
1551
+ "m": "爪",
1552
+ "n": "几",
1553
+ "o": "ㄖ",
1554
+ "p": "卩",
1555
+ "q": "Ҩ",
1556
+ "r": "尺",
1557
+ "s": "丂",
1558
+ "t": "ㄒ",
1559
+ "u": "ㄩ",
1560
+ "v": "ᐯ",
1561
+ "w": "山",
1562
+ "x": "乂",
1563
+ "y": "ㄚ",
1564
+ "z": "乙",
1565
+ "A": "卂",
1566
+ "B": "乃",
1567
+ "C": "匚",
1568
+ "D": "ᗪ",
1569
+ "E": "乇",
1570
+ "F": "千",
1571
+ "G": "ᘜ",
1572
+ "H": "卄",
1573
+ "I": "|",
1574
+ "J": "フ",
1575
+ "K": "Ҝ",
1576
+ "L": "ㄥ",
1577
+ "M": "爪",
1578
+ "N": "几",
1579
+ "O": "ㄖ",
1580
+ "P": "卩",
1581
+ "Q": "Ҩ",
1582
+ "R": "尺",
1583
+ "S": "丂",
1584
+ "T": "ㄒ",
1585
+ "U": "ㄩ",
1586
+ "V": "ᐯ",
1587
+ "W": "山",
1588
+ "X": "乂",
1589
+ "Y": "ㄚ",
1590
+ "Z": "乙",
1591
+ }
1592
+ for i, j in style.items():
1593
+ text = text.replace(i, j)
1594
+ return text
1595
+
1596
+ def stinky(text):
1597
+ style = {
1598
+ "a": "a̾",
1599
+ "b": "b̾",
1600
+ "c": "c̾",
1601
+ "d": "d̾",
1602
+ "e": "e̾",
1603
+ "f": "f̾",
1604
+ "g": "g̾",
1605
+ "h": "h̾",
1606
+ "i": "i̾",
1607
+ "j": "j̾",
1608
+ "k": "k̾",
1609
+ "l": "l̾",
1610
+ "m": "m̾",
1611
+ "n": "n̾",
1612
+ "o": "o̾",
1613
+ "p": "p̾",
1614
+ "q": "q̾",
1615
+ "r": "r̾",
1616
+ "s": "s̾",
1617
+ "t": "t̾",
1618
+ "u": "u̾",
1619
+ "v": "v̾",
1620
+ "w": "w̾",
1621
+ "x": "x̾",
1622
+ "y": "y̾",
1623
+ "z": "z̾",
1624
+ "A": "A̾",
1625
+ "B": "B̾",
1626
+ "C": "C̾",
1627
+ "D": "D̾",
1628
+ "E": "E̾",
1629
+ "F": "F̾",
1630
+ "G": "G̾",
1631
+ "H": "H̾",
1632
+ "I": "I̾",
1633
+ "J": "J̾",
1634
+ "K": "K̾",
1635
+ "L": "L̾",
1636
+ "M": "M̾",
1637
+ "N": "N̾",
1638
+ "O": "O̾",
1639
+ "P": "P̾",
1640
+ "Q": "Q̾",
1641
+ "R": "R̾",
1642
+ "S": "S̾",
1643
+ "T": "T̾",
1644
+ "U": "U̾",
1645
+ "V": "V̾",
1646
+ "W": "W̾",
1647
+ "X": "X̾",
1648
+ "Y": "Y̾",
1649
+ "Z": "Z̾",
1650
+ }
1651
+ for i, j in style.items():
1652
+ text = text.replace(i, j)
1653
+ return text
1654
+
1655
+ def bubbles(text):
1656
+ style = {
1657
+ "a": "ḁͦ",
1658
+ "b": "b̥ͦ",
1659
+ "c": "c̥ͦ",
1660
+ "d": "d̥ͦ",
1661
+ "e": "e̥ͦ",
1662
+ "f": "f̥ͦ",
1663
+ "g": "g̥ͦ",
1664
+ "h": "h̥ͦ",
1665
+ "i": "i̥ͦ",
1666
+ "j": "j̥ͦ",
1667
+ "k": "k̥ͦ",
1668
+ "l": "l̥ͦ",
1669
+ "m": "m̥ͦ",
1670
+ "n": "n̥ͦ",
1671
+ "o": "o̥ͦ",
1672
+ "p": "p̥ͦ",
1673
+ "q": "q̥ͦ",
1674
+ "r": "r̥ͦ",
1675
+ "s": "s̥ͦ",
1676
+ "t": "t̥ͦ",
1677
+ "u": "u̥ͦ",
1678
+ "v": "v̥ͦ",
1679
+ "w": "w̥ͦ",
1680
+ "x": "x̥ͦ",
1681
+ "y": "y̥ͦ",
1682
+ "z": "z̥ͦ",
1683
+ "A": "Ḁͦ",
1684
+ "B": "B̥ͦ",
1685
+ "C": "C̥ͦ",
1686
+ "D": "D̥ͦ",
1687
+ "E": "E̥ͦ",
1688
+ "F": "F̥ͦ",
1689
+ "G": "G̥ͦ",
1690
+ "H": "H̥ͦ",
1691
+ "I": "I̥ͦ",
1692
+ "J": "J̥ͦ",
1693
+ "K": "K̥ͦ",
1694
+ "L": "L̥ͦ",
1695
+ "M": "M̥ͦ",
1696
+ "N": "N̥ͦ",
1697
+ "O": "O̥ͦ",
1698
+ "P": "P̥ͦ",
1699
+ "Q": "Q̥ͦ",
1700
+ "R": "R̥ͦ",
1701
+ "S": "S̥ͦ",
1702
+ "T": "T̥ͦ",
1703
+ "U": "U̥ͦ",
1704
+ "V": "V̥ͦ",
1705
+ "W": "W̥ͦ",
1706
+ "X": "X̥ͦ",
1707
+ "Y": "Y̥ͦ",
1708
+ "Z": "Z̥ͦ",
1709
+ }
1710
+ for i, j in style.items():
1711
+ text = text.replace(i, j)
1712
+ return text
1713
+
1714
+ def underline(text):
1715
+ style = {
1716
+ "a": "a͟",
1717
+ "b": "b͟",
1718
+ "c": "c͟",
1719
+ "d": "d͟",
1720
+ "e": "e͟",
1721
+ "f": "f͟",
1722
+ "g": "g͟",
1723
+ "h": "h͟",
1724
+ "i": "i͟",
1725
+ "j": "j͟",
1726
+ "k": "k͟",
1727
+ "l": "l͟",
1728
+ "m": "m͟",
1729
+ "n": "n͟",
1730
+ "o": "o͟",
1731
+ "p": "p͟",
1732
+ "q": "q͟",
1733
+ "r": "r͟",
1734
+ "s": "s͟",
1735
+ "t": "t͟",
1736
+ "u": "u͟",
1737
+ "v": "v͟",
1738
+ "w": "w͟",
1739
+ "x": "x͟",
1740
+ "y": "y͟",
1741
+ "z": "z͟",
1742
+ "A": "A͟",
1743
+ "B": "B͟",
1744
+ "C": "C͟",
1745
+ "D": "D͟",
1746
+ "E": "E͟",
1747
+ "F": "F͟",
1748
+ "G": "G͟",
1749
+ "H": "H͟",
1750
+ "I": "I͟",
1751
+ "J": "J͟",
1752
+ "K": "K͟",
1753
+ "L": "L͟",
1754
+ "M": "M͟",
1755
+ "N": "N͟",
1756
+ "O": "O͟",
1757
+ "P": "P͟",
1758
+ "Q": "Q͟",
1759
+ "R": "R͟",
1760
+ "S": "S͟",
1761
+ "T": "T͟",
1762
+ "U": "U͟",
1763
+ "V": "V͟",
1764
+ "W": "W͟",
1765
+ "X": "X͟",
1766
+ "Y": "Y͟",
1767
+ "Z": "Z͟",
1768
+ }
1769
+ for i, j in style.items():
1770
+ text = text.replace(i, j)
1771
+ return text
1772
+
1773
+ def ladybug(text):
1774
+ style = {
1775
+ "a": "ꍏ",
1776
+ "b": "ꌃ",
1777
+ "c": "ꏳ",
1778
+ "d": "ꀷ",
1779
+ "e": "ꏂ",
1780
+ "f": "ꎇ",
1781
+ "g": "ꁅ",
1782
+ "h": "ꀍ",
1783
+ "i": "ꀤ",
1784
+ "j": "꒻",
1785
+ "k": "ꀘ",
1786
+ "l": "꒒",
1787
+ "m": "ꎭ",
1788
+ "n": "ꈤ",
1789
+ "o": "ꂦ",
1790
+ "p": "ᖘ",
1791
+ "q": "ꆰ",
1792
+ "r": "ꋪ",
1793
+ "s": "ꌚ",
1794
+ "t": "꓄",
1795
+ "u": "ꀎ",
1796
+ "v": "꒦",
1797
+ "w": "ꅐ",
1798
+ "x": "ꉧ",
1799
+ "y": "ꌩ",
1800
+ "z": "ꁴ",
1801
+ "A": "ꍏ",
1802
+ "B": "ꌃ",
1803
+ "C": "ꏳ",
1804
+ "D": "ꀷ",
1805
+ "E": "ꏂ",
1806
+ "F": "ꎇ",
1807
+ "G": "ꁅ",
1808
+ "H": "ꀍ",
1809
+ "I": "ꀤ",
1810
+ "J": "꒻",
1811
+ "K": "ꀘ",
1812
+ "L": "꒒",
1813
+ "M": "ꎭ",
1814
+ "N": "ꈤ",
1815
+ "O": "ꂦ",
1816
+ "P": "ᖘ",
1817
+ "Q": "ꆰ",
1818
+ "R": "ꋪ",
1819
+ "S": "ꌚ",
1820
+ "T": "꓄",
1821
+ "U": "ꀎ",
1822
+ "V": "꒦",
1823
+ "W": "ꅐ",
1824
+ "X": "ꉧ",
1825
+ "Y": "ꌩ",
1826
+ "Z": "ꁴ",
1827
+ }
1828
+ for i, j in style.items():
1829
+ text = text.replace(i, j)
1830
+ return text
1831
+
1832
+ def rays(text):
1833
+ style = {
1834
+ "a": "a҉",
1835
+ "b": "b҉",
1836
+ "c": "c҉",
1837
+ "d": "d҉",
1838
+ "e": "e҉",
1839
+ "f": "f҉",
1840
+ "g": "g҉",
1841
+ "h": "h҉",
1842
+ "i": "i҉",
1843
+ "j": "j҉",
1844
+ "k": "k҉",
1845
+ "l": "l҉",
1846
+ "m": "m҉",
1847
+ "n": "n҉",
1848
+ "o": "o҉",
1849
+ "p": "p҉",
1850
+ "q": "q҉",
1851
+ "r": "r҉",
1852
+ "s": "s҉",
1853
+ "t": "t҉",
1854
+ "u": "u҉",
1855
+ "v": "v҉",
1856
+ "w": "w҉",
1857
+ "x": "x҉",
1858
+ "y": "y҉",
1859
+ "z": "z҉",
1860
+ "A": "A҉",
1861
+ "B": "B҉",
1862
+ "C": "C҉",
1863
+ "D": "D҉",
1864
+ "E": "E҉",
1865
+ "F": "F҉",
1866
+ "G": "G҉",
1867
+ "H": "H҉",
1868
+ "I": "I҉",
1869
+ "J": "J҉",
1870
+ "K": "K҉",
1871
+ "L": "L҉",
1872
+ "M": "M҉",
1873
+ "N": "N҉",
1874
+ "O": "O҉",
1875
+ "P": "P҉",
1876
+ "Q": "Q҉",
1877
+ "R": "R҉",
1878
+ "S": "S҉",
1879
+ "T": "T҉",
1880
+ "U": "U҉",
1881
+ "V": "V҉",
1882
+ "W": "W҉",
1883
+ "X": "X҉",
1884
+ "Y": "Y҉",
1885
+ "Z": "Z҉",
1886
+ }
1887
+ for i, j in style.items():
1888
+ text = text.replace(i, j)
1889
+ return text
1890
+
1891
+ def birds(text):
1892
+ style = {
1893
+ "a": "a҈",
1894
+ "b": "b҈",
1895
+ "c": "c҈",
1896
+ "d": "d҈",
1897
+ "e": "e҈",
1898
+ "f": "f҈",
1899
+ "g": "g҈",
1900
+ "h": "h҈",
1901
+ "i": "i҈",
1902
+ "j": "j҈",
1903
+ "k": "k҈",
1904
+ "l": "l҈",
1905
+ "m": "m҈",
1906
+ "n": "n҈",
1907
+ "o": "o҈",
1908
+ "p": "p҈",
1909
+ "q": "q҈",
1910
+ "r": "r҈",
1911
+ "s": "s҈",
1912
+ "t": "t҈",
1913
+ "u": "u҈",
1914
+ "v": "v҈",
1915
+ "w": "w҈",
1916
+ "x": "x҈",
1917
+ "y": "y҈",
1918
+ "z": "z҈",
1919
+ "A": "A҈",
1920
+ "B": "B҈",
1921
+ "C": "C҈",
1922
+ "D": "D҈",
1923
+ "E": "E҈",
1924
+ "F": "F҈",
1925
+ "G": "G҈",
1926
+ "H": "H҈",
1927
+ "I": "I҈",
1928
+ "J": "J҈",
1929
+ "K": "K҈",
1930
+ "L": "L҈",
1931
+ "M": "M҈",
1932
+ "N": "N҈",
1933
+ "O": "O҈",
1934
+ "P": "P҈",
1935
+ "Q": "Q҈",
1936
+ "R": "R҈",
1937
+ "S": "S҈",
1938
+ "T": "T҈",
1939
+ "U": "U҈",
1940
+ "V": "V҈",
1941
+ "W": "W҈",
1942
+ "X": "X҈",
1943
+ "Y": "Y҈",
1944
+ "Z": "Z҈",
1945
+ }
1946
+ for i, j in style.items():
1947
+ text = text.replace(i, j)
1948
+ return text
1949
+
1950
+ def slash(text):
1951
+ style = {
1952
+ "a": "a̸",
1953
+ "b": "b̸",
1954
+ "c": "c̸",
1955
+ "d": "d̸",
1956
+ "e": "e̸",
1957
+ "f": "f̸",
1958
+ "g": "g̸",
1959
+ "h": "h̸",
1960
+ "i": "i̸",
1961
+ "j": "j̸",
1962
+ "k": "k̸",
1963
+ "l": "l̸",
1964
+ "m": "m̸",
1965
+ "n": "n̸",
1966
+ "o": "o̸",
1967
+ "p": "p̸",
1968
+ "q": "q̸",
1969
+ "r": "r̸",
1970
+ "s": "s̸",
1971
+ "t": "t̸",
1972
+ "u": "u̸",
1973
+ "v": "v̸",
1974
+ "w": "w̸",
1975
+ "x": "x̸",
1976
+ "y": "y̸",
1977
+ "z": "z̸",
1978
+ "A": "A̸",
1979
+ "B": "B̸",
1980
+ "C": "C̸",
1981
+ "D": "D̸",
1982
+ "E": "E̸",
1983
+ "F": "F̸",
1984
+ "G": "G̸",
1985
+ "H": "H̸",
1986
+ "I": "I̸",
1987
+ "J": "J̸",
1988
+ "K": "K̸",
1989
+ "L": "L̸",
1990
+ "M": "M̸",
1991
+ "N": "N̸",
1992
+ "O": "O̸",
1993
+ "P": "P̸",
1994
+ "Q": "Q̸",
1995
+ "R": "R̸",
1996
+ "S": "S̸",
1997
+ "T": "T̸",
1998
+ "U": "U̸",
1999
+ "V": "V̸",
2000
+ "W": "W̸",
2001
+ "X": "X̸",
2002
+ "Y": "Y̸",
2003
+ "Z": "Z̸",
2004
+ }
2005
+ for i, j in style.items():
2006
+ text = text.replace(i, j)
2007
+ return text
2008
+
2009
+ def stop(text):
2010
+ style = {
2011
+ "a": "a⃠",
2012
+ "b": "b⃠",
2013
+ "c": "c⃠",
2014
+ "d": "d⃠",
2015
+ "e": "e⃠",
2016
+ "f": "f⃠",
2017
+ "g": "g⃠",
2018
+ "h": "h⃠",
2019
+ "i": "i⃠",
2020
+ "j": "j⃠",
2021
+ "k": "k⃠",
2022
+ "l": "l⃠",
2023
+ "m": "m⃠",
2024
+ "n": "n⃠",
2025
+ "o": "o⃠",
2026
+ "p": "p⃠",
2027
+ "q": "q⃠",
2028
+ "r": "r⃠",
2029
+ "s": "s⃠",
2030
+ "t": "t⃠",
2031
+ "u": "u⃠",
2032
+ "v": "v⃠",
2033
+ "w": "w⃠",
2034
+ "x": "x⃠",
2035
+ "y": "y⃠",
2036
+ "z": "z⃠",
2037
+ "A": "A⃠",
2038
+ "B": "B⃠",
2039
+ "C": "C⃠",
2040
+ "D": "D⃠",
2041
+ "E": "E⃠",
2042
+ "F": "F⃠",
2043
+ "G": "G⃠",
2044
+ "H": "H⃠",
2045
+ "I": "I⃠",
2046
+ "J": "J⃠",
2047
+ "K": "K⃠",
2048
+ "L": "L⃠",
2049
+ "M": "M⃠",
2050
+ "N": "N⃠",
2051
+ "O": "O⃠",
2052
+ "P": "P⃠",
2053
+ "Q": "Q⃠",
2054
+ "R": "R⃠",
2055
+ "S": "S⃠",
2056
+ "T": "T⃠",
2057
+ "U": "U⃠",
2058
+ "V": "V⃠",
2059
+ "W": "W⃠",
2060
+ "X": "X⃠",
2061
+ "Y": "Y⃠",
2062
+ "Z": "Z⃠",
2063
+ }
2064
+ for i, j in style.items():
2065
+ text = text.replace(i, j)
2066
+ return text
2067
+
2068
+ def skyline(text):
2069
+ style = {
2070
+ "a": "a̺͆",
2071
+ "b": "b̺͆",
2072
+ "c": "c̺͆",
2073
+ "d": "d̺͆",
2074
+ "e": "e̺͆",
2075
+ "f": "f̺͆",
2076
+ "g": "g̺͆",
2077
+ "h": "h̺͆",
2078
+ "i": "i̺͆",
2079
+ "j": "j̺͆",
2080
+ "k": "k̺͆",
2081
+ "l": "l̺͆",
2082
+ "m": "m̺͆",
2083
+ "n": "n̺͆",
2084
+ "o": "o̺͆",
2085
+ "p": "p̺͆",
2086
+ "q": "q̺͆",
2087
+ "r": "r̺͆",
2088
+ "s": "s̺͆",
2089
+ "t": "t̺͆",
2090
+ "u": "u̺͆",
2091
+ "v": "v̺͆",
2092
+ "w": "w̺͆",
2093
+ "x": "x̺͆",
2094
+ "y": "y̺͆",
2095
+ "z": "z̺͆",
2096
+ "A": "A̺͆",
2097
+ "B": "B̺͆",
2098
+ "C": "C̺͆",
2099
+ "D": "D̺͆",
2100
+ "E": "E̺͆",
2101
+ "F": "F̺͆",
2102
+ "G": "G̺͆",
2103
+ "H": "H̺͆",
2104
+ "I": "I̺͆",
2105
+ "J": "J̺͆",
2106
+ "K": "K̺͆",
2107
+ "L": "L̺͆",
2108
+ "M": "M̺͆",
2109
+ "N": "N̺͆",
2110
+ "O": "O̺͆",
2111
+ "P": "P̺͆",
2112
+ "Q": "Q̺͆",
2113
+ "R": "R̺͆",
2114
+ "S": "S̺͆",
2115
+ "T": "T̺͆",
2116
+ "U": "U̺͆",
2117
+ "V": "V̺͆",
2118
+ "W": "W̺͆",
2119
+ "X": "X̺͆",
2120
+ "Y": "Y̺͆",
2121
+ "Z": "Z̺͆",
2122
+ }
2123
+ for i, j in style.items():
2124
+ text = text.replace(i, j)
2125
+ return text
2126
+
2127
+ def arrows(text):
2128
+ style = {
2129
+ "a": "a͎",
2130
+ "b": "b͎",
2131
+ "c": "c͎",
2132
+ "d": "d͎",
2133
+ "e": "e͎",
2134
+ "f": "f͎",
2135
+ "g": "g͎",
2136
+ "h": "h͎",
2137
+ "i": "i͎",
2138
+ "j": "j͎",
2139
+ "k": "k͎",
2140
+ "l": "l͎",
2141
+ "m": "m͎",
2142
+ "n": "n͎",
2143
+ "o": "o͎",
2144
+ "p": "p͎",
2145
+ "q": "q͎",
2146
+ "r": "r͎",
2147
+ "s": "s͎",
2148
+ "t": "t͎",
2149
+ "u": "u͎",
2150
+ "v": "v͎",
2151
+ "w": "w͎",
2152
+ "x": "x͎",
2153
+ "y": "y͎",
2154
+ "z": "z͎",
2155
+ "A": "A͎",
2156
+ "B": "B͎",
2157
+ "C": "C͎",
2158
+ "D": "D͎",
2159
+ "E": "E͎",
2160
+ "F": "F͎",
2161
+ "G": "G͎",
2162
+ "H": "H͎",
2163
+ "I": "I͎",
2164
+ "J": "J͎",
2165
+ "K": "K͎",
2166
+ "L": "L͎",
2167
+ "M": "M͎",
2168
+ "N": "N͎",
2169
+ "O": "O͎",
2170
+ "P": "P͎",
2171
+ "Q": "Q͎",
2172
+ "R": "R͎",
2173
+ "S": "S͎",
2174
+ "T": "T͎",
2175
+ "U": "U͎",
2176
+ "V": "V͎",
2177
+ "W": "W͎",
2178
+ "X": "X͎",
2179
+ "Y": "Y͎",
2180
+ "Z": "Z͎",
2181
+ }
2182
+ for i, j in style.items():
2183
+ text = text.replace(i, j)
2184
+ return text
2185
+
2186
+ def rvnes(text):
2187
+ style = {
2188
+ "a": "ል",
2189
+ "b": "ጌ",
2190
+ "c": "ር",
2191
+ "d": "ዕ",
2192
+ "e": "ቿ",
2193
+ "f": "ቻ",
2194
+ "g": "ኗ",
2195
+ "h": "ዘ",
2196
+ "i": "ጎ",
2197
+ "j": "ጋ",
2198
+ "k": "ጕ",
2199
+ "l": "ረ",
2200
+ "m": "ጠ",
2201
+ "n": "ክ",
2202
+ "o": "ዐ",
2203
+ "p": "የ",
2204
+ "q": "ዒ",
2205
+ "r": "ዪ",
2206
+ "s": "ነ",
2207
+ "t": "ፕ",
2208
+ "u": "ሁ",
2209
+ "v": "ሀ",
2210
+ "w": "ሠ",
2211
+ "x": "ሸ",
2212
+ "y": "ሃ",
2213
+ "z": "ጊ",
2214
+ "A": "ል",
2215
+ "B": "ጌ",
2216
+ "C": "ር",
2217
+ "D": "ዕ",
2218
+ "E": "ቿ",
2219
+ "F": "ቻ",
2220
+ "G": "ኗ",
2221
+ "H": "ዘ",
2222
+ "I": "ጎ",
2223
+ "J": "ጋ",
2224
+ "K": "ጕ",
2225
+ "L": "ረ",
2226
+ "M": "ጠ",
2227
+ "N": "ክ",
2228
+ "O": "ዐ",
2229
+ "P": "የ",
2230
+ "Q": "ዒ",
2231
+ "R": "ዪ",
2232
+ "S": "ነ",
2233
+ "T": "ፕ",
2234
+ "U": "ሁ",
2235
+ "V": "ሀ",
2236
+ "W": "ሠ",
2237
+ "X": "ሸ",
2238
+ "Y": "ሃ",
2239
+ "Z": "ጊ",
2240
+ }
2241
+ for i, j in style.items():
2242
+ text = text.replace(i, j)
2243
+ return text
2244
+
2245
+ def strike(text):
2246
+ style = {
2247
+ "a": "a̶",
2248
+ "b": "b̶",
2249
+ "c": "c̶",
2250
+ "d": "d̶",
2251
+ "e": "e̶",
2252
+ "f": "f̶",
2253
+ "g": "g̶",
2254
+ "h": "h̶",
2255
+ "i": "i̶",
2256
+ "j": "j̶",
2257
+ "k": "k̶",
2258
+ "l": "l̶",
2259
+ "m": "m̶",
2260
+ "n": "n̶",
2261
+ "o": "o̶",
2262
+ "p": "p̶",
2263
+ "q": "q̶",
2264
+ "r": "r̶",
2265
+ "s": "s̶",
2266
+ "t": "t̶",
2267
+ "u": "u̶",
2268
+ "v": "v̶",
2269
+ "w": "w̶",
2270
+ "x": "x̶",
2271
+ "y": "y̶",
2272
+ "z": "z̶",
2273
+ "A": "A̶",
2274
+ "B": "B̶",
2275
+ "C": "C̶",
2276
+ "D": "D̶",
2277
+ "E": "E̶",
2278
+ "F": "F̶",
2279
+ "G": "G̶",
2280
+ "H": "H̶",
2281
+ "I": "I̶",
2282
+ "J": "J̶",
2283
+ "K": "K̶",
2284
+ "L": "L̶",
2285
+ "M": "M̶",
2286
+ "N": "N̶",
2287
+ "O": "O̶",
2288
+ "P": "P̶",
2289
+ "Q": "Q̶",
2290
+ "R": "R̶",
2291
+ "S": "S̶",
2292
+ "T": "T̶",
2293
+ "U": "U̶",
2294
+ "V": "V̶",
2295
+ "W": "W̶",
2296
+ "X": "X̶",
2297
+ "Y": "Y̶",
2298
+ "Z": "Z̶",
2299
+ }
2300
+ for i, j in style.items():
2301
+ text = text.replace(i, j)
2302
+ return text
2303
+
2304
+ def frozen(text):
2305
+ style = {
2306
+ "a": "a༙",
2307
+ "b": "b༙",
2308
+ "c": "c༙",
2309
+ "d": "d༙",
2310
+ "e": "e༙",
2311
+ "f": "f༙",
2312
+ "g": "g༙",
2313
+ "h": "h༙",
2314
+ "i": "i༙",
2315
+ "j": "j༙",
2316
+ "k": "k༙",
2317
+ "l": "l༙",
2318
+ "m": "m༙",
2319
+ "n": "n༙",
2320
+ "o": "o༙",
2321
+ "p": "p༙",
2322
+ "q": "q༙",
2323
+ "r": "r༙",
2324
+ "s": "s༙",
2325
+ "t": "t༙",
2326
+ "u": "u༙",
2327
+ "v": "v༙",
2328
+ "w": "w༙",
2329
+ "x": "x༙",
2330
+ "y": "y༙",
2331
+ "z": "z༙",
2332
+ "A": "A༙",
2333
+ "B": "B༙",
2334
+ "C": "C༙",
2335
+ "D": "D༙",
2336
+ "E": "E༙",
2337
+ "F": "F༙",
2338
+ "G": "G༙",
2339
+ "H": "H༙",
2340
+ "I": "I༙",
2341
+ "J": "J༙",
2342
+ "K": "K༙",
2343
+ "L": "L༙",
2344
+ "M": "M༙",
2345
+ "N": "N༙",
2346
+ "O": "O༙",
2347
+ "P": "P༙",
2348
+ "Q": "Q༙",
2349
+ "R": "R༙",
2350
+ "S": "S༙",
2351
+ "T": "T༙",
2352
+ "U": "U༙",
2353
+ "V": "V༙",
2354
+ "W": "W༙",
2355
+ "X": "X༙",
2356
+ "Y": "Y༙",
2357
+ "Z": "Z༙",
2358
+ }
2359
+ for i, j in style.items():
2360
+ text = text.replace(i, j)
2361
+ return text
Database/sql/forceSubscribe_sql.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import Column, Numeric, String
2
+
3
+ from Database.sql import BASE, SESSION
4
+
5
+
6
+ class forceSubscribe(BASE):
7
+ __tablename__ = "forceSubscribe"
8
+ chat_id = Column(Numeric, primary_key=True)
9
+ channel = Column(String)
10
+
11
+ def __init__(self, chat_id, channel):
12
+ self.chat_id = chat_id
13
+ self.channel = channel
14
+
15
+
16
+ forceSubscribe.__table__.create(checkfirst=True)
17
+
18
+
19
+ def fs_settings(chat_id):
20
+ try:
21
+ return (
22
+ SESSION.query(forceSubscribe)
23
+ .filter(forceSubscribe.chat_id == chat_id)
24
+ .one()
25
+ )
26
+ except:
27
+ return None
28
+ finally:
29
+ SESSION.close()
30
+
31
+
32
+ def add_channel(chat_id, channel):
33
+ adder = SESSION.query(forceSubscribe).get(chat_id)
34
+ if adder:
35
+ adder.channel = channel
36
+ else:
37
+ adder = forceSubscribe(chat_id, channel)
38
+ SESSION.add(adder)
39
+ SESSION.commit()
40
+
41
+
42
+ def disapprove(chat_id):
43
+ rem = SESSION.query(forceSubscribe).get(chat_id)
44
+ if rem:
45
+ SESSION.delete(rem)
46
+ SESSION.commit()
Database/sql/locks_sql.py ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
+ # New chat added -> setup permissions
26
+ import threading
27
+
28
+ from sqlalchemy import Boolean, Column, String
29
+
30
+ from Database.sql import BASE, SESSION
31
+
32
+
33
+ class Permissions(BASE):
34
+ __tablename__ = "permissions"
35
+ chat_id = Column(String(14), primary_key=True)
36
+ # Booleans are for "is this locked", _NOT_ "is this allowed"
37
+ audio = Column(Boolean, default=False)
38
+ voice = Column(Boolean, default=False)
39
+ contact = Column(Boolean, default=False)
40
+ video = Column(Boolean, default=False)
41
+ document = Column(Boolean, default=False)
42
+ photo = Column(Boolean, default=False)
43
+ sticker = Column(Boolean, default=False)
44
+ gif = Column(Boolean, default=False)
45
+ url = Column(Boolean, default=False)
46
+ bots = Column(Boolean, default=False)
47
+ forward = Column(Boolean, default=False)
48
+ game = Column(Boolean, default=False)
49
+ location = Column(Boolean, default=False)
50
+ rtl = Column(Boolean, default=False)
51
+ button = Column(Boolean, default=False)
52
+ egame = Column(Boolean, default=False)
53
+ inline = Column(Boolean, default=False)
54
+
55
+ def __init__(self, chat_id):
56
+ self.chat_id = str(chat_id) # ensure string
57
+ self.audio = False
58
+ self.voice = False
59
+ self.contact = False
60
+ self.video = False
61
+ self.document = False
62
+ self.photo = False
63
+ self.sticker = False
64
+ self.gif = False
65
+ self.url = False
66
+ self.bots = False
67
+ self.forward = False
68
+ self.game = False
69
+ self.location = False
70
+ self.rtl = False
71
+ self.button = False
72
+ self.egame = False
73
+ self.inline = False
74
+
75
+ def __repr__(self):
76
+ return "<ᴘᴇʀᴍɪssɪᴏɴs ғᴏʀ %s>" % self.chat_id
77
+
78
+
79
+ class Restrictions(BASE):
80
+ __tablename__ = "restrictions"
81
+ chat_id = Column(String(14), primary_key=True)
82
+ # Booleans are for "is this restricted", _NOT_ "is this allowed"
83
+ messages = Column(Boolean, default=False)
84
+ media = Column(Boolean, default=False)
85
+ other = Column(Boolean, default=False)
86
+ preview = Column(Boolean, default=False)
87
+
88
+ def __init__(self, chat_id):
89
+ self.chat_id = str(chat_id) # ensure string
90
+ self.messages = False
91
+ self.media = False
92
+ self.other = False
93
+ self.preview = False
94
+
95
+ def __repr__(self):
96
+ return "<ʀᴇsᴛʀɪᴄᴛɪᴏɴs ғᴏʀ %s>" % self.chat_id
97
+
98
+
99
+ # For those who faced database error, Just uncomment the
100
+ # line below and run bot for 1 time & remove that line!
101
+
102
+ Permissions.__table__.create(checkfirst=True)
103
+ # Permissions.__table__.drop()
104
+ Restrictions.__table__.create(checkfirst=True)
105
+
106
+ PERM_LOCK = threading.RLock()
107
+ RESTR_LOCK = threading.RLock()
108
+
109
+
110
+ def init_permissions(chat_id, reset=False):
111
+ curr_perm = SESSION.query(Permissions).get(str(chat_id))
112
+ if reset:
113
+ SESSION.delete(curr_perm)
114
+ SESSION.flush()
115
+ perm = Permissions(str(chat_id))
116
+ SESSION.add(perm)
117
+ SESSION.commit()
118
+ return perm
119
+
120
+
121
+ def init_restrictions(chat_id, reset=False):
122
+ curr_restr = SESSION.query(Restrictions).get(str(chat_id))
123
+ if reset:
124
+ SESSION.delete(curr_restr)
125
+ SESSION.flush()
126
+ restr = Restrictions(str(chat_id))
127
+ SESSION.add(restr)
128
+ SESSION.commit()
129
+ return restr
130
+
131
+
132
+ def update_lock(chat_id, lock_type, locked):
133
+ with PERM_LOCK:
134
+ curr_perm = SESSION.query(Permissions).get(str(chat_id))
135
+ if not curr_perm:
136
+ curr_perm = init_permissions(chat_id)
137
+
138
+ if lock_type == "audio":
139
+ curr_perm.audio = locked
140
+ elif lock_type == "voice":
141
+ curr_perm.voice = locked
142
+ elif lock_type == "contact":
143
+ curr_perm.contact = locked
144
+ elif lock_type == "video":
145
+ curr_perm.video = locked
146
+ elif lock_type == "document":
147
+ curr_perm.document = locked
148
+ elif lock_type == "photo":
149
+ curr_perm.photo = locked
150
+ elif lock_type == "sticker":
151
+ curr_perm.sticker = locked
152
+ elif lock_type == "gif":
153
+ curr_perm.gif = locked
154
+ elif lock_type == "url":
155
+ curr_perm.url = locked
156
+ elif lock_type == "bots":
157
+ curr_perm.bots = locked
158
+ elif lock_type == "forward":
159
+ curr_perm.forward = locked
160
+ elif lock_type == "game":
161
+ curr_perm.game = locked
162
+ elif lock_type == "location":
163
+ curr_perm.location = locked
164
+ elif lock_type == "rtl":
165
+ curr_perm.rtl = locked
166
+ elif lock_type == "button":
167
+ curr_perm.button = locked
168
+ elif lock_type == "egame":
169
+ curr_perm.egame = locked
170
+ elif lock_type == "inline":
171
+ curr_perm.inline = locked
172
+
173
+ SESSION.add(curr_perm)
174
+ SESSION.commit()
175
+
176
+
177
+ def update_restriction(chat_id, restr_type, locked):
178
+ with RESTR_LOCK:
179
+ curr_restr = SESSION.query(Restrictions).get(str(chat_id))
180
+ if not curr_restr:
181
+ curr_restr = init_restrictions(chat_id)
182
+
183
+ if restr_type == "messages":
184
+ curr_restr.messages = locked
185
+ elif restr_type == "media":
186
+ curr_restr.media = locked
187
+ elif restr_type == "other":
188
+ curr_restr.other = locked
189
+ elif restr_type == "previews":
190
+ curr_restr.preview = locked
191
+ elif restr_type == "all":
192
+ curr_restr.messages = locked
193
+ curr_restr.media = locked
194
+ curr_restr.other = locked
195
+ curr_restr.preview = locked
196
+ SESSION.add(curr_restr)
197
+ SESSION.commit()
198
+
199
+
200
+ def is_locked(chat_id, lock_type):
201
+ curr_perm = SESSION.query(Permissions).get(str(chat_id))
202
+ SESSION.close()
203
+
204
+ if not curr_perm:
205
+ return False
206
+
207
+ if lock_type == "sticker":
208
+ return curr_perm.sticker
209
+ if lock_type == "photo":
210
+ return curr_perm.photo
211
+ if lock_type == "audio":
212
+ return curr_perm.audio
213
+ if lock_type == "voice":
214
+ return curr_perm.voice
215
+ if lock_type == "contact":
216
+ return curr_perm.contact
217
+ if lock_type == "video":
218
+ return curr_perm.video
219
+ if lock_type == "document":
220
+ return curr_perm.document
221
+ if lock_type == "gif":
222
+ return curr_perm.gif
223
+ if lock_type == "url":
224
+ return curr_perm.url
225
+ if lock_type == "bots":
226
+ return curr_perm.bots
227
+ if lock_type == "forward":
228
+ return curr_perm.forward
229
+ if lock_type == "game":
230
+ return curr_perm.game
231
+ if lock_type == "location":
232
+ return curr_perm.location
233
+ if lock_type == "rtl":
234
+ return curr_perm.rtl
235
+ if lock_type == "button":
236
+ return curr_perm.button
237
+ if lock_type == "egame":
238
+ return curr_perm.egame
239
+ if lock_type == "inline":
240
+ return curr_perm.inline
241
+
242
+
243
+ def is_restr_locked(chat_id, lock_type):
244
+ curr_restr = SESSION.query(Restrictions).get(str(chat_id))
245
+ SESSION.close()
246
+
247
+ if not curr_restr:
248
+ return False
249
+
250
+ if lock_type == "messages":
251
+ return curr_restr.messages
252
+ if lock_type == "media":
253
+ return curr_restr.media
254
+ if lock_type == "other":
255
+ return curr_restr.other
256
+ if lock_type == "previews":
257
+ return curr_restr.preview
258
+ if lock_type == "all":
259
+ return (
260
+ curr_restr.messages
261
+ and curr_restr.media
262
+ and curr_restr.other
263
+ and curr_restr.preview
264
+ )
265
+
266
+
267
+ def get_locks(chat_id):
268
+ try:
269
+ return SESSION.query(Permissions).get(str(chat_id))
270
+ finally:
271
+ SESSION.close()
272
+
273
+
274
+ def get_restr(chat_id):
275
+ try:
276
+ return SESSION.query(Restrictions).get(str(chat_id))
277
+ finally:
278
+ SESSION.close()
279
+
280
+
281
+ def migrate_chat(old_chat_id, new_chat_id):
282
+ with PERM_LOCK:
283
+ perms = SESSION.query(Permissions).get(str(old_chat_id))
284
+ if perms:
285
+ perms.chat_id = str(new_chat_id)
286
+ SESSION.commit()
287
+
288
+ with RESTR_LOCK:
289
+ rest = SESSION.query(Restrictions).get(str(old_chat_id))
290
+ if rest:
291
+ rest.chat_id = str(new_chat_id)
292
+ SESSION.commit()
Database/sql/log_channel_sql.py CHANGED
@@ -1,3 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
  import typing
3
 
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import threading
26
  import typing
27
 
Database/sql/nightmode_sql.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from sqlalchemy import Column, String
2
+
3
+ from Database.sql import BASE, SESSION
4
+
5
+
6
+ class Nightmode(BASE):
7
+ __tablename__ = "nightmode"
8
+ chat_id = Column(String(14), primary_key=True)
9
+
10
+ def __init__(self, chat_id):
11
+ self.chat_id = chat_id
12
+
13
+
14
+ Nightmode.__table__.create(checkfirst=True)
15
+
16
+
17
+ def add_nightmode(chat_id: str):
18
+ nightmoddy = Nightmode(str(chat_id))
19
+ SESSION.add(nightmoddy)
20
+ SESSION.commit()
21
+
22
+
23
+ def rmnightmode(chat_id: str):
24
+ rmnightmoddy = SESSION.query(Nightmode).get(str(chat_id))
25
+ if rmnightmoddy:
26
+ SESSION.delete(rmnightmoddy)
27
+ SESSION.commit()
28
+
29
+
30
+ def get_all_chat_id():
31
+ stark = SESSION.query(Nightmode).all()
32
+ SESSION.close()
33
+ return stark
34
+
35
+
36
+ def is_nightmode_indb(chat_id: str):
37
+ try:
38
+ s__ = SESSION.query(Nightmode).get(str(chat_id))
39
+ if s__:
40
+ return str(s__.chat_id)
41
+ finally:
42
+ SESSION.close()
Database/sql/notes_sql.py CHANGED
@@ -1,6 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
 
3
- from sqlalchemy import Boolean, Column, Integer, String, UnicodeText, distinct, func
4
 
5
  from Database.sql import BASE, SESSION
6
  from Mikobot.plugins.helper_funcs.msg_types import Types
@@ -14,7 +39,7 @@ class Notes(BASE):
14
  file = Column(UnicodeText)
15
  is_reply = Column(Boolean, default=False)
16
  has_buttons = Column(Boolean, default=False)
17
- msgtype = Column(Integer, default=Types.BUTTON_TEXT.value)
18
 
19
  def __init__(self, chat_id, name, value, msgtype, file=None):
20
  self.chat_id = str(chat_id) # ensure string
@@ -24,12 +49,12 @@ class Notes(BASE):
24
  self.file = file
25
 
26
  def __repr__(self):
27
- return "<Note %s>" % self.name
28
 
29
 
30
  class Buttons(BASE):
31
  __tablename__ = "note_urls"
32
- id = Column(Integer, primary_key=True, autoincrement=True)
33
  chat_id = Column(String(14), primary_key=True)
34
  note_name = Column(UnicodeText, primary_key=True)
35
  name = Column(UnicodeText, nullable=False)
@@ -118,10 +143,8 @@ def rm_note(chat_id, note_name):
118
  SESSION.delete(note)
119
  SESSION.commit()
120
  return True
121
-
122
- else:
123
- SESSION.close()
124
- return False
125
 
126
 
127
  def get_all_chat_notes(chat_id):
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
+ # Note: chat_id's are stored as strings because the int is too large to be stored in a PSQL database.
26
  import threading
27
 
28
+ from sqlalchemy import BigInteger, Boolean, Column, String, UnicodeText, distinct, func
29
 
30
  from Database.sql import BASE, SESSION
31
  from Mikobot.plugins.helper_funcs.msg_types import Types
 
39
  file = Column(UnicodeText)
40
  is_reply = Column(Boolean, default=False)
41
  has_buttons = Column(Boolean, default=False)
42
+ msgtype = Column(BigInteger, default=Types.BUTTON_TEXT.value)
43
 
44
  def __init__(self, chat_id, name, value, msgtype, file=None):
45
  self.chat_id = str(chat_id) # ensure string
 
49
  self.file = file
50
 
51
  def __repr__(self):
52
+ return "<ɴᴏᴛᴇ %s>" % self.name
53
 
54
 
55
  class Buttons(BASE):
56
  __tablename__ = "note_urls"
57
+ id = Column(BigInteger, primary_key=True, autoincrement=True)
58
  chat_id = Column(String(14), primary_key=True)
59
  note_name = Column(UnicodeText, primary_key=True)
60
  name = Column(UnicodeText, nullable=False)
 
143
  SESSION.delete(note)
144
  SESSION.commit()
145
  return True
146
+ SESSION.close()
147
+ return False
 
 
148
 
149
 
150
  def get_all_chat_notes(chat_id):
Database/sql/raid_sql.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
+ import threading
26
+
27
+ from sqlalchemy import Column, String
28
+
29
+ from Database.sql import BASE, SESSION
30
+
31
+
32
+ class RaidChats(BASE):
33
+ __tablename__ = "raid_chats"
34
+ chat_id = Column(String(14), primary_key=True)
35
+
36
+ def __init__(self, chat_id):
37
+ self.chat_id = chat_id
38
+
39
+
40
+ RaidChats.__table__.create(checkfirst=True)
41
+ INSERTION_LOCK = threading.RLock()
42
+
43
+
44
+ def is_raid(chat_id):
45
+ try:
46
+ chat = SESSION.query(RaidChats).get(str(chat_id))
47
+ return bool(chat)
48
+ finally:
49
+ SESSION.close()
50
+
51
+
52
+ def set_raid(chat_id):
53
+ with INSERTION_LOCK:
54
+ raidchat = SESSION.query(RaidChats).get(str(chat_id))
55
+ if not raidchat:
56
+ raidchat = RaidChats(str(chat_id))
57
+ SESSION.add(raidchat)
58
+ SESSION.commit()
59
+
60
+
61
+ def rem_raid(chat_id):
62
+ with INSERTION_LOCK:
63
+ raidchat = SESSION.query(RaidChats).get(str(chat_id))
64
+ if raidchat:
65
+ SESSION.delete(raidchat)
66
+ SESSION.commit()
67
+
68
+
69
+ def get_all_raid_chats():
70
+ try:
71
+ return SESSION.query(RaidChats.chat_id).all()
72
+ finally:
73
+ SESSION.close()
Database/sql/remind_sql.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
+ import threading
26
+ import time
27
+
28
+ from sqlalchemy import Column, Integer, String, UnicodeText
29
+ from sqlalchemy.sql.sqltypes import BigInteger
30
+
31
+ from Database.sql import BASE, SESSION
32
+
33
+
34
+ class Reminds(BASE):
35
+ __tablename__ = "reminds"
36
+ chat_id = Column(String(14), primary_key=True)
37
+ time_seconds = Column(Integer, primary_key=True)
38
+ remind_message = Column(UnicodeText, default="")
39
+ user_id = Column(BigInteger, default=0)
40
+
41
+ def __init__(self, chat_id, time_seconds):
42
+ self.chat_id = str(chat_id)
43
+ self.time_seconds = int(time_seconds)
44
+
45
+ def __repr__(self):
46
+ return "<ʀᴇᴍɪɴᴅ ɪɴ {} ғᴏʀ ᴛɪᴍᴇ {}>".format(
47
+ self.chat_id,
48
+ self.time_seconds,
49
+ )
50
+
51
+
52
+ # Reminds.__table__.drop()
53
+ Reminds.__table__.create(checkfirst=True)
54
+
55
+ INSERTION_LOCK = threading.RLock()
56
+
57
+ REMINDERS = {}
58
+
59
+
60
+ def set_remind(chat_id, time_sec, remind_message, user_id):
61
+ with INSERTION_LOCK:
62
+ reminds = SESSION.query(Reminds).get((str(chat_id), time_sec))
63
+ if not reminds:
64
+ reminds = Reminds(chat_id, time_sec)
65
+ reminds.remind_message = remind_message
66
+ reminds.user_id = user_id
67
+ SESSION.add(reminds)
68
+ SESSION.commit()
69
+ if not time_sec in REMINDERS:
70
+ REMINDERS[time_sec] = []
71
+ REMINDERS[time_sec].append(
72
+ {"chat_id": str(chat_id), "message": remind_message, "user_id": user_id}
73
+ )
74
+
75
+
76
+ def rem_remind(chat_id, time_sec, remind_message, user_id):
77
+ with INSERTION_LOCK:
78
+ reminds = SESSION.query(Reminds).get((str(chat_id), time_sec))
79
+ if reminds:
80
+ SESSION.delete(reminds)
81
+ SESSION.commit()
82
+ REMINDERS[time_sec].remove(
83
+ {"chat_id": str(chat_id), "message": remind_message, "user_id": user_id}
84
+ )
85
+ return True
86
+ SESSION.close()
87
+ return False
88
+
89
+
90
+ def get_remind_in_chat(chat_id, timestamp):
91
+ return (
92
+ SESSION.query(Reminds)
93
+ .filter(Reminds.chat_id == str(chat_id), Reminds.time_seconds == timestamp)
94
+ .first()
95
+ )
96
+
97
+
98
+ def num_reminds_in_chat(chat_id):
99
+ return SESSION.query(Reminds).filter(Reminds.chat_id == str(chat_id)).count()
100
+
101
+
102
+ def get_reminds_in_chat(chat_id):
103
+ try:
104
+ return (
105
+ SESSION.query(Reminds)
106
+ .filter(Reminds.chat_id == str(chat_id))
107
+ .order_by(Reminds.time_seconds.asc())
108
+ .all()
109
+ )
110
+ finally:
111
+ SESSION.close()
112
+
113
+
114
+ def __get_all_reminds():
115
+ try:
116
+ chats = SESSION.query(Reminds).all()
117
+ for chat in chats:
118
+ if (chat.time_seconds <= round(time.time())) or chat.user_id == 0:
119
+ try:
120
+ rem_remind(
121
+ chat.chat_id,
122
+ chat.time_seconds,
123
+ chat.remind_message,
124
+ chat.user_id,
125
+ )
126
+ except:
127
+ pass
128
+ continue
129
+ REMINDERS[chat.time_seconds] = [
130
+ {
131
+ "chat_id": chat.chat_id,
132
+ "message": chat.remind_message,
133
+ "user_id": chat.user_id,
134
+ }
135
+ ]
136
+ finally:
137
+ SESSION.close()
138
+
139
+
140
+ __get_all_reminds()
Database/sql/reporting_sql.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Arsh
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
+ import threading
26
+ from typing import Union
27
+
28
+ from sqlalchemy import BigInteger, Boolean, Column, String
29
+
30
+ from Database.sql import BASE, SESSION
31
+
32
+
33
+ class ReportingUserSettings(BASE):
34
+ __tablename__ = "user_report_settings"
35
+ user_id = Column(BigInteger, primary_key=True)
36
+ should_report = Column(Boolean, default=True)
37
+
38
+ def __init__(self, user_id):
39
+ self.user_id = user_id
40
+
41
+ def __repr__(self):
42
+ return "<ᴜsᴇʀ ʀᴇᴘᴏʀᴛ sᴇᴛᴛɪɴɢs ({})>".format(self.user_id)
43
+
44
+
45
+ class ReportingChatSettings(BASE):
46
+ __tablename__ = "chat_report_settings"
47
+ chat_id = Column(String(14), primary_key=True)
48
+ should_report = Column(Boolean, default=True)
49
+
50
+ def __init__(self, chat_id):
51
+ self.chat_id = str(chat_id)
52
+
53
+ def __repr__(self):
54
+ return "<ᴄʜᴀᴛ ʀᴇᴘᴏʀᴛ sᴇᴛᴛɪɴɢs ({})>".format(self.chat_id)
55
+
56
+
57
+ ReportingUserSettings.__table__.create(checkfirst=True)
58
+ ReportingChatSettings.__table__.create(checkfirst=True)
59
+
60
+ CHAT_LOCK = threading.RLock()
61
+ USER_LOCK = threading.RLock()
62
+
63
+
64
+ def chat_should_report(chat_id: Union[str, int]) -> bool:
65
+ try:
66
+ chat_setting = SESSION.query(ReportingChatSettings).get(str(chat_id))
67
+ if chat_setting:
68
+ return chat_setting.should_report
69
+ return False
70
+ finally:
71
+ SESSION.close()
72
+
73
+
74
+ def user_should_report(user_id: int) -> bool:
75
+ try:
76
+ user_setting = SESSION.query(ReportingUserSettings).get(user_id)
77
+ if user_setting:
78
+ return user_setting.should_report
79
+ return True
80
+ finally:
81
+ SESSION.close()
82
+
83
+
84
+ def set_chat_setting(chat_id: Union[int, str], setting: bool):
85
+ with CHAT_LOCK:
86
+ chat_setting = SESSION.query(ReportingChatSettings).get(str(chat_id))
87
+ if not chat_setting:
88
+ chat_setting = ReportingChatSettings(chat_id)
89
+
90
+ chat_setting.should_report = setting
91
+ SESSION.add(chat_setting)
92
+ SESSION.commit()
93
+
94
+
95
+ def set_user_setting(user_id: int, setting: bool):
96
+ with USER_LOCK:
97
+ user_setting = SESSION.query(ReportingUserSettings).get(user_id)
98
+ if not user_setting:
99
+ user_setting = ReportingUserSettings(user_id)
100
+
101
+ user_setting.should_report = setting
102
+ SESSION.add(user_setting)
103
+ SESSION.commit()
104
+
105
+
106
+ def migrate_chat(old_chat_id, new_chat_id):
107
+ with CHAT_LOCK:
108
+ chat_notes = (
109
+ SESSION.query(ReportingChatSettings)
110
+ .filter(ReportingChatSettings.chat_id == str(old_chat_id))
111
+ .all()
112
+ )
113
+ for note in chat_notes:
114
+ note.chat_id = str(new_chat_id)
115
+ SESSION.commit()
Database/sql/userinfo_sql.py CHANGED
@@ -1,3 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
 
3
  from sqlalchemy import BigInteger, Column, UnicodeText
@@ -15,7 +39,7 @@ class UserInfo(BASE):
15
  self.info = info
16
 
17
  def __repr__(self):
18
- return "<User info %d>" % self.user_id
19
 
20
 
21
  class UserBio(BASE):
@@ -28,7 +52,7 @@ class UserBio(BASE):
28
  self.bio = bio
29
 
30
  def __repr__(self):
31
- return "<User info %d>" % self.user_id
32
 
33
 
34
  UserInfo.__table__.create(checkfirst=True)
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏᴏ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import threading
26
 
27
  from sqlalchemy import BigInteger, Column, UnicodeText
 
39
  self.info = info
40
 
41
  def __repr__(self):
42
+ return "<ᴜsᴇʀ ɪɴғᴏ %d>" % self.user_id
43
 
44
 
45
  class UserBio(BASE):
 
52
  self.bio = bio
53
 
54
  def __repr__(self):
55
+ return "<ᴜsᴇʀ ɪɴғᴏ %d>" % self.user_id
56
 
57
 
58
  UserInfo.__table__.create(checkfirst=True)
Database/sql/users_sql.py CHANGED
@@ -1,10 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
 
3
  from sqlalchemy import (
4
  BigInteger,
5
  Column,
6
  ForeignKey,
7
- Integer,
8
  String,
9
  UnicodeText,
10
  UniqueConstraint,
@@ -25,7 +48,7 @@ class Users(BASE):
25
  self.username = username
26
 
27
  def __repr__(self):
28
- return "<User {} ({})>".format(self.username, self.user_id)
29
 
30
 
31
  class Chats(BASE):
@@ -38,12 +61,12 @@ class Chats(BASE):
38
  self.chat_name = chat_name
39
 
40
  def __repr__(self):
41
- return "<Chat {} ({})>".format(self.chat_name, self.chat_id)
42
 
43
 
44
  class ChatMembers(BASE):
45
  __tablename__ = "chat_members"
46
- priv_chat_id = Column(Integer, primary_key=True)
47
  # NOTE: Use dual primary key instead of private primary key?
48
  chat = Column(
49
  String(14),
@@ -62,7 +85,7 @@ class ChatMembers(BASE):
62
  self.user = user
63
 
64
  def __repr__(self):
65
- return "<Chat user {} ({}) in chat {} ({})>".format(
66
  self.user.username,
67
  self.user.user_id,
68
  self.chat.chat_name,
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import threading
26
 
27
  from sqlalchemy import (
28
  BigInteger,
29
  Column,
30
  ForeignKey,
 
31
  String,
32
  UnicodeText,
33
  UniqueConstraint,
 
48
  self.username = username
49
 
50
  def __repr__(self):
51
+ return "<ᴜsᴇʀ {} ({})>".format(self.username, self.user_id)
52
 
53
 
54
  class Chats(BASE):
 
61
  self.chat_name = chat_name
62
 
63
  def __repr__(self):
64
+ return "<ᴄʜᴀᴛ {} ({})>".format(self.chat_name, self.chat_id)
65
 
66
 
67
  class ChatMembers(BASE):
68
  __tablename__ = "chat_members"
69
+ priv_chat_id = Column(BigInteger, primary_key=True)
70
  # NOTE: Use dual primary key instead of private primary key?
71
  chat = Column(
72
  String(14),
 
85
  self.user = user
86
 
87
  def __repr__(self):
88
+ return "<ᴄʜᴀᴛ ᴜsᴇʀ {} ({}) ɪɴ ᴄʜᴀᴛ {} ({})>".format(
89
  self.user.username,
90
  self.user.user_id,
91
  self.chat.chat_name,
Database/sql/warns_sql.py CHANGED
@@ -1,15 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import threading
2
 
3
- from sqlalchemy import (
4
- BigInteger,
5
- Boolean,
6
- Column,
7
- Integer,
8
- String,
9
- UnicodeText,
10
- distinct,
11
- func,
12
- )
13
  from sqlalchemy.dialects import postgresql
14
 
15
  from Database.sql import BASE, SESSION
@@ -20,7 +35,7 @@ class Warns(BASE):
20
 
21
  user_id = Column(BigInteger, primary_key=True)
22
  chat_id = Column(String(14), primary_key=True)
23
- num_warns = Column(Integer, default=0)
24
  reasons = Column(postgresql.ARRAY(UnicodeText))
25
 
26
  def __init__(self, user_id, chat_id):
@@ -30,7 +45,7 @@ class Warns(BASE):
30
  self.reasons = []
31
 
32
  def __repr__(self):
33
- return "<{} warns for {} in {} for reasons {}>".format(
34
  self.num_warns,
35
  self.user_id,
36
  self.chat_id,
@@ -50,7 +65,7 @@ class WarnFilters(BASE):
50
  self.reply = reply
51
 
52
  def __repr__(self):
53
- return "<Permissions for %s>" % self.chat_id
54
 
55
  def __eq__(self, other):
56
  return bool(
@@ -63,7 +78,7 @@ class WarnFilters(BASE):
63
  class WarnSettings(BASE):
64
  __tablename__ = "warn_settings"
65
  chat_id = Column(String(14), primary_key=True)
66
- warn_limit = Column(Integer, default=3)
67
  soft_warn = Column(Boolean, default=False)
68
 
69
  def __init__(self, chat_id, warn_limit=3, soft_warn=False):
@@ -72,7 +87,7 @@ class WarnSettings(BASE):
72
  self.soft_warn = soft_warn
73
 
74
  def __repr__(self):
75
- return "<{} has {} possible warns.>".format(self.chat_id, self.warn_limit)
76
 
77
 
78
  Warns.__table__.create(checkfirst=True)
@@ -224,8 +239,7 @@ def get_warn_setting(chat_id):
224
  setting = SESSION.query(WarnSettings).get(str(chat_id))
225
  if setting:
226
  return setting.warn_limit, setting.soft_warn
227
- else:
228
- return 3, False
229
 
230
  finally:
231
  SESSION.close()
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import threading
26
 
27
+ from sqlalchemy import BigInteger, Boolean, Column, String, UnicodeText, distinct, func
 
 
 
 
 
 
 
 
 
28
  from sqlalchemy.dialects import postgresql
29
 
30
  from Database.sql import BASE, SESSION
 
35
 
36
  user_id = Column(BigInteger, primary_key=True)
37
  chat_id = Column(String(14), primary_key=True)
38
+ num_warns = Column(BigInteger, default=0)
39
  reasons = Column(postgresql.ARRAY(UnicodeText))
40
 
41
  def __init__(self, user_id, chat_id):
 
45
  self.reasons = []
46
 
47
  def __repr__(self):
48
+ return "<{} ᴡᴀʀɴs ғᴏʀ {} ɪɴ {} ғᴏʀ ʀᴇᴀsᴏɴs {}>".format(
49
  self.num_warns,
50
  self.user_id,
51
  self.chat_id,
 
65
  self.reply = reply
66
 
67
  def __repr__(self):
68
+ return "<ᴘᴇʀᴍɪssɪᴏɴs ғᴏʀ %s>" % self.chat_id
69
 
70
  def __eq__(self, other):
71
  return bool(
 
78
  class WarnSettings(BASE):
79
  __tablename__ = "warn_settings"
80
  chat_id = Column(String(14), primary_key=True)
81
+ warn_limit = Column(BigInteger, default=3)
82
  soft_warn = Column(Boolean, default=False)
83
 
84
  def __init__(self, chat_id, warn_limit=3, soft_warn=False):
 
87
  self.soft_warn = soft_warn
88
 
89
  def __repr__(self):
90
+ return "<{} ʜᴀs {} ᴘᴏssɪʙʟᴇ ᴡᴀʀɴs.>".format(self.chat_id, self.warn_limit)
91
 
92
 
93
  Warns.__table__.create(checkfirst=True)
 
239
  setting = SESSION.query(WarnSettings).get(str(chat_id))
240
  if setting:
241
  return setting.warn_limit, setting.soft_warn
242
+ return 3, False
 
243
 
244
  finally:
245
  SESSION.close()
Database/sql/welcome_sql.py CHANGED
@@ -1,3 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import random
2
  import threading
3
  from typing import Union
@@ -7,20 +31,19 @@ from sqlalchemy import BigInteger, Boolean, Column, Integer, String, UnicodeText
7
  from Database.sql import BASE, SESSION
8
  from Mikobot.plugins.helper_funcs.msg_types import Types
9
 
10
- DEFAULT_WELCOME = "Hey {first}, how are you?"
11
- DEFAULT_GOODBYE = "Nice knowing you!"
12
 
13
  DEFAULT_WELCOME_MESSAGES = [
14
- "{first} is here!", # Discord welcome messages copied
15
- "Ready player {first}",
16
- "Welcome bro {first}",
17
  ]
18
 
19
  DEFAULT_GOODBYE_MESSAGES = [
20
- "{first} will be missed.",
21
- "{first} when back ?",
22
  ]
23
- # Line 111 to 152 are references from https://bindingofisaac.fandom.com/wiki/Fortune_Telling_Machine
24
 
25
 
26
  class Welcome(BASE):
@@ -31,8 +54,7 @@ class Welcome(BASE):
31
  custom_content = Column(UnicodeText, default=None)
32
 
33
  custom_welcome = Column(
34
- UnicodeText,
35
- default=random.choice(DEFAULT_WELCOME_MESSAGES),
36
  )
37
  welcome_type = Column(Integer, default=Types.TEXT.value)
38
 
@@ -47,9 +69,8 @@ class Welcome(BASE):
47
  self.should_goodbye = should_goodbye
48
 
49
  def __repr__(self):
50
- return "<Chat {} should Welcome new users: {}>".format(
51
- self.chat_id,
52
- self.should_welcome,
53
  )
54
 
55
 
@@ -114,7 +135,23 @@ class CleanServiceSetting(BASE):
114
  self.chat_id = str(chat_id)
115
 
116
  def __repr__(self):
117
- return "<Chat used clean service ({})>".format(self.chat_id)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
 
120
  Welcome.__table__.create(checkfirst=True)
@@ -123,12 +160,14 @@ GoodbyeButtons.__table__.create(checkfirst=True)
123
  WelcomeMute.__table__.create(checkfirst=True)
124
  WelcomeMuteUsers.__table__.create(checkfirst=True)
125
  CleanServiceSetting.__table__.create(checkfirst=True)
 
126
 
127
  INSERTION_LOCK = threading.RLock()
128
  WELC_BTN_LOCK = threading.RLock()
129
  LEAVE_BTN_LOCK = threading.RLock()
130
  WM_LOCK = threading.RLock()
131
  CS_LOCK = threading.RLock()
 
132
 
133
 
134
  def welcome_mutes(chat_id):
@@ -260,11 +299,7 @@ def set_gdbye_preference(chat_id, should_goodbye):
260
 
261
 
262
  def set_custom_welcome(
263
- chat_id,
264
- custom_content,
265
- custom_welcome,
266
- welcome_type,
267
- buttons=None,
268
  ):
269
  if buttons is None:
270
  buttons = []
@@ -426,3 +461,47 @@ def migrate_chat(old_chat_id, new_chat_id):
426
  btn.chat_id = str(new_chat_id)
427
 
428
  SESSION.commit()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ MIT License
3
+
4
+ Copyright (c) 2022 Aʙɪsʜɴᴏɪ
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
23
+ """
24
+
25
  import random
26
  import threading
27
  from typing import Union
 
31
  from Database.sql import BASE, SESSION
32
  from Mikobot.plugins.helper_funcs.msg_types import Types
33
 
34
+ DEFAULT_WELCOME = "ʜᴇʏ {first}, ʜᴏᴡ ᴀʀᴇ ʏᴏᴜ?"
35
+ DEFAULT_GOODBYE = "ɴɪᴄᴇ ᴋɴᴏᴡɪɴɢ ʏᴀ!"
36
 
37
  DEFAULT_WELCOME_MESSAGES = [
38
+ "{first} ɪs ʜᴇʀᴇ!", # Discord welcome messages copied
39
+ "ʀᴇᴀᴅʏ ᴘʟᴀʏᴇʀ {first}",
40
+ "ᴡᴇʟᴄᴏᴍᴇ ʙʀᴏ {first}",
41
  ]
42
 
43
  DEFAULT_GOODBYE_MESSAGES = [
44
+ "{first} ᴡɪʟʟ ʙᴇ ᴍɪssᴇᴅ.",
45
+ "{first} ᴡʜᴇɴ ʙᴀᴄᴋ ?.",
46
  ]
 
47
 
48
 
49
  class Welcome(BASE):
 
54
  custom_content = Column(UnicodeText, default=None)
55
 
56
  custom_welcome = Column(
57
+ UnicodeText, default=random.choice(DEFAULT_WELCOME_MESSAGES)
 
58
  )
59
  welcome_type = Column(Integer, default=Types.TEXT.value)
60
 
 
69
  self.should_goodbye = should_goodbye
70
 
71
  def __repr__(self):
72
+ return "<ᴄʜᴀᴛ {} sʜᴏᴜʟᴅ sʜᴏᴜʟᴅ ɴᴇᴡ ᴜsᴇʀs: {}>".format(
73
+ self.chat_id, self.should_welcome
 
74
  )
75
 
76
 
 
135
  self.chat_id = str(chat_id)
136
 
137
  def __repr__(self):
138
+ return "<ᴄʜᴀᴛ ᴜsᴇᴅ ᴄʟᴇᴀɴ sᴇʀᴠɪᴄᴇ ({})>".format(self.chat_id)
139
+
140
+
141
+ class RaidMode(BASE):
142
+ __tablename__ = "raid_mode"
143
+ chat_id = Column(String(14), primary_key=True)
144
+ status = Column(Boolean, default=False)
145
+ time = Column(Integer, default=21600)
146
+ acttime = Column(Integer, default=3600)
147
+ # permanent = Column(Boolean, default=False)
148
+
149
+ def __init__(self, chat_id, status, time, acttime):
150
+ self.chat_id = str(chat_id)
151
+ self.status = status
152
+ self.time = time
153
+ self.acttime = acttime
154
+ # self.permanent = permanent
155
 
156
 
157
  Welcome.__table__.create(checkfirst=True)
 
160
  WelcomeMute.__table__.create(checkfirst=True)
161
  WelcomeMuteUsers.__table__.create(checkfirst=True)
162
  CleanServiceSetting.__table__.create(checkfirst=True)
163
+ RaidMode.__table__.create(checkfirst=True)
164
 
165
  INSERTION_LOCK = threading.RLock()
166
  WELC_BTN_LOCK = threading.RLock()
167
  LEAVE_BTN_LOCK = threading.RLock()
168
  WM_LOCK = threading.RLock()
169
  CS_LOCK = threading.RLock()
170
+ RAID_LOCK = threading.RLock()
171
 
172
 
173
  def welcome_mutes(chat_id):
 
299
 
300
 
301
  def set_custom_welcome(
302
+ chat_id, custom_content, custom_welcome, welcome_type, buttons=None
 
 
 
 
303
  ):
304
  if buttons is None:
305
  buttons = []
 
461
  btn.chat_id = str(new_chat_id)
462
 
463
  SESSION.commit()
464
+
465
+
466
+ def getRaidStatus(chat_id):
467
+ try:
468
+ if stat := SESSION.query(RaidMode).get(str(chat_id)):
469
+ return stat.status, stat.time, stat.acttime
470
+ return False, 21600, 3600 # default
471
+ finally:
472
+ SESSION.close()
473
+
474
+
475
+ def setRaidStatus(chat_id, status, time=21600, acttime=3600):
476
+ with RAID_LOCK:
477
+ if prevObj := SESSION.query(RaidMode).get(str(chat_id)):
478
+ SESSION.delete(prevObj)
479
+ newObj = RaidMode(str(chat_id), status, time, acttime)
480
+ SESSION.add(newObj)
481
+ SESSION.commit()
482
+
483
+
484
+ def toggleRaidStatus(chat_id):
485
+ newObj = True
486
+ with RAID_LOCK:
487
+ prevObj = SESSION.query(RaidMode).get(str(chat_id))
488
+ if prevObj:
489
+ newObj = not prevObj.status
490
+ stat = RaidMode(
491
+ str(chat_id), newObj, prevObj.time or 21600, prevObj.acttime or 3600
492
+ )
493
+ SESSION.add(stat)
494
+ SESSION.commit()
495
+ return newObj
496
+
497
+
498
+ def _ResetRaidOnRestart():
499
+ with RAID_LOCK:
500
+ raid = SESSION.query(RaidMode).all()
501
+ for r in raid:
502
+ r.status = False
503
+ SESSION.commit()
504
+
505
+
506
+ # it uses a cron job to turn off so if the bot restarts and there is a pending raid disable job then raid will stay on
507
+ _ResetRaidOnRestart()
Dockerfile CHANGED
@@ -9,4 +9,4 @@ RUN pip3 install --upgrade pip setuptools
9
 
10
  RUN pip install -U -r requirements.txt
11
 
12
- CMD python3 -m Mikobot
 
9
 
10
  RUN pip install -U -r requirements.txt
11
 
12
+ CMD python3 -m Mikobot
Infamous/karma.py CHANGED
@@ -44,11 +44,10 @@ START_BTN = [
44
  ),
45
  ],
46
  [
47
- InlineKeyboardButton(text="HELP", callback_data="help_back"),
48
  ],
49
  [
50
  InlineKeyboardButton(text="DETAILS", callback_data="Miko_"),
51
- InlineKeyboardButton(text="AI", callback_data="ai_handler"),
52
  InlineKeyboardButton(text="SOURCE", callback_data="git_source"),
53
  ],
54
  [
@@ -83,7 +82,7 @@ ALIVE_BTN = [
83
  ]
84
 
85
  HELP_STRINGS = """
86
- 🫧 *Yae-Miko* 🫧
87
 
88
  ☉ *Here, you will find a list of all the available commands.*
89
 
 
44
  ),
45
  ],
46
  [
47
+ InlineKeyboardButton(text="HELP", callback_data="extra_command_handler"),
48
  ],
49
  [
50
  InlineKeyboardButton(text="DETAILS", callback_data="Miko_"),
 
51
  InlineKeyboardButton(text="SOURCE", callback_data="git_source"),
52
  ],
53
  [
 
82
  ]
83
 
84
  HELP_STRINGS = """
85
+ 🫧 *Yae-Miko* 🫧 [ㅤ](https://telegra.ph/file/b05535884267a19ee5c93.jpg)
86
 
87
  ☉ *Here, you will find a list of all the available commands.*
88
 
Mikobot/__init__.py CHANGED
@@ -17,7 +17,7 @@ from telegram import Bot, InlineKeyboardButton, InlineKeyboardMarkup, Update
17
  from telegram.constants import ParseMode
18
  from telegram.ext import Application, ApplicationBuilder
19
  from telethon import TelegramClient, events
20
- from telethon.sessions import MemorySession
21
 
22
  # <=======================================================================================================>
23
 
@@ -120,12 +120,12 @@ else:
120
  ALLOW_EXCL = Config.ALLOW_EXCL
121
  DB_NAME = Config.DB_NAME
122
  DB_URI = Config.DATABASE_URL
 
123
  MESSAGE_DUMP = Config.MESSAGE_DUMP
124
  SUPPORT_ID = Config.SUPPORT_ID
125
  DEL_CMDS = Config.DEL_CMDS
126
  EVENT_LOGS = Config.EVENT_LOGS
127
  INFOPIC = Config.INFOPIC
128
- BAN_STICKER = Config.BAN_STICKER
129
  LOAD = Config.LOAD
130
  MONGO_DB_URI = Config.MONGO_DB_URI
131
  NO_LOAD = Config.NO_LOAD
@@ -230,7 +230,7 @@ loop.run_until_complete(
230
  # <=============================================== CLIENT SETUP ========================================================>
231
  # Create the Mikobot and TelegramClient instances
232
  app = Client("Mikobot", api_id=API_ID, api_hash=API_HASH, bot_token=TOKEN)
233
- tbot = TelegramClient(MemorySession(), API_ID, API_HASH)
234
  # <=======================================================================================================>
235
 
236
  # <=============================================== GETTING BOT INFO ========================================================>
 
17
  from telegram.constants import ParseMode
18
  from telegram.ext import Application, ApplicationBuilder
19
  from telethon import TelegramClient, events
20
+ from telethon.sessions import MemorySession, StringSession
21
 
22
  # <=======================================================================================================>
23
 
 
120
  ALLOW_EXCL = Config.ALLOW_EXCL
121
  DB_NAME = Config.DB_NAME
122
  DB_URI = Config.DATABASE_URL
123
+ BAN_STICKER = Config.BAN_STICKER
124
  MESSAGE_DUMP = Config.MESSAGE_DUMP
125
  SUPPORT_ID = Config.SUPPORT_ID
126
  DEL_CMDS = Config.DEL_CMDS
127
  EVENT_LOGS = Config.EVENT_LOGS
128
  INFOPIC = Config.INFOPIC
 
129
  LOAD = Config.LOAD
130
  MONGO_DB_URI = Config.MONGO_DB_URI
131
  NO_LOAD = Config.NO_LOAD
 
230
  # <=============================================== CLIENT SETUP ========================================================>
231
  # Create the Mikobot and TelegramClient instances
232
  app = Client("Mikobot", api_id=API_ID, api_hash=API_HASH, bot_token=TOKEN)
233
+ tbot = TelegramClient("Yaebot", API_ID, API_HASH)
234
  # <=======================================================================================================>
235
 
236
  # <=============================================== GETTING BOT INFO ========================================================>
Mikobot/__main__.py CHANGED
@@ -36,7 +36,6 @@ from telegram.ext import (
36
  )
37
  from telegram.helpers import escape_markdown
38
 
39
- import Database.sql.users_sql as sql
40
  from Infamous.karma import *
41
  from Mikobot import (
42
  BOT_NAME,
@@ -64,65 +63,6 @@ TELETHON_VERSION = telethon.__version__
64
 
65
 
66
  # <============================================== FUNCTIONS =========================================================>
67
- async def ai_handler_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
68
- query = update.callback_query
69
- if query.data == "ai_handler":
70
- await query.answer()
71
- await query.message.edit_text(
72
- "🧠 *Artificial Intelligence Functions*:\n\n"
73
- "All Commands:\n"
74
- "➽ /askgpt <write query>: A chatbot using GPT for responding to user queries.\n\n"
75
- "➽ /palm <write prompt>: Performs a Palm search using a chatbot.\n\n"
76
- "➽ /upscale <reply to image>: Upscales your image quality.",
77
- parse_mode=ParseMode.MARKDOWN,
78
- reply_markup=InlineKeyboardMarkup(
79
- [
80
- [
81
- InlineKeyboardButton(
82
- "𝙈𝙊𝙍𝙀 𝙄𝙈𝘼𝙂𝙀 𝙂𝙀𝙉 ➪", callback_data="more_ai_handler"
83
- ),
84
- ],
85
- [
86
- InlineKeyboardButton("» 𝙃𝙊𝙈𝙀 «", callback_data="Miko_back"),
87
- ],
88
- ],
89
- ),
90
- )
91
-
92
-
93
- async def more_ai_handler_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
94
- query = update.callback_query
95
- if query.data == "more_ai_handler":
96
- await query.answer()
97
- await query.message.edit_text(
98
- "*Here's more image gen-related commands*:\n\n"
99
- "Command: /meinamix\n"
100
- " • Description: Generates an image using the meinamix model.\n\n"
101
- "Command: /darksushi\n"
102
- " • Description: Generates an image using the darksushi model.\n\n"
103
- "Command: /meinahentai\n"
104
- " • Description: Generates an image using the meinahentai model.\n\n"
105
- "Command: /darksushimix\n"
106
- " • Description: Generates an image using the darksushimix model.\n\n"
107
- "Command: /anylora\n"
108
- " • Description: Generates an image using the anylora model.\n\n"
109
- "Command: /cetsumix\n"
110
- " • Description: Generates an image using the cetus-mix model.\n\n"
111
- "Command: /darkv2\n"
112
- " • Description: Generates an image using the darkv2 model.\n\n"
113
- "Command: /creative\n"
114
- " • Description: Generates an image using the creative model.",
115
- parse_mode=ParseMode.MARKDOWN,
116
- reply_markup=InlineKeyboardMarkup(
117
- [
118
- [
119
- InlineKeyboardButton("⇦ 𝘽𝘼𝘾𝙆", callback_data="ai_handler"),
120
- ],
121
- ],
122
- ),
123
- )
124
-
125
-
126
  def get_readable_time(seconds: int) -> str:
127
  count = 0
128
  ping_time = ""
@@ -269,6 +209,270 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
269
  )
270
 
271
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
272
  async def error_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
273
  """Log the error and send a telegram message to notify the developer."""
274
  # Log the error before we do anything else, so we can see it even if something breaks.
@@ -455,8 +659,6 @@ async def Miko_about_callback(update: Update, context: ContextTypes.DEFAULT_TYPE
455
  f"➲ <b>Ai integration.</b>"
456
  f"\n➲ <b>Advance management capability.</b>"
457
  f"\n➲ <b>Anime bot functionality.</b>"
458
- f"\n\n<b>USERS</b> » {sql.num_users()}"
459
- f"\n<b>CHATS</b> » {sql.num_chats()}"
460
  f"\n\n<b>Click on the buttons below for getting help and info about</b> {BOT_NAME}."
461
  )
462
  await query.message.edit_text(
@@ -540,7 +742,7 @@ async def get_help(update: Update, context: ContextTypes.DEFAULT_TYPE):
540
  )
541
  return
542
  await update.effective_message.reply_text(
543
- "» Choose an option for getting help.",
544
  reply_markup=InlineKeyboardMarkup(
545
  [
546
  [
@@ -554,11 +756,12 @@ async def get_help(update: Update, context: ContextTypes.DEFAULT_TYPE):
554
  [
555
  InlineKeyboardButton(
556
  text="OPEN HERE",
557
- callback_data="help_back",
558
  )
559
  ],
560
  ]
561
  ),
 
562
  )
563
  return
564
 
@@ -763,7 +966,7 @@ async def migrate_chats(update: Update, context: ContextTypes.DEFAULT_TYPE):
763
  def main():
764
  function(CommandHandler("start", start))
765
 
766
- function(CommandHandler("help", get_help))
767
  function(CallbackQueryHandler(help_button, pattern=r"help_.*"))
768
 
769
  function(CommandHandler("settings", get_settings))
@@ -773,9 +976,26 @@ def main():
773
  function(CallbackQueryHandler(Miko_about_callback, pattern=r"Miko_"))
774
  function(CallbackQueryHandler(gitsource_callback, pattern=r"git_source"))
775
  function(CallbackQueryHandler(stats_back, pattern=r"insider_"))
 
776
  function(CallbackQueryHandler(ai_handler_callback, pattern=r"ai_handler"))
777
  function(CallbackQueryHandler(more_ai_handler_callback, pattern=r"more_ai_handler"))
778
- function(MessageHandler(filters.StatusUpdate.MIGRATE, migrate_chats))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
779
 
780
  dispatcher.add_error_handler(error_callback)
781
 
 
36
  )
37
  from telegram.helpers import escape_markdown
38
 
 
39
  from Infamous.karma import *
40
  from Mikobot import (
41
  BOT_NAME,
 
63
 
64
 
65
  # <============================================== FUNCTIONS =========================================================>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  def get_readable_time(seconds: int) -> str:
67
  count = 0
68
  ping_time = ""
 
209
  )
210
 
211
 
212
+ async def extra_command_handlered(update: Update, context: ContextTypes.DEFAULT_TYPE):
213
+
214
+ keyboard = [
215
+ [
216
+ InlineKeyboardButton("MANAGEMENT", callback_data="help_back"),
217
+ InlineKeyboardButton("AI", callback_data="ai_command_handler"),
218
+ ],
219
+ [
220
+ InlineKeyboardButton("ANIME", callback_data="anime_command_handler"),
221
+ InlineKeyboardButton("GENSHIN", callback_data="genshin_command_handler"),
222
+ ],
223
+ [
224
+ InlineKeyboardButton("HOME", callback_data="Miko_back"),
225
+ ],
226
+ ]
227
+
228
+ reply_markup = InlineKeyboardMarkup(keyboard)
229
+
230
+ await update.message.reply_text(
231
+ "𝙎𝙚𝙡𝙚𝙘𝙩 𝙩𝙝𝙚 [𝙨𝙚𝙘𝙩𝙞𝙤𝙣](https://telegra.ph/file/8c092f4e9d303f9497c83.jpg) 𝙩𝙝𝙖𝙩 𝙮𝙤𝙪 𝙬𝙖𝙣𝙩 𝙩𝙤 𝙤𝙥𝙚𝙣",
232
+ reply_markup=reply_markup,
233
+ parse_mode="Markdown",
234
+ )
235
+
236
+
237
+ async def extra_command_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
238
+ query = update.callback_query
239
+ if query.data == "extra_command_handler":
240
+ await query.answer() # Use 'await' for asynchronous calls
241
+ await query.message.edit_text(
242
+ "𝙎𝙚𝙡𝙚𝙘𝙩 𝙩𝙝𝙚 [𝙨𝙚𝙘𝙩𝙞𝙤𝙣](https://telegra.ph/file/8c092f4e9d303f9497c83.jpg) 𝙩𝙝𝙖𝙩 𝙮𝙤𝙪 𝙬𝙖𝙣𝙩 𝙩𝙤 𝙤𝙥𝙚𝙣",
243
+ reply_markup=InlineKeyboardMarkup(
244
+ [
245
+ [
246
+ InlineKeyboardButton("MANAGEMENT", callback_data="help_back"),
247
+ InlineKeyboardButton("AI", callback_data="ai_command_handler"),
248
+ ],
249
+ [
250
+ InlineKeyboardButton(
251
+ "ANIME", callback_data="anime_command_handler"
252
+ ),
253
+ InlineKeyboardButton(
254
+ "GENSHIN", callback_data="genshin_command_handler"
255
+ ),
256
+ ],
257
+ [
258
+ InlineKeyboardButton("HOME", callback_data="Miko_back"),
259
+ ],
260
+ ]
261
+ ),
262
+ parse_mode="Markdown", # Added this line to explicitly specify Markdown parsing
263
+ )
264
+
265
+
266
+ async def ai_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
267
+ keyboard = [
268
+ [
269
+ InlineKeyboardButton("AI", callback_data="ai_handler"),
270
+ InlineKeyboardButton("IMAGEGEN", callback_data="more_aihandlered"),
271
+ ],
272
+ ]
273
+ reply_markup = InlineKeyboardMarkup(keyboard)
274
+
275
+ await update.message.reply_text(
276
+ "🧠 *Here are the options for* [𝗬𝗔𝗘 𝗠𝗜𝗞𝗢](https://telegra.ph/file/ed2d9c3693cacc9b0464e.jpg):",
277
+ reply_markup=reply_markup,
278
+ parse_mode="Markdown",
279
+ )
280
+
281
+
282
+ async def ai_command_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
283
+ query = update.callback_query
284
+ if query.data == "ai_command_handler":
285
+ await query.answer()
286
+ await query.message.edit_text(
287
+ "🧠 *Here are the options for* [𝗬𝗔𝗘 𝗠𝗜𝗞𝗢](https://telegra.ph/file/ed2d9c3693cacc9b0464e.jpg):",
288
+ reply_markup=InlineKeyboardMarkup(
289
+ [
290
+ [
291
+ InlineKeyboardButton("AI", callback_data="ai_handler"),
292
+ InlineKeyboardButton(
293
+ "IMAGEGEN", callback_data="more_aihandlered"
294
+ ),
295
+ ],
296
+ [
297
+ InlineKeyboardButton(
298
+ "» 𝘽𝘼𝘾𝙆 «", callback_data="extra_command_handler"
299
+ ),
300
+ ],
301
+ ]
302
+ ),
303
+ parse_mode="Markdown",
304
+ )
305
+
306
+
307
+ async def ai_handler_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
308
+ query = update.callback_query
309
+ if query.data == "ai_handler":
310
+ await query.answer()
311
+ await query.message.edit_text(
312
+ "[𝗔𝗿𝘁𝗶𝗳𝗶𝗰𝗶𝗮𝗹 𝗜𝗻𝘁𝗲𝗹𝗹𝗶𝗴𝗲𝗻𝘁 𝗙𝘂𝗻𝗰𝘁𝗶𝗼𝗻𝘀](https://telegra.ph/file/01a2e0cd1b9d03808c546.jpg):\n\n"
313
+ "All Commands:\n"
314
+ "➽ /askgpt <write query>: A chatbot using GPT for responding to user queries.\n\n"
315
+ "➽ /palm <write prompt>: Performs a Palm search using a chatbot.\n\n"
316
+ "➽ /upscale <reply to image>: Upscales your image quality.",
317
+ reply_markup=InlineKeyboardMarkup(
318
+ [
319
+ [
320
+ InlineKeyboardButton(
321
+ "More Image Gen ➪", callback_data="more_ai_handler"
322
+ ),
323
+ ],
324
+ [
325
+ InlineKeyboardButton(
326
+ "⇦ BACK", callback_data="ai_command_handler"
327
+ ),
328
+ ],
329
+ ],
330
+ ),
331
+ parse_mode="Markdown",
332
+ )
333
+
334
+
335
+ async def more_ai_handler_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
336
+ query = update.callback_query
337
+ if query.data == "more_ai_handler":
338
+ await query.answer()
339
+ await query.message.edit_text(
340
+ "*Here's more image gen related commands*:\n\n"
341
+ "Command: /meinamix\n"
342
+ " • Description: Generates an image using the meinamix model.\n\n"
343
+ "Command: /darksushi\n"
344
+ " • Description: Generates an image using the darksushi model.\n\n"
345
+ "Command: /meinahentai\n"
346
+ " • Description: Generates an image using the meinahentai model.\n\n"
347
+ "Command: /darksushimix\n"
348
+ " • Description: Generates an image using the darksushimix model.\n\n"
349
+ "Command: /anylora\n"
350
+ " • Description: Generates an image using the anylora model.\n\n"
351
+ "Command: /cetsumix\n"
352
+ " • Description: Generates an image using the cetsumix model.\n\n"
353
+ "Command: /anything\n"
354
+ " • Description: Generates an image using the anything model.\n\n"
355
+ "Command: /absolute\n"
356
+ " • Description: Generates an image using the absolute model.\n\n"
357
+ "Command: /darkv2\n"
358
+ " • Description: Generates an image using the darkv2 model.\n\n"
359
+ "Command: /creative\n"
360
+ " • Description: Generates an image using the creative model.",
361
+ reply_markup=InlineKeyboardMarkup(
362
+ [
363
+ [
364
+ InlineKeyboardButton("⇦ BACK", callback_data="ai_handler"),
365
+ ],
366
+ ],
367
+ ),
368
+ )
369
+
370
+
371
+ async def more_aihandlered_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
372
+ query = update.callback_query
373
+ if query.data == "more_aihandlered":
374
+ await query.answer()
375
+ await query.message.edit_text(
376
+ "*Here's more image gen related commands*:\n\n"
377
+ "*Command*: /meinamix\n"
378
+ " • Description: Generates an image using the meinamix model.\n\n"
379
+ "*Command*: /darksushi\n"
380
+ " • Description: Generates an image using the darksushi model.\n\n"
381
+ "*Command*: /meinahentai\n"
382
+ " • Description: Generates an image using the meinahentai model.\n\n"
383
+ "*Command*: /darksushimix\n"
384
+ " • Description: Generates an image using the darksushimix model.\n\n"
385
+ "*Command*: /anylora\n"
386
+ " • Description: Generates an image using the anylora model.\n\n"
387
+ "*Command*: /cetsumix\n"
388
+ " • Description: Generates an image using the cetsumix model.\n\n"
389
+ "*Command*: /anything\n"
390
+ " • Description: Generates an image using the anything model.\n\n"
391
+ "*Command*: /absolute\n"
392
+ " • Description: Generates an image using the absolute model.\n\n"
393
+ "*Command*: /darkv2\n"
394
+ " • Description: Generates an image using the darkv2 model.\n\n"
395
+ "*Command*: /creative\n"
396
+ " • Description: Generates an image using the creative model.",
397
+ reply_markup=InlineKeyboardMarkup(
398
+ [
399
+ [
400
+ InlineKeyboardButton(
401
+ "⇦ BACK", callback_data="ai_command_handler"
402
+ ),
403
+ ],
404
+ ],
405
+ ),
406
+ )
407
+
408
+
409
+ async def anime_command_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
410
+ query = update.callback_query
411
+ if query.data == "anime_command_handler":
412
+ await query.answer()
413
+ await query.message.edit_text(
414
+ "⛩[𝗔𝗻𝗶𝗺𝗲 𝗨𝗽𝗱𝗮𝘁𝗲𝘀](https://telegra.ph//file/59d93fede8bf12fec1a51.jpg) :\n\n"
415
+ "**╔ /anime: **fetches info on single anime (includes buttons to look up for prequels and sequels)\n"
416
+ "**╠ /character: **fetches info on multiple possible characters related to query\n"
417
+ "**╠ /manga: **fetches info on multiple possible mangas related to query\n"
418
+ "**╠ /airing: **fetches info on airing data for anime\n"
419
+ "**╠ /studio: **fetches info on multiple possible studios related to query\n"
420
+ "**╠ /schedule: **fetches scheduled animes\n"
421
+ "**╠ /browse: **get popular, trending or upcoming animes\n"
422
+ "**╠ /top: **to retrieve top animes for a genre or tag\n"
423
+ "**╠ /watch: **fetches watch order for anime series\n"
424
+ "**╠ /fillers: **to get a list of anime fillers\n"
425
+ "**╠ /gettags: **get a list of available tags\n"
426
+ "**╠ /animequotes: **get random anime quotes\n"
427
+ "**╚ /getgenres: **Get list of available Genres\n\n"
428
+ "**⚙️ Group Settings:**\n"
429
+ "**╔**\n"
430
+ "**╠ /anisettings: **to toggle NSFW lock and airing notifications and other settings in groups (anime news)\n"
431
+ "**╚**",
432
+ reply_markup=InlineKeyboardMarkup(
433
+ [
434
+ [
435
+ InlineKeyboardButton("More Info", url="https://anilist.co/"),
436
+ InlineKeyboardButton(
437
+ "㊋Infamous•Hydra", url="https://t.me/Infamous_Hydra"
438
+ ),
439
+ ],
440
+ [
441
+ InlineKeyboardButton(
442
+ "» 𝘽𝘼𝘾𝙆 «", callback_data="extra_command_handler"
443
+ ),
444
+ ],
445
+ ]
446
+ ),
447
+ parse_mode="Markdown", # Added this line to explicitly specify Markdown parsing
448
+ )
449
+
450
+
451
+ async def genshin_command_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
452
+ query = update.callback_query
453
+ if query.data == "genshin_command_handler":
454
+ await query.answer()
455
+ await query.message.edit_text(
456
+ "⛩ [𝗚𝗲𝗻𝘀𝗵𝗶𝗻 𝗜𝗺𝗽𝗮𝗰𝘁](https://telegra.ph/file/cd03348a4a357624e70db.jpg) ⛩\n\n"
457
+ "*UNDER DEVELOPMENT*",
458
+ reply_markup=InlineKeyboardMarkup(
459
+ [
460
+ [
461
+ InlineKeyboardButton(
462
+ "More Info", url="https://genshin.mihoyo.com/"
463
+ ),
464
+ ],
465
+ [
466
+ InlineKeyboardButton(
467
+ "» 𝘽𝘼𝘾𝙆 «", callback_data="extra_command_handler"
468
+ ),
469
+ ],
470
+ ]
471
+ ),
472
+ parse_mode="Markdown", # Added this line to explicitly specify Markdown parsing
473
+ )
474
+
475
+
476
  async def error_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
477
  """Log the error and send a telegram message to notify the developer."""
478
  # Log the error before we do anything else, so we can see it even if something breaks.
 
659
  f"➲ <b>Ai integration.</b>"
660
  f"\n➲ <b>Advance management capability.</b>"
661
  f"\n➲ <b>Anime bot functionality.</b>"
 
 
662
  f"\n\n<b>Click on the buttons below for getting help and info about</b> {BOT_NAME}."
663
  )
664
  await query.message.edit_text(
 
742
  )
743
  return
744
  await update.effective_message.reply_text(
745
+ *Choose an option for getting* [𝗵𝗲𝗹𝗽](https://telegra.ph/file/cce9038f6a9b88eb409b5.jpg)",
746
  reply_markup=InlineKeyboardMarkup(
747
  [
748
  [
 
756
  [
757
  InlineKeyboardButton(
758
  text="OPEN HERE",
759
+ callback_data="extra_command_handler",
760
  )
761
  ],
762
  ]
763
  ),
764
+ parse_mode="Markdown", # Added this line to explicitly specify Markdown parsing
765
  )
766
  return
767
 
 
966
  def main():
967
  function(CommandHandler("start", start))
968
 
969
+ function(CommandHandler("help", extra_command_handlered))
970
  function(CallbackQueryHandler(help_button, pattern=r"help_.*"))
971
 
972
  function(CommandHandler("settings", get_settings))
 
976
  function(CallbackQueryHandler(Miko_about_callback, pattern=r"Miko_"))
977
  function(CallbackQueryHandler(gitsource_callback, pattern=r"git_source"))
978
  function(CallbackQueryHandler(stats_back, pattern=r"insider_"))
979
+ function(MessageHandler(filters.StatusUpdate.MIGRATE, migrate_chats))
980
  function(CallbackQueryHandler(ai_handler_callback, pattern=r"ai_handler"))
981
  function(CallbackQueryHandler(more_ai_handler_callback, pattern=r"more_ai_handler"))
982
+ function(CallbackQueryHandler(ai_command_callback, pattern="ai_command_handler"))
983
+ function(
984
+ CallbackQueryHandler(anime_command_callback, pattern="anime_command_handler")
985
+ )
986
+ function(
987
+ CallbackQueryHandler(more_aihandlered_callback, pattern="more_aihandlered")
988
+ )
989
+ function(
990
+ CallbackQueryHandler(extra_command_callback, pattern="extra_command_handler")
991
+ )
992
+
993
+ function(CommandHandler("ai", ai_command))
994
+ function(
995
+ CallbackQueryHandler(
996
+ genshin_command_callback, pattern="genshin_command_handler"
997
+ )
998
+ )
999
 
1000
  dispatcher.add_error_handler(error_callback)
1001
 
Mikobot/elevated_users.json ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "devs": [5907205317, 5978107653, 2093473332],
3
+ "supports": [],
4
+ "whitelists": [],
5
+ "sudos": [6864672519],
6
+ "tigers": [],
7
+ "spammers": []
8
+ }
Mikobot/plugins/afk.py CHANGED
@@ -184,6 +184,12 @@ __help__ = """
184
 
185
  » brb , !afk <reason>*:* same as the afk command - but not a command.
186
 
 
 
 
 
 
 
187
  ➠ *When marked as AFK, any mentions will be replied to with a message to say you're not available!*
188
  """
189
 
 
184
 
185
  » brb , !afk <reason>*:* same as the afk command - but not a command.
186
 
187
+ » /bye [Reason > Optional] - Tell others that you are AFK (Away From Keyboard).
188
+
189
+ » /bye [reply to media] - AFK with media.
190
+
191
+ » /byedel - Enable auto delete AFK message in group (Only for group admin). Default is **Enable**.
192
+
193
  ➠ *When marked as AFK, any mentions will be replied to with a message to say you're not available!*
194
  """
195
 
Mikobot/plugins/ai.py CHANGED
@@ -16,7 +16,7 @@ from Mikobot.state import state
16
  # <=======================================================================================================>
17
 
18
  # <================================================ CONSTANTS =====================================================>
19
- API_URL = "https://lexica.qewertyy.me/models"
20
  PALM_MODEL_ID = 0
21
  GPT_MODEL_ID = 5
22
 
@@ -103,7 +103,7 @@ async def upscale_image(update: Update, context: ContextTypes.DEFAULT_TYPE):
103
  b = base64.b64encode(f).decode("utf-8")
104
 
105
  response = await state.post(
106
- "https://lexica.qewertyy.me/upscale",
107
  data={"image_data": b},
108
  )
109
 
 
16
  # <=======================================================================================================>
17
 
18
  # <================================================ CONSTANTS =====================================================>
19
+ API_URL = "https://lexica.qewertyy.dev/models"
20
  PALM_MODEL_ID = 0
21
  GPT_MODEL_ID = 5
22
 
 
103
  b = base64.b64encode(f).decode("utf-8")
104
 
105
  response = await state.post(
106
+ "https://lexica.qewertyy.dev/upscale",
107
  data={"image_data": b},
108
  )
109
 
Mikobot/plugins/alive.py CHANGED
@@ -34,12 +34,12 @@ async def alive(_, message: Message):
34
  caption = f"""**HEY, I AM {BOT_NAME}**
35
 
36
  ━━━━━━ 🌟✿🌟 ━━━━━━
37
- ✪ **CREATOR:** [🄺🄰🅁🄼🄰](https://t.me/anime_Freakz)
38
 
39
  {library_versions_text}
40
 
41
  ➲ **PYTHON:** `{version_info[0]}.{version_info[1]}.{version_info[2]}`
42
- ➲ **BOT VERSION:** `2.0`
43
  ━━━━━━ 🌟✿🌟 ━━━━━━"""
44
 
45
  await message.reply_animation(
 
34
  caption = f"""**HEY, I AM {BOT_NAME}**
35
 
36
  ━━━━━━ 🌟✿🌟 ━━━━━━
37
+ ✪ **CREATOR:** [🄺🄰🅁🄼🄰](https://t.me/O_oKarma)
38
 
39
  {library_versions_text}
40
 
41
  ➲ **PYTHON:** `{version_info[0]}.{version_info[1]}.{version_info[2]}`
42
+ ➲ **BOT VERSION:** `2.1 Rx`
43
  ━━━━━━ 🌟✿🌟 ━━━━━━"""
44
 
45
  await message.reply_animation(
Mikobot/plugins/anime.py CHANGED
@@ -2253,11 +2253,11 @@ async def get_top_animes(gnr: str, page, user):
2253
  async def get_user_favourites(id_, user, req, page, sighs, duser=None):
2254
  vars_ = {"id": int(id_), "page": int(page)}
2255
  result = await return_json_senpai(
2256
- FAV_ANI_QUERY
2257
- if req == "ANIME"
2258
- else FAV_CHAR_QUERY
2259
- if req == "CHAR"
2260
- else FAV_MANGA_QUERY,
2261
  vars_,
2262
  auth=True,
2263
  user=int(user),
@@ -2268,9 +2268,7 @@ async def get_user_favourites(id_, user, req, page, sighs, duser=None):
2268
  msg = (
2269
  "Favourite Animes:\n\n"
2270
  if req == "ANIME"
2271
- else "Favourite Characters:\n\n"
2272
- if req == "CHAR"
2273
- else "Favourite Manga:\n\n"
2274
  )
2275
  for i in data["edges"]:
2276
  node_name = (
@@ -2373,9 +2371,7 @@ async def get_additional_info(
2373
  (
2374
  DES_INFO_QUERY
2375
  if req == "desc"
2376
- else CHA_INFO_QUERY
2377
- if req == "char"
2378
- else REL_INFO_QUERY
2379
  )
2380
  if ctgry == "ANI"
2381
  else DESC_INFO_QUERY
@@ -2817,11 +2813,11 @@ async def toggle_favourites(id_: int, media: str, user: int):
2817
  query = (
2818
  ANIME_MUTATION
2819
  if media == "ANIME" or media == "AIRING"
2820
- else CHAR_MUTATION
2821
- if media == "CHARACTER"
2822
- else MANGA_MUTATION
2823
- if media == "MANGA"
2824
- else STUDIO_MUTATION
2825
  )
2826
  k = await return_json_senpai(query=query, vars_=vars_, auth=True, user=int(user))
2827
  try:
@@ -2890,9 +2886,7 @@ async def update_anilist(id_, req, user, eid: int = None, status: str = None):
2890
  query=(
2891
  ANILIST_MUTATION
2892
  if req == "lsas"
2893
- else ANILIST_MUTATION_UP
2894
- if req == "lsus"
2895
- else ANILIST_MUTATION_DEL
2896
  ),
2897
  vars_=vars_,
2898
  auth=True,
@@ -2902,9 +2896,11 @@ async def update_anilist(id_, req, user, eid: int = None, status: str = None):
2902
  (
2903
  k["data"]["SaveMediaListEntry"]
2904
  if req == "lsas"
2905
- else k["data"]["UpdateMediaListEntries"]
2906
- if req == "lsus"
2907
- else k["data"]["DeleteMediaListEntry"]
 
 
2908
  )
2909
  return "ok"
2910
  except KeyError:
@@ -4007,32 +4003,52 @@ async def toggle_favourites_btn(client: Client, cq: CallbackQuery, cdata: dict):
4007
  )
4008
  if query[1] == "ANIME" and len(query) == 3
4009
  else (
4010
- await get_anilist(
4011
- query[3],
4012
- page=int(query[4]),
4013
- auth=True,
4014
- user=auser,
4015
- cid=gid if gid != user else None,
4016
- )
4017
- )
4018
- if query[1] == "ANIME" and len(query) != 3
4019
- else (
4020
- await get_manga(
4021
- query[3],
4022
- page=int(query[4]),
4023
- auth=True,
4024
- user=auser,
4025
- cid=gid if gid != user else None,
4026
  )
4027
- )
4028
- if query[1] == "MANGA"
4029
- else (await get_airing(query[3], auth=True, user=auser, ind=int(query[4])))
4030
- if query[1] == "AIRING"
4031
- else (await get_character(query[3], int(query[4]), auth=True, user=auser))
4032
- if query[1] == "CHARACTER"
4033
- else (
4034
- await get_studios(
4035
- query[3], int(query[4]), user=auser, auth=True, duser=user
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4036
  )
4037
  )
4038
  )
@@ -4041,9 +4057,7 @@ async def toggle_favourites_btn(client: Client, cq: CallbackQuery, cdata: dict):
4041
  pic, msg = (
4042
  (result[0], result[1])
4043
  if query[1] == "ANIME" and len(query) == 3
4044
- else (result[0])
4045
- if query[1] == "AIRING"
4046
- else (result[0], result[1][0])
4047
  )
4048
  btns = get_btns(
4049
  query[1],
@@ -4075,9 +4089,11 @@ async def list_update_anilist_btn(client: Client, cq: CallbackQuery, cdata: dict
4075
  row.append(
4076
  InlineKeyboardButton(
4077
  text=i,
4078
- callback_data=cq.data.replace("lsadd", f"lsas_{i}")
4079
- if query[0] == "lsadd"
4080
- else cq.data.replace("lsupdt", f"lsus_{i}"),
 
 
4081
  )
4082
  )
4083
  if len(row) == 3:
@@ -4179,60 +4195,66 @@ async def update_anilist_btn(client: Client, cq: CallbackQuery, cdata: dict):
4179
  )
4180
  if query[2] == "ANIME" and (len(query) == 4 or len(query) == 5)
4181
  else (
4182
- await get_anilist(
4183
- query[4],
4184
- page=int(query[5]),
4185
- auth=True,
4186
- user=auser,
4187
- cid=gid if gid != user else None,
4188
- )
4189
- )
4190
- if query[2] == "ANIME" and len(query) == 6
4191
- else (
4192
- await get_anilist(
4193
- query[5],
4194
- page=int(query[6]),
4195
- auth=True,
4196
- user=auser,
4197
- cid=gid if gid != user else None,
4198
- )
4199
- )
4200
- if query[2] == "ANIME" and len(query) == 7
4201
- else (
4202
- await get_manga(
4203
- query[4],
4204
- page=int(query[5]),
4205
- auth=True,
4206
- user=auser,
4207
- cid=gid if gid != user else None,
4208
- )
4209
- )
4210
- if query[2] == "MANGA" and len(query) == 6
4211
- else (
4212
- await get_manga(
4213
- query[5],
4214
- page=int(query[6]),
4215
- auth=True,
4216
- user=auser,
4217
- cid=gid if gid != user else None,
4218
  )
4219
- )
4220
- if query[2] == "MANGA" and len(query) == 7
4221
- else (
4222
- await get_airing(
4223
- query[4] if eid is None else query[5],
4224
- auth=True,
4225
- user=auser,
4226
- ind=int(query[5] if eid is None else query[6]),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4227
  )
4228
  )
4229
  )
4230
  pic, msg = (
4231
  (result[0], result[1])
4232
  if query[2] == "ANIME" and (len(query) == 4 or len(query) == 5)
4233
- else (result[0])
4234
- if query[2] == "AIRING"
4235
- else (result[0], result[1][0])
4236
  )
4237
  btns = get_btns(
4238
  query[2],
@@ -4240,11 +4262,11 @@ async def update_anilist_btn(client: Client, cq: CallbackQuery, cdata: dict):
4240
  user=user,
4241
  auth=True,
4242
  lsqry=query[4] if len(query) == 6 else query[5] if len(query) == 7 else None,
4243
- lspage=int(query[5])
4244
- if len(query) == 6
4245
- else int(query[6])
4246
- if len(query) == 7
4247
- else None,
4248
  )
4249
  try:
4250
  await cq.edit_message_media(
@@ -4265,9 +4287,7 @@ async def additional_info_btn(client: Client, cq: CallbackQuery, cdata: dict):
4265
  info = (
4266
  "<b>Description</b>"
4267
  if kek == "desc"
4268
- else "<b>Series List</b>"
4269
- if kek == "ls"
4270
- else "<b>Characters List</b>"
4271
  )
4272
  page = 0
4273
  lsqry = f"_{q[3]}" if len(q) > 6 else ""
@@ -4329,9 +4349,11 @@ async def additional_info_btn(client: Client, cq: CallbackQuery, cdata: dict):
4329
  cbd = (
4330
  f"btn_{qry}_{q[3]}_{user}"
4331
  if len(q) <= 5
4332
- else f"page_ANIME{lsqry}{lspg}_{q[5]}_{user}"
4333
- if ctgry == "ANI"
4334
- else f"page_CHARACTER{lsqry}{lspg}_{q[5]}_{user}"
 
 
4335
  )
4336
  button.append([InlineKeyboardButton(text="BACK", callback_data=cbd)])
4337
  try:
@@ -5112,7 +5134,7 @@ QUOTES_IMG = [
5112
  __help__ = """
5113
  ⛩ *Anime:*
5114
 
5115
- ➠ *Mikobot provides you the best anime-based commands including anime news and much more!*
5116
 
5117
  ➠ *Commands:*
5118
 
 
2253
  async def get_user_favourites(id_, user, req, page, sighs, duser=None):
2254
  vars_ = {"id": int(id_), "page": int(page)}
2255
  result = await return_json_senpai(
2256
+ (
2257
+ FAV_ANI_QUERY
2258
+ if req == "ANIME"
2259
+ else FAV_CHAR_QUERY if req == "CHAR" else FAV_MANGA_QUERY
2260
+ ),
2261
  vars_,
2262
  auth=True,
2263
  user=int(user),
 
2268
  msg = (
2269
  "Favourite Animes:\n\n"
2270
  if req == "ANIME"
2271
+ else "Favourite Characters:\n\n" if req == "CHAR" else "Favourite Manga:\n\n"
 
 
2272
  )
2273
  for i in data["edges"]:
2274
  node_name = (
 
2371
  (
2372
  DES_INFO_QUERY
2373
  if req == "desc"
2374
+ else CHA_INFO_QUERY if req == "char" else REL_INFO_QUERY
 
 
2375
  )
2376
  if ctgry == "ANI"
2377
  else DESC_INFO_QUERY
 
2813
  query = (
2814
  ANIME_MUTATION
2815
  if media == "ANIME" or media == "AIRING"
2816
+ else (
2817
+ CHAR_MUTATION
2818
+ if media == "CHARACTER"
2819
+ else MANGA_MUTATION if media == "MANGA" else STUDIO_MUTATION
2820
+ )
2821
  )
2822
  k = await return_json_senpai(query=query, vars_=vars_, auth=True, user=int(user))
2823
  try:
 
2886
  query=(
2887
  ANILIST_MUTATION
2888
  if req == "lsas"
2889
+ else ANILIST_MUTATION_UP if req == "lsus" else ANILIST_MUTATION_DEL
 
 
2890
  ),
2891
  vars_=vars_,
2892
  auth=True,
 
2896
  (
2897
  k["data"]["SaveMediaListEntry"]
2898
  if req == "lsas"
2899
+ else (
2900
+ k["data"]["UpdateMediaListEntries"]
2901
+ if req == "lsus"
2902
+ else k["data"]["DeleteMediaListEntry"]
2903
+ )
2904
  )
2905
  return "ok"
2906
  except KeyError:
 
4003
  )
4004
  if query[1] == "ANIME" and len(query) == 3
4005
  else (
4006
+ (
4007
+ await get_anilist(
4008
+ query[3],
4009
+ page=int(query[4]),
4010
+ auth=True,
4011
+ user=auser,
4012
+ cid=gid if gid != user else None,
4013
+ )
 
 
 
 
 
 
 
 
4014
  )
4015
+ if query[1] == "ANIME" and len(query) != 3
4016
+ else (
4017
+ (
4018
+ await get_manga(
4019
+ query[3],
4020
+ page=int(query[4]),
4021
+ auth=True,
4022
+ user=auser,
4023
+ cid=gid if gid != user else None,
4024
+ )
4025
+ )
4026
+ if query[1] == "MANGA"
4027
+ else (
4028
+ (
4029
+ await get_airing(
4030
+ query[3], auth=True, user=auser, ind=int(query[4])
4031
+ )
4032
+ )
4033
+ if query[1] == "AIRING"
4034
+ else (
4035
+ (
4036
+ await get_character(
4037
+ query[3], int(query[4]), auth=True, user=auser
4038
+ )
4039
+ )
4040
+ if query[1] == "CHARACTER"
4041
+ else (
4042
+ await get_studios(
4043
+ query[3],
4044
+ int(query[4]),
4045
+ user=auser,
4046
+ auth=True,
4047
+ duser=user,
4048
+ )
4049
+ )
4050
+ )
4051
+ )
4052
  )
4053
  )
4054
  )
 
4057
  pic, msg = (
4058
  (result[0], result[1])
4059
  if query[1] == "ANIME" and len(query) == 3
4060
+ else (result[0]) if query[1] == "AIRING" else (result[0], result[1][0])
 
 
4061
  )
4062
  btns = get_btns(
4063
  query[1],
 
4089
  row.append(
4090
  InlineKeyboardButton(
4091
  text=i,
4092
+ callback_data=(
4093
+ cq.data.replace("lsadd", f"lsas_{i}")
4094
+ if query[0] == "lsadd"
4095
+ else cq.data.replace("lsupdt", f"lsus_{i}")
4096
+ ),
4097
  )
4098
  )
4099
  if len(row) == 3:
 
4195
  )
4196
  if query[2] == "ANIME" and (len(query) == 4 or len(query) == 5)
4197
  else (
4198
+ (
4199
+ await get_anilist(
4200
+ query[4],
4201
+ page=int(query[5]),
4202
+ auth=True,
4203
+ user=auser,
4204
+ cid=gid if gid != user else None,
4205
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4206
  )
4207
+ if query[2] == "ANIME" and len(query) == 6
4208
+ else (
4209
+ (
4210
+ await get_anilist(
4211
+ query[5],
4212
+ page=int(query[6]),
4213
+ auth=True,
4214
+ user=auser,
4215
+ cid=gid if gid != user else None,
4216
+ )
4217
+ )
4218
+ if query[2] == "ANIME" and len(query) == 7
4219
+ else (
4220
+ (
4221
+ await get_manga(
4222
+ query[4],
4223
+ page=int(query[5]),
4224
+ auth=True,
4225
+ user=auser,
4226
+ cid=gid if gid != user else None,
4227
+ )
4228
+ )
4229
+ if query[2] == "MANGA" and len(query) == 6
4230
+ else (
4231
+ (
4232
+ await get_manga(
4233
+ query[5],
4234
+ page=int(query[6]),
4235
+ auth=True,
4236
+ user=auser,
4237
+ cid=gid if gid != user else None,
4238
+ )
4239
+ )
4240
+ if query[2] == "MANGA" and len(query) == 7
4241
+ else (
4242
+ await get_airing(
4243
+ query[4] if eid is None else query[5],
4244
+ auth=True,
4245
+ user=auser,
4246
+ ind=int(query[5] if eid is None else query[6]),
4247
+ )
4248
+ )
4249
+ )
4250
+ )
4251
  )
4252
  )
4253
  )
4254
  pic, msg = (
4255
  (result[0], result[1])
4256
  if query[2] == "ANIME" and (len(query) == 4 or len(query) == 5)
4257
+ else (result[0]) if query[2] == "AIRING" else (result[0], result[1][0])
 
 
4258
  )
4259
  btns = get_btns(
4260
  query[2],
 
4262
  user=user,
4263
  auth=True,
4264
  lsqry=query[4] if len(query) == 6 else query[5] if len(query) == 7 else None,
4265
+ lspage=(
4266
+ int(query[5])
4267
+ if len(query) == 6
4268
+ else int(query[6]) if len(query) == 7 else None
4269
+ ),
4270
  )
4271
  try:
4272
  await cq.edit_message_media(
 
4287
  info = (
4288
  "<b>Description</b>"
4289
  if kek == "desc"
4290
+ else "<b>Series List</b>" if kek == "ls" else "<b>Characters List</b>"
 
 
4291
  )
4292
  page = 0
4293
  lsqry = f"_{q[3]}" if len(q) > 6 else ""
 
4349
  cbd = (
4350
  f"btn_{qry}_{q[3]}_{user}"
4351
  if len(q) <= 5
4352
+ else (
4353
+ f"page_ANIME{lsqry}{lspg}_{q[5]}_{user}"
4354
+ if ctgry == "ANI"
4355
+ else f"page_CHARACTER{lsqry}{lspg}_{q[5]}_{user}"
4356
+ )
4357
  )
4358
  button.append([InlineKeyboardButton(text="BACK", callback_data=cbd)])
4359
  try:
 
5134
  __help__ = """
5135
  ⛩ *Anime:*
5136
 
5137
+ ➠ *Dazai provides you the best anime-based commands including anime news and much more!*
5138
 
5139
  ➠ *Commands:*
5140
 
Mikobot/plugins/approve.py CHANGED
@@ -1,4 +1,3 @@
1
- # <============================================== IMPORTS =========================================================>
2
  import html
3
 
4
  from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
@@ -14,10 +13,7 @@ from Mikobot.plugins.helper_funcs.chat_status import check_admin
14
  from Mikobot.plugins.helper_funcs.extraction import extract_user
15
  from Mikobot.plugins.log_channel import loggable
16
 
17
- # <=======================================================================================================>
18
 
19
-
20
- # <================================================ FUNCTION =======================================================>
21
  @loggable
22
  @check_admin(is_user=True)
23
  async def approve(update: Update, context: ContextTypes.DEFAULT_TYPE):
@@ -214,9 +210,6 @@ async def unapproveall_btn(update: Update, context: ContextTypes.DEFAULT_TYPE):
214
  await query.answer("You need to be admin to do this.")
215
 
216
 
217
- # <=================================================== HELP ====================================================>
218
-
219
-
220
  __help__ = """
221
  ➠ Sometimes, you might trust a user not to send unwanted content.
222
  Maybe not enough to make them admin, but you might be ok with locks, blacklists, and antiflood not applying to them.
@@ -236,7 +229,6 @@ Maybe not enough to make them admin, but you might be ok with locks, blacklists,
236
  » /unapproveall: Unapprove *ALL* users in a chat. This cannot be undone.
237
  """
238
 
239
- # <================================================ HANDLER =======================================================>
240
  APPROVE = DisableAbleCommandHandler("approve", approve, block=False)
241
  DISAPPROVE = DisableAbleCommandHandler("unapprove", disapprove, block=False)
242
  APPROVED = DisableAbleCommandHandler("approved", approved, block=False)
@@ -256,4 +248,3 @@ dispatcher.add_handler(UNAPPROVEALL_BTN)
256
  __mod_name__ = "APPROVALS"
257
  __command_list__ = ["approve", "unapprove", "approved", "approval"]
258
  __handlers__ = [APPROVE, DISAPPROVE, APPROVED, APPROVAL]
259
- # <================================================ END =======================================================>
 
 
1
  import html
2
 
3
  from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
 
13
  from Mikobot.plugins.helper_funcs.extraction import extract_user
14
  from Mikobot.plugins.log_channel import loggable
15
 
 
16
 
 
 
17
  @loggable
18
  @check_admin(is_user=True)
19
  async def approve(update: Update, context: ContextTypes.DEFAULT_TYPE):
 
210
  await query.answer("You need to be admin to do this.")
211
 
212
 
 
 
 
213
  __help__ = """
214
  ➠ Sometimes, you might trust a user not to send unwanted content.
215
  Maybe not enough to make them admin, but you might be ok with locks, blacklists, and antiflood not applying to them.
 
229
  » /unapproveall: Unapprove *ALL* users in a chat. This cannot be undone.
230
  """
231
 
 
232
  APPROVE = DisableAbleCommandHandler("approve", approve, block=False)
233
  DISAPPROVE = DisableAbleCommandHandler("unapprove", disapprove, block=False)
234
  APPROVED = DisableAbleCommandHandler("approved", approved, block=False)
 
248
  __mod_name__ = "APPROVALS"
249
  __command_list__ = ["approve", "unapprove", "approved", "approval"]
250
  __handlers__ = [APPROVE, DISAPPROVE, APPROVED, APPROVAL]
 
Mikobot/plugins/ban.py CHANGED
@@ -1,4 +1,3 @@
1
- # <============================================== IMPORTS =========================================================>
2
  import html
3
 
4
  from telegram import (
@@ -13,7 +12,6 @@ from telegram.ext import CallbackQueryHandler, CommandHandler, ContextTypes, fil
13
  from telegram.helpers import mention_html
14
 
15
  from Mikobot import DEV_USERS, DRAGONS, LOGGER, OWNER_ID, function
16
- from Mikobot.utils.can_restrict import BAN_STICKER
17
  from Mikobot.plugins.disable import DisableAbleCommandHandler
18
  from Mikobot.plugins.helper_funcs.chat_status import (
19
  can_delete,
@@ -28,10 +26,9 @@ from Mikobot.plugins.helper_funcs.misc import mention_username
28
  from Mikobot.plugins.helper_funcs.string_handling import extract_time
29
  from Mikobot.plugins.log_channel import gloggable, loggable
30
 
31
- # <=======================================================================================================>
32
 
33
 
34
- # <================================================ FUNCTION =======================================================>
35
  @connection_status
36
  @loggable
37
  @check_admin(permission="can_restrict_members", is_both=True)
@@ -693,9 +690,6 @@ async def bans_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
693
  return log
694
 
695
 
696
- # <================================================ HELP =======================================================>
697
-
698
-
699
  __help__ = """
700
  » /kickme: kicks the user who issued the command
701
 
@@ -714,7 +708,6 @@ __help__ = """
714
  Banning or UnBanning channels only work if you reply to their message, so don't use their username to ban/unban.
715
  """
716
 
717
- # <================================================ HANDLER =======================================================>
718
  BAN_HANDLER = CommandHandler(["ban", "sban"], ban, block=False)
719
  TEMPBAN_HANDLER = CommandHandler(["tban"], temp_ban, block=False)
720
  KICK_HANDLER = CommandHandler("kick", kick, block=False)
@@ -745,4 +738,3 @@ __handlers__ = [
745
  KICKME_HANDLER,
746
  BAN_CALLBACK_HANDLER,
747
  ]
748
- # <================================================ END =======================================================>
 
 
1
  import html
2
 
3
  from telegram import (
 
12
  from telegram.helpers import mention_html
13
 
14
  from Mikobot import DEV_USERS, DRAGONS, LOGGER, OWNER_ID, function
 
15
  from Mikobot.plugins.disable import DisableAbleCommandHandler
16
  from Mikobot.plugins.helper_funcs.chat_status import (
17
  can_delete,
 
26
  from Mikobot.plugins.helper_funcs.string_handling import extract_time
27
  from Mikobot.plugins.log_channel import gloggable, loggable
28
 
29
+ BAN_STICKER = "CAACAgUAAxkBAAEGWC5lloYv1tiI3-KPguoH5YX-RveWugACoQ4AAi4b2FQGdUhawbi91DQE"
30
 
31
 
 
32
  @connection_status
33
  @loggable
34
  @check_admin(permission="can_restrict_members", is_both=True)
 
690
  return log
691
 
692
 
 
 
 
693
  __help__ = """
694
  » /kickme: kicks the user who issued the command
695
 
 
708
  Banning or UnBanning channels only work if you reply to their message, so don't use their username to ban/unban.
709
  """
710
 
 
711
  BAN_HANDLER = CommandHandler(["ban", "sban"], ban, block=False)
712
  TEMPBAN_HANDLER = CommandHandler(["tban"], temp_ban, block=False)
713
  KICK_HANDLER = CommandHandler("kick", kick, block=False)
 
738
  KICKME_HANDLER,
739
  BAN_CALLBACK_HANDLER,
740
  ]
 
Mikobot/plugins/blacklist.py CHANGED
@@ -1,4 +1,3 @@
1
- # <============================================== IMPORTS =========================================================>
2
  import html
3
  import re
4
 
@@ -21,12 +20,9 @@ from Mikobot.plugins.helper_funcs.string_handling import extract_time
21
  from Mikobot.plugins.log_channel import loggable
22
  from Mikobot.plugins.warns import warn
23
 
24
- # <=======================================================================================================>
25
-
26
  BLACKLIST_GROUP = 11
27
 
28
 
29
- # <================================================ FUNCTION =======================================================>
30
  @check_admin(is_user=True)
31
  @typing_action
32
  async def blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
@@ -401,9 +397,9 @@ async def del_blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
401
  await bot.sendMessage(
402
  chat.id,
403
  f"Muted {user.first_name} for using Blacklisted word: {trigger}!",
404
- message_thread_id=message.message_thread_id
405
- if chat.is_forum
406
- else None,
407
  )
408
  return
409
  elif getmode == 4:
@@ -413,9 +409,9 @@ async def del_blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
413
  await bot.sendMessage(
414
  chat.id,
415
  f"Kicked {user.first_name} for using Blacklisted word: {trigger}!",
416
- message_thread_id=message.message_thread_id
417
- if chat.is_forum
418
- else None,
419
  )
420
  return
421
  elif getmode == 5:
@@ -424,9 +420,9 @@ async def del_blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
424
  await bot.sendMessage(
425
  chat.id,
426
  f"Banned {user.first_name} for using Blacklisted word: {trigger}",
427
- message_thread_id=message.message_thread_id
428
- if chat.is_forum
429
- else None,
430
  )
431
  return
432
  elif getmode == 6:
@@ -436,9 +432,9 @@ async def del_blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
436
  await bot.sendMessage(
437
  chat.id,
438
  f"Banned {user.first_name} until '{value}' for using Blacklisted word: {trigger}!",
439
- message_thread_id=message.message_thread_id
440
- if chat.is_forum
441
- else None,
442
  )
443
  return
444
  elif getmode == 7:
@@ -453,9 +449,9 @@ async def del_blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
453
  await bot.sendMessage(
454
  chat.id,
455
  f"Muted {user.first_name} until '{value}' for using Blacklisted word: {trigger}!",
456
- message_thread_id=message.message_thread_id
457
- if chat.is_forum
458
- else None,
459
  )
460
  return
461
  except BadRequest as excp:
@@ -487,9 +483,6 @@ def __stats__():
487
  )
488
 
489
 
490
- # <=================================================== HELP ====================================================>
491
-
492
-
493
  __mod_name__ = "BLACKLIST"
494
 
495
  __help__ = """
@@ -517,8 +510,6 @@ Note:
517
  » <sticker link> can be https://t.me/addstickers/<sticker> or just <sticker> or reply to the sticker message
518
 
519
  """
520
-
521
- # <================================================ HANDLER =======================================================>
522
  BLACKLIST_HANDLER = DisableAbleCommandHandler(
523
  "blacklist", blacklist, admin_ok=True, block=False
524
  )
@@ -545,4 +536,3 @@ __handlers__ = [
545
  BLACKLISTMODE_HANDLER,
546
  (BLACKLIST_DEL_HANDLER, BLACKLIST_GROUP),
547
  ]
548
- # <================================================ END =======================================================>
 
 
1
  import html
2
  import re
3
 
 
20
  from Mikobot.plugins.log_channel import loggable
21
  from Mikobot.plugins.warns import warn
22
 
 
 
23
  BLACKLIST_GROUP = 11
24
 
25
 
 
26
  @check_admin(is_user=True)
27
  @typing_action
28
  async def blacklist(update: Update, context: ContextTypes.DEFAULT_TYPE):
 
397
  await bot.sendMessage(
398
  chat.id,
399
  f"Muted {user.first_name} for using Blacklisted word: {trigger}!",
400
+ message_thread_id=(
401
+ message.message_thread_id if chat.is_forum else None
402
+ ),
403
  )
404
  return
405
  elif getmode == 4:
 
409
  await bot.sendMessage(
410
  chat.id,
411
  f"Kicked {user.first_name} for using Blacklisted word: {trigger}!",
412
+ message_thread_id=(
413
+ message.message_thread_id if chat.is_forum else None
414
+ ),
415
  )
416
  return
417
  elif getmode == 5:
 
420
  await bot.sendMessage(
421
  chat.id,
422
  f"Banned {user.first_name} for using Blacklisted word: {trigger}",
423
+ message_thread_id=(
424
+ message.message_thread_id if chat.is_forum else None
425
+ ),
426
  )
427
  return
428
  elif getmode == 6:
 
432
  await bot.sendMessage(
433
  chat.id,
434
  f"Banned {user.first_name} until '{value}' for using Blacklisted word: {trigger}!",
435
+ message_thread_id=(
436
+ message.message_thread_id if chat.is_forum else None
437
+ ),
438
  )
439
  return
440
  elif getmode == 7:
 
449
  await bot.sendMessage(
450
  chat.id,
451
  f"Muted {user.first_name} until '{value}' for using Blacklisted word: {trigger}!",
452
+ message_thread_id=(
453
+ message.message_thread_id if chat.is_forum else None
454
+ ),
455
  )
456
  return
457
  except BadRequest as excp:
 
483
  )
484
 
485
 
 
 
 
486
  __mod_name__ = "BLACKLIST"
487
 
488
  __help__ = """
 
510
  » <sticker link> can be https://t.me/addstickers/<sticker> or just <sticker> or reply to the sticker message
511
 
512
  """
 
 
513
  BLACKLIST_HANDLER = DisableAbleCommandHandler(
514
  "blacklist", blacklist, admin_ok=True, block=False
515
  )
 
536
  BLACKLISTMODE_HANDLER,
537
  (BLACKLIST_DEL_HANDLER, BLACKLIST_GROUP),
538
  ]
 
Mikobot/plugins/blacklist_stickers.py CHANGED
@@ -1,4 +1,3 @@
1
- # <============================================== IMPORTS =========================================================>
2
  import html
3
 
4
  from telegram import ChatPermissions, Update
@@ -18,10 +17,7 @@ from Mikobot.plugins.helper_funcs.string_handling import extract_time
18
  from Mikobot.plugins.log_channel import loggable
19
  from Mikobot.plugins.warns import warn
20
 
21
- # <=======================================================================================================>
22
 
23
-
24
- # <================================================ FUNCTION =======================================================>
25
  async def blackliststicker(update: Update, context: ContextTypes.DEFAULT_TYPE):
26
  msg = update.effective_message # type: Optional[Message]
27
  chat = update.effective_chat # type: Optional[Chat]
@@ -452,9 +448,9 @@ async def del_blackliststicker(update: Update, context: ContextTypes.DEFAULT_TYP
452
  trigger,
453
  ),
454
  parse_mode="markdown",
455
- message_thread_id=message.message_thread_id
456
- if chat.is_forum
457
- else None,
458
  )
459
  return
460
  elif getmode == 4:
@@ -468,9 +464,9 @@ async def del_blackliststicker(update: Update, context: ContextTypes.DEFAULT_TYP
468
  trigger,
469
  ),
470
  parse_mode="markdown",
471
- message_thread_id=message.message_thread_id
472
- if chat.is_forum
473
- else None,
474
  )
475
  return
476
  elif getmode == 5:
@@ -483,9 +479,9 @@ async def del_blackliststicker(update: Update, context: ContextTypes.DEFAULT_TYP
483
  trigger,
484
  ),
485
  parse_mode="markdown",
486
- message_thread_id=message.message_thread_id
487
- if chat.is_forum
488
- else None,
489
  )
490
  return
491
  elif getmode == 6:
@@ -500,9 +496,9 @@ async def del_blackliststicker(update: Update, context: ContextTypes.DEFAULT_TYP
500
  trigger,
501
  ),
502
  parse_mode="markdown",
503
- message_thread_id=message.message_thread_id
504
- if chat.is_forum
505
- else None,
506
  )
507
  return
508
  elif getmode == 7:
@@ -522,9 +518,9 @@ async def del_blackliststicker(update: Update, context: ContextTypes.DEFAULT_TYP
522
  trigger,
523
  ),
524
  parse_mode="markdown",
525
- message_thread_id=message.message_thread_id
526
- if chat.is_forum
527
- else None,
528
  )
529
  return
530
  except BadRequest as excp:
@@ -558,7 +554,6 @@ def __stats__():
558
 
559
  __mod_name__ = "Stickers Blacklist"
560
 
561
- # <================================================ HANDLER =======================================================>
562
  BLACKLIST_STICKER_HANDLER = DisableAbleCommandHandler(
563
  "blsticker", blackliststicker, admin_ok=True, block=False
564
  )
@@ -578,4 +573,3 @@ dispatcher.add_handler(ADDBLACKLIST_STICKER_HANDLER)
578
  dispatcher.add_handler(UNBLACKLIST_STICKER_HANDLER)
579
  dispatcher.add_handler(BLACKLISTMODE_HANDLER)
580
  dispatcher.add_handler(BLACKLIST_STICKER_DEL_HANDLER)
581
- # <================================================ END =======================================================>
 
 
1
  import html
2
 
3
  from telegram import ChatPermissions, Update
 
17
  from Mikobot.plugins.log_channel import loggable
18
  from Mikobot.plugins.warns import warn
19
 
 
20
 
 
 
21
  async def blackliststicker(update: Update, context: ContextTypes.DEFAULT_TYPE):
22
  msg = update.effective_message # type: Optional[Message]
23
  chat = update.effective_chat # type: Optional[Chat]
 
448
  trigger,
449
  ),
450
  parse_mode="markdown",
451
+ message_thread_id=(
452
+ message.message_thread_id if chat.is_forum else None
453
+ ),
454
  )
455
  return
456
  elif getmode == 4:
 
464
  trigger,
465
  ),
466
  parse_mode="markdown",
467
+ message_thread_id=(
468
+ message.message_thread_id if chat.is_forum else None
469
+ ),
470
  )
471
  return
472
  elif getmode == 5:
 
479
  trigger,
480
  ),
481
  parse_mode="markdown",
482
+ message_thread_id=(
483
+ message.message_thread_id if chat.is_forum else None
484
+ ),
485
  )
486
  return
487
  elif getmode == 6:
 
496
  trigger,
497
  ),
498
  parse_mode="markdown",
499
+ message_thread_id=(
500
+ message.message_thread_id if chat.is_forum else None
501
+ ),
502
  )
503
  return
504
  elif getmode == 7:
 
518
  trigger,
519
  ),
520
  parse_mode="markdown",
521
+ message_thread_id=(
522
+ message.message_thread_id if chat.is_forum else None
523
+ ),
524
  )
525
  return
526
  except BadRequest as excp:
 
554
 
555
  __mod_name__ = "Stickers Blacklist"
556
 
 
557
  BLACKLIST_STICKER_HANDLER = DisableAbleCommandHandler(
558
  "blsticker", blackliststicker, admin_ok=True, block=False
559
  )
 
573
  dispatcher.add_handler(UNBLACKLIST_STICKER_HANDLER)
574
  dispatcher.add_handler(BLACKLISTMODE_HANDLER)
575
  dispatcher.add_handler(BLACKLIST_STICKER_DEL_HANDLER)
 
Mikobot/plugins/botadmins.py CHANGED
@@ -46,7 +46,7 @@ async def botstaff(update: Update, context: ContextTypes.DEFAULT_TYPE):
46
  try:
47
  owner = await get_chat_member(context, OWNER_ID)
48
  owner_info = await mention_html(owner.user.first_name, owner.user.id)
49
- reply = f"✪ <b>CREATOR :</b> {owner_info} (<code>{OWNER_ID}</code>)\n"
50
  except TelegramError as e:
51
  LOGGER.error(f"Error getting owner information: {e}")
52
  reply = ""
 
46
  try:
47
  owner = await get_chat_member(context, OWNER_ID)
48
  owner_info = await mention_html(owner.user.first_name, owner.user.id)
49
+ reply = f"✪ <b>OWNER :</b> {owner_info} (<code>{OWNER_ID}</code>)\n"
50
  except TelegramError as e:
51
  LOGGER.error(f"Error getting owner information: {e}")
52
  reply = ""
Mikobot/plugins/bug.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pyrogram import filters
2
+ from pyrogram.enums import ParseMode
3
+
4
+ # Chat IDs where bug reports should be sent
5
+ BUG_REPORT_CHAT_IDS = [-1001989832800, -1001823656633]
6
+
7
+ from Mikobot import app
8
+
9
+
10
+ # Define a handler for the /bug command
11
+ @app.on_message(filters.command("bug", prefixes="/"))
12
+ def bug_command_handler(client, message):
13
+ # Check if the command is a reply
14
+ if message.reply_to_message:
15
+ # Get the message being replied to
16
+ replied_message = message.reply_to_message
17
+
18
+ # Extract message content
19
+ content = replied_message.text or replied_message.caption
20
+
21
+ # Check if there is media content
22
+ media_type = (
23
+ "**Media content included**"
24
+ if replied_message.photo
25
+ or replied_message.document
26
+ or replied_message.video
27
+ or replied_message.audio
28
+ or replied_message.animation
29
+ else "**No media content included**"
30
+ )
31
+
32
+ # Prepare the report message with message link and media content info
33
+ report_message = f"**Bug reported by @{message.from_user.username}:**\n\n{content}\n\n{media_type}\n\n**Message Link:** {replied_message.link}"
34
+
35
+ # Send the report message
36
+ client.send_message(
37
+ BUG_REPORT_CHAT_IDS[0], report_message, parse_mode=ParseMode.MARKDOWN
38
+ )
39
+ else:
40
+ # If not a reply, send a message to reply with /bug command to report a bug
41
+ client.send_message(
42
+ message.chat.id,
43
+ "To report a bug, please reply to the message with **/ bug** cmd.",
44
+ parse_mode=ParseMode.MARKDOWN,
45
+ )
Mikobot/plugins/{chatbot.py → chatbot.py.txt} RENAMED
File without changes
Mikobot/plugins/connection.py CHANGED
@@ -205,9 +205,11 @@ async def connect_chat(update: Update, context: ContextTypes.DEFAULT_TYPE):
205
  ],
206
  )
207
  text += "╘══「 Total {} Chats 」".format(
208
- str(len(gethistory)) + " (max)"
209
- if len(gethistory) == 5
210
- else str(len(gethistory)),
 
 
211
  )
212
  conn_hist = InlineKeyboardMarkup(buttons)
213
  elif buttons:
 
205
  ],
206
  )
207
  text += "╘══「 Total {} Chats 」".format(
208
+ (
209
+ str(len(gethistory)) + " (max)"
210
+ if len(gethistory) == 5
211
+ else str(len(gethistory))
212
+ ),
213
  )
214
  conn_hist = InlineKeyboardMarkup(buttons)
215
  elif buttons:
Mikobot/plugins/couple.py CHANGED
@@ -9,6 +9,14 @@ from Mikobot import app
9
 
10
  # <=======================================================================================================>
11
 
 
 
 
 
 
 
 
 
12
 
13
  # <================================================ FUNCTION =======================================================>
14
  def dt():
@@ -32,33 +40,42 @@ def dt_tom():
32
  tomorrow = str(dt_tom())
33
  today = str(dt()[0])
34
 
35
- COUPLES_PIC = "https://telegra.ph/file/c6d0c884f559b9ed8a54e.jpg"
36
  C = """
37
- 𝗖𝗢𝗨𝗣𝗟𝗘𝗦 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬
38
- ➖➖➖➖➖➖➖➖➖➖➖➖
39
- {} + ( PGM🎀😶 (https://t.me/Chalnayaaaaaarr) + 花火 (https://t.me/zd_sr07) + ゼロツー (https://t.me/wewewe_x) ) = 💞
40
- ➖➖➖➖➖➖➖➖➖➖➖➖
41
- 𝗡𝗘𝗪 𝗖𝗢𝗨𝗣𝗟𝗘 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 𝗖𝗔𝗡 𝗕𝗘 𝗖𝗛𝗢𝗦𝗘𝗡 𝗔𝗧 12AM {}
 
 
 
42
  """
43
  CAP = """
44
- 𝗖𝗢𝗨𝗣𝗟𝗘𝗦 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬
45
- ➖➖➖➖➖➖➖➖➖➖➖➖
46
- {} + {} = 💞
47
- ➖➖➖➖➖➖➖➖➖➖➖➖
48
- 𝗡𝗘𝗪 𝗖𝗢𝗨𝗣𝗟𝗘 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 𝗖𝗔𝗡 𝗕𝗘 𝗖𝗛𝗢𝗦𝗘𝗡 𝗔𝗧 12AM {}
 
 
 
49
  """
50
 
51
  CAP2 = """
52
- 𝗖𝗢𝗨𝗣𝗟𝗘𝗦 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬
53
- ➖➖➖➖➖➖➖➖➖➖➖➖
54
- {} (tg://openmessage?user_id={}) + {} (tg://openmessage?user_id={}) = 💞\n
55
- ➖➖➖➖➖➖➖➖➖➖➖➖
56
- 𝗡𝗘𝗪 𝗖𝗢𝗨𝗣𝗟𝗘 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 𝗖𝗔𝗡 𝗕𝗘 𝗖𝗛𝗢𝗦𝗘𝗡 𝗔𝗧 12AM {}
 
 
 
57
  """
58
 
59
 
60
  @app.on_message(filters.command(["couple", "couples", "shipping"]) & ~filters.private)
61
  async def nibba_nibbi(_, message):
 
62
  if message.from_user.id == 5540249238:
63
  my_ = await _.get_users("rfxtuv")
64
  me = await _.get_users(5540249238)
@@ -75,7 +92,7 @@ async def nibba_nibbi(_, message):
75
  if not i.user.is_bot:
76
  list_of_users.append(i.user.id)
77
  if len(list_of_users) < 2:
78
- return await message.reply_text("ɴᴏᴛ ᴇɴᴏᴜɢʜ ᴜsᴇʀs ɪɴ ᴛʜɪs ɢʀᴏᴜᴘ.")
79
  c1_id = random.choice(list_of_users)
80
  c2_id = random.choice(list_of_users)
81
  while c1_id == c2_id:
@@ -98,11 +115,14 @@ async def nibba_nibbi(_, message):
98
  c1_name = (await _.get_users(c1_id)).first_name
99
  c2_name = (await _.get_users(c2_id)).first_name
100
  print(c1_id, c2_id, c1_name, c2_name)
101
- couple_selection_message = f""" 𝗖𝗢𝗨𝗣𝗟𝗘𝗦 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬
102
- ➖➖➖➖➖➖➖➖➖➖➖➖
103
- [{c1_name}](tg://openmessage?user_id={c1_id}) + [{c2_name}](tg://openmessage?user_id={c2_id}) = 💞
104
- ➖➖➖➖➖➖➖➖➖➖➖➖
105
- 𝗡𝗘𝗪 𝗖𝗢𝗨𝗣𝗟𝗘 𝗢𝗙 𝗧𝗛𝗘 𝗗𝗔𝗬 𝗖𝗔𝗡 𝗕𝗘 𝗖𝗛𝗢𝗦𝗘𝗡 𝗔𝗧 12AM {tomorrow}"""
 
 
 
106
  await _.send_photo(
107
  message.chat.id, photo=COUPLES_PIC, caption=couple_selection_message
108
  )
@@ -112,12 +132,10 @@ async def nibba_nibbi(_, message):
112
 
113
 
114
  # <=================================================== HELP ====================================================>
115
-
116
-
117
  __help__ = """
118
  💘 *Choose couples in your chat*
119
 
120
- » /couple, /couples, /shipping *:* Choose 2 users and send their names as couples in your chat.
121
  """
122
 
123
  __mod_name__ = "COUPLE"
 
9
 
10
  # <=======================================================================================================>
11
 
12
+ # List of additional images
13
+ ADDITIONAL_IMAGES = [
14
+ "https://telegra.ph/file/7ef6006ed6e452a6fd871.jpg",
15
+ "https://telegra.ph/file/16ede7c046f35e699ed3c.jpg",
16
+ "https://telegra.ph/file/f16b555b2a66853cc594e.jpg",
17
+ "https://telegra.ph/file/7ef6006ed6e452a6fd871.jpg",
18
+ ]
19
+
20
 
21
  # <================================================ FUNCTION =======================================================>
22
  def dt():
 
40
  tomorrow = str(dt_tom())
41
  today = str(dt()[0])
42
 
 
43
  C = """
44
+ •➵💞࿐ 𝐇𝐚𝐩𝐩𝐲 𝐜𝐨𝐮𝐩𝐥𝐞 𝐨𝐟 𝐭𝐡𝐞 𝐝𝐚𝐲
45
+ ╭──────────────
46
+ ┊•➢ {} + ( PGM🎀😶 (https://t.me/Chalnayaaaaaarr) + 花火 (https://t.me/zd_sr07) + ゼロツー (https://t.me/wewewe_x) ) = 💞
47
+ ╰───•➢♡
48
+ ╭──────────────
49
+ ┊•➢ 𝗡𝗲𝘄 𝗰𝗼𝘂𝗽𝗹𝗲 𝗼𝗳 𝘁𝗵𝗲 𝗱𝗮𝘆 𝗺𝗮𝘆𝗯𝗲
50
+ ┊ 𝗰𝗵𝗼𝘀𝗲𝗻 𝗮𝘁 12AM {}
51
+ ╰───•➢♡
52
  """
53
  CAP = """
54
+ •➵💞࿐ 𝐇𝐚𝐩𝐩𝐲 𝐜𝐨𝐮𝐩𝐥𝐞 𝐨𝐟 𝐭𝐡𝐞 𝐝𝐚𝐲
55
+ ╭──────────────
56
+ ┊•➢ {} + {} = 💞
57
+ ╰───•➢♡
58
+ ╭──────────────
59
+ ┊•➢ 𝗡𝗲𝘄 𝗰𝗼𝘂𝗽𝗹𝗲 𝗼𝗳 𝘁𝗵𝗲 𝗱𝗮𝘆 𝗺𝗮𝘆𝗯𝗲
60
+ ┊ 𝗰𝗵𝗼𝘀𝗲𝗻 𝗮𝘁 12AM {}
61
+ ╰───•➢♡
62
  """
63
 
64
  CAP2 = """
65
+ •➵💞࿐ 𝐇𝐚𝐩𝐩𝐲 𝐜𝐨𝐮𝐩𝐥𝐞 𝐨𝐟 𝐭𝐡𝐞 𝐝𝐚𝐲
66
+ ╭──────────────
67
+ {} (tg://openmessage?user_id={}) + {} (tg://openmessage?user_id={}) = 💞\n
68
+ ╰───•➢♡
69
+ ╭──────────────
70
+ ┊•➢ 𝗡𝗲𝘄 𝗰𝗼𝘂𝗽𝗹𝗲 𝗼𝗳 𝘁𝗵𝗲 𝗱𝗮𝘆 𝗺𝗮𝘆𝗯𝗲
71
+ ┊ 𝗰𝗵𝗼𝘀𝗲𝗻 𝗮𝘁 12AM {}
72
+ ╰───•➢♡
73
  """
74
 
75
 
76
  @app.on_message(filters.command(["couple", "couples", "shipping"]) & ~filters.private)
77
  async def nibba_nibbi(_, message):
78
+ COUPLES_PIC = random.choice(ADDITIONAL_IMAGES) # Move inside the command function
79
  if message.from_user.id == 5540249238:
80
  my_ = await _.get_users("rfxtuv")
81
  me = await _.get_users(5540249238)
 
92
  if not i.user.is_bot:
93
  list_of_users.append(i.user.id)
94
  if len(list_of_users) < 2:
95
+ return await message.reply_text("Not enough users in the group.")
96
  c1_id = random.choice(list_of_users)
97
  c2_id = random.choice(list_of_users)
98
  while c1_id == c2_id:
 
115
  c1_name = (await _.get_users(c1_id)).first_name
116
  c2_name = (await _.get_users(c2_id)).first_name
117
  print(c1_id, c2_id, c1_name, c2_name)
118
+ couple_selection_message = f"""•➵💞࿐ 𝐇𝐚𝐩𝐩𝐲 𝐜𝐨𝐮𝐩𝐥𝐞 𝐨𝐟 𝐭𝐡𝐞 𝐝𝐚𝐲
119
+ ╭──────────────
120
+ ┊•➢ [{c1_name}](tg://openmessage?user_id={c1_id}) + [{c2_name}](tg://openmessage?user_id={c2_id}) = 💞
121
+ ╰───•➢♡
122
+ ╭──────────────
123
+ ┊•➢ 𝗡𝗲𝘄 𝗰𝗼𝘂𝗽𝗹𝗲 𝗼𝗳 𝘁𝗵𝗲 𝗱𝗮𝘆 𝗺𝗮𝘆𝗯𝗲
124
+ ┊ 𝗰𝗵𝗼𝘀𝗲𝗻 𝗮𝘁 12AM {tomorrow}
125
+ ╰───•➢♡"""
126
  await _.send_photo(
127
  message.chat.id, photo=COUPLES_PIC, caption=couple_selection_message
128
  )
 
132
 
133
 
134
  # <=================================================== HELP ====================================================>
 
 
135
  __help__ = """
136
  💘 *Choose couples in your chat*
137
 
138
+ /couple, /couples, /shipping *:* Choose 2 users and send their names as couples in your chat.
139
  """
140
 
141
  __mod_name__ = "COUPLE"
Mikobot/plugins/cust_filters.py CHANGED
@@ -14,6 +14,7 @@ from telegram.ext import (
14
  ContextTypes,
15
  MessageHandler,
16
  )
 
17
  from telegram.ext import filters as filters_module
18
  from telegram.helpers import escape_markdown, mention_html
19
 
@@ -379,9 +380,9 @@ async def reply_filter(update: Update, context: ContextTypes.DEFAULT_TYPE):
379
  chat.id,
380
  sticker_id,
381
  reply_to_message_id=message.message_id,
382
- message_thread_id=message.message_thread_id
383
- if chat.is_forum
384
- else None,
385
  )
386
  return
387
  except BadRequest as excp:
@@ -392,9 +393,11 @@ async def reply_filter(update: Update, context: ContextTypes.DEFAULT_TYPE):
392
  await context.bot.send_message(
393
  chat.id,
394
  "Message couldn't be sent, Is the sticker id valid?",
395
- message_thread_id=message.message_thread_id
396
- if chat.is_forum
397
- else None,
 
 
398
  )
399
  return
400
  else:
@@ -412,26 +415,32 @@ async def reply_filter(update: Update, context: ContextTypes.DEFAULT_TYPE):
412
  or message.from_user.first_name,
413
  ),
414
  fullname=" ".join(
415
- [
416
- escape(message.from_user.first_name),
417
- escape(message.from_user.last_name),
418
- ]
419
- if message.from_user.last_name
420
- else [escape(message.from_user.first_name)],
 
 
421
  ),
422
- username="@" + escape(message.from_user.username)
423
- if message.from_user.username
424
- else mention_html(
425
- message.from_user.id,
426
- message.from_user.first_name,
 
 
427
  ),
428
  mention=mention_html(
429
  message.from_user.id,
430
  message.from_user.first_name,
431
  ),
432
- chatname=escape(message.chat.title)
433
- if message.chat.type != "private"
434
- else escape(message.from_user.first_name),
 
 
435
  id=message.from_user.id,
436
  )
437
  else:
@@ -469,9 +478,9 @@ async def reply_filter(update: Update, context: ContextTypes.DEFAULT_TYPE):
469
  filt.file_id,
470
  reply_markup=keyboard,
471
  reply_to_message_id=message.message_id,
472
- message_thread_id=message.message_thread_id
473
- if chat.is_forum
474
- else None,
475
  )
476
  else:
477
  await ENUM_FUNC_MAP[filt.file_type](
@@ -480,10 +489,10 @@ async def reply_filter(update: Update, context: ContextTypes.DEFAULT_TYPE):
480
  reply_markup=keyboard,
481
  caption=filt.reply_text,
482
  reply_to_message_id=message.message_id,
483
- message_thread_id=message.message_thread_id
484
- if chat.is_forum
485
- else None,
486
- has_spoiler=filt.has_media_spoiler,
487
  )
488
  except BadRequest:
489
  await send_message(
@@ -520,9 +529,9 @@ async def reply_filter(update: Update, context: ContextTypes.DEFAULT_TYPE):
520
  parse_mode=ParseMode.HTML,
521
  disable_web_page_preview=True,
522
  reply_markup=keyboard,
523
- message_thread_id=message.message_thread_id
524
- if chat.is_forum
525
- else None,
526
  )
527
  except BadRequest as excp:
528
  if excp.message == "Unsupported url protocol":
@@ -559,9 +568,9 @@ async def reply_filter(update: Update, context: ContextTypes.DEFAULT_TYPE):
559
  await context.bot.send_message(
560
  chat.id,
561
  filt.reply,
562
- message_thread_id=message.message_thread_id
563
- if chat.is_forum
564
- else None,
565
  )
566
  except BadRequest as excp:
567
  LOGGER.exception("Error in filters: " + excp.message)
 
14
  ContextTypes,
15
  MessageHandler,
16
  )
17
+ from telegram.ext import filters
18
  from telegram.ext import filters as filters_module
19
  from telegram.helpers import escape_markdown, mention_html
20
 
 
380
  chat.id,
381
  sticker_id,
382
  reply_to_message_id=message.message_id,
383
+ message_thread_id=(
384
+ message.message_thread_id if chat.is_forum else None
385
+ ),
386
  )
387
  return
388
  except BadRequest as excp:
 
393
  await context.bot.send_message(
394
  chat.id,
395
  "Message couldn't be sent, Is the sticker id valid?",
396
+ message_thread_id=(
397
+ message.message_thread_id
398
+ if chat.is_forum
399
+ else None
400
+ ),
401
  )
402
  return
403
  else:
 
415
  or message.from_user.first_name,
416
  ),
417
  fullname=" ".join(
418
+ (
419
+ [
420
+ escape(message.from_user.first_name),
421
+ escape(message.from_user.last_name),
422
+ ]
423
+ if message.from_user.last_name
424
+ else [escape(message.from_user.first_name)]
425
+ ),
426
  ),
427
+ username=(
428
+ "@" + escape(message.from_user.username)
429
+ if message.from_user.username
430
+ else mention_html(
431
+ message.from_user.id,
432
+ message.from_user.first_name,
433
+ )
434
  ),
435
  mention=mention_html(
436
  message.from_user.id,
437
  message.from_user.first_name,
438
  ),
439
+ chatname=(
440
+ escape(message.chat.title)
441
+ if message.chat.type != "private"
442
+ else escape(message.from_user.first_name)
443
+ ),
444
  id=message.from_user.id,
445
  )
446
  else:
 
478
  filt.file_id,
479
  reply_markup=keyboard,
480
  reply_to_message_id=message.message_id,
481
+ message_thread_id=(
482
+ message.message_thread_id if chat.is_forum else None
483
+ ),
484
  )
485
  else:
486
  await ENUM_FUNC_MAP[filt.file_type](
 
489
  reply_markup=keyboard,
490
  caption=filt.reply_text,
491
  reply_to_message_id=message.message_id,
492
+ message_thread_id=(
493
+ message.message_thread_id if chat.is_forum else None
494
+ ),
495
+ has_spoiler=filters.HAS_MEDIA_SPOILER,
496
  )
497
  except BadRequest:
498
  await send_message(
 
529
  parse_mode=ParseMode.HTML,
530
  disable_web_page_preview=True,
531
  reply_markup=keyboard,
532
+ message_thread_id=(
533
+ message.message_thread_id if chat.is_forum else None
534
+ ),
535
  )
536
  except BadRequest as excp:
537
  if excp.message == "Unsupported url protocol":
 
568
  await context.bot.send_message(
569
  chat.id,
570
  filt.reply,
571
+ message_thread_id=(
572
+ message.message_thread_id if chat.is_forum else None
573
+ ),
574
  )
575
  except BadRequest as excp:
576
  LOGGER.exception("Error in filters: " + excp.message)
Mikobot/plugins/disasters.py ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import html
2
+ import json
3
+ import os
4
+ from typing import Optional
5
+
6
+ from telegram import Update
7
+ from telegram.ext import CommandHandler
8
+
9
+ from Mikobot import dispatcher
10
+ from Mikobot.plugins.helper_funcs.chat_status import dev_plus, sudo_plus
11
+ from Mikobot.plugins.helper_funcs.extraction import extract_user
12
+ from Mikobot.plugins.log_channel import gloggable
13
+
14
+ ELEVATED_USERS_FILE = os.path.join(os.getcwd(), "Mikobot/elevated_users.json")
15
+
16
+ DISASTER_LEVELS = {
17
+ "Dragon": "DRAGONS",
18
+ "Demon": "DEMONS",
19
+ "Wolf": "WOLVES",
20
+ "Tiger": "TIGERS",
21
+ }
22
+
23
+
24
+ async def check_user_id(user_id: int) -> Optional[str]:
25
+ if not user_id:
26
+ return "That...is a chat! baka ka omae?"
27
+ return None
28
+
29
+
30
+ async def update_elevated_users(data):
31
+ with open(ELEVATED_USERS_FILE, "w") as outfile:
32
+ json.dump(data, outfile, indent=4)
33
+
34
+
35
+ async def add_disaster_level(update: Update, level: str, context) -> str:
36
+ message = update.effective_message
37
+ user = update.effective_user
38
+ chat = update.effective_chat
39
+ bot, args = context.bot, context.args
40
+ user_id = await extract_user(message, context, args)
41
+ user_member = await bot.get_chat(user_id)
42
+ rt = ""
43
+
44
+ reply = await check_user_id(user_id)
45
+ if reply:
46
+ await message.reply_text(reply)
47
+ return ""
48
+
49
+ with open(ELEVATED_USERS_FILE, "r") as infile:
50
+ data = json.load(infile)
51
+
52
+ disaster_list = getattr(DISASTER_LEVELS, level)
53
+ if user_id in disaster_list:
54
+ await message.reply_text(f"This user is already a {level} Disaster.")
55
+ return ""
56
+
57
+ for disaster_level, disaster_users in DISASTER_LEVELS.items():
58
+ if user_id in disaster_users:
59
+ rt += f"Requested HA to promote this {disaster_level} to {level}."
60
+ data[disaster_users].remove(user_id)
61
+ setattr(DISASTER_LEVELS, disaster_level, disaster_users)
62
+
63
+ data[DISASTER_LEVELS[level]].append(user_id)
64
+ setattr(DISASTER_LEVELS, level, user_id)
65
+
66
+ await update_effective_message.reply_text(
67
+ rt
68
+ + f"\nSuccessfully set Disaster level of {user_member.first_name} to {level}!"
69
+ )
70
+
71
+ log_message = (
72
+ f"#{level.upper()}\n"
73
+ f"<b>Admin:</b> {mention_html(user.id, html.escape(user.first_name))}\n"
74
+ f"<b>User:</b> {mention_html(user_member.id, html.escape(user_member.first_name))}"
75
+ )
76
+
77
+ if chat.type != "private":
78
+ log_message = f"<b>{html.escape(chat.title)}:</b>\n" + log_message
79
+
80
+ await update.effective_message.reply_text(log_message)
81
+
82
+ await update_elevated_users(data)
83
+
84
+
85
+ @dev_plus
86
+ @gloggable
87
+ async def addsudo(update: Update, context) -> str:
88
+ await add_disaster_level(update, "Dragon", context)
89
+
90
+
91
+ @sudo_plus
92
+ @gloggable
93
+ async def addsupport(update: Update, context) -> str:
94
+ await add_disaster_level(update, "Demon", context)
95
+
96
+
97
+ @sudo_plus
98
+ @gloggable
99
+ async def addwhitelist(update: Update, context) -> str:
100
+ await add_disaster_level(update, "Wolf", context)
101
+
102
+
103
+ @sudo_plus
104
+ @gloggable
105
+ async def addtiger(update: Update, context) -> str:
106
+ await add_disaster_level(update, "Tiger", context)
107
+
108
+
109
+ # Other functions can be refactored similarly...
110
+
111
+ SUDO_HANDLER = CommandHandler("addsudo", addsudo, block=False)
112
+ SUPPORT_HANDLER = CommandHandler(("addsupport", "adddemon"), addsupport, block=False)
113
+ TIGER_HANDLER = CommandHandler("addtiger", addtiger, block=False)
114
+ WHITELIST_HANDLER = CommandHandler(
115
+ ("addwhitelist", "addwolf"), addwhitelist, block=False
116
+ )
117
+
118
+ dispatcher.add_handler(SUDO_HANDLER)
119
+ dispatcher.add_handler(SUPPORT_HANDLER)
120
+ dispatcher.add_handler(TIGER_HANDLER)
121
+ dispatcher.add_handler(WHITELIST_HANDLER)
122
+
123
+ __mod_name__ = "Devs"
124
+ __handlers__ = [
125
+ SUDO_HANDLER,
126
+ SUPPORT_HANDLER,
127
+ TIGER_HANDLER,
128
+ WHITELIST_HANDLER,
129
+ ]