diff --git a/install/requirements-dev.txt b/install/requirements-dev.txt index c66cf1989..abbbbde88 100644 --- a/install/requirements-dev.txt +++ b/install/requirements-dev.txt @@ -15,3 +15,5 @@ feedparser==6.0.11 waitress==3.0.2 astral>=3.1 pytest==8.4.2 +gkeepapi==0.17.1 +gpsoauth==2.0.0 diff --git a/install/requirements.txt b/install/requirements.txt index 66c636ab4..52f12288d 100644 --- a/install/requirements.txt +++ b/install/requirements.txt @@ -16,3 +16,5 @@ cysystemd==2.0.1 waitress==3.0.2 feedparser==6.0.11 astral>=3.1 +gkeepapi==0.17.1 +gpsoauth==2.0.0 diff --git a/src/plugins/keep/icon.png b/src/plugins/keep/icon.png new file mode 100644 index 000000000..09d391029 Binary files /dev/null and b/src/plugins/keep/icon.png differ diff --git a/src/plugins/keep/keep.py b/src/plugins/keep/keep.py new file mode 100644 index 000000000..102945800 --- /dev/null +++ b/src/plugins/keep/keep.py @@ -0,0 +1,81 @@ +from gkeepapi.node import NodeLabels +from plugins.base_plugin.base_plugin import BasePlugin +from PIL import Image +from datetime import datetime, timezone +import logging +import pytz +import gpsoauth +import gkeepapi + +logger = logging.getLogger(__name__) +class Keep(BasePlugin): + def generate_settings_template(self): + template_params = super().generate_settings_template() + template_params['api_key'] = { + "required": True, + "service": "Google", + "expected_key": "G_EMAIL, G_ANDROID_ID, G_MASTER_TOKEN", + } + template_params['style_settings'] = True + return template_params + + def generate_image(self, settings, device_config): + note_id = settings.get('id') + if not note_id: + raise RuntimeError("Note id is required.") + + dimensions = device_config.get_resolution() + if device_config.get_config("orientation") == "vertical": + dimensions = dimensions[::-1] + + email = device_config.load_env_key("G_EMAIL") + password = device_config.load_env_key("G_PASSWORD") + android_id = device_config.load_env_key("G_ANDROID_ID") + + ### Get your master token via one of the two methods below + + ### Get token from cookie oauth + ### https://github.com/simon-weber/gpsoauth?tab=readme-ov-file#alternative-flow + # token_t = '...' + # master_response = gpsoauth.exchange_token(email, token_t, android_id) + # master_token = master_response['Token'] # if there's no token check the response for more details + # + # auth_response = gpsoauth.perform_oauth( + # email, master_token, android_id, + # service='sj', app='com.google.android.music', + # client_sig='38918a453d07199354f8b19af05ec6562ced5788') + # token = auth_response['Auth'] + # logger.info(f"Token data: {master_token}") + + ### Get token with urllib (not working with latest version of urllib as per https://github.com/urllib3/urllib3/issues/2101) + ### https://github.com/simon-weber/gpsoauth?tab=readme-ov-file#gpsoauth + # master_response = gpsoauth.perform_master_login(email, password, android_id) + # logger.info(f"Token data: {master_response}") + # master_token = master_response['Token'] + # auth_response = gpsoauth.perform_oauth( + # email, master_token, android_id, + # service='sj', app='com.google.android.music', + # client_sig='38918a453d07199354f8b19af05ec6562ced5788') + # token = auth_response['Auth'] + # logger.info(f"Token data: {token}") + + master_token = device_config.load_env_key("G_MASTER_TOKEN") + keep = gkeepapi.Keep() + success = keep.authenticate(email, master_token) + keep.sync() + + gnote = keep.get(note_id) + if not gnote: + raise RuntimeError("Note not found.") + + gnote_date_str = gnote.timestamps.edited.astimezone().strftime("%Y-%m-%d %H:%M") + + template_params = { + "title": gnote.title, + "note_item": gnote.text, + "date": "Edited: " + gnote_date_str, + "plugin_settings": settings + } + + image = self.render_image(dimensions, "keep.html", "keep.css", template_params) + return image diff --git a/src/plugins/keep/plugin-info.json b/src/plugins/keep/plugin-info.json new file mode 100644 index 000000000..be21dcd91 --- /dev/null +++ b/src/plugins/keep/plugin-info.json @@ -0,0 +1,5 @@ +{ + "display_name": "Keep", + "id": "keep", + "class": "Keep" +} diff --git a/src/plugins/keep/render/keep.css b/src/plugins/keep/render/keep.css new file mode 100644 index 000000000..97f9cb0a1 --- /dev/null +++ b/src/plugins/keep/render/keep.css @@ -0,0 +1,39 @@ +:root { + --used-height: calc(min(20dvw, 20dvh) + 10px); + --available-height: round(down, calc(100dvh - var(--used-height)), min(5dvw, 5dvh)); +} +.keep-container { + display: flex; + align-items: center; + justify-content: center; + font-family: "Jost"; + height: 100%; + width: 100%; +} +.keep-wrapper { + width: 90%; + text-align: center; + margin: 0; + padding: 0; +} +.title { + font-size: min(11dvw, 11dvh); + font-weight: bold; + letter-spacing: .3px; + line-height: 1; +} +.subtitle { + margin: min(2dvw, 2dvh); + font-size: min(5dvw, 5dvh); + line-height: 1; +} +.note_item { + display: -webkit-box; + -webkit-line-clamp: calc(var(--available-height) / min(5dvw, 5dvh)); + -webkit-box-orient: vertical; + line-height: 1; + font-size: min(5dvw, 5dvh); + overflow: hidden; + white-space: pre-wrap; + text-align: left; +} diff --git a/src/plugins/keep/render/keep.html b/src/plugins/keep/render/keep.html new file mode 100644 index 000000000..9f5b79843 --- /dev/null +++ b/src/plugins/keep/render/keep.html @@ -0,0 +1,13 @@ +{% extends "plugin.html" %} + +{% block content %} + +
{{date}}
+{{note_item}}
+