Compare commits

..

No commits in common. "6677bd95ab7478bc4cd9740e173481fbc57f5c29" and "6d3eaa020d76764b390e1210877b9c0c1ed62ff4" have entirely different histories.

10 changed files with 153 additions and 316 deletions

View File

@ -7,9 +7,9 @@ import (
"net/url" "net/url"
"os" "os"
"github.com/pstuifzand/ekster/microsub"
"github.com/pstuifzand/ekster/pkg/client" "github.com/pstuifzand/ekster/pkg/client"
"github.com/pstuifzand/ekster/pkg/indieauth" "github.com/pstuifzand/ekster/pkg/indieauth"
"github.com/pstuifzand/ekster/pkg/microsub"
) )
func init() { func init() {
@ -173,11 +173,7 @@ Commands:
} }
if len(commands) == 1 && commands[0] == "channels" { if len(commands) == 1 && commands[0] == "channels" {
channels, err := sub.ChannelsGetList() channels := sub.ChannelsGetList()
if err != nil {
log.Fatalf("An error occurred: %s\n", err)
}
for _, ch := range channels { for _, ch := range channels {
fmt.Printf("%-20s %s\n", ch.UID, ch.Name) fmt.Printf("%-20s %s\n", ch.UID, ch.Name)
} }
@ -185,10 +181,7 @@ Commands:
if len(commands) == 2 && commands[0] == "channels" { if len(commands) == 2 && commands[0] == "channels" {
name := commands[1] name := commands[1]
channel, err := sub.ChannelsCreate(name) channel := sub.ChannelsCreate(name)
if err != nil {
log.Fatalf("An error occurred: %s\n", err)
}
fmt.Printf("%s\n", channel.UID) fmt.Printf("%s\n", channel.UID)
} }
@ -196,17 +189,11 @@ Commands:
uid := commands[1] uid := commands[1]
if uid == "-delete" { if uid == "-delete" {
uid = commands[2] uid = commands[2]
err := sub.ChannelsDelete(uid) sub.ChannelsDelete(uid)
if err != nil {
log.Fatalf("An error occurred: %s\n", err)
}
fmt.Printf("Channel %s deleted\n", uid) fmt.Printf("Channel %s deleted\n", uid)
} else { } else {
name := commands[2] name := commands[2]
channel, err := sub.ChannelsUpdate(uid, name) channel := sub.ChannelsUpdate(uid, name)
if err != nil {
log.Fatalf("An error occurred: %s\n", err)
}
fmt.Printf("Channel updated %s %s\n", channel.Name, channel.UID) fmt.Printf("Channel updated %s %s\n", channel.Name, channel.UID)
} }
} }
@ -215,18 +202,13 @@ Commands:
channel := commands[1] channel := commands[1]
var timeline microsub.Timeline var timeline microsub.Timeline
var err error
if len(commands) == 4 && commands[2] == "-after" { if len(commands) == 4 && commands[2] == "-after" {
timeline, err = sub.TimelineGet("", commands[3], channel) timeline = sub.TimelineGet("", commands[3], channel)
} else if len(commands) == 4 && commands[2] == "-before" { } else if len(commands) == 4 && commands[2] == "-before" {
timeline, err = sub.TimelineGet(commands[3], "", channel) timeline = sub.TimelineGet(commands[3], "", channel)
} else { } else {
timeline, err = sub.TimelineGet("", "", channel) timeline = sub.TimelineGet("", "", channel)
}
if err != nil {
log.Fatalf("An error occurred: %s\n", err)
} }
for _, item := range timeline.Items { for _, item := range timeline.Items {
@ -238,10 +220,7 @@ Commands:
if len(commands) == 2 && commands[0] == "search" { if len(commands) == 2 && commands[0] == "search" {
query := commands[1] query := commands[1]
feeds, err := sub.Search(query) feeds := sub.Search(query)
if err != nil {
log.Fatalf("An error occurred: %s\n", err)
}
for _, feed := range feeds { for _, feed := range feeds {
fmt.Println(feed.Name, " ", feed.URL) fmt.Println(feed.Name, " ", feed.URL)
@ -250,11 +229,8 @@ Commands:
if len(commands) == 2 && commands[0] == "preview" { if len(commands) == 2 && commands[0] == "preview" {
url := commands[1] url := commands[1]
timeline, err := sub.PreviewURL(url) timeline := sub.PreviewURL(url)
if err != nil {
log.Fatalf("An error occurred: %s\n", err)
}
for _, item := range timeline.Items { for _, item := range timeline.Items {
showItem(&item) showItem(&item)
} }
@ -262,10 +238,7 @@ Commands:
if len(commands) == 2 && commands[0] == "follow" { if len(commands) == 2 && commands[0] == "follow" {
uid := commands[1] uid := commands[1]
feeds, err := sub.FollowGetList(uid) feeds := sub.FollowGetList(uid)
if err != nil {
log.Fatalf("An error occurred: %s\n", err)
}
for _, feed := range feeds { for _, feed := range feeds {
fmt.Println(feed.Name, " ", feed.URL) fmt.Println(feed.Name, " ", feed.URL)
} }
@ -274,20 +247,13 @@ Commands:
if len(commands) == 3 && commands[0] == "follow" { if len(commands) == 3 && commands[0] == "follow" {
uid := commands[1] uid := commands[1]
url := commands[2] url := commands[2]
_, err := sub.FollowURL(uid, url) sub.FollowURL(uid, url)
if err != nil {
log.Fatalf("An error occurred: %s\n", err)
}
// NOTE(peter): should we show the returned feed here?
} }
if len(commands) == 3 && commands[0] == "unfollow" { if len(commands) == 3 && commands[0] == "unfollow" {
uid := commands[1] uid := commands[1]
url := commands[2] url := commands[2]
err := sub.UnfollowURL(uid, url) sub.UnfollowURL(uid, url)
if err != nil {
log.Fatalf("An error occurred: %s\n", err)
}
} }
} }

View File

@ -34,7 +34,7 @@ import (
"time" "time"
"github.com/garyburd/redigo/redis" "github.com/garyburd/redigo/redis"
"github.com/pstuifzand/ekster/pkg/microsub" "github.com/pstuifzand/ekster/microsub"
"willnorris.com/go/microformats" "willnorris.com/go/microformats"
) )

View File

@ -28,7 +28,7 @@ import (
"time" "time"
"github.com/garyburd/redigo/redis" "github.com/garyburd/redigo/redis"
"github.com/pstuifzand/ekster/pkg/microsub" "github.com/pstuifzand/ekster/microsub"
"github.com/pstuifzand/ekster/pkg/util" "github.com/pstuifzand/ekster/pkg/util"
"github.com/pstuifzand/ekster/pkg/websub" "github.com/pstuifzand/ekster/pkg/websub"
) )

View File

@ -29,8 +29,8 @@ import (
"time" "time"
"github.com/garyburd/redigo/redis" "github.com/garyburd/redigo/redis"
"github.com/pstuifzand/ekster/microsub"
"github.com/pstuifzand/ekster/pkg/feedbin" "github.com/pstuifzand/ekster/pkg/feedbin"
"github.com/pstuifzand/ekster/pkg/microsub"
"willnorris.com/go/microformats" "willnorris.com/go/microformats"
) )
@ -138,7 +138,7 @@ func createMemoryBackend() microsub.Microsub {
} }
// ChannelsGetList gets channels // ChannelsGetList gets channels
func (b *memoryBackend) ChannelsGetList() ([]microsub.Channel, error) { func (b *memoryBackend) ChannelsGetList() []microsub.Channel {
conn := pool.Get() conn := pool.Get()
defer conn.Close() defer conn.Close()
@ -156,11 +156,11 @@ func (b *memoryBackend) ChannelsGetList() ([]microsub.Channel, error) {
} }
} }
} }
return channels, nil return channels
} }
// ChannelsCreate creates a channels // ChannelsCreate creates a channels
func (b *memoryBackend) ChannelsCreate(name string) (microsub.Channel, error) { func (b *memoryBackend) ChannelsCreate(name string) microsub.Channel {
defer b.save() defer b.save()
conn := pool.Get() conn := pool.Get()
@ -178,23 +178,22 @@ func (b *memoryBackend) ChannelsCreate(name string) (microsub.Channel, error) {
conn.Do("SADD", "channels", uid) conn.Do("SADD", "channels", uid)
conn.Do("SETNX", "channel_sortorder_"+uid, 99999) conn.Do("SETNX", "channel_sortorder_"+uid, 99999)
return channel
return channel, nil
} }
// ChannelsUpdate updates a channels // ChannelsUpdate updates a channels
func (b *memoryBackend) ChannelsUpdate(uid, name string) (microsub.Channel, error) { func (b *memoryBackend) ChannelsUpdate(uid, name string) microsub.Channel {
defer b.save() defer b.save()
if c, e := b.Channels[uid]; e { if c, e := b.Channels[uid]; e {
c.Name = name c.Name = name
b.Channels[uid] = c b.Channels[uid] = c
return c, nil return c
} }
return microsub.Channel{}, fmt.Errorf("Channel %s does not exist", uid) return microsub.Channel{}
} }
// ChannelsDelete deletes a channel // ChannelsDelete deletes a channel
func (b *memoryBackend) ChannelsDelete(uid string) error { func (b *memoryBackend) ChannelsDelete(uid string) {
defer b.save() defer b.save()
conn := pool.Get() conn := pool.Get()
@ -205,8 +204,6 @@ func (b *memoryBackend) ChannelsDelete(uid string) error {
delete(b.Channels, uid) delete(b.Channels, uid)
delete(b.Feeds, uid) delete(b.Feeds, uid)
return nil
} }
func mapToAuthor(result map[string]string) *microsub.Card { func mapToAuthor(result map[string]string) *microsub.Card {
@ -394,7 +391,7 @@ func (b *memoryBackend) run() {
}() }()
} }
func (b *memoryBackend) TimelineGet(before, after, channel string) (microsub.Timeline, error) { func (b *memoryBackend) TimelineGet(before, after, channel string) microsub.Timeline {
conn := pool.Get() conn := pool.Get()
defer conn.Close() defer conn.Close()
@ -433,14 +430,11 @@ func (b *memoryBackend) TimelineGet(before, after, channel string) (microsub.Tim
return microsub.Timeline{ return microsub.Timeline{
Paging: microsub.Pagination{}, Paging: microsub.Pagination{},
Items: items, Items: items,
}, nil }
} }
log.Printf("TimelineGet %s\n", channel) log.Printf("TimelineGet %s\n", channel)
feeds, err := b.FollowGetList(channel) feeds := b.FollowGetList(channel)
if err != nil {
return microsub.Timeline{}, err
}
log.Println(feeds) log.Println(feeds)
items := []microsub.Item{} items := []microsub.Item{}
@ -482,10 +476,11 @@ func (b *memoryBackend) TimelineGet(before, after, channel string) (microsub.Tim
) )
if err != nil { if err != nil {
log.Println(err)
return microsub.Timeline{ return microsub.Timeline{
Paging: microsub.Pagination{}, Paging: microsub.Pagination{},
Items: items, Items: items,
}, err }
} }
if len(itemScores) >= 2 { if len(itemScores) >= 2 {
@ -507,7 +502,6 @@ func (b *memoryBackend) TimelineGet(before, after, channel string) (microsub.Tim
item := microsub.Item{} item := microsub.Item{}
err := json.Unmarshal(obj, &item) err := json.Unmarshal(obj, &item)
if err != nil { if err != nil {
// FIXME: what should we do if one of the items doen't unmarshal?
log.Println(err) log.Println(err)
continue continue
} }
@ -522,7 +516,7 @@ func (b *memoryBackend) TimelineGet(before, after, channel string) (microsub.Tim
return microsub.Timeline{ return microsub.Timeline{
Paging: paging, Paging: paging,
Items: items, Items: items,
}, nil }
} }
//panic if s is not a slice //panic if s is not a slice
@ -559,17 +553,17 @@ func reverseSlice(s interface{}) {
// return false // return false
// } // }
func (b *memoryBackend) FollowGetList(uid string) ([]microsub.Feed, error) { func (b *memoryBackend) FollowGetList(uid string) []microsub.Feed {
return b.Feeds[uid], nil return b.Feeds[uid]
} }
func (b *memoryBackend) FollowURL(uid string, url string) (microsub.Feed, error) { func (b *memoryBackend) FollowURL(uid string, url string) microsub.Feed {
defer b.save() defer b.save()
feed := microsub.Feed{Type: "feed", URL: url} feed := microsub.Feed{Type: "feed", URL: url}
resp, err := b.Fetch3(uid, feed.URL) resp, err := b.Fetch3(uid, feed.URL)
if err != nil { if err != nil {
return feed, err return feed
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -577,10 +571,10 @@ func (b *memoryBackend) FollowURL(uid string, url string) (microsub.Feed, error)
b.ProcessContent(uid, feed.URL, resp.Header.Get("Content-Type"), resp.Body) b.ProcessContent(uid, feed.URL, resp.Header.Get("Content-Type"), resp.Body)
return feed, nil return feed
} }
func (b *memoryBackend) UnfollowURL(uid string, url string) error { func (b *memoryBackend) UnfollowURL(uid string, url string) {
defer b.save() defer b.save()
index := -1 index := -1
for i, f := range b.Feeds[uid] { for i, f := range b.Feeds[uid] {
@ -593,8 +587,6 @@ func (b *memoryBackend) UnfollowURL(uid string, url string) error {
feeds := b.Feeds[uid] feeds := b.Feeds[uid]
b.Feeds[uid] = append(feeds[:index], feeds[index+1:]...) b.Feeds[uid] = append(feeds[:index], feeds[index+1:]...)
} }
return nil
} }
func checkURL(u string) bool { func checkURL(u string) bool {
@ -633,7 +625,7 @@ func getPossibleURLs(query string) []string {
return urls return urls
} }
func (b *memoryBackend) Search(query string) ([]microsub.Feed, error) { func (b *memoryBackend) Search(query string) []microsub.Feed {
urls := getPossibleURLs(query) urls := getPossibleURLs(query)
feeds := []microsub.Feed{} feeds := []microsub.Feed{}
@ -692,25 +684,27 @@ func (b *memoryBackend) Search(query string) ([]microsub.Feed, error) {
} }
} }
return feeds, nil return feeds
} }
func (b *memoryBackend) PreviewURL(previewURL string) (microsub.Timeline, error) { func (b *memoryBackend) PreviewURL(previewURL string) microsub.Timeline {
resp, err := Fetch2(previewURL) resp, err := Fetch2(previewURL)
if err != nil { if err != nil {
return microsub.Timeline{}, fmt.Errorf("error while fetching %s: %v", previewURL, err) log.Printf("Error while fetching %s: %v\n", previewURL, err)
return microsub.Timeline{}
} }
items, err := b.feedItems(previewURL, resp.Header.Get("content-type"), resp.Body) items, err := b.feedItems(previewURL, resp.Header.Get("content-type"), resp.Body)
if err != nil { if err != nil {
return microsub.Timeline{}, fmt.Errorf("error while fetching %s: %v", previewURL, err) log.Printf("Error while fetching %s: %v\n", previewURL, err)
return microsub.Timeline{}
} }
return microsub.Timeline{ return microsub.Timeline{
Items: items, Items: items,
}, nil }
} }
func (b *memoryBackend) MarkRead(channel string, uids []string) error { func (b *memoryBackend) MarkRead(channel string, uids []string) {
conn := pool.Get() conn := pool.Get()
defer conn.Close() defer conn.Close()
@ -726,7 +720,6 @@ func (b *memoryBackend) MarkRead(channel string, uids []string) error {
if _, err := conn.Do("SADD", args...); err != nil { if _, err := conn.Do("SADD", args...); err != nil {
log.Printf("Marking read for channel %s has failed\n", channel) log.Printf("Marking read for channel %s has failed\n", channel)
return err
} }
zchannelKey := fmt.Sprintf("zchannel:%s:posts", channel) zchannelKey := fmt.Sprintf("zchannel:%s:posts", channel)
@ -734,7 +727,6 @@ func (b *memoryBackend) MarkRead(channel string, uids []string) error {
if _, err := conn.Do("ZREM", args...); err != nil { if _, err := conn.Do("ZREM", args...); err != nil {
log.Printf("Marking read for channel %s has failed\n", channel) log.Printf("Marking read for channel %s has failed\n", channel)
return err
} }
unread, _ := redis.Int(conn.Do("ZCARD", zchannelKey)) unread, _ := redis.Int(conn.Do("ZCARD", zchannelKey))
@ -749,6 +741,4 @@ func (b *memoryBackend) MarkRead(channel string, uids []string) error {
} }
log.Printf("Marking read success for %s %v\n", channel, itemUIDs) log.Printf("Marking read success for %s %v\n", channel, itemUIDs)
return nil
} }

View File

@ -9,7 +9,7 @@ import (
"strings" "strings"
"github.com/garyburd/redigo/redis" "github.com/garyburd/redigo/redis"
"github.com/pstuifzand/ekster/pkg/microsub" "github.com/pstuifzand/ekster/microsub"
"willnorris.com/go/microformats" "willnorris.com/go/microformats"
) )

View File

@ -8,7 +8,7 @@ import (
"os" "os"
"github.com/garyburd/redigo/redis" "github.com/garyburd/redigo/redis"
"github.com/pstuifzand/ekster/pkg/microsub" "github.com/pstuifzand/ekster/microsub"
) )
type microsubHandler struct { type microsubHandler struct {
@ -49,67 +49,34 @@ func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
values := r.URL.Query() values := r.URL.Query()
action := values.Get("action") action := values.Get("action")
if action == "channels" { if action == "channels" {
channels, err := h.Backend.ChannelsGetList() channels := h.Backend.ChannelsGetList()
if err != nil {
http.Error(w, err.Error(), 500)
return
}
jw := json.NewEncoder(w) jw := json.NewEncoder(w)
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
err = jw.Encode(map[string][]microsub.Channel{ jw.Encode(map[string][]microsub.Channel{
"channels": channels, "channels": channels,
}) })
if err != nil {
http.Error(w, err.Error(), 500)
return
}
} else if action == "timeline" { } else if action == "timeline" {
timeline, err := h.Backend.TimelineGet(values.Get("before"), values.Get("after"), values.Get("channel")) timeline := h.Backend.TimelineGet(values.Get("before"), values.Get("after"), values.Get("channel"))
if err != nil {
http.Error(w, err.Error(), 500)
return
}
jw := json.NewEncoder(w) jw := json.NewEncoder(w)
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
jw.SetIndent("", " ") jw.SetIndent("", " ")
err = jw.Encode(timeline) jw.Encode(timeline)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
} else if action == "preview" { } else if action == "preview" {
timeline, err := h.Backend.PreviewURL(values.Get("url")) timeline := h.Backend.PreviewURL(values.Get("url"))
if err != nil {
http.Error(w, err.Error(), 500)
return
}
jw := json.NewEncoder(w) jw := json.NewEncoder(w)
jw.SetIndent("", " ") jw.SetIndent("", " ")
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
err = jw.Encode(timeline) jw.Encode(timeline)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
} else if action == "follow" { } else if action == "follow" {
channel := values.Get("channel") channel := values.Get("channel")
following, err := h.Backend.FollowGetList(channel) following := h.Backend.FollowGetList(channel)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
jw := json.NewEncoder(w) jw := json.NewEncoder(w)
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
err = jw.Encode(map[string][]microsub.Feed{ jw.Encode(map[string][]microsub.Feed{
"items": following, "items": following,
}) })
if err != nil {
http.Error(w, err.Error(), 500)
return
}
} else { } else {
http.Error(w, fmt.Sprintf("unknown action %s\n", action), 500) log.Printf("unknown action %s\n", action)
return
} }
return return
} else if r.Method == http.MethodPost { } else if r.Method == http.MethodPost {
@ -120,11 +87,7 @@ func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
method := values.Get("method") method := values.Get("method")
uid := values.Get("channel") uid := values.Get("channel")
if method == "delete" { if method == "delete" {
err := h.Backend.ChannelsDelete(uid) h.Backend.ChannelsDelete(uid)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
fmt.Fprintln(w, "[]") fmt.Fprintln(w, "[]")
h.Backend.(Debug).Debug() h.Backend.(Debug).Debug()
@ -133,73 +96,37 @@ func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
jw := json.NewEncoder(w) jw := json.NewEncoder(w)
if uid == "" { if uid == "" {
channel, err := h.Backend.ChannelsCreate(name) channel := h.Backend.ChannelsCreate(name)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
err = jw.Encode(channel) jw.Encode(channel)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
} else { } else {
channel, err := h.Backend.ChannelsUpdate(uid, name) channel := h.Backend.ChannelsUpdate(uid, name)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
err = jw.Encode(channel) jw.Encode(channel)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
} }
h.Backend.(Debug).Debug() h.Backend.(Debug).Debug()
} else if action == "follow" { } else if action == "follow" {
uid := values.Get("channel") uid := values.Get("channel")
url := values.Get("url") url := values.Get("url")
h.HubIncomingBackend.CreateFeed(url, uid) h.HubIncomingBackend.CreateFeed(url, uid)
feed, err := h.Backend.FollowURL(uid, url) feed := h.Backend.FollowURL(uid, url)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
jw := json.NewEncoder(w) jw := json.NewEncoder(w)
err = jw.Encode(feed) jw.Encode(feed)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
} else if action == "unfollow" { } else if action == "unfollow" {
uid := values.Get("channel") uid := values.Get("channel")
url := values.Get("url") url := values.Get("url")
err := h.Backend.UnfollowURL(uid, url) h.Backend.UnfollowURL(uid, url)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
fmt.Fprintln(w, "[]") fmt.Fprintln(w, "[]")
} else if action == "search" { } else if action == "search" {
query := values.Get("query") query := values.Get("query")
feeds, err := h.Backend.Search(query) feeds := h.Backend.Search(query)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
jw := json.NewEncoder(w) jw := json.NewEncoder(w)
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
err = jw.Encode(map[string][]microsub.Feed{ jw.Encode(map[string][]microsub.Feed{
"results": feeds, "results": feeds,
}) })
if err != nil {
http.Error(w, err.Error(), 500)
return
}
} else if action == "timeline" || r.PostForm.Get("action") == "timeline" { } else if action == "timeline" || r.PostForm.Get("action") == "timeline" {
method := values.Get("method") method := values.Get("method")
@ -207,17 +134,9 @@ func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
values = r.Form values = r.Form
channel := values.Get("channel") channel := values.Get("channel")
if uids, e := values["entry"]; e { if uids, e := values["entry"]; e {
err := h.Backend.MarkRead(channel, uids) h.Backend.MarkRead(channel, uids)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
} else if uids, e := values["entry[]"]; e { } else if uids, e := values["entry[]"]; e {
err := h.Backend.MarkRead(channel, uids) h.Backend.MarkRead(channel, uids)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
} else { } else {
uids := []string{} uids := []string{}
for k, v := range values { for k, v := range values {
@ -225,20 +144,15 @@ func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
uids = append(uids, v...) uids = append(uids, v...)
} }
} }
err := h.Backend.MarkRead(channel, uids) h.Backend.MarkRead(channel, uids)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
} }
} else { } else {
http.Error(w, fmt.Sprintf("unknown method in timeline %s\n", method), 500) log.Printf("unknown method in timeline %s\n", method)
return
} }
w.Header().Add("Content-Type", "application/json") w.Header().Add("Content-Type", "application/json")
fmt.Fprintln(w, "[]") fmt.Fprintln(w, "[]")
} else { } else {
http.Error(w, fmt.Sprintf("unknown action %s\n", action), 500) log.Printf("unknown action %s\n", action)
} }
return return

View File

@ -18,7 +18,7 @@
package main package main
import ( import (
"github.com/pstuifzand/ekster/pkg/microsub" "github.com/pstuifzand/ekster/microsub"
) )
// NullBackend is the simplest possible backend // NullBackend is the simplest possible backend
@ -26,67 +26,64 @@ type NullBackend struct {
} }
// ChannelsGetList gets no channels // ChannelsGetList gets no channels
func (b *NullBackend) ChannelsGetList() ([]microsub.Channel, error) { func (b *NullBackend) ChannelsGetList() []microsub.Channel {
return []microsub.Channel{ return []microsub.Channel{
microsub.Channel{UID: "0000", Name: "default", Unread: 0}, microsub.Channel{UID: "0000", Name: "default", Unread: 0},
microsub.Channel{UID: "0001", Name: "notifications", Unread: 0}, microsub.Channel{UID: "0001", Name: "notifications", Unread: 0},
microsub.Channel{UID: "1000", Name: "Friends", Unread: 0}, microsub.Channel{UID: "1000", Name: "Friends", Unread: 0},
microsub.Channel{UID: "1001", Name: "Family", Unread: 0}, microsub.Channel{UID: "1001", Name: "Family", Unread: 0},
}, nil }
} }
// ChannelsCreate creates no channels // ChannelsCreate creates no channels
func (b *NullBackend) ChannelsCreate(name string) (microsub.Channel, error) { func (b *NullBackend) ChannelsCreate(name string) microsub.Channel {
return microsub.Channel{ return microsub.Channel{
UID: "1234", UID: "1234",
Name: name, Name: name,
}, nil }
} }
// ChannelsUpdate updates no channels // ChannelsUpdate updates no channels
func (b *NullBackend) ChannelsUpdate(uid, name string) (microsub.Channel, error) { func (b *NullBackend) ChannelsUpdate(uid, name string) microsub.Channel {
return microsub.Channel{ return microsub.Channel{
UID: uid, UID: uid,
Name: name, Name: name,
}, nil }
} }
// ChannelsDelete delets no channels // ChannelsDelete delets no channels
func (b *NullBackend) ChannelsDelete(uid string) error { func (b *NullBackend) ChannelsDelete(uid string) {
return nil
} }
// TimelineGet gets no timeline // TimelineGet gets no timeline
func (b *NullBackend) TimelineGet(before, after, channel string) (microsub.Timeline, error) { func (b *NullBackend) TimelineGet(before, after, channel string) microsub.Timeline {
return microsub.Timeline{ return microsub.Timeline{
Paging: microsub.Pagination{}, Paging: microsub.Pagination{},
Items: []microsub.Item{}, Items: []microsub.Item{},
}, nil }
} }
func (b *NullBackend) FollowGetList(uid string) ([]microsub.Feed, error) { func (b *NullBackend) FollowGetList(uid string) []microsub.Feed {
return []microsub.Feed{}, nil return []microsub.Feed{}
} }
func (b *NullBackend) FollowURL(uid string, url string) (microsub.Feed, error) { func (b *NullBackend) FollowURL(uid string, url string) microsub.Feed {
return microsub.Feed{Type: "feed", URL: url}, nil return microsub.Feed{Type: "feed", URL: url}
} }
func (b *NullBackend) UnfollowURL(uid string, url string) error { func (b *NullBackend) UnfollowURL(uid string, url string) {
return nil
} }
func (b *NullBackend) Search(query string) ([]microsub.Feed, error) { func (b *NullBackend) Search(query string) []microsub.Feed {
return []microsub.Feed{}, nil return []microsub.Feed{}
} }
func (b *NullBackend) PreviewURL(url string) (microsub.Timeline, error) { func (b *NullBackend) PreviewURL(url string) microsub.Timeline {
return microsub.Timeline{ return microsub.Timeline{
Paging: microsub.Pagination{}, Paging: microsub.Pagination{},
Items: []microsub.Item{}, Items: []microsub.Item{},
}, nil }
} }
func (b *NullBackend) MarkRead(channel string, uids []string) error { func (b *NullBackend) MarkRead(channel string, uids []string) {
return nil
} }

View File

@ -102,20 +102,20 @@ type Feed struct {
// Microsub is the main protocol that should be implemented by a backend // Microsub is the main protocol that should be implemented by a backend
type Microsub interface { type Microsub interface {
ChannelsGetList() ([]Channel, error) ChannelsGetList() []Channel
ChannelsCreate(name string) (Channel, error) ChannelsCreate(name string) Channel
ChannelsUpdate(uid, name string) (Channel, error) ChannelsUpdate(uid, name string) Channel
ChannelsDelete(uid string) error ChannelsDelete(uid string)
TimelineGet(before, after, channel string) (Timeline, error) TimelineGet(before, after, channel string) Timeline
MarkRead(channel string, entry []string) error MarkRead(channel string, entry []string)
FollowGetList(uid string) ([]Feed, error) FollowGetList(uid string) []Feed
FollowURL(uid string, url string) (Feed, error) FollowURL(uid string, url string) Feed
UnfollowURL(uid string, url string) error UnfollowURL(uid string, url string)
Search(query string) ([]Feed, error) Search(query string) []Feed
PreviewURL(url string) (Timeline, error) PreviewURL(url string) Timeline
} }

View File

@ -3,11 +3,12 @@ package client
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"log"
"net/http" "net/http"
"net/url" "net/url"
"strings" "strings"
"github.com/pstuifzand/ekster/pkg/microsub" "github.com/pstuifzand/ekster/microsub"
) )
type Client struct { type Client struct {
@ -79,11 +80,12 @@ func (c *Client) microsubPostFormRequest(action string, args map[string]string,
return client.Do(req) return client.Do(req)
} }
func (c *Client) ChannelsGetList() ([]microsub.Channel, error) { func (c *Client) ChannelsGetList() []microsub.Channel {
args := make(map[string]string) args := make(map[string]string)
res, err := c.microsubGetRequest("channels", args) res, err := c.microsubGetRequest("channels", args)
if err != nil { if err != nil {
return []microsub.Channel{}, err log.Println(err)
return []microsub.Channel{}
} }
defer res.Body.Close() defer res.Body.Close()
@ -93,56 +95,52 @@ func (c *Client) ChannelsGetList() ([]microsub.Channel, error) {
dec := json.NewDecoder(res.Body) dec := json.NewDecoder(res.Body)
var channels channelsResponse var channels channelsResponse
err = dec.Decode(&channels) dec.Decode(&channels)
if err != nil { return channels.Channels
return channels.Channels, err
} }
return channels.Channels, nil func (c *Client) TimelineGet(before, after, channel string) microsub.Timeline {
}
func (c *Client) TimelineGet(before, after, channel string) (microsub.Timeline, error) {
args := make(map[string]string) args := make(map[string]string)
args["after"] = after args["after"] = after
args["before"] = before args["before"] = before
args["channel"] = channel args["channel"] = channel
res, err := c.microsubGetRequest("timeline", args) res, err := c.microsubGetRequest("timeline", args)
if err != nil { if err != nil {
return microsub.Timeline{}, err log.Println(err)
return microsub.Timeline{}
} }
defer res.Body.Close() defer res.Body.Close()
dec := json.NewDecoder(res.Body) dec := json.NewDecoder(res.Body)
var timeline microsub.Timeline var timeline microsub.Timeline
err = dec.Decode(&timeline) err = dec.Decode(&timeline)
if err != nil { if err != nil {
return microsub.Timeline{}, err log.Fatal(err)
} }
return timeline, nil return timeline
} }
func (c *Client) PreviewURL(url string) (microsub.Timeline, error) { func (c *Client) PreviewURL(url string) microsub.Timeline {
args := make(map[string]string) args := make(map[string]string)
args["url"] = url args["url"] = url
res, err := c.microsubGetRequest("preview", args) res, err := c.microsubGetRequest("preview", args)
if err != nil { if err != nil {
return microsub.Timeline{}, err log.Println(err)
return microsub.Timeline{}
} }
defer res.Body.Close() defer res.Body.Close()
dec := json.NewDecoder(res.Body) dec := json.NewDecoder(res.Body)
var timeline microsub.Timeline var timeline microsub.Timeline
err = dec.Decode(&timeline) dec.Decode(&timeline)
if err != nil { return timeline
return microsub.Timeline{}, err
}
return timeline, nil
} }
func (c *Client) FollowGetList(channel string) ([]microsub.Feed, error) { func (c *Client) FollowGetList(channel string) []microsub.Feed {
args := make(map[string]string) args := make(map[string]string)
args["channel"] = channel args["channel"] = channel
res, err := c.microsubGetRequest("follow", args) res, err := c.microsubGetRequest("follow", args)
if err != nil { if err != nil {
return []microsub.Feed{}, nil log.Println(err)
return []microsub.Feed{}
} }
defer res.Body.Close() defer res.Body.Close()
dec := json.NewDecoder(res.Body) dec := json.NewDecoder(res.Body)
@ -150,96 +148,88 @@ func (c *Client) FollowGetList(channel string) ([]microsub.Feed, error) {
Items []microsub.Feed `json:"items"` Items []microsub.Feed `json:"items"`
} }
var response followResponse var response followResponse
err = dec.Decode(&response) dec.Decode(&response)
if err != nil { return response.Items
return []microsub.Feed{}, nil
}
return response.Items, nil
} }
func (c *Client) ChannelsCreate(name string) (microsub.Channel, error) { func (c *Client) ChannelsCreate(name string) microsub.Channel {
args := make(map[string]string) args := make(map[string]string)
args["name"] = name args["name"] = name
res, err := c.microsubPostRequest("channels", args) res, err := c.microsubPostRequest("channels", args)
if err != nil { if err != nil {
return microsub.Channel{}, nil log.Println(err)
return microsub.Channel{}
} }
defer res.Body.Close() defer res.Body.Close()
var channel microsub.Channel var channel microsub.Channel
dec := json.NewDecoder(res.Body) dec := json.NewDecoder(res.Body)
err = dec.Decode(&channel) dec.Decode(&channel)
if err != nil { return channel
return microsub.Channel{}, nil
}
return channel, nil
} }
func (c *Client) ChannelsUpdate(uid, name string) (microsub.Channel, error) { func (c *Client) ChannelsUpdate(uid, name string) microsub.Channel {
args := make(map[string]string) args := make(map[string]string)
args["name"] = name args["name"] = name
args["uid"] = uid args["uid"] = uid
res, err := c.microsubPostRequest("channels", args) res, err := c.microsubPostRequest("channels", args)
if err != nil { if err != nil {
return microsub.Channel{}, err log.Println(err)
return microsub.Channel{}
} }
defer res.Body.Close() defer res.Body.Close()
var channel microsub.Channel var channel microsub.Channel
dec := json.NewDecoder(res.Body) dec := json.NewDecoder(res.Body)
err = dec.Decode(&channel) dec.Decode(&channel)
if err != nil { return channel
return microsub.Channel{}, err
}
return channel, nil
} }
func (c *Client) ChannelsDelete(uid string) error { func (c *Client) ChannelsDelete(uid string) {
args := make(map[string]string) args := make(map[string]string)
args["channel"] = uid args["channel"] = uid
args["method"] = "delete" args["method"] = "delete"
res, err := c.microsubPostRequest("channels", args) res, err := c.microsubPostRequest("channels", args)
if err != nil { if err != nil {
return err log.Println(err)
return
} }
res.Body.Close() res.Body.Close()
return nil
} }
func (c *Client) FollowURL(channel, url string) (microsub.Feed, error) { func (c *Client) FollowURL(channel, url string) microsub.Feed {
args := make(map[string]string) args := make(map[string]string)
args["channel"] = channel args["channel"] = channel
args["url"] = url args["url"] = url
res, err := c.microsubPostRequest("follow", args) res, err := c.microsubPostRequest("follow", args)
if err != nil { if err != nil {
return microsub.Feed{}, err log.Println(err)
return microsub.Feed{}
} }
defer res.Body.Close() defer res.Body.Close()
var feed microsub.Feed var feed microsub.Feed
dec := json.NewDecoder(res.Body) dec := json.NewDecoder(res.Body)
err = dec.Decode(&feed) dec.Decode(&feed)
if err != nil { return feed
return microsub.Feed{}, err
}
return feed, nil
} }
func (c *Client) UnfollowURL(channel, url string) error { func (c *Client) UnfollowURL(channel, url string) {
args := make(map[string]string) args := make(map[string]string)
args["channel"] = channel args["channel"] = channel
args["url"] = url args["url"] = url
res, err := c.microsubPostRequest("unfollow", args) res, err := c.microsubPostRequest("unfollow", args)
if err != nil { if err != nil {
return err log.Println(err)
return
} }
res.Body.Close() res.Body.Close()
return nil
} }
func (c *Client) Search(query string) ([]microsub.Feed, error) { func (c *Client) Search(query string) []microsub.Feed {
args := make(map[string]string) args := make(map[string]string)
args["query"] = query args["query"] = query
res, err := c.microsubPostRequest("search", args) res, err := c.microsubPostRequest("search", args)
if err != nil { if err != nil {
return []microsub.Feed{}, err log.Println(err)
return []microsub.Feed{}
} }
type searchResponse struct { type searchResponse struct {
Results []microsub.Feed `json:"results"` Results []microsub.Feed `json:"results"`
@ -247,14 +237,11 @@ func (c *Client) Search(query string) ([]microsub.Feed, error) {
defer res.Body.Close() defer res.Body.Close()
var response searchResponse var response searchResponse
dec := json.NewDecoder(res.Body) dec := json.NewDecoder(res.Body)
err = dec.Decode(&response) dec.Decode(&response)
if err != nil { return response.Results
return []microsub.Feed{}, err
}
return response.Results, nil
} }
func (c *Client) MarkRead(channel string, uids []string) error { func (c *Client) MarkRead(channel string, uids []string) {
args := make(map[string]string) args := make(map[string]string)
args["channel"] = channel args["channel"] = channel
@ -264,9 +251,7 @@ func (c *Client) MarkRead(channel string, uids []string) error {
} }
res, err := c.microsubPostFormRequest("mark_read", args, data) res, err := c.microsubPostFormRequest("mark_read", args, data)
if err != nil { if err == nil {
return err defer res.Body.Close()
} }
res.Body.Close()
return nil
} }

View File

@ -1,15 +0,0 @@
package microsub
import (
"encoding/json"
"fmt"
"testing"
"github.com/pstuifzand/ekster/microsub"
)
func TestJson(t *testing.T) {
item := microsub.Item{Type: "entry"}
result, err := json.Marshal(item)
fmt.Println(string(result), err)
}