Browse Source

collection: Support collecting posts

This adds support for moving posts to a collection. This change relies
on #13 so that we can create and delete collections during tests.

Couple notes:

- CollectPosts accepts a single struct rather than an alias and a list
  of structs. This makes it easy to add new optional parameters in the
  future.

- We're passing `[]*CollectPost` around rather than `*[]CollectPost`
  which is done in some of the existing APIs. The reasoning for this is:

  - Idiomatically, slices are passed by-value (`[]foo`) rather than
    by-pointer (`*[]foo`) because slices are already reference types.
    Plus they're really cheap to copy since they're just a triple:
    pointer, length, and capacity ([related blog post][1]). We need
    pointers to slices only when we're trying to modify the original
    slice reference and don't have the ability to return a slice, like
    with `json.Unmarshal` (see also [this post][2]).

  - If we're trying to reduce copying, `[]*foo` is better than `[]foo`
    because otherwise `foo` will be copied when manipulating or
    accessing entries in the slice (like ranging over it).

  Existing APIs were left as-is to avoid breaking them. I can switch to
  `*[]CollectPost` if you'd prefer that but `[]*CollectPost` is more
  idiomatic.

[1]: https://blog.golang.org/go-slices-usage-and-internals#TOC_4.
[2]: https://blog.golang.org/slices#TOC_5.

Resolves #4.
pull/14/head
Abhinav Gupta 5 years ago
parent
commit
e2fd429909
2 changed files with 111 additions and 0 deletions
  1. +54
    -0
      collection.go
  2. +57
    -0
      collection_test.go

+ 54
- 0
collection.go View File

@@ -35,6 +35,35 @@ type (
DeleteCollectionParams struct {
Alias string `json:"-"`
}

// CollectPostParams holds the parameters for moving posts to a collection.
CollectPostParams struct {
// Alias of the collection.
Alias string `json:"-"`

// Posts to move to this collection.
Posts []*CollectPost
}

// CollectPost is a post being moved to a collection.
CollectPost struct {
// ID of the post.
ID string `json:"id,omitempty"`

// The post's modify token.
//
// This is required if the post does not belong to the user making
// this request.
Token string `json:"token,omitempty"`
}

// CollectPostResult holds the result of moving a single post to a
// collection.
CollectPostResult struct {
Code int `json:"code,omitempty"`
ErrorMessage string `json:"error_msg,omitempty"`
Post *Post `json:"post,omitempty"`
}
)

// CreateCollection creates a new collection, returning a user-friendly error
@@ -165,3 +194,28 @@ func (c *Client) DeleteCollection(p *DeleteCollectionParams) error {
return fmt.Errorf("Problem deleting collection: %d. %s\n", status, env.ErrorMessage)
}
}

// CollectPosts adds a group of posts to a collection.
//
// See https://developers.write.as/docs/api/#move-a-post-to-a-collection.
func (c *Client) CollectPosts(sp *CollectPostParams) ([]*CollectPostResult, error) {
endpoint := "/collections/" + sp.Alias + "/collect"

var p []*CollectPostResult
env, err := c.post(endpoint, sp.Posts, &p)
if err != nil {
return nil, err
}

status := env.Code
switch {
case status == http.StatusOK:
return p, nil
case c.isNotLoggedIn(status):
return nil, fmt.Errorf("Not authenticated.")
case status == http.StatusBadRequest:
return nil, fmt.Errorf("Bad request: %s", env.ErrorMessage)
default:
return nil, fmt.Errorf("Problem claiming post: %d. %s\n", status, env.ErrorMessage)
}
}

+ 57
- 0
collection_test.go View File

@@ -2,6 +2,7 @@ package writeas

import (
"fmt"
"net/http"
"strings"
"testing"
"time"
@@ -103,3 +104,59 @@ func ExampleClient_GetCollection() {
fmt.Printf("%s", coll.Title)
// Output: write.as
}

func TestCollectPostsAnonymous(t *testing.T) {
// Create a post anonymously.
wac := NewDevClient()
p, err := wac.CreatePost(&PostParams{
Title: "Title!",
Content: "This is a post.",
Font: "sans",
})
if err != nil {
t.Errorf("Post create failed: %v", err)
return
}
t.Logf("Post created: %+v", p)

// Log in.
if _, err := wac.LogIn("demo", "demo"); err != nil {
t.Fatalf("Unable to log in: %v", err)
}
defer wac.LogOut()

now := time.Now().Unix()
alias := fmt.Sprintf("test-collection-%v", now)

// Create a collection.
_, err = wac.CreateCollection(&CollectionParams{
Alias: alias,
Title: fmt.Sprintf("Test Collection %v", now),
})
if err != nil {
t.Fatalf("Unable to create collection %q: %v", alias, err)
}
defer wac.DeleteCollection(&DeleteCollectionParams{Alias: alias})

// Move the anonymous post to this collection.
res, err := wac.CollectPosts(&CollectPostParams{
Alias: alias,
Posts: []*CollectPost{
{
ID: p.ID,
Token: p.Token,
},
},
})
if err != nil {
t.Fatalf("Could not collect post %q: %v", p.ID, err)
}

for _, cr := range res {
if cr.Code != http.StatusOK {
t.Errorf("Failed to move post: %v", cr.ErrorMessage)
} else {
t.Logf("Moved post %q", cr.Post.ID)
}
}
}

Loading…
Cancel
Save