This commit is contained in:
2026-07-13 00:06:51 -03:00
parent a4798f8db6
commit 09c1f57a34
17 changed files with 3799 additions and 0 deletions
+167
View File
@@ -0,0 +1,167 @@
package main
// bot_config.go — in-memory bot configuration loaded from the bot_config table.
// Secrets are decrypted here and never persisted in plaintext.
import (
"context"
"errors"
"strconv"
)
var errInsufficientCredits = errors.New("insufficient credits")
func botItoa(n int) string { return strconv.Itoa(n) }
// BotConfig is the decrypted, ready-to-use bot configuration.
type BotConfig struct {
Enabled bool
TelegramToken string
TelegramMode string // polling | webhook
TelegramWebhookURL string
TelegramWebhookSecret string
MPAccessToken string
MPConfirmMode string // webhook | polling
MPWebhookSecret string
MPPollInterval string
PixExpirationMinutes int
TrialEnabled bool
TrialHours int
TrialMaxConnections int
TrialKind string // ssh | xray
TrialInboundTag string
AdminTelegramIDs []int64
Currency string
PublicHost string // SSH connection host shown to buyers
XrayPublicHost string // host used to build vless/vmess links
}
// LoadBotConfig reads the config row and decrypts secrets into a BotConfig.
func LoadBotConfig(ctx context.Context, store *Store) (*BotConfig, error) {
r, err := store.getBotConfigRow(ctx)
if err != nil {
return nil, err
}
tok, err := decryptSecret(r.TelegramTokenEnc)
if err != nil {
return nil, err
}
tgSec, err := decryptSecret(r.TelegramWebhookSecretEnc)
if err != nil {
return nil, err
}
mp, err := decryptSecret(r.MPAccessTokenEnc)
if err != nil {
return nil, err
}
mpSec, err := decryptSecret(r.MPWebhookSecretEnc)
if err != nil {
return nil, err
}
cfg := &BotConfig{
Enabled: r.Enabled,
TelegramToken: tok,
TelegramMode: r.TelegramMode,
TelegramWebhookURL: r.TelegramWebhookURL,
TelegramWebhookSecret: tgSec,
MPAccessToken: mp,
MPConfirmMode: r.MPConfirmMode,
MPWebhookSecret: mpSec,
MPPollInterval: r.MPPollInterval,
PixExpirationMinutes: r.PixExpirationMinutes,
TrialEnabled: r.TrialEnabled,
TrialHours: r.TrialHours,
TrialMaxConnections: r.TrialMaxConnections,
TrialKind: r.TrialKind,
TrialInboundTag: r.TrialInboundTag,
AdminTelegramIDs: r.AdminTelegramIDs,
Currency: r.Currency,
PublicHost: r.PublicHost,
XrayPublicHost: r.XrayPublicHost,
}
cfg.applyDefaults()
return cfg, nil
}
func (c *BotConfig) applyDefaults() {
if c.TelegramMode == "" {
c.TelegramMode = "polling"
}
if c.MPConfirmMode == "" {
c.MPConfirmMode = "polling"
}
if c.MPPollInterval == "" {
c.MPPollInterval = "20s"
}
if c.PixExpirationMinutes <= 0 {
c.PixExpirationMinutes = 30
}
if c.TrialHours <= 0 {
c.TrialHours = 1
}
if c.TrialMaxConnections <= 0 {
c.TrialMaxConnections = 1
}
if c.TrialKind == "" {
c.TrialKind = "ssh"
}
if c.Currency == "" {
c.Currency = "BRL"
}
}
func (c *BotConfig) isAdmin(telegramID int64) bool {
for _, id := range c.AdminTelegramIDs {
if id == telegramID {
return true
}
}
return false
}
// SaveBotConfig persists a BotConfig. Empty secret fields preserve the stored
// value (nil blob → column left unchanged).
func SaveBotConfig(ctx context.Context, store *Store, cfg *BotConfig) error {
cfg.applyDefaults()
row := &botConfigRow{
Enabled: cfg.Enabled,
TelegramMode: cfg.TelegramMode,
TelegramWebhookURL: cfg.TelegramWebhookURL,
MPConfirmMode: cfg.MPConfirmMode,
MPPollInterval: cfg.MPPollInterval,
PixExpirationMinutes: cfg.PixExpirationMinutes,
TrialEnabled: cfg.TrialEnabled,
TrialHours: cfg.TrialHours,
TrialMaxConnections: cfg.TrialMaxConnections,
TrialKind: cfg.TrialKind,
TrialInboundTag: cfg.TrialInboundTag,
AdminTelegramIDs: cfg.AdminTelegramIDs,
Currency: cfg.Currency,
PublicHost: cfg.PublicHost,
XrayPublicHost: cfg.XrayPublicHost,
}
var tokEnc, tgSecEnc, mpEnc, mpSecEnc []byte
var err error
if cfg.TelegramToken != "" {
if tokEnc, err = encryptSecret(cfg.TelegramToken); err != nil {
return err
}
}
if cfg.TelegramWebhookSecret != "" {
if tgSecEnc, err = encryptSecret(cfg.TelegramWebhookSecret); err != nil {
return err
}
}
if cfg.MPAccessToken != "" {
if mpEnc, err = encryptSecret(cfg.MPAccessToken); err != nil {
return err
}
}
if cfg.MPWebhookSecret != "" {
if mpSecEnc, err = encryptSecret(cfg.MPWebhookSecret); err != nil {
return err
}
}
return store.saveBotConfigRow(ctx, row, tokEnc, tgSecEnc, mpEnc, mpSecEnc)
}