--- a/account.go Sat Apr 15 00:39:43 2017 +0200
+++ b/account.go Sat Apr 15 10:26:36 2017 +0200
@@ -1,7 +1,6 @@
package gondole
import (
- "encoding/json"
"fmt"
"strconv"
@@ -19,110 +18,75 @@
}
// getSingleAccount returns an account entity
-// The target can be "account", "verify_credentials", "follow", "unfollow",
-// "block", "unblock", "mute", "unmute", "follow_requests/authorize" or
-// "follow_requests/reject".
-// The id is optional and depends on the target.
-func (g *Client) getSingleAccount(target string, id int) (*Account, error) {
+// The operation 'op' can be "account", "verify_credentials", "follow",
+// "unfollow", "block", "unblock", "mute", "unmute",
+// "follow_requests/authorize" or // "follow_requests/reject".
+// The id is optional and depends on the operation.
+func (g *Client) getSingleAccount(op string, id int) (*Account, error) {
var endPoint string
method := rest.Get
strID := strconv.Itoa(id)
- switch target {
+ switch op {
case "account":
endPoint = "accounts/" + strID
case "verify_credentials":
endPoint = "accounts/verify_credentials"
case "follow", "unfollow", "block", "unblock", "mute", "unmute":
- endPoint = "accounts/" + strID + "/" + target
+ endPoint = "accounts/" + strID + "/" + op
method = rest.Post
case "follow_requests/authorize", "follow_requests/reject":
// The documentation is incorrect, the endpoint actually
// is "follow_requests/:id/{authorize|reject}"
- endPoint = target[:16] + strID + "/" + target[16:]
+ endPoint = op[:16] + strID + "/" + op[16:]
method = rest.Post
default:
return nil, ErrInvalidParameter
}
- req := g.prepareRequest(endPoint)
- req.Method = method
-
- r, err := rest.API(req)
- if err != nil {
- return nil, fmt.Errorf("getAccount (%s): %s", target, err.Error())
- }
-
- // Check for error reply
- var errorResult Error
- if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
- // The empty object is not an error
- if errorResult.Text != "" {
- return nil, fmt.Errorf("%s", errorResult.Text)
- }
- }
-
- // Not an error reply; let's unmarshal the data
var account Account
- err = json.Unmarshal([]byte(r.Body), &account)
- if err != nil {
- return nil, fmt.Errorf("getAccount (%s) API: %s", target, err.Error())
+ if err := g.apiCall(endPoint, method, nil, &account); err != nil {
+ return nil, err
}
return &account, nil
}
// getMultipleAccounts returns a list of account entities
-// The target can be "followers", "following", "search", "blocks", "mutes",
-// "follow_requests".
-// The id is optional and depends on the target.
-func (g *Client) getMultipleAccounts(target string, opts *getAccountsOptions) ([]Account, error) {
+// The operation 'op' can be "followers", "following", "search", "blocks",
+// "mutes", "follow_requests".
+// The id is optional and depends on the operation.
+func (g *Client) getMultipleAccounts(op string, opts *getAccountsOptions) ([]Account, error) {
var endPoint string
- switch target {
+
+ switch op {
case "followers", "following":
if opts == nil || opts.ID < 1 {
return []Account{}, ErrInvalidID
}
- endPoint = "accounts/" + strconv.Itoa(opts.ID) + "/" + target
+ endPoint = "accounts/" + strconv.Itoa(opts.ID) + "/" + op
case "follow_requests", "blocks", "mutes":
- endPoint = target
+ endPoint = op
case "search":
if opts == nil || opts.Q == "" {
return []Account{}, ErrInvalidParameter
}
- endPoint = "accounts/" + target
+ endPoint = "accounts/" + op
default:
return nil, ErrInvalidParameter
}
- req := g.prepareRequest(endPoint)
-
// Handle target-specific query parameters
- if target == "search" {
- req.QueryParams["q"] = opts.Q
+ params := make(apiCallParams)
+ if op == "search" {
+ params["q"] = opts.Q
if opts.Limit > 0 {
- req.QueryParams["limit"] = strconv.Itoa(opts.Limit)
+ params["limit"] = strconv.Itoa(opts.Limit)
}
}
- r, err := rest.API(req)
- if err != nil {
- return nil, fmt.Errorf("getAccount (%s): %s", target, err.Error())
- }
-
- // Check for error reply
- var errorResult Error
- if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
- // The empty object is not an error
- if errorResult.Text != "" {
- return nil, fmt.Errorf("%s", errorResult.Text)
- }
- }
-
- // Not an error reply; let's unmarshal the data
var accounts []Account
- err = json.Unmarshal([]byte(r.Body), &accounts)
- if err != nil {
- return nil, fmt.Errorf("getAccount (%s) API: %s", target, err.Error())
+ if err := g.apiCall(endPoint, rest.Get, params, &accounts); err != nil {
+ return nil, err
}
return accounts, nil
}
@@ -190,34 +154,18 @@
}
// FollowRemoteAccount follows a remote account
-// The parameter 'id' is a URI (username@domain).
-func (g *Client) FollowRemoteAccount(id string) (*Account, error) {
- if id == "" {
+// The parameter 'uri' is a URI (e.g. "username@domain").
+func (g *Client) FollowRemoteAccount(uri string) (*Account, error) {
+ if uri == "" {
return nil, ErrInvalidID
}
- req := g.prepareRequest("follows")
- req.Method = rest.Post
- req.QueryParams["uri"] = id
- r, err := rest.API(req)
- if err != nil {
- return nil, fmt.Errorf("FollowRemoteAccount: %s", err.Error())
- }
+ params := make(apiCallParams)
+ params["uri"] = uri
- // Check for error reply
- var errorResult Error
- if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
- // The empty object is not an error
- if errorResult.Text != "" {
- return nil, fmt.Errorf("%s", errorResult.Text)
- }
- }
-
- // Not an error reply; let's unmarshal the data
var account Account
- err = json.Unmarshal([]byte(r.Body), &account)
- if err != nil {
- return nil, fmt.Errorf("FollowRemoteAccount API: %s", err.Error())
+ if err := g.apiCall("follows", rest.Post, params, &account); err != nil {
+ return nil, err
}
if account.ID == 0 {
return nil, ErrEntityNotFound
@@ -302,38 +250,22 @@
return nil, ErrInvalidID
}
- req := g.prepareRequest("accounts/relationships")
-
if len(accountIDs) > 1 { // XXX
return nil, fmt.Errorf("accounts/relationships currently does not work with more than 1 ID")
}
- req.QueryParams["id"] = strconv.Itoa(accountIDs[0])
+
+ params := make(apiCallParams)
+ params["id"] = strconv.Itoa(accountIDs[0])
/*
for i, id := range accountIDList {
qID := fmt.Sprintf("id[%d]", i+1)
- req.QueryParams[qID] = strconv.Itoa(id)
+ params[qID] = strconv.Itoa(id)
}
*/
- r, err := rest.API(req)
- if err != nil {
- return nil, fmt.Errorf("GetAccountRelationships: %s", err.Error())
- }
-
- // Check for error reply
- var errorResult Error
- if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
- // The empty object is not an error
- if errorResult.Text != "" {
- return nil, fmt.Errorf("%s", errorResult.Text)
- }
- }
-
- // Not an error reply; let's unmarshal the data
var rl []Relationship
- err = json.Unmarshal([]byte(r.Body), &rl)
- if err != nil {
- return nil, fmt.Errorf("accounts/relationships API: %s", err.Error())
+ if err := g.apiCall("accounts/relationships", rest.Get, params, &rl); err != nil {
+ return nil, err
}
return rl, nil
}
@@ -347,34 +279,17 @@
}
endPoint := "accounts/" + strconv.Itoa(accountID) + "/" + "statuses"
- req := g.prepareRequest(endPoint)
-
+ params := make(apiCallParams)
if onlyMedia {
- req.QueryParams["only_media"] = "true"
+ params["only_media"] = "true"
}
if excludeReplies {
- req.QueryParams["exclude_replies"] = "true"
- }
-
- r, err := rest.API(req)
- if err != nil {
- return nil, fmt.Errorf("GetAccountStatuses: %s", err.Error())
+ params["exclude_replies"] = "true"
}
- // Check for error reply
- var errorResult Error
- if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
- // The empty object is not an error
- if errorResult.Text != "" {
- return nil, fmt.Errorf("%s", errorResult.Text)
- }
- }
-
- // Not an error reply; let's unmarshal the data
var sl []Status
- err = json.Unmarshal([]byte(r.Body), &sl)
- if err != nil {
- return nil, fmt.Errorf("accounts/statuses API: %s", err.Error())
+ if err := g.apiCall(endPoint, rest.Get, params, &sl); err != nil {
+ return nil, err
}
return sl, nil
}
--- a/app.go Sat Apr 15 00:39:43 2017 +0200
+++ b/app.go Sat Apr 15 10:26:36 2017 +0200
@@ -1,8 +1,6 @@
package gondole
import (
- "encoding/json"
- "log"
"net/url"
"strings"
@@ -37,30 +35,22 @@
InstanceURL: instanceURL,
}
- req := g.prepareRequest("apps")
+ params := make(apiCallParams)
+ params["client_name"] = name
+ params["scopes"] = strings.Join(scopes, " ")
if redirectURI != "" {
- req.QueryParams["redirect_uris"] = redirectURI
+ params["redirect_uris"] = redirectURI
} else {
- req.QueryParams["redirect_uris"] = NoRedirect
- }
- req.QueryParams["client_name"] = name
- req.QueryParams["scopes"] = strings.Join(scopes, " ")
- req.Method = rest.Post
-
- r, err := rest.API(req)
- if err != nil {
- log.Fatalf("error can not register app: %v", err)
+ params["redirect_uris"] = NoRedirect
}
- var resp registerApp
-
- err = json.Unmarshal([]byte(r.Body), &resp)
- if err != nil {
- log.Fatalf("error can not register app: %v", err)
+ var app registerApp
+ if err := g.apiCall("apps", rest.Post, params, &app); err != nil {
+ return nil, err
}
- g.ID = resp.ClientID
- g.Secret = resp.ClientSecret
+ g.ID = app.ClientID
+ g.Secret = app.ClientSecret
return
}
--- a/cmd/gondole-cli/main.go Sat Apr 15 00:39:43 2017 +0200
+++ b/cmd/gondole-cli/main.go Sat Apr 15 10:26:36 2017 +0200
@@ -108,6 +108,9 @@
}
instance, err = gondole.NewApp("gondole-cli", scopes, gondole.NoRedirect, instanceURL)
+ if err != nil {
+ log.Fatalf("error: can not register application:", err.Error())
+ }
server := &Server{
ID: instance.ID,
--- a/favourites.go Sat Apr 15 00:39:43 2017 +0200
+++ b/favourites.go Sat Apr 15 10:26:36 2017 +0200
@@ -1,32 +1,15 @@
package gondole
import (
- "encoding/json"
- "fmt"
-
"github.com/sendgrid/rest"
)
// GetFavourites returns the list of the user's favourites
func (g *Client) GetFavourites() ([]Status, error) {
var faves []Status
-
- req := g.prepareRequest("favourites")
- r, err := rest.API(req)
+ err := g.apiCall("favourites", rest.Get, nil, &faves)
if err != nil {
- return faves, fmt.Errorf("favourites API query: %s", err.Error())
+ return nil, err
}
-
- println(r.Body)
- err = json.Unmarshal([]byte(r.Body), &faves)
- if err != nil {
- var errorRes Error
- err2 := json.Unmarshal([]byte(r.Body), &errorRes)
- if err2 == nil {
- return faves, fmt.Errorf("%s", errorRes.Text)
- }
- return faves, fmt.Errorf("favourites API: %s", err.Error())
- }
-
return faves, nil
}
--- a/gondole.go Sat Apr 15 00:39:43 2017 +0200
+++ b/gondole.go Sat Apr 15 10:26:36 2017 +0200
@@ -1,12 +1,16 @@
package gondole
import (
+ "encoding/json"
"errors"
"fmt"
"github.com/sendgrid/rest"
)
+// apiCallParams is a map with the parameters for an API call
+type apiCallParams map[string]string
+
const (
// GondoleVersion contains the version of the Gondole implementation
GondoleVersion = "0.0"
@@ -27,16 +31,12 @@
ErrInvalidID = errors.New("incorrect entity ID")
)
-// prepareRequest insert all pre-defined stuff
-func (g *Client) prepareRequest(what string) (req rest.Request) {
- var endPoint string
+// prepareRequest inserts all pre-defined stuff
+func (g *Client) prepareRequest(target string, method rest.Method, params apiCallParams) (req rest.Request) {
+ endPoint := g.APIBase + "/" + target
- endPoint = g.APIBase + "/" + what
- // Add at least one option, the APIkey if present
+ // Request headers
hdrs := make(map[string]string)
- opts := make(map[string]string)
-
- // Insert our sig
hdrs["User-Agent"] = fmt.Sprintf("Gondole/%s", GondoleVersion)
if g.userToken != nil {
hdrs["Authorization"] = fmt.Sprintf("Bearer %s", g.userToken.AccessToken)
@@ -45,7 +45,36 @@
req = rest.Request{
BaseURL: endPoint,
Headers: hdrs,
- QueryParams: opts,
+ Method: method,
+ QueryParams: params,
}
return
}
+
+// apiCall makes a call to the Mastodon API server
+func (g *Client) apiCall(endPoint string, method rest.Method, params apiCallParams, data interface{}) error {
+ // Prepare query
+ req := g.prepareRequest(endPoint, method, params)
+
+ // Make API call
+ r, err := rest.API(req)
+ if err != nil {
+ return fmt.Errorf("API query (%s) failed: %s", endPoint, err.Error())
+ }
+
+ // Check for error reply
+ var errorResult Error
+ if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
+ // The empty object is not an error
+ if errorResult.Text != "" {
+ return fmt.Errorf("%s", errorResult.Text)
+ }
+ }
+
+ // Not an error reply; let's unmarshal the data
+ err = json.Unmarshal([]byte(r.Body), &data)
+ if err != nil {
+ return fmt.Errorf("cannot decode API response (%s): %s", method, err.Error())
+ }
+ return nil
+}
--- a/gondole_test.go Sat Apr 15 00:39:43 2017 +0200
+++ b/gondole_test.go Sat Apr 15 10:26:36 2017 +0200
@@ -1,20 +1,20 @@
package gondole
import (
- "testing"
- "github.com/stretchr/testify/assert"
+ "testing"
+
+ "github.com/sendgrid/rest"
+ "github.com/stretchr/testify/assert"
)
func TestPrepareRequest(t *testing.T) {
- g := &Client{
- Name: "foo",
- ID: "666",
- Secret: "biiiip",
- APIBase: "http://example.com",
- }
+ g := &Client{
+ Name: "foo",
+ ID: "666",
+ Secret: "biiiip",
+ APIBase: "http://example.com",
+ }
- req := g.prepareRequest("bar")
- assert.NotNil(t, req.Headers, "not nil")
- assert.NotNil(t, req.QueryParams, "not nil")
+ req := g.prepareRequest("bar", rest.Get, nil)
+ assert.NotNil(t, req.Headers, "not nil")
}
-
--- a/instance.go Sat Apr 15 00:39:43 2017 +0200
+++ b/instance.go Sat Apr 15 10:26:36 2017 +0200
@@ -1,34 +1,14 @@
package gondole
import (
- "encoding/json"
- "fmt"
-
"github.com/sendgrid/rest"
)
// GetCurrentInstance returns current instance information
func (g *Client) GetCurrentInstance() (*Instance, error) {
- req := g.prepareRequest("instance")
- r, err := rest.API(req)
- if err != nil {
- return nil, fmt.Errorf("instance: %s", err.Error())
- }
-
- // Check for error reply
- var errorResult Error
- if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
- // The empty object is not an error
- if errorResult.Text != "" {
- return nil, fmt.Errorf("%s", errorResult.Text)
- }
- }
-
- // Not an error reply; let's unmarshal the data
var i Instance
- err = json.Unmarshal([]byte(r.Body), &i)
- if err != nil {
- return nil, fmt.Errorf("instance API: %s", err.Error())
+ if err := g.apiCall("instance", rest.Get, nil, &i); err != nil {
+ return nil, err
}
return &i, nil
}
--- a/notifications.go Sat Apr 15 00:39:43 2017 +0200
+++ b/notifications.go Sat Apr 15 10:26:36 2017 +0200
@@ -1,8 +1,6 @@
package gondole
import (
- "encoding/json"
- "fmt"
"strconv"
"github.com/sendgrid/rest"
@@ -11,23 +9,9 @@
// GetNotifications returns the list of the user's notifications
func (g *Client) GetNotifications() ([]Notification, error) {
var notifications []Notification
-
- req := g.prepareRequest("notifications")
- r, err := rest.API(req)
- if err != nil {
- return notifications, fmt.Errorf("notifications API query: %s", err.Error())
+ if err := g.apiCall("notifications", rest.Get, nil, ¬ifications); err != nil {
+ return nil, err
}
-
- err = json.Unmarshal([]byte(r.Body), ¬ifications)
- if err != nil {
- var errorRes Error
- err2 := json.Unmarshal([]byte(r.Body), &errorRes)
- if err2 == nil {
- return notifications, fmt.Errorf("%s", errorRes.Text)
- }
- return notifications, fmt.Errorf("notifications API: %s", err.Error())
- }
-
return notifications, nil
}
@@ -35,40 +19,23 @@
// The returned notification can be nil if there is an error or if the
// requested notification does not exist.
func (g *Client) GetNotification(id int) (*Notification, error) {
- var notification Notification
-
- req := g.prepareRequest("notifications/" + strconv.Itoa(id))
- r, err := rest.API(req)
- if err != nil {
- return ¬ification, fmt.Errorf("notification API query: %s", err.Error())
+ if id < 1 {
+ return nil, ErrInvalidID
}
- err = json.Unmarshal([]byte(r.Body), ¬ification)
- if err != nil {
- var errorRes Error
- err2 := json.Unmarshal([]byte(r.Body), &errorRes)
- if err2 == nil {
- return ¬ification, fmt.Errorf("%s", errorRes.Text)
- }
- return ¬ification, fmt.Errorf("notification API: %s", err.Error())
+ var endPoint = "notifications/" + strconv.Itoa(id)
+ var notification Notification
+ if err := g.apiCall(endPoint, rest.Get, nil, ¬ification); err != nil {
+ return nil, err
}
-
if notification.ID == 0 {
return nil, ErrEntityNotFound
}
-
return ¬ification, nil
}
// ClearNotifications deletes all notifications from the Mastodon server for
// the authenticated user
func (g *Client) ClearNotifications() error {
- req := g.prepareRequest("notifications/clear")
- req.Method = rest.Post
- _, err := rest.API(req)
- if err != nil {
- return fmt.Errorf("notifications/clear API query: %s", err.Error())
- }
-
- return nil // TODO: check returned object (should be empty)
+ return g.apiCall("notifications/clear", rest.Post, nil, &Notification{})
}
--- a/report.go Sat Apr 15 00:39:43 2017 +0200
+++ b/report.go Sat Apr 15 10:26:36 2017 +0200
@@ -1,8 +1,6 @@
package gondole
import (
- "encoding/json"
- "fmt"
"strconv"
"github.com/sendgrid/rest"
@@ -10,26 +8,9 @@
// GetReports returns the current user's reports
func (g *Client) GetReports() ([]Report, error) {
- req := g.prepareRequest("reports")
- r, err := rest.API(req)
- if err != nil {
- return nil, fmt.Errorf("reports: %s", err.Error())
- }
-
- // Check for error reply
- var errorResult Error
- if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
- // The empty object is not an error
- if errorResult.Text != "" {
- return nil, fmt.Errorf("%s", errorResult.Text)
- }
- }
-
- // Not an error reply; let's unmarshal the data
var reports []Report
- err = json.Unmarshal([]byte(r.Body), &reports)
- if err != nil {
- return nil, fmt.Errorf("reports API: %s", err.Error())
+ if err := g.apiCall("reports", rest.Get, nil, &reports); err != nil {
+ return nil, err
}
return reports, nil
}
@@ -41,32 +22,15 @@
return nil, ErrInvalidParameter
}
- req := g.prepareRequest("reports")
- req.Method = rest.Post
- req.QueryParams["account_id"] = strconv.Itoa(accountID)
+ params := make(apiCallParams)
+ params["account_id"] = strconv.Itoa(accountID)
// XXX Sending only the first one since I'm not sure arrays work
- req.QueryParams["status_ids"] = strconv.Itoa(statusIDs[0])
- req.QueryParams["comment"] = comment
-
- r, err := rest.API(req)
- if err != nil {
- return nil, fmt.Errorf("reports: %s", err.Error())
- }
+ params["status_ids"] = strconv.Itoa(statusIDs[0])
+ params["comment"] = comment
- // Check for error reply
- var errorResult Error
- if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
- // The empty object is not an error
- if errorResult.Text != "" {
- return nil, fmt.Errorf("%s", errorResult.Text)
- }
- }
-
- // Not an error reply; let's unmarshal the data
var report Report
- err = json.Unmarshal([]byte(r.Body), &report)
- if err != nil {
- return nil, fmt.Errorf("reports API: %s", err.Error())
+ if err := g.apiCall("reports", rest.Post, params, &report); err != nil {
+ return nil, err
}
return &report, nil
}
--- a/search.go Sat Apr 15 00:39:43 2017 +0200
+++ b/search.go Sat Apr 15 10:26:36 2017 +0200
@@ -1,9 +1,6 @@
package gondole
import (
- "encoding/json"
- "fmt"
-
"github.com/sendgrid/rest"
)
@@ -12,30 +9,16 @@
if query == "" {
return nil, ErrInvalidParameter
}
- req := g.prepareRequest("search")
- req.QueryParams["q"] = query
+
+ params := make(apiCallParams)
+ params["q"] = query
if resolve {
- req.QueryParams["resolve"] = "true"
- }
- r, err := rest.API(req)
- if err != nil {
- return nil, fmt.Errorf("search: %s", err.Error())
+ params["resolve"] = "true"
}
- // Check for error reply
- var errorResult Error
- if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
- // The empty object is not an error
- if errorResult.Text != "" {
- return nil, fmt.Errorf("%s", errorResult.Text)
- }
- }
-
- // Not an error reply; let's unmarshal the data
var results Results
- err = json.Unmarshal([]byte(r.Body), &results)
- if err != nil {
- return nil, fmt.Errorf("search API: %s", err.Error())
+ if err := g.apiCall("search", rest.Get, params, &results); err != nil {
+ return nil, err
}
return &results, nil
}
--- a/status.go Sat Apr 15 00:39:43 2017 +0200
+++ b/status.go Sat Apr 15 10:26:36 2017 +0200
@@ -1,7 +1,6 @@
package gondole
import (
- "encoding/json"
"fmt"
"strconv"
@@ -23,59 +22,41 @@
}
// queryStatusData queries the statuses API
-// The subquery can be empty or "status" (the status itself), "context",
+// The operation 'op' can be empty or "status" (the status itself), "context",
// "card", "reblogged_by", "favourited_by".
// The data argument will receive the object(s) returned by the API server.
-func (g *Client) queryStatusData(statusID int, subquery string, data interface{}) error {
- endPoint := "statuses/" + strconv.Itoa(statusID)
-
+func (g *Client) queryStatusData(statusID int, op string, data interface{}) error {
if statusID < 1 {
return ErrInvalidID
}
- if subquery != "" && subquery != "status" {
- switch subquery {
+ endPoint := "statuses/" + strconv.Itoa(statusID)
+
+ if op != "" && op != "status" {
+ switch op {
case "context", "card", "reblogged_by", "favourited_by":
default:
return ErrInvalidParameter
}
- endPoint += "/" + subquery
- }
- req := g.prepareRequest(endPoint)
- r, err := rest.API(req)
- if err != nil {
- return fmt.Errorf("status/%s API query: %s", subquery, err.Error())
+ endPoint += "/" + op
}
- // Check for error reply
- var errorResult Error
- if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
- // The empty object is not an error
- if errorResult.Text != "" {
- return fmt.Errorf("%s", errorResult.Text)
- }
- }
-
- // Not an error reply; let's unmarshal the data
- err = json.Unmarshal([]byte(r.Body), &data)
- if err != nil {
- return fmt.Errorf("status/%s API: %s", subquery, err.Error())
- }
- return nil
+ return g.apiCall(endPoint, rest.Get, nil, data)
}
// updateStatusData updates the statuses
-// The subquery can be empty or "status" (to post a status), "delete" (for
-// deleting a status), "reblog", "unreblog", "favourite", "unfavourite".
+// The operation 'op' can be empty or "status" (to post a status), "delete"
+// (for deleting a status), "reblog", "unreblog", "favourite", "unfavourite".
// The data argument will receive the object(s) returned by the API server.
-func (g *Client) updateStatusData(subquery string, opts updateStatusOptions, data interface{}) error {
+func (g *Client) updateStatusData(op string, opts updateStatusOptions, data interface{}) error {
method := rest.Post
endPoint := "statuses"
+ params := make(apiCallParams)
- switch subquery {
+ switch op {
case "", "status":
- subquery = "status"
+ op = "status"
if opts.Status == "" {
return ErrInvalidParameter
}
@@ -98,55 +79,33 @@
if opts.ID < 1 {
return ErrInvalidID
}
- endPoint += "/" + strconv.Itoa(opts.ID) + "/" + subquery
+ endPoint += "/" + strconv.Itoa(opts.ID) + "/" + op
default:
return ErrInvalidParameter
}
- req := g.prepareRequest(endPoint)
- req.Method = method
-
// Form items for a new toot
- if subquery == "status" {
- req.QueryParams["status"] = opts.Status
+ if op == "status" {
+ params["status"] = opts.Status
if opts.InReplyToID > 0 {
- req.QueryParams["in_reply_to_id"] = strconv.Itoa(opts.InReplyToID)
+ params["in_reply_to_id"] = strconv.Itoa(opts.InReplyToID)
}
for i, id := range opts.MediaIDs {
qID := fmt.Sprintf("media_ids[%d]", i+1)
- req.QueryParams[qID] = strconv.Itoa(id)
+ params[qID] = strconv.Itoa(id)
}
if opts.Sensitive {
- req.QueryParams["sensitive"] = "true"
+ params["sensitive"] = "true"
}
if opts.SpoilerText != "" {
- req.QueryParams["spoiler_text"] = opts.SpoilerText
+ params["spoiler_text"] = opts.SpoilerText
}
if opts.Visibility != "" {
- req.QueryParams["visibility"] = opts.Visibility
+ params["visibility"] = opts.Visibility
}
}
- r, err := rest.API(req)
- if err != nil {
- return fmt.Errorf("status/%s API query: %s", subquery, err.Error())
- }
-
- // Check for error reply
- var errorResult Error
- if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil {
- // The empty object is not an error
- if errorResult.Text != "" {
- return fmt.Errorf("%s", errorResult.Text)
- }
- }
-
- // Not an error reply; let's unmarshal the data
- err = json.Unmarshal([]byte(r.Body), &data)
- if err != nil {
- return fmt.Errorf("status/%s API: %s", subquery, err.Error())
- }
- return nil
+ return g.apiCall(endPoint, method, params, data)
}
// GetStatus returns a status
--- a/streams.go Sat Apr 15 00:39:43 2017 +0200
+++ b/streams.go Sat Apr 15 10:26:36 2017 +0200
@@ -28,7 +28,7 @@
// The stream name can be "user", "public" or "hashtag".
// For "hashtag", the hashTag argument cannot be empty.
func (g *Client) openStream(streamName, hashTag string) (*http.Response, error) {
- req := g.prepareRequest("streaming/" + streamName)
+ params := make(apiCallParams)
switch streamName {
case "user", "public":
@@ -36,15 +36,17 @@
if hashTag == "" {
return nil, ErrInvalidParameter
}
- req.QueryParams["tag"] = hashTag
+ params["tag"] = hashTag
default:
return nil, ErrInvalidParameter
}
+ req := g.prepareRequest("streaming/"+streamName, rest.Get, params)
reqObj, err := rest.BuildRequestObject(req)
if err != nil {
return nil, fmt.Errorf("cannot build stream request: %s", err.Error())
}
+
resp, err := rest.MakeRequest(reqObj)
if err != nil {
return nil, fmt.Errorf("cannot open stream: %s", err.Error())
--- a/timelines.go Sat Apr 15 00:39:43 2017 +0200
+++ b/timelines.go Sat Apr 15 10:26:36 2017 +0200
@@ -1,7 +1,6 @@
package gondole
import (
- "encoding/json"
"fmt"
"strings"
@@ -14,7 +13,6 @@
// local instance.
func (g *Client) GetTimelines(timeline string, local bool) ([]Status, error) {
var endPoint string
- var tl []Status
switch {
case timeline == "home", timeline == "public":
@@ -22,33 +20,21 @@
case strings.HasPrefix(timeline, ":"):
hashtag := timeline[1:]
if hashtag == "" {
- return tl, fmt.Errorf("timelines API: empty hashtag")
+ return nil, fmt.Errorf("timelines API: empty hashtag")
}
endPoint = "timelines/tag/" + hashtag
default:
- return tl, fmt.Errorf("GetTimelines: bad timelines argument")
- }
-
- req := g.prepareRequest(endPoint)
-
- if timeline == "public" && local {
- req.QueryParams["local"] = "true"
+ return nil, fmt.Errorf("GetTimelines: bad timelines argument")
}
- r, err := rest.API(req)
- if err != nil {
- return tl, fmt.Errorf("timelines API query: %s", err.Error())
+ params := make(apiCallParams)
+ if timeline == "public" && local {
+ params["local"] = "true"
}
- err = json.Unmarshal([]byte(r.Body), &tl)
- if err != nil {
- var errorRes Error
- err2 := json.Unmarshal([]byte(r.Body), &errorRes)
- if err2 == nil {
- return tl, fmt.Errorf("%s", errorRes.Text)
- }
- return tl, fmt.Errorf("timelines API: %s", err.Error())
+ var tl []Status
+ if err := g.apiCall(endPoint, rest.Get, params, &tl); err != nil {
+ return nil, err
}
-
return tl, nil
}