new database structur + improve bot
This commit is contained in:
parent
e962b935b3
commit
22402e3e6d
134
bot/command.go
134
bot/command.go
|
@ -3,7 +3,6 @@ package bot
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
timeago "github.com/ararog/timeago"
|
timeago "github.com/ararog/timeago"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
@ -14,16 +13,16 @@ type commandFunc func(func(string), string, []string)
|
||||||
// list help
|
// list help
|
||||||
func (b *Bot) help(answer func(string), from string, params []string) {
|
func (b *Bot) help(answer func(string), from string, params []string) {
|
||||||
msg := fmt.Sprintf("Hi %s there are the following commands:\n", from)
|
msg := fmt.Sprintf("Hi %s there are the following commands:\n", from)
|
||||||
for cmd := range b.commands {
|
for _, cmd := range b.commands {
|
||||||
msg = fmt.Sprintf("%s - !%s\n", msg, cmd)
|
msg = fmt.Sprintf("%s - !%s\n", msg, cmd)
|
||||||
}
|
}
|
||||||
answer(msg)
|
answer(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a chat to send log to a chat
|
// add a chat to send log to a chat
|
||||||
func (b *Bot) sendTo(answer func(string), from string, params []string) {
|
func (b *Bot) addSend(answer func(string), from string, params []string) {
|
||||||
if len(params) < 1 {
|
if len(params) < 1 {
|
||||||
answer("invalid: CMD IPAddress\n or\n CMD IPAddress to")
|
answer("invalid: CMD IPAddress/Hostname\n or\n CMD IPAddress/Hostname to")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
host := params[0]
|
host := params[0]
|
||||||
|
@ -32,18 +31,23 @@ func (b *Bot) sendTo(answer func(string), from string, params []string) {
|
||||||
to = params[1]
|
to = params[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := b.db.HostTo[host]; !ok {
|
h := b.db.GetHost(host)
|
||||||
b.db.HostTo[host] = make(map[string]bool)
|
if h == nil {
|
||||||
|
h = b.db.NewHost(host)
|
||||||
}
|
}
|
||||||
b.db.HostTo[host][to] = true
|
n, ok := b.db.NotifiesByAddress[to]
|
||||||
|
if !ok {
|
||||||
|
n = b.db.NewNotify(to)
|
||||||
|
}
|
||||||
|
h.AddNotify(n)
|
||||||
|
|
||||||
answer(fmt.Sprintf("added %s in list of %s", to, host))
|
answer(fmt.Sprintf("added %s in list of %s", to, host))
|
||||||
}
|
}
|
||||||
|
|
||||||
//add a chat to send log to a chat
|
//add a chat to send log to a chat
|
||||||
func (b *Bot) sendRemove(answer func(string), from string, params []string) {
|
func (b *Bot) delSend(answer func(string), from string, params []string) {
|
||||||
if len(params) < 1 {
|
if len(params) < 1 {
|
||||||
answer("invalid: CMD IPAddress\n or\n CMD IPAddress to")
|
answer("invalid: CMD IPAddress/Hostname\n or\n CMD IPAddress/Hostname to")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
host := params[0]
|
host := params[0]
|
||||||
|
@ -52,9 +56,8 @@ func (b *Bot) sendRemove(answer func(string), from string, params []string) {
|
||||||
to = params[1]
|
to = params[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if list, ok := b.db.HostTo[host]; ok {
|
if h := b.db.GetHost(host); h != nil {
|
||||||
delete(list, to)
|
h.DeleteNotify(to)
|
||||||
b.db.HostTo[host] = list
|
|
||||||
answer(fmt.Sprintf("removed %s in list of %s", to, host))
|
answer(fmt.Sprintf("removed %s in list of %s", to, host))
|
||||||
} else {
|
} else {
|
||||||
answer("not found host")
|
answer("not found host")
|
||||||
|
@ -63,7 +66,7 @@ func (b *Bot) sendRemove(answer func(string), from string, params []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// list all hostname with the chat where it send to
|
// list all hostname with the chat where it send to
|
||||||
func (b *Bot) sendList(answer func(string), from string, params []string) {
|
func (b *Bot) listSend(answer func(string), from string, params []string) {
|
||||||
msg := "sending:\n"
|
msg := "sending:\n"
|
||||||
all := false
|
all := false
|
||||||
of := from
|
of := from
|
||||||
|
@ -74,10 +77,10 @@ func (b *Bot) sendList(answer func(string), from string, params []string) {
|
||||||
of = params[0]
|
of = params[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for ip, toMap := range b.db.HostTo {
|
for _, host := range b.db.Hosts {
|
||||||
toList := ""
|
toList := ""
|
||||||
show := all
|
show := all
|
||||||
for to := range toMap {
|
for _, to := range host.Notifies {
|
||||||
if all {
|
if all {
|
||||||
toList = fmt.Sprintf("%s , %s", toList, to)
|
toList = fmt.Sprintf("%s , %s", toList, to)
|
||||||
} else if to == of {
|
} else if to == of {
|
||||||
|
@ -90,58 +93,81 @@ func (b *Bot) sendList(answer func(string), from string, params []string) {
|
||||||
if len(toList) > 3 {
|
if len(toList) > 3 {
|
||||||
toList = toList[3:]
|
toList = toList[3:]
|
||||||
}
|
}
|
||||||
if hostname, ok := b.db.Hostname[ip]; ok {
|
if host.Name != "" {
|
||||||
msg = fmt.Sprintf("%s%s (%s): %s\n", msg, ip, hostname, toList)
|
msg = fmt.Sprintf("%s%s (%s): %s\n", msg, host.Address, host.Name, toList)
|
||||||
} else {
|
} else {
|
||||||
msg = fmt.Sprintf("%s%s: %s\n", msg, ip, toList)
|
msg = fmt.Sprintf("%s%s: %s\n", msg, host.Address, toList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
answer(msg)
|
answer(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add hostname
|
||||||
|
func (b *Bot) addHostname(answer func(string), from string, params []string) {
|
||||||
|
if len(params) < 2 {
|
||||||
|
answer("invalid: CMD IPAddress/Hostname NewHostname")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addr := params[0]
|
||||||
|
name := params[1]
|
||||||
|
|
||||||
|
h := b.db.GetHost(addr)
|
||||||
|
if h == nil {
|
||||||
|
h = b.db.NewHost(addr)
|
||||||
|
}
|
||||||
|
b.db.ChangeHostname(h, name)
|
||||||
|
|
||||||
|
answer(fmt.Sprintf("set for %s the hostname %s", addr, name))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bot) delHostname(answer func(string), from string, params []string) {
|
||||||
|
if len(params) < 2 {
|
||||||
|
answer("invalid: CMD IPAddress/Hostname")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
addr := params[0]
|
||||||
|
h := b.db.GetHost(addr)
|
||||||
|
if h != nil {
|
||||||
|
b.db.DeleteHost(h)
|
||||||
|
if h.Name != "" {
|
||||||
|
answer(fmt.Sprintf("remove host %s with hostname %s", h.Address, h.Name))
|
||||||
|
} else {
|
||||||
|
answer(fmt.Sprintf("remove host %s", h.Address))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
answer("could not found host")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// list all host with his ip
|
// list all host with his ip
|
||||||
func (b *Bot) listHostname(answer func(string), from string, params []string) {
|
func (b *Bot) listHostname(answer func(string), from string, params []string) {
|
||||||
msg := "hostnames:\n"
|
msg := "hostnames:\n"
|
||||||
for ip, hostname := range b.db.Hostname {
|
for _, host := range b.db.Hosts {
|
||||||
if last, ok := b.db.Lastseen[ip]; ok {
|
if host.Lastseen.Year() > 1 {
|
||||||
got, _ := timeago.TimeAgoWithTime(time.Now(), last)
|
got, _ := timeago.TimeAgoFromNowWithTime(host.Lastseen)
|
||||||
msg = fmt.Sprintf("%s%s - %s (%s)\n", msg, ip, hostname, got)
|
msg = fmt.Sprintf("%s%s - %s (%s)\n", msg, host.Address, host.Name, got)
|
||||||
} else {
|
} else {
|
||||||
msg = fmt.Sprintf("%s%s - %s\n", msg, ip, hostname)
|
msg = fmt.Sprintf("%s%s - %s\n", msg, host.Address, host.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
answer(msg)
|
answer(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// list all hostname to a ip
|
|
||||||
func (b *Bot) setHostname(answer func(string), from string, params []string) {
|
|
||||||
if len(params) < 2 {
|
|
||||||
answer("invalid: CMD IPAddress NewHostname")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
host := params[0]
|
|
||||||
name := params[1]
|
|
||||||
|
|
||||||
b.db.Hostname[host] = name
|
|
||||||
|
|
||||||
answer(fmt.Sprintf("set for %s the hostname %s", host, name))
|
|
||||||
}
|
|
||||||
|
|
||||||
// set a filter by max
|
// set a filter by max
|
||||||
func (b *Bot) listMaxfilter(answer func(string), from string, params []string) {
|
func (b *Bot) listMaxfilter(answer func(string), from string, params []string) {
|
||||||
msg := "filters: "
|
msg := "filters: "
|
||||||
if len(params) > 0 && params[0] == "all" {
|
if len(params) > 0 && params[0] == "all" {
|
||||||
msg = fmt.Sprintf("%s\n", msg)
|
msg = fmt.Sprintf("%s\n", msg)
|
||||||
for to, filter := range b.db.MaxPrioIn {
|
for _, n := range b.db.Notifies {
|
||||||
msg = fmt.Sprintf("%s%s - %s\n", msg, to, filter.String())
|
msg = fmt.Sprintf("%s%s - %s\n", msg, n.Address(), n.MaxPrioIn.String())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
of := from
|
of := from
|
||||||
if len(params) > 0 {
|
if len(params) > 0 {
|
||||||
of = params[0]
|
of = params[0]
|
||||||
}
|
}
|
||||||
if filter, ok := b.db.MaxPrioIn[of]; ok {
|
if filter, ok := b.db.NotifiesByAddress[of]; ok {
|
||||||
msg = fmt.Sprintf("%s of %s is %s", msg, of, filter)
|
msg = fmt.Sprintf("%s of %s is %s", msg, of, filter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +177,7 @@ func (b *Bot) listMaxfilter(answer func(string), from string, params []string) {
|
||||||
// set a filter to a mix
|
// set a filter to a mix
|
||||||
func (b *Bot) setMaxfilter(answer func(string), from string, params []string) {
|
func (b *Bot) setMaxfilter(answer func(string), from string, params []string) {
|
||||||
if len(params) < 1 {
|
if len(params) < 1 {
|
||||||
answer("invalid: CMD Priority\n or\n CMD IPAddress Priority")
|
answer("invalid: CMD Priority\n or\n CMD Channel Priority")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
to := from
|
to := from
|
||||||
|
@ -165,11 +191,15 @@ func (b *Bot) setMaxfilter(answer func(string), from string, params []string) {
|
||||||
max, err = log.ParseLevel(params[0])
|
max, err = log.ParseLevel(params[0])
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
answer("invalid priority: CMD Priority\n or\n CMD IPAddress Priority")
|
answer("invalid priority: CMD Priority\n or\n CMD Channel Priority")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
n, ok := b.db.NotifiesByAddress[to]
|
||||||
|
if !ok {
|
||||||
|
n = b.db.NewNotify(to)
|
||||||
|
}
|
||||||
|
|
||||||
b.db.MaxPrioIn[to] = max
|
n.MaxPrioIn = max
|
||||||
|
|
||||||
answer(fmt.Sprintf("set filter for %s to %s", to, max.String()))
|
answer(fmt.Sprintf("set filter for %s to %s", to, max.String()))
|
||||||
}
|
}
|
||||||
|
@ -178,9 +208,9 @@ func (b *Bot) setMaxfilter(answer func(string), from string, params []string) {
|
||||||
func (b *Bot) listRegex(answer func(string), from string, params []string) {
|
func (b *Bot) listRegex(answer func(string), from string, params []string) {
|
||||||
msg := "regexs:\n"
|
msg := "regexs:\n"
|
||||||
if len(params) > 0 && params[0] == "all" {
|
if len(params) > 0 && params[0] == "all" {
|
||||||
for to, regexs := range b.db.RegexIn {
|
for _, n := range b.db.Notifies {
|
||||||
msg = fmt.Sprintf("%s%s\n-------------\n", msg, to)
|
msg = fmt.Sprintf("%s%s\n-------------\n", msg, n.Address())
|
||||||
for expression := range regexs {
|
for expression := range n.RegexIn {
|
||||||
msg = fmt.Sprintf("%s - %s\n", msg, expression)
|
msg = fmt.Sprintf("%s - %s\n", msg, expression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,9 +219,9 @@ func (b *Bot) listRegex(answer func(string), from string, params []string) {
|
||||||
if len(params) > 0 {
|
if len(params) > 0 {
|
||||||
of = params[0]
|
of = params[0]
|
||||||
}
|
}
|
||||||
if regexs, ok := b.db.RegexIn[of]; ok {
|
if n, ok := b.db.NotifiesByAddress[of]; ok {
|
||||||
msg = fmt.Sprintf("%s%s\n-------------\n", msg, from)
|
msg = fmt.Sprintf("%s%s\n-------------\n", msg, of)
|
||||||
for expression := range regexs {
|
for expression := range n.RegexIn {
|
||||||
msg = fmt.Sprintf("%s - %s\n", msg, expression)
|
msg = fmt.Sprintf("%s - %s\n", msg, expression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,7 +237,8 @@ func (b *Bot) addRegex(answer func(string), from string, params []string) {
|
||||||
}
|
}
|
||||||
regex := strings.Join(params, " ")
|
regex := strings.Join(params, " ")
|
||||||
|
|
||||||
if err := b.db.AddRegex(from, regex); err == nil {
|
n := b.db.NotifiesByAddress[from]
|
||||||
|
if err := n.AddRegex(regex); err == nil {
|
||||||
answer(fmt.Sprintf("add regex for \"%s\" to %s", from, regex))
|
answer(fmt.Sprintf("add regex for \"%s\" to %s", from, regex))
|
||||||
} else {
|
} else {
|
||||||
answer(fmt.Sprintf("\"%s\" is no valid regex expression: %s", regex, err))
|
answer(fmt.Sprintf("\"%s\" is no valid regex expression: %s", regex, err))
|
||||||
|
@ -220,7 +251,8 @@ func (b *Bot) delRegex(answer func(string), from string, params []string) {
|
||||||
answer("invalid: CMD regex\n or\n CMD channel regex")
|
answer("invalid: CMD regex\n or\n CMD channel regex")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
n := b.db.NotifiesByAddress[from]
|
||||||
regex := strings.Join(params, " ")
|
regex := strings.Join(params, " ")
|
||||||
delete(b.db.RegexIn[from], regex)
|
delete(n.RegexIn, regex)
|
||||||
b.listRegex(answer, from, []string{})
|
b.listRegex(answer, from, []string{})
|
||||||
}
|
}
|
||||||
|
|
21
bot/main.go
21
bot/main.go
|
@ -9,25 +9,30 @@ import (
|
||||||
|
|
||||||
type Bot struct {
|
type Bot struct {
|
||||||
db *database.DB
|
db *database.DB
|
||||||
commands map[string]commandFunc
|
commandsMap map[string]commandFunc
|
||||||
|
commands []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBot(db *database.DB) *Bot {
|
func NewBot(db *database.DB) *Bot {
|
||||||
b := &Bot{
|
b := &Bot{
|
||||||
db: db,
|
db: db,
|
||||||
}
|
}
|
||||||
b.commands = map[string]commandFunc{
|
b.commandsMap = map[string]commandFunc{
|
||||||
"help": b.help,
|
"help": b.help,
|
||||||
"send-to": b.sendTo,
|
"send-add": b.addSend,
|
||||||
"send-list": b.sendList,
|
"send-list": b.listSend,
|
||||||
"send-rm": b.sendRemove,
|
"send-del": b.delSend,
|
||||||
"hostname-set": b.setHostname,
|
"hostname-set": b.addHostname,
|
||||||
"hostname-list": b.listHostname,
|
"hostname-list": b.listHostname,
|
||||||
|
"hostname-del": b.delHostname,
|
||||||
"filter-set": b.setMaxfilter,
|
"filter-set": b.setMaxfilter,
|
||||||
"filter-list": b.listMaxfilter,
|
"filter-list": b.listMaxfilter,
|
||||||
"regex-add": b.addRegex,
|
"regex-add": b.addRegex,
|
||||||
"regex-list": b.listRegex,
|
"regex-list": b.listRegex,
|
||||||
"regex-rm": b.delRegex,
|
"regex-del": b.delRegex,
|
||||||
|
}
|
||||||
|
for k, _ := range b.commandsMap {
|
||||||
|
b.commands = append(b.commands, k)
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
@ -38,7 +43,7 @@ func (b *Bot) Handle(answer func(string), from, msg string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cmdName := msgParts[0][1:]
|
cmdName := msgParts[0][1:]
|
||||||
if cmd, ok := b.commands[cmdName]; ok {
|
if cmd, ok := b.commandsMap[cmdName]; ok {
|
||||||
cmd(answer, from, msgParts[1:])
|
cmd(answer, from, msgParts[1:])
|
||||||
} else {
|
} else {
|
||||||
answer(fmt.Sprintf("not found command: !%s", cmdName))
|
answer(fmt.Sprintf("not found command: !%s", cmdName))
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Host struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
Lastseen time.Time `json:"lastseen,omitempty"`
|
||||||
|
LastseenNotify time.Time `json:"lastseen_notify,omitempty"`
|
||||||
|
Notifies []string `json:"notifies"`
|
||||||
|
NotifiesByAddress map[string]*Notify `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Host) AddNotify(n *Notify) {
|
||||||
|
if _, ok := h.NotifiesByAddress[n.Address()]; !ok {
|
||||||
|
h.Notifies = append(h.Notifies, n.Address())
|
||||||
|
h.NotifiesByAddress[n.Address()] = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (h *Host) DeleteNotify(to string) {
|
||||||
|
delete(h.NotifiesByAddress, to)
|
||||||
|
for i, v := range h.Notifies {
|
||||||
|
if v == to {
|
||||||
|
copy(h.Notifies[i:], h.Notifies[i+1:])
|
||||||
|
h.Notifies = h.Notifies[:len(h.Notifies)-1]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- global notify
|
||||||
|
|
||||||
|
func (db *DB) InitHost() {
|
||||||
|
if db.HostsByAddress == nil {
|
||||||
|
db.HostsByAddress = make(map[string]*Host)
|
||||||
|
}
|
||||||
|
if db.HostsByName == nil {
|
||||||
|
db.HostsByName = make(map[string]*Host)
|
||||||
|
}
|
||||||
|
for _, h := range db.Hosts {
|
||||||
|
if h.NotifiesByAddress == nil {
|
||||||
|
h.NotifiesByAddress = make(map[string]*Notify)
|
||||||
|
}
|
||||||
|
for _, nName := range h.Notifies {
|
||||||
|
h.NotifiesByAddress[nName] = db.NotifiesByAddress[nName]
|
||||||
|
}
|
||||||
|
db.HostsByAddress[h.Address] = h
|
||||||
|
db.HostsByName[h.Name] = h
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) AddHost(h *Host) {
|
||||||
|
db.Hosts = append(db.Hosts, h)
|
||||||
|
db.HostsByAddress[h.Address] = h
|
||||||
|
db.HostsByName[h.Name] = h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) GetHost(str string) *Host {
|
||||||
|
h, ok := db.HostsByAddress[str]
|
||||||
|
if ok {
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
return db.HostsByName[str]
|
||||||
|
}
|
||||||
|
func (db *DB) DeleteHost(h *Host) {
|
||||||
|
delete(db.HostsByAddress, h.Address)
|
||||||
|
delete(db.HostsByName, h.Name)
|
||||||
|
for i, v := range db.Hosts {
|
||||||
|
if v.Address == h.Address {
|
||||||
|
copy(db.Hosts[i:], db.Hosts[i+1:])
|
||||||
|
db.Hosts[len(db.Hosts)-1] = nil
|
||||||
|
db.Hosts = db.Hosts[:len(db.Hosts)-1]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) ChangeHostname(h *Host, name string) {
|
||||||
|
delete(db.HostsByName, h.Name)
|
||||||
|
h.Name = name
|
||||||
|
db.HostsByName[name] = h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) NewHost(addr string) *Host {
|
||||||
|
h := &Host{
|
||||||
|
Address: addr,
|
||||||
|
NotifiesByAddress: make(map[string]*Notify),
|
||||||
|
}
|
||||||
|
db.AddHost(h)
|
||||||
|
return h
|
||||||
|
}
|
114
database/main.go
114
database/main.go
|
@ -4,38 +4,43 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"dev.sum7.eu/genofire/golang-lib/file"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
const AlertMsg = "alert service from logmania, device did not send new message for a while"
|
const AlertMsg = "alert service from logmania, device did not send new message for a while"
|
||||||
|
|
||||||
type DB struct {
|
type DB struct {
|
||||||
Hostname map[string]string `json:"hostname"`
|
Hostname map[string]string `json:"hostname,omitempty"`
|
||||||
HostTo map[string]map[string]bool `json:"host_to"`
|
HostTo map[string]map[string]bool `json:"host_to,omitempty"`
|
||||||
MaxPrioIn map[string]log.Level `json:"maxLevel"`
|
MaxPrioIn map[string]log.Level `json:"maxLevel,omitempty"`
|
||||||
RegexIn map[string]map[string]*regexp.Regexp `json:"regexIn"`
|
RegexIn map[string]map[string]*regexp.Regexp `json:"regexIn,omitempty"`
|
||||||
Lastseen map[string]time.Time `json:"lastseen,omitempty"`
|
Lastseen map[string]time.Time `json:"lastseen,omitempty"`
|
||||||
LastseenNotify map[string]time.Time `json:"-"`
|
LastseenNotify map[string]time.Time `json:"-"`
|
||||||
|
// new format
|
||||||
|
Hosts []*Host `json:"hosts"`
|
||||||
|
HostsByAddress map[string]*Host `json:"-"`
|
||||||
|
HostsByName map[string]*Host `json:"-"`
|
||||||
|
Notifies []*Notify `json:"notifies"`
|
||||||
|
NotifiesByAddress map[string]*Notify `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) SendTo(e *log.Entry) (*log.Entry, []string) {
|
func (db *DB) SendTo(e *log.Entry) (*log.Entry, *Host, []*Notify) {
|
||||||
hostname, ok := e.Data["hostname"].(string)
|
addr, ok := e.Data["hostname"].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return e, nil
|
return e, nil, nil
|
||||||
}
|
}
|
||||||
if to, ok := db.HostTo[hostname]; ok {
|
var host *Host
|
||||||
if e.Message != AlertMsg && hostname != "" {
|
if host, ok := db.HostsByAddress[addr]; ok {
|
||||||
db.Lastseen[hostname] = time.Now()
|
if e.Message != AlertMsg {
|
||||||
|
host.Lastseen = time.Now()
|
||||||
}
|
}
|
||||||
var toList []string
|
var toList []*Notify
|
||||||
for toEntry, _ := range to {
|
for _, notify := range host.NotifiesByAddress {
|
||||||
if lvl := db.MaxPrioIn[toEntry]; e.Level >= lvl {
|
if lvl := notify.MaxPrioIn; e.Level >= lvl {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if regex, ok := db.RegexIn[toEntry]; ok {
|
|
||||||
stopForTo := false
|
stopForTo := false
|
||||||
for _, expr := range regex {
|
for _, expr := range notify.RegexIn {
|
||||||
if expr.MatchString(e.Message) {
|
if expr.MatchString(e.Message) {
|
||||||
stopForTo = true
|
stopForTo = true
|
||||||
continue
|
continue
|
||||||
|
@ -44,66 +49,19 @@ func (db *DB) SendTo(e *log.Entry) (*log.Entry, []string) {
|
||||||
if stopForTo {
|
if stopForTo {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
toList = append(toList, notify)
|
||||||
}
|
}
|
||||||
toList = append(toList, toEntry)
|
if host.Name != "" {
|
||||||
}
|
entry := e.WithField("hostname", host.Name)
|
||||||
if replaceHostname, ok := db.Hostname[hostname]; ok {
|
|
||||||
entry := e.WithField("hostname", replaceHostname)
|
|
||||||
entry.Level = e.Level
|
entry.Level = e.Level
|
||||||
entry.Message = e.Message
|
entry.Message = e.Message
|
||||||
return entry, toList
|
return entry, host, toList
|
||||||
}
|
}
|
||||||
return e, toList
|
return e, host, toList
|
||||||
} else {
|
} else {
|
||||||
db.HostTo[hostname] = make(map[string]bool)
|
host = db.NewHost(addr)
|
||||||
}
|
|
||||||
return e, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (db *DB) AddRegex(to, expression string) error {
|
|
||||||
regex, err := regexp.Compile(expression)
|
|
||||||
if err == nil {
|
|
||||||
if _, ok := db.RegexIn[to]; !ok {
|
|
||||||
db.RegexIn[to] = make(map[string]*regexp.Regexp)
|
|
||||||
}
|
|
||||||
db.RegexIn[to][expression] = regex
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadDBFile(path string) *DB {
|
|
||||||
var db DB
|
|
||||||
|
|
||||||
if err := file.ReadJSON(path, &db); err == nil {
|
|
||||||
log.Infof("loaded %d hosts", len(db.HostTo))
|
|
||||||
if db.Lastseen == nil {
|
|
||||||
db.Lastseen = make(map[string]time.Time)
|
|
||||||
}
|
|
||||||
if db.LastseenNotify == nil {
|
|
||||||
db.LastseenNotify = make(map[string]time.Time)
|
|
||||||
}
|
|
||||||
if db.RegexIn == nil {
|
|
||||||
db.RegexIn = make(map[string]map[string]*regexp.Regexp)
|
|
||||||
} else {
|
|
||||||
for to, regexs := range db.RegexIn {
|
|
||||||
for exp, _ := range regexs {
|
|
||||||
db.AddRegex(to, exp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &db
|
|
||||||
} else {
|
|
||||||
log.Error("failed to open db file: ", path, ":", err)
|
|
||||||
}
|
|
||||||
return &DB{
|
|
||||||
Hostname: make(map[string]string),
|
|
||||||
HostTo: make(map[string]map[string]bool),
|
|
||||||
MaxPrioIn: make(map[string]log.Level),
|
|
||||||
RegexIn: make(map[string]map[string]*regexp.Regexp),
|
|
||||||
Lastseen: make(map[string]time.Time),
|
|
||||||
LastseenNotify: make(map[string]time.Time),
|
|
||||||
}
|
}
|
||||||
|
return e, host, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) Alert(expired time.Duration, send func(e *log.Entry) error) {
|
func (db *DB) Alert(expired time.Duration, send func(e *log.Entry) error) {
|
||||||
|
@ -111,17 +69,19 @@ func (db *DB) Alert(expired time.Duration, send func(e *log.Entry) error) {
|
||||||
|
|
||||||
for range c {
|
for range c {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
for host, time := range db.Lastseen {
|
for _, h := range db.Hosts {
|
||||||
if time.Before(now.Add(expired * -2)) {
|
if !h.Lastseen.Before(now.Add(expired * -2)) {
|
||||||
if timeNotify, ok := db.LastseenNotify[host]; !ok || !time.Before(timeNotify) {
|
continue
|
||||||
db.LastseenNotify[host] = now
|
}
|
||||||
|
if h.LastseenNotify.Year() <= 1 && h.Lastseen.Before(h.LastseenNotify) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
h.LastseenNotify = now
|
||||||
entry := log.NewEntry(log.New())
|
entry := log.NewEntry(log.New())
|
||||||
entry.Level = log.ErrorLevel
|
entry.Level = log.ErrorLevel
|
||||||
entry.Message = AlertMsg
|
entry.Message = AlertMsg
|
||||||
entry.WithField("hostname", host)
|
entry.WithField("hostname", h.Address)
|
||||||
send(entry)
|
send(entry)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Notify struct {
|
||||||
|
Protocoll string `json:"proto"`
|
||||||
|
To string `json:"to"`
|
||||||
|
RegexIn map[string]*regexp.Regexp `json:"regexIn"`
|
||||||
|
MaxPrioIn log.Level `json:"maxLevel"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Notify) Init() {
|
||||||
|
if n.RegexIn == nil {
|
||||||
|
n.RegexIn = make(map[string]*regexp.Regexp)
|
||||||
|
}
|
||||||
|
for exp, _ := range n.RegexIn {
|
||||||
|
regex, err := regexp.Compile(exp)
|
||||||
|
if err == nil {
|
||||||
|
n.RegexIn[exp] = regex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Notify) AddRegex(expression string) error {
|
||||||
|
regex, err := regexp.Compile(expression)
|
||||||
|
if err == nil {
|
||||||
|
n.RegexIn[expression] = regex
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Notify) Address() string {
|
||||||
|
return n.Protocoll + ":" + n.To
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- global notify
|
||||||
|
|
||||||
|
func (db *DB) InitNotify() {
|
||||||
|
if db.NotifiesByAddress == nil {
|
||||||
|
db.NotifiesByAddress = make(map[string]*Notify)
|
||||||
|
}
|
||||||
|
for _, n := range db.Notifies {
|
||||||
|
n.Init()
|
||||||
|
db.NotifiesByAddress[n.Address()] = n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) AddNotify(n *Notify) {
|
||||||
|
db.Notifies = append(db.Notifies, n)
|
||||||
|
db.NotifiesByAddress[n.Address()] = n
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) NewNotify(to string) *Notify {
|
||||||
|
addr := strings.Split(to, ":")
|
||||||
|
n := &Notify{
|
||||||
|
Protocoll: addr[0],
|
||||||
|
To: addr[1],
|
||||||
|
RegexIn: make(map[string]*regexp.Regexp),
|
||||||
|
}
|
||||||
|
db.AddNotify(n)
|
||||||
|
return n
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"dev.sum7.eu/genofire/golang-lib/file"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ReadDBFile(path string) *DB {
|
||||||
|
var db DB
|
||||||
|
|
||||||
|
if err := file.ReadJSON(path, &db); err == nil {
|
||||||
|
log.Infof("loaded %d hosts", len(db.HostTo))
|
||||||
|
|
||||||
|
db.InitNotify()
|
||||||
|
db.InitHost()
|
||||||
|
// import
|
||||||
|
db.update()
|
||||||
|
return &db
|
||||||
|
} else {
|
||||||
|
log.Error("failed to open db file: ", path, ":", err)
|
||||||
|
}
|
||||||
|
adb := &DB{}
|
||||||
|
adb.InitNotify()
|
||||||
|
adb.InitHost()
|
||||||
|
return adb
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package database
|
||||||
|
|
||||||
|
func (db *DB) update() {
|
||||||
|
if db.Hostname != nil {
|
||||||
|
for addr, name := range db.Hostname {
|
||||||
|
h, ok := db.HostsByName[name]
|
||||||
|
if !ok {
|
||||||
|
h = db.NewHost(addr)
|
||||||
|
db.ChangeHostname(h, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
db.Hostname = nil
|
||||||
|
}
|
||||||
|
if db.HostTo != nil {
|
||||||
|
for addr, channels := range db.HostTo {
|
||||||
|
h, ok := db.HostsByAddress[addr]
|
||||||
|
if !ok {
|
||||||
|
h = db.NewHost(addr)
|
||||||
|
}
|
||||||
|
for channel := range channels {
|
||||||
|
n, ok := db.NotifiesByAddress[channel]
|
||||||
|
if !ok {
|
||||||
|
n = db.NewNotify(channel)
|
||||||
|
}
|
||||||
|
h.AddNotify(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
db.HostTo = nil
|
||||||
|
}
|
||||||
|
if db.MaxPrioIn != nil {
|
||||||
|
for to, prio := range db.MaxPrioIn {
|
||||||
|
notify, ok := db.NotifiesByAddress[to]
|
||||||
|
if !ok {
|
||||||
|
notify = db.NewNotify(to)
|
||||||
|
}
|
||||||
|
notify.MaxPrioIn = prio
|
||||||
|
}
|
||||||
|
db.MaxPrioIn = nil
|
||||||
|
}
|
||||||
|
if db.RegexIn != nil {
|
||||||
|
for to, regexs := range db.RegexIn {
|
||||||
|
notify, ok := db.NotifiesByAddress[to]
|
||||||
|
if !ok {
|
||||||
|
notify = db.NewNotify(to)
|
||||||
|
}
|
||||||
|
for exp, _ := range regexs {
|
||||||
|
notify.AddRegex(exp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
db.RegexIn = nil
|
||||||
|
}
|
||||||
|
if db.Lastseen != nil {
|
||||||
|
for addr, t := range db.Lastseen {
|
||||||
|
h, ok := db.HostsByAddress[addr]
|
||||||
|
if !ok {
|
||||||
|
h = db.NewHost(addr)
|
||||||
|
}
|
||||||
|
h.Lastseen = t
|
||||||
|
}
|
||||||
|
db.Lastseen = nil
|
||||||
|
}
|
||||||
|
if db.LastseenNotify != nil {
|
||||||
|
for addr, t := range db.LastseenNotify {
|
||||||
|
h, ok := db.HostsByAddress[addr]
|
||||||
|
if !ok {
|
||||||
|
h = db.NewHost(addr)
|
||||||
|
}
|
||||||
|
h.LastseenNotify = t
|
||||||
|
}
|
||||||
|
db.LastseenNotify = nil
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,6 @@ package xmpp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
|
||||||
|
|
||||||
xmpp_client "dev.sum7.eu/genofire/yaja/client"
|
xmpp_client "dev.sum7.eu/genofire/yaja/client"
|
||||||
xmpp "dev.sum7.eu/genofire/yaja/xmpp"
|
xmpp "dev.sum7.eu/genofire/yaja/xmpp"
|
||||||
|
@ -16,8 +15,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
proto = "xmpp:"
|
proto = "xmpp"
|
||||||
protoGroup = "xmpp-muc:"
|
protoGroup = "xmpp-muc"
|
||||||
nickname = "logmania"
|
nickname = "logmania"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -94,9 +93,9 @@ func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifi
|
||||||
msg := element.(*xmpp.MessageClient)
|
msg := element.(*xmpp.MessageClient)
|
||||||
from := msg.From.Bare().String()
|
from := msg.From.Bare().String()
|
||||||
if msg.Type == xmpp.MessageTypeGroupchat {
|
if msg.Type == xmpp.MessageTypeGroupchat {
|
||||||
from = protoGroup + from
|
from = protoGroup + ":" + from
|
||||||
} else {
|
} else {
|
||||||
from = proto + from
|
from = proto + ":" + from
|
||||||
}
|
}
|
||||||
|
|
||||||
bot.Handle(func(answer string) {
|
bot.Handle(func(answer string) {
|
||||||
|
@ -116,10 +115,9 @@ func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
for _, toAddresses := range db.HostTo {
|
for toAddr, toAddresses := range db.NotifiesByAddress {
|
||||||
for to, _ := range toAddresses {
|
if toAddresses.Protocoll == protoGroup {
|
||||||
toAddr := strings.TrimPrefix(to, protoGroup)
|
toJID := xmppbase.NewJID(toAddresses.To)
|
||||||
toJID := xmppbase.NewJID(toAddr)
|
|
||||||
toJID.Resource = nickname
|
toJID.Resource = nickname
|
||||||
err := client.Send(&xmpp.PresenceClient{
|
err := client.Send(&xmpp.PresenceClient{
|
||||||
To: toJID,
|
To: toJID,
|
||||||
|
@ -143,19 +141,18 @@ func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifi
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Notifier) Send(e *log.Entry) error {
|
func (n *Notifier) Send(e *log.Entry) error {
|
||||||
e, to := n.db.SendTo(e)
|
e, _, tos := n.db.SendTo(e)
|
||||||
if to == nil {
|
if tos == nil || len(tos) <= 0 {
|
||||||
return errors.New("no reciever found")
|
return errors.New("no reciever found")
|
||||||
}
|
}
|
||||||
text, err := n.formatter.Format(e)
|
text, err := n.formatter.Format(e)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, toAddr := range to {
|
for _, to := range tos {
|
||||||
if strings.HasPrefix(toAddr, protoGroup) {
|
if to.Protocoll == protoGroup {
|
||||||
toAddr = strings.TrimPrefix(toAddr, protoGroup)
|
if _, ok := n.channels[to.To]; ok {
|
||||||
if _, ok := n.channels[toAddr]; ok {
|
toJID := xmppbase.NewJID(to.To)
|
||||||
toJID := xmppbase.NewJID(toAddr)
|
|
||||||
toJID.Resource = nickname
|
toJID.Resource = nickname
|
||||||
err := n.client.Send(&xmpp.PresenceClient{
|
err := n.client.Send(&xmpp.PresenceClient{
|
||||||
To: toJID,
|
To: toJID,
|
||||||
|
@ -163,22 +160,21 @@ func (n *Notifier) Send(e *log.Entry) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("xmpp could not join ", toJID.String(), " error:", err)
|
logger.Error("xmpp could not join ", toJID.String(), " error:", err)
|
||||||
} else {
|
} else {
|
||||||
n.channels[toAddr] = true
|
n.channels[to.To] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := n.client.Send(&xmpp.MessageClient{
|
err := n.client.Send(&xmpp.MessageClient{
|
||||||
Type: xmpp.MessageTypeGroupchat,
|
Type: xmpp.MessageTypeGroupchat,
|
||||||
To: xmppbase.NewJID(toAddr),
|
To: xmppbase.NewJID(to.To),
|
||||||
Body: string(text),
|
Body: string(text),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("xmpp to ", toAddr, " error:", err)
|
logger.Error("xmpp to ", to.To, " error:", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
toAddr = strings.TrimPrefix(toAddr, proto)
|
|
||||||
err := n.client.Send(&xmpp.MessageClient{
|
err := n.client.Send(&xmpp.MessageClient{
|
||||||
Type: xmpp.MessageTypeChat,
|
Type: xmpp.MessageTypeChat,
|
||||||
To: xmppbase.NewJID(toAddr),
|
To: xmppbase.NewJID(to.To),
|
||||||
Body: string(text),
|
Body: string(text),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue