user-scanner 1.0.8.0__py3-none-any.whl → 1.0.8.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/community/__init__.py +1 -0
- user_scanner/community/stackoverflow.py +35 -0
- user_scanner/core/orchestrator.py +1 -0
- user_scanner/creator/producthunt.py +32 -10
- user_scanner/social/youtube.py +18 -11
- user_scanner/version.json +1 -1
- {user_scanner-1.0.8.0.dist-info → user_scanner-1.0.8.1.dist-info}/METADATA +13 -10
- {user_scanner-1.0.8.0.dist-info → user_scanner-1.0.8.1.dist-info}/RECORD +11 -10
- {user_scanner-1.0.8.0.dist-info → user_scanner-1.0.8.1.dist-info}/WHEEL +0 -0
- {user_scanner-1.0.8.0.dist-info → user_scanner-1.0.8.1.dist-info}/entry_points.txt +0 -0
- {user_scanner-1.0.8.0.dist-info → user_scanner-1.0.8.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# community
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from user_scanner.core.orchestrator import generic_validate
|
|
2
|
+
from user_scanner.core.result import Result
|
|
3
|
+
|
|
4
|
+
def validate_stackoverflow(user: str) -> Result:
|
|
5
|
+
url = f"https://stackoverflow.com/users/filter?search={user}"
|
|
6
|
+
|
|
7
|
+
def process(response):
|
|
8
|
+
if response.status_code == 200:
|
|
9
|
+
text = response.text
|
|
10
|
+
|
|
11
|
+
if "No users matched your search." in text:
|
|
12
|
+
return Result.available()
|
|
13
|
+
|
|
14
|
+
pattern = f'>{user}<'
|
|
15
|
+
if pattern in text:
|
|
16
|
+
return Result.taken()
|
|
17
|
+
|
|
18
|
+
return Result.available()
|
|
19
|
+
|
|
20
|
+
return Result.error("Unexpected status code from Stack Overflow")
|
|
21
|
+
|
|
22
|
+
return generic_validate(url, process)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
if __name__ == "__main__":
|
|
26
|
+
user = input("Username?: ").strip()
|
|
27
|
+
result = validate_stackoverflow(user)
|
|
28
|
+
|
|
29
|
+
if result == Result.available():
|
|
30
|
+
print("Available!")
|
|
31
|
+
elif result == Result.taken():
|
|
32
|
+
print("Unavailable!")
|
|
33
|
+
else:
|
|
34
|
+
msg = result.get_reason()
|
|
35
|
+
print("Error occurred!" + msg)
|
|
@@ -1,25 +1,47 @@
|
|
|
1
|
-
from user_scanner.core.orchestrator import status_validate
|
|
1
|
+
from user_scanner.core.orchestrator import status_validate, Result
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def
|
|
5
|
-
url = f"https://
|
|
6
|
-
|
|
4
|
+
def validate_youtube(user) -> Result:
|
|
5
|
+
url = f"https://m.youtube.com/@{user}"
|
|
7
6
|
headers = {
|
|
8
|
-
'User-Agent': "Mozilla/5.0 (
|
|
7
|
+
'User-Agent': "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Mobile Safari/537.36",
|
|
9
8
|
'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': "
|
|
11
|
-
'
|
|
9
|
+
'Accept-Encoding': "identity",
|
|
10
|
+
'sec-ch-dpr': "2.75",
|
|
11
|
+
'sec-ch-viewport-width': "980",
|
|
12
|
+
'sec-ch-ua': "\"Google Chrome\";v=\"143\", \"Chromium\";v=\"143\", \"Not A(Brand\";v=\"24\"",
|
|
13
|
+
'sec-ch-ua-mobile': "?1",
|
|
14
|
+
'sec-ch-ua-full-version': "\"143.0.7499.52\"",
|
|
15
|
+
'sec-ch-ua-arch': "\"\"",
|
|
16
|
+
'sec-ch-ua-platform': "\"Android\"",
|
|
17
|
+
'sec-ch-ua-platform-version': "\"15.0.0\"",
|
|
18
|
+
'sec-ch-ua-bitness': "\"\"",
|
|
19
|
+
'sec-ch-ua-wow64': "?0",
|
|
20
|
+
'sec-ch-ua-full-version-list': "\"Google Chrome\";v=\"143.0.7499.52\", \"Chromium\";v=\"143.0.7499.52\", \"Not A(Brand\";v=\"24.0.0.0\"",
|
|
21
|
+
'sec-ch-ua-form-factors': "\"Mobile\"",
|
|
22
|
+
'upgrade-insecure-requests': "1",
|
|
23
|
+
'x-browser-channel': "stable",
|
|
24
|
+
'x-browser-year': "2025",
|
|
25
|
+
'x-browser-copyright': "Copyright 2025 Google LLC. All Rights reserved.",
|
|
26
|
+
'sec-fetch-site': "none",
|
|
27
|
+
'sec-fetch-mode': "navigate",
|
|
28
|
+
'sec-fetch-user': "?1",
|
|
29
|
+
'sec-fetch-dest': "document",
|
|
30
|
+
'accept-language': "en-US,en;q=0.9",
|
|
31
|
+
'priority': "u=0, i"
|
|
12
32
|
}
|
|
13
33
|
|
|
14
|
-
status_validate(url, 404, 200, headers=headers
|
|
34
|
+
return status_validate(url, 404, 200, headers=headers)
|
|
35
|
+
|
|
15
36
|
|
|
16
37
|
if __name__ == "__main__":
|
|
17
38
|
user = input("Username?: ").strip()
|
|
18
|
-
result =
|
|
39
|
+
result = validate_youtube(user)
|
|
19
40
|
|
|
20
41
|
if result == 1:
|
|
21
42
|
print("Available!")
|
|
22
43
|
elif result == 0:
|
|
23
44
|
print("Unavailable!")
|
|
24
45
|
else:
|
|
25
|
-
|
|
46
|
+
reason = result.get_reason()
|
|
47
|
+
print(f"Error occurred! Reason: {reason}")
|
user_scanner/social/youtube.py
CHANGED
|
@@ -1,25 +1,29 @@
|
|
|
1
|
-
from user_scanner.core.orchestrator import status_validate
|
|
1
|
+
from user_scanner.core.orchestrator import status_validate, Result
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
def validate_youtube(user):
|
|
4
|
+
def validate_youtube(user) -> Result:
|
|
5
5
|
url = f"https://m.youtube.com/@{user}"
|
|
6
|
-
|
|
7
6
|
headers = {
|
|
8
|
-
'User-Agent': "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
|
7
|
+
'User-Agent': "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Mobile Safari/537.36",
|
|
9
8
|
'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': "
|
|
11
|
-
'
|
|
12
|
-
'sec-ch-
|
|
9
|
+
'Accept-Encoding': "identity",
|
|
10
|
+
'sec-ch-dpr': "2.75",
|
|
11
|
+
'sec-ch-viewport-width': "980",
|
|
12
|
+
'sec-ch-ua': "\"Google Chrome\";v=\"143\", \"Chromium\";v=\"143\", \"Not A(Brand\";v=\"24\"",
|
|
13
13
|
'sec-ch-ua-mobile': "?1",
|
|
14
|
-
'sec-ch-ua-full-version': "\"
|
|
14
|
+
'sec-ch-ua-full-version': "\"143.0.7499.52\"",
|
|
15
15
|
'sec-ch-ua-arch': "\"\"",
|
|
16
16
|
'sec-ch-ua-platform': "\"Android\"",
|
|
17
17
|
'sec-ch-ua-platform-version': "\"15.0.0\"",
|
|
18
|
+
'sec-ch-ua-model': "\"I2404\"",
|
|
18
19
|
'sec-ch-ua-bitness': "\"\"",
|
|
19
20
|
'sec-ch-ua-wow64': "?0",
|
|
20
|
-
'sec-ch-ua-full-version-list': "\"Google Chrome\";v=\"
|
|
21
|
+
'sec-ch-ua-full-version-list': "\"Google Chrome\";v=\"143.0.7499.52\", \"Chromium\";v=\"143.0.7499.52\", \"Not A(Brand\";v=\"24.0.0.0\"",
|
|
21
22
|
'sec-ch-ua-form-factors': "\"Mobile\"",
|
|
22
23
|
'upgrade-insecure-requests': "1",
|
|
24
|
+
'x-browser-channel': "stable",
|
|
25
|
+
'x-browser-year': "2025",
|
|
26
|
+
'x-browser-copyright': "Copyright 2025 Google LLC. All Rights reserved.",
|
|
23
27
|
'sec-fetch-site': "none",
|
|
24
28
|
'sec-fetch-mode': "navigate",
|
|
25
29
|
'sec-fetch-user': "?1",
|
|
@@ -28,7 +32,8 @@ def validate_youtube(user):
|
|
|
28
32
|
'priority': "u=0, i"
|
|
29
33
|
}
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
|
|
36
|
+
return status_validate(url, 404, 200, headers=headers)
|
|
32
37
|
|
|
33
38
|
|
|
34
39
|
if __name__ == "__main__":
|
|
@@ -40,4 +45,6 @@ if __name__ == "__main__":
|
|
|
40
45
|
elif result == 0:
|
|
41
46
|
print("Unavailable!")
|
|
42
47
|
else:
|
|
43
|
-
|
|
48
|
+
reason = result.get_reason()
|
|
49
|
+
print(f"Error occurred! Reason: {reason}")
|
|
50
|
+
|
user_scanner/version.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: user-scanner
|
|
3
|
-
Version: 1.0.8.
|
|
3
|
+
Version: 1.0.8.1
|
|
4
4
|
Summary: Check username availability across multiple popular platforms
|
|
5
5
|
Keywords: username,checker,availability,social,tech,python,user-scanner
|
|
6
6
|
Author-email: Kaif <kafcodec@gmail.com>
|
|
@@ -15,7 +15,7 @@ Project-URL: Homepage, https://github.com/kaifcodec/user-scanner
|
|
|
15
15
|
|
|
16
16
|

|
|
17
17
|
<p align="center">
|
|
18
|
-
<img src="https://img.shields.io/badge/Version-1.0.8.
|
|
18
|
+
<img src="https://img.shields.io/badge/Version-1.0.8.1-blueviolet?style=for-the-badge&logo=github" />
|
|
19
19
|
<img src="https://img.shields.io/github/issues/kaifcodec/user-scanner?style=for-the-badge&logo=github" />
|
|
20
20
|
<img src="https://img.shields.io/badge/Tested%20on-Termux-black?style=for-the-badge&logo=termux" />
|
|
21
21
|
<img src="https://img.shields.io/badge/Tested%20on-Windows-cyan?style=for-the-badge&logo=Windows" />
|
|
@@ -33,9 +33,10 @@ Perfect for finding a **unique username** across GitHub, Twitter, Reddit, Instag
|
|
|
33
33
|
|
|
34
34
|
- ✅ Check usernames across **social networks**, **developer platforms**, and **creator communities**.
|
|
35
35
|
- ✅ Clear **Available / Taken / Error** output for each platform.
|
|
36
|
+
- ✅ Robust error handling: It prints the exact reason (e.g. Cannot use underscores, hyphens at the start/end)
|
|
36
37
|
- ✅ Fully modular: add new platform modules easily.
|
|
37
|
-
- ✅ Wildcard-based username permutations for automatic variation generation
|
|
38
|
-
- ✅ Command-line interface ready: works directly after `pip install
|
|
38
|
+
- ✅ Wildcard-based username permutations for automatic variation generation using provided suffix
|
|
39
|
+
- ✅ Command-line interface ready: works directly after `pip install`
|
|
39
40
|
- ✅ Can be used as username OSINT tool.
|
|
40
41
|
- ✅ Very low and lightweight dependencies, can be run on any machine.
|
|
41
42
|
---
|
|
@@ -109,12 +110,14 @@ user_scanner/
|
|
|
109
110
|
```
|
|
110
111
|
|
|
111
112
|
**Module guidelines:**
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
-
|
|
117
|
-
-
|
|
113
|
+
This project contains small "validator" modules that check whether a username exists on a given platform. Each validator is a single function that returns a Result object (see `core/orchestrator.py`).
|
|
114
|
+
|
|
115
|
+
Result semantics:
|
|
116
|
+
- Result.available() → `available`
|
|
117
|
+
- Result.taken() → `taken`
|
|
118
|
+
- Result.error(message: Optional[str]) → `error`, blocked, unknown, or request failure (include short diagnostic message when helpful)
|
|
119
|
+
|
|
120
|
+
Follow this document when adding or updating validators.
|
|
118
121
|
|
|
119
122
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for examples.
|
|
120
123
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
user_scanner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
user_scanner/__main__.py,sha256=r_8gq8wSRs3U7yUkTAv4e4MPopX0MUf_EbwedBTPs44,5082
|
|
3
|
-
user_scanner/version.json,sha256=
|
|
3
|
+
user_scanner/version.json,sha256=_1eU-X0UN6AjXfkZNFG3CCPFc6S2N4WQmSrbnp5Dvog,49
|
|
4
4
|
user_scanner/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
user_scanner/cli/banner.py,sha256=3t6owaDArERlvpcszA1Yi3dtksvh8a9tLyrxRowTC40,1499
|
|
6
|
-
user_scanner/community/__init__.py,sha256=
|
|
6
|
+
user_scanner/community/__init__.py,sha256=5EzlM991pJqvqIRc05_QV5BureJZ7wiCRm1AyEY6pms,12
|
|
7
7
|
user_scanner/community/coderlegion.py,sha256=W_bdjzdFPRgUrNFFlylvToSJ4AzaFCtTsUy_MRVDdSo,451
|
|
8
|
+
user_scanner/community/stackoverflow.py,sha256=MTL8O0TLHkjVbugBh1pLxELJLU3hkX_YEHjGjaKTJi4,1007
|
|
8
9
|
user_scanner/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
user_scanner/core/orchestrator.py,sha256=
|
|
10
|
+
user_scanner/core/orchestrator.py,sha256=8dLzV-0zUafZxMLIGAT65Tp4YJtvboelR6eL9M22_4M,6124
|
|
10
11
|
user_scanner/core/result.py,sha256=HWz9JjRk74shAdM56ZtdG6hIp4dgcahqYSnpOp3uCak,1933
|
|
11
12
|
user_scanner/creator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
13
|
user_scanner/creator/devto.py,sha256=mIACmG1a4eoctywxb5p04sI0YVi3dsjCRw9YVOFBEKQ,435
|
|
@@ -15,7 +16,7 @@ user_scanner/creator/itch_io.py,sha256=JsFkFzBfJI18DeuSYJIOPGEV_9v7t-jtwmBYCA9W2
|
|
|
15
16
|
user_scanner/creator/kaggle.py,sha256=QaXIG02OGxvQZEvwHm50RKNd7joxGOq0Ht3cFfrYEiU,445
|
|
16
17
|
user_scanner/creator/medium.py,sha256=NIOYnk8_ASD0kYfKqs8t6uZZTV4D-5-ZxyHMzOMMOuI,1015
|
|
17
18
|
user_scanner/creator/patreon.py,sha256=g-r85pxirf0ihK3STyGYPIzp59MB7JH64Opb4wq1fyU,461
|
|
18
|
-
user_scanner/creator/producthunt.py,sha256=
|
|
19
|
+
user_scanner/creator/producthunt.py,sha256=p0HoIIVhmv9bBkelhfzRYudUFoyk_qeT66-hPpHEFqk,1938
|
|
19
20
|
user_scanner/dev/__init__.py,sha256=qUR0eLwN-gO6oKk-1cmCVT4G_AxUHHMgpV3wJ7URXi4,7
|
|
20
21
|
user_scanner/dev/codeberg.py,sha256=Z6nV0_8xZhMiCcNn9Hn79VVh6y0ar9fqL7KS2b7IaDo,447
|
|
21
22
|
user_scanner/dev/cratesio.py,sha256=mJnlLJoMLlQ7f_95QD7LgH1xCj-e6FooOFkpYypBfG4,724
|
|
@@ -48,11 +49,11 @@ user_scanner/social/soundcloud.py,sha256=e2yU1w2fnH1EhzYed0kxgcqgWz0YoCQQFf6yKqh
|
|
|
48
49
|
user_scanner/social/telegram.py,sha256=9IS-0pghMifNRmj62NcxCOvn23Hvg0AJJcuhCa_aXD4,765
|
|
49
50
|
user_scanner/social/threads.py,sha256=rK8Gm_riDdr0djo23tk38fNVVEBuC6nj2iTXvWrqXeE,951
|
|
50
51
|
user_scanner/social/x.py,sha256=sAnboHHZN2DWyKeds46GLZHxGG-G_bjzfVNIkblSHx8,1406
|
|
51
|
-
user_scanner/social/youtube.py,sha256=
|
|
52
|
+
user_scanner/social/youtube.py,sha256=UPu584teg75P7FT05RFG3nobbHgPmzjr-ZwyN2sw6gw,1980
|
|
52
53
|
user_scanner/utils/update.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
53
54
|
user_scanner/utils/version.py,sha256=mPh24EwITyXgD3AMgbflRL180pS0JfrvuJdnoErOU34,623
|
|
54
|
-
user_scanner-1.0.8.
|
|
55
|
-
user_scanner-1.0.8.
|
|
56
|
-
user_scanner-1.0.8.
|
|
57
|
-
user_scanner-1.0.8.
|
|
58
|
-
user_scanner-1.0.8.
|
|
55
|
+
user_scanner-1.0.8.1.dist-info/entry_points.txt,sha256=XqU3kssYZ0vXaPy5qYUOTCu4u-48Xie7QWFpBCYc7Nc,59
|
|
56
|
+
user_scanner-1.0.8.1.dist-info/licenses/LICENSE,sha256=XH1QyQG68zo1opDIZHTHcTAbe9XMzewvTaFTukcN9vc,1061
|
|
57
|
+
user_scanner-1.0.8.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
|
|
58
|
+
user_scanner-1.0.8.1.dist-info/METADATA,sha256=e14tVl6oz9iSik_h3jmapma4fdyyv3YYdWaYh-82sfY,5153
|
|
59
|
+
user_scanner-1.0.8.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|