diff --git a/manicito b/manicito index 87f41c0..f74edae 100755 --- a/manicito +++ b/manicito @@ -1,14 +1,97 @@ #!/bin/sh #――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― -# Name: -# Desc: -# Reqs: -# Date: +# Name: manicito (Manic-citation) +# Desc: A Mastodon/Pleroma bot which Quote-posts all posts of the given hashtag. +# Reqs: curl, shell, jq +# Date: 2024-04-10 #――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― MANICITO_TEMPLATE='$USER ($USERHOST) posted about $TAG:
$(echo "$POST" | head -c 200)
' +# Given a post’s JSON, create and submit a quote-post for it. +# quote_post $tagged_post_json +quote_post() { + local tagged_post_json="$1" + curl --fail \ + --request POST \ + --header "Authorization: Bearer $FEDI_AUTH" \ + --header 'Content-Type: application/json' \ + --data "$(post_json "$tagged_post_json")" "$FEDI_SERVER/api/v1/statuses" +} + + +# Given a JSON-array of posts over stdin, create and submit a quote-post for each one. +# $posts_json_array | quote_posts +quote_posts() { + local IFS=" +" + while read -r tagged_post_line; do + quote_post "$tagged_post_line" + if test "$?" -ne 0; then + echo "Failed to post about post $(echo "$tagged_post_line" | jq .id)!" 1>&2 + exit 1 + fi + echo "$tagged_post_line" + done +} + + +# Given a post’s JSON, return JSON of a quote-post quoting it. +# post_json $tagged_post-json +post_json() { + local tagged_post_json="$1" + printf '{ "content_type": "text/html", "visibility": "unlisted",' + printf '"quote_id": "%s",' "$(echo "$tagged_post_json" | jq -r .id)" + printf '"status": "%s" }\n' "$(post_body "$tagged_post_json")" +} + + +# Output the contents of our quote-post’s body about the given tagged-post’s JSON. +# This uses the global variable $MANICITO as our template, replacing the variables +# $POST, $POST_URL, $USER, $USER_URL, and $USERHOST. +# post_body $tagged_post_json +post_body() { + local tagged_post_json="$1" + POST="$(echo "$tagged_post_json" | jq -r .content | tr -d "\"'\n")" + POST_URL="$(echo "$tagged_post_json" | jq -r .uri)" + USER="$(echo "$tagged_post_json" | jq -r .account.display_name)" + USER_URL="$(echo "$tagged_post_json" | jq -r .account.url)" + USERHOST="$(echo "$tagged_post_json" | jq -r .account.acct)" + env_subst "$MANICITO_TEMPLATE" +} + + +# Given a “filter” file — a newline-delimited list of post IDs that should not +# be quoted — filter out all according posts send over stdin. +# echo $post_array_json | filter_posts $history_file +filter_posts() { + local history_file="$1" + # If the history file exists and has more than five characters, use it to filter… (sanity check) + if test -f "$history_file" -a "$(wc --bytes "$history_file" | awk '{print $1}')" -gt 5; then + jq -cr .[] \ + | grep --invert-match $(sort "$history_file" | uniq | grep -v '^[[:space:]]*$' | sed 's%^%-e %') + else + jq -cr .[] + fi +} + + +# Pipe in fediverse posts in JSON format; these will all be echoed into the given +# “history file”, so that they can be filtered out and avoided on subsequent +# runs. +# echo $newline_delimited_post_jsons | update_filter $history_file +update_filter() { + local history_file="$1" + if test -f "$history_file"; then + jq -r '(.created_at + "\t" + .id)' \ + | sort -n \ + | awk -F '\t' '{print $2}' \ + >> "$history_file" + fi +} + + # Sanitize a template-string. # AKA, escape quotation-marks. # prep_template $template @@ -32,71 +115,6 @@ env_subst() { } -post_body() { - local tagged_post_json="$1" - POST="$(echo "$tagged_post_json" | jq -r .content | tr -d "\"'\n")" #lynx -stdin -dump | tr -d "\"'\n")" - echo "$POST" > /tmp/a - POST_URL="$(echo "$tagged_post_json" | jq -r .uri)" - USER="$(echo "$tagged_post_json" | jq -r .account.display_name)" - USER_URL="$(echo "$tagged_post_json" | jq -r .account.url)" - USERHOST="$(echo "$tagged_post_json" | jq -r .account.acct)" - env_subst "$MANICITO_TEMPLATE" \ - | tr -d '"' -} - - -filter_posts() { - local history_file="$1" - # If the history file exists and has more than five characters, use it to filter… (sanity check) - if test -f "$history_file" -a "$(wc --bytes "$history_file" | awk '{print $1}')" -gt 5; then - jq -cr .[] \ - | grep --invert-match $(sort "$history_file" | uniq | grep -v '^[[:space:]]*$' | sed 's%^%-e %') - else - jq -cr .[] - fi -} - - -post_json() { - local tagged_post_json="$1" - printf '{ "content_type": "text/html", "visibility": "unlisted",' - printf '"quote_id": "%s",' "$(echo "$tagged_post_json" | jq -r .id)" - printf '"status": "%s" }\n' "$(post_body "$tagged_post_json")" -} - - -quote_post() { - local tagged_post_json="$1" - curl --fail \ - --request POST \ - --header "Authorization: Bearer $FEDI_AUTH" \ - --header 'Content-Type: application/json' \ - --data "$(post_json "$tagged_post_json")" "$FEDI_SERVER/api/v1/statuses" -} - -quote_posts() { - local IFS=" -" - while read -r tagged_post_line; do - quote_post "$tagged_post_line" - if test "$?" -ne 0; then - echo "Failed to post about post $(echo "$tagged_post_line" | jq .id)!" 1>&2 - exit 1 - fi - echo "$tagged_post_line" - done -} - -update_filter() { - local history_file="$1" - if test -f "$history_file"; then - jq -r '(.created_at + "\t" + .id)' \ - | sort -n \ - | awk -F '\t' '{print $2}' \ - >> "$history_file" - fi -} - FEDI_SERVER="https://jam.xwx.moe" curl "$FEDI_SERVER/api/v1/timelines/tag/esperanto" \ | filter_posts "m" \