bot TG
This commit is contained in:
+167
@@ -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)
|
||||
}
|
||||
Reference in New Issue
Block a user