Добавлена пересылка медиа файлов

This commit is contained in:
Taz
2025-09-04 13:32:58 +02:00
parent 7e941e1497
commit 2e1fb49d9a
4 changed files with 203 additions and 130 deletions
+10 -2
View File
@@ -2,16 +2,24 @@ package main
import ( import (
"log" "log"
"github.com/bwmarrin/discordgo" "github.com/bwmarrin/discordgo"
) )
func (b *Bridge) StartDiscordListener(forward func(text string, from string)) { func (b *Bridge) StartDiscordListener(forward func(text string, sender string, media []string)) {
b.Discord.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) { b.Discord.AddHandler(func(s *discordgo.Session, m *discordgo.MessageCreate) {
if m.Author.Bot { if m.Author.Bot {
return return
} }
// Собираем URL вложений
media := make([]string, 0)
for _, a := range m.Attachments {
if a.URL != "" {
media = append(media, a.URL)
}
}
log.Printf("[Discord] %s: %s", m.Author.Username, m.Content) log.Printf("[Discord] %s: %s", m.Author.Username, m.Content)
forward(m.Content, m.Author.Username) forward(m.Content, m.Author.Username, media)
}) })
_ = b.Discord.Open() _ = b.Discord.Open()
} }
+131 -122
View File
@@ -1,142 +1,151 @@
package main package main
import ( import (
"encoding/json"
"log" "log"
"net/http"
"os" "os"
"strconv" "strconv"
"net/http" "strings"
"encoding/json"
) )
func main() { func main() {
log.Println("Go Chat Bridge запущен.") log.Println("Go Chat Bridge запущен.")
telegramToken := os.Getenv("TELEGRAM_TOKEN") telegramToken := os.Getenv("TELEGRAM_TOKEN")
discordToken := os.Getenv("DISCORD_TOKEN") discordToken := os.Getenv("DISCORD_TOKEN")
vkToken := os.Getenv("VK_TOKEN") vkToken := os.Getenv("VK_TOKEN")
if telegramToken == "" || discordToken == "" || vkToken == "" { if telegramToken == "" || discordToken == "" || vkToken == "" {
log.Fatal("Необходимо задать переменные окружения TELEGRAM_TOKEN, DISCORD_TOKEN, VK_TOKEN") log.Fatal("Необходимо задать переменные окружения TELEGRAM_TOKEN, DISCORD_TOKEN, VK_TOKEN")
} }
bridge, err := NewBridge(telegramToken, discordToken, vkToken) bridge, err := NewBridge(telegramToken, discordToken, vkToken)
if err != nil { if err != nil {
log.Fatalf("Ошибка инициализации Bridge: %v", err) log.Fatalf("Ошибка инициализации Bridge: %v", err)
} }
log.Println("Bridge успешно инициализирован:", bridge) log.Println("Bridge успешно инициализирован:", bridge)
// Получаем ID чатов/каналов из переменных окружения // Получаем ID чатов/каналов из переменных окружения
telegramChatID := os.Getenv("TELEGRAM_CHAT_ID") // int64 telegramChatID := os.Getenv("TELEGRAM_CHAT_ID") // int64
discordChannelID := os.Getenv("DISCORD_CHANNEL_ID") // string discordChannelID := os.Getenv("DISCORD_CHANNEL_ID") // string
vkPeerID := os.Getenv("VK_PEER_ID") // int vkPeerID := os.Getenv("VK_PEER_ID") // int
forward := func(text string, from string, sender string) { forward := func(text string, from string, sender string, media []string) {
log.Printf("[Bridge] Пересылка сообщения от %s (%s): %s", from, sender, text) // Собираем итоговый текст с медиа URL, если есть
msg := text
switch from { if len(media) > 0 {
case "telegram": if msg != "" {
if discordChannelID != "" { msg += "\n"
_ = bridge.SendToDiscord(discordChannelID, "[TG] "+sender+": "+text) }
} msg += strings.Join(media, "\n")
if vkPeerID != "" {
if id, err := strconv.Atoi(vkPeerID); err == nil {
_ = bridge.SendToVK(id, "[TG] "+sender+": "+text)
}
}
_ = bridge.SendToSite("[TG] " + sender + ": " + text)
case "discord":
if telegramChatID != "" {
if id, err := strconv.ParseInt(telegramChatID, 10, 64); err == nil {
_ = bridge.SendToTelegram(id, "[DS] "+sender+": "+text)
}
}
if vkPeerID != "" {
if id, err := strconv.Atoi(vkPeerID); err == nil {
_ = bridge.SendToVK(id, "[DS] "+sender+": "+text)
}
}
_ = bridge.SendToSite("[DS] " + sender + ": " + text)
case "vk":
if telegramChatID != "" {
if id, err := strconv.ParseInt(telegramChatID, 10, 64); err == nil {
_ = bridge.SendToTelegram(id, "[VK] "+sender+": "+text)
}
}
if discordChannelID != "" {
_ = bridge.SendToDiscord(discordChannelID, "[VK] "+sender+": "+text)
}
_ = bridge.SendToSite("[VK] " + sender + ": " + text)
case "site":
if telegramChatID != "" {
if id, err := strconv.ParseInt(telegramChatID, 10, 64); err == nil {
_ = bridge.SendToTelegram(id, "[SITE] "+sender+": "+text)
}
}
if discordChannelID != "" {
_ = bridge.SendToDiscord(discordChannelID, "[SITE] "+sender+": "+text)
}
if vkPeerID != "" {
if id, err := strconv.Atoi(vkPeerID); err == nil {
_ = bridge.SendToVK(id, "[SITE] "+sender+": "+text)
}
}
}
} }
log.Printf("[Bridge] Пересылка сообщения от %s (%s): %s", from, sender, msg)
bridge.StartTelegramListener(func(text, sender string) { forward(text, "telegram", sender) }) switch from {
bridge.StartDiscordListener(func(text, sender string) { forward(text, "discord", sender) }) case "telegram":
bridge.StartVKListener(func(text, sender string) { forward(text, "vk", sender) }) if discordChannelID != "" {
_ = bridge.SendToDiscord(discordChannelID, "[TG] "+sender+": "+msg)
}
if vkPeerID != "" {
if id, err := strconv.Atoi(vkPeerID); err == nil {
_ = bridge.SendToVK(id, "[TG] "+sender+": "+msg)
}
}
_ = bridge.SendToSite("[TG] " + sender + ": " + msg)
case "discord":
if telegramChatID != "" {
if id, err := strconv.ParseInt(telegramChatID, 10, 64); err == nil {
_ = bridge.SendToTelegram(id, "[DS] "+sender+": "+msg)
}
}
if vkPeerID != "" {
if id, err := strconv.Atoi(vkPeerID); err == nil {
_ = bridge.SendToVK(id, "[DS] "+sender+": "+msg)
}
}
_ = bridge.SendToSite("[DS] " + sender + ": " + msg)
case "vk":
if telegramChatID != "" {
if id, err := strconv.ParseInt(telegramChatID, 10, 64); err == nil {
_ = bridge.SendToTelegram(id, "[VK] "+sender+": "+msg)
}
}
if discordChannelID != "" {
_ = bridge.SendToDiscord(discordChannelID, "[VK] "+sender+": "+msg)
}
_ = bridge.SendToSite("[VK] " + sender + ": " + msg)
case "site":
if telegramChatID != "" {
if id, err := strconv.ParseInt(telegramChatID, 10, 64); err == nil {
_ = bridge.SendToTelegram(id, "[SITE] "+sender+": "+msg)
}
}
if discordChannelID != "" {
_ = bridge.SendToDiscord(discordChannelID, "[SITE] "+sender+": "+msg)
}
if vkPeerID != "" {
if id, err := strconv.Atoi(vkPeerID); err == nil {
_ = bridge.SendToVK(id, "[SITE] "+sender+": "+msg)
}
}
}
}
// webhook endpoint bridge.StartTelegramListener(func(text string, sender string, media []string) { forward(text, "telegram", sender, media) })
http.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) { bridge.StartDiscordListener(func(text string, sender string, media []string) { forward(text, "discord", sender, media) })
if r.Method != http.MethodPost { bridge.StartVKListener(func(text string, sender string, media []string) { forward(text, "vk", sender, media) })
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
apiKey := os.Getenv("WEBHOOK_API_KEY")
if apiKey == "" {
http.Error(w, "Webhook API key not set", http.StatusInternalServerError)
return
}
key := r.URL.Query().Get("key")
if key == "" {
// также можно принимать ключ в теле запроса
var req struct {
Key string `json:"key"`
Text string `json:"text"`
Sender string `json:"sender"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Bad request", http.StatusBadRequest)
return
}
if req.Key != apiKey {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
forward(req.Text, "site", req.Sender)
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
return
}
if key != apiKey {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
var req struct {
Text string `json:"text"`
Sender string `json:"sender"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Bad request", http.StatusBadRequest)
return
}
forward(req.Text, "site", req.Sender)
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})
log.Println("Webhook listening on :8080 (/webhook)") // webhook endpoint
log.Fatal(http.ListenAndServe(":8080", nil)) http.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
apiKey := os.Getenv("WEBHOOK_API_KEY")
if apiKey == "" {
http.Error(w, "Webhook API key not set", http.StatusInternalServerError)
return
}
key := r.URL.Query().Get("key")
if key == "" {
// также можно принимать ключ в теле запроса
var req struct {
Key string `json:"key"`
Text string `json:"text"`
Sender string `json:"sender"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Bad request", http.StatusBadRequest)
return
}
if req.Key != apiKey {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
forward(req.Text, "site", req.Sender, nil)
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
return
}
if key != apiKey {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
var req struct {
Text string `json:"text"`
Sender string `json:"sender"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "Bad request", http.StatusBadRequest)
return
}
forward(req.Text, "site", req.Sender, nil)
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
})
log.Println("Webhook listening on :8080 (/webhook)")
log.Fatal(http.ListenAndServe(":8080", nil))
} }
+58 -3
View File
@@ -1,12 +1,13 @@
package main package main
import ( import (
"fmt"
"log" "log"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
) )
func (b *Bridge) StartTelegramListener(forward func(text string, from string)) { func (b *Bridge) StartTelegramListener(forward func(text string, sender string, media []string)) {
u := tgbotapi.NewUpdate(0) u := tgbotapi.NewUpdate(0)
u.Timeout = 60 u.Timeout = 60
@@ -22,9 +23,63 @@ func (b *Bridge) StartTelegramListener(forward func(text string, from string)) {
if update.Message.From.UserName != "" { if update.Message.From.UserName != "" {
userInfo += " " + update.Message.From.UserName userInfo += " " + update.Message.From.UserName
} }
// Собираем медиа URL'ы
media := make([]string, 0)
getFileURL := func(fileID string) (string, error) {
file, err := b.Telegram.GetFile(tgbotapi.FileConfig{FileID: fileID})
if err != nil {
return "", err
}
return fmt.Sprintf("https://api.telegram.org/file/bot%s/%s", b.Telegram.Token, file.FilePath), nil
}
// Фото (берём самое большое)
if len(update.Message.Photo) > 0 {
photo := update.Message.Photo[len(update.Message.Photo)-1]
if url, err := getFileURL(photo.FileID); err == nil {
media = append(media, url)
}
}
// Document
if update.Message.Document != nil {
if url, err := getFileURL(update.Message.Document.FileID); err == nil {
media = append(media, url)
}
}
// Video
if update.Message.Video != nil {
if url, err := getFileURL(update.Message.Video.FileID); err == nil {
media = append(media, url)
}
}
// Audio
if update.Message.Audio != nil {
if url, err := getFileURL(update.Message.Audio.FileID); err == nil {
media = append(media, url)
}
}
// Voice
if update.Message.Voice != nil {
if url, err := getFileURL(update.Message.Voice.FileID); err == nil {
media = append(media, url)
}
}
// Animation (GIF)
if update.Message.Animation != nil {
if url, err := getFileURL(update.Message.Animation.FileID); err == nil {
media = append(media, url)
}
}
log.Printf("[Telegram] %s: %s", userInfo, update.Message.Text) log.Printf("[Telegram] %s: %s", userInfo, update.Message.Text)
// Передаём имя отправителя // Передаём имя отправителя и медиа
forward(update.Message.Text, userInfo) forward(update.Message.Text, userInfo, media)
} }
}() }()
} }
+4 -3
View File
@@ -1,15 +1,16 @@
package main package main
import ( import (
"context"
"log" "log"
"os" "os"
"strconv" "strconv"
"context"
"github.com/SevereCloud/vksdk/v2/events" "github.com/SevereCloud/vksdk/v2/events"
"github.com/SevereCloud/vksdk/v2/longpoll-bot" "github.com/SevereCloud/vksdk/v2/longpoll-bot"
) )
func (b *Bridge) StartVKListener(forward func(text string, from string)) { func (b *Bridge) StartVKListener(forward func(text string, sender string, media []string)) {
groupIDStr := os.Getenv("VK_GROUP_ID") groupIDStr := os.Getenv("VK_GROUP_ID")
if groupIDStr == "" { if groupIDStr == "" {
log.Println("VK_GROUP_ID не задана в переменных окружения") log.Println("VK_GROUP_ID не задана в переменных окружения")
@@ -33,7 +34,7 @@ func (b *Bridge) StartVKListener(forward func(text string, from string)) {
if name, err := b.GetVKUserName(obj.Message.FromID); err == nil { if name, err := b.GetVKUserName(obj.Message.FromID); err == nil {
sender = name sender = name
} }
forward(obj.Message.Text, sender) forward(obj.Message.Text, sender, nil)
}) })
go lp.Run() go lp.Run()
} }