forked from gaoyuanqi/DaLeDou
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdaledou.py
2927 lines (2529 loc) · 93.8 KB
/
daledou.py
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
import re
import sys
import time
import random
import traceback
from shutil import copy
from importlib import reload
from os import environ, path, getenv
import yaml
import requests
from loguru import logger
import settings
MSG = []
WEEK: str = time.strftime('%w')
DATE: str = time.strftime('%d', time.localtime())
# 不支持的通知
DISABLE_PUSH = ['乐斗', '历练', '镶嵌', '神匠坊', '背包']
MISSION = {
'one': [
[('邪神秘宝',), True],
[('华山论剑',), (int(DATE) <= 26)],
[('斗豆月卡',), True],
[('每日宝箱',), (DATE == '20')],
[('分享',), True],
[('乐斗',), True],
[('报名',), True],
[('巅峰之战进行中',), (WEEK != '2')],
[('矿洞',), True],
[('掠夺',), (WEEK in ['2', '3'])],
[('踢馆',), (WEEK in ['5', '6'])],
[('竞技场',), (int(DATE) <= 25)],
[('十二宫',), True],
[('许愿',), True],
[('抢地盘',), True],
[('历练',), True],
[('镖行天下',), True],
[('幻境',), True],
[('群雄逐鹿',), (WEEK == '6')],
[('画卷迷踪',), True],
[('门派',), True],
[('门派邀请赛',), (WEEK != '2')],
[('会武',), (WEEK not in ['5', '0'])],
[('梦想之旅',), True],
[('问鼎天下',), True],
[('帮派商会',), True],
[('帮派远征军',), True],
[('帮派黄金联赛',), True],
[('任务派遣中心',), True],
[('武林盟主',), True],
[('全民乱斗',), True],
[('侠士客栈',), True],
[('江湖长梦',), (WEEK == '4')],
[('任务',), True],
[('我的帮派',), True],
[('帮派祭坛',), True],
[('飞升大作战',), True],
[('深渊之潮',), True],
[('每日奖励',), True],
[('领取徒弟经验',), True],
[('今日活跃度',), True],
[('仙武修真',), True],
[('大侠回归三重好礼',), (WEEK == '4')],
[('乐斗黄历',), True],
[('器魂附魔',), True],
[('镶嵌',), (WEEK == '4')],
[('兵法',), (WEEK in ['4', '6'])],
[('神匠坊',), (WEEK == '4')],
[('背包',), True],
[('商店',), True],
[('猜单双',), True],
[('煮元宵',), True],
[('元宵节',), (WEEK == '4')],
[('万圣节',), True],
[('神魔转盘',), True],
[('乐斗驿站',), True],
[('浩劫宝箱',), True],
[('幸运转盘',), True],
[('喜从天降',), True],
[('冰雪企缘',), True],
[('甜蜜夫妻',), True],
[('幸运金蛋',), True],
[('乐斗菜单',), True],
[('客栈同福',), True],
[('周周礼包',), True],
[('登录有礼',), True],
[('活跃礼包',), True],
[('上香活动',), True],
[('徽章战令',), True],
[('生肖福卡',), True],
[('长安盛会',), True],
[('深渊秘宝',), True],
[('登录商店',), (WEEK == '4')],
[('盛世巡礼',), (WEEK == '4')],
[('中秋礼盒',), True],
[('双节签到',), True],
[('圣诞有礼',), (WEEK == '4')],
[('5.1礼包', '五一礼包'), (WEEK == '4')],
[('新春礼包',), (WEEK == '4')],
[('新春拜年',), True],
[('春联大赛',), True],
[('乐斗游记',), True],
[('斗境探秘',), True],
[('新春登录礼',), True],
[('年兽大作战',), True],
[('惊喜刮刮卡',), True],
[('开心娃娃机',), True],
[('好礼步步升',), True],
[('企鹅吉利兑',), True],
[('乐斗回忆录',), (WEEK == '4')],
[('乐斗大笨钟',), True],
[('爱的同心结',), (WEEK == '4')],
[('周年生日祝福',), (WEEK == '4')],
],
'two': [
[('邪神秘宝',), True],
[('问鼎天下',), (WEEK not in ['6', '0'])],
[('任务派遣中心',), True],
[('侠士客栈',), True],
[('深渊之潮',), True],
[('幸运金蛋',), True],
[('新春拜年',), True],
[('乐斗大笨钟',), True],
],
}
class CookieError(Exception):
...
class DaLeDou:
def __init__(self, cookie: str) -> None:
assert type(cookie) is str, '传入的cookie只能是str类型'
self._cookie = self._clean_cookie(cookie)
self._qq = self._match_qq()
def _clean_cookie(self, cookie: str) -> str:
'''清洁大乐斗cookie
:return: 'RK=xxx; ptcz=xxx; openId=xxx; accessToken=xxx; newuin=xxx'
'''
ck = ''
for key in ['RK', 'ptcz', 'openId', 'accessToken', 'newuin']:
try:
result = re.search(
f'{key}=(.*?); ',
f'{cookie}; ',
re.S
).group(0)
except AttributeError:
raise CookieError(f'大乐斗cookie不正确:{cookie}')
ck += f'{result}'
return ck[:-2]
def _match_qq(self) -> str:
'''从cookie中提取出qq'''
return re.search(r'newuin=(\d+)', self._cookie, re.S).group(1)
def _create_yaml(self):
'''基于 daledou.yaml 创建一份以qq命名的 yaml 配置文件
如果以qq命名的yaml配置文件已存在则不做任何操作
'''
srcpath = f'./config/daledou.yaml'
yamlpath = f'./config/{self._qq}.yaml'
if not path.isfile(yamlpath):
logger.success(f'成功创建配置文件:./config/{self._qq}.yaml')
copy(srcpath, yamlpath)
def _push(self, title: str, message: list) -> None:
'''pushplus微信通知'''
if token := settings.PUSHPLUS_TOKEN:
url = 'http://www.pushplus.plus/send/'
content = '\n'.join(list(filter(lambda x: x, message)))
data = {
'token': token,
'title': title,
'content': content,
}
res = requests.post(url, data=data)
json: dict = res.json()
if json.get('code') == 200:
return logger.success(f'pushplus推送成功:{json}')
return logger.warning(f'pushplus推送失败:{json}')
logger.warning('pushplus没有配置token,取消微信推送')
def session(self):
'''若cookie有效返回Session对象,否则返回None'''
global SESSION
url = 'https://dld.qzapp.z.qq.com/qpet/cgi-bin/phonepk?cmd=index'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
}
with requests.session() as SESSION:
requests.utils.add_dict_to_cookiejar(
SESSION.cookies, {'Cookie': self._cookie})
for _ in range(3):
res = SESSION.get(url, headers=headers)
res.encoding = 'utf-8'
html = res.text
if '商店' in html:
logger.success(f'{self._qq}:COOKIE有效')
if self._cookie != getenv(f'DLD_COOKIE_VALID_{self._qq}'):
environ[f'DLD_COOKIE_VALID_{self._qq}'] = self._cookie
self._create_yaml()
return SESSION
elif '一键登录' in html:
logger.warning(f'{self._qq}:COOKIE无效!!!')
break
if self._cookie != getenv(f'DLD_COOKIE_NULL_{self._qq}'):
environ[f'DLD_COOKIE_NULL_{self._qq}'] = self._cookie
self._push(f'cookie失效或者系统维护:{self._qq}', [self._cookie])
def create_log(self) -> int:
'''创建当天日志文件
文件夹以qq命名,日志文件以日期命名
'''
date = time.strftime('%Y-%m-%d', time.localtime())
return logger.add(
f'./log/{self._qq}/{date}.log',
format='<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <4}</level> | <level>{message}</level>',
enqueue=True,
encoding='utf-8',
retention='30 days'
)
def get(self, params: str) -> str:
'''发送get请求获取html响应内容'''
global HTML
url = f'https://dld.qzapp.z.qq.com/qpet/cgi-bin/phonepk?{params}'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
}
for _ in range(3):
res = SESSION.get(url, headers=headers)
res.encoding = 'utf-8'
HTML = res.text
time.sleep(0.2)
if '系统繁忙' not in HTML:
break
return HTML
def find(self, mode: str, name: str = '') -> str | None:
'''匹配首个'''
if match := re.search(mode, HTML, re.S):
result: str = match.group(1)
else:
result = None
if not name:
name = MISSION_NAME
logger.info(f'{self._qq} | {name}:{result}')
return result
def findall(self, mode: str) -> list:
'''匹配所有'''
return re.findall(mode, HTML, re.S)
def read_yaml(self, key: str):
'''读取config目录下的yaml配置文件'''
try:
with open(f'./config/{self._qq}.yaml', 'r', encoding='utf-8') as fp:
users = yaml.safe_load(fp)
data = users[key]
return data
except Exception:
error = traceback.format_exc()
logger.error(f'{self._qq}.yaml 配置不正确:\n{error}')
self._push(f'{self._qq}.yaml 配置不正确', [error])
def run(self, tasks: str) -> None:
global MISSION_NAME
start = time.time()
for _ in range(3):
# 大乐斗首页
get('cmd=index')
if '退出' in HTML:
html = HTML.split('【退出】')[0]
for misssion in MISSION.get(tasks, []):
is_mission: tuple = misssion[0]
is_run: bool = misssion[-1]
if len(is_mission) == 2:
mission_name, func_name = is_mission
else:
mission_name = is_mission[0]
func_name = is_mission[0]
MISSION_NAME = mission_name
if is_run and (mission_name in html):
if mission_name not in DISABLE_PUSH:
MSG.append(f'\n【{mission_name}】')
globals()[func_name]()
break
end = time.time()
MSG.append(f'\n【运行时长】\n时长:{int(end - start)} s')
self._push(f'{self._qq} {tasks}', MSG)
MSG.clear()
def get(params: str) -> str:
'''发送get请求获取html响应内容'''
HTML = DALEDOU.get(params)
return HTML
def find(mode: str, name: str = '') -> str | None:
'''匹配首个'''
return DALEDOU.find(mode, name)
def findall(mode: str) -> list:
'''匹配所有'''
return DALEDOU.findall(mode)
def read_yaml(key: str):
'''读取yaml配置文件'''
return DALEDOU.read_yaml(key)
def run(tasks: str = 'check') -> None:
global DALEDOU
if len(input := sys.argv) == 2:
tasks = input[1]
if tasks not in ['check', 'one', 'two']:
assert False, f'不支持 {tasks} 参数,只支持 check | one | two'
reload(settings)
for ck in settings.DALEDOU_ACCOUNT:
print('\n')
DALEDOU = DaLeDou(ck)
if DALEDOU.session():
if tasks == 'check':
continue
trace = DALEDOU.create_log()
DALEDOU.run(tasks)
logger.remove(trace)
del DALEDOU
def 邪神秘宝():
'''邪神秘宝
高级秘宝 免费一次 or 抽奖一次
极品秘宝 免费一次 or 抽奖一次
'''
for i in [0, 1]:
# 免费一次 or 抽奖一次
get(f'cmd=tenlottery&op=2&type={i}')
MSG.append(find(r'】</p>(.*?)<br />', '邪神秘宝'))
def 华山论剑():
'''华山论剑
每月1~25号每天至多挑战10次,耐久不足时自动更换侠士
每月26号领取赛季段位奖励
'''
if int(DATE) <= 25:
for _ in range(10):
# 开始挑战
get('cmd=knightarena&op=challenge')
if '耐久不足' in HTML:
# 战阵调整页面
get('cmd=knightarena&op=viewsetknightlist&pos=0')
knightid = findall(r'knightid=(\d+)')
# 出战侠士页面
get('cmd=knightarena&op=viewteam')
xuanze_pos = findall(r'pos=(\d+)">选择侠士')
genggai = findall(r'耐久:(\d+)/.*?pos=(\d+)">更改侠士.*?id=(\d+)')
genggai_pos = []
for n, p, id in genggai:
# 移除不可出战的侠士id
knightid.remove(id)
if n == '0':
# 筛选耐久为 0 的侠士出战次序
genggai_pos.append(p)
# 选择/更改侠士
for p in (xuanze_pos + genggai_pos):
if not knightid:
break
id: str = knightid.pop()
# 出战
get(f'cmd=knightarena&op=setknight&id={id}&pos={p}&type=1')
continue
MSG.append(find(r'荣誉兑换</a><br />(.*?)<br />'))
if '论剑所需门票不足' in HTML:
break
elif '请先设置上阵侠士后再开始战斗' in HTML:
break
elif DATE == '26':
get(r'cmd=knightarena&op=drawranking')
MSG.append(find(r'【赛季段位奖励】<br />(.*?)<br />'))
def 斗豆月卡():
'''斗豆月卡
每天领取150斗豆
'''
# 领取150斗豆
get('cmd=monthcard&sub=1')
MSG.append(find(r'<p>(.*?)<br />'))
def 每日宝箱():
'''每日宝箱
每月20号打开所有宝箱
'''
# 每日宝箱
get('cmd=dailychest')
while type_list := findall(r'type=(\d+)">打开'):
# 打开
get(f'cmd=dailychest&op=open&type={type_list[0]}')
MSG.append(find(r'规则说明</a><br />(.*?)<br />'))
if '今日开宝箱次数已达上限' in HTML:
break
def 分享():
'''分享
每天分享直到上限,若次数不足则挑战斗神塔增加次数(每挑战11层增加一次分享)
每周四领取分享次数奖励
'''
for _ in range(9):
# 一键分享
get(f'cmd=sharegame&subtype=6')
find(r'】</p>(.*?)<p>', '一键分享')
if '上限' in HTML:
MSG.append(find(r'</p><p>(.*?)<br />.*?开通达人', '分享次数'))
# 自动挑战
get('cmd=towerfight&type=11')
find(r'】<br />(.*?)<', '斗神塔')
# 结束挑战
get('cmd=towerfight&type=7')
find(r'】<br />(.*?)<br />', '斗神塔')
break
# 斗神塔
get('cmd=towerfight&type=3')
if '结束挑战' in HTML:
# 结束挑战
get('cmd=towerfight&type=7')
find(r'】<br />(.*?)<br />', '斗神塔')
for _ in range(11):
# 开始挑战 or 挑战下一层
get('cmd=towerfight&type=0')
find(r'】<br />(.*?)<', '斗神塔')
if '您需要消耗斗神符才能继续挑战斗神塔' in HTML:
# 一键分享
get(f'cmd=sharegame&subtype=6')
find(r'】</p>(.*?)<p>', '斗神塔')
return
elif '您败给' in HTML:
# 结束挑战
get('cmd=towerfight&type=7')
find(r'】<br />(.*?)<br />', '斗神塔')
break
if cooling := findall(r'战斗剩余时间:(\d+)'):
time.sleep(int(cooling[0]))
if WEEK == '4':
get('cmd=sharegame&subtype=3')
for s in findall(r'sharenums=(\d+)'):
# 领取
get(f'cmd=sharegame&subtype=4&sharenums={s}')
MSG.append(find(r'】</p>(.*?)<p>'), '斗神塔')
def 乐斗():
'''乐斗
开启自动使用体力药水
贡献药水使用4次
每天乐斗好友BOSS、帮友BOSS以及侠侣所有
'''
# 乐斗助手
get('cmd=view&type=6')
if '开启自动使用体力药水' in HTML:
# 开启自动使用体力药水
get('cmd=set&type=0')
for _ in range(4):
# 使用贡献药水
get('cmd=use&id=3038&store_type=1&page=1')
if '使用规则' in HTML:
find(r'】</p><p>(.*?)<br />')
break
else:
find(r'<br />(.*?)<br />斗豆')
# 好友BOSS
get('cmd=friendlist&page=1')
for u in findall(r'侠:.*?B_UID=(\d+)'):
# 乐斗
get(f'cmd=fight&B_UID={u}')
find(r'删</a><br />(.*?),')
if '体力值不足' in HTML:
break
# 帮友BOSS
get('cmd=viewmem&page=1')
for u in findall(r'侠:.*?B_UID=(\d+)'):
# 乐斗
get(f'cmd=fight&B_UID={u}')
find(r'侠侣</a><br />(.*?),')
if '体力值不足' in HTML:
break
# 侠侣
get('cmd=viewxialv&page=1')
try:
for u in findall(r':.*?B_UID=(\d+)')[1:]:
# 乐斗
get(f'cmd=fight&B_UID={u}')
if '使用规则' in HTML:
find(r'】</p><p>(.*?)<br />')
elif '查看乐斗过程' in HTML:
find(r'删</a><br />(.*?)!')
if '体力值不足' in HTML:
break
except Exception:
...
def 报名():
'''报名
每天报名武林大会
周二、五、日报名侠侣争霸
周六、日报名笑傲群侠
'''
# 武林大会
get('cmd=fastSignWulin&ifFirstSign=1')
if '使用规则' in HTML:
MSG.append(find(r'】</p><p>(.*?)<br />'))
else:
MSG.append(find(r'升级。<br />(.*?) '))
# 侠侣争霸
if WEEK in ['2', '5', '0']:
get('cmd=cfight&subtype=9')
if '使用规则' in HTML:
MSG.append(find(r'】</p><p>(.*?)<br />'))
else:
MSG.append(find(r'报名状态.*?<br />(.*?)<br />'))
# 笑傲群侠
if WEEK in ['6', '0']:
get('cmd=knightfight&op=signup')
MSG.append(find(r'侠士侠号.*?<br />(.*?)<br />'))
def 巅峰之战进行中():
'''巅峰之战进行中
周一报名(随机加入)、领奖
周三、四、五、六、日征战
'''
if WEEK == '1':
for c in ['cmd=gvg&sub=4&group=0&check=1', 'cmd=gvg&sub=1']:
get(c)
MSG.append(find(r'】</p>(.*?)<br />'))
elif WEEK not in ['1', '2']:
# 巅峰之战
get('cmd=gvg&sub=0')
for _ in range(14):
# 征战
get('cmd=gvg&sub=5')
if '你在巅峰之战中' in HTML:
if '战线告急' in HTML:
MSG.append(find(r'支援!<br />(.*?)。'))
else:
MSG.append(find(r'】</p>(.*?)。'))
else:
# 冷却时间
# 撒花祝贺
# 请您先报名再挑战
# 您今天已经用完复活次数了
if '战线告急' in HTML:
MSG.append(find(r'支援!<br />(.*?)<br />'))
else:
MSG.append(find(r'】</p>(.*?)<br />'))
break
def 矿洞():
'''矿洞
每天挑战3次
副本开启第五层简单
领取通关奖励
'''
# 矿洞
get('cmd=factionmine')
for _ in range(5):
if '领取奖励' in HTML:
# 领取奖励
get('cmd=factionmine&op=reward')
MSG.append(find(r'】<br /><br />(.*?)<br />'))
elif '开启副本' in HTML:
# floor 1、2、3、4、5 对应 第一、二、三、四、五层
# mode 1、2、3 对应 简单、普通、困难
# 确认开启
get('cmd=factionmine&op=start&floor=5&mode=1')
MSG.append(find(r'矿石商店</a><br />(.*?)<br />'))
elif '副本挑战中' in HTML:
# 挑战
get('cmd=factionmine&op=fight')
MSG.append(find(r'商店</a><br />(.*?)<br />'))
if '挑战次数不足' in HTML:
break
def 掠夺():
'''掠夺
周二掠夺一次(选择可掠夺粮仓最低战力)、领奖
周三领取胜负奖励
'''
if WEEK == '2':
get('cmd=forage_war')
if '本轮轮空' in HTML:
MSG.append(find(r'本届战况:(.*?)<br />'))
return
# 掠夺
get('cmd=forage_war&subtype=3')
if gra_id := findall(r'gra_id=(\d+)">掠夺'):
data = []
for id in gra_id:
get(f'cmd=forage_war&subtype=3&op=1&gra_id={id}')
if zhanli := findall(r'<br />1.*? (\d+)\.'):
data += [(int(zhanli[0]), id)]
if data:
_, id = min(data)
get(f'cmd=forage_war&subtype=4&gra_id={id}')
MSG.append(find(r'返回</a><br />(.*?)<br />'))
# 领奖
get('cmd=forage_war&subtype=5')
MSG.append(find(r'返回</a><br />(.*?)<br />'))
elif WEEK == '3':
get('cmd=forage_war&subtype=6')
MSG.append(find(r'规则</a><br />(.*?)<br />'))
def 踢馆():
'''踢馆
周五试炼5次、高倍转盘一次、挑战至多31次
周六领奖以及报名踢馆
'''
if WEEK == '5':
for t in [2, 2, 2, 2, 2, 4]:
# 试炼、高倍转盘
get(f'cmd=facchallenge&subtype={t}')
find(r'功勋商店</a><br />(.*?)<br />')
if '你们帮没有报名参加这次比赛' in HTML:
MSG.append('你们帮没有报名参加这次比赛')
return
for _ in range(31):
# 挑战
get('cmd=facchallenge&subtype=3')
find(r'功勋商店</a><br />(.*?)<br />')
if '您的挑战次数已用光' in HTML:
MSG.append('您的挑战次数已用光')
break
elif '您的复活次数已耗尽' in HTML:
MSG.append('您的复活次数已耗尽')
break
elif WEEK == '6':
for p in ['7', '1']:
get(f'cmd=facchallenge&subtype={p}')
MSG.append(find(r'功勋商店</a><br />(.*?)<br />'))
def 竞技场():
'''竞技场
每月1~25号每天至多挑战10次、领取奖励、默认兑换10个河洛图书
'''
for _ in range(10):
# 免费挑战 or 开始挑战
get('cmd=arena&op=challenge')
if '免费挑战次数已用完' in HTML:
find(r'更新提示</a><br />(.*?)!')
# 领取奖励
get('cmd=arena&op=drawdaily')
MSG.append(find(r'更新提示</a><br />(.*?)<br />'))
break
find(r'更新提示</a><br />(.*?)。')
if yaml := read_yaml('竞技场'):
# 兑换10个
get(f'cmd=arena&op=exchange&id={yaml}×=10')
MSG.append(find(r'竞技场</a><br />(.*?)<br />'))
def 十二宫():
'''十二宫
每天默认白羊宫请猴王扫荡
'''
if yaml := read_yaml('十二宫'):
# 请猴王扫荡
get(f'cmd=zodiacdungeon&op=autofight&scene_id={yaml}')
if '恭喜你' in HTML:
MSG.append(find(r'恭喜你,(.*?)!'))
return
elif '是否复活再战' in HTML:
MSG.append(find(r'<br.*>(.*?),'))
return
# 你已经不幸阵亡,请复活再战!
# 挑战次数不足
# 当前场景进度不足以使用自动挑战功能
MSG.append(find(r'<p>(.*?)<br />'))
def 许愿():
'''许愿
每天领取许愿奖励、上香许愿、领取魂珠碎片宝箱
'''
for sub in [5, 1, 6]:
get(f'cmd=wish&sub={sub}')
MSG.append(find(r'】<br />(.*?)<br />'))
def 抢地盘():
'''抢地盘
每天无限制区攻占一次第10位
等级 30级以下 40级以下 ... 120级以下 无限制区
type 1 2 10 11
'''
get('cmd=recommendmanor&type=11&page=1')
if id := findall(r'manorid=(\d+)">攻占</a>'):
# 攻占
get(f'cmd=manorfight&fighttype=1&manorid={id[-1]}')
MSG.append(find(r'】</p><p>(.*?)。'))
# 兑换武器
get('cmd=manor&sub=0')
MSG.append(find(r'【抢地盘】<br /><br />(.*?)<br /><br />'))
def 历练():
'''历练
每天默认掉落佣兵碎片的每个关卡BOSS会被乐斗3次
'''
for id in read_yaml('历练'):
for _ in range(3):
get(f'cmd=mappush&subtype=3&mapid=6&npcid={id}&pageid=2')
find(r'阅历值:\d+<br />(.*?)<br />')
if '您还没有打到该历练场景' in HTML:
find(r'介绍</a><br />(.*?)<br />')
break
elif '还不能挑战' in HTML:
break
elif '活力不足' in HTML:
return
def 镖行天下():
'''镖行天下
每天拦截成功3次、领取奖励、刷新押镖并启程护送
'''
for op in [15, 16, 7, 8, 6]:
# 护送完成 》领取奖励 》护送押镖 》刷新押镖 》启程护送
get(f'cmd=cargo&op={op}')
if '镖行天下' in HTML:
MSG.append(find(r'商店</a><br />(.*?)<br />'))
elif op == 8:
find(r'】<br />(.*?)<br />')
for _ in range(5):
# 刷新
get('cmd=cargo&op=3')
for uin in findall(r'passerby_uin=(\d+)">拦截'):
# 拦截
get(f'cmd=cargo&op=14&passerby_uin={uin}')
if '系统繁忙' in HTML:
continue
elif '这个镖车在保护期内' in HTML:
continue
elif '您今天已达拦截次数上限了' in HTML:
return
MSG.append(find(r'商店</a><br />(.*?)<br />'))
def 幻境():
'''幻境
每天默认乐斗鹅王的试炼
'''
if yaml := read_yaml('幻境'):
get(f'cmd=misty&op=start&stage_id={yaml}')
for _ in range(5):
# 乐斗
get(f'cmd=misty&op=fight')
MSG.append(find(r'星数.*?<br />(.*?)<br />'))
if '尔等之才' in HTML:
break
# 返回飘渺幻境
get('cmd=misty&op=return')
def 群雄逐鹿():
'''群雄逐鹿
每周六报名、领奖
'''
for op in ['signup', 'drawreward']:
get(f'cmd=thronesbattle&op={op}')
MSG.append(find(r'届群雄逐鹿<br />(.*?)<br />'))
def 画卷迷踪():
'''画卷迷踪
每天至多挑战20次
'''
for _ in range(20):
# 准备完成进入战斗
get('cmd=scroll_dungeon&op=fight&buff=0')
MSG.append(find(r'选择</a><br /><br />(.*?)<br />'))
if '没有挑战次数' in HTML:
break
elif '征战书不足' in HTML:
break
def 门派():
'''门派
万年寺:点燃 》点燃
八叶堂:进入木桩训练 》进入同门切磋
五花堂:至多完成任务3次
'''
# 点燃 》点燃
for op in ['fumigatefreeincense', 'fumigatepaidincense']:
get(f'cmd=sect&op={op}')
MSG.append(find(r'修行。<br />(.*?)<br />'))
# 进入木桩训练 》进入同门切磋
for op in ['trainingwithnpc', 'trainingwithmember']:
get(f'cmd=sect&op={op}')
MSG.append(find(r'【八叶堂】<br />(.*?)<br />'))
# 五花堂
wuhuatang = get('cmd=sect_task')
missions = {
'进入华藏寺看一看': 'cmd=sect_art',
'进入伏虎寺看一看': 'cmd=sect_trump',
'进入金顶看一看': 'cmd=sect&op=showcouncil',
'进入八叶堂看一看': 'cmd=sect&op=showtraining',
'进入万年寺看一看': 'cmd=sect&op=showfumigate',
'与掌门进行一次武艺切磋': 'cmd=sect&op=trainingwithcouncil&rank=1&pos=1',
'与首座进行一次武艺切磋': 'cmd=sect&op=trainingwithcouncil&rank=2&pos=1',
'与堂主进行一次武艺切磋': 'cmd=sect&op=trainingwithcouncil&rank=3&pos=1',
}
for name, url in missions.items():
if name in wuhuatang:
get(url)
if '查看一名' in wuhuatang:
# 查看一名同门成员的资料 or 查看一名其他门派成员的资料
for page in [2, 3]:
# 好友第2、3页
get(f'cmd=friendlist&page={page}')
for uin in findall(r'\d+:.*?B_UID=(\d+).*?级'):
# 查看好友
get(f'cmd=totalinfo&B_UID={uin}')
if '进行一次心法修炼' in wuhuatang:
'''
少林心法 峨眉心法 华山心法 丐帮心法 武当心法 明教心法
101 法华经 104 斩情决 107 御剑术 110 醉拳 113 太极内力 116 圣火功
102 金刚经 105 护心决 108 龟息术 111 烟雨行 114 绕指柔剑 117 五行阵
103 达摩心经 106 观音咒 109 养心术 112 笑尘诀 115 金丹秘诀 118 日月凌天
'''
for id in range(101, 119):
get(f'cmd=sect_art&subtype=2&art_id={id}×=1')
if '修炼成功' in HTML:
find(r'】<br />(.*?)<br />')
break
elif '修炼失败' in HTML:
if '你的门派贡献不足无法修炼' in HTML:
break
elif ('你的心法已达顶级无需修炼' in HTML) and (id == 118):
MSG.append('所有心法都已经顶级')
# 五花堂
get('cmd=sect_task')
for id in findall(r'task_id=(\d+)">完成'):
# 完成
get(f'cmd=sect_task&subtype=2&task_id={id}')
MSG.append(find(r'】<br />(.*?)<br />'))
def 门派邀请赛():
'''门派邀请赛
每周一报名、领取奖励
每周三、四、五、六、日挑战6次以及默认兑换10个炼气石
'''
if WEEK == '1':
# 组队报名
get('cmd=secttournament&op=signup')
if '已加入到某只队伍中' in HTML:
MSG.append(find(r'规则</a><br />(.*?)<br />'))
elif '邀请好友' in HTML:
MSG.append(find(r'】<br />(.*?)<br />'))
# 领取奖励
get('cmd=secttournament&op=getrankandrankingreward')
MSG.append(find(r'规则</a><br />(.*?)<br />'))
elif WEEK not in ['1', '2']:
for _ in range(6):
# 开始挑战
get('cmd=secttournament&op=fight')
MSG.append(find(r'规则</a><br />(.*?)<br />'))
if yaml := read_yaml('门派邀请赛'):
# 兑换10个
get(f'cmd=exchange&subtype=2&type={yaml}×=10&costtype=11')
MSG.append(find(r'】<br />(.*?)<br />'))
def 会武():
'''会武
周一初级、中级至多挑战5次,高级至多挑战10次
周二、三高级至多挑战10次(自动兑换试炼书*10)
周四助威丐帮
周六领取奖励、兑换真黄金卷轴*10
'''
if WEEK in ['1', '2', '3']:
for _ in range(21):
# 挑战
get('cmd=sectmelee&op=dotraining')
# MSG.append(find(r'最高伤害:\d+<br />(.*?)<br />'))
if '你已达今日挑战上限' in HTML:
MSG.append('试炼场挑战已达今日挑战上限')
break
elif '你的试炼书不足' in HTML:
# 兑换 试炼书*10
get('cmd=exchange&subtype=2&type=1265×=10&costtype=13')
if '会武积分不足' in HTML:
# 抱歉,您的会武积分不足,不能兑换该物品!
MSG.append('会武积分不足兑换试炼书*10')
break
elif WEEK == '4':
# 冠军助威 丐帮
get('cmd=sectmelee&op=cheer§=1003')
# 冠军助威
get('cmd=sectmelee&op=showcheer')
MSG.append(find(r'【冠军助威】<br />(.*?)<br />'))
elif WEEK == '6':
# 领奖
get('cmd=sectmelee&op=drawreward')
MSG.append(find(r'【领奖】<br />(.*?)<br />'))
# 兑换 真黄金卷轴*10
get('cmd=exchange&subtype=2&type=1263×=10&costtype=13')
MSG.append(find(r'】<br />(.*?)<br />'))
def 梦想之旅():
'''梦想之旅
每天普通旅行一次
周四梦幻旅行(如果下一个区域存在 '已去过')、领取区域、超级礼包
'''
# 普通旅行
get('cmd=dreamtrip&sub=2')
MSG.append(find(r'规则</a><br />(.*?)<br />'))
if WEEK == '4':
bmapid = {
'空桑山': 2,
'鹊山': 3,
'鹿蜀': 4,
'昆仑之丘': 1
}
# 梦想之旅
get('cmd=dreamtrip')
for k, v in bmapid.items():