commit 52d3612c8a5d4af2b70469a720cf958d10ab5096 Author: CHERWIN Date: Mon Apr 8 02:14:22 2024 +0800 第一次提交 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()