From 52d3612c8a5d4af2b70469a720cf958d10ab5096 Mon Sep 17 00:00:00 2001 From: CHERWIN Date: Mon, 8 Apr 2024 02:14:22 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E6=AC=A1=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ALYP.py | 942 +++++++++++++++++++++++++++++++++++ BWCJ.py | 286 +++++++++++ CHERWIN_TOOLS.py | 495 +++++++++++++++++++ DBKD.py | 425 ++++++++++++++++ HDL.py | 331 +++++++++++++ JTSD.py | 242 +++++++++ KFHS.py | 354 +++++++++++++ KWW.py | 366 ++++++++++++++ NXDD.py | 335 +++++++++++++ PPCS.py | 554 +++++++++++++++++++++ SFSY.py | 1121 +++++++++++++++++++++++++++++++++++++++++ TYQH.py | 1237 ++++++++++++++++++++++++++++++++++++++++++++++ TYYP.py | 280 +++++++++++ YDKD.py | 368 ++++++++++++++ YHSH.py | 1121 +++++++++++++++++++++++++++++++++++++++++ ZTKD.py | 237 +++++++++ notify.py | 552 +++++++++++++++++++++ 17 files changed, 9246 insertions(+) create mode 100755 ALYP.py create mode 100755 BWCJ.py create mode 100755 CHERWIN_TOOLS.py create mode 100755 DBKD.py create mode 100755 HDL.py create mode 100755 JTSD.py create mode 100755 KFHS.py create mode 100755 KWW.py create mode 100755 NXDD.py create mode 100755 PPCS.py create mode 100755 SFSY.py create mode 100755 TYQH.py create mode 100755 TYYP.py create mode 100755 YDKD.py create mode 100755 YHSH.py create mode 100755 ZTKD.py create mode 100755 notify.py diff --git a/ALYP.py b/ALYP.py new file mode 100755 index 0000000..4001b35 --- /dev/null +++ b/ALYP.py @@ -0,0 +1,942 @@ +''' +阿里云盘签到 +功能:自动签到,领取签到奖品,支持多账号(使用#分割token),支持青龙 +到这里获取token:http://qr.ziyuand.cn/ + +cron: 1 1,12 1 * * * +by:cherwin +''' +import base64 +import hashlib +import json +import os +import random +import time + +import requests +from os import environ, path +from sys import exit +import datetime +from requests.packages.urllib3.exceptions import InsecureRequestWarning + +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) + + +def load_send(): + global send, mg + cur_path = path.abspath(path.dirname(__file__)) + if path.exists(cur_path + "/notify.py"): + try: + from notify import send + print("加载通知服务成功!") + except: + send = False + print("加载通知服务失败~") + else: + send = False + print("加载通知服务失败~") + + +load_send() +send_msg = '' + + +def Log(cont): + global send_msg + print(cont) + send_msg += f'{cont}\n' + + +REFRESHTOEKN_PATH = "ALYP_REFRESH_TOEKN.json" + + +def saveRefreeshToken(data): + # 保存数据到文件 + if os.path.isfile(REFRESHTOEKN_PATH): + with open(REFRESHTOEKN_PATH, 'r') as file: + try: + refresh_tokens = json.load(file) + except: + refresh_tokens = {} + else: + refresh_tokens = {} + refresh_tokens.update(data) + with open(REFRESHTOEKN_PATH, 'w') as file: + json.dump(refresh_tokens, file) + + +def loadRefreshTokens(): + try: + with open(REFRESHTOEKN_PATH, 'r') as file: + file_content = file.read() + # print(file_content) + if file_content: + refresh_tokens = json.loads(file_content) + else: + refresh_tokens = '' + except FileNotFoundError: + refresh_tokens = '' + + return refresh_tokens + + +def is_last_day_of_month(): + today = datetime.date.today() + next_month = today.replace(day=28) + datetime.timedelta(days=4) + last_day = next_month - datetime.timedelta(days=next_month.day) + return today == last_day + + +class AliDrive_CheckIn: + def __init__(self, refresh_token, ali_reward): + self.userAgent = "Mozilla/5.0 (Linux; U; Android 11; zh-CN; Mi9 Pro 5G Build/RKQ1.200826.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.100 UWS/3.22.2.28 Mobile Safari/537.36 UCBS/3.22.2.28_210922181100 ChannelId(0) NebulaSDK/1.8.100112 Nebula InsidePlus/10.2.3 AliApp(AYSD/4.9.1) AlipayDefined(nt:WIFI,ws:393|0|2.75)zh-CN useStatusBar/true isConcaveScreen/trueAriver/1.0.0" + self.refresh_token = refresh_token + self.ali_reward = ali_reward + self.file_id = '' + self.headers = { + "Content-Type": "application/json", + "charset": "utf-8", + "User-Agent": self.userAgent + } + + def getToken(self): + url = 'https://auth.aliyundrive.com/v2/account/token' + body = { + "grant_type": "refresh_token", + "refresh_token": self.refresh_token + } + response = s.post(url, headers=self.headers, json=body, verify=False) + try: + resp = response.json() + if resp.get('code') == 'InvalidParameter.RefreshToken': + Log('\nRefreshToken 有误请检查!(可能token失效了,到这里获取http://qr.ziyuand.cn)\n') + return False + else: + self.aliYunPanToken = f'Bearer {resp.get("access_token", "")}' + self.access_token = resp.get("access_token", "") + self.aliYunPanRefreshToken = resp.get("refresh_token", "") + print(f'refresh_token:{self.aliYunPanRefreshToken}') + self.user_id = resp.get("user_id", "") + self.headers['Authorization'] = self.aliYunPanToken + Log(f">账号ID:【{self.user_id}】\n>获取token成功") + self.getUserInfo() + # # 保存数据到文件 + # saveData = {self.user_id: self.aliYunPanRefreshToken} + # saveRefreeshToken(saveData) + return True + except: + print(response.text) + return False + + def getUserInfo(self): + url = 'https://api.aliyundrive.com/adrive/v2/user/get' + body = { + "addition_data": {}, + "user_id": self.user_id + } + response = s.post(url, headers=self.headers, json=body, verify=False) + try: + resp = response.json() + self.phone = resp.get("phone", "") + self.default_drive_id = resp.get("default_drive_id", "") + if self.phone !='': + self.phone = self.phone[:3] + '*' * 4 + self.phone[7:] + Log(f">手机号:【{self.phone}】") + # 保存数据到文件 + saveData = {self.phone: self.aliYunPanRefreshToken} + saveRefreeshToken(saveData) + return True + except: + print(response.text) + + def get_sign_in_list(self): + Log(f'>>>>开始签到任务') + sign_url = 'https://member.aliyundrive.com/v2/activity/sign_in_list?_rx-s=mobile}' + sign_body = {'isReward': False} + sign_res = s.post(sign_url, headers=self.headers, json=sign_body, verify=False) + + try: + sign_resp = sign_res.json() + result = sign_resp.get('result', {}) + self.sign_in_count = result.get('signInCount', 0) + is_sign_in = result.get('isSignIn', False) + + if is_sign_in: + Log(f'>签到成功!\n>已累计签到{self.sign_in_count}天!') + else: + Log(f'>今日已签到!\n>已累计签到{self.sign_in_count}天!') + + sign_in_infos = result.get('signInInfos', []) + rewards_list = sign_in_infos[self.sign_in_count - 1].get('rewards', []) + status = rewards_list[1].get('status', '') + # print(status) + remind = rewards_list[1].get('remind', '') + complete_status_list = ["verification", "finished", "end"] + + if status not in complete_status_list: + self.handle_task(remind) + else: + print(f'>任务【{remind}】已完成') + except Exception as e: + print(f"获取签到列表失败:{e}") + + def handle_task(self, task_name): + Log(f'>>开始【{task_name}】任务') + if task_name == '接3次好运瓶即可领取奖励': + self.bottle_fish() + elif task_name == '订阅官方账号「阿里盘盘酱」即可领取奖励': + self.follow_user() + elif task_name == '上传10个文件到备份盘即可领取奖励': + self.fileName = '签到任务文件_喜欢可以赞赏一波_谢谢.jpg' + self.upload_files_to_drive(10) + elif task_name == '开启手机自动备份并持续至少一小时': + self.update_device_extras() + elif task_name == '备份10张照片到相册即可领取奖励': + self.fileName = '签到任务文件_喜欢可以赞赏一波_谢谢.jpg' + self.upload_files_to_drive(10, 'alibum') + elif task_name == '播放1个视频30秒即可领取奖励': + # pass + self.get_videoList() + elif task_name == '接好运瓶并转存任意1个文件': + self.get_bottleShareId() + else: + Log(f'>【{task_name}】-暂不支持此任务,请手动完成!') + time.sleep(2) + + ###############################文件上传任务开始############################### + + def upload_files_to_drive(self, num_files, drive_type='Default'): + for i in range(num_files): + self.get_user_drive_info(drive_type) + time.sleep(1) + + def get_user_drive_info(self, drive_type): + url = "https://api.aliyundrive.com/v2/drive/list_my_drives" + response = s.post(url, headers=self.headers, json={}) + try: + if response.status_code == 200: + data = response.json() + # print(data) + drive_list = data.get("items", []) + if drive_list != []: + index = None + for i, item in enumerate(drive_list): + if drive_type == 'alibum': + if item['drive_name'] == 'alibum': + index = i + break + else: + if item['drive_name'] == 'Default' and item['category'] == 'backup': + index = i + break + self.drive_id = drive_list[index]['drive_id'] + print(f'当前drive ID:{self.drive_id}') + if self.drive_id: + self.file_create(drive_type,True) + else: + print("获取用户云盘信息API请求失败") + except Exception as e: + print(f"获取用户云盘信息失败:{e}") + + def get_file_size(self, file_path): + try: + # 获取文件大小 + print(f'文件大小{os.path.getsize(file_path)}') + return os.path.getsize(file_path) + except OSError: + return 0 + + def download_file(self, url,filename): + response = requests.get(url,verify=False) + if response.status_code == 200: + with open(filename, 'wb') as f: + f.write(response.content) + print(f'{filename} 下载签到视频文件完成!') + return True + else: + print(f'下载签到视频文件失败:{response.status_code}') + return False + + def get_file_pre_hash(self, file_path,HashType='content_hash'): + if HashType =='pre_hash': + with open(file_path, 'rb') as f: + sha1 = hashlib.sha1() + data = f.read(1024) # 只读取前 1KB 的数据 + sha1.update(data) + print(f'当前文件前1K hash值:{sha1.hexdigest().upper()}') + return sha1.hexdigest().upper() + else: + with open(file_path, 'rb') as f: + sha1 = hashlib.sha1() + while True: + data = f.read(4096) + if not data: + break + sha1.update(data) + print(f'当前文件完整hash值:{sha1.hexdigest().upper()}') + return sha1.hexdigest().upper() + + + def get_signTaskFileId(self): + url = "https://api.aliyundrive.com/v2/file/search" + json_data = { + 'drive_id': self.default_drive_id, + 'order_by': 'name ASC', + 'query': f'name = "{self.fileName}"', + } + response = s.post(url, headers=self.headers, json=json_data) + data = response.json() + + try: + if response.status_code == 200: + fileList = data.get("items", []) + if fileList: + print(f'找到签到任务文件id:{fileList[0]["file_id"]}') + print(f'执行覆盖上传') + self.file_id = fileList[0]['file_id'] + return fileList[0]['file_id'] + else: + print(f'未找到签到任务文件') + else: + print("搜索文件API请求失败") + except Exception as e: + print(f"获取签到任务文件ID失败:{e}") + + return '' + + def file_create(self, type,needPreHash=True): + self.filePath = f'./{self.fileName}' + self.size = self.get_file_size(self.filePath) + if self.size == 0: + print('本地未发现签到视频文件,开始远程下载') + if self.download_file(f'{server_base_url}签到任务文件_视频.mp4',self.fileName) and self.download_file(f'{server_base_url}签到任务文件_喜欢可以赞赏一波_谢谢.jpg', self.fileName): + self.size = self.get_file_size(self.filePath) + json_data = { + 'name': self.fileName, + 'type': 'file', + 'parent_file_id': 'root', + 'drive_id': self.drive_id, + 'check_name_mode': 'ignore', + 'size': self.size, + "content_hash_name": "sha1", + } + if needPreHash: + pre_hash = self.get_file_pre_hash(self.filePath,'pre_hash') + json_data['pre_hash']=pre_hash + else: + content_hash = self.get_file_pre_hash(self.filePath,'content_hash') + json_data['content_hash'] = content_hash + json_data['proof_code'] = self._get_proof_code() + json_data['proof_version'] = "v1" + + + + url = "https://api.aliyundrive.com/v2/file/create" + if type == 'alibum': + url = "https://api.aliyundrive.com/adrive/v2/biz/albums/file/create" + json_data['proof_version'] = 'v1' + json_data['proof_code'] = self._get_proof_code() + json_data['content_type'] = 'image/jpeg' + json_data['create_scene'] = 'album_autobackup' + json_data['check_name_mode'] = 'auto_rename' + + if self.file_id == '': + self.file_id = self.get_signTaskFileId() + elif self.file_id != '': + json_data['file_id'] = self.file_id + + response = s.post(url, headers=self.headers, json=json_data) + data = response.json() + + try: + if response.status_code == 201 or response.status_code == 200: + rapid_upload = data.get('rapid_upload', False) + self.file_id = data.get('file_id', '') + print(rapid_upload) + if rapid_upload: + Log(f"文件秒传匹配成功") + else: + part_info_list = data.get('part_info_list', []) + upload_url = part_info_list[0]['upload_url'] + if type != 'alibum': + self.upload_id = data.get('upload_id', '') + if upload_url: + with open(self.filePath, 'rb') as f: + part_content = f.read(self.size) + response = s.put(upload_url, data=part_content) + if response.status_code != 200: + raise Exception(f"文件上传失败") + Log(f"文件上传成功") + self.file_complete() + elif response.status_code == 409: + Log(f"文件秒传匹配成功") + self.file_create('Default',False) + # if rapid_upload: + # Log(f"文件秒传成功") + # return "文件秒传成功" + else: + print(f"上传文件API请求失败{data}") + except Exception as e: + print(f"上传文件失败:{e}") + + return '' + + def file_complete(self): + url = "https://api.aliyundrive.com/v2/file/complete" + json_data = { + 'file_id': self.file_id, + 'upload_id': self.upload_id, + 'drive_id': self.drive_id + } + response = s.post(url, headers=self.headers, json=json_data) + + if response.status_code == 200: + print(f"上传状态上报成功") + # file_delete(file_id, drive_id) + else: + print("上传文件API请求失败") + + def file_delete(self, file_id, drive_id): + url = "https://api.aliyundrive.com/v2/file/delete" + json_data = { + 'file_id': file_id, + 'drive_id': drive_id + } + response = s.post(url, headers=self.headers, json=json_data) + if response.status_code == 204: + # print(data) + print(f"删除文件成功") + else: + print("删除文件API请求失败") + + def _get_proof_code(self) -> str: + """计算proof_code""" + md5_int = int(hashlib.md5(self.access_token.encode()).hexdigest()[:16], 16) + # file_size = os.path.getsize(file_path) + offset = md5_int % self.size if self.size else 0 + if self.filePath.startswith('http'): + # noinspection PyProtectedMember + bys = self._session.get(self.filePath, headers={ + 'Range': f'bytes={offset}-{min(8 + offset, self.size) - 1}' + }).content + else: + with open(self.filePath, 'rb') as file: + file.seek(offset) + bys = file.read(min(8, self.size - offset)) + return base64.b64encode(bys).decode() + + ###############################文件上传任务结束############################### +#接好运瓶 + def bottle_fish(self): + json_data = {} + for i in range(3): + response = s.post('https://api.aliyundrive.com/adrive/v1/bottle/fish', headers=self.headers, + json=json_data, verify=False) + if response.status_code == 200: + Log('接好运瓶成功!') + else: + print(response.text) + +#######################接好运瓶并转存1个文件任务 + + # 接好运瓶获取分享ID + def get_bottleShareId(self): + json_data = {} + response = s.post('https://api.aliyundrive.com/adrive/v1/bottle/fish', headers=self.headers,json=json_data, verify=False) + if response.status_code == 200: + resp = response.json() + self.shareid = resp.get('shareId','') + print(f'获取到好运瓶分享ID:【{self.shareid}】') + self.get_shareFileId() + else: + print(response.text) + + #根据shareid获取分享文件file_id + def get_shareFileId(self): + json_data = {"share_id":self.shareid} + response = s.post('https://api.aliyundrive.com/adrive/v2/share_link/get_share_by_anonymous', headers=self.headers,json=json_data, verify=False) + if response.status_code == 200: + resp = response.json() + file_infos = resp.get('file_infos',[]) + self.share_file_id = file_infos[0]['file_id'] + print(f'获取到文件ID:【{self.share_file_id}】') + self.get_shareToken() + + else: + print(response.text) + + #保存文件 + def get_shareToken(self): + json_data ={"share_id":self.shareid} + response = s.post('https://api.aliyundrive.com/v2/share_link/get_share_token', headers=self.headers,json=json_data, verify=False) + if response.status_code == 200: + resp = response.json() + share_token=resp.get('share_token','') + self.headers['x-share-token'] = share_token + self.save_shareFile() + else: + print(response.text) + #保存文件 + def save_shareFile(self): + json_data ={"requests":[{ + "body":{ + "share_id":self.shareid, + "to_drive_id":self.default_drive_id, + "addition_data":{"umidtoken":""}, + "auto_rename":True,"file_id":self.share_file_id, + "to_parent_file_id":"root"}, + "headers":{"Content-Type":"application/json"}, + "id":"0","method":"POST", + "url":"/file/copy"}], + "resource":"file" + } + response = s.post('https://api.aliyundrive.com/adrive/v2/batch', headers=self.headers,json=json_data, verify=False) + if response.status_code == 200: + res = response.json() + status = res["responses"][0]["status"] + file_id = res["responses"][0]["body"]["file_id"] + if status == 201: + Log('文件保存成功') + self.file_delete(file_id, self.default_drive_id) + else: + print('文件保存失败') + else: + print(response.text) + +#接好运瓶并转存1个文件任务####################### + + #领取版本升级奖励 + def version_reward(self): + json_data = {"code":"newVersion490Reward","rule":"all"} + response = s.post('https://member.aliyundrive.com/v1/users/space_goods_reward?_rx-s=mobile', headers=self.headers, + json=json_data, verify=False) + if response.status_code == 200: + Log('领取版本升级奖励成功!') + else: + print(response.text) + #领取奖励 + def reward_sign(self, type,sign_in_count=None): + if sign_in_count == None:sign_in_count = self.sign_in_count + json_data = {"signInDay": str(sign_in_count)} + if type == 'sign_in_reward': + url = f'https://member.aliyundrive.com/v1/activity/{type}?_rx-s=mobile' + else: + url = f'https://member.aliyundrive.com/v2/activity/{type}?_rx-s=mobile' + response = s.post(url, headers=self.headers, json=json_data, verify=False) + try: + resp = response.json() + if 'result' in resp and resp.get("result",None) != None: + Log(f">{resp['result']['notice']}") + elif 'success' in resp and resp.get("success",None) != None: + Log(f">已领奖") + else: + Log(f">{resp['message']}") + except: + print(response.text) + + # 订阅阿里官方账号 + def follow_user(self): + data = {"user_id": 'ec11691148db442aa7aa374ca707543c'} + response = s.post('https://api.aliyundrive.com/adrive/v1/member/follow_user', headers=self.headers, json=data, + verify=False) + if response.status_code == 200: + Log('订阅成功!') + else: + print(response.text) + + # 获取最近视频列表 + def get_videoList(self): + self.fileName = '签到任务文件_视频.mp4' + res = self.get_signTaskFileId() + if res: + # data = {} + # response = s.post('https://api.aliyundrive.com/adrive/v2/video/list', headers=self.headers, json=data, + # verify=False) + # if response.status_code == 200: + # data = response.json() + # Video_list = data.get("items",False) + # if Video_list: + # Video_list_len = len(Video_list) + # for i in range(Video_list_len): + # Video_info = Video_list[random.randint(0,Video_list_len-1)] + # # print(f'当前Video_info:\n{Video_info}') + # if Video_info.get("type", "") == 'file': + # self.file_id = Video_info['file_id'] + # self.drive_id = Video_info['drive_id'] + # self.videoUpdate() + # duration = Video_info['duration'] + # play_cursor = str(float(Video_info['play_cursor']) + 31) + # print(f'待上传时间:{play_cursor}') + # self.videoUpdate(duration,play_cursor) + # break + self.videoUpdate() + radomNum = round(random.uniform(200.000, 255.000), 3) + self.videoUpdate(radomNum, radomNum) + elif res == '未找到签到任务文件': + print('放映室没有视频文件,尝试转存任务视频,重新获取视频信息') + self.shareid = 't2j7bMBYAS5' + self.get_shareFileId() + # self.upload_files_to_drive(1) + self.videoUpdate() + radomNum = round(random.uniform(200.000, 255.000), 3) + self.videoUpdate(radomNum,radomNum) + + + else: + print(res) + + # 获取最近视频列表 + def videoUpdate(self,duration="0",play_cursor="0"): + data = { + "drive_id": self.default_drive_id, + "duration": duration, + "file_extension": 'mp4', + "file_id": self.file_id, + "play_cursor": play_cursor + } + response = s.post('https://api.aliyundrive.com/adrive/v2/video/update', headers=self.headers, json=data, + verify=False) + if response.status_code == 200: + print('>上传观看时间成功!') + else: + print(response.text) + + #弃用补签卡任务 + def join_team(self): + check_team_data = {} + check_team_res = s.post('https://member.aliyundrive.com/v1/activity/sign_in_team?_rx-s=mobile', + headers=self.headers, json=check_team_data, verify=False) + try: + resp = check_team_res.json() + if resp['result'] != 'null': + act_id = resp['result']['id'] + join_team_data = {"id": act_id, "team": "blue"} + join_team_res = requests.post('https://member.aliyundrive.com/v1/activity/sign_in_team_pk?_rx-s=mobile', + headers=self.headers, json=join_team_data, verify=False) + try: + join_team_res = join_team_res.json() + if join_team_res['success']: + Log('>加入蓝色战队成功!') + except: + print(join_team_res.text) + except: + print(check_team_res.text) + + #补签卡随机翻任务牌3次 + def get_cardTask(self): + for i in range(3): + json_data = {"position":random.randint(1,9)} + response = s.post('https://member.aliyundrive.com/v2/activity/complement_task?_rx-s=mobile', headers=self.headers, + json=json_data, verify=False) + if response.status_code == 200: + Log('翻卡成功') + else: + print(response.text) + + # 获取period + def get_period(self): + print(f'>>>>>开始获取补签卡任务') + json_data = {} + response = s.post('https://member.aliyundrive.com/v2/activity/complement_task_detail?_rx-s=mobile',headers=self.headers,json=json_data, verify=False) + if response.status_code == 200: + resp = response.json() + self.period = resp['result']['period'] + Tasks = resp['result']['tasks'] + # 在这里执行相应的操作 + if len(Tasks) < 3: + self.get_cardTask() + self.get_period() + for task in Tasks: + self.card_taskName = task['taskName'] + self.card_taskId = task['taskId'] + Log(f'>>当前任务:【{self.card_taskName}】') + if task["status"] == "finished" or task["status"] == "verification": + self.reward_cardTask() + # Log('>本周补签卡已领取') + return + if self.card_taskName == '当周使用好运瓶翻3次': + self.bottle_fish() + break + elif self.card_taskName == '当周观看任意一个电影时间满3分钟': + self.get_videoList() + break + elif self.card_taskName == '当周备份照片满20张': + Log(f'>任务:【{self.card_taskName}】暂不支持') + continue + elif self.card_taskName == '当周使用快传发送文件给好友': + Log(f'>任务:【{self.card_taskName}】暂不支持') + continue + else: + Log(f'>任务:【{self.card_taskName}】暂不支持') + continue + self.reward_cardTask() + else: + print(response.text) + + # 获取历史设备ID + def get_listDevice(self): + json_data = {} + response = s.post('https://user.aliyundrive.com/v1/deviceRoom/listDevice',headers=self.headers, json=json_data, verify=False) + if response.status_code == 200 or response.status_code == 400: + resp = response.json() + # 检查响应是否包含'items' + if 'items' in resp: + items = response.json()['items'] + + # 检查'items'列表是否不为空 + if items: + last_item = items[-1] # 获取最后一个元素 + self.x_device_id = last_item['id'] + print("x_device_id :", self.x_device_id ) + return True + + else: + print("items列表为空") + return False + else: + print("响应中没有'items'字段") + return False + else: + print(response.text) + #上传备份设置, + def update_device_extras(self): + # 生成随机的totalSize和useSize(示例范围为256GB到1TB) + total_size = random.randint(256 * 1024 * 1024 * 1024, 1024 * 1024 * 1024 * 1024) # 256GB到1TB + use_size = random.randint(total_size, total_size) # useSize小于或等于totalSize,范围也是256GB到1TB + if self.get_listDevice(): + self.headers['x-device-id'] = self.x_device_id + json_data = { + "albumAccessAuthority": True, + "albumBackupLeftFileTotal": 0, + "albumBackupLeftFileTotalSize": 0, + "albumFile": random.randint(1,20), + "autoBackupStatus": True, + "brand": "xiaomi", + "systemVersion": "Android 11", + "totalSize": total_size, + "umid": "", + "useSize": use_size, + "utdid": "" + } + response = s.post('https://api.aliyundrive.com/users/v1/users/update_device_extras', headers=self.headers,json=json_data, verify=False) + if response.status_code == 200 or response.status_code == 400: + resp = response.json() + if 'success' in resp: + print(f">{resp}") + else: + print(f">{resp['message']}") + else: + print(response.text) + #领取补签卡 + def reward_cardTask(self): + json_data = {"period":self.period,'taskId':self.card_taskId} + response = s.post('https://member.aliyundrive.com/v2/activity/complement_task_reward?_rx-s=mobile', headers=self.headers,json=json_data, verify=False) + if response.status_code == 200 or response.status_code == 400: + resp = response.json() + if 'success' in resp: + print(f">补签卡领取成功") + else: + print(f">{resp['message']}") + else: + print(response.text) + + + #使用补签卡 + def use_signCard(self): + use_signCard_data = {} + use_signCard_res = s.post('https://member.aliyundrive.com/v1/activity/complement_sign_in?_rx-s=mobile', + headers=self.headers, json=use_signCard_data, verify=False) + try: + resp = use_signCard_res.json() + if resp['code'] != 'BadRequest': + Log('>补签成功!') + else: + Log(f">补签失败!原因:{resp['message']}") + except: + print(use_signCard_res.text) + + def main(self, indx): + log_message = f"\n开始执行第【{indx + 1}】个账号--------------->>>>>" + Log(log_message) + current_day = datetime.datetime.now().day + if self.getToken(): + self.get_sign_in_list() + + #新增领取版本奖励 + # self.version_reward() + if self.ali_reward: + Log('>>>>开始领取签到奖励') + self.reward_sign('sign_in_reward') + time.sleep(2) + self.reward_sign('sign_in_task_reward') + else: + if not is_last_day_of_month(): + Log(f'>今天是【{current_day}】日,您设置了不自动领取奖品,不自动领取') + else: + Log('>今日为本月最后一天,默认领取所有奖品') + for day in range(1, current_day + 1): + Log(f'开始领取【第{day}天】奖品') + self.reward_sign('sign_in_reward', day) + self.reward_sign('sign_in_task_reward', day) + time.sleep(1) + self.get_period() + self.use_signCard() + else: + return False +#删除缓存 +def del_cash(file_path): + try: + # 删除文件 + os.remove(file_path) + print(">缓存文件删除成功") + return True + except FileNotFoundError: + print(">缓存文件不存在") + return "缓存文件不存在" + except Exception as e: + print(f">缓存文件删除失败:{e}") + return f"缓存文件删除失败:{e}" + +# 对比缓存与环境变量 token 长度 +def len_comp(cached_tokens, env_token): + global refresh_tokens, LEN + if cached_tokens != '': + cached_tokens = '#'.join(cached_tokens.values()) + cached_token_list = cached_tokens.split("#") + cached_token_len = len(cached_token_list) + else: + cached_token_len = 0 + + env_token_list = env_token.split("&") + env_token_len = len(env_token_list) + + if env_token_len != cached_token_len: + print("***缓存 freshToken 长度与环境变量长度不一致,使用【环境变量】") + del_cash(REFRESHTOEKN_PATH) + refresh_tokens = env_token_list + LEN = env_token_len + else: + print("***缓存 freshToken 长度与环境变量长度一致,使用【缓存】") + refresh_tokens = cached_token_list + LEN = cached_token_len + +def compare_versions(local_version, server_version): + local_parts = local_version.split('.') # 将本地版本号拆分成数字部分 + server_parts = server_version.split('.') # 将服务器版本号拆分成数字部分 + + for l, s in zip(local_parts, server_parts): + if int(l) < int(s): + return True # 当前版本低于服务器版本 + elif int(l) > int(s): + return False # 当前版本高于服务器版本 + + # 如果上述循环没有返回结果,则表示当前版本与服务器版本的数字部分完全相同 + if len(local_parts) < len(server_parts): + return True # 当前版本位数较短,即版本号形如 x.y 比 x.y.z 低 + else: + return False # 当前版本与服务器版本相同或更高 + +def check_update(local_version, server_version_url, server_script_url, script_filename): + """ + 检查版本并更新 + + Args: + local_version (str): 本地版本号 + server_version_url (str): 服务器版本文件地址 + server_script_url (str): 服务器脚本地址 + script_filename (str): 要保存的脚本文件名 + + Returns: + bool: 是否进行了更新操作 + """ + # 获取服务器版本号 + response = requests.get(server_version_url,verify=False) + if response.status_code == 200: + server_version = response.text.strip() # 去除首尾空格 + print(f'当前版本:【{local_version}】') + print(f'服务器版本:【{server_version}】') + + if compare_versions(local_version, server_version): + # 需要更新,下载服务器脚本 + AUTO_UPDATE =os.getenv("ALYP_UPDATE", "True").lower() != "false" + # print(AUTO_UPDATE) + if AUTO_UPDATE: + print(">>>>>>>发现新版本的脚本,默认自动更新,准备更新...") + print(">>>>>>>禁用更新请定义变量export ALYP_UPDATE = 'False'") + response = requests.get(server_script_url,verify=False,timeout=10) + if response.status_code == 200: + with open(script_filename, 'wb') as f: + f.write(response.content) + print(f'{script_filename} 下载完成!') + return True + else: + print(f'下载失败:{response.status_code}') + else: + print(">>>>>>>发现新版本的脚本,您禁用了自动更新,如需启用请删除变量ALYP_UPDATE") + else: + print(f'当前版本高于或等于服务器版本') + else: + print(f'获取服务器版本失败:{response.status_code}') + + return False + +if __name__ == '__main__': + print(''' +✨✨✨ 阿里云盘任务脚本✨✨✨ +✨脚本更新地址:https://pan.ziyuand.cn/%E8%BD%AF%E4%BB%B6%E8%B5%84%E6%BA%90%E7%B1%BB/%E8%84%9A%E6%9C%AC/%E9%98%BF%E9%87%8C%E4%BA%91%E7%9B%98 +✨获取refresh_token: + https://alist.nn.ci/zh/guide/drivers/aliyundrive.html + http://qr.ziyuand.cn/ +✨自动签到 +✨自动补签 +✨自动完成签到任务(部分) +✨自动完成补签卡任务(部分) +✨自动领取任务奖品(如无需自动领取请定义变量:export ali_reward="False",默认每月最后一天自动领取所有任务奖品) +✨支持青龙(变量:export ALYP="xxxx") +✨支持多账号(使用&分割refresh_token) +✨脚本自动更新(禁用更新,变量:ALYP_UPDATE = "False") +✨强制使用变量不使用缓存Token(变量:USE_ENV= "True") +✨✨✨ @Author CHERWIN✨✨✨ + ''') + # 检查更新 + local_version = '2023.11.05' # 本地版本 + server_base_url="http://pan.ziyuand.cn/d/软件资源类/脚本/阿里云盘/" + server_script_url = f"{server_base_url}ALYP.py" + server_version_url = f'{server_base_url}version.txt' # 服务器版本文件地址 + check_update(local_version, server_version_url, server_script_url, 'ALYP.py') + + refresh_tokens = '' + LEN = 0 + ENV = os.environ.get("ALYP") + #强制使用环境变量,首次或增加账号后建议开启,跑一次删除变量,青龙变量 export USE_ENV = True + USE_ENV = os.environ.get("USE_ENV") if environ.get("USE_ENV") else False + if USE_ENV: + print('当前强制使用变量') + del_cash(REFRESHTOEKN_PATH) + refresh_token = ENV if ENV else refresh_tokens + Cach_Tokens = loadRefreshTokens() + if refresh_token: + len_comp(Cach_Tokens, refresh_token) + else: + print("******未填写 ALYP 变量。青龙可在环境变量设置 ALYP 或者在本脚本文件上方将获取到的 refresh_token 填入refresh_token后面的''中") + exit(0) + + #自动领取开关 + ali_reward = environ.get("ali_reward") if environ.get("ali_reward") else True + if ali_reward: + print('******默认自动领取奖品,如需关闭自动领取请定义变量:export ali_reward="False"\n******默认自动补签') + else: + print('******设置了不自动领取奖品') + print(f'******当前使用token:\n{refresh_tokens}') + if LEN > 0: + print(f"\n>>>>>>>>>>共获取到{LEN}个账号<<<<<<<<<<") + for indx, ck in enumerate(refresh_tokens): + s = requests.session() + s.verify = False + # print(ck) + Sign = AliDrive_CheckIn(ck, ali_reward).main(indx) + if not Sign: continue + + + send('阿里云盘签到通知', send_msg) diff --git a/BWCJ.py b/BWCJ.py new file mode 100755 index 0000000..6c1d7a7 --- /dev/null +++ b/BWCJ.py @@ -0,0 +1,286 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# cron "30 1 * * *" script-path=xxx.py,tag=匹配cron用 +# const $ = new Env('霸王茶姬小程序') + +import os +import requests +from requests.packages.urllib3.exceptions import InsecureRequestWarning +# import CHERWIN_TOOLS +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +class RUN: + def __init__(self,info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + self.token = split_info[0] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + self.send_UID = last_info + self.index = index + 1 + Log(f"\n---------开始执行第{self.index}个账号>>>>>") + self.s = requests.session() + self.s.verify = False + + self.headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x6309080f) XWEB/8555', + 'work-wechat-userid': '', + 'multi-store-id': '', + 'gdt-vid': '', + 'qz-gtd': '', + 'scene': '1006', + 'Qm-From': 'wechat', + 'store-id': '49006', + 'Qm-User-Token': self.token, + 'channelCode': '', + 'Qm-From-Type': 'catering', + 'promotion-code': '', + 'work-staff-name': '', + 'work-staff-id': '', + 'Accept': 'v=1.0', + 'Accept-Encoding': 'gzip,compress,br,deflate', + 'Referer': 'https://servicewechat.com/wxafec6f8422cb357b/87/page-frame.html' + } + self.s.headers.update(self.headers) + self.appid = 'wxafec6f8422cb357b' + self.activity_id='947079313798000641' + + def personal_info(self): + personal_info_valid = False + + try: + # 请求的参数 + params = {'appid': self.appid} + + # 发送GET请求 + response = self.s.get('https://webapi.qmai.cn/web/catering/crm/personal-info', json=params) + result = response.json() + + # 检查请求是否成功 + if result.get('code','-1') == '0': + personal_info_valid = True + # 提取个人信息 + mobile_phone = result['data']['mobilePhone'] if 'data' in result and 'mobilePhone' in result[ + 'data'] else None + self.mobile_phone = mobile_phone[:3] + "*" * 4 + mobile_phone[7:] + self.name = result['data']['name'] if 'data' in result and 'name' in result['data'] else None + + Log(f"账号[{self.index}]登陆成功!\n用户名:【{self.name}】 \n手机号:【{self.mobile_phone}】") + else: + # 如果请求不成功,则打印错误信息 + message = result.get('message', '') + Log(f'登录失败: {message}') + + except Exception as e: + # 捕获任何异常并打印 + print(e) + + finally: + # 最终返回请求是否成功的标志 + return personal_info_valid + + def user_sign_statistics(self): + try: + + json_data = { + 'activityId': self.activity_id, + 'appid': self.appid + } + + # Send the POST request + response = self.s.post('https://webapi.qmai.cn/web/cmk-center/sign/userSignStatistics', json=json_data) + result = response.json() + status_code = response.status_code + + # Check if the request was successful + if result.get('code', status_code) == 0: + data = result.get('data', {}) + sign_days = data.get('signDays', '') + sign_status = data.get('signStatus', 0) == 1 + Log(f'新版签到今天{"已" if sign_status else "未"}签到, 已连续签到{sign_days}天') + if not sign_status: + self.take_part_in_sign() + return sign_status, sign_days + else: + message = result.get('message', '') + Log(f'查询新版签到失败: {message}') + return False, 0 + except Exception as e: + print(e) + return False, 0 + + def take_part_in_sign(self): + try: + json_data = { + 'activityId': self.activity_id, + 'appid': self.appid + } + response = self.s.post('https://webapi.qmai.cn/web/cmk-center/sign/takePartInSign', json=json_data) + result = response.json() + status_code = response.status_code + + if result.get('code', status_code) == 0: + data = result.get('data',{}) + rewardDetailList = data.get('rewardDetailList',[{}]) + if rewardDetailList: + rewardName = rewardDetailList[0].get('rewardName','') + sendNum = rewardDetailList[0].get('sendNum','') + Log(f'新版签到成功,获得【{sendNum}】{rewardName}') + return True + else: + Log(f'签到失败:【{result.get("message","")}】') + return True + else: + message = result.get('message', '') + Log(f'新版签到失败: {message}') + return False + except Exception as e: + print(e) + return False + + def points_info(self): + try: + json_data = { + 'appid': self.appid + } + + response = self.s.post('https://webapi.qmai.cn/web/catering/crm/points-info', json=json_data) + result = response.json() + status_code = response.status_code + + if result.get('code', status_code) == '0': + data = result.get('data', {}) + soon_expired_points = data.get('soonExpiredPoints', 0) + total_points = data.get('totalPoints', 0) + expired_time = data.get('expiredTime', '') + + if soon_expired_points: + Log(f'有【{soon_expired_points}】积分将于( {expired_time})过期') + + Log(f'当前积分: 【{total_points}】') + return total_points, soon_expired_points, expired_time + else: + message = result.get('message', '') + Log(f'查询积分失败: {message}') + return None + except Exception as e: + print(e) + return False + + def main(self): + if not self.personal_info() : + Log("用户信息无效,请更新CK") + return False + self.user_sign_statistics() + self.points_info() + self.sendMsg() + return True + + def sendMsg(self, help=False): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME, help) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + + +if __name__ == '__main__': + APP_NAME = '霸王茶姬小程序' + ENV_NAME = 'BWCJ' + CK_NAME = 'qm-user-token' + print(f''' +✨✨✨ {APP_NAME}签到✨✨✨ +✨ 功能: + 积分签到 +✨ 抓包步骤: + 打开{APP_NAME} + 授权登陆 + 打开抓包工具 + 找请求头带{CK_NAME}的URl + 复制里面的{CK_NAME}参数值 +✨ ✨✨wxpusher一对一推送功能, + ✨需要定义变量export WXPUSHER=wxpusher的app_token,不设置则不启用wxpusher一对一推送 + ✨需要在{ENV_NAME}变量最后添加@wxpusher的UID +参数示例:Fks8FqmiTksnmZSj2fDvxxxxxxxxx@UID_xxxxx +✨ 设置青龙变量: +export {ENV_NAME}='{CK_NAME}参数值'多账号#或&分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ ✨ 注意:抓完CK没事儿别打开小程序,重新打开小程序请重新抓包 +✨ 推荐cron:5 8 * * * +✨✨✨ @Author CHERWIN✨✨✨ +''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + for index, infos in enumerate(tokens): + run_result = RUN(infos, index).main() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) \ No newline at end of file diff --git a/CHERWIN_TOOLS.py b/CHERWIN_TOOLS.py new file mode 100755 index 0000000..2eb5a70 --- /dev/null +++ b/CHERWIN_TOOLS.py @@ -0,0 +1,495 @@ +import json +import os +import importlib.util +import subprocess +import sys +import requests +from http import HTTPStatus + +NOW_TOOLS_VERSION = '2024.04.06' +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +# 尝试导入包 +def import_or_install(package_name, import_name=None): + # 如果传入了 import_name,则使用它来检查模块,否则默认与包名相同 + import_name = import_name or package_name + + try: + # 检查模块是否已安装 + package_spec = importlib.util.find_spec(import_name) + + if package_spec is None: + print(f"{package_name} 模块未安装. 开始安装...") + subprocess.check_call([sys.executable, '-m', 'pip', 'install', package_name]) + print(f"{package_name} 模块安装完成。") + else: + print(f"{package_name} 模块已安装。") + + # 尝试导入模块检查是否安装成功 + __import__(import_name) + module = importlib.import_module(import_name) + print(f"{import_name} 模块导入成功.") + return module + except ImportError as e: + print(f"无法导入 {import_name} 模块. 错误信息: {e}") + except subprocess.CalledProcessError as e: + print(f"安装 {package_name} 模块时出错. 错误信息: {e}") + except Exception as e: + print(f"处理 {package_name} 模块时发生错误. 错误信息: {e}") + +def SAVE_INVITE_CODE(file_name, new_data): + # 读取现有JSON文件(如果存在) + try: + with open(file_name, 'r', encoding='utf-8') as file: + data = json.load(file) + except FileNotFoundError: + # 如果文件不存在,创建所需目录并一个新的空JSON文件 + directory = os.path.dirname(file_name) + if not os.path.exists(directory): + os.makedirs(directory) + data = {} + + # 检查是否已存在相同的键,如果存在,合并数据 + for key, value in new_data.items(): + if key in data: + # 如果键已存在,将新数据合并到现有数据中 + data[key].update(value) + else: + # 如果键不存在,直接插入新数据 + data[key] = value + + # 将更新后的数据写入JSON文件 + with open(file_name, 'w', encoding='utf-8') as file: + json.dump(data, file, indent=4) + +# 将参数转换为字典 +def create_dict_from_string(self, data_string): + params = {} + key_value_pairs = data_string.split(',') + for pair in key_value_pairs: + key, value = pair.split('=') + params[key] = value + return params + +def compare_versions(local_version, server_version): + local_parts = local_version.split('.') # 将本地版本号拆分成数字部分 + server_parts = server_version.split('.') # 将服务器版本号拆分成数字部分 + + for l, s in zip(local_parts, server_parts): + if int(l) < int(s): + return True # 当前版本低于服务器版本 + elif int(l) > int(s): + return False # 当前版本高于服务器版本 + + # 如果上述循环没有返回结果,则表示当前版本与服务器版本的数字部分完全相同 + if len(local_parts) < len(server_parts): + return True # 当前版本位数较短,即版本号形如 x.y 比 x.y.z 低 + else: + return False # 当前版本与服务器版本相同或更高 + +def CHECK_UPDATE(local_version, server_version_url, server_script_url, script_filename): + """ + 检查版本并更新 + + Args: + local_version (str): 本地版本号 + server_version_url (str): 服务器版本文件地址 + server_script_url (str): 服务器脚本地址 + script_filename (str): 要保存的脚本文件名 + + Returns: + bool: 是否进行了更新操作 + """ + try: + # 获取服务器版本号 + response = requests.get(server_version_url, verify=False) + response.raise_for_status() # Raises an HTTPError for bad responses + # print(response.text) + server_version = response.text.strip() # 去除首尾空格 + print(f'当前版本:【{local_version}】') + print(f'服务器版本:【{server_version}】') + + if compare_versions(local_version, server_version): + # 需要更新,下载服务器脚本 + AUTO_UPDATE = os.getenv("SCRIPT_UPDATE", "True").lower() != "false" + # print(AUTO_UPDATE) + if AUTO_UPDATE: + print(">>>>>>>发现新版本的脚本,默认自动更新,准备更新...") + print(">>>>>>>禁用更新请定义变量export SCRIPT_UPDATE = 'False'") + response_script = requests.get(server_script_url, verify=False, timeout=10) + response_script.raise_for_status() + + with open(script_filename, 'wb') as f: + f.write(response_script.content) + print(f'{script_filename} 下载完成!') + print(f'尝试运行新脚本') + import subprocess, sys + # 使用 sys.executable 获取 Python 可执行文件的完整路径 + python_executable = sys.executable + subprocess.Popen([python_executable, script_filename]) + + else: + print(">>>>>>>发现新版本的脚本,您禁用了自动更新,如需启用请删除变量SCRIPT_UPDATE") + else: + print(f'当前版本高于或等于服务器版本') + + except requests.exceptions.RequestException as e: + print(f'发生网络错误:{e}') + + except Exception as e: + print(f'发生未知错误:{e}') + + return False # 返回 False 表示没有进行更新操作 + +def CHECK_UPDATE_NEW(local_version, server_version, server_script_url, script_filename,server_version_url=None): + """ + 检查版本并更新 + + Args: + local_version (str): 本地版本号 + server_version_url (str): 服务器版本文件地址 + server_script_url (str): 服务器脚本地址 + script_filename (str): 要保存的脚本文件名 + + Returns: + bool: 是否进行了更新操作 + """ + print(f'当前检测:【{script_filename}】') + try: + if server_version_url: + # 获取服务器版本号 + response = requests.get(server_version_url, verify=False) + response.raise_for_status() # Raises an HTTPError for bad responses + # print(response.text) + server_version = response.text.strip() # 去除首尾空格 + if "code" in server_version: + print('【获取远程版本号失败,设为本地同版本】') + server_version = local_version + if not server_version :server_version = NOW_TOOLS_VERSION + print(f'本地版本:【{local_version}】') + print(f'服务器版本:【{server_version}】') + + if compare_versions(local_version, server_version): + # 需要更新,下载服务器脚本 + AUTO_UPDATE = os.getenv("SCRIPT_UPDATE", "True").lower() != "false" + # print(AUTO_UPDATE) + if AUTO_UPDATE: + print(">>>>>>>发现新版本的脚本,默认自动更新,准备更新...") + print(">>>>>>>禁用更新请定义变量export SCRIPT_UPDATE = 'False'") + if down_file(script_filename,server_script_url): + print(f'请重新运行新脚本\n') + return True + else: + print(">>>>>>>发现新版本的脚本,您禁用了自动更新,如需启用请删除变量SCRIPT_UPDATE\n") + else: + print(f'无需更新\n') + return False + + except requests.exceptions.RequestException as e: + print(f'发生网络错误:{e}') + + except Exception as e: + print(f'发生未知错误:{e}') + + return False # 返回 False 表示没有进行更新操作 + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False +def get_AuthorInviteCode(url): + global AuthorCode + try: + response = requests.get(url, verify=False, timeout=10) + if response.status_code == 200: + content = json.loads(response.text) + AuthorCode = list(content.values()) + # print(f'获取到作者邀请码:{AuthorCode}') + return AuthorCode + else: + # print("无法获取文件。状态代码:", response.status_code) + return {} + + except Exception as e: + print(f"An error occurred: {e}") + return {} + + +def GET_TIPS(server_base_url): + url = f'{server_base_url}tips.txt' + try: + response = requests.get(url, verify=False) + # 检查响应的编码 + encoding = response.encoding + # print(f"编码: {encoding}") + # 设置正确的编码(根据实际情况可能需要调整) + response.encoding = 'utf-8' + # 读取内容 + content = response.text + if 'code' in content: + content = None + except: + content = None + print('获取通知内容失败') + if content: + return (f''' +***********通知内容************\n +{content} +***********通知内容************\n +''') + else: + return (f''' +***********通知内容************\n + @Author Cherwin +***********通知内容************\n +''') + +def CHECK_PARAMENTERS(index, input_string,required_parameters): + # required_parameters = ['deviceid', 'jysessionid', 'shopid', 'memberid', 'access_token', 'sign'] + + # 记录缺少的参数 + missing_parameters = [] + + # 将输入字符串和参数列表中的所有字符都转换为小写 + input_string_lower = input_string.lower() + required_parameters_lower = [param.lower() for param in required_parameters] + + # 判断字符串中是否包含所有必需的参数 + for param in required_parameters_lower: + if param not in input_string_lower: + missing_parameters.append(param) + + if missing_parameters: + print(f"\n第【{index + 1}】个账号,缺少以下参数:【{missing_parameters}】") + return False + else: + print(f"\n第【{index + 1}】个账号,URL包含所有必需的参数,开始执行脚本") + return True + + +def QIANWEN(tongyiSysPromt, content, api_key): + print('开始调用通义千问') + # 检查dashscope库是否已安装 + dashscope = import_or_install('dashscope') + if dashscope: + dashscope.api_key = api_key + response = dashscope.Generation.call( + model='qwen-max', + messages=[ + {"role": "system", + "content": tongyiSysPromt}, + {"role": "user", "content": content}], + seed=1234, + top_p=0.8, + result_format='message', + enable_search=False, + max_tokens=1500, + temperature=1.0, + repetition_penalty=1.0, + ) + if response.status_code == HTTPStatus.OK: + # print(response) + video_info = response.output['choices'][0]['message']['content'] + print('通义生成【成功】!') + return video_info + else: + print(f"无法解析通义返回的信息:{response}") + return None + else: + print('dashscope 模块无法导入,函数无法执行。') + +# 取环境变量,并分割 +def ENV_SPLIT(input_str): + parts = [] + if '&' in input_str: + amp_parts = input_str.split('&') + for part in amp_parts: + if '#' in part: + hash_parts = part.split('#') + for hash_part in hash_parts: + parts.append(hash_part) + else: + parts.append(part) + # print(parts) + return(parts) + + elif '#' in input_str: + hash_parts = input_str.split('#') + # print(hash_parts) + return(hash_parts) + else: + out_str = str(input_str) + # print([out_str]) + return([out_str]) + +# 使用导入的模块进行验证码识别 +def CAPCODE(captcha_slider, captcha_bg): + ddddocr = import_or_install('ddddocr') + if ddddocr: + slide = ddddocr.DdddOcr(det=False, ocr=False) + with open(captcha_slider, 'rb') as f: + target_bytes = f.read() + with open(captcha_bg, 'rb') as f: + background_bytes = f.read() + res = slide.slide_match(target_bytes, background_bytes, simple_target=True) + # print(res['target'][0]) + # print(type(res['target'][0])) + return res['target'][0] + else: + print('ddddocr 模块无法导入,函数无法执行。') + return False +# +# def OCR_API(target_b64str,bg_b64str): +# import base64 +# host = 'http://192.168.10.160' +# jsonstr = json.dumps({'target_img': target_b64str, 'bg_img': bg_b64str}) +# api_url = f"{host}/slide/match/b64/json" +# resp = requests.post(api_url, data=base64.b64encode(jsonstr.encode()).decode()) +# print(f"{api_url=}, {resp.text=}") +# return resp.json().get('target_y',0) +# +# +# def BASE64_TO_IMG(base64_string, output_path): +# import base64 +# import io +# Image = import_or_install('Pillow', 'PIL.Image') +# +# if Image: +# try: +# # 解码base64字符串 +# image_data = base64.b64decode(base64_string) +# # 将字节数据转换为字节流 +# image_buf = Image.open(io.BytesIO(image_data)) +# # 转换为RGB模式 +# image_buf = image_buf.convert('RGB') +# # 保存图片到指定路径 +# image_buf.save(output_path, format='JPEG') +# return True +# except Exception as e: +# print(f'发生错误:{e}') +# return False +# else: +# print('需要的模块[PIL]无法导入,函数无法执行。') +# return False + +def send_wxpusher(UID, one_msg, APP_NAME, help=False): + WXPUSHER = os.environ.get('WXPUSHER', False) + if WXPUSHER: + if help: + push_res = wxpusher(WXPUSHER, APP_NAME + '互助', one_msg, UID, TIPS_HTML) + else: + push_res = wxpusher(WXPUSHER, APP_NAME, one_msg, UID, TIPS_HTML) + print(push_res) + + +def wxpusher(UID,msg,title,help=False): + """利用 wxpusher 的 web api 发送 json 数据包,实现微信信息的发送""" + WXPUSHER = os.environ.get('WXPUSHER', False) + if WXPUSHER: + if help:title = title+'互助' + print('\n------开始wxpusher推送------') + print(f'标题:【{title}】\n内容:{msg}') + webapi = 'http://wxpusher.zjiecode.com/api/send/message' + msg = msg.replace("\n", "
") + tips = TIPS_HTML.replace("\n", "
") + data = { + "appToken": WXPUSHER, + "content": f'{title}
{msg}
{tips}', + # "summary": msg[:99], # 该参数可选,默认为 msg 的前10个字符 + "summary":title, + "contentType": 2, + "uids": [UID], + "url": "https://gj.cherwin.cn" + } + + try: + result = requests.post(url=webapi, json=data) + result.raise_for_status() # 对于非2xx状态码,抛出异常 + response_json = result.json() + if response_json["success"]: + return "------消息发送成功------\n" + else: + return f"消息发送失败。错误信息:{response_json['msg']}" + except requests.exceptions.RequestException as e: + return f"发送消息时发生错误:{str(e)}" + except Exception as e: + return f"发生意外错误:{str(e)}" + +def RESTART_SCRIPT(RESTART_SCRIPT_NAME): + python = sys.executable + os.execl(python, RESTART_SCRIPT_NAME, *sys.argv[1:]) + +def CHECK(): + global CHERWIN_SCRIPT_CONFIG + print('>>>>>>>开始获取版本信息...') + baseurl = 'https://py.cherwin.cn/' + TOOLS_NAME = 'CHERWIN_TOOLS.py' + server_script_url = f'{baseurl}{TOOLS_NAME}' + try: + response = requests.get(f'{baseurl}CHERWIN_SCRIPT_CONFIG.json', verify=False) + response.encoding = 'utf-8' + # 读取内容 + CHERWIN_SCRIPT_CONFIG = response.json() + if 'code' in CHERWIN_SCRIPT_CONFIG: + CHERWIN_SCRIPT_CONFIG = None + server_version = CHERWIN_SCRIPT_CONFIG.get('TOOLS_VERSION', NOW_TOOLS_VERSION) + if CHECK_UPDATE_NEW(NOW_TOOLS_VERSION, server_version, server_script_url, TOOLS_NAME): + print('更新脚本完成') + # print(f'重新检测[{TOOLS_NAME}]版本') + return False + else: + return True + except: + print('获取CHERWIN_SCRIPT_CONFIG.json失败') + return False + + + +def main(APP_NAME,local_script_name,ENV_NAME,local_version): + global APP_INFO,TIPS,TIPS_HTML + server_base_url = f"https://py.cherwin.cn/{APP_NAME}/" + server_script_url = f"{server_base_url}{local_script_name}" + if CHECK(): + APP_INFO = CHERWIN_SCRIPT_CONFIG.get("APP_CONFIG", {}).get(ENV_NAME, {}) + # print(APP_INFO) + server_version = APP_INFO.get('NEW_VERSION', '') + if CHECK_UPDATE_NEW(local_version, server_version, server_script_url, local_script_name): + print('更新成功,请重新运行脚本!') + + if not APP_INFO.get('ENABLE', False): + print('当前脚本未开放') + exit() + TIPS = APP_INFO.get('NTC', '') if APP_INFO.get('NTC', '') else CHERWIN_SCRIPT_CONFIG.get('GLOBAL_NTC', '') + + TIPS_HTML = APP_INFO.get('NTC', '') if APP_INFO.get('NTC', '') else CHERWIN_SCRIPT_CONFIG.get('GLOBAL_NTC_HTML','') + ENV = os.environ.get(ENV_NAME) + AuthorCode = get_AuthorInviteCode(f'https://yhsh.ziyuand.cn/{ENV_NAME}_INVITE_CODE.json') + + return ENV,APP_INFO,TIPS,TIPS_HTML,AuthorCode + else: + exit() + + +if __name__ == '__main__': + pass diff --git a/DBKD.py b/DBKD.py new file mode 100755 index 0000000..aa82359 --- /dev/null +++ b/DBKD.py @@ -0,0 +1,425 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# ✨✨✨ @Author CHERWIN✨✨✨ +# ------------------------------- +# cron "0 6 * * *" script-path=xxx.py,tag=匹配cron用 +# const $ = new Env('中通快递小程序签到') + +import os +import requests +from requests.packages.urllib3.exceptions import InsecureRequestWarning + +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) + + +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +class RUN: + def __init__(self,info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + token = split_info[0] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + print('检测到设置了UID') + print(last_info) + self.send_UID = last_info + self.index = index + 1 + self.s = requests.session() + self.s.verify = False + + self.token = token + self.headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x6309080f) XWEB/9079', + 'Referer': 'https://servicewechat.com/wxa1ebeeb0ed47f0b2/633/page-frame.html' + } + self.baseUrl = 'https://api.ztomember.com/api/' + + + def do_request(self, method, url, params=None, data=None, headers=None): + if not headers: + headers = self.headers + try: + response = self.s.request(method, url, params=params, json=data, headers=headers) + response.raise_for_status() + return response.json() + except Exception as e: + print(f"请求错误: {e}") + return None + + def login(self): + try: + data= { + "code": self.token, + "loginType": "AUTH_CODE_SESSION_KEY_WECHAT_MINI", + "sysCode": "WECHAT_MINI" + } + response = self.do_request('POST', 'https://www.deppon.com/ndcc-gwapi/userService/eco/user/login',data=data) + if response and response.get('status') == 'success': + mobile = response['result']['mobile'] + self.mobile = mobile[:3] + "*" * 4 + mobile[7:] + Log(f'\n手机号:【{self.mobile}】') + return self.generate_tmp_token() + else: + Log(f"查询账户失败: {response.get('message')}") + return False + except Exception as e: + print(f"查询账户异常: {e}") + return False + + def generate_tmp_token(self): + try: + response = self.do_request('GET', 'https://www.deppon.com/ndcc-gwapi/userService/eco/user/token/secure/generateTmpToken') + if response and response.get('status') == 'success': + print(f'临时Token获取成功!') + return self.login_verify(response['result']) + else: + print(f"获取临时token失败: {response}") + return False + except Exception as e: + print(f"获取临时token异常: {e}") + return False + + def login_verify(self, code): + try: + data = {'code': code, 'flag': True} + self.headers['Content-Type'] = 'application/json' + response = self.do_request('POST', 'https://mas.deppon.com/crm-api/login/verify', data=data) + if response and response.get('code') == 200: + # print(response) + Log(f"登录验证成功!") + self.phone = response['data']['mobile'] + self.token = response['data']['token'] + self.headers['mobile'] = self.phone + self.headers['token'] = self.token + # + # print(f"PHONE:【{self.phone}】") + # print(f"TOKEN:【{self.token}】") + return True + else: + Log(f"登录验证失败: {response}") + return False + except Exception as e: + print(f"登录验证异常: {e}") + return False + + def getSvipNewestInfo(self,end="执行前"): + print('\n获取用户最新信息------>>>') + try: + # data ={"phone":self.phone} + response = self.do_request('GET', 'https://www.deppon.com/ndcc-gwapi/memberService/eco/member/grade/secure/getSvipNewestInfo') + if response and response.get('status') == "success": + data = response.get('result', {}) + points = data.get('points', 0) + Log(f'{end}积分:【{points}】') + else: + Log(f"获取用户最新信息失败: {response}") + return None + except Exception as e: + print(f"获取用户最新信息异常: {e}") + return None + + + def signIn_info(self): + print('获取签到信息------>>>') + try: + data = {"phone": self.phone} + response = self.do_request('POST', 'https://mas.deppon.com/crm-api/deppon/signIn/info',data = data) + if response and response.get('code') == 200: + data = response.get('data', {}) + is_sign_in = data.get('isSignIn') + sign_in_day = data.get('signInDay') + record_dtos = data.get('recordDTOS') + if not is_sign_in and record_dtos and record_dtos[0]: + self.remark = record_dtos[0].get('remark','') + self.name = record_dtos[0].get('name','') + self.taskRuleId = record_dtos[0].get('taskRuleId','') + self.signIn() + else: + Log(f'[领券签到]今天已签到, 已签到{sign_in_day}天') + return response['data'] + else: + print(f"获取签到信息失败: {response}") + return None + except Exception as e: + print(f"获取签到信息异常: {e}") + return None + + def signIn(self): + print('执行签到------>>>') + try: + data = {"phone": self.phone,'taskRuleId':self.taskRuleId} + response = self.do_request('POST', 'https://mas.deppon.com/crm-api/deppon/signIn',data=data) + if response and response.get('code') == 200: + data = response.get('data', []) + remarks = [] + for item in data: + if item.get('remark'): + remarks.append(item['remark']) + remarks_str = ', '.join(remarks) if remarks else '' + Log('签到成功: ' + remarks_str) + else: + print(f"签到失败: {response}") + except Exception as e: + print(f"签到异常: {e}") + return None + + def points_signIn_info(self): + print('获取积分签到信息------>>>') + try: + data = {"phone": self.phone} + response = self.do_request('POST', 'https://mas.deppon.com/crm-api/deppon/points/task/signIn/info',data = data) + if response and response.get('code') == 200: + data = response.get('data', {}) + is_sign_in = data.get('isSignIn') + sign_in_day = data.get('signInDay') + sign_in_day_info = data.get('signInDayInfo') + record_DTOS = data.get('recordDTOS', []) + if is_sign_in: + for record in record_DTOS: + note = sign_in_day_info + self.name = record.get('name', '') + self.taskRuleId = record.get('taskRuleId', '') + self.task_receive(note) + else: + Log(f'[积分签到]今天已签到, 已签到{sign_in_day}天') + else: + print(f"获取积分签到信息失败: {response}") + return None + except Exception as e: + print(f"获取积分签到信息异常: {e}") + return None + + def task_list(self): + print('获取任务列表------>>>') + try: + data = {"phone": self.phone} + response = self.do_request('POST', 'https://mas.deppon.com/crm-api/deppon/points/task/list',data = data) + if response and response.get('code') == 200: + data = response.get('data',{}) + taskList = data.get('taskList',[{}]) + for task in taskList: + self.taskRuleId = task.get('taskRuleId',0) + self.remark = task.get('remark','') + self.name = task.get('name','') + print(f'\n当前任务:【{self.name}】 taskRuleId:【{self.taskRuleId}】') + rightsClaimStatus = task.get('rightsClaimStatus',0) + if rightsClaimStatus == 0: + if self.taskRuleId in [8, 9, 11]: + print('任务不支持,跳过') + break + self.changeStatus() + elif rightsClaimStatus == 1: + self.task_receive() + else: + print('任务已完成!') + return response['data'] + else: + print(f"获取任务列表失败: {response}") + return None + except Exception as e: + print(f"获取任务列表异常: {e}") + return None + + def changeStatus(self): + print('完成任务------>>>') + try: + data ={ + "phone":self.phone, + "rightsClaimStatus":1, + "taskRuleId":self.taskRuleId + } + response = self.do_request('POST', 'https://mas.deppon.com/crm-api/deppon/pay/member/add/package/query',data = data) + if response and response.get('code') == 200: + Log(f'完成任务:【{self.name}】成功!') + return response['msg'] + else: + print(f"完成任务【{self.name}】失败: {response}") + return None + except Exception as e: + print(f"获取SVIP最新信息异常: {e}") + return None + + def task_receive(self,note=None): + print('领取奖励------>>>') + try: + data = {"phone": self.phone, "taskRuleId": self.taskRuleId,"ruleId":self.taskRuleId,"note":note} + response = self.do_request('POST', 'https://mas.deppon.com/crm-api/deppon/points/task/receive',data = data) + if response and response.get('code') == 200: + Log(f'领取:【{self.name}】任务奖励成功!') + return response['msg'] + else: + print(f"领取【{self.name}】任务奖励失败: {response}") + return None + except Exception as e: + print(f"领取任务奖励异常: {e}") + return None + + def lottery(self): + try: + data = {"phone": self.phone,"gameId":'Zv8i7IsOPZIQrvvupKXE1w=='} + response = self.do_request('POST', 'https://mas.deppon.com/crm-api/game/draw/lottery',data = data) + + if response and response.get('code') == 200: + print('抽奖成功') + print(response) + self.pointsAvailableValue -= 1 + return response['msg'] + else: + print(f"抽奖失败: {response}") + return None + except Exception as e: + print(f"获取任务列表异常: {e}") + return None + + def lottery_query2(self): + print('查询抽奖次数') + try: + data = {"phone": self.phone} + response = self.do_request('POST', 'https://mas.deppon.com/crm-api/points/balance/query2',data = data) + + if response and response.get('code') == 200: + # print(response) + data = {} if response.get('data', {})==None else response.get('data', {}) + self.pointsAvailableValue = data.get('pointsAvailableValue', 0) + print(f'可以抽奖【{self.pointsAvailableValue}】次') + while self.pointsAvailableValue >0: + self.lottery() + self.pointsAvailableValue -= 1 + + return response['msg'] + else: + print(f"查询抽奖失败: {response}") + return None + except Exception as e: + print(f"查询抽奖次数异常: {e}") + return None + + + + def main(self): + Log(f"\n开始执行第{self.index}个账号--------------->>>>>") + if self.login(): + self.getSvipNewestInfo() + self.signIn_info() + self.points_signIn_info() + self.task_list() + self.lottery_query2() + self.getSvipNewestInfo('执行后') + self.sendMsg() + return True + else: + return False + + def sendMsg(self): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME) + print(push_res) + return True + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + + +def import_Tools(): + global CHERWIN_TOOLS, ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME, + local_version) + + +if __name__ == '__main__': + APP_NAME = '德邦快递小程序' + ENV_NAME = 'DBKD' + CK_NAME = 'code' + CK_URL = 'https://www.deppon.com/ndcc-gwapi/userService/eco/user/login' + print(f''' +✨✨✨ {APP_NAME}签到✨✨✨ +✨ 功能: + 积分签到 +✨ 抓包步骤: + 打开{APP_NAME} + 授权登陆 + 打开抓包工具 + 找{CK_URL}请求body里面的[{CK_NAME}] + 复制里面的[{CK_NAME}]参数值 +参数示例:0f1bjLFa1ZdedHxxxxxxxx +✨ ✨✨wxpusher一对一推送功能, + ✨需要定义变量export WXPUSHER=wxpusher的app_token,不设置则不启用wxpusher一对一推送 + ✨需要在{ENV_NAME}变量最后添加@wxpusher的UID +✨ 设置青龙变量: +export {ENV_NAME}='{CK_NAME}参数值'多账号#或&分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ ✨ 注意:抓完CK没事儿别打开小程序,重新打开小程序请重新抓包 +✨ 推荐cron:0 6 * * * +✨✨✨ @Author CHERWIN✨✨✨ +''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + access_token = [] + for index, infos in enumerate(tokens): + run_result = RUN(infos, index).main() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) \ No newline at end of file diff --git a/HDL.py b/HDL.py new file mode 100755 index 0000000..c0de4f5 --- /dev/null +++ b/HDL.py @@ -0,0 +1,331 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# ✨ 推荐cron:0 6 * * * +# ✨✨✨ @Author CHERWIN✨✨✨ +# ------------------------------- +# cron "0 6 * * *" script-path=xxx.py,tag=匹配cron用 +# const $ = new Env('中通快递小程序签到') + +import os +from os import path +import requests +import hashlib +from requests.packages.urllib3.exceptions import InsecureRequestWarning +# import CHERWIN_TOOLS +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) + +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +class RUN: + def __init__(self,info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + self.openId = split_info[0] + self.uid = split_info[1] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + print('检测到设置了UID') + print(last_info) + self.send_UID = last_info + self.index = index + 1 + self.s = requests.session() + self.s.verify = False + + self.UA = 'Mozilla/5.0 (Linux; Android 14; Mi14 Pro Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/116.0.0.0 Mobile Safari/537.36 XWEB/1160065 MMWEBSDK/20230701 MMWEBID/8701 MicroMessenger/8.0.40.2420(0x28002858) WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 miniProgram/wx1ddeb67115f30d1a' + self.headers = { + 'Host': 'superapp-public.kiwa-tech.com', + 'User-Agent': self.UA , + "_haidilao_app_token": "", + "content-type": "application/json", + "xweb_xhr": "1", + "appid": "15", + "appversion": "3.67.0", + "accept": "*/*", + "sec-fetch-site": "cross-site", + "sec-fetch-mode": "cors", + "sec-fetch-dest": "empty", + "referer": "https://servicewechat.com/wx1ddeb67115f30d1a/121/page-frame.html", + "accept-language": "zh-CN,zh;q=0.9" + } + def do_request(self, url , method='POST', params=None, data=None, headers=None): + if not headers: + headers = self.headers + try: + response = self.s.request(method, url, params=params, json=data, headers=headers) + response.raise_for_status() + return response.json() + except Exception as e: + print(f"请求错误: {e}") + return None + + def wechatLogin(self): + print('>>>>>>登陆获取token') + try: + data = { + "type": 1, + "country": "CN", + "codeType": 1, + "business": "登录", + "terminal": "会员小程序", + "openId": self.openId, + "uid": self.uid + } + response = self.do_request( 'https://superapp-public.kiwa-tech.com/api/gateway/login/center/login/wechatLogin',data =data) + if response and response.get('success') == True: + data = response.get('data',{}) + id = data.get('id','') + token = data.get('token','') + self.haidilao_app_token=token + self.headers['_haidilao_app_token'] = token + Log(f'ID:【{id}】') + return True + else: + print(f"登陆获取token失败: {response}") + return False + except Exception as e: + print(f"登陆获取token异常: {e}") + return False + + + def queryMemberCacheInfo(self): + Log('>>>>>>获取用户信息') + try: + data = {"type":1} + response = self.do_request( 'https://superapp-public.kiwa-tech.com/activity/wxapp/applet/queryMemberCacheInfo',data =data) + if response and response.get('success') == True: + data = response.get('data',{}) + customerName = data.get('customerName','') + mobile = data.get('mobile','') + mobile = mobile[:3] + "*" * 4 + mobile[7:] + coinNum = data.get('coinNum','') + + Log(f'用户名:【{customerName}】\n手机号:【{mobile}】\n捞币:【{coinNum}】') + return True + else: + print(f"登陆获取token失败: {response}") + return False + except Exception as e: + print(f"登陆获取token异常: {e}") + return False + + + def daily_sign_getAct(self): + Log('>>>>>>获取签到信息') + try: + data = {"source":1} + response = self.do_request( 'https://superapp-public.kiwa-tech.com/activity/daily/sign/getAct',data =data) + if response and response.get('success') == True: + data = response.get('data',{}) + memberSignFlag = data.get('memberSignFlag',False) + if memberSignFlag: + print('已签到') + else: + print('未签到') + self.signIn() + + return True + else: + print(f"登陆获取token失败: {response}") + return False + except Exception as e: + print(f"登陆获取token异常: {e}") + return False + + + def queryFragment(self): + try: + self.headers['referer'] =f"https://superapp-public.kiwa-tech.com/app-sign-in/?SignInToken={self.haidilao_app_token}&source=MiniApp" + + response = self.do_request( 'https://superapp-public.kiwa-tech.com/activity/wxapp/signin/queryFragment') + if response and response.get('success') == True: + data = response.get('data',{}) + total = data.get('total','') + expireDate = data.get('expireDate','').split()[0] + today = data.get('today','').split()[0] + + Log(f'当前拥有:【{total}】拼图碎片') + if expireDate == today: + Log('碎片今日到期,请及时兑换!!!!!') + Log('碎片今日到期,请及时兑换!!!!!') + Log('碎片今日到期,请及时兑换!!!!!') + else: + Log(f'本期碎片失效时间:{expireDate}') + return True + else: + print(f"获取拼图失败: {response}") + return False + except Exception as e: + print(f"获取拼图异常: {e}") + return False + + + def signIn(self): + try: + data = {"signinSource": "MiniApp"} + self.headers['referer'] =f"https://superapp-public.kiwa-tech.com/app-sign-in/?SignInToken={self.haidilao_app_token}&source=MiniApp" + + response = self.do_request( 'https://superapp-public.kiwa-tech.com/activity/wxapp/signin/signin',data = data) + if response and response.get('success') == True: + # data = response.get('data',{}) + # total = data.get('total','') + Log(f'签到成功!') + return True + else: + Log(f"签到失败: {response}") + return False + except Exception as e: + print(f"签到异常: {e}") + return False + + + + + def signin_query(self): + print('>>>>>>开始签到') + try: + self.headers['referer'] =f"https://superapp-public.kiwa-tech.com/app-sign-in/?SignInToken={self.haidilao_app_token}&source=MiniApp" + + response = self.do_request( 'https://superapp-public.kiwa-tech.com/activity/wxapp/signin/query') + if response and response.get('success') == True: + data = response.get('data',{}) + signinOr = data.get('signinOr',0) + activityName = data.get('activityName',0) + signinQueryDetailList = data.get('signinQueryDetailList',[{}]) + daycount = 0 + for day in signinQueryDetailList: + days = day.get('dailySigninStatus',1) + if days == 2: + daycount+=1 + if signinOr != 0 : + Log(f'已签到,本期累计签到【{daycount}】天') + else: + Log(f'未签到,本期累计签到【{daycount}】天') + self.signIn() + return True + else: + print(f"签到失败: {response}") + return False + except Exception as e: + print(f"签到异常: {e}") + return False + + + def main(self): + Log(f"\n开始执行第{self.index}个账号--------------->>>>>") + if self.wechatLogin(): + self.queryMemberCacheInfo() + self.signin_query() + self.queryFragment() + self.sendMsg() + return True + else: + return False + def sendMsg(self): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + + +if __name__ == '__main__': + APP_NAME = '海底捞小程序' + ENV_NAME = 'HDL' + CK_NAME = 'openId@uid' + CK_URL= 'https://superapp-public.kiwa-tech.com/api/gateway/login/center/login/wechatLogin' + print(f''' +✨✨✨ {APP_NAME}签到✨✨✨ +✨ 功能: + 签到 +✨ 抓包步骤: + 打开抓包工具 + 打开{APP_NAME} + 授权登陆 + 找{CK_URL}的URl复制请求里面的body[{CK_NAME}] + 复制里面的[{CK_NAME}]参数值 +参数示例:o4YwF5LIxxxxx@oF_Z5jh0Bwg_uZrODxxxxxxx +✨ ✨✨wxpusher一对一推送功能, + ✨需要定义变量export WXPUSHER=wxpusher的app_token,不设置则不启用wxpusher一对一推送 + ✨需要在{ENV_NAME}变量最后添加@wxpusher的UID +✨ 设置青龙变量: +export {ENV_NAME}='{CK_NAME}参数值'多账号#或&分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ ✨ 注意:抓完CK没事儿别打开小程序,重新打开小程序请重新抓包 +✨ 推荐cron:0 6 * * * +✨✨✨ @Author CHERWIN✨✨✨ +''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + access_token = [] + for index, infos in enumerate(tokens): + run_result = RUN(infos, index).main() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) \ No newline at end of file diff --git a/JTSD.py b/JTSD.py new file mode 100755 index 0000000..dcf8074 --- /dev/null +++ b/JTSD.py @@ -0,0 +1,242 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# ✨✨✨ 中通快递小程序签到✨✨✨ +# ✨ 功能: +# 积分签到 +# ✨ 抓包步骤: +# 打开中通快递小程序 +# 授权登陆 +# 打开抓包工具 +# 找URl请求头带[x-token或者token] +# 复制里面的[x-token或者token]参数值 +# 参数示例:eyJhbGciOiJIUzUxMiJ9.eyJnZW5lcmF0ZVRpbWUixxxxxx +# ✨ 设置青龙变量: +# export YDKD='x-token或者token参数值'多账号#或&分割 +# export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +# ✨ ✨ 注意:抓完CK没事儿别打开小程序,重新打开小程序请重新抓包 +# ✨ 推荐cron:0 6 * * * +# ✨✨✨ @Author CHERWIN✨✨✨ +# ------------------------------- +# cron "0 6 * * *" script-path=xxx.py,tag=匹配cron用 +# const $ = new Env('中通快递小程序签到') +import json +import os +import random +import time +from os import path +import requests +import hashlib +from requests.packages.urllib3.exceptions import InsecureRequestWarning +# import CHERWIN_TOOLS +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) + +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +class RUN: + def __init__(self,info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + self.token = split_info[0] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + print('检测到设置了UID') + print(last_info) + self.send_UID = last_info + self.index = index + 1 + self.s = requests.session() + self.s.verify = False + + self.headers = { + "Host": "applets.jtexpress.com.cn", + "authtoken": self.token, + "xweb_xhr": "1", + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x6309080f) XWEB/8555", + "content-type": "application/json;charset=UTF-8", + "accept": "*/*", + "sec-fetch-site": "cross-site", + "sec-fetch-mode": "cors", + "sec-fetch-dest": "empty", + "referer": "https://servicewechat.com/wxe37801988179d0a5/316/page-frame.html", + "accept-language": "zh-CN,zh;q=0.9" + } + + self.baseUrl = 'https://applets.jtexpress.com.cn/' + self.news_List = [] + self.list_index = 0 + self.isFirstTask = True + + def qureyMyselfGrow(self): + Log('>>>>>>获取用户信息') + response = self.s.get(f'{self.baseUrl}/applets/user/qureyMyselfGrow?', headers=self.headers) + data_info = response.json() + # print(point_info) + if data_info.get('succ','') == True: + data = data_info.get('data', {}) + mobile = data.get('mobile', '') + mobile = mobile[:3] + "*" * 4 + mobile[7:] + id = data.get('id', '') + memberId = data.get('memberId', '') + growValue = data.get('growValue', '') + nextStartGrow = data.get('nextStartGrow', '') + Log(f'获取用户[{self.index}]信息成功!\n手机号:【{mobile}】\n用户ID:【{memberId}】\n成长值:【{growValue}/{nextStartGrow}】') + return True + else: + print('获取用户信息失败!可能token失效了') + return False + + def addActionRecord(self): + print('>>>>>>进入签到详情') + json_data = { + "eventTimestamp": int(time.time() * 1000), + "pagePath": "packageA/signIn/index", + "reportAddress": "", + "reportLocation": "", + "phoneModel": "microsoft", + "eventType": "enter_signIn", + "elementContent": "", + "elementEventName": "进入签到详情", + "elementCode": 2 + } + response = self.s.post(f'{self.baseUrl}/applets/user/addActionRecord', headers=self.headers,json=json_data) + data_info = response.json() + # print(point_info) + if data_info.get('succ','') == True: + msg=data_info.get('msg','') + print(f'{msg}') + return True + else: + print('进入签到详情失败!可能token失效了') + return False + def sign(self): + print('>>>>>>开始签到') + json_data = {} + response = self.s.post(f'{self.baseUrl}/applets/user/sign', headers=self.headers,json=json_data) + data_info = response.json() + # print(point_info) + if data_info.get('succ','') == True: + msg=data_info.get('msg','') + day=data_info.get('data', {}).get('day', {}) + Log(f'累计签到【{day}】天') + return True + else: + Log('签到失败') + return False + + def main(self): + Log(f"\n开始执行第{self.index}个账号--------------->>>>>") + if self.qureyMyselfGrow(): + self.addActionRecord() + self.sign() + self.sendMsg() + else: + return False + + def sendMsg(self): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + + + +if __name__ == '__main__': + APP_NAME = '极兔速递小程序' + ENV_NAME = 'JTSD' + CK_NAME = 'authtoken' + print(f''' +✨✨✨ {APP_NAME}签到✨✨✨ +✨ 功能: + 积分签到 +✨ 抓包步骤: + 打开{APP_NAME} + 授权登陆 + 打开抓包工具 + 找URl请求头带[{CK_NAME}] + 复制里面的[{CK_NAME}]参数值 +参数示例:eyJhbGciOiJIUzUxMiJ9.eyJnZW5lcmF0ZVRpbWUixxxxxx +✨ ✨✨wxpusher一对一推送功能, + ✨需要定义变量export WXPUSHER=wxpusher的app_token,不设置则不启用wxpusher一对一推送 + ✨需要在{ENV_NAME}变量最后添加@wxpusher的UID +✨ 设置青龙变量: +export {ENV_NAME}='{CK_NAME}参数值'多账号#或&分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ ✨ 注意:抓完CK没事儿别打开小程序,重新打开小程序请重新抓包 +✨ 推荐cron:0 6 * * * +✨✨✨ @Author CHERWIN✨✨✨ +''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + access_token = [] + for index, infos in enumerate(tokens): + run_result = RUN(infos, index).main() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) \ No newline at end of file diff --git a/KFHS.py b/KFHS.py new file mode 100755 index 0000000..f645f67 --- /dev/null +++ b/KFHS.py @@ -0,0 +1,354 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# cron "30 1 * * *" script-path=xxx.py,tag=匹配cron用 +# const $ = new Env('微信公众号:卡夫亨氏新厨艺') + +import os +import random +import time +from datetime import date, datetime + +import requests +from requests.packages.urllib3.exceptions import InsecureRequestWarning +# import CHERWIN_TOOLS +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +class RUN: + def __init__(self,info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + self.token = split_info[0] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + self.send_UID = last_info + self.index = index + 1 + Log(f"\n---------开始执行第{self.index}个账号>>>>>") + self.s = requests.session() + self.s.verify = False + + self.headers = { + 'Host': 'fscrm.kraftheinz.net.cn', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 NetType/WIFI MicroMessenger/7.0.20.1781(0x6700143B) WindowsWechat(0x63090719) XWEB/8447 Flue', + 'token': self.token, + 'Accept': '*/*', + 'Origin': 'https://fscrm.kraftheinz.net.cn', + 'Sec-Fetch-Site': 'same-origin', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Dest': 'empty', + 'Referer': 'https://fscrm.kraftheinz.net.cn/?code=031NdLkl2SD8ac4BUKll2x4iqC2NdLkO&state=fid%3DN8d3E4AyKCBiu7DuBRNPlw&appid=wx65da983ae179e97b', + 'Accept-Language': 'zh-CN,zh;q=0.9', + 'Content-Type': 'application/x-www-form-urlencoded', + } + self.baseUrl = 'https://fscrm.kraftheinz.net.cn/crm/public/index.php/api/v1/' + + def getUserInfo(self,End=False): + global userid_list, username_list + response = self.s.get( + f'{self.baseUrl}getUserInfo', + headers=self.headers + ) + if response.status_code == 200: + try: + resp = response.json() + data = resp.get('data',{}) + nickname = data.get('nickname','') + openId = data.get('openId','') + signTimes = data.get('signTimes',0) + memberInfo = data.get('memberInfo', {}) + phone = memberInfo.get('phone', '') + score = memberInfo.get('score', '') + if End : + Log(f'执行后积分:【{score}】') + return True + self.member_id = data.get('member_id','') + # add = {"nickname":nickname,"member_id":member_id} + userid_list.append(self.member_id) + username_list.append(nickname) + Log(f'>>>当前用户:【{nickname}】\nID:【{self.member_id}】 \nOpenID:【{openId}】 \n已连续签到【{signTimes}】天') + serialSign = data.get('serialSign', [{}]) + + if serialSign : + current_date = date.today() + date_string = serialSign[0].get('createdAt',current_date) + memberBalance = serialSign[0].get('memberBalance', 0) + parsed_date = datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S').date() + if parsed_date == current_date: + print(f"今日已签到,当前积分:【{memberBalance}】") + else: + print("今日未签到") + wait_time = random.randint(1000, 10000) / 1000.0 # 转换为秒 + time.sleep(wait_time) + print('随机延时1-10秒执行签到') + self.dailySign() + return True + except: + print(response.text) + return False + else: + print("API访问失败!") + return False + + + def dailySign(self): + print('执行签到') + response = self.s.post( + f'{self.baseUrl}dailySign', + headers=self.headers + ) + if response.status_code == 200: + try: + resp = response.json() + msg = resp['msg'] + Log(f'>{msg}') + except: + print(response.text) + else: + print("API访问失败!") + + def getCookbookIndex(self): + global Cookid_list + data = { + 'page': '1', + 'pagesize': '30' + } + response = self.s.post( + f'{self.baseUrl}getCookbookIndex', + headers=self.headers, data=data + ) + if response.status_code == 200: + try: + resp = response.json() + id_list = resp['data']['chineseCookbook']['data'] + for i in id_list: + Cookid_list.append(i['id']) + print(f'>获取到菜谱ID:【{Cookid_list}】') + except: + print(response.text) + else: + print("API访问失败!") + + def recordScoreShare(self, cookbook_id, now_id): + # print('') + # self.getUserInfo() + Log('开始互助') + for id in userid_list: + if now_id == id: continue + # Log(f'>>>开始为【{id}】分享的菜谱【{cookbook_id}】助力') + data = { + 'cookbook_id': cookbook_id, + 'invite_id': id, + } + response = self.s.post( + f'{self.baseUrl}recordScoreShare', + headers=self.headers, data=data + ) + if response.status_code == 200: + try: + resp = response.json() + msg = resp['msg'] + Log(f'>为【{id}】助力结果:【{msg}】') + except: + print(response.text) + else: + print("API访问失败!") + + def helpAuthor(self, authorid, cookbook_id, now_id): + Log('开始助力作者') + if now_id != authorid: + data = { + 'cookbook_id': cookbook_id, + 'invite_id': authorid, + } + response = self.s.post( + f'{self.baseUrl}recordScoreShare', + headers=self.headers, data=data + ) + if response.status_code == 200: + try: + resp = response.json() + msg = resp['msg'] + Log(f'>为【作者】助力结果:【{msg}】') + except: + print(response.text) + else: + print("API访问失败!") + else: + Log('助力对象为自身,跳过') + + # 预留兑换函数 + def exchangeIntegralNew(self): + data = { + 'value': '爱奇艺月卡', + 'phone': '', + 'type': '视频卡' + } + # data = { + # 'value': '全网10元话费', + # 'phone': '', + # 'type': '话费', + # 'memberId': '', + # } + response = self.s.post( + f'{self.baseUrl}exchangeIntegralNew', + headers=self.headers, + data=data + ) + if response.status_code == 200: + try: + resp = response.json() + msg = resp['msg'] + Log(f'>{msg}') + except: + print(response.text) + else: + print("API访问失败!") + + def main(self): + # self.getUserInfo() + # self.getCookbookIndex() + if self.getUserInfo(): + if self.index == 1: + self.getCookbookIndex() + self.getUserInfo(True) + self.sendMsg() + return True + else: + return False + + def help(self): + # print(Cookid_list) + # print(username_list) + # print(userid_list) + if Cookid_list and username_list and userid_list: + cookbook_id = random.choice(Cookid_list) + username = username_list[self.index-1] + now_id = userid_list[self.index-1] + Log(f'\n当前用于助力用户:【{username}】 ID:【{now_id}】') + self.helpAuthor(662056, cookbook_id, now_id) + self.recordScoreShare(cookbook_id, now_id) + self.sendMsg(True) + return True + else: + return False + + + def sendMsg(self,help=False): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME,help) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + # print(APP_NAME, local_script_name, ENV_NAME,local_version) + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + + + + +if __name__ == '__main__': + APP_NAME = '卡夫亨氏新厨艺' + ENV_NAME = 'KFHS' + CK_NAME = 'token' + print(f''' +✨✨✨ {APP_NAME}签到✨✨✨ +✨ 功能: + 积分签到 +✨ 抓包步骤: + 打开{APP_NAME} + 授权登陆 + 打开抓包工具 + 找请求头带{CK_NAME}的URl + 复制里面的{CK_NAME}参数值 +✨ 注册链接(复制微信打开):https://fscrm.kraftheinz.net.cn/?from=N8d3E4AyKCBiu7DuBRNPlw==#/ +✨ ✨✨wxpusher一对一推送功能, + ✨需要定义变量export WXPUSHER=wxpusher的app_token,不设置则不启用wxpusher一对一推送 + ✨需要在{ENV_NAME}变量最后添加@wxpusher的UID +参数示例:Fks8FqmiTksnmZSj2fDvxxxxxxxxx@UID_xxxxx +✨ 设置青龙变量: +export {ENV_NAME}='{CK_NAME}参数值'多账号#或&分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ ✨ 注意:token有效期7天,7天后重新抓 +✨ 推荐cron:5 8 * * * +✨✨✨ @Author CHERWIN✨✨✨ +''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + print(token) + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + print(tokens) + Cookid_list = [] + userid_list = [] + username_list = [] + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + for index, infos in enumerate(tokens): + run_result = RUN(infos, index).main() + if not run_result: continue + print(f"\n>>>>>>>>>>开始互助<<<<<<<<<<") + for index, infos in enumerate(tokens): + run_result = RUN(infos, index).help() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) \ No newline at end of file diff --git a/KWW.py b/KWW.py new file mode 100755 index 0000000..40d630d --- /dev/null +++ b/KWW.py @@ -0,0 +1,366 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# cron "0 6 * * *" script-path=xxx.py,tag=匹配cron用 +# const $ = new Env('口味王小程序签到') + +import os +import random +import time + +import requests +import hashlib +from requests.packages.urllib3.exceptions import InsecureRequestWarning +# import CHERWIN_TOOLS +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +class RUN: + def __init__(self,info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + self.memberId = split_info[0] + self.unionId = split_info[1] + self.openId = split_info[2] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + print('检测到设置了UID') + print(last_info) + self.send_UID = last_info + self.index = index + 1 + + + self.UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x6309080f) XWEB/9079" + + self.headers = { + "Host": "member.kwwblcj.com", + "xweb_xhr": "1", + "User-Agent": self.UA, + "user-paramname": "memberId", + "Content-Type": "application/json", + "Accept": "/", + "Sec-Fetch-Site": "cross-site", + "Sec-Fetch-Mode": "cors", + "Sec-Fetch-Dest": "empty", + "Referer": "https://servicewechat.com/wxfb0905b0787971ad/101/page-frame.html", + "Accept-Language": "zh-CN,zh;q=0.9" + } + + def wxHeards(self): + timestamp = int(time.time() * 1000) + random_num = random.randint(0, 31) + u = [ + "A", "Z", "B", "Y", "C", "X", "D", "T", "E", "S", "F", "R", "G", "Q", "H", "P", "I", "O", "J", "N", "k", + "M", "L", "a", "c", "d", "f", "h", "k", "p", "y", "n"] + r = f"{timestamp}{self.memberId}{u[random_num]}" + sign = hashlib.md5(r.encode()).hexdigest() + update_headers = { + "user-sign": sign, + "user-paramname": "memberId", + "user-timestamp": str(timestamp), + "user-random": str(random_num) + } + self.headers.update(update_headers) + + return + def do_request(self, url , method='POST', params=None, data=None, headers=None): + self.wxHeards() + if not headers: + headers = self.headers + try: + response = s.request(method, url, params=params, json=data, headers=headers) + response.raise_for_status() + return response.json() + except Exception as e: + print(f"请求错误: {e}") + return None + + def memberInfo(self): + print('>>>>>>获取用户信息') + try: + url = f"https://member.kwwblcj.com/member/api/info/?userKeys=v1.0&pageName=member-info-index-search&formName=searchForm&kwwMember.memberId={self.memberId}&kwwMember.unionid={self.unionId}&memberId={self.memberId}" + response = self.do_request(url,'GET') + if response and response.get('msg') == "查询成功": + result = response.get('result',{}) + memberInfo = result.get('memberInfo',{}) + self.userCname = memberInfo.get('userCname','') + Log(f'当前用户:【{self.userCname}】') + return True + else: + print(f"登陆获取token失败: {response}") + return False + except Exception as e: + print(f"登陆获取token异常: {e}") + return False + + + + def get_task_list(self): + print('>>>>>>获取任务列表') + # try: + url = f"https://member.kwwblcj.com/member/api/list/?userKeys=v1.0&pageName=select-task-list&formName=searchForm&page=1&rows=20&memberId={self.memberId}" + response = self.do_request(url,'GET') + if response and response.get('msg') == "查询成功": + rows = response.get('rows',[{}]) + for task in rows: + self.taskLimit = task.get('taskLimit','') + self.taskTitle = task.get('taskTitle','') + self.subTitle = task.get('subTitle','') + self.complete = task.get('complete','') + self.rewardScore = task.get('rewardScore','') + self.ruleType = task.get('ruleType','') + self.infoId = task.get('infoId','') + # print(f'\n当前任务:【{self.taskTitle}】\n任务要求:【{self.subTitle}】\n任务奖励:【{self.rewardScore}】\ninfoId:【{self.infoId}】\nruleType:【{self.ruleType}】') + print(f'当前任务:【{self.taskTitle}】') + if self.complete == '1': + print('任务已完成!') + continue + if self.taskTitle == '每日阅读': + self.ReadTask() + + elif self.taskTitle == "收青果": + self.activity() + + # elif self.taskTitle == "每日答题": + # pass + # self.loginFreePlugin() + else: + print('暂不支持此任务') + wait_time = random.randint(2, 4) # 转换为秒 + time.sleep(wait_time) # 等待 + return True + else: + print(f"获取任务列表失败: {response}") + return False + # except Exception as e: + # print(f"获取任务列表异常: {e}") + # return False + + def activity(self): + print(f'>>>>>>{self.taskTitle}') + try: + url = f"https://member.kwwblcj.com/member/api/list/?userKeys=v1.0&pageName=activeTaskFlag&formName=editForm&memberId={self.memberId}&userCname={self.userCname}&page=1&rows=2" + + response = self.do_request(url,'GET') + + # url2 = f"https://member.kwwblcj.com/member/api/list/?userKeys=v1.0&pageName=memberTaskInfo&formName=searchForm&page=1&rows=2&memberId={self.memberId}" + # response = self.do_request(url2, 'GET') + # + if response and response.get('flag') == "T": + print(f'访问:【{self.taskTitle}】成功!') + return True + else: + print(f"{self.taskTitle}失败: {response}") + return False + except Exception as e: + print(f"{self.taskTitle}异常: {e}") + return False + + + def ReadTask(self): + print(f'>>>>>>{self.taskTitle}') + try: + url = f"https://member.kwwblcj.com/member/api/list/?userKeys=v1.0&pageName=setNewsReadTaskFlag&formName=addForm&memberId={self.memberId}&userCname={self.userCname}&articleTitle=3.15&actionType=articleRead&actionDesc=3.15https%3A%2F%2Fmp.weixin.qq.com%2Fs%2F_2N3AQ12lbXfBSSPja-Q0Q&memberName={self.userCname}&objId=C01&page=1&rows=2" + + response = self.do_request(url,'GET') + + if response and response.get('flag') == "T": + + print(f'阅读成功!') + return True + else: + print(f"{self.taskTitle}失败: {response}") + return False + except Exception as e: + print(f"{self.taskTitle}异常: {e}") + return False + + def getPoint(self): + try: + url = f"https://member.kwwblcj.com/member/api/list/?userKeys=v1.0&pageName=me-funds&formName=searchForm&userId={self.memberId}&page=1&rows=2&memberId={self.memberId}" + + response = self.do_request(url,'GET') + if response and response.get('flag') == "T": + rows = response.get('rows',{}) + balance = rows.get('balance','') + # print(response) + Log(f'当前积分:【{balance}】\n') + return True + else: + print(f"获取积分信息失败: {response}") + return False + except Exception as e: + print(f"获取积分信息异常: {e}") + return False + + def loginFreePlugin(self): + print(f'>>>>>>{self.taskTitle}') + try: + url = f"https://member.kwwblcj.com/member/api/info/?userKeys=v1.0&pageName=loginFreePlugin&formName=searchForm&uid={self.memberId}&levelCode=K1&redirect=https%3A%2F%2F89420.activity-20.m.duiba.com.cn%2Fprojectx%2Fp129446ea%2Findex.html%3FappID%3D89420&memberId={self.memberId}" + response = self.do_request(url,'GET') + if response and response.get('msg') == "信息获取成功!": + result = response.get('result',{}) + self.autologin(result) + return True + else: + print(f"{self.taskTitle}失败: {response}") + return False + except Exception as e: + print(f"{self.taskTitle}异常: {e}") + return False + + def autologin(self,url): + try: + headers = { + "Host": "89420.activity-20.m.duiba.com.cn", + "upgrade-insecure-requests": "1", + "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x6309080f) XWEB/9079", + "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", + "sec-fetch-site": "none", + "sec-fetch-mode": "navigate", + "sec-fetch-user": "?1", + "sec-fetch-dest": "document", + "accept-language": "zh-CN,zh;q=0.9" + } + + response = s.get(url, headers=headers,allow_redirects=True) + print(response.text) + url = 'https://89420.activity-20.m.duiba.com.cn/projectx/p129446ea/coop_frontVariable.query?user_type=0&is_from_share=1&_t=1710789863411' + + response = s.get(url, headers=headers) + print(response.text) + # if response and response.get('msg') == "信息获取成功!": + # result = response.get('result',{}) + # + # return True + # else: + # print(f"{self.taskTitle}失败: {response}") + # return False + except Exception as e: + print(f"{self.taskTitle}异常: {e}") + return False + + + + def main(self): + print(f"\n开始执行第{self.index}个账号--------------->>>>>") + # self.memberInfo() + if self.memberInfo(): + self.get_task_list() + self.getPoint() + self.sendMsg() + return True + else: + return False + + def sendMsg(self): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + +if __name__ == '__main__': + APP_NAME = '口味王会员中心小程序' + ENV_NAME = 'KWW' + CK_NAME = 'memberId@unionid@openid' + CK_URL= '/member/api/info/' + print(f''' +✨✨✨ {APP_NAME}签到✨✨✨ +✨ 功能: + 积分签到 + 部分积分任务 +✨ 抓包步骤: + 打开抓包工具 + 打开{APP_NAME} + 授权登陆 + 找{CK_URL}的URl提取请求[{CK_NAME}](@符号连接) +参数示例:4249095xxxxxx@oWmTE6IqrlDFRzxxxxx@o_V6_5btlEBzxxxxxx +✨ ✨✨wxpusher一对一推送功能, + ✨需要定义变量export WXPUSHER=wxpusher的app_token,不设置则不启用wxpusher一对一推送 + ✨需要在{ENV_NAME}变量最后添加@wxpusher的UID +✨ 设置青龙变量: +export {ENV_NAME}='{CK_NAME}参数值'多账号#或&分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ 推荐cron:0 9 * * * +✨✨✨ @Author CHERWIN✨✨✨ +''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + access_token = [] + for index, infos in enumerate(tokens): + s = requests.session() + s.verify = False + run_result = RUN(infos, index).main() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) + + + diff --git a/NXDD.py b/NXDD.py new file mode 100755 index 0000000..4573ed8 --- /dev/null +++ b/NXDD.py @@ -0,0 +1,335 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# @Author CHERWIN✨✨✨ +# ------------------------------- +# cron "30 1 * * *" script-path=xxx.py,tag=匹配cron用 +# const $ = new Env('奈雪小程序签到') +import datetime +import json +import os +import random +import requests +import hashlib +import hmac +import base64 +import time +from requests.packages.urllib3.exceptions import InsecureRequestWarning + +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +class RUN: + def __init__(self,info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + token = split_info[0] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + print('检测到设置了UID') + print(last_info) + self.send_UID = last_info + self.index = index + 1 + self.s = requests.session() + self.s.verify = False + + self.token = f'Bearer {token}' + self.UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF XWEB/6945' + self.openId = 'QL6ZOftGzbziPlZwfiXM' + + def random_string(self,length=6, chars='123456789'): + return ''.join(random.choice(chars) for _ in range(length)) + + def get_body(self): + nonce = int(self.random_string()) + timestamp = int(time.time()) + url_path = f'nonce={nonce}&openId={self.openId}×tamp={timestamp}' + signature = base64.b64encode( + hmac.new('sArMTldQ9tqU19XIRDMWz7BO5WaeBnrezA'.encode(), url_path.encode(), hashlib.sha1).digest()).decode() + common = { + 'platform': 'wxapp', + 'version': '5.1.8', + 'imei': '', + 'osn': 'microsoft', + 'sv': 'Windows 10 x64', + 'lang': 'zh_CN', + 'currency': 'CNY', + 'timeZone': '', + 'nonce': nonce, + 'openId': self.openId, + 'timestamp': timestamp, + 'signature': signature + } + params = { + 'businessType': 1, + 'brand': 26000252, + 'tenantId': 1, + 'channel': 2, + 'stallType': None, + 'storeId': None + } + + requestData = { + 'common': common, + 'params': params + } + return requestData + + def task_api(self,api_options=None): + if api_options is None: + api_options = {} + try: + # 首先解析URL,获得主机名 + host_name = api_options['url'].replace('//', '/').split('/')[1] + full_url = api_options['url'] + if 'queryParam' in api_options: + # 如果存在查询参数,将其附加到URL + query_str = "&".join(f"{k}={v}" for k, v in api_options['queryParam'].items()) + full_url += '?' + query_str + # 定义请求头 + headers = { + 'Host': host_name, + 'Connection': 'keep-alive', + 'User-Agent': self.UA, + 'Authorization': self.token, + 'Referer': 'https://tm-web.pin-dao.cn/', + 'Origin': 'https://tm-web.pin-dao.cn' + } + # 准备请求体 + data = None + if 'body' in api_options: + body = self.get_body() + body['params'].update(api_options['body']) + content_type = api_options.get('Content-Type', 'application/json') + headers['Content-Type'] = content_type + if 'json' in content_type: + data = json.dumps(body) + else: + data = "&".join(f"{k}={json.dumps(v) if isinstance(v, dict) else v}" for k, v in body.items()) + headers['Content-Length'] = str(len(data)) + # 如果有额外的URL参数或头部参数,合并到请求中 + if 'urlObjectParam' in api_options: + # 这里根据需要处理urlObjectParam + pass + if 'headerParam' in api_options: + headers.update(api_options['headerParam']) + # 发出请求 + response = requests.request(method=api_options.get('method', 'GET'), url=full_url, headers=headers, + data=data, timeout=20,verify=False) + # 打印状态码 + if response.status_code != 200: + print(f"[{api_options.get('fn', 'unknown function')}]返回[{response.status_code}]") + + # 解析结果 + try: + result = response.json() + except ValueError: + result = response.text + return result + + except Exception as e: + print(str(e)) + return {} + + def base_userinfo(self): + try: + api_options = { + 'fn': 'baseUserinfo', + 'method': 'post', + 'url': 'https://tm-web.pin-dao.cn/user/base-userinfo', + 'body': {} + } + response = self.task_api(api_options) + if response['code'] == 0: + # 登录成功的逻辑处理 + phone = response['data']['phone'] + self.phone = phone[:3] + "*" * 4 + phone[7:] + self.userId = response['data']['userId'] + self.nickName = response['data']['nickName'] + Log(f'账号[{self.index}]登录成功!\n手机号:[{self.phone}] ID[{self.userId}]') + # print(one_msg) + return True + else: + # 登录失败的逻辑处理 + Log(f"账号登录失败: {response['message']}") + except Exception as e: + print(e) + + def user_account(self): + try: + api_options = { + 'fn': 'userAccount', + 'method': 'post', + 'url': 'https://tm-web.pin-dao.cn/user/account/user-account', + 'body': {} + } + response = self.task_api(api_options) + if response['code'] == 0: + # 查询成功的逻辑处理 + coin = response['data']['coin'] + Log(f'账号[{self.index}]当前奈雪币: {coin}') + else: + # 查询失败的逻辑处理 + Log(f'账号[{self.index}]查询失败') + except Exception as e: + print(e) + + def sign_record(self): + try: + sign_date = datetime.datetime.now().replace(day=1).strftime('%Y-%m-%d') + today_date = datetime.datetime.now().strftime('%Y-%m-%d') + api_options = { + 'fn': 'signRecord', + 'method': 'post', + 'url': 'https://tm-web.pin-dao.cn/user/sign/records', + 'body': { + 'signDate': sign_date, + 'startDate': today_date + } + } + response = self.task_api(api_options) + if response['code'] == 0: + Log(f"今天{'已' if response['data']['status'] else '未'}签到,已签到{response['data']['signCount']}天") + if not response['data']['status']: + self.sign_save() + else: + Log(f"查询签到失败: {response['message']}") + except Exception as e: + print(e) + + def sign_save(self): + try: + sign_date = datetime.datetime.now().strftime('%Y-%m-%d') + api_options = { + 'fn': 'signSave', + 'method': 'post', + 'url': 'https://tm-web.pin-dao.cn/user/sign/save', + 'body': { + 'signDate': sign_date + } + } + response = self.task_api(api_options) + if response['code'] == 0: + if response['data']['flag']: + Log('签到成功') + else: + Log('今天已经签到过了') + else: + print(f"签到失败: {response['message']}") + except Exception as e: + print(e) + + def main(self): + Log(f"\n开始执行第{self.index}个账号--------------->>>>>") + base_userinfo_result = self.base_userinfo() + if not base_userinfo_result: + Log("用户信息无效,请更新CK") + return False + self.sign_record() + self.user_account() + self.sendMsg() + return True + + def sendMsg(self, help=False): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME, help) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + +if __name__ == '__main__': + APP_NAME = '奈雪点单小程序' + ENV_NAME = 'NXDD' + CK_NAME = 'Authorization' + print(f''' +✨✨✨ {APP_NAME}签到✨✨✨ +✨ 功能: + 积分签到 +✨ 抓包步骤: + 打开{APP_NAME} + 授权登陆 + 打开抓包工具 + 找请求头带{CK_NAME}的URl + 复制里面的{CK_NAME}参数值【不要】前面的Bearer 【不要】前面的Bearer 【不要】前面的Bearer +参数示例:eyJhbGciOiJxxxxxxxxxxxx +✨ 设置青龙变量: +export {ENV_NAME}='{CK_NAME}参数值【不要】前面的Bearer'多账号#或&分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ ✨ 注意:抓完CK没事儿别打开小程序,重新打开小程序请重新抓包 +✨ 推荐cron:30 1 * * * +✨✨✨ @Author CHERWIN✨✨✨ +''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + access_token = [] + for index, infos in enumerate(tokens): + run_result = RUN(infos, index).main() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) diff --git a/PPCS.py b/PPCS.py new file mode 100755 index 0000000..9d4f141 --- /dev/null +++ b/PPCS.py @@ -0,0 +1,554 @@ +''' +!/usr/bin/python3 +-- coding: utf-8 -- +------------------------------- +✨✨✨ @Author CHERWIN✨✨✨ +cron "0 9 * * *" script-path=xxx.py,tag=匹配cron用 +const $ = new Env('朴朴超市APP') +''' + +import json +import os +import random +import time +from sys import exit +from datetime import datetime, timedelta +from urllib.parse import urlparse + +import requests +from requests.packages.urllib3.exceptions import InsecureRequestWarning +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") + +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +inviteCode = {} + +class RUN: + def __init__(self, info,index,access_token=None,user_id=None): + global one_msg + one_msg = '' + split_info = info.split('@') + self.refresh_token = split_info[0] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + self.send_UID = last_info + self.index = index + 1 + + Log(f"\n---------开始执行第{self.index}个账号>>>>>") + self.s = requests.session() + self.s.verify = False + self.UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x6309080f) XWEB/8555' + self.headers = { + 'Authorization': '', + 'Accept': 'application/json, text/plain, */*', + 'User-Agent': self.UA, + 'Origin': 'https://ma.pupumall.com', + 'Sec-Fetch-Site': 'cross-site', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Dest': 'empty', + 'Referer': 'https://ma.pupumall.com/', + 'Accept-Language': 'zh-CN,zh;q=0.9', + 'pp-os': '0' + } + # print(self.refresh_token) + self.team_need_help = False + self.teamId = '' + self.location = {} + self.store_id = None + self.zip = None + self.lng = None + self.lat = None + self.params = { + 'supplement_id': '', + 'lat_y': '', + 'lng_x': '', + } + if access_token: + self.access_token=access_token + self.headers['Authorization'] = access_token + self.headers['pp-userid'] = user_id + self.near_location_by_city() + self.wait_time = random.randint(1000, 3000) / 1000.0 # 转换为秒 + + + + def make_request(self, url, method='post',headers={},params='',data={}): + parsed_url = urlparse(url) + host = parsed_url.netloc + self.headers['Host'] = host + if headers == {}: + headers = self.headers + if data =={}: + data = self.params + try: + if method.lower() == 'get': + response = self.s.get(url, headers=headers, verify=False,params=params) + elif method.lower() == 'post': + response = self.s.post(url, headers=headers, json=data, verify=False) + else: + raise ValueError("不支持的请求方法: " + method) + + return response.json() + except requests.exceptions.RequestException as e: + print("请求异常:", e) + except ValueError as e: + print("值错误或不支持的请求方法:", e) + except Exception as e: + print("发生了未知错误:", e) + + def near_location_by_city(self): + print('>>>>>>开始随机选择位置') + url = 'https://j1.pupuapi.com/client/store/place/near_location_by_city/v2' + # 生成随机的四位数 + random_digits = ''.join(random.choices('0123456789', k=4)) + # 准备查询参数 + search_params = { + 'lng': '119.31' + random_digits, + 'lat': '26.06' + random_digits + } + try: + result =self.make_request(url,method='get',params=search_params) + errcode = result.get('errcode', -1) + if errcode == 0: + data = result.get('data') + # 假设randomList是一个选择列表中随机元素的方法 + self.location = self.randomList(data) + self.store_id = self.location['service_store_id'] + self.zip = self.location['city_zip'] + self.lng = str(self.location['lng_x']) + self.lat = str(self.location['lat_y']) + self.params['lat_y'] = self.lat + self.params['lat_x'] = self.lng + # 更新请求头部 + self.headers['pp_storeid'] = self.store_id + self.headers['pp-cityzip'] = str(self.zip) + print('>选取随机地点成功') + else: + errmsg = result.get('errmsg', '') + print(f'>选取随机地点失败[{errcode}]: {errmsg}') + except Exception as e: + print(e) + + def randomList(self, lst): + # 返回列表中的随机项 + return random.choice(lst) + + def get_AccessToken(self): + # Log('获取access_token') + url = "https://cauth.pupuapi.com/clientauth/user/refresh_token" + data = { + "refresh_token": self.refresh_token + } + headers = { + "User-Agent": "Pupumall/4.7.3;Android/11;dda37894d1b4c3ed09b6272c55b37cf2", + "Content-Type": "application/json; charset=UTF-8", + "Host": "cauth.pupuapi.com", + "Connection": "Keep-Alive", + "Accept-Encoding": "gzip" + } + + try: + response = requests.put(url, headers=headers, data=json.dumps(data), verify=False) + response.raise_for_status() + + json_response = response.json() + print(json_response) + data = json_response.get('data', {}) + access_token = data.get('access_token', '') + if access_token: + self.access_token = f'Bearer '+access_token + self.user_id = data.get('user_id') + self.name = data.get('nick_name', '') + self.headers['Authorization'] = self.access_token + self.headers['pp-userid'] = self.user_id + append_data = { + 'access_token':self.access_token, + 'user_id':self.user_id + } + access_token_li.append(append_data) + # print(f'账号【{self.index}】access_token:{self.access_token}') + return True + else: + return False + except requests.exceptions.HTTPError as http_err: + Log(f"HTTP请求出错: {http_err}") + except requests.exceptions.ConnectionError as conn_err: + Log(f"网络连接出错: {conn_err}") + except requests.exceptions.Timeout as timeout_err: + Log(f"请求超时: {timeout_err}") + except requests.exceptions.RequestException as req_err: + Log(f"出现了一个意外的请求错误: {req_err}") + except json.JSONDecodeError as json_err: + Log(f"JSON解码错误: {json_err}") + return False + + + def getUserInfo(self): + global inviteCode + Log(f'>>>>>>获取用户信息') + url = "https://cauth.pupuapi.com/clientauth/user/info" + + # response = self.do_request(url, headers=headers,req_type='get') + response = self.make_request(url,method='get') + # print(response) + if 'errcode' in response and response.get('errcode', '') == 0: + data = response.get('data') + self.user_id = data.get('user_id') + phone_number = data['phone'] + self.phone = phone_number[:3] + '****' + phone_number[7:] + self.invite_code = data['invite_code'] + Log(f'手机号:【{self.phone}】') + print(f'用户ID:【{self.user_id}】\n邀请码:【{self.invite_code}】') + # new_data = { + # self.user_id: + # { + # 'phone': self.phone, + # 'invite_code': self.invite_code + # } + # } + # CHERWIN_TOOLS.SAVE_INVITE_CODE("INVITE_CODE/PPCS_INVITE_CODE.json", new_data) + return True + else: + Log(f'>获取用户信息失败') + print(response) + return False + + def signStu(self): + Log(f'>>>>>>获取签到状态') + url = 'https://j1.pupuapi.com/client/game/sign/v2/index' + try: + result = self.make_request(url, 'get') + errcode = result.get('errcode', 1) + if errcode == 0: + data = result.get('data', {}) + is_signed = data.get('is_signed', 0) + if is_signed: + Log('今天已签到') + else: + self.sign() + else: + errmsg = result.get('errmsg', '') + print('查询签到信息失败[{}]: {}'.format(errcode, errmsg)) + except Exception as e: + print('签到索引过程中发生错误: {}'.format(e)) + + def getCoinInfo(self): + url = "https://j1.pupuapi.com/client/coin" + # response = self.do_request(url, req_type='get') + response = self.make_request(url,method='get') + # print(response) + if 'errcode' in response and response.get('errcode', '') == 0: + data = response.get('data') + # 当前朴分 + coin = data['balance'] + Log(f'当前朴分:【{coin}】') + else: + Log(f'>获取当前朴分失败') + print(response) + + + + def sign(self): + Log(f'>>>>>>开始签到') + url = "https://j1.pupuapi.com/client/game/sign/v2?supplement_id=" + # 签到 + data = {'supplement_id': ''} + try: + result = self.make_request(url, 'post', data=data) + errcode = result.get('errcode', 1) + if errcode == 0: + data = result.get('data', {}) + daily_sign_coin = data.get('daily_sign_coin', 0) + coupon_list = data.get('coupon_list', []) + + rewards = [str(daily_sign_coin) + '积分'] + for coupon in coupon_list: + condition_amount = '{:.2f}'.format(coupon['condition_amount'] / 100) + discount_amount = '{:.2f}'.format(coupon['discount_amount'] / 100) + rewards.append('满{}减{}券'.format(condition_amount, discount_amount)) + Log('签到成功: ' + ', '.join(rewards)) + else: + errmsg = result.get('errmsg', '') + Log('签到失败[{}]: {}'.format(errcode, errmsg)) + except Exception as e: + Log('签到过程中发生错误: {}'.format(e)) + + # 发起组队 + def creatTeam(self): + global inviteCode + Log(f'>>>>>>开始发起组队') + url = "https://j1.pupuapi.com/client/game/coin_share/team" + response = self.make_request(url) + # print(response) + if 'errcode' in response and response.get('errcode', '') == 0: + data = response.get('data') + self.teamId = data + Log(f'>发起组队成功,ID:【{data}】') + return True + elif 'errcode' in response and response.get('errcode', '') != 0: + Log(f'>发起组队失败:【{response.get("errmsg", "")}】') + else: + Log(f'>发起组队失败') + print(response) + return False + + def get_myTeam(self): + Log(f'>>>>>>开始查询历史组队') + # 获取当前日期 + today = datetime.now().date() + # 构建当天的23:59:59时间 + end_of_day = datetime.combine(today, datetime.max.time()) + timedelta(hours=23, minutes=59, seconds=59) + # 将时间转换为时间戳(毫秒为单位) + timestamp = int(end_of_day.timestamp() * 1000) + # 将日期格式化为字符串 + formatted_date = today.strftime("%Y-%m-%d") + # print(timestamp) + # print(formatted_date) + url = f'https://j1.pupuapi.com/client/game/coin_share/records?time_from=1704038400000&time_to={timestamp}&page=1&size=20' + try: + result = self.make_request(url,method='get') + errcode = result.get('errcode', -1) + isCreatTeam = False + if errcode == 0: + data = result.get('data',[{}]) + for team in data: + # print(team) + record_type = team.get('record_type','') + time_create = team.get('time_create','') + # 将时间戳转换为 datetime 对象 + timestamp = time_create / 1000 # 将时间戳转换为秒 + dt = datetime.fromtimestamp(timestamp) + # 将日期格式化为字符串 + formatted_time_create = dt.strftime("%Y-%m-%d") + team_id = team.get('team_id','') + # print(record_type) + # print(formatted_time_create) + # print(team_id) + if record_type == 0 and formatted_time_create == formatted_date: + self.teamId = team_id + isCreatTeam =True + break + if isCreatTeam: + Log(f'今日已创建ID:【{self.teamId}】队伍') + self.check_my_team() + else: + self.creatTeam() + else: + errmsg = result.get('errmsg', '') + print(f'查询组队历史信息失败[{errcode}]: {errmsg}') + except Exception as e: + print(str(e)) + + def check_my_team(self): + Log(f'>>>>>>开始查询组队详情') + url = f'https://j1.pupuapi.com/client/game/coin_share/teams/{self.teamId}' + try: + result = self.make_request(url,method='get') + errcode = result.get('errcode', -1) + if errcode == 0: + data = result.get('data') + status = data.get('status') + if status == 10: + self.team_need_help = True + self.team_max_help = data.get('target_team_member_num') + self.team_helped_count = data.get('current_team_member_num') + Log(f'组队未完成: {self.team_helped_count}/{self.team_max_help}') + elif status == 30: + self.team_need_help = False + coins = data.get('current_user_reward_coin') + Log(f'已组队成功, 获得了{coins}积分') + else: + Log(f'组队状态[{status}]') + print(f': {json.dumps(data)}') + else: + errmsg = result.get('errmsg', '') + print(f'查询组队信息失败[{errcode}]: {errmsg}') + except Exception as e: + print(str(e)) + # 组队 + def joinAuthorTeam(self): + Log(f'>>>>>>第1个账号开始助力作者') + if len(AuthorCode) > 0: + for code in AuthorCode: + # print(code['teamId']) + url = f"https://j1.pupuapi.com/client/game/coin_share/teams/{code['teamId']}/join" + response = self.make_request(url) + # print(response) + if 'errcode' in response and response.get('errcode', '') == 0: + print(f'>入队成功:【{code}】') + break + # elif 'errcode' in response and response.get('errcode', '') != 0: + # print(f'>入队失败:【{response.get("errmsg", "")}】') + # else: + # print(f'>入队失败') + # print(response) +# 组队 + def joinTeam(self): + global inviteCode + Log(f'>>>>>>开始本地组队') + with open('INVITE_CODE/PPCS_INVITE_CODE.json', 'r') as file: + data = json.load(file) + inviteCode = list(data.values()) + for code in inviteCode: + teamId = code.get('teamId',False) + if not teamId:continue + url = f"https://j1.pupuapi.com/client/game/coin_share/teams/{code['teamId']}/join" + response = self.make_request(url) + # print(response) + if 'errcode' in response and response.get('errcode', '') == 0: + Log(f">入队成功:【{code['teamId']}】") + elif 'errcode' in response and response.get('errcode', '') != 0: + Log(f'>入队失败:【{response.get("errmsg", "")}】') + else: + Log(f'>入队失败') + print(response) + + def main(self): + # print(self.refresh_token) + if self.get_AccessToken(): + print('成功获取了access token.') + self.getUserInfo() + self.signStu() + self.getCoinInfo() + self.get_myTeam() + new_data = { + self.user_id: + { + 'phone': self.phone, + 'invite_code': self.invite_code + } + } + if self.teamId:new_data[self.user_id]['teamId']=self.teamId + CHERWIN_TOOLS.SAVE_INVITE_CODE("INVITE_CODE/PPCS_INVITE_CODE.json", new_data) + return True + else: + Log( f'账号[{self.index}] {CK_NAME}:\n【{self.refresh_token}】\n已失效请及时更新') + return False + self.sendMsg() + + def help(self): + if self.get_AccessToken(): + + if self.index == 1: + Log('--------签到组队--------') + self.joinAuthorTeam() + else: + Log('--------签到组队--------') + self.joinTeam() + return True + else: + Log(f'账号[{self.index}] {CK_NAME}:\n【{self.refresh_token}】\n已失效请及时更新') + return False + self.sendMsg(True) + + def sendMsg(self, help=False): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME, help) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + +if __name__ == '__main__': + APP_NAME = '朴朴超市' + ENV_NAME = 'PPCS' + CK_NAME = 'refresh_token' + print(f''' +✨✨✨ 朴朴超市脚本✨✨✨ +✨ 功能: + 积分签到 + 组队互助 +✨ 抓包步骤: + 打开朴朴超市APP + 已登录先退出 + 打开抓包 + 登陆 + 找https://cauth.pupuapi.com/clientauth/user/verify_login + 复制返回body中的{CK_NAME} + 多个账号可清理APP数据进行换号别点退出否则token失效 +✨ 设置青龙变量: +export {ENV_NAME}= 'E0oXq3++6a4LG4xxxxxxxx'多账号#分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ 多账号默认第一个账号与作者组队,其余互助 +✨ 推荐定时:0 9 * * * +✨✨✨ @Author CHERWIN✨✨✨ + ''') + + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + access_token_li=[] + for index, infos in enumerate(tokens): + run_result = RUN(infos, index).main() + if not run_result: continue + + for index, infos in enumerate(tokens): + RUN(infos, index).help() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) + + diff --git a/SFSY.py b/SFSY.py new file mode 100755 index 0000000..dc23307 --- /dev/null +++ b/SFSY.py @@ -0,0 +1,1121 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# @Author : cherwin +# cron "5 5,17 * * *" script-path=xxx.py,tag=匹配cron用 +# const $ = new Env('顺丰速运') +import hashlib +import json +import os +import random +import time +from datetime import datetime, timedelta +from sys import exit +import requests +from requests.packages.urllib3.exceptions import InsecureRequestWarning +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' +#1905 #0945 #6332 #6615 2559 +inviteId=['8C3950A023D942FD93BE9218F5BFB34B','EF94619ED9C84E968C7A88CFB5E0B5DC','9C92BD3D672D4B6EBB7F4A488D020C79','803CF9D1E0734327BDF67CDAE1442B0E','00C81F67BE374041A692FA034847F503'] + +class RUN: + def __init__(self,info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + url = split_info[0] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + self.send_UID = last_info + self.index = index + 1 + Log(f"\n---------开始执行第{self.index}个账号>>>>>") + self.s = requests.session() + self.s.verify = False + self.headers = { + 'Host': 'mcs-mimp-web.sf-express.com', + 'upgrade-insecure-requests': '1', + 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 NetType/WIFI MicroMessenger/7.0.20.1781(0x6700143B) WindowsWechat(0x63090551) XWEB/6945 Flue', + 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', + 'sec-fetch-site': 'none', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-user': '?1', + 'sec-fetch-dest': 'document', + 'accept-language': 'zh-CN,zh', + 'platform': 'MINI_PROGRAM', + + } + self.anniversary_black = False + self.login_res = self.login(url) + self.today = datetime.now().strftime('%Y-%m-%d') + self.answer = APP_INFO.get('ANSWER',[]).get(self.today,False) + + def get_deviceId(self, characters='abcdef0123456789'): + result = '' + for char in 'xxxxxxxx-xxxx-xxxx': + if char == 'x': + result += random.choice(characters) + elif char == 'X': + result += random.choice(characters).upper() + else: + result += char + return result + + def login(self,sfurl): + ress = self.s.get(sfurl, headers=self.headers) + # print(ress.text) + self.user_id = self.s.cookies.get_dict().get('_login_user_id_', '') + self.phone = self.s.cookies.get_dict().get('_login_mobile_', '') + mobile = self.phone[:3] + "*" * 4 + self.phone[7:] + if self.phone != '': + Log(f'用户:【{mobile}】登陆成功') + return True + else: + Log(f'获取用户信息失败') + return False + def getSign(self): + timestamp = str(int(round(time.time() * 1000))) + token = 'wwesldfs29aniversaryvdld29' + sysCode = 'MCS-MIMP-CORE' + data = f'token={token}×tamp={timestamp}&sysCode={sysCode}' + signature = hashlib.md5(data.encode()).hexdigest() + data = { + 'sysCode': sysCode, + 'timestamp': timestamp, + 'signature': signature + } + self.headers.update(data) + return data + def do_request(self, url, data = {}, req_type = 'post'): + self.getSign() + try: + if req_type.lower() == 'get': + response = self.s.get(url, headers=self.headers) + elif req_type.lower() == 'post': + response = self.s.post(url, headers=self.headers, json=data) + else: + raise ValueError('Invalid req_type: %s' % req_type) + res = response.json() + return res + except requests.exceptions.RequestException as e: + print('Request failed:', e) + return None + except json.JSONDecodeError as e: + print('JSON decoding failed:', e) + return None + + + def sign(self): + print(f'>>>>>>开始执行签到') + json_data = {"comeFrom":"vioin","channelFrom":"WEIXIN"} + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskSignPlusService~automaticSignFetchPackage' + response = self.do_request(url, data=json_data) + # print(response) + if response.get('success') == True: + count_day = response.get('obj',{}).get('countDay',0) + if response.get('obj') and response['obj'].get('integralTaskSignPackageVOList'): + packet_name = response["obj"]["integralTaskSignPackageVOList"][0]["packetName"] + Log(f'>>>签到成功,获得【{packet_name}】,本周累计签到【{count_day+1}】天') + else: + Log(f'今日已签到,本周累计签到【{count_day+1}】天') + else: + print(f'签到失败!原因:{response.get("errorMessage")}') + + def superWelfare_receiveRedPacket(self): + print(f'>>>>>>超值福利签到') + json_data = { + 'channel': 'czflqdlhbxcx' + } + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberActLengthy~redPacketActivityService~superWelfare~receiveRedPacket' + response = self.do_request(url,data=json_data) + # print(response) + if response.get('success') == True: + gift_list = response.get('obj', {}).get('giftList', []) + if response.get('obj', {}).get('extraGiftList', []): + gift_list.extend(response['obj']['extraGiftList']) + gift_names = ', '.join([gift['giftName'] for gift in gift_list]) + receive_status = response.get('obj', {}).get('receiveStatus') + status_message = '领取成功' if receive_status == 1 else '已领取过' + Log(f'超值福利签到[{status_message}]: {gift_names}') + else: + error_message = response.get('errorMessage') or json.dumps(response) or '无返回' + print(f'超值福利签到失败: {error_message}') + + def get_SignTaskList(self,END=False): + if not END:print(f'>>>开始获取签到任务列表') + json_data = { + 'channelType': '3', + 'deviceId': self.get_deviceId(), + } + url='https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskStrategyService~queryPointTaskAndSignFromES' + response = self.do_request(url,data=json_data) + # print(response) + if response.get('success') == True and response.get('obj') !=[]: + totalPoint = response["obj"]["totalPoint"] + if END: + Log(f'当前积分:【{totalPoint}】') + return + Log(f'执行前积分:【{totalPoint}】') + for task in response["obj"]["taskTitleLevels"]: + self.taskId = task["taskId"] + self.taskCode = task["taskCode"] + self.strategyId = task["strategyId"] + self.title = task["title"] + status = task["status"] + skip_title = ['用行业模板寄件下单','去新增一个收件偏好','参与积分活动'] + if status == 3: + print(f'>{self.title}-已完成') + continue + if self.title in skip_title: + print(f'>{self.title}-跳过') + continue + else: + # print("taskId:", taskId) + # print("taskCode:", taskCode) + # print("----------------------") + # self.doTask() + time.sleep(3) + self.receiveTask() + + def doTask(self): + print(f'>>>开始去完成【{self.title}】任务') + json_data = { + 'taskCode': self.taskCode, + } + url='https://mcs-mimp-web.sf-express.com/mcs-mimp/commonRoutePost/memberEs/taskRecord/finishTask' + response = self.do_request(url,data=json_data) + if response.get('success') == True: + print(f'>【{self.title}】任务-已完成') + else: + print(f'>【{self.title}】任务-{response.get("errorMessage")}') + + def receiveTask(self): + print(f'>>>开始领取【{self.title}】任务奖励') + json_data = { + "strategyId": self.strategyId, + "taskId": self.taskId, + "taskCode": self.taskCode, + "deviceId": self.get_deviceId() + } + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~integralTaskStrategyService~fetchIntegral' + response = self.do_request(url, data=json_data) + if response.get('success') == True: + print(f'>【{self.title}】任务奖励领取成功!') + else: + print(f'>【{self.title}】任务-{response.get("errorMessage")}') + + def do_honeyTask(self): + # 做任务 + json_data = {"taskCode": self.taskCode} + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberEs~taskRecord~finishTask' + response = self.do_request(url, data=json_data) + if response.get('success') == True: + print(f'>【{self.taskType}】任务-已完成') + else: + print(f'>【{self.taskType}】任务-{response.get("errorMessage")}') + + def receive_honeyTask(self): + print('>>>执行收取丰蜜任务') + # 收取 + self.headers['syscode']='MCS-MIMP-CORE' + self.headers['channel']='wxwdsj' + self.headers['accept']='application/json, text/plain, */*' + self.headers['content-type']='application/json;charset=UTF-8' + self.headers['platform']='MINI_PROGRAM' + json_data = {"taskType": self.taskType} + # print(json_data) + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~receiveExchangeIndexService~receiveHoney' + response = self.do_request(url, data=json_data) + if response.get('success') == True: + print(f'收取任务【{self.taskType}】成功!') + else: + print(f'收取任务【{self.taskType}】失败!原因:{response.get("errorMessage")}') + + def get_coupom(self): + print('>>>执行领取生活权益领券任务') + # 领取生活权益领券 + # https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberGoods~pointMallService~createOrder + + json_data = { + "from": "Point_Mall", + "orderSource": "POINT_MALL_EXCHANGE", + "goodsNo": self.goodsNo, + "quantity": 1, + "taskCode": self.taskCode + } + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberGoods~pointMallService~createOrder' + response = self.do_request(url, data=json_data) + if response.get('success') == True: + print(f'>领券成功!') + else: + print(f'>领券失败!原因:{response.get("errorMessage")}') + + def get_coupom_list(self): + print('>>>获取生活权益券列表') + # 领取生活权益领券 + # https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberGoods~pointMallService~createOrder + + json_data = { + "memGrade": 1, + "categoryCode": "SHTQ", + "showCode": "SHTQWNTJ" + } + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberGoods~mallGoodsLifeService~list' + response = self.do_request(url, data=json_data) + # print(response) + if response.get('success') == True: + goodsList = response["obj"][0]["goodsList"] + for goods in goodsList: + exchangeTimesLimit = goods['exchangeTimesLimit'] + if exchangeTimesLimit >= 7: + self.goodsNo = goods['goodsNo'] + print(f'当前选择券号:{self.goodsNo}') + self.get_coupom() + break + else: + print(f'>领券失败!原因:{response.get("errorMessage")}') + + def get_honeyTaskListStart(self): + print('>>>开始获取采蜜换大礼任务列表') + # 任务列表 + json_data = {} + self.headers['channel']='wxwdsj' + url ='https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~receiveExchangeIndexService~taskDetail' + + response = self.do_request(url, data=json_data) + # print(response) + if response.get('success') == True: + for item in response["obj"]["list"]: + self.taskType = item["taskType"] + status = item["status"] + if status == 3: + print(f'>【{self.taskType}】-已完成') + if self.taskType == 'BEES_GAME_TASK_TYPE': + self.bee_need_help = False + continue + if "taskCode" in item: + self.taskCode = item["taskCode"] + if self.taskType == 'DAILY_VIP_TASK_TYPE': + self.get_coupom_list() + else: + self.do_honeyTask() + if self.taskType == 'BEES_GAME_TASK_TYPE': + self.honey_damaoxian() + time.sleep(2) + + def honey_damaoxian(self): + print('>>>执行大冒险任务') + # 大冒险 + gameNum = 5 + for i in range(1,gameNum): + json_data = { + 'gatherHoney': 20, + } + if gameNum < 0 :break + print(f'>>开始第{i}次大冒险') + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~receiveExchangeGameService~gameReport' + response = self.do_request(url, data=json_data) + # print(response) + stu = response.get('success') + if stu: + gameNum = response.get('obj')['gameNum'] + print(f'>大冒险成功!剩余次数【{gameNum}】') + time.sleep(2) + gameNum -= 1 + else: + print(f'>大冒险失败!【{response.get("errorMessage")}】') + break + + def honey_indexData(self,END=False): + if not END:print('\n>>>>>>>开始执行采蜜换大礼任务') + # 邀请 + random_invite = random.choice([invite for invite in inviteId if invite != self.user_id]) + self.headers['channel'] = 'wxwdsj' + json_data = {"inviteUserId": random_invite} + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~receiveExchangeIndexService~indexData' + response = self.do_request(url, data=json_data) + if response.get('success') == True: + usableHoney = response.get('obj').get('usableHoney') + if END: + Log(f'当前丰蜜:【{usableHoney}】') + return + Log(f'执行前丰蜜:【{usableHoney}】') + taskDetail = response.get('obj').get('taskDetail') + activityEndTime = response.get('obj').get('activityEndTime','') + activity_end_time = datetime.strptime(activityEndTime, "%Y-%m-%d %H:%M:%S") + current_time = datetime.now() + + if current_time.date() == activity_end_time.date(): + Log("本期活动今日结束,请及时兑换") + else: + print(f'本期活动结束时间【{activityEndTime}】') + + if taskDetail != []: + for task in taskDetail: + self.taskType = task['type'] + self.receive_honeyTask() + time.sleep(2) + + + + def EAR_END_2023_TaskList(self): + print('\n>>>>>>开始年终集卡任务') + # 任务列表 + json_data = { + "activityCode": "YEAR_END_2023", + "channelType": "MINI_PROGRAM" + } + self.headers['channel']='xcx23nz' + self.headers['platform']='MINI_PROGRAM' + self.headers['syscode']='MCS-MIMP-CORE' + + url ='https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~activityTaskService~taskList' + + response = self.do_request(url, data=json_data) + # print(response) + if response.get('success') == True: + for item in response["obj"]: + self.title = item["taskName"] + self.taskType = item["taskType"] + status = item["status"] + if status == 3: + print(f'>【{self.taskType}】-已完成') + continue + if self.taskType == 'INTEGRAL_EXCHANGE': + self.EAR_END_2023_ExchangeCard() + elif self.taskType == 'CLICK_MY_SETTING': + self.taskCode = item["taskCode"] + self.addDeliverPrefer() + if "taskCode" in item: + self.taskCode = item["taskCode"] + self.doTask() + time.sleep(3) + self.EAR_END_2023_receiveTask() + else: + print(f'暂时不支持【{self.title}】任务') + # if self.taskType == 'BEES_GAME_TASK_TYPE': + # self.honey_damaoxian() + self.EAR_END_2023_getAward() + self.EAR_END_2023_GuessIdiom() + + def addDeliverPrefer(self): + print(f'>>>开始【{self.title}】任务') + json_data = { + "country": "中国", + "countryCode": "A000086000", + "province": "北京市", + "provinceCode": "A110000000", + "city": "北京市", + "cityCode": "A111000000", + "county": "东城区", + "countyCode": "A110101000", + "address": "1号楼1单元101", + "latitude": "", + "longitude": "", + "memberId": "", + "locationCode": "010", + "zoneCode": "CN", + "postCode": "", + "takeWay": "7", + "callBeforeDelivery": 'false', + "deliverTag": "2,3,4,1", + "deliverTagContent": "", + "startDeliverTime": "", + "selectCollection": 'false', + "serviceName": "", + "serviceCode": "", + "serviceType": "", + "serviceAddress": "", + "serviceDistance": "", + "serviceTime": "", + "serviceTelephone": "", + "channelCode": "RW11111", + "taskId": self.taskId, + "extJson": "{\"noDeliverDetail\":[]}" + } + url = 'https://ucmp.sf-express.com/cx-wechat-member/member/deliveryPreference/addDeliverPrefer' + response = self.do_request(url, data=json_data) + if response.get('success') == True: + print('新增一个收件偏好,成功') + else: + print(f'>【{self.title}】任务-{response.get("errorMessage")}') + + def EAR_END_2023_ExchangeCard(self): + print(f'>>>开始积分兑换年卡') + json_data = { + "exchangeNum": 2, + "activityCode": "YEAR_END_2023", + "channelType": "MINI_PROGRAM" + } + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonNoLoginPost/~memberNonactivity~yearEnd2023TaskService~integralExchange' + response = self.do_request(url, data=json_data) + if response.get('success') == True: + receivedAccountList = response['obj']['receivedAccountList'] + for card in receivedAccountList: + print(f'>获得:【{card["urrency"]}】卡【{card["amount"]}】张!') + else: + print(f'>【{self.title}】任务-{response.get("errorMessage")}') + + def EAR_END_2023_getAward(self): + print(f'>>>开始抽卡') + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~yearEnd2023GardenPartyService~getAward' + for l in range(10): + for i in range(0,3): + json_data = { + "cardType": i + } + response = self.do_request(url, data=json_data) + # print(response) + if response.get('success') == True: + receivedAccountList = response['obj']['receivedAccountList'] + for card in receivedAccountList: + print(f'>获得:【{card["currency"]}】卡【{card["amount"]}】张!') + elif response.get('errorMessage') == '达到限流阈值,请稍后重试': + break + elif response.get('errorMessage') == '用户信息失效,请退出重新进入': + break + else: + print(f'>抽卡失败:{response.get("errorMessage")}') + time.sleep(3) + + def EAR_END_2023_GuessIdiom(self): + print(f'>>>开始猜成语') + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~yearEnd2023GuessIdiomService~win' + for i in range(1,11): + json_data = { + "index": i + } + response = self.do_request(url, data=json_data) + if response.get('success') == True: + print(f'第{i}关成功!') + # receivedAccountList = response['obj']['receivedAccountList'] + # for card in receivedAccountList: + # print(f'>获得:【{card["urrency"]}】卡【{card["amount"]}】张!') + else: + print(f'第{i}关失败!') + + def EAR_END_2023_receiveTask(self): + print(f'>>>开始领取【{self.title}】任务奖励') + json_data = { + "taskType": self.taskType, + "activityCode": "YEAR_END_2023", + "channelType": "MINI_PROGRAM" + } + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonNoLoginPost/~memberNonactivity~yearEnd2023TaskService~fetchMixTaskReward' + response = self.do_request(url, data=json_data) + if response.get('success') == True: + print(f'>【{self.title}】任务奖励领取成功!') + else: + print(f'>【{self.title}】任务-{response.get("errorMessage")}') + + def anniversary2024_weekly_gift_status(self): + print(f'\n>>>>>>>开始周年庆任务') + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024IndexService~weeklyGiftStatus' + response = self.do_request(url) + if response.get('success') == True: + weekly_gift_list = response.get('obj', {}).get('weeklyGiftList', []) + for weekly_gift in weekly_gift_list: + if not weekly_gift.get('received'): + receive_start_time = datetime.strptime(weekly_gift['receiveStartTime'], '%Y-%m-%d %H:%M:%S') + receive_end_time = datetime.strptime(weekly_gift['receiveEndTime'], '%Y-%m-%d %H:%M:%S') + current_time = datetime.now() + # print(current_time) + # print(receive_start_time) + # print(receive_end_time) + if receive_start_time <= current_time <= receive_end_time: + self.anniversary2024_receive_weekly_gift() + else: + error_message = response.get('errorMessage') or json.dumps(response) or '无返回' + print(f'查询每周领券失败: {error_message}') + if '系统繁忙' in error_message or '用户手机号校验未通过' in error_message: + self.anniversary_black = True + def anniversary2024_receive_weekly_gift(self): + print(f'>>>开始领取每周领券') + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024IndexService~receiveWeeklyGift' + response = self.do_request(url) + if response.get('success'): + product_names = [product['productName'] for product in response.get('obj', [])] + print(f'每周领券: {product_names}') + else: + error_message = response.get('errorMessage') or json.dumps(response) or '无返回' + print( f'每周领券失败: {error_message}') + if '系统繁忙' in error_message or '用户手机号校验未通过' in error_message: + self.anniversary_black = True + + def anniversary2024_taskList(self): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~activityTaskService~taskList' + data = { + 'activityCode': 'ANNIVERSARY_2024', + 'channelType': 'MINI_PROGRAM' + } + response = self.do_request(url, data) + if response and response.get('success'): + tasks = response.get('obj', []) + # 过滤出状态为1的任务并尝试接收奖励 + for task in filter(lambda x: x['status'] == 1, tasks): + if self.anniversary_black: + return + for _ in range(task['canReceiveTokenNum']): + self.anniversary2024_fetchMixTaskReward(task) + # 过滤出状态为2的任务并完成任务 + for task in filter(lambda x: x['status'] == 2, tasks): + if self.anniversary_black: + return + if task['taskType'] in ['PLAY_ACTIVITY_GAME', 'PLAY_HAPPY_ELIMINATION', 'PARTAKE_SUBJECT_GAME']: + pass + elif task['taskType'] == 'FOLLOW_SFZHUNONG_VEDIO_ID': + pass + elif task['taskType'] in ['BROWSE_VIP_CENTER', 'GUESS_GAME_TIP', 'CREATE_SFID', 'CLICK_MY_SETTING', 'CLICK_TEMPLATE', 'REAL_NAME', 'SEND_SUCCESS_RECALL', 'OPEN_SVIP', 'OPEN_FAST_CARD', 'FIRST_CHARGE_NEW_EXPRESS_CARD', 'CHARGE_NEW_EXPRESS_CARD', 'INTEGRAL_EXCHANGE']: + pass + else: + for _ in range(task['restFinishTime']): + if self.anniversary_black: + break + self.anniversary2024_finishTask(task) + def anniversary2024_finishTask(self, task): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonRoutePost/memberEs/taskRecord/finishTask' + data = {'taskCode': task['taskCode']} + response = self.do_request(url, data) + if response and response.get('success'): + print('完成任务[%s]成功' % task['taskName']) + # 完成任务后获取任务奖励的逻辑 + self.anniversary2024_fetchMixTaskReward(task) + else: + print('完成任务[%s]失败: %s' % (task['taskName'], response.get('errorMessage') or (json.dumps(response) if response else '无返回'))) + + def anniversary2024_fetchMixTaskReward(self, task): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024TaskService~fetchMixTaskReward' + data = { + 'taskType': task['taskType'], + 'activityCode': 'ANNIVERSARY_2024', + 'channelType': 'MINI_PROGRAM' + } + response = self.do_request(url, data) + if response and response.get('success'): + reward_info = response.get('obj', {}).get('account', {}) + received_list = [f"[{item['currency']}]X{item['amount']}" for item in + reward_info.get('receivedAccountList', [])] + turned_award = reward_info.get('turnedAward', {}) + if turned_award.get('productName'): + received_list.append(f"[优惠券]{turned_award['productName']}") + print('领取任务[%s]奖励: %s' % (task['taskName'], ', '.join(received_list))) + else: + error_message = response.get('errorMessage') or json.dumps(response) or '无返回' + print('领取任务[%s]奖励失败: %s' % (task['taskName'], error_message)) + if '用户手机号校验未通过' in error_message: + self.anniversary_black = True + + def anniversary2024_unbox(self): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024CardService~unbox' + response = self.do_request(url, {}) + if response and response.get('success'): + account_info = response.get('obj', {}).get('account', {}) + unbox_list = [f"[{item['currency']}]X{item['amount']}" for item in + account_info.get('receivedAccountList', [])] + print('拆盒子: %s' % ', '.join(unbox_list) or '空气') + else: + error_message = response.get('errorMessage') or json.dumps(response) or '无返回' + print('拆盒子失败: %s' % error_message) + if '用户手机号校验未通过' in error_message: + self.anniversary_black = True + + def anniversary2024_game_list(self): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024GameParkService~list' + response = self.do_request(url, {}) + try: + if response['success']: + topic_pk_info = response['obj'].get('topicPKInfo', {}) + search_word_info = response['obj'].get('searchWordInfo', {}) + happy_elimination_info = response['obj'].get('happyEliminationInfo', {}) + + if not topic_pk_info.get('isPassFlag'): + print('开始话题PK赛') + # 这里调用话题PK赛列表相关函数 + self.anniversary2024_TopicPk_topicList() + + if not search_word_info.get('isPassFlag') or not search_word_info.get('isFinishDailyFlag'): + print('开始找字游戏') + for i in range(1, 11): + wait_time = random.randint(1000, 3000) / 1000.0 # 转换为秒 + time.sleep(wait_time) + if not self.anniversary2024_SearchWord_win(i): + break + + if not happy_elimination_info.get('isPassFlag') or not happy_elimination_info.get('isFinishDailyFlag'): + print('开始消消乐') + for i in range(1, 31): + wait_time = random.randint(2000, 4000) / 1000.0 # 转换为秒 + time.sleep(wait_time) + if not self.anniversary2024_HappyElimination_win(i): + break + else: + error_message = response['errorMessage'] or json.dumps(response) or '无返回' + print('查询游戏状态失败: ' + error_message) + if '用户手机号校验未通过' in error_message: + self.anniversary_black = True + except Exception as e: + print(str(e)) + + def anniversary2024_SearchWord_win(self, index): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024SearchWordService~win' + success = True + try: + data = {'index': index} + response = self.do_request(url, data) + if response and response.get('success'): + currency_list = response.get('obj', {}).get('currencyDTOList', []) + rewards = ', '.join([f"[{c.get('currency')}]X{c.get('amount')}" for c in currency_list]) + print(f'找字游戏第{index}关通关成功: {rewards if rewards else "未获得奖励"}') + else: + error_message = response.get('errorMessage') or json.dumps(response) or '无返回' + print(f'找字游戏第{index}关失败: {error_message}') + if '系统繁忙' in error_message: + success = False + except Exception as e: + print(e) + finally: + return success + + def anniversary2024_HappyElimination_win(self, index): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024HappyEliminationService~win' + success = True + data = {'index': index} + response = self.do_request(url, data) + try: + if response and response.get('success'): + is_award = response['obj'].get('isAward') + currency_dto_list = response['obj'].get('currencyDTOList', []) + rewards = ', '.join([f"[{c.get('currency')}]X{c.get('amount')}" for c in currency_dto_list]) + print(f'第{index}关通关: {rewards if rewards else "未获得奖励"}') + else: + error_message = response.get('errorMessage') or json.dumps(response) or '无返回' + print(f'第{index}关失败: {error_message}') + if '系统繁忙' in error_message: + success = False + except Exception as e: + print(e) + success = False + finally: + return success + + def anniversary2024_TopicPk_chooseSide(self, index): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024TopicPkService~chooseSide' + success = True + data = {'index': index, 'choose': 0} # 选择某一边 + response = self.do_request(url, data) + try: + if response and response.get('success'): + currency_dto_list = response['obj'].get('currencyDTOList', []) + rewards = ', '.join([f"[{c.get('currency')}]X{c.get('amount')}" for c in currency_dto_list]) + print(f'话题PK赛选择话题{index}成功: {rewards if rewards else "未获得奖励"}') + else: + error_message = response['errorMessage'] or json.dumps(response) or '无返回' + print(f'话题PK赛选择话题{index}失败: {error_message}') + if '系统繁忙' in error_message: + success = False + except Exception as e: + print(e) + success = False + finally: + return success + + def anniversary2024_TopicPk_topicList(self): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024TopicPkService~topicList' + response = self.do_request(url, {}) + try: + if response and response.get('success'): + topics = response['obj'].get('topics', []) + for topic in topics: + if not topic.get('choose'): + index = topic.get('index', 1) + wait_time = random.randint(2000, 4000) / 1000.0 # 转换为秒 + time.sleep(wait_time) # 等待 + if not self.anniversary2024_TopicPk_chooseSide(index): + break + else: + error_message = response['errorMessage'] or json.dumps(response) or '无返回' + print(f'查询话题PK赛记录失败: {error_message}') + except Exception as e: + print(e) + + def anniversary2024_queryAccountStatus_refresh(self): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024CardService~queryAccountStatus' + response = self.do_request(url, {}) + try: + if not response or not response.get('success'): + error_message = response['errorMessage'] or json.dumps(response) or '无返回' + print(f'查询账户状态失败: {error_message}') + except Exception as e: + print(e) + + def anniversary2024_TopicPk_chooseSide(self, index): + success = True + data = { + 'index': index, + 'choose': 0 + } + self.headers['channel'] = '31annizyw' + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024TopicPkService~chooseSide' + result = self.do_request(url, data, 'post') + + if result and result.get('success'): + currency_dto_list = result.get('obj', {}).get('currencyDTOList', []) + if currency_dto_list: + rewards = [f"[{currency['currency']}]{currency['amount']}次" for currency in currency_dto_list] + print(f'话题PK赛第{index}个话题选择成功: {", ".join(rewards)}') + else: + print(f'话题PK赛第{index}个话题选择成功') + else: + error_message = result.get('errorMessage') if result else '无返回' + print(f'话题PK赛第{index}个话题失败: {error_message}') + if error_message and '系统繁忙' in error_message: + success = False + + return success + + def anniversary2024_titleList(self): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024GuessService~titleList' + response = self.do_request(url) + + if response and response.get('success'): + + guess_title_info_list = response.get('obj', {}).get('guessTitleInfoList', []) + today_titles = [title for title in guess_title_info_list if title['gameDate'] == self.today] + for title_info in today_titles: + if title_info['answerStatus']: + print('今日已回答过竞猜') + else: + answer = self.answer + if answer: + self.anniversary2024_answer(title_info, answer) + print(f'进行了答题: {answer}') + else: + error_message = response.get('errorMessage') if response else '无返回' + print(f'查询每日口令竞猜失败: {error_message}') + + def anniversary2024_titleList_award(self): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024GuessService~titleList' + response = self.do_request(url) + + if response and response.get('success'): + + guess_title_info_list = response.get('obj', {}).get('guessTitleInfoList', []) + today_awards = [title for title in guess_title_info_list if title['gameDate'] == self.today] + + for award_info in today_awards: + if award_info['answerStatus']: + awards = award_info.get('awardList', []) + award_info.get('puzzleList', []) + awards_description = ', '.join([f"{award['productName']}" for award in awards]) + print(f'口令竞猜奖励: {awards_description}' if awards_description else '今日无奖励') + else: + print('今日还没回答竞猜') + else: + error_message = response.get('errorMessage') if response else '无返回' + print(f'查询每日口令竞猜奖励失败: {error_message}') + + # 向API发送答题请求 + def anniversary2024_answer(self, answer_info): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024GuessService~answer' + data = {'period': answer_info['period'], 'answerInfo': answer_info} + response = self.do_request(url, data) + if response and response.get('success'): + print('口令竞猜回答成功') + self.anniversary2024_titleList_award() # 通过奖励接口验证答案 + else: + error_message = response.get('errorMessage') if response else '无返回' + print(f'口令竞猜回答失败: {error_message}') + + # 查询账户状态 + def anniversary2024_queryAccountStatus(self): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024CardService~queryAccountStatus' + result = self.do_request(url) + if result.get('success'): + account_currency_list = result.get('obj', {}).get('accountCurrencyList', []) + unbox_chance_currency = [currency for currency in account_currency_list if + currency.get('currency') == 'UNBOX_CHANCE'] + unbox_chance_balance = unbox_chance_currency[0].get('balance') if unbox_chance_currency else 0 + + # print('可以拆' + str(unbox_chance_balance) + '次盒子') + # while unbox_chance_balance > 0: + # self.anniversary2024_unbox() + # unbox_chance_balance -= 1 + else: + error_message = result.get('errorMessage') or json.dumps(result) or '无返回' + print('查询已收集拼图失败: ' + error_message) + + result = self.do_request(url) + if result.get('success'): + account_currency_list = result.get('obj', {}).get('accountCurrencyList', []) + account_currency_list = [currency for currency in account_currency_list if + currency.get('currency') != 'UNBOX_CHANCE'] + if account_currency_list: + cards_li = account_currency_list + card_info = [] + self.cards = { + 'CARD_1': 0, + 'CARD_2': 0, + 'CARD_3': 0, + 'CARD_4': 0, + 'CARD_5': 0, + 'CARD_6': 0, + 'CARD_7': 0, + 'CARD_8': 0, + 'CARD_9': 0, + 'COMMON_CARD': 0 + } + for card in cards_li: + currency_key = card.get('currency') + if currency_key in self.cards: + self.cards[currency_key] = int(card.get('balance')) + card_info.append('[' + card.get('currency') + ']X' + str(card.get('balance'))) + + Log(f'已收集拼图: {card_info}' ) + cards_li.sort(key=lambda x: x.get('balance'), reverse=True) + + else: + print('还没有收集到拼图') + else: + error_message = result.get('errorMessage') or json.dumps(result) or '无返回' + print('查询已收集拼图失败: ' + error_message) + + def do_draw(self, cards): + url = 'https://mcs-mimp-web.sf-express.com/mcs-mimp/commonPost/~memberNonactivity~anniversary2024CardService~collectDrawAward' + data = {"accountList":cards} + response = self.do_request(url, data) + if response and response.get('success'): + data = response.get('obj',{}) + productName = data.get('productName','') + Log(f'抽奖成功,获得{productName}') + return True + else: + error_message = response.get('errorMessage') if response else '无返回' + print(f'抽奖失败: {error_message}') + return False + + def convert_common_card(self,cards, target_card): + # 如果共通卡(COMMON_CARD)的数量大于0,转化成目标卡 + if cards['COMMON_CARD'] > 0: + cards['COMMON_CARD'] -= 1 + cards[target_card] += 1 + return True + return False + + def can_draw(self,cards, n): + # 判断是否有足够的不同卡进行抽奖 + distinct_cards = sum(1 for card, amount in cards.items() if card != 'COMMON_CARD' and amount > 0) + return distinct_cards >= n + + + def draw(self,cards, n): + drawn_cards = [] + for card, amount in sorted(cards.items(), key=lambda item: item[1]): + if card != 'COMMON_CARD' and amount > 0: + cards[card] -= 1 + drawn_cards.append(card) + if len(drawn_cards) == n: + break + if len(drawn_cards) == n: + "没有足够的卡进行抽奖" + if self.do_draw(drawn_cards): + return drawn_cards # 返回本次抽奖使用的卡 + else: + return None + + def simulate_lottery(self,cards): + while self.can_draw(cards, 9): + used_cards = self.draw(cards, 9) + print("进行了一次9卡抽奖,消耗卡片: ", used_cards) + while self.can_draw(cards, 7) or self.convert_common_card(cards, 'CARD_1'): + if not self.can_draw(cards, 7): + continue + used_cards = self.draw(cards, 7) + print("进行了一次7卡抽奖,消耗卡片: ", used_cards) + while self.can_draw(cards, 5) or self.convert_common_card(cards, 'CARD_1'): + if not self.can_draw(cards, 5): + continue + used_cards = self.draw(cards, 5) + print("进行了一次5卡抽奖,消耗卡片: ", used_cards) + while self.can_draw(cards, 3) or self.convert_common_card(cards, 'CARD_1'): + if not self.can_draw(cards, 3): + continue + used_cards = self.draw(cards, 3) + print("进行了一次3卡抽奖,消耗卡片: ", used_cards) + + def anniversary2024_task(self): + self.anniversary2024_weekly_gift_status() + if self.anniversary_black: + return + # self.anniversary2024_titleList() + # self.anniversary2024_game_list() + # self.anniversary2024_taskList() + self.anniversary2024_queryAccountStatus() + target_time = datetime(2024, 4, 3, 14, 0) + # self.simulate_lottery(self.cards) + if datetime.now() > target_time: + print('周年庆活动即将结束,开始自动抽奖') + self.simulate_lottery(self.cards) + else: + print('未到自动抽奖时间') + + + + def main(self): + global one_msg + wait_time = random.randint(1000, 3000) / 1000.0 # 转换为秒 + time.sleep(wait_time) # 等待 + one_msg = '' + if not self.login_res:return False + # 执行签到任务 + self.sign() + self.superWelfare_receiveRedPacket() + self.get_SignTaskList() + self.get_SignTaskList(True) + + #执行丰蜜任务 + self.honey_indexData() + #获取任务列表并执行任务 + self.get_honeyTaskListStart() + self.honey_indexData(True) + # # 获取当前季度结束日期 + # activity_end_date = get_quarter_end_date() + # if is_activity_end_date(activity_end_date): + # Log("今天采蜜活动截止兑换,请及时进行兑换") + # send('顺丰速运挂机通知', "今天采蜜活动截止兑换,请及时进行兑换") + target_time = datetime(2024, 4, 8, 19, 0) + if datetime.now() < target_time: + # self.EAR_END_2023_TaskList() + self.anniversary2024_task() + else: + print('周年庆活动已结束') + self.sendMsg() + return True + + def sendMsg(self, help=False): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME, help) + print(push_res) + + + +def get_quarter_end_date(): + current_date = datetime.now() + current_month = current_date.month + current_year = current_date.year + + # 计算下个季度的第一天 + next_quarter_first_day = datetime(current_year, ((current_month - 1) // 3 + 1) * 3 + 1, 1) + + # 计算当前季度的最后一天 + quarter_end_date = next_quarter_first_day - timedelta(days=1) + + return quarter_end_date.strftime("%Y-%m-%d") + +def is_activity_end_date(end_date): + current_date = datetime.now().date() + end_date = datetime.strptime(end_date, "%Y-%m-%d").date() + + return current_date == end_date + + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + +if __name__ == '__main__': + APP_NAME = '顺丰速运' + ENV_NAME = 'SFSY' + CK_NAME = 'url' + print(f''' +✨✨✨ {APP_NAME}脚本✨✨✨ +✨ 功能: + 积分签到 + 签到任务 + 采蜜任务 + 周年庆集卡 +✨ 抓包步骤: + 打开{APP_NAME}APP或小程序 + 点击我的 + 打开抓包工具 + 点击“积分”,以下几种url之一: + https://mcs-mimp-web.sf-express.com/mcs-mimp/share/weChat/shareGiftReceiveRedirect + https://mcs-mimp-web.sf-express.com/mcs-mimp/share/app/shareRedirect + 多账号#分割 +✨ ✨✨wxpusher一对一推送功能, + ✨需要定义变量export WXPUSHER=wxpusher的app_token,不设置则不启用wxpusher一对一推送 + ✨需要在{ENV_NAME}变量最后添加@wxpusher的UID +✨ 设置青龙变量: +export {ENV_NAME}='url'多账号#分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨✨✨ @Author CHERWIN✨✨✨ + ''') + + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = token.split('#') + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + for index, infos in enumerate(tokens): + run_result = RUN(infos, index).main() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) + diff --git a/TYQH.py b/TYQH.py new file mode 100755 index 0000000..db4caf3 --- /dev/null +++ b/TYQH.py @@ -0,0 +1,1237 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# @Author : cherwin +# ------------------------------- +# cron "23 7-23/2 * * * " script-path=xxx.py,tag=匹配cron用 +# const $ = new Env('统一快乐星球小程序-茄皇的家') +import hashlib +import json +import os +import random +import string +import time +from datetime import datetime +from os import environ, path + +import requests +from requests.packages.urllib3.exceptions import InsecureRequestWarning + +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) + +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV + +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +USER_INFO = {} + +class RUN: + def __init__(self, info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + self.third_id = split_info[0] + self.wid = split_info[1] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + self.send_UID = last_info + + self.user_index = index + 1 + print(f"\n---------开始执行第{self.user_index}个账号>>>>>") + self.s = requests.session() + self.s.verify = False + + self.UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF WindowsWechat(0x6309080f) XWEB/8555' + + self.headers = { + 'User-Agent': self.UA, + 'Sec-Fetch-Site': 'cross-site', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Dest': 'empty', + 'Accept-Encoding': 'gzip, deflate, br', + 'Accept-Language': 'zh-CN,zh;q=0.9', + 'Origin': 'https://thekingoftomato.ioutu.cn', + 'Referer': 'https://thekingoftomato.ioutu.cn/' + + } + self.base_url = 'https://qiehuang-apig.xiaoyisz.com/qiehuangsecond/ga' + self.sun = 0 + self.land = {} + self.refresh_land_step = False + self.need_help_unlock = True + self.need_help_task = True + self.need_help_risk = True + + self.can_go_risk = True + self.can_add_friend = True + + self.can_help_task = True + self.can_help_risk = True + self.can_help_unlock = True + + self.all_land_unlock = True + self.all_role_unlock = True + self.help_task_config = {} + self.help_role_config = {} + self.group_step = ['发育期', '幼苗期', '开花期', '结果期', '收获期'] + self.Login_res = self.login() + + def load_json(self): + try: + with open(f"INVITE_CODE/{ENV_NAME}_INVITE_CODE.json", 'r', encoding='utf-8') as file: + data = json.load(file) + return data + except FileNotFoundError: + print("未找到文件,返回空字典") + return {} + except Exception as e: + print(f"发生错误:{e}") + return {} + + def make_request(self, url, method='post', headers={}, params={}): + if headers == {}: + headers = self.headers + if params == {}: + params = self.params + try: + if method.lower() == 'get': + response = requests.get(url, headers=headers, verify=False) + + elif method.lower() == 'post': + response = requests.post(url, headers=headers, json=params, verify=False) + else: + raise ValueError("不支持的请求方法: " + method) + return response.json() + except requests.exceptions.RequestException as e: + print("请求异常:", e) + except ValueError as e: + print("值错误或不支持的请求方法:", e) + except Exception as e: + print("发生了未知错误:", e) + + def gen_sign(self, parameters={}, body=None): + sorted_keys = sorted(parameters.keys()) + parameter_strings = [] + for key in sorted_keys: + if isinstance(parameters[key], dict): + parameter_strings.append(f"{key}={json.dumps(parameters[key])}") + else: + parameter_strings.append(f"{key}={parameters[key]}") + + current_time = int(datetime.now().timestamp() * 1000) + secret_chars = list('BxzTx45uIGT25TTHIIBU2') + last_three_digits = str(current_time)[-3:] + for digit in last_three_digits: + secret_chars.insert(int(digit), digit) + + secret = hashlib.md5(''.join(secret_chars).encode()).hexdigest() + nonce_str = ''.join(random.choices(string.ascii_letters + string.digits, k=16)) + + sign_data = { + 'client_id': 'game', + 'nonstr': nonce_str, + 'timestamp': current_time, + 'body': json.dumps(body) if body else '', + 'query': '&'.join(parameter_strings) if parameter_strings else '', + 'secret': secret + } + + sign_string = '|'.join([str(v) for v in sign_data.values()]) + sign = hashlib.md5(sign_string.encode()).hexdigest().upper() + sign_header = { + 'client_id': 'game', + 'timestamp': str(current_time), + 'nonstr': sign_data['nonstr'], + 'sign': sign + } + self.headers.update(sign_header) + return self.headers + + def login(self): + login_successful = False + try: + login_params = { + 'thirdId': self.third_id, + 'wid': self.wid + } + sign_header = self.gen_sign({}, login_params) + # print(self.headers) + # Hypothetically speaking, this is how you might perform a POST request in Python with the requests library. + response = self.s.post(f'{self.base_url}/public/api/login', json=login_params, headers=sign_header) + if response.status_code == 200: + response_data = response.json() + if response_data.get('code', -1) == 0: + auth = response_data['data']['token'] or '' + if auth: + login_successful = True + Log(f'账号【{self.user_index}】登录成功') + Authorization = {'Authorization': auth} + self.headers.update(Authorization) + else: + Log(f'账号【{self.user_index}】登录获取auth失败') + else: + print(f"登录获取auth失败[{response_data['code']}]: {response_data['message']}") + elif response.status_code == 403: + print('登录失败[403]: 黑IP了, 换个IP试试吧') + except Exception as e: + print(e) + finally: + return login_successful + + def userInfo_get(self,END=False): + print(f'获取用户[{self.user_index}]信息--->>>') + try: + sign_header = self.gen_sign() + # print(self.headers) + url = f'{self.base_url}/userInfo/get' + # 发起GET请求 + response = self.s.get(url, headers=sign_header, verify=False) + data = response.json() + code = data.get('code', -1) + if code == 0: + data = data.get('data', {}) + self.userId = data['userId'] + self.gold = int(data['gold']) + self.score = int(data['score']) + self.sun = int(data['sun']) + self.sunMax = int(data['sunMax']) + self.nickName = data['nickName'] + if self.nickName == None:self.nickName = '未命名' + new_data = { + self.userId: + { + 'name': self.nickName + } + } + USER_INFO.update(new_data) + CHERWIN_TOOLS.SAVE_INVITE_CODE(f"INVITE_CODE/{ENV_NAME}_INVITE_CODE.json", new_data) + if END: + Log(f"-----用户[{self.user_index}]信息-----\n用户Id:{self.userId}\n用户名:{self.nickName}\n调料🧂x{self.gold}\n番茄🍅x{self.score}\n阳光☀x{self.sun}\n------用户[{self.user_index}]信息END------") + else: + print(f"-----用户[{self.user_index}]信息-----\n用户Id:{self.userId}\n用户名:{self.nickName}\n调料🧂x{self.gold}\n番茄🍅x{self.score}\n阳光☀x{self.sun}\n------用户[{self.user_index}]信息END------") + + else: + error_message = data.get('message', '') + print(f"获取账号信息失败[{str(code)}]: {error_message}") + except Exception as e: + print(e) + finally: + return + + def userInfo_autoSun(self): + print('收集阳光--->>>') + sign_header = self.gen_sign() + url = f'{self.base_url}/userInfo/autoSun' + response = self.s.get(url, headers=sign_header) + data = response.json() + code = data.get('code', -1) + if code == 0: + sun = data.get('data', {}).get('sun', 0) + print(f"刷新收集到【{sun}】阳光---√") + else: + print(f"刷新收集阳光失败[{data['code']}]: {str(code)}") + + def task_get(self): + print(f'获取任务列表--->>>') + sign_header = self.gen_sign() + url = f'{self.base_url}/task/get' + response = self.s.get(url, headers=sign_header) + data = response.json() + code = data.get('code', -1) + if code == 0: + tasks = data.get('data', []) + for task in tasks: + self.task_id = task['id'] + self.task_title = task['title'] + task_status = task['status'] + self.task_progress = task.get('currentProgress', 0) + self.task_max_progress = task.get('progress', 1) + + print(f"任务:【{self.task_title}】进度:【{self.task_progress}/{self.task_max_progress}】") + if self.task_title == '邀请好友助力': + if self.task_progress == self.task_max_progress: + self.need_help_task = False + # new_data = { + # self.userId: { + # 'task_id': self.task_id, + # 'task_stu': self.can_help_task, + # 'current_progress': self.task_progress + # } + # } + # USER_INFO.update(new_data) + # CHERWIN_TOOLS.SAVE_INVITE_CODE("INVITE_CODE/QH_INVITE_CODE.json", new_data) + print(f"任务 '{self.task_title}' 【跳过】---》") + continue + elif self.task_title == '邀请新人助力': + print(f"任务 '{self.task_title}' 【跳过】---》") + continue + + if task_status == 0 and self.task_progress < self.task_max_progress: + # 此任务尚未完成,根据具体业务逻辑进行处理,如启动任务 + print(f"任务【{self.task_title}】【未完成】执行任务---》") + self.task_doTask() # 取消这行注释来执行任务 + + elif task_status == 1: + # 任务已完成但奖励未被领取,根据业务逻辑领取奖励 + print(f"任务【{self.task_title}】【已完成】领取奖励---》") + self.task_reward() # 取消这行注释来领取奖励 + else: + print(f"获取任务列表失败[{data['code']}]: {str(code)}") + + def task_doHelpTask(self,help_data): + # print('开始助力任务---》') + params = {'id': help_data["task_id"]} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/task/doTask' + response = self.s.get(url, headers=sign_header,params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + print(f"助力账号[{help_data['index']}][{help_data['name']}]成功---√") + elif '已超出' in data.get('message', ''): + self.can_help_task = False + error_message = data.get('message', '') + print(f"助力账号[{help_data['index']}][{help_data['name']}]失败[{code}]: {error_message}") + else: + error_message = data.get('message', '') + print(f"助力账号[{help_data['index']}][{help_data['name']}]失败[{code}]: {error_message}") + if '助力次数' in error_message: + self.can_help_task = False + + def task_doTask(self): + sign_header = self.gen_sign({'id': self.task_id}) + url = f'{self.base_url}/task/doTask' + params = {'id': self.task_id} + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + print(f"完成任务[{self.task_title}]成功---√") + else: + print(f"完成任务[{self.task_title}]失败[{str(code)}]: {data.get('message', '')}") + + def task_reward(self): + sign_header = self.gen_sign({'id': self.task_id}) + url = f'{self.base_url}/task/reward' + params = {'id': self.task_id} + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + print(f"领取任务[{self.task_title}]奖励成功---√") + else: + print(f"领取任务[{self.task_title}]奖励失败[{str(code)}]: {data.get('message', '')}") + + def user_role_get(self): + print('\n查询角色信息--->>>') + try: + sign_header = self.gen_sign() + url = f'{self.base_url}/user-role/get' + response = self.s.get(url, headers=sign_header) + data = response.json() + code = data.get('code', -1) + if code == 0: + data = data.get('data') + if data and data.get('isReward'): + print('可领取定时奖励,开始领取---》') + self.user_role_reward() # 此处调用 user_role_reward 函数 + for role in data.get('roleList', []): + if role['status'] > 0: + print(f"角色【{role['name']}】已解锁---√") + continue + if role['unlockType'] == 1: + if self.gold >= role['unlockNum']: + print(f"调料包充足,开始解锁角色【{role['name']}】---》") + self.user_role_goldUnlock(role) # 此处调用 user_role_goldUnlock 函数 + else: + print(f"调料包不足解锁角色【{role['name']}】---!") + elif role['unlockType'] == 2: + self.user_role_findFriendHelpInfo(role) # 此处调用 user_role_findFriendHelpInfo 函数 + else: + message = data.get('message', '') + print(f'角色信息失败【{code}】: {message}') + except Exception as e: + print(e) + + def user_role_findFriendHelpInfo(self, role): + print(f'查询角色邀请进度--->>>') + try: + params = {'userRoleId': role['id']} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/user-role/findFriendHelpInfo' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + data = data.get('data') + self.help_role_config = { + 'id': role['id'], + 'progress': len(data) if data else 0, + 'max': role['unlockNum'] + } + self.role_id = role['id'] + self.role_progress = len(data) if data else 0 + self.role_max = role['unlockNum'] + if role['unlockNum'] == len(data) if data else 0: + self.need_help_unlock=False + # new_data = { + # self.userId: + # { + # 'role_id': self.role_id, + # 'role_can_help': self.can_help_unlock, + # 'role_progress': self.role_progress, + # 'role_max': self.role_max + # } + # } + # USER_INFO.update(new_data) + # CHERWIN_TOOLS.SAVE_INVITE_CODE("INVITE_CODE/QH_INVITE_CODE.json", new_data) + print(f'查询角色【{role["name"]}】邀请进度成功---√') + else: + message = data.get('message', '') + print(f'查询角色【{role["name"]}】邀请进度失败[{code}]: {message}') + except Exception as e: + print(e) + + def user_role_friendHelpUnlock(self, help_data): + print('开始角色解锁互助--->>>') + # try: + params = {'userRoleId': help_data['role_id']} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/user-role/friendHelpUnlock' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + help_data['role_progress'] += 1 + print(f'助力账号[{help_data["index"]}][{help_data["name"]}]解锁角色成功---√') + else: + message = data.get('message', '') + print(f'助力账号[{help_data["index"]}][{help_data["name"]}]解锁角色失败[{code}]: {message}') + # except Exception as e: + # print(e) + + def user_role_goldUnlock(self, role): + print(f'解锁角色开始--->>>') + try: + params = {'roleId': role['roleId']} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/user-role/goldUnlock' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + self.gold -= role['unlockNum'] + print(f'解锁角色[{role["name"]}]成功') + self.user_role_reward() # 此处调用 user_role_reward 函数 + else: + message = data.get('message', '') + print(f'解锁角色[{role["name"]}]失败[{code}]: {message}') + except Exception as e: + print(e) + + def user_role_reward(self): + print(f'领取伴手礼--->>>') + try: + sign_header = self.gen_sign() + url = f'{self.base_url}/user-role/reward' + response = self.s.get(url, headers=sign_header) + data = response.json() + code = data.get('code', -1) + if code == 0: + data = data.get('data') + name = data.get('name') if data else 'unknown' + print(f'领取伴手礼【{name}】成功') + else: + message = data.get('message', '') + print(f'领取伴手礼失败[{code}]: {message}') + except Exception as e: + print(e) + + def user_land_get(self): + print(f'\n刷新土地信息--->>>') + try: + sign_header = self.gen_sign() + url = f'{self.base_url}/user-land/get' + response = self.s.get(url, headers=sign_header) + data = response.json() + code = data.get('code', -1) + if code == 0: + print('土地信息刷新成功---√') + for land in data.get('data', {}).get('gaUserLandList', []): + ga_user_land_list = data.get('data', {}).get('gaUserLandList', []) + for land_info in ga_user_land_list: + land_id = land_info['id'] + land_no = land_info['no'] + status = land_info['status'] + step = land_info['step'] + left_sun_count = land_info['leftSunCount'] + sum_sun_count = land_info['sumSunCount'] + sun_time = land_info['sunTime'] + sun_timestamp = land_info['sunTimestamp'] + need_sun = land_info['needSun'] + use_sun_count = land_info['useSunCount'] + unlock_gold = land_info['unlockGold'] + + if not self.land.get(land_no): + self.land[land_no] = {} + + self.land[land_no].update({ + 'id': land_id, + 'no': land_no, + 'status': status, + 'step': step, + 'leftSunCount': left_sun_count, + 'sumSunCount': sum_sun_count, + 'sunTime': sun_time, + 'sunTimestamp': sun_timestamp, + 'needSun': need_sun, + 'useSunCount': use_sun_count, + 'unlockGold': unlock_gold + }) + if land['status'] == 0: + # 检查是否应该解锁土地 + if self.gold >= land['unlockGold']: + print('开始解锁新土地---》') + self.user_land_unlock(self.land[land_no]) + else: + # print('调料包不足以解锁新土地') + self.all_land_unlock = False + else: + message = data.get('message', '') + # 这里应该是日志记录的代码 + print('获取账号信息失败[{}]: {}'.format(str(code), message)) + except Exception as e: + print(e) + + def user_land_unlock(self, land_info): + print(f'解锁土地--->>>') + try: + sign_header = self.gen_sign() + url = f'{self.base_url}/user-land/unlock' + response = self.s.get(url, headers=sign_header) + data = response.json() + code = data.get('code', -1) + if code == 0: + print(f"[{land_info['no']}号土地]解锁成功---√") + self.gold -= land_info['unlockGold'] + self.user_land_get() + else: + message = data.get('message', '') + print(f"[{land_info['no']}号土地]解锁失败[{str(code)}]:{message}") + except Exception as e: + print(e) + + def user_land_result(self, land_info): + print(f'收获番茄--->>>') + try: + params = {'no': land_info['no']} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/user-land/result' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + self.refresh_land_step = True + print(f'[{land_info["no"]}号土地]收获成功: 番茄x{data.get("data", 0)}---√') + self.user_land_get() + else: + message = data.get('message', '') + print(f"[{land_info['no']}号土地]收获失败[{str(code)}]: {message}") + except Exception as e: + print(e) + + def user_land_sow(self, land_info): + print(f'播种--->>>') + try: + params = {'no': land_info['no']} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/user-land/sow' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + self.refresh_land_step = True + print(f"[{land_info['no']}号土地]种植成功---√") + self.user_land_get() + else: + message = data.get('message', '') + print(f"[{land_info['no']}号土地]种植失败[{str(code)}]: {message}") + except Exception as e: + print(e) + + def user_land_sun(self, land_info): + print(f'撒阳光--->>>') + try: + params = {'no': land_info['no']} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/user-land/sun' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + print(f"[{land_info['no']}号土地]撒阳光成功---√") + time.sleep(1) + self.sun -= land_info['needSun'] + self.user_land_get() + else: + message = data.get('message', '') + print(f"[{land_info['no']}号土地]撒阳光失败[{str(code)}]:{message}") + except Exception as e: + print(e) + + def user_land_level(self, land_info): + print(f'浇水升级--->>>') + try: + params = {'no': land_info['no']} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/user-land/level' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + self.refresh_land_step = True + print(f"[{land_info['no']}号土地]浇水升级成功---√") + self.user_land_get() + else: + message = data.get('message', '') + print(f"[{land_info['no']}号土地]浇水升级失败[{str(code)}]: {message}") + except Exception as e: + print(e) + + def take_risk_online(self): + print(f'进入冒险页--->>>') + try: + sign_header = self.gen_sign() + url = f'{self.base_url}/take-risk/online' + response = self.s.get(url, headers=sign_header) + data = response.json() + code = data.get('code', -1) + if code != 0: + message = data.get('message', '') + print(f'进入冒险页失败{str(code)}: {message}') + else: + print(f'进入冒险页成功---√') + end = data.get('data', {}).get('end', True) + if end == True: + self.need_help_risk = False + except Exception as e: + print(e) + + def take_risk_get(self): + print(f'查询冒险次数--->>>') + try: + sign_header = self.gen_sign() + url = f'{self.base_url}/common/take-risk/get' + response = self.s.get(url, headers=sign_header) + data = response.json() + code = data.get('code', -1) + if code == 0: + self.risk_num = data.get('data', {}).get('num', 0) + if data.get('data', {}).get('complete', False) == False: + self.take_risk_up(data.get('data', {}).get('gameMapEvent')) + print(f"剩余冒险【{self.risk_num}】次") + else: + message = data.get('message', '') + print(f'查询冒险次数失败: {message}' ) + except Exception as e: + print(e) + + def take_risk_go(self): + print(f'开始冒险--->>>') + try: + sign_header = self.gen_sign() + url = f'{self.base_url}/common/take-risk/go' + response = self.s.get(url, headers=sign_header) + data = response.json() + # print(data) + code = data.get('code', -1) + if code == 0: + self.risk_num = data.get('data', {}).get('num', 0) + if data.get('data', {}).get('complete'): + game_map_event_answer_list = data.get('data', {}).get('gameMapEvent', {}).get( + 'gameMapEventAnswerList', []) + filtered_list = filter(lambda x: x.get('dropReward', {}).get('finalNum'),game_map_event_answer_list) + rewards = [] + for item in filtered_list: + reward_name = item['dropReward']['name'] + final_num = item['dropReward']['finalNum'] + rewards.append(f'{reward_name}x{final_num}') + if rewards: + print(f'冒险奖励: {rewards}---√') + else: + print('触发冒险事件没有获取奖励') + else: + # print(data.get('data', {}).get('gameMapEvent')) + self.take_risk_up(data.get('data', {}).get('gameMapEvent')) + elif code == 4000: + slideImgInfo = data.get('data', {}).get('slideImgInfo', None) + validateCount = data.get('data', {}).get('validateCount', None) + if slideImgInfo and validateCount: + print('本次冒险需要验证码') + self.can_go_risk = False + # if self.get_CapCode(slideImgInfo): + # self.checkUserCapCode() + else: + print(f"验证次数上限") + self.can_go_risk = False + else: + message = data.get('message', '') + print(f'冒险失败{code}]: {message}') + if message and '冒险暂停中' in message or code == 4000: + self.can_go_risk = False + + except Exception as e: + print(e) + + def take_risk_up(self, game_map_event): + print(f'触发冒险事件--->>>') + # try: + gameMapEventAnswerList = game_map_event.get('gameMapEventAnswerList', []) + index = random.randint(0, len(gameMapEventAnswerList) - 1) + gameMapEventAnswer = gameMapEventAnswerList[index] + json_id = gameMapEventAnswer['jsonId'] + # print(json_id) + params = {'jsonId': json_id} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/common/take-risk/up' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + self.risk_num = data.get('data', {}).get('num', 0) + print(f'剩余次数:【{self.risk_num}】') + + game_map_event_list = data.get('data', {}).get('gameMapEvent', {}).get('gameMapEventAnswerList', []) + + reward_list = [event['dropReward']['name'] + 'x' + str(event['dropReward']['finalNum']) for event in + game_map_event_list if event.get('dropReward', {}).get('finalNum')] + if reward_list: + print(f'冒险奖励: {reward_list}---√') + else: + print('触发冒险事件没有获取奖励') + else: + message = data.get('message', '') + print(f'触发冒险事件[ {json_id} ]失败{code}]: {message}') + # except Exception as e: + # print(e) + + def take_risk_reward(self): + print(f'领取冒险定时奖励--->>>') + try: + url = f'{self.base_url}/take-risk/reward' + sign_header = self.gen_sign() + response = self.s.get(url, headers=sign_header) + data = response.json() + code = data.get('code', -1) + if code == 0: + print('领取冒险定时奖励成功---√') + else: + message = data.get('message', '').replace('\r', '').split('\n') + message = ','.join(filter(lambda x: x, message)) + print(f'领取冒险定时奖励失败{code}]: {message}') + except Exception as e: + print(e) + + def randomString(self,length, chars='abcdef0123456789'): + return ''.join(random.choice(chars) for _ in range(length)) + + def friend_help_task_risk(self, friend_info): + print('开始冒险互助--->>>') + # try: + params = { + 'userId': friend_info['userId'], + 'type': 0x1, + 'randomId': self.randomString(32, '0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM') + } + sign_header = self.gen_sign(params) + url = f'{self.base_url}/friend-help/help' + response = self.s.get(url, headers=sign_header,params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + if data.get('data'): + self.can_help_risk = False + print(f"冒险助力账号[{friend_info['index']}][{friend_info['name']}]成功---√") + else: + message = data.get('message', '').replace('\r', '').split('\n') + message = ','.join(filter(lambda x: x, message)) + print(f"冒险助力账号[{friend_info['index']}][{friend_info['name']}]失败{message}") + if '助力次数' in message: + self.can_help_risk = False + elif '挂机时间已完成' in message: + friend_info['need_help_risk'] = False + # except Exception as e: + # print(e) + + def friend_help(self, friend_info): + print(f'开始阳光互助--->>>') + # try: + params = { + 'userId': friend_info['userId'], + 'type': 0x0, + 'randomId': self.randomString(32, '0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM') + } + sign_header = self.gen_sign(params) + url = f'{self.base_url}/friend-help/help' + response = self.s.get(url, headers=sign_header,params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + if data.get('data'): + # print(f"请求助力账号[{friend_info['index']}][{friend_info['name']}] 成功---√") + self.task_doHelpTask(friend_info) + else: + message = data.get('message', '').replace('\r', '').split('\n') + message = ','.join(filter(lambda x: x, message)) + print(f"请求助力账号[{friend_info['index']}][{friend_info['name']}] 失败: {message}") + if '助力次数' in message: + self.can_help_task = False + # except Exception as e: + # print(e) + + def friend_findRecommend(self): + print(f'查询添加好友列表--->>>') + try: + url = f'{self.base_url}/friend/findRecommend' + sign_header = self.gen_sign() + response = self.s.get(url, headers=sign_header) + data = response.json() + code = data.get('code', -1) + if code == 0: + print(f'查询添加好友列表成功---√') + for user_info in data.get('data', []): + if not self.can_add_friend: + print('好友已满') + break + # if len(list(filter(lambda user: user['userId'] == user_info['userId'], self.user_list))) > 0: + # continue + self.friend_addFriend(user_info) + # self.friend_deleteFriend(user_info) + else: + message = data.get('message', '') + print(f'查询添加好友列表失败{code}]: {message}') + except Exception as e: + print(e) + + def friend_addFriend(self, user_data): + print(f'添加好友--->>>') + try: + friend_user_id = user_data['userId'] + params = {'friendUserId': friend_user_id} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/friend/addFriend' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + print(f"添加好友[{user_data['nickName']}]成功---√") + else: + message = data.get('message', '') + print(f'添加好友{user_data["nickName"]}失败{code}]: {message}') + if message and '达到好友上限' in message: + self.can_add_friend = False + except Exception as e: + print(e) + + def friend_deleteFriend(self, user_data): + print(f'删除好友--->>>') + try: + friend_user_id = user_data['userId'] + params = {'friendUserId': friend_user_id} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/friend/delFriend' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + print(f"删除好友[{user_data['nickName']}]成功---√") + else: + message = data.get('message', '') + print(f'删除好友{user_data["nickName"]}失败{code}]: {message}') + except Exception as e: + print(e) + + def friend_findFriend(self): + print(f'\n查询好友列表--->>>') + try: + sign_header = self.gen_sign() + url = f'{self.base_url}/friend/findFriend' + response = self.s.get(url, headers=sign_header) + data = response.json() + code = data.get('code', -1) + if code == 0: + print(f'查询好友列表成功---√') + friend_list = data.get('data', {}).get('friendList', []) + friend_list.sort(key=lambda x: x['gold'], reverse=True) + for friend in friend_list: + if friend.get('stealFlag', False): + if not self.friend_stealGold(friend): + break + + else: + message = data.get('message', '') + print(f'查询好友列表失败[{str(code)}]:{message}') + except Exception as e: + print(e) + def get_CapCode(self,slideImgInfo): + slidingImage = slideImgInfo.get('slidingImage', None) + backImage = slideImgInfo.get('backImage', None) + if slidingImage and backImage: + slidingImage_path = 'slidingImage.png' + backImage_path = 'backImage.png' + self.capcode = CHERWIN_TOOLS.OCR_API(slidingImage,backImage) + return True + # slidingImage_res = CHERWIN_TOOLS.BASE64_TO_IMG(slidingImage, slidingImage_path) + # backImage_res = CHERWIN_TOOLS.BASE64_TO_IMG(backImage, backImage_path) + # if slidingImage_res and backImage_res: + # self.capcode = CHERWIN_TOOLS.CAPCODE(slidingImage_path, backImage_path) + # return True + # else: + # return False + else: + return False + def friend_stealGold(self, user_data): + print(f'偷取好友--->>>') + # try: + friend_user_id = user_data['userId'] + params = {'friendUserId': friend_user_id} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/friend/stealGold' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + print(f"偷取好友[{user_data['nickName']}]: 阳光x{data.get('data', 0)}") + return True + elif code == 4000: + + slideImgInfo = data.get('data', {}).get('slideImgInfo', None) + validateCount = data.get('data', {}).get('validateCount', None) + if slideImgInfo and validateCount: + print(f"偷取好友[{user_data['nickName']}],需要滑块验证") + self.can_stealGold = False + # if self.get_CapCode(slideImgInfo): + # self.checkUserCapCode() + else: + print(f"偷取好友[{user_data['nickName']}]验证码上限") + self.can_stealGold = False + else: + message = data.get('message', '') + print(f"偷取好友[{user_data['nickName']}]阳光失败[{str(code)}]: {message}") + + return False + # except Exception as e: + # print(e) + + def checkUserCapCode(self): + print(f'提交验证码--->>>') + # try: + print(f'验证码:{self.capcode}') + params = {'xpos':self.capcode} + print(params) + sign_header = self.gen_sign(body=params) + url = f'{self.base_url}/checkUserCapCode' + response = self.s.post(url, headers=sign_header, json=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + data = data.get('data', 0) + print(f"验证码正确,获取到[{data}]") + else: + message = data.get('message', '') + print(f"验证码错误,偷取失败[{message}]") + # except Exception as e: + # print(e) + def exchange_reward(self, reward_id): + print(f'兑换--->>>') + try: + params = {'id': reward_id} + sign_header = self.gen_sign(params) + url = f'{self.base_url}/exchange/reward' + response = self.s.get(url, headers=sign_header, params=params) + data = response.json() + code = data.get('code', -1) + if code == 0: + data = data.get('data', {}).get('name') or '' + print(f"兑换[{data}]成功") + else: + message = data.get('message', '') + print(f'兑换[id={reward_id}]: {message}') + except Exception as e: + print(e) + + def risk_task(self): + self.take_risk_get() + self.take_risk_online() + self.take_risk_reward() + print(f'可以冒险【{self.risk_num}】次') + while self.risk_num > 0 and self.can_go_risk == True: + self.take_risk_go() + time.sleep(2) + + def land_task(self): + self.user_land_get() + if self.all_land_unlock and self.all_role_unlock: + pass + for land_number, land_info in self.land.items(): + # print(land_number) + # print(land_info) + if land_info['status'] == 0: + continue + step, use_sun_count, left_sun_count = land_info['step'], land_info['useSunCount'], land_info['leftSunCount'] + + total_sun_count = (use_sun_count if use_sun_count else 0) + (left_sun_count if left_sun_count else 0) + + print(f"\n---[{land_info['no']}号土地]---\n{self.group_step[step-1]},阶段{step}, 进度{use_sun_count}/{total_sun_count}") + + self.refresh_land_step = True + while self.refresh_land_step: + self.refresh_land_step = False + if land_info['status'] == 0: + break + if step == 0: + self.user_land_sow(land_info) + else: + if left_sun_count == 0: + if step == 5: + self.user_land_result(land_info) + else: + current_time = int(time.time() * 1000) + if current_time >= (land_info['sunTime'] + land_info['sunTimestamp']) * 1000: + self.user_land_level(land_info) + else: + if self.sun >= land_info['needSun']: + current_time = int(time.time() * 1000) + if current_time >= (land_info['sunTime'] + land_info['sunTimestamp']) * 1000: + self.user_land_sun(land_info) + # time.sleep(2) + + def userTask(self): + print('\n--------------- 开始日常任务 ---------------') + wait_time = random.randint(1000, 3000) / 1000.0 # 转换为秒 + if not self.Login_res: + return False + + self.userInfo_autoSun() + + self.userInfo_get() + + self.task_get() + + self.user_role_get() + + self.risk_task() + + self.land_task() + + self.steal_task() + + self.userInfo_get(END=True) + new_data = { + self.userId: { + 'userId': self.userId, + 'task_id': self.task_id, + 'task_can_help': self.can_help_task, + 'task_need_help': self.need_help_task, + 'task_progress': self.task_progress, + 'task_max_progress': self.task_max_progress, + 'role_id': self.role_id, + 'role_can_help': self.can_help_unlock, + 'role_need_help': self.need_help_unlock, + 'role_progress': self.role_progress, + 'role_max': self.role_max, + 'risk_can_help': self.can_help_risk, + 'risk_need_help': self.need_help_task, + 'can_go_risk': self.can_go_risk, + 'can_add_friend': self.can_add_friend + + } + } + # print(new_data) + USER_INFO.update(new_data) + CHERWIN_TOOLS.SAVE_INVITE_CODE(f"INVITE_CODE/{ENV_NAME}_INVITE_CODE.json", new_data) + # self.steal_task() + self.sendMsg() + return True + + def helpEachOther(self): + print('--------------- 开始互助 ---------------') + + if not self.Login_res: + return False + + self.userInfo_get() + + if self.user_index == 1: + print('第一个账号助力作者--->>>') + data_li = AuthorCode + help_type = '作者' + else: + print('其余账号互助--->>>') + json_data = self.load_json() + data_li = list(json_data.values()) + help_type = '本地' + + + # print(data_li) + for index, code_li in enumerate(data_li): + # print(f"Index: {index}") + # print(f"Data: {code_li}") + if code_li.get('userId','') == self.userId: + continue + task_need_help = code_li.get("task_need_help", '') + role_need_help = code_li.get("role_need_help", '') + risk_need_help = code_li.get("task_can_help", '') + code_li["index"] = index+1 + print(f'\n------助力{help_type}账号【{index+1}】开始------') + # print(code_li) + # 冒险助力 + if self.can_help_risk and risk_need_help: + self.friend_help_task_risk(code_li) + else: + print(f'好友冒险助力已完成或冒险助力次数已耗尽') + + # 解锁角色助力 + if self.can_help_unlock and role_need_help: + self.user_role_friendHelpUnlock(code_li) + else: + print(f'好友解锁角色助力已完成或解锁角色助力次数已耗尽') + + # 阳光助力 + if self.can_help_task and task_need_help: + self.friend_help(code_li) + else: + print(f'阳光助力次数已耗尽') + + print(f'------助力{help_type}账号【{index+1}】结束------') + time.sleep(1) + + + new_data = { + self.userId: { + 'task_can_help': self.can_help_task, + 'role_can_help': self.can_help_unlock, + 'risk_can_help': self.can_help_risk + } + } + CHERWIN_TOOLS.SAVE_INVITE_CODE(f"INVITE_CODE/{ENV_NAME}_INVITE_CODE.json", new_data) + self.sendMsg(True) + return True + + def steal_task(self, count=5): + if not self.Login_res: + return False + json_data = self.load_json() + self.can_add_friend = json_data.get(self.userId, {}).get('can_add_friend', '') + for i in range(count): + if self.can_add_friend: + self.friend_findRecommend() + time.sleep(2) + self.friend_findFriend() + return True + + def sendMsg(self, help=False): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME, help) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + + +if __name__ == '__main__': + APP_NAME = '统一茄皇' + ENV_NAME = 'TYQH' + CK_NAME = 'thirdId@wid' + CK_URL = '.../public/api/login' + print(f''' +✨✨✨ {APP_NAME}脚本 ✨✨✨ +✨ 功能: + 日常任务 + 互助任务 +✨ 抓包步骤: + 统一快乐星球小程序-活动 + 开始抓包-茄皇的家第三期 + 抓{CK_URL}取{CK_NAME} +✨ 设置青龙变量: +export {ENV_NAME}= '{CK_NAME}'多账号#分割或& +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ 推荐定时:25 7-23/2 * * * +✨ 第一个账号助力作者,其余互助 +✨✨✨ @Author CHERWIN✨✨✨ + ''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + access_token = [] + for index, infos in enumerate(tokens): + run_result = RUN(infos, index).userTask() + if not run_result: continue + + for index, infos in enumerate(tokens): + run_result =RUN(infos, index).helpEachOther() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) diff --git a/TYYP.py b/TYYP.py new file mode 100755 index 0000000..1087b1d --- /dev/null +++ b/TYYP.py @@ -0,0 +1,280 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# const $ = new Env('天翼云盘签到'); + +import base64 +import hashlib +import os +import re +import time +import requests +import rsa +from os import path +from requests.packages.urllib3.exceptions import InsecureRequestWarning + +# import CHERWIN_TOOLS +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +class RUN: + def __init__(self,info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + self.userid = split_info[0] + self.pwd = split_info[1] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + print('检测到设置了UID') + print(last_info) + self.send_UID = last_info + self.index = index + 1 + + self.b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + self.UA = 'Mozilla/5.0 (Linux; Android 5.1.1; SM-G930K Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/74.0.3729.136 Mobile Safari/537.36 Ecloud/8.6.3 Android/22 clientId/355325117317828 clientModel/SM-G930K imsi/460071114317824 clientChannelId/qq proVersion/1.0.6' + self.headers = { + 'User-Agent': self.UA, + "Referer": "https://m.cloud.189.cn/zhuanti/2016/sign/index.jsp?albumBackupOpened=1", + "Host": "m.cloud.189.cn", + "Accept-Encoding": "gzip, deflate", + } + + @staticmethod + def int2char(a): + return list("0123456789abcdefghijklmnopqrstuvwxyz")[a] + + def b64tohex(self, a): + d = "" + e = 0 + c = 0 + for i in range(len(a)): + if list(a)[i] != "=": + v = self.b64map.index(list(a)[i]) + if e == 0: + e = 1 + d += self.int2char(v >> 2) + c = 3 & v + elif e == 1: + e = 2 + d += self.int2char(c << 2 | v >> 4) + c = 15 & v + elif e == 2: + e = 3 + d += self.int2char(c) + d += self.int2char(v >> 2) + c = 3 & v + else: + e = 0 + d += self.int2char(c << 2 | v >> 4) + d += self.int2char(15 & v) + if e == 1: + d += self.int2char(c << 2) + return d + + def rsa_encode(self, j_rsakey, string): + rsa_key = f"-----BEGIN PUBLIC KEY-----\n{j_rsakey}\n-----END PUBLIC KEY-----" + pubkey = rsa.PublicKey.load_pkcs1_openssl_pem(rsa_key.encode()) + return self.b64tohex( + (base64.b64encode(rsa.encrypt(f"{string}".encode(), pubkey))).decode() + ) + + def login(self): + # https://m.cloud.189.cn/login2014.jsp?redirectURL=https://m.cloud.189.cn/zhuanti/2021/shakeLottery/index.html + url = "" + urlToken = "https://m.cloud.189.cn/udb/udb_login.jsp?pageId=1&pageKey=default&clientType=wap&redirectURL=https://m.cloud.189.cn/zhuanti/2021/shakeLottery/index.html" + r = s.get(urlToken) + pattern = r"https?://[^\s'\"]+" # 匹配以http或https开头的url + match = re.search(pattern, r.text) # 在文本中搜索匹配 + if match: # 如果找到匹配 + url = match.group() # 获取匹配的字符串 + # print(url) # 打印url + else: # 如果没有找到匹配 + print("没有找到url") + + r = s.get(url) + # print(r.text) + pattern = r"]*href=\"([^\"]+)\"" # 匹配id为j-tab-login-link的a标签,并捕获href引号内的内容 + match = re.search(pattern, r.text) # 在文本中搜索匹配 + if match: # 如果找到匹配 + href = match.group(1) # 获取捕获的内容 + r = s.get(href) + # print("href:" + href) # 打印href链接 + else: # 如果没有找到匹配 + print("没有找到href链接") + exit() + + captchaToken = re.findall(r"captchaToken' value='(.+?)'", r.text)[0] + lt = re.findall(r'lt = "(.+?)"', r.text)[0] + returnUrl = re.findall(r"returnUrl= '(.+?)'", r.text)[0] + paramId = re.findall(r'paramId = "(.+?)"', r.text)[0] + j_rsakey = re.findall(r'j_rsaKey" value="(\S+)"', r.text, re.M)[0] + s.headers.update({"lt": lt}) + + username = self.rsa_encode(j_rsakey, self.userid) + password = self.rsa_encode(j_rsakey, self.pwd) + url = "https://open.e.189.cn/api/logbox/oauth2/loginSubmit.do" + headers = { + 'User-Agent': self.UA, + 'Referer': 'https://open.e.189.cn/', + } + data = { + "appKey": "cloud", + "accountType": '01', + "userName": f"{{RSA}}{username}", + "password": f"{{RSA}}{password}", + "validateCode": "", + "captchaToken": captchaToken, + "returnUrl": returnUrl, + "mailSuffix": "@189.cn", + "paramId": paramId + } + r = s.post(url, data=data, headers=headers, timeout=5) + if (r.json()['result'] == 0): + Log('登陆成功!') + print(r.json()['msg']) + else: + Log('登陆失败!') + print(r.json()['msg']) + redirect_url = r.json()['toUrl'] + r = s.get(redirect_url) + if r.status_code == 200: + return r + else: + return False + + def signIn(self): + Log('>>>>>>签到') + rand = str(round(time.time() * 1000)) + # print(rand) + surl = f'https://api.cloud.189.cn/mkt/userSign.action?rand={rand}&clientType=TELEANDROID&version=8.6.3&model=SM-G930K' + + response = s.get(surl, headers=self.headers) + netdiskBonus = response.json()['netdiskBonus'] + if (response.json().get('isSign','false') == "false"): + Log(f"未签到,签到获得{netdiskBonus}M空间\n") + else: + Log(f"已经签到过了,签到获得{netdiskBonus}M空间\n") + + def lottery(self): + Log('>>>>>>抽奖') + url_list = ['https://m.cloud.189.cn/v2/drawPrizeMarketDetails.action?taskId=TASK_SIGNIN&activityId=ACT_SIGNIN', + 'https://m.cloud.189.cn/v2/drawPrizeMarketDetails.action?taskId=TASK_SIGNIN_PHOTOS&activityId=ACT_SIGNIN', + 'https://m.cloud.189.cn/v2/drawPrizeMarketDetails.action?taskId=TASK_2022_FLDFS_KJ&activityId=ACT_SIGNIN'] + for index, urls in enumerate(url_list): + response = s.get(urls, headers=self.headers) + if ("errorCode" in response.text): + Log(f"链接{index + 1}抽奖失败") + print(response.text) + else: + description = response.json()['prizeName'] + Log(f"链接{index + 1}抽奖获得{description}\n") + + def main(self): + Log(f"\n开始执行第{self.index}个账号【{self.userid[-4:]}】--------------->>>>>") + if not self.login(): + print(f'\n第{self.index}个账号【{self.userid[-4:]}登陆失败!') + return False + self.signIn() + self.lottery() + self.sendMsg() + return True + + def sendMsg(self): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + +if __name__ == '__main__': + APP_NAME = '天翼云盘' + ENV_NAME = 'TYYP' + CK_NAME = '手机号@密码' + print(f''' +✨✨✨ {APP_NAME}签到抽奖✨✨✨ +✨ 功能: + 签到 + 抽奖 +参数示例:18888888888@123456 +✨ 设置青龙变量: +export {ENV_NAME}='{CK_NAME}参数值'多账号#或&分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ 推荐cron:0 9 * * * +✨✨✨ @Author CHERWIN✨✨✨ +''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + access_token = [] + for index, infos in enumerate(tokens): + s = requests.session() + s.verify=False + run_result = RUN(infos, index).main() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) diff --git a/YDKD.py b/YDKD.py new file mode 100755 index 0000000..7392dea --- /dev/null +++ b/YDKD.py @@ -0,0 +1,368 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# @Author : cherwin +# ✨✨✨ 韵达快递小程序签到✨✨✨ +# ✨ 功能: +# 积分签到 +# ✨ 抓包步骤: +# 打开韵达快递小程序 +# 授权登陆 +# 打开抓包工具 +# 找URl请求头带openID +# 复制里面的openID参数值 +# 参数示例:at965eoakumxxxxxxxx +# ✨ 设置青龙变量: +# export YDKD='openID参数值'多账号#或&分割 +# export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +# ✨ ✨ 注意:抓完CK没事儿别打开小程序,重新打开小程序请重新抓包 +# ✨ 推荐cron:0 6 * * * +# ✨✨✨ @Author CHERWIN✨✨✨ +# ------------------------------- +# cron "30 6 * * *" script-path=xxx.py,tag=匹配cron用 +# const $ = new Env('韵达快递小程序签到') +import json +import os +import random +import time +from os import path +import requests +import hashlib +from requests.packages.urllib3.exceptions import InsecureRequestWarning +# import CHERWIN_TOOLS +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +class RUN: + def __init__(self,info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + self.token = split_info[0] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + print('检测到设置了UID') + print(last_info) + self.send_UID = last_info + self.index = index + 1 + self.headers = { + 'Host': 'op.yundasys.com', + 'Accept': 'application/json, text/plain, */*', + 'X-Requested-With': 'XMLHttpRequest', + 'Authorization': self.token, + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF XWEB/6945', + 'Content-Type': 'application/json; charset=UTF-8', + 'Sec-Fetch-Site': 'same-origin', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Dest': 'empty', + 'Referer': 'https://op.yundasys.com/mb-ext-channel/index.html', + 'Accept-Language': 'zh-CN,zh' + } + + self.baseUrl = 'https://op.yundasys.com/gateway/ydmb-integral/ydintegral/' + self.news_List = [] + self.list_index = 0 + self.isFirstTask = True + + def get_point(self): + Log('>>>>>>获取积分信息') + json_data = { + "channelId": "wxapp", + "reqTime": int(time.time()), + "accountSrc": "wxapp", + "accountId": self.token + } + response = s.post(f'{self.baseUrl}member/integral/info', headers=self.headers,json=json_data) + point_info = response.json() + # print(point_info) + if point_info['code']== 200: + point=point_info['data']['total'] + userId=point_info['data']['userId'] + Log(f'>>当前用户:【{userId}】') + Log(f'>>当前积分:【{point}】') + return True + else: + Log('可能token失效了') + return False + + def sign(self): + Log('>>>>>>签到') + json_data = { + 'channelId': 'wxapp', + 'itgType': 'sign', + 'reqTime': int(time.time()), + 'accountSrc': 'wxapp', + 'accountId': self.token + } + response = s.post(f'{self.baseUrl}obtain/event/integral', headers=self.headers,json=json_data) + point_info = response.json() + # print(point_info) + if point_info['code']== 200: + msg=point_info['message'] + Log(f'>>签到成功,,{msg}') + else: + print(f">>{point_info['message']}") + # print(response.text) + def get_TaskList(self): + Log('>>>>>>获取任务列表') + json_data ={ + "channelId": "wxapp", + "pageNum": 1, + "pageSize": 100, + "businessType": "goldBetter", + "reqTime": int(time.time()), + "accountSrc": "wxapp", + "accountId": self.token + } + response = s.post(f'{self.baseUrl}integral/event/list', headers=self.headers,json=json_data) + # try: + json_data = response.json() + # print(json_data) + skip_type=['关注公众号','实名认证','完善个人信息','累计消耗积分','寄快递','购买超级会员','兑换商品'] + complete = {} + if json_data['message'] == '请求成功': + data=json_data['data'] + list = data['items'] + for i in list: + eventStatus = i['eventStatus'] + eventCode = i['eventCode'] + #可完成次数 + surplusCount = i['surplusCount'] + title = i['eventName'] + if title == '本月寄满3件': surplusCount = 1 + if title in skip_type:continue + stu = {"0":"已完成","1":"未完成"} + Log(f'当前任务【{title}】,{stu[eventStatus]}') + for t in range(surplusCount): + if eventStatus != "1" : + self.doTask(eventCode,title) + if title == '观看精彩视频': + self.watchAd(title) + else: + complete[title] = 0 + time.sleep(2) + time.sleep(2) + + if all(value == 0 for value in complete.values()): + Log(">>>任务已全部完成") + return True + # print(f'>>当前积分:【{point}】') + # except: + # print(response.text) + def watchAd(self,title): + json_data = { + "action":"ydmbintegral.ydintegral.obtain.event.integral", + "appid":"wjvxmno358lze827", + "req_time":int(time.time()), + "options":"false", + "data":{ + "accountId":self.token, + "accountSrc":"wxapp", + "reqTime":int(time.time()),"itgType":"wechat_viewadv" + }, + "version":"V1.0"} + response = s.post(f'{self.baseUrl}obtain/event/integral', headers=self.headers, json=json_data) + point_info = response.json() + # print(point_info) + if point_info['code'] == 200: + msg = point_info['message'] + print(f'>>{title},{msg}') + else: + print(f">>{title},{point_info['message']}") + + def doTask(self,eventCode,title): + json_data = { + 'channelId': 'wxapp', + 'itgType': f'{eventCode}', + 'reqTime': int(time.time()), + 'accountSrc': 'wxapp', + 'accountId': self.token + } + response = s.post(f'{self.baseUrl}obtain/event/integral', headers=self.headers, json=json_data) + point_info = response.json() + # print(point_info) + if point_info['code'] == 200: + msg = point_info['message'] + print(f'>>{title},{msg}') + else: + print(f">>{title},{point_info['message']}") + + def getDrawInfo(self): + self.DrawHeaders = { + 'Host': 'op.yundasys.com', + 'Accept': 'application/json, text/plain, */*', + 'X-Requested-With': 'XMLHttpRequest', + 'Authorization': self.token, + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF XWEB/8259', + 'Content-Type': 'application/json; charset=UTF-8', + 'Sec-Fetch-Site': 'same-origin', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Dest': 'empty', + 'Referer': 'https://op.yundasys.com/mb-ext-channel/index.html', + 'Accept-Language': 'zh-CN,zh', + } + json_data = { + "reqTime": int(time.time()), + "accountId": self.token, + "accountSrc": "wxapp" + } + response = s.post(f'https://op.yundasys.com/gateway/ydmbaccount/ydaccount/mc/Itg/store/token', headers=self.DrawHeaders, json=json_data) + point_info = response.json() + # print(point_info) + if point_info['code'] == 200: + data = point_info['data'] + if data: + self.getDrawNumber(data) + else: + print(f">>{point_info['message']}") + + def getDrawNumber(self,data): + json_data = { + 'activityId': 16, + 'plum_session_applet': data, + 'suid': 'gmrtxvrye6', + 'mwl_client_flag': 'wxapp', + } + resp = s.post(f'https://op.yundasys.com/itgstoresys/api/lottery/drawNumber', headers=self.DrawHeaders, json=json_data) + res_info = resp.json() + if res_info['code'] == 200: + freeDrawNumber = res_info['data']['freeDrawNumber'] + print(f'>>剩余免费抽奖次数:【{freeDrawNumber}】') + if freeDrawNumber == 1: + self.doDraw(data) + + else: + print(f">>{res_info['message']}") + + def doDraw(self,data): + res_data = { + 'activityId': 16, + 'plum_session_applet': data, + 'suid': 'gmrtxvrye6', + 'mwl_client_flag': 'wxapp', + } + resp = s.post(f'https://op.yundasys.com/itgstoresys/api/lottery/draw', headers=self.DrawHeaders, json=res_data) + res_info = resp.json() + if res_info['code'] == "200": + msg = res_info['message'] + prizeName = res_info['data']['prizeName'] + Log(f'>>{msg},获得{prizeName}') + else: + Log(f">>{res_info['message']}") + + + def main(self): + Log(f"\n开始执行第{self.index}个账号--------------->>>>>") + if not self.get_point(): + return False + self.sign() + self.get_TaskList() + self.getDrawInfo() + self.sendMsg() + return True + + def sendMsg(self): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + +if __name__ == '__main__': + APP_NAME = '韵达快递小程序' + ENV_NAME = 'YDKD' + CK_NAME = 'Authorization' + print(f''' +✨✨✨ {APP_NAME}签到✨✨✨ +✨ 功能: + 积分签到 + 积分抽奖 +✨ 抓包步骤: + 打开{APP_NAME} + 授权登陆 + 打开抓包工具 + 找URl请求头带{CK_NAME} + 复制里面的{CK_NAME}参数值 +参数示例:oPJUI0eZ5cm8BpR7xxxx +✨ 设置青龙变量: +export {ENV_NAME}='{CK_NAME}参数值'多账号#或&分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ ✨ 注意:抓完CK没事儿别打开小程序,重新打开小程序请重新抓包 +✨ 推荐cron:0 6 * * * +✨✨✨ @Author CHERWIN✨✨✨ +''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + access_token = [] + for index, infos in enumerate(tokens): + s = requests.session() + s.verify = False + run_result = RUN(infos, index).main() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) \ No newline at end of file diff --git a/YHSH.py b/YHSH.py new file mode 100755 index 0000000..e2b9e4f --- /dev/null +++ b/YHSH.py @@ -0,0 +1,1121 @@ +''' +!/usr/bin/python3 +-- coding: utf-8 -- +------------------------------- +✨✨✨ @Author CHERWIN✨✨✨ +cron "51 8,21 * * *" script-path=xxx.py,tag=匹配cron用 +const $ = new Env('永辉生活') +''' +import hashlib +import json +import os +import random +import time +import urllib +from os import environ, path +from sys import exit +from urllib.parse import quote, urlparse, parse_qs + +import requests +from requests.packages.urllib3.exceptions import InsecureRequestWarning + +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +inviteCode = {} +GameCode=[] +PRIZEID = '' + + +class RUN: + def __init__(self, info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + token = split_info[0] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID =None + if len_split_info > 0 and "UID_" in last_info: + self.send_UID = last_info + self.index = index + 1 + self.s = requests.session() + self.s.verify = False + self.UA = 'Mozilla/5.0 (Linux; Android 11; Mi9 Pro 5G Build/RKQ1.200826.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/113.0.5672.162 Mobile Safari/537.36YhStore/9.6.0.14 cn.yonghui.hyd/2022946000 (client/phone; Android 30; Xiaomi/Mi9 Pro 5G)' + self.headers = { + 'Host': 'api.yonghuivip.com', + 'Connection': 'keep-alive', + 'User-Agent': self.UA, + 'X-YH-Context': 'origin=h5&morse=1', + 'Accept': '*/*', + 'Origin': 'https://m.yonghuivip.com', + 'X-Requested-With': 'cn.yonghui.hyd', + 'Sec-Fetch-Site': 'same-site', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Dest': 'empty', + 'Referer': 'https://m.yonghuivip.com/', + # 'Accept-Encoding': 'gzip, deflate, br', + 'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7', + } + # 创建一个字典来存储参数 + data = {} + # 解析第一个URL并提取参数 + parsed_url1 = urlparse(token) + # print(parsed_url1) + self.data_dict = parse_qs(parsed_url1.query) + # print(self.data_dict) + self.url_add = token.split('?')[1] + # print(self.data_dict) + self.fruit_is_ripe = False + self.gameCode ='' + if self.data_dict.get('memberid') : + self.memberId = self.data_dict.get('memberid',[])[0] + else: + self.memberId = self.data_dict.get('memberId', [])[0] + if self.data_dict.get('shopid') : + self.shopid = self.data_dict.get('shopid',[])[0] + else: + self.shopid = '9M7M' + self.url_add =f'{self.url_add}&shopid={self.shopid}' + print(self.shopid) + self.gamecode_li = [] + self.canJoinTeam = True + self.canhelp_coup = True + + + # 将参数转换为字典 + def create_dict_from_string(self, data_string): + params = {} + key_value_pairs = data_string.split(',') + for pair in key_value_pairs: + key, value = pair.split('=') + params[key] = value + return params + + # 发送请求函数 + def do_request(self, url, data={}, req_type='post', headers={}): + if headers == {}: + headers = self.headers + try: + if req_type.lower() == 'get': + response = self.s.get(url, headers=headers) + elif req_type.lower() == 'post': + response = self.s.post(url, headers=headers, json=data) + else: + raise ValueError('Invalid req_type: %s' % req_type) + res = response.json() + return res + except requests.exceptions.RequestException as e: + print('Request failed:', e) + return None + except json.JSONDecodeError as e: + print('JSON decoding failed:', e) + return None + + def getCredit(self): + Log(f'\n>>>>>>获取积分信息') + headers = { + 'Accept': '*/*' + } + url = f'https://api.yonghuivip.com/web/coupon/credit/details/?page=0&{self.url_add}' + response = self.do_request(url, req_type='get', headers=headers) + # print(response) + + if 'code' in response and response.get('code','') == 0: + credit = response.get('data')['credit'] + self.sign_count = response.get('data')['count'] + + Log(f'>当前用户:{self.memberId}\n>当前积分:{credit}') + # Log(f'>>>累计签到:{self.sign_count}天') + return True + elif response.get("message", "") == '登录状态已失效,请重新登录': + if send:send('永辉生活账号失效通知', f'账号:{self.index} ID:{self.memberId}已失效,请重新抓包') + else: + Log(f'>获取积分信息失败') + # print(response) + return False + + def sign(self): + Log(f'\n>>>>>>开始执行签到') + headers = { + 'Accept': 'application/json' + } + + data = { + "memberId": self.memberId, + "shopid": self.shopid, + "missionid": "39" + } + url = f'https://api.yonghuivip.com/web/coupon/signreward/sign?{self.url_add}' + response = self.do_request(url, headers=headers,data=data) + # print(response) + + if 'code' in response and response.get('code') == 0: + Log(f'>签到成功') + Log(f'>累计签到:{int(self.sign_count) + 1}天') + self.getCredit() + return True + elif '任务已完成,请勿重复点击' in response: + Log(f'>今日已签到') + else: + Log(f'>签到失败,{response.get("message")}') + return False + + def teamDetail(self): + Log(f'\n>>>>>>开始获取组队详情') + headers = { + 'Accept': 'application/json' + } + data = { + "createTeamFlag": True, + "shopId": self.shopid, + } + + url = f'https://api.yonghuivip.com/web/coupon/credit/dividePoint/teamDetail?{self.url_add}' + response = self.do_request(url, headers=headers,data=data) + # print(response) + if 'code' in response and response.get('code') == 0: + data = response.get('data',{}) + if data != {}: + self.teamCode = data.get('teamCode','') + subTitle = data.get('subTitle','') + print(f'战队ID:【{self.teamCode}】 状态:【{subTitle}】') + new_data={ + self.memberId:{ + 'teamCode':self.teamCode + } + } + inviteCode.update(new_data) + print(inviteCode) + else: + print('未查询到战队,开始创建') + self.creatTeam() + else: + print(f'>创建战队失败,{response.get("message")}') + + def creatTeam(self): + Log(f'\n>>>>>>开始组队任务') + headers = { + 'Accept': 'application/json' + } + data = { + "shopId": self.shopid, + } + + url = f'https://api.yonghuivip.com/web/coupon/credit/dividePoint/createTeam?{self.url_add}' + response = self.do_request(url, headers=headers,data=data) + # print(response) + if 'code' in response and response.get('code') == 0: + data = response.get('data',{}) + self.teamCode = data.get('teamCode', '') + subTitle = data.get('subTitle', '') + Log(f'创建战队成功,ID:【{self.teamCode}】 状态:【{subTitle}】') + new_data = { + self.memberId: { + 'teamCode': self.teamCode + } + } + inviteCode.update(new_data) + else: + print(f'>创建战队失败,{response.get("message")}') + + def joinAuthorTeam(self): + print(f'>>>开始加入作者队伍') + headers = { + 'Accept': 'application/json' + } + if len(AuthorCode) >0 : + for code in AuthorCode: + if not self.canJoinTeam:break + data = { + "teamCode": code.get('teamCode'), + "shopId": self.shopid + } + url = f'https://api.yonghuivip.com/web/coupon/credit/dividePoint/joinTheParty?{self.url_add}' + response = self.do_request(url, headers=headers, data=data) + if 'code' in response and response.get('code') == 0: + print(f'加入战队成功') + break + elif response.get('message') == '达到1天内组队上限': + self.canJoinTeam = False + + def joinTeam(self): + Log(f'>>>开始本地账号组队') + headers = { + 'Accept': 'application/json' + } + inviteCode_li = list(inviteCode.values()) + # print(inviteCode_li) + for code in inviteCode_li: + if not self.canJoinTeam: + print('达到1天内组队上限') + break + data = { + "teamCode": code.get('teamCode'), + "shopId": self.shopid + } + url = f'https://api.yonghuivip.com/web/coupon/credit/dividePoint/joinTheParty?{self.url_add}' + response = self.do_request(url, headers=headers, data=data) + + if 'code' in response and response.get('code') == 0: + Log(f'组队成功') + break + elif response.get("message","") == '会员专享功能,请先登录': + break + elif response.get('message') == '达到1天内组队上限': + self.canJoinTeam = False + else: + Log(f'>组队失败,{response.get("message")}') + + def farmInfo(self): + headers = { + 'Accept': '*/*' + } + url = f'https://activity.yonghuivip.com/api/web/flow/farm/info?{self.url_add}' + response = self.do_request(url, headers=headers, req_type='get') + # print(response) + + if 'code' in response and response.get('code') == 0: + self.parentId = response.get('data',[])['parentId'] + self.memberAmount = response.get('data',[])['memberAmount'] + self.ladderText = response.get('data',[]).get('ladderText','') + Log(f'>>>当前水滴:{self.memberAmount}') + Log(f'>>>当前水果进度:{self.ladderText}') + if self.ladderText == '再浇水0%,果树就要成熟了': + self.fruit_is_ripe = True + inviteCode[self.memberId]['fruit_is_ripe'] = self.fruit_is_ripe + + return True + else: + Log(f'>>>获取果园信息失败\n{response}') + return False + + def plantFruit_sign(self): + Log(f'>>>开始果园签到') + headers = { + 'Accept': 'application/json' + } + data = { + "taskType": "sign", + "activityCode": "HXNC-QG", + "shopId": "", + "channel": "" + } + url = f'https://activity.yonghuivip.com/api/web/flow/farm/doTask?{self.url_add}' + response = self.do_request(url, headers=headers, data=data) + # print(response) + + if 'code' in response and response.get('code') == 0: + signText = response.get('data')['signText'] + Log(f'>>>{signText}') + return True + else: + Log(f'>>>果园签到失败\n{response}') + return False + + def plantFruit_getTaskList(self): + print(f'>>>获取任务列表') + headers = { + 'Accept': '*/*' + } + url = f'https://activity.yonghuivip.com/api/web/flow/farm/task/list?activityCode=HXNC-QG&&parentId={self.parentId}&{self.url_add}' + response = self.do_request(url, headers=headers, req_type='get') + # print(response) + + if 'code' in response and response.get('code') == 0: + data = response.get('data') + for i in data: + subType = i['subType'] + title = i['title'] + finished = i['finished'] + self.taskId = i['taskId'] + self.rewardid = i.get('rewardId', '') + # print(self.rewardid) + if subType == 'activityPage' and finished != 1: + actionUrl = i['actionUrl'] + # 解码URL + decoded_url = urllib.parse.unquote(actionUrl) + decoded_url = decoded_url.replace('pid=null', f'pid={self.parentId}') + # print(decoded_url) + parsed_url = urllib.parse.urlparse(decoded_url) + query_params = urllib.parse.parse_qs(parsed_url.query) + self.aid = query_params.get("aid", [None])[0] + self.taskid = query_params.get("taskid", [None])[0] + # print(self.aid) + # 提取aid后面的字符串 + index = decoded_url.find("&aid=") + if index != -1: + toUrl = f'?aid={decoded_url[index + 5:]}' + else: + toUrl = "" + self.doFruitTask(title, toUrl) + if self.rewardid != '': + print('检测到有可收取任务') + self.receive_water() + return True + else: + print(response) + return False + + def doFruitTask(self, title, toUrl): + print(f'>>>开始做任务{title}') + params = {"platform": "android", + "v": "9.6.0.14", + "channel": "2", + "distinctId": "", + "proportion": 2.75, + "screen": "1080.75*2340.25", + "pagesize": 6, + "networkType": "wifi", + "aid": self.aid, + "versionpro": "2", + "appType": "h5", + "model": "Mi9 Pro 5G", + "os": "android", + "osVersion": "android30", + "channelSub": "", + "brand": "Xiaomi", + "productLine": "YhStore", + "salesChannel": "", + "deviceid": "", + "sellerid": "7", + "shopid": "90B3", + "uid": "", + "access_token": "", + "showmultiseller": "", + "shopName": "", + "isOldEdition": False, + "userid": "", + "pageid": self.aid, + "pid": self.parentId, + "taskid": self.taskid, + "sceneValue": "4", + "memberId": "" + } + + headers = { + 'Accept': 'application/json, text/plain, */*', + "Content-Type": "application/json;charset=UTF-8", + "Connection": "keep-alive", + "Connection": "keep-alive" + } + url = f'https://api.yonghuivip.com/web/coupon/dailyreward/browse{toUrl}&{self.url_add}' + response = self.do_request(url, headers=headers, data=params) + # print(response) + + if 'code' in response and response.get('code') == 0: + data = response.get('data')['title'] + Log(f'>{data}') + return True + else: + return False + + def receive_inviteWater(self): + headers = { + 'Accept': '*/*' + } + url = f'https://activity.yonghuivip.com/api/web/flow/farm/invitation/bubble?activityCode=HXNC-QG&{self.url_add}' + # print(url) + response =self.do_request(url, headers=headers,req_type='get') + # print(response) + if 'code' in response and response.get('code') == 0: + data = response['data']['inviteWaterBubble'] + if data != []: + Log(f'>>>开始领取邀请奖励') + for task in data: + url = f'https://activity.yonghuivip.com/api/web/flow/farm/receiveWater?{self.url_add}' + headers = { + "Content-Type": "application/json", + "Accept": "application/json" + } + data = {"taskId": task['taskId'], "id": task['rewardId'], "activityCode": "HXNC-QG"} + response = requests.post(url, headers=headers, json=data,verify=False).json() + if 'code' in response and response.get('code') == 0: + receiveAmount = response['data']['receiveAmount'] + print(f'>成功收取【{receiveAmount}】水滴') + else: + print(f'>收取失败,{response}') + else: + print('>没有可领取的邀请奖励') + else: + print(f'>领取邀请奖励失败,{response}') + + def receive_water(self,taskType=None): + print(f'>>>开始领取奖励') + headers = { + "Content-Type": "application/json", + "Accept": "application/json" + } + data = { + "taskId": self.taskId, + "id": self.rewardid, + "activityCode": "HXNC-QG"} + if taskType != None: + data['taskType'] = "activityPage" + url = f'https://activity.yonghuivip.com/api/web/flow/farm/receiveWater?{self.url_add}' + # print(url) + + response =self.do_request(url, headers=headers, data=data) + # response =requests.post(url, headers=headers, json=data) + # if response: + # response = response.json() + if 'code' in response and response.get('code') == 0: + receiveAmount = response['data']['receiveAmount'] + print(f'>成功收取【{receiveAmount}】水滴') + else: + print(f'>收取失败,{response}') + + def watering(self): + self.farmInfo() + if int(self.memberAmount / 10) > 1 : + print(f'>>>开始浇水') + headers = { + 'Accept': 'application/json' + } + data = {"activityCode": "HXNC-QG", "shopId": "", "channel": "", "inviteTicket": "", "inviteShopId": ""} + url = f'https://activity.yonghuivip.com/api/web/flow/farm/watering?{self.url_add}' + for i in range(int(self.memberAmount / 10)): + + response = self.do_request(url, headers=headers, data=data) + # print(response.text) + if 'code' in response and response.get('code') == 0: + print(f'>第{i + 1}次浇水成功') + elif response.get('message') == '果树已经成熟啦,快去领取奖励吧': + print(f'>果树已经成熟啦') + self.fruit_is_ripe = True + + inviteCode[self.memberId]['fruit_is_ripe'] = self.fruit_is_ripe + + break + else: + print(f'>浇水失败,{response}') + else: + print('>水滴不足,停止浇水') + + def get_inviteTicket(self): + print(f'>>>开始获取果园邀请码') + headers = { + 'Accept': 'application/json' + } + data = {"inviteAction": "802"} + url = f'https://activity.yonghuivip.com/api/web/flow/farm/invite/ticket?{self.url_add}' + response = self.do_request(url, headers=headers, data=data) + # print(response) + if 'code' in response and response.get('code','') == 0: + self.inviteTicket = response.get('data') + print(f'果园邀请码:{self.inviteTicket}') + inviteCode[self.memberId]['inviteCode']=self.inviteTicket + inviteCode[self.memberId]['shopId']=self.shopid + + else: + print(f'>获取果园邀请码失败,{response}') + + def helpAuthor(self): + print(f'>>>开始助力作者') + headers = { + 'Accept': 'application/json' + } + for code in AuthorCode: + if code.get('memberId', '') == self.memberId: continue + if code.get('fruit_is_ripe',False):break + data={ + "activityCode":"HXNC-QG", + "shopId":self.shopid, + "channel":"512", + "inviteTicket":code.get('inviteCode',''),"inviteAction":"watering","inviteShopId":code.get('shopId','') + } + url = f'https://activity.yonghuivip.com/api/web/flow/farm/watering?inviteTicket={code}&{self.url_add}' + response = self.do_request(url, headers=headers,data=data) + # print(response) + if 'code' in response and response.get('code') == 0: + Log(f'>助力作者成功') + break + elif response.get("message","") == '会员专享功能,请先登录': + break + else: + pass + # Log(f'>助力作者失败,{response.get("message","")}') + + def helpOther(self): + Log(f'>>>开始本地账号互助') + headers = { + 'Accept': 'application/json' + } + inviteCode_li = list(inviteCode.values()) + # print(inviteCode_li) + for code in inviteCode_li: + if code.get('memberId', '') == self.memberId:continue + if code.get('fruit_is_ripe', False): break + data = {"activityCode": "HXNC-QG", + "shopId": self.shopid, + "channel": "512", + "inviteTicket": code.get('inviteCode', ''), "inviteAction": "watering", + "inviteShopId": code.get('shopId', '') + } + url = f'https://activity.yonghuivip.com/api/web/flow/farm/watering?inviteTicket={code}&{self.url_add}' + response = self.do_request(url, headers=headers, data=data) + # print(response.text) + if 'code' in response and response.get('code') == 0: + Log(f'>助力成功') + elif response.get("message","") == '会员专享功能,请先登录': + break + else: + Log(f'>助力失败,{response.get("message","")}') + + ######################成长值任务 + def get_GrowthValue(self): + Log(f'\n>>>>>>开始成长任务') + headers = { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + } + data = { + "businessCode": "membershipSystem" + } + url = f'https://api.yonghuivip.com/web/member/level/benefit/queryMemberGrowthValueProcess?{self.url_add}' + response = self.do_request(url, headers=headers, data=data) + + if 'code' in response and response.get('code') == 0: + # print(response['data']) + data = response.get('data',[]) + self.levelNeedGrowthValues = data.get('levelNeedGrowthValues',[]) + if self.levelNeedGrowthValues != None: + for li in self.levelNeedGrowthValues: + isCurrentLevel = li.get('isCurrentLevel','') + # print(isCurrentLevel) + if isCurrentLevel == True: + self.levelName = li.get('levelName', '') + # print(self.levelName) + currentTotalGrowthValue = li.get('currentTotalGrowthValue', '') + nextLevelMinGrowthValue = li.get('nextLevelMinGrowthValue', '') + count = int(nextLevelMinGrowthValue)-int(currentTotalGrowthValue) + print(f'当前等级:【{self.levelName}】 积分:【{currentTotalGrowthValue}】 升级需要【{count}】') + break + else: + print('--------------') + + else: + Log(f'>获取失败,{response}') + + def get_GrowthtaskList(self): + headers = { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + } + data = { + "businessCode": "membershipSystem", + "shopId": self.shopid, + "isOpenPublishNotice": True + } + url = f'https://api.yonghuivip.com/web/member/task/listTasks?{self.url_add}' + response = self.do_request(url, headers=headers, data=data) + + if 'code' in response and response.get('code') == 0: + # print(response['data']) + data = response.get('data',[]) + self.taskCode = data.get('taskCode','') + # Log(f'>获取到当前签到任务ID:【{self.taskID}】 编码:【{self.taskCode}】') + if data.get("subTasks",[]) != None: + for li in data.get("subTasks",[]): + self.taskID = li.get('taskId','') + self.taskTitle = li.get('taskTitle','') + self.doSignTask() + else: + print('>>未发现成长值任务') + + else: + Log(f'>获取失败,{response}') + + ######################签到任务 + def get_taskList(self): + headers = { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + } + data = { + "shopId": self.shopid + } + url = f'https://api.yonghuivip.com/web/coupon/credit/task/queryTaskInfo?{self.url_add}' + response = self.do_request(url, headers=headers, data=data) + + if 'code' in response and response.get('code') == 0: + # print(response['data']) + data = response.get('data',[]) + if data: + self.taskStatus = data.get('taskStatus','') + self.taskID = data.get('taskId','') + self.taskTitle = data.get('taskTitle','') + if self.taskID and self.taskStatus ==0: + self.doTask() + else: + print('>>未发现任务') + + else: + Log(f'>获取失败,{response}') + + def doTask(self): + Log(f'>>>执行{self.taskTitle}') + headers = { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + } + data = { + "taskId": self.taskID, + "shopId": self.shopid + } + url = f'https://api.yonghuivip.com/web/coupon/credit/task/completeTask?{self.url_add}' + response = self.do_request(url, headers=headers, data=data) + + if 'code' in response and response.get('code') == 0: + data = response['data'] + success = data['success'] + sendNum = data['sendNum'] + if success: + Log(f'>获取到【{sendNum}】积分') + + elif response.get('message','')=='任务已完成,请勿重复点击': + Log(f'>今日已签到') + else: + + Log(f'>签到失败,{response}') + + def doSignTask(self): + Log(f'>>>执行{self.taskTitle}') + headers = { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + } + data = { + "taskId": self.taskID, + "shopId": self.shopid, + "taskCode": self.taskCode + } + url = f'https://api.yonghuivip.com/web/member/task/doTask?{self.url_add}' + response = self.do_request(url, headers=headers, data=data) + + if 'code' in response and response.get('code') == 0: + recive_data = response['data'] + Log(f'>签到成功获取到【{recive_data}】成长值') + elif response.get('message','')=='任务已完成,请勿重复点击': + Log(f'>今日已签到') + else: + + Log(f'>签到失败,{response}') + + #########助力券任务 + #获取助力券列表 + def listBoostCouponByPage(self): + global PRIZEID + print(f'>>>>>>开始获取助力券列表>>>>>>') + print('默认发起普通用户助力券') + headers = { + "Accept": "application/json", + "Content-Type": "application/json" + } + data = { + "current": 1, + "size": 20 + } + url = f'https://api.yonghuivip.com/web/marketing/boostcoupon/listBoostCouponByPage?{self.url_add}' + + response = self.do_request(url, headers=headers, data=data) + # print(response) + if 'code' in response and response.get('code') == 0: + # print(response) + + coupList = response.get('data')['records'] + for li in coupList: + #助力券ID + self.prizeId = li['prizeGameDTO']['prizeId'] + self.needBoostNum = li['prizeGameDTO']['needBoostNum'] + self.remainBoostNum = li['prizeGameDTO']['remainBoostNum'] + self.gameCode = li['prizeGameDTO']['gameCode'] + + # boosterType 2 新人助力 1普通助力 + self.boosterType = li['prizeGameDTO']['boosterType'] + self.boosterType ="新人" if self.boosterType == 2 else "普通用户" + self.amount = li['boostCouponVO']['amount'] + self.coupName = li['boostCouponVO']['name'] + # 剩余张数 + self.availableCount = li['boostCouponVO']['availableCount'] + # 使用限制 + self.couponDescription = li['boostCouponVO']['couponDescription'] + self.applicationScope = li['boostCouponVO']['applicationScope'] + self.canApply = li['boostCouponVO']['canApply'] + copuname = f'{self.amount}元{self.coupName}' + # if COPU_NAME == copuname: + # PRIZEID = self.prizeId + self.canApply = "可发起" if self.canApply != -1 else "不可发起" + if self.canApply != -1 and self.boosterType == '普通用户': + self.getGameCode() + if self.gameCode: + gamecode_data = { + 'name': f'{self.amount}元{self.coupName}', + 'prizeId': self.prizeId, + 'gameCode': self.gameCode + } + self.gamecode_li.append(gamecode_data) + if self.index == 1: + GameCode.append(gamecode_data) + print(f'-----【{self.amount}元{self.coupName}】----') + print(f'prizeId:【{self.prizeId}】\n需要【{self.needBoostNum}】个[{self.boosterType}]助力,仍需:【{self.remainBoostNum}】 {self.canApply}】 \n使用限制:【{self.couponDescription} {self.applicationScope}】\ngameCode:【{self.gameCode}】') + + # print('第一个账号gamecodeli:',GameCode) + # print(self.gamecode_li) + print(f'>>>>>>获取助力券列表结束>>>>>>') + + #根据prizeId获取gameCode + def getGameCode(self): + global GameCode + # print(f'>>开始获取prizeID:【{self.prizeId}】gameCode') + headers = { + "Accept": "*/*" + } + + url = f'https://api.yonghuivip.com/web/marketing/boostcoupon/getGameCode?prizeId={self.prizeId}&gameCode=&{self.url_add}' + + response = self.do_request(url, headers=headers, req_type='get') + # print(response) + if 'code' in response and response.get('code') == 0: + # print(response) + self.gameCode = response.get('data') + #保存到json + if self.gameCode: + gamecode_data ={ + 'name':f'{self.amount}元{self.coupName}', + 'prizeId':self.prizeId, + 'gameCode':self.gameCode + } + if self.index == 1: + GameCode.append(gamecode_data) + print(f'>>获取到gameCode:【{self.gameCode}】') + else: + print('>>未获取到gameCode') + elif response.get('message','') =='您今日发起活动次数已达上限,请明日再来': + self.canDoApply = False + else: + print(response.get('message')) + + #助力助力券 + def Boostcoupon(self,gameCodeLi=None): + global AuthorCode + + print(f'>>>开始领券助力') + # print('GameCode:',GameCode) + # print('AuthorCode:',inviteCode) + if gameCodeLi==None: + print('>>第一个账号开始为作者助力') + for codeli in AuthorCode: + if not self.canhelp_coup: + print(f'>>>助力次数上限') + return + # print(codeli) + gameCode = codeli.get('gameCode', [{}]) + memberId = codeli.get('memberId', '') + if memberId == self.memberId: continue + for Codes in gameCode: + code = Codes.get('gameCode', '') + self.copuHelp(code) + else: + code_list = list(inviteCode.values()) + print('>>开始为第一个账号助力') + if not self.canhelp_coup: + print(f'>>>助力次数上限') + return + gameCode = code_list[0].get('gameCode', [{}]) + for Codes in gameCode: + code = Codes.get('gameCode', '') + self.copuHelp(code) + # for codeli in GameCode: + # if not self.canhelp_coup: return + # print(codeli) + # code = codeli.get('gameCode', [{}]) + # self.copuHelp(code) + + + def copuHelp(self,code): + headers = { + "Accept": "*/*" + } + url = f'https://api.yonghuivip.com/web/marketing/boostcoupon/boost?gameCode={code}&{self.url_add}' + response = self.do_request(url, headers=headers, req_type='get') + if 'code' in response and response.get('code') == 0: + # print(response) + Log(f'>{code},助力成功!') + return True + elif response.get('message') == '每日助力次数超过限制': + self.canhelp_coup = False + return False + else: + # print(f">{code},助力失败{response.get('message')}!") + return False + + + #########试用任务 + def tryList(self,levelName=None): + if not levelName: + self.levelName = '黄金' + if self.levelName == '普通': + Log(f'当前等级【{self.levelName}】不达标,停止试用申请') + else: + Log(f'>>>开始试用申请') + headers = { + 'Accept': '*/*' + } + url = f'https://api.yonghuivip.com/web/marketing/free/trial/issue/prize/landing/page?{self.url_add}' + response = self.do_request(url, headers=headers, req_type='get') + + if 'code' in response and response.get('code') == 0: + # print(response) + if response['data']['tip'] == '本期活动报名已结束,敬请期待下期活动': + Log('>>本期活动报名已结束,敬请期待下期活动') + return False + goodsList = response['data']['currTab']['landingPagePrizeVOList'] + for liId in goodsList: + buttonStateName = liId['buttonStateName'] + self.skuTitle = liId['skuTitle'] + self.prizeId = liId['prizeId'] + if buttonStateName != '已报名': + print(f'>>产品:【{self.skuTitle}】 ID:【{self.prizeId}】【可申请】') + self.doTry() + else: + print(f'>>产品:【{self.skuTitle}】【已申请,跳过】') + + else: + Log(f'>获取失败,{response}') + + def doTry(self): + print(f'>>开始申请【{self.skuTitle}】') + headers = { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + } + data = { + "prizeId": self.prizeId + } + url = f'https://api.yonghuivip.com/web/marketing/free/trial/sign/up/fire?{self.url_add}' + response = self.do_request(url, headers=headers, data=data) + + if 'code' in response and response.get('code') == 0: + # print(response) + Log(f'>{self.skuTitle},申请成功!') + else: + Log(f'>{self.skuTitle},申请失败,{response}') + + def get_WinTryList(self): + print(f'>>>>>>获取已中奖列表>>>>>>') + headers = { + 'Accept': '*/*', + } + url = f'https://api.yonghuivip.com/web/marketing/free/trial/issue/participated/detail?fromType=1&pageNum=1&{self.url_add}' + response = self.do_request(url, headers=headers,req_type='get') + if 'code' in response and response.get('code') == 0: + data = response.get('data') + participatedVOList = data.get('participatedVOList') + for li in participatedVOList: + skuTitle = li['skuTitle'] + skuPrice = li['skuPrice'] + status = li['status'] + #1已报名 2待领券 3未中奖 4待兑换 + if status == 2: + Log(f'商品:【{skuTitle}】 价格:【{skuPrice}】 【待领券】') + elif status == 4: + Log(f'商品:【{skuTitle}】 价格:【{skuPrice}】 【待兑换】') + elif status == 6: + print(f'商品:【{skuTitle}】 价格:【{skuPrice}】 【已过期】') + elif status == 5: + print(f'商品:【{skuTitle}】 价格:【{skuPrice}】 【已兑换】') + else: + print(f'商品:【{skuTitle}】 价格:【{skuPrice}】') + # print(response) + else: + print(f'>申请失败,{response}') + def help_fun(self): + print(f"\n>>>>>>>>>>开始互助<<<<<<<<<<") + one_msg = '' + if not self.getCredit(): + return False + # # pass + # Log(f"\n********账号【{self.index}】果园互助********") + # self.helpAuthor() + # self.helpOther() + Log(f"\n********账号【{self.index}】组队互助********") + self.joinAuthorTeam() + self.joinTeam() + self.sendMsg(True) + return True + def main(self): + global one_msg + wait_time = random.randint(1000, 3000) / 1000.0 # 转换为秒 + one_msg = '' + Log(f"\n---------开始执行第{self.index}个账号>>>>>") + if not self.getCredit(): + return False + time.sleep(wait_time) # 等待 + self.sign() + time.sleep(wait_time) # 等待 + # self.teamDetail() + self.get_taskList() + time.sleep(wait_time) # 等待 + self.creatTeam() + time.sleep(wait_time) # 等待 + # Log(f'\n>>>>>>开始果园任务') + # if self.farmInfo(): + # self.plantFruit_sign() + # self.plantFruit_getTaskList() + # self.get_inviteTicket() + # self.receive_inviteWater() + # if not self.fruit_is_ripe:self.watering() + # else: + # Log('当前定位门店没有果园活动,请更换定位门店') + self.get_GrowthValue() + time.sleep(wait_time) # 等待 + self.get_GrowthtaskList() + time.sleep(wait_time) # 等待 + Log(f'\n>>>>>>开始试用任务') + self.get_WinTryList() + time.sleep(wait_time) # 等待 + self.tryList() + time.sleep(wait_time) # 等待 + Log('\n>>>>>>开始助力券任务') + self.listBoostCouponByPage() + time.sleep(wait_time) # 等待 + if self.index == 1: + self.Boostcoupon() + else: + self.Boostcoupon(GameCode) + new_data = { + self.memberId: + { + 'memberId': self.memberId, + 'gameCode': self.gamecode_li, + 'fruit_is_ripe': self.fruit_is_ripe, + # 'inviteCode': self.inviteTicket, + 'teamCode': self.teamCode, + 'shopId': self.shopid + } + } + # print(new_data) + inviteCode.update(new_data) + # print(f'当前inviteCode:\n{inviteCode}') + CHERWIN_TOOLS.SAVE_INVITE_CODE("INVITE_CODE/YHSH_INVITE_CODE.json", new_data) + self.sendMsg() + return True + + def sendMsg(self, help=False): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME, help) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + +if __name__ == '__main__': + APP_NAME='永辉生活' + ENV_NAME = 'YHSH' + CK_NAME = 'url' + print(f''' +✨✨✨ {APP_NAME}脚本✨✨✨ +✨ 功能: + 积分签到 + 种树 + 种树任务 + 成长值任务 + 试用申请 + 果园互助 + 组队互助 + 助力券助力 +✨ 抓包步骤: + 打开永辉生活APP或小程序 + 点击“我的” + 打开抓包工具 + 点击“积分签到”,找到带以下参数的链接复制: + -deviceid + -jysessionid + -shopid + -memberid + -access_token + -sign +链接示例:https://api.yonghuivip.com/web/coupon/credit/coupon/getcreditcouponpageinfo/v2?xxxxx +✨ ✨✨wxpusher一对一推送功能, + ✨需要定义变量export WXPUSHER=wxpusher的app_token,不设置则不启用wxpusher一对一推送 + ✨需要在{ENV_NAME}变量最后添加@wxpusher的UID +✨ 设置青龙变量: +export {ENV_NAME}='{CK_NAME}'多账号#分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ 默认每个账号随机助力作者一次,其余互助,后续考虑加上邀请池 +✨✨✨ @Author CHERWIN✨✨✨ + ''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = token.split('#') + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + for index, infos in enumerate(tokens): + run_result = RUN(infos, index).main() + if not run_result:continue + for index, infos in enumerate(tokens): + RUN(infos, index).help_fun() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) + diff --git a/ZTKD.py b/ZTKD.py new file mode 100755 index 0000000..e15733a --- /dev/null +++ b/ZTKD.py @@ -0,0 +1,237 @@ +# !/usr/bin/python3 +# -- coding: utf-8 -- +# ------------------------------- +# ✨✨✨ 中通快递小程序签到✨✨✨ +# ✨ 功能: +# 积分签到 +# ✨ 抓包步骤: +# 打开中通快递小程序 +# 授权登陆 +# 打开抓包工具 +# 找URl请求头带[x-token或者token] +# 复制里面的[x-token或者token]参数值 +# 参数示例:eyJhbGciOiJIUzUxMiJ9.eyJnZW5lcmF0ZVRpbWUixxxxxx +# ✨ 设置青龙变量: +# export YDKD='x-token或者token参数值'多账号#或&分割 +# export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +# ✨ ✨ 注意:抓完CK没事儿别打开小程序,重新打开小程序请重新抓包 +# ✨ 推荐cron:0 6 * * * +# ✨✨✨ @Author CHERWIN✨✨✨ +# ------------------------------- +# cron "0 6 * * *" script-path=xxx.py,tag=匹配cron用 +# const $ = new Env('中通快递小程序签到') +import json +import os +import random +import time +from datetime import datetime, date +from os import path +import requests +import hashlib +from requests.packages.urllib3.exceptions import InsecureRequestWarning +# import CHERWIN_TOOLS +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +# +if os.path.isfile('DEV_ENV.py'): + import DEV_ENV +if os.path.isfile('notify.py'): + from notify import send + print("加载通知服务成功!") +else: + print("加载通知服务失败!") +send_msg = '' +one_msg='' +def Log(cont=''): + global send_msg,one_msg + print(cont) + if cont: + one_msg += f'{cont}\n' + send_msg += f'{cont}\n' + +class RUN: + def __init__(self,info,index): + global one_msg + one_msg = '' + split_info = info.split('@') + self.token = split_info[0] + len_split_info = len(split_info) + last_info = split_info[len_split_info - 1] + self.send_UID = None + if len_split_info > 0 and "UID_" in last_info: + print('检测到设置了UID') + print(last_info) + self.send_UID = last_info + self.index = index + 1 + + self.headers = { + 'Host': 'api.ztomember.com', + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 MicroMessenger/7.0.20.1781(0x6700143B) NetType/WIFI MiniProgramEnv/Windows WindowsWechat/WMPF XWEB/6945', + 'token': self.token, + 'Content-Type': 'application/json;charset=UTF-8', + 'Accept': '*/*', + 'Sec-Fetch-Site': 'same-site', + 'Sec-Fetch-Mode': 'cors', + 'Sec-Fetch-Dest': 'empty', + 'Referer': 'https://h5.ztomember.com/', + 'Accept-Language': 'zh-CN,zh', + + } + + self.baseUrl = 'https://api.ztomember.com/api/' + self.news_List = [] + self.list_index = 0 + self.isFirstTask = True + + def get_point(self): + Log('>>>>>>获取积分信息') + json_data = {} + response = s.post(f'{self.baseUrl}user/point/get', headers=self.headers,json=json_data) + point_info = response.json() + # print(point_info) + code = point_info.get('code',-1) + if point_info.get('success',False) == True and code == 10000: + data = point_info.get('data',[{}]) + point=data.get('point',0) + mobile=data.get('mobile','') + mobile=mobile[:3] + "*" * 4 + mobile[7:] + Log(f'>>当前用户:【{mobile}】') + Log(f'>>当前积分:【{point}】') + return True + else: + Log('可能token失效了') + return False + + def Check_sign(self): + Log('>>>>>>查询签到') + json_data = {"calendarType":0} + response = s.post(f'{self.baseUrl}member/sign/v2/calendar', headers=self.headers,json=json_data) + response = response.json() + # print(point_info) + code = response.get('code', -1) + if response['success']== True and response['data'] != None and code == 10000: + data=response.get('data',{}) + dayList=data.get('dayList',[{}]) + signDays=data.get('signDays',0) + Len_dayList=len(dayList) + dates = dayList[Len_dayList-1].get('date','') + current_date = date.today() + parsed_date = datetime.strptime(dates, '%Y-%m-%d').date() + if parsed_date == current_date: + Log(f'今日已签到,连续签到【{signDays}】天') + else: + self.sign() + else: + Log(f"查询签到失败,{response['msg']}") + def sign(self): + Log('>>>>>>签到') + json_data = {} + response = s.post(f'{self.baseUrl}member/sign/v2/userSignIn', headers=self.headers,json=json_data) + point_info = response.json() + # print(point_info) + code = point_info.get('code', -1) + if point_info['success']== True and point_info['data'] != None and code == 10000: + point=point_info['data']['point'] + Log(f'>>签到成功获得:【{point}】积分') + else: + Log(f"签到失败,{point_info['msg']}") + + + + def main(self): + print(f"\n开始执行第{self.index}个账号--------------->>>>>") + if self.get_point(): + self.Check_sign() + self.get_point() + time.sleep(2) + self.sendMsg() + else: + return False + + def sendMsg(self): + if self.send_UID: + push_res = CHERWIN_TOOLS.wxpusher(self.send_UID, one_msg, APP_NAME) + print(push_res) + + +def down_file(filename, file_url): + print(f'开始下载:{filename},下载地址:{file_url}') + try: + response = requests.get(file_url, verify=False, timeout=10) + response.raise_for_status() + with open(filename + '.tmp', 'wb') as f: + f.write(response.content) + print(f'【{filename}】下载完成!') + + # 检查临时文件是否存在 + temp_filename = filename + '.tmp' + if os.path.exists(temp_filename): + # 删除原有文件 + if os.path.exists(filename): + os.remove(filename) + # 重命名临时文件 + os.rename(temp_filename, filename) + print(f'【{filename}】重命名成功!') + return True + else: + print(f'【{filename}】临时文件不存在!') + return False + except Exception as e: + print(f'【{filename}】下载失败:{str(e)}') + return False + +def import_Tools(): + global CHERWIN_TOOLS,ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode + import CHERWIN_TOOLS + ENV, APP_INFO, TIPS, TIPS_HTML, AuthorCode = CHERWIN_TOOLS.main(APP_NAME, local_script_name, ENV_NAME,local_version) + +if __name__ == '__main__': + APP_NAME = '中通快递小程序' + ENV_NAME = 'ZTKD' + CK_NAME = 'x-token或者token' + print(f''' +✨✨✨ {APP_NAME}签到✨✨✨ +✨ 功能: + 积分签到 +✨ 抓包步骤: + 打开{APP_NAME} + 授权登陆 + 打开抓包工具 + 找URl请求头带[{CK_NAME}] + 复制里面的[{CK_NAME}]参数值 +参数示例:eyJhbGciOiJIUzUxMiJ9.eyJnZW5lcmF0ZVRpbWUixxxxxx +✨ 设置青龙变量: +export {ENV_NAME}='{CK_NAME}参数值'多账号#或&分割 +export SCRIPT_UPDATE = 'False' 关闭脚本自动更新,默认开启 +✨ ✨ 注意:抓完CK没事儿别打开小程序,重新打开小程序请重新抓包 +✨ 推荐cron:0 6 * * * +✨✨✨ @Author CHERWIN✨✨✨ +''') + local_script_name = os.path.basename(__file__) + local_version = '2024.04.06' + if os.path.isfile('CHERWIN_TOOLS.py'): + import_Tools() + else: + if down_file('CHERWIN_TOOLS.py', 'https://py.cherwin.cn/CHERWIN_TOOLS.py'): + print('脚本依赖下载完成请重新运行脚本') + import_Tools() + else: + print('脚本依赖下载失败,请到https://py.cherwin.cn/CHERWIN_TOOLS.py下载最新版本依赖') + exit() + print(TIPS) + token = '' + token = ENV if ENV else token + if not token: + print(f"未填写{ENV_NAME}变量\n青龙可在环境变量设置 {ENV_NAME} 或者在本脚本文件上方将{CK_NAME}填入token =''") + exit() + tokens = CHERWIN_TOOLS.ENV_SPLIT(token) + # print(tokens) + if len(tokens) > 0: + print(f"\n>>>>>>>>>>共获取到{len(tokens)}个账号<<<<<<<<<<") + access_token = [] + for index, infos in enumerate(tokens): + s = requests.session() + s.verify = False + run_result = RUN(infos, index).main() + if not run_result: continue + if send: send(f'{APP_NAME}挂机通知', send_msg + TIPS_HTML) \ No newline at end of file diff --git a/notify.py b/notify.py new file mode 100755 index 0000000..c8b885c --- /dev/null +++ b/notify.py @@ -0,0 +1,552 @@ +#!/usr/bin/env python3 +# _*_ coding:utf-8 _*_ +import base64 +import hashlib +import hmac +import json +import os +import re +import threading +import time +import urllib.parse + +import requests + +from requests.packages.urllib3.exceptions import InsecureRequestWarning +# 禁用安全请求警告 +requests.packages.urllib3.disable_warnings(InsecureRequestWarning) +# 创建 session 对象,全局设置 verify=False +session = requests.Session() +session.verify = False + +# 原先的 print 函数和主线程的锁 +_print = print +mutex = threading.Lock() + + +# 定义新的 print 函数 +def print(text, *args, **kw): + """ + 使输出有序进行,不出现多线程同一时间输出导致错乱的问题。 + """ + with mutex: + _print(text, *args, **kw) + +# 通知服务 +# fmt: off +push_config = { + 'HITOKOTO': False, # 启用一言(随机句子) + + 'BARK_PUSH': '', # bark IP 或设备码,例:https://api.day.app/DxHcxxxxxRxxxxxxcm/ + 'BARK_ARCHIVE': '', # bark 推送是否存档 + 'BARK_GROUP': '', # bark 推送分组 + 'BARK_SOUND': '', # bark 推送声音 + + 'CONSOLE': True, # 控制台输出 + + 'DD_BOT_SECRET': '', # 钉钉机器人的 DD_BOT_SECRET + 'DD_BOT_TOKEN': '', # 钉钉机器人的 DD_BOT_TOKEN + + 'FSKEY': '', # 飞书机器人的 FSKEY + + 'GOBOT_URL': '', # go-cqhttp + # 推送到个人QQ:http://127.0.0.1/send_private_msg + # 群:http://127.0.0.1/send_group_msg + 'GOBOT_QQ': '', # go-cqhttp 的推送群或用户 + # GOBOT_URL 设置 /send_private_msg 时填入 user_id=个人QQ + # /send_group_msg 时填入 group_id=QQ群 + 'GOBOT_TOKEN': '', # go-cqhttp 的 access_token + + 'GOTIFY_URL': '', # gotify地址,如https://push.example.de:8080 + 'GOTIFY_TOKEN': '', # gotify的消息应用token + 'GOTIFY_PRIORITY': 0, # 推送消息优先级,默认为0 + + 'IGOT_PUSH_KEY': '', # iGot 聚合推送的 IGOT_PUSH_KEY + + 'PUSH_KEY': '', # server 酱的 PUSH_KEY,兼容旧版与 Turbo 版 + + 'PUSH_PLUS_TOKEN': '', # push+ 微信推送的用户令牌 + 'PUSH_PLUS_USER': '', # push+ 微信推送的群组编码 + + 'QMSG_KEY': '', # qmsg 酱的 QMSG_KEY + 'QMSG_TYPE': '', # qmsg 酱的 QMSG_TYPE + + 'QYWX_AM': '', # 企业微信应用 + + 'QYWX_KEY': '', # 企业微信机器人 + + 'TG_BOT_TOKEN': '', # tg 机器人的 TG_BOT_TOKEN,例: + 'TG_USER_ID': '', # tg 机器人的 TG_USER_ID,例:1434078534 + 'TG_API_HOST': '', # tg 代理 api + 'TG_PROXY_AUTH': '', # tg 代理认证参数 + 'TG_PROXY_HOST': '', # tg 机器人的 TG_PROXY_HOST + 'TG_PROXY_PORT': '', # tg 机器人的 TG_PROXY_PORT +} +notify_function = [] +# fmt: on + +# 首先读取 面板变量 或者 github action 运行变量 +for k in push_config: + if os.getenv(k): + v = os.getenv(k) + push_config[k] = v + +def bark(title: str, content: str) -> None: + """ + 使用 bark 推送消息。 + """ + if not push_config.get("BARK_PUSH"): + print("bark 服务的 BARK_PUSH 未设置!!\n取消推送") + return + print("bark 服务启动") + + if push_config.get("BARK_PUSH").startswith("http"): + url = f'{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}' + else: + url = f'https://api.day.app/{push_config.get("BARK_PUSH")}/{urllib.parse.quote_plus(title)}/{urllib.parse.quote_plus(content)}' + + bark_params = { + "BARK_ARCHIVE": "isArchive", + "BARK_GROUP": "group", + "BARK_SOUND": "sound", + } + params = "" + for pair in filter( + lambda pairs: pairs[0].startswith("BARK_") + and pairs[0] != "BARK_PUSH" + and pairs[1] + and bark_params.get(pairs[0]), + push_config.items(), + ): + params += f"{bark_params.get(pair[0])}={pair[1]}&" + if params: + url = url + "?" + params.rstrip("&") + response = session.get(url).json() + + if response["code"] == 200: + print("bark 推送成功!") + else: + print("bark 推送失败!") + + +def console(title: str, content: str) -> None: + """ + 使用 控制台 推送消息。 + """ + print(f"{title}\n\n{content}") + + +def dingding_bot(title: str, content: str) -> None: + """ + 使用 钉钉机器人 推送消息。 + """ + if not push_config.get("DD_BOT_SECRET") or not push_config.get("DD_BOT_TOKEN"): + print("钉钉机器人 服务的 DD_BOT_SECRET 或者 DD_BOT_TOKEN 未设置!!\n取消推送") + return + print("钉钉机器人 服务启动") + + timestamp = str(round(time.time() * 1000)) + secret_enc = push_config.get("DD_BOT_SECRET").encode("utf-8") + string_to_sign = "{}\n{}".format(timestamp, push_config.get("DD_BOT_SECRET")) + string_to_sign_enc = string_to_sign.encode("utf-8") + hmac_code = hmac.new( + secret_enc, string_to_sign_enc, digestmod=hashlib.sha256 + ).digest() + sign = urllib.parse.quote_plus(base64.b64encode(hmac_code)) + url = f'https://oapi.dingtalk.com/robot/send?access_token={push_config.get("DD_BOT_TOKEN")}×tamp={timestamp}&sign={sign}' + headers = {"Content-Type": "application/json;charset=utf-8"} + data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}} + response = session.post( + url=url, data=json.dumps(data), headers=headers, timeout=15 + ).json() + + if not response["errcode"]: + print("钉钉机器人 推送成功!") + else: + print("钉钉机器人 推送失败!") + + +def feishu_bot(title: str, content: str) -> None: + """ + 使用 飞书机器人 推送消息。 + """ + if not push_config.get("FSKEY"): + print("飞书 服务的 FSKEY 未设置!!\n取消推送") + return + print("飞书 服务启动") + + url = f'https://open.feishu.cn/open-apis/bot/v2/hook/{push_config.get("FSKEY")}' + data = {"msg_type": "text", "content": {"text": f"{title}\n\n{content}"}} + response = session.post(url, data=json.dumps(data)).json() + + if response.get("StatusCode") == 0: + print("飞书 推送成功!") + else: + print("飞书 推送失败!错误信息如下:\n", response) + + +def go_cqhttp(title: str, content: str) -> None: + """ + 使用 go_cqhttp 推送消息。 + """ + if not push_config.get("GOBOT_URL") or not push_config.get("GOBOT_QQ"): + print("go-cqhttp 服务的 GOBOT_URL 或 GOBOT_QQ 未设置!!\n取消推送") + return + print("go-cqhttp 服务启动") + + url = f'{push_config.get("GOBOT_URL")}?access_token={push_config.get("GOBOT_TOKEN")}&{push_config.get("GOBOT_QQ")}&message=标题:{title}\n内容:{content}' + response = session.get(url).json() + + if response["status"] == "ok": + print("go-cqhttp 推送成功!") + else: + print("go-cqhttp 推送失败!") + + +def gotify(title:str,content:str) -> None: + """ + 使用 gotify 推送消息。 + """ + if not push_config.get("GOTIFY_URL") or not push_config.get("GOTIFY_TOKEN"): + print("gotify 服务的 GOTIFY_URL 或 GOTIFY_TOKEN 未设置!!\n取消推送") + return + print("gotify 服务启动") + + url = f'{push_config.get("GOTIFY_URL")}/message?token={push_config.get("GOTIFY_TOKEN")}' + data = {"title": title,"message": content,"priority": push_config.get("GOTIFY_PRIORITY")} + response = session.post(url,data=data).json() + + if response.get("id"): + print("gotify 推送成功!") + else: + print("gotify 推送失败!") + + +def iGot(title: str, content: str) -> None: + """ + 使用 iGot 推送消息。 + """ + if not push_config.get("IGOT_PUSH_KEY"): + print("iGot 服务的 IGOT_PUSH_KEY 未设置!!\n取消推送") + return + print("iGot 服务启动") + + url = f'https://push.hellyw.com/{push_config.get("IGOT_PUSH_KEY")}' + data = {"title": title, "content": content} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + response = session.post(url, data=data, headers=headers).json() + + if response["ret"] == 0: + print("iGot 推送成功!") + else: + print(f'iGot 推送失败!{response["errMsg"]}') + + +def serverJ(title: str, content: str) -> None: + """ + 通过 serverJ 推送消息。 + """ + if not push_config.get("PUSH_KEY"): + print("serverJ 服务的 PUSH_KEY 未设置!!\n取消推送") + return + print("serverJ 服务启动") + + data = {"text": title, "desp": content.replace("\n", "\n\n")} + if push_config.get("PUSH_KEY").index("SCT") != -1: + url = f'https://sctapi.ftqq.com/{push_config.get("PUSH_KEY")}.send' + else: + url = f'https://sc.ftqq.com/${push_config.get("PUSH_KEY")}.send' + response = session.post(url, data=data).json() + + if response.get("errno") == 0 or response.get("code") == 0: + print("serverJ 推送成功!") + else: + print(f'serverJ 推送失败!错误码:{response["message"]}') + + +def pushplus_bot(title: str, content: str) -> None: + """ + 通过 push+ 推送消息。 + """ + if not push_config.get("PUSH_PLUS_TOKEN"): + print("PUSHPLUS 服务的 PUSH_PLUS_TOKEN 未设置!!\n取消推送") + return + print("PUSHPLUS 服务启动") + + url = "http://www.pushplus.plus/send" + data = { + "token": push_config.get("PUSH_PLUS_TOKEN"), + "title": title, + "content": content, + "topic": push_config.get("PUSH_PLUS_USER"), + } + body = json.dumps(data).encode(encoding="utf-8") + headers = {"Content-Type": "application/json"} + response = session.post(url=url, data=body, headers=headers).json() + + if response["code"] == 200: + print("PUSHPLUS 推送成功!") + + else: + + url_old = "http://pushplus.hxtrip.com/send" + headers["Accept"] = "application/json" + response = session.post(url=url_old, data=body, headers=headers).json() + + if response["code"] == 200: + print("PUSHPLUS(hxtrip) 推送成功!") + + else: + print("PUSHPLUS 推送失败!") + + +def qmsg_bot(title: str, content: str) -> None: + """ + 使用 qmsg 推送消息。 + """ + if not push_config.get("QMSG_KEY") or not push_config.get("QMSG_TYPE"): + print("qmsg 的 QMSG_KEY 或者 QMSG_TYPE 未设置!!\n取消推送") + return + print("qmsg 服务启动") + + url = f'https://qmsg.zendee.cn/{push_config.get("QMSG_TYPE")}/{push_config.get("QMSG_KEY")}' + payload = {"msg": f'{title}\n\n{content.replace("----", "-")}'.encode("utf-8")} + response = session.post(url=url, params=payload).json() + + if response["code"] == 0: + print("qmsg 推送成功!") + else: + print(f'qmsg 推送失败!{response["reason"]}') + + +def wecom_app(title: str, content: str) -> None: + """ + 通过 企业微信 APP 推送消息。 + """ + if not push_config.get("QYWX_AM"): + print("QYWX_AM 未设置!!\n取消推送") + return + QYWX_AM_AY = re.split(",", push_config.get("QYWX_AM")) + if title == "WsKey转换脚本" : + print("包含屏蔽词 取消推送") + return + if title == "WSKEY转换" : + print("包含屏蔽词 取消推送") + return + if 4 < len(QYWX_AM_AY) > 5: + print("QYWX_AM 设置错误!!\n取消推送") + return + print("企业微信 APP 服务启动") + corpid = QYWX_AM_AY[0] + corpsecret = QYWX_AM_AY[1] + touser = QYWX_AM_AY[2] + agentid = QYWX_AM_AY[3] + try: + media_id = QYWX_AM_AY[4] + except IndexError: + media_id = "" + wx = WeCom(corpid, corpsecret, agentid) + # 如果没有配置 media_id 默认就以 text 方式发送 + if not media_id: + message = title + "\n\n" + content + response = wx.send_text(message, touser) + else: + response = wx.send_mpnews(title, content, media_id, touser) + + if response == "ok": + print("企业微信推送成功!") + else: + print("企业微信推送失败!错误信息如下:\n", response) + + +class WeCom: + def __init__(self, corpid, corpsecret, agentid): + self.CORPID = corpid + self.CORPSECRET = corpsecret + self.AGENTID = agentid + + def get_access_token(self): + url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken" + values = { + "corpid": self.CORPID, + "corpsecret": self.CORPSECRET, + } + req = session.post(url, params=values) + data = json.loads(req.text) + return data["access_token"] + + def send_text(self, message, touser="@all"): + send_url = ( + "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + + self.get_access_token() + ) + send_values = { + "touser": touser, + "msgtype": "text", + "agentid": self.AGENTID, + "text": {"content": message}, + "safe": "0", + } + send_msges = bytes(json.dumps(send_values), "utf-8") + respone = session.post(send_url, send_msges) + respone = respone.json() + return respone["errmsg"] + + def send_mpnews(self, title, message, media_id, touser="@all"): + send_url = ( + "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + + self.get_access_token() + ) + send_values = { + "touser": touser, + "msgtype": "mpnews", + "agentid": self.AGENTID, + "mpnews": { + "articles": [ + { + "title": title, + "thumb_media_id": media_id, + "author": "Author", + "content_source_url": "", + "content": message.replace("\n", "
"), + "digest": message, + } + ] + }, + } + send_msges = bytes(json.dumps(send_values), "utf-8") + respone = session.post(send_url, send_msges) + respone = respone.json() + return respone["errmsg"] + + +def wecom_bot(title: str, content: str) -> None: + """ + 通过 企业微信机器人 推送消息。 + """ + if not push_config.get("QYWX_KEY"): + print("企业微信机器人 服务的 QYWX_KEY 未设置!!\n取消推送") + return + print("企业微信机器人服务启动") + + url = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={push_config.get('QYWX_KEY')}" + headers = {"Content-Type": "application/json;charset=utf-8"} + data = {"msgtype": "text", "text": {"content": f"{title}\n\n{content}"}} + response = session.post( + url=url, data=json.dumps(data), headers=headers, timeout=15 + ).json() + + if response["errcode"] == 0: + print("企业微信机器人推送成功!") + else: + print("企业微信机器人推送失败!") + + +def telegram_bot(title: str, content: str) -> None: + """ + 使用 telegram 机器人 推送消息。 + """ + if not push_config.get("TG_BOT_TOKEN") or not push_config.get("TG_USER_ID"): + print("tg 服务的 bot_token 或者 user_id 未设置!!\n取消推送") + return + print("tg 服务启动") + + if push_config.get("TG_API_HOST"): + url = f"https://{push_config.get('TG_API_HOST')}/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage" + else: + url = ( + f"https://api.telegram.org/bot{push_config.get('TG_BOT_TOKEN')}/sendMessage" + ) + headers = {"Content-Type": "application/x-www-form-urlencoded"} + payload = { + "chat_id": str(push_config.get("TG_USER_ID")), + "text": f"{title}\n\n{content}", + "disable_web_page_preview": "true", + } + proxies = None + if push_config.get("TG_PROXY_HOST") and push_config.get("TG_PROXY_PORT"): + if push_config.get("TG_PROXY_AUTH") is not None and "@" not in push_config.get( + "TG_PROXY_HOST" + ): + push_config["TG_PROXY_HOST"] = ( + push_config.get("TG_PROXY_AUTH") + + "@" + + push_config.get("TG_PROXY_HOST") + ) + proxyStr = "http://{}:{}".format( + push_config.get("TG_PROXY_HOST"), push_config.get("TG_PROXY_PORT") + ) + proxies = {"http": proxyStr, "https": proxyStr} + response = session.post( + url=url, headers=headers, params=payload, proxies=proxies + ).json() + + if response["ok"]: + print("tg 推送成功!") + else: + print("tg 推送失败!") + + +def one() -> str: + """ + 获取一条一言。 + :return: + """ + url = "https://v1.hitokoto.cn/" + res = session.get(url).json() + return res["hitokoto"] + " ----" + res["from"] + + +if push_config.get("BARK_PUSH"): + notify_function.append(bark) +if push_config.get("CONSOLE"): + notify_function.append(console) +if push_config.get("DD_BOT_TOKEN") and push_config.get("DD_BOT_SECRET"): + notify_function.append(dingding_bot) +if push_config.get("FSKEY"): + notify_function.append(feishu_bot) +if push_config.get("GOBOT_URL") and push_config.get("GOBOT_QQ"): + notify_function.append(go_cqhttp) +if push_config.get("GOTIFY_URL") and push_config.get("GOTIFY_TOKEN"): + notify_function.append(gotify) +if push_config.get("IGOT_PUSH_KEY"): + notify_function.append(iGot) +if push_config.get("PUSH_KEY"): + notify_function.append(serverJ) +if push_config.get("PUSH_PLUS_TOKEN"): + notify_function.append(pushplus_bot) +if push_config.get("QMSG_KEY") and push_config.get("QMSG_TYPE"): + notify_function.append(qmsg_bot) +if push_config.get("QYWX_AM"): + notify_function.append(wecom_app) +if push_config.get("QYWX_KEY"): + notify_function.append(wecom_bot) +if push_config.get("TG_BOT_TOKEN") and push_config.get("TG_USER_ID"): + notify_function.append(telegram_bot) + + +def send(title: str, content: str) -> None: + if not content: + print(f"{title} 推送内容为空!") + return + + hitokoto = push_config.get("HITOKOTO") + + text = one() if hitokoto else "" + now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + content += "\n" + text + f"推送时间:{now}" + + ts = [ + threading.Thread(target=mode, args=(title, content), name=mode.__name__) + for mode in notify_function + ] + [t.start() for t in ts] + [t.join() for t in ts] + + +def main(): + send("title", "content") + + +if __name__ == "__main__": + main()