From b7013d6ab0c7bf40104112903188fffd4594f136 Mon Sep 17 00:00:00 2001 From: eleksir Date: Tue, 4 Jan 2022 15:43:26 +0300 Subject: [PATCH] Loop detection, easter eggs, update readme, update sample config, fix telegram-crippled brain names --- .perlcriticrc | 1 + README | 3 +- data/config_sample.json | 17 +++++----- lib/Craniac.pm | 71 +++++++++++++++++++++++++++++++++-------- 4 files changed, 70 insertions(+), 22 deletions(-) diff --git a/.perlcriticrc b/.perlcriticrc index 41f004d..1f9bb32 100644 --- a/.perlcriticrc +++ b/.perlcriticrc @@ -93,3 +93,4 @@ lib_sections = NAME | VERSION | DESCRIPTION | AUTHOR | LICENSE AND COPYRIGHT [-ControlStructures::ProhibitDeepNests] # Have to use it, so fuckoff +[-Variables::ProhibitPackageVars] diff --git a/README b/README index 6603982..4c09113 100644 --- a/README +++ b/README @@ -14,7 +14,8 @@ aleesa-craniac и остальные, для которых ему надо решить нужен ли ответ и по-необходимости сгенерировать его, используя данные в цепях Маркова. -Ответ направляется в redis-канал, указанный в поле plugin входящего сообщения. +Ответ направляется в redis-канал, указанный в поле plugin входящего сообщения, если не предполагается некоей особой +логики, связанной с easter egg поведением. Формат протокола - см README от aleesa-misc. diff --git a/data/config_sample.json b/data/config_sample.json index 48820bc..14fd93f 100644 --- a/data/config_sample.json +++ b/data/config_sample.json @@ -1,26 +1,27 @@ { "server" : "redis", "port" : "6379", - -# inbound redis channels, where we subscribed "channels": [ - "craniac", + "craniac" ], -# should we fork() and become unix daemon? + # should we fork() and become unix daemon? "daemonize": 1, -# caches and other data goes there + # caches and other data goes there "cachedir" : "data/cache", "braindir" : "data/brains", # unprivileged system user to run bot as "user" : "nobody", -# logs goes there + # logs goes there "log" : "/var/log/aleesa-craniac/aleesa-craniac.log", "loglevel": "info", -# ditto - "pid" : "/var/run/aleesa-craniac/aleesa-craniac.pid" + # ditto + "pid" : "/var/run/aleesa-craniac/aleesa-craniac.pid", + + # maximal amount of message forwardings, to avoid endless loops + "forwards_max" : 5 } diff --git a/lib/Craniac.pm b/lib/Craniac.pm index aaaff97..a0f76db 100644 --- a/lib/Craniac.pm +++ b/lib/Craniac.pm @@ -41,6 +41,7 @@ sub RunCraniac (); my $c = LoadConf (); my $loglevel = $c->{'loglevel'} // 'info'; +my $fwd_cnt = $c->{'forward_max'} // 5; my $logfile; my $log; @@ -107,15 +108,17 @@ sub brains (@) { unless (defined $hailo->{$chatid}) { my $cid = $chatid; + my $brainname; # Костыль, чтобы не портировать данные из телеграммных мозгов unless ($telegram) { $cid = utf2sha1 ($chatid); $cid =~ s/\//-/xmsg; + $brainname = sprintf '%s/%s.sqlite', $c->{braindir}, $cid; + } else { + $brainname = sprintf '%s/%s.brain.sqlite', $c->{braindir}, $cid; } - my $brainname = sprintf '%s/%s.sqlite', $c->{braindir}, $cid; - $hailo->{$chatid} = eval { Hailo->new ( brain => $brainname, @@ -147,6 +150,18 @@ my $parse_message = sub { # Если $m->{misc}->{answer} не существует, то проставим его как 1, предполагаем, что по-умолчанию ответ от нас # всё-таки ожидают. Если что - уточним ниже. if (defined $m->{misc}) { + unless (defined $m->{misc}->{fwd_cnt}) { + $m->{misc}->{fwd_cnt} = 1; + } else { + if ($m->{misc}->{fwd_cnt} > $fwd_cnt) { + $log->error ('Forward loop detected, discarding message.'); + $log->debug (Dumper $m); + return; + } else { + $m->{misc}->{fwd_cnt}++; + } + } + unless (defined $m->{misc}->{answer}) { $m->{misc}->{answer} = 1; } @@ -251,17 +266,35 @@ my $parse_message = sub { } } else { # Пока что нам нечего ответить, известных фраз не нашлось. Ищем дальше, на сей раз фразы, зависящие от режима - # общения - приватного ли публичного. + # общения - приватного или публичного. if ($m->{mode} eq 'private') { - $phrase =~ s/^\s*(вот\s+)?скажи(\s*мне)?\s*//gui; - $phrase =~ s/\s*(,)?\s*а\s*\?$/?/gui; + # Если указанной в unless-е строки во фразе нету, то можно поискать другие приватные фразы + unless ($phrase =~ s/^\s*(вот\s+)?скажи(\s*мне)?\s*//gui) { + if ($phrase =~ /покажи +(сиськи|сиси|титьки)\s*$/ui) { + $send_to = 'webapp'; + $reply = '!boobs'; + } elsif ($phrase =~ /show +(titts|tities|boobs)\s*$/i) { + $send_to = 'webapp'; + $reply = '!boobs'; + } elsif ($phrase =~ /покажи +(попку|попу) *$/ui) { + $send_to = 'webapp'; + $reply = '!ass'; + } elsif ($phrase =~ /show +(ass|butt|butty) *$/i) { + $send_to = 'webapp'; + $reply = '!ass'; + } + } - if ($phrase =~ /^\s*кто\s+все\s+эти\s+люди\s*\?\s*$/ui) { - $reply = 'Какие "люди"? Мы здесь вдвоём, только ты и я.'; - } elsif ($phrase =~ /^\s*кто\s+я\s*\?\s*$/ui) { - $reply = 'Где?'; - } elsif ($phrase =~ /^\s*кто\s+(здесь|тут)\s*\?\s*$/ui) { - $reply = 'Ты да я, да мы с тобой.'; + unless (defined $reply) { + $phrase =~ s/\s*(,)?\s*а\s*\?$/?/gui; + + if ($phrase =~ /^\s*кто\s+все\s+эти\s+люди\s*\?\s*$/ui) { + $reply = 'Какие "люди"? Мы здесь вдвоём, только ты и я.'; + } elsif ($phrase =~ /^\s*кто\s+я\s*\?\s*$/ui) { + $reply = 'Где?'; + } elsif ($phrase =~ /^\s*кто\s+(здесь|тут)\s*\?\s*$/ui) { + $reply = 'Ты да я, да мы с тобой.'; + } } # TODO: дописать запрос в webapp, для easter egg-ов, либо делать это на уровне aleesa-misc @@ -310,7 +343,13 @@ my $parse_message = sub { # Пытаемся что-то генерировать, если фраза длиннее 3-х букв if (length ($m->{message}) > 3) { # Lazy brain init - if (brains ($chatid, 1)) { + my $telegram = 0; + + if ($m->{plugin} eq 'telegram') { + $telegram = 1; + } + + if (brains ($chatid, $telegram)) { $reply = $hailo->{$chatid}->learn_reply ($m->{message}); # Если из реактора вернулся undef выдаём "общую" фразу из словаря @@ -342,7 +381,13 @@ my $parse_message = sub { } else { # пытаемся что-то запоминать, если фраза длиннее 3-х букв if (length ($m->{message}) > 3) { - if (brains ($chatid, 1)) { + my $telegram = 0; + + if ($m->{plugin} eq 'telegram') { + $telegram = 1; + } + + if (brains ($chatid, $telegram)) { $hailo->{$chatid}->learn ($m->{message}); } }