Compare commits

..

62 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
qo-op 0e76a649bc backup .ssb 2020-03-30 03:33:30 +02:00
qo-op fb3d19fb8d extended install 2020-03-30 03:02:29 +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
Boris Paing 6741563501 Add script to find SSB user's G1 pubkey 2020-03-20 23:39:52 +01:00
Boris Paing d051566054 Update Readme bis 2020-03-20 23:18:49 +01:00
Boris Paing e2db28ff33 Improve Readme 2020-03-20 23:16:09 +01:00
Boris Paing a47bcc8593 change value fields image position 2020-03-20 17:37:17 +01:00
Boris Paing dbd470e2cb bye bye Cesium screenshots 2020-03-20 17:29:21 +01:00
Boris Paing e8c0e8dbbe Logo first 2020-03-20 17:22:13 +01:00
Boris Paing 89968b630a fix links 2020-03-20 17:17:58 +01:00
Boris Paing 8d2e2f1306 merge 2020-03-20 17:09:36 +01:00
Boris Paing 15d459d45f Split of thank you message is not a wild guess anymore 2020-03-20 17:03:27 +01:00
BorisPaing 9dfe107553 hotfix silkaj --output (bad regex usage, sorry) 2020-03-20 11:30:53 +01:00
poka b170b48111 remove sbotc bad submodule 2020-03-19 19:25:01 +01:00
BorisPaing 03a65981eb default to 0.1 instead of 0.05
accounts with less than 1 G1 are destroyed
2020-03-19 16:04:23 +01:00
joseelinchevalay 4d1071d3a7 install nodejs rust dup-mnemonic 2020-03-19 15:25:21 +01:00
Boris Paing e6c309a7ef Fix output filename 2020-03-19 11:04:45 +01:00
Boris Paing b168d862d9 Fixed default value of amount per like + fix output (duplicated links to post) 2020-03-19 10:55:02 +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
Boris Paing ba28469412 forgot to uncomment one more line 2020-03-19 02:07:18 +01:00
Boris Paing cb24229e55 forgot to uncomment... 2020-03-19 02:05:25 +01:00
Boris Paing e8cadfcbe3 deletion of useless lines at the end 2020-03-19 01:07:56 +01:00
Boris Paing a9ad86a5d1 Add more servers + split file 2020-03-19 00:56:23 +01:00
Boris Paing 5db26e0ecd Oops, forgot to uncomment usefull lines 2020-03-18 22:18:15 +01:00
Boris Paing c7d649b690 Less spammy behavior 2020-03-18 20:41:11 +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
26 changed files with 1667 additions and 316 deletions

View File

@ -1,23 +1,66 @@
FROM debian@sha256:bf338ddc710dfb9b907a29ba661b35d0f6b3eae043515c4315f64c6e93409e94
LABEL MAINTAINER=chamalow <@qio8/4L4vnzq3qRD0dqKI7sTpey54u8ZWbaICfpJOZw=.ed25519>
ENV DEBIAN_FRONTEND noninteractive
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 ./process-likes-g1tx.sh /usr/bin/process-likes-g1tx
COPY ./secret2dunikey.sh /usr/bin/secret2dunikey
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 python3-pip=18.1-5 python3-setuptools=44.0.0-1 python3-wheel=0.33.6-2 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 -y && \
chmod +x /usr/bin/secret2dunikey /usr/bin/process-likes-g1tx /usr/bin/key_create_dunikey&& \
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
RUN mkdir -p /home/astroport/.ssb/
VOLUME [ "/home/astroport/.ssb/" ]
EXPOSE 8008
ENTRYPOINT [ "/bin/bash" ]
CMD ["process-likes-g1tx"]
CMD ["docker-entrypoint.sh"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

BIN
doc/create-account.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 820 KiB

BIN
doc/ssb-g1-tip-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

BIN
doc/tip.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

BIN
doc/value-fields.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 KiB

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:

15
find_ssb_user_G1_pubkey.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
ssbPubkey=$1
if [[ ${ssbPubkey:0:1} == "@" ]]
then
ssbPubkey=${ssbPubkey:1}
fi
ssbPubkey=$(echo $ssbPubkey | cut -d '.' -f 1)
g1pub=$(echo "$ssbPubkey" | base64 -d | base58)
echo ""
echo $g1pub
echo ""

View File

@ -1,5 +1,5 @@
#!/bin/bash
################################################################################
########################################################################
# Authors:
# [@cel](@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519)
# [@Fred](@9BbJwPDjcyIqrOUPNn0nJZBduWdIrpMk3Cjz5MP361s=.ed25519)
@ -7,92 +7,142 @@
# [@poka]()
# Version: 1.0.1
# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
###########################################################################################
# ADD G1 Layer 10 LOVE to message writer you like !
# INSTALL silkaj sbotc
# PREVENT DOUBLE PAYEMENT
############################################################################################
# INSTALL requirements
[[ ! $(which base58) ]] && sudo apt install build-essential base58 -y
########################################################################
########################################################################
MY_PATH="`dirname \"$0\"`" # relative
MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized
ME="${0##*/}"
echo '
########################################################################
# \\///
# qo-op
############# '$MY_PATH/$ME'
########################################################################
# SSB-G1-TX :: INSTALL G1 + SSB for sending G1 Tip on SSB likes
########################################################################
'
# INSTALL Silkaj, CLI for Duniter
if [[ ! $(which silkaj) ]]; then
echo "INSTALL silkaj"
echo '**************************************************************
__ ___
(_ | | |/ /\ |
__) _|_ |_ |\ /--\ \_|
#Libre Money Layer
'
mkdir -p ~/.zen
sudo apt update || true
sudo apt install python3-pip python3-setuptools python3-wheel -y && pip3 install silkaj --user
sudo apt install build-essential -y
sudo pip3 install base58
sudo apt install python3-pip python3-setuptools python3-wheel -y
pip3 install silkaj --user
echo 'PATH=$PATH:.local/bin' >> ~/.bashrc && source ~/.bashrc
fi
# Install ScuttleButt
if [[ ! $(which sbot) ]]; then
# Install ScuttleButt
echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
__ _ ___ ___ _ _ ___ ___
(_ / | | | | | |_ |_) | | | |
__) \_ |_| | | |_ |_ |_) |_| | |
#Libre Social Layer
Is it a 24/24 Pub?
Yes/No: y? (Default No)'
read ssb_yes
nodename=$(cat /etc/hostname)
extension=$(echo $nodename | cut -d '.' -f 2)
[[ $extension == $nodename ]] && nodename=$nodename.local
if [[ ! $(which sbot) && "$ssb_yes" == "y" ]]; then
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | bash
source ~/.bashrc
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
nvm install --lts
sudo apt install libtool autoconf -y
npm install sodium-native ssb-backlinks
npm install -g ssb-server
nodename=$(cat /etc/hostname).local
echo "SSB Node Hostname (default $nodename)?"
read EXTERNAL
[[ $EXTERNAL == "" ]] && EXTERNAL=$nodename
mkdir -p ~/.ssb
nvm install --lts
sudo apt install libtool autoconf -y
npm install sodium-native ssb-backlinks ssb-ws ssb-links ssb-query ssb-secret-blob ssb-private
npm install -g ssb-server
# LOCAL
####### BACKUP .ssb to ~/.ssb_$USER && CREATE ~/.ssb_astroport
# If exists backup ~/.ssb to ~/.ssb_$USER SSB (one time only !)
[[ -d ~/.ssb_$USER ]] && echo "BACKUP already existing... ~/.ssb_$USER !!! Manual check please..." && exit 1
[[ -d ~/.ssb ]] && [[ ! -d ~/.ssb_$USER ]] && mv ~/.ssb ~/.ssb_$USER
# CREATE ~/.ssb_astroport
[[ ! -d ~/.ssb_astroport ]] && mkdir -p ~/.ssb_astroport
# if exists, keep ~/.ssb_$USER/secret*
[[ ! -f ~/.ssb_astroport/secret ]] && [[ -f ~/.ssb_$USER/secret ]] && cp -f ~/.ssb_$USER/secret* ~/.ssb_astroport/
# Symlink ~/.ssb -> ~/.ssb_astroport
[[ -L ~/.ssb ]] && rm ~/.ssb
[[ -d ~/.ssb_astroport ]] && ln -s ~/.ssb_astroport ~/.ssb
cat > ~/.ssb/config <<EOF
{
"connections": {
"incoming": {
"net": [
{
"scope": "public", "external": ["$EXTERNAL"], "transform": "shs", "port": 8008
},
{ "scope": "private", "transform": "shs", "port": 8008, "host": "127.0.0.1" }
{ "scope": "public", "host": "0.0.0.0", "external": ["$nodename"], "transform": "shs", "port": 8008 }
],
"ws": [
{ "scope": ["public", "local", "device"], "host": "0.0.0.0", "port": 8989, "transform": "shs", "http": true }
]
},
"outgoing": {
"net": [
{
"transform": "shs"
}
]
"net": [{ "transform": "shs" }]
}
}
}
EOF
cat > ~/run-ssb-PUB_$EXTERNAL.sh <<EOF
cat > ~/.zen/run-ssb_server.sh <<EOF
#!/bin/bash
echo _$ > ~/.zen/ssb.pid.bash
while true; do
ssb-server start --host $EXTERNAL
ssb-server start
echo _! > ~/.zen/ssb.pid
done
EOF
chmod 755 ~/run-ssb-PUB_$EXTERNAL.sh
~/run-ssb-PUB_$EXTERNAL.sh &
# REPLACE _ with $
sed -i s/_/\$/g ~/.zen/run-ssb_server.sh
chmod 755 ~/.zen/run-ssb_server.sh
# INSTALL sbotc for CLI API
if [[ ! $(which sbotc) ]]; then
sudo apt install libsodium-dev jq -y
git clone https://git.scuttlebot.io/%25133ulDgs%2FoC1DXjoK04vDFy6DgVBB%2FZok15YJmuhD5Q%3D.sha256 sbotc
cd sbotc
make
sudo make install
fi
fi
# INSTALL sbotc
if [[ ! $(which sbotc) ]]; then
sudo apt install libsodium-dev jq -y
git clone https://git.scuttlebot.io/%25133ulDgs%2FoC1DXjoK04vDFy6DgVBB%2FZok15YJmuhD5Q%3D.sha256 sbotc
cd sbotc
make
sudo make install
fi
# LOCAL NODE
if [[ $extension == $nodename ]] ; then
echo '
_ ___ _ _ _
|_) /\ | / |_| \ / / \ |_) |/
| /--\ | \_ | | \/\/ \_/ | \ |\
Install Patchwork...
'
wget -s https://github.com/ssbc/patchwork/releases/download/v3.17.6/ssb-patchwork_3.17.6_amd64.deb > /tmp/
sudo dpkg -i /tmp/ssb-patchwork_3.17.6_amd64.deb
fi
###########################################################################################
####################### G1 SSB ACCOUNT MANAGER ############################################
###########################################################################################
# If user already has an SSB account, we generate Duniter secret key from SSB secret key
if [[ -f ~/.ssb/secret ]]; then
@ -115,48 +165,62 @@ else
mkdir -p ~/.ssb
echo "WELCOME CREATING YOUR G1 SSB ACCOUNT !!!"
echo "CHOOSE YOU LOGIN or LEAVE BLANK & HIT ENTER FOR AUTO GENERATION"
echo "
__ __ __ _
/__ /| (_ (_ |_)
\_| | __) __) |_)
CHOOSE YOU LOGIN or LEAVE BLANK & HIT ENTER FOR AUTO GENERATION"
read salt
[[ $salt != "" ]] && echo "PASSWORD?" && read pepper && [[ $pepper == "" ]] && exit
[[ $salt != "" ]] && echo "PASSWORD?" && read pepper && [[ $pepper == "" ]] && exit 1
# INSTALL Cargo
if [[ ! $(which cargo) ]]; then
curl https://sh.rustup.rs -sSf | sh
PATH=$PATH:~/.cargo/env
source $HOME/.cargo/env
if [[ "$salt" == "" && "$pepper" == "" ]]; then
echo '
._ _ ._ _ ._ _ _ ._ o _
| | | | | (/_ | | | (_) | | | (_
passphrase generator...'
# INSTALL Cargo
if [[ ! $(which cargo) ]]; then
curl https://sh.rustup.rs -sSf | sh
PATH=$PATH:~/.cargo/env
source $HOME/.cargo/env
fi
# Install DUP-Mnemonic
if [[ ! $(which dup-mnemonic) ]]; then
cd /tmp
git clone https://git.duniter.org/tools/dup-mnemonic-rs
cd dup-mnemonic-rs
cargo build --release
sudo cp target/release/dup-mnemonic /usr/local/bin
fi
# GENERATE MNEMONIC KEY: 9 MOTS
if [[ $salt == "" ]]; then
declare -a makeyarray
makeyarray=($(dup-mnemonic -l $lang))
# LOGIN (=SALT) 6 WORDS
salt="${makeyarray[0]} ${makeyarray[1]} ${makeyarray[2]} ${makeyarray[3]} ${makeyarray[4]} ${makeyarray[5]}"
# PASS (=PEPPER) 3 WORDS
pepper="${makeyarray[6]} ${makeyarray[7]} ${makeyarray[8]}"
fi
echo "........."
echo "REMEMBER YOUR CREDENTIALS: $salt / $pepper"
fi
# Install DUP-Mnemonic
if [[ ! $(which dup-mnemonic) ]]; then
cd /tmp
git clone https://git.duniter.org/tools/dup-mnemonic-rs
cd dup-mnemonic-rs
cargo build --release
sudo cp target/release/dup-mnemonic /usr/local/bin
fi
# GENERATE MNEMONIC KEY: 9 MOTS
if [[ $salt == "" ]]; then
declare -a makeyarray
makeyarray=($(dup-mnemonic -l $lang))
# LOGIN (=SALT) 6 MOTS
salt="${makeyarray[0]} ${makeyarray[1]} ${makeyarray[2]} ${makeyarray[3]} ${makeyarray[4]} ${makeyarray[5]}"
# PASS (=PEPPER) 3 MOTS
pepper="${makeyarray[6]} ${makeyarray[7]} ${makeyarray[8]}"
fi
echo "........."
echo "REMEMBER YOUR CREDENTIALS: $salt / $pepper"
# CREATE ~/.ssb/secret.dunikey
python3 ./key_create_dunikey.py "$salt" "$pepper"
mv ./.secret.dunikey ~/.ssb/secret.dunikey
python3 $MY_PATH/key_create_dunikey.py "$salt" "$pepper"
mv $MY_PATH/.secret.dunikey ~/.ssb/secret.dunikey
# CREATE SSB secret
pub=$(cat ~/.ssb/secret.dunikey | grep "pub" | cut -d ' ' -f 2)
priv=$(cat ~/.ssb/secret.dunikey | grep "sec" | cut -d ' ' -f 2)
ssbpub=$(echo $pub | base58 -d | base64)
ssbpriv=$(echo $priv | base58 -d | base64)
cat > ~/.ssb/secret <<EOF
# This secret is related to your G1Wallet - https://cesium.app
# silkaj balance $pub

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

@ -1,186 +0,0 @@
#!/bin/bash
################################################################################
# Authors:
# [@cel](@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519)
# [@Fred](@9BbJwPDjcyIqrOUPNn0nJZBduWdIrpMk3Cjz5MP361s=.ed25519)
# [@Boris](@l5nYExWYIgDLV6BYHOJPoI97jIUyTdSm8CTLpQ0XeOg=.ed25519)
# Version: 1.0
# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
###########################################################################################
# PREVENT DOUBLE PAYEMENT
# ADD G1 Layer 10 LOVE to message writer you like !
############################################################################################
# Let's get G1 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)
############################################################################################
#### CHECK LIKE AND SEND LOVE
# Let's get G1 account balance
echo ""
echo "Welcome to the G1 SSB like microdonation system!"
echo "
MMMMMMMMMMMMMNk;'cdxxd:,c0WMMMMMMMMMMMMM
MMMMMMMMMMMMMNx,. .;kWMMMMMMMMMMMMM
MMMMMMMMMMMMMMMNOdlccld0NMMMMMMMMMMMMMMM
MMMMMMMMMMMWXko:,'....',:okXWMMMMMMMMMMM
MMMMMMMMMNk:. .cOWMMMMMMMMM
MMMMMMMW0: .c0MMMMMMMM
MMMMMMWk. 'lxkOOkdc' .cOWMMMMMMM
MMMMMMO' 'kNMMMMMMMMNxcoOXWMMMMMMMMM
MMMMMNl '0MMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMX; cNMMMMMMMNOkkkkkkkkkkONMMMMM
MMMMMNc ;XMMMMMMMNd' .OMMMMM
MMMMMWx. cKMMMMMMMWKc. .OMMMMM
MMMMMMNo. .lkKXNNXKkc. .OMMMMM
MMMMMMMNd. ...... .OMMMMM
MMMMMMMMWKl. 'c:. .OMMMMM
MMMMMMMMMMWXkc,.. ..,lkXWWO:;OMMMMM
MMMMMMMMMMMMMMWX0OxddxO0XWMMMMMMWXNMMMMM
MMMMMMMMMMMMMMMMNx;'',dNMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMK, '0MMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMNd. .oNMMMMMMMMMMMMMMMM
"
sleep 1
echo ""
echo "You know your SSB pubkey:"
echo $ssbpub
sleep 1
echo ""
echo "...but did you know it is also a valid G1 wallet?"
echo $g1pub
sleep 2
echo ""
echo "Let's check the current balance of your wallet!"
sleep 2
echo ""
echo "We are interrogating the G1 blockchain to check if anyone has already sent G1..."
sleep 1
echo ""
echo "A moment please..."
echo ""
sleep 1
duniter_server="duniter-g1.p2p.legal:443"
echo "Testing server $duniter_server..."
echo ""
silkaj -p "$duniter_server" balance $g1pub 2>/dev/null
if [ $? -eq 1 ]
then
duniter_server="g1.duniter.org:443"
echo "Testing server $duniter_server..."
echo ""
silkaj -p "$duniter_server" balance $g1pub 2>/dev/null
if [ $? -eq 1 ]
then
echo "The server did not respond well. Please try again."
exit 1
fi
fi
echo "Have any money? Then let's send G1love. Press ENTER to continue. " && read
###########################################################################################
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
if [ -s "$state_file" ]
then last_ts=$(cat "$state_file") || exit 1
else
last_ts=$(date -u +%s%N | cut -b1-13)
last_ts=$((last_ts - 3600000)) # timestamp from 1h ago
#else last_ts=null
fi
process_msg() {
msg=$1
target_id=$(printf %s "$msg" | jq -r '.value?.content?.vote?.link') || return 1
target_msg=$(sbotc -e get "$target_id") || return 1
target_author=$(printf %s "$target_msg" | jq -r .author) || return 1
author_s_name=$(sbotc query.read '{"query":[{"$filter":{"value":{"author": "'"$target_author"'", "content":{"type":"about", "about": "'"$target_author"'"}}}}]}' | jq .value?.content?.name | grep -v null | tail -n 1)
root_id=$(printf %s "$target_msg" | jq -r .content?.root) || return 1
[[ $root_id == "null" ]] && root_id=$target_id
g1_author=$(echo $target_author | cut -d '.' -f 1 | cut -d '@' -f2 | base64 -d | base58)
msg_excerpt=$(printf %s "$target_msg" | jq -r .content?.text | head -n 10) || return 1
}
bold=$(tput bold)
normal=$(tput sgr0)
sbotc query.read '{"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 ! ts=$(printf %s "$msg" | jq -r .value.timestamp)
then
printf 'Unable to get message timestamp\n' >&2
exit 1
fi
if ! echo "$ts" > "$state_file"~
then
printf 'Unable to write to backup state file.\n' >&2
exit 1
fi
if ! process_msg "$msg"
then
msg_id=$(printf %s "$msg" | jq -r .key)
printf 'Unable to process message %s\n' "$msg_id" >&2
exit 1
fi
echo ""
echo "================================================================"
printf "Let's thank ${bold}@%s ${normal}for their message: \n" "${author_s_name:1:-1}"
echo "================================================================"
printf "%s" "$msg_excerpt"
echo ""
echo "----------------------------------------------------------------"
if [[ $g1_author != $g1pub ]]; then
#printf '%s\n' "silkaj -af --file ~/.ssb/secret.dunikey tx --output $g1_author --amountUD 0.1 --comment _SSB:LIKE:$target_id"
#### SEND 10 LOVE = 0.1 DU to $g1_author wallet
silkaj -p "$duniter_server" -af --file ~/.ssb/secret.dunikey tx --output $g1_author --amountUD 0.1 --comment "_SSB:LIKE:$target_id" -y 2>/dev/null
#### WRITE RESPONSE MESSAGE
if [ ! -f ~/.ssb/db/g1likes ]; then
touch ~/.ssb/db/g1likes
fi
if ! grep -Fxq $target_author ~/.ssb/db/g1likes; then
echo $target_author >> ~/.ssb/db/g1likes
thank_you_msg=$(printf '[@%s](%s) > Thanks for this post ; I have just sent you G1 libre money. Use it with [Cesium](https://cesium.app). Get it from [https://git.p2p.legal/Axiom-Team/ssb-g1like](https://git.p2p.legal/Axiom-Team/ssb-g1like)' "${author_s_name:1:-1}" "$target_author")
sbotc publish '{"type":"post","text":"'"$thank_you_msg"'", "branch": "'"$target_id"'", "root": "'"$root_id"'"}' 2>&1>/dev/null
echo "----------------------------------------------------------------"
printf "Since it's the first time you sent G1 to %s, he was sent this message: \n\n%s \n" "$author_s_name" "$thank_you_msg"
echo "----------------------------------------------------------------"
fi
#printf "0.1 G1UD sent to %s!\n" "$author_s_name"
#echo "----------------------------------------------------------------"
echo ""
echo ""
sleep 20 # DO NOT OVER CHARGE DUNITER
else
echo "I LIKE MY MESSAGE $target_id"
fi
if ! mv "$state_file"~ "$state_file"
then
msg_id=$(printf %s "$msg" | jq -r .key)
printf 'Unable to write to state file. Update state file manually to prevent %s from being processed twice.\n' "$msg_id" >&2
exit 1
fi
done

157
readme.md
View File

@ -1,62 +1,137 @@
SSB/Ğ1 like
![SSB/Ğ1 tip](https://git.p2p.legal/axiom-team/ssb-g1-tip/raw/master/doc/ssb-g1-tip-logo.png)
===
**SSB/Ğ1 like** is a micro donation system, just like Flattr, except:
**SSB/Ğ1 tip** is a micro donation system, just like Flattr, except:
- It runs on SSB instead of the centralized web
- It uses a libre currency (Ğ1) instead of a private one
![SSB/Ğ1 like logo](https://git.p2p.legal/axiom-team/ssb-g1like/raw/dev-boris/doc/ssb-g1like-logo.png)
## Authors
- **cel** from the SSB community (`@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519`)
- **Fred** from the Ğ1 community (`@9BbJwPDjcyIqrOUPNn0nJZBduWdIrpMk3Cjz5MP361s=.ed25519`)
- **Boris** from the Ğ1 community (`@l5nYExWYIgDLV6BYHOJPoI97jIUyTdSm8CTLpQ0XeOg=.ed25519`)
## What is a libre currency?
A [libre currency](https://libre-currency.org/) is a concept that originated from the [Relative Theory of Money](https://en.trm.creationmonetaire.info/).
It is a way to design a currency so that every human, whatever the generation they are part of, produces the same relative amount of money.
The Relative Theory of Money was written by a French mathematician in 2010, and the first libre currency (Ğ1) was born in 2017. Up to this day, Ğ1 is the only libre currency we know of.
### Ğ1, the first libre currency
Ğ1 the first libre currency we know of.
It runs on [the Duniter blockchain engine](https://duniter.org/).
The main clients for Duniter are [Cesium](https://cesium.app/) and [Silkaj](https://mystifying-nobel-66ae54.netlify.com/)
## How to spend your Ğ1
The Ğ1 currency originated in called France, so the main part of the fun happens there.
The economy is still in its infancy, but you can already [book a reservation in a B&B](https://www.gchange.fr/#/app/market/lg?last&category=cat67&type=offer).
An other way to spend your Ğ1 is use it with this micro-donation system:
![](https://git.p2p.legal/axiom-team/ssb-g1like/raw/dev-boris/doc/process-likes-g1tx.gif)
## An SSB user sent you Ğ1? Here is how to claim it:
First, you need to get your Duniter secret key from your SSB secret key.
First, you need to generate your base58 Duniter secret key from your base64 SSB secret key.
```
chmod +x secret2dunikey.sh
./secret2dunikey.sh
```
Then, all you need to do is connect to a Duniter client, like [Cesium](https://cesium.app/), using the generated ~/.ssb/secret.dunikey
Then, all you need to do is connect to a Duniter client, using the generated ~/.ssb/secret.dunikey
On Cesium homescreen, click "**Other methods**" and choose "**Keychain file**" :
1. Download [Cesium](https://cesium.app/)
2. On Cesium homescreen, click "**Other methods**" and choose "**Keychain file**" :
3. Then, browse your filesystem to select your Duniter secret key stored in ~/.ssb/secret.dunikey :
4. Contemplate how rich and resilient you now are.
5. Update your Cesium+ profile to appear on the registry map.
![Cesium authentification](https://git.p2p.legal/axiom-team/ssb-g1like/raw/dev-boris/doc/cesium-other-methods-800.png)
![Cesium authentification](https://git.p2p.legal/axiom-team/ssb-g1-tip/raw/master/doc/create-account.gif)
Then, browse your filesystem to select your Duniter secret key stored in ~/.ssb/secret.dunikey :
## You too want to send tips?
![Cesium log with keychain file](https://git.p2p.legal/axiom-team/ssb-g1like/raw/dev-boris/doc/cesium-dunikey-800.png)
A cool way to spend your Ğ1 is use it with this micro-donation system.
### Install
First, you have to install the necessary tools using the `install.sh` script.
```
chmod +x install.sh tip.sh
./install.sh
```
This script installs tools like Silkaj, the command line Duniter client. Don't worry, you will only have to do this once 😉
### Usage
Then, once every other week, you can use the `tip.sh` script :
```
./tip.sh
```
`tip.sh` will have a look at the posts you liked and will send from your Duniter account the corresponding amount (based on the number of times you liked a post) to the appropriate recipients.
It will also generate one or more markdown formatted files to help you thank publicly your fellow butts, and make them aware you sent them a tip 😉
![](https://git.p2p.legal/axiom-team/ssb-g1-tip/raw/master/doc/tip.gif)
## Other ways to spend your Ğ1
The Ğ1 currency originated in called France, so the main part of the fun happens there.
The economy is still in its infancy, but you can already:
- [book a reservation in a B&B](https://www.gchange.fr/#/app/market/lg?last&category=cat67&type=offer),
- [buy SEO services](https://www.gchange.fr/#/app/market/lg?type=offer&q=SEO),
- [buy web hosting services](https://www.gchange.fr/#/app/market/lg?type=offer&q=h%C3%A9bergement%20web)
- [buy foreign language courses](https://www.gchange.fr/#/app/market/lg?type=offer&q=langues) (for example: [french](https://www.gchange.fr/#/app/market/view/AWybPgso8tT4T_JOSi4w/francais-langue-trangre))
- etc. etc. ([see latest offers](https://www.gchange.fr/#/app/market/lg?last&type=offer))
## Curious about libre currencies?
[Libre currencies](https://libre-currency.org/) are a concept that originated from the [Relative Theory of Money](https://en.trm.creationmonetaire.info/).
It is a way to design a currency so that every human, whatever the generation they are part of, produces the same relative amount of money.
Unlinke the majority of currencies, where money creation is centralized (money is created by big private banks via credit), in a libre currency, money creation takes place everywhere.
![](https://git.p2p.legal/axiom-team/ssb-g1-tip/raw/master/doc/value-fields.png)
The Relative Theory of Money was written in 2010 by French mathematician Stephane Laborde, and the first libre currency (Ğ1) was born in 2017. Up to this day, Ğ1 is the only libre currency we know of.
### Ğ1, the first libre currency
Ğ1 the first libre currency we know of.
Ğ1 has the particularity to use blockchain to secure transactions, and uses on a web of trust to identify unique users, in order to make sure each individual can produce only one **Universal Dividend** each day, and nobody is cheating by producing a disproportionate amount of money.
Ğ1 runs on [the Duniter blockchain engine](https://duniter.org/).
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
- **cel** (`@f/6sQ6d2CMxRUhLpspgGIulDxDCwYD7DzFzPNr7u5AU=.ed25519`)
- **Fred** (`@9BbJwPDjcyIqrOUPNn0nJZBduWdIrpMk3Cjz5MP361s=.ed25519`)
- **Boris** (`@l5nYExWYIgDLV6BYHOJPoI97jIUyTdSm8CTLpQ0XeOg=.ed25519`)
- **poka** (`@vDQif9KU3T78XJx+NliK+wdo1vmehHZCWqD+3X700Uk=.ed25519`)
- **chamalow** (`@qio8/4L4vnzq3qRD0dqKI7sTpey54u8ZWbaICfpJOZw=.ed25519`)

18
samples/message.json Normal file
View File

@ -0,0 +1,18 @@
{
"value": {
"previous": "%bcGFgwgdCjhGQjVYCNaUSKZq6xqMBpiB23U4q2lq2uE=.sha256",
"sequence": 392,
"author": "@l5nYExWYIgDLV6BYHOJPoI97jIUyTdSm8CTLpQ0XeOg=.ed25519",
"timestamp": 1584565226366,
"hash": "sha256",
"content": {
"type": "post",
"text": "",
"mentions": [
]
},
"signature": "TZ8R5HlKvuPquS26CJkq2VhPdR+yA2LdnL0cVo1GD6jJioTufup1n6mSrQIc3jHyqy+wZ8ILJfsWnqt8WegQAg==.sig.ed25519"
},
"timestamp": 1584565226369,
"rts": 1584565226366
}

View File

@ -0,0 +1,5 @@
{
"link": "",
"name": ""
},

4
samples/tag_mention.json Normal file
View File

@ -0,0 +1,4 @@
{
"link": "#"
},

View File

@ -0,0 +1,5 @@
{
"link": "",
"name": ""
},

1
sbotc

@ -1 +0,0 @@
Subproject commit f1337fffb2467ae35d1e694221cd0fd9ba97923f

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"]

535
tip.sh Executable file
View File

@ -0,0 +1,535 @@
#!/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
minimumAmountPerLikeInLOVE="10"
############################################################################################
# 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 LOVE${normal} on your Duniter Ğ1 wallet.\n\n" "$((balance * 100))"
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 -e get "$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.read '{"query":[{"$filter":{"value":{"author": "'"$author_id"'", "content":{"type":"about", "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.read '{"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 < <(printf '%s\n' "$messages")
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 LOVE do you want to send per each like you gave? (minimum is ${bold}%s LOVE${normal}) " "$((minimumAmountPerLikeInLOVE))"
read a
printf "\n"
if [[ -z $a ]]
then
amountPerLikeInUD=$(bc -l <<< "scale=2; $minimumAmountPerLikeInLOVE / 100")
else
amountPerLikeInUD=$(bc -l <<< "scale=2; $a / 100")
fi
amountGiven=$(echo "$totalLikesGiven * $amountPerLikeInUD" | bc -l)
has_enough_money=$(( $(echo "$amountGiven <= $balance" | bc -l) ))
amountPerLike_is_enough=$(( $(echo "$amountPerLikeInUD >= $minimumAmountPerLikeInLOVE" | 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 LOVE to send all transactions.\n\n"
if [[ $readable -eq 1 ]]; then sleep 1; fi
printf "${bold}%s LOVE${normal} are needed.\n\n" "$((amountGiven * 100))"
if [[ $readable -eq 1 ]]; then sleep 1; fi
elif [[ $amountPerLike_is_enough -eq 0 ]] ; then
printf "Minimum amount per like is %s LOVE.\n\n" $minimumAmountPerLikeInLOVE
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 LOVE${normal}\n\n" "$((maxAmountPerLike * 100))"
if [[ $readable -eq 1 ]]; then sleep 1; fi
else
newBalance=$(echo "$balance - $amountGiven" | bc -l)
printf "${bold}%s LOVE${normal} will be given.\n\n" "$((amountGiven * 100))"
if [[ $readable -eq 1 ]]; then sleep 1; fi
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
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 LOVE " "$((tipAmount * 100))")
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 LOVE${normal} sent to %s!\n\n" "$((tipAmount * 100))" "$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 LOVE sent to %s butts!\n\n" "$((amountGiven * 100))" "${#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"
# Open file with xed
[[ $(which xed) ]] && xed ~/$msg_filename.md &
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"

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"