1

Deejay redis subs to RedisLib.pm, translate comments, small fixes

This commit is contained in:
eleksir
2022-01-28 20:07:02 +03:00
parent 731d707baa
commit e135ef7d7c
3 changed files with 117 additions and 85 deletions

View File

@@ -7,7 +7,9 @@ use warnings;
use utf8; use utf8;
use open qw (:std :utf8); use open qw (:std :utf8);
use English qw ( -no_match_vars ); use English qw ( -no_match_vars );
use Carp qw (carp); use Carp qw (carp);
use Clone qw (clone);
use Math::Random::Secure qw (irand); use Math::Random::Secure qw (irand);
use Data::Dumper; use Data::Dumper;
use Log::Any qw ($log); use Log::Any qw ($log);
@@ -24,6 +26,12 @@ our @EXPORT_OK = qw (Command Highlight BotSleep IsCensored);
my $c = LoadConf (); my $c = LoadConf ();
my $csign = $c->{telegrambot}->{csign}; my $csign = $c->{telegrambot}->{csign};
my $redismsg->{from} = 'telegram';
$redismsg->{plugin} = 'telegram';
$redismsg->{misc}->{answer} = 1;
$redismsg->{misc}->{csign} = $c->{telegrambot}->{csign};
$redismsg->{misc}->{msg_format} = 0;
$redismsg->{misc}->{fwd_cnt} = 1;
sub Command { sub Command {
my $self = shift; my $self = shift;
@@ -33,13 +41,9 @@ sub Command {
my $reply; my $reply;
my ($userid, $username, $fullname, $highlight, $visavi) = Highlight ($msg); my ($userid, $username, $fullname, $highlight, $visavi) = Highlight ($msg);
my $rmsg = clone ($redismsg);
my $rmsg->{from} = 'telegram';
$rmsg->{misc}->{answer} = 1;
$rmsg->{misc}->{csign} = $csign;
$rmsg->{userid} = $userid; $rmsg->{userid} = $userid;
$rmsg->{chatid} = $chatid; $rmsg->{chatid} = $chatid;
$rmsg->{plugin} = 'telegram';
if ($chatid >= 0) { if ($chatid >= 0) {
$rmsg->{mode} = 'private'; $rmsg->{mode} = 'private';
@@ -48,7 +52,9 @@ sub Command {
} }
my $cmd = substr $text, 1; my $cmd = substr $text, 1;
my @cmds = qw (tits boobs tities boobies сиси сисечки butt booty ass попа попка);
# Проверка #1 на админское разрешение некоторых команд
my @cmds = qw (tits boobs tities boobies сиси сисечки);
while (my $check = pop @cmds) { while (my $check = pop @cmds) {
if ($cmd eq $check) { if ($cmd eq $check) {
@@ -58,6 +64,7 @@ sub Command {
} }
} }
# Проверка #2 на админское разрешение некоторых команд
$#cmds = -1; $#cmds = -1;
@cmds = qw (butt booty ass попа попка); @cmds = qw (butt booty ass попа попка);
@@ -69,6 +76,7 @@ sub Command {
} }
} }
# Полноценный поиск простой команды во входящем сообщении
$#cmds = -1; $#cmds = -1;
@cmds = qw (ping пинг пинх pong понг понх coin монетка roll dice кости ver version версия хэлп halp kde кде lat @cmds = qw (ping пинг пинх pong понг понх coin монетка roll dice кости ver version версия хэлп halp kde кде lat
лат friday пятница proverb пословица fortune фортунка f ф anek анек анекдот buni cat кис drink праздник fox лис лат friday пятница proverb пословица fortune фортунка f ф anek анек анекдот buni cat кис drink праздник fox лис
@@ -84,16 +92,18 @@ sub Command {
} }
} }
# TODO: Заменить на сравнение со строкой? # Поиск "сложных" команд во входящем сообщении
if (($cmd =~ /^w\s/u) || ($cmd =~ /^п\s/u) || ($cmd =~ /^weather\s/u) || ($cmd =~ /^погода\s/u) || if (($cmd =~ /^w\s/u) || ($cmd =~ /^п\s/u) || ($cmd =~ /^weather\s/u) || ($cmd =~ /^погода\s/u) ||
($cmd =~ /^погодка\s/u) || ($cmd =~ /^погадка\s/u) || ($cmd =~ /^karma\s/u) || ($cmd =~ /карма\s/u)) { ($cmd =~ /^погодка\s/u) || ($cmd =~ /^погадка\s/u) || ($cmd =~ /^karma\s/u) || ($cmd =~ /карма\s/u)) {
$bingo = 1; $bingo = 1;
} }
# Если команда найдена...
if ($bingo) { if ($bingo) {
$rmsg->{message} = $text; $rmsg->{message} = $text;
$self->log->debug ('[DEBUG] Sending message to redis ' . Dumper ($rmsg)); $self->log->debug ('[DEBUG] Sending message to redis ' . Dumper ($rmsg));
# Для некоторых команд мы хотим получать форматированный вывод
$#cmds = -1; $#cmds = -1;
@cmds = qw (fortune фортунка f ф anek анек анекдот buni cat кис fox лис frog лягушка horse лошадь @cmds = qw (fortune фортунка f ф anek анек анекдот buni cat кис fox лис frog лягушка horse лошадь
лошадка monkeyuser owl сова сыч rabbit bunny кролик snail улитка tits boobs tities boobies сиси сисечки лошадка monkeyuser owl сова сыч rabbit bunny кролик snail улитка tits boobs tities boobies сиси сисечки
@@ -106,6 +116,7 @@ sub Command {
} }
} }
# Для других команд, хотим, чтобы было упоминание пользователя в ответе, чтобы подсветить его
$#cmds = -1; $#cmds = -1;
@cmds = qw (dig копать fish fishing рыба рыбка рыбалка); @cmds = qw (dig копать fish fishing рыба рыбка рыбалка);
@@ -117,6 +128,7 @@ sub Command {
} }
} }
# Если соединения с редиской нету, ждём, пока оно появится. Своего рода костыль на всякий случай.
{ {
do { do {
my $ready = eval { $main::RCONN->is_connected; }; my $ready = eval { $main::RCONN->is_connected; };
@@ -129,6 +141,7 @@ sub Command {
$pubsub->json ($c->{'redis_router_channel'})->notify ( $pubsub->json ($c->{'redis_router_channel'})->notify (
$c->{'redis_router_channel'} => $rmsg $c->{'redis_router_channel'} => $rmsg
); );
# Если команда не найдена, но строка подозрительно напоминает команду help
} elsif (substr ($text, 1) eq 'help' || substr ($text, 1) eq 'помощь') { } elsif (substr ($text, 1) eq 'help' || substr ($text, 1) eq 'помощь') {
$reply = << "MYHELP"; $reply = << "MYHELP";
``` ```
@@ -170,10 +183,11 @@ ${csign}karma фраза | ${csign}карма фраза - посмотреть
MYHELP MYHELP
$msg->replyMd ($reply); $msg->replyMd ($reply);
return; return;
# Если строка не найдена, но это команда admin
} elsif (substr ($text, 1) eq 'admin' || substr ($text, 1) eq 'админ') { } elsif (substr ($text, 1) eq 'admin' || substr ($text, 1) eq 'админ') {
my $member = $self->getChatMember ({ 'chat_id' => $msg->chat->id, 'user_id' => $msg->from->id }); my $member = $self->getChatMember ({ 'chat_id' => $msg->chat->id, 'user_id' => $msg->from->id });
# this msg should be shown only if admins of chat request it # Это должно показываться только админам чата
if (($member->status eq 'administrator') || ($member->status eq 'creator')) { if (($member->status eq 'administrator') || ($member->status eq 'creator')) {
$reply = << "MYADMIN"; $reply = << "MYADMIN";
``` ```
@@ -200,19 +214,24 @@ MYADMIN
} }
return; return;
# Если строка не найдена, но это команда admin с параметрами
} elsif ((substr ($text, 1, 5) eq 'admin' || substr ($text, 1, 5) eq 'админ') && (length ($text) >= 8)) { } elsif ((substr ($text, 1, 5) eq 'admin' || substr ($text, 1, 5) eq 'админ') && (length ($text) >= 8)) {
my $member = $self->getChatMember ({ 'chat_id' => $msg->chat->id, 'user_id' => $msg->from->id }); my $member = $self->getChatMember ({ 'chat_id' => $msg->chat->id, 'user_id' => $msg->from->id });
# this msg should be shown only if admins of chat request it # Это должно показываться только админам чата
if (($member->status eq 'administrator') || ($member->status eq 'creator')) { if (($member->status eq 'administrator') || ($member->status eq 'creator')) {
# Вынем субкоманду, это первый аргумент команды admin
my $command = trim (substr $text, 7); my $command = trim (substr $text, 7);
$cmd = undef; $cmd = undef;
my $args; my $args;
($cmd, $args) = split /\s+/, $command, 2; ($cmd, $args) = split /\s+/, $command, 2;
# Субкоманды не нашлось, ну и какбэ досвидонья
if ($cmd eq '') { if ($cmd eq '') {
return; return;
# Субкоманда censor...
} elsif ($cmd eq 'censor' || $cmd eq 'ценз') { } elsif ($cmd eq 'censor' || $cmd eq 'ценз') {
# Censor с аргументами
if (defined ($args) && ($args ne '')) { if (defined ($args) && ($args ne '')) {
my ($msgType, $toggle) = split /\s/, $args, 2; my ($msgType, $toggle) = split /\s/, $args, 2;
@@ -229,9 +248,11 @@ MYADMIN
} }
} }
} }
# Censor без аргументов, выдаёт список типов сообщений и будут ли они автоматически удаляться
} else { } else {
$reply = ListForbidden ($chatid); $reply = ListForbidden ($chatid);
} }
# Хотим ли мы показывать фортунку с утра
} elsif ($cmd eq 'fortune' || $cmd eq 'фортунка') { } elsif ($cmd eq 'fortune' || $cmd eq 'фортунка') {
if (defined $args) { if (defined $args) {
if ($args == 1) { if ($args == 1) {
@@ -242,6 +263,7 @@ MYADMIN
} else { } else {
$reply = FortuneStatus ($chatid); $reply = FortuneStatus ($chatid);
} }
# Хотим ли мы удалять "сообщения от каналов"
} elsif ($cmd eq 'chan_msg') { } elsif ($cmd eq 'chan_msg') {
if (defined $args) { if (defined $args) {
if ($args == 1) { if ($args == 1) {
@@ -252,6 +274,7 @@ MYADMIN
} else { } else {
$reply = ChanMsgStatus ($chatid); $reply = ChanMsgStatus ($chatid);
} }
# Работает ли плагин oboobs в чатике
} elsif ($cmd eq 'oboobs') { } elsif ($cmd eq 'oboobs') {
if (defined $args) { if (defined $args) {
if ($args == 1) { if ($args == 1) {
@@ -262,6 +285,7 @@ MYADMIN
} else { } else {
$reply = PluginStatus ($chatid, 'oboobs'); $reply = PluginStatus ($chatid, 'oboobs');
} }
# Работает ли плагин obutts в чатике
} elsif ($cmd eq 'obutts') { } elsif ($cmd eq 'obutts') {
if (defined $args) { if (defined $args) {
if ($args == 1) { if ($args == 1) {

View File

@@ -5,37 +5,107 @@ use strict;
use warnings; use warnings;
use utf8; use utf8;
use open qw (:std :utf8); use open qw (:std :utf8);
use Log::Any qw ($log); use Log::Any qw ($log);
use Data::Dumper; # Чтобы "уж точно" использовать hiredis-биндинги, загрузим этот модуль перед Mojo::Redis
use Protocol::Redis::XS;
use Mojo::Redis;
use Mojo::Redis::Connection;
use BotLib::Conf qw (LoadConf);
use version; our $VERSION = qw (1.0); use version; our $VERSION = qw (1.0);
use Exporter qw (import); use Exporter qw (import);
our @EXPORT_OK = qw (redis_parse_message); our @EXPORT_OK = qw (redis_parse_message redis_events_listener);
my $c = LoadConf ();
sub redis_parse_message { sub redis_parse_message {
my $self = shift; my $self = shift;
my $m = shift; my $m = shift;
my $message; my $message;
# We cannot send message if we're not connected to telegram # Мы "не можем" отправлять сообщения в телеграм, если мы к нему не подключены
# TODO: Queue messages properly. # (конечно, можем, но Teapot-lib предполагает, что объектик с чатом - это его собственность, а городить свой что-то
# не очень хочется)
until (defined $main::TGM) { until (defined $main::TGM) {
sleep 1; sleep 1;
} }
# TODO: add some checks, at least that the bot is not muted in chat
if ($m->{misc}->{msg_format}) { if ($m->{misc}->{msg_format}) {
$message->{parse_mode} = 'Markdown'; $message->{parse_mode} = 'Markdown';
} }
$message->{chat_id} = $m->{chatid}; $message->{chat_id} = $m->{chatid};
$message->{text} = $m->{message}; $message->{text} = $m->{message};
$main::TGM->sendMessage ($message);
if (Teapot::Bot::Object::ChatPermissions::canTalk ($main::TGM, $m->{chatid})) {
# Результат этого действия нас не сильно волнует, т.к. если будет ошибка, то в лог попадёт трейс
$main::TGM->sendMessage ($message);
}
return; return;
}; };
sub redis_events_listener {
$log->notice ('[NOTICE]Run redis events listener');
# If we already connected there is no point to disconnect
if (defined $main::REDIS) {
my $connected = eval { Mojo::Redis::Connection->is_connected ($main::REDIS); };
if ($connected) {
$log->notice ('[NOTICE] Redis client already running and connected');
return;
} else {
$log->notice ('[NOTICE] Redis client registered, but looks like it is not connected, try to re-connect');
$main::REDIS = undef;
}
}
my $r = Mojo::Redis->new (
sprintf 'redis://%s:%s/1', $c->{redis_server}, $c->{redis_port}
);
$log->notice ('[NOTICE] New redis client registered, registering callbacks');
# Don't forget to update global ref to our redis context
$main::REDIS = $r;
$r->on (
connection => sub {
my ($redis, $connection) = @_;
$main::RCONN = $connection;
# Log error
$connection->on (
error => sub {
my ($conn, $error) = @_;
$log->error ("[ERROR] Redis connection error: $error");
$main::RCONN = undef;
return;
}
);
return;
}
);
# Subscribe to channels
my $pubsub = $r->pubsub;
my $sub;
my $rpm = \&redis_parse_message;
$log->notice ('[NOTICE] Subscribing to redis channels');
foreach my $channel (@{$c->{redis_channels}}) {
$log->info ("[INFO] Subscribing to $channel");
$sub->{$channel} = $pubsub->json ($channel)->listen (
$channel => sub { $rpm->(@_); }
);
}
return;
}
1; 1;
# vim: set ft=perl noet ai ts=4 sw=4 sts=4: # vim: set ft=perl noet ai ts=4 sw=4 sts=4:

View File

@@ -13,16 +13,12 @@ use File::Path qw (make_path);
use Log::Any qw ($log); use Log::Any qw ($log);
use Math::Random::Secure qw (irand); use Math::Random::Secure qw (irand);
use Mojo::Base 'Teapot::Bot::Brain'; use Mojo::Base 'Teapot::Bot::Brain';
# Чтобы "уж точно" использовать hiredis-биндинги, загрузим этот модуль перед Mojo::Redis
use Protocol::Redis::XS;
use Mojo::Redis;
use Mojo::Redis::Connection;
use BotLib::Admin qw (FortuneToggleList ChanMsgEnabled); use BotLib::Admin qw (FortuneToggleList ChanMsgEnabled);
use BotLib qw (Command Highlight BotSleep IsCensored); use BotLib qw (Command Highlight BotSleep IsCensored);
use BotLib::Conf qw (LoadConf); use BotLib::Conf qw (LoadConf);
use BotLib::Util qw (trim fmatch); use BotLib::Util qw (trim fmatch);
use RedisLib qw (redis_parse_message); use RedisLib qw (redis_parse_message redis_events_listener);
use version; our $VERSION = qw (1.0); use version; our $VERSION = qw (1.0);
use Exporter qw (import); use Exporter qw (import);
@@ -225,7 +221,7 @@ sub __on_msg {
$self->deleteMessage ({chat_id => $chatid, message_id => $msg->{message_id}}); $self->deleteMessage ({chat_id => $chatid, message_id => $msg->{message_id}});
} }
# Некоторые рекламные товарищи пыьаются срать своими каналами в чятик это тоже можно зацензурить ботом и это # Некоторые рекламные товарищи пытаются срать своими каналами в чятик это тоже можно зацензурить ботом и это
# пидорство он будет удалять asap # пидорство он будет удалять asap
# 136817688 - это специальный id пользователя, который принимает облик канала, на него можно нажать и попасть # 136817688 - это специальный id пользователя, который принимает облик канала, на него можно нажать и попасть
# на рекламируемый канал # на рекламируемый канал
@@ -319,19 +315,20 @@ sub __on_msg {
$rmsg->{userid} = $userid; $rmsg->{userid} = $userid;
$rmsg->{chatid} = $chatid; $rmsg->{chatid} = $chatid;
# phrase directed to bot # Сообщение обращено к боту
if ((lc ($text) =~ /^${qname}[\,|\:]? (.+)/) or (lc ($text) =~ /^${qtname}[\,|\:]? (.+)/)){ if ((lc ($text) =~ /^${qname}[\,|\:]? (.+)/) or (lc ($text) =~ /^${qtname}[\,|\:]? (.+)/)){
$phrase = $1; $phrase = $1;
$rmsg->{message} = $phrase; $rmsg->{message} = $phrase;
# bot mention by name # Бота упомянули по имени
} elsif ((lc ($text) =~ /.+ ${qname}[\,|\!|\?|\.| ]/) or (lc ($text) =~ / $qname$/)) { } elsif ((lc ($text) =~ /.+ ${qname}[\,|\!|\?|\.| ]/) or (lc ($text) =~ / $qname$/)) {
$phrase = $text; $phrase = $text;
$rmsg->{message} = $phrase; $rmsg->{message} = $phrase;
# bot mention by telegram name # Бота упомянули по телеграммному имени
} elsif ((lc ($text) =~ /.+ ${qtname}[\,|\!|\?|\.| ]/) or (lc ($text) =~ / $qtname$/)) { } elsif ((lc ($text) =~ /.+ ${qtname}[\,|\!|\?|\.| ]/) or (lc ($text) =~ / $qtname$/)) {
$phrase = $text; $phrase = $text;
$rmsg->{message} = $phrase; $rmsg->{message} = $phrase;
} else { } else {
$rmsg->{message} = $text; $rmsg->{message} = $text;
$rmsg->{misc}->{answer} = 0; $rmsg->{misc}->{answer} = 0;
@@ -376,65 +373,6 @@ sub __on_msg {
return; return;
} }
sub __redisListener {
$log->error ('Run redis listener');
# If we already connected there is no point to disconnect
if (defined $main::REDIS) {
my $connected = eval { Mojo::Redis::Connection->is_connected ($main::REDIS); };
if ($connected) {
$log->notice ('[NOTICE] Redis client already running and connected');
return;
} else {
$log->notice ('[NOTICE] Redis client registered, but looks like it is not connected, try to re-connect');
$main::REDIS = undef;
}
}
my $r = Mojo::Redis->new (
sprintf 'redis://%s:%s/1', $c->{redis_server}, $c->{redis_port}
);
$log->notice ('[NOTICE] New redis client registered, registering callbacks');
# Don't forget to update global ref to our redis context
$main::REDIS = $r;
$r->on (
connection => sub {
my ($redis, $connection) = @_;
$main::RCONN = $connection;
# Log error
$connection->on (
error => sub {
my ($conn, $error) = @_;
$log->error ("[ERROR] Redis connection error: $error");
$main::RCONN = undef;
return;
}
);
return;
}
);
# Subscribe to channels
my $pubsub = $r->pubsub;
my $sub;
my $rpm = \&redis_parse_message;
$log->notice ('[NOTICE] Subscribing to redis channels');
foreach my $channel (@{$c->{redis_channels}}) {
$log->info ("[INFO] Subscribing to $channel");
$sub->{$channel} = $pubsub->json ($channel)->listen (
$channel => sub { $rpm->(@_); }
);
}
return;
}
sub RandomCommonPhrase { sub RandomCommonPhrase {
my @myphrase = ( my @myphrase = (
'Так, блядь...', 'Так, блядь...',
@@ -462,7 +400,7 @@ sub init {
$self->add_listener (\&__on_msg); $self->add_listener (\&__on_msg);
$self->add_repeating_task (900, \&__cron); $self->add_repeating_task (900, \&__cron);
__redisListener (); redis_events_listener ();
return; return;
} }