diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..1cdc03a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +Dockerfile +docker-compose.yml +.env diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4c49bd7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bc56fdc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +# Go Chat Bridge Dockerfile +FROM golang:1.22-alpine AS builder +WORKDIR /app +COPY . . +RUN go mod tidy && go build -o chat-bridge . + +FROM alpine:latest +WORKDIR /app +COPY --from=builder /app/chat-bridge . + +# Переменные окружения (можно задать через docker run -e ...) +ENV TELEGRAM_TOKEN="" +ENV DISCORD_TOKEN="" +ENV VK_TOKEN="" +ENV TELEGRAM_CHAT_ID="" +ENV DISCORD_CHANNEL_ID="" +ENV VK_PEER_ID="" +ENV VK_GROUP_ID="" + +CMD ["./chat-bridge"] diff --git a/bridge.go b/bridge.go index 8378265..ceb284d 100644 --- a/bridge.go +++ b/bridge.go @@ -1,11 +1,21 @@ package main import ( + "strconv" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" "github.com/bwmarrin/discordgo" "github.com/SevereCloud/vksdk/v2/api" ) +// Получить имя пользователя VK по id +func (b *Bridge) GetVKUserName(userID int) (string, error) { + resp, err := b.VK.UsersGet(api.Params{"user_ids": userID}) + if err != nil || len(resp) == 0 { + return strconv.Itoa(userID), err + } + return resp[0].FirstName + " " + resp[0].LastName, nil +} + // Структура для хранения клиентов type Bridge struct { Telegram *tgbotapi.BotAPI diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..041e50f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,14 @@ +version: '3.8' +services: + chat-bridge: + build: . + container_name: chat-bridge + environment: + TELEGRAM_TOKEN: "${TELEGRAM_TOKEN}" + DISCORD_TOKEN: "${DISCORD_TOKEN}" + VK_TOKEN: "${VK_TOKEN}" + TELEGRAM_CHAT_ID: "${TELEGRAM_CHAT_ID}" + DISCORD_CHANNEL_ID: "${DISCORD_CHANNEL_ID}" + VK_PEER_ID: "${VK_PEER_ID}" + VK_GROUP_ID: "${VK_GROUP_ID}" + restart: unless-stopped diff --git a/main.go b/main.go index 3954942..d8dde74 100644 --- a/main.go +++ b/main.go @@ -29,49 +29,45 @@ func main() { discordChannelID := os.Getenv("DISCORD_CHANNEL_ID") // string vkPeerID := os.Getenv("VK_PEER_ID") // int - forward := func(text string, from string) { - log.Printf("[Bridge] Пересылка сообщения от %s: %s", from, text) + forward := func(text string, from string, sender string) { + log.Printf("[Bridge] Пересылка сообщения от %s (%s): %s", from, sender, text) - // Определяем источник и рассылаем в остальные платформы - switch { - case from == "telegram": - // В Discord и VK - if discordChannelID != "" { - _ = bridge.SendToDiscord(discordChannelID, "[TG] "+from+": "+text) - } - if vkPeerID != "" { - if id, err := strconv.Atoi(vkPeerID); err == nil { - _ = bridge.SendToVK(id, "[TG] "+from+": "+text) + switch from { + case "telegram": + if discordChannelID != "" { + _ = bridge.SendToDiscord(discordChannelID, "[TG] "+sender+": "+text) } - } - case from == "discord": - // В Telegram и VK - if telegramChatID != "" { - if id, err := strconv.ParseInt(telegramChatID, 10, 64); err == nil { - _ = bridge.SendToTelegram(id, "[DS] "+from+": "+text) + if vkPeerID != "" { + if id, err := strconv.Atoi(vkPeerID); err == nil { + _ = bridge.SendToVK(id, "[TG] "+sender+": "+text) + } } - } - if vkPeerID != "" { - if id, err := strconv.Atoi(vkPeerID); err == nil { - _ = bridge.SendToVK(id, "[DS] "+from+": "+text) + case "discord": + if telegramChatID != "" { + if id, err := strconv.ParseInt(telegramChatID, 10, 64); err == nil { + _ = bridge.SendToTelegram(id, "[DS] "+sender+": "+text) + } } - } - default: - // Считаем, что from — это VK ID - if telegramChatID != "" { - if id, err := strconv.ParseInt(telegramChatID, 10, 64); err == nil { - _ = bridge.SendToTelegram(id, "[VK] VK ID "+from+": "+text) + if vkPeerID != "" { + if id, err := strconv.Atoi(vkPeerID); err == nil { + _ = bridge.SendToVK(id, "[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) } - } - if discordChannelID != "" { - _ = bridge.SendToDiscord(discordChannelID, "[VK] VK ID "+from+": "+text) } } - } - bridge.StartTelegramListener(func(text, from string) { forward(text, from) }) - bridge.StartDiscordListener(func(text, from string) { forward(text, from) }) - bridge.StartVKListener(func(text, _ string) { forward(text, "vk") }) + bridge.StartTelegramListener(func(text, sender string) { forward(text, "telegram", sender) }) + bridge.StartDiscordListener(func(text, sender string) { forward(text, "discord", sender) }) + bridge.StartVKListener(func(text, sender string) { forward(text, "vk", sender) }) select {} // Блокируем main, чтобы слушатели работали } diff --git a/vk_listener.go b/vk_listener.go index 96f27b8..fac4eb4 100644 --- a/vk_listener.go +++ b/vk_listener.go @@ -29,8 +29,11 @@ func (b *Bridge) StartVKListener(forward func(text string, from string)) { lp.MessageNew(func(_ context.Context, obj events.MessageNewObject) { log.Printf("[VK] %d: %s", obj.Message.FromID, obj.Message.Text) - // Передаём текст и имя отправителя (ID) - forward(obj.Message.Text, strconv.Itoa(obj.Message.FromID)) + sender := "vk:" + strconv.Itoa(obj.Message.FromID) + if name, err := b.GetVKUserName(obj.Message.FromID); err == nil { + sender = name + } + forward(obj.Message.Text, sender) }) go lp.Run() }