Page Menu
Home
Musing Studio
Search
Configure Global Search
Log In
Files
F10669953
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/post.go b/post.go
index 300c57e..225bda7 100644
--- a/post.go
+++ b/post.go
@@ -1,217 +1,266 @@
package writeas
import (
"fmt"
"net/http"
"time"
)
type (
// Post represents a published Write.as post, whether anonymous, owned by a
// user, or part of a collection.
Post struct {
ID string `json:"id"`
Slug string `json:"slug"`
Token string `json:"token"`
Font string `json:"appearance"`
Language *string `json:"language"`
RTL *bool `json:"rtl"`
Listed bool `json:"listed"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
Title string `json:"title"`
Content string `json:"body"`
Views int64 `json:"views"`
Tags []string `json:"tags"`
Images []string `json:"images"`
OwnerName string `json:"owner,omitempty"`
Collection *Collection `json:"collection,omitempty"`
}
// OwnedPostParams are, together, fields only the original post author knows.
OwnedPostParams struct {
ID string `json:"-"`
Token string `json:"token,omitempty"`
}
// PostParams holds values for creating or updating a post.
PostParams struct {
// Parameters only for updating
ID string `json:"-"`
Token string `json:"token,omitempty"`
// Parameters for creating or updating
Title string `json:"title,omitempty"`
Content string `json:"body,omitempty"`
Font string `json:"font,omitempty"`
IsRTL *bool `json:"rtl,omitempty"`
Language *string `json:"lang,omitempty"`
// Parameters only for creating
Crosspost []map[string]string `json:"crosspost,omitempty"`
// Parameters for collection posts
Collection string `json:"-"`
}
+ // PinnedPostParams holds values for pinning a post
+ PinnedPostParams struct {
+ ID string `json:"id"`
+ Position int `json:"position"`
+ }
+
+ // BatchPostResult contains the post-specific result as part of a larger
+ // batch operation.
+ BatchPostResult struct {
+ ID string `json:"id,omitempty"`
+ Code int `json:"code,omitempty"`
+ ErrorMessage string `json:"error_msg,omitempty"`
+ }
+
// ClaimPostResult contains the post-specific result for a request to
// associate a post to an account.
ClaimPostResult struct {
ID string `json:"id,omitempty"`
Code int `json:"code,omitempty"`
ErrorMessage string `json:"error_msg,omitempty"`
Post *Post `json:"post,omitempty"`
}
)
// GetPost retrieves a published post, returning the Post and any error (in
// user-friendly form) that occurs. See
// https://developer.write.as/docs/api/#retrieve-a-post.
func (c *Client) GetPost(id string) (*Post, error) {
p := &Post{}
env, err := c.get(fmt.Sprintf("/posts/%s", id), p)
if err != nil {
return nil, err
}
var ok bool
if p, ok = env.Data.(*Post); !ok {
return nil, fmt.Errorf("Wrong data returned from API.")
}
status := env.Code
if status == http.StatusOK {
return p, nil
} else if status == http.StatusNotFound {
return nil, fmt.Errorf("Post not found.")
} else if status == http.StatusGone {
return nil, fmt.Errorf("Post unpublished.")
}
return nil, fmt.Errorf("Problem getting post: %d. %v\n", status, err)
}
// CreatePost publishes a new post, returning a user-friendly error if one comes
// up. See https://developer.write.as/docs/api/#publish-a-post.
func (c *Client) CreatePost(sp *PostParams) (*Post, error) {
p := &Post{}
endPre := ""
if sp.Collection != "" {
endPre = "/collections/" + sp.Collection
}
env, err := c.post(endPre+"/posts", sp, p)
if err != nil {
return nil, err
}
var ok bool
if p, ok = env.Data.(*Post); !ok {
return nil, fmt.Errorf("Wrong data returned from API.")
}
status := env.Code
if status == http.StatusCreated {
return p, nil
} else if status == http.StatusBadRequest {
return nil, fmt.Errorf("Bad request: %s", env.ErrorMessage)
} else {
return nil, fmt.Errorf("Problem getting post: %d. %v\n", status, err)
}
}
// UpdatePost updates a published post with the given PostParams. See
// https://developer.write.as/docs/api/#update-a-post.
func (c *Client) UpdatePost(sp *PostParams) (*Post, error) {
p := &Post{}
env, err := c.put(fmt.Sprintf("/posts/%s", sp.ID), sp, p)
if err != nil {
return nil, err
}
var ok bool
if p, ok = env.Data.(*Post); !ok {
return nil, fmt.Errorf("Wrong data returned from API.")
}
status := env.Code
if status == http.StatusOK {
return p, nil
} else if c.isNotLoggedIn(status) {
return nil, fmt.Errorf("Not authenticated.")
} else if status == http.StatusBadRequest {
return nil, fmt.Errorf("Bad request: %s", env.ErrorMessage)
}
return nil, fmt.Errorf("Problem getting post: %d. %v\n", status, err)
}
// DeletePost permanently deletes a published post. See
// https://developer.write.as/docs/api/#delete-a-post.
func (c *Client) DeletePost(sp *PostParams) error {
env, err := c.delete(fmt.Sprintf("/posts/%s", sp.ID), map[string]string{
"token": sp.Token,
})
if err != nil {
return err
}
status := env.Code
if status == http.StatusNoContent {
return nil
} else if c.isNotLoggedIn(status) {
return fmt.Errorf("Not authenticated.")
} else if status == http.StatusBadRequest {
return fmt.Errorf("Bad request: %s", env.ErrorMessage)
}
return fmt.Errorf("Problem getting post: %d. %v\n", status, err)
}
// ClaimPosts associates anonymous posts with a user / account.
// https://developer.write.as/docs/api/#claim-posts.
func (c *Client) ClaimPosts(sp *[]OwnedPostParams) (*[]ClaimPostResult, error) {
p := &[]ClaimPostResult{}
env, err := c.put("/posts/claim", sp, p)
if err != nil {
return nil, err
}
var ok bool
if p, ok = env.Data.(*[]ClaimPostResult); !ok {
return nil, fmt.Errorf("Wrong data returned from API.")
}
status := env.Code
if status == http.StatusOK {
return p, nil
} else if c.isNotLoggedIn(status) {
return nil, fmt.Errorf("Not authenticated.")
} else if status == http.StatusBadRequest {
return nil, fmt.Errorf("Bad request: %s", env.ErrorMessage)
} else {
return nil, fmt.Errorf("Problem getting post: %d. %v\n", status, err)
}
// TODO: does this also happen with moving posts?
}
// GetUserPosts retrieves the authenticated user's posts.
// See https://developers.write.as/docs/api/#retrieve-user-39-s-posts
func (c *Client) GetUserPosts() (*[]Post, error) {
p := &[]Post{}
env, err := c.get("/me/posts", p)
if err != nil {
return nil, err
}
var ok bool
if p, ok = env.Data.(*[]Post); !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 posts: %d. %v\n", status, err)
}
return p, nil
}
+
+// PinPost pins a post in the given collection.
+// See https://developers.write.as/docs/api/#pin-a-post-to-a-collection
+func (c *Client) PinPost(alias string, pp *PinnedPostParams) error {
+ res := &[]BatchPostResult{}
+ env, err := c.post(fmt.Sprintf("/collections/%s/pin", alias), []*PinnedPostParams{pp}, res)
+ if err != nil {
+ return err
+ }
+
+ var ok bool
+ if res, ok = env.Data.(*[]BatchPostResult); !ok {
+ return fmt.Errorf("Wrong data returned from API.")
+ }
+
+ // Check for basic request errors on top level response
+ status := env.Code
+ if status != http.StatusOK {
+ if c.isNotLoggedIn(status) {
+ return fmt.Errorf("Not authenticated.")
+ }
+ return fmt.Errorf("Problem pinning post: %d. %v\n", status, err)
+ }
+
+ // Check the individual post result
+ if len(*res) == 0 || len(*res) > 1 {
+ return fmt.Errorf("Wrong data returned from API.")
+ }
+ if (*res)[0].Code != http.StatusOK {
+ return fmt.Errorf("Problem pinning post: %d", (*res)[0].Code)
+ // TODO: return ErrorMessage (right now it'll be empty)
+ // return fmt.Errorf("Problem pinning post: %v", res[0].ErrorMessage)
+ }
+ return nil
+}
diff --git a/post_test.go b/post_test.go
index 830a506..11562d6 100644
--- a/post_test.go
+++ b/post_test.go
@@ -1,92 +1,106 @@
package writeas
import (
"testing"
"fmt"
"strings"
)
func TestCreatePost(t *testing.T) {
wac := NewClient()
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)
token := p.Token
// Update post
p, err = wac.UpdatePost(&PostParams{
OwnedPostParams: OwnedPostParams{
ID: p.ID,
Token: token,
},
Content: "Now it's been updated!",
})
if err != nil {
t.Errorf("Post update failed: %v", err)
return
}
t.Logf("Post updated: %+v", p)
// Delete post
err = wac.DeletePost(&PostParams{
OwnedPostParams: OwnedPostParams{
ID: p.ID,
Token: token,
},
})
if err != nil {
t.Errorf("Post delete failed: %v", err)
return
}
t.Logf("Post deleted!")
}
func TestGetPost(t *testing.T) {
dwac := NewDevClient()
res, err := dwac.GetPost("zekk5r9apum6p")
if err != nil {
t.Errorf("Unexpected fetch results: %+v, err: %v\n", res, err)
} else {
t.Logf("Post: %+v", res)
if res.Content != "This is a post." {
t.Errorf("Unexpected fetch results: %+v\n", res)
}
}
wac := NewClient()
res, err = wac.GetPost("3psnxyhqxy3hq")
if err != nil {
t.Errorf("Unexpected fetch results: %+v, err: %v\n", res, err)
} else {
if !strings.HasPrefix(res.Content, " Write.as Blog") {
t.Errorf("Unexpected fetch results: %+v\n", res)
}
}
}
+func TestPinPost(t *testing.T) {
+ dwac := NewDevClient()
+ _, err := dwac.LogIn("demo", "demo")
+ if err != nil {
+ t.Fatalf("Unable to log in: %v", err)
+ }
+ defer dwac.LogOut()
+
+ err = dwac.PinPost("tester", &PinnedPostParams{ID: "olx6uk7064heqltf"})
+ if err != nil {
+ t.Fatalf("Pin failed: %v", err)
+ }
+}
+
func ExampleClient_CreatePost() {
c := NewClient()
// Publish a post
p, err := c.CreatePost(&PostParams{
Title: "Title!",
Content: "This is a post.",
Font: "sans",
})
if err != nil {
fmt.Printf("Unable to create: %v", err)
return
}
fmt.Printf("%s", p.Content)
// Output: This is a post.
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, May 16, 6:44 PM (11 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3240374
Attached To
rWGO writeas-go
Event Timeline
Log In to Comment