#!/bin/awk -f # Convert sfeed(1) formatted files into an HTML webpage. # Usage: sfeed_html.awk -- FILES... ## Set up variables BEGIN { # Sidebar if (! ASIDE) { ASIDE = envor("SFEED_HTML_ASIDE", "/tmp/sfeed-aside.html") } print > ASIDE # clear out ASIDE in_aside = 0 # Don't show the feed in the sidebar # Formatting if (! DATEFMT) { ddf = "" DATEFMT = envor("SFEED_HTML_DATEFMT", ddf) } if (! TITLE) { TITLE = envor("SFEED_HTML_TITLE", "Planet ACDW") } if (! SEPARATOR) { SEPARATOR = envor("SFEED_HTML_SEPARATOR", "//") } if (! ALT_LINK_STAMP) { ALT_LINK_STAMP = envor("SFEED_ALT_LINK_STAMP", "&") } if (! ENCLOSURE_STAMP) { ENCLOSURE_STAMP = envor("SFEED_ENCLOSURE_STAMP", "@") } if (! SILO_STAMP) { SILO_STAMP = envor("SFEED_SILO_STAMP", "%") } # Limiting posts... ## by time if (! NOW) { datecmd = "date +%s" datecmd | getline NOW close(datecmd) } if (! FRESHDAYS) { FRESHDAYS = envor("SFEED_FRESHDAYS", 1.5) } if (! STALEDAYS) { STALEDAYS = envor("SFEED_STALEDAYS", 4) } fresh_secs = FRESHDAYS * 24 * 60 * 60 stale_secs = STALEDAYS * 24 * 60 * 60 fresh_age = (NOW - fresh_secs) stale_age = (NOW - stale_secs) ## by number if (! LIMIT) { # If LIMIT == -1, ignore time limit as well. LIMIT = envor("SFEED_LIMIT", 20) } # Alternate URLs for siloed content if (! YOUTUBE_ALT_URL) { YOUTUBE_ALT_URL = envor("SFEED_YOUTUBE_ALT_URL", "https://piped.kavin.rocks") } if (! TWITTER_ALT_URL) { TWITTER_ALT_URL = envor("SFEED_TWITTER_ALT_URL", "https://nitter.net") } if (! REDDIT_ALT_URL) { REDDIT_ALT_URL = envor("SFEED_REDDIT_ALT_URL", "https://libreddit.de") } # Paywalls PAYWALL_LADDER = "https://archive.ph/newest/" PAYWALLED[1] = "washingtonpost\\.com" PAYWALLED[2] = "nytimes\\.com" # Awk and convenience constants FS = "\t" STDERR = "/dev/stderr" } BEGIN { html_top() } FNR == 1 { if (file_count) { # End the previous file before beginning the current one end_file() } # Filename name = FILENAME sub(/.*\//, "", name) safe_name = name sub(/\//, "_", safe_name) dir = FILENAME sub(/[^\/]*$/, "", dir) if (name ~ /\[yt\]$/) { sub(/ \[yt\]$/, "", name) yt = " class=\"yt\"" } else { yt = "" } URLS = envor("SFEED_DATA", ENVIRON["HOME"] "/.sfeed") "/urls/" safe_name # State variables stamp = "." buf = "" ni = 0 stale_total += stale_count stale_count = 0 fresh_total += fresh_count fresh_count = 0 item_total += item_count item_count = 0 file_count++ siloed = 0 } { # Skip if we have too many items if ((LIMIT > 0) && (++ni > LIMIT)) { next } # Collect fields timestamp = $1 title = $2 silo = $3 link = silo_link(silo) content = unescape($4) content_type = $5 id = $6 author = $7 enclosure = $8 category = $9 # Skip if the item is too old if ((LIMIT >= 0) && (timestamp < stale_age)) { next } # Otherwise, we're showing it stale_count++ # Is this item fresh? if (timestamp >= fresh_age) { is_fresh = 1 stamp = "!" fresh_count++ } else { is_fresh = 0 } # Debugging comment bufprint("") bufprint("") # Print! bufprint("") # Timestamp datecmd = "date -d \"@" timestamp "\" +'" DATEFMT "'" if (timestamp) { datecmd | getline timestamp close(datecmd) } bufprint("") # Extra links bufprint("") if (siloed) { # "siloed" links like youtube, facebook, etc. --- I convert them # to more privacy-friendly links, but sometimes those don't # work. TODO: also try to circumvent paywalls. stamp = SILO_STAMP print_link(silo, "Silo: " silo, stamp) } if (enclosure) { # enclosures --- podcast files, etc. stamp = ENCLOSURE_STAMP print_link(enclosure, "Enclosure: " enclosure, stamp) } # Test id against silo here, since silo is the raw link value. if ((id != silo) && (id != enclosure) && (id ~ /^https?:/)) { # alternate links (comments, etc.) stamp = ALT_LINK_STAMP print_link(silo_link(id), "alternate link", stamp) } bufprint("") # Title bufprint("") # bufprint("
", 0) print_link(link, "", title) # bufprint("") # bufprint(content) # bufprint("
") bufprint("") # End row bufprint("") item_count++ } END { # End the last file and the #list section end_file() print "" # Sidebar print "" # End of
print "
" # footer printf "" # end of HTML print "" print "" print "" printf(SEPARATOR) > STDERR } function bufprint(text, sep) { buf = buf text (sep ? sep : ((sep == 0) ? "" : "\n")) sep = "" } function end_file() { if (! item_count) { return 1 } # Header printf "
\n", name, (fresh_count ? "fresh" : "stale") printf "
# %s\n", yt, name, name # Feed links printf "" printf "
\n" # Feed entries printf "\n" printf "%s", buf printf "
\n
\n" # Sidebar if (stale_count) { printf("
  • ", (fresh_count ? "fresh" : "stale")) >> ASIDE printf("%s
  • \n", name, (yt ? " class=\"yt\"" : ""), name) >> ASIDE } # Log printf("%s", stamp) > STDERR } function envor(var, def) { return (ENVIRON[var] ? ENVIRON[var] : def) } function html_escape(t) { gsub(//, "\\>", t) gsub(/&/, "\\&", t) return t } function html_top() { # Print HTML header fortunecmd = "fortune" fortunecmd | getline LOGO_TITLE close(fortunecmd) sub(/"/, "", LOGO_TITLE) datecmd = "date -u +'" DATEFMT "'" datecmd | getline UPDATE_TIME close(datecmd) print "" print "" # print "" print "" print "" print "" print "" print "" TITLE "" print "" print "" print "" print "" print "" print "" print "" print "" #
    print "
    " print "

    " printf "" print TITLE "

    " print "

    last updated at

    " print "
    " #