Skip to content

Instantly share code, notes, and snippets.

@neguse
Created May 27, 2018 06:01
Show Gist options
  • Save neguse/1d0eccb9b74dd2b07780fa2c1b1e0ee8 to your computer and use it in GitHub Desktop.
Save neguse/1d0eccb9b74dd2b07780fa2c1b1e0ee8 to your computer and use it in GitHub Desktop.
mattermostでrssを読むやつ
package main
import (
"database/sql"
"errors"
"flag"
"fmt"
"log"
"net/http"
"strings"
"time"
_ "github.com/mattn/go-sqlite3"
"github.com/mmcdole/gofeed"
)
type Feed struct {
URL string `db:"url"`
LastFetched time.Time `db:"last_fetched"`
}
type FeedItem struct {
URL string `db:"url"`
}
func GetOutdatedFeeds(db *sql.DB, intervalSec int) ([]Feed, error) {
// placeholder won't work.
q := fmt.Sprintf(`SELECT url, last_fetched FROM feed WHERE datetime(last_fetched, '%d seconds') < datetime('now')`, intervalSec)
rows, err := db.Query(q)
if err != nil {
return nil, err
}
var feeds []Feed
defer rows.Close()
for rows.Next() {
feed := Feed{}
err := rows.Scan(&feed.URL, &feed.LastFetched)
if err != nil {
return nil, err
}
feeds = append(feeds, feed)
}
err = rows.Err()
if err != nil {
return nil, err
}
return feeds, nil
}
func UpdateLastFetched(db *sql.DB, url string) error {
_, err := db.Exec(`UPDATE feed SET last_fetched = datetime('now') WHERE url = ?`, url)
return err
}
func HasFeedItem(db *sql.DB, url string) (bool, error) {
rows, err := db.Query(`SELECT url FROM feed_item WHERE url = ?)`, url)
if err != nil {
return false, err
}
defer rows.Close()
if !rows.Next() {
return false, nil
}
return true, nil
}
func InsertFeedItem(db *sql.DB, url string) (bool, error) {
res, err := db.Exec(`INSERT INTO feed_item (url) values (?)`, url)
if err != nil {
return false, err
}
if _, err := res.LastInsertId(); err != nil {
return false, err
}
return true, nil
}
var (
ErrPublishFail = errors.New("failed to publish")
)
func PublishFeedItem(url string, feed *gofeed.Feed, item *gofeed.Item) error {
body := strings.NewReader(fmt.Sprintf(`{"text":"%s [%s](%s)"}`, feed.Title, item.Title, item.Link))
resp, err := http.Post(url, "application/json", body)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return ErrPublishFail
}
return nil
}
func main() {
publishURL := flag.String("url", "", "URL for Mattermost Incoming Webhook")
flag.Parse()
db, err := sql.Open("sqlite3", "feed.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
first := true
if first {
db.Exec(`CREATE TABLE feed (url TEXT PRIMARY KEY, last_fetched DATETIME)`)
db.Exec(`CREATE TABLE feed_item (url TEXT PRIMERY KEY)`)
db.Exec(`INSERT INTO feed (url, last_fetched) VALUES ("https://www.unrealengine.com/rss", datetime('now', '-105 seconds'))`)
}
fp := gofeed.NewParser()
feeds, err := GetOutdatedFeeds(db, 100)
if err != nil {
log.Fatal(err)
}
for _, feed := range feeds {
log.Println("fetch ", feed.URL)
f, err := fp.ParseURL(feed.URL)
if err != nil {
log.Fatal(err)
}
for _, item := range f.Items {
ok, err := InsertFeedItem(db, item.Link)
if err != nil {
log.Fatal(err)
}
if ok {
err := PublishFeedItem(*publishURL, f, item)
if err != nil {
log.Fatal(err)
}
log.Println("published", item.Link)
}
}
err = UpdateLastFetched(db, feed.URL)
if err != nil {
log.Fatal(err)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment