diff --git a/common/requester/http_requester.go b/common/requester/http_requester.go
index 57808ac7..8f7e5dd0 100644
--- a/common/requester/http_requester.go
+++ b/common/requester/http_requester.go
@@ -187,11 +187,12 @@ func HandleErrorResp(resp *http.Response, toOpenAIError HttpErrorHandler) *types
if errorResponse != nil && errorResponse.Message != "" {
openAIErrorWithStatusCode.OpenAIError = *errorResponse
+ openAIErrorWithStatusCode.OpenAIError.Message = fmt.Sprintf("Provider API error: %s", openAIErrorWithStatusCode.OpenAIError.Message)
}
}
if openAIErrorWithStatusCode.OpenAIError.Message == "" {
- openAIErrorWithStatusCode.OpenAIError.Message = fmt.Sprintf("bad response status code %d", resp.StatusCode)
+ openAIErrorWithStatusCode.OpenAIError.Message = fmt.Sprintf("Provider API error: bad response status code %d", resp.StatusCode)
}
return openAIErrorWithStatusCode
diff --git a/common/token.go b/common/token.go
index bb092ce7..a2774000 100644
--- a/common/token.go
+++ b/common/token.go
@@ -26,7 +26,7 @@ func InitTokenEncoders() {
if err != nil {
FatalLog(fmt.Sprintf("failed to get gpt-4 token encoder: %s", err.Error()))
}
- for model, _ := range ModelRatio {
+ for model := range ModelRatio {
if strings.HasPrefix(model, "gpt-3.5") {
tokenEncoderMap[model] = gpt35TokenEncoder
} else if strings.HasPrefix(model, "gpt-4") {
diff --git a/model/channel.go b/model/channel.go
index 608e67ad..30a3f61a 100644
--- a/model/channel.go
+++ b/model/channel.go
@@ -262,6 +262,8 @@ func DeleteChannelByStatus(status int64) (int64, error) {
func DeleteDisabledChannel() (int64, error) {
result := DB.Where("status = ? or status = ?", common.ChannelStatusAutoDisabled, common.ChannelStatusManuallyDisabled).Delete(&Channel{})
+ // 同时删除Ability
+ DB.Where("enabled = ?", false).Delete(&Ability{})
return result.RowsAffected, result.Error
}
diff --git a/model/option.go b/model/option.go
index 730a46fb..084427f4 100644
--- a/model/option.go
+++ b/model/option.go
@@ -134,112 +134,83 @@ func UpdateOption(key string, value string) error {
return updateOptionMap(key, value)
}
+var optionIntMap = map[string]*int{
+ "FileUploadPermission": &common.FileUploadPermission,
+ "FileDownloadPermission": &common.FileDownloadPermission,
+ "ImageUploadPermission": &common.ImageUploadPermission,
+ "ImageDownloadPermission": &common.ImageDownloadPermission,
+ "SMTPPort": &common.SMTPPort,
+ "QuotaForNewUser": &common.QuotaForNewUser,
+ "QuotaForInviter": &common.QuotaForInviter,
+ "QuotaForInvitee": &common.QuotaForInvitee,
+ "QuotaRemindThreshold": &common.QuotaRemindThreshold,
+ "PreConsumedQuota": &common.PreConsumedQuota,
+ "RetryTimes": &common.RetryTimes,
+}
+
+var optionBoolMap = map[string]*bool{
+ "PasswordRegisterEnabled": &common.PasswordRegisterEnabled,
+ "PasswordLoginEnabled": &common.PasswordLoginEnabled,
+ "EmailVerificationEnabled": &common.EmailVerificationEnabled,
+ "GitHubOAuthEnabled": &common.GitHubOAuthEnabled,
+ "WeChatAuthEnabled": &common.WeChatAuthEnabled,
+ "TurnstileCheckEnabled": &common.TurnstileCheckEnabled,
+ "RegisterEnabled": &common.RegisterEnabled,
+ "EmailDomainRestrictionEnabled": &common.EmailDomainRestrictionEnabled,
+ "AutomaticDisableChannelEnabled": &common.AutomaticDisableChannelEnabled,
+ "AutomaticEnableChannelEnabled": &common.AutomaticEnableChannelEnabled,
+ "ApproximateTokenEnabled": &common.ApproximateTokenEnabled,
+ "LogConsumeEnabled": &common.LogConsumeEnabled,
+ "DisplayInCurrencyEnabled": &common.DisplayInCurrencyEnabled,
+ "DisplayTokenStatEnabled": &common.DisplayTokenStatEnabled,
+}
+
+var optionStringMap = map[string]*string{
+ "SMTPServer": &common.SMTPServer,
+ "SMTPAccount": &common.SMTPAccount,
+ "SMTPFrom": &common.SMTPFrom,
+ "SMTPToken": &common.SMTPToken,
+ "ServerAddress": &common.ServerAddress,
+ "GitHubClientId": &common.GitHubClientId,
+ "GitHubClientSecret": &common.GitHubClientSecret,
+ "Footer": &common.Footer,
+ "SystemName": &common.SystemName,
+ "Logo": &common.Logo,
+ "WeChatServerAddress": &common.WeChatServerAddress,
+ "WeChatServerToken": &common.WeChatServerToken,
+ "WeChatAccountQRCodeImageURL": &common.WeChatAccountQRCodeImageURL,
+ "TurnstileSiteKey": &common.TurnstileSiteKey,
+ "TurnstileSecretKey": &common.TurnstileSecretKey,
+ "TopUpLink": &common.TopUpLink,
+ "ChatLink": &common.ChatLink,
+}
+
func updateOptionMap(key string, value string) (err error) {
common.OptionMapRWMutex.Lock()
defer common.OptionMapRWMutex.Unlock()
common.OptionMap[key] = value
- if strings.HasSuffix(key, "Permission") {
- intValue, _ := strconv.Atoi(value)
- switch key {
- case "FileUploadPermission":
- common.FileUploadPermission = intValue
- case "FileDownloadPermission":
- common.FileDownloadPermission = intValue
- case "ImageUploadPermission":
- common.ImageUploadPermission = intValue
- case "ImageDownloadPermission":
- common.ImageDownloadPermission = intValue
- }
+ if ptr, ok := optionIntMap[key]; ok {
+ *ptr, _ = strconv.Atoi(value)
+ return
}
- if strings.HasSuffix(key, "Enabled") {
- boolValue := value == "true"
- switch key {
- case "PasswordRegisterEnabled":
- common.PasswordRegisterEnabled = boolValue
- case "PasswordLoginEnabled":
- common.PasswordLoginEnabled = boolValue
- case "EmailVerificationEnabled":
- common.EmailVerificationEnabled = boolValue
- case "GitHubOAuthEnabled":
- common.GitHubOAuthEnabled = boolValue
- case "WeChatAuthEnabled":
- common.WeChatAuthEnabled = boolValue
- case "TurnstileCheckEnabled":
- common.TurnstileCheckEnabled = boolValue
- case "RegisterEnabled":
- common.RegisterEnabled = boolValue
- case "EmailDomainRestrictionEnabled":
- common.EmailDomainRestrictionEnabled = boolValue
- case "AutomaticDisableChannelEnabled":
- common.AutomaticDisableChannelEnabled = boolValue
- case "AutomaticEnableChannelEnabled":
- common.AutomaticEnableChannelEnabled = boolValue
- case "ApproximateTokenEnabled":
- common.ApproximateTokenEnabled = boolValue
- case "LogConsumeEnabled":
- common.LogConsumeEnabled = boolValue
- case "DisplayInCurrencyEnabled":
- common.DisplayInCurrencyEnabled = boolValue
- case "DisplayTokenStatEnabled":
- common.DisplayTokenStatEnabled = boolValue
- }
+
+ if ptr, ok := optionBoolMap[key]; ok {
+ *ptr = value == "true"
+ return
}
+
+ if ptr, ok := optionStringMap[key]; ok {
+ *ptr = value
+ return
+ }
+
switch key {
case "EmailDomainWhitelist":
common.EmailDomainWhitelist = strings.Split(value, ",")
- case "SMTPServer":
- common.SMTPServer = value
- case "SMTPPort":
- intValue, _ := strconv.Atoi(value)
- common.SMTPPort = intValue
- case "SMTPAccount":
- common.SMTPAccount = value
- case "SMTPFrom":
- common.SMTPFrom = value
- case "SMTPToken":
- common.SMTPToken = value
- case "ServerAddress":
- common.ServerAddress = value
- case "GitHubClientId":
- common.GitHubClientId = value
- case "GitHubClientSecret":
- common.GitHubClientSecret = value
- case "Footer":
- common.Footer = value
- case "SystemName":
- common.SystemName = value
- case "Logo":
- common.Logo = value
- case "WeChatServerAddress":
- common.WeChatServerAddress = value
- case "WeChatServerToken":
- common.WeChatServerToken = value
- case "WeChatAccountQRCodeImageURL":
- common.WeChatAccountQRCodeImageURL = value
- case "TurnstileSiteKey":
- common.TurnstileSiteKey = value
- case "TurnstileSecretKey":
- common.TurnstileSecretKey = value
- case "QuotaForNewUser":
- common.QuotaForNewUser, _ = strconv.Atoi(value)
- case "QuotaForInviter":
- common.QuotaForInviter, _ = strconv.Atoi(value)
- case "QuotaForInvitee":
- common.QuotaForInvitee, _ = strconv.Atoi(value)
- case "QuotaRemindThreshold":
- common.QuotaRemindThreshold, _ = strconv.Atoi(value)
- case "PreConsumedQuota":
- common.PreConsumedQuota, _ = strconv.Atoi(value)
- case "RetryTimes":
- common.RetryTimes, _ = strconv.Atoi(value)
case "ModelRatio":
err = common.UpdateModelRatioByJSONString(value)
case "GroupRatio":
err = common.UpdateGroupRatioByJSONString(value)
- case "TopUpLink":
- common.TopUpLink = value
- case "ChatLink":
- common.ChatLink = value
case "ChannelDisableThreshold":
common.ChannelDisableThreshold, _ = strconv.ParseFloat(value, 64)
case "QuotaPerUnit":
diff --git a/model/token.go b/model/token.go
index 1e4e3123..11f10d1f 100644
--- a/model/token.go
+++ b/model/token.go
@@ -215,24 +215,7 @@ func PreConsumeTokenQuota(tokenId int, quota int) (err error) {
quotaTooLow := userQuota >= common.QuotaRemindThreshold && userQuota-quota < common.QuotaRemindThreshold
noMoreQuota := userQuota-quota <= 0
if quotaTooLow || noMoreQuota {
- go func() {
- email, err := GetUserEmail(token.UserId)
- if err != nil {
- common.SysError("failed to fetch user email: " + err.Error())
- }
- prompt := "您的额度即将用尽"
- if noMoreQuota {
- prompt = "您的额度已用尽"
- }
- if email != "" {
- topUpLink := fmt.Sprintf("%s/topup", common.ServerAddress)
- err = common.SendEmail(prompt, email,
- fmt.Sprintf("%s,当前剩余额度为 %d,为了不影响您的使用,请及时充值。
充值链接:%s", prompt, userQuota, topUpLink, topUpLink))
- if err != nil {
- common.SysError("failed to send email" + err.Error())
- }
- }
- }()
+ go sendQuotaWarningEmail(token.UserId, userQuota, noMoreQuota)
}
if !token.UnlimitedQuota {
err = DecreaseTokenQuota(tokenId, quota)
@@ -244,6 +227,25 @@ func PreConsumeTokenQuota(tokenId int, quota int) (err error) {
return err
}
+func sendQuotaWarningEmail(userId int, userQuota int, noMoreQuota bool) {
+ email, err := GetUserEmail(userId)
+ if err != nil {
+ common.SysError("failed to fetch user email: " + err.Error())
+ }
+ prompt := "您的额度即将用尽"
+ if noMoreQuota {
+ prompt = "您的额度已用尽"
+ }
+ if email != "" {
+ topUpLink := fmt.Sprintf("%s/topup", common.ServerAddress)
+ err = common.SendEmail(prompt, email,
+ fmt.Sprintf("%s,当前剩余额度为 %d,为了不影响您的使用,请及时充值。
充值链接:%s", prompt, userQuota, topUpLink, topUpLink))
+ if err != nil {
+ common.SysError("failed to send email" + err.Error())
+ }
+ }
+}
+
func PostConsumeTokenQuota(tokenId int, quota int) (err error) {
token, err := GetTokenById(tokenId)
if quota > 0 {
diff --git a/providers/minimax/chat.go b/providers/minimax/chat.go
index b17e40bc..c75b46ab 100644
--- a/providers/minimax/chat.go
+++ b/providers/minimax/chat.go
@@ -153,7 +153,7 @@ func convertFromChatOpenai(request *types.ChatCompletionRequest) *MiniMaxChatReq
}
messges[len(messges)-1].FunctionCall = &types.ChatCompletionToolCallsFunction{
- Name: "funciton",
+ Name: "function",
Arguments: "arguments",
}
}