/* 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() feedChs := make([]chan *gofeed.Feed, len(urls)) errChs := make([]chan error, len(urls)) for i, url := range urls { feedCh := make(chan *gofeed.Feed) errCh := make(chan error) go func(url string) { feed, err := fp.ParseURL(url) feedCh <- feed errCh <- err }(url) feedChs[i] = feedCh errChs[i] = errCh } feeds := make([]*gofeed.Feed, len(urls)) errs := make([]error, len(urls)) for i := range feedChs { feeds[i] = <-feedChs[i] errs[i] = <-errChs[i] } 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", Short: "A brief description of your application", Long: `A longer description that spans multiple lines and likely contains examples and usage of using your application. For example: Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application.`, 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") }