Skip to content

Commit

Permalink
Add custom logger
Browse files Browse the repository at this point in the history
  • Loading branch information
milouk committed Oct 14, 2024
1 parent 5babcd9 commit 39cf1e0
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 41 deletions.
3 changes: 2 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"roms": "/mnt/sdcard/ROMS",
"logos": "assets/logos",
"log_level": "info",
"colors": {
"primary": "#bb7200",
"primary_dark": "#7f4f00",
"secondary": "#292929",
"secondary_light": "#383838",
"secondary_dark": "#141414"
},
},
"screenscraper": {
"username": "",
"password": "",
Expand Down
22 changes: 16 additions & 6 deletions src/app.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import logging
import os
import sys
import time
Expand All @@ -7,6 +8,7 @@

import input
from graphic import GUI
from logger import LoggerSingleton as logger
from PIL import Image
from scraper import (
check_destination,
Expand All @@ -19,13 +21,14 @@
get_user_data,
)

VERSION = "1.0.2"

selected_position = 0
roms_selected_position = 0
selected_system = ""
current_window = "emulators"
max_elem = 11
skip_input_check = False
scraping = False


class Rom:
Expand Down Expand Up @@ -78,8 +81,15 @@ def load_config(self, config_file):
self.gui.COLOR_SECONDARY_LIGHT = self.colors.get("secondary_light")
self.gui.COLOR_SECONDARY_DARK = self.colors.get("secondary_dark")

def setup_logging(self):
log_level_str = self.config.get("log_level", "INFO").upper()
log_level = getattr(logging, log_level_str, logging.INFO)
logger.setup_logger(log_level)

def start(self, config_file: str) -> None:
self.load_config(config_file)
self.setup_logging()
logger.log_debug(f"Artie Scraper v{VERSION}")
self.gui.draw_start()
self.gui.screen_reset()
main_gui = self.gui.create_image()
Expand Down Expand Up @@ -253,6 +263,7 @@ def save_file_to_disk(self, data, destination):
check_destination(destination)
destination.write_bytes(data)
self.gui.draw_log("Scraping completed!")
logger.log_debug(f"Saved file to {destination}")
return True

def get_user_threads(self):
Expand Down Expand Up @@ -288,7 +299,7 @@ def scrape(self, rom, system_id):
if self.synopsis_enabled:
scraped_synopsis = fetch_synopsis(game, content)
except Exception as e:
print(f"Error scraping {rom.name}: {e}")
logger.log_error(f"Error scraping {rom.name}: {e}")

return scraped_box, scraped_preview, scraped_synopsis

Expand Down Expand Up @@ -381,7 +392,7 @@ def load_roms(self) -> None:

if not scraped_box and not scraped_preview and not scraped_synopsis:
self.gui.draw_log("Scraping failed!")
print(f"Failed to get screenshot for {rom.name}")
logger.log_error(f"Failed to get screenshot for {rom.name}")
self.gui.draw_paint()
time.sleep(self.LOG_WAIT)
exit_menu = True
Expand Down Expand Up @@ -410,7 +421,7 @@ def load_roms(self) -> None:
success += 1
else:
self.gui.draw_log("Scraping failed!")
print(f"Failed to get screenshot for {rom.name}")
logger.log_error(f"Failed to get screenshot for {rom.name}")
failure += 1
progress += 1
self.gui.draw_log(f"Scraping {progress} of {len(roms_to_scrape)}")
Expand Down Expand Up @@ -558,9 +569,8 @@ def row_list(
)

except Exception as e:
print(f"Error loading image from {image_path}: {e}")
logger.log_error(f"Error loading image from {image_path}: {e}")

# Draw the text
self.gui.draw_text((text_offset_x, pos[1] + 5), text)

def button_circle(self, pos: tuple[int, int], button: str, text: str) -> None:
Expand Down
10 changes: 5 additions & 5 deletions src/input.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import struct
import logging

# Set up logging
logging.basicConfig(level=logging.ERROR)
from logger import LoggerSingleton as logger

KEY_MAPPING = {
304: "A",
Expand Down Expand Up @@ -40,7 +38,9 @@ def check_input(device_path="/dev/input/event1"):
current_code = key_code
current_code_name = KEY_MAPPING.get(current_code, str(current_code))
current_value = key_value
logging.debug(f"Key pressed: {current_code_name}, value: {current_value}")
logger.log_debug(
f"Key pressed: {current_code_name}, value: {current_value}"
)
return


Expand All @@ -55,4 +55,4 @@ def reset_input():
global current_code_name, current_value
current_code_name = ""
current_value = 0
logging.debug("Input reset")
logger.log_debug("Input reset")
51 changes: 51 additions & 0 deletions src/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import logging
from typing import Optional


class LoggerSingleton:
_logger_instance: Optional[logging.Logger] = None
_log_level = logging.INFO

@classmethod
def setup_logger(cls, log_level=logging.INFO):
cls._log_level = log_level
if cls._logger_instance is None:
cls._initialize_logger()
else:
cls._logger_instance.setLevel(cls._log_level)

@classmethod
def _initialize_logger(cls):
logging.basicConfig(
level=cls._log_level, format="%(asctime)s - %(levelname)s - %(message)s"
)
cls._logger_instance = logging.getLogger("AppLogger")
cls._logger_instance.setLevel(cls._log_level)

@classmethod
def get_logger(cls) -> logging.Logger:
if cls._logger_instance is None:
cls._initialize_logger()

assert cls._logger_instance is not None, "Logger instance is not initialized"
return cls._logger_instance

@classmethod
def log_info(cls, message: str):
logger = cls.get_logger()
logger.info(message)

@classmethod
def log_debug(cls, message: str):
logger = cls.get_logger()
logger.debug(message)

@classmethod
def log_warning(cls, message: str):
logger = cls.get_logger()
logger.warning(message)

@classmethod
def log_error(cls, message: str):
logger = cls.get_logger()
logger.error(message)
52 changes: 23 additions & 29 deletions src/scraper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
import json
import os
import re
import logging
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
from pathlib import Path
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse

import requests
from logger import LoggerSingleton as logger

GAME_INFO_URL = "https://api.screenscraper.fr/api2/jeuInfos.php"
USER_INFO_URL = "https://api.screenscraper.fr/api2/ssuserInfos.php"
Expand All @@ -16,15 +16,6 @@
VALID_MEDIA_TYPES = {"box-2D", "box-3D", "mixrbv1", "mixrbv2", "ss"}


def configure_logging():
logging.basicConfig(
level=logging.ERROR, format="%(asctime)s - %(levelname)s - %(message)s"
)


configure_logging()


def get_image_files_without_extension(folder):
return [
f.stem for f in Path(folder).glob("*") if f.suffix.lower() in IMAGE_EXTENSIONS
Expand All @@ -38,7 +29,7 @@ def get_txt_files_without_extension(folder):
def sha1sum(file_path):
file_size = os.path.getsize(file_path)
if file_size > MAX_FILE_SIZE_BYTES:
logging.warning(f"File {file_path} exceeds max file size limit.")
logger.log_warning(f"File {file_path} exceeds max file size limit.")
return ""

hash_sha1 = hashlib.sha1()
Expand All @@ -47,7 +38,7 @@ def sha1sum(file_path):
for chunk in iter(lambda: f.read(4096), b""):
hash_sha1.update(chunk)
except IOError as e:
logging.error(f"Error reading file {file_path}: {e}")
logger.log_error(f"Error reading file {file_path}: {e}")
return ""
return hash_sha1.hexdigest()

Expand All @@ -66,7 +57,7 @@ def file_size(file_path):
try:
return os.path.getsize(file_path)
except OSError as e:
logging.error(f"Error getting size of file {file_path}: {e}")
logger.log_error(f"Error getting size of file {file_path}: {e}")
return None


Expand All @@ -87,7 +78,8 @@ def parse_find_game_url(system_id, rom_path, dev_id, dev_password, username, pas
try:
return urlunparse(urlparse(GAME_INFO_URL)._replace(query=urlencode(params)))
except UnicodeDecodeError as e:
logging.error(f"Error encoding URL: {e}. ROM params: {params}")
logger.log_debug("Params: %s")
logger.log_error(f"Error encoding URL: {e}. ROM params: {params}")
return None


Expand All @@ -103,7 +95,7 @@ def parse_user_info_url(dev_id, dev_password, username, password):
try:
return urlunparse(urlparse(USER_INFO_URL)._replace(query=urlencode(params)))
except UnicodeDecodeError as e:
logging.error(f"Error encoding URL: {e}. User info params: {params}")
logger.log_error(f"Error encoding URL: {e}. User info params: {params}")
return None


Expand All @@ -112,7 +104,7 @@ def find_media_url_by_region(medias, media_type, regions):
for media in medias:
if media["type"] == media_type and media["region"] == region:
return media["url"]
logging.error(f"Media not found for regions: {regions}")
logger.log_error(f"Media not found for regions: {regions}")
return None


Expand All @@ -125,20 +117,20 @@ def add_wh_to_media_url(media_url, width, height):

def is_media_type_valid(media_type):
if media_type not in VALID_MEDIA_TYPES:
logging.error(f"Unknown media type: {media_type}")
logger.log_error(f"Unknown media type: {media_type}")
return False
return True


def check_destination(dest):
if os.path.exists(dest):
logging.error(f"Destination file already exists: {dest}")
logger.log_error(f"Destination file already exists: {dest}")
return None
dest_dir = os.path.dirname(dest)
try:
os.makedirs(dest_dir, exist_ok=True)
except OSError as e:
logging.error(f"Error creating directory {dest_dir}: {e}")
logger.log_error(f"Error creating directory {dest_dir}: {e}")
return None


Expand All @@ -148,10 +140,10 @@ def get(url):
response = session.get(url, timeout=10)
response.raise_for_status()
except requests.Timeout:
logging.error("Request timed out")
logger.log_error("Request timed out")
return None
except requests.RequestException as e:
logging.error(f"Error making HTTP request: {e}")
logger.log_error(f"Error making HTTP request: {e}")
return None
return response.content

Expand All @@ -160,22 +152,22 @@ def fetch_data(url):
try:
body = get(url)
if not body:
logging.error("Empty response body")
logger.log_error("Empty response body")
return None

body_str = body.decode("utf-8")
if "API closed" in body_str:
logging.error("API is closed")
logger.log_error("API is closed")
return None
if "Erreur" in body_str:
logging.error("Error found in response: %s", body_str)
logger.log_error("Error found in response: %s", body_str)
return None

return json.loads(body_str)
except json.JSONDecodeError as e:
logging.error(f"Error decoding JSON response: {e}")
logger.log_error(f"Error decoding JSON response: {e}")
except Exception as e:
logging.error(f"Error fetching data from URL: {e}")
logger.log_error(f"Error fetching data from URL: {e}")
return None


Expand Down Expand Up @@ -211,7 +203,7 @@ def fetch_box(game, config):
regions = config.get("regions", ["us", "ame", "wor"])
box = _fetch_media(medias, config["box"], regions)
if not box:
logging.error(f"Error downloading box: {game['response']['jeu']['medias']}")
logger.log_error(f"Error downloading box: {game['response']['jeu']['medias']}")
return None
return box

Expand All @@ -221,7 +213,9 @@ def fetch_preview(game, config):
regions = config.get("regions", ["us", "ame", "wor"])
preview = _fetch_media(medias, config["preview"], regions)
if not preview:
logging.error(f"Error downloading preview: {game['response']['jeu']['medias']}")
logger.log_error(
f"Error downloading preview: {game['response']['jeu']['medias']}"
)
return None
return preview

Expand Down

0 comments on commit 39cf1e0

Please sign in to comment.