Skip to content

Instantly share code, notes, and snippets.

@brandonpollack23
Created April 3, 2026 03:45
Show Gist options
  • Select an option

  • Save brandonpollack23/db78386cb84389772974edeb9e9e29bc to your computer and use it in GitHub Desktop.

Select an option

Save brandonpollack23/db78386cb84389772974edeb9e9e29bc to your computer and use it in GitHub Desktop.
Hacker news motd script
# Hacker News MOTD
_hn_output=$(source "$HOME/rcfiles/hacker-news.sh")
if [[ -n "$_hn_output" ]]; then
echo "$_hn_output"
else
echo "⏳ Fetching Hacker News in the background..."
fi
unset _hn_output
_hn_cache="$HOME/.cache/hn_motd"
_hn_default_max_age=${HN_MAX_AGE:-18000} # 5 hours, overridable via env
_hn_default_count=${HN_COUNT:-30} # top N stories to cache, overridable via env
_hn_stale() {
local max_age=${1:-$_hn_default_max_age}
[[ ! -f "$_hn_cache" ]] && return 0
local age=$(($(date +%s) - $(date -r "$_hn_cache" +%s)))
((age > max_age))
}
_hn_fetch() {
local count=${1:-$_hn_default_count}
local ids id item title url text kid comment obj tmpfile
ids=$(curl -sf https://hacker-news.firebaseio.com/v0/topstories.json) || return
tmpfile=$(mktemp)
echo "[]" >"$tmpfile"
for id in $(echo "$ids" | jq ".[: ${count}][]"); do
item=$(curl -sf "https://hacker-news.firebaseio.com/v0/item/${id}.json") || continue
title=$(echo "$item" | jq -r '.title // empty')
[[ -z "$title" ]] && continue
url=$(echo "$item" | jq -r '.url // empty')
text=$(echo "$item" | jq -r '.text // empty')
comment=""
if [[ -n "$url" ]]; then
kid=$(echo "$item" | jq '.kids[0] // empty')
if [[ -n "$kid" ]]; then
comment=$(curl -sf "https://hacker-news.firebaseio.com/v0/item/${kid}.json" |
jq -r '.text // empty' | sed 's/<[^>]*>//g')
comment="${comment:0:100}"
fi
elif [[ -n "$text" ]]; then
comment=$(echo "$text" | sed 's/<[^>]*>//g' | head -c 100)
url=""
fi
obj=$(jq -n --arg t "$title" --arg u "$url" --arg c "$comment" \
'{title: $t, url: $u, comment: $c}')
jq --argjson e "$obj" '. + [$e]' "$tmpfile" >"${tmpfile}.tmp" &&
command mv "${tmpfile}.tmp" "$tmpfile"
done
command mv "$tmpfile" "$_hn_cache"
}
hn() {
local max_age=$_hn_default_max_age count=$_hn_default_count
while [[ $# -gt 0 ]]; do
case $1 in
--max-age)
max_age=$2
shift 2
;;
--count)
count=$2
shift 2
;;
*) shift ;;
esac
done
if [[ ! -f "$_hn_cache" ]]; then
(_hn_fetch "$count" &)
return
elif _hn_stale "$max_age"; then
(_hn_fetch "$count" &)
fi
[[ -f "$_hn_cache" ]] || return
local entry title url comment
entry=$(jq -c '.[]' "$_hn_cache" | shuf -n1)
title=$(echo "$entry" | jq -r '.title')
url=$(echo "$entry" | jq -r '.url')
comment=$(echo "$entry" | jq -r '.comment')
echo -e "\n🔥 \e[2mHacker News MOTD\e[22m\n"
echo -e "📰 \e[1m${title}\e[0m"
[[ -n "$url" ]] && echo -e " ${url}"
[[ -n "$comment" ]] && echo -e " 💬 \e[3m${comment}\e[23m…"
echo
}
hn "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment