func Test_HandleURLs(t *testing.T) { db := database.NewDatabase("./tests.sqlite", true) defer db.Close() Init(db) // --- --- --- --- --- --- Valid Event var testReply core.ReplyCallbackData HandleURLs(&validEvent, func(data *core.ReplyCallbackData) { testReply = *data }) if testReply != validReply { t.Errorf("Test data differ from reference data:\nTest data:\t%#v\nReference data: %#v\n\n", testReply, validReply) } // --- --- --- --- --- --- // --- --- --- --- --- --- Invalid Event HandleURLs(&invalidEvent, func(data *core.ReplyCallbackData) { // There is no memo command in the message, the callback should not be called t.Errorf("Callback function not supposed to be called, the message does not contain any URL (Message: %q)\n\n", messageWithoutURL) }) // --- --- --- --- --- --- // --- --- --- --- --- --- Valid Event => Trigger the "link already posted" function var testReplies []core.ReplyCallbackData HandleURLs(&validEvent, func(data *core.ReplyCallbackData) { testReplies = append(testReplies, *data) }) if len(testReplies) != 2 { t.Errorf("The test should trigger 2 callbacks, instead it triggered %d", len(testReplies)) } // First reply is the "Link already posted" message if !re.MatchString(testReplies[0].Message) { t.Errorf("Regexp %q not matching %q", re.String(), testReplies[0].Message) } // Second reply is the page title if testReplies[1] != validReply { t.Errorf("Test data differ from reference data:\nTest data:\t%#v\nReference data: %#v\n\n", testReplies[1], validReply) } // --- --- --- --- --- --- }
func Test_SendMemo(t *testing.T) { db := database.NewDatabase("./tests.sqlite", true) defer db.Close() Init(db) // Create Memo handleMemoCmd(&validEvent, nil) message := " this is a message to trigger the memo " event := irc.Event{Nick: expectedNick, Arguments: []string{"#test_channel", message}} re := regexp.MustCompile(fmt.Sprintf(`^%s: memo from Sender => "this is a memo" \(\d{2}/\d{2}/\d{4} @ \d{2}:\d{2}\)$`, expectedNick)) var testReply core.ReplyCallbackData SendMemo(&event, func(data *core.ReplyCallbackData) { testReply = *data }) if !re.MatchString(testReply.Message) { t.Errorf("Regexp %q not matching %q", re.String(), testReply.Message) } if testReply.Nick != expectedNick { t.Errorf("Incorrect Nick: should be %q, is %q", expectedNick, testReply.Nick) } }
func Test_handleMemoCmd(t *testing.T) { db := database.NewDatabase("./tests.sqlite", true) defer db.Close() Init(db) // --- --- --- --- --- --- Valid Event var testReply core.ReplyCallbackData handleMemoCmd(&validEvent, func(data *core.ReplyCallbackData) { testReply = *data }) if testReply != replyCallbackDataReference { t.Errorf("Test data differ from reference data:\nTest data:\t%#v\nReference data: %#v\n\n", testReply, replyCallbackDataReference) } // --- --- --- --- --- --- }
func main() { // Set log output to a file logFile, err := os.OpenFile("./goxxx_logs.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { log.Fatalf("Error opening file: %v", err) } defer logFile.Close() log.SetOutput(logFile) config, returnCode := getOptions() if returnCode == flagsExit { return } else if returnCode == flagsFailure { log.Fatal("Initialisation failed (getOptions())") } if config.debug { // In debug mode we show the file name and the line from where the log come from log.SetFlags(log.LstdFlags | log.Lshortfile) } // Create the database db := database.NewDatabase("", false) defer db.Close() // Process commands if necessary if returnCode == flagsAddUser { if err := database.AddUser(flag.Args()[1], flag.Args()[2]); err == nil { fmt.Println("User added to the database") } else { fmt.Printf("\nadd_user error: %s\n", err) } return } // Create the bot bot := core.NewBot(config.nick, config.server, config.channel, config.channelKey) // Initialise packages for _, module := range config.modules { switch strings.TrimSpace(module) { case "invoke": if !invoke.Init(db, config.emailSender, config.emailAccount, config.emailPassword, config.emailServer, config.emailPort) { log.Println("Error while initialising invoke package") continue } cmd := invoke.GetCommand() bot.AddCmdHandler(cmd, bot.ReplyToNick) help.AddMessages(cmd) log.Println("invoke module loaded") case "memo": memo.Init(db) bot.AddMsgHandler(memo.SendMemo, bot.ReplyToNick) cmd := memo.GetMemoCommand() bot.AddCmdHandler(cmd, bot.ReplyToAll) help.AddMessages(cmd) cmd = memo.GetMemoStatCommand() bot.AddCmdHandler(cmd, bot.ReplyToNick) help.AddMessages(cmd) log.Println("memo module loaded") case "search": cmd := search.GetDuckduckGoCmd() bot.AddCmdHandler(cmd, bot.Reply) help.AddMessages(cmd) cmd = search.GetWikipediaCmd() bot.AddCmdHandler(cmd, bot.Reply) help.AddMessages(cmd) cmd = search.GetWikipediaFRCmd() bot.AddCmdHandler(cmd, bot.Reply) help.AddMessages(cmd) cmd = search.GetUrbanDictionnaryCmd() bot.AddCmdHandler(cmd, bot.Reply) help.AddMessages(cmd) log.Println("search module loaded") case "webinfo": webinfo.Init(db) bot.AddMsgHandler(webinfo.HandleURLs, bot.ReplyToAll) cmd := webinfo.GetCommand() bot.AddCmdHandler(cmd, bot.ReplyToAll) help.AddMessages(cmd) log.Println("webinfo module loaded") case "xkcd": cmd := xkcd.GetCommand() bot.AddCmdHandler(cmd, bot.ReplyToAll) help.AddMessages(cmd) log.Println("xkcd module loaded") case "pictures": pictures.Init(db, config.admins) cmd := pictures.GetPicCommand() bot.AddCmdHandler(cmd, bot.ReplyToAll) help.AddMessages(cmd) cmd = pictures.GetAddPicCommand() bot.AddCmdHandler(cmd, bot.ReplyToAll) help.AddMessages(cmd) cmd = pictures.GetRmPicCommand() bot.AddCmdHandler(cmd, bot.ReplyToAll) help.AddMessages(cmd) log.Println("pictures module loaded") case "quote": quote.Init(db, config.admins) bot.AddMsgHandler(quote.HandleMessages, nil) cmd := quote.GetQuoteCommand() bot.AddCmdHandler(cmd, bot.ReplyToAll) help.AddMessages(cmd) cmd = quote.GetRmQuoteCommand() bot.AddCmdHandler(cmd, bot.ReplyToAll) help.AddMessages(cmd) log.Println("quote module loaded") default: } } bot.AddCmdHandler(help.GetCommand(), bot.ReplyToNick) log.Println("Goxxx started") // Go signal notification works by sending os.Signal values on a channel. // We'll create a channel to receive these notifications // (we'll also make one to notify us when the program can exit). interruptSignals := make(chan os.Signal, 1) done := make(chan bool, 1) // signal.Notify registers the given channel to receive notifications of the specified signals. signal.Notify(interruptSignals, syscall.SIGINT, syscall.SIGTERM) // This goroutine executes a blocking receive for signals. // When it gets one it'll print it out and then notify the program that it can finish. go func() { sig := <-interruptSignals log.Printf("System signal received: %s\n", sig) done <- true }() // Start the bot go bot.Run() // The current routine will be blocked here until done is true <-done // Close the bot connection and the database bot.Stop() db.Close() log.Println("Goxxx exiting") }