Skip to content

Commit

Permalink
Proxy support
Browse files Browse the repository at this point in the history
I forgot about this feature, whoops.
  • Loading branch information
ghluka committed Nov 3, 2024
1 parent 99e7223 commit ea4aff9
Show file tree
Hide file tree
Showing 25 changed files with 220 additions and 117 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,10 @@ $ python3 main.py
- [Twitch](https://twitch.tv/)
- [X](https://x.com/)

<!-- Websites end -->
<!-- Websites end -->

## 🖇️ Proxy support

We allow the use of proxies, however, if you use public proxies you'll likely encounter an infinite ratelimit from hundreds or thousands of people using the same proxy. Proxies can dramatically speed up or slow down the process depending on their quality.

Proxies should be stored in a format in a `protocol://ip:port` format.
26 changes: 9 additions & 17 deletions src/base/checker.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,21 @@
import concurrent.futures
"""Base username availability checker class.
"""
from functools import singledispatchmethod

from httpx._types import ProxiesTypes
from utils.proxies import get_proxy


class BaseChecker:
ENDPOINT = ""
RATELIMIT_TIMEOUT = 0.5

def __init__(self, proxies:ProxiesTypes=None, max_workers:int=5) -> None:
self.proxies = proxies
self.max_workers = max_workers

@singledispatchmethod
def check(self) -> str|None:
"""Checks if username is available"""
"""Checks if username is available."""
raise NotImplementedError

@check.register
def _(self, usernames:list) -> list[str]:
with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_workers) as executor:
futures = {executor.submit(self.check, username): username for username in usernames}
r = []
for future in concurrent.futures.as_completed(futures):
r.append(future.result())
r = filter(lambda item: item is not None, r)

return r
def get_proxy(self, proxy_path:str) -> dict:
"""Returns a valid proxy."""
if len(proxy_path) == 0:
return {}
return get_proxy(proxy_path)
12 changes: 7 additions & 5 deletions src/checkers/beacons-ai.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ class Checker(BaseChecker):
ENDPOINT = "https://account.beacons.ai/api/user_profile"

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

if len(username) > 30:
return None
elif username.startswith(".") or username.endswith(".") or ".." in username:
Expand All @@ -21,15 +23,15 @@ def _(self, username:str) -> str|None:
return None
elif not all(c.isalnum() and c.isascii() or c in "_." for c in username):
return None

headers = {"X-Beacons-Application-Viewed": "web", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0"}
payload = {"new_username": username, "action": "is_username_taken"}

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.post(self.ENDPOINT, json=payload, headers=headers)
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.json()["username_taken"] == False else None

return username if r.json()["username_taken"] is False else None
10 changes: 6 additions & 4 deletions src/checkers/chess-com.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ class Checker(BaseChecker):
ENDPOINT = "https://www.chess.com/callback/user/valid?username="

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.get(f"{self.ENDPOINT}{username}")
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.json()["valid"] else None

return username if r.json()["valid"] else None
12 changes: 7 additions & 5 deletions src/checkers/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,21 @@ class Checker(BaseChecker):
ENDPOINT = "https://github.com/"

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

if len(username) > 39:
return None
elif username.startswith("-") or username.endswith("-") or "--" in username:
return None
elif not all(c.isalnum() and c.isascii() or c in "-" for c in username):
return None

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.get(f"{self.ENDPOINT}{username}")
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.status_code == 404 else None

return username if r.status_code == 404 else None
10 changes: 6 additions & 4 deletions src/checkers/gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ class Checker(BaseChecker):
ENDPOINT = "https://gitlab.com/users/"

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.get(f"{self.ENDPOINT}{username}/exists")
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.json()["exists"] == False else None

return username if r.json()["exists"] is False else None
12 changes: 7 additions & 5 deletions src/checkers/instagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ class Checker(BaseChecker):
ENDPOINT = "https://www.instagram.com/api/v1/web/accounts/web_create_ajax/attempt/"

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

headers = {"X-CSRFToken": "en"}
payload = {"email": "", "username": username, "first_name": "", "opt_into_one_tap": False}

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.post(self.ENDPOINT, data=payload, headers=headers)
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if not "\"username\": [{\"message\": " in r.text else None

return username if not "\"username\": [{\"message\": " in r.text else None
10 changes: 6 additions & 4 deletions src/checkers/kahoot.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ class Checker(BaseChecker):
ENDPOINT = "https://create.kahoot.it/rest/users/usernameavailable"

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

headers={"x-kahoot-user-identifier": username}

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.get(self.ENDPOINT, headers=headers)
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.json().get("isUsernameAvailable") else None

return username if r.json().get("isUsernameAvailable") else None
10 changes: 6 additions & 4 deletions src/checkers/lichess.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ class Checker(BaseChecker):
ENDPOINT = "https://lichess.org/api/player/autocomplete?term="

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

payload = f"{username}&exists=1"

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.get(f"{self.ENDPOINT}{payload}")
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.json() == False else None

return username if r.json() is False else None
10 changes: 6 additions & 4 deletions src/checkers/linktree.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ class Checker(BaseChecker):
ENDPOINT = "https://linktr.ee/validate/username"

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0"}
payload = {"username": username, "returnSuggestions": False}

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.post(self.ENDPOINT, json=payload, headers=headers)
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.json()["result"] == "success" else None

return username if r.json()["result"] == "success" else None
10 changes: 6 additions & 4 deletions src/checkers/minecraft.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ class Checker(BaseChecker):
ENDPOINT = "https://api.mojang.com/users/profiles/minecraft/"

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.head(f"{self.ENDPOINT}{username}")
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.status_code == 404 else None

return username if r.status_code == 404 else None
12 changes: 7 additions & 5 deletions src/checkers/replit.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ class Checker(BaseChecker):
ENDPOINT = "https://replit.com/@"

@BaseChecker.check.register
def _(self, username:str) -> str|None:
if not (2 < len(username) <= 15):
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

if not 2 < len(username) <= 15:
return None
elif "--" in username:
return None
Expand All @@ -22,9 +24,9 @@ def _(self, username:str) -> str|None:

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.head(f"{self.ENDPOINT}{username}")
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.status_code == 404 else None

return username if r.status_code == 404 else None
10 changes: 6 additions & 4 deletions src/checkers/roblox.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ class Checker(BaseChecker):
ENDPOINT = "https://auth.roblox.com/v1/usernames/validate?birthday=2000-01-01T00:00:00.000Z&context=Signup&username="

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.get(f"{self.ENDPOINT}{username}")
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.json()['code'] == 0 else None

return username if r.json()['code'] == 0 else None
12 changes: 7 additions & 5 deletions src/checkers/solo-to.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,23 @@ class Checker(BaseChecker):
ENDPOINT = "https://api.solo.to/"

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

if not (1 < len(username) <= 20):
return None
elif username.endswith(".") or username.endswith(".") or ".." in username:
return None
elif not all(c.isalnum() and c.isascii() or c in "-_." for c in username):
return None

headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0"}

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.get(f"{self.ENDPOINT}{username}", headers=headers)
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if "page not found" in r.text else None

return username if "page not found" in r.text else None
12 changes: 7 additions & 5 deletions src/checkers/soundcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ class Checker(BaseChecker):
ENDPOINT = "https://soundcloud.com/"

@BaseChecker.check.register
def _(self, username:str) -> str|None:
if not (3 < len(username) <= 25):
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

if not 3 < len(username) <= 25:
return None
elif username.startswith("-") or username.startswith("_"):
return None
Expand All @@ -24,9 +26,9 @@ def _(self, username:str) -> str|None:

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.head(f"{self.ENDPOINT}{username}")
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.status_code == 404 else None

return username if r.status_code == 404 else None
12 changes: 7 additions & 5 deletions src/checkers/speedrun-com.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ class Checker(BaseChecker):
ENDPOINT = "https://www.speedrun.com/api/v2/PutAuthSignup"

@BaseChecker.check.register
def _(self, username:str) -> str|None:
def _(self, username:str, proxies:str="") -> str|None:
proxies = self.get_proxy(proxies)

payload = {"areaId": "", "email": "email@example.com", "name": username, "password": "realpassword123"}

r = Response(429)
while r.status_code == 429:
with httpx.Client(verify=False, proxies=self.proxies) as client:
with httpx.Client(verify=False, proxies=proxies) as client:
r = client.post(self.ENDPOINT, json=payload)
if r.status_code == 429:
time.sleep(self.RATELIMIT_TIMEOUT)
return username if r.status_code == 200 else None

return username if r.status_code == 200 else None
Loading

0 comments on commit ea4aff9

Please sign in to comment.