Compare commits
2 Commits
6d3eaa020d
...
6677bd95ab
Author | SHA1 | Date | |
---|---|---|---|
6677bd95ab | |||
bf645f33ef |
|
@ -7,9 +7,9 @@ import (
|
|||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/pstuifzand/ekster/microsub"
|
||||
"github.com/pstuifzand/ekster/pkg/client"
|
||||
"github.com/pstuifzand/ekster/pkg/indieauth"
|
||||
"github.com/pstuifzand/ekster/pkg/microsub"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -173,7 +173,11 @@ Commands:
|
|||
}
|
||||
|
||||
if len(commands) == 1 && commands[0] == "channels" {
|
||||
channels := sub.ChannelsGetList()
|
||||
channels, err := sub.ChannelsGetList()
|
||||
if err != nil {
|
||||
log.Fatalf("An error occurred: %s\n", err)
|
||||
}
|
||||
|
||||
for _, ch := range channels {
|
||||
fmt.Printf("%-20s %s\n", ch.UID, ch.Name)
|
||||
}
|
||||
|
@ -181,7 +185,10 @@ Commands:
|
|||
|
||||
if len(commands) == 2 && commands[0] == "channels" {
|
||||
name := commands[1]
|
||||
channel := sub.ChannelsCreate(name)
|
||||
channel, err := sub.ChannelsCreate(name)
|
||||
if err != nil {
|
||||
log.Fatalf("An error occurred: %s\n", err)
|
||||
}
|
||||
fmt.Printf("%s\n", channel.UID)
|
||||
}
|
||||
|
||||
|
@ -189,11 +196,17 @@ Commands:
|
|||
uid := commands[1]
|
||||
if uid == "-delete" {
|
||||
uid = commands[2]
|
||||
sub.ChannelsDelete(uid)
|
||||
err := sub.ChannelsDelete(uid)
|
||||
if err != nil {
|
||||
log.Fatalf("An error occurred: %s\n", err)
|
||||
}
|
||||
fmt.Printf("Channel %s deleted\n", uid)
|
||||
} else {
|
||||
name := commands[2]
|
||||
channel := sub.ChannelsUpdate(uid, name)
|
||||
channel, err := 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)
|
||||
}
|
||||
}
|
||||
|
@ -202,13 +215,18 @@ Commands:
|
|||
channel := commands[1]
|
||||
|
||||
var timeline microsub.Timeline
|
||||
var err error
|
||||
|
||||
if len(commands) == 4 && commands[2] == "-after" {
|
||||
timeline = sub.TimelineGet("", commands[3], channel)
|
||||
timeline, err = sub.TimelineGet("", commands[3], channel)
|
||||
} else if len(commands) == 4 && commands[2] == "-before" {
|
||||
timeline = sub.TimelineGet(commands[3], "", channel)
|
||||
timeline, err = sub.TimelineGet(commands[3], "", channel)
|
||||
} else {
|
||||
timeline = sub.TimelineGet("", "", channel)
|
||||
timeline, err = sub.TimelineGet("", "", channel)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("An error occurred: %s\n", err)
|
||||
}
|
||||
|
||||
for _, item := range timeline.Items {
|
||||
|
@ -220,7 +238,10 @@ Commands:
|
|||
|
||||
if len(commands) == 2 && commands[0] == "search" {
|
||||
query := commands[1]
|
||||
feeds := sub.Search(query)
|
||||
feeds, err := sub.Search(query)
|
||||
if err != nil {
|
||||
log.Fatalf("An error occurred: %s\n", err)
|
||||
}
|
||||
|
||||
for _, feed := range feeds {
|
||||
fmt.Println(feed.Name, " ", feed.URL)
|
||||
|
@ -229,8 +250,11 @@ Commands:
|
|||
|
||||
if len(commands) == 2 && commands[0] == "preview" {
|
||||
url := commands[1]
|
||||
timeline := sub.PreviewURL(url)
|
||||
timeline, err := sub.PreviewURL(url)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("An error occurred: %s\n", err)
|
||||
}
|
||||
for _, item := range timeline.Items {
|
||||
showItem(&item)
|
||||
}
|
||||
|
@ -238,7 +262,10 @@ Commands:
|
|||
|
||||
if len(commands) == 2 && commands[0] == "follow" {
|
||||
uid := commands[1]
|
||||
feeds := sub.FollowGetList(uid)
|
||||
feeds, err := sub.FollowGetList(uid)
|
||||
if err != nil {
|
||||
log.Fatalf("An error occurred: %s\n", err)
|
||||
}
|
||||
for _, feed := range feeds {
|
||||
fmt.Println(feed.Name, " ", feed.URL)
|
||||
}
|
||||
|
@ -247,13 +274,20 @@ Commands:
|
|||
if len(commands) == 3 && commands[0] == "follow" {
|
||||
uid := commands[1]
|
||||
url := commands[2]
|
||||
sub.FollowURL(uid, url)
|
||||
_, err := 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" {
|
||||
uid := commands[1]
|
||||
url := commands[2]
|
||||
sub.UnfollowURL(uid, url)
|
||||
err := sub.UnfollowURL(uid, url)
|
||||
if err != nil {
|
||||
log.Fatalf("An error occurred: %s\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/garyburd/redigo/redis"
|
||||
"github.com/pstuifzand/ekster/microsub"
|
||||
"github.com/pstuifzand/ekster/pkg/microsub"
|
||||
"willnorris.com/go/microformats"
|
||||
)
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/garyburd/redigo/redis"
|
||||
"github.com/pstuifzand/ekster/microsub"
|
||||
"github.com/pstuifzand/ekster/pkg/microsub"
|
||||
"github.com/pstuifzand/ekster/pkg/util"
|
||||
"github.com/pstuifzand/ekster/pkg/websub"
|
||||
)
|
||||
|
|
|
@ -29,8 +29,8 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/garyburd/redigo/redis"
|
||||
"github.com/pstuifzand/ekster/microsub"
|
||||
"github.com/pstuifzand/ekster/pkg/feedbin"
|
||||
"github.com/pstuifzand/ekster/pkg/microsub"
|
||||
"willnorris.com/go/microformats"
|
||||
)
|
||||
|
||||
|
@ -138,7 +138,7 @@ func createMemoryBackend() microsub.Microsub {
|
|||
}
|
||||
|
||||
// ChannelsGetList gets channels
|
||||
func (b *memoryBackend) ChannelsGetList() []microsub.Channel {
|
||||
func (b *memoryBackend) ChannelsGetList() ([]microsub.Channel, error) {
|
||||
conn := pool.Get()
|
||||
defer conn.Close()
|
||||
|
||||
|
@ -156,11 +156,11 @@ func (b *memoryBackend) ChannelsGetList() []microsub.Channel {
|
|||
}
|
||||
}
|
||||
}
|
||||
return channels
|
||||
return channels, nil
|
||||
}
|
||||
|
||||
// ChannelsCreate creates a channels
|
||||
func (b *memoryBackend) ChannelsCreate(name string) microsub.Channel {
|
||||
func (b *memoryBackend) ChannelsCreate(name string) (microsub.Channel, error) {
|
||||
defer b.save()
|
||||
|
||||
conn := pool.Get()
|
||||
|
@ -178,22 +178,23 @@ func (b *memoryBackend) ChannelsCreate(name string) microsub.Channel {
|
|||
|
||||
conn.Do("SADD", "channels", uid)
|
||||
conn.Do("SETNX", "channel_sortorder_"+uid, 99999)
|
||||
return channel
|
||||
|
||||
return channel, nil
|
||||
}
|
||||
|
||||
// ChannelsUpdate updates a channels
|
||||
func (b *memoryBackend) ChannelsUpdate(uid, name string) microsub.Channel {
|
||||
func (b *memoryBackend) ChannelsUpdate(uid, name string) (microsub.Channel, error) {
|
||||
defer b.save()
|
||||
if c, e := b.Channels[uid]; e {
|
||||
c.Name = name
|
||||
b.Channels[uid] = c
|
||||
return c
|
||||
return c, nil
|
||||
}
|
||||
return microsub.Channel{}
|
||||
return microsub.Channel{}, fmt.Errorf("Channel %s does not exist", uid)
|
||||
}
|
||||
|
||||
// ChannelsDelete deletes a channel
|
||||
func (b *memoryBackend) ChannelsDelete(uid string) {
|
||||
func (b *memoryBackend) ChannelsDelete(uid string) error {
|
||||
defer b.save()
|
||||
|
||||
conn := pool.Get()
|
||||
|
@ -204,6 +205,8 @@ func (b *memoryBackend) ChannelsDelete(uid string) {
|
|||
|
||||
delete(b.Channels, uid)
|
||||
delete(b.Feeds, uid)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func mapToAuthor(result map[string]string) *microsub.Card {
|
||||
|
@ -391,7 +394,7 @@ func (b *memoryBackend) run() {
|
|||
}()
|
||||
}
|
||||
|
||||
func (b *memoryBackend) TimelineGet(before, after, channel string) microsub.Timeline {
|
||||
func (b *memoryBackend) TimelineGet(before, after, channel string) (microsub.Timeline, error) {
|
||||
conn := pool.Get()
|
||||
defer conn.Close()
|
||||
|
||||
|
@ -430,11 +433,14 @@ func (b *memoryBackend) TimelineGet(before, after, channel string) microsub.Time
|
|||
return microsub.Timeline{
|
||||
Paging: microsub.Pagination{},
|
||||
Items: items,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
log.Printf("TimelineGet %s\n", channel)
|
||||
feeds := b.FollowGetList(channel)
|
||||
feeds, err := b.FollowGetList(channel)
|
||||
if err != nil {
|
||||
return microsub.Timeline{}, err
|
||||
}
|
||||
log.Println(feeds)
|
||||
|
||||
items := []microsub.Item{}
|
||||
|
@ -476,11 +482,10 @@ func (b *memoryBackend) TimelineGet(before, after, channel string) microsub.Time
|
|||
)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return microsub.Timeline{
|
||||
Paging: microsub.Pagination{},
|
||||
Items: items,
|
||||
}
|
||||
}, err
|
||||
}
|
||||
|
||||
if len(itemScores) >= 2 {
|
||||
|
@ -502,6 +507,7 @@ func (b *memoryBackend) TimelineGet(before, after, channel string) microsub.Time
|
|||
item := microsub.Item{}
|
||||
err := json.Unmarshal(obj, &item)
|
||||
if err != nil {
|
||||
// FIXME: what should we do if one of the items doen't unmarshal?
|
||||
log.Println(err)
|
||||
continue
|
||||
}
|
||||
|
@ -516,7 +522,7 @@ func (b *memoryBackend) TimelineGet(before, after, channel string) microsub.Time
|
|||
return microsub.Timeline{
|
||||
Paging: paging,
|
||||
Items: items,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
//panic if s is not a slice
|
||||
|
@ -553,17 +559,17 @@ func reverseSlice(s interface{}) {
|
|||
// return false
|
||||
// }
|
||||
|
||||
func (b *memoryBackend) FollowGetList(uid string) []microsub.Feed {
|
||||
return b.Feeds[uid]
|
||||
func (b *memoryBackend) FollowGetList(uid string) ([]microsub.Feed, error) {
|
||||
return b.Feeds[uid], nil
|
||||
}
|
||||
|
||||
func (b *memoryBackend) FollowURL(uid string, url string) microsub.Feed {
|
||||
func (b *memoryBackend) FollowURL(uid string, url string) (microsub.Feed, error) {
|
||||
defer b.save()
|
||||
feed := microsub.Feed{Type: "feed", URL: url}
|
||||
|
||||
resp, err := b.Fetch3(uid, feed.URL)
|
||||
if err != nil {
|
||||
return feed
|
||||
return feed, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
|
@ -571,10 +577,10 @@ func (b *memoryBackend) FollowURL(uid string, url string) microsub.Feed {
|
|||
|
||||
b.ProcessContent(uid, feed.URL, resp.Header.Get("Content-Type"), resp.Body)
|
||||
|
||||
return feed
|
||||
return feed, nil
|
||||
}
|
||||
|
||||
func (b *memoryBackend) UnfollowURL(uid string, url string) {
|
||||
func (b *memoryBackend) UnfollowURL(uid string, url string) error {
|
||||
defer b.save()
|
||||
index := -1
|
||||
for i, f := range b.Feeds[uid] {
|
||||
|
@ -587,6 +593,8 @@ func (b *memoryBackend) UnfollowURL(uid string, url string) {
|
|||
feeds := b.Feeds[uid]
|
||||
b.Feeds[uid] = append(feeds[:index], feeds[index+1:]...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkURL(u string) bool {
|
||||
|
@ -625,7 +633,7 @@ func getPossibleURLs(query string) []string {
|
|||
return urls
|
||||
}
|
||||
|
||||
func (b *memoryBackend) Search(query string) []microsub.Feed {
|
||||
func (b *memoryBackend) Search(query string) ([]microsub.Feed, error) {
|
||||
urls := getPossibleURLs(query)
|
||||
|
||||
feeds := []microsub.Feed{}
|
||||
|
@ -684,27 +692,25 @@ func (b *memoryBackend) Search(query string) []microsub.Feed {
|
|||
}
|
||||
}
|
||||
|
||||
return feeds
|
||||
return feeds, nil
|
||||
}
|
||||
|
||||
func (b *memoryBackend) PreviewURL(previewURL string) microsub.Timeline {
|
||||
func (b *memoryBackend) PreviewURL(previewURL string) (microsub.Timeline, error) {
|
||||
resp, err := Fetch2(previewURL)
|
||||
if err != nil {
|
||||
log.Printf("Error while fetching %s: %v\n", previewURL, err)
|
||||
return microsub.Timeline{}
|
||||
return microsub.Timeline{}, fmt.Errorf("error while fetching %s: %v", previewURL, err)
|
||||
}
|
||||
items, err := b.feedItems(previewURL, resp.Header.Get("content-type"), resp.Body)
|
||||
if err != nil {
|
||||
log.Printf("Error while fetching %s: %v\n", previewURL, err)
|
||||
return microsub.Timeline{}
|
||||
return microsub.Timeline{}, fmt.Errorf("error while fetching %s: %v", previewURL, err)
|
||||
}
|
||||
|
||||
return microsub.Timeline{
|
||||
Items: items,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *memoryBackend) MarkRead(channel string, uids []string) {
|
||||
func (b *memoryBackend) MarkRead(channel string, uids []string) error {
|
||||
conn := pool.Get()
|
||||
defer conn.Close()
|
||||
|
||||
|
@ -720,6 +726,7 @@ func (b *memoryBackend) MarkRead(channel string, uids []string) {
|
|||
|
||||
if _, err := conn.Do("SADD", args...); err != nil {
|
||||
log.Printf("Marking read for channel %s has failed\n", channel)
|
||||
return err
|
||||
}
|
||||
|
||||
zchannelKey := fmt.Sprintf("zchannel:%s:posts", channel)
|
||||
|
@ -727,6 +734,7 @@ func (b *memoryBackend) MarkRead(channel string, uids []string) {
|
|||
|
||||
if _, err := conn.Do("ZREM", args...); err != nil {
|
||||
log.Printf("Marking read for channel %s has failed\n", channel)
|
||||
return err
|
||||
}
|
||||
|
||||
unread, _ := redis.Int(conn.Do("ZCARD", zchannelKey))
|
||||
|
@ -741,4 +749,6 @@ func (b *memoryBackend) MarkRead(channel string, uids []string) {
|
|||
}
|
||||
|
||||
log.Printf("Marking read success for %s %v\n", channel, itemUIDs)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/garyburd/redigo/redis"
|
||||
"github.com/pstuifzand/ekster/microsub"
|
||||
"github.com/pstuifzand/ekster/pkg/microsub"
|
||||
"willnorris.com/go/microformats"
|
||||
)
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/garyburd/redigo/redis"
|
||||
"github.com/pstuifzand/ekster/microsub"
|
||||
"github.com/pstuifzand/ekster/pkg/microsub"
|
||||
)
|
||||
|
||||
type microsubHandler struct {
|
||||
|
@ -49,34 +49,67 @@ func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
values := r.URL.Query()
|
||||
action := values.Get("action")
|
||||
if action == "channels" {
|
||||
channels := h.Backend.ChannelsGetList()
|
||||
channels, err := h.Backend.ChannelsGetList()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
jw := json.NewEncoder(w)
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
jw.Encode(map[string][]microsub.Channel{
|
||||
err = jw.Encode(map[string][]microsub.Channel{
|
||||
"channels": channels,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
} else if action == "timeline" {
|
||||
timeline := h.Backend.TimelineGet(values.Get("before"), values.Get("after"), values.Get("channel"))
|
||||
timeline, err := 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)
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
jw.SetIndent("", " ")
|
||||
jw.Encode(timeline)
|
||||
err = jw.Encode(timeline)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
} else if action == "preview" {
|
||||
timeline := h.Backend.PreviewURL(values.Get("url"))
|
||||
timeline, err := h.Backend.PreviewURL(values.Get("url"))
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
jw := json.NewEncoder(w)
|
||||
jw.SetIndent("", " ")
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
jw.Encode(timeline)
|
||||
err = jw.Encode(timeline)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
} else if action == "follow" {
|
||||
channel := values.Get("channel")
|
||||
following := h.Backend.FollowGetList(channel)
|
||||
following, err := h.Backend.FollowGetList(channel)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
jw := json.NewEncoder(w)
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
jw.Encode(map[string][]microsub.Feed{
|
||||
err = jw.Encode(map[string][]microsub.Feed{
|
||||
"items": following,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
log.Printf("unknown action %s\n", action)
|
||||
http.Error(w, fmt.Sprintf("unknown action %s\n", action), 500)
|
||||
return
|
||||
}
|
||||
return
|
||||
} else if r.Method == http.MethodPost {
|
||||
|
@ -87,7 +120,11 @@ func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
method := values.Get("method")
|
||||
uid := values.Get("channel")
|
||||
if method == "delete" {
|
||||
h.Backend.ChannelsDelete(uid)
|
||||
err := h.Backend.ChannelsDelete(uid)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintln(w, "[]")
|
||||
h.Backend.(Debug).Debug()
|
||||
|
@ -96,37 +133,73 @@ func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
jw := json.NewEncoder(w)
|
||||
if uid == "" {
|
||||
channel := h.Backend.ChannelsCreate(name)
|
||||
channel, err := h.Backend.ChannelsCreate(name)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
jw.Encode(channel)
|
||||
err = jw.Encode(channel)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
channel := h.Backend.ChannelsUpdate(uid, name)
|
||||
channel, err := h.Backend.ChannelsUpdate(uid, name)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
jw.Encode(channel)
|
||||
err = jw.Encode(channel)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
}
|
||||
h.Backend.(Debug).Debug()
|
||||
} else if action == "follow" {
|
||||
uid := values.Get("channel")
|
||||
url := values.Get("url")
|
||||
h.HubIncomingBackend.CreateFeed(url, uid)
|
||||
feed := h.Backend.FollowURL(uid, url)
|
||||
feed, err := h.Backend.FollowURL(uid, url)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
jw := json.NewEncoder(w)
|
||||
jw.Encode(feed)
|
||||
err = jw.Encode(feed)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
} else if action == "unfollow" {
|
||||
uid := values.Get("channel")
|
||||
url := values.Get("url")
|
||||
h.Backend.UnfollowURL(uid, url)
|
||||
err := h.Backend.UnfollowURL(uid, url)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintln(w, "[]")
|
||||
} else if action == "search" {
|
||||
query := values.Get("query")
|
||||
feeds := h.Backend.Search(query)
|
||||
feeds, err := h.Backend.Search(query)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
jw := json.NewEncoder(w)
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
jw.Encode(map[string][]microsub.Feed{
|
||||
err = jw.Encode(map[string][]microsub.Feed{
|
||||
"results": feeds,
|
||||
})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
} else if action == "timeline" || r.PostForm.Get("action") == "timeline" {
|
||||
method := values.Get("method")
|
||||
|
||||
|
@ -134,9 +207,17 @@ func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
values = r.Form
|
||||
channel := values.Get("channel")
|
||||
if uids, e := values["entry"]; e {
|
||||
h.Backend.MarkRead(channel, uids)
|
||||
err := h.Backend.MarkRead(channel, uids)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
} else if uids, e := values["entry[]"]; e {
|
||||
h.Backend.MarkRead(channel, uids)
|
||||
err := h.Backend.MarkRead(channel, uids)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
uids := []string{}
|
||||
for k, v := range values {
|
||||
|
@ -144,15 +225,20 @@ func (h *microsubHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
uids = append(uids, v...)
|
||||
}
|
||||
}
|
||||
h.Backend.MarkRead(channel, uids)
|
||||
err := h.Backend.MarkRead(channel, uids)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Printf("unknown method in timeline %s\n", method)
|
||||
http.Error(w, fmt.Sprintf("unknown method in timeline %s\n", method), 500)
|
||||
return
|
||||
}
|
||||
w.Header().Add("Content-Type", "application/json")
|
||||
fmt.Fprintln(w, "[]")
|
||||
} else {
|
||||
log.Printf("unknown action %s\n", action)
|
||||
http.Error(w, fmt.Sprintf("unknown action %s\n", action), 500)
|
||||
}
|
||||
|
||||
return
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/pstuifzand/ekster/microsub"
|
||||
"github.com/pstuifzand/ekster/pkg/microsub"
|
||||
)
|
||||
|
||||
// NullBackend is the simplest possible backend
|
||||
|
@ -26,64 +26,67 @@ type NullBackend struct {
|
|||
}
|
||||
|
||||
// ChannelsGetList gets no channels
|
||||
func (b *NullBackend) ChannelsGetList() []microsub.Channel {
|
||||
func (b *NullBackend) ChannelsGetList() ([]microsub.Channel, error) {
|
||||
return []microsub.Channel{
|
||||
microsub.Channel{UID: "0000", Name: "default", Unread: 0},
|
||||
microsub.Channel{UID: "0001", Name: "notifications", Unread: 0},
|
||||
microsub.Channel{UID: "1000", Name: "Friends", Unread: 0},
|
||||
microsub.Channel{UID: "1001", Name: "Family", Unread: 0},
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ChannelsCreate creates no channels
|
||||
func (b *NullBackend) ChannelsCreate(name string) microsub.Channel {
|
||||
func (b *NullBackend) ChannelsCreate(name string) (microsub.Channel, error) {
|
||||
return microsub.Channel{
|
||||
UID: "1234",
|
||||
Name: name,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ChannelsUpdate updates no channels
|
||||
func (b *NullBackend) ChannelsUpdate(uid, name string) microsub.Channel {
|
||||
func (b *NullBackend) ChannelsUpdate(uid, name string) (microsub.Channel, error) {
|
||||
return microsub.Channel{
|
||||
UID: uid,
|
||||
Name: name,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ChannelsDelete delets no channels
|
||||
func (b *NullBackend) ChannelsDelete(uid string) {
|
||||
func (b *NullBackend) ChannelsDelete(uid string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TimelineGet gets no timeline
|
||||
func (b *NullBackend) TimelineGet(before, after, channel string) microsub.Timeline {
|
||||
func (b *NullBackend) TimelineGet(before, after, channel string) (microsub.Timeline, error) {
|
||||
return microsub.Timeline{
|
||||
Paging: microsub.Pagination{},
|
||||
Items: []microsub.Item{},
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *NullBackend) FollowGetList(uid string) []microsub.Feed {
|
||||
return []microsub.Feed{}
|
||||
func (b *NullBackend) FollowGetList(uid string) ([]microsub.Feed, error) {
|
||||
return []microsub.Feed{}, nil
|
||||
}
|
||||
|
||||
func (b *NullBackend) FollowURL(uid string, url string) microsub.Feed {
|
||||
return microsub.Feed{Type: "feed", URL: url}
|
||||
func (b *NullBackend) FollowURL(uid string, url string) (microsub.Feed, error) {
|
||||
return microsub.Feed{Type: "feed", URL: url}, nil
|
||||
}
|
||||
|
||||
func (b *NullBackend) UnfollowURL(uid string, url string) {
|
||||
func (b *NullBackend) UnfollowURL(uid string, url string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *NullBackend) Search(query string) []microsub.Feed {
|
||||
return []microsub.Feed{}
|
||||
func (b *NullBackend) Search(query string) ([]microsub.Feed, error) {
|
||||
return []microsub.Feed{}, nil
|
||||
}
|
||||
|
||||
func (b *NullBackend) PreviewURL(url string) microsub.Timeline {
|
||||
func (b *NullBackend) PreviewURL(url string) (microsub.Timeline, error) {
|
||||
return microsub.Timeline{
|
||||
Paging: microsub.Pagination{},
|
||||
Items: []microsub.Item{},
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *NullBackend) MarkRead(channel string, uids []string) {
|
||||
func (b *NullBackend) MarkRead(channel string, uids []string) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,12 +3,11 @@ package client
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/pstuifzand/ekster/microsub"
|
||||
"github.com/pstuifzand/ekster/pkg/microsub"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
|
@ -80,12 +79,11 @@ func (c *Client) microsubPostFormRequest(action string, args map[string]string,
|
|||
return client.Do(req)
|
||||
}
|
||||
|
||||
func (c *Client) ChannelsGetList() []microsub.Channel {
|
||||
func (c *Client) ChannelsGetList() ([]microsub.Channel, error) {
|
||||
args := make(map[string]string)
|
||||
res, err := c.microsubGetRequest("channels", args)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return []microsub.Channel{}
|
||||
return []microsub.Channel{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
|
@ -95,52 +93,56 @@ func (c *Client) ChannelsGetList() []microsub.Channel {
|
|||
|
||||
dec := json.NewDecoder(res.Body)
|
||||
var channels channelsResponse
|
||||
dec.Decode(&channels)
|
||||
return channels.Channels
|
||||
err = dec.Decode(&channels)
|
||||
if err != nil {
|
||||
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["after"] = after
|
||||
args["before"] = before
|
||||
args["channel"] = channel
|
||||
res, err := c.microsubGetRequest("timeline", args)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return microsub.Timeline{}
|
||||
return microsub.Timeline{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
dec := json.NewDecoder(res.Body)
|
||||
var timeline microsub.Timeline
|
||||
err = dec.Decode(&timeline)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return microsub.Timeline{}, err
|
||||
}
|
||||
return timeline
|
||||
return timeline, nil
|
||||
}
|
||||
|
||||
func (c *Client) PreviewURL(url string) microsub.Timeline {
|
||||
func (c *Client) PreviewURL(url string) (microsub.Timeline, error) {
|
||||
args := make(map[string]string)
|
||||
args["url"] = url
|
||||
res, err := c.microsubGetRequest("preview", args)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return microsub.Timeline{}
|
||||
return microsub.Timeline{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
dec := json.NewDecoder(res.Body)
|
||||
var timeline microsub.Timeline
|
||||
dec.Decode(&timeline)
|
||||
return timeline
|
||||
err = dec.Decode(&timeline)
|
||||
if err != nil {
|
||||
return microsub.Timeline{}, err
|
||||
}
|
||||
return timeline, nil
|
||||
}
|
||||
|
||||
func (c *Client) FollowGetList(channel string) []microsub.Feed {
|
||||
func (c *Client) FollowGetList(channel string) ([]microsub.Feed, error) {
|
||||
args := make(map[string]string)
|
||||
args["channel"] = channel
|
||||
res, err := c.microsubGetRequest("follow", args)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return []microsub.Feed{}
|
||||
return []microsub.Feed{}, nil
|
||||
}
|
||||
defer res.Body.Close()
|
||||
dec := json.NewDecoder(res.Body)
|
||||
|
@ -148,88 +150,96 @@ func (c *Client) FollowGetList(channel string) []microsub.Feed {
|
|||
Items []microsub.Feed `json:"items"`
|
||||
}
|
||||
var response followResponse
|
||||
dec.Decode(&response)
|
||||
return response.Items
|
||||
err = dec.Decode(&response)
|
||||
if err != nil {
|
||||
return []microsub.Feed{}, nil
|
||||
}
|
||||
return response.Items, nil
|
||||
}
|
||||
|
||||
func (c *Client) ChannelsCreate(name string) microsub.Channel {
|
||||
func (c *Client) ChannelsCreate(name string) (microsub.Channel, error) {
|
||||
args := make(map[string]string)
|
||||
args["name"] = name
|
||||
res, err := c.microsubPostRequest("channels", args)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return microsub.Channel{}
|
||||
return microsub.Channel{}, nil
|
||||
}
|
||||
defer res.Body.Close()
|
||||
var channel microsub.Channel
|
||||
dec := json.NewDecoder(res.Body)
|
||||
dec.Decode(&channel)
|
||||
return channel
|
||||
err = dec.Decode(&channel)
|
||||
if err != nil {
|
||||
return microsub.Channel{}, nil
|
||||
}
|
||||
return channel, nil
|
||||
}
|
||||
|
||||
func (c *Client) ChannelsUpdate(uid, name string) microsub.Channel {
|
||||
func (c *Client) ChannelsUpdate(uid, name string) (microsub.Channel, error) {
|
||||
args := make(map[string]string)
|
||||
args["name"] = name
|
||||
args["uid"] = uid
|
||||
res, err := c.microsubPostRequest("channels", args)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return microsub.Channel{}
|
||||
return microsub.Channel{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
var channel microsub.Channel
|
||||
dec := json.NewDecoder(res.Body)
|
||||
dec.Decode(&channel)
|
||||
return channel
|
||||
err = dec.Decode(&channel)
|
||||
if err != nil {
|
||||
return microsub.Channel{}, err
|
||||
}
|
||||
return channel, nil
|
||||
}
|
||||
|
||||
func (c *Client) ChannelsDelete(uid string) {
|
||||
func (c *Client) ChannelsDelete(uid string) error {
|
||||
args := make(map[string]string)
|
||||
args["channel"] = uid
|
||||
args["method"] = "delete"
|
||||
res, err := c.microsubPostRequest("channels", args)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
res.Body.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) FollowURL(channel, url string) microsub.Feed {
|
||||
func (c *Client) FollowURL(channel, url string) (microsub.Feed, error) {
|
||||
args := make(map[string]string)
|
||||
args["channel"] = channel
|
||||
args["url"] = url
|
||||
res, err := c.microsubPostRequest("follow", args)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return microsub.Feed{}
|
||||
return microsub.Feed{}, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
var feed microsub.Feed
|
||||
dec := json.NewDecoder(res.Body)
|
||||
dec.Decode(&feed)
|
||||
return feed
|
||||
err = dec.Decode(&feed)
|
||||
if err != nil {
|
||||
return microsub.Feed{}, err
|
||||
}
|
||||
return feed, nil
|
||||
}
|
||||
|
||||
func (c *Client) UnfollowURL(channel, url string) {
|
||||
func (c *Client) UnfollowURL(channel, url string) error {
|
||||
args := make(map[string]string)
|
||||
args["channel"] = channel
|
||||
args["url"] = url
|
||||
res, err := c.microsubPostRequest("unfollow", args)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
return err
|
||||
}
|
||||
res.Body.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) Search(query string) []microsub.Feed {
|
||||
func (c *Client) Search(query string) ([]microsub.Feed, error) {
|
||||
args := make(map[string]string)
|
||||
args["query"] = query
|
||||
res, err := c.microsubPostRequest("search", args)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return []microsub.Feed{}
|
||||
return []microsub.Feed{}, err
|
||||
}
|
||||
type searchResponse struct {
|
||||
Results []microsub.Feed `json:"results"`
|
||||
|
@ -237,11 +247,14 @@ func (c *Client) Search(query string) []microsub.Feed {
|
|||
defer res.Body.Close()
|
||||
var response searchResponse
|
||||
dec := json.NewDecoder(res.Body)
|
||||
dec.Decode(&response)
|
||||
return response.Results
|
||||
err = dec.Decode(&response)
|
||||
if err != nil {
|
||||
return []microsub.Feed{}, err
|
||||
}
|
||||
return response.Results, nil
|
||||
}
|
||||
|
||||
func (c *Client) MarkRead(channel string, uids []string) {
|
||||
func (c *Client) MarkRead(channel string, uids []string) error {
|
||||
args := make(map[string]string)
|
||||
args["channel"] = channel
|
||||
|
||||
|
@ -251,7 +264,9 @@ func (c *Client) MarkRead(channel string, uids []string) {
|
|||
}
|
||||
|
||||
res, err := c.microsubPostFormRequest("mark_read", args, data)
|
||||
if err == nil {
|
||||
defer res.Body.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res.Body.Close()
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -102,20 +102,20 @@ type Feed struct {
|
|||
|
||||
// Microsub is the main protocol that should be implemented by a backend
|
||||
type Microsub interface {
|
||||
ChannelsGetList() []Channel
|
||||
ChannelsCreate(name string) Channel
|
||||
ChannelsUpdate(uid, name string) Channel
|
||||
ChannelsDelete(uid string)
|
||||
ChannelsGetList() ([]Channel, error)
|
||||
ChannelsCreate(name string) (Channel, error)
|
||||
ChannelsUpdate(uid, name string) (Channel, error)
|
||||
ChannelsDelete(uid string) error
|
||||
|
||||
TimelineGet(before, after, channel string) Timeline
|
||||
TimelineGet(before, after, channel string) (Timeline, error)
|
||||
|
||||
MarkRead(channel string, entry []string)
|
||||
MarkRead(channel string, entry []string) error
|
||||
|
||||
FollowGetList(uid string) []Feed
|
||||
FollowURL(uid string, url string) Feed
|
||||
FollowGetList(uid string) ([]Feed, error)
|
||||
FollowURL(uid string, url string) (Feed, error)
|
||||
|
||||
UnfollowURL(uid string, url string)
|
||||
UnfollowURL(uid string, url string) error
|
||||
|
||||
Search(query string) []Feed
|
||||
PreviewURL(url string) Timeline
|
||||
Search(query string) ([]Feed, error)
|
||||
PreviewURL(url string) (Timeline, error)
|
||||
}
|
15
pkg/microsub/protocol_test.go
Normal file
15
pkg/microsub/protocol_test.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user