From 3202ca9f3e2a5337e75b1bd0b4f467e8487e9a00 Mon Sep 17 00:00:00 2001 From: CaIon <1808837298@qq.com> Date: Sun, 12 Nov 2023 18:51:26 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BD=99=E9=A2=9D?= =?UTF-8?q?=E4=B8=8D=E8=B6=B3=E9=82=AE=E4=BB=B6=E6=8F=90=E9=86=92bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controller/relay-audio.go | 4 +-- controller/relay-image.go | 2 +- controller/relay-mj.go | 2 +- controller/relay-text.go | 6 ++-- model/token.go | 65 ++++++++++++++++++++------------------- 5 files changed, 40 insertions(+), 39 deletions(-) diff --git a/controller/relay-audio.go b/controller/relay-audio.go index bf6a0dfe..fe91dbc6 100644 --- a/controller/relay-audio.go +++ b/controller/relay-audio.go @@ -44,7 +44,7 @@ func relayAudioHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode preConsumedQuota = 0 } if preConsumedQuota > 0 { - err := model.PreConsumeTokenQuota(tokenId, preConsumedQuota) + userQuota, err = model.PreConsumeTokenQuota(tokenId, preConsumedQuota) if err != nil { return errorWrapper(err, "pre_consume_token_quota_failed", http.StatusForbidden) } @@ -99,7 +99,7 @@ func relayAudioHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode go func() { quota := countTokenText(audioResponse.Text, audioModel) quotaDelta := quota - preConsumedQuota - err := model.PostConsumeTokenQuota(tokenId, quotaDelta) + err := model.PostConsumeTokenQuota(tokenId, userQuota, quotaDelta, preConsumedQuota) if err != nil { common.SysError("error consuming token remain quota: " + err.Error()) } diff --git a/controller/relay-image.go b/controller/relay-image.go index 89dc8212..5cebcdb1 100644 --- a/controller/relay-image.go +++ b/controller/relay-image.go @@ -147,7 +147,7 @@ func relayImageHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode var textResponse ImageResponse defer func(ctx context.Context) { if consumeQuota { - err := model.PostConsumeTokenQuota(tokenId, quota) + err := model.PostConsumeTokenQuota(tokenId, userId, quota, 0) if err != nil { common.SysError("error consuming token remain quota: " + err.Error()) } diff --git a/controller/relay-mj.go b/controller/relay-mj.go index 4f852341..948c57c0 100644 --- a/controller/relay-mj.go +++ b/controller/relay-mj.go @@ -359,7 +359,7 @@ func relayMidjourneySubmit(c *gin.Context, relayMode int) *MidjourneyResponse { defer func(ctx context.Context) { if consumeQuota { - err := model.PostConsumeTokenQuota(tokenId, quota) + err := model.PostConsumeTokenQuota(tokenId, userQuota, quota, 0) if err != nil { common.SysError("error consuming token remain quota: " + err.Error()) } diff --git a/controller/relay-text.go b/controller/relay-text.go index 84dc5822..6f56be8f 100644 --- a/controller/relay-text.go +++ b/controller/relay-text.go @@ -233,7 +233,7 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode { //common.LogInfo(c.Request.Context(), fmt.Sprintf("user %d has enough quota %d, trusted and no need to pre-consume", userId, userQuota)) } if consumeQuota && preConsumedQuota > 0 { - err := model.PreConsumeTokenQuota(tokenId, preConsumedQuota) + userQuota, err = model.PreConsumeTokenQuota(tokenId, preConsumedQuota) if err != nil { return errorWrapper(err, "pre_consume_token_quota_failed", http.StatusForbidden) } @@ -400,7 +400,7 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode { if preConsumedQuota != 0 { go func(ctx context.Context) { // return pre-consumed quota - err := model.PostConsumeTokenQuota(tokenId, -preConsumedQuota) + err := model.PostConsumeTokenQuota(tokenId, userQuota, -preConsumedQuota, 0) if err != nil { common.LogError(ctx, "error return pre-consumed quota: "+err.Error()) } @@ -434,7 +434,7 @@ func relayTextHelper(c *gin.Context, relayMode int) *OpenAIErrorWithStatusCode { quota = 0 } quotaDelta := quota - preConsumedQuota - err := model.PostConsumeTokenQuota(tokenId, quotaDelta) + err := model.PostConsumeTokenQuota(tokenId, userQuota, quotaDelta, preConsumedQuota) if err != nil { common.LogError(ctx, "error consuming token remain quota: "+err.Error()) } diff --git a/model/token.go b/model/token.go index 41746d9a..06b97750 100644 --- a/model/token.go +++ b/model/token.go @@ -178,59 +178,60 @@ func decreaseTokenQuota(id int, quota int) (err error) { return err } -func PreConsumeTokenQuota(tokenId int, quota int) (err error) { +func PreConsumeTokenQuota(tokenId int, quota int) (userQuota int, err error) { if quota < 0 { - return errors.New("quota 不能为负数!") + return 0, errors.New("quota 不能为负数!") } token, err := GetTokenById(tokenId) if err != nil { - return err + return 0, err } if !token.UnlimitedQuota && token.RemainQuota < quota { - return errors.New("令牌额度不足") + return 0, errors.New("令牌额度不足") } - userQuota, err := GetUserQuota(token.UserId) + userQuota, err = GetUserQuota(token.UserId) if err != nil { - return err + return 0, err } if userQuota < quota { - return errors.New("用户额度不足") - } - 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()) - } - } - }() + return userQuota, errors.New(fmt.Sprintf("用户额度不足,剩余额度为 %d", userQuota)) } if !token.UnlimitedQuota { err = DecreaseTokenQuota(tokenId, quota) if err != nil { - return err + return userQuota, err } } err = DecreaseUserQuota(token.UserId, quota) - return err + return userQuota, err } -func PostConsumeTokenQuota(tokenId int, quota int) (err error) { +func PostConsumeTokenQuota(tokenId int, userQuota int, quota int, preConsumedQuota int) (err error) { token, err := GetTokenById(tokenId) + if quota > 0 { + quotaTooLow := userQuota >= common.QuotaRemindThreshold && userQuota-(quota+preConsumedQuota) < common.QuotaRemindThreshold + noMoreQuota := userQuota-(quota+preConsumedQuota) <= 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()) + } + } + }() + } err = DecreaseUserQuota(token.UserId, quota) } else { err = IncreaseUserQuota(token.UserId, -quota) From 49136f29f9880465749316f9f40affb67e961a44 Mon Sep 17 00:00:00 2001 From: Calcium-Ion <61247483+Calcium-Ion@users.noreply.github.com> Date: Fri, 10 Nov 2023 13:53:04 -0600 Subject: [PATCH 2/3] Update README.md (cherry picked from commit 31d3fd1eb67538f472b10dadb1ba21ac13d2e384) --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 699551d2..89dfba3b 100644 --- a/README.md +++ b/README.md @@ -29,3 +29,14 @@ 5. 渠道显示已使用额度,支持指定组织访问 6. 分页支持选择每页显示数量 +## 界面截图 +![image](https://github.com/Calcium-Ion/new-api/assets/61247483/3ca0b282-00ff-4c96-bf9d-e29ef615c605) +![image](https://github.com/Calcium-Ion/new-api/assets/61247483/f4f40ed4-8ccb-43d7-a580-90677827646d) +![image](https://github.com/Calcium-Ion/new-api/assets/61247483/90d7d763-6a77-4b36-9f76-2bb30f18583d) +![image](https://github.com/Calcium-Ion/new-api/assets/61247483/e414228a-3c35-429a-b298-6451d76d9032) +夜间模式 +![image](https://github.com/Calcium-Ion/new-api/assets/61247483/5b3228e8-2556-44f7-97d6-4f8d8ee6effa) +![image](https://github.com/Calcium-Ion/new-api/assets/61247483/af9a07ee-5101-4b3d-8bd9-ae21a4fd7e9e) + + + From d788c05621e5cbce5aa0d91c7d20aec96a4657b1 Mon Sep 17 00:00:00 2001 From: CaIon <1808837298@qq.com> Date: Sun, 12 Nov 2023 19:04:05 +0800 Subject: [PATCH 3/3] delete workflow file --- .github/workflows/docker-image.yml | 32 ------------------------------ 1 file changed, 32 deletions(-) delete mode 100644 .github/workflows/docker-image.yml diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml deleted file mode 100644 index 7b6d3fda..00000000 --- a/.github/workflows/docker-image.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Docker Image CI - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -jobs: - - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - uses: docker/login-action@v3.0.0 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@v3 - with: - images: calciumion/neko-api - - name: Build the Docker image - uses: docker/build-push-action@v5.0.0 - with: - context: . - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }}