- Implement two different CLIs: an interactive menu and a utility CLI - CLIs support key generation, mining, transactions, and card viewing Co-authored-by: deusbalatro <github.sequence146@passinbox.com> Co-committed-by: deusbalatro <github.sequence146@passinbox.com>
156 lines
4.3 KiB
Python
Executable File
156 lines
4.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import glob
|
|
import os
|
|
from cli import opt_generate_keypair
|
|
from cli import opt_save_private_key
|
|
from cli import opt_load_private_key
|
|
from cli import opt_save_public_key
|
|
from cli import opt_mine_block
|
|
from cli import opt_generate_transaction
|
|
from cli import opt_view_deck
|
|
from cli import msg_array
|
|
from cli import get_private_key_from_file
|
|
from cli import fetch_cards_json
|
|
|
|
DEFAULT_FILENAME: str = "privatekey";
|
|
|
|
def resolve_path(path: str | None) -> str | None:
|
|
if not path or path.strip() == "":
|
|
return None;
|
|
|
|
path = path.strip();
|
|
|
|
if not path.endswith(".pem"):
|
|
path += ".pem";
|
|
|
|
if os.path.exists(path) and os.path.isfile(path):
|
|
return path;
|
|
|
|
return None;
|
|
|
|
|
|
def resolve_path_for_key_creation(filename:str | None) -> str:
|
|
default_name = "privatekey.pem";
|
|
|
|
if not filename or filename.strip() == "":
|
|
return default_name;
|
|
|
|
filename = filename.strip();
|
|
|
|
if os.path.isdir(filename):
|
|
return os.path.join(filename, default_name);
|
|
|
|
if not filename.endswith(".pem"):
|
|
filename += ".pem";
|
|
|
|
dir_path = os.path.dirname(filename);
|
|
if dir_path and not os.path.exists(dir_path):
|
|
os.makedirs(dir_path);
|
|
|
|
return filename;
|
|
|
|
def get_first_pem_file():
|
|
pem_files = glob.glob("*.pem");
|
|
|
|
if pem_files:
|
|
first_pem = min(pem_files, key=os.path.getmtime);
|
|
return first_pem;
|
|
else:
|
|
return None;
|
|
|
|
def handle_createkey(args):
|
|
rsa_key = opt_generate_keypair();
|
|
filepath = resolve_path_for_key_creation(args.output);
|
|
opt_save_private_key(rsa_key, filepath);
|
|
print(msg_array[0]);
|
|
public_path = f"pub_{filepath}"
|
|
opt_save_public_key(rsa_key, public_path);
|
|
|
|
def handle_mine(args):
|
|
file = resolve_path(args.use);
|
|
if not file:
|
|
file = get_first_pem_file();
|
|
if not file:
|
|
msg_array[0] = "No valid private key found";
|
|
return;
|
|
|
|
opt_mine_block(file);
|
|
|
|
|
|
def handle_tx(args):
|
|
|
|
file = resolve_path(args.use);
|
|
if not file:
|
|
file = get_first_pem_file();
|
|
if not file:
|
|
msg_array[0] = "No valid private key found";
|
|
return;
|
|
|
|
recv = resolve_path(args.receiver);
|
|
if args.receiver and not recv:
|
|
msg_array[0] = "No valid public key found (receiver)";
|
|
return;
|
|
|
|
opt_generate_transaction(file, recv);
|
|
|
|
|
|
def handle_deck(args):
|
|
file = resolve_path(args.use);
|
|
if not file:
|
|
file = get_first_pem_file();
|
|
if not file:
|
|
msg_array[0] = "No valid private key found";
|
|
return;
|
|
|
|
rsa = get_private_key_from_file(file);
|
|
if rsa is None:
|
|
return;
|
|
|
|
cards = fetch_cards_json(rsa);
|
|
|
|
if len(cards) < 1:
|
|
msg_array[0] = "You have no cards to view";
|
|
return;
|
|
|
|
for i, card in enumerate(cards):
|
|
print(f"{i+1}. Card ID: {card['cardId']}, Page ID: {card['pageId']}");
|
|
|
|
|
|
def build_parser():
|
|
parser = argparse.ArgumentParser(description="Wikideck CLI");
|
|
subparsers = parser.add_subparsers(dest="command", required=True);
|
|
|
|
#createkey
|
|
p_create = subparsers.add_parser("createkey",aliases=["ck"], help="Create an RSA keypair and save it to the current directory");
|
|
p_create.add_argument("-O", "--output", help="Optional custom filename (.pem)");
|
|
p_create.set_defaults(func=handle_createkey);
|
|
|
|
#mine
|
|
p_mine = subparsers.add_parser("mine", help="Mine a block, using the first ./*.pem by default.");
|
|
p_mine.add_argument("-u", "--use", help="Use specified keypair (path to .pem file)");
|
|
p_mine.set_defaults(func=handle_mine);
|
|
|
|
#transaction
|
|
p_transaction = subparsers.add_parser("transaction", aliases=["tx"], help="Generate a transaction, using the first ./*.pem by default.");
|
|
p_transaction.add_argument("-u", "--use", help="Use specified keypair (path to .pem file)");
|
|
p_transaction.add_argument("-to", "--receiver", help="Send to specified public key (path to .pem file)");
|
|
p_transaction.set_defaults(func=handle_tx);
|
|
|
|
#deck
|
|
p_deck = subparsers.add_parser("deck", help="Show all cards tied to the private key, using the first ./*.pem by default.");
|
|
p_deck.add_argument("-u", "--use", help="Use specified keypair (path to .pem file)");
|
|
p_deck.set_defaults(func=handle_deck);
|
|
|
|
return parser;
|
|
|
|
def main():
|
|
parser = build_parser();
|
|
args = parser.parse_args();
|
|
args.func(args);
|
|
print(msg_array[0]);
|
|
|
|
if __name__ == "__main__":
|
|
main();
|