Skip to content

Commit 00a3461

Browse files
committed
Replace aliyunpan.py with new daily/aliyunpan.py
Remove the old root aliyunpan.py and add a rewritten daily/aliyunpan.py. The new script is a Python3, self-contained signer that supports multiple accounts via the ALIYUN_ACCOUNTS env var (format: refresh_token#name, separated by & or newlines). It adds robust token refresh, sign-in, reward claiming, drive capacity query, logging, simple notify integration, error handling, and randomized delays between accounts for scheduled runs (cron hint included). Uses Bearer auth and updates stored refresh_token from responses.
1 parent fec492b commit 00a3461

2 files changed

Lines changed: 152 additions & 80 deletions

File tree

‎aliyunpan.py‎

Lines changed: 0 additions & 80 deletions
This file was deleted.

‎daily/aliyunpan.py‎

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""
4+
new Env('阿里云盘签到');
5+
cron: 10 6,18 * * *
6+
7+
环境变量说明:
8+
变量名: ALIYUN_ACCOUNTS
9+
格式: refresh_token#备注名 & refresh_token2#备注名2
10+
提示: 多个账号用 & 或 换行 分隔;内部参数用 # 分隔。
11+
进入网页端阿里云盘,按 F12 打开开发者工具,打开控制台输入JSON.parse(localStorage.getItem("token")).refresh_token 然后拼接#备注名即可,例如:
12+
"""
13+
14+
import os
15+
import re
16+
import time
17+
import logging
18+
import requests
19+
import random
20+
from typing import Dict
21+
22+
# ==================== 日志配置 ====================
23+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
24+
logger = logging.getLogger("AliYun")
25+
26+
# ==================== 核心逻辑 ====================
27+
class ALiYun:
28+
def __init__(self, name: str, refresh_token: str):
29+
self.session = requests.Session()
30+
self.name = name
31+
self.refresh_token = refresh_token
32+
self.access_token = ""
33+
self.headers = {
34+
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 AlphaDrive/3.0.0",
35+
"Content-Type": "application/json; charset=utf-8"
36+
}
37+
38+
def _refresh_access_token(self) -> bool:
39+
"""刷新 access_token"""
40+
url = 'https://auth.aliyundrive.com/v2/account/token'
41+
payload = {'grant_type': 'refresh_token', 'refresh_token': self.refresh_token}
42+
try:
43+
res = self.session.post(url, json=payload, timeout=10).json()
44+
if 'access_token' in res:
45+
self.access_token = res['access_token']
46+
self.refresh_token = res['refresh_token'] # 更新持久化的token
47+
return True
48+
logger.error(f"[{self.name}] 刷新 Token 失败: {res.get('message', '未知错误')}")
49+
return False
50+
except Exception as e:
51+
logger.error(f"[{self.name}] 刷新请求异常: {e}")
52+
return False
53+
54+
def check_in(self) -> Dict:
55+
"""执行签到"""
56+
url = 'https://member.aliyundrive.com/v1/activity/sign_in_list'
57+
headers = {**self.headers, "Authorization": f"Bearer {self.access_token}"}
58+
try:
59+
res = self.session.post(url, params={'_rx-s': 'mobile'}, json={'isReward': False}, headers=headers, timeout=10).json()
60+
return res
61+
except Exception as e:
62+
return {"success": False, "message": str(e)}
63+
64+
def get_reward(self, day: int) -> str:
65+
"""领取奖励"""
66+
url = 'https://member.aliyundrive.com/v1/activity/sign_in_reward'
67+
headers = {**self.headers, "Authorization": f"Bearer {self.access_token}"}
68+
try:
69+
res = self.session.post(url, params={'_rx-s': 'mobile'}, json={'signInDay': day}, headers=headers, timeout=10).json()
70+
return res.get('result', {}).get('notice', res.get('message', '未获取到奖励明细'))
71+
except Exception:
72+
return "奖励领取请求异常"
73+
74+
def get_capacity(self) -> str:
75+
"""查询容量"""
76+
def fmt(s): return f"{s/1024/1024/1024:.2f} GB" if s > 0 else "0 GB"
77+
url = 'https://api.aliyundrive.com/adrive/v1/user/driveCapacityDetails'
78+
headers = {**self.headers, "Authorization": f"Bearer {self.access_token}"}
79+
try:
80+
res = self.session.post(url, json={}, headers=headers, timeout=10).json()
81+
return (f"总空间: {fmt(res.get('drive_total_size', 0))}\n"
82+
f"已用空间: {fmt(res.get('drive_used_size', 0))}")
83+
except: return "容量查询失败"
84+
85+
def run(self):
86+
logger.info(f"--- 账号 [{self.name}] 开始签到 ---")
87+
if not self._refresh_access_token():
88+
return f"[{self.name}] ❌ 登录失效"
89+
90+
res = self.check_in()
91+
if not res.get('success'):
92+
return f"[{self.name}] ❌ 签到失败: {res.get('message')}"
93+
94+
count = res.get('result', {}).get('signInCount', 0)
95+
reward_info = self.get_reward(count)
96+
cap_info = self.get_capacity()
97+
98+
msg = (f"【{self.name}】签到成功!\n"
99+
f"本月累计签到: {count} 天\n"
100+
f"本次奖励: {reward_info}\n"
101+
f"{cap_info}")
102+
return msg
103+
104+
# ==================== 通知逻辑 ====================
105+
def send_notify(title, content):
106+
"""简易通知,如果有 notify.py 则尝试调用"""
107+
try:
108+
from notify import send
109+
print(title, content)
110+
except ImportError:
111+
logger.info("\n--- 通知预览 ---\n" + title + "\n" + content)
112+
113+
# ==================== 主入口 ====================
114+
def main():
115+
raw_conf = os.getenv("ALIYUN_ACCOUNTS", "")
116+
if not raw_conf:
117+
logger.error("未找到环境变量 ALIYUN_ACCOUNTS")
118+
return
119+
120+
# 按 & 或 换行 分隔账号
121+
account_list = re.split(r'[&\n]+', raw_conf.strip())
122+
final_reports = []
123+
124+
for idx, acc_str in enumerate(account_list):
125+
if not acc_str.strip(): continue
126+
127+
# 按 # 分隔 token 和 备注
128+
parts = acc_str.split('#')
129+
token = parts[0].strip()
130+
name = parts[1].strip() if len(parts) > 1 else f"账号{idx+1}"
131+
132+
if not token:
133+
logger.warning(f"账号 {name} 缺少 refresh_token,跳过")
134+
continue
135+
136+
client = ALiYun(name, token)
137+
try:
138+
report = client.run()
139+
final_reports.append(report)
140+
except Exception as e:
141+
logger.error(f"运行异常: {e}")
142+
final_reports.append(f"[{name}] 运行发生异常")
143+
144+
# 账号间随机延迟
145+
if idx < len(account_list) - 1:
146+
time.sleep(random.randint(3, 8))
147+
148+
if final_reports:
149+
print("阿里云盘签到报告", "\n" + "="*20 + "\n" + "\n\n".join(final_reports))
150+
151+
if __name__ == "__main__":
152+
main()

0 commit comments

Comments
 (0)