#!/usr/bin/python3 # -*- coding: utf-8 -*- from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( QMainWindow, QDialog, QListWidgetItem, QFileDialog, QMessageBox ) from jsonIO import jsonIO from form import Ui_MainWindow from search import Ui_SearchDialog statuses = { "none": "", "planned": "Запланировано", "watching": "Смотрю", "rewatching": "Пересматриваю", "completed": "Просмотрено", "on_hold": "Отложено", "dropped": "Брошено" } class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self, parent=None): QMainWindow.__init__(self, parent, flags=Qt.Window) Ui_MainWindow.__init__(self) self.ui = Ui_MainWindow() self.ui.setupUi(self) # self.file_list = jsonIO.load_json("JDM17_animes.json") # for data in self.file_list: # item = QListWidgetItem(data["target_title_ru"]) # item.setData(1, data["target_id"]) # self.ui.anime_list.addItem(item) self.file_path = "" self.file_list = [] for key, value in statuses.items(): self.ui.status.addItem(value, key) self.ui.anime_list.currentItemChanged.connect(self.show_title_info) self.ui.searchButton.clicked.connect(self.search_titles) self.ui.actionOpenFile.triggered.connect(self.action_open_file) self.ui.actionSaveFile.triggered.connect(self.action_save_file) self.ui.actionCloseFile.triggered.connect(self.action_close_file) self.ui.actionExit.triggered.connect(self.action_close_window) self.ui.actionAddTitle.triggered.connect(self.action_add_title) self.ui.actionRemoveTitle.triggered.connect(self.action_remove_title) def show_question(self, title, text): box = QMessageBox(QMessageBox.Question, title, text, parent=self) box.addButton("Да", QMessageBox.YesRole) # 0 box.addButton("Нет", QMessageBox.NoRole) # 1 return box.exec() == 0 def find_title(self, target_id): for data in self.file_list: if data["target_id"] == target_id: return data return None def check_changes(self, target_id): tbl_to_check = { "score": self.ui.score.value(), "status": self.ui.status.itemData(self.ui.status.currentIndex()), "episodes": self.ui.episodes.value(), "rewatches": self.ui.rewatches.value(), "text": self.ui.note.toPlainText() } title_data = self.find_title(target_id) for key, value in tbl_to_check.items(): if title_data[key] != value: return True return False def save_changes(self, target_id): title_data = self.find_title(target_id) title_data["score"] = self.ui.score.value() status_code = self.ui.status.itemData(self.ui.status.currentIndex()) if status_code == "none": QMessageBox.warning(self, "Предупреждение", "Выбран неверный статус, он не будет сохранен.") else: title_data["status"] = status_code title_data["episodes"] = self.ui.episodes.value() title_data["rewatches"] = self.ui.rewatches.value() title_data["text"] = self.ui.note.toPlainText() def clear_fields(self): self.ui.target_title.clear() self.ui.target_title_ru.clear() self.ui.score.setValue(0) self.ui.status.setCurrentIndex(self.ui.status.findData("none")) self.ui.episodes.setValue(0) self.ui.rewatches.setValue(0) self.ui.note.clear() def refill_anime_list(self): self.ui.anime_list.clear() for data in self.file_list: if data["target_type"] != "Anime": continue if data["text"] is None: data["text"] = "" item = QListWidgetItem() if data["target_title_ru"] != "": item.setText(data["target_title_ru"]) else: item.setText(data["target_title"]) item.setData(1, data["target_id"]) self.ui.anime_list.addItem(item) def check_current_title(self, item, ask_save=True): if item is None: return item_id = item.data(1) if not self.check_changes(item_id): return if (ask_save and self.show_question("Подтверждение", "Сохранить изменения?")) or ask_save == False: self.save_changes(item_id) def show_title_info(self, current, previous): if current is None: return self.check_current_title(previous) self.clear_fields() data = self.find_title(current.data(1)) self.ui.target_title.setText(data["target_title"]) self.ui.target_title_ru.setText(data["target_title_ru"]) self.ui.score.setValue(data["score"]) self.ui.status.setCurrentIndex(self.ui.status.findData(data["status"])) self.ui.episodes.setValue(data["episodes"]) self.ui.rewatches.setValue(data["rewatches"]) self.ui.note.setText(data["text"]) def search_titles(self): if self.file_path == "": QMessageBox.critical(self, "Ошибка", "Сначала откройте список!") return text_to_search = self.ui.searchEdit.text().lower() if len(text_to_search) == 0: self.refill_anime_list() return self.check_current_title(self.ui.anime_list.currentItem()) self.ui.anime_list.clear() for title in self.file_list: if title["target_type"] != "Anime": continue if title["target_title_ru"].lower().find(text_to_search) != -1: item = QListWidgetItem(title["target_title_ru"]) item.setData(1, title["target_id"]) self.ui.anime_list.addItem(item) def action_open_file(self): file_path, file_name = QFileDialog.getOpenFileName(parent=self, caption=self.tr("Выберите ваш файл со списком"), filter=self.tr("*.json")) if file_path == "": return if jsonIO.is_valid_json(file_path): self.file_path = file_path self.file_list = jsonIO.load_json(file_path) self.clear_fields() self.refill_anime_list() def action_save_file(self): if self.file_path == "": QMessageBox.critical(self, "Ошибка", "Сначала откройте список!") return self.check_current_title(self.ui.anime_list.currentItem()) if jsonIO.save_json(self.file_path, self.file_list): QMessageBox.information(self, "Успешно", "Файл успешно сохранен.") else: QMessageBox.critical(self, "Ошибка", "Что-то пошло не так! Попробуйте еще раз.") def action_close_file(self): if self.file_path == "": QMessageBox.critical(self, "Ошибка", "Сначала откройте список!") return if self.show_question("Вопрос", "Вы хотите сохранить файл?"): self.check_current_title(self.ui.anime_list.currentItem(), ask_save=False) self.action_save_file() self.file_path = "" self.file_list = [] self.ui.anime_list.clear() self.clear_fields() def action_close_window(self): if self.show_question("Вопрос", "Вы хотите сохранить файл?"): self.check_current_title(self.ui.anime_list.currentItem(), ask_save=False) self.action_save_file() self.close() def action_add_title(self): search_dialog = SearchDialog(self) search_dialog.exec_() def action_remove_title(self): if self.file_path == "": QMessageBox.critical(self, "Ошибка", "Сначала откройте список!") return selected_item = self.ui.anime_list.currentItem() if selected_item is None: QMessageBox.critical(self, "Ошибка", "Выберите тайтл из списка!") return target_id = selected_item.data(1) title = self.find_title(target_id) if title["target_title_ru"] != "": title_name = title["target_title_ru"] else: title_name = title["target_title"] if self.show_question("Подтверждение", "Вы действительно хотите удалить '{}'?".format(title_name)): self.ui.anime_list.takeItem(self.ui.anime_list.currentRow()) for data in self.file_list: if data["target_id"] == target_id: self.file_list.remove(data) QMessageBox.information(self, "Успешно", "Тайтл '{}' успешно удален из списка!".format(title_name)) def returnNewTitle(self, title_data): # print(title_data) # if self.find_title(title_data["target_id"]): # QMessageBox.critical(self, "Ошибка", "Данный тайтл уже есть в списке!") # return pass header = { "User-Agent": "", "Authorization": "" } from requests import post, get from urllib.parse import urlencode class SearchDialog(QDialog, Ui_SearchDialog): def __init__(self, parent=None): QDialog.__init__(self, parent, flags=Qt.Window) Ui_SearchDialog.__init__(self) self.ui = Ui_SearchDialog() self.ui.setupUi(self) self.parent = parent # import tokens from tokens.json if not jsonIO.is_valid_json("tokens.json"): jsonIO.save_json("tokens.json", { "useragent": "", "client_id": "", "client_secret": "", "authorization_code": "", "access_token": "", "refresh_token": "" }) QMessageBox.critical(self, "Ошибка", "Заполните 'tokens.json' своими данными чтобы поиск работал корректно!") self.close() else: self.tokens = jsonIO.load_json("tokens.json") for key, value in self.tokens.items(): if (key != "access_token" or key != "refresh_token") and value == "": QMessageBox.critical(self, "Ошибка", "Заполните 'tokens.json' своими данными чтобы поиск работал корректно!") self.close() if self.tokens["access_token"] == "": self.get_new_access_token() self.update_headers() self.ui.search.clicked.connect(self.search_titles) def update_headers(self): header["User-Agent"] = self.tokens["useragent"] header["Authorization"] = "Bearer {}".format(self.tokens["access_token"]) def get_new_access_token(self): response = post("https://shikimori.one/oauth/token", headers=header, data={ "grant_type": "authorization_code", "client_id": self.tokens["client_id"], "client_secret": self.tokens["client_secret"], "code": self.tokens["authorization_code"], }) if response.status_code == 200: new_tokens = response.json() self.tokens["access_token"] = new_tokens["access_token"] self.tokens["refresh_token"] = new_tokens["refresh_token"] jsonIO.save_json("tokens.json", self.tokens) self.update_headers() print("got new tokens") def refresh_access_token(self): response = post("https://shikimori.one/oauth/token", headers=header, data={ "grant_type": "refresh_token", "client_id": self.tokens["client_id"], "client_secret": self.tokens["client_secret"], "refresh_token": self.tokens["refresh_token"], }) if response.status_code == 200: new_tokens = response.json() self.tokens["access_token"] = new_tokens["access_token"] self.tokens["refresh_token"] = new_tokens["refresh_token"] jsonIO.save_json("tokens.json", self.tokens) self.update_headers() print("tokens updated", new_tokens) def search_titles(self): title_name = self.ui.to_search.text() if len(title_name) == 0: QMessageBox.critical(self, "Ошибка", "Введите название тайтла.") return response = get("https://shikimori.one/api/animes", headers=header, params={"search": title_name, "limit": 25}) # print(response.json()) if response.status_code == 401: if response.json()["error"] == "invalid_token": self.refresh_access_token() # self.search_titles() return if response.status_code == 200: found_titles = response.json() if len(found_titles) == 0: QMessageBox.information(self, "Информация", "Ничего не найдено. Попробуйте еще раз.") return self.ui.search_list.clear() for data in found_titles: item = QListWidgetItem() if data["russian"] != "": item.setText("{} | {}".format(data["russian"], data["name"])) else: item.setText(data["name"]) item.setData(1, data["id"]) self.ui.search_list.addItem(item)