diff --git a/go.mod b/go.mod index 9f05af6..3d9e673 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,9 @@ module github.com/Difrex/ctf2021_ircbot go 1.15 -require github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb +require ( + github.com/boltdb/bolt v1.3.1 + github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb + golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect + golang.org/x/text v0.3.5 // indirect +) diff --git a/go.sum b/go.sum index fbef1aa..d774a2a 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,11 @@ +github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb h1:EavwSqheIJl3nb91HhkL73DwnT2Fk8W3yM7T7TuLZvA= github.com/thoj/go-ircevent v0.0.0-20190807115034-8e7ce4b5a1eb/go.mod h1:I0ZT9x8wStY6VOxtNOrLpnDURFs7HS0z1e1vhuKUEVc= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/main.go b/main.go index 4b2d82a..4ad6526 100644 --- a/main.go +++ b/main.go @@ -21,6 +21,7 @@ import ( var channel = "#ctf" var sendHi = "" +var writeHistory = false const ( pattern = "(?i)\\b(cat|gato|miau|meow|garfield|lolcat)[s|z]{0,1}\\b" @@ -31,13 +32,15 @@ const ( // environment variables const ( - userEnv = "IRC_USER" - nickEnv = "IRC_NICK" - himsgEnv = "IRC_SAY_HI" - passEnv = "IRC_PASS" - chanEnv = "IRC_CHAN" - urlEnv = "IRC_URL" - invitionsEnv = "IRC_ENABLE_INVITIONS" + userEnv = "IRC_USER" + nickEnv = "IRC_NICK" + himsgEnv = "IRC_SAY_HI" + passEnv = "IRC_PASS" + chanEnv = "IRC_CHAN" + urlEnv = "IRC_URL" + invitionsEnv = "IRC_ENABLE_INVITIONS" + chanHistoryEnv = "IRC_CHAN_HISTORY" + dbPathEnv = "IRC_DB_PATH" ) type catFact struct { @@ -53,6 +56,7 @@ var ( type stats struct { userMessages map[string]uint invites map[string]bool + history *history mux *sync.Mutex } @@ -124,6 +128,7 @@ func addCallbacks(irccon *irc.Connection, s *stats) { e.Connection.Join(channel) e.Connection.Action(channel, "=^_^= https://gitea.difrex.ru/CTF2021/irc_bot") + e.Connection.Action(channel, "πŸ˜ΈπŸ¦„πŸ˜Έ Now with HiStOrY!!! πŸ˜ΈπŸ¦„πŸ˜Έ") // Greetings if sendHi != "" { @@ -146,8 +151,16 @@ func addCallbacks(irccon *irc.Connection, s *stats) { func main() { nick := os.Getenv(nickEnv) irccon := irc.IRC(nick, os.Getenv(userEnv)) + if irccon == nil { + log.Fatal("Connection is nil") + } s := newStats() + history, err := Open(os.Getenv(dbPathEnv)) + if err != nil { + writeHistory = false + } + s.history = history irccon.VerboseCallbackHandler = false irccon.Debug = false @@ -155,8 +168,7 @@ func main() { addCallbacks(irccon, s) - err := irccon.Connect(os.Getenv(urlEnv)) - if err != nil { + if err := irccon.Connect(os.Getenv(urlEnv)); err != nil { fmt.Printf("Err %s", err) return } @@ -170,10 +182,65 @@ func isHelpCommand(command string, e *irc.Event) bool { return false } +func isHistoryCommand(command string, e *irc.Event) bool { + if e.Nick != channel && strings.HasPrefix(e.Message(), "history") { + return true + } + return false +} + +func parseHistoryCommandArgs(e *irc.Event) [2]string { + var args [2]string + + message := strings.Split(e.Message(), " ") + if len(message) == 3 { + args[0] = message[1] + args[1] = message[2] + } + if len(message) == 2 { + args[0] = message[1] + } + + return args +} + +func showLogs(e *irc.Event, s *stats) { + var logs []LogLine + args := parseHistoryCommandArgs(e) + + if args[0] == "all" { + l, err := s.history.GetAllLog() + if err != nil { + log.Println("Error:", err) + return + } + logs = l + } + + if args[0] != "" && args[1] != "" { + l, err := s.history.GetRangedLogs(args[0], args[1]) + if err != nil { + log.Println("Error:", err) + return + } + logs = l + } + + if len(logs) == 0 { + e.Connection.Privmsg(e.Nick, ":( such empty") + } + + e.Connection.Privmsg(e.Nick, "WOW!!! HiStOrY!!!") + for _, l := range logs { + e.Connection.Privmsg(e.Nick, fmt.Sprintf("%s [%s] %s", l.Time.Format("2006-01-02T15:04:05"), l.Nick, l.Message)) + } +} + func showHelp(e *irc.Event) { e.Connection.Privmsg(e.Nick, "HELP -- show this help") e.Connection.Privmsg(e.Nick, "cat|meow|etc -- show cat fact or gif") e.Connection.Privmsg(e.Nick, "nyastat -- show #ctf channel stats") + e.Connection.Privmsg(e.Nick, "history -- show #ctf channel history logs") } func doCommand(command string, e *irc.Event, s *stats) { @@ -187,7 +254,20 @@ func doCommand(command string, e *irc.Event, s *stats) { return } + if isHistoryCommand(command, e) { + showLogs(e, s) + return + } + if ok := checkCommad(command, e.Connection); !ok { + err := s.history.WriteLog(&LogLine{ + Nick: e.Nick, + Message: e.Message(), + Time: time.Now(), + }) + if err != nil { + log.Println("Error:", err) + } return } @@ -263,14 +343,22 @@ func getChanName(e *irc.Event) string { return c } -func isInvitionsEnabled() bool { - enabled := os.Getenv(invitionsEnv) - if strings.ToLower(enabled) == "yes" { +func isFetureEnabled(feature string) bool { + if feature != "" && strings.ToLower(feature) == "yes" { return true } + return false } +func isInvitionsEnabled() bool { + return isFetureEnabled(os.Getenv(invitionsEnv)) +} + +func isHistoryEnabled() bool { + return isFetureEnabled(os.Getenv(chanHistoryEnv)) +} + func getNick() string { return os.Getenv(nickEnv) } @@ -282,4 +370,6 @@ func init() { } sendHi = os.Getenv(himsgEnv) + + writeHistory = isFetureEnabled(os.Getenv(chanHistoryEnv)) }