📦➔🦋 Store and retrieve files on the Atmosphere
1#!/usr/bin/env bash
2
3# Environment
4
5## Early-start global variables
6
7### Permutation
8
9_start="$(atfile.util.get_date "" "%s")" # 2
10_name="Atfile" # 2
11_envvar_prefix="${_name^^}" # 3
12_debug="$(atfile.util.get_envvar "${_envvar_prefix}_DEBUG" "$([[ $ATFILE_DEVEL == 1 ]] && echo 1 || echo 0)")" # 4
13_force_os="$(atfile.util.get_envvar "${_envvar_prefix}_FORCE_OS")" # 5
14
15### Combination
16
17_ci="$(atfile.util.get_ci)"
18_command="$1"
19_command_args=("${@:2}")
20_os="$(atfile.util.get_os)"
21_os_supported=0
22_is_piped=0
23_is_sourced=0
24_meta_author="{:meta_author:}"
25_meta_did="{:meta_did:}"
26_meta_repo="{:meta_repo:}"
27_meta_year="{:meta_year:}"
28_now="$(atfile.util.get_date)"
29_path_hook_post_start="$(atfile.util.get_envvar "${_envvar_prefix}_PATH_HOOK_POST_START")"
30_path_hook_pre_exit="$(atfile.util.get_envvar "${_envvar_prefix}_PATH_HOOK_PRE_EXIT")"
31_path_hook_pre_start="$(atfile.util.get_envvar "${_envvar_prefix}_PATH_HOOK_PRE_START")"
32_version="{:version:}"
33
34## "Hello, world!"
35
36atfile.say.debug "Reticulating splines..."
37atfile.util.source_hook "$_path_hook_pre_start"
38
39## Paths
40
41_path_home="$HOME"
42
43if [[ -n "$SUDO_USER" ]]; then
44 _path_home="$(eval echo "~$SUDO_USER")"
45fi
46
47_file_envvar="atfile.env"
48_path_blobs_tmp="/tmp"
49_path_cache="$_path_home/.cache"
50_path_envvar="$_path_home/.config"
51
52case $_os in
53 "haiku")
54 _path_blobs_tmp="/boot/system/cache/tmp"
55 _path_cache="$_path_home/config/cache"
56 _path_envvar="$_path_home/config/settings"
57 ;;
58 "linux-termux")
59 _path_blobs_tmp="$PREFIX/tmp"
60 ;;
61 "macos")
62 _path_envvar="$_path_home/Library/Application Support"
63 _path_blobs_tmp="/private/tmp"
64 ;;
65esac
66
67if [[ -n "$XDG_CONFIG_HOME" ]]; then
68 _path_envvar="$XDG_CONFIG_HOME"
69fi
70
71_path_blobs_tmp="$_path_blobs_tmp/at-blobs"
72_path_cache="$_path_cache/atfile"
73_path_envvar="$(atfile.util.get_envvar "${_envvar_prefix}_PATH_CONF" "$_path_envvar/$_file_envvar")"
74
75## OS detection
76
77atfile.say.debug "Detected OS: $_os"
78
79if [[ $_os != "unknown-"* ]] &&\
80 [[ $_os == "bsd" ]] ||\
81 [[ $_os == "haiku" ]] ||\
82 [[ $_os == "linux" ]] ||\
83 [[ $_os == "linux-mingw" ]] ||\
84 [[ $_os == "linux-termux" ]] ||\
85 [[ $_os == "macos" ]] ; then
86 _os_supported=1
87fi
88
89## CI detection
90
91[[ -n "$_ci" ]] && atfile.say.debug "Detected CI: $_ci"
92
93## Pipe detection
94
95if [ -p /dev/stdin ] ||\
96 [[ "$0" == "bash" || $0 == *"/bin/bash" ]]; then
97 _is_piped=1
98 atfile.say.debug "Piping: $0"
99fi
100
101## Source detection
102
103if [[ -n ${BASH_SOURCE[0]} ]]; then
104 if [[ "$0" != "${BASH_SOURCE[0]}" ]]; then
105 if [[ "$ATFILE_DEVEL" == 1 ]]; then
106 if [[ -n "$ATFILE_DEVEL_SOURCE" ]]; then
107 _is_sourced=1
108 atfile.say.debug "Sourcing: $ATFILE_DEVEL_SOURCE"
109 fi
110 else
111 _is_sourced=1
112 atfile.say.debug "Sourcing: ${BASH_SOURCE[0]}"
113 fi
114 fi
115fi
116
117# Installation
118
119if [[ $_is_piped == 1 ]] ||\
120 [[ "$1" == "install" ]]; then
121 atfile.util.source_hook "$_path_hook_post_start"
122
123 if [[ "$1" == "install" ]]; then
124 atfile.install "$2" "$3" "$4"
125 install_exit="$?"
126 else
127 atfile.install "$1" "$2" "$3"
128 install_exit="$?"
129 fi
130
131 atfile.util.source_hook "$_path_hook_pre_exit"
132 atfile.util.print_seconds_since_start_debug
133
134 exit $install_exit
135fi
136
137# Global variables
138
139## Reflection
140
141_prog="$(basename "$(atfile.util.get_realpath "$0")")"
142_prog_dir="$(dirname "$(atfile.util.get_realpath "$0")")"
143_prog_path="$(atfile.util.get_realpath "$0")"
144
145## Envvars
146
147### Fallbacks
148
149_max_list_fallback=100
150
151### Defaults
152
153_devel_dist_username_default="$_meta_did"
154_devel_enable_publish_default=0
155_disable_auth_check_default=0
156_disable_ni_exiftool_default=0
157_disable_ni_md5sum_default=0
158_disable_ni_mediainfo_default=0
159_disable_setup_dir_creation_default=0
160_disable_unsupported_os_warn_default=0
161_disable_update_checking_default=0
162_disable_update_command_default=0
163_enable_fingerprint_default=0
164_enable_update_git_clobber_default=0
165#_endpoint_appview_default="https://bsky.zio.blue"
166_endpoint_appview_default="https://api.bsky.app"
167#_endpoint_jetstream_default="wss://stream.zio.blue"
168_endpoint_jetstream_default="$(atfile.util.get_random_pbc_jetstream)"
169_endpoint_pdsls_default="https://pdsls.dev"
170_endpoint_plc_directory_default="https://plc.zio.blue"
171_endpoint_social_app_default="https://bsky.app"
172_fmt_blob_url_default="[server]/xrpc/com.atproto.sync.getBlob?did=[did]&cid=[cid]"
173_fmt_out_file_default="[key]__[name]"
174_enable_fingerprint_default=0
175_max_list_buffer=6
176_max_list_default=$(( $(atfile.util.get_term_rows) - _max_list_buffer ))
177_output_json_default=0
178
179### Set
180
181_devel_dist_password="$(atfile.util.get_envvar "${_envvar_prefix}_DEVEL_DIST_PASSWORD")"
182_devel_dist_username="$(atfile.util.get_envvar "${_envvar_prefix}_DEVEL_DIST_USERNAME" $_devel_dist_username_default)"
183_devel_enable_publish="$(atfile.util.get_envvar "${_envvar_prefix}_DEVEL_ENABLE_PUBLISH" $_devel_enable_publish_default)"
184_disable_auth_check="$(atfile.util.get_envvar "${_envvar_prefix}_DISABLE_AUTH_CHECK" "$_disable_auth_check_default")"
185_disable_ni_exiftool="$(atfile.util.get_envvar "${_envvar_prefix}_DISABLE_NI_EXIFTOOL" "$_disable_ni_exiftool_default")"
186_disable_ni_md5sum="$(atfile.util.get_envvar "${_envvar_prefix}_DISABLE_NI_MD5SUM" "$_disable_ni_md5sum_default")"
187_disable_ni_mediainfo="$(atfile.util.get_envvar "${_envvar_prefix}_DISABLE_NI_MEDIAINFO" "$_disable_ni_mediainfo_default")"
188_disable_setup_dir_creation="$(atfile.util.get_envvar "${_envvar_prefix}_DISABLE_SETUP_DIR_CREATION" "$_disable_setup_dir_creation_default")"
189_disable_unsupported_os_warn="$(atfile.util.get_envvar "${_envvar_prefix}_DISABLE_UNSUPPORTED_OS_WARN" "$_disable_unsupported_os_warn_default")"
190_disable_update_checking="$(atfile.util.get_envvar "${_envvar_prefix}_DISABLE_UPDATE_CHECKING" $_disable_update_checking_default)"
191_disable_update_command="$(atfile.util.get_envvar "${_envvar_prefix}_DISABLE_UPDATE_COMMAND" $_disable_update_command_default)"
192_enable_fingerprint="$(atfile.util.get_envvar "${_envvar_prefix}_ENABLE_FINGERPRINT" "$_enable_fingerprint_default")"
193_enable_update_git_clobber="$(atfile.util.get_envvar "${_envvar_prefix}_ENABLE_UPDATE_GIT_CLOBBER" "$_enable_update_git_clobber_default")"
194_endpoint_appview="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_APPVIEW" "$_endpoint_appview_default")"
195_endpoint_jetstream="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_JETSTREAM" "$_endpoint_jetstream_default")"
196_endpoint_pdsls="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_PDSLS" "$_endpoint_pdsls_default")"
197_endpoint_plc_directory="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_PLC_DIRECTORY" "$_endpoint_plc_directory_default")"
198_endpoint_social_app="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_SOCIAL_APP" "$_endpoint_social_app_default")"
199_fmt_blob_url="$(atfile.util.get_envvar "${_envvar_prefix}_FMT_BLOB_URL" "$_fmt_blob_url_default")"
200_fmt_out_file="$(atfile.util.get_envvar "${_envvar_prefix}_FMT_OUT_FILE" "$_fmt_out_file_default")"
201_force_meta_author="$(atfile.util.get_envvar "${_envvar_prefix}_FORCE_META_AUTHOR")"
202_force_meta_did="$(atfile.util.get_envvar "${_envvar_prefix}_FORCE_META_DID")"
203_force_meta_repo="$(atfile.util.get_envvar "${_envvar_prefix}_FORCE_META_REPO")"
204_force_meta_year="$(atfile.util.get_envvar "${_envvar_prefix}_FORCE_META_YEAR")"
205_force_now="$(atfile.util.get_envvar "${_envvar_prefix}_FORCE_NOW")"
206_force_version="$(atfile.util.get_envvar "${_envvar_prefix}_FORCE_VERSION")"
207_max_list="$(atfile.util.get_envvar "${_envvar_prefix}_MAX_LIST" "$_max_list_default")"
208_output_json="$(atfile.util.get_envvar "${_envvar_prefix}_OUTPUT_JSON" "$_output_json_default")"
209_server="$(atfile.util.get_envvar "${_envvar_prefix}_ENDPOINT_PDS")"
210_password="$(atfile.util.get_envvar "${_envvar_prefix}_PASSWORD")"
211_test_desktop_uas="Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
212_username="$(atfile.util.get_envvar "${_envvar_prefix}_USERNAME")"
213
214## Read-only
215
216_nsid_prefix="blue.zio"
217_nsid_lock="${_nsid_prefix}.atfile.lock"
218_nsid_meta="${_nsid_prefix}.atfile.meta"
219_nsid_upload="${_nsid_prefix}.atfile.upload"
220_endpoint_pdsls_name="PDSls"
221_endpoint_social_app_name="Bluesky"
222
223# Setup
224
225## Envvar correction
226
227### Overrides
228
229[[ -n $_force_meta_author ]] && \
230 _meta_author="$_force_meta_author" &&\
231 atfile.util.print_override_envvar_debug "Copyright Author" "_meta_author"
232[[ -n $_force_meta_did ]] && \
233 _meta_did="$_force_meta_did" &&\
234 _devel_dist_username="$(atfile.util.get_envvar "${_envvar_prefix}_DEVEL_DIST_USERNAME" "$_meta_did")" &&\
235 atfile.util.print_override_envvar_debug "DID" "_meta_did"
236[[ -n $_force_meta_repo ]] && \
237 _meta_repo="$_force_meta_repo" &&\
238 atfile.util.print_override_envvar_debug "Repo URL" "_meta_author"
239[[ -n $_force_meta_year ]] && \
240 _meta_year="$_force_meta_year" &&\
241 atfile.util.print_override_envvar_debug "Copyright Year" "_meta_year"
242[[ -n $_force_now ]] && \
243 _now="$_force_now" &&\
244 atfile.util.print_override_envvar_debug "Current Time" "_now"
245[[ -n $_force_os ]] &&\
246 _os="$_force_os" &&\
247 atfile.util.print_override_envvar_debug "OS" "_os"
248[[ -n $_force_version ]] && \
249 _version="$_force_version" &&\
250 atfile.util.print_override_envvar_debug "Version" "_version"
251
252if [[ $_endpoint_social_app != "$_endpoint_social_app_default" ]]; then
253 _endpoint_social_app_name="$(atfile.util.get_root_domain "$_endpoint_social_app")"
254 _endpoint_social_app_name="${_endpoint_social_app_name^}"
255fi
256
257### Validation
258
259[[ $_output_json == 1 ]] && [[ $_max_list == "$_max_list_default" ]] &&\
260 atfile.say.debug "Setting ${_envvar_prefix}_MAX_LIST to $_max_list_fallback\n↳ ${_envvar_prefix}_OUTPUT_JSON set to 1" &&\
261 _max_list=$_max_list_fallback
262[[ $(( _max_list > _max_list_fallback )) == 1 ]] &&\
263 atfile.say.debug "Setting ${_envvar_prefix}_MAX_LIST to $_max_list_fallback\n↳ Maximum is $_max_list_fallback" &&\
264 _max_list=$_max_list_fallback
265
266## OS detection
267
268if [[ $_os_supported == 0 ]]; then
269 if [[ $_disable_unsupported_os_warn == 0 ]]; then
270 atfile.die "Unsupported OS (${_os//unknown-/})\n↳ Set ${_envvar_prefix}_DISABLE_UNSUPPORTED_OS_WARN=1 to ignore"
271 else
272 atfile.say.debug "Ignoring unsupported OS warning\n↳ ${_envvar_prefix}_DISABLE_UNSUPPORTED_OS_WARN set to '$_disable_unsupported_os_warn'"
273 fi
274fi
275
276## Program detection
277
278_prog_hint_jq="https://jqlang.github.io/jq"
279
280[[ "$_os" == "haiku" ]] && _prog_hint_jq="pkgman install jq"
281
282atfile.util.check_prog "curl" "https://curl.se"
283[[ $_os != "haiku" && $_os != "solaris" ]] && atfile.util.check_prog "file" "https://www.darwinsys.com/file"
284atfile.util.check_prog "jq" "$_prog_hint_jq"
285[[ $_disable_ni_md5sum == 0 ]] && atfile.util.check_prog "md5sum" "" "${_envvar_prefix}_DISABLE_NI_MD5SUM"
286#[[ $_os == "haiku" ]] && atfile.util.check_prog "perl"
287
288# Main
289
290## Command aliases
291
292if [[ $_is_sourced == 0 ]]; then
293 previous_command="$_command"
294
295 case "$_command" in
296 "release") _command="build" ;;
297 "open"|"print"|"c") _command="cat" ;;
298 "rm") _command="delete" ;;
299 "download"|"f"|"d") _command="fetch" ;;
300 "download-crypt"|"fc"|"dc") _command="fetch-crypt" ;;
301 "at") _command="handle" ;;
302 "--help"|"-h") _command="help" ;;
303 "get"|"i") _command="info" ;;
304 "ls") _command="list" ;;
305 "did") _command="resolve" ;;
306 "sb") _command="something-broke" ;;
307 "js") _command="stream" ;;
308 "ul"|"u") _command="upload" ;;
309 "--update"|"-U") _command="update" ;;
310 "ub") _command="upload-blob" ;;
311 "uc") _command="upload-crypt" ;;
312 "get-url"|"b") _command="url" ;;
313 "--version"|"-V") _command="version" ;;
314 esac
315
316 if [[ $previous_command != "$_command" ]]; then
317 atfile.say.debug "Using command '$_command' for '$previous_command'..."
318 fi
319fi
320
321## Defaults
322
323[[ $_is_sourced == 0 && -z $_command ]] && _command="help"
324
325if [[ "$_command" == "atfile:"* || "$_command" == "at:"* || "$_command" == "https:"* ]]; then
326 _command="handle"
327 _command_args=("$1")
328 atfile.say.debug "Handling '${_command_args[*]}'..."
329fi
330
331## Invoke
332
333atfile.util.source_hook "$_path_hook_post_start"
334
335if [[ $_is_sourced == 0 ]]; then
336 atfile.auth
337 atfile.invoke "$_command" "${_command_args[@]}"
338fi
339
340atfile.util.source_hook "$_path_hook_pre_exit"
341atfile.util.print_seconds_since_start_debug