Исправил постинг токена в ссылках

This commit is contained in:
Taz
2026-03-07 19:14:58 +01:00
parent 34e6a4562c
commit d300bc9824
9 changed files with 270 additions and 91 deletions
+55
View File
@@ -1,6 +1,9 @@
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"io"
"mime"
@@ -81,6 +84,58 @@ func NewBridge(telegramToken, discordToken, vkToken string) (*Bridge, error) {
}, nil
}
// signMediaToken создаёт подписанный токен для filePath (HMAC-SHA256), чтобы не светить токен бота в ссылках.
func signMediaToken(filePath, secret string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(filePath))
sig := mac.Sum(nil)
// payload.base64(sig) — в URL без padding
enc := base64.URLEncoding.WithPadding(base64.NoPadding)
return enc.EncodeToString([]byte(filePath)) + "." + enc.EncodeToString(sig)
}
// verifyMediaToken проверяет подпись и возвращает filePath. secret должен совпадать с тем, что при подписи.
func verifyMediaToken(token, secret string) (filePath string, ok bool) {
enc := base64.URLEncoding.WithPadding(base64.NoPadding)
idx := strings.LastIndex(token, ".")
if idx == -1 {
return "", false
}
payloadB, err1 := enc.DecodeString(token[:idx])
sigB, err2 := enc.DecodeString(token[idx+1:])
if err1 != nil || err2 != nil || len(sigB) != sha256.Size {
return "", false
}
filePath = string(payloadB)
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(filePath))
expected := mac.Sum(nil)
if !hmac.Equal(sigB, expected) {
return "", false
}
return filePath, true
}
// GetTelegramFileProxyURL возвращает публичный URL прокси для файла Telegram (без токена в ссылке).
// В конец URL добавлено имя файла с расширением, чтобы ссылка в чате показывала .jpg и т.д.
func (b *Bridge) GetTelegramFileProxyURL(filePath string) string {
publicURL := strings.TrimSuffix(os.Getenv("PUBLIC_URL"), "/")
secret := os.Getenv("MEDIA_PROXY_SECRET")
if publicURL == "" || secret == "" {
return ""
}
fileName := path.Base(filePath)
if fileName == "" || fileName == "." {
fileName = "file"
}
return publicURL + "/media/" + signMediaToken(filePath, secret) + "/" + url.PathEscape(fileName)
}
// GetTelegramFileDirectURL возвращает прямую ссылку на файл Telegram (только для внутреннего использования на сервере).
func (b *Bridge) GetTelegramFileDirectURL(filePath string) string {
return fmt.Sprintf("https://api.telegram.org/file/bot%s/%s", b.Telegram.Token, filePath)
}
// Отправка сообщения в Telegram
func (b *Bridge) SendToTelegram(chatID int64, text string) error {
msg := tgbotapi.NewMessage(chatID, text)