Page Menu
Home
Musing Studio
Search
Configure Global Search
Log In
Files
F10387932
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
10 KB
Subscribers
None
View Options
diff --git a/collection.go b/collection.go
index d4c3771..c1ab46f 100644
--- a/collection.go
+++ b/collection.go
@@ -1,138 +1,222 @@
package writeas
import (
"fmt"
"net/http"
)
type (
// Collection represents a collection of posts. Blogs are a type of collection
// on Write.as.
Collection struct {
Alias string `json:"alias"`
Title string `json:"title"`
Description string `json:"description"`
StyleSheet string `json:"style_sheet"`
Private bool `json:"private"`
Views int64 `json:"views"`
Domain string `json:"domain,omitempty"`
Email string `json:"email,omitempty"`
URL string `json:"url,omitempty"`
TotalPosts int `json:"total_posts"`
Posts *[]Post `json:"posts,omitempty"`
}
// CollectionParams holds values for creating a collection.
CollectionParams struct {
Alias string `json:"alias"`
Title string `json:"title"`
Description string `json:"description,omitempty"`
}
+
+ // DeleteCollectionParams holds the parameters required to delete a
+ // collection.
+ 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
// if one comes up. Requires a Write.as subscription. See
// https://developer.write.as/docs/api/#create-a-collection
func (c *Client) CreateCollection(sp *CollectionParams) (*Collection, error) {
p := &Collection{}
env, err := c.post("/collections", sp, p)
if err != nil {
return nil, err
}
var ok bool
if p, ok = env.Data.(*Collection); !ok {
return nil, fmt.Errorf("Wrong data returned from API.")
}
status := env.Code
if status != http.StatusCreated {
if status == http.StatusBadRequest {
return nil, fmt.Errorf("Bad request: %s", env.ErrorMessage)
} else if status == http.StatusForbidden {
return nil, fmt.Errorf("Casual or Pro user required.")
} else if status == http.StatusConflict {
return nil, fmt.Errorf("Collection name is already taken.")
} else if status == http.StatusPreconditionFailed {
return nil, fmt.Errorf("Reached max collection quota.")
}
return nil, fmt.Errorf("Problem getting post: %d. %v\n", status, err)
}
return p, nil
}
// GetCollection retrieves a collection, returning the Collection and any error
// (in user-friendly form) that occurs. See
// https://developer.write.as/docs/api/#retrieve-a-collection
func (c *Client) GetCollection(alias string) (*Collection, error) {
coll := &Collection{}
env, err := c.get(fmt.Sprintf("/collections/%s", alias), coll)
if err != nil {
return nil, err
}
var ok bool
if coll, ok = env.Data.(*Collection); !ok {
return nil, fmt.Errorf("Wrong data returned from API.")
}
status := env.Code
if status == http.StatusOK {
return coll, nil
} else if status == http.StatusNotFound {
return nil, fmt.Errorf("Collection not found.")
} else {
return nil, fmt.Errorf("Problem getting collection: %d. %v\n", status, err)
}
}
// GetCollectionPosts retrieves a collection's posts, returning the Posts
// and any error (in user-friendly form) that occurs. See
// https://developer.write.as/docs/api/#retrieve-collection-posts
func (c *Client) GetCollectionPosts(alias string) (*[]Post, error) {
coll := &Collection{}
env, err := c.get(fmt.Sprintf("/collections/%s/posts", alias), coll)
if err != nil {
return nil, err
}
var ok bool
if coll, ok = env.Data.(*Collection); !ok {
return nil, fmt.Errorf("Wrong data returned from API.")
}
status := env.Code
if status == http.StatusOK {
return coll.Posts, nil
} else if status == http.StatusNotFound {
return nil, fmt.Errorf("Collection not found.")
} else {
return nil, fmt.Errorf("Problem getting collection: %d. %v\n", status, err)
}
}
// GetUserCollections retrieves the authenticated user's collections.
// See https://developers.write.as/docs/api/#retrieve-user-39-s-collections
func (c *Client) GetUserCollections() (*[]Collection, error) {
colls := &[]Collection{}
env, err := c.get("/me/collections", colls)
if err != nil {
return nil, err
}
var ok bool
if colls, ok = env.Data.(*[]Collection); !ok {
return nil, fmt.Errorf("Wrong data returned from API.")
}
status := env.Code
if status != http.StatusOK {
if c.isNotLoggedIn(status) {
return nil, fmt.Errorf("Not authenticated.")
}
return nil, fmt.Errorf("Problem getting collections: %d. %v\n", status, err)
}
return colls, nil
}
+
+// DeleteCollection permanently deletes a collection and makes any posts on it
+// anonymous.
+//
+// See https://developers.write.as/docs/api/#delete-a-collection.
+func (c *Client) DeleteCollection(p *DeleteCollectionParams) error {
+ endpoint := "/collections/" + p.Alias
+ env, err := c.delete(endpoint, nil /* data */)
+ if err != nil {
+ return err
+ }
+
+ status := env.Code
+ switch status {
+ case http.StatusNoContent:
+ return nil
+ case http.StatusUnauthorized:
+ return fmt.Errorf("Not authenticated.")
+ case http.StatusBadRequest:
+ return fmt.Errorf("Bad request: %s", env.ErrorMessage)
+ default:
+ 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)
+ }
+}
diff --git a/collection_test.go b/collection_test.go
index da9a7f3..77a32cb 100644
--- a/collection_test.go
+++ b/collection_test.go
@@ -1,63 +1,162 @@
package writeas
import (
"fmt"
+ "net/http"
+ "strings"
"testing"
+ "time"
)
func TestGetCollection(t *testing.T) {
wac := NewClient()
res, err := wac.GetCollection("blog")
if err != nil {
t.Errorf("Unexpected fetch results: %+v, err: %v\n", res, err)
} else {
t.Logf("Collection: %+v", res)
if res.Title != "write.as" {
t.Errorf("Unexpected fetch results: %+v\n", res)
}
}
}
func TestGetCollectionPosts(t *testing.T) {
wac := NewClient()
res, err := wac.GetCollectionPosts("blog")
if err != nil {
t.Errorf("Unexpected fetch results: %+v, err: %v\n", res, err)
} else {
if len(*res) == 0 {
t.Errorf("No posts returned!")
}
}
}
func TestGetUserCollections(t *testing.T) {
wac := NewDevClient()
_, err := wac.LogIn("demo", "demo")
if err != nil {
t.Fatalf("Unable to log in: %v", err)
}
defer wac.LogOut()
res, err := wac.GetUserCollections()
if err != nil {
t.Errorf("Unexpected fetch results: %+v, err: %v\n", res, err)
} else {
t.Logf("User collections: %+v", res)
if len(*res) == 0 {
t.Errorf("No collections returned!")
}
}
}
+func TestCreateAndDeleteCollection(t *testing.T) {
+ wac := NewDevClient()
+ _, err := wac.LogIn("demo", "demo")
+ if err != nil {
+ t.Fatalf("Unable to log in: %v", err)
+ }
+ defer wac.LogOut()
+
+ now := time.Now().Unix()
+ alias := fmt.Sprintf("test-collection-%v", now)
+ c, 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)
+ }
+
+ p := &DeleteCollectionParams{Alias: c.Alias}
+ if err := wac.DeleteCollection(p); err != nil {
+ t.Fatalf("Unable to delete collection %q: %v", alias, err)
+ }
+}
+
+func TestDeleteCollectionUnauthenticated(t *testing.T) {
+ wac := NewDevClient()
+
+ now := time.Now().Unix()
+ alias := fmt.Sprintf("test-collection-does-not-exist-%v", now)
+ p := &DeleteCollectionParams{Alias: alias}
+ err := wac.DeleteCollection(p)
+ if err == nil {
+ t.Fatalf("Should not be able to delete collection %q unauthenticated.", alias)
+ }
+
+ if !strings.Contains(err.Error(), "Not authenticated") {
+ t.Fatalf("Error message should be more informative: %v", err)
+ }
+}
+
func ExampleClient_GetCollection() {
c := NewClient()
coll, err := c.GetCollection("blog")
if err != nil {
fmt.Printf("%v", err)
return
}
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)
+ }
+ }
+}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Nov 25, 6:22 PM (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3106945
Attached To
rWGO writeas-go
Event Timeline
Log In to Comment