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 }