📦➔🦋 Store and retrieve files on the Atmosphere
1#!/usr/bin/env bash
2
3function atfile.upload() {
4 file="$1"
5 recipient="$2"
6 key="$3"
7 unset error
8
9 if [[ ! -f "$file" ]]; then
10 atfile.die "File '$file' does not exist"
11 else
12 file="$(atfile.util.get_realpath "$file")"
13 fi
14
15 if [[ -n $recipient ]]; then
16 file_crypt="$(dirname "$file")/$(basename "$file").gpg"
17
18 # shellcheck disable=SC2154
19 [[ $_output_json == 0 ]] && echo -e "Encrypting '$file_crypt'..."
20 gpg --yes --quiet --recipient "$recipient" --output "$file_crypt" --encrypt "$file"
21
22 # shellcheck disable=SC2181
23 if [[ $? == 0 ]]; then
24 file="$file_crypt"
25 else
26 rm -f "$file_crypt"
27 atfile.die "Unable to encrypt '$(basename "$file")'"
28 fi
29 fi
30
31 if [[ -z "$error" ]]; then
32 unset file_date
33 unset file_size
34 unset file_type
35
36 # shellcheck disable=SC2154
37 case "$_os" in
38 "bsd"|"macos")
39 file_date="$(atfile.util.get_date "$(stat -f '%Sm' -t "%Y-%m-%dT%H:%M:%SZ" "$file")")"
40 file_size="$(stat -f '%z' "$file")"
41 file_type="$(file -b --mime-type "$file")"
42 ;;
43 "haiku")
44 haiku_file_attr="$(catattr BEOS:TYPE "$file" 2> /dev/null)"
45 # shellcheck disable=SC2181
46 [[ $? == 0 ]] && file_type="$(echo "$haiku_file_attr" | cut -d ":" -f 3 | xargs)"
47
48 file_date="$(atfile.util.get_date "$(stat -c '%y' "$file")")"
49 file_size="$(stat -c %s "$file")"
50 ;;
51 *)
52 file_date="$(atfile.util.get_date "$(stat -c '%y' "$file")")"
53 file_size="$(stat -c %s "$file")"
54 file_type="$(file -b --mime-type "$file")"
55 ;;
56 esac
57
58 file_hash="$(atfile.util.get_md5 "$file")"
59 file_hash_checksum="$(echo "$file_hash" | cut -d "|" -f 1)"
60 file_hash_type="$(echo "$file_hash" | cut -d "|" -f 2)"
61 file_name="$(basename "$file")"
62
63 if [[ -n $recipient ]]; then
64 file_type="application/prs.atfile.gpg-crypt"
65 elif [[ "$file_type" == "application/"* ]]; then
66 file_extension="${file_name##*.}"
67
68 case "$file_extension" in
69 "car") file_type="application/prs.atfile.car" ;;
70 "dmg"|"smi") file_type="application/x-apple-diskimage" ;;
71 esac
72 fi
73
74 file_type_emoji="$(atfile.util.get_file_type_emoji "$file_type")"
75
76 # shellcheck disable=SC2154
77 atfile.say.debug "File: $file\n↳ Date: $file_date\n↳ Hash: $file_hash_checksum ($file_hash_type)\n↳ Name: $file_name\n↳ Size: $file_size\n↳ Type: $file_type_emoji $file_type"
78
79 unset file_finger_record
80 unset file_meta_record
81
82 file_finger_record="$(atfile.util.get_finger_record)"
83 file_meta_record="$(atfile.util.get_meta_record "$file" "$file_type")"
84
85 atfile.say.debug "Checking filesize..."
86 # shellcheck disable=SC2154
87 file_size_surplus="$(atfile.util.get_file_size_surplus_for_pds "$file_size" "$_server")"
88
89 if [[ $file_size_surplus != 0 ]]; then
90 die_message="File '$file_name' is too large ($(atfile.util.get_file_size_pretty "$file_size_surplus") over)"
91 atfile.die "$die_message"
92 fi
93
94 # shellcheck disable=SC2154
95 [[ $_output_json == 0 ]] && echo "Uploading '$file'..."
96
97 blob="$(com.atproto.sync.uploadBlob "$file")"
98 error="$(atfile.util.get_xrpc_error $? "$blob")"
99 [[ $error == "?" ]] && error="Blob rejected by PDS (too large?)"
100
101 atfile.say.debug "Uploading blob...\n↳ Ref: $(echo "$blob" | jq -r ".ref.\"\$link\"")"
102
103 if [[ -z "$error" ]]; then
104 # shellcheck disable=SC2154
105 file_record="$(blue.zio.atfile.upload "$blob" "$_now" "$file_hash_checksum" "$file_hash_type" "$file_date" "$file_name" "$file_size" "$file_type" "$file_meta_record" "$file_finger_record")"
106
107 if [[ -n "$key" ]]; then
108 # shellcheck disable=SC2154
109 atfile.say.debug "Updating record...\n↳ NSID: $_nsid_upload\n↳ Repo: $_username\n↳ Key: $key"
110 record="$(com.atproto.repo.putRecord "$_username" "$_nsid_upload" "$key" "$file_record")"
111 error="$(atfile.util.get_xrpc_error $? "$record")"
112 else
113 # shellcheck disable=SC2154
114 atfile.say.debug "Creating record...\n↳ NSID: $_nsid_upload\n↳ Repo: $_username"
115 record="$(com.atproto.repo.createRecord "$_username" "$_nsid_upload" "$file_record")"
116 error="$(atfile.util.get_xrpc_error $? "$record")"
117 fi
118 fi
119 fi
120
121 if [[ -n $recipient ]]; then
122 rm -f "$file"
123 fi
124
125 if [[ -z "$error" ]]; then
126 unset recipient_key
127 blob_uri="$(atfile.util.build_blob_uri "$(echo "$record" | jq -r ".uri" | cut -d "/" -f 3)" "$(echo "$blob" | jq -r ".ref.\"\$link\"")")"
128 key="$(atfile.util.get_rkey_from_at_uri "$(echo "$record" | jq -r ".uri")")"
129
130 if [[ -n "$recipient" ]]; then
131 recipient_key="$(gpg --list-keys "$recipient" | sed -n 2p | xargs)"
132 fi
133
134 # shellcheck disable=SC2154
135 if [[ $_output_json == 1 ]]; then
136 unset recipient_json
137
138 if [[ -n "$recipient" ]]; then
139 recipient_json="{ \"id\": \"$recipient\", \"key\": \"$recipient_key\" }"
140 else
141 recipient_json="null"
142 fi
143
144 echo -e "{ \"blob\": \"$blob_uri\", \"key\": \"$key\", \"upload\": $record, \"recipient\": $recipient_json }" | jq
145 else
146 echo "---"
147 # shellcheck disable=SC2154
148 if [[ $_os == "haiku" ]]; then
149 # BUG: Haiku Terminal has issues with emojis
150 echo "Uploaded: $file_name"
151 else
152 echo "Uploaded: $file_type_emoji $file_name"
153 fi
154 atfile.util.print_blob_url_output "$blob_uri"
155 echo -e "↳ Key: $key"
156 # shellcheck disable=SC2154
157 echo -e "↳ URI: atfile://$_username/$key"
158 if [[ -n "$recipient" ]]; then
159 echo -e "↳ Recipient: $recipient ($recipient_key)"
160 fi
161 fi
162 else
163 atfile.die.xrpc_error "Unable to upload '$file'" "$error"
164 fi
165}