added: image send

This commit is contained in:
nquidox 2025-03-29 22:00:58 +03:00
parent 4540519753
commit 9714464d20
3 changed files with 218 additions and 25 deletions

View file

@ -1,6 +1,7 @@
package discordBot package discordBot
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
"github.com/disgoorg/disgo" "github.com/disgoorg/disgo"
@ -18,11 +19,16 @@ type DiscordBot struct {
client bot.Client client bot.Client
guildID snowflake.ID guildID snowflake.ID
channelID snowflake.ID channelID snowflake.ID
token string
} }
func NewDiscordBot(ctx context.Context, config config.DiscordConfig) (*DiscordBot, error) { func NewDiscordBot(ctx context.Context, config config.DiscordConfig) (*DiscordBot, error) {
var err error var err error
dsBot := &DiscordBot{ctx: ctx, channelID: config.ChannelID} dsBot := &DiscordBot{
ctx: ctx,
channelID: config.ChannelID,
token: config.Token,
}
dsBot.client, err = disgo.New(config.Token, dsBot.client, err = disgo.New(config.Token,
bot.WithGatewayConfigOpts( bot.WithGatewayConfigOpts(
@ -40,7 +46,7 @@ func NewDiscordBot(ctx context.Context, config config.DiscordConfig) (*DiscordBo
return dsBot, nil return dsBot, nil
} }
func (d *DiscordBot) Start(fromTelegram chan dto.TelegramDTO) chan dto.DiscordDTO { func (d *DiscordBot) Start(fromTelegram <-chan dto.TelegramDTO) chan dto.DiscordDTO {
log.Info("Starting discord bot...") log.Info("Starting discord bot...")
msgChan := make(chan dto.DiscordDTO, 100) msgChan := make(chan dto.DiscordDTO, 100)
@ -50,11 +56,26 @@ func (d *DiscordBot) Start(fromTelegram chan dto.TelegramDTO) chan dto.DiscordDT
for msg := range fromTelegram { for msg := range fromTelegram {
log.WithField("content", msg).Debug("DS | Message from Telegram") log.WithField("content", msg).Debug("DS | Message from Telegram")
var files []*discord.File
for _, media := range *(msg.Images) {
file := &discord.File{
Name: media.Filename,
Reader: bytes.NewReader(media.Data),
}
files = append(files, file)
}
m := discord.MessageCreate{Content: fmt.Sprintf("[%s]\n%s", msg.AuthorName, msg.Content)} m := discord.MessageCreate{Content: fmt.Sprintf("[%s]\n%s", msg.AuthorName, msg.Content)}
if len(files) > 0 {
m.Files = append(m.Files, files...)
}
_, err := d.client.Rest().CreateMessage(d.channelID, m) _, err := d.client.Rest().CreateMessage(d.channelID, m)
if err != nil { if err != nil {
log.Errorf("Failed to send message to Discord: %v", err) log.Errorf("Failed to send message to Discord: %v", err)
continue
} }
} }
}() }()

View file

@ -2,8 +2,11 @@ package discordBot
import ( import (
"github.com/disgoorg/disgo/bot" "github.com/disgoorg/disgo/bot"
"github.com/disgoorg/disgo/discord"
"github.com/disgoorg/disgo/events" "github.com/disgoorg/disgo/events"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"io"
"net/http"
"tg-disc-bot/dto" "tg-disc-bot/dto"
) )
@ -14,9 +17,20 @@ type messageHandler struct {
func (m *messageHandler) OnEvent(event bot.Event) { func (m *messageHandler) OnEvent(event bot.Event) {
if e, ok := event.(*events.MessageCreate); ok { if e, ok := event.(*events.MessageCreate); ok {
if !e.Message.Author.Bot { if !e.Message.Author.Bot {
attachments := e.Message.Attachments
var images *[]dto.Image
var err error
if len(attachments) > 0 {
images, err = getImages(attachments)
if err != nil {
log.Warnf("could not get images from attachments: %v", err)
}
}
message := dto.DiscordDTO{ message := dto.DiscordDTO{
AuthorName: e.Message.Author.Username, AuthorName: e.Message.Author.Username,
Content: e.Message.Content, Content: e.Message.Content,
Images: images,
} }
m.msgChan <- message m.msgChan <- message
@ -26,3 +40,36 @@ func (m *messageHandler) OnEvent(event bot.Event) {
} }
} }
func getImages(a []discord.Attachment) (*[]dto.Image, error) {
var images []dto.Image
for _, item := range a {
if (*item.ContentType == "image/png") || (*item.ContentType == "image/jpeg") {
imageData, err := downloadImage(item.URL)
if err != nil {
log.Errorf("Error downloading image: %s", err)
return nil, err
}
images = append(images, dto.Image{
Data: imageData,
Filename: item.Filename,
})
}
}
return &images, nil
}
func downloadImage(url string) ([]byte, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return data, nil
}

View file

@ -1,23 +1,40 @@
package tgBot package tgBot
import ( import (
"bytes"
"context" "context"
"fmt" "fmt"
"github.com/go-telegram/bot" "github.com/go-telegram/bot"
"github.com/go-telegram/bot/models" "github.com/go-telegram/bot/models"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"io"
"net/http"
"path/filepath"
"sync"
"tg-disc-bot/config" "tg-disc-bot/config"
"tg-disc-bot/dto" "tg-disc-bot/dto"
"time"
) )
type TgBot struct { type TgBot struct {
ctx context.Context ctx context.Context
bot *bot.Bot bot *bot.Bot
chatID int64 chatID int64
token string
msgChan chan dto.TelegramDTO
mediaGroupCache map[string][]dto.Image
cacheMutex sync.Mutex
} }
func NewTgBot(ctx context.Context, config config.TelegramConfig) (*TgBot, error) { func NewTgBot(ctx context.Context, config config.TelegramConfig) (*TgBot, error) {
tgBot := &TgBot{ctx: ctx, chatID: config.ChatID} tgBot := &TgBot{
ctx: ctx,
chatID: config.ChatID,
token: config.Token,
msgChan: make(chan dto.TelegramDTO, 100),
mediaGroupCache: make(map[string][]dto.Image, 10),
cacheMutex: sync.Mutex{},
}
var err error var err error
tgBot.bot, err = bot.New(config.Token) tgBot.bot, err = bot.New(config.Token)
@ -30,24 +47,7 @@ func NewTgBot(ctx context.Context, config config.TelegramConfig) (*TgBot, error)
func (b *TgBot) Start(fromDiscord chan dto.DiscordDTO) chan dto.TelegramDTO { func (b *TgBot) Start(fromDiscord chan dto.DiscordDTO) chan dto.TelegramDTO {
msgChan := make(chan dto.TelegramDTO, 100) b.bot.RegisterHandler(bot.HandlerTypeMessageText, "", bot.MatchTypeContains, b.mainHandler)
b.bot.RegisterHandler(
bot.HandlerTypeMessageText,
"",
bot.MatchTypeContains,
func(ctx context.Context, bt *bot.Bot, update *models.Update) {
if update.Message != nil || !update.Message.From.IsBot {
msg := dto.TelegramDTO{
AuthorName: update.Message.From.Username,
Content: update.Message.Text,
}
fmt.Println(update.Message.Chat.ID)
msgChan <- msg
}
})
go func() { go func() {
log.Info("Starting telegram bot...") log.Info("Starting telegram bot...")
@ -63,8 +63,133 @@ func (b *TgBot) Start(fromDiscord chan dto.DiscordDTO) chan dto.TelegramDTO {
ChatID: b.chatID, ChatID: b.chatID,
Text: m, Text: m,
}) })
if msg.Images != nil {
var mediaGroup []models.InputMedia
for _, img := range *msg.Images {
photo := &models.InputMediaPhoto{
Media: fmt.Sprintf("attach://%s", img.Filename),
Caption: "test caption",
MediaAttachment: bytes.NewReader(img.Data),
}
mediaGroup = append(mediaGroup, photo)
}
_, err := b.bot.SendMediaGroup(b.ctx, &bot.SendMediaGroupParams{
ChatID: b.chatID,
Media: mediaGroup,
})
if err != nil {
log.Error("TG | Failed to send media group")
}
}
} }
}() }()
return msgChan return b.msgChan
}
func (b *TgBot) mainHandler(ctx context.Context, bt *bot.Bot, update *models.Update) {
if update.Message != nil && !update.Message.From.IsBot {
mediaGroupID := update.Message.MediaGroupID
if mediaGroupID != "" {
b.processMediaGroup(update, mediaGroupID, b.msgChan)
} else {
b.proccessSimple(update, b.msgChan)
}
}
}
func (b *TgBot) getImage(photo models.PhotoSize) *dto.Image {
fileID := &bot.GetFileParams{FileID: photo.FileID}
file, err := b.bot.GetFile(b.ctx, fileID)
if err != nil {
log.Errorf("GetFile error: %s", err)
return nil
}
if file.FilePath == "" {
log.Errorf("FilePath is empty for fileID: %s", photo.FileID)
return nil
}
resp, err := http.Get(fmt.Sprintf("https://api.telegram.org/file/bot%s/%s", b.token, file.FilePath))
if err != nil {
log.Errorf("Download error: %s", err)
return nil
}
defer resp.Body.Close()
imgBytes, err := io.ReadAll(resp.Body)
if err != nil {
log.Errorf("ReadAll error: %s", err)
return nil
}
image := dto.Image{
Filename: filepath.Base(file.FilePath),
Data: imgBytes,
}
return &image
}
func (b *TgBot) proccessSimple(update *models.Update, msgChan chan<- dto.TelegramDTO) {
var images []dto.Image
content := update.Message.Text
if update.Message.Photo != nil {
largest := update.Message.Photo[len(update.Message.Photo)-1]
images = append(images, *b.getImage(largest))
content = update.Message.Caption
}
msg := dto.TelegramDTO{
AuthorName: update.Message.From.Username,
Content: content,
Images: &images,
}
msgChan <- msg
}
func (b *TgBot) processMediaGroup(update *models.Update, mediaGroupID string, msgChan chan<- dto.TelegramDTO) {
b.cacheMutex.Lock()
defer b.cacheMutex.Unlock()
if update.Message.Photo != nil {
largest := update.Message.Photo[len(update.Message.Photo)-1]
image := b.getImage(largest)
b.mediaGroupCache[mediaGroupID] = append(b.mediaGroupCache[mediaGroupID], *image)
}
var content string
if update.Message.Caption != "" {
content = update.Message.Caption
} else {
content = update.Message.Text
}
go func() {
time.Sleep(2 * time.Second)
b.cacheMutex.Lock()
defer b.cacheMutex.Unlock()
images, exists := b.mediaGroupCache[mediaGroupID]
if !exists || len(images) == 0 {
return
}
delete(b.mediaGroupCache, mediaGroupID)
msg := dto.TelegramDTO{
AuthorName: update.Message.From.Username,
Content: content,
Images: &images,
}
msgChan <- msg
}()
} }