2021-07-27 17:42:47 +00:00
|
|
|
import datetime
|
2022-08-29 15:54:20 +00:00
|
|
|
from typing import Union, List
|
2021-07-27 17:42:47 +00:00
|
|
|
|
2022-07-31 08:27:58 +00:00
|
|
|
import ujson as json
|
2021-11-12 14:25:53 +00:00
|
|
|
from tenacity import retry, stop_after_attempt
|
2022-08-30 12:49:01 +00:00
|
|
|
|
2023-02-05 14:33:33 +00:00
|
|
|
from core.types.message import MessageSession, FetchTarget, FetchedSession
|
2022-06-13 04:49:22 +00:00
|
|
|
from database.orm import Session
|
2022-06-13 12:01:53 +00:00
|
|
|
from database.tables import *
|
2022-08-18 05:46:18 +00:00
|
|
|
from database.tables import TargetInfo
|
2021-09-10 18:05:27 +00:00
|
|
|
|
2022-06-13 04:49:22 +00:00
|
|
|
session = Session.session
|
2021-08-24 16:49:19 +00:00
|
|
|
|
|
|
|
|
2021-11-03 11:27:21 +00:00
|
|
|
def auto_rollback_error(func):
|
|
|
|
def wrapper(*args, **kwargs):
|
|
|
|
try:
|
|
|
|
return func(*args, **kwargs)
|
|
|
|
except Exception as e:
|
|
|
|
session.rollback()
|
|
|
|
raise e
|
2021-11-12 14:25:53 +00:00
|
|
|
|
2021-11-03 11:27:21 +00:00
|
|
|
return wrapper
|
|
|
|
|
|
|
|
|
2021-07-11 02:19:40 +00:00
|
|
|
class BotDBUtil:
|
2022-08-27 07:38:13 +00:00
|
|
|
database_version = 2
|
2022-06-13 12:01:53 +00:00
|
|
|
|
2022-08-25 18:42:31 +00:00
|
|
|
class TargetInfo:
|
|
|
|
def __init__(self, msg: [MessageSession, FetchTarget, str]):
|
|
|
|
if isinstance(msg, (MessageSession, FetchTarget)):
|
2021-08-21 15:58:07 +00:00
|
|
|
self.targetId = str(msg.target.targetId)
|
|
|
|
else:
|
|
|
|
self.targetId = msg
|
2022-08-25 18:42:31 +00:00
|
|
|
self.query = self.query_data
|
2021-08-25 11:23:59 +00:00
|
|
|
|
|
|
|
@property
|
2022-08-25 18:42:31 +00:00
|
|
|
def query_data(self):
|
|
|
|
return session.query(TargetInfo).filter_by(targetId=self.targetId).first()
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
2021-11-03 11:27:21 +00:00
|
|
|
@auto_rollback_error
|
2022-08-25 18:42:31 +00:00
|
|
|
def init(self):
|
2022-08-26 18:51:56 +00:00
|
|
|
if self.query is None:
|
|
|
|
session.add_all([TargetInfo(targetId=self.targetId)])
|
|
|
|
session.commit()
|
|
|
|
return self.query_data
|
|
|
|
else:
|
|
|
|
return self.query
|
2021-07-11 02:19:40 +00:00
|
|
|
|
2022-08-25 18:42:31 +00:00
|
|
|
@property
|
|
|
|
def enabled_modules(self) -> list:
|
|
|
|
if self.query is None:
|
|
|
|
return []
|
|
|
|
return json.loads(self.query.enabledModules)
|
2021-08-25 11:45:03 +00:00
|
|
|
|
2021-07-11 02:19:40 +00:00
|
|
|
def check_target_enabled_module(self, module_name) -> bool:
|
2022-08-25 18:42:31 +00:00
|
|
|
return True if module_name in self.enabled_modules else False
|
2021-07-11 02:19:40 +00:00
|
|
|
|
2021-09-12 12:51:13 +00:00
|
|
|
@retry(stop=stop_after_attempt(3))
|
2021-11-03 11:27:21 +00:00
|
|
|
@auto_rollback_error
|
2021-07-11 02:19:40 +00:00
|
|
|
def enable(self, module_name) -> bool:
|
2022-08-25 18:42:31 +00:00
|
|
|
if self.query is None:
|
|
|
|
self.query = self.init()
|
2022-08-26 18:51:56 +00:00
|
|
|
enabled_modules = self.enabled_modules.copy()
|
2021-11-03 11:27:21 +00:00
|
|
|
if isinstance(module_name, str):
|
2022-08-26 18:51:56 +00:00
|
|
|
if module_name not in enabled_modules:
|
|
|
|
enabled_modules.append(module_name)
|
2021-11-03 11:27:21 +00:00
|
|
|
elif isinstance(module_name, (list, tuple)):
|
|
|
|
for x in module_name:
|
2022-08-26 18:51:56 +00:00
|
|
|
if x not in enabled_modules:
|
|
|
|
enabled_modules.append(x)
|
|
|
|
self.query.enabledModules = json.dumps(enabled_modules)
|
2021-11-03 11:27:21 +00:00
|
|
|
session.commit()
|
|
|
|
session.expire_all()
|
|
|
|
return True
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def disable(self, module_name) -> bool:
|
2022-08-25 18:42:31 +00:00
|
|
|
if self.query is not None:
|
2022-08-26 18:51:56 +00:00
|
|
|
enabled_modules = self.enabled_modules.copy()
|
2022-08-25 18:42:31 +00:00
|
|
|
if isinstance(module_name, str):
|
2022-08-26 18:51:56 +00:00
|
|
|
if module_name in enabled_modules:
|
|
|
|
enabled_modules.remove(module_name)
|
2022-08-25 18:42:31 +00:00
|
|
|
elif isinstance(module_name, (list, tuple)):
|
|
|
|
for x in module_name:
|
2022-08-26 18:51:56 +00:00
|
|
|
if x in enabled_modules:
|
|
|
|
enabled_modules.remove(x)
|
|
|
|
self.query.enabledModules = json.dumps(enabled_modules)
|
2021-07-11 02:19:40 +00:00
|
|
|
session.commit()
|
2021-08-24 10:22:36 +00:00
|
|
|
session.expire_all()
|
2021-11-03 11:27:21 +00:00
|
|
|
return True
|
2021-07-12 13:31:11 +00:00
|
|
|
|
2022-08-25 18:42:31 +00:00
|
|
|
@property
|
|
|
|
def is_muted(self):
|
|
|
|
if self.query is None:
|
|
|
|
return False
|
|
|
|
return self.query.muted
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def switch_mute(self) -> bool:
|
|
|
|
if self.query is None:
|
|
|
|
self.query = self.init()
|
|
|
|
self.query.muted = not self.query.muted
|
|
|
|
session.commit()
|
|
|
|
return self.query.muted
|
|
|
|
|
|
|
|
@property
|
|
|
|
def options(self):
|
|
|
|
if self.query is None:
|
|
|
|
return {}
|
|
|
|
return json.loads(self.query.options)
|
|
|
|
|
|
|
|
def get_option(self, k=None):
|
|
|
|
if self.query is None and k is None:
|
|
|
|
return {}
|
|
|
|
elif self.query is None and k is not None:
|
|
|
|
return None
|
|
|
|
if k is None:
|
|
|
|
return self.options
|
|
|
|
else:
|
|
|
|
return self.options.get(k)
|
|
|
|
|
2021-11-18 10:24:15 +00:00
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
2022-08-25 18:42:31 +00:00
|
|
|
def edit_option(self, k, v) -> bool:
|
|
|
|
if self.query is None:
|
|
|
|
self.query = self.init()
|
|
|
|
self.query.options = json.dumps({**json.loads(self.query.options), k: v})
|
|
|
|
session.commit()
|
|
|
|
return True
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def remove_option(self, k) -> bool:
|
|
|
|
if self.query is not None:
|
2022-08-27 07:38:13 +00:00
|
|
|
options = self.options.copy()
|
|
|
|
if k in options:
|
|
|
|
options.pop(k)
|
|
|
|
self.query.options = options
|
2022-08-25 18:42:31 +00:00
|
|
|
session.commit()
|
|
|
|
return True
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def edit(self, column: str, value):
|
|
|
|
if self.query is None:
|
|
|
|
self.query = self.init()
|
|
|
|
query = self.query
|
|
|
|
setattr(query, column, value)
|
|
|
|
session.commit()
|
|
|
|
session.expire_all()
|
|
|
|
return True
|
|
|
|
|
|
|
|
@property
|
|
|
|
def custom_admins(self):
|
|
|
|
if self.query is None:
|
|
|
|
return []
|
|
|
|
return json.loads(self.query.custom_admins)
|
|
|
|
|
|
|
|
def check_custom_target_admin(self, sender_id) -> bool:
|
|
|
|
return sender_id in self.custom_admins
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def add_custom_admin(self, sender_id) -> bool:
|
|
|
|
if self.query is None:
|
|
|
|
self.query = self.init()
|
2022-08-27 07:38:13 +00:00
|
|
|
custom_admins = self.custom_admins.copy()
|
|
|
|
if sender_id not in custom_admins:
|
|
|
|
custom_admins.append(sender_id)
|
|
|
|
self.query.custom_admins = json.dumps(custom_admins)
|
2022-08-25 18:42:31 +00:00
|
|
|
session.commit()
|
|
|
|
return True
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def remove_custom_admin(self, sender_id) -> bool:
|
|
|
|
if self.query is not None:
|
2022-08-27 07:38:13 +00:00
|
|
|
custom_admins = self.custom_admins.copy()
|
|
|
|
if sender_id in custom_admins:
|
|
|
|
custom_admins.remove(sender_id)
|
|
|
|
self.query.custom_admins = json.dumps(custom_admins)
|
2022-08-25 18:42:31 +00:00
|
|
|
return True
|
|
|
|
|
|
|
|
@property
|
|
|
|
def locale(self):
|
2022-08-26 18:51:56 +00:00
|
|
|
if self.query is None:
|
|
|
|
self.query = self.init()
|
2022-08-25 18:42:31 +00:00
|
|
|
return self.query.locale
|
|
|
|
|
|
|
|
@staticmethod
|
2022-08-29 15:54:20 +00:00
|
|
|
def get_enabled_this(module_name, id_prefix=None) -> List[TargetInfo]:
|
|
|
|
filter_ = [TargetInfo.enabledModules.like(f'%"{module_name}"%')]
|
|
|
|
if id_prefix is not None:
|
|
|
|
filter_.append(TargetInfo.targetId.like(f'{id_prefix}%'))
|
|
|
|
return session.query(TargetInfo).filter(*filter_).all()
|
2021-08-02 13:39:50 +00:00
|
|
|
|
2021-07-15 14:59:32 +00:00
|
|
|
class SenderInfo:
|
2021-09-12 12:51:13 +00:00
|
|
|
@retry(stop=stop_after_attempt(3))
|
2021-11-03 11:27:21 +00:00
|
|
|
@auto_rollback_error
|
2021-07-16 15:50:25 +00:00
|
|
|
def __init__(self, senderId):
|
|
|
|
self.senderId = senderId
|
2022-08-25 18:42:31 +00:00
|
|
|
self.query = self.query_SenderInfo
|
|
|
|
if self.query is None:
|
|
|
|
session.add_all([SenderInfo(id=senderId)])
|
|
|
|
session.commit()
|
|
|
|
self.query = session.query(SenderInfo).filter_by(id=senderId).first()
|
2021-08-25 11:23:59 +00:00
|
|
|
|
|
|
|
@property
|
2021-11-18 10:24:57 +00:00
|
|
|
@retry(stop=stop_after_attempt(3))
|
2021-11-03 11:27:21 +00:00
|
|
|
@auto_rollback_error
|
2021-08-25 11:23:59 +00:00
|
|
|
def query_SenderInfo(self):
|
2021-11-03 11:27:21 +00:00
|
|
|
return session.query(SenderInfo).filter_by(id=self.senderId).first()
|
2021-07-13 15:48:43 +00:00
|
|
|
|
2021-09-12 12:51:13 +00:00
|
|
|
@retry(stop=stop_after_attempt(3))
|
2021-11-03 11:27:21 +00:00
|
|
|
@auto_rollback_error
|
2021-07-16 15:50:25 +00:00
|
|
|
def edit(self, column: str, value):
|
2021-11-03 11:27:21 +00:00
|
|
|
query = self.query_SenderInfo
|
|
|
|
setattr(query, column, value)
|
|
|
|
session.commit()
|
|
|
|
session.expire_all()
|
2022-01-30 14:02:17 +00:00
|
|
|
return True
|
2021-08-26 16:24:21 +00:00
|
|
|
|
2021-07-27 17:42:47 +00:00
|
|
|
class CoolDown:
|
2021-11-03 11:27:21 +00:00
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
2021-07-27 17:42:47 +00:00
|
|
|
def __init__(self, msg: MessageSession, name):
|
|
|
|
self.msg = msg
|
|
|
|
self.name = name
|
2022-05-18 11:47:35 +00:00
|
|
|
self.query = session.query(CommandTriggerTime).filter_by(targetId=str(msg.target.senderId),
|
2021-08-07 07:56:48 +00:00
|
|
|
commandName=name).first()
|
2021-07-27 17:42:47 +00:00
|
|
|
self.need_insert = True if self.query is None else False
|
|
|
|
|
|
|
|
def check(self, delay):
|
|
|
|
if not self.need_insert:
|
|
|
|
now = datetime.datetime.now().timestamp() - self.query.timestamp.timestamp()
|
|
|
|
if now > delay:
|
|
|
|
return 0
|
|
|
|
return now
|
|
|
|
return 0
|
|
|
|
|
2021-09-12 12:51:13 +00:00
|
|
|
@retry(stop=stop_after_attempt(3))
|
2021-11-03 11:27:21 +00:00
|
|
|
@auto_rollback_error
|
2021-07-27 17:42:47 +00:00
|
|
|
def reset(self):
|
2021-11-03 11:27:21 +00:00
|
|
|
if not self.need_insert:
|
|
|
|
session.delete(self.query)
|
2021-07-27 17:42:47 +00:00
|
|
|
session.commit()
|
2022-05-18 11:52:16 +00:00
|
|
|
session.add_all([CommandTriggerTime(targetId=self.msg.target.senderId, commandName=self.name)])
|
2021-11-03 11:27:21 +00:00
|
|
|
session.commit()
|
2021-10-16 16:17:21 +00:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
2021-11-03 11:27:21 +00:00
|
|
|
@auto_rollback_error
|
2021-11-15 16:26:11 +00:00
|
|
|
def isGroupInAllowList(targetId):
|
2021-11-03 11:27:21 +00:00
|
|
|
session.expire_all()
|
2021-11-15 16:26:11 +00:00
|
|
|
query = session.query(GroupAllowList).filter_by(targetId=targetId).first()
|
2021-11-03 11:27:21 +00:00
|
|
|
if query is not None:
|
|
|
|
return True
|
|
|
|
return False
|
2021-10-16 16:17:21 +00:00
|
|
|
|
2022-06-12 14:30:02 +00:00
|
|
|
class Data:
|
|
|
|
def __init__(self, msg: Union[MessageSession, FetchTarget]):
|
|
|
|
self.targetName = msg.target.clientName if isinstance(msg, MessageSession) else msg.name
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def add(self, name, value: str):
|
|
|
|
session.add(StoredData(name=f'{self.targetName}|{name}', value=value))
|
|
|
|
session.commit()
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def get(self, name):
|
|
|
|
return session.query(StoredData).filter_by(name=f'{self.targetName}|{name}').first()
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def update(self, name, value: str):
|
|
|
|
exists = self.get(name)
|
|
|
|
if exists is None:
|
|
|
|
self.add(name=name, value=value)
|
|
|
|
else:
|
|
|
|
exists.value = value
|
|
|
|
session.commit()
|
|
|
|
return True
|
|
|
|
|
2022-07-14 13:23:15 +00:00
|
|
|
class Analytics:
|
|
|
|
def __init__(self, target: Union[MessageSession, FetchedSession]):
|
|
|
|
self.target = target
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def add(self, command, module_name, module_type):
|
|
|
|
session.add(AnalyticsData(targetId=self.target.target.targetId,
|
|
|
|
senderId=self.target.target.senderId,
|
|
|
|
command=command,
|
|
|
|
moduleName=module_name, moduleType=module_type))
|
|
|
|
session.commit()
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get_count():
|
|
|
|
return session.query(AnalyticsData).count()
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get_first():
|
|
|
|
return session.query(AnalyticsData).filter_by(id=1).first()
|
|
|
|
|
2022-07-19 01:57:43 +00:00
|
|
|
@staticmethod
|
2022-07-19 13:01:25 +00:00
|
|
|
def get_data_by_times(new, old, module_name=None):
|
|
|
|
filter_ = [AnalyticsData.timestamp <= new, AnalyticsData.timestamp >= old]
|
|
|
|
if module_name is not None:
|
|
|
|
filter_.append(AnalyticsData.moduleName == module_name)
|
|
|
|
return session.query(AnalyticsData).filter(*filter_).all()
|
2022-07-19 01:57:43 +00:00
|
|
|
|
2022-07-25 16:55:44 +00:00
|
|
|
@staticmethod
|
|
|
|
def get_count_by_times(new, old, module_name=None):
|
2022-07-28 15:53:15 +00:00
|
|
|
filter_ = [AnalyticsData.timestamp < new, AnalyticsData.timestamp > old]
|
2022-07-25 16:55:44 +00:00
|
|
|
if module_name is not None:
|
|
|
|
filter_.append(AnalyticsData.moduleName == module_name)
|
|
|
|
return session.query(AnalyticsData).filter(*filter_).count()
|
|
|
|
|
2022-07-27 14:32:16 +00:00
|
|
|
class UnfriendlyActions:
|
|
|
|
def __init__(self, targetId, senderId):
|
|
|
|
self.targetId = targetId
|
|
|
|
self.senderId = senderId
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def check_mute(self) -> bool:
|
|
|
|
"""
|
|
|
|
|
|
|
|
:return: True = yes, False = no
|
|
|
|
"""
|
|
|
|
query = session.query(UnfriendlyActionsTable).filter_by(targetId=self.targetId).all()
|
|
|
|
unfriendly_list = []
|
|
|
|
for records in query:
|
|
|
|
if datetime.datetime.now().timestamp() - records.timestamp.timestamp() < 432000:
|
|
|
|
unfriendly_list.append(records)
|
|
|
|
if len(unfriendly_list) > 5:
|
|
|
|
return True
|
|
|
|
count = {}
|
|
|
|
for criminal in unfriendly_list:
|
|
|
|
if datetime.datetime.now().timestamp() - criminal.timestamp.timestamp() < 86400:
|
|
|
|
if criminal.senderId not in count:
|
|
|
|
count[criminal.senderId] = 0
|
|
|
|
else:
|
|
|
|
count[criminal.senderId] += 1
|
|
|
|
if len(count) >= 3:
|
|
|
|
return True
|
|
|
|
for convict in count:
|
|
|
|
if count[convict] >= 3:
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
@retry(stop=stop_after_attempt(3))
|
|
|
|
@auto_rollback_error
|
|
|
|
def add_and_check(self, action='default', detail='') -> bool:
|
|
|
|
"""
|
|
|
|
|
|
|
|
:return: True = yes, False = no
|
|
|
|
"""
|
|
|
|
session.add_all(
|
|
|
|
[UnfriendlyActionsTable(targetId=self.targetId, senderId=self.senderId, action=action, detail=detail)])
|
|
|
|
session.commit()
|
|
|
|
return self.check_mute()
|
|
|
|
|
2022-01-08 11:05:17 +00:00
|
|
|
|
2021-11-03 11:27:21 +00:00
|
|
|
__all__ = ["BotDBUtil", "auto_rollback_error", "session"]
|