Files
epaper-dashboard/.backup/2026-08-26-active/plugins/gmail.py
T
epaper-dashboardandHermes 1f142f5245 Sync to Pi: alle Features die live deployed sind
Aus dem Backup und Live-Pull vom Pi (10.11.3.144):
- dashboard.py: Grid-Linien nur im freien Hintergrund (nicht durch Widgets)
- templates/index.html: komplett redesigned mit Sidebar + Topbar + Toast + Modal
- plugins/clock.py: responsive Layout (1x1 bis 4x4)
- plugins/system.py, weather.py, minimax.py: mit Threshold-Bars und Color-Variants
- plugins/base.py: NEU — fetch_with_retry Helper (3x retry mit backoff)
  + render_error_banner für fehlgeschlagene API-Plugins
  (grosses rotes "!" Icon mit Plugin-Name und Fehler statt Crash)

Cleanup: Helfer-Chaos (renderer.py/2/3, design_a/b/c.html, clock_classic.py,
23x clock_*.png, alte test_*.py) wurde bereits im vorherigen Commit entfernt.

Co-Authored-By: Hermes <noreply@hermes.local>
2026-08-26 22:11:36 +04:00

59 lines
2.5 KiB
Python

"""Gmail Unread - responsive."""
import os, sys, json
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
from plugins.base import Widget
from palette import FG, INFO, OK, WARN, measure, fit_font, centered_text, is_small, is_wide
class Widget(Widget):
name = "gmail"
label = "Gmail Unread"
description = "Anzahl ungelesener Emails im Posteingang."
category = "info"
config_schema = [
{"key": "oauth_token_json", "label": "OAuth Token (JSON)", "type": "secret",
"help": "token.json aus einem einmaligen OAuth-Flow."},
]
default_config = {"oauth_token_json": ""}
def fetch(self):
tok = self.cfg("oauth_token_json")
if not tok:
return {"_error": "OAuth-Token fehlt"}
try:
from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
creds = Credentials.from_authorized_user_info(json.loads(tok))
if creds.expired and creds.refresh_token:
creds.refresh(Request())
service = build("gmail", "v1", credentials=creds, cache_discovery=False)
label = service.users().labels().get(userId="me", id="INBOX").execute()
return {"unread": label.get("messagesUnread", 0)}
except ImportError:
return {"_error": "google-api-python-client nicht installiert"}
except Exception as e:
return {"_error": str(e)}
def render(self, draw, fonts, x, y, w, h):
pad = 8
draw.text((x + pad, y + pad), "GMAIL", font=fonts.get("24", fonts.get("20")), fill=INFO)
d = self.fetch()
if "_error" in d:
font = fit_font(draw, "Konfig fehlt", fonts, w - 2 * pad, h - 80)
centered_text(draw, "Konfig fehlt", x, y + 60, w, h - 60, font, WARN)
return
unread = d["unread"]
color = OK if unread == 0 else WARN if unread < 10 else FG
text = str(unread)
# Big number centered
if is_small(w, h):
font = fit_font(draw, text, fonts, w - 2 * pad, h - 50)
centered_text(draw, text, x, y, w, h - 30, font, color)
else:
font = fit_font(draw, text, fonts, w - 2 * pad, int(h * 0.6))
centered_text(draw, text, x, y, w, int(h * 0.6), font, color)
font_lbl = fit_font(draw, "Ungelesen", fonts, w - 2 * pad, 24)
centered_text(draw, "Ungelesen", x, y + int(h * 0.7), w, h // 5, font_lbl, FG)