notify v0.7.1 [base]


Рассылка уведомлений (Telegram + веб-инбокс + Web Push).

README

# notify

Единая точка уведомлений: Telegram + веб (инбокс, Web Push).

Тип: Модуль. Категория: `base`. Зависимостей нет.

## Пользователю

- Колокольчик 🔔 в шапке — счётчик непрочитанных, клик открывает список.
  Кнопка «✓ Прочитано» / «✓ Всё прочитано», клик по всплывающему тосту —
  тоже «прочитано».
- «Уведомления браузера» в панели — разрешение (нужно для пушей ниже):
  кнопка «🔔 Включить» → разрешить в запросе браузера. Заблокировали —
  подсказка разрешить вручную (🔒 в адресной строке).
- Пуши при закрытой вкладке (Web Push): в панели строка «Пуши при закрытой
  вкладке» → «Подписаться» (нужны HTTPS и разрешение выше). Работает пока
  запущен браузер, вкладка не нужна. Каждое устройство подписывается само,
  «Отписаться» — там же.
- Дедуп с вкладкой: открытая видимая вкладка показывает тост сама —
  системный пуш не дублирует; клик по системному пушу гасит запись
  в инбоксе (повторно не вылезет); при открытии кабинета свернутые
  системные пуши тоже гаснут.
- Несколько вкладок/устройств на одном аккаунте — можно: пуш приходит
  везде, показ тоста — один на браузер (дедуп через localStorage).

## Разработчику: отправить уведомление

- Всем держателям права: `notify.send(text, right)` → `{tg, web}` —
  Telegram сообщением, веб — в инбокс (`receive_notifications_no_sound`
  = беззвучно/тихо). Права через `effective` (`all` покрывается).
- Конкретному пользователю: `notify.send_to("telegram:<id>"|"web:<uid>", text)`.
- Единый распил для своих рассылок: `notify.fanout(right, text, kind='send',
  level='info', retry=1)` → `{tg, web}`. Проверка прав — внутри
  (`effective`: `all` покрывается, посторонние и мусор отсекаются).
  TG-хук (кнопки/графики) — только из кода, не из API.
- Своя рассылка модуля: `notify.register(label, right, edit_right, module)`
  в `start()` (право вида `receive_notifications_*`) — дальше `send`
  по нему; пользователи управляют подпиской сами.
- Системные: `startup` / `shutdown` / `rights_changed` / `transport_switch`.

## Разработчику: как это устроено

- Буфер — `data/notify/inbox.json` (≤200 свежих на пользователя, TTL 30 сут).
  Каждая запись — `{id, ts, right, kind, title, body, level, silent, read}`.
- Доставка в браузер — WS `/ws/notify` (пуш через событие шины
  `notify.sent`), фолбэк — REST (`GET /api/notify/inbox?since=`,
  `GET /api/notify/unread`, `POST /api/notify/read`, `POST /api/notify/read_all`,
  `GET /api/notify/subs`, `POST /api/notify/sub`). Всё — только своя сессия.
- Без TG (режим «только веб») рассылка идёт только в инбокс, ошибок нет.
- Прямые `bot.send_message` вне диалогов (`tg.py`) — только через
  `fanout`: `boot --check` предупреждает (W3), если в модуле осталась
  прямая рассылка (в веб она не дойдёт).
- Закрытая вкладка — Web Push: VAPID-ключ (автогенерация,
  `data/notify/vapid_private.pem` 0600), подписки устройств
  (`data/notify/push_subs.json`, ≤10 на пользователя), fan-out из события
  шины `notify.sent` в фоне, ушедшие подписки (404/410) чистятся.
  Зависимость — `pywebpush` (`requirements.txt`); без него — тихое
  отключение (WS/REST работают).

## Права

- `receive_notifications` — базовое право рассылок
- `receive_notifications_status` — старт/стоп/связь
- `receive_notifications_status_edit` — менять себе уведомления статуса
- `receive_notifications_no_sound` — беззвучные/тихие

Манифест

{
  "name": "notify",
  "version": "0.7.1",
  "category": "base",
  "description": "Рассылка уведомлений (Telegram + веб-инбокс + Web Push).",
  "requires": [],
  "rights": [],
  "api_methods": [],
  "web_routes": [],
  "commit": "333964956544bc16dece9db79c1f8b0e1830fa90",
  "updated": "2026-10-08 22:01:59 +0300",
  "history": [
    {
      "version": "0.1.0",
      "date": "2026-09-08 09:46:42 +0300",
      "commit": "5c758d465ca4dd3e1541909f2b685dc5c5424246"
    },
    {
      "version": "0.4.0",
      "date": "2026-09-17 09:30:25 +0300",
      "commit": "47801cc7f98e5d02856f09e224f586aba5c5d256"
    },
    {
      "version": "0.5.0",
      "date": "2026-10-07 15:56:33 +0300",
      "commit": "9239e15bc832a2b502067a67bf2ca7d109fef6c0"
    },
    {
      "version": "0.6.0",
      "date": "2026-10-07 17:48:29 +0300",
      "commit": "cebc40733f8a8c97b692c26b43e7dd1047902afc"
    },
    {
      "version": "0.7.0",
      "date": "2026-10-08 12:43:58 +0300",
      "commit": "8930762567a7584c72d7f50d1f3ac8918f1788cb"
    },
    {
      "version": "0.7.1",
      "date": "2026-10-08 12:51:34 +0300",
      "commit": "a62833f8c0ebb9ec25e55570ed290d2b543bc43d"
    }
  ],
  "integrity": "sha256:9db484f2685b1ff5af50d479722843dbd693fa92e5c6ce35318449659fc171d4",
  "files": "[11 файлов — см. вкладки ниже]",
  "note": "",
  "wdesc": "",
  "wbody": "",
  "_extra": {
    "api": "",
    "ws_routes": "",
    "events_emitted": "",
    "events_subscribed": "",
    "config_schema": "config.schema.json",
    "env_example": ".env.example"
  }
}

Файлы и исходники

Дерево файлов

  • · корень
    • 4.9 КБ
    • 0.1 КБ
    • 15.5 КБ
    • 5.8 КБ
    • 5.4 КБ
    • 9.0 КБ
    • 0.1 КБ
    • 6.1 КБ
    • 6.4 КБ
    • 11.6 КБ
  • web/
    • 26.4 КБ

Предпросмотр

Выберите файл в дереве выше — код откроется здесь.

История версий

versiondatecommit
0.7.12026-10-08a62833f8c0eb
0.7.02026-10-088930762567a7
0.6.02026-10-07cebc40733f8a
0.5.02026-10-079239e15bc832
0.4.02026-09-1747801cc7f98e
0.1.02026-09-085c758d465ca4