5.8 KiB
5.8 KiB
Feeds Specification
Overview
The Feeds module allows users to subscribe to and read RSS/Atom feeds. It provides feed management, automatic fetching of new entries, and a clean reading experience for feed content.
Data Model
Feed
The Feed
entity has the following attributes:
Field | Type | Description |
---|---|---|
ID | string | Unique identifier for the feed (UUID) |
Title | string | Title of the feed |
URL | string | URL of the feed (RSS/Atom) |
Description | string | Description of the feed |
SiteURL | string | URL of the website associated with the feed |
ImageURL | string | URL of the feed's image or logo |
LastFetched | timestamp | When the feed was last fetched |
CreatedAt | timestamp | When the feed was added |
UpdatedAt | timestamp | When the feed was last updated |
Entry
The Entry
entity represents a single item in a feed:
Field | Type | Description |
---|---|---|
ID | string | Unique identifier for the entry (UUID) |
FeedID | string | ID of the parent feed |
Title | string | Title of the entry |
URL | string | URL of the entry |
Content | string | HTML content of the entry |
Summary | string | Summary or excerpt of the entry |
Author | string | Author of the entry |
Published | timestamp | When the entry was published |
Updated | timestamp | When the entry was last updated |
ReadAt | timestamp | When the entry was marked as read (null if unread) |
FullContent | string | Full content of the entry (if fetched separately) |
CreatedAt | timestamp | When the entry was added to the system |
UpdatedAt | timestamp | When the entry was last updated in the system |
UUID Generation
Both Feed and Entry entities have GORM BeforeCreate hooks which ensure that a UUID is automatically generated if the ID is not provided:
-
For the Feed entity:
func (f *Feed) BeforeCreate(tx *gorm.DB) error { if f.ID == "" { f.ID = uuid.New().String() } return nil }
-
For the Entry entity:
func (e *Entry) BeforeCreate(tx *gorm.DB) error { if e.ID == "" { e.ID = uuid.New().String() } return nil }
Features
Feed Management
- Subscribe to Feed: Users can subscribe to new feeds by providing a URL
- Unsubscribe from Feed: Users can unsubscribe from feeds
- List Feeds: Users can view a list of all subscribed feeds
- View Feed Details: Users can view details about a specific feed
Entry Management
- List Entries: Users can view a list of entries from all feeds or a specific feed
- View Entry: Users can view the content of a specific entry
- Mark as Read: Users can mark entries as read
- Mark as Unread: Users can mark entries as unread
- Filter Entries: Users can filter entries by read/unread status
Feed Fetching
- Manual Refresh: Users can manually refresh feeds to fetch new entries
- Automatic Refresh: The system can automatically refresh feeds at regular intervals
- Content Extraction: For feeds that only provide summaries, the system can fetch the full content
API Endpoints
Method | Endpoint | Description |
---|---|---|
GET | /api/feeds | List all feeds |
POST | /api/feeds | Subscribe to a new feed |
GET | /api/feeds/:id | Get a specific feed by ID |
PUT | /api/feeds/:id | Update a specific feed |
DELETE | /api/feeds/:id | Unsubscribe from a feed |
GET | /api/feeds/:id/entries | List entries for a specific feed |
GET | /api/feeds/entries | List entries from all feeds |
GET | /api/feeds/entries/:id | Get a specific entry by ID |
PUT | /api/feeds/entries/:id/read | Mark an entry as read |
PUT | /api/feeds/entries/:id/unread | Mark an entry as unread |
POST | /api/feeds/refresh | Refresh all feeds |
POST | /api/feeds/:id/refresh | Refresh a specific feed |
Frontend Routes
Route | Description |
---|---|
/feeds | List of subscribed feeds |
/feeds/:id | View entries from a specific feed |
/feeds/entries/:id | View a specific entry |
Implementation Details
Feed Parsing
The system uses the gofeed
library to parse RSS and Atom feeds:
func (s *Service) parseFeed(feedURL string) (*gofeed.Feed, error) {
fp := gofeed.NewParser()
feed, err := fp.ParseURL(feedURL)
if err != nil {
return nil, fmt.Errorf("failed to parse feed: %w", err)
}
return feed, nil
}
Feed Refreshing
When refreshing a feed, the system:
- Fetches the feed content from the URL
- Parses the feed to extract entries
- Compares entries with existing ones to identify new entries
- Saves new entries to the database
Content Extraction
For feeds that only provide summaries, the system can optionally fetch the full content of entries:
- Extract the URL of the entry
- Fetch the web page at that URL
- Use a content extraction algorithm to extract the main content
- Save the extracted content as the entry's full content
User Interface
Feed List
- Displays a list of subscribed feeds with titles, descriptions, and icons
- Shows the number of unread entries for each feed
- Provides buttons for refreshing, editing, and unsubscribing
Entry List
- Displays a list of entries from all feeds or a specific feed
- Shows entry titles, summaries, publication dates, and read status
- Provides filters for read/unread status
- Includes buttons for marking as read/unread
Entry Viewer
- Displays the entry content in a clean, reader-friendly format
- Shows the entry title, author, and publication date
- Provides buttons for marking as read/unread and returning to the list
- Includes a link to the original article
Subscribe Form
- Input field for the feed URL
- Automatic detection of feed format (RSS/Atom)
- Preview of feed details before subscribing