diff --git a/cmd/ek/main.go b/cmd/ek/main.go index e84f31f..dbb6de0 100644 --- a/cmd/ek/main.go +++ b/cmd/ek/main.go @@ -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) + } } } diff --git a/cmd/eksterd/memory.go b/cmd/eksterd/memory.go index 8716dd7..845c03e 100644 --- a/cmd/eksterd/memory.go +++ b/cmd/eksterd/memory.go @@ -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 } diff --git a/cmd/eksterd/microsub.go b/cmd/eksterd/microsub.go index 2bec02b..c98c2f2 100644 --- a/cmd/eksterd/microsub.go +++ b/cmd/eksterd/microsub.go @@ -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 diff --git a/cmd/eksterd/null.go b/cmd/eksterd/null.go index c380182..d7e25a0 100644 --- a/cmd/eksterd/null.go +++ b/cmd/eksterd/null.go @@ -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 } diff --git a/pkg/client/requests.go b/pkg/client/requests.go index 4fd821e..2fddb4a 100644 --- a/pkg/client/requests.go +++ b/pkg/client/requests.go @@ -3,7 +3,6 @@ package client import ( "encoding/json" "fmt" - "log" "net/http" "net/url" "strings" @@ -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 } diff --git a/pkg/microsub/protocol.go b/pkg/microsub/protocol.go index 60fa770..f99b29d 100644 --- a/pkg/microsub/protocol.go +++ b/pkg/microsub/protocol.go @@ -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) }