mastodon.sh 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #!/bin/sh
  2. #―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
  3. # Name: bookmarks-dl: Mastodon
  4. # Desc: A source for bookmarks-dl that fetches bookmarks from Mastodon/Pleroma.
  5. # Auth: Jaidyn Ann <jadedctrl@posteo.at>
  6. # Date: 2023-09-02
  7. # Reqs: curl, jq
  8. # Lisc: GPLv3
  9. #―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
  10. usage() {
  11. 1>&2 echo "usage: bookmarks-dl mastodon [-h] [-a USER_TOKEN] -u USERNAME -d DOMAIN"
  12. 1>&2 echo ""
  13. 1>&2 echo " -h print this message and exit"
  14. 1>&2 echo " -a the authorization token for your account; see below"
  15. 1>&2 echo " -u account username"
  16. 1>&2 echo " -d the server’s domain name"
  17. }
  18. # Fetch all of a user’s Mastodon/Pleroma bookmarks.
  19. fetch_bookmarks() {
  20. local auth="$1"
  21. local domain="$2"
  22. local url="$3"
  23. if test -z "$url"; then
  24. url="https://$domain/api/v1/bookmarks?limit=40"
  25. fi
  26. local header_file="$(mktemp)"
  27. curl -H "Authorization: Bearer $auth" \
  28. -D "$header_file" \
  29. "$url" \
  30. | bookmarks_parse
  31. local next_url="$(header_next_link "$header_file")"
  32. rm "$header_file"
  33. if test -n "$next_url"; then
  34. fetch_bookmarks "$auth" "$domain" "$next_url"
  35. fi
  36. }
  37. source_start() {
  38. local auth=""
  39. local domain=""
  40. while getopts 'hf:a:u:d:' arg; do
  41. case $arg in
  42. h)
  43. usage
  44. exit 1
  45. ;;
  46. a)
  47. auth="$OPTARG"
  48. ;;
  49. d)
  50. domain="$OPTARG"
  51. ;;
  52. esac
  53. done
  54. if test -z "$auth" -o -z "$domain"; then
  55. usage
  56. exit 5
  57. else
  58. fetch_bookmarks "$auth" "$domain"
  59. fi
  60. }
  61. # Given a page of /api/v1/bookmarks, parse into the simple bookmarks-dl format
  62. bookmarks_parse() {
  63. local bookmark_lines="$(jq -r '.[] | "\(.url)\t\t\(@json "\(.content)")\t\(.created_at)"')"
  64. local IFS="
  65. "
  66. for bookmark in $bookmark_lines; do
  67. local url="$(echo "$bookmark" | awk -F '\t' '{print $1}')"
  68. local date="$(echo "$bookmark" | awk -F '\t' '{print $4}')"
  69. local desc="$(echo "$bookmark" | bookmark_line_desc)"
  70. local title="$(echo "$desc" | head -c40)"
  71. printf '%s\t%s\t%s\t%s\n' "$url" "$title" "$desc" "$date"
  72. done
  73. }
  74. # If curl’s HTTP response contains a “link” header for pagination, return the
  75. # “next” page’s URL.
  76. header_next_link() {
  77. local header_file="$1"
  78. grep '^link:' "$header_file" \
  79. | tr -d ' ' \
  80. | tr '[A-Z]' '[a-z]' \
  81. | sed 's/>;rel="next",.*//' \
  82. | sed 's/link:<//'
  83. }
  84. # Given a tab-delimited bookmark line, process HTML description into plain-text.
  85. bookmark_line_desc() {
  86. awk -F '\t' '{print $3}' \
  87. | sed 's%^"%%' \
  88. | sed 's%"$%%' \
  89. | html_text_deescape \
  90. | tr '\n\t' ' '
  91. }