Compare commits
3 Commits
ba14f6e619
...
redis
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e135ef7d7c | ||
|
|
731d707baa | ||
|
|
6840e6d5d0 |
56
README.md
56
README.md
@@ -41,64 +41,8 @@ and all libraries should be downloaded, built, tested and installed.
|
|||||||
This bot does not [ultilize][4] webhooks, so in order to run it only well
|
This bot does not [ultilize][4] webhooks, so in order to run it only well
|
||||||
internet connection is required, no public-available ip address is needed.
|
internet connection is required, no public-available ip address is needed.
|
||||||
|
|
||||||
### Additional Settings to be performed in order to run bot as it designed
|
|
||||||
|
|
||||||
There are some "plugins" that requires registration on third party services
|
|
||||||
and API keys and secrets in order to work.
|
|
||||||
|
|
||||||
#### OpenWeatherMap
|
|
||||||
|
|
||||||
You should [register][5], [login][6] and [create][7] api key. Free plan have
|
|
||||||
all required features to run this "plugin".
|
|
||||||
|
|
||||||
Once key is created you should put it in **config.json** under openweathermap
|
|
||||||
section as appid. Thats it.
|
|
||||||
|
|
||||||
It is still impossible to disable this plugin, but "I'm working on it".
|
|
||||||
|
|
||||||
#### Imgur
|
|
||||||
|
|
||||||
This plugin "just exists" and is actually used nowhere around the code.
|
|
||||||
Anyway, to make use of it besides registering appropriate handler in code, you
|
|
||||||
should sign in imgur and get access token.
|
|
||||||
|
|
||||||
Actually at this time this "plugin" can be stub-ed with default config values.
|
|
||||||
|
|
||||||
Anyway, to fetch access token you should [login][8] and perform [registration][9]
|
|
||||||
of your app. Then you should authorize your app according to [this][10] manual. Or
|
|
||||||
[this][11] one.
|
|
||||||
|
|
||||||
#### Flickr
|
|
||||||
|
|
||||||
This "plugin" is really used to implement random picture link retrival plugins.
|
|
||||||
|
|
||||||
There is helper script in **bin/flickr_init.pl** that helps to get all required keys
|
|
||||||
and secrets from flickr api.
|
|
||||||
|
|
||||||
Before using it bot must be bootstrapped via **`bootstrap.sh`**.
|
|
||||||
|
|
||||||
[Login][11] and create an [app][12] in your flickr account. Then *logout* flickr account.
|
|
||||||
(It is required in order to properly get "verifier" parameter later).
|
|
||||||
|
|
||||||
Put your [app key and secret][13] to **config.json**. Ensure that "verifier" parameter
|
|
||||||
in Flickr-related part of config either absent or commented out.
|
|
||||||
|
|
||||||
Run **bin/flickr_init.pl** first time and follow on screen instructions - copy and
|
|
||||||
paste given link to browser login to flickr account and you'll be redirected to
|
|
||||||
example.com. Check address bar in browser to get so-called "verifier", put it in
|
|
||||||
**config.json**. Then run **bin/flickr_init.pl** again to store API access token in db
|
|
||||||
under data/image directory (in default config). You're done.
|
|
||||||
|
|
||||||
[1]: https://metacpan.org/pod/Telegram::Bot
|
[1]: https://metacpan.org/pod/Telegram::Bot
|
||||||
[2]: https://metacpan.org/pod/Hailo
|
[2]: https://metacpan.org/pod/Hailo
|
||||||
[3]: https://core.telegram.org/bots/api
|
[3]: https://core.telegram.org/bots/api
|
||||||
[4]: https://core.telegram.org/bots/api#getting-updates
|
[4]: https://core.telegram.org/bots/api#getting-updates
|
||||||
[5]: https://home.openweathermap.org/users/sign_up
|
|
||||||
[6]: https://home.openweathermap.org/users/sign_in
|
|
||||||
[7]: https://home.openweathermap.org/api_keys
|
|
||||||
[8]: https://imgur.com/signin
|
|
||||||
[9]: https://api.imgur.com/oauth2/addclient
|
|
||||||
[10]: https://apidocs.imgur.com/#authorization-and-oauth
|
|
||||||
[11]: https://identity.flickr.com/login
|
|
||||||
[12]: https://www.flickr.com/services/apps/create/apply/
|
|
||||||
[13]: https://www.flickr.com/services/api/keys/
|
|
||||||
|
|||||||
56
README_RU.md
56
README_RU.md
@@ -41,64 +41,8 @@ bash bootstrap.sh
|
|||||||
Бот не использует [вебхуки][4], поэтому ничего дополнительного, кроме хорошего
|
Бот не использует [вебхуки][4], поэтому ничего дополнительного, кроме хорошего
|
||||||
подключения к интернету ему не нужно.
|
подключения к интернету ему не нужно.
|
||||||
|
|
||||||
### Дополнительные настройки
|
|
||||||
|
|
||||||
Некоторые "плагины" требуют регистрации в сторонних сервисах (API keys, secrets
|
|
||||||
итд), чтобы бот не сыпал ошибками в логи (возможно, в дальнейшем возможно будет
|
|
||||||
отключить эти плагины).
|
|
||||||
|
|
||||||
#### OpenWeatherMap
|
|
||||||
|
|
||||||
Для работы погодного плагина, надо [заргистрироваться][5], [залогиниться][6] и
|
|
||||||
[создать][7] api key. Free plan предлагает всё необхдимое для работы "плагина".
|
|
||||||
|
|
||||||
Когда api key будет создан, его нужно вписать в **config.json** "секцию"
|
|
||||||
openweathermap в качестве appid. На этом всё.
|
|
||||||
|
|
||||||
#### Imgur
|
|
||||||
|
|
||||||
Этот плагин "просто есть" и его на самом деле ничто и никто не использует. И в
|
|
||||||
этой связи все настройки плагина можно оставить "как есть" в примере конфига.
|
|
||||||
|
|
||||||
Тем не менее, если есть большое желание, то можно [залогиниться][8] и
|
|
||||||
[зарегистрировать][9] бота как приложение, а потом разрешить приложению
|
|
||||||
пользоваться API-шкой, как описано в [этом][10] или [этом][11] мануале.
|
|
||||||
|
|
||||||
#### Flickr
|
|
||||||
|
|
||||||
Этот "плагин" действительно используется для добычи ссылок на картинки в разных
|
|
||||||
"картиночных" командах бота.
|
|
||||||
|
|
||||||
Есть скрипт, который поможет с регистрацией приложения в api Flickr -
|
|
||||||
**bin/flickr_init.pl**, он достанет все нужные ключи и секреты к ним.
|
|
||||||
|
|
||||||
До запуска этого скрипта, бот должен быть забутстраплен через **`bootstrap.sh`**.
|
|
||||||
|
|
||||||
[Залогиньтесь][11] и создайте [app][12] in своём Flicker-овском аккаунте. Далее,
|
|
||||||
*разлогиньтесь*, это нужно, чтобы потом проще было достать параметр verifier.
|
|
||||||
|
|
||||||
Запишите [app key и secret][13] в **config.json**. Удостоверьтесь, что параметр
|
|
||||||
"verifier" в конфиге либо закоменчен, либо отсутствует.
|
|
||||||
|
|
||||||
Запустите **bin/flickr_init.pl** и следуте предлагаемым инструкциям - в итоге
|
|
||||||
будет дана ссылка, которую надо скопипастить в браузер. По ссылке предложат
|
|
||||||
залогиниться, далее надо будет разрешить приложению просматривать профиль и,
|
|
||||||
через один-два редиректа, вы попадёте на example.com. Из адресной строки браузера
|
|
||||||
надо скопировать параметр "verifier" и вписать его в **config.json**.
|
|
||||||
|
|
||||||
Чтобы сохранить в бд плагина API access token для нормальной работы "плагина",
|
|
||||||
второй раз запустите **bin/flickr_init.pl**. На этом всё.
|
|
||||||
|
|
||||||
[1]: https://metacpan.org/pod/Telegram::Bot
|
[1]: https://metacpan.org/pod/Telegram::Bot
|
||||||
[2]: https://metacpan.org/pod/Hailo
|
[2]: https://metacpan.org/pod/Hailo
|
||||||
[3]: https://core.telegram.org/bots/api
|
[3]: https://core.telegram.org/bots/api
|
||||||
[4]: https://core.telegram.org/bots/api#getting-updates
|
[4]: https://core.telegram.org/bots/api#getting-updates
|
||||||
[5]: https://home.openweathermap.org/users/sign_up
|
|
||||||
[6]: https://home.openweathermap.org/users/sign_in
|
|
||||||
[7]: https://home.openweathermap.org/api_keys
|
|
||||||
[8]: https://imgur.com/signin
|
|
||||||
[9]: https://api.imgur.com/oauth2/addclient
|
|
||||||
[10]: https://apidocs.imgur.com/#authorization-and-oauth
|
|
||||||
[11]: https://identity.flickr.com/login
|
|
||||||
[12]: https://www.flickr.com/services/apps/create/apply/
|
|
||||||
[13]: https://www.flickr.com/services/api/keys/
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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 пользователя, который принимает облик канала, на него можно нажать и попасть
|
||||||
# на рекламируемый канал
|
# на рекламируемый канал
|
||||||
@@ -314,60 +310,32 @@ sub __on_msg {
|
|||||||
my $qname = quotemeta ('@' . $myusername);
|
my $qname = quotemeta ('@' . $myusername);
|
||||||
my $qtname = quotemeta $myfullname;
|
my $qtname = quotemeta $myfullname;
|
||||||
|
|
||||||
# phrase directed to bot
|
my $rmsg = clone ($redismsg);
|
||||||
|
$rmsg->{mode} = 'public';
|
||||||
|
$rmsg->{userid} = $userid;
|
||||||
|
$rmsg->{chatid} = $chatid;
|
||||||
|
|
||||||
|
# Сообщение обращено к боту
|
||||||
if ((lc ($text) =~ /^${qname}[\,|\:]? (.+)/) or (lc ($text) =~ /^${qtname}[\,|\:]? (.+)/)){
|
if ((lc ($text) =~ /^${qname}[\,|\:]? (.+)/) or (lc ($text) =~ /^${qtname}[\,|\:]? (.+)/)){
|
||||||
$phrase = $1;
|
$phrase = $1;
|
||||||
|
|
||||||
my $rmsg = clone ($redismsg);
|
|
||||||
$rmsg->{mode} = 'public';
|
|
||||||
$rmsg->{message} = $phrase;
|
$rmsg->{message} = $phrase;
|
||||||
$rmsg->{userid} = $userid;
|
# Бота упомянули по имени
|
||||||
$rmsg->{chatid} = $chatid;
|
|
||||||
my $pubsub = $main::REDIS->pubsub;
|
|
||||||
$pubsub->json ($c->{'redis_router_channel'})->notify (
|
|
||||||
$c->{'redis_router_channel'} => $rmsg
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
# bot mention by name
|
|
||||||
} elsif ((lc ($text) =~ /.+ ${qname}[\,|\!|\?|\.| ]/) or (lc ($text) =~ / $qname$/)) {
|
} elsif ((lc ($text) =~ /.+ ${qname}[\,|\!|\?|\.| ]/) or (lc ($text) =~ / $qname$/)) {
|
||||||
$phrase = $text;
|
$phrase = $text;
|
||||||
|
|
||||||
my $rmsg = clone ($redismsg);
|
|
||||||
$rmsg->{mode} = 'public';
|
|
||||||
$rmsg->{message} = $phrase;
|
$rmsg->{message} = $phrase;
|
||||||
$rmsg->{userid} = $userid;
|
# Бота упомянули по телеграммному имени
|
||||||
$rmsg->{chatid} = $chatid;
|
|
||||||
my $pubsub = $main::REDIS->pubsub;
|
|
||||||
$pubsub->json ($c->{'redis_router_channel'})->notify (
|
|
||||||
$c->{'redis_router_channel'} => $rmsg
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
# 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;
|
||||||
|
|
||||||
my $rmsg = clone ($redismsg);
|
|
||||||
$rmsg->{mode} = 'public';
|
|
||||||
$rmsg->{message} = $phrase;
|
$rmsg->{message} = $phrase;
|
||||||
$rmsg->{userid} = $userid;
|
|
||||||
$rmsg->{chatid} = $chatid;
|
|
||||||
my $pubsub = $main::REDIS->pubsub;
|
|
||||||
$pubsub->json ($c->{'redis_router_channel'})->notify (
|
|
||||||
$c->{'redis_router_channel'} => $rmsg
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
} else {
|
||||||
|
$rmsg->{message} = $text;
|
||||||
|
$rmsg->{misc}->{answer} = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $rmsg = clone ($redismsg);
|
|
||||||
$rmsg->{mode} = 'public';
|
|
||||||
$rmsg->{message} = $text;
|
|
||||||
$rmsg->{userid} = $userid;
|
|
||||||
$rmsg->{chatid} = $chatid;
|
|
||||||
$rmsg->{misc}->{answer} = 0;
|
|
||||||
my $pubsub = $main::REDIS->pubsub;
|
my $pubsub = $main::REDIS->pubsub;
|
||||||
|
|
||||||
$pubsub->json ($c->{'redis_router_channel'})->notify (
|
$pubsub->json ($c->{'redis_router_channel'})->notify (
|
||||||
$c->{'redis_router_channel'} => $rmsg
|
$c->{'redis_router_channel'} => $rmsg
|
||||||
);
|
);
|
||||||
@@ -405,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 = (
|
||||||
'Так, блядь...',
|
'Так, блядь...',
|
||||||
@@ -491,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user