Compare commits

...

5 Commits

Author SHA1 Message Date
c94db33b11 更新 ptimeparse 到 0.2.0
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-10-19 22:45:34 +08:00
67382a0c0a 在我写的模块采用更安全的 asyncio 锁写法
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2025-10-19 20:27:18 +08:00
fd4c9302c2 async with lock
All checks were successful
continuous-integration/drone/push Build is passing
2025-10-19 20:24:47 +08:00
f30ad0cb7d 判定部分优化
All checks were successful
continuous-integration/drone/push Build is passing
2025-10-19 18:48:10 +08:00
f7afe48680 精度修复
All checks were successful
continuous-integration/drone/push Build is passing
2025-10-19 18:36:27 +08:00
5 changed files with 80 additions and 69 deletions

View File

@ -254,11 +254,10 @@ def _save_longtask_data(data: LongTaskModuleData):
@asynccontextmanager
async def longtask_data():
await longtask_lock.acquire()
data = _load_longtask_data()
yield data
_save_longtask_data(data)
longtask_lock.release()
async with longtask_lock:
data = _load_longtask_data()
yield data
_save_longtask_data(data)
async def create_longtask(

View File

@ -157,24 +157,24 @@ class IdiomGame:
"""
跳过当前成语,选择下一个成语
"""
await self.lock.acquire()
self._skip_idiom_async(buff_score)
self.lock.release()
async with self.lock:
self._skip_idiom_async()
self.add_buff_score(buff_score)
return self.last_idiom
def _skip_idiom_async(self, buff_score: int = -100) -> str:
def _skip_idiom_async(self) -> str:
self.last_idiom = secrets.choice(IdiomGame.ALL_IDIOMS)
self.last_char = self.last_idiom[-1]
self.add_buff_score(buff_score)
if not self.is_nextable(self.last_char):
self._skip_idiom_async()
return self.last_idiom
async def try_verify_idiom(self, idiom: str, user_id: str) -> TryVerifyState:
"""
用户发送成语
"""
await self.lock.acquire()
state = self._verify_idiom(idiom, user_id)
self.lock.release()
async with self.lock:
state = self._verify_idiom(idiom, user_id)
return state
def is_nextable(self, last_char: str) -> bool:
@ -203,10 +203,12 @@ class IdiomGame:
return TryVerifyState.VERIFIED_BUT_NO_NEXT
return TryVerifyState.VERIFIED
def get_user_score(self, user_id: str) -> int:
def get_user_score(self, user_id: str) -> float:
if user_id not in self.score_board:
return 0
return self.score_board[user_id]["score"]
# 避免浮点数精度问题导致过长
handled_score = round(self.score_board[user_id]["score"], 1)
return handled_score
def add_score(self, user_id: str, score: int):
if user_id not in self.score_board:
@ -377,7 +379,7 @@ async def end_game(event: BaseEvent, group_id: str):
result_text += (
f"{i + 1}. "
+ UniMessage().at(user_id)
+ f": {info['score'] + instance.get_all_buff_score()}\n"
+ f": {round(info['score'] + instance.get_all_buff_score(), 1)}\n"
)
await evt.send(await result_text.export())
instance.clear_score_board()

View File

@ -15,10 +15,10 @@ from nonebot.adapters.console.event import MessageEvent as ConsoleMessageEvent
from nonebot.adapters.discord import Bot as DiscordBot
from nonebot.adapters.discord.event import MessageEvent as DiscordMessageEvent
from nonebot.adapters.onebot.v11 import Bot as OnebotV11Bot
from nonebot.adapters.onebot.v11.event import \
GroupMessageEvent as OnebotV11GroupMessageEvent
from nonebot.adapters.onebot.v11.event import \
MessageEvent as OnebotV11MessageEvent
from nonebot.adapters.onebot.v11.event import (
GroupMessageEvent as OnebotV11GroupMessageEvent,
)
from nonebot.adapters.onebot.v11.event import MessageEvent as OnebotV11MessageEvent
from nonebot_plugin_alconna import UniMessage, UniMsg
from pydantic import BaseModel
@ -68,14 +68,14 @@ def save_notify_config(config: NotifyConfigFile):
async def notify_now(notify: Notify):
if notify.platform == 'console':
if notify.platform == "console":
bot = [b for b in nonebot.get_bots().values() if isinstance(b, ConsoleBot)]
if len(bot) != 1:
logger.warning(f"提醒未成功发送出去:{nonebot.get_bots()} {notify}")
return False
bot = bot[0]
await bot.send_private_message(notify.target, f"代办通知:{notify.notify_msg}")
elif notify.platform == 'discord':
elif notify.platform == "discord":
bot = [b for b in nonebot.get_bots().values() if isinstance(b, DiscordBot)]
if len(bot) != 1:
logger.warning(f"提醒未成功发送出去:{nonebot.get_bots()} {notify}")
@ -83,7 +83,7 @@ async def notify_now(notify: Notify):
bot = bot[0]
channel = await bot.create_DM(recipient_id=int(notify.target))
await bot.send_to(channel.id, f"代办通知:{notify.notify_msg}")
elif notify.platform == 'qq':
elif notify.platform == "qq":
bot = [b for b in nonebot.get_bots().values() if isinstance(b, OnebotV11Bot)]
if len(bot) != 1:
logger.warning(f"提醒未成功发送出去:{nonebot.get_bots()} {notify}")
@ -92,17 +92,22 @@ async def notify_now(notify: Notify):
if notify.target_env is None:
await bot.send_private_msg(
user_id=int(notify.target),
message=cast(Any, await UniMessage.text(f"代办通知:{notify.notify_msg}").export(
bot=bot,
)),
message=cast(
Any,
await UniMessage.text(f"代办通知:{notify.notify_msg}").export(
bot=bot,
),
),
)
else:
await bot.send_group_msg(
group_id=int(notify.target_env),
message=cast(Any,
await UniMessage().at(
notify.target
).text(f" 代办通知:{notify.notify_msg}").export(bot=bot)
message=cast(
Any,
await UniMessage()
.at(notify.target)
.text(f" 代办通知:{notify.notify_msg}")
.export(bot=bot),
),
)
else:
@ -127,15 +132,17 @@ def create_notify_task(notify: Notify, fail2remove: bool = True):
)
res = await notify_now(notify)
if fail2remove or res:
await DATA_FILE_LOCK.acquire()
cfg = load_notify_config()
cfg.notifies = [n for n in cfg.notifies if n.get_str() != notify.get_str()]
if not res:
cfg.unsent.append(notify)
save_notify_config(cfg)
DATA_FILE_LOCK.release()
async with DATA_FILE_LOCK:
cfg = load_notify_config()
cfg.notifies = [
n for n in cfg.notifies if n.get_str() != notify.get_str()
]
if not res:
cfg.unsent.append(notify)
save_notify_config(cfg)
else:
pass
return asynkio.create_task(mission())
@ -155,7 +162,8 @@ async def _(msg: UniMsg, mEvt: Event):
notify_time, notify_text = segments
# target_time = get_target_time(notify_time)
try:
target_time = ptimeparse.parse(notify_time)
# target_time = ptimeparse.parse(notify_time)
target_time = ptimeparse.Parser().parse(notify_time)
logger.info(f"{notify_time} 解析出了时间:{target_time}")
except Exception:
logger.info(f"无法从 {notify_time} 中解析出时间")
@ -201,8 +209,12 @@ async def _(msg: UniMsg, mEvt: Event):
save_notify_config(cfg)
DATA_FILE_LOCK.release()
await evt.send(await UniMessage().at(mEvt.get_user_id()).text(
f" 了解啦!将会在 {notify.notify_time} 提醒你哦~").export())
await evt.send(
await UniMessage()
.at(mEvt.get_user_id())
.text(f" 了解啦!将会在 {notify.notify_time} 提醒你哦~")
.export()
)
logger.info(f"创建了一条于 {notify.notify_time} 的代办提醒")
@ -253,8 +265,8 @@ async def _():
logger.info("所有的代办提醒 Task 都已经退出了")
for sig in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(sig, functools.partial(
asynkio.create_task, shutdown(sig)
))
loop.add_signal_handler(
sig, functools.partial(asynkio.create_task, shutdown(sig))
)
await asynkio.gather(*ASYNK_TASKS)

8
poetry.lock generated
View File

@ -2402,14 +2402,14 @@ reference = "mirrors"
[[package]]
name = "ptimeparse"
version = "0.1.2"
version = "0.2.0"
description = "一个用于解析中文的时间表达的库"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
{file = "ptimeparse-0.1.2-py3-none-any.whl", hash = "sha256:0eea791396e53b63330fadb40d9f0a2e6272bd5467246f10d1d6971bc606edff"},
{file = "ptimeparse-0.1.2.tar.gz", hash = "sha256:658be90a3cc2994c09c4ea2f276d257e7eb84bc330be79950baefe32b19779a2"},
{file = "ptimeparse-0.2.0-py3-none-any.whl", hash = "sha256:57055f8fd99fb69e19deac3b8a5c7ac91af86c7ac09781632e9abf318df0d6d2"},
{file = "ptimeparse-0.2.0.tar.gz", hash = "sha256:867c265f2e157fe4d793d20fe9c449b8ede5c855f336d7e6b2eb78551e622766"},
]
[package.source]
@ -3807,4 +3807,4 @@ reference = "mirrors"
[metadata]
lock-version = "2.1"
python-versions = ">=3.12,<4.0"
content-hash = "d6a325b769fb3ed207c1a8891e65ea20bae20166fa281d6fa620faf54ad15bd8"
content-hash = "02530953efe65da1a788845cd43f8856be62db5bfb59de691cad813f57bab25e"

View File

@ -2,30 +2,28 @@
name = "konabot"
version = "0.1.0"
description = "在 MTTU 内部使用的 bot"
authors = [
{name = "passthem",email = "Passthem183@gmail.com"}
]
authors = [{ name = "passthem", email = "Passthem183@gmail.com" }]
readme = "README.md"
requires-python = ">=3.12,<4.0"
dependencies = [
"nonebot2[all] (>=2.4.3,<3.0.0)",
"nonebot-adapter-onebot (>=2.4.6,<3.0.0)",
"nonebot-adapter-console (>=0.9.0,<0.10.0)",
"nonebot-adapter-discord (>=0.1.8,<0.2.0)",
"nonebot-adapter-minecraft (>=1.5.2,<2.0.0)",
"nonebot-plugin-alconna (>=0.59.4,<0.60.0)",
"nonebot-plugin-apscheduler (>=0.5.0,<0.6.0)",
"requests (>=2.32.5,<3.0.0)",
"beautifulsoup4 (>=4.13.5,<5.0.0)",
"lxml (>=6.0.2,<7.0.0)",
"pillow (>=11.3.0,<12.0.0)",
"imagetext-py (>=2.2.0,<3.0.0)",
"opencv-python-headless (>=4.12.0.88,<5.0.0.0)",
"returns (>=0.26.0,<0.27.0)",
"ptimeparse (>=0.1.1,<0.2.0)",
"skia-python (>=138.0,<139.0)",
"nonebot-plugin-analysis-bilibili (>=2.8.1,<3.0.0)",
"qrcode (>=8.2,<9.0)",
"nonebot2[all] (>=2.4.3,<3.0.0)",
"nonebot-adapter-onebot (>=2.4.6,<3.0.0)",
"nonebot-adapter-console (>=0.9.0,<0.10.0)",
"nonebot-adapter-discord (>=0.1.8,<0.2.0)",
"nonebot-adapter-minecraft (>=1.5.2,<2.0.0)",
"nonebot-plugin-alconna (>=0.59.4,<0.60.0)",
"nonebot-plugin-apscheduler (>=0.5.0,<0.6.0)",
"requests (>=2.32.5,<3.0.0)",
"beautifulsoup4 (>=4.13.5,<5.0.0)",
"lxml (>=6.0.2,<7.0.0)",
"pillow (>=11.3.0,<12.0.0)",
"imagetext-py (>=2.2.0,<3.0.0)",
"opencv-python-headless (>=4.12.0.88,<5.0.0.0)",
"returns (>=0.26.0,<0.27.0)",
"ptimeparse (>=0.1.1,<1.0.0)",
"skia-python (>=138.0,<139.0)",
"nonebot-plugin-analysis-bilibili (>=2.8.1,<3.0.0)",
"qrcode (>=8.2,<9.0)",
]
[build-system]
@ -43,4 +41,4 @@ url = "https://pypi.tuna.tsinghua.edu.cn/simple/"
priority = "primary"
[tool.poetry.dependencies]
ptimeparse = {source = "pt-gitea-pypi"}
ptimeparse = { source = "pt-gitea-pypi" }