wikideck/wikideck_cli.py
deusbalatro 8061fdba9b feat(cli): add interactive and utility command-line interfaces
- 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>
2025-06-13 09:15:24 +00:00

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();