Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import tkinter as tk
- from tkinter import filedialog, ttk, messagebox
- import csv
- import requests
- import os
- import json
- import threading
- class PhoneLookupApp:
- def __init__(self, root):
- self.root = root
- self.root.title("Bulk Phone Number Lookup Tool: r/OSINT")
- self.root.geometry("600x400")
- self.root.resizable(True, True)
- # Variables
- self.api_key = tk.StringVar()
- self.file_path = tk.StringVar()
- self.status_text = tk.StringVar()
- self.status_text.set("Ready")
- self.progress_var = tk.DoubleVar()
- self.progress_var.set(0)
- # Create UI elements
- self.create_widgets()
- # Processing flag
- self.processing = False
- def create_widgets(self):
- # Main frame
- main_frame = ttk.Frame(self.root, padding="10")
- main_frame.pack(fill=tk.BOTH, expand=True)
- # API Key section
- api_frame = ttk.LabelFrame(main_frame, text="API Configuration", padding="10")
- api_frame.pack(fill=tk.X, pady=5)
- ttk.Label(api_frame, text="Trestle API Key:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
- ttk.Entry(api_frame, textvariable=self.api_key, width=50, show="*").grid(row=0, column=1, sticky=tk.W, padx=5, pady=5)
- # File selection section
- file_frame = ttk.LabelFrame(main_frame, text="File Selection", padding="10")
- file_frame.pack(fill=tk.X, pady=5)
- ttk.Label(file_frame, text="CSV File:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
- ttk.Entry(file_frame, textvariable=self.file_path, width=40).grid(row=0, column=1, sticky=tk.W, padx=5, pady=5)
- ttk.Button(file_frame, text="Browse...", command=self.browse_file).grid(row=0, column=2, sticky=tk.W, padx=5, pady=5)
- # Process button
- process_frame = ttk.Frame(main_frame)
- process_frame.pack(fill=tk.X, pady=10)
- ttk.Button(process_frame, text="Process Phone Numbers", command=self.start_processing).pack(anchor=tk.CENTER)
- # Progress bar
- progress_frame = ttk.LabelFrame(main_frame, text="Progress", padding="10")
- progress_frame.pack(fill=tk.X, pady=5)
- self.progress_bar = ttk.Progressbar(progress_frame, variable=self.progress_var, maximum=100)
- self.progress_bar.pack(fill=tk.X, padx=5, pady=5)
- # Status label
- status_frame = ttk.Frame(main_frame)
- status_frame.pack(fill=tk.X, pady=5)
- ttk.Label(status_frame, textvariable=self.status_text).pack(anchor=tk.W)
- def browse_file(self):
- file_path = filedialog.askopenfilename(
- title="Select CSV File",
- filetypes=[("CSV Files", "*.csv"), ("All Files", "*.*")]
- )
- if file_path:
- self.file_path.set(file_path)
- def start_processing(self):
- # Validate inputs
- if not self.api_key.get().strip():
- messagebox.showerror("Error", "Please enter your Trestle API Key")
- return
- if not self.file_path.get().strip():
- messagebox.showerror("Error", "Please select a CSV file")
- return
- if not os.path.exists(self.file_path.get()):
- messagebox.showerror("Error", "Selected file does not exist")
- return
- # Prevent multiple processing
- if self.processing:
- messagebox.showinfo("Info", "Processing is already in progress")
- return
- # Start processing in a separate thread
- self.processing = True
- self.progress_var.set(0)
- self.status_text.set("Starting processing...")
- processing_thread = threading.Thread(target=self.process_file)
- processing_thread.daemon = True
- processing_thread.start()
- def process_file(self):
- try:
- # Read phone numbers from CSV
- phone_numbers = self.read_phone_numbers()
- if not phone_numbers:
- self.status_text.set("No phone numbers found in the CSV file")
- self.processing = False
- return
- # Create output file path
- input_file = self.file_path.get()
- file_name, file_ext = os.path.splitext(input_file)
- output_file = f"{file_name}complete.csv"
- # Process each phone number
- total_numbers = len(phone_numbers)
- processed_numbers = 0
- # Prepare output CSV
- with open(output_file, 'w', newline='', encoding='utf-8') as csvfile:
- # We'll determine headers after the first API call
- csv_writer = None
- for phone_number in phone_numbers:
- # Update status
- self.status_text.set(f"Processing {phone_number} ({processed_numbers + 1}/{total_numbers})")
- # Call API
- result = self.lookup_phone_number(phone_number)
- # Initialize CSV writer with headers if this is the first result
- if csv_writer is None and result:
- # Flatten the result for CSV headers
- headers = self.flatten_dict_keys(result)
- csv_writer = csv.DictWriter(csvfile, fieldnames=headers)
- csv_writer.writeheader()
- # Write result to CSV
- if result and csv_writer:
- # Flatten the nested dictionaries for CSV
- flat_result = self.flatten_dict(result)
- csv_writer.writerow(flat_result)
- # Update progress
- processed_numbers += 1
- progress_percentage = (processed_numbers / total_numbers) * 100
- self.progress_var.set(progress_percentage)
- # Complete
- self.status_text.set(f"Processing complete. Results saved to {output_file}")
- messagebox.showinfo("Success", f"Processing complete. Results saved to {output_file}")
- except Exception as e:
- self.status_text.set(f"Error: {str(e)}")
- messagebox.showerror("Error", f"An error occurred: {str(e)}")
- finally:
- self.processing = False
- def read_phone_numbers(self):
- phone_numbers = []
- try:
- with open(self.file_path.get(), 'r', newline='', encoding='utf-8') as csvfile:
- csv_reader = csv.reader(csvfile)
- for row in csv_reader:
- if row and row[0].strip():
- # Assuming phone number is in the first column
- phone_number = row[0].strip()
- phone_numbers.append(phone_number)
- return phone_numbers
- except Exception as e:
- self.status_text.set(f"Error reading CSV: {str(e)}")
- messagebox.showerror("Error", f"Error reading CSV: {str(e)}")
- return []
- def lookup_phone_number(self, phone_number):
- try:
- # Prepare API request
- api_url = f"https://api.trestleiq.com/3.2/phone?phone={phone_number}"
- headers = {
- "x-api-key": self.api_key.get()
- }
- # Make API request
- response = requests.get(api_url, headers=headers)
- # Check for errors
- if response.status_code != 200:
- error_message = f"API Error: {response.status_code} - {response.text}"
- self.status_text.set(error_message)
- return None
- # Parse response
- result = response.json()
- # Add the original phone number to the result
- result['original_phone_number'] = phone_number
- return result
- except requests.exceptions.RequestException as e:
- self.status_text.set(f"API Request Error: {str(e)}")
- return None
- except json.JSONDecodeError:
- self.status_text.set("Error parsing API response")
- return None
- def flatten_dict_keys(self, d, parent_key='', sep='_'):
- """Get all keys from a nested dictionary for CSV headers"""
- items = []
- for k, v in d.items():
- new_key = f"{parent_key}{sep}{k}" if parent_key else k
- if isinstance(v, dict):
- items.extend(self.flatten_dict_keys(v, new_key, sep=sep))
- elif isinstance(v, list) and v and isinstance(v[0], dict):
- # For the first item in a list of dictionaries
- items.extend(self.flatten_dict_keys(v[0], f"{new_key}_0", sep=sep))
- else:
- items.append(new_key)
- return items
- def flatten_dict(self, d, parent_key='', sep='_'):
- """Flatten a nested dictionary for CSV output"""
- items = {}
- for k, v in d.items():
- new_key = f"{parent_key}{sep}{k}" if parent_key else k
- if isinstance(v, dict):
- items.update(self.flatten_dict(v, new_key, sep=sep))
- elif isinstance(v, list):
- if v and isinstance(v[0], dict):
- # Handle list of dictionaries (just take the first one for simplicity)
- items.update(self.flatten_dict(v[0], f"{new_key}_0", sep=sep))
- else:
- # Handle list of primitives
- items[new_key] = str(v)
- else:
- items[new_key] = v
- return items
- def main():
- root = tk.Tk()
- app = PhoneLookupApp(root)
- root.mainloop()
- if __name__ == "__main__":
- main()
Advertisement
Add Comment
Please, Sign In to add comment