barebones rss headline skimmer

This commit is contained in:
skkiesel 2017-05-10 15:15:24 -04:00
parent 419c188085
commit 9c39e3cd41
3 changed files with 138 additions and 0 deletions

View File

@ -18,6 +18,7 @@ import (
"github.com/velour/catbase/plugins/fact"
"github.com/velour/catbase/plugins/leftpad"
"github.com/velour/catbase/plugins/reminder"
"github.com/velour/catbase/plugins/rss"
"github.com/velour/catbase/plugins/talker"
"github.com/velour/catbase/plugins/your"
"github.com/velour/catbase/plugins/zork"
@ -57,6 +58,7 @@ func main() {
b.AddHandler("reminder", reminder.New(b))
b.AddHandler("babbler", babbler.New(b))
b.AddHandler("zork", zork.New(b))
b.AddHandler("rss", rss.New(b))
// catches anything left, will always return true
b.AddHandler("factoid", fact.New(b))

92
plugins/rss/rss.go Normal file
View File

@ -0,0 +1,92 @@
package rss
import (
"fmt"
"log"
"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
}
type cacheItem struct {
key string
data string
expiration time.Time
}
func New(bot bot.Bot) *RSSPlugin {
return &RSSPlugin{
Bot: bot,
cache: map[string]*cacheItem{},
shelfLife: time.Minute * 20,
}
}
func (p *RSSPlugin) Message(message msg.Message) bool {
tokens := strings.Fields(message.Body)
numTokens := len(tokens)
if numTokens == 2 && strings.ToLower(tokens[0]) == "rss" {
if data, ok := p.cache[strings.ToLower(tokens[1])]; ok && time.Now().Before(data.expiration) {
log.Printf("rss cache hit")
p.Bot.SendMessage(message.Channel, data.data)
return true
} else {
fp := gofeed.NewParser()
feed, err := fp.ParseURL(tokens[1])
if err != nil {
p.Bot.SendMessage(message.Channel, fmt.Sprintf("RSS error: %s", err.Error()))
return true
}
response := feed.Title
for _, item := range feed.Items {
response += fmt.Sprintf("\n%s", item.Title)
}
p.cache[strings.ToLower(tokens[1])] = &cacheItem{
key: strings.ToLower(tokens[1]),
data: response,
expiration: time.Now().Add(p.shelfLife),
}
p.Bot.SendMessage(message.Channel, response)
return true
}
}
return false
}
func (p *RSSPlugin) LoadData() {
// This bot has no data to load
}
// Help responds to help requests. Every plugin must implement a help function.
func (p *RSSPlugin) Help(channel string, parts []string) {
p.Bot.SendMessage(channel, "try '!rss http://rss.cnn.com/rss/edition.rss'")
}
// Empty event handler because this plugin does not do anything on event recv
func (p *RSSPlugin) Event(kind string, message msg.Message) bool {
return false
}
// Handler for bot's own messages
func (p *RSSPlugin) BotMessage(message msg.Message) bool {
return false
}
// Register any web URLs desired
func (p *RSSPlugin) RegisterWeb() *string {
return nil
}

44
plugins/rss/rss_test.go Normal file
View File

@ -0,0 +1,44 @@
package rss
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
)
func makeMessage(payload string) msg.Message {
isCmd := strings.HasPrefix(payload, "!")
if isCmd {
payload = payload[1:]
}
return msg.Message{
User: &user.User{Name: "tester"},
Channel: "test",
Body: payload,
Command: isCmd,
}
}
func TestRSS(t *testing.T) {
mb := bot.NewMockBot()
c := New(mb)
assert.NotNil(t, c)
res := c.Message(makeMessage("!rss http://rss.cnn.com/rss/edition.rss"))
assert.Len(t, mb.Messages, 1)
assert.True(t, res)
}
func TestRSSCache(t *testing.T) {
mb := bot.NewMockBot()
c := New(mb)
assert.NotNil(t, c)
res := c.Message(makeMessage("!rss http://rss.cnn.com/rss/edition.rss"))
assert.True(t, res)
res = c.Message(makeMessage("!rss http://rss.cnn.com/rss/edition.rss"))
assert.Len(t, mb.Messages, 2)
assert.True(t, res)
}