tip.sh 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. #!/bin/bash
  2. ################################################################################
  3. #
  4. # Authors:
  5. #
  6. # [@cel](@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519)
  7. # [@Fred](@9BbJwPDjcyIqrOUPNn0nJZBduWdIrpMk3Cjz5MP361s=.ed25519)
  8. # [@Boris](@l5nYExWYIgDLV6BYHOJPoI97jIUyTdSm8CTLpQ0XeOg=.ed25519)
  9. # [@poka](@vDQif9KU3T78XJx+NliK+wdo1vmehHZCWqD+3X700Uk=.ed25519)
  10. # @[chamalow](@qio8/4L4vnzq3qRD0dqKI7sTpey54u8ZWbaICfpJOZw=.ed25519)
  11. #
  12. # Version: 1.0
  13. #
  14. # License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
  15. #
  16. ###########################################################################################
  17. # PREVENT DOUBLE PAYEMENT
  18. # ADD Ğ1 Layer 10 LOVE to message writer you like !
  19. ############################################################################################
  20. # Customizable
  21. # debugMsgMode, when set to 1 does doesn't send transaction and does not update "last timestamp"
  22. debugMsgMode=0
  23. # If you don't want to wait
  24. readable=1
  25. minimumAmountPerLikeInLOVE="10"
  26. ############################################################################################
  27. # Let's get Ğ1 public and private keys
  28. g1pub=$(cat ~/.ssb/secret.dunikey | grep "pub" | cut -d ' ' -f 2)
  29. g1priv=$(cat ~/.ssb/secret.dunikey | grep "sec" | cut -d ' ' -f 2)
  30. # SSB pubkey
  31. ssbpub=$(cat ~/.ssb/secret | grep public\" | cut -d ' ' -f 4 | cut -d '.' -f 1 | sed s/\"//g)
  32. defaultAmountPerLikeInUD="0.1"
  33. bold=$(tput bold)
  34. normal=$(tput sgr0)
  35. ssbMaxSize=8192
  36. baseSizeOfAMessageFile=$(wc -c samples/message.json | awk '{print $1}')
  37. sizeOfATagMention=$(wc -c samples/tag_mention.json | awk '{print $1}')
  38. sizeOfAUserMention=$(wc -c samples/user_mention.json | awk '{print $1}')
  39. sizeOfAPostMention=$(wc -c samples/post_mention.json | awk '{print $1}')
  40. ############################################################################################
  41. #### CHECK LIKE AND SEND LOVE
  42. # Let's get Ğ1 account balance
  43. echo ""
  44. echo -e "${bold}Welcome${normal} to the Ğ1/SSB-like microdonation system!\n"
  45. if [[ $readable -eq 1 ]]; then sleep 1; fi
  46. echo "MMMMMMMMMMMMMNk;'cdxxd:,c0WMMMMMMMMMMMMM
  47. MMMMMMMMMMMMMNx,. .;kWMMMMMMMMMMMMM
  48. MMMMMMMMMMMMMMMNOdlccld0NMMMMMMMMMMMMMMM
  49. MMMMMMMMMMMWXko:,'....',:okXWMMMMMMMMMMM
  50. MMMMMMMMMNk:. .cOWMMMMMMMMM
  51. MMMMMMMW0: .c0MMMMMMMM"
  52. if [[ $readable -eq 1 ]]; then sleep 1; fi
  53. echo "MMMMMMWk. 'lxkOOkdc' .cOWMMMMMMM
  54. MMMMMMO' 'kNMMMMMMMMNxcoOXWMMMMMMMMM
  55. MMMMMNl '0MMMMMMMMMMMMMMMMMMMMMMMMMM
  56. MMMMMX; cNMMMMMMMNOkkkkkkkkkkONMMMMM
  57. MMMMMNc ;XMMMMMMMNd' .OMMMMM
  58. MMMMMWx. cKMMMMMMMWKc. .OMMMMM
  59. MMMMMMNo. .lkKXNNXKkc. .OMMMMM"
  60. if [[ $readable -eq 1 ]]; then sleep 1; fi
  61. echo "MMMMMMMNd. ...... .OMMMMM
  62. MMMMMMMMWKl. 'c:. .OMMMMM
  63. MMMMMMMMMMWXkc,.. ..,lkXWWO:;OMMMMM
  64. MMMMMMMMMMMMMMWX0OxddxO0XWMMMMMMWXNMMMMM
  65. MMMMMMMMMMMMMMMMNx;'',dNMMMMMMMMMMMMMMMM
  66. MMMMMMMMMMMMMMMMK, '0MMMMMMMMMMMMMMMM
  67. MMMMMMMMMMMMMMMMNd. .oNMMMMMMMMMMMMMMMM
  68. "
  69. if [[ $readable -eq 1 ]]; then sleep 1; fi
  70. printf "You know your SSB pubkey:\n%s\n\n" $ssbpub
  71. if [[ $readable -eq 1 ]]; then sleep 2; fi
  72. printf "...but did you know it is also a valid Ğ1 wallet?\n%s\n\n" $g1pub
  73. if [[ $readable -eq 1 ]]; then sleep 2; fi
  74. printf "Let's check the current balance of your wallet!\n\n"
  75. if [[ $readable -eq 1 ]]; then sleep 1; fi
  76. printf "I am interrogating the Ğ1 blockchain to check if anyone has already sent you Ğ1...\n\n"
  77. if [[ $readable -eq 1 ]]; then sleep 2; fi
  78. printf "A moment please...\n\n"
  79. if [[ $readable -eq 1 ]]; then sleep 1; fi
  80. silkajRelativeAmountPattern='Total\sRelative\s+=\s+(.*)\s+UD'
  81. duniter_servers[0]="duniter-g1.p2p.legal:443"
  82. duniter_servers[1]="g1.duniter.org:443"
  83. duniter_servers[2]="g1.presles.fr:443"
  84. duniter_servers[3]="balboa.altsysnet.com:10900"
  85. duniter_servers[4]="remuniter.cgeek.fr:16120"
  86. duniter_servers[5]="duniter.moul.re:443"
  87. duniter_servers[6]="77.152.31.154:20901"
  88. duniter_servers[7]="duniter.g1.1000i100.fr:443"
  89. silkajExitCode=1
  90. i=0
  91. while [ $silkajExitCode -ne 0 ] && [ $i -lt ${#duniter_servers[@]} ]
  92. do
  93. echo "Testing server ${duniter_servers[$i]}..."
  94. echo ""
  95. silkajOutput=$(silkaj -p "${duniter_servers[$i]}" balance $g1pub 2>/dev/null)
  96. silkajExitCode=$?
  97. ((i++))
  98. done
  99. if [ $silkajExitCode -eq 1 ]
  100. then
  101. echo "The server did not respond well. Please try again."
  102. exit 1
  103. fi
  104. if [[ $silkajOutput =~ $silkajRelativeAmountPattern ]]
  105. then
  106. balance="${BASH_REMATCH[1]}"
  107. else
  108. echo "Account balance wasn't found."
  109. exit 1
  110. fi
  111. printf "You have ${bold}%s LOVE${normal} on your Duniter Ğ1 wallet.\n\n" "$((balance * 100))"
  112. if [[ $readable -eq 1 ]]; then sleep 2; fi
  113. printf "Want to show your appreciation of your fellow butts' posts while helping spreading awareness about libre currencies?\n\n"
  114. if [[ $readable -eq 1 ]]; then sleep 3; fi
  115. # BEGIN timestamp computation
  116. self=$(sbotc whoami | jq -r .id) || exit 1
  117. ssb_dir=~/.${ssb_appname:-ssb}
  118. id_part=$(echo "$self" | sed 's/\//_/g' | tail -c +2 | head -c 9)
  119. state_file=$ssb_dir/likes-g1-$id_part.ts
  120. current_ts=$(date -u +%s%N | cut -b1-13)
  121. if [ -s "$state_file" ]
  122. then
  123. last_ts=$(cat "$state_file") || exit 1
  124. else
  125. # timestamp from 24h ago
  126. last_ts=$((current_ts - 24*3600*1000 - 1))
  127. #else last_ts=null
  128. fi
  129. days_from_last_tx=$(( (current_ts - last_ts) / (24*60*60*1000) ))
  130. # END timestamp computation
  131. printf "First, let's see how much ❤ you gave lately...\n\n"
  132. if [[ $readable -eq 1 ]]; then sleep 1; fi
  133. declare -A likesNbPerAuthor
  134. declare -A likedPosts
  135. declare -A likesNbPerPost
  136. declare -A postsTimestamps
  137. declare -A excerpts
  138. totalLikesGiven=0
  139. process_msg() {
  140. msg=$1
  141. target_id=$(printf %s "$msg" | jq -r '.value?.content?.vote?.link') || return 1
  142. target_msg=$(sbotc -e get "$target_id") || return 1
  143. target_author=$(printf %s "$target_msg" | jq -r .author) || return 1
  144. msg_content=$(printf %s "$target_msg" | jq -r .content?.text) || return 1
  145. # beware of markdown !
  146. msg_excerpt=${msg_content:0:10}
  147. #root_id=$(printf %s "$target_msg" | jq -r .content?.root) || return 1
  148. #[[ $root_id = "null" ]] && root_id=$target_id
  149. }
  150. process_author() {
  151. author_id=$1
  152. g1_author=$(echo $author_id | cut -d '.' -f 1 | cut -d '@' -f2 | base64 -d | base58)
  153. author_name=$(sbotc query.read '{"query":[{"$filter":{"value":{"author": "'"$author_id"'", "content":{"type":"about", "about": "'"$author_id"'"}}}}]}' | jq .value?.content?.name | grep -v null | tail -n 1)
  154. author_name=${author_name:1:-1}
  155. }
  156. authorsNb=0
  157. i=0
  158. messages=$(sbotc query.read '{"query":[{"$filter":{"value":{"author":"'"$self"'","content":{"type":"vote", "vote":{"expression":"Like"}},"timestamp":{"$gt":'"$last_ts"'}}}}]}')
  159. while read -r msg
  160. do
  161. priv=$(printf %s "$msg" | jq .value.content.private)
  162. if [[ $priv = true ]]
  163. then
  164. printf "Private message $priv, continue to next one\n" >&2
  165. continue
  166. fi
  167. if ! process_msg "$msg"
  168. then
  169. msg_id=$(printf %s "$msg" | jq -r .key)
  170. printf '\nUnable to process message %s\n' "$msg_id" >&2
  171. exit 1
  172. fi
  173. if [[ $g1_author = $g1pub ]]; then
  174. echo "I LIKE MY MESSAGE $target_id"
  175. else
  176. ((totalLikesGiven++))
  177. if [[ ${likesNbPerAuthor[$target_author]} -eq 0 ]]
  178. then
  179. likesNbPerAuthor[$target_author]=1
  180. likedPosts[$target_author]=""
  181. else
  182. likesNbPerAuthor[$target_author]=$((${likesNbPerAuthor[$target_author]} + 1))
  183. fi
  184. if [[ ${likesNbPerPost[$target_id]} -eq 0 ]]
  185. then
  186. likesNbPerPost[$target_id]=1
  187. likedPosts[$target_author]+=$target_id
  188. likedPosts[$target_author]+="\n"
  189. else
  190. ((likesNbPerPost[$target_id]++))
  191. fi
  192. excerpts[$target_id]=$msg_excerpt
  193. # We cannot use this anymore
  194. # (now saving current_ts once all tx have been sent)
  195. #
  196. # if ! postsTimestamps[$target_id]=$(printf %s "$msg" | jq -r .value.timestamp)
  197. #then
  198. # printf 'Unable to get message timestamp\n' >&2
  199. # exit 1
  200. #fi
  201. ((i++))
  202. fi
  203. done < <(printf '%s\n' "$messages")
  204. if [[ $totalLikesGiven -eq 0 ]]
  205. then
  206. printf "You did not give any like during the past %s days or they have already been processed.\n\n" "$days_from_last_tx"
  207. printf "Try again in a few days.\n\n"
  208. fi
  209. printf "You gave ${bold}%s❤${normal} during the past %s days.\n\n" "$totalLikesGiven" "$days_from_last_tx"
  210. if [[ $readable -eq 1 ]]; then sleep 2; fi
  211. tx_are_possible=0
  212. while [[ $tx_are_possible -eq 0 ]]
  213. do
  214. printf "How many LOVE do you want to send per each like you gave? (minimum is ${bold}%s LOVE${normal}) " "$((minimumAmountPerLikeInLOVE))"
  215. read a
  216. printf "\n"
  217. if [[ -z $a ]]
  218. then
  219. amountPerLikeInUD=$(bc -l <<< "scale=2; $minimumAmountPerLikeInLOVE / 100")
  220. else
  221. amountPerLikeInUD=$(bc -l <<< "scale=2; $a / 100")
  222. fi
  223. amountGiven=$(echo "$totalLikesGiven * $amountPerLikeInUD" | bc -l)
  224. has_enough_money=$(( $(echo "$amountGiven <= $balance" | bc -l) ))
  225. amountPerLike_is_enough=$(( $(echo "$amountPerLikeInUD >= $minimumAmountPerLikeInLOVE" | bc -l) ))
  226. tx_are_possible=$(( $has_enough_money && $amountPerLike_is_enough ))
  227. if [[ $readable -eq 1 ]]; then sleep 1; fi
  228. if [[ $tx_are_possible -eq 0 ]] ; then
  229. if [[ $has_enough_money -eq 0 ]] ; then
  230. printf "You don't have enough LOVE to send all transactions.\n\n"
  231. if [[ $readable -eq 1 ]]; then sleep 1; fi
  232. printf "${bold}%s LOVE${normal} are needed.\n\n" "$((amountGiven * 100))"
  233. if [[ $readable -eq 1 ]]; then sleep 1; fi
  234. elif [[ $amountPerLike_is_enough -eq 0 ]] ; then
  235. printf "Minimum amount per like is %s LOVE.\n\n" $minimumAmountPerLikeInLOVE
  236. if [[ $readable -eq 1 ]]; then sleep 1; fi
  237. fi
  238. printf "Try again with a different amount per like.\n\n"
  239. maxAmountPerLike=$(awk -vp=$balance -vq=$totalLikesGiven 'BEGIN{printf "%.2f" ,p / q}')
  240. if [[ $readable -eq 1 ]]; then sleep 1; fi
  241. printf "Maximum amount per like possible: ${bold}%s LOVE${normal}\n\n" "$((maxAmountPerLike * 100))"
  242. if [[ $readable -eq 1 ]]; then sleep 1; fi
  243. else
  244. newBalance=$(echo "$balance - $amountGiven" | bc -l)
  245. printf "${bold}%s LOVE${normal} will be given.\n\n" "$((amountGiven * 100))"
  246. if [[ $readable -eq 1 ]]; then sleep 1; fi
  247. printf "After sending transactions, your new balance will be ${bold}%s LOVE${normal}\n\n" "$((newBalance * 100))"
  248. if [[ $readable -eq 1 ]]; then sleep 1; fi
  249. printf "Press ENTER to continue: " && read
  250. printf "\n"
  251. fi
  252. done
  253. # Let's construct thank you posts (tyPosts) and send transactions!
  254. tyPostIndex=0
  255. tyPosts[0]=""
  256. tyPosts[0]+="# I tipped you for your posts!\n\n"
  257. tyPosts[0]+=$(printf "Huge thanks to the ScuttleButt community for all the fascinating posts you allowed me to read in the past %s days." "$days_from_last_tx")
  258. tyPosts[0]+="\n\nAs a means to thank you further, I have just sent you #Ğ1 libre money.\n\n"
  259. tyPosts[0]+="These messages, though they might feel spammy (sorry) are also a way for the Ğ1 community to spread awareness about [libre currencies](https://libre-currency.org/) so we can build #resilience at every level.\n\n"
  260. tyPosts[0]+="You can learn how to spend your freshly earned money at [https://git.p2p.legal/Axiom-Team/ssb-g1-tip](https://git.p2p.legal/Axiom-Team/ssb-g1-tip)\n\n"
  261. tyPosts[0]+="Below is the list of SSB users whose content I liked recently, and the amount each one was given:\n\n"
  262. tableHeaders='| thanks to | for their posts | tip |\n'
  263. tableHeaders+='| --- | --- | ---- |\n'
  264. sizeOfTableHeaders=$(printf "%s" "$tableHeaders" | wc -c)
  265. tyPosts[0]+=$tableHeaders
  266. # for message size calculation
  267. # update following if you add tags in the message :
  268. tags[0]="Ğ1"
  269. tags[1]="resilience"
  270. sizeOfTags=0
  271. for t in ${!tags[@]}
  272. do
  273. tagSize=$(printf "%s" "${tags[t]}" | wc -c)
  274. (( sizeOfTags+=sizeOfATagMention + tagSize ))
  275. done
  276. firstPostContentSize=$(printf "%s" "${tyPosts[0]}" | wc -c)
  277. tyPostsSizes[0]=$((baseSizeOfAMessageFile + firstPostContentSize + sizeOfTags))
  278. nbOfAuthors=${#likesNbPerAuthor[@]}
  279. authorNum=1
  280. for author_id in ${!likesNbPerAuthor[@]}
  281. do
  282. process_author $author_id
  283. # (Legacy) saving authors we have already mentionned in a message
  284. likedAuthorsFile=$ssb_dir/db/g1likes
  285. if [ ! -f $likedAuthorsFile ]; then
  286. touch $likedAuthorsFile
  287. fi
  288. if ! grep -Fxq $author_id $likedAuthorsFile; then
  289. echo $author_id >> $likedAuthorsFile
  290. fi
  291. tipAmount=$(bc <<< "${likesNbPerAuthor[$author_id]} * $amountPerLikeInUD")
  292. newLine=''
  293. newLine+=$(printf "| [@%s](%s) " "$author_name" "$author_id")
  294. newLine+="| "
  295. sizeOfAuthorName=$(printf "%s" "$author_name" | wc -c)
  296. sizeOfAuthorId=$(printf "%s" "$author_id" | wc -c)
  297. newLineSize=0
  298. (( newLineSize+=sizeOfAUserMention + sizeOfAuthorName + sizeOfAuthorId))
  299. p=${likedPosts[$author_id]}
  300. thisAuthorLikedPosts=( ${p//\\n/ } )
  301. isFirstPostOfThisAuthor=1
  302. for likedPostId in ${thisAuthorLikedPosts[@]}
  303. do
  304. if [[ $isFirstPostOfThisAuthor -eq 1 ]]
  305. then
  306. isFirstPostOfThisAuthor=0
  307. else
  308. newLine+=", "
  309. (( newLineSize+=2 ))
  310. fi
  311. newLine+=$(printf " %s❤" "${likesNbPerPost[$likedPostId]}")
  312. newLine+=$(printf "[\`%s\`](%s)" "${excerpts[$likedPostId]}" "$likedPostId")
  313. sizeOfExcerpt=${#excerpts[$likedPostId]}
  314. (( sizeOfExcerpt+=2 )) # for before ` and after `
  315. sizeOfLikedPostId=$(printf "%s" "$likedPostId" | wc -c)
  316. (( newLineSize+=sizeOfAPostMention + sizeOfExcerpt + sizeOfLikedPostId ))
  317. done
  318. newLine+=$(printf "| %s LOVE " "$((tipAmount * 100))")
  319. newLine+="|\n"
  320. (( newLineSize+=$(printf "%s" "$newLine" | wc -c) ))
  321. # printf "total size: %s\n\n" "$((${tyPostsSizes[$tyPostIndex]} + $newLineSize))"
  322. # If adding new line would exceed max size, we create a new thank you post
  323. sizeWithNewLine=${tyPostsSizes[$tyPostIndex]}
  324. (( sizeWithNewLine+=newLineSize ))
  325. if [[ $sizeWithNewLine -gt $ssbMaxSize ]]
  326. then
  327. printf "size before split: %s\n\n" "${tyPostsSizes[$tyPostIndex]}"
  328. printf "size with new line: %s\n\n" "$sizeWithNewLine"
  329. printf "size of new line: %s\n\n" "$newLineSize"
  330. (( tyPostIndex++ ))
  331. tyPosts[$tyPostIndex]+=$tableHeaders
  332. (( tyPostsSizes[$tyPostIndex]=baseSizeOfAMessageFile + sizeOfTableHeaders ))
  333. fi
  334. tyPosts[$tyPostIndex]+=$newLine
  335. (( tyPostsSizes[$tyPostIndex]+=newLineSize ))
  336. if [[ $debugMsgMode -eq 0 ]]
  337. then
  338. if [[ $authorNum -ne 1 ]]
  339. then
  340. sleep 20 # DO NOT OVER CHARGE DUNITER
  341. fi
  342. #printf '%s\n' "silkaj -af --file ~/.ssb/secret.dunikey tx --output $g1_author --amountUD $tipAmount --comment "Thx for your cool posts on ScuttleButt"
  343. silkaj -p "$duniter_server" -af --file ~/.ssb/secret.dunikey tx --output $g1_author --amountUD $tipAmount --comment "Thx for your cool posts on ScuttleButt" -y 2>/dev/null
  344. printf "\n${bold}%s LOVE${normal} sent to %s!\n\n" "$((tipAmount * 100))" "$author_name"
  345. fi
  346. (( authorNum++ ))
  347. done
  348. # Let's save the current timestamp
  349. if [[ $debugMsgMode -eq 0 ]]
  350. then
  351. if ! echo "$current_ts" > "$state_file"~
  352. then
  353. printf 'Unable to write to backup state file.\n' >&2
  354. exit 1
  355. fi
  356. if ! mv "$state_file"~ "$state_file"
  357. then
  358. printf 'Unable to write to state file. Update state file manually to prevent tips to %s from being processed twice.\n' "$author_name" >&2
  359. exit 1
  360. fi
  361. fi
  362. printf "\n%s LOVE sent to %s butts!\n\n" "$((amountGiven * 100))" "${#likesNbPerAuthor[@]}"
  363. # Let's publicly thank everyone!
  364. #echo -e "${tyPosts[$n]}"
  365. # the following produces error:
  366. # "sbotc: unexpected end of parent stream"
  367. # must be a non-escaped quote problem...
  368. #thank_you_msg=$(printf "%q" "${tyPosts[$n]}")
  369. #sbotc publish '{"type":"post","text":"'"$thank_you_msg"'"}' 2>&1>/dev/null
  370. printf "What now ?\n\n"
  371. if [[ $readable -eq 1 ]]; then sleep 1; fi
  372. date=$(date -u +%Y-week-%W)
  373. if [[ ${#tyPosts[@]} -eq 1 ]]
  374. then
  375. msg_filename=thank-your-butts-$date
  376. echo -e ${tyPosts[$n]} > ~/$msg_filename.md
  377. else
  378. for i in ${!tyPosts[@]}
  379. do
  380. part=$((i + 1))
  381. msg_filename=thank-your-butts-$date
  382. echo -e ${tyPosts[$i]} > ~/$msg_filename-part-$part.md
  383. done
  384. fi
  385. printf "A surprise is awaiting in your home dir (~).\n\n"
  386. if [[ $readable -eq 1 ]]; then sleep 2; fi
  387. if [[ ${#tyPosts[@]} -eq 1 ]]
  388. then
  389. printf "It's a file.\n\n"
  390. if [[ $readable -eq 1 ]]; then sleep 2; fi
  391. printf "It's called $msg_filename.md\n\n"
  392. # Open file with xed
  393. [[ $(which xed) ]] && xed ~/$msg_filename.md &
  394. else
  395. printf "It's %s files.\n\n" "${#tyPosts[@]}"
  396. if [[ $readable -eq 1 ]]; then sleep 2; fi
  397. printf "The first one is called $msg_filename-part-1.md.\n\n"
  398. fi
  399. if [[ $readable -eq 1 ]]; then sleep 2; fi
  400. printf "Customize it to your needs to thank your fellow butts publicly and help spread awareness about libre currencies :-)\n\n"
  401. if [[ $readable -eq 1 ]]; then sleep 3; fi
  402. printf "Then delete it.\n\n"
  403. if [[ $readable -eq 1 ]]; then sleep 2; fi
  404. printf "...because it won't self-destruct, haha :D \n\n"