commit 8f21b46d62364b6f11a92b0d06efa97dd079ac74
parent b43375bf7b3a8a175d1e466ba34943240ae6039c
Author: Pablo Murad <pablo@pablomurad.com>
Date: Fri, 27 Mar 2026 01:25:00 -0300
patch irc
Diffstat:
6 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/docs/05-tools-and-system-experience.md b/docs/05-tools-and-system-experience.md
@@ -28,8 +28,8 @@ Flags úteis: `--force`, `--skip-apt` (ver `--help`).
## IRC / comando `chat`
- **Utilizador:** no servidor, use apenas o comando `chat` (wrapper em `/usr/local/bin/chat` após `tools/tools.py` ou `patches/patch_irc.py`). O cliente gráfico no terminal é `weechat` / `weechat-curses` (pacote `chat` no manifesto APT).
-- **Por omissão** (após `patches/patch_irc.py`): o WeeChat fica com um único servidor com autoconnect no arranque — nome interno **`runv`**, endereço **`irc.portalidea.com.br`**, porta **6697**, **TLS ligado**, autojoin só **`#runv`**. Outras redes que o utilizador adicionar manualmente **não** autoconectam por defeito (o patch desliga `autoconnect` nos outros servidores já existentes, sem apagar redes).
-- **Provisionamento:** o patch corre com `weechat-headless -a -r '…' --stdout` (o `-a` evita auto-connect durante o batch). O launcher **`chat` não usa `-a`**. Novas contas Unix criadas com `scripts/admin/create_runv_user.py` invocam o patch automaticamente para esse utilizador.
+- **Por omissão** (após `patches/patch_irc.py`): o WeeChat fica com um único servidor com autoconnect no arranque — nome interno **`runv`**, endereço **`irc.tilde.chat`**, porta **6697**, **TLS ligado**, autojoin só **`#runv`**. Outras redes que o utilizador adicionar manualmente **não** autoconectam por defeito (o patch desliga `autoconnect` nos outros servidores já existentes, sem apagar redes).
+- **Provisionamento:** o patch corre com `weechat-headless -a -r '…' --stdout` (o `-a` evita auto-connect durante o batch). O launcher **`chat` não usa `-a`**. Novas contas Unix criadas com `scripts/admin/create_runv_user.py` invocam o patch automaticamente para esse utilizador. O `tools/tools.py` também aplica o backfill IRC ao final da execução.
- **Backfill / admin:** `sudo python3 patches/patch_irc.py --all-users` (ou `--user NOME`). Requer `weechat-headless` no sistema.
Próximo: [06-site-and-apache.md](06-site-and-apache.md).
diff --git a/patches/patch_irc.py b/patches/patch_irc.py
@@ -45,7 +45,7 @@ VERSION: Final[str] = "0.04"
DEFAULT_USERS_JSON: Final[Path] = Path("/var/lib/runv/users.json")
DEFAULT_HOMES_ROOT: Final[Path] = Path("/home")
-DEFAULT_HOST: Final[str] = "irc.portalidea.com.br"
+DEFAULT_HOST: Final[str] = "irc.tilde.chat"
DEFAULT_PORT_TLS: Final[int] = 6697
DEFAULT_SERVER_NAME: Final[str] = "runv"
DEFAULT_AUTOJOIN: Final[str] = "#runv"
diff --git a/scripts/admin/create_runv_user.py b/scripts/admin/create_runv_user.py
@@ -1257,7 +1257,7 @@ def try_patch_irc_for_new_user(
log: logging.Logger,
) -> None:
"""
- Executa ``patches/patch_irc.py --user`` (WeeChat headless: servidor «runv», TLS, #runv).
+ Executa ``patches/patch_irc.py --user`` (WeeChat headless: servidor «runv», irc.tilde.chat, TLS, #runv).
Não aborta o provisionamento se o patch falhar; contas em ``IRC_PATCH_SKIP_USERS`` são ignoradas.
"""
if dry_run:
@@ -1908,7 +1908,7 @@ def main(argv: list[str] | None = None) -> int:
print(" public_gopher: pronto (gophermap)")
print(" public_gemini: pronto (index.gmi)")
print(" bind Gemini: /var/gemini/users/<user> <- ~/public_gemini (se o diretório existir)")
- print(" IRC: comando «chat» → irc.portalidea.com.br (TLS) #runv (patch_irc.py)")
+ print(" IRC: comando «chat» → irc.tilde.chat (TLS) #runv (patch_irc.py)")
if args.with_readme:
print(" README.md: criado em ~/README.md (pt-BR)")
else:
diff --git a/tools/bin/chat b/tools/bin/chat
@@ -1,6 +1,6 @@
#!/bin/sh
# runv.club — cliente IRC interactivo; config em ~/.config/weechat.
-# Por omissão (após patches/patch_irc.py): servidor interno «runv» → irc.portalidea.com.br:6697 (TLS), canal #runv.
+# Por omissão (após patches/patch_irc.py): servidor interno «runv» → irc.tilde.chat:6697 (TLS), canal #runv.
# Utilizadores: use só o comando «chat»; não é preciso memorizar outros nomes de binário.
IRC_UI=""
@@ -33,7 +33,7 @@ if [ ! -f "$CONFIG_DIR/irc.conf" ]; then
echo "runv: peça ao admin para correr patches/patch_irc.py (rede IRC da casa)." >&2
elif ! grep -q '^runv\.' "$CONFIG_DIR/irc.conf" 2>/dev/null; then
echo "runv: aviso — servidor «runv» não está definido em $CONFIG_DIR/irc.conf." >&2
- echo "runv: o admin pode aplicar patches/patch_irc.py (TLS, #runv em irc.portalidea.com.br)." >&2
+ echo "runv: o admin pode aplicar patches/patch_irc.py (TLS, #runv em irc.tilde.chat)." >&2
fi
exec "$IRC_UI" -d "$CONFIG_DIR" "$@"
diff --git a/tools/bin/runv-help b/tools/bin/runv-help
@@ -29,7 +29,7 @@ printf ' %bgit%b Controlo de versão.\n' "${G}" "${R}"
printf ' %bless%b Paginar ficheiros longos (ex.: less README.md).\n' "${G}" "${R}"
printf ' %btmux%b / %bbyobu%b Multiplexadores de terminal (várias sessões).\n' "${G}" "${R}" "${G}" "${R}"
printf ' %bmutt%b E-mail no terminal.\n' "${G}" "${R}"
-printf ' %bchat%b IRC da rede da casa (após o admin aplicar o patch no servidor).\n' "${G}" "${R}"
+printf ' %bchat%b IRC da rede da casa.\n' "${G}" "${R}"
printf ' %btree%b Árvore de diretórios.\n' "${G}" "${R}"
printf ' %brunv-games%b Jogos do servidor (inclui adventure e gotchi).\n' "${G}" "${R}"
printf '\n'
diff --git a/tools/tools.py b/tools/tools.py
@@ -34,6 +34,7 @@ DEST_BIN_DIR: Path = Path("/usr/local/bin")
DEST_MOTD: Path = Path("/etc/update-motd.d/60-runv")
DEST_SKEL: Path = Path("/etc/skel")
DEST_SSHD_DROPIN: Path = Path("/etc/ssh/sshd_config.d/90-runv-jailed.conf")
+PATCH_IRC_PATH: Path = TOOL_ROOT.parent / "patches" / "patch_irc.py"
@dataclass
@@ -452,6 +453,38 @@ def install_skel(
os.chmod(gemini_dir, 0o755)
+def apply_irc_patch(
+ *,
+ dry_run: bool,
+ log: logging.Logger,
+ summary: RunSummary,
+) -> None:
+ if not PATCH_IRC_PATH.is_file():
+ msg = f"patch IRC não encontrado: {PATCH_IRC_PATH}"
+ summary.errors.append(msg)
+ log.error("%s", msg)
+ return
+
+ cmd = [sys.executable, str(PATCH_IRC_PATH), "--all-users"]
+ if dry_run:
+ log.info("[dry-run] %s", " ".join(cmd))
+ summary.copied.append(f"patch IRC (simulado): {' '.join(cmd)}")
+ return
+
+ r = run_subprocess(cmd, dry_run=False, log=log)
+ assert r is not None
+ if r.returncode != 0:
+ err = (r.stderr or r.stdout or "").strip()
+ msg = f"patch_irc.py falhou (código {r.returncode})" + (f": {err}" if err else "")
+ summary.errors.append(msg)
+ log.error("%s", msg)
+ return
+
+ summary.copied.append("patch IRC aplicado a todos os utilizadores")
+ if r.stdout.strip():
+ log.info("patch IRC: %s", r.stdout.strip().splitlines()[-1])
+
+
def print_summary(summary: RunSummary, log: logging.Logger) -> None:
print()
print("========== runv-tools — resumo ==========")
@@ -539,6 +572,9 @@ def main(argv: list[str] | None = None) -> int:
log.info("Sincronizando skel em %s", DEST_SKEL)
install_skel(force=args.force, dry_run=args.dry_run, log=log, summary=summary)
+ log.info("Aplicando patch IRC (chat / WeeChat)")
+ apply_irc_patch(dry_run=args.dry_run, log=log, summary=summary)
+
print_summary(summary, log)
return 0