poka 8 months ago
commit
7010403607
100 changed files with 17251 additions and 0 deletions
  1. BIN
      G1Tag.png
  2. 10 0
      GSM_POWERKEY.py
  3. 9 0
      GSM_powerkey.sh
  4. BIN
      _CopyLaRadio/bip.wav
  5. 88 0
      _CopyLaRadio/copy.sh
  6. 75 0
      _CopyLaRadio/libradio/FIP autour de llectro.php
  7. 1 0
      _CopyLaRadio/libradio/Nova zz.php
  8. 1 0
      _CopyLaRadio/libradio/fipelectro-midfi.mp3.php
  9. 74 0
      _CopyLaRadio/libradio/radionova.php
  10. 2808 0
      _CopyLaRadio/libradio/simple_html_dom.php
  11. 12 0
      _CopyLaRadio/parle.sh
  12. 212 0
      _CopyLaRadio/watch.sh
  13. 1 0
      _DU
  14. 1 0
      _chain
  15. 164 0
      _comments
  16. 1 0
      _external
  17. 1 0
      _g1cents
  18. 1 0
      _id
  19. 1 0
      _nanodate
  20. 1 0
      _official
  21. BIN
      _publishkey.gpg
  22. 1 0
      _type
  23. 1 0
      _zen
  24. 43 0
      config.sh
  25. 4 0
      email.txt
  26. 1 0
      g1sms.pub.key
  27. 83 0
      install.sh
  28. 179 0
      install_ipfs_layer.sh
  29. 60 0
      rc.local.sh
  30. 16 0
      search
  31. BIN
      shell/G1sms.png
  32. BIN
      shell/OLove.jpg
  33. BIN
      shell/Oeuro.jpg
  34. BIN
      shell/Portefeuille.png
  35. BIN
      shell/TAG_fond.jpg
  36. BIN
      shell/TAG_fond_G1Tx.jpg
  37. 1 0
      shell/bad.nodes.txt
  38. 151 0
      shell/checknodes.sh
  39. 71 0
      shell/cron_CODE.backup.sh
  40. 40 0
      shell/cron_CODE.upgrade.sh
  41. 49 0
      shell/cron_GCHANGE.sh
  42. 109 0
      shell/cron_MINUTE.sh
  43. 94 0
      shell/cron_VIR.recurrent.sh
  44. 7776 0
      shell/diceware-wordlist.txt
  45. 17 0
      shell/diceware.sh
  46. 615 0
      shell/functions.sh
  47. BIN
      shell/g1.png
  48. 42 0
      shell/g1_gen_pubkey.py
  49. 54 0
      shell/g1_send_transaction.py
  50. BIN
      shell/g1tag.png
  51. 5 0
      shell/good.nodes.txt
  52. 79 0
      shell/init.sh.template
  53. 129 0
      shell/init_keys.sh
  54. 85 0
      shell/natools.py
  55. 9 0
      shell/nodes.txt
  56. 12 0
      shell/parle.sh
  57. 32 0
      shell/request_cesium_profile.py
  58. 37 0
      shell/sms_ABO.sh
  59. 89 0
      shell/sms_ADMIN.sh
  60. 36 0
      shell/sms_AIDE.sh
  61. 157 0
      shell/sms_BILLET.sh
  62. 78 0
      shell/sms_BILLETCHK.sh
  63. 120 0
      shell/sms_BILLET_MAKE.sh
  64. 76 0
      shell/sms_COUNT.sh
  65. 75 0
      shell/sms_DESTROY.sh
  66. 49 0
      shell/sms_EMAIL.sh
  67. 16 0
      shell/sms_ERROR.sh
  68. 278 0
      shell/sms_G1TAG.sh
  69. 58 0
      shell/sms_NEW.sh
  70. 98 0
      shell/sms_PAY.sh
  71. 168 0
      shell/sms_REC.sh
  72. 44 0
      shell/sms_SETUNIT.sh
  73. 102 0
      shell/sms_VIR.sh
  74. 56 0
      shell/sms_WHERE.sh
  75. 164 0
      shell/tag_LOAD_passenger.sh
  76. 164 0
      shell/tag_OP.sh
  77. 68 0
      shell/tag_PLAY_passenger.sh
  78. 250 0
      shell/tag_READ.sh
  79. 91 0
      shell/timeout.sh
  80. 67 0
      silkaj/.gitignore
  81. 662 0
      silkaj/LICENSE
  82. 98 0
      silkaj/README.md
  83. 1 0
      silkaj/authfile
  84. 17 0
      silkaj/doc/argos.md
  85. 18 0
      silkaj/doc/build_with_pyinstaller.md
  86. 31 0
      silkaj/doc/install_on_the_system.md
  87. 39 0
      silkaj/doc/install_pyenv.md
  88. 2 0
      silkaj/licence-G1/.gitignore
  89. 13 0
      silkaj/licence-G1/.gitlab-ci.yml
  90. 5 0
      silkaj/licence-G1/README.md
  91. 78 0
      silkaj/licence-G1/license/license_g1-en.rst
  92. 90 0
      silkaj/licence-G1/license/license_g1-fr-FR.rst
  93. 24 0
      silkaj/licence-G1/package.json
  94. 67 0
      silkaj/release.sh
  95. 7 0
      silkaj/requirements.txt
  96. 1 0
      silkaj/silkaj
  97. 201 0
      silkaj/src/auth.py
  98. 88 0
      silkaj/src/cert.py
  99. 249 0
      silkaj/src/commands.py
  100. 0 0
      silkaj/src/constants.default.py

BIN
G1Tag.png


+ 10 - 0
GSM_POWERKEY.py

@@ -0,0 +1,10 @@
+import RPi.GPIO as GPIO
+import time
+GPIO.setmode(GPIO.BOARD)
+GPIO.setup(7, GPIO.OUT)
+while True:
+	GPIO.output(7, GPIO.LOW)
+	time.sleep(4)
+	GPIO.output(7, GPIO.HIGH)
+	break
+GPIO.cleanup()

+ 9 - 0
GSM_powerkey.sh

@@ -0,0 +1,9 @@
+#!/bin/bash
+if [ ! -e /sys/class/gpio/gpio4 ]; then
+    echo "File exists."
+    echo "4" > /sys/class/gpio/export
+fi
+echo "out" > /sys/class/gpio/gpio4/direction
+echo "0" > /sys/class/gpio/gpio4/value
+sleep 2
+echo "1" > /sys/class/gpio/gpio4/value

BIN
_CopyLaRadio/bip.wav


File diff suppressed because it is too large
+ 88 - 0
_CopyLaRadio/copy.sh


+ 75 - 0
_CopyLaRadio/libradio/FIP autour de llectro.php

@@ -0,0 +1,75 @@
+<?php
+/*
+################################################################################
+# FROM CopyLaRadio MODULE_TEMPLATE_0.1
+# Author: Fred (support@qo-op.com)
+# Date: 2019 04 01
+# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
+################################################################################
+*/
+// VARS INIT
+$obj=$title=$artist=$emission=$ERR=$ontheair="";
+/////////////////////////// 
+// SET TO 1 DURING DEVLT
+$debug=0;
+/////////////////////////// 
+// MODULE RADIO PARAMETERS
+/////////////////////////// 
+$RADIO = "FIP Electro";
+$referer = "https://www.fip.fr/";
+$radiourl = 'https://www.fip.fr/latest/api/graphql?operationName=Now&variables=%7B%22bannerPreset%22%3A%221400x1400%22%2C%22stationId%22%3A74%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%229551487ee4a6810ec4afa35e70dd1c204fa84db3519d39eb3176e5a3a8b0e482%22%7D%7D';
+
+// TWEEK CLIENT & REFERER 
+ini_set('user_agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0');
+$ctx = stream_context_create(array(
+	'http' => array(
+		'header'=>array("Referer: ".$referer.PHP_EOL),
+		'timeout' => 5
+		)
+	)
+);
+/////////////////////////// 
+// LOAD RADIO PAGE INTO PARSER
+$ontheair = file_get_contents($radiourl); // JSON CONTENT
+$ontheair = utf8_encode($ontheair); 
+$obj = json_decode($ontheair, true);
+
+
+// GET TRACK INFO: ADAPT WITH DATA STRUCTURE
+// ADPAPT HERE
+$current = $obj['data']['now']['playing_item'];
+// GET TRACK INFO
+if ( $current ) {
+	// ADPAPT HERE
+	$artist = ucwords(strtolower($current['title']));
+	$title = ucwords(strtolower($current['subtitle']));
+	
+	if ( $debug != 0 ) $ERR .= "\nTITRE = ".print_r($title, true);
+	if ( $debug != 0 ) $ERR .= "\nARTISTE = ".print_r($artist, true);
+
+}
+/////////////////////////// 
+// PREPARE COPY COMMAND
+$cmd = $RADIO.'|'.$artist.'|'.$title;
+
+/////////////////////////// 
+// DEBUG OR PROD
+if($debug == 1) {
+	print_r($obj);
+	print_r($cmd);
+} else {
+	if( $artist != "" && $title != "" ) {
+		// TODO Clean strings?!
+		if (! exec('grep '.escapeshellarg($cmd).' /tmp/ytdl.list')) {
+			file_put_contents("/tmp/youtube-dl.log", "ARTIST: ".$artist.". SONG: ".$title, FILE_APPEND);
+			file_put_contents("/tmp/ytdl.list","$cmd\n", FILE_APPEND);
+		} else {
+			file_put_contents("/tmp/youtube-dl.log", "ALREADY THERE!", FILE_APPEND);
+			file_put_contents("/tmp/ytdl.list","||".PHP_EOL, FILE_APPEND);
+		}
+	} else {
+		file_put_contents("/tmp/youtube-dl.log", "NO TRACK. TRY PODCAST!", FILE_APPEND);
+		file_put_contents("/tmp/ytdl.list","||".PHP_EOL, FILE_APPEND);
+	}
+}
+?>

+ 1 - 0
_CopyLaRadio/libradio/Nova zz.php

@@ -0,0 +1 @@
+radionova.php

+ 1 - 0
_CopyLaRadio/libradio/fipelectro-midfi.mp3.php

@@ -0,0 +1 @@
+FIP autour de llectro.php

+ 74 - 0
_CopyLaRadio/libradio/radionova.php

@@ -0,0 +1,74 @@
+<?php
+/*
+################################################################################
+# FROM CopyLaRadio MODULE_TEMPLATE_0.1
+# Author: Fred (support@qo-op.com)
+# Date: 2019 04 01
+# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
+################################################################################
+*/
+// VARS INIT
+$obj=$title=$artist=$emission=$ERR=$ontheair="";
+/////////////////////////// 
+// SET TO 1 DURING DEVLT
+$debug=0;
+/////////////////////////// 
+// MODULE RADIO PARAMETERS
+/////////////////////////// 
+$RADIO = "RADIO NOVA";
+$referer = "http://www.nova.fr/";
+$radiourl = 'http://www.nova.fr/radio/19577/player';
+
+// TWEEK CLIENT & REFERER 
+ini_set('user_agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0');
+$ctx = stream_context_create(array(
+	'http' => array(
+		'header'=>array("Referer: ".$referer.PHP_EOL),
+		'timeout' => 5
+		)
+	)
+);
+/////////////////////////// 
+// LOAD RADIO PAGE INTO PARSER
+$ontheair = file_get_contents($radiourl); // JSON CONTENT
+$ontheair = utf8_encode($ontheair); 
+$obj = json_decode($ontheair, true);
+
+
+// GET TRACK INFO: ADAPT WITH DATA STRUCTURE
+// ADPAPT HERE
+if ( $obj['currentTrack'] ) {
+
+	// ADPAPT HERE
+	$title = ucwords(strtolower($obj['currentTrack']['title']));
+	$artist = ucwords(strtolower($obj['currentTrack']['artist']));
+	
+	if ( $debug != 0 ) $ERR .= "\nTITRE = ".print_r($title, true);
+	if ( $debug != 0 ) $ERR .= "\nARTISTE = ".print_r($artist, true);
+
+}
+/////////////////////////// 
+// PREPARE COPY COMMAND
+$cmd = $RADIO.'|'.$artist.'|'.$title;
+
+/////////////////////////// 
+// DEBUG OR PROD
+if($debug == 1) {
+	print_r($obj);
+	print_r($cmd);
+} else {
+	if( $artist != "" && $title != "" ) {
+		// TODO Clean strings?!
+		if (! exec('grep '.escapeshellarg($cmd).' /tmp/ytdl.list')) {
+			file_put_contents("/tmp/youtube-dl.log", "ARTIST: ".$artist.". SONG: ".$title, FILE_APPEND);
+			file_put_contents("/tmp/ytdl.list","$cmd\n", FILE_APPEND);
+		} else {
+			file_put_contents("/tmp/youtube-dl.log", "ALREADY THERE!", FILE_APPEND);
+			file_put_contents("/tmp/ytdl.list","||".PHP_EOL, FILE_APPEND);
+		}
+	} else {
+		file_put_contents("/tmp/youtube-dl.log", "NO TRACK. TRY PODCAST!", FILE_APPEND);
+		file_put_contents("/tmp/ytdl.list","||".PHP_EOL, FILE_APPEND);
+	}
+}
+?>

File diff suppressed because it is too large
+ 2808 - 0
_CopyLaRadio/libradio/simple_html_dom.php


+ 12 - 0
_CopyLaRadio/parle.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+f=$(echo "$1" | sed 's/ //g' )
+echo "parle.sh: $1 | $2 = $f" >> /tmp/youtube-dl.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

+ 212 - 0
_CopyLaRadio/watch.sh

@@ -0,0 +1,212 @@
+#!/bin/bash
+# BUTTONS GPIO NUMBERS FOR PHAT BEAT
+# https://pinout.xyz/pinout/phat_beat#
+# ADD TO /etc/local for autostart
+#
+ONOFF=12
+VOLUP=16
+VOLDO=26
+BCK=13
+PLAY=6
+FWD=5
+
+# ADD YOUR DEFAULT RADIO STREAM / PLAYLIST HERE - TRACK INFORMATION FOR RECORDING ;)
+PLAYLIST="/home/pi/playlists/default.m3u"
+
+function trim() {
+	local var="$*"
+	# remove slashes
+	var=$(echo "$var" | sed 's/\// /g')
+	var=${var//[^a-zA-Z0-9_\. ]/}
+	# remove leading whitespace characters
+	var="${var#"${var%%[![:space:]]*}"}"
+	# remove trailing whitespace characters
+	var="${var%"${var##*[![:space:]]}"}" 
+
+	echo -n "$var"
+}
+
+function button() {
+  pin=$1
+  gpio -g mode $pin in # make sure pin is configured as an input
+  gpio -g mode $pin up # enable pull-up resistor
+  boucle=0
+
+  while :; do
+	gpio -g wfi $pin falling # wait for a button action
+	sleep 0.2
+	echo $pin
+	while [[ $(gpio -g read $pin) -eq 0 ]]
+	do
+		aplay bip.wav
+		sleep 0.5 # COUNT 1/2 SECOND PRESSED
+		boucle=$(bc -l <<< "$boucle + 1")
+	done
+	if [[ $boucle -gt 0 ]]; then
+		echo "LP-$pin-$boucle"
+	fi
+	boucle=0
+  done
+}
+
+boucle=0
+
+# --- main loop ---
+while :; do
+  read numbut
+
+	# WHAT IS ON AIR
+	watch="$(mpc | head -1):"
+
+	# EXTRACT ($radio :) $artist - $song
+	radio=$(echo "$watch" | cut -d ":" -f 1 | xargs)
+	if [[ "$radio" != "$watch" && $radio != "volume" && $radio != "http" ]]; then RADIO="$radio"; else radio="$watch"; RADIO=""; fi
+	play=$(echo "$watch" | cut -d ":" -f 2)
+	artist=$(echo "$play" | cut -d "-" -f 1)
+	artist=$(trim "$artist")
+	song=$(echo "$play" | cut -d "-" -f 2)
+	song=$(trim "$song")
+	if [[ "$song" == "" ]]; then
+		song=$(echo "$play" | cut -d " " -f 2)
+		song=$(trim "$song")
+	fi
+
+	# TODO: ADAPT BEHAVIOUR TO EACH RADIO STREAM
+    # NOVA RADIO PATCH
+    if [[ "$radio" == "Nova zz" ]]; then
+        artist=""
+        song=""
+    fi
+
+	echo "(CLICK $numbut) $RADIO: $artist / $song"
+	
+	case "$numbut" in
+	$ONOFF)
+		echo "REC"
+		# BUTTON QUICK RELEASE
+		if [[ $(gpio -g read $ONOFF) -eq 1 ]]; then
+			# RECORD STREAMING SONG::GENERIC
+			if [[ "$RADIO" != "" && "$artist" != "" && "$song" != "" && "$artist" != "$song" ]]; then
+				what=$(grep "$RADIO|$artist|$song" /tmp/ytdl.list)
+				if [[ "$what" == ""  ]]; then
+					~/parle.sh "Enregistrement ajouté."
+					echo "$RADIO|$artist|$song" >> /tmp/ytdl.list
+				else
+					~/parle.sh "Enregistrement déjà existant!"
+				fi
+			elif [[ "$artist" == "$song" ]]; then
+				~/parle.sh "Enregistrement $radio"
+				# USE COPY & MODULE FIFO
+				echo "$radio||" >> /tmp/ytdl.list # TODO REMOVE
+			else
+				~/parle.sh "Podcast ou Fichier local. Enregistrement inopérant."
+			fi
+		fi
+	;;
+	LP-$ONOFF-*)
+		# LONG PRESS TRACK IDENTIFICATION
+		playing=$(mpc | head -1 | cut -d ":" -f 1 | cut -d "/" -f 1 | xargs)
+		playing=$(trim "$playing")
+		~/parle.sh "$playing"
+		if [[ "$RADIO" != "" && "$artist" != "" && "$song" != "" && "$artist" != "$song" ]]; then
+			~/parle.sh "$artist - $song"
+		fi
+	;;
+	$PLAY)
+		echo "PLAY"
+		if [[ $(gpio -g read $PLAY) -eq 1 ]]; then
+			mpc toggle
+		fi		
+	;;
+	LP-$PLAY-*)
+		sec=$(echo "$numbut" | cut -d "-" -f 3)
+		case "$sec" in
+		1)
+		# 1SEC 
+			# Check if USB drive connected
+			if [[ -b /dev/sda1 ]]; then
+				~/parle.sh "Synchronisation musique sur clé U S B. Veuillez patienter"
+				sudo mount /dev/sda1 /mnt
+				sudo mkdir -p /mnt/CopyLaRadio
+				sudo rsync -rtgoDv /home/pi/music/ /mnt/CopyLaRadio
+				sudo umount /dev/sda1
+				~/parle.sh "Transfert terminé. Vous pouvez débrancher votre clé..."
+			else
+			# STOP MUSIC
+			 	~/parle.sh "STOP"
+				mpc stop
+			fi
+		;;
+		2)
+		# 2SEC = CHANGE MODE SHUFFLE LOCAL / DEFAULT PLAYLIST
+		if [[ "$RADIO" != "" && "$mode" == "" ]]; then
+			mode="LOCAL"
+			~/parle.sh "Lecture musique locale"
+			mpc clear
+			mpc listall | mpc add
+			mpc shuffle
+			~/parle.sh "Aléatoire"
+			mpc play
+		else
+			mode=""
+			mpc clear
+			mpc load default
+			~/parle.sh "Lecture liste par défaut"
+			mpc play
+		fi
+		;;
+		3)
+		#  3 SEC = HALT SYSTEM
+			~/parle.sh "Arrêt RAIQUE MACHINE"
+			sudo halt
+		;;				
+		*)
+		#  > 3 SEC = REBOOT SYSTEM
+			~/parle.sh "Redémarrage RAIQUE MACHINE"
+			sudo reboot
+		;;		
+		esac
+	;;
+	$BCK)
+		echo "BCK"
+			mpc -q prev
+	;;
+	$FWD)
+		echo "FWD"
+			mpc -q next
+	;;
+	$VOLUP)
+		echo "VOLUP"
+		if [[ $(gpio -g read $VOLUP) -eq 1 ]]; then
+			mpc -q volume +10
+			vol=$(mpc volume | cut -f 2 -d ":")
+			vol=$(trim "$vol")
+			if [ "$vol" == "100%" ]; then ~/parle.sh "VOLUME MAXIMUM"; fi
+		fi
+	;;
+	LP-$VOLUP-*)
+		sec=$(echo "$numbut" | cut -d "-" -f 3)
+		sec=+$(bc -l <<< "$sec * 10")
+		mpc -q volume $sec
+	;;
+	$VOLDO)
+		echo "VOLDO"
+		if [[ $(gpio -g read $VOLDO) -eq 1 ]]; then
+			mpc -q volume -10
+			vol=$(mpc volume | cut -f 2 -d ":")
+			vol=$(trim "$vol")
+			if [ "$vol" == "0%" ]; then ~/parle.sh "VOLUME MINIMUM"; fi
+		fi
+	;;
+	LP-$VOLDO-*)
+		sec=$(echo "$numbut" | cut -d "-" -f 3)
+		sec=-$(bc -l <<< "$sec * 10")
+		mpc -q volume $sec
+	;;
+	*)
+		echo $numbut
+	;;
+	esac
+
+done < <( button $ONOFF & button $VOLUP & button $VOLDO & button $BCK & button $PLAY & button $FWD & ) # buttons on GPIOs to monitor
+

+ 1 - 0
_DU

@@ -0,0 +1 @@
+1011

+ 1 - 0
_chain

@@ -0,0 +1 @@
+QmYZA2BruxJBrv8sDtjCfwTeB4hCFGBJsCAyUEyktB3PYs

+ 164 - 0
_comments

@@ -0,0 +1,164 @@
+Create BASIC IPNS _official IPFS HASH _chain (with iterative backup to _nanodate time, _zen / _g1 values + _external UID references): backup.sh
+Ajout de paramètres à la capsule IPNS/IPFS. _id et du backup autosigné de la clef de publication ipfs _publishkey.gpg
+Hop +1
+GO
+HOP
+update.sh
+Add init.sh
+RUN ./install.sh then ./shell/cron/update.sh
+base64 "/home/$YOU/.ipfs/keystore/SWARM_CODE_MASTER" for IPNS key
+fn_exists()
+ET LA CA PROPAGE
+/ipns/QmZHTne3bjtMgaXWRqSbdKchJbgq2NaAeVSzFUN7ceYpif/install.sh
+again
+oui
+
+_publishkey.pgp SWARM_CODE_MASTER
+HELLO
+DEBUG DAY
+MORE DEBUG. VIR RECURRENT IS ALMOST WORKING
+SMS TESTS & DEBUG
+OK
+BACKUP
+
+
+
+
+
+OK
+2019-10-24: install.sh
+2019-10-24: 
+2019-10-24: 
+2019-10-24: 
+2019-10-24: install.sh
+2019-10-24: ipfs cat /ipns/QmZHTne3bjtMgaXWRqSbdKchJbgq2NaAeVSzFUN7ceYpif/CODE/install.sh | bash
+2019-10-25: 
+2019-10-25: config.sh
+2019-11-02: BACKUP
+2019-11-04: Woooo too long to explain. G1Tag remake
+2019-11-04: encore
+2019-11-04: tag_READ.sh
+2019-11-04: YOU fix
+2019-11-04: cleaning
+2019-11-04: 
+2019-11-04: gpg -d --output /tmp/ipns.key --passphrase $B /tmp/TAG_publishkey.B.gpg
+2019-11-04: --pinentry-mode=loopback
+2019-11-04: parle
+2019-11-04: .
+2019-11-04: 01
+2019-11-04: 
+2019-11-04: 
+2019-11-04: tag READ
+2019-11-04: echo
+2019-11-04: tag actions
+2019-11-04: 
+2019-11-04: tag_READ
+2019-11-04: LOVE
+2019-11-04: YOU=$(ps auxf --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1)
+2019-11-04: g1sms.priv.key
+2019-11-04: next
+2019-11-04: 
+2019-11-04: 
+2019-11-04: tag
+2019-11-04: 
+2019-11-05: hummmm
+2019-11-05: backup
+2019-11-05: 
+2019-11-05: CASHBACK
+2019-11-05: checkonenode
+2019-11-05: G1tag read
+2019-11-05: NN
+2019-11-05: 
+2019-11-06: time for a backup
+2019-11-06: bad start
+2019-11-06: YOU=$(ps auxf --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1)
+2019-11-06: DU
+2019-11-06: Update _DU value
+2019-11-06: 
+2019-11-06: SMSNODE
+2019-11-06: 
+2019-11-06: toucassé
+2019-11-06: bug init.sh
+2019-11-06: config.sh
+2019-11-06: 
+2019-11-06: 
+2019-11-06: echo ipfs_swarm_wallets_refresh
+2019-11-06: sms_INIT_ACCOUNT migration old G1sms wallets params
+2019-11-06: HISTORY files modification
+2019-11-06: 
+2019-11-07: yeah
+2019-11-08: oula
+2019-11-08: correct
+2019-11-08: hop
+2019-11-08: bugs
+2019-11-08: ouep
+2019-11-14: After Crash and restore on better SDcard
+2019-11-15: 
+2019-11-15: waiwai
+2019-11-15: TASK s
+2019-11-15: 
+2019-11-15: 
+2019-11-15: sais plius
+2019-11-16: remote G1DAB MINUTE PRINT
+2019-11-16: tag READ OP
+2019-11-16: /
+2019-11-16: tag_OP.sh
+2019-11-16: tag READ
+2019-11-16: 
+2019-11-16: tag_READ.sh and tag_OP.sh OK. Need sudo pip3 install duniterpy for natools.py to work
+2019-11-16: TASK bug
+2019-11-17: value
+2019-11-17: clean PRINT
+2019-11-19: 
+2019-11-19: 
+2019-11-19: 
+2019-11-19: 
+2019-11-19: self
+2019-11-19: PASSENGER
+2019-11-19: 
+2019-11-19: PRINT clean
+2019-11-19: email
+2019-11-19: mail
+2019-11-19: emial
+2019-11-19: upgrades
+2019-11-19: ameliorations
+2019-11-19: qr code
+2019-11-19: install.sh su £YOU ips
+2019-11-20: gpg -d --output /tmp/ipns.key --pinentry-mode=loopback --passphrase $BB /tmp/TAG_publishkey.B.gpg
+2019-11-20: 
+2019-11-20: FID
+2019-11-20: tag READ problem
+2019-11-20: hop
+2019-11-20: read line
+2019-11-20: cat /dev/ttyACM0
+2019-11-20: tag read
+2019-11-20: TAG_passenger
+2019-11-22: REC TIME - 1
+2019-11-22: VIR recurrents check and removal
+2019-11-23: LOAD passenger
+2019-11-23: chmod 755 shell/*.sh
+2019-11-23: 
+2019-11-23: 
+2019-11-23: fi
+2019-11-23: bug
+2019-11-23: REC Tag ready?
+2019-11-23: 
+2019-11-23: yep
+2019-11-23: 
+2019-11-24: rompr
+2019-11-24: chown www-data prefs/ albumart/
+2019-11-24: 777 for rompr variables
+2019-11-24: echo "" > www/rompr-1.32.zip
+2019-11-24: 
+2019-11-24: Rompr patch [REC]
+2019-11-24: infobar2.js
+2019-11-24: FID=$(echo $ID | awk '{print toupper($1)}')
+2019-11-24: fip electro
+2019-11-24: FIP
+2019-11-24: Nova
+2019-11-25: Nova zz
+2019-11-25: NODE = $IPFSNODEID
+2019-11-25: for id in ./wallets_swarm/.Qm*/ instead of ipfs swarm peers
+2019-11-25: 
+2019-11-26: clean
+2019-11-27: sms

+ 1 - 0
_external

@@ -0,0 +1 @@
+

+ 1 - 0
_g1cents

@@ -0,0 +1 @@
+0

+ 1 - 0
_id

@@ -0,0 +1 @@
+SWARM_CODE_MASTER

+ 1 - 0
_nanodate

@@ -0,0 +1 @@
+1574863684133516892

+ 1 - 0
_official

@@ -0,0 +1 @@
+QmZHTne3bjtMgaXWRqSbdKchJbgq2NaAeVSzFUN7ceYpif

BIN
_publishkey.gpg


+ 1 - 0
_type

@@ -0,0 +1 @@
+GIT

+ 1 - 0
_zen

@@ -0,0 +1 @@
+0

+ 43 - 0
config.sh

@@ -0,0 +1,43 @@
+#!/bin/bash
+################################################################################
+# Author: Fred (support@qo-op.com)
+# Version: 0.1
+# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
+################################################################################
+now=$(date +%Y-%m-%d)
+
+echo "Ce script configure votre noeud G1sms+ (effacez ./shell/init.sh avant de le lancer)"
+IPFS=$(ps auxf --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1);
+
+if [[ -f ./shell/init.sh.template && ! -f ./shell/init.sh ]]; then
+    echo "Quel est l'utilisateur du système IPFS (détecté: $IPFS)?"
+    read YOU
+    if [[ "$YOU" == "" ]]; then YOU=$IPFS; fi
+
+    echo "Votre PSEUDO? (celui de votre Compte membre Duniter)"
+    read ADMINPSEUDO
+    if [[ "$ADMINPSEUDO" == "" ]]; then echo "IMPOSSIBLE DE CONTINUER"; exit; fi
+
+    echo "Le Numéro de téléphone SMS Admin? (Support de ce noeud) (ex +33611223344)"
+    read ADMINPHONE
+    if [[ "$ADMINPHONE" == "" ]]; then echo "IMPOSSIBLE DE CONTINUER"; exit; fi
+
+    echo "Le numéro de la carte SIM, du module SMS? (ex +33611223344)"
+    read MASTERPHONE
+
+    echo "L'adresse où se trouve votre G1Node pour indiquer où venir chercher ses G1Tag (ex: au G1FabLab de Toulouse)"
+    read ADRESSE
+
+    sed -i s/pi/$YOU/g ./shell/init.sh.template
+    sed -i s/+33660780131/$MASTERPHONE/g ./shell/init.sh.template
+    sed -i s/au\ G1FabLab\ de\ Toulouse/$ADRESSE/g ./shell/init.sh.template
+    sed -i s/+33647683646/$ADMINPHONE/g ./shell/init.sh.template
+    sed -i s/Fred/$ADMINPSEUDO/g ./shell/init.sh.template
+
+    cat ./shell/init.sh.template
+
+    echo "LES PARAMETRES SONT BONS? Appliquer? ENTER ou CTRL-C ?"
+    read
+    cp ./shell/init.sh.template ./shell/init.sh
+fi
+

+ 4 - 0
email.txt

@@ -0,0 +1,4 @@
+From: support@qo-op.com
+To: EMAIL
+Subject: SUBJECT
+MESSAGE

+ 1 - 0
g1sms.pub.key

@@ -0,0 +1 @@
+8qs69HriAdytcCLzvQGJ15XBwpjAVFx8JoVM2ahue1y7

+ 83 - 0
install.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/)
+################################################################################
+# LE Freaking LOL Hackathon de Noël https://framadate.org/sviOUlP6JLyWq5D2XLEdcKY9/admin
+#
+now=$(date -u +%Y-%m-%d)
+
+echo "Bonjour $USER, je vous souhaite bon jour ($now)"
+echo "Ce script va installer / mettre à jour votre noeud G1sms dans /home/$USER/G1sms+"
+echo "ATTENTION! Vous devez avoir installé la couche ipfs & mpd au préalable!!! ./install_ipfs_layer.sh"
+IPFS=$(ps auxf --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1);
+echo "Quel est l'utilisateur du système IPFS (détecté: $IPFS)?"
+read YOU
+if [[ "$YOU" == "" ]]; then YOU=$IPFS; fi
+
+cd /home/$USER
+echo "Déplacement dans /home/$USER/"
+echo "... Téléchargement de la dernière version du CODE G1sms+ (ipfs = $YOU)"
+
+# CODE is there?? Get it from ipns
+ipfs get --output=./ /ipns/QmZHTne3bjtMgaXWRqSbdKchJbgq2NaAeVSzFUN7ceYpif
+
+if [ ! -d ./G1sms+ ]; then
+
+    echo "RECHERCHE ET INSTALLATION DU CODE : G1sms+.latest.tgz "
+    if [[ -f "./CODE/G1sms+.latest.tgz" ]]; then
+        tar xzf ./CODE/G1sms+.latest.tgz
+    fi
+
+    echo "VOULEZ VOUS CONFIGURER VOTRE NODE G1sms+ ? ^C"
+    echo "Les paramètres se trouvent dans /home/$YOU/G1sms+/shell/init.sh"
+    read
+
+    echo "Votre PSEUDO? Celui de votre compte membre Duniter. (defaut: Fred)"
+    read ADMINPSEUDO
+    if [[ "$ADMINPSEUDO" == "" ]]; then ADMINPSEUDO="Fred"; fi
+
+    echo "Le Numéro de téléphone SMS Admin? Votre numéro de portable (defaut: +33647683646)"
+    read ADMINPHONE
+    if [[ "$ADMINPHONE" == "" ]]; then ADMINPHONE="+33647683646"; fi
+
+    echo "Le numéro de la carte SIM, du module SMS. AUCUNE liaison SMS? Laissez vide (défaut: +33611223344)"
+    read MASTERPHONE
+    if [[ "$MASTERPHONE" == "" ]]; then MASTERPHONE="+33611223344"; fi
+
+    # TODO ASK for GeoPoint
+    echo "L'adresse où se trouve votre G1Node pour indiquer où venir chercher les G1Tag imprimés (ex: au G1FabLab de Toulouse)"
+    read ADRESSE
+z
+    cp /home/$YOU/G1sms+/shell/init.sh.template /home/$YOU/G1sms+/shell/init.sh
+    sed -i s/pi/$YOU/g /home/$YOU/G1sms+/shell/init.sh
+    sed -i s/+33660780131/$MASTERPHONE/g /home/$YOU/G1sms+/shell/init.sh
+    sed -i s/au\ G1FabLab\ de\ Toulouse/$ADRESSE/g /home/$YOU/G1sms+/shell/init.sh
+    sed -i s/+33647683646/$ADMINPHONE/g /home/$YOU/G1sms+/shell/init.sh
+    sed -i s/Fred/$ADMINPSEUDO/g /home/$YOU/G1sms+/shell/init.sh
+
+    echo "========================================="
+    echo "VERIFIEZ QUE LES PARAMETRES SONT BONS... "
+    echo "========================================="
+    cat /home/$YOU/G1sms+/shell/init.sh
+    echo "========================================="
+    echo "CONFIG: vi /home/$YOU/G1sms+/shell/init.sh "
+    echo "========================================="
+
+else
+    echo "VOUS AVEZ UNE VERSION de G1sms+ DEJA INSTALLEE. MISE A JOUR..."
+    tar xzf CODE/G1sms+.latest.tgz
+
+    cd G1sms+
+    # TODO
+    # sudo chown -R $YOU ./TAG
+    # sudo chown -R $YOU ./wallets
+    echo "PREPARE rompr access from nginx"
+    mkdir -p ./www/rompr/prefs
+    mkdir -p ./www/rompr/albumarts
+    chmod 777 ./www/rompr/prefs
+    chmod 777 ./www/rompr/albumarts
+
+    echo "Version installée ($now):: IPFS chain :: $(cat ./_chain)"
+fi

+ 179 - 0
install_ipfs_layer.sh

@@ -0,0 +1,179 @@
+#!/bin/bash
+################################################################################
+# Author: Fred (support@qo-op.com)
+# Version: 0.1
+# License: AGPL-3.0 (https://choosealicense.com/licenses/agpl-3.0/)
+###########################################################################################
+#######################################
+# INSTALL IPFS on G1sms+ Pi NODES
+#######################################
+echo "DEFAULT INSTALL SCRIPT. VALIDATED ON RASPBERRYPI, SHOULD BE ADAPTED IF NOT ARM ARCH SYSTEM.
+You are going to download and install ipfs daemon environement for running G1sms+ NODE.
+TODO: TEST TEST TEST TEST + MANAGE DIFFERENT ARCH
+Ready?"
+read
+
+if [[ "$USER" == "root" ]]; then echo "Better run by 'pi', please create non-root user and become that user before launching ipfs install..."; exit;
+else echo "$USER, let's go!";
+fi
+ 
+echo "GET ipfs-update"
+cd /usr/src/
+sudo wget https://dist.ipfs.io/ipfs-update/v1.5.2/ipfs-update_v1.5.2_linux-arm.tar.gz
+
+echo "INSTALL ipfs-update"
+sudo tar xvzf ipfs-update_v1.5.2_linux-arm.tar.gz
+cd ipfs-update
+sudo ./install.sh 
+
+echo "INSTALL latest ipfs"
+sudo ipfs-update install latest
+
+echo "CREATE SYSTEMD ipfs SERVICE"
+sudo cat > /etc/systemd/system/ipfs.service << EOF
+[Unit]
+Description=IPFS daemon
+After=network.target
+
+[Service]
+User=$USER
+ExecStart=/usr/local/bin/ipfs daemon --enable-pubsub-experiment --enable-namesys-pubsub --enable-gc
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+sudo systemctl daemon-reload
+sudo systemctl enable ipfs
+
+################
+# BECOME $USER
+# INIT ipfs
+ipfs init -p lowpower
+
+# ACTIVATE CONFIG OPTIONS
+# PUBSUB
+ipfs config Pubsub.Router gossipsub
+# MAXSTORAGE
+ipfs config Datastore.StorageMax 12GB
+## PORT FORWARD (SSH)
+ipfs config --json Experimental.Libp2pStreamMounting true
+
+######### UPDATE BOOTSTRAP LIST ###########
+ipfs bootstrap rm --all
+### fred@onelove.madeinzion.org ###
+# ID: QmSX7gFRPHui5A2DWFk2VmBvq6hynj2hubhJLQAwPWe4Lh
+ipfs bootstrap add /ip6/fe80::207:cbff:fe0b:75bb/tcp/4001/ipfs/QmSX7gFRPHui5A2DWFk2VmBvq6hynj2hubhJLQAwPWe4Lh
+ipfs bootstrap add /ip4/51.15.2.211/tcp/4001/ipfs/QmSX7gFRPHui5A2DWFk2VmBvq6hynj2hubhJLQAwPWe4Lh
+### ADD NEW SWARM LEADERS SERVER HERE ###
+
+# ALLOW REMOTE SSH CONNECTION FROM rec OR onelove (For swarm.key & keystore exchange )
+# ADD SSH ADMIN/SUPPORT USERS $(cat .ssh/id_rsa.pub)
+echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCs6oXRmPukaX7u2tDcFF1cecsDSEA30YyUqDaXSrw+yWQ8G79ktZ7BN0bPYBgfxO59FU8l5Jg1SPPG9kj81jfoCwGJpYdbczmMuP/iqw3aNoGv66swxwxzrqzbHrFFCXgn+6B2spDjn87tFB8JvQQTb2Kc4/sAZ9E6eY61pFiNpqbQehXdqSV5UemV9dkSQrnmJTl1PjUQ474AKQwFPzpdKHD/3VvqQS4i7ZLVeXS65euOP/YY8Bx9HvhsmhJ3h78OOK+D6GFfyv010xXBoG6kCSYR8LYMCEexpPGYV+Mduf/tUHjHP4GuWZAhd+wLRl0uPy6Tv7wHFfLyN01m/9vl fred@rec" >> ~/.ssh/authorized_keys
+echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFthQ3FggJlz/+ZglZJjVJzYs6ehx/iB7f89KY396K+7ai4ETqFhq6ANVp9xeQ4dLU26w0bFBELcnh9rn5QDSrXjsIptoWXErkSdZOeXqofnLtJEOhZO/I328y0C1vQRwtMMXKLLnqPe14h+zJenc7KJbL5cvB3Hd7nfQ+Q0uEnIsKb0f5wcKagySHIFdmY/FqaGz5g4MXGq7nlX/31hvfTFhF0g+k3mhvTTVQ368Op9qZZIozYhBoojWWvK5mwAovxdS9QT1hKrFXHfjov/aKQxLAy0a0oxFvHKoYN/l4ffGibFMAmedljTxf1VSDBv/k/RN53UU6RufW3qqBjY0b fred@onelove" >> ~/.ssh/authorized_keys
+
+# START ipfs
+sudo systemctl start ipfs
+
+##################################
+## INSTALL TOOLS
+######## YOUTUBE-DL ##########
+sudo wget https://yt-dl.org/downloads/latest/youtube-dl -O /usr/local/bin/youtube-dl
+sudo chmod a+rx /usr/local/bin/youtube-dl
+sudo apt install libid3-tools mpd mpc lame -y
+
+## CONFIG MPD
+sudo cat > /etc/mpd.conf << EOF
+music_directory                 "/home/$USER/music"
+playlist_directory              "/home/$USER/playlists"
+user                            "$USER"
+bind_to_address                 "any"
+auto_update                     "yes"
+zeroconf_enabled                "yes"
+zeroconf_name                   "CopyLaRadio Music Recorder"
+
+filesystem_charset              "UTF-8"
+id3v1_encoding                  "UTF-8"
+###############################
+
+    audio_output {
+        type		"pulse"
+        name		"My Pulse Output"
+        server		"127.0.0.1"
+    }
+
+    audio_output {
+        type            "httpd"
+        name            "CopyLaRadio HTTP Stream"
+        encoder         "lame"
+        port            "8000"
+        quality         "5.0"
+        # bitrate       "128"
+        format          "44100:16:1"
+    }
+EOF
+
+sudo chown -R $USER /var/lib/mpd/ /var/run/mpd /run/mpd /var/log/mpd
+sudo service mpd restart
+
+sudo apt-get install nginx php-curl php-sqlite3 php-gd php-json php-xml php-mbstring php-fpm sqlite -y
+sudo apt-get install lame sox libsox-fmt-mp3 eyed3 python-chardet libav-tools imagemagick curl -y
+sudo apt-get install ca-certificates git-core binutils rsync alsa-utils bc libid3-tools espeak mpg321 fuse libttspico-utils atomicparsley -y
+
+# CONFIG NGINX
+sudo cat > /etc/nginx/sites-available/default << EOF
+server {
+listen 80 default_server;
+listen [::]:80 default_server;
+
+root /home/$USER/G1sms+/www/rompr;
+index index.html index.htm index.nginx-debian.html;
+
+server_name _;
+
+location /g1tag {
+    proxy_pass http://127.0.0.1:81;
+    proxy_set_header Host            \$host;
+    proxy_set_header X-Forwarded-For \$remote_addr;
+}
+
+location /code/ {
+	proxy_pass http://127.0.0.1:8080/ipns/QmZHTne3bjtMgaXWRqSbdKchJbgq2NaAeVSzFUN7ceYpif/;
+	proxy_set_header Host \$host;
+	proxy_set_header X-Real-IP \$remote_addr;
+	proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
+}
+
+location /ipfs {
+    proxy_pass http://127.0.0.1:8080;
+    proxy_set_header Host \$host;
+    proxy_set_header X-Forwarded-For \$remote_addr;
+}
+
+location /ipns {
+    proxy_pass http://127.0.0.1:8080;
+    proxy_set_header Host \$host;
+    proxy_set_header X-Forwarded-For \$remote_addr;
+}
+}
+EOF
+
+sudo systemctl restart nginx
+
+#################################
+## Get _CopyLaRadio distrib
+# ipfs get Qm.... > /tmp/copylaradio.zip
+
+# Add CopyLaRadio to system PATH
+#export PATH=$PATH:/home/$USER/_CopyLaRadio
+# etc....
+
+# INSTALL ROMPR WebSite LINKs
+#sudo ln -s /home/$USER/_CopyLaRadio/www/rompr /var/www/rompr
+#sudo chmod 777 /home/$USER/_CopyLaRadio/www/rompr/albumart
+#sudo chmod 777 /home/$USER/_CopyLaRadio/www/rompr/prefs
+
+
+
+

+ 60 - 0
rc.local.sh

@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# This script modify rc.local to start G1sms+ G1Tag, G1Tx and _CopyLaRadio scripts 
+######################################################################
+# INJECT it self
+######################################################################
+inserted=$(grep -Rw "rc.local.sh" /etc/rc.local)
+if [[ ! $inserted ]]; then
+    sed -i s/exit\ 0//g /etc/rc.local
+    echo "include /home/pi/G1sms+/rc.local.sh" >> /etc/rc.local
+    echo "exit 0" >> /etc/rc.local
+fi
+######################################################################
+
+# mpd Runs like pi and some rights are bad!!
+chown -R pi /var/run/mpd
+chown -R pi /run/mpd
+# RESET LOG
+echo "" > /var/log/mpd/mpd.log
+
+# CREATE EXCHANGE FILEs for pi & www-data
+touch /tmp/ytdl.list
+chmod 664 /tmp/ytdl.list
+chown pi:www-data /tmp/ytdl.list
+
+touch /tmp/youtube-dl.log
+chmod 664 /tmp/youtube-dl.log
+chown pi:www-data /tmp/youtube-dl.log
+
+# LAUNCH BUTTONS WATCH
+su pi -c "/home/pi/G1sms+/_CopyLaRadio/watch.sh &"
+# LAUNCH COPY SCRIPT
+su pi -c "/home/pi/G1sms+/_CopyLaRadio/copy.sh &"
+
+# Print the IP address
+_IP=$(hostname -I  | cut -d " " -f 1) || true
+if [ "$_IP" ]; then
+  printf "IP address is %s\n" "$_IP"
+  /home/pi/G1sms+/shell/parle.sh "Adresse IP: $_IP"
+  youtube-dl -U
+  /home/pi/G1sms+/shell/parle.sh "Mise à jour de Youtube DL. Terminé!"
+  #IPFS
+  YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1)
+  if [[ "$YOU" != "" && "$YOU" != "root" ]]; then
+    /home/pi/G1sms+/shell/parle.sh "IPFS OK. Système de fichier interplanétaire activé."
+  fi
+else
+  /home/pi/G1sms+/shell/parle.sh "Connexion Internet Impossible!"
+fi
+
+# LANCEMENT G1Tag READ
+if [[ -e "/dev/ttyACM0" ]]; then
+    cd /home/pi/G1sms+ && ./shell/tag_READ.sh &
+    /home/pi/G1sms+/shell/parle.sh "Lecteur G1 tag"
+fi
+
+if [[ -d "/home/pi/G1sms+/www/rompr" ]]; then
+    /home/pi/G1sms+/shell/parle.sh "Jukebox interplanétaire accessible"
+fi
+

+ 16 - 0
search

@@ -0,0 +1,16 @@
+#!/bin/bash
+clear
+echo "------------------------------------------------------------------------------"
+if [ "$1" == "" ]; then
+	echo "  Nothing to search for!"  
+else
+	echo "  Searching for "$1" recursively. Please Wait..."
+	echo "------------------------------------------------------------------------------"
+	grep -h -r --exclude=B00 -H --colour=always "$1" ./
+fi
+echo "------------------------------------------------------------------------------"
+if [ "$2" != "" ]; then
+        echo "  To replace \"$1\" whith \"$2\", please run"
+	echo "  grep -rl '$1' ./  | xargs sed -i 's/$1/$2/g'"
+fi
+

BIN
shell/G1sms.png


BIN
shell/OLove.jpg


BIN
shell/Oeuro.jpg


BIN
shell/Portefeuille.png


BIN
shell/TAG_fond.jpg


BIN
shell/TAG_fond_G1Tx.jpg


+ 1 - 0
shell/bad.nodes.txt

@@ -0,0 +1 @@
+duniter.moul.re:443

+ 151 - 0
shell/checknodes.sh

@@ -0,0 +1,151 @@
+#!/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)
+    echo $SERVER:443 >> ./shell/bad.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.moul.re/$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

+ 71 - 0
shell/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 MASTERKEYFILE encryption to IPFS
+################################################################################
+source ./shell/init.sh
+source ./shell/functions.sh
+now=$(date +%Y-%m-%d)
+
+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.... INITIALIZING G1 Object ipfs chain files:"
+echo "GIT" > "./$dir/_type"
+hop=$(cat "./$dir/_chain")
+LASTDU=$(curl -s ${DUNITER}/blockchain/with/ud | jq '.result.blocks[]' | tail -n 1); curl -s ${DUNITER}/blockchain/block/${LASTDU} | jq '.dividend' > "./$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 ALL ARCHIVE FILES
+tar -cvzf G1sms+_backup_$now.tar.gz --exclude 'init.sh' --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/
+mv G1sms+_backup_$now.tar.gz /tmp/CODE/G1sms+.latest.tgz
+cp ./$dir/install*.sh /tmp/CODE/
+
+# 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"
+
+

+ 40 - 0
shell/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 MASTERKEYFILE 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
+
+

+ 49 - 0
shell/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

+ 109 - 0
shell/cron_MINUTE.sh

@@ -0,0 +1,109 @@
+#!/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
+################################################################################
+YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1)
+IPFSNODEID=$(su $YOU -c "ipfs id -f='<id>\n'")
+CHEMIN="/home/$YOU/G1sms+"
+cd $CHEMIN
+source ./shell/init.sh
+source ./shell/functions.sh
+
+timebar=$(date +%H%M)
+
+if [[ "$USER" != "root" ]]; then echo "Hey, $USER you must at least be admin of your system. sudo -s ?"; exit; fi
+if [[ "$YOU" == "" || "$YOU" == "root" ]]; then echo "BAD IPFS. Aucune installation IPFS satisfaisante ici... Ciao $YOU !"; exit; fi
+
+
+##################################################################
+# Refresh All peers SWARM Wallets. 
+##################################################################
+ipfs_swarm_wallets_refresh "SIMPLE"
+
+################################################################################
+# PRINT G1Tag
+# 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 "$MASTERKEYFILE" -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
+
+
+
+##################################################################
+if [[ "$timebar" == "0300" ]]; then
+##################################################################
+##################################################################
+# Refresh G1Tag created by this NODE 
+# PROTECT from null HASH 
+for tag in ./wallets/.$IPFSNODEID/TAG/*; do
+    tagj=$(echo $tag | cut -d '/' -f 5)
+    log "__SUB:cron_MINUTE.sh: WORKING ON ${tagj}"
+    RR=$(su $YOU -c "ipfs cat /ipns/${tagj}/TAG_id | sed s/\ //g");
+    if [[ ! $RR && "${tagj}" != "" ]]; then echo "G1 Tag Destroyed"; echo "TODO: rm -Rf ./wallets/.$IPFSNODEID/TAG/${tagj} ???"; continue; fi
+
+    # GET PUBLISHKEY for that G1TAG
+    su $YOU -c "ipfs get -o /home/$YOU/.ipfs/keystore/${RR}.crypt /ipns/$tagj/TAG_publishkey.MASTER.crypt"
+    if [[ ! -f /home/$YOU/.ipfs/keystore/${RR}.crypt ]]; then log "__SUB:cron_MINUTE.sh: error getting publishkey"; continue; fi
+    ./shell/natools.py decrypt -k "$MASTERKEYFILE" -i /home/$YOU/.ipfs/keystore/${RR}.crypt -o /home/$YOU/.ipfs/keystore/$RR
+
+    log "__SUB:cron_MINUTE.sh: G1Tag PUBLISHKEY decrypted and loaded in /home/$YOU/.ipfs/keystore/${RR}"
+
+    # RE-SYNC LOCAL & SWARM G1TAG (TODO Check G1Tag chain validity)
+    rm -f ./TAG/${RR}/*
+    su $YOU -c "ipfs get --output=./TAG/${RR} /ipns/${tagj}"
+ 
+    # PUBLISH VERIFIED G1Tag VERSION
+    I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1")
+    # RECORD TAG_chain And HASH again
+    echo "$I" > "./TAG/${JDESTRR}/TAG_chain"
+    I=$(su $YOU -c "ipfs add -qr ./TAG/${RR} | tail -n 1")
+    # IPNS $JDESTRR PUBLISH
+    J=$(su $YOU -c "ipfs name publish -k ${RR} --quieter /ipfs/${I}")
+
+done
+##################################################################
+fi
+##################################################################
+

+ 94 - 0
shell/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
+############################################

File diff suppressed because it is too large
+ 7776 - 0
shell/diceware-wordlist.txt


+ 17 - 0
shell/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

+ 615 - 0
shell/functions.sh

@@ -0,0 +1,615 @@
+#!/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
+###################################################################################################################################
+
+###################################################################################################################################
+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 -l 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
+#for id in $(su $YOU -c "ipfs swarm peers" | awk -F '/' '{print $7}');
+for id in ./wallets_swarm/.Qm*/;
+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
+    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" != "" ]]; 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" # TEST!!! crypt with $PHONE wallet keypair
+	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")
+######################################################################
+	# (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 $PUBKEY -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 "$MASTERKEYFILE $PUBKEY THIRD_PARTY_MANAGER:$MASTERPUB"
+		TX_IN=$(./silkaj/silkaj transaction --auth-file -file="$MASTERKEYFILE" --amount=3.15 --output=$PUBKEY --comment="[G1sms+] $UIDNA$TAIL 3RD:$MASTERPUB " -y)
+		log "__SUB:sms_INIT_ACCOUNT: G1 Wallet TX IN: $TX_IN"
+		sleep 2
+		TX_OUT=$(./silkaj/silkaj transaction --auth-scrypt -salt="$PHONE" -password="$PIN" --amount=0.1 --output=$MASTERPUB --comment="[G1sms+] $UIDNA$TAIL 3RD:$MASTERPUB:ACK" -y)
+		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)
+        echo "" > "$PINFILE"
+        
+        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";
+    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)
+        echo "" > "$PINFILE";
+    fi
+
+    # CYPHER EMAIL FILE
+    if [[ ! -f "$GPGMAILFILE" ]]; then
+        # ------------8<------------------
+        # NO .gpg file, CREATING it (OLD G1sms accounts)
+	    if [ -f "$MAILFILE" ]; then 
+            MAIL=$(cat "$MAILFILE");
+            echo "${GPGPASS}" | gpg -q --output "$GPGMAILFILE" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "$MAILFILE";
+        else
+            MAIL="";
+        fi
+        # ------------>8------------------
+    else
+        # Already existing gpg DECODING IT
+        echo "${GPGPASS}" | gpg -d -q --output "$MAILFILE" --yes --pinentry-mode loopback --passphrase-fd 0 "$GPGMAILFILE"
+        MAIL=$(cat "$MAILFILE");
+        echo "" > "$MAILFILE";
+    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 15 sec....."
+AMOUNTG1=$(./shell/timeout.sh -t 15 ./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 20 ./silkaj/silkaj amount "$PUBKEY")
+if [[ ! $AMOUNTG1 ]]; then AMOUNTG1=$(bc -l <<< "scale=2; $(cat ./wallets_swarm/$PHONE/$PHONE.g1cents) / 100"); fi
+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 NODEG1PUB crypt
+            echo "$zenvalue" > "/tmp/move_g1cents.$winnerphone"
+            # GET NODE G1sms Wallet PUBKEY
+            NODEG1PUB=$(cat ./wallets_swarm/.$NODEID/$NODEID.pub)
+            ./shell/natools.py encrypt -p $NODEG1PUB -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)
+}

BIN
shell/g1.png


+ 42 - 0
shell/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)
+

+ 54 - 0
shell/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)")

BIN
shell/g1tag.png


+ 5 - 0
shell/good.nodes.txt

@@ -0,0 +1,5 @@
+duniter.moul.re:443
+g1.duniter.fr:443
+g1.duniter.org:443
+g1.monnaielibreoccitanie.org:443
+g1.presles.fr:443

+ 79 - 0
shell/init.sh.template

@@ -0,0 +1,79 @@
+#!/bin/bash
+##################################################################
+# Author: Fred (support@qo-op.com)
+# Version: 0.1
+# License: GPL (http://www.google.com/search?q=GPL)
+##################################################################
+# Adapter les valeurs au contexte spatio-temporel du NODE G1SMS
+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 aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1)
+    export CHEMIN="/home/$YOU/G1sms+"
+    cd $CHEMIN
+    ##################################################################
+    # Activate logging to /tmp/g1sms.log (YES/NO)
+    export DOLOG="YES"
+    export CPERROR="NOYES"
+    ##################################################################
+    # Country Node Phone international prefix (TODO Worldwide)
+    export COUNTRY="+33"
+    ##################################################################
+    # DU has a G1 value changed every 6 month!
+    # ./_DU Updated by cron_CODE.backup.sh
+    if [[ -f "./_DU" ]]; then export DUFACTOR=$(bc <<< "scale=2; $(cat "./_DU") / 100"); else log "__SUB:init.sh: FAILING TO FIND ./_DU EXIT!!!"; exit; fi
+    ##################################################################
+    # Choose Default Unit: G1, DU, LOVE (DU cents), ZEN (G1 cents)
+    export COIN="G1"
+    ##################################################################
+    # Limit and commission values 
+    export LIMIT=2 # Solde minimum = 2 G1
+    # FIXED COMMISSION SYSTEM
+    export COMMISSION=1 # transaction commission amount (G1) 
+    export BILLCOM=20
+    ##################################################################
+    # COMMISSION PARTS FROM TX FOR NODE & G1SMS NETWORK
+    # PART COMMISSION SYSTEM
+    export SWARMCOMM=10
+    # TODO: NODE G1sms Wallet can receive rewards from SWARM or WALLETS/FILES
+    export NODECOMM=10
+    ##################################################################
+    # SMS SIM Card Phone Number 
+    export MASTERPHONE="+33660780131"
+    export ADRESSE="au G1FabLab de 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 pip3 install silkaj"
+    # export SILKAJ="/usr/local/bin/silkaj"
+    source $CHEMIN/shell/init_keys.sh
+

+ 129 - 0
shell/init_keys.sh

@@ -0,0 +1,129 @@
+#!/bin/bash
+##################################################################
+# Author: Fred (support@qo-op.com)
+# Version: 0.1
+# License: GPL (http://www.google.com/search?q=GPL)
+##################################################################
+# CHECK & WARN | CREATE Keys (gpg encrypt, G1wallet, IPNS publish)
+##################################################################
+YOU=$(ps aux --sort=+utime | grep ipfs | tail -n 1 | cut -d " " -f 1)
+# TODO Make it directory independant. (for now it is tested for pi running ipfs and code in $HOME/G1sms+
+CHEMIN="/home/$YOU/G1sms+"
+
+##################################################################
+# G1sms+ Node KEYS (G1wallet, gpg, IPNS)
+##################################################################
+export GPGPASS=$(cat "/home/$YOU/.ipfs/config" | jq '.Identity.PrivKey' | sed s/\"//g)
+
+##################################################################
+# G1sms+ Swarm KEYS
+##################################################################
+# G1sms Service - G1Wallet
+if [[ -f "${CHEMIN}/g1sms.pub.key" && -f "${CHEMIN}/g1sms.priv.key" ]]; then
+    chown root:root ${CHEMIN}/g1sms.priv.key
+    chmod 600 ${CHEMIN}/g1sms.priv.key
+	export MASTERPUB=$(cat "${CHEMIN}/g1sms.pub.key")
+    export MASTERKEYFILE="${CHEMIN}/g1sms.priv.key"
+else
+    echo "ATTENTION!! Vous devez posséder la clef du G1 Wallet utilisé par le SWARM G1sms!!"
+    ./shell/parle.sh "Les clefs du portefeuille essaim G1 SMS sont absente. Au revoir."
+    echo "Fichiers manquants:"
+    echo "${CHEMIN}/g1sms.pub.key"
+    echo "${CHEMIN}/g1sms.priv.key"
+    echo "Contactez nous sur https://g1sms.fr"
+    gammu-smsd-inject -l TEXT "$ADMINPHONE" -text "Clef de G1Wallet du SWARM g1sms.priv.key manquante! contactez-nous pour la recevoir https://g1sms.fr" 1>&2
+    exit
+fi
+
+##################################################################
+# NODE KEYS (SCRIPT CALLED BY ROOT !!! gammu is root)
+##################################################################
+export IPFSNODEID=$(su $YOU -c "ipfs id -f='<id>\n'")
+export NANODATE=$(date -u +%s%N) #1569692075385428020
+
+# CHECK LAST TIME NODE HAD ACTION
+if [[ -f ./wallets/.$IPFSNODEID/$IPFSNODEID.nanodate ]]; then
+    last=$(cat ./wallets/.$IPFSNODEID/$IPFSNODEID.nanodate)
+    timediff=$( echo "${NANODATE} - ${last}" | bc -l )
+    # Get median nanodate before
+    # NODE TIME SYNC 120 milliards de nanosecondes
+    if [[ $timediff -gt 120000000000 ]]; then
+        log "__SUB:ntpdate pool.ntp.org: $timediff $(ntpdate pool.ntp.org)"
+        export NANODATE=$(date -u +%s%N)
+    fi
+fi
+
+echo $NANODATE > ./wallets/.$IPFSNODEID/$IPFSNODEID.nanodate
+
+#################################################################
+# CREATE NODE .$IPFSNODEID SPACE (G1Wallet + TASK + NODE DETAILS)
+#################################################################
+# Create G1sms Wallet with that NODE G1 wallet as member reference
+if [[ ! -f "./wallets/.$IPFSNODEID/$IPFSNODEID.pub" ]]; then
+    mkdir -p ./wallets/.$IPFSNODEID/TASK
+    NODEG1WALLET=$(./silkaj/silkaj generate_auth_file --auth-scrypt -salt="$IPFSNODEID" -password="$GPGPASS")
+    echo "${GPGPASS}" | gpg -q --output "./wallets/.$IPFSNODEID/$IPFSNODEID.authfile.GPGPASS.gpg" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "./authfile"
+    ./shell/natools.py encrypt -p $NODEG1WALLET -i "./authfile" -o "./wallets/.$IPFSNODEID/$IPFSNODEID.authfile.crypt"
+    rm -f ./authfile
+
+    echo $NODEG1WALLET > "./wallets/.$IPFSNODEID/$IPFSNODEID.pub"
+    echo $IPFSNODEID > "./wallets/.$IPFSNODEID/$IPFSNODEID.ipfsid"
+    log "__SUB:initkeys.sh: [ADMIN] G1sms+ CREATE G1WALLET FOR: $IPFSNODEID: pub = $NODEG1WALLET "
+
+    # BACKUP $IPFSNODEID config
+    ./shell/natools.py encrypt -p $MASTERPUB -i "/home/$YOU/.ipfs/config" -o "./wallets/.$IPFSNODEID/$IPFSNODEID.ipfsconfig.crypt"
+    log "__SUB:initkeys.sh: [ADMIN] BACKUP $IPFSNODEID NODE CONFIG to ./wallets/.$IPFSNODEID/$IPFSNODEID.ipfsconfig.crypt "
+
+    #######################
+    # GIVE NAME TO WALLET
+    #######################
+    # 4 derniers chiffres du numéro de téléphone
+    TAIL=${MASTERPHONE: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" > "./wallets/.$IPFSNODEID/$IPFSNODEID.uidna"
+
+    # CREATE NODE WALLET LIKE A PHONE (Stored in wallets/.$IPFSNODEID)
+    echo "${GPGPASS}" > "./wallets/.$IPFSNODEID/$IPFSNODEID.pin"
+    echo "${GPGPASS}" | gpg -q --output "./wallets/.$IPFSNODEID/$IPFSNODEID.pin.gpg" --yes --pinentry-mode loopback --symmetric --passphrase-fd 0 "./wallets/.$IPFSNODEID/$IPFSNODEID.pin"
+    echo "" > "./wallets/.$IPFSNODEID/$IPFSNODEID.pin"
+    echo "$UIDNA$TAIL" > "./wallets/.$IPFSNODEID/$IPFSNODEID.uidna"
+    echo "314" > "./wallets/.$IPFSNODEID/$IPFSNODEID.g1cents"
+    echo $NODEG1WALLET > "./wallets/.$IPFSNODEID/$IPFSNODEID.pub"
+
+    # SILKAJ INIT G1 NODE WALLET
+    TX_IN=$(./silkaj/silkaj transaction --auth-file -file="$MASTERKEYFILE" --amount=3.15 --output=$NODEG1WALLET --comment="[G1sms+] G1NODE ($ADMINPSEUDO) $UIDNA$TAIL $IPFSNODEID" -y)
+    TX_OUT=$(./silkaj/silkaj transaction --auth-scrypt -salt="$IPFSNODEID" -password="$GPGPASS" --amount=0.1 --output=$MASTERPUB --comment="[G1sms+] G1NODE $IPFSNODEID:ACK" -y)
+    log "__SUB:initkeys.sh: [ADMIN] G1sms+ $ADMINPSEUDO-$UIDNA$TAIL OUVERT POUR NODE: ls ./wallet/.$IPFSNODEID"
+    gammu-smsd-inject -l TEXT "$ADMINPHONE" -text "[ADMIN] G1sms+ $ADMINPSEUDO-$UIDNA$TAIL OUVERT POUR NODE: ls ./wallets/.$IPFSNODEID" 1>&2
+    gammu-smsd-inject -l TEXT "$ADMINPHONE" -text "$NODEG1WALLET" 1>&2
+fi
+
+################################################################
+#INFORM ABOUT NODE CAPACITIES
+export NODEG1PUB=$(cat "./wallets/.$IPFSNODEID/$IPFSNODEID.pub")
+
+## IS IT A SMS NODE (gammu-smsd is installed)??
+if [[ $G1SMS ]]; then
+    echo $MASTERPHONE > "./wallets/.$IPFSNODEID/$IPFSNODEID.sms"
+else
+    if [ -f "./wallets/.$IPFSNODEID/$IPFSNODEID.sms" ]; then rm -f "./wallets/.$IPFSNODEID/$IPFSNODEID.sms"; fi
+fi
+
+## IS THERE USB PRINTER CONNECTED?
+if [[ -e "/dev/usb/lp0" ]]; then
+    log "G1CORE: IMPRESSION G1Tag ACTIF .............."
+    echo $ADRESSE > "./wallets/.$IPFSNODEID/$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/$IPFSNODEID.scan"
+else
+    if [ -f "./wallets/.$IPFSNODEID/$IPFSNODEID.scan" ]; then rm -f "./wallets/.$IPFSNODEID/$IPFSNODEID.scan"; fi
+fi
+

+ 85 - 0
shell/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 <command> [options]
+
+Commands:
+  encrypt  Encrypt data
+  decrypt  Decrypt data
+  sign     Sign data
+  verify   Verify data
+
+Options:
+  -i <path>  Input file path (default: -)
+  -k <path>  Privkey file path (default: authfile.key)
+  -p <str>   Pubkey (base58)
+  -o <path>  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)

+ 9 - 0
shell/nodes.txt

@@ -0,0 +1,9 @@
+g1.le-sou.org:443
+follow.the.white-rabbit.net:443
+duniter.moul.re:443
+g1.monnaielibreoccitanie.org:443
+g1.duniter.inso.ovh:443
+g1.duniter.fr:443
+g1.presles.fr:443
+g1.duniter.org:443
+monit.g1.nordstrom.duniter.org:443

+ 12 - 0
shell/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

+ 32 - 0
shell/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())

+ 37 - 0
shell/sms_ABO.sh

@@ -0,0 +1,37 @@
+#!/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=SERVICE, $2=YESNO)"
+SERVICE=$1
+YESNO=$2
+PARAMS=$3
+
+case "$SERVICE" in
+	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

+ 89 - 0
shell/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 "__S