/* Copyright © 2024 filifa 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 ( "fmt" "html" "log" "os" "strings" "text/template" "github.com/mmcdole/gofeed" "github.com/spf13/cobra" ) var output string // formatItem returns an individual item formatted as a string for printing. func formatItem(item *gofeed.Item, tmpl *template.Template) (string, error) { b := new(strings.Builder) err := tmpl.Execute(b, item) return html.UnescapeString(b.String()), err } // parseFeeds parses the feeds at the given urls in parallel and returns them, // along with any parsing errors. func parseFeeds(urls []string) ([]*gofeed.Feed, []error) { fp := gofeed.NewParser() feeds := make([]*gofeed.Feed, len(urls)) errs := make([]error, len(urls)) done := make(chan int) for i, url := range urls { go func(i int, url string) { feed, err := fp.ParseURL(url) feeds[i] = feed errs[i] = err done <- i }(i, url) } for i := 0; i < len(urls); i++ { <-done } return feeds, errs } func rssfetch(cmd *cobra.Command, urls []string) { tmpl, err := template.New("out").Parse(output) if err != nil { log.Fatal(err) } feeds, errs := parseFeeds(urls) for _, err := range errs { if err != nil { log.Fatal(err) } } for _, feed := range feeds { for _, item := range feed.Items { out, err := formatItem(item, tmpl) if err != nil { log.Fatal(err) } fmt.Printf("%s", out) } } } // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "rssfetch [url ...]", Short: "rssfetch outputs items contained in rss feeds", Long: `rssfetch outputs items contained in rss feeds. You can specify the output format with the -o flag. For instance, -o "{{.Title}}" will only output the title of each item.`, Run: rssfetch, Args: cobra.MinimumNArgs(1), } // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { err := rootCmd.Execute() if err != nil { os.Exit(1) } } func init() { // Here you will define your flags and configuration settings. // Cobra supports persistent flags, which, if defined here, // will be global for your application. // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.rssfetch.yaml)") // Cobra also supports local flags, which will only run // when this action is called directly. rootCmd.Flags().StringVarP(&output, "output", "o", "{{.Title}}\n\n{{.Description}}\n\n{{.Link}}\n", "output format") }