user_notify.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package service
  2. import (
  3. "fmt"
  4. "net/http"
  5. "net/url"
  6. "one-api/common"
  7. "one-api/dto"
  8. "one-api/model"
  9. "one-api/setting/system_setting"
  10. "strings"
  11. )
  12. func NotifyRootUser(t string, subject string, content string) {
  13. user := model.GetRootUser().ToBaseUser()
  14. err := NotifyUser(user.Id, user.Email, user.GetSetting(), dto.NewNotify(t, subject, content, nil))
  15. if err != nil {
  16. common.SysLog(fmt.Sprintf("failed to notify root user: %s", err.Error()))
  17. }
  18. }
  19. func NotifyUser(userId int, userEmail string, userSetting dto.UserSetting, data dto.Notify) error {
  20. notifyType := userSetting.NotifyType
  21. if notifyType == "" {
  22. notifyType = dto.NotifyTypeEmail
  23. }
  24. // Check notification limit
  25. canSend, err := CheckNotificationLimit(userId, data.Type)
  26. if err != nil {
  27. common.SysLog(fmt.Sprintf("failed to check notification limit: %s", err.Error()))
  28. return err
  29. }
  30. if !canSend {
  31. return fmt.Errorf("notification limit exceeded for user %d with type %s", userId, notifyType)
  32. }
  33. switch notifyType {
  34. case dto.NotifyTypeEmail:
  35. // check setting email
  36. userEmail = userSetting.NotificationEmail
  37. if userEmail == "" {
  38. common.SysLog(fmt.Sprintf("user %d has no email, skip sending email", userId))
  39. return nil
  40. }
  41. return sendEmailNotify(userEmail, data)
  42. case dto.NotifyTypeWebhook:
  43. webhookURLStr := userSetting.WebhookUrl
  44. if webhookURLStr == "" {
  45. common.SysLog(fmt.Sprintf("user %d has no webhook url, skip sending webhook", userId))
  46. return nil
  47. }
  48. // 获取 webhook secret
  49. webhookSecret := userSetting.WebhookSecret
  50. return SendWebhookNotify(webhookURLStr, webhookSecret, data)
  51. case dto.NotifyTypeBark:
  52. barkURL := userSetting.BarkUrl
  53. if barkURL == "" {
  54. common.SysLog(fmt.Sprintf("user %d has no bark url, skip sending bark", userId))
  55. return nil
  56. }
  57. return sendBarkNotify(barkURL, data)
  58. }
  59. return nil
  60. }
  61. func sendEmailNotify(userEmail string, data dto.Notify) error {
  62. // make email content
  63. content := data.Content
  64. // 处理占位符
  65. for _, value := range data.Values {
  66. content = strings.Replace(content, dto.ContentValueParam, fmt.Sprintf("%v", value), 1)
  67. }
  68. return common.SendEmail(data.Title, userEmail, content)
  69. }
  70. func sendBarkNotify(barkURL string, data dto.Notify) error {
  71. // 处理占位符
  72. content := data.Content
  73. for _, value := range data.Values {
  74. content = strings.Replace(content, dto.ContentValueParam, fmt.Sprintf("%v", value), 1)
  75. }
  76. // 替换模板变量
  77. finalURL := strings.ReplaceAll(barkURL, "{{title}}", url.QueryEscape(data.Title))
  78. finalURL = strings.ReplaceAll(finalURL, "{{content}}", url.QueryEscape(content))
  79. // 发送GET请求到Bark
  80. var req *http.Request
  81. var resp *http.Response
  82. var err error
  83. if system_setting.EnableWorker() {
  84. // 使用worker发送请求
  85. workerReq := &WorkerRequest{
  86. URL: finalURL,
  87. Key: system_setting.WorkerValidKey,
  88. Method: http.MethodGet,
  89. Headers: map[string]string{
  90. "User-Agent": "OneAPI-Bark-Notify/1.0",
  91. },
  92. }
  93. resp, err = DoWorkerRequest(workerReq)
  94. if err != nil {
  95. return fmt.Errorf("failed to send bark request through worker: %v", err)
  96. }
  97. defer resp.Body.Close()
  98. // 检查响应状态
  99. if resp.StatusCode < 200 || resp.StatusCode >= 300 {
  100. return fmt.Errorf("bark request failed with status code: %d", resp.StatusCode)
  101. }
  102. } else {
  103. // 直接发送请求
  104. req, err = http.NewRequest(http.MethodGet, finalURL, nil)
  105. if err != nil {
  106. return fmt.Errorf("failed to create bark request: %v", err)
  107. }
  108. // 设置User-Agent
  109. req.Header.Set("User-Agent", "OneAPI-Bark-Notify/1.0")
  110. // 发送请求
  111. client := GetHttpClient()
  112. resp, err = client.Do(req)
  113. if err != nil {
  114. return fmt.Errorf("failed to send bark request: %v", err)
  115. }
  116. defer resp.Body.Close()
  117. // 检查响应状态
  118. if resp.StatusCode < 200 || resp.StatusCode >= 300 {
  119. return fmt.Errorf("bark request failed with status code: %d", resp.StatusCode)
  120. }
  121. }
  122. return nil
  123. }