|
""" |
|
MIT License |
|
|
|
Copyright (c) 2022 Aʙɪsʜɴᴏɪ |
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
|
of this software and associated documentation files (the "Software"), to deal |
|
in the Software without restriction, including without limitation the rights |
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
copies of the Software, and to permit persons to whom the Software is |
|
furnished to do so, subject to the following conditions: |
|
|
|
The above copyright notice and this permission notice shall be included in all |
|
copies or substantial portions of the Software. |
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
SOFTWARE. |
|
""" |
|
|
|
import threading |
|
|
|
from sqlalchemy import BigInteger, Column, String, UnicodeText |
|
|
|
from Database.sql import BASE, SESSION |
|
|
|
DEF_COUNT = 1 |
|
DEF_LIMIT = 0 |
|
DEF_OBJ = (None, DEF_COUNT, DEF_LIMIT) |
|
|
|
|
|
class FloodControl(BASE): |
|
__tablename__ = "antiflood" |
|
chat_id = Column(String(14), primary_key=True) |
|
user_id = Column(BigInteger) |
|
count = Column(BigInteger, default=DEF_COUNT) |
|
limit = Column(BigInteger, default=DEF_LIMIT) |
|
|
|
def __init__(self, chat_id): |
|
self.chat_id = str(chat_id) |
|
|
|
def __repr__(self): |
|
return "<ғʟᴏᴏᴅ ᴄᴏɴᴛʀᴏʟ ғᴏʀ %s>" % self.chat_id |
|
|
|
|
|
class FloodSettings(BASE): |
|
__tablename__ = "antiflood_settings" |
|
chat_id = Column(String(14), primary_key=True) |
|
flood_type = Column(BigInteger, default=1) |
|
value = Column(UnicodeText, default="0") |
|
|
|
def __init__(self, chat_id, flood_type=1, value="0"): |
|
self.chat_id = str(chat_id) |
|
self.flood_type = flood_type |
|
self.value = value |
|
|
|
def __repr__(self): |
|
return "<{} ᴡɪʟʟ ᴇxᴇᴄᴜᴛɪɴɢ {} ғᴏʀ ғʟᴏᴏᴅ.>".format(self.chat_id, self.flood_type) |
|
|
|
|
|
FloodControl.__table__.create(checkfirst=True) |
|
FloodSettings.__table__.create(checkfirst=True) |
|
|
|
INSERTION_FLOOD_LOCK = threading.RLock() |
|
INSERTION_FLOOD_SETTINGS_LOCK = threading.RLock() |
|
|
|
CHAT_FLOOD = {} |
|
|
|
|
|
def set_flood(chat_id, amount): |
|
with INSERTION_FLOOD_LOCK: |
|
flood = SESSION.query(FloodControl).get(str(chat_id)) |
|
if not flood: |
|
flood = FloodControl(str(chat_id)) |
|
|
|
flood.user_id = None |
|
flood.limit = amount |
|
|
|
CHAT_FLOOD[str(chat_id)] = (None, DEF_COUNT, amount) |
|
|
|
SESSION.add(flood) |
|
SESSION.commit() |
|
|
|
|
|
def update_flood(chat_id: str, user_id) -> bool: |
|
if str(chat_id) not in CHAT_FLOOD: |
|
return |
|
|
|
curr_user_id, count, limit = CHAT_FLOOD.get(str(chat_id), DEF_OBJ) |
|
|
|
if limit == 0: |
|
return False |
|
|
|
if user_id != curr_user_id or user_id is None: |
|
CHAT_FLOOD[str(chat_id)] = (user_id, DEF_COUNT, limit) |
|
return False |
|
|
|
count += 1 |
|
if count > limit: |
|
CHAT_FLOOD[str(chat_id)] = (None, DEF_COUNT, limit) |
|
return True |
|
|
|
|
|
CHAT_FLOOD[str(chat_id)] = (user_id, count, limit) |
|
return False |
|
|
|
|
|
def get_flood_limit(chat_id): |
|
return CHAT_FLOOD.get(str(chat_id), DEF_OBJ)[2] |
|
|
|
|
|
def set_flood_strength(chat_id, flood_type, value): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with INSERTION_FLOOD_SETTINGS_LOCK: |
|
curr_setting = SESSION.query(FloodSettings).get(str(chat_id)) |
|
if not curr_setting: |
|
curr_setting = FloodSettings( |
|
chat_id, |
|
flood_type=int(flood_type), |
|
value=value, |
|
) |
|
|
|
curr_setting.flood_type = int(flood_type) |
|
curr_setting.value = str(value) |
|
|
|
SESSION.add(curr_setting) |
|
SESSION.commit() |
|
|
|
|
|
def get_flood_setting(chat_id): |
|
try: |
|
setting = SESSION.query(FloodSettings).get(str(chat_id)) |
|
if setting: |
|
return setting.flood_type, setting.value |
|
return 1, "0" |
|
|
|
finally: |
|
SESSION.close() |
|
|
|
|
|
def migrate_chat(old_chat_id, new_chat_id): |
|
with INSERTION_FLOOD_LOCK: |
|
flood = SESSION.query(FloodControl).get(str(old_chat_id)) |
|
if flood: |
|
CHAT_FLOOD[str(new_chat_id)] = CHAT_FLOOD.get(str(old_chat_id), DEF_OBJ) |
|
flood.chat_id = str(new_chat_id) |
|
SESSION.commit() |
|
|
|
SESSION.close() |
|
|
|
|
|
def __load_flood_settings(): |
|
global CHAT_FLOOD |
|
try: |
|
all_chats = SESSION.query(FloodControl).all() |
|
CHAT_FLOOD = {chat.chat_id: (None, DEF_COUNT, chat.limit) for chat in all_chats} |
|
finally: |
|
SESSION.close() |
|
|
|
|
|
__load_flood_settings() |
|
|