1
0
Fork 0
mirror of https://github.com/ldericher/fftcgtool synced 2025-01-15 15:02:59 +00:00

fallback for nonexistent images, verbosity, logging output

This commit is contained in:
Jörn-Michael Miehe 2021-08-24 17:29:12 +02:00
parent ba58a99690
commit 0f6c7be504
5 changed files with 60 additions and 21 deletions

View file

@ -19,11 +19,11 @@ class Book:
# all card face URLs # all card face URLs
urls = [ urls = [
f"https://fftcg.cdn.sewest.net/images/cards/full/{card.code}_{language.image_suffix}.jpg" ("https://fftcg.cdn.sewest.net/images/cards/full/{}_{}.jpg", str(card.code), language.image_suffix)
for card in cards for card in cards
] ]
# card back URL # card back URL
urls.append(CARD_BACK_URL) urls.append((CARD_BACK_URL, "", ""))
# multi-threaded download # multi-threaded download
images = ImageLoader.load(urls, num_threads) images = ImageLoader.load(urls, num_threads)

View file

@ -1,33 +1,46 @@
import io
import logging import logging
import multiprocessing import multiprocessing
import requests import requests
from PIL import Image from PIL import Image
from .language import Language
from .utils import RESOLUTION from .utils import RESOLUTION
# constants
FALLBACK_LANGUAGE = Language("en")
class ImageLoader: class ImageLoader:
@classmethod @classmethod
def _load(cls, url: str) -> Image.Image: def _load_inner(cls, url_parts: tuple[str, str, str]) -> Image.Image:
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
base_url, code, lang_suffix = url_parts
# put together image url
url = base_url.format(code, lang_suffix)
logger.info(f"trying image {url}")
# fetch image (retry on fail) # fetch image (retry on fail)
while True: while True:
logger.info(f"downloading image {url}")
try: try:
res = requests.get(url) res = requests.get(url, stream=True)
image = Image.open(io.BytesIO(res.content)) break
# unify images except requests.RequestException:
image.convert(mode="RGB")
return image.resize(RESOLUTION, Image.BICUBIC)
except requests.exceptions.RequestException:
pass pass
# if rejected, substitute the english version
if not res.status_code == 200:
logger.warning(f"falling back to english version of {url}")
return cls._load_inner((base_url, code, FALLBACK_LANGUAGE.image_suffix))
# unify images
image = Image.open(res.raw)
image.convert(mode="RGB")
return image.resize(RESOLUTION, Image.BICUBIC)
@classmethod @classmethod
def load(cls, urls: list[str], num_threads: int) -> list[Image.Image]: def load(cls, urls_parts: list[tuple[str, str, str]], num_threads: int) -> list[Image.Image]:
with multiprocessing.Pool(num_threads) as p: with multiprocessing.Pool(num_threads) as p:
return p.map(ImageLoader._load, urls) return p.map(cls._load_inner, urls_parts)

View file

@ -1,3 +1,6 @@
from __future__ import annotations
class Language: class Language:
def __init__(self, language: str): def __init__(self, language: str):
language = language.lower() language = language.lower()
@ -15,6 +18,12 @@ class Language:
def __str__(self): def __str__(self):
return self.__short return self.__short
def __hash__(self) -> hash:
return hash(str(self))
def __eq__(self, other: Language):
return str(self) == str(other)
@property @property
def image_suffix(self): def image_suffix(self):
# supported languages for face URLs # supported languages for face URLs
@ -32,4 +41,3 @@ class Language:
return "" return ""
else: else:
return "_EN" return "_EN"

View file

@ -10,7 +10,7 @@ from .ttsdeck import TTSDeck
class Opus(Cards): class Opus(Cards):
__SQUARE_API_URL = "https://fftcg.square-enix-games.com/de/get-cards" __SQUARE_API_URL = "https://fftcg.square-enix-games.com/en/get-cards"
def __init__(self, opus_id: str, language: Language): def __init__(self, opus_id: str, language: Language):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -64,7 +64,7 @@ class Opus(Cards):
self.sort(key=lambda x: x.code.opus) self.sort(key=lambda x: x.code.opus)
for card in self: for card in self:
logger.info(f"imported card {card}") logger.debug(f"imported card {card}")
@property @property
def number(self) -> str: def number(self) -> str:

26
main.py
View file

@ -47,6 +47,12 @@ def main() -> None:
description="Imports FFTCG cards for TT-Sim.", description="Imports FFTCG cards for TT-Sim.",
) )
parser.add_argument(
"-v", "--verbose",
help="increase output verbosity",
action="count",
)
parser.add_argument( parser.add_argument(
"-l", "--language", "-l", "--language",
type=fftcg.Language, type=fftcg.Language,
@ -105,12 +111,25 @@ def main() -> None:
help="the Deck to import", help="the Deck to import",
) )
# parse arguments
args = parser.parse_args()
# set up logging # set up logging
if args.verbose is None:
args.verbose = logging.WARN
elif args.verbose == 1:
args.verbose = logging.INFO
else:
args.verbose = logging.DEBUG
logging.basicConfig( logging.basicConfig(
level=logging.INFO, level=args.verbose,
format="%(levelname)s: %(processName)s %(message)s", format="%(levelname)s: %(processName)s %(message)s",
) )
logger = logging.getLogger(__name__)
logger.debug(f"{args = }")
# output directory # output directory
if not os.path.exists(OUT_DIR_NAME): if not os.path.exists(OUT_DIR_NAME):
os.mkdir(OUT_DIR_NAME) os.mkdir(OUT_DIR_NAME)
@ -118,13 +137,12 @@ def main() -> None:
os.chdir(OUT_DIR_NAME) os.chdir(OUT_DIR_NAME)
# call function based on args # call function based on args
args = parser.parse_args()
for deck in args.func(args): for deck in args.func(args):
deck.save() deck.save()
# bye # bye
logging.info("Done. Put the generated JSON files in your 'Saved Objects' Folder.") print("Done. Put the generated JSON files in your 'Saved Objects' Folder.")
logging.info("Thanks for using fftcgtool!") print("Thanks for using fftcgtool!")
if __name__ == "__main__": if __name__ == "__main__":