added: image send
This commit is contained in:
parent
4540519753
commit
9714464d20
3 changed files with 218 additions and 25 deletions
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
||||||
171
tgBot/handler.go
171
tgBot/handler.go
|
|
@ -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
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue