Compare commits
2 Enmetoj
d312272794
...
8ca6350dda
Author | SHA1 | Date | |
---|---|---|---|
Jaidyn Ann | 8ca6350dda | ||
Jaidyn Ann | 36c4c2d205 |
194
fedi2html
194
fedi2html
|
@ -70,151 +70,151 @@ fi
|
||||||
# Given a note’s JSON, render it as HTML.
|
# Given a note’s JSON, render it as HTML.
|
||||||
# The most important part of the script!
|
# The most important part of the script!
|
||||||
# render_post $post_data $context_data $tree_level
|
# render_post $post_data $context_data $tree_level
|
||||||
render_post() {
|
render_post() (
|
||||||
local post_data="$1"
|
post_data="$1"
|
||||||
local responses_data="$2"
|
responses_data="$2"
|
||||||
local POST_TREE_LEVEL="$3"
|
POST_TREE_LEVEL="$3"
|
||||||
|
|
||||||
local reblog=""
|
reblog=""
|
||||||
local acct_data="$(echo "$post_data" | jq -r .reblog.account)"
|
acct_data="$(echo "$post_data" | jq -r .reblog.account)"
|
||||||
if test "$acct_data" = "null"; then
|
if test "$acct_data" = "null"; then
|
||||||
acct_data="$(echo "$post_data" | jq -r .account)"
|
acct_data="$(echo "$post_data" | jq -r .account)"
|
||||||
else
|
else
|
||||||
reblog="1"
|
reblog="1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local ACCOUNT_URL="$(echo "$acct_data" | jq -r .url)"
|
ACCOUNT_URL="$(echo "$acct_data" | jq -r .url)"
|
||||||
local ACCOUNT_ID="$(echo "$acct_data" | jq -r .fqn)"
|
ACCOUNT_ID="$(echo "$acct_data" | jq -r .fqn)"
|
||||||
local ACCOUNT_NAME="$(echo "$acct_data" | jq -r .display_name | replace_emojis "$acct_data")"
|
ACCOUNT_NAME="$(echo "$acct_data" | jq -r .display_name | replace_emojis "$acct_data")"
|
||||||
local ACCOUNT_AVATAR="$(echo "$acct_data" | jq -r .avatar)"
|
ACCOUNT_AVATAR="$(echo "$acct_data" | jq -r .avatar)"
|
||||||
local POST_URL="$(echo "$post_data" | jq -r .url)"
|
POST_URL="$(echo "$post_data" | jq -r .url)"
|
||||||
local POST_DATE="$(echo "$post_data" | jq -r .created_at)"
|
POST_DATE="$(echo "$post_data" | jq -r .created_at)"
|
||||||
local POST_CONTENT="$(echo "$post_data" | jq -r .content | replace_emojis "$post_data")"
|
POST_CONTENT="$(echo "$post_data" | jq -r .content | replace_emojis "$post_data")"
|
||||||
local POST_ATTACHMENTS="$(media_attachments "$post_data")"
|
POST_ATTACHMENTS="$(media_attachments "$post_data")"
|
||||||
if test -z "$NO_RESPONSES"; then
|
if test -z "$NO_RESPONSES"; then
|
||||||
local POST_RESPONSES="$(render_responses "$post_data" "$responses_data" "$POST_TREE_LEVEL")"
|
POST_RESPONSES="$(render_responses "$post_data" "$responses_data" "$POST_TREE_LEVEL")"
|
||||||
fi
|
fi
|
||||||
env_subst "$POST_TEMPLATE"
|
env_subst "$POST_TEMPLATE"
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Render a post’s responses one-by-one and recursively.
|
# Render a post’s responses one-by-one and recursively.
|
||||||
# Each branch of the response tree will be rendered completely before proceeding
|
# Each branch of the response tree will be rendered completely before proceeding
|
||||||
# to the next.
|
# to the next.
|
||||||
# render_responses $post_data $context_data $tree_level
|
# render_responses $post_data $context_data $tree_level
|
||||||
render_responses() {
|
render_responses() (
|
||||||
local post_data="$1"
|
post_data="$1"
|
||||||
local responses_data="$2"
|
responses_data="$2"
|
||||||
local level="$3"
|
level="$3"
|
||||||
if test -z "$level"; then level=0; fi
|
if test -z "$level"; then level=0; fi
|
||||||
|
|
||||||
local id="$(echo "$post_data" | jq -r '.id')"
|
id="$(echo "$post_data" | jq -r '.id')"
|
||||||
local responses="$(echo "$responses_data" | grep "in_reply_to_id.*$id")"
|
responses="$(echo "$responses_data" | grep "in_reply_to_id.*$id")"
|
||||||
local IFS="
|
IFS="
|
||||||
"
|
"
|
||||||
|
|
||||||
for response in $responses; do
|
for response in $responses; do
|
||||||
render_post "$response" "$responses_data" "$(expr "$level" + 1)"
|
render_post "$response" "$responses_data" "$((level + 1))"
|
||||||
done
|
done
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Accepts a string over stdin; it will replace all emoji shortcodes along stdin
|
# Accepts a string over stdin; it will replace all emoji shortcodes along stdin
|
||||||
# input with appropriate <img> HTML, based on $EMOJI_TEMPLATE, and based on
|
# input with appropriate <img> HTML, based on $EMOJI_TEMPLATE, and based on
|
||||||
# a post’s JSON.
|
# a post’s JSON.
|
||||||
# echo ":blobcat:" | replace_emojis $post_data
|
# echo ":blobcat:" | replace_emojis $post_data
|
||||||
replace_emojis() {
|
replace_emojis() (
|
||||||
local post_data="$1"
|
post_data="$1"
|
||||||
local emojis="$(echo "$post_data" | jq -r '.emojis[]|(.url + "\t" + .shortcode)')"
|
emojis="$(echo "$post_data" | jq -r '.emojis[]|(.url + "\t" + .shortcode)')"
|
||||||
local temp="$(mktemp)"
|
temp="$(mktemp)"
|
||||||
local IFS="
|
IFS="
|
||||||
"
|
"
|
||||||
cat > "$temp"
|
cat > "$temp"
|
||||||
|
|
||||||
for line in $emojis; do
|
for line in $emojis; do
|
||||||
local EMOJI_URL="$(echo "$line" | awk -F'\t' '{print $1}')"
|
EMOJI_URL="$(echo "$line" | awk -F'\t' '{print $1}')"
|
||||||
local EMOJI_SHORTCODE="$(echo "$line" | awk -F'\t' '{print $2}')"
|
EMOJI_SHORTCODE="$(echo "$line" | awk -F'\t' '{print $2}')"
|
||||||
local value="$(env_subst "$EMOJI_TEMPLATE")"
|
value="$(env_subst "$EMOJI_TEMPLATE")"
|
||||||
sed -i "s%:${EMOJI_SHORTCODE}:%${value}%g" "$temp"
|
sed -i "s%:${EMOJI_SHORTCODE}:%${value}%g" "$temp"
|
||||||
done
|
done
|
||||||
cat "$temp"
|
cat "$temp"
|
||||||
rm "$temp"
|
rm "$temp"
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Given a post’s JSON data, return the appropriate HTML corresponding to its
|
# Given a post’s JSON data, return the appropriate HTML corresponding to its
|
||||||
# media attachments, if any. Will return an empty string if none.
|
# media attachments, if any. Will return an empty string if none.
|
||||||
# media_attachments $post_data
|
# media_attachments $post_data
|
||||||
media_attachments() {
|
media_attachments() (
|
||||||
local post_data="$1"
|
post_data="$1"
|
||||||
local attachments="$(echo "$post_data" | jq -r '.media_attachments[]|(.type + "\t" + .url + "\t" + .description + "\t" + .preview_url)')"
|
attachments="$(echo "$post_data" | jq -r '.media_attachments[]|(.type + "\t" + .url + "\t" + .description + "\t" + .preview_url)')"
|
||||||
local IFS="
|
IFS="
|
||||||
"
|
"
|
||||||
for line in $attachments; do
|
for line in $attachments; do
|
||||||
local ATTACH_TYPE="$(echo "$line" | awk -F'\t' '{print $1}')"
|
ATTACH_TYPE="$(echo "$line" | awk -F'\t' '{print $1}')"
|
||||||
local ATTACH_URL="$(echo "$line" | awk -F'\t' '{print $2}')"
|
ATTACH_URL="$(echo "$line" | awk -F'\t' '{print $2}')"
|
||||||
local ATTACH_DESC="$(echo "$line" | awk -F'\t' '{print $3}')"
|
ATTACH_DESC="$(echo "$line" | awk -F'\t' '{print $3}')"
|
||||||
local ATTACH_PREVIEW="$(echo "$line" | awk -F'\t' '{print $4}')"
|
ATTACH_PREVIEW="$(echo "$line" | awk -F'\t' '{print $4}')"
|
||||||
local ATTACH_NAME="$(basename "$ATTACH_URL")"
|
ATTACH_NAME="$(basename "$ATTACH_URL")"
|
||||||
if test "$ATTACH_TYPE" = "image"; then
|
if test "$ATTACH_TYPE" = "image"; then
|
||||||
env_subst "$ATTACH_IMAGE_TEMPLATE"
|
env_subst "$ATTACH_IMAGE_TEMPLATE"
|
||||||
else
|
else
|
||||||
env_subst "$ATTACH_TEMPLATE"
|
env_subst "$ATTACH_TEMPLATE"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Pass a post’s context JSON along stdin; out comes the response_data in JSON.
|
# Pass a post’s context JSON along stdin; out comes the response_data in JSON.
|
||||||
# fetch_post_context $url | context_to_responses
|
# fetch_post_context $url | context_to_responses
|
||||||
context_to_responses() {
|
context_to_responses() (
|
||||||
jq '.descendants' 2> /dev/null \
|
jq '.descendants' 2> /dev/null \
|
||||||
| jq 'sort_by(.created_at)' \
|
| jq 'sort_by(.created_at)' \
|
||||||
| maybe_jq_reverse \
|
| maybe_jq_reverse \
|
||||||
| jq -cr '.[]'
|
| jq -cr '.[]'
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Make a request to the /api/v1/statuses/:id/$request API endpoint.
|
# Make a request to the /api/v1/statuses/:id/$request API endpoint.
|
||||||
# statuses_api_request $post_url $request
|
# statuses_api_request $post_url $request
|
||||||
statuses_api_request() {
|
statuses_api_request() (
|
||||||
local post_url="$1"
|
post_url="$1"
|
||||||
local api_request="$2"
|
api_request="$2"
|
||||||
if test -n "$api_request"; then
|
if test -n "$api_request"; then
|
||||||
api_request="/$api_request"
|
api_request="/$api_request"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local id="$(url_post_id "$post_url")"
|
id="$(url_post_id "$post_url")"
|
||||||
local server="$(url_server "$post_url")"
|
server="$(url_server "$post_url")"
|
||||||
curl --retry 3 --retry-delay 5 \
|
curl --retry 3 --retry-delay 5 \
|
||||||
--location --header 'Accept: application/json,application/activity+json' \
|
--location --header 'Accept: application/json,application/activity+json' \
|
||||||
"${server}/api/v1/statuses/${id}${api_request}"
|
"${server}/api/v1/statuses/${id}${api_request}"
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Require the context-JSON of a post, by URL.
|
# Require the context-JSON of a post, by URL.
|
||||||
# fetch_post_context $url
|
# fetch_post_context $url
|
||||||
fetch_post_context() {
|
fetch_post_context() (
|
||||||
local url="$1"
|
url="$1"
|
||||||
statuses_api_request "$url" "context" \
|
statuses_api_request "$url" "context" \
|
||||||
| context_to_responses
|
| context_to_responses
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Given a post URL, request its JSON.
|
# Given a post URL, request its JSON.
|
||||||
# fetch_post $url
|
# fetch_post $url
|
||||||
fetch_post() {
|
fetch_post() (
|
||||||
local url="$1"
|
url="$1"
|
||||||
statuses_api_request "$url"
|
statuses_api_request "$url"
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Given a user-account URL, request JSON of its posts.
|
# Given a user-account URL, request JSON of its posts.
|
||||||
# fetch_post $url
|
# fetch_post $url
|
||||||
fetch_user_posts() {
|
fetch_user_posts() (
|
||||||
local url="$1"
|
url="$1"
|
||||||
local server="$(url_server "$url")"
|
server="$(url_server "$url")"
|
||||||
local status_url="$server/api/v1/accounts/$(url_user_id "$url")/statuses"
|
status_url="$server/api/v1/accounts/$(url_user_id "$url")/statuses"
|
||||||
status_url="${status_url}?exclude_reblogs=${EXCLUDE_REBLOGS}&limit=$MAX_POSTS"
|
status_url="${status_url}?exclude_reblogs=${EXCLUDE_REBLOGS}&limit=$MAX_POSTS"
|
||||||
status_url="${status_url}&exclude_replies=${EXCLUDE_REPLIES}$TAG_FILTER"
|
status_url="${status_url}&exclude_replies=${EXCLUDE_REPLIES}$TAG_FILTER"
|
||||||
|
|
||||||
|
@ -222,13 +222,13 @@ fetch_user_posts() {
|
||||||
--location --header 'Accept: application/json,application/activity+json' \
|
--location --header 'Accept: application/json,application/activity+json' \
|
||||||
"$status_url" \
|
"$status_url" \
|
||||||
| jq -c '.[]'
|
| jq -c '.[]'
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Return the ID of a user, based on its URL.
|
# Return the ID of a user, based on its URL.
|
||||||
# url_user_id $url
|
# url_user_id $url
|
||||||
url_user_id() {
|
url_user_id() (
|
||||||
local url="$1"
|
url="$1"
|
||||||
# Pleroma-style URLs: https://jam.xwx.moe/users/Tirifto
|
# Pleroma-style URLs: https://jam.xwx.moe/users/Tirifto
|
||||||
# Mastodon-style URLs: https://esperanto.masto.host/@jubiloEO
|
# Mastodon-style URLs: https://esperanto.masto.host/@jubiloEO
|
||||||
if echo "$url" | grep "/users/" > /dev/null; then
|
if echo "$url" | grep "/users/" > /dev/null; then
|
||||||
|
@ -241,13 +241,13 @@ url_user_id() {
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Return the ID of a post, based on its URL.
|
# Return the ID of a post, based on its URL.
|
||||||
# url_post_id $url
|
# url_post_id $url
|
||||||
url_post_id() {
|
url_post_id() (
|
||||||
local url="$1"
|
url="$1"
|
||||||
# Pleroma-style URLs: https://jam.xwx.moe/notice/Ac6PIZAP0ZzkMTYBBg
|
# Pleroma-style URLs: https://jam.xwx.moe/notice/Ac6PIZAP0ZzkMTYBBg
|
||||||
# Mastodon-style URLs: https://esperanto.masto.host/@minjo/111461250815264185
|
# Mastodon-style URLs: https://esperanto.masto.host/@minjo/111461250815264185
|
||||||
if echo "$url" | grep "/notice/" > /dev/null; then
|
if echo "$url" | grep "/notice/" > /dev/null; then
|
||||||
|
@ -259,29 +259,29 @@ url_post_id() {
|
||||||
else
|
else
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Return the server (including protocol) of a post, based on its URL.
|
# Return the server (including protocol) of a post, based on its URL.
|
||||||
# url_server $url
|
# url_server $url
|
||||||
url_server() {
|
url_server() (
|
||||||
local url="$1"
|
url="$1"
|
||||||
local protocol="$(echo "$url" | grep --only-matching '[[:alnum:]]*://')"
|
protocol="$(echo "$url" | grep --only-matching '[[:alnum:]]*://')"
|
||||||
printf "$protocol"
|
printf '%s' "$protocol"
|
||||||
echo "$url" \
|
echo "$url" \
|
||||||
| sed 's%^'"$protocol"'%%' \
|
| sed 's%^'"$protocol"'%%' \
|
||||||
| sed 's%/.*%%'
|
| sed 's%/.*%%'
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Sanitize a template-string.
|
# Sanitize a template-string.
|
||||||
# AKA, escape quotation-marks.
|
# AKA, escape quotation-marks.
|
||||||
# prep_template $template
|
# prep_template $template
|
||||||
prep_template() {
|
prep_template() (
|
||||||
local template="$1"
|
template="$1"
|
||||||
echo "$template" \
|
echo "$template" \
|
||||||
| sed 's%\"%\\\"%g'
|
| sed 's%\"%\\\"%g'
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Rough replacement for gettext’s envsubst. Safe!
|
# Rough replacement for gettext’s envsubst. Safe!
|
||||||
|
@ -291,37 +291,37 @@ prep_template() {
|
||||||
# variables’ contents (AKA, post contents) aren’t evaluated.
|
# variables’ contents (AKA, post contents) aren’t evaluated.
|
||||||
# env_subst $template
|
# env_subst $template
|
||||||
# env_subst "$SHELL" → "/bin/sh"
|
# env_subst "$SHELL" → "/bin/sh"
|
||||||
env_subst() {
|
env_subst() (
|
||||||
local template="$1"
|
template="$1"
|
||||||
eval "echo \"$(prep_template "$template")\""
|
eval "echo \"$(prep_template "$template")\""
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Based on the environment variable $REVERSE_ORDER (whether or not user provided
|
# Based on the environment variable $REVERSE_ORDER (whether or not user provided
|
||||||
# the -I flag), reverse the JSON array over stdin.
|
# the -I flag), reverse the JSON array over stdin.
|
||||||
# This is used to enable/disable reverse-chronological order of posts.
|
# This is used to enable/disable reverse-chronological order of posts.
|
||||||
# fetch_context $url | jq '.descendants' | maybe_jq_reverse
|
# fetch_context $url | jq '.descendants' | maybe_jq_reverse
|
||||||
maybe_jq_reverse() {
|
maybe_jq_reverse() (
|
||||||
local input="$(cat)"
|
input="$(cat)"
|
||||||
if test -n "$REVERSE_ORDER"; then
|
if test -n "$REVERSE_ORDER"; then
|
||||||
echo "$input" \
|
echo "$input" \
|
||||||
| jq 'reverse'
|
| jq 'reverse'
|
||||||
else
|
else
|
||||||
echo "$input"
|
echo "$input"
|
||||||
fi
|
fi
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Render a user’s posts, one-by-one, taking into account cli arguments.
|
# Render a user’s posts, one-by-one, taking into account cli arguments.
|
||||||
# handle_user_url https://jam.xwx.moe/users/tirifto
|
# handle_user_url https://jam.xwx.moe/users/tirifto
|
||||||
handle_user_url() {
|
handle_user_url() (
|
||||||
local url="$1"
|
url="$1"
|
||||||
local user_posts="$(fetch_user_posts "$url")"
|
user_posts="$(fetch_user_posts "$url")"
|
||||||
local IFS="
|
IFS="
|
||||||
"
|
"
|
||||||
echo "$user_posts" > jadedctrl.json
|
echo "$user_posts" > jadedctrl.json
|
||||||
for post in $user_posts; do
|
for post in $user_posts; do
|
||||||
local url="$(echo "$post" | jq -r '.url')"
|
url="$(echo "$post" | jq -r '.url')"
|
||||||
if test -z "$NO_RESPONSES"; then
|
if test -z "$NO_RESPONSES"; then
|
||||||
context="$(fetch_post_context "$url")"
|
context="$(fetch_post_context "$url")"
|
||||||
if test -n "$NO_PARENT"; then
|
if test -n "$NO_PARENT"; then
|
||||||
|
@ -333,24 +333,24 @@ handle_user_url() {
|
||||||
render_post "$post" "" 0
|
render_post "$post" "" 0
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
# Render a post and/or its responses, taking into account cli arguments.
|
# Render a post and/or its responses, taking into account cli arguments.
|
||||||
handle_post_url() {
|
handle_post_url() (
|
||||||
local url="$1"
|
url="$1"
|
||||||
local post="$(fetch_post "$url")"
|
post="$(fetch_post "$url")"
|
||||||
local context="$(fetch_post_context "$url")"
|
context="$(fetch_post_context "$url")"
|
||||||
|
|
||||||
if test -n "$NO_PARENT"; then
|
if test -n "$NO_PARENT"; then
|
||||||
render_responses "$post" "$context" 0
|
render_responses "$post" "$context" 0
|
||||||
else
|
else
|
||||||
render_post "$post" "$context" 0
|
render_post "$post" "$context" 0
|
||||||
fi
|
fi
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
usage() {
|
usage() (
|
||||||
echo "usage: $(basename "$0") [-h] [-IRc] POST_URL"
|
echo "usage: $(basename "$0") [-h] [-IRc] POST_URL"
|
||||||
echo " $(basename "$0") [-h] [-IRcbBt] [-m MAX] USER_URL"
|
echo " $(basename "$0") [-h] [-IRcbBt] [-m MAX] USER_URL"
|
||||||
echo
|
echo
|
||||||
|
@ -396,7 +396,7 @@ usage() {
|
||||||
echo 'See the first few lines of fedi2html for the default (example)'
|
echo 'See the first few lines of fedi2html for the default (example)'
|
||||||
echo 'template values; see the README for a more detailed description'
|
echo 'template values; see the README for a more detailed description'
|
||||||
echo 'of these variables’ meanings.'
|
echo 'of these variables’ meanings.'
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
TAG_FILTER=""
|
TAG_FILTER=""
|
||||||
|
@ -432,6 +432,8 @@ while getopts 'hcIRt:bm:B' arg; do
|
||||||
B)
|
B)
|
||||||
EXCLUDE_REPLIES="true"
|
EXCLUDE_REPLIES="true"
|
||||||
;;
|
;;
|
||||||
|
*)
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
Ŝarĝante…
Reference in New Issue