mirror of https://github.com/velour/catbase.git
barebones rss headline skimmer
This commit is contained in:
parent
419c188085
commit
9c39e3cd41
2
main.go
2
main.go
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/velour/catbase/plugins/fact"
|
"github.com/velour/catbase/plugins/fact"
|
||||||
"github.com/velour/catbase/plugins/leftpad"
|
"github.com/velour/catbase/plugins/leftpad"
|
||||||
"github.com/velour/catbase/plugins/reminder"
|
"github.com/velour/catbase/plugins/reminder"
|
||||||
|
"github.com/velour/catbase/plugins/rss"
|
||||||
"github.com/velour/catbase/plugins/talker"
|
"github.com/velour/catbase/plugins/talker"
|
||||||
"github.com/velour/catbase/plugins/your"
|
"github.com/velour/catbase/plugins/your"
|
||||||
"github.com/velour/catbase/plugins/zork"
|
"github.com/velour/catbase/plugins/zork"
|
||||||
|
@ -57,6 +58,7 @@ func main() {
|
||||||
b.AddHandler("reminder", reminder.New(b))
|
b.AddHandler("reminder", reminder.New(b))
|
||||||
b.AddHandler("babbler", babbler.New(b))
|
b.AddHandler("babbler", babbler.New(b))
|
||||||
b.AddHandler("zork", zork.New(b))
|
b.AddHandler("zork", zork.New(b))
|
||||||
|
b.AddHandler("rss", rss.New(b))
|
||||||
// catches anything left, will always return true
|
// catches anything left, will always return true
|
||||||
b.AddHandler("factoid", fact.New(b))
|
b.AddHandler("factoid", fact.New(b))
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
Loading…
Reference in New Issue