├── Controller ├── forVPS.py ├── checkLogin.py ├── createTable.py ├── test.py ├── getEntryResults.py ├── getAccessToken.py ├── getProxy.py ├── getRefreshToken.py ├── registerAccount.py ├── iobbgen_ios.py └── launchEntry.py ├── README.md ├── Model ├── SqliteDao.py ├── NikeAccount.py └── NikeItem.py └── main.py /Controller/forVPS.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | 4 | def reconnect(): 5 | cmd_str = "rasdial ADSL /disconnect" 6 | os.system(cmd_str) 7 | time.sleep() 8 | cmd_str = "rasdial ADSL 123ABC 123456" 9 | os.system(cmd_str) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # StveaNikeBot 2 | # ⚠ 由于Nike换了抽签方式,该程序已经失效,该代码仅做参考 3 | ## 前言 4 | 断断续续写了一个月左右,基本完成了Bot的功能,并可以正常抽签,也有抽签成功的记录。但是由于抽签时间和上课时间冲突,测试的机会少,所以开源给各位作为一个抛砖引玉吧,希望更多的人可以有自己的私人bot。 5 | ## 如何运行 6 | 在第一次运行之前,运行 /Model/SqliteDao.py 中的init方法生成本地的Sqlite数据库,之后向数据库中插入账号。 7 | ### 抽签基本流程: 8 | 1.获得账号refreshToken,有效期一个月 9 | 2.使用refreshToken获得accessToken 10 | 3.使用accessToken抽签 11 | -------------------------------------------------------------------------------- /Controller/checkLogin.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | sys.path.append(r'D:\Code\Python\NikeBot V1.1\Model') 4 | import re 5 | import json 6 | import time 7 | import requests 8 | import threading 9 | from iobbgen_ios import * 10 | from NikeAccount import * 11 | from NikeItem import * 12 | from MysqlDao import * 13 | 14 | def checkLogin(username,pwd): 15 | r = requests.post('https://stvea.cn/about.php', data = {'username':username,'pwd':pwd}) 16 | if r.text=='successs': 17 | return True 18 | else: 19 | return False 20 | 21 | -------------------------------------------------------------------------------- /Controller/createTable.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | def createDataBase(): 3 | nikedb = sqlite3.connect('nike.db') 4 | nikedbCursor = nikedb.cursor() 5 | nikeac = 'CREATE TABLE `nikeaccount` (`id` int(11) NOT NULL,`email` varchar(30),`password` varchar(30),`phone` varchar(30) UNIQUE,`refreshToken` varchar(1000),`token` varchar(1000),`time` varchar(100),`accessTime` varchar(100))' 6 | nikeor = 'CREATE TABLE `nikeorder` (`id` int(11) NOT NULL,`orderid` varchar(100),`accessToken` varchar(1000),`time` varchar(100),`results` varchar(30),`accountName` varchar(100))' 7 | # nikedbCursor.execute(nikeor) 8 | if __name__ == '__main__': 9 | createDataBase() -------------------------------------------------------------------------------- /Controller/test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | import json 5 | import demjson 6 | res = "{u'skuId':u'2b31bd17-fa20-59e0-a168-ec49e233e15f', u'links': {u'self': {u'ref': u'/launch/entries/v2/2f96e678-3d73-5e31-b9f8-eb1ea43617b0'}}, u'resourceType': u'launchentry', u'estimatedResultAvailability': u'2019-03-05T01:14:09.004Z', u'launchId': u'4564eef2-6dd0-4459-a71c-f0260e7eb07e', u'creationDate': u'2019-03-05T01:14:03.952Z', u'id': u'2f96e678-3d73-5e31-b9f8-eb1ea43617b0', u'postpayLink': u'https://www.nike.com/cn/launch/t/air-max-95-nike-day-black/?LEStyleColor=BQ9131-001&LEPaymentType=Alipay'}" 7 | res = "{'skuId':'2b31bd17-fa20-59e0-a168-ec49e233e15f'}" 8 | res = demjson.decode(res) 9 | print res['skuId'] -------------------------------------------------------------------------------- /Model/SqliteDao.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | 3 | class SqliteDao: 4 | def initDataBase(self): 5 | nikeac = 'CREATE TABLE IF NOT EXISTS `nikeaccount` (`id` int(11) NOT NULL,`email` varchar(30),`password` varchar(30),`phone` varchar(30) UNIQUE,`refreshToken` varchar(1000),`token` varchar(1000),`time` varchar(100),`accessTime` varchar(100))' 6 | nikeor = 'CREATE TABLE IF NOT EXISTS `nikeorder` (`id` int(11) NOT NULL,`orderid` varchar(100),`accessToken` varchar(1000),`time` varchar(100),`results` varchar(30),`accountName` varchar(100))' 7 | SqliteDao.cur.execute(nikeac) 8 | SqliteDao.cur.execute(nikeor) 9 | 10 | def sqliteFetch(self,sql): 11 | SqliteDao.cur.execute(sql) 12 | res = SqliteDao.cur.fetchall() 13 | return res 14 | 15 | def sqliteUpdate(self,sql): 16 | SqliteDao.cur.execute(sql) 17 | SqliteDao.conn.commit() 18 | 19 | def __init__(self,dbname='nike'): 20 | SqliteDao.conn = sqlite3.connect(dbname+'.db') 21 | SqliteDao.cur = SqliteDao.conn.cursor() 22 | self.initDataBase() -------------------------------------------------------------------------------- /Model/NikeAccount.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import uuid 3 | class NikeAccount: 4 | def __init__(self,username,password,host,access_token): 5 | self.username = username 6 | self.password = password 7 | self.checkoutId = str(uuid.uuid4()) 8 | self.paymentsId = str(uuid.uuid4()) 9 | self.shippingId = str(uuid.uuid4()) 10 | self.host = host 11 | self.recipientInfo = {"lastName": 'xx ', "firstName": 'xx '} 12 | self.addressInfo = {"state": 'CN-42', "city": 'xx市', "address1": 'xx', "postalCode": "xx","address2": "xx", "county": "xx", "country": "xx"} 13 | self.access_token = access_token 14 | self.contactInfo = {"phoneNumber": 'xx', "email": 'xx@qq.com'} 15 | self.launchRecipient = {"lastName": 'xx', "firstName": 'xx', "email": 'xx@qq.com',"phoneNumber": 'xx'} 16 | self.launchAddress = {"state": 'CN-42', "city": 'xx市', "address1": 'xx', "county": "xx区", "country": "CN"} 17 | def setOrderId(id): 18 | self.OrderId = id -------------------------------------------------------------------------------- /Model/NikeItem.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import time 3 | import re 4 | import json 5 | import requests 6 | 7 | class NikeItem: 8 | 9 | def getItemInfo(self,url,shoeSize): 10 | shoesUrl = url 11 | response = requests.get(shoesUrl).text 12 | launchId = re.findall(r"\"launchViewId\":\"(.*?)\"", response, re.S | re.I)[0] 13 | size = re.findall(r"\"sizes\":(.*?),\"_fetchedAt\"", response, re.S | re.I)[0] 14 | productId = re.findall(r"product\":{\"productId\":\"(.*?)\"", response, re.S | re.I)[0] 15 | #postpayLink = getPostpayLink(productId, shoesLink) 16 | j_size = json.loads(size) 17 | return productId,j_size[str(shoeSize)]['skuId'],launchId 18 | 19 | def getPostpayLink(self,productId,shoesLink): 20 | url = "https://api.nike.com/merch/products/v2/" + productId 21 | response = requests.get(url).json() 22 | # print "[StveaSnkrsBot]System>Nike Item" 23 | postpayLink = shoesLink + "?LEStyleColor={styleColor}&LEPaymentType=Alipay".format(styleColor=response["styleColor"]) 24 | return postpayLink 25 | 26 | def __init__(self,url,size,price): 27 | NikeItem.url = url 28 | NikeItem.size = size 29 | NikeItem.price = price 30 | NikeItem.productId,NikeItem.skuId,self.launchId = self.getItemInfo(url,size) 31 | self.postpayLink = self.getPostpayLink(self.productId,self.url) -------------------------------------------------------------------------------- /Controller/getEntryResults.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import sys 3 | import time 4 | import requests 5 | sys.path.append('./Model') 6 | from SqliteDao import * 7 | def getEntryResults(): 8 | url = "https://unite.nikecloud.com/tokenRefresh?backendEnvironment=identity&locale=zh_CN&mobile=true&native=true&uxId=com.nike.commerce.snkrs.ios&sdkVersion=2.8.4&backendEnvironment=identity&platform=ios&browser=uniteSDK" 9 | while 1: 10 | orders = SqliteDao() 11 | res = orders.sqliteFetch("SELECT * FROM `nikeorder` where results is null ") 12 | # where results is null") 13 | for re in res: 14 | headers = {"authorization": "Bearer " + re[2]} 15 | try: 16 | response = requests.get("https://api.nike.com/launch/entries/v2/" + re[1], headers=headers).json() 17 | except: 18 | print "ban ip" 19 | try: 20 | if response["waitingReason"]=="OUT_OF_STOCK": 21 | print "NonWinner" 22 | orders.sqliteUpdate("UPDATE `nikeorder` SET `results`='fail' WHERE orderid = '"+re[1]+"'") 23 | print response["waitingReason"] 24 | except Exception: 25 | print response 26 | try: 27 | result = response["result"] 28 | 29 | except: 30 | continue 31 | if result["status"] == "WINNER": 32 | print "[StveaSnkrsBot]Draw Enrty username:"+re[5] 33 | orders.sqliteUpdate("UPDATE `nikeorder` SET `results`='success' WHERE orderid = '"+re[1]+"'") 34 | elif result["status"] == "NON_WINNER": 35 | print "NonWinner" 36 | orders.sqliteUpdate("UPDATE `nikeorder` SET `results`='fail' WHERE orderid = '"+re[1]+"'") -------------------------------------------------------------------------------- /Controller/getAccessToken.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import sys 3 | sys.path.append('./Model') 4 | import ttk 5 | import Tkinter as tk 6 | import requests 7 | import threading 8 | from Tkinter import * 9 | from getProxy import * 10 | from MysqlDao import * 11 | from SqliteDao import * 12 | 13 | TimeOut = 5 14 | 15 | def accessToken(id,token,isHost): 16 | url = 'https://api.nike.com/idn/shim/oauth/2.0/token' 17 | data = {'client_id':'HlHa2Cje3ctlaOqnxvgZXNaAs7T9nAuH', 18 | 'grant_type':'refresh_token', 19 | 'ux_id':'com.nike.commerce.snkrs.ios', 20 | 'refresh_token':token } 21 | try: 22 | if isHost: 23 | host = getSingleProxy() 24 | proxies = { "http": host, "https": host } 25 | a = requests.post('https://api.nike.com/idn/shim/oauth/2.0/token',json=data,verify=False,proxies=proxies, timeout=TimeOut) 26 | else: 27 | a = requests.post('https://api.nike.com/idn/shim/oauth/2.0/token',json=data,verify=False, timeout=TimeOut) 28 | except Exception: 29 | print "[StveaSnkrsBOT]"+str(id)+">代理连接失败!" 30 | return 31 | try: 32 | access_token = a.json()['access_token'] 33 | except Exception: 34 | account = SqliteDao() 35 | account.sqliteUpdate("UPDATE `nikeaccount` SET `token`= 'fail',`accessTime`='"+ str(time.time())+"' WHERE id = "+str(id)) 36 | print "[StveaSnkrsBOT]"+str(id)+">Update Access Token Fail:"+str(a.json()) 37 | return 38 | account = SqliteDao() 39 | account.sqliteUpdate("UPDATE `nikeaccount` SET `token`= '"+access_token+"',`accessTime`='"+ str(time.time())+"' WHERE id = "+str(id)) 40 | print u"[StveaSnkrsBOT]"+str(id)+">Update Access Token Success!" 41 | 42 | def mulAccessToken(isHost): 43 | account = SqliteDao() 44 | res = account.sqliteFetch("select * from nikeaccount where `refreshToken` != ''") 45 | print "[StveaSnkrsBOT]>get "+str(len(res))+" accounts Access Token" 46 | for re in res: 47 | accessToken(re[0],re[4],isHost) 48 | print "[StveaSnkrsBOT]>Finish Getting!" -------------------------------------------------------------------------------- /Controller/getProxy.py: -------------------------------------------------------------------------------- 1 | # _*_ coding:utf-8 _*_ 2 | 3 | import urllib2 4 | import random,requests,time,re 5 | 6 | proxyAPI = "https://proxy.horocn.com/api/proxies?order_id=YTDE1626729491855347&num=5&format=json&line_separator=win&can_repeat=no&loc_name=%E6%B1%9F%E8%8B%8F" 7 | MaxProxyCounts = 5 8 | ProxyCount = 0 9 | ProxyList = ['0.0.0.0','0.0.0.0','0.0.0.0','0.0.0.0','0.0.0.0'] 10 | proxyUrl = "http://api3.xiguadaili.com/ip/?tid=558658608095386&num=1&delay=1&filter=on" 11 | wandou = "http://api.wandoudl.com/api/ip?app_key=d0194613527bdce17fa055829abd45fd&pack=0&num=1&xy=1&type=1&lb=\r\n&mr=2&" 12 | 13 | def testProxy(host): 14 | head = { 15 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'} 16 | url = 'https://www.nike.com' 17 | # proxies是requests中的代理 choice是随机使用一个IP 这里http 和 https最好都写上 18 | try: 19 | request = requests.get(url, proxies={'http': host,'https':host}, headers=head,timeout=3) 20 | except Exception: 21 | return False 22 | return True 23 | 24 | def getProxy(): 25 | global ProxyCount 26 | global ProxyList 27 | global MaxProxyCounts 28 | if ProxyCount == 0: 29 | r = requests.get(proxyAPI).content 30 | json_str = json.loads(r) 31 | for h in json_str: 32 | try: 33 | host = 'http://'+h['host'] +':'+h['port'] 34 | except Exception: 35 | continue 36 | if TestProxy(host): 37 | ProxyList[ProxyCount] = host 38 | ProxyCount += 1 39 | else: 40 | continue 41 | if ProxyCount == 0: 42 | return getProxy() 43 | ProxyCount-=1 44 | return ProxyList[ProxyCount] 45 | 46 | def getSingleProxy(): 47 | host = "http://"+requests.get(proxyUrl).content 48 | if not testProxy(host): 49 | return getXiguaProxy() 50 | else: 51 | return host 52 | 53 | def getWandou(): 54 | host = requests.get(wandou).content 55 | print host 56 | return host 57 | if not testProxy(host): 58 | print "Fail:"+host 59 | return getWandou() 60 | else: 61 | return host -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import sys 3 | sys.path.append('./Controller') 4 | sys.path.append('./Model') 5 | sys.path.append('./View') 6 | 7 | from launchEntry import * 8 | from NikeItem import * 9 | from loginUI import * 10 | from getAccessToken import * 11 | from getRefreshToken import * 12 | from registerAccount import * 13 | from getEntryResults import * 14 | 15 | global isLogin 16 | 17 | 18 | def helpInfo(): 19 | print u"--------------------------------" 20 | print u" Stvea Nike Bot" 21 | print u" Verison 1.2" 22 | print u"--------------------------------" 23 | print u"Nike数据库生成于:" 24 | print u" "+os.getcwd() 25 | print u"--------------------------------" 26 | print u"[0]Exit" 27 | print u"[1]获得 Access Token" 28 | print u"[2]获得 Refresh Token by Selenium" 29 | print u"[3]注册账户 by Selenium" 30 | print u"[4]导入账户 by Txt" 31 | print u"[5]开始一次抽签" 32 | print u"[6]查询抽签结果" 33 | print u"--------------------------------" 34 | 35 | if __name__ == '__main__': 36 | while 1: 37 | helpInfo() 38 | codes = input("[StveaSnkrsBot]User>Choose Code:") 39 | if codes == 3: 40 | num = input("[StveaSnkrsBot]User>请选择注册数量:") 41 | for i in range(num): 42 | register(getWandou()) 43 | if codes == 1: 44 | flag = raw_input("[StveaSnkrsBot]User>Use host(y/n):") 45 | if flag=='y': 46 | mulAccessToken(True) 47 | else: 48 | mulAccessToken(False) 49 | if codes == 4: 50 | isHost = raw_input("[StveaSnkrsBot]User>With Token(y/n):") 51 | if isHost =='y': 52 | registerFromTxtWithRefreshToken() 53 | else: 54 | registerFromTxt() 55 | if codes == 2: 56 | isHost = raw_input("[StveaSnkrsBot]User>use host(y/n):") 57 | if isHost =='y': 58 | mulRefreshToken(True) 59 | else: 60 | mulRefreshToken(False) 61 | if codes == 6: 62 | getEntryResults() 63 | if codes == 5: 64 | itemUrl = raw_input("[StveaSnkrsBot]User>link:") 65 | itemSize = input("[StveaSnkrsBot]User>size:") 66 | itemPrice = input("[StveaSnkrsBot]User>price:") 67 | isHost = raw_input("[StveaSnkrsBot]User>host(y/n):") 68 | if isHost =='y': 69 | isHost = True 70 | else: 71 | isHost = False 72 | item = NikeItem(itemUrl,itemSize,itemPrice) 73 | mulLaunchEntry(item,isHost) -------------------------------------------------------------------------------- /Controller/getRefreshToken.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import sys 3 | sys.path.append('./Model') 4 | import time 5 | import re 6 | import json 7 | import requests 8 | from MysqlDao import * 9 | from SqliteDao import * 10 | from selenium import webdriver 11 | from selenium.common.exceptions import TimeoutException 12 | from selenium.webdriver.chrome.options import Options 13 | from selenium.webdriver.support.wait import WebDriverWait 14 | 15 | counts = 0 16 | req_url = 'https://store.nike.com/cn/zh_cn/' 17 | launch_url = 'https://www.nike.com/cn/launch/' 18 | order_url = 'https://store.nike.com/cn/zh_cn/orders/' 19 | login_url = 'https://unite.nike.com/login?' 20 | 21 | def getTokenEmail(type,username,password,host='0.0.0.0'): 22 | options = webdriver.ChromeOptions() 23 | prefs = {"profile.managed_default_content_settings.images":2} 24 | options.add_experimental_option("prefs",prefs) 25 | options.add_argument("--incognito") 26 | if host != '0.0.0.0': 27 | options.add_argument("--proxy-server="+host) 28 | print '[S]use host' 29 | options.add_argument('headless') 30 | driver = webdriver.Chrome(options=options) 31 | driver.get(req_url) 32 | try: 33 | WebDriverWait(driver,20,0.5).until(lambda x:x.find_element_by_xpath('//li[@js-hook="exp-join-login"]').is_displayed()) 34 | except TimeoutException: 35 | print('time out') 36 | else: 37 | driver.find_element_by_xpath('//li[@js-hook="exp-join-login"]').click() 38 | driver.find_element_by_link_text('使用电子邮件登录。').click() 39 | driver.find_element_by_name("emailAddress").send_keys(username) 40 | driver.find_element_by_name("password").send_keys(password) 41 | WebDriverWait(driver,20,0.5).until(lambda x:x.find_element_by_css_selector("[value='登录']").is_displayed()) 42 | driver.find_element_by_css_selector("[value='登录']").click() 43 | WebDriverWait(driver,20,0.5).until(lambda x:x.find_element_by_css_selector("[value='登录']").is_displayed()) 44 | cookies = driver.get_cookies() 45 | requests_cookies = {cookie['name']:cookie['value'] for cookie in cookies} 46 | time.sleep(10) 47 | driver.get("https://unite.nike.com/session.html") 48 | userInfo = driver.execute_script( 49 | "return localStorage.getItem('com.nike.commerce.nikedotcom.web.credential');") 50 | s = json.loads(userInfo) 51 | finally: 52 | driver.close() 53 | driver.quit() 54 | return s[type] 55 | 56 | def getTokenPhone(type,username,password,host='0.0.0.0'): 57 | options = webdriver.ChromeOptions() 58 | prefs = {"profile.managed_default_content_settings.images":2} 59 | options.add_experimental_option("prefs",prefs) 60 | options.add_argument("--incognito") 61 | if host != '0.0.0.0': 62 | options.add_argument("--proxy-server="+host) 63 | print '[S]use host' 64 | options.add_argument('headless') 65 | driver = webdriver.Chrome(options=options) 66 | driver.get(req_url) 67 | try: 68 | WebDriverWait(driver,20,0.5).until(lambda x:x.find_element_by_xpath('//li[@js-hook="exp-join-login"]').is_displayed()) 69 | except TimeoutException: 70 | print('time out') 71 | else: 72 | driver.find_element_by_xpath('//li[@js-hook="exp-join-login"]').click() 73 | driver.find_element_by_xpath('//div[@class="mobileNumber-div"]/input').send_keys(username) 74 | driver.find_element_by_xpath('//form[@id="nike-unite-mobileLoginForm"]//div[contains(@class,"password")]/input').send_keys(password) 75 | driver.find_element_by_xpath('//div[contains(@class,"mobileLoginSubmit")]').click() 76 | cookies = driver.get_cookies() 77 | requests_cookies = {cookie['name']:cookie['value'] for cookie in cookies} 78 | time.sleep(10) 79 | driver.get("https://unite.nike.com/session.html") 80 | userInfo = driver.execute_script( 81 | "return localStorage.getItem('com.nike.commerce.nikedotcom.web.credential');") 82 | s = json.loads(userInfo) 83 | finally: 84 | driver.close() 85 | driver.quit() 86 | return s[type] 87 | 88 | def refreshToken(accountId,username,password,host='0.0.0.0'): 89 | global counts 90 | account = SqliteDao() 91 | try: 92 | print "username"+username 93 | token = getTokenEmail('refresh_token',username,password,host) 94 | except Exception: 95 | counts -= 1 96 | account.sqliteUpdate("UPDATE `nikeaccount` SET `time`='failOnce' WHERE id = "+str(accountId)) 97 | print '[StveaSnkrsBOT]>update fail' 98 | return 99 | account.sqliteUpdate("UPDATE `nikeaccount` SET `refreshToken`= '"+token+"',`time`='"+ time.asctime( time.localtime(time.time()) )+"' WHERE id = "+str(accountId)) 100 | print "[StveaSnkrsBOT]Update "+username+"-"+password+" token." 101 | counts -= 1 102 | return 103 | 104 | def mulRefreshToken(isHost): 105 | global counts 106 | print "[StveaSnkrsBOT]>开始获取Refresh Token" 107 | account = SqliteDao() 108 | res = account.sqliteFetch("SELECT * FROM nikeaccount where refreshToken is NULL and phone is NULL") 109 | for re in res: 110 | refreshToken(re[0],re[1],re[2]) -------------------------------------------------------------------------------- /Controller/registerAccount.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import sys 3 | sys.path.append('./Model') 4 | import re 5 | import MySQLdb 6 | import requests 7 | import time 8 | import string 9 | import random 10 | import json 11 | import xlrd 12 | from getProxy import * 13 | from SqliteDao import * 14 | from selenium import webdriver 15 | from selenium.common.exceptions import TimeoutException 16 | from selenium.webdriver.chrome.options import Options 17 | from selenium.webdriver.support.wait import WebDriverWait 18 | 19 | # yimaToken = "011924223657bbc57ab3c37252e8159369dae533b301" 20 | # req_url = 'https://store.nike.com/cn/zh_cn/' 21 | # phone_url = 'http://api.fxhyd.cn/UserInterface.aspx?action=getmobile&token='+yimaToken+'&itemid=723' 22 | # code_url = 'http://api.fxhyd.cn/UserInterface.aspx?action=getsms&token='+yimaToken+'&itemid=723&mobile=' 23 | # code_url_back = '&release=1' 24 | # proxyAPI = "https://proxy.horocn.com/api/proxies?order_id=YTDE1626729491855347&num=10&format=json&line_separator=win&can_repeat=no&loc_name=%E6%B1%9F%E8%8B%8F%2C%E4%B8%8A%E6%B5%B7" 25 | # ProxyCount = 0 26 | # ProxyList = [] 27 | # MaxProxy = 10 28 | 29 | def register(host='0.0.0.0'): 30 | phoneNumber = requests.get(phone_url).content 31 | phoneNumber = phoneNumber.split('|')[1] 32 | options = webdriver.ChromeOptions() 33 | options.add_argument("--incognito") 34 | # options.add_argument('--headless') 35 | prefs = {"profile.managed_default_content_settings.images":2} 36 | options.add_experimental_option("prefs",prefs) 37 | # host = getProxy() 38 | if host != '0.0.0.0': 39 | ar = "--proxy-server=http://"+host 40 | print ar 41 | options.add_argument(ar) 42 | print '[StveaSnkrsBOT]Use host' 43 | options.add_argument('window-size=1200x600') 44 | driver = webdriver.Chrome(options=options) 45 | driver.get(req_url) 46 | try: 47 | WebDriverWait(driver,20,0.5).until(lambda x:x.find_element_by_xpath('//li[@js-hook="exp-join-login"]').is_displayed()) 48 | except TimeoutException: 49 | print('time out') 50 | driver.quit() 51 | else: 52 | driver.find_element_by_xpath('//li[@js-hook="exp-join-login"]').click() 53 | driver.find_element_by_link_text('立即加入。').click() 54 | driver.find_element_by_css_selector("[class='phoneNumber']").send_keys(phoneNumber) 55 | driver.find_element_by_css_selector("[class='sendCodeButton']").click() 56 | time.sleep(3) 57 | email = ''.join(random.sample(string.ascii_letters + string.digits, 8))+'98617@163.com' 58 | lastN = ''.join(random.sample(string.ascii_letters + string.digits, 3)) 59 | firstN = ''.join(random.sample(string.ascii_letters + string.digits, 3)) 60 | verifyCode = '' 61 | while 1: 62 | time.sleep(1) 63 | verify_url = code_url+phoneNumber+code_url_back 64 | verifyCode = requests.get(verify_url).content 65 | if verifyCode.find('success') != -1: 66 | verifyCode = re.findall("\d+",verifyCode)[0] 67 | print verifyCode 68 | break 69 | try: 70 | driver.find_element_by_xpath('//div[@class="verifyCode"]/input').send_keys(verifyCode) 71 | driver.find_element_by_css_selector("[value='继续']").click() 72 | WebDriverWait(driver,20,0.5).until(lambda x:x.find_element_by_css_selector("div.lastName>input").is_displayed()) 73 | driver.find_element_by_css_selector("div.lastName>input").send_keys(lastN) 74 | driver.find_element_by_css_selector("div.firstName>input").send_keys(firstN) 75 | driver.find_element_by_css_selector("div.password>input").send_keys("Aa123456") 76 | driver.find_element_by_css_selector("div.gender>ul>li").click() 77 | driver.find_element_by_css_selector("[value='注册']").click() 78 | WebDriverWait(driver,20,0.5).until(lambda x:x.find_element_by_css_selector("div.emailAddressOptional>input").is_displayed()) 79 | driver.find_element_by_css_selector("div.emailAddressOptional>input").send_keys(email) 80 | driver.find_element_by_css_selector("[value='保存']").click() 81 | print email+'!'+'Aa123456'+'!'+phoneNumber 82 | except Exception: 83 | driver.quit() 84 | return 85 | else: 86 | driver.quit() 87 | return 88 | mysql = MysqlDao() 89 | mysql.mysqlUpdate("INSERT INTO `nikeaccount`(`email`, `password`, `phone`) VALUES ('"+email+"','"+'Aa123456'+"','"+phoneNumber+"')") 90 | 91 | 92 | def registerFromTxt(): 93 | f = open("account.txt","r") 94 | line = f.readline() 95 | count = 0 96 | while line: 97 | line = line.split(':') 98 | email = line[0] 99 | pwd = line[1] 100 | sql = "INSERT INTO `nikeaccount`(`email`, `password`) VALUES ('"+email+"','"+pwd+"')" 101 | mysql = SqliteDao() 102 | mysql.sqliteUpdate(sql) 103 | count+=1 104 | line = f.readline() 105 | f.close() 106 | def registerFromExcel(): 107 | f = xlrd.open_workbook('account.xlsx') 108 | table = f.sheet_by_index(0) 109 | nrows = table.nrows 110 | sqlite = SqliteDao() 111 | print nrows 112 | for i in range(nrows): 113 | email = table.cell(i,0).value 114 | pwd = table.cell(i,1).value 115 | sql = "INSERT INTO `nikeaccount`(`email`, `password`) VALUES ('"+email+"','"+pwd+"')" 116 | sqlite.sqliteUpdate(sql) 117 | 118 | def registerFromTxtWithRefreshToken(text): 119 | f = open("/account-token.txt","r") 120 | line = f.readline() 121 | count = 0 122 | while line: 123 | line = line.split('!') 124 | email = line[0] 125 | pwd = line[1] 126 | phone = line[2] 127 | token = line[3] 128 | sql = "INSERT INTO `nikeaccount`(`email`, `password`, `phone`,`refreshToken`) VALUES ('"+email+"','"+pwd+"','"+phone+"','"+token+"')" 129 | mysql = SqliteDao() 130 | mysql.sqliteUpdate(sql) 131 | count+=1 132 | text.insert(tk.END,"[StveaSnkrsBOT]>Import "+str(count)+"st Account") 133 | line = f.readline() 134 | f.close() 135 | 136 | registerFromTxt() -------------------------------------------------------------------------------- /Controller/iobbgen_ios.py: -------------------------------------------------------------------------------- 1 | # This script is for Iovation iOS SDK version 4.3.0 2 | 3 | CURRENCY="CNY" 4 | RESOLUTION="1080X1920" 5 | MODELNO="iPhone7,1" 6 | COUNTRYCODE="cn" #ISO Country Code 7 | MODEL="iPhone" 8 | MEMORY="969" 9 | CPU="arm64v8" #uname -> machine 10 | LOCALE="zh_CN" 11 | TIMEZONE="Asia/Shanghai" 12 | KERNELVERSION="17.6.0" #uname -> release 13 | BUNDLENAME="SNKRS" 14 | MOBILENETWORKCODE="15" 15 | PROCESSNAME="SNKRS-inhouse" 16 | VOIPSUPPORTED="1" 17 | FILESYSTEMSIZE="15248" 18 | IOSVERSION="12.0.1" 19 | MOBILECOUNTRYCODE="460" # mobile country code defined in https://www.itu.int/itudoc/itu-t/ob-lists/icc/e212_685.pdf, code 234 is for UK 20 | APPID="com.nike.onenikecommerce" 21 | CURRENTRADIOACCESSTECHNOLOGY="LTE" 22 | CARRIERNAME="China Unicom" 23 | 24 | 25 | from Crypto.Cipher import AES 26 | import base64,uuid,random,os,datetime 27 | # going to use mac address ranges owned by ASUS and NETGEAR in this script, considering they are International companies manufacturing routers 28 | MACADDRESSRANGES=['00:e0:18', '00:0c:6e', '00:1b:fc', '00:1e:8c', '00:15:f2', '00:23:54', '00:1f:c6', 'f8:32:e4', '38:2c:4a', '60:a4:4c', '70:4d:7b', '88:d7:f6', '00:11:2f', '00:11:d8', '00:17:31', '00:18:f3', '48:5b:39', 'f4:6d:04', '30:85:a9', '1c:b7:2c', '40:16:7e', 'e0:3f:49', '50:46:5d', 'd0:17:c2', '2c:fd:a1', '60:45:cb', '10:7b:44', '04:92:26', '14:da:e9', '00:0e:a6', '00:13:d4', '00:26:18', '00:24:8c', 'bc:ee:7b', '08:60:6e', 'c8:60:00', '38:d5:47', '2c:4d:54', '4c:ed:fb', 'b0:6e:bf', '0c:9d:92', '90:e6:ba', 'bc:ae:c5', '10:bf:48', '14:dd:a9', '08:62:66', 'ac:9e:17', 'f0:79:59', '54:a0:50', '10:c3:7b', '78:24:af', 'd8:50:e6', '74:d0:2b', '9c:5c:8e', '70:8b:cd', '18:31:bf', '2c:56:dc', '00:1a:92', '00:1d:60', '00:22:15', '20:cf:30', 'e0:cb:4e', '1c:87:2c', '30:5a:3a', 'ac:22:0b', '54:04:a6', '34:97:f6', '04:a1:51', 'a4:2b:8c', 'a0:04:60', '9c:3d:cf', '2c:b0:5d', '50:4a:6e', '28:c6:8e', '2c:30:33', '00:14:6c', '00:09:5b', '00:0f:b5', '80:37:73', '40:5d:82', 'c0:ff:d4', '10:da:43', 'b0:39:56', 'c4:3d:c7', 'f8:73:94', '10:0d:7f', '6c:b0:ce', '50:6a:03', 'b0:7f:b9', '08:02:8e', '00:1f:33', 'c0:3f:0e', '00:24:b2', '20:4e:7f', '84:1b:5e', 'a0:21:b7', '00:22:3f', '00:1b:2f', 'e0:91:f5', '74:44:01', 'e0:46:9a', '08:bd:43', 'c4:04:15', '9c:d3:6d', '20:e5:2a', '44:94:fc', '00:8e:f2', 'b0:b9:8a', 'cc:40:d0', '78:d2:94', '3c:37:86', 'e4:f4:c6', '00:1e:2a', '00:18:4d', '00:26:f2', '30:46:9a', '4c:60:de', 'e8:fc:af', '20:0c:c8', 'dc:ef:09', 'a0:63:91', 'a0:40:a0', '8c:3b:ad', '14:59:c0'] 29 | def encrypt(x,key,pad=False): 30 | if pad: 31 | pad=16-(len(x)%16) 32 | x=x+chr(pad)*pad 33 | iv=os.urandom(16) 34 | y=AES.new(key,AES.MODE_CBC,iv) 35 | return base64.b64encode(iv+y.encrypt(x)) 36 | 37 | 38 | 39 | def generatefingerprint(): 40 | token=encrypt(uuid.uuid4().hex.upper(),'\xd7\xdf\xca2\xd0Vhu\xeb\x06\xa0\xba\n\xa2\x07O\xc1\x8b\xcf\x8f2&t\xc0\x92\xc4\xa5\x0b>\xb4\xe7\xbc') 41 | data = { 42 | "CURR": CURRENCY, 43 | "ICTKN": base64.b64encode('bplist00\xd4\x01\x02\x03\x04\x05\x06\t\nX$versionX$objectsY$archiverT$top\x12\x00\x01\x86\xa0\xa2\x07\x08U$nullO\x10\x14'+os.urandom(20)+'_\x10\x0fNSKeyedArchiver\xd1\x0b\x0cTroot\x80\x01\x08\x11\x1a#-27:@Wilq\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\r\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00s'), # UbiquityIdentityToken(identity token for the icloud account the device is logged into) stored in NSKeyedArchiver format 44 | "PLUG": str(random.randint(0,1)), # battery state(charging or not) 45 | "RES": RESOLUTION, 46 | "MODEL": MODELNO, 47 | "BATL": "0.{0:02d}".format(random.randint(20,99)), # Battery charge level 48 | "IDN": os.urandom(16).encode('hex').upper(), # md5 hash of device name 49 | "CARCC": COUNTRYCODE, 50 | "IDM": MODEL, 51 | "PHYMEM": MEMORY, 52 | "AID": str(uuid.uuid4()).upper(), # device IDFA = ASIdentifierManager.sharedManager().advertisingIdentifier.UUIDString 53 | "BBSC": "iOS", 54 | "CPU": CPU, 55 | "SIM": "0", 56 | "ISBRT": "0.{0:02d}".format(random.randint(30,99)), 57 | "LANG": LOCALE, 58 | "TZ": TIMEZONE, 59 | "KERV": KERNELVERSION, 60 | "APPV": "19546", 61 | "LSEN": "1", # Location service enables 62 | "APPN": BUNDLENAME, 63 | "JAIL": "0", 64 | "CARNC": MOBILENETWORKCODE, # mobile network code 65 | "CLIENT_TIME": datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]+"Z", 66 | "ICVOIP": VOIPSUPPORTED, 67 | "EXEN": PROCESSNAME, 68 | "ASTOKEN": token, 69 | "KCITOKEN": token, 70 | "BBRT": str(float(random.randint(10000,100000))/100000), # time passed since CLIENT_TIME was calculated 71 | "VID": str(uuid.uuid4()).upper(), # identifierForVendor 72 | "IRAD": CURRENTRADIOACCESSTECHNOLOGY, 73 | "CDTOKEN": token, 74 | "CARN": CARRIERNAME, 75 | "IAOR": "portrait", 76 | "APPID": APPID, 77 | "DEBUG": "0", 78 | "UPITOKEN": token, 79 | "NETS": "{\"pdp_ip4\":{\"mac\":\"00:00:00:00:00:01\"},\"en0\":{\"ips\":[\"fe80::"+"{0:0x}:{1:0x}:{2:0x}:{3:0x}".format(random.randint(0,0xffff),random.randint(0,0xffff),random.randint(0,0xffff),random.randint(0,0xffff))+"\",\"192.168.0."+str(random.randint(1,254))+"\"]},\"utun0\":{\"ips\":[\"fe80::"+"{0:0x}:{1:0x}:{2:0x}:{3:0x}".format(random.randint(0,0xffff),random.randint(0,0xffff),random.randint(0,0xffff),random.randint(0,0xffff))+"\"]},\"pdp_ip2\":{\"mac\":\"00:00:00:00:00:01\"},\"pdp_ip0\":{\"ips\":[\"10."+"{0}.{1}.{2}".format(random.randint(0,0xff),random.randint(0,0xff),random.randint(1,0xfe))+"\"]},\"awdl0\":{\"ips\":[\"fe80::"+"{0:0x}:{1:0x}:{2:0x}:{3:0x}".format(random.randint(0,0xffff),random.randint(0,0xffff),random.randint(0,0xffff),random.randint(0,0xffff))+"\"]},\"pdp_ip1\":{\"mac\":\"00:00:00:00:00:01\"}}", 80 | "CPUCNT": "2", 81 | "IDOR": "portrait", 82 | "KCSTAG": encrypt(uuid.uuid4().hex.upper(),'\xd7\xdf\xca2\xd0Vhu\xeb\x06\xa0\xba\n\xa2\x07O\xc1\x8b\xcf\x8f2&t\xc0\x92\xc4\xa5\x0b>\xb4\xe7\xbc'), 83 | "UPTIME": "{0}.{1:02d}".format(random.randint(10000,200000),random.randint(1,99)), 84 | "SSID": os.urandom(16).encode('hex').upper(), # md5 hash of wifi ssid 85 | "BSSID": random.choice(MACADDRESSRANGES)+ (":%02x:%02x:%02x" % (random.randint(0,0xff),random.randint(0,0xff),random.randint(0,0xff))), 86 | "PROX": "1", # proximity on 87 | "SDKBN": "1480723456", 88 | "FSSZ": FILESYSTEMSIZE, # file system size 89 | "PRON": PROCESSNAME, 90 | "OSVER": IOSVERSION, 91 | "OS": "iOS", 92 | "SDKVER": "4.3.0", 93 | "CARMC": MOBILECOUNTRYCODE 94 | } 95 | q=["05000033"] 96 | for p in KEYS: 97 | q.append("{0:04X}".format(len(p))) 98 | q.append(p) 99 | val=data[p] 100 | q.append("{0:04X}".format(len(val))) 101 | q.append(val) 102 | return "0500"+encrypt("".join(q),'\x10\xc5\x14\xfb\xca\xabn=\xcd\x9dF\xb2\x0b\xd4\x03\x05\x88:\xf2J\r\x86#x\x0e\xc4CI\xc6\xa6*p',True) 103 | KEYS=['BBSC', 'BBRT', 'SDKVER', 'SDKBN', 'CLIENT_TIME', 'NETS', 'PROX', 'CDTOKEN', 'IAOR', 'SSID', 'BATL', 'CARNC', 'LSEN', 'KERV', 'CARCC', 'UPTIME', 'AID', 'CPU', 'PHYMEM', 'TZ', 'OS', 'KCSTAG', 'MODEL', 'ICTKN', 'LANG', 'ISBRT', 'APPV', 'FSSZ', 'BSSID', 'APPN', 'APPID', 'KCITOKEN', 'ICVOIP', 'JAIL', 'PRON', 'CURR', 'CARMC', 'CARN', 'EXEN', 'SIM', 'IDOR', 'RES', 'IDM', 'CPUCNT', 'VID', 'UPITOKEN', 'ASTOKEN', 'PLUG', 'IDN', 'DEBUG', 'OSVER'] 104 | 105 | # print generatefingerprint() -------------------------------------------------------------------------------- /Controller/launchEntry.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | import sys 3 | sys.path.append('./Model') 4 | import re 5 | import json 6 | import time 7 | import requests 8 | import threading 9 | from iobbgen_ios import * 10 | from NikeAccount import * 11 | from NikeItem import * 12 | from SqliteDao import * 13 | from getProxy import * 14 | from selenium import webdriver 15 | from selenium.common.exceptions import TimeoutException 16 | from selenium.webdriver.chrome.options import Options 17 | from selenium.webdriver.support.wait import WebDriverWait 18 | 19 | UserAgent = "SNKRS/3.7.2 (iPhone; iOS 12.0.1; Scale/2.00)" 20 | XAcfSensorData="1,i,nd4i9ZepIUIjJ2pbeFiG9NPzZo3Zd185BKFfum1J92pknIC4QI555jVGq6v7mX+s+gBZ0kXPjxGD7zD1+uXFO3J63csu+ZV3sQ2SxpGahhfvQ3IisCmUo0YGTAOaVGY3wo1EmUJHvzcvhq7rkL0slrit2VBSssvSOt0Voxy/EGo=,VJmkK8Lshbx+XzbC30C971fzAE9OVCUb2WGqmJwBpvQkynA+G5leN28GaYXTs9vRN9442rNU8aeulwbS0EMK+R8nOHmUEZAIbkgyeSS6+59Hb1hrnduY+eBl0zG+IsWDhMQoyqQwxpoIarUq3qGm8Goj+jV97OFtQaGLmxlZLVc=$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$18,8,26" 21 | xNikeCaller = "nike:snkrs:ios:3.7" 22 | proxyAPI = "https://proxy.horocn.com/api/proxies?order_id=YTDE1626729491855347&num=5&format=json&line_separator=win&can_repeat=no&loc_name=%E6%B1%9F%E8%8B%8F" 23 | MaxProxyCounts = 5 24 | ProxyCount = 0 25 | ProxyList = ['0.0.0.0','0.0.0.0','0.0.0.0','0.0.0.0','0.0.0.0'] 26 | EntryList = [] 27 | counts = 0 28 | DrawAccounts = 0 29 | EntryAccounts = 0 30 | 31 | def getPaymentToken(account,item): 32 | proxies = {'http': account.host, 'https': account.host} 33 | url = "https://api.nike.com/payment/preview/v2" 34 | headers = { 35 | "Accept": "application/json; charset=utf-8", 36 | "Authorization": "Bearer " + account.access_token, 37 | "Content-Type": "application/json", 38 | "x-nike-caller-id": xNikeCaller, 39 | 'x-acf-sensor-data':XAcfSensorData, 40 | "User-Agent": UserAgent, 41 | "X-NewRelic-ID": "VQYGVF5SCBADUVBRBgAGVg==" 42 | } 43 | data = {"total": item.price, "items": [{"productId": item.productId, 44 | "shippingAddress": account.addressInfo}], 45 | "checkoutId": account.checkoutId, "currency": "CNY", "paymentInfo": [ 46 | {"id": account.paymentsId, "type": "Alipay", 47 | "billingInfo": {"name": account.recipientInfo, 48 | "contactInfo": account.contactInfo, 49 | "address": account.addressInfo}}], "country": "CN"} 50 | if account.host == '0.0.0.0': 51 | try: 52 | response = requests.post(url, headers=headers, json=data).json() 53 | except Exception: 54 | print "[StveaSnkrsBOT]Error>noHost>Connect Payment Token Fail!" 55 | return 56 | else: 57 | try: 58 | response = requests.post(url, headers=headers, json=data, proxies=proxies).json() 59 | except Exception: 60 | print "[StveaSnkrsBOT]Error>Host>Connect Payment Token Fail!" 61 | return 62 | try: 63 | # print response 64 | paymentToken = response["id"] 65 | # print "[StveaSnkrsBOT]"+account.username+">Payment Token:"+str(paymentToken) 66 | except Exception: 67 | print "[StveaSnkrsBOT]Error>Payment Token Fail:"+str(response) 68 | return 69 | return paymentToken 70 | 71 | def setCheckoutId(account,item): 72 | proxies = {'http': account.host, 'https': account.host} 73 | url = "https://api.nike.com/buy/checkout_previews/v2/" + account.checkoutId 74 | headers = { 75 | "Accept": "application/json", 76 | "Authorization": "Bearer " + account.access_token, 77 | "Content-Type": "application/json", 78 | "x-nike-caller-id": xNikeCaller, 79 | 'x-acf-sensor-data':XAcfSensorData, 80 | "User-Agent": UserAgent, 81 | "X-NewRelic-ID": "VQYGVF5SCBADUVBRBgAGVg==" 82 | } 83 | data = {"request": {"email": "119174379@qq.com", 84 | "clientInfo": {"deviceId": "", "client": "com.nike.commerce.snkrs.ios"}, "currency": "CNY", 85 | "items": [{"recipient": account.recipientInfo, 86 | "shippingAddress": account.addressInfo, 87 | "id": account.shippingId, "quantity": 1, 88 | "skuId": item.skuId, 89 | "shippingMethod": "GROUND_SERVICE", 90 | "contactInfo": account.contactInfo}], 91 | "channel": "SNKRS", "locale": "zh_CN", "country": "CN"}} 92 | if account.host == '0.0.0.0': 93 | try: 94 | response = requests.put(url, headers=headers, json=data).json() 95 | except Exception: 96 | print "[StveaSnkrsBOT]Error>noHost>Connect Set Chekout ID Fail!" 97 | return 98 | else: 99 | try: 100 | response = requests.put(url, headers=headers, json=data, proxies=proxies).json() 101 | except Exception: 102 | print "[StveaSnkrsBOT]Error>Host>Connect Set Chekout ID Fail!" 103 | return 104 | # print "[StveaSnkrsBOT]"+account.username+">Set Chekout Id response:", 105 | return response 106 | 107 | def getPriceChecksum(account): 108 | proxies = {'http': account.host, 'https': account.host} 109 | url = "https://api.nike.com/buy/checkout_previews/v2/jobs/"+account.checkoutId 110 | headers = { 111 | "Accept": "application/json", 112 | "Authorization": "Bearer " + account.access_token, 113 | "Content-Type": "application/json", 114 | "x-nike-caller-id": xNikeCaller, 115 | 'x-acf-sensor-data':XAcfSensorData, 116 | "User-Agent": UserAgent, 117 | "X-NewRelic-ID": "VQYGVF5SCBADUVBRBgAGVg==" 118 | } 119 | if account.host == '0.0.0.0': 120 | try: 121 | response = requests.get(url, headers=headers).json() 122 | except requests.exceptions.Timeout: 123 | print "[StveaSnkrsBOT]Error>noHost>Timeout>Connect Price CheckSum Fail!" 124 | return 125 | except Exception as e: 126 | print "[StveaSnkrsBOT]Error>noHost>Connect Price CheckSum Fail!"+str(e) 127 | return 128 | else: 129 | try: 130 | response = requests.get(url, headers=headers,proxies=proxies).json() 131 | except requests.exceptions.Timeout: 132 | print "[StveaSnkrsBOT]Error>Host>Timeout>Connect Price CheckSum Fail!" 133 | return 134 | except Exception: 135 | print "[StveaSnkrsBOT]Error>Host>Connect Price CheckSum Fail!" 136 | return 137 | try: 138 | priceChecksum = response["response"]["priceChecksum"] 139 | except Exception: 140 | print "[StveaSnkrsBOT]Error>Get Price CheckSum Fail!"+str(response) 141 | return 142 | # print "[StveaSnkrsBOT]"+account.username+">priceChecksum:succesee!"+priceChecksum 143 | return priceChecksum 144 | 145 | def launchEntrie(account,item): 146 | global EntryList 147 | pTOKEN = getPaymentToken(account,item) 148 | setCheckoutId(account,item) 149 | PCS = getPriceChecksum(account) 150 | # time.sleep(10) 151 | proxies = {'http': account.host, 'https': account.host} 152 | url = "https://api.nike.com/launch/entries/v2" 153 | deviceId = generatefingerprint() 154 | headers = { 155 | "Authorization": "Bearer " + account.access_token, 156 | "Content-Type": "application/json", 157 | 'x-acf-sensor-data':XAcfSensorData, 158 | "x-nike-caller-id": xNikeCaller, 159 | "User-Agent":UserAgent, 160 | "X-NewRelic-ID": "VQYGVF5SCBADUVBRBgAGVg==" 161 | } 162 | data = { 163 | "deviceId": deviceId, 164 | "postpayLink": item.postpayLink, 165 | "checkoutId": account.checkoutId, 166 | "currency": "CNY", 167 | "paymentToken": pTOKEN, 168 | "shipping": { 169 | "recipient": account.launchRecipient, 170 | "method": "GROUND_SERVICE", 171 | "address": account.launchAddress 172 | }, 173 | "skuId": item.skuId, 174 | "channel": "SNKRS", 175 | "launchId": item.launchId, 176 | 177 | "priceChecksum":PCS, 178 | "locale": "zh_CN" 179 | } 180 | if account.host == '0.0.0.0': 181 | try: 182 | response = requests.post(url, headers=headers, json=data).json() 183 | except requests.exceptions.Timeout: 184 | print "[StveaSnkrsBOT]Error>noHost>Timeout>Connect Entry Fail!" 185 | return 186 | except Exception: 187 | print "[StveaSnkrsBOT]Error>noHost>Connect Entry Fail!" 188 | return 189 | else: 190 | try: 191 | response = requests.post(url, headers=headers, json=data, proxies=proxies).json() 192 | except requests.exceptions.Timeout: 193 | print "[StveaSnkrsBOT]Error>Host>Timeout>Connect Entry Fail!" 194 | return 195 | except Exception: 196 | print "[StveaSnkrsBOT]Error>Host>Connect Entry Fail!" 197 | return 198 | # print response 199 | # print "[StveaSnkrsBOT]"+account.username+">Entry response:" 200 | # try: 201 | # print response["code"] 202 | # sna = SqliteDao() 203 | # sql = "INSERT INTO `nikeorder`( `orderid`, `accessToken`, `time`,`accountName`) VALUES ('"+response['code']+"','"+account.access_token+"','"+time.asctime( time.localtime(time.time()) )+"','"+account.username+"');" 204 | # print sql 205 | # sna = sna.sqliteUpdate(sql) 206 | # except Exception: 207 | # print "as" 208 | try: 209 | na = SqliteDao() 210 | sql = "INSERT INTO nikeorder( orderid, accessToken, accountName) VALUES ('"+response['id']+"','"+account.access_token+"','"+account.username+"');" 211 | na.sqliteUpdate(sql) 212 | print "[StveaSnkrsBOT]"+account.username+">Entry Success!" 213 | except Exception: 214 | print "[StveaSnkrsBOT]Error>"+account.username+">Entry Fail!"+str(response) 215 | na = SqliteDao() 216 | sql = "INSERT INTO nikeorder(accountName) VALUES ('fail');" 217 | na.sqliteUpdate(sql) 218 | return response 219 | 220 | def mulLaunchEntry(nikeitem,useHost=False): 221 | account = SqliteDao() 222 | res = account.sqliteFetch("select * from nikeaccount where `token` != '' ORDER BY accessTime DESC") 223 | print "[StveaSnkrsBOT]System>Start Entry" 224 | print "[StveaSnkrsBOT]System>This Task have "+str(len(res))+" accouts" 225 | if useHost: 226 | host = getProxy() 227 | else: 228 | host = '0.0.0.0' 229 | for re in res: 230 | nikeaccount = NikeAccount(re[1],re[2],host,re[5]) 231 | t = threading.Thread(target=launchEntrie,args=(nikeaccount,nikeitem)) 232 | t.start() 233 | time.sleep(1) 234 | # mulRefreshToken() 235 | # mulAccessToken(False) 236 | # refreshToken("eyJhbGciOiJSUzI1NiIsImtpZCI6IjA3ZmQ4ZGJmLTU3NDktNDlkNC05NDNkLTIzNDIwMmNiYjk3MXNpZyJ9.eyJ0cnVzdCI6MTAwLCJpYXQiOjE1NTE0NTA4MjIsImV4cCI6MTU4Mjk4NjgyMiwiaXNzIjoib2F1dGgyaWR0IiwianRpIjoiOTdkZGEwOWYtYjVkYy00ZTdiLWFkMjItNDY5Yzc0MzhiMmMwIiwibGF0IjoxNTUxNDUwODIyLCJhdWQiOiJvYXV0aDJpZHQiLCJjbGkiOiJIbEhhMkNqZTNjdGxhT3FueHZnWlhOYUFzN1Q5bkF1SCIsInN1YiI6IjA0YjJiMTgwLWJhNmItNDVkOS04ZDlkLTc2NDE5NmQ5ZTg1YyIsInNidCI6Im5pa2U6cGx1cyJ9.fmU7yUpjVigDLXUTBhX8Fx7L1_21EBBz33Jkdvf2WUpsO2SnGdk_y3H0Kkh-a1_Z7d98lZvAvwzR1uT02gBwPaEF52sBvMuxLZYuLC_cwgraP5JQv3YDl8ExoZXaLds00OGudmfjszbygMropCkloi3yDFHPv7q5G3MlGe3rcC1F5fukaluc6-UDQZKkWDBkUBtaWbRQCOnk9hxj7-7rHNWCej-8yA6WEcHuqHnSd5gKJA-7Rp-kNGtaF7MmpR7yQkTOA2bLyexf2H53nlkarjWa7uB6Pm0ILHaJAzYfTeU3UBo7fTksfb8OrX7DLEi63E1kcBzb5_qUcA331XaKiA") 237 | # mulUpdateToken() 238 | # a = NikeAccount("eyJhbGciOiJSUzI1NiIsImtpZCI6Ijc2YWI1NThkLWMwZTMtNGVhYi05MTljLTJkYjA3YjFjN2NhMHNpZyJ9.eyJ0cnVzdCI6MTAwLCJpYXQiOjE1NTEyNzg0MzksImV4cCI6MTU1MTI4MjAzOSwiaXNzIjoib2F1dGgyYWNjIiwianRpIjoiOGYyNjk0ODEtNTg3Ni00YzgwLWEyZmQtOTdlNTQxODhmMTczIiwibGF0IjoxNTUxMjc4NDM5LCJhdWQiOiJjb20ubmlrZS5kaWdpdGFsIiwic3ViIjoiY29tLm5pa2UuY29tbWVyY2UubmlrZWRvdGNvbS53ZWIiLCJzYnQiOiJuaWtlOmFwcCIsInNjcCI6WyJuaWtlLmRpZ2l0YWwiXSwicHJuIjoiODRhM2I0OWMtYTMwOS00YzRlLWI0YmMtOGZkMjlhNDc4OTBjIiwicHJ0IjoibmlrZTpwbHVzIn0.CVeeun03EUVJoNN_AQF2BFF9lIciE7wOCmv3l10ttrdCUGA1w31DjBz7X7-5ELqh_j8M96Y43ReOEAPNocHB1UOXtnKLjsMjEBQc2UDDOZl_XFSaihVQQs16CqwOFo5_7k7Vypz0gdh2Oc1xLLqo8_jomQOmeDECh_IOtWwMx9OsRe3al94IQNg4maBWOM1HTLcOw5g7tat7AKU3LNH48vkz-MV_zOLlnSu7YANFIn-fBXcy3Lxc9jHRP-TBNeOtoZdclG0btoNcX1NY4C7r5AQccispO0SQuP8PBCOZMrIi6rZlSNjNND6ghgE3YN4JCBL0aVQ6afuuUruS1FubQw") 239 | # b = NikeItem("https://www.nike.com/cn/launch/t/vaporfly-4-flyknit-gyakusou-team-red-black-sail/",9,1899) 240 | # b = NikeItem("https://www.nike.com/cn/launch/t/air-zoom-pegasus-35-turbo-gyakusou-gold-dart/",9,1399) 241 | # b = NikeItem("https://www.nike.com/cn/launch/t/womens-m2k-tekno-lx-miami-black-teal-tint-bright-citron/",8.5,899) 242 | # mulLaunchEntrie(b) 243 | # getResults() 244 | # buyCheckouts(a,b) 245 | # print getProxy() --------------------------------------------------------------------------------