import tkinter as tk from tkinter import messagebox from api import get_repo_data, get_commits, get_code_lines from parser import parse_repo_info, parse_authors from storage import ( register_user, check_user, get_repositories, add_repository, delete_repository, ) class GiteaAnalyzerApp: def __init__(self): self.root = tk.Tk() self.root.title("Gitea Analyzer") self.root.geometry("1200x750") self.root.minsize(1000, 650) self.root.resizable(True, True) self.current_user = None self.bg = "#eef4ff" self.panel = "#ffffff" self.button = "#6aa6ff" self.root.configure(bg=self.bg) self.show_splash() self.root.mainloop() def clear(self): for widget in self.root.winfo_children(): widget.destroy() def make_button(self, parent, text, command, width=24): return tk.Button( parent, text=text, command=command, width=width, bg=self.button, fg="white", activebackground="#4d8ee8", activeforeground="white", font=("Arial", 11, "bold"), relief="flat", cursor="hand2", pady=6, ) def show_splash(self): self.clear() frame = tk.Frame(self.root, bg=self.bg) frame.pack(expand=True) tk.Label( frame, text="Gitea Repository Analyzer", font=("Arial", 28, "bold"), bg=self.bg, fg="#1d3557", ).pack(pady=20) tk.Label( frame, text="Анализ репозиториев: автор, соавторы, даты и строки Python-кода", font=("Arial", 14), bg=self.bg, fg="#333333", ).pack(pady=10) tk.Label( frame, text="Загрузка...", font=("Arial", 12), bg=self.bg, fg="#555555", ).pack(pady=30) self.root.after(1200, self.show_login) def show_login(self): self.clear() frame = tk.Frame(self.root, bg=self.panel, padx=35, pady=35) frame.place(relx=0.5, rely=0.5, anchor="center") tk.Label(frame, text="Вход в аккаунт", font=("Arial", 22, "bold"), bg=self.panel).pack(pady=10) tk.Label(frame, text="Логин", bg=self.panel, font=("Arial", 11)).pack(anchor="w") login_entry = tk.Entry(frame, width=35, font=("Arial", 12)) login_entry.pack(pady=5) tk.Label(frame, text="Пароль", bg=self.panel, font=("Arial", 11)).pack(anchor="w") password_entry = tk.Entry(frame, width=35, font=("Arial", 12), show="*") password_entry.pack(pady=5) def login(): login_value = login_entry.get().strip() password_value = password_entry.get().strip() if not login_value or not password_value: messagebox.showerror("Ошибка", "Введите логин и пароль") return if check_user(login_value, password_value): self.current_user = login_value self.show_main_screen() else: messagebox.showerror("Ошибка", "Неверный логин или пароль") self.make_button(frame, "Войти", login).pack(pady=12) self.make_button(frame, "Создать профиль", self.show_register).pack(pady=5) def show_register(self): self.clear() frame = tk.Frame(self.root, bg=self.panel, padx=35, pady=35) frame.place(relx=0.5, rely=0.5, anchor="center") tk.Label(frame, text="Создание профиля", font=("Arial", 22, "bold"), bg=self.panel).pack(pady=10) tk.Label(frame, text="Логин", bg=self.panel, font=("Arial", 11)).pack(anchor="w") login_entry = tk.Entry(frame, width=35, font=("Arial", 12)) login_entry.pack(pady=5) tk.Label(frame, text="Пароль", bg=self.panel, font=("Arial", 11)).pack(anchor="w") password_entry = tk.Entry(frame, width=35, font=("Arial", 12), show="*") password_entry.pack(pady=5) def register(): login_value = login_entry.get().strip() password_value = password_entry.get().strip() if not login_value or not password_value: messagebox.showerror("Ошибка", "Введите логин и пароль") return if len(password_value) < 4: messagebox.showerror("Ошибка", "Пароль должен быть минимум 4 символа") return ok, text = register_user(login_value, password_value) if ok: messagebox.showinfo("Готово", text) self.show_login() else: messagebox.showerror("Ошибка", text) self.make_button(frame, "Зарегистрироваться", register).pack(pady=12) self.make_button(frame, "Назад", self.show_login).pack(pady=5) def show_main_screen(self): self.clear() top = tk.Frame(self.root, bg="#1d3557", height=60) top.pack(fill="x") tk.Label( top, text=f"Gitea Analyzer | Пользователь: {self.current_user}", bg="#1d3557", fg="white", font=("Arial", 18, "bold"), ).pack(side="left", padx=20, pady=15) tk.Button( top, text="Выйти", command=self.show_login, bg="#e63946", fg="white", activebackground="#c1121f", activeforeground="white", relief="flat", font=("Arial", 12), cursor="hand2", ).pack(side="right", padx=20, pady=12) content = tk.Frame(self.root, bg=self.bg) content.pack(fill="both", expand=True, padx=15, pady=15) left = tk.Frame(content, bg=self.panel, padx=15, pady=15) left.pack(side="left", fill="y") right = tk.Frame(content, bg=self.panel, padx=15, pady=15) right.pack(side="right", fill="both", expand=True, padx=(15, 0)) tk.Label(left, text="Мои репозитории", bg=self.panel, font=("Arial", 18, "bold")).pack(anchor="w") repo_listbox = tk.Listbox(left, width=44, height=18, font=("Arial", 11)) repo_listbox.pack(pady=10, fill="y") tk.Label(left, text="Новая ссылка", bg=self.panel, font=("Arial", 12)).pack(anchor="w") repo_entry = tk.Entry(left, width=44, font=("Arial", 11)) repo_entry.pack(pady=5, fill="x") result_text = tk.Text(right, width=70, height=28, font=("Consolas", 12), wrap="word") result_text.pack(fill="both", expand=True) def refresh_list(): repo_listbox.delete(0, tk.END) for repo in get_repositories(self.current_user): repo_listbox.insert(tk.END, repo) def get_selected_repo(): selection = repo_listbox.curselection() if not selection: return None return repo_listbox.get(selection[0]) def save_repo(): link = repo_entry.get().strip() if not link: messagebox.showerror("Ошибка", "Введите ссылку") return added = add_repository(self.current_user, link) if added: repo_entry.delete(0, tk.END) refresh_list() messagebox.showinfo("Готово", "Ссылка сохранена") else: messagebox.showinfo("Информация", "Эта ссылка уже сохранена") def remove_repo(): link = get_selected_repo() if not link: messagebox.showerror("Ошибка", "Выберите репозиторий") return delete_repository(self.current_user, link) refresh_list() result_text.delete("1.0", tk.END) def analyze_repo(repo_link=None): link = repo_link or get_selected_repo() if not link: messagebox.showerror("Ошибка", "Выберите репозиторий") return try: result_text.delete("1.0", tk.END) result_text.insert(tk.END, "Загрузка данных...\n") self.root.update() repo_data = get_repo_data(link) commits = get_commits(link) lines = get_code_lines(link) info = parse_repo_info(repo_data) authors = parse_authors(commits) owner = repo_data.get("owner", {}).get("login", "—") coauthors = [] for author in authors: if author != owner: coauthors.append(author) result_text.delete("1.0", tk.END) result_text.insert(tk.END, f"Ссылка:\n{link}\n\n") result_text.insert(tk.END, info) result_text.insert(tk.END, "\nАвтор репозитория:\n") result_text.insert(tk.END, f"- {owner}\n") result_text.insert(tk.END, "\nСоавторы по коммитам:\n") if coauthors: for author in coauthors: result_text.insert(tk.END, f"- {author}\n") else: result_text.insert(tk.END, "- нет соавторов\n") result_text.insert(tk.END, f"\nСтрок Python-кода: {lines}\n") except Exception as e: messagebox.showerror("Ошибка", str(e)) result_text.delete("1.0", tk.END) self.make_button(left, "Сохранить ссылку", save_repo).pack(pady=5) self.make_button(left, "Обновить информацию", analyze_repo).pack(pady=5) self.make_button(left, "Удалить ссылку", remove_repo).pack(pady=5) refresh_list() if __name__ == "__main__": GiteaAnalyzerApp()