-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathcc.py
More file actions
254 lines (207 loc) · 10.3 KB
/
Copy pathcc.py
File metadata and controls
254 lines (207 loc) · 10.3 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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
import argparse
import json
import requests
import random
from rich.console import Console
from rich.progress import Progress, SpinnerColumn, BarColumn, TextColumn
from time import sleep
from collections import defaultdict
from concurrent.futures import ThreadPoolExecutor, as_completed
# Initialize the console for rich text output
console = Console()
ASCII_ART = r"""
[bold cyan]_
[bold magenta].-'` |___________________________//////
[bold cyan]`'-._|https://github.com/OSINTI4L\\\\\\
[bold blue]_ __ __ __ __
[bold cyan]_______ ______ (_)___/ /_________/ // /_ __/ /
[bold magenta]/ ___/ / / / __ \/ / __ / ___/ ___/ // /| | /| / / /
[bold blue]/ /__/ /_/ / /_/ / / /_/ / /__/ / /__ __/ |/ |/ / /
[bold cyan]\___/\__,_/ .___/_/\__,_/\___/_/ /_/ |__/|__/_/
[bold magenta]/_/
"""
def display_ascii_art():
"""Display hardcoded ASCII art directly in the console."""
console.print(ASCII_ART)
def strip_color_tags(text):
"""Remove all color tags like [green] and [/green] from the given text."""
while '[' in text and ']' in text:
start = text.find('[')
end = text.find(']', start) + 1
text = text[:start] + text[end:] # Remove color tags
return text
def load_websites(file_path):
"""Load website information from a JSON file and organize by category."""
with open(file_path, 'r') as file:
data = json.load(file)
categorized_websites = defaultdict(dict)
for site, info in data['websites'].items():
category = info.get("category", "Other")
categorized_websites[category][site] = info
return categorized_websites
def load_user_agents(file_path):
"""Load user agents from a text file."""
with open(file_path, 'r') as file:
user_agents = file.read().splitlines()
return user_agents
def write_message(message, write_to_file=None):
"""Write message to console and optionally to a file."""
console.print(message)
if write_to_file:
write_to_file.write(strip_color_tags(message) + "\n")
def check_single_site(username, site, info, user_agents, write_to_file=None, debug=False):
"""Check a single site for the username."""
url = info.get("url").format(username=username)
check_texts = info.get("check_text", [])
not_found_texts = info.get("not_found_text", [])
headers = {
"User-Agent": random.choice(user_agents)
}
if not url or not check_texts:
write_message(f"[yellow]Skipping {site}: URL or check text missing.[/yellow]", write_to_file)
return
try:
response = requests.get(url, headers=headers, timeout=5)
response_code = f" (Response code: {response.status_code})" if debug else ""
# Identify which specific texts matched
matching_check_texts = [check_text for check_text in check_texts if check_text.lower() in response.text.lower()]
matching_not_found_texts = [not_found_text for not_found_text in not_found_texts if not_found_text.lower() in response.text.lower()]
# Determine the status and construct the appropriate message
if response.status_code == 200:
if matching_check_texts:
message = f"[green]Account found on {site}: {url}{response_code}[/green]"
if debug:
matched_items = ", ".join(matching_check_texts)
message += f" [cyan](Matched check_text items: {matched_items})[/cyan]"
elif matching_not_found_texts:
message = f"[red]No account found on {site}.{response_code}[/red]"
if debug:
matched_items = ", ".join(matching_not_found_texts)
message += f" [cyan](Matched not_found_text items: {matched_items})[/cyan]"
else:
message = f"[yellow]Possible account found on {site}: {url}{response_code}[/yellow]"
else:
message = f"[red]No account found on {site}.{response_code}[/red]"
if debug and matching_not_found_texts:
matched_items = ", ".join(matching_not_found_texts)
message += f" [cyan](Matched not_found_text items: {matched_items})[/cyan]"
except requests.Timeout:
message = f"[bold red]Timeout while checking {site}.[/bold red]"
except requests.RequestException as e:
message = f"[bold red]Network error checking {site}: {str(e)}.[/bold red]"
# Simplified message writing logic
write_message(message, write_to_file) if debug or "[green]" in message or "[yellow]" in message else None
def print_category_header(category, write_to_file=None):
"""Print and optionally write category header."""
message = f"\n[bold blue]Checking {category} platforms:[/bold blue]"
write_message(message, write_to_file)
def check_usernames(usernames, user_agents, write_to_file=None, debug=False):
"""Check the provided usernames across various websites."""
websites_by_category = load_websites('websites.json')
# Outer loop for each username
for username in usernames:
# Write username header to the results file, if applicable
if write_to_file:
write_to_file.write(f"\nResults for {username}:\n") # Add a header for the username in the file
console.print(f"\n[bold cyan]Checking username: {username}[/bold cyan]") # Print username being checked
with Progress(
SpinnerColumn(style="bold cyan"),
BarColumn(bar_width=None, complete_style="magenta"),
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
TextColumn("{task.description}"),
console=console
) as progress:
total_sites = sum(len(sites) for sites in websites_by_category.values())
overall_task = progress.add_task(f"[bold magenta]Checking {username}...", total=total_sites)
for category, sites in websites_by_category.items():
print_category_header(category, write_to_file)
with ThreadPoolExecutor(max_workers=4) as executor:
future_to_site = {
executor.submit(check_single_site, username.strip(), site, info, user_agents, write_to_file, debug): site
for site, info in sites.items()
}
for future in as_completed(future_to_site):
site = future_to_site[future]
try:
future.result()
except Exception as e:
write_message(f"[bold red]Error checking {site}: {e}[/bold red]", write_to_file)
progress.update(overall_task, advance=1) # Advance the task for the overall progress
sleep(0.2)
progress.update(overall_task, completed=total_sites) # Mark the task as completed after finishing all sites
class SpacingHelpFormatter(argparse.HelpFormatter):
"""Custom help formatter for argparse to add spacing."""
def _split_lines(self, text, width):
lines = super()._split_lines(text, width)
lines.append('') # Add a blank line for spacing
return lines
def print_sites(file_path='websites.json'):
"""Print all site names and their URLs from the JSON file."""
try:
with open(file_path, 'r') as file:
data = json.load(file)
console.print("\n[bold blue]Sites and URLs searched by cupidcr4wl:[/bold blue]")
for site, info in data['websites'].items():
url = info.get("url", "No URL available")
console.print(f"- {site}: {url}")
except FileNotFoundError:
console.print("[bold red]websites.json file not found![/bold red]")
except json.JSONDecodeError:
console.print("[bold red]Error decoding JSON from websites.json![/bold red]")
def parse_arguments():
"""Parse command-line arguments for the script."""
parser = argparse.ArgumentParser(
description="A tool for checking if an account exists across various websites.",
formatter_class=SpacingHelpFormatter
)
parser.add_argument(
"-u",
type=str,
required=False,
help="Enter a username or multiple usernames (separated by commas) to search.",
metavar="USERNAME"
)
parser.add_argument(
"--export-results",
action="store_true",
help="Search results will be exported to a text file named 'cc_results.txt'."
)
parser.add_argument(
"--debug",
action="store_true",
help="Debug mode, shows HTTP response codes and check_text/not_found_text matches for each site checked."
)
parser.add_argument(
"--sites",
action="store_true",
help="Print all sites that cupidcr4wl will check."
)
return parser.parse_args()
def main():
"""Main entry point for the script."""
display_ascii_art() # Show ASCII art
args = parse_arguments() # Parse command-line arguments
# Check if no usernames are provided and print usage information
if args.u is None and not args.sites:
console.print("[bold red]Error: Username and arguments required, see -h or --help.[/bold red]")
return
user_agents = load_user_agents('user_agents.txt') # Load user agents from file
if args.sites:
print_sites() # Print available sites and their URLs
return # Exit after printing sites
usernames = args.u.split(",") if args.u else [] # Split usernames by comma if provided
# Check usernames and handle result file writing
write_to_file = None # Initialize the file variable
if args.export_results and usernames:
result_file_name = f'cc_results.txt' # Create the result file name
write_to_file = open(result_file_name, 'w') # Open file only if conditions are met
try:
check_usernames(usernames, user_agents, write_to_file, args.debug) # Check usernames
# Print a message indicating results have been saved if exporting is enabled
if args.export_results and usernames:
console.print(f"[bold cyan]Results have been saved to '{result_file_name}'[/bold cyan]")
finally:
if write_to_file:
write_to_file.close() # Close the file if it was opened
if __name__ == "__main__":
main() # Call the main function to run the script