Add configuration options for link generation in .env.example, docker-compose.yml, and main.go; update README.md with new environment variable descriptions.
Publish telemt-bot Docker image / build-and-push (push) Successful in 52s
Publish telemt-bot Docker image / build-and-push (push) Successful in 52s
This commit is contained in:
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -32,6 +33,10 @@ type config struct {
|
||||
|
||||
TelemtTimeout time.Duration
|
||||
TelegramTimeout time.Duration
|
||||
|
||||
TelemtLinkHost string
|
||||
TelemtLinkPort int
|
||||
TelemtLinkTLSDomain string
|
||||
}
|
||||
|
||||
type bot struct {
|
||||
@@ -168,6 +173,9 @@ func loadConfig() (config, error) {
|
||||
cfg.TelemtAPIAuth = strings.TrimSpace(os.Getenv("TELEMT_API_AUTH_HEADER"))
|
||||
cfg.TelemtTimeout = parseSecondsEnv("TELEMT_HTTP_TIMEOUT_SECONDS", defaultTelemtTimeoutSeconds)
|
||||
cfg.TelegramTimeout = parseSecondsEnv("TELEGRAM_HTTP_TIMEOUT_SECONDS", defaultTelegramTimeoutSeconds)
|
||||
cfg.TelemtLinkHost = strings.TrimSpace(os.Getenv("TELEMT_LINK_HOST"))
|
||||
cfg.TelemtLinkPort = parseIntEnv("TELEMT_LINK_PORT", 9443)
|
||||
cfg.TelemtLinkTLSDomain = strings.TrimSpace(os.Getenv("TELEMT_TLS_DOMAIN"))
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
@@ -184,6 +192,18 @@ func parseSecondsEnv(key string, fallback int) time.Duration {
|
||||
return time.Duration(v) * time.Second
|
||||
}
|
||||
|
||||
func parseIntEnv(key string, fallback int) int {
|
||||
raw := strings.TrimSpace(os.Getenv(key))
|
||||
if raw == "" {
|
||||
return fallback
|
||||
}
|
||||
v, err := strconv.Atoi(raw)
|
||||
if err != nil || v <= 0 {
|
||||
return fallback
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (b *bot) run(ctx context.Context) error {
|
||||
for {
|
||||
select {
|
||||
@@ -350,14 +370,7 @@ func (b *bot) handleCreateUser(ctx context.Context, chatID int64, text string) e
|
||||
return b.sendMessage(ctx, chatID, "Ошибка создания пользователя: "+err.Error())
|
||||
}
|
||||
|
||||
links := created.User.Links
|
||||
if len(links.Classic) == 0 && len(links.Secure) == 0 && len(links.TLS) == 0 {
|
||||
var fetched userInfo
|
||||
path := "/v1/users/" + url.PathEscape(created.User.Username)
|
||||
if err := b.callTelemt(ctx, path, &fetched); err == nil {
|
||||
links = fetched.Links
|
||||
}
|
||||
}
|
||||
links := b.resolveUserLinks(ctx, created.User.Username, created.Secret, created.User.Links)
|
||||
|
||||
msg := fmt.Sprintf("Пользователь создан: %s\nsecret: %s", created.User.Username, created.Secret)
|
||||
if linksText := formatUserLinks(links); linksText != "" {
|
||||
@@ -368,6 +381,63 @@ func (b *bot) handleCreateUser(ctx context.Context, chatID int64, text string) e
|
||||
return b.sendMessage(ctx, chatID, msg)
|
||||
}
|
||||
|
||||
func hasAnyLinks(links userLinks) bool {
|
||||
return len(links.Classic) > 0 || len(links.Secure) > 0 || len(links.TLS) > 0
|
||||
}
|
||||
|
||||
func (b *bot) resolveUserLinks(ctx context.Context, username, secret string, initial userLinks) userLinks {
|
||||
if hasAnyLinks(initial) {
|
||||
return initial
|
||||
}
|
||||
|
||||
var fetched userInfo
|
||||
path := "/v1/users/" + url.PathEscape(username)
|
||||
if err := b.callTelemt(ctx, path, &fetched); err == nil && hasAnyLinks(fetched.Links) {
|
||||
return fetched.Links
|
||||
}
|
||||
|
||||
var users []userInfo
|
||||
if err := b.callTelemt(ctx, "/v1/users", &users); err == nil {
|
||||
for i := range users {
|
||||
if users[i].Username == username && hasAnyLinks(users[i].Links) {
|
||||
return users[i].Links
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
users = nil
|
||||
if err := b.callTelemt(ctx, "/v1/stats/users", &users); err == nil {
|
||||
for i := range users {
|
||||
if users[i].Username == username && hasAnyLinks(users[i].Links) {
|
||||
return users[i].Links
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return b.generateLinksFromSecret(secret)
|
||||
}
|
||||
|
||||
func (b *bot) generateLinksFromSecret(secret string) userLinks {
|
||||
host := strings.TrimSpace(b.cfg.TelemtLinkHost)
|
||||
if host == "" || secret == "" {
|
||||
return userLinks{}
|
||||
}
|
||||
port := b.cfg.TelemtLinkPort
|
||||
classic := fmt.Sprintf("tg://proxy?server=%s&port=%d&secret=%s", host, port, secret)
|
||||
dd := fmt.Sprintf("tg://proxy?server=%s&port=%d&secret=dd%s", host, port, secret)
|
||||
|
||||
out := userLinks{
|
||||
Classic: []string{classic},
|
||||
Secure: []string{dd},
|
||||
}
|
||||
if b.cfg.TelemtLinkTLSDomain != "" {
|
||||
hexDomain := hex.EncodeToString([]byte(b.cfg.TelemtLinkTLSDomain))
|
||||
tls := fmt.Sprintf("tg://proxy?server=%s&port=%d&secret=ee%s%s", host, port, secret, hexDomain)
|
||||
out.TLS = []string{tls}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func formatUserLinks(links userLinks) string {
|
||||
var sb strings.Builder
|
||||
appendLinks := func(title string, items []string) {
|
||||
|
||||
Reference in New Issue
Block a user