item.go 2.3 KB

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