mirror of
https://gitverse.ru/kpa39l/email-assistant.git
synced 2026-09-29 09:15:09 +00:00
Session 2026-09-15 code: imap_client (auth+metrics), handlers (TG date format), cron fix (venv python), openspec imap-realtime-sync proposal
This commit is contained in:
@@ -108,6 +108,17 @@ TG_TIMEOUT = 20
|
||||
# ---------------------------------------------------------------------------
|
||||
# Frontmatter
|
||||
# ---------------------------------------------------------------------------
|
||||
def _unquote_yaml(v):
|
||||
"""Снять обрамляющие двойные кавычки YAML-значения (артефакт простого парсера).
|
||||
|
||||
Если значение начинается/заканчивается на ", снять их и разэкранировать \\".
|
||||
"""
|
||||
v = v.strip()
|
||||
if len(v) >= 2 and v[0] == '"' and v[-1] == '"':
|
||||
v = v[1:-1].replace('\\"', '"').replace("\\\\", "\\")
|
||||
return v
|
||||
|
||||
|
||||
def parse_email_md(path):
|
||||
"""Прочитать email.md, вернуть (headers, body, content, fm_end)."""
|
||||
content = path.read_text(encoding="utf-8", errors="replace")
|
||||
@@ -120,7 +131,7 @@ def parse_email_md(path):
|
||||
for line in yaml_block.split("\n"):
|
||||
m = re.match(r"^(\w[\w_-]*)\s*:\s*(.*)$", line)
|
||||
if m:
|
||||
headers[m.group(1)] = m.group(2).strip()
|
||||
headers[m.group(1)] = _unquote_yaml(m.group(2))
|
||||
else:
|
||||
headers, body, fm_end = {}, content.strip(), None
|
||||
return headers, body, content, fm_end
|
||||
@@ -379,15 +390,38 @@ def tg_call(method, **params):
|
||||
return data.get("result", {})
|
||||
|
||||
|
||||
def format_date_for_tg(date_str):
|
||||
"""'2026-09-02 10:49+03:00' → '02.09.2026 10:49' (ДД.ММ.ГГГГ ЧЧ:ММ).
|
||||
|
||||
Известные форматы frontmatter:
|
||||
'2026-09-02 10:49+03:00' (ISO, может быть пробел/буква перед таймзоной)
|
||||
'2026-09-02T10:49:03+03:00' (RFC3339)
|
||||
Если распарсить не удалось — вернуть как есть (не ломать уведомление).
|
||||
"""
|
||||
s = (date_str or "").strip()
|
||||
if not s:
|
||||
return ""
|
||||
t = s
|
||||
# нормализуем: отрезаем таймзону (+03:00 / +0300 / Z)
|
||||
m = re.match(r"^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})", s)
|
||||
if m:
|
||||
return f"{m.group(3)}.{m.group(2)}.{m.group(1)} {m.group(4)}:{m.group(5)}"
|
||||
return s
|
||||
|
||||
|
||||
def handle_urgent(path, headers, body):
|
||||
"""Отправить уведомление в Telegram. Возвращает (ok, detail)."""
|
||||
subject = (headers.get("subject") or "(без темы)").strip()
|
||||
sender = (headers.get("from") or "?").strip()
|
||||
# Дата/время получения — из frontmatter, формат ДД.ММ.ГГГГ ЧЧ:ММ
|
||||
date = format_date_for_tg(headers.get("date") or headers.get("internal_date"))
|
||||
date_line = f"📅 {date}\n" if date else ""
|
||||
preview = body.strip()
|
||||
if len(preview) > MAX_PREVIEW_CHARS:
|
||||
preview = preview[:MAX_PREVIEW_CHARS].rstrip() + "…"
|
||||
text = (
|
||||
f"⚠️ СРОЧНОЕ письмо\n\n"
|
||||
f"⚠️ СРОЧНОЕ письмо\n"
|
||||
f"{date_line}"
|
||||
f"От: {sender}\n"
|
||||
f"Тема: {subject}\n\n"
|
||||
f"{preview}\n\n"
|
||||
|
||||
Reference in New Issue
Block a user