From f228daf9fbd796bdd87ba8e062081b7f7cc5dbbf Mon Sep 17 00:00:00 2001 From: Ace Date: Sun, 14 Jan 2024 10:58:11 +0100 Subject: [PATCH] implement Tindie module for Inkycal --- inkycal/modules/__init__.py | 1 + inkycal/modules/inkycal_tindie.py | 107 ++++++++++++++++++++++++++++++ tests/config.py | 4 ++ tests/test_inkycal_tindie.py | 72 ++++++++++++++++++++ 4 files changed, 184 insertions(+) create mode 100755 inkycal/modules/inkycal_tindie.py create mode 100755 tests/test_inkycal_tindie.py diff --git a/inkycal/modules/__init__.py b/inkycal/modules/__init__.py index 3c0d809..9895d6c 100755 --- a/inkycal/modules/__init__.py +++ b/inkycal/modules/__init__.py @@ -10,3 +10,4 @@ from .inkycal_slideshow import Slideshow from .inkycal_textfile_to_display import TextToDisplay from .inkycal_webshot import Webshot from .inkycal_xkcd import Xkcd +from .inkycal_tindie import Tindie diff --git a/inkycal/modules/inkycal_tindie.py b/inkycal/modules/inkycal_tindie.py new file mode 100755 index 0000000..1f7a742 --- /dev/null +++ b/inkycal/modules/inkycal_tindie.py @@ -0,0 +1,107 @@ +""" +Tindie module for Inkycal Project +Shows unshipped orders from your Tindie store + +Copyright by aceinnolab +""" +import json + +import arrow + +from inkycal.custom import * +from inkycal.modules.template import inkycal_module + +# Show less logging for request module +logging.getLogger("urllib3").setLevel(logging.WARNING) + +logger = logging.getLogger(__name__) + + +class Tindie(inkycal_module): + """Tindie - show latest orders from your store""" + + def __init__(self, config): + """Initialize inkycal_feeds module""" + + super().__init__(config) + + config = config['config'] + self.api_key = config['api_key'] + self.username = config['username'] + # todo implement mode + # self.mode = config['mode'] # unshipped_orders, shipped_orders, all_orders + + # give an OK message + print(f'{__name__} loaded') + + def generate_image(self): + """Generate image for this module""" + # Define new image size with respect to padding + im_width = int(self.width - (2 * self.padding_left)) + im_height = int(self.height - (2 * self.padding_top)) + im_size = im_width, im_height + logger.info(f'image size: {im_width} x {im_height} px') + + # Create an image for black pixels and one for coloured pixels + im_black = Image.new('RGB', size=im_size, color='white') + im_colour = Image.new('RGB', size=im_size, color='white') + + # Check if internet is available + if internet_available(): + logger.info('Connection test passed') + else: + raise NetworkNotReachableError + + # Set some parameters for formatting feeds + line_spacing = 5 + text_bbox = self.font.getbbox("hg") + line_height = text_bbox[3] + line_spacing + line_width = im_width + max_lines = (im_height // (line_height + line_spacing)) + + logger.debug(f"max_lines: {max_lines}") + + # Calculate padding from top so the lines look centralised + spacing_top = int(im_height % line_height / 2) + + # Calculate line_positions + line_positions = [ + (0, spacing_top + _ * line_height) for _ in range(max_lines)] + + logger.debug(f'line positions: {line_positions}') + + # Make the API call + url = f"https://www.tindie.com/api/v1/order/?format=json&username={self.username}&api_key={self.api_key}" + header = {"accept": "text/json"} + response = requests.get(url, headers=header, params={"shipped": "false", "limit": "50"}) + if response.status_code != 200: + logger.error(f"Failed to get orders, status code: {response.status_code}, reason: {response.reason}") + raise AssertionError("Failed to get orders") + else: + logger.info("Orders received") + + text = [] + + orders = json.loads(response.text)["orders"] + text.append(f"You have {len(orders)} unshipped orders") + previous_date = None + for index, order in enumerate(orders, start=1): + items = order["items"] + date = arrow.get(order["date"]).to("local").format("YY/MM/DD") + if not previous_date or previous_date != date: + text.append(date) + previous_date = date + user_name = order["shipping_name"] + text.append(f"{index}) {user_name} from {order['shipping_country_code']} ordered {len(items)} items!") + + for pos, line in enumerate(text): + if pos > max_lines - 1: + logger.error(f'Ran out of lines! Required {len(text)} lines but only {max_lines} available') + break + if pos == 0: + write(im_colour, line_positions[pos], (line_width, line_height), line, font=self.font, alignment='left') + else: + write(im_black, line_positions[pos], (line_width, line_height), line, font=self.font, alignment='left') + + # Return images for black and colour channels + return im_black, im_colour diff --git a/tests/config.py b/tests/config.py index c3d3b03..f90a485 100644 --- a/tests/config.py +++ b/tests/config.py @@ -31,6 +31,10 @@ class Config: TEST_SETTINGS_PATH = f"{basedir}/settings.json" + # inkycal_tindie_test + TINDIE_API_KEY = get("TINDIE_API_KEY") + TINDIE_USERNAME = get("TINDIE_USERNAME") + diff --git a/tests/test_inkycal_tindie.py b/tests/test_inkycal_tindie.py new file mode 100755 index 0000000..ff9389c --- /dev/null +++ b/tests/test_inkycal_tindie.py @@ -0,0 +1,72 @@ +""" +inkycal_Tindie unittest +""" +import logging +import unittest + +from inkycal.modules import Tindie +from inkycal.modules.inky_image import Inkyimage +from tests import Config + +preview = Inkyimage.preview +merge = Inkyimage.merge + +logger = logging.getLogger(__name__) +logging.basicConfig(level=logging.DEBUG) + +tindie_api_key = Config.TINDIE_API_KEY +tindie_username = Config.TINDIE_USERNAME + +tests = [ + { + "name": "Tindie", + "config": { + "size": [300, 100], + "padding_x": 10, + "padding_y": 10, + "fontsize": 12, + "language": "en", + "api_key": tindie_api_key, + "username": tindie_username, + "mode": "unshipped_orders" + } + }, + { + "name": "Tindie", + "config": { + "size": [300, 150], + "padding_x": 10, + "padding_y": 10, + "fontsize": 12, + "language": "en", + "api_key": tindie_api_key, + "username": tindie_username, + "mode": "unshipped_orders" + } + }, + { + "name": "Tindie", + "config": { + "size": [300, 800], + "padding_x": 10, + "padding_y": 10, + "fontsize": 18, + "language": "en", + "api_key": tindie_api_key, + "username": tindie_username, + "mode": "unshipped_orders" + } + }, +] + + +class TestTindie(unittest.TestCase): + + def test_generate_image(self): + for test in tests: + logger.info(f'test {tests.index(test) + 1} generating image..') + module = Tindie(test) + im_black, im_colour = module.generate_image() + logger.info('OK') + if Config.USE_PREVIEW: + preview(merge(im_black, im_colour))