diff --git a/.gitignore b/.gitignore
index 5dab794..006f9b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ workpath_pyinstaller/
hd_cards_downloader_tracker
hd_fields_downloader_tracker
+HdDownloader.LICENSE.txt
diff --git a/HdDownloader.LICENSE.txt b/HdDownloader.LICENSE.txt
deleted file mode 100644
index 4d7e4e9..0000000
--- a/HdDownloader.LICENSE.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright © 2021 Douglas Sebastian
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the “Software”), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/Makefile b/Makefile
index d748017..1ac5df3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,14 +1,19 @@
-FILENAME = EDOPro-HD-Downloader
-LICENSE = HdDownloader.LICENSE.txt
-DISTPATH = bin
-WORKPATH = workpath_pyinstaller
-ZIP_WIN = windows.zip
+FILENAME = EDOPro-HD-Downloader
+LICENSE = LICENSE
+LICENSE_BIN = HdDownloader.LICENSE.txt
+DISTPATH = bin
+WORKPATH = workpath_pyinstaller
+ZIP_WIN = windows.zip
build:
pyinstaller main.py -y --distpath "$(DISTPATH)" -F --specpath "$(DISTPATH)" -n "$(FILENAME)" -c --clean --workpath "$(WORKPATH)"
- cp "$(LICENSE)" "$(DISTPATH)/$(LICENSE)"
+ cp "$(LICENSE)" "$(DISTPATH)/$(LICENSE_BIN)"
rm -rf "$(WORKPATH)"
7z-win: build
- cd "$(DISTPATH)" && 7z a "$(ZIP_WIN)" "$(FILENAME).exe" "$(LICENSE)"
+ cd "$(DISTPATH)" && 7z a "$(ZIP_WIN)" "$(FILENAME).exe" "$(LICENSE_BIN)"
+
+clean:
+ rm -rf "hd_cards_downloader_tracker"
+ rm -rf "hd_fields_downloader_tracker"
diff --git a/apiaccess.py b/apiaccess.py
deleted file mode 100644
index e25c23a..0000000
--- a/apiaccess.py
+++ /dev/null
@@ -1,52 +0,0 @@
-from http.client import HTTPResponse as __HTTPResponse
-from urllib import request as __request
-from json import loads as __loads
-
-API_URL = "https://db.ygoprodeck.com/api/v7/cardinfo.php"
-"""Base API URL for YGOProDeck"""
-
-API_HEADER = {
- "User-Agent": "NiiMiyo-EDOPro-HD-Downloader/2.0.1"
-}
-"""Header JSON to be used in an API request"""
-
-def __get_ids_from_api_response(response: __HTTPResponse) -> list[int]:
- """Returns only the ids of the cards requested"""
-
- data = __loads(response.read()).get("data")
- ids: list[int] = list()
-
- for card in data:
- for image in card.get("card_images"):
- ids.append(image.get("id"))
-
- return ids
-
-
-def get_all_cards() -> list[int]:
- """Returns the ids of all Yu-Gi-Oh! cards in
- `db.ygoprodeck.com` database"""
-
- try:
- request = __request.Request(API_URL, headers=API_HEADER)
- response = __request.urlopen(request)
- except Exception as e:
- print(f"Error fetching db.ygoprodeck.com: {e}")
- return list()
- else:
- return __get_ids_from_api_response(response)
-
-
-def get_all_fields() -> list[int]:
- """Returns the ids of all Yu-Gi-Oh! Field Spell cards in
- `db.ygoprodeck.com` database"""
-
- try:
- params = r"?type=spell%20card&race=field"
- request = __request.Request(API_URL + params, headers=API_HEADER)
- response = __request.urlopen(request)
- except Exception as e:
- print(e)
- return list()
- else:
- return __get_ids_from_api_response(response)
diff --git a/commands/cmd_all.py b/commands/cmd_all.py
index 8a65144..d399c93 100644
--- a/commands/cmd_all.py
+++ b/commands/cmd_all.py
@@ -9,8 +9,8 @@ def __cmd_all(_: str) -> CommandReturn:
return allcards.action(_) + allfields.action(_) # type: ignore
-CommandHandler.add_command(DownloaderCommand(
+COMMAND_ALL = DownloaderCommand(
name="all",
help_text="downloads all cards images and all fields artworks",
action=__cmd_all
-))
+)
diff --git a/commands/cmd_allcards.py b/commands/cmd_allcards.py
index 1e64ddf..263818c 100644
--- a/commands/cmd_allcards.py
+++ b/commands/cmd_allcards.py
@@ -1,6 +1,5 @@
-from command_handler import CommandHandler
from commands.typing import CommandReturn, DownloadCard, DownloaderCommand
-from apiaccess import get_all_cards
+from web_access.ygoprodeck_api import get_all_cards
def __cmd_all_cards_action(_: str) -> CommandReturn:
@@ -10,8 +9,8 @@ def __cmd_all_cards_action(_: str) -> CommandReturn:
]
-CommandHandler.add_command(DownloaderCommand(
+COMMAND_ALLCARDS = DownloaderCommand(
name="allcards",
help_text="downloads all cards",
action=__cmd_all_cards_action
-))
+)
diff --git a/commands/cmd_allfields.py b/commands/cmd_allfields.py
index 2653faf..5510122 100644
--- a/commands/cmd_allfields.py
+++ b/commands/cmd_allfields.py
@@ -1,7 +1,5 @@
-from command_handler import CommandHandler
from commands.typing import DownloadCard, DownloaderCommand, CommandReturn
-from apiaccess import get_all_fields
-
+from web_access.ygoprodeck_api import get_all_fields
def __cmd_all_fields_action(_: str) -> CommandReturn:
return [
@@ -10,8 +8,8 @@ def __cmd_all_fields_action(_: str) -> CommandReturn:
]
-CommandHandler.add_command(DownloaderCommand(
+COMMAND_ALLFIELDS = DownloaderCommand(
name="allfields",
help_text="downloads all fields artworks",
action=__cmd_all_fields_action
-))
+)
\ No newline at end of file
diff --git a/commands/cmd_exit.py b/commands/cmd_exit.py
index c5ca167..7ddc041 100644
--- a/commands/cmd_exit.py
+++ b/commands/cmd_exit.py
@@ -1,4 +1,3 @@
-from command_handler import CommandHandler
from commands.typing import CommandReturn, DownloaderCommand
@@ -7,8 +6,8 @@ def __cmd_exit_action(_: str) -> CommandReturn:
exit(0)
-CommandHandler.add_command(DownloaderCommand(
+COMMAND_EXIT = DownloaderCommand(
name="exit",
help_text="closes the program",
action=__cmd_exit_action
-))
+)
diff --git a/commands/cmd_force.py b/commands/cmd_force.py
index d37a430..e932135 100644
--- a/commands/cmd_force.py
+++ b/commands/cmd_force.py
@@ -1,4 +1,3 @@
-from command_handler import CommandHandler
from commands.typing import CommandReturn, DownloadCard, DownloaderCommand
from commands.utils import get_args
from input_handler import handle_input
@@ -14,9 +13,9 @@ def __cmd_force_action(user_input: str) -> CommandReturn:
for c in cards
]
-CommandHandler.add_command(DownloaderCommand(
+COMMAND_FORCE = DownloaderCommand(
name="force",
shown_name="force ",
help_text="executes ignoring trackers (example: /force /allcards)",
action=__cmd_force_action
-))
+)
diff --git a/commands/cmd_help.py b/commands/cmd_help.py
index ee71291..7f28782 100644
--- a/commands/cmd_help.py
+++ b/commands/cmd_help.py
@@ -25,8 +25,8 @@ def __cmd_help_action(_: str) -> CommandReturn:
return []
-CommandHandler.add_command(DownloaderCommand(
+COMMAND_HELP = DownloaderCommand(
name="help",
help_text="see this text",
action=__cmd_help_action
-))
+)
diff --git a/commands/setup.py b/commands/setup.py
index 35a2b73..eb53d44 100644
--- a/commands/setup.py
+++ b/commands/setup.py
@@ -1,9 +1,16 @@
-# Yes, this is correct
-# I'm sorry
+from command_handler import CommandHandler
+from commands.cmd_allcards import COMMAND_ALLCARDS
+from commands.cmd_all import COMMAND_ALL
+from commands.cmd_allfields import COMMAND_ALLFIELDS
+from commands.cmd_exit import COMMAND_EXIT
+from commands.cmd_force import COMMAND_FORCE
+from commands.cmd_help import COMMAND_HELP
+
+
def setup_commands():
- import commands.cmd_allcards as _
- import commands.cmd_allfields as _
- import commands.cmd_exit as _
- import commands.cmd_force as _
- import commands.cmd_help as _
- import commands.cmd_all as _
+ CommandHandler.add_command(COMMAND_ALL)
+ CommandHandler.add_command(COMMAND_ALLCARDS)
+ CommandHandler.add_command(COMMAND_ALLFIELDS)
+ CommandHandler.add_command(COMMAND_EXIT)
+ CommandHandler.add_command(COMMAND_FORCE)
+ CommandHandler.add_command(COMMAND_HELP)
diff --git a/constants.py b/constants.py
new file mode 100644
index 0000000..ca1de0d
--- /dev/null
+++ b/constants.py
@@ -0,0 +1,28 @@
+DOWNLOADER_VERSION = "2.1"
+"""Program version"""
+
+REQUEST_HEADERS = {
+ "User-Agent": f"NiiMiyo-EDOPro-HD-Downloader/{DOWNLOADER_VERSION}"
+}
+"""Header to be used in an HTTP request"""
+
+INPUT_STRING = "Insert deck name (without .ydk) or command: "
+"""String that appears at user input"""
+
+YGOPRODECK_CARDS_URL = "https://db.ygoprodeck.com/api/v7/cardinfo.php"
+"""Base API URL for YGOProDeck"""
+
+IMAGES_BASE_URL = "https://images.ygoprodeck.com/images/cards"
+"""Base URL for images"""
+
+CARD_CACHE_PATH = "./hd_cards_downloader_tracker"
+"""Path to the cards cache file"""
+
+FIELD_CACHE_PATH = "./hd_fields_downloader_tracker"
+"""Path to the fields cache file"""
+
+SETUP_CREATION_FILES = (CARD_CACHE_PATH, FIELD_CACHE_PATH)
+"""Files needed on setup"""
+
+SETUP_CREATION_FOLDERS = ("pics", "pics/field")
+"""Folders needed on setup"""
diff --git a/downloader.py b/downloader.py
deleted file mode 100644
index 4cf751b..0000000
--- a/downloader.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from urllib import request as __request
-from os.path import join as __join
-
-from commands.typing import DownloadCard
-
-def download_image(card: DownloadCard) -> bool:
- """Downloads the card image or artwork and puts in the specified folder.
-
- Returns `True` if downloads successfully, otherwise returns `False`."""
-
- img_url = "https://storage.googleapis.com/ygoprodeck.com/pics"
- if not card.artwork:
- img_url += f"/{card.card_id}.jpg"
- store_at = "./pics/"
- else:
- img_url += f"_artgame/{card.card_id}.jpg"
- store_at = "./pics/field/"
-
- file_path = __join(store_at, f"{card.card_id}.jpg")
- try:
- __request.urlretrieve(img_url, file_path)
- return True
-
- except Exception as e:
- print(f"Error downloading '{card.card_id}': {e}")
- return False
diff --git a/main.py b/main.py
index 49cbc2c..1f843e9 100644
--- a/main.py
+++ b/main.py
@@ -2,30 +2,29 @@
from time import sleep
from traceback import print_exc
from commands.setup import setup_commands
+from constants import DOWNLOADER_VERSION, INPUT_STRING, SETUP_CREATION_FILES
from input_handler import handle_input
from commands.typing import DownloadCard
-from downloader import download_image
-from tracker import (already_downloaded, card_cache_path, field_cache_path,
- mark_as_downloaded)
+from web_access.downloader import download_image
+from tracker import (already_downloaded, mark_as_downloaded)
-# String that appears at user input
-INPUT_STRING = "Insert deck name (without .ydk) or command: "
def initialize():
"""Creates tracker files if they do not exist, setups all commands and
introduces the program
"""
- global card_cache_path, field_cache_path
- for i in card_cache_path, field_cache_path:
- if not exists(i):
- open(i, "w+").close()
+ for f in SETUP_CREATION_FILES:
+ if not exists(f):
+ with open(f, "w+"):
+ # I only need that the files exist
+ pass
setup_commands()
print("\n".join([
- "EDOPro HD Downloader",
+ f"EDOPro HD Downloader v{DOWNLOADER_VERSION}",
"Created by Nii Miyo",
"Type \"/help\" for help"
]))
@@ -37,7 +36,7 @@ def to_download(card: DownloadCard):
if (card.force) or (not already_downloaded(card)):
success = download_image(card)
if success: mark_as_downloaded(card)
- sleep(.1)
+ sleep(.5)
def main():
diff --git a/tracker.py b/tracker.py
index 33f47d7..bcf75c0 100644
--- a/tracker.py
+++ b/tracker.py
@@ -1,17 +1,14 @@
from commands.typing import DownloadCard
+from constants import CARD_CACHE_PATH, FIELD_CACHE_PATH
-card_cache_path = "./hd_cards_downloader_tracker"
-field_cache_path = "./hd_fields_downloader_tracker"
-
def __get_cached(is_artwork: bool):
"""Reads tracker file and returns a list of ids
that already were downloaded"""
- cache = field_cache_path if is_artwork else card_cache_path
- cache_file = open(cache, mode="r+", encoding="utf8")
- cards = [c.strip() for c in cache_file.readlines()]
- cache_file.close()
+ cache = FIELD_CACHE_PATH if is_artwork else CARD_CACHE_PATH
+ with open(cache, mode="r+", encoding="utf8") as cache_file:
+ cards = [c.strip() for c in cache_file.readlines()]
return cards
def already_downloaded(card: DownloadCard):
@@ -24,8 +21,7 @@ def already_downloaded(card: DownloadCard):
def mark_as_downloaded(card: DownloadCard):
"""Opens tracker file to add an id to the downloaded list"""
- cache = card_cache_path if not card.artwork else field_cache_path
+ cache = FIELD_CACHE_PATH if card.artwork else CARD_CACHE_PATH
- cache_file = open(cache, mode="a+", encoding="utf8")
- cache_file.write(f"{card.card_id}\n")
- cache_file.close()
+ with open(cache, mode="a+", encoding="utf8") as cache_file:
+ cache_file.write(f"{card.card_id}\n")
diff --git a/web_access/downloader.py b/web_access/downloader.py
new file mode 100644
index 0000000..ca40ac6
--- /dev/null
+++ b/web_access/downloader.py
@@ -0,0 +1,30 @@
+import requests
+from os.path import join
+
+from commands.typing import DownloadCard
+from constants import IMAGES_BASE_URL
+
+def download_image(card: DownloadCard) -> bool:
+ """
+ Downloads the card image or artwork and puts in the specified folder.
+
+ Returns `True` if downloads successfully, otherwise returns `False`.
+ """
+
+ url = IMAGES_BASE_URL
+ store_at = "./pics/"
+
+ if card.artwork:
+ url += "_cropped"
+ store_at += "field/"
+ url += f"/{card.card_id}.jpg"
+
+ file_path = join(store_at, f"{card.card_id}.jpg")
+ try:
+ res = requests.get(url)
+ with open(file_path, 'wb+') as f:
+ f.write(res.content)
+ return True
+ except Exception as e:
+ print(f"Error downloading '{card.card_id}': {type(e).__name__}\n{e}")
+ return False
diff --git a/web_access/request_helper.py b/web_access/request_helper.py
new file mode 100644
index 0000000..de8175b
--- /dev/null
+++ b/web_access/request_helper.py
@@ -0,0 +1,10 @@
+from typing import Any, Optional
+import requests
+from constants import REQUEST_HEADERS
+
+def make_request(
+ url: str,
+ params: Optional[dict[Any, Any]] = None
+) -> requests.Response:
+
+ return requests.get(url, headers=REQUEST_HEADERS, params=params)
diff --git a/web_access/ygoprodeck_api.py b/web_access/ygoprodeck_api.py
new file mode 100644
index 0000000..dde0be1
--- /dev/null
+++ b/web_access/ygoprodeck_api.py
@@ -0,0 +1,42 @@
+from requests import Response
+from constants import YGOPRODECK_CARDS_URL
+from web_access.request_helper import make_request
+
+
+def _get_ids_from_response(response: Response) -> list[int]:
+ """Returns only the ids of the cards requested"""
+ data = response.json().get("data")
+ ids: list[int] = list()
+
+ for c in data:
+ for img in c.get("card_images"):
+ ids.append(img.get("id"))
+ return ids
+
+def get_all_cards() -> list[int]:
+ """Returns the ids of all Yu-Gi-Oh! cards in `db.ygoprodeck.com` database"""
+
+ try:
+ response = make_request(YGOPRODECK_CARDS_URL)
+ return _get_ids_from_response(response)
+ except Exception as e:
+ print(f"Error fetching db.ygoprodeck.com: {type(e).__name__}\n{e}")
+
+ return list()
+
+def get_all_fields() -> list[int]:
+ """
+ Returns the ids of all Yu-Gi-Oh! Field Spell cards in
+ `db.ygoprodeck.com` database
+ """
+
+ try:
+ response = make_request(
+ YGOPRODECK_CARDS_URL,
+ params={"type": "spell card","race": "field"}
+ )
+ return _get_ids_from_response(response)
+ except Exception as e:
+ print(f"Error fetching db.ygoprodeck.com: {type(e).__name__}\n{e}")
+
+ return list()