Archived
1
0
Fork 0
This repository has been archived on 2024-04-26. You can view files and clone it, but cannot push or open issues or pull requests.
akari-bot/database/__init__.py

445 lines
16 KiB
Python
Raw Normal View History

2021-07-27 17:42:47 +00:00
import datetime
2023-09-03 08:50:12 +00:00
import uuid
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 *
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
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
return wrapper
class BotDBUtil:
2023-04-14 13:15:04 +00:00
database_version = 3
2022-06-13 12:01:53 +00:00
class TargetInfo:
2023-04-14 13:15:04 +00:00
def __init__(self, msg: Union[MessageSession, FetchTarget, str]):
if isinstance(msg, (MessageSession, FetchTarget)):
2023-09-01 14:38:32 +00:00
self.target_id = str(msg.target.target_id)
2021-08-21 15:58:07 +00:00
else:
2023-09-01 14:38:32 +00:00
self.target_id = msg
self.query = self.query_data
2021-08-25 11:23:59 +00:00
@property
def query_data(self):
2023-09-01 14:38:32 +00:00
return session.query(TargetInfo).filter_by(targetId=self.target_id).first()
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
def init(self):
2023-12-19 06:35:50 +00:00
if not self.query:
2023-09-01 14:38:32 +00:00
session.add_all([TargetInfo(targetId=self.target_id)])
2022-08-26 18:51:56 +00:00
session.commit()
return self.query_data
else:
return self.query
@property
def enabled_modules(self) -> list:
2023-12-19 06:35:50 +00:00
if not self.query:
return []
return json.loads(self.query.enabledModules)
2021-08-25 11:45:03 +00:00
def check_target_enabled_module(self, module_name) -> bool:
return True if module_name in self.enabled_modules else False
2021-09-12 12:51:13 +00:00
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
def enable(self, module_name) -> bool:
2023-12-19 06:35:50 +00:00
if not self.query:
self.query = self.init()
2022-08-26 18:51:56 +00:00
enabled_modules = self.enabled_modules.copy()
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)
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)
session.commit()
session.expire_all()
return True
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
def disable(self, module_name) -> bool:
2023-12-19 08:50:45 +00:00
if self.query:
2022-08-26 18:51:56 +00:00
enabled_modules = self.enabled_modules.copy()
if isinstance(module_name, str):
2022-08-26 18:51:56 +00:00
if module_name in enabled_modules:
enabled_modules.remove(module_name)
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)
session.commit()
2021-08-24 10:22:36 +00:00
session.expire_all()
return True
2021-07-12 13:31:11 +00:00
@property
def is_muted(self):
2023-12-19 06:35:50 +00:00
if not self.query:
return False
return self.query.muted
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
def switch_mute(self) -> bool:
2023-12-19 06:35:50 +00:00
if not self.query:
self.query = self.init()
self.query.muted = not self.query.muted
session.commit()
return self.query.muted
@property
def options(self):
2023-12-19 06:35:50 +00:00
if not self.query:
return {}
return json.loads(self.query.options)
def get_option(self, k=None):
2023-12-19 08:50:45 +00:00
if not self.query and not k:
return {}
2023-12-19 08:50:45 +00:00
elif not self.query and k:
return None
2023-12-19 06:35:50 +00:00
if not k:
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
def edit_option(self, k, v) -> bool:
2023-12-19 06:35:50 +00:00
if not self.query:
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:
2023-12-19 08:50:45 +00:00
if self.query:
2022-08-27 07:38:13 +00:00
options = self.options.copy()
if k in options:
options.pop(k)
self.query.options = options
session.commit()
return True
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
def edit(self, column: str, value):
2023-12-19 06:35:50 +00:00
if not self.query:
self.query = self.init()
query = self.query
setattr(query, column, value)
session.commit()
session.expire_all()
return True
@property
def custom_admins(self):
2023-12-19 06:35:50 +00:00
if not self.query:
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:
2023-12-19 06:35:50 +00:00
if not self.query:
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)
session.commit()
return True
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
def remove_custom_admin(self, sender_id) -> bool:
2023-12-19 08:50:45 +00:00
if self.query:
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)
return True
@property
def locale(self):
2023-12-19 06:35:50 +00:00
if not self.query:
2022-08-26 18:51:56 +00:00
self.query = self.init()
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}"%')]
2023-12-19 08:50:45 +00:00
if id_prefix:
2022-08-29 15:54:20 +00:00
filter_.append(TargetInfo.targetId.like(f'{id_prefix}%'))
return session.query(TargetInfo).filter(*filter_).all()
2023-04-14 13:15:04 +00:00
@property
def petal(self):
2023-12-19 06:35:50 +00:00
if not self.query:
2023-04-14 13:15:04 +00:00
return 0
return self.query.petal
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
def modify_petal(self, amount: int) -> bool:
2023-12-19 06:35:50 +00:00
if not self.query:
2023-04-14 13:15:04 +00:00
self.query = self.init()
petal = self.petal
new_petal = petal + amount
self.query.petal = new_petal
session.commit()
return True
2021-07-15 14:59:32 +00:00
class SenderInfo:
2021-09-12 12:51:13 +00:00
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
2023-09-03 11:49:14 +00:00
def __init__(self, sender_id):
self.sender_id = sender_id
self.query = self.query_SenderInfo
2023-12-19 06:35:50 +00:00
if not self.query:
2023-09-03 11:49:14 +00:00
session.add_all([SenderInfo(id=sender_id)])
session.commit()
2023-09-03 11:49:14 +00:00
self.query = session.query(SenderInfo).filter_by(id=sender_id).first()
2021-08-25 11:23:59 +00:00
@property
2021-11-18 10:24:57 +00:00
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
2021-08-25 11:23:59 +00:00
def query_SenderInfo(self):
2023-09-03 11:49:14 +00:00
return session.query(SenderInfo).filter_by(id=self.sender_id).first()
2021-07-13 15:48:43 +00:00
2021-09-12 12:51:13 +00:00
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
def edit(self, column: str, value):
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:
@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
2023-09-01 14:38:32 +00:00
self.query = session.query(CommandTriggerTime).filter_by(targetId=str(msg.target.sender_id),
2021-08-07 07:56:48 +00:00
commandName=name).first()
2023-12-19 06:35:50 +00:00
self.need_insert = True if not self.query else False
2021-07-27 17:42:47 +00:00
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))
@auto_rollback_error
2021-07-27 17:42:47 +00:00
def reset(self):
if not self.need_insert:
session.delete(self.query)
2021-07-27 17:42:47 +00:00
session.commit()
2023-09-01 14:38:32 +00:00
session.add_all([CommandTriggerTime(targetId=self.msg.target.sender_id, commandName=self.name)])
session.commit()
session.expire_all()
@staticmethod
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
2023-09-01 14:38:32 +00:00
def isGroupInAllowList(target_id):
session.expire_all()
2023-09-01 14:38:32 +00:00
query = session.query(GroupAllowList).filter_by(targetId=target_id).first()
2023-12-19 08:50:45 +00:00
if query:
return True
return False
2022-06-12 14:30:02 +00:00
class Data:
2023-08-29 18:13:34 +00:00
def __init__(self, msg: Union[MessageSession, FetchTarget, str]):
if isinstance(msg, MessageSession):
2023-09-01 14:38:32 +00:00
self.targetName = msg.target.client_name
2023-08-29 18:13:34 +00:00
elif isinstance(msg, FetchTarget):
self.targetName = msg.name
else:
self.targetName = msg
2022-06-12 14:30:02 +00:00
@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)
2023-12-19 06:35:50 +00:00
if not exists:
2022-06-12 14:30:02 +00:00
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):
2023-09-01 14:38:32 +00:00
session.add(AnalyticsData(targetId=self.target.target.target_id,
senderId=self.target.target.sender_id,
2022-07-14 13:23:15 +00:00
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]
2023-12-19 08:50:45 +00:00
if module_name:
2022-07-19 13:01:25 +00:00
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]
2023-12-19 08:50:45 +00:00
if module_name:
2022-07-25 16:55:44 +00:00
filter_.append(AnalyticsData.moduleName == module_name)
return session.query(AnalyticsData).filter(*filter_).count()
2022-07-27 14:32:16 +00:00
class UnfriendlyActions:
2023-09-01 14:38:32 +00:00
def __init__(self, target_id, sender_id):
self.target_id = target_id
self.sender_id = sender_id
2022-07-27 14:32:16 +00:00
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
def check_mute(self) -> bool:
"""
:return: True = yes, False = no
"""
2023-09-01 14:38:32 +00:00
query = session.query(UnfriendlyActionsTable).filter_by(targetId=self.target_id).all()
2022-07-27 14:32:16 +00:00
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:
2023-09-03 11:49:14 +00:00
if criminal.sender_id not in count:
count[criminal.sender_id] = 0
2022-07-27 14:32:16 +00:00
else:
2023-09-03 11:49:14 +00:00
count[criminal.sender_id] += 1
2022-07-27 14:32:16 +00:00
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
"""
2023-09-01 14:38:32 +00:00
session.add_all([UnfriendlyActionsTable(targetId=self.target_id,
senderId=self.sender_id, action=action, detail=detail)])
2022-07-27 14:32:16 +00:00
session.commit()
return self.check_mute()
2023-08-27 13:36:11 +00:00
class JobQueue:
@staticmethod
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
def add(target_client: str, action: str, args: dict):
taskid = str(uuid.uuid4())
session.add_all([JobQueueTable(taskid=taskid, targetClient=target_client, action=action,
args=json.dumps(args))])
session.commit()
session.expire_all()
return taskid
@staticmethod
@retry(stop=stop_after_attempt(3))
def get(taskid: str) -> JobQueueTable:
return session.query(JobQueueTable).filter_by(taskid=taskid).first()
@staticmethod
@retry(stop=stop_after_attempt(3))
def get_first(target_client: str) -> JobQueueTable:
return session.query(JobQueueTable).filter_by(targetClient=target_client, hasDone=False).first()
2023-08-27 13:36:11 +00:00
@staticmethod
@retry(stop=stop_after_attempt(3))
def get_all(target_client: str) -> List[JobQueueTable]:
return session.query(JobQueueTable).filter_by(targetClient=target_client, hasDone=False).all()
@staticmethod
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
def return_val(query: JobQueueTable, value):
query.returnVal = json.dumps(value)
2023-08-27 13:36:11 +00:00
query.hasDone = True
session.commit()
session.expire_all()
return True
@staticmethod
@retry(stop=stop_after_attempt(3))
@auto_rollback_error
2023-08-30 06:32:02 +00:00
def clear(time=43200):
2023-08-27 13:36:11 +00:00
queries = session.query(JobQueueTable).all()
for q in queries:
2023-08-30 06:32:02 +00:00
if datetime.datetime.now().timestamp() - q.timestamp.timestamp() > time:
2023-08-27 13:36:11 +00:00
session.delete(q)
session.commit()
session.expire_all()
return True
2022-01-08 11:05:17 +00:00
__all__ = ["BotDBUtil", "auto_rollback_error", "session"]