ready to pass from server to monitor but monitor still needs save to disk and reload
Former-commit-id: 1cebef822fdc157f0622b4e0fb9f93db48e0e70dmaster
parent
4bd05d15b4
commit
5e87f1659d
|
|
@ -1,8 +1,6 @@
|
||||||
package monitor
|
package monitor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/gob"
|
|
||||||
"local/rssmon3/config"
|
"local/rssmon3/config"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -65,19 +63,16 @@ func (i *Item) getInterval() (time.Duration, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return forever, err
|
return forever, err
|
||||||
}
|
}
|
||||||
buff := bytes.NewBuffer(b)
|
err = config.Decode(b, &t)
|
||||||
dec := gob.NewDecoder(buff)
|
|
||||||
err = dec.Decode(&t)
|
|
||||||
return t, err
|
return t, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Item) setInterval(t time.Duration) error {
|
func (i *Item) setInterval(t time.Duration) error {
|
||||||
buff := bytes.NewBuffer(nil)
|
b, err := config.Encode(t)
|
||||||
enc := gob.NewEncoder(buff)
|
if err != nil {
|
||||||
if err := enc.Encode(t); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := config.Values().DB.Set(i.Key, buff.Bytes(), nsInterval); err != nil {
|
if err := config.Values().DB.Set(i.Key, b, nsInterval); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -98,29 +93,21 @@ func (i *Item) Mark() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Item) setLast(t time.Time) error {
|
func (i *Item) setLast(t time.Time) error {
|
||||||
buff := bytes.NewBuffer(nil)
|
b, err := config.Encode(t)
|
||||||
enc := gob.NewEncoder(buff)
|
if err != nil {
|
||||||
if err := enc.Encode(t); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := config.Values().DB.Set(i.Key, buff.Bytes(), nsLast); err != nil {
|
return config.Values().DB.Set(i.Key, b, nsLast)
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Item) getLast() (time.Time, error) {
|
func (i *Item) getLast() (time.Time, error) {
|
||||||
t := time.Now()
|
t := never
|
||||||
b, err := config.Values().DB.Get(i.Key, nsLast)
|
b, err := config.Values().DB.Get(i.Key, nsLast)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return never, err
|
return never, err
|
||||||
}
|
}
|
||||||
buff := bytes.NewBuffer(b)
|
err = config.Decode(b, &t)
|
||||||
dec := gob.NewDecoder(buff)
|
return t, err
|
||||||
if err := dec.Decode(&t); err != nil {
|
|
||||||
return never, err
|
|
||||||
}
|
|
||||||
return t, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Item) Encode() ([]byte, error) {
|
func (i *Item) Encode() ([]byte, error) {
|
||||||
|
|
|
||||||
21
rss/feed.go
21
rss/feed.go
|
|
@ -23,25 +23,8 @@ type Feed struct {
|
||||||
Tags []string
|
Tags []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func TaggedFeeds(tag string) ([]*Feed, error) {
|
func SubmitFeed(f *Feed) error {
|
||||||
db := config.Values().DB
|
return f.save()
|
||||||
feedNames, err := db.List([]string{nsFeeds})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
results := []*Feed{}
|
|
||||||
for _, feedName := range feedNames {
|
|
||||||
f := newFeed(feedName)
|
|
||||||
if err := f.Load(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for i := range f.Tags {
|
|
||||||
if f.Tags[i] == tag {
|
|
||||||
results = append(results, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFeed(key string) *Feed {
|
func newFeed(key string) *Feed {
|
||||||
|
|
|
||||||
|
|
@ -177,29 +177,3 @@ func TestRSSFeedPull(t *testing.T) {
|
||||||
t.Fatal(i)
|
t.Fatal(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRSSTaggedFeeds(t *testing.T) {
|
|
||||||
initRSSFeed()
|
|
||||||
|
|
||||||
for _, k := range []string{"a", "b"} {
|
|
||||||
f := newFeed(k)
|
|
||||||
f.Tags = []string{"TAG"}
|
|
||||||
if err := f.save(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if feeds, err := TaggedFeeds("NOTTAG"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if len(feeds) != 0 {
|
|
||||||
t.Fatal(len(feeds))
|
|
||||||
}
|
|
||||||
|
|
||||||
if feeds, err := TaggedFeeds("TAG"); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
} else if len(feeds) != 2 {
|
|
||||||
t.Fatal(len(feeds))
|
|
||||||
} else {
|
|
||||||
t.Logf("%v", feeds)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package rss
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"local/rssmon3/config"
|
||||||
|
|
||||||
|
"github.com/gorilla/feeds"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TaggedFeeds(tag string) ([]*Feed, error) {
|
||||||
|
db := config.Values().DB
|
||||||
|
feedNames, err := db.List([]string{nsFeeds})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
results := []*Feed{}
|
||||||
|
for _, feedName := range feedNames {
|
||||||
|
f := newFeed(feedName)
|
||||||
|
if err := f.Load(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for i := range f.Tags {
|
||||||
|
if f.Tags[i] == tag {
|
||||||
|
results = append(results, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteFeed(w io.Writer, tag string, items []*Item) error {
|
||||||
|
feed := &feeds.Feed{
|
||||||
|
Title: tag,
|
||||||
|
Link: &feeds.Link{},
|
||||||
|
Description: tag,
|
||||||
|
Items: make([]*feeds.Item, len(items)),
|
||||||
|
}
|
||||||
|
for i, item := range items {
|
||||||
|
feed.Items[i] = &feeds.Item{
|
||||||
|
Title: item.Title,
|
||||||
|
Link: &feeds.Link{Href: item.Link},
|
||||||
|
Description: item.Content,
|
||||||
|
Created: item.TS,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s, err := feed.ToRss()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
w.Write([]byte(s))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package rss
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func initRSSSerialize() {
|
||||||
|
initRSSFeed()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRSSTaggedFeeds(t *testing.T) {
|
||||||
|
initRSSFeed()
|
||||||
|
|
||||||
|
for _, k := range []string{"a", "b"} {
|
||||||
|
f := newFeed(k)
|
||||||
|
f.Tags = []string{"TAG"}
|
||||||
|
if err := f.save(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if feeds, err := TaggedFeeds("NOTTAG"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if len(feeds) != 0 {
|
||||||
|
t.Fatal(len(feeds))
|
||||||
|
}
|
||||||
|
|
||||||
|
if feeds, err := TaggedFeeds("TAG"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if len(feeds) != 2 {
|
||||||
|
t.Fatal(len(feeds))
|
||||||
|
} else {
|
||||||
|
t.Logf("%v", feeds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRSSWriteFeed(t *testing.T) {
|
||||||
|
initRSSFeed()
|
||||||
|
s := mockRSS()
|
||||||
|
defer s.Close()
|
||||||
|
|
||||||
|
f := newFeed("key")
|
||||||
|
f.TitleFilter = "5[0-9]{2}"
|
||||||
|
f.ContentFilter = "b"
|
||||||
|
f.Tags = []string{"c"}
|
||||||
|
f.URL = s.URL
|
||||||
|
|
||||||
|
log.SetOutput(bytes.NewBuffer(nil))
|
||||||
|
defer log.SetOutput(os.Stderr)
|
||||||
|
if err := f.pull(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
log.SetOutput(os.Stderr)
|
||||||
|
|
||||||
|
items, err := f.Items(5)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(items) != 5 {
|
||||||
|
t.Fatal(len(items))
|
||||||
|
}
|
||||||
|
|
||||||
|
buff := bytes.NewBuffer(nil)
|
||||||
|
if err := WriteFeed(buff, "c", items); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Logf("%s", buff.Bytes())
|
||||||
|
}
|
||||||
Binary file not shown.
|
|
@ -1,12 +1,16 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"local/router"
|
"local/router"
|
||||||
|
"local/rssmon3/monitor"
|
||||||
|
"local/rssmon3/rss"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Server) Routes() error {
|
func (s *Server) Routes() error {
|
||||||
|
|
@ -15,6 +19,7 @@ func (s *Server) Routes() error {
|
||||||
handler http.HandlerFunc
|
handler http.HandlerFunc
|
||||||
}{
|
}{
|
||||||
{path: fmt.Sprintf("/api/tag/%s", router.Wildcard), handler: s.tag},
|
{path: fmt.Sprintf("/api/tag/%s", router.Wildcard), handler: s.tag},
|
||||||
|
{path: fmt.Sprintf("/api/feed"), handler: s.feed},
|
||||||
}
|
}
|
||||||
for _, handle := range handles {
|
for _, handle := range handles {
|
||||||
if err := s.router.Add(handle.path, handle.handler); err != nil {
|
if err := s.router.Add(handle.path, handle.handler); err != nil {
|
||||||
|
|
@ -47,6 +52,57 @@ func (s *Server) tag(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tag := regexp.MustCompile("^.*\\/").ReplaceAllString(r.URL.Path, "")
|
tag := regexp.MustCompile("^.*\\/").ReplaceAllString(r.URL.Path, "")
|
||||||
log.Println(tag)
|
feeds, err := rss.TaggedFeeds(tag)
|
||||||
|
if err != nil {
|
||||||
|
s.error(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
items := []*rss.Item{}
|
||||||
|
for _, feed := range feeds {
|
||||||
|
feedItems, err := feed.Items(20)
|
||||||
|
if err != nil {
|
||||||
|
s.error(w, r, err)
|
||||||
|
}
|
||||||
|
items = append(items, feedItems...)
|
||||||
|
}
|
||||||
|
if err := rss.WriteFeed(w, tag, items); err != nil {
|
||||||
|
s.error(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) feed(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != "PUT" {
|
||||||
|
s.notFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var putFeed struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
Interval time.Duration `json:"refresh"`
|
||||||
|
TitleFilter string `json:"items"`
|
||||||
|
ContentFilter string `json:"content"`
|
||||||
|
Tags []string `json:"tags"`
|
||||||
|
}
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&putFeed); err != nil {
|
||||||
|
s.userError(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f := &rss.Feed{
|
||||||
|
Key: putFeed.URL,
|
||||||
|
URL: putFeed.URL,
|
||||||
|
TitleFilter: putFeed.TitleFilter,
|
||||||
|
ContentFilter: putFeed.ContentFilter,
|
||||||
|
Tags: putFeed.Tags,
|
||||||
|
}
|
||||||
|
if err := rss.SubmitFeed(f); err != nil {
|
||||||
|
s.error(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
i, err := monitor.NewItem(f.Key, putFeed.Interval)
|
||||||
|
if err != nil {
|
||||||
|
s.error(w, r, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println(i)
|
||||||
s.error(w, r, errors.New("not impl"))
|
s.error(w, r, errors.New("not impl"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue