# Admiral SYN-ACKbar's AbuseIPDB Bulk Checker (https://github.com/AdmiralSYN-ACKbar/AbuseIPDB-Bulk-Checker)
import csv #implements classes to read and write tabular data in CSV format
import requests #allows sending/receiving HTTP requests
import json #parse JSON strings
import os #provides functions for interacting with the operating system
import tkinter as tk #GUI toolkit
from tkinter import filedialog, ttk, messagebox #filedialog: open/save files; ttk: themed widgets; messagebox: display message boxes
import time #time-related functions
import math #mathematical functions
def bulk_check(csv_path, api_key, export_path, progress, output_box):
start_time = time.time()
json_temp_path = os.path.join(os.path.dirname(export_path), 'aipdbulkchecktempfile.json') # Create a named temporary file in the output directory
try:
with open(csv_path, 'r') as file: # Open the input CSV file
csv_reader = csv.reader(file)
total_rows = sum(1 for row in csv_reader) # Calculate the total number of rows in the CSV file
file.seek(0) # Reset file pointer to beginning
for i, row in enumerate(csv_reader): # Process each row in the CSV file
ip = row[0] # Extract the IP address from the row
# Send a request to the AbuseIPDB API to check the IP address
response = requests.get(f"https://api.abuseipdb.com/api/v2/check?ipAddress={ip}", headers={'Accept': 'application/json', 'Key': api_key})
if response.status_code == 200: # If the API request was successful
with open(json_temp_path, 'a') as json_file: # Write the response to the temporary JSON file
json_file.write(json.dumps(response.json()) + "\n")
else: # If the API request was not successful
output_box.delete('1.0', tk.END) # Clear the output box
output_box.insert(tk.END, f"{ip} is not a valid IP!") # Display an error message
progress['value'] = (i + 1) / total_rows * 100 # Update the progress bar
output_box.delete('1.0', tk.END) # Clear the output box
output_box.insert(tk.END, f"Processing {i + 1} of {total_rows}") # Display the current progress
root.update_idletasks() # Update the Tkinter GUI
end_time = time.time() # Record the end time of the function
elapsed_time = end_time - start_time # Calculate the total elapsed time
elapsed_minutes, elapsed_seconds = divmod(elapsed_time, 60) # Convert the elapsed time from seconds to minutes and seconds
elapsed_minutes = math.floor(elapsed_minutes) # Round down the number of elapsed minutes to the nearest whole number
elapsed_seconds = round(elapsed_seconds, 1) # Round the number of elapsed seconds to one decimal place
# Calculate the average time per IP address. If no rows were processed, set the average time to 0 to avoid division by zero.
avg_time_per_ip = elapsed_time / total_rows if total_rows > 0 else 0
avg_time_per_ip = round(avg_time_per_ip, 1) # Round the average time per IP address to one decimal place
with open(json_temp_path, 'r') as json_file, open(export_path, 'w', newline='') as csv_file: # Open the temporary JSON file and the output CSV file
csv_writer = csv.writer(csv_file) # Create a CSV writer
csv_writer.writerow(["ipAddress", "abuseConfidenceScore", "isp", "domain", "countryCode", "totalReports", "lastReportedAt"]) # Write the header row to the CSV file
for line in json_file: # Process each line in the JSON file
data = json.loads(line)["data"] # Parse the JSON data
csv_writer.writerow([data["ipAddress"], data["abuseConfidenceScore"], data["isp"], data["domain"], data["countryCode"], data["totalReports"], data["lastReportedAt"]]) # Write the data to the CSV file
except Exception as e: # Handle any exceptions that occur during the file processing
output_box.delete('1.0', tk.END) # Clear the output box
output_box.insert(tk.END, f"An error occurred: {str(e)}") # Display the error message
finally:
if os.path.exists(json_temp_path): # If the temporary file exists
os.remove(json_temp_path) # Delete the temporary file
output_box.delete('1.0', tk.END) # Clear the output box
output_box.insert(tk.END, f"Started check of {total_rows} IPs at {time.strftime('%b %d %H:%M:%S', time.localtime(start_time))}\nCompleted check at {time.strftime('%b %d %H:%M:%S', time.localtime(end_time))}\nTime elapsed was {elapsed_minutes} minutes and {elapsed_seconds} seconds\nAverage time per IP checked was {avg_time_per_ip} seconds\n\nThe Admiralty commends you for your efforts!") # Display the final results
def browse_file(entry): # Define a function to browse for a file
filename = filedialog.askopenfilename() # Open a file dialog and get the selected filename
entry.delete(0, tk.END) # Clear the entry box
entry.insert(0, filename) # Insert the filename into the entry box
def browse_save_file(entry): # Define a function to browse for a file save
filename = filedialog.asksaveasfilename(defaultextension=".csv", filetypes=[("CSV files", "*.csv")]) # Open a save file dialog and get the selected filename
if filename: # If a filename was selected
if os.path.exists(filename): # If the file already exists
if messagebox.askokcancel("Warning", "The file already exists. Do you want to overwrite it?"): # Ask the user if they want to overwrite the existing file
entry.delete(0, tk.END) # Clear the entry box
entry.insert(0, filename) # Insert the filename into the entry box
else: # If the file does not exist
entry.delete(0, tk.END) # Clear the entry box
entry.insert(0, filename) # Insert the filename into the entry box
def main():
global root
root = tk.Tk() # Create the main window
root.title("Admiral SYN-ACKbar's AbuseIPDB Bulk Checker") # Set the title of the window
root.geometry("500x600") # Set the size of the window
frame = ttk.Frame(root, padding="10") # Create a frame widget
frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S)) # Place the frame on the grid
# Create and place two title labels
title_label1 = ttk.Label(frame, text="Admiral SYN-ACKbar's", font=("Sylfaen", 14, "italic"))
title_label1.grid(row=0, column=0, columnspan=3)
title_label2 = ttk.Label(frame, text="AbuseIPDB Bulk Checker", font=("Sylfaen", 18, "bold"))
title_label2.grid(row=1, column=0, columnspan=3)
# Create and place the API key label and entry box
api_label = ttk.Label(frame, text="API Key:")
api_label.grid(row=2, column=0, sticky=tk.W)
api_entry = ttk.Entry(frame, width=30, show="*")
api_entry.grid(row=2, column=1, sticky=(tk.W, tk.E))
# Create and place the CSV input file path label, entry box, and browse button
csv_label = ttk.Label(frame, text="CSV Input File Path / Name:")
csv_label.grid(row=3, column=0, sticky=tk.W)
csv_entry = ttk.Entry(frame, width=30)
csv_entry.grid(row=3, column=1, sticky=(tk.W, tk.E))
csv_button = ttk.Button(frame, text="Browse", command=lambda: browse_file(csv_entry))
csv_button.grid(row=3, column=2, sticky=tk.W)
# Create and place the CSV export file path label, entry box, and browse button
export_label = ttk.Label(frame, text="CSV Export File Path / Name:")
export_label.grid(row=4, column=0, sticky=tk.W)
export_entry = ttk.Entry(frame, width=30)
export_entry.grid(row=4, column=1, sticky=(tk.W, tk.E))
export_button = ttk.Button(frame, text="Browse", command=lambda: browse_save_file(export_entry))
export_button.grid(row=4, column=2, sticky=tk.W)
# Create and place the submit button
style = ttk.Style()
style.configure('Engage.TButton', font=("Sylfaen", 14, "bold"))
style.configure('Engage.TButton', background='red')
submit_button = ttk.Button(frame, text="ENGAGE", command=lambda: bulk_check(csv_entry.get(), api_entry.get(), export_entry.get(), progress, output_box), style='Engage.TButton')
submit_button.grid(row=5, column=0, columnspan=3, sticky=(tk.W, tk.E))
# Create and place the output label, progress bar, and output box
output_label = ttk.Label(frame, text="Output:", font=("Sylfaen", 14, "bold"))
output_label.grid(row=6, column=0, sticky=tk.W)
progress = ttk.Progressbar(frame, orient='horizontal', length=300, mode='determinate')
progress.grid(row=7, column=0, columnspan=3, sticky=(tk.W, tk.E))
output_box = tk.Text(frame, width=50, height=9)
output_box.grid(row=8, column=0, columnspan=3, sticky=(tk.W, tk.E))
# Create and place the quit button
style.configure('RunAway.TButton', font=("Sylfaen", 14, "bold"))
style.configure('RunAway.TButton', background='blue')
quit_button = ttk.Button(frame, text="RUN AWAY", command=root.destroy, style='RunAway.TButton')
quit_button.grid(row=9, column=0, columnspan=3, sticky=(tk.W, tk.E))
# Add padding to all child widgets of the frame
for child in frame.winfo_children():
child.grid_configure(padx=5, pady=5)
root.mainloop() # Start the Tkinter event loop
if __name__ == "__main__":
main() # Call the main function if the script is being run directly