2020-12-12 01:26:39 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
2020-12-12 20:59:40 +01:00
|
|
|
import argparse, sys, os, getpass, string, random
|
2020-12-12 01:26:39 +01:00
|
|
|
from os.path import join, dirname
|
|
|
|
from shutil import copyfile
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
from duniterpy.key import SigningKey
|
|
|
|
|
2020-12-12 20:59:40 +01:00
|
|
|
__version__ = "0.0.2"
|
|
|
|
|
|
|
|
MY_PATH = os.path.realpath(os.path.dirname(sys.argv[0])) + '/'
|
2020-12-12 01:26:39 +01:00
|
|
|
|
|
|
|
# Get variables environment
|
2020-12-12 20:59:40 +01:00
|
|
|
if not os.path.isfile(MY_PATH + '.env'):
|
|
|
|
copyfile(MY_PATH + ".env.template",MY_PATH + ".env")
|
|
|
|
dotenv_path = join(dirname(__file__),MY_PATH + '.env')
|
2020-12-12 01:26:39 +01:00
|
|
|
load_dotenv(dotenv_path)
|
|
|
|
|
|
|
|
# Parse arguments
|
|
|
|
parser = argparse.ArgumentParser(description="Client CLI pour Cesium+ et Ḡchange")
|
|
|
|
parser.add_argument('-v', '--version', action='store_true', help="Affiche la version actuelle du programme")
|
|
|
|
parser.add_argument('-k', '--key', help="Chemin vers mon trousseau de clé (PubSec)")
|
2020-12-12 20:59:40 +01:00
|
|
|
parser.add_argument('-n', '--node', help="Adresse du noeud Cesium+, Gchange ou Duniter à utiliser")
|
2020-12-12 01:26:39 +01:00
|
|
|
|
|
|
|
subparsers = parser.add_subparsers(title="Commandes de jaklis", dest="cmd")
|
|
|
|
read_cmd = subparsers.add_parser('read', help="Lecture des messages")
|
|
|
|
send_cmd = subparsers.add_parser('send', help="Envoi d'un message")
|
|
|
|
delete_cmd = subparsers.add_parser('delete', help="Supression d'un message")
|
|
|
|
getProfile_cmd = subparsers.add_parser('get', help="Voir un profile Cesium+")
|
|
|
|
setProfile_cmd = subparsers.add_parser('set', help="Configurer son profile Cesium+")
|
|
|
|
eraseProfile_cmd = subparsers.add_parser('erase', help="Effacer son profile Cesium+")
|
2021-02-24 16:13:19 +01:00
|
|
|
stars_cmd = subparsers.add_parser('stars', help="Voir les étoiles d'un profile / Noter un profile (option -s NOTE)")
|
|
|
|
unstars_cmd = subparsers.add_parser('unstars', help="Supprimer un star")
|
|
|
|
getoffer_cmd = subparsers.add_parser('getoffer', help="Obtenir les informations d'une annonce gchange")
|
|
|
|
setoffer_cmd = subparsers.add_parser('setoffer', help="Créer une annonce gchange")
|
|
|
|
deleteoffer_cmd = subparsers.add_parser('deleteoffer', help="Supprimer une annonce gchange")
|
2020-12-12 20:59:40 +01:00
|
|
|
pay_cmd = subparsers.add_parser('pay', help="Payer en Ḡ1")
|
|
|
|
history_cmd = subparsers.add_parser('history', help="Voir l'historique des transactions d'un compte Ḡ1")
|
|
|
|
balance_cmd = subparsers.add_parser('balance', help="Voir le solde d'un compte Ḡ1")
|
2020-12-12 01:26:39 +01:00
|
|
|
|
|
|
|
# Messages management
|
|
|
|
read_cmd.add_argument('-n', '--number',type=int, default=3, help="Affiche les NUMBER derniers messages")
|
|
|
|
read_cmd.add_argument('-j', '--json', action='store_true', help="Sort au format JSON")
|
|
|
|
read_cmd.add_argument('-o', '--outbox', action='store_true', help="Lit les messages envoyés")
|
|
|
|
|
|
|
|
send_cmd.add_argument('-d', '--destinataire', required=True, help="Destinataire du message")
|
|
|
|
send_cmd.add_argument('-t', '--titre', help="Titre du message à envoyer")
|
|
|
|
send_cmd.add_argument('-m', '--message', help="Message à envoyer")
|
|
|
|
send_cmd.add_argument('-f', '--fichier', help="Envoyer le message contenu dans le fichier 'FICHIER'")
|
|
|
|
send_cmd.add_argument('-o', '--outbox', action='store_true', help="Envoi le message sur la boite d'envoi")
|
|
|
|
|
|
|
|
delete_cmd.add_argument('-i', '--id', action='append', nargs='+', required=True, help="ID(s) du/des message(s) à supprimer")
|
|
|
|
delete_cmd.add_argument('-o', '--outbox', action='store_true', help="Suppression d'un message envoyé")
|
|
|
|
|
|
|
|
# Profiles management
|
|
|
|
setProfile_cmd.add_argument('-n', '--name', help="Nom du profile")
|
|
|
|
setProfile_cmd.add_argument('-d', '--description', help="Description du profile")
|
|
|
|
setProfile_cmd.add_argument('-v', '--ville', help="Ville du profile")
|
|
|
|
setProfile_cmd.add_argument('-a', '--adresse', help="Adresse du profile")
|
|
|
|
setProfile_cmd.add_argument('-pos', '--position', nargs=2, help="Points géographiques (lat + lon)")
|
|
|
|
setProfile_cmd.add_argument('-s', '--site', help="Site web du profile")
|
|
|
|
setProfile_cmd.add_argument('-A', '--avatar', help="Chemin vers mon avatar en PNG")
|
|
|
|
|
|
|
|
getProfile_cmd.add_argument('-p', '--profile', help="Nom du profile")
|
|
|
|
getProfile_cmd.add_argument('-a', '--avatar', action='store_true', help="Récupérer également l'avatar au format raw base64")
|
|
|
|
|
|
|
|
# Likes management
|
2021-02-24 16:13:19 +01:00
|
|
|
stars_cmd.add_argument('-p', '--profile', help="Profile cible")
|
|
|
|
stars_cmd.add_argument('-n', '--number', type=int, help="Nombre d'étoile")
|
|
|
|
unstars_cmd.add_argument('-p', '--profile', help="Profile à dénoter")
|
|
|
|
|
|
|
|
# Offers management
|
|
|
|
getoffer_cmd.add_argument('-i', '--id', help="Annonce cible à récupérer")
|
|
|
|
setoffer_cmd.add_argument('-t', '--title', help="Titre de l'annonce à créer")
|
|
|
|
setoffer_cmd.add_argument('-d', '--description', help="Description de l'annonce à créer")
|
|
|
|
setoffer_cmd.add_argument('-c', '--category', help="Categorie de l'annonce à créer")
|
|
|
|
setoffer_cmd.add_argument('-l', '--localisation', nargs=2, help="Localisation de l'annonce à créer (lat + lon)")
|
|
|
|
setoffer_cmd.add_argument('-p', '--picture', help="Image de l'annonce à créer")
|
|
|
|
setoffer_cmd.add_argument('-ci', '--city', help="Ville de l'annonce à créer")
|
|
|
|
setoffer_cmd.add_argument('-pr', '--price', help="Prix de l'annonce à créer")
|
|
|
|
deleteoffer_cmd.add_argument('-i', '--id', help="Annonce cible à supprimer")
|
2020-12-12 01:26:39 +01:00
|
|
|
|
2020-12-12 20:59:40 +01:00
|
|
|
# GVA usage
|
|
|
|
pay_cmd.add_argument('-p', '--pubkey', help="Destinataire du paiement")
|
|
|
|
pay_cmd.add_argument('-a', '--amount', type=float, help="Montant de la transaction")
|
|
|
|
pay_cmd.add_argument('-c', '--comment', default="", help="Commentaire de la transaction")
|
|
|
|
pay_cmd.add_argument('-m', '--mempool', action='store_true', help="Utilise les sources en Mempool")
|
|
|
|
pay_cmd.add_argument('-v', '--verbose', action='store_true', help="Affiche le résultat JSON de la transaction")
|
|
|
|
|
|
|
|
history_cmd.add_argument('-p', '--pubkey', help="Clé publique du compte visé")
|
2021-02-24 16:13:19 +01:00
|
|
|
history_cmd.add_argument('-n', '--number',type=int, default=10, help="Affiche les NUMBER dernières transactions")
|
2020-12-12 20:59:40 +01:00
|
|
|
history_cmd.add_argument('-j', '--json', action='store_true', help="Affiche le résultat en format JSON")
|
|
|
|
history_cmd.add_argument('--nocolors', action='store_true', help="Affiche le résultat en noir et blanc")
|
|
|
|
|
|
|
|
balance_cmd.add_argument('-p', '--pubkey', help="Clé publique du compte visé")
|
|
|
|
balance_cmd.add_argument('-m', '--mempool', action='store_true', help="Utilise les sources en Mempool")
|
|
|
|
|
|
|
|
|
2020-12-12 01:26:39 +01:00
|
|
|
args = parser.parse_args()
|
|
|
|
cmd = args.cmd
|
|
|
|
|
2020-12-12 20:59:40 +01:00
|
|
|
if args.version:
|
|
|
|
print(__version__)
|
|
|
|
sys.exit(0)
|
|
|
|
|
2020-12-12 01:26:39 +01:00
|
|
|
if not cmd:
|
|
|
|
parser.print_help()
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
def createTmpDunikey():
|
|
|
|
# Generate pseudo-random nonce
|
|
|
|
nonce=[]
|
|
|
|
for _ in range(32):
|
|
|
|
nonce.append(random.choice(string.ascii_letters + string.digits))
|
|
|
|
nonce = ''.join(nonce)
|
|
|
|
keyPath = "/tmp/secret.dunikey-" + nonce
|
|
|
|
|
|
|
|
key = SigningKey.from_credentials(getpass.getpass("Identifiant: "), getpass.getpass("Mot de passe: "), None)
|
|
|
|
key.save_pubsec_file(keyPath)
|
|
|
|
|
|
|
|
return keyPath
|
|
|
|
|
2020-12-12 20:59:40 +01:00
|
|
|
# Check if we need dunikey
|
|
|
|
try:
|
|
|
|
pubkey = args.pubkey
|
|
|
|
except:
|
|
|
|
pubkey = False
|
|
|
|
try:
|
|
|
|
profile = args.profile
|
|
|
|
except:
|
|
|
|
profile = False
|
|
|
|
|
|
|
|
if cmd in ('history','balance','get') and (pubkey or profile):
|
|
|
|
noNeedDunikey = True
|
2020-12-12 01:26:39 +01:00
|
|
|
keyPath = False
|
2020-12-12 20:59:40 +01:00
|
|
|
try:
|
|
|
|
dunikey = args.pubkey
|
|
|
|
except:
|
|
|
|
dunikey = args.profile
|
2020-12-12 01:26:39 +01:00
|
|
|
else:
|
2020-12-12 20:59:40 +01:00
|
|
|
noNeedDunikey = False
|
|
|
|
if args.key:
|
|
|
|
dunikey = args.key
|
2020-12-12 01:26:39 +01:00
|
|
|
keyPath = False
|
|
|
|
else:
|
2020-12-12 20:59:40 +01:00
|
|
|
dunikey = os.getenv('DUNIKEY')
|
|
|
|
if not dunikey:
|
|
|
|
keyPath = createTmpDunikey()
|
|
|
|
dunikey = keyPath
|
|
|
|
else:
|
|
|
|
keyPath = False
|
|
|
|
if not os.path.isfile(dunikey):
|
|
|
|
HOME = os.getenv("HOME")
|
|
|
|
dunikey = HOME + dunikey
|
|
|
|
if not os.path.isfile(dunikey):
|
|
|
|
sys.stderr.write('Le fichier de trousseau {0} est introuvable.\n'.format(dunikey))
|
|
|
|
sys.exit(1)
|
2020-12-12 01:26:39 +01:00
|
|
|
|
|
|
|
|
2020-12-12 20:59:40 +01:00
|
|
|
# Construct CesiumPlus object
|
2021-02-24 16:13:19 +01:00
|
|
|
if cmd in ("read","send","delete","set","get","erase","stars","unstars","getoffer","setoffer","deleteoffer"):
|
2020-12-12 20:59:40 +01:00
|
|
|
from lib.cesium import CesiumPlus
|
2020-12-12 01:26:39 +01:00
|
|
|
|
2020-12-12 20:59:40 +01:00
|
|
|
if args.node:
|
|
|
|
pod = args.node
|
|
|
|
else:
|
|
|
|
pod = os.getenv('POD')
|
|
|
|
if not pod:
|
|
|
|
pod="https://g1.data.le-sou.org"
|
|
|
|
|
|
|
|
cesium = CesiumPlus(dunikey, pod, noNeedDunikey)
|
|
|
|
|
|
|
|
# Messaging
|
|
|
|
if cmd == "read":
|
|
|
|
cesium.read(args.number, args.outbox, args.json)
|
|
|
|
elif cmd == "send":
|
|
|
|
if args.fichier:
|
|
|
|
with open(args.fichier, 'r') as f:
|
|
|
|
msgT = f.read()
|
|
|
|
titre = msgT.splitlines(True)[0].replace('\n', '')
|
|
|
|
msg = ''.join(msgT.splitlines(True)[1:])
|
|
|
|
if args.titre:
|
|
|
|
titre = args.titre
|
|
|
|
msg = msgT
|
|
|
|
elif args.titre and args.message:
|
|
|
|
titre = args.titre
|
|
|
|
msg = args.message
|
|
|
|
else:
|
|
|
|
titre = input("Indiquez le titre du message: ")
|
|
|
|
msg = input("Indiquez le contenu du message: ")
|
|
|
|
|
|
|
|
cesium.send(titre, msg, args.destinataire, args.outbox)
|
|
|
|
|
|
|
|
elif cmd == "delete":
|
|
|
|
cesium.delete(args.id[0], args.outbox)
|
|
|
|
|
|
|
|
# Profiles
|
|
|
|
elif cmd == "set":
|
2020-12-12 01:26:39 +01:00
|
|
|
cesium.set(args.name, args.description, args.ville, args.adresse, args.position, args.site, args.avatar)
|
|
|
|
elif cmd == "get":
|
|
|
|
cesium.get(args.profile, args.avatar)
|
|
|
|
elif cmd == "erase":
|
|
|
|
cesium.erase()
|
|
|
|
|
2021-02-24 16:13:19 +01:00
|
|
|
# Stars
|
|
|
|
elif cmd == "stars":
|
|
|
|
if args.number or args.number == 0:
|
|
|
|
cesium.like(args.number, args.profile)
|
2020-12-12 20:59:40 +01:00
|
|
|
else:
|
|
|
|
cesium.readLikes(args.profile)
|
2021-02-24 16:13:19 +01:00
|
|
|
elif cmd == "unstars":
|
2020-12-12 20:59:40 +01:00
|
|
|
cesium.unLike(args.profile)
|
|
|
|
|
2021-02-24 16:13:19 +01:00
|
|
|
# Offers
|
|
|
|
elif cmd == "getoffer":
|
|
|
|
cesium.getOffer(args.id)
|
|
|
|
elif cmd == "setoffer":
|
|
|
|
cesium.setOffer(args.title, args.description, args.city, args.localisation, args.category, args.price, args.picture)
|
|
|
|
elif cmd == "deleteoffer":
|
|
|
|
cesium.deleteOffer(args.id)
|
|
|
|
|
2020-12-12 20:59:40 +01:00
|
|
|
# Construct GVA object
|
|
|
|
elif cmd in ("pay","history","balance"):
|
|
|
|
from lib.gva import GvaApi
|
|
|
|
|
|
|
|
if args.node:
|
|
|
|
node = args.node
|
|
|
|
else:
|
|
|
|
node = os.getenv('NODE')
|
|
|
|
if not node:
|
|
|
|
node="https://g1.librelois.fr/gva"
|
|
|
|
|
|
|
|
if args.pubkey:
|
|
|
|
destPubkey = args.pubkey
|
2020-12-12 01:26:39 +01:00
|
|
|
else:
|
2020-12-12 20:59:40 +01:00
|
|
|
destPubkey = False
|
|
|
|
|
|
|
|
gva = GvaApi(dunikey, node, destPubkey, noNeedDunikey)
|
|
|
|
|
|
|
|
if cmd == "pay":
|
|
|
|
gva.pay(args.amount, args.comment, args.mempool, args.verbose)
|
|
|
|
if cmd == "history":
|
2021-02-24 16:13:19 +01:00
|
|
|
gva.history(args.json, args.nocolors, args.number)
|
2020-12-12 20:59:40 +01:00
|
|
|
if cmd == "balance":
|
|
|
|
gva.balance(args.mempool)
|
2020-12-12 01:26:39 +01:00
|
|
|
|
|
|
|
|
|
|
|
if keyPath:
|
|
|
|
os.remove(keyPath)
|