123 lines
2.6 KiB
Go
123 lines
2.6 KiB
Go
package models
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Role string
|
|
|
|
const (
|
|
RoleAdmin Role = "admin"
|
|
RoleUser Role = "user"
|
|
)
|
|
|
|
type User struct {
|
|
ID int64
|
|
Username string
|
|
PasswordHash string
|
|
Role Role
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type Item struct {
|
|
ID int64
|
|
Name string
|
|
SearchQuery string
|
|
URL string
|
|
Category string
|
|
TargetPrice *float64
|
|
NtfyTopic string
|
|
NtfyPriority string
|
|
PollIntervalMinutes int
|
|
IncludeOutOfStock bool
|
|
MinPrice *float64
|
|
ExcludeKeywords string
|
|
Marketplaces []string
|
|
ListingType string
|
|
ActorActive string
|
|
ActorSold string
|
|
ActorPriceCompare string
|
|
UsePriceComparison bool
|
|
Active bool
|
|
LastPolledAt *time.Time
|
|
LastPollError string
|
|
BestPrice *float64
|
|
BestPriceStore string
|
|
BestPriceURL string
|
|
BestPriceImageURL string
|
|
BestPriceTitle string
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
}
|
|
|
|
type Result struct {
|
|
ID int64
|
|
ItemID int64
|
|
Title string
|
|
Price *float64
|
|
Currency string
|
|
URL string
|
|
Source string
|
|
ImageURL string
|
|
MatchedQuery string
|
|
Alerted bool
|
|
FoundAt time.Time
|
|
}
|
|
|
|
// SearchQueries returns the item's alias list. Splits on newline, comma, and
|
|
// semicolon; trims; drops blanks; dedupes case-insensitively. Result order is
|
|
// the user's input order (first occurrence wins).
|
|
func (it *Item) SearchQueries() []string {
|
|
return SplitList(it.SearchQuery, 10)
|
|
}
|
|
|
|
// ExcludeKeywordsList returns the item's exclude-keyword list, normalized the
|
|
// same way as SearchQueries.
|
|
func (it *Item) ExcludeKeywordsList() []string {
|
|
return SplitList(it.ExcludeKeywords, 20)
|
|
}
|
|
|
|
// SplitList splits a user-entered list on newline, comma, or semicolon,
|
|
// trims whitespace, drops empty entries, dedupes case-insensitively, and caps
|
|
// the result at max entries (0 = no cap).
|
|
func SplitList(s string, max int) []string {
|
|
if s == "" {
|
|
return nil
|
|
}
|
|
seen := map[string]bool{}
|
|
var out []string
|
|
for _, part := range strings.FieldsFunc(s, func(r rune) bool {
|
|
return r == '\n' || r == '\r' || r == ',' || r == ';'
|
|
}) {
|
|
t := strings.TrimSpace(part)
|
|
if t == "" {
|
|
continue
|
|
}
|
|
k := strings.ToLower(t)
|
|
if seen[k] {
|
|
continue
|
|
}
|
|
seen[k] = true
|
|
out = append(out, t)
|
|
if max > 0 && len(out) >= max {
|
|
break
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
type PricePoint struct {
|
|
ID int64
|
|
ItemID int64
|
|
Price float64
|
|
Store string
|
|
PolledAt time.Time
|
|
}
|
|
|
|
type Setting struct {
|
|
Key string
|
|
Value string
|
|
UpdatedAt time.Time
|
|
}
|