mirror of https://github.com/matrix-org/go-neb.git
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.
173 lines
4.8 KiB
173 lines
4.8 KiB
package rssbot
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"strings"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/matrix-org/go-neb/database"
|
|
"github.com/matrix-org/go-neb/testutils"
|
|
"github.com/matrix-org/go-neb/types"
|
|
"maunium.net/go/mautrix"
|
|
mevt "maunium.net/go/mautrix/event"
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
const rssFeedXML = `
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<rss version="2.0"
|
|
xmlns:content="http://purl.org/rss/1.0/modules/content/"
|
|
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
|
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
xmlns:atom="http://www.w3.org/2005/Atom"
|
|
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
|
|
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
|
|
>
|
|
<channel>
|
|
<title>Mask Shop</title>
|
|
<item>
|
|
<title>New Item: Majora’s Mask</title>
|
|
<link>http://go.neb/rss/majoras-mask</link>
|
|
<author>The Skullkid!</author>
|
|
</item>
|
|
</channel>
|
|
</rss>`
|
|
|
|
func createRSSClient(t *testing.T, feedURL string) *Service {
|
|
database.SetServiceDB(&database.NopStorage{})
|
|
// Replace the cachingClient with a mock so we can intercept RSS requests
|
|
rssTrans := testutils.NewRoundTripper(func(req *http.Request) (*http.Response, error) {
|
|
if req.URL.String() != feedURL {
|
|
return nil, errors.New("Unknown test URL")
|
|
}
|
|
return &http.Response{
|
|
StatusCode: 200,
|
|
Body: ioutil.NopCloser(bytes.NewBufferString(rssFeedXML)),
|
|
}, nil
|
|
})
|
|
cachingClient = &http.Client{Transport: rssTrans}
|
|
|
|
// Create the RSS service
|
|
srv, err := types.CreateService("id", "rssbot", "@happy_mask_salesman:hyrule", []byte(
|
|
`{"feeds": {"`+feedURL+`":{}}}`, // no config yet
|
|
))
|
|
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
rssbot := srv.(*Service)
|
|
|
|
// Configure the service to force OnPoll to query the RSS feed and attempt to send results
|
|
// to the right room.
|
|
f := rssbot.Feeds[feedURL]
|
|
f.Rooms = []id.RoomID{"!linksroom:hyrule"}
|
|
f.NextPollTimestampSecs = time.Now().Unix()
|
|
rssbot.Feeds[feedURL] = f
|
|
|
|
return rssbot
|
|
}
|
|
|
|
func TestHTMLEntities(t *testing.T) {
|
|
feedURL := "https://thehappymaskshop.hyrule"
|
|
|
|
rssbot := createRSSClient(t, feedURL)
|
|
|
|
// Create the Matrix client which will send the notification
|
|
wg := sync.WaitGroup{}
|
|
wg.Add(1)
|
|
matrixTrans := struct{ testutils.MockTransport }{}
|
|
matrixTrans.RT = func(req *http.Request) (*http.Response, error) {
|
|
if strings.HasPrefix(req.URL.Path, "/_matrix/client/r0/rooms/!linksroom:hyrule/send/m.room.message") {
|
|
// Check content body to make sure it is decoded
|
|
var msg mevt.MessageEventContent
|
|
if err := json.NewDecoder(req.Body).Decode(&msg); err != nil {
|
|
t.Fatal("Failed to decode request JSON: ", err)
|
|
return nil, errors.New("Error handling matrix client test request")
|
|
}
|
|
want := "New Item: Majora\u2019s Mask" // 0x2019 = 8217
|
|
if !strings.Contains(msg.Body, want) {
|
|
t.Errorf("TestHTMLEntities: want '%s' in body, got '%s'", want, msg.Body)
|
|
}
|
|
|
|
wg.Done()
|
|
return &http.Response{
|
|
StatusCode: 200,
|
|
Body: ioutil.NopCloser(bytes.NewBufferString(`
|
|
{"event_id":"$123456:hyrule"}
|
|
`)),
|
|
}, nil
|
|
}
|
|
return nil, errors.New("Unhandled matrix client test request")
|
|
}
|
|
matrixClient, _ := mautrix.NewClient("https://hyrule", "@happy_mask_salesman:hyrule", "its_a_secret")
|
|
matrixClient.Client = &http.Client{Transport: matrixTrans}
|
|
|
|
// Invoke OnPoll to trigger the RSS feed update
|
|
_ = rssbot.OnPoll(matrixClient)
|
|
|
|
// Check that the Matrix client sent a message
|
|
wg.Wait()
|
|
}
|
|
|
|
func TestFeedItemFiltering(t *testing.T) {
|
|
feedURL := "https://thehappymaskshop.hyrule"
|
|
|
|
// Create rssbot client
|
|
rssbot := createRSSClient(t, feedURL)
|
|
|
|
feed := rssbot.Feeds[feedURL]
|
|
feed.MustInclude.Title = []string{"Zelda"}
|
|
rssbot.Feeds[feedURL] = feed
|
|
|
|
_, items, _ := rssbot.queryFeed(feedURL)
|
|
// Expect that we get no items if we filter for 'Zelda' in title
|
|
if len(items) != 0 {
|
|
t.Errorf("Expected 0 items, got %v", items)
|
|
}
|
|
|
|
// Recreate rssbot client
|
|
rssbot = createRSSClient(t, feedURL)
|
|
|
|
feed = rssbot.Feeds[feedURL]
|
|
feed.MustInclude.Title = []string{"Majora"}
|
|
rssbot.Feeds[feedURL] = feed
|
|
|
|
_, items, _ = rssbot.queryFeed(feedURL)
|
|
// Expect one item if we filter for 'Majora' in title
|
|
if len(items) != 1 {
|
|
t.Errorf("Expected 1 item, got %d", len(items))
|
|
}
|
|
|
|
// Recreate rssbot client
|
|
rssbot = createRSSClient(t, feedURL)
|
|
|
|
feed = rssbot.Feeds[feedURL]
|
|
feed.MustNotInclude.Author = []string{"kid"}
|
|
rssbot.Feeds[feedURL] = feed
|
|
|
|
_, items, _ = rssbot.queryFeed(feedURL)
|
|
// 'kid' does not match an entire word in the author name, so it's not filtered
|
|
if len(items) != 1 {
|
|
t.Errorf("Expected 1 item, got %d", len(items))
|
|
}
|
|
|
|
// Recreate rssbot client
|
|
rssbot = createRSSClient(t, feedURL)
|
|
|
|
feed = rssbot.Feeds[feedURL]
|
|
feed.MustNotInclude.Author = []string{"Skullkid"}
|
|
rssbot.Feeds[feedURL] = feed
|
|
|
|
_, items, _ = rssbot.queryFeed(feedURL)
|
|
// Expect no items if we filter for 'Skullkid' not in author name
|
|
if len(items) != 0 {
|
|
t.Errorf("Expected 0 items, got %v", items)
|
|
}
|
|
}
|