Karma
commited on
Commit
·
f45efbd
1
Parent(s):
7a6546b
Add files via upload
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- Database/mongodb/afk_db.py +53 -0
- Database/mongodb/blacklistdb.py +51 -0
- Database/mongodb/db.py +6 -0
- Database/mongodb/fsub_db.py +18 -0
- Database/mongodb/karma_mongo.py +122 -0
- Database/mongodb/locale_db.py +22 -0
- Database/mongodb/mongodb.py +75 -0
- Database/mongodb/sangmata_db.py +42 -0
- Database/mongodb/toggle_mongo.py +50 -0
- Database/mongodb/users_chats_db.py +111 -0
- Database/mongodb/users_db.py +102 -0
- Database/mongodb/whispers.py +19 -0
- Database/sql/__init__.py +27 -0
- Database/sql/afk_sql.py +99 -0
- Database/sql/antichannel_sql.py +88 -0
- Database/sql/antiflood_sql.py +171 -0
- Database/sql/antilinkedchannel_sql.py +142 -0
- Database/sql/approve_sql.py +85 -0
- Database/sql/blacklist_sql.py +223 -0
- Database/sql/blacklistusers_sql.py +90 -0
- Database/sql/blsticker_sql.py +223 -0
- Database/sql/cleaner_sql.py +225 -0
- Database/sql/connection_sql.py +230 -0
- Database/sql/cust_filters_sql.py +404 -0
- Database/sql/disable_sql.py +129 -0
- Database/sql/feds_sql.py +931 -0
- Database/sql/fontsql.py +2361 -0
- Database/sql/forceSubscribe_sql.py +46 -0
- Database/sql/global_bans_sql.py +167 -0
- Database/sql/kuki_sql.py +42 -0
- Database/sql/locks_sql.py +292 -0
- Database/sql/log_channel_sql.py +180 -0
- Database/sql/nightmode_sql.py +42 -0
- Database/sql/notes_sql.py +210 -0
- Database/sql/raid_sql.py +73 -0
- Database/sql/remind_sql.py +140 -0
- Database/sql/reporting_sql.py +115 -0
- Database/sql/rules_sql.py +58 -0
- Database/sql/userinfo_sql.py +100 -0
- Database/sql/users_sql.py +258 -0
- Database/sql/warns_sql.py +341 -0
- Database/sql/welcome_sql.py +507 -0
- Dockerfile +12 -0
- Extra/Calistoga-Regular.ttf +0 -0
- Extra/MutantAcademyStyle.ttf +0 -0
- Extra/a.jpg +0 -0
- Extra/bgg.jpg +0 -0
- Extra/default.ttf +0 -0
- Extra/profilepic.png +0 -0
- Infamous/karma.py +90 -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/db.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from motor.motor_asyncio import AsyncIOMotorClient as MongoClient
|
2 |
+
|
3 |
+
from Mikobot import DB_NAME, MONGO_DB_URI
|
4 |
+
|
5 |
+
mongo = MongoClient(MONGO_DB_URI)
|
6 |
+
dbname = mongo[DB_NAME]
|
Database/mongodb/fsub_db.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from Infamous.temp import dbname
|
2 |
+
|
3 |
+
fsub = dbname.force_sub
|
4 |
+
|
5 |
+
|
6 |
+
def fs_settings(chat_id: int):
|
7 |
+
_x = fsub.find_one({"chat_id": chat_id})
|
8 |
+
if _x:
|
9 |
+
return _x
|
10 |
+
return None
|
11 |
+
|
12 |
+
|
13 |
+
def add_channel(chat_id: int, channel):
|
14 |
+
fsub.update_one({"chat_id": chat_id}, {"$set": {"channel": channel}}, upsert=True)
|
15 |
+
|
16 |
+
|
17 |
+
def disapprove(chat_id: int):
|
18 |
+
fsub.delete_one({"chat_id": chat_id})
|
Database/mongodb/karma_mongo.py
ADDED
@@ -0,0 +1,122 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Dict, Union
|
2 |
+
|
3 |
+
from pymongo import MongoClient
|
4 |
+
|
5 |
+
from Mikobot import DB_NAME, MONGO_DB_URI
|
6 |
+
|
7 |
+
client = MongoClient(MONGO_DB_URI)
|
8 |
+
db = client[DB_NAME]
|
9 |
+
|
10 |
+
coupledb = db.couple
|
11 |
+
karmadb = db.karma
|
12 |
+
|
13 |
+
|
14 |
+
async def _get_lovers(chat_id: int):
|
15 |
+
lovers = coupledb.find_one({"chat_id": chat_id})
|
16 |
+
if lovers:
|
17 |
+
lovers = lovers["couple"]
|
18 |
+
else:
|
19 |
+
lovers = {}
|
20 |
+
return lovers
|
21 |
+
|
22 |
+
|
23 |
+
async def get_couple(chat_id: int, date: str):
|
24 |
+
lovers = await _get_lovers(chat_id)
|
25 |
+
if date in lovers:
|
26 |
+
return lovers[date]
|
27 |
+
else:
|
28 |
+
return False
|
29 |
+
|
30 |
+
|
31 |
+
async def save_couple(chat_id: int, date: str, couple: dict):
|
32 |
+
lovers = await _get_lovers(chat_id)
|
33 |
+
lovers[date] = couple
|
34 |
+
coupledb.update_one({"chat_id": chat_id}, {"$set": {"couple": lovers}}, upsert=True)
|
35 |
+
|
36 |
+
|
37 |
+
async def get_karmas_count() -> dict:
|
38 |
+
chats = karmadb.find({"chat_id": {"$lt": 0}})
|
39 |
+
if not chats:
|
40 |
+
return {}
|
41 |
+
chats_count = 0
|
42 |
+
karmas_count = 0
|
43 |
+
for chat in await chats.to_list(length=1000000):
|
44 |
+
for i in chat["karma"]:
|
45 |
+
karma_ = chat["karma"][i]["karma"]
|
46 |
+
if karma_ > 0:
|
47 |
+
karmas_count += karma_
|
48 |
+
chats_count += 1
|
49 |
+
return {"chats_count": chats_count, "karmas_count": karmas_count}
|
50 |
+
|
51 |
+
|
52 |
+
async def user_global_karma(user_id) -> int:
|
53 |
+
chats = karmadb.find({"chat_id": {"$lt": 0}})
|
54 |
+
if not chats:
|
55 |
+
return 0
|
56 |
+
total_karma = 0
|
57 |
+
for chat in await chats.to_list(length=1000000):
|
58 |
+
karma = await get_karma(chat["chat_id"], await int_to_alpha(user_id))
|
59 |
+
if karma and (int(karma["karma"]) > 0):
|
60 |
+
total_karma += int(karma["karma"])
|
61 |
+
return total_karma
|
62 |
+
|
63 |
+
|
64 |
+
async def get_karmas(chat_id: int) -> Dict[str, int]:
|
65 |
+
karma = karmadb.find_one({"chat_id": chat_id})
|
66 |
+
if not karma:
|
67 |
+
return {}
|
68 |
+
return karma["karma"]
|
69 |
+
|
70 |
+
|
71 |
+
async def get_karma(chat_id: int, name: str) -> Union[bool, dict]:
|
72 |
+
name = name.lower().strip()
|
73 |
+
karmas = await get_karmas(chat_id)
|
74 |
+
if name in karmas:
|
75 |
+
return karmas[name]
|
76 |
+
|
77 |
+
|
78 |
+
async def update_karma(chat_id: int, name: str, karma: dict):
|
79 |
+
name = name.lower().strip()
|
80 |
+
karmas = await get_karmas(chat_id)
|
81 |
+
karmas[name] = karma
|
82 |
+
karmadb.update_one({"chat_id": chat_id}, {"$set": {"karma": karmas}}, upsert=True)
|
83 |
+
|
84 |
+
|
85 |
+
async def is_karma_on(chat_id: int) -> bool:
|
86 |
+
chat = karmadb.find_one({"chat_id_toggle": chat_id})
|
87 |
+
if not chat:
|
88 |
+
return True
|
89 |
+
return False
|
90 |
+
|
91 |
+
|
92 |
+
async def karma_on(chat_id: int):
|
93 |
+
is_karma = await is_karma_on(chat_id)
|
94 |
+
if is_karma:
|
95 |
+
return
|
96 |
+
return karmadb.delete_one({"chat_id_toggle": chat_id})
|
97 |
+
|
98 |
+
|
99 |
+
async def karma_off(chat_id: int):
|
100 |
+
is_karma = await is_karma_on(chat_id)
|
101 |
+
if not is_karma:
|
102 |
+
return
|
103 |
+
return karmadb.insert_one({"chat_id_toggle": chat_id})
|
104 |
+
|
105 |
+
|
106 |
+
async def int_to_alpha(user_id: int) -> str:
|
107 |
+
alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
|
108 |
+
text = ""
|
109 |
+
user_id = str(user_id)
|
110 |
+
for i in user_id:
|
111 |
+
text += alphabet[int(i)]
|
112 |
+
return text
|
113 |
+
|
114 |
+
|
115 |
+
async def alpha_to_int(user_id_alphabet: str) -> int:
|
116 |
+
alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
|
117 |
+
user_id = ""
|
118 |
+
for i in user_id_alphabet:
|
119 |
+
index = alphabet.index(i)
|
120 |
+
user_id += str(index)
|
121 |
+
user_id = int(user_id)
|
122 |
+
return user_id
|
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/mongodb.py
ADDED
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from sys import exit as exiter
|
2 |
+
|
3 |
+
from pymongo import MongoClient
|
4 |
+
from pymongo.errors import PyMongoError
|
5 |
+
|
6 |
+
from Mikobot import DB_NAME, LOGGER, MONGO_DB_URI
|
7 |
+
|
8 |
+
try:
|
9 |
+
Mikobot_db_client = MongoClient(MONGO_DB_URI)
|
10 |
+
except PyMongoError as f:
|
11 |
+
LOGGER.error(f"Error in Mongodb: {f}")
|
12 |
+
exiter(1)
|
13 |
+
Mikobot_main_db = Mikobot_db_client[DB_NAME]
|
14 |
+
|
15 |
+
|
16 |
+
class MongoDB:
|
17 |
+
"""Class for interacting with Bot database."""
|
18 |
+
|
19 |
+
def __init__(self, collection) -> None:
|
20 |
+
self.collection = Mikobot_main_db[collection]
|
21 |
+
|
22 |
+
# Insert one entry into collection
|
23 |
+
def insert_one(self, document):
|
24 |
+
result = self.collection.insert_one(document)
|
25 |
+
return repr(result.inserted_id)
|
26 |
+
|
27 |
+
# Find one entry from collection
|
28 |
+
def find_one(self, query):
|
29 |
+
result = self.collection.find_one(query)
|
30 |
+
if result:
|
31 |
+
return result
|
32 |
+
return False
|
33 |
+
|
34 |
+
# Find entries from collection
|
35 |
+
def find_all(self, query=None):
|
36 |
+
if query is None:
|
37 |
+
query = {}
|
38 |
+
return list(self.collection.find(query))
|
39 |
+
|
40 |
+
# Count entries from collection
|
41 |
+
def count(self, query=None):
|
42 |
+
if query is None:
|
43 |
+
query = {}
|
44 |
+
return self.collection.count_documents(query)
|
45 |
+
|
46 |
+
# Delete entry/entries from collection
|
47 |
+
def delete_one(self, query):
|
48 |
+
self.collection.delete_many(query)
|
49 |
+
return self.collection.count_documents({})
|
50 |
+
|
51 |
+
# Replace one entry in collection
|
52 |
+
def replace(self, query, new_data):
|
53 |
+
old = self.collection.find_one(query)
|
54 |
+
_id = old["_id"]
|
55 |
+
self.collection.replace_one({"_id": _id}, new_data)
|
56 |
+
new = self.collection.find_one({"_id": _id})
|
57 |
+
return old, new
|
58 |
+
|
59 |
+
# Update one entry from collection
|
60 |
+
def update(self, query, update):
|
61 |
+
result = self.collection.update_one(query, {"$set": update})
|
62 |
+
new_document = self.collection.find_one(query)
|
63 |
+
return result.modified_count, new_document
|
64 |
+
|
65 |
+
@staticmethod
|
66 |
+
def close():
|
67 |
+
return Mikobot_db_client.close()
|
68 |
+
|
69 |
+
|
70 |
+
def __connect_first():
|
71 |
+
_ = MongoDB("test")
|
72 |
+
LOGGER.info("Initialized Mongo Database!\n")
|
73 |
+
|
74 |
+
|
75 |
+
__connect_first()
|
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/toggle_mongo.py
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from Database.mongodb.db import *
|
2 |
+
|
3 |
+
dwelcomedb = dbname.dwelcome
|
4 |
+
nsfwdb = dbname.nsfw
|
5 |
+
nekomodedb = dbname.nekomode
|
6 |
+
|
7 |
+
|
8 |
+
async def is_dwelcome_on(chat_id: int) -> bool:
|
9 |
+
chat = await dwelcomedb.find_one({"chat_id_toggle": chat_id})
|
10 |
+
return not bool(chat)
|
11 |
+
|
12 |
+
|
13 |
+
async def dwelcome_on(chat_id: int):
|
14 |
+
await dwelcomedb.delete_one({"chat_id_toggle": chat_id})
|
15 |
+
|
16 |
+
|
17 |
+
async def dwelcome_off(chat_id: int):
|
18 |
+
await dwelcomedb.insert_one({"chat_id_toggle": chat_id})
|
19 |
+
|
20 |
+
|
21 |
+
async def is_nsfw_on(chat_id: int) -> bool:
|
22 |
+
chat = await nsfwdb.find_one({"chat_id": chat_id})
|
23 |
+
return chat
|
24 |
+
|
25 |
+
|
26 |
+
async def nsfw_on(chat_id: int):
|
27 |
+
is_nsfw = await is_nsfw_on(chat_id)
|
28 |
+
if is_nsfw:
|
29 |
+
return
|
30 |
+
return await nsfwdb.insert_one({"chat_id": chat_id})
|
31 |
+
|
32 |
+
|
33 |
+
async def nsfw_off(chat_id: int):
|
34 |
+
is_nsfw = await is_nsfw_on(chat_id)
|
35 |
+
if not is_nsfw:
|
36 |
+
return
|
37 |
+
return await nsfwdb.delete_one({"chat_id": chat_id})
|
38 |
+
|
39 |
+
|
40 |
+
async def is_nekomode_on(chat_id: int) -> bool:
|
41 |
+
chat = await nekomodedb.find_one({"chat_id_toggle": chat_id})
|
42 |
+
return not bool(chat)
|
43 |
+
|
44 |
+
|
45 |
+
async def nekomode_on(chat_id: int):
|
46 |
+
await nekomodedb.delete_one({"chat_id_toggle": chat_id})
|
47 |
+
|
48 |
+
|
49 |
+
async def nekomode_off(chat_id: int):
|
50 |
+
await nekomodedb.insert_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/mongodb/users_db.py
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from threading import RLock
|
2 |
+
from time import time
|
3 |
+
|
4 |
+
from Database.mongodb.mongodb import MongoDB
|
5 |
+
from Mikobot import LOGGER
|
6 |
+
|
7 |
+
INSERTION_LOCK = RLock()
|
8 |
+
|
9 |
+
|
10 |
+
class Users(MongoDB):
|
11 |
+
"""Class to manage users for bot."""
|
12 |
+
|
13 |
+
db_name = "users"
|
14 |
+
|
15 |
+
def __init__(self, user_id: int) -> None:
|
16 |
+
super().__init__(self.db_name)
|
17 |
+
self.user_id = user_id
|
18 |
+
self.user_info = self.__ensure_in_db()
|
19 |
+
|
20 |
+
def update_user(self, name: str, username: str = None):
|
21 |
+
with INSERTION_LOCK:
|
22 |
+
if name != self.user_info["name"] or username != self.user_info["username"]:
|
23 |
+
return self.update(
|
24 |
+
{"_id": self.user_id},
|
25 |
+
{"username": username, "name": name},
|
26 |
+
)
|
27 |
+
return True
|
28 |
+
|
29 |
+
def delete_user(self):
|
30 |
+
with INSERTION_LOCK:
|
31 |
+
return self.delete_one({"_id": self.user_id})
|
32 |
+
|
33 |
+
@staticmethod
|
34 |
+
def count_users():
|
35 |
+
with INSERTION_LOCK:
|
36 |
+
collection = MongoDB(Users.db_name)
|
37 |
+
return collection.count()
|
38 |
+
|
39 |
+
def get_my_info(self):
|
40 |
+
with INSERTION_LOCK:
|
41 |
+
return self.user_info
|
42 |
+
|
43 |
+
@staticmethod
|
44 |
+
def list_users():
|
45 |
+
with INSERTION_LOCK:
|
46 |
+
collection = MongoDB(Users.db_name)
|
47 |
+
return collection.find_all()
|
48 |
+
|
49 |
+
@staticmethod
|
50 |
+
def get_user_info(user_id: int or str):
|
51 |
+
with INSERTION_LOCK:
|
52 |
+
collection = MongoDB(Users.db_name)
|
53 |
+
if isinstance(user_id, int):
|
54 |
+
curr = collection.find_one({"_id": user_id})
|
55 |
+
elif isinstance(user_id, str):
|
56 |
+
# user_id[1:] because we don't want the '@' in the username
|
57 |
+
# search!
|
58 |
+
curr = collection.find_one({"username": user_id[1:]})
|
59 |
+
else:
|
60 |
+
curr = None
|
61 |
+
|
62 |
+
if curr:
|
63 |
+
return curr
|
64 |
+
|
65 |
+
return {}
|
66 |
+
|
67 |
+
def __ensure_in_db(self):
|
68 |
+
chat_data = self.find_one({"_id": self.user_id})
|
69 |
+
if not chat_data:
|
70 |
+
new_data = {"_id": self.user_id, "username": "", "name": "unknown_till_now"}
|
71 |
+
self.insert_one(new_data)
|
72 |
+
LOGGER.info(f"Initialized User Document for {self.user_id}")
|
73 |
+
return new_data
|
74 |
+
return chat_data
|
75 |
+
|
76 |
+
@staticmethod
|
77 |
+
def load_from_db():
|
78 |
+
with INSERTION_LOCK:
|
79 |
+
collection = MongoDB(Users.db_name)
|
80 |
+
return collection.find_all()
|
81 |
+
|
82 |
+
@staticmethod
|
83 |
+
def repair_db(collection):
|
84 |
+
all_data = collection.find_all()
|
85 |
+
keys = {"username": "", "name": "unknown_till_now"}
|
86 |
+
for data in all_data:
|
87 |
+
for key, val in keys.items():
|
88 |
+
try:
|
89 |
+
_ = data[key]
|
90 |
+
except KeyError:
|
91 |
+
LOGGER.warning(
|
92 |
+
f"Repairing Users Database - setting '{key}:{val}' for {data['_id']}",
|
93 |
+
)
|
94 |
+
collection.update({"_id": data["_id"]}, {key: val})
|
95 |
+
|
96 |
+
|
97 |
+
def __pre_req_users():
|
98 |
+
start = time()
|
99 |
+
LOGGER.info("Starting Users Database Repair...")
|
100 |
+
collection = MongoDB(Users.db_name)
|
101 |
+
Users.repair_db(collection)
|
102 |
+
LOGGER.info(f"Done in {round((time() - start), 3)}s!")
|
Database/mongodb/whispers.py
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from Database.mongodb.db import dbname
|
2 |
+
|
3 |
+
collection = dbname["whisper"]
|
4 |
+
|
5 |
+
|
6 |
+
class Whispers:
|
7 |
+
@staticmethod
|
8 |
+
async def add_whisper(WhisperId, WhisperData):
|
9 |
+
whisper = {"WhisperId": WhisperId, "whisperData": WhisperData}
|
10 |
+
await collection.insert_one(whisper)
|
11 |
+
|
12 |
+
@staticmethod
|
13 |
+
async def del_whisper(WhisperId):
|
14 |
+
await collection.delete_one({"WhisperId": WhisperId})
|
15 |
+
|
16 |
+
@staticmethod
|
17 |
+
async def get_whisper(WhisperId):
|
18 |
+
whisper = await collection.find_one({"WhisperId": WhisperId})
|
19 |
+
return whisper["whisperData"] if whisper else None
|
Database/sql/__init__.py
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from sqlalchemy import create_engine
|
2 |
+
from sqlalchemy.ext.declarative import declarative_base
|
3 |
+
from sqlalchemy.orm import scoped_session, sessionmaker
|
4 |
+
|
5 |
+
from Mikobot import DB_URI
|
6 |
+
from Mikobot import LOGGER as log
|
7 |
+
|
8 |
+
if DB_URI and DB_URI.startswith("postgres://"):
|
9 |
+
DB_URI = DB_URI.replace("postgres://", "postgresql://", 1)
|
10 |
+
|
11 |
+
|
12 |
+
def start() -> scoped_session:
|
13 |
+
engine = create_engine(DB_URI, client_encoding="utf8")
|
14 |
+
log.info("[PostgreSQL] Connecting to database......")
|
15 |
+
BASE.metadata.bind = engine
|
16 |
+
BASE.metadata.create_all(engine)
|
17 |
+
return scoped_session(sessionmaker(bind=engine, autoflush=False))
|
18 |
+
|
19 |
+
|
20 |
+
BASE = declarative_base()
|
21 |
+
try:
|
22 |
+
SESSION = start()
|
23 |
+
except Exception as e:
|
24 |
+
log.exception(f"[PostgreSQL] Failed to connect due to {e}")
|
25 |
+
exit()
|
26 |
+
|
27 |
+
log.info("[PostgreSQL] Connection successful, session started.")
|
Database/sql/afk_sql.py
ADDED
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import threading
|
2 |
+
from datetime import datetime
|
3 |
+
|
4 |
+
from sqlalchemy import BigInteger, Boolean, Column, DateTime, UnicodeText
|
5 |
+
|
6 |
+
from Database.sql import BASE, SESSION
|
7 |
+
|
8 |
+
|
9 |
+
class AFK(BASE):
|
10 |
+
__tablename__ = "afk_user"
|
11 |
+
|
12 |
+
user_id = Column(BigInteger, primary_key=True)
|
13 |
+
is_afk = Column(Boolean)
|
14 |
+
reason = Column(UnicodeText)
|
15 |
+
time = Column(DateTime)
|
16 |
+
|
17 |
+
def __init__(self, user_id: int, reason: str = "", is_afk: bool = True):
|
18 |
+
self.user_id = user_id
|
19 |
+
self.reason = reason
|
20 |
+
self.is_afk = is_afk
|
21 |
+
self.time = datetime.now()
|
22 |
+
|
23 |
+
def __repr__(self):
|
24 |
+
return "afk_status for {}".format(self.user_id)
|
25 |
+
|
26 |
+
|
27 |
+
AFK.__table__.create(checkfirst=True)
|
28 |
+
INSERTION_LOCK = threading.RLock()
|
29 |
+
|
30 |
+
AFK_USERS = {}
|
31 |
+
|
32 |
+
|
33 |
+
def is_afk(user_id):
|
34 |
+
return user_id in AFK_USERS
|
35 |
+
|
36 |
+
|
37 |
+
def check_afk_status(user_id):
|
38 |
+
try:
|
39 |
+
return SESSION.query(AFK).get(user_id)
|
40 |
+
finally:
|
41 |
+
SESSION.close()
|
42 |
+
|
43 |
+
|
44 |
+
def set_afk(user_id, reason=""):
|
45 |
+
with INSERTION_LOCK:
|
46 |
+
curr = SESSION.query(AFK).get(user_id)
|
47 |
+
if not curr:
|
48 |
+
curr = AFK(user_id, reason, True)
|
49 |
+
else:
|
50 |
+
curr.is_afk = True
|
51 |
+
|
52 |
+
AFK_USERS[user_id] = {"reason": reason, "time": curr.time}
|
53 |
+
|
54 |
+
SESSION.add(curr)
|
55 |
+
SESSION.commit()
|
56 |
+
|
57 |
+
|
58 |
+
def rm_afk(user_id):
|
59 |
+
with INSERTION_LOCK:
|
60 |
+
curr = SESSION.query(AFK).get(user_id)
|
61 |
+
if curr:
|
62 |
+
if user_id in AFK_USERS: # sanity check
|
63 |
+
del AFK_USERS[user_id]
|
64 |
+
|
65 |
+
SESSION.delete(curr)
|
66 |
+
SESSION.commit()
|
67 |
+
return True
|
68 |
+
|
69 |
+
SESSION.close()
|
70 |
+
return False
|
71 |
+
|
72 |
+
|
73 |
+
def toggle_afk(user_id, reason=""):
|
74 |
+
with INSERTION_LOCK:
|
75 |
+
curr = SESSION.query(AFK).get(user_id)
|
76 |
+
if not curr:
|
77 |
+
curr = AFK(user_id, reason, True)
|
78 |
+
elif curr.is_afk:
|
79 |
+
curr.is_afk = False
|
80 |
+
elif not curr.is_afk:
|
81 |
+
curr.is_afk = True
|
82 |
+
SESSION.add(curr)
|
83 |
+
SESSION.commit()
|
84 |
+
|
85 |
+
|
86 |
+
def __load_afk_users():
|
87 |
+
global AFK_USERS
|
88 |
+
try:
|
89 |
+
all_afk = SESSION.query(AFK).all()
|
90 |
+
AFK_USERS = {
|
91 |
+
user.user_id: {"reason": user.reason, "time": user.time}
|
92 |
+
for user in all_afk
|
93 |
+
if user.is_afk
|
94 |
+
}
|
95 |
+
finally:
|
96 |
+
SESSION.close()
|
97 |
+
|
98 |
+
|
99 |
+
__load_afk_users()
|
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
ADDED
@@ -0,0 +1,171 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
31 |
+
DEF_COUNT = 1
|
32 |
+
DEF_LIMIT = 0
|
33 |
+
DEF_OBJ = (None, DEF_COUNT, DEF_LIMIT)
|
34 |
+
|
35 |
+
|
36 |
+
class FloodControl(BASE):
|
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"):
|
57 |
+
self.chat_id = str(chat_id)
|
58 |
+
self.flood_type = flood_type
|
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)
|
66 |
+
FloodSettings.__table__.create(checkfirst=True)
|
67 |
+
|
68 |
+
INSERTION_FLOOD_LOCK = threading.RLock()
|
69 |
+
INSERTION_FLOOD_SETTINGS_LOCK = threading.RLock()
|
70 |
+
|
71 |
+
CHAT_FLOOD = {}
|
72 |
+
|
73 |
+
|
74 |
+
def set_flood(chat_id, amount):
|
75 |
+
with INSERTION_FLOOD_LOCK:
|
76 |
+
flood = SESSION.query(FloodControl).get(str(chat_id))
|
77 |
+
if not flood:
|
78 |
+
flood = FloodControl(str(chat_id))
|
79 |
+
|
80 |
+
flood.user_id = None
|
81 |
+
flood.limit = amount
|
82 |
+
|
83 |
+
CHAT_FLOOD[str(chat_id)] = (None, DEF_COUNT, amount)
|
84 |
+
|
85 |
+
SESSION.add(flood)
|
86 |
+
SESSION.commit()
|
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:
|
127 |
+
curr_setting = FloodSettings(
|
128 |
+
chat_id,
|
129 |
+
flood_type=int(flood_type),
|
130 |
+
value=value,
|
131 |
+
)
|
132 |
+
|
133 |
+
curr_setting.flood_type = int(flood_type)
|
134 |
+
curr_setting.value = str(value)
|
135 |
+
|
136 |
+
SESSION.add(curr_setting)
|
137 |
+
SESSION.commit()
|
138 |
+
|
139 |
+
|
140 |
+
def get_flood_setting(chat_id):
|
141 |
+
try:
|
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()
|
149 |
+
|
150 |
+
|
151 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
152 |
+
with INSERTION_FLOOD_LOCK:
|
153 |
+
flood = SESSION.query(FloodControl).get(str(old_chat_id))
|
154 |
+
if flood:
|
155 |
+
CHAT_FLOOD[str(new_chat_id)] = CHAT_FLOOD.get(str(old_chat_id), DEF_OBJ)
|
156 |
+
flood.chat_id = str(new_chat_id)
|
157 |
+
SESSION.commit()
|
158 |
+
|
159 |
+
SESSION.close()
|
160 |
+
|
161 |
+
|
162 |
+
def __load_flood_settings():
|
163 |
+
global CHAT_FLOOD
|
164 |
+
try:
|
165 |
+
all_chats = SESSION.query(FloodControl).all()
|
166 |
+
CHAT_FLOOD = {chat.chat_id: (None, DEF_COUNT, chat.limit) for chat in all_chats}
|
167 |
+
finally:
|
168 |
+
SESSION.close()
|
169 |
+
|
170 |
+
|
171 |
+
__load_flood_settings()
|
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
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
28 |
+
|
29 |
+
from Database.sql import BASE, SESSION
|
30 |
+
|
31 |
+
|
32 |
+
class Approvals(BASE):
|
33 |
+
__tablename__ = "approval"
|
34 |
+
chat_id = Column(String(14), primary_key=True)
|
35 |
+
user_id = Column(BigInteger, primary_key=True)
|
36 |
+
|
37 |
+
def __init__(self, chat_id, user_id):
|
38 |
+
self.chat_id = str(chat_id) # ensure 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)
|
46 |
+
|
47 |
+
APPROVE_INSERTION_LOCK = threading.RLock()
|
48 |
+
|
49 |
+
|
50 |
+
def approve(chat_id, user_id):
|
51 |
+
with APPROVE_INSERTION_LOCK:
|
52 |
+
approve_user = Approvals(str(chat_id), user_id)
|
53 |
+
SESSION.add(approve_user)
|
54 |
+
SESSION.commit()
|
55 |
+
|
56 |
+
|
57 |
+
def is_approved(chat_id, user_id):
|
58 |
+
try:
|
59 |
+
return SESSION.query(Approvals).get((str(chat_id), user_id))
|
60 |
+
finally:
|
61 |
+
SESSION.close()
|
62 |
+
|
63 |
+
|
64 |
+
def disapprove(chat_id, user_id):
|
65 |
+
with APPROVE_INSERTION_LOCK:
|
66 |
+
disapprove_user = SESSION.query(Approvals).get((str(chat_id), user_id))
|
67 |
+
if disapprove_user:
|
68 |
+
SESSION.delete(disapprove_user)
|
69 |
+
SESSION.commit()
|
70 |
+
return True
|
71 |
+
else:
|
72 |
+
SESSION.close()
|
73 |
+
return False
|
74 |
+
|
75 |
+
|
76 |
+
def list_approved(chat_id):
|
77 |
+
try:
|
78 |
+
return (
|
79 |
+
SESSION.query(Approvals)
|
80 |
+
.filter(Approvals.chat_id == str(chat_id))
|
81 |
+
.order_by(Approvals.user_id.asc())
|
82 |
+
.all()
|
83 |
+
)
|
84 |
+
finally:
|
85 |
+
SESSION.close()
|
Database/sql/blacklist_sql.py
ADDED
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
31 |
+
|
32 |
+
class BlackListFilters(BASE):
|
33 |
+
__tablename__ = "blacklist"
|
34 |
+
chat_id = Column(String(14), primary_key=True)
|
35 |
+
trigger = Column(UnicodeText, primary_key=True, nullable=False)
|
36 |
+
|
37 |
+
def __init__(self, chat_id, trigger):
|
38 |
+
self.chat_id = str(chat_id) # ensure string
|
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(
|
46 |
+
isinstance(other, BlackListFilters)
|
47 |
+
and self.chat_id == other.chat_id
|
48 |
+
and self.trigger == other.trigger,
|
49 |
+
)
|
50 |
+
|
51 |
+
|
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"):
|
59 |
+
self.chat_id = str(chat_id)
|
60 |
+
self.blacklist_type = blacklist_type
|
61 |
+
self.value = value
|
62 |
+
|
63 |
+
def __repr__(self):
|
64 |
+
return "<{} ᴡɪʟʟ ᴇxᴇᴄᴜᴛɪɴɢ {} ғᴏʀ ʙʟᴀᴄᴋʟɪsᴛ ᴛʀɪɢɢᴇʀ.>".format(
|
65 |
+
self.chat_id,
|
66 |
+
self.blacklist_type,
|
67 |
+
)
|
68 |
+
|
69 |
+
|
70 |
+
BlackListFilters.__table__.create(checkfirst=True)
|
71 |
+
BlacklistSettings.__table__.create(checkfirst=True)
|
72 |
+
|
73 |
+
BLACKLIST_FILTER_INSERTION_LOCK = threading.RLock()
|
74 |
+
BLACKLIST_SETTINGS_INSERTION_LOCK = threading.RLock()
|
75 |
+
|
76 |
+
CHAT_BLACKLISTS = {}
|
77 |
+
CHAT_SETTINGS_BLACKLISTS = {}
|
78 |
+
|
79 |
+
|
80 |
+
def add_to_blacklist(chat_id, trigger):
|
81 |
+
with BLACKLIST_FILTER_INSERTION_LOCK:
|
82 |
+
blacklist_filt = BlackListFilters(str(chat_id), trigger)
|
83 |
+
|
84 |
+
SESSION.merge(blacklist_filt) # merge to avoid duplicate key issues
|
85 |
+
SESSION.commit()
|
86 |
+
global CHAT_BLACKLISTS
|
87 |
+
if CHAT_BLACKLISTS.get(str(chat_id), set()) == set():
|
88 |
+
CHAT_BLACKLISTS[str(chat_id)] = {trigger}
|
89 |
+
else:
|
90 |
+
CHAT_BLACKLISTS.get(str(chat_id), set()).add(trigger)
|
91 |
+
|
92 |
+
|
93 |
+
def rm_from_blacklist(chat_id, trigger):
|
94 |
+
with BLACKLIST_FILTER_INSERTION_LOCK:
|
95 |
+
blacklist_filt = SESSION.query(BlackListFilters).get((str(chat_id), trigger))
|
96 |
+
if blacklist_filt:
|
97 |
+
if trigger in CHAT_BLACKLISTS.get(str(chat_id), set()): # sanity check
|
98 |
+
CHAT_BLACKLISTS.get(str(chat_id), set()).remove(trigger)
|
99 |
+
|
100 |
+
SESSION.delete(blacklist_filt)
|
101 |
+
SESSION.commit()
|
102 |
+
return True
|
103 |
+
|
104 |
+
SESSION.close()
|
105 |
+
return False
|
106 |
+
|
107 |
+
|
108 |
+
def get_chat_blacklist(chat_id):
|
109 |
+
return CHAT_BLACKLISTS.get(str(chat_id), set())
|
110 |
+
|
111 |
+
|
112 |
+
def num_blacklist_filters():
|
113 |
+
try:
|
114 |
+
return SESSION.query(BlackListFilters).count()
|
115 |
+
finally:
|
116 |
+
SESSION.close()
|
117 |
+
|
118 |
+
|
119 |
+
def num_blacklist_chat_filters(chat_id):
|
120 |
+
try:
|
121 |
+
return (
|
122 |
+
SESSION.query(BlackListFilters.chat_id)
|
123 |
+
.filter(BlackListFilters.chat_id == str(chat_id))
|
124 |
+
.count()
|
125 |
+
)
|
126 |
+
finally:
|
127 |
+
SESSION.close()
|
128 |
+
|
129 |
+
|
130 |
+
def num_blacklist_filter_chats():
|
131 |
+
try:
|
132 |
+
return SESSION.query(func.count(distinct(BlackListFilters.chat_id))).scalar()
|
133 |
+
finally:
|
134 |
+
SESSION.close()
|
135 |
+
|
136 |
+
|
137 |
+
def set_blacklist_strength(chat_id, blacklist_type, value):
|
138 |
+
# for blacklist_type
|
139 |
+
# 0 = nothing
|
140 |
+
# 1 = delete
|
141 |
+
# 2 = warn
|
142 |
+
# 3 = mute
|
143 |
+
# 4 = kick
|
144 |
+
# 5 = ban
|
145 |
+
# 6 = tban
|
146 |
+
# 7 = tmute
|
147 |
+
with BLACKLIST_SETTINGS_INSERTION_LOCK:
|
148 |
+
global CHAT_SETTINGS_BLACKLISTS
|
149 |
+
curr_setting = SESSION.query(BlacklistSettings).get(str(chat_id))
|
150 |
+
if not curr_setting:
|
151 |
+
curr_setting = BlacklistSettings(
|
152 |
+
chat_id,
|
153 |
+
blacklist_type=int(blacklist_type),
|
154 |
+
value=value,
|
155 |
+
)
|
156 |
+
|
157 |
+
curr_setting.blacklist_type = int(blacklist_type)
|
158 |
+
curr_setting.value = str(value)
|
159 |
+
CHAT_SETTINGS_BLACKLISTS[str(chat_id)] = {
|
160 |
+
"blacklist_type": int(blacklist_type),
|
161 |
+
"value": value,
|
162 |
+
}
|
163 |
+
|
164 |
+
SESSION.add(curr_setting)
|
165 |
+
SESSION.commit()
|
166 |
+
|
167 |
+
|
168 |
+
def get_blacklist_setting(chat_id):
|
169 |
+
try:
|
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()
|
177 |
+
|
178 |
+
|
179 |
+
def __load_chat_blacklists():
|
180 |
+
global CHAT_BLACKLISTS
|
181 |
+
try:
|
182 |
+
chats = SESSION.query(BlackListFilters.chat_id).distinct().all()
|
183 |
+
for (chat_id,) in chats: # remove tuple by ( ,)
|
184 |
+
CHAT_BLACKLISTS[chat_id] = []
|
185 |
+
|
186 |
+
all_filters = SESSION.query(BlackListFilters).all()
|
187 |
+
for x in all_filters:
|
188 |
+
CHAT_BLACKLISTS[x.chat_id] += [x.trigger]
|
189 |
+
|
190 |
+
CHAT_BLACKLISTS = {x: set(y) for x, y in CHAT_BLACKLISTS.items()}
|
191 |
+
|
192 |
+
finally:
|
193 |
+
SESSION.close()
|
194 |
+
|
195 |
+
|
196 |
+
def __load_chat_settings_blacklists():
|
197 |
+
global CHAT_SETTINGS_BLACKLISTS
|
198 |
+
try:
|
199 |
+
chats_settings = SESSION.query(BlacklistSettings).all()
|
200 |
+
for x in chats_settings: # remove tuple by ( ,)
|
201 |
+
CHAT_SETTINGS_BLACKLISTS[x.chat_id] = {
|
202 |
+
"blacklist_type": x.blacklist_type,
|
203 |
+
"value": x.value,
|
204 |
+
}
|
205 |
+
|
206 |
+
finally:
|
207 |
+
SESSION.close()
|
208 |
+
|
209 |
+
|
210 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
211 |
+
with BLACKLIST_FILTER_INSERTION_LOCK:
|
212 |
+
chat_filters = (
|
213 |
+
SESSION.query(BlackListFilters)
|
214 |
+
.filter(BlackListFilters.chat_id == str(old_chat_id))
|
215 |
+
.all()
|
216 |
+
)
|
217 |
+
for filt in chat_filters:
|
218 |
+
filt.chat_id = str(new_chat_id)
|
219 |
+
SESSION.commit()
|
220 |
+
|
221 |
+
|
222 |
+
__load_chat_blacklists()
|
223 |
+
__load_chat_settings_blacklists()
|
Database/sql/blacklistusers_sql.py
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
28 |
+
|
29 |
+
from Database.sql import BASE, SESSION
|
30 |
+
|
31 |
+
|
32 |
+
class BlacklistUsers(BASE):
|
33 |
+
__tablename__ = "blacklistusers"
|
34 |
+
user_id = Column(String(14), primary_key=True)
|
35 |
+
reason = Column(UnicodeText)
|
36 |
+
|
37 |
+
def __init__(self, user_id, reason=None):
|
38 |
+
self.user_id = user_id
|
39 |
+
self.reason = reason
|
40 |
+
|
41 |
+
|
42 |
+
BlacklistUsers.__table__.create(checkfirst=True)
|
43 |
+
|
44 |
+
BLACKLIST_LOCK = threading.RLock()
|
45 |
+
BLACKLIST_USERS = set()
|
46 |
+
|
47 |
+
|
48 |
+
def blacklist_user(user_id, reason=None):
|
49 |
+
with BLACKLIST_LOCK:
|
50 |
+
user = SESSION.query(BlacklistUsers).get(str(user_id))
|
51 |
+
if not user:
|
52 |
+
user = BlacklistUsers(str(user_id), reason)
|
53 |
+
else:
|
54 |
+
user.reason = reason
|
55 |
+
|
56 |
+
SESSION.add(user)
|
57 |
+
SESSION.commit()
|
58 |
+
__load_blacklist_userid_list()
|
59 |
+
|
60 |
+
|
61 |
+
def unblacklist_user(user_id):
|
62 |
+
with BLACKLIST_LOCK:
|
63 |
+
user = SESSION.query(BlacklistUsers).get(str(user_id))
|
64 |
+
if user:
|
65 |
+
SESSION.delete(user)
|
66 |
+
|
67 |
+
SESSION.commit()
|
68 |
+
__load_blacklist_userid_list()
|
69 |
+
|
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 |
+
|
77 |
+
|
78 |
+
def is_user_blacklisted(user_id):
|
79 |
+
return user_id in BLACKLIST_USERS
|
80 |
+
|
81 |
+
|
82 |
+
def __load_blacklist_userid_list():
|
83 |
+
global BLACKLIST_USERS
|
84 |
+
try:
|
85 |
+
BLACKLIST_USERS = {int(x.user_id) for x in SESSION.query(BlacklistUsers).all()}
|
86 |
+
finally:
|
87 |
+
SESSION.close()
|
88 |
+
|
89 |
+
|
90 |
+
__load_blacklist_userid_list()
|
Database/sql/blsticker_sql.py
ADDED
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
31 |
+
|
32 |
+
class StickersFilters(BASE):
|
33 |
+
__tablename__ = "blacklist_stickers"
|
34 |
+
chat_id = Column(String(14), primary_key=True)
|
35 |
+
trigger = Column(UnicodeText, primary_key=True, nullable=False)
|
36 |
+
|
37 |
+
def __init__(self, chat_id, trigger):
|
38 |
+
self.chat_id = str(chat_id) # ensure string
|
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(
|
46 |
+
isinstance(other, StickersFilters)
|
47 |
+
and self.chat_id == other.chat_id
|
48 |
+
and self.trigger == other.trigger,
|
49 |
+
)
|
50 |
+
|
51 |
+
|
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"):
|
59 |
+
self.chat_id = str(chat_id)
|
60 |
+
self.blacklist_type = blacklist_type
|
61 |
+
self.value = value
|
62 |
+
|
63 |
+
def __repr__(self):
|
64 |
+
return "<{} ᴡɪʟʟ ᴇxᴇᴄᴜᴛɪɴɢ {} ғᴏʀ ʙʟᴀᴄᴋʟɪsᴛ ᴛʀɪɢɢᴇʀ.>".format(
|
65 |
+
self.chat_id,
|
66 |
+
self.blacklist_type,
|
67 |
+
)
|
68 |
+
|
69 |
+
|
70 |
+
StickersFilters.__table__.create(checkfirst=True)
|
71 |
+
StickerSettings.__table__.create(checkfirst=True)
|
72 |
+
|
73 |
+
STICKERS_FILTER_INSERTION_LOCK = threading.RLock()
|
74 |
+
STICKSET_FILTER_INSERTION_LOCK = threading.RLock()
|
75 |
+
|
76 |
+
CHAT_STICKERS = {}
|
77 |
+
CHAT_BLSTICK_BLACKLISTS = {}
|
78 |
+
|
79 |
+
|
80 |
+
def add_to_stickers(chat_id, trigger):
|
81 |
+
with STICKERS_FILTER_INSERTION_LOCK:
|
82 |
+
stickers_filt = StickersFilters(str(chat_id), trigger)
|
83 |
+
|
84 |
+
SESSION.merge(stickers_filt) # merge to avoid duplicate key issues
|
85 |
+
SESSION.commit()
|
86 |
+
global CHAT_STICKERS
|
87 |
+
if CHAT_STICKERS.get(str(chat_id), set()) == set():
|
88 |
+
CHAT_STICKERS[str(chat_id)] = {trigger}
|
89 |
+
else:
|
90 |
+
CHAT_STICKERS.get(str(chat_id), set()).add(trigger)
|
91 |
+
|
92 |
+
|
93 |
+
def rm_from_stickers(chat_id, trigger):
|
94 |
+
with STICKERS_FILTER_INSERTION_LOCK:
|
95 |
+
stickers_filt = SESSION.query(StickersFilters).get((str(chat_id), trigger))
|
96 |
+
if stickers_filt:
|
97 |
+
if trigger in CHAT_STICKERS.get(str(chat_id), set()): # sanity check
|
98 |
+
CHAT_STICKERS.get(str(chat_id), set()).remove(trigger)
|
99 |
+
|
100 |
+
SESSION.delete(stickers_filt)
|
101 |
+
SESSION.commit()
|
102 |
+
return True
|
103 |
+
|
104 |
+
SESSION.close()
|
105 |
+
return False
|
106 |
+
|
107 |
+
|
108 |
+
def get_chat_stickers(chat_id):
|
109 |
+
return CHAT_STICKERS.get(str(chat_id), set())
|
110 |
+
|
111 |
+
|
112 |
+
def num_stickers_filters():
|
113 |
+
try:
|
114 |
+
return SESSION.query(StickersFilters).count()
|
115 |
+
finally:
|
116 |
+
SESSION.close()
|
117 |
+
|
118 |
+
|
119 |
+
def num_stickers_chat_filters(chat_id):
|
120 |
+
try:
|
121 |
+
return (
|
122 |
+
SESSION.query(StickersFilters.chat_id)
|
123 |
+
.filter(StickersFilters.chat_id == str(chat_id))
|
124 |
+
.count()
|
125 |
+
)
|
126 |
+
finally:
|
127 |
+
SESSION.close()
|
128 |
+
|
129 |
+
|
130 |
+
def num_stickers_filter_chats():
|
131 |
+
try:
|
132 |
+
return SESSION.query(func.count(distinct(StickersFilters.chat_id))).scalar()
|
133 |
+
finally:
|
134 |
+
SESSION.close()
|
135 |
+
|
136 |
+
|
137 |
+
def set_blacklist_strength(chat_id, blacklist_type, value):
|
138 |
+
# for blacklist_type
|
139 |
+
# 0 = nothing
|
140 |
+
# 1 = delete
|
141 |
+
# 2 = warn
|
142 |
+
# 3 = mute
|
143 |
+
# 4 = kick
|
144 |
+
# 5 = ban
|
145 |
+
# 6 = tban
|
146 |
+
# 7 = tmute
|
147 |
+
with STICKSET_FILTER_INSERTION_LOCK:
|
148 |
+
global CHAT_BLSTICK_BLACKLISTS
|
149 |
+
curr_setting = SESSION.query(StickerSettings).get(str(chat_id))
|
150 |
+
if not curr_setting:
|
151 |
+
curr_setting = StickerSettings(
|
152 |
+
chat_id,
|
153 |
+
blacklist_type=int(blacklist_type),
|
154 |
+
value=value,
|
155 |
+
)
|
156 |
+
|
157 |
+
curr_setting.blacklist_type = int(blacklist_type)
|
158 |
+
curr_setting.value = str(value)
|
159 |
+
CHAT_BLSTICK_BLACKLISTS[str(chat_id)] = {
|
160 |
+
"blacklist_type": int(blacklist_type),
|
161 |
+
"value": value,
|
162 |
+
}
|
163 |
+
|
164 |
+
SESSION.add(curr_setting)
|
165 |
+
SESSION.commit()
|
166 |
+
|
167 |
+
|
168 |
+
def get_blacklist_setting(chat_id):
|
169 |
+
try:
|
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()
|
177 |
+
|
178 |
+
|
179 |
+
def __load_CHAT_STICKERS():
|
180 |
+
global CHAT_STICKERS
|
181 |
+
try:
|
182 |
+
chats = SESSION.query(StickersFilters.chat_id).distinct().all()
|
183 |
+
for (chat_id,) in chats: # remove tuple by ( ,)
|
184 |
+
CHAT_STICKERS[chat_id] = []
|
185 |
+
|
186 |
+
all_filters = SESSION.query(StickersFilters).all()
|
187 |
+
for x in all_filters:
|
188 |
+
CHAT_STICKERS[x.chat_id] += [x.trigger]
|
189 |
+
|
190 |
+
CHAT_STICKERS = {x: set(y) for x, y in CHAT_STICKERS.items()}
|
191 |
+
|
192 |
+
finally:
|
193 |
+
SESSION.close()
|
194 |
+
|
195 |
+
|
196 |
+
def __load_chat_stickerset_blacklists():
|
197 |
+
global CHAT_BLSTICK_BLACKLISTS
|
198 |
+
try:
|
199 |
+
chats_settings = SESSION.query(StickerSettings).all()
|
200 |
+
for x in chats_settings: # remove tuple by ( ,)
|
201 |
+
CHAT_BLSTICK_BLACKLISTS[x.chat_id] = {
|
202 |
+
"blacklist_type": x.blacklist_type,
|
203 |
+
"value": x.value,
|
204 |
+
}
|
205 |
+
|
206 |
+
finally:
|
207 |
+
SESSION.close()
|
208 |
+
|
209 |
+
|
210 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
211 |
+
with STICKERS_FILTER_INSERTION_LOCK:
|
212 |
+
chat_filters = (
|
213 |
+
SESSION.query(StickersFilters)
|
214 |
+
.filter(StickersFilters.chat_id == str(old_chat_id))
|
215 |
+
.all()
|
216 |
+
)
|
217 |
+
for filt in chat_filters:
|
218 |
+
filt.chat_id = str(new_chat_id)
|
219 |
+
SESSION.commit()
|
220 |
+
|
221 |
+
|
222 |
+
__load_CHAT_STICKERS()
|
223 |
+
__load_chat_stickerset_blacklists()
|
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
ADDED
@@ -0,0 +1,230 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
28 |
+
|
29 |
+
from sqlalchemy import BigInteger, Boolean, Column, String, UnicodeText
|
30 |
+
|
31 |
+
from Database.sql import BASE, SESSION
|
32 |
+
|
33 |
+
|
34 |
+
class ChatAccessConnectionSettings(BASE):
|
35 |
+
__tablename__ = "access_connection"
|
36 |
+
chat_id = Column(String(14), primary_key=True)
|
37 |
+
allow_connect_to_chat = Column(Boolean, default=True)
|
38 |
+
|
39 |
+
def __init__(self, chat_id, allow_connect_to_chat):
|
40 |
+
self.chat_id = str(chat_id)
|
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 |
+
|
50 |
+
class Connection(BASE):
|
51 |
+
__tablename__ = "connection"
|
52 |
+
user_id = Column(BigInteger, primary_key=True)
|
53 |
+
chat_id = Column(String(14))
|
54 |
+
|
55 |
+
def __init__(self, user_id, chat_id):
|
56 |
+
self.user_id = user_id
|
57 |
+
self.chat_id = str(chat_id) # Ensure String
|
58 |
+
|
59 |
+
|
60 |
+
class ConnectionHistory(BASE):
|
61 |
+
__tablename__ = "connection_history"
|
62 |
+
user_id = Column(BigInteger, primary_key=True)
|
63 |
+
chat_id = Column(String(14), primary_key=True)
|
64 |
+
chat_name = Column(UnicodeText)
|
65 |
+
conn_time = Column(BigInteger)
|
66 |
+
|
67 |
+
def __init__(self, user_id, chat_id, chat_name, conn_time):
|
68 |
+
self.user_id = user_id
|
69 |
+
self.chat_id = str(chat_id)
|
70 |
+
self.chat_name = str(chat_name)
|
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)
|
78 |
+
Connection.__table__.create(checkfirst=True)
|
79 |
+
ConnectionHistory.__table__.create(checkfirst=True)
|
80 |
+
|
81 |
+
CHAT_ACCESS_LOCK = threading.RLock()
|
82 |
+
CONNECTION_INSERTION_LOCK = threading.RLock()
|
83 |
+
CONNECTION_HISTORY_LOCK = threading.RLock()
|
84 |
+
|
85 |
+
HISTORY_CONNECT = {}
|
86 |
+
|
87 |
+
|
88 |
+
def allow_connect_to_chat(chat_id: Union[str, int]) -> bool:
|
89 |
+
try:
|
90 |
+
chat_setting = SESSION.query(ChatAccessConnectionSettings).get(str(chat_id))
|
91 |
+
if chat_setting:
|
92 |
+
return chat_setting.allow_connect_to_chat
|
93 |
+
return False
|
94 |
+
finally:
|
95 |
+
SESSION.close()
|
96 |
+
|
97 |
+
|
98 |
+
def set_allow_connect_to_chat(chat_id: Union[int, str], setting: bool):
|
99 |
+
with CHAT_ACCESS_LOCK:
|
100 |
+
chat_setting = SESSION.query(ChatAccessConnectionSettings).get(str(chat_id))
|
101 |
+
if not chat_setting:
|
102 |
+
chat_setting = ChatAccessConnectionSettings(chat_id, setting)
|
103 |
+
|
104 |
+
chat_setting.allow_connect_to_chat = setting
|
105 |
+
SESSION.add(chat_setting)
|
106 |
+
SESSION.commit()
|
107 |
+
|
108 |
+
|
109 |
+
def connect(user_id, chat_id):
|
110 |
+
with CONNECTION_INSERTION_LOCK:
|
111 |
+
prev = SESSION.query(Connection).get((int(user_id)))
|
112 |
+
if prev:
|
113 |
+
SESSION.delete(prev)
|
114 |
+
connect_to_chat = Connection(int(user_id), chat_id)
|
115 |
+
SESSION.add(connect_to_chat)
|
116 |
+
SESSION.commit()
|
117 |
+
return True
|
118 |
+
|
119 |
+
|
120 |
+
def get_connected_chat(user_id):
|
121 |
+
try:
|
122 |
+
return SESSION.query(Connection).get((int(user_id)))
|
123 |
+
finally:
|
124 |
+
SESSION.close()
|
125 |
+
|
126 |
+
|
127 |
+
def curr_connection(chat_id):
|
128 |
+
try:
|
129 |
+
return SESSION.query(Connection).get((str(chat_id)))
|
130 |
+
finally:
|
131 |
+
SESSION.close()
|
132 |
+
|
133 |
+
|
134 |
+
def disconnect(user_id):
|
135 |
+
with CONNECTION_INSERTION_LOCK:
|
136 |
+
disconnect = SESSION.query(Connection).get((int(user_id)))
|
137 |
+
if disconnect:
|
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):
|
146 |
+
global HISTORY_CONNECT
|
147 |
+
with CONNECTION_HISTORY_LOCK:
|
148 |
+
conn_time = int(time.time())
|
149 |
+
if HISTORY_CONNECT.get(int(user_id)):
|
150 |
+
counting = (
|
151 |
+
SESSION.query(ConnectionHistory.user_id)
|
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)
|
167 |
+
HISTORY_CONNECT[int(user_id)].pop(todeltime)
|
168 |
+
elif counting >= 5:
|
169 |
+
todel = list(HISTORY_CONNECT[int(user_id)])
|
170 |
+
todel.reverse()
|
171 |
+
todel = todel[4:]
|
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)
|
179 |
+
HISTORY_CONNECT[int(user_id)].pop(x)
|
180 |
+
else:
|
181 |
+
HISTORY_CONNECT[int(user_id)] = {}
|
182 |
+
delold = SESSION.query(ConnectionHistory).get((int(user_id), str(chat_id)))
|
183 |
+
if delold:
|
184 |
+
SESSION.delete(delold)
|
185 |
+
history = ConnectionHistory(int(user_id), str(chat_id), chat_name, conn_time)
|
186 |
+
SESSION.add(history)
|
187 |
+
SESSION.commit()
|
188 |
+
HISTORY_CONNECT[int(user_id)][conn_time] = {
|
189 |
+
"chat_name": chat_name,
|
190 |
+
"chat_id": str(chat_id),
|
191 |
+
}
|
192 |
+
|
193 |
+
|
194 |
+
def get_history_conn(user_id):
|
195 |
+
if not HISTORY_CONNECT.get(int(user_id)):
|
196 |
+
HISTORY_CONNECT[int(user_id)] = {}
|
197 |
+
return HISTORY_CONNECT[int(user_id)]
|
198 |
+
|
199 |
+
|
200 |
+
def clear_history_conn(user_id):
|
201 |
+
global HISTORY_CONNECT
|
202 |
+
todel = list(HISTORY_CONNECT[int(user_id)])
|
203 |
+
for x in todel:
|
204 |
+
chat_old = HISTORY_CONNECT[int(user_id)][x]["chat_id"]
|
205 |
+
delold = SESSION.query(ConnectionHistory).get((int(user_id), str(chat_old)))
|
206 |
+
if delold:
|
207 |
+
SESSION.delete(delold)
|
208 |
+
HISTORY_CONNECT[int(user_id)].pop(x)
|
209 |
+
SESSION.commit()
|
210 |
+
return True
|
211 |
+
|
212 |
+
|
213 |
+
def __load_user_history():
|
214 |
+
global HISTORY_CONNECT
|
215 |
+
try:
|
216 |
+
qall = SESSION.query(ConnectionHistory).all()
|
217 |
+
HISTORY_CONNECT = {}
|
218 |
+
for x in qall:
|
219 |
+
check = HISTORY_CONNECT.get(x.user_id)
|
220 |
+
if check is None:
|
221 |
+
HISTORY_CONNECT[x.user_id] = {}
|
222 |
+
HISTORY_CONNECT[x.user_id][x.conn_time] = {
|
223 |
+
"chat_name": x.chat_name,
|
224 |
+
"chat_id": x.chat_id,
|
225 |
+
}
|
226 |
+
finally:
|
227 |
+
SESSION.close()
|
228 |
+
|
229 |
+
|
230 |
+
__load_user_history()
|
Database/sql/cust_filters_sql.py
ADDED
@@ -0,0 +1,404 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
7 |
+
|
8 |
+
|
9 |
+
class CustomFilters(BASE):
|
10 |
+
__tablename__ = "cust_filters"
|
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 |
+
|
91 |
+
def __repr__(self):
|
92 |
+
return "<Filter for %s>" % self.chat_id
|
93 |
+
|
94 |
+
def __eq__(self, other):
|
95 |
+
return bool(
|
96 |
+
isinstance(other, CustomFilters)
|
97 |
+
and self.chat_id == other.chat_id
|
98 |
+
and self.keyword == other.keyword
|
99 |
+
)
|
100 |
+
|
101 |
+
|
102 |
+
class Buttons(BASE):
|
103 |
+
__tablename__ = "cust_filter_urls"
|
104 |
+
id = Column(Integer, primary_key=True, autoincrement=True)
|
105 |
+
chat_id = Column(String(14), primary_key=True)
|
106 |
+
keyword = Column(UnicodeText, primary_key=True)
|
107 |
+
name = Column(UnicodeText, nullable=False)
|
108 |
+
url = Column(UnicodeText, nullable=False)
|
109 |
+
same_line = Column(Boolean, default=False)
|
110 |
+
|
111 |
+
def __init__(self, chat_id, keyword, name, url, same_line=False):
|
112 |
+
self.chat_id = str(chat_id)
|
113 |
+
self.keyword = keyword
|
114 |
+
self.name = name
|
115 |
+
self.url = url
|
116 |
+
self.same_line = same_line
|
117 |
+
|
118 |
+
|
119 |
+
CustomFilters.__table__.create(checkfirst=True)
|
120 |
+
Buttons.__table__.create(checkfirst=True)
|
121 |
+
|
122 |
+
CUST_FILT_LOCK = threading.RLock()
|
123 |
+
BUTTON_LOCK = threading.RLock()
|
124 |
+
CHAT_FILTERS = {}
|
125 |
+
|
126 |
+
|
127 |
+
def get_all_filters():
|
128 |
+
try:
|
129 |
+
return SESSION.query(CustomFilters).all()
|
130 |
+
finally:
|
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 |
+
):
|
193 |
+
global CHAT_FILTERS
|
194 |
+
|
195 |
+
if buttons is None:
|
196 |
+
buttons = []
|
197 |
+
|
198 |
+
with CUST_FILT_LOCK:
|
199 |
+
prev = SESSION.query(CustomFilters).get((str(chat_id), keyword))
|
200 |
+
if prev:
|
201 |
+
with BUTTON_LOCK:
|
202 |
+
prev_buttons = (
|
203 |
+
SESSION.query(Buttons)
|
204 |
+
.filter(Buttons.chat_id == str(chat_id), Buttons.keyword == keyword)
|
205 |
+
.all()
|
206 |
+
)
|
207 |
+
for btn in prev_buttons:
|
208 |
+
SESSION.delete(btn)
|
209 |
+
SESSION.delete(prev)
|
210 |
+
|
211 |
+
filt = CustomFilters(
|
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,
|
225 |
+
)
|
226 |
+
|
227 |
+
if keyword not in CHAT_FILTERS.get(str(chat_id), []):
|
228 |
+
CHAT_FILTERS[str(chat_id)] = sorted(
|
229 |
+
CHAT_FILTERS.get(str(chat_id), []) + [keyword],
|
230 |
+
key=lambda x: (-len(x), x),
|
231 |
+
)
|
232 |
+
|
233 |
+
SESSION.add(filt)
|
234 |
+
SESSION.commit()
|
235 |
+
|
236 |
+
for b_name, url, same_line in buttons:
|
237 |
+
add_note_button_to_db(chat_id, keyword, b_name, url, same_line)
|
238 |
+
|
239 |
+
|
240 |
+
def remove_filter(chat_id, keyword):
|
241 |
+
global CHAT_FILTERS
|
242 |
+
with CUST_FILT_LOCK:
|
243 |
+
filt = SESSION.query(CustomFilters).get((str(chat_id), keyword))
|
244 |
+
if filt:
|
245 |
+
if keyword in CHAT_FILTERS.get(str(chat_id), []): # Sanity check
|
246 |
+
CHAT_FILTERS.get(str(chat_id), []).remove(keyword)
|
247 |
+
|
248 |
+
with BUTTON_LOCK:
|
249 |
+
prev_buttons = (
|
250 |
+
SESSION.query(Buttons)
|
251 |
+
.filter(Buttons.chat_id == str(chat_id), Buttons.keyword == keyword)
|
252 |
+
.all()
|
253 |
+
)
|
254 |
+
for btn in prev_buttons:
|
255 |
+
SESSION.delete(btn)
|
256 |
+
|
257 |
+
SESSION.delete(filt)
|
258 |
+
SESSION.commit()
|
259 |
+
return True
|
260 |
+
|
261 |
+
SESSION.close()
|
262 |
+
return False
|
263 |
+
|
264 |
+
|
265 |
+
def get_chat_triggers(chat_id):
|
266 |
+
return CHAT_FILTERS.get(str(chat_id), set())
|
267 |
+
|
268 |
+
|
269 |
+
def get_chat_filters(chat_id):
|
270 |
+
try:
|
271 |
+
return (
|
272 |
+
SESSION.query(CustomFilters)
|
273 |
+
.filter(CustomFilters.chat_id == str(chat_id))
|
274 |
+
.order_by(func.length(CustomFilters.keyword).desc())
|
275 |
+
.order_by(CustomFilters.keyword.asc())
|
276 |
+
.all()
|
277 |
+
)
|
278 |
+
finally:
|
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:
|
286 |
+
SESSION.close()
|
287 |
+
|
288 |
+
|
289 |
+
def add_note_button_to_db(chat_id, keyword, b_name, url, same_line):
|
290 |
+
with BUTTON_LOCK:
|
291 |
+
button = Buttons(chat_id, keyword, b_name, url, same_line)
|
292 |
+
SESSION.add(button)
|
293 |
+
SESSION.commit()
|
294 |
+
|
295 |
+
|
296 |
+
def get_buttons(chat_id, keyword):
|
297 |
+
try:
|
298 |
+
return (
|
299 |
+
SESSION.query(Buttons)
|
300 |
+
.filter(Buttons.chat_id == str(chat_id), Buttons.keyword == keyword)
|
301 |
+
.order_by(Buttons.id)
|
302 |
+
.all()
|
303 |
+
)
|
304 |
+
finally:
|
305 |
+
SESSION.close()
|
306 |
+
|
307 |
+
|
308 |
+
def num_filters():
|
309 |
+
try:
|
310 |
+
return SESSION.query(CustomFilters).count()
|
311 |
+
finally:
|
312 |
+
SESSION.close()
|
313 |
+
|
314 |
+
|
315 |
+
def num_chats():
|
316 |
+
try:
|
317 |
+
return SESSION.query(func.count(distinct(CustomFilters.chat_id))).scalar()
|
318 |
+
finally:
|
319 |
+
SESSION.close()
|
320 |
+
|
321 |
+
|
322 |
+
def __load_chat_filters():
|
323 |
+
global CHAT_FILTERS
|
324 |
+
try:
|
325 |
+
chats = SESSION.query(CustomFilters.chat_id).distinct().all()
|
326 |
+
for (chat_id,) in chats: # remove tuple by ( ,)
|
327 |
+
CHAT_FILTERS[chat_id] = []
|
328 |
+
|
329 |
+
all_filters = SESSION.query(CustomFilters).all()
|
330 |
+
for x in all_filters:
|
331 |
+
CHAT_FILTERS[x.chat_id] += [x.keyword]
|
332 |
+
|
333 |
+
CHAT_FILTERS = {
|
334 |
+
x: sorted(set(y), key=lambda i: (-len(i), i))
|
335 |
+
for x, y in CHAT_FILTERS.items()
|
336 |
+
}
|
337 |
+
|
338 |
+
finally:
|
339 |
+
SESSION.close()
|
340 |
+
|
341 |
+
|
342 |
+
# ONLY USE FOR MIGRATE OLD FILTERS TO NEW FILTERS
|
343 |
+
def __migrate_filters():
|
344 |
+
try:
|
345 |
+
all_filters = SESSION.query(CustomFilters).distinct().all()
|
346 |
+
for x in all_filters:
|
347 |
+
if x.is_document:
|
348 |
+
file_type = Types.DOCUMENT
|
349 |
+
elif x.is_image:
|
350 |
+
file_type = Types.PHOTO
|
351 |
+
elif x.is_video:
|
352 |
+
file_type = Types.VIDEO
|
353 |
+
elif x.is_sticker:
|
354 |
+
file_type = Types.STICKER
|
355 |
+
elif x.is_audio:
|
356 |
+
file_type = Types.AUDIO
|
357 |
+
elif x.is_voice:
|
358 |
+
file_type = Types.VOICE
|
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)
|
373 |
+
SESSION.commit()
|
374 |
+
|
375 |
+
finally:
|
376 |
+
SESSION.close()
|
377 |
+
|
378 |
+
|
379 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
380 |
+
with CUST_FILT_LOCK:
|
381 |
+
chat_filters = (
|
382 |
+
SESSION.query(CustomFilters)
|
383 |
+
.filter(CustomFilters.chat_id == str(old_chat_id))
|
384 |
+
.all()
|
385 |
+
)
|
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 = (
|
397 |
+
SESSION.query(Buttons).filter(Buttons.chat_id == str(old_chat_id)).all()
|
398 |
+
)
|
399 |
+
for btn in chat_buttons:
|
400 |
+
btn.chat_id = str(new_chat_id)
|
401 |
+
SESSION.commit()
|
402 |
+
|
403 |
+
|
404 |
+
__load_chat_filters()
|
Database/sql/disable_sql.py
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
28 |
+
|
29 |
+
from Database.sql import BASE, SESSION
|
30 |
+
|
31 |
+
|
32 |
+
class Disable(BASE):
|
33 |
+
__tablename__ = "disabled_commands"
|
34 |
+
chat_id = Column(String(14), primary_key=True)
|
35 |
+
command = Column(UnicodeText, primary_key=True)
|
36 |
+
|
37 |
+
def __init__(self, chat_id, command):
|
38 |
+
self.chat_id = chat_id
|
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)
|
46 |
+
DISABLE_INSERTION_LOCK = threading.RLock()
|
47 |
+
|
48 |
+
DISABLED = {}
|
49 |
+
|
50 |
+
|
51 |
+
def disable_command(chat_id, disable):
|
52 |
+
with DISABLE_INSERTION_LOCK:
|
53 |
+
disabled = SESSION.query(Disable).get((str(chat_id), disable))
|
54 |
+
|
55 |
+
if not disabled:
|
56 |
+
DISABLED.setdefault(str(chat_id), set()).add(disable)
|
57 |
+
|
58 |
+
disabled = Disable(str(chat_id), disable)
|
59 |
+
SESSION.add(disabled)
|
60 |
+
SESSION.commit()
|
61 |
+
return True
|
62 |
+
|
63 |
+
SESSION.close()
|
64 |
+
return False
|
65 |
+
|
66 |
+
|
67 |
+
def enable_command(chat_id, enable):
|
68 |
+
with DISABLE_INSERTION_LOCK:
|
69 |
+
disabled = SESSION.query(Disable).get((str(chat_id), enable))
|
70 |
+
|
71 |
+
if disabled:
|
72 |
+
if enable in DISABLED.get(str(chat_id)): # sanity check
|
73 |
+
DISABLED.setdefault(str(chat_id), set()).remove(enable)
|
74 |
+
|
75 |
+
SESSION.delete(disabled)
|
76 |
+
SESSION.commit()
|
77 |
+
return True
|
78 |
+
|
79 |
+
SESSION.close()
|
80 |
+
return False
|
81 |
+
|
82 |
+
|
83 |
+
def is_command_disabled(chat_id, cmd):
|
84 |
+
return str(cmd).lower() in DISABLED.get(str(chat_id), set())
|
85 |
+
|
86 |
+
|
87 |
+
def get_all_disabled(chat_id):
|
88 |
+
return DISABLED.get(str(chat_id), set())
|
89 |
+
|
90 |
+
|
91 |
+
def num_chats():
|
92 |
+
try:
|
93 |
+
return SESSION.query(func.count(distinct(Disable.chat_id))).scalar()
|
94 |
+
finally:
|
95 |
+
SESSION.close()
|
96 |
+
|
97 |
+
|
98 |
+
def num_disabled():
|
99 |
+
try:
|
100 |
+
return SESSION.query(Disable).count()
|
101 |
+
finally:
|
102 |
+
SESSION.close()
|
103 |
+
|
104 |
+
|
105 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
106 |
+
with DISABLE_INSERTION_LOCK:
|
107 |
+
chats = SESSION.query(Disable).filter(Disable.chat_id == str(old_chat_id)).all()
|
108 |
+
for chat in chats:
|
109 |
+
chat.chat_id = str(new_chat_id)
|
110 |
+
SESSION.add(chat)
|
111 |
+
|
112 |
+
if str(old_chat_id) in DISABLED:
|
113 |
+
DISABLED[str(new_chat_id)] = DISABLED.get(str(old_chat_id), set())
|
114 |
+
|
115 |
+
SESSION.commit()
|
116 |
+
|
117 |
+
|
118 |
+
def __load_disabled_commands():
|
119 |
+
global DISABLED
|
120 |
+
try:
|
121 |
+
all_chats = SESSION.query(Disable).all()
|
122 |
+
for chat in all_chats:
|
123 |
+
DISABLED.setdefault(chat.chat_id, set()).add(chat.command)
|
124 |
+
|
125 |
+
finally:
|
126 |
+
SESSION.close()
|
127 |
+
|
128 |
+
|
129 |
+
__load_disabled_commands()
|
Database/sql/feds_sql.py
ADDED
@@ -0,0 +1,931 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import ast
|
2 |
+
import threading
|
3 |
+
|
4 |
+
from sqlalchemy import BigInteger, Boolean, Column, Integer, String, UnicodeText
|
5 |
+
from telegram.error import BadRequest, Forbidden
|
6 |
+
|
7 |
+
from Database.sql import BASE, SESSION
|
8 |
+
from Mikobot import dispatcher
|
9 |
+
|
10 |
+
|
11 |
+
class Federations(BASE):
|
12 |
+
__tablename__ = "feds"
|
13 |
+
owner_id = Column(String(14))
|
14 |
+
fed_name = Column(UnicodeText)
|
15 |
+
fed_id = Column(UnicodeText, primary_key=True)
|
16 |
+
fed_rules = Column(UnicodeText)
|
17 |
+
fed_log = Column(UnicodeText)
|
18 |
+
fed_users = Column(UnicodeText)
|
19 |
+
|
20 |
+
def __init__(self, owner_id, fed_name, fed_id, fed_rules, fed_log, fed_users):
|
21 |
+
self.owner_id = owner_id
|
22 |
+
self.fed_name = fed_name
|
23 |
+
self.fed_id = fed_id
|
24 |
+
self.fed_rules = fed_rules
|
25 |
+
self.fed_log = fed_log
|
26 |
+
self.fed_users = fed_users
|
27 |
+
|
28 |
+
|
29 |
+
class ChatF(BASE):
|
30 |
+
__tablename__ = "chat_feds"
|
31 |
+
chat_id = Column(String(14), primary_key=True)
|
32 |
+
chat_name = Column(UnicodeText)
|
33 |
+
fed_id = Column(UnicodeText)
|
34 |
+
|
35 |
+
def __init__(self, chat_id, chat_name, fed_id):
|
36 |
+
self.chat_id = chat_id
|
37 |
+
self.chat_name = chat_name
|
38 |
+
self.fed_id = fed_id
|
39 |
+
|
40 |
+
|
41 |
+
class BansF(BASE):
|
42 |
+
__tablename__ = "bans_feds"
|
43 |
+
fed_id = Column(UnicodeText, primary_key=True)
|
44 |
+
user_id = Column(String(14), primary_key=True)
|
45 |
+
first_name = Column(UnicodeText, nullable=False)
|
46 |
+
last_name = Column(UnicodeText)
|
47 |
+
user_name = Column(UnicodeText)
|
48 |
+
reason = Column(UnicodeText, default="")
|
49 |
+
time = Column(Integer, default=0)
|
50 |
+
|
51 |
+
def __init__(self, fed_id, user_id, first_name, last_name, user_name, reason, time):
|
52 |
+
self.fed_id = fed_id
|
53 |
+
self.user_id = user_id
|
54 |
+
self.first_name = first_name
|
55 |
+
self.last_name = last_name
|
56 |
+
self.user_name = user_name
|
57 |
+
self.reason = reason
|
58 |
+
self.time = time
|
59 |
+
|
60 |
+
|
61 |
+
class FedsUserSettings(BASE):
|
62 |
+
__tablename__ = "feds_settings"
|
63 |
+
user_id = Column(BigInteger, primary_key=True)
|
64 |
+
should_report = Column(Boolean, default=True)
|
65 |
+
|
66 |
+
def __init__(self, user_id):
|
67 |
+
self.user_id = user_id
|
68 |
+
|
69 |
+
def __repr__(self):
|
70 |
+
return "<Feds report settings ({})>".format(self.user_id)
|
71 |
+
|
72 |
+
|
73 |
+
class FedSubs(BASE):
|
74 |
+
__tablename__ = "feds_subs"
|
75 |
+
fed_id = Column(UnicodeText, primary_key=True)
|
76 |
+
fed_subs = Column(UnicodeText, primary_key=True, nullable=False)
|
77 |
+
|
78 |
+
def __init__(self, fed_id, fed_subs):
|
79 |
+
self.fed_id = fed_id
|
80 |
+
self.fed_subs = fed_subs
|
81 |
+
|
82 |
+
def __repr__(self):
|
83 |
+
return "<Fed {} subscribes for {}>".format(self.fed_id, self.fed_subs)
|
84 |
+
|
85 |
+
|
86 |
+
# Dropping db
|
87 |
+
# Federations.__table__.drop()
|
88 |
+
# ChatF.__table__.drop()
|
89 |
+
# BansF.__table__.drop()
|
90 |
+
# FedSubs.__table__.drop()
|
91 |
+
|
92 |
+
Federations.__table__.create(checkfirst=True)
|
93 |
+
ChatF.__table__.create(checkfirst=True)
|
94 |
+
BansF.__table__.create(checkfirst=True)
|
95 |
+
FedsUserSettings.__table__.create(checkfirst=True)
|
96 |
+
FedSubs.__table__.create(checkfirst=True)
|
97 |
+
|
98 |
+
FEDS_LOCK = threading.RLock()
|
99 |
+
CHAT_FEDS_LOCK = threading.RLock()
|
100 |
+
FEDS_SETTINGS_LOCK = threading.RLock()
|
101 |
+
FEDS_SUBSCRIBER_LOCK = threading.RLock()
|
102 |
+
|
103 |
+
FEDERATION_BYNAME = {}
|
104 |
+
FEDERATION_BYOWNER = {}
|
105 |
+
FEDERATION_BYFEDID = {}
|
106 |
+
|
107 |
+
FEDERATION_CHATS = {}
|
108 |
+
FEDERATION_CHATS_BYID = {}
|
109 |
+
|
110 |
+
FEDERATION_BANNED_FULL = {}
|
111 |
+
FEDERATION_BANNED_USERID = {}
|
112 |
+
|
113 |
+
FEDERATION_NOTIFICATION = {}
|
114 |
+
FEDS_SUBSCRIBER = {}
|
115 |
+
MYFEDS_SUBSCRIBER = {}
|
116 |
+
|
117 |
+
|
118 |
+
def get_fed_info(fed_id):
|
119 |
+
get = FEDERATION_BYFEDID.get(str(fed_id))
|
120 |
+
if get is None:
|
121 |
+
return False
|
122 |
+
return get
|
123 |
+
|
124 |
+
|
125 |
+
def get_fed_id(chat_id):
|
126 |
+
get = FEDERATION_CHATS.get(str(chat_id))
|
127 |
+
if get is None:
|
128 |
+
return False
|
129 |
+
else:
|
130 |
+
return get["fid"]
|
131 |
+
|
132 |
+
|
133 |
+
def get_fed_name(chat_id):
|
134 |
+
get = FEDERATION_CHATS.get(str(chat_id))
|
135 |
+
if get is None:
|
136 |
+
return False
|
137 |
+
else:
|
138 |
+
return get["chat_name"]
|
139 |
+
|
140 |
+
|
141 |
+
def get_user_fban(fed_id, user_id):
|
142 |
+
if not FEDERATION_BANNED_FULL.get(fed_id):
|
143 |
+
return False, False, False
|
144 |
+
user_info = FEDERATION_BANNED_FULL[fed_id].get(user_id)
|
145 |
+
if not user_info:
|
146 |
+
return None, None, None
|
147 |
+
return user_info["first_name"], user_info["reason"], user_info["time"]
|
148 |
+
|
149 |
+
|
150 |
+
def get_user_admin_fed_name(user_id):
|
151 |
+
user_feds = []
|
152 |
+
for f in FEDERATION_BYFEDID:
|
153 |
+
if int(user_id) in ast.literal_eval(
|
154 |
+
ast.literal_eval(FEDERATION_BYFEDID[f]["fusers"])["members"]
|
155 |
+
):
|
156 |
+
user_feds.append(FEDERATION_BYFEDID[f]["fname"])
|
157 |
+
return user_feds
|
158 |
+
|
159 |
+
|
160 |
+
def get_user_owner_fed_name(user_id):
|
161 |
+
user_feds = []
|
162 |
+
for f in FEDERATION_BYFEDID:
|
163 |
+
if int(user_id) == int(
|
164 |
+
ast.literal_eval(FEDERATION_BYFEDID[f]["fusers"])["owner"]
|
165 |
+
):
|
166 |
+
user_feds.append(FEDERATION_BYFEDID[f]["fname"])
|
167 |
+
return user_feds
|
168 |
+
|
169 |
+
|
170 |
+
def get_user_admin_fed_full(user_id):
|
171 |
+
user_feds = []
|
172 |
+
for f in FEDERATION_BYFEDID:
|
173 |
+
if int(user_id) in ast.literal_eval(
|
174 |
+
ast.literal_eval(FEDERATION_BYFEDID[f]["fusers"])["members"]
|
175 |
+
):
|
176 |
+
user_feds.append({"fed_id": f, "fed": FEDERATION_BYFEDID[f]})
|
177 |
+
return user_feds
|
178 |
+
|
179 |
+
|
180 |
+
def get_user_owner_fed_full(user_id):
|
181 |
+
user_feds = []
|
182 |
+
for f in FEDERATION_BYFEDID:
|
183 |
+
if int(user_id) == int(
|
184 |
+
ast.literal_eval(FEDERATION_BYFEDID[f]["fusers"])["owner"]
|
185 |
+
):
|
186 |
+
user_feds.append({"fed_id": f, "fed": FEDERATION_BYFEDID[f]})
|
187 |
+
return user_feds
|
188 |
+
|
189 |
+
|
190 |
+
def get_user_fbanlist(user_id):
|
191 |
+
banlist = FEDERATION_BANNED_FULL
|
192 |
+
user_name = ""
|
193 |
+
fedname = []
|
194 |
+
for x in banlist:
|
195 |
+
if banlist[x].get(user_id):
|
196 |
+
if user_name == "":
|
197 |
+
user_name = banlist[x][user_id].get("first_name")
|
198 |
+
fedname.append([x, banlist[x][user_id].get("reason")])
|
199 |
+
return user_name, fedname
|
200 |
+
|
201 |
+
|
202 |
+
def new_fed(owner_id, fed_name, fed_id):
|
203 |
+
with FEDS_LOCK:
|
204 |
+
global FEDERATION_BYOWNER, FEDERATION_BYFEDID, FEDERATION_BYNAME
|
205 |
+
fed = Federations(
|
206 |
+
str(owner_id),
|
207 |
+
fed_name,
|
208 |
+
str(fed_id),
|
209 |
+
"Rules is not set in this federation.",
|
210 |
+
None,
|
211 |
+
str({"owner": str(owner_id), "members": "[]"}),
|
212 |
+
)
|
213 |
+
SESSION.add(fed)
|
214 |
+
SESSION.commit()
|
215 |
+
FEDERATION_BYOWNER[str(owner_id)] = {
|
216 |
+
"fid": str(fed_id),
|
217 |
+
"fname": fed_name,
|
218 |
+
"frules": "Rules is not set in this federation.",
|
219 |
+
"flog": None,
|
220 |
+
"fusers": str({"owner": str(owner_id), "members": "[]"}),
|
221 |
+
}
|
222 |
+
FEDERATION_BYFEDID[str(fed_id)] = {
|
223 |
+
"owner": str(owner_id),
|
224 |
+
"fname": fed_name,
|
225 |
+
"frules": "Rules is not set in this federation.",
|
226 |
+
"flog": None,
|
227 |
+
"fusers": str({"owner": str(owner_id), "members": "[]"}),
|
228 |
+
}
|
229 |
+
FEDERATION_BYNAME[fed_name] = {
|
230 |
+
"fid": str(fed_id),
|
231 |
+
"owner": str(owner_id),
|
232 |
+
"frules": "Rules is not set in this federation.",
|
233 |
+
"flog": None,
|
234 |
+
"fusers": str({"owner": str(owner_id), "members": "[]"}),
|
235 |
+
}
|
236 |
+
return fed
|
237 |
+
|
238 |
+
|
239 |
+
def del_fed(fed_id):
|
240 |
+
with FEDS_LOCK:
|
241 |
+
global FEDERATION_BYOWNER, FEDERATION_BYFEDID, FEDERATION_BYNAME, FEDERATION_CHATS, FEDERATION_CHATS_BYID, FEDERATION_BANNED_USERID, FEDERATION_BANNED_FULL
|
242 |
+
getcache = FEDERATION_BYFEDID.get(fed_id)
|
243 |
+
if getcache is None:
|
244 |
+
return False
|
245 |
+
# Variables
|
246 |
+
getfed = FEDERATION_BYFEDID.get(fed_id)
|
247 |
+
owner_id = getfed["owner"]
|
248 |
+
fed_name = getfed["fname"]
|
249 |
+
# Delete from cache
|
250 |
+
FEDERATION_BYOWNER.pop(owner_id)
|
251 |
+
FEDERATION_BYFEDID.pop(fed_id)
|
252 |
+
FEDERATION_BYNAME.pop(fed_name)
|
253 |
+
if FEDERATION_CHATS_BYID.get(fed_id):
|
254 |
+
for x in FEDERATION_CHATS_BYID[fed_id]:
|
255 |
+
delchats = SESSION.query(ChatF).get(str(x))
|
256 |
+
if delchats:
|
257 |
+
SESSION.delete(delchats)
|
258 |
+
SESSION.commit()
|
259 |
+
FEDERATION_CHATS.pop(x)
|
260 |
+
FEDERATION_CHATS_BYID.pop(fed_id)
|
261 |
+
# Delete fedban users
|
262 |
+
getall = FEDERATION_BANNED_USERID.get(fed_id)
|
263 |
+
if getall:
|
264 |
+
for x in getall:
|
265 |
+
banlist = SESSION.query(BansF).get((fed_id, str(x)))
|
266 |
+
if banlist:
|
267 |
+
SESSION.delete(banlist)
|
268 |
+
SESSION.commit()
|
269 |
+
if FEDERATION_BANNED_USERID.get(fed_id):
|
270 |
+
FEDERATION_BANNED_USERID.pop(fed_id)
|
271 |
+
if FEDERATION_BANNED_FULL.get(fed_id):
|
272 |
+
FEDERATION_BANNED_FULL.pop(fed_id)
|
273 |
+
# Delete fedsubs
|
274 |
+
getall = MYFEDS_SUBSCRIBER.get(fed_id)
|
275 |
+
if getall:
|
276 |
+
for x in getall:
|
277 |
+
getsubs = SESSION.query(FedSubs).get((fed_id, str(x)))
|
278 |
+
if getsubs:
|
279 |
+
SESSION.delete(getsubs)
|
280 |
+
SESSION.commit()
|
281 |
+
if FEDS_SUBSCRIBER.get(fed_id):
|
282 |
+
FEDS_SUBSCRIBER.pop(fed_id)
|
283 |
+
if MYFEDS_SUBSCRIBER.get(fed_id):
|
284 |
+
MYFEDS_SUBSCRIBER.pop(fed_id)
|
285 |
+
# Delete from database
|
286 |
+
curr = SESSION.query(Federations).get(fed_id)
|
287 |
+
if curr:
|
288 |
+
SESSION.delete(curr)
|
289 |
+
SESSION.commit()
|
290 |
+
return True
|
291 |
+
|
292 |
+
|
293 |
+
def rename_fed(fed_id, owner_id, newname):
|
294 |
+
with FEDS_LOCK:
|
295 |
+
global FEDERATION_BYFEDID, FEDERATION_BYOWNER, FEDERATION_BYNAME
|
296 |
+
fed = SESSION.query(Federations).get(fed_id)
|
297 |
+
if not fed:
|
298 |
+
return False
|
299 |
+
fed.fed_name = newname
|
300 |
+
SESSION.commit()
|
301 |
+
|
302 |
+
# Update the dicts
|
303 |
+
oldname = FEDERATION_BYFEDID[str(fed_id)]["fname"]
|
304 |
+
tempdata = FEDERATION_BYNAME[oldname]
|
305 |
+
FEDERATION_BYNAME.pop(oldname)
|
306 |
+
|
307 |
+
FEDERATION_BYOWNER[str(owner_id)]["fname"] = newname
|
308 |
+
FEDERATION_BYFEDID[str(fed_id)]["fname"] = newname
|
309 |
+
FEDERATION_BYNAME[newname] = tempdata
|
310 |
+
return True
|
311 |
+
|
312 |
+
|
313 |
+
def chat_join_fed(fed_id, chat_name, chat_id):
|
314 |
+
with FEDS_LOCK:
|
315 |
+
global FEDERATION_CHATS, FEDERATION_CHATS_BYID
|
316 |
+
r = ChatF(chat_id, chat_name, fed_id)
|
317 |
+
SESSION.add(r)
|
318 |
+
FEDERATION_CHATS[str(chat_id)] = {"chat_name": chat_name, "fid": fed_id}
|
319 |
+
checkid = FEDERATION_CHATS_BYID.get(fed_id)
|
320 |
+
if checkid is None:
|
321 |
+
FEDERATION_CHATS_BYID[fed_id] = []
|
322 |
+
FEDERATION_CHATS_BYID[fed_id].append(str(chat_id))
|
323 |
+
SESSION.commit()
|
324 |
+
return r
|
325 |
+
|
326 |
+
|
327 |
+
def search_fed_by_name(fed_name):
|
328 |
+
allfed = FEDERATION_BYNAME.get(fed_name)
|
329 |
+
if allfed is None:
|
330 |
+
return False
|
331 |
+
return allfed
|
332 |
+
|
333 |
+
|
334 |
+
def search_user_in_fed(fed_id, user_id):
|
335 |
+
getfed = FEDERATION_BYFEDID.get(fed_id)
|
336 |
+
if getfed is None:
|
337 |
+
return False
|
338 |
+
getfed = ast.literal_eval(getfed["fusers"])["members"]
|
339 |
+
if user_id in ast.literal_eval(getfed):
|
340 |
+
return True
|
341 |
+
else:
|
342 |
+
return False
|
343 |
+
|
344 |
+
|
345 |
+
def user_demote_fed(fed_id, user_id):
|
346 |
+
with FEDS_LOCK:
|
347 |
+
global FEDERATION_BYOWNER, FEDERATION_BYFEDID, FEDERATION_BYNAME
|
348 |
+
# Variables
|
349 |
+
getfed = FEDERATION_BYFEDID.get(str(fed_id))
|
350 |
+
owner_id = getfed["owner"]
|
351 |
+
fed_name = getfed["fname"]
|
352 |
+
fed_rules = getfed["frules"]
|
353 |
+
fed_log = getfed["flog"]
|
354 |
+
# Temp set
|
355 |
+
try:
|
356 |
+
members = ast.literal_eval(ast.literal_eval(getfed["fusers"])["members"])
|
357 |
+
except ValueError:
|
358 |
+
return False
|
359 |
+
members.remove(user_id)
|
360 |
+
# Set user
|
361 |
+
FEDERATION_BYOWNER[str(owner_id)]["fusers"] = str(
|
362 |
+
{"owner": str(owner_id), "members": str(members)},
|
363 |
+
)
|
364 |
+
FEDERATION_BYFEDID[str(fed_id)]["fusers"] = str(
|
365 |
+
{"owner": str(owner_id), "members": str(members)},
|
366 |
+
)
|
367 |
+
FEDERATION_BYNAME[fed_name]["fusers"] = str(
|
368 |
+
{"owner": str(owner_id), "members": str(members)},
|
369 |
+
)
|
370 |
+
# Set on database
|
371 |
+
fed = Federations(
|
372 |
+
str(owner_id),
|
373 |
+
fed_name,
|
374 |
+
str(fed_id),
|
375 |
+
fed_rules,
|
376 |
+
fed_log,
|
377 |
+
str({"owner": str(owner_id), "members": str(members)}),
|
378 |
+
)
|
379 |
+
SESSION.merge(fed)
|
380 |
+
SESSION.commit()
|
381 |
+
return True
|
382 |
+
|
383 |
+
curr = SESSION.query(UserF).all()
|
384 |
+
result = False
|
385 |
+
for r in curr:
|
386 |
+
if int(r.user_id) == int(user_id):
|
387 |
+
if r.fed_id == fed_id:
|
388 |
+
SESSION.delete(r)
|
389 |
+
SESSION.commit()
|
390 |
+
result = True
|
391 |
+
|
392 |
+
SESSION.close()
|
393 |
+
return result
|
394 |
+
|
395 |
+
|
396 |
+
def user_join_fed(fed_id, user_id):
|
397 |
+
with FEDS_LOCK:
|
398 |
+
global FEDERATION_BYOWNER, FEDERATION_BYFEDID, FEDERATION_BYNAME
|
399 |
+
# Variables
|
400 |
+
getfed = FEDERATION_BYFEDID.get(str(fed_id))
|
401 |
+
owner_id = getfed["owner"]
|
402 |
+
fed_name = getfed["fname"]
|
403 |
+
fed_rules = getfed["frules"]
|
404 |
+
fed_log = getfed["flog"]
|
405 |
+
# Temp set
|
406 |
+
members = ast.literal_eval(ast.literal_eval(getfed["fusers"])["members"])
|
407 |
+
members.append(user_id)
|
408 |
+
# Set user
|
409 |
+
FEDERATION_BYOWNER[str(owner_id)]["fusers"] = str(
|
410 |
+
{"owner": str(owner_id), "members": str(members)},
|
411 |
+
)
|
412 |
+
FEDERATION_BYFEDID[str(fed_id)]["fusers"] = str(
|
413 |
+
{"owner": str(owner_id), "members": str(members)},
|
414 |
+
)
|
415 |
+
FEDERATION_BYNAME[fed_name]["fusers"] = str(
|
416 |
+
{"owner": str(owner_id), "members": str(members)},
|
417 |
+
)
|
418 |
+
# Set on database
|
419 |
+
fed = Federations(
|
420 |
+
str(owner_id),
|
421 |
+
fed_name,
|
422 |
+
str(fed_id),
|
423 |
+
fed_rules,
|
424 |
+
fed_log,
|
425 |
+
str({"owner": str(owner_id), "members": str(members)}),
|
426 |
+
)
|
427 |
+
SESSION.merge(fed)
|
428 |
+
SESSION.commit()
|
429 |
+
__load_all_feds_chats()
|
430 |
+
return True
|
431 |
+
|
432 |
+
|
433 |
+
def chat_leave_fed(chat_id):
|
434 |
+
with FEDS_LOCK:
|
435 |
+
global FEDERATION_CHATS, FEDERATION_CHATS_BYID
|
436 |
+
# Set variables
|
437 |
+
fed_info = FEDERATION_CHATS.get(str(chat_id))
|
438 |
+
if fed_info is None:
|
439 |
+
return False
|
440 |
+
fed_id = fed_info["fid"]
|
441 |
+
# Delete from cache
|
442 |
+
FEDERATION_CHATS.pop(str(chat_id))
|
443 |
+
FEDERATION_CHATS_BYID[str(fed_id)].remove(str(chat_id))
|
444 |
+
# Delete from db
|
445 |
+
curr = SESSION.query(ChatF).all()
|
446 |
+
for U in curr:
|
447 |
+
if int(U.chat_id) == int(chat_id):
|
448 |
+
SESSION.delete(U)
|
449 |
+
SESSION.commit()
|
450 |
+
return True
|
451 |
+
|
452 |
+
|
453 |
+
def all_fed_chats(fed_id):
|
454 |
+
with FEDS_LOCK:
|
455 |
+
getfed = FEDERATION_CHATS_BYID.get(fed_id)
|
456 |
+
if getfed is None:
|
457 |
+
return []
|
458 |
+
else:
|
459 |
+
return getfed
|
460 |
+
|
461 |
+
|
462 |
+
def all_fed_users(fed_id):
|
463 |
+
with FEDS_LOCK:
|
464 |
+
getfed = FEDERATION_BYFEDID.get(str(fed_id))
|
465 |
+
if getfed is None:
|
466 |
+
return False
|
467 |
+
fed_owner = ast.literal_eval(ast.literal_eval(getfed["fusers"])["owner"])
|
468 |
+
fed_admins = ast.literal_eval(ast.literal_eval(getfed["fusers"])["members"])
|
469 |
+
fed_admins.append(fed_owner)
|
470 |
+
return fed_admins
|
471 |
+
|
472 |
+
|
473 |
+
def all_fed_members(fed_id):
|
474 |
+
with FEDS_LOCK:
|
475 |
+
getfed = FEDERATION_BYFEDID.get(str(fed_id))
|
476 |
+
fed_admins = ast.literal_eval(ast.literal_eval(getfed["fusers"])["members"])
|
477 |
+
return fed_admins
|
478 |
+
|
479 |
+
|
480 |
+
def set_frules(fed_id, rules):
|
481 |
+
with FEDS_LOCK:
|
482 |
+
global FEDERATION_BYOWNER, FEDERATION_BYFEDID, FEDERATION_BYNAME
|
483 |
+
# Variables
|
484 |
+
getfed = FEDERATION_BYFEDID.get(str(fed_id))
|
485 |
+
owner_id = getfed["owner"]
|
486 |
+
fed_name = getfed["fname"]
|
487 |
+
fed_members = getfed["fusers"]
|
488 |
+
fed_rules = str(rules)
|
489 |
+
fed_log = getfed["flog"]
|
490 |
+
# Set user
|
491 |
+
FEDERATION_BYOWNER[str(owner_id)]["frules"] = fed_rules
|
492 |
+
FEDERATION_BYFEDID[str(fed_id)]["frules"] = fed_rules
|
493 |
+
FEDERATION_BYNAME[fed_name]["frules"] = fed_rules
|
494 |
+
# Set on database
|
495 |
+
fed = Federations(
|
496 |
+
str(owner_id),
|
497 |
+
fed_name,
|
498 |
+
str(fed_id),
|
499 |
+
fed_rules,
|
500 |
+
fed_log,
|
501 |
+
str(fed_members),
|
502 |
+
)
|
503 |
+
SESSION.merge(fed)
|
504 |
+
SESSION.commit()
|
505 |
+
return True
|
506 |
+
|
507 |
+
|
508 |
+
def get_frules(fed_id):
|
509 |
+
with FEDS_LOCK:
|
510 |
+
rules = FEDERATION_BYFEDID[str(fed_id)]["frules"]
|
511 |
+
return rules
|
512 |
+
|
513 |
+
|
514 |
+
def fban_user(fed_id, user_id, first_name, last_name, user_name, reason, time):
|
515 |
+
with FEDS_LOCK:
|
516 |
+
r = SESSION.query(BansF).all()
|
517 |
+
for I in r:
|
518 |
+
if I.fed_id == fed_id:
|
519 |
+
if int(I.user_id) == int(user_id):
|
520 |
+
SESSION.delete(I)
|
521 |
+
|
522 |
+
r = BansF(
|
523 |
+
str(fed_id),
|
524 |
+
str(user_id),
|
525 |
+
first_name,
|
526 |
+
last_name,
|
527 |
+
user_name,
|
528 |
+
reason,
|
529 |
+
time,
|
530 |
+
)
|
531 |
+
|
532 |
+
SESSION.add(r)
|
533 |
+
try:
|
534 |
+
SESSION.commit()
|
535 |
+
except:
|
536 |
+
SESSION.rollback()
|
537 |
+
return False
|
538 |
+
finally:
|
539 |
+
SESSION.commit()
|
540 |
+
__load_all_feds_banned()
|
541 |
+
return r
|
542 |
+
|
543 |
+
|
544 |
+
def multi_fban_user(
|
545 |
+
multi_fed_id,
|
546 |
+
multi_user_id,
|
547 |
+
multi_first_name,
|
548 |
+
multi_last_name,
|
549 |
+
multi_user_name,
|
550 |
+
multi_reason,
|
551 |
+
):
|
552 |
+
if True: # with FEDS_LOCK:
|
553 |
+
counter = 0
|
554 |
+
time = 0
|
555 |
+
for x in range(len(multi_fed_id)):
|
556 |
+
fed_id = multi_fed_id[x]
|
557 |
+
user_id = multi_user_id[x]
|
558 |
+
first_name = multi_first_name[x]
|
559 |
+
last_name = multi_last_name[x]
|
560 |
+
user_name = multi_user_name[x]
|
561 |
+
reason = multi_reason[x]
|
562 |
+
r = SESSION.query(BansF).all()
|
563 |
+
for I in r:
|
564 |
+
if I.fed_id == fed_id:
|
565 |
+
if int(I.user_id) == int(user_id):
|
566 |
+
SESSION.delete(I)
|
567 |
+
|
568 |
+
r = BansF(
|
569 |
+
str(fed_id),
|
570 |
+
str(user_id),
|
571 |
+
first_name,
|
572 |
+
last_name,
|
573 |
+
user_name,
|
574 |
+
reason,
|
575 |
+
time,
|
576 |
+
)
|
577 |
+
|
578 |
+
SESSION.add(r)
|
579 |
+
counter += 1
|
580 |
+
try:
|
581 |
+
SESSION.commit()
|
582 |
+
except:
|
583 |
+
SESSION.rollback()
|
584 |
+
return False
|
585 |
+
finally:
|
586 |
+
SESSION.commit()
|
587 |
+
__load_all_feds_banned()
|
588 |
+
return counter
|
589 |
+
|
590 |
+
|
591 |
+
def un_fban_user(fed_id, user_id):
|
592 |
+
with FEDS_LOCK:
|
593 |
+
r = SESSION.query(BansF).all()
|
594 |
+
for I in r:
|
595 |
+
if I.fed_id == fed_id:
|
596 |
+
if int(I.user_id) == int(user_id):
|
597 |
+
SESSION.delete(I)
|
598 |
+
try:
|
599 |
+
SESSION.commit()
|
600 |
+
except:
|
601 |
+
SESSION.rollback()
|
602 |
+
return False
|
603 |
+
finally:
|
604 |
+
SESSION.commit()
|
605 |
+
__load_all_feds_banned()
|
606 |
+
return I
|
607 |
+
|
608 |
+
|
609 |
+
def get_fban_user(fed_id, user_id):
|
610 |
+
list_fbanned = FEDERATION_BANNED_USERID.get(fed_id)
|
611 |
+
if list_fbanned is None:
|
612 |
+
FEDERATION_BANNED_USERID[fed_id] = []
|
613 |
+
if user_id in FEDERATION_BANNED_USERID[fed_id]:
|
614 |
+
r = SESSION.query(BansF).all()
|
615 |
+
reason = None
|
616 |
+
for I in r:
|
617 |
+
if I.fed_id == fed_id:
|
618 |
+
if int(I.user_id) == int(user_id):
|
619 |
+
reason = I.reason
|
620 |
+
time = I.time
|
621 |
+
return True, reason, time
|
622 |
+
else:
|
623 |
+
return False, None, None
|
624 |
+
|
625 |
+
|
626 |
+
def get_all_fban_users(fed_id):
|
627 |
+
list_fbanned = FEDERATION_BANNED_USERID.get(fed_id)
|
628 |
+
if list_fbanned is None:
|
629 |
+
FEDERATION_BANNED_USERID[fed_id] = []
|
630 |
+
return FEDERATION_BANNED_USERID[fed_id]
|
631 |
+
|
632 |
+
|
633 |
+
def get_all_fban_users_target(fed_id, user_id):
|
634 |
+
list_fbanned = FEDERATION_BANNED_FULL.get(fed_id)
|
635 |
+
if list_fbanned is None:
|
636 |
+
FEDERATION_BANNED_FULL[fed_id] = []
|
637 |
+
return False
|
638 |
+
getuser = list_fbanned[str(user_id)]
|
639 |
+
return getuser
|
640 |
+
|
641 |
+
|
642 |
+
def get_all_fban_users_global():
|
643 |
+
list_fbanned = FEDERATION_BANNED_USERID
|
644 |
+
total = []
|
645 |
+
for x in list(FEDERATION_BANNED_USERID):
|
646 |
+
for y in FEDERATION_BANNED_USERID[x]:
|
647 |
+
total.append(y)
|
648 |
+
return total
|
649 |
+
|
650 |
+
|
651 |
+
def get_all_feds_users_global():
|
652 |
+
list_fed = FEDERATION_BYFEDID
|
653 |
+
total = []
|
654 |
+
for x in list(FEDERATION_BYFEDID):
|
655 |
+
total.append(FEDERATION_BYFEDID[x])
|
656 |
+
return total
|
657 |
+
|
658 |
+
|
659 |
+
def search_fed_by_id(fed_id):
|
660 |
+
get = FEDERATION_BYFEDID.get(fed_id)
|
661 |
+
if get is None:
|
662 |
+
return False
|
663 |
+
else:
|
664 |
+
return get
|
665 |
+
result = False
|
666 |
+
for Q in curr:
|
667 |
+
if Q.fed_id == fed_id:
|
668 |
+
result = Q.fed_id
|
669 |
+
|
670 |
+
return result
|
671 |
+
|
672 |
+
|
673 |
+
def user_feds_report(user_id: int) -> bool:
|
674 |
+
user_setting = FEDERATION_NOTIFICATION.get(str(user_id))
|
675 |
+
if user_setting is None:
|
676 |
+
user_setting = True
|
677 |
+
return user_setting
|
678 |
+
|
679 |
+
|
680 |
+
def set_feds_setting(user_id: int, setting: bool):
|
681 |
+
with FEDS_SETTINGS_LOCK:
|
682 |
+
global FEDERATION_NOTIFICATION
|
683 |
+
user_setting = SESSION.query(FedsUserSettings).get(user_id)
|
684 |
+
if not user_setting:
|
685 |
+
user_setting = FedsUserSettings(user_id)
|
686 |
+
|
687 |
+
user_setting.should_report = setting
|
688 |
+
FEDERATION_NOTIFICATION[str(user_id)] = setting
|
689 |
+
SESSION.add(user_setting)
|
690 |
+
SESSION.commit()
|
691 |
+
|
692 |
+
|
693 |
+
async def get_fed_log(fed_id):
|
694 |
+
fed_setting = FEDERATION_BYFEDID.get(str(fed_id))
|
695 |
+
if fed_setting is None:
|
696 |
+
fed_setting = False
|
697 |
+
return fed_setting
|
698 |
+
if fed_setting.get("flog") is None:
|
699 |
+
return False
|
700 |
+
elif fed_setting.get("flog"):
|
701 |
+
try:
|
702 |
+
await dispatcher.bot.get_chat(fed_setting.get("flog"))
|
703 |
+
except BadRequest:
|
704 |
+
set_fed_log(fed_id, None)
|
705 |
+
return False
|
706 |
+
except Forbidden:
|
707 |
+
set_fed_log(fed_id, None)
|
708 |
+
return False
|
709 |
+
return fed_setting.get("flog")
|
710 |
+
else:
|
711 |
+
return False
|
712 |
+
|
713 |
+
|
714 |
+
def set_fed_log(fed_id, chat_id):
|
715 |
+
with FEDS_LOCK:
|
716 |
+
global FEDERATION_BYOWNER, FEDERATION_BYFEDID, FEDERATION_BYNAME
|
717 |
+
# Variables
|
718 |
+
getfed = FEDERATION_BYFEDID.get(str(fed_id))
|
719 |
+
owner_id = getfed["owner"]
|
720 |
+
fed_name = getfed["fname"]
|
721 |
+
fed_members = getfed["fusers"]
|
722 |
+
fed_rules = getfed["frules"]
|
723 |
+
fed_log = str(chat_id)
|
724 |
+
# Set user
|
725 |
+
FEDERATION_BYOWNER[str(owner_id)]["flog"] = fed_log
|
726 |
+
FEDERATION_BYFEDID[str(fed_id)]["flog"] = fed_log
|
727 |
+
FEDERATION_BYNAME[fed_name]["flog"] = fed_log
|
728 |
+
# Set on database
|
729 |
+
fed = Federations(
|
730 |
+
str(owner_id),
|
731 |
+
fed_name,
|
732 |
+
str(fed_id),
|
733 |
+
fed_rules,
|
734 |
+
fed_log,
|
735 |
+
str(fed_members),
|
736 |
+
)
|
737 |
+
SESSION.merge(fed)
|
738 |
+
SESSION.commit()
|
739 |
+
return True
|
740 |
+
|
741 |
+
|
742 |
+
def subs_fed(fed_id, my_fed):
|
743 |
+
check = get_spec_subs(fed_id, my_fed)
|
744 |
+
if check:
|
745 |
+
return False
|
746 |
+
with FEDS_SUBSCRIBER_LOCK:
|
747 |
+
subsfed = FedSubs(fed_id, my_fed)
|
748 |
+
|
749 |
+
SESSION.merge(subsfed) # merge to avoid duplicate key issues
|
750 |
+
SESSION.commit()
|
751 |
+
global FEDS_SUBSCRIBER, MYFEDS_SUBSCRIBER
|
752 |
+
# Temporary Data For Subbed Feds
|
753 |
+
if FEDS_SUBSCRIBER.get(fed_id, set()) == set():
|
754 |
+
FEDS_SUBSCRIBER[fed_id] = {my_fed}
|
755 |
+
else:
|
756 |
+
FEDS_SUBSCRIBER.get(fed_id, set()).add(my_fed)
|
757 |
+
# Temporary data for Fed Subs
|
758 |
+
if MYFEDS_SUBSCRIBER.get(my_fed, set()) == set():
|
759 |
+
MYFEDS_SUBSCRIBER[my_fed] = {fed_id}
|
760 |
+
else:
|
761 |
+
MYFEDS_SUBSCRIBER.get(my_fed, set()).add(fed_id)
|
762 |
+
return True
|
763 |
+
|
764 |
+
|
765 |
+
def unsubs_fed(fed_id, my_fed):
|
766 |
+
with FEDS_SUBSCRIBER_LOCK:
|
767 |
+
getsubs = SESSION.query(FedSubs).get((fed_id, my_fed))
|
768 |
+
if getsubs:
|
769 |
+
if my_fed in FEDS_SUBSCRIBER.get(fed_id, set()): # sanity check
|
770 |
+
FEDS_SUBSCRIBER.get(fed_id, set()).remove(my_fed)
|
771 |
+
if fed_id in MYFEDS_SUBSCRIBER.get(my_fed, set()): # sanity check
|
772 |
+
MYFEDS_SUBSCRIBER.get(my_fed, set()).remove(fed_id)
|
773 |
+
|
774 |
+
SESSION.delete(getsubs)
|
775 |
+
SESSION.commit()
|
776 |
+
return True
|
777 |
+
|
778 |
+
SESSION.close()
|
779 |
+
return False
|
780 |
+
|
781 |
+
|
782 |
+
def get_all_subs(fed_id):
|
783 |
+
return FEDS_SUBSCRIBER.get(fed_id, set())
|
784 |
+
|
785 |
+
|
786 |
+
def get_spec_subs(fed_id, fed_target):
|
787 |
+
if FEDS_SUBSCRIBER.get(fed_id, set()) == set():
|
788 |
+
return {}
|
789 |
+
else:
|
790 |
+
return FEDS_SUBSCRIBER.get(fed_id, fed_target)
|
791 |
+
|
792 |
+
|
793 |
+
def get_mysubs(my_fed):
|
794 |
+
return list(MYFEDS_SUBSCRIBER.get(my_fed))
|
795 |
+
|
796 |
+
|
797 |
+
def get_subscriber(fed_id):
|
798 |
+
return FEDS_SUBSCRIBER.get(fed_id, set())
|
799 |
+
|
800 |
+
|
801 |
+
def __load_all_feds():
|
802 |
+
global FEDERATION_BYOWNER, FEDERATION_BYFEDID, FEDERATION_BYNAME
|
803 |
+
try:
|
804 |
+
feds = SESSION.query(Federations).all()
|
805 |
+
for x in feds: # remove tuple by ( ,)
|
806 |
+
# Fed by Owner
|
807 |
+
check = FEDERATION_BYOWNER.get(x.owner_id)
|
808 |
+
if check is None:
|
809 |
+
FEDERATION_BYOWNER[x.owner_id] = []
|
810 |
+
FEDERATION_BYOWNER[str(x.owner_id)] = {
|
811 |
+
"fid": str(x.fed_id),
|
812 |
+
"fname": x.fed_name,
|
813 |
+
"frules": x.fed_rules,
|
814 |
+
"flog": x.fed_log,
|
815 |
+
"fusers": str(x.fed_users),
|
816 |
+
}
|
817 |
+
# Fed By FedId
|
818 |
+
check = FEDERATION_BYFEDID.get(x.fed_id)
|
819 |
+
if check is None:
|
820 |
+
FEDERATION_BYFEDID[x.fed_id] = []
|
821 |
+
FEDERATION_BYFEDID[str(x.fed_id)] = {
|
822 |
+
"owner": str(x.owner_id),
|
823 |
+
"fname": x.fed_name,
|
824 |
+
"frules": x.fed_rules,
|
825 |
+
"flog": x.fed_log,
|
826 |
+
"fusers": str(x.fed_users),
|
827 |
+
}
|
828 |
+
# Fed By Name
|
829 |
+
check = FEDERATION_BYNAME.get(x.fed_name)
|
830 |
+
if check is None:
|
831 |
+
FEDERATION_BYNAME[x.fed_name] = []
|
832 |
+
FEDERATION_BYNAME[x.fed_name] = {
|
833 |
+
"fid": str(x.fed_id),
|
834 |
+
"owner": str(x.owner_id),
|
835 |
+
"frules": x.fed_rules,
|
836 |
+
"flog": x.fed_log,
|
837 |
+
"fusers": str(x.fed_users),
|
838 |
+
}
|
839 |
+
finally:
|
840 |
+
SESSION.close()
|
841 |
+
|
842 |
+
|
843 |
+
def __load_all_feds_chats():
|
844 |
+
global FEDERATION_CHATS, FEDERATION_CHATS_BYID
|
845 |
+
try:
|
846 |
+
qall = SESSION.query(ChatF).all()
|
847 |
+
FEDERATION_CHATS = {}
|
848 |
+
FEDERATION_CHATS_BYID = {}
|
849 |
+
for x in qall:
|
850 |
+
# Federation Chats
|
851 |
+
check = FEDERATION_CHATS.get(x.chat_id)
|
852 |
+
if check is None:
|
853 |
+
FEDERATION_CHATS[x.chat_id] = {}
|
854 |
+
FEDERATION_CHATS[x.chat_id] = {"chat_name": x.chat_name, "fid": x.fed_id}
|
855 |
+
# Federation Chats By ID
|
856 |
+
check = FEDERATION_CHATS_BYID.get(x.fed_id)
|
857 |
+
if check is None:
|
858 |
+
FEDERATION_CHATS_BYID[x.fed_id] = []
|
859 |
+
FEDERATION_CHATS_BYID[x.fed_id].append(x.chat_id)
|
860 |
+
finally:
|
861 |
+
SESSION.close()
|
862 |
+
|
863 |
+
|
864 |
+
def __load_all_feds_banned():
|
865 |
+
global FEDERATION_BANNED_USERID, FEDERATION_BANNED_FULL
|
866 |
+
try:
|
867 |
+
FEDERATION_BANNED_USERID = {}
|
868 |
+
FEDERATION_BANNED_FULL = {}
|
869 |
+
qall = SESSION.query(BansF).all()
|
870 |
+
for x in qall:
|
871 |
+
check = FEDERATION_BANNED_USERID.get(x.fed_id)
|
872 |
+
if check is None:
|
873 |
+
FEDERATION_BANNED_USERID[x.fed_id] = []
|
874 |
+
if int(x.user_id) not in FEDERATION_BANNED_USERID[x.fed_id]:
|
875 |
+
FEDERATION_BANNED_USERID[x.fed_id].append(int(x.user_id))
|
876 |
+
check = FEDERATION_BANNED_FULL.get(x.fed_id)
|
877 |
+
if check is None:
|
878 |
+
FEDERATION_BANNED_FULL[x.fed_id] = {}
|
879 |
+
FEDERATION_BANNED_FULL[x.fed_id][x.user_id] = {
|
880 |
+
"first_name": x.first_name,
|
881 |
+
"last_name": x.last_name,
|
882 |
+
"user_name": x.user_name,
|
883 |
+
"reason": x.reason,
|
884 |
+
"time": x.time,
|
885 |
+
}
|
886 |
+
finally:
|
887 |
+
SESSION.close()
|
888 |
+
|
889 |
+
|
890 |
+
def __load_all_feds_settings():
|
891 |
+
global FEDERATION_NOTIFICATION
|
892 |
+
try:
|
893 |
+
getuser = SESSION.query(FedsUserSettings).all()
|
894 |
+
for x in getuser:
|
895 |
+
FEDERATION_NOTIFICATION[str(x.user_id)] = x.should_report
|
896 |
+
finally:
|
897 |
+
SESSION.close()
|
898 |
+
|
899 |
+
|
900 |
+
def __load_feds_subscriber():
|
901 |
+
global FEDS_SUBSCRIBER
|
902 |
+
global MYFEDS_SUBSCRIBER
|
903 |
+
try:
|
904 |
+
feds = SESSION.query(FedSubs.fed_id).distinct().all()
|
905 |
+
for (fed_id,) in feds: # remove tuple by ( ,)
|
906 |
+
FEDS_SUBSCRIBER[fed_id] = []
|
907 |
+
MYFEDS_SUBSCRIBER[fed_id] = []
|
908 |
+
|
909 |
+
all_fedsubs = SESSION.query(FedSubs).all()
|
910 |
+
for x in all_fedsubs:
|
911 |
+
FEDS_SUBSCRIBER[x.fed_id] += [x.fed_subs]
|
912 |
+
try:
|
913 |
+
MYFEDS_SUBSCRIBER[x.fed_subs] += [x.fed_id]
|
914 |
+
except KeyError:
|
915 |
+
getsubs = SESSION.query(FedSubs).get((x.fed_id, x.fed_subs))
|
916 |
+
if getsubs:
|
917 |
+
SESSION.delete(getsubs)
|
918 |
+
SESSION.commit()
|
919 |
+
|
920 |
+
FEDS_SUBSCRIBER = {x: set(y) for x, y in FEDS_SUBSCRIBER.items()}
|
921 |
+
MYFEDS_SUBSCRIBER = {x: set(y) for x, y in MYFEDS_SUBSCRIBER.items()}
|
922 |
+
|
923 |
+
finally:
|
924 |
+
SESSION.close()
|
925 |
+
|
926 |
+
|
927 |
+
__load_all_feds()
|
928 |
+
__load_all_feds_chats()
|
929 |
+
__load_all_feds_banned()
|
930 |
+
__load_all_feds_settings()
|
931 |
+
__load_feds_subscriber()
|
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/global_bans_sql.py
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import threading
|
2 |
+
|
3 |
+
from sqlalchemy import BigInteger, Boolean, Column, String, UnicodeText
|
4 |
+
|
5 |
+
from Database.sql import BASE, SESSION
|
6 |
+
|
7 |
+
|
8 |
+
class GloballyBannedUsers(BASE):
|
9 |
+
__tablename__ = "gbans"
|
10 |
+
user_id = Column(BigInteger, primary_key=True)
|
11 |
+
name = Column(UnicodeText, nullable=False)
|
12 |
+
reason = Column(UnicodeText)
|
13 |
+
|
14 |
+
def __init__(self, user_id, name, reason=None):
|
15 |
+
self.user_id = user_id
|
16 |
+
self.name = name
|
17 |
+
self.reason = reason
|
18 |
+
|
19 |
+
def __repr__(self):
|
20 |
+
return "<GBanned User {} ({})>".format(self.name, self.user_id)
|
21 |
+
|
22 |
+
def to_dict(self):
|
23 |
+
return {"user_id": self.user_id, "name": self.name, "reason": self.reason}
|
24 |
+
|
25 |
+
|
26 |
+
class GbanSettings(BASE):
|
27 |
+
__tablename__ = "gban_settings"
|
28 |
+
chat_id = Column(String(14), primary_key=True)
|
29 |
+
setting = Column(Boolean, default=True, nullable=False)
|
30 |
+
|
31 |
+
def __init__(self, chat_id, enabled):
|
32 |
+
self.chat_id = str(chat_id)
|
33 |
+
self.setting = enabled
|
34 |
+
|
35 |
+
def __repr__(self):
|
36 |
+
return "<Gban setting {} ({})>".format(self.chat_id, self.setting)
|
37 |
+
|
38 |
+
|
39 |
+
GloballyBannedUsers.__table__.create(checkfirst=True)
|
40 |
+
GbanSettings.__table__.create(checkfirst=True)
|
41 |
+
|
42 |
+
GBANNED_USERS_LOCK = threading.RLock()
|
43 |
+
GBAN_SETTING_LOCK = threading.RLock()
|
44 |
+
GBANNED_LIST = set()
|
45 |
+
GBANSTAT_LIST = set()
|
46 |
+
|
47 |
+
|
48 |
+
def gban_user(user_id, name, reason=None):
|
49 |
+
with GBANNED_USERS_LOCK:
|
50 |
+
user = SESSION.query(GloballyBannedUsers).get(user_id)
|
51 |
+
if not user:
|
52 |
+
user = GloballyBannedUsers(user_id, name, reason)
|
53 |
+
else:
|
54 |
+
user.name = name
|
55 |
+
user.reason = reason
|
56 |
+
|
57 |
+
SESSION.merge(user)
|
58 |
+
SESSION.commit()
|
59 |
+
__load_gbanned_userid_list()
|
60 |
+
|
61 |
+
|
62 |
+
def update_gban_reason(user_id, name, reason=None):
|
63 |
+
with GBANNED_USERS_LOCK:
|
64 |
+
user = SESSION.query(GloballyBannedUsers).get(user_id)
|
65 |
+
if not user:
|
66 |
+
return None
|
67 |
+
old_reason = user.reason
|
68 |
+
user.name = name
|
69 |
+
user.reason = reason
|
70 |
+
|
71 |
+
SESSION.merge(user)
|
72 |
+
SESSION.commit()
|
73 |
+
return old_reason
|
74 |
+
|
75 |
+
|
76 |
+
def ungban_user(user_id):
|
77 |
+
with GBANNED_USERS_LOCK:
|
78 |
+
user = SESSION.query(GloballyBannedUsers).get(user_id)
|
79 |
+
if user:
|
80 |
+
SESSION.delete(user)
|
81 |
+
|
82 |
+
SESSION.commit()
|
83 |
+
__load_gbanned_userid_list()
|
84 |
+
|
85 |
+
|
86 |
+
def is_user_gbanned(user_id):
|
87 |
+
return user_id in GBANNED_LIST
|
88 |
+
|
89 |
+
|
90 |
+
def get_gbanned_user(user_id):
|
91 |
+
try:
|
92 |
+
return SESSION.query(GloballyBannedUsers).get(user_id)
|
93 |
+
finally:
|
94 |
+
SESSION.close()
|
95 |
+
|
96 |
+
|
97 |
+
def get_gban_list():
|
98 |
+
try:
|
99 |
+
return [x.to_dict() for x in SESSION.query(GloballyBannedUsers).all()]
|
100 |
+
finally:
|
101 |
+
SESSION.close()
|
102 |
+
|
103 |
+
|
104 |
+
def enable_gbans(chat_id):
|
105 |
+
with GBAN_SETTING_LOCK:
|
106 |
+
chat = SESSION.query(GbanSettings).get(str(chat_id))
|
107 |
+
if not chat:
|
108 |
+
chat = GbanSettings(chat_id, True)
|
109 |
+
|
110 |
+
chat.setting = True
|
111 |
+
SESSION.add(chat)
|
112 |
+
SESSION.commit()
|
113 |
+
if str(chat_id) in GBANSTAT_LIST:
|
114 |
+
GBANSTAT_LIST.remove(str(chat_id))
|
115 |
+
|
116 |
+
|
117 |
+
def disable_gbans(chat_id):
|
118 |
+
with GBAN_SETTING_LOCK:
|
119 |
+
chat = SESSION.query(GbanSettings).get(str(chat_id))
|
120 |
+
if not chat:
|
121 |
+
chat = GbanSettings(chat_id, False)
|
122 |
+
|
123 |
+
chat.setting = False
|
124 |
+
SESSION.add(chat)
|
125 |
+
SESSION.commit()
|
126 |
+
GBANSTAT_LIST.add(str(chat_id))
|
127 |
+
|
128 |
+
|
129 |
+
def does_chat_gban(chat_id):
|
130 |
+
return str(chat_id) not in GBANSTAT_LIST
|
131 |
+
|
132 |
+
|
133 |
+
def num_gbanned_users():
|
134 |
+
return len(GBANNED_LIST)
|
135 |
+
|
136 |
+
|
137 |
+
def __load_gbanned_userid_list():
|
138 |
+
global GBANNED_LIST
|
139 |
+
try:
|
140 |
+
GBANNED_LIST = {x.user_id for x in SESSION.query(GloballyBannedUsers).all()}
|
141 |
+
finally:
|
142 |
+
SESSION.close()
|
143 |
+
|
144 |
+
|
145 |
+
def __load_gban_stat_list():
|
146 |
+
global GBANSTAT_LIST
|
147 |
+
try:
|
148 |
+
GBANSTAT_LIST = {
|
149 |
+
x.chat_id for x in SESSION.query(GbanSettings).all() if not x.setting
|
150 |
+
}
|
151 |
+
finally:
|
152 |
+
SESSION.close()
|
153 |
+
|
154 |
+
|
155 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
156 |
+
with GBAN_SETTING_LOCK:
|
157 |
+
chat = SESSION.query(GbanSettings).get(str(old_chat_id))
|
158 |
+
if chat:
|
159 |
+
chat.chat_id = new_chat_id
|
160 |
+
SESSION.add(chat)
|
161 |
+
|
162 |
+
SESSION.commit()
|
163 |
+
|
164 |
+
|
165 |
+
# Create in memory userid to avoid disk access
|
166 |
+
__load_gbanned_userid_list()
|
167 |
+
__load_gban_stat_list()
|
Database/sql/kuki_sql.py
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import threading
|
2 |
+
|
3 |
+
from sqlalchemy import Column, String
|
4 |
+
|
5 |
+
from Database.sql import BASE, SESSION
|
6 |
+
|
7 |
+
|
8 |
+
class KukiChats(BASE):
|
9 |
+
__tablename__ = "kuki_chats"
|
10 |
+
chat_id = Column(String(14), primary_key=True)
|
11 |
+
|
12 |
+
def __init__(self, chat_id):
|
13 |
+
self.chat_id = chat_id
|
14 |
+
|
15 |
+
|
16 |
+
KukiChats.__table__.create(checkfirst=True)
|
17 |
+
INSERTION_LOCK = threading.RLock()
|
18 |
+
|
19 |
+
|
20 |
+
def is_kuki(chat_id):
|
21 |
+
try:
|
22 |
+
chat = SESSION.query(KukiChats).get(str(chat_id))
|
23 |
+
return bool(chat)
|
24 |
+
finally:
|
25 |
+
SESSION.close()
|
26 |
+
|
27 |
+
|
28 |
+
def set_kuki(chat_id):
|
29 |
+
with INSERTION_LOCK:
|
30 |
+
kukichat = SESSION.query(KukiChats).get(str(chat_id))
|
31 |
+
if not kukichat:
|
32 |
+
kukichat = KukiChats(str(chat_id))
|
33 |
+
SESSION.add(kukichat)
|
34 |
+
SESSION.commit()
|
35 |
+
|
36 |
+
|
37 |
+
def rem_kuki(chat_id):
|
38 |
+
with INSERTION_LOCK:
|
39 |
+
kukichat = SESSION.query(KukiChats).get(str(chat_id))
|
40 |
+
if kukichat:
|
41 |
+
SESSION.delete(kukichat)
|
42 |
+
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
ADDED
@@ -0,0 +1,180 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
|
28 |
+
from sqlalchemy import BigInteger, Boolean, Column, String, distinct, func
|
29 |
+
|
30 |
+
from Database.sql import BASE, SESSION
|
31 |
+
|
32 |
+
|
33 |
+
class GroupLogs(BASE):
|
34 |
+
__tablename__ = "log_channels"
|
35 |
+
chat_id = Column(String(14), primary_key=True)
|
36 |
+
log_channel = Column(String(14), nullable=False)
|
37 |
+
|
38 |
+
def __init__(self, chat_id, log_channel):
|
39 |
+
self.chat_id = str(chat_id)
|
40 |
+
self.log_channel = str(log_channel)
|
41 |
+
|
42 |
+
|
43 |
+
class LogChannelSettings(BASE):
|
44 |
+
__tablename__ = "log_channel_setting"
|
45 |
+
chat_id = Column(BigInteger, primary_key=True)
|
46 |
+
log_joins = Column(Boolean, default=True)
|
47 |
+
log_leave = Column(Boolean, default=True)
|
48 |
+
log_warn = Column(Boolean, default=True)
|
49 |
+
log_action = Column(Boolean, default=True)
|
50 |
+
# log_media = Column(Boolean)
|
51 |
+
log_report = Column(Boolean, default=True)
|
52 |
+
|
53 |
+
def __init__(
|
54 |
+
self,
|
55 |
+
chat_id: int,
|
56 |
+
log_join: bool,
|
57 |
+
log_leave: bool,
|
58 |
+
log_warn: bool,
|
59 |
+
log_action: bool,
|
60 |
+
log_report: bool,
|
61 |
+
):
|
62 |
+
self.chat_id = chat_id
|
63 |
+
self.log_warn = log_warn
|
64 |
+
self.log_joins = log_join
|
65 |
+
self.log_leave = log_leave
|
66 |
+
self.log_report = log_report
|
67 |
+
self.log_action = log_action
|
68 |
+
|
69 |
+
def toggle_warn(self) -> bool:
|
70 |
+
self.log_warn = not self.log_warn
|
71 |
+
SESSION.commit()
|
72 |
+
return self.log_warn
|
73 |
+
|
74 |
+
def toggle_joins(self) -> bool:
|
75 |
+
self.log_joins = not self.log_joins
|
76 |
+
SESSION.commit()
|
77 |
+
return self.log_joins
|
78 |
+
|
79 |
+
def toggle_leave(self) -> bool:
|
80 |
+
self.log_leave = not self.log_leave
|
81 |
+
SESSION.commit()
|
82 |
+
return self.log_leave
|
83 |
+
|
84 |
+
def toggle_report(self) -> bool:
|
85 |
+
self.log_report = not self.log_report
|
86 |
+
SESSION.commit()
|
87 |
+
return self.log_report
|
88 |
+
|
89 |
+
def toggle_action(self) -> bool:
|
90 |
+
self.log_action = not self.log_action
|
91 |
+
SESSION.commit()
|
92 |
+
return self.log_action
|
93 |
+
|
94 |
+
|
95 |
+
GroupLogs.__table__.create(checkfirst=True)
|
96 |
+
LogChannelSettings.__table__.create(checkfirst=True)
|
97 |
+
|
98 |
+
LOGS_INSERTION_LOCK = threading.RLock()
|
99 |
+
LOG_SETTING_LOCK = threading.RLock()
|
100 |
+
CHANNELS = {}
|
101 |
+
|
102 |
+
|
103 |
+
def get_chat_setting(chat_id: int) -> typing.Optional[LogChannelSettings]:
|
104 |
+
with LOG_SETTING_LOCK:
|
105 |
+
return SESSION.query(LogChannelSettings).get(chat_id)
|
106 |
+
|
107 |
+
|
108 |
+
def set_chat_setting(setting: LogChannelSettings):
|
109 |
+
with LOGS_INSERTION_LOCK:
|
110 |
+
res: LogChannelSettings = SESSION.query(LogChannelSettings).get(setting.chat_id)
|
111 |
+
if res:
|
112 |
+
res.log_warn = setting.log_warn
|
113 |
+
res.log_action = setting.log_action
|
114 |
+
res.log_report = setting.log_report
|
115 |
+
res.log_joins = setting.log_joins
|
116 |
+
res.log_leave = setting.log_leave
|
117 |
+
else:
|
118 |
+
SESSION.add(setting)
|
119 |
+
SESSION.commit()
|
120 |
+
|
121 |
+
|
122 |
+
def set_chat_log_channel(chat_id, log_channel):
|
123 |
+
with LOGS_INSERTION_LOCK:
|
124 |
+
res = SESSION.query(GroupLogs).get(str(chat_id))
|
125 |
+
if res:
|
126 |
+
res.log_channel = log_channel
|
127 |
+
else:
|
128 |
+
res = GroupLogs(chat_id, log_channel)
|
129 |
+
SESSION.add(res)
|
130 |
+
|
131 |
+
CHANNELS[str(chat_id)] = log_channel
|
132 |
+
SESSION.commit()
|
133 |
+
|
134 |
+
|
135 |
+
def get_chat_log_channel(chat_id):
|
136 |
+
return CHANNELS.get(str(chat_id))
|
137 |
+
|
138 |
+
|
139 |
+
def stop_chat_logging(chat_id):
|
140 |
+
with LOGS_INSERTION_LOCK:
|
141 |
+
res = SESSION.query(GroupLogs).get(str(chat_id))
|
142 |
+
if res:
|
143 |
+
if str(chat_id) in CHANNELS:
|
144 |
+
del CHANNELS[str(chat_id)]
|
145 |
+
|
146 |
+
log_channel = res.log_channel
|
147 |
+
SESSION.delete(res)
|
148 |
+
SESSION.commit()
|
149 |
+
return log_channel
|
150 |
+
|
151 |
+
|
152 |
+
def num_logchannels():
|
153 |
+
try:
|
154 |
+
return SESSION.query(func.count(distinct(GroupLogs.chat_id))).scalar()
|
155 |
+
finally:
|
156 |
+
SESSION.close()
|
157 |
+
|
158 |
+
|
159 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
160 |
+
with LOGS_INSERTION_LOCK:
|
161 |
+
chat = SESSION.query(GroupLogs).get(str(old_chat_id))
|
162 |
+
if chat:
|
163 |
+
chat.chat_id = str(new_chat_id)
|
164 |
+
SESSION.add(chat)
|
165 |
+
if str(old_chat_id) in CHANNELS:
|
166 |
+
CHANNELS[str(new_chat_id)] = CHANNELS.get(str(old_chat_id))
|
167 |
+
|
168 |
+
SESSION.commit()
|
169 |
+
|
170 |
+
|
171 |
+
def __load_log_channels():
|
172 |
+
global CHANNELS
|
173 |
+
try:
|
174 |
+
all_chats = SESSION.query(GroupLogs).all()
|
175 |
+
CHANNELS = {chat.chat_id: chat.log_channel for chat in all_chats}
|
176 |
+
finally:
|
177 |
+
SESSION.close()
|
178 |
+
|
179 |
+
|
180 |
+
__load_log_channels()
|
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
ADDED
@@ -0,0 +1,210 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
32 |
+
|
33 |
+
|
34 |
+
class Notes(BASE):
|
35 |
+
__tablename__ = "notes"
|
36 |
+
chat_id = Column(String(14), primary_key=True)
|
37 |
+
name = Column(UnicodeText, primary_key=True)
|
38 |
+
value = Column(UnicodeText, nullable=False)
|
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
|
46 |
+
self.name = name
|
47 |
+
self.value = value
|
48 |
+
self.msgtype = msgtype
|
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)
|
61 |
+
url = Column(UnicodeText, nullable=False)
|
62 |
+
same_line = Column(Boolean, default=False)
|
63 |
+
|
64 |
+
def __init__(self, chat_id, note_name, name, url, same_line=False):
|
65 |
+
self.chat_id = str(chat_id)
|
66 |
+
self.note_name = note_name
|
67 |
+
self.name = name
|
68 |
+
self.url = url
|
69 |
+
self.same_line = same_line
|
70 |
+
|
71 |
+
|
72 |
+
Notes.__table__.create(checkfirst=True)
|
73 |
+
Buttons.__table__.create(checkfirst=True)
|
74 |
+
|
75 |
+
NOTES_INSERTION_LOCK = threading.RLock()
|
76 |
+
BUTTONS_INSERTION_LOCK = threading.RLock()
|
77 |
+
|
78 |
+
|
79 |
+
def add_note_to_db(chat_id, note_name, note_data, msgtype, buttons=None, file=None):
|
80 |
+
if not buttons:
|
81 |
+
buttons = []
|
82 |
+
|
83 |
+
with NOTES_INSERTION_LOCK:
|
84 |
+
prev = SESSION.query(Notes).get((str(chat_id), note_name))
|
85 |
+
if prev:
|
86 |
+
with BUTTONS_INSERTION_LOCK:
|
87 |
+
prev_buttons = (
|
88 |
+
SESSION.query(Buttons)
|
89 |
+
.filter(
|
90 |
+
Buttons.chat_id == str(chat_id),
|
91 |
+
Buttons.note_name == note_name,
|
92 |
+
)
|
93 |
+
.all()
|
94 |
+
)
|
95 |
+
for btn in prev_buttons:
|
96 |
+
SESSION.delete(btn)
|
97 |
+
SESSION.delete(prev)
|
98 |
+
note = Notes(
|
99 |
+
str(chat_id),
|
100 |
+
note_name,
|
101 |
+
note_data or "",
|
102 |
+
msgtype=msgtype.value,
|
103 |
+
file=file,
|
104 |
+
)
|
105 |
+
SESSION.add(note)
|
106 |
+
SESSION.commit()
|
107 |
+
|
108 |
+
for b_name, url, same_line in buttons:
|
109 |
+
add_note_button_to_db(chat_id, note_name, b_name, url, same_line)
|
110 |
+
|
111 |
+
|
112 |
+
def get_note(chat_id, note_name):
|
113 |
+
try:
|
114 |
+
return (
|
115 |
+
SESSION.query(Notes)
|
116 |
+
.filter(func.lower(Notes.name) == note_name, Notes.chat_id == str(chat_id))
|
117 |
+
.first()
|
118 |
+
)
|
119 |
+
finally:
|
120 |
+
SESSION.close()
|
121 |
+
|
122 |
+
|
123 |
+
def rm_note(chat_id, note_name):
|
124 |
+
with NOTES_INSERTION_LOCK:
|
125 |
+
note = (
|
126 |
+
SESSION.query(Notes)
|
127 |
+
.filter(func.lower(Notes.name) == note_name, Notes.chat_id == str(chat_id))
|
128 |
+
.first()
|
129 |
+
)
|
130 |
+
if note:
|
131 |
+
with BUTTONS_INSERTION_LOCK:
|
132 |
+
buttons = (
|
133 |
+
SESSION.query(Buttons)
|
134 |
+
.filter(
|
135 |
+
Buttons.chat_id == str(chat_id),
|
136 |
+
Buttons.note_name == note_name,
|
137 |
+
)
|
138 |
+
.all()
|
139 |
+
)
|
140 |
+
for btn in buttons:
|
141 |
+
SESSION.delete(btn)
|
142 |
+
|
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):
|
151 |
+
try:
|
152 |
+
return (
|
153 |
+
SESSION.query(Notes)
|
154 |
+
.filter(Notes.chat_id == str(chat_id))
|
155 |
+
.order_by(Notes.name.asc())
|
156 |
+
.all()
|
157 |
+
)
|
158 |
+
finally:
|
159 |
+
SESSION.close()
|
160 |
+
|
161 |
+
|
162 |
+
def add_note_button_to_db(chat_id, note_name, b_name, url, same_line):
|
163 |
+
with BUTTONS_INSERTION_LOCK:
|
164 |
+
button = Buttons(chat_id, note_name, b_name, url, same_line)
|
165 |
+
SESSION.add(button)
|
166 |
+
SESSION.commit()
|
167 |
+
|
168 |
+
|
169 |
+
def get_buttons(chat_id, note_name):
|
170 |
+
try:
|
171 |
+
return (
|
172 |
+
SESSION.query(Buttons)
|
173 |
+
.filter(Buttons.chat_id == str(chat_id), Buttons.note_name == note_name)
|
174 |
+
.order_by(Buttons.id)
|
175 |
+
.all()
|
176 |
+
)
|
177 |
+
finally:
|
178 |
+
SESSION.close()
|
179 |
+
|
180 |
+
|
181 |
+
def num_notes():
|
182 |
+
try:
|
183 |
+
return SESSION.query(Notes).count()
|
184 |
+
finally:
|
185 |
+
SESSION.close()
|
186 |
+
|
187 |
+
|
188 |
+
def num_chats():
|
189 |
+
try:
|
190 |
+
return SESSION.query(func.count(distinct(Notes.chat_id))).scalar()
|
191 |
+
finally:
|
192 |
+
SESSION.close()
|
193 |
+
|
194 |
+
|
195 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
196 |
+
with NOTES_INSERTION_LOCK:
|
197 |
+
chat_notes = (
|
198 |
+
SESSION.query(Notes).filter(Notes.chat_id == str(old_chat_id)).all()
|
199 |
+
)
|
200 |
+
for note in chat_notes:
|
201 |
+
note.chat_id = str(new_chat_id)
|
202 |
+
|
203 |
+
with BUTTONS_INSERTION_LOCK:
|
204 |
+
chat_buttons = (
|
205 |
+
SESSION.query(Buttons).filter(Buttons.chat_id == str(old_chat_id)).all()
|
206 |
+
)
|
207 |
+
for btn in chat_buttons:
|
208 |
+
btn.chat_id = str(new_chat_id)
|
209 |
+
|
210 |
+
SESSION.commit()
|
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/rules_sql.py
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import threading
|
2 |
+
|
3 |
+
from sqlalchemy import Column, String, UnicodeText, distinct, func
|
4 |
+
|
5 |
+
from Database.sql import BASE, SESSION
|
6 |
+
|
7 |
+
|
8 |
+
class Rules(BASE):
|
9 |
+
__tablename__ = "rules"
|
10 |
+
chat_id = Column(String(14), primary_key=True)
|
11 |
+
rules = Column(UnicodeText, default="")
|
12 |
+
|
13 |
+
def __init__(self, chat_id):
|
14 |
+
self.chat_id = chat_id
|
15 |
+
|
16 |
+
def __repr__(self):
|
17 |
+
return "<Chat {} rules: {}>".format(self.chat_id, self.rules)
|
18 |
+
|
19 |
+
|
20 |
+
Rules.__table__.create(checkfirst=True)
|
21 |
+
|
22 |
+
INSERTION_LOCK = threading.RLock()
|
23 |
+
|
24 |
+
|
25 |
+
def set_rules(chat_id, rules_text):
|
26 |
+
with INSERTION_LOCK:
|
27 |
+
rules = SESSION.query(Rules).get(str(chat_id))
|
28 |
+
if not rules:
|
29 |
+
rules = Rules(str(chat_id))
|
30 |
+
rules.rules = rules_text
|
31 |
+
|
32 |
+
SESSION.add(rules)
|
33 |
+
SESSION.commit()
|
34 |
+
|
35 |
+
|
36 |
+
def get_rules(chat_id):
|
37 |
+
rules = SESSION.query(Rules).get(str(chat_id))
|
38 |
+
ret = ""
|
39 |
+
if rules:
|
40 |
+
ret = rules.rules
|
41 |
+
|
42 |
+
SESSION.close()
|
43 |
+
return ret
|
44 |
+
|
45 |
+
|
46 |
+
def num_chats():
|
47 |
+
try:
|
48 |
+
return SESSION.query(func.count(distinct(Rules.chat_id))).scalar()
|
49 |
+
finally:
|
50 |
+
SESSION.close()
|
51 |
+
|
52 |
+
|
53 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
54 |
+
with INSERTION_LOCK:
|
55 |
+
chat = SESSION.query(Rules).get(str(old_chat_id))
|
56 |
+
if chat:
|
57 |
+
chat.chat_id = str(new_chat_id)
|
58 |
+
SESSION.commit()
|
Database/sql/userinfo_sql.py
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
28 |
+
|
29 |
+
from Database.sql import BASE, SESSION
|
30 |
+
|
31 |
+
|
32 |
+
class UserInfo(BASE):
|
33 |
+
__tablename__ = "userinfo"
|
34 |
+
user_id = Column(BigInteger, primary_key=True)
|
35 |
+
info = Column(UnicodeText)
|
36 |
+
|
37 |
+
def __init__(self, user_id, info):
|
38 |
+
self.user_id = user_id
|
39 |
+
self.info = info
|
40 |
+
|
41 |
+
def __repr__(self):
|
42 |
+
return "<ᴜsᴇʀ ɪɴғᴏ %d>" % self.user_id
|
43 |
+
|
44 |
+
|
45 |
+
class UserBio(BASE):
|
46 |
+
__tablename__ = "userbio"
|
47 |
+
user_id = Column(BigInteger, primary_key=True)
|
48 |
+
bio = Column(UnicodeText)
|
49 |
+
|
50 |
+
def __init__(self, user_id, bio):
|
51 |
+
self.user_id = user_id
|
52 |
+
self.bio = bio
|
53 |
+
|
54 |
+
def __repr__(self):
|
55 |
+
return "<ᴜsᴇʀ ɪɴғᴏ %d>" % self.user_id
|
56 |
+
|
57 |
+
|
58 |
+
UserInfo.__table__.create(checkfirst=True)
|
59 |
+
UserBio.__table__.create(checkfirst=True)
|
60 |
+
|
61 |
+
INSERTION_LOCK = threading.RLock()
|
62 |
+
|
63 |
+
|
64 |
+
def get_user_me_info(user_id):
|
65 |
+
userinfo = SESSION.query(UserInfo).get(user_id)
|
66 |
+
SESSION.close()
|
67 |
+
if userinfo:
|
68 |
+
return userinfo.info
|
69 |
+
return None
|
70 |
+
|
71 |
+
|
72 |
+
def set_user_me_info(user_id, info):
|
73 |
+
with INSERTION_LOCK:
|
74 |
+
userinfo = SESSION.query(UserInfo).get(user_id)
|
75 |
+
if userinfo:
|
76 |
+
userinfo.info = info
|
77 |
+
else:
|
78 |
+
userinfo = UserInfo(user_id, info)
|
79 |
+
SESSION.add(userinfo)
|
80 |
+
SESSION.commit()
|
81 |
+
|
82 |
+
|
83 |
+
def get_user_bio(user_id):
|
84 |
+
userbio = SESSION.query(UserBio).get(user_id)
|
85 |
+
SESSION.close()
|
86 |
+
if userbio:
|
87 |
+
return userbio.bio
|
88 |
+
return None
|
89 |
+
|
90 |
+
|
91 |
+
def set_user_bio(user_id, bio):
|
92 |
+
with INSERTION_LOCK:
|
93 |
+
userbio = SESSION.query(UserBio).get(user_id)
|
94 |
+
if userbio:
|
95 |
+
userbio.bio = bio
|
96 |
+
else:
|
97 |
+
userbio = UserBio(user_id, bio)
|
98 |
+
|
99 |
+
SESSION.add(userbio)
|
100 |
+
SESSION.commit()
|
Database/sql/users_sql.py
ADDED
@@ -0,0 +1,258 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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,
|
34 |
+
func,
|
35 |
+
)
|
36 |
+
|
37 |
+
from Database.sql import BASE, SESSION
|
38 |
+
from Mikobot import dispatcher
|
39 |
+
|
40 |
+
|
41 |
+
class Users(BASE):
|
42 |
+
__tablename__ = "users"
|
43 |
+
user_id = Column(BigInteger, primary_key=True)
|
44 |
+
username = Column(UnicodeText)
|
45 |
+
|
46 |
+
def __init__(self, user_id, username=None):
|
47 |
+
self.user_id = user_id
|
48 |
+
self.username = username
|
49 |
+
|
50 |
+
def __repr__(self):
|
51 |
+
return "<ᴜsᴇʀ {} ({})>".format(self.username, self.user_id)
|
52 |
+
|
53 |
+
|
54 |
+
class Chats(BASE):
|
55 |
+
__tablename__ = "chats"
|
56 |
+
chat_id = Column(String(14), primary_key=True)
|
57 |
+
chat_name = Column(UnicodeText, nullable=False)
|
58 |
+
|
59 |
+
def __init__(self, chat_id, chat_name):
|
60 |
+
self.chat_id = str(chat_id)
|
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),
|
73 |
+
ForeignKey("chats.chat_id", onupdate="CASCADE", ondelete="CASCADE"),
|
74 |
+
nullable=False,
|
75 |
+
)
|
76 |
+
user = Column(
|
77 |
+
BigInteger,
|
78 |
+
ForeignKey("users.user_id", onupdate="CASCADE", ondelete="CASCADE"),
|
79 |
+
nullable=False,
|
80 |
+
)
|
81 |
+
__table_args__ = (UniqueConstraint("chat", "user", name="_chat_members_uc"),)
|
82 |
+
|
83 |
+
def __init__(self, chat, user):
|
84 |
+
self.chat = chat
|
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,
|
92 |
+
self.chat.chat_id,
|
93 |
+
)
|
94 |
+
|
95 |
+
|
96 |
+
Users.__table__.create(checkfirst=True)
|
97 |
+
Chats.__table__.create(checkfirst=True)
|
98 |
+
ChatMembers.__table__.create(checkfirst=True)
|
99 |
+
|
100 |
+
INSERTION_LOCK = threading.RLock()
|
101 |
+
|
102 |
+
|
103 |
+
def ensure_bot_in_db():
|
104 |
+
with INSERTION_LOCK:
|
105 |
+
bot = Users(dispatcher.bot.id, dispatcher.bot.username)
|
106 |
+
SESSION.merge(bot)
|
107 |
+
SESSION.commit()
|
108 |
+
|
109 |
+
|
110 |
+
def update_user(user_id, username, chat_id=None, chat_name=None):
|
111 |
+
with INSERTION_LOCK:
|
112 |
+
user = SESSION.query(Users).get(user_id)
|
113 |
+
if not user:
|
114 |
+
user = Users(user_id, username)
|
115 |
+
SESSION.add(user)
|
116 |
+
SESSION.flush()
|
117 |
+
else:
|
118 |
+
user.username = username
|
119 |
+
|
120 |
+
if not chat_id or not chat_name:
|
121 |
+
SESSION.commit()
|
122 |
+
return
|
123 |
+
|
124 |
+
chat = SESSION.query(Chats).get(str(chat_id))
|
125 |
+
if not chat:
|
126 |
+
chat = Chats(str(chat_id), chat_name)
|
127 |
+
SESSION.add(chat)
|
128 |
+
SESSION.flush()
|
129 |
+
|
130 |
+
else:
|
131 |
+
chat.chat_name = chat_name
|
132 |
+
|
133 |
+
member = (
|
134 |
+
SESSION.query(ChatMembers)
|
135 |
+
.filter(ChatMembers.chat == chat.chat_id, ChatMembers.user == user.user_id)
|
136 |
+
.first()
|
137 |
+
)
|
138 |
+
if not member:
|
139 |
+
chat_member = ChatMembers(chat.chat_id, user.user_id)
|
140 |
+
SESSION.add(chat_member)
|
141 |
+
|
142 |
+
SESSION.commit()
|
143 |
+
|
144 |
+
|
145 |
+
def get_userid_by_name(username):
|
146 |
+
try:
|
147 |
+
return (
|
148 |
+
SESSION.query(Users)
|
149 |
+
.filter(func.lower(Users.username) == username.lower())
|
150 |
+
.all()
|
151 |
+
)
|
152 |
+
finally:
|
153 |
+
SESSION.close()
|
154 |
+
|
155 |
+
|
156 |
+
def get_name_by_userid(user_id):
|
157 |
+
try:
|
158 |
+
return SESSION.query(Users).get(Users.user_id == int(user_id)).first()
|
159 |
+
finally:
|
160 |
+
SESSION.close()
|
161 |
+
|
162 |
+
|
163 |
+
def get_chat_members(chat_id):
|
164 |
+
try:
|
165 |
+
return SESSION.query(ChatMembers).filter(ChatMembers.chat == str(chat_id)).all()
|
166 |
+
finally:
|
167 |
+
SESSION.close()
|
168 |
+
|
169 |
+
|
170 |
+
def get_all_chats():
|
171 |
+
try:
|
172 |
+
return SESSION.query(Chats).all()
|
173 |
+
finally:
|
174 |
+
SESSION.close()
|
175 |
+
|
176 |
+
|
177 |
+
def get_all_users():
|
178 |
+
try:
|
179 |
+
return SESSION.query(Users).all()
|
180 |
+
finally:
|
181 |
+
SESSION.close()
|
182 |
+
|
183 |
+
|
184 |
+
def get_user_num_chats(user_id):
|
185 |
+
try:
|
186 |
+
return (
|
187 |
+
SESSION.query(ChatMembers).filter(ChatMembers.user == int(user_id)).count()
|
188 |
+
)
|
189 |
+
finally:
|
190 |
+
SESSION.close()
|
191 |
+
|
192 |
+
|
193 |
+
def get_user_com_chats(user_id):
|
194 |
+
try:
|
195 |
+
chat_members = (
|
196 |
+
SESSION.query(ChatMembers).filter(ChatMembers.user == int(user_id)).all()
|
197 |
+
)
|
198 |
+
return [i.chat for i in chat_members]
|
199 |
+
finally:
|
200 |
+
SESSION.close()
|
201 |
+
|
202 |
+
|
203 |
+
def num_chats():
|
204 |
+
try:
|
205 |
+
return SESSION.query(Chats).count()
|
206 |
+
finally:
|
207 |
+
SESSION.close()
|
208 |
+
|
209 |
+
|
210 |
+
def num_users():
|
211 |
+
try:
|
212 |
+
return SESSION.query(Users).count()
|
213 |
+
finally:
|
214 |
+
SESSION.close()
|
215 |
+
|
216 |
+
|
217 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
218 |
+
with INSERTION_LOCK:
|
219 |
+
chat = SESSION.query(Chats).get(str(old_chat_id))
|
220 |
+
if chat:
|
221 |
+
chat.chat_id = str(new_chat_id)
|
222 |
+
SESSION.commit()
|
223 |
+
|
224 |
+
chat_members = (
|
225 |
+
SESSION.query(ChatMembers)
|
226 |
+
.filter(ChatMembers.chat == str(old_chat_id))
|
227 |
+
.all()
|
228 |
+
)
|
229 |
+
for member in chat_members:
|
230 |
+
member.chat = str(new_chat_id)
|
231 |
+
SESSION.commit()
|
232 |
+
|
233 |
+
|
234 |
+
ensure_bot_in_db()
|
235 |
+
|
236 |
+
|
237 |
+
def del_user(user_id):
|
238 |
+
with INSERTION_LOCK:
|
239 |
+
curr = SESSION.query(Users).get(user_id)
|
240 |
+
if curr:
|
241 |
+
SESSION.delete(curr)
|
242 |
+
SESSION.commit()
|
243 |
+
return True
|
244 |
+
|
245 |
+
ChatMembers.query.filter(ChatMembers.user == user_id).delete()
|
246 |
+
SESSION.commit()
|
247 |
+
SESSION.close()
|
248 |
+
return False
|
249 |
+
|
250 |
+
|
251 |
+
def rem_chat(chat_id):
|
252 |
+
with INSERTION_LOCK:
|
253 |
+
chat = SESSION.query(Chats).get(str(chat_id))
|
254 |
+
if chat:
|
255 |
+
SESSION.delete(chat)
|
256 |
+
SESSION.commit()
|
257 |
+
else:
|
258 |
+
SESSION.close()
|
Database/sql/warns_sql.py
ADDED
@@ -0,0 +1,341 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
31 |
+
|
32 |
+
|
33 |
+
class Warns(BASE):
|
34 |
+
__tablename__ = "warns"
|
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):
|
42 |
+
self.user_id = user_id
|
43 |
+
self.chat_id = str(chat_id)
|
44 |
+
self.num_warns = 0
|
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,
|
52 |
+
self.reasons,
|
53 |
+
)
|
54 |
+
|
55 |
+
|
56 |
+
class WarnFilters(BASE):
|
57 |
+
__tablename__ = "warn_filters"
|
58 |
+
chat_id = Column(String(14), primary_key=True)
|
59 |
+
keyword = Column(UnicodeText, primary_key=True, nullable=False)
|
60 |
+
reply = Column(UnicodeText, nullable=False)
|
61 |
+
|
62 |
+
def __init__(self, chat_id, keyword, reply):
|
63 |
+
self.chat_id = str(chat_id) # ensure string
|
64 |
+
self.keyword = keyword
|
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(
|
72 |
+
isinstance(other, WarnFilters)
|
73 |
+
and self.chat_id == other.chat_id
|
74 |
+
and self.keyword == other.keyword,
|
75 |
+
)
|
76 |
+
|
77 |
+
|
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):
|
85 |
+
self.chat_id = str(chat_id)
|
86 |
+
self.warn_limit = warn_limit
|
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)
|
94 |
+
WarnFilters.__table__.create(checkfirst=True)
|
95 |
+
WarnSettings.__table__.create(checkfirst=True)
|
96 |
+
|
97 |
+
WARN_INSERTION_LOCK = threading.RLock()
|
98 |
+
WARN_FILTER_INSERTION_LOCK = threading.RLock()
|
99 |
+
WARN_SETTINGS_LOCK = threading.RLock()
|
100 |
+
|
101 |
+
WARN_FILTERS = {}
|
102 |
+
|
103 |
+
|
104 |
+
def warn_user(user_id, chat_id, reason=None):
|
105 |
+
with WARN_INSERTION_LOCK:
|
106 |
+
warned_user = SESSION.query(Warns).get((user_id, str(chat_id)))
|
107 |
+
if not warned_user:
|
108 |
+
warned_user = Warns(user_id, str(chat_id))
|
109 |
+
|
110 |
+
warned_user.num_warns += 1
|
111 |
+
if reason:
|
112 |
+
warned_user.reasons = warned_user.reasons + [
|
113 |
+
reason,
|
114 |
+
] # TODO:: double check this wizardry
|
115 |
+
|
116 |
+
reasons = warned_user.reasons
|
117 |
+
num = warned_user.num_warns
|
118 |
+
|
119 |
+
SESSION.add(warned_user)
|
120 |
+
SESSION.commit()
|
121 |
+
|
122 |
+
return num, reasons
|
123 |
+
|
124 |
+
|
125 |
+
def remove_warn(user_id, chat_id):
|
126 |
+
with WARN_INSERTION_LOCK:
|
127 |
+
removed = False
|
128 |
+
warned_user = SESSION.query(Warns).get((user_id, str(chat_id)))
|
129 |
+
|
130 |
+
if warned_user and warned_user.num_warns > 0:
|
131 |
+
warned_user.num_warns -= 1
|
132 |
+
warned_user.reasons = warned_user.reasons[:-1]
|
133 |
+
SESSION.add(warned_user)
|
134 |
+
SESSION.commit()
|
135 |
+
removed = True
|
136 |
+
|
137 |
+
SESSION.close()
|
138 |
+
return removed
|
139 |
+
|
140 |
+
|
141 |
+
def reset_warns(user_id, chat_id):
|
142 |
+
with WARN_INSERTION_LOCK:
|
143 |
+
warned_user = SESSION.query(Warns).get((user_id, str(chat_id)))
|
144 |
+
if warned_user:
|
145 |
+
warned_user.num_warns = 0
|
146 |
+
warned_user.reasons = []
|
147 |
+
|
148 |
+
SESSION.add(warned_user)
|
149 |
+
SESSION.commit()
|
150 |
+
SESSION.close()
|
151 |
+
|
152 |
+
|
153 |
+
def get_warns(user_id, chat_id):
|
154 |
+
try:
|
155 |
+
user = SESSION.query(Warns).get((user_id, str(chat_id)))
|
156 |
+
if not user:
|
157 |
+
return None
|
158 |
+
reasons = user.reasons
|
159 |
+
num = user.num_warns
|
160 |
+
return num, reasons
|
161 |
+
finally:
|
162 |
+
SESSION.close()
|
163 |
+
|
164 |
+
|
165 |
+
def add_warn_filter(chat_id, keyword, reply):
|
166 |
+
with WARN_FILTER_INSERTION_LOCK:
|
167 |
+
warn_filt = WarnFilters(str(chat_id), keyword, reply)
|
168 |
+
|
169 |
+
if keyword not in WARN_FILTERS.get(str(chat_id), []):
|
170 |
+
WARN_FILTERS[str(chat_id)] = sorted(
|
171 |
+
WARN_FILTERS.get(str(chat_id), []) + [keyword],
|
172 |
+
key=lambda x: (-len(x), x),
|
173 |
+
)
|
174 |
+
|
175 |
+
SESSION.merge(warn_filt) # merge to avoid duplicate key issues
|
176 |
+
SESSION.commit()
|
177 |
+
|
178 |
+
|
179 |
+
def remove_warn_filter(chat_id, keyword):
|
180 |
+
with WARN_FILTER_INSERTION_LOCK:
|
181 |
+
warn_filt = SESSION.query(WarnFilters).get((str(chat_id), keyword))
|
182 |
+
if warn_filt:
|
183 |
+
if keyword in WARN_FILTERS.get(str(chat_id), []): # sanity check
|
184 |
+
WARN_FILTERS.get(str(chat_id), []).remove(keyword)
|
185 |
+
|
186 |
+
SESSION.delete(warn_filt)
|
187 |
+
SESSION.commit()
|
188 |
+
return True
|
189 |
+
SESSION.close()
|
190 |
+
return False
|
191 |
+
|
192 |
+
|
193 |
+
def get_chat_warn_triggers(chat_id):
|
194 |
+
return WARN_FILTERS.get(str(chat_id), set())
|
195 |
+
|
196 |
+
|
197 |
+
def get_chat_warn_filters(chat_id):
|
198 |
+
try:
|
199 |
+
return (
|
200 |
+
SESSION.query(WarnFilters).filter(WarnFilters.chat_id == str(chat_id)).all()
|
201 |
+
)
|
202 |
+
finally:
|
203 |
+
SESSION.close()
|
204 |
+
|
205 |
+
|
206 |
+
def get_warn_filter(chat_id, keyword):
|
207 |
+
try:
|
208 |
+
return SESSION.query(WarnFilters).get((str(chat_id), keyword))
|
209 |
+
finally:
|
210 |
+
SESSION.close()
|
211 |
+
|
212 |
+
|
213 |
+
def set_warn_limit(chat_id, warn_limit):
|
214 |
+
with WARN_SETTINGS_LOCK:
|
215 |
+
curr_setting = SESSION.query(WarnSettings).get(str(chat_id))
|
216 |
+
if not curr_setting:
|
217 |
+
curr_setting = WarnSettings(chat_id, warn_limit=warn_limit)
|
218 |
+
|
219 |
+
curr_setting.warn_limit = warn_limit
|
220 |
+
|
221 |
+
SESSION.add(curr_setting)
|
222 |
+
SESSION.commit()
|
223 |
+
|
224 |
+
|
225 |
+
def set_warn_strength(chat_id, soft_warn):
|
226 |
+
with WARN_SETTINGS_LOCK:
|
227 |
+
curr_setting = SESSION.query(WarnSettings).get(str(chat_id))
|
228 |
+
if not curr_setting:
|
229 |
+
curr_setting = WarnSettings(chat_id, soft_warn=soft_warn)
|
230 |
+
|
231 |
+
curr_setting.soft_warn = soft_warn
|
232 |
+
|
233 |
+
SESSION.add(curr_setting)
|
234 |
+
SESSION.commit()
|
235 |
+
|
236 |
+
|
237 |
+
def get_warn_setting(chat_id):
|
238 |
+
try:
|
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()
|
246 |
+
|
247 |
+
|
248 |
+
def num_warns():
|
249 |
+
try:
|
250 |
+
return SESSION.query(func.sum(Warns.num_warns)).scalar() or 0
|
251 |
+
finally:
|
252 |
+
SESSION.close()
|
253 |
+
|
254 |
+
|
255 |
+
def num_warn_chats():
|
256 |
+
try:
|
257 |
+
return SESSION.query(func.count(distinct(Warns.chat_id))).scalar()
|
258 |
+
finally:
|
259 |
+
SESSION.close()
|
260 |
+
|
261 |
+
|
262 |
+
def num_warn_filters():
|
263 |
+
try:
|
264 |
+
return SESSION.query(WarnFilters).count()
|
265 |
+
finally:
|
266 |
+
SESSION.close()
|
267 |
+
|
268 |
+
|
269 |
+
def num_warn_chat_filters(chat_id):
|
270 |
+
try:
|
271 |
+
return (
|
272 |
+
SESSION.query(WarnFilters.chat_id)
|
273 |
+
.filter(WarnFilters.chat_id == str(chat_id))
|
274 |
+
.count()
|
275 |
+
)
|
276 |
+
finally:
|
277 |
+
SESSION.close()
|
278 |
+
|
279 |
+
|
280 |
+
def num_warn_filter_chats():
|
281 |
+
try:
|
282 |
+
return SESSION.query(func.count(distinct(WarnFilters.chat_id))).scalar()
|
283 |
+
finally:
|
284 |
+
SESSION.close()
|
285 |
+
|
286 |
+
|
287 |
+
def __load_chat_warn_filters():
|
288 |
+
global WARN_FILTERS
|
289 |
+
try:
|
290 |
+
chats = SESSION.query(WarnFilters.chat_id).distinct().all()
|
291 |
+
for (chat_id,) in chats: # remove tuple by ( ,)
|
292 |
+
WARN_FILTERS[chat_id] = []
|
293 |
+
|
294 |
+
all_filters = SESSION.query(WarnFilters).all()
|
295 |
+
for x in all_filters:
|
296 |
+
WARN_FILTERS[x.chat_id] += [x.keyword]
|
297 |
+
|
298 |
+
WARN_FILTERS = {
|
299 |
+
x: sorted(set(y), key=lambda i: (-len(i), i))
|
300 |
+
for x, y in WARN_FILTERS.items()
|
301 |
+
}
|
302 |
+
|
303 |
+
finally:
|
304 |
+
SESSION.close()
|
305 |
+
|
306 |
+
|
307 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
308 |
+
with WARN_INSERTION_LOCK:
|
309 |
+
chat_notes = (
|
310 |
+
SESSION.query(Warns).filter(Warns.chat_id == str(old_chat_id)).all()
|
311 |
+
)
|
312 |
+
for note in chat_notes:
|
313 |
+
note.chat_id = str(new_chat_id)
|
314 |
+
SESSION.commit()
|
315 |
+
|
316 |
+
with WARN_FILTER_INSERTION_LOCK:
|
317 |
+
chat_filters = (
|
318 |
+
SESSION.query(WarnFilters)
|
319 |
+
.filter(WarnFilters.chat_id == str(old_chat_id))
|
320 |
+
.all()
|
321 |
+
)
|
322 |
+
for filt in chat_filters:
|
323 |
+
filt.chat_id = str(new_chat_id)
|
324 |
+
SESSION.commit()
|
325 |
+
old_warn_filt = WARN_FILTERS.get(str(old_chat_id))
|
326 |
+
if old_warn_filt is not None:
|
327 |
+
WARN_FILTERS[str(new_chat_id)] = old_warn_filt
|
328 |
+
del WARN_FILTERS[str(old_chat_id)]
|
329 |
+
|
330 |
+
with WARN_SETTINGS_LOCK:
|
331 |
+
chat_settings = (
|
332 |
+
SESSION.query(WarnSettings)
|
333 |
+
.filter(WarnSettings.chat_id == str(old_chat_id))
|
334 |
+
.all()
|
335 |
+
)
|
336 |
+
for setting in chat_settings:
|
337 |
+
setting.chat_id = str(new_chat_id)
|
338 |
+
SESSION.commit()
|
339 |
+
|
340 |
+
|
341 |
+
__load_chat_warn_filters()
|
Database/sql/welcome_sql.py
ADDED
@@ -0,0 +1,507 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
28 |
+
|
29 |
+
from sqlalchemy import BigInteger, Boolean, Column, Integer, String, UnicodeText
|
30 |
+
|
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):
|
50 |
+
__tablename__ = "welcome_pref"
|
51 |
+
chat_id = Column(String(14), primary_key=True)
|
52 |
+
should_welcome = Column(Boolean, default=True)
|
53 |
+
should_goodbye = Column(Boolean, default=True)
|
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 |
+
|
61 |
+
custom_leave = Column(UnicodeText, default=random.choice(DEFAULT_GOODBYE_MESSAGES))
|
62 |
+
leave_type = Column(Integer, default=Types.TEXT.value)
|
63 |
+
|
64 |
+
clean_welcome = Column(BigInteger)
|
65 |
+
|
66 |
+
def __init__(self, chat_id, should_welcome=True, should_goodbye=True):
|
67 |
+
self.chat_id = chat_id
|
68 |
+
self.should_welcome = should_welcome
|
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 |
+
|
77 |
+
class WelcomeButtons(BASE):
|
78 |
+
__tablename__ = "welcome_urls"
|
79 |
+
id = Column(Integer, primary_key=True, autoincrement=True)
|
80 |
+
chat_id = Column(String(14), primary_key=True)
|
81 |
+
name = Column(UnicodeText, nullable=False)
|
82 |
+
url = Column(UnicodeText, nullable=False)
|
83 |
+
same_line = Column(Boolean, default=False)
|
84 |
+
|
85 |
+
def __init__(self, chat_id, name, url, same_line=False):
|
86 |
+
self.chat_id = str(chat_id)
|
87 |
+
self.name = name
|
88 |
+
self.url = url
|
89 |
+
self.same_line = same_line
|
90 |
+
|
91 |
+
|
92 |
+
class GoodbyeButtons(BASE):
|
93 |
+
__tablename__ = "leave_urls"
|
94 |
+
id = Column(Integer, primary_key=True, autoincrement=True)
|
95 |
+
chat_id = Column(String(14), primary_key=True)
|
96 |
+
name = Column(UnicodeText, nullable=False)
|
97 |
+
url = Column(UnicodeText, nullable=False)
|
98 |
+
same_line = Column(Boolean, default=False)
|
99 |
+
|
100 |
+
def __init__(self, chat_id, name, url, same_line=False):
|
101 |
+
self.chat_id = str(chat_id)
|
102 |
+
self.name = name
|
103 |
+
self.url = url
|
104 |
+
self.same_line = same_line
|
105 |
+
|
106 |
+
|
107 |
+
class WelcomeMute(BASE):
|
108 |
+
__tablename__ = "welcome_mutes"
|
109 |
+
chat_id = Column(String(14), primary_key=True)
|
110 |
+
welcomemutes = Column(UnicodeText, default=False)
|
111 |
+
|
112 |
+
def __init__(self, chat_id, welcomemutes):
|
113 |
+
self.chat_id = str(chat_id) # ensure string
|
114 |
+
self.welcomemutes = welcomemutes
|
115 |
+
|
116 |
+
|
117 |
+
class WelcomeMuteUsers(BASE):
|
118 |
+
__tablename__ = "human_checks"
|
119 |
+
user_id = Column(BigInteger, primary_key=True)
|
120 |
+
chat_id = Column(String(14), primary_key=True)
|
121 |
+
human_check = Column(Boolean)
|
122 |
+
|
123 |
+
def __init__(self, user_id, chat_id, human_check):
|
124 |
+
self.user_id = user_id # ensure string
|
125 |
+
self.chat_id = str(chat_id)
|
126 |
+
self.human_check = human_check
|
127 |
+
|
128 |
+
|
129 |
+
class CleanServiceSetting(BASE):
|
130 |
+
__tablename__ = "clean_service"
|
131 |
+
chat_id = Column(String(14), primary_key=True)
|
132 |
+
clean_service = Column(Boolean, default=True)
|
133 |
+
|
134 |
+
def __init__(self, chat_id):
|
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)
|
158 |
+
WelcomeButtons.__table__.create(checkfirst=True)
|
159 |
+
GoodbyeButtons.__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):
|
174 |
+
try:
|
175 |
+
welcomemutes = SESSION.query(WelcomeMute).get(str(chat_id))
|
176 |
+
if welcomemutes:
|
177 |
+
return welcomemutes.welcomemutes
|
178 |
+
return False
|
179 |
+
finally:
|
180 |
+
SESSION.close()
|
181 |
+
|
182 |
+
|
183 |
+
def set_welcome_mutes(chat_id, welcomemutes):
|
184 |
+
with WM_LOCK:
|
185 |
+
prev = SESSION.query(WelcomeMute).get((str(chat_id)))
|
186 |
+
if prev:
|
187 |
+
SESSION.delete(prev)
|
188 |
+
welcome_m = WelcomeMute(str(chat_id), welcomemutes)
|
189 |
+
SESSION.add(welcome_m)
|
190 |
+
SESSION.commit()
|
191 |
+
|
192 |
+
|
193 |
+
def set_human_checks(user_id, chat_id):
|
194 |
+
with INSERTION_LOCK:
|
195 |
+
human_check = SESSION.query(WelcomeMuteUsers).get((user_id, str(chat_id)))
|
196 |
+
if not human_check:
|
197 |
+
human_check = WelcomeMuteUsers(user_id, str(chat_id), True)
|
198 |
+
|
199 |
+
else:
|
200 |
+
human_check.human_check = True
|
201 |
+
|
202 |
+
SESSION.add(human_check)
|
203 |
+
SESSION.commit()
|
204 |
+
|
205 |
+
return human_check
|
206 |
+
|
207 |
+
|
208 |
+
def get_human_checks(user_id, chat_id):
|
209 |
+
try:
|
210 |
+
human_check = SESSION.query(WelcomeMuteUsers).get((user_id, str(chat_id)))
|
211 |
+
if not human_check:
|
212 |
+
return None
|
213 |
+
human_check = human_check.human_check
|
214 |
+
return human_check
|
215 |
+
finally:
|
216 |
+
SESSION.close()
|
217 |
+
|
218 |
+
|
219 |
+
def get_welc_mutes_pref(chat_id):
|
220 |
+
welcomemutes = SESSION.query(WelcomeMute).get(str(chat_id))
|
221 |
+
SESSION.close()
|
222 |
+
|
223 |
+
if welcomemutes:
|
224 |
+
return welcomemutes.welcomemutes
|
225 |
+
|
226 |
+
return False
|
227 |
+
|
228 |
+
|
229 |
+
def get_welc_pref(chat_id):
|
230 |
+
welc = SESSION.query(Welcome).get(str(chat_id))
|
231 |
+
SESSION.close()
|
232 |
+
if welc:
|
233 |
+
return (
|
234 |
+
welc.should_welcome,
|
235 |
+
welc.custom_welcome,
|
236 |
+
welc.custom_content,
|
237 |
+
welc.welcome_type,
|
238 |
+
)
|
239 |
+
|
240 |
+
else:
|
241 |
+
# Welcome by default.
|
242 |
+
return True, DEFAULT_WELCOME, None, Types.TEXT
|
243 |
+
|
244 |
+
|
245 |
+
def get_gdbye_pref(chat_id):
|
246 |
+
welc = SESSION.query(Welcome).get(str(chat_id))
|
247 |
+
SESSION.close()
|
248 |
+
if welc:
|
249 |
+
return welc.should_goodbye, welc.custom_leave, welc.leave_type
|
250 |
+
else:
|
251 |
+
# Welcome by default.
|
252 |
+
return True, DEFAULT_GOODBYE, Types.TEXT
|
253 |
+
|
254 |
+
|
255 |
+
def set_clean_welcome(chat_id, clean_welcome):
|
256 |
+
with INSERTION_LOCK:
|
257 |
+
curr = SESSION.query(Welcome).get(str(chat_id))
|
258 |
+
if not curr:
|
259 |
+
curr = Welcome(str(chat_id))
|
260 |
+
|
261 |
+
curr.clean_welcome = int(clean_welcome)
|
262 |
+
|
263 |
+
SESSION.add(curr)
|
264 |
+
SESSION.commit()
|
265 |
+
|
266 |
+
|
267 |
+
def get_clean_pref(chat_id):
|
268 |
+
welc = SESSION.query(Welcome).get(str(chat_id))
|
269 |
+
SESSION.close()
|
270 |
+
|
271 |
+
if welc:
|
272 |
+
return welc.clean_welcome
|
273 |
+
|
274 |
+
return False
|
275 |
+
|
276 |
+
|
277 |
+
def set_welc_preference(chat_id, should_welcome):
|
278 |
+
with INSERTION_LOCK:
|
279 |
+
curr = SESSION.query(Welcome).get(str(chat_id))
|
280 |
+
if not curr:
|
281 |
+
curr = Welcome(str(chat_id), should_welcome=should_welcome)
|
282 |
+
else:
|
283 |
+
curr.should_welcome = should_welcome
|
284 |
+
|
285 |
+
SESSION.add(curr)
|
286 |
+
SESSION.commit()
|
287 |
+
|
288 |
+
|
289 |
+
def set_gdbye_preference(chat_id, should_goodbye):
|
290 |
+
with INSERTION_LOCK:
|
291 |
+
curr = SESSION.query(Welcome).get(str(chat_id))
|
292 |
+
if not curr:
|
293 |
+
curr = Welcome(str(chat_id), should_goodbye=should_goodbye)
|
294 |
+
else:
|
295 |
+
curr.should_goodbye = should_goodbye
|
296 |
+
|
297 |
+
SESSION.add(curr)
|
298 |
+
SESSION.commit()
|
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 = []
|
306 |
+
|
307 |
+
with INSERTION_LOCK:
|
308 |
+
welcome_settings = SESSION.query(Welcome).get(str(chat_id))
|
309 |
+
if not welcome_settings:
|
310 |
+
welcome_settings = Welcome(str(chat_id), True)
|
311 |
+
|
312 |
+
if custom_welcome or custom_content:
|
313 |
+
welcome_settings.custom_content = custom_content
|
314 |
+
welcome_settings.custom_welcome = custom_welcome
|
315 |
+
welcome_settings.welcome_type = welcome_type.value
|
316 |
+
|
317 |
+
else:
|
318 |
+
welcome_settings.custom_welcome = DEFAULT_WELCOME
|
319 |
+
welcome_settings.welcome_type = Types.TEXT.value
|
320 |
+
|
321 |
+
SESSION.add(welcome_settings)
|
322 |
+
|
323 |
+
with WELC_BTN_LOCK:
|
324 |
+
prev_buttons = (
|
325 |
+
SESSION.query(WelcomeButtons)
|
326 |
+
.filter(WelcomeButtons.chat_id == str(chat_id))
|
327 |
+
.all()
|
328 |
+
)
|
329 |
+
for btn in prev_buttons:
|
330 |
+
SESSION.delete(btn)
|
331 |
+
|
332 |
+
for b_name, url, same_line in buttons:
|
333 |
+
button = WelcomeButtons(chat_id, b_name, url, same_line)
|
334 |
+
SESSION.add(button)
|
335 |
+
|
336 |
+
SESSION.commit()
|
337 |
+
|
338 |
+
|
339 |
+
def get_custom_welcome(chat_id):
|
340 |
+
welcome_settings = SESSION.query(Welcome).get(str(chat_id))
|
341 |
+
ret = DEFAULT_WELCOME
|
342 |
+
if welcome_settings and welcome_settings.custom_welcome:
|
343 |
+
ret = welcome_settings.custom_welcome
|
344 |
+
|
345 |
+
SESSION.close()
|
346 |
+
return ret
|
347 |
+
|
348 |
+
|
349 |
+
def set_custom_gdbye(chat_id, custom_goodbye, goodbye_type, buttons=None):
|
350 |
+
if buttons is None:
|
351 |
+
buttons = []
|
352 |
+
|
353 |
+
with INSERTION_LOCK:
|
354 |
+
welcome_settings = SESSION.query(Welcome).get(str(chat_id))
|
355 |
+
if not welcome_settings:
|
356 |
+
welcome_settings = Welcome(str(chat_id), True)
|
357 |
+
|
358 |
+
if custom_goodbye:
|
359 |
+
welcome_settings.custom_leave = custom_goodbye
|
360 |
+
welcome_settings.leave_type = goodbye_type.value
|
361 |
+
|
362 |
+
else:
|
363 |
+
welcome_settings.custom_leave = DEFAULT_GOODBYE
|
364 |
+
welcome_settings.leave_type = Types.TEXT.value
|
365 |
+
|
366 |
+
SESSION.add(welcome_settings)
|
367 |
+
|
368 |
+
with LEAVE_BTN_LOCK:
|
369 |
+
prev_buttons = (
|
370 |
+
SESSION.query(GoodbyeButtons)
|
371 |
+
.filter(GoodbyeButtons.chat_id == str(chat_id))
|
372 |
+
.all()
|
373 |
+
)
|
374 |
+
for btn in prev_buttons:
|
375 |
+
SESSION.delete(btn)
|
376 |
+
|
377 |
+
for b_name, url, same_line in buttons:
|
378 |
+
button = GoodbyeButtons(chat_id, b_name, url, same_line)
|
379 |
+
SESSION.add(button)
|
380 |
+
|
381 |
+
SESSION.commit()
|
382 |
+
|
383 |
+
|
384 |
+
def get_custom_gdbye(chat_id):
|
385 |
+
welcome_settings = SESSION.query(Welcome).get(str(chat_id))
|
386 |
+
ret = DEFAULT_GOODBYE
|
387 |
+
if welcome_settings and welcome_settings.custom_leave:
|
388 |
+
ret = welcome_settings.custom_leave
|
389 |
+
|
390 |
+
SESSION.close()
|
391 |
+
return ret
|
392 |
+
|
393 |
+
|
394 |
+
def get_welc_buttons(chat_id):
|
395 |
+
try:
|
396 |
+
return (
|
397 |
+
SESSION.query(WelcomeButtons)
|
398 |
+
.filter(WelcomeButtons.chat_id == str(chat_id))
|
399 |
+
.order_by(WelcomeButtons.id)
|
400 |
+
.all()
|
401 |
+
)
|
402 |
+
finally:
|
403 |
+
SESSION.close()
|
404 |
+
|
405 |
+
|
406 |
+
def get_gdbye_buttons(chat_id):
|
407 |
+
try:
|
408 |
+
return (
|
409 |
+
SESSION.query(GoodbyeButtons)
|
410 |
+
.filter(GoodbyeButtons.chat_id == str(chat_id))
|
411 |
+
.order_by(GoodbyeButtons.id)
|
412 |
+
.all()
|
413 |
+
)
|
414 |
+
finally:
|
415 |
+
SESSION.close()
|
416 |
+
|
417 |
+
|
418 |
+
def clean_service(chat_id: Union[str, int]) -> bool:
|
419 |
+
try:
|
420 |
+
chat_setting = SESSION.query(CleanServiceSetting).get(str(chat_id))
|
421 |
+
if chat_setting:
|
422 |
+
return chat_setting.clean_service
|
423 |
+
return False
|
424 |
+
finally:
|
425 |
+
SESSION.close()
|
426 |
+
|
427 |
+
|
428 |
+
def set_clean_service(chat_id: Union[int, str], setting: bool):
|
429 |
+
with CS_LOCK:
|
430 |
+
chat_setting = SESSION.query(CleanServiceSetting).get(str(chat_id))
|
431 |
+
if not chat_setting:
|
432 |
+
chat_setting = CleanServiceSetting(chat_id)
|
433 |
+
|
434 |
+
chat_setting.clean_service = setting
|
435 |
+
SESSION.add(chat_setting)
|
436 |
+
SESSION.commit()
|
437 |
+
|
438 |
+
|
439 |
+
def migrate_chat(old_chat_id, new_chat_id):
|
440 |
+
with INSERTION_LOCK:
|
441 |
+
chat = SESSION.query(Welcome).get(str(old_chat_id))
|
442 |
+
if chat:
|
443 |
+
chat.chat_id = str(new_chat_id)
|
444 |
+
|
445 |
+
with WELC_BTN_LOCK:
|
446 |
+
chat_buttons = (
|
447 |
+
SESSION.query(WelcomeButtons)
|
448 |
+
.filter(WelcomeButtons.chat_id == str(old_chat_id))
|
449 |
+
.all()
|
450 |
+
)
|
451 |
+
for btn in chat_buttons:
|
452 |
+
btn.chat_id = str(new_chat_id)
|
453 |
+
|
454 |
+
with LEAVE_BTN_LOCK:
|
455 |
+
chat_buttons = (
|
456 |
+
SESSION.query(GoodbyeButtons)
|
457 |
+
.filter(GoodbyeButtons.chat_id == str(old_chat_id))
|
458 |
+
.all()
|
459 |
+
)
|
460 |
+
for btn in chat_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
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.11.9
|
2 |
+
|
3 |
+
WORKDIR /root/Mikobot
|
4 |
+
|
5 |
+
COPY . .
|
6 |
+
|
7 |
+
RUN apt-get install -y ffmpeg python3-pip curl
|
8 |
+
RUN pip3 install --upgrade pip setuptools
|
9 |
+
|
10 |
+
RUN pip install -U -r requirements.txt
|
11 |
+
|
12 |
+
CMD python3 -m Mikobot
|
Extra/Calistoga-Regular.ttf
ADDED
Binary file (129 kB). View file
|
|
Extra/MutantAcademyStyle.ttf
ADDED
Binary file (56.4 kB). View file
|
|
Extra/a.jpg
ADDED
![]() |
Extra/bgg.jpg
ADDED
![]() |
Extra/default.ttf
ADDED
Binary file (136 kB). View file
|
|
Extra/profilepic.png
ADDED
![]() |
Infamous/karma.py
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# https://github.com/Infamous-Hydra/YaeMiko
|
2 |
+
# https://github.com/Team-ProjectCodeX
|
3 |
+
# https://t.me/O_okarma
|
4 |
+
|
5 |
+
# <============================================== IMPORTS =========================================================>
|
6 |
+
from pyrogram.types import InlineKeyboardButton as ib
|
7 |
+
from telegram import InlineKeyboardButton
|
8 |
+
|
9 |
+
from Mikobot import BOT_USERNAME, OWNER_ID, SUPPORT_CHAT
|
10 |
+
|
11 |
+
# <============================================== CONSTANTS =========================================================>
|
12 |
+
START_IMG = [
|
13 |
+
"https://telegra.ph/file/40b93b46642124605e678.jpg",
|
14 |
+
"https://telegra.ph/file/01a2e0cd1b9d03808c546.jpg",
|
15 |
+
"https://telegra.ph/file/ed4385c26dcf6de70543f.jpg",
|
16 |
+
"https://telegra.ph/file/33a8d97739a2a4f81ddde.jpg",
|
17 |
+
"https://telegra.ph/file/cce9038f6a9b88eb409b5.jpg",
|
18 |
+
"https://telegra.ph/file/262c86393730a609cdade.jpg",
|
19 |
+
"https://telegra.ph/file/33a8d97739a2a4f81ddde.jpg",
|
20 |
+
]
|
21 |
+
|
22 |
+
HEY_IMG = "https://telegra.ph/file/33a8d97739a2a4f81ddde.jpg"
|
23 |
+
|
24 |
+
ALIVE_ANIMATION = [
|
25 |
+
"https://telegra.ph//file/f9e2b9cdd9324fc39970a.mp4",
|
26 |
+
"https://telegra.ph//file/8d4d7d06efebe2f8becd0.mp4",
|
27 |
+
"https://telegra.ph//file/c4c2759c5fc04cefd207a.mp4",
|
28 |
+
"https://telegra.ph//file/b1fa6609b1c4807255927.mp4",
|
29 |
+
"https://telegra.ph//file/f3c7147da6511fbe27c25.mp4",
|
30 |
+
"https://telegra.ph//file/39071b73c02e3ff5945ca.mp4",
|
31 |
+
"https://telegra.ph//file/8d4d7d06efebe2f8becd0.mp4",
|
32 |
+
"https://telegra.ph//file/6efdd8e28756bc2f6e53e.mp4",
|
33 |
+
]
|
34 |
+
|
35 |
+
FIRST_PART_TEXT = "✨ *ʜᴇʟʟᴏ* `{}` . . ."
|
36 |
+
|
37 |
+
PM_START_TEXT = "✨ *ɪ ᴀᴍ ᴍɪᴋᴏ, ᴀ ɢᴇɴꜱʜɪɴ ɪᴍᴘᴀᴄᴛ ᴛʜᴇᴍᴇᴅ ʀᴏʙᴏᴛ ᴡʜɪᴄʜ ᴄᴀɴ ʜᴇʟᴘ ʏᴏᴜ ᴛᴏ ᴍᴀɴᴀɢᴇ ᴀɴᴅ ꜱᴇᴄᴜʀᴇ ʏᴏᴜʀ ɢʀᴏᴜᴘ ᴡɪᴛʜ ʜᴜɢᴇ ɢʀᴏᴜᴘ ᴍᴀɴᴀɢᴇᴍᴇɴᴛ*"
|
38 |
+
|
39 |
+
START_BTN = [
|
40 |
+
[
|
41 |
+
InlineKeyboardButton(
|
42 |
+
text="⇦ ADD ME ⇨",
|
43 |
+
url=f"https://t.me/{BOT_USERNAME}?startgroup=true",
|
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 |
+
[
|
54 |
+
InlineKeyboardButton(text="CREATOR", url=f"tg://user?id={OWNER_ID}"),
|
55 |
+
],
|
56 |
+
]
|
57 |
+
|
58 |
+
GROUP_START_BTN = [
|
59 |
+
[
|
60 |
+
InlineKeyboardButton(
|
61 |
+
text="⇦ ADD ME ⇨",
|
62 |
+
url=f"https://t.me/{BOT_USERNAME}?startgroup=true",
|
63 |
+
),
|
64 |
+
],
|
65 |
+
[
|
66 |
+
InlineKeyboardButton(text="SUPPORT", url=f"https://t.me/{SUPPORT_CHAT}"),
|
67 |
+
InlineKeyboardButton(text="CREATOR", url=f"tg://user?id={OWNER_ID}"),
|
68 |
+
],
|
69 |
+
]
|
70 |
+
|
71 |
+
ALIVE_BTN = [
|
72 |
+
[
|
73 |
+
ib(text="UPDATES", url="https://t.me/Hydra_Updates"),
|
74 |
+
ib(text="SUPPORT", url="https://t.me/hydraXsupport"),
|
75 |
+
],
|
76 |
+
[
|
77 |
+
ib(
|
78 |
+
text="⇦ ADD ME ⇨",
|
79 |
+
url=f"https://t.me/{BOT_USERNAME}?startgroup=true",
|
80 |
+
),
|
81 |
+
],
|
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 |
+
|
89 |
+
ᴀʟʟ ᴄᴏᴍᴍᴀɴᴅs ᴄᴀɴ ʙᴇ ᴜsᴇᴅ ᴡɪᴛʜ : /
|
90 |
+
"""
|