channel.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package service
  2. import (
  3. "fmt"
  4. "net/http"
  5. "one-api/common"
  6. "one-api/dto"
  7. "one-api/model"
  8. "one-api/setting/operation_setting"
  9. "strings"
  10. )
  11. func formatNotifyType(channelId int, status int) string {
  12. return fmt.Sprintf("%s_%d_%d", dto.NotifyTypeChannelUpdate, channelId, status)
  13. }
  14. // disable & notify
  15. func DisableChannel(channelId int, channelName string, reason string) {
  16. success := model.UpdateChannelStatusById(channelId, common.ChannelStatusAutoDisabled, reason)
  17. if success {
  18. subject := fmt.Sprintf("通道「%s」(#%d)已被禁用", channelName, channelId)
  19. content := fmt.Sprintf("通道「%s」(#%d)已被禁用,原因:%s", channelName, channelId, reason)
  20. NotifyRootUser(formatNotifyType(channelId, common.ChannelStatusAutoDisabled), subject, content)
  21. }
  22. }
  23. func EnableChannel(channelId int, channelName string) {
  24. success := model.UpdateChannelStatusById(channelId, common.ChannelStatusEnabled, "")
  25. if success {
  26. subject := fmt.Sprintf("通道「%s」(#%d)已被启用", channelName, channelId)
  27. content := fmt.Sprintf("通道「%s」(#%d)已被启用", channelName, channelId)
  28. NotifyRootUser(formatNotifyType(channelId, common.ChannelStatusEnabled), subject, content)
  29. }
  30. }
  31. func ShouldDisableChannel(channelType int, err *dto.OpenAIErrorWithStatusCode) bool {
  32. if !common.AutomaticDisableChannelEnabled {
  33. return false
  34. }
  35. if err == nil {
  36. return false
  37. }
  38. if err.LocalError {
  39. return false
  40. }
  41. if err.StatusCode == http.StatusUnauthorized {
  42. return true
  43. }
  44. if err.StatusCode == http.StatusForbidden {
  45. switch channelType {
  46. case common.ChannelTypeGemini:
  47. return true
  48. }
  49. }
  50. switch err.Error.Code {
  51. case "invalid_api_key":
  52. return true
  53. case "account_deactivated":
  54. return true
  55. case "billing_not_active":
  56. return true
  57. }
  58. switch err.Error.Type {
  59. case "insufficient_quota":
  60. return true
  61. case "insufficient_user_quota":
  62. return true
  63. // https://docs.anthropic.com/claude/reference/errors
  64. case "authentication_error":
  65. return true
  66. case "permission_error":
  67. return true
  68. case "forbidden":
  69. return true
  70. }
  71. lowerMessage := strings.ToLower(err.Error.Message)
  72. search, _ := AcSearch(lowerMessage, operation_setting.AutomaticDisableKeywords, true)
  73. if search {
  74. return true
  75. }
  76. return false
  77. }
  78. func ShouldEnableChannel(err error, openaiWithStatusErr *dto.OpenAIErrorWithStatusCode, status int) bool {
  79. if !common.AutomaticEnableChannelEnabled {
  80. return false
  81. }
  82. if err != nil {
  83. return false
  84. }
  85. if openaiWithStatusErr != nil {
  86. return false
  87. }
  88. if status != common.ChannelStatusAutoDisabled {
  89. return false
  90. }
  91. return true
  92. }