From 2af857818d3d1263b433e8a7784de52c0a3117a9 Mon Sep 17 00:00:00 2001 From: Yasuhiro Matsumoto Date: Fri, 14 Apr 2017 23:37:29 +0900 Subject: [PATCH] add some APIs for Accounts * AccountFollow * AccountUnfollow * AccountBlock * AccountUnblock * AccountMute * AccountUnmute * GetAccountRelationship * AccountsSearch --- accounts.go | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mastodon.go | 184 -------------------------------------------------- 2 files changed, 188 insertions(+), 184 deletions(-) create mode 100644 accounts.go diff --git a/accounts.go b/accounts.go new file mode 100644 index 0000000..a751642 --- /dev/null +++ b/accounts.go @@ -0,0 +1,188 @@ +package mastodon + +import ( + "fmt" + "net/url" + "time" +) + +// Account hold information for mastodon account. +type Account struct { + ID int64 `json:"id"` + Username string `json:"username"` + Acct string `json:"acct"` + DisplayName string `json:"display_name"` + Locked bool `json:"locked"` + CreatedAt time.Time `json:"created_at"` + FollowersCount int64 `json:"followers_count"` + FollowingCount int64 `json:"following_count"` + StatusesCount int64 `json:"statuses_count"` + Note string `json:"note"` + URL string `json:"url"` + Avatar string `json:"avatar"` + AvatarStatic string `json:"avatar_static"` + Header string `json:"header"` + HeaderStatic string `json:"header_static"` +} + +// GetAccount return Account. +func (c *Client) GetAccount(id int) (*Account, error) { + var account Account + err := c.doAPI("GET", fmt.Sprintf("/api/v1/accounts/%d", id), nil, &account) + if err != nil { + return nil, err + } + return &account, nil +} + +// GetAccountCurrentUser return Account of current user. +func (c *Client) GetAccountCurrentUser() (*Account, error) { + var account Account + err := c.doAPI("GET", "/api/v1/accounts/verify_credentials", nil, &account) + if err != nil { + return nil, err + } + return &account, nil +} + +// GetAccountFollowers return followers list. +func (c *Client) GetAccountFollowers(id int64) ([]*Account, error) { + var accounts []*Account + err := c.doAPI("GET", fmt.Sprintf("/api/v1/accounts/%d/followers", id), nil, &accounts) + if err != nil { + return nil, err + } + return accounts, nil +} + +// GetAccountFollowing return following list. +func (c *Client) GetAccountFollowing(id int64) ([]*Account, error) { + var accounts []*Account + err := c.doAPI("GET", fmt.Sprintf("/api/v1/accounts/%d/following", id), nil, &accounts) + if err != nil { + return nil, err + } + return accounts, nil +} + +// Relationship hold information for relation-ship to the account. +type Relationship struct { + Following bool `json:"following"` + FollowedBy bool `json:"followed_by"` + Blocking bool `json:"blocking"` + Muting bool `json:"muting"` + Requested bool `json:"requested"` +} + +// AccountFollow follow the account. +func (c *Client) AccountFollow(id int64) (*Relationship, error) { + var relationship Relationship + err := c.doAPI("POST", fmt.Sprintf("/api/v1/accounts/%d/follow", id), nil, &relationship) + if err != nil { + return nil, err + } + return &relationship, nil +} + +// AccountUnfollow unfollow the account. +func (c *Client) AccountUnfollow(id int64) (*Relationship, error) { + var relationship Relationship + err := c.doAPI("POST", fmt.Sprintf("/api/v1/accounts/%d/unfollow", id), nil, &relationship) + if err != nil { + return nil, err + } + return &relationship, nil +} + +// AccountBlock block the account. +func (c *Client) AccountBlock(id int64) (*Relationship, error) { + var relationship Relationship + err := c.doAPI("POST", fmt.Sprintf("/api/v1/accounts/%d/block", id), nil, &relationship) + if err != nil { + return nil, err + } + return &relationship, nil +} + +// AccountUnblock unblock the account. +func (c *Client) AccountUnblock(id int64) (*Relationship, error) { + var relationship Relationship + err := c.doAPI("POST", fmt.Sprintf("/api/v1/accounts/%d/unblock", id), nil, &relationship) + if err != nil { + return nil, err + } + return &relationship, nil +} + +// AccountMute mute the account. +func (c *Client) AccountMute(id int64) (*Relationship, error) { + var relationship Relationship + err := c.doAPI("POST", fmt.Sprintf("/api/v1/accounts/%d/mute", id), nil, &relationship) + if err != nil { + return nil, err + } + return &relationship, nil +} + +// AccountUnmute unmute the account. +func (c *Client) AccountUnmute(id int64) (*Relationship, error) { + var relationship Relationship + err := c.doAPI("POST", fmt.Sprintf("/api/v1/accounts/%d/unmute", id), nil, &relationship) + if err != nil { + return nil, err + } + return &relationship, nil +} + +// GetAccountRelationship return relationship for the account. +func (c *Client) GetAccountRelationship(id int64) ([]*Relationship, error) { + params := url.Values{} + params.Set("id", fmt.Sprint(id)) + + var relationships []*Relationship + err := c.doAPI("GET", "/api/v1/accounts/relationship", params, &relationships) + if err != nil { + return nil, err + } + return relationships, nil +} + +// AccountsSearch search accounts by query. +func (c *Client) AccountsSearch(q string, limit int64) ([]*Account, error) { + params := url.Values{} + params.Set("q", q) + params.Set("limit", fmt.Sprint(limit)) + + var accounts []*Account + err := c.doAPI("GET", "/api/v1/accounts/search", params, &accounts) + if err != nil { + return nil, err + } + return accounts, nil +} + +// Follow send follow-request. +func (c *Client) Follow(uri string) (*Account, error) { + params := url.Values{} + params.Set("uri", uri) + + var account Account + err := c.doAPI("POST", "/api/v1/follows", params, &account) + if err != nil { + return nil, err + } + return &account, nil +} + +// GetFollowRequests return follow-requests. +func (c *Client) GetFollowRequests(uri string) ([]*Account, error) { + params := url.Values{} + params.Set("uri", uri) + + var accounts []*Account + err := c.doAPI("GET", "/api/v1/follow_requests", params, &accounts) + if err != nil { + return nil, err + } + return accounts, nil +} diff --git a/mastodon.go b/mastodon.go index 77527a0..3b6f246 100644 --- a/mastodon.go +++ b/mastodon.go @@ -1,11 +1,8 @@ package mastodon import ( - "bufio" - "context" "encoding/json" "fmt" - "io" "net/http" "net/url" "path" @@ -172,25 +169,6 @@ func RegisterApp(appConfig *AppConfig) (*Application, error) { return &app, nil } -// Account hold information for mastodon account. -type Account struct { - ID int64 `json:"id"` - Username string `json:"username"` - Acct string `json:"acct"` - DisplayName string `json:"display_name"` - Locked bool `json:"locked"` - CreatedAt time.Time `json:"created_at"` - FollowersCount int64 `json:"followers_count"` - FollowingCount int64 `json:"following_count"` - StatusesCount int64 `json:"statuses_count"` - Note string `json:"note"` - URL string `json:"url"` - Avatar string `json:"avatar"` - AvatarStatic string `json:"avatar_static"` - Header string `json:"header"` - HeaderStatic string `json:"header_static"` -} - // Toot is struct to post status. type Toot struct { Status string `json:"status"` @@ -225,46 +203,6 @@ type Status struct { Reblogged interface{} `json:"reblogged"` } -// GetAccount return Account. -func (c *Client) GetAccount(id int) (*Account, error) { - var account Account - err := c.doAPI("GET", fmt.Sprintf("/api/v1/accounts/%d", id), nil, &account) - if err != nil { - return nil, err - } - return &account, nil -} - -// GetAccountCurrentUser return Account of current user. -func (c *Client) GetAccountCurrentUser() (*Account, error) { - var account Account - err := c.doAPI("GET", "/api/v1/accounts/verify_credentials", nil, &account) - if err != nil { - return nil, err - } - return &account, nil -} - -// GetAccountFollowers return followers list. -func (c *Client) GetAccountFollowers(id int64) ([]*Account, error) { - var accounts []*Account - err := c.doAPI("GET", fmt.Sprintf("/api/v1/accounts/%d/followers", id), nil, &accounts) - if err != nil { - return nil, err - } - return accounts, nil -} - -// GetAccountFollowing return following list. -func (c *Client) GetAccountFollowing(id int64) ([]*Account, error) { - var accounts []*Account - err := c.doAPI("GET", fmt.Sprintf("/api/v1/accounts/%d/following", id), nil, &accounts) - if err != nil { - return nil, err - } - return accounts, nil -} - // GetTimelineHome return statuses from home timeline. func (c *Client) GetTimelineHome() ([]*Status, error) { var statuses []*Status @@ -292,125 +230,3 @@ func (c *Client) PostStatus(toot *Toot) (*Status, error) { } return &status, nil } - -// UpdateEvent is struct for passing status event to app. -type UpdateEvent struct{ Status *Status } - -func (e *UpdateEvent) event() {} - -// NotificationEvent is struct for passing notification event to app. -type NotificationEvent struct{} - -func (e *NotificationEvent) event() {} - -// DeleteEvent is struct for passing deletion event to app. -type DeleteEvent struct{ ID int64 } - -func (e *DeleteEvent) event() {} - -// ErrorEvent is struct for passing errors to app. -type ErrorEvent struct{ err error } - -func (e *ErrorEvent) event() {} -func (e *ErrorEvent) Error() string { return e.err.Error() } - -// Event is interface passing events to app. -type Event interface { - event() -} - -func handleReader(ctx context.Context, q chan Event, r io.Reader) error { - name := "" - s := bufio.NewScanner(r) - for s.Scan() { - line := s.Text() - token := strings.SplitN(line, ":", 2) - if len(token) != 2 { - continue - } - switch strings.TrimSpace(token[0]) { - case "event": - name = strings.TrimSpace(token[1]) - case "data": - switch name { - case "update": - var status Status - err := json.Unmarshal([]byte(token[1]), &status) - if err == nil { - q <- &UpdateEvent{&status} - } - case "notification": - case "delete": - } - default: - } - } - return ctx.Err() -} - -// StreamingPublic return channel to read events. -func (c *Client) StreamingPublic(ctx context.Context) (chan Event, error) { - url, err := url.Parse(c.config.Server) - if err != nil { - return nil, err - } - url.Path = path.Join(url.Path, "/api/v1/streaming/public") - - var resp *http.Response - - q := make(chan Event, 10) - go func() { - defer ctx.Done() - - for { - req, err := http.NewRequest("GET", url.String(), nil) - if err == nil { - req.Header.Set("Authorization", "Bearer "+c.config.AccessToken) - resp, err = c.Do(req) - } - if err == nil { - err = handleReader(ctx, q, resp.Body) - resp.Body.Close() - if err == nil { - break - } - } else { - q <- &ErrorEvent{err} - } - time.Sleep(3 * time.Second) - } - }() - go func() { - <-ctx.Done() - if resp != nil && resp.Body != nil { - resp.Body.Close() - } - }() - return q, nil -} - -// Follow send follow-request. -func (c *Client) Follow(uri string) (*Account, error) { - params := url.Values{} - params.Set("uri", uri) - - var account Account - err := c.doAPI("POST", "/api/v1/follows", params, &account) - if err != nil { - return nil, err - } - return &account, nil -} - -// GetFollowRequests return follow-requests. -func (c *Client) GetFollowRequests(uri string) ([]*Account, error) { - params := url.Values{} - params.Set("uri", uri) - - var accounts []*Account - err := c.doAPI("GET", "/api/v1/follow_requests", params, &accounts) - if err != nil { - return nil, err - } - return accounts, nil -}