summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--bot.go159
-rw-r--r--go.mod2
-rw-r--r--lib/models.go14
-rw-r--r--plugins/plugin.go7
-rw-r--r--plugins/tg.go129
-rw-r--r--plugins/tt.go107
7 files changed, 270 insertions, 149 deletions
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)
+ }
+ }
+ }
+}