catbase/plugins/rss/rss.go

110 lines
2.5 KiB
Go

package rss
import (
"fmt"
"strings"
"time"
"github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/mmcdole/gofeed"
)
type RSSPlugin struct {
Bot bot.Bot
cache map[string]*cacheItem
shelfLife time.Duration
maxLines int
}
type cacheItem struct {
key string
data []string
currentLine int
expiration time.Time
}
func (c *cacheItem) getCurrentPage(maxLines int) string {
if len(c.data) <= maxLines {
return strings.Join(c.data, "\n")
}
start := c.currentLine
end := start + maxLines
if end > len(c.data) {
end = len(c.data)
}
page := strings.Join(c.data[start:end], "\n")
if end-start == maxLines {
c.currentLine = end
} else {
c.currentLine = maxLines - (end - start)
page += "\n"
page += strings.Join(c.data[0:c.currentLine], "\n")
}
return page
}
func New(b bot.Bot) *RSSPlugin {
rss := &RSSPlugin{
Bot: b,
cache: map[string]*cacheItem{},
shelfLife: time.Minute * time.Duration(b.Config().GetInt("rss.shelfLife", 20)),
maxLines: b.Config().GetInt("rss.maxLines", 5),
}
b.Register(rss, bot.Message, rss.message)
b.Register(rss, bot.Help, rss.help)
return rss
}
func (p *RSSPlugin) message(kind bot.Kind, message msg.Message, args ...interface{}) bool {
tokens := strings.Fields(message.Body)
numTokens := len(tokens)
if numTokens == 2 && strings.ToLower(tokens[0]) == "rss" {
if item, ok := p.cache[strings.ToLower(tokens[1])]; ok && time.Now().Before(item.expiration) {
p.Bot.Send(bot.Message, message.Channel, item.getCurrentPage(p.maxLines))
return true
} else {
fp := gofeed.NewParser()
feed, err := fp.ParseURL(tokens[1])
if err != nil {
p.Bot.Send(bot.Message, message.Channel, fmt.Sprintf("RSS error: %s", err.Error()))
return true
}
item := &cacheItem{
key: strings.ToLower(tokens[1]),
data: []string{feed.Title},
expiration: time.Now().Add(p.shelfLife),
currentLine: 0,
}
for _, feedItem := range feed.Items {
item.data = append(item.data, feedItem.Title)
}
p.cache[strings.ToLower(tokens[1])] = item
p.Bot.Send(bot.Message, message.Channel, item.getCurrentPage(p.maxLines))
return true
}
}
return false
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *RSSPlugin) help(kind bot.Kind, message msg.Message, args ...interface{}) bool {
p.Bot.Send(bot.Message, message.Channel, "try '!rss http://rss.cnn.com/rss/edition.rss'")
return true
}
// Register any web URLs desired
func (p *RSSPlugin) RegisterWeb() *string {
return nil
}