From 44d7ac1f4a93c63c8fd565667bbc358ed1697bdf Mon Sep 17 00:00:00 2001 From: Alexander Kiryukhin Date: Wed, 17 Apr 2019 15:07:50 +0300 Subject: Refactoring --- .gitignore | 1 + bot.go | 159 ++++-------------------------------------------------- go.mod | 2 + lib/models.go | 14 +++++ plugins/plugin.go | 7 +++ plugins/tg.go | 129 ++++++++++++++++++++++++++++++++++++++++++++ plugins/tt.go | 107 ++++++++++++++++++++++++++++++++++++ 7 files changed, 270 insertions(+), 149 deletions(-) create mode 100644 .gitignore create mode 100644 lib/models.go create mode 100644 plugins/plugin.go create mode 100644 plugins/tg.go create mode 100644 plugins/tt.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/bot.go b/bot.go index 0ad1620..d3d8a8e 100644 --- a/bot.go +++ b/bot.go @@ -1,171 +1,32 @@ package main import ( - "context" - "fmt" "log" "os" - "strings" - "github.com/go-telegram-bot-api/telegram-bot-api" "github.com/neonxp/rutina" - "github.com/neonxp/tamtam" -) - -type message struct { - From string - To int64 - Text string - Images []string - Sticker string -} -type routing struct { - TgID int64 - TTID int64 -} + "transport/lib" + "transport/plugins" +) func main() { tamtamToken := os.Getenv("TAMTAM") telegramToken := os.Getenv("TELEGRAM") r := rutina.New() - routes := []routing{ + routes := []lib.Routing{ {TgID: -1001046507545, TTID: -69062921115159}, } - tt2tg := make(chan message, 1) - tg2tt := make(chan message, 1) - - // region TamTam - tamtamApi := tamtam.New(tamtamToken) - ttch := make(chan interface{}, 1) - r.Go(func(ctx context.Context) error { - for { - select { - case <-ctx.Done(): - return nil - case upd := <-ttch: - log.Printf("[TT] Received: %#v", upd) - switch upd := upd.(type) { - case tamtam.UpdateMessageCreated: - for _, r := range routes { - if r.TTID == upd.Message.Recipient.ChatId { - from := upd.Message.Sender.Name - if upd.Message.Sender.Username != "" { - from = fmt.Sprintf("%s (%s)", upd.Message.Sender.Name, upd.Message.Sender.Username) - } - isSticker := "" - images := make([]string, 0) - for _, a := range upd.Message.Body.Attachments { - switch a := a.(type) { - case *tamtam.PhotoAttachment: - images = append(images, a.Payload.Url) - case *tamtam.StickerAttachment: - images = append(images, a.Payload.Url) - isSticker = "STICKER" - } - } - tt2tg <- message{ - To: r.TgID, - From: from, - Text: upd.Message.Body.Text, - Images: images, - Sticker: isSticker, - } - } - } - - default: - log.Printf("Unknown type: %#v", upd) - } - case msg := <-tg2tt: - - text := fmt.Sprintf("[TG] %s: %s", msg.From, msg.Text) - if msg.Sticker != "" { - text = fmt.Sprintf("[TG] %s: [%s]", msg.From, msg.Sticker) - } - if len(msg.Images) > 0 { - text += "[IMAGES] " + strings.Join(msg.Images, " ") - } - res, err := tamtamApi.SendMessage(msg.To, msg.To, &tamtam.NewMessageBody{ - Text: text, - }) - log.Printf("[TT] Answer: %#v %#v", res, err) - } - } - }, rutina.ShutdownIfDone, rutina.RestartIfFail) - r.Go(func(ctx context.Context) error { - return tamtamApi.GetUpdatesLoop(ctx, ttch) - }, rutina.ShutdownIfDone, rutina.RestartIfFail) - // endregion - - // region Telegram - tgApi, err := tgbotapi.NewBotAPI(telegramToken) - if err != nil { - log.Panic(err) - } + tt2tg := make(chan lib.Message, 1) + tg2tt := make(chan lib.Message, 1) - u := tgbotapi.NewUpdate(0) - u.Timeout = 60 - updates, err := tgApi.GetUpdatesChan(u) - r.Go(func(ctx context.Context) error { - for { - select { - case <-ctx.Done(): - return nil - case upd := <-updates: - if upd.Message == nil { // ignore any non-Message Updates - continue - } - for _, r := range routes { - if r.TgID == upd.Message.Chat.ID { - from := fmt.Sprintf("%s %s", upd.Message.From.FirstName, upd.Message.From.LastName) - if upd.Message.From.UserName != "" { - from = fmt.Sprintf("%s %s (%s)", upd.Message.From.FirstName, upd.Message.From.LastName, upd.Message.From.UserName) - } - isSticker := "" - images := make([]string, 0) - if upd.Message.Sticker != nil { - isSticker = upd.Message.Sticker.Emoji - s, _ := tgApi.GetFileDirectURL(upd.Message.Sticker.Thumbnail.FileID) - images = append(images, s) - } - if upd.Message.Photo != nil { - for _, p := range *upd.Message.Photo { - s, _ := tgApi.GetFileDirectURL(p.FileID) - images = append(images, s) - } - } - tg2tt <- message{ - To: r.TTID, - From: from, - Text: upd.Message.Text, - Images: images, - Sticker: isSticker, - } - } - } - case msg := <-tt2tg: - att := make([]interface{}, 0) - for _, a := range msg.Images { - att = append(att, tamtam.Image{Url: a}) - } - text := fmt.Sprintf("[TT] %s: %s", msg.From, msg.Text) - if msg.Sticker != "" { - text = fmt.Sprintf("[TT] %s: [%s]", msg.From, msg.Sticker) - } - if len(msg.Images) > 0 { - text += "[IMAGES] " + strings.Join(msg.Images, " ") - } - m := tgbotapi.NewMessage(msg.To, text) - res, err := tgApi.Send(m) - log.Printf("[TG] Answer: %#v %#v", res, err) - } - } - }, rutina.ShutdownIfDone, rutina.RestartIfFail) + tg := plugins.NewTelegram(telegramToken, tt2tg, tg2tt, routes) + tt := plugins.NewTamTam(tamtamToken, tg2tt, tt2tg, routes) - // endregion + r.Go(tg.Run, rutina.ShutdownIfDone, rutina.RestartIfFail) + r.Go(tt.Run, rutina.ShutdownIfDone, rutina.RestartIfFail) r.ListenOsSignals() if err := r.Wait(); err != nil { diff --git a/go.mod b/go.mod index 4b87825..0fcec10 100644 --- a/go.mod +++ b/go.mod @@ -8,3 +8,5 @@ require ( github.com/neonxp/tamtam v0.1.0 github.com/technoweenie/multipartstreamer v1.0.1 // indirect ) + +replace github.com/neonxp/tamtam => ../tamtam diff --git a/lib/models.go b/lib/models.go new file mode 100644 index 0000000..ccc7601 --- /dev/null +++ b/lib/models.go @@ -0,0 +1,14 @@ +package lib + +type Message struct { + From string + To int64 + Text string + Images []string + Sticker string +} + +type Routing struct { + TgID int64 + TTID int64 +} diff --git a/plugins/plugin.go b/plugins/plugin.go new file mode 100644 index 0000000..504c4af --- /dev/null +++ b/plugins/plugin.go @@ -0,0 +1,7 @@ +package plugins + +import "context" + +type Plugin interface { + Run(ctx context.Context) error +} diff --git a/plugins/tg.go b/plugins/tg.go new file mode 100644 index 0000000..ccd3a9b --- /dev/null +++ b/plugins/tg.go @@ -0,0 +1,129 @@ +package plugins + +import ( + "context" + "fmt" + "io" + "io/ioutil" + "log" + "net/http" + "os" + + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api" + "github.com/neonxp/tamtam" + + "transport/lib" +) + +type Telegram struct { + Routing []lib.Routing + API *tgbotapi.BotAPI + Updates chan lib.Message + Bus chan lib.Message +} + +func NewTelegram(token string, updates chan lib.Message, bus chan lib.Message, routing []lib.Routing) *Telegram { + tgApi, err := tgbotapi.NewBotAPI(token) + if err != nil { + log.Panic(err) + } + + return &Telegram{API: tgApi, Updates: updates, Bus: bus, Routing: routing} +} + +func (t *Telegram) Run(ctx context.Context) error { + + u := tgbotapi.NewUpdate(0) + u.Timeout = 60 + + updates, err := t.API.GetUpdatesChan(u) + if err != nil { + return err + } + for { + select { + case <-ctx.Done(): + return nil + case upd := <-updates: + if upd.Message == nil { // ignore any non-Message Updates + continue + } + for _, r := range t.Routing { + if r.TgID == upd.Message.Chat.ID { + from := fmt.Sprintf("%s %s", upd.Message.From.FirstName, upd.Message.From.LastName) + if upd.Message.From.UserName != "" { + from = fmt.Sprintf("%s %s (%s)", upd.Message.From.FirstName, upd.Message.From.LastName, upd.Message.From.UserName) + } + isSticker := "" + images := make([]string, 0) + if upd.Message.Sticker != nil { + isSticker = upd.Message.Sticker.Emoji + s, _ := t.API.GetFileDirectURL(upd.Message.Sticker.Thumbnail.FileID) + images = append(images, s) + } + if upd.Message.Photo != nil && len(*upd.Message.Photo) > 0 { + p := (*upd.Message.Photo)[0] + s, _ := t.API.GetFileDirectURL(p.FileID) + images = append(images, s) + } + t.Bus <- lib.Message{ + To: r.TTID, + From: from, + Text: upd.Message.Text, + Images: images, + Sticker: isSticker, + } + } + } + case msg := <-t.Updates: + att := make([]interface{}, 0) + for _, a := range msg.Images { + att = append(att, tamtam.Image{Url: a}) + } + text := fmt.Sprintf("*%s*:\n%s", msg.From, msg.Text) + if len(msg.Text) > 0 { + res, err := t.API.Send(tgbotapi.MessageConfig{ + BaseChat: tgbotapi.BaseChat{ + ChatID: msg.To, + ReplyToMessageID: 0, + }, + Text: text, + DisableWebPagePreview: false, + ParseMode: "markdown", + }) + log.Printf("[TG] Send text: %#v %#v", res, err) + } + if len(msg.Images) > 0 { + for _, i := range msg.Images { + u, err := t.DownloadFile(i) + if err != nil { + log.Printf("[TG] Download image: %#v", err) + continue + } + m := tgbotapi.NewPhotoUpload(msg.To, u) + m.Caption = msg.Sticker + res, err := t.API.Send(m) + log.Printf("[TG] Send image: %#v %#v", res, err) + } + } + } + } +} + +func (t *Telegram) DownloadFile(u string) (string, error) { + resp, err := http.Get(u) + if err != nil { + return "", err + } + defer resp.Body.Close() + + // Write the body to file + + f, err := ioutil.TempFile(os.TempDir(), "tg*") + if err != nil { + return "", err + } + _, err = io.Copy(f, resp.Body) + defer f.Close() + return f.Name(), nil +} diff --git a/plugins/tt.go b/plugins/tt.go new file mode 100644 index 0000000..89fa77c --- /dev/null +++ b/plugins/tt.go @@ -0,0 +1,107 @@ +package plugins + +import ( + "context" + "fmt" + "log" + + "github.com/neonxp/tamtam" + + "transport/lib" +) + +type TamTam struct { + Routing []lib.Routing + API *tamtam.Api + Updates chan lib.Message + Bus chan lib.Message +} + +func NewTamTam(token string, updates chan lib.Message, bus chan lib.Message, routing []lib.Routing) *TamTam { + return &TamTam{API: tamtam.New(token), Updates: updates, Bus: bus, Routing: routing} +} + +func (t *TamTam) Run(ctx context.Context) error { + updates := make(chan interface{}, 1) + go func() { + if err := t.API.GetUpdatesLoop(ctx, updates); err != nil { + log.Printf("[TT] Error: %#v", err) + } + }() + for { + select { + case <-ctx.Done(): + return nil + case upd := <-updates: + log.Printf("[TT] Received: %#v", upd) + switch upd := upd.(type) { + case tamtam.UpdateMessageCreated: + for _, r := range t.Routing { + if r.TTID == upd.Message.Recipient.ChatId { + from := upd.Message.Sender.Name + if upd.Message.Sender.Username != "" { + from = fmt.Sprintf("%s (%s)", upd.Message.Sender.Name, upd.Message.Sender.Username) + } + isSticker := "" + images := make([]string, 0) + for _, a := range upd.Message.Body.Attachments { + switch a := a.(type) { + case *tamtam.PhotoAttachment: + images = append(images, *a.Payload.Url) + case *tamtam.StickerAttachment: + images = append(images, a.Payload.Url) + isSticker = "СТИКЕР" + } + } + t.Bus <- lib.Message{ + To: r.TgID, + From: from, + Text: upd.Message.Body.Text, + Images: images, + Sticker: isSticker, + } + } + } + + default: + log.Printf("Unknown type: %#v", upd) + } + case msg := <-t.Updates: + + text := fmt.Sprintf("*%s*:\n%s", msg.From, msg.Text) + if msg.Sticker != "" { + text = fmt.Sprintf("*%s*: [%s]", msg.From, msg.Sticker) + } + attachments := make([]interface{}, 0, len(msg.Images)) + if len(msg.Images) > 0 { + toSent := []string{} + for _, i := range msg.Images { + ok := true + for _, j := range toSent { + if i == j { + ok = false + } + } + if ok { + toSent = append(toSent, i) + } + } + for _, i := range toSent { + attachments = append(attachments, tamtam.PhotoAttachment{ + Type: "image", + Payload: tamtam.PhotoAttachmentPayload{ + Url: &i, + }, + }) + } + } + if len(text) > 0 || len(attachments) > 0 { + res, err := t.API.SendMessage(msg.To, msg.To, &tamtam.NewMessageBody{ + Text: text, + Attachments: attachments, + }) + log.Printf("[TT] Answer: %#v %#v", res, err) + } + } + } +} -- cgit v1.2.3