user-scanner 1.0.5.0__py3-none-any.whl → 1.0.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- user_scanner/__init__.py +0 -1
- user_scanner/__main__.py +73 -49
- user_scanner/cli/banner.py +2 -0
- user_scanner/community/coderlegion.py +15 -14
- user_scanner/core/orchestrator.py +69 -31
- user_scanner/creator/devto.py +13 -11
- user_scanner/creator/hashnode.py +19 -17
- user_scanner/creator/itch_io.py +12 -10
- user_scanner/creator/kaggle.py +12 -11
- user_scanner/creator/medium.py +11 -10
- user_scanner/creator/patreon.py +17 -15
- user_scanner/creator/producthunt.py +16 -14
- user_scanner/dev/codeberg.py +13 -11
- user_scanner/dev/cratesio.py +19 -17
- user_scanner/dev/dockerhub.py +17 -15
- user_scanner/dev/github.py +26 -24
- user_scanner/dev/gitlab.py +14 -12
- user_scanner/dev/launchpad.py +19 -17
- user_scanner/dev/npmjs.py +22 -19
- user_scanner/dev/replit.py +13 -11
- user_scanner/donation/buymeacoffee.py +11 -10
- user_scanner/donation/liberapay.py +36 -0
- user_scanner/gaming/chess_com.py +20 -18
- user_scanner/gaming/minecraft.py +24 -0
- user_scanner/gaming/monkeytype.py +4 -3
- user_scanner/gaming/osu.py +14 -12
- user_scanner/gaming/roblox.py +20 -16
- user_scanner/gaming/steam.py +12 -10
- user_scanner/social/bluesky.py +20 -18
- user_scanner/social/discord.py +12 -13
- user_scanner/social/instagram.py +22 -20
- user_scanner/social/mastodon.py +17 -15
- user_scanner/social/pinterest.py +13 -11
- user_scanner/social/reddit.py +13 -11
- user_scanner/social/snapchat.py +28 -26
- user_scanner/social/telegram.py +13 -11
- user_scanner/social/threads.py +23 -21
- user_scanner/social/x.py +14 -12
- user_scanner/social/youtube.py +37 -34
- user_scanner/utils/update.py +0 -0
- user_scanner/utils/version.py +2 -0
- user_scanner/version.json +1 -1
- {user_scanner-1.0.5.0.dist-info → user_scanner-1.0.7.0.dist-info}/METADATA +24 -7
- user_scanner-1.0.7.0.dist-info/RECORD +55 -0
- user_scanner-1.0.5.0.dist-info/RECORD +0 -52
- {user_scanner-1.0.5.0.dist-info → user_scanner-1.0.7.0.dist-info}/WHEEL +0 -0
- {user_scanner-1.0.5.0.dist-info → user_scanner-1.0.7.0.dist-info}/entry_points.txt +0 -0
- {user_scanner-1.0.5.0.dist-info → user_scanner-1.0.7.0.dist-info}/licenses/LICENSE +0 -0
user_scanner/__init__.py
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
user_scanner/__main__.py
CHANGED
|
@@ -1,40 +1,27 @@
|
|
|
1
1
|
import argparse
|
|
2
|
+
import time
|
|
2
3
|
import re
|
|
3
|
-
from user_scanner.core.orchestrator import run_checks, load_modules
|
|
4
|
+
from user_scanner.core.orchestrator import run_checks, load_modules , generate_permutations, load_categories
|
|
4
5
|
from colorama import Fore, Style
|
|
5
6
|
from .cli import banner
|
|
6
7
|
from .cli.banner import print_banner
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
"dev": "dev",
|
|
10
|
-
"social": "social",
|
|
11
|
-
"creator": "creator",
|
|
12
|
-
"community": "community",
|
|
13
|
-
"gaming": "gaming",
|
|
14
|
-
"donation": "donation"
|
|
15
|
-
}
|
|
9
|
+
MAX_PERMUTATIONS_LIMIT = 100 # To prevent excessive generation
|
|
16
10
|
|
|
17
11
|
def list_modules(category=None):
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"dev": dev,
|
|
21
|
-
"social": social,
|
|
22
|
-
"creator": creator,
|
|
23
|
-
"community": community,
|
|
24
|
-
"gaming": gaming,
|
|
25
|
-
"donation": donation
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
categories_to_list = [category] if category else packages.keys()
|
|
12
|
+
categories = load_categories()
|
|
13
|
+
categories_to_list = [category] if category else categories.keys()
|
|
29
14
|
|
|
30
15
|
for cat_name in categories_to_list:
|
|
31
|
-
|
|
32
|
-
modules = load_modules(
|
|
33
|
-
print(Fore.MAGENTA +
|
|
16
|
+
path = categories[cat_name]
|
|
17
|
+
modules = load_modules(path)
|
|
18
|
+
print(Fore.MAGENTA +
|
|
19
|
+
f"\n== {cat_name.upper()} SITES =={Style.RESET_ALL}")
|
|
34
20
|
for module in modules:
|
|
35
21
|
site_name = module.__name__.split(".")[-1]
|
|
36
22
|
print(f" - {site_name}")
|
|
37
23
|
|
|
24
|
+
|
|
38
25
|
def main():
|
|
39
26
|
parser = argparse.ArgumentParser(
|
|
40
27
|
prog="user-scanner",
|
|
@@ -44,7 +31,7 @@ def main():
|
|
|
44
31
|
"-u", "--username", help="Username to scan across platforms"
|
|
45
32
|
)
|
|
46
33
|
parser.add_argument(
|
|
47
|
-
"-c", "--category", choices=
|
|
34
|
+
"-c", "--category", choices=load_categories().keys(),
|
|
48
35
|
help="Scan all platforms in a category"
|
|
49
36
|
)
|
|
50
37
|
parser.add_argument(
|
|
@@ -56,55 +43,92 @@ def main():
|
|
|
56
43
|
parser.add_argument(
|
|
57
44
|
"-v", "--verbose", action="store_true", help="Enable verbose output"
|
|
58
45
|
)
|
|
59
|
-
|
|
46
|
+
|
|
47
|
+
parser.add_argument(
|
|
48
|
+
"-p", "--permute",type=str,help="Generate username permutations using a string pattern (e.g -p 234)"
|
|
49
|
+
)
|
|
50
|
+
parser.add_argument(
|
|
51
|
+
"-s", "--stop",type=int,default=MAX_PERMUTATIONS_LIMIT,help="Limit the number of username permutations generated"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
parser.add_argument(
|
|
55
|
+
"-d", "--delay",type=float,default=0,help="Delay in seconds between requests (recommended: 1-2 seconds)"
|
|
56
|
+
)
|
|
57
|
+
|
|
60
58
|
args = parser.parse_args()
|
|
61
|
-
|
|
62
|
-
if args.module and "." in args.module:
|
|
63
|
-
args.module = args.module.replace(".", "_")
|
|
64
|
-
|
|
59
|
+
|
|
65
60
|
if args.list:
|
|
66
61
|
list_modules(args.category)
|
|
67
62
|
return
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
|
|
64
|
+
if not args.username:
|
|
65
|
+
parser.print_help()
|
|
66
|
+
return
|
|
67
|
+
|
|
70
68
|
# Special username checks before run
|
|
71
69
|
if (args.module == "x" or args.category == "social"):
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
if re.search(r"[^a-zA-Z0-9._-]", args.username):
|
|
71
|
+
print(
|
|
72
|
+
Fore.RED + f"[!] Username '{args.username}' contains unsupported special characters. X (Twitter) doesn't support these." + Style.RESET_ALL)
|
|
74
73
|
if (args.module == "bluesky" or args.category == "social"):
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return
|
|
80
|
-
else:
|
|
81
|
-
print_banner()
|
|
74
|
+
if re.search(r"[^a-zA-Z0-9\.-]", args.username):
|
|
75
|
+
print(
|
|
76
|
+
Fore.RED + f"[!] Username '{args.username}' contains unsupported special characters. Bluesky will throw error. (Supported: only hyphens and digits)" + Style.RESET_ALL + "\n")
|
|
77
|
+
print_banner()
|
|
82
78
|
|
|
79
|
+
if args.permute and args.delay == 0:
|
|
80
|
+
print(
|
|
81
|
+
Fore.YELLOW
|
|
82
|
+
+ "[!] Warning: You're generating multiple usernames with NO delay between requests. "
|
|
83
|
+
"This may trigger rate limits or IP bans. Use --delay 1 or higher. (Use only if the sites throw errors otherwise ignore)\n"
|
|
84
|
+
+ Style.RESET_ALL)
|
|
85
|
+
|
|
86
|
+
usernames = [args.username] # Default single username list
|
|
87
|
+
|
|
88
|
+
#Added permutation support , generate all possible permutation of given sequence.
|
|
89
|
+
if args.permute:
|
|
90
|
+
usernames = generate_permutations(args.username, args.permute , args.stop)
|
|
91
|
+
print(Fore.CYAN + f"[+] Generated {len(usernames)} username permutations" + Style.RESET_ALL)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
if args.module and "." in args.module:
|
|
96
|
+
args.module = args.module.replace(".", "_")
|
|
83
97
|
|
|
84
|
-
from user_scanner import dev, social, creator, community, gaming, donation
|
|
85
98
|
|
|
86
99
|
if args.module:
|
|
87
100
|
# Single module search across all categories
|
|
88
|
-
packages = [dev, social, creator, community, gaming, donation]
|
|
89
101
|
found = False
|
|
90
|
-
for
|
|
91
|
-
modules = load_modules(
|
|
102
|
+
for cat_path in load_categories().values():
|
|
103
|
+
modules = load_modules(cat_path)
|
|
92
104
|
for module in modules:
|
|
93
105
|
site_name = module.__name__.split(".")[-1]
|
|
94
106
|
if site_name.lower() == args.module.lower():
|
|
95
107
|
from user_scanner.core.orchestrator import run_module_single
|
|
96
|
-
|
|
108
|
+
for name in usernames: # <-- permutation support here
|
|
109
|
+
run_module_single(module, name)
|
|
110
|
+
if args.delay > 0:
|
|
111
|
+
time.sleep(args.delay)
|
|
97
112
|
found = True
|
|
98
113
|
if not found:
|
|
99
|
-
print(
|
|
114
|
+
print(
|
|
115
|
+
Fore.RED + f"[!] Module '{args.module}' not found in any category." + Style.RESET_ALL)
|
|
100
116
|
elif args.category:
|
|
101
117
|
# Category-wise scan
|
|
102
|
-
category_package =
|
|
118
|
+
category_package = load_categories().get(args.category)
|
|
103
119
|
from user_scanner.core.orchestrator import run_checks_category
|
|
104
|
-
|
|
120
|
+
|
|
121
|
+
for name in usernames: # <-- permutation support here
|
|
122
|
+
run_checks_category(category_package, name, args.verbose)
|
|
123
|
+
if args.delay > 0:
|
|
124
|
+
time.sleep(args.delay)
|
|
105
125
|
else:
|
|
106
126
|
# Full scan
|
|
107
|
-
|
|
127
|
+
for name in usernames:
|
|
128
|
+
run_checks(name)
|
|
129
|
+
if args.delay > 0:
|
|
130
|
+
time.sleep(args.delay)
|
|
131
|
+
|
|
108
132
|
|
|
109
133
|
if __name__ == "__main__":
|
|
110
134
|
main()
|
user_scanner/cli/banner.py
CHANGED
|
@@ -23,10 +23,12 @@ INFO_BOX = f"""{C_MAGENTA} ╔═══════════════
|
|
|
23
23
|
║ {C_RED}♚ {C_GREEN}Email{C_WHITE} : kaifcodec@gmail.com {C_MAGENTA}║
|
|
24
24
|
══════════════════════════════════════════{Style.RESET_ALL}""".strip()
|
|
25
25
|
|
|
26
|
+
|
|
26
27
|
def print_banner():
|
|
27
28
|
print(BANNER_ASCII)
|
|
28
29
|
print(INFO_BOX)
|
|
29
30
|
print(" ")
|
|
30
31
|
|
|
32
|
+
|
|
31
33
|
if __name__ == "__main__":
|
|
32
34
|
print_banner()
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
from
|
|
1
|
+
from user_scanner.core.orchestrator import status_validate
|
|
2
2
|
|
|
3
|
-
def validate_coderlegion(user):
|
|
4
|
-
url = f"https://coderlegion.com/user/{user}"
|
|
5
|
-
|
|
6
|
-
return status_validate(url, 404, 200, timeout = 15.0)
|
|
7
3
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
def validate_coderlegion(user):
|
|
5
|
+
url = f"https://coderlegion.com/user/{user}"
|
|
6
|
+
|
|
7
|
+
return status_validate(url, 404, 200, timeout=15.0)
|
|
11
8
|
|
|
12
|
-
if result == 1:
|
|
13
|
-
print("Available!")
|
|
14
|
-
elif result == 0:
|
|
15
|
-
print("Unavailable!")
|
|
16
|
-
else:
|
|
17
|
-
print("Error occured!")
|
|
18
9
|
|
|
10
|
+
if __name__ == "__main__":
|
|
11
|
+
user = input("Username?: ").strip()
|
|
12
|
+
result = validate_coderlegion(user)
|
|
13
|
+
|
|
14
|
+
if result == 1:
|
|
15
|
+
print("Available!")
|
|
16
|
+
elif result == 0:
|
|
17
|
+
print("Unavailable!")
|
|
18
|
+
else:
|
|
19
|
+
print("Error occured!")
|
|
@@ -2,31 +2,50 @@ import importlib
|
|
|
2
2
|
import pkgutil
|
|
3
3
|
from colorama import Fore, Style
|
|
4
4
|
import threading
|
|
5
|
-
|
|
5
|
+
from itertools import permutations
|
|
6
6
|
import httpx
|
|
7
7
|
from httpx import ConnectError, TimeoutException
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Dict
|
|
8
10
|
|
|
9
11
|
lock = threading.Condition()
|
|
10
|
-
#Basically which thread is the one to print
|
|
12
|
+
# Basically which thread is the one to print
|
|
11
13
|
print_queue = 0
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
|
|
16
|
+
def load_categories() -> Dict[str, Path]:
|
|
17
|
+
root = Path(__file__).resolve().parent.parent # Should be user_scanner
|
|
18
|
+
categories = {}
|
|
19
|
+
|
|
20
|
+
for subfolder in root.iterdir():
|
|
21
|
+
if subfolder.is_dir() and \
|
|
22
|
+
not subfolder.name.lower() in ["cli", "utils", "core"] and \
|
|
23
|
+
not "__" in subfolder.name: # Removes __pycache__
|
|
24
|
+
categories[subfolder.name] = subfolder.resolve()
|
|
25
|
+
|
|
26
|
+
return categories
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def load_modules(category_path: Path):
|
|
14
30
|
|
|
15
31
|
modules = []
|
|
16
|
-
for
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
32
|
+
for file in category_path.glob("*.py"):
|
|
33
|
+
if file.name == "__init__.py":
|
|
34
|
+
continue
|
|
35
|
+
spec = importlib.util.spec_from_file_location(file.stem, str(file))
|
|
36
|
+
module = importlib.util.module_from_spec(spec)
|
|
37
|
+
spec.loader.exec_module(module)
|
|
38
|
+
|
|
39
|
+
modules.append(module)
|
|
22
40
|
return modules
|
|
23
41
|
|
|
42
|
+
|
|
24
43
|
def worker_single(module, username, i):
|
|
25
44
|
global print_queue
|
|
26
45
|
|
|
27
46
|
func = next((getattr(module, f) for f in dir(module)
|
|
28
47
|
if f.startswith("validate_") and callable(getattr(module, f))), None)
|
|
29
|
-
site_name = module.__name__.split('.')[-1].capitalize().replace("_",".")
|
|
48
|
+
site_name = module.__name__.split('.')[-1].capitalize().replace("_", ".")
|
|
30
49
|
if site_name == "X":
|
|
31
50
|
site_name = "X (Twitter)"
|
|
32
51
|
|
|
@@ -35,18 +54,18 @@ def worker_single(module, username, i):
|
|
|
35
54
|
try:
|
|
36
55
|
result = func(username)
|
|
37
56
|
if result == 1:
|
|
38
|
-
output = f" {Fore.GREEN}[✔] {site_name}: Available{Style.RESET_ALL}"
|
|
57
|
+
output = f" {Fore.GREEN}[✔] {site_name} ({username}): Available{Style.RESET_ALL}"
|
|
39
58
|
elif result == 0:
|
|
40
|
-
output = f" {Fore.RED}[✘] {site_name}: Taken{Style.RESET_ALL}"
|
|
59
|
+
output = f" {Fore.RED}[✘] {site_name} ({username}): Taken{Style.RESET_ALL}"
|
|
41
60
|
else:
|
|
42
|
-
output = f" {Fore.YELLOW}[!] {site_name}: Error{Style.RESET_ALL}"
|
|
61
|
+
output = f" {Fore.YELLOW}[!] {site_name} ({username}): Error{Style.RESET_ALL}"
|
|
43
62
|
except Exception as e:
|
|
44
63
|
output = f" {Fore.YELLOW}[!] {site_name}: Exception - {e}{Style.RESET_ALL}"
|
|
45
64
|
else:
|
|
46
65
|
output = f" {Fore.YELLOW}[!] {site_name} has no validate_ function{Style.RESET_ALL}"
|
|
47
66
|
|
|
48
67
|
with lock:
|
|
49
|
-
#Waits for in-order printing
|
|
68
|
+
# Waits for in-order printing
|
|
50
69
|
while i != print_queue:
|
|
51
70
|
lock.wait()
|
|
52
71
|
|
|
@@ -54,15 +73,17 @@ def worker_single(module, username, i):
|
|
|
54
73
|
print_queue += 1
|
|
55
74
|
lock.notify_all()
|
|
56
75
|
|
|
76
|
+
|
|
57
77
|
def run_module_single(module, username):
|
|
58
|
-
#Just executes as if it was a thread
|
|
78
|
+
# Just executes as if it was a thread
|
|
59
79
|
worker_single(module, username, print_queue)
|
|
60
|
-
|
|
61
|
-
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def run_checks_category(category_path:Path, username:str, verbose=False):
|
|
62
83
|
global print_queue
|
|
63
|
-
|
|
64
|
-
modules = load_modules(
|
|
65
|
-
category_name =
|
|
84
|
+
|
|
85
|
+
modules = load_modules(category_path)
|
|
86
|
+
category_name = category_path.stem.capitalize()
|
|
66
87
|
print(f"{Fore.MAGENTA}== {category_name} SITES =={Style.RESET_ALL}")
|
|
67
88
|
|
|
68
89
|
print_queue = 0
|
|
@@ -76,17 +97,15 @@ def run_checks_category(package, username, verbose=False):
|
|
|
76
97
|
for t in threads:
|
|
77
98
|
t.join()
|
|
78
99
|
|
|
79
|
-
def run_checks(username):
|
|
80
|
-
from user_scanner import dev, social, creator, community, gaming, donation
|
|
81
|
-
|
|
82
|
-
packages = [dev, social, creator, community, gaming, donation]
|
|
83
100
|
|
|
101
|
+
def run_checks(username):
|
|
84
102
|
print(f"\n{Fore.CYAN} Checking username: {username}{Style.RESET_ALL}\n")
|
|
85
103
|
|
|
86
|
-
for
|
|
87
|
-
run_checks_category(
|
|
104
|
+
for category_path in load_categories().values():
|
|
105
|
+
run_checks_category(category_path, username)
|
|
88
106
|
print()
|
|
89
107
|
|
|
108
|
+
|
|
90
109
|
def make_get_request(url, **kwargs):
|
|
91
110
|
"""Simple wrapper to **httpx.get** that predefines headers and timeout"""
|
|
92
111
|
if not "headers" in kwargs:
|
|
@@ -103,6 +122,7 @@ def make_get_request(url, **kwargs):
|
|
|
103
122
|
|
|
104
123
|
return httpx.get(url, **kwargs)
|
|
105
124
|
|
|
125
|
+
|
|
106
126
|
def generic_validate(url, func, **kwargs):
|
|
107
127
|
"""
|
|
108
128
|
A generic validate function that makes a request and executes the provided function on the response.
|
|
@@ -114,7 +134,8 @@ def generic_validate(url, func, **kwargs):
|
|
|
114
134
|
return 2
|
|
115
135
|
except Exception:
|
|
116
136
|
return 2
|
|
117
|
-
|
|
137
|
+
|
|
138
|
+
|
|
118
139
|
def status_validate(url, available, taken, **kwargs):
|
|
119
140
|
"""
|
|
120
141
|
Function that takes a **url** and **kwargs** for the request and
|
|
@@ -122,15 +143,14 @@ def status_validate(url, available, taken, **kwargs):
|
|
|
122
143
|
**Available** and **Taken** must either be whole numbers or lists of whole numbers.
|
|
123
144
|
"""
|
|
124
145
|
def inner(response):
|
|
125
|
-
#Checks if a number is equal or is contained inside
|
|
126
|
-
contains
|
|
127
|
-
|
|
146
|
+
# Checks if a number is equal or is contained inside
|
|
147
|
+
def contains(a, b): return (isinstance(a, list) and b in a) or (a == b)
|
|
128
148
|
status = response.status_code
|
|
129
149
|
available_value = contains(available, status)
|
|
130
150
|
taken_value = contains(taken, status)
|
|
131
151
|
|
|
132
152
|
if available_value and taken_value:
|
|
133
|
-
return 2
|
|
153
|
+
return 2 # Can't be both available and taken
|
|
134
154
|
elif available_value:
|
|
135
155
|
return 1
|
|
136
156
|
elif taken_value:
|
|
@@ -138,3 +158,21 @@ def status_validate(url, available, taken, **kwargs):
|
|
|
138
158
|
return 2
|
|
139
159
|
|
|
140
160
|
return generic_validate(url, inner, **kwargs)
|
|
161
|
+
|
|
162
|
+
def generate_permutations(username, pattern, limit=None):
|
|
163
|
+
"""
|
|
164
|
+
Generate all order-based permutations of characters in `pattern`
|
|
165
|
+
appended after `username`.
|
|
166
|
+
"""
|
|
167
|
+
permutations_set = {username}
|
|
168
|
+
|
|
169
|
+
chars = list(pattern)
|
|
170
|
+
|
|
171
|
+
# generate permutations of length 1 → len(chars)
|
|
172
|
+
for r in range(1, len(chars) + 1):
|
|
173
|
+
for combo in permutations(chars, r):
|
|
174
|
+
permutations_set.add(username + ''.join(combo))
|
|
175
|
+
if limit and len(permutations_set) >= limit:
|
|
176
|
+
return list(permutations_set)[:limit]
|
|
177
|
+
|
|
178
|
+
return sorted(permutations_set)
|
user_scanner/creator/devto.py
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
from
|
|
1
|
+
from user_scanner.core.orchestrator import status_validate
|
|
2
|
+
|
|
2
3
|
|
|
3
4
|
def validate_devto(user):
|
|
4
|
-
|
|
5
|
+
url = f"https://dev.to/{user}"
|
|
6
|
+
|
|
7
|
+
return status_validate(url, 404, 200, follow_redirects=True)
|
|
5
8
|
|
|
6
|
-
return status_validate(url, 404, 200, follow_redirects = True)
|
|
7
9
|
|
|
8
10
|
if __name__ == "__main__":
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
user = input("Username?: ").strip()
|
|
12
|
+
result = validate_devto(user)
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
if result == 1:
|
|
15
|
+
print("Available!")
|
|
16
|
+
elif result == 0:
|
|
17
|
+
print("Unavailable!")
|
|
18
|
+
else:
|
|
19
|
+
print("Error occurred!")
|
user_scanner/creator/hashnode.py
CHANGED
|
@@ -2,20 +2,21 @@ import httpx
|
|
|
2
2
|
import json
|
|
3
3
|
from httpx import ConnectError, TimeoutException
|
|
4
4
|
|
|
5
|
+
|
|
5
6
|
def validate_hashnode(user):
|
|
6
7
|
url = "https://hashnode.com/utility/ajax/check-username"
|
|
7
8
|
|
|
8
9
|
payload = {
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
"username": user,
|
|
11
|
+
"name": "Dummy Dummy"
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
headers = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
'User-Agent': "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Mobile Safari/537.36",
|
|
16
|
+
'Accept': "application/json",
|
|
17
|
+
'Content-Type': "application/json",
|
|
18
|
+
'Origin': "https://hashnode.com",
|
|
19
|
+
'Referer': "https://hashnode.com/signup",
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
try:
|
|
@@ -33,7 +34,7 @@ def validate_hashnode(user):
|
|
|
33
34
|
return 2
|
|
34
35
|
|
|
35
36
|
else:
|
|
36
|
-
|
|
37
|
+
return 2
|
|
37
38
|
|
|
38
39
|
except (ConnectError, TimeoutException):
|
|
39
40
|
return 2
|
|
@@ -42,13 +43,14 @@ def validate_hashnode(user):
|
|
|
42
43
|
except Exception:
|
|
43
44
|
return 2
|
|
44
45
|
|
|
46
|
+
|
|
45
47
|
if __name__ == "__main__":
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
user = input("Username?: ").strip()
|
|
49
|
+
result = validate_hashnode(user)
|
|
50
|
+
|
|
51
|
+
if result == 1:
|
|
52
|
+
print("Available!")
|
|
53
|
+
elif result == 0:
|
|
54
|
+
print("Unavailable!")
|
|
55
|
+
else:
|
|
56
|
+
print("Error occurred!")
|
user_scanner/creator/itch_io.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from user_scanner.core.orchestrator import status_validate
|
|
2
|
+
|
|
2
3
|
|
|
3
4
|
def validate_itch_io(user):
|
|
4
5
|
"""
|
|
@@ -8,15 +9,16 @@ def validate_itch_io(user):
|
|
|
8
9
|
|
|
9
10
|
url = f"https://{user}.itch.io"
|
|
10
11
|
|
|
11
|
-
return
|
|
12
|
+
return status_validate(url, 404, 200, follow_redirects=True)
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
if __name__ == "__main__":
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
user = input("Username?: ").strip()
|
|
17
|
+
result = validate_itch_io(user)
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
if result == 1:
|
|
20
|
+
print("Available!")
|
|
21
|
+
elif result == 0:
|
|
22
|
+
print("Unavailable!")
|
|
23
|
+
else:
|
|
24
|
+
print("Error occurred!")
|
user_scanner/creator/kaggle.py
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
from
|
|
1
|
+
from user_scanner.core.orchestrator import status_validate
|
|
2
|
+
|
|
2
3
|
|
|
3
4
|
def validate_kaggle(user):
|
|
4
|
-
|
|
5
|
+
url = f"https://www.kaggle.com/{user}"
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
return status_validate(url, 404, 200, follow_redirects=True)
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
if __name__ == "__main__":
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
user = input("Username?: ").strip()
|
|
12
|
+
result = validate_kaggle(user)
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
if result == 1:
|
|
15
|
+
print("Available!")
|
|
16
|
+
elif result == 0:
|
|
17
|
+
print("Unavailable!")
|
|
18
|
+
else:
|
|
19
|
+
print("Error occurred!")
|
user_scanner/creator/medium.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import httpx
|
|
2
2
|
from httpx import ConnectError, TimeoutException
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
def validate_medium(user):
|
|
5
6
|
url = f"https://medium.com/@{user}"
|
|
6
7
|
|
|
@@ -15,7 +16,6 @@ def validate_medium(user):
|
|
|
15
16
|
if response.status_code == 200:
|
|
16
17
|
html_text = response.text
|
|
17
18
|
|
|
18
|
-
|
|
19
19
|
username_tag = f'property="profile:username" content="{user}"'
|
|
20
20
|
|
|
21
21
|
if username_tag in html_text:
|
|
@@ -29,13 +29,14 @@ def validate_medium(user):
|
|
|
29
29
|
except Exception:
|
|
30
30
|
return 2
|
|
31
31
|
|
|
32
|
+
|
|
32
33
|
if __name__ == "__main__":
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
user = input("Username?: ").strip()
|
|
35
|
+
result = validate_medium(user)
|
|
36
|
+
|
|
37
|
+
if result == 1:
|
|
38
|
+
print("Available!")
|
|
39
|
+
elif result == 0:
|
|
40
|
+
print("Unavailable!")
|
|
41
|
+
else:
|
|
42
|
+
print("Error occurred!")
|
user_scanner/creator/patreon.py
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
from
|
|
1
|
+
from user_scanner.core.orchestrator import status_validate
|
|
2
|
+
|
|
2
3
|
|
|
3
4
|
def validate_patreon(user):
|
|
4
5
|
url = f"https://www.patreon.com/{user}"
|
|
5
6
|
|
|
6
|
-
return status_validate(url, 404, 200, timeout
|
|
7
|
+
return status_validate(url, 404, 200, timeout=15.0, follow_redirects=True)
|
|
8
|
+
|
|
7
9
|
|
|
8
10
|
if __name__ == "__main__":
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
try:
|
|
12
|
+
import httpx
|
|
13
|
+
except ImportError:
|
|
14
|
+
print("Error: 'httpx' library is not installed.")
|
|
15
|
+
exit()
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
user = input("Username?: ").strip()
|
|
18
|
+
result = validate_patreon(user)
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
if result == 1:
|
|
21
|
+
print("Available!")
|
|
22
|
+
elif result == 0:
|
|
23
|
+
print("Unavailable!")
|
|
24
|
+
else:
|
|
25
|
+
print("Error occured!")
|