Created
May 27, 2018 06:01
-
-
Save neguse/1d0eccb9b74dd2b07780fa2c1b1e0ee8 to your computer and use it in GitHub Desktop.
mattermostでrssを読むやつ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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