-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlookout.py
More file actions
133 lines (111 loc) · 5.13 KB
/
lookout.py
File metadata and controls
133 lines (111 loc) · 5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import sys
import subprocess
# ------------------- Dependency Check -------------------
required_modules = ["requests", "rich"]
for module in required_modules:
try:
__import__(module)
except ImportError:
print(f"[!] Module '{module}' not found. Installing now...")
try:
subprocess.check_call([sys.executable, "-m", "pip", "install", module])
print(f"[+] Module '{module}' installed successfully.")
except subprocess.CalledProcessError:
print(f"[x] Failed to install '{module}'. Please install manually and rerun.")
sys.exit(1)
import os
import json
import requests
import time
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.live import Live
console = Console()
# ------------------- Banner -------------------
def print_banner():
banner_text = """
__ _____ _____ _____ _____ _____ _____
| | | | | | | | | |_ _|
| |__| | | | | -| | | | | | |
|_____|_____|_____|__|__|_____|_____| |_| .OSINT TOOL
Intended Use: For ethical, personal username discovery only.
Do not use for harassment, doxxing, or illegal activity.
CREATED WITH 🖤 BY https://github.com/cmdKiller
"""
console.print(Panel.fit(banner_text, style="#008000"))
# ------------------- Utilities -------------------
def normalize_username(username: str) -> str:
"""Clean up username input."""
username = username.lower().strip()
username = username.replace(" ", "_")
username = "".join(c for c in username if c.isalnum() or c in "_-")
return username
# ------------------- Load Sites -------------------
def load_sites(json_path="sites/all_sites.json", include_nsfw=False):
with open(json_path, "r", encoding="utf-8") as f:
data = json.load(f)
socials = data.get("social", {})
nsfw = data.get("nsfw", {}) if include_nsfw else {}
return socials, nsfw
# ------------------- Check Username -------------------
def check_username(username: str, site_info: dict) -> bool:
url = site_info["url"].format(username)
headers = site_info.get("headers", {})
try:
response = requests.get(url, headers=headers, timeout=10)
if "errorMsg" in site_info:
return site_info["errorMsg"] not in response.text
elif site_info.get("errorType") == "status_code":
return response.status_code == 200
elif site_info.get("errorType") == "response_url":
error_url = site_info.get("errorUrl", "")
return response.url != error_url.format(username)
else:
return True
except requests.RequestException:
return False
# ------------------- Build Table -------------------
def build_table(username: str, sites: dict, title: str, results_dict: dict) -> Table:
table = Table(title=f"{title} 🔍 [bold cyan]{username}[/bold cyan]", title_style="bold magenta")
table.add_column("Site", style="yellow")
table.add_column("Status", style="bold")
table.add_column("URL", style="cyan")
for site_name, site_info in sites.items():
exists = results_dict.get(site_name)
if exists is None:
status_text = "[grey]Checking...[/grey]"
url_text = "-"
else:
status_text = "FOUND ✅" if exists else "NOT FOUND ❌"
url_text = site_info["url"].format(username)
table.add_row(site_name, status_text, url_text)
return table
# ------------------- Main Program -------------------
def main():
os.system("cls" if os.name == "nt" else "clear")
print_banner()
raw_username = console.input("Enter a username to check: ")
username = normalize_username(raw_username)
include_nsfw = console.input("Include NSFW sites? (y/N): ").strip().lower() == "y"
socials, nsfw = load_sites(include_nsfw=include_nsfw)
# Merge socials + NSFW (if included) into one dictionary for live scanning
all_sites = {**socials, **nsfw} if include_nsfw else {**socials}
results_all = {site: None for site in all_sites}
with Live(refresh_per_second=6) as live:
for site_name, site_info in all_sites.items():
results_all[site_name] = check_username(username, site_info)
live.update(build_table(username, all_sites, "Lookout Scan", results_all))
time.sleep(0.03) # sexy pacing so it feels live
total_found = sum(results_all.values())
total_not_found = len(results_all) - total_found
# ------------------- Summary -------------------
summary = Table(title="📊 Summary", title_style="bold magenta")
summary.add_column("Category", style="yellow")
summary.add_column("Found", style="green")
summary.add_column("Not Found", style="red")
summary.add_row("All Sites", str(total_found), str(total_not_found))
console.print(summary)
console.print(Panel.fit(f"💥 Scan for [bold cyan]{username}[/bold cyan] Complete! 💥", style="bold magenta"))
if __name__ == "__main__":
main()