├── .gitignore ├── README.md ├── config.py ├── ecloud.py ├── index.py ├── requirements.txt └── tools.py /.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | __pycache__ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 天翼云签到(云函数版) 2 | 3 | ### 步骤 4 | 5 | 1. 选择 `python3.7`, 改执行方法为 `index.main` 6 | 7 | 2. ctrl + ` 进入终端 8 | 9 | 3. 输入 `pip3 install -r ./src/requirements.txt -t ./src` 安装依赖 (腾讯云函数) 10 | 11 | 华为云函数需要在底下创建依赖 12 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | config = { 2 | "multi": [ 3 | { 4 | "account": "...", 5 | "password": "...", 6 | }, 7 | ], 8 | "push": { 9 | "type": "workWechat", 10 | "key": { 11 | "corpSecret": "slF...", 12 | "corpid": "ww9...", 13 | }, 14 | "agentid": 1000002, 15 | "msgtype": "markdown", 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /ecloud.py: -------------------------------------------------------------------------------- 1 | import random 2 | import requests as req 3 | import rsa 4 | from tools import failed, success, b64ToHex 5 | from base64 import b64encode 6 | from urllib.parse import urlparse, parse_qs 7 | from time import time, sleep 8 | 9 | KEY = "-----BEGIN PUBLIC KEY-----\n<% pubkey %>\n-----END PUBLIC KEY-----" 10 | 11 | BASE_URL = "https://open.e.189.cn" 12 | 13 | 14 | class ecloud: 15 | def __init__(self, **config): 16 | self.account = config.get("account") 17 | self.password = config.get("password") 18 | self.client = req.Session() 19 | self.init() 20 | 21 | def init(self): 22 | resp = req.post( 23 | f"{BASE_URL}/api/logbox/config/encryptConf.do", 24 | data={"appId": "cloud"}, 25 | ).json() 26 | 27 | if resp.get("result") == 0: 28 | success("get encrypt config.") 29 | 30 | pubkey_str = resp.get("data").get("pubKey") 31 | self.pre = resp.get("data").get("pre") 32 | 33 | pubkey = KEY.replace("<% pubkey %>", pubkey_str).encode() 34 | self.pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(pubkey) 35 | else: 36 | failed("can not get encrypt config.") 37 | 38 | @staticmethod 39 | def app_config(lt: str, reqId: str): 40 | resp = req.post( 41 | f"{BASE_URL}/api/logbox/oauth2/appConf.do", 42 | data={"version": 2.0, "appKey": "cloud"}, 43 | headers={"lt": lt, "reqId": reqId}, 44 | ).json() 45 | 46 | if resp.get("result") == "0": 47 | success("get app config.") 48 | else: 49 | failed("get app config.") 50 | 51 | return resp.get("data") 52 | 53 | @staticmethod 54 | def lt_reqid_url(): 55 | resp = req.get( 56 | "https://cloud.189.cn/api/portal/loginUrl.action", 57 | params={"redirectURL": "https://cloud.189.cn/web/redirect.html"}, 58 | allow_redirects=True, 59 | ) 60 | 61 | url = urlparse(resp.url) 62 | query = parse_qs(url.query) 63 | lt = query.get("lt")[0] 64 | reqId = query.get("reqId")[0] 65 | 66 | return lt, reqId, resp.url 67 | 68 | def encrypt(self, s: str): 69 | b = rsa.encrypt(s.encode(), self.pubkey) 70 | return f"{self.pre}{b64ToHex(b64encode(b).decode())}" 71 | 72 | def login(self): 73 | self.lt, self.reqId, url = ecloud.lt_reqid_url() 74 | 75 | resp = ecloud.app_config(self.lt, self.reqId) 76 | 77 | self.headers = { 78 | "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.57", 79 | "origin": "https://open.e.189.cn", 80 | "referer": url, 81 | "lt": self.lt, 82 | "reqid": self.reqId, 83 | } 84 | 85 | data = { 86 | "version": "v2.0", 87 | "apToken": "", 88 | "appKey": "cloud", 89 | "accountType": "01", 90 | "userName": self.encrypt(self.account), 91 | "password": self.encrypt(self.password), 92 | "validateCode": "", 93 | "captchaToken": "", 94 | "returnUrl": resp.get("returnUrl"), 95 | "mailSuffix": "@189.cn", 96 | "dynamicCheck": "FALSE", 97 | "clientType": "1", 98 | "cb_SaveName": "0", 99 | "isOauth2": "false", 100 | "state": "", 101 | "paramId": resp.get("paramId"), 102 | } 103 | 104 | resp = self.client.post( 105 | f"{BASE_URL}/api/logbox/oauth2/loginSubmit.do", 106 | data=data, 107 | headers=self.headers, 108 | timeout=5, 109 | ).json() 110 | 111 | if resp.get("result") == 0: 112 | success(resp.get("msg")) 113 | else: 114 | failed("Login failed.") 115 | 116 | self.client.get(resp.get("toUrl")) 117 | 118 | def checkIn(self): 119 | self.login() 120 | 121 | headers = { 122 | "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X)", 123 | "Referer": "https://m.cloud.189.cn/zhuanti/2016/sign/index.jsp?albumBackupOpened=1", 124 | "Host": "m.cloud.189.cn", 125 | "Accept-Encoding": "gzip, deflate", 126 | } 127 | 128 | resp = self.client.get( 129 | "https://api.cloud.189.cn/mkt/userSign.action", 130 | params={ 131 | "rand": str(round(time() * 1000)), 132 | "clientType": "TELEANDROID", 133 | "version": "8.6.3", 134 | }, 135 | headers=headers, 136 | ).json() 137 | 138 | if "errorCode" in resp: 139 | reward = f"【签到】{resp.get('errorCode')}, {resp.get('errorMsg')}" 140 | failed(reward) 141 | else: 142 | r = resp.get("netdiskBonus") 143 | 144 | if resp.get("isSign"): 145 | reward = f"【已签】获得{r}M空间" 146 | else: 147 | reward = f"【签到】获得{r}M空间" 148 | 149 | success(reward) 150 | 151 | prizes = [] 152 | 153 | urls = [ 154 | "https://m.cloud.189.cn/v2/drawPrizeMarketDetails.action?taskId=TASK_SIGNIN&activityId=ACT_SIGNIN", 155 | "https://m.cloud.189.cn/v2/drawPrizeMarketDetails.action?taskId=TASK_SIGNIN_PHOTOS&activityId=ACT_SIGNIN", 156 | "https://m.cloud.189.cn/v2/drawPrizeMarketDetails.action?taskId=TASK_2022_FLDFS_KJ&activityId=ACT_SIGNIN", 157 | ] 158 | 159 | for idx, u in enumerate(urls): 160 | resp = self.client.get(u, headers=headers).json() 161 | # print(resp) 162 | 163 | if "prizeName" in resp: 164 | p = resp.get("prizeName") 165 | prize = f"【抽奖{idx+1}】{p}" 166 | success(prize) 167 | prizes.append(prize) 168 | else: 169 | if "errorCode" in resp: 170 | p = f"【抽奖{idx+1}】{resp.get('errorCode')}" 171 | errorMsg = resp.get("errorMsg") 172 | failed(p, errorMsg) 173 | prizes.append(p) 174 | elif "error" in resp: 175 | p = f"【抽奖{idx+1}】{resp.get('error')}" 176 | failed(p) 177 | prizes.append(p) 178 | 179 | sleep(random.randint(5, 10)) 180 | 181 | return { 182 | "reward": reward, 183 | "prizes": prizes, 184 | } 185 | 186 | def start(self): 187 | res = self.checkIn() 188 | 189 | msg = [ 190 | { 191 | "h4": { 192 | "content": "天翼云盘签到小助手", 193 | }, 194 | "txt": { 195 | "content": f"【账号】{self.account}", 196 | }, 197 | }, 198 | { 199 | "txt": { 200 | "content": res.get("reward"), 201 | }, 202 | }, 203 | ] 204 | 205 | for p in res["prizes"]: 206 | msg.append( 207 | { 208 | "txt": { 209 | "content": p, 210 | } 211 | } 212 | ) 213 | 214 | return {"title": "天翼云盘签到小助手", "message": msg} 215 | -------------------------------------------------------------------------------- /index.py: -------------------------------------------------------------------------------- 1 | from ecloud import ecloud 2 | from config import config 3 | from push_tools import push_creator 4 | from dict2str import dict2str 5 | 6 | 7 | def parse_message(message, msg_type): 8 | print(dict2str(message, type=msg_type)) 9 | return str(dict2str(message, type=msg_type)) 10 | 11 | 12 | def push_message(message, push_config): 13 | if isinstance(push_config, list): 14 | 15 | for item in push_config: 16 | t = item.get("type") 17 | p = push_creator(t, item.get("key")) 18 | m = item.get("msgtype") or item.get("template", "markdown") 19 | 20 | item.pop("type") 21 | item.pop("key") 22 | 23 | msg = parse_message(message, m) 24 | p.send(msg, title=message["title"], **item) 25 | else: 26 | t = push_config.get("type") 27 | p = push_creator(t, push_config.get("key")) 28 | m = push_config.get("msgtype") or push_config.get("template", "markdown") 29 | 30 | push_config.pop("type") 31 | push_config.pop("key") 32 | 33 | msg = parse_message(message["message"], m) 34 | p.send(msg, title=message["title"], **push_config) 35 | 36 | 37 | def main(*_): 38 | configs = config.get("multi") 39 | push_together = config.get("push") 40 | 41 | messages = [] 42 | 43 | for conf in configs: 44 | obj = ecloud(**conf) 45 | 46 | res = obj.start() 47 | 48 | push = conf.get("push") 49 | 50 | if push is None: 51 | if push_together is not None: 52 | messages.append(res) 53 | else: 54 | push_message(res, push) 55 | 56 | if len(messages) != 0 and push_together is not None: 57 | m = [] 58 | for msg in messages: 59 | m.extend(msg["message"]) 60 | 61 | msg = {"title": messages[0]["title"], "message": m} 62 | push_message(msg, push_together) 63 | 64 | 65 | if __name__ == "__main__": 66 | main() 67 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcturus-script/ecloud/b169518d68a1a54d74f09f312225a7b591ebc7ed/requirements.txt -------------------------------------------------------------------------------- /tools.py: -------------------------------------------------------------------------------- 1 | import string 2 | 3 | 4 | def _chr(a): 5 | return f"{string.digits}{string.ascii_lowercase}"[a] 6 | 7 | 8 | b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" 9 | 10 | 11 | def b64ToHex(a): 12 | d = "" 13 | e = 0 14 | c = 0 15 | for i in range(len(a)): 16 | if list(a)[i] != "=": 17 | v = b64map.index(list(a)[i]) 18 | if 0 == e: 19 | e = 1 20 | d += _chr(v >> 2) 21 | c = 3 & v 22 | elif 1 == e: 23 | e = 2 24 | d += _chr(c << 2 | v >> 4) 25 | c = 15 & v 26 | elif 2 == e: 27 | e = 3 28 | d += _chr(c) 29 | d += _chr(v >> 2) 30 | c = 3 & v 31 | else: 32 | e = 0 33 | d += _chr(c << 2 | v >> 4) 34 | d += _chr(15 & v) 35 | if e == 1: 36 | d += _chr(c << 2) 37 | return d 38 | 39 | 40 | def failed(*args, **kwargs): 41 | print("[\033[31mfailed\033[0m] ", end="") 42 | print(*args, **kwargs) 43 | 44 | 45 | def success(*args, **kwargs): 46 | print("[\033[32msuccess\033[0m] ", end="") 47 | print(*args, **kwargs) 48 | 49 | 50 | def info(*args, **kwargs): 51 | print("[\033[34minfo\033[0m] ", end="") 52 | print(*args, **kwargs) 53 | --------------------------------------------------------------------------------