diff --git a/docs/deployment/config.md b/docs/deployment/config.md index 6ab3ceb5..53c04a38 100644 --- a/docs/deployment/config.md +++ b/docs/deployment/config.md @@ -21,12 +21,13 @@ nickname: [ "liteyuki" ] # 机器人昵称 superusers: [ "1919810" ] # 超级用户 # 未列出的配置项(如要自定义请手动修改) -onebot_access_token: "" # 访问令牌,对公网开放时建议设置 -default_language: "zh-CN" # 默认语言,支持i18n部分语言和自行扩展的语言代码 +onebot_access_token: "" # 访问令牌,对公开放时建议设置 +default_language: "zh-CN" # 默认语言 log_level: "INFO" # 日志等级 log_icon: true # 是否显示日志等级图标(某些控制台字体不可用) -auto_report: true # 是否自动上报问题给轻雪服务器,仅包含硬件信息和运行软件版本 -fake_device_info: # 统计卡片显示的虚假设备信息,用于保护隐私 +auto_report: true # 是否自动上报问题给轻雪服务器 +auto_update: true # 是否自动更新轻雪,每天4点检查更新 +fake_device_info: # 用于保护设备隐私 cpu: brand: AMD cores: 16 # 物理核心数 diff --git a/liteyuki/liteyuki_main/api.py b/liteyuki/liteyuki_main/api.py new file mode 100644 index 00000000..f208e560 --- /dev/null +++ b/liteyuki/liteyuki_main/api.py @@ -0,0 +1,67 @@ +import nonebot +from git import Repo + +remote_urls = [ + "https://github.com/snowykami/LiteyukiBot.git", + "https://gitee.com/snowykami/LiteyukiBot.git" +] + + +def detect_update() -> bool: + # 对每个远程仓库进行检查,只要有一个仓库有更新,就返回True + for remote_url in remote_urls: + repo = Repo(".") + repo.remotes.origin.set_url(remote_url) + repo.remotes.origin.fetch() + if repo.head.commit != repo.commit('origin/main'): + return True + + +def update_liteyuki() -> tuple[bool, str]: + """更新轻雪 + :return: 是否更新成功,更新变动""" + # origins = ["origin", "origin2"] + # repo = Repo(".") + # + # # Get the current HEAD commit + # current_head_commit = repo.head.commit + # + # # Fetch the latest information from the cloud + # repo.remotes.origin.fetch() + # + # # Get the latest HEAD commit + # new_head_commit = repo.commit('origin/main') + # + # # If the new HEAD commit is different from the current HEAD commit, there is a new commit + # diffs = current_head_commit.diff(new_head_commit) + # logs = "" + # for diff in diffs.iter_change_type('M'): + # logs += f"\n{diff.a_path}" + # + # for origin in origins: + # try: + # repo.remotes[origin].pull() + # break + # except Exception as e: + # nonebot.logger.error(f"Pull from {origin} failed: {e}") + # continue + # else: + # return False, 0 + # + # return True, len(logs) + new_commit_detected = detect_update() + if new_commit_detected: + repo = Repo(".") + logs = "" + # 对每个远程仓库进行更新 + for remote_url in remote_urls: + repo.remotes.origin.set_url(remote_url) + repo.remotes.origin.pull() + diffs = repo.head.commit.diff("origin/main") + + for diff in diffs.iter_change_type('M'): + logs += f"\n{diff.a_path}" + return True, logs + else: + return False, "Nothing Changed" + diff --git a/liteyuki/liteyuki_main/core.py b/liteyuki/liteyuki_main/core.py index 32ad7839..c6758311 100644 --- a/liteyuki/liteyuki_main/core.py +++ b/liteyuki/liteyuki_main/core.py @@ -1,25 +1,25 @@ -import asyncio import base64 import time from typing import Any import nonebot import pip -from git import Repo from nonebot import Bot, get_driver, require from nonebot.exception import MockApiException from nonebot.internal.matcher import Matcher from nonebot.permission import SUPERUSER -from liteyuki.utils.config import load_from_yaml +from liteyuki.utils.config import get_config, load_from_yaml from liteyuki.utils.data_manager import StoredConfig, TempConfig, common_db from liteyuki.utils.language import get_user_lang from liteyuki.utils.ly_typing import T_Bot, T_MessageEvent from liteyuki.utils.message import Markdown as md from liteyuki.utils.reloader import Reloader +from .api import update_liteyuki -require("nonebot_plugin_alconna"), require("nonebot_plugin_htmlrender") +require("nonebot_plugin_alconna"), require("nonebot_plugin_apscheduler") from nonebot_plugin_alconna import on_alconna, Alconna, Args, Subcommand, Arparma +from nonebot_plugin_apscheduler import scheduler driver = get_driver() @@ -46,30 +46,7 @@ async def _(bot: T_Bot, matcher: Matcher): async def _(bot: T_Bot, event: T_MessageEvent): # 使用git pull更新 ulang = get_user_lang(str(event.user_id)) - origins = ["origin", "origin2"] - repo = Repo(".") - - # Get the current HEAD commit - current_head_commit = repo.head.commit - - # Fetch the latest information from the cloud - repo.remotes.origin.fetch() - - # Get the latest HEAD commit - new_head_commit = repo.commit('origin/main') - - # If the new HEAD commit is different from the current HEAD commit, there is a new commit - diffs = current_head_commit.diff(new_head_commit) - logs = "" - for diff in diffs.iter_change_type('M'): - logs += f"\n{diff.a_path}" - - for origin in origins: - try: - repo.remotes[origin].pull() - break - except Exception as e: - nonebot.logger.error(f"Pull from {origin} failed: {e}") + success, logs = update_liteyuki() reply = "Liteyuki updated!\n" reply += f"```\n{logs}\n```\n" btn_restart = md.btn_cmd(ulang.get("liteyuki.restart_now"), "reload-liteyuki") @@ -173,7 +150,7 @@ async def _(event: T_MessageEvent, matcher: Matcher): aliases={"轻雪文档"}, ).handle() async def _(matcher: Matcher): - matcher.finish("https://bot.liteyuki.icu/usage") + await matcher.finish("https://bot.liteyuki.icu/usage") # system hook @@ -240,3 +217,15 @@ async def _(bot: T_Bot): group_id=reload_session_id, message="Liteyuki reloaded in %.2f s" % delta_time ) + + +# 每天4点更新 +@scheduler.scheduled_job("cron", hour=4) +async def every_day_update(): + if get_config("auto_update", True): + result, logs = update_liteyuki() + if result: + nonebot.logger.info(f"Liteyuki updated: {logs}") + Reloader.reload(1) + else: + nonebot.logger.info(logs) \ No newline at end of file diff --git a/liteyuki/resources/templates/css/status.css b/liteyuki/resources/templates/css/status.css new file mode 100644 index 00000000..e69de29b diff --git a/liteyuki/resources/templates/status.html b/liteyuki/resources/templates/status.html index 0e88f158..b819ce3f 100644 --- a/liteyuki/resources/templates/status.html +++ b/liteyuki/resources/templates/status.html @@ -7,7 +7,7 @@