Files
commons/models.go
primal 60d24e4a1e Rewrite handle derivation for 63-char AT Protocol limit
Previously constrained to 18 chars (old PDS restriction), now uses
the full 63-char label limit. Preserves full hostname in handles
(e.g., calmchristmas-substack-com) with shortening only when needed.
Removes PublishAccount field from Feed struct in favor of runtime
derivation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-05 16:30:38 -05:00

97 lines
3.2 KiB
Go

package commons
import (
"time"
)
// Feed represents a discovered RSS/Atom feed with metadata
type Feed struct {
URL string `json:"url"`
Type string `json:"type"` // "rss", "atom", "json", or "unknown"
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Language string `json:"language,omitempty"`
// Timing
LastCheckedAt time.Time `json:"last_checked_at,omitempty"` // feed_check: when last checked
// Cache headers for conditional requests
ETag string `json:"etag,omitempty"`
LastModified string `json:"last_modified,omitempty"`
// Status: PUBLISH, STANDBY, IGNORE
Status string `json:"status"`
LastError string `json:"last_error,omitempty"`
// Computed from items table (not stored in feeds table)
ItemCount int `json:"item_count,omitempty"`
// Adaptive check interval
MissCount int `json:"miss_count"` // Consecutive checks with no new items
}
// Enclosure represents a media attachment (audio, video, image)
type Enclosure struct {
URL string `json:"url"`
Type string `json:"type"` // MIME type (audio/mpeg, image/jpeg, etc.)
}
// Item represents an individual entry/article from a feed
type Item struct {
FeedURL string `json:"feed_url"`
Link string `json:"link"` // Primary key (with feed_url)
Title string `json:"title,omitempty"`
Description string `json:"description,omitempty"`
Author string `json:"author,omitempty"`
PubDate time.Time `json:"pub_date,omitempty"`
// Media attachments
Enclosure *Enclosure `json:"enclosure,omitempty"` // Primary enclosure (podcast audio, etc.)
ImageURLs []string `json:"image_urls,omitempty"` // Image URLs extracted from description
Tags []string `json:"tags,omitempty"` // Category/tag strings from feed
}
// ShortURL represents a shortened URL mapping
type ShortURL struct {
Code string `json:"code"`
OriginalURL string `json:"original_url"`
ItemGUID string `json:"item_guid,omitempty"`
FeedURL string `json:"feed_url,omitempty"`
CreatedAt time.Time `json:"created_at"`
ClickCount int `json:"click_count"`
}
// Click represents a click event on a short URL
type Click struct {
ID int64 `json:"id"`
ShortCode string `json:"short_code"`
ClickedAt time.Time `json:"clicked_at"`
Referrer string `json:"referrer,omitempty"`
UserAgent string `json:"user_agent,omitempty"`
IPHash string `json:"ip_hash,omitempty"`
Country string `json:"country,omitempty"`
}
// DashboardStats holds all statistics for the dashboard
type DashboardStats struct {
// Feed stats by status
TotalFeeds int `json:"total_feeds"`
PublishFeeds int `json:"publish_feeds"` // status='PUBLISH'
StandbyFeeds int `json:"standby_feeds"` // status='STANDBY'
IgnoreFeeds int `json:"ignore_feeds"` // status='IGNORE'
// Feed stats by type
RSSFeeds int `json:"rss_feeds"`
AtomFeeds int `json:"atom_feeds"`
JSONFeeds int `json:"json_feeds"`
UnknownFeeds int `json:"unknown_feeds"`
// Processing rates (per minute)
FeedCheckRate int `json:"feed_check_rate"` // feed_check per minute
// Timing
UpdatedAt time.Time `json:"updated_at"`
}