runv-server

server tooling for runv.club
Log | Files | Refs | README

runv-email-alias (4036B)


      1 #!/usr/bin/env python3
      2 """Pedidos de alias de email runv.club para membros (username@runv.club)."""
      3 
      4 from __future__ import annotations
      5 
      6 import argparse
      7 import sys
      8 from pathlib import Path
      9 
     10 sys.tracebacklimit = 0
     11 
     12 
     13 def _bootstrap() -> None:
     14     installed = Path("/usr/local/share/runv/lib")
     15     candidates = [installed]
     16     script = Path(__file__).resolve()
     17     if script.parent.name == "bin":
     18         candidates.insert(0, script.parent.parent / "lib")
     19     for c in candidates:
     20         if (c / "runv_email_aliases.py").is_file() and str(c) not in sys.path:
     21             sys.path.insert(0, str(c))
     22             return
     23 
     24 
     25 _bootstrap()
     26 import runv_email_aliases as ea  # noqa: E402
     27 
     28 
     29 def cmd_request(destination: str) -> int:
     30     username = ea.current_username()
     31     dest = ea.validate_destination_email(destination)
     32     active = ea.get_active_alias(username)
     33     if active is not None:
     34         print(
     35             "Aviso: já tem alias activo; este pedido altera o destino após aprovação admin.\n"
     36         )
     37     payload = ea.create_pending_request(username, dest)
     38     print("Pedido de alias criado.\n")
     39     print("Alias:")
     40     print(f"  {payload['alias']}\n")
     41     print("Destino:")
     42     print(f"  {payload['destination']}\n")
     43     print("Status:")
     44     print("  pending\n")
     45     print("Um admin precisa aprovar antes de ativar.")
     46     return 0
     47 
     48 
     49 def cmd_status() -> int:
     50     username = ea.current_username()
     51     active = ea.get_active_alias(username)
     52     pending = ea.find_pending_for_user(username)
     53 
     54     if active is None and pending is None:
     55         print("Você ainda não tem alias de email.\n")
     56         print("Para solicitar:")
     57         print("  runv-email-alias request seu-email@exemplo.com")
     58         return 0
     59 
     60     if active is None and pending is not None:
     61         print("Alias:")
     62         print(f"  {pending.get('alias', ea.alias_address(username))}\n")
     63         print("Destino solicitado:")
     64         print(f"  {pending.get('destination', '?')}\n")
     65         print("Status:")
     66         print("  pending")
     67         return 0
     68 
     69     if active is not None and pending is None:
     70         print("Alias:")
     71         print(f"  {active.get('alias', ea.alias_address(username))}\n")
     72         print("Destino:")
     73         print(f"  {active.get('destination', '?')}\n")
     74         print("Status:")
     75         print("  active")
     76         return 0
     77 
     78     print("Alias ativo:")
     79     print(f"  {active.get('alias')} -> {active.get('destination')}\n")
     80     print("Alteração pendente:")
     81     print(f"  {pending.get('alias')} -> {pending.get('destination')}\n")
     82     print("Status:")
     83     print("  pending")
     84     return 0
     85 
     86 
     87 def cmd_cancel() -> int:
     88     username = ea.current_username()
     89     cancelled = ea.cancel_latest_pending(username)
     90     if cancelled is None:
     91         print("nenhum pedido pendente para cancelar.")
     92         return 1
     93     print("Pedido cancelado.")
     94     return 0
     95 
     96 
     97 def build_parser() -> argparse.ArgumentParser:
     98     p = argparse.ArgumentParser(
     99         prog="runv-email-alias",
    100         description="Solicitar alias username@runv.club que encaminha para o seu email externo.",
    101     )
    102     sub = p.add_subparsers(dest="command", required=True)
    103     req = sub.add_parser("request", help="pedir alias (só informa o email de destino)")
    104     req.add_argument("destination", help="email externo de destino")
    105     sub.add_parser("status", help="ver alias activo e pedidos pendentes")
    106     sub.add_parser("cancel", help="cancelar pedido pendente mais recente")
    107     return p
    108 
    109 
    110 def main(argv: list[str] | None = None) -> int:
    111     try:
    112         args = build_parser().parse_args(argv)
    113         if args.command == "request":
    114             return cmd_request(args.destination)
    115         if args.command == "status":
    116             return cmd_status()
    117         if args.command == "cancel":
    118             return cmd_cancel()
    119         return 1
    120     except KeyboardInterrupt:
    121         print("\nInterrompido.", file=sys.stderr)
    122         return 130
    123     except SystemExit:
    124         raise
    125     except Exception as e:
    126         ea.rc.friendly_exit(f"erro: {e}")
    127 
    128 
    129 if __name__ == "__main__":
    130     raise SystemExit(main())