Skip to content

feat: Add Gotify Notification Channel for Quota Alerts - #1948

Merged
seefs001 merged 2 commits into
QuantumNous:alphafrom
RedwindA:feat/gotify
Oct 2, 2025
Merged

feat: Add Gotify Notification Channel for Quota Alerts#1948
seefs001 merged 2 commits into
QuantumNous:alphafrom
RedwindA:feat/gotify

Conversation

@RedwindA

@RedwindA RedwindA commented Oct 1, 2025

Copy link
Copy Markdown
Contributor

PR 类型

  • Bug 修复
  • 新功能
  • 文档更新
  • 其他

PR 是否包含破坏性更新?

PR 描述

支持使用Gotify发送余额预警
图片

c3e4a868813a9be1b7a8e131936f4ab5

Summary by CodeRabbit

  • New Features

    • Added Gotify as a notification option for quota alerts and in notification type selector.
    • Personal Settings: configure Gotify URL, token, and priority (0–10, default 5) with validation, setup guidance, and UI fields.
    • Quota notifications support Gotify-specific content formatting and sending path.
  • Bug Fixes

    • Email notifications now fall back to the user’s account email when a notification-specific email is not set.
  • Documentation

    • Added localization entries for Bark and Gotify in UI locales.

@coderabbitai

coderabbitai Bot commented Oct 1, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds Gotify as a new notification channel across backend and frontend: DTO/constants, user settings update/validation, quota notification formatting, notification sending helper with worker/direct paths and SSRF checks, UI fields/validation, and an email fallback when user email is missing.

Changes

Cohort / File(s) Summary
Backend DTO & Controller
dto/user_settings.go, controller/user.go
Add NotifyTypeGotify constant; extend UserSetting and UpdateUserSettingRequest with gotify_url, gotify_token, gotify_priority. Validate Gotify selection (URL scheme http/https, token required, priority clamped 0–10) and persist settings.
Notification Services
service/user_notify.go, service/quota.go
Add gotify branch to notification flow: resolve placeholders, build JSON payload, clamp priority, send via worker or direct HTTP (with SSRF checks). Add email fallback to use user's default email if settings email empty. Update quota notification formatting for Gotify.
Web UI — Settings State & Save
web/src/components/settings/PersonalSetting.jsx
Add component state fields gotifyUrl, gotifyToken, gotifyPriority (default 5); map load/save to backend fields and coerce priority to integer.
Web UI — Notification Form
web/src/components/settings/personal/cards/NotificationSettings.jsx
Add "Gotify" radio option and config block with URL, token, priority inputs and validation messages; include guidance/docs link.
i18n Locales
web/src/i18n/locales/en.json, web/src/i18n/locales/fr.json
Add English and French translation keys/strings for Bark and Gotify UI text, validation messages, and guidance.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Web as Web UI
  participant API as Controller
  participant Svc as Notify Service
  participant Gotify as Gotify Server
  participant Mail as Email Provider
  participant Hook as Webhook

  rect rgba(230,240,255,0.35)
  User->>Web: Choose "Gotify", enter URL/Token/Priority
  Web->>API: PUT /user/settings { gotify_url, gotify_token, gotify_priority, warning_type: "gotify" }
  API->>API: Validate URL scheme & token, clamp priority
  API-->>Web: 200 OK
  end

  Note over Svc: Quota warning trigger
  API->>Svc: NotifyUser(user, settings, dto.Notify)
  alt warning_type == "gotify"
    Svc->>Svc: Build Gotify payload (title, text, clamp priority)
    par via worker
      Svc->>Svc: Enqueue worker job with payload
    and direct HTTP
      Svc->>Gotify: POST /message?token=... (SSRF-checked)
    end
    Gotify-->>Svc: 200/4xx
  else warning_type == "email"
    Svc->>Svc: Resolve email (settings email or user email)
    opt email exists
      Svc->>Mail: Send email
      Mail-->>Svc: Result
    end
  else warning_type == "webhook"
    Svc->>Hook: POST payload
    Hook-->>Svc: Result
  else warning_type == "bark"
    Svc->>...: Bark send (unchanged)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • feat: bark notification #1699 #1712 — Adds a notification channel (Bark) touching the same controller/DTO, service notification logic, quota paths, and settings UI patterns; closely parallel to this Gotify integration.

Suggested reviewers

  • Calcium-Ion

Poem

I hop through fields of JSON bright,
With tokens snug and URLs right,
Priority five, a gentle ping,
Gotify hums — the alerts now sing.
Thump-thump — the rabbit ships the thing. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title “feat: Add Gotify Notification Channel for Quota Alerts” clearly and concisely describes the primary change introduced by the pull request, which is the integration of a Gotify channel for sending quota alerts. It follows a conventional commit style prefix, is specific to the feature, and avoids unnecessary detail or ambiguity. The wording directly reflects the core functionality added without listing individual files or using vague terminology.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85ff8b1 and d6db10b.

📒 Files selected for processing (3)
  • web/src/components/settings/personal/cards/NotificationSettings.jsx (2 hunks)
  • web/src/i18n/locales/en.json (2 hunks)
  • web/src/i18n/locales/fr.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/src/components/settings/personal/cards/NotificationSettings.jsx
🔇 Additional comments (2)
web/src/i18n/locales/en.json (1)

1316-1357: Translations align with new Gotify/Bark settings

New strings are comprehensive and mirror the source keys without losing placeholders or guidance. No changes needed.

web/src/i18n/locales/fr.json (1)

1311-1352: French copy matches feature scope

Localized Bark/Gotify entries read naturally and preserve the required technical details. Looks good to me.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
web/src/components/settings/personal/cards/NotificationSettings.jsx (1)

648-665: Consider adding numeric input validation for priority.

The priority field uses AutoComplete with predefined values (0, 2, 5, 8, 10), but users can potentially enter custom values. Consider adding a validator to ensure the value is numeric and within the 0-10 range, consistent with the backend validation at controller/user.go lines 1270-1274.

Add validation rule:

                    <Form.AutoComplete
                      field='gotifyPriority'
                      label={t('消息优先级')}
                      placeholder={t('请选择消息优先级')}
                      data={[
                        { value: 0, label: t('0 - 最低') },
                        { value: 2, label: t('2 - 低') },
                        { value: 5, label: t('5 - 正常(默认)') },
                        { value: 8, label: t('8 - 高') },
                        { value: 10, label: t('10 - 最高') },
                      ]}
                      onChange={(val) =>
                        handleFormChange('gotifyPriority', val)
                      }
                      prefix={<IconBell />}
                      extraText={t('消息优先级,范围0-10,默认为5')}
                      style={{ width: '100%', maxWidth: '300px' }}
+                     rules={[
+                       {
+                         validator: (rule, value) => {
+                           const numValue = Number(value);
+                           if (isNaN(numValue) || numValue < 0 || numValue > 10) {
+                             return Promise.reject(t('优先级必须在0-10之间'));
+                           }
+                           return Promise.resolve();
+                         },
+                       },
+                     ]}
                    />
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 96b172e and 85ff8b1.

📒 Files selected for processing (6)
  • controller/user.go (4 hunks)
  • dto/user_settings.go (2 hunks)
  • service/quota.go (1 hunks)
  • service/user_notify.go (4 hunks)
  • web/src/components/settings/PersonalSetting.jsx (3 hunks)
  • web/src/components/settings/personal/cards/NotificationSettings.jsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
service/user_notify.go (7)
common/sys_log.go (1)
  • SysLog (11-14)
dto/user_settings.go (1)
  • NotifyTypeGotify (22-22)
setting/system_setting/system_setting_old.go (2)
  • EnableWorker (8-10)
  • WorkerValidKey (5-5)
service/download.go (2)
  • WorkerRequest (14-20)
  • DoWorkerRequest (23-49)
setting/system_setting/fetch_setting.go (1)
  • GetFetchSetting (32-34)
common/ssrf_protection.go (1)
  • ValidateURLWithFetchSetting (305-327)
service/http_client.go (1)
  • GetHttpClient (32-34)
controller/user.go (1)
dto/user_settings.go (4)
  • NotifyTypeEmail (19-19)
  • NotifyTypeWebhook (20-20)
  • NotifyTypeBark (21-21)
  • NotifyTypeGotify (22-22)
service/quota.go (2)
dto/user_settings.go (1)
  • NotifyTypeGotify (22-22)
logger/logger.go (1)
  • FormatQuota (102-108)
web/src/components/settings/personal/cards/NotificationSettings.jsx (1)
web/src/components/settings/PersonalSetting.jsx (1)
  • notificationSettings (77-89)
🔇 Additional comments (21)
dto/user_settings.go (2)

10-12: LGTM! Field definitions are correct.

The Gotify fields are properly structured:

  • GotifyUrl and GotifyToken correctly use omitempty for optional strings
  • GotifyPriority intentionally omits omitempty since 0 is a valid priority value (Gotify supports 0-10 range)

22-22: LGTM! Constant follows existing pattern.

The new NotifyTypeGotify constant aligns with the existing notification type constants.

web/src/components/settings/personal/cards/NotificationSettings.jsx (4)

403-403: LGTM! Radio option integrated correctly.

The Gotify notification option is added consistently with existing notification types.


604-627: LGTM! URL validation is comprehensive.

The Gotify URL field includes:

  • Required validation when Gotify is selected
  • Regex pattern validation for http/https schemes
  • Clear user guidance

629-646: LGTM! Token field properly validated.

The Gotify token field correctly requires input when Gotify notification type is selected.


667-698: LGTM! Excellent user guidance.

The configuration panel provides clear setup instructions and links to official documentation, improving the user experience.

service/quota.go (1)

552-559: LGTM! Content formatting differentiated appropriately.

The Gotify notification path correctly formats content as plain text (no HTML), distinct from the Email/Webhook path which includes HTML links. The message structure is clear and includes the necessary placeholder variables.

web/src/components/settings/PersonalSetting.jsx (3)

84-86: LGTM! Initial state correctly configured.

The Gotify fields are properly initialized with sensible defaults, especially gotifyPriority: 5 which aligns with Gotify's default priority level.


155-160: LGTM! Loading logic handles undefined priority correctly.

The conditional check ensures that if gotify_priority is undefined, it defaults to 5, preventing potential issues with missing values.


418-423: LGTM! Priority parsing with fallback is robust.

The save logic correctly:

  • Parses the priority to integer
  • Falls back to default value 5 if parsing fails
  • Aligns with backend validation at controller/user.go lines 1270-1274
controller/user.go (4)

1105-1107: LGTM! Request struct extended correctly.

The Gotify fields are properly added to UpdateUserSettingRequest with appropriate JSON tags and omitempty for optional fields.


1123-1123: LGTM! Notification type validation complete.

The validation now includes all four notification types: email, webhook, bark, and gotify.


1198-1230: LGTM! Gotify validation is comprehensive and consistent.

The validation block correctly:

  • Enforces required URL and token fields
  • Validates URL format using url.ParseRequestURI
  • Checks for http/https scheme prefix
  • Mirrors the validation pattern used for Bark (lines 1172-1196)

1265-1275: LGTM! Settings storage handles priority range correctly.

The Gotify settings are properly stored with:

  • URL and token assignment
  • Priority clamping to valid range (0-10) with sensible default (5)
  • Conditional application only when notification type is Gotify
service/user_notify.go (7)

4-5: LGTM!

The new imports are necessary for Gotify JSON payload marshaling and HTTP request construction.


41-51: LGTM!

The email fallback logic correctly prioritizes the notification email from settings and falls back to the user's default email, with appropriate logging when both are unavailable.


69-76: LGTM!

The Gotify case integration follows the established pattern for other notification types, with appropriate validation and error handling.


161-176: LGTM!

Placeholder replacement, URL construction, and priority clamping are implemented correctly. The priority is appropriately constrained to Gotify's 0-10 range with a sensible default.


177-194: LGTM!

The Gotify payload structure and JSON marshaling are correct and follow Gotify's API specification.


199-221: LGTM!

The worker-based sending path correctly constructs the worker request with appropriate headers, body, and error handling.


222-251: LGTM (pending User-Agent fix).

The direct HTTP path correctly applies SSRF protection, constructs the request, and validates the response. Once the User-Agent inconsistency is fixed, this implementation will be complete.

Comment thread service/user_notify.go
Method: http.MethodPost,
Headers: map[string]string{
"Content-Type": "application/json; charset=utf-8",
"User-Agent": "OneAPI-Gotify-Notify/1.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent User-Agent strings between worker and direct paths.

Line 207 uses "OneAPI-Gotify-Notify/1.0" while line 237 uses "NewAPI-Gotify-Notify/1.0". These should be consistent for proper identification and monitoring.

Apply this diff to standardize the User-Agent:

-		req.Header.Set("User-Agent", "NewAPI-Gotify-Notify/1.0")
+		req.Header.Set("User-Agent", "OneAPI-Gotify-Notify/1.0")

Also applies to: 237-237

🤖 Prompt for AI Agents
In service/user_notify.go around lines 207 and 237 the User-Agent strings are
inconsistent ("OneAPI-Gotify-Notify/1.0" vs "NewAPI-Gotify-Notify/1.0"); update
both occurrences to the same canonical value (choose one, e.g.,
"OneAPI-Gotify-Notify/1.0") so both code paths use the identical User-Agent, and
search the file/repo for any other User-Agent occurrences to standardize them as
well; after changing, run tests/lint to ensure no formatting or build issues.

@seefs001
seefs001 changed the base branch from main to alpha October 2, 2025 06:11
@seefs001
seefs001 merged commit dae661b into QuantumNous:alpha Oct 2, 2025
1 check passed
x22x22 pushed a commit to x22x22/new-api that referenced this pull request Apr 24, 2026
feat: Add Gotify Notification Channel for Quota Alerts
@coderabbitai coderabbitai Bot mentioned this pull request Apr 29, 2026
11 tasks
jiutubaba pushed a commit to jiutubaba/fx-api that referenced this pull request May 17, 2026
…ount-test-responses-stream

fix(openai): tighten responses stream account tests
@RedwindA
RedwindA deleted the feat/gotify branch July 23, 2026 07:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants