item.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package googlereader // import "miniflux.app/v2/internal/googlereader"
  4. import (
  5. "errors"
  6. "fmt"
  7. "net/http"
  8. "strconv"
  9. "strings"
  10. )
  11. const (
  12. ItemIDPrefix = "tag:google.com,2005:reader/item/"
  13. ItemIDFormat = "tag:google.com,2005:reader/item/%016x"
  14. )
  15. func convertEntryIDToLongFormItemID(entryID int64) string {
  16. // The entry ID is a 64-bit integer, so we need to format it as a 16-character hexadecimal string.
  17. return fmt.Sprintf(ItemIDFormat, entryID)
  18. }
  19. // Expected format: "tag:google.com,2005:reader/item/00000000148b9369" (hexadecimal string with prefix and padding)
  20. // NetNewsWire uses this format: "tag:google.com,2005:reader/item/2f2" (hexadecimal string with prefix and no padding)
  21. // Reeder uses this format: "000000000000048c" (hexadecimal string without prefix and padding)
  22. // Liferea uses this format: "12345" (decimal string)
  23. // It returns the parsed ID as a int64 and an error if parsing fails.
  24. func parseItemID(itemIDValue string) (int64, error) {
  25. var itemID int64
  26. if strings.HasPrefix(itemIDValue, ItemIDPrefix) {
  27. n, err := fmt.Sscanf(itemIDValue, ItemIDFormat, &itemID)
  28. if err != nil {
  29. return 0, fmt.Errorf("failed to parse hexadecimal item ID %s: %w", itemIDValue, err)
  30. }
  31. if n != 1 {
  32. return 0, fmt.Errorf("failed to parse hexadecimal item ID %s: expected 1 value, got %d", itemIDValue, n)
  33. }
  34. if itemID == 0 {
  35. return 0, fmt.Errorf("failed to parse hexadecimal item ID %s: item ID is zero", itemIDValue)
  36. }
  37. return itemID, nil
  38. }
  39. if len(itemIDValue) == 16 {
  40. if n, err := fmt.Sscanf(itemIDValue, "%016x", &itemID); err == nil && n == 1 {
  41. return itemID, nil
  42. }
  43. }
  44. itemID, err := strconv.ParseInt(itemIDValue, 10, 64)
  45. if err != nil {
  46. return 0, fmt.Errorf("failed to parse decimal item ID %s: %w", itemIDValue, err)
  47. }
  48. return itemID, nil
  49. }
  50. func parseItemIDsFromRequest(r *http.Request) ([]int64, error) {
  51. items := r.Form[paramItemIDs]
  52. if len(items) == 0 {
  53. return nil, errors.New("googlereader: no items requested")
  54. }
  55. itemIDs := make([]int64, len(items))
  56. for i, item := range items {
  57. itemID, err := parseItemID(item)
  58. if err != nil {
  59. return nil, fmt.Errorf("googlereader: failed to parse item ID %s: %w", item, err)
  60. }
  61. itemIDs[i] = itemID
  62. }
  63. return itemIDs, nil
  64. }