302 endPoint = "follow_requests/authorize" |
309 endPoint = "follow_requests/authorize" |
303 } |
310 } |
304 _, err := mc.getSingleAccount(endPoint, accountID) |
311 _, err := mc.getSingleAccount(endPoint, accountID) |
305 return err |
312 return err |
306 } |
313 } |
|
314 |
|
315 // UpdateAccount updates the connected user's account data |
|
316 // The fields avatar & headerImage can contain base64-encoded images; if |
|
317 // they do not (that is; if they don't contain ";base64,"), they are considered |
|
318 // as file paths and their content will be encoded. |
|
319 // All fields can be nil, in which case they are not updated. |
|
320 // displayName and note can be set to "" to delete previous values; |
|
321 // I'm not sure images can be deleted -- only replaced AFAICS. |
|
322 func (mc *Client) UpdateAccount(displayName, note, avatar, headerImage *string) (*Account, error) { |
|
323 const endPoint = "accounts/update_credentials" |
|
324 params := make(apiCallParams) |
|
325 |
|
326 if displayName != nil { |
|
327 params["display_name"] = *displayName |
|
328 } |
|
329 if note != nil { |
|
330 params["note"] = *note |
|
331 } |
|
332 |
|
333 var err error |
|
334 avatar, err = fileToBase64(avatar, nil) |
|
335 if err != nil { |
|
336 return nil, err |
|
337 } |
|
338 headerImage, err = fileToBase64(headerImage, nil) |
|
339 if err != nil { |
|
340 return nil, err |
|
341 } |
|
342 |
|
343 var formBuf bytes.Buffer |
|
344 w := multipart.NewWriter(&formBuf) |
|
345 |
|
346 if avatar != nil { |
|
347 w.WriteField("avatar", *avatar) |
|
348 } |
|
349 if headerImage != nil { |
|
350 w.WriteField("header", *headerImage) |
|
351 } |
|
352 w.Close() |
|
353 |
|
354 // Prepare the request |
|
355 req, err := mc.prepareRequest(endPoint, rest.Patch, params) |
|
356 if err != nil { |
|
357 return nil, fmt.Errorf("prepareRequest failed: %s", err.Error()) |
|
358 } |
|
359 req.Headers["Content-Type"] = w.FormDataContentType() |
|
360 req.Body = formBuf.Bytes() |
|
361 |
|
362 // Make API call |
|
363 r, err := restAPI(req) |
|
364 if err != nil { |
|
365 return nil, fmt.Errorf("account update failed: %s", err.Error()) |
|
366 } |
|
367 |
|
368 // Check for error reply |
|
369 var errorResult Error |
|
370 if err := json.Unmarshal([]byte(r.Body), &errorResult); err == nil { |
|
371 // The empty object is not an error |
|
372 if errorResult.Text != "" { |
|
373 return nil, fmt.Errorf("%s", errorResult.Text) |
|
374 } |
|
375 } |
|
376 |
|
377 // Not an error reply; let's unmarshal the data |
|
378 var account Account |
|
379 if err := json.Unmarshal([]byte(r.Body), &account); err != nil { |
|
380 return nil, fmt.Errorf("cannot decode API response: %s", err.Error()) |
|
381 } |
|
382 return &account, nil |
|
383 } |
|
384 |
|
385 // fileToBase64 is a helper function to convert a file's contents to |
|
386 // base64-encoded data. Is the data string already contains base64 data, it |
|
387 // is not modified. |
|
388 // If contentType is nil, it is detected. |
|
389 func fileToBase64(data, contentType *string) (*string, error) { |
|
390 if data == nil { |
|
391 return nil, nil |
|
392 } |
|
393 |
|
394 if *data == "" { |
|
395 return data, nil |
|
396 } |
|
397 |
|
398 if strings.Contains(*data, ";base64,") { |
|
399 return data, nil |
|
400 } |
|
401 |
|
402 // We need to convert the file and file name to base64 |
|
403 |
|
404 file, err := os.Open(*data) |
|
405 if err != nil { |
|
406 return nil, err |
|
407 } |
|
408 defer file.Close() |
|
409 |
|
410 fStat, err := file.Stat() |
|
411 if err != nil { |
|
412 return nil, err |
|
413 } |
|
414 |
|
415 buffer := make([]byte, fStat.Size()) |
|
416 _, err = file.Read(buffer) |
|
417 if err != nil { |
|
418 return nil, err |
|
419 } |
|
420 |
|
421 var cType string |
|
422 if contentType == nil || *contentType == "" { |
|
423 cType = http.DetectContentType(buffer[:512]) |
|
424 } else { |
|
425 cType = *contentType |
|
426 } |
|
427 contentData := base64.StdEncoding.EncodeToString(buffer) |
|
428 newData := "data:" + cType + ";base64," + contentData |
|
429 return &newData, nil |
|
430 } |