# -*- sh -*-
# SFEED="$HOME/.sfeed"
USER_AGENT='Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0'
# sfeedpath="$SFEED/feeds"
maxjobs="$(nproc)"
### Feeds #######################################################
feeds() {
## feed NAME FEED_URL BASE_URL ENCODING # defined by sfeedrc(5).
# I want to add some extra fields after these.
feeds_planets
feeds_youtube
feeds_podcasts
feeds_friends
feeds_people
feeds_news
feeds_smolweb
feeds_comics
feeds_misc
feeds_me
}
feeds_planets() {
feed "Planet Emacs" "https://planet.emacslife.com/atom.xml" "https://planet.emacslife.com/" ""
feed "r/emacs" "https://i.reddit.com/r/emacs.rss" "https://i.reddit.com/r/emacs" ""
feed "Planet Lisp" "https://planet.lisp.org/rss20.xml" "https://planet.lisp.org/" ""
feed "Planet Scheme" "https://planet.scheme.org/atom.xml" "https://planet.scheme.org/" ""
}
yt_feed() { # yt_feed TITLE CHANNEL_ID
feed "$1 [yt]" "https://www.youtube.com/feeds/videos.xml?channel_id=$2" "https://youtube.com/channel/$2"
}
feeds_youtube() {
yt_feed "3Blue1Brown" "UCYO_jab_esuFRV4b17AJtAw"
yt_feed "AB - Ancienne Belgique" "UCUVAw2kdxJlcfCdEcdgXv5A"
yt_feed "Adam Ragusea" "UC9_p50tH3WmMslWRWKnM7dQ"
yt_feed "Babish Culinary Universe" "UCJHA_jMfCvEnv-3kRjTCQXw"
yt_feed "Baggers" "UCMV8p6Lb-bd6UZtTc_QD4zA"
yt_feed "Case Duckworth" "UC92gRJdnUYklVu4pvj9n0Lw"
yt_feed "Claire Saffitz x Dessert Person" "UCvw6Y1kr_8bp6B5m1dqNyiw"
yt_feed "Computerphile" "UC9-y-6csu5WGm29I7JiwpnA"
yt_feed "EBRPL Career Center" "UCIvntuaxP7PyaJDeHE_9E8Q"
yt_feed "EmacsConf and Emacs hangouts" "UCwuyodzTl_KdEKNuJmeo99A"
yt_feed "Gavin Freeborn" "UCJetJ7nDNLlEzDLXv7KIo0w"
yt_feed "Henry Homesweet" "UCZqjwc1Wy5t1rsviYYsJiYg"
yt_feed "Howard Abrams" "UCVHICXXtKG7rZgtC5xonNdQ"
yt_feed "Ignite Talks" "UCZotK8ZPTUNLMeW5Q6T0cKg"
yt_feed "Jake B" "UCBMMB7Yi0eyFuY95Qn2o0Yg"
yt_feed "James Tomasino" "UCbTp1BYjpuhDRG5OmgIT8iw"
yt_feed "jan Misali" "UCJOh5FKisc0hUlEeWFBlD-w"
yt_feed "J Duckworth Animations" "UCtAEaNVrNxAUy2VSRPD_PYQ"
yt_feed "Jelle's Marble Runs" "UCYJdpnjuSWVOLgGT9fIzL0g"
yt_feed "John Kitchin" "UCQp2VLAOlvq142YN3JO3y8w"
yt_feed "karthik" "UCbh_g91w0T6OYp40xFrtnhA"
yt_feed "Ken Forkish" "UCvVvFZd0e86bLbd5FdgYiUg"
yt_feed "Lex Fridman" "UCSHZKyawb77ixDdsGog4iWA"
yt_feed "LockPickingLawyer" "UCm9K6rby98W8JigLoZOh6FQ"
yt_feed "Maangchi" "UC8gFadPgK2r1ndqLI04Xvvw"
yt_feed "Mike Zamansky" "UCxkMDXQ5qzYOgXPRnOBrp1w"
yt_feed "MIT OpenCourseWare" "UCEBb1b_L6zDS3xTUrIALZOw"
yt_feed "My Analog Journal" "UC8TZwtZ17WKFJSmwTZQpBTA"
yt_feed "Nat's What I Reckon" "UCEFW1E8QzP-hKxjO2Rj68wg"
yt_feed "Now You See It" "UCWTFGPpNQ0Ms6afXhaWDiRw"
yt_feed "Numberphile" "UCoxcjq-8xIDTYp3uz647V5A"
yt_feed "Philosophy Tube" "UC2PA-AKmVpU6NKCGtZq_rKQ"
yt_feed "PronunciationManual" "UCqDSLtXeZsGc3dtVb5MW13g"
yt_feed "Protesilaos Stavrou" "UC0uTPqBCFIpZxlz_Lv1tk_g"
yt_feed "RailCowGirl" "UCj-Xm8j6WBgKY8OG7s9r2vQ"
yt_feed "Simone Giertz" "UC3KEoMzNz8eYnwBC34RaKCQ"
yt_feed "Steve Yegge" "UC2RCcnTltR3HMQOYVqwmweA"
yt_feed "System Crafters" "UCAiiOTio8Yu69c3XnR7nQBQ"
yt_feed "Tasting History with Max Miller" "UCsaGKqPZnGp_7N80hcHySGQ"
yt_feed "Technology Connections" "UCy0tKL1T7wFoYcxCe0xjN6Q"
yt_feed "Too Many Zooz" "UCtjXVqMVzBIgU0SO8AV0vPg"
yt_feed "Townsends" "UCxr2d4As312LulcajAkKJYw"
yt_feed "Unitarian Church of Baton Rouge" "UClrqHvbiFM-1hn931ZmAPFw"
yt_feed "Vulf" "UCtWuB1D_E3mcyYThA9iKggQ"
yt_feed "WFTDA: Women's Flat Track Derby Association" "UC7eMWpvytqd3gYAqxTl9w7g"
yt_feed "Zach Anner" "UCPTVYxUoYWhNa8J7GzIGnyQ"
yt_feed "Andrew Tropin" "UCuj_loxODrOPxSsXDfJmpng"
yt_feed "Animist" "UCweDxCT5Fiykk3uHqPKqLWg"
yt_feed "Chris Were Digital" "UCAPR27YUyxmgwm3Wc2WSHLw"
yt_feed "Esoterica" "UCoydhtfFSk1fZXNRnkGnneQ"
yt_feed "FOSDEM" "UC9NuJImUbaSNKiwF2bdSfAw"
}
feeds_podcasts() {
feed "Tilde Whirl Tildeverse Podcast" "https://tilde.town/~dozens/podcast/rss.xml" "https://tilde.town/~dozens/podcast/" ""
feed "trash cat tech cat" "https://podcast.librepunk.club/tctc/ogg.xml" "https://podcast.librepunk.club/tctc/" ""
feed "Hacker Public Radio" "https://hackerpublicradio.org/hpr_ogg_rss.php" "https://hackerpublicradio.org/" ""
feed "Levar Burton Reads" "https://feeds.simplecast.com/LDNgBXht"
}
feeds_friends() {
feed "lipu pi jan Niko" "https://tilde.town/~nihilazo/index.xml" "https://tilde.town/~nihilazo/" ""
feed "chrismanbrown.gitlab.io (dozens)" "https://chrismanbrown.gitlab.io/rss.xml" "https://chrismanbrown.gitlab.io/" ""
feed "Dozens and Dragons" "https://dozensanddragons.neocities.org/rss.xml" "https://dozensanddragons.neocities.org/" ""
feed "dozens: Society For Putting Things On Top Of Other Things" "https://society.neocities.org/rss.xml" "https://society.neocities.org/" ""
feed "dozens: vgnfdblg" "https://supervegan.neocities.org/feed.xml" "https://supervegan.neocities.org/" ""
feed "dozens: backgammon" "http://tilde.town/~dozens/backgammon/rss.xml" "http://tilde.town/~dozens/backgammon/" ""
feed "dozens: It's Pro Toad and Superb Owl" "https://git.tilde.town/dozens/protoadandsuperbowl/raw/branch/master/feed.xml" "https://git.tilde.town/dozens/protoadandsuperbowl/" ""
feed "dozens dreams" "https://tilde.team/~dozens/dreams/rss.xml" "https://tilde.team/~dozens/dreams/" ""
feed "dozens: write.as" "https://write.tildeverse.org/dozens/feed/" "https://write.tildeverse.org/dozens/" ""
feed "dozens css art" "http://tilde.town/~dozens/cssart/feed.xml" "http://tilde.town/~dozens/cssart/" ""
feed "Benjamin Wil" "https://benjaminwil.info/feed.xml" "https://benjaminwil.info/" ""
feed "(lambda (x) (create x))" "http://lambdacreate.com/static/feed.rss" "http://lambdacreate.com/" ""
feed "m455.casa" "https://m455.casa/feed.rss" "https://m455.casa/" ""
feed "Oatmeal" "https://eli.li/feed.rss" "https://eli.li/" ""
feed "RSRSSS" "https://envs.net/~lucidiot/rsrsss/feed.xml" "https://envs.net/~lucidiot/rsrsss/" ""
feed "Tomasino Blog" "https://blog.tomasino.org/index.xml" "https://blog.tomasino.org/" ""
feed "Tomasino Labs" "https://labs.tomasino.org/index.xml" "https://labs.tomasino.org/" ""
feed "Will's Blog" "https://wflewis.com/feed.xml" "https://wflewis.com/" ""
feed "Rick Carlino's Blog" "https://rickcarlino.com/rss/feed.rss" "https://rickcarlino.com/rss/" ""
feed "Causal Agency" "https://text.causal.agency/feed.atom" "https://text.causal.agency/" ""
feed "Benoit Joly" "https://blog.benoitj.ca/posts/index.xml" "https://blog.benoitj.ca/posts/" ""
feed "linkbudz" "https://linkbudz.m455.casa/feed.rss" "https://linkbudz.m455.casa/" ""
feed "Alex Schroeder" "https://alexschroeder.ch/wiki/feed/full/" "https://alexschroeder.ch/" ""
feed "Björn Wärmedal" "https://warmedal.se/~bjorn/atom.xml" "https://warmedal.se/~bjorn/" ""
feed "a rickety bridge of impossible crossing" "https://bluelander.bearblog.dev/feed/" "https://bluelander.bearblog.dev/" ""
feed "javapool updates" "https://tilde.town/~m455/javapool.rss" "" ""
feed "coolguy.website" "https://coolguy.website/rss/index.xml" "https://coolguy.website/"
feed "brainshit" "https://brainshit.fr/rss" "https://brainshit.fr"
}
feeds_people() {
feed "ajroach" "http://ajroach42.com/feed.xml" "http://ajroach42.com/" ""
feed "rachelbythebay" "https://rachelbythebay.com/w/atom.xml" "https://rachelbythebay.com/" ""
}
feeds_news() {
feed "Hacker News" "https://news.ycombinator.com/rss" "https://news.ycombinator.com/" ""
feed "lobste.rs" "https://lobste.rs/rss" "https://lobste.rs/" ""
feed "tilde news" "https://tilde.news/rss" "https://tilde.news/" ""
feed "Tildes Atom feed" "https://tildes.net/topics.atom" "https://tildes.net/" ""
feed "NPR" "https://feeds.npr.org/1001/rss.xml" "https://text.npr.org/" ""
}
feeds_smolweb() {
feed "~town friday postcard" "https://tilde.town/~lucidiot/fridaypostcard.xml" ""
feed "Cosmic Voyage" "https://cosmic.voyage/rss.xml" "https://cosmic.voyage/" ""
feed "plan.cat" "https://plan.cat/rss" "https://plan.cat/" ""
}
feeds_comics() {
feed "Cat and Girl" "https://catandgirl.com/feed/" "https://catandgirl.com/" ""
feed "Dinosaur Comics!" "https://qwantz.com/rssfeed.php" "https://qwantz.com/" ""
feed "False Knees" "https://falseknees.tumblr.com/rss" "https://falseknees.tumblr.com/" ""
feed "Saturday Morning Breakfast Cereal" "https://www.smbc-comics.com/comic/rss" "https://www.smbc-comics.com/" ""
feed "xkcd" "https://xkcd.com/atom.xml" "https://xkcd.com/" ""
}
feeds_misc() {
feed "Crystalverse" "https://crystalverse.com/feed/" "https://crystalverse.com/" ""
feed "Hetzner" "https://status.hetzner.com/en.atom" "https://status.hetzner.com/" ""
feed "LOW-TECH MAGAZINE" "https://feeds2.feedburner.com/typepad/krisdedecker/lowtechmagazineenglish" "https://www.lowtechmagazine.com/" ""
feed "500-mile email" "https://500mile.email/feed.xml" "https://500mile.email/"
feed "computers are bad" "https://computer.rip/rss.xml" "https://computer.rip/"
}
feeds_me() {
:
}
### Filter ######################################################
filter() {
case "$1" in
# Filter items based on feed name.
*'Hacker News'*)
# Hacker news is stupid and doesn't include IDs, and
# instead includes a comments tag in its body.
gawk 'BEGIN {FS="\t"; OFS="\t"} {
$6 = $4
sub(/^.*$/,"", $6)
print
}'
;;
*NPR*)
sed 's@www\.npr\.org@text.npr.org@'
;;
r_* | r/*)
# Reddit doesn't include a link as its item IDs, but instead
# something of the form `t3_xxxxx', where xxxxx can be glommed
# into a URL to get to the comments.
awk -v SUBREDDIT="$1" -v ALT=i.reddit.com \
'BEGIN {FS="\t";OFS="\t"}
{ $6 = $3 #ALT "/" SUBREDDIT "/" substr($6, 4)
}
{
if (match($4,/\[link\]<\/a>/,ln)) $3 = ln[1]
}
{ gsub(/www\.reddit\.com/, ALT, $0) }
{ print }'
;;
'Saturday Morning Breakfast Cereal')
sed 's@Saturday Morning Breakfast Cereal - @@'
;;
*) cat ;;
esac |
filter_add_empties |
filter_html_entities |
filter_filter_links
}
filter_add_empties() {
awk 'BEGIN{FS="\t";OFS=FS;}
{ $2 = $2 ? $2 : "[empty]" }
{ print $1,$2,$3,$4,$5,$6,$7,$8,$9; }
'
}
filter_embed_youtube() {
# replace youtube links with embed links
sed 's@www\.youtube\.com/watch?v=@www.youtube.com/embed/@g'
}
filter_filter_links() {
# shorten feedburner links and strip tracking parameters and pixels
awk -F '\t' 'BEGIN { OFS = "\t"; }
function filterlink(s) {
# protocol must start with http, https or gopher.
if (match(s, /^(http|https|gopher):\/\//) == 0) {
return "";
}
# shorten feedburner links.
if (match(s, /^(http|https):\/\/[^\/]+\/~r\/.*\/~3\/[^\/]+\//)) {
s = substr($3, RSTART, RLENGTH);
}
# strip tracking parameters
# urchin, facebook, piwik, webtrekk and generic.
gsub(/\?(ad|campaign|fbclid|pk|tm|utm|wt)_([^&]+)/, "?", s);
gsub(/&(ad|campaign|fbclid|pk|tm|utm|wt)_([^&]+)/, "", s);
gsub(/\?&/, "?", s);
gsub(/[\?&]+$/, "", s);
return s
}
{
$3 = filterlink($3); # link
$8 = filterlink($8); # enclosure
# try to remove tracking pixels: tags with 1px width or height.
gsub("]*(width|height)[[:space:]]*=[[:space:]]*[\"'"'"' ]?1[\"'"'"' ]?[^0-9>]+[^>]*>", "", $4);
print $0;
}'
}
filter_html_entities() {
# convert HTML entities into dumb counterparts
# (and weird shit to normal shit, too)
awk '{
gsub(/"/,"\""); gsub(/"/,"\"");
gsub(/'/,"'\''"); gsub(/'/,"'\''");
gsub(/’/,"'\''");
gsub(/&/,"\\&"); # MUST BE LAST!;
print
}'
}
# Fetch #########################################################
fetch() { # fetch(name, url, feedfile)
"${NOFETCH:-false}" && return
curl -s -L \
--max-redirs 3 \
--header "'User-Agent: $USER_AGENT'" \
--fail \
--max-time 15 \
"$2"
}
# Local Variables:
# truncate-lines: t
# End: