Esboço aproximado de um plugin irssi znc auto-opt

Eu escrevi um plug-in irssi rápido que me permite executar algumas sessões de irssi no tmux em vários hosts de nuvem que operam uns aos outros usando o protocolo auto-op popularizado pelo znc bouncer. Posso fazer o tmux e começar a conversar como qualquer um deles.

Protocolo ZNC Auto-op

O protocolo de operação automática ZNC é uma sequência de avisos IRC.

bot: !ZNCAO CHALLENGE uOceZDNtXOv36VJXc5Dt0Ji9NiZxX0Tz 
you
: !ZNCAO RESPONSE 51f34b12e2f2a5678a173a97f73fc5dc

O bot tem duas coisas em comum com você: um segredo e um desafio enfêmero de 32 caracteres que ele envia sempre que vê você. A resposta é um md5sum do segredo, :: e do desafio.

Código de demonstração
O seguinte é um código muito aproximado, eliminado para abreviar e não funciona. Tem muitos detalhes que demorei um pouco para descobrir.

Precisamos de uma função md5 e dependemos de uma função (não fornecida aqui) para gerar strings aleatórias de um certo comprimento (gerar string aleatória int).

use strict;
use Digest::MD5 qw(md5_hex);

Existem dois manipuladores de sinais para entradas e notificações de canal.

Emitindo um desafio
Quando um nick entra no canal e pode ser mapeado para um segredo compartilhado, emita um desafio:

sub message_join {
my ($server, $channel, $nick, $address) = @_;
my ($challenge) = generate_random_string(32);
$server
->command("NOTICE $nick !ZNCAO CHALLENGE $challenge");
}

Lidando com uma resposta
Se o bot receber um aviso, pode ser uma resposta ou um desafio.

sub event_notice {
my ($server, $msg, $nick, $address, $target) = @_;

Para uma resposta, calcule a resposta esperada tomando o md5 da concatenação de senha compartilhada, ::, e o desafio enviado.

my ($to,$response) = $msg =~ m{^(S+)s+:s*!ZNCAOs+RESPONSEs+(.+)$};
my ($expected_response) = md5_hex($password . "::" . $challenge);
if ($response eq $expected_response) {
# op them
}

Oh Ho! Somos um desafio
Para um desafio, responda usando a mesma fórmula de processamento de uma resposta e envie um aviso.

my ($to,$challenge) = $msg =~ m{^(S+)s+:s*!ZNCAOs+CHALLENGEs+(.+)$};
my ($response) = md5_hex($password . "::" . $challenge);
$server
->command("NOTICE $nick !ZNCAO RESPONSE $response");

Registro de sinal
Registre os dois sinais para avisos e entradas de canal.

Irssi::signal_add("event notice", "event_notice");
Irssi::signal_add("message join", "message_join");