user-scanner 1.0.0.3__py3-none-any.whl → 1.0.2.1__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 +1 -0
- user_scanner/__main__.py +24 -10
- user_scanner/cli/__init__.py +0 -0
- user_scanner/cli/banner.py +39 -0
- user_scanner/community/coderlegion.py +39 -0
- user_scanner/core/orchestrator.py +3 -2
- user_scanner/creator/kaggle.py +0 -4
- user_scanner/creator/patreon.py +45 -0
- user_scanner/gaming/__init__.py +0 -0
- user_scanner/gaming/chess_com.py +54 -0
- user_scanner/gaming/monkeytype.py +63 -0
- user_scanner/gaming/osu.py +44 -0
- user_scanner/gaming/roblox.py +48 -0
- user_scanner/social/bluesky.py +71 -0
- user_scanner/social/discord.py +44 -0
- user_scanner/social/instagram.py +2 -8
- user_scanner/social/mastodon.py +45 -0
- user_scanner/social/pinterest.py +0 -6
- user_scanner/social/reddit.py +0 -6
- user_scanner/social/snapchat.py +0 -6
- user_scanner/social/telegram.py +34 -0
- user_scanner/social/threads.py +0 -6
- user_scanner/social/x.py +4 -8
- user_scanner/social/youtube.py +0 -6
- user_scanner/utils/update.py +0 -0
- user_scanner/utils/version.py +20 -0
- user_scanner/version.json +4 -0
- user_scanner-1.0.2.1.dist-info/METADATA +165 -0
- user_scanner-1.0.2.1.dist-info/RECORD +48 -0
- user_scanner-1.0.0.3.dist-info/METADATA +0 -14
- user_scanner-1.0.0.3.dist-info/RECORD +0 -32
- {user_scanner-1.0.0.3.dist-info → user_scanner-1.0.2.1.dist-info}/WHEEL +0 -0
- {user_scanner-1.0.0.3.dist-info → user_scanner-1.0.2.1.dist-info}/entry_points.txt +0 -0
- {user_scanner-1.0.0.3.dist-info → user_scanner-1.0.2.1.dist-info}/licenses/LICENSE +0 -0
user_scanner/__init__.py
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
user_scanner/__main__.py
CHANGED
|
@@ -2,21 +2,26 @@ import argparse
|
|
|
2
2
|
import re
|
|
3
3
|
from user_scanner.core.orchestrator import run_checks, load_modules
|
|
4
4
|
from colorama import Fore, Style
|
|
5
|
+
from .cli import banner
|
|
6
|
+
from .cli.banner import print_banner
|
|
7
|
+
|
|
5
8
|
|
|
6
9
|
CATEGORY_MAPPING = {
|
|
7
10
|
"dev": "dev",
|
|
8
11
|
"social": "social",
|
|
9
12
|
"creator": "creator",
|
|
10
|
-
"community": "community"
|
|
13
|
+
"community": "community",
|
|
14
|
+
"gaming": "gaming"
|
|
11
15
|
}
|
|
12
16
|
|
|
13
17
|
def list_modules(category=None):
|
|
14
|
-
from user_scanner import dev, social, creator, community
|
|
18
|
+
from user_scanner import dev, social, creator, community, gaming
|
|
15
19
|
packages = {
|
|
16
20
|
"dev": dev,
|
|
17
21
|
"social": social,
|
|
18
22
|
"creator": creator,
|
|
19
|
-
"community": community
|
|
23
|
+
"community": community,
|
|
24
|
+
"gaming": gaming
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
categories_to_list = [category] if category else packages.keys()
|
|
@@ -35,7 +40,7 @@ def main():
|
|
|
35
40
|
description="Scan usernames across multiple platforms."
|
|
36
41
|
)
|
|
37
42
|
parser.add_argument(
|
|
38
|
-
"-u", "--username",
|
|
43
|
+
"-u", "--username", help="Username to scan across platforms"
|
|
39
44
|
)
|
|
40
45
|
parser.add_argument(
|
|
41
46
|
"-c", "--category", choices=CATEGORY_MAPPING.keys(),
|
|
@@ -57,17 +62,26 @@ def main():
|
|
|
57
62
|
list_modules(args.category)
|
|
58
63
|
return
|
|
59
64
|
|
|
65
|
+
|
|
66
|
+
# Special username checks before run
|
|
67
|
+
if (args.module == "x" or args.category == "social"):
|
|
68
|
+
if re.search(r"[^a-zA-Z0-9._-]", args.username):
|
|
69
|
+
print(Fore.RED + f"[!] Username '{args.username}' contains unsupported special characters. X (Twitter) doesn't support these." + Style.RESET_ALL)
|
|
70
|
+
if (args.module == "bluesky" or args.category == "social"):
|
|
71
|
+
if re.search(r"[^a-zA-Z0-9\.-]", args.username):
|
|
72
|
+
print(Fore.RED + f"[!] Username '{args.username}' contains unsupported special characters. Bluesky will throw error. (Supported: only hyphens and digits)" + Style.RESET_ALL +"\n")
|
|
60
73
|
if not args.username:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
74
|
+
parser.print_help()
|
|
75
|
+
return
|
|
76
|
+
else:
|
|
77
|
+
print_banner()
|
|
78
|
+
|
|
65
79
|
|
|
66
|
-
from user_scanner import dev, social, creator, community
|
|
80
|
+
from user_scanner import dev, social, creator, community, gaming
|
|
67
81
|
|
|
68
82
|
if args.module:
|
|
69
83
|
# Single module search across all categories
|
|
70
|
-
packages = [dev, social, creator, community]
|
|
84
|
+
packages = [dev, social, creator, community, gaming]
|
|
71
85
|
found = False
|
|
72
86
|
for package in packages:
|
|
73
87
|
modules = load_modules(package)
|
|
File without changes
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from colorama import Fore, Style, init
|
|
3
|
+
from ..utils.version import load_local_version
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
version, version_type = load_local_version()
|
|
7
|
+
init(autoreset=True)
|
|
8
|
+
C_RED = Fore.RED + Style.BRIGHT
|
|
9
|
+
C_CYAN = Fore.CYAN + Style.BRIGHT
|
|
10
|
+
C_GREEN = Fore.GREEN + Style.BRIGHT
|
|
11
|
+
C_WHITE = Fore.WHITE + Style.BRIGHT
|
|
12
|
+
C_MAGENTA = Fore.MAGENTA + Style.BRIGHT
|
|
13
|
+
BANNER_ASCII = fr"""{C_CYAN} _ _ ___ ___ _ __ ___ ___ __ _ _ __ _ __ ___ _ __
|
|
14
|
+
| | | / __|/ _ \ '__|____/ __|/ __/ _` | '_ \| '_ \ / _ \ '__|
|
|
15
|
+
| |_| \__ \ __/ | |_____\__ \ (_| (_| | | | | | | | __/ |
|
|
16
|
+
\__,_|___/\___|_| |___/\___\__,_|_| |_|_| |_|\___|_| Version: {version}
|
|
17
|
+
{Style.RESET_ALL}""".strip()
|
|
18
|
+
|
|
19
|
+
INFO_BOX = f"""{C_MAGENTA} ╔════════════════════════════════════════╗
|
|
20
|
+
║ {C_RED}♚ {C_GREEN}Project Name{C_WHITE} : UserScanner {C_MAGENTA}║
|
|
21
|
+
║ {C_RED}♚ {C_GREEN}Author{C_WHITE} : Kaif {C_MAGENTA}║
|
|
22
|
+
║ {C_RED}♚ {C_GREEN}Github{C_WHITE} : github.com/kaifcodec {C_MAGENTA}║
|
|
23
|
+
║ {C_RED}♚ {C_GREEN}Email{C_WHITE} : kaifcodec@gmail.com {C_MAGENTA}║
|
|
24
|
+
══════════════════════════════════════════{Style.RESET_ALL}""".strip()
|
|
25
|
+
|
|
26
|
+
def print_banner():
|
|
27
|
+
print(BANNER_ASCII)
|
|
28
|
+
print(INFO_BOX)
|
|
29
|
+
print(" ")
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
print_banner()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from httpx import ConnectError, TimeoutException
|
|
3
|
+
|
|
4
|
+
def validate_coderlegion(user):
|
|
5
|
+
url = f"https://coderlegion.com/user/{user}"
|
|
6
|
+
|
|
7
|
+
headers = {
|
|
8
|
+
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
|
|
9
|
+
'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
|
|
10
|
+
'Accept-Encoding': "gzip, deflate, br",
|
|
11
|
+
'Accept-Language': "en-US,en;q=0.9",
|
|
12
|
+
}
|
|
13
|
+
try:
|
|
14
|
+
response = httpx.get(url, headers=headers, timeout = 15.0)
|
|
15
|
+
status = response.status_code
|
|
16
|
+
|
|
17
|
+
if status == 200:
|
|
18
|
+
return 0
|
|
19
|
+
elif status == 404:
|
|
20
|
+
return 1
|
|
21
|
+
else:
|
|
22
|
+
return 2
|
|
23
|
+
|
|
24
|
+
except (ConnectError, TimeoutException):
|
|
25
|
+
return 2
|
|
26
|
+
except Exception:
|
|
27
|
+
return 2
|
|
28
|
+
|
|
29
|
+
if __name__ == "__main__":
|
|
30
|
+
user = input ("Username?: ").strip()
|
|
31
|
+
result = validate_coderlegion(user)
|
|
32
|
+
|
|
33
|
+
if result == 1:
|
|
34
|
+
print("Available!")
|
|
35
|
+
elif result == 0:
|
|
36
|
+
print("Unavailable!")
|
|
37
|
+
else:
|
|
38
|
+
print("Error occured!")
|
|
39
|
+
|
|
@@ -45,13 +45,14 @@ def run_checks_category(package, username, verbose=False):
|
|
|
45
45
|
|
|
46
46
|
def run_checks(username):
|
|
47
47
|
|
|
48
|
-
from user_scanner import dev, social,creator, community
|
|
48
|
+
from user_scanner import dev, social,creator, community, gaming
|
|
49
49
|
|
|
50
50
|
categories = [
|
|
51
51
|
("DEV", dev),
|
|
52
52
|
("SOCIAL", social),
|
|
53
53
|
("CREATOR", creator),
|
|
54
|
-
("COMMUNITY", community)
|
|
54
|
+
("COMMUNITY", community),
|
|
55
|
+
("GAMING", gaming)
|
|
55
56
|
]
|
|
56
57
|
|
|
57
58
|
print(f"\n{Fore.CYAN} Checking username: {username}{Style.RESET_ALL}\n")
|
user_scanner/creator/kaggle.py
CHANGED
|
@@ -10,17 +10,13 @@ def validate_kaggle(user):
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
try:
|
|
13
|
-
# Use GET request for maximum fidelity, though we only check status code
|
|
14
13
|
response = httpx.get(url, headers=headers, timeout=3.0, follow_redirects=True)
|
|
15
14
|
status = response.status_code
|
|
16
15
|
|
|
17
|
-
# If a profile exists (Taken) -> 200 OK
|
|
18
16
|
if status == 200:
|
|
19
17
|
return 0
|
|
20
|
-
# If no profile exists (Available) -> 404 Not Found
|
|
21
18
|
elif status == 404:
|
|
22
19
|
return 1
|
|
23
|
-
# Other status codes are errors
|
|
24
20
|
else:
|
|
25
21
|
return 2
|
|
26
22
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from httpx import ConnectError, TimeoutException
|
|
3
|
+
|
|
4
|
+
def validate_patreon(user):
|
|
5
|
+
url = f"https://www.patreon.com/{user}"
|
|
6
|
+
|
|
7
|
+
headers = {
|
|
8
|
+
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
|
|
9
|
+
'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
|
|
10
|
+
'Accept-Encoding': "gzip, deflate, br",
|
|
11
|
+
'Accept-Language': "en-US,en;q=0.9",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
response = httpx.get(url, headers=headers, timeout = 15.0, follow_redirects=True)
|
|
16
|
+
status = response.status_code
|
|
17
|
+
|
|
18
|
+
if status == 200:
|
|
19
|
+
return 0
|
|
20
|
+
elif status == 404:
|
|
21
|
+
return 1
|
|
22
|
+
else:
|
|
23
|
+
return 2
|
|
24
|
+
|
|
25
|
+
except (ConnectError, TimeoutException):
|
|
26
|
+
return 2
|
|
27
|
+
except Exception:
|
|
28
|
+
return 2
|
|
29
|
+
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
try:
|
|
32
|
+
import httpx
|
|
33
|
+
except ImportError:
|
|
34
|
+
print("Error: 'httpx' library is not installed.")
|
|
35
|
+
exit()
|
|
36
|
+
|
|
37
|
+
user = input ("Username?: ").strip()
|
|
38
|
+
result = validate_patreon(user)
|
|
39
|
+
|
|
40
|
+
if result == 1:
|
|
41
|
+
print("Available!")
|
|
42
|
+
elif result == 0:
|
|
43
|
+
print("Unavailable!")
|
|
44
|
+
else:
|
|
45
|
+
print("Error occured!")
|
|
File without changes
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from httpx import ConnectError, TimeoutException
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
def validate_chess_com(user):
|
|
6
|
+
url = f"https://www.chess.com/callback/user/valid?username={user}"
|
|
7
|
+
|
|
8
|
+
headers = {
|
|
9
|
+
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
|
|
10
|
+
'Accept': "application/json, text/plain, */*",
|
|
11
|
+
'Accept-Encoding': "identity",
|
|
12
|
+
'Accept-Language': "en-US,en;q=0.9",
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
response = httpx.get(url, headers=headers, timeout = 3.0)
|
|
17
|
+
status = response.status_code
|
|
18
|
+
|
|
19
|
+
if status == 200:
|
|
20
|
+
data = response.json()
|
|
21
|
+
if data.get('valid') is True:
|
|
22
|
+
# 'valid': true means the username is NOT taken
|
|
23
|
+
return 1
|
|
24
|
+
elif data.get('valid') is False:
|
|
25
|
+
# 'valid': false means the username IS taken
|
|
26
|
+
return 0
|
|
27
|
+
else:
|
|
28
|
+
return 2
|
|
29
|
+
else:
|
|
30
|
+
return 2
|
|
31
|
+
|
|
32
|
+
except (ConnectError, TimeoutException):
|
|
33
|
+
return 2
|
|
34
|
+
except json.JSONDecodeError:
|
|
35
|
+
return 2
|
|
36
|
+
except Exception:
|
|
37
|
+
return 2
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
try:
|
|
41
|
+
import httpx
|
|
42
|
+
except ImportError:
|
|
43
|
+
print("Error: 'httpx' library is not installed.")
|
|
44
|
+
exit()
|
|
45
|
+
|
|
46
|
+
user = input ("Username?: ").strip()
|
|
47
|
+
result = validate_chess_com(user)
|
|
48
|
+
|
|
49
|
+
if result == 1:
|
|
50
|
+
print("Available!")
|
|
51
|
+
elif result == 0:
|
|
52
|
+
print("Unavailable!")
|
|
53
|
+
else:
|
|
54
|
+
print("Error occured!")
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from httpx import ConnectError, TimeoutException
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
def validate_monkeytype(user: str) -> int:
|
|
6
|
+
|
|
7
|
+
url = f"https://api.monkeytype.com/users/checkName/{user}"
|
|
8
|
+
|
|
9
|
+
headers = {
|
|
10
|
+
"User-Agent": (
|
|
11
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
|
12
|
+
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
|
13
|
+
"Chrome/128.0.0.0 Safari/537.36"
|
|
14
|
+
),
|
|
15
|
+
"Accept": "application/json, text/plain, */*",
|
|
16
|
+
"Accept-Encoding": "identity",
|
|
17
|
+
"Accept-Language": "en-US,en;q=0.9",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
response = httpx.get(url, headers=headers, timeout=3.0)
|
|
22
|
+
status = response.status_code
|
|
23
|
+
|
|
24
|
+
if status == 200:
|
|
25
|
+
data = response.json()
|
|
26
|
+
# Expected shape:
|
|
27
|
+
# { "message": "string", "data": { "available": true/false } }
|
|
28
|
+
payload = data.get("data", {})
|
|
29
|
+
available = payload.get("available")
|
|
30
|
+
|
|
31
|
+
if available is True:
|
|
32
|
+
return 1
|
|
33
|
+
elif available is False:
|
|
34
|
+
return 0
|
|
35
|
+
else:
|
|
36
|
+
return 2
|
|
37
|
+
else:
|
|
38
|
+
return 2
|
|
39
|
+
|
|
40
|
+
except (ConnectError, TimeoutException):
|
|
41
|
+
return 2
|
|
42
|
+
except json.JSONDecodeError:
|
|
43
|
+
return 2
|
|
44
|
+
except Exception:
|
|
45
|
+
return 2
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
if __name__ == "__main__":
|
|
49
|
+
try:
|
|
50
|
+
import httpx # noqa: F401
|
|
51
|
+
except ImportError:
|
|
52
|
+
print("Error: 'httpx' library is not installed.")
|
|
53
|
+
raise SystemExit(1)
|
|
54
|
+
|
|
55
|
+
user = input("Username?: ").strip()
|
|
56
|
+
result = validate_monkeytype(user)
|
|
57
|
+
|
|
58
|
+
if result == 1:
|
|
59
|
+
print("Available!")
|
|
60
|
+
elif result == 0:
|
|
61
|
+
print("Unavailable!")
|
|
62
|
+
else:
|
|
63
|
+
print("Error occurred!")
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from httpx import ConnectError, TimeoutException
|
|
3
|
+
|
|
4
|
+
def validate_osu(user):
|
|
5
|
+
"""
|
|
6
|
+
Checks if a Osu username is available.
|
|
7
|
+
Returns: 1 -> available, 0 -> taken, 2 -> error
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
url = f"https://osu.ppy.sh/users/{user}"
|
|
11
|
+
|
|
12
|
+
headers = {
|
|
13
|
+
'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
|
|
14
|
+
'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
15
|
+
'Accept-Encoding': "gzip, deflate, br",
|
|
16
|
+
'Accept-Language': "en-US,en;q=0.9",
|
|
17
|
+
'sec-fetch-dest': "document",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
response = httpx.get(url, headers = headers, timeout = 5.0, follow_redirects = True)
|
|
22
|
+
status = response.status_code
|
|
23
|
+
|
|
24
|
+
if status == 200:
|
|
25
|
+
return 0
|
|
26
|
+
elif status == 404:
|
|
27
|
+
return 1
|
|
28
|
+
else:
|
|
29
|
+
return 2
|
|
30
|
+
except (ConnectError, TimeoutException):
|
|
31
|
+
return 2
|
|
32
|
+
except Exception:
|
|
33
|
+
return 2
|
|
34
|
+
|
|
35
|
+
if __name__ == "__main__":
|
|
36
|
+
user = input ("Username?: ").strip()
|
|
37
|
+
result = validate_osu(user)
|
|
38
|
+
|
|
39
|
+
if result == 1:
|
|
40
|
+
print("Available!")
|
|
41
|
+
elif result == 0:
|
|
42
|
+
print("Unavailable!")
|
|
43
|
+
else:
|
|
44
|
+
print("Error occurred!")
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from httpx import ConnectError, TimeoutException
|
|
3
|
+
|
|
4
|
+
def validate_roblox(user):
|
|
5
|
+
"""
|
|
6
|
+
Checks if a roblox username is available.
|
|
7
|
+
Returns: 1 -> available, 0 -> taken, 2 -> error
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
url = f"https://users.roblox.com/v1/users/search?keyword={user}&limit=10" # official api
|
|
11
|
+
|
|
12
|
+
headers = {
|
|
13
|
+
'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36",
|
|
14
|
+
'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
15
|
+
'Accept-Encoding': "gzip, deflate, br",
|
|
16
|
+
'Accept-Language': "en-US,en;q=0.9",
|
|
17
|
+
'sec-fetch-dest': "document",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
response = httpx.get(url, headers = headers, timeout = 5.5, follow_redirects = True)
|
|
22
|
+
status = response.status_code
|
|
23
|
+
search_results = response.json() # api response
|
|
24
|
+
|
|
25
|
+
if "errors" in search_results: # this usually triggers when timeout or ratelimit
|
|
26
|
+
return 2
|
|
27
|
+
|
|
28
|
+
for entry in search_results["data"]: # iterates through the entries in the search results
|
|
29
|
+
# .lower() so casing from the API doesn't matter
|
|
30
|
+
if entry["name"].lower() == user.lower(): # if a username matches the user
|
|
31
|
+
return 0
|
|
32
|
+
return 1
|
|
33
|
+
|
|
34
|
+
except (ConnectError, TimeoutException):
|
|
35
|
+
return 2
|
|
36
|
+
except Exception as e:
|
|
37
|
+
return 2
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
user = input ("Username?: ").strip()
|
|
41
|
+
result = validate_roblox(user)
|
|
42
|
+
|
|
43
|
+
if result == 1:
|
|
44
|
+
print("Available!")
|
|
45
|
+
elif result == 0:
|
|
46
|
+
print("Unavailable!")
|
|
47
|
+
else:
|
|
48
|
+
print("Error occurred!")
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from httpx import ConnectError, TimeoutException
|
|
3
|
+
import re
|
|
4
|
+
import json
|
|
5
|
+
|
|
6
|
+
def validate_bluesky(user):
|
|
7
|
+
handle = user if user.endswith('.bsky.social') else f"{user}.bsky.social"
|
|
8
|
+
url = "https://bsky.social/xrpc/com.atproto.temp.checkHandleAvailability"
|
|
9
|
+
|
|
10
|
+
headers = {
|
|
11
|
+
'User-Agent': "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Mobile Safari/537.36",
|
|
12
|
+
'Accept-Encoding': "gzip",
|
|
13
|
+
'atproto-accept-labelers': "did:plc:ar7c4by46qjdydhdevvrndac;redact",
|
|
14
|
+
'sec-ch-ua-platform': "\"Android\"",
|
|
15
|
+
'sec-ch-ua': "\"Google Chrome\";v=\"141\", \"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"141\"",
|
|
16
|
+
'sec-ch-ua-mobile': "?1",
|
|
17
|
+
'origin': "https://bsky.app",
|
|
18
|
+
'sec-fetch-site': "cross-site",
|
|
19
|
+
'sec-fetch-mode': "cors",
|
|
20
|
+
'sec-fetch-dest': "empty",
|
|
21
|
+
'referer': "https://bsky.app/",
|
|
22
|
+
'accept-language': "en-US,en;q=0.9",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
params = {
|
|
26
|
+
'handle': handle,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if not re.fullmatch(r"^[a-zA-Z0-9\.-]{1,64}$", user):
|
|
30
|
+
return 2
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
response = httpx.get(url, headers=headers, params=params, timeout = 15.0)
|
|
34
|
+
status = response.status_code
|
|
35
|
+
|
|
36
|
+
if status == 200:
|
|
37
|
+
data = response.json()
|
|
38
|
+
result_type = data.get('result', {}).get('$type')
|
|
39
|
+
|
|
40
|
+
if result_type == "com.atproto.temp.checkHandleAvailability#resultAvailable":
|
|
41
|
+
return 1
|
|
42
|
+
elif result_type == "com.atproto.temp.checkHandleAvailability#resultUnavailable":
|
|
43
|
+
return 0
|
|
44
|
+
else:
|
|
45
|
+
return 2
|
|
46
|
+
else:
|
|
47
|
+
return 2
|
|
48
|
+
|
|
49
|
+
except (ConnectError, TimeoutException):
|
|
50
|
+
return 2
|
|
51
|
+
except json.JSONDecodeError:
|
|
52
|
+
return 2
|
|
53
|
+
except Exception:
|
|
54
|
+
return 2
|
|
55
|
+
|
|
56
|
+
if __name__ == "__main__":
|
|
57
|
+
try:
|
|
58
|
+
import httpx
|
|
59
|
+
except ImportError:
|
|
60
|
+
print("Error: 'httpx' library is not installed.")
|
|
61
|
+
exit()
|
|
62
|
+
|
|
63
|
+
user = input ("Username?: ").strip()
|
|
64
|
+
result = validate_bluesky(user)
|
|
65
|
+
|
|
66
|
+
if result == 1:
|
|
67
|
+
print("Available!")
|
|
68
|
+
elif result == 0:
|
|
69
|
+
print("Unavailable!")
|
|
70
|
+
else:
|
|
71
|
+
print("Error occured!")
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from httpx import ConnectError, TimeoutException
|
|
3
|
+
|
|
4
|
+
def validate_discord(user):
|
|
5
|
+
url = "https://discord.com/api/v9/unique-username/username-attempt-unauthed"
|
|
6
|
+
|
|
7
|
+
headers = {
|
|
8
|
+
"authority": "discord.com",
|
|
9
|
+
"accept": "/",
|
|
10
|
+
"accept-language": "en-GB,en-US;q=0.9,en;q=0.8",
|
|
11
|
+
"content-type": "application/json",
|
|
12
|
+
"origin": "https://discord.com",
|
|
13
|
+
"referer": "https://discord.com/register"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
data = {"username": user}
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
response = httpx.post(url, headers=headers, json=data, timeout=3.0)
|
|
20
|
+
if response.status_code == 200:
|
|
21
|
+
status = response.json().get("taken")
|
|
22
|
+
if status is True:
|
|
23
|
+
return 0
|
|
24
|
+
elif status is False:
|
|
25
|
+
return 1
|
|
26
|
+
return 2
|
|
27
|
+
except (ConnectError, TimeoutException):
|
|
28
|
+
return 2
|
|
29
|
+
except Exception:
|
|
30
|
+
return 2
|
|
31
|
+
|
|
32
|
+
if __name__ == "__main__":
|
|
33
|
+
user = input ("Username?: ").strip()
|
|
34
|
+
result = validate_discord(user)
|
|
35
|
+
|
|
36
|
+
if result == 1:
|
|
37
|
+
print("Available!")
|
|
38
|
+
elif result == 0:
|
|
39
|
+
print("Unavailable!")
|
|
40
|
+
else:
|
|
41
|
+
print("Error occured!")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
user_scanner/social/instagram.py
CHANGED
|
@@ -13,9 +13,9 @@ def validate_instagram(user):
|
|
|
13
13
|
'X-Requested-With': "XMLHttpRequest",
|
|
14
14
|
'Referer': f"https://www.instagram.com/{user}/",
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
try:
|
|
18
|
-
response = httpx.get(url, headers=headers, timeout =
|
|
18
|
+
response = httpx.get(url, headers=headers, timeout = 3.0)
|
|
19
19
|
status = response.status_code
|
|
20
20
|
|
|
21
21
|
if status == 200:
|
|
@@ -31,12 +31,6 @@ def validate_instagram(user):
|
|
|
31
31
|
return 2
|
|
32
32
|
|
|
33
33
|
if __name__ == "__main__":
|
|
34
|
-
try:
|
|
35
|
-
import httpx
|
|
36
|
-
except ImportError:
|
|
37
|
-
print("Error: 'httpx' library is not installed.")
|
|
38
|
-
exit()
|
|
39
|
-
|
|
40
34
|
user = input ("Username?: ").strip()
|
|
41
35
|
result = validate_instagram(user)
|
|
42
36
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
from httpx import ConnectError, TimeoutException
|
|
3
|
+
|
|
4
|
+
def validate_mastodon(user):
|
|
5
|
+
url = f"https://mastodon.social/@{user}"
|
|
6
|
+
|
|
7
|
+
headers = {
|
|
8
|
+
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
|
|
9
|
+
'Accept': "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
|
|
10
|
+
'Accept-Encoding': "gzip, deflate, br",
|
|
11
|
+
'Accept-Language': "en-US,en;q=0.9",
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
response = httpx.get(url, headers=headers, timeout = 3.0, follow_redirects=True)
|
|
16
|
+
status = response.status_code
|
|
17
|
+
|
|
18
|
+
if status == 200:
|
|
19
|
+
return 0
|
|
20
|
+
elif status == 404:
|
|
21
|
+
return 1
|
|
22
|
+
else:
|
|
23
|
+
return 2
|
|
24
|
+
|
|
25
|
+
except (ConnectError, TimeoutException):
|
|
26
|
+
return 2
|
|
27
|
+
except Exception:
|
|
28
|
+
return 2
|
|
29
|
+
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
try:
|
|
32
|
+
import httpx
|
|
33
|
+
except ImportError:
|
|
34
|
+
print("Error: 'httpx' library is not installed.")
|
|
35
|
+
exit()
|
|
36
|
+
|
|
37
|
+
user = input ("Username?: ").strip()
|
|
38
|
+
result = validate_mastodon(user)
|
|
39
|
+
|
|
40
|
+
if result == 1:
|
|
41
|
+
print("Available!")
|
|
42
|
+
elif result == 0:
|
|
43
|
+
print("Unavailable!")
|
|
44
|
+
else:
|
|
45
|
+
print("Error occured!")
|
user_scanner/social/pinterest.py
CHANGED
|
@@ -31,12 +31,6 @@ def validate_pinterest(user):
|
|
|
31
31
|
return 2
|
|
32
32
|
|
|
33
33
|
if __name__ == "__main__":
|
|
34
|
-
try:
|
|
35
|
-
import httpx
|
|
36
|
-
except ImportError:
|
|
37
|
-
print("Error: 'httpx' library is not installed.")
|
|
38
|
-
exit()
|
|
39
|
-
|
|
40
34
|
user = input ("Username?: ").strip()
|
|
41
35
|
result = validate_pinterest(user)
|
|
42
36
|
|
user_scanner/social/reddit.py
CHANGED
|
@@ -31,12 +31,6 @@ def validate_reddit(user):
|
|
|
31
31
|
return 2
|
|
32
32
|
|
|
33
33
|
if __name__ == "__main__":
|
|
34
|
-
try:
|
|
35
|
-
import httpx
|
|
36
|
-
except ImportError:
|
|
37
|
-
print("Error: 'httpx' library is not installed.")
|
|
38
|
-
exit()
|
|
39
|
-
|
|
40
34
|
user = input ("Username?: ").strip()
|
|
41
35
|
result = validate_reddit(user)
|
|
42
36
|
|
user_scanner/social/snapchat.py
CHANGED
|
@@ -37,12 +37,6 @@ def validate_snapchat(user):
|
|
|
37
37
|
return 2
|
|
38
38
|
|
|
39
39
|
if __name__ == "__main__":
|
|
40
|
-
try:
|
|
41
|
-
import httpx
|
|
42
|
-
except ImportError:
|
|
43
|
-
print("Error: 'httpx' library is not installed.")
|
|
44
|
-
exit()
|
|
45
|
-
|
|
46
40
|
user = input ("Username?: ").strip()
|
|
47
41
|
result = validate_snapchat(user)
|
|
48
42
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
import re
|
|
3
|
+
|
|
4
|
+
def validate_telegram(user: str) -> int:
|
|
5
|
+
"""
|
|
6
|
+
Checks if a Telegram username is available.
|
|
7
|
+
Returns: 1 -> available, 0 -> taken, 2 -> error
|
|
8
|
+
"""
|
|
9
|
+
url = f"https://t.me/{user}"
|
|
10
|
+
headers = {
|
|
11
|
+
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
r = httpx.get(url, headers=headers, follow_redirects=True, timeout=3.0)
|
|
16
|
+
if r.status_code == 200:
|
|
17
|
+
return 0 if re.search(r'<div[^>]*class="tgme_page_extra"[^>]*>', r.text) else 1
|
|
18
|
+
return 2
|
|
19
|
+
except (httpx.ConnectError, httpx.TimeoutException):
|
|
20
|
+
return 2
|
|
21
|
+
except Exception:
|
|
22
|
+
return 2
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
user = input ("Username?: ").strip()
|
|
27
|
+
result = validate_telegram(user)
|
|
28
|
+
|
|
29
|
+
if result == 1:
|
|
30
|
+
print("Available!")
|
|
31
|
+
elif result == 0:
|
|
32
|
+
print("Unavailable!")
|
|
33
|
+
else:
|
|
34
|
+
print("Error occured!")
|
user_scanner/social/threads.py
CHANGED
|
@@ -31,12 +31,6 @@ def validate_instagram(user):
|
|
|
31
31
|
return 2
|
|
32
32
|
|
|
33
33
|
if __name__ == "__main__":
|
|
34
|
-
try:
|
|
35
|
-
import httpx
|
|
36
|
-
except ImportError:
|
|
37
|
-
print("Error: 'httpx' library is not installed.")
|
|
38
|
-
exit()
|
|
39
|
-
|
|
40
34
|
user = input ("Username?: ").strip()
|
|
41
35
|
result = validate_instagram(user)
|
|
42
36
|
|
user_scanner/social/x.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import httpx
|
|
2
2
|
import json
|
|
3
|
+
from colorama import Fore, Style
|
|
3
4
|
from httpx import ConnectError, TimeoutException
|
|
4
5
|
|
|
5
6
|
def validate_x(user):
|
|
@@ -19,6 +20,7 @@ def validate_x(user):
|
|
|
19
20
|
try:
|
|
20
21
|
response = httpx.get(url, params=params, headers=headers, timeout = 3.0)
|
|
21
22
|
status = response.status_code
|
|
23
|
+
# print(response.text)
|
|
22
24
|
if status in [401, 403, 429]:
|
|
23
25
|
return 2
|
|
24
26
|
|
|
@@ -29,8 +31,8 @@ def validate_x(user):
|
|
|
29
31
|
return 1
|
|
30
32
|
elif data.get('reason') == 'taken':
|
|
31
33
|
return 0
|
|
32
|
-
elif data.get('reason') == "improper_format":
|
|
33
|
-
print(data.get('desc'))
|
|
34
|
+
elif (data.get('reason') == "improper_format" or data.get('reason') == "invalid_username"):
|
|
35
|
+
print("\n" +" "+f"{Fore.CYAN}X says: {data.get('desc')}{Style.RESET_ALL}")
|
|
34
36
|
return 2
|
|
35
37
|
else:
|
|
36
38
|
return 2
|
|
@@ -41,12 +43,6 @@ def validate_x(user):
|
|
|
41
43
|
return 2
|
|
42
44
|
|
|
43
45
|
if __name__ == "__main__":
|
|
44
|
-
try:
|
|
45
|
-
import httpx
|
|
46
|
-
except ImportError:
|
|
47
|
-
print("Error: 'httpx' library is not installed.")
|
|
48
|
-
exit()
|
|
49
|
-
|
|
50
46
|
user = input ("Username?: ").strip()
|
|
51
47
|
result = validate_x(user)
|
|
52
48
|
|
user_scanner/social/youtube.py
CHANGED
|
@@ -45,12 +45,6 @@ def validate_youtube(user):
|
|
|
45
45
|
return 2
|
|
46
46
|
|
|
47
47
|
if __name__ == "__main__":
|
|
48
|
-
try:
|
|
49
|
-
import httpx
|
|
50
|
-
except ImportError:
|
|
51
|
-
print("Error: 'httpx' library is not installed.")
|
|
52
|
-
exit()
|
|
53
|
-
|
|
54
48
|
user = input ("Username?: ").strip()
|
|
55
49
|
result = validate_youtube(user)
|
|
56
50
|
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
_SCRIPT_DIR = Path(__file__).resolve().parent
|
|
5
|
+
VERSION_FILE = _SCRIPT_DIR.parent / "version.json"
|
|
6
|
+
|
|
7
|
+
def load_local_version():
|
|
8
|
+
try:
|
|
9
|
+
data = json.loads(VERSION_FILE.read_text())
|
|
10
|
+
return data.get("version", "0.0.0"), data.get("version_type", "local")
|
|
11
|
+
except FileNotFoundError:
|
|
12
|
+
return "N/A", "file_missing"
|
|
13
|
+
except json.JSONDecodeError:
|
|
14
|
+
return "N/A", "json_error"
|
|
15
|
+
except Exception:
|
|
16
|
+
return "N/A", "error"
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
version, version_type = load_local_version()
|
|
20
|
+
print(f"Version: {version}, Type: {version_type}")
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: user-scanner
|
|
3
|
+
Version: 1.0.2.1
|
|
4
|
+
Summary: Check username availability across multiple popular platforms
|
|
5
|
+
Keywords: username,checker,availability,social,tech,python,user-scanner
|
|
6
|
+
Author-email: Kaif <kafcodec@gmail.com>
|
|
7
|
+
Requires-Python: >=3.7
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: httpx
|
|
11
|
+
Requires-Dist: colorama
|
|
12
|
+
Project-URL: Homepage, https://github.com/kaifcodec/user-scanner
|
|
13
|
+
|
|
14
|
+
# User Scanner
|
|
15
|
+
|
|
16
|
+

|
|
17
|
+
<p align="center">
|
|
18
|
+
<img src="https://img.shields.io/badge/Version-1.0.2.0-blueviolet?style=for-the-badge&logo=github" />
|
|
19
|
+
<img src="https://img.shields.io/github/issues/kaifcodec/user-scanner?style=for-the-badge&logo=github" />
|
|
20
|
+
<img src="https://img.shields.io/badge/Tested%20on-Termux-black?style=for-the-badge&logo=termux" />
|
|
21
|
+
<img src="https://img.shields.io/badge/Tested%20on-Windows-cyan?style=for-the-badge&logo=Windows" />
|
|
22
|
+
<img src="https://img.shields.io/badge/Tested%20on-Linux-balck?style=for-the-badge&logo=Linux" />
|
|
23
|
+
<img src="https://img.shields.io/pepy/dt/user-scanner?style=for-the-badge" />
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
Scan a username across multiple social, developer, and creator platforms to see if it’s available.
|
|
29
|
+
Perfect for finding a **unique username** across GitHub, Twitter, Reddit, Instagram, and more, all in one command.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Features
|
|
33
|
+
|
|
34
|
+
- ✅ Check usernames across **social networks**, **developer platforms**, and **creator communities**.
|
|
35
|
+
- ✅ Clear **Available / Taken / Error** output for each platform.
|
|
36
|
+
- ✅ Fully modular: add new platform modules easily.
|
|
37
|
+
- ✅ Command-line interface ready: works directly after `pip install`.
|
|
38
|
+
- ✅ Can be used as username OSINT tool.
|
|
39
|
+
- ✅ Very low and lightweight dependencies, can be run on any machine.
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
### Installation
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install user-scanner
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
### Usage
|
|
51
|
+
|
|
52
|
+
Scan a username across all platforms:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
user-scanner -u <username>
|
|
56
|
+
```
|
|
57
|
+
Optionally, scan a specific category or single module:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
user-scanner -u <username> -c dev
|
|
61
|
+
user-scanner -l # Lists all available modules
|
|
62
|
+
user-scanner -u <username> -m github
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
---
|
|
66
|
+
### Example Output:
|
|
67
|
+
|
|
68
|
+
- Note*: New modules are constantly getting added so this might have only limited, outdated output:
|
|
69
|
+
```bash
|
|
70
|
+
Checking username: johndoe078
|
|
71
|
+
|
|
72
|
+
== DEV SITES ==
|
|
73
|
+
[✔] Codeberg: Available
|
|
74
|
+
[✔] Cratesio: Available
|
|
75
|
+
[✔] Dockerhub: Available
|
|
76
|
+
[✘] Github: Taken
|
|
77
|
+
[✔] Gitlab: Available
|
|
78
|
+
[✔] Launchpad: Available
|
|
79
|
+
[✔] Npmjs: Available
|
|
80
|
+
[✔] Replit: Available
|
|
81
|
+
|
|
82
|
+
== SOCIAL SITES ==
|
|
83
|
+
[✔] Bluesky: Available
|
|
84
|
+
[✔] Discord: Available
|
|
85
|
+
[✘] Instagram: Taken
|
|
86
|
+
[✔] Mastodon: Available
|
|
87
|
+
[✔] Pinterest: Available
|
|
88
|
+
[✘] Reddit: Taken
|
|
89
|
+
[✔] Snapchat: Available
|
|
90
|
+
[✔] Telegram: Available
|
|
91
|
+
[✘] Threads: Taken
|
|
92
|
+
[✔] X (Twitter): Available
|
|
93
|
+
[✔] Youtube: Available
|
|
94
|
+
|
|
95
|
+
== CREATOR SITES ==
|
|
96
|
+
[✔] Devto: Available
|
|
97
|
+
[✔] Hashnode: Available
|
|
98
|
+
[✔] Kaggle: Available
|
|
99
|
+
[✔] Medium: Available
|
|
100
|
+
[✔] Patreon: Available
|
|
101
|
+
|
|
102
|
+
== COMMUNITY SITES ==
|
|
103
|
+
[✔] Coderlegion: Available
|
|
104
|
+
|
|
105
|
+
== GAMING SITES ==
|
|
106
|
+
[✔] Chess_com: Available
|
|
107
|
+
[✔] Osu: Available
|
|
108
|
+
[✔] Roblox: Available
|
|
109
|
+
...
|
|
110
|
+
...
|
|
111
|
+
...
|
|
112
|
+
```
|
|
113
|
+
### Contributing:
|
|
114
|
+
|
|
115
|
+
Modules are organized by category:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
user_scanner/
|
|
119
|
+
├── dev/ # Developer platforms (GitHub, GitLab, etc.)
|
|
120
|
+
├── social/ # Social platforms (Twitter/X, Reddit, Instagram, etc.)
|
|
121
|
+
├── creator/ # Creator platforms (Hashnode, Dev.to, Medium, etc.)
|
|
122
|
+
├── community/ # Community platforms (forums, niche sites)
|
|
123
|
+
├── gaming/ # Gaming sites (chess.com, roblox, monkeytype etc.)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Module guidelines:**
|
|
127
|
+
- Each module must define a `validate_<site>()` function that takes a `username` and returns:
|
|
128
|
+
- `1` → Available
|
|
129
|
+
- `0` → Taken
|
|
130
|
+
- `2` → Error / Could not check
|
|
131
|
+
- Use `httpx` for requests, `colorama` for colored output.
|
|
132
|
+
- Optional: modules can define a CLI parser if they support custom arguments.
|
|
133
|
+
|
|
134
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for examples.
|
|
135
|
+
|
|
136
|
+
### 📧 Contact:
|
|
137
|
+
- [Email](kaifcodec@gmail.com)
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### Dependencies:
|
|
142
|
+
- [httpx](https://pypi.org/project/httpx/)
|
|
143
|
+
- [colorama](https://pypi.org/project/colorama/)
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### License
|
|
148
|
+
|
|
149
|
+
This project is licensed under the **MIT License**. See [LICENSE](LICENSE) for details.
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
<!---
|
|
153
|
+
## 🌟 Stars:
|
|
154
|
+
|
|
155
|
+
<a href="https://www.star-history.com/#kaifcodec/user-scanner&type=date&legend=top-left">
|
|
156
|
+
<picture>
|
|
157
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=kaifcodec/user-scanner&type=date&theme=dark&legend=top-left" />
|
|
158
|
+
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=kaifcodec/user-scanner&type=date&legend=top-left" />
|
|
159
|
+
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=kaifcodec/user-scanner&type=date&legend=top-left" />
|
|
160
|
+
</picture>
|
|
161
|
+
</a>
|
|
162
|
+
--->
|
|
163
|
+
---
|
|
164
|
+
## ⚠️ `community/` and `gaming/` are small, looking for contributions
|
|
165
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
user_scanner/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
2
|
+
user_scanner/__main__.py,sha256=Zu9ZPz3f4QPvtyj9NswmUkqjQmKiFKoxOp6KKCz-ngg,3676
|
|
3
|
+
user_scanner/version.json,sha256=Cg76jtg6LF1WMxx8Bh3Bsu6-Bhh0Xf3_CoSKTqU3MV8,49
|
|
4
|
+
user_scanner/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
user_scanner/cli/banner.py,sha256=mg9yKqaK5VRvZKs7vteU1wyUlCnrmWpGC5nq9BmTGNc,1504
|
|
6
|
+
user_scanner/community/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
user_scanner/community/coderlegion.py,sha256=wva0seSkd4h7kSjIprW0wM7JC0zspFjXGnDHkeIJ3YI,1141
|
|
8
|
+
user_scanner/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
user_scanner/core/orchestrator.py,sha256=-iP6qZQx5vN8fSZ4Z_TOxUcP9Pf3VYhsbBSQLP9ABEc,3230
|
|
10
|
+
user_scanner/creator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
user_scanner/creator/devto.py,sha256=K9jXlwSlhJxwZomGJB7m8u_22kTejLPJ_-AvwFZahsY,1034
|
|
12
|
+
user_scanner/creator/hashnode.py,sha256=2Q-K9Yuy-6qOoJJPMq3UD0JHP4d9XeO9OGpBeHuMims,1351
|
|
13
|
+
user_scanner/creator/kaggle.py,sha256=pCq7QQ62wxunEmBIWNjKyWIH2ENXK76BM3zt4HWi0zM,927
|
|
14
|
+
user_scanner/creator/medium.py,sha256=dWNialp0QTo4GRq64afA00G3PDXVOLZM3mnO3WnmR8c,1008
|
|
15
|
+
user_scanner/creator/patreon.py,sha256=drjlB5XDFs1TW6J3W1LqBwZhc6PWtn-5nLBG8OtnFhU,1274
|
|
16
|
+
user_scanner/dev/__init__.py,sha256=qUR0eLwN-gO6oKk-1cmCVT4G_AxUHHMgpV3wJ7URXi4,7
|
|
17
|
+
user_scanner/dev/codeberg.py,sha256=WuGisrD2-OVolXB1T_5Dn-J8Nx5BTX_Fh2MTsK-F7os,930
|
|
18
|
+
user_scanner/dev/cratesio.py,sha256=n1yJFJ2uWfRzpARSNSZ9s53iPm-5IiAxTOMTq0hOVis,999
|
|
19
|
+
user_scanner/dev/dockerhub.py,sha256=P5bQEY9hm-k600rAtFi9rhiRAZy3Ansch282cC-ZTGk,1108
|
|
20
|
+
user_scanner/dev/github.py,sha256=RSjJrCOchvQKYPScR2BeBn_qyUZxGyfTmNYFCOY3J7E,1407
|
|
21
|
+
user_scanner/dev/gitlab.py,sha256=0-3vYg5G5_uguH2I68zZdPyq5VaMUS76766Db7uWrR8,1433
|
|
22
|
+
user_scanner/dev/launchpad.py,sha256=ank50BpTsN7m5_MuQNxAbLpfQOrwjnwS_olO9nhPwgk,1074
|
|
23
|
+
user_scanner/dev/npmjs.py,sha256=Tv2YgCpuSxJKWEPdcTWwm9CCl2rmfKlGdQe2rnMnXM8,1141
|
|
24
|
+
user_scanner/dev/replit.py,sha256=GN1Q8PecTzBsd6TpOT-qRnMvKhFTh1P6uCa8CDlXkpw,925
|
|
25
|
+
user_scanner/gaming/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
|
+
user_scanner/gaming/chess_com.py,sha256=QDUdijyQQi7fwy6roYWzDyAQv6gbtV-Zh_uZyHXiaR4,1505
|
|
27
|
+
user_scanner/gaming/monkeytype.py,sha256=k4wgDR5lQTJBIcyeMRjPE_F5KC3kJfeAuS2eez43yAs,1665
|
|
28
|
+
user_scanner/gaming/osu.py,sha256=Jz_s6qNURC-L10-MSfTh6mEywoEqOh8Stvb_bWJR_0I,1239
|
|
29
|
+
user_scanner/gaming/roblox.py,sha256=eCiAEiC8BaMwcd_6k3PE30FebtsjVCBkvUTZkaaJhHY,1605
|
|
30
|
+
user_scanner/social/__init__.py,sha256=jaCkFwX1uYtF0ENifVwF8OfHrYYUTm64B9wlBq9BBfQ,9
|
|
31
|
+
user_scanner/social/bluesky.py,sha256=r5UIFCStlwEM4UxE6cDTrDb5w_EqPCgJ2iYz27GpjA8,2157
|
|
32
|
+
user_scanner/social/discord.py,sha256=3TaYAzqK9sPKzL_GPzli4P-U22Dwe-mSmeH6kVHJXI4,1137
|
|
33
|
+
user_scanner/social/instagram.py,sha256=oskZgHagkyl_p-bi7CMYqCh0wsoqfCFnR7GZcbKX1-U,1229
|
|
34
|
+
user_scanner/social/mastodon.py,sha256=KbhdutPe_M0bvtkJXz2VEhalSEgA7n-bUbrkR3pYAb4,1276
|
|
35
|
+
user_scanner/social/pinterest.py,sha256=LHCiTmPALPLYXDClz09EBKRREhs5u3CajeFiQg5Vvlg,1168
|
|
36
|
+
user_scanner/social/reddit.py,sha256=DQYWedJeeyUuk-6EARU_52rPQHNkjfSbahOl5AHENa0,1194
|
|
37
|
+
user_scanner/social/snapchat.py,sha256=ZG-SIv6RopT45dudfOm5sRxmV_ihWG1Vh1Z766fm8XE,1527
|
|
38
|
+
user_scanner/social/telegram.py,sha256=QxK2jD2QEvrYmnkxysl_yk7-G6CRWvkK5EnK6n5q3jY,946
|
|
39
|
+
user_scanner/social/threads.py,sha256=QRidTYquAMDHJSg68ySpWCbliRYdWJkbOqn8RfWzFQQ,1231
|
|
40
|
+
user_scanner/social/x.py,sha256=NetPGmPnWEKv6za9E_Ekah9bAeeFlEeY3qbTJQo7AqE,1560
|
|
41
|
+
user_scanner/social/youtube.py,sha256=zuyWCy5FtEilaIcUZ4dTCctRR9deFnwwWJkf-h_1K0E,1943
|
|
42
|
+
user_scanner/utils/update.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
|
+
user_scanner/utils/version.py,sha256=ou6CF7ndVwEYvSpO4Se-B-71AvVezZcaZJpYFgDQsqM,621
|
|
44
|
+
user_scanner-1.0.2.1.dist-info/entry_points.txt,sha256=XqU3kssYZ0vXaPy5qYUOTCu4u-48Xie7QWFpBCYc7Nc,59
|
|
45
|
+
user_scanner-1.0.2.1.dist-info/licenses/LICENSE,sha256=XH1QyQG68zo1opDIZHTHcTAbe9XMzewvTaFTukcN9vc,1061
|
|
46
|
+
user_scanner-1.0.2.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
47
|
+
user_scanner-1.0.2.1.dist-info/METADATA,sha256=AJhJys-X1IAUp3JW3UoEYcztTVYNUyRZSd5_Zu5yYHc,4970
|
|
48
|
+
user_scanner-1.0.2.1.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: user-scanner
|
|
3
|
-
Version: 1.0.0.3
|
|
4
|
-
Summary: Check username availability across multiple popular platforms
|
|
5
|
-
Keywords: username,checker,availability,social,tech,python,user-scanner
|
|
6
|
-
Author-email: Kaif <kafcodec@gmail.com>
|
|
7
|
-
Requires-Python: >=3.7
|
|
8
|
-
Description-Content-Type: text/markdown
|
|
9
|
-
License-File: LICENSE
|
|
10
|
-
Requires-Dist: httpx
|
|
11
|
-
Requires-Dist: colorama
|
|
12
|
-
Project-URL: Homepage, https://github.com/kaifcodec/user-scanner
|
|
13
|
-
|
|
14
|
-
# user-scanner
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
user_scanner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
user_scanner/__main__.py,sha256=gTuNDvGcxJxnJgbviOARUN42bhpEZ3j5oUgZBFIYa4U,3164
|
|
3
|
-
user_scanner/community/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
user_scanner/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
user_scanner/core/orchestrator.py,sha256=5HgT9tP5r6pX8eUOaHOwXeCz0wDTfifyGW_WtNnz6kQ,3194
|
|
6
|
-
user_scanner/creator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
user_scanner/creator/devto.py,sha256=K9jXlwSlhJxwZomGJB7m8u_22kTejLPJ_-AvwFZahsY,1034
|
|
8
|
-
user_scanner/creator/hashnode.py,sha256=2Q-K9Yuy-6qOoJJPMq3UD0JHP4d9XeO9OGpBeHuMims,1351
|
|
9
|
-
user_scanner/creator/kaggle.py,sha256=t5mTBz0eWZMNdy4YD1_O1wBAqHXjhmcOD0uAPzijS38,1156
|
|
10
|
-
user_scanner/creator/medium.py,sha256=dWNialp0QTo4GRq64afA00G3PDXVOLZM3mnO3WnmR8c,1008
|
|
11
|
-
user_scanner/dev/__init__.py,sha256=qUR0eLwN-gO6oKk-1cmCVT4G_AxUHHMgpV3wJ7URXi4,7
|
|
12
|
-
user_scanner/dev/codeberg.py,sha256=WuGisrD2-OVolXB1T_5Dn-J8Nx5BTX_Fh2MTsK-F7os,930
|
|
13
|
-
user_scanner/dev/cratesio.py,sha256=n1yJFJ2uWfRzpARSNSZ9s53iPm-5IiAxTOMTq0hOVis,999
|
|
14
|
-
user_scanner/dev/dockerhub.py,sha256=P5bQEY9hm-k600rAtFi9rhiRAZy3Ansch282cC-ZTGk,1108
|
|
15
|
-
user_scanner/dev/github.py,sha256=RSjJrCOchvQKYPScR2BeBn_qyUZxGyfTmNYFCOY3J7E,1407
|
|
16
|
-
user_scanner/dev/gitlab.py,sha256=0-3vYg5G5_uguH2I68zZdPyq5VaMUS76766Db7uWrR8,1433
|
|
17
|
-
user_scanner/dev/launchpad.py,sha256=ank50BpTsN7m5_MuQNxAbLpfQOrwjnwS_olO9nhPwgk,1074
|
|
18
|
-
user_scanner/dev/npmjs.py,sha256=Tv2YgCpuSxJKWEPdcTWwm9CCl2rmfKlGdQe2rnMnXM8,1141
|
|
19
|
-
user_scanner/dev/replit.py,sha256=GN1Q8PecTzBsd6TpOT-qRnMvKhFTh1P6uCa8CDlXkpw,925
|
|
20
|
-
user_scanner/social/__init__.py,sha256=jaCkFwX1uYtF0ENifVwF8OfHrYYUTm64B9wlBq9BBfQ,9
|
|
21
|
-
user_scanner/social/instagram.py,sha256=6m2TJYWSzD5cWXXBlgFRtGRY0KlqGdHFh7_mBaOQ2bg,1357
|
|
22
|
-
user_scanner/social/pinterest.py,sha256=5cDmvtAXPtvpsO2vdAd30_Gx11i8L90mYrAU2OgNMQE,1291
|
|
23
|
-
user_scanner/social/reddit.py,sha256=GkbQ6fPQVDygcOsnpuOkmIpATW5YlbEnKtC8lF2U5w0,1317
|
|
24
|
-
user_scanner/social/snapchat.py,sha256=Qik4Jfaz3Glo_Wer5NrB7IVTBcP2D8AL_mVRnPXAKkc,1650
|
|
25
|
-
user_scanner/social/threads.py,sha256=_8pUvLtJ6NT0LA9cEQn2IqIiA0IIn3LKZFaVtbhSMQk,1354
|
|
26
|
-
user_scanner/social/x.py,sha256=8SfCq61ky012s1FtqQ9mcpexs3Y8z7dynmp6YgpK2gQ,1522
|
|
27
|
-
user_scanner/social/youtube.py,sha256=pYBVeYpo1fFdcMAQ22ruka9TFkNpQr1h3YuatM_s0rU,2066
|
|
28
|
-
user_scanner-1.0.0.3.dist-info/entry_points.txt,sha256=XqU3kssYZ0vXaPy5qYUOTCu4u-48Xie7QWFpBCYc7Nc,59
|
|
29
|
-
user_scanner-1.0.0.3.dist-info/licenses/LICENSE,sha256=XH1QyQG68zo1opDIZHTHcTAbe9XMzewvTaFTukcN9vc,1061
|
|
30
|
-
user_scanner-1.0.0.3.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
31
|
-
user_scanner-1.0.0.3.dist-info/METADATA,sha256=Smt9GME2bnRFIMnbAbs34NrbttkJtU8KHqjJI28ccj8,452
|
|
32
|
-
user_scanner-1.0.0.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|