Using sfeed_update to it's full potential

It's no secret I'm a big fan of sfeed, I use the suite daily for my consooming needs wants. It's how I get new blog posts, new YouTube videos, even new Patreon posts using kemono.su.

This blog post is going to assume some basic knowledge of how sfeed works. If you don't have that knowledge, I implore you to give the README a quick scan. Don't delve too far though, you might accidentally read the rest of this article in there.

feeds()

A very basic feeds() function may look like this:

   feeds() {
      feed "Bruce Schneier" "https://www.schneier.com/feed/" "https://www.schneier.com/" "UTF-8"
   }

This feeds() function only contains one feed, that of Bruce Schneier (whom I suggest you subscribe to, always love reading his articles). What we're gonna do now is follow where this function is executed. The first thing that executes in sfeed_update, after some variables are set, is the main() function. This function is the heart of sfeed_update, it sets 2 variables, sets up traps for handling SIGINT and SIGTERM. After that preamble, it loads your configuration, or your sfeedrc. Hopefully you've put this in $HOME/.sfeed/sfeedrc, or specified where you have it when you launch sfeed_update by putting it as the first argument. So, let's say it loads the configuration above, with one feed item in feeds(). main() then makes a temporary directory and subdirectories, ensures your feeds directory exists (talk about this later), then runs your feeds() function.

This feed() (yeah, it's actually a function!) you've supplied then gets ran in an internal function called _feed(). This is a bit more complicated than the main() function, but it's pretty understandable. It sets the variables you've given it to more human-readable names than \(1, \)2 etc. It then downloads the RSS/ATOM file (with a function fetch() that we'll get to later), then attempts to check the decoding using sfeed_xmlenc. If it fails, it assumes utf-8. It then attempts to parse the RSS/ATOM file, then filter it if you have that set up. Then merge if you have a file already for that feed in your feeds directory. If it fails at any of these stages (or substages I've left out for brevity), it errors out and spits a failure message out to stdout. If, however, everything works okay, you get a message on stdout saying as such.

Customizing _feed()

So let us say, for example, you like to order your feeds in a directory structure. You have one directory for blogs, another for recipes, another for YouTube videos. By default, _feed() won't let you do this. Here's how it handles the name of the feed (with some variables resolved for legibility):

    name="$1"
    filename="$( printf '%s' "${name}" | tr '/' '_' )"
    sfeedfile="$HOME/.sfeed/feeds/${filename}"

As you might imagine, $sfeedfile is where sfeed_update will put the resulting feed file. So let's say you wanna add this directory functionality to _feed(). Due to how _feed() is structured, this is very easy. Here's what the preamble of _feed() might look like if you do implement this:

    name="$1"
    feedurl="$2"
    directory="$3"
    basesiteurl="$4"
    encoding="$5"
    
    filename="$(printf '%s' "${name}" | tr '/' '_' )"
    sfeedfile="${sfeedpath}/${directory}/${filename}"

All that functionality in such a brief time. Here's how the above feeds() function would look with this new implementation of _feed() and subsequently feed():

    feeds() {
      feed "Bruce Schneier" "https://www.schneier.com/feed/" "blogs" "https://www.schneier.com/" "UTF-8"
    }

Customizing fetch()

By default, this is how sfeed_update downloads new feed files:

	 curl -L --max-redirs 0 -H "User-Agent:" -f -s -m 15 \
	 	"$2" 2>/dev/null

$2 of course being the feed URL. Let's say, for example, you'd like to change how curl (or any other command) would run on a per-URL basis. This can be done quite easily with a case:

    url="$2"
    case $url in
      *.onion)
         curl -L --max-redirs 0 -H "User-Agent:" -f -s -m 15 \
            --socks5-hostname localhost:9050 \
            "$url"
      ;;
      *)
       curl -L --max-redirs 0 -H "User-Agent:" -f -s -m 15 \
         "$url" 2>/dev/null
      ;;
    esac

This'll make any URL you've defined with a .onion TLD be downloaded from your tor-daemon session. (You do have that set up, right anon?) You can also see how you might set this so you can have shorthand for certain things, like YouTube channel UCIDs. After all, it's probably fair to say any 'url' starting with UC is a YouTube channel. Go wild! Delve in more to how sfeed_update works. Smell the roses!


Happy consooming!