Начинает работу без команды. когда загружаешь фото, запрос на получение пикселей fetch_current_pixels должен отправлять на сервер не более чем один раз в 10 секунд, кешируй в общем. Установить позицию где будет происходить рисование не получается и сделай флаг который позволит игнорировать рисование черного цвета. Кроме того вместо # Получение текущего цвета пикселя отправки запроса сделай чтобы цвета брал из fetch_current_pixels. не сокращай мои 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
import queue

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


    # Управление токенами с использованием очереди
    self.tokens = ["28862a05a3f84141b50828b6dbd78884.0d8b887f5b744531a4d51b9d3ef07f62.m2rl7z0l","c2b44bf252b4459ea753dbff0dca94a6.9e374c5481af4395b6c95dbced6b979b.m2utx942","0bdc81e3e4c7496da4f0ebf25e0dcdc6.b91387eb9246476f972a8e75fee4d3ab.m2rkw5so","15f33cad6f824c7ca8437ab42c2fb6b0.0a9428d4a2a94afca7ae2b401d1eb79a.m2uuxcz0","b3c635a83a2145c6b298e626e5f1768a.0fc91a85fcb84ef3987aaa1f20da8e34.m2uv21iv","13ef609edbe3404fb113c835e7282ec8.75bdb429646848a4b6feacd703962fda.m2uv2z2a","364a2bfea0584a81828104727ada7fd6.01a948b01c4c475d8fbce8656750bc8b.m2uv3tw3","9f08fd41a7ef48f2b06e11c40ac0ea20.0395268728804e8e81d3939c52597a9c.m2uv4t8q"]
    self.token_lock = threading.Lock()
    self.token_queue = queue.Queue()
    for token in self.tokens:
        self.token_queue.put(token)

    # Масштаб и пикселизация
    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=f"Всего токенов: {len(self.tokens)}")
    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:
        with self.token_lock:
            self.tokens.append(token)
            self.token_queue.put(token)
            self.token_label.config(text=f"Всего токенов: {len(self.tokens)}")

def remove_token(self):
    with self.token_lock:
        if self.tokens:
            removed = self.tokens.pop()
            # Перестраиваем очередь без удаленного токена
            # Примечание: очередь Queue не поддерживает удаление элементов,
            # поэтому мы создаем новую очередь и повторно добавляем все остальные токены
            remaining_tokens = list(self.token_queue.queue)
            remaining_tokens = [t for t in remaining_tokens if t != removed]
            self.token_queue = queue.Queue()
            for token in remaining_tokens:
                self.token_queue.put(token)
            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) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36",
        "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": "carrotquest_device_guid=28884379-c402-4760-b2bd-237448f93638; _ym_uid=1699882530587841879; _ym_d=1699882530; cf_clearance=iociDUITz1GvVdkgPr.PJ7mbkxhbdTPGmVJwe_A.vC0-1730230345-1.2.1.1-h.klFKOnF9LAfzKjogGrQcPq8YJHKpA6zJ2hMBIhzxtYxq3T4QXExqN3I3DIslc4iOcWEMaigi3L05CJLkBK_gq2Qz9Xa4KP5ciExfexTnNkEm18KQO3_eSlrQ4HYIZfcrpj0i9XlqKU5HzpBItqZvM0DkiEXzo._EAJ_iMog3SH_mq_6qPzMpmLtzjgeBVB7K6TUA9Zu.vOBrtJjzIHPkCP7s1GhquO7cLG.Ts2uigIy5Tj2Hhpw828PZ_HzVQa7REvlwtnZZYLWjkzOgOZYBUtVI97sfC2Kf8.bVY5D5Hfoao_H38bkBBsIsmRiliYvFQ0jaZZrENMKIdKD.EvhGggUB6ZX4yA.AuBcbB.hrhu46gmcYQZcJxzjOQuo8saFWWQR5YbAzLzz08kwGB6XBjFpLit61kFnqdWo_Tcmq01IiHYtQRRu8.oV0ZjE6FH",
        "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 self.token_queue.empty():
        messagebox.showerror("Ошибка", "Нет доступных токенов.")
        return

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

    # Запуск сетевого запроса в отдельном потоке
    self.place_pixel(x, y, color)

def place_pixel(self, x, y, color):
    threading.Thread(target=self.use_token_and_place_pixel, args=(x, y, color), daemon=True).start()

def use_token_and_place_pixel(self, x, y, color):
    try:
        # Получение токена из очереди (ожидание, если очередь пуста)
        token = self.token_queue.get(block=True)

        headers = {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
            "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",
            "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": "carrotquest_device_guid=28884379-c402-4760-b2bd-237448f93638; _ym_uid=1699882530587841879; _ym_d=1699882530; cf_clearance=iociDUITz1GvVdkgPr.PJ7mbkxhbdTPGmVJwe_A.vC0-1730230345-1.2.1.1-h.klFKOnF9LAfzKjogGrQcPq8YJHKpA6zJ2hMBIhzxtYxq3T4QXExqN3I3DIslc4iOcWEMaigi3L05CJLkBK_gq2Qz9Xa4KP5ciExfexTnNkEm18KQO3_eSlrQ4HYIZfcrpj0i9XlqKU5HzpBItqZvM0DkiEXzo._EAJ_iMog3SH_mq_6qPzMpmLtzjgeBVB7K6TUA9Zu.vOBrtJjzIHPkCP7s1GhquO7cLG.Ts2uigIy5Tj2Hhpw828PZ_HzVQa7REvlwtnZZYLWjkzOgOZYBUtVI97sfC2Kf8.bVY5D5Hfoao_H38bkBBsIsmRiliYvFQ0jaZZrENMKIdKD.EvhGggUB6ZX4yA.AuBcbB.hrhu46gmcYQZcJxzjOQuo8saFWWQR5YbAzLzz08kwGB6XBjFpLit61kFnqdWo_Tcmq01IiHYtQRRu8.oV0ZjE6FH",
            "Priority": "u"
        }

        # Получение текущего цвета пикселя
        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:
                try:
                    self.pixelated_image.putpixel((x, y), self.hex_to_rgb(color))
                    self.update_canvas()
                except Exception as e:
                    print(f"Ошибка при обновлении локального изображения: {e}")
        else:
            print(f"Не удалось установить пиксель ({x},{y}): статус {put_response.status_code}")
    except Exception as e:
        print(f"Ошибка при установке пикселя ({x},{y}): {e}")
    finally:
        # Возврат токена в очередь через 5 секунд
        threading.Timer(5, self.token_queue.put, args=(token,)).start()

def get_available_token(self):
    # Этот метод теперь не нужен, так как мы используем очередь
    pass

# Удаляем метод release_token, так как управление токенами осуществляется через очередь
# 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  # Пропускаем пиксели вне границ холста

            # Запуск сетевого запроса в отдельном потоке
            self.place_pixel(canvas_x, canvas_y, desired_hex)

            # Регулируем скорость: каждые 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  # Пропускаем пиксели вне границ холста

                # Запуск сетевого запроса в отдельном потоке
                self.place_pixel(canvas_x, canvas_y, desired_hex)

            except Exception as e:
                print(f"Ошибка при проверке пикселя ({x},{y}): {e}")

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

if name == "main":
main()