clean up talker
This commit is contained in:
parent
4a5d02119e
commit
e5b15abf91
@ -165,7 +165,7 @@ def sanitize_title(text: str, basic: bool = False) -> str:
|
||||
def titles_match(search_title: str, record_title: str, threshold: int = 90) -> bool:
|
||||
sanitized_search = sanitize_title(search_title)
|
||||
sanitized_record = sanitize_title(record_title)
|
||||
ratio: int = rapidfuzz.fuzz.ratio(sanitized_search, sanitized_record)
|
||||
ratio = int(rapidfuzz.fuzz.ratio(sanitized_search, sanitized_record))
|
||||
logger.debug(
|
||||
"search title: %s ; record title: %s ; ratio: %d ; match threshold: %d",
|
||||
search_title,
|
||||
|
@ -23,7 +23,7 @@ class QTextEditLogger(QtCore.QObject, logging.Handler):
|
||||
|
||||
|
||||
class ApplicationLogWindow(QtWidgets.QDialog):
|
||||
def __init__(self, log_handler: QTextEditLogger, parent: QtCore.QObject = None) -> None:
|
||||
def __init__(self, log_handler: QTextEditLogger, parent: QtCore.QObject | None = None) -> None:
|
||||
super().__init__(parent)
|
||||
uic.loadUi(ui_path / "logwindow.ui", self)
|
||||
|
||||
|
@ -28,7 +28,7 @@ from comictaggerlib.coverimagewidget import CoverImageWidget
|
||||
from comictaggerlib.resulttypes import IssueResult, MultipleMatch
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictaggerlib.ui.qtutils import reduce_widget_font_size
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
from comictalker.comictalker import ComicTalker
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -41,7 +41,7 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
|
||||
style: int,
|
||||
fetch_func: Callable[[IssueResult], GenericMetadata],
|
||||
config: settngs.Namespace,
|
||||
talker_api: ComicTalker,
|
||||
talker: ComicTalker,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
@ -52,7 +52,7 @@ class AutoTagMatchWindow(QtWidgets.QDialog):
|
||||
self.current_match_set: MultipleMatch = match_set_list[0]
|
||||
|
||||
self.altCoverWidget = CoverImageWidget(
|
||||
self.altCoverContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker_api
|
||||
self.altCoverContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.altCoverContainer)
|
||||
gridlayout.addWidget(self.altCoverWidget)
|
||||
|
@ -22,13 +22,13 @@ from PyQt5 import QtCore, QtWidgets, uic
|
||||
from comictaggerlib.coverimagewidget import CoverImageWidget
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictaggerlib.ui.qtutils import reduce_widget_font_size
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
from comictalker.comictalker import ComicTalker
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AutoTagProgressWindow(QtWidgets.QDialog):
|
||||
def __init__(self, parent: QtWidgets.QWidget, talker_api: ComicTalker) -> None:
|
||||
def __init__(self, parent: QtWidgets.QWidget, talker: ComicTalker) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "autotagprogresswindow.ui", self)
|
||||
|
@ -49,7 +49,7 @@ class AutoTagStartWindow(QtWidgets.QDialog):
|
||||
self.cbxIgnoreLeadingDigitsInFilename.setChecked(self.config.autotag_ignore_leading_numbers_in_filename)
|
||||
self.cbxRemoveAfterSuccess.setChecked(self.config.autotag_remove_archive_after_successful_match)
|
||||
self.cbxWaitForRateLimit.setChecked(self.config.autotag_wait_and_retry_on_rate_limit)
|
||||
self.cbxAutoImprint.setChecked(self.config.talkers_auto_imprint)
|
||||
self.cbxAutoImprint.setChecked(self.config.talker_auto_imprint)
|
||||
|
||||
nlmt_tip = """<html>The <b>Name Match Ratio Threshold: Auto-Identify</b> is for eliminating automatic
|
||||
search matches that are too long compared to your series name search. The lower
|
||||
@ -75,7 +75,7 @@ class AutoTagStartWindow(QtWidgets.QDialog):
|
||||
self.remove_after_success = False
|
||||
self.wait_and_retry_on_rate_limit = False
|
||||
self.search_string = ""
|
||||
self.name_length_match_tolerance = self.config.talkers_series_match_search_thresh
|
||||
self.name_length_match_tolerance = self.config.talker_series_match_search_thresh
|
||||
self.split_words = self.cbxSplitWords.isChecked()
|
||||
|
||||
def search_string_toggle(self) -> None:
|
||||
|
@ -34,21 +34,27 @@ from comictaggerlib.filerenamer import FileRenamer, get_rename_dir
|
||||
from comictaggerlib.graphics import graphics_path
|
||||
from comictaggerlib.issueidentifier import IssueIdentifier
|
||||
from comictaggerlib.resulttypes import MultipleMatch, OnlineMatchResults
|
||||
from comictalker.talkerbase import ComicTalker, TalkerError
|
||||
from comictalker.comictalker import ComicTalker, TalkerError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CLI:
|
||||
def __init__(self, config: settngs.Values, talker_api: ComicTalker):
|
||||
def __init__(self, config: settngs.Namespace, talkers: dict[str, ComicTalker]):
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.talkers = talkers
|
||||
self.batch_mode = False
|
||||
|
||||
def current_talker(self) -> ComicTalker:
|
||||
if self.config[0].talker_source in self.talkers:
|
||||
return self.talkers[self.config[0].talker_source]
|
||||
logger.error("Could not find the '%s' talker", self.config[0].talker_source)
|
||||
raise SystemExit(2)
|
||||
|
||||
def actual_issue_data_fetch(self, issue_id: str) -> GenericMetadata:
|
||||
# now get the particular issue data
|
||||
try:
|
||||
ct_md = self.talker_api.fetch_comic_data(issue_id)
|
||||
ct_md = self.current_talker().fetch_comic_data(issue_id)
|
||||
except TalkerError as e:
|
||||
logger.exception(f"Error retrieving issue details. Save aborted.\n{e}")
|
||||
return GenericMetadata()
|
||||
@ -108,7 +114,7 @@ class CLI:
|
||||
ca = match_set.ca
|
||||
md = self.create_local_metadata(ca)
|
||||
ct_md = self.actual_issue_data_fetch(match_set.matches[int(i) - 1]["issue_id"])
|
||||
if self.config.talkers_clear_metadata_on_import:
|
||||
if self.config.talker_clear_metadata_on_import:
|
||||
md = ct_md
|
||||
else:
|
||||
notes = (
|
||||
@ -117,7 +123,7 @@ class CLI:
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.config.talkers_auto_imprint:
|
||||
if self.config.talker_auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
self.actual_metadata_save(ca, md)
|
||||
@ -342,7 +348,7 @@ class CLI:
|
||||
if self.config.runtime_issue_id is not None:
|
||||
# we were given the actual issue ID to search with
|
||||
try:
|
||||
ct_md = self.talker_api.fetch_comic_data(self.config.runtime_issue_id)
|
||||
ct_md = self.current_talker().fetch_comic_data(self.config.runtime_issue_id)
|
||||
except TalkerError as e:
|
||||
logger.exception(f"Error retrieving issue details. Save aborted.\n{e}")
|
||||
match_results.fetch_data_failures.append(str(ca.path.absolute()))
|
||||
@ -361,7 +367,7 @@ class CLI:
|
||||
match_results.no_matches.append(str(ca.path.absolute()))
|
||||
return
|
||||
|
||||
ii = IssueIdentifier(ca, self.config, self.talker_api)
|
||||
ii = IssueIdentifier(ca, self.config, self.current_talker())
|
||||
|
||||
def myoutput(text: str) -> None:
|
||||
if self.config.runtime_verbose:
|
||||
@ -421,7 +427,7 @@ class CLI:
|
||||
match_results.fetch_data_failures.append(str(ca.path.absolute()))
|
||||
return
|
||||
|
||||
if self.config.talkers_clear_metadata_on_import:
|
||||
if self.config.talker_clear_metadata_on_import:
|
||||
md = ct_md
|
||||
else:
|
||||
notes = (
|
||||
@ -430,7 +436,7 @@ class CLI:
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.config.talkers_auto_imprint:
|
||||
if self.config.talker_auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
# ok, done building our metadata. time to save
|
||||
|
@ -31,7 +31,7 @@ from comictaggerlib.imagepopup import ImagePopup
|
||||
from comictaggerlib.pageloader import PageLoader
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictaggerlib.ui.qtutils import get_qimage_from_data, reduce_widget_font_size
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
from comictalker.comictalker import ComicTalker
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -68,17 +68,17 @@ class CoverImageWidget(QtWidgets.QWidget):
|
||||
parent: QtWidgets.QWidget,
|
||||
mode: int,
|
||||
cache_folder: pathlib.Path | None,
|
||||
talker_api: ComicTalker | None,
|
||||
talker: ComicTalker | None,
|
||||
expand_on_click: bool = True,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
if mode not in (self.AltCoverMode, self.URLMode) or cache_folder is None:
|
||||
self.cover_fetcher = None
|
||||
self.talker_api = None
|
||||
self.talker = None
|
||||
else:
|
||||
self.cover_fetcher = ImageFetcher(cache_folder)
|
||||
self.talker_api = None
|
||||
self.talker = None
|
||||
uic.loadUi(ui_path / "coverimagewidget.ui", self)
|
||||
|
||||
reduce_widget_font_size(self.label)
|
||||
|
@ -8,7 +8,7 @@ from comictaggerlib.ctsettings.commandline import (
|
||||
from comictaggerlib.ctsettings.file import register_file_settings, validate_file_settings
|
||||
from comictaggerlib.ctsettings.plugin import register_plugin_settings, validate_plugin_settings
|
||||
from comictaggerlib.ctsettings.types import ComicTaggerPaths
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
from comictalker import ComicTalker
|
||||
|
||||
talkers: dict[str, ComicTalker] = {}
|
||||
|
||||
|
@ -267,8 +267,9 @@ def register_commandline_settings(parser: settngs.Manager) -> None:
|
||||
parser.add_group("runtime", register_settings)
|
||||
|
||||
|
||||
def validate_commandline_settings(config: settngs.Config[settngs.Values], parser: settngs.Manager) -> settngs.Values:
|
||||
|
||||
def validate_commandline_settings(
|
||||
config: settngs.Config[settngs.Namespace], parser: settngs.Manager
|
||||
) -> settngs.Config[settngs.Namespace]:
|
||||
if config[0].commands_version:
|
||||
parser.exit(
|
||||
status=1,
|
||||
|
@ -2,7 +2,6 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import uuid
|
||||
from typing import Any
|
||||
|
||||
import settngs
|
||||
|
||||
@ -84,8 +83,8 @@ def filename(parser: settngs.Manager) -> None:
|
||||
)
|
||||
|
||||
|
||||
def talkers(parser: settngs.Manager) -> None:
|
||||
# General settings for all information talkers
|
||||
def talker(parser: settngs.Manager) -> None:
|
||||
# General settings for talkers
|
||||
parser.add_setting("--source", default="comicvine", help="Use a specified source by source ID")
|
||||
parser.add_setting(
|
||||
"--series-match-search-thresh",
|
||||
@ -225,7 +224,7 @@ def autotag(parser: settngs.Manager) -> None:
|
||||
)
|
||||
|
||||
|
||||
def validate_file_settings(config: settngs.Config[settngs.Values]) -> dict[str, dict[str, Any]]:
|
||||
def validate_file_settings(config: settngs.Config[settngs.Namespace]) -> settngs.Config[settngs.Namespace]:
|
||||
config[0].identifier_publisher_filter = [x.strip() for x in config[0].identifier_publisher_filter if x.strip()]
|
||||
config[0].rename_replacements = Replacements(
|
||||
[Replacement(x[0], x[1], x[2]) for x in config[0].rename_replacements[0]],
|
||||
@ -240,7 +239,7 @@ def register_file_settings(parser: settngs.Manager) -> None:
|
||||
parser.add_group("identifier", identifier, False)
|
||||
parser.add_group("dialog", dialog, False)
|
||||
parser.add_group("filename", filename, False)
|
||||
parser.add_group("talkers", talkers, False)
|
||||
parser.add_group("talker", talker, False)
|
||||
parser.add_group("cbl", cbl, False)
|
||||
parser.add_group("rename", rename, False)
|
||||
parser.add_group("autotag", autotag, False)
|
||||
|
@ -10,7 +10,7 @@ import types
|
||||
import settngs
|
||||
|
||||
from comictaggerlib.graphics import graphics_path
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
from comictalker.comictalker import ComicTalker
|
||||
|
||||
logger = logging.getLogger("comictagger")
|
||||
try:
|
||||
@ -83,7 +83,7 @@ except ImportError as e:
|
||||
|
||||
|
||||
def open_tagger_window(
|
||||
talker_api: ComicTalker | None, config: settngs.Config[settngs.Namespace], error: tuple[str, bool] | None
|
||||
talkers: dict[str, ComicTalker], config: settngs.Config[settngs.Namespace], error: tuple[str, bool] | None
|
||||
) -> None:
|
||||
os.environ["QtWidgets.QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"
|
||||
args = []
|
||||
@ -96,8 +96,6 @@ def open_tagger_window(
|
||||
if error[1]:
|
||||
raise SystemExit(1)
|
||||
|
||||
assert talker_api is not None
|
||||
|
||||
# needed to catch initial open file events (macOS)
|
||||
app.openFileRequest.connect(lambda x: config[0].runtime_files.append(x.toLocalFile()))
|
||||
|
||||
@ -127,7 +125,7 @@ def open_tagger_window(
|
||||
QtWidgets.QApplication.processEvents()
|
||||
|
||||
try:
|
||||
tagger_window = TaggerWindow(config[0].runtime_files, config, talker_api)
|
||||
tagger_window = TaggerWindow(config[0].runtime_files, config, talkers)
|
||||
tagger_window.setWindowIcon(QtGui.QIcon(str(graphics_path / "app.png")))
|
||||
tagger_window.show()
|
||||
|
||||
|
@ -30,7 +30,7 @@ from comicapi.issuestring import IssueString
|
||||
from comictaggerlib.imagefetcher import ImageFetcher, ImageFetcherException
|
||||
from comictaggerlib.imagehasher import ImageHasher
|
||||
from comictaggerlib.resulttypes import IssueResult
|
||||
from comictalker.talkerbase import ComicTalker, TalkerError
|
||||
from comictalker.comictalker import ComicTalker, TalkerError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -72,9 +72,9 @@ class IssueIdentifier:
|
||||
result_one_good_match = 4
|
||||
result_multiple_good_matches = 5
|
||||
|
||||
def __init__(self, comic_archive: ComicArchive, config: settngs.Namespace, talker_api: ComicTalker) -> None:
|
||||
def __init__(self, comic_archive: ComicArchive, config: settngs.Namespace, talker: ComicTalker) -> None:
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.talker = talker
|
||||
self.comic_archive: ComicArchive = comic_archive
|
||||
self.image_hasher = 1
|
||||
|
||||
@ -188,8 +188,8 @@ class IssueIdentifier:
|
||||
height = bbox[3] - bbox[1]
|
||||
|
||||
# Convert to percent
|
||||
width_percent = 100 - ((width / im.width) * 100)
|
||||
height_percent = 100 - ((height / im.height) * 100)
|
||||
width_percent = int(100 - ((width / im.width) * 100))
|
||||
height_percent = int(100 - ((height / im.height) * 100))
|
||||
logger.debug(
|
||||
"Width: %s Height: %s, ratio: %s %s ratio met: %s",
|
||||
im.width,
|
||||
@ -411,7 +411,7 @@ class IssueIdentifier:
|
||||
|
||||
self.log_msg(f"Searching for {keys['series']} #{keys['issue_number']} ...")
|
||||
try:
|
||||
ct_search_results = self.talker_api.search_for_series(keys["series"])
|
||||
ct_search_results = self.talker.search_for_series(keys["series"])
|
||||
except TalkerError as e:
|
||||
self.log_msg(f"Error searching for series.\n{e}")
|
||||
return []
|
||||
@ -460,7 +460,7 @@ class IssueIdentifier:
|
||||
issue_list = None
|
||||
try:
|
||||
if len(series_by_id) > 0:
|
||||
issue_list = self.talker_api.fetch_issues_by_series_issue_num_and_year(
|
||||
issue_list = self.talker.fetch_issues_by_series_issue_num_and_year(
|
||||
list(series_by_id.keys()), keys["issue_number"], keys["year"]
|
||||
)
|
||||
except TalkerError as e:
|
||||
|
@ -24,8 +24,8 @@ from comicapi.issuestring import IssueString
|
||||
from comictaggerlib.coverimagewidget import CoverImageWidget
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictaggerlib.ui.qtutils import reduce_widget_font_size
|
||||
from comictalker.comictalker import ComicTalker, TalkerError
|
||||
from comictalker.resulttypes import ComicIssue
|
||||
from comictalker.talkerbase import ComicTalker, TalkerError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -43,7 +43,7 @@ class IssueSelectionWindow(QtWidgets.QDialog):
|
||||
self,
|
||||
parent: QtWidgets.QWidget,
|
||||
config: settngs.Namespace,
|
||||
talker_api: ComicTalker,
|
||||
talker: ComicTalker,
|
||||
series_id: str,
|
||||
issue_number: str,
|
||||
) -> None:
|
||||
@ -52,7 +52,7 @@ class IssueSelectionWindow(QtWidgets.QDialog):
|
||||
uic.loadUi(ui_path / "issueselectionwindow.ui", self)
|
||||
|
||||
self.coverWidget = CoverImageWidget(
|
||||
self.coverImageContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker_api
|
||||
self.coverImageContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.coverImageContainer)
|
||||
gridlayout.addWidget(self.coverWidget)
|
||||
@ -72,24 +72,24 @@ class IssueSelectionWindow(QtWidgets.QDialog):
|
||||
self.series_id = series_id
|
||||
self.issue_id: str = ""
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.talker = talker
|
||||
self.url_fetch_thread = None
|
||||
self.issue_list: list[ComicIssue] = []
|
||||
|
||||
# Display talker logo and set url
|
||||
self.lblIssuesSourceName.setText(talker_api.static_config.attribution_string)
|
||||
self.lblIssuesSourceName.setText(talker.attribution)
|
||||
|
||||
self.imageIssuesSourceWidget = CoverImageWidget(
|
||||
self.imageIssuesSourceLogo,
|
||||
CoverImageWidget.URLMode,
|
||||
config.runtime_config.user_cache_dir,
|
||||
talker_api,
|
||||
talker,
|
||||
False,
|
||||
)
|
||||
gridlayoutIssuesSourceLogo = QtWidgets.QGridLayout(self.imageIssuesSourceLogo)
|
||||
gridlayoutIssuesSourceLogo.addWidget(self.imageIssuesSourceWidget)
|
||||
gridlayoutIssuesSourceLogo.setContentsMargins(0, 2, 0, 0)
|
||||
self.imageIssuesSourceWidget.set_url(talker_api.source_details.logo)
|
||||
self.imageIssuesSourceWidget.set_url(talker.logo_url)
|
||||
|
||||
if issue_number is None or issue_number == "":
|
||||
self.issue_number = "1"
|
||||
@ -119,7 +119,7 @@ class IssueSelectionWindow(QtWidgets.QDialog):
|
||||
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CursorShape.WaitCursor))
|
||||
|
||||
try:
|
||||
self.issue_list = self.talker_api.fetch_issues_by_series(self.series_id)
|
||||
self.issue_list = self.talker.fetch_issues_by_series(self.series_id)
|
||||
except TalkerError as e:
|
||||
QtWidgets.QApplication.restoreOverrideCursor()
|
||||
QtWidgets.QMessageBox.critical(self, f"{e.source} {e.code_name} Error", f"{e}")
|
||||
|
@ -24,7 +24,7 @@ import sys
|
||||
import settngs
|
||||
|
||||
import comicapi
|
||||
import comictalker.comictalkerapi as ct_api
|
||||
import comictalker
|
||||
from comictaggerlib import cli, ctsettings
|
||||
from comictaggerlib.ctversion import version
|
||||
from comictaggerlib.log import setup_logging
|
||||
@ -34,21 +34,22 @@ if sys.version_info < (3, 10):
|
||||
else:
|
||||
import importlib.metadata as importlib_metadata
|
||||
|
||||
logger = logging.getLogger("comictagger")
|
||||
|
||||
try:
|
||||
from comictaggerlib import gui
|
||||
|
||||
qt_available = gui.qt_available
|
||||
except Exception:
|
||||
logger.exception("Qt unavailable")
|
||||
qt_available = False
|
||||
|
||||
logger = logging.getLogger("comictagger")
|
||||
|
||||
|
||||
logger.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
def update_publishers(config: settngs.Namespace) -> None:
|
||||
json_file = config.runtime_config.user_config_dir / "publishers.json"
|
||||
def update_publishers(config: settngs.Config[settngs.Namespace]) -> None:
|
||||
json_file = config[0].runtime_config.user_config_dir / "publishers.json"
|
||||
if json_file.exists():
|
||||
try:
|
||||
comicapi.utils.update_publishers(json.loads(json_file.read_text("utf-8")))
|
||||
@ -60,7 +61,7 @@ class App:
|
||||
"""docstring for App"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.config = settngs.Config({}, {})
|
||||
self.config: settngs.Config[settngs.Namespace]
|
||||
self.initial_arg_parser = ctsettings.initial_commandline_parser()
|
||||
self.config_load_success = False
|
||||
|
||||
@ -73,9 +74,9 @@ class App:
|
||||
|
||||
self.main()
|
||||
|
||||
def load_plugins(self, opts) -> None:
|
||||
def load_plugins(self, opts: argparse.Namespace) -> None:
|
||||
comicapi.comicarchive.load_archive_plugins()
|
||||
ctsettings.talkers = ct_api.get_talkers(version, opts.config.user_cache_dir)
|
||||
ctsettings.talkers = comictalker.get_talkers(version, opts.config.user_cache_dir)
|
||||
|
||||
def initialize(self) -> argparse.Namespace:
|
||||
conf, _ = self.initial_arg_parser.parse_known_args()
|
||||
@ -92,9 +93,9 @@ class App:
|
||||
ctsettings.register_file_settings(self.manager)
|
||||
ctsettings.register_plugin_settings(self.manager)
|
||||
|
||||
def parse_settings(self, config_paths: ctsettings.ComicTaggerPaths) -> settngs.Config:
|
||||
config, self.config_load_success = self.manager.parse_config(config_paths.user_config_dir / "settings.json")
|
||||
config = self.manager.get_namespace(config)
|
||||
def parse_settings(self, config_paths: ctsettings.ComicTaggerPaths) -> settngs.Config[settngs.Namespace]:
|
||||
cfg, self.config_load_success = self.manager.parse_config(config_paths.user_config_dir / "settings.json")
|
||||
config = self.manager.get_namespace(cfg)
|
||||
|
||||
config = ctsettings.validate_commandline_settings(config, self.manager)
|
||||
config = ctsettings.validate_file_settings(config)
|
||||
@ -125,7 +126,7 @@ class App:
|
||||
logger.debug("%s\t%s", pkg.metadata["Name"], pkg.metadata["Version"])
|
||||
|
||||
comicapi.utils.load_publishers()
|
||||
update_publishers(self.config[0])
|
||||
update_publishers(self.config)
|
||||
|
||||
if not qt_available and not self.config[0].runtime_no_gui:
|
||||
self.config[0].runtime_no_gui = True
|
||||
@ -143,31 +144,26 @@ class App:
|
||||
print("Key set") # noqa: T201
|
||||
return
|
||||
|
||||
try:
|
||||
talker_api = ctsettings.talkers[self.config[0].talkers_source]
|
||||
except Exception as e:
|
||||
logger.exception(f"Unable to load talker {self.config[0].talkers_source}")
|
||||
error = (f"Unable to load talker {self.config[0].talkers_source}: {e}", True)
|
||||
talker_api = None
|
||||
|
||||
if not self.config_load_success:
|
||||
error = (
|
||||
f"Failed to load settings, check the log located in '{self.config[0].runtime_config.user_log_dir}' for more details",
|
||||
True,
|
||||
)
|
||||
|
||||
talkers = ctsettings.talkers
|
||||
del ctsettings.talkers
|
||||
|
||||
if self.config[0].runtime_no_gui:
|
||||
if error and error[1]:
|
||||
print(f"A fatal error occurred please check the log for more information: {error[0]}") # noqa: T201
|
||||
raise SystemExit(1)
|
||||
assert talker_api is not None
|
||||
try:
|
||||
cli.CLI(self.config[0], talker_api).run()
|
||||
cli.CLI(self.config[0], talkers).run()
|
||||
except Exception:
|
||||
logger.exception("CLI mode failed")
|
||||
else:
|
||||
gui.open_tagger_window(talker_api, self.config, error)
|
||||
gui.open_tagger_window(talkers, self.config, error)
|
||||
|
||||
|
||||
def main():
|
||||
def main() -> None:
|
||||
App().run()
|
||||
|
@ -26,7 +26,7 @@ from comictaggerlib.coverimagewidget import CoverImageWidget
|
||||
from comictaggerlib.resulttypes import IssueResult
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictaggerlib.ui.qtutils import reduce_widget_font_size
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
from comictalker.comictalker import ComicTalker
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -37,15 +37,15 @@ class MatchSelectionWindow(QtWidgets.QDialog):
|
||||
parent: QtWidgets.QWidget,
|
||||
matches: list[IssueResult],
|
||||
comic_archive: ComicArchive,
|
||||
config: settngs.Values,
|
||||
talker_api: ComicTalker,
|
||||
config: settngs.Namespace,
|
||||
talker: ComicTalker,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "matchselectionwindow.ui", self)
|
||||
|
||||
self.altCoverWidget = CoverImageWidget(
|
||||
self.altCoverContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker_api
|
||||
self.altCoverContainer, CoverImageWidget.AltCoverMode, config.runtime_config.user_cache_dir, talker
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.altCoverContainer)
|
||||
gridlayout.addWidget(self.altCoverWidget)
|
||||
|
@ -25,13 +25,12 @@ from comicapi.genericmetadata import GenericMetadata
|
||||
from comictaggerlib.coverimagewidget import CoverImageWidget
|
||||
from comictaggerlib.graphics import graphics_path
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PageBrowserWindow(QtWidgets.QDialog):
|
||||
def __init__(self, parent: QtWidgets.QWidget, talker_api: ComicTalker, metadata: GenericMetadata) -> None:
|
||||
def __init__(self, parent: QtWidgets.QWidget, metadata: GenericMetadata) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "pagebrowser.ui", self)
|
||||
|
@ -23,7 +23,6 @@ from comicapi.comicarchive import ComicArchive, MetaDataStyle
|
||||
from comicapi.genericmetadata import ImageMetadata, PageType
|
||||
from comictaggerlib.coverimagewidget import CoverImageWidget
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -68,7 +67,7 @@ class PageListEditor(QtWidgets.QWidget):
|
||||
PageType.Deleted: "Deleted",
|
||||
}
|
||||
|
||||
def __init__(self, parent: QtWidgets.QWidget, talker_api: ComicTalker) -> None:
|
||||
def __init__(self, parent: QtWidgets.QWidget) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "pagelisteditor.ui", self)
|
||||
|
@ -27,7 +27,7 @@ from comictaggerlib.filerenamer import FileRenamer, get_rename_dir
|
||||
from comictaggerlib.settingswindow import SettingsWindow
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictaggerlib.ui.qtutils import center_window_on_parent
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
from comictalker.comictalker import ComicTalker
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -38,8 +38,8 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
parent: QtWidgets.QWidget,
|
||||
comic_archive_list: list[ComicArchive],
|
||||
data_style: int,
|
||||
config: settngs.Config,
|
||||
talker_api: ComicTalker,
|
||||
config: settngs.Config[settngs.Namespace],
|
||||
talker: ComicTalker,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
@ -55,7 +55,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
)
|
||||
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.talker = talker
|
||||
self.comic_archive_list = comic_archive_list
|
||||
self.data_style = data_style
|
||||
self.rename_list: list[str] = []
|
||||
@ -162,7 +162,7 @@ class RenameWindow(QtWidgets.QDialog):
|
||||
self.twList.setSortingEnabled(True)
|
||||
|
||||
def modify_settings(self) -> None:
|
||||
settingswin = SettingsWindow(self, self.config, self.talker_api)
|
||||
settingswin = SettingsWindow(self, self.config, self.talker)
|
||||
settingswin.setModal(True)
|
||||
settingswin.show_rename_tab()
|
||||
settingswin.exec()
|
||||
|
@ -33,8 +33,8 @@ from comictaggerlib.matchselectionwindow import MatchSelectionWindow
|
||||
from comictaggerlib.progresswindow import IDProgressWindow
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictaggerlib.ui.qtutils import reduce_widget_font_size
|
||||
from comictalker.comictalker import ComicTalker, TalkerError
|
||||
from comictalker.resulttypes import ComicSeries
|
||||
from comictalker.talkerbase import ComicTalker, TalkerError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -45,14 +45,14 @@ class SearchThread(QtCore.QThread):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
talker_api: ComicTalker,
|
||||
talker: ComicTalker,
|
||||
series_name: str,
|
||||
refresh: bool,
|
||||
literal: bool = False,
|
||||
series_match_thresh: int = 90,
|
||||
) -> None:
|
||||
QtCore.QThread.__init__(self)
|
||||
self.talker_api = talker_api
|
||||
self.talker = talker
|
||||
self.series_name = series_name
|
||||
self.refresh: bool = refresh
|
||||
self.error_e: TalkerError
|
||||
@ -64,7 +64,7 @@ class SearchThread(QtCore.QThread):
|
||||
def run(self) -> None:
|
||||
try:
|
||||
self.ct_error = False
|
||||
self.ct_search_results = self.talker_api.search_for_series(
|
||||
self.ct_search_results = self.talker.search_for_series(
|
||||
self.series_name, self.prog_callback, self.refresh, self.literal, self.series_match_thresh
|
||||
)
|
||||
except TalkerError as e:
|
||||
@ -112,7 +112,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
cover_index_list: list[int],
|
||||
comic_archive: ComicArchive | None,
|
||||
config: settngs.Namespace,
|
||||
talker_api: ComicTalker,
|
||||
talker: ComicTalker,
|
||||
autoselect: bool = False,
|
||||
literal: bool = False,
|
||||
) -> None:
|
||||
@ -121,7 +121,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
uic.loadUi(ui_path / "seriesselectionwindow.ui", self)
|
||||
|
||||
self.imageWidget = CoverImageWidget(
|
||||
self.imageContainer, CoverImageWidget.URLMode, config.runtime_config.user_cache_dir, talker_api
|
||||
self.imageContainer, CoverImageWidget.URLMode, config.runtime_config.user_cache_dir, talker
|
||||
)
|
||||
gridlayout = QtWidgets.QGridLayout(self.imageContainer)
|
||||
gridlayout.addWidget(self.imageWidget)
|
||||
@ -156,25 +156,25 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
self.progdialog: QtWidgets.QProgressDialog | None = None
|
||||
self.search_thread: SearchThread | None = None
|
||||
|
||||
self.use_filter = self.config.talkers_always_use_publisher_filter
|
||||
self.use_filter = self.config.talker_always_use_publisher_filter
|
||||
|
||||
# Load to retrieve settings
|
||||
self.talker_api = talker_api
|
||||
self.talker = talker
|
||||
|
||||
# Display talker logo and set url
|
||||
self.lblSourceName.setText(talker_api.static_config.attribution_string)
|
||||
self.lblSourceName.setText(talker.attribution)
|
||||
|
||||
self.imageSourceWidget = CoverImageWidget(
|
||||
self.imageSourceLogo,
|
||||
CoverImageWidget.URLMode,
|
||||
config.runtime_config.user_cache_dir,
|
||||
talker_api,
|
||||
talker,
|
||||
False,
|
||||
)
|
||||
gridlayoutSourceLogo = QtWidgets.QGridLayout(self.imageSourceLogo)
|
||||
gridlayoutSourceLogo.addWidget(self.imageSourceWidget)
|
||||
gridlayoutSourceLogo.setContentsMargins(0, 2, 0, 0)
|
||||
self.imageSourceWidget.set_url(talker_api.source_details.logo)
|
||||
self.imageSourceWidget.set_url(talker.logo_url)
|
||||
|
||||
# Set the minimum row height to the default.
|
||||
# this way rows will be more consistent when resizeRowsToContents is called
|
||||
@ -224,7 +224,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
self.iddialog.rejected.connect(self.identify_cancel)
|
||||
self.iddialog.show()
|
||||
|
||||
self.ii = IssueIdentifier(self.comic_archive, self.config, self.talker_api)
|
||||
self.ii = IssueIdentifier(self.comic_archive, self.config, self.talker)
|
||||
|
||||
md = GenericMetadata()
|
||||
md.series = self.series_name
|
||||
@ -298,7 +298,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
|
||||
if choices:
|
||||
selector = MatchSelectionWindow(
|
||||
self, matches, self.comic_archive, talker_api=self.talker_api, config=self.config
|
||||
self, matches, self.comic_archive, talker=self.talker, config=self.config
|
||||
)
|
||||
selector.setModal(True)
|
||||
selector.exec()
|
||||
@ -315,7 +315,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
self.show_issues()
|
||||
|
||||
def show_issues(self) -> None:
|
||||
selector = IssueSelectionWindow(self, self.config, self.talker_api, self.series_id, self.issue_number)
|
||||
selector = IssueSelectionWindow(self, self.config, self.talker, self.series_id, self.issue_number)
|
||||
title = ""
|
||||
for record in self.ct_search_results:
|
||||
if record.id == self.series_id:
|
||||
@ -343,7 +343,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
def perform_query(self, refresh: bool = False) -> None:
|
||||
|
||||
self.search_thread = SearchThread(
|
||||
self.talker_api, self.series_name, refresh, self.literal, self.config.talkers_series_match_search_thresh
|
||||
self.talker, self.series_name, refresh, self.literal, self.config.talker_series_match_search_thresh
|
||||
)
|
||||
self.search_thread.searchComplete.connect(self.search_complete)
|
||||
self.search_thread.progressUpdate.connect(self.search_progress_update)
|
||||
@ -410,7 +410,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
# compare as str in case extra chars ie. '1976?'
|
||||
# - missing (none) values being converted to 'None' - consistent with prior behaviour in v1.2.3
|
||||
# sort by start_year if set
|
||||
if self.config.talkers_sort_series_by_year:
|
||||
if self.config.talker_sort_series_by_year:
|
||||
try:
|
||||
self.ct_search_results = sorted(
|
||||
self.ct_search_results,
|
||||
@ -428,7 +428,7 @@ class SeriesSelectionWindow(QtWidgets.QDialog):
|
||||
logger.exception("bad data error sorting results by count_of_issues")
|
||||
|
||||
# move sanitized matches to the front
|
||||
if self.config.talkers_exact_series_matches_first:
|
||||
if self.config.talker_exact_series_matches_first:
|
||||
try:
|
||||
sanitized = utils.sanitize_title(self.series_name, False).casefold()
|
||||
sanitized_no_articles = utils.sanitize_title(self.series_name, True).casefold()
|
||||
|
@ -32,7 +32,7 @@ from comictaggerlib.filerenamer import FileRenamer, Replacement, Replacements
|
||||
from comictaggerlib.imagefetcher import ImageFetcher
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictalker.comiccacher import ComicCacher
|
||||
from comictalker.talkerbase import ComicTalker
|
||||
from comictalker.comictalker import ComicTalker
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -130,7 +130,9 @@ Spider-Geddon #1 - New Players; Check In
|
||||
|
||||
|
||||
class SettingsWindow(QtWidgets.QDialog):
|
||||
def __init__(self, parent: QtWidgets.QWidget, config: settngs.Config, talker_api: ComicTalker) -> None:
|
||||
def __init__(
|
||||
self, parent: QtWidgets.QWidget, config: settngs.Config[settngs.Namespace], talker: ComicTalker
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "settingswindow.ui", self)
|
||||
@ -140,7 +142,7 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
)
|
||||
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.talker = talker
|
||||
self.name = "Settings"
|
||||
|
||||
if platform.system() == "Windows":
|
||||
@ -294,12 +296,12 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
def settings_to_form(self) -> None:
|
||||
self.disconnect_signals()
|
||||
# Copy values from settings to form
|
||||
if "archiver" in self.config[1] and "rar" in self.config[1]["archiver"]:
|
||||
self.leRarExePath.setText(getattr(self.config[0], self.config[1]["archiver"]["rar"].internal_name))
|
||||
if "archiver" in self.config[1] and "rar" in self.config[1]["archiver"].v:
|
||||
self.leRarExePath.setText(getattr(self.config[0], self.config[1]["archiver"].v["rar"].internal_name))
|
||||
else:
|
||||
self.leRarExePath.setEnabled(False)
|
||||
self.sbNameMatchIdentifyThresh.setValue(self.config[0].identifier_series_match_identify_thresh)
|
||||
self.sbNameMatchSearchThresh.setValue(self.config[0].talkers_series_match_search_thresh)
|
||||
self.sbNameMatchSearchThresh.setValue(self.config[0].talker_series_match_search_thresh)
|
||||
self.tePublisherFilter.setPlainText("\n".join(self.config[0].identifier_publisher_filter))
|
||||
|
||||
self.cbxCheckForNewVersion.setChecked(self.config[0].general_check_for_new_version)
|
||||
@ -311,12 +313,12 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
self.switch_parser()
|
||||
|
||||
self.cbxUseSeriesStartAsVolume.setChecked(self.config[0].talker_comicvine_cv_use_series_start_as_volume)
|
||||
self.cbxClearFormBeforePopulating.setChecked(self.config[0].talkers_clear_form_before_populating)
|
||||
self.cbxClearFormBeforePopulating.setChecked(self.config[0].talker_clear_form_before_populating)
|
||||
self.cbxRemoveHtmlTables.setChecked(self.config[0].talker_comicvine_cv_remove_html_tables)
|
||||
|
||||
self.cbxUseFilter.setChecked(self.config[0].talkers_always_use_publisher_filter)
|
||||
self.cbxSortByYear.setChecked(self.config[0].talkers_sort_series_by_year)
|
||||
self.cbxExactMatches.setChecked(self.config[0].talkers_exact_series_matches_first)
|
||||
self.cbxUseFilter.setChecked(self.config[0].talker_always_use_publisher_filter)
|
||||
self.cbxSortByYear.setChecked(self.config[0].talker_sort_series_by_year)
|
||||
self.cbxExactMatches.setChecked(self.config[0].talker_exact_series_matches_first)
|
||||
|
||||
self.leKey.setText(self.config[0].talker_comicvine_cv_api_key)
|
||||
self.leURL.setText(self.config[0].talker_comicvine_cv_url)
|
||||
@ -403,11 +405,11 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
)
|
||||
|
||||
# Copy values from form to settings and save
|
||||
if "archiver" in self.config[1] and "rar" in self.config[1]["archiver"]:
|
||||
setattr(self.config[0], self.config[1]["archiver"]["rar"].internal_name, str(self.leRarExePath.text()))
|
||||
if "archiver" in self.config[1] and "rar" in self.config[1]["archiver"].v:
|
||||
setattr(self.config[0], self.config[1]["archiver"].v["rar"].internal_name, str(self.leRarExePath.text()))
|
||||
|
||||
# make sure rar program is now in the path for the rar class
|
||||
if self.config[0].archivers_rar:
|
||||
if self.config[0].archiver_rar:
|
||||
utils.add_to_path(os.path.dirname(str(self.leRarExePath.text())))
|
||||
|
||||
if not str(self.leIssueNumPadding.text()).isdigit():
|
||||
@ -416,7 +418,7 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
self.config[0].general_check_for_new_version = self.cbxCheckForNewVersion.isChecked()
|
||||
|
||||
self.config[0].identifier_series_match_identify_thresh = self.sbNameMatchIdentifyThresh.value()
|
||||
self.config[0].talkers_series_match_search_thresh = self.sbNameMatchSearchThresh.value()
|
||||
self.config[0].talker_series_match_search_thresh = self.sbNameMatchSearchThresh.value()
|
||||
self.config[0].identifier_publisher_filter = [
|
||||
x.strip() for x in str(self.tePublisherFilter.toPlainText()).splitlines() if x.strip()
|
||||
]
|
||||
@ -427,20 +429,20 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
self.config[0].filename_remove_publisher = self.cbxRemovePublisher.isChecked()
|
||||
|
||||
self.config[0].talker_comicvine_cv_use_series_start_as_volume = self.cbxUseSeriesStartAsVolume.isChecked()
|
||||
self.config[0].talkers_clear_form_before_populating = self.cbxClearFormBeforePopulating.isChecked()
|
||||
self.config[0].talker_clear_form_before_populating = self.cbxClearFormBeforePopulating.isChecked()
|
||||
self.config[0].talker_comicvine_cv_remove_html_tables = self.cbxRemoveHtmlTables.isChecked()
|
||||
|
||||
self.config[0].talkers_always_use_publisher_filter = self.cbxUseFilter.isChecked()
|
||||
self.config[0].talkers_sort_series_by_year = self.cbxSortByYear.isChecked()
|
||||
self.config[0].talkers_exact_series_matches_first = self.cbxExactMatches.isChecked()
|
||||
self.config[0].talker_always_use_publisher_filter = self.cbxUseFilter.isChecked()
|
||||
self.config[0].talker_sort_series_by_year = self.cbxSortByYear.isChecked()
|
||||
self.config[0].talker_exact_series_matches_first = self.cbxExactMatches.isChecked()
|
||||
|
||||
if self.leKey.text().strip():
|
||||
self.config[0].talker_comicvine_cv_api_key = self.leKey.text().strip()
|
||||
self.talker_api.api_key = self.config[0].talker_comicvine_cv_api_key
|
||||
self.talker.api_key = self.config[0].talker_comicvine_cv_api_key
|
||||
|
||||
if self.leURL.text().strip():
|
||||
self.config[0].talker_comicvine_cv_url = self.leURL.text().strip()
|
||||
self.talker_api.api_url = self.config[0].talker_comicvine_cv_url
|
||||
self.talker.api_url = self.config[0].talker_comicvine_cv_url
|
||||
|
||||
self.config[0].cbl_assume_lone_credit_is_primary = self.cbxAssumeLoneCreditIsPrimary.isChecked()
|
||||
self.config[0].cbl_copy_characters_to_tags = self.cbxCopyCharactersToTags.isChecked()
|
||||
@ -462,10 +464,17 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
self.config[0].rename_strict = self.cbxRenameStrict.isChecked()
|
||||
self.config[0].rename_replacements = self.get_replacements()
|
||||
|
||||
self.update_talkers_config()
|
||||
|
||||
settngs.save_file(self.config, self.config[0].runtime_config.user_config_dir / "settings.json")
|
||||
self.parent().config = self.config
|
||||
QtWidgets.QDialog.accept(self)
|
||||
|
||||
def update_talkers_config(self) -> None:
|
||||
cfg = settngs.normalize_config(self.config, True, True)
|
||||
if f"talker_{self.talker.id}" in cfg[0]:
|
||||
self.talker.parse_settings(cfg[0][f"talker_{self.talker.id}"])
|
||||
|
||||
def select_rar(self) -> None:
|
||||
self.select_file(self.leRarExePath, "RAR")
|
||||
|
||||
@ -475,7 +484,7 @@ class SettingsWindow(QtWidgets.QDialog):
|
||||
QtWidgets.QMessageBox.information(self, self.name, "Cache has been cleared.")
|
||||
|
||||
def test_api_key(self) -> None:
|
||||
if self.talker_api.check_api_key(self.leKey.text().strip(), self.leURL.text().strip()):
|
||||
if self.talker.check_api_key(self.leKey.text().strip(), self.leURL.text().strip()):
|
||||
QtWidgets.QMessageBox.information(self, "API Key Test", "Key is valid!")
|
||||
else:
|
||||
QtWidgets.QMessageBox.warning(self, "API Key Test", "Key is NOT valid.")
|
||||
|
@ -63,7 +63,7 @@ from comictaggerlib.settingswindow import SettingsWindow
|
||||
from comictaggerlib.ui import ui_path
|
||||
from comictaggerlib.ui.qtutils import center_window_on_parent, reduce_widget_font_size
|
||||
from comictaggerlib.versionchecker import VersionChecker
|
||||
from comictalker.talkerbase import ComicTalker, TalkerError
|
||||
from comictalker.comictalker import ComicTalker, TalkerError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -79,15 +79,15 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
def __init__(
|
||||
self,
|
||||
file_list: list[str],
|
||||
config: settngs.Config,
|
||||
talker_api: ComicTalker,
|
||||
config: settngs.Config[settngs.Namespace],
|
||||
talkers: dict[str, ComicTalker],
|
||||
parent: QtWidgets.QWidget | None = None,
|
||||
) -> None:
|
||||
super().__init__(parent)
|
||||
|
||||
uic.loadUi(ui_path / "taggerwindow.ui", self)
|
||||
self.config = config
|
||||
self.talker_api = talker_api
|
||||
self.talkers = talkers
|
||||
self.log_window = self.setup_logger()
|
||||
|
||||
# prevent multiple instances
|
||||
@ -126,7 +126,7 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
grid_layout.addWidget(self.archiveCoverWidget)
|
||||
grid_layout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
self.page_list_editor = PageListEditor(self.tabPages, self.talker_api)
|
||||
self.page_list_editor = PageListEditor(self.tabPages)
|
||||
grid_layout = QtWidgets.QGridLayout(self.tabPages)
|
||||
grid_layout.addWidget(self.page_list_editor)
|
||||
|
||||
@ -249,21 +249,27 @@ class TaggerWindow(QtWidgets.QMainWindow):
|
||||
self,
|
||||
"Welcome!",
|
||||
"""
|
||||
Thanks for trying ComicTagger!<br><br>
|
||||
Be aware that this is beta-level software, and consider it experimental.
|
||||
You should use it very carefully when modifying your data files. As the
|
||||
license says, it's "AS IS!"<br><br>
|
||||
Also, be aware that writing tags to comic archives will change their file hashes,
|
||||
which has implications with respect to other software packages. It's best to
|
||||
use ComicTagger on local copies of your comics.<br><br>
|
||||
Have fun!
|
||||
""",
|
||||
Thanks for trying ComicTagger!<br><br>
|
||||
Be aware that this is beta-level software, and consider it experimental.
|
||||
You should use it very carefully when modifying your data files. As the
|
||||
license says, it's "AS IS!"<br><br>
|
||||
Also, be aware that writing tags to comic archives will change their file hashes,
|
||||
which has implications with respect to other software packages. It's best to
|
||||
use ComicTagger on local copies of your comics.<br><br>
|
||||
Have fun!
|
||||
""",
|
||||
)
|
||||
self.config[0].dialog_show_disclaimer = not checked
|
||||
|
||||
if self.config[0].general_check_for_new_version:
|
||||
self.check_latest_version_online()
|
||||
|
||||
def current_talker(self) -> ComicTalker:
|
||||
if self.config[0].talker_source in self.talkers:
|
||||
return self.talkers[self.config[0].talker_source]
|
||||
logger.error("Could not find the '%s' talker", self.config[0].talker_source)
|
||||
raise SystemExit(2)
|
||||
|
||||
def open_file_event(self, url: QtCore.QUrl) -> None:
|
||||
logger.info(url.toLocalFile())
|
||||
self.fileSelectionList.add_path_list([url.toLocalFile()])
|
||||
@ -1045,7 +1051,7 @@ Have fun!
|
||||
cover_index_list,
|
||||
self.comic_archive,
|
||||
self.config[0],
|
||||
self.talker_api,
|
||||
self.current_talker(),
|
||||
autoselect,
|
||||
literal,
|
||||
)
|
||||
@ -1063,7 +1069,7 @@ Have fun!
|
||||
self.form_to_metadata()
|
||||
|
||||
try:
|
||||
new_metadata = self.talker_api.fetch_comic_data(
|
||||
new_metadata = self.current_talker().fetch_comic_data(
|
||||
issue_id=selector.issue_id, series_id=selector.series_id, issue_number=selector.issue_number
|
||||
)
|
||||
except TalkerError as e:
|
||||
@ -1075,11 +1081,11 @@ Have fun!
|
||||
if self.config[0].cbl_apply_transform_on_import:
|
||||
new_metadata = CBLTransformer(new_metadata, self.config[0]).apply()
|
||||
|
||||
if self.config[0].talkers_clear_form_before_populating:
|
||||
if self.config[0].talker_clear_form_before_populating:
|
||||
self.clear_form()
|
||||
|
||||
notes = (
|
||||
f"Tagged with ComicTagger {ctversion.version} using info from {self.talker_api.source_details.name} on"
|
||||
f"Tagged with ComicTagger {ctversion.version} using info from {self.current_talker().name} on"
|
||||
f" {datetime.now():%Y-%m-%d %H:%M:%S}. [Issue ID {new_metadata.issue_id}]"
|
||||
)
|
||||
self.metadata.overlay(
|
||||
@ -1360,7 +1366,7 @@ Have fun!
|
||||
|
||||
def show_settings(self) -> None:
|
||||
|
||||
settingswin = SettingsWindow(self, self.config, self.talker_api)
|
||||
settingswin = SettingsWindow(self, self.config, self.current_talker())
|
||||
settingswin.setModal(True)
|
||||
settingswin.exec()
|
||||
settingswin.result()
|
||||
@ -1669,7 +1675,7 @@ Have fun!
|
||||
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.CursorShape.WaitCursor))
|
||||
|
||||
try:
|
||||
ct_md = self.talker_api.fetch_comic_data(match["issue_id"])
|
||||
ct_md = self.current_talker().fetch_comic_data(match["issue_id"])
|
||||
except TalkerError:
|
||||
logger.exception("Save aborted.")
|
||||
|
||||
@ -1694,7 +1700,7 @@ Have fun!
|
||||
self, ca: ComicArchive, match_results: OnlineMatchResults, dlg: AutoTagStartWindow
|
||||
) -> tuple[bool, OnlineMatchResults]:
|
||||
success = False
|
||||
ii = IssueIdentifier(ca, self.config[0], self.talker_api)
|
||||
ii = IssueIdentifier(ca, self.config[0], self.current_talker())
|
||||
|
||||
# read in metadata, and parse file name if not there
|
||||
try:
|
||||
@ -1793,7 +1799,7 @@ Have fun!
|
||||
)
|
||||
md.overlay(ct_md.replace(notes=utils.combine_notes(md.notes, notes, "Tagged with ComicTagger")))
|
||||
|
||||
if self.config[0].talkers_auto_imprint:
|
||||
if self.config[0].talker_auto_imprint:
|
||||
md.fix_publisher()
|
||||
|
||||
if not ca.write_metadata(md, self.save_data_style):
|
||||
@ -1834,7 +1840,7 @@ Have fun!
|
||||
if not atstartdlg.exec():
|
||||
return
|
||||
|
||||
self.atprogdialog = AutoTagProgressWindow(self, self.talker_api)
|
||||
self.atprogdialog = AutoTagProgressWindow(self, self.current_talker())
|
||||
self.atprogdialog.setModal(True)
|
||||
self.atprogdialog.show()
|
||||
self.atprogdialog.progressBar.setMaximum(len(ca_list))
|
||||
@ -1926,7 +1932,7 @@ Have fun!
|
||||
style,
|
||||
self.actual_issue_data_fetch,
|
||||
self.config[0],
|
||||
self.talker_api,
|
||||
self.current_talker(),
|
||||
)
|
||||
matchdlg.setModal(True)
|
||||
matchdlg.exec()
|
||||
@ -1989,7 +1995,7 @@ Have fun!
|
||||
|
||||
def show_page_browser(self) -> None:
|
||||
if self.page_browser is None:
|
||||
self.page_browser = PageBrowserWindow(self, self.talker_api, self.metadata)
|
||||
self.page_browser = PageBrowserWindow(self, self.metadata)
|
||||
if self.comic_archive is not None:
|
||||
self.page_browser.set_comic_archive(self.comic_archive)
|
||||
self.page_browser.finished.connect(self.page_browser_closed)
|
||||
@ -2056,7 +2062,7 @@ Have fun!
|
||||
"File Rename", "If you rename files now, unsaved data in the form will be lost. Are you sure?"
|
||||
):
|
||||
|
||||
dlg = RenameWindow(self, ca_list, self.load_data_style, self.config, self.talker_api)
|
||||
dlg = RenameWindow(self, ca_list, self.load_data_style, self.config, self.current_talker())
|
||||
dlg.setModal(True)
|
||||
if dlg.exec() and self.comic_archive is not None:
|
||||
self.fileSelectionList.update_selected_rows()
|
||||
|
@ -1 +1,31 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import pathlib
|
||||
|
||||
import comictalker.talkers.comicvine
|
||||
from comictalker.comictalker import ComicTalker, TalkerError
|
||||
from comictalker.resulttypes import ComicIssue, ComicSeries
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
__all__ = [
|
||||
"ComicTalker",
|
||||
"TalkerError",
|
||||
"ComicIssue",
|
||||
"ComicSeries",
|
||||
]
|
||||
|
||||
|
||||
def get_talkers(version: str, cache: pathlib.Path) -> dict[str, ComicTalker]:
|
||||
"""Returns all comic talker instances"""
|
||||
talkers: dict[str, ComicTalker] = {}
|
||||
|
||||
for talker in [comictalker.talkers.comicvine.ComicVineTalker]:
|
||||
try:
|
||||
obj = talker(version, cache)
|
||||
talkers[obj.id] = obj
|
||||
except Exception:
|
||||
logger.exception("Failed to load talker: %s", "comicvine")
|
||||
raise TalkerError(source="comicvine", code=4, desc="Failed to initialise talker")
|
||||
return talkers
|
||||
|
@ -25,38 +25,6 @@ from comictalker.resulttypes import ComicIssue, ComicSeries
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SourceDetails:
|
||||
def __init__(
|
||||
self,
|
||||
name: str = "",
|
||||
ident: str = "",
|
||||
logo: str = "",
|
||||
):
|
||||
self.name = name
|
||||
self.id = ident
|
||||
self.logo = logo
|
||||
|
||||
|
||||
class SourceStaticSettings:
|
||||
def __init__(
|
||||
self,
|
||||
website: str = "",
|
||||
attribution_string: str = "", # Full string including web link, example: Metadata provided by <a href='http://website'>Example</a>
|
||||
has_issues: bool = False,
|
||||
has_alt_covers: bool = False,
|
||||
requires_apikey: bool = False,
|
||||
has_nsfw: bool = False,
|
||||
has_censored_covers: bool = False,
|
||||
) -> None:
|
||||
self.website = website
|
||||
self.attribution_string = attribution_string
|
||||
self.has_issues = has_issues
|
||||
self.has_alt_covers = has_alt_covers
|
||||
self.requires_apikey = requires_apikey
|
||||
self.has_nsfw = has_nsfw
|
||||
self.has_censored_covers = has_censored_covers
|
||||
|
||||
|
||||
class TalkerError(Exception):
|
||||
"""Base class exception for information sources.
|
||||
|
||||
@ -71,10 +39,8 @@ class TalkerError(Exception):
|
||||
|
||||
codes = {1: "General", 2: "Network", 3: "Data", 4: "Other"}
|
||||
|
||||
def __init__(self, source: str, desc: str, code: int = 4, sub_code: int = 0) -> None:
|
||||
def __init__(self, source: str, desc: str = "Unknown", code: int = 4, sub_code: int = 0) -> None:
|
||||
super().__init__()
|
||||
if desc == "":
|
||||
desc = "Unknown"
|
||||
self.desc = desc
|
||||
self.code = code
|
||||
self.code_name = self.codes[code]
|
||||
@ -136,14 +102,16 @@ class TalkerDataError(TalkerError):
|
||||
super().__init__(source, desc, 3, sub_code)
|
||||
|
||||
|
||||
# Class talkers instance
|
||||
class ComicTalker:
|
||||
"""The base class for all comic source talkers"""
|
||||
|
||||
name: str = "Example"
|
||||
id: str = "example"
|
||||
logo_url: str = "https://example.com/logo.png"
|
||||
website: str = "https://example.com/"
|
||||
attribution: str = f"Metadata provided by <a href='{website}'>{name}</a>"
|
||||
|
||||
def __init__(self, version: str, cache_folder: pathlib.Path) -> None:
|
||||
# Identity name for the information source etc.
|
||||
self.source_details = SourceDetails()
|
||||
self.static_config = SourceStaticSettings()
|
||||
self.cache_folder = cache_folder
|
||||
self.version = version
|
||||
self.api_key: str = ""
|
||||
@ -153,10 +121,12 @@ class ComicTalker:
|
||||
"""Allows registering settings using the settngs package with an argparse like interface"""
|
||||
return None
|
||||
|
||||
def parse_settings(self, settings: dict[str, Any]) -> None:
|
||||
"""settings is a dictionary of options defined in register_settings.
|
||||
It is only guaranteed that the settings defined in register_settings will be present."""
|
||||
return None
|
||||
def parse_settings(self, settings: dict[str, Any]) -> dict[str, Any]:
|
||||
"""
|
||||
settings is a dictionary of settings defined in register_settings.
|
||||
It is only guaranteed that the settings defined in register_settings will be present.
|
||||
"""
|
||||
return settings
|
||||
|
||||
def check_api_key(self, key: str, url: str) -> bool:
|
||||
"""
|
@ -1,39 +0,0 @@
|
||||
"""Handles collecting data from source talkers."""
|
||||
|
||||
# Copyright 2012-2014 Anthony Beville
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import pathlib
|
||||
|
||||
import comictalker.talkers.comicvine
|
||||
from comictalker.talkerbase import ComicTalker, TalkerError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_talkers(version: str, cache: pathlib.Path) -> dict[str, ComicTalker]:
|
||||
"""Returns all comic talker instances"""
|
||||
# TODO separate PR will bring talkers in via entry points. TalkerError etc. source will then be a var
|
||||
talkers: dict[str, ComicTalker] = {}
|
||||
|
||||
for talker in [comictalker.talkers.comicvine.ComicVineTalker]:
|
||||
try:
|
||||
obj = talker(version, cache)
|
||||
talkers[obj.source_details.id] = obj
|
||||
except Exception:
|
||||
logger.exception("Failed to load talker: %s", "comicvine")
|
||||
raise TalkerError(source="comicvine", code=4, desc="Failed to initialise talker")
|
||||
return talkers
|
@ -1,5 +1,3 @@
|
||||
"""Generic sources utils to format API data and the like.
|
||||
"""
|
||||
# Copyright 2012-2014 Anthony Beville
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,7 +21,7 @@ from bs4 import BeautifulSoup
|
||||
from comicapi import utils
|
||||
from comicapi.genericmetadata import GenericMetadata
|
||||
from comicapi.issuestring import IssueString
|
||||
from comictalker.talkerbase import ComicIssue
|
||||
from comictalker.resulttypes import ComicIssue
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -33,8 +33,8 @@ from comicapi import utils
|
||||
from comicapi.genericmetadata import GenericMetadata
|
||||
from comicapi.issuestring import IssueString
|
||||
from comictalker.comiccacher import ComicCacher
|
||||
from comictalker.comictalker import ComicTalker, TalkerDataError, TalkerNetworkError
|
||||
from comictalker.resulttypes import ComicIssue, ComicSeries, Credit
|
||||
from comictalker.talkerbase import ComicTalker, SourceDetails, SourceStaticSettings, TalkerDataError, TalkerNetworkError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -150,40 +150,28 @@ class CVResult(TypedDict, Generic[T]):
|
||||
version: str
|
||||
|
||||
|
||||
CV_RATE_LIMIT_STATUS = 107
|
||||
CV_STATUS_RATELIMIT = 107
|
||||
|
||||
|
||||
class ComicVineTalker(ComicTalker):
|
||||
name: str = "Comic Vine"
|
||||
id: str = "comicvine"
|
||||
logo_url: str = "https://comicvine.gamespot.com/a/bundles/comicvinesite/images/logo.png"
|
||||
website: str = "https://comicvine.gamespot.com/"
|
||||
attribution: str = f"Metadata provided by <a href='{website}'>{name}</a>"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
version: str,
|
||||
cache_folder: pathlib.Path,
|
||||
):
|
||||
super().__init__(version, cache_folder)
|
||||
self.source_details = SourceDetails(
|
||||
name="Comic Vine",
|
||||
ident="comicvine",
|
||||
logo="https://comicvine.gamespot.com/a/bundles/comicvinesite/images/logo.png",
|
||||
)
|
||||
self.static_config = SourceStaticSettings(
|
||||
website="https://comicvine.gamespot.com/",
|
||||
attribution_string="Metadata provided by <a href='https://comicvine.gamespot.com/'>Comic Vine</a>",
|
||||
has_issues=True,
|
||||
has_alt_covers=True,
|
||||
requires_apikey=True,
|
||||
has_nsfw=False,
|
||||
has_censored_covers=False,
|
||||
)
|
||||
# Default settings
|
||||
self.api_url: str = "https://comicvine.gamespot.com/api"
|
||||
self.api_key: str = "27431e6787042105bd3e47e169a624521f89f3a4"
|
||||
self.remove_html_tables: bool = False
|
||||
self.use_series_start_as_volume: bool = False
|
||||
self.wait_for_rate_limit: bool = False
|
||||
|
||||
# Identity name for the information source
|
||||
self.source_name: str = self.source_details.id
|
||||
self.source_name_friendly: str = self.source_details.name
|
||||
self.wait_on_ratelimit: bool = False
|
||||
|
||||
tmp_url = urlsplit(self.api_url)
|
||||
|
||||
@ -194,7 +182,7 @@ class ComicVineTalker(ComicTalker):
|
||||
self.api_url = tmp_url.geturl()
|
||||
|
||||
# NOTE: This was hardcoded before which is why it isn't in settings
|
||||
self.wait_for_rate_limit_time: int = 20
|
||||
self.wait_on_ratelimit_time: int = 20
|
||||
|
||||
def register_settings(self, parser: settngs.Manager) -> None:
|
||||
parser.add_setting("--cv-use-series-start-as-volume", default=False, action=argparse.BooleanOptionalAction)
|
||||
@ -214,9 +202,7 @@ class ComicVineTalker(ComicTalker):
|
||||
help="Use the given Comic Vine URL.",
|
||||
)
|
||||
|
||||
def parse_settings(self, settings: dict[str, Any]) -> None:
|
||||
self.remove_html_tables = settings["cv_remove_html_tables"]
|
||||
self.use_series_start_as_volume = settings["cv_use_series_start_as_volume"]
|
||||
def parse_settings(self, settings: dict[str, Any]) -> dict[str, Any]:
|
||||
if settings["cv_api_key"]:
|
||||
self.api_key = settings["cv_api_key"]
|
||||
if settings["cv_url"]:
|
||||
@ -227,6 +213,11 @@ class ComicVineTalker(ComicTalker):
|
||||
|
||||
self.api_url = tmp_url.geturl()
|
||||
|
||||
self.use_series_start_as_volume = settings["cv_use_series_start_as_volume"]
|
||||
self.wait_on_ratelimit = settings["cv_wait_on_ratelimit"]
|
||||
self.remove_html_tables = settings["cv_remove_html_tables"]
|
||||
return settngs
|
||||
|
||||
def check_api_key(self, key: str, url: str) -> bool:
|
||||
if not url:
|
||||
url = self.api_url
|
||||
@ -259,7 +250,7 @@ class ComicVineTalker(ComicTalker):
|
||||
wait_times = [1, 2, 3, 4]
|
||||
while True:
|
||||
cv_response: CVResult = self.get_url_content(url, params)
|
||||
if self.wait_for_rate_limit and cv_response["status_code"] == CV_RATE_LIMIT_STATUS:
|
||||
if self.wait_on_ratelimit and cv_response["status_code"] == CV_STATUS_RATELIMIT:
|
||||
logger.info(f"Rate limit encountered. Waiting for {limit_wait_time} minutes\n")
|
||||
time.sleep(limit_wait_time * 60)
|
||||
total_time_waited += limit_wait_time
|
||||
@ -267,15 +258,13 @@ class ComicVineTalker(ComicTalker):
|
||||
if counter < 3:
|
||||
counter += 1
|
||||
# don't wait much more than 20 minutes
|
||||
if total_time_waited < self.wait_for_rate_limit_time:
|
||||
if total_time_waited < self.wait_on_ratelimit_time:
|
||||
continue
|
||||
if cv_response["status_code"] != 1:
|
||||
logger.debug(
|
||||
f"{self.source_name_friendly} query failed with error #{cv_response['status_code']}: [{cv_response['error']}]."
|
||||
)
|
||||
raise TalkerNetworkError(
|
||||
self.source_name_friendly, 0, f"{cv_response['status_code']}: {cv_response['error']}"
|
||||
f"{self.name} query failed with error #{cv_response['status_code']}: [{cv_response['error']}]."
|
||||
)
|
||||
raise TalkerNetworkError(self.name, 0, f"{cv_response['status_code']}: {cv_response['error']}")
|
||||
|
||||
# it's all good
|
||||
break
|
||||
@ -298,16 +287,16 @@ class ComicVineTalker(ComicTalker):
|
||||
break
|
||||
|
||||
except requests.exceptions.Timeout:
|
||||
logger.debug(f"Connection to {self.source_name_friendly} timed out.")
|
||||
raise TalkerNetworkError(self.source_name_friendly, 4)
|
||||
logger.debug(f"Connection to {self.name} timed out.")
|
||||
raise TalkerNetworkError(self.name, 4)
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.debug(f"Request exception: {e}")
|
||||
raise TalkerNetworkError(self.source_name_friendly, 0, str(e)) from e
|
||||
raise TalkerNetworkError(self.name, 0, str(e)) from e
|
||||
except json.JSONDecodeError as e:
|
||||
logger.debug(f"JSON decode error: {e}")
|
||||
raise TalkerDataError(self.source_name_friendly, 2, "ComicVine did not provide json")
|
||||
raise TalkerDataError(self.name, 2, "ComicVine did not provide json")
|
||||
|
||||
raise TalkerNetworkError(self.source_name_friendly, 5)
|
||||
raise TalkerNetworkError(self.name, 5)
|
||||
|
||||
def format_search_results(self, search_results: list[CVSeries]) -> list[ComicSeries]:
|
||||
formatted_results = []
|
||||
@ -415,13 +404,13 @@ class ComicVineTalker(ComicTalker):
|
||||
) -> list[ComicSeries]:
|
||||
# Sanitize the series name for comicvine searching, comicvine search ignore symbols
|
||||
search_series_name = utils.sanitize_title(series_name, literal)
|
||||
logger.info(f"{self.source_name_friendly} searching: {search_series_name}")
|
||||
logger.info(f"{self.name} searching: {search_series_name}")
|
||||
|
||||
# Before we search online, look in our cache, since we might have done this same search recently
|
||||
# For literal searches always retrieve from online
|
||||
cvc = ComicCacher(self.cache_folder, self.version)
|
||||
if not refresh_cache and not literal:
|
||||
cached_search_results = cvc.get_search_results(self.source_name, series_name)
|
||||
cached_search_results = cvc.get_search_results(self.id, series_name)
|
||||
|
||||
if len(cached_search_results) > 0:
|
||||
return cached_search_results
|
||||
@ -495,7 +484,7 @@ class ComicVineTalker(ComicTalker):
|
||||
|
||||
# Cache these search results, even if it's literal we cache the results
|
||||
# The most it will cause is extra processing time
|
||||
cvc.add_search_results(self.source_name, series_name, formatted_search_results)
|
||||
cvc.add_search_results(self.id, series_name, formatted_search_results)
|
||||
|
||||
return formatted_search_results
|
||||
|
||||
@ -514,7 +503,7 @@ class ComicVineTalker(ComicTalker):
|
||||
def fetch_series_data(self, series_id: int) -> ComicSeries:
|
||||
# before we search online, look in our cache, since we might already have this info
|
||||
cvc = ComicCacher(self.cache_folder, self.version)
|
||||
cached_series_result = cvc.get_series_info(str(series_id), self.source_name)
|
||||
cached_series_result = cvc.get_series_info(str(series_id), self.id)
|
||||
|
||||
if cached_series_result is not None:
|
||||
return cached_series_result
|
||||
@ -531,14 +520,14 @@ class ComicVineTalker(ComicTalker):
|
||||
formatted_series_results = self.format_search_results([series_results])
|
||||
|
||||
if series_results:
|
||||
cvc.add_series_info(self.source_name, formatted_series_results[0])
|
||||
cvc.add_series_info(self.id, formatted_series_results[0])
|
||||
|
||||
return formatted_series_results[0]
|
||||
|
||||
def fetch_issues_by_series(self, series_id: str) -> list[ComicIssue]:
|
||||
# before we search online, look in our cache, since we might already have this info
|
||||
cvc = ComicCacher(self.cache_folder, self.version)
|
||||
cached_series_issues_result = cvc.get_series_issues_info(series_id, self.source_name)
|
||||
cached_series_issues_result = cvc.get_series_issues_info(series_id, self.id)
|
||||
|
||||
series_data = self.fetch_series_data(int(series_id))
|
||||
|
||||
@ -575,7 +564,7 @@ class ComicVineTalker(ComicTalker):
|
||||
# Format to expected output
|
||||
formatted_series_issues_result = self.format_issue_results(series_issues_result)
|
||||
|
||||
cvc.add_series_issues_info(self.source_name, formatted_series_issues_result)
|
||||
cvc.add_series_issues_info(self.id, formatted_series_issues_result)
|
||||
|
||||
return formatted_series_issues_result
|
||||
|
||||
@ -640,7 +629,7 @@ class ComicVineTalker(ComicTalker):
|
||||
if f_record and f_record.complete:
|
||||
# Cache had full record
|
||||
return talker_utils.map_comic_issue_to_metadata(
|
||||
f_record, self.source_name_friendly, self.remove_html_tables, self.use_series_start_as_volume
|
||||
f_record, self.name, self.remove_html_tables, self.use_series_start_as_volume
|
||||
)
|
||||
|
||||
if f_record is not None:
|
||||
@ -650,12 +639,12 @@ class ComicVineTalker(ComicTalker):
|
||||
def fetch_issue_data_by_issue_id(self, issue_id: str) -> GenericMetadata:
|
||||
# before we search online, look in our cache, since we might already have this info
|
||||
cvc = ComicCacher(self.cache_folder, self.version)
|
||||
cached_issues_result = cvc.get_issue_info(int(issue_id), self.source_name)
|
||||
cached_issues_result = cvc.get_issue_info(int(issue_id), self.id)
|
||||
|
||||
if cached_issues_result and cached_issues_result.complete:
|
||||
return talker_utils.map_comic_issue_to_metadata(
|
||||
cached_issues_result,
|
||||
self.source_name_friendly,
|
||||
self.name,
|
||||
self.remove_html_tables,
|
||||
self.use_series_start_as_volume,
|
||||
)
|
||||
@ -672,12 +661,12 @@ class ComicVineTalker(ComicTalker):
|
||||
# Due to issue not returning publisher, fetch the series.
|
||||
cv_issues[0].series = self.fetch_series_data(int(cv_issues[0].series.id))
|
||||
|
||||
cvc.add_series_issues_info(self.source_name, cv_issues)
|
||||
cvc.add_series_issues_info(self.id, cv_issues)
|
||||
|
||||
# Now, map the ComicIssue data to generic metadata
|
||||
return talker_utils.map_comic_issue_to_metadata(
|
||||
cv_issues[0],
|
||||
self.source_name_friendly,
|
||||
self.name,
|
||||
self.remove_html_tables,
|
||||
self.use_series_start_as_volume,
|
||||
)
|
||||
|
@ -5,7 +5,7 @@ natsort>=8.1.0
|
||||
pathvalidate
|
||||
pillow>=9.1.0, <10
|
||||
pycountry
|
||||
pyicu; sys_platform == 'linux' or sys_platform == 'darwin'
|
||||
#pyicu; sys_platform == 'linux' or sys_platform == 'darwin'
|
||||
rapidfuzz>=2.12.0
|
||||
requests==2.*
|
||||
settngs==0.5.0
|
||||
|
@ -11,7 +11,7 @@ import testing.comicvine
|
||||
def test_search_for_series(comicvine_api, comic_cache):
|
||||
results = comicvine_api.search_for_series("cory doctorows futuristic tales of the here and now")
|
||||
cache_issues = comic_cache.get_search_results(
|
||||
comicvine_api.source_name, "cory doctorows futuristic tales of the here and now"
|
||||
comicvine_api.id, "cory doctorows futuristic tales of the here and now"
|
||||
)
|
||||
assert results == cache_issues
|
||||
|
||||
@ -20,7 +20,7 @@ def test_fetch_series_data(comicvine_api, comic_cache):
|
||||
result = comicvine_api.fetch_series_data(23437)
|
||||
# del result["description"]
|
||||
# del result["image_url"]
|
||||
cache_result = comic_cache.get_series_info(23437, comicvine_api.source_name)
|
||||
cache_result = comic_cache.get_series_info(23437, comicvine_api.id)
|
||||
# del cache_result["description"]
|
||||
# del cache_result["image_url"]
|
||||
assert result == cache_result
|
||||
@ -28,7 +28,7 @@ def test_fetch_series_data(comicvine_api, comic_cache):
|
||||
|
||||
def test_fetch_issues_by_series(comicvine_api, comic_cache):
|
||||
results = comicvine_api.fetch_issues_by_series(23437)
|
||||
cache_issues = comic_cache.get_series_issues_info(23437, comicvine_api.source_name)
|
||||
cache_issues = comic_cache.get_series_issues_info(23437, comicvine_api.id)
|
||||
assert dataclasses.asdict(results[0])["series"] == dataclasses.asdict(cache_issues[0])["series"]
|
||||
|
||||
|
||||
|
@ -15,8 +15,8 @@ from PIL import Image
|
||||
import comicapi.comicarchive
|
||||
import comicapi.genericmetadata
|
||||
import comictaggerlib.ctsettings
|
||||
import comictalker
|
||||
import comictalker.comiccacher
|
||||
import comictalker.comictalkerapi
|
||||
import comictalker.talkers.comicvine
|
||||
from comicapi import utils
|
||||
from testing import comicvine, filenames
|
||||
|
Loading…
Reference in New Issue
Block a user