Jelajahi Sumber

refactor(misc): replace fmt.Errorf with errors.New where possible

No need to to invoke the whole Printf machinery for constant strings. While
this shouldn't have an impact on memory consumption nor allocation (as
constructing errors to return is never in a hot path), this should reduce a bit
the code size, as errors.New will be inlined to a simple struct initialization
instead of a function call.
jvoisin 6 bulan lalu
induk
melakukan
dd44fbcc76
37 mengubah file dengan 88 tambahan dan 60 penghapusan
  1. 1 1
      client/client.go
  2. 2 1
      internal/cli/reset_password.go
  3. 3 2
      internal/config/parser.go
  4. 4 3
      internal/config/validators.go
  5. 4 5
      internal/googlereader/handler.go
  6. 2 1
      internal/googlereader/item.go
  7. 2 2
      internal/googlereader/request_modifier.go
  8. 2 1
      internal/integration/apprise/apprise.go
  9. 2 1
      internal/integration/espial/espial.go
  10. 2 1
      internal/integration/instapaper/instapaper.go
  11. 2 1
      internal/integration/linkace/linkace.go
  12. 2 1
      internal/integration/linkding/linkding.go
  13. 2 1
      internal/integration/linktaco/linktaco.go
  14. 2 1
      internal/integration/linkwarden/linkwarden.go
  15. 2 1
      internal/integration/notion/notion.go
  16. 2 1
      internal/integration/nunuxkeeper/nunuxkeeper.go
  17. 2 2
      internal/integration/pinboard/pinboard.go
  18. 2 1
      internal/integration/pushover/pushover.go
  19. 2 1
      internal/integration/raindrop/raindrop.go
  20. 2 1
      internal/integration/readeck/readeck.go
  21. 2 1
      internal/integration/readwise/readwise.go
  22. 2 1
      internal/integration/shaarli/shaarli.go
  23. 2 1
      internal/integration/shiori/shiori.go
  24. 2 1
      internal/integration/wallabag/wallabag.go
  25. 2 1
      internal/integration/webhook/webhook.go
  26. 3 2
      internal/reader/processor/bilibili.go
  27. 2 1
      internal/reader/readability/readability_test.go
  28. 3 3
      internal/reader/sanitizer/srcset.go
  29. 2 2
      internal/reader/urlcleaner/urlcleaner.go
  30. 2 1
      internal/storage/api_key.go
  31. 3 2
      internal/storage/user_session.go
  32. 2 1
      internal/systemd/systemd.go
  33. 3 2
      internal/template/functions.go
  34. 3 2
      internal/urllib/url.go
  35. 2 2
      internal/validator/enclosure.go
  36. 5 4
      internal/validator/entry.go
  37. 4 4
      internal/validator/validator.go

+ 1 - 1
client/client.go

@@ -125,7 +125,7 @@ func (c *Client) UserByID(userID int64) (*User, error) {
 
 
 // UserByUsername returns a single user.
 // UserByUsername returns a single user.
 func (c *Client) UserByUsername(username string) (*User, error) {
 func (c *Client) UserByUsername(username string) (*User, error) {
-	body, err := c.request.Get(fmt.Sprintf("/v1/users/%s", username))
+	body, err := c.request.Get("/v1/users/" + username)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}

+ 2 - 1
internal/cli/reset_password.go

@@ -4,6 +4,7 @@
 package cli // import "miniflux.app/v2/internal/cli"
 package cli // import "miniflux.app/v2/internal/cli"
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 
 
 	"miniflux.app/v2/internal/model"
 	"miniflux.app/v2/internal/model"
@@ -19,7 +20,7 @@ func resetPassword(store *storage.Storage) {
 	}
 	}
 
 
 	if user == nil {
 	if user == nil {
-		printErrorAndExit(fmt.Errorf("user not found"))
+		printErrorAndExit(errors.New("user not found"))
 	}
 	}
 
 
 	userModificationRequest := &model.UserModificationRequest{
 	userModificationRequest := &model.UserModificationRequest{

+ 3 - 2
internal/config/parser.go

@@ -7,6 +7,7 @@ import (
 	"bufio"
 	"bufio"
 	"bytes"
 	"bytes"
 	"crypto/rand"
 	"crypto/rand"
+	"errors"
 	"fmt"
 	"fmt"
 	"io"
 	"io"
 	"net/url"
 	"net/url"
@@ -60,7 +61,7 @@ func (cp *configParser) postParsing() error {
 
 
 	scheme := strings.ToLower(parsedURL.Scheme)
 	scheme := strings.ToLower(parsedURL.Scheme)
 	if scheme != "https" && scheme != "http" {
 	if scheme != "https" && scheme != "http" {
-		return fmt.Errorf("BASE_URL scheme must be http or https")
+		return errors.New("BASE_URL scheme must be http or https")
 	}
 	}
 
 
 	cp.options.options["BASE_URL"].ParsedStringValue = baseURL
 	cp.options.options["BASE_URL"].ParsedStringValue = baseURL
@@ -294,7 +295,7 @@ func readSecretFileValue(filename string) (string, error) {
 
 
 	value := string(bytes.TrimSpace(data))
 	value := string(bytes.TrimSpace(data))
 	if value == "" {
 	if value == "" {
-		return "", fmt.Errorf("secret file is empty")
+		return "", errors.New("secret file is empty")
 	}
 	}
 
 
 	return value, nil
 	return value, nil

+ 4 - 3
internal/config/validators.go

@@ -4,6 +4,7 @@
 package config // import "miniflux.app/v2/internal/config"
 package config // import "miniflux.app/v2/internal/config"
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"slices"
 	"slices"
 	"strconv"
 	"strconv"
@@ -29,7 +30,7 @@ func validateListChoices(inputValues, choices []string) error {
 func validateGreaterThan(rawValue string, min int) error {
 func validateGreaterThan(rawValue string, min int) error {
 	intValue, err := strconv.Atoi(rawValue)
 	intValue, err := strconv.Atoi(rawValue)
 	if err != nil {
 	if err != nil {
-		return fmt.Errorf("value must be an integer")
+		return errors.New("value must be an integer")
 	}
 	}
 	if intValue > min {
 	if intValue > min {
 		return nil
 		return nil
@@ -40,7 +41,7 @@ func validateGreaterThan(rawValue string, min int) error {
 func validateGreaterOrEqualThan(rawValue string, min int) error {
 func validateGreaterOrEqualThan(rawValue string, min int) error {
 	intValue, err := strconv.Atoi(rawValue)
 	intValue, err := strconv.Atoi(rawValue)
 	if err != nil {
 	if err != nil {
-		return fmt.Errorf("value must be an integer")
+		return errors.New("value must be an integer")
 	}
 	}
 	if intValue >= min {
 	if intValue >= min {
 		return nil
 		return nil
@@ -51,7 +52,7 @@ func validateGreaterOrEqualThan(rawValue string, min int) error {
 func validateRange(rawValue string, min, max int) error {
 func validateRange(rawValue string, min, max int) error {
 	intValue, err := strconv.Atoi(rawValue)
 	intValue, err := strconv.Atoi(rawValue)
 	if err != nil {
 	if err != nil {
-		return fmt.Errorf("value must be an integer")
+		return errors.New("value must be an integer")
 	}
 	}
 	if intValue < min || intValue > max {
 	if intValue < min || intValue > max {
 		return fmt.Errorf("value must be between %d and %d", min, max)
 		return fmt.Errorf("value must be between %d and %d", min, max)

+ 4 - 5
internal/googlereader/handler.go

@@ -126,8 +126,7 @@ func checkOutputFormat(r *http.Request) error {
 		output = request.QueryStringParam(r, "output", "")
 		output = request.QueryStringParam(r, "output", "")
 	}
 	}
 	if output != "json" {
 	if output != "json" {
-		err := fmt.Errorf("googlereader: only json output is supported")
-		return err
+		return errors.New("googlereader: only json output is supported")
 	}
 	}
 	return nil
 	return nil
 }
 }
@@ -280,7 +279,7 @@ func (h *handler) editTagHandler(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 	if len(addTags) == 0 && len(removeTags) == 0 {
 	if len(addTags) == 0 && len(removeTags) == 0 {
-		err = fmt.Errorf("googlreader: add or/and remove tags should be supplied")
+		err = errors.New("googlreader: add or/and remove tags should be supplied")
 		json.ServerError(w, r, err)
 		json.ServerError(w, r, err)
 		return
 		return
 	}
 	}
@@ -1014,7 +1013,7 @@ func (h *handler) userInfoHandler(w http.ResponseWriter, r *http.Request) {
 		json.ServerError(w, r, err)
 		json.ServerError(w, r, err)
 		return
 		return
 	}
 	}
-	userInfo := userInfoResponse{UserID: fmt.Sprint(user.ID), UserName: user.Username, UserProfileID: fmt.Sprint(user.ID), UserEmail: user.Username}
+	userInfo := userInfoResponse{UserID: strconv.FormatInt(user.ID, 10), UserName: user.Username, UserProfileID: strconv.FormatInt(user.ID, 10), UserEmail: user.Username}
 	json.OK(w, r, userInfo)
 	json.OK(w, r, userInfo)
 }
 }
 
 
@@ -1048,7 +1047,7 @@ func (h *handler) streamItemIDsHandler(w http.ResponseWriter, r *http.Request) {
 	)
 	)
 
 
 	if len(rm.Streams) != 1 {
 	if len(rm.Streams) != 1 {
-		json.ServerError(w, r, fmt.Errorf("googlereader: only one stream type expected"))
+		json.ServerError(w, r, errors.New("googlereader: only one stream type expected"))
 		return
 		return
 	}
 	}
 	switch rm.Streams[0].Type {
 	switch rm.Streams[0].Type {

+ 2 - 1
internal/googlereader/item.go

@@ -4,6 +4,7 @@
 package googlereader // import "miniflux.app/v2/internal/googlereader"
 package googlereader // import "miniflux.app/v2/internal/googlereader"
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"strconv"
 	"strconv"
@@ -58,7 +59,7 @@ func parseItemID(itemIDValue string) (int64, error) {
 func parseItemIDsFromRequest(r *http.Request) ([]int64, error) {
 func parseItemIDsFromRequest(r *http.Request) ([]int64, error) {
 	items := r.Form[paramItemIDs]
 	items := r.Form[paramItemIDs]
 	if len(items) == 0 {
 	if len(items) == 0 {
-		return nil, fmt.Errorf("googlereader: no items requested")
+		return nil, errors.New("googlereader: no items requested")
 	}
 	}
 
 
 	itemIDs := make([]int64, len(items))
 	itemIDs := make([]int64, len(items))

+ 2 - 2
internal/googlereader/request_modifier.go

@@ -49,8 +49,8 @@ func (r RequestModifiers) String() string {
 
 
 	results = append(results, fmt.Sprintf("Count: %d", r.Count))
 	results = append(results, fmt.Sprintf("Count: %d", r.Count))
 	results = append(results, fmt.Sprintf("Offset: %d", r.Offset))
 	results = append(results, fmt.Sprintf("Offset: %d", r.Offset))
-	results = append(results, fmt.Sprintf("Sort Direction: %s", r.SortDirection))
-	results = append(results, fmt.Sprintf("Continuation Token: %s", r.ContinuationToken))
+	results = append(results, "Sort Direction: "+r.SortDirection)
+	results = append(results, "Continuation Token: "+r.ContinuationToken)
 	results = append(results, fmt.Sprintf("Start Time: %d", r.StartTime))
 	results = append(results, fmt.Sprintf("Start Time: %d", r.StartTime))
 	results = append(results, fmt.Sprintf("Stop Time: %d", r.StopTime))
 	results = append(results, fmt.Sprintf("Stop Time: %d", r.StopTime))
 
 

+ 2 - 1
internal/integration/apprise/apprise.go

@@ -6,6 +6,7 @@ package apprise
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"log/slog"
 	"log/slog"
 	"net/http"
 	"net/http"
@@ -29,7 +30,7 @@ func NewClient(serviceURL, baseURL string) *Client {
 
 
 func (c *Client) SendNotification(feed *model.Feed, entries model.Entries) error {
 func (c *Client) SendNotification(feed *model.Feed, entries model.Entries) error {
 	if c.baseURL == "" || c.servicesURL == "" {
 	if c.baseURL == "" || c.servicesURL == "" {
-		return fmt.Errorf("apprise: missing base URL or services URL")
+		return errors.New("apprise: missing base URL or services URL")
 	}
 	}
 
 
 	for _, entry := range entries {
 	for _, entry := range entries {

+ 2 - 1
internal/integration/espial/espial.go

@@ -6,6 +6,7 @@ package espial // import "miniflux.app/v2/internal/integration/espial"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"time"
 	"time"
@@ -27,7 +28,7 @@ func NewClient(baseURL, apiKey string) *Client {
 
 
 func (c *Client) CreateLink(entryURL, entryTitle, espialTags string) error {
 func (c *Client) CreateLink(entryURL, entryTitle, espialTags string) error {
 	if c.baseURL == "" || c.apiKey == "" {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("espial: missing base URL or API key")
+		return errors.New("espial: missing base URL or API key")
 	}
 	}
 
 
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/add")
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/add")

+ 2 - 1
internal/integration/instapaper/instapaper.go

@@ -4,6 +4,7 @@
 package instapaper // import "miniflux.app/v2/internal/integration/instapaper"
 package instapaper // import "miniflux.app/v2/internal/integration/instapaper"
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"net/url"
 	"net/url"
@@ -25,7 +26,7 @@ func NewClient(username, password string) *Client {
 
 
 func (c *Client) AddURL(entryURL, entryTitle string) error {
 func (c *Client) AddURL(entryURL, entryTitle string) error {
 	if c.username == "" || c.password == "" {
 	if c.username == "" || c.password == "" {
-		return fmt.Errorf("instapaper: missing username or password")
+		return errors.New("instapaper: missing username or password")
 	}
 	}
 
 
 	values := url.Values{}
 	values := url.Values{}

+ 2 - 1
internal/integration/linkace/linkace.go

@@ -3,6 +3,7 @@ package linkace
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"strings"
 	"strings"
@@ -28,7 +29,7 @@ func NewClient(baseURL, apiKey, tags string, private bool, checkDisabled bool) *
 
 
 func (c *Client) AddURL(entryURL, entryTitle string) error {
 func (c *Client) AddURL(entryURL, entryTitle string) error {
 	if c.baseURL == "" || c.apiKey == "" {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("linkace: missing base URL or API key")
+		return errors.New("linkace: missing base URL or API key")
 	}
 	}
 
 
 	tagsSplitFn := func(c rune) bool {
 	tagsSplitFn := func(c rune) bool {

+ 2 - 1
internal/integration/linkding/linkding.go

@@ -6,6 +6,7 @@ package linkding // import "miniflux.app/v2/internal/integration/linkding"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"strings"
 	"strings"
@@ -30,7 +31,7 @@ func NewClient(baseURL, apiKey, tags string, unread bool) *Client {
 
 
 func (c *Client) CreateBookmark(entryURL, entryTitle string) error {
 func (c *Client) CreateBookmark(entryURL, entryTitle string) error {
 	if c.baseURL == "" || c.apiKey == "" {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("linkding: missing base URL or API key")
+		return errors.New("linkding: missing base URL or API key")
 	}
 	}
 
 
 	tagsSplitFn := func(c rune) bool {
 	tagsSplitFn := func(c rune) bool {

+ 2 - 1
internal/integration/linktaco/linktaco.go

@@ -6,6 +6,7 @@ package linktaco // import "miniflux.app/v2/internal/integration/linktaco"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"strings"
 	"strings"
@@ -44,7 +45,7 @@ func NewClient(apiToken, orgSlug, tags, visibility string) *Client {
 
 
 func (c *Client) CreateBookmark(entryURL, entryTitle, entryContent string) error {
 func (c *Client) CreateBookmark(entryURL, entryTitle, entryContent string) error {
 	if c.apiToken == "" || c.orgSlug == "" {
 	if c.apiToken == "" || c.orgSlug == "" {
-		return fmt.Errorf("linktaco: missing API token or organization slug")
+		return errors.New("linktaco: missing API token or organization slug")
 	}
 	}
 
 
 	description := entryContent
 	description := entryContent

+ 2 - 1
internal/integration/linkwarden/linkwarden.go

@@ -6,6 +6,7 @@ package linkwarden // import "miniflux.app/v2/internal/integration/linkwarden"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"time"
 	"time"
@@ -27,7 +28,7 @@ func NewClient(baseURL, apiKey string) *Client {
 
 
 func (c *Client) CreateBookmark(entryURL, entryTitle string) error {
 func (c *Client) CreateBookmark(entryURL, entryTitle string) error {
 	if c.baseURL == "" || c.apiKey == "" {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("linkwarden: missing base URL or API key")
+		return errors.New("linkwarden: missing base URL or API key")
 	}
 	}
 
 
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/v1/links")
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/v1/links")

+ 2 - 1
internal/integration/notion/notion.go

@@ -6,6 +6,7 @@ package notion
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"time"
 	"time"
@@ -26,7 +27,7 @@ func NewClient(apiToken, pageID string) *Client {
 
 
 func (c *Client) UpdateDocument(entryURL string, entryTitle string) error {
 func (c *Client) UpdateDocument(entryURL string, entryTitle string) error {
 	if c.apiToken == "" || c.pageID == "" {
 	if c.apiToken == "" || c.pageID == "" {
-		return fmt.Errorf("notion: missing API token or page ID")
+		return errors.New("notion: missing API token or page ID")
 	}
 	}
 
 
 	apiEndpoint := "https://api.notion.com/v1/blocks/" + c.pageID + "/children"
 	apiEndpoint := "https://api.notion.com/v1/blocks/" + c.pageID + "/children"

+ 2 - 1
internal/integration/nunuxkeeper/nunuxkeeper.go

@@ -6,6 +6,7 @@ package nunuxkeeper // import "miniflux.app/v2/internal/integration/nunuxkeeper"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"time"
 	"time"
@@ -27,7 +28,7 @@ func NewClient(baseURL, apiKey string) *Client {
 
 
 func (c *Client) AddEntry(entryURL, entryTitle, entryContent string) error {
 func (c *Client) AddEntry(entryURL, entryTitle, entryContent string) error {
 	if c.baseURL == "" || c.apiKey == "" {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("nunux-keeper: missing base URL or API key")
+		return errors.New("nunux-keeper: missing base URL or API key")
 	}
 	}
 
 
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/v2/documents")
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/v2/documents")

+ 2 - 2
internal/integration/pinboard/pinboard.go

@@ -14,8 +14,8 @@ import (
 	"miniflux.app/v2/internal/version"
 	"miniflux.app/v2/internal/version"
 )
 )
 
 
-var errPostNotFound = fmt.Errorf("pinboard: post not found")
-var errMissingCredentials = fmt.Errorf("pinboard: missing auth token")
+var errPostNotFound = errors.New("pinboard: post not found")
+var errMissingCredentials = errors.New("pinboard: missing auth token")
 
 
 const defaultClientTimeout = 10 * time.Second
 const defaultClientTimeout = 10 * time.Second
 
 

+ 2 - 1
internal/integration/pushover/pushover.go

@@ -5,6 +5,7 @@ package pushover // import "miniflux.app/v2/internal/integration/pushover"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"log/slog"
 	"log/slog"
 	"net/http"
 	"net/http"
@@ -72,7 +73,7 @@ func New(user, token string, priority int, device, urlPrefix string) *Client {
 
 
 func (c *Client) SendMessages(feed *model.Feed, entries model.Entries) error {
 func (c *Client) SendMessages(feed *model.Feed, entries model.Entries) error {
 	if c.token == "" || c.user == "" {
 	if c.token == "" || c.user == "" {
-		return fmt.Errorf("pushover token and user are required")
+		return errors.New("pushover token and user are required")
 	}
 	}
 	for _, entry := range entries {
 	for _, entry := range entries {
 		msg := &Message{
 		msg := &Message{

+ 2 - 1
internal/integration/raindrop/raindrop.go

@@ -6,6 +6,7 @@ package raindrop // import "miniflux.app/v2/internal/integration/raindrop"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"strings"
 	"strings"
@@ -29,7 +30,7 @@ func NewClient(token, collectionID, tags string) *Client {
 // https://developer.raindrop.io/v1/raindrops/single#create-raindrop
 // https://developer.raindrop.io/v1/raindrops/single#create-raindrop
 func (c *Client) CreateRaindrop(entryURL, entryTitle string) error {
 func (c *Client) CreateRaindrop(entryURL, entryTitle string) error {
 	if c.token == "" {
 	if c.token == "" {
-		return fmt.Errorf("raindrop: missing token")
+		return errors.New("raindrop: missing token")
 	}
 	}
 
 
 	var request *http.Request
 	var request *http.Request

+ 2 - 1
internal/integration/readeck/readeck.go

@@ -6,6 +6,7 @@ package readeck // import "miniflux.app/v2/internal/integration/readeck"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"mime/multipart"
 	"mime/multipart"
 	"net/http"
 	"net/http"
@@ -31,7 +32,7 @@ func NewClient(baseURL, apiKey, labels string, onlyURL bool) *Client {
 
 
 func (c *Client) CreateBookmark(entryURL, entryTitle string, entryContent string) error {
 func (c *Client) CreateBookmark(entryURL, entryTitle string, entryContent string) error {
 	if c.baseURL == "" || c.apiKey == "" {
 	if c.baseURL == "" || c.apiKey == "" {
-		return fmt.Errorf("readeck: missing base URL or API key")
+		return errors.New("readeck: missing base URL or API key")
 	}
 	}
 
 
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/bookmarks/")
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/bookmarks/")

+ 2 - 1
internal/integration/readwise/readwise.go

@@ -8,6 +8,7 @@ package readwise // import "miniflux.app/v2/internal/integration/readwise"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"time"
 	"time"
@@ -30,7 +31,7 @@ func NewClient(apiKey string) *Client {
 
 
 func (c *Client) CreateDocument(entryURL string) error {
 func (c *Client) CreateDocument(entryURL string) error {
 	if c.apiKey == "" {
 	if c.apiKey == "" {
-		return fmt.Errorf("readwise: missing API key")
+		return errors.New("readwise: missing API key")
 	}
 	}
 
 
 	requestBody, err := json.Marshal(&readwiseDocument{
 	requestBody, err := json.Marshal(&readwiseDocument{

+ 2 - 1
internal/integration/shaarli/shaarli.go

@@ -9,6 +9,7 @@ import (
 	"crypto/sha512"
 	"crypto/sha512"
 	"encoding/base64"
 	"encoding/base64"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"time"
 	"time"
@@ -30,7 +31,7 @@ func NewClient(baseURL, apiSecret string) *Client {
 
 
 func (c *Client) CreateLink(entryURL, entryTitle string) error {
 func (c *Client) CreateLink(entryURL, entryTitle string) error {
 	if c.baseURL == "" || c.apiSecret == "" {
 	if c.baseURL == "" || c.apiSecret == "" {
-		return fmt.Errorf("shaarli: missing base URL or API secret")
+		return errors.New("shaarli: missing base URL or API secret")
 	}
 	}
 
 
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/v1/links")
 	apiEndpoint, err := urllib.JoinBaseURLAndPath(c.baseURL, "/api/v1/links")

+ 2 - 1
internal/integration/shiori/shiori.go

@@ -6,6 +6,7 @@ package shiori // import "miniflux.app/v2/internal/integration/shiori"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"time"
 	"time"
@@ -28,7 +29,7 @@ func NewClient(baseURL, username, password string) *Client {
 
 
 func (c *Client) CreateBookmark(entryURL, entryTitle string) error {
 func (c *Client) CreateBookmark(entryURL, entryTitle string) error {
 	if c.baseURL == "" || c.username == "" || c.password == "" {
 	if c.baseURL == "" || c.username == "" || c.password == "" {
-		return fmt.Errorf("shiori: missing base URL, username or password")
+		return errors.New("shiori: missing base URL, username or password")
 	}
 	}
 
 
 	token, err := c.authenticate()
 	token, err := c.authenticate()

+ 2 - 1
internal/integration/wallabag/wallabag.go

@@ -6,6 +6,7 @@ package wallabag // import "miniflux.app/v2/internal/integration/wallabag"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"net/url"
 	"net/url"
@@ -34,7 +35,7 @@ func NewClient(baseURL, clientID, clientSecret, username, password, tags string,
 
 
 func (c *Client) CreateEntry(entryURL, entryTitle, entryContent string) error {
 func (c *Client) CreateEntry(entryURL, entryTitle, entryContent string) error {
 	if c.baseURL == "" || c.clientID == "" || c.clientSecret == "" || c.username == "" || c.password == "" {
 	if c.baseURL == "" || c.clientID == "" || c.clientSecret == "" || c.username == "" || c.password == "" {
-		return fmt.Errorf("wallabag: missing base URL, client ID, client secret, username or password")
+		return errors.New("wallabag: missing base URL, client ID, client secret, username or password")
 	}
 	}
 
 
 	accessToken, err := c.getAccessToken()
 	accessToken, err := c.getAccessToken()

+ 2 - 1
internal/integration/webhook/webhook.go

@@ -6,6 +6,7 @@ package webhook // import "miniflux.app/v2/internal/integration/webhook"
 import (
 import (
 	"bytes"
 	"bytes"
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"net/http"
 	"net/http"
 	"time"
 	"time"
@@ -113,7 +114,7 @@ func (c *Client) SendNewEntriesWebhookEvent(feed *model.Feed, entries model.Entr
 
 
 func (c *Client) makeRequest(eventType string, payload any) error {
 func (c *Client) makeRequest(eventType string, payload any) error {
 	if c.webhookURL == "" {
 	if c.webhookURL == "" {
-		return fmt.Errorf(`webhook: missing webhook URL`)
+		return errors.New(`webhook: missing webhook URL`)
 	}
 	}
 
 
 	requestBody, err := json.Marshal(payload)
 	requestBody, err := json.Marshal(payload)

+ 3 - 2
internal/reader/processor/bilibili.go

@@ -5,6 +5,7 @@ package processor // import "miniflux.app/v2/internal/reader/processor"
 
 
 import (
 import (
 	"encoding/json"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"fmt"
 	"log/slog"
 	"log/slog"
 	"regexp"
 	"regexp"
@@ -75,12 +76,12 @@ func fetchBilibiliWatchTime(websiteURL string) (int, error) {
 
 
 	data, ok := result["data"].(map[string]any)
 	data, ok := result["data"].(map[string]any)
 	if !ok {
 	if !ok {
-		return 0, fmt.Errorf("data field not found or not an object")
+		return 0, errors.New("data field not found or not an object")
 	}
 	}
 
 
 	duration, ok := data["duration"].(float64)
 	duration, ok := data["duration"].(float64)
 	if !ok {
 	if !ok {
-		return 0, fmt.Errorf("duration not found or not a number")
+		return 0, errors.New("duration not found or not a number")
 	}
 	}
 	intDuration := int(duration)
 	intDuration := int(duration)
 	durationMin := intDuration / 60
 	durationMin := intDuration / 60

+ 2 - 1
internal/reader/readability/readability_test.go

@@ -5,6 +5,7 @@ package readability // import "miniflux.app/v2/internal/reader/readability"
 
 
 import (
 import (
 	"bytes"
 	"bytes"
+	"errors"
 	"fmt"
 	"fmt"
 	"os"
 	"os"
 	"strings"
 	"strings"
@@ -2301,5 +2302,5 @@ func TestExtractContentWithBrokenReader(t *testing.T) {
 type brokenReader struct{}
 type brokenReader struct{}
 
 
 func (br *brokenReader) Read(p []byte) (n int, err error) {
 func (br *brokenReader) Read(p []byte) (n int, err error) {
-	return 0, fmt.Errorf("simulated read error")
+	return 0, errors.New("simulated read error")
 }
 }

+ 3 - 3
internal/reader/sanitizer/srcset.go

@@ -4,7 +4,7 @@
 package sanitizer
 package sanitizer
 
 
 import (
 import (
-	"fmt"
+	"errors"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 )
 )
@@ -54,11 +54,11 @@ func parseImageCandidate(input string) (*imageCandidate, error) {
 		return &imageCandidate{ImageURL: parts[0]}, nil
 		return &imageCandidate{ImageURL: parts[0]}, nil
 	case 2:
 	case 2:
 		if !isValidWidthOrDensityDescriptor(parts[1]) {
 		if !isValidWidthOrDensityDescriptor(parts[1]) {
-			return nil, fmt.Errorf(`srcset: invalid descriptor`)
+			return nil, errors.New(`srcset: invalid descriptor`)
 		}
 		}
 		return &imageCandidate{ImageURL: parts[0], Descriptor: parts[1]}, nil
 		return &imageCandidate{ImageURL: parts[0], Descriptor: parts[1]}, nil
 	default:
 	default:
-		return nil, fmt.Errorf(`srcset: invalid number of descriptors`)
+		return nil, errors.New(`srcset: invalid number of descriptors`)
 	}
 	}
 }
 }
 
 

+ 2 - 2
internal/reader/urlcleaner/urlcleaner.go

@@ -4,7 +4,7 @@
 package urlcleaner // import "miniflux.app/v2/internal/reader/urlcleaner"
 package urlcleaner // import "miniflux.app/v2/internal/reader/urlcleaner"
 
 
 import (
 import (
-	"fmt"
+	"errors"
 	"net/url"
 	"net/url"
 	"strings"
 	"strings"
 )
 )
@@ -97,7 +97,7 @@ var trackingParamsOutbound = map[string]bool{
 
 
 func RemoveTrackingParameters(parsedFeedURL, parsedSiteURL, parsedInputUrl *url.URL) (string, error) {
 func RemoveTrackingParameters(parsedFeedURL, parsedSiteURL, parsedInputUrl *url.URL) (string, error) {
 	if parsedFeedURL == nil || parsedSiteURL == nil || parsedInputUrl == nil {
 	if parsedFeedURL == nil || parsedSiteURL == nil || parsedInputUrl == nil {
-		return "", fmt.Errorf("urlcleaner: one of the URLs is nil")
+		return "", errors.New("urlcleaner: one of the URLs is nil")
 	}
 	}
 
 
 	queryParams := parsedInputUrl.Query()
 	queryParams := parsedInputUrl.Query()

+ 2 - 1
internal/storage/api_key.go

@@ -4,13 +4,14 @@
 package storage // import "miniflux.app/v2/internal/storage"
 package storage // import "miniflux.app/v2/internal/storage"
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 
 
 	"miniflux.app/v2/internal/crypto"
 	"miniflux.app/v2/internal/crypto"
 	"miniflux.app/v2/internal/model"
 	"miniflux.app/v2/internal/model"
 )
 )
 
 
-var ErrAPIKeyNotFound = fmt.Errorf("store: API Key not found")
+var ErrAPIKeyNotFound = errors.New("store: API Key not found")
 
 
 // APIKeyExists checks if an API Key with the same description exists.
 // APIKeyExists checks if an API Key with the same description exists.
 func (s *Storage) APIKeyExists(userID int64, description string) bool {
 func (s *Storage) APIKeyExists(userID int64, description string) bool {

+ 3 - 2
internal/storage/user_session.go

@@ -6,6 +6,7 @@ package storage // import "miniflux.app/v2/internal/storage"
 import (
 import (
 	"crypto/rand"
 	"crypto/rand"
 	"database/sql"
 	"database/sql"
+	"errors"
 	"fmt"
 	"fmt"
 	"time"
 	"time"
 
 
@@ -138,7 +139,7 @@ func (s *Storage) RemoveUserSessionByToken(userID int64, token string) error {
 	}
 	}
 
 
 	if count != 1 {
 	if count != 1 {
-		return fmt.Errorf(`store: nothing has been removed`)
+		return errors.New(`store: nothing has been removed`)
 	}
 	}
 
 
 	return nil
 	return nil
@@ -158,7 +159,7 @@ func (s *Storage) RemoveUserSessionByID(userID, sessionID int64) error {
 	}
 	}
 
 
 	if count != 1 {
 	if count != 1 {
-		return fmt.Errorf(`store: nothing has been removed`)
+		return errors.New(`store: nothing has been removed`)
 	}
 	}
 
 
 	return nil
 	return nil

+ 2 - 1
internal/systemd/systemd.go

@@ -4,6 +4,7 @@
 package systemd // import "miniflux.app/v2/internal/systemd"
 package systemd // import "miniflux.app/v2/internal/systemd"
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"net"
 	"net"
 	"os"
 	"os"
@@ -40,7 +41,7 @@ func WatchdogInterval() (time.Duration, error) {
 	}
 	}
 
 
 	if s <= 0 {
 	if s <= 0 {
-		return 0, fmt.Errorf(`systemd: error WATCHDOG_USEC must be a positive number`)
+		return 0, errors.New(`systemd: error WATCHDOG_USEC must be a positive number`)
 	}
 	}
 
 
 	return time.Duration(s) * time.Microsecond, nil
 	return time.Duration(s) * time.Microsecond, nil

+ 3 - 2
internal/template/functions.go

@@ -4,6 +4,7 @@
 package template // import "miniflux.app/v2/internal/template"
 package template // import "miniflux.app/v2/internal/template"
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"html/template"
 	"html/template"
 	"math"
 	"math"
@@ -153,13 +154,13 @@ func csp(user *model.User, nonce string) string {
 
 
 func dict(values ...any) (map[string]any, error) {
 func dict(values ...any) (map[string]any, error) {
 	if len(values)%2 != 0 {
 	if len(values)%2 != 0 {
-		return nil, fmt.Errorf("dict expects an even number of arguments")
+		return nil, errors.New("dict expects an even number of arguments")
 	}
 	}
 	dict := make(map[string]any, len(values)/2)
 	dict := make(map[string]any, len(values)/2)
 	for i := 0; i < len(values); i += 2 {
 	for i := 0; i < len(values); i += 2 {
 		key, ok := values[i].(string)
 		key, ok := values[i].(string)
 		if !ok {
 		if !ok {
-			return nil, fmt.Errorf("dict keys must be strings")
+			return nil, errors.New("dict keys must be strings")
 		}
 		}
 		dict[key] = values[i+1]
 		dict[key] = values[i+1]
 	}
 	}

+ 3 - 2
internal/urllib/url.go

@@ -4,6 +4,7 @@
 package urllib // import "miniflux.app/v2/internal/urllib"
 package urllib // import "miniflux.app/v2/internal/urllib"
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 	"net/url"
 	"net/url"
 	"strings"
 	"strings"
@@ -103,11 +104,11 @@ func DomainWithoutWWW(websiteURL string) string {
 // JoinBaseURLAndPath returns a URL string with the provided path elements joined together.
 // JoinBaseURLAndPath returns a URL string with the provided path elements joined together.
 func JoinBaseURLAndPath(baseURL, path string) (string, error) {
 func JoinBaseURLAndPath(baseURL, path string) (string, error) {
 	if baseURL == "" {
 	if baseURL == "" {
-		return "", fmt.Errorf("empty base URL")
+		return "", errors.New("empty base URL")
 	}
 	}
 
 
 	if path == "" {
 	if path == "" {
-		return "", fmt.Errorf("empty path")
+		return "", errors.New("empty path")
 	}
 	}
 
 
 	_, err := url.Parse(baseURL)
 	_, err := url.Parse(baseURL)

+ 2 - 2
internal/validator/enclosure.go

@@ -4,14 +4,14 @@
 package validator
 package validator
 
 
 import (
 import (
-	"fmt"
+	"errors"
 
 
 	"miniflux.app/v2/internal/model"
 	"miniflux.app/v2/internal/model"
 )
 )
 
 
 func ValidateEnclosureUpdateRequest(request *model.EnclosureUpdateRequest) error {
 func ValidateEnclosureUpdateRequest(request *model.EnclosureUpdateRequest) error {
 	if request.MediaProgression < 0 {
 	if request.MediaProgression < 0 {
-		return fmt.Errorf(`media progression must an positive integer`)
+		return errors.New(`media progression must an positive integer`)
 	}
 	}
 
 
 	return nil
 	return nil

+ 5 - 4
internal/validator/entry.go

@@ -4,6 +4,7 @@
 package validator // import "miniflux.app/v2/internal/validator"
 package validator // import "miniflux.app/v2/internal/validator"
 
 
 import (
 import (
+	"errors"
 	"fmt"
 	"fmt"
 
 
 	"miniflux.app/v2/internal/model"
 	"miniflux.app/v2/internal/model"
@@ -12,7 +13,7 @@ import (
 // ValidateEntriesStatusUpdateRequest validates a status update for a list of entries.
 // ValidateEntriesStatusUpdateRequest validates a status update for a list of entries.
 func ValidateEntriesStatusUpdateRequest(request *model.EntriesStatusUpdateRequest) error {
 func ValidateEntriesStatusUpdateRequest(request *model.EntriesStatusUpdateRequest) error {
 	if len(request.EntryIDs) == 0 {
 	if len(request.EntryIDs) == 0 {
-		return fmt.Errorf(`the list of entries cannot be empty`)
+		return errors.New(`the list of entries cannot be empty`)
 	}
 	}
 
 
 	return ValidateEntryStatus(request.Status)
 	return ValidateEntryStatus(request.Status)
@@ -35,17 +36,17 @@ func ValidateEntryOrder(order string) error {
 		return nil
 		return nil
 	}
 	}
 
 
-	return fmt.Errorf(`invalid entry order, valid order values are: "id", "status", "changed_at", "published_at", "created_at", "category_title", "category_id", "title", "author"`)
+	return errors.New(`invalid entry order, valid order values are: "id", "status", "changed_at", "published_at", "created_at", "category_title", "category_id", "title", "author"`)
 }
 }
 
 
 // ValidateEntryModification makes sure the entry modification is valid.
 // ValidateEntryModification makes sure the entry modification is valid.
 func ValidateEntryModification(request *model.EntryUpdateRequest) error {
 func ValidateEntryModification(request *model.EntryUpdateRequest) error {
 	if request.Title != nil && *request.Title == "" {
 	if request.Title != nil && *request.Title == "" {
-		return fmt.Errorf(`the entry title cannot be empty`)
+		return errors.New(`the entry title cannot be empty`)
 	}
 	}
 
 
 	if request.Content != nil && *request.Content == "" {
 	if request.Content != nil && *request.Content == "" {
-		return fmt.Errorf(`the entry content cannot be empty`)
+		return errors.New(`the entry content cannot be empty`)
 	}
 	}
 
 
 	return nil
 	return nil

+ 4 - 4
internal/validator/validator.go

@@ -4,7 +4,7 @@
 package validator // import "miniflux.app/v2/internal/validator"
 package validator // import "miniflux.app/v2/internal/validator"
 
 
 import (
 import (
-	"fmt"
+	"errors"
 	"net/url"
 	"net/url"
 	"regexp"
 	"regexp"
 	"strings"
 	"strings"
@@ -15,11 +15,11 @@ var domainRegex = regexp.MustCompile(`^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.
 // ValidateRange makes sure the offset/limit values are valid.
 // ValidateRange makes sure the offset/limit values are valid.
 func ValidateRange(offset, limit int) error {
 func ValidateRange(offset, limit int) error {
 	if offset < 0 {
 	if offset < 0 {
-		return fmt.Errorf(`offset value should be >= 0`)
+		return errors.New(`offset value should be >= 0`)
 	}
 	}
 
 
 	if limit < 0 {
 	if limit < 0 {
-		return fmt.Errorf(`limit value should be >= 0`)
+		return errors.New(`limit value should be >= 0`)
 	}
 	}
 
 
 	return nil
 	return nil
@@ -32,7 +32,7 @@ func ValidateDirection(direction string) error {
 		return nil
 		return nil
 	}
 	}
 
 
-	return fmt.Errorf(`invalid direction, valid direction values are: "asc" or "desc"`)
+	return errors.New(`invalid direction, valid direction values are: "asc" or "desc"`)
 }
 }
 
 
 // IsValidRegex verifies if the regex can be compiled.
 // IsValidRegex verifies if the regex can be compiled.