Skip to content

Commit

Permalink
tg-bot messaging (#33)
Browse files Browse the repository at this point in the history
* From #28

* Fixed api

* Fixed subscription

* Deleted chats table, added html templates, a handler, changed initialization

* Added chat init log

* Added unit files

* Altered ping message

* Updated messages

Co-authored-by: Nikolay Eskov <[email protected]>
  • Loading branch information
esuwu and nickeskov authored Apr 26, 2022
1 parent ed5a343 commit 71d3de6
Show file tree
Hide file tree
Showing 16 changed files with 267 additions and 216 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ mod-clean:
go mod tidy

build-bot-linux-amd64:
@CGO_ENABLE=0 GOOS=linux GOARCH=amd64 go build -o bin/nodemon-tg ./cmd/telegram_bot/bot.go
@CGO_ENABLE=0 GOOS=linux GOARCH=amd64 go build -o bin/nodemon-tg ./cmd/tg_bot/bot.go
build-nodemon-linux-amd64:
@CGO_ENABLE=0 GOOS=linux GOARCH=amd64 go build -o bin/nodemon ./cmd/nodemon/nodemon.go

5 changes: 4 additions & 1 deletion cmd/nodemon/nodemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,10 @@ func run() error {
go func() {
for alert := range alerts {
log.Printf("Alert has been generated: %v", alert)
err := socket.Send([]byte(alert.Message()))
message := make([]byte, len(alert.Message())+1)
message[0] = byte(alert.Type())
copy(message[1:], alert.Message())
err := socket.Send(message)
if err != nil {
log.Printf("failed to send a message to socket, %v", err)
}
Expand Down
10 changes: 5 additions & 5 deletions cmd/tg_bot/tg_bot.go → cmd/tg_bot/bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ func run() error {
webhookLocalAddress string // only for webhook method
publicURL string // only for webhook method
botToken string
storagePath string
chatID int64
)
flag.StringVar(&nanomsgURL, "nano-msg-url", "ipc:///tmp/nano-msg-nodemon-pubsub.ipc", "Nanomsg IPC URL. Default is tcp://:8000")
flag.StringVar(&behavior, "behavior", "webhook", "Behavior is either webhook or polling")
flag.StringVar(&webhookLocalAddress, "webhook-local-address", ":8081", "The application's webhook address is :8081 by default")
flag.StringVar(&botToken, "bot-token", "", "Temporarily: the default token is the current token")
flag.StringVar(&publicURL, "public-url", "", "Default is https://mainnet-go-htz-fsn1-1.wavesnodes.com/bot")
flag.StringVar(&storagePath, "storage", "", "Path to storage")
flag.Int64Var(&chatID, "chat-id", 0, "Chat ID to send alerts through")
flag.Parse()

if botToken == "" {
Expand All @@ -54,15 +54,15 @@ func run() error {
log.Println("invalid public url")
return errorInvalidParameters
}
if storagePath == "" {
log.Println("invalid storage path")
if chatID == 0 {
log.Println("invalid chat ID")
return errorInvalidParameters
}

ctx, done := signal.NotifyContext(context.Background(), os.Interrupt)
defer done()

tgBotEnv, err := tgBot.InitTgBot(behavior, webhookLocalAddress, publicURL, botToken, storagePath)
tgBotEnv, err := tgBot.InitTgBot(behavior, webhookLocalAddress, publicURL, botToken, chatID)
if err != nil {
log.Println("failed to initialize telegram bot")
return errors.Wrap(err, "failed to init tg bot")
Expand Down
25 changes: 0 additions & 25 deletions cmd/tg_bot/internal/base_messages/base_messages.go

This file was deleted.

82 changes: 68 additions & 14 deletions cmd/tg_bot/internal/environment.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
package internal

import (
"bytes"
"embed"
"html/template"
"log"

"github.com/pkg/errors"
"gopkg.in/telebot.v3"
"nodemon/pkg/entities"
"nodemon/pkg/storing/chats"
)

var (
//go:embed templates
templateFiles embed.FS
)

var errUnknownAlertType = errors.New("received unknown alert type")

type TelegramBotEnvironment struct {
ChatStorage *chats.Storage
Bot *telebot.Bot
Mute bool
ChatID int64
Bot *telebot.Bot
Mute bool
}

func NewTelegramBotEnvironment(bot *telebot.Bot, storage *chats.Storage, shutUp bool) *TelegramBotEnvironment {
return &TelegramBotEnvironment{Bot: bot, ChatStorage: storage, Mute: shutUp}
type Alert struct {
AlertType string
Severity string
Details string
}

func NewTelegramBotEnvironment(bot *telebot.Bot, chatID int64, mute bool) *TelegramBotEnvironment {
return &TelegramBotEnvironment{Bot: bot, ChatID: chatID, Mute: mute}
}

func (tgEnv *TelegramBotEnvironment) Start() {
Expand All @@ -25,23 +40,62 @@ func (tgEnv *TelegramBotEnvironment) Start() {
log.Println("Telegram bot finished")
}

func (tgEnv *TelegramBotEnvironment) constructMessage(alert string, msg []byte) (string, error) {
a := Alert{
AlertType: alert,
Severity: "Error",
Details: string(msg),
}

tmpl, err := template.ParseFS(templateFiles, "templates/alert.html")

if err != nil {
log.Printf("failed to construct a message, %v", err)
return "", err
}

w := &bytes.Buffer{}
err = tmpl.Execute(w, a)
if err != nil {
log.Printf("failed to construct a message, %v", err)
return "", err
}
return w.String(), nil
}

func (tgEnv *TelegramBotEnvironment) SendMessage(msg []byte) {
if tgEnv.Mute {
log.Printf("received an alert, but asleep now")
return
}

chatID, err := tgEnv.ChatStorage.FindChatID(entities.TelegramPlatform)
if err != nil {
if errors.Is(err, chats.ErrorChatNotFound) {
log.Println("have not received a chat id yet")
} else {
log.Printf("failed to find chat id: %v", err)
chat := &telebot.Chat{ID: tgEnv.ChatID}

alertDescription, ok := entities.AlertTypes[entities.AlertType(msg[0])]
if !ok {
log.Printf("failed to construct message, %v", errUnknownAlertType)
_, err := tgEnv.Bot.Send(
chat,
errUnknownAlertType.Error(),
&telebot.SendOptions{ParseMode: telebot.ModeHTML},
)
if err != nil {
log.Printf("failed to send a message to telegram, %v", err)
}
return
}

chat := &telebot.Chat{ID: int64(*chatID)}
_, err = tgEnv.Bot.Send(chat, string(msg))
messageToBot, err := tgEnv.constructMessage(alertDescription, msg[1:])
if err != nil {
log.Printf("failed to construct message, %v", err)
return
}
_, err = tgEnv.Bot.Send(
chat,
messageToBot,
&telebot.SendOptions{ParseMode: telebot.ModeHTML},
)

if err != nil {
log.Printf("failed to send a message to telegram, %v", err)
}
Expand Down
55 changes: 20 additions & 35 deletions cmd/tg_bot/internal/handlers/handlers.go
Original file line number Diff line number Diff line change
@@ -1,59 +1,44 @@
package handlers

import (
"log"
"fmt"

tele "gopkg.in/telebot.v3"
"nodemon/cmd/tg_bot/internal"
"nodemon/cmd/tg_bot/internal/base_messages"
"nodemon/pkg/entities"
"nodemon/cmd/tg_bot/internal/messages"
)

func InitHandlers(bot *tele.Bot, environment *internal.TelegramBotEnvironment) {
bot.Handle("/hello", func(c tele.Context) error {
oldChatID, err := environment.ChatStorage.FindChatID(entities.TelegramPlatform)
if err != nil {
log.Printf("failed to insert chat id into db: %v", err)
return c.Send("An error occurred while finding the chat id in database")
}
if oldChatID != nil {
return c.Send("Hello! I remember this chat.")
}
chatID := entities.ChatID(c.Chat().ID)

err = environment.ChatStorage.InsertChatID(chatID, entities.TelegramPlatform)
if err != nil {
log.Printf("failed to insert chat id into db: %v", err)
return c.Send("I failed to save this chat id")
}
return c.Send("Hello! This new chat has been saved for alerting.")
bot.Handle("/chat", func(c tele.Context) error {
return c.Send(fmt.Sprintf("I am sending alerts through %d chat id", environment.ChatID))
})

bot.Handle("/ping", func(c tele.Context) error {
return c.Send("pong!")
if environment.Mute {
return c.Send(messages.PongText + " I am currently sleeping" + messages.SleepingMsg)
}
return c.Send(messages.PongText + " I am monitoring" + messages.MonitoringMsg)
})

bot.Handle("/start", func(c tele.Context) error {
environment.Mute = true
return c.Send("Started working...")
if environment.Mute {
environment.Mute = false
return c.Send("I had been asleep, but started monitoring now... " + messages.MonitoringMsg)
}
return c.Send("I had already been monitoring" + messages.MonitoringMsg)
})

bot.Handle("/mute", func(c tele.Context) error {
environment.Mute = false
return c.Send("Say no more..")
if environment.Mute {
return c.Send("I had already been sleeping, continue sleeping.." + messages.SleepingMsg)
}
environment.Mute = true
return c.Send("I had been monitoring, but going to sleep now.." + messages.SleepingMsg)
})

bot.Handle("/help", func(c tele.Context) error {
replyKeyboard := base_messages.HelpCommandKeyboard()
return c.Send(
base_messages.HelpInfoText2,
&tele.SendOptions{
ParseMode: tele.ModeHTML,
ReplyMarkup: &tele.ReplyMarkup{
OneTimeKeyboard: true,
ResizeKeyboard: true,
ReplyKeyboard: replyKeyboard,
},
})
messages.HelpInfoText,
&tele.SendOptions{ParseMode: tele.ModeHTML})
})
}
12 changes: 5 additions & 7 deletions cmd/tg_bot/internal/init/init.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
package init

import (
"log"

"github.com/pkg/errors"
tele "gopkg.in/telebot.v3"
"nodemon/cmd/tg_bot/internal"
"nodemon/cmd/tg_bot/internal/config"
"nodemon/cmd/tg_bot/internal/handlers"
"nodemon/pkg/storing/chats"
)

func InitTgBot(behavior string,
webhookLocalAddress string,
publicURL string,
botToken string,
storagePath string,
chatID int64,
) (*internal.TelegramBotEnvironment, error) {
botSettings, err := config.NewBotSettings(behavior, webhookLocalAddress, publicURL, botToken)
if err != nil {
Expand All @@ -24,12 +25,9 @@ func InitTgBot(behavior string,
return nil, errors.Wrap(err, "failed to start bot")
}

stor, err := chats.NewStorage(storagePath)
if err != nil {
return nil, errors.Wrap(err, "failed to initialize storage")
}
log.Printf("chat id for sending alerts is %d", chatID)

tgBotEnv := internal.NewTelegramBotEnvironment(bot, stor, false)
tgBotEnv := internal.NewTelegramBotEnvironment(bot, chatID, false)
handlers.InitHandlers(bot, tgBotEnv)
return tgBotEnv, nil
}
6 changes: 6 additions & 0 deletions cmd/tg_bot/internal/messages/alert_messages.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package messages

const (
ErrorMsg = "❌"
infoMsg = "ℹ️"
)
18 changes: 18 additions & 0 deletions cmd/tg_bot/internal/messages/base_messages.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package messages

const (
MonitoringMsg = "📡"
SleepingMsg = "💤"
PongMsg = "🏓"

HelpInfoText = infoMsg + " This is a bot for monitoring Waves nodes. The next commands are available:\n\n" +
"/ping - the command to check whether the bot is available and what his current state is\n" +
"/hello - the command to make the bot <b>save this chat for alerts</b>. Needs to be done first time\n" +
"/start - the command to make the bot <b>start getting alerts</b>\n" +
"/mute - the command to make the bot <b>stop listening to alerts</b>" +
"/help - the command to see <b>information about bot</b> and available commands"

MuteText = "Say no more..." + SleepingMsg
PongText = "Pong!" + PongMsg
StartText = "Started monitoring..." + MonitoringMsg
)
5 changes: 5 additions & 0 deletions cmd/tg_bot/internal/templates/alert.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<b>Alert type:</b> {{ .AlertType}}

<b>Severity:</b> {{ .Severity}}

<b>Details:</b> {{ .Details}}
Loading

0 comments on commit 71d3de6

Please sign in to comment.