1

I'm trying to create a program that automatically creates accounts upon available usernames using api calls. The program works fine. However, I want it to run faster. Therefore I tried using threading but the problem is that whenever I use more than one thread my terminal creates a big mess. youtube video on what happens.

My code:

    # Login --> Threading --> Checker
    def login(self):
        self.headers["Authorization"] = "Basic " + self.finalLogin
        r = requests.post("https://public-ubiservices.ubi.com/v3/profiles/sessions", json={"Content-Type":"application/json"}, headers=self.headers)
        if r.status_code == 200:
            if r.json()["ticket"]:
                token = "Ubi_v1 t=" + r.json()["ticket"]
                self.headers['Authorization'] = token
                self.threading()

    def checker(self):
        [self.usernames.put(line.strip()) for line in open("external/wordlist.txt")]  
        while not self.usernames.empty():
            name = self.usernames.get(); self.usernames.put(name)
            url = f"https://public-ubiservices.ubi.com/v3/profiles?nameOnPlatform={name}&platformType=uplay"   
            try:
                r = requests.get(url, headers=self.headers)
                
                if self.checkedCount % 100 == 0:
                    self.checkedCount += 1
                    print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Message:        Using new login")
                    self.accounts()

                ctypes.windll.kernel32.SetConsoleTitleW(f"Gx | Checked: {self.checkedCount}, Available: {self.availableCount}, Errors: {self.errorCount}")
                if r.status_code == 200:
                    self.checkedCount += 1
                    if len(r.json()['profiles']) != 0:
                        print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Taken:          {name}")       
                    
                    else:  
                        print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Available:      {name}")
                        self.availableCount += 1
                        self.create(name)

                else:
                    self.errorCount += 1
                    print(f"{Fore.LIGHTBLACK_EX}[+]{Fore.RESET} Error:          Check errors.txt")
                    with open('external/errors.txt', "a") as errorFile:
                        errorFile.write(f'{self.currentTime} | Error code: {r.status_code}, Error message: {r.text}\n')
            
                    self.checkedCount += 1
                    self.accounts()

            except Exception:
                self.errorCount += 1
                pass

    def threading(self): 
        [self.usernames.put(line.strip()) for line in open("external/wordlist.txt")]   
        for x in range(5):
            threading.Thread(target=self.checker, args=()).start()

  • 1
    I have not looked at your YouTube video. However, what you have here is multiple threads *print*ing to the standard output stream concurrently. It's almost certainly going to create a "big mess". –  Oct 25 '21 at 06:16
  • the terminal is displaying what its supposed to, you can't call it a mess . – Zain Ul Abidin Oct 25 '21 at 06:20

1 Answers1

0

What you call a mess it what happens, when using print while running multiple threads. This is, because print, especially the output buffer, is not thread safe. As described in more detail here, you must use a thread safe approach.

I think of two options:

  1. Using a lock on the print statement, e.g.
from threading import Lock
print_lock = Lock()

with print_lock:
    print(...)
  1. Using a wrapper function (taken from here) and use that wrapper function to print things:
def safe_print(*args, sep=" ", end="", **kwargs):
    joined_string = sep.join([ str(arg) for arg in args ])
    print(joined_string  + "\n", sep=sep, end=end, **kwargs)
AnsFourtyTwo
  • 2,480
  • 2
  • 13
  • 33
  • Thanks, for the `safe_print` method you would have to do `safe_print('something to print')` everytime you want it to print right –  Oct 25 '21 at 20:43
  • That is one correct example, yes. Actually `safe_print` resembles the arguments of the real `print` function, so you should be able to use it, just as you would use `print`. – AnsFourtyTwo Oct 26 '21 at 09:36
  • Unfortunately none of them work :/ –  Oct 26 '21 at 21:42