The new logbot, not committed from the wrong terminal window this time.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
2.4 KiB

6 years ago
  1. package bot
  2. import (
  3. "context"
  4. "log"
  5. "strings"
  6. "time"
  7. "git.aiterp.net/gisle/irc"
  8. "git.aiterp.net/rpdata/logbot3/internal/models/channels"
  9. )
  10. var botKey = "git.aiterp.net/rpdata/logbot.Bot.key"
  11. // The Bot is the IRC client.
  12. type Bot struct {
  13. commandChannel string
  14. client *irc.Client
  15. ctx context.Context
  16. ctxCancel context.CancelFunc
  17. }
  18. // New creates a new Bot.
  19. func New(ctx context.Context, nick string, alternatives []string) *Bot {
  20. client := irc.New(ctx, irc.Config{
  21. Nick: nick,
  22. Alternatives: alternatives,
  23. SendRate: 2,
  24. SkipSSLVerification: false,
  25. })
  26. bot := &Bot{
  27. client: client,
  28. }
  29. client.SetValue(botKey, bot)
  30. return bot
  31. }
  32. // Connect connects the bot to the IRC server. This will disconnect already
  33. // established connections.
  34. func (bot *Bot) Connect(server string, ssl bool) error {
  35. if bot.ctxCancel != nil {
  36. bot.ctxCancel()
  37. }
  38. bot.ctx, bot.ctxCancel = context.WithCancel(bot.client.Context())
  39. return bot.client.Connect(server, ssl)
  40. }
  41. func (bot *Bot) loop() {
  42. ticker := time.NewTicker(time.Second * 10)
  43. defer ticker.Stop()
  44. log.Println("Client ready.")
  45. for {
  46. select {
  47. case <-ticker.C:
  48. {
  49. bot.syncChannels()
  50. }
  51. case <-bot.ctx.Done():
  52. {
  53. log.Println("Spinning down bot main loop.")
  54. return
  55. }
  56. }
  57. }
  58. }
  59. func (bot *Bot) syncChannels() {
  60. channels, err := channels.ListOpen(bot.ctx)
  61. if err != nil {
  62. log.Println("Failed to update channel-list:", err)
  63. return
  64. }
  65. names := make([]string, 0, len(channels))
  66. joins := make([]string, 0, len(channels))
  67. leaves := make([]string, 0, len(names))
  68. // Add new channels to join list.
  69. for _, channel := range channels {
  70. name := channel.Name
  71. names = append(names, name)
  72. if bot.client.Channel(name) == nil {
  73. joins = append(joins, name)
  74. }
  75. }
  76. // Add no longer logged channels to leave list.
  77. LeaveLoop:
  78. for _, channel := range bot.client.Channels() {
  79. for _, name := range names {
  80. if strings.ToLower(channel.Name()) == strings.ToLower(name) {
  81. continue LeaveLoop
  82. }
  83. }
  84. }
  85. // Join channels.
  86. if len(joins) > 0 {
  87. log.Println("Joining", strings.Join(joins, ", "))
  88. bot.client.SendQueuedf("JOIN %s", strings.Join(joins, ","))
  89. }
  90. // leave channels.
  91. if len(leaves) > 0 {
  92. log.Println("Leaving", strings.Join(leaves, ", "))
  93. bot.client.SendQueuedf("PART %s :Channel removed.", strings.Join(leaves, ","))
  94. }
  95. }
  96. func (bot *Bot) stopLoop() {
  97. if bot.ctxCancel != nil {
  98. bot.ctxCancel()
  99. }
  100. }