๐Ÿ“ฆโž”๐Ÿฆ‹ Store and retrieve files on the Atmosphere
35
fork

Configure Feed

Select the types of activity you want to include in your feed.

[#7] dev โž” issue/7-lexicon-docs

Ducky 1dd0b6d1 ae2e2373

+525 -184
+14
.vscode/launch.json
··· 1 + { 2 + // Use IntelliSense to learn about possible attributes. 3 + // Hover to view descriptions of existing attributes. 4 + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 + "version": "0.2.0", 6 + "configurations": [ 7 + { 8 + "type": "bashdb", 9 + "request": "launch", 10 + "name": "Debug", 11 + "program": "atfile.sh" 12 + } 13 + ] 14 + }
+1 -1
atfile-install.sh
··· 6 6 } 7 7 8 8 uid="$(id -u)" 9 - tag="v/0.x/0.4.6" 9 + tag="v/0.x/0.4.10" 10 10 url="https://raw.githubusercontent.com/electricduck/atfile/refs/tags/$tag/atfile.sh" 11 11 12 12 install_file="atfile"
+510 -183
atfile.sh
··· 81 81 82 82 # Utilities 83 83 84 + function atfile.util.build_blob_uri() { 85 + did="$1" 86 + cid="$2" 87 + pds="$_server" 88 + 89 + echo "$_fmt_blob_url" | sed -e "s|\[pds\]|$pds|g" -e "s|\[server\]|$pds|g" -e "s|\[cid\]|$cid|g" -e "s|\[did\]|$did|g" 90 + } 91 + 92 + function atfile.util.build_out_filename() { 93 + key="$1" 94 + name="$2" 95 + 96 + echo "$_fmt_out_file" | sed -e "s|\[name\]|$name|g" -e "s|\[key\]|$key|g" 97 + } 98 + 84 99 function atfile.util.check_prog() { 85 100 command="$1" 86 101 download_hint="$2" ··· 110 125 [[ $_skip_ni_mediainfo == 0 ]] && atfile.util.check_prog "mediainfo" "https://mediaarea.net/en/MediaInfo" "${_envvar_prefix}_SKIP_NI_MEDIAINFO" 111 126 } 112 127 128 + function atfile.util.get_app_url_for_at_uri() { 129 + uri="$1" 130 + 131 + actor="$(echo $uri | cut -d / -f 3)" 132 + collection="$(echo $uri | cut -d / -f 4)" 133 + rkey="$(echo $uri | cut -d / -f 5)" 134 + 135 + ignore_url_validation=0 136 + resolved_actor="$(atfile.util.resolve_identity "$actor")" 137 + unset actor_handle 138 + unset actor_pds 139 + unset resolved_url 140 + 141 + if [[ $? == 0 ]]; then 142 + actor="$(echo "$resolved_actor" | cut -d "|" -f 1)" 143 + actor_handle="$(echo "$resolved_actor" | cut -d "|" -f 3 | cut -d "/" -f 3)" 144 + actor_pds="$(echo "$resolved_actor" | cut -d "|" -f 2)" 145 + else 146 + unset actor 147 + fi 148 + 149 + [[ -z "$rkey" ]] && rkey="self" 150 + 151 + if [[ -n "$actor" && -n "$collection" && -n "$rkey" ]]; then 152 + case "$collection" in 153 + "app.bsky.actor.profile") resolved_url="https://bsky.app/profile/$actor" ;; 154 + "app.bsky.feed.generator") resolved_url="https://bsky.app/profile/$actor/feed/$rkey" ;; 155 + "app.bsky.graph.list") resolved_url="https://bsky.app/profile/$actor/lists/$rkey" ;; 156 + "app.bsky.graph.starterpack") resolved_url="https://bsky.app/starter-pack/$actor/$rkey" ;; 157 + "app.bsky.feed.post") resolved_url="https://bsky.app/profile/$actor/post/$rkey" ;; 158 + "blue.linkat.board") ignore_url_validation=1 && resolved_url="https://linkat.blue/$actor_handle" ;; 159 + "blue.zio.atfile.lock") ignore_url_validation=1 && resolved_url="atfile://$actor/upload/$rkey" ;; 160 + "blue.zio.atfile.upload") ignore_url_validation=1 && resolved_url="atfile://$actor/upload/$rkey" ;; 161 + "chat.bsky.actor.declaration") resolved_url="https://bsky.app/messages/settings" ;; 162 + "com.shinolabs.pinksea.oekaki") resolved_url="https://pinksea.art/$actor/oekaki/$rkey" ;; 163 + "com.whtwnd.blog.entry") resolved_url="https://whtwnd.com/$actor/$rkey" ;; 164 + "events.smokesignal.app.profile") resolved_url="https://smokesignal.events/$actor" ;; 165 + "events.smokesignal.calendar.event") resolved_url="https://smokesignal.events/$actor/$rkey" ;; 166 + "fyi.unravel.frontpage.post") resolved_url="https://frontpage.fyi/post/$actor/$rkey" ;; 167 + "app.bsky.feed.like"| \ 168 + "app.bsky.feed.postgate"| \ 169 + "app.bsky.feed.repost"| \ 170 + "app.bsky.feed.threadgate"| \ 171 + "app.bsky.graph.follow"| \ 172 + "app.bsky.graph.listblock"| \ 173 + "app.bsky.graph.listitem"| \ 174 + "events.smokesignal.calendar.rsvp"| \ 175 + "fyi.unravel.frontpage.comment"| \ 176 + "fyi.unravel.frontpage.vote") 177 + record="$(atfile.xrpc.get "com.atproto.repo.getRecord" "repo=$actor&collection=$collection&rkey=$rkey" "" "$actor_pds")" 178 + 179 + if [[ "$(atfile.util.is_xrpc_success $? "$record")" == 1 ]]; then 180 + case "$collection" in 181 + "app.bsky.feed.like") 182 + resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.subject.uri')")" ;; 183 + "app.bsky.feed.postgate") 184 + resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.post')")" ;; 185 + "app.bsky.feed.repost") 186 + resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.subject.uri')")" ;; 187 + "app.bsky.feed.threadgate") 188 + resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.post')")" ;; 189 + "app.bsky.graph.follow") 190 + resolved_url="https://bsky.app/profile/$(echo "$record" | jq -r '.value.subject')" ;; 191 + "app.bsky.graph.listblock") 192 + resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.subject')")" ;; 193 + "app.bsky.graph.listitem") 194 + resolved_url="https://bsky.app/profile/$(echo "$record" | jq -r '.value.subject')" ;; 195 + "events.smokesignal.calendar.rsvp") 196 + resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.subject.uri')")" ;; 197 + "fyi.unravel.frontpage.comment") 198 + resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.post.uri')")/$actor/$rkey" ;; 199 + "fyi.unravel.frontpage.vote") 200 + resolved_url="$(atfile.util.get_app_url_for_at_uri "$(echo "$record" | jq -r '.value.subject.uri')")" ;; 201 + esac 202 + fi 203 + ;; 204 + esac 205 + elif [[ -n "$actor" ]]; then 206 + resolved_url="https://pdsls.dev/at/$actor" 207 + fi 208 + 209 + if [[ -n "$resolved_url" && $ignore_url_validation == 0 ]]; then 210 + if [[ $(atfile.util.is_url_okay "$resolved_url") == 0 ]]; then 211 + unset resolved_url 212 + fi 213 + fi 214 + 215 + echo "$resolved_url" 216 + } 217 + 113 218 function atfile.util.get_cache() { 114 219 file="$_cache_dir/$1" 115 220 ··· 168 273 else 169 274 echo "null" 170 275 fi 276 + } 277 + 278 + function atfile.util.get_didplc_doc() { 279 + actor="$1" 280 + 281 + function atfile.util.get_didplc_doc.request_doc() { 282 + endpoint="$1" 283 + actor="$2" 284 + 285 + curl -s -L -X GET "$endpoint/$actor" 286 + } 287 + 288 + didplc_endpoint="$_endpoint_plc_directory" 289 + didplc_doc="$(atfile.util.get_didplc_doc.request_doc "$didplc_endpoint" "$actor")" 290 + 291 + if [[ "$didplc_doc" != "{"* ]]; then 292 + didplc_endpoint="$_endpoint_plc_directory_fallback" 293 + didplc_doc="$(atfile.util.get_didplc_doc.request_doc "$didplc_endpoint" "$actor")" 294 + fi 295 + 296 + echo "$(echo $didplc_doc | jq ". += {\"directory\": \"$didplc_endpoint\"}")" 297 + } 298 + 299 + function atfile.util.get_didweb_doc_url() { 300 + actor="$1" 301 + echo "https://$(echo "$actor" | sed "s/did:web://")/.well-known/did.json" 171 302 } 172 303 173 304 function atfile.util.get_envvar() { ··· 499 630 esac 500 631 } 501 632 633 + function atfile.util.get_pds_pretty() { 634 + pds="$1" 635 + 636 + pds_host="$(echo $pds | cut -d "/" -f 3)" 637 + 638 + if [[ $pds_host == *".host.bsky.network" ]]; then 639 + bsky_host="$(echo $pds_host | cut -d "." -f 1)" 640 + bsky_region="$(echo $pds_host | cut -d "." -f 2)" 641 + echo "๐Ÿ„ ${bsky_host^} ($(atfile.util.get_region_pretty "$bsky_region"))" 642 + elif [[ $pds_host == "atproto.brid.gy" ]]; then 643 + echo "๐Ÿ”€ Bridy Fed" 644 + else 645 + pds_oauth_url="$pds/oauth/authorize" 646 + pds_oauth_page="$(curl -s -L -X GET "$pds_oauth_url")" 647 + pds_customization_data="$(echo $pds_oauth_page | sed -s s/.*_customizationData\"]=//g | sed -s s/\;document\.currentScript\.remove.*//g)" 648 + 649 + if [[ $pds_customization_data == "{"* ]]; then 650 + echo "๐ŸŸฆ $(echo $pds_customization_data | jq -r '.name')" 651 + else 652 + echo "$pds" 653 + fi 654 + fi 655 + } 656 + 502 657 function atfile.util.get_realpath() { 503 658 path="$1" 504 659 ··· 507 662 else 508 663 realpath -s "$path" 509 664 fi 665 + } 666 + 667 + function atfile.util.get_region_pretty() { 668 + region="$1" 669 + 670 + region_sub="$(echo $1 | cut -d "-" -f 2)" 671 + region="$(echo $1 | cut -d "-" -f 1)" 672 + 673 + echo "${region^^} ${region_sub^}" 510 674 } 511 675 512 676 function atfile.util.get_rkey_from_at_uri() { ··· 577 741 578 742 function atfile.util.is_url_accessible_in_browser() { 579 743 url="$1" 744 + atfile.util.is_url_okay "$url" "$_test_desktop_uas" 745 + } 746 + 747 + function atfile.util.is_url_okay() { 748 + url="$1" 749 + uas="$2" 750 + 751 + [[ -z "$uas" ]] && uas="$(atfile.util.get_uas)" 752 + 753 + code="$(curl -H "User-Agent: $uas" -s -o /dev/null -w "%{http_code}" "$url")" 580 754 581 - code="$(curl -H "User-Agent: $_test_desktop_uas" -s -o /dev/null -w "%{http_code}" "$url")" 582 - 583 755 if [[ "$code" == 2* || "$code" == 3* ]]; then 584 756 echo 1 585 757 else ··· 598 770 fi 599 771 } 600 772 601 - function atfile.util.build_blob_uri() { 602 - did="$1" 603 - cid="$2" 604 - pds="$_server" 605 - 606 - echo "$_fmt_blob_url" | sed -e "s|\[pds\]|$pds|g" -e "s|\[server\]|$pds|g" -e "s|\[cid\]|$cid|g" -e "s|\[did\]|$did|g" 607 - } 608 - 609 - function atfile.util.build_out_filename() { 610 - key="$1" 611 - name="$2" 773 + function atfile.until.launch_uri() { 774 + uri="$1" 612 775 613 - echo "$_fmt_out_file" | sed -e "s|\[name\]|$name|g" -e "s|\[key\]|$key|g" 614 - } 615 - 616 - function atfile.util.resolve_identity() { 617 - actor="$1" 618 - 619 - if [[ "$actor" != "did:"* ]]; then 620 - resolved_handle="$(atfile.xrpc.get "com.atproto.identity.resolveHandle" "handle=$actor" "" "$_endpoint_resolve_handle")" 621 - if [[ $(atfile.util.is_xrpc_success $? "$resolved_handle") == 1 ]]; then 622 - actor="$(echo "$resolved_handle" | jq -r ".did")" 623 - fi 624 - fi 625 - 626 - if [[ "$actor" == "did:"* ]]; then 627 - unset did_doc 628 - 629 - case "$actor" in 630 - "did:plc:"*) did_doc="$(curl -s -L -X GET "$_endpoint_plc_directory/$actor")" ;; # TODO: What if they're not on plc.directory? 631 - "did:web:"*) did_doc="$(curl -s -L -X GET "$(echo "$actor" | sed "s/did:web://")/.well-known/did.json")" ;; 632 - esac 633 - 634 - if [[ $? != 0 || -z "$did_doc" ]]; then 635 - atfile.die "Unable to fetch DID Doc for '$actor'" 776 + if [[ -n $DISPLAY ]] && [ -x "$(command -v xdg-open)" ]; then 777 + if [[ $(atfile.util.get_os) == "macos" ]]; then 778 + open "$uri" 636 779 else 637 - did="$(echo "$did_doc" | jq -r ".id")" 638 - pds="$(echo "$did_doc" | jq -r '.service[] | select(.id == "#atproto_pds") | .serviceEndpoint')" 639 - 640 - echo "$did@$pds" 780 + xdg-open "$uri" 641 781 fi 642 782 else 643 - atfile.die "Unable to resolve '$actor'" 783 + echo "$uri" 644 784 fi 645 785 } 646 786 ··· 656 796 657 797 if ! [[ $actor == $_username ]]; then 658 798 resolved_id="$(atfile.util.resolve_identity "$actor")" 659 - _username="$(echo $resolved_id | cut -d "@" -f 1)" 660 - _server="$(echo $resolved_id | cut -d "@" -f 2)" 799 + _username="$(echo $resolved_id | cut -d "|" -f 1)" 800 + _server="$(echo $resolved_id | cut -d "|" -f 2)" 661 801 662 802 if [[ "$_fmt_blob_url" != "$_fmt_blob_url_default" ]]; then 663 803 export _fmt_blob_url="$_fmt_blob_url_default" ··· 673 813 [[ -n "$_fmt_blob_url_original" ]] && _fmt_blob_url="$_fmt_blob_url_original"; unset _fmt_blob_url_original 674 814 } 675 815 816 + function atfile.util.parse_exiftool_date() { 817 + in_date="$1" 818 + tz="$2" 819 + 820 + date="$(echo "$in_date" | cut -d " " -f 1 | sed -e "s|:|-|g")" 821 + time="$(echo "$in_date" | cut -d " " -f 2)" 822 + 823 + echo "$date $time $tz" 824 + } 825 + 676 826 function atfile.util.print_blob_url_output() { 677 827 blob_uri="$1" 678 828 ··· 697 847 fi 698 848 } 699 849 700 - function atfile.util.print_hidden_command_warning() { 701 - envvar="$1" 702 - echo -e "โš ๏ธ Hidden command ($_command)\n If you know what you're doing, enable with ${_envvar_prefix}_ENABLE_HIDDEN_COMMANDS=1" 703 - } 704 - 705 850 # HACK: We don't normally atfile.say() in the atfile.util.* namespace, but 706 851 # atfile.until.override_actor() is in this namespace and it would be nice 707 852 # to have a debug output for it when called in the main command case ··· 720 865 fi 721 866 } 722 867 723 - function atfile.util.parse_exiftool_date() { 724 - in_date="$1" 725 - tz="$2" 726 - 727 - date="$(echo "$in_date" | cut -d " " -f 1 | sed -e "s|:|-|g")" 728 - time="$(echo "$in_date" | cut -d " " -f 2)" 729 - 730 - echo "$date $time $tz" 731 - } 732 - 733 868 function atfile.util.repeat_char() { 734 869 char="$1" 735 870 amount="$2" ··· 737 872 printf "%0.s$char" $(seq 1 $amount) 738 873 } 739 874 875 + function atfile.util.resolve_identity() { 876 + actor="$1" 877 + 878 + if [[ "$actor" != "did:"* ]]; then 879 + resolved_handle="$(atfile.xrpc.get "com.atproto.identity.resolveHandle" "handle=$actor" "" "$_endpoint_resolve_handle")" 880 + if [[ $(atfile.util.is_xrpc_success $? "$resolved_handle") == 1 ]]; then 881 + actor="$(echo "$resolved_handle" | jq -r ".did")" 882 + fi 883 + fi 884 + 885 + if [[ "$actor" == "did:"* ]]; then 886 + unset did_doc 887 + 888 + case "$actor" in 889 + "did:plc:"*) did_doc="$(atfile.util.get_didplc_doc "$actor")" ;; 890 + "did:web:"*) did_doc="$(curl -s -L -X GET "$(atfile.util.get_didweb_doc_url "$actor")")" ;; 891 + esac 892 + 893 + if [[ $? != 0 || -z "$did_doc" ]]; then 894 + atfile.die "Unable to fetch DID Doc for '$actor'" 895 + else 896 + did="$(echo "$did_doc" | jq -r ".id")" 897 + didplc_dir="$(echo "$did_doc" | jq -r ".directory")" 898 + pds="$(echo "$did_doc" | jq -r '.service[] | select(.id == "#atproto_pds") | .serviceEndpoint')" 899 + handle="$(echo "$did_doc" | jq -r '.alsoKnownAs[0]')" 900 + 901 + [[ $didplc_dir == "null" ]] && unset didplc_dir 902 + 903 + echo "$did|$pds|$handle|$didplc_dir" 904 + fi 905 + else 906 + atfile.die "Unable to resolve '$actor'" 907 + fi 908 + } 909 + 740 910 function atfile.util.write_cache() { 741 911 file="$1" 742 912 file_path="$_cache_dir/$1" ··· 799 969 -H "Content-Type: $type" \ 800 970 -H "User-Agent: $(atfile.util.get_uas)" \ 801 971 --data-binary @"$file" | jq 972 + } 973 + 974 + ## JetStream 975 + 976 + function atfile.js.subscribe() { 977 + collection="$1" 978 + 979 + atfile.util.check_prog "websocat" 980 + websocat "$_endpoint_jetstream/subscribe?wantedCollections=$collection" 802 981 } 803 982 804 983 # Lexicons ··· 1213 1392 โ†ณ UAS: $(atfile.util.get_uas) 1214 1393 Variables 1215 1394 $(atfile.invoke.debug.print_envvar "DEBUG" $_debug_default) 1216 - $(atfile.invoke.debug.print_envvar "ENABLE_HIDDEN_COMMANDS" $_enable_hidden_commands_default) 1217 1395 $(atfile.invoke.debug.print_envvar "ENDPOINT_PDS") 1218 1396 $(atfile.invoke.debug.print_envvar "ENDPOINT_PLC_DIRECTORY" $_endpoint_plc_directory_default) 1219 1397 $(atfile.invoke.debug.print_envvar "ENDPOINT_RESOLVE_HANDLE" $_endpoint_resolve_handle_default) ··· 1446 1624 fi 1447 1625 } 1448 1626 1449 - function atfile.invoke.update() { 1450 - function atfile.invoke.update.parse_version() { 1451 - version="$1" 1452 - version="$(echo $version | cut -d "+" -f 1)" 1453 - v_major="$(printf "%04d\n" "$(echo $version | cut -d "." -f 1)")" 1454 - v_minor="$(printf "%04d\n" "$(echo $version | cut -d "." -f 2)")" 1455 - v_rev="$(printf "%04d\n" "$(echo $version | cut -d "." -f 3)")" 1456 - echo "$(echo ${v_major}${v_minor}${v_rev} | sed 's/^0*//')" 1627 + function atfile.invoke.handle() { 1628 + uri="$1" 1629 + 1630 + function atfile.invoke.handle.handle_error() { 1631 + cli_error="$1" 1632 + gui_error="$2" 1633 + 1634 + [[ -z $gui_error ]] && gui_error="$cli_error" 1635 + 1636 + if [ -x "$(command -v zenity)" ]; then 1637 + zenity --error --text "$gui_error" 1638 + fi 1639 + 1640 + atfile.die "$cli_error" 1457 1641 } 1458 1642 1459 - if [[ $_output_json == 1 ]]; then 1460 - atfile.die "Command not available as JSON" 1461 - fi 1462 - 1463 - atfile.say.debug "Getting latest release..." 1464 - latest_release="$(curl -s -H "User-Agent $_uas" "https://api.github.com/repos/$_gh_user/$_gh_repo/releases/latest")" 1465 - [[ $? != 0 ]] && atfile.die "Unable to get latest version (is GitHub up?)" 1466 - 1467 - latest_version="$(echo "$latest_release" | jq -r ".name")" 1468 - latest_tag="$(echo "$latest_release" | jq -r ".tag_name")" 1469 - 1470 - parsed_latest_version="$(atfile.invoke.update.parse_version $latest_version)" 1471 - parsed_running_version="$(atfile.invoke.update.parse_version $_version)" 1472 - 1473 - atfile.say.debug "Version\nโ†ณ Latest: $latest_version ($parsed_latest_version)\n โ†ณ Tag: $latest_tag\nโ†ณ Running: $_version ($parsed_running_version)" 1474 - 1475 - if [[ $_version == *+git* ]]; then 1476 - atfile.die "Cannot update Git version ($_version)" 1477 - fi 1478 - 1479 - if [[ $(( $parsed_latest_version > $parsed_running_version )) == 1 ]]; then 1480 - temp_updated_path="$_prog_dir/${_prog}-${latest_version}.tmp" 1481 - 1482 - atfile.say.debug "Touching temporary path ($temp_updated_path)..." 1483 - touch "$temp_updated_path" 1484 - [[ $? != 0 ]] && atfile.die "Unable to create temporary file (do you have permission?)" 1485 - 1486 - atfile.say.debug "Downloading latest release..." 1487 - curl -s -o "$temp_updated_path" "https://raw.githubusercontent.com/$_gh_user/$_gh_repo/refs/tags/$latest_tag/atfile.sh" 1488 - if [[ $? == 0 ]]; then 1489 - mv "$temp_updated_path" "$_prog_path" 1490 - if [[ $? != 0 ]]; then 1491 - atfile.die "Unable to update (do you have permission?)" 1492 - else 1493 - chmod +x "$_prog_path" 1494 - atfile.say "๐Ÿ˜Ž Updated to $latest_version!" 1495 - exit 0 1496 - fi 1497 - else 1498 - atfile.die "Unable to download latest version" 1499 - fi 1643 + [[ $_output_json == 1 ]] && atfile.die "Command not available as JSON" 1644 + [[ "$uri" != "at://"* ]] && atfile.invoke.handle.handle_error \ 1645 + "Invalid AT URI\nโ†ณ Must be 'at://<actor>[/<collection>/<rkey>]'" \ 1646 + "Invalid AT URI" 1647 + 1648 + atfile.say.debug "Resolving '$uri'..." 1649 + app_uri="$(atfile.util.get_app_url_for_at_uri "$uri")" 1650 + [[ -z "$app_uri" ]] && atfile.invoke.handle.handle_error \ 1651 + "Unable to resolve AT URI to App" 1652 + 1653 + app_proto="$(echo $app_uri | cut -d ":" -f 1)" 1654 + 1655 + atfile.say.debug "Opening '$app_uri' ($app_proto)..." 1656 + 1657 + if [[ $app_proto == "atfile" ]]; then 1658 + atfile.util.handle_protocol "$app_uri" 1500 1659 else 1501 - atfile.say "No updates found" 1660 + atfile.until.launch_uri "$app_uri" 1502 1661 fi 1503 1662 } 1504 1663 ··· 1692 1851 "delete") 1693 1852 collection="$(atfile.invoke.manage_record.get_collection "$3")" 1694 1853 key="$2" 1695 - [[ -z "$key" ]] && atfile.die "<key> not set" 1854 + [[ -z "$key" ]] && atfile.die "<key/at-uri> not set" 1696 1855 1697 1856 if [[ "$key" == at:* ]]; then 1698 1857 at_uri="$key" ··· 1731 1890 atfile.util.override_actor_reset 1732 1891 ;; 1733 1892 "put") 1734 - collection="$(atfile.invoke.manage_record.get_collection "$3")" 1893 + collection="$(atfile.invoke.manage_record.get_collection "$4")" 1735 1894 key="$2" 1736 1895 record="$3" 1737 - [[ -z "$key" ]] && atfile.die "<key> not set" 1896 + [[ -z "$key" ]] && atfile.die "<key/at-uri> not set" 1738 1897 [[ -z "$record" ]] && atfile.die "<record> not set" 1739 1898 1740 1899 record_json="$(echo "$record" | jq)" ··· 1797 1956 fi 1798 1957 } 1799 1958 1959 + function atfile.invoke.resolve() { 1960 + actor="$1" 1961 + 1962 + atfile.say.debug "Resolving actor '$actor'..." 1963 + resolved_did="$(atfile.util.resolve_identity "$actor")" 1964 + 1965 + alias="$(echo $resolved_did | cut -d "|" -f 3)" 1966 + did="$(echo $resolved_did | cut -d "|" -f 1)" 1967 + did_doc="$(echo $resolved_did | cut -d "|" -f 4)/$did" 1968 + did_type="did:$(echo $did | cut -d ":" -f 2)" 1969 + handle="$(echo $resolved_did | cut -d "|" -f 3 | cut -d "/" -f 3)" 1970 + pds="$(echo $resolved_did | cut -d "|" -f 2)" 1971 + pds_name="$(atfile.util.get_pds_pretty "$pds")" 1972 + atfile.say.debug "Getting PDS version for '$pds'..." 1973 + pds_version="$(curl -s -l -X GET "$pds/xrpc/_health" | jq -r '.version')" 1974 + 1975 + [[ "$did" == "null" ]] && atfile.die "Unable to resolve '$actor'" 1976 + 1977 + case "$did_type" in 1978 + "did:web") 1979 + did_doc="$(atfile.util.get_didweb_doc_url "$actor")" 1980 + ;; 1981 + esac 1982 + 1983 + if [[ $_output_json == 1 ]]; then 1984 + did_doc_data="$(curl -s -l -X GET "$did_doc")" 1985 + 1986 + echo -e "{ 1987 + \"did\": \"$did\", 1988 + \"doc\": { 1989 + \"data\": $did_doc_data, 1990 + \"url\": \"$did_doc\" 1991 + }, 1992 + \"handle\": \"$handle\", 1993 + \"pds\": { 1994 + \"endpoint\": \"$pds\", 1995 + \"name\": \"$pds_name\", 1996 + \"version\": \"$pds_version\" 1997 + }, 1998 + \"type\": \"$did_type\" 1999 + }" | jq 2000 + else 2001 + echo "$did" 2002 + echo "โ†ณ Type: $did_type" 2003 + echo " โ†ณ Doc: $did_doc" 2004 + echo "โ†ณ Handle: @$handle" 2005 + echo "โ†ณ PDS: $pds_name" 2006 + echo " โ†ณ Endpoint: $pds" 2007 + [[ $pds_version != "null" ]] && echo " โ†ณ Version: $pds_version" 2008 + fi 2009 + } 2010 + 2011 + function atfile.invoke.stream() { 2012 + collection="$1" 2013 + [[ -z "$collection" ]] && collection="blue.zio.atfile.upload" 2014 + atfile.js.subscribe "$collection" 2015 + } 2016 + 2017 + function atfile.invoke.update() { 2018 + function atfile.invoke.update.parse_version() { 2019 + version="$1" 2020 + version="$(echo $version | cut -d "+" -f 1)" 2021 + v_major="$(printf "%04d\n" "$(echo $version | cut -d "." -f 1)")" 2022 + v_minor="$(printf "%04d\n" "$(echo $version | cut -d "." -f 2)")" 2023 + v_rev="$(printf "%04d\n" "$(echo $version | cut -d "." -f 3)")" 2024 + echo "$(echo ${v_major}${v_minor}${v_rev} | sed 's/^0*//')" 2025 + } 2026 + 2027 + if [[ $_output_json == 1 ]]; then 2028 + atfile.die "Command not available as JSON" 2029 + fi 2030 + 2031 + atfile.say.debug "Getting latest release..." 2032 + latest_release="$(curl -s -H "User-Agent $_uas" "https://api.github.com/repos/$_gh_user/$_gh_repo/releases/latest")" 2033 + [[ $? != 0 ]] && atfile.die "Unable to get latest version (is GitHub up?)" 2034 + 2035 + latest_version="$(echo "$latest_release" | jq -r ".name")" 2036 + latest_tag="$(echo "$latest_release" | jq -r ".tag_name")" 2037 + 2038 + parsed_latest_version="$(atfile.invoke.update.parse_version $latest_version)" 2039 + parsed_running_version="$(atfile.invoke.update.parse_version $_version)" 2040 + 2041 + atfile.say.debug "Version\nโ†ณ Latest: $latest_version ($parsed_latest_version)\n โ†ณ Tag: $latest_tag\nโ†ณ Running: $_version ($parsed_running_version)" 2042 + 2043 + if [[ $_version == *+git* ]]; then 2044 + atfile.die "Cannot update Git version ($_version)" 2045 + fi 2046 + 2047 + if [[ $(( $parsed_latest_version > $parsed_running_version )) == 1 ]]; then 2048 + temp_updated_path="$_prog_dir/${_prog}-${latest_version}.tmp" 2049 + 2050 + atfile.say.debug "Touching temporary path ($temp_updated_path)..." 2051 + touch "$temp_updated_path" 2052 + [[ $? != 0 ]] && atfile.die "Unable to create temporary file (do you have permission?)" 2053 + 2054 + atfile.say.debug "Downloading latest release..." 2055 + curl -s -o "$temp_updated_path" "https://raw.githubusercontent.com/$_gh_user/$_gh_repo/refs/tags/$latest_tag/atfile.sh" 2056 + if [[ $? == 0 ]]; then 2057 + mv "$temp_updated_path" "$_prog_path" 2058 + if [[ $? != 0 ]]; then 2059 + atfile.die "Unable to update (do you have permission?)" 2060 + else 2061 + chmod +x "$_prog_path" 2062 + atfile.say "๐Ÿ˜Ž Updated to $latest_version!" 2063 + exit 0 2064 + fi 2065 + else 2066 + atfile.die "Unable to download latest version" 2067 + fi 2068 + else 2069 + atfile.say "No updates found" 2070 + fi 2071 + } 2072 + 1800 2073 function atfile.invoke.upload() { 1801 2074 file="$(atfile.util.get_file_path "$1")" 1802 2075 recipient="$2" ··· 1936 2209 fi 1937 2210 1938 2211 # ------------------------------------------------------------------------------ 1939 - usage_arguments="<actor> Act upon another ATProto user (either by handle or DID) 1940 - <cursor> Key or CID used as a reference to paginate through lists 1941 - <key> Key of an uploaded file (unique to that user and collection) 1942 - <nick> Nickname 1943 - <recipient> GPG recipient during file encryption 1944 - See 'gpg --help' for more information" 1945 - 1946 2212 usage_commands="upload <file> [<key>] 1947 2213 Upload new file to the PDS 1948 2214 โš ๏ธ ATProto records are public: do not upload sensitive files ··· 1990 2256 update 1991 2257 Check for updates and update if outdated" 1992 2258 1993 - if [[ $_enable_hidden_commands == 1 ]]; then 1994 - usage_commands+="\n\nCommands (Hidden) 1995 - blob list 2259 + usage_commands_tools="blob list 1996 2260 blob upload <path> 1997 - Manage blobs on a repository 2261 + Manage blobs on authenticated repository 2262 + 2263 + handle <at-uri> 2264 + Open at:// URL with relevant App 1998 2265 1999 2266 record add <record-json> [<collection>] 2000 2267 record get <key> [<collection>] [<actor>] ··· 2004 2271 record rm <key> [<collection>] 2005 2272 record rm <at-uri> 2006 2273 Manage records on a repository 2007 - โš ๏ธ Intended for advanced users. Here be dragons 2008 - โ„น๏ธ <collection> defaults to '$_nsid_upload'" 2009 - fi 2274 + โš ๏ธ No validation is performed. Here be dragons! 2275 + โ„น๏ธ <collection> defaults to '$_nsid_upload' 2276 + 2277 + resolve <actor> 2278 + Get details for <actor> 2279 + 2280 + stream <collection> 2281 + Stream records from Jetstream" 2010 2282 2011 2283 usage_envvars="${_envvar_prefix}_USERNAME <string> (required) 2012 2284 Username of the PDS user (handle or DID) ··· 2014 2286 Password of the PDS user 2015 2287 An App Password is recommended (https://bsky.app/settings/app-passwords) 2016 2288 2017 - ${_envvar_prefix}_INCLUDE_FINGERPRINT <bool*> (default: $_include_fingerprint_default) 2289 + ${_envvar_prefix}_INCLUDE_FINGERPRINT <boolยน> (default: $_include_fingerprint_default) 2018 2290 Apply machine fingerprint to uploaded files 2019 - ${_envvar_prefix}_OUTPUT_JSON <bool> (default: $_output_json_default) 2291 + ${_envvar_prefix}_OUTPUT_JSON <boolยน> (default: $_output_json_default) 2020 2292 Print all commands (and errors) as JSON 2021 2293 โš ๏ธ When sourcing, sets to 1 2022 2294 ${_envvar_prefix}_MAX_LIST <int> (default: $_max_list_default) ··· 2032 2304 Format for fetched filenames. Fragments: 2033 2305 * [key]: Record key of uploaded file 2034 2306 * [name]: Original name of uploaded file 2035 - ${_envvar_prefix}_SKIP_AUTH_CHECK <bool*> (default: $_skip_auth_check_default) 2307 + ${_envvar_prefix}_SKIP_AUTH_CHECK <boolยน> (default: $_skip_auth_check_default) 2036 2308 Skip session validation on startup 2037 2309 If you're confident your credentials are correct, and \$${_envvar_prefix}_USERNAME 2038 2310 is a DID (*not* a handle), this will drastically improve performance! 2039 - ${_envvar_prefix}_SKIP_COPYRIGHT_WARN <bool*> (default: $_skip_copyright_warn_default) 2311 + ${_envvar_prefix}_SKIP_COPYRIGHT_WARN <boolยน> (default: $_skip_copyright_warn_default) 2040 2312 Do not print copyright warning when uploading files to 2041 2313 https://bsky.social 2042 - ${_envvar_prefix}_SKIP_NI_EXIFTOOL <bool*> (default: $_skip_ni_exiftool_default) 2314 + ${_envvar_prefix}_SKIP_NI_EXIFTOOL <boolยน> (default: $_skip_ni_exiftool_default) 2043 2315 Do not check if ExifTool is installed 2044 2316 โš ๏ธ If Exiftool is not installed, the relevant metadata records will 2045 2317 not be created: 2046 2318 * image/*: $_nsid_meta#photo 2047 - ${_envvar_prefix}_SKIP_NI_MEDIAINFO <bool*> (default: $_skip_ni_mediainfo_default) 2319 + ${_envvar_prefix}_SKIP_NI_MEDIAINFO <boolยน> (default: $_skip_ni_mediainfo_default) 2048 2320 Do not check if MediaInfo is installed 2049 2321 โš ๏ธ If MediaInfo is not installed, the relevant metadata records will 2050 2322 not be created: 2051 2323 * audio/*: $_nsid_meta#audio 2052 2324 * video/*: $_nsid_meta#video 2053 2325 2326 + ${_envvar_prefix}_ENDPOINT_JETSTREAM <url> (default: $_endpoint_jetstream_default) 2327 + Endpoint of the Jetstream relay 2054 2328 ${_envvar_prefix}_ENDPOINT_PDS <url> 2055 2329 Endpoint of the PDS 2056 2330 โ„น๏ธ Your PDS is resolved from your username. Set to override it (or if 2057 2331 resolving fails) 2058 - ${_envvar_prefix}_ENDPOINT_PLC_DIRECTORY <url> (default: $_endpoint_plc_directory_default) 2059 - Endpoint of PLC directory 2060 - ${_envvar_prefix}_ENDPOINT_RESOLVE_HANDLE <url> (default: $_endpoint_resolve_handle_default) 2061 - Endpoint used for handle resolving 2062 - โ„น๏ธ Default value is a PDS ran by @ducky.ws and @astra.blue. You can 2063 - trust us! 2332 + ${_envvar_prefix}_ENDPOINT_PLC_DIRECTORY <url> (default: ${_endpoint_plc_directory_default}$([[ $_endpoint_plc_directory_default == *"zio.blue" ]] && echo "ยฒ")) 2333 + Endpoint of the PLC directory 2334 + ${_envvar_prefix}_ENDPOINT_RESOLVE_HANDLE <url> (default: ${_endpoint_resolve_handle_default}$([[ $_endpoint_plc_directory_default == *"zio.blue" ]] && echo "ยฒ")) 2335 + Endpoint of the PDS/AppView used for handle resolving 2064 2336 2065 - ${_envvar_prefix}_DEBUG <bool> (default: $_debug_default) 2337 + ${_envvar_prefix}_DEBUG <boolยน> (default: $_debug_default) 2066 2338 Print debug outputs 2067 2339 โš ๏ธ When output is JSON (${_envvar_prefix}_OUTPUT_JSON=1), sets to 0 2068 - ${_envvar_prefix}_ENABLE_HIDDEN_COMMANDS <bool> (default: $_enable_hidden_commands_default) 2069 - Enable hidden commands 2070 - โš ๏ธ When sourcing, sets to 1 2071 2340 2072 - * A bool in Bash is 1 (true) or 0 (false)" 2341 + ยน A bool in Bash is 1 (true) or 0 (false) 2342 + ยฒ These servers are ran by @ducky.ws (and @astra.blue). You can trust us!" 2073 2343 2074 2344 usage_files="$_envfile 2075 2345 List of key/values of the above environment variables. Exporting these 2076 2346 on the shell (with \`export \$ATFILE_VARIABLE\`) overrides these values 2077 2347 2078 2348 $_cache_dir/ 2079 - Cache and temporary storage" 2349 + Cache and temporary storage 2350 + โ„น๏ธ Intended for future use" 2080 2351 2081 2352 usage="ATFile | ๐Ÿ“ฆ โž” ๐Ÿฆ‹ 2082 2353 Store and retrieve files on the ATmosphere ··· 2090 2361 Commands 2091 2362 $usage_commands 2092 2363 2093 - Arguments 2094 - $usage_arguments 2364 + Commands (Tools) 2365 + $usage_commands_tools 2095 2366 2096 2367 Environment Variables 2097 2368 $usage_envvars ··· 2114 2385 2115 2386 ## Global variables 2116 2387 2388 + ### General 2389 + 2117 2390 _prog="$(basename "$(atfile.util.get_realpath "$0")")" 2118 - _prog_dir="$(dirname "$atfile.util.get_realpath "$0")")" 2391 + _prog_dir="$(dirname "$(atfile.util.get_realpath "$0")")" 2119 2392 _prog_path="$(atfile.util.get_realpath "$0")" 2120 - _version="0.4.6" 2393 + _version="0.4.10" 2121 2394 _c_author="Ducky" 2122 2395 _c_year="2024" 2123 2396 _gh_user="electricduck" ··· 2130 2403 _is_sourced=0 2131 2404 _now="$(atfile.util.get_date)" 2132 2405 2406 + ### Envvars 2407 + 2408 + #### Defaults 2409 + 2133 2410 _debug_default=0 2134 - _enable_hidden_commands_default=0 2411 + _endpoint_jetstream_default="wss://jetstream.atproto.tools" 2135 2412 _endpoint_resolve_handle_default="https://zio.blue" # lol wtf is bsky.social 2136 - _endpoint_plc_directory_default="https://plc.directory" 2413 + _endpoint_plc_directory_default="https://plc.zio.blue" 2137 2414 _fmt_blob_url_default="[server]/xrpc/com.atproto.sync.getBlob?did=[did]&cid=[cid]" 2138 2415 _fmt_out_file_default="[key]__[name]" 2139 2416 _include_fingerprint_default=0 ··· 2145 2422 _skip_ni_exiftool_default=0 2146 2423 _skip_ni_mediainfo_default=0 2147 2424 2425 + #### Fallbacks 2426 + 2427 + _endpoint_plc_directory_fallback="https://plc.directory" 2428 + 2429 + #### Set 2430 + 2148 2431 _debug="$(atfile.util.get_envvar "${_envvar_prefix}_DEBUG" $_debug_default)" 2149 - _enable_hidden_commands="$(atfile.util.get_envvar "${_envvar_prefix}_ENABLE_HIDDEN_COMMANDS" "$_enable_hidden_commands_default")" 2150 2432 _fmt_blob_url="$(atfile.util.get_envvar "${_envvar_prefix}_FMT_BLOB_URL" "$_fmt_blob_url_default")" 2151 2433 _fmt_out_file="$(atfile.util.get_envvar "${_envvar_prefix}_FMT_OUT_FILE" "$_fmt_out_file_default")" 2152 2434 _include_fingerprint="$(atfile.util.get_envvar "${_envvar_prefix}_INCLUDE_FINGERPRINT" "$_include_fingerprint_default")" 2435 + _endpoint_jetstream="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_JETSTREAM" "$_endpoint_jetstream_default")" 2153 2436 _endpoint_plc_directory="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_PLC_DIRECTORY" "$_endpoint_plc_directory_default")" 2154 2437 _endpoint_resolve_handle="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_RESOLVE_HANDLE" "$_endpoint_resolve_handle_default")" 2155 2438 _max_list="$(atfile.util.get_envvar "${_envvar_prefix}_MAX_LIST" "$_max_list_default")" ··· 2163 2446 _test_desktop_uas="Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0" 2164 2447 _username="$(atfile.util.get_envvar "${_envvar_prefix}_USERNAME")" 2165 2448 2449 + ### NSIDs 2450 + 2166 2451 _nsid_prefix="blue.zio" 2167 2452 _nsid_lock="${_nsid_prefix}.atfile.lock" 2168 2453 _nsid_meta="${_nsid_prefix}.atfile.meta" ··· 2173 2458 2174 2459 if [[ "$0" != "$BASH_SOURCE" ]]; then 2175 2460 _debug=0 2176 - _enable_hidden_commands=1 2177 2461 _is_sourced=1 2178 2462 _output_json=1 2179 2463 fi ··· 2193 2477 2194 2478 ## Git detection 2195 2479 2196 - if [ -x "$(command -v git)" ] && [[ -d "$_prog_dir/.git" ]]; then 2480 + if [ -x "$(command -v git)" ] && [[ -d "$_prog_dir/.git" ]] && [[ "$(realpath $(pwd))" == "$_prog_dir" ]]; then 2197 2481 atfile.say.debug "Getting tag from Git..." 2198 2482 git describe --exact-match --tags > /dev/null 2>&1 2199 2483 [[ $? != 0 ]] && _version+="+git.$(git rev-parse --short HEAD)" ··· 2234 2518 "rm") _command="delete" ;; 2235 2519 "download"|"f"|"d") _command="fetch" ;; 2236 2520 "download-crypt"|"fc"|"dc") _command="fetch-crypt" ;; 2521 + "at") _command="handle" ;; 2237 2522 "get"|"i") _command="info" ;; 2238 2523 "ls") _command="list" ;; 2524 + "did") _command="resolve" ;; 2525 + "js") _command="stream" ;; 2239 2526 "ul"|"u") _command="upload" ;; 2240 2527 "uc") _command="upload-crypt" ;; 2241 2528 "get-url"|"b") _command="url" ;; ··· 2262 2549 skip_resolving=0 2263 2550 2264 2551 if [[ $_is_sourced == 0 ]]; then 2265 - # NOTE: Speeds things up a little if the user is overriding actor 2266 - # Keep this in-sync with the main command case below! 2552 + # NOTE: Speeds things up a little if the user is overriding actor 2553 + # Keep this in-sync with the main command case below! 2267 2554 if [[ $_command == "cat" && -n "$3" ]] ||\ 2268 2555 [[ $_command == "fetch" && -n "$3" ]] ||\ 2269 2556 [[ $_command == "fetch-crypt" && -n "$3" ]] ||\ 2270 2557 [[ $_command == "info" && -n "$2" ]] ||\ 2271 2558 [[ $_command == "list" ]] && [[ "$2" == *.* || "$2" == did:* ]] ||\ 2272 2559 [[ $_command == "list" && -n "$3" ]] ||\ 2273 - [[ $_command == "url" && -n "$2" ]]; then 2274 - atfile.say.debug "Skipping identity resolving\nโ†ณ Actor is overridden" 2275 - skip_resolving=1 2560 + [[ $_command == "url" && -n "$3" ]]; then 2561 + atfile.say.debug "Skipping identity resolving\nโ†ณ Actor is overridden" 2562 + skip_resolving=1 2563 + fi 2564 + 2565 + # NOTE: Speeds things up a little if the command doesn't need actor resolving 2566 + if [[ $_command == "handle" ]] ||\ 2567 + [[ $_command == "resolve" ]]; then 2568 + atfile.say.debug "Skipping identity resolving\nโ†ณ Not required for command '$_command'" 2569 + skip_resolving=1 2276 2570 fi 2277 2571 fi 2278 2572 ··· 2280 2574 atfile.say.debug "Resolving identity..." 2281 2575 2282 2576 resolved_id="$(atfile.util.resolve_identity "$_username")" 2283 - _username="$(echo $resolved_id | cut -d "@" -f 1)" 2284 - _server="$(echo $resolved_id | cut -d "@" -f 2)" 2577 + _username="$(echo $resolved_id | cut -d "|" -f 1)" 2578 + _server="$(echo $resolved_id | cut -d "|" -f 2)" 2285 2579 2286 2580 atfile.say.debug "Resolved identity\nโ†ณ DID: $_username\nโ†ณ PDS: $_server" 2287 2581 fi ··· 2296 2590 2297 2591 session="$(com.atproto.server.getSession)" 2298 2592 if [[ $(atfile.util.is_xrpc_success $? "$session") == 0 ]]; then 2299 - atfile.die "Unable to authenticate as \"$_username\" on \"$_server\"" 2593 + atfile.die "Unable to authenticate" 2300 2594 else 2301 2595 _username="$(echo $session | jq -r ".did")" 2302 2596 fi ··· 2308 2602 fi 2309 2603 fi 2310 2604 2605 + function atfile.util.handle_protocol() { 2606 + uri="$1" 2607 + 2608 + actor="$(echo $uri | cut -d "/" -f 3)" 2609 + path="$(echo $uri | cut -d "/" -f 4)" 2610 + key="$(echo $uri | cut -d "/" -f 5)" 2611 + 2612 + if [[ -n "$actor" && -n "$path" && -n "$key" ]]; then 2613 + case "$path" in 2614 + "upload") 2615 + atfile.util.override_actor "$actor" 2616 + 2617 + if [[ -n $TERM ]]; then 2618 + atfile.invoke.get "$key" 2619 + else 2620 + atfile.until.launch_uri "$key" 2621 + fi 2622 + ;; 2623 + *) 2624 + atfile.die "Unable to handle '$path'" 2625 + esac 2626 + fi 2627 + } 2628 + 2629 + ## Protocol Handler 2630 + 2631 + if [[ "$_command" == "atfile:"* ]]; then 2632 + atfile.say.debug "Handling '$_command'..." 2633 + atfile.util.handle_protocol "$_command" 2634 + exit 0 2635 + fi 2636 + 2311 2637 ## Commands 2312 2638 2313 2639 if [[ $_is_sourced == 0 ]]; then ··· 2315 2641 2316 2642 case "$_command" in 2317 2643 "blob") 2318 - if [[ "$_enable_hidden_commands" == 1 ]]; then 2319 - case "$2" in 2320 - "list"|"ls"|"l") atfile.invoke.list_blobs "$3" ;; 2321 - "upload"|"u") atfile.invoke.upload_blob "$3" ;; 2322 - *) atfile.die.unknown_command "$(echo "$_command $2" | xargs)" ;; 2323 - esac 2324 - else 2325 - atfile.util.print_hidden_command_warning 2326 - exit 1 2327 - fi 2644 + case "$2" in 2645 + "list"|"ls"|"l") atfile.invoke.list_blobs "$3" ;; 2646 + "upload"|"u") atfile.invoke.upload_blob "$3" ;; 2647 + *) atfile.die.unknown_command "$(echo "$_command $2" | xargs)" ;; 2648 + esac 2328 2649 ;; 2329 2650 "cat") 2330 2651 [[ -z "$2" ]] && atfile.die "<key> not set" ··· 2358 2679 2359 2680 atfile.invoke.download "$2" 1 2360 2681 ;; 2682 + "handle") 2683 + atfile.invoke.handle "$2" 2684 + ;; 2361 2685 "info") 2362 2686 [[ -z "$2" ]] && atfile.die "<key> not set" 2363 2687 if [[ -n "$3" ]]; then ··· 2393 2717 ;; 2394 2718 "record") 2395 2719 # NOTE: Performs no validation (apart from JSON)! Here be dragons 2396 - if [[ "$_enable_hidden_commands" == 1 ]]; then 2397 - case "$2" in 2398 - "add"|"create"|"c") atfile.invoke.manage_record "create" "$3" "$4" ;; 2399 - "get"|"g") atfile.invoke.manage_record "get" "$3" "$4" "$5" ;; 2400 - "put"|"update"|"u") atfile.invoke.manage_record "put" "$3" "$4" ;; 2401 - "rm"|"delete"|"d") atfile.invoke.manage_record "delete" "$3" "$4" ;; 2402 - *) atfile.die.unknown_command "$(echo "$_command $2" | xargs)" ;; 2403 - esac 2404 - else 2405 - atfile.util.print_hidden_command_warning 2406 - exit 1 2407 - fi 2720 + case "$2" in 2721 + "add"|"create"|"c") atfile.invoke.manage_record "create" "$3" "$4" ;; 2722 + "get"|"g") atfile.invoke.manage_record "get" "$3" "$4" "$5" ;; 2723 + "put"|"update"|"u") atfile.invoke.manage_record "put" "$3" "$4" ;; 2724 + "rm"|"delete"|"d") atfile.invoke.manage_record "delete" "$3" "$4" ;; 2725 + *) atfile.die.unknown_command "$(echo "$_command $2" | xargs)" ;; 2726 + esac 2727 + ;; 2728 + "resolve") 2729 + atfile.invoke.resolve "$2" 2408 2730 ;; 2409 2731 "something-broke") 2410 2732 atfile.invoke.debug 2733 + ;; 2734 + "stream") 2735 + atfile.invoke.stream "$2" 2411 2736 ;; 2412 2737 "upload") 2413 2738 atfile.util.check_prog_optional_metadata ··· 2438 2763 ;; 2439 2764 esac 2440 2765 fi 2766 + 2767 + # lord help me