diff --git a/jd_jinggengInvite.py b/jd_jinggengInvite.py new file mode 100644 index 0000000..65720d4 --- /dev/null +++ b/jd_jinggengInvite.py @@ -0,0 +1,569 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +File: jd_jinggengInvite.py(jinggeng邀请入会有礼) +Author: HarbourJ +Date: 2022/8/1 22:37 +TG: https://t.me/HarbourToulu +cron: 1 1 1 1 1 1 +new Env('jinggeng邀请入会有礼'); +活动入口: https://jinggeng-isv.isvjcloud.com/ql/front/showInviteJoin?id=9e80809282a4bdc90182ab254c7e0a12&user_id=1000121005&inviterNick=Ny0m1K1tVHIJvt0j4SQ9RbRPXMHHf%2BDrNmMVfT8S5hq3SjYMAACrbEHZQ40J5yPY +变量设置: export redis_url="redis_ip", export redis_pwd="xxx"(没有可写变量) + export jinggengInviteJoin="9e80809282a4bdc90182ab254c7e0a12&1000121005"(活动id&店铺id) +""" + +import time +import requests +import sys +import re +import os +from bs4 import BeautifulSoup +from datetime import datetime +import json +import random +from urllib.parse import quote_plus, unquote_plus +import logging +logging.basicConfig(level=logging.INFO, format='%(message)s') +logger = logging.getLogger() +import warnings +warnings.filterwarnings("ignore", category=DeprecationWarning) + +from jd_sign import * +try: + from jdCookie import get_cookies + getCk = get_cookies() +except: + logger.info("请先下载依赖脚本,\n下载链接: https://raw.githubusercontent.com/HarbourJ/HarbourToulu/main/jdCookie.py") + sys.exit(3) +try: + if os.environ.get("redis_url"): + redis_url = os.environ["redis_url"] # redis ip + else: + redis_url = "172.17.0.1" + if os.environ.get("redis_pwd"): + redis_pwd = os.environ["redis_pwd"] # redis 密码 + else: + redis_pwd = "" +except: + redis_url = "172.17.0.1" + redis_pwd = "" + +try: + if os.environ.get("jinggengInviteJoin"): + jinggengInviteJoin = os.environ["jinggengInviteJoin"] + else: + jinggengInviteJoin = "9e8080e0828365a10182868854b40115&1000004385" +except: + jinggengInviteJoin = "9e80809282a4bdc90182ab254c7e0a12&1000121005" + +inviterNicks = [ + "Ny0m1K1tVHIJvt0j4SQ9RbRPXMHHf%2BDrNmMVfT8S5hq3SjYMAACrbEHZQ40J5yPY", + "pWGUWZJQ3actex0X2vQyLsjNhNaYFy2HteErE6izlhTf9nrGY7gBkCdGU4C6z%2FxD" +] +if "&" not in jinggengInviteJoin: + logger.info("⚠️jinggengInviteJoin变量有误!退出程序!") + sys.exit() +ac_id = jinggengInviteJoin.split("&")[0] +user_id = jinggengInviteJoin.split("&")[1] +inviterNick = random.choice(inviterNicks) +activity_url = f"https://jinggeng-isv.isvjcloud.com/ql/front/showInviteJoin?id={ac_id}&user_id={user_id}&inviterNick={inviterNick}" + +def redis_conn(): + try: + import redis + try: + pool = redis.ConnectionPool(host=redis_url, port=6379, decode_responses=True, socket_connect_timeout=5, password=redis_pwd) + r = redis.Redis(connection_pool=pool) + r.get('conn_test') + logger.info('✅redis连接成功') + return r + except: + logger.info("⚠️redis连接异常") + except: + logger.info("⚠️缺少redis依赖,请运行pip3 install redis") + +def getToken(ck, r=None): + try: + # redis缓存Token 活动域名+pt_pin + pt_pin = unquote_plus(re.compile(r'pt_pin=(.*?);').findall(ck)[0]) + except: + # redis缓存Token 活动域名+ck前7位(获取pin失败) + pt_pin = ck[:8] + try: + if r is not None: + Token = r.get(f'{activityUrl.split("https://")[1].split("-")[0]}_{pt_pin}') + # logger.info("Token过期时间", r.ttl(f'{activityUrl.split("https://")[1].split("-")[0]}_{pt_pin}')) + if Token is not None: + logger.info(f"♻️获取缓存Token->: {Token}") + return Token + else: + logger.info("🈳去设置Token缓存-->") + s.headers = { + 'Connection': 'keep-alive', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'User-Agent': '', + 'Cookie': ck, + 'Host': 'api.m.jd.com', + 'Referer': '', + 'Accept-Language': 'zh-Hans-CN;q=1 en-CN;q=0.9', + 'Accept': '*/*' + } + sign_txt = sign({"url": f"{activityUrl}", "id": ""}, 'isvObfuscator') + # logger.info(sign_txt) + f = s.post('https://api.m.jd.com/client.action', verify=False, timeout=30) + if f.status_code != 200: + logger.info(f.status_code) + return + else: + if "参数异常" in f.text: + return + Token_new = f.json()['token'] + logger.info(f"Token->: {Token_new}") + if r.set(f'{activityUrl.split("https://")[1].split("-")[0]}_{pt_pin}', Token_new, ex=1800): + logger.info("✅Token缓存设置成功") + else: + logger.info("❌Token缓存设置失败") + return Token_new + else: + s.headers = { + 'Connection': 'keep-alive', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'User-Agent': '', + 'Cookie': ck, + 'Host': 'api.m.jd.com', + 'Referer': '', + 'Accept-Language': 'zh-Hans-CN;q=1 en-CN;q=0.9', + 'Accept': '*/*' + } + sign_txt = sign({"url": f"{activityUrl}", "id": ""}, 'isvObfuscator') + # logger.info(sign_txt) + f = s.post('https://api.m.jd.com/client.action', verify=False, timeout=30) + if f.status_code != 200: + logger.info(f.status_code) + return + else: + if "参数异常" in f.text: + return + Token = f.json()['token'] + logger.info(f"Token->: {Token}") + return Token + except: + return + +def getJdTime(): + url = "http://api.m.jd.com/client.action?functionId=queryMaterialProducts&client=wh5" + headers = { + 'Accept': '*/*', + 'Accept-Encoding': 'gzip, deflate', + 'Accept-Language': 'zh-CN,zh;q=0.9', + 'Host': 'api.m.jd.com', + 'Proxy-Connection': 'keep-alive', + 'Upgrade-Insecure-Requests': '1', + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36' + } + try: + response = requests.request("GET", url, headers=headers, timeout=2) + if response.status_code == 200: + res = response.json() + jdTime = res['currentTime2'] + except: + jdTime = int(round(time.time() * 1000)) + return jdTime + +def randomString(e, flag=False): + t = "0123456789abcdef" + if flag: t = t.upper() + n = [random.choice(t) for _ in range(e)] + return ''.join(n) + +def refresh_cookies(res): + if res.cookies: + cookies = res.cookies.get_dict() + set_cookie = [(set_cookie + "=" + cookies[set_cookie]) for set_cookie in cookies] + global activityCookie + activityCookieMid = [i for i in activityCookie.split(';') if i != ''] + for i in activityCookieMid: + for x in set_cookie: + if i.split('=')[0] == x.split('=')[0]: + if i.split('=')[1] != x.split('=')[1]: + activityCookieMid.remove(i) + activityCookie = ''.join(sorted([(set_cookie + ";") for set_cookie in list(set(activityCookieMid + set_cookie))])) + +def getActivity(index=1, isOpenCard=0, inviterCode=None, getIndex=0): + url = f"{activityUrl}&isOpenCard={isOpenCard}&from=kouling" + if len(token) == 0: + IsvToken = '' + else: + IsvToken = f"IsvToken={token};" + headers = { + 'Host': 'jinggeng-isv.isvjcloud.com', + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'User-Agent': ua, + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Referer': url, + 'Cookie': IsvToken + activityCookie + } + response = requests.request("GET", url, headers=headers) + html_text = response.text + if response.status_code == 493: + logger.info(response.status_code, "⚠️ip疑似黑了,休息一会再来撸~") + sys.exit() + # if response.cookies: + cookies = response.cookies.get_dict() + set_cookies = [(set_cookie + "=" + cookies[set_cookie]) for set_cookie in cookies] + set_cookie = ''.join(sorted([(set_cookie + ";") for set_cookie in set_cookies])) + if getIndex == 3: + return set_cookie + if "活动时间" in html_text: + refresh_cookies(response) + soup = BeautifulSoup(html_text, 'html.parser') + errorMsg = soup.find('input', attrs={'id': 'errorMsg'})['value'] + inviteSucc = soup.find('input', attrs={'id': 'inviteSucc'})['value'] + if len(errorMsg) != 0: + errorMsg0 = errorMsg + if len(inviteSucc) != 0: + errorMsg0 = inviteSucc + if index == 1: + if getIndex == 2: + pass + shop_title = soup.find('input', attrs={'id': 'shop_title'})['value'].replace(' ', '') + actName = soup.find('input', attrs={'id': 'actName'})['value'] + shop_sid = soup.find('input', attrs={'id': 'shop_sid'})['value'] + inviteSuccNums = (soup.find('input', attrs={'id': 'helpLogs'})['value']) + inviteSetting2s = eval(soup.find('input', attrs={'id': 'inviteSetting2'})['value']) + logger.info(f"店铺名称: {shop_title} \n活动名称: {actName} \n店铺ID: {shop_sid}") + num1 = {'1': 'one', '2': 'two', '3': 'three', '4': 'four'} + num2 = {'1': 'leveOneNum', '2': 'leveTwoNum', '3': 'leveThreeNum', '4': 'leveFourNum'} + needInviteNums = [] + for a in range(len(inviteSetting2s)): + b = a + 1 + inviteSetting2 = inviteSetting2s[num1[str(b)]] + # equityEndTime = inviteSetting2['equityEndTime'] + freezeQuantity = inviteSetting2['freezeQuantity'] + availableQuantity = inviteSetting2['availableQuantity'] + equityType = inviteSetting2['equityType'] + equityName = inviteSetting2['equityName'] + leveNum = inviteSetting2[num2[str(b)]] + if equityType == "JD_GOODS": + denomination = '' + else: + denomination = inviteSetting2['denomination'] + awardId = inviteSetting2['id'] + # inviteSucc = soup.find('input', attrs={'id': 'inviteSucc'})['value'] + logger.info(f"奖品{b}: {equityName} 奖励: {denomination} 总数: {freezeQuantity}份 剩余: {availableQuantity}份 需要邀请: {leveNum}人") + if availableQuantity > 0: + needInviteNums.append((leveNum, awardId, equityType)) + if len(needInviteNums) == 0: + logger.info(f"⛈⛈⛈活动奖品全部发完啦!") + sys.exit() + return errorMsg, inviteSuccNums, needInviteNums + return errorMsg0 + elif "活动已结束" in html_text: + logger.info("😭活动已结束,下次早点来~") + sys.exit() + else: + return set_cookie + +def setMixNick(token): + url = "https://jinggeng-isv.isvjcloud.com/front/setMixNick" + payload = f"strTMMixNick={token}&userId={user_id}&source=01" + headers = { + 'Host': 'jinggeng-isv.isvjcloud.com', + 'Accept': 'application/json, text/javascript, */*; q=0.01', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'Origin': 'https://jinggeng-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': f'{activityUrl}&isOpenCard=0&from=kouling', + 'Content-Length': '116', + 'Cookie': activityCookie + } + try: + response = requests.request("POST", url, headers=headers, data=payload) + res = response.text + setMixNick0 = eval(res.replace('true', 'True').replace('false', 'False').replace('none', 'None'))['msg'] + refresh_cookies(response) + return setMixNick0 + except Exception as e: + logger.info(e) + return + +def recordActPvUvdata(token): + url = "https://jinggeng-isv.isvjcloud.com/ql/front/reportActivity/recordActPvUvData" + payload = F"userId={user_id}&actId={ac_id}" + headers = { + 'Host': 'jinggeng-isv.isvjcloud.com', + 'Accept': 'application/json, text/javascript, */*; q=0.01', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'Origin': 'https://jinggeng-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': f'{activityUrl}&isOpenCard=0&from=kouling', + 'Content-Length': '56', + 'Cookie': f"IsvToken={token};" + activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + +def checkTokenInSession(token): + url = "https://jinggeng-isv.isvjcloud.com/front/checkTokenInSession" + payload = f"userId={user_id}&token={token}" + headers = { + 'Host': 'jinggeng-isv.isvjcloud.com', + 'Accept': 'application/json, text/javascript, */*; q=0.01', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'Origin': 'https://jinggeng-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': f'{activityUrl}&isOpenCard=0&from=kouling', + 'Content-Length': '99', + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + +def shopmember(cookie): + url = f'https://shopmember.m.jd.com/shopcard/?venderId={user_id}&channel=401&returnUrl={quote_plus(activityUrl + "&isOpenCard=1")}' + headers = { + 'Host': 'shopmember.m.jd.com', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Connection': 'keep-alive', + 'Cookie': cookie, + 'User-Agent': ua, + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Referer': 'https://jinggeng-isv.isvjcloud.com/', + 'Accept-Encoding': 'gzip, deflate, br' + } + requests.request("GET", url, headers=headers) + +def bindWithVender(cookie): + try: + body = {"venderId": user_id, "shopId": user_id, "bindByVerifyCodeFlag": 1,"registerExtend": {},"writeChildFlag":0, "channel": 401} + url = f'https://api.m.jd.com/client.action?appid=jd_shop_member&functionId=bindWithVender&body={json.dumps(body)}&client=H5&clientVersion=9.2.0&uuid=88888&h5st=20220614102046318%3B7327310984571307%3Bef79a%3Btk02wa31b1c7718neoZNHBp75rw4pE%2Fw7fXko2SdFCd1vIeWy005pEHdm0lw2CimWpaw3qc9il8r9xVLHp%2Bhzmo%2B4swg%3Bdd9526fc08234276b392435c8623f4a737e07d4503fab90bf2cd98d2a3a778ac%3B3.0%3B1655173246318' + headers = { + 'Host': 'api.m.jd.com', + 'Cookie': cookie, + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive', + 'Accept': '*/*', + 'User-Agent': ua, + 'Referer': f'https://shopmember.m.jd.com/shopcard/?venderId={user_id}&channel=401&returnUrl={quote_plus(activityUrl + "&isOpenCard=1")}' + } + response = requests.get(url=url, headers=headers, timeout=30).text + res = json.loads(response) + if res['success']: + open_result = res['message'] + if "火爆" in open_result: + logger.info(f"\t⛈⛈⛈{open_result}") + else: + logger.info(f"\t🎉🎉🎉{open_result}") + return res['message'] + except Exception as e: + logger.info(e) + +def receiveInviteJoinAward(token, awardId): + url = "https://jinggeng-isv.isvjcloud.com/ql/front/receiveInviteJoinAward" + payload = f"act_id={ac_id}&user_id={user_id}&awardId={awardId}" + headers = { + 'Host': 'jinggeng-isv.isvjcloud.com', + 'Accept': 'application/json, text/javascript, */*; q=0.01', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'Origin': 'https://jinggeng-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': f'{activityUrl}&isOpenCard=0&from=kouling&sid=09a25fb32a08d0b0fbdef65ab52a40dw&un_area=15_1213_1215_50108', + 'Content-Length': '99', + 'Cookie': f"IsvToken={token};" + activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload).text + res = eval(response.replace('true', 'True').replace('false', 'False').replace('none', 'None')) + if res['succ'] is True: + msg = eval(str(res['msg']).replace('\\\\', '')) + if msg['isSendSucc']: + awardType = msg['drawAwardDto']['awardType'].replace('JD_BEAN', '京豆').replace('JD_POINT', '积分') + awardDenomination = msg['drawAwardDto']['awardDenomination'] + logger.info(f"\t🎉🎉成功领取{awardDenomination}{awardType}") + else: + logger.info(f"\t🎉🎉{res['msg']}") + + +if __name__ == '__main__': + r = redis_conn() + try: + cks = getCk + if not cks: + sys.exit() + except: + logger.info("未获取到有效COOKIE,退出程序!") + sys.exit() + global inviterCode, inviteSuccNums, activityUrl, needInviteNums, rewardIndex, firstCk + inviteSuccNums = 0 + inviterCode = inviterNick + activityUrl = activity_url + needInviteNums = None + rewardIndex = 0 + num = 0 + for cookie in cks: + num += 1 + if num == 1: + firstCk = cookie + if num % 5 == 0: + logger.info("⏰等待5s") + time.sleep(5) + global ua, activityCookie, token, getIndex + getIndex = 0 + ua = userAgent() + try: + pt_pin = re.compile(r'pt_pin=(.*?);').findall(cookie)[0] + pt_pin = unquote_plus(pt_pin) + except IndexError: + pt_pin = f'用户{num}' + logger.info(f'\n******开始【京东账号{num}】{pt_pin} *********\n') + logger.info(datetime.now()) + token = '' + activityCookie = '' + activityCookie = getActivity(num, 0, inviterCode, 0) + try: + token = getToken(cookie, r) + if token is None: + if num == 1: + logger.info(f"⚠️车头获取Token失败,退出本程序!") + # sys.exit() + os._exit() + logger.info(f"⚠️获取Token失败!⏰等待3s") + time.sleep(3) + continue + except: + logger.info(f"⚠️获取Token失败!⏰等待3s") + time.sleep(3) + continue + time.sleep(1.5) + setMixNick0 = setMixNick(token) + if setMixNick0 is None: + if num == 1: + logger.info(f"⚠️车头获取邀请码失败,退出本程序!") + sys.exit() + else: + continue + else: + logger.info(f"邀请码->: {setMixNick0}") + time.sleep(1) + logger.info(f"准备助力-->: {inviterCode}") + inviteSuccNum = getActivity(num, 0, inviterCode, 1) + if num == 1: + errorMsg0 = inviteSuccNum[0] + if "跳开卡页面" not in errorMsg0: + logger.info("无法助力自己") + inviteSuccNums0 = inviteSuccNum[1] + needInviteNums = inviteSuccNum[2] + inviteSuccNums = len(eval(inviteSuccNums0)) + logger.info(f"🛳已经邀请{inviteSuccNums}人") + for i, needNum0 in enumerate(needInviteNums): + needNum = needNum0[0] + awardId = needNum0[1] + if inviteSuccNums >= needNum: + logger.info(f"🎉恭喜已完成第{i + 1}档邀请,快去领奖吧!") + time.sleep(1) + recordActPvUvdata(token) + checkTokenInSession(token) + time.sleep(1) + if equityType == "JD_GOODS": + logger.info(f"\t🎉🎉成功获得实物奖励,请尽快前往领取:{activityUrl}") + else: + receiveInviteJoinAward(token, awardId) + rewardIndex += 1 + time.sleep(3) + if i + 1 == len(needInviteNums): + logger.info("🎉🎉🎉奖励全部领取完毕~") + sys.exit() + time.sleep(1) + inviterCode = setMixNick0 + activityUrl = f"https://jinggeng-isv.isvjcloud.com/ql/front/showInviteJoin?id={ac_id}&user_id={user_id}&inviterNick={inviterCode}" + continue + else: + errorMsg1 = inviteSuccNum + # logger.info("num != 1", errorMsg1) + if "跳开卡页面" not in errorMsg1: + if "已成功邀请您加入本店会员" in errorMsg1: + logger.info("⛈已经是会员了,无法完成助力") + else: + logger.info(f"🛳{errorMsg1}") + time.sleep(1) + continue + time.sleep(1.5) + recordActPvUvdata(token) + checkTokenInSession(token) + time.sleep(1) + shopmember(cookie) + logger.info("现在去开卡") + open_result = bindWithVender(cookie) + if open_result is not None: + if "火爆" in open_result: + time.sleep(1.5) + logger.info("\t尝试重新入会 第1次") + open_result = bindWithVender(cookie) + if "火爆" in open_result: + time.sleep(1.5) + logger.info("\t尝试重新入会 第2次") + open_result = bindWithVender(cookie) + time.sleep(1) + if num == 1: + getIndex = 2 + errorMsg2 = getActivity(num, 1, inviterCode, getIndex) + time.sleep(2) + recordActPvUvdata(token) + checkTokenInSession(token) + # logger.info(errorMsg2, '============================') + if num == 1 and "开卡失败" in errorMsg2: + logger.info(f"⚠️车头疑似火爆号,退出本程序!") + sys.exit() + if "已成功邀请您加入本店会员" in errorMsg2: + inviteSuccNums += 1 + logger.info(f"🛳已经邀请{inviteSuccNums}人") + for i, needNum1 in enumerate(needInviteNums): + # logger.info(i, needNum1) + needNum = needNum1[0] + awardId = needNum1[1] + equityType = needNum1[2] + if inviteSuccNums >= needNum: + if rewardIndex >= i + 1: + time.sleep(1) + continue + logger.info(f"🎉恭喜已完成第{i + 1}档邀请,快去领奖吧!") + token = getToken(firstCk, r) + activityCookie = getActivity(1, 0, inviterCode, 3) + setMixNick(token) + time.sleep(0.5) + recordActPvUvdata(token) + time.sleep(0.5) + if equityType == "JD_GOODS": + logger.info(f"\t🎉🎉成功获得实物奖励,请尽快前往领取:{activityUrl}") + else: + receiveInviteJoinAward(token, awardId) + rewardIndex += 1 + time.sleep(3) + if i + 1 == len(needInviteNums): + logger.info("🎉🎉🎉奖励全部领取完毕~") + sys.exit() + if num == 1: + inviterCode = setMixNick0 + activityUrl = f"https://jinggeng-isv.isvjcloud.com/ql/front/showInviteJoin?id={ac_id}&user_id={user_id}&inviterNick={inviterCode}" + + time.sleep(3) \ No newline at end of file diff --git a/jd_joinCommon_opencard.py b/jd_joinCommon_opencard.py new file mode 100644 index 0000000..2f2df53 --- /dev/null +++ b/jd_joinCommon_opencard.py @@ -0,0 +1,687 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +File: jd_joinCommon_opencard.py(通用开卡-customized系列) +Author: HarbourJ +Date: 2022/8/12 20:37 +TG: https://t.me/HarbourToulu +TgChat: https://t.me/HarbourSailing +cron: 1 1 1 1 1 1 +new Env('通用开卡-joinCommon系列'); +ActivityEntry: https://lzdz1-isv.isvjcloud.com/dingzhi/joinCommon/activity?activityId=2b870a1a74504c45995a5d5119487f3a +Description: dingzhi/joinCommon系列通用开卡脚本(通常情况下,开一张卡10豆,邀请成功获得20豆)。 + 本地sign算法+redis缓存Token+代理ip(自行配置,实测可行) + 变量: export jd_joinCommonId="2b870a1a7450xxxxxxxxxxxxx&1000000904" 变量值需要传入活动id&shopId +""" + +import time +import requests +import sys +import re +import os +from datetime import datetime +import json +import random +from urllib.parse import quote_plus, unquote_plus +from functools import partial +print = partial(print, flush=True) +import warnings +warnings.filterwarnings("ignore", category=DeprecationWarning) + +from jd_sign import * +try: + from jdCookie import get_cookies + getCk = get_cookies() +except: + print("请先下载依赖脚本,\n下载链接: https://raw.githubusercontent.com/HarbourJ/HarbourToulu/main/jdCookie.py") + sys.exit(3) + +redis_url = os.environ.get("redis_url") if os.environ.get("redis_url") else "172.17.0.1" +redis_pwd = os.environ.get("redis_pwd") if os.environ.get("redis_pwd") else "" +jd_joinCommonId = os.environ.get("jd_joinCommonId") if os.environ.get("jd_joinCommonId") else "" + +inviterUuids = [ + "4d06aea11bd64802b4d615cf3977001d", + "479fbbaa47a8494a86ecefaacb6558cc", + "7eb63ebcab3e4503bf3d2b1ee3e0afa5", +] + +inviterUuid = random.choice(inviterUuids) +if not jd_joinCommonId: + print("⚠️未发现有效活动变量,退出程序!") + sys.exit() +if jd_joinCommonId and "&" not in jd_joinCommonId: + print("⚠️活动变量错误,退出程序!") + sys.exit() +activityId = jd_joinCommonId.split('&')[0] +shopId = jd_joinCommonId.split('&')[1] +activity_url = f"https://lzdz1-isv.isvjcloud.com/dingzhi/joinCommon/activity/5929859?activityId={activityId}&shareUuid={inviterUuid}&adsource=null&shareuserid4minipg=null&lng=00.000000&lat=00.000000&sid=&un_area=&&shopid={shopId}" + +def redis_conn(): + try: + import redis + try: + pool = redis.ConnectionPool(host=redis_url, port=6379, decode_responses=True, socket_connect_timeout=5, password=redis_pwd) + r = redis.Redis(connection_pool=pool) + r.get('conn_test') + print('✅redis连接成功') + return r + except: + print("⚠️redis连接异常") + except: + print("⚠️缺少redis依赖,请运行pip3 install redis") + sys.exit() + +def getToken(ck, r=None): + host = f'{activityUrl.split("com/")[0]}com' + try: + # redis缓存Token 活动域名+pt_pin + pt_pin = unquote_plus(re.compile(r'pt_pin=(.*?);').findall(ck)[0]) + except: + # redis缓存Token 活动域名+ck前7位(获取pin失败) + pt_pin = ck[:8] + try: + if r is not None: + Token = r.get(f'{activityUrl.split("https://")[1].split("-")[0]}_{pt_pin}') + # print("Token过期时间", r.ttl(f'{activityUrl.split("https://")[1].split("-")[0]}_{pt_pin}')) + if Token is not None: + # print(f"♻️获取缓存Token->: {Token}") + print(f"♻️获取缓存Token") + return Token + else: + print("🈳去设置Token缓存") + s.headers = { + 'Connection': 'keep-alive', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'User-Agent': '', + 'Cookie': ck, + 'Host': 'api.m.jd.com', + 'Referer': '', + 'Accept-Language': 'zh-Hans-CN;q=1 en-CN;q=0.9', + 'Accept': '*/*' + } + sign_txt = sign({"url": f"{host}", "id": ""}, 'isvObfuscator') + # print(sign_txt) + f = s.post('https://api.m.jd.com/client.action', verify=False, timeout=30) + if f.status_code != 200: + print(f.status_code) + return + else: + if "参数异常" in f.text: + return + Token_new = f.json()['token'] + # print(f"Token->: {Token_new}") + if r.set(f'{activityUrl.split("https://")[1].split("-")[0]}_{pt_pin}', Token_new, ex=1800): + print("✅Token缓存设置成功") + else: + print("❌Token缓存设置失败") + return Token_new + else: + s.headers = { + 'Connection': 'keep-alive', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'User-Agent': '', + 'Cookie': ck, + 'Host': 'api.m.jd.com', + 'Referer': '', + 'Accept-Language': 'zh-Hans-CN;q=1 en-CN;q=0.9', + 'Accept': '*/*' + } + sign_txt = sign({"url": f"{host}", "id": ""}, 'isvObfuscator') + # print(sign_txt) + f = s.post('https://api.m.jd.com/client.action', verify=False, timeout=30) + if f.status_code != 200: + print(f.status_code) + return + else: + if "参数异常" in f.text: + return + Token = f.json()['token'] + print(f"Token->: {Token}") + return Token + except: + return + +def getJdTime(): + jdTime = int(round(time.time() * 1000)) + return jdTime + +def randomString(e, flag=False): + t = "0123456789abcdef" + if flag: t = t.upper() + n = [random.choice(t) for _ in range(e)] + return ''.join(n) + +def refresh_cookies(res): + if res.cookies: + cookies = res.cookies.get_dict() + set_cookie = [(set_cookie + "=" + cookies[set_cookie]) for set_cookie in cookies] + global activityCookie + activityCookieMid = [i for i in activityCookie.split(';') if i != ''] + for i in activityCookieMid: + for x in set_cookie: + if i.split('=')[0] == x.split('=')[0]: + if i.split('=')[1] != x.split('=')[1]: + activityCookieMid.remove(i) + activityCookie = ''.join(sorted([(set_cookie + ";") for set_cookie in list(set(activityCookieMid + set_cookie))])) + +def getActivity(): + url = activityUrl + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'User-Agent': ua, + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive' + } + + response = requests.request("GET", url, headers=headers) + if response.status_code == 200: + if response.cookies: + cookies = response.cookies.get_dict() + set_cookies = [(set_cookie + "=" + cookies[set_cookie]) for set_cookie in cookies] + set_cookie = ''.join(sorted([(set_cookie + ";") for set_cookie in set_cookies])) + return set_cookie + else: + print(response.status_code, "⚠️ip疑似黑了,休息一会再来撸~") + sys.exit() + +def getSystemConfigForNew(): + url = "https://lzdz1-isv.isvjcloud.com/wxCommonInfo/getSystemConfigForNew" + payload = f'activityId={activityId}&activityType=99' + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + +def getSimpleActInfoVo(): + url = "https://lzdz1-isv.isvjcloud.com/dz/common/getSimpleActInfoVo" + payload = f"activityId={activityId}" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + res = response.json() + if res['result']: + return res['data'] + else: + print(res['errorMessage']) + +def getMyPing(index, venderId): + url = "https://lzdz1-isv.isvjcloud.com/customer/getMyPing" + payload = f"userId={venderId}&token={token}&fromType=APP" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + res = response.json() + if res['result']: + return res['data']['nickname'], res['data']['secretPin'] + else: + print(f"⚠️{res['errorMessage']}") + if index == 1 and "火爆" in res['errorMessage']: + print(f"\t⛈车头黑,退出本程序!") + sys.exit() + +def accessLogWithAD(venderId, pin): + url = "https://lzdz1-isv.isvjcloud.com/common/accessLogWithAD" + payload = f"venderId={venderId}&code=99&pin={quote_plus(pin)}&activityId={activityId}&pageUrl={quote_plus(activityUrl)}&subType=app&adSource=null" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + +def getSystime(): + url = "https://lzdz1-isv.isvjcloud.com/common/getSystime" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'Accept-Encoding': 'gzip, deflate, br', + 'Cookie': activityCookie, + 'Content-Length': '0', + 'Connection': 'keep-alive', + 'Accept': 'application/json', + 'User-Agent': ua, + 'Referer': activityUrl, + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'X-Requested-With': 'XMLHttpRequest' + } + response = requests.request("POST", url, headers=headers) + refresh_cookies(response) + +def getUserInfo(pin): + url = "https://lzdz1-isv.isvjcloud.com/wxActionCommon/getUserInfo" + payload = f"pin={quote_plus(pin)}" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + res = response.json() + if res['result']: + return res['data']['nickname'], res['data']['yunMidImageUrl'], res['data']['pin'] + else: + print(res['errorMessage']) + +def activityContent(pin, pinImg, nickname): + url = "https://lzdz1-isv.isvjcloud.com/dingzhi/joinCommon/activityContent" + try: + yunMidImageUrl = quote_plus(pinImg) + except: + yunMidImageUrl = quote_plus("https://img10.360buyimg.com/imgzone/jfs/t1/21383/2/6633/3879/5c5138d8E0967ccf2/91da57c5e2166005.jpg") + payload = f"activityId={activityId}&pin={quote_plus(pin)}&pinImg={quote_plus(yunMidImageUrl)}&nick={quote_plus(nickname)}&cjyxPin=&cjhyPin=&shareUuid={shareUuid}" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': f'IsvToken={token};{activityCookie}' + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + res = response.json() + if res['result']: + return res['data'] + else: + print(res['errorMessage']) + if "活动已结束" in res['errorMessage']: + sys.exit() + +def shareRecord(pin, actorUuid): + url = "https://lzdz1-isv.isvjcloud.com/dingzhi/joinCommon/shareRecord" + payload = f"activityId={activityId}&pin={quote_plus(pin)}&uuid={actorUuid}&num=30" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + +def taskRecord(pin, actorUuid): + url = "https://lzdz1-isv.isvjcloud.com/dingzhi/joinCommon/taskRecord" + payload = f"activityId={activityId}&pin={quote_plus(pin)}&uuid={actorUuid}&taskType=" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + +def drawContent(actorUuid, pin): + url = "https://lzdz1-isv.isvjcloud.com/dingzhi/taskact/common/drawContent" + payload = f"activityId={actorUuid}&pin={quote_plus(pin)}" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + requests.request("POST", url, headers=headers, data=payload) + +def taskInfo(pin): + url = "https://lzdz1-isv.isvjcloud.com/dingzhi/joinCommon/taskInfo" + payload = f"activityId={activityId}&pin={quote_plus(pin)}" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + res = response.json() + if res['result']: + return res['data'] + else: + print(res['errorMessage']) + +def assist(pin, uuid): + url = "https://lzdz1-isv.isvjcloud.com/dingzhi/joinCommon/assist" + payload = f"activityId={activityId}&pin={quote_plus(pin)}&uuid={uuid}&shareUuid={shareUuid}" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + res = response.json() + if res['result']: + return res['data'] + else: + print(res['errorMessage']) + +def doTask(actorUuid, pin, taskType): + url = "https://lzdz1-isv.isvjcloud.com/dingzhi/joinCommon/doTask" + payload = f"activityId={activityId}&uuid={actorUuid}&pin={quote_plus(pin)}&taskType={taskType}&taskValue=" + headers = { + 'Host': 'lzdz1-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzdz1-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + res = response.json() + print('doTask', res) + if res['result']: + data = res['data'] + if data['score'] == 0: + print("\t获得 💨💨💨") + else: + print(f"\t🎉获得{data['score']}积分") + else: + print(res['errorMessage']) + +def bindWithVender(cookie, venderId): + try: + shopcard_url0 = f"https://lzdz1-isv.isvjcloud.com/dingzhi/joinCommon/activity/7854908?activityId={activityId}&shareUuid={shareUuid}" + shopcard_url = f"https://shopmember.m.jd.com/shopcard/?venderId={venderId}&channel=401&returnUrl={quote_plus(shopcard_url0)}" + body = {"venderId": venderId, "bindByVerifyCodeFlag": 1,"registerExtend": {},"writeChildFlag":0, "channel": 401} + url = f'https://api.m.jd.com/client.action?appid=jd_shop_member&functionId=bindWithVender&body={json.dumps(body)}&client=H5&clientVersion=9.2.0&uuid=88888&h5st=20220614102046318%3B7327310984571307%3Bef79a%3Btk02wa31b1c7718neoZNHBp75rw4pE%2Fw7fXko2SdFCd1vIeWy005pEHdm0lw2CimWpaw3qc9il8r9xVLHp%2Bhzmo%2B4swg%3Bdd9526fc08234276b392435c8623f4a737e07d4503fab90bf2cd98d2a3a778ac%3B3.0%3B1655173246318' + headers = { + 'Host': 'api.m.jd.com', + 'Cookie': cookie, + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive', + 'Accept': '*/*', + 'User-Agent': ua, + 'Referer': shopcard_url + } + response = requests.get(url=url, headers=headers, timeout=30).text + res = json.loads(response) + if res['success']: + return res['message'] + except Exception as e: + print(e) + +def getShopOpenCardInfo(cookie, venderId): + shopcard_url0 = f"https://lzdz1-isv.isvjcloud.com/dingzhi/joinCommon/activity/7854908?activityId={activityId}&shareUuid={shareUuid}" + shopcard_url = f"https://shopmember.m.jd.com/shopcard/?venderId={venderId}&channel=401&returnUrl={quote_plus(shopcard_url0)}" + try: + body = {"venderId": str(venderId), "channel": "401"} + url = f'https://api.m.jd.com/client.action?appid=jd_shop_member&functionId=getShopOpenCardInfo&body={json.dumps(body)}&client=H5&clientVersion=9.2.0&uuid=88888' + headers = { + 'Host': 'api.m.jd.com', + 'Accept': '*/*', + 'Connection': 'keep-alive', + 'Cookie': cookie, + 'User-Agent': ua, + 'Accept-Language': 'zh-cn', + 'Referer': shopcard_url, + 'Accept-Encoding': 'gzip, deflate' + } + response = requests.get(url=url, headers=headers, timeout=5).text + res = json.loads(response) + if res['success']: + venderCardName = res['result']['shopMemberCardInfo']['venderCardName'] + return venderCardName + else: + return venderId + except: + return venderId + + +if __name__ == '__main__': + r = redis_conn() + try: + cks = getCk + if not cks: + sys.exit() + except: + print("未获取到有效COOKIE,退出程序!") + sys.exit() + global shareUuid, inviteSuccNum, activityUrl, firstCk + inviteSuccNum = 0 + shareUuid = inviterUuid + activityUrl = activity_url + num = 0 + for cookie in cks[:]: + num += 1 + if num == 1: + firstCk = cookie + if num % 8 == 0: + print("⏰等待10s,休息一下") + time.sleep(10) + global ua, activityCookie, token + ua = userAgent() + try: + pt_pin = re.compile(r'pt_pin=(.*?);').findall(cookie)[0] + pt_pin = unquote_plus(pt_pin) + except IndexError: + pt_pin = f'用户{num}' + print(f'\n******开始【京东账号{num}】{pt_pin} *********\n') + print(datetime.now()) + + token = getToken(cookie, r) + if token is None: + if num == 1: + print(f"⚠️车头获取Token失败,退出本程序!") + sys.exit() + print(f"⚠️获取Token失败!⏰等待3s") + time.sleep(3) + continue + time.sleep(0.5) + activityCookie = getActivity() + time.sleep(0.5) + getSystemConfigForNew() + time.sleep(0.3) + getSimAct = getSimpleActInfoVo() + if getSimAct: + venderId = getSimAct['venderId'] + else: + venderId = shopId + time.sleep(0.2) + getPin = getMyPing(num, venderId) + if getPin is not None: + nickname = getPin[0] + secretPin = getPin[1] + time.sleep(0.5) + accessLogWithAD(venderId, secretPin) + time.sleep(0.5) + userInfo = getUserInfo(secretPin) + time.sleep(0.8) + nickname = userInfo[0] + yunMidImageUrl = userInfo[1] + pin = userInfo[2] + actContent = activityContent(pin, yunMidImageUrl, nickname) + if not actContent: + if num == 1: + print("⚠️无法获取车头邀请码,退出本程序!") + sys.exit() + continue + hasEnd = actContent['hasEnd'] + if hasEnd: + print("活动已结束,下次早点来~") + sys.exit() + print(f"✅开启【{actContent['activityName']}】活动\n") + if num == 1: + print(f"🛳 已邀请{actContent['actorInfo']['totalAssistCount']}, 有效助力{actContent['actorInfo']['assistCount']}") + actorUuid = actContent['actorInfo']['uuid'] + taskType = actContent['taskType'] + print(f"邀请码->: {actorUuid}") + print(f"准备助力->: {shareUuid}") + time.sleep(0.5) + shareRecord(pin, actorUuid) + time.sleep(0.5) + taskRecord(pin, actorUuid) + time.sleep(0.5) + print("现在去一键关注店铺") + doTask(actorUuid, pin, 20) + time.sleep(1) + doTask(actorUuid, pin, 23) + time.sleep(1) + ass0 = assist(pin, actorUuid) + assistState0 = ass0['assistState'] + openAll0 = ass0['openCardInfo']['openAll'] + openVenderId0 = ass0['openCardInfo']['openVenderId'] + assStat = False + if openAll0: + print("已完成全部开卡任务") + if assistState0 == 0: + print("已经助力过你~") + # elif assistState0 == 0: + # print("无法助力自己~") + elif assistState0 == 3: + print("已助力过其他好友~") + elif assistState0 == 1: + print("已完成开卡关注任务,未助力过好友~") + assStat = True + else: + # print('assistStatus:', assistState0) + assStat = True + else: + print("现在去开卡") + task_info0 = taskInfo(pin) + openCardList = task_info0['1']['settingInfo'] + openCardLists = [(int(i['value']), i['name']) for i in openCardList] + unOpenCardLists = [i for i in openCardLists if i[0] not in openVenderId0] + for shop in unOpenCardLists: + print(f"去开卡 {shop[1]} {shop[0]}") + venderId = shop[0] + venderCardName = shop[1] + getShopOpenCardInfo(cookie, venderId) + open_result = bindWithVender(cookie, venderId) + if open_result is not None: + if "火爆" in open_result: + time.sleep(1.5) + print("\t尝试重新入会 第1次") + open_result = bindWithVender(cookie, venderId) + if "火爆" in open_result: + time.sleep(1.5) + print("\t尝试重新入会 第2次") + open_result = bindWithVender(cookie, venderId) + if "火爆" in open_result: + print(f"\t⛈⛈{venderCardName} {open_result}") + assStat = False + else: + print(f"\t🎉🎉{venderCardName} {open_result}") + assStat = True + time.sleep(1.5) + activityContent(pin, yunMidImageUrl, nickname) + shareRecord(pin, actorUuid) + time.sleep(0.5) + taskRecord(pin, actorUuid) + time.sleep(0.5) + ass1 = assist(pin, actorUuid) + assistState1 = ass1['assistState'] + if assStat and assistState1 == 1: + print("🎉🎉🎉助力成功~") + inviteSuccNum += 1 + print(f"本次车头已邀请{inviteSuccNum}人") + + if num == 1: + print(f"后面账号全部助力 {actorUuid}") + if num == 1: + shareUuid = actorUuid + activityUrl = f"https://lzdz1-isv.isvjcloud.com/dingzhi/joinCommon/activity/5929859?activityId={activityId}&shareUuid={shareUuid}&adsource=null&shareuserid4minipg=null&lng=00.000000&lat=00.000000&sid=&un_area=&&shopid={shopId}" + + time.sleep(3) \ No newline at end of file diff --git a/jd_sign.so b/jd_sign.so new file mode 100755 index 0000000..78bb6b8 Binary files /dev/null and b/jd_sign.so differ diff --git a/jd_wxShopGift.py b/jd_wxShopGift.py new file mode 100644 index 0000000..fa2c0ae --- /dev/null +++ b/jd_wxShopGift.py @@ -0,0 +1,396 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +File: jd_wxShopGift.py(店铺特效关注有礼) +Author: HarbourJ +Date: 2022/8/8 19:52 +TG: https://t.me/HarbourToulu +TgChat: https://t.me/HarbourSailing +cron: 1 1 1 1 1 1 +new Env('店铺特效关注有礼'); +ActivityEntry: https://lzkj-isv.isvjcloud.com/wxShopGift/activity?activityId=971e85d5dfd445e1acfc63bafffb8ecc +""" + +import time +import requests +import sys +import re +import os +from datetime import datetime +import json +import random +from urllib.parse import quote_plus, unquote_plus +from functools import partial +print = partial(print, flush=True) +import warnings +warnings.filterwarnings("ignore", category=DeprecationWarning) + +from jd_sign import * +try: + from jdCookie import get_cookies + getCk = get_cookies() +except: + print("请先下载依赖脚本,\n下载链接: https://raw.githubusercontent.com/HarbourJ/HarbourToulu/main/jdCookie.py") + sys.exit(3) +redis_url = os.environ.get("redis_url") if os.environ.get("redis_url") else "172.17.0.1" +redis_pwd = os.environ.get("redis_pwd") if os.environ.get("redis_pwd") else "" +activityId = os.environ.get("jd_wxShopGiftId") if os.environ.get("jd_wxShopGiftId") else "" + +if not activityId: + print("⚠️未发现有效活动变量,退出程序!") + sys.exit() +activityUrl = f"https://lzkj-isv.isvjcloud.com/wxShopGift/activity?activityId={activityId}" + +def redis_conn(): + try: + import redis + try: + pool = redis.ConnectionPool(host=redis_url, port=6379, decode_responses=True, socket_connect_timeout=5, password=redis_pwd) + r = redis.Redis(connection_pool=pool) + r.get('conn_test') + print('✅redis连接成功') + return r + except: + print("⚠️redis连接异常") + except: + print("⚠️缺少redis依赖,请运行pip3 install redis") + sys.exit() + +def getToken(ck, r=None): + host = f'{activityUrl.split("com/")[0]}com' + try: + # redis缓存Token 活动域名+pt_pin + pt_pin = unquote_plus(re.compile(r'pt_pin=(.*?);').findall(ck)[0]) + except: + # redis缓存Token 活动域名+ck前7位(获取pin失败) + pt_pin = ck[:8] + try: + if r is not None: + Token = r.get(f'{activityUrl.split("https://")[1].split("-")[0]}_{pt_pin}') + # print("Token过期时间", r.ttl(f'{activityUrl.split("https://")[1].split("-")[0]}_{pt_pin}')) + if Token is not None: + # print(f"♻️获取缓存Token->: {Token}") + print(f"♻️获取缓存Token") + return Token + else: + print("🈳去设置Token缓存") + s.headers = { + 'Connection': 'keep-alive', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'User-Agent': '', + 'Cookie': ck, + 'Host': 'api.m.jd.com', + 'Referer': '', + 'Accept-Language': 'zh-Hans-CN;q=1 en-CN;q=0.9', + 'Accept': '*/*' + } + sign_txt = sign({"url": f"{host}", "id": ""}, 'isvObfuscator') + # print(sign_txt) + f = s.post('https://api.m.jd.com/client.action', verify=False, timeout=30) + if f.status_code != 200: + print(f.status_code) + return + else: + if "参数异常" in f.text: + return + Token_new = f.json()['token'] + # print(f"Token->: {Token_new}") + if r.set(f'{activityUrl.split("https://")[1].split("-")[0]}_{pt_pin}', Token_new, ex=1800): + print("✅Token缓存设置成功") + else: + print("❌Token缓存设置失败") + return Token_new + else: + s.headers = { + 'Connection': 'keep-alive', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'User-Agent': '', + 'Cookie': ck, + 'Host': 'api.m.jd.com', + 'Referer': '', + 'Accept-Language': 'zh-Hans-CN;q=1 en-CN;q=0.9', + 'Accept': '*/*' + } + sign_txt = sign({"url": f"{host}", "id": ""}, 'isvObfuscator') + # print(sign_txt) + f = s.post('https://api.m.jd.com/client.action', verify=False, timeout=30) + if f.status_code != 200: + print(f.status_code) + return + else: + if "参数异常" in f.text: + return + Token = f.json()['token'] + print(f"Token->: {Token}") + return Token + except: + return + +def getJdTime(): + jdTime = int(round(time.time() * 1000)) + return jdTime + +def randomString(e, flag=False): + t = "0123456789abcdef" + if flag: t = t.upper() + n = [random.choice(t) for _ in range(e)] + return ''.join(n) + +def refresh_cookies(res): + if res.cookies: + cookies = res.cookies.get_dict() + set_cookie = [(set_cookie + "=" + cookies[set_cookie]) for set_cookie in cookies] + global activityCookie + activityCookieMid = [i for i in activityCookie.split(';') if i != ''] + for i in activityCookieMid: + for x in set_cookie: + if i.split('=')[0] == x.split('=')[0]: + if i.split('=')[1] != x.split('=')[1]: + activityCookieMid.remove(i) + activityCookie = ''.join(sorted([(set_cookie + ";") for set_cookie in list(set(activityCookieMid + set_cookie))])) + +def getActivity(): + url = f"https://lzkj-isv.isvjcloud.com/wxShopGift/activity?activityId={activityId}" + headers = { + 'Host': 'lzkj-isv.isvjcloud.com', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'User-Agent': ua, + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Connection': 'keep-alive' + } + response = requests.request("GET", url, headers=headers) + if response.status_code == 200: + if response.cookies: + cookies = response.cookies.get_dict() + set_cookies = [(set_cookie + "=" + cookies[set_cookie]) for set_cookie in cookies] + set_cookie = ''.join(sorted([(set_cookie + ";") for set_cookie in set_cookies])) + return set_cookie + else: + print(response.status_code) + print("⚠️疑似ip黑了") + sys.exit() + +def getSystemConfigForNew(): + url = "https://lzkj-isv.isvjcloud.com/wxCommonInfo/getSystemConfigForNew" + payload = f'activityId={activityId}&activityType=99' + headers = { + 'Host': 'lzkj-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzkj-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + +def getSimpleActInfoVo(): + url = "https://lzkj-isv.isvjcloud.com/customer/getSimpleActInfoVo" + payload = f"activityId={activityId}" + headers = { + 'Host': 'lzkj-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzkj-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + res = response.json() + if res['result']: + return res['data'] + +def getMyPing(venderId): + url = "https://lzkj-isv.isvjcloud.com/customer/getMyPing" + payload = f"userId={venderId}&token={token}&fromType=APP_shopGift" + headers = { + 'Host': 'lzkj-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzkj-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + res = response.json() + if res['result']: + return res['data']['nickname'], res['data']['secretPin'] + else: + print(f"⚠️{res['errorMessage']}") + +def accessLogWithAD(venderId, pin): + url = "https://lzkj-isv.isvjcloud.com/common/accessLogWithAD" + payload = f"venderId={venderId}&code=24&pin={quote_plus(pin)}&activityId={activityId}&pageUrl={quote_plus(activityUrl)}&subType=app&adSource=" + headers = { + 'Host': 'lzkj-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzkj-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + +def activityContent(pin): + url = "https://lzkj-isv.isvjcloud.com/wxShopGift/activityContent" + payload = f"activityId={activityId}&buyerPin={quote_plus(pin)}" + headers = { + 'Host': 'lzkj-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzkj-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': f'IsvToken={token};{activityCookie}' + } + response = requests.request("POST", url, headers=headers, data=payload) + refresh_cookies(response) + res = response.json() + act_label = True + reward = '' + if res['result']: + endTime = res['data']['endTime'] + list = res['data']['list'] + if getJdTime() > endTime: + print("⛈活动已结束,下次早点来~") + sys.exit() + if len(list) == 0: + print("礼品已领完") + act_label = False + return act_label + for r in list: + reward += str(r['takeNum']) + r['type'] + '' + if len(reward) > 0: + reward = reward.replace('jd', '京豆').replace('jf', '积分').replace('dq', '东券') + else: + print(f"⛈{res['errorMessage']}") + sys.exit() + return reward, act_label + +def draw(pin, nickname, reward): + url = "https://lzkj-isv.isvjcloud.com/wxShopGift/draw" + payload = f"activityId={activityId}&buyerPin={quote_plus(pin)}&hasFollow=false&accessType=app" + headers = { + 'Host': 'lzkj-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzkj-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': f'IsvToken={token};{activityCookie}' + } + response = requests.request("POST", url, headers=headers, data=payload) + res = response.json() + if res['result']: + print(f"🎉🎉🎉{nickname} 成功领取 {reward}") + else: + print(f"⛈⛈⛈{nickname} {res['errorMessage']}") + +def attendLog(venderId, pin): + url = "https://lzkj-isv.isvjcloud.com/common/attendLog" + payload = f"venderId={venderId}&activityType=24&activityId={activityId}&pin={quote_plus(pin)}&clientType=app" + headers = { + 'Host': 'lzkj-isv.isvjcloud.com', + 'Accept': 'application/json', + 'X-Requested-With': 'XMLHttpRequest', + 'Accept-Language': 'zh-CN,zh-Hans;q=0.9', + 'Accept-Encoding': 'gzip, deflate, br', + 'Content-Type': 'application/x-www-form-urlencoded', + 'Origin': 'https://lzkj-isv.isvjcloud.com', + 'User-Agent': ua, + 'Connection': 'keep-alive', + 'Referer': activityUrl, + 'Cookie': activityCookie + } + requests.request("POST", url, headers=headers, data=payload) + + +if __name__ == '__main__': + r = redis_conn() + try: + cks = getCk + if not cks: + sys.exit() + except: + print("未获取到有效COOKIE,退出程序!") + sys.exit() + num = 0 + for cookie in cks[:]: + num += 1 + if num % 9 == 0: + print("⏰等待8s,休息一下") + time.sleep(8) + global ua, activityCookie, token + ua = userAgent() + try: + pt_pin = re.compile(r'pt_pin=(.*?);').findall(cookie)[0] + pt_pin = unquote_plus(pt_pin) + except IndexError: + pt_pin = f'用户{num}' + print(f'\n******开始【京东账号{num}】{pt_pin} *********\n') + print(datetime.now()) + token = getToken(cookie, r) + if token is None: + print(f"⚠️获取Token失败!⏰等待2s") + time.sleep(2) + continue + time.sleep(0.5) + activityCookie = getActivity() + time.sleep(0.5) + getSystemConfigForNew() + time.sleep(0.3) + getSimAct = getSimpleActInfoVo() + venderId = getSimAct['venderId'] + time.sleep(0.2) + getPin = getMyPing(venderId) + if getPin is not None: + nickname = getPin[0] + secretPin = getPin[1] + time.sleep(0.3) + accessLogWithAD(venderId, secretPin) + time.sleep(0.5) + actCon = activityContent(secretPin) + if not actCon: + continue + if not actCon[1]: + continue + reward = actCon[0] + time.sleep(0.8) + draw(secretPin, nickname, reward) + + time.sleep(5) \ No newline at end of file