mirror of
https://github.com/suyiiyii/nonebot-bison.git
synced 2026-05-09 18:27:56 +08:00
🚚 修改 nonebot_bison 项目结构 (#211)
* 🎨 修改 nonebot_bison 目录位置 * auto fix by pre-commit hooks * 🚚 fix frontend build target * 🚚 use soft link * Revert "🚚 use soft link" This reverts commit de21f79d5ae1bd5515b04f42a4138cb25ddf3e62. * 🚚 modify dockerfile --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: felinae98 <731499577@qq.com>
This commit is contained in:
@@ -0,0 +1 @@
|
||||
from .manager import *
|
||||
@@ -0,0 +1,54 @@
|
||||
from typing import Type
|
||||
|
||||
from ..config import config
|
||||
from ..config.db_model import Target
|
||||
from ..platform import platform_manager
|
||||
from ..types import Target as T_Target
|
||||
from ..utils import SchedulerConfig
|
||||
from .scheduler import Scheduler
|
||||
|
||||
scheduler_dict: dict[Type[SchedulerConfig], Scheduler] = {}
|
||||
|
||||
|
||||
async def init_scheduler():
|
||||
_schedule_class_dict: dict[Type[SchedulerConfig], list[Target]] = {}
|
||||
_schedule_class_platform_dict: dict[Type[SchedulerConfig], list[str]] = {}
|
||||
for platform in platform_manager.values():
|
||||
scheduler_config = platform.scheduler
|
||||
if not hasattr(scheduler_config, "name") or not scheduler_config.name:
|
||||
scheduler_config.name = f"AnonymousScheduleConfig[{platform.platform_name}]"
|
||||
|
||||
platform_name = platform.platform_name
|
||||
targets = await config.get_platform_target(platform_name)
|
||||
if scheduler_config not in _schedule_class_dict:
|
||||
_schedule_class_dict[scheduler_config] = targets
|
||||
else:
|
||||
_schedule_class_dict[scheduler_config].extend(targets)
|
||||
if scheduler_config not in _schedule_class_platform_dict:
|
||||
_schedule_class_platform_dict[scheduler_config] = [platform_name]
|
||||
else:
|
||||
_schedule_class_platform_dict[scheduler_config].append(platform_name)
|
||||
for scheduler_config, target_list in _schedule_class_dict.items():
|
||||
schedulable_args = []
|
||||
for target in target_list:
|
||||
schedulable_args.append((target.platform_name, T_Target(target.target)))
|
||||
platform_name_list = _schedule_class_platform_dict[scheduler_config]
|
||||
scheduler_dict[scheduler_config] = Scheduler(
|
||||
scheduler_config, schedulable_args, platform_name_list
|
||||
)
|
||||
|
||||
|
||||
async def handle_insert_new_target(platform_name: str, target: T_Target):
|
||||
platform = platform_manager[platform_name]
|
||||
scheduler_obj = scheduler_dict[platform.scheduler]
|
||||
scheduler_obj.insert_new_schedulable(platform_name, target)
|
||||
|
||||
|
||||
async def handle_delete_target(platform_name: str, target: T_Target):
|
||||
platform = platform_manager[platform_name]
|
||||
scheduler_obj = scheduler_dict[platform.scheduler]
|
||||
scheduler_obj.delete_schedulable(platform_name, target)
|
||||
|
||||
|
||||
config.register_add_target_hook(handle_insert_new_target)
|
||||
config.register_delete_target_hook(handle_delete_target)
|
||||
@@ -0,0 +1,144 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Optional, Type
|
||||
|
||||
from nonebot.adapters.onebot.v11.bot import Bot
|
||||
from nonebot.log import logger
|
||||
from nonebot_plugin_apscheduler import scheduler
|
||||
|
||||
from ..config import config
|
||||
from ..platform import platform_manager
|
||||
from ..send import send_msgs
|
||||
from ..types import Target
|
||||
from ..utils import ProcessContext, SchedulerConfig
|
||||
from ..utils.get_bot import get_bot
|
||||
|
||||
|
||||
@dataclass
|
||||
class Schedulable:
|
||||
platform_name: str
|
||||
target: Target
|
||||
current_weight: int
|
||||
|
||||
|
||||
class Scheduler:
|
||||
|
||||
schedulable_list: list[Schedulable]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
scheduler_config: Type[SchedulerConfig],
|
||||
schedulables: list[tuple[str, Target]],
|
||||
platform_name_list: list[str],
|
||||
):
|
||||
self.name = scheduler_config.name
|
||||
if not scheduler_config:
|
||||
logger.error(f"scheduler config [{self.name}] not found, exiting")
|
||||
raise RuntimeError(f"{self.name} not found")
|
||||
self.scheduler_config = scheduler_config
|
||||
self.scheduler_config_obj = self.scheduler_config()
|
||||
self.schedulable_list = []
|
||||
for platform_name, target in schedulables:
|
||||
self.schedulable_list.append(
|
||||
Schedulable(
|
||||
platform_name=platform_name, target=target, current_weight=0
|
||||
)
|
||||
)
|
||||
self.platform_name_list = platform_name_list
|
||||
self.pre_weight_val = 0 # 轮调度中“本轮”增加权重和的初值
|
||||
logger.info(
|
||||
f"register scheduler for {self.name} with {self.scheduler_config.schedule_type} {self.scheduler_config.schedule_setting}"
|
||||
)
|
||||
scheduler.add_job(
|
||||
self.exec_fetch,
|
||||
self.scheduler_config.schedule_type,
|
||||
**self.scheduler_config.schedule_setting,
|
||||
)
|
||||
|
||||
async def get_next_schedulable(self) -> Optional[Schedulable]:
|
||||
if not self.schedulable_list:
|
||||
return None
|
||||
cur_weight = await config.get_current_weight_val(self.platform_name_list)
|
||||
weight_sum = self.pre_weight_val
|
||||
self.pre_weight_val = 0
|
||||
cur_max_schedulable = None
|
||||
for schedulable in self.schedulable_list:
|
||||
schedulable.current_weight += cur_weight[
|
||||
f"{schedulable.platform_name}-{schedulable.target}"
|
||||
]
|
||||
weight_sum += cur_weight[
|
||||
f"{schedulable.platform_name}-{schedulable.target}"
|
||||
]
|
||||
if (
|
||||
not cur_max_schedulable
|
||||
or cur_max_schedulable.current_weight < schedulable.current_weight
|
||||
):
|
||||
cur_max_schedulable = schedulable
|
||||
assert cur_max_schedulable
|
||||
cur_max_schedulable.current_weight -= weight_sum
|
||||
return cur_max_schedulable
|
||||
|
||||
async def exec_fetch(self):
|
||||
context = ProcessContext()
|
||||
if not (schedulable := await self.get_next_schedulable()):
|
||||
return
|
||||
logger.debug(
|
||||
f"scheduler {self.name} fetching next target: [{schedulable.platform_name}]{schedulable.target}"
|
||||
)
|
||||
send_userinfo_list = await config.get_platform_target_subscribers(
|
||||
schedulable.platform_name, schedulable.target
|
||||
)
|
||||
|
||||
client = await self.scheduler_config_obj.get_client(schedulable.target)
|
||||
context.register_to_client(client)
|
||||
|
||||
try:
|
||||
platform_obj = platform_manager[schedulable.platform_name](context, client)
|
||||
to_send = await platform_obj.do_fetch_new_post(
|
||||
schedulable.target, send_userinfo_list
|
||||
)
|
||||
except Exception as err:
|
||||
records = context.gen_req_records()
|
||||
for record in records:
|
||||
logger.warning("API request record: " + record)
|
||||
err.args += (records,)
|
||||
raise
|
||||
|
||||
if not to_send:
|
||||
return
|
||||
|
||||
for user, send_list in to_send:
|
||||
bot = get_bot(user)
|
||||
for send_post in send_list:
|
||||
logger.info("send to {}: {}".format(user, send_post))
|
||||
if not bot:
|
||||
logger.warning("no bot connected")
|
||||
else:
|
||||
await send_msgs(
|
||||
bot,
|
||||
user.user,
|
||||
user.user_type,
|
||||
await send_post.generate_messages(),
|
||||
)
|
||||
|
||||
def insert_new_schedulable(self, platform_name: str, target: Target):
|
||||
self.pre_weight_val += 1000
|
||||
self.schedulable_list.append(Schedulable(platform_name, target, 1000))
|
||||
logger.info(
|
||||
f"insert [{platform_name}]{target} to Schduler({self.scheduler_config.name})"
|
||||
)
|
||||
|
||||
def delete_schedulable(self, platform_name, target: Target):
|
||||
if not self.schedulable_list:
|
||||
return
|
||||
to_find_idx = None
|
||||
for idx, schedulable in enumerate(self.schedulable_list):
|
||||
if (
|
||||
schedulable.platform_name == platform_name
|
||||
and schedulable.target == target
|
||||
):
|
||||
to_find_idx = idx
|
||||
break
|
||||
if to_find_idx is not None:
|
||||
deleted_schdulable = self.schedulable_list.pop(to_find_idx)
|
||||
self.pre_weight_val -= deleted_schdulable.current_weight
|
||||
return
|
||||
Reference in New Issue
Block a user