Merge remote-tracking branch 'origin/main'

This commit is contained in:
1808837298@qq.com
2025-02-01 13:41:38 +08:00
3 changed files with 99 additions and 8 deletions

View File

@@ -78,6 +78,36 @@ type APGC2DGPTUsageResponse struct {
TotalUsed float64 `json:"total_used"` TotalUsed float64 `json:"total_used"`
} }
type SiliconFlowUsageResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Status bool `json:"status"`
Data struct {
ID string `json:"id"`
Name string `json:"name"`
Image string `json:"image"`
Email string `json:"email"`
IsAdmin bool `json:"isAdmin"`
Balance string `json:"balance"`
Status string `json:"status"`
Introduction string `json:"introduction"`
Role string `json:"role"`
ChargeBalance string `json:"chargeBalance"`
TotalBalance string `json:"totalBalance"`
Category string `json:"category"`
} `json:"data"`
}
type DeepSeekUsageResponse struct {
IsAvailable bool `json:"is_available"`
BalanceInfos []struct {
Currency string `json:"currency"`
TotalBalance string `json:"total_balance"`
GrantedBalance string `json:"granted_balance"`
ToppedUpBalance string `json:"topped_up_balance"`
} `json:"balance_infos"`
}
// GetAuthHeader get auth header // GetAuthHeader get auth header
func GetAuthHeader(token string) http.Header { func GetAuthHeader(token string) http.Header {
h := http.Header{} h := http.Header{}
@@ -185,6 +215,57 @@ func updateChannelAPI2GPTBalance(channel *model.Channel) (float64, error) {
return response.TotalRemaining, nil return response.TotalRemaining, nil
} }
func updateChannelSiliconFlowBalance(channel *model.Channel) (float64, error) {
url := "https://api.siliconflow.cn/v1/user/info"
body, err := GetResponseBody("GET", url, channel, GetAuthHeader(channel.Key))
if err != nil {
return 0, err
}
response := SiliconFlowUsageResponse{}
err = json.Unmarshal(body, &response)
if err != nil {
return 0, err
}
if response.Code != 20000 {
return 0, fmt.Errorf("code: %d, message: %s", response.Code, response.Message)
}
balance, err := strconv.ParseFloat(response.Data.TotalBalance, 64)
if err != nil {
return 0, err
}
channel.UpdateBalance(balance)
return balance, nil
}
func updateChannelDeepSeekBalance(channel *model.Channel) (float64, error) {
url := "https://api.deepseek.com/user/balance"
body, err := GetResponseBody("GET", url, channel, GetAuthHeader(channel.Key))
if err != nil {
return 0, err
}
response := DeepSeekUsageResponse{}
err = json.Unmarshal(body, &response)
if err != nil {
return 0, err
}
index := -1
for i, balanceInfo := range response.BalanceInfos {
if balanceInfo.Currency == "CNY" {
index = i
break
}
}
if index == -1 {
return 0, errors.New("currency CNY not found")
}
balance, err := strconv.ParseFloat(response.BalanceInfos[index].TotalBalance, 64)
if err != nil {
return 0, err
}
channel.UpdateBalance(balance)
return balance, nil
}
func updateChannelAIGC2DBalance(channel *model.Channel) (float64, error) { func updateChannelAIGC2DBalance(channel *model.Channel) (float64, error) {
url := "https://api.aigc2d.com/dashboard/billing/credit_grants" url := "https://api.aigc2d.com/dashboard/billing/credit_grants"
body, err := GetResponseBody("GET", url, channel, GetAuthHeader(channel.Key)) body, err := GetResponseBody("GET", url, channel, GetAuthHeader(channel.Key))
@@ -222,6 +303,10 @@ func updateChannelBalance(channel *model.Channel) (float64, error) {
return updateChannelAPI2GPTBalance(channel) return updateChannelAPI2GPTBalance(channel)
case common.ChannelTypeAIGC2D: case common.ChannelTypeAIGC2D:
return updateChannelAIGC2DBalance(channel) return updateChannelAIGC2DBalance(channel)
case common.ChannelTypeSiliconFlow:
return updateChannelSiliconFlowBalance(channel)
case common.ChannelTypeDeepSeek:
return updateChannelDeepSeekBalance(channel)
default: default:
return 0, errors.New("尚未实现") return 0, errors.New("尚未实现")
} }
@@ -300,9 +385,9 @@ func updateAllChannelsBalance() error {
continue continue
} }
// TODO: support Azure // TODO: support Azure
if channel.Type != common.ChannelTypeOpenAI && channel.Type != common.ChannelTypeCustom { //if channel.Type != common.ChannelTypeOpenAI && channel.Type != common.ChannelTypeCustom {
continue // continue
} //}
balance, err := updateChannelBalance(channel) balance, err := updateChannelBalance(channel)
if err != nil { if err != nil {
continue continue

View File

@@ -510,6 +510,7 @@ func UpdateChannel(c *gin.Context) {
func FetchModels(c *gin.Context) { func FetchModels(c *gin.Context) {
var req struct { var req struct {
BaseURL string `json:"base_url"` BaseURL string `json:"base_url"`
Type int `json:"type"`
Key string `json:"key"` Key string `json:"key"`
} }
@@ -523,7 +524,7 @@ func FetchModels(c *gin.Context) {
baseURL := req.BaseURL baseURL := req.BaseURL
if baseURL == "" { if baseURL == "" {
baseURL = "https://api.openai.com" baseURL = common.ChannelBaseURLs[req.Type]
} }
client := &http.Client{} client := &http.Client{}
@@ -538,7 +539,11 @@ func FetchModels(c *gin.Context) {
return return
} }
request.Header.Set("Authorization", "Bearer "+req.Key) // remove line breaks and extra spaces.
key := strings.TrimSpace(req.Key)
// If the key contains a line break, only take the first part.
key = strings.Split(key, "\n")[0]
request.Header.Set("Authorization", "Bearer "+key)
response, err := client.Do(request) response, err := client.Do(request)
if err != nil { if err != nil {

View File

@@ -218,6 +218,7 @@ const EditChannel = (props) => {
try { try {
const res = await API.post('/api/channel/fetch_models', { const res = await API.post('/api/channel/fetch_models', {
base_url: inputs['base_url'], base_url: inputs['base_url'],
type: inputs['type'],
key: inputs['key'] key: inputs['key']
}); });
@@ -885,7 +886,7 @@ const EditChannel = (props) => {
</Typography.Text> </Typography.Text>
</div> </div>
<TextArea <TextArea
placeholder={t('此项可选用于复写返回的状态码比如将claude渠道的400错误复写为500用于重试请勿滥用该功能例如') + placeholder={t('此项可选用于复写返回的状态码比如将claude渠道的400错误复写为500用于重试请勿滥用该功能例如') +
'\n' + JSON.stringify(STATUS_CODE_MAPPING_EXAMPLE, null, 2)} '\n' + JSON.stringify(STATUS_CODE_MAPPING_EXAMPLE, null, 2)}
name="status_code_mapping" name="status_code_mapping"
onChange={(value) => { onChange={(value) => {
@@ -984,7 +985,7 @@ const EditChannel = (props) => {
/> />
<Typography.Text <Typography.Text
style={{ style={{
color: 'rgba(var(--semi-blue-5), 1)', color: 'rgba(var(--semi-blue-5), 1)',
userSelect: 'none', userSelect: 'none',
cursor: 'pointer' cursor: 'pointer'
}} }}
@@ -1000,7 +1001,7 @@ const EditChannel = (props) => {
{t('填入模板')} {t('填入模板')}
</Typography.Text> </Typography.Text>
</> </>
)} )}
</Spin> </Spin>
</SideSheet> </SideSheet>
</> </>