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

Skip to content
Merged
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/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Miniflux API Client

[![PkgGoDev](https://pkg.go.dev/badge/miniflux.app/v2/client)](https://pkg.go.dev/miniflux.app/v2/client)

Client library for Miniflux REST API.
Go client for the Miniflux REST API. It supports API tokens or basic authentication and mirrors the server endpoints closely.

Installation
------------
Expand Down
26 changes: 13 additions & 13 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,14 +334,14 @@ func (c *Client) MarkA 10BC8 llAsReadContext(ctx context.Context, userID int64) error {
return err
}

// IntegrationsStatus fetches the integrations status for the logged user.
// IntegrationsStatus fetches the integrations status for the signed-in user.
func (c *Client) IntegrationsStatus() (bool, error) {
ctx, cancel := withDefaultTimeout()
defer cancel()
return c.IntegrationsStatusContext(ctx)
}

// IntegrationsStatusContext fetches the integrations status for the logged user.
// IntegrationsStatusContext fetches the integrations status for the signed-in user.
func (c *Client) IntegrationsStatusContext(ctx context.Context) (bool, error) {
body, err := c.request.Get(ctx, "/v1/integrations/status")
if err != nil {
Expand All @@ -360,7 +360,7 @@ func (c *Client) IntegrationsStatusContext(ctx context.Context) (bool, error) {
return response.HasIntegrations, nil
}

// Discover try to find subscriptions from a website.
// Discover tries to find subscriptions on a website.
func (c *Client) Discover(url string) (Subscriptions, error) {
ctx, cancel := withDefaultTimeout()
defer cancel()
Expand All @@ -383,14 +383,14 @@ func (c *Client) DiscoverContext(ctx context.Context, url string) (Subscriptions
return subscriptions, nil
}

// Categories gets the list of categories.
// Categories retrieves the list of categories.
func (c *Client) Categories() (Categories, error) {
ctx, cancel := withDefaultTimeout()
defer cancel()
return c.CategoriesContext(ctx)
}

// CategoriesContext gets the list of categories.
// CategoriesContext retrieves the list of categories.
func (c *Client) CategoriesContext(ctx context.Context) (Categories, error) {
body, err := c.request.Get(ctx, "/v1/categories")
if err != nil {
Expand Down Expand Up @@ -537,14 +537,14 @@ func (c *Client) MarkCategoryAsReadContext(ctx context.Context, categoryID int64
return err
}

// CategoryFeeds gets feeds of a category.
// CategoryFeeds returns all feeds for a category.
func (c *Client) CategoryFeeds(categoryID int64) (Feeds, error) {
ctx, cancel := withDefaultTimeout()
defer cancel()
return c.CategoryFeedsContext(ctx, categoryID)
}

// CategoryFeedsContext gets feeds of a category.
// CategoryFeedsContext returns all feeds for a category.
func (c *Client) CategoryFeedsContext(ctx context.Context, categoryID int64) (Feeds, error) {
body, err := c.request.Get(ctx, fmt.Sprintf("/v1/categories/%d/feeds", categoryID))
if err != nil {
Expand Down Expand Up @@ -608,14 +608,14 @@ func (c *Client) FeedsContext(ctx context.Context) (Feeds, error) {
return feeds, nil
}

// Export creates OPML file.
// Export exports subscriptions as an OPML document.
func (c *Client) Export() ([]byte, error) {
ctx, cancel := withDefaultTimeout()
defer cancel()
return c.ExportContext(ctx)
}

// ExportContext creates OPML file.
// ExportContext exports subscriptions as an OPML document.
func (c *Client) ExportContext(ctx context.Context) ([]byte, error) {
body, err := c.request.Get(ctx, "/v1/export")
if err != nil {
Expand Down Expand Up @@ -886,7 +886,7 @@ func (c *Client) EntryContext(ctx context.Context, entryID int64) (*Entry, error
return entry, nil
}

// Entries fetch entries.
// Entries fetches entries using the given filter.
func (c *Client) Entries(filter *Filter) (*EntryResultSet, error) {
ctx, cancel := withDefaultTimeout()
defer cancel()
Expand All @@ -911,7 +911,7 @@ func (c *Client) EntriesContext(ctx context.Context, filter *Filter) (*EntryResu
return &result, nil
}

// FeedEntries fetch feed entries.
// FeedEntries fetches entries for a feed using the given filter.
func (c *Client) FeedEntries(feedID int64, filter *Filter) (*EntryResultSet, error) {
ctx, cancel := withDefaultTimeout()
defer cancel()
Expand All @@ -936,7 +936,7 @@ func (c *Client) FeedEntriesContext(ctx context.Context, feedID int64, filter *F
return &result, nil
}

// CategoryEntries fetch entries of a category.
// CategoryEntries fetches entries for a category using the given filter.
func (c *Client) CategoryEntries(categoryID int64, filter *Filter) (*EntryResultSet, error) {
ctx, cancel := withDefaultTimeout()
defer cancel()
Expand Down Expand Up @@ -1002,7 +1002,7 @@ func (c *Client) UpdateEntryContext(ctx context.Context, entryID int64, entryCha
return entry, nil
}

// ToggleStarred toggles entry starred value.
// ToggleStarred toggles the starred flag of an entry.
func (c *Client) ToggleStarred(entryID int64) error {
ctx, cancel := withDefaultTimeout()
defer cancel()
Expand Down
4 changes: 2 additions & 2 deletions client/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Package client implements a client library for the Miniflux REST API.

# Examples

This code snippet fetch the list of users:
This example fetches the list of users:

import (
miniflux "miniflux.app/v2/client"
Expand All @@ -20,7 +20,7 @@ This code snippet fetch the list of users:
}
fmt.Println(users, err)

This one discover subscriptions on a website:
This example discovers subscriptions on a website:

subscriptions, err := client.Discover("https://example.org/")
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions client/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ type APIKeyCreationRequest struct {
Description string `json:"description"`
}

// SetOptionalField returns a pointer to the given value so optional request fields can be marked as set.
func SetOptionalField[T any](value T) *T {
return &value
}
48 changes: 24 additions & 24 deletions internal/api/entry.go
BD0 < 10000 td class="blob-num blob-num-addition empty-cell">
Original file line number Diff line number Diff line change
Expand Up @@ -308,47 +308,47 @@ func (h *handler) importFeedEntry(w http.ResponseWriter, r *http.Request) {
return
}

var req EntryImportRequest
if err := json_parser.NewDecoder(r.Body).Decode(&req); err != nil {
var importRequest entryImportRequest
if err := json_parser.NewDecoder(r.Body).Decode(&importRequest); err != nil {
json.BadRequest(w, r, err)
return
}

if req.URL == "" {
if importRequest.URL == "" {
json.BadRequest(w, r, errors.New("url is required"))
return
}

if req.Status == "" {
req.Status = model.EntryStatusRead
if importRequest.Status == "" {
importRequest.Status = model.EntryStatusRead
}

if err := validator.ValidateEntryStatus(req.Status); err != nil {
if err := validator.ValidateEntryStatus(importRequest.Status); err != nil {
json.BadRequest(w, r, err)
return
}

entry := model.NewEntry()
entry.URL = req.URL
entry.CommentsURL = req.CommentsURL
entry.Author = req.Author
entry.Tags = req.Tags
entry.URL = importRequest.URL
entry.CommentsURL = importRequest.CommentsURL
entry.Author = importRequest.Author
entry.Tags = importRequest.Tags

if req.PublishedAt > 0 {
entry.Date = time.Unix(req.PublishedAt, 0).UTC()
if importRequest.PublishedAt > 0 {
entry.Date = time.Unix(importRequest.PublishedAt, 0).UTC()
} else {
entry.Date = time.Now().UTC()
}

if req.Title == "" {
if importRequest.Title == "" {
entry.Title = entry.URL
} else {
entry.Title = req.Title
entry.Title = importRequest.Title
}

hashInput := req.ExternalID
hashInput := importRequest.ExternalID
if hashInput == "" {
hashInput = req.URL
hashInput = importRequest.URL
}
entry.Hash = crypto.HashFromBytes([]byte(hashInput))

Expand All @@ -363,8 +363,8 @@ func (h *handler) importFeedEntry(w http.ResponseWriter, r *http.Request) {
return
}

if req.Content != "" {
entry.Content = sanitizer.SanitizeHTML(entry.URL, req.Content, &sanitizer.SanitizerOptions{OpenLinksInNewTab: user.OpenExternalLinksInNewTab})
if importRequest.Content != "" {
entry.Content = sanitizer.SanitizeHTML(entry.URL, importRequest.Content, &sanitizer.SanitizerOptions{OpenLinksInNewTab: user.OpenExternalLinksInNewTab})
}

if user.ShowReadingTime {
Expand All @@ -377,13 +377,13 @@ func (h *handler) importFeedEntry(w http.ResponseWriter, r *http.Request) {
return
}

if err := h.store.SetEntriesStatus(userID, []int64{entry.ID}, req.Status); err != nil {
if err := h.store.SetEntriesStatus(userID, []int64{entry.ID}, importRequest.Status); err != nil {
json.ServerError(w, r, err)
return
}
entry.Status = req.Status
entry.Status = importRequest.Status

if req.Starred {
if importRequest.Starred {
if err := h.store.SetEntriesStarredState(userID, []int64{entry.ID}, true); err != nil {
json.ServerError(w, r, err)
return
Expand All @@ -392,9 +392,9 @@ func (h *handler) importFeedEntry(w http.ResponseWriter, r *http.Request) {
}

if created {
json.Created(w, r, map[string]int64{"id": entry.ID})
json.Created(w, r, entryIDResponse{ID: entry.ID})
} else {
json.OK(w, r, map[string]int64{"id": entry.ID})
json.OK(w, r, entryIDResponse{ID: entry.ID})
}
}

Expand Down Expand Up @@ -454,7 +454,7 @@ func (h *handler) fetchContent(w ht 10BC8 tp.ResponseWriter, r *http.Request) {
}
}

json.OK(w, r, map[string]any{"content": mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, entry.Content), "reading_time": entry.ReadingTime})
json.OK(w, r, entryContentResponse{Content: mediaproxy.RewriteDocumentWithAbsoluteProxyURL(h.router, entry.Content), ReadingTime: entry.ReadingTime})
}

func (h *handler) flushHistory(w http.ResponseWriter, r *http.Request) {
Expand Down
2 changes: 1 addition & 1 deletion internal/api/opml.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ func (h *handler) importFeeds(w http.ResponseWriter, r *http.Request) {
return
}

json.Created(w, r, map[string]string{"message": "Feeds imported successfully"})
json.Created(w, r, importFeedsResponse{Message: "Feeds imported successfully"})
}
20 changes: 18 additions & 2 deletions internal/api/payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,20 @@ type entriesResponse struct {
Entries model.Entries `json:"entries"`
}

// EntryImportRequest represents a manually imported entry for a feed.
type EntryImportRequest struct {
type integrationsStatusResponse struct {
HasIntegrations bool `json:"has_integrations"`
}

type entryIDResponse struct {
ID int64 `json:"id"`
}

type entryContentResponse struct {
Content string `json:"content"`
ReadingTime int `json:"reading_time"`
}

type entryImportRequest struct {
URL string `json:"url"`
Title string `json:"title"`
Content string `json:"content"`
Expand All @@ -36,6 +48,10 @@ type feedCreationResponse struct {
FeedID int64 `json:"feed_id"`
}

type importFeedsResponse struct {
Message string `json:"message"`
}

type versionResponse struct {
Version string `json:"version"`
Commit string `json:"commit"`
Expand Down
8 changes: 1 addition & 7 deletions internal/api/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,7 @@ func (h *handler) getIntegrationsStatus(w http.ResponseWriter, r *http.Request)

hasIntegrations := h.store.HasSaveEntry(userID)

response := struct {
HasIntegrations bool `json:"has_integrations"`
}{
HasIntegrations: hasIntegrations,
}

json.OK(w, r, response)
json.OK(w, r, integrationsStatusResponse{HasIntegrations: hasIntegrations})
}

func (h *handler) users(w http.ResponseWriter, r *http.Request) {
Expand Down
6 changes: 3 additions & 3 deletions internal/http/request/client_ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"strings"
)

// IsTrustedIP checks if the given remote IP belongs to one of the trusted networks.
// IsTrustedIP reports whether the given remote IP address belongs to one of the trusted networks.
func IsTrustedIP(remoteIP string, trustedNetworks []string) bool {
if remoteIP == "@" || strings.HasPrefix(remoteIP, "/") {
return true
Expand All @@ -34,7 +34,7 @@ func IsTrustedIP(remoteIP string, trustedNetworks []string) bool {
return false
}

// FindClientIP returns the client real IP address based on trusted Reverse-Proxy HTTP headers.
// FindClientIP returns the real client IP address using trusted reverse-proxy headers when allowed.
func FindClientIP(r *http.Request, isTrustedProxyClient bool) string {
if isTrustedProxyClient {
headers := [...]string{"X-Forwarded-For", "X-Real-Ip"}
Expand All @@ -57,7 +57,7 @@ func FindClientIP(r *http.Request, isTrustedProxyClient bool) string {
return FindRemoteIP(r)
}

// FindRemoteIP returns remote client IP address without considering HTTP headers.
// FindRemoteIP returns the remote client IP address without considering HTTP headers.
func FindRemoteIP(r *http.Request) string {
remoteIP, _, err := net.SplitHostPort(r.RemoteAddr)
if err != nil {
Expand Down
Loading
Loading
0