diff --git a/README.md b/README.md index 66d30b0..7848e8b 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ go install ... ### Add a RSS feed or youtube channel -Currently RSS feeds, Atom feeds and Youtube channel links are supported. +Currently only RSS and Atom feeds and are supported. ```sh freed add "https://feed.url" diff --git a/cmd/add.go b/cmd/add.go index 02eff10..6f231de 100644 --- a/cmd/add.go +++ b/cmd/add.go @@ -31,8 +31,9 @@ var addCmd = &cobra.Command{ Long: `Validates and stores a feed in the application's database. Depending on the feed type, articles, videos, or updates are fetched right away. Supported types currently are: -- RSS -- Youtube Channel links`, +- RSS feeds +- Atom feeds +`, Run: func(cmd *cobra.Command, args []string) { feedName, articlesCount, err := internal.AddFeed(args[0]) diff --git a/cmd/list.go b/cmd/list.go new file mode 100644 index 0000000..abfe39b --- /dev/null +++ b/cmd/list.go @@ -0,0 +1,58 @@ +/* +Copyright © 2025 Dennis Schoepf + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +package cmd + +import ( + "freed/internal" + + "github.com/pterm/pterm" + "github.com/spf13/cobra" +) + +// listCmd represents the list command +var listCmd = &cobra.Command{ + Use: "list", + Aliases: []string{"ls"}, + Short: "Lists all currently stored feeds", + Long: `This command lists all currently stored feeds with some metadata and their IDs. In the future it is possible to manipulate these feeds by referencing their ID.`, + Example: `freed list +freed ls`, + Run: func(cmd *cobra.Command, args []string) { + tableData, err := internal.GetAllFeedsAsTable() + + if err != nil { + pterm.Error.Printf("Error listing feeds: %v\n", err) + return + } + + pterm.DefaultTable.WithHasHeader().WithBoxed().WithData(tableData).Render() + }, +} + +func init() { + rootCmd.AddCommand(listCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // listCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // listCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/internal/database/feed.go b/internal/database/feed.go index 7707473..eaf766f 100644 --- a/internal/database/feed.go +++ b/internal/database/feed.go @@ -1,16 +1,24 @@ package database -import "time" +import ( + "time" +) type FeedType string type Feed struct { + ID int64 Name string Url string - AddedAt *time.Time + CreatedAt *time.Time LastSyncedAt *time.Time } +type FeedWithArticleCount struct { + Feed + ArticleCount int +} + func (f Feed) Insert() (int64, error) { result, err := db.Exec("INSERT INTO feed (name, url) VALUES (?,?)", f.Name, f.Url) @@ -26,3 +34,28 @@ func (f Feed) Insert() (int64, error) { return id, nil } + +func FindAllFeedsWithArticleCount() (*[]FeedWithArticleCount, error) { + rows, err := db.Query("SELECT f.id, f.name, f.url, f.createdAt, f.lastSyncedAt, COUNT(a.id) FROM feed as f LEFT JOIN article as a ON a.feedId = f.id;") + if err != nil { + return nil, err + } + defer rows.Close() + + var feeds []FeedWithArticleCount + + for rows.Next() { + var feed FeedWithArticleCount + err := rows.Scan(&feed.ID, &feed.Name, &feed.Url, &feed.CreatedAt, &feed.LastSyncedAt, &feed.ArticleCount) + if err != nil { + return nil, err + } + feeds = append(feeds, feed) + } + + if err = rows.Err(); err != nil { + return nil, err + } + + return &feeds, nil +} diff --git a/internal/feed.go b/internal/feed.go index ea80454..4d28cf8 100644 --- a/internal/feed.go +++ b/internal/feed.go @@ -4,8 +4,10 @@ import ( "fmt" "freed/internal/database" "net/url" + "strconv" "github.com/mmcdole/gofeed" + "github.com/pterm/pterm" ) func AddFeed(feedUrl string) (string, int, error) { @@ -50,6 +52,34 @@ func AddFeed(feedUrl string) (string, int, error) { return feed.Title, len(articles), nil } +func GetAllFeedsAsTable() (pterm.TableData, error) { + feeds, err := database.FindAllFeedsWithArticleCount() + + if err != nil { + return nil, err + } + + tableData := pterm.TableData{} + headerRow := []string{"ID", "Name", "Url", "Item Count", "Created At", "Last Synced At"} + + tableData = append(tableData, headerRow) + + for _, feed := range *feeds { + rowData := []string{ + fmt.Sprintf("[%d]", feed.ID), + feed.Name, + feed.Url, + strconv.Itoa(feed.ArticleCount), + pterm.Gray(feed.CreatedAt), + pterm.Gray(feed.LastSyncedAt), + } + + tableData = append(tableData, rowData) + } + + return tableData, nil +} + func parseByUrl(u string) (*gofeed.Feed, error) { fp := gofeed.NewParser()