поправь код он не ждет пока токен будет снова рабочим - через 5 секунд, он сразу начинает запросы слать, когда происходит восстановление пикселей и во время рисования большая часть пикселей просто в пропуск идут и не рисуются и тут уже работает правило не использование токенов , но он не ждет обновления а просто без остановочно пытается взять токен пропуская пиксели и сделай чтобы я во время работы мог добавлять токены. headers не трогай пожайлуйста!! import tkinter as tk
from tkinter import ttk, filedialog, messagebox, simpledialog
import requests
from PIL import Image, ImageTk
import threading
import time
import io
import random

class PixelBattleApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Pixel Battle Manager")

        # Управление токенами
        self.tokens = ["28862a05a3f84141b50828b6dbd78884.0d8b887f5b744531a4d51b9d3ef07f62.m2rl7z0l"]
        self.token_last_used = {}
        self.token_lock = threading.Lock()

        # Масштаб и пикселизация
        self.scale_factor = 1
        self.pixel_size = 1

        # Изображение и позиция для рисования
        self.original_image = None
        self.pixelated_image = None
        self.start_position = (0, 0)
        self.setting_start_position = False

        # Авто-рисование
        self.auto_drawing = False
        self.auto_draw_thread = None

        # Периодическое обновление
        self.update_interval = 10  # секунды
        self.update_thread = None

        # Настройка UI и холста
        self.setup_ui()
        self.setup_canvas()
        self.start_periodic_update()

    def setup_ui(self):
        # Фрейм для управления токенами
        token_frame = ttk.LabelFrame(self.root, text="Управление токенами")
        token_frame.pack(padx=5, pady=5, fill="x")

        ttk.Button(token_frame, text="Добавить токен", command=self.add_token).pack(side="left", padx=5)
        ttk.Button(token_frame, text="Удалить токен", command=self.remove_token).pack(side="left", padx=5)
        self.token_label = ttk.Label(token_frame, text="Всего токенов: 0")
        self.token_label.pack(side="left", padx=10)

        # Фрейм для управления изображением
        image_frame = ttk.LabelFrame(self.root, text="Управление изображением")
        image_frame.pack(padx=5, pady=5, fill="x")

        ttk.Button(image_frame, text="Загрузить изображение", command=self.load_image).pack(side="left", padx=5)
        ttk.Button(image_frame, text="Показать оригинал", command=self.show_original_image).pack(side="left", padx=5)
        ttk.Button(image_frame, text="Начать авто-рисование", command=self.start_auto_draw).pack(side="left", padx=5)
        ttk.Button(image_frame, text="Остановить авто-рисование", command=self.stop_auto_draw).pack(side="left", padx=5)

        # Фрейм для управления масштабом и пикселизацией
        control_frame = ttk.LabelFrame(self.root, text="Настройки")
        control_frame.pack(padx=5, pady=5, fill="x")

        # Масштаб
        ttk.Label(control_frame, text="Масштаб:").pack(side="left", padx=5)
        self.scale_entry = ttk.Entry(control_frame, width=5)
        self.scale_entry.insert(0, "1")
        self.scale_entry.pack(side="left", padx=5)
        ttk.Button(control_frame, text="Применить", command=self.apply_scale).pack(side="left", padx=5)

        # Размер пикселя
        ttk.Label(control_frame, text="Размер пикселя:").pack(side="left", padx=5)
        self.pixel_size_entry = ttk.Entry(control_frame, width=5)
        self.pixel_size_entry.insert(0, "1")
        self.pixel_size_entry.pack(side="left", padx=5)
        ttk.Button(control_frame, text="Применить", command=self.apply_pixel_size).pack(side="left", padx=5)

        # Кнопка установки начальной позиции
        ttk.Button(self.root, text="Установить начальную позицию", command=self.set_start_position).pack(padx=5, pady=5, fill="x")

        # Фрейм для управления цветом
        color_frame = ttk.LabelFrame(self.root, text="Цвет пикселя")
        color_frame.pack(padx=5, pady=5, fill="x")

        ttk.Label(color_frame, text="Цвет:").pack(side="left", padx=5)
        self.color_entry = ttk.Entry(color_frame)
        self.color_entry.insert(0, "#000000")
        self.color_entry.pack(side="left", padx=5)

    def setup_canvas(self):
        self.canvas = tk.Canvas(self.root, width=800, height=600, bg="white")
        self.canvas.pack(padx=5, pady=5)
        self.canvas.bind("<Button-1>", self.canvas_click)

        # Для установки начальной позиции
        self.canvas.bind("<Button-3>", self.remove_start_position)

        # Хранение объектов на холсте
        self.canvas_current_image = None  # Текущее состояние пикселей с сервера
        self.canvas_loaded_image = None  # Загруженное пикселизированное изображение
        self.canvas_start_position_marker = None  # Маркер начальной позиции

    def add_token(self):
        token = simpledialog.askstring("Добавить токен", "Введите Bearer токен:")
        if token:
            self.tokens.append(token)
            self.token_last_used[token] = 0
            self.token_label.config(text=f"Всего токенов: {len(self.tokens)}")

    def remove_token(self):
        if self.tokens:
            removed = self.tokens.pop()
            del self.token_last_used[removed]
            self.token_label.config(text=f"Всего токенов: {len(self.tokens)}")
            messagebox.showinfo("Токен удалён", f"Токен {removed} удалён.")
        else:
            messagebox.showwarning("Предупреждение", "Нет токенов для удаления.")

    def apply_scale(self):
        try:
            scale = float(self.scale_entry.get())
            if scale <= 0:
                raise ValueError
            self.scale_factor = scale
            if self.original_image:
                self.pixelize_image()
                self.update_canvas()
        except ValueError:
            messagebox.showerror("Ошибка", "Неверный коэффициент масштаба.")

    def apply_pixel_size(self):
        try:
            size = int(self.pixel_size_entry.get())
            if size <= 0:
                raise ValueError
            self.pixel_size = size
            if self.original_image:
                self.pixelize_image()
                self.update_canvas()
        except ValueError:
            messagebox.showerror("Ошибка", "Неверный размер пикселя.")

    def set_start_position(self):
        messagebox.showinfo("Установка позиции", "Кликните левой кнопкой мыши на холсте для установки начальной позиции.")
        self.setting_start_position = True

    def remove_start_position(self, event):
        self.start_position = None
        if self.canvas_start_position_marker:
            self.canvas.delete(self.canvas_start_position_marker)
            self.canvas_start_position_marker = None
        messagebox.showinfo("Позиция сброшена", "Начальная позиция сброшена.")

    def pixelize_image(self):
        if self.original_image:
            width, height = self.original_image.size
            px_size = self.pixel_size
            # Пикселизация
            self.pixelated_image = self.original_image.resize(
                (width // px_size, height // px_size),
                Image.NEAREST
            ).resize((width, height), Image.NEAREST)
            # Применение масштаба
            if self.scale_factor != 1:
                new_size = (int(self.pixelated_image.width * self.scale_factor), int(self.pixelated_image.height * self.scale_factor))
                self.pixelated_image = self.pixelated_image.resize(new_size, Image.NEAREST)

    def load_image(self):
        file_path = filedialog.askopenfilename(
            filetypes=[("Файлы изображений", "*.png *.jpg *.jpeg *.bmp *.gif")]
        )
        if file_path:
            try:
                self.original_image = Image.open(file_path).convert("RGB")
                # Проверка размера и автоматическое изменение
                max_size = 40  # Максимальная ширина или высота
                if self.original_image.width > max_size or self.original_image.height > max_size:
                    self.original_image.thumbnail((max_size, max_size), Image.LANCZOS)
                    messagebox.showinfo("Изменение размера", f"Изображение было изменено до {self.original_image.size}")
                self.pixelize_image()
                # Создание изображения для отображения на холсте
                self.canvas_loaded_image = ImageTk.PhotoImage(self.pixelated_image)
                self.update_canvas()
            except Exception as e:
                messagebox.showerror("Ошибка", f"Не удалось загрузить изображение: {e}")

    def show_original_image(self):
        if self.original_image:
            original_window = tk.Toplevel(self.root)
            original_window.title("Оригинальное изображение")
            original_photo = ImageTk.PhotoImage(self.original_image)
            label = tk.Label(original_window, image=original_photo)
            label.image = original_photo  # Сохраняем ссылку
            label.pack()
        else:
            messagebox.showwarning("Предупреждение", "Нет загруженного изображения.")

    def update_canvas(self):
        def task():
            if self.pixelated_image:
                try:
                    self.fetch_current_pixels()
                except Exception as e:
                    print(f"Ошибка обновления холста: {e}")

        threading.Thread(target=task, daemon=True).start()

    def fetch_current_pixels(self):
        url = f"https://3years.aeza.net/api/pixels.png?{random.random()}"
        headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0",
    "Accept": "*/*",
    "Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Referer": "https://3years.aeza.net/",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-origin",
    "Connection": "keep-alive",
    "Cookie": "cf_clearance=8EvuO.fzfN9UMpnQJp8UfGumow3RPIgJ9WtYV8QvtUU-1730228418-1.2.1.1-.KHBbxDuDd82ehZIqZP5E7BSk9JKUccvd54jCJGjXyR9ur7kb4aUrAlXRbw_m0d6KDeMYWpM3FPEMMNdu6Usx3VWSkryZH4nz6ytOfScywsZpiwCSA0sw3XvH2hb6G2SvgoHxnkX9bjFUT6ALpzWeuhCMukgqw.NgAB3_SIl0SUip5xNEm_tDt58krqBngX1yUiSF.EAhBGUn7Ym9i0BuWGrf8OcS3dCpu1jcm4DvxE9ne92vbcqriFLhJVKrIvBW16bd7UrZAqjXajscWwnfUrIow77QnKu6t2E7PnNCUi2cMpYvPvbH6RZHstff5zNjBPnkpZDwVwg23.X3E5uZhu1lPIdkUJhLVyFYtpXiQrjRi8j4_vY_52iQuoJh6Rj4OjmvRwkc83EeGDWNQspNQ",
    "Priority": "u"
        }

        try:
            response = requests.get(url, headers=headers)
            if response.status_code == 200:
                image = Image.open(io.BytesIO(response.content))
                # Применение масштаба
                if self.scale_factor != 1:
                    new_size = (int(image.width * self.scale_factor), int(image.height * self.scale_factor))
                    image = image.resize(new_size, Image.NEAREST)
                photo = ImageTk.PhotoImage(image)
                self.canvas_current_image = photo  # Сохраняем ссылку
                self.canvas.delete("all")  # Очистить холст
                self.canvas.create_image(0, 0, anchor="nw", image=self.canvas_current_image)

                # Отображение пикселизированного изображения, если задана начальная позиция
                if self.start_position and self.pixelated_image:
                    self.canvas_loaded_image = ImageTk.PhotoImage(self.pixelated_image)
                    self.canvas.create_image(self.start_position[0], self.start_position[1], anchor="nw", image=self.canvas_loaded_image)

                    # Отображение маркера начальной позиции
                    if not self.canvas_start_position_marker:
                        x, y = self.start_position
                        self.canvas_start_position_marker = self.canvas.create_rectangle(
                            x,
                            y,
                            x + self.pixelated_image.width,
                            y + self.pixelated_image.height,
                            outline="red",
                            width=2
                        )
                else:
                    # Если позиция не установлена, просто отображаем загруженное изображение на холсте
                    if self.pixelated_image:
                        self.canvas_loaded_image = ImageTk.PhotoImage(self.pixelated_image)
                        self.canvas.create_image(0, 0, anchor="nw", image=self.canvas_loaded_image)

            else:
                print(f"Не удалось получить карту пикселей: статус {response.status_code}")
        except Exception as e:
            print(f"Ошибка при получении карты пикселей: {e}")

    def canvas_click(self, event):
        if self.setting_start_position:
            # Установка начальной позиции
            x = event.x
            y = event.y
            self.start_position = (x, y)
            self.setting_start_position = False
            messagebox.showinfo("Позиция установлена", f"Начальная позиция установлена на ({x}, {y})")
            self.update_canvas()
            return

        if not self.tokens:
            messagebox.showerror("Ошибка", "Нет доступных токенов.")
            return

        # Обработка левого клика для установки пикселя
        x = int(event.x / self.scale_factor)
        y = int(event.y / self.scale_factor)
        color = self.color_entry.get()

        # Запуск сетевого запроса в отдельном потоке
        threading.Thread(target=self.place_pixel, args=(x, y, color), daemon=True).start()

    def place_pixel(self, x, y, color):
        token = self.get_available_token()
        if not token:
            print("Нет доступных токенов для использования.")
            return

        headers = {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0",
    "Accept": "*/*",
    "Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Referer": "https://3years.aeza.net/",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-origin",
    "Connection": "keep-alive",
    "Cookie": "cf_clearance=8EvuO.fzfN9UMpnQJp8UfGumow3RPIgJ9WtYV8QvtUU-1730228418-1.2.1.1-.KHBbxDuDd82ehZIqZP5E7BSk9JKUccvd54jCJGjXyR9ur7kb4aUrAlXRbw_m0d6KDeMYWpM3FPEMMNdu6Usx3VWSkryZH4nz6ytOfScywsZpiwCSA0sw3XvH2hb6G2SvgoHxnkX9bjFUT6ALpzWeuhCMukgqw.NgAB3_SIl0SUip5xNEm_tDt58krqBngX1yUiSF.EAhBGUn7Ym9i0BuWGrf8OcS3dCpu1jcm4DvxE9ne92vbcqriFLhJVKrIvBW16bd7UrZAqjXajscWwnfUrIow77QnKu6t2E7PnNCUi2cMpYvPvbH6RZHstff5zNjBPnkpZDwVwg23.X3E5uZhu1lPIdkUJhLVyFYtpXiQrjRi8j4_vY_52iQuoJh6Rj4OjmvRwkc83EeGDWNQspNQ",
    "Priority": "u"
        }

        try:
            # Получение текущего цвета пикселя
            get_response = requests.get(f'https://3years.aeza.net/api/pixels?x={x}&y={y}', headers=headers)
            if get_response.status_code != 200:
                print(f"Не удалось получить пиксель ({x},{y}): статус {get_response.status_code}")
                return
            current_pixel = get_response.json()
            if current_pixel.get("color").lower() == color.lower():
                print(f"Пиксель ({x},{y}) уже нужного цвета.")
                return

            # Установка нового цвета пикселя
            data = {"color": color, "x": x, "y": y}
            put_response = requests.put('https://3years.aeza.net/api/pixels', headers=headers, json=data)
            if put_response.status_code == 200:
                print(f"Пиксель ({x},{y}) установлен на {color}.")
                # Обновление локального изображения
                if self.pixelated_image:
                    self.pixelated_image.putpixel((x, y), self.hex_to_rgb(color))
                    self.update_canvas()
            else:
                print(f"Не удалось установить пиксель ({x},{y}): статус {put_response.status_code}")
        except Exception as e:
            print(f"Ошибка при установке пикселя ({x},{y}): {e}")
        finally:
            self.release_token(token)

    def get_available_token(self):
        with self.token_lock:
            current_time = time.time()
            for token in self.tokens:
                last_used = self.token_last_used.get(token, 0)
                if current_time - last_used >= 6:  # Задержка 5 секунд
                    self.token_last_used[token] = current_time
                    return token
        return None

    def release_token(self, token):
        with self.token_lock:
            self.token_last_used[token] = 0  # Сброс времени использования

    def hex_to_rgb(self, hex_color):
        hex_color = hex_color.lstrip('#')
        if len(hex_color) != 6:
            raise ValueError("Неверный формат цвета.")
        r, g, b = tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
        return (r, g, b)

    def start_auto_draw(self):
        if not self.pixelated_image:
            messagebox.showerror("Ошибка", "Нет загруженного изображения для рисования.")
            return
        if self.auto_drawing:
            messagebox.showinfo("Информация", "Авто-рисование уже запущено.")
            return
        self.auto_drawing = True
        self.auto_draw_thread = threading.Thread(target=self.auto_draw, daemon=True)
        self.auto_draw_thread.start()
        messagebox.showinfo("Информация", "Авто-рисование запущено.")

    def stop_auto_draw(self):
        if self.auto_drawing:
            self.auto_drawing = False
            messagebox.showinfo("Информация", "Авто-рисование остановлено.")
        else:
            messagebox.showinfo("Информация", "Авто-рисование не запущено.")

    def auto_draw(self):
        px_size = self.pixel_size
        width, height = self.pixelated_image.size

        # Если начальная позиция не установлена, не продолжаем
        if not self.start_position:
            print("Начальная позиция не установлена.")
            self.auto_drawing = False
            return

        # Определяем область для рисования
        start_x, start_y = self.start_position
        end_x = min(start_x + width, 255)  # Предполагаемая ширина холста
        end_y = min(start_y + height, 255)  # Предполагаемая высота холста

        for y in range(height):
            for x in range(width):
                if not self.auto_drawing:
                    print("Авто-рисование остановлено пользователем.")
                    return

                color = self.pixelated_image.getpixel((x, y))
                desired_hex = "#%02x%02x%02x" % color

                canvas_x = start_x + x
                canvas_y = start_y + y

                if canvas_x < 0 or canvas_x >= 255 or canvas_y < 0 or canvas_y >= 255:
                    continue  # Пропускаем пиксели вне границ холста

                threading.Thread(target=self.place_pixel, args=(canvas_x, canvas_y, desired_hex), daemon=True).start()

                # Регулируем скорость: каждые 10 пикселей делаем паузу
                if (x + y * width) % 10 == 0:
                    time.sleep(0.1)

        print("Авто-рисование завершено.")
        self.auto_drawing = False

    def start_periodic_update(self):
        self.update_thread = threading.Thread(target=self.periodic_update, daemon=True)
        self.update_thread.start()

    def periodic_update(self):
        while True:
            if self.pixelated_image and self.start_position:
                self.check_and_update_pixels()
            time.sleep(self.update_interval)

    def check_and_update_pixels(self):
        px_size = self.pixel_size
        width, height = self.pixelated_image.size

        start_x, start_y = self.start_position
        end_x = min(start_x + width, 255)
        end_y = min(start_y + height, 255)

        for y in range(height):
            for x in range(width):
                try:
                    desired_color = self.pixelated_image.getpixel((x, y))
                    desired_hex = "#%02x%02x%02x" % desired_color

                    canvas_x = start_x + x
                    canvas_y = start_y + y

                    if canvas_x < 0 or canvas_x >= 255 or canvas_y < 0 or canvas_y >= 255:
                        continue  # Пропускаем пиксели вне границ холста

                    token = self.get_available_token()
                    if not token:
                        continue  # Ждём доступности токенов

                    headers = {
                        "Authorization": f"Bearer {token}",
                        "Content-Type": "application/json",
                            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:131.0) Gecko/20100101 Firefox/131.0",
    "Accept": "*/*",
    "Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Referer": "https://3years.aeza.net/",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-origin",
    "Connection": "keep-alive",
    "Cookie": "cf_clearance=8EvuO.fzfN9UMpnQJp8UfGumow3RPIgJ9WtYV8QvtUU-1730228418-1.2.1.1-.KHBbxDuDd82ehZIqZP5E7BSk9JKUccvd54jCJGjXyR9ur7kb4aUrAlXRbw_m0d6KDeMYWpM3FPEMMNdu6Usx3VWSkryZH4nz6ytOfScywsZpiwCSA0sw3XvH2hb6G2SvgoHxnkX9bjFUT6ALpzWeuhCMukgqw.NgAB3_SIl0SUip5xNEm_tDt58krqBngX1yUiSF.EAhBGUn7Ym9i0BuWGrf8OcS3dCpu1jcm4DvxE9ne92vbcqriFLhJVKrIvBW16bd7UrZAqjXajscWwnfUrIow77QnKu6t2E7PnNCUi2cMpYvPvbH6RZHstff5zNjBPnkpZDwVwg23.X3E5uZhu1lPIdkUJhLVyFYtpXiQrjRi8j4_vY_52iQuoJh6Rj4OjmvRwkc83EeGDWNQspNQ",
    "Priority": "u"
                    }

                    # Получение текущего цвета пикселя
                    get_response = requests.get(f'https://3years.aeza.net/api/pixels?x={canvas_x}&y={canvas_y}', headers=headers)
                    if get_response.status_code != 200:
                        print(f"Не удалось получить пиксель ({canvas_x},{canvas_y}): статус {get_response.status_code}")
                        continue
                    current_pixel = get_response.json()
                    if current_pixel.get("color").lower() != desired_hex.lower():
                        # Пиксель был изменён, восстанавливаем
                        data = {"color": desired_hex, "x": canvas_x, "y": canvas_y}
                        put_response = requests.put('https://3years.aeza.net/api/pixels', headers=headers, json=data)
                        if put_response.status_code == 200:
                            print(f"Пиксель ({canvas_x},{canvas_y}) восстановлен на {desired_hex}.")
                            # Обновление локального изображения
                            self.pixelated_image.putpixel((x, y), self.hex_to_rgb(desired_hex))
                            self.update_canvas()
                        else:
                            print(f"Не удалось восстановить пиксель ({canvas_x},{canvas_y}): статус {put_response.status_code}")
                except Exception as e:
                    print(f"Ошибка при проверке пикселя ({x},{y}): {e}")
                finally:
                    if 'token' in locals():
                        self.release_token(token)

    def run(self):
        self.root.mainloop()

def main():
    root = tk.Tk()
    app = PixelBattleApp(root)
    app.run()

if __name__ == "__main__":
    main()