package bot import ( "context" "log" "strings" "time" "git.aiterp.net/gisle/irc" "git.aiterp.net/rpdata/logbot3/internal/models/channels" ) var botKey = "git.aiterp.net/rpdata/logbot.Bot.key" // The Bot is the IRC client. type Bot struct { commandChannel string client *irc.Client ctx context.Context ctxCancel context.CancelFunc } // New creates a new Bot. func New(ctx context.Context, nick string, alternatives []string) *Bot { client := irc.New(ctx, irc.Config{ Nick: nick, Alternatives: alternatives, SendRate: 2, SkipSSLVerification: false, }) bot := &Bot{ client: client, } client.SetValue(botKey, bot) return bot } // Connect connects the bot to the IRC server. This will disconnect already // established connections. func (bot *Bot) Connect(server string, ssl bool) error { if bot.ctxCancel != nil { bot.ctxCancel() } bot.ctx, bot.ctxCancel = context.WithCancel(bot.client.Context()) return bot.client.Connect(server, ssl) } func (bot *Bot) loop() { ticker := time.NewTicker(time.Second * 10) defer ticker.Stop() log.Println("Client ready.") for { select { case <-ticker.C: { bot.syncChannels() } case <-bot.ctx.Done(): { log.Println("Spinning down bot main loop.") return } } } } func (bot *Bot) syncChannels() { channels, err := channels.ListOpen(bot.ctx) if err != nil { log.Println("Failed to update channel-list:", err) return } names := make([]string, 0, len(channels)) joins := make([]string, 0, len(channels)) leaves := make([]string, 0, len(names)) // Add new channels to join list. for _, channel := range channels { name := channel.Name names = append(names, name) if bot.client.Channel(name) == nil { joins = append(joins, name) } } // Add no longer logged channels to leave list. LeaveLoop: for _, channel := range bot.client.Channels() { for _, name := range names { if strings.ToLower(channel.Name()) == strings.ToLower(name) { continue LeaveLoop } } } // Join channels. if len(joins) > 0 { log.Println("Joining", strings.Join(joins, ", ")) bot.client.SendQueuedf("JOIN %s", strings.Join(joins, ",")) } // leave channels. if len(leaves) > 0 { log.Println("Leaving", strings.Join(leaves, ", ")) bot.client.SendQueuedf("PART %s :Channel removed.", strings.Join(leaves, ",")) } } func (bot *Bot) stopLoop() { if bot.ctxCancel != nil { bot.ctxCancel() } }