Compare commits
10 commits
7c610d0477
...
d9e56de17f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9e56de17f | ||
|
|
fb7f88ff7e | ||
|
|
5f72059bb6 | ||
|
|
fd7868128a | ||
|
|
d9288d2b55 | ||
|
|
724169c09c | ||
|
|
9714464d20 | ||
|
|
4540519753 | ||
|
|
082afea891 | ||
|
|
73314aebbf |
14 changed files with 526 additions and 41 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1 +1,2 @@
|
||||||
.idea
|
.idea
|
||||||
|
config/dev_config.go
|
||||||
|
|
|
||||||
21
Dockerfile
Normal file
21
Dockerfile
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
FROM golang:1.25.7-alpine3.23 AS builder
|
||||||
|
|
||||||
|
WORKDIR /build
|
||||||
|
|
||||||
|
COPY go.* ./
|
||||||
|
|
||||||
|
RUN go mod tidy
|
||||||
|
|
||||||
|
RUN go mod download
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux go build -o app ./
|
||||||
|
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
RUN mkdir -p /home
|
||||||
|
|
||||||
|
COPY --from=builder /build/app /home/app
|
||||||
|
|
||||||
|
CMD ["./home/app"]
|
||||||
|
|
@ -11,6 +11,7 @@ type Config struct {
|
||||||
AppConf AppConfig
|
AppConf AppConfig
|
||||||
TgConf TelegramConfig
|
TgConf TelegramConfig
|
||||||
DsConf DiscordConfig
|
DsConf DiscordConfig
|
||||||
|
HttpConf HttpConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppConfig struct {
|
type AppConfig struct {
|
||||||
|
|
@ -28,10 +29,17 @@ type DiscordConfig struct {
|
||||||
ChannelID snowflake.ID
|
ChannelID snowflake.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HttpConfig struct {
|
||||||
|
Host string
|
||||||
|
Port string
|
||||||
|
GinMode string
|
||||||
|
}
|
||||||
|
|
||||||
|
// prod config
|
||||||
func NewConfig() *Config {
|
func NewConfig() *Config {
|
||||||
return &Config{
|
return &Config{
|
||||||
AppConfig{
|
AppConfig{
|
||||||
LogLvl: "info",
|
LogLvl: getEnv("APP_LOG_LEVEL", "debug"),
|
||||||
},
|
},
|
||||||
TelegramConfig{
|
TelegramConfig{
|
||||||
Token: getEnv("TELEGRAM_TOKEN", ""),
|
Token: getEnv("TELEGRAM_TOKEN", ""),
|
||||||
|
|
@ -42,6 +50,12 @@ func NewConfig() *Config {
|
||||||
GuildID: convertID(getEnv("GUILD_ID", "")),
|
GuildID: convertID(getEnv("GUILD_ID", "")),
|
||||||
ChannelID: convertID(getEnv("CHANNEL_ID", "")),
|
ChannelID: convertID(getEnv("CHANNEL_ID", "")),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
HttpConfig{
|
||||||
|
Host: getEnv("HTTP_HOST", "0.0.0.0"),
|
||||||
|
Port: getEnv("HTTP_PORT", "8080"),
|
||||||
|
GinMode: getEnv("GIN_MODE", "debug"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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")
|
||||||
|
|
||||||
m := discord.MessageCreate{Content: fmt.Sprintf("[%s]\n%s", msg.AuthorName, msg.Content)}
|
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)}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,5 @@ package dto
|
||||||
type DiscordDTO struct {
|
type DiscordDTO struct {
|
||||||
AuthorName string
|
AuthorName string
|
||||||
Content string
|
Content string
|
||||||
|
Images *[]Image
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
dto/image.go
Normal file
6
dto/image.go
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
package dto
|
||||||
|
|
||||||
|
type Image struct {
|
||||||
|
Data []byte
|
||||||
|
Filename string
|
||||||
|
}
|
||||||
|
|
@ -3,4 +3,5 @@ package dto
|
||||||
type TelegramDTO struct {
|
type TelegramDTO struct {
|
||||||
AuthorName string
|
AuthorName string
|
||||||
Content string
|
Content string
|
||||||
|
Images *[]Image
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
go.mod
42
go.mod
|
|
@ -1,18 +1,54 @@
|
||||||
module tg-disc-bot
|
module tg-disc-bot
|
||||||
|
|
||||||
go 1.24.1
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/disgoorg/disgo v0.18.15
|
github.com/disgoorg/disgo v0.18.15
|
||||||
github.com/disgoorg/snowflake/v2 v2.0.3
|
github.com/disgoorg/snowflake/v2 v2.0.3
|
||||||
|
github.com/gin-gonic/gin v1.12.0
|
||||||
github.com/go-telegram/bot v1.14.1
|
github.com/go-telegram/bot v1.14.1
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
|
github.com/zsais/go-gin-prometheus v1.0.3
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
|
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||||
|
github.com/bytedance/sonic v1.15.0 // indirect
|
||||||
|
github.com/bytedance/sonic/loader v0.5.0 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||||
github.com/disgoorg/json v1.2.0 // indirect
|
github.com/disgoorg/json v1.2.0 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
||||||
|
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.30.1 // indirect
|
||||||
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
|
github.com/goccy/go-yaml v1.19.2 // indirect
|
||||||
github.com/gorilla/websocket v1.5.3 // indirect
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
|
github.com/prometheus/client_golang v1.22.0 // indirect
|
||||||
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
|
github.com/prometheus/common v0.65.0 // indirect
|
||||||
|
github.com/prometheus/procfs v0.16.1 // indirect
|
||||||
|
github.com/quic-go/qpack v0.6.0 // indirect
|
||||||
|
github.com/quic-go/quic-go v0.59.0 // indirect
|
||||||
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad // indirect
|
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad // indirect
|
||||||
golang.org/x/crypto v0.36.0 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
golang.org/x/sys v0.31.0 // indirect
|
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||||
|
go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect
|
||||||
|
golang.org/x/arch v0.22.0 // indirect
|
||||||
|
golang.org/x/crypto v0.48.0 // indirect
|
||||||
|
golang.org/x/net v0.51.0 // indirect
|
||||||
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
|
golang.org/x/text v0.34.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.36.10 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
103
go.sum
103
go.sum
|
|
@ -1,3 +1,15 @@
|
||||||
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
|
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
|
||||||
|
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
|
||||||
|
github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE=
|
||||||
|
github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k=
|
||||||
|
github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE=
|
||||||
|
github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
|
||||||
|
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
|
@ -7,25 +19,106 @@ github.com/disgoorg/json v1.2.0 h1:6e/j4BCfSHIvucG1cd7tJPAOp1RgnnMFSqkvZUtEd1Y=
|
||||||
github.com/disgoorg/json v1.2.0/go.mod h1:BHDwdde0rpQFDVsRLKhma6Y7fTbQKub/zdGO5O9NqqA=
|
github.com/disgoorg/json v1.2.0/go.mod h1:BHDwdde0rpQFDVsRLKhma6Y7fTbQKub/zdGO5O9NqqA=
|
||||||
github.com/disgoorg/snowflake/v2 v2.0.3 h1:3B+PpFjr7j4ad7oeJu4RlQ+nYOTadsKapJIzgvSI2Ro=
|
github.com/disgoorg/snowflake/v2 v2.0.3 h1:3B+PpFjr7j4ad7oeJu4RlQ+nYOTadsKapJIzgvSI2Ro=
|
||||||
github.com/disgoorg/snowflake/v2 v2.0.3/go.mod h1:W6r7NUA7DwfZLwr00km6G4UnZ0zcoLBRufhkFWgAc4c=
|
github.com/disgoorg/snowflake/v2 v2.0.3/go.mod h1:W6r7NUA7DwfZLwr00km6G4UnZ0zcoLBRufhkFWgAc4c=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||||
|
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||||
|
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||||
|
github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8=
|
||||||
|
github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
|
github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
|
||||||
|
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
|
||||||
github.com/go-telegram/bot v1.14.1 h1:ySVCITvYsvBSiChOmr6GolLUcWX2T/ugykc2rjIaaQg=
|
github.com/go-telegram/bot v1.14.1 h1:ySVCITvYsvBSiChOmr6GolLUcWX2T/ugykc2rjIaaQg=
|
||||||
github.com/go-telegram/bot v1.14.1/go.mod h1:i2TRs7fXWIeaceF3z7KzsMt/he0TwkVC680mvdTFYeM=
|
github.com/go-telegram/bot v1.14.1/go.mod h1:i2TRs7fXWIeaceF3z7KzsMt/he0TwkVC680mvdTFYeM=
|
||||||
|
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||||
|
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
|
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
|
||||||
|
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||||
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||||
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||||
|
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||||
|
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||||
|
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||||
|
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
|
||||||
|
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||||
|
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||||
|
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||||
|
github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
|
||||||
|
github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
|
||||||
|
github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw=
|
||||||
|
github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU=
|
||||||
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad h1:qIQkSlF5vAUHxEmTbaqt1hkJ/t6skqEGYiMag343ucI=
|
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad h1:qIQkSlF5vAUHxEmTbaqt1hkJ/t6skqEGYiMag343ucI=
|
||||||
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s=
|
github.com/sasha-s/go-csync v0.0.0-20240107134140-fcbab37b09ad/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
|
github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY=
|
||||||
|
github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||||
|
github.com/zsais/go-gin-prometheus v1.0.3 h1:NIYXItaoGNiyDWXqrIzfQHWcRnen+iwgAw4sX/UieiM=
|
||||||
|
github.com/zsais/go-gin-prometheus v1.0.3/go.mod h1:avQI7yOKIhpOi4QJxFZdmZb47AEjmS4MTC4Z6PsNmiA=
|
||||||
|
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
|
||||||
|
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||||
|
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||||
|
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||||
|
golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI=
|
||||||
|
golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
|
||||||
|
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||||
|
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||||
|
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||||
|
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||||
|
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
|
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||||
|
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||||
|
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||||
|
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|
|
||||||
23
main.go
23
main.go
|
|
@ -3,13 +3,16 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
"tg-disc-bot/config"
|
"tg-disc-bot/config"
|
||||||
"tg-disc-bot/discordBot"
|
"tg-disc-bot/discordBot"
|
||||||
"tg-disc-bot/dto"
|
"tg-disc-bot/dto"
|
||||||
|
"tg-disc-bot/router"
|
||||||
"tg-disc-bot/tgBot"
|
"tg-disc-bot/tgBot"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -38,13 +41,33 @@ func main() {
|
||||||
tgMsgs := tgb.Start(fromDiscord)
|
tgMsgs := tgb.Start(fromDiscord)
|
||||||
dsMsgs := dsb.Start(fromTelegram)
|
dsMsgs := dsb.Start(fromTelegram)
|
||||||
|
|
||||||
|
r := router.NewHandler(router.Deps{
|
||||||
|
Addr: net.JoinHostPort(c.HttpConf.Host, c.HttpConf.Port),
|
||||||
|
GinMode: c.HttpConf.GinMode,
|
||||||
|
})
|
||||||
|
|
||||||
log.Info("App is now running. Press CTRL-C to exit.")
|
log.Info("App is now running. Press CTRL-C to exit.")
|
||||||
|
|
||||||
|
errChan := make(chan error, 10)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err = r.Run(); err != nil {
|
||||||
|
errChan <- err
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case sig := <-shutdown:
|
case sig := <-shutdown:
|
||||||
{
|
{
|
||||||
|
shutdownCtx, shutdownCancel := context.WithTimeout(ctx, 15*time.Second)
|
||||||
|
|
||||||
|
if err = r.Shutdown(shutdownCtx); err != nil {
|
||||||
|
log.WithError(err).Error("Error shutting down router")
|
||||||
|
}
|
||||||
|
|
||||||
log.WithField("type", sig).Info("terminating, close app")
|
log.WithField("type", sig).Info("terminating, close app")
|
||||||
|
shutdownCancel()
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
|
|
||||||
67
router/handler.go
Normal file
67
router/handler.go
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
ginprometheus "github.com/zsais/go-gin-prometheus"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Handler struct {
|
||||||
|
srv *http.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
type Deps struct {
|
||||||
|
Addr string
|
||||||
|
GinMode string
|
||||||
|
}
|
||||||
|
|
||||||
|
const pkgLogHeader string = "Router |"
|
||||||
|
|
||||||
|
func NewHandler(deps Deps) *Handler {
|
||||||
|
engine := gin.Default()
|
||||||
|
|
||||||
|
if deps.GinMode == "release" {
|
||||||
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
err := engine.SetTrustedProxies([]string{"172.20.0.0/16"})
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Errorf("%v Set proxies failed", pkgLogHeader)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
engine.GET("/", func(c *gin.Context) { c.JSON(200, gin.H{"msg": "v2"}) })
|
||||||
|
|
||||||
|
p := ginprometheus.NewPrometheus("gin")
|
||||||
|
p.Use(engine)
|
||||||
|
|
||||||
|
engine.Use(gin.LoggerWithConfig(gin.LoggerConfig{
|
||||||
|
Skip: func(c *gin.Context) bool {
|
||||||
|
return c.Request.URL.Path == "/metrics"
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
srv := http.Server{
|
||||||
|
Addr: deps.Addr,
|
||||||
|
Handler: engine,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Handler{
|
||||||
|
srv: &srv,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) Run() error {
|
||||||
|
log.Infof("Starting server on %s", h.srv.Addr)
|
||||||
|
if err := h.srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
|
log.WithError(err).Errorf("%v ListenAndServe failed", pkgLogHeader)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) Shutdown(ctx context.Context) error {
|
||||||
|
return h.srv.Shutdown(ctx)
|
||||||
|
}
|
||||||
14
secret.env
Normal file
14
secret.env
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#APP
|
||||||
|
APP_LOG_LEVEL=info
|
||||||
|
HTTP_HOST=0.0.0.0
|
||||||
|
HTTP_PORT=8080
|
||||||
|
GIN_MODE=release
|
||||||
|
|
||||||
|
#Telegram
|
||||||
|
TELEGRAM_TOKEN=
|
||||||
|
TELEGRAM_CHANNEL_ID=
|
||||||
|
|
||||||
|
#Discord
|
||||||
|
DISCORD_TOKEN=
|
||||||
|
GUILD_ID=
|
||||||
|
CHANNEL_ID=
|
||||||
182
tgBot/handler.go
182
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...")
|
||||||
|
|
@ -57,14 +57,154 @@ func (b *TgBot) Start(fromDiscord chan dto.DiscordDTO) chan dto.TelegramDTO {
|
||||||
go func() {
|
go func() {
|
||||||
for msg := range fromDiscord {
|
for msg := range fromDiscord {
|
||||||
log.WithField("content", msg).Debug("TG | Message from Discord")
|
log.WithField("content", msg).Debug("TG | Message from Discord")
|
||||||
m := fmt.Sprintf("[%s]\n%s", msg.AuthorName, msg.Content)
|
|
||||||
|
m := fmt.Sprintf("*\\[ %s \\]*\n%s", msg.AuthorName, msg.Content)
|
||||||
|
|
||||||
b.bot.SendMessage(b.ctx, &bot.SendMessageParams{
|
b.bot.SendMessage(b.ctx, &bot.SendMessageParams{
|
||||||
ChatID: b.chatID,
|
ChatID: b.chatID,
|
||||||
Text: m,
|
Text: m,
|
||||||
|
ParseMode: "",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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: b.getName(update),
|
||||||
|
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: b.getName(update),
|
||||||
|
Content: content,
|
||||||
|
Images: &images,
|
||||||
|
}
|
||||||
|
|
||||||
|
msgChan <- msg
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *TgBot) getName(update *models.Update) string {
|
||||||
|
switch {
|
||||||
|
case update.Message.From.Username != "":
|
||||||
|
return update.Message.From.Username
|
||||||
|
case update.Message.From.FirstName != "":
|
||||||
|
return update.Message.From.FirstName
|
||||||
|
case update.Message.From.LastName != "":
|
||||||
|
return update.Message.From.LastName
|
||||||
|
default:
|
||||||
|
return "No name"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue