karakeep.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package karakeep // import "miniflux.app/v2/internal/integration/karakeep"
  4. import (
  5. "bytes"
  6. "encoding/json"
  7. "fmt"
  8. "io"
  9. "net/http"
  10. "time"
  11. "miniflux.app/v2/internal/version"
  12. )
  13. const defaultClientTimeout = 10 * time.Second
  14. type errorResponse struct {
  15. Code string `json:"code"`
  16. Error string `json:"error"`
  17. }
  18. type saveURLPayload struct {
  19. Type string `json:"type"`
  20. URL string `json:"url"`
  21. }
  22. type Client struct {
  23. wrapped *http.Client
  24. apiEndpoint string
  25. apiToken string
  26. }
  27. func NewClient(apiToken string, apiEndpoint string) *Client {
  28. return &Client{wrapped: &http.Client{Timeout: defaultClientTimeout}, apiEndpoint: apiEndpoint, apiToken: apiToken}
  29. }
  30. func (c *Client) SaveURL(entryURL string) error {
  31. requestBody, err := json.Marshal(&saveURLPayload{
  32. Type: "link",
  33. URL: entryURL,
  34. })
  35. if err != nil {
  36. return fmt.Errorf("karakeep: unable to encode request body: %v", err)
  37. }
  38. req, err := http.NewRequest(http.MethodPost, c.apiEndpoint, bytes.NewReader(requestBody))
  39. if err != nil {
  40. return fmt.Errorf("karakeep: unable to create request: %v", err)
  41. }
  42. req.Header.Set("Authorization", "Bearer "+c.apiToken)
  43. req.Header.Set("Content-Type", "application/json")
  44. req.Header.Set("User-Agent", "Miniflux/"+version.Version)
  45. resp, err := c.wrapped.Do(req)
  46. if err != nil {
  47. return fmt.Errorf("karakeep: unable to send request: %v", err)
  48. }
  49. defer resp.Body.Close()
  50. responseBody, err := io.ReadAll(resp.Body)
  51. if err != nil {
  52. return fmt.Errorf("karakeep: failed to parse response: %s", err)
  53. }
  54. if resp.Header.Get("Content-Type") != "application/json" {
  55. return fmt.Errorf("karakeep: unexpected content type response: %s", resp.Header.Get("Content-Type"))
  56. }
  57. if resp.StatusCode != http.StatusCreated {
  58. var errResponse errorResponse
  59. if err := json.Unmarshal(responseBody, &errResponse); err != nil {
  60. return fmt.Errorf("karakeep: unable to parse error response: status=%d body=%s", resp.StatusCode, string(responseBody))
  61. }
  62. return fmt.Errorf("karakeep: failed to save URL: status=%d errorcode=%s %s", resp.StatusCode, errResponse.Code, errResponse.Error)
  63. }
  64. return nil
  65. }