Compare commits

...

41 Commits

Author SHA1 Message Date
qo-op 09b4bc65e2 Merge branch 'dev-joss' of josselinchevalay/ssb-g1like into master
je ne sais pas fusionner... @poka...
2020-05-10 20:33:32 +02:00
qo-op 2206ed5378 Send LOVE now (1 DUG1 = 100 LOVE) 2020-04-29 22:34:05 +02:00
qo-op 04c6b7d2c4 Open file with xed 2020-04-29 22:19:35 +02:00
qo-op 3519cb29e9 grep -rl UDĞ1 ./ | xargs sed -i s/UDĞ1/LOVE/g 2020-04-29 22:12:17 +02:00
joseelinchevalay de9d0e5a91 fix quelque issue avec les script et le dependance entre les containers 2020-04-06 09:11:20 +02:00
joseelinchevalay 845b0b5332 add documentation to install docker docker-compose 2020-04-01 15:16:29 +02:00
joseelinchevalay 8a4c2fbee2 mise à jour de la documentation 2020-04-01 14:53:00 +02:00
joseelinchevalay 631c5e8caf création paramétrer le ssb-path 2020-04-01 09:18:31 +02:00
joseelinchevalay 757a90df9a ressoud l'issue daemonize tip container 2020-04-01 09:09:48 +02:00
joseelinchevalay 4f428b5dc3 fixe le bug dans secret2dunikey and daemonize tip container 2020-03-31 11:46:27 +02:00
joseelinchevalay 879bf6ef11 solved issue with tip.sh and add bc package 2020-03-27 16:59:29 +01:00
joseelinchevalay 0227ec48cf change some information into docker-compose 2020-03-27 08:52:02 +01:00
joseelinchevalay 51fe6cc391 add ipfs node 2020-03-27 08:42:32 +01:00
joseelinchevalay 0f530efb3c query issue solved 2020-03-26 17:20:25 +01:00
joseelinchevalay c513455d9a solve issue with sbotc tcp_connect 2020-03-26 10:11:56 +01:00
joseelinchevalay e71d12de6f fix issue ssb-server port settings 2020-03-25 11:15:29 +01:00
joseelinchevalay fdb88fe137 essaye de connecter ssb-server et sbotc de tip container 2020-03-24 17:31:56 +01:00
joseelinchevalay a395a7d378 supression du repertoire docker pas utile 2020-03-24 11:07:24 +01:00
joseelinchevalay 1ebbb25515 fix le bug des sample non trouvés et mis à jour de la documentation 2020-03-24 11:05:11 +01:00
joseelinchevalay 0d677fded6 update script 2020-03-24 08:07:14 +01:00
joseelinchevalay 67e3f28e51 create dockerfile for tip container 2020-03-24 08:06:17 +01:00
joseelinchevalay 82c5a11a57 update documentation 2020-03-23 17:23:08 +01:00
joseelinchevalay 10b85b1dbe création d'une image pour secret2dunikey 2020-03-23 17:21:54 +01:00
joseelinchevalay 7592f0fd1d changement d'approche avec docker-compose multiple petit container 2020-03-23 13:51:32 +01:00
joseelinchevalay aefe3fa53f add some script and samples 2020-03-23 09:37:31 +01:00
joseelinchevalay da40eb80ad merge master 2020-03-23 08:55:30 +01:00
joseelinchevalay faef88183b change entrypoint 2020-03-23 08:52:28 +01:00
joseelinchevalay 4d1071d3a7 install nodejs rust dup-mnemonic 2020-03-19 15:25:21 +01:00
joseelinchevalay 62772d225c Merge branch 'dev-joss' of https://git.p2p.legal/josselinchevalay/ssb-g1like into dev-joss 2020-03-19 09:02:03 +01:00
joseelinchevalay c39715a743 try to add nvm 2020-03-19 08:58:41 +01:00
joseelinchevalay 022e8ed558 add autoconf and libtool package 2020-03-19 08:58:41 +01:00
joseelinchevalay 79173ac78e updaate python3-wheel 2020-03-19 08:58:41 +01:00
joseelinchevalay e4a34db411 add base58 and build-essential package 2020-03-19 08:58:41 +01:00
joseelinchevalay 671916418b change documentation 2020-03-19 08:58:41 +01:00
joseelinchevalay 7ef3a65ab5 add dockerfile 2020-03-19 08:58:41 +01:00
joseelinchevalay bbb006e452 try to add nvm 2020-03-19 08:54:30 +01:00
joseelinchevalay bf909804a5 add autoconf and libtool package 2020-03-18 17:48:48 +01:00
joseelinchevalay 61a94c4d9d updaate python3-wheel 2020-03-18 14:14:53 +01:00
joseelinchevalay b8b5ac3d2b add base58 and build-essential package 2020-03-17 17:45:27 +01:00
joseelinchevalay 367c37c8b1 change documentation 2020-03-16 16:40:23 +01:00
joseelinchevalay 2e826c1981 add dockerfile 2020-03-16 16:17:01 +01:00
10 changed files with 897 additions and 16 deletions

66
Dockerfile Normal file
View File

@ -0,0 +1,66 @@
FROM debian@sha256:bf338ddc710dfb9b907a29ba661b35d0f6b3eae043515c4315f64c6e93409e94
LABEL MAINTAINER=chamalow <@qio8/4L4vnzq3qRD0dqKI7sTpey54u8ZWbaICfpJOZw=.ed25519>
ENV DEBIAN_FRONTEND noninteractive
ENV RUSTUP_HOME /usr/local/rustup
ENV CARGO_HOME /usr/local/cargo
ENV PATH /usr/local/cargo/bin:$PATH
ENV RUST_VERSION 1.42.0
COPY ./key_create_dunikey.py /usr/bin/key_create_dunikey
COPY ./find_ssb_user_G1_pubkey.sh /usr/bin/find_ssb_user_G1_pubkey
COPY ./tip.sh /usr/bin/tip
RUN apt-get update -y && \
apt-get install autoconf=2.69-11.1 build-essential=12.8 python3-pip=18.1-5 python3-setuptools=44.0.0-1 python3-wheel=0.33.6-3 libsodium-dev=1.0.18-1 jq=1.6-1 make=4.2.1-1.2 git=1:2.25.1-1 gcc=4:9.2.1-3.1 base58=1.0.3-1 libtool=2.4.6-14 curl=7.68.0-1 -y && \
chmod +x /usr/bin/secret2dunikey /usr/bin/key_create_dunikey /usr/bin/find_ssb_user_G1_pubkey /usr/bin/tip && \
pip3 install duniterpy==0.56.0 silkaj==0.7.6 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
useradd -ms /bin/bash astroport
RUN set -eux; \
dpkgArch="$(dpkg --print-architecture)"; \
case "${dpkgArch##*-}" in \
amd64) rustArch='x86_64-unknown-linux-gnu'; rustupSha256='ad1f8b5199b3b9e231472ed7aa08d2e5d1d539198a15c5b1e53c746aad81d27b' ;; \
armhf) rustArch='armv7-unknown-linux-gnueabihf'; rustupSha256='6c6c3789dabf12171c7f500e06d21d8004b5318a5083df8b0b02c0e5ef1d017b' ;; \
arm64) rustArch='aarch64-unknown-linux-gnu'; rustupSha256='26942c80234bac34b3c1352abbd9187d3e23b43dae3cf56a9f9c1ea8ee53076d' ;; \
i386) rustArch='i686-unknown-linux-gnu'; rustupSha256='27ae12bc294a34e566579deba3e066245d09b8871dc021ef45fc715dced05297' ;; \
*) echo >&2 "unsupported architecture: ${dpkgArch}"; exit 1 ;; \
esac; \
url="https://static.rust-lang.org/rustup/archive/1.21.1/${rustArch}/rustup-init"; \
curl -O "$url"; \
echo "${rustupSha256} *rustup-init" | sha256sum -c -; \
chmod +x rustup-init; \
./rustup-init -y --no-modify-path --profile minimal --default-toolchain $RUST_VERSION; \
rm rustup-init; \
chmod -R a+w $RUSTUP_HOME $CARGO_HOME; \
rustup --version; \
cargo --version; \
rustc --version;
RUN git clone https://git.scuttlebot.io/%25133ulDgs%2FoC1DXjoK04vDFy6DgVBB%2FZok15YJmuhD5Q%3D.sha256 sbotc
WORKDIR /sbotc
RUN make && make install
WORKDIR /
RUN git clone https://git.duniter.org/tools/dup-mnemonic-rs
WORKDIR /dup-mnemonic-rs
RUN cargo build --release && \
cp target/release/dup-mnemonic /usr/local/bin
COPY ./docker/docker-entrypoint.sh /home/astroport/
COPY ./samples /home/astroport/
RUN chmod +x /home/astroport/docker-entrypoint.sh
USER astroport
WORKDIR /home/astroport
VOLUME [ "/home/astroport/.ssb/" ]
EXPOSE 8008
ENTRYPOINT [ "/bin/bash" ]
CMD ["docker-entrypoint.sh"]

86
docker-compose.yml Normal file
View File

@ -0,0 +1,86 @@
version: "3"
services:
redis:
image: redis
mongo:
image: mongo
volumes:
- mongo-data:/data
ohmyform:
image: ohmyform/ohmyform
#build: .
#volumes:
# - ".:/opt/app"
environment:
CREATE_ADMIN: "TRUE"
SOCKET_URL: 'localhost:5000'
SOCKET_PORT: "5000"
SOCKET_PORT_EXTERN_VISIBLE: "TRUE"
MONGODB_URI: mongodb://mongo/ohmyform
REDIS_URL: redis://redis
MAILER_SMTP_HOST: mail
MAILER_SMTP_PORT: 1025
# command: grunt dev # override command to have livereloading on file change
links:
- mongo
- redis
- mail
ports:
- "5000:5000"
depends_on:
- mongo
- redis
mail:
image: mailhog/mailhog
ports:
- "5050:8025"
mongoexpress:
image: mongo-express
environment:
ME_CONFIG_MONGODB_SERVER: mongo
ports:
- "5051:8081"
links:
- mongo
depends_on:
- mongo
secret2dunikey:
build:
context: .
dockerfile: ./secret2dunikey/Dockerfile
volumes:
- ${SSB_PATH}:/home/astroport/.ssb
oasis:
build:
context: .
dockerfile: ./oasis/Dockerfile
tty: true
ports:
- 3000:3000
volumes:
- ${SSB_PATH}:/home/astroport/.ssb
depends_on:
- secret2dunikey
tip:
build:
context: .
dockerfile: ./tip/Dockerfile
tty: true
volumes:
- ${SSB_PATH}:/home/astroport/.ssb
links:
- oasis
depends_on:
- oasis
- secret2dunikey
ipfs:
image: ipfs/go-ipfs
volumes:
- ipfs-data:/data/ipfs
ports:
- 8080:8080
- 4001:4001
- 5001:5001
volumes:
ipfs-data:
mongo-data:

37
oasis/Dockerfile Normal file
View File

@ -0,0 +1,37 @@
FROM debian@sha256:bf338ddc710dfb9b907a29ba661b35d0f6b3eae043515c4315f64c6e93409e94
LABEL MAINTAINER=chamalow <@qio8/4L4vnzq3qRD0dqKI7sTpey54u8ZWbaICfpJOZw=.ed25519>
ENV DEBIAN_FRONTEND noninteractive
ENV NVM_INSTALL_DIR /opt/nvm
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION v12.16.1
RUN apt-get update -y && \
apt-get install autoconf=2.69-11.1 build-essential=12.8 python3-pip=20.0.2-2 python3-setuptools=44.0.0-1 libsodium-dev=1.0.18-1 jq=1.6-1 make=4.2.1-1.2 git=1:2.25.1-1 gcc=4:9.2.1-3.1 base58=1.0.3-1 libtool=2.4.6-14 curl=7.68.0-1 git=1:2.25.1-1 bc=1.07.1-2+b2 -y && \
pip3 install duniterpy==0.56.0 silkaj==0.7.6 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
useradd -ms /bin/bash astroport
RUN git clone https://github.com/creationix/nvm.git $NVM_INSTALL_DIR && \
. $NVM_INSTALL_DIR/nvm.sh && \
nvm install --lts && \
nvm alias default $NODE_VERSION && \
nvm use default && \
echo "export NVM_DIR=${NVM_DIR}" > /home/astroport/.bashrc && \
echo ". ${NVM_INSTALL_DIR}/nvm.sh" > /home/astroport/.bashrc && \
chown -R astroport:astroport $NVM_DIR
USER astroport
RUN . ~/.bashrc && \
mkdir -p /home/astroport/.ssb/ && \
npm install -g sodium-native@3.0.0 ssb-backlinks@1.0.0 && \
npm install -g fraction/oasis#semver:
VOLUME [ "/home/astroport/.ssb"]
EXPOSE 3000
EXPOSE 8008
ENTRYPOINT ["/bin/bash"]
CMD ["-c", ". ~/.bashrc && oasis --host 0.0.0.0 --open false && tail -f /dev/null"]

View File

@ -90,6 +90,43 @@ The Relative Theory of Money was written in 2010 by French mathematician Stephan
The main clients for Duniter are [Cesium](https://cesium.app/) and [Silkaj](https://mystifying-nobel-66ae54.netlify.com/) The main clients for Duniter are [Cesium](https://cesium.app/) and [Silkaj](https://mystifying-nobel-66ae54.netlify.com/)
## With docker (experimental)
### install docker & docker-compose
[Docker](https://docs.docker.com/install/)
[Docker-compose](https://docs.docker.com/compose/install/)
### variables
SSB_PATH : this is important variable to locate your ssb db path and secret file don't forget to set that.
First you need to build docker image.
```
SSB_PATH=~/.ssb/ docker-compose build
```
create your dunikey
```
SSB_PATH=~/your-copy-ssb/ docker-compose up -d tip # only you need to run tiping part
SSB_PATH=~/your-copy-ssb/ docker-compose up -d # if you need to run all platform
```
run main tip script
```
container_id=$(docker ps -a -q --filter="ancestor=ssb-g1like_tip") && docker exec -ti $container_id bash -c "/home/astroport/tip"
```
For display thank you file
```
container_id=$(docker ps -a -q --filter="ancestor=ssb-g1like_tip") && docker cp $container_id:/home/astroport/thank-your-butts-$(date -u +%Y-week-%W).md ~ && docker exec -ti $container_id bash -c "rm -rf /home/astroport/thank-your-butts-$(date -u +%Y-week-%W).md"
```
## Authors ## Authors
- **cel** (`@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519`) - **cel** (`@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519`)
@ -97,3 +134,4 @@ The main clients for Duniter are [Cesium](https://cesium.app/) and [Silkaj](http
- **Boris** (`@l5nYExWYIgDLV6BYHOJPoI97jIUyTdSm8CTLpQ0XeOg=.ed25519`) - **Boris** (`@l5nYExWYIgDLV6BYHOJPoI97jIUyTdSm8CTLpQ0XeOg=.ed25519`)
- **poka** (`@vDQif9KU3T78XJx+NliK+wdo1vmehHZCWqD+3X700Uk=.ed25519`) - **poka** (`@vDQif9KU3T78XJx+NliK+wdo1vmehHZCWqD+3X700Uk=.ed25519`)
- **chamalow** (`@qio8/4L4vnzq3qRD0dqKI7sTpey54u8ZWbaICfpJOZw=.ed25519`) - **chamalow** (`@qio8/4L4vnzq3qRD0dqKI7sTpey54u8ZWbaICfpJOZw=.ed25519`)

18
secret2dunikey/Dockerfile Normal file
View File

@ -0,0 +1,18 @@
FROM debian@sha256:bf338ddc710dfb9b907a29ba661b35d0f6b3eae043515c4315f64c6e93409e94
LABEL MAINTAINER=chamalow <@qio8/4L4vnzq3qRD0dqKI7sTpey54u8ZWbaICfpJOZw=.ed25519>
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update -y && \
apt-get install base58=1.0.3-1 python3-pip=20.0.2-2 python3-setuptools=44.0.0-1 -y && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
useradd -ms /bin/bash astroport
USER astroport
WORKDIR /home/astroport/
COPY ./secret2dunikey.sh /home/astroport/secret2dunikey.sh
ENTRYPOINT ["/bin/bash"]
CMD [ "secret2dunikey.sh"]

35
tip.sh
View File

@ -26,7 +26,7 @@ debugMsgMode=0
# If you don't want to wait # If you don't want to wait
readable=1 readable=1
minimumAmountPerLikeInUD="0.1" minimumAmountPerLikeInLOVE="10"
############################################################################################ ############################################################################################
@ -129,7 +129,7 @@ else
exit 1 exit 1
fi fi
printf "You have ${bold}%s UDĞ1${normal} on your Duniter Ğ1 wallet.\n\n" "$balance" printf "You have ${bold}%s LOVE${normal} on your Duniter Ğ1 wallet.\n\n" "$((balance * 100))"
if [[ $readable -eq 1 ]]; then sleep 2; fi if [[ $readable -eq 1 ]]; then sleep 2; fi
printf "Want to show your appreciation of your fellow butts' posts while helping spreading awareness about libre currencies?\n\n" printf "Want to show your appreciation of your fellow butts' posts while helping spreading awareness about libre currencies?\n\n"
if [[ $readable -eq 1 ]]; then sleep 3; fi if [[ $readable -eq 1 ]]; then sleep 3; fi
@ -274,22 +274,22 @@ tx_are_possible=0
while [[ $tx_are_possible -eq 0 ]] while [[ $tx_are_possible -eq 0 ]]
do do
printf "How many UDĞ1 do you want to send per each like you gave? (minimum is ${bold}%s UDĞ1${normal}) " "$minimumAmountPerLikeInUD" printf "How many LOVE do you want to send per each like you gave? (minimum is ${bold}%s LOVE${normal}) " "$((minimumAmountPerLikeInLOVE))"
read a read a
printf "\n" printf "\n"
if [[ -z $a ]] if [[ -z $a ]]
then then
amountPerLikeInUD=$minimumAmountPerLikeInUD amountPerLikeInUD=$(bc -l <<< "scale=2; $minimumAmountPerLikeInLOVE / 100")
else else
amountPerLikeInUD=$a amountPerLikeInUD=$(bc -l <<< "scale=2; $a / 100")
fi fi
amountGiven=$(echo "$totalLikesGiven * $amountPerLikeInUD" | bc -l) amountGiven=$(echo "$totalLikesGiven * $amountPerLikeInUD" | bc -l)
has_enough_money=$(( $(echo "$amountGiven <= $balance" | bc -l) )) has_enough_money=$(( $(echo "$amountGiven <= $balance" | bc -l) ))
amountPerLike_is_enough=$(( $(echo "$amountPerLikeInUD >= $minimumAmountPerLikeInUD" | bc -l) )) amountPerLike_is_enough=$(( $(echo "$amountPerLikeInUD >= $minimumAmountPerLikeInLOVE" | bc -l) ))
tx_are_possible=$(( $has_enough_money && $amountPerLike_is_enough )) tx_are_possible=$(( $has_enough_money && $amountPerLike_is_enough ))
if [[ $readable -eq 1 ]]; then sleep 1; fi if [[ $readable -eq 1 ]]; then sleep 1; fi
@ -298,13 +298,13 @@ do
if [[ $has_enough_money -eq 0 ]] ; then if [[ $has_enough_money -eq 0 ]] ; then
printf "You don't have enough UDĞ1 to send all transactions.\n\n" printf "You don't have enough LOVE to send all transactions.\n\n"
if [[ $readable -eq 1 ]]; then sleep 1; fi if [[ $readable -eq 1 ]]; then sleep 1; fi
printf "${bold}%s UDĞ1${normal} are needed.\n\n" "$amountGiven" printf "${bold}%s LOVE${normal} are needed.\n\n" "$((amountGiven * 100))"
if [[ $readable -eq 1 ]]; then sleep 1; fi if [[ $readable -eq 1 ]]; then sleep 1; fi
elif [[ $amountPerLike_is_enough -eq 0 ]] ; then elif [[ $amountPerLike_is_enough -eq 0 ]] ; then
printf "Minimum amount per like is %s UDĞ1.\n\n" $minimumAmountPerLikeInUD printf "Minimum amount per like is %s LOVE.\n\n" $minimumAmountPerLikeInLOVE
if [[ $readable -eq 1 ]]; then sleep 1; fi if [[ $readable -eq 1 ]]; then sleep 1; fi
fi fi
@ -312,13 +312,13 @@ do
printf "Try again with a different amount per like.\n\n" printf "Try again with a different amount per like.\n\n"
maxAmountPerLike=$(awk -vp=$balance -vq=$totalLikesGiven 'BEGIN{printf "%.2f" ,p / q}') maxAmountPerLike=$(awk -vp=$balance -vq=$totalLikesGiven 'BEGIN{printf "%.2f" ,p / q}')
if [[ $readable -eq 1 ]]; then sleep 1; fi if [[ $readable -eq 1 ]]; then sleep 1; fi
printf "Maximum amount per like possible: ${bold}%s UDĞ1${normal}\n\n" "$maxAmountPerLike" printf "Maximum amount per like possible: ${bold}%s LOVE${normal}\n\n" "$((maxAmountPerLike * 100))"
if [[ $readable -eq 1 ]]; then sleep 1; fi if [[ $readable -eq 1 ]]; then sleep 1; fi
else else
newBalance=$(echo "$balance - $amountGiven" | bc -l) newBalance=$(echo "$balance - $amountGiven" | bc -l)
printf "${bold}%s UDĞ1${normal} will be given.\n\n" "$amountGiven" printf "${bold}%s LOVE${normal} will be given.\n\n" "$((amountGiven * 100))"
if [[ $readable -eq 1 ]]; then sleep 1; fi if [[ $readable -eq 1 ]]; then sleep 1; fi
printf "After sending transactions, your new balance will be ${bold}%s UDĞ1${normal}\n\n" "$newBalance" printf "After sending transactions, your new balance will be ${bold}%s LOVE${normal}\n\n" "$((newBalance * 100))"
if [[ $readable -eq 1 ]]; then sleep 1; fi if [[ $readable -eq 1 ]]; then sleep 1; fi
printf "Press ENTER to continue: " && read printf "Press ENTER to continue: " && read
printf "\n" printf "\n"
@ -410,7 +410,7 @@ do
done done
newLine+=$(printf "| %s UDĞ1 " "$tipAmount") newLine+=$(printf "| %s LOVE " "$((tipAmount * 100))")
newLine+="|\n" newLine+="|\n"
@ -451,7 +451,7 @@ do
#printf '%s\n' "silkaj -af --file ~/.ssb/secret.dunikey tx --output $g1_author --amountUD $tipAmount --comment "Thx for your cool posts on ScuttleButt" #printf '%s\n' "silkaj -af --file ~/.ssb/secret.dunikey tx --output $g1_author --amountUD $tipAmount --comment "Thx for your cool posts on ScuttleButt"
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 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
printf "\n${bold}%s UDĞ1${normal} sent to %s!\n\n" "$tipAmount" "$author_name" printf "\n${bold}%s LOVE${normal} sent to %s!\n\n" "$((tipAmount * 100))" "$author_name"
fi fi
(( authorNum++ )) (( authorNum++ ))
@ -473,7 +473,7 @@ then
fi fi
fi fi
printf "\n%s UDĞ1 sent to %s butts!\n\n" "$amountGiven" "${#likesNbPerAuthor[@]}" printf "\n%s LOVE sent to %s butts!\n\n" "$((amountGiven * 100))" "${#likesNbPerAuthor[@]}"
# Let's publicly thank everyone! # Let's publicly thank everyone!
#echo -e "${tyPosts[$n]}" #echo -e "${tyPosts[$n]}"
@ -512,6 +512,9 @@ then
printf "It's a file.\n\n" printf "It's a file.\n\n"
if [[ $readable -eq 1 ]]; then sleep 2; fi if [[ $readable -eq 1 ]]; then sleep 2; fi
printf "It's called $msg_filename.md\n\n" printf "It's called $msg_filename.md\n\n"
# Open file with xed
[[ $(which xed) ]] && xed ~/$msg_filename.md &
else else
printf "It's %s files.\n\n" "${#tyPosts[@]}" printf "It's %s files.\n\n" "${#tyPosts[@]}"
if [[ $readable -eq 1 ]]; then sleep 2; fi if [[ $readable -eq 1 ]]; then sleep 2; fi

42
tip/Dockerfile Normal file
View File

@ -0,0 +1,42 @@
FROM debian@sha256:bf338ddc710dfb9b907a29ba661b35d0f6b3eae043515c4315f64c6e93409e94
LABEL MAINTAINER=chamalow <@qio8/4L4vnzq3qRD0dqKI7sTpey54u8ZWbaICfpJOZw=.ed25519>
ENV DEBIAN_FRONTEND noninteractive
ENV NVM_INSTALL_DIR /opt/nvm
ENV NVM_DIR /usr/local/nvm
ENV NODE_VERSION v12.16.1
COPY ./tip/sbotc.sh /usr/bin/sbotc
RUN apt-get update -y && \
apt-get install autoconf=2.69-11.1 build-essential=12.8 python3-pip=20.0.2-2 python3-setuptools=44.0.0-1 libsodium-dev=1.0.18-1 jq=1.6-1 make=4.2.1-1.2 git=1:2.25.1-1 gcc=4:9.2.1-3.1 base58=1.0.3-1 libtool=2.4.6-14 curl=7.68.0-1 git=1:2.25.1-1 bc=1.07.1-2+b2 -y && \
pip3 install duniterpy==0.56.0 silkaj==0.7.6 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* && \
useradd -ms /bin/bash astroport && \
chmod +x /usr/bin/sbotc
RUN git clone https://github.com/creationix/nvm.git $NVM_INSTALL_DIR && \
. $NVM_INSTALL_DIR/nvm.sh && \
nvm install --lts && \
nvm alias default $NODE_VERSION && \
nvm use default && \
echo "export NVM_DIR=${NVM_DIR}" > /home/astroport/.bashrc && \
echo ". ${NVM_INSTALL_DIR}/nvm.sh" > /home/astroport/.bashrc && \
chown -R astroport:astroport $NVM_DIR
COPY ./samples /home/astroport/samples
COPY ./tip/tip.sh /home/astroport/tip
COPY ./tip/sbotc.js /home/astroport/sbotc.js
RUN chmod +x /home/astroport/samples /home/astroport/tip /home/astroport/sbotc.js
USER astroport
WORKDIR /home/astroport/
RUN . ~/.bashrc && \
mkdir -p /home/astroport/.ssb/ && \
npm install -g sodium-native@3.0.0 ssb-backlinks@1.0.0 && \
npm install commander@5.0.0 ssb-client@4.9.0 pull-stream@3.6.14
VOLUME [ "/home/astroport/.ssb"]
ENTRYPOINT ["/bin/bash"]
CMD ["-c", "tail" ,"-f", "/dev/null"]

56
tip/sbotc.js Executable file
View File

@ -0,0 +1,56 @@
const {program} = require("commander");
const ssbClient = require('ssb-client');
const pull = require('pull-stream');
let convertToInt = (value) => {
return parseInt(value);
}
let throwProgram = (err) => {
console.error(err.message);
process.exit(1);
}
program.version('.0.0.1');
program
.requiredOption('-s, --host <value>', 'host name or ip of ssb-server', 'oasis')
.requiredOption('-p, --port <number>', 'port of ssb-server', convertToInt, 8008)
/**
* whoami command
*/
program
.command('whoami')
.description('return your identity')
.action(() => {
ssbClient({host:program.host, port:program.port}, (err, sbot) => {
if(err) throwProgram(err)
sbot.whoami((err, identity) =>{
if(err) throwProgram
console.log(JSON.stringify(identity));
sbot.close();
})
})
});
/**
* query
*/
program
.command('query <query>')
.description('you can execute a query')
.action((query) => {
ssbClient({host:program.host, port:program.port}, (err, sbot) =>{
if(err) throwProgram(err);
pull(sbot.query.read({query:JSON.parse(query)}),pull.collect( (err, array) => {
if(err) throwProgram(err);
array.forEach((result) => {
console.log(JSON.stringify(result));
})
sbot.close();
}))
})
});
program.parse(process.argv);

4
tip/sbotc.sh Normal file
View File

@ -0,0 +1,4 @@
#!/bin/bash
. ~/.bashrc
node ~/sbotc.js $@

531
tip/tip.sh Executable file
View File

@ -0,0 +1,531 @@
#!/bin/bash
################################################################################
#
# Authors:
#
# [@cel](@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519)
# [@Fred](@9BbJwPDjcyIqrOUPNn0nJZBduWdIrpMk3Cjz5MP361s=.ed25519)
# [@Boris](@l5nYExWYIgDLV6BYHOJPoI97jIUyTdSm8CTLpQ0XeOg=.ed25519)
# [@poka](@vDQif9KU3T78XJx+NliK+wdo1vmehHZCWqD+3X700Uk=.ed25519)
# @[chamalow](@qio8/4L4vnzq3qRD0dqKI7sTpey54u8ZWbaICfpJOZw=.ed25519)
#
# Version: 1.0
#
# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
#
###########################################################################################
# PREVENT DOUBLE PAYEMENT
# ADD Ğ1 Layer 10 LOVE to message writer you like !
############################################################################################
# Customizable
# debugMsgMode, when set to 1 does doesn't send transaction and does not update "last timestamp"
debugMsgMode=0
# If you don't want to wait
readable=1
minimumAmountPerLikeInUD="0.1"
############################################################################################
# Let's get Ğ1 public and private keys
g1pub=$(cat ~/.ssb/secret.dunikey | grep "pub" | cut -d ' ' -f 2)
g1priv=$(cat ~/.ssb/secret.dunikey | grep "sec" | cut -d ' ' -f 2)
# SSB pubkey
ssbpub=$(cat ~/.ssb/secret | grep public\" | cut -d ' ' -f 4 | cut -d '.' -f 1 | sed s/\"//g)
defaultAmountPerLikeInUD="0.1"
bold=$(tput bold)
normal=$(tput sgr0)
ssbMaxSize=8192
baseSizeOfAMessageFile=$(wc -c samples/message.json | awk '{print $1}')
sizeOfATagMention=$(wc -c samples/tag_mention.json | awk '{print $1}')
sizeOfAUserMention=$(wc -c samples/user_mention.json | awk '{print $1}')
sizeOfAPostMention=$(wc -c samples/post_mention.json | awk '{print $1}')
############################################################################################
#### CHECK LIKE AND SEND LOVE
# Let's get Ğ1 account balance
echo ""
echo -e "${bold}Welcome${normal} to the Ğ1/SSB-like microdonation system!\n"
if [[ $readable -eq 1 ]]; then sleep 1; fi
echo "MMMMMMMMMMMMMNk;'cdxxd:,c0WMMMMMMMMMMMMM
MMMMMMMMMMMMMNx,. .;kWMMMMMMMMMMMMM
MMMMMMMMMMMMMMMNOdlccld0NMMMMMMMMMMMMMMM
MMMMMMMMMMMWXko:,'....',:okXWMMMMMMMMMMM
MMMMMMMMMNk:. .cOWMMMMMMMMM
MMMMMMMW0: .c0MMMMMMMM"
if [[ $readable -eq 1 ]]; then sleep 1; fi
echo "MMMMMMWk. 'lxkOOkdc' .cOWMMMMMMM
MMMMMMO' 'kNMMMMMMMMNxcoOXWMMMMMMMMM
MMMMMNl '0MMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMX; cNMMMMMMMNOkkkkkkkkkkONMMMMM
MMMMMNc ;XMMMMMMMNd' .OMMMMM
MMMMMWx. cKMMMMMMMWKc. .OMMMMM
MMMMMMNo. .lkKXNNXKkc. .OMMMMM"
if [[ $readable -eq 1 ]]; then sleep 1; fi
echo "MMMMMMMNd. ...... .OMMMMM
MMMMMMMMWKl. 'c:. .OMMMMM
MMMMMMMMMMWXkc,.. ..,lkXWWO:;OMMMMM
MMMMMMMMMMMMMMWX0OxddxO0XWMMMMMMWXNMMMMM
MMMMMMMMMMMMMMMMNx;'',dNMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMK, '0MMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMNd. .oNMMMMMMMMMMMMMMMM
"
if [[ $readable -eq 1 ]]; then sleep 1; fi
printf "You know your SSB pubkey:\n%s\n\n" $ssbpub
if [[ $readable -eq 1 ]]; then sleep 2; fi
printf "...but did you know it is also a valid Ğ1 wallet?\n%s\n\n" $g1pub
if [[ $readable -eq 1 ]]; then sleep 2; fi
printf "Let's check the current balance of your wallet!\n\n"
if [[ $readable -eq 1 ]]; then sleep 1; fi
printf "I am interrogating the Ğ1 blockchain to check if anyone has already sent you Ğ1...\n\n"
if [[ $readable -eq 1 ]]; then sleep 2; fi
printf "A moment please...\n\n"
if [[ $readable -eq 1 ]]; then sleep 1; fi
silkajRelativeAmountPattern='Total\sRelative\s+=\s+(.*)\s+UD'
duniter_servers[0]="duniter-g1.p2p.legal:443"
duniter_servers[1]="g1.duniter.org:443"
duniter_servers[2]="g1.presles.fr:443"
duniter_servers[3]="balboa.altsysnet.com:10900"
duniter_servers[4]="remuniter.cgeek.fr:16120"
duniter_servers[5]="duniter.moul.re:443"
duniter_servers[6]="77.152.31.154:20901"
duniter_servers[7]="duniter.g1.1000i100.fr:443"
silkajExitCode=1
i=0
while [ $silkajExitCode -ne 0 ] && [ $i -lt ${#duniter_servers[@]} ]
do
echo "Testing server ${duniter_servers[$i]}..."
echo ""
silkajOutput=$(silkaj -p "${duniter_servers[$i]}" balance $g1pub 2>/dev/null)
silkajExitCode=$?
((i++))
done
if [ $silkajExitCode -eq 1 ]
then
echo "The server did not respond well. Please try again."
exit 1
fi
if [[ $silkajOutput =~ $silkajRelativeAmountPattern ]]
then
balance="${BASH_REMATCH[1]}"
else
echo "Account balance wasn't found."
exit 1
fi
printf "You have ${bold}%s UDĞ1${normal} on your Duniter Ğ1 wallet.\n\n" "$balance"
if [[ $readable -eq 1 ]]; then sleep 2; fi
printf "Want to show your appreciation of your fellow butts' posts while helping spreading awareness about libre currencies?\n\n"
if [[ $readable -eq 1 ]]; then sleep 3; fi
# BEGIN timestamp computation
self=$(sbotc whoami | jq -r .id) || exit 1
ssb_dir=~/.${ssb_appname:-ssb}
id_part=$(echo "$self" | sed 's/\//_/g' | tail -c +2 | head -c 9)
state_file=$ssb_dir/likes-g1-$id_part.ts
current_ts=$(date -u +%s%N | cut -b1-13)
if [ -s "$state_file" ]
then
last_ts=$(cat "$state_file") || exit 1
else
# timestamp from 24h ago
last_ts=$((current_ts - 24*3600*1000 - 1))
#else last_ts=null
fi
days_from_last_tx=$(( (current_ts - last_ts) / (24*60*60*1000) ))
# END timestamp computation
printf "First, let's see how much ❤ you gave lately...\n\n"
if [[ $readable -eq 1 ]]; then sleep 1; fi
declare -A likesNbPerAuthor
declare -A likedPosts
declare -A likesNbPerPost
declare -A postsTimestamps
declare -A excerpts
totalLikesGiven=0
process_msg() {
msg=$1
target_id=$(printf %s "$msg" | jq -r '.value?.content?.vote?.link') || return 1
target_msg=$(sbotc query '[{"$filter":{"value":{"content":{}},"key":"'"$target_id"'"}}]') || return 1
target_author=$(printf %s "$target_msg" | jq -r .author) || return 1
msg_content=$(printf %s "$target_msg" | jq -r .content?.text) || return 1
# beware of markdown !
msg_excerpt=${msg_content:0:10}
#root_id=$(printf %s "$target_msg" | jq -r .content?.root) || return 1
#[[ $root_id = "null" ]] && root_id=$target_id
}
process_author() {
author_id=$1
g1_author=$(echo $author_id | cut -d '.' -f 1 | cut -d '@' -f2 | base64 -d | base58)
author_name=$(sbotc query '[{"$filter":{"value":{"content":{"about":"'"$author_id"'"}}}}]' | jq .value?.content?.name | grep -v null | tail -n 1)
author_name=${author_name:1:-1}
}
authorsNb=0
i=0
messages=$(sbotc query '[{"$filter":{"value":{"author":"'"$self"'","content":{"type":"vote","vote":{"expression":"Like"}},"timestamp":{"$gt":'"$last_ts"'}}}}]')
while read -r msg
do
priv=$(printf %s "$msg" | jq .value.content.private)
if [[ $priv = true ]]
then
printf "Private message $priv, continue to next one\n" >&2
continue
fi
if ! process_msg "$msg"
then
msg_id=$(printf %s "$msg" | jq -r .key)
printf '\nUnable to process message %s\n' "$msg_id" >&2
exit 1
fi
if [[ $g1_author = $g1pub ]]; then
echo "I LIKE MY MESSAGE $target_id"
else
((totalLikesGiven++))
if [[ ${likesNbPerAuthor[$target_author]} -eq 0 ]]
then
likesNbPerAuthor[$target_author]=1
likedPosts[$target_author]=""
else
likesNbPerAuthor[$target_author]=$((${likesNbPerAuthor[$target_author]} + 1))
fi
if [[ ${likesNbPerPost[$target_id]} -eq 0 ]]
then
likesNbPerPost[$target_id]=1
likedPosts[$target_author]+=$target_id
likedPosts[$target_author]+="\n"
else
((likesNbPerPost[$target_id]++))
fi
excerpts[$target_id]=$msg_excerpt
# We cannot use this anymore
# (now saving current_ts once all tx have been sent)
#
# if ! postsTimestamps[$target_id]=$(printf %s "$msg" | jq -r .value.timestamp)
#then
# printf 'Unable to get message timestamp\n' >&2
# exit 1
#fi
((i++))
fi
done < <(echo "$messages" | jq -c)
if [[ $totalLikesGiven -eq 0 ]]
then
printf "You did not give any like during the past %s days or they have already been processed.\n\n" "$days_from_last_tx"
printf "Try again in a few days.\n\n"
fi
printf "You gave ${bold}%s❤${normal} during the past %s days.\n\n" "$totalLikesGiven" "$days_from_last_tx"
if [[ $readable -eq 1 ]]; then sleep 2; fi
tx_are_possible=0
while [[ $tx_are_possible -eq 0 ]]
do
printf "How many UDĞ1 do you want to send per each like you gave? (minimum is ${bold}%s UDĞ1${normal}) " "$minimumAmountPerLikeInUD"
read a
printf "\n"
if [[ -z $a ]]
then
amountPerLikeInUD=$minimumAmountPerLikeInUD
else
amountPerLikeInUD=$a
fi
amountGiven=$(echo "$totalLikesGiven * $amountPerLikeInUD" | bc -l)
has_enough_money=$(( $(echo "$amountGiven <= $balance" | bc -l) ))
amountPerLike_is_enough=$(( $(echo "$amountPerLikeInUD >= $minimumAmountPerLikeInUD" | bc -l) ))
tx_are_possible=$(( $has_enough_money && $amountPerLike_is_enough ))
if [[ $readable -eq 1 ]]; then sleep 1; fi
if [[ $tx_are_possible -eq 0 ]] ; then
if [[ $has_enough_money -eq 0 ]] ; then
printf "You don't have enough UDĞ1 to send all transactions.\n\n"
if [[ $readable -eq 1 ]]; then sleep 1; fi
printf "${bold}%s UDĞ1${normal} are needed.\n\n" "$amountGiven"
if [[ $readable -eq 1 ]]; then sleep 1; fi
elif [[ $amountPerLike_is_enough -eq 0 ]] ; then
printf "Minimum amount per like is %s UDĞ1.\n\n" $minimumAmountPerLikeInUD
if [[ $readable -eq 1 ]]; then sleep 1; fi
fi
printf "Try again with a different amount per like.\n\n"
maxAmountPerLike=$(awk -vp=$balance -vq=$totalLikesGiven 'BEGIN{printf "%.2f" ,p / q}')
if [[ $readable -eq 1 ]]; then sleep 1; fi
printf "Maximum amount per like possible: ${bold}%s UDĞ1${normal}\n\n" "$maxAmountPerLike"
if [[ $readable -eq 1 ]]; then sleep 1; fi
else
newBalance=$(echo "$balance - $amountGiven" | bc -l)
printf "${bold}%s UDĞ1${normal} will be given.\n\n" "$amountGiven"
if [[ $readable -eq 1 ]]; then sleep 1; fi
printf "After sending transactions, your new balance will be ${bold}%s UDĞ1${normal}\n\n" "$newBalance"
if [[ $readable -eq 1 ]]; then sleep 1; fi
printf "Press ENTER to continue: " && read
printf "\n"
fi
done
# Let's construct thank you posts (tyPosts) and send transactions!
tyPostIndex=0
tyPosts[0]=""
tyPosts[0]+="# I tipped you for your posts!\n\n"
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")
tyPosts[0]+="\n\nAs a means to thank you further, I have just sent you #Ğ1 libre money.\n\n"
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"
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"
tyPosts[0]+="Below is the list of SSB users whose content I liked recently, and the amount each one was given:\n\n"
tableHeaders='| thanks to | for their posts | tip |\n'
tableHeaders+='| --- | --- | ---- |\n'
sizeOfTableHeaders=$(printf "%s" "$tableHeaders" | wc -c)
tyPosts[0]+=$tableHeaders
# for message size calculation
# update following if you add tags in the message :
tags[0]="Ğ1"
tags[1]="resilience"
sizeOfTags=0
for t in ${!tags[@]}
do
tagSize=$(printf "%s" "${tags[t]}" | wc -c)
(( sizeOfTags+=sizeOfATagMention + tagSize ))
done
firstPostContentSize=$(printf "%s" "${tyPosts[0]}" | wc -c)
tyPostsSizes[0]=$((baseSizeOfAMessageFile + firstPostContentSize + sizeOfTags))
nbOfAuthors=${#likesNbPerAuthor[@]}
authorNum=1
for author_id in ${!likesNbPerAuthor[@]}
do
process_author $author_id
# (Legacy) saving authors we have already mentionned in a message
likedAuthorsFile=$ssb_dir/db/g1likes
if [ ! -f $likedAuthorsFile ]; then
touch $likedAuthorsFile
fi
if ! grep -Fxq $author_id $likedAuthorsFile; then
echo $author_id >> $likedAuthorsFile
fi
tipAmount=$(bc <<< "${likesNbPerAuthor[$author_id]} * $amountPerLikeInUD")
newLine=''
newLine+=$(printf "| [@%s](%s) " "$author_name" "$author_id")
newLine+="| "
sizeOfAuthorName=$(printf "%s" "$author_name" | wc -c)
sizeOfAuthorId=$(printf "%s" "$author_id" | wc -c)
newLineSize=0
(( newLineSize+=sizeOfAUserMention + sizeOfAuthorName + sizeOfAuthorId))
p=${likedPosts[$author_id]}
thisAuthorLikedPosts=( ${p//\\n/ } )
isFirstPostOfThisAuthor=1
for likedPostId in ${thisAuthorLikedPosts[@]}
do
if [[ $isFirstPostOfThisAuthor -eq 1 ]]
then
isFirstPostOfThisAuthor=0
else
newLine+=", "
(( newLineSize+=2 ))
fi
newLine+=$(printf " %s❤" "${likesNbPerPost[$likedPostId]}")
newLine+=$(printf "[\`%s\`](%s)" "${excerpts[$likedPostId]}" "$likedPostId")
sizeOfExcerpt=${#excerpts[$likedPostId]}
(( sizeOfExcerpt+=2 )) # for before ` and after `
sizeOfLikedPostId=$(printf "%s" "$likedPostId" | wc -c)
(( newLineSize+=sizeOfAPostMention + sizeOfExcerpt + sizeOfLikedPostId ))
done
newLine+=$(printf "| %s UDĞ1 " "$tipAmount")
newLine+="|\n"
(( newLineSize+=$(printf "%s" "$newLine" | wc -c) ))
# printf "total size: %s\n\n" "$((${tyPostsSizes[$tyPostIndex]} + $newLineSize))"
# If adding new line would exceed max size, we create a new thank you post
sizeWithNewLine=${tyPostsSizes[$tyPostIndex]}
(( sizeWithNewLine+=newLineSize ))
if [[ $sizeWithNewLine -gt $ssbMaxSize ]]
then
printf "size before split: %s\n\n" "${tyPostsSizes[$tyPostIndex]}"
printf "size with new line: %s\n\n" "$sizeWithNewLine"
printf "size of new line: %s\n\n" "$newLineSize"
(( tyPostIndex++ ))
tyPosts[$tyPostIndex]+=$tableHeaders
(( tyPostsSizes[$tyPostIndex]=baseSizeOfAMessageFile + sizeOfTableHeaders ))
fi
tyPosts[$tyPostIndex]+=$newLine
(( tyPostsSizes[$tyPostIndex]+=newLineSize ))
if [[ $debugMsgMode -eq 0 ]]
then
if [[ $authorNum -ne 1 ]]
then
sleep 20 # DO NOT OVER CHARGE DUNITER
fi
#printf '%s\n' "silkaj -af --file ~/.ssb/secret.dunikey tx --output $g1_author --amountUD $tipAmount --comment "Thx for your cool posts on ScuttleButt"
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
printf "\n${bold}%s UDĞ1${normal} sent to %s!\n\n" "$tipAmount" "$author_name"
fi
(( authorNum++ ))
done
# Let's save the current timestamp
if [[ $debugMsgMode -eq 0 ]]
then
if ! echo "$current_ts" > "$state_file"~
then
printf 'Unable to write to backup state file.\n' >&2
exit 1
fi
if ! mv "$state_file"~ "$state_file"
then
printf 'Unable to write to state file. Update state file manually to prevent tips to %s from being processed twice.\n' "$author_name" >&2
exit 1
fi
fi
printf "\n%s UDĞ1 sent to %s butts!\n\n" "$amountGiven" "${#likesNbPerAuthor[@]}"
# Let's publicly thank everyone!
#echo -e "${tyPosts[$n]}"
# the following produces error:
# "sbotc: unexpected end of parent stream"
# must be a non-escaped quote problem...
#thank_you_msg=$(printf "%q" "${tyPosts[$n]}")
#sbotc publish '{"type":"post","text":"'"$thank_you_msg"'"}' 2>&1>/dev/null
printf "What now ?\n\n"
if [[ $readable -eq 1 ]]; then sleep 1; fi
date=$(date -u +%Y-week-%W)
if [[ ${#tyPosts[@]} -eq 1 ]]
then
msg_filename=thank-your-butts-$date
echo -e ${tyPosts[$n]} > ~/$msg_filename.md
else
for i in ${!tyPosts[@]}
do
part=$((i + 1))
msg_filename=thank-your-butts-$date
echo -e ${tyPosts[$i]} > ~/$msg_filename-part-$part.md
done
fi
printf "A surprise is awaiting in your home dir (~).\n\n"
if [[ $readable -eq 1 ]]; then sleep 2; fi
if [[ ${#tyPosts[@]} -eq 1 ]]
then
printf "It's a file.\n\n"
if [[ $readable -eq 1 ]]; then sleep 2; fi
printf "It's called $msg_filename.md\n\n"
else
printf "It's %s files.\n\n" "${#tyPosts[@]}"
if [[ $readable -eq 1 ]]; then sleep 2; fi
printf "The first one is called $msg_filename-part-1.md.\n\n"
fi
if [[ $readable -eq 1 ]]; then sleep 2; fi
printf "Customize it to your needs to thank your fellow butts publicly and help spread awareness about libre currencies :-)\n\n"
if [[ $readable -eq 1 ]]; then sleep 3; fi
printf "Then delete it.\n\n"
if [[ $readable -eq 1 ]]; then sleep 2; fi
printf "...because it won't self-destruct, haha :D \n\n"