145 lines
3.8 KiB
Go
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,
|
||
|
})
|
||
|
}
|