Update bot logic, Dockerfile and docker-compose.yml

This commit is contained in:
Sarteambot Admin
2026-03-11 21:55:20 +08:00
parent 3adb3f1079
commit faf4308f7f
3 changed files with 88 additions and 24 deletions

View File

@@ -1,5 +1,5 @@
# Build stage # Build stage
FROM golang:1.21-alpine AS builder FROM golang:1.25-alpine AS builder
WORKDIR /app WORKDIR /app
COPY go.mod go.sum ./ COPY go.mod go.sum ./
@@ -15,6 +15,7 @@ ENV TZ=Asia/Shanghai
WORKDIR /app WORKDIR /app
COPY --from=builder /app/go-helper . COPY --from=builder /app/go-helper .
COPY image.png .
COPY .env.example .env COPY .env.example .env
ENTRYPOINT ["./go-helper"] ENTRYPOINT ["./go-helper"]

36
docker-compose.yml Normal file
View File

@@ -0,0 +1,36 @@
version: "3.8"
services:
# PostgreSQL 数据库
db:
image: postgres:16-alpine
container_name: gpt-team-db
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: teamhelper
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
interval: 5s
timeout: 5s
retries: 5
# Go Helper Bot
bot:
build: .
container_name: gpt-team-bot
restart: always
depends_on:
db:
condition: service_healthy
env_file:
- .env
environment:
# 覆盖 .env 中的数据库连接串,指向 docker 内部的 db 服务
DATABASE_URL: postgres://postgres:postgres@db:5432/teamhelper?sslmode=disable
volumes:
pgdata:

View File

@@ -1,4 +1,4 @@
package bot package bot
import ( import (
"fmt" "fmt"
@@ -589,17 +589,13 @@ func (b *Bot) callbackActionPick(chatID int64, msgID int, action string, userID
} }
backCallback = "cmd:list_accounts" backCallback = "cmd:list_accounts"
prefix := "📧"
if action == "del" { if action == "del" {
label = "🗑️ 选择要删除的账号" label = "🗑️ 选择要删除的账号"
prefix = "🗑"
} else if action == "ref" { } else if action == "ref" {
label = "🔄 选择要刷新的账号" label = "🔄 选择要刷新的账号"
prefix = "🔄"
} else if action == "pending_invite" { } else if action == "pending_invite" {
label = "📩 选择管理账户" label = "📩 选择管理账户"
prefix = "📧"
backCallback = "cmd:back" backCallback = "cmd:back"
} }
@@ -622,17 +618,29 @@ func (b *Bot) callbackActionPick(chatID int64, msgID int, action string, userID
shown := accounts[start:end] shown := accounts[start:end]
var rows [][]tgbotapi.InlineKeyboardButton var rows [][]tgbotapi.InlineKeyboardButton
var lns []string
var rBtns []tgbotapi.InlineKeyboardButton
// Create a button map for i, a := range shown {
for _, a := range shown {
btnAction := fmt.Sprintf("%s:%d", action, a.ID) btnAction := fmt.Sprintf("%s:%d", action, a.ID)
idx := start + i + 1
lns = append(lns, fmt.Sprintf("*%d.* ID: `%d` (%s)", idx, a.ID, a.Email))
rows = append(rows, tgbotapi.NewInlineKeyboardRow( rBtns = append(rBtns, tgbotapi.NewInlineKeyboardButtonData(
tgbotapi.NewInlineKeyboardButtonData( fmt.Sprintf("%d", idx),
fmt.Sprintf("%s %s", prefix, a.Email), btnAction,
btnAction,
),
)) ))
// Row break every 5 items
if len(rBtns) == 5 {
rows = append(rows, tgbotapi.NewInlineKeyboardRow(rBtns...))
rBtns = nil
}
}
// Append remaining buttons
if len(rBtns) > 0 {
rows = append(rows, tgbotapi.NewInlineKeyboardRow(rBtns...))
} }
// Pagination buttons // Pagination buttons
@@ -647,9 +655,16 @@ func (b *Bot) callbackActionPick(chatID int64, msgID int, action string, userID
rows = append(rows, tgbotapi.NewInlineKeyboardRow(navRow...)) rows = append(rows, tgbotapi.NewInlineKeyboardRow(navRow...))
} }
rows = append(rows, tgbotapi.NewInlineKeyboardRow( if action == "ref" {
tgbotapi.NewInlineKeyboardButtonData("⬅️ 返回", backCallback), rows = append(rows, tgbotapi.NewInlineKeyboardRow(
)) tgbotapi.NewInlineKeyboardButtonData("🔄 刷新全部", "cmd:refresh_all"),
tgbotapi.NewInlineKeyboardButtonData("⬅️ 返回", backCallback),
))
} else {
rows = append(rows, tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("⬅️ 返回", backCallback),
))
}
kb := tgbotapi.InlineKeyboardMarkup{InlineKeyboard: rows} kb := tgbotapi.InlineKeyboardMarkup{InlineKeyboard: rows}
@@ -658,7 +673,7 @@ func (b *Bot) callbackActionPick(chatID int64, msgID int, action string, userID
pageInfo = fmt.Sprintf("\n(第 %d/%d 页)", page+1, totalPages) pageInfo = fmt.Sprintf("\n(第 %d/%d 页)", page+1, totalPages)
} }
b.editMsgWithKeyboard(chatID, msgID, fmt.Sprintf("%s%s:", label, pageInfo), &kb) b.editMsgWithKeyboard(chatID, msgID, fmt.Sprintf("%s%s:\n\n%s", label, pageInfo, strings.Join(lns, "\n")), &kb)
} }
func (b *Bot) callbackDelAccount(chatID int64, msgID int, idStr string) { func (b *Bot) callbackDelAccount(chatID int64, msgID int, idStr string) {
@@ -722,6 +737,16 @@ func (b *Bot) callbackRefAccount(chatID int64, msgID int, idStr string) {
_ = b.db.UpdateAccountTokens(id, result.AccessToken, result.RefreshToken) _ = b.db.UpdateAccountTokens(id, result.AccessToken, result.RefreshToken)
// Sync member counts after token refresh.
acc.Token = result.AccessToken
if userTotal, _, err2 := b.client.GetUsers(acc); err2 == nil {
invTotal := acc.InviteCount
if inv, _, err3 := b.client.GetInvites(acc); err3 == nil {
invTotal = inv
}
_ = b.db.UpdateAccountCounts(id, userTotal, invTotal)
}
kb := tgbotapi.NewInlineKeyboardMarkup( kb := tgbotapi.NewInlineKeyboardMarkup(
tgbotapi.NewInlineKeyboardRow( tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("⬅️ 返回列表", "cmd:list_accounts"), tgbotapi.NewInlineKeyboardButtonData("⬅️ 返回列表", "cmd:list_accounts"),
@@ -1014,8 +1039,10 @@ func (b *Bot) handleMessage(msg *tgbotapi.Message) {
if hasSess && !strings.HasPrefix(text, "/") { if hasSess && !strings.HasPrefix(text, "/") {
switch sess.flowType { switch sess.flowType {
case "redeem_code": case "redeem_code":
b.deleteMsg(chatID, msg.MessageID)
b.handleRedeemCode(chatID, text) b.handleRedeemCode(chatID, text)
case "redeem": case "redeem":
b.deleteMsg(chatID, msg.MessageID)
b.handleRedeemEmail(chatID, sess, text) b.handleRedeemEmail(chatID, sess, text)
case "login": case "login":
b.handleLoginCallback(chatID, msg.MessageID, text) b.handleLoginCallback(chatID, msg.MessageID, text)
@@ -1030,7 +1057,7 @@ func (b *Bot) handleMessage(msg *tgbotapi.Message) {
if email == "" { if email == "" {
return return
} }
accounts, err := b.db.GetOpenAccounts(b.cfg.TeamCapacity) accounts, err := b.db.GetOpenAccounts(b.cfg.TeamCapacity - 1)
if err != nil || len(accounts) == 0 { if err != nil || len(accounts) == 0 {
kb := tgbotapi.NewInlineKeyboardMarkup( kb := tgbotapi.NewInlineKeyboardMarkup(
tgbotapi.NewInlineKeyboardRow( tgbotapi.NewInlineKeyboardRow(
@@ -1230,7 +1257,7 @@ func (b *Bot) handleRedeemEmail(chatID int64, sess *chatSession, email string) {
if panelMsgID != 0 { if panelMsgID != 0 {
b.editMsgWithKeyboard(chatID, panelMsgID, "⏳ 正在处理兑换,请稍候...", nil) b.editMsgWithKeyboard(chatID, panelMsgID, "⏳ 正在处理兑换,请稍候...", nil)
result, err := redeem.Redeem(b.db, b.client, sess.code, email, b.cfg.TeamCapacity) result, err := redeem.Redeem(b.db, b.client, sess.code, email, b.cfg.TeamCapacity-1)
if err != nil { if err != nil {
b.editMsgWithKeyboard(chatID, panelMsgID, fmt.Sprintf("❌ 兑换失败: %s", err.Error()), &backKb) b.editMsgWithKeyboard(chatID, panelMsgID, fmt.Sprintf("❌ 兑换失败: %s", err.Error()), &backKb)
return return
@@ -1239,7 +1266,7 @@ func (b *Bot) handleRedeemEmail(chatID int64, sess *chatSession, email string) {
} else { } else {
msgID := b.sendAndGetID(chatID, "⏳ 正在处理兑换,请稍候...") msgID := b.sendAndGetID(chatID, "⏳ 正在处理兑换,请稍候...")
result, err := redeem.Redeem(b.db, b.client, sess.code, email, b.cfg.TeamCapacity) result, err := redeem.Redeem(b.db, b.client, sess.code, email, b.cfg.TeamCapacity-1)
if err != nil { if err != nil {
b.editMsg(chatID, msgID, fmt.Sprintf("❌ 兑换失败: %s", err.Error())) b.editMsg(chatID, msgID, fmt.Sprintf("❌ 兑换失败: %s", err.Error()))
return return
@@ -1337,9 +1364,9 @@ func (b *Bot) handleAddAccount(chatID int64, panelMsgID int, args string) {
continue continue
} }
// Generate codes based on remaining capacity: 6 - (current user count + pending invites). // Generate codes based on remaining capacity: (b.cfg.TeamCapacity - 1) - (current user count + pending invites).
newAcct, _ := b.db.GetAccountByID(id) newAcct, _ := b.db.GetAccountByID(id)
codeCount := 6 codeCount := b.cfg.TeamCapacity
if newAcct != nil { if newAcct != nil {
var userTotal, inviteTotal int var userTotal, inviteTotal int
if ut, _, err2 := b.client.GetUsers(newAcct); err2 == nil { if ut, _, err2 := b.client.GetUsers(newAcct); err2 == nil {
@@ -1348,7 +1375,7 @@ func (b *Bot) handleAddAccount(chatID int64, panelMsgID int, args string) {
if it, _, err3 := b.client.GetInvites(newAcct); err3 == nil { if it, _, err3 := b.client.GetInvites(newAcct); err3 == nil {
inviteTotal = it inviteTotal = it
} }
codeCount = 6 - (userTotal + inviteTotal) codeCount = b.cfg.TeamCapacity - (userTotal + inviteTotal)
_ = b.db.UpdateAccountCounts(id, userTotal, inviteTotal) _ = b.db.UpdateAccountCounts(id, userTotal, inviteTotal)
} }
if codeCount < 0 { if codeCount < 0 {
@@ -1549,7 +1576,7 @@ func (b *Bot) handleGenCodes(chatID int64, panelMsgID int, args string) {
email := eligible[i].Email email := eligible[i].Email
existing, _ := b.db.CountAvailableCodesByAccount(email) existing, _ := b.db.CountAvailableCodesByAccount(email)
maxCodes := b.cfg.TeamCapacity - eligible[i].UserCount - eligible[i].InviteCount maxCodes := (b.cfg.TeamCapacity - 1) - eligible[i].UserCount - eligible[i].InviteCount
if maxCodes < 0 { if maxCodes < 0 {
maxCodes = 0 maxCodes = 0
} }