Repository navigation
Expand file tree
/
Copy pathoppo.py
More file actions
1316 lines (1155 loc) · 59.4 KB
/
Copy pathoppo.py
File metadata and controls
1316 lines (1155 loc) · 59.4 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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
File: OPPO.py(OPPO签到)
Author-original: ytt447735
Author: sjmy
cron: 15 8 * * *
new Env('OPPO签到');
getenv name: OPPO_COOKIE
getenv value: 账号1 TOKENSID#账号1 session_id&账号2 TOKENSID#账号2 session_id&...
请阅读 `Problem-3` 进行配置session_id
Update: 2025/08/10
Description:
1. 新增了token使用期限检查功能,支持多账号签到
2. 增加了OPPO会员、OPPO商城的微信小程序签到
3. 增加了OPPO商城、OPPO社区、钱包(代码不完善)、我的一加、一加社区、阅读的签到
4. 累计签到会自动领取
5. 任务列表会自动执行去完成(目前就只做了简单的跳转的、开启通知、预约的任务)
6. OPPO商城微信小程序自动抽奖
7. OPPO社区点赞帖子任务自动执行
Problem:
1. 可能会出现签到失败的情况,需要手动检查
2. 钱包的签到出了点问题,可能无法签到
3. OPPO会员小程序签到,今日积分收入统计不是依赖token,依赖的是sessionId,需要手动获取,如果不执行相应的流程,可把session_id留空
Future:
0. 牙膏要一点一点挤,显卡要一刀一刀切,代码要一点一点写,生活要一点一点过,预计亿年内完成。
1. OPPO商城网站签到未完成.(验证会每天更换,非常困难,估计完不成)
2. 主题商店签到、装扮萌宠养成未完成。(任务太多,类型太杂,一时间分析不过来)
3. 阅读APP里累计阅读功能未实现。(还未找到具体的请求逻辑,初步判断有加密)
4.
"""
import base64
import json
import os
import re
import time
from datetime import datetime
import requests
import ujson
import notify
# 定义 ActivityInfo 类
class ActivityInfo:
def __init__(self, activityName, apkPkg, activityId, creditsAddActionId, business, s_channel):
"""
初始化 ActivityInfo 类的实例。
:param activityName: 活动名称
:param apkPkg: APK 包名
:param activityId: 活动 ID
:param creditsAddActionId: 积分增加动作 ID
:param business: 业务信息
:param s_channel: 设备信息
"""
self.activityName = activityName
self.apkPkg = apkPkg
self.activityId = activityId
self.creditsAddActionId = creditsAddActionId
self.business = business
self.s_channel = s_channel
def toJson(self):
"""
将对象转换为不包含活动名称的 JSON 格式的字符串。
:return: JSON 格式的字符串
"""
# 创建一个不包含 activityName 的字典
data = {
"activityId": self.activityId,
"creditsAddActionId": self.creditsAddActionId,
"business": self.business
}
return json.dumps(data, ensure_ascii=False)
# 定义 APP 类
class APP :
def __init__(self, encryptedId, apkPkg, creditsAddActionId, business, s_channel, source_type):
"""
初始化 APP 类的实例。
:param encryptedId: 加密 ID
:param apkPkg: APK 包名
:param creditsAddActionId: 积分增加动作 ID
:param business: 业务信息
:param s_channel: 设备信息
:param source_type: 来源类型
"""
self.encryptedId = encryptedId
self.apkPkg = apkPkg
self.creditsAddActionId = creditsAddActionId
self.business = business
self.s_channel = s_channel
self.source_type = source_type
class OPPO:
def __init__(self):
self.Log = ""
# self.set_log("🤖运行了__init__")
self.ck = ''
self.apkPkg = 'com.oppo.store'
self.UA = 'Mozilla/5.0 (Linux; Android 15; PJD110 Build/AP3A.240617.008; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/130.0.6723.58 Mobile Safari/537.36 ColorOS/V15.0.0 brand/OnePlus model/PJD110'
# 修改为任务活动对象列表
self.activityId_taskActivityInfo = []
self.activity_list = []
self.session_id = ''
self.appList = []
# 一加社区签到
def bbsSign(self):
# self.set_log("🤖运行了 bbsSign")
url = "https://bbs-api-cn.oneplus.com/task/api/sign/v1/create"
params = {
'ver': "bbs44102",
'timestamp': int(round(time.time() * 1000)),
# 'sign': "9ca3735c9d81a55663e6659b282afadb1b9dea4595cd4fedb3597c7f57a1c9ef"
}
headers = {
'User-Agent': "bbs/android/bbs44102",
'Accept-Encoding': "gzip",
'model': "PJD110",
'osver': "android15",
'romv': "PJD110_15.0.0.701(CN01)",
'lang': "zh-CN",
'token': f"TOKEN_{self.ck}",
'tz': "Asia/Shanghai"
}
response = requests.post(url, params=params, headers=headers)
# self.set_log(response.text)
try:
j = ujson.loads(response.text)
if j["code"] == 200:
if 'todaySigned' in j["data"]:
self.set_log('➖今天已经签到过啦!')
else:
self.set_log('🎉`今天签到成功!`')
self.set_log('📝累计签到:`' + str(j['data']['signDays']) + '`天')
self.set_log('📝连续签到:`' + str(j['data']['continuousSignDays']) + '`天')
self.set_log('📝再连续签到`' + str(j['data']['extSignDays']) + '`天,可额外获得' + str(
j['data']['extCredit']) + '积分')
else:
self.set_log(f"❌一加社区签到失败,`{j['msg']}`")
except (KeyError, ValueError):
self.set_log(f"💥一加社区签到失败,解析响应数据出错{response.text}")
# 钱包签到
def continueSign(self):
# self.set_log("🤖运行了 continueSign")
url = "https://hwallet.finzfin.com/act/usersign/v1/continueSign"
payload = ujson.dumps({
"actId": "AID202207111442220933",
"funcId": "CONTINUEV2202209161649037309"
})
headers = {
'User-Agent': self.UA,
'Accept': "application/json;charset=UTF-8",
'Content-Type': "application/json",
'x-token': f"TOKEN_{self.ck}",
}
response = requests.post(url, data=payload, headers=headers)
# response = requests.request("POST", url, headers=headers, data=payload)
# self.set_log("continueSign", response.text)
try:
j = ujson.loads(response.text)
if j.get("success"):
award_name = j["data"]["name"]
self.set_log(f"🎉签到成功,获得`{award_name}`")
else:
error_msg = j["error"]["msg"]
self.set_log(f"❌签到失败,`{error_msg}`")
except (KeyError, ValueError):
self.set_log(f"💥签到失败,解析响应数据出错 {response.text} ")
# 阅读签到
def zhangyueSign(self):
# self.set_log("🤖运行了 zhangyueSign")
zhangyueUSR = "i4791337318"
url = f"https://webboot.zhangyue.com/zycl/newwelfare/sign?usr={zhangyueUSR}"
headers = {
'User-Agent': self.UA,
}
response = requests.get(url, headers=headers)
try:
j = ujson.loads(response.text)
if j["code"] == 0:
# 签到成功,返回 signTitle 的结果
self.set_log(f'🎉`{j["body"]["signTitle"]}`')
else:
# 其他错误情况
self.set_log(f"➖阅读签到失败:`{j['msg']}`")
except (KeyError, ValueError):
self.set_log(f"💥阅读签到失败,解析响应数据出错{response.text}")
# OPPO会员小程序签到
def oppo_member_app_sign(self):
# self.set_log("🤖运行了 oppo_member_app_sign")
url = f"https://omoapplet-api-cn.heytap.com/activity/signIn/daily?sessionId={self.session_id}&version=2"
headers = {
'User-Agent': self.UA
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = json.loads(response.text)
if data["ret"] == "1":
# 签到成功
integral = data.get("data", {}).get("integral", 0)
self.set_log(f"\u2705 OPPO会员小程序签到成功,获得`{integral}`积分")
return True
elif data["ret"] == "0" and data.get("errCode") == "214000023":
# 已经签到过
self.set_log(f"➖ OPPO会员小程序今日已签到: {data.get('errMsg', '奖励已发放')}")
return True
else:
self.set_log(f"❌ OPPO会员小程序签到失败: {data.get('errMsg', '未知错误')}")
return False
except requests.exceptions.RequestException as e:
self.set_log(f"💥 OPPO会员小程序签到请求失败: {e}")
except json.JSONDecodeError as e:
self.set_log(f"💥 解析OPPO会员小程序签到结果失败: {e}")
except Exception as e:
self.set_log(f"💥 OPPO会员小程序签到过程中出现未预期的错误: {e}")
return False
# 获取签到渠道ID和活动ID
def get_activityId(self, app:APP):
# self.set_log("🤖运行了get_activityId")
url = f'https://hd.opposhop.cn/bp/{app.encryptedId}?nightModelEnable=true&us=wode&um=qiandaobanner'
headers = {
'Cookie': f"apkPkg={app.apkPkg}; TOKENSID=TOKEN_{self.ck}",
'User-Agent': self.UA
}
response = requests.request("GET", url, headers=headers)
# 确保响应使用UTF-8编码
response.encoding = 'utf-8'
# 初始化活动列表(如果还没有初始化)
# if not hasattr(self, 'activity_list') or self.activity_list is None:
# self.activity_list = []
# 获取所有的活动ID和活动名称
# 尝试匹配 "activityInfo":{"activityId":"1938150025645531136","activityName":"金钻会员-每日签到-商城客户端(25年7月)"}
activity_pattern = r'"activityInfo":{"activityId":"(\d+)","activityName":"([^"]+)"'
activity_matches = re.findall(activity_pattern, response.text)
# 如果上面的正则表达式没有匹配到,尝试另一种格式
if not activity_matches:
self.set_log("🈚️没找到,尝试另一种格式")
# 尝试匹配 "activityId":"1938150025645531136","activityName":"金钻会员-每日签到-商城客户端(25年7月)"
alt_pattern = r'"activityId":"(\d+)","activityName":"([^"]+)"'
activity_matches = re.findall(alt_pattern, response.text)
if activity_matches:
# self.set_log("======================================================")
self.set_log(f"🤓👆🏻找到`{len(activity_matches)}`个活动:")
# 创建一个集合来存储已经添加的活动ID,避免重复
existing_activity_ids = {activity.activityId for activity in self.activity_list}
for i, (activity_id, activity_name) in enumerate(activity_matches):
# 对活动名称进行解码,处理中文字符
# 使用json.loads来解码转义的Unicode字符
try:
decoded_name = json.loads(f'"{activity_name}"')
except json.JSONDecodeError:
# 如果json解码失败,尝试使用正则表达式替换Unicode转义序列
self.set_log("💥json解码失败,尝试进行正则表达式替换Unicode转义序列")
decoded_name = re.sub(r'\\u([0-9a-fA-F]{4})', lambda m: chr(int(m.group(1), 16)), activity_name)
if decoded_name == activity_name: # 如果没有变化,可能不是Unicode转义
decoded_name = activity_name
self.set_log(f"🤓👆🏻活动 {i + 1}: `{decoded_name}`")
# self.set_log(f"🤓👆🏻活动 {i+1}ID: {activity_id}")
# 检查活动ID是否已经存在于活动列表中
if activity_id not in existing_activity_ids:
# 将活动添加到活动列表
self.activity_list.append(
ActivityInfo(
decoded_name, # 使用解码后的名称
app.apkPkg, # 使用默认的积分增加动作ID
activity_id,
app.creditsAddActionId, # 使用默认的积分增加动作ID
app.business, # 默认业务类型为1
app.s_channel # 默认渠道(对应s_channel)
)
)
existing_activity_ids.add(activity_id)
else:
self.set_log(f"🔄活动:`{decoded_name}`已存在于活动列表中,跳过添加")
# self.set_log(f"🔄活动:{decoded_name} ID {activity_id} 已存在于活动列表中,跳过添加")
# self.set_log("======================================================")
else:
self.set_log(f"❌签到失败,未找到活动ID和活动名称!")
# 获取活动任务 ID
task_activity_pattern = r'"taskActivityInfo":{"activityId":"(\d+)"(?:,"activityName":"([^"]*)")?'
task_activity_matches = re.findall(task_activity_pattern, response.text)
if task_activity_matches:
# 创建一个集合来存储已经添加的任务活动ID,避免重复
existing_task_activity_ids = {task_activity.activityId for task_activity in
self.activityId_taskActivityInfo}
for i, (task_id, activity_name) in enumerate(task_activity_matches):
# 如果没有找到活动名称,使用默认名称
activity_name = activity_name if activity_name else f"任务活动{i + 1}"
# 尝试解码活动名称
try:
decoded_name = json.loads(f'"{activity_name}"')
except json.JSONDecodeError:
decoded_name = re.sub(r'\\u([0-9a-fA-F]{4})', lambda m: chr(int(m.group(1), 16)), activity_name)
if decoded_name == activity_name: # 如果没有变化,可能不是Unicode转义
decoded_name = activity_name
if task_id not in existing_task_activity_ids:
# 将任务活动添加到列表
self.activityId_taskActivityInfo.append(
ActivityInfo(
decoded_name, # 活动名称
app.apkPkg, # 使用该app默认apkpkg
task_id, # 活动ID
"", # task 不需要此字段
app.source_type, # 使用该app默认类型
app.s_channel # 该app默认渠道
)
)
existing_task_activity_ids.add(task_id)
self.set_log(f"\u2705已添加活动任务:`{decoded_name}`到列表")
# self.set_log(f"\u2705已添加活动任务: {decoded_name}, ID: {task_id} 到列表")
# else:
# self.set_log(f"🔄活动任务 : {decoded_name} 已存在于列表中,跳过添加")
# self.set_log(f"🔄活动任务 ID: {task_id} 已存在于列表中,跳过添加")
# self.set_log(f"⏩当前活动任务列表: {[task.activityName for task in self.activityId_taskActivityInfo]}")
# self.set_log(f"⏩当前活动任务列表: {[task.activityId for task in self.activityId_taskActivityInfo]}")
else:
self.set_log("❌获取活动任务 ID 获取失败")
# for activity in self.activity_list:
# self.set_log("activity.activityName", activity.activityName)
# self.set_log("activity.activityId", activity.activityId)
# 各渠道签到
def shopping_signIn(self, activity):
# self.set_log("🤖运行了 shopping_signIn")
url = "https://hd.opposhop.cn/api/cn/oapi/marketing/cumulativeSignIn/signIn"
payload = activity.toJson() # 直接使用toJson方法返回的JSON字符串
headers = {
's_channel': activity.s_channel,
'Cookie': f"apkPkg={self.apkPkg}; TOKENSID=TOKEN_{self.ck}",
'User-Agent': self.UA,
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
try:
j = ujson.loads(response.text)
if j["code"] == 200:
awardType = j['data']['awardType']
awardValue = j['data']['awardValue']
if awardType == 1:
self.set_log(f"🎉{activity.activityName} 签到成功,奖励`{awardValue}`积分")
elif j["code"] == 5008: # 5008 表示已经签到过了
self.set_log(f"➖{activity.activityName} : `{j['message']}`")
else:
message = j['message']
self.set_log(f"❌{activity.activityName} 签到失败,`{message}`")
except (KeyError, ValueError):
self.set_log(f"💥{activity.activityName} APP: 解析响应数据出错,可能是登录已失效 {response.text} ")
time.sleep(2) # 添加间隔时间,避免请求过快
# 获取累计签到列表
def check_cumulative_sign_in(self, activity):
# self.set_log(f"🤖运行了 check_cumulative_sign_in ")
self.set_log(f"👀检查`{activity.activityName}`累计签到情况")
url = f"https://hd.opposhop.cn/api/cn/oapi/marketing/cumulativeSignIn/getSignInDetail?activityId={activity.activityId}"
headers = {
'Accept': 'application/json, text/plain, */*',
'User-Agent': self.UA,
'Cookie': f"apkPkg={activity.apkPkg}; TOKENSID=TOKEN_{self.ck}"
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status() # 检查HTTP错误
j = json.loads(response.text)
if j["code"] == 200: # 正常响应
data = j["data"]
# 显示当前签到情况
today_signed = data.get("todaySignIn", False)
if not today_signed: # 今日未签到
self.set_log(f"❌ {activity.activityName} 今日未签到")
self.shopping_signIn(activity)
time.sleep(2) # 等待2秒,确保签到成功,重新获取数据
response = requests.get(url, headers=headers)
j = json.loads(response.text)
data = j["data"]
today_signed = data.get("todaySignIn", False)
sign_in_day_num = data.get("signInDayNum", 0)
self.set_log(f"📊 {activity.activityName} 当前已累计签到`{sign_in_day_num}`天")
self.set_log(f"📅 今日是否已签到: `{'是' if today_signed else '否'}`")
# # 显示基础签到奖励列表
# if "baseAwards" in data:
# self.set_log("🔄 每日签到奖励列表:")
# for award in data["baseAwards"]:
# sign_time = award.get("signTime", "未知")
# award_type = self._get_award_type_text(award.get("awardType"))
# award_value = award.get("awardValue", "未知")
# status = award.get("status", 0)
# status_text = "已领取" if status == 1 else "未达成" if status == 0 else "可领取"
# self.set_log(f" - {sign_time}: {award_type} x {award_value} ({status_text})")
# 处理累计签到奖励列表
if "cumulativeAwards" in data:
cumulative_awards = data["cumulativeAwards"]
# self.set_log("🎁 累计签到奖励列表:")
# 检查是否有可领取的奖励
has_available_award = False
for award in cumulative_awards:
sign_day_num = award.get("signDayNum", 0)
award_id = award.get("awardId", 0)
award_type = self._get_award_type_text(award.get("awardType"))
award_value = award.get("awardValue", "未知")
status = award.get("status", 0)
status_text = "➖已领取" if status == 1 else "❌未达成" if status == 0 else "✅可领取"
# 累计签到列表详情
# self.set_log(f" - 累计 {sign_day_num} 天: {award_type} x {award_value}`{status_text}`")
# 如果有可领取的奖励,自动领取
if status == 2: # 可领取状态
has_available_award = True
self.set_log(
f"🎉 发现可领取的累计签到奖励: `累计 {sign_day_num} 天 {award_type} x {award_value}`")
self.draw_cumulative_award(activity, award_id)
if not has_available_award:
self.set_log("➖ 暂无累计签到奖励可领取")
return True
else:
self.set_log(f"❌获取累计签到列表失败:{j.get('errorMessage', '未知错误')}")
return False
except requests.exceptions.RequestException as e:
self.set_log(f"💥请求失败: {e}")
except json.JSONDecodeError as e:
self.set_log(f"💥解析响应数据失败: {e}")
except KeyError as e:
self.set_log(f"💥处理响应数据时出错: {e}")
except Exception as e:
self.set_log(f"💥未预期的错误: {e}")
if 'response' in locals():
self.set_log(f"响应内容: {response.text[:200]}...") # 只显示前200个字符,避免日志过长
return False
# 领取累计签到奖励
def draw_cumulative_award(self, activity, award_id):
# self.set_log(f"🤖运行了 draw_cumulative_award ")
self.set_log(f"🔜领取`{activity.activityName}`累计签到奖励")
url = "https://hd.opposhop.cn/api/cn/oapi/marketing/cumulativeSignIn/drawCumulativeAward"
payload = {
"activityId": activity.activityId,
"awardId": award_id,
"creditsAddActionId": activity.creditsAddActionId,
"business": activity.business
}
headers = {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json',
'User-Agent': self.UA,
'Cookie': f"apkPkg={activity.apkPkg}; TOKENSID=TOKEN_{self.ck}"
}
try:
response = requests.post(url, json=payload, headers=headers)
response.raise_for_status() # 检查HTTP错误
j = json.loads(response.text)
if j["code"] == 200: # 正常响应
data = j["data"]
award_type = self._get_award_type_text(data.get("awardType"))
award_value = data.get("awardValue", "未知")
sign_day_num = data.get("signInDayNum", 0)
self.set_log(
f"🎉 累计签到奖励领取成功! 您已累计签到·`{sign_day_num}`天,获得`{award_type} x {award_value}`")
return True
elif j["code"] == 5013: # 重复领取
self.set_log(f"ℹ️ {j.get('errorMessage', '累计奖励已领取,重复领取')}")
return False
else:
self.set_log(f"❌领取累计签到奖励失败:{j.get('errorMessage', '未知错误')}")
return False
except requests.exceptions.RequestException as e:
self.set_log(f"💥请求失败: {e}")
except json.JSONDecodeError as e:
self.set_log(f"💥解析响应数据失败: {e}")
except KeyError as e:
self.set_log(f"💥处理响应数据时出错: {e}")
except Exception as e:
self.set_log(f"💥未预期的错误: {e}")
if 'response' in locals():
self.set_log(f"响应内容: {response.text[:200]}...") # 只显示前200个字符,避免日志过长
return False
# 获取奖励类型文本
def _get_award_type_text(self, award_type):
# 将奖励类型转换为文字
if award_type == 1:
return "积分"
elif award_type == 2:
return "优惠券"
elif award_type == 3:
return "抽奖机会"
else:
return f"奖励({award_type})"
# 获取任务列表
def get_task(self, task_activity):
# self.set_log("🤖运行了 get_task")
url = f"https://hd.opposhop.cn/api/cn/oapi/marketing/task/queryTaskList?activityId={task_activity.activityId}&source=c"
payload = {}
headers = {
'Cookie': f"apkPkg={task_activity.apkPkg}; TOKENSID=TOKEN_{self.ck}",
'Accept': 'application/json, text/plain, */*',
's_channel': task_activity.s_channel,
'source_type': str(task_activity.business),
'User-Agent': self.UA
}
response = requests.request("GET", url, headers=headers, data=payload)
# self.set_log("get_task", response.text)
try:
j = ujson.loads(response.text)
if j["code"] == 200:
# self.set_log(f"🤓👆🏻获取任务列表成功")
activity_name = j["data"]["activityName"]
# 更新活动名称,如果API返回的名称不为空
if activity_name and activity_name.strip():
task_activity.activityName = activity_name
self.set_log(f"⏩正在执行任务列表:`{task_activity.activityName}`")
# self.set_log(f"⏩正在执行任务列表:`{task_activity.activityId}`")
for i, element in enumerate(j["data"]["taskDTOList"]):
taskName = element['taskName']
taskId = element['taskId']
activityId = element['activityId']
taskType = element['taskType'] # 1=浏览,4=预约, 6=开卡/购买
taskStatus = element['taskStatus'] # 是否完成 1=未完成,2=可领取,3=已领取
# self.set_log(f"🤓👆🏻获取到任务:{taskName},任务ID:{taskId},活动ID:{activityId},任务类型:{taskType},任务状态:{taskStatus},skuId:{skuId}")
if taskStatus == 1: # 未完成
self.set_log(f"🤓👆🏻`{taskName}` 任务还未完成,即将执行:")
# 这里写判断类型,并进行相应的操作:
# 5:预约直播,6:购买商品,10:预约任务,14:学生认证,15:关注公众号,
# 17:首单付费,18:内容点赞,23:打开通知
if taskType in [1, 3, 9, 16, 17]: # 经典提交任务即可领取奖励类型
self.task_signInOrShareTask(taskName, taskId, activityId)
elif taskType in [4,10]: # 预约任务
skuId = ''
if element['attachConfigTwo']:
attachConfigTwo_link = element['attachConfigTwo']['link']
match = re.search(r'skuId=(\d+)', attachConfigTwo_link)
if match:
skuId = match.group(1)
# self.set_log(f"skuId={skuId}")
self.subscribes(skuId, taskName, taskId, activityId)
elif taskType in [5]: # 预约直播
stream_id = element["actionUrl"].split("StreamId=")[1]
self.liveSubscribe(stream_id, taskName, taskId, activityId)
elif taskType in [23]: # 打开通知任务
self.PushSwitch(activityId, False) # 关闭通知
self.PushSwitch(activityId, True) # 打开通知
self.task_receiveAward(taskName, taskId, activityId) # 领取奖励
elif taskType in [18]: # 内容点赞
self.thumbsupList() # 点赞
self.task_receiveAward(taskName, taskId, activityId) # 领取奖励
else: # 6:购买商品,
self.set_log(
f"❌`{taskName}`任务执行失败,未分配类型:{taskType}=>{element['taskTypeName']}")
elif taskStatus == 2: # 可领取
self.set_log(f"⏬`{taskName}`任务已完成,即将领取奖励:")
self.task_receiveAward(taskName, taskId, activityId)
elif taskStatus == 3: # 已领取
self.set_log(f"➖`{taskName}`任务已完成,无需再执行签到。")
# 等待完善输出逻辑
elif taskStatus == 6: # 已领光
self.set_log(f"➖`{taskName}`任务已领光。")
else:
self.set_log(f"❌`{taskName}`任务状态未知")
time.sleep(2)
else:
self.set_log(f"⚠️获取任务列表失败,`{j['message']}`")
except (KeyError, ValueError):
self.set_log(f"💥获取任务列表失败,解析响应数据出错,可能是登录已失效 {response.text} ")
# 这个OPPO商城的任务在APP里面和小程序里面显示的不一样,特此进行特别处理一下
if task_activity.s_channel == 'oppo_appstore':
task_activity.s_channel = 'program_wx'
task_activity.business = 503
self.get_task(task_activity)
# 提交任务
def task_signInOrShareTask(self, taskName, taskId, activityId):
# self.set_log("🤖运行了 task_signInOrShareTask")
url = f"https://hd.opposhop.cn/api/cn/oapi/marketing/taskReport/signInOrShareTask?taskId={taskId}&activityId={activityId}&taskType=1"
payload = {}
headers = {
'Cookie': f"apkPkg={self.apkPkg}; TOKENSID=TOKEN_{self.ck}",
'Accept': 'application/json, text/plain, */*',
'User-Agent': self.UA
}
response = requests.request("GET", url, headers=headers, data=payload)
# self.set_log("task_signInOrShareTask", response.text)
try:
j = ujson.loads(response.text)
if j["code"] == 200:
self.task_receiveAward(taskName, taskId, activityId)
else:
message = j['message']
self.set_log(f"❌{taskName} 任务提交失败,{message}")
except (KeyError, ValueError):
self.set_log(f"💥{taskName} 任务提交失败,解析响应数据出错,可能是登录已失效 {response.text} ")
# 领取任务奖励
def task_receiveAward(self, taskName, taskId, activityId):
# self.set_log("🤖运行了 task_receiveAward")
url = f"https://hd.opposhop.cn/api/cn/oapi/marketing/task/receiveAward?taskId={taskId}&activityId={activityId}"
payload = {}
headers = {
'Cookie': f"apkPkg={self.apkPkg}; TOKENSID=TOKEN_{self.ck}",
'Accept': 'application/json, text/plain, */*',
'User-Agent': self.UA
}
response = requests.request("GET", url, headers=headers, data=payload)
# self.set_log("task_receiveAward", response.text)
try:
j = ujson.loads(response.text)
if j["code"] == 200:
awardType = j['data']['awardType']
awardValue = j['data']['awardType']
if awardType == 1:
self.set_log(f"🎉`{taskName}`任务完成,奖励`{awardValue}`积分")
else:
self.set_log(f"❌`{taskName}`任务失败,`{j['message']}`")
except (KeyError, ValueError):
self.set_log(f"💥`{taskName}` 任务失败,解析响应数据出错,可能是登录已失效: {response.text} ")
# 预约任务
def subscribes(self, skuId, taskName, taskId, activityId):
# self.set_log("🤖运行了 subscribes")
url = "https://msec.opposhop.cn/goods/web/subscribes/goodsSubscribeV1"
payload = f"type=1&skuId={skuId}"
headers = {
'Cookie': f"apkPkg={self.apkPkg}; TOKENSID=TOKEN_{self.ck}",
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'okhttp/4.9.3.6'
}
response = requests.post(url, data=payload, headers=headers)
# response = requests.request("POST", url, headers=headers, data=payload)
# self.set_log("subscribes", response.text)
j = ujson.loads(response.text)
if j["code"] == 200:
self.task_receiveAward(taskName, taskId, activityId)
else:
message = j['errorMessage']
self.set_log(f"❌{taskName} 预约失败,{message}")
# 直播预约任务
def liveSubscribe(self, streamId, taskName, taskId, activityId):
# self.set_log("🤖运行了 liveSubscribe")
url = "https://msec.opposhop.cn/live/app/lives/subscribeV1"
payload = {'streamId': streamId}
headers = {
'Cookie': f"apkPkg={self.apkPkg}; TOKENSID=TOKEN_{self.ck}",
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'okhttp/4.9.3.6'
}
response = requests.post(url, data=payload, headers=headers)
# response = requests.request("POST", url, headers=headers, data=payload)
# self.set_log("liveSubscribe", response.text)
j = ujson.loads(response.text)
if j["code"] == 200:
if j["data"]["isSubscribe"]:
self.set_log(f"❌{taskName}:{j['data']['message']}")
else:
self.set_log(f"✅{taskName}:直播预约成功")
self.task_receiveAward(taskName, taskId, activityId)
else:
self.set_log(f"❌{taskName} 预约失败,{j['errorMessage']}")
# 打开通知
def PushSwitch(self, activityId, Switch):
# self.set_log("🤖运行了 PushSwitch")
url = f"https://hd.opposhop.cn/api/cn/oapi/marketing/userEvent/openPushSwitch?activityId={activityId}&eventType={5 if Switch else 4}"
headers = {
'User-Agent': self.UA,
'Accept': "application/json, text/plain, */*",
'Cookie': f"apkPkg={self.apkPkg}; TOKENSID=TOKEN_{self.ck}"
}
response = requests.get(url, headers=headers)
try:
j = ujson.loads(response.text)
self.set_log(f"{'✅打开' if Switch else '关闭'}通知权限:`{j['message']}`")
except (KeyError, ValueError):
self.set_log(f"💥签到失败,解析响应数据出错 {response.text} ")
# 获取点赞列表
def thumbsupList(self):
# self.set_log("🤖运行了 thumbsupList")
url = "https://hd.opposhop.cn/api/cn/oapi/java/ugc/frontend/hot/thread/v1/list?contentId=30&viewType=2&dataType=2&limit=10&page=1"
headers = {
'User-Agent': self.UA,
'Accept': "application/json, text/plain, */*",
'sa_distinct_id': "MEZ5RTA0N2REY3BWcXBZdmxSSzQ5QT09, MEZ5RTA0N2REY3BWcXBZdmxSSzQ5QT09",
'Cookie': f"apkPkg=com.oppo.community; TOKENSID=TOKEN_{self.ck}"
}
response = requests.get(url, headers=headers)
try:
j = ujson.loads(response.text)
if j["code"] == 200:
# self.set_log("\u2705获取点赞列表成功")
for row in j["data"]["rows"]:
tid = row["threadBaseInfoVO"]["tid"]
uid = row["author"]["uid"]
praise_status = row["praiseStatus"]
# self.set_log(f"⏩准备点赞帖子 tid: {tid}, uid: {uid}")
self.thumbsup(tid, uid)
if praise_status != 0: # 0 表示未点赞
# self.set_log(f"\u2705帖子 tid: {tid} 已点赞,正在取消并再次签到")
self.thumbsup(tid, uid)
else:
self.set_log(f"❌获取点赞列表失败,{j['msg']}")
except (KeyError, ValueError):
self.set_log(f"💥获取点赞列表失败,解析响应数据出错 {response.text} ")
# 点赞
def thumbsup(self, tid, uid):
# self.set_log("🤖运行了 thumbsup")
url = "https://hd.opposhop.cn/api/cn/oapi/java/ugc/frontend/praise/thread"
payload = {
'tid': tid,
'uid': uid
}
headers = {
'User-Agent': self.UA,
'Cookie': f"apkPkg=com.oppo.community; TOKENSID=TOKEN_{self.ck}",
}
response = requests.post(url, data=payload, headers=headers)
try:
j = ujson.loads(response.text)
if j["code"] == 200:
self.set_log(f"🎉帖子 tid: {tid} : {j['msg']}")
else:
self.set_log(f"❌帖子 tid: {tid} 点赞失败,{j['msg']}")
except (KeyError, ValueError):
self.set_log(f"💥帖子 tid: {tid} 点赞失败,解析响应数据出错 {response.text} ")
# 小程序抽奖功能
def do_raffle(self):
# self.set_log("🤖运行了 do_raffle 抽奖功能")
# 抽奖活动ID
activity_id = "1937054297539874816"
# 先查询抽奖次数
query_url = f"https://hd.opposhop.cn/api/cn/oapi/marketing/raffle/queryRaffleCount?activityId={activity_id}"
headers = {
'User-Agent': self.UA,
'Accept': "application/json, text/plain, */*",
'Cookie': f"TOKENSID=TOKEN_{self.ck}; apkPkg=com.oppo.store"
}
try:
# 查询抽奖次数
response = requests.get(query_url, headers=headers)
response.raise_for_status()
count_data = json.loads(response.text)
if count_data["code"] == 200:
raffle_count = count_data["data"].get("count", -1)
if raffle_count == -1:
self.set_log("❌ 获取抽奖次数失败,可能是账号状态有误。")
return False
elif raffle_count == 0:
self.set_log("➖今日抽奖次数已用完")
return True
else:
self.set_log(f"🎁 您当前有`{raffle_count}`次抽奖机会")
# 开始抽奖
self.set_log("🎲 开始抽奖...")
for i in range(raffle_count):
self.do_single_raffle(activity_id, i + 1, raffle_count)
time.sleep(2) # 添加间隔时间,避免请求过快
return True
else:
self.set_log(f"❌ 查询抽奖次数失败: {count_data.get('message', '未知错误')}")
return False
except requests.exceptions.RequestException as e:
self.set_log(f"💥 抽奖请求失败: {e}")
except json.JSONDecodeError as e:
self.set_log(f"💥 解析抽奖数据失败: {e}")
except Exception as e:
self.set_log(f"💥 抽奖过程中出现未预期的错误: {e}")
return False
# 执行单次抽奖
def do_single_raffle(self, activity_id, current_draw, total_draws):
raffle_url = f"https://hd.opposhop.cn/api/cn/oapi/marketing/raffle/clickRaffle"
# 构建查询参数
params = {
"activityId": activity_id,
# "creditsAddActionId": "1788913e6d9e4683b8b9ab0088733560",
# "creditsDeductActionId": "d5e44c73030a4b1287bff7bfa3df0320",
# "business": "1",
# "jimuId": "GG//dAZ99/eP6geYUp/gxg==",
# "jimuName": "签到赢好礼"
}
# 构建请求头
headers = {
'Accept': 'application/json, text/plain, */*',
'User-Agent': self.UA,
# 'encryption': 'jqU44Ezs8rZKpZ5DQa+MzCkSId6F8m7b7n2SX6SUSPVIizOCngKa6mppYO1jODSPoLftNf7oGSw8Jo30PcWZew==',
# 'source_type': '503',
# 's_channel': 'program_wx',
'Cookie': f"TOKENSID=TOKEN_{self.ck}; apkPkg=com.oppo.store"
}
try:
# 发起抽奖请求
response = requests.get(raffle_url, params=params, headers=headers)
response.raise_for_status()
raffle_data = json.loads(response.text)
if raffle_data["code"] == 200:
inspection_code = raffle_data.get("data", {}).get("inspectionQualification", {}).get("code")
if inspection_code == 204:
self.set_log(
f"ℹ️ 第`{current_draw}/{total_draws}`次抽奖:`{raffle_data['data']['inspectionQualification']['msg']}`")
return False
raffle_winner = raffle_data.get("data", {}).get("raffleWinnerVO", {})
award_name = raffle_winner.get("exhibitAwardName", "未知奖品")
self.set_log(f"🎉 第`{current_draw}/{total_draws}`次抽奖成功,获得: `{award_name}`")
return True
else:
self.set_log(
f"❌ 第`{current_draw}/{total_draws}`次抽奖失败: `{raffle_data.get('message', '未知错误')}`")
return False
except requests.exceptions.RequestException as e:
self.set_log(f"💥 抽奖请求失败: {e}")
except json.JSONDecodeError as e:
self.set_log(f"💥 解析抽奖结果失败: {e}")
except Exception as e:
self.set_log(f"💥 抽奖过程中出现未预期的错误: {e}")
return False
# 统计今日积分收入
def today_credits_summary(self):
# self.set_log("🤖运行了 today_credits_summary")
today = datetime.now().strftime("%Y-%m-%d")
total_in = 0
total_out = 0
all_today_records = []
# 初始化为空,第一次请求不带时间戳
last_timestamp = ""
# 使用循环获取所有分页数据,直到找到不是今天的记录
page = 1
has_more_today_data = True
found_earlier_date = False
while has_more_today_data and not found_earlier_date and page <= 10: # 限制最多查询10页,避免无限循环
# self.set_log(f"📑 正在获取第 {page} 页积分记录...")
# 构建分页查询URL
url_params = f"sessionId={self.session_id}&loadSize=15"
if last_timestamp:
url_params += f"&lastRecordTimeStamp={last_timestamp}"
url = f"https://omoapplet-api-cn.heytap.com/point/creditsList?{url_params}"
headers = {
'User-Agent': self.UA
}
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
data = json.loads(response.text)
if data["ret"] == "1":
# 获取下一页的时间戳
last_timestamp = data.get("data", {}).get("lastRecordTimeStamp", "")
if not last_timestamp:
has_more_today_data = False # 没有更多数据了
# 遍历积分组
today_records_in_page = []
for group in data.get("data", {}).get("groups", []):
for record in group.get("creditsList", []):
record_time = record.get("createTime", "")
record_date = record_time.split(" ")[0] if " " in record_time else ""
# 检查是否找到了不是今天的记录
if record_date and record_date != today:
found_earlier_date = True # 找到了早于今天的记录,停止查询
break
# 只处理今天的数据
if record_date == today:
today_records_in_page.append(record)
if found_earlier_date:
break
# 如果当前页没有今天的记录,则停止查询
if not today_records_in_page:
has_more_today_data = False
else:
all_today_records.extend(today_records_in_page)
# 如果没有下一页数据,则停止查询
if not last_timestamp:
has_more_today_data = False
else:
self.set_log(f"❌ 获取积分明细失败: {data.get('errMsg', '未知错误')}")
return False
except requests.exceptions.RequestException as e:
self.set_log(f"💥 获取积分明细请求失败: {e}")
return False
except json.JSONDecodeError as e:
self.set_log(f"💥 解析积分明细结果失败: {e}")
return False
except Exception as e:
self.set_log(f"💥 获取积分明细过程中出现未预期的错误: {e}")
return False
page += 1
time.sleep(1) # 添加间隔时间,避免请求过快
# 处理所有今天的积分记录
if all_today_records:
# 获取总积分
total_amount = data.get("data", {}).get("amount", 0)
self.set_log(f"📊 当前积分总额:`{total_amount}`")
self.set_log(f"📝 今日积分收支明细 (共`{len(all_today_records)}`条记录):")