📦➔🦋 Store and retrieve files on the Atmosphere
1#!/usr/bin/env bash
2
3function atfile.help() {
4 # shellcheck disable=SC2154
5 if [[ $_output_json == 1 ]]; then
6 atfile.die "Command not available as JSON"
7 fi
8
9 unset error
10 unset handle
11
12 resolved_did="$(atfile.util.resolve_identity "$_meta_did")"
13 error="$(atfile.util.get_xrpc_error $? "$resolved_did")"
14
15 if [[ -n "$error" ]]; then
16 handle="invalid.handle"
17 else
18 handle="$(echo "$resolved_did" | cut -d "|" -f 3 | sed -s 's/at:\/\///g')"
19 fi
20
21# ------------------------------------------------------------------------------
22 usage_commands="Commands
23 upload <file> [<key>]
24 Upload new file to the PDS
25 ⚠️ ATProto records are public: do not upload sensitive files\n
26 list [<cursor>] [<actor>]
27 list <actor> [<cursor>]
28 List all uploaded files. Only $_max_list items can be displayed; to
29 paginate, use the last Key for <cursor>\n
30 fetch <key> [<actor>]
31 Download an uploaded file\n
32 cat <key> [<actor>]
33 Print (don't download) an uploaded file to the shell\n
34 url <key> [<actor>]
35 Get blob URL for an uploaded file\n
36 info <key> [<actor>]
37 Get full details for an uploaded file\n
38 delete <key>
39 Delete an uploaded file
40 ⚠️ No confirmation is asked before deletion\n
41 lock <key>
42 unlock <key>
43 Lock (or unlock) an uploaded file to prevent it from unintended
44 deletions
45 ⚠️ Other clients may be able to delete the file. This is intended as
46 a safety-net to avoid inadvertently deleting the wrong file\n
47 upload-crypt <file> <recipient> [<key>]
48 Encrypt file (with GPG) for <recipient> and upload to the PDS
49 ℹ️ Make sure the necessary GPG key has been imported first\n
50 fetch-crypt <file> [<actor>]
51 Download an uploaded encrypted file and attempt to decrypt it (with
52 GPG)
53 ℹ️ Make sure the necessary GPG key has been imported first"
54
55 usage_commands_devel="Commands (Devel)
56 build
57 Build (and release, if requested) as one file (to ./bin)
58 ℹ️ Set ${_envvar_prefix}_DEVEL_ENABLE_PUBLISH=1 to upload release"
59
60 usage_commands_lifecycle="Commands (Lifecycle)
61 update
62 Check for updates and update if outdated
63 ⚠️ If installed from your system's package manager, self-updating is
64 not possible\n
65 toggle-mime
66 Install/uninstall desktop file to handle atfile:/at: protocol"
67
68 usage_commands_tools="Commands (Tools)
69 blob list
70 List blobs on authenticated repository\n
71 blob upload <path>
72 Upload blobs to authenticated repository
73 ℹ️ Unless referenced by a record shortly after uploading, blob will be
74 garbage collected by the PDS\n
75 bsky [<actor>]
76 Get Bluesky profile for <actor>\n
77 handle <at-uri>
78 Open at:// URI with PDSls\n
79 handle <atfile-uri> [<handler>]
80 Open atfile:// URI with relevant App
81 ℹ️ Set <handler> to a .desktop entry (with '.desktop') to force the
82 application <atfile-uri> opens with\n
83 now
84 Get date in ISO-8601 format\n
85 record list <at-uri>
86 record create <collection> <record-json>
87 record create <at-uri> <record-json>
88 record get <at-uri>
89 record update <at-uri> <record-json>
90 record recreate <at-uri> <record-json>
91 record delete <at-uri>
92 Manage records on a repository
93 ⚠️ No validation is performed. Here be dragons!\n
94 resolve <actor>
95 Get details for <actor>\n
96 stream [<collection(s)>] [<did(s)>] [<cursor>] [<compress>]
97 Stream records from Jetstream
98 ℹ️ For multiple values (where appropriate) separate with ';'\n
99 token
100 Get JWT for authenticated account"
101
102 usage_envvars="Environment Variables
103 ${_envvar_prefix}_USERNAME <string> (required)
104 Username of the PDS user (handle or DID)
105 ${_envvar_prefix}_PASSWORD <string> (required)
106 Password of the PDS user
107 ℹ️ An App Password is recommended
108 ($_endpoint_social_app/settings/app-passwords)\n
109 ${_envvar_prefix}_ENABLE_FINGERPRINT <bool¹> (default: $_enable_fingerprint_default)
110 Apply machine fingerprint to uploaded files
111 ${_envvar_prefix}_OUTPUT_JSON <bool¹> (default: $_output_json_default)
112 Print all commands (and errors) as JSON
113 ⚠️ When sourcing, sets to 1
114 ${_envvar_prefix}_MAX_LIST <int> (default: $_max_list_default)
115 Maximum amount of items in any lists
116 ℹ️ Default value is calculated from your terminal's height
117 ⚠️ When output is JSON (${_envvar_prefix}_OUTPUT_JSON=1), sets to 100
118 ${_envvar_prefix}_FMT_BLOB_URL <string> (default: $_fmt_blob_url_default)
119 Format for blob URLs. Fragments:
120 * [server]: PDS endpoint
121 * [did]: Actor DID
122 * [cid]: Blob CID
123 ${_envvar_prefix}_FMT_OUT_FILE <string> (default: $_fmt_out_file_default)
124 Format for fetched filenames. Fragments:
125 * [key]: Record key of uploaded file
126 * [name]: Original name of uploaded file\n
127 ${_envvar_prefix}_ENDPOINT_APPVIEW <url> (default: ${_endpoint_appview_default}$([[ $_endpoint_appview_default == *"zio.blue" ]] && echo "²"))
128 Endpoint of the Bluesky (or compatible) AppView
129 ${_envvar_prefix}_ENDPOINT_JETSTREAM <url> (default: $_endpoint_jetstream_default$([[ $_endpoint_jetstream_default == *"zio.blue" ]] && echo "²"))
130 Endpoint of the Jetstream relay
131 ${_envvar_prefix}_ENDPOINT_PDS <url>
132 Endpoint of the PDS
133 ℹ️ Your PDS is resolved from your username. Set to override it (or if
134 resolving fails)
135 ${_envvar_prefix}_ENDPOINT_PDSLS <url> (default: ${_endpoint_pdsls_default})
136 Endpoint of PDSls
137 ${_envvar_prefix}_ENDPOINT_PLC_DIRECTORY <url> (default: ${_endpoint_plc_directory_default}$([[ $_endpoint_plc_directory_default == *"zio.blue" ]] && echo "²"))
138 Endpoint of the PLC directory
139 ${_envvar_prefix}_ENDPOINT_SOCIAL_APP <url> (default: ${_endpoint_social_app_default})
140 Endpoint of the Bluesky (or compatible) social app\n
141 ${_envvar_prefix}_DISABLE_AUTH_CHECK <bool¹> (default: $_disable_auth_check_default)
142 Skip session validation on startup
143 If you're confident your credentials are correct, and
144 \$${_envvar_prefix}_USERNAME is a DID (*not* a handle), this will
145 drastically improve performance!
146 ${_envvar_prefix}_DISABLE_NI_EXIFTOOL <bool¹> (default: $_disable_ni_exiftool_default)
147 Do not check if ExifTool is installed
148 ⚠️ If Exiftool is not installed, the relevant metadata records will
149 not be created:
150 * image/*: $_nsid_meta#photo
151 ${_envvar_prefix}_DISABLE_NI_MD5SUM <bool¹> (default: $_disable_ni_md5sum_default)
152 Do not check if MD5Sum is installed
153 ${_envvar_prefix}_DISABLE_NI_MEDIAINFO <bool¹> (default: $_disable_ni_mediainfo_default)
154 Do not check if MediaInfo is installed
155 ⚠️ If MediaInfo is not installed, the relevant metadata records will
156 not be created:
157 * audio/*: $_nsid_meta#audio
158 * video/*: $_nsid_meta#video
159 ${_envvar_prefix}_DISABLE_SETUP_DIR_CREATION <bool¹> (default: $_disable_setup_dir_creation)
160 Disable directory creation during setup
161 ${_envvar_prefix}_DISABLE_UNSUPPORTED_OS_WARN <bool¹> (default: $_disable_unsupported_os_warn)
162 Do not error when running on an unsupported OS
163 ${_envvar_prefix}_DISABLE_UPDATE_CHECKING <bool¹> (default: $_disable_update_checking_default)
164 Disable periodic update checking when command finishes
165 ${_envvar_prefix}_DISABLE_UPDATE_COMMAND <bool¹> (default: $_disable_update_command_default)
166 Disable \`update\` command\n
167 ${_envvar_prefix}_DEBUG³ <bool¹> (default: 0)
168 Print debug outputs
169 ⚠️ When output is JSON (${_envvar_prefix}_OUTPUT_JSON=1), sets to 0\n
170 ¹ A bool in Bash is 1 (true) or 0 (false)
171 ² These servers are ran by @$handle. You can trust us!
172 ³ Cannot be set by config file"
173
174 usage_paths="Paths
175 $_path_envvar
176 List of key/values of the above environment variables. Exporting these
177 on the shell (with \`export \$ATFILE_VARIABLE\`) overrides these values
178 ℹ️ Set ${_envvar_prefix}_PATH_CONF to override\n
179 $_path_cache/
180 $_path_blobs_tmp/
181 Cache and temporary storage"
182
183 usage="ATFile"
184 [[ $_os != "haiku" ]] && usage+=" | 📦 ➔ 🦋"
185
186 usage+="\n Store and retrieve files on the ATmosphere\n
187 Version $_version
188 (c) $_meta_year $_meta_author <$_meta_repo>
189 Licensed as MIT License ✨\n
190 🦋 Follow @$handle on the ATmosphere
191 ↳ $_endpoint_social_app_name: $_endpoint_social_app/profile/$handle
192 ↳ Tangled: https://tangled.sh/@$handle
193
194Usage
195 $_prog <command> [<arguments>]
196 $_prog atfile://<actor>/<key>\n\n"
197
198 [[ $ATFILE_DEVEL == 1 ]] && usage+="$usage_commands_devel\n\n"
199 usage+="$usage_commands\n\n"
200 usage+="$usage_commands_lifecycle\n\n"
201 usage+="$usage_commands_tools\n\n"
202 usage+="$usage_envvars\n\n"
203 usage+="$usage_paths\n"
204
205 if [[ $_debug == 1 ]]; then
206 echo -e "$usage"
207 else
208 echo -e "$usage" | less
209 fi
210
211 [[ -n "$error" ]] && atfile.die.xrpc_error "Unable to resolve '$_meta_did'" "$error"
212
213# ------------------------------------------------------------------------------
214}