From 1827ac84c018a6f57f94d8d21a1a93c27f96260c Mon Sep 17 00:00:00 2001 From: UPToZ Date: Sun, 1 Jun 2025 14:42:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20iKuuu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iKuuu/README.md | 53 +++++++++++ iKuuu/ik_signin.py | 216 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) create mode 100644 iKuuu/README.md create mode 100644 iKuuu/ik_signin.py diff --git a/iKuuu/README.md b/iKuuu/README.md new file mode 100644 index 0000000..feae271 --- /dev/null +++ b/iKuuu/README.md @@ -0,0 +1,53 @@ +# iKuuu 青龙面板签到脚本 + +## 脚本说明 + +此脚本用于青龙面板自动签到iKuuu网站,支持多账号配置、域名自动更新和通知功能。 + +### 功能特性 + +- 自动检测并更新iKuuu官方域名 +- 支持多账号批量签到 +- 签到结果通过青龙面板通知系统推送 +- 域名不可用时自动切换备用域名 +- 完整的异常处理和日志记录 + +## 安装步骤 + +1. 将脚本保存为`ik_signin.py`到青龙面板的`scripts`目录 +2. 添加环境变量`IKUUU_ACCOUNTS`,格式为: +``` +邮箱1:密码1 +邮箱2:密码2 +``` +3. 在青龙面板添加定时任务: +``` +task ik_signin 0 0 1 * * ? +``` + +## 环境变量配置 + +| 变量名 | 说明 | 示例 | +| ---- | ---- | ---- | +| IKUUU_ACCOUNTS | iKuuu账号密码,每行一个账号,格式为`邮箱:密码` | `test@example.com:password123` | + +## 使用说明 + +1. 脚本会自动检测当前域名是否可用 +2. 若检测到域名变更,会自动更新脚本中的域名信息 +3. 依次对配置的所有账号进行签到操作 +4. 签到结果会通过青龙面板的通知系统发送 + +## 更新日志 + +### 2025-05-31 +- 初始版本发布 +- 实现基本签到功能 +- 添加域名自动检测和更新机制 +- 支持多账号配置和结果通知 + +## 注意事项 + +- 请确保青龙面板已配置通知功能,否则无法接收签到结果通知 +- 脚本运行需要网络连接畅通,否则可能导致签到失败 +- 若官方域名发生变更,脚本会自动更新,但可能需要手动触发一次以完成更新 \ No newline at end of file diff --git a/iKuuu/ik_signin.py b/iKuuu/ik_signin.py new file mode 100644 index 0000000..8f73e26 --- /dev/null +++ b/iKuuu/ik_signin.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -* +''' +定时自定义 +0 0 1 * * ? iKuuu.py +new Env('iKuuu签到'); +''' +import requests +import re +import json +import os +import datetime +import urllib.parse +import sys +import os + +# 添加青龙脚本根目录到Python路径 +QL_SCRIPTS_DIR = '/ql/scripts' # 青龙脚本默认目录 +sys.path.append(QL_SCRIPTS_DIR) + +# 添加notify可能存在的其他路径 +POSSIBLE_PATHS = [ + '/ql', # 青龙根目录 + '/ql/data/scripts', # 新版青龙数据目录 + '/ql/scripts/notify', # 自定义通知目录 + os.path.dirname(__file__) # 当前脚本目录 +] + +for path in POSSIBLE_PATHS: + if os.path.exists(os.path.join(path, 'notify.py')): + sys.path.append(path) + break + +try: + from notify import send +except ImportError: + print("⚠️ 无法加载通知模块,请检查路径配置") + send = lambda title, content: None # 创建空函数防止报错 + +# 初始域名 +ikun_host = "ikuuu.one" # 自动更新于2025-04-29 13:08:20 +backup_hosts = ["ikuuu.one", "ikuuu.pw", "ikuuu.me"] # 备用域名列表 + +def get_latest_ikun_host(): + test_url = f"https://{ikun_host}/" + try: + response = requests.get(test_url, timeout=10) + if response.status_code == 200: + if "官网域名已更改" in response.text or "Domain deprecated" in response.text: + print("检测到域名变更通知,正在提取新域名...") + h2_matches = re.findall(r'

.*?(?:域名|domain)[::]\s*([a-zA-Z0-9.-]+)

', response.text) + if h2_matches: + return h2_matches[0] + js_matches = re.findall(r'https?://([a-zA-Z0-9.-]+)/auth/login', response.text) + if js_matches: + return js_matches[0] + fallback_match = re.search(r'(?:域名|domain)[::]\s*([a-zA-Z0-9.-]+)', response.text) + if fallback_match: + return fallback_match.group(1) + print("⚠️ 检测到域名变更但无法提取新域名") + return None + else: + print("✅ 当前域名正常") + return None + except Exception as e: + print(f"域名检测异常: {e}") + return None + +def update_self_host(new_host): + script_path = os.path.abspath(__file__) + with open(script_path, "r", encoding="utf-8") as f: + lines = f.readlines() + updated = False + for i, line in enumerate(lines): + if line.strip().startswith("ikun_host = "): + lines[i] = f'ikun_host = "{new_host}" # 自动更新于{datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}\n' + updated = True + break + if updated: + with open(script_path, "w", encoding="utf-8") as f: + f.writelines(lines) + print(f"✅ 脚本已更新至域名: {new_host}") + return True + else: + print("⚠️ 域名更新失败") + return False + +def test_host_reachable(host): + try: + response = requests.get(f"https://{host}/", timeout=10) + return response.status_code == 200 + except: + return False + +def ikuuu_signin(email, password): + params = {'email': email, 'passwd': password, 'code': ''} + login_url = f'https://{ikun_host}/auth/login' + try: + # 登录请求 + login_res = requests.post(login_url, data=params, timeout=15) + if login_res.status_code != 200: + return False, f"登录失败(状态码{login_res.status_code})" + + login_data = login_res.json() + if login_data.get('ret') != 1: + return False, f"登录失败:{login_data.get('msg', '未知错误')}" + + # 执行签到 + cookies = login_res.cookies + checkin_res = requests.post(f'https://{ikun_host}/user/checkin', cookies=cookies, timeout=15) + if checkin_res.status_code != 200: + return False, f"签到失败(状态码{checkin_res.status_code})" + + checkin_data = checkin_res.json() + if checkin_data.get('ret') == 1: + return True, f"成功 | {checkin_data.get('msg', '')}" + else: + return False, f"签到失败:{checkin_data.get('msg', '未知错误')}" + except json.JSONDecodeError: + return False, "响应解析失败" + except requests.exceptions.Timeout: + return False, "请求超时" + except Exception as e: + return False, f"请求异常:{str(e)}" + +def send_qinglong_notification(results): + """ + 使用青龙面板内置通知模块发送通知 + 需要青龙面板已配置config.sh内的通知渠道(如钉钉、企业微信等) + """ + title = "iKuuu签到通知" + + # 构建消息内容 + success_count = sum(1 for res in results if res['success']) + failure_count = len(results) - success_count + + message = [ + f"🔔 签到完成 | 成功:{success_count} 失败:{failure_count}", + "================================" + ] + + for index, res in enumerate(results, 1): + status = "✅ 成功" if res['success'] else "❌ 失败" + message.append(f"{index}. {res['email']}") + message.append(f" 状态:{status}") + message.append(f" 详情:{res['message']}") + message.append("--------------------------------") + + # 添加统计信息 + message.append("\n🕒 执行时间:" + datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) + + try: + # 发送通知(青龙自动处理多通知渠道) + send(title, "\n".join(message)) + print("✅ 通知已发送") + except Exception as e: + print(f"⚠️ 通知发送失败,请检查通知配置: {str(e)}") + +if __name__ == "__main__": + # ==================== 域名更新逻辑 ==================== + print(f"当前域名: {ikun_host}") + latest_host = get_latest_ikun_host() + if latest_host: + print(f"检测到新域名: {latest_host}") + if update_self_host(latest_host): + ikun_host = latest_host + + # ==================== 域名可用性检查 ==================== + if not test_host_reachable(ikun_host): + print("主域名不可用,尝试备用域名...") + found = False + for host in backup_hosts: + if test_host_reachable(host): + ikun_host = host + print(f"切换到备用域名: {ikun_host}") + found = True + break + if not found: + print("❌ 所有域名均不可用") + exit(1) + + # ==================== 账户处理 ==================== + accounts = [] + account_str = os.getenv('IKUUU_ACCOUNTS') + if not account_str: + print("❌ 未找到环境变量 IKUUU_ACCOUNTS") + exit(1) + + for line in account_str.strip().splitlines(): + if ':' in line: + email, pwd = line.split(':', 1) + accounts.append((email.strip(), pwd.strip())) + else: + print(f"⚠️ 忽略无效账户行: {line}") + + if not accounts: + print("❌ 未找到有效账户") + exit(1) + + # ==================== 执行签到 ==================== + results = [] + for email, pwd in accounts: + print(f"\n处理账户: {email}") + success, msg = ikuuu_signin(email, pwd) + results.append({'email': email, 'success': success, 'message': msg}) + print(f"结果: {'成功' if success else '失败'} - {msg}") + + # ==================== 结果通知 ==================== + print("\n正在发送通知...") + send_qinglong_notification(results) + + # ==================== 本地结果输出 ==================== + print("\n签到结果汇总:") + for res in results: + print(f"邮箱: {res['email']}") + print(f"状态: {'成功' if res['success'] else '失败'}") + print(f"详情: {res['message']}\n{'-'*40}") \ No newline at end of file