fix golint errors
This commit is contained in:
@@ -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
@@ -63,7 +63,7 @@ func main() {
|
||||
client := memos.NewClient(cfg.Memos.URL, cfg.Memos.Token)
|
||||
|
||||
// Search selector
|
||||
selector := search.NewSelector(client, store, cfg.Search, loc, logger)
|
||||
selector := search.NewSelector(client, store, &cfg.Search, loc, logger)
|
||||
|
||||
// Memory service
|
||||
memorySvc := memory.NewService(selector, store, loc, logger)
|
||||
@@ -71,6 +71,18 @@ func main() {
|
||||
// Web handler
|
||||
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
|
||||
srv := &http.Server{
|
||||
Addr: cfg.Web.Listen,
|
||||
@@ -84,13 +96,7 @@ func main() {
|
||||
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||
defer stop()
|
||||
|
||||
// Telegram bot
|
||||
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)
|
||||
}
|
||||
if tgBot != nil {
|
||||
go tgBot.Run(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ func (c *Client) ListMemos(ctx context.Context, filter string, pageSize int, pag
|
||||
}
|
||||
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 {
|
||||
return nil, fmt.Errorf("create request: %w", err)
|
||||
}
|
||||
@@ -79,7 +79,7 @@ func (c *Client) DownloadAttachment(ctx context.Context, att Attachment) ([]byte
|
||||
needsAuth = true
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, http.NoBody)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create request: %w", err)
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func weightedSelect(candidates []candidate, preferOlder bool, maxYearsBack int)
|
||||
total += score
|
||||
}
|
||||
|
||||
r := rand.Float64() * total
|
||||
r := rand.Float64() * total //nolint:gosec // non-cryptographic use
|
||||
var cumulative float64
|
||||
for i, s := range scores {
|
||||
cumulative += s
|
||||
|
||||
@@ -22,19 +22,16 @@ type Selector struct {
|
||||
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{
|
||||
client: client,
|
||||
store: store,
|
||||
cfg: cfg,
|
||||
cfg: *cfg,
|
||||
loc: loc,
|
||||
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.
|
||||
func (s *Selector) Select(ctx context.Context, today time.Time) (*Memory, error) {
|
||||
weights := s.cfg.TierWeights.AsSlice()
|
||||
@@ -248,7 +245,7 @@ func weightedTierOrder(weights [7]int) []int {
|
||||
break
|
||||
}
|
||||
|
||||
r := rand.IntN(totalWeight)
|
||||
r := rand.IntN(totalWeight) //nolint:gosec // non-cryptographic use
|
||||
cumulative := 0
|
||||
for i, e := range remaining {
|
||||
cumulative += e.weight
|
||||
|
||||
@@ -43,7 +43,7 @@ func (s *Storage) GetShowCounts(ctx context.Context, memoNames []string) (map[st
|
||||
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`,
|
||||
strings.Join(placeholders, ","))
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
_ "modernc.org/sqlite" // SQLite driver
|
||||
)
|
||||
|
||||
type Storage struct {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -93,8 +94,12 @@ func (b *Bot) nextSendTime() time.Time {
|
||||
hour := 9
|
||||
minute := 0
|
||||
if len(parts) == 2 {
|
||||
fmt.Sscanf(parts[0], "%d", &hour)
|
||||
fmt.Sscanf(parts[1], "%d", &minute)
|
||||
if h, err := strconv.Atoi(parts[0]); err == nil {
|
||||
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)
|
||||
@@ -185,7 +190,7 @@ type imageFile struct {
|
||||
|
||||
// downloadImages downloads image attachments, skipping failures.
|
||||
func (b *Bot) downloadImages(ctx context.Context, attachments []memos.Attachment) []imageFile {
|
||||
var files []imageFile
|
||||
files := make([]imageFile, 0, len(attachments))
|
||||
for _, att := range attachments {
|
||||
data, err := b.client.DownloadAttachment(ctx, att)
|
||||
if err != nil {
|
||||
|
||||
@@ -41,7 +41,7 @@ func formatMemory(mem *search.Memory, publicURL string) (mainText, captionText s
|
||||
|
||||
// Link to original
|
||||
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()
|
||||
mainText = truncateHTML(full, maxMessageLen)
|
||||
|
||||
@@ -80,21 +80,25 @@ func (h *Handler) handleMemory(w http.ResponseWriter, r *http.Request) {
|
||||
if err != nil {
|
||||
h.logger.Error("failed to get memory", "error", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
templates.ExecuteTemplate(w, "error.html", errorData{
|
||||
if err := templates.ExecuteTemplate(w, "error.html", errorData{
|
||||
Message: "Не удалось загрузить воспоминание",
|
||||
})
|
||||
}); err != nil {
|
||||
h.logger.Error("template render failed", "error", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if mem == nil {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
templates.ExecuteTemplate(w, "error.html", errorData{
|
||||
if err := templates.ExecuteTemplate(w, "error.html", errorData{
|
||||
Message: "Нет заметок для воспоминания",
|
||||
})
|
||||
}); err != nil {
|
||||
h.logger.Error("template render failed", "error", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var images []imageData
|
||||
images := make([]imageData, 0, len(mem.Memo.Attachments))
|
||||
for _, att := range mem.Memo.Attachments {
|
||||
if !att.IsImage() {
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user