fix golint errors

This commit is contained in:
2026-02-12 18:00:32 +03:00
parent a058b622e3
commit ccabeee1f1
10 changed files with 74 additions and 28 deletions
+34
View File
@@ -0,0 +1,34 @@
linters:
enable:
- bodyclose
- errcheck
- errorlint
- goconst
- gocritic
- gofmt
- gosec
- gosimple
- govet
- ineffassign
- misspell
- noctx
- prealloc
- revive
- staticcheck
- typecheck
- unconvert
- unparam
- unused
- wastedassign
linters-settings:
gocritic:
enabled-tags:
- diagnostic
- style
- performance
revive:
rules:
- name: blank-imports
- name: exported
disabled: true
+14 -8
View File
@@ -63,7 +63,7 @@ func main() {
client := memos.NewClient(cfg.Memos.URL, cfg.Memos.Token) client := memos.NewClient(cfg.Memos.URL, cfg.Memos.Token)
// Search selector // Search selector
selector := search.NewSelector(client, store, cfg.Search, loc, logger) selector := search.NewSelector(client, store, &cfg.Search, loc, logger)
// Memory service // Memory service
memorySvc := memory.NewService(selector, store, loc, logger) memorySvc := memory.NewService(selector, store, loc, logger)
@@ -71,6 +71,18 @@ func main() {
// Web handler // Web handler
handler := web.NewHandler(memorySvc, cfg.Memos.URL, cfg.Memos.PublicURL, cfg.General.AllowLoadMore, logger) handler := web.NewHandler(memorySvc, cfg.Memos.URL, cfg.Memos.PublicURL, cfg.General.AllowLoadMore, logger)
// Telegram bot
var tgBot *telegram.Bot
if cfg.Telegram.Enabled {
var err error
tgBot, err = telegram.NewBot(cfg.Telegram, memorySvc, client, cfg.Memos.URL, cfg.Memos.PublicURL, cfg.General.AllowLoadMore, loc, logger)
if err != nil {
logger.Error("failed to create telegram bot", "error", err)
store.Close()
os.Exit(1) //nolint:gocritic // store.Close() called above; linter doesn't track manual cleanup
}
}
// HTTP server // HTTP server
srv := &http.Server{ srv := &http.Server{
Addr: cfg.Web.Listen, Addr: cfg.Web.Listen,
@@ -84,13 +96,7 @@ func main() {
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop() defer stop()
// Telegram bot if tgBot != nil {
if cfg.Telegram.Enabled {
tgBot, err := telegram.NewBot(cfg.Telegram, memorySvc, client, cfg.Memos.URL, cfg.Memos.PublicURL, cfg.General.AllowLoadMore, loc, logger)
if err != nil {
logger.Error("failed to create telegram bot", "error", err)
os.Exit(1)
}
go tgBot.Run(ctx) go tgBot.Run(ctx)
} }
+2 -2
View File
@@ -43,7 +43,7 @@ func (c *Client) ListMemos(ctx context.Context, filter string, pageSize int, pag
} }
u.RawQuery = q.Encode() u.RawQuery = q.Encode()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), http.NoBody)
if err != nil { if err != nil {
return nil, fmt.Errorf("create request: %w", err) return nil, fmt.Errorf("create request: %w", err)
} }
@@ -79,7 +79,7 @@ func (c *Client) DownloadAttachment(ctx context.Context, att Attachment) ([]byte
needsAuth = true needsAuth = true
} }
req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil) req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, http.NoBody)
if err != nil { if err != nil {
return nil, fmt.Errorf("create request: %w", err) return nil, fmt.Errorf("create request: %w", err)
} }
+1 -1
View File
@@ -54,7 +54,7 @@ func weightedSelect(candidates []candidate, preferOlder bool, maxYearsBack int)
total += score total += score
} }
r := rand.Float64() * total r := rand.Float64() * total //nolint:gosec // non-cryptographic use
var cumulative float64 var cumulative float64
for i, s := range scores { for i, s := range scores {
cumulative += s cumulative += s
+3 -6
View File
@@ -22,19 +22,16 @@ type Selector struct {
logger *slog.Logger logger *slog.Logger
} }
func NewSelector(client *memos.Client, store *storage.Storage, cfg config.SearchConfig, loc *time.Location, logger *slog.Logger) *Selector { func NewSelector(client *memos.Client, store *storage.Storage, cfg *config.SearchConfig, loc *time.Location, logger *slog.Logger) *Selector {
return &Selector{ return &Selector{
client: client, client: client,
store: store, store: store,
cfg: cfg, cfg: *cfg,
loc: loc, loc: loc,
logger: logger, logger: logger,
} }
} }
// tierFunc returns date ranges for a given tier.
type tierFunc func(today time.Time, maxYears int, loc *time.Location) []DateRange
// Select runs the full search algorithm and returns one Memory for the given day. // Select runs the full search algorithm and returns one Memory for the given day.
func (s *Selector) Select(ctx context.Context, today time.Time) (*Memory, error) { func (s *Selector) Select(ctx context.Context, today time.Time) (*Memory, error) {
weights := s.cfg.TierWeights.AsSlice() weights := s.cfg.TierWeights.AsSlice()
@@ -248,7 +245,7 @@ func weightedTierOrder(weights [7]int) []int {
break break
} }
r := rand.IntN(totalWeight) r := rand.IntN(totalWeight) //nolint:gosec // non-cryptographic use
cumulative := 0 cumulative := 0
for i, e := range remaining { for i, e := range remaining {
cumulative += e.weight cumulative += e.weight
+1 -1
View File
@@ -43,7 +43,7 @@ func (s *Storage) GetShowCounts(ctx context.Context, memoNames []string) (map[st
args[i] = name args[i] = name
} }
query := fmt.Sprintf( query := fmt.Sprintf( //nolint:gosec // placeholders are always "?"
`SELECT memo_name, COUNT(*) FROM show_history WHERE memo_name IN (%s) GROUP BY memo_name`, `SELECT memo_name, COUNT(*) FROM show_history WHERE memo_name IN (%s) GROUP BY memo_name`,
strings.Join(placeholders, ",")) strings.Join(placeholders, ","))
+1 -1
View File
@@ -5,7 +5,7 @@ import (
"database/sql" "database/sql"
"fmt" "fmt"
_ "modernc.org/sqlite" _ "modernc.org/sqlite" // SQLite driver
) )
type Storage struct { type Storage struct {
+8 -3
View File
@@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"log/slog" "log/slog"
"strconv"
"strings" "strings"
"time" "time"
@@ -93,8 +94,12 @@ func (b *Bot) nextSendTime() time.Time {
hour := 9 hour := 9
minute := 0 minute := 0
if len(parts) == 2 { if len(parts) == 2 {
fmt.Sscanf(parts[0], "%d", &hour) if h, err := strconv.Atoi(parts[0]); err == nil {
fmt.Sscanf(parts[1], "%d", &minute) hour = h
}
if m, err := strconv.Atoi(parts[1]); err == nil {
minute = m
}
} }
target := time.Date(now.Year(), now.Month(), now.Day(), hour, minute, 0, 0, b.loc) target := time.Date(now.Year(), now.Month(), now.Day(), hour, minute, 0, 0, b.loc)
@@ -185,7 +190,7 @@ type imageFile struct {
// downloadImages downloads image attachments, skipping failures. // downloadImages downloads image attachments, skipping failures.
func (b *Bot) downloadImages(ctx context.Context, attachments []memos.Attachment) []imageFile { func (b *Bot) downloadImages(ctx context.Context, attachments []memos.Attachment) []imageFile {
var files []imageFile files := make([]imageFile, 0, len(attachments))
for _, att := range attachments { for _, att := range attachments {
data, err := b.client.DownloadAttachment(ctx, att) data, err := b.client.DownloadAttachment(ctx, att)
if err != nil { if err != nil {
+1 -1
View File
@@ -41,7 +41,7 @@ func formatMemory(mem *search.Memory, publicURL string) (mainText, captionText s
// Link to original // Link to original
memoURL := fmt.Sprintf("%s/%s", publicURL, mem.Memo.Name) memoURL := fmt.Sprintf("%s/%s", publicURL, mem.Memo.Name)
b.WriteString(fmt.Sprintf("\n\n<a href=\"%s\">Оригинал</a>", memoURL)) b.WriteString("\n\n<a href=\"" + memoURL + "\">Оригинал</a>")
full := b.String() full := b.String()
mainText = truncateHTML(full, maxMessageLen) mainText = truncateHTML(full, maxMessageLen)
+9 -5
View File
@@ -80,21 +80,25 @@ func (h *Handler) handleMemory(w http.ResponseWriter, r *http.Request) {
if err != nil { if err != nil {
h.logger.Error("failed to get memory", "error", err) h.logger.Error("failed to get memory", "error", err)
w.WriteHeader(http.StatusInternalServerError) w.WriteHeader(http.StatusInternalServerError)
templates.ExecuteTemplate(w, "error.html", errorData{ if err := templates.ExecuteTemplate(w, "error.html", errorData{
Message: "Не удалось загрузить воспоминание", Message: "Не удалось загрузить воспоминание",
}) }); err != nil {
h.logger.Error("template render failed", "error", err)
}
return return
} }
if mem == nil { if mem == nil {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
templates.ExecuteTemplate(w, "error.html", errorData{ if err := templates.ExecuteTemplate(w, "error.html", errorData{
Message: "Нет заметок для воспоминания", Message: "Нет заметок для воспоминания",
}) }); err != nil {
h.logger.Error("template render failed", "error", err)
}
return return
} }
var images []imageData images := make([]imageData, 0, len(mem.Memo.Attachments))
for _, att := range mem.Memo.Attachments { for _, att := range mem.Memo.Attachments {
if !att.IsImage() { if !att.IsImage() {
continue continue