Public Access
Исправил постинг токена в ссылках
This commit is contained in:
@@ -2,15 +2,35 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
// Заполняются при сборке: go build -ldflags "-X main.Version=... -X main.BuildDate=..."
|
||||
var (
|
||||
Version = "dev"
|
||||
BuildDate = "unknown"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Загружаем .env из текущей директории или рядом с бинарником
|
||||
if err := godotenv.Load(); err != nil {
|
||||
execPath, _ := os.Executable()
|
||||
envPath := filepath.Join(filepath.Dir(execPath), ".env")
|
||||
if err2 := godotenv.Load(envPath); err2 != nil {
|
||||
log.Println("Файл .env не найден, используются переменные окружения shell")
|
||||
}
|
||||
}
|
||||
log.Println("Go Chat Bridge запущен.")
|
||||
log.Printf("Версия: %s, сборка: %s", Version, BuildDate)
|
||||
|
||||
telegramToken := os.Getenv("TELEGRAM_TOKEN")
|
||||
discordToken := os.Getenv("DISCORD_TOKEN")
|
||||
@@ -144,6 +164,67 @@ func main() {
|
||||
bridge.StartDiscordListener(discordChannelID, func(text string, sender string, media []string) { forward(text, "discord", sender, media) })
|
||||
bridge.StartVKListener(func(text string, sender string, media []string) { forward(text, "vk", sender, media) })
|
||||
|
||||
// Прокси медиа Telegram: по подписанному токену отдаём файл без раскрытия токена бота в ссылках
|
||||
http.HandleFunc("/media/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet && r.Method != http.MethodHead {
|
||||
log.Printf("[Media] %s %s — Method not allowed", r.Method, r.URL.Path)
|
||||
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
// Путь: /media/<токен>/<имя_файла.jpg> — имя в конце только для вида, токен до последнего /
|
||||
pathSuffix := strings.TrimPrefix(r.URL.Path, "/media/")
|
||||
if pathSuffix == "" {
|
||||
log.Printf("[Media] запрос без токена")
|
||||
http.Error(w, "Not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
token := pathSuffix
|
||||
if idx := strings.LastIndex(pathSuffix, "/"); idx != -1 {
|
||||
token = pathSuffix[:idx]
|
||||
}
|
||||
secret := os.Getenv("MEDIA_PROXY_SECRET")
|
||||
if secret == "" {
|
||||
log.Printf("[Media] MEDIA_PROXY_SECRET не задан, прокси отключён")
|
||||
http.Error(w, "Proxy not configured", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
filePath, ok := verifyMediaToken(token, secret)
|
||||
if !ok {
|
||||
pathLog := r.URL.Path
|
||||
if len(pathLog) > 50 {
|
||||
pathLog = pathLog[:50] + "..."
|
||||
}
|
||||
log.Printf("[Media] неверный или просроченный токен (path=%s)", pathLog)
|
||||
http.Error(w, "Invalid or expired link", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
log.Printf("[Media] отдача файла: %s", filePath)
|
||||
directURL := bridge.GetTelegramFileDirectURL(filePath)
|
||||
resp, err := http.Get(directURL)
|
||||
if err != nil {
|
||||
log.Printf("[Media] ошибка загрузки из Telegram для %s: %v", filePath, err)
|
||||
http.Error(w, "Failed to fetch file", http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
log.Printf("[Media] Telegram вернул %d для %s", resp.StatusCode, filePath)
|
||||
http.Error(w, "Upstream error", resp.StatusCode)
|
||||
return
|
||||
}
|
||||
if ct := resp.Header.Get("Content-Type"); ct != "" {
|
||||
w.Header().Set("Content-Type", ct)
|
||||
}
|
||||
// Имя файла с расширением — иначе при открытии/сохранении расширение теряется
|
||||
fileName := path.Base(filePath)
|
||||
if fileName != "" && fileName != "." {
|
||||
w.Header().Set("Content-Disposition", "inline; filename=\""+fileName+"\"")
|
||||
}
|
||||
w.Header().Set("Cache-Control", "private, max-age=86400")
|
||||
io.Copy(w, resp.Body)
|
||||
log.Printf("[Media] отдано: %s", filePath)
|
||||
})
|
||||
|
||||
// webhook endpoint
|
||||
http.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
@@ -193,6 +274,11 @@ func main() {
|
||||
w.Write([]byte("ok"))
|
||||
})
|
||||
|
||||
log.Println("Webhook listening on :8080 (/webhook)")
|
||||
if os.Getenv("PUBLIC_URL") != "" && os.Getenv("MEDIA_PROXY_SECRET") != "" {
|
||||
log.Println("Медиа-прокси включён: ссылки из Telegram будут без токена в URL")
|
||||
} else {
|
||||
log.Println("Медиа-прокси выключен (задайте PUBLIC_URL и MEDIA_PROXY_SECRET для включения)")
|
||||
}
|
||||
log.Println("Webhook listening on :8080 (/webhook, /media/)")
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user