Files
shikimori_list_viewer/window.py
2024-02-06 08:07:42 +07:00

329 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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)