2021-08-17 15:37:28 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2021-09-06 02:40:28 +00:00
|
|
|
import io
|
2021-09-03 05:11:46 +00:00
|
|
|
import json
|
2021-08-23 11:38:01 +00:00
|
|
|
import pickle
|
2021-09-03 05:11:46 +00:00
|
|
|
import zipfile
|
2021-09-06 02:40:28 +00:00
|
|
|
from os import PathLike
|
|
|
|
from typing import IO
|
|
|
|
|
|
|
|
import requests
|
2021-08-16 12:45:15 +00:00
|
|
|
|
2021-08-23 14:55:41 +00:00
|
|
|
from .card import Card
|
|
|
|
from .cards import Cards
|
|
|
|
from .code import Code
|
2021-09-02 01:06:12 +00:00
|
|
|
from .language import API_LANGS
|
2021-08-17 15:37:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
class CardDB:
|
2021-09-06 02:40:28 +00:00
|
|
|
_instance: CardDB = None
|
|
|
|
_cards: dict[Code, Card]
|
|
|
|
_face_to_url: dict[str, str]
|
|
|
|
|
|
|
|
_DB_FILE_NAME = "cards.pickle"
|
|
|
|
_MAPPING_FILE_NAME = "face_to_url.json"
|
|
|
|
|
|
|
|
def __new__(cls, *more) -> CardDB:
|
|
|
|
if CardDB._instance is None:
|
|
|
|
CardDB._instance = object.__new__(CardDB)
|
|
|
|
|
|
|
|
return CardDB._instance
|
2021-08-16 12:45:15 +00:00
|
|
|
|
2021-09-06 02:40:28 +00:00
|
|
|
def __init__(self, db_url: str = None):
|
|
|
|
if db_url is not None:
|
|
|
|
res = requests.get(db_url, stream=True)
|
|
|
|
if not res.ok:
|
|
|
|
raise ValueError("Invalid URL given to CardDB!")
|
|
|
|
|
|
|
|
self._load(io.BytesIO(res.content))
|
|
|
|
|
|
|
|
def _load(self, db: PathLike[str] | IO[bytes]):
|
|
|
|
try:
|
|
|
|
# unpickle db file
|
|
|
|
with zipfile.ZipFile(db, "r") as zip_file:
|
|
|
|
# cards db
|
|
|
|
with zip_file.open(CardDB._DB_FILE_NAME, "r") as file:
|
|
|
|
self._cards = pickle.load(file)
|
2021-09-03 05:11:46 +00:00
|
|
|
|
2021-09-06 02:40:28 +00:00
|
|
|
# face_to_url mapping
|
|
|
|
with zip_file.open(CardDB._MAPPING_FILE_NAME, "r") as file:
|
|
|
|
self._face_to_url = json.load(file)
|
2021-08-16 12:45:15 +00:00
|
|
|
|
2021-09-06 02:40:28 +00:00
|
|
|
except FileNotFoundError:
|
|
|
|
self._cards = {}
|
|
|
|
self._face_to_url = {}
|
2021-08-16 12:45:15 +00:00
|
|
|
|
2021-09-02 00:54:16 +00:00
|
|
|
def __contains__(self, item: Code) -> bool:
|
2021-09-06 02:40:28 +00:00
|
|
|
return item in self._cards
|
2021-09-02 00:54:16 +00:00
|
|
|
|
2021-08-18 14:52:32 +00:00
|
|
|
def __getitem__(self, code: Code) -> Card:
|
2021-09-06 02:40:28 +00:00
|
|
|
return self._cards[code]
|
2021-09-02 01:06:12 +00:00
|
|
|
|
2021-09-02 01:11:31 +00:00
|
|
|
def get_face_url(self, face: str) -> str:
|
2021-09-06 02:40:28 +00:00
|
|
|
if face in self._face_to_url:
|
|
|
|
return self._face_to_url[face]
|
2021-09-02 01:11:31 +00:00
|
|
|
else:
|
|
|
|
return face
|
|
|
|
|
2021-09-06 02:40:28 +00:00
|
|
|
def save(self) -> None:
|
|
|
|
return
|
2021-09-03 05:11:46 +00:00
|
|
|
|
2021-09-06 02:40:28 +00:00
|
|
|
def update(self, cards: Cards) -> None:
|
|
|
|
return
|
2021-09-03 05:11:46 +00:00
|
|
|
|
2021-09-06 02:40:28 +00:00
|
|
|
def upload_prompt(self) -> None:
|
|
|
|
return
|
2021-09-03 05:11:46 +00:00
|
|
|
|
|
|
|
|
2021-09-06 02:40:28 +00:00
|
|
|
class RWCardDB(CardDB):
|
|
|
|
__db_path: PathLike[str]
|
|
|
|
|
|
|
|
def __new__(cls, *more) -> RWCardDB:
|
|
|
|
if CardDB._instance is None:
|
|
|
|
CardDB._instance = object.__new__(RWCardDB)
|
|
|
|
|
|
|
|
return CardDB._instance
|
|
|
|
|
|
|
|
def __init__(self, db_path: PathLike[str] = None):
|
|
|
|
super().__init__(None)
|
2021-09-03 05:11:46 +00:00
|
|
|
|
2021-09-06 02:40:28 +00:00
|
|
|
if db_path is not None:
|
|
|
|
self.__db_path = db_path
|
|
|
|
self._load(self.__db_path)
|
|
|
|
|
|
|
|
def save(self) -> None:
|
|
|
|
with zipfile.ZipFile(self.__db_path, "w", compression=zipfile.ZIP_LZMA) as zip_file:
|
|
|
|
# cards db
|
|
|
|
with zip_file.open(CardDB._DB_FILE_NAME, "w") as file:
|
|
|
|
pickle.dump(self._cards, file)
|
|
|
|
|
|
|
|
# face_to_url mapping
|
|
|
|
with zip_file.open(CardDB._MAPPING_FILE_NAME, "w") as file:
|
|
|
|
file.write(json.dumps(self._face_to_url, indent=2).encode("utf-8"))
|
2021-09-03 05:11:46 +00:00
|
|
|
|
|
|
|
def update(self, cards: Cards) -> None:
|
|
|
|
for card in cards:
|
2021-09-06 02:40:28 +00:00
|
|
|
self._cards[card.code] = card
|
2021-09-03 05:11:46 +00:00
|
|
|
|
2021-09-02 01:06:12 +00:00
|
|
|
def upload_prompt(self) -> None:
|
|
|
|
faces = list(set([
|
|
|
|
card[lang].face
|
2021-09-06 02:40:28 +00:00
|
|
|
for card in self._cards.values()
|
2021-09-02 01:06:12 +00:00
|
|
|
for lang in API_LANGS
|
|
|
|
if card[lang].face
|
|
|
|
]))
|
|
|
|
faces.sort()
|
|
|
|
|
|
|
|
for face in faces:
|
2021-09-06 02:40:28 +00:00
|
|
|
if face not in self._face_to_url:
|
2021-09-02 01:06:12 +00:00
|
|
|
face_url = input(f"Upload '{face}' and paste URL: ")
|
|
|
|
if face_url:
|
2021-09-06 02:40:28 +00:00
|
|
|
self._face_to_url[face] = face_url
|