diff --git a/g1sms/G1Anar.png b/g1sms/G1Anar.png new file mode 100644 index 0000000..2105132 Binary files /dev/null and b/g1sms/G1Anar.png differ diff --git a/g1sms/G1Billet_LOVE.png b/g1sms/G1Billet_LOVE.png new file mode 100644 index 0000000..84d3d31 Binary files /dev/null and b/g1sms/G1Billet_LOVE.png differ diff --git a/g1sms/Oeuro.jpg b/g1sms/Oeuro.jpg new file mode 100644 index 0000000..c076e05 Binary files /dev/null and b/g1sms/Oeuro.jpg differ diff --git a/g1sms/OneLove.jpg b/g1sms/OneLove.jpg new file mode 100644 index 0000000..a8d227d Binary files /dev/null and b/g1sms/OneLove.jpg differ diff --git a/g1sms/TAG_fond.jpg b/g1sms/TAG_fond.jpg new file mode 100644 index 0000000..d1fb219 Binary files /dev/null and b/g1sms/TAG_fond.jpg differ diff --git a/g1sms/TAG_fond_G1Tx.jpg b/g1sms/TAG_fond_G1Tx.jpg new file mode 100644 index 0000000..bdd7541 Binary files /dev/null and b/g1sms/TAG_fond_G1Tx.jpg differ diff --git a/g1sms/checknodes.sh b/g1sms/checknodes.sh new file mode 100755 index 0000000..26e6066 --- /dev/null +++ b/g1sms/checknodes.sh @@ -0,0 +1,152 @@ +#!/bin/bash +################################################################################ +# Authors: @jytou (https://git.duniter.org/jytou) +# Modified by Fred (support@qo-op.com) to modifiy silkaj constant with best server +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +# Checks the current block number of nodes.txt (is run in parallel) and output random (from last synchronized) node +# pip3 install duniterpy +# pip3 install silkaj --user + +checkonenode() +{ + # Timeout in seconds for https nodes + httpsTimeout=1 + # Timeout in seconds for http nodes + httpTimeout=1 + + node=$1 + watched=$2 + outfile=$3 + # Curl: -m timeout, -k ignore SSL certificate errors + cur=`echo "$( { curl -m $httpsTimeout -k https://$node/blockchain/current; } 2>&1 )"` + n=$node + if [[ "$cur" != *issuersFrameVar* ]] + then + # It failed in https, maybe try http? + cur=`echo "$( { curl -m $httpTimeout http://$node/blockchain/current; } 2>&1 )"` + if [[ "$cur" == *issuersFrameVar* ]] + then + # Indicate that the node is http + n="$n-(http)" + fi + fi + if [[ "$cur" != *issuersFrameVar* ]] + then + # The node didn't respond on time + cur="ERROR" + else + # The node did respond - grab the block number and hash of the block as key + cur="`echo "$cur"|grep '^ "number": '|awk '{print $2}'|awk -F, '{print $1}'`-`echo "$cur"|grep '^ "hash": '|awk '{print $2}'|awk '{print substr($1,2,13)}'`" + fi + if [[ $watched =~ .*#$node#.* ]] + then + # The node is a watched node, add some bold + n="\e[1m$n\e[0m" + fi + # Put the result into the file + echo "$cur $n">$outfile + # Notify that we're done here + touch $outfile.done +} + +# Temp dir where results are stored +DIR=/tmp/gnodewatch +export DIR +mkdir -p $DIR/chains +########### +# BANNISH DUNITER NODE? +# TODO: silkaj evolution!! Better CLI integration to make! +# Duniter Node is too slow or behave badly, remove it from nodes.txt list +BAN=$1 +if [[ "$BAN" == "BAN" ]]; then + # Get actual Duniter node used by silkaj + SERVER=$(cat ./silkaj/src/constants.py | grep G1_DEFAULT_ENDPOINT | awk '{print $3}' | sed s/\"\,//g | sed s/\"//g) + [[ ! $(grep $SERVER:443 shell/bad.nodes.txt) ]] && echo $SERVER:443 >> shell/bad.nodes.txt + sed -i "/$SERVER:443/d" ./shell/good.nodes.txt + echo "$SERVER:443 IS NOW in ./shell/bad.nodes.txt" +fi + +### nodes.txt EMPTYNESS CARE +NBgood=$(cat ./shell/good.nodes.txt | wc -l) +NBbad=$(cat ./shell/bad.nodes.txt | wc -l) +if [[ $NBgood -le $NBbad ]]; then + echo "" > ./shell/good.nodes.txt + echo "" > ./shell/bad.nodes.txt + # TODO: Each decentralized App must have a source for its confidence to be UP and running and publishing latest code for our concensus behaviour! + echo "___ REFRESH ./shell/nodes.txt from g1.duniter.org:443 ___" + curl -s https://g1.duniter.org/network/peers | jq '.peers[] | .endpoints' | grep BMAS | awk '{print $2,$3}' | sed s/\"//g | sed s/\,//g | sed s/\ /:/g > "./shell/nodes.txt" + echo $(cat "./shell/nodes.txt") +fi +########### +# CONTINUE + +# Grab the nodes we are actively watching - they will be in bold in the final output +watched=`grep -v "#" ./shell/nodes.txt|egrep "\!$"|awk '{print "#" $1 "#"}'` +# All nodes we are watching +nodes=`grep -v "#" ./shell/nodes.txt|awk '{print $1}'` +# The index to generate separate file names +index=0 +# Wipe out the output directory +rm $DIR/*out $DIR/*done $DIR/chains/* $DIR/NODE.* 2>/dev/null + +# Query all nodes in parallel +for node in $nodes +do + checkonenode $node "$watched" $DIR/$index.out & + ((index++)) +done + +# Wait a little for the first files to be created +sleep 1s +# Wait for all the threads to report they are done +while [ `ls $DIR/*done|wc -l` -lt $index ] +do + sleep 1s +done + +# Grab all results +curs=`cat $DIR/*out|sort` +# Extract all forks, excluding all errors +chains="`echo "$curs"|grep -v ERROR|awk '{print $1}'|sort -r|uniq`" + +# Count the number of chains and output most recent consensus to "good.nodes.txt" +nb=0 +for chain in $chains +do + echo "$curs" | egrep "^$chain " | awk '{print $2}' >> $DIR/chains/$nb; + ((nb++)) +done + +longchain=$(ls -S /tmp/gnodewatch/chains/ | head -n 1) +cp /tmp/gnodewatch/chains/$longchain "./shell/good.nodes.txt" + +##################################################################################### +# ASK peers to all good.nodes.txt +#for node in $(cat ./shell/good.nodes.txt); do +# NANODATE=$(date +%s%N); +# DUN="https://$(echo $node| cut -d ":" -f 1)"; +# curl -s -o $DIR/NODE.$NANODATE.$node ${DUN}/network/peers; +#done + +# REFRESH from all known peers NEW nodes.txt +#cat /tmp/gnodewatch/NODE.* | jq '.peers[] | .endpoints' | grep BMAS | awk '{print $2,$3}' | sed s/\"//g | sed s/\,//g | sed s/\ /:/g | sort | uniq > "./shell/nodes.txt" +##################################################################################### + +# Output Random actual best node +# Compare with ./shell/bad.nodes.txt +while [[ "$BAD" == "$DUNITER" ]]; do + DUNITER=$(shuf "./shell/good.nodes.txt" | head -n 1) + BAD=$(grep -Rw "$DUNITER" ./shell/bad.nodes.txt) +done +################# MODIFY silkaj constants.py +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-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 +fi +echo $DUNITER diff --git a/g1sms/cron_CODE.backup.sh b/g1sms/cron_CODE.backup.sh new file mode 100755 index 0000000..a62825c --- /dev/null +++ b/g1sms/cron_CODE.backup.sh @@ -0,0 +1,71 @@ +#!/bin/bash +################################################################################ +# 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 SWARM_CODE_MASTER to IPFS +################################################################################ +source ./shell/init.sh +source ./shell/functions.sh +now=$(date +%Y-%m-%d) + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + +echo "COMMENTAIRES?" +read COMMENT + +# CREATE CURRENT NODE "SWARM_CODE_MASTER" ipns key +if [[ ! -f "/home/$YOU/.ipfs/keystore/SWARM_CODE_MASTER" ]]; then + echo "Vous ne possédez pas la clef SWARM_CODE_MASTER de ce CODE..." + # echo "FORK ? su $YOU -c \"ipfs key gen -t rsa -s 2048 SWARM_CODE_MASTER\"" + echo "Si vous souhaiter participer au CODE, contactez https://g1sms.fr " + echo "Utilisez le script ./G1sms+/install.sh pour installer ou mettre à jour votre noeud" + exit +else + # Only "SWARM_CODE_MASTER" key owner(s) can update & publish this _official _chain + #rm "./$dir/_publishkey.pgp" # TEMP for file name correction... + cat "/home/$YOU/.ipfs/keystore/SWARM_CODE_MASTER" | base64 | gpg -q --output "./$dir/_publishkey.gpg" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "/home/$YOU/.ipfs/keystore/SWARM_CODE_MASTER" +fi + +## Backup $ROOT +dir=$(pwd | awk 'BEGIN { FS = "/" } ; {print $4}') +cd .. + +############################################### +# Create BASIC IPNS _official IPFS HASH _chain +# with iterative update _chain, _nanodate, _zen, _g1cents values +# + _external UID references & _comments lines +########################################################################################### +echo "PLEASE WAIT...." +echo "GIT" > "./$dir/_type" +hop=$(cat "./$dir/_chain") +LASTDU=$(curl -s ${DUNITER}/blockchain/with/ud | jq '.result.blocks[]' | tail -n 1); +[[ $LASTDU != "" ]] && curl -s ${DUNITER}/blockchain/block/${LASTDU} | jq '.dividend' > "./$dir/_DU" || LASTDU=$(cat ./$dir/_DU) +echo "Valeur courante du DU=$(cat ./$dir/_DU) ZEN - CHAIN: $hop" +read + +if [[ ! -f "./$dir/_id" ]]; then echo "SWARM_CODE_MASTER" > "./$dir/_id"; fi +if [[ ! -f "./$dir/_zen" ]]; then echo 0 > "./$dir/_zen"; fi +if [[ ! -f "./$dir/_g1cents" ]]; then echo 0 > "./$dir/_g1cents"; fi +if [[ ! -f "./$dir/_external" ]]; then echo "" > "./$dir/_external"; fi # Used to link to External UniqID +echo $(date +%s%N) > "./$dir/_nanodate" + +echo "$now: $COMMENT" >> "./$dir/_comments" + +# TAR G1sms+ FILES (WITH EXCLUSIONS!!) +tar -cvzf ~/G1sms+_backup_$now.tar.gz --exclude 'g1sms.preoni.*' --exclude 'authfile' --exclude 'init.sh' --exclude '.git' --exclude 'billets' --exclude 'constants.py' --exclude 'TAG' --exclude 'history*' --exclude 'trash' --exclude 'print' --exclude 'wallets' --exclude 'wallets_swarm' --exclude 'g1sms.priv.key' ./$dir + +mkdir -p /tmp/CODE/ && tar xzf ~/G1sms+_backup_$now.tar.gz -C /tmp/CODE/ && rm -f ~/G1sms+_backup_$now.tar.gz + +# PUBLISH IT +hash=$(su $YOU -c "ipfs add -rq /tmp/CODE/ -w | tail -n 1") + +echo $hash > "./$dir/_chain" +publish=$(su $YOU -c "ipfs name publish -k SWARM_CODE_MASTER --quieter /ipfs/${hash}") +echo $publish > "./$dir/_official" + +rm -Rf /tmp/CODE + +echo "_CHAIN: NEW /ipfs/$hash // $hop PUBLISHED with \"SWARM_CODE_MASTER\" key +ipfs get --output=./ /ipns/$publish" diff --git a/g1sms/cron_CODE.upgrade.sh b/g1sms/cron_CODE.upgrade.sh new file mode 100755 index 0000000..ca83152 --- /dev/null +++ b/g1sms/cron_CODE.upgrade.sh @@ -0,0 +1,40 @@ +#!/bin/bash +################################################################################ +# 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 NODE_G1AUTHFILE encryption to IPFS +################################################################################ +## GET LATEST DEV $ROOT +source ./shell/init.sh +source ./shell/functions.sh +now=$(date +%Y-%m-%d) +dir=$(pwd | awk 'BEGIN { FS = "/" } ; {print $4}') +cd .. + +publish=$(cat "./$dir/_official") +maillon=$(cat "./$dir/_chain") +if [[ "$publish" == "" ]]; then lev="ipfs"; hash="$maillon"; else lev="ipns"; hash="$publish"; fi + +su $YOU -c "ipfs get --output=./ /$lev/$hash" + +if [[ -f "./CODE/G1sms+.latest.tgz" ]]; then + echo "TODAY CODE FOUND... UNTAR in ls ./TODAY" + mkdir -p ./TODAY + cd TODAY + tar xvzf ../CODE/G1sms+.latest.tgz + # KEEP LOCAL NODE init.sh + if [[ ! -f "./$dir/shell/init.sh" ]]; then echo "backup restore problem..."; exit; fi + echo "REMOVE DEFAULT INIT..." + rm -f ./$dir/shell/init.sh + + echo "DIFFERENCES ENTRE LES 2 VERSIONS:" + diff ./$dir/ ../$dir/ + + echo "VOULEZ VOUS METTRE A JOUR? Saisissez OUI" + read QUOI + if [[ "$QUOI" == "OUI" ]]; then sudo cp -Rf . ..; else echo "ANNULATION UPDATE"; exit; fi + +fi + + diff --git a/g1sms/cron_G1TAG_REFRESH.sh b/g1sms/cron_G1TAG_REFRESH.sh new file mode 100755 index 0000000..874f45f --- /dev/null +++ b/g1sms/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=$($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 "$NODE_G1AUTHFILE" -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}" + 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 + 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/g1sms/cron_GCHANGE.sh b/g1sms/cron_GCHANGE.sh new file mode 100755 index 0000000..5617834 --- /dev/null +++ b/g1sms/cron_GCHANGE.sh @@ -0,0 +1,49 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +# TODO: SMS Alerte quand une annonce GCHANGE est proche du GeoPoint du téléphone/membre +# +# EXTRAIT LES DERNIERES ANNNONCES +# TODO Requête ES sur la distance directement !!!! @kimamila or http://www.elasticsearchtutorial.com/spatial-search-tutorial.html help? + +CESIUM="https://g1.data.le-sou.org" +echo "Entrez PubKey"; read DESTRIB; +curl -sk ${CESIUM}/user/profile/${DESTRIB} -o /tmp/profile.json +LON=$(cat /tmp/profile.json | jq '._source.geoPoint.lon') +LAT=$(cat /tmp/profile.json | jq '._source.geoPoint.lat') + +if [[ "$LON" != "null" ]]; then +curl -sk -XPOST 'https://data.gchange.fr/market/record/_search?pretty&_source=title' -d ' + { + "size": 100, + "query": { + "bool": { + "filter": [{ + "geo_distance": { + "distance": "100km", + "geoPoint": { + "lat": '$LAT', + "lon": '$LON' + } + } + }] + } + } + }' | jq +else + echo "Aucune coordonnées geoPoint pour $DESTRIB" +fi + +TOTAL=$(curl -s https://data.gchange.fr/market/record/_search | jq .hits.total) +echo "TOTAL ANNONCES GCHANGE: $TOTAL" +chunk=0 +while [[ $chunk -lt $TOTAL ]]; do + for res in $(curl -s https://data.gchange.fr/market/record/_search?from=$chunk | jq .hits.hits[]._id | sed s/\"//g ) do; + echo $res; + # curl -s --create-dirs -o ./gchange/$ID.json -s https://data.gchange.fr/market/record/$ID?_source=category,title,description,issuer,time,creationTime,location,address,city,price,unit,currency,thumbnail._content_type,picturesCount,type,stock,fees,feesCurrency,geoPoint + done + chunk=$((chunk+10)) +done diff --git a/g1sms/cron_IPFS_open_SSH.sh b/g1sms/cron_IPFS_open_SSH.sh new file mode 100755 index 0000000..849e4c4 --- /dev/null +++ b/g1sms/cron_IPFS_open_SSH.sh @@ -0,0 +1,23 @@ +#!/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" +su $YOU -c "ipfs p2p listen /x/http /ip4/127.0.0.1/tcp/80" +su $YOU -c "ipfs p2p listen /x/https /ip4/127.0.0.1/tcp/443" +su $YOU -c "ipfs p2p ls" \ No newline at end of file diff --git a/g1sms/cron_MINUTE.sh b/g1sms/cron_MINUTE.sh new file mode 100755 index 0000000..3eb4e60 --- /dev/null +++ b/g1sms/cron_MINUTE.sh @@ -0,0 +1,108 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +# 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 +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 +source ./shell/init.sh +source ./shell/functions.sh + +timebar=$(date +%H:%M) + +################################################################## +if [[ "$1" == "" ]]; then +################################################################## + echo "It is $timebar in the morning, or in the night? It depends on your day..." + exit +fi +################################################################## + +################################################################## +if [[ "$1" == "PRINT" ]]; then +################################################################## + ################################################################## + # Refresh All peers SWARM Wallets. + ################################################################## + ipfs_swarm_wallets_refresh "SIMPLE" + + ################################################################################ + # 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" + mkdir -p ./wallets/.$IPFSNODEID/PRINT/ + + for qrrtag in ./wallets_swarm/.$IPFSNODEID/PRINT/*.bin; do + 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 "$NODE_G1AUTHFILE" -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)" + brother_ql_print "/tmp/G1Tag.bin" /dev/usb/lp0 + log "__SUB:cron_MINUTE.sh: brother_ql_print - $(date)" + # INFORM PRINT DONE + echo "OK" > ./wallets/.$IPFSNODEID/PRINT/done.$rr + I=$(ipfs_node_wallets_add) + else + lqrrtag=$(echo "${qrrtag}" | sed s/_swarm//g ) + log "__SUB:cron_MINUTE.sh: REMOVE OLD DONE PRINT ${lqrrtag} + ./wallets/.$IPFSNODEID/PRINT/done.$rr" + rm -f "./wallets/.$IPFSNODEID/PRINT/done.$rr" + rm -f "${lqrrtag}" + I=$(ipfs_node_wallets_add) + fi + done + + log "__SUB:cron_MINUTE.sh: REMOVE OLD PRINT MARKED AS DONE" + for scan in ./wallets_swarm/.Qm*/PRINT/done.*; do + lscan=$(echo $scan | sed s/_swarm//g ) + lid=$(echo $scan | cut -d '/' -f 3 | cut -d '.' -f 2 ) + lrr=$(echo $scan | cut -d '/' -f 5 | cut -d '.' -f 2 ) + log "__SUB:cron_MINUTE.sh: REMOVE ./wallets/.$lid/PRINT/$lrr.bin OLD PRINT ${lscan} SENT to $lid ($lrr.bin)" + rm -f ./wallets/.$lid/PRINT/$lrr.bin + rm -f "${lscan}" + I=$(ipfs_node_wallets_add) + done + + rm "/tmp/G1Tag.bin" + rm "/tmp/G1Tag.png" + fi +fi +################################################################## + +################################################################## +if [[ "$1" == "KALKUN" ]]; then +################################################################## + for number in ./wallets/*; do + member="" + phone=$(echo $number | cut -d '/' -f 3); + if [[ -f $number/$phone.uidname ]]; then member=$(cat $number/$phone.uidname); fi + if [[ ! $member ]]; then member=$phone; fi + if [[ $phone && $member ]]; then add_contact $phone $member; log "__SUB:cron_MINUTE.sh: KALKUN add_contact $phone $member"; fi + done +fi +################################################################## + +################################################################## +if [[ "$1" == "TAG" ]]; then +################################################################## + for tag in ./TAG/*; do + echo $tag + done +fi +################################################################## diff --git a/g1sms/cron_VIR.recurrent.sh b/g1sms/cron_VIR.recurrent.sh new file mode 100755 index 0000000..74723f0 --- /dev/null +++ b/g1sms/cron_VIR.recurrent.sh @@ -0,0 +1,94 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +# Effectue les payements récurrents et enlève le vérrou (DESTROY) +# TAKES CARE OF DOING RECURRENT PAYEMENTS EVERY DAY FOR ITS $PHONE G1Wallets +# TODO: Add SMS Alert if G1sms Wallet is low... +source ./shell/init.sh +source ./shell/functions.sh +log "__SUB:cron_VIR.reccurent.sh: START" + +rm -f /tmp/VIR* +echo "" > /tmp/VIR + +TODAY=$(date '+%Y%m%d') +log "__SUB:cron_VIR.reccurent.sh: Searching payements to do for $TODAY" +for file in ./wallets/*/VIREMENTS.gpg ; do + if [[ -f $file ]]; then + log "__SUB:cron_VIR.reccurent.sh: FOUND $file decrypting with Node key" + echo "${GPGPASS}" | gpg -d -q --output "/tmp/VIREMENTS" --yes --pinentry-mode loopback --passphrase-fd 0 "$file" + cat /tmp/VIREMENTS | sort >> /tmp/VIR$TODAY + else + continue + fi +done + +############################################ +if [[ -f /tmp/VIR$TODAY ]]; then +############################################ +while read line + do virement=(${line}); + if [[ ${virement[0]} == ${TODAY} ]]; then + log "__SUB:cron_VIR.reccurent.sh: PAYING !!! ${line}" + PHONE=${virement[2]} + VIR=${virement[3]} + DESTRIB=${virement[4]} + DESTUID=${virement[5]} + REF=${virement[6]} + NB=${virement[7]} + + sms_INIT_ACCOUNT "$PHONE" "NOSMS" + # echo -salt="$PHONE" -password="$PIN" --amount="$VIR" --output="$DESTRIB" --comment="[G1sms+] VIR $REF / $NB" + PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$VIR" --output="$DESTRIB" --comment="[G1sms+] VIR $REF / $NB" -y) + if [[ "$(echo $PAY | cut -d '|' -f 1)" == "KO" ]]; then + new=$(./shell/checknodes.sh "BAN") + sms_ERROR "$PHONE" "Il est survenu un problème avec votre virement. Retour silkaj: $PAY ... $new"; + else + new=$(./shell/checknodes.sh) + sms_SEND "$PHONE" "$TODAY Virement automatique $REF vers $DESTUID : $PAY (Reste $NB)" + cents=$(echo $(bc -l <<< "scale=0; $VIR * 100") | cut -d '.' -f 1) + move_g1cents "$PHONE" "$DESTRIB" "$cents" + fi + log "__SUB:cron_VIR.reccurent.sh: $TODAY VIR DONE.... Rotation Silkaj : $new " + else + virement="" + echo "$(declare -p virement)" + fi +done < /tmp/VIR$TODAY + +# CHECK FOR LAST VIREMENTS AND CLEAN IT? +for virfile in "./wallets/*/VIREMENTS.gpg"; do + phone=$(echo $virfile | cut -d '/' -f 3) + if [[ "$phone" == "*" ]]; then exit; fi + echo "${GPGPASS}" | gpg -d -q --output "/tmp/$phone.VIREMENTS" --yes --pinentry-mode loopback --passphrase-fd 0 "./wallets/$phone/VIREMENTS.gpg" + nv=0; tot=0; + while read ligne + do virs=(${ligne}); + if [[ ${virs[0]} -gt ${TODAY} ]]; then + # Some other payments are to be done in the future + ((nv++)) + tot=$((tot + {virs[3]})) + fi + done < /tmp/$phone.VIREMENTS + + # NO FUTURE PAYMENTS. REMOVE VIREMENTS files + if [[ $nv -eq 0 ]]; then + log "__SUB:cron_VIR.reccurent.sh: Plus AUCUN payement récurrent !!" + sms_SEND "$phone" "Plus AUCUN payement récurrent" + rm -f "./wallets/$phone/VIREMENTS.gpg" + rm -f "./wallets/$phone/VIREMENTS" + I=$(ipfs_node_wallets_add) + else + log "__SUB:cron_VIR.reccurent.sh: Encore $nv payements récurrents à réaliser pour $tot G1" + # TODO Verify Wallet Amount is not too low... To send alert (sms, email) + # cts=$(echo $(bc -l <<< "scale=0; $tot * 100") | cut -d '.' -f 1) + sms_SEND "$phone" "Encore $nv payements récurrents à réaliser pour $tot G1. Approvisionnez votre solde en conséqence..." + fi + rm -f "/tmp/$phone.VIREMENTS" +done +############################################ +fi +############################################ diff --git a/g1sms/diceware-wordlist.txt b/g1sms/diceware-wordlist.txt new file mode 100644 index 0000000..6a49fb9 --- /dev/null +++ b/g1sms/diceware-wordlist.txt @@ -0,0 +1,7776 @@ +11111 minou +11112 yes +11113 love +11114 kraken +11115 matiou +11116 cgeek +11121 g1 +11122 minette +11123 fred +11124 world +11125 bingo +11126 money +11131 duniter +11132 cesium +11133 greg +11134 linux +11135 linus +11136 peps +11141 tim +11142 emma +11143 kitty +11144 cyber +11145 tulipe +11146 moringa +11151 michel +11152 trm +11153 lucien +11154 gaston +11155 moul +11156 elois +11161 vanna +11162 papy +11163 mamy +11164 ludo +11165 fiston +11166 moon +11211 gilles +11212 demo +11213 alex +11214 0 +11215 1 +11216 10 +11221 100 +11222 1000 +11223 100eme +11224 101 +11225 10eme +11226 11 +11231 111 +11232 1111 +11233 11eme +11234 12 +11235 123 +11236 1234 +11241 12eme +11242 13 +11243 13eme +11244 14 +11245 1492 +11246 14eme +11251 15 +11252 1500 +11253 15eme +11254 16 +11255 1600 +11256 16eme +11261 17 +11262 1700 +11263 17eme +11264 18 +11265 1800 +11266 18eme +11311 19 +11312 1900 +11313 1910 +11314 1920 +11315 1925 +11316 1930 +11321 1935 +11322 1940 +11323 1945 +11324 1950 +11325 1955 +11326 1960 +11331 1965 +11332 1970 +11333 1975 +11334 1980 +11335 1985 +11336 1990 +11341 1991 +11342 1992 +11343 1993 +11344 1994 +11345 1995 +11346 1996 +11351 1997 +11352 1998 +11353 1999 +11354 19eme +11355 1er +11356 2 +11361 20 +11362 200 +11363 2000 +11364 2001 +11365 2002 +11366 2003 +11411 2004 +11412 2005 +11413 2006 +11414 2007 +11415 2008 +11416 2009 +11421 2010 +11422 2015 +11423 2020 +11424 2030 +11425 2035 +11426 2040 +11431 2045 +11432 2050 +11433 20eme +11434 21 +11435 21eme +11436 22 +11441 222 +11442 2222 +11443 22eme +11444 23 +11445 234 +11446 2345 +11451 23eme +11452 24 +11453 2468 +11454 24eme +11455 25 +11456 25eme +11461 26 +11462 26eme +11463 27 +11464 27eme +11465 28 +11466 28eme +11511 29 +11512 29eme +11513 2eme +11514 3 +11515 30 +11516 300 +11521 3000 +11522 30eme +11523 31 +11524 31eme +11525 32 +11526 32eme +11531 33 +11532 333 +11533 3333 +11534 33eme +11535 34 +11536 345 +11541 3456 +11542 34eme +11543 35 +11544 35eme +11545 36 +11546 36eme +11551 37 +11552 37eme +11553 38 +11554 38eme +11555 39 +11556 39eme +11561 3eme +11562 4 +11563 40 +11564 400 +11565 4000 +11566 40eme +11611 41 +11612 41eme +11613 42 +11614 42eme +11615 43 +11616 4321 +11621 43eme +11622 44 +11623 444 +11624 4444 +11625 44eme +11626 45 +11631 456 +11632 4567 +11633 45eme +11634 46 +11635 46eme +11636 47 +11641 47eme +11642 48 +11643 48eme +11644 49 +11645 49eme +11646 4eme +11651 5 +11652 50 +11653 500 +11654 5000 +11655 50eme +11656 51 +11661 51eme +11662 52 +11663 52eme +11664 53 +11665 53eme +11666 54 +12111 54eme +12112 55 +12113 555 +12114 5555 +12115 55eme +12116 56 +12121 567 +12122 5678 +12123 56eme +12124 57 +12125 57eme +12126 58 +12131 58eme +12132 59 +12133 59eme +12134 5eme +12135 6 +12136 60 +12141 600 +12142 6000 +12143 60eme +12144 61 +12145 61eme +12146 62 +12151 62eme +12152 63 +12153 63eme +12154 64 +12155 64eme +12156 65 +12161 65eme +12162 66 +12163 666 +12164 6666 +12165 66eme +12166 67 +12211 678 +12212 6789 +12213 67eme +12214 68 +12215 68eme +12216 69 +12221 69eme +12222 6eme +12223 7 +12224 70 +12225 700 +12226 7000 +12231 70eme +12232 71 +12233 71eme +12234 72 +12235 72eme +12236 73 +12241 73eme +12242 74 +12243 74eme +12244 75 +12245 75eme +12246 76 +12251 76eme +12252 77 +12253 777 +12254 7777 +12255 77eme +12256 78 +12261 789 +12262 78eme +12263 79 +12264 79eme +12265 7eme +12266 8 +12311 80 +12312 800 +12313 8000 +12314 80eme +12315 81 +12316 81eme +12321 82 +12322 82eme +12323 83 +12324 83eme +12325 84 +12326 84eme +12331 85 +12332 85eme +12333 86 +12334 86eme +12335 87 +12336 87eme +12341 88 +12342 888 +12343 8888 +12344 88eme +12345 89 +12346 89eme +12351 8eme +12352 9 +12353 90 +12354 900 +12355 9000 +12356 90eme +12361 91 +12362 91eme +12363 92 +12364 92eme +12365 93 +12366 93eme +12411 94 +12412 94eme +12413 95 +12414 95eme +12415 96 +12416 96eme +12421 97 +12422 97eme +12423 98 +12424 9876 +12425 98eme +12426 99 +12431 999 +12432 9999 +12433 99eme +12434 9eme +12435 a +12436 aa +12441 aaa +12442 aaaa +12443 ab +12444 abat +12445 abats +12446 abatte +12451 abc +12452 abject +12453 aboie +12454 abois +12455 aboli +12456 abonda +12461 abonne +12462 abord +12463 aborda +12464 aborde +12465 abords +12466 abouti +12511 aboya +12512 aboyer +12513 abri +12514 abris +12515 abrita +12516 abrite +12521 abroge +12522 abrupt +12523 abruti +12524 absent +12525 abus +12526 abusa +12531 abuse +12532 ac +12533 acajou +12534 accola +12535 accord +12536 accroc +12541 accru +12542 accule +12543 accusa +12544 ace +12545 acerbe +12546 aces +12551 achat +12552 acheta +12553 acheva +12554 acide +12555 acier +12556 acquis +12561 acquit +12562 acte +12563 actes +12564 acteur +12565 actif +12566 ad +12611 adage +12612 adapta +12613 adapte +12614 adepte +12615 adieu +12616 adjura +12621 adjure +12622 admet +12623 admira +12624 admis +12625 admise +12626 admit +12631 adonne +12632 adopta +12633 adopte +12634 adora +12635 adore +12636 adorer +12641 adores +12642 aduler +12643 adulte +12644 advenu +12645 ae +12646 aequo +12651 af +12652 affine +12653 affixe +12654 afflua +12655 afflue +12656 afflux +12661 affola +12662 affole +12663 affres +12664 afin +12665 ag +12666 agace +13111 agaces +13112 agacez +13113 agate +13114 agates +13115 agence +13116 agenda +13121 agent +13122 agi +13123 agile +13124 agio +13125 agios +13126 agiote +13131 agir +13132 agira +13133 agirai +13134 agis +13135 agisse +13136 agit +13141 agita +13142 agite +13143 agiter +13144 agonie +13145 agonir +13146 agrafe +13151 ah +13152 ahuri +13153 ahurir +13154 ai +13155 aida +13156 aidais +13161 aidant +13162 aide +13163 aider +13164 aides +13165 aidez +13166 aidiez +13211 aidons +13212 aie +13213 aient +13214 aies +13215 aigle +13216 aigles +13221 aigre +13222 aigres +13223 aigri +13224 aigrie +13225 aigris +13226 aigrit +13231 aigu +13232 aigus +13233 ail +13234 aile +13235 ailes +13236 aille +13241 aima +13242 aimant +13243 aime +13244 aimer +13245 aimera +13246 aimes +13251 aimez +13252 aine +13253 aines +13254 ainsi +13255 air +13256 aire +13261 airer +13262 aires +13263 airs +13264 aise +13265 aises +13266 ait +13311 aj +13312 ajonc +13313 ajout +13314 ajouta +13315 ajuste +13316 ak +13321 al +13322 alarme +13323 album +13324 alcool +13325 alerta +13326 alevin +13331 alezan +13332 alfa +13333 alfas +13334 algue +13335 algues +13336 alias +13341 alibi +13342 aliter +13343 alla +13344 aller +13345 allez +13346 allia +13351 allie +13352 allier +13353 allies +13354 alloue +13355 allume +13356 allure +13361 aloi +13362 alors +13363 alpaga +13364 alpage +13365 alpin +13366 alpins +13411 alter +13412 alto +13413 altos +13414 alu +13415 aluner +13416 am +13421 amant +13422 amants +13423 amarre +13424 amas +13425 amble +13426 ambler +13431 ambre +13432 ambrer +13433 amen +13434 amena +13435 amenda +13436 amener +13441 amer +13442 amers +13443 ameuta +13444 ami +13445 amibe +13446 amical +13451 amie +13452 amies +13453 amis +13454 amont +13455 amour +13456 amours +13461 amphi +13462 ample +13463 amples +13464 ampli +13465 amputa +13466 amurer +13511 amusa +13512 amuse +13513 amuser +13514 amusez +13515 an +13516 anche +13521 anches +13522 ancra +13523 ancre +13524 ancrer +13525 ancres +13526 ancrez +13531 and +13532 ange +13533 anges +13534 angine +13535 angle +13536 angles +13541 angora +13542 anima +13543 anime +13544 animez +13545 anis +13546 aniser +13551 anneau +13552 annexa +13553 annota +13554 annote +13555 anode +13556 anodes +13561 ans +13562 anse +13563 anses +13564 antan +13565 antre +13566 antres +13611 anus +13612 ao +13613 aorte +13614 ap +13615 aphte +13616 aplani +13621 apparu +13622 appas +13623 appel +13624 appels +13625 apport +13626 apposa +13631 appose +13632 appris +13633 appui +13634 appuie +13635 appuis +13636 apte +13641 aptes +13642 apura +13643 apure +13644 apurer +13645 apures +13646 aq +13651 ar +13652 arabe +13653 araser +13654 arbora +13655 arbre +13656 arc +13661 arcade +13662 arche +13663 archet +13664 arcs +13665 ardu +13666 ardue +14111 ardues +14112 ardus +14113 are +14114 ares +14115 argile +14116 argot +14121 argots +14122 aria +14123 arias +14124 aride +14125 arides +14126 arma +14131 armais +14132 armait +14133 armant +14134 arme +14135 arment +14136 armer +14141 armes +14142 armez +14143 arpent +14144 arrime +14145 arriva +14146 arrive +14151 arroge +14152 arrosa +14153 art +14154 arts +14155 as +14156 asile +14161 aspect +14162 aspic +14163 assagi +14164 assez +14165 assis +14166 assit +14211 assoie +14212 assume +14213 astral +14214 astre +14215 astres +14216 astuce +14221 at +14222 atlas +14223 atoll +14224 atome +14225 atomes +14226 atone +14231 atones +14232 atours +14233 atout +14234 atouts +14235 attire +14236 au +14241 aube +14242 aubier +14243 aucun +14244 audit +14245 audits +14246 auge +14251 auges +14252 augura +14253 aune +14254 aunes +14255 auquel +14256 aura +14261 aurai +14262 auras +14263 aurez +14264 auriez +14265 aussi +14266 autel +14311 auteur +14312 auto +14313 autos +14314 autre +14315 auvent +14316 aux +14321 av +14322 avais +14323 avait +14324 aval +14325 avala +14326 avale +14331 avales +14332 avalez +14333 avals +14334 avance +14335 avant +14336 avants +14341 avare +14342 avarie +14343 avatar +14344 avec +14345 avenir +14346 avenu +14351 avenue +14352 avenus +14353 averse +14354 aveu +14355 aveuli +14356 aveux +14361 avez +14362 avide +14363 avides +14364 aviez +14365 avili +14366 avilir +14411 avilis +14412 avilit +14413 avion +14414 avions +14415 avis +14416 avisa +14421 avise +14422 avises +14423 aviso +14424 avisos +14425 aviva +14426 avive +14431 avives +14432 avoir +14433 avoirs +14434 avons +14435 avoua +14436 avoue +14441 avouer +14442 avouez +14443 avril +14444 aw +14445 ax +14446 axa +14451 axais +14452 axait +14453 axant +14454 axe +14455 axent +14456 axer +14461 axera +14462 axes +14463 axez +14464 axiez +14465 axiome +14466 axons +14511 ay +14512 ayant +14513 ayez +14514 ayons +14515 az +14516 azote +14521 azur +14522 azyme +14523 b +14524 ba +14525 baba +14526 babas +14531 babil +14532 bac +14533 bacon +14534 bacs +14535 badaud +14536 badge +14541 badges +14542 badin +14543 badine +14544 bafoua +14545 bagne +14546 bagou +14551 bague +14552 baguer +14553 bahut +14554 bahuts +14555 bai +14556 baie +14561 baies +14562 baigna +14563 bail +14564 bain +14565 bains +14566 bais +14611 baiser +14612 baissa +14613 baisse +14614 bal +14615 balade +14616 balai +14621 balais +14622 balaya +14623 balisa +14624 balise +14625 balle +14626 baller +14631 balles +14632 bals +14633 balsa +14634 bambin +14635 bambou +14636 ban +14641 banal +14642 banals +14643 banane +14644 banc +14645 bancal +14646 banco +14651 bancos +14652 bancs +14653 bande +14654 bandes +14655 bang +14656 bangs +14661 banjo +14662 banni +14663 bannit +14664 banque +14665 bans +14666 bantou +15111 baquet +15112 bar +15113 barbe +15114 barbet +15115 barbu +15116 barda +15121 bardas +15122 barde +15123 bardes +15124 barge +15125 baril +15126 barman +15131 baron +15132 barra +15133 barre +15134 barrez +15135 barrir +15136 bars +15141 bas +15142 basa +15143 basait +15144 basane +15145 base +15146 basent +15151 baser +15152 bases +15153 basez +15154 basque +15155 basse +15156 bassin +15161 basson +15162 bat +15163 bateau +15164 bats +15165 batte +15166 battez +15211 battit +15212 battre +15213 battu +15214 battus +15215 baudet +15216 bauge +15221 baume +15222 baux +15223 bava +15224 bavait +15225 bave +15226 baver +15231 baves +15232 bavez +15233 baviez +15234 bayer +15235 bazar +15236 bb +15241 bbb +15242 bbbb +15243 bc +15244 bcd +15245 bd +15246 be +15251 beau +15252 beaux +15253 bec +15254 becs +15255 becter +15256 beige +15261 beiges +15262 bel +15263 belge +15264 belle +15265 belles +15266 belon +15311 belons +15312 benne +15313 bennes +15314 berce +15315 bercer +15316 bercez +15321 berge +15322 berger +15323 berlue +15324 berna +15325 berne +15326 bernez +15331 besoin +15332 bette +15333 bettes +15334 bf +15335 bg +15336 bh +15341 bi +15342 biais +15343 biaisa +15344 bible +15345 biceps +15346 biche +15351 bicher +15352 bidet +15353 bidon +15354 bien +15355 biens +15356 biffa +15361 biffe +15362 bigler +15363 bijou +15364 bilan +15365 bilans +15366 bile +15411 biler +15412 bille +15413 biller +15414 billes +15415 billet +15416 billot +15421 binage +15422 biner +15423 bis +15424 bise +15425 biseau +15426 biser +15431 bises +15432 bison +15433 bisons +15434 bistro +15435 bit +15436 bits +15441 bitume +15442 bj +15443 bk +15444 bl +15445 blague +15446 blanc +15451 blancs +15452 blaser +15453 blesse +15454 blet +15455 blets +15456 bleu +15461 bleue +15462 bleui +15463 bleuie +15464 bleuir +15465 bleus +15466 blinde +15511 bloc +15512 blocs +15513 blond +15514 bloque +15515 blouse +15516 blues +15521 bluff +15522 bm +15523 bn +15524 bo +15525 boa +15526 boas +15531 bob +15532 bobine +15533 bobs +15534 bocal +15535 bocaux +15536 bock +15541 bocks +15542 boeuf +15543 bogue +15544 boira +15545 boirai +15546 boire +15551 boirez +15552 bois +15553 boit +15554 boita +15555 boite +15556 boitez +15561 boive +15562 boives +15563 bol +15564 bolet +15565 bolide +15566 bols +15611 bombe +15612 bomber +15613 bombes +15614 bon +15615 bonbon +15616 bond +15621 bonde +15622 bondes +15623 bondi +15624 bondir +15625 bondit +15626 bonds +15631 boni +15632 bonis +15633 bonne +15634 bonnes +15635 bons +15636 bonus +15641 bonze +15642 bonzes +15643 boom +15644 boots +15645 bord +15646 borda +15651 borde +15652 border +15653 bordes +15654 bordez +15655 bords +15656 borgne +15661 borna +15662 borne +15663 borner +15664 bornez +15665 bosse +15666 bosser +16111 bosses +16112 bossez +16113 bossu +16114 bot +16115 bots +16116 botte +16121 bouc +16122 boucs +16123 bouda +16124 boude +16125 bouder +16126 boudes +16131 boudez +16132 boudin +16133 boue +16134 boues +16135 bouffe +16136 bouffi +16141 bouge +16142 bouges +16143 bougre +16144 boule +16145 boulon +16146 boumer +16151 bourg +16152 bourre +16153 bous +16154 bouse +16155 bout +16156 bouter +16161 bouts +16162 bovin +16163 bovins +16164 box +16165 boxa +16166 boxe +16211 boxer +16212 boxera +16213 boxers +16214 boxes +16215 boxeur +16216 boxez +16221 boxiez +16222 boxons +16223 boy +16224 boyau +16225 boys +16226 bp +16231 bq +16232 br +16233 brada +16234 brade +16235 brader +16236 brades +16241 bradez +16242 braire +16243 braise +16244 brame +16245 bramer +16246 branle +16251 braque +16252 bras +16253 brassa +16254 brava +16255 brave +16256 braver +16261 braves +16262 bravez +16263 bravo +16264 bravos +16265 break +16266 breaks +16311 brebis +16312 bref +16313 brefs +16314 brevet +16315 bric +16316 brick +16321 bricks +16322 brida +16323 bride +16324 bridez +16325 bridge +16326 brie +16331 brilla +16332 brille +16333 brima +16334 brime +16335 brimer +16336 brimes +16341 brin +16342 brins +16343 brio +16344 brique +16345 bris +16346 brisa +16351 brise +16352 brises +16353 broc +16354 brocs +16355 broda +16356 brode +16361 broie +16362 bronza +16363 bronze +16364 brou +16365 brouta +16366 broya +16411 bru +16412 bruine +16413 bruir +16414 bruire +16415 bruit +16416 bruits +16421 brume +16422 brumer +16423 brun +16424 brune +16425 bruni +16426 brunie +16431 brunir +16432 brunit +16433 bruns +16434 brus +16435 brut +16436 brute +16441 bruts +16442 bs +16443 bt +16444 bu +16445 buccal +16446 budget +16451 bue +16452 bues +16453 buffle +16454 buggy +16455 buggys +16456 buis +16461 bulbe +16462 bulle +16463 bulles +16464 bure +16465 burent +16466 burin +16511 bus +16512 busard +16513 buse +16514 buses +16515 buste +16516 but +16521 buta +16522 butait +16523 butane +16524 butant +16525 bute +16526 buter +16531 butera +16532 butes +16533 buteur +16534 butez +16535 butiez +16536 butin +16541 butins +16542 butor +16543 butors +16544 buts +16545 butte +16546 buvait +16551 buvard +16552 buveur +16553 buvez +16554 bv +16555 bw +16556 bx +16561 by +16562 bz +16563 c +16564 ca +16565 caban +16566 cabas +16611 cabine +16612 cabra +16613 cabre +16614 cabres +16615 cabrez +16616 cabri +16621 cacao +16622 cacha +16623 cache +16624 cacher +16625 caches +16626 cachet +16631 cachou +16632 cactus +16633 caddie +16634 cade +16635 cades +16636 cadet +16641 cadi +16642 cadis +16643 cadra +16644 cadre +16645 cadrer +16646 cadrez +16651 caduc +16652 cafard +16653 cage +16654 cages +16655 cagibi +16656 cahot +16661 cahota +16662 cahote +16663 cahots +16664 cajou +16665 cajous +16666 cajun +21111 cake +21112 cakes +21113 cal +21114 cala +21115 calage +21116 calais +21121 calant +21122 calcul +21123 cale +21124 calent +21125 caler +21126 cales +21131 calez +21132 calma +21133 calmar +21134 calme +21135 calot +21136 cals +21141 calva +21142 came +21143 camer +21144 cames +21145 camion +21146 camp +21151 campa +21152 campe +21153 camper +21154 campes +21155 campez +21156 camps +21161 camus +21162 canal +21163 canard +21164 canari +21165 cancer +21166 candi +21211 candir +21212 cane +21213 caner +21214 canes +21215 canif +21216 canna +21221 canne +21222 canon +21223 canot +21224 canots +21225 canule +21226 cap +21231 cape +21232 caper +21233 capes +21234 capot +21235 capots +21236 caps +21241 capta +21242 capte +21243 capter +21244 captes +21245 captez +21246 captif +21251 caquer +21252 car +21253 carafe +21254 carat +21255 carcan +21256 carde +21261 cargo +21262 cargos +21263 caria +21264 carie +21265 caries +21266 carmin +21311 carnet +21312 carpe +21313 carre +21314 carrer +21315 carres +21316 cars +21321 carte +21322 carter +21323 cartes +21324 carton +21325 cas +21326 casa +21331 casait +21332 casant +21333 case +21334 casent +21335 caser +21336 casera +21341 cases +21342 casez +21343 casino +21344 cassa +21345 casse +21346 casser +21351 cassez +21352 cassis +21353 caste +21354 catch +21355 catir +21356 caudal +21361 causa +21362 cause +21363 causer +21364 causes +21365 cavale +21366 cave +21411 caveau +21412 caver +21413 caves +21414 caviar +21415 cb +21416 cc +21421 ccc +21422 cccc +21423 cd +21424 cde +21425 ce +21426 ceci +21431 cedex +21432 ceint +21433 ceints +21434 cela +21435 celer +21436 celle +21441 celui +21442 cens +21443 cent +21444 centra +21445 cents +21446 cep +21451 ceps +21452 cercla +21453 cerf +21454 cerfs +21455 cerna +21456 cerne +21461 cerner +21462 cernez +21463 ces +21464 cessa +21465 cesse +21466 cesser +21511 cet +21512 cette +21513 ceux +21514 cf +21515 cg +21516 ch +21521 chacun +21522 chah +21523 chahs +21524 chai +21525 chair +21526 chaire +21531 chais +21532 champ +21533 chance +21534 change +21535 chant +21536 chanta +21541 chaos +21542 chape +21543 char +21544 charma +21545 chars +21546 charte +21551 chas +21552 chat +21553 chaton +21554 chats +21555 chaud +21556 chauds +21561 chaume +21562 chauve +21563 chaux +21564 check +21565 chef +21566 chefs +21611 chelem +21612 chemin +21613 chenet +21614 chenil +21615 cher +21616 chers +21621 chevet +21622 chez +21623 chic +21624 chien +21625 chiens +21626 chier +21631 chiot +21632 chiper +21633 chips +21634 chique +21635 chlore +21636 choc +21641 chocs +21642 choeur +21643 choie +21644 choies +21645 choir +21646 choisi +21651 choix +21652 chope +21653 chopes +21654 choqua +21655 choque +21656 choral +21661 chose +21662 choses +21663 chou +21664 choux +21665 choya +21666 choyer +22111 chrome +22112 chromo +22113 chrono +22114 chut +22115 chuta +22116 chute +22121 chutes +22122 chutez +22123 ci +22124 cible +22125 cibler +22126 cibles +22131 cidre +22132 cidres +22133 ciel +22134 cierge +22135 cieux +22136 cil +22141 ciller +22142 cils +22143 cime +22144 cimes +22145 cinq +22146 cintra +22151 cintre +22152 cira +22153 cirais +22154 cirant +22155 cire +22156 cirent +22161 cirer +22162 cirera +22163 cires +22164 cireur +22165 cirez +22166 cirrus +22211 cita +22212 cite +22213 citer +22214 cites +22215 citez +22216 citron +22221 civet +22222 civets +22223 civil +22224 cj +22225 ck +22226 cl +22231 claie +22232 clair +22233 clairs +22234 clam +22235 clama +22236 clame +22241 clamer +22242 clames +22243 clamez +22244 clams +22245 clan +22246 clans +22251 clapir +22252 claque +22253 classe +22254 claver +22255 clef +22256 clefs +22261 clerc +22262 clercs +22263 climat +22264 clin +22265 clins +22266 clip +22311 clips +22312 clique +22313 cloche +22314 clone +22315 clora +22316 cloras +22321 clore +22322 clos +22323 close +22324 clou +22325 cloua +22326 cloue +22331 cloues +22332 clous +22333 clown +22334 club +22335 clubs +22336 cm +22341 cn +22342 co +22343 cobol +22344 cobra +22345 cocha +22346 coche +22351 cochez +22352 cochon +22353 coco +22354 cocon +22355 cocons +22356 coda +22361 codage +22362 codais +22363 codait +22364 codas +22365 code +22366 codent +22411 coder +22412 codera +22413 codes +22414 codeur +22415 codez +22416 codons +22421 coeur +22422 coeurs +22423 cogna +22424 cognac +22425 cogne +22426 cogner +22431 cognez +22432 cohue +22433 coi +22434 coiffe +22435 coin +22436 coince +22441 coing +22442 coings +22443 coins +22444 cois +22445 coite +22446 coites +22451 coke +22452 col +22453 cola +22454 colin +22455 colis +22456 colite +22461 colla +22462 colle +22463 colles +22464 collez +22465 colon +22466 colore +22511 cols +22512 colt +22513 colts +22514 colza +22515 coma +22516 comas +22521 combat +22522 combla +22523 comme +22524 commet +22525 compta +22526 compte +22531 comte +22532 comtes +22533 con +22534 conclu +22535 confia +22536 confus +22541 conne +22542 connes +22543 connu +22544 connue +22545 connut +22546 conque +22551 cons +22552 conte +22553 contes +22554 contre +22555 convie +22556 convoi +22561 copia +22562 copie +22563 copier +22564 copies +22565 copine +22566 coq +22611 coqs +22612 coque +22613 coquet +22614 cor +22615 corail +22616 corde +22621 corder +22622 corne +22623 corner +22624 cornet +22625 cornu +22626 cornus +22631 coron +22632 corps +22633 cors +22634 corsa +22635 corse +22636 corses +22641 corset +22642 corsez +22643 cortex +22644 coryza +22645 cosmos +22646 cosse +22651 cossu +22652 cossue +22653 cossus +22654 cosy +22655 cosys +22656 cota +22661 cotais +22662 cote +22663 coteau +22664 cotent +22665 coter +22666 cotes +23111 cotez +23112 cotir +23113 coton +23114 cotons +23115 cotte +23116 cou +23121 couac +23122 couche +23123 coucou +23124 coud +23125 coude +23126 couder +23131 couds +23132 coula +23133 coule +23134 coulez +23135 coup +23136 coupa +23141 coupe +23142 coupez +23143 coupla +23144 coups +23145 cour +23146 courbe +23151 coure +23152 coures +23153 courre +23154 cours +23155 course +23156 court +23161 couru +23162 courue +23163 courus +23164 cous +23165 couse +23166 couses +23211 cousez +23212 cousu +23213 cousus +23214 coutil +23215 couva +23216 couve +23221 couvez +23222 couvre +23223 cp +23224 cpt +23225 cq +23226 cr +23231 crabe +23232 crack +23233 cracks +23234 craie +23235 craies +23236 crains +23241 crampe +23242 cran +23243 crans +23244 crasse +23245 crawl +23246 crayon +23251 credo +23252 creuse +23253 creux +23254 creva +23255 crevez +23256 cri +23261 cria +23262 criais +23263 criait +23264 criard +23265 crible +23266 cric +23311 cricri +23312 crics +23313 crie +23314 crier +23315 criera +23316 cries +23321 crieur +23322 criez +23323 crime +23324 crimes +23325 crin +23326 crins +23331 crions +23332 cris +23333 crise +23334 crissa +23335 croc +23336 crocs +23341 croie +23342 croira +23343 crois +23344 croisa +23345 croise +23346 croit +23351 croix +23352 croqua +23353 croque +23354 cross +23355 crosse +23356 crotte +23361 croula +23362 cru +23363 crue +23364 cruel +23365 cruels +23366 crues +23411 crus +23412 crut +23413 cs +23414 ct +23415 cu +23416 cuba +23421 cubait +23422 cubant +23423 cube +23424 cuber +23425 cubera +23426 cubes +23431 cuir +23432 cuira +23433 cuirai +23434 cuire +23435 cuirs +23436 cuis +23441 cuise +23442 cuises +23443 cuisez +23444 cuisse +23445 cuit +23446 cuite +23451 cuiter +23452 cuits +23453 cuivre +23454 cul +23455 culer +23456 culot +23461 culs +23462 culte +23463 cultes +23464 cumin +23465 cumul +23466 cumula +23511 cupide +23512 cupule +23513 curage +23514 cure +23515 curer +23516 cures +23521 curry +23522 cuti +23523 cuva +23524 cuvait +23525 cuve +23526 cuver +23531 cuves +23532 cuvez +23533 cuviez +23534 cv +23535 cw +23536 cx +23541 cy +23542 cycle +23543 cycles +23544 cygne +23545 cygnes +23546 cz +23551 d +23552 da +23553 dada +23554 dadas +23555 dague +23556 dagues +23561 daigne +23562 daim +23563 daims +23564 dais +23565 dalla +23566 dalle +23611 dame +23612 damer +23613 dames +23614 damna +23615 damne +23616 damnez +23621 dan +23622 dandy +23623 dandys +23624 dans +23625 dansa +23626 danse +23631 danser +23632 dansez +23633 darce +23634 darces +23635 dard +23636 darder +23641 dards +23642 darne +23643 darnes +23644 darse +23645 dartre +23646 data +23651 datait +23652 datant +23653 date +23654 dater +23655 dates +23656 dateur +23661 datez +23662 datif +23663 dation +23664 datte +23665 dattes +23666 daube +24111 dauber +24112 db +24113 dc +24114 dd +24115 ddd +24116 dddd +24121 de +24122 debout +24123 dedans +24124 def +24125 delta +24126 demain +24131 demi +24132 demie +24133 demis +24134 denier +24135 dense +24136 denses +24141 dent +24142 dents +24143 derby +24144 derbys +24145 derme +24146 des +24151 design +24152 dessus +24153 destin +24154 dette +24155 deuil +24156 deuils +24161 deux +24162 devais +24163 devait +24164 devant +24165 devenu +24166 devez +24211 devin +24212 devina +24213 devins +24214 devint +24215 devis +24216 devons +24221 devra +24222 devras +24223 devrez +24224 df +24225 dg +24226 dh +24231 di +24232 diapo +24233 dicta +24234 dicte +24235 dictez +24236 dicton +24241 diesel +24242 dieu +24243 dieux +24244 diffus +24245 digit +24246 digits +24251 digne +24252 digue +24253 dilua +24254 dilue +24255 dinde +24256 dindon +24261 dinghy +24262 dingo +24263 dingos +24264 diode +24265 dira +24266 dirai +24311 dirait +24312 diras +24313 dire +24314 direct +24315 dires +24316 direz +24321 dirige +24322 dirons +24323 dis +24324 discal +24325 disco +24326 dise +24331 disert +24332 dises +24333 disiez +24334 dispos +24335 dit +24336 dite +24341 dites +24342 dito +24343 dits +24344 divan +24345 divin +24346 divisa +24351 divise +24352 dix +24353 dj +24354 dk +24355 dl +24356 dm +24361 dn +24362 do +24363 docile +24364 dock +24365 docks +24366 docte +24411 doctes +24412 dodu +24413 dodue +24414 dodues +24415 dodus +24416 dogme +24421 dogmes +24422 dogue +24423 dogues +24424 doigt +24425 doigts +24426 dois +24431 doit +24432 doive +24433 doives +24434 dollar +24435 dolmen +24436 domina +24441 domine +24442 dompta +24443 don +24444 donc +24445 donjon +24446 donna +24451 donne +24452 donnes +24453 donnez +24454 dons +24455 dont +24456 dopa +24461 dopait +24462 dopant +24463 dope +24464 doper +24465 dopes +24466 dopez +24511 dopons +24512 dora +24513 dorade +24514 dorait +24515 dorant +24516 dore +24521 dorent +24522 dorer +24523 doreur +24524 dorme +24525 dormi +24526 dormir +24531 dors +24532 dort +24533 dorure +24534 dos +24535 dosa +24536 dosage +24541 dosais +24542 dosant +24543 dose +24544 dosent +24545 doser +24546 doses +24551 dosez +24552 dosons +24553 dot +24554 dota +24555 dote +24556 dotent +24561 doter +24562 dotes +24563 dotez +24564 dotons +24565 dots +24566 douane +24611 douant +24612 doubla +24613 double +24614 douce +24615 douces +24616 douche +24621 douer +24622 douta +24623 doute +24624 doutez +24625 douve +24626 douves +24631 doux +24632 douze +24633 doyen +24634 dp +24635 dq +24636 dr +24641 dragon +24642 drain +24643 draine +24644 drame +24645 drap +24646 drapa +24651 drape +24652 drapes +24653 drapez +24654 draps +24655 dressa +24656 dresse +24661 drille +24662 drisse +24663 driver +24664 drogua +24665 droit +24666 drop +25111 drops +25112 dru +25113 drue +25114 drues +25115 drus +25116 ds +25121 dt +25122 du +25123 duc +25124 ducal +25125 ducale +25126 ducs +25131 due +25132 duel +25133 duels +25134 dues +25135 dune +25136 dunes +25141 duo +25142 duos +25143 dupa +25144 dupais +25145 dupait +25146 dupant +25151 dupe +25152 duper +25153 dupera +25154 dupes +25155 dupez +25156 dupons +25161 dur +25162 dura +25163 durait +25164 durci +25165 durcit +25166 dure +25211 durent +25212 durer +25213 durera +25214 dures +25215 durs +25216 dus +25221 dut +25222 duvet +25223 duvets +25224 dv +25225 dw +25226 dx +25231 dy +25232 dynamo +25233 dz +25234 e +25235 ea +25236 eau +25241 eaux +25242 eb +25243 ec +25244 ed +25245 ee +25246 eee +25251 eeee +25252 ef +25253 efface +25254 effara +25255 effare +25256 effet +25261 effets +25262 effila +25263 effile +25264 effort +25265 effroi +25266 efg +25311 eg +25312 ego +25313 eh +25314 ei +25315 eider +25316 ej +25321 ek +25322 el +25323 elfe +25324 elfes +25325 elle +25326 elles +25331 em +25332 embuer +25333 emmena +25334 empan +25335 empara +25336 empli +25341 emplis +25342 emplit +25343 empois +25344 en +25345 encan +25346 encas +25351 encore +25352 encra +25353 encre +25354 encres +25355 encrez +25356 endos +25361 enduis +25362 endure +25363 enfer +25364 enfila +25365 enfile +25366 enfin +25411 enfla +25412 enfle +25413 enfler +25414 enflez +25415 enfoui +25416 enfui +25421 enfuit +25422 enfuma +25423 engin +25424 enivre +25425 enjeu +25426 enjeux +25431 enlisa +25432 ennemi +25433 ennui +25434 ennuie +25435 ennuis +25436 ennuya +25441 enquit +25442 enraya +25443 enraye +25444 enroba +25445 ensuit +25446 entama +25451 entame +25452 enter +25453 entier +25454 entra +25455 entre +25456 entrez +25461 envia +25462 envie +25463 envier +25464 envies +25465 enviez +25466 envoi +25511 envois +25512 envol +25513 envola +25514 envols +25515 enzyme +25516 eo +25521 ep +25522 eq +25523 er +25524 erg +25525 ergot +25526 ergots +25531 ergs +25532 ermite +25533 erra +25534 erre +25535 errer +25536 errera +25541 erres +25542 errez +25543 erriez +25544 ersatz +25545 es +25546 escale +25551 esche +25552 escher +25553 esches +25554 espion +25555 espoir +25556 essai +25561 essaim +25562 essaya +25563 esse +25564 esses +25565 essor +25566 essore +25611 essuya +25612 est +25613 ester +25614 estima +25615 estoc +25616 et +25621 ethnie +25622 eu +25623 eue +25624 eues +25625 euh +25626 eurent +25631 euro +25632 euros +25633 eus +25634 eut +25635 eux +25636 ev +25641 ew +25642 ex +25643 exact +25644 exacte +25645 exacts +25646 exalte +25651 exauce +25652 excite +25653 exclu +25654 excusa +25655 excuse +25656 exerce +25661 exhala +25662 exige +25663 exiger +25664 exiges +25665 exigu +25666 exil +26111 exila +26112 exile +26113 exiles +26114 exils +26115 exista +26116 exocet +26121 exode +26122 expert +26123 expia +26124 expie +26125 expier +26126 expira +26131 expire +26132 exposa +26133 expose +26134 extra +26135 exulte +26136 ey +26141 ez +26142 f +26143 fa +26144 fable +26145 fabula +26146 face +26151 faces +26152 facial +26153 facto +26154 factor +26155 fade +26156 fades +26161 fadeur +26162 fagot +26163 faible +26164 faibli +26165 faim +26166 faire +26211 fais +26212 fait +26213 faite +26214 faites +26215 faits +26216 fakir +26221 fallu +26222 falot +26223 falote +26224 falots +26225 fameux +26226 fan +26231 fana +26232 fanal +26233 fane +26234 fanent +26235 faner +26236 fanes +26241 fange +26242 fanion +26243 fanon +26244 fanons +26245 fans +26246 faon +26251 faons +26252 far +26253 faraud +26254 farce +26255 farces +26256 farci +26261 farcir +26262 fard +26263 farda +26264 farde +26265 fardes +26266 fardez +26311 fards +26312 farine +26313 fars +26314 fart +26315 farts +26316 fasse +26321 fasses +26322 faste +26323 fat +26324 fatal +26325 fats +26326 fauche +26331 faudra +26332 faune +26333 faut +26334 faute +26335 fautes +26336 fauve +26341 faux +26342 fax +26343 faxer +26344 fb +26345 fc +26346 fco +26351 fd +26352 fe +26353 feins +26354 feint +26355 feinte +26356 feints +26361 femme +26362 fend +26363 fende +26364 fendes +26365 fendra +26366 fendre +26411 fends +26412 fendu +26413 fente +26414 fer +26415 fera +26416 ferai +26421 ferais +26422 feras +26423 ferez +26424 feriez +26425 ferma +26426 ferme +26431 fermer +26432 fermez +26433 feront +26434 ferrer +26435 fers +26436 fesse +26441 fesser +26442 festif +26443 feu +26444 feue +26445 feues +26446 feutra +26451 feux +26452 fez +26453 ff +26454 fff +26455 ffff +26456 fg +26461 fgh +26462 fh +26463 fi +26464 fia +26465 fiacre +26466 fiais +26511 fiait +26512 fiance +26513 fiant +26514 fiasco +26515 fibre +26516 fibres +26521 fibule +26522 ficela +26523 ficha +26524 fiche +26525 fichez +26526 fichu +26531 fictif +26532 fie +26533 fief +26534 fiefs +26535 fiel +26536 fient +26541 fier +26542 fiera +26543 fierai +26544 fieras +26545 fiers +26546 fies +26551 fiez +26552 fifre +26553 fige +26554 figea +26555 figer +26556 figes +26561 figez +26562 figue +26563 figura +26564 fiiez +26565 fiions +26566 fil +26611 fila +26612 filait +26613 filant +26614 file +26615 filent +26616 filer +26621 filera +26622 files +26623 filet +26624 filets +26625 filez +26626 filin +26631 fille +26632 filles +26633 film +26634 filma +26635 filme +26636 filmes +26641 films +26642 filon +26643 filons +26644 filou +26645 fils +26646 filtra +26651 filtre +26652 fin +26653 final +26654 finals +26655 finaud +26656 fine +26661 fines +26662 fini +26663 finie +26664 finies +26665 finir +26666 finira +31111 finis +31112 finit +31113 fins +31114 fiole +31115 fioles +31116 fions +31121 firent +31122 firme +31123 fisc +31124 fiscal +31125 fiscs +31126 fit +31131 fixa +31132 fixais +31133 fixait +31134 fixant +31135 fixe +31136 fixer +31141 fixes +31142 fixez +31143 fj +31144 fjord +31145 fjords +31146 fk +31151 fl +31152 flacon +31153 flair +31154 flairs +31155 flambe +31156 flamme +31161 flan +31162 flanc +31163 flans +31164 flapi +31165 flash +31166 flatta +31211 flatte +31212 flegme +31213 flemme +31214 fleur +31215 fleura +31216 fleuri +31221 flippe +31222 flirt +31223 flirts +31224 flood +31225 flore +31226 flores +31231 flot +31232 flots +31233 flou +31234 floua +31235 floue +31236 flous +31241 fluer +31242 fluet +31243 fluide +31244 fluor +31245 fluors +31246 flux +31251 fm +31252 fn +31253 fo +31254 foc +31255 focal +31256 focale +31261 focs +31262 focus +31263 foehn +31264 foetus +31265 foi +31266 foie +31311 foies +31312 foin +31313 foins +31314 foire +31315 fois +31316 foison +31321 fol +31322 folie +31323 folies +31324 folio +31325 folios +31326 foliot +31331 folle +31332 fonce +31333 foncer +31334 fonces +31335 foncez +31336 fond +31341 fonda +31342 fonde +31343 fonder +31344 fondez +31345 fonds +31346 fondu +31351 fondue +31352 fondus +31353 font +31354 fonte +31355 fontes +31356 fonts +31361 foot +31362 for +31363 fora +31364 forage +31365 forain +31366 forais +31411 forait +31412 force +31413 forces +31414 fore +31415 forent +31416 forer +31421 forera +31422 fores +31423 foret +31424 forez +31425 forge +31426 forger +31431 forges +31432 forgez +31433 foriez +31434 forma +31435 forme +31436 formel +31441 former +31442 formes +31443 formez +31444 formol +31445 fors +31446 fort +31451 forte +31452 forts +31453 forum +31454 forums +31455 fosse +31456 fosses +31461 fou +31462 fouet +31463 fouine +31464 fouir +31465 foula +31466 foule +31511 foules +31512 four +31513 fours +31514 fous +31515 foutez +31516 foutu +31521 foutus +31522 fox +31523 foyer +31524 foyers +31525 fp +31526 fq +31531 fr +31532 frac +31533 fracas +31534 fracs +31535 frai +31536 fraie +31541 frais +31542 fraise +31543 franc +31544 fraser +31545 fraya +31546 fraye +31551 frayer +31552 frayes +31553 frayez +31554 frein +31555 freina +31556 freins +31561 fret +31562 frets +31563 friche +31564 frigo +31565 frigos +31566 frime +31611 frimer +31612 fripa +31613 fripe +31614 friper +31615 frira +31616 frirai +31621 friras +31622 frire +31623 frirez +31624 fris +31625 frisa +31626 frise +31631 frisez +31632 frit +31633 frite +31634 frits +31635 froc +31636 froid +31641 front +31642 fronts +31643 frugal +31644 fruit +31645 fs +31646 ft +31651 fu +31652 fucus +31653 fuel +31654 fuels +31655 fugace +31656 fugue +31661 fuguer +31662 fui +31663 fuie +31664 fuies +31665 fuir +31666 fuira +32111 fuirai +32112 fuirez +32113 fuis +32114 fuit +32115 fuite +32116 fuites +32121 full +32122 fulls +32123 fuma +32124 fumage +32125 fumait +32126 fume +32131 fumer +32132 fumes +32133 fumet +32134 fumets +32135 fumeur +32136 fumez +32141 fumier +32142 fumoir +32143 fur +32144 furet +32145 furets +32146 fureur +32151 furia +32152 furie +32153 furies +32154 fusa +32155 fusain +32156 fusait +32161 fuse +32162 fuseau +32163 fuser +32164 fusera +32165 fusil +32166 fut +32211 futur +32212 fuyais +32213 fuyant +32214 fuyez +32215 fuyiez +32216 fuyons +32221 fv +32222 fw +32223 fx +32224 fy +32225 fz +32226 g +32231 ga +32232 gaffe +32233 gaffer +32234 gaffes +32235 gag +32236 gage +32241 gagea +32242 gager +32243 gages +32244 gagez +32245 gagna +32246 gagne +32251 gagner +32252 gagnes +32253 gagnez +32254 gags +32255 gai +32256 gaie +32261 gaies +32262 gain +32263 gaine +32264 gainer +32265 gaines +32266 gains +32311 gais +32312 gala +32313 galant +32314 galas +32315 galbe +32316 galber +32321 galbes +32322 gale +32323 gales +32324 galet +32325 galeux +32326 galon +32331 galop +32332 gamba +32333 gambas +32334 gamet +32335 gamets +32336 gamin +32341 gamine +32342 gamins +32343 gamme +32344 gang +32345 gangs +32346 gangue +32351 ganse +32352 ganses +32353 gant +32354 gants +32355 gara +32356 garant +32361 garce +32362 garda +32363 garde +32364 gardes +32365 gardez +32366 gare +32411 garer +32412 garera +32413 gares +32414 garez +32415 gariez +32416 garni +32421 garnie +32422 garnit +32423 gars +32424 gaule +32425 gava +32426 gavais +32431 gavant +32432 gave +32433 gaver +32434 gaves +32435 gavez +32436 gavial +32441 gaviez +32442 gaz +32443 gazage +32444 gaze +32445 gazer +32446 gazes +32451 gazeux +32452 gazon +32453 gazons +32454 gb +32455 gc +32456 gd +32461 ge +32462 geai +32463 geais +32464 geigne +32465 geins +32466 geint +32511 gel +32512 gela +32513 gelais +32514 gelait +32515 gelant +32516 geler +32521 gelez +32522 geliez +32523 gelons +32524 gels +32525 gemme +32526 gemmer +32531 gendre +32532 genet +32533 genets +32534 genou +32535 genre +32536 genres +32541 gens +32542 gentes +32543 gentil +32544 gerbe +32545 gerber +32546 gerbes +32551 gerce +32552 germa +32553 germe +32554 geste +32555 gf +32556 gg +32561 ggg +32562 gggg +32563 gh +32564 ghi +32565 gi +32566 gibbon +32611 gibet +32612 gibets +32613 gicla +32614 gicle +32615 gifla +32616 gifle +32621 gifler +32622 giflez +32623 gigot +32624 gigue +32625 gilet +32626 gilets +32631 gin +32632 gins +32633 girl +32634 girls +32635 giron +32636 gisait +32641 gisant +32642 gitan +32643 gitane +32644 gitans +32645 givra +32646 givre +32651 givrer +32652 gj +32653 gk +32654 gl +32655 glabre +32656 glace +32661 glacer +32662 glaces +32663 glana +32664 gland +32665 glane +32666 glaner +33111 glanes +33112 glas +33113 glatir +33114 globe +33115 globes +33116 gloire +33121 glose +33122 gloser +33123 gloses +33124 glu +33125 gluant +33126 glus +33131 gm +33132 gn +33133 gnome +33134 gnon +33135 gnons +33136 gnou +33141 gnous +33142 go +33143 goal +33144 goals +33145 goba +33146 gobait +33151 gobe +33152 gober +33153 gobes +33154 gobez +33155 gobons +33156 goder +33161 godet +33162 goitre +33163 golden +33164 golf +33165 golfe +33166 golfs +33211 gomma +33212 gomme +33213 gommez +33214 gond +33215 gonds +33216 gonfle +33221 gong +33222 gongs +33223 goret +33224 gorge +33225 gorger +33226 gorges +33231 gosier +33232 gosse +33233 gouge +33234 gouges +33235 goulot +33236 goulu +33241 goulue +33242 gourd +33243 gourde +33244 gourds +33245 gourou +33246 gousse +33251 gp +33252 gq +33253 gr +33254 gracia +33255 grade +33256 gradin +33261 grain +33262 grains +33263 grand +33264 grandi +33265 grappe +33266 gras +33311 grasse +33312 gratin +33313 gratis +33314 gratta +33315 grava +33316 grave +33321 graver +33322 graves +33323 gravi +33324 gravie +33325 gravis +33326 gravit +33331 grec +33332 grecs +33333 greffe +33334 grenat +33335 grener +33336 grenu +33341 greva +33342 grevez +33343 grief +33344 griefs +33345 griffe +33346 griffu +33351 gril +33352 grill +33353 grils +33354 grimer +33355 grimpa +33356 grimpe +33361 griot +33362 grippe +33363 gris +33364 grisa +33365 grisbi +33366 grise +33411 grises +33412 grive +33413 grives +33414 grog +33415 grogna +33416 grogs +33421 groin +33422 gronda +33423 groom +33424 gros +33425 grosse +33426 grotte +33431 groupa +33432 grouse +33433 gruau +33434 gruaux +33435 grue +33436 grues +33441 gruger +33442 grume +33443 gs +33444 gt +33445 gu +33446 guano +33451 guerre +33452 guet +33453 guette +33454 gueuse +33455 gui +33456 guida +33461 guide +33462 guider +33463 guidez +33464 guigne +33465 guimpe +33466 guis +33511 guise +33512 gv +33513 gw +33514 gx +33515 gy +33516 gypse +33521 gz +33522 h +33523 ha +33524 habile +33525 habit +33526 habita +33531 habits +33532 hacha +33533 hache +33534 hachez +33535 hachis +33536 hacker +33541 haie +33542 haies +33543 haine +33544 hais +33545 hait +33546 haler +33551 haleta +33552 hall +33553 halle +33554 halls +33555 halo +33556 halos +33561 halte +33562 haltes +33563 hamac +33564 hampe +33565 hampes +33566 hanta +33611 hante +33612 hantez +33613 happa +33614 happe +33615 haras +33616 harder +33621 hardi +33622 harem +33623 harems +33624 hargne +33625 haro +33626 haros +33631 harpe +33632 harpes +33633 harpie +33634 hase +33635 hases +33636 haussa +33641 hausse +33642 haut +33643 haute +33644 hautes +33645 hauts +33646 havane +33651 haver +33652 havre +33653 havres +33654 hayon +33655 hayons +33656 hb +33661 hc +33662 hd +33663 he +33664 heaume +33665 hein +33666 hennir +34111 herbe +34112 herber +34113 herbes +34114 hernie +34115 herse +34116 hertz +34121 heur +34122 heure +34123 heures +34124 heurt +34125 heurta +34126 heurts +34131 hf +34132 hg +34133 hh +34134 hhh +34135 hhhh +34136 hi +34141 hiatus +34142 hibou +34143 hic +34144 hideux +34145 hie +34146 hier +34151 hies +34152 hij +34153 hilare +34154 hindi +34155 hippie +34156 hippy +34161 hissa +34162 hisse +34163 hisser +34164 hiver +34165 hj +34166 hk +34211 hl +34212 hm +34213 hn +34214 ho +34215 hobby +34216 hocha +34221 hoche +34222 hocher +34223 hochet +34224 hockey +34225 homard +34226 home +34231 homme +34232 honni +34233 honnie +34234 honnis +34235 honora +34236 honte +34241 horde +34242 horion +34243 hors +34244 hostie +34245 hotte +34246 hotter +34251 houe +34252 houer +34253 houes +34254 houle +34255 hourra +34256 housse +34261 houx +34262 hp +34263 hq +34264 hr +34265 hs +34266 ht +34311 hu +34312 hua +34313 huais +34314 huait +34315 huant +34316 huche +34321 hucher +34322 hue +34323 huent +34324 huer +34325 huera +34326 huerez +34331 hues +34332 huez +34333 hui +34334 huiez +34335 huila +34336 huile +34341 huilez +34342 huis +34343 huit +34344 huma +34345 humait +34346 humant +34351 hume +34352 hument +34353 humer +34354 humes +34355 humeur +34356 humez +34361 humons +34362 humour +34363 humus +34364 hune +34365 hunes +34366 huons +34411 huotte +34412 huppe +34413 hurla +34414 hurle +34415 hurrah +34416 hutte +34421 huttes +34422 hv +34423 hw +34424 hx +34425 hy +34426 hydre +34431 hydres +34432 hymen +34433 hymens +34434 hymne +34435 hz +34436 i +34441 ia +34442 iambe +34443 ib +34444 ibis +34445 ic +34446 ici +34451 ictus +34452 id +34453 idem +34454 ides +34455 idiome +34456 idiot +34461 idoine +34462 idole +34463 idoles +34464 idylle +34465 ie +34466 if +34511 ifs +34512 ig +34513 igloo +34514 igloos +34515 igname +34516 ignare +34521 ignore +34522 iguane +34523 ih +34524 ii +34525 iii +34526 iiii +34531 ij +34532 ijk +34533 ik +34534 il +34535 ilote +34536 ils +34541 im +34542 image +34543 images +34544 imbibe +34545 imbu +34546 imbue +34551 imbus +34552 imita +34553 imite +34554 imitez +34555 imper +34556 impie +34561 impies +34562 impoli +34563 impur +34564 impure +34565 impurs +34566 imputa +34611 impute +34612 in +34613 inapte +34614 inca +34615 incas +34616 incite +34621 index +34622 indexa +34623 indexe +34624 indu +34625 indue +34626 induis +34631 indus +34632 inepte +34633 inerte +34634 infime +34635 infini +34636 influa +34641 influx +34642 infusa +34643 infuse +34644 ingrat +34645 inhuma +34646 inique +34651 initie +34652 injure +34653 innove +34654 inox +34655 input +34656 instar +34661 insu +34662 inter +34663 intima +34664 invita +34665 invite +34666 io +35111 iode +35112 ioder +35113 iodes +35114 ion +35115 ions +35116 iota +35121 iouler +35122 ip +35123 iq +35124 ir +35125 ira +35126 irai +35131 irais +35132 irait +35133 iras +35134 irez +35135 iriez +35136 irions +35141 iris +35142 ironie +35143 irons +35144 iront +35145 irrita +35146 irrite +35151 is +35152 isard +35153 isba +35154 isbas +35155 islam +35156 isola +35161 isole +35162 isoler +35163 issu +35164 issue +35165 issus +35166 it +35211 item +35212 iu +35213 iv +35214 ivraie +35215 ivre +35216 ivres +35221 iw +35222 ix +35223 iy +35224 iz +35225 j +35226 ja +35231 jabler +35232 jabot +35233 jabots +35234 jade +35235 jades +35236 jadis +35241 jaguar +35242 jais +35243 jalon +35244 jalons +35245 jambe +35246 jambes +35251 jambon +35252 jante +35253 jantes +35254 jardin +35255 jarre +35256 jarret +35261 jars +35262 jas +35263 jasa +35264 jasait +35265 jasant +35266 jase +35311 jasent +35312 jaser +35313 jasera +35314 jasper +35315 jatte +35316 jattes +35321 jauge +35322 jauger +35323 jauges +35324 jaugez +35325 jaune +35326 jaunes +35331 jauni +35332 jaunis +35333 java +35334 javas +35335 jazz +35336 jb +35341 jc +35342 jd +35343 je +35344 jean +35345 jeans +35346 jerez +35351 jerk +35352 jerker +35353 jet +35354 jeta +35355 jeter +35356 jetez +35361 jetiez +35362 jeton +35363 jetons +35364 jets +35365 jette +35366 jeu +35411 jeudi +35412 jeun +35413 jeune +35414 jeunes +35415 jeux +35416 jf +35421 jg +35422 jh +35423 ji +35424 jj +35425 jjj +35426 jjjj +35431 jk +35432 jkl +35433 jl +35434 jm +35435 jn +35436 jo +35441 job +35442 jobard +35443 jobs +35444 jockey +35445 joie +35446 joies +35451 joins +35452 joint +35453 jointe +35454 joker +35455 jokers +35456 joli +35461 jolie +35462 jolis +35463 jonc +35464 joncs +35465 jongla +35466 jongle +35511 jonque +35512 joua +35513 jouait +35514 joual +35515 jouant +35516 joue +35521 jouer +35522 jouera +35523 joues +35524 jouet +35525 joueur +35526 jouez +35531 joug +35532 jougs +35533 joui +35534 jouiez +35535 jouir +35536 jouira +35541 jouis +35542 jouit +35543 joule +35544 joules +35545 jour +35546 jours +35551 joute +35552 joutes +35553 jouxte +35554 joyau +35555 joyaux +35556 joyeux +35561 jp +35562 jq +35563 jr +35564 js +35565 jt +35566 ju +35611 jubila +35612 jubile +35613 judas +35614 judo +35615 judoka +35616 juge +35621 jugea +35622 juger +35623 juges +35624 jugez +35625 jugiez +35626 juif +35631 juifs +35632 juin +35633 juive +35634 juives +35635 jumeau +35636 jumela +35641 junior +35642 junte +35643 juntes +35644 jupe +35645 jupes +35646 jupon +35651 jura +35652 jurais +35653 jurait +35654 jurant +35655 jure +35656 jurer +35661 jures +35662 jurez +35663 juron +35664 jurons +35665 jury +35666 jurys +36111 jus +36112 jusque +36113 juste +36114 jute +36115 juter +36116 juteux +36121 jv +36122 jw +36123 jx +36124 jy +36125 jz +36126 k +36131 ka +36132 kaki +36133 kakis +36134 kaolin +36135 kapok +36136 karma +36141 kart +36142 karts +36143 kasher +36144 kayak +36145 kb +36146 kc +36151 kd +36152 ke +36153 kf +36154 kg +36155 kh +36156 ki +36161 kif +36162 kilo +36163 kilos +36164 kilt +36165 kilts +36166 kimono +36211 kir +36212 kit +36213 kits +36214 kiwi +36215 kiwis +36216 kj +36221 kk +36222 kkk +36223 kkkk +36224 kl +36225 klm +36226 km +36231 kn +36232 ko +36233 kola +36234 kolas +36235 kp +36236 kq +36241 kr +36242 krach +36243 kraft +36244 krak +36245 kraks +36246 ks +36251 kt +36252 ku +36253 kv +36254 kvas +36255 kw +36256 kwas +36261 kx +36262 ky +36263 kyste +36264 kystes +36265 kz +36266 l +36311 la +36312 label +36313 labial +36314 lac +36315 lace +36316 lacer +36321 laces +36322 lacet +36323 lacets +36324 lacez +36325 laciez +36326 lacis +36331 lacs +36332 lad +36333 ladre +36334 ladres +36335 lads +36336 lagon +36341 lagons +36342 lagune +36343 laid +36344 laide +36345 laids +36346 laie +36351 laies +36352 laine +36353 lainer +36354 laisse +36355 lait +36356 laits +36361 lama +36362 lamas +36363 lame +36364 lamer +36365 lames +36366 lamine +36411 lampe +36412 lance +36413 lances +36414 land +36415 landau +36416 lande +36421 landes +36422 lange +36423 langue +36424 laper +36425 lapin +36426 lapine +36431 lapis +36432 laps +36433 lapsus +36434 laque +36435 lard +36436 larder +36441 lardon +36442 large +36443 largua +36444 largue +36445 larme +36446 larmes +36451 larron +36452 larve +36453 las +36454 lascar +36455 lascif +36456 laser +36461 lassa +36462 lasse +36463 lasses +36464 lassez +36465 lasso +36466 lassos +36511 latent +36512 latex +36513 latin +36514 latine +36515 latins +36516 latte +36521 lattes +36522 lava +36523 lavage +36524 lavait +36525 lave +36526 laver +36531 laves +36532 lavez +36533 lavis +36534 lavoir +36535 layer +36536 lazzi +36541 lb +36542 lc +36543 ld +36544 le +36545 leader +36546 ledit +36551 legs +36552 lent +36553 lente +36554 lents +36555 les +36556 lest +36561 lesta +36562 leste +36563 lestes +36564 lests +36565 let +36566 lettre +36611 leur +36612 leurs +36613 leva +36614 levage +36615 levain +36616 levais +36621 levait +36622 levant +36623 lever +36624 levers +36625 levez +36626 levons +36631 levure +36632 lf +36633 lg +36634 lh +36635 li +36636 lia +36641 liais +36642 liait +36643 liane +36644 lianes +36645 liant +36646 liants +36651 libre +36652 libres +36653 lice +36654 licher +36655 licite +36656 licol +36661 licols +36662 licou +36663 licous +36664 lie +36665 lied +36666 lieds +41111 lien +41112 liens +41113 lient +41114 lier +41115 liera +41116 lierai +41121 lies +41122 lieu +41123 lieue +41124 lieuse +41125 lieux +41126 liez +41131 lift +41132 lifter +41133 lifts +41134 ligne +41135 ligner +41136 ligote +41141 ligua +41142 ligue +41143 liguer +41144 liguez +41145 liiez +41146 liions +41151 lilas +41152 lima +41153 limais +41154 limait +41155 lime +41156 limer +41161 limera +41162 limes +41163 limez +41164 limier +41165 limite +41166 limoge +41211 limon +41212 limons +41213 lin +41214 linge +41215 lino +41216 linos +41221 lion +41222 lionne +41223 lions +41224 lipide +41225 lippe +41226 lippu +41231 lippue +41232 lira +41233 lirai +41234 liras +41235 lire +41236 lires +41241 lirez +41242 liriez +41243 lis +41244 lisait +41245 lisant +41246 lise +41251 lisent +41252 lises +41253 lisez +41254 lissa +41255 lisse +41256 lisses +41261 lista +41262 liste +41263 listez +41264 lit +41265 liter +41266 litre +41311 litres +41312 lits +41313 livra +41314 livre +41315 livrer +41316 lj +41321 lk +41322 ll +41323 lll +41324 llll +41325 lm +41326 lmn +41331 ln +41332 lo +41333 lob +41334 lobby +41335 lobe +41336 lober +41341 lobes +41342 lobs +41343 local +41344 locale +41345 locher +41346 loden +41351 loess +41352 lofer +41353 loge +41354 logea +41355 logent +41356 loger +41361 loges +41362 logeur +41363 logez +41364 logiez +41365 logis +41366 logo +41411 logos +41412 loi +41413 loin +41414 loir +41415 loirs +41416 lois +41421 long +41422 longe +41423 longer +41424 longes +41425 longs +41426 lopin +41431 lopins +41432 loque +41433 lors +41434 lot +41435 lote +41436 lotes +41441 loti +41442 lotie +41443 loties +41444 lotir +41445 lotira +41446 lotis +41451 lotit +41452 loto +41453 lots +41454 lotte +41455 lottes +41456 lotus +41461 loua +41462 louage +41463 loue +41464 louer +41465 loues +41466 loueur +41511 louez +41512 louiez +41513 loup +41514 loupe +41515 louper +41516 loups +41521 lourd +41522 lourds +41523 loutre +41524 louve +41525 louves +41526 lover +41531 loyal +41532 loyale +41533 loyaux +41534 loyer +41535 loyers +41536 lp +41541 lq +41542 lr +41543 ls +41544 lt +41545 lu +41546 lubie +41551 lucide +41552 lucre +41553 lue +41554 lues +41555 lueur +41556 luge +41561 luger +41562 luges +41563 lui +41564 luira +41565 luire +41566 luise +41611 luit +41612 lump +41613 lumps +41614 lunch +41615 lundi +41616 lune +41621 lunes +41622 lupin +41623 lupins +41624 lurent +41625 luron +41626 lurons +41631 lus +41632 lustra +41633 lustre +41634 lut +41635 luter +41636 luth +41641 luths +41642 lutin +41643 lutta +41644 lutte +41645 lutter +41646 lux +41651 luxa +41652 luxant +41653 luxe +41654 luxent +41655 luxer +41656 luxes +41661 luxez +41662 luxiez +41663 luxure +41664 lv +41665 lw +41666 lx +42111 ly +42112 lynx +42113 lyre +42114 lyres +42115 lys +42116 lyse +42121 lyses +42122 lz +42123 m +42124 ma +42125 mach +42126 madone +42131 mafia +42132 mage +42133 mages +42134 magie +42135 magma +42136 magner +42141 magot +42142 mai +42143 maille +42144 main +42145 mains +42146 maint +42151 mainte +42152 maints +42153 maire +42154 maires +42155 mairie +42156 mais +42161 major +42162 mal +42163 malaxa +42164 malice +42165 malin +42166 malins +42211 malle +42212 malles +42213 malt +42214 malter +42215 malus +42216 maman +42221 mamans +42222 man +42223 manche +42224 manda +42225 mandat +42226 mande +42231 mander +42232 mandez +42233 manga +42234 mange +42235 manger +42236 mania +42241 manie +42242 maniez +42243 manioc +42244 manne +42245 manqua +42246 mante +42251 mantes +42252 manuel +42253 maquer +42254 maquis +42255 marbre +42256 marc +42261 marche +42262 mardi +42263 mare +42264 mares +42265 marge +42266 marges +42311 mari +42312 maria +42313 marie +42314 maries +42315 mariez +42316 marin +42321 marina +42322 marine +42323 maris +42324 mark +42325 marks +42326 marne +42331 marner +42332 marque +42333 marra +42334 marre +42335 marres +42336 marri +42341 marrie +42342 marris +42343 mars +42344 marte +42345 martel +42346 martes +42351 martre +42352 martyr +42353 mas +42354 masqua +42355 massa +42356 masse +42361 masser +42362 massue +42363 mastic +42364 mastoc +42365 masure +42366 mat +42411 match +42412 matchs +42413 mate +42414 mater +42415 mates +42416 math +42421 maths +42422 matin +42423 matir +42424 mats +42425 mature +42426 mauve +42431 mauves +42432 mauvis +42433 maux +42434 maxima +42435 maya +42436 mayas +42441 mazer +42442 mazout +42443 mb +42444 mc +42445 md +42446 me +42451 melon +42452 men +42453 mena +42454 menace +42455 menait +42456 menant +42461 mendia +42462 mendie +42463 mener +42464 meneur +42465 menez +42466 menons +42511 mens +42512 ment +42513 mente +42514 mentez +42515 menti +42516 menton +42521 mentor +42522 menu +42523 menue +42524 menues +42525 menuet +42526 menus +42531 mer +42532 merci +42533 mercis +42534 merder +42535 merise +42536 merlan +42541 merle +42542 merlu +42543 mers +42544 mes +42545 mess +42546 messe +42551 messes +42552 messie +42553 met +42554 mets +42555 mette +42556 mettes +42561 meubla +42562 meugle +42563 meule +42564 meure +42565 meurs +42566 meurt +42611 meus +42612 meut +42613 meute +42614 meutes +42615 meuve +42616 mf +42621 mg +42622 mh +42623 mi +42624 miasme +42625 mica +42626 micas +42631 miche +42632 miches +42633 micmac +42634 micro +42635 micron +42636 micros +42641 midi +42642 midis +42643 mie +42644 miel +42645 miels +42646 mien +42651 mienne +42652 miens +42653 mieux +42654 mignon +42655 migre +42656 migrer +42661 migrez +42662 mijota +42663 mil +42664 milan +42665 mile +42666 miles +43111 milite +43112 mille +43113 milles +43114 millet +43115 mima +43116 mimait +43121 mimant +43122 mime +43123 mimer +43124 mimes +43125 mimez +43126 min +43131 mina +43132 minais +43133 mince +43134 minci +43135 mincie +43136 mincis +43141 mine +43142 minent +43143 miner +43144 mines +43145 minet +43146 mineur +43151 minez +43152 minime +43153 minois +43154 minons +43155 minora +43156 minore +43161 minuit +43162 minus +43163 mioche +43164 mira +43165 mirage +43166 mirait +43211 mirant +43212 mire +43213 mirent +43214 mirer +43215 mirera +43216 mires +43221 mirez +43222 miroir +43223 mis +43224 misa +43225 misait +43226 misant +43231 mise +43232 miser +43233 misera +43234 mises +43235 misez +43236 misiez +43241 misons +43242 miss +43243 missel +43244 misses +43245 mit +43246 mita +43251 mite +43252 mitent +43253 miter +43254 mitera +43255 mites +43256 mitre +43261 mitron +43262 mixa +43263 mixage +43264 mixais +43265 mixait +43266 mixant +43311 mixe +43312 mixent +43313 mixer +43314 mixes +43315 mixez +43316 mixte +43321 mixtes +43322 mj +43323 mk +43324 ml +43325 mm +43326 mmm +43331 mmmm +43332 mn +43333 mno +43334 mo +43335 moche +43336 modal +43341 modale +43342 mode +43343 modela +43344 modem +43345 modes +43346 modula +43351 modus +43352 moelle +43353 moi +43354 moine +43355 moines +43356 moins +43361 moire +43362 mois +43363 moisi +43364 moisie +43365 moisir +43366 moite +43411 moites +43412 moitir +43413 moka +43414 mokas +43415 mol +43416 molle +43421 mollet +43422 molli +43423 moment +43424 momie +43425 momies +43426 mon +43431 monde +43432 monder +43433 mondes +43434 mont +43435 monta +43436 monte +43441 montra +43442 monts +43443 moqua +43444 moque +43445 moquez +43446 moral +43451 mord +43452 morde +43453 mordre +43454 mords +43455 mordu +43456 mordue +43461 morgue +43462 morne +43463 mornes +43464 mors +43465 morse +43466 morses +43511 mort +43512 morte +43513 mortel +43514 morts +43515 morue +43516 morve +43521 mot +43522 motel +43523 motif +43524 motiva +43525 moto +43526 motos +43531 mots +43532 motte +43533 mou +43534 moucha +43535 mouche +43536 moud +43541 moudra +43542 moudre +43543 mouds +43544 moue +43545 moues +43546 moula +43551 moule +43552 moulin +43553 moulu +43554 mourez +43555 mouron +43556 mourut +43561 mous +43562 moussa +43563 mousse +43564 mouvez +43565 moyen +43566 moyeu +43611 moyeux +43612 mp +43613 mq +43614 mr +43615 ms +43616 mt +43621 mu +43622 mua +43623 muais +43624 muait +43625 muant +43626 mue +43631 muent +43632 muer +43633 muera +43634 muerez +43635 mues +43636 muet +43641 muets +43642 muez +43643 mufle +43644 mugi +43645 mugir +43646 mugis +43651 mugit +43652 muiez +43653 mule +43654 mules +43655 mulet +43656 mulot +43661 muni +43662 munie +43663 munir +43664 munira +43665 munis +43666 munit +44111 muons +44112 mur +44113 mura +44114 murais +44115 mural +44116 murale +44121 murals +44122 mure +44123 murent +44124 murer +44125 mures +44126 muret +44131 murez +44132 muriez +44133 murons +44134 murs +44135 mus +44136 musc +44141 muscat +44142 muscle +44143 muscs +44144 muse +44145 museau +44146 muser +44151 muses +44152 musser +44153 muta +44154 mutant +44155 mute +44156 muter +44161 mutera +44162 mutes +44163 mutez +44164 mutiez +44165 mutile +44166 mutin +44211 mutina +44212 mv +44213 mw +44214 mx +44215 my +44216 myope +44221 myrrhe +44222 mythe +44223 mz +44224 n +44225 na +44226 nabab +44231 nababs +44232 nabot +44233 nabote +44234 nacre +44235 nacres +44236 nage +44241 nagea +44242 nager +44243 nages +44244 nagez +44245 nain +44246 naine +44251 nains +44252 nais +44253 naja +44254 najas +44255 nanan +44256 nanti +44261 nantir +44262 nantis +44263 nantit +44264 napalm +44265 nappe +44266 naquit +44311 narra +44312 narre +44313 narres +44314 narrez +44315 naseau +44316 nasse +44321 natal +44322 natale +44323 natif +44324 nation +44325 natte +44326 natter +44331 nattes +44332 naval +44333 navals +44334 navet +44335 navets +44336 navire +44341 navra +44342 navre +44343 navrer +44344 navrez +44345 nazi +44346 nazie +44351 nazies +44352 nazis +44353 nb +44354 nc +44355 nd +44356 ne +44361 nectar +44362 nef +44363 nefs +44364 negro +44365 neige +44366 neiger +44411 nenni +44412 nerf +44413 nerfs +44414 nervi +44415 nervis +44416 net +44421 nets +44422 nette +44423 nettes +44424 neuf +44425 neufs +44426 neutre +44431 neuve +44432 neveu +44433 nez +44434 nf +44435 ng +44436 nh +44441 ni +44442 nia +44443 niable +44444 niais +44445 niait +44446 niant +44451 nicha +44452 niche +44453 nicher +44454 niches +44455 nid +44456 nids +44461 nie +44462 nient +44463 nier +44464 niera +44465 nierai +44466 nies +44511 niez +44512 nigaud +44513 niiez +44514 nimber +44515 ninja +44516 ninjas +44521 nions +44522 nippe +44523 nipper +44524 nique +44525 niveau +44526 nivela +44531 nj +44532 nk +44533 nl +44534 nm +44535 nn +44536 nnn +44541 nnnn +44542 no +44543 noble +44544 nobles +44545 noce +44546 noces +44551 nocif +44552 nocifs +44553 nodule +44554 noeud +44555 noie +44556 noiera +44561 noies +44562 noir +44563 noire +44564 noires +44565 noirs +44566 noise +44611 noises +44612 noix +44613 nom +44614 nomade +44615 nomma +44616 nomme +44621 nommer +44622 noms +44623 non +44624 nonce +44625 nonne +44626 nop +44631 nord +44632 normal +44633 norme +44634 normes +44635 nos +44636 nota +44641 notais +44642 notait +44643 note +44644 notent +44645 noter +44646 notera +44651 notes +44652 notez +44653 notice +44654 notons +44655 notre +44656 notule +44661 noua +44662 noue +44663 nouer +44664 nouera +44665 noues +44666 noueux +45111 nouez +45112 nouiez +45113 nouons +45114 nourri +45115 nous +45116 nover +45121 noya +45122 noyau +45123 noyaux +45124 noyer +45125 noyez +45126 noyiez +45131 noyons +45132 np +45133 nq +45134 nr +45135 ns +45136 nt +45141 nu +45142 nuage +45143 nubile +45144 nue +45145 nues +45146 nui +45151 nuira +45152 nuiras +45153 nuire +45154 nuirez +45155 nuis +45156 nuise +45161 nuit +45162 nuits +45163 nul +45164 nulle +45165 nulles +45166 nuls +45211 nuque +45212 nurse +45213 nus +45214 nv +45215 nw +45216 nx +45221 ny +45222 nylon +45223 nz +45224 o +45225 oa +45226 oasis +45231 ob +45232 obier +45233 objet +45234 objets +45235 oblige +45236 obole +45241 obture +45242 obtus +45243 obus +45244 obvier +45245 oc +45246 occupe +45251 ocre +45252 ocrer +45253 ocres +45254 octal +45255 octane +45256 octave +45261 octet +45262 octroi +45263 od +45264 ode +45265 odes +45266 odeur +45311 odieux +45312 oe +45313 oeil +45314 oeuf +45315 oeufs +45316 oeuvre +45321 of +45322 offert +45323 office +45324 offre +45325 offres +45326 offrez +45331 og +45332 ogive +45333 ogives +45334 ogre +45335 ogres +45336 oh +45341 ohm +45342 ohms +45343 oi +45344 oie +45345 oies +45346 oignon +45351 oisif +45352 oisifs +45353 oison +45354 oisons +45355 oj +45356 ok +45361 okapi +45362 ol +45363 olive +45364 olives +45365 om +45366 ombre +45411 omet +45412 omets +45413 omette +45414 omis +45415 omise +45416 omit +45421 on +45422 onagre +45423 once +45424 onces +45425 oncle +45426 oncles +45431 onde +45432 ondes +45433 ondula +45434 ongle +45435 ont +45436 onyx +45441 onze +45442 oo +45443 ooo +45444 oooo +45445 op +45446 opale +45451 opales +45452 opaque +45453 opina +45454 opine +45455 opiner +45456 opines +45461 opium +45462 opq +45463 opta +45464 opte +45465 optent +45466 opter +45511 optera +45512 optes +45513 optez +45514 optima +45515 option +45516 opus +45521 oq +45522 or +45523 orage +45524 oral +45525 orale +45526 oraux +45531 orc +45532 orcs +45533 ordre +45534 ordure +45535 ores +45536 orge +45541 orges +45542 orgie +45543 orgies +45544 orgue +45545 orme +45546 ormeau +45551 ormes +45552 orna +45553 ornais +45554 ornant +45555 orne +45556 ornent +45561 orner +45562 ornes +45563 ornez +45564 orniez +45565 ornons +45566 oronge +45611 orque +45612 ors +45613 orteil +45614 ortie +45615 orvet +45616 os +45621 osa +45622 osais +45623 osait +45624 osant +45625 oscar +45626 oscars +45631 ose +45632 osent +45633 oser +45634 osera +45635 oses +45636 osez +45641 osier +45642 osiers +45643 osiez +45644 osions +45645 osmose +45646 osons +45651 ot +45652 otage +45653 otages +45654 otarie +45655 otite +45656 otites +45661 ou +45662 ouate +45663 ouater +45664 oubli +45665 oublis +45666 oued +46111 oueds +46112 ouest +46113 oui +46114 ourdi +46115 ourdie +46116 ourdis +46121 ourler +46122 ours +46123 ourse +46124 outil +46125 outils +46126 outra +46131 outre +46132 outrez +46133 ouvre +46134 ouvrer +46135 ouvrez +46136 ov +46141 ovaire +46142 ovale +46143 ovales +46144 ovine +46145 ovni +46146 ovnis +46151 ovule +46152 ovuler +46153 ow +46154 ox +46155 oxyda +46156 oxyde +46161 oxyder +46162 oy +46163 oz +46164 ozone +46165 ozones +46166 p +46211 pa +46212 pacha +46213 pack +46214 packs +46215 pacte +46216 page +46221 pages +46222 pagina +46223 pagine +46224 pagne +46225 pagode +46226 paie +46231 paient +46232 paies +46233 paille +46234 pain +46235 pains +46236 pair +46241 paire +46242 paires +46243 pairs +46244 paix +46245 pal +46246 palace +46251 palan +46252 pale +46253 pales +46254 palet +46255 palier +46256 palme +46261 palmes +46262 palot +46263 palpa +46264 palpe +46265 palpes +46266 palpez +46311 pals +46312 pampa +46313 pampas +46314 pan +46315 panda +46316 panel +46321 panels +46322 paner +46323 panne +46324 pannes +46325 pans +46326 pansa +46331 panse +46332 panser +46333 pansez +46334 pantin +46335 paon +46336 paonne +46341 paons +46342 papa +46343 papal +46344 papale +46345 papas +46346 papaux +46351 pape +46352 papes +46353 papier +46354 paquet +46355 par +46356 para +46361 parada +46362 parade +46363 parafe +46364 paras +46365 parc +46366 parce +46411 parcs +46412 pare +46413 pareil +46414 parer +46415 pares +46416 parez +46421 pari +46422 paria +46423 parias +46424 parie +46425 paris +46426 parla +46431 parle +46432 parles +46433 parmi +46434 paroi +46435 pars +46436 part +46441 parte +46442 parti +46443 partie +46444 partit +46445 parts +46446 paru +46451 parue +46452 parure +46453 parus +46454 parut +46455 pas +46456 pascal +46461 passa +46462 passe +46463 passer +46464 passes +46465 passez +46466 passif +46511 patent +46512 patin +46513 patine +46514 patio +46515 patte +46516 paume +46521 paumes +46522 pause +46523 pauses +46524 pava +46525 pavait +46526 pavant +46531 pave +46532 pavent +46533 paver +46534 paves +46535 paveur +46536 pavez +46541 pavois +46542 pavons +46543 pavot +46544 paya +46545 paye +46546 payent +46551 payer +46552 payera +46553 payes +46554 payeur +46555 payez +46556 payiez +46561 pays +46562 payse +46563 pb +46564 pc +46565 pd +46566 pe +46611 peau +46612 peaux +46613 peina +46614 peine +46615 peiner +46616 peines +46621 peinez +46622 peins +46623 peint +46624 peints +46625 pela +46626 pelage +46631 peler +46632 pelez +46633 peliez +46634 pelle +46635 pelles +46636 pelons +46641 pelote +46642 pencha +46643 penche +46644 pend +46645 pende +46646 pendes +46651 pendra +46652 pends +46653 pendu +46654 pendue +46655 pensa +46656 pense +46661 penses +46662 pensez +46663 pensum +46664 pente +46665 perce +46666 perd +51111 perde +51112 perdre +51113 perds +51114 perdu +51115 perdue +51116 perla +51121 perle +51122 permet +51123 permis +51124 permit +51125 perron +51126 pers +51131 perse +51132 perses +51133 perte +51134 pesa +51135 pesage +51136 pesais +51141 peser +51142 peseta +51143 pesez +51144 pesons +51145 pesta +51146 peste +51151 pestes +51152 pet +51153 petit +51154 peton +51155 petons +51156 pets +51161 peu +51162 peupla +51163 peuple +51164 peur +51165 peurs +51166 peut +51211 peux +51212 pf +51213 pg +51214 ph +51215 phare +51216 phares +51221 phase +51222 phases +51223 phobie +51224 phone +51225 phono +51226 phoque +51231 photo +51232 pi +51233 piaffe +51234 piano +51235 pic +51236 pics +51241 pie +51242 pied +51243 pieds +51244 pies +51245 pieu +51246 pieuse +51251 pieux +51252 pige +51253 piger +51254 piges +51255 pigne +51256 pignon +51261 pila +51262 pilait +51263 pile +51264 piler +51265 piles +51266 pileux +51311 pilez +51312 piliez +51313 pilla +51314 pille +51315 pillez +51316 pilon +51321 pilou +51322 pilous +51323 pilule +51324 pin +51325 pince +51326 pins +51331 pinte +51332 piolet +51333 pion +51334 pions +51335 pipe +51336 pipeau +51341 piper +51342 pipes +51343 piqua +51344 pique +51345 piquer +51346 piques +51351 pire +51352 pires +51353 pis +51354 pisser +51355 pista +51356 piste +51361 pister +51362 pistes +51363 pistez +51364 pistil +51365 piteux +51366 piton +51411 pitons +51412 pitre +51413 pivot +51414 pivote +51415 pivots +51416 pixel +51421 pixels +51422 pizza +51423 pizzas +51424 pj +51425 pk +51426 pl +51431 place +51432 places +51433 placet +51434 placez +51435 plage +51436 plagia +51441 plagie +51442 plaid +51443 plaids +51444 plaie +51445 plaies +51446 plaine +51451 plains +51452 plais +51453 plan +51454 plana +51455 plane +51456 planes +51461 planez +51462 plans +51463 plant +51464 plante +51465 plaqua +51466 plasma +51511 plat +51512 plate +51513 plates +51514 plats +51515 plein +51516 pleins +51521 pleur +51522 pleura +51523 pleure +51524 pleut +51525 pli +51526 plia +51531 pliage +51532 plie +51533 plier +51534 plies +51535 pliez +51536 pliiez +51541 plions +51542 plis +51543 pliure +51544 ploie +51545 plomb +51546 plombe +51551 plot +51552 plots +51553 ploya +51554 ployer +51555 ployez +51556 plu +51561 pluie +51562 plume +51563 plumer +51564 plumes +51565 plus +51566 plut +51611 pm +51612 pn +51613 pneu +51614 pneus +51615 po +51616 poche +51621 pocher +51622 poches +51623 podium +51624 pogrom +51625 poids +51626 poil +51631 poils +51632 poilu +51633 poilue +51634 poilus +51635 poing +51636 poings +51641 point +51642 pointa +51643 points +51644 pointu +51645 poire +51646 pois +51651 poisse +51652 poix +51653 poker +51654 pokers +51655 poli +51656 polie +51661 polio +51662 polios +51663 polir +51664 polis +51665 polit +51666 polka +52111 pollen +52112 polo +52113 polos +52114 pomme +52115 pommer +52116 pompa +52121 pompe +52122 pompez +52123 pompon +52124 ponce +52125 poncez +52126 pond +52131 ponde +52132 pondes +52133 pondre +52134 ponds +52135 pondu +52136 pondue +52141 poney +52142 pont +52143 ponte +52144 ponter +52145 ponts +52146 pool +52151 pools +52152 pope +52153 popes +52154 popote +52155 porc +52156 porcs +52161 pore +52162 pores +52163 porno +52164 pornos +52165 port +52166 porta +52211 porte +52212 porto +52213 ports +52214 posa +52215 pose +52216 poser +52221 poses +52222 posez +52223 posons +52224 posta +52225 postal +52226 poste +52231 postez +52232 pot +52233 potage +52234 pote +52235 potes +52236 potin +52241 potion +52242 pots +52243 pou +52244 pouce +52245 pouces +52246 poudra +52251 poudre +52252 pouf +52253 poufs +52254 poule +52255 poules +52256 poulet +52261 pouls +52262 poumon +52263 poupe +52264 poupes +52265 poupin +52266 poupon +52311 pour +52312 pourra +52313 pourri +52314 pourvu +52315 pousse +52316 poux +52321 pp +52322 ppp +52323 pppp +52324 pq +52325 pqr +52326 pr +52331 prend +52332 presse +52333 pria +52334 priait +52335 prie +52336 prier +52341 priera +52342 pries +52343 priez +52344 prima +52345 primat +52346 prime +52351 primer +52352 prions +52353 pris +52354 prisa +52355 prise +52356 prises +52361 prison +52362 prit +52363 priva +52364 prive +52365 priver +52366 prix +52411 probe +52412 proche +52413 profit +52414 proie +52415 proies +52416 projet +52421 promet +52422 promis +52423 promit +52424 promu +52425 promue +52426 promus +52431 promut +52432 pronom +52433 propre +52434 prose +52435 proue +52436 proues +52441 prude +52442 prune +52443 ps +52444 pt +52445 pu +52446 pua +52451 puait +52452 puant +52453 pub +52454 pubis +52455 public +52456 publie +52461 pubs +52462 puce +52463 puceau +52464 puces +52465 pue +52466 puent +52511 puer +52512 puera +52513 puis +52514 puisa +52515 puise +52516 puiser +52521 puises +52522 puisse +52523 puits +52524 pull +52525 pulls +52526 pulpe +52531 puma +52532 pumas +52533 punch +52534 puni +52535 punie +52536 punir +52541 punira +52542 punis +52543 punit +52544 pur +52545 pure +52546 purent +52551 pures +52552 purge +52553 purgea +52554 purger +52555 purin +52556 purs +52561 pus +52562 put +52563 putain +52564 putois +52565 puzzle +52566 pv +52611 pw +52612 px +52613 py +52614 pyjama +52615 pyrex +52616 pz +52621 q +52622 qa +52623 qb +52624 qc +52625 qd +52626 qe +52631 qf +52632 qg +52633 qh +52634 qi +52635 qj +52636 qk +52641 ql +52642 qm +52643 qn +52644 qo +52645 qp +52646 qq +52651 qqn +52652 qqq +52653 qqqq +52654 qqun +52655 qr +52656 qrs +52661 qs +52662 qt +52663 qu +52664 quai +52665 quais +52666 quand +53111 quant +53112 quart +53113 quarts +53114 quartz +53115 quasi +53116 quatre +53121 que +53122 quel +53123 quels +53124 queue +53125 queux +53126 qui +53131 quidam +53132 quille +53133 quinte +53134 quitus +53135 quo +53136 quoi +53141 quota +53142 quotas +53143 qv +53144 qw +53145 qx +53146 qy +53151 qz +53152 r +53153 ra +53154 rabane +53155 rabat +53156 rabbin +53161 rabiot +53162 rabot +53163 rabote +53164 race +53165 races +53166 racine +53211 racla +53212 racle +53213 raclez +53214 racola +53215 racole +53216 radar +53221 rade +53222 radeau +53223 rader +53224 rades +53225 radia +53226 radie +53231 radio +53232 radios +53233 radis +53234 radium +53235 radius +53236 radota +53241 radoub +53242 rafale +53243 raffut +53244 rafla +53245 rafle +53246 rafler +53251 rafles +53252 raflez +53253 rage +53254 ragea +53255 ragent +53256 rager +53261 ragera +53262 rages +53263 ragez +53264 ragot +53265 ragots +53266 raguer +53311 raid +53312 raide +53313 raidi +53314 raids +53315 raie +53316 raies +53321 rail +53322 railla +53323 raille +53324 rails +53325 rainer +53326 raire +53331 rama +53332 ramait +53333 rame +53334 ramena +53335 rament +53336 ramer +53341 rames +53342 rameur +53343 ramez +53344 rami +53345 ramis +53346 ramone +53351 ramons +53352 rampa +53353 rampe +53354 ramper +53355 rampez +53356 rance +53361 rances +53362 ranch +53363 ranci +53364 rancie +53365 rancir +53366 rancis +53411 rang +53412 range +53413 rangez +53414 rangs +53415 ranime +53416 rapace +53421 raphia +53422 rappel +53423 rapt +53424 rapts +53425 raquer +53426 rare +53431 rares +53432 ras +53433 rasa +53434 rasade +53435 rasage +53436 rasais +53441 rasant +53442 rase +53443 rasent +53444 raser +53445 rases +53446 rasez +53451 rasoir +53452 rasons +53453 rassir +53454 rassit +53455 rat +53456 rata +53461 ratage +53462 ratais +53463 ratant +53464 rate +53465 rater +53466 ratera +53511 rates +53512 ratez +53513 ratio +53514 ration +53515 raton +53516 ratons +53521 rats +53522 ravage +53523 ravale +53524 rave +53525 raves +53526 ravi +53531 ravie +53532 ravies +53533 ravin +53534 ravina +53535 ravir +53536 ravira +53541 ravis +53542 ravisa +53543 ravit +53544 ravoir +53545 raya +53546 rayait +53551 raye +53552 rayer +53553 rayes +53554 rayez +53555 rayon +53556 rayons +53561 raz +53562 razzia +53563 rb +53564 rc +53565 rd +53566 re +53611 rebat +53612 rebord +53613 rebut +53614 rebuta +53615 recel +53616 recoin +53621 record +53622 recoud +53623 recru +53624 recta +53625 recto +53626 rectum +53631 recuit +53632 recul +53633 redira +53634 redire +53635 redis +53636 redit +53641 redits +53642 redoux +53643 refera +53644 refit +53645 reflux +53646 refuge +53651 refus +53652 refuse +53653 reg +53654 regard +53655 regret +53656 regs +53661 rein +53662 reine +53663 reines +53664 reins +53665 rejet +53666 rejeta +54111 relaxa +54112 relent +54113 releva +54114 relia +54115 relie +54116 relira +54121 relis +54122 relise +54123 relit +54124 relu +54125 relue +54126 relui +54131 reluit +54132 relus +54133 relut +54134 remet +54135 remis +54136 remisa +54141 remit +54142 remous +54143 remua +54144 remue +54145 remuer +54146 renais +54151 renard +54152 rend +54153 rende +54154 rendes +54155 rendez +54156 rendit +54161 rendre +54162 rends +54163 rendu +54164 renia +54165 renie +54166 renies +54211 renne +54212 renom +54213 renoms +54214 renoua +54215 rente +54216 renter +54221 rentes +54222 rentra +54223 rentre +54224 renvoi +54225 repaie +54226 repars +54231 repas +54232 repaya +54233 repens +54234 repent +54235 repli +54236 repos +54241 reposa +54242 repose +54243 repris +54244 reprit +54245 repu +54246 repue +54251 repues +54252 repus +54253 ressac +54254 resta +54255 reste +54256 rester +54261 retard +54262 retenu +54263 revint +54264 revis +54265 revit +54266 revois +54311 revoit +54312 revu +54313 revue +54314 revus +54315 rf +54316 rg +54321 rh +54322 rhum +54323 rhume +54324 rhums +54325 ri +54326 riais +54331 riait +54332 riant +54333 riants +54334 ribler +54335 riche +54336 ricin +54341 rida +54342 ridant +54343 ride +54344 rider +54345 rides +54346 rie +54351 rien +54352 riens +54353 rient +54354 ries +54355 rieur +54356 riez +54361 rifle +54362 rifles +54363 rigide +54364 riiez +54365 rima +54366 rime +54411 riment +54412 rimer +54413 rimes +54414 rince +54415 rinces +54416 ring +54421 rings +54422 rions +54423 rioter +54424 riper +54425 rira +54426 rirai +54431 riras +54432 rire +54433 rirent +54434 rires +54435 rirez +54436 ririez +54441 rirons +54442 ris +54443 riser +54444 risqua +54445 risque +54446 rit +54451 rite +54452 rites +54453 rituel +54454 riva +54455 rivage +54456 rivais +54461 rival +54462 rivale +54463 rivant +54464 rive +54465 river +54466 rives +54511 rivet +54512 rivez +54513 riviez +54514 rivons +54515 rixe +54516 rixes +54521 riz +54522 rj +54523 rk +54524 rl +54525 rm +54526 rn +54531 ro +54532 robe +54533 rober +54534 robes +54535 robot +54536 roc +54541 roche +54542 roches +54543 rock +54544 rocker +54545 rocks +54546 rococo +54551 rocs +54552 roda +54553 rodage +54554 rodais +54555 rode +54556 roder +54561 rodes +54562 rodez +54563 rogna +54564 rogne +54565 rogner +54566 rognez +54611 rognon +54612 rogue +54613 roi +54614 rois +54615 roll +54616 romain +54621 roman +54622 rompe +54623 rompes +54624 romps +54625 rompt +54626 rompu +54631 rompue +54632 ronce +54633 ronces +54634 rond +54635 ronde +54636 rondin +54641 ronds +54642 ronfla +54643 ronge +54644 rongea +54645 roque +54646 rosace +54651 rosbif +54652 rose +54653 roser +54654 roses +54655 rosi +54656 rosie +54661 rosir +54662 rosis +54663 rosit +54664 rosse +54665 rosses +54666 rot +55111 roter +55112 rotin +55113 rotins +55114 rotor +55115 rots +55116 rotule +55121 roue +55122 rouer +55123 roues +55124 rouge +55125 rouget +55126 rougi +55131 rougie +55132 rougir +55133 rouir +55134 roula +55135 roule +55136 rouler +55141 roules +55142 roulez +55143 roulis +55144 round +55145 rounds +55146 rousse +55151 routa +55152 route +55153 routes +55154 roux +55155 royal +55156 royale +55161 royaux +55162 rp +55163 rq +55164 rr +55165 rrr +55166 rrrr +55211 rs +55212 rst +55213 rt +55214 ru +55215 rua +55216 ruade +55221 ruais +55222 ruait +55223 ruant +55224 ruban +55225 rubis +55226 ruche +55231 rude +55232 rudes +55233 rudoie +55234 rudoya +55235 rue +55236 ruent +55241 ruer +55242 ruera +55243 rueras +55244 ruerez +55245 rues +55246 ruez +55251 rugby +55252 rugbys +55253 rugi +55254 rugir +55255 rugira +55256 rugis +55261 rugit +55262 ruiez +55263 ruiler +55264 ruina +55265 ruine +55266 ruinez +55311 ruions +55312 rumina +55313 rumine +55314 ruons +55315 rural +55316 rusa +55321 ruse +55322 ruser +55323 rusera +55324 ruses +55325 rusez +55326 rush +55331 rushs +55332 rusiez +55333 russe +55334 russes +55335 rut +55336 rutila +55341 ruts +55342 rv +55343 rw +55344 rx +55345 ry +55346 rythme +55351 rz +55352 s +55353 sa +55354 sabir +55355 sabirs +55356 sable +55361 sabot +55362 sabote +55363 sabra +55364 sabre +55365 sabrer +55366 sabres +55411 sabrez +55412 sac +55413 sache +55414 saches +55415 sacre +55416 sacrer +55421 sacres +55422 sacs +55423 saga +55424 sagas +55425 sage +55426 sages +55431 saille +55432 sailli +55433 sain +55434 saine +55435 saines +55436 sains +55441 saint +55442 sainte +55443 sais +55444 saisi +55445 saisie +55446 saisis +55451 sait +55452 sala +55453 salait +55454 sale +55455 saler +55456 sales +55461 salez +55462 sali +55463 salie +55464 salin +55465 saline +55466 salir +55511 salis +55512 salit +55513 salive +55514 salle +55515 salmis +55516 saloir +55521 salon +55522 salons +55523 saloon +55524 salua +55525 salue +55526 saluez +55531 salut +55532 salve +55533 samba +55534 samedi +55535 sana +55536 sanas +55541 sang +55542 sangs +55543 sans +55544 santon +55545 saoul +55546 saoule +55551 sapa +55552 sapait +55553 sapant +55554 sape +55555 saper +55556 sapera +55561 sapes +55562 sapeur +55563 sapin +55564 saquer +55565 sari +55566 saris +55611 sarrau +55612 sas +55613 satin +55614 satins +55615 satire +55616 satura +55621 sauce +55622 sauces +55623 sauf +55624 saufs +55625 sauge +55626 sauges +55631 saule +55632 saules +55633 sauna +55634 sauner +55635 saur +55636 saura +55641 saurs +55642 saut +55643 sauta +55644 saute +55645 sauts +55646 sauva +55651 sauve +55652 savait +55653 savant +55654 savez +55655 saviez +55656 savon +55661 savons +55662 saxo +55663 saxon +55664 saxos +55665 sb +55666 sbire +56111 sc +56112 scalp +56113 scanda +56114 scande +56115 sceau +56116 scella +56121 scia +56122 sciant +56123 scie +56124 scier +56125 sciera +56126 scies +56131 sciez +56132 sciiez +56133 scion +56134 scions +56135 scoop +56136 score +56141 scorie +56142 scout +56143 scouts +56144 scruta +56145 sd +56146 se +56151 seau +56152 seaux +56153 sec +56154 secs +56155 secte +56156 seiche +56161 sein +56162 seing +56163 seins +56164 seize +56165 sel +56166 self +56211 selfs +56212 selle +56213 seller +56214 selon +56215 sels +56216 sema +56221 semais +56222 semble +56223 semer +56224 semez +56225 semis +56226 semoir +56231 sens +56232 sent +56233 sente +56234 senti +56235 sentir +56236 sentis +56241 seoir +56242 sept +56243 sera +56244 serai +56245 seras +56246 serez +56251 serf +56252 serfs +56253 serge +56254 serin +56255 serons +56256 seront +56261 serpe +56262 serra +56263 serre +56264 serrer +56265 sers +56266 sert +56311 serti +56312 sertie +56313 serval +56314 serve +56315 servi +56316 servit +56321 ses +56322 set +56323 sets +56324 setter +56325 seuil +56326 seuils +56331 seul +56332 seule +56333 seules +56334 seuls +56335 sevra +56336 sevrer +56341 sevrez +56342 sexe +56343 sexes +56344 sexy +56345 seyant +56346 sf +56351 sg +56352 sh +56353 shah +56354 shahs +56355 shako +56356 shoot +56361 shoots +56362 short +56363 shorts +56364 show +56365 shows +56366 si +56411 sic +56412 sied +56413 sien +56414 sienne +56415 siens +56416 sieste +56421 sieur +56422 siffla +56423 sigle +56424 signa +56425 signal +56426 signe +56431 signer +56432 signes +56433 signet +56434 signez +56435 silex +56436 sillon +56441 silo +56442 silos +56443 simoun +56444 singe +56445 singer +56446 sinon +56451 sinus +56452 siphon +56453 sire +56454 sirop +56455 sis +56456 sisal +56461 sise +56462 sises +56463 site +56464 sites +56465 situa +56466 situe +56511 situer +56512 situes +56513 situez +56514 six +56515 sj +56516 sk +56521 skate +56522 ski +56523 skia +56524 skiant +56525 skie +56526 skient +56531 skier +56532 skiera +56533 skies +56534 skieur +56535 skiez +56536 skiff +56541 skiffs +56542 skions +56543 skis +56544 sl +56545 slave +56546 slip +56551 slips +56552 slogan +56553 slow +56554 slows +56555 sm +56556 smash +56561 sn +56562 snack +56563 snob +56564 snobs +56565 so +56566 sobre +56611 sobres +56612 soc +56613 social +56614 socle +56615 socles +56616 socs +56621 soda +56622 sodas +56623 sodium +56624 soeur +56625 soeurs +56626 sofa +56631 sofas +56632 soi +56633 soie +56634 soient +56635 soies +56636 soif +56641 soifs +56642 soigna +56643 soigne +56644 soin +56645 soins +56646 soir +56651 soirs +56652 sois +56653 soit +56654 soja +56655 sojas +56656 sol +56661 solda +56662 solde +56663 soldez +56664 sole +56665 solen +56666 soles +61111 soli +61112 solo +61113 solos +61114 sols +61115 sombra +61116 sombre +61121 somma +61122 somme +61123 sommes +61124 sommet +61125 sommez +61126 son +61131 sonar +61132 sonate +61133 sonda +61134 sonde +61135 sondes +61136 songe +61141 songea +61142 songer +61143 songez +61144 sonna +61145 sonne +61146 sonner +61151 sonnet +61152 sono +61153 sonos +61154 sons +61155 sont +61156 sorbe +61161 sorbes +61162 sors +61163 sort +61164 sorte +61165 sorti +61166 sortie +61211 sortis +61212 sortit +61213 sorts +61214 sosie +61215 sot +61216 sots +61221 sotte +61222 sottes +61223 sou +61224 souci +61225 soucia +61226 soucie +61231 soucis +61232 souda +61233 soude +61234 souder +61235 soudes +61236 souk +61241 souks +61242 soulte +61243 soumet +61244 soumit +61245 soupa +61246 soupe +61251 souper +61252 soupes +61253 soupez +61254 source +61255 sourd +61256 sourde +61261 sourds +61262 souri +61263 souris +61264 sous +61265 soute +61266 soviet +61311 soya +61312 soyas +61313 soyeux +61314 soyez +61315 sp +61316 spasme +61321 sphinx +61322 spire +61323 spires +61324 sport +61325 sports +61326 spot +61331 spots +61332 sq +61333 square +61334 squaw +61335 sr +61336 ss +61341 sss +61342 ssss +61343 st +61344 stable +61345 stade +61346 stades +61351 staff +61352 stage +61353 stages +61354 stagna +61355 stagne +61356 stand +61361 stands +61362 star +61363 stars +61364 statif +61365 statu +61366 statua +61411 statut +61412 steak +61413 steaks +61414 stem +61415 stemm +61416 stemms +61421 stems +61422 stick +61423 stock +61424 stocka +61425 stocke +61426 stop +61431 stoppe +61432 stops +61433 store +61434 stores +61435 strate +61436 strie +61441 stu +61442 stuc +61443 stucs +61444 style +61445 styles +61446 stylet +61451 stylo +61452 su +61453 sua +61454 suais +61455 suait +61456 suant +61461 suave +61462 suaves +61463 subi +61464 subie +61465 subies +61466 subir +61511 subis +61512 subit +61513 subits +61514 suc +61515 suce +61516 sucent +61521 sucer +61522 sucera +61523 suces +61524 sucez +61525 sucra +61526 sucre +61531 sucres +61532 sucs +61533 sud +61534 sue +61535 suent +61536 suer +61541 suera +61542 suerai +61543 sueras +61544 sues +61545 sueur +61546 suez +61551 suffi +61552 suffit +61553 suie +61554 suiez +61555 suif +61556 suint +61561 suinta +61562 suinte +61563 suis +61564 suisse +61565 suit +61566 suite +61611 suive +61612 suives +61613 suivi +61614 suivie +61615 suivis +61616 suivit +61621 suivre +61622 sujet +61623 sujets +61624 sulky +61625 sulkys +61626 sultan +61631 suons +61632 super +61633 supin +61634 sur +61635 sure +61636 surent +61641 sures +61642 surf +61643 surfa +61644 surfai +61645 surfas +61646 surfe +61651 surfil +61652 surfs +61653 surgi +61654 surgie +61655 surir +61656 surjet +61661 surs +61662 sursis +61663 survis +61664 survit +61665 survol +61666 sus +62111 sut +62112 sv +62113 sw +62114 swap +62115 swaps +62116 swing +62121 swings +62122 sx +62123 sy +62124 sympa +62125 sympas +62126 syndic +62131 synode +62132 syrien +62133 sz +62134 t +62135 ta +62136 tabac +62141 tabacs +62142 tabla +62143 table +62144 tabler +62145 tabou +62146 tac +62151 tacha +62152 tache +62153 tachez +62154 tact +62155 tacts +62156 taie +62161 taies +62162 tailla +62163 taille +62164 tain +62165 taira +62166 tairas +62211 taire +62212 tairez +62213 tais +62214 taise +62215 tait +62216 talc +62221 talcs +62222 taler +62223 talon +62224 talons +62225 talus +62226 tamis +62231 tan +62232 tandem +62233 tandis +62234 tango +62235 tangua +62236 tangue +62241 tanin +62242 tank +62243 tanks +62244 tant +62245 tante +62246 tantes +62251 taon +62252 taons +62253 tapa +62254 tapais +62255 tapait +62256 tapant +62261 tape +62262 taper +62263 tapes +62264 tapeur +62265 tapez +62266 tapi +62311 tapie +62312 tapies +62313 tapir +62314 tapira +62315 tapirs +62316 tapis +62321 tapit +62322 tapons +62323 tapota +62324 taquet +62325 taquin +62326 tard +62331 tarda +62332 tarde +62333 tardez +62334 tardif +62335 tare +62336 tarer +62341 tares +62342 targua +62343 tari +62344 tarie +62345 taries +62346 tarif +62351 tarifa +62352 tarife +62353 tarir +62354 taris +62355 tarit +62356 tarot +62361 tarots +62362 tarte +62363 tartes +62364 tartir +62365 tas +62366 tassa +62411 tasse +62412 tasser +62413 tasses +62414 tassez +62415 taule +62416 taupe +62421 taupes +62422 taurin +62423 taux +62424 taxa +62425 taxant +62426 taxe +62431 taxent +62432 taxer +62433 taxes +62434 taxez +62435 taxi +62436 taxis +62441 tb +62442 tc +62443 td +62444 te +62445 teck +62446 teins +62451 teint +62452 tek +62453 teks +62454 tel +62455 telle +62456 tels +62461 tempe +62462 tempes +62463 tempo +62464 tempos +62465 temps +62466 tenais +62511 tenait +62512 tend +62513 tende +62514 tendez +62515 tends +62516 tendu +62521 tendue +62522 teneur +62523 tenez +62524 teniez +62525 tenir +62526 tenon +62531 tenons +62532 tenta +62533 tente +62534 tenter +62535 tentes +62536 tentez +62541 tenu +62542 tenue +62543 tenues +62544 tenus +62545 ter +62546 terme +62551 termes +62552 terne +62553 terni +62554 ternis +62555 ternit +62556 terra +62561 terre +62562 terrer +62563 terri +62564 terril +62565 tertre +62566 tes +62611 test +62612 testa +62613 teste +62614 testes +62615 testez +62616 tests +62621 texan +62622 texte +62623 textes +62624 tf +62625 tg +62626 th +62631 thon +62632 thons +62633 thuya +62634 thuyas +62635 thym +62636 ti +62641 tiare +62642 tibia +62643 tic +62644 tics +62645 tien +62646 tienne +62651 tiens +62652 tient +62653 tierce +62654 tiers +62655 tige +62656 tiges +62661 tigre +62662 tigres +62663 tilde +62664 tildes +62665 tiller +62666 tilt +63111 tilts +63112 timbre +63113 timide +63114 timon +63115 tint +63116 tinta +63121 tinte +63122 tique +63123 tiques +63124 tir +63125 tira +63126 tirade +63131 tirait +63132 tirant +63133 tire +63134 tirent +63135 tirer +63136 tirera +63141 tires +63142 tiret +63143 tirets +63144 tirez +63145 tiroir +63146 tirs +63151 tisane +63152 tison +63153 tisons +63154 tissa +63155 tisse +63156 tisses +63161 tissez +63162 tissu +63163 titan +63164 titane +63165 titans +63166 titra +63211 titre +63212 titrer +63213 tj +63214 tk +63215 tl +63216 tm +63221 tn +63222 to +63223 toast +63224 toc +63225 tocs +63226 toge +63231 toges +63232 toi +63233 toile +63234 toiles +63235 toisa +63236 toise +63241 toiser +63242 toises +63243 toisez +63244 toison +63245 toit +63246 toits +63251 tomba +63252 tombe +63253 tombes +63254 tome +63255 tomes +63256 tomme +63261 ton +63262 tonal +63263 tonals +63264 tond +63265 tonde +63266 tondre +63311 tonds +63312 tondu +63313 tondue +63314 tonna +63315 tonne +63316 tonner +63321 tonnes +63322 tons +63323 tonte +63324 tonus +63325 top +63326 topaze +63331 toper +63332 tops +63333 toque +63334 toquer +63335 tord +63336 torde +63341 tordre +63342 tords +63343 tordu +63344 tordus +63345 torero +63346 toril +63351 torils +63352 toron +63353 torons +63354 tors +63355 torse +63356 torses +63361 tort +63362 torts +63363 torve +63364 tosser +63365 total +63366 totale +63411 totaux +63412 totem +63413 touer +63414 toupet +63415 toupie +63416 tour +63421 tours +63422 tous +63423 tout +63424 toute +63425 toutes +63426 toux +63431 toxine +63432 tp +63433 tq +63434 tr +63435 trac +63436 trace +63441 tract +63442 tracta +63443 tracte +63444 trahi +63445 trahie +63446 trahir +63451 traie +63452 train +63453 trais +63454 trait +63455 traita +63456 traits +63461 tram +63462 trama +63463 trame +63464 trames +63465 trams +63466 transi +63511 trapu +63512 traqua +63513 trauma +63514 treize +63515 trempe +63516 tresse +63521 treuil +63522 tri +63523 tria +63524 triade +63525 triage +63526 triais +63531 tribu +63532 tribun +63533 triche +63534 tricot +63535 trie +63536 trient +63541 trier +63542 triera +63543 tries +63544 triez +63545 triiez +63546 trille +63551 trio +63552 trios +63553 tripe +63554 tris +63555 triste +63556 troc +63561 trocs +63562 trois +63563 troll +63564 trombe +63565 tronc +63566 trop +63611 trope +63612 troqua +63613 troque +63614 trot +63615 trots +63616 trotta +63621 trou +63622 troua +63623 troue +63624 troues +63625 trous +63626 trouve +63631 truand +63632 truc +63633 trucs +63634 truffa +63635 truie +63636 truies +63641 truite +63642 trust +63643 truste +63644 ts +63645 tsar +63646 tsars +63651 tt +63652 ttt +63653 tttt +63654 tu +63655 tua +63656 tuais +63661 tuait +63662 tuant +63663 tuba +63664 tubas +63665 tube +63666 tuber +64111 tubes +64112 tue +64113 tuent +64114 tuer +64115 tuera +64116 tueras +64121 tuerez +64122 tuerie +64123 tues +64124 tueur +64125 tueurs +64126 tueuse +64131 tuez +64132 tuf +64133 tufs +64134 tuiez +64135 tuile +64136 tuiles +64141 tulle +64142 tuner +64143 tuners +64144 tuons +64145 turban +64146 turc +64151 turcs +64152 turent +64153 turf +64154 turfs +64155 tus +64156 tussor +64161 tut +64162 tuv +64163 tuyau +64164 tuyaux +64165 tv +64166 tw +64211 tweed +64212 tweeds +64213 tx +64214 ty +64215 type +64216 typer +64221 types +64222 typhon +64223 typo +64224 typon +64225 typons +64226 typos +64231 tyran +64232 tyrans +64233 tz +64234 u +64235 ua +64236 ub +64241 ubac +64242 ubacs +64243 uc +64244 ud +64245 ue +64246 uf +64251 ug +64252 uh +64253 ui +64254 uj +64255 uk +64256 ukase +64261 ukases +64262 ul +64263 um +64264 un +64265 une +64266 unes +64311 uni +64312 unie +64313 unies +64314 unifia +64315 unifie +64316 union +64321 unique +64322 unir +64323 unira +64324 unirez +64325 unis +64326 unit +64331 uns +64332 uo +64333 up +64334 uq +64335 ur +64336 urge +64341 urgea +64342 urger +64343 urine +64344 urne +64345 urnes +64346 us +64351 usa +64352 usage +64353 usager +64354 usais +64355 usait +64356 usant +64361 usante +64362 usants +64363 use +64364 usent +64365 user +64366 usera +64411 userai +64412 useras +64413 userez +64414 uses +64415 usez +64416 usiez +64421 usina +64422 usine +64423 usiner +64424 usons +64425 usuel +64426 usure +64431 usurpa +64432 ut +64433 utile +64434 utiles +64435 uu +64436 uuu +64441 uuuu +64442 uv +64443 uvw +64444 uw +64445 ux +64446 uy +64451 uz +64452 v +64453 va +64454 vacant +64455 vache +64456 vagin +64461 vagins +64462 vagir +64463 vague +64464 vagues +64465 vaille +64466 vain +64511 vainc +64512 vaincs +64513 vaine +64514 vaines +64515 vains +64516 vais +64521 val +64522 valais +64523 valant +64524 valent +64525 valet +64526 valeur +64531 valez +64532 valgus +64533 vallon +64534 valoir +64535 valons +64536 vals +64541 valsa +64542 valse +64543 valser +64544 valsez +64545 valu +64546 value +64551 valus +64552 valut +64553 valve +64554 vamp +64555 vamper +64556 vamps +64561 van +64562 vanne +64563 vanner +64564 vans +64565 vanta +64566 vante +64611 vanter +64612 vantes +64613 vapeur +64614 vaqua +64615 vaque +64616 vaquer +64621 varan +64622 varech +64623 varia +64624 varie +64625 varus +64626 vas +64631 vase +64632 vases +64633 vaseux +64634 vassal +64635 vaste +64636 vastes +64641 vaut +64642 vaux +64643 vb +64644 vc +64645 vd +64646 ve +64651 veau +64652 veaux +64653 veine +64654 veiner +64655 velu +64656 velue +64661 velus +64662 vend +64663 vende +64664 vendit +64665 vendra +64666 vendre +65111 vends +65112 vendu +65113 veneur +65114 venez +65115 venge +65116 vengea +65121 venger +65122 venges +65123 vengez +65124 venin +65125 venir +65126 venons +65131 vent +65132 venta +65133 vente +65134 ventru +65135 vents +65136 venu +65141 venue +65142 venus +65143 ver +65144 verbe +65145 verbes +65146 verdi +65151 verdir +65152 verdit +65153 verge +65154 verger +65155 verni +65156 vernie +65161 vernis +65162 verra +65163 verre +65164 verres +65165 verrez +65166 verrou +65211 vers +65212 versa +65213 verse +65214 verser +65215 verses +65216 versez +65221 verso +65222 versos +65223 vert +65224 verte +65225 vertes +65226 verts +65231 vertu +65232 verve +65233 vessie +65234 veste +65235 veto +65236 veuf +65241 veufs +65242 veule +65243 veut +65244 veuve +65245 veux +65246 vexa +65251 vexais +65252 vexant +65253 vexe +65254 vexer +65255 vexes +65256 vexez +65261 vexiez +65262 vf +65263 vg +65264 vh +65265 vi +65266 via +65311 viable +65312 viager +65313 viande +65314 vibra +65315 vibre +65316 vice +65321 vices +65322 vichy +65323 vicia +65324 vicie +65325 vida +65326 vidage +65331 vidais +65332 vidait +65333 vidant +65334 vide +65335 vider +65336 videra +65341 vides +65342 videz +65343 vie +65344 vieil +65345 vielle +65346 vienne +65351 viens +65352 vient +65353 vies +65354 vieux +65355 vif +65356 vifs +65361 vigie +65362 vigies +65363 vigile +65364 vigne +65365 vil +65366 vile +65411 viles +65412 villa +65413 villas +65414 ville +65415 vils +65416 vin +65421 viner +65422 vineux +65423 vingt +65424 vins +65425 vint +65426 vinyle +65431 viol +65432 viola +65433 viole +65434 violes +65435 violet +65436 violon +65441 viols +65442 vira +65443 virago +65444 virais +65445 viral +65446 virant +65451 vire +65452 virer +65453 virera +65454 vires +65455 virez +65456 viriez +65461 viril +65462 virons +65463 virus +65464 vis +65465 visa +65466 visage +65511 visais +65512 visait +65513 visant +65514 visas +65515 vise +65516 viser +65521 visera +65522 vises +65523 visez +65524 visiez +65525 vision +65526 visita +65531 vison +65532 visons +65533 vissa +65534 visse +65535 visser +65536 vissez +65541 visuel +65542 vit +65543 vitae +65544 vital +65545 vite +65546 vitre +65551 vitrer +65552 vitres +65553 vivace +65554 vivat +65555 vive +65556 vivent +65561 vives +65562 vivez +65563 vivier +65564 viviez +65565 vivote +65566 vivra +65611 vivrai +65612 vivras +65613 vivre +65614 vj +65615 vk +65616 vl +65621 vm +65622 vn +65623 vo +65624 vocal +65625 vocale +65626 vodka +65631 vodkas +65632 voeu +65633 voeux +65634 vogua +65635 vogue +65636 voguer +65641 vogues +65642 voici +65643 voie +65644 voies +65645 voila +65646 voile +65651 voir +65652 voire +65653 voirie +65654 vois +65655 voit +65656 voix +65661 vol +65662 vola +65663 volait +65664 vole +65665 volent +65666 voler +66111 volera +66112 voles +66113 volet +66114 volets +66115 voleur +66116 volez +66121 vols +66122 volt +66123 volts +66124 volute +66125 vomi +66126 vomie +66131 vomies +66132 vomir +66133 vomis +66134 vomit +66135 vont +66136 vos +66141 vota +66142 votais +66143 votant +66144 vote +66145 votent +66146 voter +66151 votera +66152 votes +66153 votez +66154 votons +66155 votre +66156 voua +66161 vouais +66162 vouait +66163 voue +66164 vouent +66165 vouer +66166 voues +66211 vouez +66212 vouiez +66213 voulu +66214 voulue +66215 vous +66216 voyais +66221 voyeur +66222 voyez +66223 voyiez +66224 voyons +66225 voyou +66226 vp +66231 vq +66232 vr +66233 vrac +66234 vrai +66235 vraie +66236 vrais +66241 vrille +66242 vs +66243 vt +66244 vu +66245 vue +66246 vues +66251 vulve +66252 vus +66253 vv +66254 vvv +66255 vvvv +66256 vw +66261 vwx +66262 vx +66263 vy +66264 vz +66265 w +66266 wa +66311 wagon +66312 waters +66313 watt +66314 watts +66315 wb +66316 wc +66321 wd +66322 we +66323 wf +66324 wg +66325 wh +66326 wi +66331 wj +66332 wk +66333 wl +66334 wm +66335 wn +66336 wo +66341 wp +66342 wq +66343 wr +66344 ws +66345 wt +66346 wu +66351 wv +66352 ww +66353 www +66354 wwww +66355 wx +66356 wxy +66361 wy +66362 wz +66363 x +66364 xa +66365 xb +66366 xc +66411 xd +66412 xe +66413 xf +66414 xg +66415 xh +66416 xi +66421 xj +66422 xk +66423 xl +66424 xm +66425 xn +66426 xo +66431 xp +66432 xq +66433 xr +66434 xs +66435 xt +66436 xu +66441 xv +66442 xw +66443 xx +66444 xxx +66445 xxxx +66446 xy +66451 xyz +66452 xz +66453 y +66454 ya +66455 yacht +66456 yack +66461 yacks +66462 yak +66463 yaks +66464 yard +66465 yards +66466 yb +66511 yc +66512 yd +66513 ye +66514 yeux +66515 yf +66516 yg +66521 yh +66522 yi +66523 yj +66524 yk +66525 yl +66526 ym +66531 yn +66532 yo +66533 yoga +66534 yp +66535 yq +66536 yr +66541 ys +66542 yt +66543 yu +66544 yv +66545 yw +66546 yx +66551 yy +66552 yyy +66553 yyyy +66554 yz +66555 z +66556 za +66561 zb +66562 zc +66563 zd +66564 ze +66565 zen +66566 zeste +66611 zester +66612 zestes +66613 zf +66614 zg +66615 zh +66616 zi +66621 zinc +66622 zincs +66623 zipper +66624 zj +66625 zk +66626 zl +66631 zm +66632 zn +66633 zo +66634 zona +66635 zonas +66636 zone +66641 zones +66642 zoo +66643 zoom +66644 zooms +66645 zoos +66646 zp +66651 zq +66652 zr +66653 zs +66654 zt +66655 zu +66656 zv +66661 zw +66662 zx +66663 zy +66664 zz +66665 zzz +66666 zzzz \ No newline at end of file diff --git a/g1sms/diceware.sh b/g1sms/diceware.sh new file mode 100755 index 0000000..8219568 --- /dev/null +++ b/g1sms/diceware.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +MOTS=$(echo "$1" | grep -E "^\-?[0-9]+$") +# Default to 6 words passphrase +if [[ "$MOTS" == "" ]]; then MOTS=6; fi +WORDCOUNT=${1-$MOTS} +# Download the wordlist +# wget -nc -O ~/.diceware-wordlist http://world.std.com/%7Ereinhold/diceware.wordlist.asc 2> /dev/null +# print a list of the diceware words +cat ./shell/diceware-wordlist.txt | +awk '/[1-6][1-6][1-6][1-6][1-6]/{ print $2 }' | +# randomize the list order +shuf --random-source=/dev/urandom | +# pick the first n words +head -n ${WORDCOUNT} | +# pretty print +tr '\n' ' ' +echo diff --git a/g1sms/functions.sh b/g1sms/functions.sh new file mode 100755 index 0000000..85595a2 --- /dev/null +++ b/g1sms/functions.sh @@ -0,0 +1,672 @@ +#!/bin/bash +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +# G1SMS COMMUN FUNCTIONS + +# TODO: REWRITE AND MAKE FULL IPFS get wallet value through IPNS links +# ipfs cat /ipns/QmUrUdfz5hWJ6354D3N6DT64tbs5CLEndSYYiqrj9Wa4Ax/+33647683646/+33647683646.uidna +################################################################################################################################### + +################################################################################################################################### + +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" + local mess="$2" + if [[ ${#dest} -eq 10 || ${#dest} -eq 12 ]]; then + if [[ -d ./wallets/$dest ]]; then + # TEST IF $dest IS ON CURRENT NODE + 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) + log "$dest is managed by NODE: $DESTNODEID)" + mkdir "./wallets/.$DESTNODEID/SMS" + echo $mess > "./wallets/.$DESTNODEID/SMS/$dest.sms2send" + I=$(ipfs_node_wallets_add) + fi + else + log ">>>>>>>>>>SMS ERROR BAD DESTINATION $dest" + fi + log ">>>>>>>>>> SENDING SMS $mess TO $dest ($DESTNODEID)" +} + + +################################################################################################################################# +function sms_ERROR () { +# sms_ERROR ($1=phone, $2=message) + local dest="$1" + local mess="[ERREUR] +$2" + if [[ ${#dest} -eq 10 || ${#dest} -eq 12 ]]; then + gammu-smsd-inject TEXT "$dest" -text "$mess" 1>&2 + else + log ">>>>>>>>>>SMS ERROR BAD DESTINATION $dest" + fi + log ">>>>>>>>>> SENDING SMS $mess TO $dest" + # SEND ERROR COPY TO ADMINPHONE + if [[ "$CPERROR" == "YES" ]]; then sms_SEND "$ADMINPHONE" "ADMIN! ERROR ($dest): $mess"; fi +} + + +################################################################################################################################# +function log_history () { + log "__SUB:log_history: history ($1, $2)" + PHONE="$1" + HISTFILE="./history.$IPFSNODEID.log.csv" + + echo "$(date +%Y%m%d), $(date +%H:%M:%S), $1, $2" >> "$HISTFILE" +} + + +################################################################################################################################# +function security () { + +if [[ "$G1SMS" == "YES" ]]; then # ONLY OF gammu is really sending SMS on that NODE + # No Reply to MySelf (or enjoy SMS LOOP of the death) Nobody neither + if [[ "$PHONE" == "$MASTERPHONE" || "$PHONE" == "" ]]; then log "__SUB:security: SMS REJECTED !! $PHONE $TEXT"; exit; fi + + # ADAPT TO YOUR PHONE COMPANY / ADVERT ANNOYANCE + if [[ "$PHONE" == "Orange Info" ]]; then log "__SUB:security: SMS REJECTED !! $PHONE ADVERT $TEXT"; exit; fi + if [[ ${#PHONE} -ne 12 && ${#PHONE} -ne 46 ]]; then log "!! SMS REJECTED !! $PHONE BAD $TEXT"; exit; fi +fi + +# ANTI SPAM SMS (1 mn entre chaque commande) +find /tmp -cmin +1 -type f -name "sms_received_*" -exec rm -f '{}' \; + +# Do not consider SPAM, Delivered notification +if [[ "$CMD" != "DELIVERED" && "$CMD" != "PENDING" ]]; then + if [[ -f "/tmp/sms_received_$PHONE" ]]; then + # Send response SMS + if [[ ! -f "/tmp/sms_SPAM_$PHONE" ]]; then + sms_ERROR "$PHONE" "Je ne le dirai pas 2 fois... Laissez moi au moins 1 minute entre chacune de vos commandes SMS! Autrement je n'y répondrai pas. Merci!" + echo $(date) > "/tmp/sms_SPAM_$PHONE" + fi + log "__SUB:security: ################################" + log "__SUB:security: $PHONE COMMAND REJECTED: $TEXT" + exit + fi + echo "$TEXT" > "/tmp/sms_received_$PHONE" + # Remove SPAM flag older than one day + find /tmp -ctime +1 -type f -name "sms_SPAM_*" -exec rm -f '{}' \; +else + # THIS IS AN AKNOWLEGEMENT + log "__SUB:security: ################################" + log "__SUB:security: $PHONE COMMAND REJECTED: $TEXT" + exit +fi +# Remove SPAM flag older than one day +find /tmp -ctime +1 -type f -name "sms_SPAM_*" -exec rm -f '{}' \; + +} + + +################################################################################################################################# +function ipfs_swarm_wallets_refresh (){ + +# Refresh CURRENT NODE wallets STATUS +I=$(ipfs_node_wallets_add) + +# REFRESH SWARM MEMORY +mkdir -p "./wallets_swarm" +chown -R $YOU "./wallets_swarm" +log "__SUB:ipfs_swarm_wallets_refresh: REFRESHING SWARM $PHONE shared memory..." +if [[ $PHONE ]]; then rm -Rf ./wallets_swarm/$PHONE; fi + +# GET IPNS published wallets from ALL SWARM NODES / TODO: IF NODES MISSING, check ./wallets_swarm/.QmNODES... +#log "__SUB:ipfs_swarm_wallets_refresh: IPFS: ipfs get --output=./wallets_swarm/ /ipns/$IPFSNODEID" +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/.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) + log "__SUB:ipfs_swarm_wallets_refresh: IPFS: ipfs get --output=./wallets_swarm/ /ipns/$id" + rm -Rf ./wallets_swarm/.$id + ./shell/timeout.sh -t 20 su $YOU -c "ipfs get --output=./wallets_swarm/ /ipns/$id" +done +log "__SUB:ipfs_swarm_wallets_refresh: ./wallets_swarm/ RENEW from $count peers .........OK!!!" + + +############################################################################" +# TREAT move_g1cents Tasks in ./wallets/.$IPFSNODEID +# IF NODE find in ./wallets_swarm/.$IPFSNODEID/TASK directory && Have it's G1 Wallet already (for natools crypto) +if [[ "$1" != "SIMPLE" && -d ./wallets_swarm/.$IPFSNODEID/TASK && -f "./wallets/.$IPFSNODEID/$IPFSNODEID.authfile.GPGPASS.gpg" ]]; then +############################################################################" +for task in $(ls ./wallets_swarm/.$IPFSNODEID/TASK/*.move_g1cents.*); # ./wallets/.$IPFSNODEID/TASK/$NANODATE.move_g1cents.$DESTPHONE.NODEPUB.crypt OR "done.$NANODATE" FILES +do + FTASK=$( echo $task | cut -d '/' -f 5 ) # "$NANODATE.move_g1cents.$DESTPHONE.NODEPUB.crypt" + TNANO=$( echo $FTASK | cut -d '.' -f 1) # $NANODATE + TTYPE=$( echo $FTASK | cut -d '.' -f 2) # move_g1cents + TDEST=$( echo $FTASK | cut -d '.' -f 3) # $DESTPHONE + log "__SUB:ipfs_swarm_wallets_refresh: .$IPFSNODEID($FTASK) FOUND TASK $TNANO:$TTYPE:$TDEST " + # MAKE LOCAL .$IPFSNODEID directory + mkdir -p ./wallets/.$IPFSNODEID/TASK/ + # TODO: CHECK BETTER NOT DONE YET and $NANODATE > $TNANO (=> detect NODES writing in the future!!) + if [[ ! -f "./wallets/.$IPFSNODEID/TASK/done.$TNANO" ]]; then # NOT DONE YET: NEW TASK! + tdiff=$(bc -l <<< "$NANODATE - $TNANO") + if [[ $tdiff -gt 0 ]]; then + # GET BACK MY NODE G1 Wallet authfile from my LOCAL ./wallets + echo "${GPGPASS}" | gpg -q -d --output "./NODEG1Wallet.authfile" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "./wallets/.$IPFSNODEID/$IPFSNODEID.authfile.GPGPASS.gpg" + # DECRYPT and CAT move_g1cents VALUE + ./shell/natools.py decrypt -k "./NODEG1Wallet.authfile" -i "$task" -o "/tmp/move_g1cents.$TDEST" + ZENVAL=$(cat "/tmp/move_g1cents.$TDEST") + log "__SUB:ipfs_swarm_wallets_refresh: tdiff=$tdiff .$IPFSNODEID G1 = ./NODEG1Wallet.authfile :decrypt: Found $ZENVAL Zen to ADD" + rm -f "./NODEG1Wallet.authfile" + if [[ $ZENVAL -gt 0 ]]; then + curvalue=$(cat ./wallets/$TDEST/$TDEST.g1cents) + newvalue=$(bc -l <<< "$curvalue + $ZENVAL") + echo $newvalue > ./wallets/$TDEST/$TDEST.g1cents + echo "OK.$tdiff" > ./wallets/.$IPFSNODEID/TASK/done.$TNANO + log "__SUB:ipfs_swarm_wallets_refresh: .$IPFSNODEID($FTASK) DONE! OPERATION: ($curvalue + $ZENVAL) = $newvalue Zen <=> ./wallets/$TDEST/$TDEST.g1cents:: OK" + # REFRESH ./wallets and PUBLISH + I=$(ipfs_node_wallets_add) + else + echo "KO.$tdiff" > ./wallets/.$IPFSNODEID/TASK/done.$TNANO + log "__SUB:ipfs_swarm_wallets_refresh: .$IPFSNODEID($FTASK) ERROR! BAD: ($curvalue + $ZENVAL) = $newvalue Zen <=> ./wallets/$TDEST/$TDEST.g1cents :: KO" + I=$(ipfs_node_wallets_add) + sms_SEND "$ADMINPHONE" "ADMIN! TASK ERROR: .$IPFSNODEID($FTASK) ERROR! BAD: ($curvalue + $ZENVAL) = $newvalue Zen <=> ./wallets/$TDEST/$TDEST.g1cents :: KO" + fi + else + # TODO: Bad NODE in the Future task !!! Make better BAD Node detection = Swarm Banish? + echo "KO.$tdiff" > ./wallets/.$IPFSNODEID/TASK/done.$TNANO + log "__SUB:ipfs_swarm_wallets_refresh: .$IPFSNODEID($FTASK) ERROR! DATE PROBLEM: $NANODATE < $TNANO :: KO" + I=$(ipfs_node_wallets_add) + sms_SEND "$ADMINPHONE" "ADMIN! .$IPFSNODEID($FTASK) ERROR! DATE PROBLEM: $NANODATE < $TNANO :: KO" + fi + fi +done + + log "__SUB:ipfs_swarm_wallets_refresh: REMOVE OLD TASK MARKED AS DONE" + for scan in ./wallets_swarm/.Qm*/TASK/done.*; do + lscan=$(echo $scan | sed s/_swarm//g ) + lid=$(echo $scan | cut -d '/' -f 3 | cut -d '.' -f 2 ) + lnano=$(echo $scan | cut -d '/' -f 5 | cut -d '.' -f 2 ) + if [[ "$lid" != "$IPFSNODEID" ]]; then + log "__SUB:ipfs_swarm_wallets_refresh: CLEANING done OLD TASK ${lscan} SENT to $lid ($lnano.bin)" + rm -f ./wallets/.$lid/TASK/$lnano.* + I=$(ipfs_node_wallets_add) + fi + done +else + log "__SUB:ipfs_swarm_wallets_refresh: .$IPFSNODEID :: NO TASK ! " +############################################################################" +fi +} + + +################################################################################################################################# +function ipfs_node_wallets_add (){ + ########################## + ########################## + IWALLETS=$(su $YOU -c "ipfs add -rHq './wallets' | tail -n 1") + + # CHAIN STATE FOR $IPFSNODEID + echo $IWALLETS > ./wallets/.$IPFSNODEID.wallets.chain + log "__SUB:ipfs_node_wallets_add: NEW './wallets' HASH ipfs ls $IWALLETS" + + # PUBLISH IPNS NODE WALLETS + NODEWALLETS=$(su $YOU -c "ipfs name publish --quieter /ipfs/$IWALLETS") + log "__SUB:ipfs_node_wallets_add: G1smsWallet = ipfs cat /ipns/$NODEWALLETS/$PHONE/$PHONE.g1cents Zen" + + echo $IWALLETS +} + + +################################################################################################################################# +function sms_uid2key (){ + RIBFILE="./wallets/$PHONE/$PHONE.uidrib" + NAMEFILE="./wallets/$PHONE/$PHONE.uidname" + UIDNAFILE="./wallets/$PHONE/$PHONE.uidna" + # New related wallet asked + ASKWALLET="$1" + #For micro payement + PHONE="$2" + PIN="$3" + if -f "$UIDNAFILE"; then UIDNA=$(cat "$UIDNAFILE"); else UIDNA=""; fi + log "__SUB:sms_uid2key: $UIDNA Try to associate $ASKWALLET with $PHONE... SEARCHING..." + + if [[ $UIDNA && "$ASKWALLET" == "$UIDNA" ]]; then + log "__SUB:sms_uid2key: "$ASKWALLET" == "$UIDNA" !!" + sms_SEND "$PHONE" "[G1sms+] $UIDNA est le nom de votre porte monnaie libre pour $PHONE. Il ne peut également être compte maître!" + fi + + # Test if member files exists + if [ -f "$NAMEFILE" ]; then + UIDNAME=$(cat "$NAMEFILE") + log "__SUB:sms_uid2key: ALREADY $UIDNAME related Wallet for $PHONE Wallet change to $ASKWALLET !!" + if [["$UIDNAME" != "$ASKWALLET" ]]; then + sms_SEND "$ADMINPHONE" "ADMIN! INFO: $PHONE Wallet associé à $UIDNAME change en $ASKWALLET !!" + sms_SEND "$PHONE" "[G1sms+] Votre portefeuille maitre va passer de $UIDNAME à $ASKWALLET!" + fi + fi + + # Search fo duplicate + DUP=$(grep -Rwl "$ASKWALLET" ./wallets/*/*.uidname | cut -f 3 -d '/') + if [[ "$DUP" != "" && "$DUP" != "$PHONE" ]]; then + sms_SEND "$ADMINPHONE" "ADMIN! INFO: $PHONE prend le même $ASKWALLET, que $DUP" + sms_SEND "$DUP" "Vous devez savoir que $ASKWALLET est associé à un autre téléphone que le votre également!" + fi + + ########################################################### + # FIND ASKWALLET into wallets, wallest_swarm OR duniter (silkaj) + DESTMEM="$VIRDEST" + # SEARCH IN WALLETS + LOCAL=$(grep -Rwl "$ASKWALLET" ./wallets/*/*.uidna | cut -f 3 -d '/') + if [[ "$LOCAL" != "" ]]; then + # LOCAL G1sms account + DESTRIB=$(cat ./wallets/$LOCAL/$LOCAL.pub) + DESTPHONE=$LOCAL + log "__SUB:sms_uid2key: FOUND LOCAL ($MASTERPHONE) G1sms+ wallet: $DESTRIB ($LOCAL)" + else + # SEARCH IN WALLETS SWARM + INSWARM=$(grep -Rwl "$ASKWALLET" ./wallets_swarm/*/*.uidna | cut -f 3 -d '/') + if [[ "$INSWARM" != "" ]]; then + REMOTENODE=$(cat ./wallets_swarm/$INSWARM/MASTERPHONE.sms) + DESTRIB=$(cat ./wallets_swarm/$INSWARM/$INSWARM.pub) + DESTPHONE=$INSWARM + log "__SUB:sms_uid2key: FOUND SWARM ($REMOTENODE) G1sms+ wallet: $DESTRIB ($INSWARM)" + else + # SEARCH WITH SILKAJ + log "__SUB:sms_uid2key: GETTING FROM SILKAJ MEMBER ID" + DESTRIB=$(./silkaj/silkaj id "$ASKWALLET" | grep -w "$ASKWALLET" | awk '{print $2}') + log "__SUB:sms_uid2key: OUT OFF SWARM MEMBER wallet: $DESTRIB" + # GET CESIUM+ geoPoint DATA (TODO: cron for GCHANGE SMS Alert) + curl -s ${CESIUM}/user/profile/${DESTRIB} | jq '._source.geoPoint' > "./wallets/$PHONE/$PHONE.uidgeo.json" + log "__SUB:sms_uid2key: GET CESIUM+ geoPoint and AVATAR : $(cat ./wallets/$PHONE/$PHONE.uidgeo.json)" + curl -s ${CESIUM}/user/profile/${DESTRIB} | jq '._source.avatar._content' | sed 's/\"//g' | base64 -d > "./wallets/$PHONE/$PHONE.avatar.png" + fi + fi + + if [ "$DESTRIB" != "" ]; then + echo "$DESTRIB" > "$RIBFILE" + echo "$ASKWALLET" > "$NAMEFILE" + log "__SUB:sms_uid2key: NEW EXTERNAL RELATED $DESTRIB / FOR MEMBER OR WALLET = $ASKWALLET - INIT 0.1 TX" + INIT=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="0.1" --output=$DESTRIB --comment="[G1sms+] Porte Monnaie $(cat $UIDNAFILE) -> $(cat $NAMEFILE)" -y) + log "__SUB:sms_uid2key: INIT = $INIT | Create Connection with related Wallet." + log_history "$PHONE" "MEMBER, $ASKWALLET" + sms_SEND "$ADMINPHONE" "ADMIN! LOG: $PHONE Nouveau compte lié $UIDNA -- $ASKWALLET ($INIT)" + else + sms_SEND "$ADMINPHONE" "ADMIN! LOG: $PHONE / $ASKWALLET ABSENT" + fi + + log "__SUB:sms_uid2key: $MEMBER($DESTRIB)" + echo "$DESTRIB" +} + + +################################################################################################################################# +function sms_INIT_ACCOUNT () { +log "__SUB:sms_INIT_ACCOUNT: ($1=phone, $2=NOSMS)" + PHONE="$1" + UNKNOWN=0 + # TODO Optimize GLOBAL/local variables use, use more function array output ?! + # Initiate PHONE settings files and values + IPFSNODEIDFILE="./wallets/$PHONE/MASTERPHONE.ipfsid" # Contains G1sms+ NODE IPFS id + SMSNODE="./wallets/$PHONE/MASTERPHONE.sms" # Contains G1sms+ SMS phone number + PINFILE="./wallets/$PHONE/$PHONE.pin" # Contains phone wallet diceware password + GPGPINFILE="./wallets/$PHONE/$PHONE.pin.gpg" # Contains g1smsnode cypher phone wallet diceware password + AUTHCRYPTFILE="./wallets/$PHONE/$PHONE.authfile.crypt" # Crypt with $NODE_G1PUBKEY + PUBKEYFILE="./wallets/$PHONE/$PHONE.pub" # Contains phone wallet public key (RIB) + UNITFILE="./wallets/$PHONE/$PHONE.unit" # Contains phone wallet prefered unit (LOVE,G1,DU) + + RIBFILE="./wallets/$PHONE/$PHONE.uidrib" # Contains phone wallet related UID Pubkey + NAMEFILE="./wallets/$PHONE/$PHONE.uidname" # Contains the member UID related to wallet + MAILFILE="./wallets/$PHONE/$PHONE.email" # Contains the member EMAIL (Send BILLET) + GPGMAILFILE="./wallets/$PHONE/$PHONE.email.gpg" # Contains the member EMAIL (Send BILLET) + UIDNAFILE="./wallets/$PHONE/$PHONE.uidna" # Contains the G1sms+ UID Name for recursive VIR + GEOFILE="./wallets/$PHONE/$PHONE.uidgeo.json" # Contains the member GeoPoint from member Cesium+ related to wallet + + RECFILE="./wallets/$PHONE/VIREMENTS" # File showing recurrent payements are left to be done with this G1sms Wallet + GPGRECFILE="./wallets/$PHONE/VIREMENTS.gpg" # Cypher file with GPGPASS (Node .Identity.PrivKey) + G1COUNTFILE="./wallets/$PHONE/$PHONE.g1cents" # Last sms_COUNT.sh call value + CHAINFILE="./wallets/$PHONE/$PHONE.chain" # Contains wallet last IPFS hash before ZEN value change + + DABUIDF="./wallets/$PHONE/uidna.G1TAGNODE" # Contains G1Dab Name + # GET CURRENT NODE UIDNA (default DABUID) + NODEUIDNA=$(cat "./wallets/.$IPFSNODEID/$IPFSNODEID.uidna") + [[ $NODEUIDNA == "" ]] && NODEUIDNA=$(cat "./wallets/.$IPFSNODEID/_uidna") +###################################################################### + # (NO PIN) = FIRST ACCOUNT: Create wallet + if [ ! -f "$PINFILE" ]; then + # NOSMS mode? + if [[ $2 == "NOSMS" ]]; then UNKNOWN="unknown"; return; fi + + ####################### + # Create Account Files + ####################### + mkdir -p "./wallets/$PHONE/" + PIN=$(./shell/diceware.sh | xargs) + PUBKEY=$(./silkaj/silkaj generate_auth_file --auth-scrypt -salt="$PHONE" -password="$PIN") + + # BACKUP authfile available to authfile or PIN owner (DOUBLON AVEC PIN) TEST + log "__SUB:sms_INIT_ACCOUNT: ./shell/natools.py encrypt -p $PUBKEY -i ""./authfile"" -o ""$AUTHCRYPTFILE""" + ./shell/natools.py encrypt -p $NODE_G1PUBKEY -i "./authfile" -o "$AUTHCRYPTFILE" + rm -f ./authfile + log "__SUB:sms_INIT_ACCOUNT: !! G1 Wallet CREATED: $PHONE $PIN : $PUBKEY" + + ####################### + # GIVE NAME 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" + + ####################### + # ACTIVATE G1SMS WALLET + ####################### + # log "$NODE_G1AUTHFILE $PUBKEY THIRD_PARTY_MANAGER:$NODE_G1PUBKEY" + TX_IN=$(./silkaj/silkaj transaction --auth-file -file="$NODE_G1AUTHFILE" --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=$NODE_G1PUBKEY --comment="[G1sms+] $UIDNA$TAIL 3RD:$NODE_G1PUBKEY:ACK" -y) + log "__SUB:sms_INIT_ACCOUNT: G1 Wallet TX OUT: $TX_OUT" + + ################ + # GPG cypher PIN (ONLY CREATOR NODE CAN ACCESS IT !) + ################ + echo "$PIN" > "$PINFILE" + echo "${GPGPASS}" | gpg -q --output "$GPGPINFILE" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$PINFILE" + PIN=$(cat "$PINFILE" | xargs) + [[ "$PIN" != "" ]] && echo "" > "$PINFILE" || log "SYSTEM ERROR :: PIN EMPTY !!! GPG???" + + echo "114" > "$G1COUNTFILE" + echo "$PUBKEY" > "$PUBKEYFILE" + echo "$COIN" > "$UNITFILE" + echo "$MASTERPHONE" > "$SMSNODE" + log_history "$PHONE" "NEW, $PUBKEY" + + # ADD WALLET TO IPFS + I=$(ipfs_node_wallets_add) + fi + + + ################################################# + # PUBLISH G1sms+ WALLET PROPERTIES MAIN PROCESS + ################################################# +###################################################################### + if [[ ! -f "$GPGPINFILE" ]] + then + # ------------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" + + 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"; + ./shell/natools.py encrypt -p $NODE_G1PUBKEY -i "$PINFILE" -o "$PINFILE.$NODE_UIDNA.crypt" + 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" + PIN=$(cat "$PINFILE" | xargs) + [[ "$PIN" == "" && -f "$PINFILE.$NODE_UIDNA.crypt" ]] && ./shell/natools.py decrypt -k "$NODE_G1AUTHFILE" -i "$PINFILE.$NODE_UIDNA.crypt" -o "$PINFILE" && PIN=$(cat "$PINFILE"); + [[ "$PIN" != "" ]] && echo "" > "$PINFILE" || log "SYSTEM ERROR :: PIN EMPTY !!! GPG???" + fi + + # CYPHER EMAIL FILE + if [[ ! -f "$GPGMAILFILE" ]]; then + # ------------8<------------------ + log "__SUB:sms_INIT_ACCOUNT: NO EMAIL .gpg file, CREATING it" + if [ -f "$MAILFILE" ]; then + MAIL=$(cat "$MAILFILE"); + echo "${GPGPASS}" | gpg -q --output "$GPGMAILFILE" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$MAILFILE"; + else + MAIL=""; + fi + # ------------>8------------------ + else + log "__SUB:sms_INIT_ACCOUNT: DECODING EMAIL .gpg... " + echo "${GPGPASS}" | gpg -d -q --output "$MAILFILE" --yes --pinentry-mode loopback --passphrase-fd 0 "$GPGMAILFILE" + MAIL=$(cat "$MAILFILE"); + [[ $MAIL == "" && -f "$MAILFILE.node.crypt" ]] && ./shell/natools.py decrypt -k "$NODE_G1AUTHFILE" -i "$MAILFILE.node.crypt" -o "$MAILFILE" && MAIL=$(cat "$MAILFILE"); + # EMPTY CLEAR EMAIL FILE + [[ $MAIL != "" ]] && echo "" > "$MAILFILE" || log "SYSTEM ERROR :: MAIL EMPTY !!! GPG???" + fi + + # ------------8<------------------ + # REMOVE OLD HISTORY FILES + rm -f ./wallets/$PHONE/$PHONE.hist + # ------------>8------------------ + + # PUBLISH GLOBAL VARS FROM ACCOUNT FILES + echo $IPFSNODEID > $IPFSNODEIDFILE + PUBKEY=$(cat "$PUBKEYFILE" | xargs) + UNIT=$(cat "$UNITFILE" | xargs) + if [ -f "$G1COUNTFILE" ]; then AMOUNTG1=$(bc <<< "scale=2; $(cat $G1COUNTFILE) / 100"); fi + if [ -f "$NAMEFILE" ]; then MEMBER=$(cat "$NAMEFILE"); else MEMBER=""; fi + if [ -f "$RIBFILE" ]; then MEMRIB=$(cat "$RIBFILE"); else MEMRIB=""; fi + if [ -f "$UIDNAFILE" ]; then UIDNA=$(cat "$UIDNAFILE"); else UIDNA=""; fi + if [ -f "$DABUIDF" ]; then DABID=$(cat "$DABUIDF"); else DABID="$NODEUIDNA"; fi + + + AMOUNTDU=$(bc <<< "scale=2; $AMOUNTG1 / $DUFACTOR") + AMOUNTLOVE=$(bc <<< "$AMOUNTG1 * 100 / $DUFACTOR") + + case "$UNIT" in + G1) + AMOUNT=$AMOUNTG1 + ;; + DU) + AMOUNT=$AMOUNTDU + ;; + *) + AMOUNT=$AMOUNTLOVE + ;; + esac + log "__SUB:sms_INIT_ACCOUNT: $AMOUNTG1 = $AMOUNT $UNIT" + + # LOG # TODO REMOVE PIN LOG!! + log "#####################" + log "PHONE: $PHONE" + log "PIN: $PIN" + log "PUBKEY: $PUBKEY" + log "G1: $AMOUNTG1" + log "AMOUNT: $AMOUNT $UNIT" + log "UIDNA: $UIDNA" + log "MEMBER: $MEMBER" + log "MEMRIB: $MEMRIB" + log "MAIL: $MAIL" + log "DABID: $DABID" + log "#####################" + + + log "__SUB:sms_INIT_ACCOUNT: END" +} + + +################################################################################################################################# +function check_account (){ +log "__SUB:check_account: SILKAJ...... max 30 sec....." +AMOUNTG1=$(./shell/timeout.sh -t 30 ./silkaj/silkaj amount "$PUBKEY") +AMOUNTDU=$(bc <<< "scale=2; $AMOUNTG1 / $DUFACTOR") +AMOUNTLOVE=$(bc <<< "$AMOUNTG1 * 100 / $DUFACTOR") + +case "$UNIT" in + G1) + AMOUNT=$AMOUNTG1 + ;; + DU) + AMOUNT=$AMOUNTDU + ;; + *) + AMOUNT=$AMOUNTLOVE + ;; +esac +G1cents=$(echo "$AMOUNTG1*100" | bc -l | awk '{print int($0)}') + +log "__SUB:check_account: $PHONE: $AMOUNTG1 = $AMOUNT $UNIT ($G1cents) - $PUBKEY" + +if [[ "$G1cents" != "" ]]; then + NN=$(cat "./wallets/$PHONE/$PHONE.n") + ((NN++)) + echo "$NN" > "./wallets/$PHONE/$PHONE.n" + echo $G1cents > "./wallets/$PHONE/$PHONE.g1cents" + # REFRESH NODE IPFS wallets & PUBLISH + I=$(ipfs_node_wallets_add) + # Register modification + echo "$I" > "./wallets/$PHONE/$PHONE.chain" +else + # BAN actual Duniter Node in case of silkaj timeout. + export NEWDUNITER=$(./shell/checknodes.sh 'BAN') + log "__SUB:check_account: !!! SILKAJ IS TOO SLOW !!! => NEW DUNITER SERVER: $NEWDUNITER" +fi + +declare -a aaa +aaa=( "$AMOUNTG1" "$AMOUNT" "$UNIT" ) +log "__SUB:check_account: $(declare -p aaa)" +echo ${aaa[@]} +} + + +################################################################################################################################# +function make_accounting (){ +# CONVERT AMOUNT UNIT to VIR G1 +case "$UNIT" in +G1) + VIR=$AMOUNT; + ;; +DU) + VIR=$(bc -l <<< "scale=2; $AMOUNT * $DUFACTOR") + ;; +LOVE) + VIR=$(bc -l <<< "scale=2; $AMOUNT * $DUFACTOR / 100") + ;; +*) + VIR=$(bc -l <<< "scale=2; $AMOUNT * $DUFACTOR / 100") + ;; +esac + +########################################################### +# GET G1sms wallet AMOUNTG1 and CHECK for right balance +log "__SUB:make_accounting: LOCAL $VIR amount for $PHONE : $PUBKEY" +# Try to ask silkaj. If timeout, use SWARM last known $PHONE.g1cents value +AMOUNTG1=$(./shell/timeout.sh -t 30 ./silkaj/silkaj amount "$PUBKEY") +if [[ "$AMOUNTG1" == "" ]]; then AMOUNTG1=0; fi +# TAX AND MINIMUM WALLET ACCOUNT CALCULATION +PERCENT=0$(bc -l <<< "scale=2; $VIR / $SWARMCOMM") +MIN=$(bc -l <<< "$AMOUNTG1 - $PERCENT - $LIMIT") +CHARGE=$(bc -l <<< "scale=2; $VIR + $PERCENT + $LIMIT") +TESTMIN=$( echo "${VIR} < ${MIN}" | bc -l ) +log "__SUB:make_accounting: TEST $AMOUNT $UNIT :: $VIR + $PERCENT + $LIMIT = $CHARGE < $AMOUNTG1 ? $TESTMIN" + +declare -a myarray +myarray=( "$TESTMIN" "$VIR" "$PERCENT" "$CHARGE") +log "__SUB:make_accounting: $(declare -p myarray)" +echo ${myarray[@]} +} + +################################################################################################################################# +function move_g1cents (){ + # MODIFY $PHONE.g1cents value according to current silkaj + # TODO MAKE ALL SILKAJ TX CALL HERE. OR REMOVE??? + # USE TASK COMMUNICATION BETWEEN NODES. + phonesrc=$1 + pubkeydest=$2 + zenvalue=$3 + log "__SUB:move_g1cents: $phonesrc ($zenvalue) -> $pubkeydest :: $G1COUNTFILE ::" + + ### CHANGE INPUT VALUE #### + curvalue=$(cat ./wallets/$phonesrc/$phonesrc.g1cents | cut -d '.' -f 1) + newvalue=$(bc -l <<< "$curvalue - $zenvalue") + echo $newvalue > ./wallets/$phonesrc/$phonesrc.g1cents + log "__SUB:move_g1cents: DEBIT: OK APPLY $curvalue - $zenvalue = $newvalue TO ./wallets/$phonesrc/$phonesrc.g1cents" + + ### CHANGE OUTPUT VALUE #### + # TEST IF $dest is a wallets_ G1sms PUBKEY? + winnerphone=$(grep -Rwl "$pubkeydest" ./wallets_swarm/*/*.pub | cut -d '.' -f 2 | cut -d '/' -f 3) + if [[ $winnerphone ]]; then + # GET INFORMATON ON MANAGER NODE + NODEID=$(cat ./wallets_swarm/$winnerphone/MASTERPHONE.ipfsid) + + if [[ "$NODEID" == "$IPFSNODEID" ]]; then + # ACTUAL NODE IS WALLET MANAGING NODE ;) + curvalue=$(cat ./wallets/$winnerphone/$winnerphone.g1cents | cut -d '.' -f 1) + newvalue=$(bc -l <<< "$curvalue + $zenvalue") + echo $newvalue > ./wallets/$winnerphone/$winnerphone.g1cents + log "__SUB:move_g1cents: CREDIT: OK APPLY $curvalue + $zenvalue = $newvalue TO ./wallets/$winnerphone/$winnerphone.g1cents" + else + # MUST ASK MANAGER NODE TO CORRECT g1cents FOR $winnerphone WALLET + # WRITE TASK TO .$NODEID CHANNEL + mkdir -p ./wallets/.$NODEID/TASK/ + # USE natools with NODEPUB crypt + echo "$zenvalue" > "/tmp/move_g1cents.$winnerphone" + # GET NODE G1sms Wallet PUBKEY + NODEPUB=$(cat ./wallets_swarm/.$NODEID/$NODEID.pub) + ./shell/natools.py encrypt -p $NODEPUB -i "/tmp/move_g1cents.$winnerphone" -o "./wallets/.$NODEID/TASK/$NANODATE.move_g1cents.$winnerphone.NODEPUB.crypt" + log "__SUB:move_g1cents: CREDIT: WRITE TASK TO ./wallets/.$NODEID/$NANODATE.move_g1cents.$winnerphone.NODEPUB.crypt " + rm -f /tmp/move_g1cents.$winnerphone + fi + else + log "__SUB:move_g1cents: ERROR: NO $pubkeydest WALLET FOUND" + fi + # 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 -N -u$userDB -p$pwdDB gammu -e" + + local PHONE=$1 + local MEMBERUID=$2 + + [[ -z $MEMBERUID ]] && MEMBERUID=$PHONE + + [[ -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 + +} + +function rm_contact(){ + userDB="gammu" + pwdDB=$(cat /etc/gammu-smsdrc | grep "password =" | awk '{ print $3 }' || exit 1) + local sql="mysql -N -u$userDB -p$pwdDB gammu -e" + + local PHONE=$1 + local MEMBERUID=$2 + + [[ -z $MEMBERUID ]] && MEMBERUID=$PHONE + + 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/g1sms/g1.png b/g1sms/g1.png new file mode 100644 index 0000000..e96366e Binary files /dev/null and b/g1sms/g1.png differ diff --git a/g1sms/g1tag-v0.png b/g1sms/g1tag-v0.png new file mode 100644 index 0000000..194c743 Binary files /dev/null and b/g1sms/g1tag-v0.png differ diff --git a/g1sms/g1tag.png b/g1sms/g1tag.png new file mode 100644 index 0000000..f6b61e9 Binary files /dev/null and b/g1sms/g1tag.png differ diff --git a/g1sms/good.nodes.txt b/g1sms/good.nodes.txt new file mode 100644 index 0000000..214199d --- /dev/null +++ b/g1sms/good.nodes.txt @@ -0,0 +1,6 @@ +duniter.moul.re:443 +g1.duniter.fr:443 +g1.duniter.org:443 +g1.le-sou.org:443 +g1.monnaielibreoccitanie.org:443 +g1.presles.fr:443 diff --git a/g1sms/init.sh.old b/g1sms/init.sh.old new file mode 100755 index 0000000..ca20a67 --- /dev/null +++ b/g1sms/init.sh.old @@ -0,0 +1,83 @@ +#!/bin/bash +################################################################## +# Author: Fred (support@qo-op.com) +# 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) + if [ "$DOLOG" == "YES" ] + then + echo "$PHONE:$1" >> /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 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) + 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 $GPATH/shell/init_keys.sh + diff --git a/g1sms/init_keys.sh b/g1sms/init_keys.sh new file mode 100755 index 0000000..35127e1 --- /dev/null +++ b/g1sms/init_keys.sh @@ -0,0 +1,148 @@ +#!/bin/bash +################################################################## +# Author: Fred (support@qo-op.com) +# Version: 0.2 +# License: GPL (http://www.google.com/search?q=GPL) +################################################################## +# CHECK & WARN | CREATE Keys (gpg encrypt, G1wallet, IPNS publish) +################################################################## + +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) +IPFSNODEID=$(su $YOU -c "ipfs id -f='\n'") +NANODATE=$(date -u +%s%N) #1569692075385428020 + +################################################################## +# G1sms+ Node KEYS (G1wallet, gpg, IPNS) +################################################################## +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 +################################################################## +# G1sms Service - G1Wallet +# +# CLEF G1 DU SWARM +SWARM_G1PUBKEY=$(cat "${GPATH}/g1sms.pub.key") +SWARM_G1AUTHFILE="${GPATH}/g1sms.priv.key" + +# CLEF G1 NODE = CLEF G1 SWARM !! +if [[ ! -e "./g1sms.preoni.pub.key" && -f "./g1sms.priv.key" ]]; then + log "__SUB:initkeys.sh: Linking preoni Keys to SWARM G1 Keys" + ln -s ./g1sms.priv.key ./g1sms.preoni.priv.key + ln -s ./g1sms.pub.key ./g1sms.preoni.pub.key +elif [[ ! -f ./g1sms.preoni.priv.key ]]; then + # CREATE NODE G1 KEYS AND FILES + mkdir -p ./wallets/.$IPFSNODEID/TASK + ################################################ + # GIVE NAME TO NODE G1 WALLET: "0000diceware" + # CREATE "preoni" KeyS & ./wallets/.Qm***/_files + ################################################ + # 4 derniers chiffres du MASTERPHONE + diceware + PRE=${MASTERPHONE:8:4} + ZUID=$(./shell/diceware.sh 1 | xargs) + # Check if already existing among all swarm wallets + while [[ $(grep -Rwl "$PRE$ZUID" ./wallets_swarm/.*/_uidna) ]]; do ZUID=$(./shell/diceware.sh 1 | xargs); done + NODE_UIDNA="$PRE$ZUID" + NODE_PIN=$(./shell/diceware.sh | xargs) + + NODE_G1PUBKEY=$(./silkaj/silkaj generate_auth_file --auth-scrypt -salt="$NODE_UIDNA" -password="$NODE_PIN") + if [[ ! $NODE_G1PUBKEY ]]; then log "PROBLEME CREATION DU WALLET G1 POUR $NODE_UIDNA = $IPFSNODEID"; exit; fi + log "__SUB:initkeys.sh: NODE G1WALLET CESIUM: $NODE_UIDNA / $NODE_PIN CREATED..." + + # WRITE NODE_UIDNA + echo "$NODE_UIDNA" > "./wallets/.$IPFSNODEID/_uidna" ################# _uidna + + ############ SYSTEM MODIFY hosts & hostname ################ + # WRITE NODE uidna NAME TO /etc/hosts & .Qm*/_uidna file + echo "127.0.0.101 $NODE_UIDNA" >> "/etc/hosts" + echo $NODE_UIDNA > "/etc/hostname" + ############################################################ + + # BACKUP AUTHFILE FOR FOR SWARM USE (TODO: Refine Swarm, Node access): GIVES SMARM WITHDRAW ACTION + ./shell/natools.py encrypt -p $SWARM_G1PUBKEY -i "./authfile" -o "./wallets/.$IPFSNODEID/_authfile.swarm.crypt" + + echo $NODE_G1PUBKEY > "./wallets/.$IPFSNODEID/_pub" ################# _pub + echo $IPFSNODEID > "./wallets/.$IPFSNODEID/_ipfsid" ################# _ipfsid + log "__SUB:initkeys.sh: [ADMIN] G1sms+ CREATE G1WALLET FOR: $IPFSNODEID: _pub = $NODE_G1PUBKEY " + + # BACKUP $IPFSNODEID config ################# _ipfsconfig.swarm.crypt : GIVES SMARM NODE RESTORE ACTION + ./shell/natools.py encrypt -p $SWARM_G1PUBKEY -i "/home/$YOU/.ipfs/config" -o "./wallets/.$IPFSNODEID/_ipfsconfig.swarm.crypt" + log "__SUB:initkeys.sh: [ADMIN] BACKUP IPFS NODE CONFIG to ./wallets/.$IPFSNODEID/_ipfsconfig.swarm.crypt" + + # Cyper & Empty PIN + echo "${NODE_PIN}" > "./wallets/.$IPFSNODEID/_pin" ################# _pin / _pin.node.crypt / _pin.gpg + ./shell/natools.py encrypt -p $NODE_G1PUBKEY -i "./wallets/.$IPFSNODEID/_pin" -o "./wallets/.$IPFSNODEID/_pin.node.crypt" + echo "${GPGPASS}" | gpg -q --output "./wallets/.$IPFSNODEID/_pin.gpg" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "./wallets/.$IPFSNODEID/_pin" + echo "" > "./wallets/.$IPFSNODEID/_pin" + + echo "314" > "./wallets/.$IPFSNODEID/_g1cents" ################# _g1cents + echo $NANODATE > "./wallets/.$IPFSNODEID/_nanodate" ################# _nanodate + + # SILKAJ INIT G1 NODE WALLET + TX_IN=$(./silkaj/silkaj transaction --auth-file -file="$SWARM_G1AUTHFILE" --amount=3.24 --output=$NODE_G1PUBKEY --comment="[G1sms+] G1NODE ($ADMINPSEUDO) $NODE_UIDNA $IPFSNODEID" -y) + TX_OUT=$(./silkaj/silkaj transaction --auth-scrypt -salt="$NODE_UIDNA" -password="$NODE_PIN" --amount=0.1 --output=$SWARM_G1PUBKEY --comment="[G1sms+] G1NODE ($ADMINPSEUDO) $NODE_UIDNA $IPFSNODEID:ACK" -y) + + log "__SUB:initkeys.sh: [ADMIN] NODE G1sms+ $NODE_UIDNA : ls ./wallets/.$IPFSNODEID" + gammu-smsd-inject -l TEXT "$ADMINPHONE" -text "[ADMIN] G1sms+ NODE $NODE_UIDNA ($IPFSNODEID)" 1>&2 + gammu-smsd-inject -l TEXT "$ADMINPHONE" -text "$NODE_G1PUBKEY" 1>&2 + + # CREATE preoni FILES + mv ./authfile ./g1sms.preoni.priv.key + echo $NODE_G1PUBKEY > ./g1sms.preoni.pub.key +fi + +NODE_UIDNA=$(cat "./wallets/.$IPFSNODEID/_uidna") +## INIT NODE G1 PUB & PRIV KEY +NODE_G1PUBKEY=$(cat "${GPATH}/g1sms.preoni.pub.key") +NODE_G1AUTHFILE="${GPATH}/g1sms.preoni.priv.key" + +########################################################## +# MEMORIZE NODE NANODATE EXECUTION TIME (for ntpdate regular sync) +if [[ -f ./wallets/.$IPFSNODEID/_nanodate ]]; then + last=$(cat ./wallets/.$IPFSNODEID/_nanodate) + timediff=$( echo "${NANODATE} - ${last}" | bc -l ) + # NODE TIME SYNC 600 milliards de nanosecondes = 600 s = 10 mn + if [[ $timediff -gt 600000000000 ]]; then + # RUN & LOG ntpdate + log "__SUB:ntpdate pool.ntp.org: $timediff $(ntpdate pool.ntp.org)" + export NANODATE=$(date -u +%s%N) + fi + echo $NANODATE > ./wallets/.$IPFSNODEID/_nanodate +fi + +################################################################ +#INFORM ABOUT NODE CAPACITIES +export NODEPUB=$(cat "./wallets/.$IPFSNODEID/_pub") + +## IS IT A SMS NODE (gammu-smsd is installed)?? +if [[ $G1SMS ]]; then + echo $MASTERPHONE > "./wallets/.$IPFSNODEID/_sms" +else + if [ -f "./wallets/.$IPFSNODEID/_sms" ]; then rm -f "./wallets/.$IPFSNODEID/_sms"; fi +fi + +## IS THERE USB PRINTER CONNECTED? +if [[ -e "/dev/usb/lp0" ]]; then + log "G1CORE: IMPRESSION G1Tag ACTIF .............." + echo $ADRESSE > "./wallets/.$IPFSNODEID/_where" +fi + +## IS THERE SERIAL QR CODE READER CONNECTED? +if [[ -e "/dev/ttyACM0" ]]; then + log "G1CORE: SCAN G1Tag ACTIF .............." + export G1TX="YES" + echo "/dev/ttyACM0" > "./wallets/.$IPFSNODEID/_scan" +else + if [ -f "./wallets/.$IPFSNODEID/_scan" ]; then rm -f "./wallets/.$IPFSNODEID/_scan"; fi +fi + diff --git a/g1sms/manual_BILLETS_PERIMES.sh b/g1sms/manual_BILLETS_PERIMES.sh new file mode 100755 index 0000000..b7d84ec --- /dev/null +++ b/g1sms/manual_BILLETS_PERIMES.sh @@ -0,0 +1,64 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +# 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=$NODE_G1PUBKEY; fi + +echo "Recherche de G1Billets plus vieux que $vieux jours." +Nbillets=$(find billets/ -daystart -mtime +$vieux -type f -name "*.pubkey" | wc -l) +echo "$Nbillets G1Billets trouvés..." + +for result in $(find billets/ -daystart -mtime +$vieux -type d -name "*"); do + billetname=$(echo $result | cut -d '/' -f 2) + if [[ $billetname && "$billetname" != "MEMBERS" ]]; then + ((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") + + solde=$(/usr/local/bin/silkaj -p duniter-g1.p2p.legal:443 balance $pubkey | grep Quantitative | cut -d '=' -f 2 | cut -d ' ' -f 2) + + # 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 $numero + echo $secret $salt + echo "/usr/local/bin/silkaj tx --amount=\"$virement\" --output=\"$dest\"" + + if [[ "$virement" == "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" --comment="[G1Billet] $numero" -y) + if [[ ! $(echo $PAY | grep "successfully sent") ]]; then + 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" + echo + rm -Rf $result + fi + fi + else + echo "MEMBER:" $result + fi +done + diff --git a/g1sms/natools.py b/g1sms/natools.py new file mode 100755 index 0000000..5149743 --- /dev/null +++ b/g1sms/natools.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 + +import os, sys, duniterpy.key, libnacl.sign + +def getargv(arg:str, default:str="", n:int=1, args:list=sys.argv) -> str: + if arg in args and len(args) > args.index(arg)+n: + return args[args.index(arg)+n] + else: + return default + +def read_data(data_path, b=True): + if data_path == "-": + if b: + return sys.stdin.read().encode() + else: + return sys.stdin.read() + else: + if b: + return open(os.path.expanduser(data_path), "rb").read() + else: + return open(os.path.expanduser(data_path), "r").read() + +def write_data(data, result_path): + (sys.stdout if result_path == "-" else open(os.path.expanduser(result_path), "wb")).write(data) + +def encrypt(data, pubkey): + return duniterpy.key.PublicKey(pubkey).encrypt_seal(data) + +def decrypt(data, privkey): + return duniterpy.key.SigningKey.from_seedhex(privkey).decrypt_seal(data) + +def sign(data, privkey): + return duniterpy.key.SigningKey.from_seedhex(privkey).sign(data) + +def verify(data, pubkey): + try: + return libnacl.sign.Verifier(duniterpy.key.PublicKey(pubkey).hex_pk()).verify(data) + except ValueError: + exit(1) + +def show_help(): + print("""Usage: +python3 natools.py [options] + +Commands: + encrypt Encrypt data + decrypt Decrypt data + sign Sign data + verify Verify data + +Options: + -i Input file path (default: -) + -k Privkey file path (default: authfile.key) + -p Pubkey (base58) + -o Output file path (default: -) + +Note: "-" means stdin or stdout. +""") + +if __name__ == "__main__": + + if "--help" in sys.argv: + show_help() + exit() + + data_path = getargv("-i", "-") + privkey_path = getargv("-k", "authfile.key") + pubkey = getargv("-p") + result_path = getargv("-o", "-") + + try: + if sys.argv[1] == "encrypt": + write_data(encrypt(read_data(data_path), pubkey), result_path) + elif sys.argv[1] == "decrypt": + write_data(decrypt(read_data(data_path), read_data(privkey_path, False)), result_path) + elif sys.argv[1] == "sign": + write_data(sign(read_data(data_path), read_data(privkey_path, False)), result_path) + elif sys.argv[1] == "verify": + write_data(verify(read_data(data_path), pubkey), result_path) + else: + show_help() + except Exception as e: + sys.stderr.write("Error: ", e, "\n") + show_help() + exit(1) diff --git a/g1sms/nodes.txt b/g1sms/nodes.txt new file mode 100644 index 0000000..87579bf --- /dev/null +++ b/g1sms/nodes.txt @@ -0,0 +1,11 @@ +duniter.moul.re: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/g1sms/parle.sh b/g1sms/parle.sh new file mode 100755 index 0000000..ed99fd9 --- /dev/null +++ b/g1sms/parle.sh @@ -0,0 +1,12 @@ +#!/bin/bash +f=$(echo "$1" | sed 's/ //g' ) +echo "parle.sh: $1 | $2 = $f" >> /tmp/parle.log 2>&1 +if [[ "$2" == "" ]]; then + lang="fr-FR" +else + lang="en-US" +fi +if [[ ! -f "/tmp/$lang_${f}.wav" ]]; then + pico2wave -l $lang -w /tmp/$lang_${f}.wav "$1" +fi +aplay -q /tmp/$lang_${f}.wav diff --git a/g1sms/sms_ABO.sh b/g1sms/sms_ABO.sh new file mode 100755 index 0000000..28ff437 --- /dev/null +++ b/g1sms/sms_ABO.sh @@ -0,0 +1,49 @@ +#!/bin/bash +################################################################## +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: GPL (http://www.google.com/search?q=GPL) +################################################################## +# Commande SMS: sms_ABO.sh +# ABO "$SERVICE" "$YESNO" +# Gère les Abonnements aux communications PUSH SMS +################################################################## +# TODO: Create information Channels and moderate OPT IN/OUT +source ./shell/init.sh +source ./shell/functions.sh +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" + 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" + 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) + log "Avertissement G1 marchés" + # PARAMS could be "$distance" to Member GeoPoint... + ;; + GCHANGE) + log "Création Alerte Annonce GCHANGE" + # PARAMS could be "$distance#$keyword" to search gchange.fr near Member GeoPoint... + ;; + INFO) + log "Abonnement Newsletter" + # PARAMS could be "$distance#$keyword" to search gchange.fr near Member GeoPoint... + ;; + *) + # AIDE : ABO GCHANGE 100#maison... + log "Renvoyez AIDE..." + sms_SEND "$PHONE" "Cette commande est inactive..." + ;; +esac diff --git a/g1sms/sms_ADMIN.sh b/g1sms/sms_ADMIN.sh new file mode 100755 index 0000000..dd45b7f --- /dev/null +++ b/g1sms/sms_ADMIN.sh @@ -0,0 +1,89 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +# Accessible seulement pour ADMINPHONE. +# Permet de lancer des paquets de SMS aux membres, wallets, ... +# TODO Add OptIN/OUT options (./shell/sms_ABO.sh) + Extand ADMIN functions... +source ./shell/init.sh +source ./shell/functions.sh +log "__SUB:sms_ADMIN.sh: START ($1=CMD, $2=MESSAGE)" + +CMD="$1" +MESSAGE="$2" + +case "$CMD" in + + USR) + log "__SUB:sms_ADMIN.sh: Send message to phone Member or Wallet UIDNA" + # Get it from first MESSAGE message word... + towoo=$(echo $MESSAGE | cut -d ' ' -f 1) + + SEARCH=$(grep -Rwl "$towoo" ./wallets_swarm/*/*.uidna* | tail -n 1 | cut -f 3 -d '/') + if [[ "$SEARCH" != "" ]]; then + REMOTENODE=$(cat ./wallets_swarm/$SEARCH/MASTERPHONE.sms) + DESTRIB=$(cat ./wallets_swarm/$SEARCH/$SEARCH.pub) + DESTPHONE=$SEARCH + log "__SUB:sms_ADMIN.sh: FOUND $towoo on NODE ($REMOTENODE) G1sms+ wallet: $DESTRIB : $DESTPHONE)" + + if [[ "$DESTPHONE" == "$ADMINPHONE" || "$DESTPHONE" == "$MASTERPHONE" ]]; then continue; fi + sms_SEND "$DESTPHONE" "$MESSAGE" + sms_SEND "$ADMINPHONE" "ADMIN OK!! Message: $MESSAGE envoyé à $towoo: $DESTPHONE" + fi + ;; + + + MEM) + log "__SUB:sms_ADMIN.sh: Send $MESSAGE message to All NODE members" + for f in ./wallets/*/*.uidname; do + uid=$(cat $f); + num=$(echo $f | cut -d '/' -f3); + if [[ "$num" == "$ADMINPHONE" || "$num" == "$MASTERPHONE" ]]; then continue; fi + log "__SUB:sms_ADMIN.sh: Send SMS to $num: $uid" + sms_SEND "$num" "$uid, $MESSAGE" + sleep 5 + done + sms_SEND "$ADMINPHONE" "ADMIN! Message envoyé aux $(cat ./wallets/*/*.uidname | wc -l) membres de ce NODE" + ;; + + ALL) + log "__SUB:sms_ADMIN.sh: Send $MESSAGE message to All NODE G1sms wallets" + for f in ./wallets/*; do + num=$(echo $f | cut -d '/' -f3); + if [[ "$num" == "$ADMINPHONE" || "$num" == "$MASTERPHONE" ]]; then continue; fi + log "__SUB:sms_ADMIN.sh: Send SMS to $num" + sms_SEND "$num" "$MESSAGE" + sleep 5 + done + sms_SEND "$ADMINPHONE" "ADMIN! Message envoyé aux $(ls ./wallets/ | cut -d '/' -f3 | wc -l) possesseur de G1sms Wallets de ce NODE" + ;; + + SWARM) + log "__SUB:sms_ADMIN.sh: Send $MESSAGE message to All SWARM G1sms wallets" + for f in ./wallets_swarm/+33*; do + num=$(echo $f | cut -d '/' -f3); + if [[ "$num" == "$ADMINPHONE" || "$num" == "$MASTERPHONE" ]]; then continue; fi + log "__SUB:sms_ADMIN.sh: Send SMS to $num" + sms_SEND "$num" "$MESSAGE" + sleep 5 + done + sms_SEND "$ADMINPHONE" "ADMIN! Message: $MESSAGE envoyé aux $(ls ./wallets_swarm/ | cut -d '/' -f3 | wc -l) PHONE G1sms Wallets du SWARM" + ;; + + *) + log "__SUB:sms_ADMIN.sh: Send back ERRORs message to Admin" + if [ -f "/tmp/ERROR.CRON" ]; then + text=$(cat "/tmp/ERROR.CRON") + rm -f "/tmp/ERROR.CRON" + fi + sms_SEND "$ADMINPHONE" "USR / MEM / ALL / SWARM +$text" + ;; +esac + +sms_SEND "$ADMINPHONE" "ADMIN! JOB FINISHED" + +log "__SUB:sms_ADMIN.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~" +exit diff --git a/g1sms/sms_AIDE.sh b/g1sms/sms_AIDE.sh new file mode 100755 index 0000000..0bd21ad --- /dev/null +++ b/g1sms/sms_AIDE.sh @@ -0,0 +1,33 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +source ./shell/init.sh +source ./shell/functions.sh +log "X sms_AIDE.sh ($1=phone)" + +sms_INIT_ACCOUNT "$1" "NOSMS" + +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 : 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) +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" +log "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + +exit diff --git a/g1sms/sms_BILLET.sh b/g1sms/sms_BILLET.sh new file mode 100755 index 0000000..0680cac --- /dev/null +++ b/g1sms/sms_BILLET.sh @@ -0,0 +1,180 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +# Create and print 6 G1Billets de nn LOVE +source ./shell/init.sh +source ./shell/functions.sh +log "__SUB:sms_BILLET.sh: ($1=phone, $2=VALbillet)" + +phone="$1" +VALbillet="$2" +# 6 BILLETS DE $VALbillet LOVE PAR SMS !! +NBbillets=6 + +# Initialise PHONE, PIN, PUBKEY, UNIT, HIST + MEMBER + MEMRIB +... +sms_INIT_ACCOUNT "$phone" "NOSMS" + +# FIXED LOVE UNIT (6 month maximum validity) +UNIT="LOVE" + +log "__SUB:sms_BILLET.sh: MEMBER? $PHONE => $MEMBER" + +if [[ $UNKNOWN == "unknown" || "$MEMBER" == "" ]]; then + sms_ERROR "$phone" "Porte-monnaie non identifié. +Envoyez N suivi de votre pseudo membre (en respectant Majuscule et minuscule)." + exit +fi + +if [[ $MAIL == "" ]]; then + sms_ERROR "$phone" "Impossible de réaliser votre commande. +Envoyez \"EMAIL votre_email\" pour pouvoir recevoir vos billets..." + exit +fi + +if [ $VALbillet -lt 10 ]; then + sms_ERROR "$phone" "Montant minimum 10 $UNIT !!" + exit +fi + +if [ $VALbillet -gt 1000 ]; then + sms_ERROR "$phone" "Montant maximum: 1000 $UNIT !!" + exit +fi + +# Get AMOUNTG1, AMOUNTLOVE, AMOUNTDU +AMOUNTG1=$(./silkaj/silkaj amount "$PUBKEY") +AMOUNTDU=$(bc -l <<< "scale=2; $AMOUNTG1 / $DUFACTOR") +AMOUNTLOVE=$(bc -l <<< "scale=0; $AMOUNTG1 * 100 / $DUFACTOR") + +# Convert amount to G1 unit +amount=$(bc <<< "$NBbillets * $VALbillet") +VIR=$(bc -l <<< "scale=2; $amount * $DUFACTOR / 100") + +# Need at least $MIN G1 available! $BILLCOM G1 commission +MIN=$(bc -l <<< "$AMOUNTG1 - $LIMIT - $BILLCOM") +testmin=$( echo "${VIR} < ${MIN}" | bc -l ) +log "__SUB:sms_BILLET.sh: TEST : $VIR < $MIN ? $testmin" + +# silkaj NODE CHANGE !!! +#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 2 | xargs) + bpath=$(echo $NUMBER | sed 's/ /_/g') + + # Cas d'un billet existant + while [ -d "./billets/$bpath" ] + do + NUMBER=$(./shell/diceware.sh 2 | xargs) + bpath=$(echo $NUMBER | sed 's/ /_/g') + done + + SECRET=$(./shell/diceware.sh 4 | xargs) + + boucle=$(bc -l <<< "$boucle + 1") + + log "__SUB:sms_BILLET.sh: ->BILLET:$PHONE:$NUMBER:$VALbillet:$UNIT" + # CREATE "NUMBER SECRET" ACCOUNT for G1 transfert + TRANSAC=$(bc -l <<< "scale=2; $VIR / $NBbillets") + BILLETPUBKEY=$(./silkaj/silkaj generate_auth_file --auth-scrypt -salt="$NUMBER" -password="$SECRET") + # COPY authfile for 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" + ./shell/natools.py encrypt -p $NODE_G1PUBKEY -i "./authfile" -o "./billets/$bpath/note.authfile.$NODE_UIDNA.crypt" + rm -f "./authfile" + + 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 + # 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 "$VALbillet" > "./billets/$bpath/note.love" + echo "$TRANSAC" > "./billets/$bpath/note.g1" + echo "$BILLETPUBKEY" > "./billets/$bpath/note.pubkey" + log "Remplissage: $TRANSAC G1... $BILLETPUBKEY = $PAY" + + # CREATION FICHIER IMAGE BILLET + $(./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" --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" + # Copy & Send produced 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) + + # POUR IMPRIMER LES BILLETS! Brancher votre imprimante, configurer cups, activer code lp ;) + num=$(date +%Y%m%d) + 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 << +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....." + + 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... +Support: $ADMINPSEUDO ($ADMINPHONE) +" + + sms_SEND "$phone" "$mess" + # 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 +else + text="Solde: $AMOUNTLOVE LOVE ($AMOUNTG1 G1 = $AMOUNTDU DU) +Insuffisant pour créer $NBbillets billet(s) de $VALbillet $UNIT +(= $VIR G1 + Commission $BILLCOM G1)" + sms_ERROR "$phone" "$text" + + sms_SEND "$phone" "Rechargez votre porte-monnaie! +https://g1.duniter.fr/api/#/v1/payment/$PUBKEY?amount=$VIR" +fi + +log "__SUB:sms_BILLET.sh: END sms_BILLET.sh" +log "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + +exit diff --git a/g1sms/sms_BILLETCHK.sh b/g1sms/sms_BILLETCHK.sh new file mode 100755 index 0000000..b0e0c1d --- /dev/null +++ b/g1sms/sms_BILLETCHK.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# If 4 words provided => Check if Billet exists and return BILLET AMOUNT VALUE +# If 7 words provided => if Billet exists, transfer AMOUNT to PHONE & destroy BILLET +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +source ./shell/init.sh +source ./shell/functions.sh +log "X sms_BILLETCHK.sh $0" + +PHONE="$1" +CODE="$2 $3" +SEC="$4 $5 $6 $7" + +# Construct billet path +bpath=$(echo "$CODE" | sed 's/ /_/g') + +if [ -d "./billets/$bpath" ] +then + SECRET=$(cat "./billets/$bpath/note.secret") + SALT=$(cat "./billets/$bpath/note.salt") + VALbillet=$(cat "./billets/$bpath/note.value") + UNIT=$(cat "./billets/$bpath/note.unit") + BILLETPUBKEY=$(cat "./billets/$bpath/note.pubkey") + + AMOUNTG1=$(./silkaj/silkaj amount "$BILLETPUBKEY") + log "Billet: $AMOUNTG1 ($VALbillet $UNIT): $BILLETPUBKEY" + + # NO GOOD SECRET + if [[ "$SEC" != "$SECRET" ]]; then + # SEND ACTUAL BILLET VALUE + mess="[G1SMS] +Billet de $VALbillet $UNIT Valide! +Valeur: $AMOUNTG1 G1 +https://www.g1sms.fr/contact" + sms_SEND "$PHONE" "$mess" + log "BILLETCHK: $VALbillet $UNIT ($AMOUNTG1 G1)" + log_history $PHONE "BILLET_CHK, $AMOUNTG1, $bpath" + else + # TRANSFER & DESTROY + sms_INIT_ACCOUNT "$PHONE" "NOSMS" + if [[ "$UNKNOWN" == "unknown" ]]; then + # 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:$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 + rm -Rf ./billets/$bpath + # DESTROY PUBLIC CACHE in /tmp + if [ -d "/tmp/billets_valides/$bpath" ]; then + rm -Rf /tmp/billets_valides/$bpath + fi + + SOLDE=$(./silkaj/silkaj amount "$PUBKEY") + + mess="[G1SMS] +ENCAISSEMENT de $VALbillet $UNIT ($AMOUNTG1 G1) +dans portefeuille $UIDNA ($PHONE) +OK! +Solde: $SOLDE G1" + sms_SEND "$PHONE" "$mess" + log "BILLETCHK DESTROY: $VALbillet $UNIT ($AMOUNTG1 G1)" + log "=> $PUBKEY" + log_history $PHONE "BILLET_CHK, $AMOUNTG1, $bpath, $PUBKEY" + else + sms_ERROR "$PHONE" "Erreur! Transaction Impossible! Valeur du G1Billet $AMOUNTG1 G1. Contactez $ADMINPSEUDO : $ADMINPHONE" + fi + fi +else + sms_SEND "$PHONE" "BILLET \"$CODE\" INCONNU !!" + log_history $PHONE "BILLET_CHK, ERROR, $bpath" +fi + +log "END sms_BILLETCHK.sh" +log "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" diff --git a/g1sms/sms_BILLET_MAKE.sh b/g1sms/sms_BILLET_MAKE.sh new file mode 100755 index 0000000..18c1493 --- /dev/null +++ b/g1sms/sms_BILLET_MAKE.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# Make Billet fabrique l'image de 6 billets de monnaie libre +# Date de validité de 6 mois à compter du premier jour du mois courant +############################################################################ +# INSTALLER convert et qrencode: sudo apt install imagemagick qrencode +# IMPRIMANTE (http://smspi:631/) : sudo apt install printer-driver-all cups +# https://junise.wordpress.com/2015/04/12/install-online-cups-printer-in-raspberry-pi/ +############################################################################ +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +# TEST: +# ./shell/sms_BILLET_MAKE.sh "nu me ro test" "se cr et" 100 LOVE 10.04 "https://g1sms.fr" G1SMS TEST +############################################################################ +source "./shell/init.sh" +source "./shell/functions.sh" + +NUMERO="$1" +SECRET="$2" +MONTANT="$3" +UNIT="$4" +JUNE="$5" +NOTERIB="$6" +MEMBER="$7" +TRANSAC="$8" +PHONE="$9" +log "X sudo ./shell/sms_BILLET_MAKE.sh \"$1\" \"$2\" \"$3\" \"$4\" \"$5\" \"$6\" \"$7\" \"$8\"" + +if [[ "$NOTERIB" == "" || "$MEMBER" == "" ]] +then + log "ERROR MAKE BILLET" + exit +fi + +# VALIDITY? Calculate 6 month period dates +cm=$(date +%m) +cy=$(date +%Y) +valid=$(bc <<< "$cm + 6") +if [ $valid -gt 12 ] +then + valid=$(bc <<< "$valid - 12") + year=$(bc <<< "$cy + 1") +else + year=$cy +fi +valid="0${valid:0:2}" +# ADD VALIDITY to convert: -pointsize 20 -draw 'text 380,410 "'"A encaisser avant le 01/$valid/$year"'"' \ + +# 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" +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) +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 -s 3 -o "/tmp/$NUMERO_NOTERIB.png" "$NOTERIB" + +# BILL PUBKEY means Someone can Add amount to it !!! +# Add verification QRCode +composite -compose Over -gravity NorthEast -geometry +50+25 "/tmp/$NUMERO_NOTERIB.png" "/tmp/$NUMERO.jpg" "/tmp/$NUMERO.jpg" + +# Add June logo +case "$MONTANT" in + 10) + convert "./shell/g1.png" -fuzz 20% -fill grey -opaque '#e5912b' "/tmp/g1.png" + ;; + 20) + convert "./shell/g1.png" -fuzz 20% -fill green -opaque '#e5912b' "/tmp/g1.png" + ;; + 50) + convert "./shell/g1.png" -fuzz 20% -fill orange -opaque '#e5912b' "/tmp/g1.png" + ;; + 100) + convert "./shell/g1.png" -fuzz 20% -fill blue -opaque '#e5912b' "/tmp/g1.png" + ;; + 200) + convert "./shell/g1.png" -fuzz 20% -fill purple -opaque '#e5912b' "/tmp/g1.png" + ;; + 500) + convert "./shell/g1.png" -fuzz 20% -fill red -opaque '#e5912b' "/tmp/g1.png" + ;; + 1000) + convert "./shell/g1.png" -fuzz 20% -fill black -opaque '#e5912b' "/tmp/g1.png" + ;; + *) + cp "./shell/g1.png" "/tmp/g1.png" + ;; +esac +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 +testdu=$( echo "${DUPART} < 1" | bc -l ) +if [[ "$testdu" -eq "1" ]]; then + DUPART="0${DUPART}" +fi + +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 "'"https://g1sms.fr _ G1Billet _ $JUNE G1"'"' \ +-pointsize 30 -draw 'text 60,100 "'"Identifiant: $NUMERO"'"' \ +-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 +# "CHK $NUMERO $SECRET" + +if [[ "$TRANSAC" == "TEST" ]]; then + exit +else + # Move billet to MEMBER folder 6 month later + mkdir -p "./billets/MEMBERS/$MEMBER/" + mv "/tmp/BILL.$year.$valid.$NUMERO.$MONTANT.$UNIT.jpg" "./billets/MEMBERS/$MEMBER/" + # Clean TEMP files + rm "/tmp/$NUMERO_NOTERIB.png" + rm "/tmp/$NUMERO.jpg" +fi + +log "END sms_BILLET_MAKE.sh" +log "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" diff --git a/g1sms/sms_COUNT.sh b/g1sms/sms_COUNT.sh new file mode 100755 index 0000000..db68e8c --- /dev/null +++ b/g1sms/sms_COUNT.sh @@ -0,0 +1,77 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +source ./shell/init.sh +source ./shell/functions.sh +log "X sms_COUNT.sh ($1=phone $2=NOSMS)" +PHONE=$1 +TODAY=$(date '+%Y%m%d') +# Initialise PHONE, PIN, PUBKEY, UNIT +sms_INIT_ACCOUNT "$PHONE" "NOSMS" +if [[ $UNKNOWN == "unknown" && "$PHONE" != "" ]]; then + sms_ERROR "$PHONE" "Porte-monnaie inconnu. Envoyez N (suivi de votre Pseudo membre) pour le créer." + exit +fi + +# Check account amount +declare -a accounting +accounting=($(check_account)) +log "$(declare -p accounting)" +AMOUNTG1=${accounting[0]} +AMOUNT=${accounting[1]} +UNIT=${accounting[2]} + +# SEARCH FOR VIREMENT +if [[ -f ./wallets/$PHONE/VIREMENTS.gpg ]]; then + echo "FOUND $file decrypting with Node key" + echo "${GPGPASS}" | gpg -d -q --output "/tmp/VIREMENTS.$PHONE" --yes --pinentry-mode loopback --passphrase-fd 0 "$file" + declare -a LIST + num=0 + cat /tmp/VIREMENTS.$PHONE | while read LIST; do + if [[ ${LIST[0]} -gt $TODAY ]]; then + ((num++)) + todo="$todo +${LIST[0]}: ${LIST[3]} G1 vers ${LIST[5]}" + fi + done + rm "/tmp/VIREMENTS.$PHONE" +fi + +# LOG +log "Solde = $AMOUNTG1 ($UNIT)" + +# If script control only run: NOSMS +if [ "$2" != "NOSMS" ]; then + if [[ "$AMOUNT" != "" ]]; then + mess="[G1sms+] +ID: $UIDNA +$AMOUNT $UNIT ($AMOUNTG1 G1) +=> $MEMBER +$MEMRIB +https://cesium.app" + # Send response SMS + sms_SEND "$PHONE" "$mess" + sms_SEND "$PHONE" "$PUBKEY" + + # CHECK NEXT VIREMENTS + if [[ $num -gt 0 ]]; then + sms_SEND "$PHONE" "Reste $num Virements récurrents +$(echo $todo | head -n 2) +... + +$(echo $todo | tail -n 1)"; + fi + log_history $PHONE "SOLDE, $AMOUNTG1" + else + sms_ERROR "$PHONE" "Problème de dialogue silkaj, Serveur $NEWDUNITER... Essayez dans 1 minute SVP..." + fi +else + echo $AMOUNTG1 +fi + +log "END sms_COUNT.sh" +log "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" +exit diff --git a/g1sms/sms_DESTROY.sh b/g1sms/sms_DESTROY.sh new file mode 100755 index 0000000..4b53d1c --- /dev/null +++ b/g1sms/sms_DESTROY.sh @@ -0,0 +1,78 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +source ./shell/init.sh +source ./shell/functions.sh +log "${c_yellow}__SUB:sms_DESTROY.sh: START ($1=phone, $2=uid)$c_" + +PHONE="$1" +MEMBERUID="$2" +TODAY=$(date '+%Y%m%d') + +if [[ -f "./wallets/$PHONE/VIREMENTS" ]]; then +# CHECK IF ALL DONE. + log "__SUB:sms_DESTROY.sh: FOUND "./wallets/$PHONE/VIREMENTS" decrypting with Node key" + echo "${GPGPASS}" | gpg -d -q --output "/tmp/VIREMENTS.$PHONE" --yes --pinentry-mode loopback --passphrase-fd 0 "./wallets/$PHONE/VIREMENTS.gpg" + for next in $(cat /tmp/VIREMENTS.$PHONE | cut -d ' ' -f 1); do + if [[ $next -ge $TODAY ]]; then + log "__SUB:sms_DESTROY.sh: VIREMENT $next >= $TODAY" + sms_ERROR "$PHONE" "Votre portefeuille comporte des virements non réglés... FERMETURE IMPOSSIBLE!" + exit + else + log "__SUB:sms_DESTROY.sh: VIREMENT $next ${c_green}OK$c_" + fi + done +fi + +# Initialise PHONE, PIN, PUBKEY, UNIT ... +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 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") + PAY=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$GETLIMIT" --output="$MEMRIB" --comment="[G1sms+] Wallet DESTROY $MEMBER $MEMBERUID" -y) + sleep 5 + back=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$LIMIT" --output="$NODEPUB" --comment="[G1sms+] Wallet DESTROY Send $LIMIT To NODE" -y) + + 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) + move_g1cents "$PHONE" "$MEMRIB" "$cents" + 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 : ${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 "${c_red}__SUB:sms_DESTROY.sh: END WITH ERRORS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~$c_" + exit + fi +fi + +# Remove contact from database +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/g1sms/sms_EMAIL.sh b/g1sms/sms_EMAIL.sh new file mode 100755 index 0000000..f70b16b --- /dev/null +++ b/g1sms/sms_EMAIL.sh @@ -0,0 +1,58 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +# 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" +mail="$2" + +MAILFILE="./wallets/$phone/$phone.email" # Contains the member EMAIL (Send BILLET) + +# Initialise PHONE, PIN, PUBKEY, UNIT ... +sms_INIT_ACCOUNT "$phone" "NOSMS" +if [[ $UNKNOWN == "unknown" || "$MEMBER" == "" ]]; then + sms_ERROR "$phone" "Porte-monnaie non identifié. +Envoyez N suivi de votre pseudo membre (en respectant Majuscule et minuscule)." + exit +fi + +if [[ "$mail" != "" ]]; then + echo "$mail" > "$MAILFILE" + ./shell/natools.py encrypt -p $NODE_G1PUBKEY -i "$MAILFILE" -o "$MAILFILE.node.crypt" + echo "" > "$MAILFILE" + log "__SUB:sms_EMAIL.sh.sh: EMAIL $MEMBER ($PHONE) NOUVEAU: $mail... Publishing to IPFS" + ipfs_node_wallets_add +else + mail=$MAIL +fi + +# SEND EMAIL WITH ssmtp +SUBJECT="[G1sms+] $MEMBER, Message de votre portefeuille monnaie libre $UIDNA ($PHONE)" +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 ($ADMINPHONE)" +cat ./email.txt | sed s/EMAIL/"${mail}"/g | sed s/SUBJECT/"${SUBJECT}"/g | sed s/MESSAGE/"${MESSAGE}"/g | ssmtp ${mail} +mpack -s "[G1sms+] $PHONE, $UIDNA :: Envoyer 'BILL nnn' à $MASTERPHONE pour fabriquer des G1Billets (ci-joint exemple de verso)" ./Dos_G1Billets.odt ${mail} + +log "__SUB:sms_EMAIL.sh.sh: Send welcome EMAIL to $mail via ssmtp" +log_history $PHONE "EMAIL, $mail" + +mess="[G1sms+] +$MEMBER +Votre email est : $mail +Mettez le à jour, si cela est nécessaire..." + +sms_SEND "$phone" "$mess" + + +log "END sms_EMAIL.sh" +log "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" +exit diff --git a/g1sms/sms_ERROR.sh b/g1sms/sms_ERROR.sh new file mode 100755 index 0000000..6bac774 --- /dev/null +++ b/g1sms/sms_ERROR.sh @@ -0,0 +1,16 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +source ./shell/init.sh +source ./shell/functions.sh +log "X sms_ERROR.sh ($1=phone, $2=message)" + +MESS="Commande inconnue $2." + +# Send response SMS +$(sms_ERROR "$1" "$MESS") + +exit diff --git a/g1sms/sms_G1TAG.sh b/g1sms/sms_G1TAG.sh new file mode 100755 index 0000000..8e7bef9 --- /dev/null +++ b/g1sms/sms_G1TAG.sh @@ -0,0 +1,302 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.2020 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +########################################################################################### +# == G1tag == +# IPFS ZEN WALLETS +# RJ: READ G1Tag +# BJ: WRITE G1Tag +# WRITE ACCESS ONLY for B possessor and NODE G1Tag Creator +# TODO: MAKE http API for G1Tag accessible through local ipfs gateway !!!! +# https://github.com/typicode/lowdb USE json and ipfs DAG??! +# +# TAG 250 => Imprime un G1Tag rempli de 250 UNIT +# TAG 2 100 => Imprime 100 G1Tag BON de 2 UNIT +# PHONE any ./wallets/IDs +# TODO: for multi-channel -> Use HASHLINK + UIDNA + NODE_UIDNA + AMOUNT ... +########################################################################################### +source ./shell/init.sh +source ./shell/functions.sh +log "__SUB:sms_G1TAG.sh: START ($1=PHONE, $2=AMOUNT, $3=NUMBER)" + +PHONE=$1 +AMOUNT=$2 +if [[ "$AMOUNT" == "" ]]; then AMOUNT=0; fi +NUMBER=$3 +# DEFAULT TYPE IS PRINTED G1TAG +# BUT COULD BE USED TO CARRY VALUE INTO IPFS STORED FILES +# FIRST ATTEMPT IS TO COPY YOUTUBE INTO M4A AND LEND THEM G1. +TYPE=$4 # This is the type of passenger: YOUTUBE, NODE (EMPTY = default means sticker printed G1Tag) +# Give ipfs hash of any External ID like YOUTUBEID ;) +PASSENGER=$5 + +# == G1tag == +# IPFS G1sms Wallet to TAG creation/relation manager +# TODO Modulate access to TAGs with IPNS publish key cypher +# A/R: (G1TagID) +# B: (GPG Key for HUMAN WRITE access) +# J: (IPNS link to G1tag storage) +# MASTER: Global SWARM Access +############################################################################################### +# Initialize PHONE, PIN, PUBKEY, UNIT, MEMBER, MEMRIB, EMAIL, etc... +sms_INIT_ACCOUNT "$PHONE" "NOSMS" + +if [[ $UNKNOWN == "unknown" ]]; then + sms_ERROR "$PHONE" "Porte-monnaie inconnu. Envoyez N (suivi de votre Pseudo membre) pour le créer." + log "__SUB:sms_G1TAG.sh: Porte-monnaie inconnu" + exit +fi + +########################################################### +# CALCULATE if wallet have enough for VIR+PERCENT +AMOUNT=$2 # BE CAREFULL AMOUNT was changed by 1st sms_INIT_ACCOUNT!! +if [[ "$AMOUNT" == "" ]]; then AMOUNT=0; fi +if [[ ! $PASSENGER && "$NUMBER" != "" ]]; then + # MULTI TAG NUMBER ($NUMBER = How many tags to print) + AMOUNT=$(bc -l <<< "$AMOUNT * $NUMBER") +else + NUMBER=1 +fi +VIR=0 +accounting=($(make_accounting)) +log "__SUB:sms_G1TAG.sh: $(declare -p accounting)" +testmin=${accounting[0]} +VIR=${accounting[1]} +PERCENT=${accounting[2]} +CHARGE=${accounting[3]} +if [[ $testmin -eq 0 ]]; then + sms_SEND "$PHONE" "Le solde de votre Porte-monnaie est insuffisant. Minimum requis = ${CHARGE} + ${PERCENT} (+ ${LIMIT}) G1! Rechargez avec https://cesium.app" + exit +fi + +##### IS G1DAB NODE? +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 sur $DABnode non détectée!! Choisissez un autre G1Dab..." + log "__SUB:sms_G1TAG.sh: IMPRIMANTE G1Tag non détectée!!" + exit + fi + fi +fi + +# TODO: SEARCH PROXIMITY DAB LOCATION (GeoPoint + GPS)... +# for node in ./wallets_swarm/.*/*.where; do +# done +########################################################### +# silkaj NODE CHANGE !!! +#SILKAJNODE=$(./shell/checknodes.sh) +#log "NEW SILKAJ NODE: $SILKAJNODE" + +########################################### +# 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="$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" "$NODE_G1PUBKEY" "$cents" +fi + +############################################# +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++)) + # 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 in all SWARM! + 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 : 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 +TAGNODEID="./TAG/${RR}/TAG_nodeid" # G1sms+ NODE IPFS ID managing that G1Tag +TAGID="./TAG/${RR}/TAG_id" #Nom du TAG +TAGCURRENCY="./TAG/${RR}/TAG_currency" # ZEN (0.01 G1) +TAGAMOUNT="./TAG/${RR}/TAG_amount" # Tag amount. It is! +TAGTYPE="./TAG/${RR}/TAG_type" # G1 Tag type +TAGPASSENGER="./TAG/${RR}/TAG_passenger" # Reference to G1Tag owner/counter put in "./wallets/.$IPFSNODEID/TAG/${J}" +# ... GESTION DE LA CLEF DE PUBLICATION IPNS ".ipfs/keystore/${RR}" ... +TAGPUBLISH_B_GPG="./TAG/${RR}/TAG_publishkey.B.gpg" # ipns publish key B PGP cyphered +TAGPUBLISH_PHONE_CRYPT="./TAG/${RR}/TAG_publishkey.phone.crypt" # natools.py crypt with creator G1sms Wallet PUBKEY +TAGPUBLISH_NODE_CRYPT="./TAG/${RR}/TAG_publishkey.$NODE_UIDNA.crypt" # natools.py crypt with NODE G1sms Wallet PUBKEY +TAGPUBLISH_SWARM_CRYPT="./TAG/${RR}/TAG_publishkey.swarm.crypt" # natools.py crypt with SWARM G1sms Wallet PUBKEY +TAGN="./TAG/${RR}/TAG_n" # Tag modification number (0 first) +TAGIPNS="./TAG/${RR}/TAG_ipns" # /ipns/Qm... link to last G1Tag version +TAGCHAIN="./TAG/${RR}/TAG_chain" # contains IPFS current ipfs hash + + # WRITE MULTITAG FILES with AMOUNT + mkdir -p ./TAG/${RR} + + log "__SUB:sms_G1TAG.sh: G1Tag: $RR / ${NANODATE}" + log "__SUB:sms_G1TAG.sh: MEMRIB: $MEMRIB" + log "__SUB:sms_G1TAG.sh: A: ${AA}" + log "__SUB:sms_G1TAG.sh: B: ${BB}" + log "__SUB:sms_G1TAG.sh: USER_KEY: $TAGPUBLISH_B_GPG" + log "__SUB:sms_G1TAG.sh: PHONE G1WALLET_KEY: $TAGPUBLISH_PHONE_CRYPT" + log "__SUB:sms_G1TAG.sh: NODE G1WALLET_KEY: $TAGPUBLISH_NODE_CRYPT" + log "__SUB:sms_G1TAG.sh: SWARM G1WALLET_KEY: $TAGPUBLISH_SWARM_CRYPT" + #################### + + #################################################### + # IPFS files are created and calculated immutable I + #################################################### + # A or R is Human readable G1tag Name + echo "${AA}" > "$TAGID" + echo "0" > "$TAGN" + echo "${NANODATE}" > "$TAGDATE" + echo "${IPFSNODEID}" > "$TAGNODEID" + echo "${TYPE}" > "$TAGTYPE" + + echo "ZEN" > "$TAGCURRENCY" + ZEN=$(bc -l <<< "$2 * 100") # TODO, Test. Unit != G1 may lead to miss calculation BUG?? + echo "${ZEN}" > "$TAGAMOUNT" + + # Création de la clef ${R} IPNS qui permet de publier des changements sur le TAG! + if [[ ! -f "/home/$YOU/.ipfs/keystore/${RR}" ]]; then + su $YOU -c "ipfs key gen -t rsa -s 2048 ${RR}" + fi + + # GIVE QRCODE BJ ACCESS TO G1TAG + # Enregistrement de la clef de publication IPNS du wallet ${R} cryptée par B + echo "${BB}" | gpg -q --output "$TAGPUBLISH_B_GPG" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "/home/$YOU/.ipfs/keystore/${RR}" + + # GIVE PHONE CREATOR G1WALLET ACCESS TO ZEN TAG + # 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 "$TAGPUBLISH_PHONE_CRYPT" + + # GIVE NODE_UIDNA ACCESS TO ZEN TAG + ./shell/natools.py encrypt -p $NODE_G1PUBKEY -i "/home/$YOU/.ipfs/keystore/${RR}" -o "$TAGPUBLISH_NODE_CRYPT" + + # GIVE SWARM ACCESS TO ZEN TAG + ./shell/natools.py encrypt -p $SWARM_G1PUBKEY -i "/home/$YOU/.ipfs/keystore/${RR}" -o "$TAGPUBLISH_SWARM_CRYPT" + + ########################################################### + # TAG IPFS STORAGE & G1Tag IPNS PUBLISHING + ########################################################### + I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") + # MEMORIZE FOR CHAINING FUTURE CHANGES ( Block0 TAG version has no file published ;) + echo "${I}" > "$TAGCHAIN" + # Activate chain + I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") + # IPFS Hash for Immutable G1tag data + J=$(su $YOU -c "ipfs name publish -k ${RR} --quieter /ipfs/${I}") + echo "${J}" > "$TAGIPNS" + + # KEEP G1Tag J MEMORY in NODE ./wallets/.$IPFSNODEID/TAG/ (TODO: OPTIMIZE SWARM SYNC and REPUBLISH) + mkdir -p "./wallets/.$IPFSNODEID/TAG/" + # WRITE PASSENGER to J Link (G1Tag is stick to it: PHONE, NODE, FILE ) + # TODO USE SHA256 ID !!! + echo "$PHONE" > "./wallets/.$IPFSNODEID/TAG/${J}" + if [[ $PASSENGER ]]; then + HPASSENGER=$(echo -n $PASSENGER | sha256sum | cut -d ' ' -f 1) + echo "$HPASSENGER" > "./wallets/.$IPFSNODEID/TAG/${J}"; + fi + + ########################################################### + log "__SUB:sms_G1TAG.sh: TAG: ipfs ls /ipns/${J}" + if [[ ! $PASSENGER ]]; then + # QR CODE LECTURE + qrencode -s 5 -o "./TAG/${RR}/TAG_READ.png" "RJ:${RR}#${J}" + log "__SUB:sms_G1TAG.sh: CREATE READ QRCODE -> RJ: ${RR} # ipfs ls /ipns/${J}" + + # QR CODE ECRITURE + qrencode -s 5 -o "./TAG/${RR}/TAG_WRITE.png" "BJ:${BB}#${J}" + log "__SUB:sms_G1TAG.sh: CREATE WRITE QRCODE [] BJ: ${BB} # ipfs ls /ipns/${J}" + + # COMPOSE G1TAG PRINT + TAG_READ.png + TAG_WRITE.png + 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/G1Anar.png" "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png" +# fi + + + convert -pointsize 60 -fill black -gravity Center -draw 'text 0,-100 "'"$2"'"' "./TAG/${RR}/${RR}.png" "./TAG/${RR}/${RR}.png"; + + 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" + + # ROTATION (FIXE AVATAR & CHIFFRE)? + # convert "./TAG/${RR}/${RR}.png" -rotate -180 "./TAG/${RR}/${RR}.png" + # QL-700 PRINT PREPARE + + if [[ -f "./wallets/$PHONE/ipfsid.G1TAGNODE" ]]; then + destnode=$(cat "./wallets/$PHONE/ipfsid.G1TAGNODE") + if [[ "$destnode" == "" || "$destnode" == "$IPFSNODEID" ]]; then + log "__SUB:sms_G1TAG.sh: Local PRINT ${RR} # ipfs ls /ipns/${J}" + 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 NODE_G1PUBKEY ? + log "__SUB:sms_G1TAG.sh: Remote PRINT :: ./wallets/.$destnode/PRINT/${RR}.bin " + mkdir -p "./wallets/.$destnode/PRINT/" + # TODO: USE $DEST_G1PUBKEY is better + ./shell/natools.py encrypt -p $NODE_G1PUBKEY -i "./TAG/${RR}/${RR}.png" -o "./wallets/.$destnode/PRINT/${RR}.bin" + fi + else + # + log "__SUB:sms_G1TAG.sh: Becoming default PRINTER :: $IPFSNODEID" + echo "$IPFSNODEID" > "./wallets/$PHONE/ipfsid.G1TAGNODE" + 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 + destnode="$IPFSNODEID" + fi + fi +done + +#################################################### +# PRINT $PHONE WALLET PUBKEY +#################################################### +if [[ "$destnode" == "" || "$destnode" == "$IPFSNODEID" ]]; then + qrencode -s 5 -o "/tmp/G1PubQR.$PHONE.png" "$(cat ./wallets/$PHONE/$PHONE.pub)" + 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 -gravity Center "./wallets/$PHONE/$PHONE.avatar.png" "/tmp/G1PubQR.$PHONE.png" "/tmp/G1PubQR.$PHONE.png" + fi + 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.* +fi + +# Send dest SMS +mess_dest="[G1sms+] +Vos $NUMBER G1Tag(s) de $2 $UNIT sont imprimé(s). +Veuillez les récupérer ici: +$ADRESSE +Merci" +sms_SEND "$PHONE" "$mess_dest" + +ipfs_node_wallets_add + +log "__SUB:sms_G1TAG.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~" +exit diff --git a/g1sms/sms_NEW.sh b/g1sms/sms_NEW.sh new file mode 100755 index 0000000..4bfa424 --- /dev/null +++ b/g1sms/sms_NEW.sh @@ -0,0 +1,60 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +source ./shell/init.sh +source ./shell/functions.sh +log "${c_yellow}X sms_NEW.sh ($1=phone, $2=uid)$c_" + +PHONE="$1" +MEMBERUID="$2" + +# Initialise PHONE, PIN, PUBKEY, UNIT +sms_INIT_ACCOUNT "$PHONE" +if [[ "$MEMBERUID" != "" && "$MEMBERUID" != "N" && "$MEMBERUID" != "D" && "$MEMBERUID" != "NOUV" ]]; then + # UID RECEIVED in SMS + VIRDEST=$MEMBERUID + MEMRIB=$(sms_uid2key "$MEMBERUID" "$PHONE" "$PIN") + if [[ $MEMRIB == "" ]]; then exit; fi + MEMBER="$MEMBERUID" +fi + +sms_INIT_ACCOUNT "$PHONE" "NOSMS" +# Check account amount +countvalues=($(check_account)) +log "$(declare -p countvalues)" +AMOUNTG1=${countvalues[0]} +AMOUNT=${countvalues[1]} +UNIT=${countvalues[2]} + +mess="[G1sms+] +Id: $UIDNA +Solde: $AMOUNT $UNIT +DAB: $DABID +--- +https://cesium.app +* Identifiant =" +sms_SEND "$PHONE" "$mess" +sleep 2 +sms_SEND "$PHONE" "$PHONE" +sleep 2 +sms_SEND "$PHONE" "* Mot de passe =" +sleep 2 +sms_SEND "$PHONE" "$PIN" +sleep 2 +sms_SEND "$PHONE" "* Clef Publique (RIB) =" +sleep 2 +sms_SEND "$PHONE" "$PUBKEY" +sleep 2 +[[ $MEMRIB != "" ]] && sms_SEND "$PHONE" "Compte relié? $MEMBER $MAIL +$MEMRIB" + +# Add contact to database +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 "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" +exit + diff --git a/g1sms/sms_PAY.sh b/g1sms/sms_PAY.sh new file mode 100755 index 0000000..d989cc9 --- /dev/null +++ b/g1sms/sms_PAY.sh @@ -0,0 +1,98 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +source ./shell/init.sh +source ./shell/functions.sh +log "__SUB:sms_PAY.sh: START ($1=PHONE, $2=PHONEDEST, $3=AMOUNT)" + +phone="$1" +PHONEDEST="$2" + +# Initialise PHONE, PIN, PUBKEY, UNIT +sms_INIT_ACCOUNT "$phone" "NOSMS" +pin=$PIN +if [[ $UNKNOWN == "unknown" ]]; then + sms_ERROR "$phone" "Porte-monnaie inconnu. Envoyez N (suivi de votre Pseudo membre) pour le créer." + exit +fi + +########################################################### +# CALCULATE if wallet have enough for VIR+PERCENT +AMOUNT="$3" +accounting=($(make_accounting)) +log "__SUB:sms_PAY.sh: $(declare -p accounting)" +testmin=${accounting[0]} +VIR=${accounting[1]} +PERCENT=${accounting[2]} +CHARGE=${accounting[3]} +if [[ $testmin -eq 0 ]]; then + sms_ERROR "$phone" "Solde de votre Porte-monnaie G1sms insuffisant. Minimum: $CHARGE G1! Rechargez avec https://Cesium.app" + exit +fi + +# Add COUNTRY code to PHONEDEST + PHONEDEST INIT +PHONEDEST="$COUNTRY${PHONEDEST:1:10}" + +# CHECK if PHONEDEST have an account in IPFS G1sms+ SWARM +if [[ -f "./wallets_swarm/$PHONEDEST/$PHONEDEST.pub" ]] +then + PUBKEYDEST=$(cat "./wallets_swarm/$PHONEDEST/$PHONEDEST.pub") + UNITDEST=$(cat "./wallets_swarm/$PHONEDEST/$PHONEDEST.unit") +else + # NO, then create NEW Wallet + sms_INIT_ACCOUNT "$PHONEDEST" + # Refreshed new values + PUBKEYDEST="$PUBKEY" + UNITDEST="$UNIT" +fi + +# Payement +PAY=$(./shell/timeout.sh -t 20 ./silkaj/silkaj transaction --auth-scrypt -salt="$phone" -password="$pin" --amount="$VIR" --output="$PUBKEYDEST" --comment="[G1sms+] PAY" -y) +if [[ "$(echo $PAY | cut -d '|' -f 1)" == "KO" || "$PAY" == "" ]]; then + 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 + cents=$(echo $(bc -l <<< "scale=0; $VIR * 100") | cut -d '.' -f 1) + move_g1cents "$phone" "$PUBKEYDEST" "$cents" +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" + exit +else + # OK: Sync g1cents + cents=$(echo $(bc -l <<< "scale=0; $PERCENT * 100") | cut -d '.' -f 1) + move_g1cents "$phone" "$NODE_G1PUBKEY" "$cents" +fi + +# LOG ACCOUNT HISTORY EVENTS +log "__SUB:sms_PAY.sh: $1 => $2 = $3 $UNIT / SILKAJ == TxPay $PAY + TxCom $COM /" +log_history $phone "PAY, $VIR, $PHONEDEST, $PUBKEYDEST" + +# Send response SMS +mess_src="[G1sms+] +Envoi de $VIR G1 vers $PHONEDEST effectué! ++ Commission: $PERCENT G1" +sms_SEND "$phone" "$mess_src" + +# Send dest SMS +mess_dest="[G1sms+] Bonjour. +Un(e) ami(e) ($phone) vient de vous envoyer $VIR G1 sur votre portefeuille G1sms! +Envoyez D pour (D)étail. +A pour (A)ide..." +sms_SEND "$PHONEDEST" "$mess_dest" + + +log "__SUB:sms_PAY.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~ " +exit diff --git a/g1sms/sms_REC.sh b/g1sms/sms_REC.sh new file mode 100755 index 0000000..911e01d --- /dev/null +++ b/g1sms/sms_REC.sh @@ -0,0 +1,170 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +# RECORD RECURRENT PAYEMENTS WITH "Cesium+ ID" Pubkey TODO cron ./wallets/$PHONE/VIREMENTS, Fusion avec sms_VIR.sh +################################################################################ +source ./shell/init.sh +source ./shell/functions.sh +log "__SUB:sms_REC.sh: START ($1=PHONE, $2=VIRDEST, $3=AMOUNT, $4=PERIOD, $5=TIME)" + +PHONE="$1" +VIRDEST="$2" +AMOUNT=$3 +PERIOD="$4" +TIME=$5 + +case "$PERIOD" in +J|D) + PERIOD="jour"; + NEXTDATE="days"; + ;; +S|W) + PERIOD="semaine"; + NEXTDATE="weeks"; + ;; +M) + PERIOD="mois"; + NEXTDATE="months"; + ;; +A|Y) + PERIOD="année"; + NEXTDATE="years"; + ;; +*) + sms_ERROR "$PHONE" "Erreur sur la période de votre virement! Jour, Semaine, Mois, Année? Valeur: J,S,M,A (ex: REC 10 Fred J 3)" + exit; + ;; +esac + +########################################################### +# Initialise PHONE, PIN, PUBKEY, UNIT +sms_INIT_ACCOUNT "$PHONE" "NOSMS" +if [[ $MEMBER == "" ]]; then MEMBER=$UIDNA; fi +########################################################### +# CHECK FOR ERRORS +if [[ $UNKNOWN == "unknown" ]]; then + sms_ERROR "$PHONE" "Porte-monnaie inconnu. Envoyez N (suivi de votre Pseudo membre) pour le créer." + exit +fi +if [[ "$MEMBER" == "" ]]; then + sms_ERROR "$PHONE" "Aucun membre associé à votre Portefeuille!? Envoyer N suivi de votre Pseudo membre pour activer les virements récurrents..." + exit +fi + +########################################################### +# CALCULATE if wallet have enough for VIR+PERCENT +AMOUNT=$(bc -l <<< "$3 * $TIME") +accounting=($(make_accounting)) +log "__SUB:sms_REC.sh: $(declare -p accounting)" +testmin=${accounting[0]} +VIR=$(bc -l <<< "scale=2; ${accounting[1]} / $TIME") +PERCENT=${accounting[2]} +CHARGE=${accounting[3]} +if [[ $testmin -eq 0 ]]; then + sms_ERROR "$PHONE" "Votre Porte-monnaie G1sms doit comporter un solde suffisant! Au minimum $CHARGE G1! Rechargez par Cesium (ou contactez https://g1sms.fr)." + exit +fi + +########################################################### +# TODO Unify REC and VIR +# FIND VIRDEST into wallets, wallest-swarm OR duniter (silkaj) +if [[ "$VIRDEST" == "" || "$VIRDEST" == "$MEMBER" ]]; then + # VIR TO MEMBER PHONE OWNER + DESTMEM="$MEMBER" + DESTRIB="$MEMRIB" + log "__SUB:sms_REC.sh: SEND TO MEMBER related wallet!!! $DESTRIB " +else + log "__SUB:sms_REC.sh: SEARCH $VIRDEST related wallet!!! $DESTRIB " + DESTMEM="$VIRDEST" + # SEARCH IN WALLETS + LOCAL=$(grep -Rwl "$DESTMEM" ./wallets/*/*.uidname | tail -n 1 | cut -f 3 -d '/') + if [[ "$LOCAL" == "" ]]; then LOCAL=$(grep -Rwl "$DESTMEM" ./wallets/*/*.uidna | tail -n 1 | cut -f 3 -d '/'); fi + if [[ "$LOCAL" != "" ]]; then + # LOCAL G1sms account + DESTRIB=$(cat ./wallets/$LOCAL/$LOCAL.pub) + DESTPHONE=$LOCAL + log "__SUB:sms_REC.sh: FOUND LOCAL ($MASTERPHONE) G1sms+ wallet: $DESTRIB ($LOCAL)" + else + # SEARCH IN WALLETS SWARM (MEMBER THEN UIDNA) + INSWARM=$(grep -Rwl "$DESTMEM" ./wallets_swarm/*/*.uidname | tail -n 1 | cut -f 3 -d '/') + if [[ "$INSWARM" == "" ]]; then INSWARM=$(grep -Rwl "$DESTMEM" ./wallets_swarm/*/*.uidna | tail -n 1 | cut -f 3 -d '/'); fi + if [[ "$INSWARM" != "" ]]; then + REMOTENODE=$(cat ./wallets_swarm/$INSWARM/MASTERPHONE.sms) + DESTRIB=$(cat ./wallets_swarm/$INSWARM/$INSWARM.pub) + DESTPHONE=$INSWARM + log "__SUB:sms_REC.sh: FOUND SWARM ($REMOTENODE) G1sms+ wallet: $DESTRIB ($INSWARM)" + else + # SEARCH WITH SILKAJ + DESTRIB=$(./silkaj/silkaj id "$DESTMEM" | grep -w "$DESTMEM" | awk '{print $2}') + log "__SUB:sms_REC.sh: OUT OFF SWARM MEMBER wallet: $DESTRIB" + fi + fi +fi + +# ADD DATES TO VIREMENTS +if [[ "$DESTRIB" != "" ]]; then + log "__SUB:sms_REC.sh: TRAITEMENT DU VIREMENT DE $AMOUNT $UNIT = 1ER VIREMENT de $VIR G1 vers $VIRDEST ($DESTRIB) $TIME FOIS. OK..." + PAY=$(./shell/timeout.sh -t 20 ./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount="$VIR" --output="$DESTRIB" --comment="[G1sms+] REC 1/$TIME ($PERIOD)" -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_REC.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + exit + else + cents=$(echo $(bc -l <<< "scale=0; $VIR * 100") | cut -d '.' -f 1) + move_g1cents "$PHONE" "$DESTRIB" "$cents" + fi + log "__SUB:sms_REC.sh: UPDATE ./wallets/$PHONE/VIREMENTS with FUTURE PAYEMENTS? $PAY" + + ########### MAKE ./wallets/$PHONE/VIREMENTS for NEXT ONES + if [[ -f "./wallets/$PHONE/VIREMENTS.gpg" ]]; then + # DECYPHER FILE FOR CHANGE + echo "${GPGPASS}" | gpg -d -q --output "./wallets/$PHONE/VIREMENTS" --yes --pinentry-mode loopback --passphrase-fd 0 "./wallets/$PHONE/VIREMENTS.gpg" + fi + # WRITE NEW LINES INTO AN ARRAY FILE: VIREMENTS + boucle=$((TIME - 1)) + num=0 + while [[ boucle -gt 0 ]]; do + $((boucle --)) + $((num ++)) + NEXT=$(date --date="$num $NEXTDATE" '+%Y%m%d') + # ADD NEW LINE IN VIREMENTS + echo "$NEXT $MEMBER $PHONE $VIR $DESTRIB $DESTMEM $MEMBER#$TIME#$AMOUNT#$DESTMEM $boucle " >> ./wallets/$PHONE/VIREMENTS + + done + # CYPHER FILE + echo "${GPGPASS}" | gpg -q --output "./wallets/$PHONE/VIREMENTS.gpg" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "./wallets/$PHONE/VIREMENTS" + # EMPTY CLEAR FILE + log "__SUB:sms_REC.sh: $(cat ./wallets/$PHONE/VIREMENTS)" + echo "" > ./wallets/$PHONE/VIREMENTS + ########### + + log "__SUB:sms_REC.sh: .....................................OK!!!" + + # SEND ACK SMS + log "__SUB:sms_REC.sh: VIREMENTS RECURRENTS $MEMBER#$TIME#$AMOUNT#$DESTMEM => $VIR G1 pour $DESTMEM (pendant $TIME $PERIOD) + AJOUT" + mess="[G1sms+] +Virement de $VIR G1 pour $DESTMEM (pendant $TIME $PERIOD) +Total: $AMOUNT $UNIT + +$MEMBER#$TIME#$AMOUNT#$DESTMEM +$DESTRIB" + + sms_SEND "$PHONE" "$mess" + + 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 $UIDNA." + fi + +else + log "__SUB:sms_REC.sh: ERROR $MEMBER: $DESTMEM DESTRIB NOT FOUND" + mess="[G1sms+] Virement annulé... +Destinataire: $DESTMEM inconnu! Vérifiez son existence." + sms_SEND "$PHONE" "$mess" +fi + +log "__SUB:sms_REC.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~" diff --git a/g1sms/sms_SETUNIT.sh b/g1sms/sms_SETUNIT.sh new file mode 100755 index 0000000..145ddcf --- /dev/null +++ b/g1sms/sms_SETUNIT.sh @@ -0,0 +1,44 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +source ./shell/init.sh +source ./shell/functions.sh +log "X sms_SETUNIT.sh ($1=phone, $2=unit)" + +phone="$1" +unit="$2" +UNITFILE="./wallets/$phone/$phone.unit" + +# Initialise PHONE, PIN, PUBKEY, UNIT, HIST +sms_INIT_ACCOUNT "$phone" "NOSMS" + +if [[ $UNKNOWN == "unknown" ]]; then + sms_ERROR "$phone" "Porte-monnaie inconnu. Envoyez N (suivi de votre Pseudo membre) pour le créer." + exit +fi + +# No unit received +if [[ $unit == "U" || $unit == "" ]]; then + if [[ -f "$UNITFILE" ]]; then + unit=$(cat "$UNITFILE") + else + unit="$COIN"; + fi +fi + +echo "$unit" > "$UNITFILE" +log "G1sms wallet new $unit... IPFS SWARM publishing..." +ipfs_node_wallets_add + +mess="[G1sms+] +Unité de votre portefeuille: $unit" + +sms_SEND "$phone" "$mess" + +log "END sms_SETUNIT.sh" +log "~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + +exit diff --git a/g1sms/sms_VIR.sh b/g1sms/sms_VIR.sh new file mode 100755 index 0000000..63bd94c --- /dev/null +++ b/g1sms/sms_VIR.sh @@ -0,0 +1,104 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +source ./shell/init.sh +source ./shell/functions.sh +log "__SUB:sms_VIR.sh: START ($1=phone, $2=AMOUNT, $3=VIRDEST)" + +phone="$1" +AMOUNT="$2" +VIRDEST="$3" + +# Initialise PHONE, PIN, PUBKEY, UNIT +sms_INIT_ACCOUNT "$phone" "NOSMS" +if [[ $MEMBER == "" ]]; then MEMBER=$UIDNA; fi +member=$MEMBER +if [[ "$AMOUNT" == "" ]]; then + sms_ERROR "$phone" "Montant incorrect!! +Ex: +VIR 100, pour virer 100 $UNIT vers votre compte relié. +VIR 100 $ADMINPSEUDO, pour virer 100 $UNIT au membre administrateur de ce NODE G1sms+ ;)" + exit +fi + +########################################################### +# CALCULATE if wallet have enough for VIR+PERCENT +AMOUNT="$2" +accounting=($(make_accounting)) +log "__SUB:sms_VIR.sh: $(declare -p accounting)" +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 $VIR + $LIMIT G1! Rechargez par Cesium." + exit +fi + +########################################################### +# FIND VIRDEST into wallets, wallest-swarm OR duniter (silkaj) +if [[ "$VIRDEST" == "" || "$VIRDEST" == "$MEMBER" ]]; then + # VIR TO MEMBER PHONE OWNER + DESTMEM="$MEMBER" + DESTRIB="$MEMRIB" + log "__SUB:sms_VIR.sh: SEND TO MEMBER related wallet!!! $DESTRIB " +else + log "__SUB:sms_VIR.sh: SEARCH $VIRDEST related wallet!!! $DESTRIB " + DESTMEM="$VIRDEST" + # SEARCH IN WALLETS + LOCAL=$(grep -Rwl "$DESTMEM" ./wallets/*/*.uidname | tail -n 1 | cut -f 3 -d '/') + if [[ "$LOCAL" == "" ]]; then LOCAL=$(grep -Rwl "$DESTMEM" ./wallets/*/*.uidna | tail -n 1 | cut -f 3 -d '/'); fi + if [[ "$LOCAL" != "" ]]; then + # LOCAL G1sms account + DESTRIB=$(cat ./wallets/$LOCAL/$LOCAL.pub) + DESTPHONE=$LOCAL + log "__SUB:sms_VIR.sh: FOUND LOCAL ($MASTERPHONE) G1sms+ wallet: $DESTRIB ($LOCAL)" + else + # SEARCH IN WALLETS SWARM (MEMBER THEN UIDNA) + INSWARM=$(grep -Rwl "$DESTMEM" ./wallets_swarm/*/*.uidname | tail -n 1 | cut -f 3 -d '/') + if [[ "$INSWARM" == "" ]]; then INSWARM=$(grep -Rwl "$DESTMEM" ./wallets_swarm/*/*.uidna | tail -n 1 | cut -f 3 -d '/'); fi + if [[ "$INSWARM" != "" ]]; then + REMOTENODE=$(cat ./wallets_swarm/$INSWARM/MASTERPHONE.sms) + DESTRIB=$(cat ./wallets_swarm/$INSWARM/$INSWARM.pub) + DESTPHONE=$INSWARM + log "__SUB:sms_VIR.sh: FOUND SWARM ($REMOTENODE) G1sms+ wallet: $DESTRIB ($INSWARM)" + else + # SEARCH WITH SILKAJ + DESTRIB=$(./silkaj/silkaj id "$DESTMEM" | grep -w "$DESTMEM" | awk '{print $2}') + log "__SUB:sms_VIR.sh: OUT OFF SWARM MEMBER wallet: $DESTRIB" + fi + fi +fi + +if [[ "$DESTRIB" != "" ]]; then + 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 +Virement de $AMOUNT $UNIT ($VIR G1) +vers $DESTMEM ($DESTRIB) +OK! +$PAY" + sms_SEND "$PHONE" "$mess" + 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" + fi + cents=$(echo $(bc -l <<< "scale=0; $VIR * 100") | cut -d '.' -f 1) + move_g1cents "$PHONE" "$DESTRIB" "$cents" + else + new=$(./shell/checknodes.sh "BAN") + sms_SEND "$ADMINPHONE" "ADMIN! Problème de payement avec silkaj (changement de serveur $new): $PAY"; + fi +else + log "__SUB:sms_VIR.sh: ERROR $MEMBER: $DESTMEM DESTRIB NOT FOUND" + mess="[G1sms+] Virement annulé... +Membre: $DESTMEM inconnu! Vérifiez son existence." + sms_SEND "$PHONE" "$mess" +fi + +log "__SUB:sms_VIR.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~" +exit diff --git a/g1sms/sms_WHERE.sh b/g1sms/sms_WHERE.sh new file mode 100755 index 0000000..b998159 --- /dev/null +++ b/g1sms/sms_WHERE.sh @@ -0,0 +1,56 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +################################################################################ +# is there ADMINPSEUDO-UIDNATAIL in ./wallets_swarm/.*/*.uidna ?" +source ./shell/init.sh +source ./shell/functions.sh +log "__SUB:sms_WHERE.sh: START ($1=PHONE $2=askeduidna)" + +phone="$1" +askeduidna="$2" + +# Initialise PHONE, PIN, PUBKEY, UIDNA, UIDNAFILE ... +sms_INIT_ACCOUNT "$phone" "NOSMS" +if [[ "$UNKNOWN" == "unknown" ]]; then + sms_ERROR "$phone" "Porte-monnaie non identifié! +Envoyez N pour créer votre portefeuille G1sms" + exit +fi + +if [[ "$askeduidna" == "" ]]; then #SELF + if [[ -f "./wallets/.$IPFSNODEID/$IPFSNODEID.uidna" ]]; then + nodeuidnafile="./wallets/.$IPFSNODEID/$IPFSNODEID.uidna" + uidna=$(cat $nodeuidnafile) + fi +else + nodeuidnafile=$(grep -Rwl "$askeduidna" ./wallets_swarm/.*/*.uidna) + uidna=$(cat $nodeuidnafile) +fi + +if [[ -f $nodeuidnafile && "$uidna" != "" ]]; then + ipfsnodeid=$(echo $nodeuidnafile | cut -d '/' -f 3 | cut -d '.' -f 2 ) + echo $uidna > ./wallets/$PHONE/uidna.G1TAGNODE + echo $ipfsnodeid > ./wallets/$PHONE/ipfsid.G1TAGNODE + log "__SUB:sms_WHERE.sh: Distributeur de G1Tag $uidna : $ipfsnodeid " + I=$(ipfs_node_wallets_add) + log_history $PHONE "G1TagNode, $uidna, $ipfsnodeid" +else + log "__SUB:sms_WHERE.sh: ERROR Distributeur de G1Tag $askeduidna inconnu ???" + sms_ERROR "$PHONE" "Désolé. Aucun Distributeur de G1Tag : $askeduidna !!!" + log "__SUB:sms_WHERE.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + exit +fi + +mess="[G1sms+] $MEMBER +Votre distributeur de G1Tag par défaut est +$uidna ($ipfsnodeid), situé: +$(cat ./wallets_swarm/.$ipfsnodeid/$ipfsnodeid.where)" + +sms_SEND "$PHONE" "$mess" + + +log "__SUB:sms_WHERE.sh: END ~~~~~~~~~~~~~~~~~~~~~~~~~~~~" +exit diff --git a/g1sms/tag_LOAD_passenger.sh b/g1sms/tag_LOAD_passenger.sh new file mode 100755 index 0000000..fdde8d7 --- /dev/null +++ b/g1sms/tag_LOAD_passenger.sh @@ -0,0 +1,164 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +########################################################################################### +# LOAD MUSIC FILE IN G1TAG... + SHELL OPCODE INJECTED INTO G1TAG +# sudo pip3 install duniterpy +########################################################################################### +# ipfs ls /ipns/QmY6ooFcsGXY4VSindqKMz9GvrprFXY32RrsTmqvVTYQX5 +# QmZ3RfWk1u5LEGYLHA633B5TNJy3Du27K6Fny9wcxpowGS 4 TAG_amount +# QmXizDydPuiBd1V7JBVY5kdppShm9xdk2aoYj7c8V8Foxe 47 TAG_chain +# QmeHHBZKtLJHr11rwXKeimwDE4i3nLMy2VPkWZsNaFasg1 4 TAG_currency +# QmSjBDpjnoxnQT5RWRnyLxqwE3ovSRVb7xjwZoiufZAv3E 39 TAG_id +# QmUQcSjQx2bg4cSe2rUZyQi6F8QtJFJb74fWL7D784UWf9 2 TAG_n +# QmdbdBWv4SygqaaeWHAvABiQAa3faf4ncfSyzRnx8BDdCc 20 TAG_nanodate +# QmbN6gNM2vjLj7yaJ6xJcySDxmuSK2eB9ZDv5dpj2bo5pM 47 TAG_nodeid +# QmXaMzRqhEs4cQMRN18FWaCeqGmrDBfV8hTkbfQuBCXnnA 1243 TAG_publishkey.swarm.crypt +# QmWHsRZCTSjSxnp1Qm8WcmHNNQTJwDS2ukLE7NTccc3Kp9 1304 TAG_publishkey.B.gpg +# TAG_passenger, TAG_file is used to attach G1Tag to file. +# ADD A PASSENGER FILE (Web2.0ID) INTO a G1Tag + Add INIT credit/debit values to live in SWARM. +# GRAB a G1Tag CAPSULE + PUT A PASSENGER MUSIC FILE IN IT +#### TODO USE "ipfs dag" + json +# { +# "type": "REC_YOUTUBE", +# "search": "${MUSICFILE}", +# "id": "vLXHXGoXuBU", +# "title": "Tale Of Us - Oliver Koletzki - Miss Monique - More Artist • New Life III (DifferentSound Mix)", +# "size": 123, +# "debit": 10, +# "credit": 1, +# "file": { +# "ld": "LDhashIPFS", +# "sd": "SDhashIPFS", +# "hd": "HDhashIPFS" +# }, +# "g1tag": "RR", +# "ipns": "J", +# "ld": "ZEN", +# "sd": "ZEN", +# "hd": "EUR" +# } +# +############################################################################################################# +# ./shell/tag_LOAD_passenger.sh G1TagIPNS FileID MusicFile MASTERKEY +JSOURCE=$1 +TUBEID=$2 +MUSICFILE=$3 +KEYFILE=$4 +# EXTENSION (Define Debit for Hosting / Credit for Reading) +DEB=$5 +CRED=$6 +if [[ ! $DED ]]; then DED=10; fi +if [[ ! $CRED ]]; then CRED=1; fi +if [[ ! -f "$KEYFILE" || ! -f "$MUSICFILE" || ! -f "./g1sms.pub.key" ]]; then "Do you know what you are doing? MUSICFILE=$MUSICFILE? KEYFILE=$KEYFILE?"; exit; fi + +############################################# +############## INIT & root check +NANODATE=$(date -u +%s%N) +echo "__SUB:tag_LOAD_passenger.sh: LOAD \"$MUSICFILE\" into REC G1Tag $JSOURCE indexed by $TUBEID (using $KEYFILE)... $NANODATE" +if [[ "$USER" != "root" ]]; then echo "__SUB:tag_LOAD_passenger.sh: Hey, $USER you must be root. 'sudo ./shell/tag_LOAD_passenger.sh ...' ?"; exit; fi + +############################################# +############## CHECK ipfs daemon user +YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) +if [[ "$YOU" == "" || "$YOU" == "root" ]]; then echo "__SUB:tag_LOAD_passenger.sh: BAD IPFS. Aucune installation IPFS satisfaisante ici... Ciao $YOU !"; exit; fi +IPFSNODEID=$(su $YOU -c "ipfs id -f='\n'") + +###################################################### +############## EXTRACT $JSOURCERR key, amount, nodeid +JSOURCERR=$(su $YOU -c "ipfs cat /ipns/$JSOURCE/TAG_id | sed s/\ //g"); +if [[ "$JSOURCERR" == "" ]]; then echo "__SUB:tag_LOAD_passenger.sh: G1TAG DETRUIT. Aucun G1Tag /ipns/$JSOURCERR ici... Ciao."; exit; fi +mkdir -p ./TAG/${JSOURCERR}; rm -f ./TAG/${JSOURCERR}/* +echo "__SUB:tag_LOAD_passenger.sh: LOG. Hey You get a G1Tag!! GET IT now: ipfs get --output=./TAG/${JSOURCERR}/ /ipns/$JSOURCE" +chown -R $YOU ./TAG/${JSOURCERR}/ +su $YOU -c "ipfs get --output=./TAG/${JSOURCERR}/ /ipns/$JSOURCE" 2>&1 +JSOURCEPUBLISHKEY="./TAG/${JSOURCERR}/TAG_publishkey.swarm.crypt" +JSOURCEVALUE=$(cat ./TAG/${JSOURCERR}/TAG_amount) +TAGNODEID=$(cat ./TAG/${JSOURCERR}/TAG_nodeid) +TAGPASSENGER="./TAG/${JSOURCERR}/TAG_passenger" # contains HASH for PASSENGER FILE (CRYPT & PUBLISH) + +############################################# +# CAN IT LOAD PASSENGER ? +if [[ ! -f $TAGPASSENGER ]]; then + echo "__SUB:tag_LOAD_passenger.sh: G1TAG transmis pas encore transformé en REC TAG... Ciao $YOU !"; + exit +else + passenger=$(cat $TAGPASSENGER) + if [[ "$passenger" != "READY" ]]; then echo "__SUB:tag_LOAD_passenger.sh: REC TAG not READY ($passenger)!"; exit; # COMMENT TO ALLOW REWRITE + fi +fi + +############################################# +# ONLY CREATOR NODE CAN LOAD G1TAG +if [[ "$IPFSNODEID" != "$TAGNODEID" ]]; then + echo "__SUB:tag_LOAD_passenger.sh: Ce G1Tag est géré par $TAGNODEID (vous êtes $IPFSNODEID)" + exit +fi + +############################################# +############## EXTRACT $JSOURCERR PUBLISH KEY +if [[ -f "$KEYFILE" ]]; then + ./shell/natools.py decrypt -k "$KEYFILE" -i "$JSOURCEPUBLISHKEY" -o "/home/$YOU/.ipfs/keystore/$JSOURCERR" +else + echo "__SUB:tag_LOAD_passenger.sh: KO. La clef $KEYFILE fournie pour ce G1Tag $JSOURCERR est inexistante. Procurez-vous un portefeuille monnaie libre sur https://g1sms.fr" + exit +fi + +############################################# +############## G1TAG OPERATION +NN=$(cat ./TAG/${JSOURCERR}/TAG_n); ((NN++)); echo "$NN" > "./TAG/${JSOURCERR}/TAG_n" + +TAGTYPE="./TAG/${JSOURCERR}/TAG_type" # contains PASSENGER TYPE ("" = G1, YOUTUBE, any "REC SRC") +TAGPASSENGERID="./TAG/${JSOURCERR}/TAG_passenger_id" # contains PASSENGER ID (depending TYPE) YoutubeID, + +TAGPASSENGERCRYPT="./TAG/${JSOURCERR}/TAG_passenger.crypt" # contains HASH for PASSENGER FILE natools crypt with MASTERKEY +TAGPASSENGERDEBIT="./TAG/${JSOURCERR}/TAG_passenger_debit" # Countains amount Passenger is Paying Daily to SWARM IPFS Nodes (PIN) +TAGPASSENGERCREDIT="./TAG/${JSOURCERR}/TAG_passenger_credit" # Countains amount Node G1Tag must pay to PLAY file passenger +TAGPASSENGERSIZE="./TAG/${JSOURCERR}/TAG_passenger_size" # contains File Size in Mo + +echo "REC" > $TAGTYPE +echo "$TUBEID" > $TAGPASSENGERID + +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) +NODE_G1PUBKEY=$(cat "./g1sms.pub.key") +./shell/natools.py encrypt -p "$NODE_G1PUBKEY" -i "$TAGPASSENGER" -o "$TAGPASSENGERCRYPT" +echo "LOADED" > $TAGPASSENGER + +echo "$DEB" > $TAGPASSENGERDEBIT +echo "$CRED" > $TAGPASSENGERCREDIT + +############################################# +echo "${NANODATE}" > "./TAG/${JSOURCERR}/TAG_nanodate" +I=$(su $YOU -c "ipfs add -qr ./TAG/${JSOURCERR} | tail -n 1") +# RECORD TAG_chain And HASH again before publish +echo "$I" > "./TAG/${JSOURCERR}/TAG_chain" +I=$(su $YOU -c "ipfs add -qr ./TAG/${JSOURCERR} | tail -n 1") +# IPNS $JSOURCERR PUBLISH +J=$(su $YOU -c "ipfs name publish -k ${JSOURCERR} --quieter /ipfs/${I}") +# TODO rm "/home/$YOU/.ipfs/keystore/$JSOURCERR" + +# WRITE FILE REC INDEX IN NODE G1TAG REF. +mkdir -p ./wallets/.$IPFSNODEID/TAG/ +echo "$TUBEID" > "./wallets/.$IPFSNODEID/TAG/${J}.youtubeid" + +########################## +# REFRESH SWARM +########################## +IWALLETS=$(su $YOU -c "ipfs add -rHq './wallets' | tail -n 1") + +# CHAIN STATE FOR $IPFSNODEID +echo $IWALLETS > ./wallets/.$IPFSNODEID.wallets.chain +echo "__SUB:tag_LOAD_passenger.sh: NEW './wallets' HASH ipfs ls $IWALLETS" + +# PUBLISH IPNS NODE WALLETS +NODEWALLETS=$(su $YOU -c "ipfs name publish --quieter /ipfs/$IWALLETS") +echo "__SUB:tag_LOAD_passenger.sh: YOUTUBE REC G1 TAG LOADED ($TAGPASSENGERCRYPT) <<<<<< https://youtube.com/watch?v=$TUBEID" +echo "__SUB:tag_LOAD_passenger.sh: ipfs cat /ipns/$NODEWALLETS/.$IPFSNODEID/TAG/${J}.youtubeid" +exit +echo "__SUB:tag_LOAD_passenger.sh: ZEN BALANCE: $JSOURCEVALUE Zen. HEB: $DEB / PLAY: $CRED" +exit diff --git a/g1sms/tag_OP.sh b/g1sms/tag_OP.sh new file mode 100755 index 0000000..59ccb2a --- /dev/null +++ b/g1sms/tag_OP.sh @@ -0,0 +1,168 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.2020 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +########################################################################################### +# tag_OP.sh OPERATION ON G1TAG... +# sudo pip3 install duniterpy +########################################################################################### +# ipfs ls /ipns/QmY6ooFcsGXY4VSindqKMz9GvrprFXY32RrsTmqvVTYQX5 +# QmZ3RfWk1u5LEGYLHA633B5TNJy3Du27K6Fny9wcxpowGS 4 TAG_amount +# QmXizDydPuiBd1V7JBVY5kdppShm9xdk2aoYj7c8V8Foxe 47 TAG_chain +# QmeHHBZKtLJHr11rwXKeimwDE4i3nLMy2VPkWZsNaFasg1 4 TAG_currency +# QmSjBDpjnoxnQT5RWRnyLxqwE3ovSRVb7xjwZoiufZAv3E 39 TAG_id +# QmUQcSjQx2bg4cSe2rUZyQi6F8QtJFJb74fWL7D784UWf9 2 TAG_n +# QmdbdBWv4SygqaaeWHAvABiQAa3faf4ncfSyzRnx8BDdCc 20 TAG_nanodate +# QmbN6gNM2vjLj7yaJ6xJcySDxmuSK2eB9ZDv5dpj2bo5pM 47 TAG_nodeid +# QmXaMzRqhEs4cQMRN18FWaCeqGmrDBfV8hTkbfQuBCXnnA 1243 TAG_publishkey.swarm.crypt +# QmWHsRZCTSjSxnp1Qm8WcmHNNQTJwDS2ukLE7NTccc3Kp9 1304 TAG_publishkey.B.gpg +# ... +# TAG_passenger, TAG_file is used to attach G1Tag to file. +# +# TRANSFERT ZEN FROM G1Tag to G1Tag + +# G1Tag J References IPNS G1 Tag link +JSOURCE=$1 +JDEST=$2 +# Zen Amount to transfert +VALUE=$3 +# Needed to Open ipfs publish Key +KEYFILE=$4 + +############################################ +############## INIT & root check +NANODATE=$(date -u +%s%N) +echo "__SUB:tag_OP.sh: TRANSFER from $JSOURCE (1) to $JDEST (2) G1Tag = $VALUE (3) using \"$KEYFILE\" (4)... GO... $NANODATE" +if [[ "$USER" != "root" ]]; then echo "__SUB:tag_OP.sh: Hey, $USER you must at least be admin of your system. sudo -s ?"; exit; fi + +############################################# +############## CHECK ipfs daemon user +YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) +if [[ "$YOU" == "" || "$YOU" == "root" ]]; then echo "__SUB:tag_OP.sh: BAD IPFS. Aucune installation IPFS satisfaisante ici... Ciao $YOU !"; exit; fi +IPFSNODEID=$(su $YOU -c "ipfs id -f='\n'") + +############################################# +############## SOURCE EXTRACTION +JSOURCERR=$(su $YOU -c "ipfs cat /ipns/$JSOURCE/TAG_id | sed s/\ //g"); +############################################# +############## GOOD or BAD ? +if [[ "$JSOURCERR" == "" ]]; then echo "__SUB:tag_OP.sh: G1TAG DETRUIT. Aucun G1Tag /ipns/$JSOURCERR ici... Ciao."; exit; fi +echo "__SUB:tag_OP.sh: LOG. SOURCE G1Tag OK!! GREAT... Retrieving it all: ipfs get --output=./TAG/${JSOURCERR}/ /ipns/$JSOURCE" +mkdir -p ./TAG/${JSOURCERR}; rm -f ./TAG/${JSOURCERR}/* +chown -R $YOU ./TAG/${JSOURCERR}/ +su $YOU -c "ipfs get --output=./TAG/${JSOURCERR}/ /ipns/$JSOURCE" +JSOURCEPUBLISHKEY="./TAG/${JSOURCERR}/TAG_publishkey.swarm.crypt" +JSOURCEVALUE=$(cat ./TAG/${JSOURCERR}/TAG_amount); + +############################################# +############## No JDEST, then return $JSOURCEVALUE +if [[ "$JDEST" == "" ]]; then echo "__SUB:tag_OP.sh: OK. G1Tag $JSOURCE VALUE = $JSOURCEVALUE Zen"; exit; fi + +############################################# +############## TEST IF $VALUE IS AVAILABLE +FINALSOURCE=$( echo "${JSOURCEVALUE} - ${VALUE}" | bc -l ) +if [[ $FINALSOURCE -lt 0 ]]; then echo "__SUB:tag_OP.sh: KO. La valeur de ce G1Tag ne peut pas être : $FINALSOURCE Zen... Ciao $YOU !"; exit; fi + +############################################# +############## EXTRACT $JSOURCERR PUBLISH KEY +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 + echo "__SUB:tag_OP.sh: KO. La clef de dévérouillage pour $JSOURCERR est inexistante. Contact: https://g1sms.fr" + fi +fi + +############################################# +############## DESTINATION EXTRACTION +JDESTRR=$(su $YOU -c "ipfs cat /ipns/$JDEST/TAG_id | sed s/\ //g"); +if [[ "$JDESTRR" == "" ]]; then echo "__SUB:tag_OP.sh: BAD G1TAG. Aucun G1Tag /ipns/$JDESTRR ici... Ciao."; exit; fi +mkdir -p ./TAG/${JDESTRR}; rm -f ./TAG/${JDESTRR}/* +echo "__SUB:tag_OP.sh: LOG. Hey You get a G1Tag!! GREAT... ipfs get --output=./TAG/${JDESTRR}/ /ipns/$JDEST" +chown -R $YOU ./TAG/${JDESTRR}/ +su $YOU -c "ipfs get --output=./TAG/${JDESTRR}/ /ipns/$JDEST" +JDESTPUBLISHKEY="./TAG/${JDESTRR}/TAG_publishkey.swarm.crypt" +JDESTVALUE=$(cat ./TAG/${JDESTRR}/TAG_amount); +FINALDEST=$(echo "${JDESTVALUE} + ${VALUE}" | bc -l) +# EXTRACT $JSOURCERR PUBLISH KEY to "/home/$YOU/.ipfs/keystore/JSOURCE" +# EXTRACT PUBLISH KEY +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 + echo "__SUB:tag_OP.sh: KO. La clef de dévérouillage pour $JDESTRR est inexistante. Contact: https://g1sms.fr" + fi +fi + +###################################################################################################### +if [[ -f "/home/$YOU/.ipfs/keystore/$JDESTRR" && -f "/home/$YOU/.ipfs/keystore/$JSOURCERR" ]]; then +# IF PUBLISH key for BOTH G1TAG exists +############################################# +############## SOURCE OPERATION +NN=$(cat ./TAG/${JSOURCERR}/TAG_n); ((NN++)); echo "$NN" > "./TAG/${JSOURCERR}/TAG_n" +############################################# +# Destroy B Access ?!! +#rm -f ./TAG/${JSOURCERR}/TAG_publishkey.B.gpg +echo "$FINALSOURCE" > "./TAG/${JSOURCERR}/TAG_amount" +echo "${NANODATE}" > "./TAG/${JSOURCERR}/TAG_nanodate" # TODO: ACTIVATE NANODATE CONTROL / NODES MEDIANTIME +echo "${IPFSNODEID}" > "./TAG/${JSOURCERR}/TAG_writerid" + +if [[ "$JSOURCE" == "$JDEST" ]]; then + # PUT "READY" IN TAG_passenger (can now be loaded with a file), now actual IPFSNODEID is creator + echo "READY" > "./TAG/${JSOURCERR}/TAG_passenger" + echo "${IPFSNODEID}" > "./TAG/${JSOURCERR}/TAG_nodeid" + echo "__SUB:tag_OP.sh: ${IPFSNODEID} NODE created REC TAG. ${JSOURCERR}. READY to LOAD_passenger now!!" +fi + +SOURCENODEID=$(cat "./TAG/${JSOURCERR}/TAG_nodeid") +I=$(su $YOU -c "ipfs add -qr ./TAG/${JSOURCERR} | tail -n 1") +# RECORD TAG_chain And HASH again +echo "$I" > "./TAG/${JSOURCERR}/TAG_chain" +I=$(su $YOU -c "ipfs add -qr ./TAG/${JSOURCERR} | tail -n 1") +# IPNS $JSOURCERR PUBLISH +J=$(su $YOU -c "ipfs name publish -k ${JSOURCERR} --quieter /ipfs/${I}") +# CLEAN IPFS keystore +if [[ "${SOURCENODEID}" != "${IPFSNODEID}" ]]; then + rm -f "/home/$YOU/.ipfs/keystore/$JSOURCERR" +fi +echo "__SUB:tag_OP.sh: G1Tag $JSOURCERR value ($FINALSOURCE) :: su $YOU -c \"ipfs cat /ipns/$JSOURCE/TAG_amount\"" + +if [[ "$JSOURCE" != "$JDEST" ]]; then + ############################################# + ############## DESTINATION OPERATION + NN=$(cat ./TAG/${JDESTRR}/TAG_n); ((NN++)); echo "$NN" > "./TAG/${JDESTRR}/TAG_n" + ############################################# + # Destroy B Access ?!! + #rm -f ./TAG/${JDESTRR}/TAG_publishkey.B.gpg + echo "${FINALDEST}" > "./TAG/${JDESTRR}/TAG_amount" + ############################################################################################################################## + if [[ $FINALSOURCE -eq 0 ]]; then + echo "OK. G1Tag ${JSOURCERR} is empty destroying it!!"; + rm -f "./TAG/${JDESTRR}/TAG_id"; + fi + ############################################################################################################################## + echo "${NANODATE}" > "./TAG/${JDESTRR}/TAG_nanodate" + echo "${IPFSNODEID}" > "./TAG/${JDESTRR}/TAG_writerid" + DESTNODEID=$(cat "./TAG/${JDESTRR}/TAG_nodeid") + I=$(su $YOU -c "ipfs add -qr ./TAG/${JDESTRR} | tail -n 1") + # RECORD TAG_chain And HASH again + echo "$I" > "./TAG/${JDESTRR}/TAG_chain" + I=$(su $YOU -c "ipfs add -qr ./TAG/${JDESTRR} | tail -n 1") + # IPNS $JDESTRR PUBLISH + J=$(su $YOU -c "ipfs name publish -k ${JDESTRR} --quieter /ipfs/${I}") + if [[ "${DESTNODEID}" != "${IPFSNODEID}" ]]; then + rm -f "/home/$YOU/.ipfs/keystore/$JDESTRR" + fi + echo "__SUB:tag_OP.sh: G1Tag $JDESTRR value ($FINALDEST) :: su $YOU -c \"ipfs cat /ipns/$JDEST/TAG_amount\"" +fi + +echo "__SUB:tag_OP.sh: DONE. G1Tag balance updated: +$JSOURCERR (/ipns/$JSOURCE) : $JSOURCEVALUE => $FINALSOURCE +$JDESTRR (/ipns/$JSDEST) : $JDESTVALUE) => $FINALDEST" + +else + echo "__SUB:tag_OP.sh: NO OPERATION DONE" + +fi +###################################################################################################### diff --git a/g1sms/tag_PLAY_passenger.sh b/g1sms/tag_PLAY_passenger.sh new file mode 100755 index 0000000..39a42a9 --- /dev/null +++ b/g1sms/tag_PLAY_passenger.sh @@ -0,0 +1,68 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +########################################################################################### +# Find and PLAY (cat) passenger File OF G1Tag / REC TAG +# sudo pip3 install duniterpy +# READERID is PHONE or IPFSNODEID (G1 ./wallets/* ) +# JSOURCE is G1Tag IPNS link with PASSENGER +########################################################################################### +READERID=$1 +JSOURCE=$2 +KEYFILE="./g1sms.priv.key" +NODE_G1PUBKEY=$(cat "./g1sms.pub.key") + +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 + # INIT NODE G1TAG WITH 1000 zen + echo "__SUB:tag_PLAY_passenger.sh: $READERID ne possède pas de G1Tag sudo ./shell/sms_G1TAG.sh \"$READERID\" \"10\" \"1\" \"NODE\" \"$READERID\" " + exit +fi + +############################################# +############## INIT & root check +NANODATE=$(date -u +%s%N) +echo "__SUB:tag_PLAY_passenger.sh: $READERID IS READING $JSOURCE" + +############################################# +############## CHECK ipfs daemon user +YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1) +if [[ "$USER" != "root" ]]; then echo "__SUB:tag_PLAY_passenger.sh: Hey, $USER you must able to be root for now (try if sudo access is ok)"; fi +if [[ "$YOU" == "" || "$YOU" == "root" ]]; then echo "__SUB:tag_PLAY_passenger.sh: BAD IPFS. Aucune installation IPFS satisfaisante ici... Ciao $USER !"; exit; fi +IPFSNODEID=$(su $YOU -c "ipfs id -f='\n'") + +############################################# +JSOURCERR=$(su $YOU -c "ipfs cat /ipns/$JSOURCE/TAG_id | sed s/\ //g"); +if [[ "$JSOURCERR" == "" ]]; then echo "__SUB:tag_PLAY_passenger.sh: G1TAG DETRUIT. Aucun G1Tag /ipns/$JSOURCERR ici... Ciao."; exit; fi +mkdir -p ./TAG/${JSOURCERR}; rm -f ./TAG/${JSOURCERR}/* +echo "__SUB:tag_PLAY_passenger.sh: FOUND G1Tag... GETTING IT: ipfs get --output=./TAG/${JSOURCERR}/ /ipns/$JSOURCE" +chown -R $YOU ./TAG/${JSOURCERR}/ +su $YOU -c "ipfs get --output=./TAG/${JSOURCERR}/ /ipns/$JSOURCE" +JSOURCEPUBLISHKEY="./TAG/${JSOURCERR}/TAG_publishkey.swarm.crypt" + +TAGZEN=$(cat "./TAG/${JSOURCERR}/TAG_amount"); +DEB=$(cat "./TAG/${JSOURCERR}/TAG_passenger_debit") +CRED=$(cat "./TAG/${JSOURCERR}/TAG_passenger_credit") + +############################################## +# MAKE TRANSACTIONS +NODEZEN=$(cat "./wallets/$READERID/$READERID.g1cents") +uidna=$(cat "./wallets/$READERID/$READERID.uidna") +if [[ $ZEN -gt $CRED ]]; then + REZ=$((TAGZEN + CRED)) + + #echo "$REZ" > "./TAG/${JSOURCERR}/TAG_amount" + # TODO READER NEEDS ITS G1TAG + #./shell/tag_OP.sh "$READERIDTAG" "J2TAG" "$CRED" $KEYFILE +else + echo "Désolé ;( $READERID vous manquez de ZEN ($ZEN) pour vous payer la lecture de $JSOURCE ($CRED)" + echo "Rechargez avec un VIREMENT vers $uidna" +fi + + +# READ PASSENGER + diff --git a/g1sms/tag_READ.sh b/g1sms/tag_READ.sh new file mode 100755 index 0000000..1f4a2a7 --- /dev/null +++ b/g1sms/tag_READ.sh @@ -0,0 +1,250 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +########################################################################################### +########################################################################################### +echo "__SUB:tag_READ.sh: QRCODE READER : START" +source ./shell/init.sh +source ./shell/functions.sh + +# DOUCHETTE ES TU LA? +if [ ! $G1TX ]; then ./shell/parle.sh "Branchez votre lecteur de QR code!"; exit; fi + +# TABLEAU MEMOIRE DE SCAN +declare -a act +declare -a obj +declare -a val +./shell/parle.sh "Lecteur de G1 Tag. OK. Prêt" + +cat /dev/ttyACM0 | while read line; do + lon=${#line} + pref=$(echo $line | cut -d ":" -f 1) + qrvalue=$(echo $line | cut -d ":" -f 2) + log "__SUB:tag_READ.sh: SCAN /dev/ttyACM0 ($lon) :: $line" + + case $pref in + RJ) + ./shell/parle.sh "R J" + R=$(echo $qrvalue | cut -d '#' -f 1) + J=$(echo $qrvalue | cut -d '#' -f 2) + log "__SUB:tag_READ.sh: Lecture G1Tag $R $J" + # + ID=$(su $YOU -c "ipfs cat /ipns/$J/TAG_id"); + if [[ "$ID" == "" ]]; then + ./shell/parle.sh "G1 Tag déjà capturé, veuillez le détruire!"; + sms_SEND "$ADMINPHONE" "ADMIN! FRAUDE G1Tag RJ $R $J" + # TODO: ENQUETER auprès du CREATEUR de ce G1 Tag !! + continue + fi + RR=$(echo $ID | sed s/\ //g) + FID=$(echo $ID | awk '{print toupper($1)}') + 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/parle.sh "Rec Tag Machine $PASSENGER! Valeur $RVALUE $CUR"; + else + G1VAL=$(bc -l <<< "scale=2; $RVALUE / 100" | cut -d '.' -f 1) + log "__SUB:tag_READ.sh: G1Tag $FID. Valeur $RVALUE $CURRENCY = $G1VAL G1" + ./shell/parle.sh "G1 Tag $FID. Valeur $RVALUE $CUR convertible en $G1VAL June" + fi + cmd="RJ" + CASHBACK="" + val+=("$RVALUE") + ;; + + BJ) + ./shell/parle.sh "B J" + BB=$(echo $qrvalue | cut -d '#' -f 1) + J=$(echo $qrvalue | cut -d '#' -f 2) + log "__SUB:tag_READ.sh: Ouverture G1Tag $BB $J" + # + ID=$(su $YOU -c "ipfs cat /ipns/$J/TAG_id"); + FID=$(echo $ID | awk '{print toupper($1)}') + if [[ "$ID" == "" ]]; then + ./shell/parle.sh "G1 Tag inconnu! veuillez le détruire!"; + # sms_SEND "$ADMINPHONE" "ADMIN! FRAUDE G1Tag BJ $B $J" + # TODO: ENQUETER auprès du CREATEUR de ce G1 Tag !! + continue + fi + RR=$(echo $ID | sed s/\ //g) + 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 + log "__SUB:tag_READ.sh: Clef de publication IPFS $RR déjà présente" + else + rm /tmp/TAG_publishkey.B.gpg + su $YOU -c "ipfs get -o /tmp/ /ipns/$J/TAG_publishkey.B.gpg" + # CHECK IF OK + gpg -d --output /tmp/ipns.key --pinentry-mode=loopback --passphrase $BB /tmp/TAG_publishkey.B.gpg + if [[ ! -f /tmp/ipns.key ]]; then + ./shell/parle.sh "Erreur. Problème de déchiffrage PGP ${FID}! Vérifiez vos logs"; + log "__SUB:tag_READ.sh: ERROR! gpg -d --output /tmp/ipns.key --pinentry-mode=loopback --passphrase $BB /tmp/TAG_publishkey.B.gpg" + continue + fi + mv /tmp/ipns.key /home/$YOU/.ipfs/keystore/$RR + log "__SUB:tag_READ.sh: Récupération de la clef de publication $RR" + ./shell/parle.sh "Récupération clef de publication du G1 Tag ${FID}" + fi + if [[ "$PASSENGER" != "" ]]; then + log "__SUB:tag_READ.sh: !!!! REC Tag = $BVALUE $CURRENCY" + ./shell/parle.sh "Rec Tag Machine! Valeur $BVALUE $CUR"; + else + log "__SUB:tag_READ.sh: Ce G1 Tag contient $BVALUE $CURRENCY" + ./shell/parle.sh "Ce G1 Tag contient $BVALUE $CUR" + fi + cmd="BJ" + val+=("$BVALUE") + ;; + + *) + if [[ $lon -eq 44 ]]; then + ./shell/parle.sh "Portefeuille G1?" + J=$qrvalue + if [[ "$J" != "${obj[0]}" ]]; then + VALUE=$(./shell/timeout.sh -t 15 ./silkaj/silkaj amount $J) + + if [[ "$(echo $VALUE | cut -d ':' -f 1)" != "Error" && "$VALUE" != "" ]]; then + log "__SUB:tag_READ.sh: Ce compte monnaie libre contient $VALUE G1" + ./shell/parle.sh "Ce compte monnaie libre contient $VALUE G1" + CASHBACK="$J" + cmd="G1" + val+=("$VALUE") + else + log "__SUB:tag_READ.sh: ERREUR QR code illisible. longueur $J = ${#J}" + if [[ "$VALUE" == "" ]]; then + DUNITER=$(./shell/checknodes.sh 'BAN') + echo "TIMEOUT. CHANGE SILKAJ SERVER: $DUNITER" + ./shell/parle.sh "Temps dépassé. Changement de serveur $DUNITER" + CASHBACK="" + else + ./shell/parle.sh "QR code inconnu." + CASHBACK="" + fi + fi + else + ./shell/parle.sh "Ce compte monnaie libre contient ${val[0]} G1" + fi + else + ./shell/parle.sh "QR code de type inconnu" + fi + + ;; + + esac + + ############################################################### + # APRES G1 CASHBACK : G1 Tag BJ WRITE => ENCAISSEMENT + if [[ "${cmd}" == "BJ" && "$CASHBACK" != "" && -f /home/$YOU/.ipfs/keystore/${RR} ]]; then + ./shell/parle.sh "Encaissement du G1 Tag" + log "__SUB:tag_READ.sh: G1 tag de $BVALUE G1 ! /ipns/$J Virement vers $CASHBACK? " + + ./shell/parle.sh "vers portefeuille G1" + # ipfs get G1Tag vers ./TAG/${RR} + mkdir -p ./TAG/${RR}; rm -f ./TAG/${RR}/*; chown -R $YOU ./TAG/${RR}/ + log "__SUB:tag_READ.sh: ipfs get --output=./TAG/${RR} /ipns/$J" + su $YOU -c "ipfs get --output=./TAG/${RR} /ipns/$J" + + if [[ $(cat ./TAG/${RR}/TAG_passenger) != "" ]]; then ./shell/parle.sh "Impossible à encaisser. REC Tag ${FID}. $(cat ./TAG/${RR}/TAG_passenger) de Valeur $BVALUE "; continue; fi + + # Make Silkaj TX + G1VAL=$(bc -l <<< "scale=2; $BVALUE / 100" | cut -d '.' -f 1) + log "__SUB:tag_READ.sh: Silkaj TX $SWARM_G1AUTHFILE ($G1VAL) -> $CASHBACK" + PAY=$(./silkaj/silkaj transaction --auth-file -file="$SWARM_G1AUTHFILE" --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 + new=$(./shell/checknodes.sh "BAN") + sms_ERROR "$ADMINPHONE" "Il est survenu un problème avec un virement. Retour silkaj: $PAY ... $new"; + ./shell/parle.sh "Erreur de virement. Changement de serveur Duniter. Veuillez recommencer" + else + # ENCAISSEMENT G1Tag + ./shell/parle.sh "Transfert du Tag ${FID} de $G1VAL G1 vers portefeuille OK" + # CAPTURE / DESTRUCTION du G1 Tag + echo "0" > "./TAG/${RR}/TAG_amount" + echo "${J}" > "./TAG/${RR}/TAG_ipns" + + # Iterate + if [[ -f ./TAG/${RR}/TAG_n ]]; then NN=$(cat ./TAG/${RR}/TAG_n); ((NN++)); else NN=0; fi + + # TAG_actions + echo "$NN" > "./TAG/${RR}/TAG_n" + echo "${NANODATE}" > "./TAG/${RR}/TAG_nanodate" + echo "${IPFSNODEID}" > "./TAG/${RR}/TAG_writerid" + + # EMPTY G1TAG ID AND REMOVE PUBLISHKEYS + echo "" > "./TAG/${RR}/TAG_id" + rm -f ./TAG/TAG_publishkey.* + + log "__SUB:tag_READ.sh: Destruction G1Tag TAG_id $NN.${NANODATE} (par NODE ${IPFSNODEID}) => Value = 0" + I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") + # TAG_chain + echo "$I" > "./TAG/${RR}/TAG_chain" + I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") + # IPNS $RR PUBLISH + J=$(su $YOU -c "ipfs name publish -k ${RR} --quieter /ipfs/${I}") + + log "__SUB:tag_READ.sh: Destruction de ce G1 Tag publish -k ${RR} --quieter /ipfs/${I} :: ipfs ls /ipns/$J" + ./shell/parle.sh "${FID} G1 Tag vide. Merci de détruire ce G1 Tag!" + + # CLEAN IPFS keystore: remove NOT created NODE keys + SOURCENODEID=$(cat "./TAG/${RR}/TAG_nodeid") + if [[ "${SOURCENODEID}" != "${IPFSNODEID}" ]]; then + rm -f /home/$YOU/.ipfs/keystore/${RR} + fi + fi + else + # AJOUT MEMOIRE SCAN + ./shell/parle.sh "Mémorisation" + act+=("$cmd") + obj+=("$J") + fi + + + # FLUSH MEMOIRE 2 SCAN + if [[ ${#act[@]} -eq 2 ]]; then + echo "${act[@]}" + echo "${obj[@]}" + echo "${val[@]}" + ############################################################### + # PRESENTATION RJ puis BJ différents Tag WRITE = TRANSFERT G1 TAG + if [[ "${act[0]}" == "RJ" && "${act[1]}" == "BJ" && "${obj[0]}" != "${obj[1]}" ]]; then + PASSENGER=$(su $YOU -c "ipfs cat /ipns/${obj[1]}/TAG_passenger"); + if [[ "$PASSENGER" != "" ]]; then + ./shell/parle.sh "Rec Tag Machine non transférable!"; + 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]} $SWARM_G1AUTHFILE)" + fi + CASHBACK="" + fi + ############################################################### + # PRESENTATION BJ identiques TRANSFORMATION G1 TAG en REC TAG + if [[ "${act[0]}" == "BJ" && "${act[1]}" == "BJ" && "${obj[0]}" == "${obj[1]}" ]]; then + PASSENGER=$(su $YOU -c "ipfs cat /ipns/${obj[0]}/TAG_passenger"); + if [[ "$PASSENGER" != "" ]]; then + ./shell/parle.sh "Déjà Rec Tag Machine!"; + 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 $SWARM_G1AUTHFILE)" + fi + CASHBACK="" + fi + + act=() + obj=() + val=() + ./shell/parle.sh "Nouveau cycle de lecture." + fi + + ./shell/parle.sh "Flasher un QR code" + +done diff --git a/g1sms/tag_READ_X.sh b/g1sms/tag_READ_X.sh new file mode 100755 index 0000000..d783b0e --- /dev/null +++ b/g1sms/tag_READ_X.sh @@ -0,0 +1,286 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +########################################################################################### +########################################################################################### +# Lit les données reçues depuis un lecteur de QR Code branché en USB/SERIE (/dev/ttyACM0) +# Interpète les G1QRcodes et les G1Tag (R/W) +# Saisie du montant à transférer par pavé numérique +########################################################################################### +echo "__SUB:tag_READ_X.sh: QRCODE READER : START" +source ./shell/init.sh +source ./shell/functions.sh + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized +function log () { + echo "$line +$1" >> /tmp/tag_READ_X.log +} + +SWARM_G1AUTHFILE="${MY_PATH}/../g1sms.priv.key" +if [ ! -f $SWARM_G1AUTHFILE ]; then echo "ERREUR CLEF DECHIFFRAGE!"; exit; fi +# TODO G1TAG: USE CREATOR NODE KEY FILE INSTEAD OF SWARM_G1AUTHFILE SWARM KEY + +# DOUCHETTE ES TU LA? +if [ ! $G1TX ]; then echo "Branchez votre lecteur de QR code!"; exit; fi +./shell/tools/4LETTER.scroll.py "G1TX START" +./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) + log "__SUB:tag_READ_X.sh: SCAN /dev/ttyACM0 ($lon) :: $line" + + case $pref in + RJ) + R=$(echo $qrvalue | cut -d '#' -f 1) + J=$(echo $qrvalue | cut -d '#' -f 2) + log "__SUB:tag_READ_X.sh: Lecture G1Tag $R $J" + # IPFS READ + ID=$(su $YOU -c "ipfs cat /ipns/$J/TAG_id"); + if [[ "$ID" == "" ]]; then + ./shell/tools/4LETTER.scroll.py ">> BAD G1TAG <<" + continue + fi + # Get First R Tag name word and remove space for RR + FID=$(echo $ID | awk '{print toupper($1)}') + RR=$(echo $ID | sed s/\ //g) + + ./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)}') + + PASSENGER=$(su $YOU -c "ipfs cat /ipns/$J/TAG_passenger"); + if [[ "$PASSENGER" != "" ]]; then + ./shell/tools/4LETTER.scroll.py "G1TAG PASSENGER $RVALUE ZEN" + 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 *** $G1VAL G1" + fi + cmd="RJ" + CASHBACK="" + val+=("$RVALUE") + ;; + + BJ) + BB=$(echo $qrvalue | cut -d '#' -f 1) + J=$(echo $qrvalue | cut -d '#' -f 2) + log "__SUB:tag_READ_X.sh: Ouverture G1Tag $BB $J" + # + ID=$(su $YOU -c "ipfs cat /ipns/$J/TAG_id"); + if [[ "$ID" == "" ]]; then + ./shell/tools/4LETTER.scroll.py ">> BAD G1TAG <<" + continue + fi + FID=$(echo $ID | awk '{print toupper($1)}') + RR=$(echo $ID | sed s/\ //g) + + ./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)}') + + PASSENGER=$(su $YOU -c "ipfs cat /ipns/$J/TAG_passenger"); + # DIG PUBLISHING KEY + if [[ -f /home/$YOU/.ipfs/keystore/$RR ]]; then + log "__SUB:tag_READ_X.sh: Clef de publication IPFS $RR déjà présente" + else + rm /tmp/TAG_publishkey.B.gpg + su $YOU -c "ipfs get -o /tmp/ /ipns/$J/TAG_publishkey.B.gpg" + ./shell/tools/4LETTER.scroll.py "** GPG **" + gpg -d --output /tmp/ipns.key --pinentry-mode=loopback --passphrase $BB /tmp/TAG_publishkey.B.gpg + # CHECK IF OK + if [[ ! -f /tmp/ipns.key ]]; then + ./shell/tools/4LETTER.scroll.py ">> BAD GPG KEY <<" + continue + fi + mv /tmp/ipns.key /home/$YOU/.ipfs/keystore/$RR + log "__SUB:tag_READ_X.sh: Récupération de la clef de publication $RR" + fi + if [[ "$PASSENGER" != "" ]]; then + 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 *** $G1VAL G1 MAX" + fi + cmd="BJ" + val+=("$BVALUE") + ;; + + *) + if [[ $lon -eq 44 ]]; then + ./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) + + if [[ "$(echo $VALUE | cut -d ':' -f 1)" != "Error" && "$VALUE" != "" ]]; then + log "__SUB:tag_READ_X.sh: Ce compte monnaie libre contient $VALUE G1" + NOPOINT=$(echo $VALUE | cut -d '.' -f 1) + ./shell/tools/4LETTER.scroll.py " $NOPOINT G1 *** $NOPOINT G1 " + CASHBACK="$J" + cmd="G1" + val+=("$VALUE") + else + if [[ "$VALUE" == "" ]]; then + DUNITER=$(./shell/checknodes.sh 'BAN') + 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 " 2 X " + fi + else + ./shell/tools/4LETTER.scroll.py "ERREUR QRCODE INCONNU" + fi + + ;; + + esac + + ############################################################### + # APRES G1 CASHBACK : G1 Tag BJ WRITE => ENCAISSEMENT + if [[ "${cmd}" == "BJ" && "$CASHBACK" != "" && -f /home/$YOU/.ipfs/keystore/${RR} ]]; then + ./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.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" + su $YOU -c "ipfs get --output=./TAG/${RR} /ipns/$J" + + if [[ $(cat ./TAG/${RR}/TAG_passenger) != "" ]]; then ./shell/tools/4LETTER.scroll.py "IMPOSSIBLE TAG PASSENGER $BVALUE ZEN"; continue; fi + + # Make Silkaj TX + G1VAL=$(bc -l <<< "scale=2; $BVALUE / 100" | cut -d '.' -f 1) + log "__SUB:tag_READ_X.sh: Silkaj TX $SWARM_G1AUTHFILE ($G1VAL) -> $CASHBACK" + PAY=$(./silkaj/silkaj transaction --auth-file -file="$SWARM_G1AUTHFILE" --amount=$G1VAL --output=$CASHBACK --comment="[G1sms+] G1Tag $RR ZEN -> G1" -y) + + log "__SUB:tag_READ_X.sh: Silkaj output = $PAY" + # 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 " + # CAPTURE / DESTRUCTION du G1 Tag + echo "0" > "./TAG/${RR}/TAG_amount" + echo "${J}" > "./TAG/${RR}/TAG_ipns" + + # Iterate + if [[ -f ./TAG/${RR}/TAG_n ]]; then NN=$(cat ./TAG/${RR}/TAG_n); ((NN++)); else NN=0; fi + + # TAG_actions + echo "$NN" > "./TAG/${RR}/TAG_n" + echo "${NANODATE}" > "./TAG/${RR}/TAG_nanodate" + echo "${IPFSNODEID}" > "./TAG/${RR}/TAG_writerid" + + # EMPTY G1TAG ID AND REMOVE PUBLISHKEYS + echo "" > "./TAG/${RR}/TAG_id" + rm -f ./TAG/TAG_publishkey.* + + log "__SUB:tag_READ_X.sh: Destruction G1Tag TAG_id $NN.${NANODATE} (par NODE ${IPFSNODEID}) => Value = 0" + I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") + # TAG_chain + echo "$I" > "./TAG/${RR}/TAG_chain" + I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") + # IPNS $RR PUBLISH + 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 "DETRUIRE G1TAG ${FID}" + + # CLEAN IPFS keystore: remove NOT created NODE keys + SOURCENODEID=$(cat "./TAG/${RR}/TAG_nodeid") + if [[ "${SOURCENODEID}" != "${IPFSNODEID}" ]]; then + rm -f /home/$YOU/.ipfs/keystore/${RR} + fi + fi + else + # AJOUT MEMOIRE SCAN + ./shell/timeout.sh -t 1 ./shell/tools/4LETTER.spinner.py + act+=("$cmd") + obj+=("$J") + fi + + + # FLUSH MEMOIRE 2 SCAN + if [[ ${#act[@]} -eq 2 ]]; then + echo "${act[@]}" + echo "${obj[@]}" + echo "${val[@]}" + ############################################################### + # PRESENTATION RJ puis BJ différents Tag WRITE = TRANSFERT G1 TAG + if [[ "${act[0]}" == "RJ" && "${act[1]}" == "BJ" && "${obj[0]}" != "${obj[1]}" ]]; then + PASSENGER=$(su $YOU -c "ipfs cat /ipns/${obj[1]}/TAG_passenger"); + if [[ "$PASSENGER" != "" ]]; then + ./shell/tools/4LETTER.scroll.py "IMPOSSIBLE TAG PASSENGER"; + else + ########################################################### + # 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} -> TX $COMBIENZEN ZEN *** $COMBIEN G1" + log "__SUB:tag_READ_X.sh: ./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIENZEN $SWARM_G1AUTHFILE" + ./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIENZEN "$SWARM_G1AUTHFILE" + else + ./shell/tools/4LETTER.scroll.py "ERREUR $COMBIEN > VALEUR DE ${FID} *** ${val[1]} ZEN" + fi + fi + CASHBACK="" + fi + ############################################################### + # PRESENTATION BJ identiques TRANSFORMATION G1 TAG en REC TAG + if [[ "${act[0]}" == "BJ" && "${act[1]}" == "BJ" && "${obj[0]}" == "${obj[1]}" ]]; then + PASSENGER=$(su $YOU -c "ipfs cat /ipns/${obj[0]}/TAG_passenger"); + if [[ "$PASSENGER" != "" ]]; then + ./shell/tools/4LETTER.scroll.py "DEJA TAG PASSENGER"; + 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 $SWARM_G1AUTHFILE)" + fi + CASHBACK="" + fi + + 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/g1sms/tag_READ_XY.sh b/g1sms/tag_READ_XY.sh new file mode 100644 index 0000000..da8c145 --- /dev/null +++ b/g1sms/tag_READ_XY.sh @@ -0,0 +1,300 @@ +#!/bin/bash +################################################################################ +# Author: Fred (support@qo-op.com) +# Version: 0.1 +# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/) +########################################################################################### +########################################################################################### +# Lit les données reçues depuis un lecteur de QR Code branché en USB/SERIE (/dev/ttyACM0) +# Interpète les G1QRcodes et les G1Tag (R/W) +# Saisie du montant à transférer par pavé numérique +########################################################################################### +echo "__SUB:tag_READ_XY.sh: QRCODE READER : START" +function log () { + echo "$line +$1" >> /tmp/tag_READ_XY.log +} +source ./shell/init.sh +source ./shell/functions.sh +############################################## +# NODE ENVIRONEMENT DETECTION +############################################## +YOU=$(ps auxf --sort=+utime | grep -w ipfs | grep -v -E 'color=auto|grep' | tail -n 1 | cut -d " " -f 1); +IPFSNODEID=$(su $YOU -c "ipfs id -f='\n'") +NODE_UIDNA=$(cat "./wallets/.$IPFSNODEID/_uidna") + +MY_PATH="`dirname \"$0\"`" # relative +MY_PATH="`( cd \"$MY_PATH\" && pwd )`" # absolutized and normalized + +SWARM_G1PUBKEY=$(cat "${GPATH}/g1sms.pub.key") +SWARM_G1AUTHFILE="${GPATH}/g1sms.priv.key" +if [[ ! -f $SWARM_G1AUTHFILE ]]; then echo "ERREUR CLEF DECHIFFRAGE!"; exit; fi + +## INIT NODE G1 PUB & PRIV KEY +NODE_G1PUBKEY=$(cat "${GPATH}/g1sms.preoni.pub.key") +NODE_G1AUTHFILE="${GPATH}/g1sms.preoni.priv.key" + + +if [[ ! -e "/dev/ttyACM0" ]]; then echo "Branchez votre lecteur de QR code!"; exit; fi +############################################## + +# DOUCHETTE ES TU LA? +./shell/tools/4LETTER.scroll.py "G1TX START" +./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) + log "__SUB:tag_READ_X.sh: SCAN /dev/ttyACM0 ($lon) :: $line" + + case $pref in + RJ) + R=$(echo $qrvalue | cut -d '#' -f 1) + J=$(echo $qrvalue | cut -d '#' -f 2) + log "__SUB:tag_READ_X.sh: Lecture G1Tag $R $J" + # IPFS READ + ID=$(su $YOU -c "ipfs cat /ipns/$J/TAG_id"); + if [[ "$ID" == "" ]]; then + ./shell/tools/4LETTER.scroll.py ">> BAD G1TAG <<" + continue + fi + # Get First R Tag name word and remove space for RR + FID=$(echo $ID | awk '{print toupper($1)}') + RR=$(echo $ID | sed s/\ //g) + + ./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)}') + + PASSENGER=$(su $YOU -c "ipfs cat /ipns/$J/TAG_passenger"); + if [[ "$PASSENGER" != "" ]]; then + ./shell/tools/4LETTER.scroll.py "G1TAG PASSENGER $RVALUE ZEN" + 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 *** $G1VAL G1" + fi + cmd="RJ" + CASHBACK="" + val+=("$RVALUE") + ;; + + BJ) + BB=$(echo $qrvalue | cut -d '#' -f 1) + J=$(echo $qrvalue | cut -d '#' -f 2) + log "__SUB:tag_READ_X.sh: Ouverture G1Tag $BB $J" + # + ID=$(su $YOU -c "ipfs cat /ipns/$J/TAG_id"); + if [[ "$ID" == "" ]]; then + ./shell/tools/4LETTER.scroll.py ">> BAD G1TAG <<" + continue + fi + FID=$(echo $ID | awk '{print toupper($1)}') + RR=$(echo $ID | sed s/\ //g) + + ./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)}') + + PASSENGER=$(su $YOU -c "ipfs cat /ipns/$J/TAG_passenger"); + # DIG PUBLISHING KEY + if [[ -f /home/$YOU/.ipfs/keystore/$RR ]]; then + log "__SUB:tag_READ_X.sh: Clef de publication IPFS $RR déjà présente" + else + rm /tmp/TAG_publishkey.B.gpg + su $YOU -c "ipfs get -o /tmp/ /ipns/$J/TAG_publishkey.B.gpg" + ./shell/tools/4LETTER.scroll.py "** GPG **" + gpg -d --output /tmp/ipns.key --pinentry-mode=loopback --passphrase $BB /tmp/TAG_publishkey.B.gpg + # CHECK IF OK + if [[ ! -f /tmp/ipns.key ]]; then + ./shell/tools/4LETTER.scroll.py ">> BAD GPG KEY <<" + continue + fi + mv /tmp/ipns.key /home/$YOU/.ipfs/keystore/$RR + log "__SUB:tag_READ_X.sh: Récupération de la clef de publication $RR" + fi + if [[ "$PASSENGER" != "" ]]; then + 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 *** $G1VAL G1 MAX" + fi + cmd="BJ" + val+=("$BVALUE") + ;; + + *) + if [[ $lon -eq 44 ]]; then + ./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) + + if [[ "$(echo $VALUE | cut -d ':' -f 1)" != "Error" && "$VALUE" != "" ]]; then + log "__SUB:tag_READ_X.sh: Ce compte monnaie libre contient $VALUE G1" + NOPOINT=$(echo $VALUE | cut -d '.' -f 1) + ./shell/tools/4LETTER.scroll.py " $NOPOINT G1 *** $NOPOINT G1 " + CASHBACK="$J" + cmd="G1" + val+=("$VALUE") + else + if [[ "$VALUE" == "" ]]; then + DUNITER=$(./shell/checknodes.sh 'BAN') + 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 " 2 X " + fi + else + ./shell/tools/4LETTER.scroll.py "ERREUR QRCODE INCONNU" + fi + + ;; + + esac + + ############################################################### + # APRES G1 CASHBACK : G1 Tag BJ WRITE => ENCAISSEMENT + if [[ "${cmd}" == "BJ" && "$CASHBACK" != "" && -f /home/$YOU/.ipfs/keystore/${RR} ]]; then + ./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.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" + su $YOU -c "ipfs get --output=./TAG/${RR} /ipns/$J" + + if [[ $(cat ./TAG/${RR}/TAG_passenger) != "" ]]; then ./shell/tools/4LETTER.scroll.py "IMPOSSIBLE TAG PASSENGER $BVALUE ZEN"; continue; fi + + # Make Silkaj TX + G1VAL=$(bc -l <<< "scale=2; $BVALUE / 100" | cut -d '.' -f 1) + log "__SUB:tag_READ_X.sh: Silkaj TX $SWARM_G1AUTHFILE ($G1VAL) -> $CASHBACK" + PAY=$(./silkaj/silkaj transaction --auth-file -file="$SWARM_G1AUTHFILE" --amount=$G1VAL --output=$CASHBACK --comment="[G1sms+] G1Tag $RR ZEN -> G1" -y) + + log "__SUB:tag_READ_X.sh: Silkaj output = $PAY" + # 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 " + # CAPTURE / DESTRUCTION du G1 Tag + echo "0" > "./TAG/${RR}/TAG_amount" + echo "${J}" > "./TAG/${RR}/TAG_ipns" + + # Iterate + if [[ -f ./TAG/${RR}/TAG_n ]]; then NN=$(cat ./TAG/${RR}/TAG_n); ((NN++)); else NN=0; fi + + # TAG_actions + echo "$NN" > "./TAG/${RR}/TAG_n" + echo "${NANODATE}" > "./TAG/${RR}/TAG_nanodate" + echo "${IPFSNODEID}" > "./TAG/${RR}/TAG_writerid" + + # EMPTY G1TAG ID AND REMOVE PUBLISHKEYS + echo "" > "./TAG/${RR}/TAG_id" + rm -f ./TAG/TAG_publishkey.* + + log "__SUB:tag_READ_X.sh: Destruction G1Tag TAG_id $NN.${NANODATE} (par NODE ${IPFSNODEID}) => Value = 0" + I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") + # TAG_chain + echo "$I" > "./TAG/${RR}/TAG_chain" + I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1") + # IPNS $RR PUBLISH + 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 "DETRUIRE G1TAG ${FID}" + + # CLEAN IPFS keystore: remove NOT created NODE keys + SOURCENODEID=$(cat "./TAG/${RR}/TAG_nodeid") + if [[ "${SOURCENODEID}" != "${IPFSNODEID}" ]]; then + rm -f /home/$YOU/.ipfs/keystore/${RR} + fi + fi + else + # AJOUT MEMOIRE SCAN + ./shell/timeout.sh -t 1 ./shell/tools/4LETTER.spinner.py + act+=("$cmd") + obj+=("$J") + fi + + + # FLUSH MEMOIRE 2 SCAN + if [[ ${#act[@]} -eq 2 ]]; then + echo "${act[@]}" + echo "${obj[@]}" + echo "${val[@]}" + ############################################################### + # PRESENTATION RJ puis BJ différents Tag WRITE = TRANSFERT G1 TAG + if [[ "${act[0]}" == "RJ" && "${act[1]}" == "BJ" && "${obj[0]}" != "${obj[1]}" ]]; then + PASSENGER=$(su $YOU -c "ipfs cat /ipns/${obj[1]}/TAG_passenger"); + if [[ "$PASSENGER" != "" ]]; then + ./shell/tools/4LETTER.scroll.py "IMPOSSIBLE TAG PASSENGER"; + else + ########################################################### + # 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} -> TX $COMBIENZEN ZEN *** $COMBIEN G1" + log "__SUB:tag_READ_X.sh: ./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIENZEN $SWARM_G1AUTHFILE" + ./shell/tag_OP.sh ${obj[1]} ${obj[0]} $COMBIENZEN "$SWARM_G1AUTHFILE" + else + ./shell/tools/4LETTER.scroll.py "ERREUR $COMBIEN > VALEUR DE ${FID} *** ${val[1]} ZEN" + fi + fi + CASHBACK="" + fi + ############################################################### + # PRESENTATION BJ identiques TRANSFORMATION G1 TAG en REC TAG + if [[ "${act[0]}" == "BJ" && "${act[1]}" == "BJ" && "${obj[0]}" == "${obj[1]}" ]]; then + PASSENGER=$(su $YOU -c "ipfs cat /ipns/${obj[0]}/TAG_passenger"); + if [[ "$PASSENGER" != "" ]]; then + ./shell/tools/4LETTER.scroll.py "DEJA TAG PASSENGER"; + 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 $SWARM_G1AUTHFILE)" + fi + CASHBACK="" + fi + + 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/g1sms/timeout.sh b/g1sms/timeout.sh new file mode 100755 index 0000000..5c19d2e --- /dev/null +++ b/g1sms/timeout.sh @@ -0,0 +1,91 @@ +#!/bin/bash +# +# The Bash shell script executes a command with a time-out. +# Upon time-out expiration SIGTERM (15) is sent to the process. If the signal +# is blocked, then the subsequent SIGKILL (9) terminates it. +# +# Based on the Bash documentation example. + +# Hello Chet, +# please find attached a "little easier" :-) to comprehend +# time-out example. If you find it suitable, feel free to include +# anywhere: the very same logic as in the original examples/scripts, a +# little more transparent implementation to my taste. +# +# Dmitry V Golovashkin + +scriptName="${0##*/}" + +declare -i DEFAULT_TIMEOUT=9 +declare -i DEFAULT_INTERVAL=1 +declare -i DEFAULT_DELAY=1 + +# Timeout. +declare -i timeout=DEFAULT_TIMEOUT +# Interval between checks if the process is still alive. +declare -i interval=DEFAULT_INTERVAL +# Delay between posting the SIGTERM signal and destroying the process by SIGKILL. +declare -i delay=DEFAULT_DELAY + +function printUsage() { + cat < 0)); do + sleep $interval + kill -0 $$ || exit 0 + ((t -= interval)) + done + + # Be nice, post SIGTERM first. + # The 'exit 0' below will be executed if any preceeding command fails. + kill -s SIGTERM $$ && kill -0 $$ || exit 0 + sleep $delay + kill -s SIGKILL $$ +) 2> /dev/null & + +exec "$@" diff --git a/g1sms/tools/4LETTER.blink.py b/g1sms/tools/4LETTER.blink.py new file mode 100755 index 0000000..5f77418 --- /dev/null +++ b/g1sms/tools/4LETTER.blink.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import time +import fourletterphat + +fourletterphat.clear() + +fourletterphat.print_str("SCAN") +fourletterphat.set_blink(fourletterphat.HT16K33_BLINK_HALFHZ) +fourletterphat.show() +time.sleep(1) +fourletterphat.set_blink(fourletterphat.HT16K33_BLINK_OFF) +fourletterphat.print_str("CODE") +fourletterphat.show() +time.sleep(0.5) diff --git a/g1sms/tools/4LETTER.clear.py b/g1sms/tools/4LETTER.clear.py new file mode 100755 index 0000000..059c6c6 --- /dev/null +++ b/g1sms/tools/4LETTER.clear.py @@ -0,0 +1,3 @@ +#!/usr/bin/env python +import fourletterphat +fourletterphat.clear() diff --git a/g1sms/tools/4LETTER.clock.py b/g1sms/tools/4LETTER.clock.py new file mode 100755 index 0000000..138cd59 --- /dev/null +++ b/g1sms/tools/4LETTER.clock.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +import time +import fourletterphat + +while True: + fourletterphat.clear() + + str_time = time.strftime("%H%M") + + # Display the time + fourletterphat.print_number_str(str_time) + + # Blink the middle decimal point + # int(time.time() % 2) will alternate 1 0 1 0 + # which we can use to directly set the point + fourletterphat.set_decimal(1, int(time.time() % 2)) + + fourletterphat.show() + time.sleep(0.1) diff --git a/g1sms/tools/4LETTER.scroll.py b/g1sms/tools/4LETTER.scroll.py new file mode 100755 index 0000000..c77897f --- /dev/null +++ b/g1sms/tools/4LETTER.scroll.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python +import sys +import fourletterphat + +# if bad number of arguments... +if len(sys.argv) != 2: + + # display command usage + print(""" + Usage: + python 4LETTER.scroll.py "message a afficher" + """) + + # exit with status code error + exit(1) + +# Get message from arguments +message = sys.argv[1] +fourletterphat.scroll_print( message ) + diff --git a/g1sms/tools/4LETTER.spinner.py b/g1sms/tools/4LETTER.spinner.py new file mode 100755 index 0000000..2e4ca45 --- /dev/null +++ b/g1sms/tools/4LETTER.spinner.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import time +import fourletterphat as flp + +spinner = ["|", "/", "-", "\\"] + +while True: + for i in range(4): + for s in spinner: + s = s * 4 + flp.clear() + flp.print_str(s) + flp.show() + time.sleep(0.1) diff --git a/g1sms/tools/G1_IPFS_pishrink.sh b/g1sms/tools/G1_IPFS_pishrink.sh new file mode 100644 index 0000000..cd7ebb2 --- /dev/null +++ b/g1sms/tools/G1_IPFS_pishrink.sh @@ -0,0 +1,332 @@ +#!/bin/bash +########################################################### +# FORK of pishrink.sh +# SHRINK IMAGE OF YOUR RASPIAN PI SD CARD +# +# + TODO: THIS SCRIPT RESET IPFS / G1 Keys / SWARM config +# AND RUN CONFIG on FIRST IMG BOOT in /etc/rc.local +########################################################### +version="v0.1.3" + +CURRENT_DIR=$(pwd) +SCRIPTNAME="${0##*/}" +LOGFILE=${CURRENT_DIR}/${SCRIPTNAME%.*}.log + +function info() { + echo "$SCRIPTNAME: $1..." +} + +function error() { + echo -n "$SCRIPTNAME: ERROR occured in line $1: " + shift + echo "$@" +} + +function cleanup() { + if losetup "$loopback" &>/dev/null; then + losetup -d "$loopback" + fi + if [ "$debug" = true ]; then + local old_owner=$(stat -c %u:%g "$src") + chown "$old_owner" "$LOGFILE" + fi + +} + +function logVariables() { + if [ "$debug" = true ]; then + echo "Line $1" >> "$LOGFILE" + shift + local v var + for var in "$@"; do + eval "v=\$$var" + echo "$var: $v" >> "$LOGFILE" + done + fi +} + +function checkFilesystem() { + info "Checking filesystem" + e2fsck -pf "$loopback" + (( $? < 4 )) && return + + info "Filesystem error detected!" + + info "Trying to recover corrupted filesystem" + e2fsck -y "$loopback" + (( $? < 4 )) && return + +if [[ $repair == true ]]; then + info "Trying to recover corrupted filesystem - Phase 2" + e2fsck -fy -b 32768 "$loopback" + (( $? < 4 )) && return +fi + error $LINENO "Filesystem recoveries failed. Giving up..." + exit -9 + +} + +help() { + local help + read -r -d '' help << EOM +Usage: $0 [-sdrzh] imagefile.img [newimagefile.img] + + -s: Don't expand filesystem when image is booted the first time + -d: Write debug messages in a debug log file + -r: Use advanced filesystem repair option if the normal one fails + -z: Gzip compress image after shrinking +EOM + echo "$help" + exit -1 +} + +usage() { + echo "Usage: $0 [-sdrpzh] imagefile.img [newimagefile.img]" + echo "" + echo " -s: Skip autoexpand" + echo " -d: Debug mode on" + echo " -r: Use advanced repair options" + echo " -z: Gzip compress image after shrinking" + echo " -h: display help text" + exit -1 +} + +should_skip_autoexpand=false +debug=false +repair=false +gzip_compress=false + +while getopts ":sdrzh" opt; do + case "${opt}" in + s) should_skip_autoexpand=true ;; + d) debug=true;; + r) repair=true;; + z) gzip_compress=true;; + h) help;; + *) usage ;; + esac +done +shift $((OPTIND-1)) + +if [ "$debug" = true ]; then + info "Creating log file $LOGFILE" + rm "$LOGFILE" &>/dev/null + exec 1> >(stdbuf -i0 -o0 -e0 tee -a "$LOGFILE" >&1) + exec 2> >(stdbuf -i0 -o0 -e0 tee -a "$LOGFILE" >&2) +fi + +echo "${0##*/} $version" + +#Args +src="$1" +img="$1" + +#Usage checks +if [[ -z "$img" ]]; then + usage +fi +if [[ ! -f "$img" ]]; then + error $LINENO "$img is not a file..." + exit -2 +fi +if (( EUID != 0 )); then + error $LINENO "You need to be running as root." + exit -3 +fi + +#Check that what we need is installed +for command in parted losetup tune2fs md5sum e2fsck resize2fs; do + command -v $command >/dev/null 2>&1 + if (( $? != 0 )); then + error $LINENO "$command is not installed." + exit -4 + fi +done + +#Copy to new file if requested +if [ -n "$2" ]; then + info "Copying $1 to $2..." + cp --reflink=auto --sparse=always "$1" "$2" + if (( $? != 0 )); then + error $LINENO "Could not copy file..." + exit -5 + fi + old_owner=$(stat -c %u:%g "$1") + chown "$old_owner" "$2" + img="$2" +fi + +# cleanup at script exit +trap cleanup ERR EXIT + +#Gather info +info "Gatherin data" +beforesize=$(ls -lh "$img" | cut -d ' ' -f 5) +parted_output=$(parted -ms "$img" unit B print | tail -n 1) +partnum=$(echo "$parted_output" | cut -d ':' -f 1) +partstart=$(echo "$parted_output" | cut -d ':' -f 2 | tr -d 'B') +loopback=$(losetup -f --show -o "$partstart" "$img") +tune2fs_output=$(tune2fs -l "$loopback") +currentsize=$(echo "$tune2fs_output" | grep '^Block count:' | tr -d ' ' | cut -d ':' -f 2) +blocksize=$(echo "$tune2fs_output" | grep '^Block size:' | tr -d ' ' | cut -d ':' -f 2) + +logVariables $LINENO tune2fs_output currentsize blocksize + +#Check if we should make pi expand rootfs on next boot +if [ "$should_skip_autoexpand" = false ]; then + #Make pi expand rootfs on next boot + mountdir=$(mktemp -d) + mount "$loopback" "$mountdir" + + if [ "$(md5sum "$mountdir/etc/rc.local" | cut -d ' ' -f 1)" != "0542054e9ff2d2e0507ea1ffe7d4fc87" ]; then + echo "Creating new /etc/rc.local" + mv "$mountdir/etc/rc.local" "$mountdir/etc/rc.local.bak" + #####Do not touch the following lines##### +cat <<\EOF1 > "$mountdir/etc/rc.local" +#!/bin/bash +do_expand_rootfs() { + ROOT_PART=$(mount | sed -n 's|^/dev/\(.*\) on / .*|\1|p') + + PART_NUM=${ROOT_PART#mmcblk0p} + if [ "$PART_NUM" = "$ROOT_PART" ]; then + echo "$ROOT_PART is not an SD card. Don't know how to expand" + return 0 + fi + + # Get the starting offset of the root partition + PART_START=$(parted /dev/mmcblk0 -ms unit s p | grep "^${PART_NUM}" | cut -f 2 -d: | sed 's/[^0-9]//g') + [ "$PART_START" ] || return 1 + # Return value will likely be error for fdisk as it fails to reload the + # partition table because the root fs is mounted + fdisk /dev/mmcblk0 < /etc/rc.local && +#!/bin/sh +echo "Expanding /dev/$ROOT_PART" +resize2fs /dev/$ROOT_PART +rm -f /etc/rc.local; cp -f /etc/rc.local.bak /etc/rc.local; /etc/rc.local + +EOF +reboot +exit +} +raspi_config_expand() { +/usr/bin/env raspi-config --expand-rootfs +if [[ $? != 0 ]]; then + return -1 +else + rm -f /etc/rc.local; cp -f /etc/rc.local.bak /etc/rc.local; /etc/rc.local + reboot + exit +fi +} +raspi_config_expand +echo "WARNING: Using backup expand..." +sleep 5 +do_expand_rootfs +echo "ERROR: Expanding failed..." +sleep 5 +rm -f /etc/rc.local; cp -f /etc/rc.local.bak /etc/rc.local; /etc/rc.local +exit 0 +EOF1 + #####End no touch zone##### + chmod +x "$mountdir/etc/rc.local" + fi + umount "$mountdir" +else + echo "Skipping autoexpanding process..." +fi + +#Make sure filesystem is ok +checkFilesystem + +if ! minsize=$(resize2fs -P "$loopback"); then + rc=$? + error $LINENO "resize2fs failed with rc $rc" + exit -10 +fi +minsize=$(cut -d ':' -f 2 <<< "$minsize" | tr -d ' ') +logVariables $LINENO minsize +if [[ $currentsize -eq $minsize ]]; then + error $LINENO "Image already shrunk to smallest size" + exit -11 +fi + +#Add some free space to the end of the filesystem +extra_space=$(($currentsize - $minsize)) +logVariables $LINENO extra_space +for space in 5000 1000 100; do + if [[ $extra_space -gt $space ]]; then + minsize=$(($minsize + $space)) + break + fi +done +logVariables $LINENO minsize + +#Shrink filesystem +info "Shrinking filesystem" +resize2fs -p "$loopback" $minsize +if [[ $? != 0 ]]; then + error $LINENO "resize2fs failed" + mount "$loopback" "$mountdir" + mv "$mountdir/etc/rc.local.bak" "$mountdir/etc/rc.local" + umount "$mountdir" + losetup -d "$loopback" + exit -12 +fi +sleep 1 + +#Shrink partition +partnewsize=$(($minsize * $blocksize)) +newpartend=$(($partstart + $partnewsize)) +logVariables $LINENO partnewsize newpartend +if ! parted -s -a minimal "$img" rm "$partnum"; then + rc=$? + error $LINENO "parted failed with rc $rc" + exit -13 +fi + +if ! parted -s "$img" unit B mkpart primary "$partstart" "$newpartend"; then + rc=$? + error $LINENO "parted failed with rc $rc" + exit -14 +fi + +#Truncate the file +info "Shrinking image" +if ! endresult=$(parted -ms "$img" unit B print free); then + rc=$? + error $LINENO "parted failed with rc $rc" + exit -15 +fi + +endresult=$(tail -1 <<< "$endresult" | cut -d ':' -f 2 | tr -d 'B') +logVariables $LINENO endresult +if ! truncate -s "$endresult" "$img"; then + rc=$? + error $LINENO "trunate failed with rc $rc" + exit -16 +fi + +if [[ $gzip_compress == true ]]; then + info "Gzipping the shrunk image" + if [[ ! $(gzip -f9 "$img") ]]; then + img=$img.gz + fi +fi + +aftersize=$(ls -lh "$img" | cut -d ' ' -f 5) +logVariables $LINENO aftersize + +info "Shrunk $img from $beforesize to $aftersize" diff --git a/g1sms/tools/G1_TUX_keygen.py b/g1sms/tools/G1_TUX_keygen.py new file mode 100755 index 0000000..395d75f --- /dev/null +++ b/g1sms/tools/G1_TUX_keygen.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 + +""" + CopyLeft 2019 Pascal Engélibert + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +""" + +import sys +from duniterpy.key import SigningKey + +def getargv(arg, default=""): + if arg in sys.argv and len(sys.argv) > sys.argv.index(arg)+1: + return sys.argv[sys.argv.index(arg)+1] + else: + return default + +if __name__ == "__main__": + + if "--help" in sys.argv or not "-i" in sys.argv or not "-o" in sys.argv: + print("""Duniter MiniTools: Mass Keygen +CopyLeft 2019 Pascal Engélibert + +Usage: +python3 keygen.py -i -o +Format: CSV ; Separator: tab +""") + exit() + + infile = open(getargv("-i"), "r") + outfile = open(getargv("-o"), "w") + + i = 0 + while True: + line = infile.readline() + if line == "": + break + i += 1 + if "\n" in line: + line = line[:len(line)-1] + + cols = line.split("\t") + while "" in cols: + cols.remove("") + if len(cols) < 2: + print("Error (line "+str(i)+"): less than 2 columns! (at least 2 expected)") + break + + key = SigningKey.from_credentials(cols[0], cols[1]) + outfile.write(cols[0]+"\t"+cols[1]+"\t"+key.pubkey+"\n") + + infile.close() + outfile.close() diff --git a/g1sms/tools/G1_TUX_natools.py b/g1sms/tools/G1_TUX_natools.py new file mode 100755 index 0000000..5149743 --- /dev/null +++ b/g1sms/tools/G1_TUX_natools.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 + +import os, sys, duniterpy.key, libnacl.sign + +def getargv(arg:str, default:str="", n:int=1, args:list=sys.argv) -> str: + if arg in args and len(args) > args.index(arg)+n: + return args[args.index(arg)+n] + else: + return default + +def read_data(data_path, b=True): + if data_path == "-": + if b: + return sys.stdin.read().encode() + else: + return sys.stdin.read() + else: + if b: + return open(os.path.expanduser(data_path), "rb").read() + else: + return open(os.path.expanduser(data_path), "r").read() + +def write_data(data, result_path): + (sys.stdout if result_path == "-" else open(os.path.expanduser(result_path), "wb")).write(data) + +def encrypt(data, pubkey): + return duniterpy.key.PublicKey(pubkey).encrypt_seal(data) + +def decrypt(data, privkey): + return duniterpy.key.SigningKey.from_seedhex(privkey).decrypt_seal(data) + +def sign(data, privkey): + return duniterpy.key.SigningKey.from_seedhex(privkey).sign(data) + +def verify(data, pubkey): + try: + return libnacl.sign.Verifier(duniterpy.key.PublicKey(pubkey).hex_pk()).verify(data) + except ValueError: + exit(1) + +def show_help(): + print("""Usage: +python3 natools.py [options] + +Commands: + encrypt Encrypt data + decrypt Decrypt data + sign Sign data + verify Verify data + +Options: + -i Input file path (default: -) + -k Privkey file path (default: authfile.key) + -p Pubkey (base58) + -o Output file path (default: -) + +Note: "-" means stdin or stdout. +""") + +if __name__ == "__main__": + + if "--help" in sys.argv: + show_help() + exit() + + data_path = getargv("-i", "-") + privkey_path = getargv("-k", "authfile.key") + pubkey = getargv("-p") + result_path = getargv("-o", "-") + + try: + if sys.argv[1] == "encrypt": + write_data(encrypt(read_data(data_path), pubkey), result_path) + elif sys.argv[1] == "decrypt": + write_data(decrypt(read_data(data_path), read_data(privkey_path, False)), result_path) + elif sys.argv[1] == "sign": + write_data(sign(read_data(data_path), read_data(privkey_path, False)), result_path) + elif sys.argv[1] == "verify": + write_data(verify(read_data(data_path), pubkey), result_path) + else: + show_help() + except Exception as e: + sys.stderr.write("Error: ", e, "\n") + show_help() + exit(1) diff --git a/g1sms/tools/G1_gen_pubkey.py b/g1sms/tools/G1_gen_pubkey.py new file mode 100755 index 0000000..0a543f5 --- /dev/null +++ b/g1sms/tools/G1_gen_pubkey.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +import sys +from duniterpy.key import SigningKey + + +def generate_public_key(salt: str, password: str) -> str: + """ + Return public key from credentials + + :param salt: Salt passphrase, using quotes if space in it + :param password: Password + """ + # Create key object + # key = SigningKey(salt, password) + key = SigningKey.from_credentials(salt, password) + # SigningKey.save_private_key("private.key", "./") + return key.pubkey + +if __name__ == '__main__': + + # if bad number of arguments... + if len(sys.argv) != 3: + + # display command usage + print(""" + Usage: + python gen_pubkey.py salt password + """) + + # exit with status code error + exit(1) + + # capture arguments + _salt = sys.argv[1] + _password = sys.argv[2] + + # display the public key + print(generate_public_key(_salt, _password)) + + # exit with status code ok + exit(0) + diff --git a/g1sms/tools/G1_request_cesium_profile.py b/g1sms/tools/G1_request_cesium_profile.py new file mode 100755 index 0000000..27f9d41 --- /dev/null +++ b/g1sms/tools/G1_request_cesium_profile.py @@ -0,0 +1,32 @@ +import asyncio +import json +import sys +from duniterpy.api.client import Client + +ES_CORE_ENDPOINT = "ES_CORE_API g1.data.duniter.fr 443" +ES_USER_ENDPOINT = "ES_USER_API g1.data.duniter.fr 443" + +async def main(): + """ + Main code (synchronous requests) + """ + # Create Client from endpoint string in Duniter format + client = Client(ES_USER_ENDPOINT) + + # Get entry + # pubkey = input("\nEnter a public key to get the user profile: ") + # pubkey = "DsEx1pS33vzYZg4MroyBV9hCw98j1gtHEhwiZ5tK7ech" + pubkey = sys.argv[1] + + # Get the profil of a public key (direct REST GET request) + # print("\nGET user/profile/{0}/_source:".format(pubkey)) + # response = await client.get('tx/history/{0}'.format(pubkey.strip(' \n'))) + response = await client.get('user/profile/{0}/_source'.format(pubkey.strip(' \n'))) + print(json.dumps(response)) + + # Close client aiohttp session + await client.close() + +# Latest duniter-python-api is asynchronous and you have to use asyncio, an asyncio loop and a "as" on the data. +# ( https://docs.python.org/3/library/asyncio.html ) +asyncio.get_event_loop().run_until_complete(main()) diff --git a/g1sms/tools/G1_send_transaction.py b/g1sms/tools/G1_send_transaction.py new file mode 100755 index 0000000..6f819b5 --- /dev/null +++ b/g1sms/tools/G1_send_transaction.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +import asyncio +import getpass +import sys +import silkaj.money, silkaj.tx, silkaj.auth +from duniterpy.key import SigningKey + +# CONFIG ####################################### + +# You can either use a complete defined endpoint : [NAME_OF_THE_API] [DOMAIN] [IPv4] [IPv6] [PORT] +# or the simple definition : [NAME_OF_THE_API] [DOMAIN] [PORT] +# Here we use the secure BASIC_MERKLED_API (BMAS) +BMAS_ENDPOINT = "BMAS g1.duniter.org 443" + +# Version of the transaction document +TRANSACTION_VERSION = 10 + +################################################ + + +def sendTransaction(sender_keys, receiver_pubkey, amount, comment): + sender_amount = silkaj.money.get_amount_from_pubkey(sender_keys.pubkey)[0] + assert sender_amount >= amount, "not enough money" + silkaj.tx.generate_and_send_transaction(sender_keys.hex_seed().decode(), sender_keys.pubkey, amount, [receiver_pubkey], comment) + + +if __name__ == '__main__': + """ + Main code + """ + # if bad number of arguments... + if len(sys.argv) != 6: + + # display command usage + print(""" + Usage: + ./g1_send_transaction.py phone pin dest amount comment + """) + + # exit with status code error + exit(1) + + # capture arguments + _salt = sys.argv[1] + _password = sys.argv[2] + _dest = sys.argv[3] + _amount = sys.argv[4] + _comment = sys.argv[5] + + # create keys from credentials + sender_keys = SigningKey(_salt, _password) + pubkey_from = sender_keys.pubkey + + print("txstatus = sendTransaction(sender_keys, _dest, _amount, _comment)") diff --git a/g1sms/tools/matrixKeypad.py b/g1sms/tools/matrixKeypad.py new file mode 100755 index 0000000..ba1c3d4 --- /dev/null +++ b/g1sms/tools/matrixKeypad.py @@ -0,0 +1,41 @@ +#! /usr/bin/python +import fourletterphat +from matrixKeypad_RPi_GPIO import keypad +from time import sleep + +# Initialize the keypad class +kp = keypad() + +fourletterphat.print_str(" G1?") +fourletterphat.show() + +def digit(): + # Loop while waiting for a keypress + r = None + while r == None: + r = kp.getKey() + return r + +#print ("Please enter a 4 digit code: ") + +# Getting digit 1, printing it, then sleep to allow the next digit press. +d1 = digit() +#print (d1) +sleep(0.25) + +d2 = digit() +#print (d2) +sleep(0.25) + +d3 = digit() +#print (d3) +sleep(0.25) + +d4 = digit() +#print (d4) + +# printing out the assembled 4 digit code. +print "%s%s%s%s"%(d1,d2,d3,d4) +fourletterphat.clear() +fourletterphat.scroll_print("OK %s%s%s%s"%(d1,d2,d3,d4)) +sleep(2) diff --git a/g1sms/tools/matrixKeypad_RPi_GPIO.py b/g1sms/tools/matrixKeypad_RPi_GPIO.py new file mode 100755 index 0000000..c162fcc --- /dev/null +++ b/g1sms/tools/matrixKeypad_RPi_GPIO.py @@ -0,0 +1,102 @@ +# ##################################################### +# Python Library for 3x4 matrix keypad using +# 7 of the avialable GPIO pins on the Raspberry Pi. +# +# This could easily be expanded to handle a 4x4 but I +# don't have one for testing. The KEYPAD constant +# would need to be updated. Also the setting/checking +# of the colVal part would need to be expanded to +# handle the extra column. +# +# Written by Chris Crumpacker +# May 2013 +# +# main structure is adapted from Bandono's +# matrixQPI which is wiringPi based. +# https://github.com/bandono/matrixQPi?source=cc +# ##################################################### + +import RPi.GPIO as GPIO + +class keypad(): + # CONSTANTS + KEYPAD = [ + [1,2,3], + [4,5,6], + [7,8,9], + ["*",0,"#"] + ] + + ROW = [18,23,24,25] + COLUMN = [5,6,13] + + def __init__(self): + GPIO.setmode(GPIO.BCM) + + def getKey(self): + + # Set all columns as output low + for j in range(len(self.COLUMN)): + GPIO.setup(self.COLUMN[j], GPIO.OUT) + GPIO.output(self.COLUMN[j], GPIO.LOW) + + # Set all rows as input + for i in range(len(self.ROW)): + GPIO.setup(self.ROW[i], GPIO.IN, pull_up_down=GPIO.PUD_UP) + + # Scan rows for pushed key/button + # A valid key press should set "rowVal" between 0 and 3. + rowVal = -1 + for i in range(len(self.ROW)): + tmpRead = GPIO.input(self.ROW[i]) + if tmpRead == 0: + rowVal = i + + # if rowVal is not 0 thru 3 then no button was pressed and we can exit + if rowVal <0 or rowVal >3: + self.exit() + return + + # Convert columns to input + for j in range(len(self.COLUMN)): + GPIO.setup(self.COLUMN[j], GPIO.IN, pull_up_down=GPIO.PUD_DOWN) + + # Switch the i-th row found from scan to output + GPIO.setup(self.ROW[rowVal], GPIO.OUT) + GPIO.output(self.ROW[rowVal], GPIO.HIGH) + + # Scan columns for still-pushed key/button + # A valid key press should set "colVal" between 0 and 2. + colVal = -1 + for j in range(len(self.COLUMN)): + tmpRead = GPIO.input(self.COLUMN[j]) + if tmpRead == 1: + colVal=j + + # if colVal is not 0 thru 2 then no button was pressed and we can exit + if colVal <0 or colVal >2: + self.exit() + return + + # Return the value of the key pressed + self.exit() + return self.KEYPAD[rowVal][colVal] + + def exit(self): + # Reinitialize all rows and columns as input at exit + for i in range(len(self.ROW)): + GPIO.setup(self.ROW[i], GPIO.IN, pull_up_down=GPIO.PUD_UP) + for j in range(len(self.COLUMN)): + GPIO.setup(self.COLUMN[j], GPIO.IN, pull_up_down=GPIO.PUD_UP) + +if __name__ == '__main__': + # Initialize the keypad class + kp = keypad() + + # Loop while waiting for a keypress + digit = None + while digit == None: + digit = kp.getKey() + + # Print the result + print digit diff --git a/g1sms/tools/matrixKeypad_RPi_GPIO.pyc b/g1sms/tools/matrixKeypad_RPi_GPIO.pyc new file mode 100755 index 0000000..6d3fee1 Binary files /dev/null and b/g1sms/tools/matrixKeypad_RPi_GPIO.pyc differ