Add config option to deliver alerts with PRIVMSG

Add `use_privmsg` config option to deliver alerts with PRIVMSG instead
of the default NOTICE.

This addresses a use case described in
https://github.com/google/alertmanager-irc-relay/pull/1 .

Signed-off-by: Luca Bigliardi <shammash@google.com>
This commit is contained in:
Luca Bigliardi 2020-01-25 18:03:13 +00:00
parent 4e1aeaf931
commit ae6594c606
5 changed files with 75 additions and 1 deletions

View File

@ -48,6 +48,11 @@ irc_channels:
# Send only one message when webhook data is received.
# Note: By default a message is sent for each alert in the webhook data.
msg_once_per_alert_group: no
#
# Use PRIVMSG instead of NOTICE (default) to send messages.
# Note: Sending PRIVMSG from bots is bad practice, do not enable this unless
# necessary (e.g. unless NOTICEs would weaken your channel moderation policies)
use_privmsg: yes
# Define how IRC messages should be formatted.
#

View File

@ -41,6 +41,7 @@ type Config struct {
IRCChannels []IRCChannel `yaml:"irc_channels"`
MsgTemplate string `yaml:"msg_template"`
MsgOnce bool `yaml:"msg_once_per_alert_group"`
UsePrivmsg bool `yaml:"use_privmsg"`
}
func LoadConfig(configFile string) (*Config, error) {
@ -55,6 +56,7 @@ func LoadConfig(configFile string) (*Config, error) {
IRCUseSSL: true,
IRCChannels: []IRCChannel{IRCChannel{Name: "#airtest"}},
MsgOnce: false,
UsePrivmsg: false,
}
if configFile != "" {

View File

@ -43,6 +43,7 @@ func TestLoadGoodConfig(t *testing.T) {
IRCChannels: []IRCChannel{IRCChannel{Name: "#foobar"}},
MsgTemplate: defaultMsgTemplate,
MsgOnce: false,
UsePrivmsg: false,
}
expectedData, err := yaml.Marshal(expectedConfig)
if err != nil {

10
irc.go
View File

@ -62,6 +62,8 @@ type IRCNotifier struct {
PreJoinChannels []IRCChannel
JoinedChannels map[string]ChannelState
UsePrivmsg bool
NickservDelayWait time.Duration
BackoffCounter Delayer
}
@ -94,6 +96,7 @@ func NewIRCNotifier(config *Config, alertMsgs chan AlertMsg) (*IRCNotifier, erro
sessionDownSignal: make(chan bool),
PreJoinChannels: config.IRCChannels,
JoinedChannels: make(map[string]ChannelState),
UsePrivmsg: config.UsePrivmsg,
NickservDelayWait: nickservWaitSecs * time.Second,
BackoffCounter: backoffCounter,
}
@ -196,7 +199,12 @@ func (notifier *IRCNotifier) MaybeSendAlertMsg(alertMsg *AlertMsg) {
return
}
notifier.JoinChannel(&IRCChannel{Name: alertMsg.Channel})
notifier.Client.Notice(alertMsg.Channel, alertMsg.Alert)
if notifier.UsePrivmsg {
notifier.Client.Privmsg(alertMsg.Channel, alertMsg.Alert)
} else {
notifier.Client.Notice(alertMsg.Channel, alertMsg.Alert)
}
}
func (notifier *IRCNotifier) Run() {

View File

@ -212,6 +212,7 @@ func makeTestIRCConfig(IRCPort int) *Config {
IRCChannel{Name: "#bar"},
IRCChannel{Name: "#baz"},
},
UsePrivmsg: false,
}
}
@ -321,6 +322,63 @@ func TestSendAlertOnPreJoinedChannel(t *testing.T) {
}
}
func TestUsePrivmsgToSendAlertOnPreJoinedChannel(t *testing.T) {
server, port := makeTestServer(t)
config := makeTestIRCConfig(port)
config.UsePrivmsg = true
notifier, alertMsgs := makeTestNotifier(t, config)
var testStep sync.WaitGroup
testChannel := "#foo"
testMessage := "test message"
// Send the alert after configured channels have joined, to ensure we
// check for no re-join attempt.
joinedHandler := func(conn *bufio.ReadWriter, line *irc.Line) error {
if line.Args[0] == testChannel {
testStep.Done()
}
return nil
}
server.SetHandler("JOIN", joinedHandler)
testStep.Add(1)
go notifier.Run()
testStep.Wait()
server.SetHandler("JOIN", nil)
privmsgHandler := func(conn *bufio.ReadWriter, line *irc.Line) error {
testStep.Done()
return nil
}
server.SetHandler("PRIVMSG", privmsgHandler)
testStep.Add(1)
alertMsgs <- AlertMsg{Channel: testChannel, Alert: testMessage}
testStep.Wait()
notifier.StopRunning <- true
server.Stop()
expectedCommands := []string{
"NICK foo",
"USER foo 12 * :",
"JOIN #foo",
"JOIN #bar",
"JOIN #baz",
"PRIVMSG #foo :test message",
"QUIT :see ya",
}
if !reflect.DeepEqual(expectedCommands, server.Log) {
t.Error("Alert not sent correctly. Received commands:\n", strings.Join(server.Log, "\n"))
}
}
func TestSendAlertAndJoinChannel(t *testing.T) {
server, port := makeTestServer(t)
config := makeTestIRCConfig(port)