Initial commit
[bloat] / mastodon / accounts.go
1 package mastodon
2
3 import (
4         "context"
5         "fmt"
6         "net/http"
7         "net/url"
8         "strconv"
9         "time"
10 )
11
12 // Account hold information for mastodon account.
13 type Account struct {
14         ID             string    `json:"id"`
15         Username       string    `json:"username"`
16         Acct           string    `json:"acct"`
17         DisplayName    string    `json:"display_name"`
18         Locked         bool      `json:"locked"`
19         CreatedAt      time.Time `json:"created_at"`
20         FollowersCount int64     `json:"followers_count"`
21         FollowingCount int64     `json:"following_count"`
22         StatusesCount  int64     `json:"statuses_count"`
23         Note           string    `json:"note"`
24         URL            string    `json:"url"`
25         Avatar         string    `json:"avatar"`
26         AvatarStatic   string    `json:"avatar_static"`
27         Header         string    `json:"header"`
28         HeaderStatic   string    `json:"header_static"`
29         Emojis         []Emoji   `json:"emojis"`
30         Moved          *Account  `json:"moved"`
31         Fields         []Field   `json:"fields"`
32         Bot            bool      `json:"bot"`
33 }
34
35 // Field is a Mastodon account profile field.
36 type Field struct {
37         Name       string    `json:"name"`
38         Value      string    `json:"value"`
39         VerifiedAt time.Time `json:"verified_at"`
40 }
41
42 // AccountSource is a Mastodon account profile field.
43 type AccountSource struct {
44         Privacy   *string  `json:"privacy"`
45         Sensitive *bool    `json:"sensitive"`
46         Language  *string  `json:"language"`
47         Note      *string  `json:"note"`
48         Fields    *[]Field `json:"fields"`
49 }
50
51 // GetAccount return Account.
52 func (c *Client) GetAccount(ctx context.Context, id string) (*Account, error) {
53         var account Account
54         err := c.doAPI(ctx, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s", url.PathEscape(string(id))), nil, &account, nil)
55         if err != nil {
56                 return nil, err
57         }
58         return &account, nil
59 }
60
61 // GetAccountCurrentUser return Account of current user.
62 func (c *Client) GetAccountCurrentUser(ctx context.Context) (*Account, error) {
63         var account Account
64         err := c.doAPI(ctx, http.MethodGet, "/api/v1/accounts/verify_credentials", nil, &account, nil)
65         if err != nil {
66                 return nil, err
67         }
68         return &account, nil
69 }
70
71 // Profile is a struct for updating profiles.
72 type Profile struct {
73         // If it is nil it will not be updated.
74         // If it is empty, update it with empty.
75         DisplayName *string
76         Note        *string
77         Locked      *bool
78         Fields      *[]Field
79         Source      *AccountSource
80
81         // Set the base64 encoded character string of the image.
82         Avatar string
83         Header string
84 }
85
86 // AccountUpdate updates the information of the current user.
87 func (c *Client) AccountUpdate(ctx context.Context, profile *Profile) (*Account, error) {
88         params := url.Values{}
89         if profile.DisplayName != nil {
90                 params.Set("display_name", *profile.DisplayName)
91         }
92         if profile.Note != nil {
93                 params.Set("note", *profile.Note)
94         }
95         if profile.Locked != nil {
96                 params.Set("locked", strconv.FormatBool(*profile.Locked))
97         }
98         if profile.Fields != nil {
99                 for idx, field := range *profile.Fields {
100                         params.Set(fmt.Sprintf("fields_attributes[%d][name]", idx), field.Name)
101                         params.Set(fmt.Sprintf("fields_attributes[%d][value]", idx), field.Value)
102                 }
103         }
104         if profile.Source != nil {
105                 if profile.Source.Privacy != nil {
106                         params.Set("source[privacy]", *profile.Source.Privacy)
107                 }
108                 if profile.Source.Sensitive != nil {
109                         params.Set("source[sensitive]", strconv.FormatBool(*profile.Source.Sensitive))
110                 }
111                 if profile.Source.Language != nil {
112                         params.Set("source[language]", *profile.Source.Language)
113                 }
114         }
115         if profile.Avatar != "" {
116                 params.Set("avatar", profile.Avatar)
117         }
118         if profile.Header != "" {
119                 params.Set("header", profile.Header)
120         }
121
122         var account Account
123         err := c.doAPI(ctx, http.MethodPatch, "/api/v1/accounts/update_credentials", params, &account, nil)
124         if err != nil {
125                 return nil, err
126         }
127         return &account, nil
128 }
129
130 // GetAccountStatuses return statuses by specified accuont.
131 func (c *Client) GetAccountStatuses(ctx context.Context, id string, pg *Pagination) ([]*Status, error) {
132         var statuses []*Status
133         err := c.doAPI(ctx, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/statuses", url.PathEscape(string(id))), nil, &statuses, pg)
134         if err != nil {
135                 return nil, err
136         }
137         return statuses, nil
138 }
139
140 // GetAccountFollowers return followers list.
141 func (c *Client) GetAccountFollowers(ctx context.Context, id string, pg *Pagination) ([]*Account, error) {
142         var accounts []*Account
143         err := c.doAPI(ctx, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/followers", url.PathEscape(string(id))), nil, &accounts, pg)
144         if err != nil {
145                 return nil, err
146         }
147         return accounts, nil
148 }
149
150 // GetAccountFollowing return following list.
151 func (c *Client) GetAccountFollowing(ctx context.Context, id string, pg *Pagination) ([]*Account, error) {
152         var accounts []*Account
153         err := c.doAPI(ctx, http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/following", url.PathEscape(string(id))), nil, &accounts, pg)
154         if err != nil {
155                 return nil, err
156         }
157         return accounts, nil
158 }
159
160 // GetBlocks return block list.
161 func (c *Client) GetBlocks(ctx context.Context, pg *Pagination) ([]*Account, error) {
162         var accounts []*Account
163         err := c.doAPI(ctx, http.MethodGet, "/api/v1/blocks", nil, &accounts, pg)
164         if err != nil {
165                 return nil, err
166         }
167         return accounts, nil
168 }
169
170 // Relationship hold information for relation-ship to the account.
171 type Relationship struct {
172         ID                  string `json:"id"`
173         Following           bool   `json:"following"`
174         FollowedBy          bool   `json:"followed_by"`
175         Blocking            bool   `json:"blocking"`
176         Muting              bool   `json:"muting"`
177         MutingNotifications bool   `json:"muting_notifications"`
178         Requested           bool   `json:"requested"`
179         DomainBlocking      bool   `json:"domain_blocking"`
180         ShowingReblogs      bool   `json:"showing_reblogs"`
181         Endorsed            bool   `json:"endorsed"`
182 }
183
184 // AccountFollow follow the account.
185 func (c *Client) AccountFollow(ctx context.Context, id string) (*Relationship, error) {
186         var relationship Relationship
187         err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/follow", url.PathEscape(string(id))), nil, &relationship, nil)
188         if err != nil {
189                 return nil, err
190         }
191         return &relationship, nil
192 }
193
194 // AccountUnfollow unfollow the account.
195 func (c *Client) AccountUnfollow(ctx context.Context, id string) (*Relationship, error) {
196         var relationship Relationship
197         err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/unfollow", url.PathEscape(string(id))), nil, &relationship, nil)
198         if err != nil {
199                 return nil, err
200         }
201         return &relationship, nil
202 }
203
204 // AccountBlock block the account.
205 func (c *Client) AccountBlock(ctx context.Context, id string) (*Relationship, error) {
206         var relationship Relationship
207         err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/block", url.PathEscape(string(id))), nil, &relationship, nil)
208         if err != nil {
209                 return nil, err
210         }
211         return &relationship, nil
212 }
213
214 // AccountUnblock unblock the account.
215 func (c *Client) AccountUnblock(ctx context.Context, id string) (*Relationship, error) {
216         var relationship Relationship
217         err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/unblock", url.PathEscape(string(id))), nil, &relationship, nil)
218         if err != nil {
219                 return nil, err
220         }
221         return &relationship, nil
222 }
223
224 // AccountMute mute the account.
225 func (c *Client) AccountMute(ctx context.Context, id string) (*Relationship, error) {
226         var relationship Relationship
227         err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/mute", url.PathEscape(string(id))), nil, &relationship, nil)
228         if err != nil {
229                 return nil, err
230         }
231         return &relationship, nil
232 }
233
234 // AccountUnmute unmute the account.
235 func (c *Client) AccountUnmute(ctx context.Context, id string) (*Relationship, error) {
236         var relationship Relationship
237         err := c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/unmute", url.PathEscape(string(id))), nil, &relationship, nil)
238         if err != nil {
239                 return nil, err
240         }
241         return &relationship, nil
242 }
243
244 // GetAccountRelationships return relationship for the account.
245 func (c *Client) GetAccountRelationships(ctx context.Context, ids []string) ([]*Relationship, error) {
246         params := url.Values{}
247         for _, id := range ids {
248                 params.Add("id[]", id)
249         }
250
251         var relationships []*Relationship
252         err := c.doAPI(ctx, http.MethodGet, "/api/v1/accounts/relationships", params, &relationships, nil)
253         if err != nil {
254                 return nil, err
255         }
256         return relationships, nil
257 }
258
259 // AccountsSearch search accounts by query.
260 func (c *Client) AccountsSearch(ctx context.Context, q string, limit int64) ([]*Account, error) {
261         params := url.Values{}
262         params.Set("q", q)
263         params.Set("limit", fmt.Sprint(limit))
264
265         var accounts []*Account
266         err := c.doAPI(ctx, http.MethodGet, "/api/v1/accounts/search", params, &accounts, nil)
267         if err != nil {
268                 return nil, err
269         }
270         return accounts, nil
271 }
272
273 // FollowRemoteUser send follow-request.
274 func (c *Client) FollowRemoteUser(ctx context.Context, uri string) (*Account, error) {
275         params := url.Values{}
276         params.Set("uri", uri)
277
278         var account Account
279         err := c.doAPI(ctx, http.MethodPost, "/api/v1/follows", params, &account, nil)
280         if err != nil {
281                 return nil, err
282         }
283         return &account, nil
284 }
285
286 // GetFollowRequests return follow-requests.
287 func (c *Client) GetFollowRequests(ctx context.Context, pg *Pagination) ([]*Account, error) {
288         var accounts []*Account
289         err := c.doAPI(ctx, http.MethodGet, "/api/v1/follow_requests", nil, &accounts, pg)
290         if err != nil {
291                 return nil, err
292         }
293         return accounts, nil
294 }
295
296 // FollowRequestAuthorize is authorize the follow request of user with id.
297 func (c *Client) FollowRequestAuthorize(ctx context.Context, id string) error {
298         return c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/follow_requests/%s/authorize", url.PathEscape(string(id))), nil, nil, nil)
299 }
300
301 // FollowRequestReject is rejects the follow request of user with id.
302 func (c *Client) FollowRequestReject(ctx context.Context, id string) error {
303         return c.doAPI(ctx, http.MethodPost, fmt.Sprintf("/api/v1/follow_requests/%s/reject", url.PathEscape(string(id))), nil, nil, nil)
304 }
305
306 // GetMutes returns the list of users muted by the current user.
307 func (c *Client) GetMutes(ctx context.Context, pg *Pagination) ([]*Account, error) {
308         var accounts []*Account
309         err := c.doAPI(ctx, http.MethodGet, "/api/v1/mutes", nil, &accounts, pg)
310         if err != nil {
311                 return nil, err
312         }
313         return accounts, nil
314 }