-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathtclx.py
More file actions
245 lines (227 loc) · 9.77 KB
/
tclx.py
File metadata and controls
245 lines (227 loc) · 9.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# -*- coding=UTF-8 -*-
# @Project QL_TimingScript
# @fileName tclx.py
# @author Echo
# @EditTime 2025/3/14
# cron: 0 0 9 * * *
# const $ = new Env('同程旅游');
"""
开启抓包,进入app 进入‘领福利’界面,点击签到,查看https://app.17u.cn/welfarecenter/index/signIndex请求头
提取变量: apptoken、device
变量格式: phone#apptoken#device,多个账号用@隔开
"""
import asyncio
import time
from datetime import datetime
import httpx
from fn_print import fn_print
from get_env import get_env
from sendNotify import send_notification_message_collection
tc_cookies = get_env("tc_cookie", "@")
class Tclx:
def __init__(self, cookie):
self.client = httpx.AsyncClient(base_url="https://app.17u.cn/welfarecenter",
verify=False,
timeout=60)
self.phone = cookie.split("#")[0]
self.apptoken = cookie.split("#")[1]
self.device = cookie.split("#")[2]
self.headers = {
'accept': 'application/json, text/plain, */*',
'phone': self.phone,
'channel': '1',
'apptoken': self.apptoken,
'sec-fetch-site': 'same-site',
'accept-language': 'zh-CN,zh-Hans;q=0.9',
'accept-encoding': 'gzip, deflate, br',
'sec-fetch-mode': 'cors',
'origin': 'https://m.17u.cn',
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 TcTravel/11.0.0 tctype/wk',
'referer': 'https://m.17u.cn/',
# 'content-length': str(len(payload_str.encode('utf-8'))),
'device': self.device,
'sec-fetch-dest': 'empty'
}
@staticmethod
async def get_today_date():
return datetime.now().strftime('%Y-%m-%d')
async def sign_in(self):
try:
response = await self.client.post(
url="/index/signIndex",
headers=self.headers,
json={}
)
data = response.json()
if data['code'] != 2200:
fn_print(f"用户【{self.phone}】 - token失效了,请更新")
return None
else:
today_sign = data['data']['todaySign']
mileage = data['data']['mileageBalance']['mileage']
fn_print(f"用户【{self.phone}】 - 今日{'已' if today_sign else '未'}签到,当前剩余里程{mileage}!")
return today_sign
except Exception as e:
fn_print(f"用户【{self.phone}】 - 签到请求异常!{e}")
fn_print(response.text)
return None
async def do_sign_in(self):
today_date = await self.get_today_date()
try:
response = await self.client.post(
url="/index/sign",
headers=self.headers,
json={"type": 1, "day": today_date}
)
data = response.json()
if data['code'] != 2200:
fn_print(f"用户【{self.phone}】 - 签到失败了,尝试获取任务列表")
return False
else:
fn_print(f"用户【{self.phone}】 - 签到成功!开始获取任务列表")
return True
except Exception as e:
fn_print(f"用户【{self.phone}】 - 执行签到请求异常!{e}")
fn_print(response.text)
return False
async def get_task_list(self):
try:
response = await self.client.post(
url="/task/taskList?version=11.0.7",
headers=self.headers,
json={}
)
data = response.json()
if data['code'] != 2200:
fn_print(f"用户【{self.phone}】 - 获取任务列表失败了")
return None
else:
tasks = []
for task in data['data']:
if task['state'] == 1 and task['browserTime'] != 0:
tasks.append(
{
'taskCode': task['taskCode'],
'title': task['title'],
'browserTime': task['browserTime']
}
)
return tasks
except Exception as e:
fn_print(f"用户【{self.phone}】 - 获取任务列表请求异常!{e}")
fn_print(response.text)
return None
async def perform_tasks(self, task_code):
try:
response = await self.client.post(
url="/task/start",
headers=self.headers,
json={"taskCode": task_code}
)
data = response.json()
if data['code'] != 2200:
fn_print(f"用户【{self.phone}】 - 执行任务【{task_code}】失败了,跳过当前任务")
return None
else:
task_id = data['data']
return task_id
except Exception as e:
fn_print(f"用户【{self.phone}】 - 执行任务【{task_code}】请求异常!{e}")
fn_print(response.text)
return None
async def finsh_task(self, task_id):
max_retry = 3 # 最大重试次数
retry_delay = 2 # 重试间隔时间(秒)
for attempt in range(max_retry):
try:
response = await self.client.post(
url="/task/finish",
headers=self.headers,
json={"id": task_id}
)
data = response.json()
if data['code'] == 2200:
fn_print(f"用户【{self.phone}】 - 完成任务【{task_id}】成功!开始领取奖励")
return True
if attempt < max_retry - 1:
fn_print(f"用户【{self.phone}】 - 完成任务【{task_id}】失败了,尝试重新提交(第{attempt + 1}次重试。。)")
await asyncio.sleep(retry_delay * (attempt + 1))
continue
fn_print(f"用户【{self.phone}】 - 完成任务【{task_id}】最终失败,跳过当前任务")
return False
except Exception as e:
error_msg = f"用户【{self.phone}】 - 完成任务【{task_id}】请求异常!{e}"
if 'response' in locals():
error_msg += f"\n{response.text}"
fn_print(error_msg)
if attempt == max_retry - 1:
return False
await asyncio.sleep(retry_delay * (attempt + 1))
async def receive_reward(self, task_id):
try:
response = await self.client.post(
url="/task/receive",
headers=self.headers,
json={"id": task_id}
)
data = response.json()
if data['code'] != 2200:
fn_print(f"用户【{self.phone}】 - 领取签到奖励失败了, 请尝试手动领取")
else:
fn_print(f"用户【{self.phone}】 - 领取签到奖励成功!开始下一个任务")
except Exception as e:
fn_print(f"用户【{self.phone}】 - 领取签到奖励请求异常!{e}")
fn_print(response.text)
async def get_mileage_info(self):
try:
response = await self.client.post(
url="/index/signIndex",
headers=self.headers,
json={}
)
data = response.json()
if data['code'] != 2200:
fn_print(f"用户【{self.phone}】 - 获取积分信息失败了")
return None
else:
cycle_sign_num = data['data']['cycleSighNum']
continuous_history = data['data']['continuousHistory']
mileage = data['data']['mileageBalance']['mileage']
today_mileage = data['data']['mileageBalance']['todayMileage']
fn_print(
f"用户【{self.phone}】 - 本月签到{cycle_sign_num}天,连续签到{continuous_history}天,今日共获取{today_mileage}里程,当前剩余里程{mileage}")
except Exception as e:
fn_print(f"用户【{self.phone}】 - 获取积分信息请求异常!{e}")
fn_print(response.text)
return None
async def run(self):
today_sign = await self.sign_in()
if today_sign is None:
return
if today_sign:
fn_print(f"用户【{self.phone}】 - 今日已签到,开始获取任务列表")
else:
if await self.do_sign_in():
fn_print(f"用户【{self.phone}】 - 签到成功,开始获取任务列表")
tasks = await self.get_task_list()
if tasks:
for task in tasks:
task_code = task['taskCode']
title = task['title']
browser_time = task['browserTime']
fn_print(f"用户【{self.phone}】 - 开始做任务【{title}】,需要浏览{browser_time}秒")
task_id = await self.perform_tasks(task_code)
if task_id:
await asyncio.sleep(browser_time)
if await self.finsh_task(task_id):
await self.receive_reward(task_id)
await self.get_mileage_info()
async def main():
tasks = []
for cookie in tc_cookies:
tclx = Tclx(cookie)
tasks.append(tclx.run())
await asyncio.gather(*tasks)
if __name__ == '__main__':
asyncio.run(main())
send_notification_message_collection(f"同程旅行签到通知 - {datetime.now().strftime('%Y/%m/%d')}")