From ee3a6bc9f424d5d9b327d043fb7abd93ada80664 Mon Sep 17 00:00:00 2001 From: poka Date: Sat, 14 Dec 2019 20:45:36 +0000 Subject: [PATCH 01/26] Lot of changes in .install. Add Kalkun install (not finish) --- .gitignore | 3 +- .install/1-install_requirements.sh | 62 ++++---- .install/2-configure_ipfs_layer.sh | 2 +- .install/3-install_copylaradio.sh | 33 ++-- .install/4-install_playsms.sh | 140 ----------------- .install/4a-install_kalkun.sh | 98 ++++++++++++ .install/4b-install_playsms.sh | 102 ++++++++++++ .install/ssl.sh | 30 ++-- .install/templates/1/gammu-smsdrc | 34 ++++ .install/templates/{ => 1}/ipfs.service | 0 .install/templates/{ => 3}/mpd.conf | 0 .install/templates/4a/daemon.php | 10 ++ .install/templates/4a/daemon.sh | 8 + .install/templates/4a/database.php | 58 +++++++ .install/templates/4a/kalkun.conf | 40 +++++ .install/templates/4a/mysql.sql | 192 +++++++++++++++++++++++ .install/templates/{ => 4b}/install-playsms.conf | 0 .install/templates/{ => 4b}/playsms.conf | 4 +- .install/templates/{ => 5}/default | 0 .install/templates/{ => rproxy}/proxypass.conf | 0 .install/templates/{ => rproxy}/ssl.conf | 0 .install/templates/{ => rproxy}/ssl_renew.sh | 0 GSM_POWERKEY.py => debug/GSM_POWERKEY.py | 0 GSM_powerkey.sh => debug/GSM_powerkey.sh | 0 debug/debugTTY.sh | 19 +++ debug/gammu-loglevel.sh | 13 ++ debug/gammu-restart.sh | 9 ++ install.sh | 15 +- test.sh => tests/test.sh | 0 29 files changed, 672 insertions(+), 200 deletions(-) delete mode 100755 .install/4-install_playsms.sh create mode 100755 .install/4a-install_kalkun.sh create mode 100755 .install/4b-install_playsms.sh create mode 100644 .install/templates/1/gammu-smsdrc rename .install/templates/{ => 1}/ipfs.service (100%) rename .install/templates/{ => 3}/mpd.conf (100%) create mode 100755 .install/templates/4a/daemon.php create mode 100755 .install/templates/4a/daemon.sh create mode 100644 .install/templates/4a/database.php create mode 100644 .install/templates/4a/kalkun.conf create mode 100644 .install/templates/4a/mysql.sql rename .install/templates/{ => 4b}/install-playsms.conf (100%) rename .install/templates/{ => 4b}/playsms.conf (94%) rename .install/templates/{ => 5}/default (100%) rename .install/templates/{ => rproxy}/proxypass.conf (100%) rename .install/templates/{ => rproxy}/ssl.conf (100%) rename .install/templates/{ => rproxy}/ssl_renew.sh (100%) rename GSM_POWERKEY.py => debug/GSM_POWERKEY.py (100%) rename GSM_powerkey.sh => debug/GSM_powerkey.sh (100%) create mode 100755 debug/debugTTY.sh create mode 100755 debug/gammu-loglevel.sh create mode 100755 debug/gammu-restart.sh rename test.sh => tests/test.sh (100%) diff --git a/.gitignore b/.gitignore index 183b73d..7c37ee6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ g1sms.bfproject g1sms.priv.key shell/init.sh +shell/init.sh.old *~ wallets/ shell/trash/ @@ -9,5 +10,5 @@ history.* TAG/ .install/errors .install/log -shell/init.sh.old +.install/.OS .profile diff --git a/.install/1-install_requirements.sh b/.install/1-install_requirements.sh index 9011077..602d579 100755 --- a/.install/1-install_requirements.sh +++ b/.install/1-install_requirements.sh @@ -15,9 +15,9 @@ sudo apt install curl jq zip unzip htop tree ntpdate gnupg ssmtp mpack imagemagi silkaj() { libsodium=$(sudo apt search libsodium 2>/dev/null | grep -v -E "header|debug symbols" | grep "Network communication" -B1 | head -n1 | awk -F '/' '{ print $1 }') [[ $libsodium =~ " " ]] && libsodium=$(echo $libsodium | awk '{ print $2 }') - sudo apt install python3-pip $libsodium -y - pip3 install duniterpy - pip3 install silkaj --user + sudo apt install python3-pip $libsodium -y || err=1 + pip3 install duniterpy || err=1 + pip3 install silkaj --user || err=1 } @@ -25,35 +25,35 @@ silkaj() { ipfs() { [[ -f /usr/local/bin/ipfs ]] && sudo service ipfs stop if [[ $isARM ]]; then - wget https://dist.ipfs.io/ipfs-update/v1.5.2/ipfs-update_v1.5.2_linux-arm.tar.gz -O $MY_PATH/ipfs-update.tar.gz + wget https://dist.ipfs.io/ipfs-update/v1.5.2/ipfs-update_v1.5.2_linux-arm.tar.gz -O $MY_PATH/ipfs-update.tar.gz || err=1 else - wget https://dist.ipfs.io/ipfs-update/v1.5.2/ipfs-update_v1.5.2_linux-amd64.tar.gz -O $MY_PATH/ipfs-update.tar.gz + wget https://dist.ipfs.io/ipfs-update/v1.5.2/ipfs-update_v1.5.2_linux-amd64.tar.gz -O $MY_PATH/ipfs-update.tar.gz || err=1 fi echo "INSTALL ipfs-update" - sudo tar -xvzf $MY_PATH/ipfs-update.tar.gz -C /usr/src/ + sudo tar -xvzf $MY_PATH/ipfs-update.tar.gz -C /usr/src/ || err=1 rm $MY_PATH/ipfs-update.tar.gz cd /usr/src/ipfs-update/ - sudo ./install.sh + sudo ./install.sh || err=1 cd $MY_PATH echo "INSTALL latest ipfs" - sudo ipfs-update install latest + sudo ipfs-update install latest || err=1 echo "CREATE SYSTEMD ipfs SERVICE" [[ -f /etc/systemd/system/ipfs.service ]] && sudo rm /etc/systemd/system/ipfs.service - sudo cp -f $MY_PATH/templates/ipfs.service /etc/systemd/system/ + sudo cp -f $MY_PATH/templates/1/ipfs.service /etc/systemd/system/ sudo sed -i "s/_USER/$USER/g" /etc/systemd/system/ipfs.service - sudo systemctl daemon-reload - sudo systemctl enable ipfs + sudo systemctl daemon-reload || err=1 + sudo systemctl enable ipfs || err=1 } # Install gammu gammu() { - sudo apt install ppp screen git minicom gammu -y + sudo apt install ppp screen git minicom gammu -y || err=1 sleep 1 - sudo apt install gammu-smsd -y || sudo apt install -f + sudo apt install gammu-smsd -y || sudo apt install -f || err=1 sudo usermod -aG gammu $USER } @@ -61,22 +61,24 @@ gammu() { # Install PHP + MySQL php() { if [[ $OS == "buster" ]]; then - sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xF1656F24C74CD1D8 - sudo add-apt-repository 'deb [arch=amd64] http://mariadb.mirror.liquidtelecom.com/repo/10.4/debian buster main' - sudo apt -y update - sudo apt -y install software-properties-common nginx php php-common php-fpm php-gettext php-gd php-mysql php-curl php-imap php-mbstring php-xml php-cli mariadb-server + sudo apt -y install software-properties-common nginx php php-common php-fpm php-gettext php-gd php-mysql php-curl php-imap php-mbstring php-xml php-cli mariadb-server || err=1 elif [[ $OS == "stretch" ]]; then - sudo apt -y install lsb-release apt-transport-https ca-certificates - sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg - echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php7.3.list - sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 - echo -e "deb [arch=amd64,i386,ppc64el] http://sfo1.mirrors.digitalocean.com/mariadb/repo/10.4/debian stretch main\ndeb-src http://sfo1.mirrors.digitalocean.com/mariadb/repo/10.4/debian stretch main" | sudo tee /etc/apt/sources.list.d/mariadb.list - sudo apt -y update - sudo apt -y install software-properties-common dirmngr nginx php7.3 php7.3-common php7.3-gettext php7.3-fpm php7.3-gd php7.3-mysql php7.3-curl php7.3-imap php7.3-mbstring php7.3-xml php7.3-cli mariadb-server + sudo apt -y install lsb-release apt-transport-https ca-certificates || err=1 + sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg || err=1 + echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php7.3.list + sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 || err=1 + sudo apt update + sudo apt -y install software-properties-common dirmngr nginx php7.3 php7.3-common php7.3-gettext php7.3-fpm php7.3-gd php7.3-mysql php7.3-curl php7.3-imap php7.3-mbstring php7.3-xml php7.3-cli mariadb-server || err=1 else - echo "${c_red}Votre système n'est pas pris en charge par ce script d'installation.$c_" - exit 1 + echo "${c_red}Votre système n'est pas pris en charge par ce script d'installation.$c_" + exit 1 fi + + isLocalhostUsers=$(sudo mysql -e "select user from mysql.user;" | grep "localhost") + isTestDB=$(sudo mysql -e "show databases" | grep "test") + [[ -n $isLocalhostUsers ]] && sudo mysql -e "DROP USER ''@'localhost'; DROP USER ''@'$(hostname)'" + [[ -n $isTestDB ]] && sudo mysql -e "DROP DATABASE test" + sudo mysql -e "FLUSH PRIVILEGES" } # Read arguments @@ -85,4 +87,10 @@ for i in $@; do $i done -exit 0 +if [[ $err ]]; then + echo -e "${c_red}Installation des prérequis incomplète$c_" + exit 1 +else + echo -e "${c_green}Les prérequis ont été correctement installés$c_" + exit 0 +fi diff --git a/.install/2-configure_ipfs_layer.sh b/.install/2-configure_ipfs_layer.sh index b1b3981..0839556 100755 --- a/.install/2-configure_ipfs_layer.sh +++ b/.install/2-configure_ipfs_layer.sh @@ -8,7 +8,7 @@ MY_PATH="`dirname \"$0\"`" # relative MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized stamp=$(date +%s) -templates="$MY_PATH/templates" +templates="$MY_PATH/templates/2" ####################################### # CONFIGURE IPFS for G1sms+ Pi NODES diff --git a/.install/3-install_copylaradio.sh b/.install/3-install_copylaradio.sh index b9f72d1..1de3c4f 100755 --- a/.install/3-install_copylaradio.sh +++ b/.install/3-install_copylaradio.sh @@ -9,7 +9,7 @@ isARM=$(cat $MY_PATH/.OS | grep YES) ################################## ## INSTALL TOOLS ######## YOUTUBE-DL ########## -sudo wget https://yt-dl.org/downloads/latest/youtube-dl -O /usr/local/bin/youtube-dl +sudo wget https://yt-dl.org/downloads/latest/youtube-dl -O /usr/local/bin/youtube-dl || err=1 sudo chmod a+rx /usr/local/bin/youtube-dl ## TODO FOR DEBIAN STRETCH @@ -17,20 +17,20 @@ sudo chmod a+rx /usr/local/bin/youtube-dl wget -q https://ftp-master.debian.org/keys/release-10.asc -O- | sudo apt-key add - echo "deb http://deb.debian.org/debian buster non-free" | sudo tee -a /etc/apt/sources.list sudo apt update -sudo apt install libid3-tools mpd mpc lame -y libttspico-utils -y +sudo apt install libid3-tools mpd mpc lame -y libttspico-utils -y || err=1 ## CONFIG MPD sudo cp -f $templates/mpd.conf /etc/mpd.conf -sudo sed -i "s/_USER/$USER/g" /etc/mpd.conf +sudo sed -i "s/_USER/$USER/g" /etc/mpd.conf || err=1 sudo chown -R $USER /var/lib/mpd/ /var/run/mpd /run/mpd /var/log/mpd -sudo service mpd restart +sudo service mpd restart || err=1 -sudo apt-get install nginx php-curl php-sqlite3 php-gd php-json php-xml php-mbstring php-fpm sqlite -y -sudo apt-get install lame sox libsox-fmt-mp3 eyed3 python-chardet imagemagick curl -y #libav-tools -sudo apt-get install ca-certificates git-core binutils rsync alsa-utils bc libid3-tools espeak mpg321 fuse atomicparsley -y #libttspico-utils +sudo apt-get install nginx php-curl php-sqlite3 php-gd php-json php-xml php-mbstring php-fpm sqlite -y || err=1 +sudo apt-get install lame sox libsox-fmt-mp3 eyed3 python-chardet imagemagick curl -y #libav-tools || err=1 +sudo apt-get install ca-certificates git-core binutils rsync alsa-utils bc libid3-tools espeak mpg321 fuse atomicparsley -y || err=1 wget http://launchpadlibrarian.net/339874908/libav-tools_3.3.4-2_all.deb -O $MY_PATH/libav-tools.deb wget http://ftp.fr.debian.org/debian/pool/non-free/s/svox/libttspico-data_1.0+git20130326-3_all.deb -O $MY_PATH/libttspico-data.deb @@ -41,10 +41,10 @@ else wget http://ftp.fr.debian.org/debian/pool/non-free/s/svox/libttspico0_1.0+git20130326-5_amd64.deb -O $MY_PATH/libttspico0.deb wget http://ftp.fr.debian.org/debian/pool/non-free/s/svox/libttspico-utils_1.0+git20130326-9_amd64.deb -O $MY_PATH/libttspico-utils.deb fi -sudo dpkg -i $MY_PATH/libttspico-data.deb -sudo dpkg -i $MY_PATH/libttspico0.deb -sudo dpkg -i $MY_PATH/libttspico-utils.deb -sudo dpkg -i $MY_PATH/libav-tools.deb || sudo apt --fix-broken install -y +sudo dpkg -i $MY_PATH/libttspico-data.deb || err=1 +sudo dpkg -i $MY_PATH/libttspico0.deb || err=1 +sudo dpkg -i $MY_PATH/libttspico-utils.deb || err=1 +sudo dpkg -i $MY_PATH/libav-tools.deb || sudo apt --fix-broken install -y || err=1 rm $MY_PATH/libttspico-data.deb $MY_PATH/libttspico0.deb $MY_PATH/libttspico-utils.deb $MY_PATH/libav-tools.deb @@ -52,7 +52,7 @@ rm $MY_PATH/libttspico-data.deb $MY_PATH/libttspico0.deb $MY_PATH/libttspico-uti sudo cp -f $templates/default /etc/nginx/sites-available/ sudo sed -i "s/_USER/$USER/g" /etc/nginx/sites-available/default -sudo systemctl restart nginx +sudo systemctl restart nginx || err=1 ################################# ## Get _CopyLaRadio distrib @@ -67,4 +67,11 @@ sudo systemctl restart nginx #sudo chmod 777 /home/$USER/_CopyLaRadio/www/rompr/albumart #sudo chmod 777 /home/$USER/_CopyLaRadio/www/rompr/prefs -exit 0 +if [[ $err ]]; then + echo -e "${c_red}Installation de copylaradio incomplète$c_" + exit 1 +else + echo -e "${c_green}CopyLaRadio a été installé avec succès$c_" + exit 0 +fi + diff --git a/.install/4-install_playsms.sh b/.install/4-install_playsms.sh deleted file mode 100755 index 95c5ea1..0000000 --- a/.install/4-install_playsms.sh +++ /dev/null @@ -1,140 +0,0 @@ -#!/bin/bash - -MY_PATH="`dirname \"$0\"`" # relative -MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized - -[[ -f $MY_PATH/../.profile ]] && source $MY_PATH/../.profile -unset err -pwdDB=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 42 | head -n 1) - -args=$@ -[[ $args =~ noask ]] && noask=o && askSSL=o - -[[ ! $PSMS_DOMAIN ]] && echo -e "${c_yellow}Choisissez un nom de domain pour playsms: $c_" && read PSMS_DOMAIN - -## Install PHP + MySQL -$MY_PATH/1-install_requirements.sh php - -## Create database - -if [[ ! $(sudo mysql -e "show databases;" | grep gammu) ]]; then - sudo mysql -e "CREATE DATABASE gammu" - sudo mysql -e "CREATE USER 'gammu'@'localhost' IDENTIFIED BY '$pwdDB';" - sudo mysql -e "GRANT ALL PRIVILEGES ON playsms.* TO 'gammu'@'localhost';" - sudo mysql -e "FLUSH PRIVILEGES;" -else - sudo mysql -e "ALTER USER 'gammu'@'localhost' IDENTIFIED BY '$pwdDB';" -fi - -## Clone repo playSMS -[[ -d $MY_PATH/playsms ]] && sudo rm -rf $MY_PATH/playsms -git clone https://github.com/antonraharja/playSMS.git $MY_PATH/playsms - -cp $MY_PATH/templates/install-playsms.conf $MY_PATH/playsms/install.conf -sed -i "s/_pwdDB/$pwdDB/g" $MY_PATH/playsms/install.conf - -[[ -d /var/www/playsms ]] && sudo rm -rf /var/www/playsms -sudo chmod u+x $MY_PATH/playsms/install-playsms.sh -cd $MY_PATH/playsms -sed -i "s/read /confirm=y; #read /g" install-playsms.sh -sudo ./install-playsms.sh -sudo sed -i "/ishttps/d" /var/www/playsms/config.php -sudo sed -i "/http or https*/a \$core_config['ishttps'] = true;" /var/www/playsms/config.php -[[ -d $MY_PATH/playsms ]] && sudo rm -rf $MY_PATH/playsms -cd $MY_PATH - -## Start playsmsd on boot -sudo /usr/local/bin/playsmsd start - -if [[ -f /etc/rc.local ]]; then - [[ ! $(grep playsmsd /etc/rc.local) ]] && sudo sed -i '/^exit 0.*/i /usr/local/bin/playsmsd start' /etc/rc.local -else - echo "/usr/local/bin/playsmsd start" | sudo tee /etc/rc.local -fi - -## Tests -if [[ $(sudo playsmsd status) =~ "is running" ]]; then - echo -e "${c_green}playSMS a été installé correctement et le daemon est démarré =)$c_" -else - echo -e "${c_red}Une erreur est survenu$c_" - err=1 -fi - -## Config NGINX - -[[ ! -d /etc/nginx/def_conf ]] && sudo mkdir /etc/nginx/def_conf/ -sudo cp $MY_PATH/templates/proxypass.conf /etc/nginx/def_conf/ -sudo cp $MY_PATH/templates/playsms.conf /etc/nginx/conf.d/ -sudo sed -i "s/_PSMS_DOMAIN/$PSMS_DOMAIN/" /etc/nginx/conf.d/playsms.conf - -## Active SSL - -manageSSL() { - - local action=$1 - [[ ! $action =~ ^(on|off|certif)$ ]] && echo "Veuillez choisir ssl, nonssl ou certif pour créer un certificat ssl" && exit 1 - - install_certbot(){ - sudo apt update - if [[ $(grep -E 'stretch|buster' /etc/os-release) ]]; then - sudo apt install certbot python-certbot-nginx -y - elif [[ $(grep -E '16.|17.|18.|19.' /etc/os-release) ]]; then - sudo apt install software-properties-common - sudo add-apt-repository universe - sudo add-apt-repository ppa:certbot/certbot - sudo apt update - sudo apt install certbot python-certbot-nginx - else - echo "OS non supporté pour certbot." && exit 1 - fi - } - - create_certificate() { - sudo certbot --nginx certonly --non-interactive --agree-tos -m $USER@$PSMS_DOMAIN -d $PSMS_DOMAIN && echo "Le certificat de $PSMS_DOMAIN a bien été déployé" || echo "Une erreur s'est produite lors de la création du certificat SSL" - - ## Cronification - [[ ! -e /opt/scripts ]] && sudo mkdir /opt/scripts - sudo cp $MY_PATH/templates/ssl_renew.sh /opt/scripts/ - [[ -z $(sudo crontab -l | grep "/opt/scripts/ssl_renew.sh") ]] && (sudo crontab -l ; sudo echo "12 2 * * 1 /opt/scripts/ssl_renew.sh") | sudo crontab -u root - - } - - - case $action in - on) - sudo sed -i 's/ #if/ if/' /etc/nginx/conf.d/playsms.conf - - sudo sed -i "s/listen 443;/listen 443 ssl;/" /etc/nginx/conf.d/playsms.conf - [[ ! -d /etc/nginx/includes ]] && sudo mkdir /etc/nginx/includes - sudo cp $MY_PATH/templates/ssl.conf /etc/nginx/includes/ - sudo sed -i "/Content-Security-Policy/a \ include includes/ssl.conf;\n ssl_certificate /etc/letsencrypt/live/$PSMS_DOMAIN/fullchain.pem;\n ssl_certificate_key /etc/letsencrypt/live/$PSMS_DOMAIN/privkey.pem;" /etc/nginx/conf.d/playsms.conf - ;; - - off) - sudo sed -i 's/ if/ #if/' /etc/nginx/conf.d/playsms.conf - sudo sed -i '/ssl.conf;/d' /etc/nginx/conf.d/playsms.conf - sudo sed -i '/ssl_certificate/d' /etc/nginx/conf.d/playsms.conf - ;; - certif) - [[ -z $(which certbot) ]] && install_certbot - [[ -n /etc/letsencrypt/live/$PSMS_DOMAIN/fullchain.pem ]] && create_certificate - ;; - - esac -} - -echo -e "${c_yellow}playSMS ne fonctionne pas sans certifcat SSL.$c_" -[[ ! $noask ]] && printf "${c_yellow}Voulez-vous installer et activer un certificat SSL maintenant pour $PSMS_DOMAIN ? (o/n) $c_" && read askSSL -if [[ $askSSL =~ ^(o|y|yes|oui|Y|O|YES)$ ]]; then - manageSSL certif - if sudo test -f /etc/letsencrypt/live/$PSMS_DOMAIN/fullchain.pem; then manageSSL on; else manageSSL off && echo "Une erreur s'est produite, basculement vers le mode non SSL"; fi - http=https -else - manageSSL off - http=http -fi - -sudo service nginx restart - -[[ ! $err ]] && echo -e "${c_green}Félicitation ! playSMS est accessible via l'URL $http://$PSMS_DOMAIN" || echo -e "${c_red}Installation incomplète$c_" - -exit 0 diff --git a/.install/4a-install_kalkun.sh b/.install/4a-install_kalkun.sh new file mode 100755 index 0000000..7ea5713 --- /dev/null +++ b/.install/4a-install_kalkun.sh @@ -0,0 +1,98 @@ +#!/bin/bash + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + +[[ -f $MY_PATH/../.profile ]] && source $MY_PATH/../.profile +unset err + +args=$@ +[[ $args =~ noask ]] && noask=o && askSSL=o + +IP=$(ifconfig | grep "inet " | grep -v "127.0.0.1" | awk '{ print $2 }') +[[ ! $KSMS_DOMAIN ]] && echo -e "${c_yellow}Choisissez un nom de domaine pour KALKUN (Sinon $IP sera choisi): $c_" && read KSMS_DOMAIN +[[ ! $KSMS_DOMAIN ]] && KSMS_DOMAIN=$IP && askSSL=n && noask=o + +DOMAIN=$KSMS_DOMAIN + +## Install PHP + MySQL +$MY_PATH/1-install_requirements.sh php + +## Create database + +if [[ $(sudo mysql -e "select * from mysql.user;" | grep gammu) ]]; then + pwdDB=$(cat /etc/gammu-smsdrc | grep "password" | grep -v "# " | awk '{ print $3 }') +else + pwdDB=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 42 | head -n 1) + sudo mysql -e "CREATE USER 'gammu'@'localhost' IDENTIFIED BY '$pwdDB';" +fi + +if [[ ! $(sudo mysql -e "show databases;" | grep gammu) ]]; then + sudo mysql -e "CREATE DATABASE gammu" + sudo mysql -e "GRANT ALL PRIVILEGES ON gammu.* TO 'gammu'@'localhost';" + sudo mysql -e "FLUSH PRIVILEGES;" +fi + +[[ ! $(sudo mysql gammu -e "SHOW TABLES LIKE 'outbox';") ]] && sudo mysql gammu < $MY_PATH/templates/4a/mysql.sql || err=1 + +## Clone repo KALKUN + +[[ -d $MY_PATH/kalkun ]] && sudo rm -rf $MY_PATH/kalkun +git clone https://github.com/back2arie/Kalkun.git $MY_PATH/kalkun + +cp $MY_PATH/templates/4a/database.php $MY_PATH/kalkun/application/config/ +cp $MY_PATH/templates/4a/daemon.sh $MY_PATH/templates/4a/daemon.php $MY_PATH/kalkun/scripts +sed -i "s/_PWD/$pwdDB/g" $MY_PATH/kalkun/application/config/database.php || err=1 +echo "debug 1" +sed -i "s/_DOMAIN/$DOMAIN/g" $MY_PATH/templates/4a/daemon.php || err=1 + +## Place le dossier kalkun dans /var/www/ +[[ -d /var/www/kalkun ]] && sudo rm -rf /var/www/kalkun +sudo mv $MY_PATH/kalkun /var/www/ || err=1 +sudo chown -R www-data:www-data /var/www/kalkun || err=1 +sudo chmod u+x /var/www/kalkun/scripts/* + +## Add daemon launcher in sms_received.sh +[[ ! $(grep "Execute Kalkun daemon" $MY_PATH/../sms_received.sh) ]] && sed -i "/^export YOU/i # Execute Kalkun daemon\n/var/www/kalkun/scripts/daemon.sh &\n" $MY_PATH/../sms_received.sh + +## Active gammu in MySQL mode +if [[ $(grep "service = files" /etc/gammu-smsdrc) ]]; then + sudo sed -i "/^service = files/a service = sql\ndriver = native_mysql\nhost = localhost\nuser = gammu\npassword = $pwdDB\ndatabase = gammu" /etc/gammu-smsdrc || err=1 + sudo sed -i "/service = files/d" /etc/gammu-smsdrc || err=1 + $MY_PATH/../debug/gammu-restart.sh || err=1 +fi + +## Config NGINX + +[[ ! -d /etc/nginx/def_conf ]] && sudo mkdir /etc/nginx/def_conf/ +sudo cp $MY_PATH/templates/rproxy/proxypass.conf /etc/nginx/def_conf/ || err=1 +sudo cp $MY_PATH/templates/4a/kalkun.conf /etc/nginx/conf.d/ || err=1 +sudo sed -i "s/_DOMAIN/$DOMAIN/g" /etc/nginx/conf.d/kalkun.conf || err=1 + +## Active SSL + +[[ ! $noask ]] && printf "${c_yellow}Voulez-vous installer et activer un certificat SSL maintenant pour $DOMAIN ? (o/n) $c_" && read askSSL +if [[ $askSSL =~ ^(o|y|yes|oui|Y|O|YES)$ ]]; then + $MY_PATH/ssl.sh certif APP=kalkun DOMAIN=$DOMAIN || err=1 + if sudo test -f /etc/letsencrypt/live/$DOMAIN/fullchain.pem; then + $MY_PATH/ssl.sh on APP=kalkun DOMAIN=$DOMAIN || err=1 + else + echo -e "${c_red}Une erreur s'est produite, basculement vers le mode non SSL$c_" + $MY_PATH/ssl.sh off APP=kalkun DOMAIN=$DOMAIN || err=1 + fi + http=https + sudo sed -i "s/http/https/g" /var/www/kalkun/scripts/daemon.php || err=1 +else + $MY_PATH/ssl.sh off APP=kalkun DOMAIN=$DOMAIN || err=1 + http=http +fi + +sudo service nginx restart || err=1 + +if [[ $err ]]; then + echo -e "${c_red}Installation incomplète$c_" + exit 1 +else + echo -e "${c_green}Kalkun est accessible via l'URL $http://$DOMAIN$c_" + exit 0 +fi diff --git a/.install/4b-install_playsms.sh b/.install/4b-install_playsms.sh new file mode 100755 index 0000000..594d638 --- /dev/null +++ b/.install/4b-install_playsms.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + +[[ -f $MY_PATH/../.profile ]] && source $MY_PATH/../.profile +unset err +pwdDB=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 42 | head -n 1) + +args=$@ +[[ $args =~ noask ]] && noask=o && askSSL=o + +IP=$(ifconfig | grep "inet " | grep -v "127.0.0.1" | awk '{ print $2 }') +[[ ! $PSMS_DOMAIN ]] && echo -e "${c_yellow}Choisissez un nom de domaine pour PlaySMS (Sinon $IP sera choisi): $c_" && read PSMS_DOMAIN +[[ ! $PSMS_DOMAIN ]] && PSMS_DOMAIN=$IP && askSSL=n && noask=o + + +DOMAIN=$PSMS_DOMAIN + +## Install PHP + MySQL +$MY_PATH/1-install_requirements.sh php + +## Create database + +if [[ $(sudo mysql -e "show databases;" | grep gammu) ]]; then + pwdDB=$(cat /etc/gammu-smsdrc | grep "password" | grep -v "# " | awk '{ print $3 }') +else + sudo mysql -e "CREATE DATABASE gammu" + sudo mysql -e "CREATE USER 'gammu'@'localhost' IDENTIFIED BY '$pwdDB';" + sudo mysql -e "GRANT ALL PRIVILEGES ON gammu.* TO 'gammu'@'localhost';" + sudo mysql -e "FLUSH PRIVILEGES;" +fi + +## Clone repo playSMS +[[ -d $MY_PATH/playsms ]] && sudo rm -rf $MY_PATH/playsms +git clone https://github.com/antonraharja/playSMS.git $MY_PATH/playsms + +cp $MY_PATH/templates/4b/install-playsms.conf $MY_PATH/playsms/install.conf +sed -i "s/_pwdDB/$pwdDB/g" $MY_PATH/playsms/install.conf + +[[ -d /var/www/playsms ]] && sudo rm -rf /var/www/playsms +sudo chmod u+x $MY_PATH/playsms/install-playsms.sh +cd $MY_PATH/playsms +sed -i "s/read /confirm=y; #read /g" install-playsms.sh +sudo ./install-playsms.sh +sudo sed -i "/ishttps/d" /var/www/playsms/config.php +sudo sed -i "/http or https*/a \$core_config['ishttps'] = true;" /var/www/playsms/config.php +[[ -d $MY_PATH/playsms ]] && sudo rm -rf $MY_PATH/playsms +cd $MY_PATH + +## Start playsmsd on boot +sudo /usr/local/bin/playsmsd start + +if [[ -f /etc/rc.local ]]; then + [[ ! $(grep playsmsd /etc/rc.local) ]] && sudo sed -i '/^exit 0.*/i /usr/local/bin/playsmsd start' /etc/rc.local +else + echo "/usr/local/bin/playsmsd start" | sudo tee /etc/rc.local +fi + +## Tests +if [[ $(sudo playsmsd status) =~ "is running" ]]; then + echo -e "${c_green}playSMS a été installé correctement et le daemon est démarré =)$c_" +else + echo -e "${c_red}Une erreur est survenu$c_" + err=1 +fi + +## Config NGINX + +[[ ! -d /etc/nginx/def_conf ]] && sudo mkdir /etc/nginx/def_conf/ +sudo cp $MY_PATH/templates/rproxy/proxypass.conf /etc/nginx/def_conf/ +sudo cp $MY_PATH/templates/4b/playsms.conf /etc/nginx/conf.d/ +sudo sed -i "s/_DOMAIN/$DOMAIN/" /etc/nginx/conf.d/playsms.conf + +## Active SSL + +echo -e "${c_yellow}playSMS ne fonctionne pas sans certifcat SSL.$c_" +[[ ! $noask ]] && printf "${c_yellow}Voulez-vous installer et activer un certificat SSL maintenant pour $DOMAIN ? (o/n) $c_" && read askSSL +if [[ $askSSL =~ ^(o|y|yes|oui|Y|O|YES)$ ]]; then + $MY_PATH/ssl.sh certif APP=playsms DOMAIN=$DOMAIN + if sudo test -f /etc/letsencrypt/live/$DOMAIN/fullchain.pem; then + $MY_PATH/ssl.sh on APP=playsms DOMAIN=$DOMAIN + else + echo -e "${c_red}Une erreur s'est produite, basculement vers le mode non SSL$c_" + $MY_PATH/ssl.sh off APP=playsms DOMAIN=$DOMAIN + fi + http=https +else + $MY_PATH/ssl.sh off APP=playsms DOMAIN=$DOMAIN + http=http +fi + +sudo service nginx restart + +if [[ $err ]]; then + echo -e "${c_red}Installation incomplète$c_" + exit 1 +else + echo -e "${c_green}PlaySMS est accessible via l'URL $http://$DOMAIN$c_" + exit 0 +fi + diff --git a/.install/ssl.sh b/.install/ssl.sh index 31b95a5..f5d51de 100755 --- a/.install/ssl.sh +++ b/.install/ssl.sh @@ -6,7 +6,19 @@ MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized ### Vars #DOMAIN=g1sms-blois-2.p2p.legal args=$@ -[[ "$args" =~ "type=" ]] && DOMAIN=$(echo "$args" | grep "\ diff --git a/.install/templates/4a/daemon.sh b/.install/templates/4a/daemon.sh new file mode 100755 index 0000000..37cac37 --- /dev/null +++ b/.install/templates/4a/daemon.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# Configure this (use absolute path) +PHP=/usr/bin/php # php cli path +DAEMON=/var/www/kalkun/scripts/daemon.php # daemon.php path + +# Execute +$PHP $DAEMON diff --git a/.install/templates/4a/database.php b/.install/templates/4a/database.php new file mode 100644 index 0000000..1b25db5 --- /dev/null +++ b/.install/templates/4a/database.php @@ -0,0 +1,58 @@ + .install/.OS @@ -88,13 +87,15 @@ fi repOld=$repOption [[ -z $repOption ]] && echo -e "${c_yellow}Voulez-vous installer les modules complémentaires de copylaradio ? (o/n)$c_" && read repOption -[[ $repOption =~ ^(o|1|yes|options|a|all)$ ]] && .install/3-install_copylaradio.sh; repOption=$repOld -[[ -z $repOption ]] && echo -e "${c_yellow}Voulez-vous installer l'interface web playSMS ? (o/n)$c_" && read repOption -[[ $repOption =~ ^(o|1|yes|options|a|all)$ ]] && .install/4-install_playsms.sh; repOption=$repOld +if [[ $repOption =~ ^(o|1|yes|options|a|all)$ ]]; then $MY_PATH/.install/3-install_copylaradio.sh || err=1; fi; repOption=$repOld +[[ -z $repOption ]] && echo -e "${c_yellow}Voulez-vous installer l'interface web Kalkun ? (o/n)$c_" && read repOption +if [[ $repOption =~ ^(o|1|yes|options|a|all)$ ]]; then isKalkun=1; $MY_PATH/.install/4a-install_kalkun.sh || err=1; fi; repOption=$repOld +[[ -z $repOption && -z $isKalkun ]] && echo -e "${c_yellow}Voulez-vous installer l'interface web playSMS ? (o/n)$c_" && read repOption +if [[ $repOption =~ ^(o|1|yes|options|a|all)$ ]]; then $MY_PATH/.install/4b-install_playsms.sh || err=1; fi; repOption=$repOld if [[ $err ]]; then - echo -e "---\n${c_red}L'installation n'est mal déroulé =($c_" + echo -e "---\n${c_red}L'installation générale n'est mal déroulé =($c_" else - echo -e "---\n${c_green}L'installation de votre noeud G1SMS est terminé !\nBienvenue à bord =)$c_" + echo -e "---\n${c_green}Félécitation ! L'installation de votre noeud G1SMS s'est terminé avec succès !\nBienvenue à bord =)$c_" fi exit 0 diff --git a/test.sh b/tests/test.sh similarity index 100% rename from test.sh rename to tests/test.sh From 7b18a29c7050541e7bef36bbe6ad6250bac751b9 Mon Sep 17 00:00:00 2001 From: poka Date: Sun, 15 Dec 2019 01:55:15 +0000 Subject: [PATCH 02/26] Improve error management in install. Finish Kalkun install OK --- .install/1-install_requirements.sh | 42 +++-- .install/3-install_copylaradio.sh | 2 +- .install/4a-install_kalkun.sh | 57 ++++--- .install/ssl.sh | 18 +- .install/templates/{5 => 3}/default | 0 .install/templates/4a/kalkun.sql | 331 ++++++++++++++++++++++++++++++++++++ .install/templates/4a/mysql.sql | 12 -- install.sh | 17 +- 8 files changed, 410 insertions(+), 69 deletions(-) rename .install/templates/{5 => 3}/default (100%) create mode 100644 .install/templates/4a/kalkun.sql diff --git a/.install/1-install_requirements.sh b/.install/1-install_requirements.sh index 602d579..6db0560 100755 --- a/.install/1-install_requirements.sh +++ b/.install/1-install_requirements.sh @@ -5,70 +5,76 @@ MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized OS=$(head -n1 $MY_PATH/.OS) isARM=$(cat $MY_PATH/.OS | grep YES) +unset err # Basics sudo apt update +echo -e "${c_yellow}Mise à jours des prérequis...$c_" sudo apt install curl jq zip unzip htop tree ntpdate gnupg ssmtp mpack imagemagick qrencode bc -y # Silkaj + Duniterpy silkaj() { + echo -e "${c_yellow}Installation de Silkaj...$c_" libsodium=$(sudo apt search libsodium 2>/dev/null | grep -v -E "header|debug symbols" | grep "Network communication" -B1 | head -n1 | awk -F '/' '{ print $1 }') [[ $libsodium =~ " " ]] && libsodium=$(echo $libsodium | awk '{ print $2 }') - sudo apt install python3-pip $libsodium -y || err=1 - pip3 install duniterpy || err=1 - pip3 install silkaj --user || err=1 + sudo apt install python3-pip $libsodium -y || err+="Install python3 and $libsodium" + pip3 install duniterpy || err+="Install duniterpy" + pip3 install silkaj --user || err+="Install Silkaj" } # Install IPFS ipfs() { + echo -e "${c_yellow}Installation d'IPFS...$c_" [[ -f /usr/local/bin/ipfs ]] && sudo service ipfs stop if [[ $isARM ]]; then - wget https://dist.ipfs.io/ipfs-update/v1.5.2/ipfs-update_v1.5.2_linux-arm.tar.gz -O $MY_PATH/ipfs-update.tar.gz || err=1 + wget https://dist.ipfs.io/ipfs-update/v1.5.2/ipfs-update_v1.5.2_linux-arm.tar.gz -O $MY_PATH/ipfs-update.tar.gz || err+="Download ipfs-update" else - wget https://dist.ipfs.io/ipfs-update/v1.5.2/ipfs-update_v1.5.2_linux-amd64.tar.gz -O $MY_PATH/ipfs-update.tar.gz || err=1 + wget https://dist.ipfs.io/ipfs-update/v1.5.2/ipfs-update_v1.5.2_linux-amd64.tar.gz -O $MY_PATH/ipfs-update.tar.gz || err+="Download ipfs-update" fi echo "INSTALL ipfs-update" - sudo tar -xvzf $MY_PATH/ipfs-update.tar.gz -C /usr/src/ || err=1 + sudo tar -xvzf $MY_PATH/ipfs-update.tar.gz -C /usr/src/ || err+="Untar ipfs-update" rm $MY_PATH/ipfs-update.tar.gz cd /usr/src/ipfs-update/ - sudo ./install.sh || err=1 + sudo ./install.sh || err+="Install ipfs-update" cd $MY_PATH echo "INSTALL latest ipfs" - sudo ipfs-update install latest || err=1 + sudo ipfs-update install latest || err+="Install IPFS" echo "CREATE SYSTEMD ipfs SERVICE" [[ -f /etc/systemd/system/ipfs.service ]] && sudo rm /etc/systemd/system/ipfs.service sudo cp -f $MY_PATH/templates/1/ipfs.service /etc/systemd/system/ sudo sed -i "s/_USER/$USER/g" /etc/systemd/system/ipfs.service - sudo systemctl daemon-reload || err=1 - sudo systemctl enable ipfs || err=1 + sudo systemctl daemon-reload || err+="Restart IPFS" + sudo systemctl enable ipfs || err+="Enable IPFS daemon" } # Install gammu gammu() { - sudo apt install ppp screen git minicom gammu -y || err=1 + echo -e "${c_yellow}Installation de gammu...$c_" + sudo apt install ppp screen git minicom gammu -y || err+="Install gammu requirements" sleep 1 - sudo apt install gammu-smsd -y || sudo apt install -f || err=1 + sudo apt install gammu-smsd -y || sudo apt install -f || err+="Install gammu" sudo usermod -aG gammu $USER } # Install PHP + MySQL php() { + echo -e "${c_yellow}Installation de PHP et MySQL$c_" if [[ $OS == "buster" ]]; then - sudo apt -y install software-properties-common nginx php php-common php-fpm php-gettext php-gd php-mysql php-curl php-imap php-mbstring php-xml php-cli mariadb-server || err=1 + sudo apt -y install software-properties-common nginx php php-common php-fpm php-gettext php-gd php-mysql php-curl php-imap php-mbstring php-xml php-cli mariadb-server || err+="Install PHP and MySQL" elif [[ $OS == "stretch" ]]; then - sudo apt -y install lsb-release apt-transport-https ca-certificates || err=1 - sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg || err=1 + sudo apt -y install lsb-release apt-transport-https ca-certificates || err+="Install apt-transport-https" + sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg || err+="Download PHP key" echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php7.3.list - sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 || err=1 + sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 || err+="Download PHP key" sudo apt update - sudo apt -y install software-properties-common dirmngr nginx php7.3 php7.3-common php7.3-gettext php7.3-fpm php7.3-gd php7.3-mysql php7.3-curl php7.3-imap php7.3-mbstring php7.3-xml php7.3-cli mariadb-server || err=1 + sudo apt -y install software-properties-common dirmngr nginx php7.3 php7.3-common php7.3-gettext php7.3-fpm php7.3-gd php7.3-mysql php7.3-curl php7.3-imap php7.3-mbstring php7.3-xml php7.3-cli mariadb-server || err+="Install PHP and MySQL" else echo "${c_red}Votre système n'est pas pris en charge par ce script d'installation.$c_" exit 1 @@ -88,7 +94,7 @@ for i in $@; do done if [[ $err ]]; then - echo -e "${c_red}Installation des prérequis incomplète$c_" + echo -e "${c_red}Installation des prérequis incomplète: $err$c_" exit 1 else echo -e "${c_green}Les prérequis ont été correctement installés$c_" diff --git a/.install/3-install_copylaradio.sh b/.install/3-install_copylaradio.sh index 1de3c4f..e45c776 100755 --- a/.install/3-install_copylaradio.sh +++ b/.install/3-install_copylaradio.sh @@ -2,7 +2,7 @@ MY_PATH="`dirname \"$0\"`" # relative MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized -templates="$MY_PATH/templates" +templates="$MY_PATH/templates/3" isARM=$(cat $MY_PATH/.OS | grep YES) diff --git a/.install/4a-install_kalkun.sh b/.install/4a-install_kalkun.sh index 7ea5713..15f4872 100755 --- a/.install/4a-install_kalkun.sh +++ b/.install/4a-install_kalkun.sh @@ -19,7 +19,6 @@ DOMAIN=$KSMS_DOMAIN $MY_PATH/1-install_requirements.sh php ## Create database - if [[ $(sudo mysql -e "select * from mysql.user;" | grep gammu) ]]; then pwdDB=$(cat /etc/gammu-smsdrc | grep "password" | grep -v "# " | awk '{ print $3 }') else @@ -28,28 +27,37 @@ else fi if [[ ! $(sudo mysql -e "show databases;" | grep gammu) ]]; then + echo -e "${c_yellow}Création de la base de donnée...$c_" sudo mysql -e "CREATE DATABASE gammu" sudo mysql -e "GRANT ALL PRIVILEGES ON gammu.* TO 'gammu'@'localhost';" sudo mysql -e "FLUSH PRIVILEGES;" fi - -[[ ! $(sudo mysql gammu -e "SHOW TABLES LIKE 'outbox';") ]] && sudo mysql gammu < $MY_PATH/templates/4a/mysql.sql || err=1 +if [[ -z $(sudo mysql gammu -e "SHOW TABLES LIKE 'outbox';") ]]; then + echo -e "${c_yellow}Importation du dump gammu...$c_" + sudo mysql gammu < $MY_PATH/templates/4a/mysql.sql || err+="Import dump MySQL" +fi +if [[ -z $(sudo mysql gammu -e "SHOW TABLES LIKE 'kalkun';") ]]; then + echo -e "${c_yellow}Importation du dump kalkun...$c_" + sudo mysql gammu < $MY_PATH/templates/4a/kalkun.sql || err+="Import dump Kalkun" +fi ## Clone repo KALKUN [[ -d $MY_PATH/kalkun ]] && sudo rm -rf $MY_PATH/kalkun +echo -e "${c_yellow}Clonage du dépot de Kalkun...$c_" git clone https://github.com/back2arie/Kalkun.git $MY_PATH/kalkun cp $MY_PATH/templates/4a/database.php $MY_PATH/kalkun/application/config/ cp $MY_PATH/templates/4a/daemon.sh $MY_PATH/templates/4a/daemon.php $MY_PATH/kalkun/scripts -sed -i "s/_PWD/$pwdDB/g" $MY_PATH/kalkun/application/config/database.php || err=1 -echo "debug 1" -sed -i "s/_DOMAIN/$DOMAIN/g" $MY_PATH/templates/4a/daemon.php || err=1 +sed -i "s/_PWD/$pwdDB/g" $MY_PATH/kalkun/application/config/database.php || err+="Sed database password" +sed -i "s/_DOMAIN/$DOMAIN/g" $MY_PATH/templates/4a/daemon.php || err+="Sed domaine to daemon.php" + +# touch $MY_PATH/kalkun/install ## Place le dossier kalkun dans /var/www/ [[ -d /var/www/kalkun ]] && sudo rm -rf /var/www/kalkun -sudo mv $MY_PATH/kalkun /var/www/ || err=1 -sudo chown -R www-data:www-data /var/www/kalkun || err=1 +sudo mv $MY_PATH/kalkun /var/www/ || err+="Move kalkun to /var/www" +sudo chown -R www-data:www-data /var/www/kalkun || err+="Chown www-data to kalkun" sudo chmod u+x /var/www/kalkun/scripts/* ## Add daemon launcher in sms_received.sh @@ -57,40 +65,47 @@ sudo chmod u+x /var/www/kalkun/scripts/* ## Active gammu in MySQL mode if [[ $(grep "service = files" /etc/gammu-smsdrc) ]]; then - sudo sed -i "/^service = files/a service = sql\ndriver = native_mysql\nhost = localhost\nuser = gammu\npassword = $pwdDB\ndatabase = gammu" /etc/gammu-smsdrc || err=1 - sudo sed -i "/service = files/d" /etc/gammu-smsdrc || err=1 - $MY_PATH/../debug/gammu-restart.sh || err=1 + echo -e "${c_yellow}Activation de gammu-smsd en mode MySQL...$c_" + sudo sed -i "/^service = files/a service = sql\ndriver = native_mysql\nhost = localhost\nuser = gammu\npassword = $pwdDB\ndatabase = gammu" /etc/gammu-smsdrc || err+="Sed gammu-smsd" + sudo sed -i "/service = files/d" /etc/gammu-smsdrc || err+="Sed delete in gammu-smsd" + $MY_PATH/../debug/gammu-restart.sh || err+="Restart gammu" fi ## Config NGINX +echo -e "${c_yellow}Configuration de Nginx...$c_" [[ ! -d /etc/nginx/def_conf ]] && sudo mkdir /etc/nginx/def_conf/ -sudo cp $MY_PATH/templates/rproxy/proxypass.conf /etc/nginx/def_conf/ || err=1 -sudo cp $MY_PATH/templates/4a/kalkun.conf /etc/nginx/conf.d/ || err=1 -sudo sed -i "s/_DOMAIN/$DOMAIN/g" /etc/nginx/conf.d/kalkun.conf || err=1 +sudo cp $MY_PATH/templates/rproxy/proxypass.conf /etc/nginx/def_conf/ || err+="Copy proxypass.conf" +sudo cp $MY_PATH/templates/4a/kalkun.conf /etc/nginx/conf.d/ || err+="Copy kalkun.conf" +sudo sed -i "s/_DOMAIN/$DOMAIN/g" /etc/nginx/conf.d/kalkun.conf || err+="Sed domain in kalkun.conf" ## Active SSL [[ ! $noask ]] && printf "${c_yellow}Voulez-vous installer et activer un certificat SSL maintenant pour $DOMAIN ? (o/n) $c_" && read askSSL if [[ $askSSL =~ ^(o|y|yes|oui|Y|O|YES)$ ]]; then - $MY_PATH/ssl.sh certif APP=kalkun DOMAIN=$DOMAIN || err=1 + if sudo test ! -f /etc/letsencrypt/live/$DOMAIN/fullchain.pem; then + $MY_PATH/ssl.sh certif APP=kalkun DOMAIN=$DOMAIN || err+="Create SSL certification" + fi if sudo test -f /etc/letsencrypt/live/$DOMAIN/fullchain.pem; then - $MY_PATH/ssl.sh on APP=kalkun DOMAIN=$DOMAIN || err=1 + $MY_PATH/ssl.sh on APP=kalkun DOMAIN=$DOMAIN || err+="Enable SSL certification" else echo -e "${c_red}Une erreur s'est produite, basculement vers le mode non SSL$c_" - $MY_PATH/ssl.sh off APP=kalkun DOMAIN=$DOMAIN || err=1 + $MY_PATH/ssl.sh off APP=kalkun DOMAIN=$DOMAIN || err+="Disable SSL certification" fi http=https - sudo sed -i "s/http/https/g" /var/www/kalkun/scripts/daemon.php || err=1 + sudo sed -i "s/http/https/g" /var/www/kalkun/scripts/daemon.php || err+="Sed http to https in daemon.php" else - $MY_PATH/ssl.sh off APP=kalkun DOMAIN=$DOMAIN || err=1 + $MY_PATH/ssl.sh off APP=kalkun DOMAIN=$DOMAIN || err+="Disable SSL certification" http=http fi -sudo service nginx restart || err=1 +echo -e "${c_yellow}Redémarrage de Nginx...$c_" +sudo service nginx restart || err+="Restart Nginx" +echo -e "${c_yellow}Redémarrage de gammu-smsd...$c_" +$MY_PATH/../debug/gammu-restart.sh || err+="Restart gammu" if [[ $err ]]; then - echo -e "${c_red}Installation incomplète$c_" + echo -e "${c_red}Installation incomplète: $err$c_" exit 1 else echo -e "${c_green}Kalkun est accessible via l'URL $http://$DOMAIN$c_" diff --git a/.install/ssl.sh b/.install/ssl.sh index f5d51de..84ea3aa 100755 --- a/.install/ssl.sh +++ b/.install/ssl.sh @@ -4,8 +4,8 @@ MY_PATH="`dirname \"$0\"`" # relative MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized ### Vars -#DOMAIN=g1sms-blois-2.p2p.legal -args=$@ +args=$(echo $@ | tr " " "\n") + if [[ "$args" =~ "DOMAIN=" ]]; then DOMAIN=$(echo "$args" | grep "\ Date: Sun, 15 Dec 2019 23:24:16 +0000 Subject: [PATCH 03/26] Add wvdial to requirements --- .install/1-install_requirements.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.install/1-install_requirements.sh b/.install/1-install_requirements.sh index bb13f9b..b3642a4 100755 --- a/.install/1-install_requirements.sh +++ b/.install/1-install_requirements.sh @@ -54,7 +54,7 @@ ipfs() { # Install gammu gammu() { echo -e "${c_yellow}Installation de gammu...$c_" - sudo apt install ppp screen git minicom gammu -y || err+="Install gammu requirements" + sudo apt install wvdial ppp screen git minicom gammu -y || err+="Install gammu requirements" sleep 1 sudo apt install gammu-smsd -y || sudo apt install -f || err+="Install gammu" From 8647b941d6eda5c18ecdfedcd72501d8c6844585 Mon Sep 17 00:00:00 2001 From: poka Date: Sun, 15 Dec 2019 23:27:06 +0000 Subject: [PATCH 04/26] Add kalkun script exectution if exist iin sms_received.sh --- sms_received.sh | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/sms_received.sh b/sms_received.sh index 7ad4f64..2b4b461 100755 --- a/sms_received.sh +++ b/sms_received.sh @@ -6,7 +6,7 @@ # # G1sms+ est totalement décentralisé! Il peut être fait de multiples SWARM de Services dont les codes évoluent de façon décentralisé. # Puis se mettent à jour autour des $ADMINPHONE par consensus d'utilisateurs ;) -# +# # Log => tail -f /tmp/g1sms.log -n 200 # gammu => tail -f /tmp/smsd.log -n 200 # @@ -16,16 +16,20 @@ # # Utiliser la commande ./search fournie pour fouiller dans le code, mais tout est ordonnancé d'ici, donc vous êtes au bon endroit pour commencer à farfouiller. ############################################################################### -# EN FAISANT PARTIE DU SWARM G1sms+ VOUS VOUS ENGAGEZ A ASSURER LA SECURITE +# EN FAISANT PARTIE DU SWARM G1sms+ VOUS VOUS ENGAGEZ A ASSURER LA SECURITE # PHYSIQUE ET INFORMATIQUE DE VOTRE NOEUD ET NE PAS INTRODUIRE DE CODE MALVEILLANT # DANS LE GROUPE SI VOUS ETES AMENES A EN PROPOSER UNE MISE A JOUR. -# UNE COMMISSION EST PERCU SUR CERTAINS TRANSFERTS. +# UNE COMMISSION EST PERCU SUR CERTAINS TRANSFERTS. # ELLE EST PROVISION EN CAS DE FRAUDE ET SA REATRIBUTION POURRA EVOLUER... # # Author: Fred (support@qo-op.com) # Version: 0.1 # License: GPL (http://www.google.com/search?q=GPL) ################################################################################ + +# Execute Kalkun daemon +[[ -f /var/www/kalkun/scripts/daemon.sh ]] && /var/www/kalkun/scripts/daemon.sh + export YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) export CHEMIN="/home/$YOU/G1sms+" cd $CHEMIN @@ -55,7 +59,7 @@ log "#############################################" security ################################################################## -# Refresh All peers SWARM Wallets. +# Refresh All peers SWARM Wallets. ################################################################## ipfs_swarm_wallets_refresh @@ -109,9 +113,9 @@ case "$CMD" in else ./shell/sms_ERROR.sh "$PHONE" "ex:: VIR 100 mot5678 = Envoyer 100 $UNIT au portefeuille G1sms+ 'mot5678' (On peut aussi utiliser le pseudo d'un Membre)" & fi - ;; + ;; REC) - # ex: "REC 2000 John J 12" (Virer 2000 UNIT au G1sms+ wallet de John pour les 12 prochains jours) + # ex: "REC 2000 John J 12" (Virer 2000 UNIT au G1sms+ wallet de John pour les 12 prochains jours) AMOUNT=$(echo "$TEXT" | awk '{print $2}' | grep -E "^\-?[0-9]+$") VIRDEST=$(echo "$TEXT" | awk '{print $3}' | grep -E "([A-Za-z0-9\-\_]+$)") PERIOD=$(echo "$TEXT" | awk '{print toupper($4)}' | grep -E "([A-Za-z0-9\-\_]+$)") @@ -119,7 +123,7 @@ case "$CMD" in if [[ "$VIRDEST" != "" && "$AMOUNT" != "" && "$PERIOD" != "" && "$TIME" != "" ]]; then ./shell/sms_REC.sh "$PHONE" "$VIRDEST" "$AMOUNT" "$PERIOD" "$TIME" & else - ./shell/sms_ERROR.sh "$PHONE" "ex:: REC 20 Fred M 12 => Virer 20 $UNIT au portefeuille G1sms+ de Fred pendant 12 Mois (Choisir la période: J,S,M,A)." & + ./shell/sms_ERROR.sh "$PHONE" "ex:: REC 20 Fred M 12 => Virer 20 $UNIT au portefeuille G1sms+ de Fred pendant 12 Mois (Choisir la période: J,S,M,A)." & fi ;; C|S|SOLDE) @@ -165,7 +169,7 @@ case "$CMD" in if [[ "$VAL" != "" ]]; then ./shell/sms_G1TAG.sh "$PHONE" "$VAL" "$NUM" & else - ./shell/sms_ERROR.sh "$PHONE" "ex:: TAG 2 12 => Créer 12 G1Tag de 2 G1" & + ./shell/sms_ERROR.sh "$PHONE" "ex:: TAG 2 12 => Créer 12 G1Tag de 2 G1" & fi ;; U|UNIT) @@ -189,7 +193,7 @@ case "$CMD" in exit ;; ADMIN) - # If Phone is ADMIN + # If Phone is ADMIN if [[ "$PHONE" == "$ADMINPHONE" ]]; then CMD=$(echo "$TEXT" | awk '{print toupper($2)}') PARAM=$(echo "$TEXT" | awk '{print substr($0,index($0,$3))}') From 975963b9b6577b6c44d7036b0e5bafd5410c2ae3 Mon Sep 17 00:00:00 2001 From: qo-op Date: Tue, 17 Dec 2019 11:51:13 +0100 Subject: [PATCH 05/26] Tag Reader G1Tx --- _chain | 2 +- _comments | 1 + _nanodate | 2 +- _publishkey.gpg | Bin 1288 -> 1288 bytes shell/functions.sh | 5 +- shell/init.sh.old | 79 +++++++++++++++++++++++++++++++ shell/sms_G1TAG.sh | 27 ++++++----- shell/tag_OP.sh | 4 +- shell/tag_READ_X.sh | 55 +++++++++++++-------- shell/tools/G1_TUX_keygen.py | 0 shell/tools/G1_TUX_natools.py | 0 shell/tools/G1_request_cesium_profile.py | 0 shell/tools/matrixKeypad.py | 2 +- shell/tools/matrixKeypad_RPi_GPIO.pyc | Bin 14 files changed, 137 insertions(+), 40 deletions(-) create mode 100755 shell/init.sh.old mode change 100644 => 100755 shell/tools/G1_TUX_keygen.py mode change 100644 => 100755 shell/tools/G1_TUX_natools.py mode change 100644 => 100755 shell/tools/G1_request_cesium_profile.py mode change 100644 => 100755 shell/tools/matrixKeypad_RPi_GPIO.pyc diff --git a/_chain b/_chain index 33d4fcc..c021b22 100755 --- a/_chain +++ b/_chain @@ -1 +1 @@ -Qmad8nh1sLJJS8UtyXQJ2GzYrv768dDsBfwhtFyBjXh8Z3 +QmRd3LFiGbA8s17vsYdwWftSnEnnEQGzAzCEPbJBLDrXEf diff --git a/_comments b/_comments index 9cc3739..d7fd648 100755 --- a/_comments +++ b/_comments @@ -172,3 +172,4 @@ OK 2019-12-14: COMMENT 2019-12-14: 2019-12-14: +2019-12-17: Better G1Tx diff --git a/_nanodate b/_nanodate index d0acc79..ae44054 100755 --- a/_nanodate +++ b/_nanodate @@ -1 +1 @@ -1576284752579254475 +1576547374550330601 diff --git a/_publishkey.gpg b/_publishkey.gpg index 8927cc32575f599cf1239609f08309603c3c6fc6..9e229543f35e4b8b1aaf9a92855f6bae87534489 100755 GIT binary patch literal 1288 zcmV+j1^4=l4Fm}T0;bIgR`ao^9>CJ-0Se*$|7I8|a0Hmuj0#JKn7nH4RnrA`24H#5LIEaIipL^Q^2;VAUAt z@Q_xfe4>#BMQwW;pE|;NHr_$zHBBnbd|;pafQ^MO^rbNWu#<9hVVzVjkhkQuti88W zSYQ-`#OdE?F3C;kls^qAL|u@!al@_xK6HZvCG|~J%{hK~Hw!FnGX6tlLCbb-cphX< zySwJ%LoR01AG)OnjIGemk6iDtUCXa5>Z>S+v;JF!YOw$RB8zW(ox#}u@*FW3LO8j$f}RmZzZ zN_r{W_{uR_$ekb`o`ag6`YCSkilq6wD|>b!#PjwWDqBx2&(gbOS#t5)<5}@Yd*oBKnJ(b_!V!kbuGE4i{gOu)q4j_>Qn5Qyf^8`K$wvOoA3Iv(8|wcn@T3dOD(b< z2GyVa4M-o}U;$4{<7V7C!Ooesd-kaT5kGOFYxg^Js2nM;xe?@>BM{7?Waf-ub+nB`cT(x2Z$iCi6WF6@hU5u5u3J*{y*u}UYEPtRFz31RvZt3W_$a~|$-s0%AedTu%Q3cd z>4@U%B02j~%M?m;;a`Q`J+75%=Ku{jpr_vbx1!k2UTf66Qmkr=mW={dY;>-3l&Im0 z4EaA{DMyD_IeH?)3`ji?2uQpm?3_OK)IBJ%??Lsj$?-I)QJSTmycAQA@)M7GyhMmM z8?bx%$cIrG=?e%&_5BWKL?;S6Z2H%VbedfLd1DsR3@+Z-2n5%gESl1j1LT?1Tv!wO+o?ooi%S_$s@V=pqI@ zS(7CF5kv(+N=$IIj;S4 yLAzZG%Ncj^3LrtdKCE+wfEV967QKu*+66{P!;KiSaUE@Q(_@~S5bdw|)Zp zohX7+Oldp=hS`ie3$5X=xjS5`1&K;snAk5?x(3qVkW95ieBDSd-f7cR*Q4c+#yPvX z+M#=b!b6uvI)tt4({PqLCHBX8N%EX@vWMaH6FQO1kmJoK&@C*;tK)zoy0?$Yt7w6h;HXj(+ZT~fFE116La7t@gcZIG)7RD^lSF0&ZL?UIEl zZhvjP7{9z&9_wqmZu=)GX*0iUI81FJJOGY-`EJF2ve`fNXr!F}nr7>=!5B_CCUIZx zD?!+l=jla{MjW^npADhf*59u`%TIGpd!OzC2eUBSA>hI8-V$$e(|)V}6~vl;fr{9o z>Ixk8QX>{29Jp{@3v_WI(naFZL#&+)6u3ak?-hd@whqRrtu4Z`F1yYJe)`SGTZ}oH z$ga1OE6u?maxyD0>v>AyZX?)%-oo#}MBAC6YScpsKe^eP1@U@VKTijY`$`eJ)14yk zRQnr;ih7vk%+SnU#qYttdK$8|%7oTECdDyPwHE;9*}&mW-Yhcih|vVLCQqAz%Iqa zN`fBbY|boZz%}85FskzKldD*o(El=0+8aX}iAaLEz)w1Wf&^-O9FbPASclp@4pKu=w{b;Yk> /tmp/g1sms.log + fi +} + + +################################################################################################################################### +fn_exists() { + # appended double quote is an ugly trick to make sure we do get a string -- if $1 is not a known command, type does not output anything + [ `type -t $1`"" == 'file' ] +} +# ATOMATIC gammu-smsd-inject desactivation if no gammu is installed on system +if ! fn_exists gammu-smsd-inject; then +log ":p) DESACTIVATION ENVOI DE SMS .............." +function gammu-smsd-inject () { + log "$PHONE: >>> SENDING SMS $4 TO $2 " +} +else +export G1SMS="YES" +fi + + + export YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) + export CHEMIN="/home/$YOU/G1sms+" + cd $CHEMIN + ################################################################## + # Activate logging to /tmp/g1sms.log (YES/NO) + export DOLOG="YES" + export CPERROR="NOYES" + ################################################################## + # Country Node Phone international prefix (TODO Worldwide) + export COUNTRY="+33" + ################################################################## + # DU has a G1 value changed every 6 month! + # ./_DU Updated by cron_CODE.backup.sh + if [[ -f "./_DU" ]]; then export DUFACTOR=$(bc <<< "scale=2; $(cat "./_DU") / 100"); else log "__SUB:init.sh: FAILING TO FIND ./_DU EXIT!!!"; exit; fi + ################################################################## + # Choose Default Unit: G1, DU, LOVE (DU cents), ZEN (G1 cents) + export COIN="G1" + ################################################################## + # Limit and commission values + export LIMIT=2 # Solde minimum = 2 G1 + # FIXED COMMISSION SYSTEM + export COMMISSION=1 # transaction commission amount (G1) + export BILLCOM=20 + ################################################################## + # COMMISSION PARTS FROM TX FOR NODE & G1SMS NETWORK + # PART COMMISSION SYSTEM + export SWARMCOMM=10 + # TODO: NODE G1sms Wallet can receive rewards from SWARM or WALLETS/FILES + export NODECOMM=10 + ################################################################## + # SMS SIM Card Phone Number + export MASTERPHONE="+33651136520" + export ADRESSE="G1_Fablab_Toulouse" + export G1DAB="NO" + ################################################################## + # ADMIN COMMAND PHONE ORIGIN + export ADMINPHONE="+33647683646" + export ADMINPSEUDO="Fred" + ################################################################## + # DUNITER/CESIUM+ DEFAULT SERVERS + export DUNITER="https://g1.duniter.org" + export CESIUM="https://g1.data.le-sou.org" + + # TODO Use latest Silkaj from "sudo fredp3 install silkaj" + # export SILKAJ="/usr/local/bin/silkaj" + source $CHEMIN/shell/init_keys.sh + diff --git a/shell/sms_G1TAG.sh b/shell/sms_G1TAG.sh index 2951d25..e022f48 100755 --- a/shell/sms_G1TAG.sh +++ b/shell/sms_G1TAG.sh @@ -49,11 +49,11 @@ if [[ $UNKNOWN == "unknown" ]]; then fi ## NEEDED FOR Avatar + GeoPoint -if [[ ! $PASSENGER && "$MEMBER" == "" ]]; then - sms_ERROR "$PHONE" "Aucun membre associé à votre Portefeuille!? Envoyer N suivi de votre Pseudo membre pour activer la création de G1Tag..." - log "__SUB:sms_G1TAG.sh: Aucun membre associé" - exit -fi +#if [[ ! $PASSENGER && "$MEMBER" == "" ]]; then +# sms_ERROR "$PHONE" "Aucun membre associé à votre Portefeuille!? Envoyer N suivi de votre Pseudo membre pour activer la création de G1Tag..." +# log "__SUB:sms_G1TAG.sh: Aucun membre associé" +# exit +#fi ########################################################### # CALCULATE if wallet have enough for VIR+PERCENT @@ -115,16 +115,19 @@ log "__SUB:sms_G1TAG.sh: CREATE $NUMBER x $2 $UNIT G1Tag(s) for $MEMBER ($PHONE) c=0 while [[ $c -lt $NUMBER ]]; do ((c++)) - # Create Unique SWARM G1tag! - AA=$(./shell/diceware.sh 6 | xargs); RR=$(echo ${AA} | sed s/\ //g ); PR=$(echo ${AA} | cut -d ' ' -f 1 ); - while [ -d "./wallets_swarm/TAG/${RR}" ]; do - AA=$(./shell/diceware.sh 6 | xargs); - RR=$(echo ${AA} | sed s/\ //g ); + # Nom du G1Tag imprimé du le QRCode RJ + AA=$(./shell/diceware.sh 6 | xargs); # Nom = Diceware de 6 mots + RR=$(echo ${AA} | sed s/\ //g ); # Nom concaténé + PR=$(echo ${AA} | cut -d ' ' -f 1 ); # Prénom du G1Tag + # Create Unique G1tag! + while [[ $(ls "./wallets_swarm/.Qm*/TAG/${RR}") ]]; do + AA=$(./shell/diceware.sh 6 | xargs); RR=$(echo ${AA} | sed s/\ //g ); PR=$(echo ${AA} | cut -d ' ' -f 1 ); done + # Clef de chiffrage PGP imprimée sur le QRCode BJ BB=$(date +%N | sha256sum | base64 | head -c 32) #YjY4MDc3OTVjNmUxN2JhYWVjYmU3MDcy # BB=$(openssl rand -base64 32 | base64) #Yk8yMnVtdzZmendJbHNoK2Q0b0liakRpNHNJUk9UQW5Dd042cFdDODlJTT0K -# G1Tag init +# G1Tag init : Nom et usage des fichiers du G1Tag # TODO CHECK _nanodate to detect bad nodes/tx behaviour... and banish them) TAGDATE="./TAG/${RR}/TAG_nanodate" # Nanodate notification (ntpdate in init.sh for NODE sync in case of TAGNID="./TAG/${RR}/TAG_nodeid" # G1sms+ NODE IPFS ID managing that G1Tag @@ -153,7 +156,7 @@ TAGCHAIN="./TAG/${RR}/TAG_chain" # contains IPFS current ipfs hash #################################################### # IPFS files are created and calculated immutable I #################################################### - # A or R is the Human readable G1tag ID (kind of TAG pubkey) + # A or R is Human readable G1tag Name echo "${AA}" > "$TAGID" echo "0" > "$TAGN" echo "${NANODATE}" > "$TAGDATE" diff --git a/shell/tag_OP.sh b/shell/tag_OP.sh index 4a47744..a7075de 100755 --- a/shell/tag_OP.sh +++ b/shell/tag_OP.sh @@ -69,7 +69,7 @@ if [[ $FINALSOURCE -lt 0 ]]; then echo "__SUB:tag_OP.sh: KO. La valeur de ce G1T if [[ -f $KEYFILE && ! -f "/home/$YOU/.ipfs/keystore/$JSOURCERR" ]]; then ./shell/natools.py decrypt -k "$KEYFILE" -i "$JSOURCEPUBLISHKEY" -o "/home/$YOU/.ipfs/keystore/$JSOURCERR" else - if [[ ! -f $KEYFILE ]] then + if [[ ! -f $KEYFILE ]]; then echo "__SUB:tag_OP.sh: KO. La clef de dévérouillage pour $JSOURCERR est inexistante. Contact: https://g1sms.fr" fi fi @@ -90,7 +90,7 @@ FINALDEST=$(echo "${JDESTVALUE} + ${VALUE}" | bc -l) if [[ -f $KEYFILE && ! -f "/home/$YOU/.ipfs/keystore/$JDESTRR" ]]; then ./shell/natools.py decrypt -k "$KEYFILE" -i "$JDESTPUBLISHKEY" -o "/home/$YOU/.ipfs/keystore/$JDESTRR" else - if [[ ! -f $KEYFILE ]] then + if [[ ! -f $KEYFILE ]]; then echo "__SUB:tag_OP.sh: KO. La clef de dévérouillage pour $JDESTRR est inexistante. Contact: https://g1sms.fr" fi fi diff --git a/shell/tag_READ_X.sh b/shell/tag_READ_X.sh index 5e101c5..538939c 100755 --- a/shell/tag_READ_X.sh +++ b/shell/tag_READ_X.sh @@ -27,14 +27,16 @@ if [ ! -f $MASTERKEYFILE ]; then echo "ERREUR CLEF DECHIFFRAGE!"; exit; fi # DOUCHETTE ES TU LA? if [ ! $G1TX ]; then echo "Branchez votre lecteur de QR code!"; exit; fi ./shell/tools/4LETTER.scroll.py "G1TX START" -./shell/timeout.sh -t 2 ./shell/tools/4LETTER.spinner.py - +./shell/tools/4LETTER.clock.py & +clockpid=$! # TABLEAU MEMOIRE DE SCAN declare -a act declare -a obj declare -a val cat /dev/ttyACM0 | while read line; do + kill $clockpid + lon=${#line} pref=$(echo $line | cut -d ":" -f 1) qrvalue=$(echo $line | cut -d ":" -f 2) @@ -55,7 +57,7 @@ cat /dev/ttyACM0 | while read line; do FID=$(echo $ID | awk '{print toupper($1)}') RR=$(echo $ID | sed s/\ //g) - ./shell/tools/4LETTER.scroll.py "G1TAG $FID READ" + ./shell/tools/4LETTER.scroll.py "G1TAG $FID >" RVALUE=$(su $YOU -c "ipfs cat /ipns/$J/TAG_amount"); CURRENCY=$(su $YOU -c "ipfs cat /ipns/$J/TAG_currency" | awk '{print tolower($1)}') if [[ "$CURRENCY" == "zen" ]]; then CUR="zène"; else CUR=$CURRENCY; fi # Correction du défaut de prononciation. @@ -65,7 +67,7 @@ cat /dev/ttyACM0 | while read line; do else G1VAL=$(bc -l <<< "scale=2; $RVALUE / 100" | cut -d '.' -f 1) log "__SUB:tag_READ_X.sh: G1Tag $FID. Valeur $RVALUE $CURRENCY = $G1VAL G1" - ./shell/tools/4LETTER.scroll.py "$RVALUE ZEN *** $RVALUE ZEN" + ./shell/tools/4LETTER.scroll.py "$RVALUE ZEN *** $G1VAL G1" fi cmd="RJ" CASHBACK="" @@ -85,7 +87,7 @@ cat /dev/ttyACM0 | while read line; do FID=$(echo $ID | awk '{print toupper($1)}') RR=$(echo $ID | sed s/\ //g) - ./shell/tools/4LETTER.scroll.py "G1TAG $FID >>TX>> " + ./shell/tools/4LETTER.scroll.py "G1TAG [TX] $FID >" BVALUE=$(su $YOU -c "ipfs cat /ipns/$J/TAG_amount") CURRENCY=$(su $YOU -c "ipfs cat /ipns/$J/TAG_currency" | awk '{print tolower($1)}') if [[ "$CURRENCY" == "zen" ]]; then CUR="zène"; else CUR=$CURRENCY; fi # Correction du défaut de prononciation. @@ -110,8 +112,9 @@ cat /dev/ttyACM0 | while read line; do log "__SUB:tag_READ_X.sh: !!!! $FID REC Tag = $BVALUE $CURRENCY" ./shell/tools/4LETTER.scroll.py "G1TAG PASSENGER $BVALUE ZEN" else + G1VAL=$(bc -l <<< "scale=2; $BVALUE / 100" | cut -d '.' -f 1) log "__SUB:tag_READ_X.sh: Ce G1 Tag $FID contient $BVALUE $CURRENCY" - ./shell/tools/4LETTER.scroll.py "$BVALUE ZEN *** $BVALUE ZEN MAX" + ./shell/tools/4LETTER.scroll.py "$BVALUE ZEN *** $G1VAL G1 MAX" fi cmd="BJ" val+=("$BVALUE") @@ -132,21 +135,21 @@ cat /dev/ttyACM0 | while read line; do cmd="G1" val+=("$VALUE") else - log "__SUB:tag_READ_X.sh: ERREUR QR code illisible. longueur $J = ${#J}" if [[ "$VALUE" == "" ]]; then DUNITER=$(./shell/checknodes.sh 'BAN') - echo "ERREUR TIMEOUT. CHANGE SILKAJ SERVER: $DUNITER" + log "__SUB:tag_READ_X.sh: ERREUR TIMEOUT. CHANGE SILKAJ SERVER: $DUNITER" ./shell/tools/4LETTER.scroll.py "ERREUR TIMEOUT SILKAJ" ./shell/timeout.sh -t 1 ./shell/tools/4LETTER.spinner.py CASHBACK="" else + log "__SUB:tag_READ_X.sh: ERREUR QRCODE ILLISIBLE. longueur $J = ${#J}" ./shell/tools/4LETTER.scroll.py "ERREUR QRCODE INCONNU" ./shell/timeout.sh -t 1 ./shell/tools/4LETTER.spinner.py CASHBACK="" fi fi else - ./shell/tools/4LETTER.scroll.py "G1 ${val[0]} / G1 ${val[0]}" + ./shell/tools/4LETTER.scroll.py " 2 X " fi else ./shell/tools/4LETTER.scroll.py "ERREUR QRCODE INCONNU" @@ -159,10 +162,12 @@ cat /dev/ttyACM0 | while read line; do ############################################################### # APRES G1 CASHBACK : G1 Tag BJ WRITE => ENCAISSEMENT if [[ "${cmd}" == "BJ" && "$CASHBACK" != "" && -f /home/$YOU/.ipfs/keystore/${RR} ]]; then - ./shell/tools/4LETTER.scroll.py "ENCAISSEMENT G1TAG" + ./shell/tools/4LETTER.scroll.py "ZEN -> G1" log "__SUB:tag_READ_X.sh: G1 tag de $BVALUE G1 ! /ipns/$J Virement vers $CASHBACK? " - ./shell/tools/4LETTER.scroll.py "VERS PORTEFEUILLE G1" + ./shell/tools/4LETTER.spinner.py & + spinnerpid=$! + # ipfs get G1Tag vers ./TAG/${RR} mkdir -p ./TAG/${RR}; rm -f ./TAG/${RR}/*; chown -R $YOU ./TAG/${RR}/ log "__SUB:tag_READ_X.sh: ipfs get --output=./TAG/${RR} /ipns/$J" @@ -173,16 +178,19 @@ cat /dev/ttyACM0 | while read line; do # Make Silkaj TX G1VAL=$(bc -l <<< "scale=2; $BVALUE / 100" | cut -d '.' -f 1) log "__SUB:tag_READ_X.sh: Silkaj TX $MASTERKEYFILE ($G1VAL) -> $CASHBACK" - PAY=$(./silkaj/silkaj transaction --auth-file -file="$MASTERKEYFILE" --amount=$G1VAL --output=$CASHBACK --comment="[G1sms+] CAPTURE G1Tag $RR" -y) + PAY=$(./silkaj/silkaj transaction --auth-file -file="$MASTERKEYFILE" --amount=$G1VAL --output=$CASHBACK --comment="[G1sms+] G1Tag $RR ZEN -> G1" -y) log "__SUB:tag_READ_X.sh: Silkaj output = $PAY" - if [[ "$(echo $PAY | cut -d '|' -f 1)" == "KO" ]]; then + # Stop 1LETTER.spinner.py + kill $spinnerpid + + if [[ "$(echo $PAY | cut -d '|' -f 1)" == "KO" && "$PAY" != "" ]]; then new=$(./shell/checknodes.sh "BAN") sms_ERROR "$ADMINPHONE" "Il est survenu un problème avec un virement. Retour silkaj: $PAY ... $new"; ./shell/tools/4LETTER.scroll.py "ERREUR SILKAJ ERREUR" else # ENCAISSEMENT G1Tag - ./shell/tools/4LETTER.scroll.py "VIR ${FID} $G1VAL G1 ---) OK" + ./shell/tools/4LETTER.scroll.py "VIR ${FID} $G1VAL G1 -> OK " # CAPTURE / DESTRUCTION du G1 Tag echo "0" > "./TAG/${RR}/TAG_amount" echo "${J}" > "./TAG/${RR}/TAG_ipns" @@ -208,7 +216,7 @@ cat /dev/ttyACM0 | while read line; do J=$(su $YOU -c "ipfs name publish -k ${RR} --quieter /ipfs/${I}") log "__SUB:tag_READ_X.sh: Destruction de ce G1 Tag publish -k ${RR} --quieter /ipfs/${I} :: ipfs ls /ipns/$J" - ./shell/tools/4LETTER.scroll.py "${FID} G1TAG VIDE !! DETRUCTION !!" + ./shell/tools/4LETTER.scroll.py "DETRUIRE G1TAG ${FID}" # CLEAN IPFS keystore: remove NOT created NODE keys SOURCENODEID=$(cat "./TAG/${RR}/TAG_nodeid") @@ -236,14 +244,17 @@ cat /dev/ttyACM0 | while read line; do if [[ "$PASSENGER" != "" ]]; then ./shell/tools/4LETTER.scroll.py "IMPOSSIBLE TAG PASSENGER"; else - # READ KEYBOARD VALUE !!! - COMBIEN=$(./shell/tools/matrixKeypad.py) + ########################################################### + # READ KEYBOARD VALUE !!! 4 DIGIT REMOVING LEADING 0 + COMBIEN=$(./shell/tools/matrixKeypad.py | sed 's/^0*//') if [[ $COMBIEN -le ${val[1]} ]]; then + COMBIENZEN=$(bc -l <<< "$COMBIEN * 100") log "__SUB:tag_READ_X.sh: Transfert de G1 Tag à G1 Tag. $COMBIEN" - ./shell/tools/4LETTER.scroll.py "G1TAG ${FID} TRANSFERT DE $COMBIEN ZEN" - log "__SUB:tag_READ_X.sh: $(./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIEN $MASTERKEYFILE)" + ./shell/tools/4LETTER.scroll.py "G1TAG ${FID} -> TX $COMBIENZEN ZEN *** $COMBIEN G1" + log "__SUB:tag_READ_X.sh: ./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIENZEN $MASTERKEYFILE" + ./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIENZEN "$MASTERKEYFILE" else - ./shell/tools/4LETTER.scroll.py "$COMBIEN DEPASSE ${val[1]} $CUR DU G1TAG ${FID}" + ./shell/tools/4LETTER.scroll.py "ERREUR $COMBIEN > VALEUR DE ${FID} *** ${val[1]} ZEN" fi fi CASHBACK="" @@ -265,9 +276,11 @@ cat /dev/ttyACM0 | while read line; do act=() obj=() val=() + # END OF 2-PASS READ ./shell/timeout.sh -t 2 ./shell/tools/4LETTER.spinner.py fi ./shell/tools/4LETTER.blink.py - + ./shell/tools/4LETTER.clock.py & + clockpid=$! done diff --git a/shell/tools/G1_TUX_keygen.py b/shell/tools/G1_TUX_keygen.py old mode 100644 new mode 100755 diff --git a/shell/tools/G1_TUX_natools.py b/shell/tools/G1_TUX_natools.py old mode 100644 new mode 100755 diff --git a/shell/tools/G1_request_cesium_profile.py b/shell/tools/G1_request_cesium_profile.py old mode 100644 new mode 100755 diff --git a/shell/tools/matrixKeypad.py b/shell/tools/matrixKeypad.py index 492de43..ba1c3d4 100755 --- a/shell/tools/matrixKeypad.py +++ b/shell/tools/matrixKeypad.py @@ -6,7 +6,7 @@ from time import sleep # Initialize the keypad class kp = keypad() -fourletterphat.print_str("ZEN?") +fourletterphat.print_str(" G1?") fourletterphat.show() def digit(): diff --git a/shell/tools/matrixKeypad_RPi_GPIO.pyc b/shell/tools/matrixKeypad_RPi_GPIO.pyc old mode 100644 new mode 100755 From 014634e84077e99468d216c420e6a794b386c5ae Mon Sep 17 00:00:00 2001 From: qo-op Date: Tue, 17 Dec 2019 17:22:06 +0100 Subject: [PATCH 06/26] TAG REFRESH --- shell/cron_G1TAG_REFRESH.sh | 83 +++++++++++++++++++++++++++++++++++++++++++++ shell/cron_MINUTE.sh | 33 ++---------------- shell/init_keys.sh | 2 +- 3 files changed, 86 insertions(+), 32 deletions(-) create mode 100755 shell/cron_G1TAG_REFRESH.sh diff --git a/shell/cron_G1TAG_REFRESH.sh b/shell/cron_G1TAG_REFRESH.sh new file mode 100755 index 0000000..debb381 --- /dev/null +++ b/shell/cron_G1TAG_REFRESH.sh @@ -0,0 +1,83 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +########################################################################################### +# cron_G1TAG_REFRESH.sh +# Scan all TAG created by current $IPFSNODEID +# Update local and Publish it +# Remove too old or empty ones +################################################################## +YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) +IPFSNODEID=$(su $YOU -c "ipfs id -f='\n'") +NANODATE=$(date -u +%s%N) #1569692075385428020 + +# PROTECT from null HASH +for tag in ./wallets/.$IPFSNODEID/TAG/*; do + function rmtag () { + echo "__SUB:cron_G1TAG_REFRESH.sh: rm -Rf ./wallets/.$IPFSNODEID/TAG/${tagj}" + rm -Rf ./TAG/${tagj} + rm -f ./wallets/.$IPFSNODEID/TAG/${tagj} + rm -f ./wallets_swarm/.$IPFSNODEID/TAG/${tagj} + rm -f /home/$YOU/.ipfs/keystore/${tagj} + } + + # Refresh G1Tag created by this NODE + tagj=$(echo $tag | cut -d '/' -f 5) + if [[ "${tagj}" == "" ]]; then echo "__SUB:cron_G1TAG_REFRESH.sh: EMPTY"; continue; fi + echo "__SUB:cron_G1TAG_REFRESH.sh: WORKING ON ${tagj}" + RR=$(./shell/timeout.sh -t 8 su $YOU -c "ipfs cat /ipns/${tagj}/TAG_id | sed s/\ //g"); + if [[ "$RR" == "" ]]; then + echo "__SUB:cron_G1TAG_REFRESH.sh: G1Tag Destroyed !!!??"; + + rmtag + continue; + fi + + # RE-SYNC LOCAL & SWARM G1TAG - TODO Check for G1Tag chain corruption + mv ./TAG/${RR} ./TAG/${RR}.old + mkdir -p ./TAG/${RR} + chown -R $YOU ./TAG/${RR} + su $YOU -c "ipfs get --output=./TAG/${RR} /ipns/${tagj}" + oldtagval=$(cat ./TAG/${RR}.old/TAG_amount) + curtagval=$(cat ./TAG/${RR}/TAG_amount) + oldtagn=$(cat ./TAG/${RR}.old/TAG_n) + curtagn=$(cat ./TAG/${RR}/TAG_n) + oldtagchain=$(cat ./TAG/${RR}.old/TAG_chain) + curtagchain=$(cat ./TAG/${RR}/TAG_chain) + echo "__SUB:cron_G1TAG_REFRESH.sh: ./TAG/$RR VALUE: ($oldtagn) $oldtagval ZEN -> ($curtagn) $curtagval ZEN" + echo "__SUB:cron_G1TAG_REFRESH.sh: $oldtagchain -> $curtagchain" + + rm -Rf ./TAG/${RR}.old + if [[ $curtagval -eq 0 || "$curtagval" == "" ]]; then rmtag; continue; fi + + # SHOULD PUBLISH ONLY MORE THAN 6h NO USE G1TAG + last=$(cat ./TAG/${RR}/TAG_nanodate) + timediff=$( echo "${NANODATE} - ${last}" | bc -l ) + # G1TAG TIME SYNC 21600 milliards de nanosecondes = 6h + if [[ $timediff -gt 21600000000000 ]]; then + + # GET PUBLISHKEY for that G1TAG + if [[ ! -f /home/$YOU/.ipfs/keystore/${RR} ]]; then + echo "__SUB:cron_G1TAG_REFRESH.sh: GET PUBLISHKEY for that G1TAG"; + su $YOU -c "ipfs get -o /home/$YOU/.ipfs/keystore/${RR}.crypt /ipns/$tagj/TAG_publishkey.MASTER.crypt" + if [[ ! -f /home/$YOU/.ipfs/keystore/${RR}.crypt ]]; then log "__SUB:cron_MINUTE.sh: error getting publishkey"; continue; fi + ./shell/natools.py decrypt -k "$MASTERKEYFILE" -i /home/$YOU/.ipfs/keystore/${RR}.crypt -o /home/$YOU/.ipfs/keystore/$RR + rm /home/$YOU/.ipfs/keystore/${RR}.crypt + fi + echo "__SUB:cron_G1TAG_REFRESH.sh: G1Tag PUBLISHKEY OK : /home/$YOU/.ipfs/keystore/${RR}" + + # PUBLISH VERIFIED G1Tag VERSION + I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") + # RECORD TAG_chain And HASH again + echo "$I" > "./TAG/${JDESTRR}/TAG_chain" + I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") + # IPNS $JDESTRR PUBLISH + J=$(su $YOU -c "ipfs name publish -k ${RR} --quieter /ipfs/${I}") + echo "__SUB:cron_G1TAG_REFRESH.sh: G1Tag IPNS PUBLISH" + fi + + +done +################################################################## diff --git a/shell/cron_MINUTE.sh b/shell/cron_MINUTE.sh index 9e0ffe1..483b68f 100755 --- a/shell/cron_MINUTE.sh +++ b/shell/cron_MINUTE.sh @@ -26,7 +26,7 @@ if [[ "$YOU" == "" || "$YOU" == "root" ]]; then echo "BAD IPFS. Aucune installat ipfs_swarm_wallets_refresh "SIMPLE" ################################################################################ -# PRINT G1Tag +# PRINT G1Tag PRINTED FROM ANOTHER NODE # CREATE and REMOVE rr.bin -> done.rr if [[ -d "./wallets_swarm/.$IPFSNODEID/PRINT/" ]]; then log "__SUB:cron_MINUTE.sh: SEARCH NEW PRINT FOR ME .$IPFSNODEID" @@ -74,36 +74,7 @@ fi ################################################################## if [[ "$timebar" == "0300" ]]; then ################################################################## -################################################################## -# Refresh G1Tag created by this NODE -# PROTECT from null HASH -for tag in ./wallets/.$IPFSNODEID/TAG/*; do - tagj=$(echo $tag | cut -d '/' -f 5) - log "__SUB:cron_MINUTE.sh: WORKING ON ${tagj}" - RR=$(su $YOU -c "ipfs cat /ipns/${tagj}/TAG_id | sed s/\ //g"); - if [[ ! $RR && "${tagj}" != "" ]]; then echo "G1 Tag Destroyed"; echo "TODO: rm -Rf ./wallets/.$IPFSNODEID/TAG/${tagj} ???"; continue; fi - - # GET PUBLISHKEY for that G1TAG - su $YOU -c "ipfs get -o /home/$YOU/.ipfs/keystore/${RR}.crypt /ipns/$tagj/TAG_publishkey.MASTER.crypt" - if [[ ! -f /home/$YOU/.ipfs/keystore/${RR}.crypt ]]; then log "__SUB:cron_MINUTE.sh: error getting publishkey"; continue; fi - ./shell/natools.py decrypt -k "$MASTERKEYFILE" -i /home/$YOU/.ipfs/keystore/${RR}.crypt -o /home/$YOU/.ipfs/keystore/$RR - - log "__SUB:cron_MINUTE.sh: G1Tag PUBLISHKEY decrypted and loaded in /home/$YOU/.ipfs/keystore/${RR}" - - # RE-SYNC LOCAL & SWARM G1TAG (TODO Check G1Tag chain validity) - rm -f ./TAG/${RR}/* - su $YOU -c "ipfs get --output=./TAG/${RR} /ipns/${tagj}" - - # PUBLISH VERIFIED G1Tag VERSION - I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") - # RECORD TAG_chain And HASH again - echo "$I" > "./TAG/${JDESTRR}/TAG_chain" - I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") - # IPNS $JDESTRR PUBLISH - J=$(su $YOU -c "ipfs name publish -k ${RR} --quieter /ipfs/${I}") - -done -################################################################## + echo "It is 3 in the morning, or in the night? It depends on your day..." fi ################################################################## diff --git a/shell/init_keys.sh b/shell/init_keys.sh index 515692f..67210aa 100755 --- a/shell/init_keys.sh +++ b/shell/init_keys.sh @@ -47,7 +47,7 @@ if [[ -f ./wallets/.$IPFSNODEID/$IPFSNODEID.nanodate ]]; then last=$(cat ./wallets/.$IPFSNODEID/$IPFSNODEID.nanodate) timediff=$( echo "${NANODATE} - ${last}" | bc -l ) # Get median nanodate before - # NODE TIME SYNC 120 milliards de nanosecondes + # NODE TIME SYNC 120 milliards de nanosecondes = 120s if [[ $timediff -gt 120000000000 ]]; then log "__SUB:ntpdate pool.ntp.org: $timediff $(ntpdate pool.ntp.org)" export NANODATE=$(date -u +%s%N) From c03a3245d6cac7786859c010e85ad04cb00be119 Mon Sep 17 00:00:00 2001 From: poka Date: Tue, 17 Dec 2019 20:02:40 +0100 Subject: [PATCH 07/26] Add contact to database when wallet is created. Remove contact from database where wellet is destroyed --- debug/GSM_POWERKEY.py => GSM_POWERKEY.py | 0 debug/GSM_powerkey.sh => GSM_powerkey.sh | 0 shell/functions.sh | 42 ++++++++++++++++++++++++++++++++ shell/sms_DESTROY.sh | 15 +++++++----- shell/sms_NEW.sh | 12 +++++---- 5 files changed, 58 insertions(+), 11 deletions(-) rename debug/GSM_POWERKEY.py => GSM_POWERKEY.py (100%) rename debug/GSM_powerkey.sh => GSM_powerkey.sh (100%) diff --git a/debug/GSM_POWERKEY.py b/GSM_POWERKEY.py similarity index 100% rename from debug/GSM_POWERKEY.py rename to GSM_POWERKEY.py diff --git a/debug/GSM_powerkey.sh b/GSM_powerkey.sh similarity index 100% rename from debug/GSM_powerkey.sh rename to GSM_powerkey.sh diff --git a/shell/functions.sh b/shell/functions.sh index 4e00c34..7fc456d 100755 --- a/shell/functions.sh +++ b/shell/functions.sh @@ -614,3 +614,45 @@ function move_g1cents (){ # UPDATE MY new ./wallet STATUS to SWARM I=$(ipfs_node_wallets_add) } + + +################################################################################################################################# +# Contact database management +function add_contact(){ + userDB="gammu" + pwdDB=$(cat /etc/gammu-smsdrc | grep "password =" | awk '{ print $3 }' || exit 1) + local sql="mysql -u$userDB -p$pwdDB gammu -e" + + local MEMBERUID=$1 + local PHONE=$2 + + local reqPhoneExist="SELECT * FROM pbk WHERE Number=$PHONE" + + if [[ -z $($sql "$reqPhoneExist") ]]; then + local reqAddContact="INSERT INTO pbk (GroupID, Name, Number, id_user, is_public) VALUES ('-1', '$MEMBERUID', '$PHONE', '1', 'false')" + $sql "$reqAddContact" || exit 1 + else + log "${red}Contact already exist$c_" + fi + +} + +function rm_contact(){ + userDB="gammu" + pwdDB=$(cat /etc/gammu-smsdrc | grep "password =" | awk '{ print $3 }' || exit 1) + local sql="mysql -u$userDB -p$pwdDB gammu -e" + + local MEMBERUID=$1 + local PHONE=$2 + + local reqPhoneExist="SELECT * FROM pbk WHERE Number=$PHONE" + + if [[ ! -z $($sql "$reqPhoneExist") ]]; then + local reqRmContact="DELETE FROM pbk WHERE Number=$PHONE" + $sql "$reqRmContact" || exit 1 + else + log "${red}Contact doesn't exist$c_" + fi + +} + diff --git a/shell/sms_DESTROY.sh b/shell/sms_DESTROY.sh index 26bdece..372309a 100755 --- a/shell/sms_DESTROY.sh +++ b/shell/sms_DESTROY.sh @@ -6,7 +6,7 @@ ################################################################################ source ./shell/init.sh source ./shell/functions.sh -log "__SUB:sms_DESTROY.sh: START ($1=phone, $2=uid)" +log "${c_yellow}__SUB:sms_DESTROY.sh: START ($1=phone, $2=uid)$c_" PHONE="$1" MEMBERUID="$2" @@ -22,7 +22,7 @@ if [[ -f "./wallets/$PHONE/VIREMENTS" ]]; then sms_ERROR "$PHONE" "Votre portefeuille comporte des virements non réglés... FERMETURE IMPOSSIBLE!" exit else - log "__SUB:sms_DESTROY.sh: VIREMENT $next OK " + log "__SUB:sms_DESTROY.sh: VIREMENT $next ${c_green}OK$c_" fi done fi @@ -50,12 +50,12 @@ if [[ "$MEMBERUID" == "DON" || "$MEMBERUID" == "" || "$MEMBERUID" == "$MEMBER" ] cents=$(echo $(bc -l <<< "scale=0; $LIMIT * 100") | cut -d '.' -f 1) move_g1cents "$PHONE" "$NODEPUB" "$cents" I=$(ipfs_node_wallets_add) - log "__SUB:sms_DESTROY.sh: WALLET DESTROYED : $PHONE / $UIDNA / $MEMBER : OK" + log "__SUB:sms_DESTROY.sh: WALLET DESTROYED : $PHONE / $UIDNA / $MEMBER : ${c_green}OK$c_" fi else new=$(./shell/checknodes.sh "BAN") - sms_ERROR "$PHONE" "Problème de payement avec silkaj (changement de serveur $new): $PAY"; - log "__SUB:sms_DESTROY.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + sms_ERROR "$PHONE" "Problème de payement avec silkaj (changement de serveur $new): $PAY"; + log "${c_red}__SUB:sms_DESTROY.sh: END WITH ERRORS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~$c_" exit fi fi @@ -71,5 +71,8 @@ $back" sms_SEND "$PHONE" "$mess" -log "__SUB:sms_DESTROY.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~" +# Remove contact from database +rm_contact $MEMBERUID $PHONE && log "${c_green}Contact has been deleted from database$c_" || "${c_red}Contact can't be deleted database$c_" + +log "${c_yellow}__SUB:sms_DESTROY.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~$c_" exit diff --git a/shell/sms_NEW.sh b/shell/sms_NEW.sh index 1d4949a..d4f637c 100755 --- a/shell/sms_NEW.sh +++ b/shell/sms_NEW.sh @@ -6,7 +6,7 @@ ################################################################################ source ./shell/init.sh source ./shell/functions.sh -log "X sms_NEW.sh ($1=phone, $2=uid)" +log "${c_yellow}X sms_NEW.sh ($1=phone, $2=uid)$c_" PHONE="$1" MEMBERUID="$2" @@ -15,9 +15,9 @@ MEMBERUID="$2" sms_INIT_ACCOUNT "$PHONE" if [[ "$MEMBERUID" != "" && "$MEMBERUID" != "N" && "$MEMBERUID" != "D" && "$MEMBERUID" != "NOUV" ]]; then # UID RECEIVED in SMS - VIRDEST=$MEMBERUID + VIRDEST=$MEMBERUID MEMRIB=$(sms_uid2key "$MEMBERUID" "$PHONE" "$PIN") - if [[ $MEMRIB == "" ]]; then exit; fi + if [[ $MEMRIB == "" ]]; then exit; fi MEMBER="$MEMBERUID" fi @@ -51,8 +51,10 @@ sleep 2 sms_SEND "$PHONE" "Compte relié? $MEMBER $MAIL $MEMRIB" +# Add contact to database +add_contact $MEMBERUID $PHONE && log "${c_green}Contact has been added to database$c_" || "${c_red}Contact can't be added to database$c_" - -log "END sms_NEW.sh" +log "${c_yellow}END sms_NEW.sh$c_" log "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" exit + From 7126c11e04a179974a92a59d295f2525527060ed Mon Sep 17 00:00:00 2001 From: qo-op Date: Tue, 17 Dec 2019 20:18:49 +0100 Subject: [PATCH 08/26] shell/manual_BILLETS_PERIMES.sh --- _chain | 2 +- _comments | 1 + _nanodate | 2 +- _publishkey.gpg | Bin 1288 -> 1288 bytes shell/manual_BILLETS_PERIMES.sh | 2 +- silkaj/src/constants.py | 2 +- 6 files changed, 5 insertions(+), 4 deletions(-) diff --git a/_chain b/_chain index c021b22..493f092 100755 --- a/_chain +++ b/_chain @@ -1 +1 @@ -QmRd3LFiGbA8s17vsYdwWftSnEnnEQGzAzCEPbJBLDrXEf +QmTDcHP1Nqy4SFzYCwuDH3JxvBT7fsdAKWQvrcvsVPMUpD diff --git a/_comments b/_comments index d7fd648..c06d6e2 100755 --- a/_comments +++ b/_comments @@ -173,3 +173,4 @@ OK 2019-12-14: 2019-12-14: 2019-12-17: Better G1Tx +2019-12-17: G1TAG REFRESH & more diff --git a/_nanodate b/_nanodate index ae44054..a017c9f 100755 --- a/_nanodate +++ b/_nanodate @@ -1 +1 @@ -1576547374550330601 +1576604811163661452 diff --git a/_publishkey.gpg b/_publishkey.gpg index 9e229543f35e4b8b1aaf9a92855f6bae87534489..5a2f3c4d9fcf5296250fbbcbf5ad63ebad4d2c45 100755 GIT binary patch literal 1288 zcmV+j1^4=l4Fm}T0vYn|A(C*8g}~D40R;;-A-QTEM1{7};D23B=K!*U>~q8&?@xYG zS>q8n#PFAfz)x)$R+8xCuRISdCMd$Wq>D8cQiC{>VZreo)?ix)ylPykDX1s%Xdf* znxO##0w;VO?qfKv#_<&08Z9SUN)9^XJWZ$rlin0Co~yurH*C@I;huXV3SMTHF9YRq zi$fZw$|;oH>jsW(K=nLNTL4&Jv|;f2lAPcKxUV9wSnW>HXx^Crp!UVlEPua);at;>ltX^u zsdC+|ofFcl$|KsQh>-6$gYIL!I{P$0M8#kR2kSP3m(gA+T;|N+ZFPH!LnM{SBWLW< z+PCP_j;;{V&ifvf8=58JQwtBZ2mhXZJcF6bze$^wOhHpp1~NS}n$!`oyJ>QwWoTDJ z!DD>b>J-YFDDB@IoQVww(*oiIp`jEb`V7UJjGdHc)j;m}tN-6w;@+JUoMfnH8E)wU ztd9Y9(?>BQhwMvs*}vkVXfCnT%KFQ5wM22!9{D~IM&EebDRXg?^ z;~Cr)ifa}zTIqBIq~b-^JVd_Z3=TNV3B{qF; zCtO*?P{O29X*0IpR|XZD+Nd-BIHxfxzKw9@nBtQ3ad+74iS8W*m1%jCJ@tM<5vtAE3lkn~BN51dsoE`GwrD_WvfmVb zcXbU?mo*vUz%?;_l3)vC!OJzP{1cPadR^z^s%)R=7#w#X?H%$~OF|WpgAM|+LOcS> zler)rTTTcxY$FCj<8ORrqJAZN`q}1C1^U(OHO{7zj({oA46_HcO(J&~G8f_LCQ|leqwz-j#E8|_v{u~9SuG+q#Y+Tb@&qIKtd9|}D>2RW`-&AZ- zna*0NOhq5v{E%~Xv2`{O43zYj y+RD?|wJyf0{5UL%yDm1}UsG_d@UZjz8PWLofFT0`8~Qt-dkYvY-k>PK@KF0IhIl^! literal 1288 zcmV+j1^4=l4Fm}T0;bIgR`ao^9>CJ-0Se*$|7I8|a0Hmuj0#JKn7nH4RnrA`24H#5LIEaIipL^Q^2;VAUAt z@Q_xfe4>#BMQwW;pE|;NHr_$zHBBnbd|;pafQ^MO^rbNWu#<9hVVzVjkhkQuti88W zSYQ-`#OdE?F3C;kls^qAL|u@!al@_xK6HZvCG|~J%{hK~Hw!FnGX6tlLCbb-cphX< zySwJ%LoR01AG)OnjIGemk6iDtUCXa5>Z>S+v;JF!YOw$RB8zW(ox#}u@*FW3LO8j$f}RmZzZ zN_r{W_{uR_$ekb`o`ag6`YCSkilq6wD|>b!#PjwWDqBx2&(gbOS#t5)<5}@Yd*oBKnJ(b_!V!kbuGE4i{gOu)q4j_>Qn5Qyf^8`K$wvOoA3Iv(8|wcn@T3dOD(b< z2GyVa4M-o}U;$4{<7V7C!Ooesd-kaT5kGOFYxg^Js2nM;xe?@>BM{7?Waf-ub+nB`cT(x2Z$iCi6WF6@hU5u5u3J*{y*u}UYEPtRFz31RvZt3W_$a~|$-s0%AedTu%Q3cd z>4@U%B02j~%M?m;;a`Q`J+75%=Ku{jpr_vbx1!k2UTf66Qmkr=mW={dY;>-3l&Im0 z4EaA{DMyD_IeH?)3`ji?2uQpm?3_OK)IBJ%??Lsj$?-I)QJSTmycAQA@)M7GyhMmM z8?bx%$cIrG=?e%&_5BWKL?;S6Z2H%VbedfLd1DsR3@+Z-2n5%gESl1j1LT?1Tv!wO+o?ooi%S_$s@V=pqI@ zS(7CF5kv(+N=$IIj;S4 yL Date: Wed, 18 Dec 2019 00:54:42 +0100 Subject: [PATCH 09/26] SMS RAZ --- shell/cron_G1TAG_REFRESH.sh | 2 +- shell/manual_BILLETS_PERIMES.sh | 2 +- shell/sms_DESTROY.sh | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/shell/cron_G1TAG_REFRESH.sh b/shell/cron_G1TAG_REFRESH.sh index debb381..ff4251d 100755 --- a/shell/cron_G1TAG_REFRESH.sh +++ b/shell/cron_G1TAG_REFRESH.sh @@ -45,7 +45,7 @@ for tag in ./wallets/.$IPFSNODEID/TAG/*; do oldtagn=$(cat ./TAG/${RR}.old/TAG_n) curtagn=$(cat ./TAG/${RR}/TAG_n) oldtagchain=$(cat ./TAG/${RR}.old/TAG_chain) - curtagchain=$(cat ./TAG/${RR}/TAG_chain) + curtagchain=$(cat ./TAG/${RR}/TAG_chain) echo "__SUB:cron_G1TAG_REFRESH.sh: ./TAG/$RR VALUE: ($oldtagn) $oldtagval ZEN -> ($curtagn) $curtagval ZEN" echo "__SUB:cron_G1TAG_REFRESH.sh: $oldtagchain -> $curtagchain" diff --git a/shell/manual_BILLETS_PERIMES.sh b/shell/manual_BILLETS_PERIMES.sh index 3961903..8b202c0 100755 --- a/shell/manual_BILLETS_PERIMES.sh +++ b/shell/manual_BILLETS_PERIMES.sh @@ -39,7 +39,7 @@ for result in $(find billets/ -daystart -mtime +$vieux -type d -name "*"); do PAY=$(/usr/local/bin/silkaj -p duniter-g1.p2p.legal:443 tx --amount="$virement" --output="$dest" -y) if [[ ! $(echo $PAY | grep "successfully sent") ]]; then - echo "!!!! ERREUR: Something Wrong happened with $result" + echo "!!!! ERREUR: $virement Something Wrong happened with $result" if [[ ! $virement ]]; then mv $result /tmp/$result; fi else echo "Tout s'est bien passé! On supprime $result et continue avec le billet $Nbillets" diff --git a/shell/sms_DESTROY.sh b/shell/sms_DESTROY.sh index 372309a..01f2142 100755 --- a/shell/sms_DESTROY.sh +++ b/shell/sms_DESTROY.sh @@ -43,6 +43,17 @@ if [[ "$MEMBERUID" == "DON" || "$MEMBERUID" == "" || "$MEMBERUID" == "$MEMBER" ] if [[ "$(echo $PAY | cut -d '|' -f 1)" != "KO" && "$PAY" != "" && "$(echo $back | cut -d '|' -f 1)" != "KO" ]]; then # DESTROY FILESYSTEM AND G1sms WALLET SWARM REFERENCE if [[ "$PHONE" != "" ]]; then +# SEND SMS BEFORE DELETE FOLDER +mess="[G1sms+] $PAY +Portefeuille détruit! +Viré vers $MEMBER +$MEMRIB + +Merci, à bientôt. +$ADMINPSEUDO @ $NODEUIDNA +$back" +sms_SEND "$PHONE" "$mess" + rm -Rf ./wallets/$PHONE; rm -Rf ./wallets_swarm/$PHONE; cents=$(echo $(bc -l <<< "scale=0; $GETLIMIT * 100") | cut -d '.' -f 1) @@ -60,17 +71,6 @@ if [[ "$MEMBERUID" == "DON" || "$MEMBERUID" == "" || "$MEMBERUID" == "$MEMBER" ] fi fi -mess="[G1sms+] $PAY -Portefeuille détruit! -Viré vers $MEMBER -$MEMRIB - -Merci, à bientôt. -$ADMINPSEUDO @ $NODEUIDNA -$back" - -sms_SEND "$PHONE" "$mess" - # Remove contact from database rm_contact $MEMBERUID $PHONE && log "${c_green}Contact has been deleted from database$c_" || "${c_red}Contact can't be deleted database$c_" From dd74cff5aa1790da2e78a38c0e6260c87881c58f Mon Sep 17 00:00:00 2001 From: qo-op Date: Wed, 18 Dec 2019 00:57:15 +0100 Subject: [PATCH 10/26] mysql-stretch.sql --- .install/templates/4a/mysql-stretch.sql | 227 ++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 .install/templates/4a/mysql-stretch.sql diff --git a/.install/templates/4a/mysql-stretch.sql b/.install/templates/4a/mysql-stretch.sql new file mode 100644 index 0000000..44448af --- /dev/null +++ b/.install/templates/4a/mysql-stretch.sql @@ -0,0 +1,227 @@ +-- +-- Database for Gammu SMSD +-- +-- In case you get errors about not supported charset, please +-- replace utf8mb4 with utf8. + +-- -------------------------------------------------------- + +-- +-- Table structure for table `gammu` +-- + +CREATE TABLE `gammu` ( + `Version` integer NOT NULL default '0' PRIMARY KEY +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; + +-- +-- Dumping data for table `gammu` +-- + +INSERT INTO `gammu` (`Version`) VALUES (16); + +-- -------------------------------------------------------- + +-- +-- Table structure for table `inbox` +-- + +CREATE TABLE `inbox` ( + `UpdatedInDB` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `ReceivingDateTime` timestamp NOT NULL default '0000-00-00 00:00:00', + `Text` text NOT NULL, + `SenderNumber` varchar(20) NOT NULL default '', + `Coding` enum('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression') NOT NULL default 'Default_No_Compression', + `UDH` text NOT NULL, + `SMSCNumber` varchar(20) NOT NULL default '', + `Class` integer NOT NULL default '-1', + `TextDecoded` text NOT NULL, + `ID` integer unsigned NOT NULL auto_increment, + `RecipientID` text NOT NULL, + `Processed` enum('false','true') NOT NULL default 'false', + PRIMARY KEY `ID` (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ; + +-- +-- Dumping data for table `inbox` +-- + + +-- -------------------------------------------------------- + +-- +-- Table structure for table `outbox` +-- + +CREATE TABLE `outbox` ( + `UpdatedInDB` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `InsertIntoDB` timestamp NOT NULL default '0000-00-00 00:00:00', + `SendingDateTime` timestamp NOT NULL default '0000-00-00 00:00:00', + `SendBefore` time NOT NULL DEFAULT '23:59:59', + `SendAfter` time NOT NULL DEFAULT '00:00:00', + `Text` text, + `DestinationNumber` varchar(20) NOT NULL default '', + `Coding` enum('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression') NOT NULL default 'Default_No_Compression', + `UDH` text, + `Class` integer default '-1', + `TextDecoded` text NOT NULL, + `ID` integer unsigned NOT NULL auto_increment, + `MultiPart` enum('false','true') default 'false', + `RelativeValidity` integer default '-1', + `SenderID` varchar(255), + `SendingTimeOut` timestamp NULL default '0000-00-00 00:00:00', + `DeliveryReport` enum('default','yes','no') default 'default', + `CreatorID` text NOT NULL, + `Retries` int(3) default 0, + `Priority` integer default 0, + PRIMARY KEY `ID` (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; + +CREATE INDEX outbox_date ON outbox(SendingDateTime, SendingTimeOut); +CREATE INDEX outbox_sender ON outbox(SenderID(250)); + +-- +-- Dumping data for table `outbox` +-- + + +-- -------------------------------------------------------- + +-- +-- Table structure for table `outbox_multipart` +-- + +CREATE TABLE `outbox_multipart` ( + `Text` text, + `Coding` enum('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression') NOT NULL default 'Default_No_Compression', + `UDH` text, + `Class` integer default '-1', + `TextDecoded` text, + `ID` integer unsigned NOT NULL default '0', + `SequencePosition` integer NOT NULL default '1', + PRIMARY KEY (`ID`, `SequencePosition`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; + +-- +-- Dumping data for table `outbox_multipart` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `phones` +-- + +CREATE TABLE `phones` ( + `ID` text NOT NULL, + `UpdatedInDB` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `InsertIntoDB` timestamp NOT NULL default '0000-00-00 00:00:00', + `TimeOut` timestamp NOT NULL default '0000-00-00 00:00:00', + `Send` enum('yes','no') NOT NULL default 'no', + `Receive` enum('yes','no') NOT NULL default 'no', + `IMEI` varchar(35) NOT NULL, + `IMSI` varchar(35) NOT NULL, + `NetCode` varchar(10) default 'ERROR', + `NetName` varchar(35) default 'ERROR', + `Client` text NOT NULL, + `Battery` integer NOT NULL DEFAULT -1, + `Signal` integer NOT NULL DEFAULT -1, + `Sent` int NOT NULL DEFAULT 0, + `Received` int NOT NULL DEFAULT 0, + PRIMARY KEY (`IMEI`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; + +-- +-- Dumping data for table `phones` +-- + +-- -------------------------------------------------------- + +-- +-- Table structure for table `sentitems` +-- + +CREATE TABLE `sentitems` ( + `UpdatedInDB` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `InsertIntoDB` timestamp NOT NULL default '0000-00-00 00:00:00', + `SendingDateTime` timestamp NOT NULL default '0000-00-00 00:00:00', + `DeliveryDateTime` timestamp NULL, + `Text` text NOT NULL, + `DestinationNumber` varchar(20) NOT NULL default '', + `Coding` enum('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression') NOT NULL default 'Default_No_Compression', + `UDH` text NOT NULL, + `SMSCNumber` varchar(20) NOT NULL default '', + `Class` integer NOT NULL default '-1', + `TextDecoded` text NOT NULL, + `ID` integer unsigned NOT NULL default '0', + `SenderID` varchar(255) NOT NULL, + `SequencePosition` integer NOT NULL default '1', + `Status` enum('SendingOK','SendingOKNoReport','SendingError','DeliveryOK','DeliveryFailed','DeliveryPending','DeliveryUnknown','Error') NOT NULL default 'SendingOK', + `StatusError` integer NOT NULL default '-1', + `TPMR` integer NOT NULL default '-1', + `RelativeValidity` integer NOT NULL default '-1', + `CreatorID` text NOT NULL, + PRIMARY KEY (`ID`, `SequencePosition`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4; + +CREATE INDEX sentitems_date ON sentitems(DeliveryDateTime); +CREATE INDEX sentitems_tpmr ON sentitems(TPMR); +CREATE INDEX sentitems_dest ON sentitems(DestinationNumber); +CREATE INDEX sentitems_sender ON sentitems(SenderID(250)); + +-- +-- Dumping data for table `sentitems` +-- + + +-- +-- Triggers for setting default timestamps +-- + +DELIMITER // + +CREATE TRIGGER inbox_timestamp BEFORE INSERT ON inbox +FOR EACH ROW +BEGIN + IF NEW.ReceivingDateTime = '0000-00-00 00:00:00' THEN + SET NEW.ReceivingDateTime = CURRENT_TIMESTAMP(); + END IF; +END;// + +CREATE TRIGGER outbox_timestamp BEFORE INSERT ON outbox +FOR EACH ROW +BEGIN + IF NEW.InsertIntoDB = '0000-00-00 00:00:00' THEN + SET NEW.InsertIntoDB = CURRENT_TIMESTAMP(); + END IF; + IF NEW.SendingDateTime = '0000-00-00 00:00:00' THEN + SET NEW.SendingDateTime = CURRENT_TIMESTAMP(); + END IF; + IF NEW.SendingTimeOut = '0000-00-00 00:00:00' THEN + SET NEW.SendingTimeOut = CURRENT_TIMESTAMP(); + END IF; +END;// + +CREATE TRIGGER phones_timestamp BEFORE INSERT ON phones +FOR EACH ROW +BEGIN + IF NEW.InsertIntoDB = '0000-00-00 00:00:00' THEN + SET NEW.InsertIntoDB = CURRENT_TIMESTAMP(); + END IF; + IF NEW.TimeOut = '0000-00-00 00:00:00' THEN + SET NEW.TimeOut = CURRENT_TIMESTAMP(); + END IF; +END;// + +CREATE TRIGGER sentitems_timestamp BEFORE INSERT ON sentitems +FOR EACH ROW +BEGIN + IF NEW.InsertIntoDB = '0000-00-00 00:00:00' THEN + SET NEW.InsertIntoDB = CURRENT_TIMESTAMP(); + END IF; + IF NEW.SendingDateTime = '0000-00-00 00:00:00' THEN + SET NEW.SendingDateTime = CURRENT_TIMESTAMP(); + END IF; +END;// + +DELIMITER ; From a00cfd9e6e4f502aa2599d19f73cde0612e82db5 Mon Sep 17 00:00:00 2001 From: poka Date: Wed, 18 Dec 2019 01:53:42 +0100 Subject: [PATCH 11/26] Fix non SSL for kalkun. Add default contact group. Add new user in contact group --- .install/1-install_requirements.sh | 1 - .install/4a-install_kalkun.sh | 2 ++ .install/ssl.sh | 3 +++ .install/templates/4a/kalkun.conf | 4 +--- .install/templates/4a/kalkun.sql | 17 +++++++++++++---- shell/functions.sh | 2 +- shell/init.sh.old | 10 +++++----- shell/sms_DESTROY.sh | 2 +- shell/sms_NEW.sh | 2 +- 9 files changed, 27 insertions(+), 16 deletions(-) diff --git a/.install/1-install_requirements.sh b/.install/1-install_requirements.sh index 91d9ed3..514cf3f 100755 --- a/.install/1-install_requirements.sh +++ b/.install/1-install_requirements.sh @@ -70,7 +70,6 @@ php() { sudo apt -y install lsb-release apt-transport-https ca-certificates || err+="Install apt-transport-https" sudo wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg || err+="Download PHP key" echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php7.3.list - sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8 || err+="Download PHP key" sudo apt update sudo apt -y install software-properties-common dirmngr nginx php7.3 php7.3-common php7.3-gettext php7.3-fpm php7.3-gd php7.3-mysql php7.3-curl php7.3-imap php7.3-mbstring php7.3-xml php7.3-cli mariadb-server || err+="Install PHP and MySQL" else diff --git a/.install/4a-install_kalkun.sh b/.install/4a-install_kalkun.sh index 15f4872..0fbcec2 100755 --- a/.install/4a-install_kalkun.sh +++ b/.install/4a-install_kalkun.sh @@ -38,6 +38,8 @@ if [[ -z $(sudo mysql gammu -e "SHOW TABLES LIKE 'outbox';") ]]; then fi if [[ -z $(sudo mysql gammu -e "SHOW TABLES LIKE 'kalkun';") ]]; then echo -e "${c_yellow}Importation du dump kalkun...$c_" + [[ ! $ADRESSE ]] && ADRESSE=G1GROUPE + sed -i "s/_GROUPDEF/$ADRESSE/g" $MY_PATH/templates/4a/kalkun.sql sudo mysql gammu < $MY_PATH/templates/4a/kalkun.sql || err+="Import dump Kalkun" fi diff --git a/.install/ssl.sh b/.install/ssl.sh index 84ea3aa..5dc466f 100755 --- a/.install/ssl.sh +++ b/.install/ssl.sh @@ -51,6 +51,7 @@ create_certificate() { case $action in on) sudo sed -i 's/ #if/ if/g' /etc/nginx/conf.d/$APP.conf + sudo sed -i 's/ #add/ add/g' /etc/nginx/conf.d/$APP.conf sudo sed -i "s/listen 443;/listen 443 ssl;/g" /etc/nginx/conf.d/$APP.conf [[ ! -d /etc/nginx/includes ]] && sudo mkdir /etc/nginx/includes @@ -60,6 +61,8 @@ on) off) sudo sed -i "s/ if/ #if/g" /etc/nginx/conf.d/$APP.conf + sudo sed -i "s/ add/ #add/g" /etc/nginx/conf.d/$APP.conf + sudo sed -i "/ssl.conf;/d" /etc/nginx/conf.d/$APP.conf sudo sed -i "/ssl_certificate/d" /etc/nginx/conf.d/$APP.conf ;; diff --git a/.install/templates/4a/kalkun.conf b/.install/templates/4a/kalkun.conf index 0aa6f72..779ecd2 100644 --- a/.install/templates/4a/kalkun.conf +++ b/.install/templates/4a/kalkun.conf @@ -4,9 +4,7 @@ server { listen [::]:443 ssl; server_name _DOMAIN; - add_header Content-Security-Policy upgrade-insecure-requests; -# add_header 'Access-Control-Allow-Origin' '*'; - + #add_header Content-Security-Policy upgrade-insecure-requests; #if ($http_x_forwarded_proto = "http") { return 301 https://$server_name$request_uri; } location / { diff --git a/.install/templates/4a/kalkun.sql b/.install/templates/4a/kalkun.sql index 4b665aa..ed090a1 100644 --- a/.install/templates/4a/kalkun.sql +++ b/.install/templates/4a/kalkun.sql @@ -67,7 +67,7 @@ CREATE TABLE IF NOT EXISTS `user` ( -- INSERT INTO `user` (`id_user`, `username`, `realname`, `password`, `phone_number`, `level`) VALUES -(1, 'kalkun', 'Kalkun SMS', 'f0af18413d1c9e0366d8d1273160f55d5efeddfe', '123456789', 'admin'); +(1, 'admin', 'G1Admin', 'd033e22ae348aeb5660fc2140aec35850c4da997', '0600000000', 'admin'); -- -------------------------------------------------------- @@ -147,9 +147,9 @@ CREATE TABLE IF NOT EXISTS `user_settings` ( `paging` int(2) NOT NULL DEFAULT '10', `bg_image` varchar(50) NOT NULL, `delivery_report` enum('default','yes','no') NOT NULL DEFAULT 'default', - `language` varchar(20) NOT NULL DEFAULT 'english', + `language` varchar(20) NOT NULL DEFAULT 'french', `conversation_sort` enum('asc','desc') NOT NULL DEFAULT 'asc', - `country_code` varchar(2) NOT NULL DEFAULT 'US', + `country_code` varchar(2) NOT NULL DEFAULT 'FR', PRIMARY KEY (`id_user`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; @@ -158,7 +158,7 @@ CREATE TABLE IF NOT EXISTS `user_settings` ( -- INSERT INTO `user_settings` (`id_user`, `theme`, `signature`, `permanent_delete`, `paging`, `bg_image`, `delivery_report`, `language`, `conversation_sort`) VALUES -(1, 'green', 'false;--\nPut your signature here', 'false', 20, 'true;background.jpg', 'default' , 'english', 'asc'); +(1, 'green', 'false;--\nVotre signature ici', 'false', 20, 'true;background.jpg', 'default' , 'french', 'asc'); -- -------------------------------------------------------- @@ -329,3 +329,12 @@ CREATE TABLE `ci_sessions` ( `data` blob NOT NULL, KEY `ci_sessions_timestamp` (`timestamp`) ) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- -------------------------------------------------------- + +-- +-- Insert default contact group +-- + +INSERT INTO `pbk_groups` (`ID`, `Name`, `id_user`, `is_public`) VALUES +('1', 'Blois', '1', 'false'); diff --git a/shell/functions.sh b/shell/functions.sh index 7fc456d..20f82ec 100755 --- a/shell/functions.sh +++ b/shell/functions.sh @@ -629,7 +629,7 @@ function add_contact(){ local reqPhoneExist="SELECT * FROM pbk WHERE Number=$PHONE" if [[ -z $($sql "$reqPhoneExist") ]]; then - local reqAddContact="INSERT INTO pbk (GroupID, Name, Number, id_user, is_public) VALUES ('-1', '$MEMBERUID', '$PHONE', '1', 'false')" + local reqAddContact="INSERT INTO pbk (GroupID, Name, Number, id_user, is_public) VALUES ('1', '$MEMBERUID', '$PHONE', '1', 'false')" $sql "$reqAddContact" || exit 1 else log "${red}Contact already exist$c_" diff --git a/shell/init.sh.old b/shell/init.sh.old index 47d1f27..65517c1 100755 --- a/shell/init.sh.old +++ b/shell/init.sh.old @@ -1,6 +1,6 @@ #!/bin/bash ################################################################## -# Author: Fred (support@qo-op.com) +# Author: poka (support@qo-op.com) # Version: 0.1 # License: GPL (http://www.google.com/search?q=GPL) ################################################################## @@ -61,13 +61,13 @@ fi export NODECOMM=10 ################################################################## # SMS SIM Card Phone Number - export MASTERPHONE="+33651136520" - export ADRESSE="G1_Fablab_Toulouse" + export MASTERPHONE="+3368818767" + export ADRESSE="Blois" export G1DAB="NO" ################################################################## # ADMIN COMMAND PHONE ORIGIN - export ADMINPHONE="+33647683646" - export ADMINPSEUDO="Fred" + export ADMINPHONE="+33650573417" + export ADMINPSEUDO="poka" ################################################################## # DUNITER/CESIUM+ DEFAULT SERVERS export DUNITER="https://g1.duniter.org" diff --git a/shell/sms_DESTROY.sh b/shell/sms_DESTROY.sh index 372309a..1f9fec9 100755 --- a/shell/sms_DESTROY.sh +++ b/shell/sms_DESTROY.sh @@ -72,7 +72,7 @@ $back" sms_SEND "$PHONE" "$mess" # Remove contact from database -rm_contact $MEMBERUID $PHONE && log "${c_green}Contact has been deleted from database$c_" || "${c_red}Contact can't be deleted database$c_" +rm_contact $MEMBERUID $PHONE && log "${c_green}Contact has been deleted from database$c_" || log "${c_red}Contact can't be deleted database$c_" log "${c_yellow}__SUB:sms_DESTROY.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~$c_" exit diff --git a/shell/sms_NEW.sh b/shell/sms_NEW.sh index d4f637c..04f537a 100755 --- a/shell/sms_NEW.sh +++ b/shell/sms_NEW.sh @@ -52,7 +52,7 @@ sms_SEND "$PHONE" "Compte relié? $MEMBER $MAIL $MEMRIB" # Add contact to database -add_contact $MEMBERUID $PHONE && log "${c_green}Contact has been added to database$c_" || "${c_red}Contact can't be added to database$c_" +add_contact $MEMBERUID $PHONE && log "${c_green}Contact has been added to database$c_" || log "${c_red}Contact can't be added to database$c_" log "${c_yellow}END sms_NEW.sh$c_" log "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" From f07f5f994afe7a626cc3a5a849dc9dd89f1988e3 Mon Sep 17 00:00:00 2001 From: qo-op Date: Wed, 18 Dec 2019 02:31:12 +0100 Subject: [PATCH 12/26] shell/sms_ABO.sh --- _chain | 2 +- _comments | 1 + _nanodate | 2 +- _publishkey.gpg | Bin 1288 -> 1288 bytes shell/cron_G1TAG_REFRESH.sh | 2 +- shell/functions.sh | 4 ++-- shell/sms_ABO.sh | 24 ++++++++++++++++++++---- sms_received.sh | 5 ++--- 8 files changed, 28 insertions(+), 12 deletions(-) mode change 100644 => 100755 shell/sms_ABO.sh diff --git a/_chain b/_chain index 493f092..953407d 100755 --- a/_chain +++ b/_chain @@ -1 +1 @@ -QmTDcHP1Nqy4SFzYCwuDH3JxvBT7fsdAKWQvrcvsVPMUpD +QmbRvGMpwZws4ii5xe5x8EgK1SSxNBaNNjinwdWjhye3TR diff --git a/_comments b/_comments index c06d6e2..7842c23 100755 --- a/_comments +++ b/_comments @@ -174,3 +174,4 @@ OK 2019-12-14: 2019-12-17: Better G1Tx 2019-12-17: G1TAG REFRESH & more +2019-12-18: RAZ diff --git a/_nanodate b/_nanodate index a017c9f..7778f6d 100755 --- a/_nanodate +++ b/_nanodate @@ -1 +1 @@ -1576604811163661452 +1576627244479575204 diff --git a/_publishkey.gpg b/_publishkey.gpg index 5a2f3c4d9fcf5296250fbbcbf5ad63ebad4d2c45..619e3dc50687c359bc2dc032d3aeb90658ecfee3 100755 GIT binary patch literal 1288 zcmV+j1^4=l4Fm}T0tzl_!_Nv3yui}x0VC1ylAIPxJroN22|@7*|4&J!EX5-P4<7Ty z#@!yLtP{1+fPga`XURI@?+W_Hn_6i_fz7@`up(-H@u(lK=bwg}2~_EVtS+NfPG=iL zpI>6EWLk=Z?U1%#_<~qq{UPZr;$tvkfF2%P$cc%*0`Gpksx+#rm(t4**=z*5;7Mq$Ui+)U{{KB^= zJIhY^ysF&tXr$PwI8LTHzNNrqb$CaB_#|uaHrnR|EVmq4#jdKb?yOv*p=kbfUqACb zoXtzywvs1`!>zw^wSrg8&oFK0Bzj9=TxE~+kGNAp@BpyD(CH|quuIGz{qx^K@1>W6 zh?%*SX7-5cz}HgX0LB~a=Ul%?wbWIJB-wEa0BLkvzE~|1D38n{3M#Oj1D*5@I0H*f zv)5{?_aE}MgkH4#fb=aZ5K&Muv)?w-e|j198Mn+Ke(x?-2#!fEtzHSa8t`VWE3gwYSyJn}KeKrTbcaDOT zVKdDzoq^3@=}o?>jNI&gc}tr$A?hHoyP(hYyJsm!Gr@8A*r&Jb#`k)m!+1whU=UoC zU;YV3vvay2D*rO-e-r0`uyn*dK5#KSw>Q@=EPrm?K zh9No25#x@H0G+jBpH*V)?#=eR9=*5q|3OgD%tB@n=l;rg#)=)?kM$++L|CIi}h3mZXQ`&a6t&b>aHxlf?Qq0UzbDuQ{OtoK1_3!Wj=Qvk5j8hjcP@=$5sQf@d8;@G ztd&?5V`b*Bz%{ncK&MMXO*hK>KDf0h_Z#(X%`lKSs7UVX?93qEO>-gCFBleLwDw%} zt^87Y*mw(=Dn7gTiyZ|0^0U3J)bcbYzJSw&w0JQ6O0||N=;ix?rk;Vw#7`i8vQE`- zESK?mi~7STKw%R89}uS6)eRNdxEs~q8&?@xYG zS>q8n#PFAfz)x)$R+8xCuRISdCMd$Wq>D8cQiC{>VZreo)?ix)ylPykDX1s%Xdf* znxO##0w;VO?qfKv#_<&08Z9SUN)9^XJWZ$rlin0Co~yurH*C@I;huXV3SMTHF9YRq zi$fZw$|;oH>jsW(K=nLNTL4&Jv|;f2lAPcKxUV9wSnW>HXx^Crp!UVlEPua);at;>ltX^u zsdC+|ofFcl$|KsQh>-6$gYIL!I{P$0M8#kR2kSP3m(gA+T;|N+ZFPH!LnM{SBWLW< z+PCP_j;;{V&ifvf8=58JQwtBZ2mhXZJcF6bze$^wOhHpp1~NS}n$!`oyJ>QwWoTDJ z!DD>b>J-YFDDB@IoQVww(*oiIp`jEb`V7UJjGdHc)j;m}tN-6w;@+JUoMfnH8E)wU ztd9Y9(?>BQhwMvs*}vkVXfCnT%KFQ5wM22!9{D~IM&EebDRXg?^ z;~Cr)ifa}zTIqBIq~b-^JVd_Z3=TNV3B{qF; zCtO*?P{O29X*0IpR|XZD+Nd-BIHxfxzKw9@nBtQ3ad+74iS8W*m1%jCJ@tM<5vtAE3lkn~BN51dsoE`GwrD_WvfmVb zcXbU?mo*vUz%?;_l3)vC!OJzP{1cPadR^z^s%)R=7#w#X?H%$~OF|WpgAM|+LOcS> zler)rTTTcxY$FCj<8ORrqJAZN`q}1C1^U(OHO{7zj({oA46_HcO(J&~G8f_LCQ|leqwz-j#E8|_v{u~9SuG+q#Y+Tb@&qIKtd9|}D>2RW`-&AZ- zna*0NOhq5v{E%~Xv2`{O43zYj y+RD?|wJyf0{5UL%yDm1}UsG_d@UZjz8PWLofFT0`8~Qt-dkYvY-k>PK@KF0IhIl^! diff --git a/shell/cron_G1TAG_REFRESH.sh b/shell/cron_G1TAG_REFRESH.sh index ff4251d..de8eaec 100755 --- a/shell/cron_G1TAG_REFRESH.sh +++ b/shell/cron_G1TAG_REFRESH.sh @@ -67,7 +67,7 @@ for tag in ./wallets/.$IPFSNODEID/TAG/*; do rm /home/$YOU/.ipfs/keystore/${RR}.crypt fi echo "__SUB:cron_G1TAG_REFRESH.sh: G1Tag PUBLISHKEY OK : /home/$YOU/.ipfs/keystore/${RR}" - + echo ${NANODATE} > ./TAG/${RR}/TAG_nanodate # PUBLISH VERIFIED G1Tag VERSION I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") # RECORD TAG_chain And HASH again diff --git a/shell/functions.sh b/shell/functions.sh index 20f82ec..7dbb9bf 100755 --- a/shell/functions.sh +++ b/shell/functions.sh @@ -116,8 +116,8 @@ if [[ $PHONE ]]; then rm -Rf ./wallets_swarm/$PHONE; fi su $YOU -c "ipfs get --output=./wallets_swarm/ /ipns/$IPFSNODEID" count=1 # Search for All peers Nodes. TODO: To be changed when Swarm is too bug or not expendanding -#for id in ./wallets_swarm/.Qm*/; -for id in $(su $YOU -c "ipfs swarm peers" | awk -F '/' '{print $7}'); +for id in ./wallets_swarm/.Qm*/; +#for id in $(su $YOU -c "ipfs swarm peers" | awk -F '/' '{print $7}'); do count=$((count+1)) id=$(echo $id | cut -d '.' -f 3 | cut -d '/' -f 1) diff --git a/shell/sms_ABO.sh b/shell/sms_ABO.sh old mode 100644 new mode 100755 index 7601a87..1686a3a --- a/shell/sms_ABO.sh +++ b/shell/sms_ABO.sh @@ -11,12 +11,28 @@ # TODO: Create information Channels and moderate OPT IN/OUT source ./shell/init.sh source ./shell/functions.sh -log "__SUB:sms_ABO.sh: START ($1=SERVICE, $2=YESNO)" -SERVICE=$1 -YESNO=$2 -PARAMS=$3 +log "__SUB:sms_ABO.sh: START ($1=PHONE, $2=SERVICE)" +PHONE=$1 +SERVICE=$2 + +sms_INIT_ACCOUNT "$PHONE" case "$SERVICE" in + ON) + log "Abonnement Kalkun" + if [[ "$MEMBER" != "" ]]; then + add_contact $MEMBER $PHONE && log "${c_green}Contact has been added to database$c_" || "${c_red}Contact can't be added to database$c_"; + sms_SEND "$PHONE" "$MEMBER votre inscription annuaire est active" + fi + ;; + OFF) + log "Retrait Kalkun" + if [[ $MEMBER ]]; then + rm_contact $MEMBER $PHONE && log "${c_green}Contact has been deleted from database$c_" || "${c_red}Contact can't be deleted database$c_"; + sms_SEND "$PHONE" "$MEMBER retrait annuaire prise en compte..." + fi + ;; + MARCHE) log "Avertissement G1 marchés" # PARAMS could be "$distance" to Member GeoPoint... diff --git a/sms_received.sh b/sms_received.sh index 2b4b461..4bf00d5 100755 --- a/sms_received.sh +++ b/sms_received.sh @@ -184,9 +184,8 @@ case "$CMD" in ;; ABO) # GERER SES ABONNEMENT CANAUX INFO SMS - CANAL=$(echo "$TEXT" | awk '{print $2}'| grep -E "([A-Za-z0-9\-\_]+$)") - YESNO=$(echo "$TEXT" | awk '{print $3}'| grep -E "([A-Za-z0-9\-\_]+$)") - ./shell/sms_ABO.sh "$PHONE" "$CANAL" "$YESNO" & + SERVICE=$(echo "$TEXT" | awk '{print toupper($2)}'| grep -E "([A-Za-z0-9\-\_]+$)") + ./shell/sms_ABO.sh "$PHONE" "$SERVICE" & ;; DELIVERED|PENDING|FAILED) # If delivered/pending notification come back (gammu/phone config) From 123b4ea563e332a6625b466134a3d6334bbe6bc6 Mon Sep 17 00:00:00 2001 From: poka Date: Wed, 18 Dec 2019 02:47:10 +0100 Subject: [PATCH 13/26] Adapat install kallkun for gammu 1.37 on stretch --- .install/4a-install_kalkun.sh | 14 +++++++++++--- .install/templates/.profile | 12 +++++------- .install/templates/init.sh | 10 +++++----- install.sh | 21 ++++++++++++++------- 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/.install/4a-install_kalkun.sh b/.install/4a-install_kalkun.sh index 0fbcec2..67f4952 100755 --- a/.install/4a-install_kalkun.sh +++ b/.install/4a-install_kalkun.sh @@ -9,9 +9,13 @@ unset err args=$@ [[ $args =~ noask ]] && noask=o && askSSL=o +OS=$(head -n1 $MY_PATH/.OS) IP=$(ifconfig | grep "inet " | grep -v "127.0.0.1" | awk '{ print $2 }') -[[ ! $KSMS_DOMAIN ]] && echo -e "${c_yellow}Choisissez un nom de domaine pour KALKUN (Sinon $IP sera choisi): $c_" && read KSMS_DOMAIN -[[ ! $KSMS_DOMAIN ]] && KSMS_DOMAIN=$IP && askSSL=n && noask=o +if [[ -z $KSMS_DOMAIN ]]; then + echo -e "${c_yellow}Choisissez un nom de domaine pour KALKUN (Sinon $IP sera choisi): $c_" && read KSMS_DOMAIN + [[ -z $KSMS_DOMAIN ]] && KSMS_DOMAIN=$IP && askSSL=n && noask=o + sed -i "s/\ Date: Wed, 18 Dec 2019 02:53:11 +0100 Subject: [PATCH 14/26] Fix ABO log --- shell/sms_ABO.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/sms_ABO.sh b/shell/sms_ABO.sh index 1686a3a..8af0bfa 100755 --- a/shell/sms_ABO.sh +++ b/shell/sms_ABO.sh @@ -21,14 +21,14 @@ case "$SERVICE" in ON) log "Abonnement Kalkun" if [[ "$MEMBER" != "" ]]; then - add_contact $MEMBER $PHONE && log "${c_green}Contact has been added to database$c_" || "${c_red}Contact can't be added to database$c_"; + add_contact $MEMBER $PHONE && log "${c_green}Contact has been added to database$c_" || log "${c_red}Contact can't be added to database$c_"; sms_SEND "$PHONE" "$MEMBER votre inscription annuaire est active" fi ;; OFF) log "Retrait Kalkun" if [[ $MEMBER ]]; then - rm_contact $MEMBER $PHONE && log "${c_green}Contact has been deleted from database$c_" || "${c_red}Contact can't be deleted database$c_"; + rm_contact $MEMBER $PHONE && log "${c_green}Contact has been deleted from database$c_" || log "${c_red}Contact can't be deleted database$c_"; sms_SEND "$PHONE" "$MEMBER retrait annuaire prise en compte..." fi ;; From 043b7db512c568a92b6334ce149f99d2c016be78 Mon Sep 17 00:00:00 2001 From: poka Date: Wed, 18 Dec 2019 03:16:33 +0100 Subject: [PATCH 15/26] Remover Sender:@username. Echo admin / admin default login. Good default settings --- .install/4a-install_kalkun.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.install/4a-install_kalkun.sh b/.install/4a-install_kalkun.sh index 67f4952..e35ffce 100755 --- a/.install/4a-install_kalkun.sh +++ b/.install/4a-install_kalkun.sh @@ -61,6 +61,7 @@ cp $MY_PATH/templates/4a/database.php $MY_PATH/kalkun/application/config/ cp $MY_PATH/templates/4a/daemon.sh $MY_PATH/templates/4a/daemon.php $MY_PATH/kalkun/scripts sed -i "s/_PWD/$pwdDB/g" $MY_PATH/kalkun/application/config/database.php || err+="Sed database password" sed -i "s/_DOMAIN/$DOMAIN/g" $MY_PATH/templates/4a/daemon.php || err+="Sed domaine to daemon.php" +sed -i "s/$config\['append_username_message'\] = \"Sender: @username\";/$config\['append_username_message'\] = \"\";/g" $MY_PATH/kalkun/application/config/kalkun_settings.php # touch $MY_PATH/kalkun/install @@ -118,6 +119,7 @@ if [[ $err ]]; then echo -e "${c_red}Installation incomplète: $err$c_" exit 1 else - echo -e "${c_green}Kalkun est accessible via l'URL $http://$DOMAIN$c_" + echo -e "${c_green}Kalkun est accessible via l'URL$c_light $http://$DOMAIN$c_" + echo -e "${c_green}Les identifiants de connexion par defaut sont:$c_light admin / admin$c_" exit 0 fi From 7ccfd8f377aa30bbf358159d08a65b8cc2fd8671 Mon Sep 17 00:00:00 2001 From: poka Date: Wed, 18 Dec 2019 16:23:58 +0100 Subject: [PATCH 16/26] Fix add user to group. Check if group 1 doesn't exist, create it --- shell/functions.sh | 40 ++++++++++++++++++++++++++-------------- shell/sms_ABO.sh | 8 ++++---- shell/sms_DESTROY.sh | 2 +- shell/sms_NEW.sh | 2 +- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/shell/functions.sh b/shell/functions.sh index 7dbb9bf..43edb1c 100755 --- a/shell/functions.sh +++ b/shell/functions.sh @@ -7,6 +7,13 @@ ################################################################################################################################### ################################################################################################################################### + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + +## Récupère les données du profile +[[ -f $MY_PATH/.profile ]] && source $MY_PATH/.profile + function sms_SEND () { # sms_SEND ($1=phone, $2=message) local dest="$1" @@ -621,16 +628,19 @@ function move_g1cents (){ function add_contact(){ userDB="gammu" pwdDB=$(cat /etc/gammu-smsdrc | grep "password =" | awk '{ print $3 }' || exit 1) - local sql="mysql -u$userDB -p$pwdDB gammu -e" + local sql="mysql -N -u$userDB -p$pwdDB gammu -e" - local MEMBERUID=$1 - local PHONE=$2 + local PHONE=$1 + local MEMBERUID=$2 - local reqPhoneExist="SELECT * FROM pbk WHERE Number=$PHONE" + [[ -z $MEMBERUID ]] && MEMBERUID=$PHONE - if [[ -z $($sql "$reqPhoneExist") ]]; then - local reqAddContact="INSERT INTO pbk (GroupID, Name, Number, id_user, is_public) VALUES ('1', '$MEMBERUID', '$PHONE', '1', 'false')" - $sql "$reqAddContact" || exit 1 + [[ -z $($sql "SELECT * FROM pbk_groups WHERE ID='1'") ]] && $sql "INSERT INTO pbk_groups (ID, Name, id_user, is_public) VALUES ('1', '$(grep "ADRESSE" $MY_PATH/../.profile | awk -F= '{ print $2 }' | tr -d '"')', '1', 'false')" + + if [[ -z $($sql "SELECT * FROM pbk WHERE Number=$PHONE") ]]; then + $sql "INSERT INTO pbk (GroupID, Name, Number, id_user, is_public) VALUES ('1', '$MEMBERUID', '$PHONE', '1', 'false')" || exit 1 + local id_user=$($sql "SELECT ID FROM pbk WHERE Number=$PHONE" || exit 1) + $sql "INSERT INTO user_group (id_group, id_pbk, id_pbk_groups, id_user) VALUES ('$id_user', '$id_user', '1', '1')" || exit 1 else log "${red}Contact already exist$c_" fi @@ -640,19 +650,21 @@ function add_contact(){ function rm_contact(){ userDB="gammu" pwdDB=$(cat /etc/gammu-smsdrc | grep "password =" | awk '{ print $3 }' || exit 1) - local sql="mysql -u$userDB -p$pwdDB gammu -e" + local sql="mysql -N -u$userDB -p$pwdDB gammu -e" - local MEMBERUID=$1 - local PHONE=$2 + local PHONE=$1 + local MEMBERUID=$2 - local reqPhoneExist="SELECT * FROM pbk WHERE Number=$PHONE" + [[ -z $MEMBERUID ]] && MEMBERUID=$PHONE - if [[ ! -z $($sql "$reqPhoneExist") ]]; then - local reqRmContact="DELETE FROM pbk WHERE Number=$PHONE" - $sql "$reqRmContact" || exit 1 + if [[ ! -z $($sql "SELECT * FROM pbk WHERE Number=$PHONE") ]]; then + local id_user=$($sql "SELECT ID FROM pbk WHERE Number=$PHONE" || exit 1) + $sql "DELETE FROM pbk WHERE Number=$PHONE" || exit 1 + $sql "DELETE FROM user_group WHERE id_group='$id_user'" || exit 1 else log "${red}Contact doesn't exist$c_" fi } +$@ diff --git a/shell/sms_ABO.sh b/shell/sms_ABO.sh index 8af0bfa..e3c77fb 100755 --- a/shell/sms_ABO.sh +++ b/shell/sms_ABO.sh @@ -19,16 +19,16 @@ sms_INIT_ACCOUNT "$PHONE" case "$SERVICE" in ON) - log "Abonnement Kalkun" + log "Abonnement Kalkun" if [[ "$MEMBER" != "" ]]; then - add_contact $MEMBER $PHONE && log "${c_green}Contact has been added to database$c_" || log "${c_red}Contact can't be added to database$c_"; + add_contact $PHONE $MEMBERUID && log "${c_green}Contact has been added to database$c_" || log "${c_red}Contact can't be added to database$c_"; sms_SEND "$PHONE" "$MEMBER votre inscription annuaire est active" fi ;; OFF) - log "Retrait Kalkun" + log "Retrait Kalkun" if [[ $MEMBER ]]; then - rm_contact $MEMBER $PHONE && log "${c_green}Contact has been deleted from database$c_" || log "${c_red}Contact can't be deleted database$c_"; + rm_contact $PHONE $MEMBERUID && log "${c_green}Contact has been deleted from database$c_" || log "${c_red}Contact can't be deleted database$c_"; sms_SEND "$PHONE" "$MEMBER retrait annuaire prise en compte..." fi ;; diff --git a/shell/sms_DESTROY.sh b/shell/sms_DESTROY.sh index ae0bcb7..5369a74 100755 --- a/shell/sms_DESTROY.sh +++ b/shell/sms_DESTROY.sh @@ -72,7 +72,7 @@ sms_SEND "$PHONE" "$mess" fi # Remove contact from database -rm_contact $MEMBERUID $PHONE && log "${c_green}Contact has been deleted from database$c_" || log "${c_red}Contact can't be deleted database$c_" +rm_contact $PHONE $MEMBERUID && log "${c_green}Contact has been deleted from database$c_" || log "${c_red}Contact can't be deleted database$c_" log "${c_yellow}__SUB:sms_DESTROY.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~$c_" exit diff --git a/shell/sms_NEW.sh b/shell/sms_NEW.sh index 04f537a..0c945d8 100755 --- a/shell/sms_NEW.sh +++ b/shell/sms_NEW.sh @@ -52,7 +52,7 @@ sms_SEND "$PHONE" "Compte relié? $MEMBER $MAIL $MEMRIB" # Add contact to database -add_contact $MEMBERUID $PHONE && log "${c_green}Contact has been added to database$c_" || log "${c_red}Contact can't be added to database$c_" +add_contact $PHONE $MEMBERUID && log "${c_green}Contact has been added to database$c_" || log "${c_red}Contact can't be added to database$c_" log "${c_yellow}END sms_NEW.sh$c_" log "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" From fac3136524dd1d4561642b61eff8c0d94ead9a51 Mon Sep 17 00:00:00 2001 From: poka Date: Wed, 18 Dec 2019 16:25:59 +0100 Subject: [PATCH 17/26] Fix add user to group. Check if group 1 doesn't exist, create it --- shell/functions.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/shell/functions.sh b/shell/functions.sh index 43edb1c..a7e80f3 100755 --- a/shell/functions.sh +++ b/shell/functions.sh @@ -666,5 +666,3 @@ function rm_contact(){ fi } - -$@ From 7c0d9977f69d290dd38ad573ed7a11e83dfa805a Mon Sep 17 00:00:00 2001 From: poka Date: Wed, 18 Dec 2019 16:35:29 +0100 Subject: [PATCH 18/26] Fix sms_abo memberid --- shell/sms_ABO.sh | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/shell/sms_ABO.sh b/shell/sms_ABO.sh index e3c77fb..28ff437 100755 --- a/shell/sms_ABO.sh +++ b/shell/sms_ABO.sh @@ -19,18 +19,14 @@ sms_INIT_ACCOUNT "$PHONE" case "$SERVICE" in ON) - log "Abonnement Kalkun" - if [[ "$MEMBER" != "" ]]; then - add_contact $PHONE $MEMBERUID && log "${c_green}Contact has been added to database$c_" || log "${c_red}Contact can't be added to database$c_"; - sms_SEND "$PHONE" "$MEMBER votre inscription annuaire est active" - fi + log "Abonnement Kalkun" + add_contact $PHONE $MEMBER && log "${c_green}Contact has been added to database$c_" || log "${c_red}Contact can't be added to database$c_"; + sms_SEND "$PHONE" "$MEMBER votre inscription annuaire est active" ;; OFF) log "Retrait Kalkun" - if [[ $MEMBER ]]; then - rm_contact $PHONE $MEMBERUID && log "${c_green}Contact has been deleted from database$c_" || log "${c_red}Contact can't be deleted database$c_"; - sms_SEND "$PHONE" "$MEMBER retrait annuaire prise en compte..." - fi + rm_contact $PHONE $MEMBER && log "${c_green}Contact has been deleted from database$c_" || log "${c_red}Contact can't be deleted database$c_"; + sms_SEND "$PHONE" "$MEMBER retrait annuaire prise en compte..." ;; MARCHE) From 8d2e611162e118f7b540cb9bb76238f6bbb55b0e Mon Sep 17 00:00:00 2001 From: poka Date: Fri, 20 Dec 2019 19:59:01 +0100 Subject: [PATCH 19/26] Fix debug/GSM_powerkey.sh do not stop key if is started. Replace by . Add .install/templates/2b/gammu-smsdrc --- .install/.GPATH | 1 + ...re_ipfs_layer.sh => 2a-configure_ipfs_layer.sh} | 2 +- .install/2b-configure_gammu.sh | 34 ++++++ .install/5-install_rompr.sh | 14 +++ .install/templates/.profile | 1 + .install/templates/2/swarm.key | 3 - .install/templates/2b/gammu-smsdrc | 26 +++++ .install/templates/5/youtube-dl.php | 128 +++++++++++++++++++++ .install/templates/init.sh | 10 +- GSM_POWERKEY.py | 10 -- _CopyLaRadio/copy.sh | 8 +- GSM_powerkey.sh => debug/GSM_powerkey.sh | 13 ++- debug/smsc.txt | 5 + install.sh | 15 ++- search | 4 +- shell/cron_MINUTE.sh | 8 +- shell/init.sh.old | 10 +- shell/init_keys.sh | 20 ++-- shell/sms_EMAIL.sh | 3 +- sms_received.sh | 10 +- www/rompr/REC/youtube-dl.php | 16 +-- 21 files changed, 289 insertions(+), 52 deletions(-) create mode 100644 .install/.GPATH rename .install/{2-configure_ipfs_layer.sh => 2a-configure_ipfs_layer.sh} (98%) create mode 100644 .install/2b-configure_gammu.sh create mode 100755 .install/5-install_rompr.sh delete mode 100644 .install/templates/2/swarm.key create mode 100644 .install/templates/2b/gammu-smsdrc create mode 100644 .install/templates/5/youtube-dl.php delete mode 100755 GSM_POWERKEY.py rename GSM_powerkey.sh => debug/GSM_powerkey.sh (54%) create mode 100644 debug/smsc.txt diff --git a/.install/.GPATH b/.install/.GPATH new file mode 100644 index 0000000..ac91fa6 --- /dev/null +++ b/.install/.GPATH @@ -0,0 +1 @@ +GPATH=/home/pi/G1sms+ diff --git a/.install/2-configure_ipfs_layer.sh b/.install/2a-configure_ipfs_layer.sh similarity index 98% rename from .install/2-configure_ipfs_layer.sh rename to .install/2a-configure_ipfs_layer.sh index 0839556..162f6f6 100755 --- a/.install/2-configure_ipfs_layer.sh +++ b/.install/2a-configure_ipfs_layer.sh @@ -8,7 +8,7 @@ MY_PATH="`dirname \"$0\"`" # relative MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized stamp=$(date +%s) -templates="$MY_PATH/templates/2" +templates="$MY_PATH/templates/2a" ####################################### # CONFIGURE IPFS for G1sms+ Pi NODES diff --git a/.install/2b-configure_gammu.sh b/.install/2b-configure_gammu.sh new file mode 100644 index 0000000..4940c5c --- /dev/null +++ b/.install/2b-configure_gammu.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized +source $MY_PATH/../.install/.GPATH + +## Récupère les données du profile +[[ -f $MY_PATH/../.profile ]] && source $MY_PATH/../.profile + +## Désactive les processus écoutant le tty1 +[[ $(sudo systemctl status getty@tty1.service | grep "loaded") ]] && sudo systemctl stop getty@tty1.service && sudo systemctl disable getty@tty1.service + +## Copie et sed de /etc/gammu-smsdrc +[[ -f /etc/gammu-smsdrc ]] && sudo mv /etc/gammu-smsdrc /etc/gammu-smsdrc.old && echo "/etc/gammu-smsdrc a été renommé en /etc/gammu-smsdrc.old" +sudo cp $MY_PATH/templates/2b/gammu-smsdrc /etc/ + +GPATHS=$(echo $GPATH | sed 's./.\\/.g') +sudo sed -i "s/_GPATH/$GPATHS/g" /etc/gammu-smsdrc +sudo sed -i "s/_PIN/$PIN/g" /etc/gammu-smsdrc + +## Configure correctement le UART + +[[ ! $(grep enable_uart=1 /boot/config.txt) ]] && echo "enable_uart=1" | sudo tee -a /boot/config.txt +[[ $(grep "console=serial0" /boot/cmdline.txt) ]] && sudo sed -i "s/console=serial0,115200//g" /boot/cmdline.txt +[[ $(grep "console=serial0" /boot/cmdline.txt) ]] && echo -e "${c_red}Attention, console=serial0 est toujours présent dans /boot/cmdline.txt !$c_" && err=1 + +## Configure rc.local + + + +## Redémarre gammu-smsd +sudo service gammu-smsd restart && echo -e "${c_green}Gammu a été correctement configuré$c_" || echo -e "${c_green}Un problème est survenu lors de la configuration de gammu$c_" + +exit 0 diff --git a/.install/5-install_rompr.sh b/.install/5-install_rompr.sh new file mode 100755 index 0000000..987c507 --- /dev/null +++ b/.install/5-install_rompr.sh @@ -0,0 +1,14 @@ +#!/bin/bash +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized +source $MY_PATH/../.install/.GPATH + +GPATHS=$(echo $GPATH | sed 's./.\\/.g') + +sudo cp $MY_PATH/templates/5/youtube-dl.php $GPATH/www/rompr/REC/youtube-dl.php +sudo sed -i "s/_GPATH/$GPATHS/g" $GPATH/www/rompr/REC/youtube-dl.php + +## TODO +# Tout les reste ... + +exit 0 diff --git a/.install/templates/.profile b/.install/templates/.profile index d202a9a..c32b4b1 100644 --- a/.install/templates/.profile +++ b/.install/templates/.profile @@ -2,4 +2,5 @@ ADMINPSEUDO=_ADMINPSEUDO ADMINPHONE=_ADMINPHONE MASTERPHONE=_MASTERPHONE ADRESSE="_ADRESSE" +PIN=_PIN KSMS_DOMAIN= diff --git a/.install/templates/2/swarm.key b/.install/templates/2/swarm.key deleted file mode 100644 index 829df9d..0000000 --- a/.install/templates/2/swarm.key +++ /dev/null @@ -1,3 +0,0 @@ -/key/swarm/psk/1.0.0/ -/base16/ -66f6fcfa6e89bc14721d905370dae9026442eb44fa4d0c92464da887074a234f diff --git a/.install/templates/2b/gammu-smsdrc b/.install/templates/2b/gammu-smsdrc new file mode 100644 index 0000000..77fbaad --- /dev/null +++ b/.install/templates/2b/gammu-smsdrc @@ -0,0 +1,26 @@ +# Configuration file for Gammu SMS Daemon + +[gammu] +port = /dev/ttyS0 +synchronizetime = yes +gammucoding = utf8 +connection = at +# Debugging +logformat = textall + +# SMSD configuration, see gammu-smsdrc(5) +[smsd] +service = files + +logfile = /var/log/gammu-smsd.log +PIN = _PIN + +# Paths where messages are stored (Not use if service = sql) +inboxpath = /var/spool/gammu/inbox/ +outboxpath = /var/spool/gammu/outbox/ +sentsmspath = /var/spool/gammu/sent/ +errorsmspath = /var/spool/gammu/error/ + +RunOnReceive = _GPATH/sms_received.sh +#IncludeSMSCFile = _GPATH/debug/smsc.txt +debuglevel = 3 diff --git a/.install/templates/5/youtube-dl.php b/.install/templates/5/youtube-dl.php new file mode 100644 index 0000000..efd05ca --- /dev/null +++ b/.install/templates/5/youtube-dl.php @@ -0,0 +1,128 @@ +[REC]'; + zcopylink += ' *'; + lines[0].text += zcopylink; +// ZEEBOX HACK ZONE +*/ +// RUN CLI if($argc>1) parse_str(implode('&',array_slice($argv, 1)), $_REQUEST); +$search=$radio=$artist=$title=$lnk=$lnkform=$cmd=$len=""; +$search = trim(urldecode($_REQUEST['q'])); + +$radio = urldecode($_REQUEST['radio']); +$artist = urldecode($_REQUEST['artist']); +$title = urldecode($_REQUEST['title']); +$lnk = trim(urldecode($_REQUEST['lnk'])); +$cmd="$radio|$artist|$title"; +$len=strlen($artist.$title); + +//$result='
'; +$result='
'; +if( $radio == "" ) { $radio = "CopyLaRadio"; } +if( $radio == "Nova zz" ) { + $artist = "undefined"; + $title = "undefined"; +} +// Write request for copy.sh triggering +if( $search == "REC" ) { +/////////////////// + $result.='

♫ '.$radio.' ♫

'; + // LINK RECEIVED + if ($lnk) { + $artist=""; + shell_exec('_GPATH/_CopyLaRadio/parle.sh "Lien reçu."'); + // Not making double request + if( ! exec('grep '.escapeshellarg($lnk).' /tmp/ytdl.list') ) { + file_put_contents("/tmp/ytdl.list","CopyLibre||$lnk\n", FILE_APPEND); + } + $result.='

LIEN: '.$lnk.'

'; +/////////////////// + // TRACK COPY (not for undefined or local file) + } else if ($radio && $artist != $title && $artist != "undefined" && $title != "undefined" && strlen(explode(".", $title)[1]) != 3 && explode(".", $title)[1] != "opus" ) { + // Not making double request + if( ! exec('grep '.escapeshellarg($cmd).' /tmp/ytdl.list') ) { + shell_exec('_GPATH/_CopyLaRadio/parle.sh "Enregistrement ajouté."'); + file_put_contents("/tmp/ytdl.list","$cmd\n", FILE_APPEND); + } else { + shell_exec('_GPATH/_CopyLaRadio/parle.sh "Copie déjà lancée"'); + } + $result.=' +

'.$artist.' / '.$title.'

+
'; +/////////////////// + // RADIO EXTERNAL TRACK SCRAPER + } else if($radio != "" && $artist == "undefined" && $title == "undefined" ){ + shell_exec('_GPATH/_CopyLaRadio/parle.sh "Recherche externe pour '.$radio.'"'); + file_put_contents("/tmp/youtube-dl.log", "_GPATH/_CopyLaRadio/libradio/".escapeshellcmd($radio).".php".PHP_EOL, FILE_APPEND); + if ( file_exists("_GPATH/_CopyLaRadio/libradio/".escapeshellcmd($radio).".php") ) { + file_put_contents("/tmp/ytdl.list","$radio||".PHP_EOL, FILE_APPEND); + } else { + shell_exec('_GPATH/_CopyLaRadio/parle.sh "Aucun module"'); + } + + } else { + shell_exec('_GPATH/_CopyLaRadio/parle.sh "Identification imprécise. Podcast? Fichier local?"'); + } + +} + +$ytform = '
+
+

ARTISTE:

+

TITRE:

+
+ + +
+ +
+'; + +$lnkform.='
+ +

youtube-dl

+- Sites compatibles - + + +

+
+ +
+
'; + +?> + + + + + + + + <?php echo $search;?> - Recherche YouTube & Copie privée + + + +
+
+
+
+
    + +
    +
+
    + +
    + +
    +
+ +
+
+
+
+ + diff --git a/.install/templates/init.sh b/.install/templates/init.sh index 672085c..7f5a01b 100755 --- a/.install/templates/init.sh +++ b/.install/templates/init.sh @@ -4,6 +4,11 @@ # Version: 0.1 # License: GPL (http://www.google.com/search?q=GPL) ################################################################## + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized +source $MY_PATH/.install/.GPATH + # Adapter les valeurs au contexte spatio-temporel du NODE G1SMS function log () { # log ($1=text) @@ -31,8 +36,7 @@ fi export YOU=$(ps auxf --sort=+utime | grep -w ipfs | grep -v -E 'color=auto|grep' | tail -n 1 | cut -d " " -f 1); - export CHEMIN="/home/$YOU/G1sms+" - cd $CHEMIN + cd $GPATH ################################################################## # Activate logging to /tmp/g1sms.log (YES/NO) export DOLOG="YES" @@ -75,5 +79,5 @@ fi # TODO Use latest Silkaj from "sudo fredp3 install silkaj" # export SILKAJ="/usr/local/bin/silkaj" - source $CHEMIN/shell/init_keys.sh + source $GPATH/shell/init_keys.sh diff --git a/GSM_POWERKEY.py b/GSM_POWERKEY.py deleted file mode 100755 index 037387e..0000000 --- a/GSM_POWERKEY.py +++ /dev/null @@ -1,10 +0,0 @@ -import RPi.GPIO as GPIO -import time -GPIO.setmode(GPIO.BOARD) -GPIO.setup(7, GPIO.OUT) -while True: - GPIO.output(7, GPIO.LOW) - time.sleep(4) - GPIO.output(7, GPIO.HIGH) - break -GPIO.cleanup() diff --git a/_CopyLaRadio/copy.sh b/_CopyLaRadio/copy.sh index 8391a86..c94b441 100755 --- a/_CopyLaRadio/copy.sh +++ b/_CopyLaRadio/copy.sh @@ -1,5 +1,9 @@ #!/bin/bash +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized +source $MY_PATH/../.install/.GPATH + # Clean /tmp/ytdl.list #echo > /tmp/ytdl.list @@ -74,9 +78,9 @@ elif [[ "$radio" != "" && "$artist" == "" && "$song" == "" ]]; then # EXTERNAL PARSER: ADD SCRAPERS IN ./libradio ~/parle.sh "Recherche RADIO ${radio}" echo "External search: ${radio}" >> /tmp/youtube-dl.log 2>&1 - if [[ -f /home/pi/G1sms+/_CopyLaRadio/libradio/${radio}.php ]]; then + if [[ -f $GPATH/_CopyLaRadio/libradio/${radio}.php ]]; then ~/parle.sh "Module existant" - php "/home/pi/G1sms+/_CopyLaRadio/libradio/${radio}.php" + php "$GPATH/_CopyLaRadio/libradio/${radio}.php" else ~/parle.sh "Aucun module de décodage pour cette radio." fi diff --git a/GSM_powerkey.sh b/debug/GSM_powerkey.sh similarity index 54% rename from GSM_powerkey.sh rename to debug/GSM_powerkey.sh index 3615018..5526df2 100755 --- a/GSM_powerkey.sh +++ b/debug/GSM_powerkey.sh @@ -1,9 +1,16 @@ #!/bin/bash + +MY_PATH="`dirname \"$0\"`" +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" + if [ ! -e /sys/class/gpio/gpio4 ]; then - echo "File exists." + echo "File doesn't exists." echo "4" > /sys/class/gpio/export fi + echo "out" > /sys/class/gpio/gpio4/direction -echo "0" > /sys/class/gpio/gpio4/value -sleep 2 echo "1" > /sys/class/gpio/gpio4/value + +sleep 3 && $MY_PATH/gammu-restart.sh + +exit 0 diff --git a/debug/smsc.txt b/debug/smsc.txt new file mode 100644 index 0000000..1dd1c98 --- /dev/null +++ b/debug/smsc.txt @@ -0,0 +1,5 @@ ++33695000695 ++33695000647 ++33695000646 ++33695000643 ++33695000636 diff --git a/install.sh b/install.sh index 0ecd354..e44d8bb 100755 --- a/install.sh +++ b/install.sh @@ -6,6 +6,10 @@ ################################################################################ MY_PATH="`dirname \"$0\"`" # relative MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + +echo "GPATH=$MY_PATH" > $MY_PATH/.install/.GPATH +source $MY_PATH/.install/.GPATH + init_loc="$MY_PATH/shell/init.sh" now=$(date +%Y-%m-%d) unset err @@ -47,7 +51,7 @@ $MY_PATH/.install/export_colors.sh if [[ $force_req == "o" || -z $(which ipfs) || -z $(which gammu) ]];then echo -e "${c_yellow}IPFS ou gammu n'ont pas été détectés sur votre machine, nous allons installer tous les prérequis...$c_" $MY_PATH/.install/1-install_requirements.sh silkaj ipfs gammu || err+=1 - $MY_PATH/.install/2-configure_ipfs_layer.sh || err+=1 + $MY_PATH/.install/2a-configure_ipfs_layer.sh || err+=1 else echo -e "${c_green}IPFS et gammu sont déjà installé !$c_" fi @@ -66,7 +70,10 @@ if [[ -f $MY_PATH/.install/templates/init.sh ]]; then [[ ! $ADRESSE ]] && echo -e "${c_light}L'adresse où se trouve votre G1Node pour indiquer où venir chercher ses G1Tag (ex: au G1FabLab de Toulouse)$c_" && read ADRESSE - echo -e "ADMINPSEUDO: $ADMINPSEUDO\nADMINPHONE: $ADMINPHONE\nMASTERPHONE: $MASTERPHONE\nADRESSE: $ADRESSE" + [[ ! $PIN ]] && echo -e "${c_light}Le code PIN de votre carte SIM ? (ex: 1234)$c_" && read PIN + [[ "$PIN" == "" ]] && PIN="1234" + + echo -e "ADMINPSEUDO: $ADMINPSEUDO\nADMINPHONE: $ADMINPHONE\nMASTERPHONE: $MASTERPHONE\nADRESSE: $ADRESSE\nPIN: $PIN" [[ $noask != "o" ]] && echo -e "${c_light}${c_blue}LES PARAMETRES SONT BONS? Appliquer? ENTER ou CTRL-C ? (Editez le fichier .profile si incorrect)$c_" && read [[ -f shell/init.sh ]] && mv shell/init.sh shell/init.sh.old @@ -83,6 +90,7 @@ if [[ -f $MY_PATH/.install/templates/init.sh ]]; then sed -i s/_ADRESSE/$ADRESSE/g $MY_PATH/.profile sed -i s/_ADMINPHONE/$ADMINPHONE/g $MY_PATH/.profile sed -i s/_ADMINPSEUDO/$ADMINPSEUDO/g $MY_PATH/.profile + sed -i s/_PIN/$PIN/g $MY_PATH/.profile fi else @@ -91,6 +99,9 @@ else exit 1 fi +## Configuration de gammu +$MY_PATH/.install/2b-configure_gammu.sh || err=1 + ## Installations optionnels repOld=$repOption diff --git a/search b/search index b2c0947..f5b8195 100755 --- a/search +++ b/search @@ -2,7 +2,7 @@ clear echo "------------------------------------------------------------------------------" if [ "$1" == "" ]; then - echo " Nothing to search for!" + echo " Nothing to search for!" else echo " Searching for "$1" recursively. Please Wait..." echo "------------------------------------------------------------------------------" @@ -10,7 +10,7 @@ else fi echo "------------------------------------------------------------------------------" if [ "$2" != "" ]; then - echo " To replace \"$1\" whith \"$2\", please run" + echo " To replace \"$1\" whith \"$2\", please run" echo " grep -rl '$1' ./ | xargs sed -i 's/$1/$2/g'" fi diff --git a/shell/cron_MINUTE.sh b/shell/cron_MINUTE.sh index 483b68f..9e6c50f 100755 --- a/shell/cron_MINUTE.sh +++ b/shell/cron_MINUTE.sh @@ -7,10 +7,14 @@ # CE FICHIER cron_MINUTE.sh EST EXECUTE TOUTES LES MINUTES # IL CONSTITUE LE BATEMENT DE COEUR DU SYSTEME ################################################################################ + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized +source $MY_PATH/../.install/.GPATH + YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) IPFSNODEID=$(su $YOU -c "ipfs id -f='\n'") -CHEMIN="/home/$YOU/G1sms+" -cd $CHEMIN +cd $GPATH source ./shell/init.sh source ./shell/functions.sh diff --git a/shell/init.sh.old b/shell/init.sh.old index 65517c1..7a2984a 100755 --- a/shell/init.sh.old +++ b/shell/init.sh.old @@ -5,6 +5,11 @@ # License: GPL (http://www.google.com/search?q=GPL) ################################################################## # Adapter les valeurs au contexte spatio-temporel du NODE G1SMS + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized +source $MY_PATH/../.install/.GPATH + function log () { # log ($1=text) if [ "$DOLOG" == "YES" ] @@ -31,8 +36,7 @@ fi export YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) - export CHEMIN="/home/$YOU/G1sms+" - cd $CHEMIN + cd $GPATH ################################################################## # Activate logging to /tmp/g1sms.log (YES/NO) export DOLOG="YES" @@ -75,5 +79,5 @@ fi # TODO Use latest Silkaj from "sudo fredp3 install silkaj" # export SILKAJ="/usr/local/bin/silkaj" - source $CHEMIN/shell/init_keys.sh + source $GPATH/shell/init_keys.sh diff --git a/shell/init_keys.sh b/shell/init_keys.sh index 67210aa..eb495a9 100755 --- a/shell/init_keys.sh +++ b/shell/init_keys.sh @@ -6,9 +6,13 @@ ################################################################## # CHECK & WARN | CREATE Keys (gpg encrypt, G1wallet, IPNS publish) ################################################################## + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized +source $MY_PATH/.install/.GPATH + YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) # TODO Make it directory independant. (for now it is tested for pi running ipfs and code in $HOME/G1sms+ -CHEMIN="/home/$YOU/G1sms+" ################################################################## # G1sms+ Node KEYS (G1wallet, gpg, IPNS) @@ -20,17 +24,17 @@ if [ ! $GPGPASS ]; then echo "FATAL ERROR:: IPFS Node.Identity.PrivKey GPGPASS E # G1sms+ Swarm KEYS ################################################################## # G1sms Service - G1Wallet -if [[ -f "${CHEMIN}/g1sms.pub.key" && -f "${CHEMIN}/g1sms.priv.key" ]]; then - chown root:root ${CHEMIN}/g1sms.priv.key - chmod 600 ${CHEMIN}/g1sms.priv.key - export MASTERPUB=$(cat "${CHEMIN}/g1sms.pub.key") - export MASTERKEYFILE="${CHEMIN}/g1sms.priv.key" +if [[ -f "${GPATH}/g1sms.pub.key" && -f "${GPATH}/g1sms.priv.key" ]]; then + chown root:root ${GPATH}/g1sms.priv.key + chmod 600 ${GPATH}/g1sms.priv.key + export MASTERPUB=$(cat "${GPATH}/g1sms.pub.key") + export MASTERKEYFILE="${GPATH}/g1sms.priv.key" else echo "ATTENTION!! Vous devez posséder la clef du G1 Wallet utilisé par le SWARM G1sms!!" ./shell/parle.sh "Les clefs du portefeuille essaim G1 SMS sont absente. Au revoir." echo "Fichiers manquants:" - echo "${CHEMIN}/g1sms.pub.key" - echo "${CHEMIN}/g1sms.priv.key" + echo "${GPATH}/g1sms.pub.key" + echo "${GPATH}/g1sms.priv.key" echo "Contactez nous sur https://g1sms.fr" gammu-smsd-inject -l TEXT "$ADMINPHONE" -text "Clef de G1Wallet du SWARM g1sms.priv.key manquante! contactez-nous pour la recevoir https://g1sms.fr" 1>&2 exit diff --git a/shell/sms_EMAIL.sh b/shell/sms_EMAIL.sh index 2ebba7b..14d901a 100755 --- a/shell/sms_EMAIL.sh +++ b/shell/sms_EMAIL.sh @@ -7,9 +7,10 @@ # sudo apt install ssmtp mpack # Configure in /etc/ssmtp # Send email with file attachement: mpack -s "Logo G1Tag" /home/pi/G1sms+/G1Tag.png dest@email.ext - + source ./shell/init.sh source ./shell/functions.sh + log "__SUB:sms_EMAIL.sh.sh: START ($1=phone, $2=mail)" phone="$1" diff --git a/sms_received.sh b/sms_received.sh index 4bf00d5..c6d1f93 100755 --- a/sms_received.sh +++ b/sms_received.sh @@ -27,14 +27,16 @@ # License: GPL (http://www.google.com/search?q=GPL) ################################################################################ +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + # Execute Kalkun daemon [[ -f /var/www/kalkun/scripts/daemon.sh ]] && /var/www/kalkun/scripts/daemon.sh export YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) -export CHEMIN="/home/$YOU/G1sms+" -cd $CHEMIN -source ./shell/init.sh -source ./shell/functions.sh +cd $GPATH +source $MY_PATH/shell/init.sh +source $MY_PATH/shell/functions.sh ################################################################## # Get global variables from gammu-smsd diff --git a/www/rompr/REC/youtube-dl.php b/www/rompr/REC/youtube-dl.php index 26e2eda..ad1d71d 100644 --- a/www/rompr/REC/youtube-dl.php +++ b/www/rompr/REC/youtube-dl.php @@ -1,11 +1,11 @@ [REC]'; +// ZEEBOX HACK ZONE + var reclink = '/REC/youtube-dl.php?q=REC&artist=' + escape(encodeURIComponent(npinfo.Artist)) + '&title=' + escape(encodeURIComponent(npinfo.Title)) + '&radio='+ escape(encodeURIComponent(npinfo.stream)) +'&maxResults=1'; + var zcopylink = ' [REC]'; zcopylink += ' *'; - lines[0].text += zcopylink; + lines[0].text += zcopylink; // ZEEBOX HACK ZONE */ // RUN CLI if($argc>1) parse_str(implode('&',array_slice($argv, 1)), $_REQUEST); @@ -22,7 +22,7 @@ $len=strlen($artist.$title); //$result='
'; $result='
'; if( $radio == "" ) { $radio = "CopyLaRadio"; } -if( $radio == "Nova zz" ) { +if( $radio == "Nova zz" ) { $artist = "undefined"; $title = "undefined"; } @@ -62,7 +62,7 @@ if( $search == "REC" ) { } else { shell_exec('/home/pi/G1sms+/_CopyLaRadio/parle.sh "Aucun module"'); } - + } else { shell_exec('/home/pi/G1sms+/_CopyLaRadio/parle.sh "Identification imprécise. Podcast? Fichier local?"'); } @@ -116,10 +116,10 @@ $lnkform.='

    - +
- + From cb07116eb8a6cd476064718ee406e048c092ae4e Mon Sep 17 00:00:00 2001 From: qo-op Date: Sat, 21 Dec 2019 22:58:36 +0100 Subject: [PATCH 20/26] G1Billets and some more --- .install/2b-configure_gammu.sh | 22 ++++++++-------- .install/templates/init.sh | 3 ++- _chain | 2 +- _comments | 1 + _nanodate | 2 +- _publishkey.gpg | Bin 1288 -> 1288 bytes shell/G1Billet_LOVE.png | Bin 0 -> 78936 bytes shell/G1sms.png | Bin 35854 -> 0 bytes shell/{OLove.jpg => OneLove.jpg} | Bin shell/cron_MINUTE.sh | 9 +++++++ shell/functions.sh | 2 +- shell/init.sh.old | 16 ++++++------ shell/init_keys.sh | 6 ++++- shell/manual_BILLETS_PERIMES.sh | 2 +- shell/sms_BILLET.sh | 53 +++++++++++++++++++++++---------------- shell/sms_BILLETCHK.sh | 14 +++++------ shell/sms_BILLET_MAKE.sh | 29 ++++++++++++--------- shell/sms_EMAIL.sh | 4 +-- shell/tag_READ_X.sh | 10 ++++---- sms_received.sh | 4 +-- 20 files changed, 105 insertions(+), 74 deletions(-) mode change 100644 => 100755 .install/2b-configure_gammu.sh create mode 100644 shell/G1Billet_LOVE.png delete mode 100644 shell/G1sms.png rename shell/{OLove.jpg => OneLove.jpg} (100%) diff --git a/.install/2b-configure_gammu.sh b/.install/2b-configure_gammu.sh old mode 100644 new mode 100755 index 4940c5c..c4ce55c --- a/.install/2b-configure_gammu.sh +++ b/.install/2b-configure_gammu.sh @@ -8,15 +8,20 @@ source $MY_PATH/../.install/.GPATH [[ -f $MY_PATH/../.profile ]] && source $MY_PATH/../.profile ## Désactive les processus écoutant le tty1 -[[ $(sudo systemctl status getty@tty1.service | grep "loaded") ]] && sudo systemctl stop getty@tty1.service && sudo systemctl disable getty@tty1.service +[[ $(sudo systemctl status getty@tty1.service | grep "loaded" 2>/dev/null) ]] && sudo systemctl stop getty@tty1.service && sudo systemctl disable getty@tty1.service -## Copie et sed de /etc/gammu-smsdrc -[[ -f /etc/gammu-smsdrc ]] && sudo mv /etc/gammu-smsdrc /etc/gammu-smsdrc.old && echo "/etc/gammu-smsdrc a été renommé en /etc/gammu-smsdrc.old" -sudo cp $MY_PATH/templates/2b/gammu-smsdrc /etc/ +if [[ -z $(grep "PIN" /etc/gammu-smsdrc) ]]; then + ## Copie et sed de /etc/gammu-smsdrc + [[ -f /etc/gammu-smsdrc ]] && sudo mv /etc/gammu-smsdrc /etc/gammu-smsdrc.old && echo "/etc/gammu-smsdrc a été renommé en /etc/gammu-smsdrc.old" + sudo cp $MY_PATH/templates/2b/gammu-smsdrc /etc/ -GPATHS=$(echo $GPATH | sed 's./.\\/.g') -sudo sed -i "s/_GPATH/$GPATHS/g" /etc/gammu-smsdrc -sudo sed -i "s/_PIN/$PIN/g" /etc/gammu-smsdrc + GPATHS=$(echo $GPATH | sed 's./.\\/.g') + sudo sed -i "s/_GPATH/$GPATHS/g" /etc/gammu-smsdrc + sudo sed -i "s/_PIN/$PIN/g" /etc/gammu-smsdrc + + ## Redémarre gammu-smsd + sudo service gammu-smsd restart && echo -e "${c_green}Gammu a été correctement configuré$c_" || echo -e "${c_green}Un problème est survenu lors de la configuration de gammu$c_" +fi ## Configure correctement le UART @@ -28,7 +33,4 @@ sudo sed -i "s/_PIN/$PIN/g" /etc/gammu-smsdrc -## Redémarre gammu-smsd -sudo service gammu-smsd restart && echo -e "${c_green}Gammu a été correctement configuré$c_" || echo -e "${c_green}Un problème est survenu lors de la configuration de gammu$c_" - exit 0 diff --git a/.install/templates/init.sh b/.install/templates/init.sh index 7f5a01b..8a17973 100755 --- a/.install/templates/init.sh +++ b/.install/templates/init.sh @@ -7,7 +7,8 @@ MY_PATH="`dirname \"$0\"`" # relative MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized -source $MY_PATH/.install/.GPATH +if [[ -f $MY_PATH/.install/.GPATH ]]; then source $MY_PATH/.install/.GPATH; fi +if [[ -f $MY_PATH/../.install/.GPATH ]]; then source $MY_PATH/../.install/.GPATH; fi # Adapter les valeurs au contexte spatio-temporel du NODE G1SMS function log () { diff --git a/_chain b/_chain index 08f5b4c..d4047b1 100755 --- a/_chain +++ b/_chain @@ -1 +1 @@ -QmaN3w2NGxejb8yNN1sP4fvnfDV3YDghStcjbyLr7zchCC +QmdKvkQL65ibGXEBXGxZZu9a58udDCZPutC1NZQfFm9sDT diff --git a/_comments b/_comments index 8d6d3ca..8fbc500 100755 --- a/_comments +++ b/_comments @@ -176,3 +176,4 @@ OK 2019-12-17: G1TAG REFRESH & more 2019-12-18: RAZ 2019-12-20: NOW +2019-12-21: Various diff --git a/_nanodate b/_nanodate index 1a8bd2e..e24818e 100755 --- a/_nanodate +++ b/_nanodate @@ -1 +1 @@ -1576803110070568420 +1576935242369880952 diff --git a/_publishkey.gpg b/_publishkey.gpg index 69ba96ad3a4a3b7aea51459ca6324f9636c1f003..17c8a492b8cf7a7edd17484264c4b2c603e01c55 100755 GIT binary patch literal 1288 zcmV+j1^4=l4Fm}T0yy?Mh-%A@%)!#?0gCkbez|TDq+9XRByFu2sA%x%|;}wsC8-^vl)0xh|FvWx;RBzE{Z&lh1 zqiQgL4Zw8{iTP^TnJ?}G!T3~;?}Gc+p%r{*LcBYLh~k=zZy;XvN$-tW!bliFZ$V9% zns)i{w{|6hzEEUF$n!#S2C3#=KbyNVYSh=ymThF{#LZPVG?OKD3s#|{#FjG=d7_*O zxYgNHD^RFTSlMaI93j*wG0bQ4omGvZ&>H(n1gZTV;S2NA0uAyPSWSev9TJwpgbEOe zn>Z}h$t1WbdRKmcWbF&>kT>!V{7PsGq&g&<1SScp@YyZ02HXK?Y7xP#+e|N1ojJGW z`9H6%As^1e*p?nFUOi(5)~UrP-lW1MYr8#l-b2axS5L81z$AgDE8XC&_v^7`gIzq1ij>;JNB0%m1_)J_wGf0tfin3DFI zA)03ci{e($WJ)la*@{PpjTWDsxSa%ltNSfsLKs*JVJN1ojAx^rV-yDGi!F+ zY#KIyrZtOAZY+`L_XR{wx7A4j25_3FHFg`-9ozy<>-6b)ww~}}GWcB+6a;Z-G)&t0 zhr56L*qQ~I zcGTL00vkKD-XCUwp=n}XJE`Zm-cDbL&M4>P1O>Pagd(#1)aC#Lz5d zDBgTgQNffBle^WSH!oRye#7T6%Kan?vHU$l3%(6tW)6yMh3E`$Dsj>mP)<;uI1XcV9IvHbhF=@0=rFwW`NpvmV zO{DE@onOp~Q@9^0*}|bO?U_KcB|!5T zoX%RvGXh>d(+T^4%yc5Fk-97NapF?#V<*7Q0CV@H^l|~xD8MAh(}8f$B$Qp2`J#OB zVLTR<^B*s#Ss7eE*@`sS@zjo|Da~@Z#6ZVAhT5}%Hn^XpB3-sq#fkSycm-^LCf00@6gYls(p$8 literal 1288 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 ej}61PXZRcFwhdPiPBQ!e0000W|a02y>e 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 u(@Z_!^G&2 + gammu-smsd-inject TEXT "$dest" -text "$mess" 1>&2 else # Send SMS through $dest NODE (TODO: send it like PRINT, TASK, ...) DESTNODEID=$(cat ./wallets_swarm/$dest/MASTERPHONE.ipfsid) diff --git a/shell/init.sh.old b/shell/init.sh.old index 7a2984a..ca20a67 100755 --- a/shell/init.sh.old +++ b/shell/init.sh.old @@ -1,15 +1,15 @@ #!/bin/bash ################################################################## -# Author: poka (support@qo-op.com) +# Author: Fred (support@qo-op.com) # Version: 0.1 # License: GPL (http://www.google.com/search?q=GPL) ################################################################## -# Adapter les valeurs au contexte spatio-temporel du NODE G1SMS MY_PATH="`dirname \"$0\"`" # relative MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized -source $MY_PATH/../.install/.GPATH +source $MY_PATH/.install/.GPATH +# Adapter les valeurs au contexte spatio-temporel du NODE G1SMS function log () { # log ($1=text) if [ "$DOLOG" == "YES" ] @@ -35,7 +35,7 @@ export G1SMS="YES" fi - export YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) + export YOU=$(ps auxf --sort=+utime | grep -w ipfs | grep -v -E 'color=auto|grep' | tail -n 1 | cut -d " " -f 1); cd $GPATH ################################################################## # Activate logging to /tmp/g1sms.log (YES/NO) @@ -65,13 +65,13 @@ fi export NODECOMM=10 ################################################################## # SMS SIM Card Phone Number - export MASTERPHONE="+3368818767" - export ADRESSE="Blois" + export MASTERPHONE="+33651136520" + export ADRESSE="G1_Fablab_Toulouse" export G1DAB="NO" ################################################################## # ADMIN COMMAND PHONE ORIGIN - export ADMINPHONE="+33650573417" - export ADMINPSEUDO="poka" + export ADMINPHONE="+33647683646" + export ADMINPSEUDO="Fred" ################################################################## # DUNITER/CESIUM+ DEFAULT SERVERS export DUNITER="https://g1.duniter.org" diff --git a/shell/init_keys.sh b/shell/init_keys.sh index 5d6a089..4fb94f2 100755 --- a/shell/init_keys.sh +++ b/shell/init_keys.sh @@ -9,7 +9,8 @@ MY_PATH="`dirname \"$0\"`" # relative MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized -source $MY_PATH/../.install/.GPATH +if [[ -f $MY_PATH/.install/.GPATH ]]; then source $MY_PATH/.install/.GPATH; fi +if [[ -f $MY_PATH/../.install/.GPATH ]]; then source $MY_PATH/../.install/.GPATH; fi YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) # TODO Make it directory independant. (for now it is tested for pi running ipfs and code in $HOME/G1sms+ @@ -36,7 +37,10 @@ else echo "${GPATH}/g1sms.pub.key" echo "${GPATH}/g1sms.priv.key" echo "Contactez nous sur https://g1sms.fr" + log "${GPATH}/g1sms.pub.key" + log "${GPATH}/g1sms.priv.key" gammu-smsd-inject -l TEXT "$ADMINPHONE" -text "Clef de G1Wallet du SWARM g1sms.priv.key manquante! contactez-nous pour la recevoir https://g1sms.fr" 1>&2 + gammu-smsd-inject -l TEXT "$ADMINPHONE" -text "Debug: ${GPATH}/g1sms.pub.key et ${GPATH}/g1sms.priv.key" 1>&2 exit fi diff --git a/shell/manual_BILLETS_PERIMES.sh b/shell/manual_BILLETS_PERIMES.sh index 79d4e21..92439a2 100755 --- a/shell/manual_BILLETS_PERIMES.sh +++ b/shell/manual_BILLETS_PERIMES.sh @@ -9,7 +9,7 @@ source ./shell/init.sh source ./shell/functions.sh # Existence days number can be $1 -if [[ "$1" ]]; then vieux="$1"; else vieux=180; fi +if [[ "$1" ]]; then vieux="$1"; else vieux=210; fi if [[ "$2" ]]; then dest="$2"; else dest=$MASTERPUB; fi echo "Recherche de G1Billets plus vieux que $vieux jours." diff --git a/shell/sms_BILLET.sh b/shell/sms_BILLET.sh index 5fe9d18..11d03d1 100755 --- a/shell/sms_BILLET.sh +++ b/shell/sms_BILLET.sh @@ -59,38 +59,43 @@ testmin=$( echo "${VIR} < ${MIN}" | bc -l ) log "TEST : $VIR < $MIN ? $testmin" # silkaj NODE CHANGE !!! -SILKAJNODE=$(./shell/checknodes.sh) -log "NEW SILKAJ NODE: $SILKAJNODE" +#SILKAJNODE=$(./shell/checknodes.sh) +#log "NEW SILKAJ NODE: $SILKAJNODE" if [[ "$testmin" -eq "1" ]] then + # Clean MEMBER directory + rm -f ./billets/MEMBERS/$MEMBER/*.jpg boucle=0; while [ $boucle -lt $NBbillets ] do # Creation du numéro de billet - NUMBER=$(./shell/diceware.sh 4 | xargs) + NUMBER=$(./shell/diceware.sh 2 | xargs) bpath=$(echo $NUMBER | sed 's/ /_/g') # Cas d'un billet existant while [ -d "./billets/$bpath" ] do - NUMBER=$(./shell/diceware.sh 4 | xargs) + NUMBER=$(./shell/diceware.sh 2 | xargs) bpath=$(echo $NUMBER | sed 's/ /_/g') done SECRET=$(./shell/diceware.sh 3 | xargs) - SALT=$(./shell/diceware.sh 3 | xargs) + + # ADD/REMOVE G1sms forced control over G1Billet + # SALT=$(./shell/diceware.sh 3 | xargs) + SALT="" boucle=$(bc -l <<< "$boucle + 1") log "->BILLET:$PHONE:$NUMBER:$VALbillet:$UNIT" # CREATE "NUMBER SECRET SALT" ACCOUNT for G1 transfert TRANSAC=$(bc -l <<< "scale=2; $VIR / $NBbillets") - BILLETPUBKEY=$(./silkaj/silkaj generate_auth_file --auth-scrypt -salt="$NUMBER" -password="$SECRET $SALT") + BILLETPUBKEY=$(./silkaj/silkaj generate_auth_file --auth-scrypt -salt="$NUMBER" -password="$SECRET$SALT") log_history $PHONE "BILLET, $TRANSAC, $BILLETPUBKEY" sleep 3 # Fill BILLET with TRANSAC amount - PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$TRANSAC" --output="$BILLETPUBKEY" --comment="THIRD_PARTY_MANAGER:$MASTERPUB:G1SMS:BILLET" -y) + PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$TRANSAC" --output="$BILLETPUBKEY" --comment="G1Billet $NUMBER" -y) if [[ "$(echo $PAY | cut -d '|' -f 1)" != "KO" ]]; then mkdir -p "./billets/$bpath" # NOTES ARE FILES STORED IN DICEWARE COMPOSED SUBDIR @@ -105,14 +110,16 @@ then log "Remplissage: $TRANSAC G1... $BILLETPUBKEY = $PAY" # CREATION FICHIER IMAGE BILLET - $(./shell/sms_BILLET_MAKE.sh "$NUMBER" "$SECRET" "$VALbillet" "$UNIT" "$DUFACTOR" "$BILLETPUBKEY" "$MEMBER" "$TRANSAC") - log "./shell/sms_BILLET_MAKE.sh \"$NUMBER\" \"$SECRET\" \"$VALbillet\" \"$UNIT\" \"$DUFACTOR\" \"$BILLETPUBKEY\" \"$MEMBER\" \"$TRANSAC\"" + $(./shell/sms_BILLET_MAKE.sh "$NUMBER" "$SECRET" "$VALbillet" "$UNIT" "$TRANSAC" "$BILLETPUBKEY" "$MEMBER" "$TRANSAC" "$PHONE") + log "./shell/sms_BILLET_MAKE.sh \"$NUMBER\" \"$SECRET\" \"$VALbillet\" \"$UNIT\" \"$TRANSAC\" \"$BILLETPUBKEY\" \"$MEMBER\" \"$TRANSAC\" \"$PHONE\"" # Transaction to create Link BILLET <-> MEMBER RIB => Decrease BILLET value ! sleep 2 # PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$NUMBER" -password="$SECRET $SALT" --amount="0.05" --output="$MEMRIB" --comment="THIRD_PARTY_MANAGER:$MASTERPUB:G1SMS:BILLET:$VALbillet:$UNIT:$NUMBER" -y) else sms_ERROR "$PHONE" "Un problème est survenu. Contactez $ADMINPSEUDO au $ADMINPHONE" + log "ERROR SILKAJ" + exit fi done @@ -120,22 +127,26 @@ then sleep 2 COM=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$BILLCOM" --output="$MASTERPUB" --comment="[G1SMS] G1billet Commission" -y) - # IMPRIMER LES BILLETS! Brancher votre imprimante et configurer cups avant ;) + # POUR IMPRIMER LES BILLETS! Brancher votre imprimante, configurer cups, activer code lp ;) num=$(date +%Y%m%d) log "PRINT $num $MEMBER" - montage ./billets/MEMBERS/$MEMBER/*.jpg -tile 2x3 -geometry 964x459 /tmp/$PHONE_Bills_$bpath.pdf -# lp /tmp/$PHONE_Bills_$bpath.pdf - cp /tmp/$PHONE_Bills_$bpath.pdf ./billets/MEMBERS/$MEMBER/ - zip ./_Bill_$MEMBER_$num.zip ./billets/MEMBERS/$MEMBER/*.jpg && rm -f ./billets/MEMBERS/$MEMBER/*.jpg + montage ./billets/MEMBERS/$MEMBER/*.jpg -tile 2x3 -geometry 964x459 /tmp/$PHONE_Bills_$bpath.pdf && rm -f ./billets/MEMBERS/$MEMBER/*.jpg && log "PDF made /tmp/$PHONE_Bills_$bpath.pdf" + zip /tmp/$PHONE_Bills_$bpath.zip /tmp/$PHONE_Bills_$bpath.pdf && rm -f /tmp/$PHONE_Bills_$bpath.pdf && log "Zip done. Remove PDF" - # SEND EMAIL - # Détruit ce mail et le pdf après impression et fabrication des billets au code caché. - # Créer la monnaie implique une grande responsabilité! - + # SEND EMAIL ZIP attached + echo "Commande #$NANODATE/$bpath +>> Planche de 6 G1Billets : $VALbillet LOVE << +Ecrivez-nous vos remarques... +Cesium: https://cesium.app +SMS: https://g1sms.fr" > /tmp/message_body.txt + mpack -s "[G1sms+]_G1Billets ($bpath) Imprimer + Scotch à gratter! Détruire cet email..." -d /tmp/message_body.txt /tmp/$PHONE_Bills_$bpath.zip $MAIL && rm /tmp/$PHONE_Bills_$bpath.zip && log "EMAIL sent....." + mpack -s "[G1sms+]_G1Billets ($bpath) imprimer recto/verso vos G1Billets?!" -d /tmp/message_body.txt ./Dos_G1Billets.odt $MAIL && log "+ EMAIL recto: OK" + log "G1Billets $PHONE_Bills_$bpath.pdf envoyé par email à $MEMBER : $MAIL " mess="[G1SMS] -$NBbillets billet(s) de $VALbillet $UNIT ($TRANSAC G1) créé(s). -Contactez $ADMINPSEUDO au $ADMINPHONE pour les recevoir... -http://g1sms.fr/g1sms/aide" +$NBbillets G1Billets de $VALbillet $UNIT ($TRANSAC G1) créé(s). +Envoyés vers $MAIL, vérifiez vos SPAM... +Support: $ADMINPSEUDO ($ADMINPHONE) +" sms_SEND "$phone" "$mess" diff --git a/shell/sms_BILLETCHK.sh b/shell/sms_BILLETCHK.sh index 5a46923..af688d3 100755 --- a/shell/sms_BILLETCHK.sh +++ b/shell/sms_BILLETCHK.sh @@ -41,24 +41,22 @@ https://www.g1sms.fr/contact" # Account creation sms_INIT_ACCOUNT "$PHONE" fi - log "./silkaj/silkaj transaction --auth-scrypt -salt=\"$CODE\" -password=\"$SEC $SALT\" --amount=\"$AMOUNTG1\" --output=\"$PUBKEY\" --comment=\"THIRD_PARTY_MANAGER:$MASTERPUB:G1SMS:ENCAISSEMENT:$CODE\" -y" - PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$CODE" -password="$SEC $SALT" --amount="$AMOUNTG1" --output="$PUBKEY" --comment="THIRD_PARTY_MANAGER:$MASTERPUB:ENCAISSEMENT:$CODE" -y) + log "./silkaj/silkaj transaction --auth-scrypt -salt=\"$CODE\" -password=\"$SEC$SALT\" --amount=\"$AMOUNTG1\" --output=\"$PUBKEY\" --comment=\"THIRD_PARTY_MANAGER:$MASTERPUB:G1SMS:ENCAISSEMENT:$CODE\" -y" + PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$CODE" -password="$SEC$SALT" --amount="$AMOUNTG1" --output="$PUBKEY" --comment="THIRD_PARTY_MANAGER:$MASTERPUB:ENCAISSEMENT:$CODE" -y) if [[ "$(echo $PAY | cut -d '|' -f 1)" != "KO" ]]; then # DESTROY BILLET - rm -f ./billets/$bpath/note.* - rmdir ./billets/$bpath + rm -Rf ./billets/$bpath # DESTROY PUBLIC CACHE in /tmp if [ -d "/tmp/billets_valides/$bpath" ]; then - rm -f /tmp/billets_valides/$bpath/* - rmdir /tmp/billets_valides/$bpath + rm -Rf /tmp/billets_valides/$bpath fi SOLDE=$(./silkaj/silkaj amount "$PUBKEY") mess="[G1SMS] ENCAISSEMENT de $VALbillet $UNIT ($AMOUNTG1 G1) -ds le porte-monnaie $PHONE ($PUBKEY) +dans portefeuille $UIDNA ($PHONE) OK! Solde: $SOLDE G1" sms_SEND "$PHONE" "$mess" @@ -66,7 +64,7 @@ Solde: $SOLDE G1" log "=> $PUBKEY" log_history $PHONE "BILLET_CHK, $AMOUNTG1, $bpath, $PUBKEY" else - sms_ERROR "$PHONE" "Erreur! Transaction Impossible... Réessayez plus tard ou contactez $ADMINPSEUDO : $ADMINPHONE" + sms_ERROR "$PHONE" "Erreur! Transaction Impossible! Valeur du G1Billet $AMOUNTG1 G1. Contactez $ADMINPSEUDO : $ADMINPHONE" fi fi else diff --git a/shell/sms_BILLET_MAKE.sh b/shell/sms_BILLET_MAKE.sh index 9b39a91..62fca10 100755 --- a/shell/sms_BILLET_MAKE.sh +++ b/shell/sms_BILLET_MAKE.sh @@ -17,10 +17,11 @@ NUMERO="$1" SECRET="$2" MONTANT="$3" UNIT="$4" -DUFACTOR="$5" +JUNE="$5" NOTERIB="$6" MEMBER="$7" TRANSAC="$8" +PHONE="$9" log "X ./shell/sms_BILLET_MAKE.sh \"$1\" \"$2\" \"$3\" \"$4\" \"$5\" \"$6\" \"$7\" \"$8\"" if [[ "$NOTERIB" == "" || "$MEMBER" == "" ]] @@ -43,17 +44,21 @@ fi valid="0${valid:0:2}" # ADD VALIDITY to convert: -pointsize 20 -draw 'text 380,410 "'"A encaisser avant le 01/$valid/$year"'"' \ -# Add G1sms logo (250px) -composite -compose Over -gravity SouthWest -geometry +50+50 "./shell/G1sms.png" "./shell/Oeuro.jpg" "/tmp/$NUMERO.jpg" +# ADD Avatar on G1 Logo SouthEast +if [[ $(file "./wallets/$PHONE/$PHONE.avatar.png" | grep 'PNG') ]]; then + composite -compose Over -gravity East -geometry +15+0 -dissolve 33% "./wallets/$PHONE/$PHONE.avatar.png" "./shell/Oeuro.jpg" "/tmp/$NUMERO.jpg" + composite -compose Over -gravity West -geometry +15+0 -dissolve 33% "./wallets/$PHONE/$PHONE.avatar.png" "/tmp/$NUMERO.jpg" "/tmp/$NUMERO.jpg" +fi + +# Add G1Billet_LOVE.png logo (250px) +composite -compose Over -gravity SouthWest -geometry +50+50 -dissolve 70% "./shell/G1Billet_LOVE.png" "/tmp/$NUMERO.jpg" "/tmp/$NUMERO.jpg" # Prepare BILLET qrcode verification URL -#qrencode "$NOTERIB" -o "/tmp/$NUMERO_NOTERIB.png" -REQ=$(echo $NUMERO | sed 's/ /_/g') -qrencode "https://www.g1sms.fr/$ADMINPSEUDO/check.php?code=$REQ" -o "/tmp/$NUMERO_NOTERIB.png" +qrencode -s 3 -o "/tmp/$NUMERO_NOTERIB.png" "$NOTERIB" -# BILL PUBKEY => Someone can Add amount to it !!! +# BILL PUBKEY means Someone can Add amount to it !!! # Add verification QRCode -composite -compose Over -gravity NorthEast -geometry +40+40 "/tmp/$NUMERO_NOTERIB.png" "/tmp/$NUMERO.jpg" "/tmp/$NUMERO.jpg" +composite -compose Over -gravity NorthEast -geometry +50+25 "/tmp/$NUMERO_NOTERIB.png" "/tmp/$NUMERO.jpg" "/tmp/$NUMERO.jpg" # Add June logo case "$MONTANT" in @@ -82,7 +87,7 @@ case "$MONTANT" in cp "./shell/g1.png" "/tmp/g1.png" ;; esac -composite -compose Over -gravity SouthEast -geometry +20+20 "/tmp/g1.png" "/tmp/$NUMERO.jpg" "/tmp/$NUMERO.jpg" +composite -compose Over -gravity SouthEast -geometry +20+20 -dissolve 90% "/tmp/g1.png" "/tmp/$NUMERO.jpg" "/tmp/$NUMERO.jpg" DUPART=$(bc -l <<< "scale=2; $MONTANT / 100") # ADD 0 to <1 DUPART @@ -95,11 +100,11 @@ fi convert -font 'Liberation-Sans' \ -pointsize 120 -fill black -draw 'text 200,220 "'"$DUPART DU"'"' \ -pointsize 45 -draw 'text 550,270 "'"$MONTANT $UNIT"'"' \ --pointsize 35 -draw 'text 50,60 "'"[G1sms] 06 66 80 57 20"'"' \ +-pointsize 35 -draw 'text 50,60 "'"$JUNE G1 [G1sms $MASTERPHONE]"'"' \ -pointsize 30 -draw 'text 60,100 "'"CHK $NUMERO"'"' \ -pointsize 22 -fill black -draw 'text 520,340 "'"$SECRET"'"' \ --pointsize 22 -fill black -draw 'text 400,410 "'"Encaisser avant le 01/$valid/$year"'"' \ --pointsize 20 -draw 'text 50,444 "'"Envoyer par sms, CHK $NUMERO + les mots découverts sous la zone à gratter"'"' \ +-pointsize 22 -fill black -draw 'text 400,410 "'"A encaisser avant le 01/$valid/$year"'"' \ +-pointsize 20 -draw 'text 50,444 "'"SMS: CHK $NUMERO + mots secrets à gratter ou https://cesium.app "'"' \ "/tmp/$NUMERO.jpg" "/tmp/BILL.$year.$valid.$NUMERO.$MONTANT.$UNIT.jpg" # Payable par SMS en envoyant les codes grattant la case comportant le SECRET diff --git a/shell/sms_EMAIL.sh b/shell/sms_EMAIL.sh index 14d901a..9df63c6 100755 --- a/shell/sms_EMAIL.sh +++ b/shell/sms_EMAIL.sh @@ -36,7 +36,7 @@ fi # SEND EMAIL WITH ssmtp SUBJECT="[G1sms+] $MEMBER, message de votre portefeuille monnaie libre $UIDNA ($PHONE)" -MESSAGE="Bonjour $MEMBER\n\nLe detenteur du porte-monnaie G1sms $UIDNA ($PHONE) a choisi votre email comme contact.\nVous y recevrez nos prochains envois ...\n\n\nA bientot <3\n$ADMINPSEUDO - ($MASTERPHONE) Partenaire G1sms+" +MESSAGE="Bonjour $MEMBER\n\nVotre porte-monnaie G1sms $UIDNA ($PHONE) a choisi votre email comme contact.\nPour commander vos G1Billets, envoyez par SMS à $MASTERPHONE :\nBILL 10/20/50/100/200/500/1000\n\n\nA bientot <3\n$ADMINPSEUDO - ($MASTERPHONE) Partenaire G1sms+" cat ./email.txt | sed s/EMAIL/"${mail}"/g | sed s/SUBJECT/"${SUBJECT}"/g | sed s/MESSAGE/"${MESSAGE}"/g | ssmtp ${mail} log "__SUB:sms_EMAIL.sh.sh: Send welcome EMAIL to $mail via ssmtp" log_history $PHONE "EMAIL, $mail" @@ -44,7 +44,7 @@ log_history $PHONE "EMAIL, $mail" mess="[G1sms+] $MEMBER Votre email est : $mail -Mettez le à jour, quand cela est nécessaire..." +Mettez le à jour, si cela est nécessaire..." sms_SEND "$phone" "$mess" diff --git a/shell/tag_READ_X.sh b/shell/tag_READ_X.sh index 538939c..efcb303 100755 --- a/shell/tag_READ_X.sh +++ b/shell/tag_READ_X.sh @@ -57,10 +57,10 @@ cat /dev/ttyACM0 | while read line; do FID=$(echo $ID | awk '{print toupper($1)}') RR=$(echo $ID | sed s/\ //g) - ./shell/tools/4LETTER.scroll.py "G1TAG $FID >" + ./shell/tools/4LETTER.scroll.py "${#act[@]} $FID > " RVALUE=$(su $YOU -c "ipfs cat /ipns/$J/TAG_amount"); CURRENCY=$(su $YOU -c "ipfs cat /ipns/$J/TAG_currency" | awk '{print tolower($1)}') - if [[ "$CURRENCY" == "zen" ]]; then CUR="zène"; else CUR=$CURRENCY; fi # Correction du défaut de prononciation. + PASSENGER=$(su $YOU -c "ipfs cat /ipns/$J/TAG_passenger"); if [[ "$PASSENGER" != "" ]]; then ./shell/tools/4LETTER.scroll.py "G1TAG PASSENGER $RVALUE ZEN" @@ -87,10 +87,10 @@ cat /dev/ttyACM0 | while read line; do FID=$(echo $ID | awk '{print toupper($1)}') RR=$(echo $ID | sed s/\ //g) - ./shell/tools/4LETTER.scroll.py "G1TAG [TX] $FID >" + ./shell/tools/4LETTER.scroll.py "${#act[@]} $FID TX >>" BVALUE=$(su $YOU -c "ipfs cat /ipns/$J/TAG_amount") CURRENCY=$(su $YOU -c "ipfs cat /ipns/$J/TAG_currency" | awk '{print tolower($1)}') - if [[ "$CURRENCY" == "zen" ]]; then CUR="zène"; else CUR=$CURRENCY; fi # Correction du défaut de prononciation. + PASSENGER=$(su $YOU -c "ipfs cat /ipns/$J/TAG_passenger"); # DIG PUBLISHING KEY if [[ -f /home/$YOU/.ipfs/keystore/$RR ]]; then @@ -122,7 +122,7 @@ cat /dev/ttyACM0 | while read line; do *) if [[ $lon -eq 44 ]]; then - ./shell/tools/4LETTER.scroll.py "PORTEFEUILLE G1 >>>>>>>>" & + ./shell/tools/4LETTER.scroll.py "PORTEFEUILLE G1 >>>>>>>> ${#act[@]}" & J=$qrvalue if [[ "$J" != "${obj[0]}" ]]; then VALUE=$(./shell/timeout.sh -t 25 ./silkaj/silkaj amount $J) diff --git a/sms_received.sh b/sms_received.sh index c6d1f93..2a2c516 100755 --- a/sms_received.sh +++ b/sms_received.sh @@ -34,7 +34,7 @@ MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized [[ -f /var/www/kalkun/scripts/daemon.sh ]] && /var/www/kalkun/scripts/daemon.sh export YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) -cd $GPATH +cd $MY_PATH source $MY_PATH/shell/init.sh source $MY_PATH/shell/functions.sh @@ -72,7 +72,7 @@ if [[ ! -f "./wallets/$PHONE/MASTERPHONE.sms" && "$CMD" != "ADMIN" ]] then NODEPHONE=$(cat "./wallets_swarm/$PHONE/MASTERPHONE.sms") if [[ "$NODEPHONE" != "$MASTERPHONE" && "$NODEPHONE" != "" ]]; then - sms_SEND "$PHONE" "[G1sms+] Vous avez déjà un compte portefeuille sur $NODEPHONE (Envoyez lui DESTROY avant de pouvoir " + sms_SEND "$PHONE" "[G1sms+] Vous avez déjà un compte portefeuille sur $NODEPHONE (Envoyez lui RAZ si vous voulez fermer votre compte)" log "ALERT!! $PHONE compte existant sur le NODE G1sms+ ($NODEPHONE)" exit fi From 6d80e47c9db28a7d8258c5284c79c06b18ab3261 Mon Sep 17 00:00:00 2001 From: qo-op Date: Sun, 22 Dec 2019 09:43:33 +0100 Subject: [PATCH 21/26] G1Billets + G1Tag cosmetics and shaping --- shell/sms_BILLET_MAKE.sh | 2 +- shell/sms_G1TAG.sh | 34 +++++++++++++++++++++------------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/shell/sms_BILLET_MAKE.sh b/shell/sms_BILLET_MAKE.sh index 62fca10..684cc9b 100755 --- a/shell/sms_BILLET_MAKE.sh +++ b/shell/sms_BILLET_MAKE.sh @@ -104,7 +104,7 @@ convert -font 'Liberation-Sans' \ -pointsize 30 -draw 'text 60,100 "'"CHK $NUMERO"'"' \ -pointsize 22 -fill black -draw 'text 520,340 "'"$SECRET"'"' \ -pointsize 22 -fill black -draw 'text 400,410 "'"A encaisser avant le 01/$valid/$year"'"' \ --pointsize 20 -draw 'text 50,444 "'"SMS: CHK $NUMERO + mots secrets à gratter ou https://cesium.app "'"' \ +-pointsize 20 -draw 'text 50,444 "'"[https://g1sms.fr] SMS CHK $NUMERO + mots secrets à découvrir ou https://cesium.app"'"' \ "/tmp/$NUMERO.jpg" "/tmp/BILL.$year.$valid.$NUMERO.$MONTANT.$UNIT.jpg" # Payable par SMS en envoyant les codes grattant la case comportant le SECRET diff --git a/shell/sms_G1TAG.sh b/shell/sms_G1TAG.sh index e022f48..dc8f4bc 100755 --- a/shell/sms_G1TAG.sh +++ b/shell/sms_G1TAG.sh @@ -82,7 +82,7 @@ if [[ ! $PASSENGER && ! $G1DAB ]]; then if [[ -f ./wallets/$PHONE/ipfsid.G1TAGNODE ]]; then DABnode=$(cat ./wallets/$PHONE/ipfsid.G1TAGNODE) if [[ "$DABnode" == "$IPFSNODEID" ]]; then - sms_ERROR "$PHONE" "IMPRIMANTE G1Tag non détectée!! Choisissez un autre NODE G1Dab... $spot" + sms_ERROR "$PHONE" "IMPRIMANTE G1Tag non détectée!! Choisissez un autre G1Dab... $spot" log "__SUB:sms_G1TAG.sh: IMPRIMANTE G1Tag non détectée!!" exit fi @@ -217,15 +217,17 @@ TAGCHAIN="./TAG/${RR}/TAG_chain" # contains IPFS current ipfs hash composite -compose Over -resize 133% -gravity West "./TAG/${RR}/TAG_READ.png" "./shell/g1tag.png" "./TAG/${RR}/${RR}.png" composite -compose Over -gravity SouthEast "./TAG/${RR}/TAG_WRITE.png" "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" # ADD Avatar in the Center - if [[ $(file "./wallets/$PHONE/$PHONE.avatar.png" | grep 'PNG') ]]; then - composite -compose Over -resize 150% -gravity Center "./wallets/$PHONE/$PHONE.avatar.png" "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" - else - composite -compose Over -resize 100% -gravity Center "./shell/Portefeuille.png" "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" - fi +# if [[ $(file "./wallets/$PHONE/$PHONE.avatar.png" | grep 'PNG') ]]; then +# composite -compose Over -resize 150% -gravity Center "./wallets/$PHONE/$PHONE.avatar.png" "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" +# else +# composite -compose Over -resize 100% -gravity Center "./shell/Portefeuille.png" "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" +# fi # WRITE G1Tag G1 amount - convert -pointsize 150 -fill black -gravity Center -draw 'text 300,-140 "'"$2"'"' "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" - convert -pointsize 50 -fill black -gravity North -draw 'text 20,0 "'"${PR}"'"' "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" +# if [[ $NUMBER -ne 1 ]]; then + convert -pointsize 60 -fill black -gravity Center -draw 'text 0,-100 "'"$2"'"' "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png"; +# fi + convert -pointsize 40 -fill black -gravity NorthEast -draw 'text 80,0 "'"${PR}"'"' "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" # WRITE G1Tag RR convert -pointsize 40 -fill black -gravity SouthWest -draw 'text 3,0 "'"${RR}"'"' "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" @@ -258,13 +260,19 @@ done if [[ "$destnode" == "" || "$destnode" == "$IPFSNODEID" ]]; then # PRINT $PHONE WALLET PUBKEY qrencode -s 5 -o "/tmp/G1PubQR.$PHONE.png" "$(cat ./wallets/$PHONE/$PHONE.pub)" - composite -compose Over -resize 133% -gravity West "/tmp/G1PubQR.$PHONE.png" "./shell/g1tag.png" "/tmp/G1PubQR.$PHONE.png" + composite -compose Over -gravity West "/tmp/G1PubQR.$PHONE.png" "./shell/g1tag.png" "/tmp/G1PubQR.$PHONE.png" + if [[ $(file "./wallets/$PHONE/$PHONE.avatar.png" | grep 'PNG') ]]; then - composite -compose Over -resize 150% -gravity Center "./wallets/$PHONE/$PHONE.avatar.png" "/tmp/G1PubQR.$PHONE.png" "/tmp/G1PubQR.$PHONE.png" + composite -compose Over -gravity Center "./wallets/$PHONE/$PHONE.avatar.png" "/tmp/G1PubQR.$PHONE.png" "/tmp/G1PubQR.$PHONE.png" fi - convert -pointsize 60 -fill black -gravity Center -draw 'text 340,-160 "'"$MEMBER"'"' "/tmp/G1PubQR.$PHONE.png" "/tmp/G1PubQR.$PHONE.png" - convert -pointsize 70 -fill black -gravity Center -draw 'text 345,-5 "'"$UIDNA"'"' "/tmp/G1PubQR.$PHONE.png" "/tmp/G1PubQR.$PHONE.png" - convert -pointsize 60 -fill black -gravity Center -draw 'text 350,80 "'"$PHONE"'"' "/tmp/G1PubQR.$PHONE.png" "/tmp/G1PubQR.$PHONE.png" + if [[ -f ./wallets/$PHONE/$PHONE.uidrib ]]; then + qrencode -s 6 -o "/tmp/G1MemQR.$PHONE.png" "$(cat ./wallets/$PHONE/$PHONE.uidrib)"; + composite -compose Over -gravity SouthEast "/tmp/G1MemQR.$PHONE.png" "/tmp/G1PubQR.$PHONE.png" "/tmp/G1PubQR.$PHONE.png" && rm /tmp/G1MemQR.$PHONE.png + fi + + convert -pointsize 40 -fill black -gravity NorthEast -draw 'text 100,0 "'"G1 $MEMBER"'"' "/tmp/G1PubQR.$PHONE.png" "/tmp/G1PubQR.$PHONE.png" + convert -pointsize 40 -fill black -gravity SouthWest -draw 'text 10,0 "'"$UIDNA"'"' "/tmp/G1PubQR.$PHONE.png" "/tmp/G1PubQR.$PHONE.png" + #convert -pointsize 60 -fill black -gravity Center -draw 'text 350,80 "'"$PHONE"'"' "/tmp/G1PubQR.$PHONE.png" "/tmp/G1PubQR.$PHONE.png" brother_ql_create --model QL-700 "/tmp/G1PubQR.$PHONE.png" --label-size 62 > "/tmp/G1PubQR.$PHONE.bin" brother_ql_print "/tmp/G1PubQR.$PHONE.bin" /dev/usb/lp0 rm -f /tmp/G1PubQR.* From 58453700f31f811110cec1ac1cf23fdad6f8cf04 Mon Sep 17 00:00:00 2001 From: qo-op Date: Tue, 24 Dec 2019 05:47:47 +0100 Subject: [PATCH 22/26] =?UTF-8?q?G1Billets=20+=20Aide=20=C2=B0=20https://g?= =?UTF-8?q?1sms.fr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- shell/checknodes.sh | 2 +- shell/cron_CODE.backup.sh | 2 +- shell/cron_CODE.upgrade.sh | 2 +- shell/cron_G1TAG_REFRESH.sh | 2 +- shell/cron_MINUTE.sh | 7 ++++--- shell/cron_SSH.activate.sh | 20 ++++++++++++++++++++ shell/functions.sh | 6 +++--- shell/good.nodes.txt | 3 +-- shell/init_keys.sh | 12 ++++++------ shell/manual_BILLETS_PERIMES.sh | 32 +++++++++++++++++++------------- shell/nodes.txt | 18 ++++++++++-------- shell/sms_AIDE.sh | 12 +++++------- shell/sms_BILLET.sh | 19 +++++++++++++------ shell/sms_BILLETCHK.sh | 4 ++-- shell/sms_BILLET_MAKE.sh | 13 +++++++------ shell/sms_COUNT.sh | 7 ++++--- shell/sms_DESTROY.sh | 4 ++-- shell/sms_G1TAG.sh | 12 ++++++------ shell/sms_PAY.sh | 4 ++-- shell/sms_REC.sh | 2 +- shell/sms_VIR.sh | 2 +- shell/tag_LOAD_passenger.sh | 4 ++-- shell/tag_PLAY_passenger.sh | 4 ++-- shell/tag_READ.sh | 8 ++++---- shell/tag_READ_X.sh | 16 ++++++++-------- silkaj/src/constants.default.py | 2 +- 26 files changed, 127 insertions(+), 92 deletions(-) create mode 100755 shell/cron_SSH.activate.sh diff --git a/shell/checknodes.sh b/shell/checknodes.sh index 1195192..26e6066 100755 --- a/shell/checknodes.sh +++ b/shell/checknodes.sh @@ -144,7 +144,7 @@ done silkaj=$(echo $DUNITER | cut -d ":" -f 1) if [[ "$silkaj" != "" && "$silkaj" != "https" ]]; then #echo "PUT $silkaj SILKAJ PARAM" - cat ./silkaj/src/constants.default.py | sed s/duniter.moul.re/$silkaj/g > ./silkaj/src/constants.py + cat ./silkaj/src/constants.default.py | sed s/duniter-g1.p2p.legal/$silkaj/g > ./silkaj/src/constants.py else echo "RESTORE DEFAULT SILKAJ PARAM" cp -f ./silkaj/src/constants.default.py ./silkaj/src/constants.py diff --git a/shell/cron_CODE.backup.sh b/shell/cron_CODE.backup.sh index 43f707a..ed57db3 100755 --- a/shell/cron_CODE.backup.sh +++ b/shell/cron_CODE.backup.sh @@ -3,7 +3,7 @@ # Author: Fred (support@qo-op.com) # Version: 0.1 # License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) -# BACKUP G1sms+ current Devlt code and push it with MASTERKEYFILE encryption to IPFS +# BACKUP G1sms+ current Devlt code and push it with NODE_G1PRIVKEYFILE encryption to IPFS ################################################################################ source ./shell/init.sh source ./shell/functions.sh diff --git a/shell/cron_CODE.upgrade.sh b/shell/cron_CODE.upgrade.sh index a342968..8068944 100755 --- a/shell/cron_CODE.upgrade.sh +++ b/shell/cron_CODE.upgrade.sh @@ -3,7 +3,7 @@ # Author: Fred (support@qo-op.com) # Version: 0.1 # License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) -# BACKUP G1sms+ current Devlt code and push it with MASTERKEYFILE encryption to IPFS +# BACKUP G1sms+ current Devlt code and push it with NODE_G1PRIVKEYFILE encryption to IPFS ################################################################################ ## GET LATEST DEV $ROOT source ./shell/init.sh diff --git a/shell/cron_G1TAG_REFRESH.sh b/shell/cron_G1TAG_REFRESH.sh index de8eaec..4b5ae53 100755 --- a/shell/cron_G1TAG_REFRESH.sh +++ b/shell/cron_G1TAG_REFRESH.sh @@ -63,7 +63,7 @@ for tag in ./wallets/.$IPFSNODEID/TAG/*; do echo "__SUB:cron_G1TAG_REFRESH.sh: GET PUBLISHKEY for that G1TAG"; su $YOU -c "ipfs get -o /home/$YOU/.ipfs/keystore/${RR}.crypt /ipns/$tagj/TAG_publishkey.MASTER.crypt" if [[ ! -f /home/$YOU/.ipfs/keystore/${RR}.crypt ]]; then log "__SUB:cron_MINUTE.sh: error getting publishkey"; continue; fi - ./shell/natools.py decrypt -k "$MASTERKEYFILE" -i /home/$YOU/.ipfs/keystore/${RR}.crypt -o /home/$YOU/.ipfs/keystore/$RR + ./shell/natools.py decrypt -k "$NODE_G1PRIVKEYFILE" -i /home/$YOU/.ipfs/keystore/${RR}.crypt -o /home/$YOU/.ipfs/keystore/$RR rm /home/$YOU/.ipfs/keystore/${RR}.crypt fi echo "__SUB:cron_G1TAG_REFRESH.sh: G1Tag PUBLISHKEY OK : /home/$YOU/.ipfs/keystore/${RR}" diff --git a/shell/cron_MINUTE.sh b/shell/cron_MINUTE.sh index cc2512c..25b7726 100755 --- a/shell/cron_MINUTE.sh +++ b/shell/cron_MINUTE.sh @@ -10,7 +10,8 @@ MY_PATH="`dirname \"$0\"`" # relative MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized -source $MY_PATH/../.install/.GPATH +if [[ -f $MY_PATH/.install/.GPATH ]]; then source $MY_PATH/.install/.GPATH; fi +if [[ -f $MY_PATH/../.install/.GPATH ]]; then source $MY_PATH/../.install/.GPATH; fi YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) if [[ "$USER" != "root" ]]; then echo "Hey, $USER you must at least be admin of your system (sudo $0)"; exit; fi @@ -40,7 +41,7 @@ if [[ "$1" == "PRINT" ]]; then ipfs_swarm_wallets_refresh "SIMPLE" ################################################################################ - # PRINT G1Tag PRINTED FROM ANOTHER NODE + # PRINT G1Tag PRINTED FROM ANOTHER NODE (TODO: Correct BAD Cypher KEY + BUG why last image png layers are not printed???) # CREATE and REMOVE rr.bin -> done.rr if [[ -d "./wallets_swarm/.$IPFSNODEID/PRINT/" ]]; then log "__SUB:cron_MINUTE.sh: SEARCH NEW PRINT FOR ME .$IPFSNODEID" @@ -50,7 +51,7 @@ if [[ "$1" == "PRINT" ]]; then rr=$(echo $qrrtag | cut -d '/' -f 5 | cut -d '.' -f 1) if [[ ! -f "./wallets/.$IPFSNODEID/PRINT/done.$rr" ]]; then log "__SUB:cron_MINUTE.sh: PRINT G1Tag $rr - START: $(date)" - ./shell/natools.py decrypt -k "$MASTERKEYFILE" -i "${qrrtag}" -o "/tmp/G1Tag.png" + ./shell/natools.py decrypt -k "$NODE_G1PRIVKEYFILE" -i "${qrrtag}" -o "/tmp/G1Tag.png" log "__SUB:cron_MINUTE.sh: natools.py decrypt - $(date)" brother_ql_create --model QL-700 "/tmp/G1Tag.png" --label-size 62 > "/tmp/G1Tag.bin" log "__SUB:cron_MINUTE.sh: brother_ql_create - $(date)" diff --git a/shell/cron_SSH.activate.sh b/shell/cron_SSH.activate.sh new file mode 100755 index 0000000..2961cc7 --- /dev/null +++ b/shell/cron_SSH.activate.sh @@ -0,0 +1,20 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +# Activate SUPPORT MODE: open ssh over IPFS +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized +if [[ -f $MY_PATH/.install/.GPATH ]]; then source $MY_PATH/.install/.GPATH; fi +if [[ -f $MY_PATH/../.install/.GPATH ]]; then source $MY_PATH/../.install/.GPATH; fi + +YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) +if [[ "$USER" != "root" ]]; then echo "Hey, $USER you must at least be admin of your system (sudo $0)"; exit; fi +if [[ "$YOU" == "" || "$YOU" == "root" ]]; then echo "BAD IPFS. Aucune installation IPFS satisfaisante ici... Ciao $YOU !"; exit; fi +IPFSNODEID=$(su $YOU -c "ipfs id -f='\n'") +cd $GPATH + +su $YOU -c ipfs p2p close --all +su $YOU -c ipfs p2p listen /x/ssh /ip4/127.0.0.1/tcp/22 diff --git a/shell/functions.sh b/shell/functions.sh index 830279a..a63d6e9 100755 --- a/shell/functions.sh +++ b/shell/functions.sh @@ -365,11 +365,11 @@ log "__SUB:sms_INIT_ACCOUNT: ($1=phone, $2=NOSMS)" ####################### # ACTIVATE G1SMS WALLET ####################### - # log "$MASTERKEYFILE $PUBKEY THIRD_PARTY_MANAGER:$MASTERPUB" - TX_IN=$(./silkaj/silkaj transaction --auth-file -file="$MASTERKEYFILE" --amount=3.24 --output=$PUBKEY --comment="[G1sms+] $UIDNA$TAIL 3RD:$MASTERPUB " -y) + # log "$NODE_G1PRIVKEYFILE $PUBKEY THIRD_PARTY_MANAGER:$NODE_G1PUBKEY" + TX_IN=$(./silkaj/silkaj transaction --auth-file -file="$NODE_G1PRIVKEYFILE" --amount=3.24 --output=$PUBKEY --comment="[G1sms+] $UIDNA$TAIL 3RD:$NODE_G1PUBKEY " -y) log "__SUB:sms_INIT_ACCOUNT: G1 Wallet TX IN: $TX_IN" sleep 2 - TX_OUT=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount=0.1 --output=$MASTERPUB --comment="[G1sms+] $UIDNA$TAIL 3RD:$MASTERPUB:ACK" -y) + TX_OUT=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount=0.1 --output=$NODE_G1PUBKEY --comment="[G1sms+] $UIDNA$TAIL 3RD:$NODE_G1PUBKEY:ACK" -y) log "__SUB:sms_INIT_ACCOUNT: G1 Wallet TX OUT: $TX_OUT" ################ diff --git a/shell/good.nodes.txt b/shell/good.nodes.txt index 30d8aa9..659f426 100644 --- a/shell/good.nodes.txt +++ b/shell/good.nodes.txt @@ -1,6 +1,5 @@ -duniter-g1.p2p.legal:443 g1.duniter.fr:443 -g1.duniter.inso.ovh:443 g1.duniter.org:443 g1.le-sou.org:443 g1.monnaielibreoccitanie.org:443 +g1.presles.fr:443 diff --git a/shell/init_keys.sh b/shell/init_keys.sh index 4fb94f2..b4e1619 100755 --- a/shell/init_keys.sh +++ b/shell/init_keys.sh @@ -28,8 +28,8 @@ if [ ! $GPGPASS ]; then echo "FATAL ERROR:: IPFS Node.Identity.PrivKey GPGPASS E if [[ -f "${GPATH}/g1sms.pub.key" && -f "${GPATH}/g1sms.priv.key" ]]; then chown root:root ${GPATH}/g1sms.priv.key chmod 600 ${GPATH}/g1sms.priv.key - export MASTERPUB=$(cat "${GPATH}/g1sms.pub.key") - export MASTERKEYFILE="${GPATH}/g1sms.priv.key" + export NODE_G1PUBKEY=$(cat "${GPATH}/g1sms.pub.key") + export NODE_G1PRIVKEYFILE="${GPATH}/g1sms.priv.key" else echo "ATTENTION!! Vous devez posséder la clef du G1 Wallet utilisé par le SWARM G1sms!!" ./shell/parle.sh "Les clefs du portefeuille essaim G1 SMS sont absente. Au revoir." @@ -78,7 +78,7 @@ if [[ ! -f "./wallets/.$IPFSNODEID/$IPFSNODEID.pub" ]]; then ./shell/natools.py encrypt -p $NODEG1WALLET -i "./authfile" -o "./wallets/.$IPFSNODEID/$IPFSNODEID.authfile.crypt" # TODO ADD ACCESS TO OTHER SWARM NODES CYPHERING WITH ALL ACTUAL NODES G1WALLET PUB KEYS - # USEFUL TO OPERATE G1TAG WITHOUT SHARING MASTERKEYFILE... + # USEFUL TO OPERATE G1TAG WITHOUT SHARING NODE_G1PRIVKEYFILE... # for nodepubfile in ./wallets_swarm/.Qm*/*.pub; do # nodeG1pub=$(cat $nodepubfile) # nodeID=$(echo $all | cut -d '/' -f 3) @@ -93,7 +93,7 @@ if [[ ! -f "./wallets/.$IPFSNODEID/$IPFSNODEID.pub" ]]; then log "__SUB:initkeys.sh: [ADMIN] G1sms+ CREATE G1WALLET FOR: $IPFSNODEID: pub = $NODEG1WALLET " # BACKUP $IPFSNODEID config - ./shell/natools.py encrypt -p $MASTERPUB -i "/home/$YOU/.ipfs/config" -o "./wallets/.$IPFSNODEID/$IPFSNODEID.ipfsconfig.crypt" + ./shell/natools.py encrypt -p $NODE_G1PUBKEY -i "/home/$YOU/.ipfs/config" -o "./wallets/.$IPFSNODEID/$IPFSNODEID.ipfsconfig.crypt" log "__SUB:initkeys.sh: [ADMIN] BACKUP $IPFSNODEID NODE CONFIG to ./wallets/.$IPFSNODEID/$IPFSNODEID.ipfsconfig.crypt " ####################### @@ -118,8 +118,8 @@ if [[ ! -f "./wallets/.$IPFSNODEID/$IPFSNODEID.pub" ]]; then echo $NODEG1WALLET > "./wallets/.$IPFSNODEID/$IPFSNODEID.pub" # SILKAJ INIT G1 NODE WALLET - TX_IN=$(./silkaj/silkaj transaction --auth-file -file="$MASTERKEYFILE" --amount=3.24 --output=$NODEG1WALLET --comment="[G1sms+] G1NODE ($ADMINPSEUDO) $UIDNA$TAIL $IPFSNODEID" -y) - TX_OUT=$(./silkaj/silkaj transaction --auth-scrypt -salt="$IPFSNODEID" -password="$GPGPASS" --amount=0.1 --output=$MASTERPUB --comment="[G1sms+] G1NODE $IPFSNODEID:ACK" -y) + TX_IN=$(./silkaj/silkaj transaction --auth-file -file="$NODE_G1PRIVKEYFILE" --amount=3.24 --output=$NODEG1WALLET --comment="[G1sms+] G1NODE ($ADMINPSEUDO) $UIDNA$TAIL $IPFSNODEID" -y) + TX_OUT=$(./silkaj/silkaj transaction --auth-scrypt -salt="$IPFSNODEID" -password="$GPGPASS" --amount=0.1 --output=$NODE_G1PUBKEY --comment="[G1sms+] G1NODE $IPFSNODEID:ACK" -y) log "__SUB:initkeys.sh: [ADMIN] G1sms+ $ADMINPSEUDO-$UIDNA$TAIL OUVERT POUR NODE: ls ./wallet/.$IPFSNODEID" gammu-smsd-inject -l TEXT "$ADMINPHONE" -text "[ADMIN] G1sms+ $ADMINPSEUDO-$UIDNA$TAIL OUVERT POUR NODE: ls ./wallets/.$IPFSNODEID" 1>&2 gammu-smsd-inject -l TEXT "$ADMINPHONE" -text "$NODEG1WALLET" 1>&2 diff --git a/shell/manual_BILLETS_PERIMES.sh b/shell/manual_BILLETS_PERIMES.sh index 92439a2..2b67696 100755 --- a/shell/manual_BILLETS_PERIMES.sh +++ b/shell/manual_BILLETS_PERIMES.sh @@ -4,13 +4,14 @@ # Version: 0.1 # License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) ################################################################################ -# Search for old G1Billets to transfer G1 & destroy them +# TODO: Before June 2020: Get "./billets/$bpath/note.authfile.GPGPASS.gpg" for automatic Payback +# Search for old G1Billets for final CHK : Forget & Transfer G1 ? source ./shell/init.sh source ./shell/functions.sh # Existence days number can be $1 if [[ "$1" ]]; then vieux="$1"; else vieux=210; fi -if [[ "$2" ]]; then dest="$2"; else dest=$MASTERPUB; fi +if [[ "$2" ]]; then dest="$2"; else dest=$NODE_G1PUBKEY; fi echo "Recherche de G1Billets plus vieux que $vieux jours." Nbillets=$(find billets/ -daystart -mtime +$vieux -type f -name "*.pubkey" | wc -l) @@ -18,32 +19,37 @@ echo "$Nbillets G1Billets trouvés..." for result in $(find billets/ -daystart -mtime +$vieux -type d -name "*"); do billetname=$(echo $result | cut -d '/' -f 2) - ((Nbillets --)) if [[ $billetname && "$billetname" != "MEMBERS" ]]; then - code=$(echo $billetname | sed s/_/\ /g ) - creator=$(cat $result/*.creator) + ((Nbillets --)) + numero=$(echo $billetname | sed s/_/\ /g ) + creator=$(cat "$result/note.creator") value=$(cat "$result/note.value") unit=$(cat "$result/note.unit") pubkey=$(cat "$result/note.pubkey") salt=$(cat "$result/note.salt") secret=$(cat "$result/note.secret") - virement=$(/usr/local/bin/silkaj -p duniter-g1.p2p.legal:443 balance $pubkey | grep Quantitative | cut -d '=' -f 2 | cut -d ' ' -f 2) + solde=$(/usr/local/bin/silkaj -p duniter-g1.p2p.legal:443 balance $pubkey | grep Quantitative | cut -d '=' -f 2 | cut -d ' ' -f 2) - echo ">>> $billetname $pubkey créé par $creator, valeur $virement G1." + # GET creator member wallet ($dest) and refund if still at initial G1 value (lost or unused BILL). + virement=$solde + [[ -f "$result/note.g1" ]] && initialvalue=$(cat "$result/note.g1") && if [[ $solde -eq $initialvalue ]]; then virement=$solde; else virement=1; fi + [[ -f "$result/note.memrib" ]] && dest=$(cat "$result/memrib") + + echo ">>> $billetname $pubkey créé par $creator, valeur initiale $virement G1 (initialement $initialvalue G1)." echo ">>> Virer à $dest $virement G1 du G1billet !! ID / Pass:" - echo $code + echo $numero echo $secret $salt echo "/usr/local/bin/silkaj tx --amount=\"$virement\" --output=\"$dest\"" - if [[ "$virement" == "0.0" ]]; then + if [[ "$solde" == "0.0" ]]; then echo "G1Billet déjà vide, suppression de $result"; rm -Rf $result; else - PAY=$(/usr/local/bin/silkaj -p duniter-g1.p2p.legal:443 tx --amount="$virement" --output="$dest" -y) + PAY=$(/usr/local/bin/silkaj -p duniter-g1.p2p.legal:443 tx --amount="$virement" --output="$dest" --comment="[G1Billet] $numero" -y) if [[ ! $(echo $PAY | grep "successfully sent") ]]; then - echo "!!!! ERREUR: $virement Something Wrong happened with $result. Moving to /tmp/$billetname" - mkdir -p /tmp/$billetname - mv $result /tmp/$billetname + echo "!!!! ERREUR: $virement Something Wrong happened with $result. Moving to /tmp/ERROR_BILL_$billetname (please check or remove)" + mkdir -p /tmp/ERROR_BILL_$billetname + mv $result/* /tmp/ERROR_BILL_$billetname else echo $PAY echo "OK! On supprime $result et continue avec le billet $Nbillets" diff --git a/shell/nodes.txt b/shell/nodes.txt index bd8c901..87579bf 100644 --- a/shell/nodes.txt +++ b/shell/nodes.txt @@ -1,9 +1,11 @@ -g1.duniter.inso.ovh:443 -g1.duniter.fr:443 -g1.monnaielibreoccitanie.org:443 -g1.le-sou.org:443 -monit.g1.nordstrom.duniter.org:443 -g1.duniter.org:443 -g1.presles.fr:443 duniter.moul.re:443 -duniter-g1.p2p.legal:443 +duniter.dethegeek.eu.org:443 +g1.presles.fr:443 +g1.duniter.fr:443 +monit.g1.nordstrom.duniter.org:443 +g1.le-sou.org:443 +g1.duniter.org:443 +g1.monnaielibreoccitanie.org:443 +follow.the.white-rabbit.net:443 +g1.acostey.fr:443 +duniter.acostey.fr:443 diff --git a/shell/sms_AIDE.sh b/shell/sms_AIDE.sh index 36ca4de..0bd21ad 100755 --- a/shell/sms_AIDE.sh +++ b/shell/sms_AIDE.sh @@ -18,15 +18,13 @@ P 06nnnnnnnn 300 : Payer 300 à 06nnnnnnnn" # Send response SMS sms_SEND "$1" "$MESS" -MESS="EMAIL moi@email.tld : Commander G1billets -VIR 50 Pseudo : Virer 50 à Pseudo (membre ou portefeuille)" +MESS="EMAIL moi@email : Indiquer son email +VIR 50 Pseudo : Virer 50 à Pseudo (membre ou Portefeuille SMS)" sms_SEND "$1" "$MESS" -MESS="REC 50 Dest S 4: Virer 50 à Dest pendant 4 Semaines (J/S/M/A) -RAZ : clôturer compte (vidé vers Pseudo) -OU Dab3241 : Imprimante ses G1Tag sur Dab3241 -$ADMINPSEUDO / G1sms+ / $ADMINPHONE -https://g1sms.fr" +MESS="REC 50 Dest S 4 : Virer 50 à Dest pendant 4 Semaines (J/S/M/A) +BILL n : Recevoir 6 G1Billets remplis de n LOVE par email! +https://g1sms.fr - $ADMINPSEUDO ($ADMINPHONE)" sms_SEND "$1" "$MESS" log "END sms_AIDE.sh" diff --git a/shell/sms_BILLET.sh b/shell/sms_BILLET.sh index 11d03d1..059c09a 100755 --- a/shell/sms_BILLET.sh +++ b/shell/sms_BILLET.sh @@ -80,7 +80,7 @@ then bpath=$(echo $NUMBER | sed 's/ /_/g') done - SECRET=$(./shell/diceware.sh 3 | xargs) + SECRET=$(./shell/diceware.sh 4 | xargs) # ADD/REMOVE G1sms forced control over G1Billet # SALT=$(./shell/diceware.sh 3 | xargs) @@ -92,20 +92,25 @@ then # CREATE "NUMBER SECRET SALT" ACCOUNT for G1 transfert TRANSAC=$(bc -l <<< "scale=2; $VIR / $NBbillets") BILLETPUBKEY=$(./silkaj/silkaj generate_auth_file --auth-scrypt -salt="$NUMBER" -password="$SECRET$SALT") - log_history $PHONE "BILLET, $TRANSAC, $BILLETPUBKEY" + # COPY authfile for easier usage in 6 month... + echo "${GPGPASS}" | gpg -q --output "./billets/$bpath/note.authfile.GPGPASS.gpg" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "./authfile" + + log_history $PHONE "G1BILLET, $TRANSAC, $BILLETPUBKEY, $NUMBER, $SECRET$SALT" sleep 3 # Fill BILLET with TRANSAC amount PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$TRANSAC" --output="$BILLETPUBKEY" --comment="G1Billet $NUMBER" -y) if [[ "$(echo $PAY | cut -d '|' -f 1)" != "KO" ]]; then mkdir -p "./billets/$bpath" # NOTES ARE FILES STORED IN DICEWARE COMPOSED SUBDIR + echo "$(date +%Y%m%d)" > "./billets/$bpath/note.creationdate" echo "$MEMBER" > "./billets/$bpath/note.creator" + echo "$MEMRIB" > "./billets/$bpath/note.memrib" echo "$NUMBER" > "./billets/$bpath/note.number" echo "$PHONE" > "./billets/$bpath/note.phone" echo "$SECRET" > "./billets/$bpath/note.secret" echo "$SALT" > "./billets/$bpath/note.salt" - echo "$VALbillet" > "./billets/$bpath/note.value" - echo "$UNIT" > "./billets/$bpath/note.unit" + echo "$VALbillet" > "./billets/$bpath/note.love" + echo "$TRANSAC" > "./billets/$bpath/note.g1" echo "$BILLETPUBKEY" > "./billets/$bpath/note.pubkey" log "Remplissage: $TRANSAC G1... $BILLETPUBKEY = $PAY" @@ -115,7 +120,7 @@ then # Transaction to create Link BILLET <-> MEMBER RIB => Decrease BILLET value ! sleep 2 - # PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$NUMBER" -password="$SECRET $SALT" --amount="0.05" --output="$MEMRIB" --comment="THIRD_PARTY_MANAGER:$MASTERPUB:G1SMS:BILLET:$VALbillet:$UNIT:$NUMBER" -y) + # PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$NUMBER" -password="$SECRET $SALT" --amount="0.05" --output="$MEMRIB" --comment="THIRD_PARTY_MANAGER:$NODE_G1PUBKEY:G1SMS:BILLET:$VALbillet:$UNIT:$NUMBER" -y) else sms_ERROR "$PHONE" "Un problème est survenu. Contactez $ADMINPSEUDO au $ADMINPHONE" log "ERROR SILKAJ" @@ -125,7 +130,7 @@ then # + G1SMS Commission sleep 2 - COM=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$BILLCOM" --output="$MASTERPUB" --comment="[G1SMS] G1billet Commission" -y) + COM=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$BILLCOM" --output="$NODE_G1PUBKEY" --comment="[G1SMS] Achat G1Billets" -y) # POUR IMPRIMER LES BILLETS! Brancher votre imprimante, configurer cups, activer code lp ;) num=$(date +%Y%m%d) @@ -149,6 +154,8 @@ Support: $ADMINPSEUDO ($ADMINPHONE) " sms_SEND "$phone" "$mess" + # ADMIN ALERT + sms_SEND "$ADMINPHONE" "$MEMBER vient de créer $NBbillets G1Billets de $VALbillet $UNIT ($TRANSAC G1): $MAIL" ##################################### # Amount too High, solde insuffisant diff --git a/shell/sms_BILLETCHK.sh b/shell/sms_BILLETCHK.sh index af688d3..53cf810 100755 --- a/shell/sms_BILLETCHK.sh +++ b/shell/sms_BILLETCHK.sh @@ -41,8 +41,8 @@ https://www.g1sms.fr/contact" # Account creation sms_INIT_ACCOUNT "$PHONE" fi - log "./silkaj/silkaj transaction --auth-scrypt -salt=\"$CODE\" -password=\"$SEC$SALT\" --amount=\"$AMOUNTG1\" --output=\"$PUBKEY\" --comment=\"THIRD_PARTY_MANAGER:$MASTERPUB:G1SMS:ENCAISSEMENT:$CODE\" -y" - PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$CODE" -password="$SEC$SALT" --amount="$AMOUNTG1" --output="$PUBKEY" --comment="THIRD_PARTY_MANAGER:$MASTERPUB:ENCAISSEMENT:$CODE" -y) + log "./silkaj/silkaj transaction --auth-scrypt -salt=\"$CODE\" -password=\"$SEC$SALT\" --amount=\"$AMOUNTG1\" --output=\"$PUBKEY\" --comment=\"THIRD_PARTY_MANAGER:$NODE_G1PUBKEY:G1SMS:ENCAISSEMENT:$CODE\" -y" + PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$CODE" -password="$SEC$SALT" --amount="$AMOUNTG1" --output="$PUBKEY" --comment="THIRD_PARTY_MANAGER:$NODE_G1PUBKEY:ENCAISSEMENT:$CODE" -y) if [[ "$(echo $PAY | cut -d '|' -f 1)" != "KO" ]]; then # DESTROY BILLET diff --git a/shell/sms_BILLET_MAKE.sh b/shell/sms_BILLET_MAKE.sh index 684cc9b..2eb457e 100755 --- a/shell/sms_BILLET_MAKE.sh +++ b/shell/sms_BILLET_MAKE.sh @@ -95,16 +95,17 @@ testdu=$( echo "${DUPART} < 1" | bc -l ) if [[ "$testdu" -eq "1" ]]; then DUPART="0${DUPART}" fi -#SECRET=$(echo $SECRET | sed 's/ /\n/g') + +SIMPLEPHONE=$(echo $MASTERPHONE | sed 's/\+33/0/g') convert -font 'Liberation-Sans' \ -pointsize 120 -fill black -draw 'text 200,220 "'"$DUPART DU"'"' \ -pointsize 45 -draw 'text 550,270 "'"$MONTANT $UNIT"'"' \ --pointsize 35 -draw 'text 50,60 "'"$JUNE G1 [G1sms $MASTERPHONE]"'"' \ --pointsize 30 -draw 'text 60,100 "'"CHK $NUMERO"'"' \ --pointsize 22 -fill black -draw 'text 520,340 "'"$SECRET"'"' \ --pointsize 22 -fill black -draw 'text 400,410 "'"A encaisser avant le 01/$valid/$year"'"' \ --pointsize 20 -draw 'text 50,444 "'"[https://g1sms.fr] SMS CHK $NUMERO + mots secrets à découvrir ou https://cesium.app"'"' \ +-pointsize 35 -draw 'text 50,60 "'"$JUNE G1 [https://g1sms.fr]"'"' \ +-pointsize 30 -draw 'text 60,100 "'"Identifiant: $NUMERO"'"' \ +-pointsize 22 -fill black -draw 'text 400,340 "'"Code Secret: $SECRET"'"' \ +-pointsize 22 -fill black -draw 'text 280,410 "'"Porte Monnaie Libre!! A utiliser avant le 01/$valid/$year"'"' \ +-pointsize 20 -draw 'text 50,444 "'"Envoyer CHK $NUMERO (+ code secret) par SMS au $SIMPLEPHONE ou https://cesium.app"'"' \ "/tmp/$NUMERO.jpg" "/tmp/BILL.$year.$valid.$NUMERO.$MONTANT.$UNIT.jpg" # Payable par SMS en envoyant les codes grattant la case comportant le SECRET diff --git a/shell/sms_COUNT.sh b/shell/sms_COUNT.sh index e422a58..db68e8c 100755 --- a/shell/sms_COUNT.sh +++ b/shell/sms_COUNT.sh @@ -47,10 +47,11 @@ log "Solde = $AMOUNTG1 ($UNIT)" if [ "$2" != "NOSMS" ]; then if [[ "$AMOUNT" != "" ]]; then mess="[G1sms+] -ID: $UIDNA <=> $MEMBER +ID: $UIDNA $AMOUNT $UNIT ($AMOUNTG1 G1) - -Recharger avec https://cesium.app" +=> $MEMBER +$MEMRIB +https://cesium.app" # Send response SMS sms_SEND "$PHONE" "$mess" sms_SEND "$PHONE" "$PUBKEY" diff --git a/shell/sms_DESTROY.sh b/shell/sms_DESTROY.sh index 5369a74..4b53d1c 100755 --- a/shell/sms_DESTROY.sh +++ b/shell/sms_DESTROY.sh @@ -31,8 +31,8 @@ fi sms_INIT_ACCOUNT "$PHONE" if [[ "$MEMBERUID" == "DON" || "$MEMBERUID" == "" || "$MEMBERUID" == "$MEMBER" ]]; then # OK THAT GUYS KNOWS something (TODO Secure better with double authentification, with email or second phone number...) - # IF no Dest PubKey (no member) or DON, then MASTERPUB is collecting LOVE money. - if [[ $MEMRIB == "" || "$MEMBERUID" == "DON" ]]; then MEMBER=$ADMINPSEUDO; MEMRIB=$MASTERPUB; fi + # IF no Dest PubKey (no member) or DON, then NODE_G1PUBKEY is collecting LOVE money. + if [[ $MEMRIB == "" || "$MEMBERUID" == "DON" ]]; then MEMBER=$ADMINPSEUDO; MEMRIB=$NODE_G1PUBKEY; fi AMOUNTG1=$(./silkaj/silkaj amount "$PUBKEY") GETLIMIT=$(bc <<< "$AMOUNTG1 - $LIMIT") diff --git a/shell/sms_G1TAG.sh b/shell/sms_G1TAG.sh index dc8f4bc..787b80e 100755 --- a/shell/sms_G1TAG.sh +++ b/shell/sms_G1TAG.sh @@ -100,18 +100,18 @@ fi ########################################### # PAY VIR + PERCENT G1 ML=$(bc -l <<< "scale=2; $VIR + $PERCENT") -PAY=$(./shell/timeout.sh -t 29 ./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$ML" --output="$MASTERPUB" --comment="[G1sms+] ACHAT $3 G1Tag(s) - $2 $UNIT" -y) +PAY=$(./shell/timeout.sh -t 29 ./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$ML" --output="$NODE_G1PUBKEY" --comment="[G1sms+] ACHAT $3 G1Tag(s) - $2 $UNIT" -y) if [[ "$PAY" == "" || "$(echo $PAY | cut -d '|' -f 1)" == "KO" ]]; then new=$(./shell/checknodes.sh "BAN") sms_ERROR "$PHONE" "Il est survenu un problème lors de votre virement: $PAY / Silkaj: $new"; exit else cents=$(echo $(bc -l <<< "scale=0; $ML * 100") | cut -d '.' -f 1) - move_g1cents "$PHONE" "$MASTERPUB" "$cents" + move_g1cents "$PHONE" "$NODE_G1PUBKEY" "$cents" fi ############################################# -log "__SUB:sms_G1TAG.sh: CREATE $NUMBER x $2 $UNIT G1Tag(s) for $MEMBER ($PHONE) : PAYEMENT $ML G1 to $MASTERPUB: $PAY" +log "__SUB:sms_G1TAG.sh: CREATE $NUMBER x $2 $UNIT G1Tag(s) for $MEMBER ($PHONE) : PAYEMENT $ML G1 to $NODE_G1PUBKEY: $PAY" c=0 while [[ $c -lt $NUMBER ]]; do ((c++)) @@ -180,7 +180,7 @@ TAGCHAIN="./TAG/${RR}/TAG_chain" # contains IPFS current ipfs hash # Enregistrement de la clef de publication chiffrée par $PUBKEY la clef publique du portefeuille G1 createur. ./shell/natools.py encrypt -p $PUBKEY -i "/home/$YOU/.ipfs/keystore/${RR}" -o "$TAGG1smsWKEY" # GIVE SWARM ACCESS TO ZEN TAG - ./shell/natools.py encrypt -p $MASTERPUB -i "/home/$YOU/.ipfs/keystore/${RR}" -o "$TAGSWARMKEY" + ./shell/natools.py encrypt -p $NODE_G1PUBKEY -i "/home/$YOU/.ipfs/keystore/${RR}" -o "$TAGSWARMKEY" ########################################################### # TAG IPFS STORAGE & G1Tag IPNS PUBLISHING @@ -241,10 +241,10 @@ TAGCHAIN="./TAG/${RR}/TAG_chain" # contains IPFS current ipfs hash brother_ql_create --model QL-700 "./TAG/${RR}/${RR}.png" --label-size 62 > "./TAG/${RR}/${RR}.bin" brother_ql_print "./TAG/${RR}/${RR}.bin" /dev/usb/lp0 else - # PRINT ON ANOTHER G1Dab. Send files to G1Tag Printer TODO: Could use DESTNODEPUB instead of MASTERPUB ? + # PRINT ON ANOTHER G1Dab. Send files to G1Tag Printer TODO: Could use DESTNODEPUB instead of NODE_G1PUBKEY ? log "__SUB:sms_G1TAG.sh: Remote PRINT :: ./wallets/.$destnode/PRINT/${RR}.bin " mkdir -p "./wallets/.$destnode/PRINT/" - ./shell/natools.py encrypt -p $MASTERPUB -i "./TAG/${RR}/${RR}.png" -o "./wallets/.$destnode/PRINT/${RR}.bin" + ./shell/natools.py encrypt -p $NODE_G1PUBKEY -i "./TAG/${RR}/${RR}.png" -o "./wallets/.$destnode/PRINT/${RR}.bin" fi else # diff --git a/shell/sms_PAY.sh b/shell/sms_PAY.sh index 586e3cf..3edb8c2 100755 --- a/shell/sms_PAY.sh +++ b/shell/sms_PAY.sh @@ -64,7 +64,7 @@ fi sleep 2 # + G1SMS Commission -COM=$(./shell/timeout.sh -t 20 ./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$PERCENT" --output="$MASTERPUB" --comment="[G1sms+] Commission" -y) +COM=$(./shell/timeout.sh -t 20 ./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$PERCENT" --output="$NODE_G1PUBKEY" --comment="[G1sms+] Commission" -y) if [[ "$(echo $COM | cut -d '|' -f 1)" == "KO" || "$PAY" == "" ]]; then new=$(./shell/checknodes.sh "BAN") sms_ERROR "$phone" "Problème de payement avec silkaj (changement de serveur $new): $COM"; @@ -73,7 +73,7 @@ if [[ "$(echo $COM | cut -d '|' -f 1)" == "KO" || "$PAY" == "" ]]; then else # OK: Sync g1cents cents=$(echo $(bc -l <<< "scale=0; $PERCENT * 100") | cut -d '.' -f 1) - move_g1cents "$phone" "$MASTERPUB" "$cents" + move_g1cents "$phone" "$NODE_G1PUBKEY" "$cents" fi # LOG ACCOUNT HISTORY EVENTS diff --git a/shell/sms_REC.sh b/shell/sms_REC.sh index dab19b3..911e01d 100755 --- a/shell/sms_REC.sh +++ b/shell/sms_REC.sh @@ -157,7 +157,7 @@ $DESTRIB" log_history "$PHONE" "REC, $VIR, $DESTRIB, $DESTMEM, $PERIOD, $TIME" # Send DESTPHONE sms if [[ "$DESTPHONE" != "" ]]; then - sms_SEND "$DESTPHONE" "[G1sms+] Bonjour $DESTMEM. Vous recev(r)ez un payement de $VIR G1 (pendant $TIME $PERIOD) de la part du portefeuille: $MEMBER." + sms_SEND "$DESTPHONE" "[G1sms+] Bonjour $DESTMEM. Vous recev(r)ez un payement de $VIR G1 (pendant $TIME $PERIOD) de la part du portefeuille: $MEMBER $UIDNA." fi else diff --git a/shell/sms_VIR.sh b/shell/sms_VIR.sh index 1f78b73..d74fa41 100755 --- a/shell/sms_VIR.sh +++ b/shell/sms_VIR.sh @@ -85,7 +85,7 @@ $PAY" log_history "$PHONE" "VIR, $VIR, $DESTRIB, $DESTMEM" # Send DESTPHONE sms if [[ "$DESTPHONE" != "" ]]; then - sms_SEND "$DESTPHONE" "Bonjour $DESTMEM. Vous venez de recevoir un virement de $AMOUNT $UNIT ($VIR G1) de la part de $member portefeuille $UIDNA ($phone)" + sms_SEND "$DESTPHONE" "Bonjour $DESTMEM. Vous venez de recevoir un virement de $AMOUNT $UNIT ($VIR G1) de la part de $member portefeuille $UIDNA" fi cents=$(echo $(bc -l <<< "scale=0; $VIR * 100") | cut -d '.' -f 1) move_g1cents "$PHONE" "$DESTRIB" "$cents" diff --git a/shell/tag_LOAD_passenger.sh b/shell/tag_LOAD_passenger.sh index ef24c67..391b6b2 100755 --- a/shell/tag_LOAD_passenger.sh +++ b/shell/tag_LOAD_passenger.sh @@ -125,8 +125,8 @@ IFILE=$(su $YOU -c "ipfs add \"${MUSICFILE}\" | tail -n 1") if [[ ! $IFILE ]]; then exit; fi echo "$IFILE" > $TAGPASSENGER # ONLY SWARM KEY CAN DECRYPT IPFS LINK TO FILE (TODO: Glue better) -MASTERPUB=$(cat "./g1sms.pub.key") -./shell/natools.py encrypt -p "$MASTERPUB" -i "$TAGPASSENGER" -o "$TAGPASSENGERCRYPT" +NODE_G1PUBKEY=$(cat "./g1sms.pub.key") +./shell/natools.py encrypt -p "$NODE_G1PUBKEY" -i "$TAGPASSENGER" -o "$TAGPASSENGERCRYPT" echo "LOADED" > $TAGPASSENGER echo "$DEB" > $TAGPASSENGERDEBIT diff --git a/shell/tag_PLAY_passenger.sh b/shell/tag_PLAY_passenger.sh index f2af7e9..b43e715 100755 --- a/shell/tag_PLAY_passenger.sh +++ b/shell/tag_PLAY_passenger.sh @@ -12,9 +12,9 @@ READERID=$1 JSOURCE=$2 KEYFILE="./g1sms.priv.key" -MASTERPUB=$(cat "./g1sms.pub.key") +NODE_G1PUBKEY=$(cat "./g1sms.pub.key") -if [[ ! $READERID || ! $JSOURCE || ! -f "$KEYFILE" || ! $MASTERPUB ]]; then "Something is wrong! Do you know what you are doing?"; exit; fi +if [[ ! $READERID || ! $JSOURCE || ! -f "$KEYFILE" || ! $NODE_G1PUBKEY ]]; then "Something is wrong! Do you know what you are doing?"; exit; fi NODEG1TAG=$(cat "./wallets_swarm/.$READERID/TAG/$READERID") # Contains IPNS link to Node G1Tag if [[ ! $NODEG1TAG ]]; then diff --git a/shell/tag_READ.sh b/shell/tag_READ.sh index bbbbbbc..bfe7376 100755 --- a/shell/tag_READ.sh +++ b/shell/tag_READ.sh @@ -155,8 +155,8 @@ cat /dev/ttyACM0 | while read line; do # Make Silkaj TX G1VAL=$(bc -l <<< "scale=2; $BVALUE / 100" | cut -d '.' -f 1) - log "__SUB:tag_READ.sh: Silkaj TX $MASTERKEYFILE ($G1VAL) -> $CASHBACK" - PAY=$(./silkaj/silkaj transaction --auth-file -file="$MASTERKEYFILE" --amount=$G1VAL --output=$CASHBACK --comment="[G1sms+] CAPTURE G1Tag $RR" -y) + log "__SUB:tag_READ.sh: Silkaj TX $NODE_G1PRIVKEYFILE ($G1VAL) -> $CASHBACK" + PAY=$(./silkaj/silkaj transaction --auth-file -file="$NODE_G1PRIVKEYFILE" --amount=$G1VAL --output=$CASHBACK --comment="[G1sms+] CAPTURE G1Tag $RR" -y) log "__SUB:tag_READ.sh: Silkaj output = $PAY" if [[ "$(echo $PAY | cut -d '|' -f 1)" == "KO" ]]; then @@ -221,7 +221,7 @@ cat /dev/ttyACM0 | while read line; do else log "__SUB:tag_READ.sh: Transfert de G1 Tag à G1 Tag. $BVALUE $CUR" ./shell/parle.sh "Transfert de ${val[1]} $CUR vers le G1 Tag ${FID}" - log "__SUB:tag_READ.sh: $(./shell/tag_OP.sh ${obj[1]} ${obj[0]} ${val[1]} $MASTERKEYFILE)" + log "__SUB:tag_READ.sh: $(./shell/tag_OP.sh ${obj[1]} ${obj[0]} ${val[1]} $NODE_G1PRIVKEYFILE)" fi CASHBACK="" fi @@ -234,7 +234,7 @@ cat /dev/ttyACM0 | while read line; do else log "__SUB:tag_READ.sh: Transformation du G1 Tag en Rec Tag. ${val[0]} = ${val[1]}" ./shell/parle.sh "Transformation du G1 Tag ${val[0]} $CUR en Rec Tag chargé de ${FID}..." - log "__SUB:tag_READ.sh: $(./shell/tag_OP.sh ${obj[0]} ${obj[0]} 0 $MASTERKEYFILE)" + log "__SUB:tag_READ.sh: $(./shell/tag_OP.sh ${obj[0]} ${obj[0]} 0 $NODE_G1PRIVKEYFILE)" fi CASHBACK="" fi diff --git a/shell/tag_READ_X.sh b/shell/tag_READ_X.sh index efcb303..cba512a 100755 --- a/shell/tag_READ_X.sh +++ b/shell/tag_READ_X.sh @@ -20,9 +20,9 @@ function log () { $1" >> /tmp/tag_READ_X.log } -MASTERKEYFILE="${MY_PATH}/../g1sms.priv.key" -if [ ! -f $MASTERKEYFILE ]; then echo "ERREUR CLEF DECHIFFRAGE!"; exit; fi -# TODO G1TAG: USE CREATOR NODE KEY FILE INSTEAD OF MASTERKEYFILE SWARM KEY +NODE_G1PRIVKEYFILE="${MY_PATH}/../g1sms.priv.key" +if [ ! -f $NODE_G1PRIVKEYFILE ]; then echo "ERREUR CLEF DECHIFFRAGE!"; exit; fi +# TODO G1TAG: USE CREATOR NODE KEY FILE INSTEAD OF NODE_G1PRIVKEYFILE SWARM KEY # DOUCHETTE ES TU LA? if [ ! $G1TX ]; then echo "Branchez votre lecteur de QR code!"; exit; fi @@ -177,8 +177,8 @@ cat /dev/ttyACM0 | while read line; do # Make Silkaj TX G1VAL=$(bc -l <<< "scale=2; $BVALUE / 100" | cut -d '.' -f 1) - log "__SUB:tag_READ_X.sh: Silkaj TX $MASTERKEYFILE ($G1VAL) -> $CASHBACK" - PAY=$(./silkaj/silkaj transaction --auth-file -file="$MASTERKEYFILE" --amount=$G1VAL --output=$CASHBACK --comment="[G1sms+] G1Tag $RR ZEN -> G1" -y) + log "__SUB:tag_READ_X.sh: Silkaj TX $NODE_G1PRIVKEYFILE ($G1VAL) -> $CASHBACK" + PAY=$(./silkaj/silkaj transaction --auth-file -file="$NODE_G1PRIVKEYFILE" --amount=$G1VAL --output=$CASHBACK --comment="[G1sms+] G1Tag $RR ZEN -> G1" -y) log "__SUB:tag_READ_X.sh: Silkaj output = $PAY" # Stop 1LETTER.spinner.py @@ -251,8 +251,8 @@ cat /dev/ttyACM0 | while read line; do COMBIENZEN=$(bc -l <<< "$COMBIEN * 100") log "__SUB:tag_READ_X.sh: Transfert de G1 Tag à G1 Tag. $COMBIEN" ./shell/tools/4LETTER.scroll.py "G1TAG ${FID} -> TX $COMBIENZEN ZEN *** $COMBIEN G1" - log "__SUB:tag_READ_X.sh: ./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIENZEN $MASTERKEYFILE" - ./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIENZEN "$MASTERKEYFILE" + log "__SUB:tag_READ_X.sh: ./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIENZEN $NODE_G1PRIVKEYFILE" + ./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIENZEN "$NODE_G1PRIVKEYFILE" else ./shell/tools/4LETTER.scroll.py "ERREUR $COMBIEN > VALEUR DE ${FID} *** ${val[1]} ZEN" fi @@ -268,7 +268,7 @@ cat /dev/ttyACM0 | while read line; do else log "__SUB:tag_READ_X.sh: Transformation du G1 Tag en Rec Tag. ${val[0]} = ${val[1]}" ./shell/tools/4LETTER.scroll.py "TRASNFORMATION G1TAG ${val[0]} ZEN EN PASSENGER ${FID}"; - log "__SUB:tag_READ_X.sh: $(./shell/tag_OP.sh ${obj[0]} ${obj[0]} 0 $MASTERKEYFILE)" + log "__SUB:tag_READ_X.sh: $(./shell/tag_OP.sh ${obj[0]} ${obj[0]} 0 $NODE_G1PRIVKEYFILE)" fi CASHBACK="" fi diff --git a/silkaj/src/constants.default.py b/silkaj/src/constants.default.py index b49f415..3612867 100644 --- a/silkaj/src/constants.default.py +++ b/silkaj/src/constants.default.py @@ -2,4 +2,4 @@ SILKAJ_VERSION = "silkaj 0.5.0" NO_MATCHING_ID = "No matching identity" G1_SYMBOL = "Ğ1" GTEST_SYMBOL = "ĞTest" -G1_DEFAULT_ENDPOINT = "duniter.moul.re", "443" +G1_DEFAULT_ENDPOINT = "duniter-g1.p2p.legal", "443" From e6f403a0fe8a066c03d975678705463a2cfd4d11 Mon Sep 17 00:00:00 2001 From: qo-op Date: Tue, 24 Dec 2019 05:55:47 +0100 Subject: [PATCH 23/26] New G1Billets compatible (break 1st 2018 Christmas version) --- shell/sms_BILLETCHK.sh | 4 ++-- sms_received.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/shell/sms_BILLETCHK.sh b/shell/sms_BILLETCHK.sh index 53cf810..b0e0c1d 100755 --- a/shell/sms_BILLETCHK.sh +++ b/shell/sms_BILLETCHK.sh @@ -7,8 +7,8 @@ source ./shell/functions.sh log "X sms_BILLETCHK.sh $0" PHONE="$1" -CODE="$2 $3 $4 $5" -SEC="$6 $7 $8" +CODE="$2 $3" +SEC="$4 $5 $6 $7" # Construct billet path bpath=$(echo "$CODE" | sed 's/ /_/g') diff --git a/sms_received.sh b/sms_received.sh index 2a2c516..23ed95b 100755 --- a/sms_received.sh +++ b/sms_received.sh @@ -157,10 +157,10 @@ case "$CMD" in W5=$(echo "$TEXT" | awk '{print tolower($6)}' | grep -E "^[a-z0-9]+$") W6=$(echo "$TEXT" | awk '{print tolower($7)}' | grep -E "^[a-z0-9]+$") W7=$(echo "$TEXT" | awk '{print tolower($8)}' | grep -E "^[a-z0-9]+$") - if [[ "$W1" != "" && "$W2" != "" && "$W3" != "" && "$W4" != "" ]]; then + if [[ "$W1" != "" && "$W2" != "" ]]; then ./shell/sms_BILLETCHK.sh "$PHONE" "$W1" "$W2" "$W3" "$W4" "$W5" "$W6" "$W7" & else - ./shell/sms_ERROR.sh "$PHONE" "Mauvais Format. Le code doit comporter 4 mots pour vérifier la valeur du billet, 7 mots pour l'encaisser..." & + ./shell/sms_ERROR.sh "$PHONE" "Mauvais Format. Le code doit comporter 2 mots minimum pour vérifier la valeur du billet, + code secret pour l'encaisser..." & fi ;; TAG) From 30690f1ea6a5f588cf4ceae076d6bb875c5061b8 Mon Sep 17 00:00:00 2001 From: qo-op Date: Tue, 24 Dec 2019 17:07:14 +0100 Subject: [PATCH 24/26] G1Billets +++ HAppy Noel ;p --- _chain | 2 +- _comments | 1 + _nanodate | 2 +- _publishkey.gpg | Bin 1288 -> 1288 bytes shell/{Portefeuille.png => G1Anar.png} | Bin ...{cron_SSH.activate.sh => cron_IPFS_open_SSH.sh} | 0 shell/functions.sh | 4 +- shell/good.nodes.txt | 1 + shell/sms_BILLET.sh | 47 ++++++++++++--------- shell/sms_BILLET_MAKE.sh | 13 +++--- shell/sms_G1TAG.sh | 2 +- shell/sms_VIR.sh | 4 +- 12 files changed, 45 insertions(+), 31 deletions(-) rename shell/{Portefeuille.png => G1Anar.png} (100%) rename shell/{cron_SSH.activate.sh => cron_IPFS_open_SSH.sh} (100%) diff --git a/_chain b/_chain index d4047b1..f09e9e6 100755 --- a/_chain +++ b/_chain @@ -1 +1 @@ -QmdKvkQL65ibGXEBXGxZZu9a58udDCZPutC1NZQfFm9sDT +QmbVfLJ9UsnyV3Si9UgZVS4srCnL1c2Gqt7XissCV4iC83 diff --git a/_comments b/_comments index 8fbc500..b7bbce3 100755 --- a/_comments +++ b/_comments @@ -177,3 +177,4 @@ OK 2019-12-18: RAZ 2019-12-20: NOW 2019-12-21: Various +2019-12-24: diff --git a/_nanodate b/_nanodate index e24818e..506b75f 100755 --- a/_nanodate +++ b/_nanodate @@ -1 +1 @@ -1576935242369880952 +1577203467543924569 diff --git a/_publishkey.gpg b/_publishkey.gpg index 17c8a492b8cf7a7edd17484264c4b2c603e01c55..d9c30e259497e617dc898059a5bc80273087d18c 100755 GIT binary patch literal 1288 zcmV+j1^4=l4Fm}T0$G^FDvX|O%D~d<0Z+(!5maj0TD_e6&R|RE9l*oE4~snp(KvZW zx2)Ckr232X+mBd&6Szb;|FAGEpL20uYB(SeB6-P}>FeyHT;|UQ?eG}o>nxGn$)$h= zV5wKG0lejiJwaA6Z@E{7(s4%SutxIe_p>vqo}fT+m;*mfa)G4T5m!vAHtX$d<5aQ)lx1q z2DR1va#v&rGy?;P*(!vf62%h!lZ%cC4tq_aq(t#x-1lf@;S1lM5*e(BYrQAJ_s+`E zoRzz=D-_5(_f;ozph*^7zn*r%FPP;9F*gbg-5KvndKz;L*Nu)f0;qRt7|OtBaO^MD z@N??{Bl^LhPlOGnKP_!>P6NnWZgHA~i<6nLO-dpMF$$v7p-aPuNi&SR+)P`{y4kH1Y@RofH z`%hH7Wk8M8SxF#S8x|lGoHKZ|)XhOP7~KjH7=UP6rmcR>I!fej2gVgs9-=acurq#Bd-FVA1F%C-F-NW)>7h_~AmfEz%b&*ZO@$!r?7};Z zsX^(GabOVO7*Cu51O}g&8SU62<^z9oc8LMbAtMBy7+^~79;CB|B)9RxbL z+I99BgKkS2xFQLRCLsJg21%ih@{$jp5N?cY{pT+qdSr+Mk4KEGZf$EKFYWmRB-Yt* z^8X*Q<>hksqu$lP#JkL4?MGX8vILMC&d)UOUq^RWxk62?`h9y z2-D<|iCU_DusKyNFiz?HPn6!$H|j|Nep)VkhhU`pD`=I`C5zdRuKT?l5n?mSPps~8 z++~1+PR-2yYf1^@rMu88oJe6UPc&F`xSaX@Q;ilb3D7u9x}TCx#VRbFZUG`YiTJ0L z1Kmyc-0}InFzIsWb^Q6}lG3UTg0h}PN%tycV#=WN-Su@F=424?%iigmYxyL+EXI`y zp3I$Xi*r)(P)l=kT-MGg7|-Sb+j(tOp3%-_B#PU;jh$cVJmkP6+^ric#l}Y%E%0sM z-m64HpCBqin~bDENQd=bmPBgpaCV-IvO#uOXtrJ}iUrhCMQ&b7&KXxSgwJdyh9*^ufIy zcHdm-o2NfLz%||>VDSFAfieto$eY9=Rfi`f_-{li0L{T<`PAWE*RTF9MyZE4x2wb8 zE0*PKI}uRlCXsSoqs#5M1|)?<49L`@9%fUW#4%jBN%P!9)5=L>W^+$Cwicf@hp(H% zmB5>eIw))MPyY;a#mlkpXRGrIX}aTsn`$UZw^g09ajr#ZIT?ps+1{|yA5u@ra_VoxTtY-c*J|N*^VaS-!XcY5GSeiWKBKPb#(3&D6^=9ei`IXtnP?>%> y3Hp5^46&fg<|w?4UuUZhPnw%@?A!ROe!q%6Uk?$)z&gpLEkN5d=+H@6>bez|TDq+9XRByFu2sA%x%|;}wsC8-^vl)0xh|FvWx;RBzE{Z&lh1 zqiQgL4Zw8{iTP^TnJ?}G!T3~;?}Gc+p%r{*LcBYLh~k=zZy;XvN$-tW!bliFZ$V9% zns)i{w{|6hzEEUF$n!#S2C3#=KbyNVYSh=ymThF{#LZPVG?OKD3s#|{#FjG=d7_*O zxYgNHD^RFTSlMaI93j*wG0bQ4omGvZ&>H(n1gZTV;S2NA0uAyPSWSev9TJwpgbEOe zn>Z}h$t1WbdRKmcWbF&>kT>!V{7PsGq&g&<1SScp@YyZ02HXK?Y7xP#+e|N1ojJGW z`9H6%As^1e*p?nFUOi(5)~UrP-lW1MYr8#l-b2axS5L81z$AgDE8XC&_v^7`gIzq1ij>;JNB0%m1_)J_wGf0tfin3DFI zA)03ci{e($WJ)la*@{PpjTWDsxSa%ltNSfsLKs*JVJN1ojAx^rV-yDGi!F+ zY#KIyrZtOAZY+`L_XR{wx7A4j25_3FHFg`-9ozy<>-6b)ww~}}GWcB+6a;Z-G)&t0 zhr56L*qQ~I zcGTL00vkKD-XCUwp=n}XJE`Zm-cDbL&M4>P1O>Pagd(#1)aC#Lz5d zDBgTgQNffBle^WSH!oRye#7T6%Kan?vHU$l3%(6tW)6yMh3E`$Dsj>mP)<;uI1XcV9IvHbhF=@0=rFwW`NpvmV zO{DE@onOp~Q@9^0*}|bO?U_KcB|!5T zoX%RvGXh>d(+T^4%yc5Fk-97NapF?#V<*7Q0CV@H^l|~xD8MAh(}8f$B$Qp2`J#OB zVLTR<^B*s#Ss7eE*@`sS@zjo|Da~@Z#6ZVAhT5}%Hn^XpB3-sq#fkSycm-^LCf00@6gYls(p$8 diff --git a/shell/Portefeuille.png b/shell/G1Anar.png similarity index 100% rename from shell/Portefeuille.png rename to shell/G1Anar.png diff --git a/shell/cron_SSH.activate.sh b/shell/cron_IPFS_open_SSH.sh similarity index 100% rename from shell/cron_SSH.activate.sh rename to shell/cron_IPFS_open_SSH.sh diff --git a/shell/functions.sh b/shell/functions.sh index a63d6e9..b7367e0 100755 --- a/shell/functions.sh +++ b/shell/functions.sh @@ -494,8 +494,8 @@ log "__SUB:sms_INIT_ACCOUNT: ($1=phone, $2=NOSMS)" ################################################################################################################################# function check_account (){ -log "__SUB:check_account: SILKAJ...... max 15 sec....." -AMOUNTG1=$(./shell/timeout.sh -t 15 ./silkaj/silkaj amount "$PUBKEY") +log "__SUB:check_account: SILKAJ...... max 21 sec....." +AMOUNTG1=$(./shell/timeout.sh -t 21 ./silkaj/silkaj amount "$PUBKEY") AMOUNTDU=$(bc <<< "scale=2; $AMOUNTG1 / $DUFACTOR") AMOUNTLOVE=$(bc <<< "$AMOUNTG1 * 100 / $DUFACTOR") diff --git a/shell/good.nodes.txt b/shell/good.nodes.txt index 659f426..b5b717b 100644 --- a/shell/good.nodes.txt +++ b/shell/good.nodes.txt @@ -1,3 +1,4 @@ +duniter.dethegeek.eu.org:443 g1.duniter.fr:443 g1.duniter.org:443 g1.le-sou.org:443 diff --git a/shell/sms_BILLET.sh b/shell/sms_BILLET.sh index 059c09a..f902841 100755 --- a/shell/sms_BILLET.sh +++ b/shell/sms_BILLET.sh @@ -7,7 +7,7 @@ # Create and print 6 G1Billets de nn LOVE source ./shell/init.sh source ./shell/functions.sh -log "X sms_BILLET.sh ($1=phone, $2=VALbillet)" +log "__SUB:sms_BILLET.sh: ($1=phone, $2=VALbillet)" phone="$1" VALbillet="$2" @@ -20,7 +20,7 @@ sms_INIT_ACCOUNT "$phone" "NOSMS" # FIXED LOVE UNIT (6 month maximum validity) UNIT="LOVE" -log "MEMBER? $PHONE => $MEMBER" +log "__SUB:sms_BILLET.sh: MEMBER? $PHONE => $MEMBER" if [[ $UNKNOWN == "unknown" || "$MEMBER" == "" ]]; then sms_ERROR "$phone" "Porte-monnaie non identifié. @@ -56,7 +56,7 @@ VIR=$(bc -l <<< "scale=2; $amount * $DUFACTOR / 100") # Need at least $MIN G1 available! $BILLCOM G1 commission MIN=$(bc -l <<< "$AMOUNTG1 - $LIMIT - 21") testmin=$( echo "${VIR} < ${MIN}" | bc -l ) -log "TEST : $VIR < $MIN ? $testmin" +log "__SUB:sms_BILLET.sh: TEST : $VIR < $MIN ? $testmin" # silkaj NODE CHANGE !!! #SILKAJNODE=$(./shell/checknodes.sh) @@ -88,19 +88,21 @@ then boucle=$(bc -l <<< "$boucle + 1") - log "->BILLET:$PHONE:$NUMBER:$VALbillet:$UNIT" + log "__SUB:sms_BILLET.sh: ->BILLET:$PHONE:$NUMBER:$VALbillet:$UNIT" # CREATE "NUMBER SECRET SALT" ACCOUNT for G1 transfert TRANSAC=$(bc -l <<< "scale=2; $VIR / $NBbillets") BILLETPUBKEY=$(./silkaj/silkaj generate_auth_file --auth-scrypt -salt="$NUMBER" -password="$SECRET$SALT") # COPY authfile for easier usage in 6 month... + log "__SUB:sms_BILLET.sh: authfile KEY : ./billets/$bpath/note.authfile.GPGPASS.gpg" + mkdir -p "./billets/$bpath" echo "${GPGPASS}" | gpg -q --output "./billets/$bpath/note.authfile.GPGPASS.gpg" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "./authfile" + rm -f "./authfile" - log_history $PHONE "G1BILLET, $TRANSAC, $BILLETPUBKEY, $NUMBER, $SECRET$SALT" + log_history $PHONE "G1BILLET, $TRANSAC, $BILLETPUBKEY" sleep 3 # Fill BILLET with TRANSAC amount PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$TRANSAC" --output="$BILLETPUBKEY" --comment="G1Billet $NUMBER" -y) if [[ "$(echo $PAY | cut -d '|' -f 1)" != "KO" ]]; then - mkdir -p "./billets/$bpath" # NOTES ARE FILES STORED IN DICEWARE COMPOSED SUBDIR echo "$(date +%Y%m%d)" > "./billets/$bpath/note.creationdate" echo "$MEMBER" > "./billets/$bpath/note.creator" @@ -123,30 +125,36 @@ then # PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$NUMBER" -password="$SECRET $SALT" --amount="0.05" --output="$MEMRIB" --comment="THIRD_PARTY_MANAGER:$NODE_G1PUBKEY:G1SMS:BILLET:$VALbillet:$UNIT:$NUMBER" -y) else sms_ERROR "$PHONE" "Un problème est survenu. Contactez $ADMINPSEUDO au $ADMINPHONE" - log "ERROR SILKAJ" + # Copy & Send produiced files + zip /tmp/$PHONE_Bills_$bpath.zip ./billets/MEMBERS/$MEMBER/*.* + mpack -s "[G1sms+]_G1Billets ($bpath) Erreur... création G1Billets..." -d /tmp/message_body.txt /tmp/$PHONE_Bills_$bpath.zip $MAIL && mv /tmp/$PHONE_Bills_$bpath.zip ./billets/MEMBERS/$MEMBER/ && log "__SUB:sms_BILLET.sh: ALERT sent....." + + log "__SUB:sms_BILLET.sh: ERROR SILKAJ $(cat ./silkaj/src/constants.py)" exit fi done # + G1SMS Commission sleep 2 - COM=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$BILLCOM" --output="$NODE_G1PUBKEY" --comment="[G1SMS] Achat G1Billets" -y) + COM=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$BILLCOM" --output="$NODE_G1PUBKEY" --comment="[G1sms+] Achat G1Billets" -y) # POUR IMPRIMER LES BILLETS! Brancher votre imprimante, configurer cups, activer code lp ;) num=$(date +%Y%m%d) - log "PRINT $num $MEMBER" - montage ./billets/MEMBERS/$MEMBER/*.jpg -tile 2x3 -geometry 964x459 /tmp/$PHONE_Bills_$bpath.pdf && rm -f ./billets/MEMBERS/$MEMBER/*.jpg && log "PDF made /tmp/$PHONE_Bills_$bpath.pdf" - zip /tmp/$PHONE_Bills_$bpath.zip /tmp/$PHONE_Bills_$bpath.pdf && rm -f /tmp/$PHONE_Bills_$bpath.pdf && log "Zip done. Remove PDF" + log "__SUB:sms_BILLET.sh: PRINT $num $MEMBER" + montage ./billets/MEMBERS/$MEMBER/*.jpg -tile 2x3 -geometry 964x459 /tmp/$PHONE_Bills_$bpath.pdf && rm -f ./billets/MEMBERS/$MEMBER/*.jpg && log "__SUB:sms_BILLET.sh: PDF made /tmp/$PHONE_Bills_$bpath.pdf" + cd /tmp && zip $PHONE_Bills_$bpath.zip $PHONE_Bills_$bpath.pdf && log "__SUB:sms_BILLET.sh: Zip DONE :: /tmp$PHONE_Bills_$bpath.zip !!" && cd - + # rm -f /tmp/$PHONE_Bills_$bpath.pdf # SEND EMAIL ZIP attached echo "Commande #$NANODATE/$bpath >> Planche de 6 G1Billets : $VALbillet LOVE << -Ecrivez-nous vos remarques... -Cesium: https://cesium.app -SMS: https://g1sms.fr" > /tmp/message_body.txt - mpack -s "[G1sms+]_G1Billets ($bpath) Imprimer + Scotch à gratter! Détruire cet email..." -d /tmp/message_body.txt /tmp/$PHONE_Bills_$bpath.zip $MAIL && rm /tmp/$PHONE_Bills_$bpath.zip && log "EMAIL sent....." - mpack -s "[G1sms+]_G1Billets ($bpath) imprimer recto/verso vos G1Billets?!" -d /tmp/message_body.txt ./Dos_G1Billets.odt $MAIL && log "+ EMAIL recto: OK" - log "G1Billets $PHONE_Bills_$bpath.pdf envoyé par email à $MEMBER : $MAIL " +Envoyez-nous vos remarques... + +https://g1sms.fr" > /tmp/message_body.txt + mpack -s "[G1sms+]_G1Billets ($bpath) A IMPRIMER et détruire cet email..." -d /tmp/message_body.txt /tmp/$PHONE_Bills_$bpath.zip $MAIL && log "__SUB:sms_BILLET.sh: EMAIL sent....." +# rm -f /tmp/$PHONE_Bills_$bpath.zip +# mpack -s "[G1sms+]_G1Billets ($bpath) imprimer recto/verso vos G1Billets?!" -d /tmp/message_body.txt ./Dos_G1Billets.odt $MAIL && log "__SUB:sms_BILLET.sh: + EMAIL recto: OK" + log "__SUB:sms_BILLET.sh: G1Billets $PHONE_Bills_$bpath.pdf envoyé par email à $MEMBER : $MAIL " mess="[G1SMS] $NBbillets G1Billets de $VALbillet $UNIT ($TRANSAC G1) créé(s). Envoyés vers $MAIL, vérifiez vos SPAM... @@ -154,8 +162,9 @@ Support: $ADMINPSEUDO ($ADMINPHONE) " sms_SEND "$phone" "$mess" - # ADMIN ALERT + # ADMIN ALERT SMS + TODO Add ADMINEMAIL parameter in "install.sh" sms_SEND "$ADMINPHONE" "$MEMBER vient de créer $NBbillets G1Billets de $VALbillet $UNIT ($TRANSAC G1): $MAIL" + cat ./email.txt | sed s/EMAIL/frenault@linkeo.com/g | sed s/SUBJECT/Creation_G1Billets/g | sed s/MESSAGE/"$MEMBER ($PHONE) vient de creer $NBbillets G1Billets de $VALbillet $UNIT ($TRANSAC G1) vers $MAIL"/g | ssmtp "frenault@linkeo.com" ##################################### # Amount too High, solde insuffisant @@ -169,7 +178,7 @@ Insuffisant pour créer $NBbillets billet(s) de $VALbillet $UNIT https://g1.duniter.fr/api/#/v1/payment/$PUBKEY?amount=$VIR" fi -log "END sms_BILLET.sh" +log "__SUB:sms_BILLET.sh: END sms_BILLET.sh" log "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" exit diff --git a/shell/sms_BILLET_MAKE.sh b/shell/sms_BILLET_MAKE.sh index 2eb457e..18c1493 100755 --- a/shell/sms_BILLET_MAKE.sh +++ b/shell/sms_BILLET_MAKE.sh @@ -22,7 +22,7 @@ NOTERIB="$6" MEMBER="$7" TRANSAC="$8" PHONE="$9" -log "X ./shell/sms_BILLET_MAKE.sh \"$1\" \"$2\" \"$3\" \"$4\" \"$5\" \"$6\" \"$7\" \"$8\"" +log "X sudo ./shell/sms_BILLET_MAKE.sh \"$1\" \"$2\" \"$3\" \"$4\" \"$5\" \"$6\" \"$7\" \"$8\"" if [[ "$NOTERIB" == "" || "$MEMBER" == "" ]] then @@ -48,6 +48,9 @@ valid="0${valid:0:2}" if [[ $(file "./wallets/$PHONE/$PHONE.avatar.png" | grep 'PNG') ]]; then composite -compose Over -gravity East -geometry +15+0 -dissolve 33% "./wallets/$PHONE/$PHONE.avatar.png" "./shell/Oeuro.jpg" "/tmp/$NUMERO.jpg" composite -compose Over -gravity West -geometry +15+0 -dissolve 33% "./wallets/$PHONE/$PHONE.avatar.png" "/tmp/$NUMERO.jpg" "/tmp/$NUMERO.jpg" +else + composite -compose Over -gravity East -geometry +15+0 -dissolve 33% "./shell/G1Anar.png" "./shell/Oeuro.jpg" "/tmp/$NUMERO.jpg" + composite -compose Over -gravity West -geometry +15+0 -dissolve 33% "./shell/G1Anar.png" "/tmp/$NUMERO.jpg" "/tmp/$NUMERO.jpg" fi # Add G1Billet_LOVE.png logo (250px) @@ -101,11 +104,11 @@ SIMPLEPHONE=$(echo $MASTERPHONE | sed 's/\+33/0/g') convert -font 'Liberation-Sans' \ -pointsize 120 -fill black -draw 'text 200,220 "'"$DUPART DU"'"' \ -pointsize 45 -draw 'text 550,270 "'"$MONTANT $UNIT"'"' \ --pointsize 35 -draw 'text 50,60 "'"$JUNE G1 [https://g1sms.fr]"'"' \ +-pointsize 35 -draw 'text 50,60 "'"https://g1sms.fr _ G1Billet _ $JUNE G1"'"' \ -pointsize 30 -draw 'text 60,100 "'"Identifiant: $NUMERO"'"' \ --pointsize 22 -fill black -draw 'text 400,340 "'"Code Secret: $SECRET"'"' \ --pointsize 22 -fill black -draw 'text 280,410 "'"Porte Monnaie Libre!! A utiliser avant le 01/$valid/$year"'"' \ --pointsize 20 -draw 'text 50,444 "'"Envoyer CHK $NUMERO (+ code secret) par SMS au $SIMPLEPHONE ou https://cesium.app"'"' \ +-pointsize 22 -fill black -draw 'text 380,340 "'"Code Secret: $SECRET"'"' \ +-pointsize 22 -fill black -draw 'text 260,408 "'"Porte Monnaie Libre!! A utiliser avant le 01/$valid/$year"'"' \ +-pointsize 20 -draw 'text 15,442 "'"Utilisation: CHK $NUMERO (+ code secret) par SMS au $SIMPLEPHONE ou https://cesium.app"'"' \ "/tmp/$NUMERO.jpg" "/tmp/BILL.$year.$valid.$NUMERO.$MONTANT.$UNIT.jpg" # Payable par SMS en envoyant les codes grattant la case comportant le SECRET diff --git a/shell/sms_G1TAG.sh b/shell/sms_G1TAG.sh index 787b80e..4d4d528 100755 --- a/shell/sms_G1TAG.sh +++ b/shell/sms_G1TAG.sh @@ -220,7 +220,7 @@ TAGCHAIN="./TAG/${RR}/TAG_chain" # contains IPFS current ipfs hash # if [[ $(file "./wallets/$PHONE/$PHONE.avatar.png" | grep 'PNG') ]]; then # composite -compose Over -resize 150% -gravity Center "./wallets/$PHONE/$PHONE.avatar.png" "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" # else -# composite -compose Over -resize 100% -gravity Center "./shell/Portefeuille.png" "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" +# composite -compose Over -resize 100% -gravity Center "./shell/G1Anar.png" "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" # fi # WRITE G1Tag G1 amount diff --git a/shell/sms_VIR.sh b/shell/sms_VIR.sh index d74fa41..5847be3 100755 --- a/shell/sms_VIR.sh +++ b/shell/sms_VIR.sh @@ -33,7 +33,7 @@ testmin=${accounting[0]} VIR=${accounting[1]} PERCENT=${accounting[2]} if [[ $testmin -eq 0 ]]; then - sms_ERROR "$PHONE" "Solde de votre Porte-monnaie G1sms insuffisant. Minimum $charge G1! Rechargez par Cesium." + sms_ERROR "$PHONE" "Solde de votre Porte-monnaie G1sms insuffisant. Minimum $VIR G1! Rechargez par Cesium." exit fi @@ -73,7 +73,7 @@ else fi if [[ "$DESTRIB" != "" ]]; then - PAY=$(./shell/timeout.sh -t 20 ./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$VIR" --output="$DESTRIB" --comment="[G1sms+] VIR $VIR G1" -y) + PAY=$(./shell/timeout.sh -t 30 ./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$VIR" --output="$DESTRIB" --comment="[G1sms+] VIR $VIR G1" -y) if [[ "$(echo $PAY | cut -d '|' -f 1)" != "KO" && "$PAY" != "" ]]; then log "__SUB:sms_VIR.sh: VIREMENT VERS $DESTMEM OK" mess="[G1sms+] $MEMBER From 8bf6afe50581184e52f9838e64395f067612a361 Mon Sep 17 00:00:00 2001 From: qo-op Date: Thu, 26 Dec 2019 17:44:26 +0100 Subject: [PATCH 25/26] SHA256 PHONE compatibility & SWARMKEY GPG CYPHER --- _chain | 2 +- _comments | 3 +++ _nanodate | 2 +- _publishkey.gpg | Bin 1288 -> 1288 bytes shell/cron_IPFS_open_SSH.sh | 18 +++++++++++------- shell/functions.sh | 44 +++++++++++++++++++++++++++++++------------- shell/init_keys.sh | 8 ++++++-- shell/sms_AIDE.sh | 18 +++++++++--------- shell/sms_PAY.sh | 24 +++++++++++++++--------- 9 files changed, 77 insertions(+), 42 deletions(-) diff --git a/_chain b/_chain index f09e9e6..a1c8920 100755 --- a/_chain +++ b/_chain @@ -1 +1 @@ -QmbVfLJ9UsnyV3Si9UgZVS4srCnL1c2Gqt7XissCV4iC83 +QmWEyZDyn7XMM3pDFCBkDqC6XPAraTSLHbVD3h7geunNWy diff --git a/_comments b/_comments index b7bbce3..0c75af6 100755 --- a/_comments +++ b/_comments @@ -178,3 +178,6 @@ OK 2019-12-20: NOW 2019-12-21: Various 2019-12-24: +2019-12-26: SWARMKEY +2019-12-26: ipfs p2p listen /x/$YOU /ip4/127.0.0.1/tcp/80 +2019-12-26: ./wallets/sha256sum(PHONE) diff --git a/_nanodate b/_nanodate index 506b75f..95fdd35 100755 --- a/_nanodate +++ b/_nanodate @@ -1 +1 @@ -1577203467543924569 +1577378596986046001 diff --git a/_publishkey.gpg b/_publishkey.gpg index d9c30e259497e617dc898059a5bc80273087d18c..2b7049901c18943d74b54cc9773c61bc4ea9f1da 100755 GIT binary patch literal 1288 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 "$PINFILE" echo "${GPGPASS}" | gpg -q --output "$GPGPINFILE" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$PINFILE" + echo "${SWARMKEY}" | gpg -q --output "$GPGPINFILE.swarm" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$PINFILE" PIN=$(cat "$PINFILE" | xargs) echo "" > "$PINFILE" - echo "114" > "$G1COUNTFILE" + echo "314" > "$G1COUNTFILE" echo "$PUBKEY" > "$PUBKEYFILE" echo "$COIN" > "$UNITFILE" echo "$MASTERPHONE" > "$SMSNODE" @@ -397,39 +407,46 @@ log "__SUB:sms_INIT_ACCOUNT: ($1=phone, $2=NOSMS)" ###################################################################### if [[ ! -f "$GPGPINFILE" ]] then + HASH=$(echo $PHONE | sha256sum | cut -d ' ' -f 1) + # ------------8<------------------ # WALLET MIGRATION -> CRYPT PIN (For Old G1sms clear PIN WALLETs...) - # ADD NEW PARAMS TO WALLET - ####################### - # 4 derniers chiffres du numéro de téléphone - echo "$MASTERPHONE" > "$SMSNODE" - TAIL=${PHONE:8:4} - # No UIDNA yet. Create new - UIDNA=$(./shell/diceware.sh 1 | xargs) - # Check if already existing among all swarm wallets - while [[ $(grep -Rwl $UIDNA$TAIL ./wallets_swarm/*/*.uidna) ]]; do UIDNA=$(./shell/diceware.sh 1 | xargs); done - echo "$UIDNA$TAIL" > "$UIDNAFILE" + if [[ ! -s "$UIDNAFILE" ]]; then + # ADD NEW PARAMS TO WALLET + ####################### + # 4 derniers chiffres du numéro de téléphone + TAIL=${PHONE:8:4} + # No UIDNA yet. Create new + UIDNA=$(./shell/diceware.sh 1 | xargs) + # Check if already existing among all swarm wallets + while [[ $(grep -Rwl $UIDNA$TAIL ./wallets_swarm/*/*.uidna) ]]; do UIDNA=$(./shell/diceware.sh 1 | xargs); done + echo "$UIDNA$TAIL" > "$UIDNAFILE" + fi + echo "$MASTERPHONE" > "$SMSNODE" PIN=$(cat "$PINFILE" | xargs) log "__SUB:sms_INIT_ACCOUNT: Old G1sms wallet ;) SECURITY HOLE... Chiffrage PGP du PIN !!!" echo "${GPGPASS}" | gpg -q --output "$GPGPINFILE" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$PINFILE"; + echo "${SWARMKEY}" | gpg -q --output "$GPGPINFILE.swarm" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$PINFILE"; else # ------------>8------------------ log "__SUB:sms_INIT_ACCOUNT: Déchiffrage PGP PIN..." # GPG decypher PIN # TODO make decypher less stress on filesystem, use /tmp and ramdisk echo "${GPGPASS}" | gpg -d -q --output "$PINFILE" --yes --pinentry-mode loopback --passphrase-fd 0 "$GPGPINFILE" + [[ ! -f $PINFILE ]] && echo "${SWARMKEY}" | gpg -d -q --output "$PINFILE" --yes --pinentry-mode loopback --passphrase-fd 0 "$GPGPINFILE.swarm" PIN=$(cat "$PINFILE" | xargs) echo "" > "$PINFILE"; fi # CYPHER EMAIL FILE - if [[ ! -f "$GPGMAILFILE" ]]; then + if [[ ! -f "$GPGMAILFILE.swarm" ]]; then # ------------8<------------------ # NO .gpg file, CREATING it (OLD G1sms accounts) if [ -f "$MAILFILE" ]; then MAIL=$(cat "$MAILFILE"); echo "${GPGPASS}" | gpg -q --output "$GPGMAILFILE" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$MAILFILE"; + echo "${SWARMKEY}" | gpg -q --output "$GPGMAILFILE.swarm" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$MAILFILE"; else MAIL=""; fi @@ -437,6 +454,7 @@ log "__SUB:sms_INIT_ACCOUNT: ($1=phone, $2=NOSMS)" else # Already existing gpg DECODING IT echo "${GPGPASS}" | gpg -d -q --output "$MAILFILE" --yes --pinentry-mode loopback --passphrase-fd 0 "$GPGMAILFILE" + [[ -f "$GPGMAILFILE.swarm" ]] && echo "${SWARMKEY}" | gpg -d -q --output "$MAILFILE" --yes --pinentry-mode loopback --passphrase-fd 0 "$GPGMAILFILE.swarm" MAIL=$(cat "$MAILFILE"); echo "" > "$MAILFILE"; fi diff --git a/shell/init_keys.sh b/shell/init_keys.sh index b4e1619..fa9baf1 100755 --- a/shell/init_keys.sh +++ b/shell/init_keys.sh @@ -21,6 +21,10 @@ YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) export GPGPASS=$(cat "/home/$YOU/.ipfs/config" | jq '.Identity.PrivKey' | sed s/\"//g) if [ ! $GPGPASS ]; then echo "FATAL ERROR:: IPFS Node.Identity.PrivKey GPGPASS EMPTY"; exit; fi +# GET SWARM KEY G1sms+ .ipfs/swarm.key +export SWARMKEY=$(cat "/home/$YOU/.ipfs/swarm.key" | tail -n 1) +if [ ! $SWARMKEY ]; then echo "FATAL ERROR:: .ipfs/swarm.key EMPTY"; exit; fi + ################################################################## # G1sms+ Swarm KEYS ################################################################## @@ -31,8 +35,8 @@ if [[ -f "${GPATH}/g1sms.pub.key" && -f "${GPATH}/g1sms.priv.key" ]]; then export NODE_G1PUBKEY=$(cat "${GPATH}/g1sms.pub.key") export NODE_G1PRIVKEYFILE="${GPATH}/g1sms.priv.key" else - echo "ATTENTION!! Vous devez posséder la clef du G1 Wallet utilisé par le SWARM G1sms!!" - ./shell/parle.sh "Les clefs du portefeuille essaim G1 SMS sont absente. Au revoir." + echo "ATTENTION!! Vous devez installer une clef de G1 Wallet!!" + ./shell/parle.sh "Il manque les Clefs du portefeuille G1 de votre noeud. Au revoir." echo "Fichiers manquants:" echo "${GPATH}/g1sms.pub.key" echo "${GPATH}/g1sms.priv.key" diff --git a/shell/sms_AIDE.sh b/shell/sms_AIDE.sh index 0bd21ad..7c182dd 100755 --- a/shell/sms_AIDE.sh +++ b/shell/sms_AIDE.sh @@ -10,21 +10,21 @@ log "X sms_AIDE.sh ($1=phone)" sms_INIT_ACCOUNT "$1" "NOSMS" -MESS="[Aide] -N Pseudo (membre ou nom de portefeuille) : Création portefeuille +MESS="N Pseudo : Création Portefeuille rattaché à Pseudo +S : Synchro Solde +P 06nnnnnnnn 300 : Payer 300 à 06nnnnnnnn U G1/DU/LOVE : Unité -S : Solde -P 06nnnnnnnn 300 : Payer 300 à 06nnnnnnnn" +" # Send response SMS sms_SEND "$1" "$MESS" -MESS="EMAIL moi@email : Indiquer son email -VIR 50 Pseudo : Virer 50 à Pseudo (membre ou Portefeuille SMS)" +MESS="EMAIL moi@email : Email pour commande G1Billets +BILL n : Recevoir 6 G1Billets remplis de n LOVE" sms_SEND "$1" "$MESS" -MESS="REC 50 Dest S 4 : Virer 50 à Dest pendant 4 Semaines (J/S/M/A) -BILL n : Recevoir 6 G1Billets remplis de n LOVE par email! -https://g1sms.fr - $ADMINPSEUDO ($ADMINPHONE)" +MESS="VIR 50 Pseudo : Virer 50 à Pseudo (membre ou Portefeuille SMS) +REC 50 Dest S 4 : Virer 50 à Dest, 4 Semaines (J/S/M/A) +Contact : $ADMINPSEUDO ($ADMINPHONE) - https://g1sms.fr" sms_SEND "$1" "$MESS" log "END sms_AIDE.sh" diff --git a/shell/sms_PAY.sh b/shell/sms_PAY.sh index 3edb8c2..f2add6a 100755 --- a/shell/sms_PAY.sh +++ b/shell/sms_PAY.sh @@ -17,6 +17,8 @@ pin=$PIN if [[ $UNKNOWN == "unknown" ]]; then sms_ERROR "$phone" "Porte-monnaie inconnu. Envoyez N (suivi de votre Pseudo membre) pour le créer." exit +else + log "PIN: $pin" fi ########################################################### @@ -40,8 +42,10 @@ if [[ -f "./wallets_swarm/$PHONEDEST/$PHONEDEST.pub" ]] then PUBKEYDEST=$(cat "./wallets_swarm/$PHONEDEST/$PHONEDEST.pub") UNITDEST=$(cat "./wallets_swarm/$PHONEDEST/$PHONEDEST.unit") + log "__SUB:sms_PAY.sh: PUBKEYDEST found in swarn... $PUBKEYDEST" else # NO, then create NEW Wallet + log "__SUB:sms_PAY.sh: Creating Account for... $PHONEDEST" sms_INIT_ACCOUNT "$PHONEDEST" # Refreshed new values PUBKEYDEST="$PUBKEY" @@ -49,11 +53,13 @@ else fi # Payement -PAY=$(./shell/timeout.sh -t 20 ./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$VIR" --output="$PUBKEYDEST" --comment="[G1sms+] PAY $AMOUNT $UNIT" -y) +log "./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$VIR" --output="$PUBKEYDEST"" +PAY=$(./shell/timeout.sh -t 30 ./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$VIR" --output="$PUBKEYDEST" --comment="[G1sms+] PAY $AMOUNT $UNIT" -y) if [[ "$(echo $PAY | cut -d '|' -f 1)" == "KO" || "$PAY" == "" ]]; then - new=$(./shell/checknodes.sh "BAN") - sms_ERROR "$phone" "Problème de payement avec silkaj (changement de serveur $new): $PAY"; - log "__SUB:sms_PAY.sh: Problème de payement avec silkaj $new : $PAY" + sms_ERROR "$phone" "PIN : $PAY ? Voyez vous votre code secret: $pin? +NON, Reinitaliser Compte. Envoyer: RAZ +OUI, Bourage Blockchain. Envoyer: S"; + log "__SUB:sms_PAY.sh: Problème de payement avec silkaj : $PAY" exit else # OK: Sync g1cents TODO check move_g1cents function and generalize on all silkaj transactions @@ -64,11 +70,11 @@ fi sleep 2 # + G1SMS Commission -COM=$(./shell/timeout.sh -t 20 ./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$PERCENT" --output="$NODE_G1PUBKEY" --comment="[G1sms+] Commission" -y) -if [[ "$(echo $COM | cut -d '|' -f 1)" == "KO" || "$PAY" == "" ]]; then - new=$(./shell/checknodes.sh "BAN") - sms_ERROR "$phone" "Problème de payement avec silkaj (changement de serveur $new): $COM"; - log "__SUB:sms_PAY.sh: Problème de payement avec silkaj $new : $COM" +log "./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$PERCENT" --output="$NODE_G1PUBKEY"" +COM=$(./shell/timeout.sh -t 30 ./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$PERCENT" --output="$NODE_G1PUBKEY" --comment="[G1sms+] P Commission" -y) +if [[ "$(echo $COM | cut -d '|' -f 1)" == "KO" || "$COM" == "" ]]; then + sms_ERROR "$phone" "Problème de bourrage blockchain : $COM"; + log "__SUB:sms_PAY.sh: Problème de payement avec silkaj : $COM" exit else # OK: Sync g1cents From 8d7188681e526d6579260aa0a73684eff8b6c67d Mon Sep 17 00:00:00 2001 From: qo-op Date: Sun, 29 Dec 2019 15:08:27 +0100 Subject: [PATCH 26/26] prepare multicanal --- _chain | 2 +- _comments | 3 --- _nanodate | 2 +- _publishkey.gpg | Bin 1288 -> 1288 bytes shell/cron_IPFS_open_SSH.sh | 12 ++++-------- shell/functions.sh | 44 +++++++++++++------------------------------- shell/init_keys.sh | 8 ++------ shell/sms_AIDE.sh | 18 +++++++++--------- shell/sms_PAY.sh | 24 +++++++++--------------- 9 files changed, 39 insertions(+), 74 deletions(-) diff --git a/_chain b/_chain index a1c8920..f09e9e6 100755 --- a/_chain +++ b/_chain @@ -1 +1 @@ -QmWEyZDyn7XMM3pDFCBkDqC6XPAraTSLHbVD3h7geunNWy +QmbVfLJ9UsnyV3Si9UgZVS4srCnL1c2Gqt7XissCV4iC83 diff --git a/_comments b/_comments index 0c75af6..b7bbce3 100755 --- a/_comments +++ b/_comments @@ -178,6 +178,3 @@ OK 2019-12-20: NOW 2019-12-21: Various 2019-12-24: -2019-12-26: SWARMKEY -2019-12-26: ipfs p2p listen /x/$YOU /ip4/127.0.0.1/tcp/80 -2019-12-26: ./wallets/sha256sum(PHONE) diff --git a/_nanodate b/_nanodate index 95fdd35..506b75f 100755 --- a/_nanodate +++ b/_nanodate @@ -1 +1 @@ -1577378596986046001 +1577203467543924569 diff --git a/_publishkey.gpg b/_publishkey.gpg index 2b7049901c18943d74b54cc9773c61bc4ea9f1da..d9c30e259497e617dc898059a5bc80273087d18c 100755 GIT binary patch literal 1288 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 "$PINFILE" echo "${GPGPASS}" | gpg -q --output "$GPGPINFILE" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$PINFILE" - echo "${SWARMKEY}" | gpg -q --output "$GPGPINFILE.swarm" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$PINFILE" PIN=$(cat "$PINFILE" | xargs) echo "" > "$PINFILE" - echo "314" > "$G1COUNTFILE" + echo "114" > "$G1COUNTFILE" echo "$PUBKEY" > "$PUBKEYFILE" echo "$COIN" > "$UNITFILE" echo "$MASTERPHONE" > "$SMSNODE" @@ -407,46 +397,39 @@ log "__SUB:sms_INIT_ACCOUNT: ($1=phone, $2=NOSMS)" ###################################################################### if [[ ! -f "$GPGPINFILE" ]] then - HASH=$(echo $PHONE | sha256sum | cut -d ' ' -f 1) - # ------------8<------------------ # WALLET MIGRATION -> CRYPT PIN (For Old G1sms clear PIN WALLETs...) - if [[ ! -s "$UIDNAFILE" ]]; then - # ADD NEW PARAMS TO WALLET - ####################### - # 4 derniers chiffres du numéro de téléphone - TAIL=${PHONE:8:4} - # No UIDNA yet. Create new - UIDNA=$(./shell/diceware.sh 1 | xargs) - # Check if already existing among all swarm wallets - while [[ $(grep -Rwl $UIDNA$TAIL ./wallets_swarm/*/*.uidna) ]]; do UIDNA=$(./shell/diceware.sh 1 | xargs); done - echo "$UIDNA$TAIL" > "$UIDNAFILE" - fi - + # ADD NEW PARAMS TO WALLET + ####################### + # 4 derniers chiffres du numéro de téléphone echo "$MASTERPHONE" > "$SMSNODE" + TAIL=${PHONE:8:4} + # No UIDNA yet. Create new + UIDNA=$(./shell/diceware.sh 1 | xargs) + # Check if already existing among all swarm wallets + while [[ $(grep -Rwl $UIDNA$TAIL ./wallets_swarm/*/*.uidna) ]]; do UIDNA=$(./shell/diceware.sh 1 | xargs); done + echo "$UIDNA$TAIL" > "$UIDNAFILE" + PIN=$(cat "$PINFILE" | xargs) log "__SUB:sms_INIT_ACCOUNT: Old G1sms wallet ;) SECURITY HOLE... Chiffrage PGP du PIN !!!" echo "${GPGPASS}" | gpg -q --output "$GPGPINFILE" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$PINFILE"; - echo "${SWARMKEY}" | gpg -q --output "$GPGPINFILE.swarm" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$PINFILE"; else # ------------>8------------------ log "__SUB:sms_INIT_ACCOUNT: Déchiffrage PGP PIN..." # GPG decypher PIN # TODO make decypher less stress on filesystem, use /tmp and ramdisk echo "${GPGPASS}" | gpg -d -q --output "$PINFILE" --yes --pinentry-mode loopback --passphrase-fd 0 "$GPGPINFILE" - [[ ! -f $PINFILE ]] && echo "${SWARMKEY}" | gpg -d -q --output "$PINFILE" --yes --pinentry-mode loopback --passphrase-fd 0 "$GPGPINFILE.swarm" PIN=$(cat "$PINFILE" | xargs) echo "" > "$PINFILE"; fi # CYPHER EMAIL FILE - if [[ ! -f "$GPGMAILFILE.swarm" ]]; then + if [[ ! -f "$GPGMAILFILE" ]]; then # ------------8<------------------ # NO .gpg file, CREATING it (OLD G1sms accounts) if [ -f "$MAILFILE" ]; then MAIL=$(cat "$MAILFILE"); echo "${GPGPASS}" | gpg -q --output "$GPGMAILFILE" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$MAILFILE"; - echo "${SWARMKEY}" | gpg -q --output "$GPGMAILFILE.swarm" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$MAILFILE"; else MAIL=""; fi @@ -454,7 +437,6 @@ log "__SUB:sms_INIT_ACCOUNT: ($1=phone, $2=NOSMS)" else # Already existing gpg DECODING IT echo "${GPGPASS}" | gpg -d -q --output "$MAILFILE" --yes --pinentry-mode loopback --passphrase-fd 0 "$GPGMAILFILE" - [[ -f "$GPGMAILFILE.swarm" ]] && echo "${SWARMKEY}" | gpg -d -q --output "$MAILFILE" --yes --pinentry-mode loopback --passphrase-fd 0 "$GPGMAILFILE.swarm" MAIL=$(cat "$MAILFILE"); echo "" > "$MAILFILE"; fi diff --git a/shell/init_keys.sh b/shell/init_keys.sh index fa9baf1..b4e1619 100755 --- a/shell/init_keys.sh +++ b/shell/init_keys.sh @@ -21,10 +21,6 @@ YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) export GPGPASS=$(cat "/home/$YOU/.ipfs/config" | jq '.Identity.PrivKey' | sed s/\"//g) if [ ! $GPGPASS ]; then echo "FATAL ERROR:: IPFS Node.Identity.PrivKey GPGPASS EMPTY"; exit; fi -# GET SWARM KEY G1sms+ .ipfs/swarm.key -export SWARMKEY=$(cat "/home/$YOU/.ipfs/swarm.key" | tail -n 1) -if [ ! $SWARMKEY ]; then echo "FATAL ERROR:: .ipfs/swarm.key EMPTY"; exit; fi - ################################################################## # G1sms+ Swarm KEYS ################################################################## @@ -35,8 +31,8 @@ if [[ -f "${GPATH}/g1sms.pub.key" && -f "${GPATH}/g1sms.priv.key" ]]; then export NODE_G1PUBKEY=$(cat "${GPATH}/g1sms.pub.key") export NODE_G1PRIVKEYFILE="${GPATH}/g1sms.priv.key" else - echo "ATTENTION!! Vous devez installer une clef de G1 Wallet!!" - ./shell/parle.sh "Il manque les Clefs du portefeuille G1 de votre noeud. Au revoir." + echo "ATTENTION!! Vous devez posséder la clef du G1 Wallet utilisé par le SWARM G1sms!!" + ./shell/parle.sh "Les clefs du portefeuille essaim G1 SMS sont absente. Au revoir." echo "Fichiers manquants:" echo "${GPATH}/g1sms.pub.key" echo "${GPATH}/g1sms.priv.key" diff --git a/shell/sms_AIDE.sh b/shell/sms_AIDE.sh index 7c182dd..0bd21ad 100755 --- a/shell/sms_AIDE.sh +++ b/shell/sms_AIDE.sh @@ -10,21 +10,21 @@ log "X sms_AIDE.sh ($1=phone)" sms_INIT_ACCOUNT "$1" "NOSMS" -MESS="N Pseudo : Création Portefeuille rattaché à Pseudo -S : Synchro Solde -P 06nnnnnnnn 300 : Payer 300 à 06nnnnnnnn +MESS="[Aide] +N Pseudo (membre ou nom de portefeuille) : Création portefeuille U G1/DU/LOVE : Unité -" +S : Solde +P 06nnnnnnnn 300 : Payer 300 à 06nnnnnnnn" # Send response SMS sms_SEND "$1" "$MESS" -MESS="EMAIL moi@email : Email pour commande G1Billets -BILL n : Recevoir 6 G1Billets remplis de n LOVE" +MESS="EMAIL moi@email : Indiquer son email +VIR 50 Pseudo : Virer 50 à Pseudo (membre ou Portefeuille SMS)" sms_SEND "$1" "$MESS" -MESS="VIR 50 Pseudo : Virer 50 à Pseudo (membre ou Portefeuille SMS) -REC 50 Dest S 4 : Virer 50 à Dest, 4 Semaines (J/S/M/A) -Contact : $ADMINPSEUDO ($ADMINPHONE) - https://g1sms.fr" +MESS="REC 50 Dest S 4 : Virer 50 à Dest pendant 4 Semaines (J/S/M/A) +BILL n : Recevoir 6 G1Billets remplis de n LOVE par email! +https://g1sms.fr - $ADMINPSEUDO ($ADMINPHONE)" sms_SEND "$1" "$MESS" log "END sms_AIDE.sh" diff --git a/shell/sms_PAY.sh b/shell/sms_PAY.sh index f2add6a..3edb8c2 100755 --- a/shell/sms_PAY.sh +++ b/shell/sms_PAY.sh @@ -17,8 +17,6 @@ pin=$PIN if [[ $UNKNOWN == "unknown" ]]; then sms_ERROR "$phone" "Porte-monnaie inconnu. Envoyez N (suivi de votre Pseudo membre) pour le créer." exit -else - log "PIN: $pin" fi ########################################################### @@ -42,10 +40,8 @@ if [[ -f "./wallets_swarm/$PHONEDEST/$PHONEDEST.pub" ]] then PUBKEYDEST=$(cat "./wallets_swarm/$PHONEDEST/$PHONEDEST.pub") UNITDEST=$(cat "./wallets_swarm/$PHONEDEST/$PHONEDEST.unit") - log "__SUB:sms_PAY.sh: PUBKEYDEST found in swarn... $PUBKEYDEST" else # NO, then create NEW Wallet - log "__SUB:sms_PAY.sh: Creating Account for... $PHONEDEST" sms_INIT_ACCOUNT "$PHONEDEST" # Refreshed new values PUBKEYDEST="$PUBKEY" @@ -53,13 +49,11 @@ else fi # Payement -log "./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$VIR" --output="$PUBKEYDEST"" -PAY=$(./shell/timeout.sh -t 30 ./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$VIR" --output="$PUBKEYDEST" --comment="[G1sms+] PAY $AMOUNT $UNIT" -y) +PAY=$(./shell/timeout.sh -t 20 ./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$VIR" --output="$PUBKEYDEST" --comment="[G1sms+] PAY $AMOUNT $UNIT" -y) if [[ "$(echo $PAY | cut -d '|' -f 1)" == "KO" || "$PAY" == "" ]]; then - sms_ERROR "$phone" "PIN : $PAY ? Voyez vous votre code secret: $pin? -NON, Reinitaliser Compte. Envoyer: RAZ -OUI, Bourage Blockchain. Envoyer: S"; - log "__SUB:sms_PAY.sh: Problème de payement avec silkaj : $PAY" + new=$(./shell/checknodes.sh "BAN") + sms_ERROR "$phone" "Problème de payement avec silkaj (changement de serveur $new): $PAY"; + log "__SUB:sms_PAY.sh: Problème de payement avec silkaj $new : $PAY" exit else # OK: Sync g1cents TODO check move_g1cents function and generalize on all silkaj transactions @@ -70,11 +64,11 @@ fi sleep 2 # + G1SMS Commission -log "./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$PERCENT" --output="$NODE_G1PUBKEY"" -COM=$(./shell/timeout.sh -t 30 ./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$PERCENT" --output="$NODE_G1PUBKEY" --comment="[G1sms+] P Commission" -y) -if [[ "$(echo $COM | cut -d '|' -f 1)" == "KO" || "$COM" == "" ]]; then - sms_ERROR "$phone" "Problème de bourrage blockchain : $COM"; - log "__SUB:sms_PAY.sh: Problème de payement avec silkaj : $COM" +COM=$(./shell/timeout.sh -t 20 ./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$PERCENT" --output="$NODE_G1PUBKEY" --comment="[G1sms+] Commission" -y) +if [[ "$(echo $COM | cut -d '|' -f 1)" == "KO" || "$PAY" == "" ]]; then + new=$(./shell/checknodes.sh "BAN") + sms_ERROR "$phone" "Problème de payement avec silkaj (changement de serveur $new): $COM"; + log "__SUB:sms_PAY.sh: Problème de payement avec silkaj $new : $COM" exit else # OK: Sync g1cents