Enhance deep username research and real-time scan timing#30
Conversation
There was a problem hiding this comment.
Pull request overview
This PR extends the PH0MBER CLI scanners by adding a deep username research/enrichment pipeline and introducing real-time scan timing output (elapsed + estimated remaining), alongside packaging/docs hygiene updates.
Changes:
- Added a deep username research pipeline using a Sherlock-style site manifest, profile probing, and best-effort public identity extraction.
- Introduced a live scan timing ticker for scanners plus a final timing/variance summary on completion.
- Added/updated project packaging and documentation artifacts (
requirements.txt,.gitignore,pyproject.toml, README updates).
Reviewed changes
Copilot reviewed 3 out of 5 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
phomber.py |
Adds live timing ticker, environment-tunable username enrichment, improved validations, and some reliability tweaks. |
README.md |
Updates install instructions and documents new timer/username behavior (partially). |
requirements.txt |
Adds a pip requirements list for running from source. |
pyproject.toml |
Adjusts runtime dependencies and console script entry point. |
.gitignore |
Adds standard Python/project ignores and history/config exclusions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| [project.scripts] | ||
| phomber = "phomber.phomber:main" | ||
|
|
||
| [project.entry-points."phomber"] | ||
| phomber = "phomber.phomber:main" No newline at end of file | ||
| phomber = "phomber:main" No newline at end of file |
There was a problem hiding this comment.
The console script entry point references phomber:main, but the project does not declare any packages/py-modules for setuptools to include. Add explicit setuptools configuration (e.g., py-modules = ["phomber"] or a package directory) so pip install . actually installs an importable phomber module for this entry point.
| - all scanners now display estimated and real-time research duration | ||
| - `username` scan now performs deep profile research across direct platform profiles and best-effort public identity extraction | ||
| - tune depth via `PHOMBER_USERNAME_IDENTITY_SOURCES` (default: `20`) | ||
| - tune per-profile fetch timeout via `PHOMBER_PROFILE_FETCH_TIMEOUT` (default: `8` seconds) |
There was a problem hiding this comment.
README mentions only PHOMBER_USERNAME_IDENTITY_SOURCES and PHOMBER_PROFILE_FETCH_TIMEOUT, but the code also introduces other tuning env vars (PHOMBER_USERNAME_SITE_LIMIT, PHOMBER_SHERLOCK_DATA_URL, PHOMBER_IPINFO_TOKEN). Document these or remove/support defaults consistently so users can understand/override the new behavior.
| - tune per-profile fetch timeout via `PHOMBER_PROFILE_FETCH_TIMEOUT` (default: `8` seconds) | |
| - tune per-profile fetch timeout via `PHOMBER_PROFILE_FETCH_TIMEOUT` (default: `8` seconds) | |
| - tune maximum number of sites checked in `username` scan via `PHOMBER_USERNAME_SITE_LIMIT` | |
| - override the Sherlock sites data source used by `username` scan via `PHOMBER_SHERLOCK_DATA_URL` | |
| - provide an IP geolocation token via `PHOMBER_IPINFO_TOKEN` to enrich IP-related lookup results |
| return complete_scan_timing('number', started_at, result) | ||
|
|
||
| # Information gathering about the number | ||
| printit(f' [+] Grathering information about \33[1;49;96m{phone_number}\33[1;49;93m...', coledt=[1, 49, 93], space_down=True) |
There was a problem hiding this comment.
Typo in user-facing output: “Grathering” should be “Gathering”.
| printit(f' [+] Grathering information about \33[1;49;96m{phone_number}\33[1;49;93m...', coledt=[1, 49, 93], space_down=True) | |
| printit(f' [+] Gathering information about \33[1;49;96m{phone_number}\33[1;49;93m...', coledt=[1, 49, 93], space_down=True) |
| return finalize_scan(False) | ||
|
|
||
| # Information gathering about the ip address | ||
| printit(f' [+] Grathering information about \33[1;49;96m{ip_address}\33[1;49;93m...', coledt=[1, 49, 93], space_down=True) |
There was a problem hiding this comment.
Typo in user-facing output: “Grathering” should be “Gathering”.
| return complete_scan_timing('mac', started_at, result) | ||
|
|
||
| # Information gathering about the mac address | ||
| printit(f' [+] Grathering information about \33[1;49;96m{mac_address}\33[1;49;93m...', coledt=[1, 49, 93], space_down=True) |
There was a problem hiding this comment.
Typo in user-facing output: “Grathering” should be “Gathering”.
| printit(f' [+] Grathering information about \33[1;49;96m{mac_address}\33[1;49;93m...', coledt=[1, 49, 93], space_down=True) | |
| printit(f' [+] Gathering information about \33[1;49;96m{mac_address}\33[1;49;93m...', coledt=[1, 49, 93], space_down=True) |
| prv_op += final_output+'\n' | ||
|
|
||
| return True | ||
| return finalize_scan(True) |
There was a problem hiding this comment.
ip_lookup always returns success (True) at the end even when all external lookups fail and the function prints a failure table. Track whether any provider actually returned usable data and return False when all providers fail so the UI expression/output state is accurate.
| def _worker(): | ||
| while not stop_event.wait(1.0): | ||
| elapsed_seconds = max(0.0, time.perf_counter() - started_at) | ||
| remaining_seconds = max(0.0, estimate_seconds - elapsed_seconds) | ||
| status_line = ( | ||
| f' [+] {scanner_name} scan running | ' | ||
| f'elapsed: {elapsed_seconds:6.1f}s | ' | ||
| f'est remaining: {remaining_seconds:6.1f}s' | ||
| ) | ||
| sys.stdout.write('\r\33[1;49;93m' + status_line.ljust(140) + '\033[0m') | ||
| sys.stdout.flush() |
There was a problem hiding this comment.
The live scan progress ticker writes to stdout from a background thread while the main scan also prints output, which can interleave and corrupt terminal formatting. Consider synchronizing writes (e.g., a shared lock) and clearing the live line before any normal print/printit output while the ticker is active.
| | \33[1;49;97mType\033[0m | \33[1;49;96mOSINT Framework\033[0m | | ||
| | \33[1;49;97mDeveloper\033[0m | \33[1;49;96ms41r4j\033[0m | | ||
| | \33[1;49;97mDeveloper\033[0m | \33[1;49;96ms41r4j, DkHrR\033[0m | | ||
| | \33[1;49;97mGithub\033[0m | \33[1;49;96mhttps://github.com/s41r4j/phomber\033[0m | |
There was a problem hiding this comment.
Brand spelling: use “GitHub” instead of “Github” in the displayed info table.
| | \33[1;49;97mGithub\033[0m | \33[1;49;96mhttps://github.com/s41r4j/phomber\033[0m | | |
| | \33[1;49;97mGitHub\033[0m | \33[1;49;96mhttps://github.com/s41r4j/phomber\033[0m | |
| return finalize_scan(False) | ||
|
|
||
| # Information gathering about the domain | ||
| printit(f' [+] Grathering information about \33[1;49;96m{domain}\33[1;49;93m...', coledt=[1, 49, 93], space_down=True) |
There was a problem hiding this comment.
Typo in user-facing output: “Grathering” should be “Gathering”.
| printit(f' [+] Grathering information about \33[1;49;96m{domain}\33[1;49;93m...', coledt=[1, 49, 93], space_down=True) | |
| printit(f' [+] Gathering information about \33[1;49;96m{domain}\33[1;49;93m...', coledt=[1, 49, 93], space_down=True) |
| try: | ||
| PHOMBER_USERNAME_SITE_LIMIT = int(os.environ.get('PHOMBER_USERNAME_SITE_LIMIT', '80')) | ||
| except (TypeError, ValueError): | ||
| PHOMBER_USERNAME_SITE_LIMIT = 80 | ||
| try: | ||
| PHOMBER_USERNAME_IDENTITY_SOURCES = int(os.environ.get('PHOMBER_USERNAME_IDENTITY_SOURCES', '20')) | ||
| except (TypeError, ValueError): | ||
| PHOMBER_USERNAME_IDENTITY_SOURCES = 20 | ||
| if PHOMBER_USERNAME_IDENTITY_SOURCES < 1: | ||
| PHOMBER_USERNAME_IDENTITY_SOURCES = 1 |
There was a problem hiding this comment.
PHOMBER_USERNAME_SITE_LIMIT is parsed from the environment but not clamped/sanitized (unlike PHOMBER_USERNAME_IDENTITY_SOURCES). If it’s set to 0 or negative, the Sherlock loop will skip all sources; consider enforcing a minimum of 1 (or explicitly documenting that 0 disables checks).
Summary
Included changes
phomber.pyelapsed+est remaining) for all scannersREADME.md.gitignoreandrequirements.txtpyproject.tomlValidation
usernameandipscans