8000 [pull] main from miniflux:main by pull[bot] · Pull Request #238 · suhaoGe/miniflux · GitHub
[go: up one dir, main page]

Skip to content
Merged
< 8000 /div>
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ func (c *Client) UpdateCategory(categoryID int64, title string) (*Category, erro
// UpdateCategoryContext updates a category.
func (c *Client) UpdateCategoryContext(ctx context.Context, categoryID int64, title string) (*Category, error) {
body, err := c.request.Put(ctx, fmt.Sprintf("/v1/categories/%d", categoryID), &CategoryModificationRequest{
Title: SetOptionalField(title),
Title: new(title),
})
if err != nil {
return nil, err
Expand Down
6 changes: 4 additions & 2 deletions client/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ type Feed struct {
FeedURL string `json:"feed_url"`
SiteURL string `json:"site_url"`
Title string `json:"title"`
CheckedAt time.Time `json:"checked_at,omitempty"`
CheckedAt time.Time `json:"checked_at"`
EtagHeader string `json:"etag_header,omitempty"`
LastModifiedHeader string `json:"last_modified_header,omitempty"`
ParsingErrorMsg string `json:"parsing_error_message,omitempty"`
Expand Down Expand Up @@ -360,6 +360,8 @@ type APIKeyCreationRequest struct {
}

// SetOptionalField returns a pointer to the given value so optional request fields can be marked as set.
//
//go:fix inline
func SetOptionalField[T any](value T) *T {
return &value
return new(value)
}
8 changes: 3 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module miniflux.app/v2

// +heroku goVersion go1.24
// +heroku goVersion go1.26

require (
github.com/PuerkitoBio/goquery v1.11.0
Expand All @@ -16,6 +16,7 @@ require (
golang.org/x/net v0.50.0
golang.org/x/oauth2 v0.35.0
golang.org/x/term v0.40.0
golang.org/x/text v0.34.0
)

require (
Expand All @@ -41,10 +42,7 @@ require (
github.com/x448/float16 v0.8.4 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.34.0 // indirect
google.golang.org/protobuf v1.36.8 // indirect
)

go 1.24.0

toolchain go1.24.1
go 1.26.0
30 changes: 15 additions & 15 deletions internal/api/api_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ func TestUpdateUserEndpointByChangingDefaultTheme(t *testing.T) {
regularUserClient := miniflux.NewClient(testConfig.testBaseURL, regularTestUser.Username, testConfig.testRegularPassword)

userUpdateRequest := &miniflux.UserModificationRequest{
Theme: miniflux.SetOptionalField("dark_serif" 8000 ),
Theme: new("dark_serif"),
}

updatedUser, err := regularUserClient.UpdateUser(regularTestUser.ID, userUpdateRequest)
Expand Down Expand Up @@ -609,7 +609,7 @@ func TestUpdateUserEndpointByChangingExternalFonts(t *testing.T) {
regularUserClient := miniflux.NewClient(testConfig.testBaseURL, regularTestUser.Username, testConfig.testRegularPassword)

userUpdateRequest := &miniflux.UserModificationRequest{
ExternalFontHosts: miniflux.SetOptionalField(" fonts.example.org "),
ExternalFontHosts: new(" fonts.example.org "),
}

updatedUser, err := regularUserClient.UpdateUser(regularTestUser.ID, userUpdateRequest)
Expand Down Expand Up @@ -638,7 +638,7 @@ func TestUpdateUserEndpointByChangingExternalFontsWithInvalidValue(t *testing.T)
regularUserClient := miniflux.NewClient(testConfig.testBaseURL, regularTestUser.Username, testConfig.testRegularPassword)

userUpdateRequest := &miniflux.UserModificationRequest{
ExternalFontHosts: miniflux.SetOptionalField("'self' *"),
ExternalFontHosts: new("'self' *"),
}

if _, err := regularUserClient.UpdateUser(regularTestUser.ID, userUpdateRequest); err == nil {
Expand All @@ -662,7 +662,7 @@ func TestUpdateUserEndpointByChangingCustomJS(t *testing.T) {
regularUserClient := miniflux.NewClient(testConfig.testBaseURL, regularTestUser.Username, testConfig.testRegularPassword)

userUpdateRequest := &miniflux.UserModificationRequest{
CustomJS: miniflux.SetOptionalField("alert('Hello, World!');"),
CustomJS: new("alert('Hello, World!');"),
}

updatedUser, err := regularUserClient.UpdateUser(regularTestUser.ID, userUpdateRequest)
Expand Down Expand Up @@ -691,7 +691,7 @@ func TestUpdateUserEndpointByChangingDefaultThemeToInvalidValue(t *testing.T) {
regularUserClient := miniflux.NewClient(testConfig.test 8BD0 BaseURL, regularTestUser.Username, testConfig.testRegularPassword)

userUpdateRequest := &miniflux.UserModificationRequest{
Theme: miniflux.SetOptionalField("invalid_theme"),
Theme: new("invalid_theme"),
}

_, err = regularUserClient.UpdateUser(regularTestUser.ID, userUpdateRequest)
Expand Down Expand Up @@ -721,7 +721,7 @@ func TestRegularUsersCannotUpdateOtherUsers(t *testing.T) {
regularUserClient := miniflux.NewClient(testConfig.testBaseURL, regularTestUser.Username, testConfig.testRegularPassword)

userUpdateRequest := &miniflux.UserModificationRequest{
Theme: miniflux.SetOptionalField("dark_serif"),
Theme: new("dark_serif"),
}

_, err = regularUserClient.UpdateUser(adminUser.ID, userUpdateRequest)
Expand Down Expand Up @@ -1090,7 +1090,7 @@ func TestUpdateCategoryWithOptions(t *testing.T) {
}

updatedCategory, err := regularUserClient.UpdateCategoryWithOptions(newCategory.ID, &miniflux.CategoryModificationRequest{
Title: miniflux.SetOptionalField("new title"),
Title: new("new title"),
})
if err != nil {
t.Fatal(err)
Expand All @@ -1109,7 +1109,7 @@ func TestUpdateCategoryWithOptions(t *testing.T) {
}

updatedCategory, err = regularUserClient.UpdateCategoryWithOptions(newCategory.ID, &miniflux.CategoryModificationRequest{
HideGlobally: miniflux.SetOptionalField(true),
HideGlobally: new(true),
})
if err != nil {
t.Fatal(err)
Expand All @@ -1128,14 +1128,14 @@ func TestUpdateCategoryWithOptions(t *testing.T) {
}

updatedCategory, err = regularUserClient.UpdateCategoryWithOptions(newCategory.ID, &miniflux.CategoryModificationRequest{
HideGlobally: miniflux.SetOptionalField(false),
HideGlobally: new(false),
})
if err != nil {
t.Fatal(err)
}

if updatedCategory.ID != newCategory.ID {
t.Errorf(`Invalid categoryID, got %q`, updatedCategory.ID)
t.Errorf(`Invalid categoryID, got %d`, updatedCategory.ID)
}

if updatedCategory.Title != "new title" {
Expand Down Expand Up @@ -1612,7 +1612,7 @@ func TestUpdateFeedEndpoint(t *testing.T) {
}

feedUpdateRequest := &miniflux.FeedModificationRequest{
FeedURL: miniflux.SetOptionalField("https://example.org/feed.xml"),
FeedURL: new("https://example.org/feed.xml"),
}

updatedFeed, err := regularUserClient.UpdateFeed(feedID, feedUpdateRequest)
Expand Down Expand Up @@ -1653,7 +1653,7 @@ func TestCannotHaveDuplicateFeedWhenUpdatingFeed(t *testing.T) {
}

feedUpdateRequest := &miniflux.FeedModificationRequest{
FeedURL: miniflux.SetOptionalField(testConfig.testFeedURL),
FeedURL: new(testConfig.testFeedURL),
}

if _, err := regularUserClient.UpdateFeed(feedID, feedUpdateRequest); err == nil {
Expand Down Expand Up @@ -1685,7 +1685,7 @@ func TestUpdateFeedWithInvalidCategory(t *testing.T) {
}

feedUpdateRequest := &miniflux.FeedModificationRequest{
CategoryID: miniflux.SetOptionalField(int64(123456789)),
CategoryID: new(int64(123456789)),
}

if _, err := regularUserClient.UpdateFeed(feedID, feedUpdateRequest); err == nil {
Expand Down Expand Up @@ -2718,8 +2718,8 @@ func TestUpdateEntryEndpoint(t *testing.T) {
}

entryUpdateRequest := &miniflux.EntryModificationRequest{
Title: miniflux.SetOptionalField("New title"),
Content: miniflux.SetOptionalField("New content"),
Title: new("New title"),
Content: new("New content"),
}

updatedEntry, err := regularUserClient.UpdateEntry(result.Entries[0].ID, entryUpdateRequest)
Expand Down
2 changes: 1 addition & 1 deletion internal/googlereader/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ func (h *handler) renameTagHandler(w http.ResponseWriter, r *http.Request) {
}

categoryModificationRequest := model.CategoryModificationRequest{
Title: model.SetOptionalField(destination.ID),
Title: new(destination.ID),
}

if validationError := validator.ValidateCategoryModification(h.store, userID, category.ID, &categoryModificationRequest); validationError != nil {
Expand Down
62 changes: 31 additions & 31 deletions internal/integration/linktaco/linktaco_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func TestCreateBookmark(t *testing.T) {

// Parse and verify request
body, _ := io.ReadAll(r.Body)
var req map[string]interface{}
var req map[string]any
if err := json.Unmarshal(body, &req); err != nil {
t.Errorf("Failed to parse request body: %v", err)
}
Expand All @@ -62,9 +62,9 @@ func TestCreateBookmark(t *testing.T) {

// Return success response
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]interface{}{
"data": map[string]interface{}{
"addLink": map[string]interface{}{
json.NewEncoder(w).Encode(map[string]any{
"data": map[string]any{
"addLink": map[string]any{
"id": "123",
"url": "https://example.com",
"title": "Test Article",
Expand Down Expand Up @@ -111,9 +111,9 @@ func TestCreateBookmark(t *testing.T) {
entryContent: "Content",
serverResponse: func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]interface{}{
"errors": []interface{}{
map[string]interface{}{
json.NewEncoder(w).Encode(map[string]any{
"errors": []any{
map[string]any{
"message": "Invalid input",
},
},
Expand Down Expand Up @@ -145,9 +145,9 @@ func TestCreateBookmark(t *testing.T) {
entryContent: "Content",
serverResponse: func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]interface{}{
"errors": []interface{}{
map[string]interface{}{
json.NewEncoder(w).Encode(map[string]any{
"errors": []any{
map[string]any{
"message": "PRIVATE visibility requires a paid LinkTaco account",
},
},
Expand All @@ -165,22 +165,22 @@ func TestCreateBookmark(t *testing.T) {
entryContent: strings.Repeat("a", 600), // Content longer than 500 chars
serverResponse: func(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
var req map[string]interface{}
var req map[string]any
json.Unmarshal(body, &req)

// Check that description was truncated
variables := req["variables"].(map[string]interface{})
input := variables["input"].(map[string]interface{})
variables := req["variables"].(map[string]any)
input := variables["input"].(map[string]any)
description := input["description"].(string)

if len(description) != maxDescrip 10BC8 tionLength {
t.Errorf("Expected description length %d, got %d", maxDescriptionLength, len(description))
}

w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]interface{}{
"data": map[string]interface{}{
"addLink": map[string]interface{}{"id": "123"},
json.NewEncoder(w).Encode(map[string]any{
"data": map[string]any{
"addLink": map[string]any{"id": "123"},
},
})
},
Expand All @@ -196,12 +196,12 @@ func TestCreateBookmark(t *testing.T) {
entryContent: "Content",
serverResponse: func(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
var req map[string]interface{}
var req map[string]any
json.Unmarshal(body, &req)

// Check that only 10 tags were sent
variables := req["variables"].(map[string]interface{})
input := variables["input"].(map[string]interface{})
variables := req["variables"].(map[string]any)
input := variables["input"].(map[string]any)
tags := input["tags"].(string)

tagCount := len(strings.Split(tags, ","))
Expand All @@ -210,9 +210,9 @@ func TestCreateBookmark(t *testing.T) {
}

w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]interface{}{
"data": map[string]interface{}{
"addLink": map[string]interface{}{"id": "123"},
json.NewEncoder(w).Encode(map[string]any{
"data": map[string]any{
"addLink": map[string]any{"id": "123"},
},
})
},
Expand Down Expand Up @@ -326,7 +326,7 @@ func TestGraphQLMutation(t *testing.T) {
// Test that the GraphQL mutation is properly formatted
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
var req map[string]interface{}
var req map[string]any
if err := json.Unmarshal(body, &req); err != nil {
t.Fatalf("Failed to parse request: %v", err)
}
Expand All @@ -349,12 +349,12 @@ func TestGraphQLMutation(t *testing.T) {
}

// Verify variables structure
variables, ok := req["variables"].(map[string]interface{})
variables, ok := req["variables"].(map[string]any)
if !ok {
t.Fatal("Missing variables field")
}

input, ok := variables["input"].(map[string]interface{})
input, ok := variables["input"].(map[string]any)
if !ok {
t.Fatal("Missing input in variables")
}
Expand All @@ -369,9 +369,9 @@ func TestGraphQLMutation(t *testing.T) {

// Return success
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]interface{}{
"data": map[string]interface{}{
"addLink": map[string]interface{}{
json.NewEncoder(w).Encode(map[string]any{
"data": map[string]any{
"addLink": map[string]any{
"id": "123",
},
},
Expand All @@ -397,9 +397,9 @@ func BenchmarkCreateBookmark(b *testing.B) {
// Create a mock server that always returns success
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]interface{}{
"data": map[string]interface{}{
"addLink": map[string]interface{}{
json.NewEncoder(w).Encode(map[string]any{
"data": map[string]any{
"addLink": map[string]any{
"id": "123",
},
},
Expand Down
2 changes: 1 addition & 1 deletion internal/integration/raindrop/raindrop.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (c *Client) CreateRaindrop(entryURL, entryTitle string) error {
type raindrop struct {
Link string `json:"link"`
Title string `json:"title"`
Collection collection `json:"collection,omitempty"`
Collection collection `json:"collection"`
Tags []string `json:"tags"`
}

Expand Down
14 changes: 7 additions & 7 deletions internal/integration/readeck/readeck_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ func TestCreateBookmark(t *testing.T) {
if !strings.HasPrefix(ct, "multipart/form-data;") {
t.Errorf("expected multipart/form-data, got %s", ct)
}
boundaryIdx := strings.Index(ct, "boundary=")
if boundaryIdx == -1 {
_, after, ok := strings.Cut(ct, "boundary=")
if !ok {
t.Fatalf("missing multipart boundary in Content-Type: %s", ct)
}
boundary := ct[boundaryIdx+len("boundary="):]
boundary := after
mr := multipart.NewReader(r.Body, boundary)

seenLabels := []string{}
Expand Down Expand Up @@ -132,12 +132,12 @@ func TestCreateBookmark(t *testing.T) {
case "resource":
// First line is JSON header, then newline, then content
all := string(data)
idx := strings.IndexByte(all, '\n')
if idx == -1 {
before, after, ok := strings.Cut(all, "\n")
if !ok {
t.Fatalf("resource content missing header separator")
}
headerJSON := all[:idx]
resourceBody = all[idx+1:]
headerJSON := before
resourceBody = after
if err := json.Unmarshal([]byte(headerJSON), &resourceHeader); err != nil {
t.Fatalf("invalid resource header JSON: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/integration/shaarli/shaarli.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (c *Client) CreateLink(entryURL, entryTitle string) error {

func (c *Client) generateBearerToken() string {
header := base64.RawURLEncoding.EncodeToString([]byte(`{"typ":"JWT","alg":"HS512"}`))
payload := base64.RawURLEncoding.EncodeToString([]byte(fmt.Sprintf(`{"iat":%d}`, time.Now().Unix())))
payload := base64.RawURLEncoding.EncodeToString(fmt.Appendf(nil, `{"iat":%d}`, time.Now().Unix()))
data := header + "." + payload

mac := hmac.New(sha512.New, []byte(c.apiSecret))
Expand Down
Loading
Loading
0