From ef86244cc5f257e403219bd0975fcef72a6ddd24 Mon Sep 17 00:00:00 2001 From: Yashar Dabiran Date: Sat, 15 Feb 2025 23:01:03 -0500 Subject: [PATCH] pass list name + refactor --- main.py | 105 +++++++++++++++++++++++++++------------ views/full-height.liquid | 8 +-- views/half-height.liquid | 83 +++++++++++++++---------------- 3 files changed, 115 insertions(+), 81 deletions(-) diff --git a/main.py b/main.py index a93339f..0c2b677 100644 --- a/main.py +++ b/main.py @@ -1,70 +1,113 @@ -import aiohttp +"""Bring! TRMNL plugin""" + import asyncio +import copy import datetime import os import time +from dataclasses import dataclass, field +from typing import List -from dotenv import load_dotenv - +import aiohttp +from aiohttp.web_exceptions import HTTPException from bring_api import Bring from bring_api.exceptions import BringException +from dotenv import load_dotenv load_dotenv() EXCEPTION_SLEEP_INTERVAL = 60 +PLUGIN_SLEEP_INTERVAL = 60 * 15 # 15 minutes + + +@dataclass +class BringList: + """Represents a Bring list""" + + name: str = "" + uuid: str = "" + items: List[str] = field(default_factory=list) + + def __eq__(self, other): + if isinstance(other, BringList): + return ( + self.name == other.name + and self.uuid == other.uuid + and set(self.items) == set(other.items) + ) + return False + class BringPlugin: - SLEEP_INTERVAL = 15 * 60 # 15 minutes + """ + Class syncing Bring shopping list with TRMNL. + The plugin currently supports only one shopping list. + """ def __init__(self): - self.email = os.getenv('EMAIL') - self.password = os.getenv('PASSWORD') - self.webhook_url = os.getenv('WEBHOOK_URL') - self.items = [] + self.email = os.getenv("EMAIL") + self.password = os.getenv("PASSWORD") + self.webhook_url = os.getenv("WEBHOOK_URL") + self.bring = None + self.existing_list = None - async def grabItems(self): - itemObjs = (await self.bring.get_list(self.list)).items.purchase - items = [item.itemId for item in itemObjs] + async def grab_items(self, bring_list): + """Grabs the items of the list using the list's uuid""" + item_objs = (await self.bring.get_list(bring_list.uuid)).items.purchase + bring_list.items = [item.itemId for item in item_objs] print(f"Successfully fetched items at {datetime.datetime.now().isoformat()}") - print(f"Items = {items}") - return items - - async def sendItemsToTerminal(self, session, items): - if set (self.items) == set(items): - print(f"The items list hasn't changed since the last fetch.") - print(f"Skipping sending updates to TRMNL.") + print(f"Items = {bring_list.items}") + + async def send_list_to_trmnl(self, session, bring_list): + """Sends the list to TRMNL if it has changed""" + if self.existing_list == bring_list: + print("The items list hasn't changed since the last fetch.") + print("Skipping sending updates to TRMNL.") return - self.items = items + self.existing_list = bring_list try: await session.post( self.webhook_url, - json={'merge_variables': {'items': items}}, - headers={'Content-Type': 'application/json'}, - raise_for_status=True) - + json={ + "merge_variables": { + "items": self.existing_list.items, + "list_name": self.existing_list.name, + } + }, + headers={"Content-Type": "application/json"}, + raise_for_status=True, + ) + current_timestamp = datetime.datetime.now().isoformat() print(f"Items sent successfully to TRMNL at {current_timestamp}") - except Exception as e: + except HTTPException as e: print(f"Exception occurred during sending items to TRMNL: {e}") async def run(self): + """Start the plugin""" async with aiohttp.ClientSession() as session: self.bring = Bring(session, self.email, self.password) await self.bring.login() while True: - self.list = (await self.bring.load_lists()).lists[0].listUuid - items = await self.grabItems() - await self.sendItemsToTerminal(session, items) - time.sleep(self.SLEEP_INTERVAL) + new_list = None + if self.existing_list: + new_list = copy.deepcopy(self.existing_list) + else: + bring_api_list = (await self.bring.load_lists()).lists[0] + new_list = BringList(name=bring_api_list.name, uuid=bring_api_list.listUuid) + + await self.grab_items(new_list) + await self.send_list_to_trmnl(session, new_list) + time.sleep(PLUGIN_SLEEP_INTERVAL) if __name__ == "__main__": bring_plugin = BringPlugin() loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - + while True: try: loop.run_until_complete(bring_plugin.run()) @@ -72,7 +115,7 @@ if __name__ == "__main__": print(f"Bring exception occured: {e}") print(f"Sleeping for {EXCEPTION_SLEEP_INTERVAL} seconds.") time.sleep(EXCEPTION_SLEEP_INTERVAL) - print(f"Retrying the service") + print("Retrying the service") except Exception as e: print(f"Unknown exception occured: {e}") - raise \ No newline at end of file + raise diff --git a/views/full-height.liquid b/views/full-height.liquid index 18f4d1e..6766825 100644 --- a/views/full-height.liquid +++ b/views/full-height.liquid @@ -24,8 +24,7 @@ {% for item in items_to_display %} {% assign number_of_items_displayed = number_of_items_displayed | plus: 1 %}
-
-
+
{{ item }}
@@ -41,8 +40,5 @@ src="https://cdn.prod.website-files.com/5fbe6548a005d56f0dd39a2e/5fc24a65f7e1555200865e1b_bring-logo.svg" > Bring! - Home + {{ list_name }}
- - - diff --git a/views/half-height.liquid b/views/half-height.liquid index 51853e9..9df1b6c 100644 --- a/views/half-height.liquid +++ b/views/half-height.liquid @@ -1,49 +1,44 @@
-
- {% assign number_of_items_per_column = 6 %} - {% assign number_of_columns = 2 %} - {% assign total_count = items | size %} - {% assign number_of_items_displayed = 0 %} +
+ {% assign number_of_items_per_column = 6 %} + {% assign number_of_columns = 2 %} + {% assign total_count = items | size %} + {% assign number_of_items_displayed = 0 %} - {% assign var = number_of_columns | minus: 1 %} - {% for i in (0..var) %} - {% if number_of_items_displayed >= total_count %} - {% break %} + {% assign var = number_of_columns | minus: 1 %} + {% for i in (0..var) %} + {% if number_of_items_displayed >= total_count %} + {% break %} + {% endif %} +
+ {% assign items_to_display_count = number_of_items_per_column %} + {% if i == var %} + {% assign items_to_display_count = total_count | minus: number_of_items_displayed %} {% endif %} -
- {% assign items_to_display_count = number_of_items_per_column %} - {% if i == var %} - {% assign items_to_display_count = total_count | minus: number_of_items_displayed %} - {% endif %} - {% assign items_to_display = items | slice: number_of_items_displayed, items_to_display_count %} - {% for item in items_to_display %} - {% assign number_of_items_displayed = number_of_items_displayed | plus: 1 %} -
-
-
-
- {{ item }} -
+ {% assign items_to_display = items | slice: number_of_items_displayed, items_to_display_count %} + {% for item in items_to_display %} + {% assign number_of_items_displayed = number_of_items_displayed | plus: 1 %} +
+
+
+ {{ item }}
- {% endfor %} -
- {% endfor %} -
+
+ {% endfor %} +
+ {% endfor %}
-
- - Bring! - Home -
- - - - \ No newline at end of file +
+
+ + Bring! + {{ list_name }} +