infotrex / bulk-upload-to-opensea

BULK UPLOAD NFTs to OPENSEA
276 stars 203 forks source link

Does this project still receive any support or updates? #252

Open Chelvis opened 1 year ago

Chelvis commented 1 year ago

?

hamhocks commented 1 year ago

It doesn't seem like it. I wish someone would make a new version for the recent chrome browser because this doesn't work as well. Very slow almost manual, it just fills out the details.

Cyberhyper777 commented 1 year ago

It doesn't seem like it. I wish someone would make a new version for the recent chrome browser because this doesn't work as well. Very slow almost manual, it just fills out the details.

it doesn’t work for me at all (( although everything is installed correctly, and I don’t know how to fix it. I need this bot to fill in the fields at least up to the captcha.

Chelvis commented 1 year ago

It doesn't seem like it. I wish someone would make a new version for the recent chrome browser because this doesn't work as well. Very slow almost manual, it just fills out the details.

it doesn’t work for me at all (( although everything is installed correctly, and I don’t know how to fix it. I need this bot to fill in the fields at least up to the captcha.

I changed the code and made it way simpler to fill the form up to the captcha. I also had to fix some stuff that was not working. It's no longer configured to run batch, but oneby one.

here is the code:

_upload_2captchaV2.py

import tkinter
import subprocess
from tkinter import *
from tkinter import filedialog
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import tkinter.font as font
from turtle import width
from PIL import ImageTk, Image
import urllib.request
from urllib import parse
from io import BytesIO
import os
import io
import sys
import pickle
import time
from decimal import *
import webbrowser
# from click import command
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support import expected_conditions as ExpectedConditions
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.keys import Keys
from datetime import timedelta  
import dateutil.relativedelta
from datetime import timedelta, date
import locale
import json 
import ssl
import random
import timeit #HKN
import re #HKN
from functools import partial #HKN

ssl._create_default_https_context = ssl._create_unverified_context

#check local date format
locale.setlocale(locale.LC_ALL, '')
lastdate = date(date.today().year, 12, 31)

root = Tk()
root.geometry('610x420')
root.resizable(False, False)
root.title("NFTs Upload to OpenSea v2.0.1 - 2Captcha.com Solver")

input_save_list = ["NFTs folder :", 0, 0, 0, 0, 0, 0, 0, 0, 0]
main_directory = os.path.join(sys.path[0])

def supportURL():
    webbrowser.open_new("https://www.infotrex.net/opensea/support.asp?r=app")

def coffeeURL():
    webbrowser.open_new("https://github.com/infotrex/bulk-upload-to-opensea/#thanks")

class WebImage:
    def __init__(self, url):
        with urllib.request.urlopen(url) as u:
            raw_data = u.read()
        #self.image = tk.PhotoImage(data=base64.encodebytes(raw_data))
        image = Image.open(io.BytesIO(raw_data))
        self.image = ImageTk.PhotoImage(image)

    def get(self):
        return self.image

imageurl = "https://www.infotrex.net/opensea/header.png"
img = WebImage(imageurl).get()
imagelab = tk.Label(root, image=img)
imagelab.grid(row=0, columnspan=2)
imagelab.bind("<Button-1>", lambda e:supportURL())

def open_chrome_profile():
    subprocess.Popen(
        [
            "start",
            "chrome",
            "--remote-debugging-port=8989",
            "--user-data-dir=" + main_directory + "/chrome_profile",
        ],
        shell=True,
    )

def save_file_path():
    return os.path.join(sys.path[0], "Save_gui.cloud") 

# ask for directory on clicking button, changes button name.
def upload_folder_input():
    global upload_path
    upload_path = filedialog.askdirectory()
    Name_change_img_folder_button(upload_path)

def Name_change_img_folder_button(upload_folder_input):
    upload_folder_input_button["text"] = upload_folder_input

def is_numeric(val):
    if str(val).isdigit():
        return True
    elif str(val).replace('.','',1).isdigit():
        return True
    else:
        return False

def check_exists_by_xpath(driver, xpath):
    try:
        # driver.find_element_by_xpath(xpath)
        driver.find_element(By.XPATH, xpath)
    except NoSuchElementException:
        return False
    return True

class InputField:
    def __init__(self, label, row_io, column_io, pos, txt_width=60, master=root):
        self.master = master
        self.input_field = Entry(self.master, width=txt_width)
        self.input_field.grid(ipady=3)
        self.input_field.label = Label(master, text=label, anchor="w", width=20, height=1 )
        self.input_field.label.grid(row=row_io, column=column_io, padx=12, pady=2)
        self.input_field.grid(row=row_io, column=column_io + 1, padx=12, pady=2)

        try:
            with open(save_file_path(), "rb") as infile:
                new_dict = pickle.load(infile)
                self.insert_text(new_dict[pos])
        except FileNotFoundError:
            pass

    def insert_text(self, text):
        self.input_field.delete(0, "end")
        self.input_field.insert(0, text)

    def save_inputs(self, pos):
        #messagebox.showwarning("showwarning", "Warning")
        input_save_list.insert(pos, self.input_field.get())
        #print(self.input_field.get())
        with open(save_file_path(), "wb") as outfile:
            pickle.dump(input_save_list, outfile)

    def validate_inputs(self, maxlen, type, message):

        if type == 0 and (len(self.input_field.get()) == 0 or (self.input_field.get()).isdigit() != True or len(self.input_field.get()) > maxlen):
            messagebox.showwarning("showwarning", message)

        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):
            messagebox.showwarning("showwarning", message)       

        elif type == 2 and ( len(self.input_field.get()) == 0 or len(self.input_field.get()) > maxlen):
            messagebox.showwarning("showwarning", message)

        else:
            return True     

###input objects###
collection_link_input = InputField("OpenSea Collection Link:", 2, 0, 1)
start_num_input = InputField("Number:", 3, 0, 2)
title = InputField("Title:", 4, 0, 5)
description = InputField("Description:", 5, 0, 6)
file_format = InputField("NFT Image Format:", 6, 0, 7)
external_link = InputField("External link:", 7, 0, 8)

def save():
    collection_link_input.validate_inputs(200, 2, 'Collection link required')
    title.validate_inputs(100, 2, 'title required')
    description.validate_inputs(500, 2, 'description required')
    file_format.validate_inputs(100, 2, 'file format required - png, jpg, jpeg, gif')
    external_link.validate_inputs(300, 3, '')

    input_save_list.insert(0, upload_path)
    collection_link_input.save_inputs(1)
    start_num_input.save_inputs(2)
    title.save_inputs(5)
    description.save_inputs(6)
    file_format.save_inputs(7)
    external_link.save_inputs(8)
    #Total_Items.save_inputs(10)
    #Control_Line_Number.save_inputs(11)
    #Items_In_Line.save_inputs(12)

def main_program(prgrm):

    project_path = main_directory
    file_path = upload_path
    collection_link = collection_link_input.input_field.get()
    start_num = int(start_num_input.input_field.get())
    loop_title = title.input_field.get()
    loop_file_format = file_format.input_field.get()
    loop_external_link = str(external_link.input_field.get())
    loop_description = description.input_field.get()

    ##chromeoptions
    options = webdriver.ChromeOptions()
    options.add_argument("--disable-blink-features=AutomationControlled")
    options.add_experimental_option("debuggerAddress", "localhost:8989")
    driver = webdriver.Chrome(executable_path=project_path + "/chromedriver.exe",options=options)
    # driver = webdriver.Chrome( service=Service(project_path + "/chromedriver.exe"), options=opt )
    wait = WebDriverWait(driver, 60)

    ###wait for methods
    def wait_css_selector(code):
        wait.until(
            ExpectedConditions.presence_of_element_located((By.CSS_SELECTOR, code))
        )

    def wait_css_selectorTest(code):
        wait.until(
            ExpectedConditions.elementToBeClickable((By.CSS_SELECTOR, code))
        )    

    def wait_xpath(code):
        wait.until(ExpectedConditions.presence_of_element_located((By.XPATH, code)))

    sleeptime = random.uniform(0.01, 0.02) #HKN
    Lines = []

    start_numformat = f"{ start_num:01}"
    #HKN S Only Listing
    if prgrm =="Full":#HKN
        time.sleep(sleeptime)
        print("Start filling data for NFT " +  loop_title + str(start_numformat))
        driver.get(collection_link)

        #HKN S
        wait_E = True
        while wait_E:
            try:
                WebDriverWait(driver, 20).until(ExpectedConditions.presence_of_element_located((By.CSS_SELECTOR, "button[aria-label='Add properties']" )))
                wait_E = False
            except:
                print("Refresh")
                with open(os.path.join(sys.path[0], "Log.txt"),  'a') as outputfile:  # Use file to refer to the file object
                    outputfile.write("Starting Point This Page Needed To Be Refreshed \n")
                driver.get(collection_link)
                time.sleep(sleeptime)
                wait_E = True    
        #HKN F

        #HKN Start
        wait_xpath('//*[@id="name"]')
        name = driver.find_element(By.XPATH, '//*[@id="name"]')
        name.send_keys(loop_title + str(start_numformat))  # +1000 for other folders #change name before "#"
        time.sleep(sleeptime)
        name_i = 1
        kacinci = 0
        start = timeit.default_timer()
        stop = timeit.default_timer()
        yenilendi = False
        while name_i == 1:
            if yenilendi == True :
                wait_xpath('//*[@id="name"]')
                name = driver.find_element(By.XPATH, '//*[@id="name"]')
                yenilendi = False
            if len(name.get_attribute("value")) == 0:
                if kacinci < 10 :
                    kacinci = kacinci + 1
                    if kacinci == 1:
                        start = timeit.default_timer()
                    name.send_keys(loop_title + str(start_numformat))  # +1000 for other folders #change name before "#"
                    time.sleep(sleeptime)
                else :
                    with open(os.path.join(sys.path[0], "Log.txt"),  'a') as outputfile:  # Use file to refer to the file object
                        outputfile.write("This Page Needed To Be Refreshed \n")
                    yenilendi = True
                    kacinci = 0
                    driver.refresh()
            else:
                name_i = 0
                stop = timeit.default_timer()
                with open(os.path.join(sys.path[0], "Log.txt"),  'a') as outputfile:  # Use file to refer to the file object
                    outputfile.write("Total Retries : " + str(kacinci) + " :: " +"Total Time : " + str((stop - start)) + "\n")

        wait_xpath('//*[@id="media"]')
        imageUpload = driver.find_element(By.XPATH, '//*[@id="media"]')
        imagePath = os.path.abspath(file_path + "\\images\\" + str(start_numformat) + "." + loop_file_format)  # change folder here
        imageUpload.send_keys(imagePath)
        time.sleep(sleeptime)
        #HKN Finish

        ext_link = driver.find_element(By.XPATH, '//*[@id="external_link"]')
        ext_link.send_keys(loop_external_link + str(start_numformat) if loop_external_link != '' else '')
        time.sleep(sleeptime)

        desc = driver.find_element(By.XPATH, '//*[@id="description"]')
        desc.send_keys(loop_description)
        time.sleep(sleeptime)

        jsonFile = file_path + "/json/"+ str(start_numformat) + ".json"
        if os.path.isfile(jsonFile) and os.access(jsonFile, os.R_OK):

            #print(str(jsonMetaData))
            wait_css_selector("button[aria-label='Add properties']")
            properties = driver.find_element(By.CSS_SELECTOR, "button[aria-label='Add properties']")
            driver.execute_script("arguments[0].click();", properties)
            time.sleep(sleeptime)

            # checks if file exists
            jsonData = json.loads(open(file_path + "\\json\\"+ str(start_numformat) + ".json").read())

            if "attributes" in jsonData:
                jsonMetaData = jsonData['attributes']

                for key in jsonMetaData:
                    input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
                    input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
                    #print(str(key['trait_type']))
                    #print(str(key['value']))
                    input1.send_keys(str(key['trait_type']).encode("windows-1252").decode("utf-8"))
                    input2.send_keys(str(key['value']).encode("windows-1252").decode("utf-8"))
                    addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
                    driver.execute_script("arguments[0].click();", addmore_button)
                time.sleep(sleeptime)

                try:
                    save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
                    driver.execute_script("arguments[0].click();", save_button)
                    time.sleep(sleeptime)
                except:
                    driver.find_element(By.XPATH, '//button[text()="Save"]').click()
                    time.sleep(sleeptime)

            elif "properties" in jsonData:
                jsonMetaData = jsonData['properties']

                wait_xpath('//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')#HKN
                for key in jsonMetaData:
                    input1 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[1]/div/div/input')
                    input2 = driver.find_element(By.XPATH, '//tbody[@class="AssetTraitsForm--body"]/tr[last()]/td[2]/div/div/input')
                    #print(str(key['type']))
                    #print(str(key['name']))
                    input1.send_keys(str(key['type']))
                    input2.send_keys(str(key['name']))
                    addmore_button = driver.find_element(By.XPATH, '//button[text()="Add more"]')
                    driver.execute_script("arguments[0].click();", addmore_button)
                time.sleep(sleeptime)

                try:
                    save_button = driver.find_element(By.XPATH, '//button[text()="Save"]')
                    driver.execute_script("arguments[0].click();", save_button)
                    time.sleep(sleeptime)
                except:
                    driver.find_element(By.XPATH, '//button[text()="Save"]').click()
                    time.sleep(sleeptime)

            else:
                print("keys not found!") 

        # Select Polygon blockchain if applicable
        wait_xpath('//*[@id="chain"]')
        blockchain_dropdown = driver.find_element(By.CSS_SELECTOR, "div:has(> input#chain)")
        driver.execute_script("arguments[0].scrollIntoView();", blockchain_dropdown )
        driver.execute_script("arguments[0].click();", blockchain_dropdown )
        driver.execute_script("arguments[0].click();", blockchain_dropdown )

        WebDriverWait(driver, 100).until(ExpectedConditions.presence_of_element_located((By.CSS_SELECTOR, '.tippy-content ul')))

        polygon_botton = driver.find_element(By.CSS_SELECTOR, '.tippy-content img[alt="Polygon chain image"]')
        driver.execute_script("arguments[0].click();", polygon_botton)

        # delay()
        create = driver.find_element(By.XPATH, '//*[@id="__next"]/div[1]/main/div/div/section/div[2]/form/div/div[1]/span/button')
        driver.execute_script("arguments[0].click();", create)

        print(loop_title + str(start_numformat) + " is ready to go! It's now on you to solve that fucking Captcha. \n")

upload_folder_input_button = tkinter.Button(root, width=50, height=1, text="Add NFTs Upload Folder", command=upload_folder_input)
upload_folder_input_button.grid(row=21, column=1, padx=2)
open_browser = tkinter.Button(root, width=50, height=1,  text="Open Chrome Browser", command=open_chrome_profile)
open_browser.grid(row=23, column=1, pady=2)
button_save = tkinter.Button(root, width=50, height=1,  text="Save This Form", command=save) 
button_save.grid(row=22, column=1, pady=2)
button_start = tkinter.Button(root, width=44, height=2, bg="green", fg="white", text="Start", command=partial(main_program, "Full"))#command=lambda: main_program("Full")
button_start['font'] = font.Font(size=10, weight='bold')
button_start.grid(row=25, column=1, pady=2)

try:
    with open(save_file_path(), "rb") as infile:
        new_dict = pickle.load(infile)
        global upload_path
        Name_change_img_folder_button(new_dict[0])
        upload_path = new_dict[0]
except FileNotFoundError:
    pass
#####BUTTON ZONE END#######
root.mainloop()