4
0
Эх сурвалжийг харах

fix(googlereader): handle various item ID formats

- Expected format: "tag:google.com,2005:reader/item/00000000148b9369" (hexadecimal string with prefix and padding)
- NetNewsWire uses this format: "tag:google.com,2005:reader/item/2f2" (hexadecimal string with prefix and no padding)
- Reeder uses this format: "000000000000048c" (hexadecimal string without prefix and padding)
- Liferea uses this format: "12345" (decimal string)
Frédéric Guillot 11 сар өмнө
parent
commit
8d821dfc3b

+ 5 - 16
internal/googlereader/handler.go

@@ -292,7 +292,7 @@ func (h *handler) editTagHandler(w http.ResponseWriter, r *http.Request) {
 
 	itemIDs, err := parseItemIDsFromRequest(r)
 	if err != nil {
-		json.ServerError(w, r, err)
+		json.BadRequest(w, r, err)
 		return
 	}
 
@@ -709,7 +709,7 @@ func (h *handler) streamItemContentsHandler(w http.ResponseWriter, r *http.Reque
 
 	itemIDs, err := parseItemIDsFromRequest(r)
 	if err != nil {
-		json.ServerError(w, r, err)
+		json.BadRequest(w, r, err)
 		return
 	}
 
@@ -733,22 +733,11 @@ func (h *handler) streamItemContentsHandler(w http.ResponseWriter, r *http.Reque
 		return
 	}
 
-	if len(entries) == 0 {
-		json.BadRequest(w, r, fmt.Errorf("googlereader: no items returned from the database for item IDs: %v", itemIDs))
-		return
-	}
-
 	result := streamContentItems{
 		Direction: "ltr",
-		ID:        fmt.Sprintf("feed/%d", entries[0].FeedID),
-		Title:     entries[0].Feed.Title,
-		Alternate: []contentHREFType{
-			{
-				HREF: entries[0].Feed.SiteURL,
-				Type: "text/html",
-			},
-		},
-		Updated: time.Now().Unix(),
+		ID:        "user/-/state/com.google/reading-list",
+		Title:     "Reading List",
+		Updated:   time.Now().Unix(),
 		Self: []contentHREF{
 			{
 				HREF: config.Opts.RootURL() + route.Path(h.router, "StreamItemsContents"),

+ 28 - 19
internal/googlereader/item.go

@@ -4,7 +4,6 @@
 package googlereader // import "miniflux.app/v2/internal/googlereader"
 
 import (
-	"errors"
 	"fmt"
 	"net/http"
 	"strconv"
@@ -13,37 +12,47 @@ import (
 
 const (
 	ItemIDPrefix = "tag:google.com,2005:reader/item/"
+	ItemIDFormat = "tag:google.com,2005:reader/item/%016x"
 )
 
 func convertEntryIDToLongFormItemID(entryID int64) string {
 	// The entry ID is a 64-bit integer, so we need to format it as a 16-character hexadecimal string.
-	return ItemIDPrefix + fmt.Sprintf("%016x", entryID)
+	return fmt.Sprintf(ItemIDFormat, entryID)
 }
 
-// parseItemID parses a Google Reader ID string.
-// It supports both the long form (tag:google.com,2005:reader/item/<hex_id>) and the short form (<decimal_id>).
+// Expected format: "tag:google.com,2005:reader/item/00000000148b9369" (hexadecimal string with prefix and padding)
+// NetNewsWire uses this format: "tag:google.com,2005:reader/item/2f2" (hexadecimal string with prefix and no padding)
+// Reeder uses this format: "000000000000048c" (hexadecimal string without prefix and padding)
+// Liferea uses this format: "12345" (decimal string)
 // It returns the parsed ID as a int64 and an error if parsing fails.
 func parseItemID(itemIDValue string) (int64, error) {
+	var itemID int64
 	if strings.HasPrefix(itemIDValue, ItemIDPrefix) {
-		hexID := strings.TrimPrefix(itemIDValue, ItemIDPrefix)
-
-		// It's always 16 characters wide.
-		if len(hexID) != 16 {
-			return 0, errors.New("long form ID has incorrect length")
-		}
-
-		parsedID, err := strconv.ParseInt(hexID, 16, 64)
+		n, err := fmt.Sscanf(itemIDValue, ItemIDFormat, &itemID)
 		if err != nil {
-			return 0, errors.New("failed to parse long form hex ID: " + err.Error())
+			return 0, fmt.Errorf("failed to parse hexadecimal item ID %s: %w", itemIDValue, err)
 		}
-		return parsedID, nil
-	} else {
-		parsedID, err := strconv.ParseInt(itemIDValue, 10, 64)
-		if err != nil {
-			return 0, errors.New("failed to parse short form decimal ID: " + err.Error())
+		if n != 1 {
+			return 0, fmt.Errorf("failed to parse hexadecimal item ID %s: expected 1 value, got %d", itemIDValue, n)
+		}
+		if itemID == 0 {
+			return 0, fmt.Errorf("failed to parse hexadecimal item ID %s: item ID is zero", itemIDValue)
 		}
-		return parsedID, nil
+		return itemID, nil
 	}
+
+	if len(itemIDValue) == 16 {
+		if n, err := fmt.Sscanf(itemIDValue, "%016x", &itemID); err == nil && n == 1 {
+			return itemID, nil
+		}
+	}
+
+	itemID, err := strconv.ParseInt(itemIDValue, 10, 64)
+	if err != nil {
+		return 0, fmt.Errorf("failed to parse decimal item ID %s: %w", itemIDValue, err)
+	}
+
+	return itemID, nil
 }
 
 func parseItemIDsFromRequest(r *http.Request) ([]int64, error) {

+ 16 - 21
internal/googlereader/item_test.go

@@ -23,7 +23,10 @@ func TestConvertEntryIDToLongFormItemID(t *testing.T) {
 func TestParseItemIDsFromRequest(t *testing.T) {
 	formValues := url.Values{}
 	formValues.Add("i", "12345")
-	formValues.Add("i", convertEntryIDToLongFormItemID(45678))
+	formValues.Add("i", "tag:google.com,2005:reader/item/00000000148b9369")
+	formValues.Add("i", "tag:google.com,2005:reader/item/2f2")
+	formValues.Add("i", "000000000000046f")
+	formValues.Add("i", "tag:google.com,2005:reader/item/272")
 
 	request := &http.Request{
 		Form: formValues,
@@ -34,7 +37,7 @@ func TestParseItemIDsFromRequest(t *testing.T) {
 		t.Fatalf("unexpected error: %v", err)
 	}
 
-	var expected = []int64{12345, 45678}
+	var expected = []int64{12345, 344691561, 754, 1135, 626}
 	if !reflect.DeepEqual(result, expected) {
 		t.Errorf("expected %v, got %v", expected, result)
 	}
@@ -51,7 +54,7 @@ func TestParseItemIDsFromRequest(t *testing.T) {
 }
 
 func TestParseItemID(t *testing.T) {
-	// Test with long form ID
+	// Test with long form ID and hex ID
 	result, err := parseItemID("tag:google.com,2005:reader/item/0000000000000001")
 	if err != nil {
 		t.Fatalf("unexpected error: %v", err)
@@ -61,6 +64,16 @@ func TestParseItemID(t *testing.T) {
 		t.Errorf("expected %d, got %d", expected, result)
 	}
 
+	// Test with hexadecimal long form ID
+	result, err = parseItemID("0000000000000468")
+	if err != nil {
+		t.Fatalf("unexpected error: %v", err)
+	}
+	expected = int64(1128)
+	if result != expected {
+		t.Errorf("expected %d, got %d", expected, result)
+	}
+
 	// Test with short form ID
 	result, err = parseItemID("12345")
 	if err != nil {
@@ -88,22 +101,4 @@ func TestParseItemID(t *testing.T) {
 	if err == nil {
 		t.Fatalf("expected error, got nil")
 	}
-
-	// Test with ID that is too short
-	_, err = parseItemID("tag:google.com,2005:reader/item/00000000000000")
-	if err == nil {
-		t.Fatalf("expected error, got nil")
-	}
-
-	// Test with ID that is too long
-	_, err = parseItemID("tag:google.com,2005:reader/item/000000000000000000")
-	if err == nil {
-		t.Fatalf("expected error, got nil")
-	}
-
-	// Test with ID that is not a number
-	_, err = parseItemID("tag:google.com,2005:reader/item/abc")
-	if err == nil {
-		t.Fatalf("expected error, got nil")
-	}
 }