diff --git a/main.py b/main.py index 411e010..9c0ce52 100644 --- a/main.py +++ b/main.py @@ -62,7 +62,7 @@ class App: self.running = True if not (discord_webhook_url.startswith("https://") or do_mock_discord): - msg = f'{discord_webhook_url} не вебхук, так то' + msg = f"{discord_webhook_url} не вебхук, так то" print(msg) raise RuntimeError(msg) @@ -83,7 +83,7 @@ class App: for line in self.monitor_log_file(): if not self.running: break - + process_important_realtime_events = self.do_backread or line.is_realtime if "" in line.line: @@ -107,7 +107,7 @@ class App: msg = f"💀 **{kill.victim}** killed by 🔫 **{kill.killer}**" self.send(msg) - + # Call the callback if provided if self.kill_callback: self.kill_callback(kill, msg) @@ -158,53 +158,80 @@ class DeathLogGUI: self.root.title("Star Citizen Death Log Monitor") self.root.geometry("800x600") self.root.minsize(600, 400) - + self.log_path = tk.StringVar(value=str(DEFAULT_LOG_FILE_PATH)) self.webhook_url = tk.StringVar(value=DEFAULT_DISCORD_WEBHOOK_URL) self.do_backread = tk.BooleanVar(value=False) self.do_mock_discord = tk.BooleanVar(value=False) self.hide_npc_kills = tk.BooleanVar(value=True) - + self.app = None self.monitor_thread = None self.kill_queue = queue.Queue() self.recent_kills: list[str] = [] self.max_kills_to_display = 100 - + self.create_widgets() self.update_kill_display() - + def create_widgets(self): # Create main frame main_frame = ttk.Frame(self.root, padding="10") main_frame.pack(fill=tk.BOTH, expand=True) - + # Configuration section config_frame = ttk.LabelFrame(main_frame, text="Configuration", padding="10") config_frame.pack(fill=tk.X, pady=5) - + # Log file path - ttk.Label(config_frame, text="Log File Path:").grid(row=0, column=0, sticky=tk.W, pady=2) - ttk.Entry(config_frame, textvariable=self.log_path, width=50).grid(row=0, column=1, sticky=tk.W+tk.E, pady=2, padx=5) - ttk.Button(config_frame, text="Browse", command=self.browse_log_file).grid(row=0, column=2, pady=2) - + ttk.Label(config_frame, text="Log File Path:").grid( + row=0, column=0, sticky=tk.W, pady=2 + ) + ttk.Entry(config_frame, textvariable=self.log_path, width=50).grid( + row=0, column=1, sticky=tk.W + tk.E, pady=2, padx=5 + ) + ttk.Button(config_frame, text="Browse", command=self.browse_log_file).grid( + row=0, column=2, pady=2 + ) + # Discord webhook URL - ttk.Label(config_frame, text="Discord Webhook URL:").grid(row=1, column=0, sticky=tk.W, pady=2) - ttk.Entry(config_frame, textvariable=self.webhook_url, width=50).grid(row=1, column=1, sticky=tk.W+tk.E, pady=2, padx=5) + ttk.Label(config_frame, text="Discord Webhook URL:").grid( + row=1, column=0, sticky=tk.W, pady=2 + ) + ttk.Entry(config_frame, textvariable=self.webhook_url, width=50).grid( + row=1, column=1, sticky=tk.W + tk.E, pady=2, padx=5 + ) # Checkboxes - ttk.Checkbutton(config_frame, text="Process existing log entries", variable=self.do_backread).grid(row=2, column=0, columnspan=2, sticky=tk.W, pady=2) - ttk.Checkbutton(config_frame, text="Mock Discord (don't send actual messages)", variable=self.do_mock_discord).grid(row=3, column=0, columnspan=2, sticky=tk.W, pady=2) - ttk.Checkbutton(config_frame, text="Hide NPC kills (_NPC_ in name)", variable=self.hide_npc_kills).grid(row=4, column=0, columnspan=2, sticky=tk.W, pady=2) + ttk.Checkbutton( + config_frame, text="Process existing log entries", variable=self.do_backread + ).grid(row=2, column=0, columnspan=2, sticky=tk.W, pady=2) + ttk.Checkbutton( + config_frame, + text="Mock Discord (don't send actual messages)", + variable=self.do_mock_discord, + ).grid(row=3, column=0, columnspan=2, sticky=tk.W, pady=2) + ttk.Checkbutton( + config_frame, + text="Hide NPC kills (_NPC_ in name)", + variable=self.hide_npc_kills, + ).grid(row=4, column=0, columnspan=2, sticky=tk.W, pady=2) # Control buttons control_frame = ttk.Frame(main_frame) control_frame.pack(fill=tk.X, pady=5) - self.start_button = ttk.Button(control_frame, text="Start Monitoring", command=self.start_monitoring) + self.start_button = ttk.Button( + control_frame, text="Start Monitoring", command=self.start_monitoring + ) self.start_button.pack(side=tk.LEFT, padx=5) - self.stop_button = ttk.Button(control_frame, text="Stop Monitoring", command=self.stop_monitoring, state=tk.DISABLED) + self.stop_button = ttk.Button( + control_frame, + text="Stop Monitoring", + command=self.stop_monitoring, + state=tk.DISABLED, + ) self.stop_button.pack(side=tk.LEFT, padx=5) # Status indicator @@ -212,25 +239,31 @@ class DeathLogGUI: status_frame = ttk.Frame(main_frame) status_frame.pack(fill=tk.X, pady=5) ttk.Label(status_frame, text="Status:").pack(side=tk.LEFT) - self.status_label = ttk.Label(status_frame, textvariable=self.status_var, foreground="red") + self.status_label = ttk.Label( + status_frame, textvariable=self.status_var, foreground="red" + ) self.status_label.pack(side=tk.LEFT, padx=5) # Kill events display - kills_frame = ttk.LabelFrame(main_frame, text="Recent Kill Events", padding="10") + kills_frame = ttk.LabelFrame( + main_frame, text="Recent Kill Events", padding="10" + ) kills_frame.pack(fill=tk.BOTH, expand=True, pady=5) - self.kill_display = scrolledtext.ScrolledText(kills_frame, wrap=tk.WORD, height=10) + self.kill_display = scrolledtext.ScrolledText( + kills_frame, wrap=tk.WORD, height=10 + ) self.kill_display.pack(fill=tk.BOTH, expand=True) self.kill_display.config(state=tk.DISABLED) def browse_log_file(self): filename = filedialog.askopenfilename( title="Select Star Citizen Log File", - filetypes=[("Log Files", "*.log"), ("All Files", "*.*")] + filetypes=[("Log Files", "*.log"), ("All Files", "*.*")], ) if filename: self.log_path.set(filename) - + def start_monitoring(self): if self.monitor_thread and self.monitor_thread.is_alive(): return @@ -238,44 +271,46 @@ class DeathLogGUI: try: log_path = Path(self.log_path.get()) webhook_url = self.webhook_url.get() - + self.app = App( log_file_path=log_path, discord_webhook_url=webhook_url, do_backread=self.do_backread.get(), do_mock_discord=self.do_mock_discord.get(), hide_npc_kills=self.hide_npc_kills.get(), - kill_callback=self.on_kill + kill_callback=self.on_kill, + ) + + self.monitor_thread = threading.Thread( + target=self.app.process_lines, daemon=True ) - - self.monitor_thread = threading.Thread(target=self.app.process_lines, daemon=True) self.monitor_thread.start() - + self.status_var.set("Monitoring active") self.status_label.config(foreground="green") self.start_button.config(state=tk.DISABLED) self.stop_button.config(state=tk.NORMAL) - + except Exception as e: self.status_var.set(f"Error: {str(e)}") self.status_label.config(foreground="red") - + def stop_monitoring(self): if self.app: self.app.stop() - + if self.monitor_thread: self.monitor_thread.join(timeout=1.0) - + self.status_var.set("Monitoring stopped") self.status_label.config(foreground="red") self.start_button.config(state=tk.NORMAL) self.stop_button.config(state=tk.DISABLED) - + def on_kill(self, kill: Kill, message: str): # No need to filter here as it's already filtered in the App class self.kill_queue.put((kill, message)) - + def update_kill_display(self): while not self.kill_queue.empty(): try: @@ -285,12 +320,14 @@ class DeathLogGUI: if kill.victim == kill.killer: formatted_message = f"[{timestamp}] 🤦 {kill.victim} (self-kill)\n" else: - formatted_message = f"[{timestamp}] 💀 {kill.victim} killed by 🔫 {kill.killer}\n" + formatted_message = ( + f"[{timestamp}] 💀 {kill.victim} killed by 🔫 {kill.killer}\n" + ) self.recent_kills.append(formatted_message) if len(self.recent_kills) > self.max_kills_to_display: self.recent_kills.pop(0) - + self.kill_display.config(state=tk.NORMAL) self.kill_display.delete(1.0, tk.END) for msg in self.recent_kills: @@ -299,7 +336,7 @@ class DeathLogGUI: self.kill_display.see(tk.END) except queue.Empty: break - + self.root.after(100, self.update_kill_display) @@ -307,13 +344,24 @@ def main(): try: # Check if we should run in GUI mode or CLI mode import sys + if len(sys.argv) > 1 and sys.argv[1] == "--cli": # CLI mode if DEBUG is True: - app = App(Path("./Game.log"), DEFAULT_DISCORD_WEBHOOK_URL, do_mock_discord=True, do_backread=True, hide_npc_kills=False) + app = App( + Path("./Game.log"), + DEFAULT_DISCORD_WEBHOOK_URL, + do_mock_discord=True, + do_backread=True, + hide_npc_kills=False, + ) else: - app = App(DEFAULT_LOG_FILE_PATH, DEFAULT_DISCORD_WEBHOOK_URL, hide_npc_kills=False) + app = App( + DEFAULT_LOG_FILE_PATH, + DEFAULT_DISCORD_WEBHOOK_URL, + hide_npc_kills=False, + ) app.process_lines() else: