feat: add Gitea as webhook-based service provider

First webhook-based provider integration (Immich uses polling).
Gitea pushes events via POST /api/webhooks/gitea/{provider_id} with
HMAC-SHA256 signature validation.

- 9 event types: push, issue opened/closed/commented, PR opened/closed/merged/commented, release published
- Generic filters system on NotificationTracker (collections, senders, exclude_senders)
- Provider capabilities include supported_filters and webhook_based flag
- Gitea API client for connection testing and repository listing
- 18 default Jinja2 notification templates (EN + RU)
- Frontend: conditional provider forms, Gitea event toggles in tracking config
- Auto-migration for filters column and Gitea tracking flags
This commit is contained in:
2026-03-22 12:58:35 +03:00
parent 1167d138a3
commit 6d28cfb8d8
39 changed files with 1588 additions and 25 deletions
+1
View File
@@ -99,4 +99,5 @@ export const previewTargetTypeItems = (): GridItem[] => [
export const providerTypeItems = (): GridItem[] => [
{ value: 'immich', icon: 'mdiCamera', label: t('providers.typeImmich') },
{ value: 'gitea', icon: 'mdiGit', label: t('providers.typeGitea') },
];
+17
View File
@@ -106,11 +106,18 @@
"offline": "Offline",
"checking": "Checking...",
"typeImmich": "Immich",
"typeGitea": "Gitea",
"loadError": "Failed to load providers.",
"externalDomain": "External Domain",
"optional": "optional",
"urlApiKeyRequired": "URL and API Key are required",
"externalDomainHint": "Public-facing URL for notification links. Falls back to server URL.",
"webhookSecret": "Webhook Secret",
"webhookSecretKeep": "Webhook Secret (leave empty to keep current)",
"webhookSecretHint": "Shared secret for HMAC-SHA256 signature verification. Set the same secret in Gitea webhook settings.",
"webhookSecretRequired": "Webhook secret is required",
"apiToken": "API Token",
"apiTokenHint": "Optional. Needed for connection testing and repository listing.",
"testAndSave": "Test & Save",
"saveWithoutTest": "Save without testing"
},
@@ -248,6 +255,7 @@
"matrixRoomId": "Room ID",
"receivers": "Receivers",
"noReceivers": "No receivers yet",
"alreadyAdded": "already added",
"addReceiver": "Add Receiver",
"receiverAdded": "Receiver added",
"receiverDeleted": "Receiver deleted",
@@ -348,6 +356,15 @@
"albumRenamed": "Album renamed",
"albumDeleted": "Album deleted",
"sharingChanged": "Sharing changed",
"push": "Push",
"issueOpened": "Issue opened",
"issueClosed": "Issue closed",
"issueCommented": "Issue commented",
"prOpened": "PR opened",
"prClosed": "PR closed",
"prMerged": "PR merged",
"prCommented": "PR commented",
"releasePublished": "Release published",
"trackImages": "Track images",
"trackVideos": "Track videos",
"favoritesOnly": "Favorites only",
+17
View File
@@ -106,11 +106,18 @@
"offline": "Не в сети",
"checking": "Проверка...",
"typeImmich": "Immich",
"typeGitea": "Gitea",
"loadError": "Не удалось загрузить провайдеры.",
"externalDomain": "Внешний домен",
"optional": "необязательно",
"urlApiKeyRequired": "URL и API ключ обязательны",
"externalDomainHint": "Публичный URL для ссылок в уведомлениях. По умолчанию используется URL сервера.",
"webhookSecret": "Секрет вебхука",
"webhookSecretKeep": "Секрет вебхука (оставьте пустым для сохранения текущего)",
"webhookSecretHint": "Общий секрет для проверки HMAC-SHA256 подписи. Укажите тот же секрет в настройках вебхука Gitea.",
"webhookSecretRequired": "Секрет вебхука обязателен",
"apiToken": "API токен",
"apiTokenHint": "Необязательно. Нужен для проверки подключения и получения списка репозиториев.",
"testAndSave": "Проверить и сохранить",
"saveWithoutTest": "Сохранить без проверки"
},
@@ -248,6 +255,7 @@
"matrixRoomId": "ID комнаты",
"receivers": "Получатели",
"noReceivers": "Нет получателей",
"alreadyAdded": "уже добавлен",
"addReceiver": "Добавить получателя",
"receiverAdded": "Получатель добавлен",
"receiverDeleted": "Получатель удалён",
@@ -348,6 +356,15 @@
"albumRenamed": "Альбом переименован",
"albumDeleted": "Альбом удалён",
"sharingChanged": "Изменение доступа",
"push": "Push",
"issueOpened": "Задача создана",
"issueClosed": "Задача закрыта",
"issueCommented": "Комментарий к задаче",
"prOpened": "PR создан",
"prClosed": "PR закрыт",
"prMerged": "PR влит",
"prCommented": "Комментарий к PR",
"releasePublished": "Релиз опубликован",
"trackImages": "Фото",
"trackVideos": "Видео",
"favoritesOnly": "Только избранные",