Skip to content
This repository was archived by the owner on Apr 2, 2023. It is now read-only.

Commit 39f31f6

Browse files
committed
Merge branch 'add-submit-entry' into main
2 parents a973de1 + 1f0d6d4 commit 39f31f6

File tree

10 files changed

+786
-45
lines changed

10 files changed

+786
-45
lines changed

README.md

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,26 @@ $ python3 main.py
2626
| keys | dict | dict containing keys to solving sites | - |
2727
| generate_random | bool | Should the program generate random password. | `true` or `false` |
2828
| choices | array | Array of password choices | - |
29-
29+
| user_agents| array | Array of user-agents for mobile & desktop | - |
3030

3131
### /newegg/*
3232
- Contains the core software code.
3333

34+
# Creating Accounts
35+
- If you want to create accounts via mobile, change line 93 in `main.py` from `desktop.Create_Account(self, email)` to `mobile.Create_Account(self, email)`
36+
* And vice versa
37+
- MAKE SURE YOU STORE YOUR SESSIONS SOMEWHERE (Don't delete the `.log` file)
38+
39+
# Submitting Entries
40+
- In order to submit entries, you must make sure:
41+
* The program will pull accounts/sessions from the filename that was used to create accounts (`output_filename` in the settings.json file).
42+
* Your .log file is in the main directory (alongside with `main.py`)
43+
* Accounts/Sessions are still in the .log file
44+
* The program will automatically enter on the same platform as the account was created (Desktop or App)
45+
* MAKE SURE YOU KEEP YOUR SESSIONS (Don't delete the `.log` file)
46+
3447
# Recommendations
35-
1. **MAKE SURE YOU STORE YOUR SESSIONS SOMEWHERE**
48+
1. **MAKE SURE YOU STORE YOUR SESSIONS SOMEWHERE (Don't delete the `.log` file)**
3649
2. Althought not completely necessary, but you should add/delete/randomify events for accertify.
3750
3. Make sure iOS app version is up to date
3851
4. Handle exceptions better
@@ -47,12 +60,23 @@ $ python3 main.py
4760
* I recommend using anticaptcha for V3, but Capmonster & 2Captcha is also available.
4861
- Only tested on Python 3.7
4962
* *Should* work on other versions, but I can't promise anything.
50-
- This is intended for devs, so try not to change too much code as it might break something.
63+
- This is intended for devs. If you aren't familiar with python, try not to change too much code as it might break something.
5164
- This isn't a reflection of how I actually write code so pls don't judge too hard :joy:
5265
* I've been writing in Go lately, hence the structure of the whole thing.
53-
- If you want to create accounts via mobile, change line 79 in `main.py` from `desktop.Create_Account(self, email)` to `mobile.Create_Account(self, email)`
54-
* And vice versa
55-
- There are lots of ways to make this better, cleaner and better on memory. If I find till I'll update this repo.
66+
- There are lots of ways to make this better, cleaner and better on memory. If I find time, I'll update this repo.
67+
68+
69+
# Maintenance
70+
- This bot is fully functional with success. I won't be working on it much. I'll only work on it when:
71+
* They make some massive change
72+
* Have *loads* of free time and can complete the [to do list](https://github.com/Matthew17-21/Newegg-Shuffle#to-do)
73+
- Pull requests are always welcome
74+
- If any issues were to arise, [open an issue](https://github.com/Matthew17-21/Newegg-Shuffle/issues/new)
75+
* Please incude:
76+
* Python version
77+
* Error
78+
* How to replicate
79+
- You may also contact me on discord - `Matthew#6937` with any questions or concerns
5680

5781
# FAQ
5882
1. Does this work out of the box?
@@ -68,8 +92,12 @@ $ python3 main.py
6892

6993
# Success
7094
![Genning](https://i.imgur.com/lvrTp36.png)
95+
![Running](https://i.imgur.com/r8gPUIq.png)
7196
![Success](https://i.imgur.com/8csUoqR.png)
7297

7398
# TO DO
74-
1. [] Clean up code
75-
2. [] Update documentation
99+
1. [] Clean up & document code
100+
2. [] Release GUI version
101+
3. [] Maybe a folder for logs?
102+
4. [] Release in Go
103+
5. [] Inherit, don't pass.

data/settings.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"ios_app_version": "6.23.0",
23
"output_filename": "Successfully created accounts.log",
34
"captcha": {
45
"version": "v3",
@@ -17,6 +18,14 @@
1718
"Also,IfYouHaventNoticed,!!1!",
1819
"ThereNeedsToBeANumberAndSpecialChar!12!"
1920
]
21+
},
22+
"user_agents": {
23+
"mobile":[
24+
"Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1"
25+
],
26+
"desktop":[
27+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36"
28+
]
2029
}
2130

2231
}

main.py

Lines changed: 136 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import sys
22
try:
3+
import os
4+
import platform
35
import logging
46
import json
57
import threading
@@ -10,21 +12,21 @@
1012
colorama.init()
1113
init(autoreset=True)
1214
from captchatools import captcha_harvesters
13-
from newegg.create_account import desktop, mobile, static_data
15+
from newegg.create_account import static_data
16+
import time
1417
except ModuleNotFoundError:
1518
print("Make sure you ran pip3 install -r requirements.txt")
19+
time.sleep(999)
1620
sys.exit(0)
1721

1822

19-
with open("./data/settings.json") as settingsFile:
20-
settings = json.load(settingsFile)
21-
logging.basicConfig(filename=settings["output_filename"], level=logging.INFO)
2223

2324
class Newegg:
2425
def __init__(self):
2526
self.screenlock = Semaphore(value=1)
2627

2728
# Load config
29+
settings = self.load_settings()
2830
self.settings = settings
2931
if settings["captcha"]["captcha_solver"] == 1 or str( settings["captcha"]["captcha_solver"]).lower() == "capmonster":
3032
api_key = settings["captcha"]["keys"]["capmonster"]
@@ -33,9 +35,9 @@ def __init__(self):
3335
elif settings["captcha"]["captcha_solver"] == 3 or str( settings["captcha"]["captcha_solver"]).lower() == "2captcha":
3436
api_key = settings["captcha"]["keys"]["2captcha"]
3537

36-
if settings["captcha"]["version"] == "v3":
38+
if settings["captcha"]["version"].lower() == "v3":
3739
sitekey = static_data.v3_sitekey
38-
elif settings["captcha"]["version"] == "v3":
40+
elif settings["captcha"]["version"].lower() == "v2":
3941
sitekey = static_data.v2_sitekey
4042

4143

@@ -47,33 +49,148 @@ def __init__(self):
4749
min_score=0.7, action="Register", captcha_type=settings["captcha"]["version"]
4850
)
4951

50-
# Start the bot.
52+
# Start the bot when initialized.
5153
self.main()
5254

5355
def main(self):
54-
num_tasks = eval(input(Fore.BLUE + "Enter amount of tasks at a time: " + Fore.WHITE + " "))
56+
'''
57+
Main method.
58+
59+
This method will be called (automatically) when the bot starts.
60+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
61+
'''
62+
63+
# Get user input for what they want to do
64+
print()
65+
print(Fore.CYAN + '1' ,Fore.MAGENTA + "=", Fore.YELLOW + "Create Accounts")
66+
print(Fore.CYAN + '2' ,Fore.MAGENTA + "=", Fore.YELLOW + "Submit Entries")
67+
choice = eval(input("{}".format(Fore.MAGENTA + "Enter your choice: " + Fore.CYAN)))
68+
if choice == 1:
69+
self.create_accounts()
70+
elif choice == 2:
71+
self.submit_entries()
72+
73+
def load_settings(self):
74+
# Some users said their program couldn't find the files
75+
# So this is a quick fix to that.
76+
original_path = os.getcwd()
77+
os.chdir("./data/")
78+
self.PATH_EMAILS = os.getcwd() + "\\emails.txt"
79+
self.PATH_PROXIES = os.getcwd() + "\\proxies.txt"
80+
if platform.system() == "Linux" or platform.system() == "Darwin":
81+
self.PATH_EMAILS = self.PATH_EMAILS.replace("\\", "/")
82+
self.PATH_PROXIES = self.PATH_PROXIES.replace("\\", "/")
83+
84+
85+
# Open settings file
86+
settings_file_path = os.getcwd() + "/settings.json"
87+
os.chdir(original_path)
88+
with open(settings_file_path) as settingsFile:
89+
try:
90+
return json.load(settingsFile)
91+
except json.JSONDecodeError:
92+
print(Fore.RED + "There is an error in your settings.json file." +
93+
"Make sure the commas are correct and there aren't any extra commas!")
94+
time.sleep(999)
95+
sys.exit(0)
96+
97+
def create_accounts(self):
98+
'''
99+
This method will be called when the user wants to create Newegg Accounts.
100+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
101+
102+
It will pull emails from the /data/emails.txt folder and use those
103+
to create the accounts
104+
'''
105+
from newegg.create_account import desktop, app, static_data
106+
107+
# Prompt for how many tasks
108+
num_tasks = eval(input(Fore.BLUE + "\nEnter amount of tasks at a time: " + Fore.WHITE + " "))
55109
self.sema = threading.Semaphore(value=num_tasks)
56110
threads = []
57111

58-
with open("./data/emails.txt") as email_file:
112+
# Start to create create accounts
113+
with open(self.PATH_EMAILS) as email_file:
59114
for line in email_file.readlines():
60115
email = line.split(':')[0].strip("\n")
61116
self.sema.acquire()
62-
thread = threading.Thread(target=self.create,args=(email,))
117+
thread = threading.Thread(target=desktop.Create_Account,args=(self,email))
63118
threads.append(thread)
64119
thread.start()
65120

66-
def create(self,email):
67-
task = desktop.Create_Account(self, email)
68-
data = task.start()
121+
def submit_entries(self):
122+
'''
123+
This method will be called when the user wants to enter the Newegg raffle.
124+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
125+
126+
It'll pull sessions from the file that the user used to create accounts
127+
'''
128+
from newegg.submit_raffle import raffles, app, desktop
129+
path_to_created_accounts = os.getcwd() + "\\{}".format(self.settings["output_filename"]) if \
130+
platform.system == "Windows" else os.getcwd() + "/{}".format(self.settings["output_filename"])
131+
132+
# Because Newegg still has V2 captcha enabled for submitting entries,
133+
# we'll use that over V3. If for whatever reason you want to use V3,
134+
# you would have to change this line of code.
135+
self.captcha_solver.sitekey = "6Lcv-WUUAAAAAA9hyir8HPKZ44OvDLg1oZqnq_9d"
136+
self.captcha_solver.captcha_type = "v2"
137+
138+
# Scrape & display raffle items
139+
print()
140+
print(Fore.YELLOW + "Getting items in raffle...")
141+
items = raffles.get_items()
142+
index = 0
143+
for item in items:
144+
print(Fore.GREEN + str(index) ,Fore.MAGENTA + "=", Fore.CYAN + "{} (${})".format( item["name"], item["price"]))
145+
index +=1
69146

70-
# Log Data
71-
logging.info("{}:{}".format(
72-
email,
73-
json.dumps(data)
74-
))
75-
self.sema.release()
76147

148+
# Get user choice(s) for the items they want to enter for
149+
self.PRODUCTS_TO_ENTER = [] # This will be the array used to submit entries
150+
choices = input(Fore.MAGENTA + "Enter the numbers of all the products you'd like to enter for, seperated by a space. (Example: 1 5 7 9 ): " + Fore.GREEN)
151+
for choice in choices.split():
152+
try:
153+
self.PRODUCTS_TO_ENTER.append({"ItemNumber": items[eval(choice)]["id"]})
154+
except Exception:
155+
print(Fore.RED + f"There was an error with item: #{choice}. Skipping that item.")
156+
157+
158+
# Show how many accounts have been made / are about to enter the raffle
159+
print()
160+
try:
161+
with open(path_to_created_accounts) as email_file:
162+
print( Fore.BLUE + "Amount of accounts loaded: {} ({})".format(
163+
Fore.CYAN + str(len(email_file.readlines())),
164+
self.settings["output_filename"])
165+
)
166+
except (FileExistsError, FileNotFoundError):
167+
print(Fore.RED + "Could not find the file with sessions. Check repo fore help.")
168+
time.sleep(100)
169+
return
170+
171+
172+
# Prompt how many tasks
173+
num_tasks = eval(input(Fore.BLUE + "Enter amount of tasks at a time: " + Fore.WHITE + " "))
174+
self.sema = threading.Semaphore(value=num_tasks)
175+
threads = []
176+
177+
178+
# Enter raffle
179+
with open(path_to_created_accounts) as email_file: # Get the emails from the file the user named
180+
for line in email_file.readlines():
181+
if "error" not in line:
182+
self.sema.acquire()
183+
email = line.split(':')[2].strip("\n")
184+
sessionData = json.loads(":".join(line.split(":")[3:]))
185+
186+
# If the acct was created via desktop, it will enter via that way
187+
# If the acct was created via app, it will enter via that way
188+
if sessionData["desktop"] == {}: # If there are no desktop cookies, means it was created via APP
189+
task = threading.Thread(target=app.SubmitRaffle,args=(self,email, sessionData))
190+
else:
191+
task = threading.Thread(target=desktop.SubmitRaffle,args=(self,email, sessionData))
192+
threads.append(task)
193+
task.start()
77194

78195

79196
Newegg()

newegg/create_account/mobile.py renamed to newegg/create_account/app.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,25 @@
1919
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pksc1_v1_5
2020
from Crypto.PublicKey import RSA
2121
from . import static_data, Accertify
22-
22+
from threading import Thread
2323
POSTURL_ticketID = "https://secure.m.newegg.com//Application/UnifiedLogin/Landingpage"
2424

2525

2626

2727
class Create_Account:
2828
def __init__(self, NeweggParent:object, email):
29+
# I don't like how I'm passing these in. I'm going to change this soon.
30+
logging.basicConfig(filename=NeweggParent.settings["output_filename"], level=logging.INFO)
2931
self.screenlock = NeweggParent.screenlock
3032
self.captcha_solver = NeweggParent.captcha_solver
33+
self.sema = NeweggParent.sema
34+
self.PATH_PROXIES = NeweggParent.PATH_PROXIES
35+
3136

3237
# Define basic info
3338
self.current_task = email
3439
self.email = email
3540
self.logging_data = {}
36-
3741
if NeweggParent.settings["password"]["generate_random"]:
3842
self.password = self.randompassword()
3943
else:
@@ -47,14 +51,32 @@ def __init__(self, NeweggParent:object, email):
4751
self.HEADERS_createAccount = static_data.HEADERS_createAccount
4852
self.HEADERS_afterCreate = static_data.HEADERS_afterCreate
4953

54+
# Update Headers
55+
user_agent = random.choice(NeweggParent.settings["user_agents"]["mobile"])
56+
self.HEADERS_getTicketID["User-Agent"] = user_agent
57+
self.HEADERS_getFormKeys["User-Agent"] = user_agent
58+
self.HEADERS_createAccount["User-Agent"] = user_agent
59+
self.HEADERS_afterCreate["User-Agent"] = user_agent
60+
61+
self.start()
62+
5063
def start(self):
5164
self.getProxy()
5265
self.get_ticket_id()
5366
if self.create_account():
5467
self.get_cookies()
55-
return self.logging_data
68+
69+
logging.info("{}:{}".format(
70+
self.email,
71+
json.dumps(self.logging_data)
72+
))
73+
self.sema.release()
74+
return
5675

5776
def get_ticket_id(self):
77+
'''
78+
The get_ticket_id methods returns an ID that is used in POST URL's to create account
79+
'''
5880
while True:
5981
try:
6082
# Get Cookies
@@ -65,7 +87,6 @@ def get_ticket_id(self):
6587
self.session.get(GETURL_getCookies, headers=self.HEADERS_getCookies)
6688

6789

68-
6990
# Get Ticket ID
7091
payload = "Payload=%7B%22enableGustCheckout%22%3Afalse%2C%22regionCode%22%3A%22USA%22%2C%22LastLoginName%22%3A%22%22%2C%22themeStyle%22%3A0%2C%22userState%22%3A%22%7B%5C%22APPType%5C%22%3A%5C%22ios%5C%22%2C%5C%22path%5C%22%3A%5C%22SignUp%5C%22%7D%22%7D"
7192
resp = self.session.post(POSTURL_ticketID, headers=self.HEADERS_getTicketID, data=payload, allow_redirects=False)
@@ -94,6 +115,9 @@ def get_ticket_id(self):
94115
continue
95116

96117
def create_account(self):
118+
'''
119+
The create_account is called when all the info is gather and creates accounts.
120+
'''
97121
POSTURL_createAccount = f"https://secure.newegg.com/identity/api/SignUp?ticket={self.ticketID}"
98122
GETURL_tokenData = f"https://secure.newegg.com/identity/api/InitSignUp?ticket={self.ticketID}"
99123
self.HEADERS_createAccount["Referer"] = self.ticketURL
@@ -189,7 +213,7 @@ def create_account(self):
189213

190214
def getProxy(self):
191215
# Load proxy from file
192-
with open("./data/proxies.txt", "r") as file:
216+
with open(self.PATH_PROXIES, "r") as file:
193217
proxies = file.readlines()
194218
if len(proxies) > 0:
195219
line = proxies[random.randint(0, len(proxies) - 1)].strip("\n").split(":")

0 commit comments

Comments
 (0)