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:
@@ -32,6 +32,7 @@ from .api.command_configs import router as command_configs_router
|
||||
from .api.command_trackers import router as command_trackers_router
|
||||
from .api.command_template_configs import router as command_template_configs_router
|
||||
from .commands.webhook import router as webhook_router, set_webhook_secret
|
||||
from .api.webhooks import router as webhooks_router
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
@@ -88,6 +89,7 @@ app.include_router(command_configs_router)
|
||||
app.include_router(command_trackers_router)
|
||||
app.include_router(command_template_configs_router)
|
||||
app.include_router(webhook_router)
|
||||
app.include_router(webhooks_router)
|
||||
|
||||
|
||||
@app.get("/api/health")
|
||||
@@ -120,7 +122,7 @@ async def _seed_default_templates():
|
||||
}
|
||||
|
||||
for locale in ("en", "ru"):
|
||||
slots = load_default_templates(locale)
|
||||
slots = load_default_templates(locale, provider_type="immich")
|
||||
if not slots:
|
||||
continue
|
||||
|
||||
@@ -193,6 +195,86 @@ async def _seed_default_templates():
|
||||
template=template_text,
|
||||
))
|
||||
|
||||
# --- Seed Gitea default templates ---
|
||||
gitea_result = await session.exec(
|
||||
select(TemplateConfig).where(
|
||||
TemplateConfig.user_id == 0,
|
||||
TemplateConfig.provider_type == "gitea",
|
||||
)
|
||||
)
|
||||
gitea_configs = gitea_result.all()
|
||||
gitea_existing_locales = {
|
||||
(c.locale if c.locale else "en"): c for c in gitea_configs
|
||||
}
|
||||
|
||||
for locale in ("en", "ru"):
|
||||
gitea_slots = load_default_templates(locale, provider_type="gitea")
|
||||
if not gitea_slots:
|
||||
continue
|
||||
|
||||
if locale not in gitea_existing_locales:
|
||||
from datetime import datetime as _dt, timezone as _tz
|
||||
now = _dt.now(_tz.utc).isoformat()
|
||||
name = f"Default Gitea ({locale.upper()})"
|
||||
desc = f"Default Gitea templates ({locale.upper()})"
|
||||
col_info = (await session.execute(
|
||||
text("PRAGMA table_info(template_config)")
|
||||
)).fetchall()
|
||||
col_names = [c[1] for c in col_info if c[1] != "id"]
|
||||
values = {}
|
||||
for col in col_names:
|
||||
if col == "user_id":
|
||||
values[col] = 0
|
||||
elif col == "provider_type":
|
||||
values[col] = "gitea"
|
||||
elif col == "name":
|
||||
values[col] = name
|
||||
elif col == "description":
|
||||
values[col] = desc
|
||||
elif col == "created_at":
|
||||
values[col] = now
|
||||
elif col == "date_format":
|
||||
values[col] = "%d.%m.%Y, %H:%M UTC"
|
||||
elif col == "date_only_format":
|
||||
values[col] = "%d.%m.%Y"
|
||||
elif col == "locale":
|
||||
values[col] = locale
|
||||
else:
|
||||
values[col] = ""
|
||||
cols_str = ", ".join(values.keys())
|
||||
placeholders = ", ".join(f":{k}" for k in values.keys())
|
||||
await session.execute(
|
||||
text(f"INSERT INTO template_config ({cols_str}) VALUES ({placeholders})"),
|
||||
values,
|
||||
)
|
||||
row = (await session.execute(text("SELECT last_insert_rowid()"))).scalar()
|
||||
gitea_config_id = row
|
||||
for slot_name, template_text in gitea_slots.items():
|
||||
session.add(TemplateSlot(
|
||||
config_id=gitea_config_id,
|
||||
slot_name=slot_name,
|
||||
template=template_text,
|
||||
))
|
||||
else:
|
||||
config = gitea_existing_locales[locale]
|
||||
for slot_name, template_text in gitea_slots.items():
|
||||
slot_result = await session.exec(
|
||||
select(TemplateSlot).where(
|
||||
TemplateSlot.config_id == config.id,
|
||||
TemplateSlot.slot_name == slot_name,
|
||||
)
|
||||
)
|
||||
existing = slot_result.first()
|
||||
if existing:
|
||||
existing.template = template_text
|
||||
session.add(existing)
|
||||
else:
|
||||
session.add(TemplateSlot(
|
||||
config_id=config.id,
|
||||
slot_name=slot_name,
|
||||
template=template_text,
|
||||
))
|
||||
|
||||
await session.commit()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user