Publish Docker image (Multi-arch) / Build & push (amd64) (push) Failing after 1m40s
Release (Linux, macOS, Windows) / Linux Release (push) Failing after 42m16s
Publish Docker image (Multi-arch) / Build & push (arm64) (push) Canceled after 0s
Release (Linux, macOS, Windows) / macOS Release (push) Canceled after 0s
Release (Linux, macOS, Windows) / Windows Release (push) Canceled after 0s
Publish Docker image (Multi-arch) / Create multi-arch manifests (push) Canceled after 0s
Sync production source including routing, billing, Astra detection and public uptime. Update custom build instructions and license packaging.
91 lines
3.1 KiB
Go
91 lines
3.1 KiB
Go
package service
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/QuantumNous/new-api/common"
|
|
"github.com/QuantumNous/new-api/model"
|
|
"github.com/QuantumNous/new-api/relaykit/dto"
|
|
"github.com/QuantumNous/new-api/relaykit/types"
|
|
"github.com/QuantumNous/new-api/setting/operation_setting"
|
|
)
|
|
|
|
func formatNotifyType(channelId int, status int) string {
|
|
return fmt.Sprintf("%s_%d_%d", dto.NotifyTypeChannelUpdate, channelId, status)
|
|
}
|
|
|
|
func shouldCloseActiveWebSocketsAfterDisable(channelId int) bool {
|
|
channel, err := model.GetChannelById(channelId, true)
|
|
if err != nil {
|
|
common.SysLog(fmt.Sprintf("failed to check channel status before closing active websockets: channel_id=%d, error=%v", channelId, err))
|
|
return true
|
|
}
|
|
return channel.Status != common.ChannelStatusEnabled
|
|
}
|
|
|
|
// disable & notify
|
|
func DisableChannel(channelError types.ChannelError, reason string) {
|
|
common.SysLog(fmt.Sprintf("通道「%s」(#%d)发生错误,准备禁用,原因:%s", channelError.ChannelName, channelError.ChannelId, common.LocalLogPreview(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 {
|
|
if shouldCloseActiveWebSocketsAfterDisable(channelError.ChannelId) {
|
|
CloseActiveWebSocketsForChannel(channelError.ChannelId, ChannelDisabledCloseReason)
|
|
}
|
|
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(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
|
|
}
|
|
|
|
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
|
|
}
|