├── data ├── tasks.json ├── profiles.json ├── proxies.json ├── .DS_Store └── settings.json ├── .gitignore ├── images ├── edit.png └── birdbot.png ├── pages ├── .DS_Store ├── createdialog.py ├── settingspage.py ├── proxiespage.py ├── homepage.py └── profilespage.py ├── sites ├── .DS_Store ├── walmart.py ├── bestbuy.py └── walmart_encryption.py ├── requirements.txt ├── settings.py ├── README.md ├── LICENSE ├── webhook.py ├── utils.py ├── app.py └── encrypt.js /data/tasks.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /data/profiles.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /data/proxies.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | data/profiles.json 2 | data/proxies.json 3 | -------------------------------------------------------------------------------- /data/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/natewong1313/bird-bot/HEAD/data/.DS_Store -------------------------------------------------------------------------------- /images/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/natewong1313/bird-bot/HEAD/images/edit.png -------------------------------------------------------------------------------- /pages/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/natewong1313/bird-bot/HEAD/pages/.DS_Store -------------------------------------------------------------------------------- /sites/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/natewong1313/bird-bot/HEAD/sites/.DS_Store -------------------------------------------------------------------------------- /images/birdbot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/natewong1313/bird-bot/HEAD/images/birdbot.png -------------------------------------------------------------------------------- /data/settings.json: -------------------------------------------------------------------------------- 1 | {"webhook": "", "webhookonbrowser": true, "webhookonorder": true, "webhookonfailed": true, "browseronfailed": true, "onlybuyone": true} -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyqt5==5.14.2 2 | js2py==0.68 3 | requests==2.23.0 4 | lxml==4.5.0 5 | darkdetect==0.1.1 6 | colorama==0.4.3 7 | selenium==3.141.0 8 | chromedriver-py==81.0.4044.69 9 | pycryptodome==3.4.3 10 | -------------------------------------------------------------------------------- /settings.py: -------------------------------------------------------------------------------- 1 | global webhook 2 | webhook = "" 3 | global webhook_on_browser 4 | webhook_on_browser = True 5 | global webhook_on_order 6 | webhook_on_order = True 7 | global webhook_on_failed 8 | webhook_on_failed = True 9 | global browser_on_failed 10 | browser_on_failed = True -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bird Bot 2 | [Support Discord](https://discord.gg/kfAqBKv)

3 | Bird Bot is an auto-checkout bot that currently supports Walmart and Best buy. It is intended to be used to purchase Nintendo Switch consoles. More sites will be added in the future. 4 | 5 | * Easy to use interface built on PyQt5 6 | * Waits for items to restock if they are out of stock 7 | * Optional price checker 8 | * Lighting fast auto-checkout 9 | 10 |

11 | Bird Bot UI 12 |

13 | 14 | ## Installation 15 | [View The Docs Here](https://nateskicks13.gitbook.io/bird-bot/) 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Nate 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /webhook.py: -------------------------------------------------------------------------------- 1 | import requests, time, datetime, json 2 | 3 | #modified from https://github.com/lovvskillz/python-discord-webhook 4 | 5 | class DiscordWebhook: 6 | def __init__(self, url, **kwargs): 7 | self.url = url 8 | self.content = kwargs.get("content") 9 | self.username = kwargs.get("username") 10 | self.avatar_url = kwargs.get("avatar_url") 11 | self.tts = kwargs.get("tts", False) 12 | self.files = kwargs.get("files", dict()) 13 | self.embeds = kwargs.get("embeds", []) 14 | self.proxies = kwargs.get("proxies", None) 15 | 16 | def add_file(self, file, filename): 17 | self.files["_{}".format(filename)] = (filename, file) 18 | 19 | def add_embed(self, embed): 20 | self.embeds.append(embed.__dict__ if isinstance(embed, DiscordEmbed) else embed) 21 | 22 | def remove_embed(self, index): 23 | self.embeds.pop(index) 24 | 25 | def get_embeds(self): 26 | return self.embeds 27 | 28 | def set_proxies(self, proxies): 29 | self.proxies = proxies 30 | 31 | @property 32 | def json(self): 33 | data = dict() 34 | embeds = self.embeds 35 | self.embeds = list() 36 | for embed in embeds: 37 | self.add_embed(embed) 38 | for key, value in self.__dict__.items(): 39 | if value and key not in ["url", "files", "filename"]: 40 | data[key] = value 41 | embeds_empty = all(not embed for embed in data["embeds"]) if "embeds" in data else True 42 | return data 43 | 44 | def execute(self): 45 | if bool(self.files) is False: 46 | response = requests.post(self.url, json=self.json, proxies=self.proxies) 47 | else: 48 | self.files["payload_json"] = (None, json.dumps(self.json)) 49 | response = requests.post(self.url, files=self.files, proxies=self.proxies) 50 | 51 | 52 | class DiscordEmbed: 53 | def __init__(self, **kwargs): 54 | self.title = kwargs.get("title") 55 | self.description = kwargs.get("description") 56 | self.url = kwargs.get("url") 57 | self.timestamp = kwargs.get("timestamp") 58 | self.color = kwargs.get("color") 59 | self.footer = kwargs.get("footer") 60 | self.image = kwargs.get("image") 61 | self.thumbnail = kwargs.get("thumbnail") 62 | self.video = kwargs.get("video") 63 | self.provider = kwargs.get("provider") 64 | self.author = kwargs.get("author") 65 | self.fields = kwargs.get("fields", []) 66 | 67 | def set_title(self, title): 68 | self.title = title 69 | 70 | def set_description(self, description): 71 | self.description = description 72 | 73 | def set_url(self, url): 74 | self.url = url 75 | 76 | def set_timestamp(self, timestamp=str(datetime.datetime.utcfromtimestamp(time.time()))): 77 | self.timestamp = timestamp 78 | 79 | def set_color(self, color): 80 | self.color = color 81 | 82 | def set_footer(self, **kwargs): 83 | self.footer = { 84 | "text": kwargs.get("text"), 85 | "icon_url": kwargs.get("icon_url"), 86 | "proxy_icon_url": kwargs.get("proxy_icon_url") 87 | } 88 | 89 | def set_image(self, **kwargs): 90 | self.image = { 91 | "url": kwargs.get("url"), 92 | "proxy_url": kwargs.get("proxy_url"), 93 | "height": kwargs.get("height"), 94 | "width": kwargs.get("width"), 95 | } 96 | 97 | def set_thumbnail(self, **kwargs): 98 | self.thumbnail = { 99 | "url": kwargs.get("url"), 100 | "proxy_url": kwargs.get("proxy_url"), 101 | "height": kwargs.get("height"), 102 | "width": kwargs.get("width"), 103 | } 104 | 105 | def set_video(self, **kwargs): 106 | self.video = { 107 | "url": kwargs.get("url"), 108 | "height": kwargs.get("height"), 109 | "width": kwargs.get("width"), 110 | } 111 | 112 | def set_provider(self, **kwargs): 113 | self.provider = { 114 | "name": kwargs.get("name"), 115 | "url": kwargs.get("url"), 116 | } 117 | 118 | def set_author(self, **kwargs): 119 | self.author = { 120 | "name": kwargs.get("name"), 121 | "url": kwargs.get("url"), 122 | "icon_url": kwargs.get("icon_url"), 123 | "proxy_icon_url": kwargs.get("proxy_icon_url"), 124 | } 125 | 126 | def add_embed_field(self, **kwargs): 127 | self.fields.append({ 128 | "name": kwargs.get("name"), 129 | "value": kwargs.get("value"), 130 | "inline": kwargs.get("inline", True) 131 | }) 132 | 133 | def del_embed_field(self, index): 134 | self.fields.pop(index) 135 | 136 | def get_embed_fields(self): 137 | return self.fields -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | try: 2 | from Crypto import Random 3 | from Crypto.Cipher import AES 4 | except: 5 | from Cryptodome import Random 6 | from Cryptodome.Cipher import AES 7 | from colorama import init, Fore, Back, Style 8 | from datetime import datetime 9 | from selenium.webdriver import Chrome, ChromeOptions 10 | from selenium.webdriver.common.desired_capabilities import DesiredCapabilities 11 | from webhook import DiscordWebhook, DiscordEmbed 12 | from chromedriver_py import binary_path as driver_path 13 | import json, platform, darkdetect, random, settings, threading, hashlib, base64 14 | normal_color = Fore.CYAN 15 | e_key = "YnJ1aG1vbWVudA==".encode() 16 | BLOCK_SIZE=16 17 | if platform.system() == "Windows": 18 | init(convert=True) 19 | else: 20 | init() 21 | print(normal_color + "Welcome To Bird Bot") 22 | 23 | class BirdLogger: 24 | def ts(self): 25 | return str(datetime.now())[:-7] 26 | def normal(self,task_id,msg): 27 | print(normal_color + "[{}][TASK {}] {}".format(self.ts(),task_id,msg)) 28 | def alt(self,task_id,msg): 29 | print(Fore.MAGENTA + "[{}][TASK {}] {}".format(self.ts(),task_id,msg)) 30 | def error(self,task_id,msg): 31 | print(Fore.RED + "[{}][TASK {}] {}".format(self.ts(),task_id,msg)) 32 | def success(self,task_id,msg): 33 | print(Fore.GREEN + "[{}][TASK {}] {}".format(self.ts(),task_id,msg)) 34 | class Encryption: 35 | def encrypt(self,msg): 36 | IV = Random.new().read(BLOCK_SIZE) 37 | aes = AES.new(self.trans(e_key), AES.MODE_CFB, IV) 38 | return base64.b64encode(IV + aes.encrypt(msg.encode("utf-8"))) 39 | def decrypt(self,msg): 40 | msg = base64.b64decode(msg) 41 | IV = msg[:BLOCK_SIZE] 42 | aes = AES.new(self.trans(e_key), AES.MODE_CFB, IV) 43 | return aes.decrypt(msg[BLOCK_SIZE:]) 44 | def trans(self,key): 45 | return hashlib.md5(key).digest() 46 | def return_data(path): 47 | with open(path,"r") as file: 48 | data = json.load(file) 49 | file.close() 50 | return data 51 | def write_data(path,data): 52 | with open(path, "w") as file: 53 | json.dump(data, file) 54 | file.close() 55 | def get_profile(profile_name): 56 | profiles = return_data("./data/profiles.json") 57 | for p in profiles: 58 | if p["profile_name"] == profile_name: 59 | try: 60 | p["card_number"] = (Encryption().decrypt(p["card_number"].encode("utf-8"))).decode("utf-8") 61 | except ValueError: 62 | pass 63 | return p 64 | return None 65 | def get_proxy(list_name): 66 | if list_name == "Proxy List" or list_name == "None": 67 | return False 68 | proxies = return_data("./data/proxies.json") 69 | for proxy_list in proxies: 70 | if proxy_list["list_name"] == list_name: 71 | return format_proxy(random.choice(proxy_list["proxies"].splitlines())) 72 | return None 73 | def format_proxy(proxy): 74 | try: 75 | proxy_parts = proxy.split(":") 76 | ip, port, user, passw = proxy_parts[0], proxy_parts[1], proxy_parts[2], proxy_parts[3] 77 | return { 78 | "http": "http://{}:{}@{}:{}".format(user, passw, ip, port), 79 | "https": "https://{}:{}@{}:{}".format(user, passw, ip, port) 80 | } 81 | except IndexError: 82 | return {"http": "http://" + proxy, "https": "https://" + proxy} 83 | def send_webhook(webhook_type,site,profile,task_id,image_url): 84 | if settings.webhook !="": 85 | webhook = DiscordWebhook(url=settings.webhook, username="Bird Bot", avatar_url="https://i.imgur.com/fy26LbM.png") 86 | if webhook_type == "OP": 87 | if not settings.webhook_on_order: 88 | return 89 | embed = DiscordEmbed(title="Order Placed",color=0x34c693) 90 | elif webhook_type == "B": 91 | if not settings.webhook_on_browser: 92 | return 93 | embed = DiscordEmbed(title="Complete Order in Browser",color=0xf2a689) 94 | elif webhook_type == "PF": 95 | if not settings.webhook_on_failed: 96 | return 97 | embed = DiscordEmbed(title="Payment Failed",color=0xfc5151) 98 | embed.set_footer(text="Via Bird Bot",icon_url="https://i.imgur.com/fy26LbM.png") 99 | embed.add_embed_field(name="Site", value=site,inline=True) 100 | embed.add_embed_field(name="Profile", value=profile,inline=True) 101 | embed.add_embed_field(name="Task ID", value=task_id,inline=True) 102 | embed.set_thumbnail(url=image_url) 103 | webhook.add_embed(embed) 104 | try: 105 | webhook.execute() 106 | except: 107 | pass 108 | 109 | def open_browser(link,cookies): 110 | threading.Thread(target = start_browser, args=(link,cookies)).start() 111 | 112 | def start_browser(link,cookies): 113 | caps = DesiredCapabilities().CHROME 114 | caps["pageLoadStrategy"] = "eager" 115 | chrome_options = ChromeOptions() 116 | chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"]) 117 | chrome_options.add_experimental_option("useAutomationExtension", False) 118 | driver = Chrome(desired_capabilities=caps, executable_path=driver_path, options=chrome_options) 119 | driver.execute_cdp_cmd( 120 | "Page.addScriptToEvaluateOnNewDocument", 121 | { 122 | "source": """ 123 | Object.defineProperty(window, 'navigator', { 124 | value: new Proxy(navigator, { 125 | has: (target, key) => (key === 'webdriver' ? false : key in target), 126 | get: (target, key) => 127 | key === 'webdriver' 128 | ? undefined 129 | : typeof target[key] === 'function' 130 | ? target[key].bind(target) 131 | : target[key] 132 | }) 133 | }) 134 | """ 135 | }, 136 | ) 137 | driver.get(link) 138 | for cookie in cookies: 139 | driver.add_cookie({ 140 | "name": cookie["name"], 141 | "value" : cookie["value"], 142 | "domain" : cookie["domain"] 143 | }) 144 | driver.get(link) 145 | -------------------------------------------------------------------------------- /pages/createdialog.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtCore, QtGui, QtWidgets 2 | import sys,platform 3 | def no_abort(a, b, c): 4 | sys.__excepthook__(a, b, c) 5 | sys.excepthook = no_abort 6 | 7 | class CreateDialog(QtWidgets.QDialog): 8 | def __init__(self,parent=None): 9 | super(CreateDialog, self).__init__(parent) 10 | self.setupUi(self) 11 | self.show() 12 | def setupUi(self, CreateDialog): 13 | self.CreateDialog = CreateDialog 14 | CreateDialog.setFixedSize(647, 164) 15 | CreateDialog.setStyleSheet("QComboBox::drop-down { border: 0px;}QComboBox::down-arrow { image: url(:/images/down_icon.png); width: 14px; height: 14px;}QComboBox{ padding: 1px 0px 1px 3px;}QLineEdit:focus { border: none; outline: none;} QSpinBox::up-button {subcontrol-origin: border;subcontrol-position: top right;width: 8px; border-image: url(:/images/uparrow_icon.png) 1;border-width: 1px;}QSpinBox::down-button {subcontrol-origin: border;subcontrol-position: bottom right;width: 8px;border-image: url(:/images/downarrow_icon.png) 1;border-width: 1px;border-top-width: 0;}") 16 | CreateDialog.setWindowTitle("Create Tasks") 17 | self.background = QtWidgets.QWidget(CreateDialog) 18 | self.background.setGeometry(QtCore.QRect(0, 0, 691, 391)) 19 | self.background.setStyleSheet("background-color: #1E1E1E;") 20 | font = QtGui.QFont() 21 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 22 | font.setFamily("Arial") 23 | self.site_box = QtWidgets.QComboBox(self.background) 24 | self.site_box.setGeometry(QtCore.QRect(50, 20, 151, 21)) 25 | self.site_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 26 | self.site_box.addItem("Site") 27 | self.site_box.setFont(font) 28 | self.input_edit = QtWidgets.QLineEdit(self.background) 29 | self.input_edit.setGeometry(QtCore.QRect(250, 20, 151, 21)) 30 | self.input_edit.setFocusPolicy(QtCore.Qt.ClickFocus) 31 | self.input_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 32 | self.input_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 33 | self.input_edit.setPlaceholderText("Link") 34 | self.input_edit.setFont(font) 35 | self.input_edit.textEdited.connect(self.autofill) 36 | self.profile_box = QtWidgets.QComboBox(self.background) 37 | self.profile_box.setGeometry(QtCore.QRect(450, 20, 151, 21)) 38 | self.profile_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 39 | self.profile_box.addItem("Profile") 40 | self.profile_box.setFont(font) 41 | self.proxies_box = QtWidgets.QComboBox(self.background) 42 | self.proxies_box.setGeometry(QtCore.QRect(450, 70, 151, 21)) 43 | self.proxies_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 44 | self.proxies_box.addItem("Proxy List") 45 | self.proxies_box.addItem("None") 46 | self.proxies_box.setFont(font) 47 | self.monitor_edit = QtWidgets.QLineEdit(self.background) 48 | self.monitor_edit.setGeometry(QtCore.QRect(50, 70, 61, 21)) 49 | self.monitor_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 50 | self.monitor_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 51 | self.monitor_edit.setPlaceholderText("Monitor") 52 | self.monitor_edit.setFont(font) 53 | self.monitor_edit.setText("5.0") 54 | self.only_float = QtGui.QDoubleValidator() 55 | self.monitor_edit.setValidator(self.only_float) 56 | self.error_edit = QtWidgets.QLineEdit(self.background) 57 | self.error_edit.setGeometry(QtCore.QRect(140, 70, 61, 21)) 58 | self.error_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 59 | self.error_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 60 | self.error_edit.setPlaceholderText("Error") 61 | self.error_edit.setFont(font) 62 | self.error_edit.setText("5.0") 63 | self.error_edit.setValidator(self.only_float) 64 | self.addtask_btn = QtWidgets.QPushButton(self.background) 65 | self.addtask_btn.setGeometry(QtCore.QRect(250, 110, 151, 32)) 66 | self.addtask_btn.setText("Add Task") 67 | self.maxprice_checkbox = QtWidgets.QCheckBox(self.background) 68 | self.maxprice_checkbox.setGeometry(QtCore.QRect(250, 70, 87, 20)) 69 | font = QtGui.QFont() 70 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 71 | font.setFamily("Arial") 72 | self.maxprice_checkbox.setFont(font) 73 | self.maxprice_checkbox.setStyleSheet("color: #FFFFFF;") 74 | self.maxprice_checkbox.setText("Max Price") 75 | self.price_edit = QtWidgets.QLineEdit(self.background) 76 | self.price_edit.setGeometry(QtCore.QRect(350, 70, 51, 21)) 77 | self.price_edit.setFont(font) 78 | self.price_edit.setFocusPolicy(QtCore.Qt.ClickFocus) 79 | self.price_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 80 | self.price_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 81 | self.only_int = QtGui.QIntValidator() 82 | self.price_edit.setValidator(self.only_int) 83 | font = QtGui.QFont() 84 | font.setFamily("Arial") 85 | font.setPointSize(14) if platform.system() == "Darwin" else font.setPointSize(14*.75) 86 | self.addtask_btn.setFont(font) 87 | self.addtask_btn.setStyleSheet("border-radius: 10px;background-color: #5D43FB;color: #FFFFFF;") 88 | self.addtask_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 89 | self.taskcount_spinbox = QtWidgets.QSpinBox(self.background) 90 | self.taskcount_spinbox.setGeometry(QtCore.QRect(420, 115, 41, 21)) 91 | self.taskcount_spinbox.setStyleSheet("border: 1px solid #5D43FB;border-width: 0 0 2px;color: #FFFFFF;") 92 | self.taskcount_spinbox.setMinimum(1) 93 | self.taskcount_spinbox.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 94 | 95 | self.site_box.addItem("Bestbuy") 96 | self.site_box.addItem("Walmart") 97 | 98 | QtCore.QMetaObject.connectSlotsByName(CreateDialog) 99 | def autofill(self): 100 | if "bestbuy" in self.input_edit.text(): 101 | self.site_box.setCurrentIndex(self.site_box.findText("Bestbuy")) 102 | elif "walmart" in self.input_edit.text(): 103 | self.site_box.setCurrentIndex(self.site_box.findText("Walmart")) 104 | 105 | def load_data(self, task_tab): 106 | self.site_box.setCurrentText(task_tab.site) 107 | self.input_edit.setText(task_tab.product) 108 | self.profile_box.setCurrentText(task_tab.profile) 109 | self.proxies_box.setCurrentText(task_tab.proxies) 110 | self.monitor_edit.setText(task_tab.monitor_delay) 111 | self.error_edit.setText(task_tab.error_delay) 112 | self.price_edit.setText(task_tab.max_price) 113 | self.maxprice_checkbox.setChecked(task_tab.max_price is not '') 114 | self.addtask_btn.setText('Update Task') 115 | 116 | 117 | -------------------------------------------------------------------------------- /pages/settingspage.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtCore, QtGui, QtWidgets 2 | from utils import return_data,write_data 3 | import sys,platform,settings 4 | def no_abort(a, b, c): 5 | sys.__excepthook__(a, b, c) 6 | sys.excepthook = no_abort 7 | 8 | class SettingsPage(QtWidgets.QWidget): 9 | def __init__(self,parent=None): 10 | super(SettingsPage, self).__init__(parent) 11 | self.setupUi(self) 12 | def setupUi(self, settingspage): 13 | self.settingspage = settingspage 14 | self.settingspage.setAttribute(QtCore.Qt.WA_StyledBackground, True) 15 | self.settingspage.setGeometry(QtCore.QRect(60, 0, 1041, 601)) 16 | self.settingspage.setStyleSheet("QComboBox::drop-down { border: 0px;}QComboBox::down-arrow { image: url(:/images/down_icon.png); width: 14px; height: 14px;}QComboBox{ padding: 1px 0px 1px 3px;}QLineEdit:focus { border: none; outline: none;}") 17 | self.settings_card = QtWidgets.QWidget(self.settingspage) 18 | self.settings_card.setGeometry(QtCore.QRect(30, 70, 471, 501)) 19 | font = QtGui.QFont() 20 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 21 | font.setFamily("Arial") 22 | self.settings_card.setFont(font) 23 | self.settings_card.setStyleSheet("background-color: #232323;border-radius: 20px;border: 1px solid #2e2d2d;") 24 | self.webhook_edit = QtWidgets.QLineEdit(self.settings_card) 25 | self.webhook_edit.setGeometry(QtCore.QRect(30, 50, 411, 21)) 26 | self.webhook_edit.setFont(font) 27 | self.webhook_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 28 | self.webhook_edit.setPlaceholderText("Webhook Link") 29 | self.webhook_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 30 | self.webhook_header = QtWidgets.QLabel(self.settings_card) 31 | self.webhook_header.setGeometry(QtCore.QRect(20, 10, 101, 31)) 32 | font = QtGui.QFont() 33 | font.setFamily("Arial") 34 | font.setPointSize(18) if platform.system() == "Darwin" else font.setPointSize(18*.75) 35 | font.setWeight(50) 36 | self.webhook_header.setFont(font) 37 | self.webhook_header.setStyleSheet("color: rgb(212, 214, 214);border: none;") 38 | self.webhook_header.setText("Webhook") 39 | self.savesettings_btn = QtWidgets.QPushButton(self.settings_card) 40 | self.savesettings_btn.setGeometry(QtCore.QRect(190, 450, 86, 32)) 41 | font = QtGui.QFont() 42 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 43 | font.setFamily("Arial") 44 | self.savesettings_btn.setFont(font) 45 | self.savesettings_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 46 | self.savesettings_btn.setStyleSheet("color: #FFFFFF;background-color: #5D43FB;border-radius: 10px;border: 1px solid #2e2d2d;") 47 | self.savesettings_btn.setText("Save") 48 | self.savesettings_btn.clicked.connect(self.save_settings) 49 | self.browser_checkbox = QtWidgets.QCheckBox(self.settings_card) 50 | self.browser_checkbox.setGeometry(QtCore.QRect(30, 90, 111, 20)) 51 | self.browser_checkbox.setStyleSheet("color: #FFFFFF;border: none;") 52 | self.browser_checkbox.setText("Browser Opened") 53 | self.order_checkbox = QtWidgets.QCheckBox(self.settings_card) 54 | self.order_checkbox.setGeometry(QtCore.QRect(30, 120, 221, 20)) 55 | self.order_checkbox.setStyleSheet("color: #FFFFFF;border: none;") 56 | self.order_checkbox.setText("Order Placed") 57 | self.paymentfailed_checkbox = QtWidgets.QCheckBox(self.settings_card) 58 | self.paymentfailed_checkbox.setGeometry(QtCore.QRect(30, 150, 121, 20)) 59 | self.paymentfailed_checkbox.setStyleSheet("color: #FFFFFF;border: none;") 60 | self.paymentfailed_checkbox.setText("Payment Failed") 61 | self.general_header = QtWidgets.QLabel(self.settings_card) 62 | self.general_header.setGeometry(QtCore.QRect(20, 180, 101, 31)) 63 | font = QtGui.QFont() 64 | font.setFamily("Arial") 65 | font.setPointSize(18) if platform.system() == "Darwin" else font.setPointSize(18*.75) 66 | font.setWeight(50) 67 | self.general_header.setFont(font) 68 | self.general_header.setStyleSheet("color: rgb(212, 214, 214);border: none;") 69 | self.general_header.setText("General") 70 | self.onfailed_checkbox = QtWidgets.QCheckBox(self.settings_card) 71 | self.onfailed_checkbox.setGeometry(QtCore.QRect(30, 220, 221, 20)) 72 | self.onfailed_checkbox.setStyleSheet("color: #FFFFFF;border: none;") 73 | self.onfailed_checkbox.setText("Open browser on payment failed") 74 | self.buy_one_checkbox = QtWidgets.QCheckBox(self.settings_card) 75 | self.buy_one_checkbox.setGeometry(QtCore.QRect(30, 250, 221, 20)) 76 | self.buy_one_checkbox.setStyleSheet("color: #FFFFFF;border: none;") 77 | self.buy_one_checkbox.setText("Stop All after success") 78 | self.proxies_header = QtWidgets.QLabel(self.settingspage) 79 | self.proxies_header.setGeometry(QtCore.QRect(30, 10, 81, 31)) 80 | font = QtGui.QFont() 81 | font.setFamily("Arial") 82 | font.setPointSize(22) if platform.system() == "Darwin" else font.setPointSize(22*.75) 83 | font.setWeight(50) 84 | self.proxies_header.setFont(font) 85 | self.proxies_header.setStyleSheet("color: rgb(234, 239, 239);") 86 | self.proxies_header.setText("Settings") 87 | self.set_data() 88 | QtCore.QMetaObject.connectSlotsByName(settingspage) 89 | 90 | def set_data(self): 91 | settings = return_data("./data/settings.json") 92 | self.webhook_edit.setText(settings["webhook"]) 93 | if settings["webhookonbrowser"]: 94 | self.browser_checkbox.setChecked(True) 95 | if settings["webhookonorder"]: 96 | self.order_checkbox.setChecked(True) 97 | if settings["webhookonfailed"]: 98 | self.paymentfailed_checkbox.setChecked(True) 99 | if settings["browseronfailed"]: 100 | self.onfailed_checkbox.setChecked(True) 101 | if settings['onlybuyone']: 102 | self.buy_one_checkbox.setChecked(True) 103 | self.update_settings(settings) 104 | 105 | def save_settings(self): 106 | settings = {"webhook":self.webhook_edit.text(), 107 | "webhookonbrowser":self.browser_checkbox.isChecked(), 108 | "webhookonorder":self.order_checkbox.isChecked(), 109 | "webhookonfailed":self.paymentfailed_checkbox.isChecked(), 110 | "browseronfailed":self.onfailed_checkbox.isChecked(), 111 | 'onlybuyone':self.buy_one_checkbox.isChecked()} 112 | write_data("./data/settings.json",settings) 113 | self.update_settings(settings) 114 | QtWidgets.QMessageBox.information(self, "Bird Bot", "Saved Settings") 115 | 116 | def update_settings(self,settings_data): 117 | global webhook, webhook_on_browser, webhook_on_order, webhook_on_failed, browser_on_failed 118 | settings.webhook, settings.webhook_on_browser, settings.webhook_on_order, settings.webhook_on_failed, settings.browser_on_failed, settings.buy_one = settings_data["webhook"], settings_data["webhookonbrowser"], settings_data["webhookonorder"], settings_data["webhookonfailed"], settings_data["browseronfailed"], settings_data['onlybuyone'] 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /pages/proxiespage.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtCore, QtGui, QtWidgets 2 | from utils import return_data,write_data 3 | import sys,platform 4 | def no_abort(a, b, c): 5 | sys.__excepthook__(a, b, c) 6 | sys.excepthook = no_abort 7 | 8 | class ProxiesPage(QtWidgets.QWidget): 9 | def __init__(self,parent=None): 10 | super(ProxiesPage, self).__init__(parent) 11 | self.setupUi(self) 12 | def setupUi(self, proxiespage): 13 | self.proxiespage = proxiespage 14 | self.proxiespage.setAttribute(QtCore.Qt.WA_StyledBackground, True) 15 | self.proxiespage.setGeometry(QtCore.QRect(60, 0, 1041, 601)) 16 | self.proxiespage.setStyleSheet("QComboBox::drop-down { border: 0px;}QComboBox::down-arrow { image: url(:/images/down_icon.png); width: 14px; height: 14px;}QComboBox{ padding: 1px 0px 1px 3px;}QLineEdit:focus { border: none; outline: none;}") 17 | self.proxies_card = QtWidgets.QWidget(self.proxiespage) 18 | self.proxies_card.setGeometry(QtCore.QRect(30, 70, 981, 501)) 19 | font = QtGui.QFont() 20 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 21 | font.setFamily("Arial") 22 | self.proxies_card.setFont(font) 23 | self.proxies_card.setStyleSheet("background-color: #232323;border-radius: 20px;border: 1px solid #2e2d2d;") 24 | self.listname_edit = QtWidgets.QLineEdit(self.proxies_card) 25 | self.listname_edit.setGeometry(QtCore.QRect(20, 50, 161, 21)) 26 | self.listname_edit.setFont(font) 27 | self.listname_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 28 | self.listname_edit.setPlaceholderText("List Name") 29 | self.listname_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 30 | self.editproxies_header = QtWidgets.QLabel(self.proxies_card) 31 | self.editproxies_header.setGeometry(QtCore.QRect(20, 10, 101, 31)) 32 | font = QtGui.QFont() 33 | font.setFamily("Arial") 34 | font.setPointSize(18) if platform.system() == "Darwin" else font.setPointSize(18*.75) 35 | font.setWeight(50) 36 | self.editproxies_header.setFont(font) 37 | self.editproxies_header.setStyleSheet("color: rgb(212, 214, 214);border: none;") 38 | self.editproxies_header.setText("Edit Proxies") 39 | self.loadlist_box = QtWidgets.QComboBox(self.proxies_card) 40 | self.loadlist_box.setGeometry(QtCore.QRect(210, 50, 161, 21)) 41 | font = QtGui.QFont() 42 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 43 | font.setFamily("Arial") 44 | self.loadlist_box.setFont(font) 45 | self.loadlist_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 46 | self.loadlist_box.addItem("Load List") 47 | self.loadlist_box.currentTextChanged.connect(self.load_proxies) 48 | self.saveproxies_btn = QtWidgets.QPushButton(self.proxies_card) 49 | self.saveproxies_btn.setGeometry(QtCore.QRect(400, 450, 86, 32)) 50 | self.saveproxies_btn.setFont(font) 51 | self.saveproxies_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 52 | self.saveproxies_btn.setStyleSheet("color: #FFFFFF;background-color: #5D43FB;border-radius: 10px;border: 1px solid #2e2d2d;") 53 | self.saveproxies_btn.setText("Save") 54 | self.saveproxies_btn.clicked.connect(self.save_proxies) 55 | self.proxies_edit = QtWidgets.QTextEdit(self.proxies_card) 56 | self.proxies_edit.setGeometry(QtCore.QRect(20, 90, 941, 341)) 57 | self.proxies_edit.setFont(font) 58 | self.proxies_edit.setStyleSheet("color: #FFFFFF;padding: 10px;") 59 | self.proxies_edit.setPlaceholderText("ip:port or ip:port:user:pass") 60 | self.proxies_edit.setAcceptRichText(False) 61 | self.deleteproxies_btn = QtWidgets.QPushButton(self.proxies_card) 62 | self.deleteproxies_btn.setGeometry(QtCore.QRect(500, 450, 86, 32)) 63 | self.deleteproxies_btn.setFont(font) 64 | self.deleteproxies_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 65 | self.deleteproxies_btn.setStyleSheet("color: #FFFFFF;background-color: #5D43FB;border-radius: 10px;border: 1px solid #2e2d2d;") 66 | self.deleteproxies_btn.setText("Delete") 67 | self.deleteproxies_btn.clicked.connect(self.delete_proxies) 68 | self.proxies_header = QtWidgets.QLabel(self.proxiespage) 69 | self.proxies_header.setGeometry(QtCore.QRect(30, 10, 81, 31)) 70 | font = QtGui.QFont() 71 | font.setFamily("Arial") 72 | font.setPointSize(22) if platform.system() == "Darwin" else font.setPointSize(22*.75) 73 | font.setWeight(50) 74 | self.proxies_header.setFont(font) 75 | self.proxies_header.setStyleSheet("color: rgb(234, 239, 239);") 76 | self.proxies_header.setText("Proxies") 77 | self.set_data() 78 | QtCore.QMetaObject.connectSlotsByName(proxiespage) 79 | 80 | def set_data(self): 81 | proxies = return_data("./data/proxies.json") 82 | for proxies_list in proxies: 83 | list_name = proxies_list["list_name"] 84 | self.loadlist_box.addItem(list_name) 85 | self.parent().parent().createdialog.proxies_box.addItem(list_name) 86 | 87 | def load_proxies(self): 88 | list_name = self.loadlist_box.currentText() 89 | if list_name !="Load Proxies": 90 | proxies = return_data("./data/proxies.json") 91 | for proxies_list in proxies: 92 | if proxies_list["list_name"] == list_name: 93 | self.listname_edit.setText(list_name) 94 | self.proxies_edit.setText(proxies_list["proxies"]) 95 | 96 | def save_proxies(self): 97 | list_name = self.listname_edit.text() 98 | proxies = self.proxies_edit.toPlainText() 99 | if proxies != "" and list_name != "": 100 | for item in proxies.splitlines(): 101 | if ":" not in item or item == "": 102 | QtWidgets.QMessageBox.critical(self, "Bird Bot", "Incorrect Proxies") 103 | return 104 | proxies_data = { 105 | "list_name": list_name, 106 | "proxies": self.proxies_edit.toPlainText() 107 | } 108 | proxies = return_data("./data/proxies.json") 109 | for p in proxies: 110 | if p["list_name"] == list_name: 111 | proxies.remove(p) 112 | break 113 | proxies.append(proxies_data) 114 | write_data("./data/proxies.json",proxies) 115 | if self.loadlist_box.findText(list_name) == -1: 116 | self.loadlist_box.addItem(list_name) 117 | self.parent().parent().createdialog.proxies_box.addItem(list_name) 118 | QtWidgets.QMessageBox.information(self, "Bird Bot", "Saved Proxies") 119 | else: 120 | QtWidgets.QMessageBox.critical(self, "Bird Bot", "Missing Fields") 121 | 122 | def delete_proxies(self): 123 | list_name = self.listname_edit.text() 124 | proxies = return_data("./data/proxies.json") 125 | for p in proxies: 126 | if p["list_name"] == list_name: 127 | proxies.remove(p) 128 | break 129 | write_data("./data/proxies.json",proxies) 130 | self.loadlist_box.removeItem(self.loadlist_box.findText(list_name)) 131 | self.parent().parent().createdialog.proxies_box.removeItem(self.parent().parent().createdialog.proxies_box.findText(list_name)) 132 | self.loadlist_box.setCurrentIndex(0) 133 | self.listname_edit.setText("") 134 | self.proxies_edit.setText("") 135 | QtWidgets.QMessageBox.information(self, "Bird Bot", "Deleted Proxy List") 136 | 137 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtCore, QtGui, QtWidgets 2 | from pages.homepage import HomePage,TaskTab 3 | from pages.createdialog import CreateDialog 4 | from pages.profilespage import ProfilesPage 5 | from pages.proxiespage import ProxiesPage 6 | from pages.settingspage import SettingsPage 7 | import images.images, sys, os 8 | def no_abort(a, b, c): 9 | sys.__excepthook__(a, b, c) 10 | sys.excepthook = no_abort 11 | class MainWindow(QtWidgets.QMainWindow): 12 | def __init__(self, parent=None): 13 | super(MainWindow, self).__init__(parent=parent) 14 | self.setupUi(self) 15 | self.show() 16 | def setupUi(self, MainWindow): 17 | MainWindow.setFixedSize(1109, 600) 18 | MainWindow.setStyleSheet("background-color: #1E1E1E;") 19 | MainWindow.setWindowTitle("Bird Bot") 20 | self.centralwidget = QtWidgets.QWidget(MainWindow) 21 | self.centralwidget.setStyleSheet("QMessageBox QLabel { color: #FFFFFF; }QMessageBox QPushButton { background-color: #5D43FB;color: #FFFFFF;}") 22 | self.sidebar = QtWidgets.QWidget(self.centralwidget) 23 | self.sidebar.setGeometry(QtCore.QRect(0, 0, 61, 601)) 24 | self.sidebar.setStyleSheet("background-color: #232323;border-right: 1px solid #2e2d2d;") 25 | self.home_tab = QtWidgets.QWidget(self.sidebar) 26 | self.home_tab.setGeometry(QtCore.QRect(0, 85, 60, 45)) 27 | self.home_tab.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 28 | self.home_tab.setStyleSheet("background-color: #272342;border: none;") 29 | self.home_active_tab = QtWidgets.QWidget(self.home_tab) 30 | self.home_active_tab.setGeometry(QtCore.QRect(0, 0, 4, 45)) 31 | self.home_active_tab.setStyleSheet("background-color: #5D43FB;border: none;") 32 | self.home_active_tab.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 33 | self.home_icon = QtWidgets.QLabel(self.home_tab) 34 | self.home_icon.setGeometry(QtCore.QRect(21, 13, 20, 20)) 35 | self.home_icon.setStyleSheet("border: none;") 36 | self.home_icon.setText("") 37 | self.home_icon.setPixmap(QtGui.QPixmap(":/images/home_alt.png")) 38 | self.home_icon.setScaledContents(True) 39 | self.home_icon.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 40 | self.profiles_tab = QtWidgets.QWidget(self.sidebar) 41 | self.profiles_tab.setGeometry(QtCore.QRect(0, 130, 60, 45)) 42 | self.profiles_tab.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 43 | self.profiles_tab.setStyleSheet("background-color: transparent;border: none;") 44 | self.profiles_active_tab = QtWidgets.QWidget(self.profiles_tab) 45 | self.profiles_active_tab.setGeometry(QtCore.QRect(0, 0, 4, 45)) 46 | self.profiles_active_tab.setStyleSheet("background-color: transparent;border: none;") 47 | self.profiles_active_tab.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 48 | self.profiles_icon = QtWidgets.QLabel(self.profiles_tab) 49 | self.profiles_icon.setGeometry(QtCore.QRect(21, 13, 20, 20)) 50 | self.profiles_icon.setStyleSheet("border: none;") 51 | self.profiles_icon.setText("") 52 | self.profiles_icon.setPixmap(QtGui.QPixmap(":/images/profiles.png")) 53 | self.profiles_icon.setScaledContents(True) 54 | self.profiles_icon.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 55 | self.proxies_tab = QtWidgets.QWidget(self.sidebar) 56 | self.proxies_tab.setGeometry(QtCore.QRect(0, 175, 60, 45)) 57 | self.proxies_tab.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 58 | self.proxies_tab.setStyleSheet("background-color: transparent;border: none;") 59 | self.proxies_active_tab = QtWidgets.QWidget(self.proxies_tab) 60 | self.proxies_active_tab.setGeometry(QtCore.QRect(0, 0, 4, 45)) 61 | self.proxies_active_tab.setStyleSheet("background-color: transparent;border: none;") 62 | self.proxies_icon = QtWidgets.QLabel(self.proxies_tab) 63 | self.proxies_icon.setGeometry(QtCore.QRect(21, 13, 20, 20)) 64 | self.proxies_icon.setStyleSheet("border: none;") 65 | self.proxies_icon.setPixmap(QtGui.QPixmap(":/images/proxies.png")) 66 | self.proxies_icon.setScaledContents(True) 67 | self.settings_tab = QtWidgets.QWidget(self.sidebar) 68 | self.settings_tab.setGeometry(QtCore.QRect(0, 220, 60, 45)) 69 | self.settings_tab.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 70 | self.settings_tab.setStyleSheet("background-color: transparent;border: none;") 71 | self.settings_active_tab = QtWidgets.QWidget(self.settings_tab) 72 | self.settings_active_tab.setGeometry(QtCore.QRect(0, 0, 4, 45)) 73 | self.settings_active_tab.setStyleSheet("background-color: transparent;border: none;") 74 | self.settings_icon = QtWidgets.QLabel(self.settings_tab) 75 | self.settings_icon.setGeometry(QtCore.QRect(21, 13, 20, 20)) 76 | self.settings_icon.setStyleSheet("border: none;") 77 | self.settings_icon.setPixmap(QtGui.QPixmap(":/images/settings.png")) 78 | self.settings_icon.setScaledContents(True) 79 | self.logo = QtWidgets.QLabel(self.sidebar) 80 | self.logo.setGeometry(QtCore.QRect(10, 23, 41, 41)) 81 | self.logo.setStyleSheet("border: none;") 82 | self.logo.setText("") 83 | self.logo.setPixmap(QtGui.QPixmap(":/images/birdbot.png")) 84 | self.logo.setScaledContents(True) 85 | self.homepage = HomePage(self.centralwidget) 86 | self.createdialog = CreateDialog(self) 87 | self.createdialog.addtask_btn.clicked.connect(self.create_task) 88 | self.createdialog.setWindowIcon(QtGui.QIcon("images/birdbot.png")) 89 | self.createdialog.hide() 90 | self.profilespage = ProfilesPage(self.centralwidget) 91 | self.profilespage.hide() 92 | self.proxiespage = ProxiesPage(self.centralwidget) 93 | self.proxiespage.hide() 94 | self.settingspage = SettingsPage(self.centralwidget) 95 | self.settingspage.hide() 96 | MainWindow.setCentralWidget(self.centralwidget) 97 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 98 | self.set_functions() 99 | def set_functions(self): 100 | self.current_page = "home" 101 | self.home_tab.mousePressEvent = lambda event: self.change_page(event,"home") 102 | self.profiles_tab.mousePressEvent = lambda event: self.change_page(event,"profiles") 103 | self.proxies_tab.mousePressEvent = lambda event: self.change_page(event,"proxies") 104 | self.settings_tab.mousePressEvent = lambda event: self.change_page(event,"settings") 105 | self.homepage.newtask_btn.clicked.connect(self.createdialog.show) 106 | 107 | def change_page(self,event,current_page): 108 | eval('self.{}_active_tab.setStyleSheet("background-color: transparent;border: none;")'.format(self.current_page)) 109 | eval('self.{}_icon.setPixmap(QtGui.QPixmap(":/images/{}.png"))'.format(self.current_page,self.current_page)) 110 | eval('self.{}_tab.setStyleSheet("background-color: transparent;border: none;")'.format(self.current_page)) 111 | eval("self.{}page.hide()".format(self.current_page)) 112 | self.current_page = current_page 113 | eval('self.{}_active_tab.setStyleSheet("background-color: #5D43FB;border: none;")'.format(self.current_page)) 114 | eval('self.{}_icon.setPixmap(QtGui.QPixmap(":/images/{}_alt.png"))'.format(self.current_page,self.current_page)) 115 | eval('self.{}_tab.setStyleSheet("background-color: #272342;border: none;")'.format(self.current_page)) 116 | eval("self.{}page.show()".format(self.current_page)) 117 | 118 | def create_task(self): 119 | site = self.createdialog.site_box.currentText() 120 | product = self.createdialog.input_edit.text() 121 | profile = self.createdialog.profile_box.currentText() 122 | proxies = self.createdialog.proxies_box.currentText() 123 | monitor_delay = self.createdialog.monitor_edit.text() 124 | error_delay = self.createdialog.error_edit.text() 125 | max_price = self.createdialog.price_edit.text() if self.createdialog.maxprice_checkbox.isChecked() else "" 126 | if site != "Site" and product != "" and profile != "Profile" and monitor_delay != "" and error_delay != "": 127 | for i in range(self.createdialog.taskcount_spinbox.value()): 128 | self.homepage.verticalLayout.takeAt(self.homepage.verticalLayout.count()-1) 129 | tab = TaskTab( 130 | site, 131 | product, 132 | profile, 133 | proxies, 134 | monitor_delay, 135 | error_delay, 136 | max_price, 137 | self.homepage.stop_all_tasks, 138 | self.homepage.scrollAreaWidgetContents) 139 | self.homepage.verticalLayout.addWidget(tab) 140 | spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 141 | self.homepage.verticalLayout.addItem(spacerItem) 142 | 143 | #(.*) 144 | if __name__ == "__main__": 145 | ui_app = QtWidgets.QApplication(sys.argv) 146 | ui = MainWindow() 147 | ui.setWindowIcon(QtGui.QIcon("images/birdbot.png")) 148 | os._exit(ui_app.exec_()) 149 | -------------------------------------------------------------------------------- /encrypt.js: -------------------------------------------------------------------------------- 1 | var n = {}; 2 | n.base10 = "0123456789", n.base62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", n.luhn = function (e) { 3 | for (var t = e.length - 1, n = 0; t >= 0;) n += parseInt(e.substr(t, 1), 10), t -= 2; 4 | for (t = e.length - 2; t >= 0;) { 5 | var r = 2 * parseInt(e.substr(t, 1), 10); 6 | n += r < 10 ? r : r - 9, t -= 2 7 | } 8 | return n % 10 9 | }, n.fixluhn = function (e, t, r) { 10 | var a = n.luhn(e); 11 | return a < r ? a += 10 - r : a -= r, 0 != a ? (a = (e.length - t) % 2 != 0 ? 10 - a : a % 2 == 0 ? 5 - a / 2 : (9 - a) / 2 + 5, e.substr(0, t) + a + e.substr(t + 1)) : e 12 | }, n.distill = function (e) { 13 | for (var t = "", r = 0; r < e.length; ++r) n.base10.indexOf(e.charAt(r)) >= 0 && (t += e.substr(r, 1)); 14 | return t 15 | }, n.reformat = function (e, t) { 16 | for (var r = "", a = 0, i = 0; i < t.length; ++i) a < e.length && n.base10.indexOf(t.charAt(i)) >= 0 ? (r += e.substr(a, 1), ++a) : r += t.substr(i, 1); 17 | return r 18 | }, n.integrity = function (e, t, n) { 19 | var o = String.fromCharCode(0) + String.fromCharCode(t.length) + t + String.fromCharCode(0) + String.fromCharCode(n.length) + n, 20 | c = a.HexToWords(e); 21 | c[3] ^= 1; 22 | var u = new r.cipher.aes(c), 23 | s = i.compute(u, o); 24 | return a.WordToHex(s[0]) + a.WordToHex(s[1]) 25 | } 26 | var r = { 27 | cipher: {}, 28 | hash: {}, 29 | mode: {}, 30 | misc: {}, 31 | codec: {}, 32 | exception: { 33 | corrupt: function (e) { 34 | this.toString = function () { 35 | return "CORRUPT: " + this.message 36 | }, this.message = e 37 | }, 38 | invalid: function (e) { 39 | this.toString = function () { 40 | return "INVALID: " + this.message 41 | }, this.message = e 42 | }, 43 | bug: function (e) { 44 | this.toString = function () { 45 | return "BUG: " + this.message 46 | }, this.message = e 47 | } 48 | } 49 | }; 50 | r.cipher.aes = function (e) { 51 | this._tables[0][0][0] || this._precompute(); 52 | var t, n, a, i, o, c = this._tables[0][4], 53 | u = this._tables[1], 54 | s = e.length, 55 | d = 1; 56 | if (4 !== s && 6 !== s && 8 !== s) throw new r.exception.invalid("invalid aes key size"); 57 | for (this._key = [i = e.slice(0), o = []], t = s; t < 4 * s + 28; t++) a = i[t - 1], (t % s == 0 || 8 === s && t % s == 4) && (a = c[a >>> 24] << 24 ^ c[a >> 16 & 255] << 16 ^ c[a >> 8 & 255] << 8 ^ c[255 & a], t % s == 0 && (a = a << 8 ^ a >>> 24 ^ d << 24, d = d << 1 ^ 283 * (d >> 7))), i[t] = i[t - s] ^ a; 58 | for (n = 0; t; n++, t--) a = i[3 & n ? t : t - 4], o[n] = t <= 4 || n < 4 ? a : u[0][c[a >>> 24]] ^ u[1][c[a >> 16 & 255]] ^ u[2][c[a >> 8 & 255]] ^ u[3][c[255 & a]] 59 | }, r.cipher.aes.prototype = { 60 | encrypt: function (e) { 61 | return this._crypt(e, 0) 62 | }, 63 | decrypt: function (e) { 64 | return this._crypt(e, 1) 65 | }, 66 | _tables: [ 67 | [ 68 | [], 69 | [], 70 | [], 71 | [], 72 | [] 73 | ], 74 | [ 75 | [], 76 | [], 77 | [], 78 | [], 79 | [] 80 | ] 81 | ], 82 | _precompute: function () { 83 | var e, t, n, r, a, i, o, c, u = this._tables[0], 84 | s = this._tables[1], 85 | d = u[4], 86 | l = s[4], 87 | f = [], 88 | p = []; 89 | for (e = 0; e < 256; e++) p[(f[e] = e << 1 ^ 283 * (e >> 7)) ^ e] = e; 90 | for (t = n = 0; !d[t]; t ^= 0 == r ? 1 : r, n = 0 == p[n] ? 1 : p[n]) 91 | for (i = (i = n ^ n << 1 ^ n << 2 ^ n << 3 ^ n << 4) >> 8 ^ 255 & i ^ 99, d[t] = i, l[i] = t, c = 16843009 * f[a = f[r = f[t]]] ^ 65537 * a ^ 257 * r ^ 16843008 * t, o = 257 * f[i] ^ 16843008 * i, e = 0; e < 4; e++) u[e][t] = o = o << 24 ^ o >>> 8, s[e][i] = c = c << 24 ^ c >>> 8; 92 | for (e = 0; e < 5; e++) u[e] = u[e].slice(0), s[e] = s[e].slice(0) 93 | }, 94 | _crypt: function (e, t) { 95 | if (4 !== e.length) throw new r.exception.invalid("invalid aes block size"); 96 | var n, a, i, o, c = this._key[t], 97 | u = e[0] ^ c[0], 98 | s = e[t ? 3 : 1] ^ c[1], 99 | d = e[2] ^ c[2], 100 | l = e[t ? 1 : 3] ^ c[3], 101 | f = c.length / 4 - 2, 102 | p = 4, 103 | m = [0, 0, 0, 0], 104 | h = this._tables[t], 105 | b = h[0], 106 | v = h[1], 107 | y = h[2], 108 | E = h[3], 109 | g = h[4]; 110 | for (o = 0; o < f; o++) n = b[u >>> 24] ^ v[s >> 16 & 255] ^ y[d >> 8 & 255] ^ E[255 & l] ^ c[p], a = b[s >>> 24] ^ v[d >> 16 & 255] ^ y[l >> 8 & 255] ^ E[255 & u] ^ c[p + 1], i = b[d >>> 24] ^ v[l >> 16 & 255] ^ y[u >> 8 & 255] ^ E[255 & s] ^ c[p + 2], l = b[l >>> 24] ^ v[u >> 16 & 255] ^ y[s >> 8 & 255] ^ E[255 & d] ^ c[p + 3], p += 4, u = n, s = a, d = i; 111 | for (o = 0; o < 4; o++) m[t ? 3 & -o : o] = g[u >>> 24] << 24 ^ g[s >> 16 & 255] << 16 ^ g[d >> 8 & 255] << 8 ^ g[255 & l] ^ c[p++], n = u, u = s, s = d, d = l, l = n; 112 | return m 113 | } 114 | }; 115 | var a = { 116 | HexToKey: function (e) { 117 | return new r.cipher.aes(a.HexToWords(e)) 118 | }, 119 | HexToWords: function (e) { 120 | var t = new Array(4); 121 | if (32 != e.length) return null; 122 | for (var n = 0; n < 4; n++) t[n] = parseInt(e.substr(8 * n, 8), 16); 123 | return t 124 | }, 125 | Hex: "0123456789abcdef", 126 | WordToHex: function (e) { 127 | for (var t = 32, n = ""; t > 0;) t -= 4, n += a.Hex.substr(e >>> t & 15, 1); 128 | return n 129 | } 130 | }, 131 | i = {}; 132 | i.MSBnotZero = function (e) { 133 | return 2147483647 != (2147483647 | e) 134 | }, i.leftShift = function (e) { 135 | e[0] = (2147483647 & e[0]) << 1 | e[1] >>> 31, e[1] = (2147483647 & e[1]) << 1 | e[2] >>> 31, e[2] = (2147483647 & e[2]) << 1 | e[3] >>> 31, e[3] = (2147483647 & e[3]) << 1 136 | }, i.const_Rb = 135, i.compute = function (e, t) { 137 | var n = [0, 0, 0, 0], 138 | r = e.encrypt(n), 139 | a = r[0]; 140 | i.leftShift(r), i.MSBnotZero(a) && (r[3] ^= i.const_Rb); 141 | for (var o = 0; o < t.length;) n[o >> 2 & 3] ^= (255 & t.charCodeAt(o)) << 8 * (3 - (3 & o)), 0 == (15 & ++o) && o < t.length && (n = e.encrypt(n)); 142 | return 0 != o && 0 == (15 & o) || (a = r[0], i.leftShift(r), i.MSBnotZero(a) && (r[3] ^= i.const_Rb), n[o >> 2 & 3] ^= 128 << 8 * (3 - (3 & o))), n[0] ^= r[0], n[1] ^= r[1], n[2] ^= r[2], n[3] ^= r[3], e.encrypt(n) 143 | }; 144 | var o = { 145 | alphabet: ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"], 146 | precompF: function (e, t, n, r) { 147 | var a = new Array(4), 148 | i = n.length; 149 | return a[0] = 16908544 | r >> 16 & 255, a[1] = (r >> 8 & 255) << 24 | (255 & r) << 16 | 2560 | 255 & Math.floor(t / 2), a[2] = t, a[3] = i, e.encrypt(a) 150 | }, 151 | precompb: function (e, t) { 152 | for (var n = Math.ceil(t / 2), r = 0, a = 1; n > 0;) --n, (a *= e) >= 256 && (a /= 256, ++r); 153 | return a > 1 && ++r, r 154 | }, 155 | bnMultiply: function (e, t, n) { 156 | var r, a = 0; 157 | for (r = e.length - 1; r >= 0; --r) { 158 | var i = e[r] * n + a; 159 | e[r] = i % t, a = (i - e[r]) / t 160 | } 161 | }, 162 | bnAdd: function (e, t, n) { 163 | for (var r = e.length - 1, a = n; r >= 0 && a > 0;) { 164 | var i = e[r] + a; 165 | e[r] = i % t, a = (i - e[r]) / t, --r 166 | } 167 | }, 168 | convertRadix: function (e, t, n, r, a) { 169 | var i, c = new Array(r); 170 | for (i = 0; i < r; ++i) c[i] = 0; 171 | for (var u = 0; u < t; ++u) o.bnMultiply(c, a, n), o.bnAdd(c, a, e[u]); 172 | return c 173 | }, 174 | cbcmacq: function (e, t, n, r) { 175 | for (var a = new Array(4), i = 0; i < 4; ++i) a[i] = e[i]; 176 | for (var o = 0; 4 * o < n;) { 177 | for (i = 0; i < 4; ++i) a[i] = a[i] ^ (t[4 * (o + i)] << 24 | t[4 * (o + i) + 1] << 16 | t[4 * (o + i) + 2] << 8 | t[4 * (o + i) + 3]); 178 | a = r.encrypt(a), o += 4 179 | } 180 | return a 181 | }, 182 | F: function (e, t, n, r, a, i, c, u, s) { 183 | var d = Math.ceil(s / 4) + 1, 184 | l = n.length + s + 1 & 15; 185 | l > 0 && (l = 16 - l); 186 | var f, p = new Array(n.length + l + s + 1); 187 | for (f = 0; f < n.length; f++) p[f] = n.charCodeAt(f); 188 | for (; f < l + n.length; f++) p[f] = 0; 189 | p[p.length - s - 1] = t; 190 | for (var m = o.convertRadix(r, a, u, s, 256), h = 0; h < s; h++) p[p.length - s + h] = m[h]; 191 | var b, v = o.cbcmacq(c, p, p.length, e), 192 | y = v, 193 | E = new Array(2 * d); 194 | for (f = 0; f < d; ++f) f > 0 && 0 == (3 & f) && (b = f >> 2 & 255, b |= b << 8 | b << 16 | b << 24, y = e.encrypt([v[0] ^ b, v[1] ^ b, v[2] ^ b, v[3] ^ b])), E[2 * f] = y[3 & f] >>> 16, E[2 * f + 1] = 65535 & y[3 & f]; 195 | return o.convertRadix(E, 2 * d, 65536, i, u) 196 | }, 197 | DigitToVal: function (e, t, n) { 198 | var r = new Array(t); 199 | if (256 == n) { 200 | for (var a = 0; a < t; a++) r[a] = e.charCodeAt(a); 201 | return r 202 | } 203 | for (var i = 0; i < t; i++) { 204 | var o = parseInt(e.charAt(i), n); 205 | if (NaN == o || !(o < n)) return ""; 206 | r[i] = o 207 | } 208 | return r 209 | }, 210 | ValToDigit: function (e, t) { 211 | var n, r = ""; 212 | if (256 == t) 213 | for (n = 0; n < e.length; n++) r += String.fromCharCode(e[n]); 214 | else 215 | for (n = 0; n < e.length; n++) r += o.alphabet[e[n]]; 216 | return r 217 | }, 218 | encryptWithCipher: function (e, t, n, r) { 219 | var a = e.length, 220 | i = Math.floor(a / 2), 221 | c = o.precompF(n, a, t, r), 222 | u = o.precompb(r, a), 223 | s = o.DigitToVal(e, i, r), 224 | d = o.DigitToVal(e.substr(i), a - i, r); 225 | if ("" == s || "" == d) return ""; 226 | for (var l = 0; l < 5; l++) { 227 | var f, p = o.F(n, 2 * l, t, d, d.length, s.length, c, r, u); 228 | f = 0; 229 | for (var m = s.length - 1; m >= 0; --m) { 230 | (h = s[m] + p[m] + f) < r ? (s[m] = h, f = 0) : (s[m] = h - r, f = 1) 231 | } 232 | p = o.F(n, 2 * l + 1, t, s, s.length, d.length, c, r, u); 233 | f = 0; 234 | for (m = d.length - 1; m >= 0; --m) { 235 | var h; 236 | (h = d[m] + p[m] + f) < r ? (d[m] = h, f = 0) : (d[m] = h - r, f = 1) 237 | } 238 | } 239 | return o.ValToDigit(s, r) + o.ValToDigit(d, r) 240 | }, 241 | encrypt: function (e, t, n, r) { 242 | var i = a.HexToKey(n); 243 | return null == i ? "" : o.encryptWithCipher(e, t, i, r) 244 | } 245 | } 246 | function encrypt(e,t,PIE_L,PIE_E,PIE_K,PIE_key_id,PIE_phase){ 247 | PIE = {L: parseInt(PIE_L), E: parseInt(PIE_E), K: PIE_K, key_id: PIE_key_id, phase: parseInt(PIE_phase)} 248 | var a_var = n.distill(e) 249 | var i_var = n.distill(t) 250 | var c_var = a_var.substr(0, PIE.L) + a_var.substring(a_var.length - PIE.E) 251 | var u_var = n.luhn(a_var) 252 | var s_var = a_var.substring(PIE.L + 1, a_var.length - PIE.E) 253 | var d_var = o.encrypt(s_var + i_var, c_var, PIE.K, 10) 254 | var l_var = a_var.substr(0, PIE.L) + "0" + d_var.substr(0, d_var.length - i_var.length) + a_var.substring(a_var.length - PIE.E) 255 | var f_var = n.reformat(n.fixluhn(l_var, PIE.L, u_var), e) 256 | var p_var = n.reformat(d_var.substring(d_var.length - i_var.length), t) 257 | return [f_var, p_var, n.integrity(PIE.K, f_var, p_var)] 258 | } -------------------------------------------------------------------------------- /sites/walmart.py: -------------------------------------------------------------------------------- 1 | from sites.walmart_encryption import walmart_encryption as w_e 2 | from utils import send_webhook 3 | import urllib,requests,time,lxml.html,json,sys,settings 4 | 5 | class Walmart: 6 | def __init__(self,task_id,status_signal,image_signal,product,profile,proxy,monitor_delay,error_delay,max_price): 7 | self.task_id,self.status_signal,self.image_signal,self.product,self.profile,self.monitor_delay,self.error_delay,self.max_price = task_id,status_signal,image_signal,product,profile,float(monitor_delay),float(error_delay),max_price 8 | self.session = requests.Session() 9 | if proxy != False: 10 | self.session.proxies.update(proxy) 11 | self.status_signal.emit({"msg":"Starting","status":"normal"}) 12 | self.product_image, offer_id = self.monitor() 13 | self.atc(offer_id) 14 | item_id, fulfillment_option, ship_method = self.check_cart_items() 15 | self.submit_shipping_method(item_id, fulfillment_option, ship_method) 16 | self.submit_shipping_address() 17 | card_data,PIE_key_id,PIE_phase = self.get_PIE() 18 | pi_hash = self.submit_payment(card_data,PIE_key_id,PIE_phase) 19 | self.submit_billing(pi_hash) 20 | self.submit_order() 21 | def monitor(self): 22 | headers = { 23 | "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 24 | "accept-encoding": "gzip, deflate, br", 25 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 26 | "cache-control": "max-age=0", 27 | "upgrade-insecure-requests": "1", 28 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36" 29 | } 30 | image_found = False 31 | sproduct_image = "" 32 | while True: 33 | self.status_signal.emit({"msg":"Loading Product Page","status":"normal"}) 34 | try: 35 | r = self.session.get(self.product,headers=headers) 36 | if r.status_code == 200: 37 | doc = lxml.html.fromstring(r.text) 38 | if not image_found: 39 | product_image = doc.xpath('//meta[@property="og:image"]/@content')[0] 40 | self.image_signal.emit(product_image) 41 | image_found = True 42 | price = float(doc.xpath('//span[@itemprop="price"]/@content')[0]) 43 | if "Add to Cart" in r.text: 44 | if self.max_price !="": 45 | if float(self.max_price) < price: 46 | self.status_signal.emit({"msg":"Waiting For Price Restock","status":"normal"}) 47 | self.session.cookies.clear() 48 | time.sleep(self.monitor_delay) 49 | continue 50 | offer_id = json.loads(doc.xpath('//script[@id="item"]/text()')[0])["item"]["product"]["buyBox"]["products"][0]["offerId"] 51 | return product_image, offer_id 52 | self.status_signal.emit({"msg":"Waiting For Restock","status":"normal"}) 53 | self.session.cookies.clear() 54 | time.sleep(self.monitor_delay) 55 | else: 56 | self.status_signal.emit({"msg":"Product Not Found","status":"normal"}) 57 | time.sleep(self.monitor_delay) 58 | except Exception as e: 59 | self.status_signal.emit({"msg":"Error Loading Product Page (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 60 | time.sleep(self.error_delay) 61 | 62 | def atc(self,offer_id): 63 | headers={ 64 | "accept": "application/json", 65 | "accept-encoding": "gzip, deflate, br", 66 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 67 | "content-type": "application/json", 68 | "origin": "https://www.walmart.com", 69 | "referer": self.product, 70 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36" 71 | } 72 | body = {"offerId":offer_id,"quantity":1} 73 | while True: 74 | self.status_signal.emit({"msg":"Adding To Cart","status":"normal"}) 75 | try: 76 | r = self.session.post("https://www.walmart.com/api/v3/cart/guest/:CID/items",json=body,headers=headers) 77 | if r.status_code == 201 and json.loads(r.text)["checkoutable"] == True: 78 | self.status_signal.emit({"msg":"Added To Cart","status":"carted"}) 79 | return 80 | else: 81 | self.status_signal.emit({"msg":"Error Adding To Cart","status":"error"}) 82 | time.sleep(self.error_delay) 83 | except Exception as e: 84 | self.status_signal.emit({"msg":"Error Adding To Cart (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 85 | time.sleep(self.error_delay) 86 | 87 | def check_cart_items(self): 88 | headers = { 89 | "accept": "application/json, text/javascript, */*; q=0.01", 90 | "accept-encoding": "gzip, deflate, br", 91 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 92 | "content-type": "application/json", 93 | "origin": "https://www.walmart.com", 94 | "referer": "https://www.walmart.com/checkout/", 95 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36", 96 | "wm_vertical_id": "0" 97 | } 98 | profile = self.profile 99 | body = {"postalCode":profile["shipping_zipcode"],"city":profile["shipping_city"],"state":profile["shipping_state"],"isZipLocated":True,"crt:CRT":"","customerId:CID":"","customerType:type":"","affiliateInfo:com.wm.reflector":""} 100 | while True: 101 | self.status_signal.emit({"msg":"Loading Cart Items","status":"normal"}) 102 | try: 103 | r = self.session.post("https://www.walmart.com/api/checkout/v3/contract?page=CHECKOUT_VIEW",json=body,headers=headers) 104 | if r.status_code == 201: 105 | r = json.loads(r.text)["items"][0] 106 | item_id = r["id"] 107 | fulfillment_option = r["fulfillmentSelection"]["fulfillmentOption"] 108 | ship_method = r["fulfillmentSelection"]["shipMethod"] 109 | self.status_signal.emit({"msg":"Loaded Cart Items","status":"normal"}) 110 | return item_id, fulfillment_option, ship_method 111 | else: 112 | if json.loads(r.text)["message"] == "Item is no longer in stock.": 113 | self.status_signal.emit({"msg":"Waiting For Restock","status":"normal"}) 114 | time.sleep(self.monitor_delay) 115 | else: 116 | self.status_signal.emit({"msg":"Error Loading Cart Items, Got Response: "+str(r.text),"status":"error"}) 117 | time.sleep(self.error_delay) 118 | except Exception as e: 119 | self.status_signal.emit({"msg":"Error Loading Cart Items (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 120 | time.sleep(self.error_delay) 121 | 122 | def submit_shipping_method(self, item_id, fulfillment_option, ship_method): 123 | headers = { 124 | "accept": "application/json, text/javascript, */*; q=0.01", 125 | "accept-encoding": "gzip, deflate, br", 126 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 127 | "content-type": "application/json", 128 | "origin": "https://www.walmart.com", 129 | "referer": "https://www.walmart.com/checkout/", 130 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36", 131 | "wm_vertical_id": "0" 132 | } 133 | body = {"groups":[{"fulfillmentOption":fulfillment_option,"itemIds":[item_id],"shipMethod":ship_method}]} 134 | while True: 135 | self.status_signal.emit({"msg":"Submitting Shipping Method","status":"normal"}) 136 | try: 137 | r = self.session.post("https://www.walmart.com/api/checkout/v3/contract/:PCID/fulfillment",json=body,headers=headers) 138 | if r.status_code == 200: 139 | try: 140 | r = json.loads(r.text) 141 | self.status_signal.emit({"msg":"Submitted Shipping Method","status":"normal"}) 142 | return 143 | except: 144 | pass 145 | self.status_signal.emit({"msg":"Error Submitting Shipping Method","status":"error"}) 146 | time.sleep(self.error_delay) 147 | except Exception as e: 148 | self.status_signal.emit({"msg":"Error Submitting Shipping Method (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 149 | time.sleep(self.error_delay) 150 | 151 | def submit_shipping_address(self): 152 | headers = { 153 | "accept": "application/json, text/javascript, */*; q=0.01", 154 | "accept-encoding": "gzip, deflate, br", 155 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 156 | "content-type": "application/json", 157 | "inkiru_precedence": "false", 158 | "origin": "https://www.walmart.com", 159 | "referer": "https://www.walmart.com/checkout/", 160 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36", 161 | "wm_vertical_id": "0" 162 | } 163 | profile = self.profile 164 | body = { 165 | "addressLineOne":profile["shipping_a1"], 166 | "city":profile["shipping_city"], 167 | "firstName":profile["shipping_fname"], 168 | "lastName":profile["shipping_lname"], 169 | "phone":profile["shipping_phone"], 170 | "email":profile["shipping_email"], 171 | "marketingEmailPref":False, 172 | "postalCode":profile["shipping_zipcode"], 173 | "state":profile["shipping_state"], 174 | "countryCode":"USA", 175 | "addressType":"RESIDENTIAL", 176 | "changedFields":[] 177 | } 178 | if profile["shipping_a2"] !="": 179 | body.update({"addressLineTwo":profile["shipping_a2"]}) 180 | while True: 181 | self.status_signal.emit({"msg":"Submitting Shipping Address","status":"normal"}) 182 | try: 183 | r = self.session.post("https://www.walmart.com/api/checkout/v3/contract/:PCID/shipping-address",json=body,headers=headers) 184 | if r.status_code == 200: 185 | try: 186 | r = json.loads(r.text) 187 | self.status_signal.emit({"msg":"Submitted Shipping Address","status":"normal"}) 188 | return 189 | except: 190 | pass 191 | self.status_signal.emit({"msg":"Error Submitting Shipping Address","status":"error"}) 192 | time.sleep(self.error_delay) 193 | except Exception as e: 194 | self.status_signal.emit({"msg":"Error Submitting Shipping Address (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 195 | time.sleep(self.error_delay) 196 | 197 | def get_PIE(self): 198 | headers = { 199 | "Accept": "*/*", 200 | "Accept-Encoding": "gzip, deflate, br", 201 | "Accept-Language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 202 | "Connection": "keep-alive", 203 | "Host": "securedataweb.walmart.com", 204 | "Referer": "https://www.walmart.com/", 205 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36" 206 | } 207 | profile = self.profile 208 | while True: 209 | self.status_signal.emit({"msg":"Getting Checkout Data","status":"normal"}) 210 | try: 211 | r = self.session.get("https://securedataweb.walmart.com/pie/v1/wmcom_us_vtg_pie/getkey.js?bust="+str(int(time.time())),headers=headers) 212 | if r.status_code == 200: 213 | PIE_L = int(r.text.split("PIE.L = ")[1].split(";")[0]) 214 | PIE_E = int(r.text.split("PIE.E = ")[1].split(";")[0]) 215 | PIE_K = str(r.text.split('PIE.K = "')[1].split('";')[0]) 216 | PIE_key_id = str(r.text.split('PIE.key_id = "')[1].split('";')[0]) 217 | PIE_phase = int(r.text.split('PIE.phase = ')[1].split(';')[0]) 218 | card_data = w_e.encrypt(profile["card_number"],profile["card_cvv"],PIE_L,PIE_E,PIE_K,PIE_key_id,PIE_phase) 219 | self.status_signal.emit({"msg":"Got Checkout Data","status":"normal"}) 220 | return card_data, PIE_key_id, PIE_phase 221 | self.status_signal.emit({"msg":"Error Getting Checkout Data","status":"error"}) 222 | time.sleep(self.error_delay) 223 | except Exception as e: 224 | self.status_signal.emit({"msg":"Error Getting Checkout Data (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 225 | time.sleep(self.error_delay) 226 | 227 | def submit_payment(self,card_data,PIE_key_id,PIE_phase): 228 | headers = { 229 | "accept": "application/json", 230 | "accept-encoding": "gzip, deflate, br", 231 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 232 | "content-type": "application/json", 233 | "inkiru_precedence": "false", 234 | "origin": "https://www.walmart.com", 235 | "referer": "https://www.walmart.com/checkout/", 236 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36" 237 | } 238 | profile = self.profile 239 | body = { 240 | "encryptedPan": card_data[0], 241 | "encryptedCvv": card_data[1], 242 | "integrityCheck": card_data[2], 243 | "keyId": PIE_key_id, 244 | "phase": PIE_phase, 245 | "state": profile["billing_state"], 246 | "postalCode": profile["billing_zipcode"], 247 | "addressLineOne": profile["billing_a1"], 248 | "addressLineTwo": profile["billing_a2"], 249 | "city": profile["billing_city"], 250 | "firstName": profile["billing_fname"], 251 | "lastName": profile["billing_lname"], 252 | "expiryMonth": profile["card_month"], 253 | "expiryYear": profile["card_year"], 254 | "phone": profile["billing_phone"], 255 | "cardType": profile["card_type"].upper(), 256 | "isGuest":True 257 | } 258 | while True: 259 | self.status_signal.emit({"msg":"Submitting Payment","status":"normal"}) 260 | try: 261 | r = self.session.post("https://www.walmart.com/api/checkout-customer/:CID/credit-card",json=body,headers=headers) 262 | if r.status_code == 200: 263 | pi_hash = json.loads(r.text)["piHash"] 264 | self.status_signal.emit({"msg":"Submitted Payment","status":"normal"}) 265 | return pi_hash 266 | self.status_signal.emit({"msg":"Error Submitting Payment","status":"error"}) 267 | if self.check_browser(): 268 | return 269 | time.sleep(self.error_delay) 270 | except Exception as e: 271 | self.status_signal.emit({"msg":"Error Submitting Payment (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 272 | time.sleep(self.error_delay) 273 | 274 | def submit_billing(self,pi_hash): 275 | headers = { 276 | "accept": "application/json, text/javascript, */*; q=0.01", 277 | "accept-encoding": "gzip, deflate, br", 278 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 279 | "content-type": "application/json", 280 | "inkiru_precedence": "false", 281 | "origin": "https://www.walmart.com", 282 | "referer": "https://www.walmart.com/checkout/", 283 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36", 284 | "wm_vertical_id": "0" 285 | } 286 | profile = self.profile 287 | card_data,PIE_key_id,PIE_phase = self.get_PIE() 288 | body = { 289 | "payments":[{ 290 | "paymentType":"CREDITCARD", 291 | "cardType": profile["card_type"].upper(), 292 | "firstName": profile["billing_fname"], 293 | "lastName": profile["billing_lname"], 294 | "addressLineOne": profile["billing_a1"], 295 | "addressLineTwo": profile["billing_a2"], 296 | "city": profile["billing_city"], 297 | "state": profile["billing_state"], 298 | "postalCode": profile["billing_zipcode"], 299 | "expiryMonth": profile["card_month"], 300 | "expiryYear": profile["card_year"], 301 | "email": profile["billing_email"], 302 | "phone": profile["billing_phone"], 303 | "encryptedPan": card_data[0], 304 | "encryptedCvv": card_data[1], 305 | "integrityCheck": card_data[2], 306 | "keyId": PIE_key_id, 307 | "phase": PIE_phase, 308 | "piHash": pi_hash 309 | }] 310 | } 311 | while True: 312 | self.status_signal.emit({"msg":"Submitting Billing","status":"normal"}) 313 | try: 314 | r = self.session.post("https://www.walmart.com/api/checkout/v3/contract/:PCID/payment",json=body,headers=headers) 315 | if r.status_code == 200: 316 | try: 317 | r = json.loads(r.text) 318 | self.status_signal.emit({"msg":"Submitted Billing","status":"normal"}) 319 | return 320 | except: 321 | pass 322 | self.status_signal.emit({"msg":"Error Submitting Billing","status":"error"}) 323 | if self.check_browser(): 324 | return 325 | time.sleep(self.error_delay) 326 | except Exception as e: 327 | self.status_signal.emit({"msg":"Error Submitting Billing (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 328 | time.sleep(self.error_delay) 329 | 330 | def submit_order(self): 331 | headers = { 332 | "accept": "application/json, text/javascript, */*; q=0.01", 333 | "accept-encoding": "gzip, deflate, br", 334 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 335 | "content-type": "application/json", 336 | "inkiru_precedence": "false", 337 | "origin": "https://www.walmart.com", 338 | "referer": "https://www.walmart.com/checkout/", 339 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36", 340 | "wm_vertical_id": "0" 341 | } 342 | while True: 343 | self.status_signal.emit({"msg":"Submitting Order","status":"alt"}) 344 | try: 345 | r = self.session.put("https://www.walmart.com/api/checkout/v3/contract/:PCID/order",json={},headers=headers) 346 | try: 347 | json.loads(r.text)["order"] 348 | self.status_signal.emit({"msg":"Order Placed","status":"success"}) 349 | send_webhook("OP","Walmart",self.profile["profile_name"],self.task_id,self.product_image) 350 | return 351 | except: 352 | self.status_signal.emit({"msg":"Payment Failed","status":"error"}) 353 | if self.check_browser(): 354 | return 355 | send_webhook("PF","Walmart",self.profile["profile_name"],self.task_id,self.product_image) 356 | return 357 | except Exception as e: 358 | self.status_signal.emit({"msg":"Error Submitting Order (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 359 | time.sleep(self.error_delay) 360 | 361 | def check_browser(self): 362 | if settings.browser_on_failed: 363 | self.status_signal.emit({"msg":"Browser Ready","status":"alt","url":"https://www.walmart.com/checkout/#/payment","cookies":[{"name":cookie.name,"value":cookie.value,"domain":cookie.domain} for cookie in self.session.cookies]}) 364 | send_webhook("B","Walmart",self.profile["profile_name"],self.task_id,self.product_image) 365 | return True 366 | return False -------------------------------------------------------------------------------- /pages/homepage.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtCore, QtGui, QtWidgets 2 | from sites.walmart import Walmart 3 | from sites.bestbuy import BestBuy 4 | from pages.createdialog import CreateDialog 5 | from utils import get_profile, get_proxy, BirdLogger, return_data, write_data, open_browser 6 | import urllib.request,sys,platform 7 | import settings 8 | def no_abort(a, b, c): 9 | sys.__excepthook__(a, b, c) 10 | sys.excepthook = no_abort 11 | logger = BirdLogger() 12 | class HomePage(QtWidgets.QWidget): 13 | def __init__(self,parent=None): 14 | super(HomePage, self).__init__(parent) 15 | self.setupUi(self) 16 | self.load_tasks() 17 | def setupUi(self, homepage): 18 | global tasks 19 | self.tasks = [] 20 | tasks = self.tasks 21 | self.homepage = homepage 22 | self.homepage.setAttribute(QtCore.Qt.WA_StyledBackground, True) 23 | self.homepage.setGeometry(QtCore.QRect(60, 0, 1041, 601)) 24 | self.tasks_card = QtWidgets.QWidget(self.homepage) 25 | self.tasks_card.setGeometry(QtCore.QRect(30, 110, 991, 461)) 26 | self.tasks_card.setStyleSheet("background-color: #232323;border-radius: 20px;border: 1px solid #2e2d2d;") 27 | self.scrollArea = QtWidgets.QScrollArea(self.tasks_card) 28 | self.scrollArea.setGeometry(QtCore.QRect(20, 30, 951, 421)) 29 | self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 30 | self.scrollArea.setStyleSheet("border:none;") 31 | self.scrollArea.setWidgetResizable(True) 32 | self.scrollAreaWidgetContents = QtWidgets.QWidget() 33 | self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 951, 421)) 34 | self.verticalLayout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents) 35 | self.verticalLayout.setContentsMargins(0, -1, 0, -1) 36 | self.verticalLayout.setSpacing(2) 37 | spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 38 | self.verticalLayout.addItem(spacerItem) 39 | self.scrollArea.setWidget(self.scrollAreaWidgetContents) 40 | self.image_table_header = QtWidgets.QLabel(self.tasks_card) 41 | self.image_table_header.setGeometry(QtCore.QRect(40, 7, 51, 31)) 42 | self.image_table_header.setText("Image") 43 | font = QtGui.QFont() 44 | font.setFamily("Arial") 45 | font.setPointSize(15) if platform.system() == "Darwin" else font.setPointSize(15*.75) 46 | font.setBold(False) 47 | font.setWeight(50) 48 | self.image_table_header.setFont(font) 49 | self.image_table_header.setStyleSheet("color: rgb(234, 239, 239);border: none;") 50 | self.product_table_header = QtWidgets.QLabel(self.tasks_card) 51 | self.product_table_header.setGeometry(QtCore.QRect(240, 7, 61, 31)) 52 | self.product_table_header.setFont(font) 53 | self.product_table_header.setStyleSheet("color: rgb(234, 239, 239);border: none;") 54 | self.product_table_header.setText("Product") 55 | self.profile_table_header = QtWidgets.QLabel(self.tasks_card) 56 | self.profile_table_header.setGeometry(QtCore.QRect(590, 7, 61, 31)) 57 | self.profile_table_header.setFont(font) 58 | self.profile_table_header.setStyleSheet("color: rgb(234, 239, 239);border: none;") 59 | self.profile_table_header.setText("Profile") 60 | self.status_table_header = QtWidgets.QLabel(self.tasks_card) 61 | self.status_table_header.setGeometry(QtCore.QRect(650, 7, 61, 31)) 62 | self.status_table_header.setFont(font) 63 | self.status_table_header.setStyleSheet("color: rgb(234, 239, 239);border: none;") 64 | self.status_table_header.setText("Status") 65 | self.actions_table_header = QtWidgets.QLabel(self.tasks_card) 66 | self.actions_table_header.setGeometry(QtCore.QRect(890, 7, 61, 31)) 67 | self.actions_table_header.setFont(font) 68 | self.actions_table_header.setStyleSheet("color: rgb(234, 239, 239);border: none;") 69 | self.actions_table_header.setText("Actions") 70 | self.site_table_header = QtWidgets.QLabel(self.tasks_card) 71 | self.site_table_header.setGeometry(QtCore.QRect(160, 7, 61, 31)) 72 | self.site_table_header.setFont(font) 73 | self.site_table_header.setStyleSheet("color: rgb(234, 239, 239);border: none;") 74 | self.site_table_header.setText("Site") 75 | self.id_header = QtWidgets.QLabel(self.tasks_card) 76 | self.id_header.setGeometry(QtCore.QRect(110, 7, 31, 31)) 77 | self.id_header.setFont(font) 78 | self.id_header.setStyleSheet("color: rgb(234, 239, 239);border: none;") 79 | self.id_header.setText("ID") 80 | self.tasks_header = QtWidgets.QLabel(self.homepage) 81 | self.tasks_header.setGeometry(QtCore.QRect(30, 10, 61, 31)) 82 | self.tasks_header.setText("Tasks") 83 | font = QtGui.QFont() 84 | font.setFamily("Arial") 85 | font.setPointSize(22) if platform.system() == "Darwin" else font.setPointSize(22*.75) 86 | font.setBold(False) 87 | font.setWeight(50) 88 | self.tasks_header.setFont(font) 89 | self.tasks_header.setStyleSheet("color: rgb(234, 239, 239);") 90 | self.checkouts_card = QtWidgets.QWidget(self.homepage) 91 | self.checkouts_card.setGeometry(QtCore.QRect(440, 45, 171, 51)) 92 | self.checkouts_card.setStyleSheet("background-color: #232323;border-radius: 10px;border: 1px solid #2e2d2d;") 93 | self.checkouts_label = QtWidgets.QLabel(self.checkouts_card) 94 | self.checkouts_label.setGeometry(QtCore.QRect(78, 10, 81, 31)) 95 | font = QtGui.QFont() 96 | font.setFamily("Arial") 97 | font.setPointSize(16) if platform.system() == "Darwin" else font.setPointSize(16*.75) 98 | font.setBold(False) 99 | font.setWeight(50) 100 | self.checkouts_label.setFont(font) 101 | self.checkouts_label.setStyleSheet("color: rgb(234, 239, 239);border: none;") 102 | self.checkouts_label.setText("Checkouts") 103 | self.checkouts_icon = QtWidgets.QLabel(self.checkouts_card) 104 | self.checkouts_icon.setGeometry(QtCore.QRect(10, 10, 31, 31)) 105 | self.checkouts_icon.setStyleSheet("border: none;") 106 | self.checkouts_icon.setText("") 107 | self.checkouts_icon.setPixmap(QtGui.QPixmap(":/images/success.png")) 108 | self.checkouts_icon.setScaledContents(True) 109 | global checkouts_count 110 | self.checkouts_count = QtWidgets.QLabel(self.checkouts_card) 111 | checkouts_count = self.checkouts_count 112 | self.checkouts_count.setGeometry(QtCore.QRect(43, 10, 31, 31)) 113 | self.checkouts_count.setFont(font) 114 | self.checkouts_count.setStyleSheet("color: #34C693;border: none;") 115 | self.checkouts_count.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) 116 | self.checkouts_count.setText("0") 117 | self.tasks_total_card = QtWidgets.QWidget(self.homepage) 118 | self.tasks_total_card.setGeometry(QtCore.QRect(30, 45, 181, 51)) 119 | self.tasks_total_card.setStyleSheet("background-color: #232323;border-radius: 10px;border: 1px solid #2e2d2d;") 120 | self.tasks_total_label = QtWidgets.QLabel(self.tasks_total_card) 121 | self.tasks_total_label.setGeometry(QtCore.QRect(80, 10, 91, 31)) 122 | self.tasks_total_label.setFont(font) 123 | self.tasks_total_label.setStyleSheet("color: rgb(234, 239, 239);border: none;") 124 | self.tasks_total_label.setText("Total Tasks") 125 | self.tasks_total_icon = QtWidgets.QLabel(self.tasks_total_card) 126 | self.tasks_total_icon.setGeometry(QtCore.QRect(10, 10, 31, 31)) 127 | self.tasks_total_icon.setStyleSheet("border: none;") 128 | self.tasks_total_icon.setText("") 129 | self.tasks_total_icon.setPixmap(QtGui.QPixmap(":/images/tasks.png")) 130 | self.tasks_total_icon.setScaledContents(True) 131 | global tasks_total_count 132 | self.tasks_total_count = QtWidgets.QLabel(self.tasks_total_card) 133 | tasks_total_count = self.tasks_total_count 134 | self.tasks_total_count.setGeometry(QtCore.QRect(43, 10, 31, 31)) 135 | self.tasks_total_count.setFont(font) 136 | self.tasks_total_count.setStyleSheet("color: #755FF6;border: none;") 137 | self.tasks_total_count.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) 138 | self.tasks_total_count.setText("0") 139 | self.carted_card = QtWidgets.QWidget(self.homepage) 140 | self.carted_card.setGeometry(QtCore.QRect(240, 45, 171, 51)) 141 | self.carted_card.setStyleSheet("background-color: #232323;border-radius: 10px;border: 1px solid #2e2d2d;") 142 | self.carted_label = QtWidgets.QLabel(self.carted_card) 143 | self.carted_label.setGeometry(QtCore.QRect(80, 10, 90, 31)) 144 | self.carted_label.setFont(font) 145 | self.carted_label.setStyleSheet("color: rgb(234, 239, 239);border: none;") 146 | self.carted_label.setText("Total Carts") 147 | self.carted_icon = QtWidgets.QLabel(self.carted_card) 148 | self.carted_icon.setGeometry(QtCore.QRect(10, 10, 31, 31)) 149 | self.carted_icon.setStyleSheet("border: none;") 150 | self.carted_icon.setText("") 151 | self.carted_icon.setPixmap(QtGui.QPixmap(":/images/cart.png")) 152 | self.carted_icon.setScaledContents(True) 153 | global carted_count 154 | self.carted_count = QtWidgets.QLabel(self.carted_card) 155 | carted_count = self.carted_count 156 | self.carted_count.setGeometry(QtCore.QRect(43, 10, 31, 31)) 157 | self.carted_count.setFont(font) 158 | self.carted_count.setStyleSheet("color: #F6905E;border: none;") 159 | self.carted_count.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) 160 | self.carted_count.setText("0") 161 | self.buttons_card = QtWidgets.QWidget(self.homepage) 162 | self.buttons_card.setGeometry(QtCore.QRect(640, 45, 381, 51)) 163 | self.buttons_card.setStyleSheet("background-color: #232323;border-radius: 10px;border: 1px solid #2e2d2d;") 164 | self.startall_btn = QtWidgets.QPushButton(self.buttons_card) 165 | self.startall_btn.setGeometry(QtCore.QRect(103, 10, 86, 32)) 166 | font = QtGui.QFont() 167 | font.setFamily("Arial") 168 | self.startall_btn.setFont(font) 169 | self.startall_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 170 | self.startall_btn.setStyleSheet("color: #FFFFFF;background-color: #5D43FB;border: none;") 171 | self.startall_btn.setText("Start All") 172 | self.startall_btn.clicked.connect(self.start_all_tasks) 173 | self.stopall_btn = QtWidgets.QPushButton(self.buttons_card) 174 | self.stopall_btn.setGeometry(QtCore.QRect(197, 10, 81, 32)) 175 | self.stopall_btn.setFont(font) 176 | self.stopall_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 177 | self.stopall_btn.setStyleSheet("color: #FFFFFF;background-color: #5D43FB;border: none;") 178 | self.stopall_btn.setText("Stop All") 179 | self.stopall_btn.clicked.connect(self.stop_all_tasks) 180 | self.deleteall_btn = QtWidgets.QPushButton(self.buttons_card) 181 | self.deleteall_btn.setGeometry(QtCore.QRect(285, 10, 86, 32)) 182 | self.deleteall_btn.setFont(font) 183 | self.deleteall_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 184 | self.deleteall_btn.setStyleSheet("color: #FFFFFF;background-color: #5D43FB;border: none;") 185 | self.deleteall_btn.setText("Delete All") 186 | self.deleteall_btn.clicked.connect(self.delete_all_tasks) 187 | self.newtask_btn = QtWidgets.QPushButton(self.buttons_card) 188 | self.newtask_btn.setGeometry(QtCore.QRect(10, 10, 86, 32)) 189 | self.newtask_btn.setFont(font) 190 | self.newtask_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 191 | self.newtask_btn.setStyleSheet("color: #FFFFFF;background-color: #5D43FB;border: none;") 192 | self.newtask_btn.setText("New Task") 193 | QtCore.QMetaObject.connectSlotsByName(homepage) 194 | 195 | def load_tasks(self): 196 | tasks_data = return_data("./data/tasks.json") 197 | write_data("./data/tasks.json",[]) 198 | try: 199 | for task in tasks_data: 200 | tab = TaskTab(task["site"],task["product"],task["profile"],task["proxies"],task["monitor_delay"],task["error_delay"],task["max_price"],self.stop_all_tasks,self.scrollAreaWidgetContents) 201 | self.verticalLayout.takeAt(self.verticalLayout.count()-1) 202 | self.verticalLayout.addWidget(tab) 203 | spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) 204 | self.verticalLayout.addItem(spacerItem) 205 | except: 206 | pass 207 | 208 | def set_settings_data(self,settings_data): 209 | global settings 210 | settings = settings_data 211 | 212 | def start_all_tasks(self): 213 | for task in self.tasks: 214 | try: 215 | task.start(None) 216 | except: 217 | pass 218 | def stop_all_tasks(self): 219 | for task in self.tasks: 220 | try: 221 | task.stop(None) 222 | except: 223 | pass 224 | 225 | def delete_all_tasks(self): 226 | for task in self.tasks: 227 | try: 228 | task.delete(None) 229 | except: 230 | pass 231 | 232 | class TaskTab(QtWidgets.QWidget): 233 | def __init__(self,site,product,profile,proxies,monitor_delay,error_delay,max_price,stop_all,parent=None): 234 | super(TaskTab, self).__init__(parent) 235 | self.task_id = str(int(tasks_total_count.text())+1) 236 | tasks_total_count.setText(self.task_id) 237 | self.site,self.product,self.profile,self.proxies,self.monitor_delay,self.error_delay,self.max_price,self.stop_all = site,product,profile,proxies,monitor_delay,error_delay,max_price,stop_all 238 | self.setupUi(self) 239 | tasks.append(self) 240 | tasks_data = return_data("./data/tasks.json") 241 | task_data = {"task_id": self.task_id,"site":self.site,"product": self.product,"profile": self.profile,"proxies": self.proxies,"monitor_delay": self.monitor_delay,"error_delay": self.error_delay,"max_price": self.max_price} 242 | tasks_data.append(task_data) 243 | write_data("./data/tasks.json",tasks_data) 244 | def setupUi(self,TaskTab): 245 | self.running = False 246 | 247 | self.TaskTab = TaskTab 248 | self.TaskTab.setMinimumSize(QtCore.QSize(0, 50)) 249 | self.TaskTab.setMaximumSize(QtCore.QSize(16777215, 50)) 250 | self.TaskTab.setStyleSheet("border-radius: none;") 251 | self.product_label = QtWidgets.QLabel(self.TaskTab) 252 | self.product_label.setGeometry(QtCore.QRect(222, 10, 331, 31)) 253 | font = QtGui.QFont() 254 | font.setFamily("Arial") 255 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 256 | font.setBold(False) 257 | font.setWeight(50) 258 | self.product_label.setFont(font) 259 | self.product_label.setStyleSheet("color: rgb(234, 239, 239);") 260 | self.profile_label = QtWidgets.QLabel(self.TaskTab) 261 | self.profile_label.setGeometry(QtCore.QRect(571, 10, 51, 31)) 262 | self.profile_label.setFont(font) 263 | self.profile_label.setStyleSheet("color: rgb(234, 239, 239);") 264 | self.status_label = QtWidgets.QLabel(self.TaskTab) 265 | self.status_label.setGeometry(QtCore.QRect(632, 10, 231, 31)) 266 | self.status_label.setFont(font) 267 | self.status_label.setStyleSheet("color: rgb(234, 239, 239);") 268 | self.browser_label = QtWidgets.QLabel(self.TaskTab) 269 | self.browser_label.setGeometry(QtCore.QRect(632, 10, 231, 31)) 270 | self.browser_label.setFont(font) 271 | self.browser_label.setStyleSheet("color: rgb(163, 149, 255);") 272 | self.browser_label.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 273 | self.browser_label.mousePressEvent = self.open_browser 274 | self.browser_label.hide() 275 | self.start_btn = QtWidgets.QLabel(self.TaskTab) 276 | self.start_btn.setGeometry(QtCore.QRect(870, 15, 16, 16)) 277 | self.start_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 278 | self.start_btn.setPixmap(QtGui.QPixmap(":/images/play.png")) 279 | self.start_btn.setScaledContents(True) 280 | self.start_btn.mousePressEvent = self.start 281 | self.stop_btn = QtWidgets.QLabel(self.TaskTab) 282 | self.stop_btn.setGeometry(QtCore.QRect(870, 15, 16, 16)) 283 | self.stop_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 284 | self.stop_btn.setPixmap(QtGui.QPixmap(":/images/stop.png")) 285 | self.stop_btn.setScaledContents(True) 286 | self.stop_btn.mousePressEvent = self.stop 287 | self.delete_btn = QtWidgets.QLabel(self.TaskTab) 288 | self.delete_btn.setGeometry(QtCore.QRect(920, 15, 16, 16)) 289 | self.delete_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 290 | self.delete_btn.setPixmap(QtGui.QPixmap(":/images/trash.png")) 291 | self.delete_btn.setScaledContents(True) 292 | self.delete_btn.mousePressEvent = self.delete 293 | self.edit_btn = QtWidgets.QLabel(self.TaskTab) 294 | self.edit_btn.setGeometry(QtCore.QRect(895, 15, 16, 16)) 295 | self.edit_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 296 | self.edit_btn.setPixmap(QtGui.QPixmap(":/images/edit.png")) 297 | self.edit_btn.setScaledContents(True) 298 | self.edit_btn.mousePressEvent = self.edit 299 | self.image = QtWidgets.QLabel(self.TaskTab) 300 | self.image.setGeometry(QtCore.QRect(20, 0, 50, 50)) 301 | self.image.setPixmap(QtGui.QPixmap(":/images/no_image.png")) 302 | self.image.setScaledContents(True) 303 | self.site_label = QtWidgets.QLabel(self.TaskTab) 304 | self.site_label.setGeometry(QtCore.QRect(140, 10, 61, 31)) 305 | self.site_label.setFont(font) 306 | self.site_label.setStyleSheet("color: rgb(234, 239, 239);") 307 | self.id_label = QtWidgets.QLabel(self.TaskTab) 308 | self.id_label.setGeometry(QtCore.QRect(90, 10, 31, 31)) 309 | self.id_label.setFont(font) 310 | self.id_label.setStyleSheet("color: rgb(234, 239, 239);") 311 | self.stop_btn.raise_() 312 | self.product_label.raise_() 313 | self.profile_label.raise_() 314 | self.browser_label.raise_() 315 | self.start_btn.raise_() 316 | self.delete_btn.raise_() 317 | self.image.raise_() 318 | self.site_label.raise_() 319 | self.monitor_delay_label = QtWidgets.QLabel(self.TaskTab) 320 | self.monitor_delay_label.hide() 321 | self.error_delay_label = QtWidgets.QLabel(self.TaskTab) 322 | self.error_delay_label.hide() 323 | self.max_price_label = QtWidgets.QLabel(self.TaskTab) 324 | self.max_price_label.hide() 325 | self.proxies_label = QtWidgets.QLabel(self.TaskTab) 326 | self.proxies_label.hide() 327 | self.load_labels() 328 | 329 | 330 | def load_labels(self): 331 | self.id_label.setText(self.task_id) 332 | self.product_label.setText(self.product) 333 | self.profile_label.setText(self.profile) 334 | self.proxies_label.setText(self.proxies) 335 | self.status_label.setText("Idle") 336 | self.browser_label.setText("Click To Open Browser") 337 | self.site_label.setText(self.site) 338 | self.monitor_delay_label.setText(self.monitor_delay) 339 | self.error_delay_label.setText(self.error_delay) 340 | self.max_price_label.setText(self.max_price) 341 | 342 | def update_status(self,msg): 343 | self.status_label.setText(msg["msg"]) 344 | if msg["msg"] == "Browser Ready": 345 | self.browser_url,self.browser_cookies = msg["url"],msg["cookies"] 346 | self.running = False 347 | self.start_btn.raise_() 348 | self.browser_label.show() 349 | logger.alt(self.task_id,msg["msg"]) 350 | loop = QtCore.QEventLoop() 351 | QtCore.QTimer.singleShot(1000, loop.quit) 352 | loop.exec_() 353 | self.task.stop() 354 | return 355 | if msg["status"] == "idle": 356 | self.status_label.setStyleSheet("color: rgb(255, 255, 255);") 357 | logger.normal(self.task_id,msg["msg"]) 358 | elif msg["status"] == "normal": 359 | self.status_label.setStyleSheet("color: rgb(163, 149, 255);") 360 | logger.normal(self.task_id,msg["msg"]) 361 | elif msg["status"] == "alt": 362 | self.status_label.setStyleSheet("color: rgb(242, 166, 137);") 363 | logger.alt(self.task_id,msg["msg"]) 364 | elif msg["status"] == "error": 365 | self.status_label.setStyleSheet("color: rgb(252, 81, 81);") 366 | logger.error(self.task_id,msg["msg"]) 367 | elif msg["status"] == "success": 368 | self.status_label.setStyleSheet("color: rgb(52, 198, 147);") 369 | logger.success(self.task_id,msg["msg"]) 370 | self.running = False 371 | self.start_btn.raise_() 372 | if settings.buy_one: 373 | self.stop_all() 374 | checkouts_count.setText(str(int(checkouts_count.text())+1)) 375 | elif msg["status"] == "carted": 376 | self.status_label.setStyleSheet("color: rgb(163, 149, 255);") 377 | logger.alt(self.task_id,msg["msg"]) 378 | carted_count.setText(str(int(carted_count.text())+1)) 379 | 380 | def update_image(self,image_url): 381 | self.image_thread = ImageThread(image_url) 382 | self.image_thread.finished_signal.connect(self.set_image) 383 | self.image_thread.start() 384 | 385 | def set_image(self,pixmap): 386 | self.image.setPixmap(pixmap) 387 | 388 | def start(self,event): 389 | if not self.running: 390 | self.browser_label.hide() 391 | self.task = TaskThread() 392 | self.task.status_signal.connect(self.update_status) 393 | self.task.image_signal.connect(self.update_image) 394 | self.task.set_data( 395 | self.task_id, 396 | self.site_label.text(), 397 | self.product_label.text(), 398 | self.profile_label.text(), 399 | self.proxies_label.text(), 400 | self.monitor_delay_label.text(), 401 | self.error_delay_label.text(), 402 | self.max_price_label.text() 403 | ) 404 | self.task.start() 405 | self.running = True 406 | self.stop_btn.raise_() 407 | 408 | def stop(self,event): 409 | self.task.stop() 410 | self.running = False 411 | self.update_status({"msg":"Stopped","status":"idle"}) 412 | self.start_btn.raise_() 413 | 414 | def edit(self,event): 415 | self.edit_dialog = CreateDialog() 416 | self.edit_dialog.addtask_btn.clicked.connect(self.update_task) 417 | self.edit_dialog.taskcount_spinbox.hide() 418 | self.edit_dialog.profile_box.clear() 419 | self.edit_dialog.proxies_box.clear() 420 | profile_combobox = self.parent().parent().parent().parent().parent().parent().parent().createdialog.profile_box 421 | for profile in [profile_combobox.itemText(i) for i in range(profile_combobox.count())]: 422 | self.edit_dialog.profile_box.addItem(profile) 423 | proxies_combobox = self.parent().parent().parent().parent().parent().parent().parent().createdialog.proxies_box 424 | for proxy in [proxies_combobox.itemText(i) for i in range(proxies_combobox.count())]: 425 | self.edit_dialog.proxies_box.addItem(proxy) 426 | self.edit_dialog.load_data(self) 427 | self.edit_dialog.show() 428 | 429 | def update_task(self): 430 | self.site=self.edit_dialog.site_box.currentText() 431 | self.product=self.edit_dialog.input_edit.text() 432 | self.profile=self.edit_dialog.profile_box.currentText() 433 | self.proxies=self.edit_dialog.proxies_box.currentText() 434 | self.monitor_delay=self.edit_dialog.monitor_edit.text() 435 | self.error_delay = self.edit_dialog.error_edit.text() 436 | self.max_price = self.edit_dialog.price_edit.text() 437 | self.load_labels() 438 | self.delete_json() 439 | tasks_data = return_data("./data/tasks.json") 440 | task_data = {"task_id": self.task_id, "site": self.site, "product": self.product, "profile": self.profile, 441 | "proxies": self.proxies, "monitor_delay": self.monitor_delay, "error_delay": self.error_delay, 442 | "max_price": self.max_price} 443 | tasks_data.append(task_data) 444 | write_data("./data/tasks.json",tasks_data) 445 | self.edit_dialog.deleteLater() 446 | 447 | def delete_json(self): 448 | tasks_data = return_data("./data/tasks.json") 449 | for task in tasks_data: 450 | if task["task_id"] == self.task_id: 451 | tasks_data.remove(task) 452 | break 453 | write_data("./data/tasks.json", tasks_data) 454 | 455 | def delete(self,event): 456 | tasks_total_count.setText(str(int(tasks_total_count.text()) - 1)) 457 | self.delete_json() 458 | self.TaskTab.deleteLater() 459 | 460 | def open_browser(self,event): 461 | self.browser_thread = BrowserThread() 462 | self.browser_thread.set_data( 463 | self.browser_url, 464 | self.browser_cookies 465 | ) 466 | self.browser_thread.start() 467 | class TaskThread(QtCore.QThread): 468 | status_signal = QtCore.pyqtSignal("PyQt_PyObject") 469 | image_signal = QtCore.pyqtSignal("PyQt_PyObject") 470 | def __init__(self): 471 | QtCore.QThread.__init__(self) 472 | 473 | def set_data(self,task_id,site,product,profile,proxies,monitor_delay,error_delay,max_price): 474 | self.task_id,self.site,self.product,self.profile,self.proxies,self.monitor_delay,self.error_delay,self.max_price = task_id,site,product,profile,proxies,monitor_delay,error_delay,max_price 475 | 476 | def run(self): 477 | profile,proxy = get_profile(self.profile),get_proxy(self.proxies) 478 | if profile == None: 479 | self.status_signal.emit({"msg":"Invalid profile","status":"error"}) 480 | return 481 | if proxy == None: 482 | self.status_signal.emit({"msg":"Invalid proxy list","status":"error"}) 483 | return 484 | if self.site == "Walmart": 485 | Walmart(self.task_id,self.status_signal,self.image_signal,self.product,profile,proxy,self.monitor_delay,self.error_delay,self.max_price) 486 | elif self.site == "Bestbuy": 487 | BestBuy(self.task_id,self.status_signal,self.image_signal,self.product,profile,proxy,self.monitor_delay,self.error_delay) 488 | 489 | def stop(self): 490 | self.terminate() 491 | 492 | class ImageThread(QtCore.QThread): 493 | finished_signal = QtCore.pyqtSignal("PyQt_PyObject") 494 | def __init__(self,image_url): 495 | self.image_url = image_url 496 | QtCore.QThread.__init__(self) 497 | 498 | def run(self): 499 | data = urllib.request.urlopen(self.image_url).read() 500 | pixmap = QtGui.QPixmap() 501 | pixmap.loadFromData(data) 502 | self.finished_signal.emit(pixmap) 503 | 504 | class BrowserThread(QtCore.QThread): 505 | def __init__(self): 506 | QtCore.QThread.__init__(self) 507 | 508 | def set_data(self,url,cookies): 509 | self.url,self.cookies = url,cookies 510 | def run(self): 511 | open_browser(self.url,self.cookies) 512 | 513 | -------------------------------------------------------------------------------- /pages/profilespage.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtCore, QtGui, QtWidgets 2 | from utils import return_data,write_data,get_profile,Encryption 3 | import sys,platform 4 | def no_abort(a, b, c): 5 | sys.__excepthook__(a, b, c) 6 | sys.excepthook = no_abort 7 | 8 | class ProfilesPage(QtWidgets.QWidget): 9 | def __init__(self,parent=None): 10 | super(ProfilesPage, self).__init__(parent) 11 | self.setupUi(self) 12 | def setupUi(self, profilespage): 13 | self.profilespage = profilespage 14 | self.profilespage.setAttribute(QtCore.Qt.WA_StyledBackground, True) 15 | self.profilespage.setGeometry(QtCore.QRect(60, 0, 1041, 601)) 16 | self.profilespage.setStyleSheet("QComboBox::drop-down { border: 0px;}QComboBox::down-arrow { image: url(:/images/down_icon.png); width: 14px; height: 14px;}QComboBox{ padding: 1px 0px 1px 3px;}QLineEdit:focus { border: none; outline: none;}") 17 | self.shipping_card = QtWidgets.QWidget(self.profilespage) 18 | self.shipping_card.setGeometry(QtCore.QRect(30, 70, 313, 501)) 19 | self.shipping_card.setStyleSheet("background-color: #232323;border-radius: 20px;border: 1px solid #2e2d2d;") 20 | self.shipping_fname_edit = QtWidgets.QLineEdit(self.shipping_card) 21 | self.shipping_fname_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 22 | self.shipping_fname_edit.setGeometry(QtCore.QRect(30, 50, 113, 21)) 23 | font = QtGui.QFont() 24 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 25 | font.setFamily("Arial") 26 | self.shipping_fname_edit.setFont(font) 27 | self.shipping_fname_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 28 | self.shipping_fname_edit.setPlaceholderText("First Name") 29 | self.shipping_header = QtWidgets.QLabel(self.shipping_card) 30 | self.shipping_header.setGeometry(QtCore.QRect(20, 10, 81, 31)) 31 | font.setPointSize(18) if platform.system() == "Darwin" else font.setPointSize(18*.75) 32 | font.setBold(False) 33 | font.setWeight(50) 34 | self.shipping_header.setFont(font) 35 | self.shipping_header.setStyleSheet("color: rgb(212, 214, 214);border: none;") 36 | self.shipping_header.setText("Shipping") 37 | self.shipping_lname_edit = QtWidgets.QLineEdit(self.shipping_card) 38 | self.shipping_lname_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 39 | self.shipping_lname_edit.setGeometry(QtCore.QRect(170, 50, 113, 21)) 40 | font = QtGui.QFont() 41 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 42 | font.setFamily("Arial") 43 | self.shipping_lname_edit.setFont(font) 44 | self.shipping_lname_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 45 | self.shipping_lname_edit.setPlaceholderText("Last Name") 46 | self.shipping_email_edit = QtWidgets.QLineEdit(self.shipping_card) 47 | self.shipping_email_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 48 | self.shipping_email_edit.setGeometry(QtCore.QRect(30, 100, 253, 21)) 49 | self.shipping_email_edit.setFont(font) 50 | self.shipping_email_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 51 | self.shipping_email_edit.setPlaceholderText("Email Address") 52 | self.shipping_phone_edit = QtWidgets.QLineEdit(self.shipping_card) 53 | self.shipping_phone_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 54 | self.shipping_phone_edit.setGeometry(QtCore.QRect(30, 150, 253, 21)) 55 | self.shipping_phone_edit.setFont(font) 56 | self.shipping_phone_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 57 | self.shipping_phone_edit.setPlaceholderText("Phone Number") 58 | self.shipping_address1_edit = QtWidgets.QLineEdit(self.shipping_card) 59 | self.shipping_address1_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 60 | self.shipping_address1_edit.setGeometry(QtCore.QRect(30, 200, 151, 21)) 61 | self.shipping_address1_edit.setFont(font) 62 | self.shipping_address1_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 63 | self.shipping_address1_edit.setPlaceholderText("Address 1") 64 | self.shipping_address2_edit = QtWidgets.QLineEdit(self.shipping_card) 65 | self.shipping_address2_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 66 | self.shipping_address2_edit.setGeometry(QtCore.QRect(208, 200, 75, 21)) 67 | self.shipping_address2_edit.setFont(font) 68 | self.shipping_address2_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 69 | self.shipping_address2_edit.setPlaceholderText("Address 2") 70 | self.shipping_city_edit = QtWidgets.QLineEdit(self.shipping_card) 71 | self.shipping_city_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 72 | self.shipping_city_edit.setGeometry(QtCore.QRect(30, 250, 151, 21)) 73 | self.shipping_city_edit.setFont(font) 74 | self.shipping_city_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 75 | self.shipping_city_edit.setPlaceholderText("City") 76 | self.shipping_zipcode_edit = QtWidgets.QLineEdit(self.shipping_card) 77 | self.shipping_zipcode_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 78 | self.shipping_zipcode_edit.setGeometry(QtCore.QRect(208, 250, 75, 21)) 79 | self.shipping_zipcode_edit.setFont(font) 80 | self.shipping_zipcode_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 81 | self.shipping_zipcode_edit.setPlaceholderText("Zip Code") 82 | self.shipping_state_box = QtWidgets.QComboBox(self.shipping_card) 83 | self.shipping_state_box.setGeometry(QtCore.QRect(30, 300, 253, 26)) 84 | self.shipping_state_box.setFont(font) 85 | self.shipping_state_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 86 | self.shipping_state_box.addItem("State") 87 | self.shipping_country_box = QtWidgets.QComboBox(self.shipping_card) 88 | self.shipping_country_box.setGeometry(QtCore.QRect(30, 360, 253, 26)) 89 | self.shipping_country_box.setFont(font) 90 | self.shipping_country_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 91 | self.shipping_country_box.addItem("Country") 92 | self.shipping_country_box.addItem("United States") 93 | self.profiles_header = QtWidgets.QLabel(self.profilespage) 94 | self.profiles_header.setGeometry(QtCore.QRect(30, 10, 81, 31)) 95 | font.setPointSize(22) if platform.system() == "Darwin" else font.setPointSize(22*.75) 96 | font.setBold(False) 97 | font.setWeight(50) 98 | self.profiles_header.setFont(font) 99 | self.profiles_header.setStyleSheet("color: rgb(234, 239, 239);") 100 | self.profiles_header.setText("Profiles") 101 | self.billing_card = QtWidgets.QWidget(self.profilespage) 102 | self.billing_card.setGeometry(QtCore.QRect(365, 70, 313, 501)) 103 | self.billing_card.setStyleSheet("background-color: #232323;border-radius: 20px;border: 1px solid #2e2d2d;") 104 | self.billing_fname_edit = QtWidgets.QLineEdit(self.billing_card) 105 | self.billing_fname_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 106 | self.billing_fname_edit.setGeometry(QtCore.QRect(30, 50, 113, 21)) 107 | font = QtGui.QFont() 108 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 109 | font.setFamily("Arial") 110 | self.billing_fname_edit.setFont(font) 111 | self.billing_fname_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 112 | self.billing_fname_edit.setPlaceholderText("First Name") 113 | self.billing_header = QtWidgets.QLabel(self.billing_card) 114 | self.billing_header.setGeometry(QtCore.QRect(20, 10, 51, 31)) 115 | font.setPointSize(18) if platform.system() == "Darwin" else font.setPointSize(18*.75) 116 | font.setBold(False) 117 | font.setWeight(50) 118 | self.billing_header.setFont(font) 119 | self.billing_header.setStyleSheet("color: rgb(212, 214, 214);border: none;") 120 | self.billing_header.setText("Billing") 121 | font = QtGui.QFont() 122 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 123 | font.setFamily("Arial") 124 | self.billing_lname_edit = QtWidgets.QLineEdit(self.billing_card) 125 | self.billing_lname_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 126 | self.billing_lname_edit.setGeometry(QtCore.QRect(170, 50, 113, 21)) 127 | self.billing_lname_edit.setFont(font) 128 | self.billing_lname_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 129 | self.billing_lname_edit.setPlaceholderText("Last Name") 130 | self.billing_email_edit = QtWidgets.QLineEdit(self.billing_card) 131 | self.billing_email_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 132 | self.billing_email_edit.setGeometry(QtCore.QRect(30, 100, 253, 21)) 133 | self.billing_email_edit.setFont(font) 134 | self.billing_email_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 135 | self.billing_email_edit.setPlaceholderText("Email Address") 136 | self.billing_phone_edit = QtWidgets.QLineEdit(self.billing_card) 137 | self.billing_phone_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 138 | self.billing_phone_edit.setGeometry(QtCore.QRect(30, 150, 253, 21)) 139 | self.billing_phone_edit.setFont(font) 140 | self.billing_phone_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 141 | self.billing_phone_edit.setPlaceholderText("Phone Number") 142 | self.billing_address1_edit = QtWidgets.QLineEdit(self.billing_card) 143 | self.billing_address1_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 144 | self.billing_address1_edit.setGeometry(QtCore.QRect(30, 200, 151, 21)) 145 | self.billing_address1_edit.setFont(font) 146 | self.billing_address1_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 147 | self.billing_address1_edit.setPlaceholderText("Address 1") 148 | self.billing_address2_edit = QtWidgets.QLineEdit(self.billing_card) 149 | self.billing_address2_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 150 | self.billing_address2_edit.setGeometry(QtCore.QRect(208, 200, 75, 21)) 151 | self.billing_address2_edit.setFont(font) 152 | self.billing_address2_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 153 | self.billing_address2_edit.setPlaceholderText("Address 2") 154 | self.billing_city_edit = QtWidgets.QLineEdit(self.billing_card) 155 | self.billing_city_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 156 | self.billing_city_edit.setGeometry(QtCore.QRect(30, 250, 151, 21)) 157 | self.billing_city_edit.setFont(font) 158 | self.billing_city_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 159 | self.billing_city_edit.setPlaceholderText("City") 160 | self.billing_zipcode_edit = QtWidgets.QLineEdit(self.billing_card) 161 | self.billing_zipcode_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 162 | self.billing_zipcode_edit.setGeometry(QtCore.QRect(208, 250, 75, 21)) 163 | self.billing_zipcode_edit.setFont(font) 164 | self.billing_zipcode_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 165 | self.billing_zipcode_edit.setPlaceholderText("Zip Code") 166 | self.billing_state_box = QtWidgets.QComboBox(self.billing_card) 167 | self.billing_state_box.setGeometry(QtCore.QRect(30, 300, 253, 26)) 168 | self.billing_state_box.setFont(font) 169 | self.billing_state_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 170 | self.billing_state_box.addItem("State") 171 | self.billing_country_box = QtWidgets.QComboBox(self.billing_card) 172 | self.billing_country_box.setGeometry(QtCore.QRect(30, 360, 253, 26)) 173 | self.billing_country_box.setFont(font) 174 | self.billing_country_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 175 | self.billing_country_box.addItem("Country") 176 | self.billing_country_box.addItem("United States") 177 | self.same_shipping_checkbox = QtWidgets.QCheckBox(self.billing_card) 178 | self.same_shipping_checkbox.setGeometry(QtCore.QRect(160, 16, 131, 20)) 179 | self.same_shipping_checkbox.setFont(font) 180 | self.same_shipping_checkbox.setStyleSheet("border:none;color: rgb(234, 239, 239);") 181 | self.same_shipping_checkbox.setText("Same as shipping") 182 | self.same_shipping_checkbox.stateChanged.connect(self.same_shipping_checkbox_clicked) 183 | self.tasks_card_3 = QtWidgets.QWidget(self.profilespage) 184 | self.tasks_card_3.setGeometry(QtCore.QRect(700, 70, 313, 501)) 185 | self.tasks_card_3.setStyleSheet("background-color: #232323;border-radius: 20px;border: 1px solid #2e2d2d;") 186 | self.payment_header = QtWidgets.QLabel(self.tasks_card_3) 187 | self.payment_header.setGeometry(QtCore.QRect(20, 10, 81, 31)) 188 | font.setPointSize(18) if platform.system() == "Darwin" else font.setPointSize(18*.75) 189 | font.setBold(False) 190 | font.setWeight(50) 191 | self.payment_header.setFont(font) 192 | self.payment_header.setStyleSheet("color: rgb(212, 214, 214);border: none;") 193 | self.payment_header.setText("Payment") 194 | self.cardnumber_edit = QtWidgets.QLineEdit(self.tasks_card_3) 195 | self.cardnumber_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 196 | self.cardnumber_edit.setGeometry(QtCore.QRect(30, 100, 151, 21)) 197 | font = QtGui.QFont() 198 | font.setFamily("Arial") 199 | self.cardnumber_edit.setFont(font) 200 | self.cardnumber_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 201 | self.cardnumber_edit.setPlaceholderText("Card Number") 202 | self.cardcvv_edit = QtWidgets.QLineEdit(self.tasks_card_3) 203 | self.cardcvv_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 204 | self.cardcvv_edit.setGeometry(QtCore.QRect(208, 100, 75, 21)) 205 | self.cardcvv_edit.setFont(font) 206 | self.cardcvv_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 207 | self.cardcvv_edit.setPlaceholderText("CVV") 208 | self.save_btn = QtWidgets.QPushButton(self.tasks_card_3) 209 | self.save_btn.setGeometry(QtCore.QRect(70, 300, 86, 32)) 210 | self.save_btn.setFont(font) 211 | self.save_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 212 | self.save_btn.setStyleSheet("color: #FFFFFF;background-color: #5D43FB;border-radius: 10px;border: 1px solid #2e2d2d;") 213 | self.save_btn.setText("Save") 214 | self.save_btn.clicked.connect(self.save_profile) 215 | self.cardtype_box = QtWidgets.QComboBox(self.tasks_card_3) 216 | self.cardtype_box.setGeometry(QtCore.QRect(30, 50, 253, 26)) 217 | self.cardtype_box.setFont(font) 218 | self.cardtype_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 219 | self.cardtype_box.addItem("Card Type") 220 | self.cardmonth_box = QtWidgets.QComboBox(self.tasks_card_3) 221 | self.cardmonth_box.setGeometry(QtCore.QRect(30, 150, 113, 26)) 222 | self.cardmonth_box.setFont(font) 223 | self.cardmonth_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 224 | self.cardmonth_box.addItem("Month") 225 | self.cardyear_box = QtWidgets.QComboBox(self.tasks_card_3) 226 | self.cardyear_box.setGeometry(QtCore.QRect(170, 150, 113, 26)) 227 | self.cardyear_box.setFont(font) 228 | self.cardyear_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 229 | self.cardyear_box.addItem("Year") 230 | self.profile_header = QtWidgets.QLabel(self.tasks_card_3) 231 | self.profile_header.setGeometry(QtCore.QRect(20, 220, 81, 31)) 232 | font.setPointSize(18) if platform.system() == "Darwin" else font.setPointSize(18*.75) 233 | font.setBold(False) 234 | font.setWeight(50) 235 | self.profile_header.setFont(font) 236 | self.profile_header.setStyleSheet("color: rgb(212, 214, 214);border: none;") 237 | self.profile_header.setText("Profile") 238 | self.profilename_edit = QtWidgets.QLineEdit(self.tasks_card_3) 239 | self.profilename_edit.setAttribute(QtCore.Qt.WA_MacShowFocusRect, 0) 240 | self.profilename_edit.setGeometry(QtCore.QRect(30, 260, 253, 21)) 241 | font = QtGui.QFont() 242 | font.setPointSize(13) if platform.system() == "Darwin" else font.setPointSize(13*.75) 243 | font.setFamily("Arial") 244 | self.profilename_edit.setFont(font) 245 | self.profilename_edit.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 246 | self.profilename_edit.setPlaceholderText("Profile Name") 247 | self.loadprofile_box = QtWidgets.QComboBox(self.tasks_card_3) 248 | self.loadprofile_box.setGeometry(QtCore.QRect(30, 350, 253, 26)) 249 | self.loadprofile_box.setFont(font) 250 | self.loadprofile_box.setStyleSheet("outline: 0;border: 1px solid #5D43FB;border-width: 0 0 2px;color: rgb(234, 239, 239);") 251 | self.loadprofile_box.addItem("Load Profile") 252 | self.loadprofile_box.currentTextChanged.connect(self.load_profile) 253 | self.delete_btn = QtWidgets.QPushButton(self.tasks_card_3) 254 | self.delete_btn.setGeometry(QtCore.QRect(167, 300, 86, 32)) 255 | self.delete_btn.setFont(font) 256 | self.delete_btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) 257 | self.delete_btn.setStyleSheet("color: #FFFFFF;background-color: #5D43FB;border-radius: 10px;border: 1px solid #2e2d2d;") 258 | self.delete_btn.setText("Delete") 259 | self.delete_btn.clicked.connect(self.delete_profile) 260 | self.set_data() 261 | QtCore.QMetaObject.connectSlotsByName(profilespage) 262 | 263 | def set_data(self): 264 | for state in ["AL", "AK", "AS", "AZ", "AR", "CA", "CO", "CT", "DE", "DC", "FM", "FL", "GA", "GU", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MH", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ", "NM", "NY", "NC", "ND", "MP", "OH", "OK", "OR", "PW", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "VT", "VI", "VA", "WA", "WV", "WI", "WY"]: 265 | self.shipping_state_box.addItem(state) 266 | self.billing_state_box.addItem(state) 267 | for month in range(1,13): 268 | self.cardmonth_box.addItem(str(month)) if month>9 else self.cardmonth_box.addItem("0"+str(month)) 269 | for year in range(2020,2031): 270 | self.cardyear_box.addItem(str(year)) 271 | for card_type in ["Visa", "Mastercard", "American Express", "Discover"]: 272 | self.cardtype_box.addItem(card_type) 273 | profiles = return_data("./data/profiles.json") 274 | for profile in profiles: 275 | profile_name = profile["profile_name"] 276 | self.loadprofile_box.addItem(profile_name) 277 | self.parent().parent().createdialog.profile_box.addItem(profile_name) 278 | 279 | def same_shipping_checkbox_clicked(self): 280 | if self.same_shipping_checkbox.isChecked(): 281 | self.billing_country_box.setCurrentIndex(self.billing_country_box.findText(self.shipping_country_box.currentText())) 282 | self.billing_fname_edit.setText(self.shipping_fname_edit.text()) 283 | self.billing_lname_edit.setText(self.shipping_lname_edit.text()) 284 | self.billing_email_edit.setText(self.shipping_email_edit.text()) 285 | self.billing_phone_edit.setText(self.shipping_phone_edit.text()) 286 | self.billing_address1_edit.setText(self.shipping_address1_edit.text()) 287 | self.billing_address2_edit.setText(self.shipping_address2_edit.text()) 288 | self.billing_city_edit.setText(self.shipping_city_edit.text()) 289 | self.billing_zipcode_edit.setText(self.shipping_zipcode_edit.text()) 290 | self.billing_state_box.setCurrentIndex(self.billing_state_box.findText(self.shipping_state_box.currentText())) 291 | 292 | def load_profile(self): 293 | profile_name = self.loadprofile_box.currentText() 294 | p = get_profile(profile_name) 295 | if p is not None: 296 | self.profilename_edit.setText(p["profile_name"]) 297 | self.shipping_fname_edit.setText(p["shipping_fname"]) 298 | self.shipping_lname_edit.setText(p["shipping_lname"]) 299 | self.shipping_email_edit.setText(p["shipping_email"]) 300 | self.shipping_phone_edit.setText(p["shipping_phone"]) 301 | self.shipping_address1_edit.setText(p["shipping_a1"]) 302 | self.shipping_address2_edit.setText(p["shipping_a2"]) 303 | self.shipping_city_edit.setText(p["shipping_city"]) 304 | self.shipping_zipcode_edit.setText(p["shipping_zipcode"]) 305 | self.shipping_state_box.setCurrentIndex(self.shipping_state_box.findText(p["shipping_state"])) 306 | self.shipping_country_box.setCurrentIndex(self.shipping_country_box.findText(p["shipping_country"])) 307 | self.billing_fname_edit.setText(p["billing_fname"]) 308 | self.billing_lname_edit.setText(p["billing_lname"]) 309 | self.billing_email_edit.setText(p["billing_email"]) 310 | self.billing_phone_edit.setText(p["billing_phone"]) 311 | self.billing_address1_edit.setText(p["billing_a1"]) 312 | self.billing_address2_edit.setText(p["billing_a2"]) 313 | self.billing_city_edit.setText(p["billing_city"]) 314 | self.billing_zipcode_edit.setText(p["billing_zipcode"]) 315 | self.billing_state_box.setCurrentIndex(self.billing_state_box.findText(p["billing_state"])) 316 | self.billing_country_box.setCurrentIndex(self.billing_country_box.findText(p["billing_country"])) 317 | self.cardnumber_edit.setText(p["card_number"]) 318 | self.cardmonth_box.setCurrentIndex(self.cardmonth_box.findText(p["card_month"])) 319 | self.cardyear_box.setCurrentIndex(self.cardyear_box.findText(p["card_year"])) 320 | self.cardtype_box.setCurrentIndex(self.cardtype_box.findText(p["card_type"])) 321 | self.cardcvv_edit.setText(p["card_cvv"]) 322 | return 323 | def save_profile(self): 324 | profile_name = self.profilename_edit.text() 325 | profile_data={ 326 | "profile_name":profile_name, 327 | "shipping_fname": self.shipping_fname_edit.text(), 328 | "shipping_lname": self.shipping_lname_edit.text(), 329 | "shipping_email": self.shipping_email_edit.text(), 330 | "shipping_phone": self.shipping_phone_edit.text(), 331 | "shipping_a1": self.shipping_address1_edit.text(), 332 | "shipping_a2": self.shipping_address2_edit.text(), 333 | "shipping_city": self.shipping_city_edit.text(), 334 | "shipping_zipcode": self.shipping_zipcode_edit.text(), 335 | "shipping_state": self.shipping_state_box.currentText(), 336 | "shipping_country": self.shipping_country_box.currentText(), 337 | "billing_fname": self.billing_fname_edit.text(), 338 | "billing_lname": self.billing_lname_edit.text(), 339 | "billing_email": self.billing_email_edit.text(), 340 | "billing_phone": self.billing_phone_edit.text(), 341 | "billing_a1": self.billing_address1_edit.text(), 342 | "billing_a2": self.billing_address2_edit.text(), 343 | "billing_city": self.billing_city_edit.text(), 344 | "billing_zipcode": self.billing_zipcode_edit.text(), 345 | "billing_state": self.billing_state_box.currentText(), 346 | "billing_country": self.billing_country_box.currentText(), 347 | "card_number": (Encryption().encrypt(self.cardnumber_edit.text())).decode("utf-8"), 348 | "card_month": self.cardmonth_box.currentText(), 349 | "card_year": self.cardyear_box.currentText(), 350 | "card_type": self.cardtype_box.currentText(), 351 | "card_cvv": self.cardcvv_edit.text() 352 | } 353 | profiles = return_data("./data/profiles.json") 354 | for p in profiles: 355 | if p["profile_name"] == profile_name: 356 | profiles.remove(p) 357 | break 358 | profiles.append(profile_data) 359 | write_data("./data/profiles.json",profiles) 360 | if self.loadprofile_box.findText(profile_name) == -1: 361 | self.loadprofile_box.addItem(profile_name) 362 | self.parent().parent().createdialog.profile_box.addItem(profile_name) 363 | QtWidgets.QMessageBox.information(self, "Bird Bot", "Saved Profile") 364 | 365 | def delete_profile(self): 366 | profile_name = self.profilename_edit.text() 367 | profiles = return_data("./data/profiles.json") 368 | for profile in profiles: 369 | if profile["profile_name"] == profile_name: 370 | profiles.remove(profile) 371 | break 372 | write_data("./data/profiles.json",profiles) 373 | self.loadprofile_box.removeItem(self.loadprofile_box.findText(profile_name)) 374 | self.parent().parent().createdialog.profile_box.removeItem(self.parent().parent().createdialog.profile_box.findText(profile_name)) 375 | 376 | self.loadprofile_box.setCurrentIndex(0) 377 | self.profilename_edit.setText("") 378 | self.profilename_edit.setText("") 379 | self.shipping_fname_edit.setText("") 380 | self.shipping_lname_edit.setText("") 381 | self.shipping_email_edit.setText("") 382 | self.shipping_phone_edit.setText("") 383 | self.shipping_address1_edit.setText("") 384 | self.shipping_address2_edit.setText("") 385 | self.shipping_city_edit.setText("") 386 | self.shipping_zipcode_edit.setText("") 387 | self.shipping_state_box.setCurrentIndex(0) 388 | self.shipping_country_box.setCurrentIndex(0) 389 | self.billing_fname_edit.setText("") 390 | self.billing_lname_edit.setText("") 391 | self.billing_email_edit.setText("") 392 | self.billing_phone_edit.setText("") 393 | self.billing_address1_edit.setText("") 394 | self.billing_address2_edit.setText("") 395 | self.billing_city_edit.setText("") 396 | self.billing_zipcode_edit.setText("") 397 | self.billing_state_box.setCurrentIndex(0) 398 | self.billing_country_box.setCurrentIndex(0) 399 | self.cardnumber_edit.setText("") 400 | self.cardmonth_box.setCurrentIndex(0) 401 | self.cardyear_box.setCurrentIndex(0) 402 | self.cardtype_box.setCurrentIndex(0) 403 | self.cardcvv_edit.setText("") 404 | QtWidgets.QMessageBox.information(self, "Bird Bot", "Deleted Profile") 405 | -------------------------------------------------------------------------------- /sites/bestbuy.py: -------------------------------------------------------------------------------- 1 | try: 2 | from Crypto.PublicKey import RSA 3 | from Crypto.Cipher import PKCS1_OAEP 4 | except: 5 | from Cryptodome.PublicKey import RSA 6 | from Cryptodome.Cipher import PKCS1_OAEP 7 | from base64 import b64encode 8 | from utils import send_webhook 9 | import requests,time,lxml.html,json,sys,settings 10 | 11 | class BestBuy: 12 | def __init__(self,task_id,status_signal,image_signal,product,profile,proxy,monitor_delay,error_delay): 13 | self.status_signal,self.image_signal,self.product,self.profile,self.monitor_delay,self.error_delay = status_signal,image_signal,product,profile,float(monitor_delay),float(error_delay) 14 | self.session = requests.Session() 15 | if proxy != False: 16 | self.session.proxies.update(proxy) 17 | self.status_signal.emit({"msg":"Starting","status":"normal"}) 18 | tas_data = self.get_tas_data() 19 | product_image = self.monitor() 20 | self.atc() 21 | self.start_checkout() 22 | self.submit_shipping() 23 | self.submit_payment(tas_data) 24 | while True: 25 | success,jwt = self.submit_order() 26 | if not success and jwt != None: 27 | transaction_id = self.handle_3dsecure(jwt) 28 | self.submit_card(transaction_id) 29 | else: 30 | if success: 31 | send_webhook("OP","Bestbuy",self.profile["profile_name"],task_id,product_image) 32 | else: 33 | if settings.browser_on_failed: 34 | self.status_signal.emit({"msg":"Browser Ready","status":"alt","url":"https://www.bestbuy.com/checkout/r/fulfillment","cookies":[{"name":cookie.name,"value":cookie.value,"domain":cookie.domain} for cookie in self.session.cookies]}) 35 | send_webhook("B","Bestbuy",self.profile["profile_name"],task_id,product_image) 36 | else: 37 | send_webhook("PF","Bestbuy",self.profile["profile_name"],task_id,product_image) 38 | break 39 | 40 | def get_tas_data(self): 41 | headers={ 42 | "accept": "*/*", 43 | "accept-encoding": "gzip, deflate, br", 44 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 45 | "content-type": "application/json", 46 | "referer": "https://www.bestbuy.com/checkout/r/payment", 47 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" 48 | } 49 | while True: 50 | try: 51 | self.status_signal.emit({"msg":"Getting TAS Data","status":"normal"}) 52 | r = requests.get("https://www.bestbuy.com/api/csiservice/v2/key/tas",headers=headers) 53 | self.status_signal.emit({"msg":"Got TAS Data","status":"normal"}) 54 | return json.loads(r.text) 55 | except Exception as e: 56 | self.status_signal.emit({"msg":"Error Getting TAS Data(line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 57 | time.sleep(self.error_delay) 58 | def monitor(self): 59 | headers = { 60 | "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 61 | "accept-encoding": "gzip, deflate, br", 62 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 63 | "cache-control": "max-age=0", 64 | "upgrade-insecure-requests": "1", 65 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.69 Safari/537.36" 66 | } 67 | image_found = False 68 | product_image = "" 69 | while True: 70 | self.status_signal.emit({"msg":"Loading Product Page","status":"normal"}) 71 | try: 72 | r = self.session.get(self.product,headers=headers) 73 | if r.status_code == 200: 74 | doc = lxml.html.fromstring(r.text) 75 | if not image_found: 76 | self.sku_id = doc.xpath('//span[@class="product-data-value body-copy"]/text()')[1].strip() 77 | product_image = doc.xpath('//img[@class="primary-image"]/@src')[0] 78 | self.image_signal.emit(product_image) 79 | image_found = True 80 | if self.check_stock(): 81 | return product_image 82 | self.status_signal.emit({"msg":"Waiting For Restock","status":"normal"}) 83 | time.sleep(self.monitor_delay) 84 | else: 85 | self.status_signal.emit({"msg":"Product Not Found","status":"normal"}) 86 | time.sleep(self.monitor_delay) 87 | except Exception as e: 88 | self.status_signal.emit({"msg":"Error Loading Product Page (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 89 | time.sleep(self.error_delay) 90 | 91 | def check_stock(self): 92 | headers = { 93 | "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 94 | "accept-encoding": "gzip, deflate, br", 95 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 96 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" 97 | } 98 | while True: 99 | self.status_signal.emit({"msg":"Checking Stock","status":"normal"}) 100 | try: 101 | url = "https://www.bestbuy.com/api/tcfb/model.json?paths=%5B%5B%22shop%22%2C%22scds%22%2C%22v2%22%2C%22page%22%2C%22tenants%22%2C%22bbypres%22%2C%22pages%22%2C%22globalnavigationv5sv%22%2C%22header%22%5D%2C%5B%22shop%22%2C%22buttonstate%22%2C%22v5%22%2C%22item%22%2C%22skus%22%2C{}%2C%22conditions%22%2C%22NONE%22%2C%22destinationZipCode%22%2C%22%2520%22%2C%22storeId%22%2C%22%2520%22%2C%22context%22%2C%22cyp%22%2C%22addAll%22%2C%22false%22%5D%5D&method=get".format(self.sku_id) 102 | r = self.session.get(url,headers=headers) 103 | return "ADD_TO_CART" in r.text 104 | except Exception as e: 105 | self.status_signal.emit({"msg":"Error Checking Stock (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 106 | time.sleep(self.error_delay) 107 | 108 | def atc(self): 109 | headers={ 110 | "accept": "application/json", 111 | "accept-encoding": "gzip, deflate, br", 112 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 113 | "content-length": "31", 114 | "content-type": "application/json; charset=UTF-8", 115 | "origin": "https://www.bestbuy.com", 116 | "referer": self.product, 117 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" 118 | } 119 | body = {"items":[{"skuId":self.sku_id}]} 120 | while True: 121 | self.status_signal.emit({"msg":"Adding To Cart","status":"normal"}) 122 | try: 123 | r = self.session.post("https://www.bestbuy.com/cart/api/v1/addToCart",json=body,headers=headers) 124 | if r.status_code == 200 and json.loads(r.text)["cartCount"] == 1: 125 | self.status_signal.emit({"msg":"Added To Cart","status":"carted"}) 126 | return 127 | else: 128 | self.status_signal.emit({"msg":"Error Adding To Cart","status":"error"}) 129 | time.sleep(self.error_delay) 130 | except Exception as e: 131 | self.status_signal.emit({"msg":"Error Adding To Cart (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 132 | time.sleep(self.error_delay) 133 | 134 | def start_checkout(self): 135 | headers = { 136 | "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 137 | "accept-encoding": "gzip, deflate, br", 138 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 139 | "upgrade-insecure-requests": "1", 140 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36", 141 | } 142 | while True: 143 | self.status_signal.emit({"msg":"Starting Checkout","status":"normal"}) 144 | try: 145 | r = self.session.get("https://www.bestbuy.com/checkout/r/fufillment",headers=headers) 146 | if r.status_code == 200: 147 | r = json.loads(r.text.split("var orderData = ")[1].split(";")[0]) 148 | self.order_id = r["id"] 149 | self.item_id = r["items"][0]["id"] 150 | self.status_signal.emit({"msg":"Started Checkout","status":"normal"}) 151 | return 152 | self.status_signal.emit({"msg":"Error Starting Checkout","status":"error"}) 153 | time.sleep(self.error_delay) 154 | except Exception as e: 155 | self.status_signal.emit({"msg":"Error Starting Checkout (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 156 | time.sleep(self.error_delay) 157 | 158 | def submit_shipping(self): 159 | headers={ 160 | "accept": "application/com.bestbuy.order+json", 161 | "accept-encoding": "gzip, deflate, br", 162 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 163 | "content-type": "application/json", 164 | "origin": "https://www.bestbuy.com", 165 | "referer": "https://www.bestbuy.com/checkout/r/fulfillment", 166 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36", 167 | "x-user-interface": "DotCom-Optimized" 168 | } 169 | profile = self.profile 170 | body = {"items":[{"id":self.item_id,"type":"DEFAULT","selectedFulfillment":{"shipping":{"address":{ 171 | "country":"US", 172 | "saveToProfile":False, 173 | "street2":profile["shipping_a2"], 174 | "useAddressAsBilling":False, 175 | "middleInitial":"", 176 | "lastName":profile["shipping_lname"], 177 | "street":profile["shipping_a1"], 178 | "city":profile["shipping_city"], 179 | "override":False, 180 | "zipcode":profile["shipping_zipcode"], 181 | "state":profile["shipping_state"], 182 | "firstName":profile["shipping_fname"], 183 | "isWishListAddress":False, 184 | "dayPhoneNumber":profile["shipping_phone"],"type":"RESIDENTIAL"}}},"giftMessageSelected":False}], 185 | "phoneNumber":profile["shipping_phone"], 186 | "smsNotifyNumber":"", 187 | "smsOptIn":False, 188 | "emailAddress":profile["shipping_email"]} 189 | while True: 190 | self.status_signal.emit({"msg":"Submitting Shipping","status":"normal"}) 191 | try: 192 | r = self.session.patch("https://www.bestbuy.com/checkout/orders/{}/".format(self.order_id),json=body,headers=headers) 193 | if json.loads(r.text)["id"] == self.order_id: 194 | self.status_signal.emit({"msg":"Submitted Shipping","status":"normal"}) 195 | return 196 | self.status_signal.emit({"msg":"Error Submitting Shipping","status":"error"}) 197 | time.sleep(self.error_delay) 198 | except Exception as e: 199 | self.status_signal.emit({"msg":"Error Submitting Shipping (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 200 | time.sleep(self.error_delay) 201 | 202 | def submit_payment(self,tas_data): 203 | headers={ 204 | "accept": "application/com.bestbuy.order+json", 205 | "accept-encoding": "gzip, deflate, br", 206 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 207 | "content-type": "application/json", 208 | "origin": "https://www.bestbuy.com", 209 | "referer": "https://www.bestbuy.com/checkout/r/fulfillment", 210 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36", 211 | "x-user-interface": "DotCom-Optimized" 212 | } 213 | profile = self.profile 214 | card_number = profile["card_number"] 215 | key = RSA.importKey(tas_data["publicKey"]) 216 | cipher = PKCS1_OAEP.new(key) 217 | encrypted_card = b64encode(cipher.encrypt(("00926999"+card_number).encode("utf-8"))).decode("utf-8") 218 | zero_string = "" 219 | for i in range(len(card_number)-10): 220 | zero_string+="0" 221 | self.bin_number = card_number[:6] 222 | encrypted_card +=":3:"+tas_data["keyId"]+":"+self.bin_number+zero_string+card_number[-4:] 223 | body = {"billingAddress":{ 224 | "country":"US", 225 | "saveToProfile":False, 226 | "street2": profile["billing_a2"], 227 | "useAddressAsBilling": True, 228 | "middleInitial":"", 229 | "lastName": profile["billing_lname"], 230 | "street": profile["billing_a1"], 231 | "city": profile["billing_city"], 232 | "override":False, 233 | "zipcode": profile["billing_zipcode"], 234 | "state": profile["billing_state"], 235 | "dayPhoneNumber": profile["billing_phone"], 236 | "firstName": profile["billing_fname"], 237 | "isWishListAddress":False}, 238 | "creditCard":{ 239 | "hasCID":False, 240 | "invalidCard":False, 241 | "isCustomerCard":False, 242 | "isNewCard":True, 243 | "isVisaCheckout":False, 244 | "govPurchaseCard":False, 245 | "isInternationalCard":False, 246 | "number": encrypted_card, 247 | "binNumber": self.bin_number, 248 | "cardType": profile["card_type"].upper(), 249 | "cid": profile["card_cvv"], 250 | "expiration":{"month": profile["card_month"],"year": profile["card_year"]}, 251 | "isPWPRegistered":False}} 252 | while True: 253 | self.status_signal.emit({"msg":"Submitting Payment","status":"normal"}) 254 | try: 255 | r = self.session.patch("https://www.bestbuy.com/checkout/orders/{}/paymentMethods".format(self.order_id),json=body,headers=headers) 256 | r = json.loads(r.text) 257 | if r["id"] == self.order_id: 258 | self.status_signal.emit({"msg":"Submitted Payment","status":"normal"}) 259 | return 260 | self.status_signal.emit({"msg":"Error Submitting Payment","status":"error"}) 261 | time.sleep(self.error_delay) 262 | except Exception as e: 263 | self.status_signal.emit({"msg":"Error Submitting Payment (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 264 | time.sleep(self.error_delay) 265 | 266 | def submit_order(self): 267 | headers = { 268 | "accept": "application/com.bestbuy.order+json", 269 | "accept-encoding": "gzip, deflate, br", 270 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 271 | "content-type": "application/json", 272 | "origin": "https://www.bestbuy.com", 273 | "referer": "https://www.bestbuy.com/checkout/r/payment", 274 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36", 275 | "x-user-interface": "DotCom-Optimized" 276 | } 277 | body = {"browserInfo":{"javaEnabled":False,"language":"en-US","userAgent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36","height":"1057","width":"1057","timeZone":"240","colorDepth":"24"}} 278 | while True: 279 | self.status_signal.emit({"msg":"Submitting Order","status":"alt"}) 280 | try: 281 | r = self.session.post("https://www.bestbuy.com/checkout/orders/{}/".format(self.order_id),json=body,headers=headers) 282 | r = json.loads(r.text) 283 | try: 284 | r = r["errors"][0] 285 | if r["errorCode"] == "PAY_SECURE_REDIRECT": 286 | self.status_signal.emit({"msg":"3DSecure Found, Starting Auth Process","status":"error"}) 287 | return False, r["paySecureResponse"]["stepUpJwt"] 288 | except: 289 | if r["state"] == "SUBMITTED": 290 | self.status_signal.emit({"msg":"Order Placed","status":"success"}) 291 | return True, None 292 | self.status_signal.emit({"msg":"Payment Failed","status":"error"}) 293 | return False, None 294 | 295 | except Exception as e: 296 | self.status_signal.emit({"msg":"Error Submitting Order (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 297 | time.sleep(self.error_delay) 298 | 299 | def handle_3dsecure(self,jwt): 300 | headers = { 301 | "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 302 | "accept-encoding": "gzip, deflate, br", 303 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 304 | "cache-control": "max-age=0", 305 | "content-type": "application/x-www-form-urlencoded", 306 | "origin": "https://www.bestbuy.com", 307 | "referer": "https://www.bestbuy.com/", 308 | "upgrade-insecure-requests": "1", 309 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" 310 | } 311 | body = { 312 | "JWT": jwt, 313 | "TermUrl": "/payment/r/threeDSecure/redirect", 314 | "MD": "" 315 | } 316 | while True: 317 | self.status_signal.emit({"msg":"Authorizing Card (1)","status":"normal"}) 318 | try: 319 | r = self.session.post("https://centinelapi.cardinalcommerce.com/V2/Cruise/StepUp",data=body,headers=headers) 320 | doc = lxml.html.fromstring(r.text) 321 | pa_req = doc.xpath('//input[@id="payload"]/@value')[0] 322 | md = doc.xpath('//input[@id="mcsId"]/@value')[0] 323 | term_url = doc.xpath('//input[@id="termUrl"]/@value')[0] 324 | acs_url = doc.xpath('//input[@id="acsUrl"]/@value')[0] 325 | break 326 | except Exception as e: 327 | self.status_signal.emit({"msg":"Error Authorizing Card (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 328 | time.sleep(self.error_delay) 329 | headers = { 330 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 331 | "Accept-Encoding": "gzip, deflate, br", 332 | "Accept-Language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 333 | "Cache-Control": "max-age=0", 334 | "Connection": "keep-alive", 335 | "Content-Type": "application/x-www-form-urlencoded", 336 | "Host": "1eaf.cardinalcommerce.com", 337 | "Origin": "https://centinelapi.cardinalcommerce.com", 338 | "Referer": "https://centinelapi.cardinalcommerce.com/", 339 | "Upgrade-Insecure-Requests": "1", 340 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" 341 | } 342 | body = { 343 | "PaReq": pa_req, 344 | "MD": md, 345 | "TermUrl": term_url 346 | } 347 | while True: 348 | self.status_signal.emit({"msg":"Authorizing Card (2)","status":"normal"}) 349 | try: 350 | r = self.session.post(acs_url,data=body,headers=headers) 351 | doc = lxml.html.fromstring(r.text) 352 | pa_req = doc.xpath('//input[@name="PaReq"]/@value')[0] 353 | term_url = doc.xpath('//input[@name="TermUrl"]/@value')[0] 354 | md = doc.xpath('//input[@name="MD"]/@value')[0] 355 | url = doc.xpath("//form/@action")[0] 356 | break 357 | except Exception as e: 358 | self.status_signal.emit({"msg":"Error Authorizing Card (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 359 | time.sleep(self.error_delay) 360 | headers = { 361 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 362 | "Accept-Encoding": "gzip, deflate, br", 363 | "Accept-Language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 364 | "Cache-Control": "max-age=0", 365 | "Connection": "keep-alive", 366 | "Content-Type": "application/x-www-form-urlencoded", 367 | "Host": "secure4.arcot.com", 368 | "Origin": "https://1eaf.cardinalcommerce.com", 369 | "Referer": "https://1eaf.cardinalcommerce.com/", 370 | "Upgrade-Insecure-Requests": "1", 371 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" 372 | } 373 | body = { 374 | "PaReq": pa_req, 375 | "TermUrl": term_url, 376 | "MD": md 377 | } 378 | while True: 379 | self.status_signal.emit({"msg":"Authorizing Card (3)","status":"normal"}) 380 | try: 381 | r = self.session.post(url,data=body,headers=headers) 382 | doc = lxml.html.fromstring(r.text) 383 | pa_res = doc.xpath('//input[@name="PaRes"]/@value')[0] 384 | pa_req = doc.xpath('//input[@name="PaReq"]/@value')[0] 385 | md = doc.xpath('//input[@name="MD"]/@value')[0] 386 | device_id = doc.xpath('//input[@name="DeviceID"]/@value')[0] 387 | locale = doc.xpath('//input[@name="locale"]/@value')[0] 388 | ABSlog = doc.xpath('//input[@name="ABSlog"]/@value')[0] 389 | device_DNA = doc.xpath('//input[@name="deviceDNA"]/@value')[0] 390 | execution_time = doc.xpath('//input[@name="executionTime"]/@value')[0] 391 | dna_error = doc.xpath('//input[@name="dnaError"]/@value')[0] 392 | mesc = doc.xpath('//input[@name="mesc"]/@value')[0] 393 | mesc_iteration_count = doc.xpath('//input[@name="mescIterationCount"]/@value')[0] 394 | desc = doc.xpath('//input[@name="desc"]/@value')[0] 395 | is_DNA_done = doc.xpath('//input[@name="isDNADone"]/@value')[0] 396 | arcot_flash_cookie = doc.xpath('//input[@name="arcotFlashCookie"]/@value')[0] 397 | url = doc.xpath("//form/@action")[0] 398 | break 399 | except Exception as e: 400 | self.status_signal.emit({"msg":"Error Authorizing Card (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 401 | time.sleep(self.error_delay) 402 | 403 | headers = { 404 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 405 | "Accept-Encoding": "gzip, deflate, br", 406 | "Accept-Language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 407 | "Cache-Control": "max-age=0", 408 | "Connection": "keep-alive", 409 | "Content-Type": "application/x-www-form-urlencoded", 410 | "Host": "1eaf.cardinalcommerce.com", 411 | "Origin": "https://secure4.arcot.com", 412 | "Referer": "https://secure4.arcot.com/", 413 | "Upgrade-Insecure-Requests": "1", 414 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" 415 | } 416 | body = { 417 | "PaRes": pa_res, 418 | "PaReq": pa_req, 419 | "MD": md, 420 | "DeviceID": device_id, 421 | "locale": locale, 422 | "ABSlog": ABSlog, 423 | "deviceDNA": device_DNA, 424 | "executionTime": execution_time, 425 | "dnaError": dna_error, 426 | "mesc": mesc, 427 | "mescIterationCount": mesc_iteration_count, 428 | "desc": desc, 429 | "isDNADone": is_DNA_done 430 | } 431 | while True: 432 | self.status_signal.emit({"msg":"Authorizing Card (4)","status":"normal"}) 433 | try: 434 | r = self.session.post(url,data=body,headers=headers) 435 | doc = lxml.html.fromstring(r.text) 436 | pa_res = doc.xpath('//input[@name="PaRes"]/@value')[0] 437 | md = doc.xpath('//input[@name="MD"]/@value')[0] 438 | url = doc.xpath("//form/@action")[0] 439 | break 440 | except Exception as e: 441 | self.status_signal.emit({"msg":"Error Authorizing Card (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 442 | time.sleep(self.error_delay) 443 | headers = { 444 | "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 445 | "accept-encoding": "gzip, deflate, br", 446 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 447 | "cache-control": "max-age=0", 448 | "content-type": "application/x-www-form-urlencoded", 449 | "origin": "https://1eaf.cardinalcommerce.com", 450 | "referer": "https://1eaf.cardinalcommerce.com/", 451 | "upgrade-insecure-requests": "1", 452 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" 453 | } 454 | body = { 455 | "PaRes": pa_res, 456 | "MD": md 457 | } 458 | while True: 459 | self.status_signal.emit({"msg":"Authorizing Card (5)","status":"normal"}) 460 | try: 461 | r = self.session.post(url,data=body,headers=headers) 462 | jwt = r.text.split('parent.postMessage("')[1].split('"')[0] 463 | break 464 | except Exception as e: 465 | self.status_signal.emit({"msg":"Error Authorizing Card (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 466 | time.sleep(self.error_delay) 467 | headers = { 468 | "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", 469 | "accept-encoding": "gzip, deflate, br", 470 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 471 | "cache-control": "max-age=0", 472 | "content-type": "application/x-www-form-urlencoded", 473 | "origin": "https://centinelapi.cardinalcommerce.com", 474 | "referer": "https://centinelapi.cardinalcommerce.com/V2/Cruise/StepUp", 475 | "upgrade-insecure-requests": "1", 476 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" 477 | } 478 | body = { 479 | "McsId": md, 480 | "CardinalJWT": jwt, 481 | "Error": "" 482 | } 483 | while True: 484 | self.status_signal.emit({"msg":"Authorizing Card (6)","status":"normal"}) 485 | try: 486 | r = self.session.post("https://centinelapi.cardinalcommerce.com/V1/Cruise/TermRedirection",data=body,headers=headers) 487 | doc = lxml.html.fromstring(r.text) 488 | transaction_id = doc.xpath('//input[@name="TransactionId"]/@value')[0] 489 | # url = doc.xpath("//form/@action")[0] 490 | return transaction_id 491 | except Exception as e: 492 | self.status_signal.emit({"msg":"Error Authorizing Card (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 493 | time.sleep(self.error_delay) 494 | 495 | def submit_card(self,transaction_id): 496 | headers = { 497 | "accept": "application/json, text/javascript, */*; q=0.01", 498 | "accept-encoding": "gzip, deflate, br", 499 | "accept-language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7", 500 | "content-type": "application/json", 501 | "origin": "https://www.bestbuy.com", 502 | "referer": "https://www.bestbuy.com/checkout/r/payment", 503 | "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36", 504 | "x-user-interface": "DotCom-Optimized", 505 | "x-native-checkout-version": "__VERSION__" 506 | } 507 | body = {"PaRes":"","orderId":self.order_id,"TransactionId":transaction_id} 508 | while True: 509 | self.status_signal.emit({"msg":"Submitting Card","status":"normal"}) 510 | try: 511 | r = self.session.post("https://www.bestbuy.com/checkout/api/1.0/paysecure/submitCardAuthentication",json=body,headers=headers) 512 | if r.status_code == 200: 513 | return 514 | else: 515 | self.status_signal.emit({"msg":"Error Submitting Card","status":"error"}) 516 | time.sleep(self.error_delay) 517 | except Exception as e: 518 | self.status_signal.emit({"msg":"Error Submitting Card (line {} {} {})".format(sys.exc_info()[-1].tb_lineno, type(e).__name__, e),"status":"error"}) 519 | time.sleep(self.error_delay) 520 | 521 | 522 | 523 | -------------------------------------------------------------------------------- /sites/walmart_encryption.py: -------------------------------------------------------------------------------- 1 | __all__ = ['walmart_encryption'] 2 | 3 | # Don't look below, you will not understand this Python code :) I don't. 4 | 5 | from js2py.pyjs import * 6 | # setting scope 7 | var = Scope( JS_BUILTINS ) 8 | set_global_object(var) 9 | 10 | # Code follows: 11 | var.registers(['n', 'r', 'a', 'i', 'encrypt', 'o']) 12 | @Js 13 | def PyJsHoisted_encrypt_(e, t, PIE_L, PIE_E, PIE_K, PIE_key_id, PIE_phase, this, arguments, var=var): 14 | var = Scope({'e':e, 't':t, 'PIE_L':PIE_L, 'PIE_E':PIE_E, 'PIE_K':PIE_K, 'PIE_key_id':PIE_key_id, 'PIE_phase':PIE_phase, 'this':this, 'arguments':arguments}, var) 15 | var.registers(['PIE_L', 'PIE_K', 'l_var', 'PIE_key_id', 'p_var', 'i_var', 'PIE_E', 'u_var', 'PIE_phase', 'e', 'f_var', 'd_var', 'a_var', 't', 's_var', 'c_var']) 16 | var.put('PIE', Js({'L':var.get('parseInt')(var.get('PIE_L')),'E':var.get('parseInt')(var.get('PIE_E')),'K':var.get('PIE_K'),'key_id':var.get('PIE_key_id'),'phase':var.get('parseInt')(var.get('PIE_phase'))})) 17 | var.put('a_var', var.get('n').callprop('distill', var.get('e'))) 18 | var.put('i_var', var.get('n').callprop('distill', var.get('t'))) 19 | var.put('c_var', (var.get('a_var').callprop('substr', Js(0.0), var.get('PIE').get('L'))+var.get('a_var').callprop('substring', (var.get('a_var').get('length')-var.get('PIE').get('E'))))) 20 | var.put('u_var', var.get('n').callprop('luhn', var.get('a_var'))) 21 | var.put('s_var', var.get('a_var').callprop('substring', (var.get('PIE').get('L')+Js(1.0)), (var.get('a_var').get('length')-var.get('PIE').get('E')))) 22 | var.put('d_var', var.get('o').callprop('encrypt', (var.get('s_var')+var.get('i_var')), var.get('c_var'), var.get('PIE').get('K'), Js(10.0))) 23 | var.put('l_var', (((var.get('a_var').callprop('substr', Js(0.0), var.get('PIE').get('L'))+Js('0'))+var.get('d_var').callprop('substr', Js(0.0), (var.get('d_var').get('length')-var.get('i_var').get('length'))))+var.get('a_var').callprop('substring', (var.get('a_var').get('length')-var.get('PIE').get('E'))))) 24 | var.put('f_var', var.get('n').callprop('reformat', var.get('n').callprop('fixluhn', var.get('l_var'), var.get('PIE').get('L'), var.get('u_var')), var.get('e'))) 25 | var.put('p_var', var.get('n').callprop('reformat', var.get('d_var').callprop('substring', (var.get('d_var').get('length')-var.get('i_var').get('length'))), var.get('t'))) 26 | return Js([var.get('f_var'), var.get('p_var'), var.get('n').callprop('integrity', var.get('PIE').get('K'), var.get('f_var'), var.get('p_var'))]) 27 | PyJsHoisted_encrypt_.func_name = 'encrypt' 28 | var.put('encrypt', PyJsHoisted_encrypt_) 29 | var.put('n', Js({})) 30 | def PyJs_LONG_6_(var=var): 31 | @Js 32 | def PyJs_anonymous_0_(e, this, arguments, var=var): 33 | var = Scope({'e':e, 'this':this, 'arguments':arguments}, var) 34 | var.registers(['t', 'n', 'e', 'r']) 35 | #for JS loop 36 | var.put('t', (var.get('e').get('length')-Js(1.0))) 37 | var.put('n', Js(0.0)) 38 | while (var.get('t')>=Js(0.0)): 39 | PyJsComma(var.put('n', var.get('parseInt')(var.get('e').callprop('substr', var.get('t'), Js(1.0)), Js(10.0)), '+'),var.put('t', Js(2.0), '-')) 40 | 41 | #for JS loop 42 | var.put('t', (var.get('e').get('length')-Js(2.0))) 43 | while (var.get('t')>=Js(0.0)): 44 | var.put('r', (Js(2.0)*var.get('parseInt')(var.get('e').callprop('substr', var.get('t'), Js(1.0)), Js(10.0)))) 45 | PyJsComma(var.put('n', (var.get('r') if (var.get('r')=Js(0.0)) and var.put('t', var.get('e').callprop('substr', var.get('r'), Js(1.0)), '+')) 68 | finally: 69 | var.put('r',Js(var.get('r').to_number())+Js(1)) 70 | return var.get('t') 71 | PyJs_anonymous_3_._set_name('anonymous') 72 | @Js 73 | def PyJs_anonymous_4_(e, t, this, arguments, var=var): 74 | var = Scope({'e':e, 't':t, 'this':this, 'arguments':arguments}, var) 75 | var.registers(['r', 'a', 'i', 'e', 't']) 76 | #for JS loop 77 | var.put('r', Js('')) 78 | var.put('a', Js(0.0)) 79 | var.put('i', Js(0.0)) 80 | while (var.get('i')=Js(0.0))) else var.put('r', var.get('t').callprop('substr', var.get('i'), Js(1.0)), '+')) 83 | finally: 84 | var.put('i',Js(var.get('i').to_number())+Js(1)) 85 | return var.get('r') 86 | PyJs_anonymous_4_._set_name('anonymous') 87 | @Js 88 | def PyJs_anonymous_5_(e, t, n, this, arguments, var=var): 89 | var = Scope({'e':e, 't':t, 'n':n, 'this':this, 'arguments':arguments}, var) 90 | var.registers(['n', 'c', 'u', 'e', 's', 't', 'o']) 91 | var.put('o', (((((var.get('String').callprop('fromCharCode', Js(0.0))+var.get('String').callprop('fromCharCode', var.get('t').get('length')))+var.get('t'))+var.get('String').callprop('fromCharCode', Js(0.0)))+var.get('String').callprop('fromCharCode', var.get('n').get('length')))+var.get('n'))) 92 | var.put('c', var.get('a').callprop('HexToWords', var.get('e'))) 93 | var.get('c').put('3', Js(1.0), '^') 94 | var.put('u', var.get('r').get('cipher').get('aes').create(var.get('c'))) 95 | var.put('s', var.get('i').callprop('compute', var.get('u'), var.get('o'))) 96 | return (var.get('a').callprop('WordToHex', var.get('s').get('0'))+var.get('a').callprop('WordToHex', var.get('s').get('1'))) 97 | PyJs_anonymous_5_._set_name('anonymous') 98 | return PyJsComma(PyJsComma(PyJsComma(PyJsComma(PyJsComma(PyJsComma(var.get('n').put('base10', Js('0123456789')),var.get('n').put('base62', Js('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'))),var.get('n').put('luhn', PyJs_anonymous_0_)),var.get('n').put('fixluhn', PyJs_anonymous_1_)),var.get('n').put('distill', PyJs_anonymous_3_)),var.get('n').put('reformat', PyJs_anonymous_4_)),var.get('n').put('integrity', PyJs_anonymous_5_)) 99 | PyJs_LONG_6_() 100 | @Js 101 | def PyJs_anonymous_7_(e, this, arguments, var=var): 102 | var = Scope({'e':e, 'this':this, 'arguments':arguments}, var) 103 | var.registers(['e']) 104 | @Js 105 | def PyJs_anonymous_8_(this, arguments, var=var): 106 | var = Scope({'this':this, 'arguments':arguments}, var) 107 | var.registers([]) 108 | return (Js('CORRUPT: ')+var.get(u"this").get('message')) 109 | PyJs_anonymous_8_._set_name('anonymous') 110 | PyJsComma(var.get(u"this").put('toString', PyJs_anonymous_8_),var.get(u"this").put('message', var.get('e'))) 111 | PyJs_anonymous_7_._set_name('anonymous') 112 | @Js 113 | def PyJs_anonymous_9_(e, this, arguments, var=var): 114 | var = Scope({'e':e, 'this':this, 'arguments':arguments}, var) 115 | var.registers(['e']) 116 | @Js 117 | def PyJs_anonymous_10_(this, arguments, var=var): 118 | var = Scope({'this':this, 'arguments':arguments}, var) 119 | var.registers([]) 120 | return (Js('INVALID: ')+var.get(u"this").get('message')) 121 | PyJs_anonymous_10_._set_name('anonymous') 122 | PyJsComma(var.get(u"this").put('toString', PyJs_anonymous_10_),var.get(u"this").put('message', var.get('e'))) 123 | PyJs_anonymous_9_._set_name('anonymous') 124 | @Js 125 | def PyJs_anonymous_11_(e, this, arguments, var=var): 126 | var = Scope({'e':e, 'this':this, 'arguments':arguments}, var) 127 | var.registers(['e']) 128 | @Js 129 | def PyJs_anonymous_12_(this, arguments, var=var): 130 | var = Scope({'this':this, 'arguments':arguments}, var) 131 | var.registers([]) 132 | return (Js('BUG: ')+var.get(u"this").get('message')) 133 | PyJs_anonymous_12_._set_name('anonymous') 134 | PyJsComma(var.get(u"this").put('toString', PyJs_anonymous_12_),var.get(u"this").put('message', var.get('e'))) 135 | PyJs_anonymous_11_._set_name('anonymous') 136 | var.put('r', Js({'cipher':Js({}),'hash':Js({}),'mode':Js({}),'misc':Js({}),'codec':Js({}),'exception':Js({'corrupt':PyJs_anonymous_7_,'invalid':PyJs_anonymous_9_,'bug':PyJs_anonymous_11_})})) 137 | @Js 138 | def PyJs_anonymous_13_(e, this, arguments, var=var): 139 | var = Scope({'e':e, 'this':this, 'arguments':arguments}, var) 140 | var.registers(['n', 'd', 'c', 'a', 'u', 'i', 'e', 's', 't', 'o']) 141 | (var.get(u"this").get('_tables').get('0').get('0').get('0') or var.get(u"this").callprop('_precompute')) 142 | var.put('c', var.get(u"this").get('_tables').get('0').get('4')) 143 | var.put('u', var.get(u"this").get('_tables').get('1')) 144 | var.put('s', var.get('e').get('length')) 145 | var.put('d', Js(1.0)) 146 | if ((PyJsStrictNeq(Js(4.0),var.get('s')) and PyJsStrictNeq(Js(6.0),var.get('s'))) and PyJsStrictNeq(Js(8.0),var.get('s'))): 147 | PyJsTempException = JsToPyException(var.get('r').get('exception').get('invalid').create(Js('invalid aes key size'))) 148 | raise PyJsTempException 149 | #for JS loop 150 | PyJsComma(var.get(u"this").put('_key', Js([var.put('i', var.get('e').callprop('slice', Js(0.0))), var.put('o', Js([]))])),var.put('t', var.get('s'))) 151 | while (var.get('t')<((Js(4.0)*var.get('s'))+Js(28.0))): 152 | try: 153 | def PyJs_LONG_14_(var=var): 154 | return PyJsComma(var.put('a', ((((var.get('c').get(PyJsBshift(var.get('a'),Js(24.0)))<>Js(16.0))&Js(255.0)))<>Js(8.0))&Js(255.0)))<>Js(7.0)))))))) 155 | PyJsComma(PyJsComma(var.put('a', var.get('i').get((var.get('t')-Js(1.0)))),((((var.get('t')%var.get('s'))==Js(0.0)) or (PyJsStrictEq(Js(8.0),var.get('s')) and ((var.get('t')%var.get('s'))==Js(4.0)))) and PyJs_LONG_14_())),var.get('i').put(var.get('t'), (var.get('i').get((var.get('t')-var.get('s')))^var.get('a')))) 156 | finally: 157 | (var.put('t',Js(var.get('t').to_number())+Js(1))-Js(1)) 158 | #for JS loop 159 | var.put('n', Js(0.0)) 160 | while var.get('t'): 161 | try: 162 | def PyJs_LONG_15_(var=var): 163 | return var.get('o').put(var.get('n'), (var.get('a') if ((var.get('t')<=Js(4.0)) or (var.get('n')>Js(16.0))&Js(255.0)))))^var.get('u').get('2').get(var.get('c').get(((var.get('a')>>Js(8.0))&Js(255.0)))))^var.get('u').get('3').get(var.get('c').get((Js(255.0)&var.get('a'))))))) 164 | PyJsComma(var.put('a', var.get('i').get((var.get('t') if (Js(3.0)&var.get('n')) else (var.get('t')-Js(4.0))))),PyJs_LONG_15_()) 165 | finally: 166 | PyJsComma((var.put('n',Js(var.get('n').to_number())+Js(1))-Js(1)),(var.put('t',Js(var.get('t').to_number())-Js(1))+Js(1))) 167 | PyJs_anonymous_13_._set_name('anonymous') 168 | @Js 169 | def PyJs_anonymous_16_(e, this, arguments, var=var): 170 | var = Scope({'e':e, 'this':this, 'arguments':arguments}, var) 171 | var.registers(['e']) 172 | return var.get(u"this").callprop('_crypt', var.get('e'), Js(0.0)) 173 | PyJs_anonymous_16_._set_name('anonymous') 174 | @Js 175 | def PyJs_anonymous_17_(e, this, arguments, var=var): 176 | var = Scope({'e':e, 'this':this, 'arguments':arguments}, var) 177 | var.registers(['e']) 178 | return var.get(u"this").callprop('_crypt', var.get('e'), Js(1.0)) 179 | PyJs_anonymous_17_._set_name('anonymous') 180 | @Js 181 | def PyJs_anonymous_18_(this, arguments, var=var): 182 | var = Scope({'this':this, 'arguments':arguments}, var) 183 | var.registers(['l', 'n', 'd', 'p', 'r', 'c', 'a', 'u', 'i', 'f', 'e', 's', 't', 'o']) 184 | var.put('u', var.get(u"this").get('_tables').get('0')) 185 | var.put('s', var.get(u"this").get('_tables').get('1')) 186 | var.put('d', var.get('u').get('4')) 187 | var.put('l', var.get('s').get('4')) 188 | var.put('f', Js([])) 189 | var.put('p', Js([])) 190 | #for JS loop 191 | var.put('e', Js(0.0)) 192 | while (var.get('e')>Js(7.0)))))^var.get('e')), var.get('e')) 195 | finally: 196 | (var.put('e',Js(var.get('e').to_number())+Js(1))-Js(1)) 197 | #for JS loop 198 | var.put('t', var.put('n', Js(0.0))) 199 | while var.get('d').get(var.get('t')).neg(): 200 | try: 201 | #for JS loop 202 | def PyJs_LONG_19_(var=var): 203 | return PyJsComma(PyJsComma(PyJsComma(PyJsComma(PyJsComma(var.put('i', (((var.put('i', ((((var.get('n')^(var.get('n')<>Js(8.0))^(Js(255.0)&var.get('i')))^Js(99.0))),var.get('d').put(var.get('t'), var.get('i'))),var.get('l').put(var.get('i'), var.get('t'))),var.put('c', ((((Js(16843009.0)*var.get('f').get(var.put('a', var.get('f').get(var.put('r', var.get('f').get(var.get('t')))))))^(Js(65537.0)*var.get('a')))^(Js(257.0)*var.get('r')))^(Js(16843008.0)*var.get('t'))))),var.put('o', ((Js(257.0)*var.get('f').get(var.get('i')))^(Js(16843008.0)*var.get('i'))))),var.put('e', Js(0.0))) 204 | PyJs_LONG_19_() 205 | while (var.get('e')>Js(16.0))&Js(255.0))))^var.get('y').get(((var.get('d')>>Js(8.0))&Js(255.0))))^var.get('E').get((Js(255.0)&var.get('l'))))^var.get('c').get(var.get('p')))),var.put('a', ((((var.get('b').get(PyJsBshift(var.get('s'),Js(24.0)))^var.get('v').get(((var.get('d')>>Js(16.0))&Js(255.0))))^var.get('y').get(((var.get('l')>>Js(8.0))&Js(255.0))))^var.get('E').get((Js(255.0)&var.get('u'))))^var.get('c').get((var.get('p')+Js(1.0)))))),var.put('i', ((((var.get('b').get(PyJsBshift(var.get('d'),Js(24.0)))^var.get('v').get(((var.get('l')>>Js(16.0))&Js(255.0))))^var.get('y').get(((var.get('u')>>Js(8.0))&Js(255.0))))^var.get('E').get((Js(255.0)&var.get('s'))))^var.get('c').get((var.get('p')+Js(2.0)))))),var.put('l', ((((var.get('b').get(PyJsBshift(var.get('l'),Js(24.0)))^var.get('v').get(((var.get('u')>>Js(16.0))&Js(255.0))))^var.get('y').get(((var.get('s')>>Js(8.0))&Js(255.0))))^var.get('E').get((Js(255.0)&var.get('d'))))^var.get('c').get((var.get('p')+Js(3.0)))))),var.put('p', Js(4.0), '+')),var.put('u', var.get('n'))),var.put('s', var.get('a'))),var.put('d', var.get('i'))) 247 | PyJs_LONG_21_() 248 | finally: 249 | (var.put('o',Js(var.get('o').to_number())+Js(1))-Js(1)) 250 | #for JS loop 251 | var.put('o', Js(0.0)) 252 | while (var.get('o')>Js(16.0))&Js(255.0)))<>Js(8.0))&Js(255.0)))<Js(0.0)): 292 | PyJsComma(var.put('t', Js(4.0), '-'),var.put('n', var.get('a').get('Hex').callprop('substr', (PyJsBshift(var.get('e'),var.get('t'))&Js(15.0)), Js(1.0)), '+')) 293 | 294 | return var.get('n') 295 | PyJs_anonymous_25_._set_name('anonymous') 296 | var.put('a', Js({'HexToKey':PyJs_anonymous_23_,'HexToWords':PyJs_anonymous_24_,'Hex':Js('0123456789abcdef'),'WordToHex':PyJs_anonymous_25_})) 297 | var.put('i', Js({})) 298 | @Js 299 | def PyJs_anonymous_26_(e, this, arguments, var=var): 300 | var = Scope({'e':e, 'this':this, 'arguments':arguments}, var) 301 | var.registers(['e']) 302 | return (Js(2147483647.0)!=(Js(2147483647.0)|var.get('e'))) 303 | PyJs_anonymous_26_._set_name('anonymous') 304 | @Js 305 | def PyJs_anonymous_27_(e, this, arguments, var=var): 306 | var = Scope({'e':e, 'this':this, 'arguments':arguments}, var) 307 | var.registers(['e']) 308 | def PyJs_LONG_28_(var=var): 309 | return PyJsComma(PyJsComma(PyJsComma(var.get('e').put('0', (((Js(2147483647.0)&var.get('e').get('0'))<>Js(2.0))&Js(3.0)), ((Js(255.0)&var.get('t').callprop('charCodeAt', var.get('o')))<<(Js(8.0)*(Js(3.0)-(Js(3.0)&var.get('o'))))), '^'),(((Js(0.0)==(Js(15.0)&var.put('o',Js(var.get('o').to_number())+Js(1)))) and (var.get('o')>Js(2.0))&Js(3.0)), (Js(128.0)<<(Js(8.0)*(Js(3.0)-(Js(3.0)&var.get('o'))))), '^'))) 327 | return PyJsComma(PyJsComma(PyJsComma(PyJsComma(PyJsComma(PyJs_LONG_30_(),var.get('n').put('0', var.get('r').get('0'), '^')),var.get('n').put('1', var.get('r').get('1'), '^')),var.get('n').put('2', var.get('r').get('2'), '^')),var.get('n').put('3', var.get('r').get('3'), '^')),var.get('e').callprop('encrypt', var.get('n'))) 328 | PyJs_anonymous_29_._set_name('anonymous') 329 | PyJsComma(PyJsComma(PyJsComma(var.get('i').put('MSBnotZero', PyJs_anonymous_26_),var.get('i').put('leftShift', PyJs_anonymous_27_)),var.get('i').put('const_Rb', Js(135.0))),var.get('i').put('compute', PyJs_anonymous_29_)) 330 | @Js 331 | def PyJs_anonymous_31_(e, t, n, r, this, arguments, var=var): 332 | var = Scope({'e':e, 't':t, 'n':n, 'r':r, 'this':this, 'arguments':arguments}, var) 333 | var.registers(['n', 'r', 'a', 'i', 'e', 't']) 334 | var.put('a', var.get('Array').create(Js(4.0))) 335 | var.put('i', var.get('n').get('length')) 336 | def PyJs_LONG_32_(var=var): 337 | return PyJsComma(PyJsComma(PyJsComma(PyJsComma(var.get('a').put('0', (Js(16908544.0)|((var.get('r')>>Js(16.0))&Js(255.0)))),var.get('a').put('1', ((((((var.get('r')>>Js(8.0))&Js(255.0))<Js(0.0)): 349 | PyJsComma(var.put('n',Js(var.get('n').to_number())-Js(1)),((var.put('a', var.get('e'), '*')>=Js(256.0)) and PyJsComma(var.put('a', Js(256.0), '/'),var.put('r',Js(var.get('r').to_number())+Js(1))))) 350 | 351 | return PyJsComma(((var.get('a')>Js(1.0)) and var.put('r',Js(var.get('r').to_number())+Js(1))),var.get('r')) 352 | PyJs_anonymous_33_._set_name('anonymous') 353 | @Js 354 | def PyJs_anonymous_34_(e, t, n, this, arguments, var=var): 355 | var = Scope({'e':e, 't':t, 'n':n, 'this':this, 'arguments':arguments}, var) 356 | var.registers(['n', 'r', 'a', 'i', 'e', 't']) 357 | var.put('a', Js(0.0)) 358 | #for JS loop 359 | var.put('r', (var.get('e').get('length')-Js(1.0))) 360 | while (var.get('r')>=Js(0.0)): 361 | try: 362 | var.put('i', ((var.get('e').get(var.get('r'))*var.get('n'))+var.get('a'))) 363 | PyJsComma(var.get('e').put(var.get('r'), (var.get('i')%var.get('t'))),var.put('a', ((var.get('i')-var.get('e').get(var.get('r')))/var.get('t')))) 364 | finally: 365 | var.put('r',Js(var.get('r').to_number())-Js(1)) 366 | PyJs_anonymous_34_._set_name('anonymous') 367 | @Js 368 | def PyJs_anonymous_35_(e, t, n, this, arguments, var=var): 369 | var = Scope({'e':e, 't':t, 'n':n, 'this':this, 'arguments':arguments}, var) 370 | var.registers(['n', 'r', 'a', 'i', 'e', 't']) 371 | #for JS loop 372 | var.put('r', (var.get('e').get('length')-Js(1.0))) 373 | var.put('a', var.get('n')) 374 | while ((var.get('r')>=Js(0.0)) and (var.get('a')>Js(0.0))): 375 | var.put('i', (var.get('e').get(var.get('r'))+var.get('a'))) 376 | PyJsComma(PyJsComma(var.get('e').put(var.get('r'), (var.get('i')%var.get('t'))),var.put('a', ((var.get('i')-var.get('e').get(var.get('r')))/var.get('t')))),var.put('r',Js(var.get('r').to_number())-Js(1))) 377 | 378 | PyJs_anonymous_35_._set_name('anonymous') 379 | @Js 380 | def PyJs_anonymous_36_(e, t, n, r, a, this, arguments, var=var): 381 | var = Scope({'e':e, 't':t, 'n':n, 'r':r, 'a':a, 'this':this, 'arguments':arguments}, var) 382 | var.registers(['n', 'r', 'c', 'a', 'u', 'i', 'e', 't']) 383 | var.put('c', var.get('Array').create(var.get('r'))) 384 | #for JS loop 385 | var.put('i', Js(0.0)) 386 | while (var.get('i')Js(0.0)) and var.put('l', (Js(16.0)-var.get('l')))) 433 | var.put('p', var.get('Array').create((((var.get('n').get('length')+var.get('l'))+var.get('s'))+Js(1.0)))) 434 | #for JS loop 435 | var.put('f', Js(0.0)) 436 | while (var.get('f')Js(0.0)) and (Js(0.0)==(Js(3.0)&var.get('f')))) and PyJsComma(PyJsComma(var.put('b', ((var.get('f')>>Js(2.0))&Js(255.0))),var.put('b', (((var.get('b')<=Js(0.0)): 541 | try: 542 | (PyJsComma(var.get('s').put(var.get('m'), var.get('h')),var.put('f', Js(0.0))) if (var.put('h', ((var.get('s').get(var.get('m'))+var.get('p').get(var.get('m')))+var.get('f')))=Js(0.0)): 550 | try: 551 | pass 552 | (PyJsComma(var.get('d').put(var.get('m'), var.get('h')),var.put('f', Js(0.0))) if (var.put('h', ((var.get('d').get(var.get('m'))+var.get('p').get(var.get('m')))+var.get('f')))