6 |
6 |
7 package madon |
7 package madon |
8 |
8 |
9 import ( |
9 import ( |
10 "fmt" |
10 "fmt" |
11 "strconv" |
|
12 |
11 |
13 "github.com/pkg/errors" |
12 "github.com/pkg/errors" |
14 "github.com/sendgrid/rest" |
13 "github.com/sendgrid/rest" |
15 ) |
14 ) |
16 |
15 |
17 // PostStatusParams contains option fields for the PostStatus command |
16 // PostStatusParams contains option fields for the PostStatus command |
18 type PostStatusParams struct { |
17 type PostStatusParams struct { |
19 Text string |
18 Text string |
20 InReplyTo int64 |
19 InReplyTo ActivityID |
21 MediaIDs []int64 |
20 MediaIDs []ActivityID |
22 Sensitive bool |
21 Sensitive bool |
23 SpoilerText string |
22 SpoilerText string |
24 Visibility string |
23 Visibility string |
25 } |
24 } |
26 |
25 |
27 // updateStatusOptions contains option fields for POST and DELETE API calls |
26 // updateStatusOptions contains option fields for POST and DELETE API calls |
28 type updateStatusOptions struct { |
27 type updateStatusOptions struct { |
29 // The ID is used for most commands |
28 // The ID is used for most commands |
30 ID int64 |
29 ID ActivityID |
31 |
30 |
32 // The following fields are used for posting a new status |
31 // The following fields are used for posting a new status |
33 Status string |
32 Status string |
34 InReplyToID int64 |
33 InReplyToID ActivityID |
35 MediaIDs []int64 |
34 MediaIDs []ActivityID |
36 Sensitive bool |
35 Sensitive bool |
37 SpoilerText string |
36 SpoilerText string |
38 Visibility string // "direct", "private", "unlisted" or "public" |
37 Visibility string // "direct", "private", "unlisted" or "public" |
39 } |
38 } |
40 |
39 |
64 |
63 |
65 // queryStatusData queries the statuses API |
64 // queryStatusData queries the statuses API |
66 // The operation 'op' can be empty or "status" (the status itself), "context", |
65 // The operation 'op' can be empty or "status" (the status itself), "context", |
67 // "card", "reblogged_by", "favourited_by". |
66 // "card", "reblogged_by", "favourited_by". |
68 // The data argument will receive the object(s) returned by the API server. |
67 // The data argument will receive the object(s) returned by the API server. |
69 func (mc *Client) queryStatusData(statusID int64, op string, data interface{}) error { |
68 func (mc *Client) queryStatusData(statusID ActivityID, op string, data interface{}) error { |
70 if statusID < 1 { |
69 if statusID == "" { |
71 return ErrInvalidID |
70 return ErrInvalidID |
72 } |
71 } |
73 |
72 |
74 endPoint := "statuses/" + strconv.FormatInt(statusID, 10) |
73 endPoint := "statuses/" + statusID |
75 |
74 |
76 if op != "" && op != "status" { |
75 if op != "" && op != "status" { |
77 switch op { |
76 switch op { |
78 case "context", "card", "reblogged_by", "favourited_by": |
77 case "context", "card", "reblogged_by", "favourited_by": |
79 default: |
78 default: |
111 if len(opts.MediaIDs) > 4 { |
110 if len(opts.MediaIDs) > 4 { |
112 return errors.New("too many (>4) media IDs") |
111 return errors.New("too many (>4) media IDs") |
113 } |
112 } |
114 case "delete": |
113 case "delete": |
115 method = rest.Delete |
114 method = rest.Delete |
116 if opts.ID < 1 { |
115 if opts.ID == "" { |
117 return ErrInvalidID |
116 return ErrInvalidID |
118 } |
117 } |
119 endPoint += "/" + strconv.FormatInt(opts.ID, 10) |
118 endPoint += "/" + opts.ID |
120 case "reblog", "unreblog", "favourite", "unfavourite": |
119 case "reblog", "unreblog", "favourite", "unfavourite": |
121 if opts.ID < 1 { |
120 if opts.ID == "" { |
122 return ErrInvalidID |
121 return ErrInvalidID |
123 } |
122 } |
124 endPoint += "/" + strconv.FormatInt(opts.ID, 10) + "/" + op |
123 endPoint += "/" + opts.ID + "/" + op |
125 case "mute", "unmute", "pin", "unpin": |
124 case "mute", "unmute", "pin", "unpin": |
126 if opts.ID < 1 { |
125 if opts.ID == "" { |
127 return ErrInvalidID |
126 return ErrInvalidID |
128 } |
127 } |
129 endPoint += "/" + strconv.FormatInt(opts.ID, 10) + "/" + op |
128 endPoint += "/" + opts.ID + "/" + op |
130 default: |
129 default: |
131 return ErrInvalidParameter |
130 return ErrInvalidParameter |
132 } |
131 } |
133 |
132 |
134 // Form items for a new toot |
133 // Form items for a new toot |
135 if op == "status" { |
134 if op == "status" { |
136 params["status"] = opts.Status |
135 params["status"] = opts.Status |
137 if opts.InReplyToID > 0 { |
136 if opts.InReplyToID != "" { |
138 params["in_reply_to_id"] = strconv.FormatInt(opts.InReplyToID, 10) |
137 params["in_reply_to_id"] = opts.InReplyToID |
139 } |
138 } |
140 for i, id := range opts.MediaIDs { |
139 for i, id := range opts.MediaIDs { |
141 if id < 1 { |
140 if id == "" { |
142 return ErrInvalidID |
141 return ErrInvalidID |
143 } |
142 } |
144 qID := fmt.Sprintf("[%d]media_ids", i) |
143 qID := fmt.Sprintf("[%d]media_ids", i) |
145 params[qID] = strconv.FormatInt(id, 10) |
144 params[qID] = id |
146 } |
145 } |
147 if opts.Sensitive { |
146 if opts.Sensitive { |
148 params["sensitive"] = "true" |
147 params["sensitive"] = "true" |
149 } |
148 } |
150 if opts.SpoilerText != "" { |
149 if opts.SpoilerText != "" { |
159 } |
158 } |
160 |
159 |
161 // GetStatus returns a status |
160 // GetStatus returns a status |
162 // The returned status can be nil if there is an error or if the |
161 // The returned status can be nil if there is an error or if the |
163 // requested ID does not exist. |
162 // requested ID does not exist. |
164 func (mc *Client) GetStatus(statusID int64) (*Status, error) { |
163 func (mc *Client) GetStatus(statusID ActivityID) (*Status, error) { |
165 var status Status |
164 var status Status |
166 |
165 |
167 if err := mc.queryStatusData(statusID, "status", &status); err != nil { |
166 if err := mc.queryStatusData(statusID, "status", &status); err != nil { |
168 return nil, err |
167 return nil, err |
169 } |
168 } |
170 if status.ID == 0 { |
169 if status.ID == "" { |
171 return nil, ErrEntityNotFound |
170 return nil, ErrEntityNotFound |
172 } |
171 } |
173 return &status, nil |
172 return &status, nil |
174 } |
173 } |
175 |
174 |
176 // GetStatusContext returns a status context |
175 // GetStatusContext returns a status context |
177 func (mc *Client) GetStatusContext(statusID int64) (*Context, error) { |
176 func (mc *Client) GetStatusContext(statusID ActivityID) (*Context, error) { |
178 var context Context |
177 var context Context |
179 if err := mc.queryStatusData(statusID, "context", &context); err != nil { |
178 if err := mc.queryStatusData(statusID, "context", &context); err != nil { |
180 return nil, err |
179 return nil, err |
181 } |
180 } |
182 return &context, nil |
181 return &context, nil |
183 } |
182 } |
184 |
183 |
185 // GetStatusCard returns a status card |
184 // GetStatusCard returns a status card |
186 func (mc *Client) GetStatusCard(statusID int64) (*Card, error) { |
185 func (mc *Client) GetStatusCard(statusID ActivityID) (*Card, error) { |
187 var card Card |
186 var card Card |
188 if err := mc.queryStatusData(statusID, "card", &card); err != nil { |
187 if err := mc.queryStatusData(statusID, "card", &card); err != nil { |
189 return nil, err |
188 return nil, err |
190 } |
189 } |
191 return &card, nil |
190 return &card, nil |
192 } |
191 } |
193 |
192 |
194 // GetStatusRebloggedBy returns a list of the accounts who reblogged a status |
193 // GetStatusRebloggedBy returns a list of the accounts who reblogged a status |
195 func (mc *Client) GetStatusRebloggedBy(statusID int64, lopt *LimitParams) ([]Account, error) { |
194 func (mc *Client) GetStatusRebloggedBy(statusID ActivityID, lopt *LimitParams) ([]Account, error) { |
196 o := &getAccountsOptions{ID: statusID, Limit: lopt} |
195 o := &getAccountsOptions{ID: statusID, Limit: lopt} |
197 return mc.getMultipleAccountsHelper("reblogged_by", o) |
196 return mc.getMultipleAccountsHelper("reblogged_by", o) |
198 } |
197 } |
199 |
198 |
200 // GetStatusFavouritedBy returns a list of the accounts who favourited a status |
199 // GetStatusFavouritedBy returns a list of the accounts who favourited a status |
201 func (mc *Client) GetStatusFavouritedBy(statusID int64, lopt *LimitParams) ([]Account, error) { |
200 func (mc *Client) GetStatusFavouritedBy(statusID ActivityID, lopt *LimitParams) ([]Account, error) { |
202 o := &getAccountsOptions{ID: statusID, Limit: lopt} |
201 o := &getAccountsOptions{ID: statusID, Limit: lopt} |
203 return mc.getMultipleAccountsHelper("favourited_by", o) |
202 return mc.getMultipleAccountsHelper("favourited_by", o) |
204 } |
203 } |
205 |
204 |
206 // PostStatus posts a new "toot" |
205 // PostStatus posts a new "toot" |
219 |
218 |
220 err := mc.updateStatusData("status", o, &status) |
219 err := mc.updateStatusData("status", o, &status) |
221 if err != nil { |
220 if err != nil { |
222 return nil, err |
221 return nil, err |
223 } |
222 } |
224 if status.ID == 0 { |
223 if status.ID == "" { |
225 return nil, ErrEntityNotFound // TODO Change error message |
224 return nil, ErrEntityNotFound // TODO Change error message |
226 } |
225 } |
227 return &status, err |
226 return &status, err |
228 } |
227 } |
229 |
228 |
230 // DeleteStatus deletes a status |
229 // DeleteStatus deletes a status |
231 func (mc *Client) DeleteStatus(statusID int64) error { |
230 func (mc *Client) DeleteStatus(statusID ActivityID) error { |
232 var status Status |
231 var status Status |
233 o := updateStatusOptions{ID: statusID} |
232 o := updateStatusOptions{ID: statusID} |
234 err := mc.updateStatusData("delete", o, &status) |
233 err := mc.updateStatusData("delete", o, &status) |
235 return err |
234 return err |
236 } |
235 } |
237 |
236 |
238 // ReblogStatus reblogs a status |
237 // ReblogStatus reblogs a status |
239 func (mc *Client) ReblogStatus(statusID int64) error { |
238 func (mc *Client) ReblogStatus(statusID ActivityID) error { |
240 var status Status |
239 var status Status |
241 o := updateStatusOptions{ID: statusID} |
240 o := updateStatusOptions{ID: statusID} |
242 err := mc.updateStatusData("reblog", o, &status) |
241 err := mc.updateStatusData("reblog", o, &status) |
243 return err |
242 return err |
244 } |
243 } |
245 |
244 |
246 // UnreblogStatus unreblogs a status |
245 // UnreblogStatus unreblogs a status |
247 func (mc *Client) UnreblogStatus(statusID int64) error { |
246 func (mc *Client) UnreblogStatus(statusID ActivityID) error { |
248 var status Status |
247 var status Status |
249 o := updateStatusOptions{ID: statusID} |
248 o := updateStatusOptions{ID: statusID} |
250 err := mc.updateStatusData("unreblog", o, &status) |
249 err := mc.updateStatusData("unreblog", o, &status) |
251 return err |
250 return err |
252 } |
251 } |
253 |
252 |
254 // FavouriteStatus favourites a status |
253 // FavouriteStatus favourites a status |
255 func (mc *Client) FavouriteStatus(statusID int64) error { |
254 func (mc *Client) FavouriteStatus(statusID ActivityID) error { |
256 var status Status |
255 var status Status |
257 o := updateStatusOptions{ID: statusID} |
256 o := updateStatusOptions{ID: statusID} |
258 err := mc.updateStatusData("favourite", o, &status) |
257 err := mc.updateStatusData("favourite", o, &status) |
259 return err |
258 return err |
260 } |
259 } |
261 |
260 |
262 // UnfavouriteStatus unfavourites a status |
261 // UnfavouriteStatus unfavourites a status |
263 func (mc *Client) UnfavouriteStatus(statusID int64) error { |
262 func (mc *Client) UnfavouriteStatus(statusID ActivityID) error { |
264 var status Status |
263 var status Status |
265 o := updateStatusOptions{ID: statusID} |
264 o := updateStatusOptions{ID: statusID} |
266 err := mc.updateStatusData("unfavourite", o, &status) |
265 err := mc.updateStatusData("unfavourite", o, &status) |
267 return err |
266 return err |
268 } |
267 } |
269 |
268 |
270 // PinStatus pins a status |
269 // PinStatus pins a status |
271 func (mc *Client) PinStatus(statusID int64) error { |
270 func (mc *Client) PinStatus(statusID ActivityID) error { |
272 var status Status |
271 var status Status |
273 o := updateStatusOptions{ID: statusID} |
272 o := updateStatusOptions{ID: statusID} |
274 err := mc.updateStatusData("pin", o, &status) |
273 err := mc.updateStatusData("pin", o, &status) |
275 return err |
274 return err |
276 } |
275 } |
277 |
276 |
278 // UnpinStatus unpins a status |
277 // UnpinStatus unpins a status |
279 func (mc *Client) UnpinStatus(statusID int64) error { |
278 func (mc *Client) UnpinStatus(statusID ActivityID) error { |
280 var status Status |
279 var status Status |
281 o := updateStatusOptions{ID: statusID} |
280 o := updateStatusOptions{ID: statusID} |
282 err := mc.updateStatusData("unpin", o, &status) |
281 err := mc.updateStatusData("unpin", o, &status) |
283 return err |
282 return err |
284 } |
283 } |
285 |
284 |
286 // MuteConversation mutes the conversation containing a status |
285 // MuteConversation mutes the conversation containing a status |
287 func (mc *Client) MuteConversation(statusID int64) (*Status, error) { |
286 func (mc *Client) MuteConversation(statusID ActivityID) (*Status, error) { |
288 var status Status |
287 var status Status |
289 o := updateStatusOptions{ID: statusID} |
288 o := updateStatusOptions{ID: statusID} |
290 err := mc.updateStatusData("mute", o, &status) |
289 err := mc.updateStatusData("mute", o, &status) |
291 return &status, err |
290 return &status, err |
292 } |
291 } |
293 |
292 |
294 // UnmuteConversation unmutes the conversation containing a status |
293 // UnmuteConversation unmutes the conversation containing a status |
295 func (mc *Client) UnmuteConversation(statusID int64) (*Status, error) { |
294 func (mc *Client) UnmuteConversation(statusID ActivityID) (*Status, error) { |
296 var status Status |
295 var status Status |
297 o := updateStatusOptions{ID: statusID} |
296 o := updateStatusOptions{ID: statusID} |
298 err := mc.updateStatusData("unmute", o, &status) |
297 err := mc.updateStatusData("unmute", o, &status) |
299 return &status, err |
298 return &status, err |
300 } |
299 } |