runv-server

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

runv-finger (3286B)


      1 #!/usr/bin/env python3
      2 """Mostra o perfil público de um membro runv.club (estilo finger)."""
      3 
      4 from __future__ import annotations
      5 
      6 import argparse
      7 import sys
      8 
      9 sys.tracebacklimit = 0
     10 
     11 
     12 def _bootstrap() -> None:
     13     from pathlib import Path
     14 
     15     installed = Path("/usr/local/share/runv/lib")
     16     candidates = [installed]
     17     script = Path(__file__).resolve()
     18     if script.parent.name == "bin":
     19         candidates.insert(0, script.parent.parent / "lib")
     20     for c in candidates:
     21         if (c / "runv_community.py").is_file() and str(c) not in sys.path:
     22             sys.path.insert(0, str(c))
     23             return
     24 
     25 
     26 _bootstrap()
     27 import runv_community as rc  # noqa: E402
     28 
     29 
     30 def cmd_finger(username: str) -> int:
     31     user = rc.validate_username(username)
     32     paths = rc.home_paths(user)
     33     if not paths["home"].is_dir():
     34         rc.friendly_exit(f"usuário não encontrado: {user}")
     35 
     36     print(f"{user} @ runv.club\n")
     37 
     38     profile_text = rc.read_text_limited(paths["profile"])
     39     profile, warn = rc.parse_profile_json(profile_text)
     40     if warn:
     41         print(warn)
     42 
     43     def field(label: str, value: str | None) -> None:
     44         print(f"{label}: {value if value and value.strip() else 'não informado'}")
     45 
     46     if profile:
     47         field("Nome", profile.get("display_name", ""))
     48         field("Bio", profile.get("bio", ""))
     49         field("Local", profile.get("location", ""))
     50     else:
     51         field("Nome", None)
     52         field("Bio", None)
     53         field("Local", None)
     54 
     55     if paths["public_index"].is_file():
     56         print(f"Home: /~{user}/")
     57         mtime = rc.format_mtime_local(paths["public_index"])
     58         if mtime:
     59             print(f"Home atualizada: {mtime}")
     60     else:
     61         print("Home: não informado")
     62 
     63     project_text = rc.read_text_limited(paths["project"])
     64     plan_text = rc.read_text_limited(paths["plan"])
     65 
     66     print("\nProjeto:")
     67     if project_text and project_text.strip():
     68         for line in project_text.strip().splitlines():
     69             print(f"  {line}")
     70     else:
     71         print("  não informado")
     72 
     73     print("\n.plan:")
     74     if plan_text and plan_text.strip():
     75         for line in plan_text.strip().splitlines():
     76             print(f"  {line}")
     77     else:
     78         print("  não informado")
     79 
     80     if profile:
     81         links = profile.get("links") or []
     82         print("\nLinks:")
     83         if links:
     84             for link in links:
     85                 print(f"  {link}")
     86         else:
     87             print("  não informado")
     88         interests = profile.get("interests") or []
     89         print("\nInteresses:")
     90         if interests:
     91             for item in interests:
     92                 print(f"  {item}")
     93         else:
     94             print("  não informado")
     95 
     96     return 0
     97 
     98 
     99 def main(argv: list[str] | None = None) -> int:
    100     try:
    101         p = argparse.ArgumentParser(
    102             prog="runv-finger",
    103             description="Mostra o perfil público de outro membro.",
    104         )
    105         p.add_argument("username", help="nome de utilizador Unix")
    106         args = p.parse_args(argv)
    107         return cmd_finger(args.username)
    108     except KeyboardInterrupt:
    109         print("\nInterrompido.", file=sys.stderr)
    110         return 130
    111     except SystemExit:
    112         raise
    113     except Exception as e:
    114         rc.friendly_exit(f"erro: {e}")
    115 
    116 
    117 if __name__ == "__main__":
    118     raise SystemExit(main())