CrowdSec_Notification_Telegram/main.go
2022-02-11 14:09:02 +01:00

145 lines
3.8 KiB
Go

package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/enescakir/emoji"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"net/http"
"os"
"strings"
"github.com/crowdsecurity/crowdsec/pkg/protobufs"
"github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"
"gopkg.in/yaml.v2"
)
var logger hclog.Logger = hclog.New(&hclog.LoggerOptions{
Name: "telegram-plugin",
Level: hclog.LevelFromString("DEBUG"),
Output: os.Stderr,
JSONFormat: true,
})
type PluginConfig struct {
Name string `yaml:"name"`
LogLevel *string `yaml:"log_level"`
BotToken string `yaml:"bot_token"`
ChannelID int64 `yaml:"channel_id"`
}
type TelegramPlugin struct {
ConfigByName map[string]PluginConfig
}
type Datas struct {
Message string `json:"message"`
Image string `json:"image,omitempty"`
Country string `json:"country,omitempty"`
}
func (n *TelegramPlugin) Configure(ctx context.Context, config *protobufs.Config) (*protobufs.Empty, error) {
d := PluginConfig{}
if err := yaml.Unmarshal(config.Config, &d); err != nil {
return nil, err
}
n.ConfigByName[d.Name] = d
return &protobufs.Empty{}, nil
}
func (n *TelegramPlugin) Notify(ctx context.Context, notification *protobufs.Notification) (*protobufs.Empty, error) {
if _, ok := n.ConfigByName[notification.Name]; !ok {
return nil, fmt.Errorf("invalid plugin config name %s", notification.Name)
}
cfg := n.ConfigByName[notification.Name]
if cfg.LogLevel != nil && *cfg.LogLevel != "" {
logger.SetLevel(hclog.LevelFromString(*cfg.LogLevel))
} else {
logger.SetLevel(hclog.Info)
}
var datas []Datas
err := json.Unmarshal([]byte(notification.Text), &datas)
if err != nil {
logger.Error(err.Error())
return nil, err
}
bot, err := tgbotapi.NewBotAPI(cfg.BotToken)
if err != nil {
logger.Error(err.Error())
return nil, err
}
//bot.Debug = true // ToDo alling with logger level
logger.Info(fmt.Sprintf("Authorized on account %s", bot.Self.UserName))
for _, data := range datas {
var flag emoji.Emoji
if len(data.Country) != 0 {
flag, err = emoji.CountryFlag(data.Country)
}
if len(data.Country) == 0 || err != nil {
flag = emoji.PirateFlag
}
data.Message = strings.Replace(data.Message, ":flag:", string(flag), -1)
data.Message = strings.Replace(data.Message, ".", "\\.", -1)
data.Message = strings.Replace(data.Message, "-", "\\-", -1)
var msg tgbotapi.Chattable
if len(data.Image) != 0 {
response, err := http.Get(data.Image)
if err != nil {
return nil, err
}
defer response.Body.Close()
if response.StatusCode != 200 {
return nil, errors.New("received non 200 response code for image")
}
tmpMsg := tgbotapi.NewPhoto(cfg.ChannelID, tgbotapi.FileReader{Name: "map.png", Reader: response.Body})
tmpMsg.Caption = data.Message
tmpMsg.ParseMode = tgbotapi.ModeMarkdownV2
msg = tmpMsg
} else {
tmpMsg := tgbotapi.NewMessage(cfg.ChannelID, data.Message)
tmpMsg.ParseMode = tgbotapi.ModeMarkdownV2
tmpMsg.DisableWebPagePreview = true
msg = tmpMsg
}
_, err = bot.Send(msg)
if err != nil {
return nil, err
}
}
return &protobufs.Empty{}, nil
}
func main() {
var handshake = plugin.HandshakeConfig{
ProtocolVersion: 1,
MagicCookieKey: "CROWDSEC_PLUGIN_KEY",
MagicCookieValue: os.Getenv("CROWDSEC_PLUGIN_KEY"),
}
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: handshake,
Plugins: map[string]plugin.Plugin{
"telegram": &protobufs.NotifierPlugin{
Impl: &TelegramPlugin{ConfigByName: make(map[string]PluginConfig)},
},
},
GRPCServer: plugin.DefaultGRPCServer,
Logger: logger,
})
}