| package service |
|
|
| import ( |
| "fmt" |
| "net/http" |
| "strings" |
|
|
| "github.com/QuantumNous/new-api/common" |
| "github.com/QuantumNous/new-api/constant" |
| "github.com/QuantumNous/new-api/dto" |
| "github.com/QuantumNous/new-api/model" |
| "github.com/QuantumNous/new-api/setting/operation_setting" |
| "github.com/QuantumNous/new-api/types" |
| ) |
|
|
| func formatNotifyType(channelId int, status int) string { |
| return fmt.Sprintf("%s_%d_%d", dto.NotifyTypeChannelUpdate, channelId, status) |
| } |
|
|
| |
| func DisableChannel(channelError types.ChannelError, reason string) { |
| common.SysLog(fmt.Sprintf("通道「%s」(#%d)发生错误,准备禁用,原因:%s", channelError.ChannelName, channelError.ChannelId, reason)) |
|
|
| |
| if !channelError.AutoBan { |
| common.SysLog(fmt.Sprintf("通道「%s」(#%d)未启用自动禁用功能,跳过禁用操作", channelError.ChannelName, channelError.ChannelId)) |
| return |
| } |
|
|
| success := model.UpdateChannelStatus(channelError.ChannelId, channelError.UsingKey, common.ChannelStatusAutoDisabled, reason) |
| if success { |
| subject := fmt.Sprintf("通道「%s」(#%d)已被禁用", channelError.ChannelName, channelError.ChannelId) |
| content := fmt.Sprintf("通道「%s」(#%d)已被禁用,原因:%s", channelError.ChannelName, channelError.ChannelId, reason) |
| NotifyRootUser(formatNotifyType(channelError.ChannelId, common.ChannelStatusAutoDisabled), subject, content) |
| } |
| } |
|
|
| func EnableChannel(channelId int, usingKey string, channelName string) { |
| success := model.UpdateChannelStatus(channelId, usingKey, common.ChannelStatusEnabled, "") |
| if success { |
| subject := fmt.Sprintf("通道「%s」(#%d)已被启用", channelName, channelId) |
| content := fmt.Sprintf("通道「%s」(#%d)已被启用", channelName, channelId) |
| NotifyRootUser(formatNotifyType(channelId, common.ChannelStatusEnabled), subject, content) |
| } |
| } |
|
|
| func ShouldDisableChannel(channelType int, err *types.NewAPIError) bool { |
| if !common.AutomaticDisableChannelEnabled { |
| return false |
| } |
| if err == nil { |
| return false |
| } |
| if types.IsChannelError(err) { |
| return true |
| } |
| if types.IsSkipRetryError(err) { |
| return false |
| } |
| if operation_setting.ShouldDisableByStatusCode(err.StatusCode) { |
| return true |
| } |
| |
| |
| |
| if err.StatusCode == http.StatusForbidden { |
| switch channelType { |
| case constant.ChannelTypeGemini: |
| return true |
| } |
| } |
| oaiErr := err.ToOpenAIError() |
| switch oaiErr.Code { |
| case "invalid_api_key": |
| return true |
| case "account_deactivated": |
| return true |
| case "billing_not_active": |
| return true |
| case "pre_consume_token_quota_failed": |
| return true |
| case "Arrearage": |
| return true |
| } |
| switch oaiErr.Type { |
| case "insufficient_quota": |
| return true |
| case "insufficient_user_quota": |
| return true |
| |
| case "authentication_error": |
| return true |
| case "permission_error": |
| return true |
| case "forbidden": |
| return true |
| } |
|
|
| lowerMessage := strings.ToLower(err.Error()) |
| search, _ := AcSearch(lowerMessage, operation_setting.AutomaticDisableKeywords, true) |
| return search |
| } |
|
|
| func ShouldEnableChannel(newAPIError *types.NewAPIError, status int) bool { |
| if !common.AutomaticEnableChannelEnabled { |
| return false |
| } |
| if newAPIError != nil { |
| return false |
| } |
| if status != common.ChannelStatusAutoDisabled { |
| return false |
| } |
| return true |
| } |
|
|