├── Doc
├── 0.png
├── 1.png
├── 10.png
├── 11.png
├── 2.png
├── 3.png
├── 4.png
├── 5.png
├── 6.png
├── 7.png
├── 8.png
├── 9.png
└── README.md
├── index.py
├── HT_account.py
├── LICENSE
├── HT_config.py
├── README.md
├── TimingCash.py
├── Backup
├── ChockInEarly.py
├── Community.py
├── CollectionCard.py
├── BattleForHeyTap.py
└── Double11.py
├── BattleForRealMe.py
├── OnePlusJYStation.py
├── DailyCash.py
├── TaskCenter.py
└── sendNotify.py
/Doc/0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/0.png
--------------------------------------------------------------------------------
/Doc/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/1.png
--------------------------------------------------------------------------------
/Doc/10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/10.png
--------------------------------------------------------------------------------
/Doc/11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/11.png
--------------------------------------------------------------------------------
/Doc/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/2.png
--------------------------------------------------------------------------------
/Doc/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/3.png
--------------------------------------------------------------------------------
/Doc/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/4.png
--------------------------------------------------------------------------------
/Doc/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/5.png
--------------------------------------------------------------------------------
/Doc/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/6.png
--------------------------------------------------------------------------------
/Doc/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/7.png
--------------------------------------------------------------------------------
/Doc/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/8.png
--------------------------------------------------------------------------------
/Doc/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/HEAD/Doc/9.png
--------------------------------------------------------------------------------
/index.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/10/27
4 | # @Author : MashiroF
5 | # @File : index.py
6 | # @Software: PyCharm
7 | from importlib import import_module
8 |
9 | def main_handler(event, context):
10 | taskName = import_module(event['TriggerName'])
11 | taskName.main_handler(None, None)
12 |
--------------------------------------------------------------------------------
/HT_account.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/9/29
4 | # @Author : MashiroF
5 | # @File : HT_account.py
6 | # @Software: PyCharm
7 |
8 | ## 账号管理样本
9 | # {
10 | # 'user':'', # 备注,必要
11 | # 'CK':'', # Cookie,必要(建议全部粘贴)
12 | # 'UA':'' # User-Agent,必要
13 | # },
14 |
15 | ## 账号管理
16 | accounts = [
17 | {
18 | 'user':'',
19 | 'CK':'',
20 | 'UA':''
21 | },
22 | {
23 | 'user':'',
24 | 'CK':'',
25 | 'UA':''
26 | },
27 | ]
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 happy_and_healthy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Doc/README.md:
--------------------------------------------------------------------------------
1 | ### 准备:访问腾讯云函数
2 | [云函数直达](https://console.cloud.tencent.com/scf/list)
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 | | 定时任务名称 | Cron表达式 |
67 | | ----------------- | --------------- |
68 | | `TaskCenter` | `25 5,12 * * *` |
69 | | `ChockInEarly` | `35 0,19 * * *` |
70 | | `Double11` | `44 7,11 * * *` |
71 | | `BattleForRealMe` | `40 5,12 * * *` |
72 | | `DailyCash` | `30 5,12 * * *` |
73 | | `TimingCash` | `*/30 * * * *` |
74 |
75 | ---
76 |
--------------------------------------------------------------------------------
/HT_config.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/9/12
4 | # @Author : MashiroF
5 | # @File : HT_config.py
6 | # @Software: PyCharm
7 |
8 | #################################### 以下配置可更改 #########################################
9 | ## 云函数/青龙面板 环境变量优先级 > 配置文件 `HT_config` 变量优先级
10 | # 通知黑名单
11 | # 环境变量名:notifyBlack,多个以`&`隔开
12 | notifyBlackList = ['TimingCash','']
13 |
14 | ###########################################################################################
15 |
16 |
17 |
18 |
19 | ####################################### 以下配置不要动 #######################################
20 | # 导入系统内置包
21 | import os
22 | import sys
23 | import logging
24 |
25 | # 全局变量
26 | downFlag = False # 下载标志
27 | notifyBlack = None
28 |
29 | # 读取通知黑名单以及转盘抽奖环境变量
30 | if "Lottery" in os.environ:
31 | Lottery = os.environ["Lottery"]
32 | if "notifyBlack" in os.environ:
33 | notifyBlack = os.environ["notifyBlack"]
34 |
35 | # 日志模块
36 | logger = logging.getLogger(__name__)
37 | logger.setLevel(logging.INFO)
38 | logFormat = logging.Formatter("%(message)s")
39 |
40 | # 日志输出流
41 | stream = logging.StreamHandler()
42 | stream.setFormatter(logFormat)
43 | logger.addHandler(stream)
44 |
45 | # 第三方库
46 | try:
47 | import requests
48 | except ModuleNotFoundError:
49 | logger.info("缺少requests依赖!程序将尝试安装依赖!")
50 | os.system("pip3 install requests -i https://pypi.tuna.tsinghua.edu.cn/simple")
51 | os.execl(sys.executable, 'python3', __file__, *sys.argv)
52 |
53 | # 检测配置文件并下载函数
54 | # Ps:云函数可能不适用,该函数语法不够优雅,希望大佬给个优雅方案
55 | def checkFile(urlList):
56 | for url in urlList:
57 | fileName = url.split('/')[-1]
58 | fileUrl = f'https://ghproxy.com/{url}'
59 | try:
60 | if not os.path.exists(fileName):
61 | global downFlag
62 | downFlag = True
63 | logger.info(f"`{fileName}`不存在,尝试进行下载...")
64 | content = requests.get(url=fileUrl).content.decode('utf-8')
65 | with open(file=fileName, mode='w', encoding='utf-8') as fc:
66 | fc.write(content)
67 | except:
68 | logger.info(f'请手动下载配置文件`{fileName[:-3]}`到 {os.path.dirname(os.path.abspath(__file__))}')
69 | logger.info(f'下载地址:{fileUrl}\n')
70 |
71 | # 检测必备文件
72 | fileUrlList = [
73 | 'https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/main/sendNotify.py',
74 | 'https://raw.githubusercontent.com/Mashiro2000/HeyTapTask/main/HT_account.py'
75 | ]
76 | checkFile(fileUrlList)
77 |
78 | ## 提示文本
79 | if os.path.exists('/ql/config/auth.json'):
80 | logger.info("""
81 | 鉴于青龙面板会破坏欢太CK格式,尝试修复无效,故建议使用配置文件
82 | 该项目不再支持青龙面板`环境变量`添加账号,请将CK转移至配置文件
83 | 青龙面板 -> 脚本管理 -> 搜索`HT_account`关键字 -> 编辑
84 | CK最简格式:'source_type=xxx;TOKENSID=xxx;app_param=xxx;'
85 | """)
86 |
87 | ###########################################################################################
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #
HeyTapTask
2 | 早睡打卡,早起打卡需要验证,已下架脚本(欢太力度不大且验证码复杂,不再维护)
3 | 建议各位本地运行,由于本项目并不成熟,常变更拉库命令,请及时更新
4 | 喜欢这个项目?可以在右上角给颗⭐!你的支持是我最大的动力😎!
5 |
6 | ## 免责声明
7 | - 本仓库发布的HeyTapTask项目中涉及的任何脚本,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断.
8 |
9 | - 所有使用者在使用HeyTapTask项目的任何部分时,需先遵守法律法规。对于一切使用不当所造成的后果,需自行承担.对任何脚本问题概不负责,包括但不限于由任何脚本错误导致的任何损失或损害.
10 |
11 | - 如果任何单位或个人认为该项目可能涉嫌侵犯其权利,则应及时通知并提供身份证明,所有权证明,我们将在收到认证文件后删除相关文件.
12 |
13 | - 任何以任何方式查看此项目的人或直接或间接使用该HeyTapTask项目的任何脚本的使用者都应仔细阅读此声明。本人保留随时更改或补充此免责声明的权利。一旦使用并复制了任何相关脚本或HeyTapTask项目的规则,则视为您已接受此免责声明.
14 |
15 | 您必须在下载后的24小时内从计算机或手机中完全删除以上内容.
16 |
17 | > 您使用或者复制了本仓库且本人制作的任何脚本,则视为`已接受`此声明,请仔细阅读
18 |
19 | ## 环境
20 |
21 | [Python3](https://www.python.org/) >= 3.6
22 |
23 | ## 已实现功能
24 | * [x] 每日签到
25 | * [x] 每日浏览商品任务
26 | * [x] 每日分享商品任务
27 | * [x] ~~每日点推送任务~~(已下架)
28 | * [x] 赚积分活动
29 | * [x] ~~天天积分翻倍~~(暂时移除)
30 | * [x] 天天领现金任务列表
31 | * [x] 天天领现金定时红包
32 | * [x] 早睡打卡
33 | * [x] 集卡赢套票
34 | * [x] 积分大作战(realme)
35 | * [x] 积分大作战(HeyTap)
36 | * [x] 配信功能 由@Oreomeow开发
37 | * [x] OPPO社区早起打卡&OPPO社区签到(国内服务器)
38 |
39 | ## 文件说明
40 | ```text
41 | │ TaskCenter.py # 欢太商城任务中心
42 | │ TimingCash.py # 欢太定时红包
43 | │ DailyCash.py # 每日现金任务
44 | │ ChockInEarly.py # 欢太商城,早睡报名或打卡
45 | │ BattleForHeyTap.py # 积分大作战(欢太)
46 | │ BattleForRealMe.py # 积分大作战(真我)
47 | │ CollectionCard.py # 集卡赢套件(已下架)
48 | │ Community.py # OPPO社区(签到&早起打卡)
49 | │ HT_account.py # 欢太CK文件
50 | │ HT_config.py # 欢太配置文件
51 | │ sendNotify.py # 欢太配信文件(强制下载本项目配信文件,配信方式较全)
52 | │ README.md # 说明文档
53 | ```
54 |
55 | #### 一、Linux部署
56 | ```bash
57 | yum install python3 -y
58 |
59 | yum install git -y
60 |
61 | git clone https://ghproxy.com/https://github.com/Mashiro2000/HeyTapTask.git # 国内git较慢,故添加代理前缀
62 |
63 | cd HeyTapTask
64 |
65 | vi HT_account.py
66 | ```
67 |
68 | #### 二、青龙面板拉库指令
69 | ```text
70 | 第一次拉取
71 | ql repo https://github.com/Mashiro2000/HeyTapTask.git "" "Backup|index|HT.*|sendNotify" "HT.*|sendNotify"
72 |
73 | 拉取完成后,修改拉库指令,确保HT_account.py不被覆盖,更改拉库命令,命令如下
74 | ql repo https://github.com/Mashiro2000/HeyTapTask.git "" "Backup|index|HT.*|sendNotify" "HT_config|sendNotify"
75 | ```
76 |
77 | #### 三、云函数
78 | > 云函数教程:[点击直达](https://github.com/Mashiro2000/HeyTapTask/blob/main/Doc/README.md)
79 | > > 特别感谢@FgywAwut、@11yiyang提供的方案
80 |
81 | ##### 变量值
82 | - 测试表明欢太所需CK为: `source_type`、`TOKENSID`、`app_param`,顺序不可乱
83 | - 不再支持青龙面板`环境变量`添加账号的方案,请尽快将CK转移至配置文件
84 | - 原因:欢太变量采用json字符串,但青龙会将`HUAWEI P50`解析为`HUAWEIP50`
85 | - CK和UA中的特定字符会被错误的解析,为了长远发展,请使用配置文件
86 |
87 | ##### 编辑配置文件(本地/青龙/云函数)
88 | ```text
89 | {
90 | 'user':'', # 自定义备注(为了区分账号,包括未登录状态下)
91 | 'CK':'source_type=xxx;TOKENSID=TOKEN_xxxx;app_param=xxxx', # 用户环境变量 Cookie,建议全部粘贴,且顺序不可乱
92 | 'UA':'UA' # 用户环境变量 User-Agent
93 | }
94 | ```
95 |
96 | ##### 变量获取
97 | - CK和UA信息需自行抓包,欢太商城 -> 我的 -> 任务中心 -> 领券中心
98 | - 抓包地址:`https://store.oppo.com/cn/oapi/users/web/checkPeople/isNewPeople`
99 |
100 | - 集卡活动提示信息更改,缓存已刷新?
101 | - 欢太商城 -> 首页 -> 右上角集卡(访问进去)
102 |
103 | #### 其他帮助
104 | - Q:NameError: name '`xxxxxx`' is not defined
105 | - A:可能是因为CK的格式存在错误
106 |
107 | - Q:环境变量如何使用?
108 | - A:参考格式:`export notifyBlack="TimingCash&DailyCash"`
109 |
110 |
111 | #### 更新日志
112 |
113 |
114 |
115 | > 证明该项目仍然存活
116 |
117 | 2021-9-29
118 | 重构代码,确保后续更新不在涉及`HT_account.py`文件,新增环境变量`notifyBlack`
119 |
120 |
121 |
--------------------------------------------------------------------------------
/TimingCash.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/9/17
4 | # @Author : MashiroF
5 | # @File : TimingCash.py
6 | # @Software: PyCharm
7 |
8 | '''
9 | cron: */30 * * * * TimingCash.py
10 | new Env('欢太定时现金');
11 | '''
12 |
13 | import os
14 | import re
15 | import sys
16 | import time
17 | import random
18 |
19 | # 配置文件
20 | try:
21 | from HT_config import downFlag,notifyBlackList,logger
22 | import requests
23 | except Exception as error:
24 | logger.info(f'失败原因:{error}')
25 | sys.exit(0)
26 |
27 | # 判断是否发生下载行为
28 | if downFlag == True:
29 | logger.info('发生下载行为,应退出程序,编辑配置文件')
30 | sys.exit(0)
31 |
32 | # 配信文件
33 | try:
34 | from sendNotify import send
35 | except Exception as error:
36 | logger.info('推送文件有误')
37 | logger.info(f'失败原因:{error}')
38 | sys.exit(0)
39 |
40 | # 导入账户
41 | try:
42 | from HT_account import accounts
43 | lists = accounts
44 | except Exception as error:
45 | logger.info(f'失败原因:{error}')
46 | lists = []
47 |
48 | # 配信内容格式
49 | allMess = ''
50 | def notify(content=None):
51 | global allMess
52 | allMess = allMess + content + '\n'
53 | logger.info(content)
54 |
55 | # 日志录入时间
56 | notify(f"任务:欢太定时现金\n时间:{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())}")
57 |
58 | class TimingCash:
59 | def __init__(self,dic):
60 | self.dic = dic
61 | self.sess = requests.session()
62 |
63 | # 登录验证
64 | def login(self):
65 | url = 'https://store.oppo.com/cn/oapi/users/web/member/check'
66 | headers = {
67 | 'Host': 'store.oppo.com',
68 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
69 | 'Content-Type': 'application/x-www-form-urlencoded',
70 | 'Connection': 'keep-alive',
71 | 'Accept-Language': 'zh-cn',
72 | 'Accept-Encoding': 'gzip, deflate, br',
73 | }
74 | response = self.sess.get(url=url,headers=headers).json()
75 | if response['code'] == 200:
76 | notify(f"{self.dic['user']}\t登录成功")
77 | return True
78 | else:
79 | notify(f"{self.dic['user']}\t登录失败")
80 | return False
81 |
82 | # 天天领取现金
83 | def getDailyCashTask(self):
84 | url = 'https://store.oppo.com/cn/oapi/omp-web/web/dailyCash/queryActivityReward'
85 | headers = {
86 | 'Host': 'store.oppo.com',
87 | 'Connection': 'keep-alive',
88 | 'source_type': '501',
89 | 'clientPackage': 'com.oppo.store',
90 | 'Accept': 'application/json, text/plain, */*',
91 | 'Referer': 'https://store.oppo.com/cn/app/cashRedEnvelope?activityId=1&us=shouye&um=xuanfu&uc=xianjinhongbao',
92 | 'Accept-Encoding': 'gzip, deflate',
93 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
94 | }
95 | params = {
96 | 'activityId':1
97 | }
98 | response = self.sess.get(url=url,headers=headers,params=params).json()
99 | if response['code'] == 200:
100 | self.timingRewardList = response['data']['timingRewardList']
101 | return True
102 | elif response['code'] == 1000001:
103 | notify(f"[定时红包]\t{response['errorMessage']}")
104 | return False
105 |
106 | def getCash(self,dic):
107 | url = 'https://store.oppo.com/cn/oapi/omp-web/web/dailyCash/drawReward'
108 | headers = {
109 | 'Host': 'store.oppo.com',
110 | 'Connection': 'keep-alive',
111 | 'Origin': 'https://store.oppo.com',
112 | 'source_type': '501',
113 | 'clientPackage': 'com.oppo.store',
114 | 'Content-Type': 'application/x-www-form-urlencoded',
115 | 'Accept': 'application/json, text/plain, */*',
116 | 'Referer': 'https://store.oppo.com/cn/app/cashRedEnvelope?activityId=1&us=shouye&um=xuanfu&uc=xianjinhongbao',
117 | 'Accept-Encoding': 'gzip, deflate',
118 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
119 | }
120 | data = {
121 | 'activityId':1,
122 | 'channel':1,
123 | 'channelRewardId':dic['id']
124 | }
125 | response = self.sess.post(url=url,headers=headers,data=data).json()
126 | if response['code'] == 200:
127 | notify(f"[定时红包]\t第{dic['id']}个红包:{response['data']['amount']}")
128 | elif response['code'] == 1000001:
129 | notify(f"[定时红包]\t第{dic['id']}个红包:{response['errorMessage']}")
130 |
131 | def runtimeReward(self):
132 | for each in self.timingRewardList:
133 | if each['hasDraw'] == False:
134 | self.getCash(dic=each)
135 | break
136 |
137 | # 执行欢太商城实例对象
138 | def start(self):
139 | self.sess.headers.update({
140 | "User-Agent":self.dic['UA']
141 | })
142 | self.sess.cookies.update({
143 | "Cookie": self.dic['CK']
144 | })
145 | if self.login() == True:
146 | if self.getDailyCashTask() == True:
147 | self.runtimeReward()
148 |
149 | # 检测CK是否存在必备参数
150 | def checkHT(dic):
151 | CK = dic['CK']
152 | if len(re.findall(r'source_type=.*?;',CK)) == 0:
153 | notify(f"{dic['user']}\tCK格式有误:可能缺少`source_type`字段")
154 | return False
155 | if len(re.findall(r'TOKENSID=.*?;',CK)) == 0:
156 | notify(f"{dic['user']}\tCK格式有误:可能缺少`TOKENSID`字段")
157 | return False
158 | if len(re.findall(r'app_param=.*?[;]?',CK)) == 0:
159 | notify(f"{dic['user']}\tCK格式有误:可能缺少`app_param`字段")
160 | return False
161 | return True
162 |
163 | # 兼容云函数
164 | def main_handler(event, context):
165 | global lists
166 | for each in lists:
167 | if each['CK']!='' and each['UA'] != '':
168 | if checkHT(each):
169 | timingCash = TimingCash(each)
170 | for count in range(3):
171 | try:
172 | time.sleep(random.randint(2,5)) # 随机延时
173 | timingCash.start()
174 | break
175 | except requests.exceptions.ConnectionError:
176 | notify(f"{timingCash.dic['user']}\t请求失败,随机延迟后再次访问")
177 | time.sleep(random.randint(2,5))
178 | continue
179 | else:
180 | notify(f"账号: {timingCash.dic['user']}\n状态: 取消登录\n原因: 多次登录失败")
181 | break
182 | elif not all(each.values()):
183 | notify("账号:空账户\t状态:跳过")
184 | else:
185 | notify(f"账号: {each['user']}\n状态: 取消登录\n原因: json数据不齐全")
186 | notify('*' * 40 + '\n')
187 | if not os.path.basename(__file__).split('_')[-1][:-3] in notifyBlackList:
188 | send('欢太定时现金',allMess)
189 |
190 | if __name__ == '__main__':
191 | main_handler(None,None)
192 |
--------------------------------------------------------------------------------
/Backup/ChockInEarly.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/9/12
4 | # @Author : MashiroF
5 | # @File : ChockInEarly.py
6 | # @Software: PyCharm
7 |
8 | '''
9 | cron: 35 0,19 * * * ChockInEarly.py
10 | new Env('欢太早睡打卡');
11 | '''
12 |
13 | import os
14 | import re
15 | import sys
16 | import time
17 | import random
18 |
19 | # 配置文件
20 | try:
21 | from HT_config import downFlag,notifyBlackList,logger
22 | import requests
23 | except Exception as error:
24 | logger.info(f'失败原因:{error}')
25 | sys.exit(0)
26 |
27 | # 判断是否发生下载行为
28 | if downFlag == True:
29 | logger.info('发生下载行为,应退出程序,编辑配置文件')
30 | sys.exit(0)
31 |
32 | # 配信文件
33 | try:
34 | from sendNotify import send
35 | except Exception as error:
36 | logger.info('推送文件有误')
37 | logger.info(f'失败原因:{error}')
38 | sys.exit(0)
39 |
40 | # 导入账户
41 | try:
42 | from HT_account import accounts
43 | lists = accounts
44 | except Exception as error:
45 | logger.info(f'失败原因:{error}')
46 | lists = []
47 |
48 | # 配信内容格式
49 | allMess = ''
50 | def notify(content=None):
51 | global allMess
52 | allMess = allMess + content + '\n'
53 | logger.info(content)
54 |
55 | # 日志录入时间
56 | notify(f"任务:欢太早睡打卡\n时间:{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())}")
57 |
58 | class CheckInEarly:
59 | def __init__(self,dic):
60 | self.dic = dic
61 | self.sess = requests.session()
62 |
63 | # 登录验证
64 | def login(self):
65 | url = 'https://store.oppo.com/cn/oapi/users/web/member/check'
66 | headers = {
67 | 'Host': 'store.oppo.com',
68 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
69 | 'Content-Type': 'application/x-www-form-urlencoded',
70 | 'Connection': 'keep-alive',
71 | 'Accept-Language': 'zh-cn',
72 | 'Accept-Encoding': 'gzip, deflate, br',
73 | }
74 | response = self.sess.get(url=url,headers=headers).json()
75 | if response['code'] == 200:
76 | notify(f"{self.dic['user']}\t登录成功")
77 | return True
78 | else:
79 | notify(f"{self.dic['user']}\t登录失败")
80 | return False
81 |
82 | # 报名或打卡
83 | # 报名或打卡是同一个链接,配合Linux定时系统
84 | def early(self):
85 | url = 'https://store.oppo.com/cn/oapi/credits/web/clockin/applyOrClockIn'
86 | headers = {'Host': 'store.oppo.com',
87 | 'Connection': 'keep-alive',
88 | 'source_type': '501',
89 | 'clientPackage': 'com.oppo.store',
90 | 'Accept': 'application/json, text/plain, */*',
91 | 'Referer': 'https://store.oppo.com/cn/app/cardingActivities?us=gerenzhongxin&um=hudongleyuan&uc=zaoshuidaka',
92 | 'Accept-Encoding': 'gzip, deflate',
93 | 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7'
94 | }
95 | response = self.sess.get(url=url,headers=headers).json()
96 | if response['code'] == 200:
97 | if response['data']['clockInStatus'] == 0:
98 | if response['data']['applyStatus'] == 0:
99 | notify(f"{self.dic['user']}\t积分过少,取消报名!")
100 | elif response['data']['applyStatus'] == 1:
101 | notify(f"{self.dic['user']}\t报名成功!")
102 | elif response['data']['applyStatus'] == 2:
103 | notify(f"{self.dic['user']}\t已报名!")
104 | elif response['data']['clockInStatus'] == 1:
105 | notify(f"{self.dic['user']}\t早睡瓜分积分,打卡成功!")
106 | elif response['data']['clockInStatus'] == 2:
107 | notify(f"{self.dic['user']}\t早睡瓜分积分,已成功打卡!")
108 | elif response['code'] == 1000005:
109 | notify(f"{self.dic['user']}\t{response['errorMessage']}")
110 |
111 | # 获取积分数量(只找到这个,找不到昨天积分数据)
112 | def getIntegral(self):
113 | url = 'https://store.oppo.com/cn/oapi/credits/web/credits/show'
114 | headers = {
115 | 'Host': 'store.oppo.com',
116 | 'Connection': 'keep-alive',
117 | 'source_type': '501',
118 | 'clientPackage': 'com.oppo.store',
119 | 'Accept': 'application/json, text/plain, */*',
120 | 'Accept-Encoding': 'gzip, deflate',
121 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
122 | 'X-Requested-With': 'com.oppo.store',
123 | 'Referer': 'https://store.oppo.com/cn/app/taskCenter/index?us=gerenzhongxin&um=hudongleyuan&uc=renwuzhongxin'
124 | }
125 | response = self.sess.get(url=url,headers=headers).json()
126 | if response['code'] == 200:
127 | return f"{self.dic['user']}\t总积分:{response['data']['userCredits']}"
128 | else:
129 | return f"{self.dic['user']}\t错误原因:{response}"
130 |
131 | # 执行欢太商城实例对象
132 | def start(self):
133 | self.sess.headers.update({
134 | "User-Agent":self.dic['UA']
135 | })
136 | self.sess.cookies.update({
137 | "Cookie":self.dic['CK']
138 | })
139 | if self.login() == True:
140 | self.early()
141 | notify(self.getIntegral())
142 |
143 | # 检测CK是否存在必备参数
144 | def checkHT(dic):
145 | CK = dic['CK']
146 | if len(re.findall(r'source_type=.*?;',CK)) == 0:
147 | notify(f"{dic['user']}\tCK格式有误:可能缺少`source_type`字段")
148 | return False
149 | if len(re.findall(r'TOKENSID=.*?;',CK)) == 0:
150 | notify(f"{dic['user']}\tCK格式有误:可能缺少`TOKENSID`字段")
151 | return False
152 | if len(re.findall(r'app_param=.*?[;]?',CK)) == 0:
153 | notify(f"{dic['user']}\tCK格式有误:可能缺少`app_param`字段")
154 | return False
155 | return True
156 |
157 | # 兼容云函数
158 | def main_handler(event, context):
159 | global lists
160 | for each in lists:
161 | if each['CK']!='' and each['UA'] != '':
162 | if checkHT(each):
163 | checkInEarly = CheckInEarly(each)
164 | for count in range(3):
165 | try:
166 | time.sleep(random.randint(2,5)) # 随机延时
167 | checkInEarly.start()
168 | break
169 | except requests.exceptions.ConnectionError:
170 | notify(f"{checkInEarly.dic['user']}\t请求失败,随机延迟后再次访问")
171 | time.sleep(random.randint(2,5))
172 | continue
173 | else:
174 | notify(f"账号: {checkInEarly.dic['user']}\n状态: 取消登录\n原因: 多次登录失败")
175 | break
176 | elif not all(each.values()):
177 | notify("账号:空账户\t状态:跳过")
178 | else:
179 | notify(f"账号: {each['user']}\n状态: 取消登录\n原因: json数据不齐全")
180 | notify('*' * 40 + '\n')
181 | if not os.path.basename(__file__).split('_')[-1][:-3] in notifyBlackList:
182 | send('欢太早睡打卡',allMess)
183 |
184 | if __name__ == '__main__':
185 | main_handler(None,None)
186 |
--------------------------------------------------------------------------------
/Backup/Community.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/11/14
4 | # @Author : MashiroF
5 | # @File : Community.py
6 | # @Software: PyCharm
7 |
8 | '''
9 | cron: 30 6,12 * * * Community.py
10 | new Env('OPPO社区签到、早起打卡');
11 | '''
12 |
13 | import os
14 | import re
15 | import sys
16 | import time
17 | import random
18 | import requests
19 |
20 | # 配置文件
21 | try:
22 | from HT_config import downFlag,notifyBlackList,logger
23 | except Exception as error:
24 | logger.info(f'失败原因:{error}')
25 | sys.exit(0)
26 |
27 | # 判断是否发生下载行为
28 | if downFlag == True:
29 | logger.info('发生下载行为,应退出程序,编辑配置文件')
30 | sys.exit(0)
31 |
32 | # 配信文件
33 | try:
34 | from sendNotify import send
35 | except Exception as error:
36 | logger.info('推送文件有误')
37 | logger.info(f'失败原因:{error}')
38 | sys.exit(0)
39 |
40 | # 导入账户
41 | try:
42 | from HT_account import accounts
43 | lists = accounts
44 | except Exception as error:
45 | logger.info(f'失败原因:{error}')
46 | lists = []
47 |
48 | # 配信内容格式
49 | allMess = ''
50 | def notify(content=None):
51 | global allMess
52 | allMess = allMess + content + '\n'
53 | logger.info(content)
54 |
55 | # 日志录入时间
56 | notify(f"任务:OPPO社区签到、早起打卡\n时间:{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())}")
57 |
58 | class Community:
59 | def __init__(self,dic):
60 | self.sess = requests.session()
61 | self.dic = dic
62 | self.ID = 453509395675611143
63 |
64 | def login(self):
65 | url = 'https://i-user.oppo.cn/member/v3/index/get.pb'
66 | headers = {
67 | "Accept-Encoding": "gzip",
68 | "Connection": "Keep-Alive",
69 | "Host": "i-user.oppo.cn",
70 | "TAP-GSLB": "0,0",
71 | "User-Agent": "okhttp/3.12.12.217",
72 | 'Accept': 'application/json, text/plain, */*'
73 | }
74 | response = self.sess.get(url=url,headers=headers).json()
75 | if response['message']['code'] == 200:
76 | self.loginMess = response
77 | notify(f"{self.dic['user']}\t登录成功")
78 | return True
79 | else:
80 | notify(f"{self.dic['user']}\t登录失败")
81 | return False
82 |
83 | # def computerValue(self,c,d):
84 | # r = int(d + (random.random() % 10) * 16) % 16 | 0
85 | # d = math.floor(d / 16)
86 | # return d,hex(r if c == 'x' else (r & 0x3 | 0x8))[-1]
87 | #
88 | # def generateUUID(self):
89 | # d = round(time.time() * 1000)
90 | # oldStr = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
91 | # newStr = ''
92 | # for i in oldStr:
93 | # if i == 'x' or i == 'y':
94 | # d,v = self.computerValue(i,d)
95 | # newStr += v
96 | # else:
97 | # newStr += i
98 | # return newStr
99 |
100 | def ClockIn(self):
101 | url = 'https://i-api.oppo.cn/sign/v1/index/create.pb'
102 | headers = {
103 | "Accept-Encoding": "gzip",
104 | "Connection": "Keep-Alive",
105 | "Host": "i-api.oppo.cn",
106 | "TAP-GSLB": "0,0",
107 | "User-Agent": "okhttp/3.12.12.217",
108 | 'Accept': 'application/json, text/plain, */*'
109 | }
110 | response = self.sess.get(url=url,headers=headers).json()
111 | if response['message']['code'] == 200 and response['message']['msg'] == '操作成功':
112 | notify(f"[每日签到]\t签到成功")
113 | elif response['message']['code'] == 200 and response['message']['msg'] == 'SUCCESS':
114 | notify(f"[每日签到]\t已签到")
115 | else:
116 | notify(f"[每日签到]\t签到失败\t失败原因:{response}")
117 |
118 | def SignUp(self):
119 | url = 'https://hdapi.oppo.cn/user/attendance/signUp'
120 | headers = {
121 | "Accept": "*/*",
122 | "Accept-Encoding": "gzip, deflate",
123 | "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
124 | "Cache-Control": "no-cache",
125 | "Connection": "keep-alive",
126 | "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
127 | "Host": "hdapi.oppo.cn",
128 | "Origin": "https://hdpage.oppo.cn",
129 | "Pragma": "no-cache",
130 | "Referer": f"https://hdpage.oppo.cn/rglpdu/index.html?id={self.ID}",
131 | "X-Requested-With": "XMLHttpRequest"
132 | }
133 | data = {
134 | 'attendanceId':self.ID,
135 | 'nickName':self.loginMess['nickname']
136 | }
137 | response = self.sess.post(url=url,headers=headers,data=data).json()
138 | if response['code'] == 200:
139 | notify(f"[早起打卡]\t报名成功")
140 | else:
141 | notify(f"[早起打卡]\t{response['msg']}")
142 |
143 |
144 | def SignIn(self):
145 | url = 'https://hdapi.oppo.cn/user/attendance/signIn'
146 | headers = {
147 | "Accept": "*/*",
148 | "Accept-Encoding": "gzip, deflate",
149 | "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
150 | "Cache-Control": "no-cache",
151 | "Connection": "keep-alive",
152 | "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
153 | "Host": "hdapi.oppo.cn",
154 | "Origin": "https://hdpage.oppo.cn",
155 | "Pragma": "no-cache",
156 | "Referer": f"https://hdpage.oppo.cn/rglpdu/index.html?id={self.ID}",
157 | "X-Requested-With": "XMLHttpRequest"
158 | }
159 | data = {
160 | 'attendanceId':self.ID
161 | }
162 | response = self.sess.post(url=url,headers=headers,data=data).json()
163 | if response['code'] == 200:
164 | notify(f"[早起打卡]\t打卡成功")
165 | else:
166 | notify(f"[早起打卡]\t{response['msg']}")
167 |
168 | def getTime(self):
169 | now = time.time()
170 | TZ = time.strftime("%Z", time.localtime(now))
171 | if TZ == 'UTC' or TZ == '协调世界时':
172 | return time.strftime('%H:%M:%S',time.localtime(now+ 8*3600))
173 | elif TZ == 'CST' or TZ == '中国标准时间':
174 | return time.strftime('%H:%M:%S',time.localtime(now))
175 | else:
176 | notify(f"时区设置错误,当前时区:{TZ}\t预期时区:CST")
177 | return False
178 |
179 | def earlyBed(self):
180 | now = self.getTime()
181 | if now != False:
182 | if now > '09:30:00' and now < '23:59:00':
183 | self.SignUp()
184 | elif now > '05:30:00' and now < '09:00:00':
185 | self.SignIn()
186 | else:
187 | notify(f"[早起打卡]\t打卡报名时间段外,取消后续操作")
188 |
189 |
190 | def start(self):
191 | token = re.findall(r'TOKENSID=(TOKEN.*?;)',self.dic['CK'],re.S)
192 | if token !=[]:
193 | self.sess.headers.update({
194 | "User-Agent":self.dic['UA']
195 | })
196 | self.sess.cookies.update({
197 | "Cookie": ';token=' + token[0]
198 | })
199 | if self.login() == True:
200 | self.ClockIn()
201 | self.earlyBed ()
202 |
203 | def checkHT(dic):
204 | if len(re.findall(r'TOKENSID=.*?;',dic['CK'])) == 0:
205 | notify(f"{dic['user']}\tCK格式有误:可能缺少`TOKENSID`字段")
206 | return False
207 | return True
208 |
209 | # 兼容云函数
210 | def main_handler(event, context):
211 | global lists
212 | for each in lists:
213 | if each['CK']!='' and each['UA'] != '':
214 | if checkHT(each):
215 | community = Community(each)
216 | for count in range(3):
217 | try:
218 | time.sleep(random.randint(2,5)) # 随机延时
219 | community.start()
220 | break
221 | except requests.exceptions.ConnectionError:
222 | notify(f"{community.dic['user']}\t请求失败,随机延迟后再次访问")
223 | time.sleep(random.randint(2,5))
224 | continue
225 | else:
226 | notify(f"账号: {community.dic['user']}\n状态: 取消登录\n原因: 多次登录失败")
227 | elif not all(each.values()):
228 | notify("账号:空账户\t状态:跳过")
229 | else:
230 | notify(f"账号: {each['user']}\n状态: 取消登录\n原因: json数据不齐全")
231 | notify('*' * 40 + '\n')
232 | if not os.path.basename(__file__).split('_')[-1][:-3] in notifyBlackList:
233 | send('OPPO社区签到、早起打卡',allMess)
234 |
235 | if __name__ == '__main__':
236 | main_handler(None,None)
237 |
--------------------------------------------------------------------------------
/Backup/CollectionCard.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/9/26
4 | # @Author : MashiroF
5 | # @File : CollectionCard.py
6 | # @Software: PyCharm
7 |
8 | '''
9 | cron: 46 5,12 * * * CollectionCard.py
10 | new Env('集卡赢套票');
11 | '''
12 |
13 | import os
14 | import re
15 | import sys
16 | import time
17 | import random
18 | import requests
19 |
20 | # 配置文件
21 | try:
22 | from HT_config import downFlag,notifyBlackList,logger
23 | except Exception as error:
24 | logger.info(f'失败原因:{error}')
25 | sys.exit(0)
26 |
27 | # 判断是否发生下载行为
28 | if downFlag == True:
29 | logger.info('发生下载行为,应退出程序,编辑配置文件')
30 | sys.exit(0)
31 |
32 | # 配信文件
33 | try:
34 | from sendNotify import send
35 | except Exception as error:
36 | logger.info('推送文件有误')
37 | logger.info(f'失败原因:{error}')
38 | sys.exit(0)
39 |
40 | # 导入账户
41 | try:
42 | from HT_account import accounts
43 | lists = accounts
44 | except Exception as error:
45 | logger.info(f'失败原因:{error}')
46 | lists = []
47 |
48 | # 配信内容格式
49 | allMess = ''
50 | def notify(content=None):
51 | global allMess
52 | allMess = allMess + content + '\n'
53 | logger.info(content)
54 |
55 | # 日志录入时间
56 | notify(f"任务:集卡赢套票\n时间:{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())}")
57 |
58 | class CollectionCard:
59 | def __init__(self,dic):
60 | self.dic = dic
61 | self.sess = requests.session()
62 |
63 | # 登录验证
64 | def login(self):
65 | url = 'https://store.oppo.com/cn/oapi/users/web/member/check'
66 | headers = {
67 | 'Host': 'store.oppo.com',
68 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
69 | 'Content-Type': 'application/x-www-form-urlencoded',
70 | 'Connection': 'keep-alive',
71 | 'Accept-Language': 'zh-cn',
72 | 'Accept-Encoding': 'gzip, deflate, br',
73 | }
74 | response = self.sess.get(url=url,headers=headers).json()
75 | if response['code'] == 200:
76 | notify(f"{self.dic['user']}\t登录成功")
77 | return True
78 | else:
79 | notify(f"{self.dic['user']}\t登录失败")
80 | return False
81 |
82 | def drawCard(self):
83 | url = 'https://store.oppo.com/cn/oapi/credits/web/ccv2/collect'
84 | headers = {
85 | "Host": "store.oppo.com",
86 | "Connection": "keep-alive",
87 | "s_channel": "oppo_appstore",
88 | "utm_term": "direct",
89 | "source_type": "501",
90 | "utm_campaign": "direct",
91 | "utm_source": "jika",
92 | "ut": "direct",
93 | "uc": "direct",
94 | "clientPackage": "com.oppo.store",
95 | "Cache-Control": "no-cache",
96 | "um": "youshangjiao",
97 | "ouid": "",
98 | "Content-Type": "application/x-www-form-urlencoded",
99 | "Accept": "application/json, text/plain, */*",
100 | "guid": "",
101 | "utm_medium": "xidi",
102 | "appId": "",
103 | "s_version": "201201",
104 | "us": "shouye",
105 | "appKey": "",
106 | "Origin": "https://store.oppo.com",
107 | "X-Requested-With": "com.oppo.store",
108 | "Referer": "https://store.oppo.com/cn/app/collectCard/index?activityId=RWTNLNQ8&us=shouye&um=youshangjiao",
109 | "Accept-Encoding": "gzip, deflate",
110 | "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7"
111 | }
112 | data = {
113 | 'activityId':'RWTNLNQ8'
114 | }
115 | while True:
116 | response = self.sess.post(url=url,headers=headers,data=data).json()
117 | if response['code'] == 200:
118 | notify(f"[集卡活动]\t结果:{response['data']['collectCard']['cardName']}")
119 | else:
120 | notify(f"[集卡活动]\t{response['errorMessage']}")
121 | break
122 | time.sleep(random.randint(3,5))
123 |
124 |
125 | def getTaskList(self):
126 | url = 'https://store.oppo.com/cn/oapi/credits/web/ccv2/showTaskList?activityId=RWTNLNQ8'
127 | headers = {
128 | "Host": "store.oppo.com",
129 | "Connection": "keep-alive",
130 | "s_channel": "oppo_appstore",
131 | "utm_term": "direct",
132 | "source_type": "501",
133 | "utm_campaign": "direct",
134 | "appKey": "",
135 | "ut": "direct",
136 | "uc": "direct",
137 | "clientPackage": "com.oppo.store",
138 | "Cache-Control": "no-cache",
139 | "um": "youshangjiao",
140 | "ouid": "",
141 | "Accept": "application/json, text/plain, */*",
142 | "guid": "",
143 | "appId": "",
144 | "s_version": "201201",
145 | "us": "shouye",
146 | "utm_source": "jika",
147 | "X-Requested-With": "com.oppo.store",
148 | "Referer": "https://store.oppo.com/cn/app/collectCard/index?activityId=RWTNLNQ8&us=shouye&um=youshangjiao",
149 | "Accept-Encoding": "gzip, deflate",
150 | "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7"
151 | }
152 | response = self.sess.get(url=url,headers=headers).json()
153 |
154 | if response['code'] == 200:
155 | self.taskData = response['data']
156 | return True
157 | else:
158 | notify(f"{response}")
159 | return False
160 | time.sleep(random.randint(1,3))
161 |
162 | def runTask(self,dic):
163 | url = 'https://store.oppo.com/cn/oapi/credits/web/ccv2/ReportedTask'
164 | params = {
165 | 'activityId':'RWTNLNQ8',
166 | 'taskType':dic['taskId']
167 | }
168 | headers = {
169 | "Host": "store.oppo.com",
170 | "Connection": "keep-alive",
171 | "s_channel": "oppo_appstore",
172 | "utm_term": "direct",
173 | "source_type": "501",
174 | "utm_campaign": "direct",
175 | "appKey": "",
176 | "ut": "direct",
177 | "uc": "direct",
178 | "clientPackage": "com.oppo.store",
179 | "Cache-Control": "no-cache",
180 | "um": "youshangjiao",
181 | "ouid": "",
182 | "Accept": "application/json, text/plain, */*",
183 | "guid": "",
184 | "utm_medium": "xidi",
185 | "appId": "",
186 | "s_version": "201201",
187 | "us": "shouye",
188 | "utm_source": "jika",
189 | "X-Requested-With": "com.oppo.store",
190 | "Referer": "https://store.oppo.com/cn/app/collectCard/index?activityId=RWTNLNQ8&us=shouye&um=youshangjiao",
191 | "Accept-Encoding": "gzip, deflate",
192 | "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7"
193 | }
194 | response = self.sess.get(url=url,params=params,headers=headers).json()
195 | if response['code'] == 200:
196 | notify(f"[{dic['name']}]\t任务完成")
197 | else:
198 | notify(f"[{dic['name']}]\tcode:{response['code']}")
199 | time.sleep(random.randint(3,5))
200 |
201 | def runTaskList(self):
202 | for each in self.taskData:
203 | if each['name'] == '每日打卡':
204 | if each['status'] == 0:
205 | self.runTask(dic=each)
206 | elif each['status'] == 2:
207 | notify(f"[{each['name']}]\t已打卡")
208 | elif each['name'] == '浏览会员日主会场':
209 | if each['status'] == 0:
210 | self.runTask(dic=each)
211 | elif each['status'] == 2:
212 | notify(f"[{each['name']}]\t已浏览")
213 | elif each['name'] == '分享活动':
214 | if each['status'] == 0:
215 | self.runTask(dic=each)
216 | elif each['status'] == 2:
217 | notify(f"[{each['name']}]\t已浏览")
218 | elif each['name'] == '浏览会员中心':
219 | if each['status'] == 0:
220 | self.runTask(dic=each)
221 | elif each['status'] == 2:
222 | notify(f"[{each['name']}]\t已浏览")
223 | elif each['name'] == '浏览秒杀频道':
224 | if each['status'] == 0:
225 | self.runTask(dic=each)
226 | elif each['status'] == 2:
227 | notify(f"[{each['name']}]\t已浏览")
228 | elif each['name'] == '浏览领券中心':
229 | if each['status'] == 0:
230 | self.runTask(dic=each)
231 | elif each['status'] == 2:
232 | notify(f"[{each['name']}]\t已浏览")
233 |
234 | # 执行欢太商城实例对象
235 | def start(self):
236 | self.sess.headers.update({
237 | "User-Agent":self.dic['UA']
238 | })
239 | self.sess.cookies.update({
240 | "Cookie": self.dic['CK']
241 | })
242 | if self.login() == True:
243 | if self.getTaskList() == True: # 获取任务中心数据,判断CK是否正确(登录可能成功,但无法跑任务)
244 | self.runTaskList() # 运行任务中心
245 | self.drawCard()
246 | notify('*' * 40 + '\n')
247 |
248 | # 检测CK是否存在必备参数
249 | def checkHT(dic):
250 | CK = dic['CK']
251 | if len(re.findall(r'source_type=.*?;',CK)) == 0:
252 | notify(f"{dic['user']}\tCK格式有误:可能缺少`source_type`字段")
253 | return False
254 | if len(re.findall(r'TOKENSID=.*?;',CK)) == 0:
255 | notify(f"{dic['user']}\tCK格式有误:可能缺少`TOKENSID`字段")
256 | return False
257 | if len(re.findall(r'app_param=.*?[;]?',CK)) == 0:
258 | notify(f"{dic['user']}\tCK格式有误:可能缺少`app_param`字段")
259 | return False
260 | return True
261 |
262 | # 兼容云函数
263 | def main_handler(event, context):
264 | global lists
265 | for each in lists:
266 | if all(each.values()):
267 | if checkHT(each):
268 | collectionCard = CollectionCard(each)
269 | for count in range(3):
270 | try:
271 | time.sleep(random.randint(2,5)) # 随机延时
272 | collectionCard.start()
273 | break
274 | except requests.exceptions.ConnectionError:
275 | notify(f"{collectionCard.dic['user']}\t请求失败,随机延迟后再次访问")
276 | time.sleep(random.randint(2,5))
277 | continue
278 | else:
279 | notify(f"账号: {collectionCard.dic['user']}\n状态: 取消登录\n原因: 多次登录失败")
280 | break
281 | elif not all(each.values()):
282 | notify("账号:空账户\t状态:跳过")
283 | else:
284 | notify(f"账号: {each['user']}\n状态: 取消登录\n原因: json数据不齐全")
285 | if not os.path.basename(__file__).split('_')[-1][:-3] in notifyBlackList:
286 | send('集卡赢套票',allMess)
287 |
288 | if __name__ == '__main__':
289 | main_handler(None,None)
290 |
--------------------------------------------------------------------------------
/Backup/BattleForHeyTap.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/9/26
4 | # @Author : MashiroF
5 | # @File : BattleForHeyTap.py
6 | # @Software: PyCharm
7 |
8 | '''
9 | cron: 45 5,12 * * * BattleForHeyTap.py
10 | new Env('欢太积分大乱斗');
11 | '''
12 |
13 | import os
14 | import re
15 | import sys
16 | import time
17 | import random
18 | import requests
19 |
20 | # 配置文件
21 | try:
22 | from HT_config import downFlag,notifyBlackList,logger
23 | except Exception as error:
24 | logger.info(f'失败原因:{error}')
25 | sys.exit(0)
26 |
27 | # 判断是否发生下载行为
28 | if downFlag == True:
29 | logger.info('发生下载行为,应退出程序,编辑配置文件')
30 | sys.exit(0)
31 |
32 | # 配信文件
33 | try:
34 | from sendNotify import send
35 | except Exception as error:
36 | logger.info('推送文件有误')
37 | logger.info(f'失败原因:{error}')
38 | sys.exit(0)
39 |
40 | # 导入账户
41 | try:
42 | from HT_account import accounts
43 | lists = accounts
44 | except Exception as error:
45 | logger.info(f'失败原因:{error}')
46 | lists = []
47 |
48 | # 配信内容格式
49 | allMess = ''
50 | def notify(content=None):
51 | global allMess
52 | allMess = allMess + content + '\n'
53 | logger.info(content)
54 |
55 | # 日志录入时间
56 | notify(f"任务:欢太积分大乱斗\n时间:{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())}")
57 |
58 | class BattleForHeyTap:
59 | def __init__(self,dic):
60 | self.dic = dic
61 | self.sess = requests.session()
62 |
63 | # 登录验证
64 | def login(self):
65 | url = 'https://store.oppo.com/cn/oapi/users/web/member/check'
66 | headers = {
67 | 'Host': 'store.oppo.com',
68 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
69 | 'Content-Type': 'application/x-www-form-urlencoded',
70 | 'Connection': 'keep-alive',
71 | 'Accept-Language': 'zh-cn',
72 | 'Accept-Encoding': 'gzip, deflate, br',
73 | }
74 | response = self.sess.get(url=url,headers=headers).json()
75 | if response['code'] == 200:
76 | notify(f"{self.dic['user']}\t登录成功")
77 | return True
78 | else:
79 | notify(f"{self.dic['user']}\t登录失败")
80 | return False
81 |
82 | def receiveAward(self,dic):
83 | aid = 1598
84 | url = 'https://hd.oppo.com/task/award'
85 | headers = {
86 | 'Host': 'hd.oppo.com',
87 | 'Connection': 'keep-alive',
88 | 'Accept': '*/*',
89 | 'Origin': 'https://hd.oppo.com',
90 | 'X-Requested-With': 'XMLHttpRequest',
91 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
92 | 'Referer': 'https://hd.oppo.com/act/m/2021/jifenzhuanpan/index.html?us=gerenzhongxin&um=hudongleyuan&uc=yingjifen',
93 | 'Accept-Encoding': 'gzip, deflate',
94 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
95 | }
96 | data = {
97 | 'aid': aid,
98 | 't_index': dic['t_index']
99 | }
100 | response = self.sess.post(url=url,headers=headers,data=data).json()
101 | if response['no'] == '200':
102 | notify(f"[{dic['title']}]\t{response['msg']}")
103 | else:
104 | notify(f"[{dic['title']}]\t{response['msg']}")
105 | time.sleep(random.randint(3,5))
106 |
107 | def shareGoods(self,count=2,flag=None,dic=None):
108 | url = 'https://msec.opposhop.cn/users/vi/creditsTask/pushTask'
109 | headers = {
110 | 'clientPackage': 'com.oppo.store',
111 | 'Host': 'msec.opposhop.cn',
112 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
113 | 'Content-Type': 'application/x-www-form-urlencoded',
114 | 'Connection': 'keep-alive',
115 | 'User-Agent': 'okhttp/3.12.12.200sp1',
116 | 'Accept-Encoding': 'gzip',
117 | }
118 | params = {
119 | 'marking': 'daily_sharegoods'
120 | }
121 | for i in range(count + random.randint(1,3)):
122 | self.sess.get(url=url,headers=headers,params=params)
123 | notify(f"正在执行第{i+1}次微信分享...")
124 | time.sleep(random.randint(7,10))
125 | if flag == 1: #来源积分大乱斗
126 | self.receiveAward(dic=dic)
127 |
128 | # 直播,宠粉,浏览商品
129 | def runViewTask(self,dic=None):
130 | aid = 1598
131 | url = 'https://hd.oppo.com/task/finish'
132 | headers = {
133 | 'Host': 'hd.oppo.com',
134 | 'Connection': 'keep-alive',
135 | 'Accept': '*/*',
136 | 'Origin': 'https://hd.oppo.com',
137 | 'X-Requested-With': 'XMLHttpRequest',
138 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
139 | 'Referer': 'https://hd.oppo.com/act/m/2021/2021/realmejifendalu/index.html',
140 | 'Accept-Encoding': 'gzip, deflate',
141 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
142 | }
143 | data = {
144 | 'aid': aid,
145 | 't_index': dic['t_index']
146 | }
147 | response = self.sess.post(url=url,headers=headers,data=data).json()
148 | if response['no'] == '200':
149 | notify(f"[{dic['title']}]\t{response['msg']}")
150 | self.receiveAward(dic)
151 | else:
152 | notify(f"[{dic['title']}]\t{response['msg']}")
153 | time.sleep(random.randint(3,5))
154 |
155 | def getBattleList(self):
156 | aid = 1598 # 抓包结果为固定值:1598
157 | url = 'https://hd.oppo.com/task/list'
158 | headers = {
159 | 'Host':'hd.oppo.com',
160 | 'Connection': 'keep-alive',
161 | 'Referer':'https://hd.oppo.com/act/m/2021/2021/realmejifendalu/index.html',
162 | 'Accept-Encoding': 'gzip, deflate',
163 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
164 | }
165 | params = {
166 | 'aid':aid
167 | }
168 | response = self.sess.get(url=url,headers=headers,params=params).json()
169 | if response['no'] == '200':
170 | self.taskData = response['data']
171 | return True
172 | else:
173 | notify(f"{response['msg']}")
174 | return False
175 | time.sleep(random.randint(1,3))
176 |
177 | def runBattleTask(self):
178 | for each in self.taskData:
179 | if each['title'] == '浏览realme会场':
180 | if each['t_status'] == 0:
181 | self.runViewTask(dic=each)
182 | elif each['t_status'] == 1:
183 | self.receiveAward(each)
184 | elif each['t_status'] == 2:
185 | notify(f"[{each['title']}]\任务完成")
186 | elif each['title'] == '浏览一加会场':
187 | if each['t_status'] == 0:
188 | self.runViewTask(dic=each)
189 | elif each['t_status'] == 1:
190 | self.receiveAward(each)
191 | elif each['t_status'] == 2:
192 | notify(f"[{each['title']}]\t任务完成")
193 | elif each['title'] == '浏览潮流好物会场':
194 | if each['t_status'] == 0:
195 | self.runViewTask(dic=each)
196 | elif each['t_status'] == 1:
197 | self.receiveAward(each)
198 | elif each['t_status'] == 2:
199 | notify(f"[{each['title']}]\t任务完成")
200 | elif each['title'] == '观看realme直播':
201 | if each['t_status'] == 0:
202 | self.runViewTask(dic=each)
203 | elif each['t_status'] == 1:
204 | self.receiveAward(each)
205 | elif each['t_status'] == 2:
206 | notify(f"[{each['title']}]\t任务完成")
207 | elif each['title'] == '观看一加直播':
208 | if each['t_status'] == 0:
209 | self.runViewTask(dic=each)
210 | elif each['t_status'] == 1:
211 | self.receiveAward(each)
212 | elif each['t_status'] == 2:
213 | notify(f"[{each['title']}]\t任务完成")
214 |
215 | # 获取积分数量(只找到这个,找不到昨天积分数据)
216 | def getIntegral(self):
217 | url = 'https://store.oppo.com/cn/oapi/credits/web/credits/show'
218 | headers = {
219 | 'Host': 'store.oppo.com',
220 | 'Connection': 'keep-alive',
221 | 'source_type': '501',
222 | 'clientPackage': 'com.oppo.store',
223 | 'Accept': 'application/json, text/plain, */*',
224 | 'Accept-Encoding': 'gzip, deflate',
225 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
226 | 'X-Requested-With': 'com.oppo.store',
227 | 'Referer': 'https://store.oppo.com/cn/app/taskCenter/index?us=gerenzhongxin&um=hudongleyuan&uc=renwuzhongxin'
228 | }
229 | response = self.sess.get(url=url,headers=headers).json()
230 | if response['code'] == 200:
231 | return f"{self.dic['user']}\t总积分:{response['data']['userCredits']}"
232 | else:
233 | return f"{self.dic['user']}\t错误原因:{response}"
234 |
235 | # 执行欢太商城实例对象
236 | def start(self):
237 | self.sess.headers.update({
238 | "User-Agent":self.dic['UA']
239 | })
240 | self.sess.cookies.update({
241 | "Cookie": self.dic['CK']
242 | })
243 | if self.login() == True:
244 | if self.getBattleList() == True: # 获取任务中心数据,判断CK是否正确(登录可能成功,但无法跑任务)
245 | self.runBattleTask() # 运行任务中心
246 | notify(self.getIntegral())
247 |
248 | # 检测CK是否存在必备参数
249 | def checkHT(dic):
250 | CK = dic['CK']
251 | if len(re.findall(r'source_type=.*?;',CK)) == 0:
252 | notify(f"{dic['user']}\tCK格式有误:可能缺少`source_type`字段")
253 | return False
254 | if len(re.findall(r'TOKENSID=.*?;',CK)) == 0:
255 | notify(f"{dic['user']}\tCK格式有误:可能缺少`TOKENSID`字段")
256 | return False
257 | if len(re.findall(r'app_param=.*?[;]?',CK)) == 0:
258 | notify(f"{dic['user']}\tCK格式有误:可能缺少`app_param`字段")
259 | return False
260 | return True
261 |
262 | # 兼容云函数
263 | def main_handler(event, context):
264 | global lists
265 | for each in lists:
266 | if each['CK']!='' and each['UA'] != '':
267 | if checkHT(each):
268 | battleForHeyTap = BattleForHeyTap(each)
269 | for count in range(3):
270 | try:
271 | time.sleep(random.randint(2,5)) # 随机延时
272 | battleForHeyTap.start()
273 | break
274 | except requests.exceptions.ConnectionError:
275 | notify(f"{battleForHeyTap.dic['user']}\t请求失败,随机延迟后再次访问")
276 | time.sleep(random.randint(2,5))
277 | continue
278 | else:
279 | notify(f"账号: {battleForHeyTap.dic['user']}\n状态: 取消登录\n原因: 多次登录失败")
280 | break
281 | elif not all(each.values()):
282 | notify("账号:空账户\t状态:跳过")
283 | else:
284 | notify(f"账号: {each['user']}\n状态: 取消登录\n原因: json数据不齐全")
285 | notify('*' * 40 + '\n')
286 | if not os.path.basename(__file__).split('_')[-1][:-3] in notifyBlackList:
287 | send('欢太积分大乱斗',allMess)
288 |
289 | if __name__ == '__main__':
290 | main_handler(None,None)
291 |
--------------------------------------------------------------------------------
/BattleForRealMe.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/9/16
4 | # @Author : MashiroF
5 | # @File : BattleForRealMe.py
6 | # @Software: PyCharm
7 |
8 | '''
9 | cron: 40 5,12 * * * BattleForRealMe.py
10 | new Env('RealMe积分大乱斗');
11 | '''
12 |
13 | import os
14 | import re
15 | import sys
16 | import time
17 | import random
18 | import requests
19 |
20 | # 配置文件
21 | try:
22 | from HT_config import downFlag,notifyBlackList,logger
23 | except Exception as error:
24 | logger.info(f'失败原因:{error}')
25 | sys.exit(0)
26 |
27 | # 判断是否发生下载行为
28 | if downFlag == True:
29 | logger.info('发生下载行为,应退出程序,编辑配置文件')
30 | sys.exit(0)
31 |
32 | # 配信文件
33 | try:
34 | from sendNotify import send
35 | except Exception as error:
36 | logger.info('推送文件有误')
37 | logger.info(f'失败原因:{error}')
38 | sys.exit(0)
39 |
40 | # 导入账户
41 | try:
42 | from HT_account import accounts
43 | lists = accounts
44 | except Exception as error:
45 | logger.info(f'失败原因:{error}')
46 | lists = []
47 |
48 | # 配信内容格式
49 | allMess = ''
50 | def notify(content=None):
51 | global allMess
52 | allMess = allMess + content + '\n'
53 | logger.info(content)
54 |
55 | # 日志录入时间
56 | notify(f"任务:RealMe积分大乱斗\n时间:{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())}")
57 |
58 | class BattleForRealMe:
59 | def __init__(self,dic):
60 | self.dic = dic
61 | self.sess = requests.session()
62 |
63 | # 登录验证
64 | def login(self):
65 | url = 'https://store.oppo.com/cn/oapi/users/web/member/check'
66 | headers = {
67 | 'Host': 'store.oppo.com',
68 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
69 | 'Content-Type': 'application/x-www-form-urlencoded',
70 | 'Connection': 'keep-alive',
71 | 'Accept-Language': 'zh-cn',
72 | 'Accept-Encoding': 'gzip, deflate, br',
73 | }
74 | response = self.sess.get(url=url,headers=headers).json()
75 | if response['code'] == 200:
76 | notify(f"{self.dic['user']}\t登录成功")
77 | return True
78 | else:
79 | notify(f"{self.dic['user']}\t登录失败")
80 | return False
81 |
82 | def receiveAward(self,dic):
83 | aid = 1582
84 | url = 'https://hd.oppo.com/task/award'
85 | headers = {
86 | 'Host': 'hd.oppo.com',
87 | 'Connection': 'keep-alive',
88 | 'Accept': '*/*',
89 | 'Origin': 'https://hd.oppo.com',
90 | 'X-Requested-With': 'XMLHttpRequest',
91 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
92 | 'Referer': 'https://hd.oppo.com/act/m/2021/jifenzhuanpan/index.html?us=gerenzhongxin&um=hudongleyuan&uc=yingjifen',
93 | 'Accept-Encoding': 'gzip, deflate',
94 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
95 | }
96 | data = {
97 | 'aid': aid,
98 | 't_index': dic['t_index']
99 | }
100 | response = self.sess.post(url=url,headers=headers,data=data).json()
101 | if response['no'] == '200':
102 | notify(f"[{dic['title']}]\t{response['msg']}")
103 | else:
104 | notify(f"[{dic['title']}]\t{response['msg']}")
105 | time.sleep(random.randint(1,3))
106 |
107 | def shareGoods(self,count=2,flag=None,dic=None):
108 | url = 'https://msec.opposhop.cn/users/vi/creditsTask/pushTask'
109 | headers = {
110 | 'clientPackage': 'com.oppo.store',
111 | 'Host': 'msec.opposhop.cn',
112 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
113 | 'Content-Type': 'application/x-www-form-urlencoded',
114 | 'Connection': 'keep-alive',
115 | 'User-Agent': 'okhttp/3.12.12.200sp1',
116 | 'Accept-Encoding': 'gzip',
117 | }
118 | params = {
119 | 'marking': 'daily_sharegoods'
120 | }
121 | for i in range(count + random.randint(1,3)):
122 | self.sess.get(url=url,headers=headers,params=params)
123 | notify(f"正在执行第{i+1}次微信分享...")
124 | time.sleep(random.randint(7,10))
125 | if flag == 1: #来源积分大乱斗
126 | self.receiveAward(dic=dic)
127 |
128 | # # 直播,宠粉,浏览商品
129 | def runViewTask(self,dic=None):
130 | aid = 1582
131 | url = 'https://hd.oppo.com/task/finish'
132 | headers = {
133 | 'Host': 'hd.oppo.com',
134 | 'Connection': 'keep-alive',
135 | 'Accept': '*/*',
136 | 'Origin': 'https://hd.oppo.com',
137 | 'X-Requested-With': 'XMLHttpRequest',
138 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
139 | 'Referer': 'https://hd.oppo.com/act/m/2021/2021/realmejifendalu/index.html',
140 | 'Accept-Encoding': 'gzip, deflate',
141 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
142 | }
143 | data = {
144 | 'aid': aid,
145 | 't_index': dic['t_index']
146 | }
147 | response = self.sess.post(url=url,headers=headers,data=data).json()
148 | if response['no'] == '200':
149 | notify(f"[{dic['title']}]\t{response['msg']}")
150 | self.receiveAward(dic)
151 | else:
152 | notify(f"[{dic['title']}]\t{response['msg']}")
153 | time.sleep(random.randint(3,5))
154 |
155 | def getBattleList(self):
156 | aid = 1582 # 抓包结果为固定值:1582
157 | url = 'https://hd.oppo.com/task/list'
158 | headers = {
159 | 'Host':'hd.oppo.com',
160 | 'Connection': 'keep-alive',
161 | 'Referer':'https://hd.oppo.com/act/m/2021/2021/realmejifendalu/index.html',
162 | 'Accept-Encoding': 'gzip, deflate',
163 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
164 | }
165 | params = {
166 | 'aid':aid
167 | }
168 | response = self.sess.get(url=url,headers=headers,params=params).json()
169 | time.sleep(random.randint(3,5))
170 | if response['no'] == '200':
171 | self.taskData = response['data']
172 | return True
173 | else:
174 | notify(f"{response['msg']}")
175 | return False
176 |
177 | def runBattleTask(self):
178 | for each in self.taskData:
179 | if each['title'] == '分享商品':
180 | if each['t_status'] == 0:
181 | self.shareGoods(flag=1,count=2,dic=each)
182 | elif each['t_status'] == 1:
183 | self.receiveAward(each)
184 | elif each['t_status'] == 2:
185 | notify(f"[{each['title']}]\t领取成功")
186 | elif each['title'] == '参与欢太超级宠粉':
187 | if each['t_status'] == 0:
188 | self.runViewTask(dic=each)
189 | elif each['t_status'] == 1:
190 | self.receiveAward(each)
191 | elif each['t_status'] == 2:
192 | notify(f"[{each['title']}]\t任务完成")
193 | elif each['title'] == '观看直播':
194 | if each['t_status'] == 0:
195 | self.runViewTask(dic=each)
196 | elif each['t_status'] == 1:
197 | self.receiveAward(each)
198 | elif each['t_status'] == 2:
199 | notify(f"[{each['title']}]\t任务完成")
200 | elif each['title'] == '浏览真我Q3S' or each['title'] == '浏览真我Q3S':
201 | if each['t_status'] == 0:
202 | self.runViewTask(dic=each)
203 | elif each['t_status'] == 1:
204 | self.receiveAward(each)
205 | elif each['t_status'] == 2:
206 | notify(f"[{each['title']}]\t任务完成")
207 | elif each['title'] == '浏览真我GT Neo2T' or each['title'] == '预约真我GT Neo2T':
208 | if each['t_status'] == 0:
209 | self.runViewTask(dic=each)
210 | elif each['t_status'] == 1:
211 | self.receiveAward(each)
212 | elif each['t_status'] == 2:
213 | notify(f"[{each['title']}]\t任务完成")
214 | elif each['title'] == '浏览realme会场':
215 | if each['t_status'] == 0:
216 | self.runViewTask(dic=each)
217 | elif each['t_status'] == 1:
218 | self.receiveAward(each)
219 | elif each['t_status'] == 2:
220 | notify(f"[{each['title']}]\t任务完成")
221 |
222 | # 获取积分数量(只找到这个,找不到昨天积分数据)
223 | def getIntegral(self):
224 | url = 'https://store.oppo.com/cn/oapi/credits/web/credits/show'
225 | headers = {
226 | 'Host': 'store.oppo.com',
227 | 'Connection': 'keep-alive',
228 | 'source_type': '501',
229 | 'clientPackage': 'com.oppo.store',
230 | 'Accept': 'application/json, text/plain, */*',
231 | 'Accept-Encoding': 'gzip, deflate',
232 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
233 | 'X-Requested-With': 'com.oppo.store',
234 | 'Referer': 'https://store.oppo.com/cn/app/taskCenter/index?us=gerenzhongxin&um=hudongleyuan&uc=renwuzhongxin'
235 | }
236 | response = self.sess.get(url=url,headers=headers).json()
237 | if response['code'] == 200:
238 | return f"{self.dic['user']}\t总积分:{response['data']['userCredits']}"
239 | else:
240 | return f"{self.dic['user']}\t错误原因:{response}"
241 |
242 | # 执行欢太商城实例对象
243 | def start(self):
244 | self.sess.headers.update({
245 | "User-Agent":self.dic['UA']
246 | })
247 | self.sess.cookies.update({
248 | "Cookie": self.dic['CK']
249 | })
250 | if self.login() == True:
251 | if self.getBattleList() == True: # 获取任务中心数据,判断CK是否正确(登录可能成功,但无法跑任务)
252 | self.runBattleTask() # 运行任务中心
253 | notify(self.getIntegral())
254 |
255 | # 检测CK是否存在必备参数
256 | def checkHT(dic):
257 | CK = dic['CK']
258 | if len(re.findall(r'source_type=.*?;',CK)) == 0:
259 | notify(f"{dic['user']}\tCK格式有误:可能缺少`source_type`字段")
260 | return False
261 | if len(re.findall(r'TOKENSID=.*?;',CK)) == 0:
262 | notify(f"{dic['user']}\tCK格式有误:可能缺少`TOKENSID`字段")
263 | return False
264 | if len(re.findall(r'app_param=.*?[;]?',CK)) == 0:
265 | notify(f"{dic['user']}\tCK格式有误:可能缺少`app_param`字段")
266 | return False
267 | return True
268 |
269 | # 兼容云函数
270 | def main_handler(event, context):
271 | global lists
272 | for each in lists:
273 | if each['CK']!='' and each['UA'] != '':
274 | if checkHT(each):
275 | battleForRealMe = BattleForRealMe(each)
276 | for count in range(3):
277 | try:
278 | time.sleep(random.randint(2,5)) # 随机延时
279 | battleForRealMe.start()
280 | break
281 | except requests.exceptions.ConnectionError:
282 | notify(f"{battleForRealMe.dic['user']}\t请求失败,随机延迟后再次访问")
283 | time.sleep(random.randint(2,5))
284 | continue
285 | else:
286 | notify(f"账号: {battleForRealMe.dic['user']}\n状态: 取消登录\n原因: 多次登录失败")
287 | break
288 | elif not all(each.values()):
289 | notify("账号:空账户\t状态:跳过")
290 | else:
291 | notify(f"账号: {each['user']}\n状态: 取消登录\n原因: json数据不齐全")
292 | notify('*' * 40 + '\n')
293 | if not os.path.basename(__file__).split('_')[-1][:-3] in notifyBlackList:
294 | send('RealMe积分大乱斗',allMess)
295 |
296 | if __name__ == '__main__':
297 | main_handler(None,None)
298 |
--------------------------------------------------------------------------------
/OnePlusJYStation.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/9/26
4 | # @Author : MashiroF
5 | # @File : OnePlusJYStation.py
6 | # @Software: PyCharm
7 |
8 | '''
9 | cron: 16 5,12 * * * OnePlusJYStation.py
10 | new Env('一加加油站');
11 | '''
12 |
13 | import os
14 | import re
15 | import sys
16 | import time
17 | import random
18 | import requests
19 |
20 | # 配置文件
21 | try:
22 | from HT_config import downFlag,notifyBlackList,logger
23 | except Exception as error:
24 | logger.info(f'失败原因:{error}')
25 | sys.exit(0)
26 |
27 | # 判断是否发生下载行为
28 | if downFlag == True:
29 | logger.info('发生下载行为,应退出程序,编辑配置文件')
30 | sys.exit(0)
31 |
32 | # 配信文件
33 | try:
34 | from sendNotify import send
35 | except Exception as error:
36 | logger.info('推送文件有误')
37 | logger.info(f'失败原因:{error}')
38 | sys.exit(0)
39 |
40 | # 导入账户
41 | try:
42 | from HT_account import accounts
43 | lists = accounts
44 | except:
45 | lists = []
46 |
47 | # 配信内容格式
48 | allMess = ''
49 | def notify(content=None):
50 | global allMess
51 | allMess = allMess + content + '\n'
52 | logger.info(content)
53 |
54 | # 日志录入时间
55 | notify(f"任务:一加加油站\n时间:{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())}")
56 |
57 | class OnePlusJYStation:
58 | def __init__(self,dic):
59 | self.dic = dic
60 | self.sess = requests.session()
61 |
62 | # 登录验证
63 | def login(self):
64 | url = 'https://store.oppo.com/cn/oapi/users/web/member/check'
65 | headers = {
66 | 'Host': 'store.oppo.com',
67 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
68 | 'Content-Type': 'application/x-www-form-urlencoded',
69 | 'Connection': 'keep-alive',
70 | 'Accept-Language': 'zh-cn',
71 | 'Accept-Encoding': 'gzip, deflate, br',
72 | }
73 | response = self.sess.get(url=url,headers=headers).json()
74 | if response['code'] == 200:
75 | notify(f"{self.dic['user']}\t登录成功")
76 | return True
77 | else:
78 | notify(f"{self.dic['user']}\t登录失败")
79 | return False
80 |
81 | def receiveAward(self,dic):
82 | aid = 1473
83 | url = 'https://hd.oppo.com/task/award'
84 | headers = {
85 | 'Host': 'hd.oppo.com',
86 | 'Connection': 'keep-alive',
87 | 'Accept': '*/*',
88 | 'Origin': 'https://hd.oppo.com',
89 | 'X-Requested-With': 'XMLHttpRequest',
90 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
91 | 'Referer': 'https://hd.oppo.com/act/m/2021/jifenzhuanpan/index.html?us=gerenzhongxin&um=hudongleyuan&uc=yingjifen',
92 | 'Accept-Encoding': 'gzip, deflate',
93 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
94 | }
95 | data = {
96 | 'aid': aid,
97 | 't_index': dic['t_index']
98 | }
99 | response = self.sess.post(url=url,headers=headers,data=data).json()
100 | if response['no'] == '200':
101 | notify(f"[{dic['title']}]\t{response['msg']}")
102 | else:
103 | notify(f"[{dic['title']}]\t{response['msg']}")
104 | time.sleep(random.randint(3,5))
105 |
106 | def shareGoods(self,count=2,flag=None,dic=None):
107 | url = 'https://msec.opposhop.cn/users/vi/creditsTask/pushTask'
108 | headers = {
109 | 'clientPackage': 'com.oppo.store',
110 | 'Host': 'msec.opposhop.cn',
111 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
112 | 'Content-Type': 'application/x-www-form-urlencoded',
113 | 'Connection': 'keep-alive',
114 | 'User-Agent': 'okhttp/3.12.12.200sp1',
115 | 'Accept-Encoding': 'gzip',
116 | }
117 | params = {
118 | 'marking': 'daily_sharegoods'
119 | }
120 | for i in range(count + random.randint(1,3)):
121 | self.sess.get(url=url,headers=headers,params=params)
122 | notify(f"正在执行第{i+1}次微信分享...")
123 | time.sleep(random.randint(7,10))
124 | if flag == 1: #来源积分大乱斗
125 | self.receiveAward(dic=dic)
126 | # 秒杀详情页获取商品数据
127 | def getGoodMess(self,count=10):
128 | taskUrl = f'https://msec.opposhop.cn/goods/v1/SeckillRound/goods/{random.randint(100,250)}' # 随机商品
129 | headers = {
130 | 'clientPackage': 'com.oppo.store',
131 | 'Host': 'msec.opposhop.cn',
132 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
133 | 'Content-Type': 'application/x-www-form-urlencoded',
134 | 'Connection': 'keep-alive',
135 | 'User-Agent': 'okhttp/3.12.12.200sp1',
136 | 'Accept-Encoding': 'gzip',
137 | }
138 | params = {
139 | 'pageSize':count + random.randint(1,3)
140 | }
141 | response = self.sess.get(url=taskUrl,headers=headers,params=params).json()
142 | if response['meta']['code'] == 200:
143 | return response
144 |
145 | def viewGoods(self, count,dic=None):
146 | headers = {
147 | 'clientPackage': 'com.oppo.store',
148 | 'Host': 'msec.opposhop.cn',
149 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
150 | 'Content-Type': 'application/x-www-form-urlencoded',
151 | 'Connection': 'keep-alive',
152 | 'User-Agent': 'okhttp/3.12.12.200sp1',
153 | 'Accept-Encoding': 'gzip'
154 | }
155 | result = self.getGoodMess(count=count) # 秒杀列表存在商品url
156 | if result['meta']['code'] == 200:
157 | for each in result['detail']:
158 | url = f"https://msec.opposhop.cn/goods/v1/info/sku?skuId={each['skuid']}"
159 | self.sess.get(url=url,headers=headers)
160 | notify(f"正在浏览商品id:{each['skuid']}...")
161 | time.sleep(random.randint(7,10))
162 | if dic:
163 | self.receiveAward(dic)
164 |
165 | # 直播,宠粉,浏览商品
166 | def runViewTask(self,dic=None):
167 | aid = 1473
168 | url = 'https://hd.oppo.com/task/finish'
169 | headers = {
170 | 'Host': 'hd.oppo.com',
171 | 'Connection': 'keep-alive',
172 | 'Accept': '*/*',
173 | 'Origin': 'https://hd.oppo.com',
174 | 'X-Requested-With': 'XMLHttpRequest',
175 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
176 | 'Referer': 'https://hd.oppo.com/act/m/2021/2021/realmejifendalu/index.html',
177 | 'Accept-Encoding': 'gzip, deflate',
178 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
179 | }
180 | data = {
181 | 'aid': aid,
182 | 't_index': dic['t_index']
183 | }
184 | response = self.sess.post(url=url,headers=headers,data=data).json()
185 | if response['no'] == '200':
186 | notify(f"[{dic['title']}]\t{response['msg']}")
187 | self.receiveAward(dic)
188 | else:
189 | notify(f"[{dic['title']}]\t{response['msg']}")
190 | time.sleep(random.randint(3,5))
191 |
192 | def getBattleList(self):
193 | aid = 1473 # 抓包结果为固定值:1473
194 | url = 'https://hd.oppo.com/task/list'
195 | headers = {
196 | 'Host':'hd.oppo.com',
197 | 'Connection': 'keep-alive',
198 | 'Referer':'https://hd.oppo.com/act/m/2021/2021/realmejifendalu/index.html',
199 | 'Accept-Encoding': 'gzip, deflate',
200 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
201 | }
202 | params = {
203 | 'aid':aid
204 | }
205 | response = self.sess.get(url=url,headers=headers,params=params).json()
206 | if response['no'] == '200':
207 | self.taskData = response['data']
208 | return True
209 | else:
210 | notify(f"{response['msg']}")
211 | return False
212 | time.sleep(random.randint(1,3))
213 |
214 | def runBattleTask(self):
215 | for each in self.taskData:
216 | if each['title'] == '每日签到':
217 | if each['t_status'] == 0:
218 | self.runViewTask(dic=each)
219 | elif each['t_status'] == 1:
220 | self.receiveAward(each)
221 | elif each['t_status'] == 2:
222 | notify(f"[{each['title']}]\t领取成功")
223 | elif each['title'] == '浏览一加11.11会场':
224 | if each['t_status'] == 0:
225 | self.runViewTask(dic=each)
226 | elif each['t_status'] == 1:
227 | self.receiveAward(each)
228 | elif each['t_status'] == 2:
229 | notify(f"[{each['title']}]\t任务完成")
230 | elif each['title'] == '浏览一加商品':
231 | if each['t_status'] == 0:
232 | self.viewGoods(count=6,dic=each)
233 | elif each['t_status'] == 1:
234 | self.receiveAward(each)
235 | elif each['t_status'] == 2:
236 | notify(f"[{each['title']}]\t任务完成")
237 |
238 | # 获取积分数量(只找到这个,找不到昨天积分数据)
239 | def getIntegral(self):
240 | url = 'https://store.oppo.com/cn/oapi/credits/web/credits/show'
241 | headers = {
242 | 'Host': 'store.oppo.com',
243 | 'Connection': 'keep-alive',
244 | 'source_type': '501',
245 | 'clientPackage': 'com.oppo.store',
246 | 'Accept': 'application/json, text/plain, */*',
247 | 'Accept-Encoding': 'gzip, deflate',
248 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
249 | 'X-Requested-With': 'com.oppo.store',
250 | 'Referer': 'https://store.oppo.com/cn/app/taskCenter/index?us=gerenzhongxin&um=hudongleyuan&uc=renwuzhongxin'
251 | }
252 | response = self.sess.get(url=url,headers=headers).json()
253 | if response['code'] == 200:
254 | return f"{self.dic['user']}\t总积分:{response['data']['userCredits']}"
255 | else:
256 | return f"{self.dic['user']}\t错误原因:{response}"
257 |
258 | # 执行欢太商城实例对象
259 | def start(self):
260 | self.sess.headers.update({
261 | "User-Agent":self.dic['UA']
262 | })
263 | self.sess.cookies.update({
264 | "Cookie": self.dic['CK']
265 | })
266 | if self.login() == True:
267 | if self.getBattleList() == True: # 获取任务中心数据,判断CK是否正确(登录可能成功,但无法跑任务)
268 | self.runBattleTask() # 运行任务中心
269 | notify(self.getIntegral())
270 |
271 | # 检测CK是否存在必备参数
272 | def checkHT(dic):
273 | CK = dic['CK']
274 | if len(re.findall(r'source_type=.*?;',CK)) == 0:
275 | notify(f"{dic['user']}\tCK格式有误:可能缺少`source_type`字段")
276 | return False
277 | if len(re.findall(r'TOKENSID=.*?;',CK)) == 0:
278 | notify(f"{dic['user']}\tCK格式有误:可能缺少`TOKENSID`字段")
279 | return False
280 | if len(re.findall(r'app_param=.*?[;]?',CK)) == 0:
281 | notify(f"{dic['user']}\tCK格式有误:可能缺少`app_param`字段")
282 | return False
283 | return True
284 |
285 | # 兼容云函数
286 | def main_handler(event, context):
287 | global lists
288 | for each in lists:
289 | if each['CK']!='' and each['UA'] != '':
290 | if checkHT(each):
291 | onePlusJYStation = OnePlusJYStation(each)
292 | for count in range(3):
293 | try:
294 | time.sleep(random.randint(2,5)) # 随机延时
295 | onePlusJYStation.start()
296 | break
297 | except requests.exceptions.ConnectionError:
298 | notify(f"{onePlusJYStation.dic['user']}\t请求失败,随机延迟后再次访问")
299 | time.sleep(random.randint(2,5))
300 | continue
301 | else:
302 | notify(f"账号: {onePlusJYStation.dic['user']}\n状态: 取消登录\n原因: 多次登录失败")
303 | break
304 | elif not all(each.values()):
305 | notify("账号:空账户\t状态:跳过")
306 | else:
307 | notify(f"账号: {each['user']}\n状态: 取消登录\n原因: json数据不齐全")
308 | notify('*' * 40 + '\n')
309 | if not os.path.basename(__file__).split('_')[-1][:-3] in notifyBlackList:
310 | send('一加加油站',allMess)
311 |
312 | if __name__ == '__main__':
313 | main_handler(None,None)
314 |
--------------------------------------------------------------------------------
/DailyCash.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/9/12
4 | # @Author : MashiroF
5 | # @File : DailyCash.py
6 | # @Software: PyCharm
7 |
8 | '''
9 | cron: 30 5,12 * * * DailyCash.py
10 | new Env('欢太每日现金');
11 | '''
12 |
13 | import os
14 | import re
15 | import sys
16 | import time
17 | import random
18 |
19 | # 配置文件
20 | try:
21 | from HT_config import downFlag,notifyBlackList,logger
22 | import requests
23 | except Exception as error:
24 | logger.info(f'失败原因:{error}')
25 | sys.exit(0)
26 |
27 | # 判断是否发生下载行为
28 | if downFlag == True:
29 | logger.info('发生下载行为,应退出程序,编辑配置文件')
30 | sys.exit(0)
31 |
32 | # 配信文件
33 | try:
34 | from sendNotify import send
35 | except Exception as error:
36 | logger.info('推送文件有误')
37 | logger.info(f'失败原因:{error}')
38 | sys.exit(0)
39 |
40 | # 导入账户
41 | try:
42 | from HT_account import accounts
43 | lists = accounts
44 | except Exception as error:
45 | logger.info(f'失败原因:{error}')
46 | lists = []
47 |
48 | # 配信内容格式
49 | allMess = ''
50 | def notify(content=None):
51 | global allMess
52 | allMess = allMess + content + '\n'
53 | logger.info(content)
54 |
55 | # 日志录入时间
56 | notify(f"任务:欢太每日现金\n时间:{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())}")
57 |
58 | class DailyCash:
59 | def __init__(self,dic):
60 | self.dic = dic
61 | self.sess = requests.session()
62 |
63 | # 登录验证
64 | def login(self):
65 | url = 'https://store.oppo.com/cn/oapi/users/web/member/check'
66 | headers = {
67 | 'Host': 'store.oppo.com',
68 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
69 | 'Content-Type': 'application/x-www-form-urlencoded',
70 | 'Connection': 'keep-alive',
71 | 'Accept-Language': 'zh-cn',
72 | 'Accept-Encoding': 'gzip, deflate, br',
73 | }
74 | response = self.sess.get(url=url,headers=headers).json()
75 | if response['code'] == 200:
76 | notify(f"{self.dic['user']}\t登录成功")
77 | return True
78 | else:
79 | notify(f"{self.dic['user']}\t登录失败")
80 | return False
81 |
82 | # 浏览商品
83 | def viewGoods(self, count,flag,dic=None):
84 | headers = {
85 | 'clientPackage': 'com.oppo.store',
86 | 'Host': 'msec.opposhop.cn',
87 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
88 | 'Content-Type': 'application/x-www-form-urlencoded',
89 | 'Connection': 'keep-alive',
90 | 'User-Agent': 'okhttp/3.12.12.200sp1',
91 | 'Accept-Encoding': 'gzip'
92 | }
93 | result = self.getGoodMess(count=count) # 秒杀列表存在商品url
94 | if result['meta']['code'] == 200:
95 | for each in result['detail']:
96 | url = f"https://msec.opposhop.cn/goods/v1/info/sku?skuId={each['skuid']}"
97 | self.sess.get(url=url,headers=headers)
98 | notify(f"正在浏览商品id:{each['skuid']}...")
99 | time.sleep(random.randint(7,10))
100 | if flag == 1: # 来源天天领现金
101 | self.getCash(dic=dic)
102 |
103 | # 分享商品
104 | def shareGoods(self, flag,count,dic=None):
105 | url = 'https://msec.opposhop.cn/users/vi/creditsTask/pushTask'
106 | headers = {
107 | 'clientPackage': 'com.oppo.store',
108 | 'Host': 'msec.opposhop.cn',
109 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
110 | 'Content-Type': 'application/x-www-form-urlencoded',
111 | 'Connection': 'keep-alive',
112 | 'User-Agent': 'okhttp/3.12.12.200sp1',
113 | 'Accept-Encoding': 'gzip',
114 | }
115 | params = {
116 | 'marking': 'daily_sharegoods'
117 | }
118 | for i in range(count + random.randint(1,3)):
119 | self.sess.get(url=url,headers=headers,params=params)
120 | notify(f"正在执行第{i+1}次微信分享...")
121 | time.sleep(random.randint(7,10))
122 | if flag == 1: #来源天天赚钱
123 | self.getCash(dic=dic)
124 |
125 | # 秒杀详情页获取商品数据
126 | def getGoodMess(self,count=10):
127 | taskUrl = f'https://msec.opposhop.cn/goods/v1/SeckillRound/goods/{random.randint(100,250)}' # 随机商品
128 | headers = {
129 | 'clientPackage': 'com.oppo.store',
130 | 'Host': 'msec.opposhop.cn',
131 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
132 | 'Content-Type': 'application/x-www-form-urlencoded',
133 | 'Connection': 'keep-alive',
134 | 'User-Agent': 'okhttp/3.12.12.200sp1',
135 | 'Accept-Encoding': 'gzip',
136 | }
137 | params = {
138 | 'pageSize':count + random.randint(1,3)
139 | }
140 | response = self.sess.get(url=taskUrl,headers=headers,params=params).json()
141 | if response['meta']['code'] == 200:
142 | return response
143 | else:
144 | notify(response)
145 |
146 | def getCash(self,dic):
147 | url = 'https://store.oppo.com/cn/oapi/omp-web/web/dailyCash/drawReward'
148 | headers = {
149 | 'Host': 'store.oppo.com',
150 | 'Connection': 'keep-alive',
151 | 'Origin': 'https://store.oppo.com',
152 | 'source_type': '501',
153 | 'clientPackage': 'com.oppo.store',
154 | 'Content-Type': 'application/x-www-form-urlencoded',
155 | 'Accept': 'application/json, text/plain, */*',
156 | 'Referer': 'https://store.oppo.com/cn/app/cashRedEnvelope?activityId=1&us=shouye&um=xuanfu&uc=xianjinhongbao',
157 | 'Accept-Encoding': 'gzip, deflate',
158 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
159 | }
160 | data = {
161 | 'activityId':1,
162 | 'channel':3,
163 | 'channelRewardId':dic['id']
164 | }
165 | response = self.sess.post(url=url,headers=headers,data=data).json()
166 | if response['code'] == 200:
167 | notify(f"[{dic['taskName']}]\t{response['data']['amount']}")
168 | elif response['code'] == 1000001:
169 | notify(f"[{dic['taskName']}]\t{response['errorMessage']}")
170 |
171 | # 天天领取现金
172 | def getDailyCashTask(self):
173 | url = 'https://store.oppo.com/cn/oapi/omp-web/web/dailyCash/queryActivityReward'
174 | headers = {
175 | 'Host': 'store.oppo.com',
176 | 'Connection': 'keep-alive',
177 | 'source_type': '501',
178 | 'clientPackage': 'com.oppo.store',
179 | 'Accept': 'application/json, text/plain, */*',
180 | 'Referer': 'https://store.oppo.com/cn/app/cashRedEnvelope?activityId=1&us=shouye&um=xuanfu&uc=xianjinhongbao',
181 | 'Accept-Encoding': 'gzip, deflate',
182 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
183 | }
184 | params = {
185 | 'activityId':1
186 | }
187 | response = self.sess.get(url=url,headers=headers,params=params).json()
188 | if response['code'] == 200:
189 | self.taskRewardList = response['data']['taskRewardList']
190 | self.timingRewardList = response['data']['timingRewardList']
191 | return True
192 | elif response['code'] == 1000001:
193 | notify(response['errorMessage'])
194 | return False
195 |
196 | # 天天领现金浏览模板
197 | def viewCashTask(self,dic):
198 | url = 'https://store.oppo.com/cn/oapi/credits/web/dailyCash/reportDailyTask'
199 | param = {
200 | 'taskType':dic['taskType'],
201 | 'taskId':f"dailyCash{dic['id']}"
202 | }
203 | headers = {
204 | 'Host': 'store.oppo.com',
205 | 'Connection': 'keep-alive',
206 | 'source_type': '501',
207 | 'clientPackage': 'com.oppo.store',
208 | 'Cache-Control': 'no-cache',
209 | 'Accept': 'application/json, text/plain, */*',
210 | 'Referer': 'https://store.oppo.com/cn/app/cashRedEnvelope?activityId=1&us=shouye&um=xuanfu&uc=xianjinhongbao',
211 | 'Accept-Encoding': 'gzip, deflate',
212 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
213 | }
214 | response = self.sess.get(url=url,headers=headers,params=param).json()
215 | if response['code'] == 200:
216 | notify(f"正在执行{dic['taskName']}...")
217 | time.sleep(random.randint(5,7))
218 | self.getCash(dic=dic)
219 | else:
220 | notify(f"{dic['taskName']}执行失败")
221 |
222 |
223 | def runTaskRewardList(self):
224 | for each in self.taskRewardList:
225 | if each['taskName'] == '浏览商品':
226 | if each['taskStatus'] == 0:
227 | self.viewGoods(count=6,flag=1,dic=each)
228 | elif each['taskStatus'] == 1:
229 | self.getCash(dic=each)
230 | elif each['taskStatus'] == 2:
231 | notify(f"{each['taskName']}\t已领取")
232 | elif each['taskName'] == '浏览秒杀专区':
233 | if each['taskStatus'] == 0:
234 | self.viewCashTask(each)
235 | elif each['taskStatus'] == 1:
236 | self.getCash(dic=each)
237 | elif each['taskStatus'] == 2:
238 | notify(f"{each['taskName']}\t已领取")
239 | elif each['taskName'] == '分享商品':
240 | if each['taskStatus'] == 0:
241 | self.shareGoods(count=2,flag=1,dic=each)
242 | elif each['taskStatus'] == 1:
243 | self.getCash(dic=each)
244 | elif each['taskStatus'] == 2:
245 | notify(f"{each['taskName']}\t已领取")
246 | elif each['taskName'] == '观看直播':
247 | if each['taskStatus'] == 0:
248 | self.viewCashTask(each)
249 | elif each['taskStatus'] == 1:
250 | self.getCash(dic=each)
251 | elif each['taskStatus'] == 2:
252 | notify(f"{each['taskName']}\t已领取")
253 | elif each['taskName'] == '浏览签到页':
254 | if each['taskStatus'] == 0:
255 | self.viewCashTask(each)
256 | elif each['taskStatus'] == 1:
257 | self.getCash(dic=each)
258 | elif each['taskStatus'] == 2:
259 | notify(f"{each['taskName']}\t已领取")
260 | if each['taskName'] == '浏览领券中心':
261 | if each['taskStatus'] == 0:
262 | self.viewCashTask(each)
263 | elif each['taskStatus'] == 1:
264 | self.getCash(dic=each)
265 | elif each['taskStatus'] == 2:
266 | notify(f"{each['taskName']}\t已领取")
267 | elif each['taskName'] == '浏览realme商品':
268 | if each['taskStatus'] == 0:
269 | self.viewCashTask(each)
270 | elif each['taskStatus'] == 1:
271 | self.getCash(dic=each)
272 | elif each['taskStatus'] == 2:
273 | notify(f"{each['taskName']}\t已领取")
274 | elif each['taskName'] == '浏览指定商品':
275 | if each['taskStatus'] == 0:
276 | self.viewCashTask(each)
277 | elif each['taskStatus'] == 1:
278 | self.getCash(dic=each)
279 | elif each['taskStatus'] == 2:
280 | notify(f"{each['taskName']}\t已领取")
281 | elif each['taskName'] == '浏览一加商品':
282 | if each['taskStatus'] == 0:
283 | self.viewCashTask(each)
284 | elif each['taskStatus'] == 1:
285 | self.getCash(dic=each)
286 | elif each['taskStatus'] == 2:
287 | notify(f"{each['taskName']}\t已领取")
288 | elif each['taskName'] == '浏览OPPO商品':
289 | if each['taskStatus'] == 0:
290 | self.viewCashTask(each)
291 | elif each['taskStatus'] == 1:
292 | self.getCash(dic=each)
293 | elif each['taskStatus'] == 2:
294 | notify(f"{each['taskName']}\t已领取")
295 |
296 | # 执行欢太商城实例对象
297 | def start(self):
298 | self.sess.headers.update({
299 | "User-Agent":self.dic['UA']
300 | })
301 | self.sess.cookies.update({
302 | "Cookie": self.dic['CK']
303 | })
304 | if self.login() == True:
305 | if self.getDailyCashTask() == True: # 获取天天领现金数据,判断CK是否正确(登录可能成功,但无法跑任务)
306 | self.runTaskRewardList() # 运行天天领现金
307 |
308 | # 检测CK是否存在必备参数
309 | def checkHT(dic):
310 | CK = dic['CK']
311 | if len(re.findall(r'source_type=.*?;',CK)) == 0:
312 | notify(f"{dic['user']}\tCK格式有误:可能缺少`source_type`字段")
313 | return False
314 | if len(re.findall(r'TOKENSID=.*?;',CK)) == 0:
315 | notify(f"{dic['user']}\tCK格式有误:可能缺少`TOKENSID`字段")
316 | return False
317 | if len(re.findall(r'app_param=.*?[;]?',CK)) == 0:
318 | notify(f"{dic['user']}\tCK格式有误:可能缺少`app_param`字段")
319 | return False
320 | return True
321 |
322 | # 兼容云函数
323 | def main_handler(event, context):
324 | global lists
325 | for each in lists:
326 | if each['CK']!='' and each['UA'] != '':
327 | if checkHT(each):
328 | dailyCash = DailyCash(each)
329 | for count in range(3):
330 | try:
331 | time.sleep(random.randint(2,5)) # 随机延时
332 | dailyCash.start()
333 | break
334 | except requests.exceptions.ConnectionError:
335 | notify(f"{dailyCash.dic['user']}\t请求失败,随机延迟后再次访问")
336 | time.sleep(random.randint(2,5))
337 | continue
338 | else:
339 | notify(f"账号: {dailyCash.dic['user']}\n状态: 取消登录\n原因: 多次登录失败")
340 | break
341 | elif not all(each.values()):
342 | notify("账号:空账户\t状态:跳过")
343 | else:
344 | notify(f"账号: {each['user']}\n状态: 取消登录\n原因: json数据不齐全")
345 | notify('*' * 40 + '\n')
346 | if not os.path.basename(__file__).split('_')[-1][:-3] in notifyBlackList:
347 | send('欢太每日现金',allMess)
348 |
349 | if __name__ == '__main__':
350 | main_handler(None,None)
351 |
--------------------------------------------------------------------------------
/Backup/Double11.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/10/20
4 | # @Author : MashiroF
5 | # @File : Double11.py
6 | # @Software: PyCharm
7 |
8 | '''
9 | cron: 44 7,11 * * * Double11.py
10 | new Env('全名抽免单');
11 | '''
12 |
13 | import os
14 | import re
15 | import sys
16 | import time
17 | import random
18 | import requests
19 |
20 | # 配置文件
21 | try:
22 | from HT_config import downFlag,notifyBlackList,logger
23 | except Exception as error:
24 | logger.info(f'失败原因:{error}')
25 | sys.exit(0)
26 |
27 | # 判断是否发生下载行为
28 | if downFlag == True:
29 | logger.info('发生下载行为,应退出程序,编辑配置文件')
30 | sys.exit(0)
31 |
32 | # 配信文件
33 | try:
34 | from sendNotify import send
35 | except Exception as error:
36 | logger.info('推送文件有误')
37 | logger.info(f'失败原因:{error}')
38 | sys.exit(0)
39 |
40 | # 导入账户
41 | try:
42 | from HT_account import accounts
43 | lists = accounts
44 | except Exception as error:
45 | logger.info(f'失败原因:{error}')
46 | lists = []
47 |
48 | # 配信内容格式
49 | allMess = ''
50 | def notify(content=None):
51 | global allMess
52 | allMess = allMess + content + '\n'
53 | logger.info(content)
54 |
55 | # 日志录入时间
56 | notify(f"任务:全名抽免单\n时间:{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())}")
57 |
58 | class Double11:
59 | def __init__(self,dic):
60 | self.dic = dic
61 | self.sess = requests.session()
62 |
63 | # 登录验证
64 | def login(self):
65 | url = 'https://store.oppo.com/cn/oapi/users/web/member/check'
66 | headers = {
67 | 'Host': 'store.oppo.com',
68 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
69 | 'Content-Type': 'application/x-www-form-urlencoded',
70 | 'Connection': 'keep-alive',
71 | 'Accept-Language': 'zh-cn',
72 | 'Accept-Encoding': 'gzip, deflate, br',
73 | }
74 | response = self.sess.get(url=url,headers=headers).json()
75 | if response['code'] == 200:
76 | notify(f"{self.dic['user']}\t登录成功")
77 | return True
78 | else:
79 | notify(f"{self.dic['user']}\t登录失败")
80 | return False
81 |
82 | # 秒杀详情页获取商品数据
83 | def getGoodMess(self,count=10):
84 | taskUrl = f'https://msec.opposhop.cn/goods/v1/SeckillRound/goods/{random.randint(100,250)}' # 随机商品
85 | headers = {
86 | 'clientPackage': 'com.oppo.store',
87 | 'Host': 'msec.opposhop.cn',
88 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
89 | 'Content-Type': 'application/x-www-form-urlencoded',
90 | 'Connection': 'keep-alive',
91 | 'User-Agent': 'okhttp/3.12.12.200sp1',
92 | 'Accept-Encoding': 'gzip',
93 | }
94 | params = {
95 | 'pageSize':count + random.randint(1,3)
96 | }
97 | response = self.sess.get(url=taskUrl,headers=headers,params=params).json()
98 | if response['meta']['code'] == 200:
99 | return response
100 |
101 | def viewGoods(self, count,dic=None):
102 | headers = {
103 | 'clientPackage': 'com.oppo.store',
104 | 'Host': 'msec.opposhop.cn',
105 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
106 | 'Content-Type': 'application/x-www-form-urlencoded',
107 | 'Connection': 'keep-alive',
108 | 'User-Agent': 'okhttp/3.12.12.200sp1',
109 | 'Accept-Encoding': 'gzip'
110 | }
111 | result = self.getGoodMess(count=count) # 秒杀列表存在商品url
112 | if result['meta']['code'] == 200:
113 | for each in result['detail']:
114 | url = f"https://msec.opposhop.cn/goods/v1/info/sku?skuId={each['skuid']}"
115 | self.sess.get(url=url,headers=headers)
116 | notify(f"正在浏览商品id:{each['skuid']}...")
117 | time.sleep(random.randint(7,10))
118 | if dic:
119 | self.receiveAward(dic)
120 |
121 | def receiveAward(self,dic):
122 | aid = 1768
123 | url = 'https://hd.oppo.com/task/award'
124 | headers = {
125 | 'Host': 'hd.oppo.com',
126 | 'Connection': 'keep-alive',
127 | 'Accept': '*/*',
128 | 'Origin': 'https://hd.oppo.com',
129 | 'X-Requested-With': 'XMLHttpRequest',
130 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
131 | 'Referer': 'https://hd.oppo.com/act/m/2021/jifenzhuanpan/index.html?us=gerenzhongxin&um=hudongleyuan&uc=yingjifen',
132 | 'Accept-Encoding': 'gzip, deflate',
133 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
134 | }
135 | data = {
136 | 'aid': aid,
137 | 't_index': dic['t_index']
138 | }
139 | response = self.sess.post(url=url,headers=headers,data=data).json()
140 | if response['no'] == '200':
141 | notify(f"[{dic['title']}]\t{response['msg']}")
142 | else:
143 | notify(f"[{dic['title']}]\t{response['msg']}")
144 | time.sleep(random.randint(1,3))
145 |
146 | # def shareGoods(self,count=2,flag=None,dic=None):
147 | # url = 'https://msec.opposhop.cn/users/vi/creditsTask/pushTask'
148 | # headers = {
149 | # 'clientPackage': 'com.oppo.store',
150 | # 'Host': 'msec.opposhop.cn',
151 | # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
152 | # 'Content-Type': 'application/x-www-form-urlencoded',
153 | # 'Connection': 'keep-alive',
154 | # 'User-Agent': 'okhttp/3.12.12.200sp1',
155 | # 'Accept-Encoding': 'gzip',
156 | # }
157 | # params = {
158 | # 'marking': 'daily_sharegoods'
159 | # }
160 | # for i in range(count + random.randint(1,3)):
161 | # self.sess.get(url=url,headers=headers,params=params)
162 | # notify(f"正在执行第{i+1}次微信分享...")
163 | # time.sleep(random.randint(7,10))
164 | # if flag == 1:
165 | # self.receiveAward(dic=dic)
166 |
167 | def runViewTask(self,dic=None):
168 | aid = 1768
169 | url = 'https://hd.oppo.com/task/finish'
170 | headers = {
171 | 'Host': 'hd.oppo.com',
172 | 'Connection': 'keep-alive',
173 | 'Accept': '*/*',
174 | 'Origin': 'https://hd.oppo.com',
175 | 'X-Requested-With': 'XMLHttpRequest',
176 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
177 | 'Referer': 'https://hd.oppo.com/act/m/2021/2021/realmejifendalu/index.html',
178 | 'Accept-Encoding': 'gzip, deflate',
179 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
180 | }
181 | data = {
182 | 'aid': aid,
183 | 't_index': dic['t_index']
184 | }
185 | response = self.sess.post(url=url,headers=headers,data=data).json()
186 | if response['no'] == '200':
187 | notify(f"[{dic['title']}]\t{response['msg']}")
188 | self.receiveAward(dic)
189 | else:
190 | notify(f"[{dic['title']}]\t{response['msg']}")
191 | time.sleep(random.randint(3,5))
192 |
193 | def getBattleList(self):
194 | aid = 1768 # 抓包结果为固定值:1582
195 | url = 'https://hd.oppo.com/task/list'
196 | headers = {
197 | 'Host':'hd.oppo.com',
198 | 'Connection': 'keep-alive',
199 | 'Referer':'https://hd.oppo.com/act/m/2021/2021/realmejifendalu/index.html',
200 | 'Accept-Encoding': 'gzip, deflate',
201 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
202 | }
203 | params = {
204 | 'aid':aid
205 | }
206 | response = self.sess.get(url=url,headers=headers,params=params).json()
207 | time.sleep(random.randint(3,5))
208 | if response['no'] == '200':
209 | self.taskData = response['data']
210 | return True
211 | else:
212 | notify(f"{response['msg']}")
213 | return False
214 |
215 | def runBattleTask(self):
216 | for each in self.taskData:
217 | if each['title'] == '每日签到':
218 | if each['t_status'] == 0:
219 | self.runViewTask(dic=each)
220 | elif each['t_status'] == 1:
221 | self.receiveAward(each)
222 | elif each['t_status'] == 2:
223 | notify(f"[{each['title']}]\t领取成功")
224 | elif each['title'] == '浏览11.11主会场':
225 | if each['t_status'] == 0:
226 | self.runViewTask(dic=each)
227 | elif each['t_status'] == 1:
228 | self.receiveAward(each)
229 | elif each['t_status'] == 2:
230 | notify(f"[{each['title']}]\t任务完成")
231 | elif each['title'] == '浏览天天抢5折会场':
232 | if each['t_status'] == 0:
233 | self.runViewTask(dic=each)
234 | elif each['t_status'] == 1:
235 | self.receiveAward(each)
236 | elif each['t_status'] == 2:
237 | notify(f"[{each['title']}]\t任务完成")
238 | elif each['title'] == '浏览会员中心':
239 | if each['t_status'] == 0:
240 | self.runViewTask(dic=each)
241 | elif each['t_status'] == 1:
242 | self.receiveAward(each)
243 | elif each['t_status'] == 2:
244 | notify(f"[{each['title']}]\t任务完成")
245 | elif each['title'] == '浏览OPPO 11.11会场':
246 | if each['t_status'] == 0:
247 | self.runViewTask(dic=each)
248 | elif each['t_status'] == 1:
249 | self.receiveAward(each)
250 | elif each['t_status'] == 2:
251 | notify(f"[{each['title']}]\t任务完成")
252 | elif each['title'] == '浏览一加 11.11会场':
253 | if each['t_status'] == 0:
254 | self.runViewTask(dic=each)
255 | elif each['t_status'] == 1:
256 | self.receiveAward(each)
257 | elif each['t_status'] == 2:
258 | notify(f"[{each['title']}]\t任务完成")
259 | elif each['title'] == '浏览realme 11.11会场':
260 | if each['t_status'] == 0:
261 | self.runViewTask(dic=each)
262 | elif each['t_status'] == 1:
263 | self.receiveAward(each)
264 | elif each['t_status'] == 2:
265 | notify(f"[{each['title']}]\t任务完成")
266 | elif each['title'] == '浏览智能硬件 11.11会场':
267 | if each['t_status'] == 0:
268 | self.runViewTask(dic=each)
269 | elif each['t_status'] == 1:
270 | self.receiveAward(each)
271 | elif each['t_status'] == 2:
272 | notify(f"[{each['title']}]\t任务完成")
273 | elif each['title'] == '浏览潮流好物 11.11会场':
274 | if each['t_status'] == 0:
275 | self.runViewTask(dic=each)
276 | elif each['t_status'] == 1:
277 | self.receiveAward(each)
278 | elif each['t_status'] == 2:
279 | notify(f"[{each['title']}]\t任务完成")
280 | elif each['title'] == '浏览商品':
281 | if each['t_status'] == 0:
282 | self.viewGoods(count=2,dic=each)
283 | elif each['t_status'] == 1:
284 | self.receiveAward(each)
285 | elif each['t_status'] == 2:
286 | notify(f"[{each['title']}]\t任务完成")
287 |
288 | # 获取积分数量(只找到这个,找不到昨天积分数据)
289 | def getIntegral(self):
290 | url = 'https://store.oppo.com/cn/oapi/credits/web/credits/show'
291 | headers = {
292 | 'Host': 'store.oppo.com',
293 | 'Connection': 'keep-alive',
294 | 'source_type': '501',
295 | 'clientPackage': 'com.oppo.store',
296 | 'Accept': 'application/json, text/plain, */*',
297 | 'Accept-Encoding': 'gzip, deflate',
298 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
299 | 'X-Requested-With': 'com.oppo.store',
300 | 'Referer': 'https://store.oppo.com/cn/app/taskCenter/index?us=gerenzhongxin&um=hudongleyuan&uc=renwuzhongxin'
301 | }
302 | response = self.sess.get(url=url,headers=headers).json()
303 | if response['code'] == 200:
304 | return f"{self.dic['user']}\t总积分:{response['data']['userCredits']}"
305 | else:
306 | return f"{self.dic['user']}\t错误原因:{response}"
307 |
308 | # 执行欢太商城实例对象
309 | def start(self):
310 | self.sess.headers.update({
311 | "User-Agent":self.dic['UA']
312 | })
313 | self.sess.cookies.update({
314 | "Cookie": self.dic['CK']
315 | })
316 | if self.login() == True:
317 | if self.getBattleList() == True: # 获取任务中心数据,判断CK是否正确(登录可能成功,但无法跑任务)
318 | self.runBattleTask() # 运行任务中心
319 | notify(self.getIntegral())
320 | notify('*' * 40 + '\n')
321 |
322 | # 检测CK是否存在必备参数
323 | def checkHT(dic):
324 | CK = dic['CK']
325 | if len(re.findall(r'source_type=.*?;',CK)) == 0:
326 | notify(f"{dic['user']}\tCK格式有误:可能缺少`source_type`字段")
327 | return False
328 | if len(re.findall(r'TOKENSID=.*?;',CK)) == 0:
329 | notify(f"{dic['user']}\tCK格式有误:可能缺少`TOKENSID`字段")
330 | return False
331 | if len(re.findall(r'app_param=.*?[;]?',CK)) == 0:
332 | notify(f"{dic['user']}\tCK格式有误:可能缺少`app_param`字段")
333 | return False
334 | return True
335 |
336 | # 兼容云函数
337 | def main_handler(event, context):
338 | global lists
339 | for each in lists:
340 | if all(each.values()):
341 | if checkHT(each):
342 | double11 = Double11(each)
343 | for count in range(3):
344 | try:
345 | time.sleep(random.randint(2,5)) # 随机延时
346 | double11.start()
347 | break
348 | except requests.exceptions.ConnectionError:
349 | notify(f"{double11.dic['user']}\t请求失败,随机延迟后再次访问")
350 | time.sleep(random.randint(2,5))
351 | continue
352 | else:
353 | notify(f"账号: {double11.dic['user']}\n状态: 取消登录\n原因: 多次登录失败")
354 | break
355 | elif not all(each.values()):
356 | notify("账号:空账户\t状态:跳过")
357 | else:
358 | notify(f"账号: {each['user']}\n状态: 取消登录\n原因: json数据不齐全")
359 | if not os.path.basename(__file__).split('_')[-1][:-3] in notifyBlackList:
360 | send('全名抽免单',allMess)
361 |
362 | if __name__ == '__main__':
363 | main_handler(None,None)
364 |
--------------------------------------------------------------------------------
/TaskCenter.py:
--------------------------------------------------------------------------------
1 | # !/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | # @Time : 2021/9/12
4 | # @Author : MashiroF
5 | # @File : TaskCenter.py
6 | # @Software: PyCharm
7 |
8 | '''
9 | cron: 25 5,12 * * * TaskCenter.py
10 | new Env('欢太任务中心');
11 | '''
12 |
13 | import os
14 | import re
15 | import sys
16 | import time
17 | import random
18 | import requests
19 |
20 | # 配置文件
21 | try:
22 | from HT_config import downFlag,notifyBlackList,logger
23 | except Exception as error:
24 | logger.info(f'失败原因:{error}')
25 | sys.exit(0)
26 |
27 | # 判断是否发生下载行为
28 | if downFlag == True:
29 | logger.info('发生下载行为,应退出程序,编辑配置文件')
30 | sys.exit(0)
31 |
32 | # 配信文件
33 | try:
34 | from sendNotify import send
35 | except Exception as error:
36 | logger.info('推送文件有误')
37 | logger.info(f'失败原因:{error}')
38 | sys.exit(0)
39 |
40 | # 导入账户
41 | try:
42 | from HT_account import accounts
43 | lists = accounts
44 | except Exception as error:
45 | logger.info(f'失败原因:{error}')
46 | lists = []
47 |
48 | # 配信内容格式
49 | allMess = ''
50 | def notify(content=None):
51 | global allMess
52 | allMess = allMess + content + '\n'
53 | logger.info(content)
54 |
55 | # 日志录入时间
56 | notify(f"任务:欢太任务中心\n时间:{time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())}")
57 |
58 | # 欢太任务中心类
59 | class TaskCenter:
60 | def __init__(self,dic):
61 | self.dic = dic
62 | self.sess = requests.session()
63 |
64 | # 登录验证
65 | def login(self):
66 | url = 'https://store.oppo.com/cn/oapi/users/web/member/check'
67 | headers = {
68 | 'Host': 'store.oppo.com',
69 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
70 | 'Content-Type': 'application/x-www-form-urlencoded',
71 | 'Connection': 'keep-alive',
72 | 'Accept-Language': 'zh-cn',
73 | 'Accept-Encoding': 'gzip, deflate, br',
74 | }
75 | response = self.sess.get(url=url,headers=headers).json()
76 | if response['code'] == 200:
77 | notify(f"{self.dic['user']}\t登录成功")
78 | return True
79 | else:
80 | notify(f"{self.dic['user']}\t登录失败")
81 | return False
82 |
83 | # 任务中心
84 | # 位置:我的 -> 任务中心
85 | # 函数作用:获取任务数据以及判断CK是否正确
86 | def getTaskList(self):
87 | url = 'https://store.oppo.com/cn/oapi/credits/web/credits/show'
88 | headers = {
89 | 'Host': 'store.oppo.com',
90 | 'Connection': 'keep-alive',
91 | 'source_type': '501',
92 | 'clientPackage': 'com.oppo.store',
93 | 'Accept': 'application/json, text/plain, */*',
94 | 'Accept-Encoding': 'gzip, deflate',
95 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
96 | 'X-Requested-With': 'com.oppo.store',
97 | 'Referer': 'https://store.oppo.com/cn/app/taskCenter/index?us=gerenzhongxin&um=hudongleyuan&uc=renwuzhongxin'
98 | }
99 | response = self.sess.get(url=url,headers=headers).json()
100 | if response['code'] == 200:
101 | self.taskData = response['data']
102 | return True
103 | else:
104 | notify(f"{self.dic['user']}\t失败原因:{response['errorMessage']}")
105 | return False
106 |
107 | # 每日签到
108 | # 位置: APP → 我的 → 签到
109 | def signIn(self):
110 | signInData = self.taskData['userReportInfoForm'] # 签到数据源
111 | if signInData['status'] == 0 :
112 | for each in signInData['gifts']:
113 | if each['today'] == True:
114 | url = 'https://store.oppo.com/cn/oapi/credits/web/report/immediately'
115 | headers = {
116 | 'Host': 'store.oppo.com',
117 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
118 | 'Content-Type': 'application/x-www-form-urlencoded',
119 | 'Connection': 'keep-alive',
120 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
121 | 'Accept-Encoding': 'gzip, deflate, br',
122 | 'referer':'https://store.oppo.com/cn/app/taskCenter/index'
123 | }
124 | data = {
125 | 'amount': each['credits']
126 | }
127 | while True:
128 | response = self.sess.post(url=url, headers=headers,data=data).json()
129 | if response['code'] == 200:
130 | notify(f"{self.dic['user']}\t签到结果:{response['data']['message']}")
131 | break
132 | elif response['code'] == 1000005:
133 | data = {
134 | 'amount': each['credits'],
135 | 'type': each['type'],
136 | 'gift': each['gift']
137 | }
138 | else:
139 | notify(f"{self.dic['user']}\t签到结果:{response['errorMessage']}")
140 | break
141 | elif signInData['status'] == 1:
142 | notify(f"{self.dic['user']}\t今日已签到")
143 | else:
144 | notify(f"{self.dic['user']}\t未知错误")
145 |
146 | # 秒杀详情页获取商品数据
147 | def getGoodMess(self,count=10):
148 | taskUrl = f'https://msec.opposhop.cn/goods/v1/SeckillRound/goods/{random.randint(100,250)}' # 随机商品
149 | headers = {
150 | 'clientPackage': 'com.oppo.store',
151 | 'Host': 'msec.opposhop.cn',
152 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
153 | 'Content-Type': 'application/x-www-form-urlencoded',
154 | 'Connection': 'keep-alive',
155 | 'User-Agent': 'okhttp/3.12.12.200sp1',
156 | 'Accept-Encoding': 'gzip',
157 | }
158 | params = {
159 | 'pageSize':count + random.randint(1,3)
160 | }
161 | response = self.sess.get(url=taskUrl,headers=headers,params=params).json()
162 | if response['meta']['code'] == 200:
163 | return response
164 |
165 | # 整合每日浏览、分享、推送数据
166 | def dailyTask(self):
167 | if self.taskData['everydayList'] != None:
168 | for eachTask in self.taskData['everydayList']: # 每日任务数据源
169 | if eachTask['marking'] == 'daily_viewgoods':
170 | self.viewData = eachTask
171 | elif eachTask['marking'] == 'daily_sharegoods':
172 | self.shareData = eachTask
173 | # elif eachTask['marking'] == 'daily_viewpush':
174 | # self.pushData = eachTask
175 | return True
176 | else:
177 | notify(f"[每日任务]\t任务数据获取失败,跳过")
178 | return False
179 |
180 | # 浏览任务
181 | def runViewTask(self):
182 | if self.viewData['completeStatus'] == 0:
183 | self.viewGoods(count=self.viewData['times'] - self.viewData['readCount'], flag=1)
184 | elif self.viewData['completeStatus'] == 1:
185 | self.cashingCredits(self.viewData['name'],self.viewData['marking'], self.viewData['type'],self.viewData['credits'])
186 | elif self.viewData['completeStatus'] == 2:
187 | notify(f"[{self.viewData['name']}]\t已完成,奖励已领取")
188 | time.sleep(random.randint(3,5))
189 |
190 |
191 | # 浏览商品
192 | def viewGoods(self, count,flag,dic=None):
193 | headers = {
194 | 'clientPackage': 'com.oppo.store',
195 | 'Host': 'msec.opposhop.cn',
196 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
197 | 'Content-Type': 'application/x-www-form-urlencoded',
198 | 'Connection': 'keep-alive',
199 | 'User-Agent': 'okhttp/3.12.12.200sp1',
200 | 'Accept-Encoding': 'gzip'
201 | }
202 | result = self.getGoodMess(count=count) # 秒杀列表存在商品url
203 | if result['meta']['code'] == 200:
204 | for each in result['detail']:
205 | url = f"https://msec.opposhop.cn/goods/v1/info/sku?skuId={each['skuid']}"
206 | self.sess.get(url=url,headers=headers)
207 | notify(f"正在浏览商品id:{each['skuid']}...")
208 | time.sleep(random.randint(7,10))
209 | if flag == 1: # 来源任务中心的浏览任务
210 | self.cashingCredits(self.viewData['name'], self.viewData['marking'], self.viewData['type'],self.viewData['credits'])
211 | elif flag == 2: # 来源赚积分的浏览任务
212 | self.receiveAward(dic)
213 |
214 | # 分享任务
215 | def runShareTask(self):
216 | if self.shareData['completeStatus'] == 0:
217 | self.shareGoods(flag=1,count=self.shareData['times'] - self.shareData['readCount'])
218 | elif self.shareData['completeStatus'] == 1:
219 | self.cashingCredits(self.shareData['name'],self.shareData['marking'], self.shareData['type'],self.shareData['credits'])
220 | elif self.shareData['completeStatus'] == 2:
221 | notify(f"[{self.shareData['name']}]\t已完成,奖励已领取")
222 | time.sleep(random.randint(1,3))
223 |
224 | # 分享商品
225 | def shareGoods(self, flag,count):
226 | url = 'https://msec.opposhop.cn/users/vi/creditsTask/pushTask'
227 | headers = {
228 | 'clientPackage': 'com.oppo.store',
229 | 'Host': 'msec.opposhop.cn',
230 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
231 | 'Content-Type': 'application/x-www-form-urlencoded',
232 | 'Connection': 'keep-alive',
233 | 'User-Agent': 'okhttp/3.12.12.200sp1',
234 | 'Accept-Encoding': 'gzip',
235 | }
236 | params = {
237 | 'marking': 'daily_sharegoods'
238 | }
239 | for i in range(count + random.randint(1,3)):
240 | self.sess.get(url=url,headers=headers,params=params)
241 | notify(f"正在执行第{i+1}次微信分享...")
242 | time.sleep(random.randint(7,10))
243 | if flag == 1: # 来源任务中心
244 | self.cashingCredits(self.shareData['name'],self.shareData['marking'], self.shareData['type'],self.shareData['credits'])
245 |
246 |
247 | # # 浏览推送任务
248 | # def runViewPush(self):
249 | # if self.pushData['completeStatus'] == 0:
250 | # self.viewPush(self.pushData['times'] - self.pushData['readCount'])
251 | # elif self.pushData['completeStatus'] == 1:
252 | # self.cashingCredits(self.pushData['name'], self.pushData['marking'], self.pushData['type'],self.pushData['credits'])
253 | # elif self.pushData['completeStatus'] == 2:
254 | # notify(f"[{self.pushData['name']}]\t已完成,奖励已领取")
255 | # time.sleep(random.randint(1,3))
256 |
257 | # # 点击推送
258 | # def viewPush(self,count):
259 | # url = 'https://msec.opposhop.cn/users/vi/creditsTask/pushTask'
260 | # headers = {
261 | # 'clientPackage': 'com.oppo.store',
262 | # 'Host': 'msec.opposhop.cn',
263 | # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
264 | # 'Content-Type': 'application/x-www-form-urlencoded',
265 | # 'Connection': 'keep-alive',
266 | # 'User-Agent': 'okhttp/3.12.12.200sp1',
267 | # 'Accept-Encoding': 'gzip',
268 | # }
269 | # params = {
270 | # 'marking': 'daily_viewpush'
271 | # }
272 | # for i in range(count + random.randint(1,3)):
273 | # self.sess.get(url=url,headers=headers,params=params)
274 | # notify(f"正在点击第{i+1}次信息推送...")
275 | # time.sleep(random.randint(7,10))
276 | # self.cashingCredits(self.pushData['name'], self.pushData['marking'], self.pushData['type'],self.pushData['credits'])
277 |
278 | # 领取奖励
279 | def cashingCredits(self,name,marking,type,amount):
280 | url = 'https://store.oppo.com/cn/oapi/credits/web/credits/cashingCredits'
281 | headers = {
282 | 'Host': 'store.oppo.com',
283 | 'Connection': 'keep-alive',
284 | 'Origin': 'https://store.oppo.com',
285 | 'clientPackage': 'com.oppo.store',
286 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
287 | 'Content-Type': 'application/x-www-form-urlencoded',
288 | 'Accept-Encoding': 'gzip, deflate',
289 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
290 | 'Referer':'https://store.oppo.com/cn/app/taskCenter/index?us=gerenzhongxin&um=hudongleyuan&uc=renwuzhongxin'
291 | }
292 | data = {
293 | 'marking':marking,
294 | 'type':str(type),
295 | 'amount':str(amount)
296 | }
297 | response = self.sess.post(url=url,headers=headers,data=data).json()
298 | if response['code'] == 200:
299 | notify(f'{name}\t已领取奖励')
300 | else:
301 | notify(f'{name}\t领取失败')
302 | time.sleep(random.randint(3,5))
303 |
304 | # 赚积分(抽奖)任务
305 | def runEarnPoint(self):
306 | aid = 1418 # 抓包结果为固定值:1418
307 | url = 'https://hd.oppo.com/task/list'
308 | headers = {
309 | 'Host':'hd.oppo.com',
310 | 'Connection': 'keep-alive',
311 | 'Referer':'https://hd.oppo.com/act/m/2021/jifenzhuanpan/index.html?us=gerenzhongxin&um=hudongleyuan&uc=yingjifen',
312 | 'Accept-Encoding': 'gzip, deflate',
313 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
314 | }
315 | params = {
316 | 'aid':aid
317 | }
318 | response = self.sess.get(url=url,headers=headers,params=params).json()
319 | if response['no'] == '200':
320 | for each in response['data']:
321 | if each['title'] == '每日签到':
322 | if each['t_status'] == 0:
323 | self.clockIn(each)
324 | elif each['t_status'] == 1:
325 | self.receiveAward(each)
326 | elif each['t_status'] == 2:
327 | notify(f"[{each['title']}]\t任务完成")
328 | elif each['title'] == '浏览商详':
329 | if each['t_status'] == 0:
330 | self.viewGoods(count=6,flag=2,dic=each)
331 | elif each['t_status'] == 1:
332 | self.receiveAward(each)
333 | elif each['t_status'] == 2:
334 | notify(f"[{each['title']}]\t任务完成")
335 | time.sleep(random.randint(3,5))
336 |
337 | # 赚积分 -> 每日打卡
338 | def clockIn(self,dic):
339 | aid = 1418
340 | url = 'https://hd.oppo.com/task/finish'
341 | headers = {
342 | 'Host': 'hd.oppo.com',
343 | 'Connection': 'keep-alive',
344 | 'Accept': '*/*',
345 | 'Origin': 'https://hd.oppo.com',
346 | 'X-Requested-With': 'XMLHttpRequest',
347 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
348 | 'Referer': 'https://hd.oppo.com/act/m/2021/2021/realmejifendalu/index.html',
349 | 'Accept-Encoding': 'gzip, deflate',
350 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
351 | }
352 | data = {
353 | 'aid': aid,
354 | 't_index': dic['t_index']
355 | }
356 | response = self.sess.post(url=url,headers=headers,data=data).json()
357 | if response['no'] == '200':
358 | notify(f"[{dic['title']}]\t{response['msg']}")
359 | self.receiveAward(dic)
360 | else:
361 | notify(f"[{dic['title']}]\t{response['msg']}")
362 | time.sleep(random.randint(3,5))
363 |
364 | # 领取奖励
365 | def receiveAward(self,dic):
366 | aid = 1418
367 | url = 'https://hd.oppo.com/task/award'
368 | headers = {
369 | 'Host': 'hd.oppo.com',
370 | 'Connection': 'keep-alive',
371 | 'Accept': '*/*',
372 | 'Origin': 'https://hd.oppo.com',
373 | 'X-Requested-With': 'XMLHttpRequest',
374 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
375 | 'Referer': 'https://hd.oppo.com/act/m/2021/jifenzhuanpan/index.html?us=gerenzhongxin&um=hudongleyuan&uc=yingjifen',
376 | 'Accept-Encoding': 'gzip, deflate',
377 | 'Accept-Language': 'zh-CN,en-US;q=0.9'
378 | }
379 | data = {
380 | 'aid': aid,
381 | 't_index': dic['t_index']
382 | }
383 | response = self.sess.post(url=url,headers=headers,data=data).json()
384 | if response['no'] == '200':
385 | notify(f"[{dic['title']}]\t{response['msg']}")
386 | else:
387 | notify(f"[{dic['title']}]\t{response['msg']}")
388 | time.sleep(random.randint(3,5))
389 |
390 | # 跑任务中心
391 | # 位置:我的 -> 任务中心
392 | def runTaskCenter(self):
393 | self.signIn() # 签到打卡
394 | if self.dailyTask() == True:
395 | self.runViewTask() # 浏览任务
396 | self.runShareTask() # 分享任务
397 | self.runEarnPoint() # 赚积分
398 | # self.runViewPush() # 浏览推送任务(已下架)
399 |
400 | # 获取积分数量(只找到这个,找不到昨天积分数据)
401 | def getIntegral(self):
402 | url = 'https://store.oppo.com/cn/oapi/credits/web/credits/show'
403 | headers = {
404 | 'Host': 'store.oppo.com',
405 | 'Connection': 'keep-alive',
406 | 'source_type': '501',
407 | 'clientPackage': 'com.oppo.store',
408 | 'Accept': 'application/json, text/plain, */*',
409 | 'Accept-Encoding': 'gzip, deflate',
410 | 'Accept-Language': 'zh-CN,en-US;q=0.9',
411 | 'X-Requested-With': 'com.oppo.store',
412 | 'Referer': 'https://store.oppo.com/cn/app/taskCenter/index?us=gerenzhongxin&um=hudongleyuan&uc=renwuzhongxin'
413 | }
414 | response = self.sess.get(url=url,headers=headers).json()
415 | if response['code'] == 200:
416 | return f"{self.dic['user']}\t总积分:{response['data']['userCredits']}"
417 | else:
418 | return f"{self.dic['user']}\t错误原因:{response}"
419 |
420 | # 执行欢太商城实例对象
421 | def start(self):
422 | self.sess.headers.update({
423 | "User-Agent":self.dic['UA']
424 | })
425 | self.sess.cookies.update({
426 | "Cookie": self.dic['CK']
427 | })
428 | if self.login() == True:
429 | if self.getTaskList() == True: # 获取任务中心数据,判断CK是否正确(登录可能成功,但无法跑任务)
430 | self.runTaskCenter() # 运行任务中心
431 | notify(self.getIntegral())
432 |
433 | # 检测CK是否存在必备参数
434 | def checkHT(dic):
435 | CK = dic['CK']
436 | if len(re.findall(r'source_type=.*?;',CK)) == 0:
437 | notify(f"{dic['user']}\tCK格式有误:可能缺少`source_type`字段")
438 | return False
439 | if len(re.findall(r'TOKENSID=.*?;',CK)) == 0:
440 | notify(f"{dic['user']}\tCK格式有误:可能缺少`TOKENSID`字段")
441 | return False
442 | if len(re.findall(r'app_param=.*?[;]?',CK)) == 0:
443 | notify(f"{dic['user']}\tCK格式有误:可能缺少`app_param`字段")
444 | return False
445 | return True
446 |
447 | # 兼容云函数
448 | def main_handler(event, context):
449 | global lists
450 | for each in lists:
451 | if each['CK']!='' and each['UA'] != '':
452 | if checkHT(each):
453 | taskCenter = TaskCenter(each)
454 | for count in range(3):
455 | try:
456 | time.sleep(random.randint(2,5)) # 随机延时
457 | taskCenter.start()
458 | break
459 | except requests.exceptions.ConnectionError:
460 | notify(f"{taskCenter.dic['user']}\t请求失败,随机延迟后再次访问")
461 | time.sleep(random.randint(2,5))
462 | continue
463 | else:
464 | notify(f"账号: {taskCenter.dic['user']}\n状态: 取消登录\n原因: 多次登录失败")
465 | break
466 | elif not all(each.values()):
467 | notify("账号:空账户\t状态:跳过")
468 | else:
469 | notify(f"账号: {each['user']}\n状态: 取消登录\n原因: json数据不齐全")
470 | notify('*' * 40 + '\n')
471 | if not os.path.basename(__file__).split('_')[-1][:-3] in notifyBlackList:
472 | send('欢太任务中心',allMess)
473 |
474 | if __name__ == '__main__':
475 | main_handler(None,None)
476 |
--------------------------------------------------------------------------------
/sendNotify.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # _*_ coding:utf-8 _*_
3 | import base64
4 | import hashlib
5 | import hmac
6 | import json
7 | import os
8 | import re
9 | import threading
10 | import time
11 | import traceback
12 | import urllib.parse
13 |
14 | import requests
15 |
16 | # 原先的 print 函数和主线程的锁
17 | _print = print
18 | mutex = threading.Lock()
19 |
20 |
21 | # 定义新的 print 函数
22 | def print(text, *args, **kw):
23 | """
24 | 使输出有序进行,不出现多线程同一时间输出导致错乱的问题。
25 | """
26 | with mutex:
27 | _print(text, *args, **kw)
28 |
29 |
30 | # 通知服务
31 | # fmt: off
32 | push_config = {
33 | 'HITOKOTO': False, # 启用一言(随机句子)
34 |
35 | 'BARK_PUSH': '', # bark IP 或设备码,例:https://api.day.app/DxHcxxxxxRxxxxxxcm
36 | 'BARK_ARCHIVE': '', # bark 推送是否存档
37 | 'BARK_GROUP': '', # bark 推送分组
38 | 'BARK_SOUND': '', # bark 推送声音
39 |
40 | 'CONSOLE': False, # 控制台输出
41 |
42 | 'DD_BOT_SECRET': '', # 钉钉机器人的 DD_BOT_SECRET
43 | 'DD_BOT_TOKEN': '', # 钉钉机器人的 DD_BOT_TOKEN
44 |
45 | 'FSKEY': '', # 飞书机器人的 FSKEY
46 |
47 | 'GOBOT_URL': '', # go-cqhttp
48 | # 推送到个人QQ:http://127.0.0.1/send_private_msg
49 | # 群:http://127.0.0.1/send_group_msg
50 | 'GOBOT_QQ': '', # go-cqhttp 的推送群或用户
51 | # GOBOT_URL 设置 /send_private_msg 时填入 user_id=个人QQ
52 | # /send_group_msg 时填入 group_id=QQ群
53 | 'GOBOT_TOKEN': '', # go-cqhttp 的 access_token
54 |
55 | 'IGOT_PUSH_KEY': '', # iGot 聚合推送的 IGOT_PUSH_KEY
56 |
57 | 'PUSH_KEY': '', # server 酱的 PUSH_KEY,兼容旧版与 Turbo 版
58 |
59 | 'PUSH_PLUS_TOKEN': '', # push+ 微信推送的用户令牌
60 | 'PUSH_PLUS_USER': '', # push+ 微信推送的群组编码
61 |
62 | 'QMSG_KEY': '', # qmsg 酱的 QMSG_KEY
63 | 'QMSG_TYPE': '', # qmsg 酱的 QMSG_TYPE
64 |
65 | 'QYWX_AM': '', # 企业微信应用
66 |
67 | 'QYWX_KEY': '', # 企业微信机器人
68 |
69 | 'TG_BOT_TOKEN': '', # tg 机器人的 TG_BOT_TOKEN,例:1407203283:AAG9rt-6RDaaX0HBLZQq0laNOh898iFYaRQ
70 | 'TG_USER_ID': '', # tg 机器人的 TG_USER_ID,例:1434078534
71 | 'TG_API_HOST': '', # tg 代理 api
72 | 'TG_PROXY_AUTH': '', # tg 代理认证参数
73 | 'TG_PROXY_HOST': '', # tg 机器人的 TG_PROXY_HOST
74 | 'TG_PROXY_PORT': '', # tg 机器人的 TG_PROXY_PORT
75 | }
76 | notify_function = []
77 | # fmt: on
78 |
79 | # 首先读取 面板变量 或者 github action 运行变量
80 | for k in push_config:
81 | if os.getenv(k):
82 | v = os.getenv(k)
83 | push_config[k] = v
84 |
85 |
86 | def bark(title: str, content: str) -> None:
87 | """
88 | 使用 bark 推送消息。
89 | """
90 | if not push_config.get("BARK_PUSH"):
91 | print("bark 服务的 BARK_PUSH 未设置!!\n取消推送")
92 | return
93 | print("bark 服务启动")
94 |
95 | if push_config.get("BARK_PUSH").startswith("http"):
96 | url = f'{push_config.get("BARK_PUSH").rstrip("/")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
97 | else:
98 | url = f'https://api.day.app/{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}'
99 |
100 | bark_params = {
101 | "BARK_ARCHIVE": "isArchive",
102 | "BARK_GROUP": "group",
103 | "BARK_SOUND": "sound",
104 | }
105 | params = ""
106 | for pair in filter(
107 | lambda pairs: pairs[0].startswith("BARK_")
108 | and pairs[0] != "BARK_PUSH"
109 | and pairs[1]
110 | and bark_params.get(pairs[0]),
111 | push_config.items(),
112 | ):
113 | params += f"{bark_params.get(pair[0])}={pair[1]}&"
114 | if params:
115 | url = url + "?" + params.rstrip("&")
116 |
117 | try:
118 | response = requests.get(url, timeout=15)
119 | try:
120 | datas = response.json()
121 | if datas.get("code") == 200:
122 | print("bark 推送成功!")
123 | elif datas.get("code") == 400:
124 | print("bark 推送失败!找不到 Key 对应的 DeviceToken。")
125 | else:
126 | print(f"bark 推送失败!响应数据:{datas}")
127 | except json.JSONDecodeError:
128 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
129 | except requests.exceptions.RequestException:
130 | print(f"网络异常,请检查你的网络连接、推送服务器和代理配置。\n{traceback.format_exc()}")
131 | except Exception:
132 | print(f"其他错误信息:\n{traceback.format_exc()}")
133 |
134 |
135 | def console(title: str, content: str) -> None:
136 | """
137 | 使用 控制台 推送消息。
138 | """
139 | print(f"{title}\n\n{content}")
140 |
141 |
142 | def dingding_bot(title: str, content: str) -> None:
143 | """
144 | 使用 钉钉机器人 推送消息。
145 | """
146 | if not push_config.get("DD_BOT_SECRET") or not push_config.get("DD_BOT_TOKEN"):
147 | print("钉钉机器人 服务的 DD_BOT_SECRET 或者 DD_BOT_TOKEN 未设置!!\n取消推送")
148 | return
149 | print("钉钉机器人 服务启动")
150 |
151 | timestamp = str(round(time.time() * 1000))
152 | secret_enc = push_config.get("DD_BOT_SECRET").encode("utf-8")
153 | string_to_sign = "{}\n{}".format(timestamp, push_config.get("DD_BOT_SECRET"))
154 | string_to_sign_enc = string_to_sign.encode("utf-8")
155 | hmac_code = hmac.new(
156 | secret_enc, string_to_sign_enc, digestmod=hashlib.sha256
157 | ).digest()
158 | sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
159 | url = f'https://oapi.dingtalk.com/robot/send?access_token={push_config.get("DD_BOT_TOKEN")}×tamp={timestamp}&sign={sign}'
160 | headers = {"Content-Type": "application/json;charset=utf-8"}
161 | data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
162 |
163 | try:
164 | response = requests.post(
165 | url=url, data=json.dumps(data), headers=headers, timeout=15
166 | )
167 | try:
168 | datas = response.json()
169 | if datas.get("errcode") == 0:
170 | print("钉钉机器人 推送成功!")
171 | else:
172 | print(f"钉钉机器人 推送失败!响应数据:{datas}")
173 | except json.JSONDecodeError:
174 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
175 | except requests.exceptions.RequestException:
176 | print(f"网络异常,请检查你的网络连接、推送服务器和代理配置。\n{traceback.format_exc()}")
177 | except Exception:
178 | print(f"其他错误信息:\n{traceback.format_exc()}")
179 |
180 |
181 | def feishu_bot(title: str, content: str) -> None:
182 | """
183 | 使用 飞书机器人 推送消息。
184 | """
185 | if not push_config.get("FSKEY"):
186 | print("飞书 服务的 FSKEY 未设置!!\n取消推送")
187 | return
188 | print("飞书 服务启动")
189 |
190 | url = f'https://open.feishu.cn/open-apis/bot/v2/hook/{push_config.get("FSKEY")}'
191 | data = {"msg_type": "text", "content": {"text": f"{title}\n\n{content}"}}
192 | try:
193 | response = requests.post(url, data=json.dumps(data), timeout=15)
194 | try:
195 | datas = response.json()
196 | if datas.get("StatusCode") == 0:
197 | print("飞书 推送成功!")
198 | else:
199 | print(f"飞书 推送失败!响应数据:{datas}")
200 | except json.JSONDecodeError:
201 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
202 | except requests.exceptions.RequestException:
203 | print(f"网络异常,请检查你的网络连接、推送服务器和代理配置。\n{traceback.format_exc()}")
204 | except Exception:
205 | print(f"其他错误信息:\n{traceback.format_exc()}")
206 |
207 |
208 | def go_cqhttp(title: str, content: str) -> None:
209 | """
210 | 使用 go_cqhttp 推送消息。
211 | """
212 | if not push_config.get("GOBOT_URL") or not push_config.get("GOBOT_QQ"):
213 | print("go-cqhttp 服务的 GOBOT_URL 或 GOBOT_QQ 未设置!!\n取消推送")
214 | return
215 | print("go-cqhttp 服务启动")
216 |
217 | url = f'{push_config.get("GOBOT_URL")}?access_token={push_config.get("GOBOT_TOKEN")}&{push_config.get("GOBOT_QQ")}&message=标题:{title}\n内容:{content}'
218 |
219 | try:
220 | response = requests.get(url, timeout=15)
221 | try:
222 | datas = response.json()
223 | if datas.get("status") == "ok":
224 | print("go-cqhttp 推送成功!")
225 | else:
226 | print(f"go-cqhttp 推送失败!响应数据:{datas}")
227 | except json.JSONDecodeError:
228 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
229 | except requests.exceptions.RequestException:
230 | print(f"网络异常,请检查你的网络连接、推送服务器和代理配置。\n{traceback.format_exc()}")
231 | except Exception:
232 | print(f"其他错误信息:\n{traceback.format_exc()}")
233 |
234 |
235 | def iGot(title: str, content: str) -> None:
236 | """
237 | 使用 iGot 推送消息。
238 | """
239 | if not push_config.get("IGOT_PUSH_KEY"):
240 | print("iGot 服务的 IGOT_PUSH_KEY 未设置!!\n取消推送")
241 | return
242 | print("iGot 服务启动")
243 |
244 | url = f'https://push.hellyw.com/{push_config.get("IGOT_PUSH_KEY")}'
245 | data = {"title": title, "content": content}
246 | headers = {"Content-Type": "application/x-www-form-urlencoded"}
247 |
248 | try:
249 | response = requests.post(url, data=data, headers=headers, timeout=15)
250 | try:
251 | datas = response.json()
252 | if datas.get("ret") == 0:
253 | print("iGot 推送成功!")
254 | else:
255 | print(f'iGot 推送失败!错误信息:{datas.get("errMsg")}')
256 | except json.JSONDecodeError:
257 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
258 | except requests.exceptions.RequestException:
259 | print(f"网络异常,请检查你的网络连接、推送服务器和代理配置。\n{traceback.format_exc()}")
260 | except Exception:
261 | print(f"其他错误信息:\n{traceback.format_exc()}")
262 |
263 |
264 | def serverJ(title: str, content: str) -> None:
265 | """
266 | 通过 serverJ 推送消息。
267 | """
268 | if not push_config.get("PUSH_KEY"):
269 | print("serverJ 服务的 PUSH_KEY 未设置!!\n取消推送")
270 | return
271 | print("serverJ 服务启动")
272 |
273 | data = {"text": title, "desp": content.replace("\n", "\n\n")}
274 | if push_config.get("PUSH_KEY").index("SCT") != -1:
275 | url = f'https://sctapi.ftqq.com/{push_config.get("PUSH_KEY")}.send'
276 | else:
277 | url = f'https://sc.ftqq.com/${push_config.get("PUSH_KEY")}.send'
278 |
279 | try:
280 | response = requests.post(url, data=data, timeout=15)
281 | try:
282 | datas = response.json()
283 | if datas.get("errno") == 0 or datas.get("code") == 0:
284 | print("serverJ 推送成功!")
285 | elif datas.get("code") == 40001:
286 | print("serverJ 推送失败!PUSH_KEY 错误。")
287 | else:
288 | print(f'serverJ 推送失败!错误码:{datas.get("message")}')
289 | except json.JSONDecodeError:
290 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
291 | except requests.exceptions.RequestException:
292 | print(f"网络异常,请检查你的网络连接、推送服务器和代理配置。\n{traceback.format_exc()}")
293 | except Exception:
294 | print(f"其他错误信息:\n{traceback.format_exc()}")
295 |
296 |
297 | def pushplus_bot(title: str, content: str) -> None:
298 | """
299 | 通过 push+ 推送消息。
300 | """
301 | if not push_config.get("PUSH_PLUS_TOKEN"):
302 | print("PUSHPLUS 服务的 PUSH_PLUS_TOKEN 未设置!!\n取消推送")
303 | return
304 | print("PUSHPLUS 服务启动")
305 |
306 | url = "http://www.pushplus.plus/send"
307 | data = {
308 | "token": push_config.get("PUSH_PLUS_TOKEN"),
309 | "title": title,
310 | "content": content,
311 | "topic": push_config.get("PUSH_PLUS_USER"),
312 | }
313 | body = json.dumps(data).encode(encoding="utf-8")
314 | headers = {"Content-Type": "application/json"}
315 |
316 | try:
317 | response = requests.post(url=url, data=body, headers=headers, timeout=15)
318 | try:
319 | datas = response.json()
320 | if datas.get("code") == 200:
321 | print("PUSHPLUS 推送成功!")
322 | elif datas.get("code") == 600:
323 | url2 = "http://pushplus.hxtrip.com/send"
324 | response2 = requests.post(
325 | url=url2, data=body, headers=headers, timeout=15
326 | )
327 | try:
328 | datas2 = response2.json()
329 | if datas2.get("code") == 200:
330 | print("PUSHPLUS(hxtrip) 推送成功!")
331 | elif datas2.get("code") == 600:
332 | print("PUSHPLUS 推送失败!PUSH_PLUS_TOKEN 错误。")
333 | else:
334 | print(f"PUSHPLUS(hxtrip) 推送失败!响应数据:{datas2}")
335 | except json.JSONDecodeError:
336 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response2.text}")
337 | else:
338 | print(f"PUSHPLUS 推送失败!响应数据:{datas}")
339 | except json.JSONDecodeError:
340 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
341 | except requests.exceptions.RequestException:
342 | print(f"网络异常,请检查你的网络连接、推送服务器和代理配置。\n{traceback.format_exc()}")
343 | except Exception:
344 | print(f"其他错误信息:\n{traceback.format_exc()}")
345 |
346 |
347 | def qmsg_bot(title: str, content: str) -> None:
348 | """
349 | 使用 qmsg 推送消息。
350 | """
351 | if not push_config.get("QMSG_KEY") or not push_config.get("QMSG_TYPE"):
352 | print("qmsg 的 QMSG_KEY 或者 QMSG_TYPE 未设置!!\n取消推送")
353 | return
354 | print("qmsg 服务启动")
355 |
356 | url = f'https://qmsg.zendee.cn/{push_config.get("QMSG_TYPE")}/{push_config.get("QMSG_KEY")}'
357 | payload = {"msg": f'{title}\n\n{content.replace("----", "-")}'.encode("utf-8")}
358 |
359 | try:
360 | response = requests.post(url=url, params=payload, timeout=15)
361 | try:
362 | datas = response.json()
363 | if response.get("code") == 0:
364 | print("qmsg 推送成功!")
365 | else:
366 | print(f'qmsg 推送失败!错误信息:{datas.get("reason")}')
367 | except json.JSONDecodeError:
368 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
369 | except requests.exceptions.RequestException:
370 | print(f"网络异常,请检查你的网络连接、推送服务器和代理配置。\n{traceback.format_exc()}")
371 | except Exception:
372 | print(f"其他错误信息:\n{traceback.format_exc()}")
373 |
374 |
375 | def wecom_app(title: str, content: str) -> None:
376 | """
377 | 通过 企业微信 APP 推送消息。
378 | """
379 | if not push_config.get("QYWX_AM"):
380 | print("QYWX_AM 未设置!!\n取消推送")
381 | return
382 | QYWX_AM_AY = re.split(",", push_config.get("QYWX_AM"))
383 | if 4 < len(QYWX_AM_AY) > 5:
384 | print("QYWX_AM 设置错误!!\n取消推送")
385 | return
386 | print("企业微信 APP 服务启动")
387 |
388 | corpid = QYWX_AM_AY[0]
389 | corpsecret = QYWX_AM_AY[1]
390 | touser = QYWX_AM_AY[2]
391 | agentid = QYWX_AM_AY[3]
392 | try:
393 | media_id = QYWX_AM_AY[4]
394 | except IndexError:
395 | media_id = ""
396 | wx = WeCom(corpid, corpsecret, agentid)
397 | # 如果没有配置 media_id 默认就以 text 方式发送
398 | try:
399 | if not media_id:
400 | message = title + "\n\n" + content
401 | datas = wx.send_text(message, touser)
402 | else:
403 | datas = wx.send_mpnews(title, content, media_id, touser)
404 | if datas == "ok":
405 | print("企业微信推送成功!")
406 | else:
407 | print(f"企业微信推送失败!错误信息:{datas}")
408 | except requests.exceptions.RequestException:
409 | print(f"网络异常,请检查你的网络连接、推送服务器和代理配置。\n{traceback.format_exc()}")
410 | except Exception:
411 | print(f"其他错误信息:\n{traceback.format_exc()}")
412 |
413 |
414 | class WeCom:
415 | def __init__(self, corpid, corpsecret, agentid):
416 | self.CORPID = corpid
417 | self.CORPSECRET = corpsecret
418 | self.AGENTID = agentid
419 |
420 | def get_access_token(self):
421 | url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
422 | values = {
423 | "corpid": self.CORPID,
424 | "corpsecret": self.CORPSECRET,
425 | }
426 | req = requests.post(url, params=values, timeout=15)
427 | datas = json.loads(req.text)
428 | return datas.get("access_token")
429 |
430 | def send_text(self, message, touser="@all"):
431 | send_url = (
432 | "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
433 | + self.get_access_token()
434 | )
435 | send_values = {
436 | "touser": touser,
437 | "msgtype": "text",
438 | "agentid": self.AGENTID,
439 | "text": {"content": message},
440 | "safe": "0",
441 | }
442 | send_msges = bytes(json.dumps(send_values), "utf-8")
443 | response = requests.post(send_url, send_msges, timeout=15)
444 | try:
445 | datas = response.json()
446 | return datas.get("errmsg")
447 | except json.JSONDecodeError:
448 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
449 | return response.text
450 |
451 | def send_mpnews(self, title, message, media_id, touser="@all"):
452 | send_url = (
453 | "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token="
454 | + self.get_access_token()
455 | )
456 | send_values = {
457 | "touser": touser,
458 | "msgtype": "mpnews",
459 | "agentid": self.AGENTID,
460 | "mpnews": {
461 | "articles": [
462 | {
463 | "title": title,
464 | "thumb_media_id": media_id,
465 | "author": "Author",
466 | "content_source_url": "",
467 | "content": message.replace("\n", "
"),
468 | "digest": message,
469 | }
470 | ]
471 | },
472 | }
473 | send_msges = bytes(json.dumps(send_values), "utf-8")
474 | response = requests.post(send_url, send_msges, timeout=15)
475 | try:
476 | datas = response.json()
477 | return datas.get("errmsg")
478 | except json.JSONDecodeError:
479 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
480 | return response.text
481 |
482 |
483 | def wecom_bot(title: str, content: str) -> None:
484 | """
485 | 通过 企业微信机器人 推送消息。
486 | """
487 | if not push_config.get("QYWX_KEY"):
488 | print("企业微信机器人 服务的 QYWX_KEY 未设置!!\n取消推送")
489 | return
490 | print("企业微信机器人服务启动")
491 |
492 | url = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={push_config.get('QYWX_KEY')}"
493 | headers = {"Content-Type": "application/json;charset=utf-8"}
494 | data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}}
495 |
496 | try:
497 | response = requests.post(
498 | url=url, data=json.dumps(data), headers=headers, timeout=15
499 | )
500 | try:
501 | datas = response.json()
502 | if datas.get("errcode") == 0:
503 | print("企业微信机器人 推送成功!")
504 | else:
505 | print(f"企业微信机器人 推送失败!响应数据:{datas}")
506 | except json.JSONDecodeError:
507 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
508 | except requests.exceptions.RequestException:
509 | print(f"网络异常,请检查你的网络连接、推送服务器和代理配置。\n{traceback.format_exc()}")
510 | except Exception:
511 | print(f"其他错误信息:\n{traceback.format_exc()}")
512 |
513 |
514 | def telegram_bot(title: str, content: str) -> None:
515 | """
516 | 使用 telegram 机器人 推送消息。
517 | """
518 | if not push_config.get("TG_BOT_TOKEN") or not push_config.get("TG_USER_ID"):
519 | print("tg 服务的 bot_token 或者 user_id 未设置!!\n取消推送")
520 | return
521 | print("tg 服务启动")
522 |
523 | if push_config.get("TG_API_HOST"):
524 | url = f"https://{push_config.get('TG_API_HOST')}/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
525 | else:
526 | url = (
527 | f"https://api.telegram.org/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage"
528 | )
529 | headers = {"Content-Type": "application/x-www-form-urlencoded"}
530 | payload = {
531 | "chat_id": str(push_config.get("TG_USER_ID")),
532 | "text": f"{title}\n\n{content}",
533 | "disable_web_page_preview": "true",
534 | }
535 | proxies = None
536 | if push_config.get("TG_PROXY_HOST") and push_config.get("TG_PROXY_PORT"):
537 | if push_config.get("TG_PROXY_AUTH") is not None and "@" not in push_config.get(
538 | "TG_PROXY_HOST"
539 | ):
540 | push_config["TG_PROXY_HOST"] = (
541 | push_config.get("TG_PROXY_AUTH")
542 | + "@"
543 | + push_config.get("TG_PROXY_HOST")
544 | )
545 | proxyStr = "http://{}:{}".format(
546 | push_config.get("TG_PROXY_HOST"), push_config.get("TG_PROXY_PORT")
547 | )
548 | proxies = {"http": proxyStr, "https": proxyStr}
549 |
550 | try:
551 | response = requests.post(
552 | url=url, headers=headers, params=payload, proxies=proxies, timeout=15
553 | )
554 | try:
555 | datas = response.json()
556 | if datas.get("ok") == True:
557 | print("tg 推送成功!")
558 | elif datas.get("error_code") == 400:
559 | print("tg 推送失败!请主动给 bot 发送一条消息并检查接收用户 TG_USER_ID 是否正确。")
560 | elif datas.get("error_code") == 401:
561 | print("tg 推送失败!TG_BOT_TOKEN 填写错误。")
562 | else:
563 | print(f"tg 推送失败!响应数据:{datas}")
564 | except json.JSONDecodeError:
565 | print(f"推送返回值非 json 格式,请检查网址和账号是否填写正确。\n{response.text}")
566 | except requests.exceptions.RequestException:
567 | print(f"网络异常,请检查你的网络连接、推送服务器和代理配置。\n{traceback.format_exc()}")
568 | except Exception:
569 | print(f"其他错误信息:\n{traceback.format_exc()}")
570 |
571 |
572 | def one() -> str:
573 | """
574 | 获取一条一言。
575 | :return:
576 | """
577 | try:
578 | url = "https://v1.hitokoto.cn/"
579 | res = requests.get(url).json()
580 | return res["hitokoto"] + " ----" + res["from"]
581 | except requests.exceptions.ConnectionError:
582 | return ""
583 |
584 |
585 | if push_config.get("BARK_PUSH"):
586 | notify_function.append(bark)
587 | if push_config.get("CONSOLE"):
588 | notify_function.append(console)
589 | if push_config.get("DD_BOT_TOKEN") and push_config.get("DD_BOT_SECRET"):
590 | notify_function.append(dingding_bot)
591 | if push_config.get("FSKEY"):
592 | notify_function.append(feishu_bot)
593 | if push_config.get("GOBOT_URL") and push_config.get("GOBOT_QQ"):
594 | notify_function.append(go_cqhttp)
595 | if push_config.get("IGOT_PUSH_KEY"):
596 | notify_function.append(iGot)
597 | if push_config.get("PUSH_KEY"):
598 | notify_function.append(serverJ)
599 | if push_config.get("PUSH_PLUS_TOKEN"):
600 | notify_function.append(pushplus_bot)
601 | if push_config.get("QMSG_KEY") and push_config.get("QMSG_TYPE"):
602 | notify_function.append(qmsg_bot)
603 | if push_config.get("QYWX_AM"):
604 | notify_function.append(wecom_app)
605 | if push_config.get("QYWX_KEY"):
606 | notify_function.append(wecom_bot)
607 | if push_config.get("TG_BOT_TOKEN") and push_config.get("TG_USER_ID"):
608 | notify_function.append(telegram_bot)
609 |
610 |
611 | def send(title: str, content: str) -> None:
612 | if not content:
613 | print(f"{title} 推送内容为空!")
614 | return
615 |
616 | hitokoto = push_config.get("HITOKOTO")
617 |
618 | text = one() if hitokoto else ""
619 | content += "\n\n" + text
620 |
621 | ts = [
622 | threading.Thread(target=mode, args=(title, content), name=mode.__name__)
623 | for mode in notify_function
624 | ]
625 | [t.start() for t in ts]
626 | [t.join() for t in ts]
627 |
628 |
629 | def main():
630 | send("title", "content")
631 |
632 |
633 | if __name__ == "__main__":
634 | main()
635 |
--------------------------------------------------------------------------------