2017-05-10 19:15:24 +00:00
|
|
|
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
|
2017-05-10 19:56:03 +00:00
|
|
|
maxLines int
|
2017-05-10 19:15:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type cacheItem struct {
|
2017-05-10 19:56:03 +00:00
|
|
|
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")
|
|
|
|
|
2018-05-02 11:02:04 +00:00
|
|
|
if end-start == maxLines {
|
2017-05-10 19:56:03 +00:00
|
|
|
c.currentLine = end
|
|
|
|
} else {
|
2018-05-02 11:02:04 +00:00
|
|
|
c.currentLine = maxLines - (end - start)
|
2017-05-10 19:56:03 +00:00
|
|
|
page += "\n"
|
|
|
|
page += strings.Join(c.data[0:c.currentLine], "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
return page
|
2017-05-10 19:15:24 +00:00
|
|
|
}
|
|
|
|
|
2019-02-05 19:41:38 +00:00
|
|
|
func New(b bot.Bot) *RSSPlugin {
|
|
|
|
rss := &RSSPlugin{
|
|
|
|
Bot: b,
|
2017-05-10 19:15:24 +00:00
|
|
|
cache: map[string]*cacheItem{},
|
2019-02-05 19:41:38 +00:00
|
|
|
shelfLife: time.Minute * time.Duration(b.Config().GetInt("rss.shelfLife", 20)),
|
|
|
|
maxLines: b.Config().GetInt("rss.maxLines", 5),
|
2017-05-10 19:15:24 +00:00
|
|
|
}
|
2019-02-05 19:41:38 +00:00
|
|
|
b.Register(rss, bot.Message, rss.message)
|
|
|
|
b.Register(rss, bot.Help, rss.help)
|
|
|
|
return rss
|
2017-05-10 19:15:24 +00:00
|
|
|
}
|
|
|
|
|
2019-02-05 19:41:38 +00:00
|
|
|
func (p *RSSPlugin) message(kind bot.Kind, message msg.Message, args ...interface{}) bool {
|
2017-05-10 19:15:24 +00:00
|
|
|
tokens := strings.Fields(message.Body)
|
|
|
|
numTokens := len(tokens)
|
|
|
|
|
|
|
|
if numTokens == 2 && strings.ToLower(tokens[0]) == "rss" {
|
2017-05-10 19:56:03 +00:00
|
|
|
if item, ok := p.cache[strings.ToLower(tokens[1])]; ok && time.Now().Before(item.expiration) {
|
2019-02-05 15:54:13 +00:00
|
|
|
p.Bot.Send(bot.Message, message.Channel, item.getCurrentPage(p.maxLines))
|
2017-05-10 19:15:24 +00:00
|
|
|
return true
|
|
|
|
} else {
|
|
|
|
fp := gofeed.NewParser()
|
|
|
|
feed, err := fp.ParseURL(tokens[1])
|
|
|
|
if err != nil {
|
2019-02-05 15:54:13 +00:00
|
|
|
p.Bot.Send(bot.Message, message.Channel, fmt.Sprintf("RSS error: %s", err.Error()))
|
2017-05-10 19:15:24 +00:00
|
|
|
return true
|
|
|
|
}
|
2017-05-10 19:56:03 +00:00
|
|
|
item := &cacheItem{
|
|
|
|
key: strings.ToLower(tokens[1]),
|
|
|
|
data: []string{feed.Title},
|
|
|
|
expiration: time.Now().Add(p.shelfLife),
|
|
|
|
currentLine: 0,
|
2017-05-10 19:15:24 +00:00
|
|
|
}
|
|
|
|
|
2017-05-10 19:56:03 +00:00
|
|
|
for _, feedItem := range feed.Items {
|
|
|
|
item.data = append(item.data, feedItem.Title)
|
2017-05-10 19:15:24 +00:00
|
|
|
}
|
|
|
|
|
2017-05-10 19:56:03 +00:00
|
|
|
p.cache[strings.ToLower(tokens[1])] = item
|
|
|
|
|
2019-02-05 15:54:13 +00:00
|
|
|
p.Bot.Send(bot.Message, message.Channel, item.getCurrentPage(p.maxLines))
|
2017-05-10 19:15:24 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Help responds to help requests. Every plugin must implement a help function.
|
2019-02-05 19:41:38 +00:00
|
|
|
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
|
2017-05-10 19:15:24 +00:00
|
|
|
}
|