From ab526a5e5f712cb969fe31ac2c0cba7d99f7ae16 Mon Sep 17 00:00:00 2001 From: KafCoppelia <740677208@qq.com> Date: Tue, 27 Dec 2022 21:03:18 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=20v0.3.2a2:=20improved=20code=20fo?= =?UTF-8?q?rmat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +- nonebot_plugin_morning/__init__.py | 99 +++++--- nonebot_plugin_morning/config.py | 12 +- nonebot_plugin_morning/data_source.py | 347 ++++++++++++++------------ nonebot_plugin_morning/utils.py | 5 +- pyproject.toml | 2 +- 6 files changed, 263 insertions(+), 208 deletions(-) diff --git a/README.md b/README.md index 8bfd8dc..2582f84 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ _🌈 おはよう! 🌈_ - + @@ -34,11 +34,11 @@ _🌈 おはよう! 🌈_ ## 版本 -v0.3.2a1 +v0.3.2a2 ⚠ 适配nonebot2-2.0.0rc1+ -[更新日志](https://github.com/MinatoAquaCrews/nonebot_plugin_morning/releases/tag/v0.3.2a1) +[更新日志](https://github.com/MinatoAquaCrews/nonebot_plugin_morning/releases/tag/v0.3.2a2) ## 安装 diff --git a/nonebot_plugin_morning/__init__.py b/nonebot_plugin_morning/__init__.py index 20818ff..3937753 100644 --- a/nonebot_plugin_morning/__init__.py +++ b/nonebot_plugin_morning/__init__.py @@ -9,7 +9,7 @@ from .config import driver from .data_source import morning_manager -__morning_version__ = "v0.3.2a1" +__morning_version__ = "v0.3.2a2" __morning_usages__ = f''' [早安] 早安/哦哈哟/おはよう [晚安] 晚安/哦呀斯密/おやすみ @@ -45,16 +45,17 @@ morning_setting = on_regex(pattern=r"^早安(开启|关闭|设置)( (时限|多重起床|超级亢奋)(( \d{1,2}){1,2})?)?$", permission=SUPERUSER | GROUP_OWNER | GROUP_ADMIN, priority=10, block=True) night_setting = on_regex(pattern=r"^晚安(开启|关闭|设置)( (时限|优质睡眠|深度睡眠)(( \d{1,2}){1,2})?)?$", permission=SUPERUSER | GROUP_OWNER | GROUP_ADMIN, priority=10, block=True) + @morning.handle() async def good_morning(bot: Bot, matcher: Matcher, event: GroupMessageEvent, args: Message = CommandArg()): arg: str = args.extract_plain_text() if arg == "帮助": await matcher.finish(__morning_usages__) - + uid = event.user_id gid = event.group_id mem_info = await bot.call_api("get_group_member_info", group_id=gid, user_id=uid) - + sex = mem_info["sex"] if sex == "male": sex_str = "少年" @@ -66,16 +67,17 @@ async def good_morning(bot: Bot, matcher: Matcher, event: GroupMessageEvent, arg msg = morning_manager.get_morning_msg(str(gid), str(uid), sex_str) await matcher.finish(message=msg, at_sender=True) + @night.handle() async def good_night(bot: Bot, matcher: Matcher, event: GroupMessageEvent, args: Message = CommandArg()): arg: str = args.extract_plain_text() if arg == "帮助": await matcher.finish(__morning_usages__) - + uid: int = event.user_id gid: int = event.group_id mem_info = await bot.call_api("get_group_member_info", group_id=gid, user_id=uid) - + sex = mem_info["sex"] if sex == "male": sex_str = "少年" @@ -87,33 +89,37 @@ async def good_night(bot: Bot, matcher: Matcher, event: GroupMessageEvent, args: msg = morning_manager.get_night_msg(str(gid), str(uid), sex_str) await matcher.finish(message=msg, at_sender=True) + @my_routine.handle() async def _(matcher: Matcher, event: GroupMessageEvent): gid = str(event.group_id) uid = str(event.user_id) - + msg = morning_manager.get_my_routine(gid, uid) await matcher.finish(message=msg, at_sender=True) + @group_routine.handle() async def _(bot: Bot, matcher: Matcher, event: GroupMessageEvent): gid = event.group_id morning_count, night_count, uid = morning_manager.get_group_routine(str(gid)) msg: str = f"今天已经有{morning_count}位群友早安了,{night_count}位群友晚安了~" - + if uid: mem_info = await bot.call_api("get_group_member_info", group_id=gid, user_id=int(uid)) nickname: str = mem_info["card"] if mem_info["card"] else mem_info["nickname"] msg += f"\n上周睡觉大王是群友:{nickname},再接再厉~" - + await matcher.finish(MessageSegment.text(msg)) + @configure.handle() async def _(matcher: Matcher, event: GroupMessageEvent): gid = str(event.group_id) - msg = morning_manager.get_group_config(gid) + msg = morning_manager.get_group_config() await matcher.finish(msg) + def parse_item(_key: str): ''' Parser setting item @@ -121,43 +127,44 @@ def parse_item(_key: str): async def _item_parser(matcher: Matcher, arg: str = ArgStr("item")) -> None: if arg == "取消": await matcher.finish("操作已取消") - + if arg == "时限" or arg == "多重起床" or arg == "超级亢奋" or \ - arg == "优质睡眠" or arg == "深度睡眠": + arg == "优质睡眠" or arg == "深度睡眠": matcher.set_arg("item", Message(arg)) else: if _key == "morning": await matcher.reject_arg("item", "输入配置不合法,可选时限/多重起床/超级亢奋") else: await matcher.reject_arg("item", "输入配置不合法,可选时限/优质睡眠/深度睡眠") - + return _item_parser + def parse_params(): ''' Parser extra params ''' async def _params_parser(matcher: Matcher, input_args: str = ArgStr("param1")) -> None: args: List[str] = input_args.split() - + logger.info(f"check in _params_parser: {args}") - + if args[0] == "取消": await matcher.finish("操作已取消") - + item = matcher.get_arg("item", None) if not item: await matcher.finish("配置出错,操作已取消") - + if item != "时限": if len(args) > 1: await matcher.send("输入参数过多,仅取第一个参数") - + try: _ = int(args[0]) except ValueError: await matcher.reject_arg("param1", "输入参数必须是纯数字") - + matcher.set_arg("param1", Message(args[0])) else: if len(args) == 1: @@ -168,28 +175,29 @@ async def _params_parser(matcher: Matcher, input_args: str = ArgStr("param1")) - _ = int(args[1]) except ValueError: await matcher.send("输入参数必须是纯数字,请重新输入") - + matcher.set_arg("param1", Message(args[0])) matcher.set_arg("param2", Message(args[1])) return _params_parser + @morning_setting.handle() async def _(matcher: Matcher, matched: str = RegexMatched()): args: List[str] = matched.split() arg_len: int = len(args) - + if args[0][-2:] == "开启" or args[0][-2:] == "关闭" or args[0][-2:] == "设置": matcher.set_arg("op_type", Message(args[0][-2:])) else: await matcher.finish("输入指令不合法,可选:开启/关闭/设置") - + if arg_len > 1: if args[1] == "时限" or args[1] == "多重起床" or args[1] == "超级亢奋": matcher.set_arg("item", Message(args[1])) else: await matcher.finish("输入配置不合法,可选:时限/多重起床/超级亢奋") - + # Params are numbers, but store in state in string if arg_len > 2: if args[1] != "时限": @@ -212,10 +220,11 @@ async def _(matcher: Matcher, matched: str = RegexMatched()): _ = int(args[3]) except ValueError: await matcher.send("输入参数必须是纯数字,请重新输入") - + matcher.set_arg("param1", Message(args[2])) matcher.set_arg("param2", Message(args[3])) + @morning_setting.got( "item", prompt="请选择配置项,可选:时限/多重起床/超级亢奋,输入取消以取消操作", @@ -224,6 +233,7 @@ async def _(matcher: Matcher, matched: str = RegexMatched()): async def _(matcher: Matcher): matcher.skip() + @morning_setting.got( "param1", prompt="请输入设置参数,时限配置项请输入允许的最早/晚的睡觉时间(空格间隔),其余配置项请输入一个时间,输入取消以取消操作", @@ -234,51 +244,52 @@ async def _(event: GroupMessageEvent, matcher: Matcher): _op_type: str = "" if __op_type: _op_type = __op_type.extract_plain_text() - + __item = matcher.get_arg("item", None) _item: str = "" if __item: _item = __item.extract_plain_text() - + __param1 = matcher.get_arg("param1", None) if __param1: _param1 = int(__param1.extract_plain_text()) else: _param1 = 0 - + __param2 = matcher.get_arg("param2", None) if __param2: _param2 = int(__param2.extract_plain_text()) else: _param2 = 0 - + if _op_type == "设置": msg = morning_manager.morning_config(_item, _param1, _param2) elif _op_type == "开启": msg = morning_manager.morning_switch(_item, True) else: msg = morning_manager.morning_switch(_item, False) - + await morning_setting.finish(msg) - + + @night_setting.handle() async def _(matcher: Matcher, matched: str = RegexMatched()): args: List[str] = matched.split() arg_len: int = len(args) - + logger.info(f"check in handle: {args}") if args[0][-2:] == "开启" or args[0][-2:] == "关闭" or args[0][-2:] == "设置": matcher.set_arg("op_type", Message(args[0][-2:])) else: await matcher.finish("输入指令不合法,可选:开启/关闭/设置") - + if arg_len > 1: if args[1] == "时限" or args[1] == "优质睡眠" or args[1] == "深度睡眠": matcher.set_arg("item", Message(args[1])) else: await matcher.finish("输入配置不合法,可选:时限/优质睡眠/深度睡眠") - + # Params are numbers, but store in state in string if arg_len > 2: if args[1] != "时限": @@ -301,10 +312,11 @@ async def _(matcher: Matcher, matched: str = RegexMatched()): _ = int(args[3]) except ValueError: await matcher.send("输入参数必须是纯数字,请重新输入") - + matcher.set_arg("param1", Message(args[2])) matcher.set_arg("param2", Message(args[3])) - + + @night_setting.got( "item", prompt="请选择配置项,可选:时限/优质睡眠/深度睡眠,输入取消以取消操作", @@ -313,6 +325,7 @@ async def _(matcher: Matcher, matched: str = RegexMatched()): async def _(matcher: Matcher): matcher.skip() + @night_setting.got( "param1", prompt="请输入设置参数,时限配置项请输入允许的最早/晚的睡觉时间(空格间隔),其余配置项请输入一个时间,输入取消以取消操作", @@ -323,47 +336,53 @@ async def _(event: GroupMessageEvent, matcher: Matcher): _op_type: str = "" if __op_type: _op_type = __op_type.extract_plain_text() - + __item = matcher.get_arg("item", None) _item: str = "" if __item: _item = __item.extract_plain_text() - + __param1 = matcher.get_arg("param1", None) if __param1: _param1 = int(__param1.extract_plain_text()) else: _param1 = 0 - + __param2 = matcher.get_arg("param2", None) if __param2: _param2 = int(__param2.extract_plain_text()) else: _param2 = 0 - + if _op_type == "设置": msg = morning_manager.night_config(_item, _param1, _param2) elif _op_type == "开启": msg = morning_manager.night_switch(_item, True) else: msg = morning_manager.night_switch(_item, False) - + await night_setting.finish(msg) # 每日最早晚安时间,重置昨日早晚安计数 + + @driver.on_startup async def daily_refresh(): morning_manager.daily_scheduler() logger.info("每日早晚安定时刷新任务已启动!") # 每周一最晚晚安时间统计部分周数据 + + @driver.on_startup async def monday_weekly_night_refresh(): morning_manager.weekly_night_scheduler() logger.info("每周晚安定时刷新任务已启动!") # 每周一最晚早安时间,统计上周睡眠时间、早安并重置 + + @driver.on_startup async def weekly_refresh(): morning_manager.weekly_sleep_time_scheduler() - logger.info("每周睡眠时间定时刷新任务已启动!") \ No newline at end of file + logger.info("每周睡眠时间定时刷新任务已启动!") diff --git a/nonebot_plugin_morning/config.py b/nonebot_plugin_morning/config.py index 617603e..70c15a6 100644 --- a/nonebot_plugin_morning/config.py +++ b/nonebot_plugin_morning/config.py @@ -3,7 +3,10 @@ from pathlib import Path from pydantic import BaseModel, Extra from typing import Dict, Union -import json +try: + import ujson as json +except ModuleNotFoundError: + import json from .utils import morning_json_update @@ -80,7 +83,7 @@ async def _() -> None: with open(config_json_path, 'w', encoding='utf-8') as f: json.dump(_config, f, ensure_ascii=False, indent=4) - logger.info("Initialized the config.json of Morning plugin") + logger.info("Initialized the config.json") # Old data.json will be transferred from v0.2.x into v0.3.x version automatically old_data_path: Path = morning_config.morning_path / "data.json" @@ -96,7 +99,7 @@ async def _() -> None: with open(new_data_path, 'w', encoding='utf-8') as f: json.dump(_nfile, f, ensure_ascii=False, indent=4) - logger.info("旧版数据文件已自动更新至新版,后续可关闭 OLD_MORNING_COMPATIBLE 选项!") + logger.info("旧版数据文件已自动更新至新版格式!") old_data_path.unlink() @@ -104,5 +107,4 @@ async def _() -> None: with open(new_data_path, 'w', encoding='utf-8') as f: json.dump(dict(), f, ensure_ascii=False, indent=4) - logger.warning( - "旧版数据文件不存在,已自动创建新版数据文件。开启 OLD_MORNING_COMPATIBLE 选项可将旧版 data.json 数据文件自动更新。") + logger.warning("旧版数据文件不存在,已重新创建数据文件!") diff --git a/nonebot_plugin_morning/data_source.py b/nonebot_plugin_morning/data_source.py index 755c69d..f8285b5 100644 --- a/nonebot_plugin_morning/data_source.py +++ b/nonebot_plugin_morning/data_source.py @@ -8,7 +8,7 @@ import random from .config import morning_config from .utils import * - + require("nonebot_plugin_apscheduler") from nonebot_plugin_apscheduler import scheduler from apscheduler.jobstores.base import JobLookupError @@ -17,7 +17,7 @@ class MorningManager: def __init__(self): self._morning: Dict[str, Dict[str, Dict[str, Dict[str, Union[str, int, datetime, List[int]]]]]] = dict() self._morning_path: Path = morning_config.morning_path / "morning.json" - + self._config: Dict[str, Dict[str, Dict[str, Dict[str, Union[bool, int]]]]] = dict() self._config_path: Path = morning_config.morning_path / "config.json" @@ -26,79 +26,94 @@ def _init_group_data(self, gid: str) -> None: Initialize group data. ''' self._load_data() - + if gid not in self._morning: self._morning.update({ gid: { "group_count": { "daily": { - "good_morning": 0, # Daily good-morning count of groups, REFRESH at the late time of good-morning everyday - "good_night": 0 # Daily good-night count of groups, REFRESH at the late time of good-night everyday + # Daily good-morning count of groups, REFRESH at the late time of good-morning everyday + "good_morning": 0, + # Daily good-night count of groups, REFRESH at the late time of good-night everyday + "good_night": 0 }, "weekly": { - "sleeping_king": "" # Sleeping king of group of last week, REFRESH at the late time of good-morning every Monday + # Sleeping king of group of last week, REFRESH at the late time of good-morning every Monday + "sleeping_king": "" } } } }) - + self._save_data() # ------------------------------ Config ------------------------------ # - def get_group_config(self, gid: str) -> MessageSegment: + def get_group_config(self) -> MessageSegment: ''' Return the current configurations. ''' msg: str = "早安晚安设置如下:" self._load_config() - + # Morning config msg += "\n是否要求规定时间内起床:" morning_intime = self._config["morning"]["morning_intime"]["enable"] + if morning_intime: - msg += "是\n - 最早允许起床时间:" + str(self._config["morning"]['morning_intime']["early_time"]) + "点\n - 最晚允许起床时间:" + str(self._config["morning"]["morning_intime"]["late_time"]) + "点" + msg += "是\n - 最早允许起床时间:" + str(self._config["morning"]['morning_intime']["early_time"]) + "点\n - 最晚允许起床时间:" + str( + self._config["morning"]["morning_intime"]["late_time"]) + "点" else: msg += "否" - + msg += "\n是否允许连续多次起床:" multi_get_up = self._config["morning"]["multi_get_up"]["enable"] + if multi_get_up: msg += "是" else: - msg += "否\n - 允许的最短起床间隔:" + str(self._config["morning"]["multi_get_up"]["interval"]) + "小时" - + msg += "否\n - 允许的最短起床间隔:" + \ + str(self._config["morning"]["multi_get_up"]["interval"]) + "小时" + msg += "\n是否允许超级亢奋(即睡眠时长很短):" - super_get_up= self._config["morning"]["super_get_up"]["enable"] + super_get_up = self._config["morning"]["super_get_up"]["enable"] + if super_get_up: msg += "是" else: - msg += "否\n - 允许的最短睡觉时长:" + str(self._config["morning"]["super_get_up"]["interval"]) + "小时" - + msg += "否\n - 允许的最短睡觉时长:" + \ + str(self._config["morning"]["super_get_up"]["interval"]) + "小时" + # Night config msg += "\n是否要求规定时间内睡觉:" night_intime = self._config["night"]["night_intime"]["enable"] + if night_intime: msg += "是\n - 最早允许睡觉时间:" + str(self._config["night"]["night_intime"]["early_time"]) + \ - "点\n - 最晚允许睡觉时间:第二天早上" + str(self._config["night"]["night_intime"]["late_time"]) + "点" + "点\n - 最晚允许睡觉时间:第二天早上" + \ + str(self._config["night"]["night_intime"]["late_time"]) + "点" else: msg += "否" - + msg += "\n是否开启优质睡眠:" good_sleep = self._config["night"]["good_sleep"]["enable"] + if good_sleep: msg += "是" else: - msg += "否\n - 允许的最短优质睡眠:" + str(self._config["night"]["good_sleep"]["interval"]) + "小时" - + msg += "否\n - 允许的最短优质睡眠:" + \ + str(self._config["night"]["good_sleep"]["interval"]) + "小时" + msg += "\n是否允许深度睡眠(即清醒时长很短):" deep_sleep = self._config["night"]["deep_sleep"]["enable"] + if deep_sleep: msg += "是" else: - msg += "否\n - 允许的最短清醒时长:" + str(self._config["night"]["deep_sleep"]["interval"]) + "小时" - + msg += "否\n - 允许的最短清醒时长:" + \ + str(self._config["night"]["deep_sleep"]["interval"]) + "小时" + return MessageSegment.text(msg) - + def _change_enable(self, day_or_night: str, _setting: str, new_state: bool) -> str: ''' Change and save the new state of a setting. @@ -114,63 +129,64 @@ def _change_set_time(self, _day_or_night: str, _setting: str, _interval_or_early Change the interval of a setting. ''' self._load_config() - + if _setting == "morning_intime" or _setting == "night_intime": if not isinstance(_late_time, int): return "配置更新失败:缺少参数!" - + early_time: int = _interval_or_early_time late_time: int = _late_time - + self._config[_day_or_night][_setting]["early_time"] = early_time self._config[_day_or_night][_setting]["late_time"] = late_time else: interval: int = _interval_or_early_time self._config[_day_or_night][_setting]["interval"] = interval - + msg: str = "配置更新成功!" - + # Some settings are True in default if _setting == "morning_intime" or _setting == "night_intime" or _setting == "good_sleep" \ - and self._config[_day_or_night][_setting]["enable"] == False: + and self._config[_day_or_night][_setting]["enable"] == False: self._config[_day_or_night][_setting]["enable"] = True msg += "且此项设置已启用!" - + # Some settings are False in default if _setting == "multi_get_up" or _setting == "super_get_up" or _setting == "deep_sleep" \ - and self._config[_day_or_night][_setting]["enable"] == True: + and self._config[_day_or_night][_setting]["enable"] == True: self._config[_day_or_night][_setting]["enable"] = False msg += "且此项设置已禁用!" - + self._save_config() - + return msg - def morning_config(self, _mor_setting: str, *args: List[int]) -> MessageSegment: + def morning_config(self, _mor_setting: str, param1: int, param2: int) -> MessageSegment: ''' Configurations about morning. ''' _setting: str = mor_switcher[_mor_setting] if _setting == "morning_intime": - early_time: int = args[0] - late_time: int = args[1] - + early_time: int = param1 + late_time: int = param2 + if early_time < 0 or early_time > 24 or late_time < 0 or late_time > 24: msg = "错误!您设置的时间未在0-24之间,要求:0 <= 时间 <= 24" else: - msg = self._change_set_time("morning", _setting, early_time, late_time) - + msg = self._change_set_time( + "morning", _setting, early_time, late_time) + # Change the data of daily good-morning/night scheduler and weekly sleeping time scheduler self.daily_scheduler(early_time) self.weekly_sleep_time_scheduler(late_time) else: - interval: int = args[0] - + interval: int = param1 + if interval < 0 or interval > 24: msg = "错误!您设置的时间间隔未在0-24之间,要求:0 <= 时间 <= 24" else: msg = self._change_set_time("morning", _setting, interval) - + return MessageSegment.text(msg) def morning_switch(self, _mor_setting: str, new_state: bool) -> MessageSegment: @@ -179,7 +195,7 @@ def morning_switch(self, _mor_setting: str, new_state: bool) -> MessageSegment: ''' _setting: str = mor_switcher[_mor_setting] msg: str = self._change_enable("morning", _setting, new_state) - + # Change the status of daily good-morning/night schedulers and weekly sleeping time scheduler if _setting == "morning_intime": # Remove the schedulers @@ -187,52 +203,53 @@ def morning_switch(self, _mor_setting: str, new_state: bool) -> MessageSegment: try: scheduler.remove_job("weekly_sleep_time_scheduler") logger.info(f"每周睡眠时间定时刷新任务已关闭!") - + except JobLookupError as e: logger.warning(f"每周睡眠时间定时刷新任务移除失败: {e}") msg += "\n每周睡眠时间定时刷新任务移除失败" - + try: scheduler.remove_job("daily_scheduler") logger.info(f"每日早晚安定时刷新任务已关闭!") - + except JobLookupError as e: logger.warning(f"每日早晚安定时刷新任务移除失败: {e}") msg += "\n每日早晚安定时刷新任务移除失败" - + # Add the schedulers if they don't exist else: if not scheduler.get_job("weekly_sleep_time_scheduler"): self.weekly_sleep_time_scheduler() logger.info("每周睡眠时间定时刷新任务已启动!") - - if not scheduler.get_job("daily_scheduler"): + + if not scheduler.get_job("daily_scheduler"): self.daily_scheduler() logger.info("每日早晚安定时刷新任务已启动!") - + return MessageSegment.text(msg) - def night_config(self, _nig_setting: str, *args: List[int]) -> MessageSegment: + def night_config(self, _nig_setting: str, param1: int, param2: int) -> MessageSegment: ''' Configurations about night. ''' _setting: str = nig_switcher[_nig_setting] if _setting == "night_intime": - early_time: int = args[0] - late_time: int = args[1] - + early_time: int = param1 + late_time: int = param2 + if early_time < 0 or early_time > 24 or late_time < 0 or late_time > 24: msg = "错误!您设置的时间未在0-24之间,要求:0 <= 时间 <= 24" else: - msg = self._change_set_time("night", _setting, early_time, late_time) + msg = self._change_set_time( + "night", _setting, early_time, late_time) else: - interval: int = args[0] - + interval: int = param1 + if interval < 0 or interval > 24: msg = "错误!您设置的时间间隔未在0-24之间,要求:0 <= 时间 <= 24" else: msg = self._change_set_time("night", _setting, interval, None) - + return MessageSegment.text(msg) def night_switch(self, _nig_setting: str, new_state: bool) -> MessageSegment: @@ -241,7 +258,7 @@ def night_switch(self, _nig_setting: str, new_state: bool) -> MessageSegment: ''' _setting: str = nig_switcher[_nig_setting] msg: str = self._change_enable("night", _setting, new_state) - + return MessageSegment.text(msg) # ------------------------------ Morning Judgement ------------------------------ # @@ -250,15 +267,15 @@ def _morning_and_update(self, gid: str, uid: str, now_time: datetime) -> Tuple[s Morning & update data. ''' self._load_data() - + # 起床并写数据 sleep_time: datetime = datetime.strptime(self._morning[gid][uid]["daily"]["night_time"], "%Y-%m-%d %H:%M:%S") in_sleep: timedelta = now_time - sleep_time - days, hours, minutes, seconds = total_seconds2tuple_time(int(in_sleep.total_seconds())) - + _, hours, minutes, seconds = total_seconds2tuple_time(int(in_sleep.total_seconds())) + # 睡觉时间小于24小时就同时给出睡眠时长,记录;否则隔日 in_sleep_tmp: str = "" - + if in_sleep.days > 0: in_sleep_tmp = "" else: @@ -272,9 +289,9 @@ def _morning_and_update(self, gid: str, uid: str, now_time: datetime) -> Tuple[s self._morning[gid][uid]["weekly"]["weekly_morning_count"] += 1 # Total morning count add self._morning[gid][uid]["total"]["morning_count"] += 1 - + lastweek_emt: Union[int, str] = self._morning[gid][uid]["weekly"]["lastweek_earliest_morning_time"] - + # If it is integer, it means no data if isinstance(lastweek_emt, int): self._morning[gid][uid]["weekly"]["lastweek_earliest_morning_time"] = now_time @@ -282,10 +299,10 @@ def _morning_and_update(self, gid: str, uid: str, now_time: datetime) -> Tuple[s # If weekly morning time is later than daily's, update if not is_later(self._morning[gid][uid]["daily"]["morning_time"], self._morning[gid][uid]["weekly"]["lastweek_earliest_morning_time"]): self._morning[gid][uid]["weekly"]["lastweek_earliest_morning_time"] = now_time - + # 判断是今天第几个起床的 self._morning[gid]["group_count"]["daily"]["good_morning"] += 1 - + self._save_data() return self._morning[gid]["group_count"]["daily"]["good_morning"], in_sleep_tmp if in_sleep_tmp != "" else 0 @@ -295,39 +312,39 @@ def get_morning_msg(self, gid: str, uid: str, sex_str: str) -> MessageSegment: Return good-morning info. ''' self._load_config() - + # 若开启规定时间早安,则判断该时间是否允许早安 now_time: datetime = datetime.now() if self._config["morning"]["morning_intime"]["enable"]: _early_time: int = self._config["morning"]["morning_intime"]["early_time"] _late_time: int = self._config["morning"]["morning_intime"]["late_time"] - + if not is_MorTimeinRange(_early_time, _late_time, now_time): msg = f"现在不能早安哦,可以早安的时间为{_early_time}时到{_late_time}时~" return MessageSegment.text(msg) self._init_group_data(gid) - + # 当数据里有过这个人的信息 if uid in self._morning[gid]: # 判断是否隔日 last_sleep_time: datetime = datetime.strptime(self._morning[gid][uid]["daily"]["night_time"], "%Y-%m-%d %H:%M:%S") if last_sleep_time - now_time < timedelta(hours=24): - + # 若关闭连续多次早安,则判断在设定时间内是否多次早安 if not self._config["morning"]["multi_get_up"]["enable"] and self._morning[gid][uid]["daily"]["morning_time"] != 0: interval: int = self._config["morning"]["multi_get_up"]["interval"] morning_time: datetime = datetime.strptime(self._morning[gid][uid]["daily"]["morning_time"], "%Y-%m-%d %H:%M:%S") - + if now_time - morning_time < timedelta(hours=interval): msg = f"{interval}小时内你已经早安过了哦~" return MessageSegment.text(msg) - + # 若关闭超级亢奋,则判断睡眠时长是否小于设定时间 if not self._config["morning"]["super_get_up"]["enable"]: interval: int = self._config["morning"]["super_get_up"]["interval"] night_time: datetime = datetime.strptime(self._morning[gid][uid]["daily"]["night_time"], "%Y-%m-%d %H:%M:%S") - + if now_time - night_time < timedelta(hours=interval): msg = "你可猝死算了吧?现在不能早安哦~" return MessageSegment.text(msg) @@ -335,19 +352,19 @@ def get_morning_msg(self, gid: str, uid: str, sex_str: str) -> MessageSegment: else: msg = random.choice(morning_prompt) return MessageSegment.text(msg) - + # 否则说明:他还没睡过觉;即便如此,还是回复早安! else: msg = random.choice(morning_prompt) return MessageSegment.text(msg) - + # 当前面条件均符合的时候,允许早安 num, in_sleep = self._morning_and_update(gid, uid, now_time) if isinstance(in_sleep, str): msg = f"早安成功!你的睡眠时长为{in_sleep},\n你是今早第{num}个起床的{sex_str}!" else: msg = random.choice(morning_prompt) - + return MessageSegment.text(msg) # ------------------------------ Night Judgement ------------------------------ # @@ -356,35 +373,46 @@ def _night_and_update(self, gid: str, uid: str, now_time: datetime) -> Tuple[str Good night & update. ''' self._load_data() - + # 没有晚安数据,则创建 if uid not in self._morning[gid]: self._morning[gid].update({ uid: { "daily": { - "morning_time": 0, + "morning_time": 0, "night_time": now_time }, "weekly": { - "weekly_morning_count": 0, # Weekly good-morning count, RESET at the late time of good-morning every Monday - "weekly_night_count": 1, # Weekly good-night count, RESET at 0 A.M. every Monday - "weekly_sleep": [0, 0, 0, 0], # Weekly sleeping time, list of days/hrs/mins/secs, RESET at the late time of good-morning every Monday - "lastweek_morning_count": 0, # Good-morning count of last week, REFRESH at the late time of good-morning every Monday - "lastweek_night_count": 0, # Good-night count of last week, REFRESH at 0 A.M. every Monday - "lastweek_sleep": [0, 0, 0, 0], # Sleeping time of last week, list of days/hrs/mins/secs, REFRESH at the late time of good-morning every Monday - "lastweek_earliest_morning_time": 0,# Earliest good-morning time of last week, REFRESH at a new daily good-morning time in - "lastweek_latest_night_time": 0 # Latest good-night time of last week, REFRESH at a new daily good-night time in + # Weekly good-morning count, RESET at the late time of good-morning every Monday + "weekly_morning_count": 0, + # Weekly good-night count, RESET at 0 A.M. every Monday + "weekly_night_count": 1, + # Weekly sleeping time, list of days/hrs/mins/secs, RESET at the late time of good-morning every Monday + "weekly_sleep": [0, 0, 0, 0], + # Good-morning count of last week, REFRESH at the late time of good-morning every Monday + "lastweek_morning_count": 0, + # Good-night count of last week, REFRESH at 0 A.M. every Monday + "lastweek_night_count": 0, + # Sleeping time of last week, list of days/hrs/mins/secs, REFRESH at the late time of good-morning every Monday + "lastweek_sleep": [0, 0, 0, 0], + # Earliest good-morning time of last week, REFRESH at a new daily good-morning time in + "lastweek_earliest_morning_time": 0, + # Latest good-night time of last week, REFRESH at a new daily good-night time in + "lastweek_latest_night_time": 0 }, "total": { - "morning_count": 0, # Total good-morning count, never RESET - "night_count": 1, # Total good-night count, never RESET - "total_sleep": [0, 0, 0, 0] # Total sleeping time, list of days/hrs/mins/secs, REFRESH at every valid good-morning + # Total good-morning count, never RESET + "morning_count": 0, + # Total good-night count, never RESET + "night_count": 1, + # Total sleeping time, list of days/hrs/mins/secs, REFRESH at every valid good-morning + "total_sleep": [0, 0, 0, 0] } } }) - + self._morning[gid][uid]["weekly"]["lastweek_latest_night_time"] = self._morning[gid][uid]["daily"]["night_time"] - + # 若有就更新数据 else: # Daily night time @@ -393,9 +421,9 @@ def _night_and_update(self, gid: str, uid: str, now_time: datetime) -> Tuple[str self._morning[gid][uid]["weekly"]["weekly_night_count"] += 1 # Total night count add self._morning[gid][uid]["total"]["night_count"] += 1 - + lastweek_lnt: Union[int, str] = self._morning[gid][uid]["weekly"]["lastweek_latest_night_time"] - + # If lastweek_lnt is integer, it means no data if isinstance(lastweek_lnt, int): self._morning[gid][uid]["weekly"]["lastweek_latest_night_time"] = now_time @@ -403,14 +431,14 @@ def _night_and_update(self, gid: str, uid: str, now_time: datetime) -> Tuple[str # If daily sleep time is later than weekly's, update if is_later(self._morning[gid][uid]["daily"]["night_time"], self._morning[gid][uid]["weekly"]["lastweek_latest_night_time"]): self._morning[gid][uid]["weekly"]["lastweek_latest_night_time"] = now_time - + # 当上次起床时间非0,计算清醒时长 in_day_tmp: str = "" if self._morning[gid][uid]["daily"].get("morning_time", 0) != 0: get_up_time: datetime = datetime.strptime(self._morning[gid][uid]["daily"]["morning_time"], "%Y-%m-%d %H:%M:%S") in_day: timedelta = now_time - get_up_time _, hours, minutes, seconds = total_seconds2tuple_time(int(in_day.total_seconds())) - + if in_day.days > 0: in_day_tmp = "" else: @@ -418,7 +446,7 @@ def _night_and_update(self, gid: str, uid: str, now_time: datetime) -> Tuple[str # 判断是今天第几个睡觉的 self._morning[gid]["group_count"]["daily"]["good_night"] += 1 - + self._save_data() return self._morning[gid]["group_count"]["daily"]["good_night"], in_day_tmp if in_day_tmp != "" else 0 @@ -428,13 +456,13 @@ def get_night_msg(self, gid: str, uid: str, sex_str: str) -> MessageSegment: Return good-night info. ''' self._load_config() - + # 若开启规定时间晚安,则判断该时间是否允许晚安 now_time: datetime = datetime.now() if self._config["night"]["night_intime"]["enable"]: _early_time: int = self._config["night"]["night_intime"]["early_time"] _late_time: int = self._config["night"]["night_intime"]["late_time"] - + if not is_NigTimeinRange(_early_time, _late_time, now_time): msg = f"现在不能晚安哦,可以晚安的时间为{_early_time}时到第二天早上{_late_time}时~" return MessageSegment.text(msg) @@ -443,22 +471,22 @@ def get_night_msg(self, gid: str, uid: str, sex_str: str) -> MessageSegment: # 当数据里有过这个人的信息就判断: if uid in self._morning[gid]: - + # 若开启优质睡眠,则判断在设定时间内是否多次晚安 if self._config["night"]["good_sleep"]["enable"]: interval: int = self._config["night"]["good_sleep"]["interval"] night_time: datetime = datetime.strptime(self._morning[gid][uid]["daily"]["night_time"], "%Y-%m-%d %H:%M:%S") - + if now_time - night_time < timedelta(hours=interval): msg = f"{interval}小时内你已经晚安过了哦~" return MessageSegment.text(msg) - + # 若关闭深度睡眠,则判断不在睡觉的时长是否小于设定时长 if isinstance(self._morning[gid][uid]["daily"]["morning_time"], str): if not self._config["night"]["deep_sleep"]["enable"]: interval: int = self._config["night"]["deep_sleep"]["interval"] morning_time: datetime = datetime.strptime(self._morning[gid][uid]["daily"]["morning_time"], "%Y-%m-%d %H:%M:%S") - + if now_time - morning_time < timedelta(hours=interval): msg = "睡这么久还不够?现在不能晚安哦~" return MessageSegment.text(msg) @@ -469,81 +497,82 @@ def get_night_msg(self, gid: str, uid: str, sex_str: str) -> MessageSegment: msg = f"晚安成功!你是今晚第{num}个睡觉的{sex_str}!" else: msg = f"晚安成功!你今天的清醒时长为{in_day},\n你是今晚第{num}个睡觉的{sex_str}!" - + return MessageSegment.text(msg) - + # ------------------------------ Routine ------------------------------ # def get_my_routine(self, gid: str, uid: str) -> MessageSegment: ''' Get user's routine. - If on Monday and now is later than the latest time of good-morning of Monday, good-morning/night count of last week & sleeping time will be included. - Else, add weekly info of current week. ''' self._init_group_data(gid) - + now_time: datetime = datetime.now() today: int = now_time.weekday() - + if uid in self._morning[gid]: # Daily info get_up_time: str = self._morning[gid][uid]["daily"]["morning_time"] sleep_time: str = self._morning[gid][uid]["daily"]["night_time"] - + # Total info morning_count: int = self._morning[gid][uid]["total"]["morning_count"] night_count: int = self._morning[gid][uid]["total"]["night_count"] total_sleep: List[int] = self._morning[gid][uid]["total"]["total_sleep"] - + msg: str = "你的作息数据如下:" msg += f"\n最近一次早安时间为{get_up_time}" msg += f"\n最近一次晚安时间为{sleep_time}" - + week_list: List[str] = ["一", "二", "三", "四", "五", "六", "日"] - + # When on Monday and now time is later than the latest time of good-morning if today == MONDAY: hour: int = self.get_refresh_time("morning", "late_time") - + if hour != -1 and is_later_oclock(now_time, hour): lastweek_morning_count: int = self._morning[gid][uid]["weekly"]["lastweek_morning_count"] lastweek_night_count: int = self._morning[gid][uid]["weekly"]["lastweek_night_count"] lastweek_sleep: List[int] = self._morning[gid][uid]["weekly"]["lastweek_sleep"] - - lastweek_lnt_date: datetime = datetime.strptime(self._morning[gid][uid]["weekly"]["lastweek_latest_night_time"], "%Y-%m-%d %H:%M:%S") + + lastweek_lnt_date: datetime = datetime.strptime( + self._morning[gid][uid]["weekly"]["lastweek_latest_night_time"], "%Y-%m-%d %H:%M:%S") lastweek_lnt: time = lastweek_lnt_date.time() latest_day: int = lastweek_lnt_date.weekday() - - lastweek_emt_date: datetime = datetime.strptime(self._morning[gid][uid]["weekly"]["lastweek_earliest_morning_time"], "%Y-%m-%d %H:%M:%S") + + lastweek_emt_date: datetime = datetime.strptime( + self._morning[gid][uid]["weekly"]["lastweek_earliest_morning_time"], "%Y-%m-%d %H:%M:%S") lastweek_emt: time = lastweek_emt_date.time() earliest_day: int = lastweek_emt_date.weekday() - + msg += f"\n上周早安了{lastweek_morning_count}次" msg += f"\n上周晚安了{lastweek_night_count}次" msg += f"\n上周睡眠时间为{lastweek_sleep[0]}天{lastweek_sleep[1]}时{lastweek_sleep[2]}分{lastweek_sleep[3]}秒" msg += f"\n上周最晚晚安时间是周{week_list[latest_day]} {lastweek_lnt}" if random.random() > 0.5: msg += f",{random.choice(the_latest_night_prompt)}" - + msg += f"\n上周最早早安时间是周{week_list[earliest_day]} {lastweek_emt}" if random.random() > 0.5: msg += f",{random.choice(the_earliest_morning_prompt)}" - + # Not on Monday, add weekly info else: weekly_morning_count: int = self._morning[gid][uid]["weekly"]["weekly_morning_count"] weekly_night_count: int = self._morning[gid][uid]["weekly"]["weekly_night_count"] - + msg += f"\n本周早安了{weekly_morning_count}次" msg += f"\n本周晚安了{weekly_night_count}次" - + msg += f"\n一共早安了{morning_count}次" msg += f"\n一共晚安了{night_count}次" msg += f"\n一共睡眠了{total_sleep[0]}天{total_sleep[1]}时{total_sleep[2]}分{total_sleep[3]}秒" + else: msg: str = "你本周还没有早晚安过呢!暂无数据~" - + return MessageSegment.text(msg) def get_group_routine(self, gid: str) -> Tuple[int, int, Optional[str]]: @@ -552,29 +581,29 @@ def get_group_routine(self, gid: str) -> Tuple[int, int, Optional[str]]: If on Monday and now is later than the latest time of good-morning of Monday, add sleeping king of last week. ''' self._init_group_data(gid) - + now_time: datetime = datetime.now() today: int = now_time.weekday() - + morning_count: int = self._morning[gid]["group_count"]["daily"]["good_morning"] - night_count: int = self._morning[gid]["group_count"]["daily"]["good_night"] - + night_count: int = self._morning[gid]["group_count"]["daily"]["good_night"] + if today == MONDAY: uid: str = "" hour: int = self.get_refresh_time("morning", "late_time") - + if hour != -1 and is_later_oclock(now_time, hour): uid = self._morning[gid]["group_count"]["weekly"]["sleeping_king"] - + return morning_count, night_count, uid if uid != "" else None - + return morning_count, night_count, None # ------------------------------ Utils ------------------------------ # def _save_data(self) -> None: with open(self._morning_path, 'w', encoding='utf-8') as f: json.dump(self._morning, f, ensure_ascii=False, indent=4, cls=DateTimeEncoder) - + def _save_config(self) -> None: with open(self._config_path, 'w', encoding='utf-8') as f: json.dump(self._config, f, ensure_ascii=False, indent=4) @@ -582,11 +611,11 @@ def _save_config(self) -> None: def _load_data(self) -> None: with open(self._morning_path, "r", encoding="utf-8") as f: self._morning = json.load(f) - + def _load_config(self) -> None: with open(self._config_path, "r", encoding="utf-8") as f: self._config = json.load(f) - + def get_refresh_time(self, _time: str, key: str) -> int: ''' Get the time given the specific type(day or night) and key. @@ -595,39 +624,39 @@ def get_refresh_time(self, _time: str, key: str) -> int: self._load_config() return self._config[_time][f"{_time}_intime"][key] if self._config[_time][f"{_time}_intime"]["enable"] else -1 - - # ------------------------------ Refreshing Jobs ------------------------------ # + + # ------------------------------ Refreshing Jobs ------------------------------ # def group_daily_refresh(self) -> None: ''' Reset good-morning/night count of groups of yesterday at the earliest time of daily good-night. ''' self._load_data() - + for gid in self._morning: self._morning[gid]["group_count"]["daily"]["good_morning"] = 0 self._morning[gid]["group_count"]["daily"]["good_night"] = 0 - + self._save_data() logger.info("每日早晚安已刷新!") - + def weekly_night_refresh(self) -> None: ''' 1. Refresh good-night count of last week at 0 A.M. every Monday. 2. Reset weekly good-night count at 0 A.M. every Monday. ''' self._load_data() - + for gid in self._morning: for uid, user_items in self._morning[gid].items(): # Remember to jump over the key "group_count" if uid == "group_count": continue - + user_items["weekly"]["lastweek_night_count"] = user_items["weekly"]["weekly_night_count"] user_items["weekly"]["weekly_night_count"] = 0 - + self._save_data() - + def weekly_sleep_time_refresh(self) -> None: ''' 1. Refresh sleeping time & good-morning count of last week. @@ -635,29 +664,29 @@ def weekly_sleep_time_refresh(self) -> None: 3. Reset weekly sleeping time & good-morning count. ''' self._load_data() - + for gid in self._morning: _max_sleep_time: List[int] = [0, 0, 0, 0] _sleeping_king_uid: str = "" - + for uid, user_items in self._morning[gid].items(): # Remember to jump over the key "group_count" - if uid == "group_count": + if uid == "group_count": continue - + user_items["weekly"]["lastweek_morning_count"] = user_items["weekly"]["weekly_morning_count"] user_items["weekly"]["lastweek_sleep"] = user_items["weekly"]["weekly_sleep"] - + user_items["weekly"]["weekly_morning_count"] = 0 user_items["weekly"]["weekly_sleep"] = [0, 0, 0, 0] - + # Compare sleeping times, day > hrs > mins > secs if user_items["weekly"]["lastweek_sleep"] > _max_sleep_time: _max_sleep_time = user_items["weekly"]["lastweek_sleep"] _sleeping_king_uid = uid - + self._morning[gid]["group_count"]["weekly"]["sleeping_king"] = _sleeping_king_uid - + self._save_data() logger.info("每周睡眠时间、每周早安已刷新!") @@ -669,7 +698,7 @@ def daily_scheduler(self, oclock: Optional[int] = None) -> None: _oclock = oclock else: _oclock = self.get_refresh_time("night", "early_time") - + if _oclock != -1: scheduler.add_job( self.group_daily_refresh, @@ -680,16 +709,17 @@ def daily_scheduler(self, oclock: Optional[int] = None) -> None: minute=0, misfire_grace_time=60 ) - + def weekly_night_scheduler(self) -> None: ''' Run the schedulers for refreshing the weekly good-night time. Replace the existing schedulers. ''' oclock: int = self.get_refresh_time("night", "late_time") _night_early_oclock: int = self.get_refresh_time("night", "early_time") - + if oclock != -1: - day_of_week: str = "0" if oclock < _night_early_oclock else "6" # From Monday to Sunday: 0~6 + # From Monday to Sunday: 0~6 + day_of_week: str = "0" if oclock < _night_early_oclock else "6" scheduler.add_job( func=self.weekly_night_refresh, trigger="cron", @@ -700,7 +730,7 @@ def weekly_night_scheduler(self) -> None: day_of_week=day_of_week, misfire_grace_time=60 ) - + def weekly_sleep_time_scheduler(self, oclock: Optional[int] = None) -> None: ''' Run the scheduler for refreshing the weekly sleeping time. Replace the existing scheduler. @@ -709,7 +739,7 @@ def weekly_sleep_time_scheduler(self, oclock: Optional[int] = None) -> None: _oclock = oclock else: _oclock = self.get_refresh_time("morning", "late_time") - + if _oclock != -1: scheduler.add_job( self.weekly_sleep_time_refresh, @@ -722,4 +752,5 @@ def weekly_sleep_time_scheduler(self, oclock: Optional[int] = None) -> None: misfire_grace_time=60 ) -morning_manager = MorningManager() \ No newline at end of file + +morning_manager = MorningManager() diff --git a/nonebot_plugin_morning/utils.py b/nonebot_plugin_morning/utils.py index b6da323..99e2bbc 100644 --- a/nonebot_plugin_morning/utils.py +++ b/nonebot_plugin_morning/utils.py @@ -1,6 +1,9 @@ from datetime import datetime, timedelta, date from typing import Union, Tuple, List, Dict -import json +try: + import ujson as json +except ModuleNotFoundError: + import json mor_switcher: Dict[str, str] = { "时限": "morning_intime", diff --git a/pyproject.toml b/pyproject.toml index c9cc1bb..2ad6f32 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "nonebot-plugin-morning" -version = "0.3.2a1" +version = "0.3.2a2" description = "Good morning & good night!" authors = ["KafCoppelia "] license = "MIT"