feat: implement feed agg and browse

This commit is contained in:
Stevan Freeborn
2026-08-03 07:14:33 -05:00
parent f51b1b941a
commit 667f5f112b
12 changed files with 444 additions and 40 deletions
+90 -18
View File
@@ -5,14 +5,19 @@ import (
"context"
"fmt"
"net/url"
"os"
"os/signal"
"slices"
"strconv"
"strings"
"syscall"
"time"
"github.com/StevanFreeborn/gator/internal/database"
"github.com/StevanFreeborn/gator/internal/rss"
"github.com/StevanFreeborn/gator/internal/state"
"github.com/google/uuid"
"golang.org/x/term"
)
type Command struct {
@@ -54,6 +59,7 @@ func NewRegistry() *CommandRegistry {
followCommand(),
followingCommand(),
unfollowCommand(),
browseCommand(),
}
for _, cmd := range commands {
@@ -172,25 +178,60 @@ func usersCommand() *Command {
func aggCommand() *Command {
return newCommand("agg", func(s *state.State) error {
// if len(s.Arguments) == 0 {
// return fmt.Errorf("Did not receive expected feed argument")
// }
// feed := s.Arguments[0]
//
// validUrl, err := url.Parse(feed)
//
// if err != nil {
// return fmt.Errorf("Feed '%s' is not a valid url", feed)
// }
rssFeed, err := rss.FetchFeed(context.Background(), "https://www.wagslane.dev/index.xml")
if err != nil {
return err
if len(s.Arguments) == 0 {
return fmt.Errorf("Did not receive expected time between requests argument")
}
fmt.Printf("%v\n", rssFeed)
timeBetweenRequests := s.Arguments[0]
validDuration, err := time.ParseDuration(timeBetweenRequests)
if err != nil {
return fmt.Errorf("Time between requests argument '%s' not valid duration string", timeBetweenRequests)
}
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
oldState, err := term.MakeRaw(int(os.Stdin.Fd()))
if err != nil {
return fmt.Errorf("Failed to enable raw mode: %v", err)
}
defer term.Restore(int(os.Stdin.Fd()), oldState)
go func() {
buf := make([]byte, 1)
for {
n, err := os.Stdin.Read(buf)
if err != nil || n == 0 {
return
}
if buf[0] == 'q' || buf[0] == 'Q' || buf[0] == 3 {
cancel()
return
}
}
}()
ticker := time.NewTicker(validDuration)
defer ticker.Stop()
rss.ScrapeNextFeed(ctx, s)
fetchFeeds:
for {
select {
case <-ctx.Done():
fmt.Print("Stopping feed agg command\r\n")
break fetchFeeds
case <-ticker.C:
rss.ScrapeNextFeed(ctx, s)
}
}
return nil
})
@@ -321,7 +362,7 @@ func followingCommand() *Command {
}
for _, follow := range follows {
fmt.Printf("* %s", follow.FeedName)
fmt.Printf("* %s\n", follow.FeedName)
}
return nil
@@ -358,3 +399,34 @@ func unfollowCommand() *Command {
return nil
}))
}
func browseCommand() *Command {
return newCommand("browse", requiresLoggedInUser(func(s *state.State, currentUser database.User) error {
limit := int32(2)
if len(s.Arguments) > 0 {
parsedLimit, err := strconv.ParseInt(s.Arguments[0], 10, 32)
if err == nil {
limit = int32(parsedLimit)
}
}
getUserPostsParams := database.GetPostsForUserParams{
UserID: currentUser.ID,
Limit: limit,
}
posts, err := s.Database.GetPostsForUser(context.Background(), getUserPostsParams)
if err != nil {
return err
}
for _, post := range posts {
fmt.Printf("* %s - %s\n", post.FeedName, post.Title)
}
return nil
}))
}