From 0194c93783fde305b589ed5b64dfd297da8bea62 Mon Sep 17 00:00:00 2001 From: Boom <654612@qq.com> Date: Mon, 10 Nov 2025 17:03:54 +0800 Subject: [PATCH] init --- Dockerfile | 32 ++++++++ README.md | 0 build.bat | 2 + firmware_checker.py | 171 ++++++++++++++++++++++++++++++++++++++++++ firmware_versions.txt | 2 + requirements.txt | 1 + 6 files changed, 208 insertions(+) create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 build.bat create mode 100644 firmware_checker.py create mode 100644 firmware_versions.txt create mode 100644 requirements.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f5c10fe --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +# 使用Python官方镜像作为基础镜像 +FROM docker.1ms.run/library/python:3.11-slim + +# 设置工作目录 +WORKDIR /app + +# 设置环境变量 +# 默认检查间隔为30分钟(可被运行时环境变量覆盖) +ENV CHECK_INTERVAL_MINUTES=30 +# 企业微信webhook地址(可被运行时环境变量覆盖) +ENV WECHAT_WEBHOOK_URL='https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4226c76e-725b-4990-b926-05f16142e513' +# 设置Python日志输出环境变量,确保日志不缓冲 +ENV PYTHONUNBUFFERED=1 +ENV PYTHONIOENCODING=utf-8 + +# 安装依赖 +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# 复制脚本文件 +COPY firmware_checker.py . +COPY firmware_versions.txt . + +# 创建卷,以便可以持久化和修改versions.txt文件 +VOLUME ["/app"] + +# 添加健康检查(可选) +HEALTHCHECK --interval=60s --timeout=10s --start-period=5s --retries=3 \ + CMD python -c "import os; import sys; sys.exit(0 if os.path.exists('/app/firmware_checker.py') else 1)" || exit 1 + +# 设置容器启动时执行的命令 +CMD ["python", "firmware_checker.py"] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..276978e --- /dev/null +++ b/build.bat @@ -0,0 +1,2 @@ +docker build -t registry.cn-beijing.aliyuncs.com/zyh5/firmware-checker . +docker push registry.cn-beijing.aliyuncs.com/zyh5/firmware-checker:latest \ No newline at end of file diff --git a/firmware_checker.py b/firmware_checker.py new file mode 100644 index 0000000..a9177db --- /dev/null +++ b/firmware_checker.py @@ -0,0 +1,171 @@ +import requests +import os +import json +import re +import time +import sys +import logging + +# 配置日志系统 +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(message)s', + handlers=[ + logging.StreamHandler(sys.stdout) + ] +) +logger = logging.getLogger(__name__) + +# 确保日志输出不缓冲 +for handler in logging.getLogger().handlers: + handler.flush = sys.stdout.flush + +def get_firmware_list(): + """访问API获取固件列表""" + url = 'https://app4.i4.cn/getFirmwareList.xhtml?model=iPhone+13+Pro+Max&fs=2&seltype=1&ios=' + try: + response = requests.get(url, timeout=10) + response.raise_for_status() # 检查请求是否成功 + return response.json() + except Exception as e: + logger.error(f"获取固件列表失败: {e}") + return None + +def extract_versions_from_api(data): + """从API返回的数据中提取版本号""" + versions = [] + if data and data.get('success') and 'list' in data: + for item in data['list']: + if 'version' in item: + # 提取主要版本号(如26.1,忽略beta等后缀) + version = item['version'] + main_version_match = re.match(r'(\d+\.\d+)', version) + if main_version_match: + main_version = main_version_match.group(1) + versions.append(main_version) + return versions + +def get_local_versions(): + """直接读取firmware_versions.txt文件中的版本号""" + local_versions = [] + file_path = os.path.join(os.getcwd(), 'firmware_versions.txt') + + if not os.path.exists(file_path): + logger.warning(f"版本文件不存在: {file_path}") + return local_versions + + try: + with open(file_path, 'r', encoding='utf-8') as f: + for line in f: + line = line.strip() + if line: + # 提取行中的版本号格式 + version_match = re.match(r'(\d+\.\d+)', line) + if version_match: + main_version = version_match.group(1) + local_versions.append(main_version) + else: + # 如果整行不是版本号格式,也添加到列表中 + local_versions.append(line) + except Exception as e: + logger.error(f"读取版本文件失败: {e}") + + return local_versions + +def send_wechat_message(message): + """通过企业微信webhook发送消息""" + # 从环境变量获取webhook_url,如果没有则使用默认值 + webhook_url = os.environ.get( + 'WECHAT_WEBHOOK_URL', + 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4226c76e-725b-4990-b926-05f16142e513' + ) + headers = {'Content-Type': 'application/json'} + + # 企业微信机器人消息格式 + payload = { + "msgtype": "text", + "text": { + "content": message + } + } + + try: + response = requests.post(webhook_url, headers=headers, data=json.dumps(payload), timeout=10) + response.raise_for_status() + result = response.json() + if result.get('errcode') != 0: + logger.error(f"发送企业微信消息失败: {result.get('errmsg')}") + except Exception as e: + logger.error(f"发送企业微信消息失败: {e}") + +def check_versions(): + """检查并比较版本号""" + # 获取API返回的版本号 + api_data = get_firmware_list() + if not api_data: + return + + api_versions = extract_versions_from_api(api_data) + api_versions_set = set(api_versions) + + # 获取本地txt文件中的版本号 + local_versions = get_local_versions() + if not local_versions: + # 如果没有本地版本,创建一个示例txt文件 + create_example_txt() + return + + # 找出不在本地的版本号 + new_versions = [] + for api_version in api_versions_set: + if api_version not in local_versions: + new_versions.append(api_version) + + if new_versions: + logger.info(f"发现新固件版本: {', '.join(new_versions)}") + # 构建消息内容并发送到企业微信 + message = f"✅ 固件版本检查完成\n发现新的验证版本:\n" + "\n".join([f" - {v}" for v in new_versions]) + send_wechat_message(message) + else: + logger.info("所有固件版本已是最新") + +def create_example_txt(): + """创建示例txt文件""" + example_path = os.path.join(os.getcwd(), 'firmware_versions.txt') + try: + with open(example_path, 'w', encoding='utf-8') as f: + f.write("26.1\n") + logger.info(f"已创建版本文件: {example_path}") + except Exception as e: + logger.error(f"创建版本文件失败: {e}") + +def main(): + """主函数,支持定时执行""" + # 从环境变量读取执行间隔,默认30分钟 + interval_env = os.environ.get('CHECK_INTERVAL_MINUTES') + try: + interval_minutes = int(interval_env) if interval_env else 30 + except ValueError: + logger.warning(f"检查间隔参数无效,使用默认值30分钟") + interval_minutes = 30 + + interval_seconds = interval_minutes * 60 + logger.info(f"固件版本检查服务启动,间隔: {interval_minutes}分钟,当前时间: {time.strftime('%Y-%m-%d %H:%M:%S')}") + + # 首次立即执行一次 + check_versions() + + # 然后定时执行 + try: + while True: + logger.info(f"等待下次检查,{interval_minutes}分钟后...") + time.sleep(interval_seconds) + check_versions() + except KeyboardInterrupt: + logger.info("服务已停止") + except Exception as e: + logger.error(f"服务运行出错: {e}") + sys.exit(1) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/firmware_versions.txt b/firmware_versions.txt new file mode 100644 index 0000000..e942385 --- /dev/null +++ b/firmware_versions.txt @@ -0,0 +1,2 @@ +26.1 +26.0 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6f89372 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +requests>=2.32.0 \ No newline at end of file