diff --git a/README.md b/README.md
index c54450ee..9280a347 100644
--- a/README.md
+++ b/README.md
@@ -66,6 +66,7 @@ _✨ All in one 的 OpenAI 接口,整合各种 API 访问方式,开箱即用
+ [x] [API2D](https://api2d.com/r/197971)
+ [x] [OhMyGPT](https://aigptx.top?aff=uFpUl2Kf)
+ [x] [AI Proxy](https://aiproxy.io/?i=OneAPI) (邀请码:`OneAPI`)
+ + [x] [CloseAI](https://console.closeai-asia.com/r/2412)
+ [x] 自定义渠道:例如各种未收录的第三方代理服务
2. 支持通过**负载均衡**的方式访问多个渠道。
3. 支持 **stream 模式**,可以通过流式传输实现打字机效果。
diff --git a/common/constants.go b/common/constants.go
index a850b3e8..08754213 100644
--- a/common/constants.go
+++ b/common/constants.go
@@ -152,18 +152,18 @@ const (
)
var ChannelBaseURLs = []string{
- "", // 0
- "https://api.openai.com", // 1
- "https://oa.api2d.net", // 2
- "", // 3
- "https://api.openai-proxy.org", // 4
- "https://api.openai-sb.com", // 5
- "https://api.openaimax.com", // 6
- "https://api.ohmygpt.com", // 7
- "", // 8
- "https://api.caipacity.com", // 9
- "https://api.aiproxy.io", // 10
- "", // 11
- "https://api.api2gpt.com", // 12
- "https://api.aigc2d.com", // 13
+ "", // 0
+ "https://api.openai.com", // 1
+ "https://oa.api2d.net", // 2
+ "", // 3
+ "https://api.closeai-proxy.xyz", // 4
+ "https://api.openai-sb.com", // 5
+ "https://api.openaimax.com", // 6
+ "https://api.ohmygpt.com", // 7
+ "", // 8
+ "https://api.caipacity.com", // 9
+ "https://api.aiproxy.io", // 10
+ "", // 11
+ "https://api.api2gpt.com", // 12
+ "https://api.aigc2d.com", // 13
}
diff --git a/controller/channel-billing.go b/controller/channel-billing.go
index 4026e583..31c9a133 100644
--- a/controller/channel-billing.go
+++ b/controller/channel-billing.go
@@ -32,6 +32,13 @@ type OpenAIUsageDailyCost struct {
}
}
+type OpenAICreditGrants struct {
+ Object string `json:"object"`
+ TotalGranted float64 `json:"total_granted"`
+ TotalUsed float64 `json:"total_used"`
+ TotalAvailable float64 `json:"total_available"`
+}
+
type OpenAIUsageResponse struct {
Object string `json:"object"`
//DailyCosts []OpenAIUsageDailyCost `json:"daily_costs"`
@@ -100,6 +107,22 @@ func GetResponseBody(method, url string, channel *model.Channel, headers http.He
return body, nil
}
+func updateChannelCloseAIBalance(channel *model.Channel) (float64, error) {
+ url := fmt.Sprintf("%s/dashboard/billing/credit_grants", channel.BaseURL)
+ body, err := GetResponseBody("GET", url, channel, GetAuthHeader(channel.Key))
+
+ if err != nil {
+ return 0, err
+ }
+ response := OpenAICreditGrants{}
+ err = json.Unmarshal(body, &response)
+ if err != nil {
+ return 0, err
+ }
+ channel.UpdateBalance(response.TotalAvailable)
+ return response.TotalAvailable, nil
+}
+
func updateChannelOpenAISBBalance(channel *model.Channel) (float64, error) {
url := fmt.Sprintf("https://api.openai-sb.com/sb-api/user/status?api_key=%s", channel.Key)
body, err := GetResponseBody("GET", url, channel, GetAuthHeader(channel.Key))
@@ -175,6 +198,9 @@ func updateChannelAIGC2DBalance(channel *model.Channel) (float64, error) {
func updateChannelBalance(channel *model.Channel) (float64, error) {
baseURL := common.ChannelBaseURLs[channel.Type]
+ if channel.BaseURL == "" {
+ channel.BaseURL = baseURL
+ }
switch channel.Type {
case common.ChannelTypeOpenAI:
if channel.BaseURL != "" {
@@ -184,6 +210,8 @@ func updateChannelBalance(channel *model.Channel) (float64, error) {
return 0, errors.New("尚未实现")
case common.ChannelTypeCustom:
baseURL = channel.BaseURL
+ case common.ChannelTypeCloseAI:
+ return updateChannelCloseAIBalance(channel)
case common.ChannelTypeOpenAISB:
return updateChannelOpenAISBBalance(channel)
case common.ChannelTypeAIProxy:
diff --git a/web/src/components/ChannelsTable.js b/web/src/components/ChannelsTable.js
index 0b29ff9e..4ea6965d 100644
--- a/web/src/components/ChannelsTable.js
+++ b/web/src/components/ChannelsTable.js
@@ -30,6 +30,9 @@ function renderType(type) {
function renderBalance(type, balance) {
switch (type) {
case 1: // OpenAI
+ return ${balance.toFixed(2)};
+ case 4: // CloseAI
+ return ¥{balance.toFixed(2)};
case 8: // 自定义
return ${balance.toFixed(2)};
case 5: // OpenAI-SB