Collect authenticated Qinglong scripts batch

This commit is contained in:
Hermes Agent
2026-05-24 03:53:42 +00:00
parent 0d80b33d25
commit 28d62fef03
86 changed files with 18420 additions and 5 deletions

View File

@@ -0,0 +1,26 @@
# Source: https://github.com/back-101/zyqinglong/blob/main/AiPm.py
# Raw: https://raw.githubusercontent.com/back-101/zyqinglong/main/AiPm.py
# Repo: back-101/zyqinglong
# Path: AiPm.py
# UploadedAt: 2026-03-13T04:15:05Z
# SHA256: 125ff6e463e1279559086f8786cc3a4987223ac41d2923be61bb587ea8e17e5f
# Category: APP版/抓包
# Evidence: cookie/token/authorization/header
# -*- coding=UTF-8 -*-
# @Project QL_TimingScript
# @fileName AiPm.py
# @author Leon
# @EditTime 2026/3/12
# const $ = new Env('AIPM中转站');
# cron: 0 0 12 * * *
from checkin_core import run_checkin
if __name__ == "__main__":
run_checkin(
env_name="aipm_cookies",
base_url="https://emtf.aipm9527.online",
origin="https://emtf.aipm9527.online",
referer="https://emtf.aipm9527.online/console/personal",
notify_title="AIPM",
)

View File

@@ -0,0 +1,26 @@
# Source: https://github.com/back-101/zyqinglong/blob/main/DGB.py
# Raw: https://raw.githubusercontent.com/back-101/zyqinglong/main/DGB.py
# Repo: back-101/zyqinglong
# Path: DGB.py
# UploadedAt: 2026-04-01T04:49:35Z
# SHA256: 088295b00248471126407a7c10abdee790c1800cca0349f240ef4847bb36a7e8
# Category: APP版/抓包
# Evidence: cookie/token/authorization/header
# -*- coding=UTF-8 -*-
# @Project QL_TimingScript
# @fileName AiPm.py
# @author Leon
# @EditTime 2026/3/12
# const $ = new Env('DGB中转站');
# cron: 0 0 12 * * *
from checkin_core import run_checkin
if __name__ == "__main__":
run_checkin(
env_name="dgb_cookies",
base_url="https://freeapi.dgbmc.top",
origin="https://freeapi.dgbmc.top",
referer="https://freeapi.dgbmc.top/console/personal",
notify_title="DGB",
)

View File

@@ -0,0 +1,246 @@
# Source: https://github.com/CN-Grace/QinglongScripts/blob/main/HelloGithub.py
# Raw: https://raw.githubusercontent.com/CN-Grace/QinglongScripts/main/HelloGithub.py
# Repo: CN-Grace/QinglongScripts
# Path: HelloGithub.py
# UploadedAt: 2026-05-23T15:48:24Z
# SHA256: 041c84250a0164d2dd96a531bc3bb7a90a4a49ee508c39952a74641b319915f2
# Category: APP版/抓包
# Evidence: cookie/token/authorization/header
#!/usr/bin/env python3
"""
cron: 0 8 1 * *
new Env("HelloGitHub月刊")
HelloGitHub 月刊更新提醒
每月运行一次,检查并发送最新月刊内容。
支持分多条消息发送完整内容,基于字符长度分段。
"""
import json
import os
import re
import time
import requests
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional, Tuple
from utils import log_info, log_success, log_warning, log_error, beijing_time_str
from notifier import send as notify_send
# ==================== 用户配置 ====================
STATE_FILE = Path.home() / ".hellogithub_bot_state.json"
PERIODICAL_API = "https://abroad.hellogithub.com/v1/periodical/"
PERIODICAL_PAGE_URL = "https://hellogithub.com/periodical"
MAX_MESSAGE_LENGTH = 3900
def load_last_sent_volume() -> int:
try:
if STATE_FILE.exists():
with open(STATE_FILE, "r", encoding="utf-8") as f:
return json.load(f).get("last_sent_volume", 0)
return 0
except Exception as e:
log_error(f"读取状态文件失败: {e}")
return 0
def save_last_sent_volume(volume_num: int) -> None:
try:
state = {"last_sent_volume": volume_num, "updated_at": datetime.now().isoformat(), "last_run": beijing_time_str()}
with open(STATE_FILE, "w", encoding="utf-8") as f:
json.dump(state, f, ensure_ascii=False, indent=2)
log_success(f"已更新状态文件,最新期数: {volume_num}")
except Exception as e:
log_error(f"保存状态文件失败: {e}")
def get_latest_volume_info() -> Tuple[Optional[int], Optional[str]]:
try:
resp = requests.get(PERIODICAL_API, timeout=10)
resp.raise_for_status()
data = resp.json()
if data.get("success"):
latest = data["volumes"][0]
return latest["num"], latest["lastmod"]
log_error("API 返回 success 为 false")
return None, None
except Exception as e:
log_error(f"请求期数 API 失败: {e}")
return None, None
def extract_build_id() -> Optional[str]:
try:
resp = requests.get(PERIODICAL_PAGE_URL, timeout=10)
resp.raise_for_status()
match = re.search(r'<script id="__NEXT_DATA__" type="application/json">(.*?)</script>', resp.text, re.DOTALL)
if match:
next_data = json.loads(match.group(1))
build_id = next_data.get("buildId")
if build_id:
log_info(f"成功获取 buildId: {build_id}")
return build_id
log_error("未找到 buildId")
return None
except Exception as e:
log_error(f"提取 buildId 失败: {e}")
return None
def get_volume_content(volume_num: int, build_id: str) -> Optional[Dict]:
content_api = f"https://hellogithub.com/_next/data/{build_id}/zh/periodical/volume/{volume_num}.json"
try:
data = requests.get(content_api, timeout=10).json()
page_props = data.get("pageProps", {})
volume_data = page_props.get("volumeData") or page_props.get("volume", {})
if not volume_data:
return None
title = volume_data.get("title", f"HelloGitHub 第 {volume_num}")
desc = volume_data.get("desc", "")
categories_data = []
for category_item in volume_data.get("data", []):
formatted_items = []
for item in category_item.get("items", []):
formatted_items.append({
"full_name": item.get("full_name", "未知项目"),
"description": item.get("description", "暂无描述"),
"github_url": item.get("github_url", ""),
"stars": item.get("stars", 0),
"forks": item.get("forks", 0),
"watch": item.get("watch", 0),
"language": item.get("lang", ""),
"homepage": item.get("homepage", ""),
})
if formatted_items:
categories_data.append({"category_name": category_item.get("category_name", "未分类"), "items": formatted_items})
return {"title": title, "description": desc, "categories": categories_data, "total_items": sum(len(c["items"]) for c in categories_data), "volume_num": volume_num}
except Exception as e:
log_error(f"请求内容 API 失败: {e}")
return None
def format_project_info(project: Dict, project_num: int, total_projects: int) -> str:
name = project["full_name"]
desc = project["description"]
stars, forks, watch = project["stars"], project["forks"], project["watch"]
lang = project["language"]
github_url = project["github_url"]
lines = [f" {project_num}/{total_projects}. 【{name}"]
if lang:
lines.append(f" 语言: {lang}")
lines.append(f" 描述: {desc}")
stats = []
if stars > 0: stats.append(f"{stars}")
if forks > 0: stats.append(f"🔀 {forks}")
if watch > 0: stats.append(f"👀 {watch}")
if stats:
lines.append(f" 数据: {' | '.join(stats)}")
if github_url:
lines.append(f" 链接: {github_url}")
lines.append("")
return "\n".join(lines)
def format_category_header(category: Dict, category_num: int, total_categories: int) -> str:
category_name = category["category_name"]
items = category["items"]
return f"\n{'' * 40}\n\n🎯 {category_num}/{total_categories}. {category_name} ({len(items)} 个项目)\n\n"
def create_report_pages(content: Dict) -> List[str]:
if not content:
return []
title = content["title"]
desc = content["description"]
categories = content.get("categories", [])
total_items = content.get("total_items", 0)
volume_num = content.get("volume_num", 0)
total_categories = len(categories)
latest_num, lastmod = get_latest_volume_info()
pub_date = lastmod[:10] if lastmod else beijing_time_str("%Y-%m-%d")
# 标题页
header = f"🚀 {title}\n\n"
if desc:
header += f"📝 {desc}\n\n"
header += f"📅 发布时间: {pub_date}\n🔢 期号: 第 {volume_num}\n📚 项目总数: {total_items}\n🏷️ 分类数量: {total_categories}\n\n{'' * 40}\n"
pages = [header]
all_parts = []
cat_num = 1
for cat in categories:
all_parts.append(format_category_header(cat, cat_num, total_categories))
for i, item in enumerate(cat["items"]):
proj_num = sum(len(c["items"]) for c in categories[:cat_num - 1]) + i + 1
all_parts.append(format_project_info(item, proj_num, total_items))
cat_num += 1
current = ""
for part in all_parts:
if len(current) + len(part) <= MAX_MESSAGE_LENGTH:
current += part
else:
if current:
pages.append(f"📋 第 {volume_num} 期 - 项目详情\n\n{current}")
current = part
if len(part) > MAX_MESSAGE_LENGTH:
pages.append(part)
current = ""
if current:
pages.append(f"📋 第 {volume_num} 期 - 项目详情\n\n{current}")
read_more = f"https://hellogithub.com/zh/periodical/volume/{volume_num}/"
footer = f"\n{'' * 40}\n\n🎉 {title} 完整内容已发送完毕!\n\n📊 本期共 {total_items} 个项目,{total_categories} 个分类\n🔗 在线阅读: {read_more}\n🌟 GitHub: https://github.com/521xueweihan/HelloGitHub"
pages.append(footer)
return pages
def main():
log_info("===== HelloGitHub 月刊检查开始 =====")
last_sent = load_last_sent_volume()
log_info(f"上次发送的期数: {last_sent}")
latest_num, lastmod = get_latest_volume_info()
if not latest_num:
log_error("无法获取最新期数信息,任务终止")
return
log_info(f"最新期数: {latest_num}, 更新时间: {lastmod}")
if latest_num <= last_sent:
log_info(f"没有新刊发布 (最新: {latest_num}, 已发送: {last_sent})")
return
log_info(f"发现新刊! 第 {latest_num}")
build_id = extract_build_id()
if not build_id:
log_error("无法获取 buildId任务终止")
return
content = get_volume_content(latest_num, build_id)
if not content:
log_error(f"无法获取第 {latest_num} 期内容")
return
log_success(f"成功获取第 {latest_num} 期内容,包含 {content.get('total_items', 0)} 个项目")
pages = create_report_pages(content)
log_info(f"共生成 {len(pages)} 条消息")
for i, page_text in enumerate(pages, 1):
log_info(f"正在发送第 {i}/{len(pages)} 条消息 ({len(page_text)} 字符)...")
notify_send(f"HelloGitHub 第 {latest_num} 期 ({i}/{len(pages)})", page_text)
if i < len(pages):
time.sleep(2)
save_last_sent_volume(latest_num)
log_info("===== 任务完成 =====")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,37 @@
// # Source: https://github.com/Wenmoux/checkbox/blob/master/scripts/Qoo.js
// # Raw: https://raw.githubusercontent.com/Wenmoux/checkbox/master/scripts/Qoo.js
// # Repo: Wenmoux/checkbox
// # Path: scripts/Qoo.js
// # UploadedAt: 2021-10-10T06:20:09Z
// # SHA256: d538c7cb1f22866224e5a1db8be4d8450e58f12b1a583c705a319ea2e59bef4a
// # Category: APP版/抓包
// # Evidence: cookie/token/authorization/header
//
//Qoo app 个人中心转蛋 没啥用
const axios = require("axios");
function task() {
return new Promise(async (resolve) => {
try {
let token = config.Qoo.token;
await axios.post(`https://api.qoo-app.com/v9/usercard/setcardshare?token=${token}`)
let url = `https://api.qoo-app.com/v9/usercard/signincard?token=${token}`;
let res = await axios.post(url);
if (res.data.code == 200) {
msg = `签到成功✅ 当前共${res.data.data.point}转蛋券`;
if(res.data.data.ret==1) console.log(`签到成功!今日获得${res.data.data.add}`)
} else {
msg = JSON.stringify(res.data);
}
console.log(msg);
} catch (err) {
msg = "签到接口请求出错";
console.log(err);
}
resolve("【Qoo】"+msg );
});
}
module.exports = task;

View File

@@ -0,0 +1,167 @@
# Source: https://github.com/CN-Grace/QinglongScripts/blob/main/SSL.py
# Raw: https://raw.githubusercontent.com/CN-Grace/QinglongScripts/main/SSL.py
# Repo: CN-Grace/QinglongScripts
# Path: SSL.py
# UploadedAt: 2026-05-23T16:04:54Z
# SHA256: c1f33bef544c897a6d3ea4c28fde98c6ee9729002ec45451f6197a1348d24589
# Category: APP版/抓包
# Evidence: cookie/token/authorization/header
#!/usr/bin/env python3
"""
cron: 0 0 * * *
new Env("SSL证书检查")
SSL 证书检查脚本
- 批量检查多个域名的 SSL 证书状态
- 获取证书到期时间、剩余天数、颁发者等信息
- 分类显示正常、警告、过期和检查失败的证书
"""
import os
import ssl
import socket
from datetime import datetime, timezone
from typing import List, Dict
from utils import log_info, log_success, log_warning, log_error, beijing_now, beijing_time_str
from notifier import send as notify_send
# ==================== 用户配置 ====================
DOMAINS_TO_CHECK = [d.strip() for d in os.environ.get("SSL_DOMAINS", "").split(",") if d.strip()]
WARNING_THRESHOLD = 30
CONNECTION_TIMEOUT = 10
def get_certificate_info(domain: str) -> Dict:
"""获取单个域名的 SSL 证书信息"""
result = {"domain": domain, "expiry_date": datetime.min, "days_left": -1, "issuer": "", "is_valid": False, "error": None}
try:
hostname = domain if ":" in domain else f"{domain}:443"
host, port = hostname.split(":")
port = int(port)
context = ssl.create_default_context()
with socket.create_connection((host, port), timeout=CONNECTION_TIMEOUT) as sock:
with context.wrap_socket(sock, server_hostname=host) as ssock:
cert = ssock.getpeercert()
expiry_str = cert["notAfter"]
expiry_date = datetime.strptime(expiry_str, "%b %d %H:%M:%S %Y %Z").replace(tzinfo=timezone.utc)
now = datetime.now(timezone.utc)
days_left = (expiry_date - now).days
issuer_dict = dict(x[0] for x in cert["issuer"])
issuer = issuer_dict.get("organizationName", "Unknown")
result.update({"expiry_date": expiry_date, "days_left": days_left, "issuer": issuer, "is_valid": days_left > 0})
log_info(f"{domain} 证书剩余 {days_left}")
except Exception as e:
result["error"] = str(e)
log_error(f"{domain} 检查失败: {e}")
return result
def check_all_domains(domains: List[str]) -> List[Dict]:
"""检查所有域名的 SSL 证书"""
results = []
log_info(f"开始检查 {len(domains)} 个域名的 SSL 证书...")
for domain in domains:
log_info(f"正在检查: {domain}")
cert_info = get_certificate_info(domain)
results.append(cert_info)
if cert_info["is_valid"]:
if cert_info["days_left"] <= WARNING_THRESHOLD:
log_warning(f" ⚠️ {domain} 将在 {cert_info['days_left']} 天后过期")
else:
log_success(f"{domain} 证书正常,剩余 {cert_info['days_left']}")
elif cert_info["error"]:
log_error(f" 🔧 {domain} 检查失败: {cert_info['error']}")
else:
log_error(f"{domain} 证书已过期")
return results
def categorize_certificates(certificates: List[Dict]) -> Dict[str, List[Dict]]:
"""将证书结果分类"""
warning_certs, expired_certs, valid_certs, error_certs = [], [], [], []
for cert in certificates:
if cert["error"] is not None:
error_certs.append(cert)
elif cert["is_valid"]:
if 0 < cert["days_left"] <= WARNING_THRESHOLD:
warning_certs.append(cert)
elif cert["days_left"] > WARNING_THRESHOLD:
valid_certs.append(cert)
else:
expired_certs.append(cert)
return {"warning": warning_certs, "expired": expired_certs, "valid": valid_certs, "error": error_certs}
def format_certificate_report(certificates: List[Dict]) -> str:
"""格式化证书检查报告"""
cats = categorize_certificates(certificates)
lines = [f"🔔 SSL 证书检查报告", "", f"⏰ 检查时间: {beijing_time_str()}", f"📊 总计: {len(certificates)} 个域名", ""]
if cats["expired"]:
lines.append("❌ 已过期的证书:")
for cert in cats["expired"]:
expiry = cert["expiry_date"].strftime("%Y-%m-%d") if cert["expiry_date"] != datetime.min else "未知"
lines.append(f" {cert['domain']} — 已过期 {abs(cert['days_left'])} 天 (到期: {expiry})")
lines.append("")
if cats["warning"]:
lines.append("⚠️ 即将过期的证书 (30天内):")
for cert in cats["warning"]:
expiry = cert["expiry_date"].strftime("%Y-%m-%d")
lines.append(f" {cert['domain']} — 剩余 {cert['days_left']} 天 (到期: {expiry} | 颁发: {cert['issuer']})")
lines.append("")
if cats["valid"]:
lines.append("✅ 证书状态正常:")
for cert in cats["valid"]:
lines.append(f" {cert['domain']} — 剩余 {cert['days_left']}")
lines.append("")
if cats["error"]:
lines.append("🔧 检查失败的域名:")
for cert in cats["error"]:
lines.append(f" {cert['domain']} — 错误: {cert['error']}")
lines.append("")
lines.append("📈 统计信息:")
lines.append(f" ✅ 正常: {len(cats['valid'])}")
lines.append(f" ⚠️ 警告: {len(cats['warning'])}")
lines.append(f" ❌ 过期: {len(cats['expired'])}")
lines.append(f" 🔧 失败: {len(cats['error'])}")
lines.append("")
lines.append("" * 18)
lines.append(f"🕒 执行时间: {beijing_time_str()}")
return "\n".join(lines)
def main():
log_info("=" * 50)
log_info("SSL 证书检查脚本开始执行")
log_info("=" * 50)
cert_results = check_all_domains(DOMAINS_TO_CHECK)
report = format_certificate_report(cert_results)
notify_send("SSL 证书检查报告", report)
cats = categorize_certificates(cert_results)
print(f"\n{'=' * 60}")
print(f"SSL 证书检查完成! 检查域名总数: {len(cert_results)}")
print(f"正常: {len(cats['valid'])} | 警告: {len(cats['warning'])} | 过期: {len(cats['expired'])} | 失败: {len(cats['error'])}")
print("=" * 60)
if cats["expired"] or cats["warning"]:
print("\n⚠️ 需要注意的域名:")
for cert in cats["expired"]:
print(f"{cert['domain']} — 已过期")
for cert in cats["warning"]:
print(f" ⚠️ {cert['domain']} — 剩余 {cert['days_left']} 天到期")
log_info("=" * 50)
log_info(f"脚本执行结束")
log_info("=" * 50)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,26 @@
# Source: https://github.com/back-101/zyqinglong/blob/main/Z-API.py
# Raw: https://raw.githubusercontent.com/back-101/zyqinglong/main/Z-API.py
# Repo: back-101/zyqinglong
# Path: Z-API.py
# UploadedAt: 2026-03-13T04:15:05Z
# SHA256: 2978ef593177e01cc1909a0a71d714a837f3b049687027380de321bfe641634b
# Category: APP版/抓包
# Evidence: cookie/token/authorization/header
# -*- coding=UTF-8 -*-
# @Project QL_TimingScript
# @fileName Z-API.py
# @author Leon
# @EditTime 2026/3/12
# const $ = new Env('Z-API中转站');
# cron: 0 0 12 * * *
from checkin_core import run_checkin
if __name__ == "__main__":
run_checkin(
env_name="zapi_cookies",
base_url="https://zapi.aicc0.com",
origin="https://zapi.aicc0.com",
referer="https://zapi.aicc0.com/console/personal",
notify_title="Z-API",
)

View File

@@ -0,0 +1,261 @@
// # Source: https://github.com/Wenmoux/checkbox/blob/master/scripts/aw.js
// # Raw: https://raw.githubusercontent.com/Wenmoux/checkbox/master/scripts/aw.js
// # Repo: Wenmoux/checkbox
// # Path: scripts/aw.js
// # UploadedAt: 2025-12-09T08:05:01Z
// # SHA256: e1df85787b7fee88ca6371dad4e14db2a71e331346b733c8bd50a4f762080297
// # Category: APP版/抓包
// # Evidence: cookie/token/authorization/header
//
// 爱吾游戏宝盒全能自动脚本 v4.0 - 兼容依赖版本
// 配置文件字段config.aiwu.*
const axios = require('axios');
const crypto = require('crypto');
// querystring 是 Node.js 内置模块,无需 require
// =====================================================================
// 1. 配置和常量定义
// =====================================================================
const USER_CONFIG = {
VersionCode: config.aiwu.VersionCode || "2050902",
Serial: config.aiwu.Serial || "", // 设备序列号
Phone: config.aiwu.Phone || "",
PhoneCP: config.aiwu.PhoneCP || "",
Channel: config.aiwu.Channel || "25az",
VIPSign: config.aiwu.VIPSign || "",
AppPackageName: config.aiwu.AppPackageName || "com.aiwu.market",
oaid: config.aiwu.oaid || "",
android_id: config.aiwu.android_id || "",
isLogin: config.aiwu.isLogin || "1",
UserId: config.aiwu.UserId || "" // 用户ID
};
const BASE_URL = "https://service.25game.com/v2";
const API = {
TASK: "/User/MyTask.aspx", // 日常任务 & 领奖
BBS: "/BBS/BBSPost.aspx" // 论坛签到
};
const HEADERS = {
'Accept-Language': 'zh-CN,zh;q=0.8',
'User-Agent': 'okhttp-okgo/jeasonlzy',
'Content-Type': 'application/x-www-form-urlencoded',
'Host': 'service.25game.com',
'Connection': 'Keep-Alive',
'Accept-Encoding': 'gzip'
};
// =====================================================================
// 2. 工具函数
// =====================================================================
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// 部分反转字符串
function partialReverse(str) {
let arr = str.split('');
for (let i = 0; i < 16; i += 2) {
let j = 31 - i;
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr.join('');
}
// 生成签名
function generateSignature(params, timestamp) {
const finalParams = { ...params, Time: timestamp };
const sortedKeys = Object.keys(finalParams).sort();
let javaString = "";
sortedKeys.forEach(key => {
let val = finalParams[key];
if (val === undefined || val === null) val = "";
javaString += `${key}=${val}&`;
});
const salt = "Wlb=wlbnb&Key=AppKey";
const remainder = parseInt(timestamp, 10) % 8;
const rawString = `${javaString}${salt}${timestamp}${remainder}`;
const md5Step1 = crypto.createHash('md5').update(rawString).digest('hex');
const reversedStr = partialReverse(md5Step1);
return crypto.createHash('md5').update(reversedStr).digest('hex');
}
// 构建查询字符串
function buildQueryString(data) {
return Object.keys(data)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
.join('&');
}
// =====================================================================
// 3. 网络请求封装
// =====================================================================
async function sendRequest(apiPath, businessParams = {}) {
const timestamp = Math.floor(Date.now() / 1000).toString();
const requestParams = { ...USER_CONFIG, ...businessParams };
const sign = generateSignature(requestParams, timestamp);
const bodyData = {
...requestParams,
Time: timestamp,
Sign: sign
};
try {
const response = await axios.post(BASE_URL + apiPath, buildQueryString(bodyData), {
headers: HEADERS
});
return response.data;
} catch (error) {
console.error(`[请求异常] ${apiPath}: ${error.message}`);
return null;
}
}
// =====================================================================
// 4. 业务逻辑函数
// =====================================================================
async function runDailyTasks() {
const logs = ["执行日常活跃任务"];
const tasks = [
{ name: "每日签到", act: "DailyLogin" },
{ name: "云游戏打卡", act: "DailyCloudGame" },
{ name: "每日搜索", act: "DailySearchGame" },
{ name: "每日分享", act: "DailyShare" },
{ name: "每日下载", act: "DailyDown" },
];
for (const t of tasks) {
const res = await sendRequest(API.TASK, { Act: t.act });
logs.push(`${t.name}: ${res?.Message || (res ? "完成" : "失败")}`);
await sleep(1200);
}
// 广告需要看2次
for (let i = 1; i <= 2; i++) {
const res = await sendRequest(API.TASK, { Act: 'DailyLookAd' });
logs.push(`观看广告第${i}次: ${res?.Message || "完成"}`);
await sleep(2000);
}
return logs;
}
async function runBbsSign() {
const logs = ["执行论坛版块签到"];
const sessionIds = [5, 6, 12, 13]; // 常见版块ID
for (const id of sessionIds) {
const res = await sendRequest(API.BBS, {
Act: "SignSession",
SessionId: id
});
if (res?.Code === "0") {
logs.push(`签到版块[ID:${id}]: ${res.Message}`);
} else {
logs.push(`签到版块[ID:${id}]: ${res?.Message || "失败"}`);
}
await sleep(1500);
}
return logs;
}
async function runClaimRewards() {
const logs = ["检查并领取奖励"];
const res = await sendRequest(API.TASK, {});
if (!res || !res.Data) {
logs.push("获取任务列表失败");
return logs;
}
let claimCount = 0;
for (const task of res.Data) {
const name = task.TaskNum;
if (name == "每日登录") continue;
const cur = parseInt(task.CompleteNum);
const total = parseInt(task.TotalNum);
const isReceived = (task.isReward === "True");
const taskNo = task.TaskNo;
if (cur >= total && !isReceived && taskNo) {
const claim = await sendRequest(API.TASK, {
TaskNo: taskNo,
Act: 'ReceiveAward'
});
if (claim?.Code === "0") {
logs.push(`领取[${name}]: 成功 金币+${claim.RewardGold}, 经验+${claim.RewardExp}`);
claimCount++;
} else {
logs.push(`领取[${name}]: 失败 ${claim?.Message}`);
}
await sleep(1000);
}
}
if (claimCount === 0) logs.push("没有可领取的奖励");
return logs;
}
// =====================================================================
// 5. 主函数 - 适配checkbox.js模板
// =====================================================================
async function main() {
let result = "【爱吾游戏宝盒】:";
const allLogs = [];
try {
// 验证必要配置
if (!USER_CONFIG.UserId || !USER_CONFIG.Serial) {
return result + "请先配置UserId和Serial参数";
}
// 执行日常任务
const dailyLogs = await runDailyTasks();
allLogs.push(...dailyLogs);
// 执行论坛签到
const bbsLogs = await runBbsSign();
allLogs.push(...bbsLogs);
// 领取奖励
const rewardLogs = await runClaimRewards();
allLogs.push(...rewardLogs);
// 汇总结果
const successCount = allLogs.filter(log =>
log.includes("成功") ||
log.includes("完成") ||
log.includes("金币+")
).length;
result += `任务执行完成,成功项: ${successCount}/${allLogs.length -3}`;
// 将详细日志作为第二行(如果需要)
const detailLogs = allLogs.map(log => ` ${log}`).join('\n');
if (detailLogs) {
result += `\n详细:\n${detailLogs}`;
}
} catch (error) {
console.error("脚本执行出错:", error);
result += "脚本执行异常: " + error.message;
}
return result;
}
// =====================================================================
// 6. 导出模块
// =====================================================================
module.exports = main;

View File

@@ -0,0 +1,90 @@
// # Source: https://github.com/Wenmoux/checkbox/blob/master/scripts/hscy.js
// # Raw: https://raw.githubusercontent.com/Wenmoux/checkbox/master/scripts/hscy.js
// # Repo: Wenmoux/checkbox
// # Path: scripts/hscy.js
// # UploadedAt: 2023-04-01T13:17:21Z
// # SHA256: de58e1b4fb5c45c288f630776a7b58c5712594cc73b6e9a86b3124759fdcb146
// # Category: APP版/抓包
// # Evidence: cookie/token/authorization/header
//
const axios = require("axios")
const headers = {
Authorization: config.hscy.authorization,
Cookie: `b2_token=${config.hscy.authorization.slice(7)}`
};
let result = "【黑丝次元】:";
let nickname = "";
let nowCredit = 0;
function getUserInfo() {
return new Promise(async (resolve) => {
try {
const url = `https://heisi.moe/wp-json/b2/v1/getUserInfo`;
let res = await axios.post(url, "", {headers});
nickname = res.data.user_data.name;
nowCredit = res.data.user_data.credit;
result += `\n[${nickname}]当前积分:${nowCredit}`;
} catch (err) {
console.log(err)
result += "\n获取用户信息失败 ";
console.log(result);
}
resolve();
});
}
function sign() {
return new Promise(async (resolve) => {
try {
const url = `https://heisi.moe/wp-json/b2/v1/userMission`;
let res = await axios.post(url, "", {headers});
let credit = res.data.credit ? res.data.credit : res.data
console.log(`签到成功,获得:` + credit + "分");
result += ` || 签到成功,获得:` + credit + "分";
} catch (err) {
console.log(err)
result += " || 签到失败,已签到过或其它未知原因!! ";
console.log(result);
}
resolve();
});
}
function submitComment() {
return new Promise(async (resolve) => {
try {
const url = `https://heisi.moe/wp-json/b2/v1/commentSubmit`;
// 0-2500随机评论
let data = `comment_post_ID=${Math.round(Math.random() * (2500 - 0) + 0)}&author=${encodeURI(nickname)}&comment=%E5%A5%BD%E7%9C%8B&comment_parent=0&img%5BimgUrl%5D=&img%5BimgId%5D=`
let res = await axios.post(url, data, {headers});
console.log(`[${nickname}]评论成功`);
result += ` || [${nickname}]评论成功`;
} catch (err) {
console.log(err)
result += " || 评论失败,已评论过或其它未知原因!! ";
console.log(result);
}
resolve();
});
}
function sleep(time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
async function hscy() {
await getUserInfo();
await sleep(1000);
await sign();
await sleep(1000);
for (let i = 0; i < 5; i++) {
await submitComment();
await sleep(61000); // 延迟,否则太快评论不上
}
await getUserInfo();
return result;
}
module.exports = hscy;

View File

@@ -0,0 +1,38 @@
// # Source: https://github.com/Wenmoux/checkbox/blob/master/scripts/ldygo.js
// # Raw: https://raw.githubusercontent.com/Wenmoux/checkbox/master/scripts/ldygo.js
// # Repo: Wenmoux/checkbox
// # Path: scripts/ldygo.js
// # UploadedAt: 2021-04-16T00:43:18Z
// # SHA256: 1c2bfc752df7a9d5a50a1d06e382a940c6fea22656b67da275952fe8e61aed6a
// # Category: APP版/抓包
// # Evidence: cookie/token/authorization/header
//
//联动云租车每日签到https://m.ldygo.com/app/extension/phoneVoucher.html?inviteCode=JW0hcdmJ
const axios = require("axios");
function ldygo() {
return new Promise(async (resolve) => {
try {
let url =
"https://m.ldygo.com/los/zuche-intf-union.signIn";
const header = {
headers: {
cookie: config.ldygo.cookie,
},
};
const postdata = {"_channel_id":"09","_client_version_no":"2.11.0","timestamp":Math.round(new Date().getTime()/1000).toString()}
let res = await axios.post(url, postdata,header);
if (res.data.responseCode == "000000") {
data = `签到成功! ☁️ + ${res.data.model.points}`;
} else {
data = res.data.responseMsg;
}
console.log(data);
} catch (err) {
console.log(err);
data="签到接口请求出错"
}
resolve("【联动云租车】:" + data);
});
}
module.exports = ldygo;

View File

@@ -0,0 +1,33 @@
// # Source: https://github.com/Wenmoux/checkbox/blob/master/scripts/lkong.js
// # Raw: https://raw.githubusercontent.com/Wenmoux/checkbox/master/scripts/lkong.js
// # Repo: Wenmoux/checkbox
// # Path: scripts/lkong.js
// # UploadedAt: 2021-04-16T00:43:18Z
// # SHA256: 31125817fbd89450962eccb39bdd21d8768afc609a6b7b50c59ae078e842da40
// # Category: APP版/抓包
// # Evidence: cookie/token/authorization/header
//
const axios = require("axios");
function task() {
return new Promise(async (resolve) => {
try {
let cookie = config.lkong.cookie;
let url = "http://lkong.cn/index.php?mod=ajax&action=punch";
let res = await axios.get(url, { headers: { cookie: cookie } });
if (res.data.punchday) {
msg = `签到成功✅已连签${res.data.punchday}`;
} else {
msg = res.data.error;
}
console.log(msg);
} catch (err) {
msg = "签到接口请求出错";
console.log(err);
}
resolve("【龙空论坛】:" + msg);
});
}
//task()
module.exports = task;

View File

@@ -0,0 +1,74 @@
// # Source: https://github.com/Wenmoux/checkbox/blob/master/scripts/nga.js
// # Raw: https://raw.githubusercontent.com/Wenmoux/checkbox/master/scripts/nga.js
// # Repo: Wenmoux/checkbox
// # Path: scripts/nga.js
// # UploadedAt: 2022-12-29T07:44:16Z
// # SHA256: a31a39d2686a445bba1c94e9887a51f92854932d575a45c27bf8c7ab35850ea9
// # Category: APP版/抓包
// # Evidence: cookie/token/authorization/header
//
const axios = require("axios");
function ngaGet(lib, act, output = 11, other = null) {
return new Promise(async (resolve) => {
try {
let nga = config.nga;
let url = "https://ngabbs.com/nuke.php";
let res = await axios.post(
url,
`access_uid=${nga.uid}&access_token=${
nga.accesstoken
}& app_id=1010&__act=${act}&__lib=${lib}&__output=${output}&${other}`, {
headers: {
"User-Agent": nga.UA ? nga.UA : "xxxxxx Nga_Official/90409"
}
}
);
console.log(" " + (res.data && res.data.time || res.data.code))
resolve(res.data)
} catch (err) {
console.log(err);
resolve({
error: ["签到接口请求出错"]
})
}
resolve();
});
}
async function task() {
msg = "【NGA】\n"
//签到
let res1 = await ngaGet("check_in", "check_in")
if (res1 && res1.data) {
msg += " 签到:" + res1.data[0];
} else {
console.log(res1);
msg += " 签到:" + (res1.error && res1.error[0]);
}
if (!msg.match(/登录|CLIENT/)) {
await ngaGet("mission", "checkin_count_add", 11, "mid=2&get_success_repeat=1&no_compatible_fix=1")
await ngaGet("mission", "checkin_count_add", 11, "mid=131&get_success_repeat=1&no_compatible_fix=1")
await ngaGet("mission", "checkin_count_add", 11, "mid=30&get_success_repeat=1&no_compatible_fix=1")
console.log("看视频免广告")
await ngaGet("mission", "video_view_task_counter_add_v2_for_adfree_sp1")
for (c of new Array(4)) await ngaGet("mission", "video_view_task_counter_add_v2_for_adfree")
console.log("看视频得N币")
for (c of new Array(5)) await ngaGet("mission", "video_view_task_counter_add_v2")
//分享帖子
console.log("分享帖子 5")
tid = Math.ceil(Math.random() * 12346567) + 12345678
for (c of new Array(5)) await ngaGet("data_query", "topic_share_log_v2", 12, "event=4&tid=" + tid)
console.log("领取分享奖励 1N币")
await ngaGet("mission", "check_mission", 11, "mid=149&get_success_repeat=1&no_compatible_fix=1")
//查询
let {
data: [sign, money, y]
} = await ngaGet("check_in", "get_stat")
msg += ` 连签 ${sign.continued}天 累签 ${sign.sum}\n N币${money.money_n}\n 铜币:${money.money}\n 啊哈:${y[0]}`
}
return msg
}
module.exports = task;

View File

@@ -0,0 +1,42 @@
// # Source: https://github.com/Wenmoux/checkbox/blob/master/scripts/ssly.js
// # Raw: https://raw.githubusercontent.com/Wenmoux/checkbox/master/scripts/ssly.js
// # Repo: Wenmoux/checkbox
// # Path: scripts/ssly.js
// # UploadedAt: 2024-02-15T10:01:01Z
// # SHA256: c6789fe7074c540cd5425bfa4cc2b8b89942eda9f52d6fd931eefb9c42c4f19d
// # Category: APP版/抓包
// # Evidence: cookie/token/authorization/header
//
const axios = require("axios");
const CryptoJS = require("crypto-js");
//绅士领域 注册时候推荐码填2984317
uid = config.ssly.uid; //抓包看,比如签到的post包里就有u_id,如120487
function ssly() {
return new Promise(async (resolve) => {
try {
let url = `https://sslyapp.site/mz_pbl/app_con/add_sign.php`;
let timestamp = Math.floor((new Date()).getTime()/1000)+"";
timestamp = timestamp.replace(/^\s+|\s+$/g,"");
let mac = CryptoJS.MD5(CryptoJS.SHA1(CryptoJS.MD5(timestamp).toString()).toString()).toString();
let data = `time=${timestamp}&mac=${mac}&u_id=${uid}`;
let res = await axios.post(url, data);
if (res.data.state == 0) {
msg = res.data.erro;
} else if (res.data.state == 1) {
msg = res.data.sms;
} else {
console.log(res.data);
msg = "签到失败,原因未知";
}
console.log(msg);
} catch (err) {
console.log(err);
msg = "签到接口请求失败";
}
resolve("【绅士领域】:" + msg);
});
}
//ssly()
module.exports = ssly;

View File

@@ -0,0 +1,26 @@
# Source: https://github.com/back-101/zyqinglong/blob/main/FCAPI.py
# Raw: https://raw.githubusercontent.com/back-101/zyqinglong/main/FCAPI.py
# Repo: back-101/zyqinglong
# Path: FCAPI.py
# UploadedAt: 2026-03-16T04:42:35Z
# SHA256: 8f67b1f15f44591d48f12216dc4a28f781ba25b80af1c1cbc321af55f46c983f
# Category: APP版/抓包
# Evidence: cookie/token/authorization/header
# -*- coding=UTF-8 -*-
# @Project QL_TimingScript
# @fileName AiPm.py
# @author Leon
# @EditTime 2026/3/12
# const $ = new Env('发财网API中转站');
# cron: 0 0 12 * * *
from checkin_core import run_checkin
if __name__ == "__main__":
run_checkin(
env_name="fc_cookies",
base_url="https://ai.facai.cloudns.org",
origin="https://ai.facai.cloudns.org",
referer="https://ai.facai.cloudns.org/console/personal",
notify_title="发财网API",
)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,29 @@
// # Source: https://github.com/Wenmoux/checkbox/blob/master/scripts/fishc.js
// # Raw: https://raw.githubusercontent.com/Wenmoux/checkbox/master/scripts/fishc.js
// # Repo: Wenmoux/checkbox
// # Path: scripts/fishc.js
// # UploadedAt: 2021-09-25T00:15:59Z
// # SHA256: 2fcb72b6b50e8095d2fbe70f2e3fc123bb687b34ac7d77f189d7bbd37f4a7a09
// # Category: APP版/抓包
// # Evidence: cookie/token/authorization/header
//
const rules = {
name: "【鱼C论坛】 ",
url: "https://fishc.com.cn/plugin.php?id=k_misign:sign", //用于获取formhash的链接
cookie: config.fishc.cookie,
formhash: 'formhash=(.+?)\\"', //formhash正则
verify: "您需要先登录才能继续本操作", //验证cookie状态
op: [{
name: "签到",
charset: "gbk",
method: "get", //签到请求方式 get/post
url: "https://fishc.com.cn/plugin.php?id=k_misign:sign&operation=qiandao&format=text&formhash=@formhash"
}]
};
async function fishc() {
const template = require("../Template");
return rules.name + await template(rules)
}
module.exports = fishc

View File

@@ -0,0 +1,265 @@
# Source: https://github.com/CN-Grace/QinglongScripts/blob/main/Airport.py
# Raw: https://raw.githubusercontent.com/CN-Grace/QinglongScripts/main/Airport.py
# Repo: CN-Grace/QinglongScripts
# Path: Airport.py
# UploadedAt: 2026-05-23T15:48:24Z
# SHA256: 8d929ef7cd9c6942b81d31e420758e46f8ca649407c505dc3567b84385f5e6f4
# Category: APP版/账密
# Evidence: username/password/mobile/login
#!/usr/bin/env python3
"""
cron: 0 0 * * *
new Env("机场签到")
多服务机场自动签到脚本
- 自动登录多个指定服务网站
- 执行每日签到任务
- 获取剩余流量信息
- 发送格式化报告到通知渠道
"""
import os
import re
import sys
import time
import base64
import requests
from lxml import html
from typing import Dict, Any, List, Tuple
from utils import log_info, log_success, log_warning, log_error, beijing_time_str, create_session
from notifier import send as notify_send
# ==================== 服务配置 ====================
SERVICES = [
{
"name": "速鹰666",
"base_url": "https://suying00.com",
"login_path": "/auth/login",
"checkin_path": "/user/checkin",
"user_info_path": "/user",
"traffic_xpath": '//*[@id="app"]/div/div[3]/section/div[3]/div[2]/div/div[2]/div[2]',
"username": os.environ.get("SUYING_USERNAME", ""),
"password": os.environ.get("SUYING_PASSWORD", ""),
}
]
REQUEST_TIMEOUT = 10
# ==================== 功能函数 ====================
def login_to_service(service_config: Dict[str, str]) -> Tuple[bool, Any]:
"""登录到服务网站"""
session = create_session()
session.headers.update({"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"})
login_url = f"{service_config['base_url']}{service_config['login_path']}"
login_data = {"email": service_config["username"], "passwd": service_config["password"], "remember_me": "on", "code": ""}
try:
log_info(f"正在登录 [{service_config['name']}] 账户: {service_config['username']}")
response = session.post(login_url, data=login_data, timeout=REQUEST_TIMEOUT)
response.raise_for_status()
login_success = False
try:
json_data = response.json()
if json_data.get("ret") == 1 or json_data.get("success"):
login_success = True
log_success(f"[{service_config['name']}] 登录成功")
except Exception:
pass
if not login_success:
cookies = session.cookies.get_dict()
if "uid" in cookies or "key" in cookies or "email" in cookies:
login_success = True
log_success(f"[{service_config['name']}] 登录成功")
if not login_success and response.text:
if any(kw in response.text.lower() for kw in ["登录成功", "login success", "success", "欢迎"]):
login_success = True
log_success(f"[{service_config['name']}] 登录成功")
if login_success:
return True, session
log_error(f"[{service_config['name']}] 登录失败,响应: {response.text[:200]}")
return False, "无法判断登录状态"
except requests.exceptions.RequestException as e:
log_error(f"[{service_config['name']}] 登录请求失败: {e}")
return False, f"网络请求失败: {e}"
except Exception as e:
log_error(f"[{service_config['name']}] 登录未知错误: {e}")
return False, f"未知错误: {e}"
def perform_checkin(session, service_config: Dict[str, str]) -> Dict[str, Any]:
"""执行签到"""
checkin_url = f"{service_config['base_url']}{service_config['checkin_path']}"
result = {"success": False, "message": "签到失败", "details": {}}
try:
log_info(f"[{service_config['name']}] 正在执行签到...")
response = session.post(checkin_url, timeout=REQUEST_TIMEOUT)
response.raise_for_status()
try:
json_data = response.json()
result["details"] = json_data
result["message"] = json_data.get("msg", "签到完成")
result["success"] = True
log_success(f"[{service_config['name']}] 签到成功: {result['message']}")
except ValueError:
result["message"] = "签到完成,返回非标准格式"
result["details"] = {"raw_response": response.text[:500]}
result["success"] = True
log_success(f"[{service_config['name']}] 签到完成")
except requests.exceptions.RequestException as e:
log_error(f"[{service_config['name']}] 签到请求失败: {e}")
result["message"] = f"网络请求失败: {e}"
except Exception as e:
log_error(f"[{service_config['name']}] 签到未知错误: {e}")
result["message"] = f"未知错误: {e}"
return result
def extract_and_decode_base64(html_content):
"""从 HTML 中提取 base64 内容并解码"""
pattern = r'var\s+originBody\s*=\s*["\']([^"\']+)["\']'
match = re.search(pattern, html_content)
if match:
try:
decoded_bytes = base64.b64decode(match.group(1))
return decoded_bytes.decode("utf-8")
except Exception as e:
log_warning(f"Base64 解码失败: {e}")
return None
return None
def get_traffic_info(session, service_config: Dict[str, str]) -> Dict[str, Any]:
"""获取剩余流量信息"""
info_url = f"{service_config['base_url']}{service_config['user_info_path']}"
result = {"success": False, "traffic": "获取失败", "raw_html": None, "error": None}
try:
log_info(f"[{service_config['name']}] 正在获取流量信息...")
response = session.get(info_url, timeout=REQUEST_TIMEOUT)
response.raise_for_status()
raw_html = response.text
result["raw_html"] = raw_html
decoded_html = extract_and_decode_base64(raw_html)
html_to_parse = decoded_html or raw_html
tree = html.fromstring(html_to_parse)
traffic_elements = tree.xpath(service_config["traffic_xpath"])
if traffic_elements:
traffic_text = traffic_elements[0].text_content().strip()
result["traffic"] = traffic_text
result["success"] = True
log_success(f"[{service_config['name']}] 流量信息: {traffic_text}")
else:
result["error"] = "XPath 未找到匹配元素"
log_warning(f"[{service_config['name']}] {result['error']}")
except requests.exceptions.RequestException as e:
log_error(f"[{service_config['name']}] 获取流量请求失败: {e}")
result["error"] = f"网络请求失败: {e}"
except Exception as e:
log_error(f"[{service_config['name']}] 解析流量未知错误: {e}")
result["error"] = f"解析错误: {e}"
return result
def format_multi_checkin_report(results: List[Dict[str, Any]]) -> str:
"""格式化多服务签到报告"""
lines = ["📋 多服务签到报告", "", f"执行时间: {beijing_time_str()}", ""]
for idx, res in enumerate(results, 1):
name = res["name"]
checkin = res["checkin_result"]
traffic = res["traffic_result"]
login_error = res.get("login_error")
lines.append(f"{idx}. {name}")
if login_error:
lines.append(f" 🔐 登录: ❌ 失败 — {login_error}")
lines.append(f" 📝 签到: 跳过 | 📊 流量: 跳过")
else:
ci_emoji = "" if checkin["success"] else ""
lines.append(f" 📝 签到: {ci_emoji}{checkin['message']}")
if traffic["success"]:
lines.append(f" 📊 流量: ✅ {traffic['traffic']}")
else:
lines.append(f" 📊 流量: ❌ 获取失败")
if traffic.get("error"):
lines.append(f" 错误: {traffic['error']}")
lines.append("")
lines.append("" * 18)
lines.append(f"🕒 执行时间: {beijing_time_str()}")
return "\n".join(lines)
def save_debug_info(service_name, traffic_result, checkin_result):
"""保存调试信息"""
if traffic_result.get("raw_html"):
filename = f"debug_{service_name}_{beijing_time_str('%Y%m%d_%H%M%S')}.html"
try:
with open(filename, "w", encoding="utf-8") as f:
f.write(f"=== 调试信息 ===\n服务: {service_name}\n时间: {beijing_time_str()}\n签到: {checkin_result}\n流量: {traffic_result.get('traffic', 'N/A')}\n\n=== 原始HTML ===\n{traffic_result['raw_html']}")
log_info(f"调试信息已保存到: {filename}")
return filename
except Exception as e:
log_error(f"保存调试信息失败: {e}")
return None
def main():
log_info("=" * 50)
log_info("多服务自动签到脚本开始执行")
log_info("=" * 50)
start_time = time.time()
results = []
for service in SERVICES:
service_name = service["name"]
log_info(f"--- 开始处理: {service_name} ---")
login_success, login_result = login_to_service(service)
if not login_success:
log_error(f"[{service_name}] 登录失败: {login_result}")
results.append({"name": service_name, "login_error": login_result, "checkin_result": None, "traffic_result": None})
continue
session = login_result
checkin_result = perform_checkin(session, service)
traffic_result = get_traffic_info(session, service)
results.append({"name": service_name, "login_error": None, "checkin_result": checkin_result, "traffic_result": traffic_result})
if not traffic_result["success"] and traffic_result.get("raw_html"):
save_debug_info(service_name, traffic_result, checkin_result)
log_info(f"--- {service_name} 处理完成 ---")
report = format_multi_checkin_report(results)
notify_send("机场签到报告", report)
print(f"\n{'=' * 60}\n{report}\n{'=' * 60}")
execution_time = time.time() - start_time
log_info(f"脚本执行完成,耗时: {execution_time:.2f}")
any_success = any(res.get("checkin_result") and res["checkin_result"]["success"] for res in results)
return 0 if any_success else 1
if __name__ == "__main__":
try:
exit_code = main()
except KeyboardInterrupt:
log_info("用户中断执行")
exit_code = 130
except Exception as e:
log_error(f"脚本异常: {e}")
notify_send("机场签到脚本异常", f"错误: {str(e)[:200]}")
exit_code = 1
sys.exit(exit_code)

View File

@@ -0,0 +1,120 @@
# Source: https://github.com/CN-Grace/QinglongScripts/blob/main/Aliyun.py
# Raw: https://raw.githubusercontent.com/CN-Grace/QinglongScripts/main/Aliyun.py
# Repo: CN-Grace/QinglongScripts
# Path: Aliyun.py
# UploadedAt: 2026-05-23T15:48:24Z
# SHA256: 3b7f116faf934e85235755bfab79f1a491b48adf931889612cf496052943a7ae
# Category: APP版/账密
# Evidence: username/password/mobile/login
#!/usr/bin/env python3
"""
cron: 0 0 * * *
new Env("阿里云盘签到")
阿里云盘 每日签到脚本
- 刷新 Access Token
- 获取累计签到天数和奖励信息
"""
import os
import requests
import urllib3
from typing import Dict, Any, Optional
from utils import log_info, log_success, log_warning, log_error, beijing_time_str
from notifier import send as notify_send
urllib3.disable_warnings()
# ==================== 用户配置 ====================
ALIYUN_REFRESH_TOKEN = os.environ.get("ALIYUN_REFRESH_TOKEN", "")
def get_access_token(refresh_token: str) -> Optional[str]:
"""使用 refresh_token 获取新的 access_token"""
url = "https://auth.aliyundrive.com/v2/account/token"
data = {"grant_type": "refresh_token", "refresh_token": refresh_token}
try:
result = requests.post(url=url, json=data, timeout=10).json()
access_token = result.get("access_token")
if access_token:
log_success("Token 刷新成功")
return access_token
log_error("Token 刷新失败,响应中无 access_token")
return None
except Exception as e:
log_error(f"Token 刷新异常: {e}")
return None
def sign(access_token: str) -> Dict[str, Any]:
"""执行签到,返回累计天数和奖励信息"""
url = "https://member.aliyundrive.com/v1/activity/sign_in_list"
headers = {"Authorization": access_token, "Content-Type": "application/json"}
try:
result = requests.post(url=url, headers=headers, json={}, timeout=10).json()
if not result.get("success"):
msg = result.get("message", "未知错误")
log_error(f"签到失败: {msg}")
return {"success": False, "message": msg}
sign_days = result["result"]["signInCount"]
log_info(f"累计签到天数: {sign_days}")
reward_name, reward_desc = "", ""
for log in result["result"]["signInLogs"]:
if log["status"] == "normal":
today_log = log
if today_log.get("reward"):
reward_name = today_log["reward"].get("name", "")
reward_desc = today_log["reward"].get("description", "")
log_success(f"今日奖励: {reward_name}{reward_desc}")
break
else:
log_warning("今日奖励信息未找到")
return {
"success": True,
"sign_days": sign_days,
"reward_name": reward_name,
"reward_desc": reward_desc,
}
except Exception as e:
log_error(f"签到请求异常: {e}")
return {"success": False, "message": str(e)}
def build_report(result: Dict[str, Any]) -> str:
"""构建签到报告"""
lines = ["📦 阿里云盘 签到报告", ""]
if result.get("success"):
lines.append(f"✅ 签到状态: 成功")
lines.append(f"📅 累计签到: {result['sign_days']}")
if result["reward_name"] or result["reward_desc"]:
lines.append(f"🎁 今日奖励: {result['reward_name']}{result['reward_desc']}")
else:
lines.append(f"❌ 签到状态: 失败")
lines.append(f"⚠️ 错误信息: {result.get('message', '未知错误')}")
lines.append("")
lines.append("" * 18)
lines.append(f"🕒 执行时间: {beijing_time_str()}")
return "\n".join(lines)
def main() -> Dict[str, Any]:
if not ALIYUN_REFRESH_TOKEN:
log_error("未配置 ALIYUN_REFRESH_TOKEN")
return {"success": False, "message": "未配置 refresh_token"}
access_token = get_access_token(ALIYUN_REFRESH_TOKEN)
if not access_token:
return {"success": False, "message": "Token 刷新失败"}
return sign(access_token)
if __name__ == "__main__":
result = main()
report = build_report(result)
notify_send("阿里云盘 签到报告", report)
log_info(f"签到结果: {result}")