import os import random from tkinter import * from tkinter.messagebox import * from PIL import Image, ImageTk from db import Database database = Database() class PuzzleCaptcha: def __init__(self, parent, user_data, on_success): self.top = Toplevel(parent) self.top.title("Каптча") self.top.geometry("350x450") self.top.grab_set() self.top.resizable(False, False) self.user_data = user_data self.on_success = on_success self.correct_order = [1, 2, 3, 4] self.current_order = [1, 2, 3, 4] random.shuffle(self.current_order) self.images = {} self.selected_index = None Label(self.top, text="Соберите пазл").pack(pady=5) Label(self.top, text="Кликните на две картинки,\nчтобы поменять их местами.").pack(pady=5) self.frame_grid = Frame(self.top) self.frame_grid.pack(pady=5) if self.load_images(): self.draw_grid() Button(self.top, text="Подтвердить", width=20, command=self.check_result).pack(pady=15) def load_images(self): try: for i in range(1, 5): path = os.path.join("img", f"{i}.png") img = Image.open(path).resize((120, 120)) self.images[i] = ImageTk.PhotoImage(img) return True except Exception as e: showerror("Ошибка", f"Не найдены картинки в папке img!\n{e}") self.top.destroy() return False def draw_grid(self): for widget in self.frame_grid.winfo_children(): widget.destroy() for index, img_id in enumerate(self.current_order): color = "gray" if index == self.selected_index else "white" relief = "sunken" if index == self.selected_index else "raised" btn = Button(self.frame_grid, image=self.images[img_id], bg=color, relief=relief, bd=3, command=lambda idx=index: self.on_click(idx)) btn.grid(row=index // 2, column=index % 2, padx=2, pady=2) def on_click(self, index): if self.selected_index is None: self.selected_index = index else: if self.selected_index == index: self.selected_index = None else: i1, i2 = self.selected_index, index self.current_order[i1], self.current_order[i2] = self.current_order[i2], self.current_order[i1] self.selected_index = None self.draw_grid() def check_result(self): if self.current_order == self.correct_order: self.top.destroy() self.on_success() else: showerror("Ошибка", "Картинка собрана неверно.") def open_admin_panel(): adm = Toplevel(root) adm.title("Админ-панель") adm.geometry("500x450") Label(adm, text="Пользователи:").pack() text_area = Text(adm, height=12, width=60) text_area.pack(pady=5) def refresh(): text_area.delete(1.0, END) for u in database.get_all_users(): text_area.insert(END, f"ID:{u[0]} | Log:{u[1]} | Role:{u[2]} | Ban:{u[3]} | Tries:{u[4]}\n") refresh() f = Frame(adm) f.pack(pady=10) Label(f, text="ID:").grid(row=0, column=0) e_id = Entry(f, width=5); e_id.grid(row=0, column=1) Label(f, text="Роль:").grid(row=0, column=2) e_role = Entry(f, width=8); e_role.grid(row=0, column=3) Label(f, text="Забанен(0/1):").grid(row=0, column=4) e_ban = Entry(f, width=5); e_ban.grid(row=0, column=5) def save(): try: uid, urole, uban = e_id.get(), e_role.get(), e_ban.get() if uban is None: uban = 0 if uid: database.update_user_admin(uid, urole, uban) if uban == '0': database.set_tries(uid, 0) showinfo("OK", "Обновлено") refresh() except: showerror("Err", "Ошибка ввода") Button(adm, text="Сохранить", command=save).pack() def finalize_login(user, pwd_input): uid, ulogin, urole, uban, upass = user[0], user[1], user[2], user[3], user[4] utries = user[5] if len(user) > 5 else 0 if pwd_input == upass: database.set_tries(uid, 0) if urole == "admin": open_admin_panel() else: showinfo("Успех", f"Добро пожаловать, {ulogin}!") else: new_tries = utries + 1 database.set_tries(uid, new_tries) if new_tries >= 3: database.set_banned(uid, 1) showerror("Блок", "3 ошибки. Аккаунт заблокирован.") else: showerror("Ошибка", f"Неверный пароль ({new_tries}/3)") def try_login(): login = e_login.get().strip() password = e_pass.get().strip() if not login or not password: return showwarning("!", "Заполните поля") user = database.get_user_by_login(login) if not user: return showerror("!", "Пользователь не найден") if user[3] == 1: return showerror("!", "Вы забанены") PuzzleCaptcha(root, user, lambda: finalize_login(user, password)) root = Tk() root.title("Вход") root.geometry("300x200") Label(root, text="Логин:").pack(pady=(20, 0)) e_login = Entry(root); e_login.pack() Label(root, text="Пароль:").pack() e_pass = Entry(root, show="*"); e_pass.pack() Button(root, text="Войти", command=try_login, width=10).pack(pady=20) root.mainloop()