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:
@@ -4,3 +4,6 @@ TELEMT_API_BASE_URL=http://host.docker.internal:9091
|
||||
TELEMT_API_AUTH_HEADER=Bearer replace_me
|
||||
TELEGRAM_HTTP_TIMEOUT_SECONDS=60
|
||||
TELEMT_HTTP_TIMEOUT_SECONDS=5
|
||||
TELEMT_LINK_HOST=127.0.0.1
|
||||
TELEMT_LINK_PORT=9443
|
||||
TELEMT_TLS_DOMAIN=
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
- `TELEMT_API_AUTH_HEADER` - значение заголовка `Authorization` для Telemt API (если включён `auth_header`).
|
||||
- `TELEGRAM_HTTP_TIMEOUT_SECONDS` - timeout запросов к Telegram (по умолчанию `60`).
|
||||
- `TELEMT_HTTP_TIMEOUT_SECONDS` - timeout запросов к Telemt API (по умолчанию `5`).
|
||||
- `TELEMT_LINK_HOST` - хост для генерации `tg://proxy` ссылок, если API их не вернуло.
|
||||
- `TELEMT_LINK_PORT` - порт для ссылок (по умолчанию `9443`).
|
||||
- `TELEMT_TLS_DOMAIN` - TLS-домен для генерации `EE-TLS` ссылки (опционально).
|
||||
|
||||
## Быстрый старт (локально, Linux/bash)
|
||||
|
||||
@@ -47,6 +50,9 @@ services:
|
||||
TELEMT_API_AUTH_HEADER: ${TELEMT_API_AUTH_HEADER}
|
||||
TELEGRAM_HTTP_TIMEOUT_SECONDS: ${TELEGRAM_HTTP_TIMEOUT_SECONDS:-60}
|
||||
TELEMT_HTTP_TIMEOUT_SECONDS: ${TELEMT_HTTP_TIMEOUT_SECONDS:-5}
|
||||
TELEMT_LINK_HOST: ${TELEMT_LINK_HOST}
|
||||
TELEMT_LINK_PORT: ${TELEMT_LINK_PORT:-9443}
|
||||
TELEMT_TLS_DOMAIN: ${TELEMT_TLS_DOMAIN:-}
|
||||
```
|
||||
|
||||
Запуск (Linux/bash):
|
||||
@@ -56,6 +62,9 @@ export TELEGRAM_BOT_TOKEN="xxx:telegram_bot_token"
|
||||
export TELEGRAM_ADMIN_CHAT_ID="123456789"
|
||||
export TELEMT_API_BASE_URL="http://host.docker.internal:9091"
|
||||
export TELEMT_API_AUTH_HEADER="Bearer secret"
|
||||
export TELEMT_LINK_HOST="172.20.0.3"
|
||||
export TELEMT_LINK_PORT="9443"
|
||||
export TELEMT_TLS_DOMAIN="tf.ivx.su"
|
||||
|
||||
docker compose up -d
|
||||
docker compose logs -f
|
||||
@@ -73,6 +82,9 @@ docker run -d \
|
||||
-e TELEMT_API_AUTH_HEADER="Bearer secret" \
|
||||
-e TELEGRAM_HTTP_TIMEOUT_SECONDS="60" \
|
||||
-e TELEMT_HTTP_TIMEOUT_SECONDS="5" \
|
||||
-e TELEMT_LINK_HOST="172.20.0.3" \
|
||||
-e TELEMT_LINK_PORT="9443" \
|
||||
-e TELEMT_TLS_DOMAIN="tf.ivx.su" \
|
||||
git.shts.su/denozord/telemt-bot:latest
|
||||
```
|
||||
|
||||
|
||||
@@ -12,3 +12,6 @@ services:
|
||||
TELEMT_API_AUTH_HEADER: ${TELEMT_API_AUTH_HEADER}
|
||||
TELEGRAM_HTTP_TIMEOUT_SECONDS: ${TELEGRAM_HTTP_TIMEOUT_SECONDS:-60}
|
||||
TELEMT_HTTP_TIMEOUT_SECONDS: ${TELEMT_HTTP_TIMEOUT_SECONDS:-5}
|
||||
TELEMT_LINK_HOST: ${TELEMT_LINK_HOST}
|
||||
TELEMT_LINK_PORT: ${TELEMT_LINK_PORT:-9443}
|
||||
TELEMT_TLS_DOMAIN: ${TELEMT_TLS_DOMAIN:-}
|
||||
|
||||
@@ -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