Compare commits

...

35 Commits

Author SHA1 Message Date
eleksir
6a4c2bd076 Add command пословиться 2023-05-19 00:16:14 +03:00
eleksir
2f9b79d77d Add missing semicolon in Teapot/Bot/Object/Chat.pm 2023-04-16 17:06:33 +03:00
eleksir
8eb83ac2b8 Update internal version number of Teapot lib 2023-04-16 17:03:39 +03:00
eleksir
df3c198bce Add general support for BotAPI v6.6 2023-04-16 16:58:59 +03:00
eleksir
f019b98b1f Add partial BotAPI v6.5 support 2023-04-16 16:31:12 +03:00
eleksir
ecf4f94dca Add general support for BotAPI v6.4 2023-04-16 16:03:38 +03:00
eleksir
cea6920d78 Change loglevel for known errors to notice while handling sendMessage errors 2023-01-14 20:52:03 +03:00
eleksir
d4d830715b Add comments fo couple of fields in banChatMember method 2023-01-14 20:50:02 +03:00
eleksir
be5c654045 Rework BotAPI error handling, this time it looks kinda working, still wip, though 2023-01-07 17:19:16 +03:00
eleksir
5edf5a7e0c Fine tune GET polling requests timings, update Teapot lib pod-docs, bump Teapot lib version where missed last time 2023-01-07 16:56:56 +03:00
eleksir
780ec4fe29 Correctly handle successful response from banChatMember and restrictChatMember in BotLib.pm 2023-01-07 16:53:47 +03:00
eleksir
fc56f99433 Try to catch and log as most Bot API errors as we can in BotLib.pm 2023-01-02 21:27:34 +03:00
eleksir
5b93e43280 Only creator can toggle admin mute 2023-01-02 19:54:22 +03:00
eleksir
c5b4d1c866 Try to catch and log as most Bot API errors as we can in TelegramBot.pm 2023-01-02 19:34:38 +03:00
eleksir
5a5e4b5ead 5/5 Fix formatting in TelegramBot.pm 2023-01-02 19:21:19 +03:00
eleksir
e8765c0e88 4/5 Try to handle errors on sending message in RedisLib.pm 2023-01-02 19:20:31 +03:00
eleksir
3dc75936ea 3/5 Allow to enable mute-by-command not only to creator of chat 2023-01-02 19:08:02 +03:00
eleksir
1f3675de8f 2/5 Lift up error to caller in Teapot lib, introduce can_talk() in Brain.pm 2023-01-02 19:06:02 +03:00
eleksir
3668620bd8 1/5 Fix formatting in bin/aleesa-telegram 2023-01-02 19:04:28 +03:00
eleksir
5411d6df7f Fix fetching error message 2022-12-15 02:21:17 +03:00
eleksir
f6a5a05e58 Disable chat in morning greet list if chat id is not found 2022-12-15 02:19:01 +03:00
eleksir
6e084995a7 Use proper functions to check state of services in migration 2022-12-15 02:03:02 +03:00
eleksir
43c08e156f Return only if migration performed 2022-12-12 17:31:18 +03:00
eleksir
b84f8bb245 Move IsCensored to Admin.pm 2022-12-12 17:26:50 +03:00
eleksir
d43cb5995b Add settings migration when group -> supergroup promotion event discovered 2022-12-12 17:10:02 +03:00
eleksir
7d74a86dad In channel context Hightlight() is pointless 2022-12-12 15:19:41 +03:00
eleksir
d539c8c9cf DeeJay utility functions to Util.pm 2022-12-12 13:32:44 +03:00
eleksir
bd9f66930b In _post_request() try to catch error message as raw and return it to upper layer 2022-12-12 12:41:54 +03:00
eleksir
9618369a45 Add debug for api errors 2022-11-26 14:22:11 +03:00
eleksir
770fce4cfe Update dependencies 2022-11-26 14:16:19 +03:00
eleksir
80d9aeca20 Add fuck command 2022-11-26 14:02:52 +03:00
eleksir
548c0b3655 Fix logic in GreetMsgToggle() 2022-11-07 00:57:09 +03:00
eleksir
b4e6685213 Add support for Bot API 6.3 2022-11-06 22:08:02 +03:00
eleksir
f9658ac5e8 Actually add admin mute command 2022-10-09 02:06:54 +03:00
eleksir
3a75f4c947 Rename admin mute command because it actually bans chat prticipants 2022-10-09 00:47:38 +03:00
60 changed files with 1991 additions and 772 deletions

View File

@@ -42,7 +42,6 @@ sub __fork;
sub __signal_handler;
local $OUTPUT_AUTOFLUSH = 1;
my $runAsUid = $UID;
my $piddir = '/var/run/' . basename (abs_path ($PROGRAM_NAME));
my $C = LoadConf ();

View File

@@ -7,7 +7,7 @@ requires 'Cwd', '==3.75';
requires 'Cwd::utf8', '==0.011';
requires 'Data::Dumper', '==2.183';
requires 'Digest::SHA', '==6.02';
requires 'Encode', '==3.16';
requires 'Encode', '==3.19';
requires 'English', '0';
requires 'Exporter', '==5.74';
# part of perl distribution
@@ -15,23 +15,23 @@ requires 'IPC::Open2', '0';
requires 'File::Basename', '==2.85';
requires 'File::Path', '==2.18';
requires 'File::Spec', '==3.75';
requires 'IO::Socket::SSL', '==2.074';
requires 'JSON', '==4.05';
requires 'JSON::PP', '==4.07';
requires 'IO::Socket::SSL', '==2.077';
requires 'JSON', '==4.10';
requires 'JSON::PP', '==4.12';
requires 'JSON::XS', '==4.03';
requires 'List::Util', '==1.60';
requires 'local::lib', '==2.000028';
requires 'Log::Any', '==1.710';
requires 'Log::Any::Adapter', '==1.710';
requires 'local::lib', '==2.000029';
requires 'Log::Any', '==1.711';
requires 'Log::Any::Adapter', '==1.711';
requires 'Log::Any::For::Std', '==0.05';
requires 'Math::Random::Secure', '==0.080001';
requires 'MIME::Base64', '==3.16';
requires 'Mojolicious', '==9.24';
requires 'Mojolicious', '==9.30';
# part of Mojolicious
requires 'Mojo::Base', '0';
# part of Mojolicious
requires 'Mojo::IOLoop', '0';
requires 'Mojo::Redis', '==3.27';
requires 'Mojo::Redis', '==3.29';
# part of Mojo::Redis
requires 'Mojo::Redis::Connection', '0';
# part of Mojolicious
@@ -41,7 +41,7 @@ requires 'open', '0';
# part of perl distribution
requires 'POSIX', '0';
requires 'Text::Fuzzy', '==0.29';
requires 'URI::URL', '==5.10';
requires 'URI::URL', '==5.17';
# part of perl distribution
requires 'utf8', '0';
requires 'version', '==0.9929';

View File

@@ -17,17 +17,19 @@ use BotLib::Conf qw (LoadConf);
use BotLib::Admin qw (@ForbiddenMessageTypes GetForbiddenTypes AddForbiddenType
DelForbiddenType ListForbidden FortuneToggle FortuneStatus
PluginToggle PluginStatus PluginEnabled ChanMsgToggle ChanMsgStatus
GreetMsgToggle GreetMsgStatus GoodbyeMsgToggle GoodbyeMsgStatus);
use BotLib::Util qw (trim);
GreetMsgToggle GreetMsgStatus GoodbyeMsgToggle GoodbyeMsgStatus MuteByAdminToggle
MuteByAdminStatus MuteByAdminEnabled);
use BotLib::Util qw (trim Highlight);
use version; our $VERSION = qw (1.1);
use Exporter qw (import);
our @EXPORT_OK = qw (Command Highlight BotSleep IsCensored);
our @EXPORT_OK = qw (Command);
my $c = LoadConf ();
my $csign = $c->{telegrambot}->{csign};
my $redismsg->{from} = 'telegram';
$redismsg->{threadid} = '';
$redismsg->{plugin} = 'telegram';
$redismsg->{misc}->{answer} = 1;
$redismsg->{misc}->{csign} = "$c->{telegrambot}->{csign}";
@@ -83,9 +85,10 @@ sub Command {
# Полноценный поиск простой команды во входящем сообщении
$#cmds = -1;
@cmds = qw (ping пинг пинх pong понг понх coin монетка roll dice кости ver version версия хэлп halp kde кде lat
лат friday пятница proverb пословица fortune фортунка f ф anek анек анекдот buni cat кис drink праздник fox лис
frog лягушка horse лошадь лошадка monkeyuser owl сова сыч rabbit bunny кролик snail улитка tits boobs tities
boobies сиси сисечки butt booty ass попа попка xkcd dig копать fish fishing рыба рыбка рыбалка karma карма);
лат friday пятница proverb пословица пословиться fortune фортунка f ф anek анек анекдот buni cat кис
drink праздник fox лис frog лягушка horse лошадь лошадка monkeyuser owl сова сыч rabbit bunny кролик
snail улитка tits boobs tities boobies сиси сисечки butt booty ass попа попка xkcd dig копать fish
fishing рыба рыбка рыбалка karma карма fuck);
my $bingo = 0;
@@ -130,6 +133,15 @@ sub Command {
}
}
# Если тип группы supergroup, в ней могут быть треды, попробуем найти message_thread_id, если таковой есть
if ($msg->chat->type eq 'supergroup') {
if ($msg->can ('is_topic_message') && $msg->is_topic_message) {
if ($msg->can ('message_thread_id') && $msg->message_thread_id ne '') {
$rmsg->{threadid} = "$msg->message_thread_id";
}
}
}
# Если соединения с редиской нету, ждём, пока оно появится. Своего рода костыль на всякий случай.
{
do {
@@ -185,18 +197,31 @@ ${csign}karma фраза | ${csign}карма фраза - посмотреть
Но на самом деле я бот больше для общения, чем для исполнения команд.
Поговоришь со мной?
MYHELP
$msg->replyMd ("$reply");
my $res = $msg->replyMd ("$reply");
if ($res->{error}) {
$log->error ('[ERROR] Unable to call sendMessage BotAPI method: ' . Dumper ($res));
}
return;
# Если команда не найдена, но это команда admin
} elsif ($cmd =~ /^(admin|админ)$/u) {
my $member = $self->getChatMember ({ 'chat_id' => 0 + $msg->chat->id, 'user_id' => 0 + $msg->from->id });
# Если команда не найдена, но это команда admin :)
} elsif ($cmd =~ /^(admin|админ)(\s+|\s+.*)?$/u) {
my $send_args->{chat_id} = 0 + $chatid;
$send_args->{user_id} = 0 + $msg->from->id;
my $member = $self->getChatMember ($send_args);
if ($member->{error}) {
$log->error ('[ERROR] Unable to call getChatMember BotAPI method: ' . Dumper ($member));
return;
}
# Это должно показываться только админам чата
if (($member->status eq 'administrator') || ($member->status eq 'creator')) {
if (($member->status ne 'administrator') && ($member->status ne 'creator')) {
$log->debug ("[DEBUG] Non admin member called ${csign}admin command, " . $member->status);
return;
}
if ($cmd =~ /^(admin|админ)\s*$/u) {
$reply = << "MYADMIN";
```
${csign}admin censor type # - где 1 - вкл, 0 - выкл цензуры для означенного типа сообщений
@@ -217,51 +242,78 @@ ${csign}admin obutts # - где 1 - вкл, 0 - выкл плагина o
${csign}admin obutts - показываем ли попки по просьбе участников чата (команды ${csign}ass, ${csign}butt, ${csign}booty, ${csign}попа, ${csign}попка)
${csign}admin chan_msg - оставляем ли сообщения присланные от имени (других) каналов
${csign}admin chan_msg # - где 1 - оставляем, 0 - удаляем
${csign}admin ban userid sec - выдаём ban указанному user-у на указанное количество секунд (от 30 сек до 1 года), доступно только создателю чата
${csign}admin mute userid sec - выдаём mute указанному user-у на указанное количество секунд (от 30 сек до 1 года), доступно только создателю чата
${csign}admin admin mute - разрешено ли обычным админам мьютить участников чата через бота (если бот - админ), (создатель чата всегда может попросить бота-админа замьютить обычного участника чата)
${csign}admin admin mute # - где 1 - разрешено, 0 - не разрешено
```
Типы сообщений:
audio voice photo video animation sticker dice game poll document
MYADMIN
$msg->replyMd ($reply);
my $res = $msg->replyMd ($reply);
if ($res->{error}) {
$log->error('[ERROR] Unable to call sendMessage BotAPI method: ' . Dumper($res));
}
return;
# Если строка не найдена, но это команда admin с параметрами
} elsif ($cmd =~ /^admin\s+.+$/u || $cmd =~ /^админ\s+.+$/u) {
my $member = $self->getChatMember ({ 'chat_id' => 0 + $msg->chat->id, 'user_id' => 0 + $msg->from->id });
} elsif ($cmd =~ /^admin\s+(admin\s+mute)(\s*|\s+0|\s+1)$/gu) {
my $arg;
$arg = trim $2 if (defined $2);
if ($member->{error}) {
return;
if (defined $arg && $arg !~ /^\s*$/ && ($member->status eq 'creator')) {
if ($arg == 1) {
$reply = MuteByAdminToggle ($chatid, 1);
} elsif ($arg == 0) {
$reply = MuteByAdminToggle ($chatid, 0);
}
} else {
$reply = MuteByAdminStatus ($chatid);
}
} elsif ($cmd =~ /^(admin|админ)\s+(ban|mute)\s+(\d+)\s+(\d+)$/gu) {
if ($member->status eq 'admin' && (! MuteByAdminEnabled ($chatid))) {
return 'Не буду я для тебя никого мьтить.';
}
# Мьютить через бота можно только создателю чятика
if (($member->status eq 'creator') && $cmd =~ /^(admin|админ)\s+mute\s+(\d+)\s+(\d+)$/gu) {
my (undef, undef, $user_id_to_mute, $time) = split /\s+/, $cmd;
my (undef, $action, $user_id_to_prosecute, $time) = split /\s+/, $cmd;
# Бот должен быть админом, чтобы мьютить юзеров
# Бот должен быть админом, чтобы банить юзеров
my $me = $self->getMe ();
if ($me->{error}) {
$log->error ('[ERROR] Unable to call getMe BotAPI method: ' . Dumper ($member));
return;
}
my $myId = $me->id;
if ($myId == $user_id_to_mute) {
if ($myId == $user_id_to_prosecute) {
if ($action eq 'mute') {
$reply = 'Я не буду себя мьютить.';
} else {
$me = $self->getChatMember ({'chat_id' => $chatid, 'user_id' => $me->id});
$reply = 'Я не буду себя банить.';
}
} else {
$send_args = undef;
$send_args->{chat_id} = 0 + $chatid;
$send_args->{user_id} = 0 + $me->id;
$me = $self->getChatMember ($send_args);
if ($me->{error}) {
$log->error ('[ERROR] Unable to call getChatMember BotAPI method: ' . Dumper ($me));
return;
}
if ($me->status eq 'administrator') {
# Проверим, что такой юзер есть в чятике
my $chatMember = $self->getChatMember ({'chat_id' => $chatid, 'user_id' => $user_id_to_mute});
$send_args = undef;
$send_args->{chat_id} = 0 + $chatid;
$send_args->{user_id} = 0 + $user_id_to_prosecute;
my $chatMember = $self->getChatMember ($send_args);
if ($chatMember->{error}) {
$log->error ('[ERROR] Unable to call getChatMember BotAPI method: ' . Dumper ($chatMember));
return;
}
@@ -269,27 +321,62 @@ MYADMIN
my $memberStatus = $chatMember->status;
if ($memberStatus eq 'creator') {
if ($action eq 'mute') {
$reply = 'Ты поехал себя мьютить?';
} else {
$reply = 'Ты поехал себя банить?';
}
} elsif ($memberStatus eq 'administrator') {
if ($action eq 'mute') {
$reply = 'Админов мьютить не буду.';
} else {
$reply = 'Админов банить не буду.';
}
} else {
if ($time < 30) {
$reply = 'Ты слишком добр.';
} elsif ($time > (60 * 60 * 24 * 366)) {
if ($action eq 'mute') {
$reply = 'Мьют более чем на 366 дней - перманентный, ты слишком жесток, я так не играю.';
} else {
my $result = $self->banChatMember (
{
'chat_id' => 0 + $chatid,
'user_id' => 0 + $user_id_to_mute,
'until_date' => $time + time (),
},
);
$reply = 'Бан более чем на 366 дней - перманентный, ты слишком жесток, я так не играю.';
}
} else {
my $result;
$send_args = undef;
$send_args->{chat_id} = 0 + $chatid;
$send_args->{user_id} = 0 + $user_id_to_prosecute;
$send_args->{until_date} = $time + time ();
if ($result->{error}) {
if ($action eq 'mute') {
$result = $self->muteChatMember ($send_args);
} else {
$result = $self->banChatMember ($send_args);
}
# Если всё хорошо, то возвращается true в формате JSON::PP::Boolean
if ((ref ($result) eq 'JSON::PP::Boolean') && ($result == JSON::PP::true)) {
$reply = 'Готово.';
} elsif (defined ($result->{error}) && $result->{error}) {
if ($action eq 'mute') {
$log->error (
'[ERROR] Unable to call muteChatMember BotAPI method: ' .
Dumper ($result)
);
$reply = 'Что-то пошло не так, не получается замьютить.';
} else {
$reply = 'Готово.';
$log->error (
'[ERROR] Unable to call banChatMember BotAPI method: ' .
Dumper ($result)
);
$reply = 'Что-то пошло не так, не получается забанить.';
}
} else {
$log->error (
'[ERROR] Unable to call banChatMember/muteChatMember BotAPI method: ' .
Dumper ($result)
);
$reply = 'Что-то пошло совсем не так.';
}
}
}
@@ -297,22 +384,14 @@ MYADMIN
$reply = 'Я так пока не умею, я здесь не админ.'
}
}
} elsif ($cmd =~ /^admin\s+(censor|ценз)\s*$/gu) {
$reply = ListForbidden ($chatid);
} elsif ($cmd =~ /^admin\s+(censor|ценз)\s+(type|тип)\s+(.+)$/gu) {
my $arg;
$arg = trim $3 if (defined $3);
# Это должно показываться только админам чата
} elsif (($member->status eq 'administrator') || ($member->status eq 'creator')) {
# Вынем субкоманду, это первый аргумент команды admin
$cmd =~ /^(admin|админ)\s+(.+)$/u;
my $command = trim ($2); ## no critic (RegularExpressions::ProhibitCaptureWithoutTest)
my ($subcmd, $args) = split /\s+/, $command, 2;
# Субкоманды не нашлось, ну и какбэ досвидонья
if ($subcmd eq '') {
return;
# Субкоманда censor...
} elsif ($subcmd eq 'censor' || $subcmd eq 'ценз') {
# Censor с аргументами
if (defined ($args) && ($args ne '')) {
my ($msgType, $toggle) = split /\s/, $args, 2;
if (defined $arg && $arg ne '') {
my ($msgType, $toggle) = split /\s/, $arg, 2;
if (defined $toggle) {
foreach (@ForbiddenMessageTypes) {
@@ -327,70 +406,80 @@ MYADMIN
}
}
}
# Censor без аргументов, выдаёт список типов сообщений и будут ли они автоматически удаляться
} else {
$reply = ListForbidden ($chatid);
}
# Хотим ли мы показывать фортунку с утра
} elsif ($subcmd eq 'fortune' || $subcmd eq 'фортунка') {
if (defined $args) {
if ($args == 1) {
} elsif ($cmd =~ /^admin\s+(fortune|фортунка)(\s*|\s+0|\s+1)$/gu) {
my $arg;
$arg = trim $2 if (defined $2);
if (defined $arg && $arg !~ /^\s*$/) {
if ($arg == 1) {
$reply = FortuneToggle ($chatid, 1);
} elsif ($args == 0) {
} elsif ($arg == 0) {
$reply = FortuneToggle ($chatid, 0);
}
} else {
$reply = FortuneStatus ($chatid);
}
# Хотим ли мы удалять "сообщения от каналов"
} elsif ($subcmd eq 'chan_msg') {
if (defined $args) {
if ($args == 1) {
} elsif ($cmd =~ /^admin\s+chan_msg(\s*|\s+0|\s+1)$/gu) {
my $arg = $1;
$arg = trim $1 if (defined $1);
if (defined $arg && $arg !~ /^\s*$/) {
if ($arg == 1) {
$reply = ChanMsgToggle ($chatid, 1);
} elsif ($args == 0) {
} elsif ($arg == 0) {
$reply = ChanMsgToggle ($chatid, 0);
}
} else {
$reply = ChanMsgStatus ($chatid);
}
# Приветствуем ли мы новых участников чата
} elsif ($subcmd eq 'greet' || $subcmd eq 'приветствие') {
if (defined $args) {
if ($args == 1) {
} elsif ($cmd =~ /^admin\s+(greet|приветствие)(\s*|\s+0|\s+1)$/gu) {
my $arg = $2;
$arg = trim $2 if (defined $2);
if (defined $arg && $arg !~ /^\s*$/) {
if ($arg == 1) {
$reply = GreetMsgToggle ($chatid, 1);
} elsif ($args == 0) {
} elsif ($arg == 0) {
$reply = GreetMsgToggle ($chatid, 0);
}
} else {
$reply = GreetMsgStatus ($chatid);
}
} elsif ($subcmd eq 'goodbye' || $subcmd eq 'прощание') {
if (defined $args) {
if ($args == 1) {
} elsif ($cmd =~ /^admin\s+(goodbye|прощание)(\s*|\s+0|\s+1)$/gu) {
my $arg = $2;
$arg = trim $2 if (defined $2);
if (defined $arg && $arg !~ /^\s*$/) {
if ($arg == 1) {
$reply = GoodbyeMsgToggle ($chatid, 1);
} elsif ($args == 0) {
} elsif ($arg == 0) {
$reply = GoodbyeMsgToggle ($chatid, 0);
}
} else {
$reply = GoodbyeMsgStatus ($chatid);
}
# Работает ли плагин oboobs в чатике
} elsif ($subcmd eq 'oboobs') {
if (defined $args) {
if ($args == 1) {
} elsif ($cmd =~ /^admin\s+oboobs(\s*|\s+0|\s+1)$/gu) {
my $arg = $1;
$arg = trim $1 if (defined $1);
if (defined $arg) {
if ($arg == 1) {
$reply = PluginToggle ($chatid, 'oboobs', 1);
} elsif ($args == 0) {
} elsif ($arg == 0) {
$reply = PluginToggle ($chatid, 'oboobs', 0);
}
} else {
$reply = PluginStatus ($chatid, 'oboobs');
}
# Работает ли плагин obutts в чатике
} elsif ($subcmd eq 'obutts') {
if (defined $args) {
if ($args == 1) {
} elsif ($cmd =~ /^admin\s+obutts(\s*|\s+0|\s+1)$/gu) {
my $arg = $1;
$arg = trim $1 if (defined $1);
if (defined $arg) {
if ($arg == 1) {
$reply = PluginToggle ($chatid, 'obutts', 1);
} elsif ($args == 0) {
} elsif ($arg == 0) {
$reply = PluginToggle ($chatid, 'obutts', 0);
}
} else {
@@ -398,90 +487,10 @@ MYADMIN
}
}
}
}
return $reply;
}
sub Highlight {
my $msg = shift;
my $fullname;
my $highlight;
my $username;
my $visavi = '';
my $userid = $msg->from->id;
if ($msg->from->can ('username') && defined $msg->from->username ) {
$username = $msg->from->username;
}
if ($msg->from->can ('first_name') && defined $msg->from->first_name) {
$fullname = $msg->from->first_name;
if ($msg->from->can ('last_name') && defined $msg->from->last_name) {
$fullname .= ' ' . $msg->from->last_name;
}
} elsif ($msg->from->can ('last_name') && defined $msg->from->last_name) {
$fullname .= $msg->from->last_name;
}
if (defined $username) {
$visavi .= '@' . $username;
if (defined $fullname) {
$highlight = "[$fullname](tg://user?id=$userid)";
$visavi .= ', ' . $fullname;
} else {
$highlight = "[$username](tg://user?id=$userid)";
}
} else {
$highlight = "[$fullname](tg://user?id=$userid)";
$visavi .= $fullname;
}
$visavi .= " ($userid)";
return ($userid, $username, $fullname, $highlight, $visavi);
}
sub BotSleep {
# TODO: Parametrise this with fuzzy sleep time in seconds
my $msg = shift;
# let's emulate real human and delay answer
sleep (irand (2) + 1);
for (0..(4 + irand (3))) {
$msg->typing ();
sleep 3;
sleep 3 unless ($_);
}
sleep ( 3 + irand (2));
return;
}
sub IsCensored {
my $msg = shift;
my $forbidden = GetForbiddenTypes ($msg->chat->id);
# voice messages are special
if (defined ($msg->voice) && defined ($msg->voice->duration) && ($msg->voice->duration > 0)) {
if ($forbidden->{'voice'}) {
return 1;
}
}
foreach (keys %{$forbidden}) {
if ($forbidden->{$_} && (defined $msg->{$_})) {
return 1;
}
}
return 0;
}
1;
# vim: set ft=perl noet ai ts=4 sw=4 sts=4:

View File

@@ -18,7 +18,8 @@ our @ISA = qw / Exporter /; ## no critic (ClassHierarchies::ProhibitExplicitI
our @EXPORT_OK = qw (@ForbiddenMessageTypes @PluginList GetForbiddenTypes AddForbiddenType DelForbiddenType
ListForbidden FortuneToggle FortuneToggleList FortuneStatus PluginToggle PluginStatus
PluginEnabled ChanMsgToggle ChanMsgStatus ChanMsgEnabled GreetMsgToggle GreetMsgStatus
GreetMsgEnabled GoodbyeMsgToggle GoodbyeMsgStatus GoodbyeMsgEnabled);
GreetMsgEnabled GoodbyeMsgToggle GoodbyeMsgStatus GoodbyeMsgEnabled MuteByAdminToggle
MuteByAdminStatus MuteByAdminEnabled MigrateSettingsToNewChatID IsCensored);
my $c = LoadConf ();
my $cachedir = $c->{cachedir};
@@ -108,6 +109,29 @@ sub ListForbidden {
return join "\n", @list;
}
sub EnabledForbidden {
my $chatid = shift;
my $ftype = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'censor' . '_' . utf2sha1 ($chatid),
);
my $type = $cache->get ($ftype);
if ($type) {
return 1;
} else {
unless (defined $type) {
$cache->set ($ftype, 0, 'never');
}
return 0;
}
}
sub FortuneToggle (@) {
my $chatid = shift;
my $action = shift // undef;
@@ -166,6 +190,24 @@ sub FortuneStatus ($) {
return $phrase;
}
sub FortuneEnabled ($) {
my $chatid = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'fortune',
);
my $state = $cache->get ($chatid);
if (defined $state && $state) {
return 1;
} else {
return 0;
}
}
sub FortuneToggleList () {
my $cache = CHI->new (
driver => 'BerkeleyDB',
@@ -288,33 +330,28 @@ sub GreetMsgToggle (@) {
namespace => __PACKAGE__ . '_' . 'greet_msg',
);
if (defined $action) {
if ($action == 0) {
$cache->set ($chatid, 0, 'never');
$phrase .= 'выключены.';
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'включены.';
}
} else {
my $state = $cache->get ($chatid);
if (defined $action) {
if ($action) {
$cache->set ($chatid, 1, 'never');
$phrase .= 'включено.';
} else {
if (defined $state && $state) {
if (defined $state) {
if ($state != 0) {
$cache->set ($chatid, 0, 'never');
$phrase .= 'выключено.';
$phrase .= 'выключены.';
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'включено.';
}
}
} else {
if (defined $state){
if ($state) {
$cache->set ($chatid, 0, 'never');
$phrase .= 'выключено.';
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'включено.';
$phrase .= 'включены.';
}
} else {
$cache->set ($chatid, 0, 'never');
$phrase .= 'выключено.';
$phrase .= 'выключены.';
}
}
@@ -539,6 +576,162 @@ sub PluginToggle (@) {
return $phrase;
}
sub MuteByAdminToggle (@) {
my $chatid = shift;
my $action = shift // undef;
my $phrase = 'Мьют участников чата админами ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'admin_mute',
);
my $state = $cache->get ($chatid);
if (defined $action) {
if ($action) {
$cache->set ($chatid, 1, 'never');
$phrase .= 'разрешён.';
} else {
$cache->set ($chatid, 0, 'never');
$phrase .= 'запрещён.';
}
} else {
if (defined $state){
if ($state) {
$cache->set ($chatid, 0, 'never');
$phrase .= 'запрещён.';
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'разрешён.';
}
} else {
$cache->set ($chatid, 1, 'never');
$phrase .= 'разрешён.';
}
}
return $phrase;
}
sub MuteByAdminStatus ($) {
my $chatid = shift;
my $phrase = 'Мьют админами участников чата ';
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'admin_mute',
);
my $state = $cache->get ($chatid);
if (defined $state) {
if ($state) {
$phrase .= 'разрешён.';
} else {
$phrase .= 'запрещён.';
}
} else {
$phrase .= 'запрещён.';
}
return $phrase;
}
sub MuteByAdminEnabled ($) {
my $chatid = shift;
my $cache = CHI->new (
driver => 'BerkeleyDB',
root_dir => $cachedir,
namespace => __PACKAGE__ . '_' . 'admin_mute',
);
my $state = $cache->get ($chatid);
if (defined $state) {
if ($state) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
sub MigrateSettingsToNewChatID {
my $old_id = shift;
my $new_id = shift;
# TODO: Catch errors, if error==1, than noop
if (FortuneEnabled ($old_id)) {
FortuneToggle ($new_id, 1);
FortuneToggle ($old_id, 0);
} else {
FortuneToggle ($new_id, 0);
}
if (ChanMsgEnabled ($old_id)) {
ChanMsgToggle ($new_id, 1);
} else {
ChanMsgToggle ($new_id, 0);
}
if (GreetMsgEnabled ($old_id)) {
GreetMsgToggle ($new_id, 1);
} else {
GreetMsgToggle ($new_id, 0);
}
if (GoodbyeMsgEnabled ($old_id)) {
GoodbyeMsgToggle ($new_id, 1);
} else {
GoodbyeMsgToggle ($new_id, 0);
}
foreach my $plugin (@PluginList) {
if (PluginEnabled ($old_id, $plugin)) {
PluginToggle ($new_id, $plugin, 1);
} else {
PluginToggle ($new_id, $plugin, 0);
}
}
foreach my $ftype (@ForbiddenMessageTypes) {
if (EnabledForbidden($old_id, $ftype)) {
AddForbiddenType($new_id, $ftype);
}
# Looks like we don't need to add forbidden type for allowed types... right?
}
return;
}
sub IsCensored {
my $msg = shift;
my $forbidden = GetForbiddenTypes ($msg->chat->id);
# voice messages are special
if (defined ($msg->voice) && defined ($msg->voice->duration) && ($msg->voice->duration > 0)) {
if ($forbidden->{'voice'}) {
return 1;
}
}
foreach (keys %{$forbidden}) {
if ($forbidden->{$_} && (defined $msg->{$_})) {
return 1;
}
}
return 0;
}
1;
# vim: set ft=perl noet ai ts=4 sw=4 sts=4:

View File

@@ -8,13 +8,14 @@ use open qw (:std :utf8);
use English qw ( -no_match_vars );
use Digest::SHA qw (sha1_base64);
use Encode qw (encode_utf8);
use Math::Random::Secure qw (irand);
use MIME::Base64 qw (encode_base64);
use Text::Fuzzy qw (distance_edits);
use URI::URL qw (url);
use version; our $VERSION = qw (1.0);
use Exporter qw (import);
our @EXPORT_OK = qw (trim urlencode fmatch utf2b64 utf2sha1);
our @EXPORT_OK = qw (trim urlencode fmatch utf2b64 utf2sha1 BotSleep Highlight RandomCommonPhrase);
sub trim {
my $str = shift;
@@ -72,6 +73,91 @@ sub utf2sha1 {
return sha1_base64 $bytes;
}
sub Highlight {
my $msg = shift;
my $fullname;
my $highlight;
my $username;
my $visavi = '';
my $userid;
# In channel message $msg->from->id is omitted
# In channel context Highlight is pointless
if ($msg->chat->type eq 'channel') {
return ($userid, $username, $fullname, $highlight, undef);
}
$userid = $msg->from->id;
if ($msg->from->can ('username') && defined $msg->from->username ) {
$username = $msg->from->username;
}
if ($msg->from->can ('first_name') && defined $msg->from->first_name) {
$fullname = $msg->from->first_name;
if ($msg->from->can ('last_name') && defined $msg->from->last_name) {
$fullname .= ' ' . $msg->from->last_name;
}
} elsif ($msg->from->can ('last_name') && defined $msg->from->last_name) {
$fullname .= $msg->from->last_name;
}
if (defined $username) {
$visavi .= '@' . $username;
if (defined $fullname) {
$highlight = "[$fullname](tg://user?id=$userid)";
$visavi .= ', ' . $fullname;
} else {
$highlight = "[$username](tg://user?id=$userid)";
}
} else {
$highlight = "[$fullname](tg://user?id=$userid)";
$visavi .= $fullname;
}
$visavi .= " ($userid)";
return ($userid, $username, $fullname, $highlight, $visavi);
}
sub RandomCommonPhrase {
my @myphrase = (
'Так, блядь...',
'*Закатывает рукава* И ради этого ты меня позвал?',
'Ну чего ты начинаешь, нормально же общались',
'Повтори свой вопрос, не поняла',
'Выйди и зайди нормально',
'Я подумаю',
'Даже не знаю, что на это ответить',
'Ты упал такие вопросы девочке задавать?',
'Можно и так, но не уверена',
'А как ты думаешь?',
'А ви, таки, почему интересуетесь?',
);
return $myphrase[irand ($#myphrase + 1)];
}
sub BotSleep {
# TODO: Parametrise this with fuzzy sleep time in seconds
my $msg = shift;
# let's emulate real human and delay answer
sleep (irand (2) + 1);
for (0..(4 + irand (3))) {
$msg->typing ();
sleep 3;
sleep 3 unless ($_);
}
sleep ( 3 + irand (2));
return;
}
1;
# vim: set ft=perl noet ai ts=4 sw=4 sts=4:

View File

@@ -4,15 +4,17 @@ use 5.018; ## no critic (ProhibitImplicitImport)
use strict;
use warnings;
use utf8;
use English qw ( -no_match_vars );
use open qw (:std :utf8);
use Data::Dumper qw (Dumper);
use JSON::XS qw (decode_json);
use Log::Any qw ($log);
use Mojo::Redis ();
use Mojo::Redis::Connection ();
use BotLib::Admin qw (MigrateSettingsToNewChatID FortuneToggle);
use BotLib::Conf qw (LoadConf);
use Teapot::Bot::Object::ChatPermissions ();
use version; our $VERSION = qw (1.0);
use Exporter qw (import);
@@ -41,25 +43,76 @@ sub redis_parse_message {
$message->{chat_id} = eval { 0 + $m->{chatid}; };
unless (defined $message->{chat_id}) {
$log->error ('Incoming redis message is incorrect: chat id must be numeric value!');
$log->error ('[ERROR] Incoming redis message is incorrect: chat id must be numeric value!');
return;
}
if ($message->{chat_id} == 0) {
$log->error ('Incoming redis message is incorrect: chat id must not be equal 0!');
$log->error ('[ERROR] Incoming redis message is incorrect: chat id must not be equal 0!');
return;
}
$message->{text} = "$m->{message}";
my $can_talk = Teapot::Bot::Object::ChatPermissions->canTalk ($main::TGM, 0 + $m->{chatid});
if (defined ($m->{threadid}) && $m->{threadid} ne '') {
$message->{message_thread_id} = 0 + $m->{threadid};
}
if ($can_talk) {
# Результат этого действия нас не сильно волнует, т.к. если будет ошибка, то в лог попадёт трейс
# we cannot use $self->_brain->can_talk here because of $self pointing to redis object, not telegram
my $can_talk = $main::TGM->can_talk ({ chat_id => 0 + $m->{chatid}});
if ($can_talk->{error}) {
$log->error ('[ERROR] Unable to guess if i can talk in this chat: ' . Dumper ($can_talk));
return;
}
if ($can_talk->{can_talk}) {
my $r = $main::TGM->sendMessage ($message);
if ($r->{error}) {
$log->error ("An error occured while sending message to chat $m->{chatid}");
# TODO: handle 50x errors? They occur when api servers being updated.
$log->error ('[ERROR] Unable to call sendMessage() BotAPI method: ' . Dumper ($r));
my $resp = eval { $r->{debug}->json };
if (defined $resp) {
if (defined ($resp->{error_code}) && $resp->{error_code} == 400) {
if (defined $resp->{description}) {
if ($resp->{description} eq 'Bad Request: have no rights to send a message') {
$log->notice ("[NOTICE] Have no rights to send message to $m->{chatid}");
# TODO: disable fortune if message is good morning fortune
} elsif ($resp->{description} eq 'Bad Request: chat not found') {
$log->notice (
"[NOTICE] Chat not found toggling good morning fortune off for $m->{chatid}"
);
FortuneToggle($m->{chatid}, 0);
return;
} elsif ($resp->description eq 'Bad Request: group chat was upgraded to a supergroup chat') {
if (defined ($resp->{parameters}) &&
defined ($resp->{parameters}->{migrate_to_chat_id})) {
my $tpl = '[NOTICE] group upgraded to supergroup, chat_id changed, ';
$tpl .= 'migrating settings from %s to %s';
$log->notice (
sprintf($tpl, $m->{chatid}, $resp->{parameters}->{migrate_to_chat_id})
);
MigrateSettingsToNewChatID (
$m->{chatid},
$resp->{parameters}->{migrate_to_chat_id}
);
}
} else {
$log->error ('[ERROR] Unable to call sendMessage() BotAPI method: ' . Dumper ($r));
}
} else {
$log->error ('[ERROR] BotAPI returns parsable error: ' . Dumper ($resp));
}
} else {
$log->error ('[ERROR] Unable to handle BotAPI error: ' . Dumper ($resp));
}
}
}
}

View File

@@ -4,7 +4,7 @@ use strict;
use warnings;
use 5.018; ## no critic (ProhibitImplicitImport)
use utf8;
$Teapot::Bot::VERSION = '0.023';
$Teapot::Bot::VERSION = '0.026';
# ABSTRACT: A base class to make your very own Telegram bot
1;
@@ -25,7 +25,7 @@ A base class to make your very own Telegram bot
=head1 VERSION
version 0.023
version 0.026
=head1 SYNOPSIS

File diff suppressed because it is too large Load Diff

View File

@@ -9,14 +9,14 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::PhotoSize ();
$Teapot::Bot::Object::Animation::VERSION = '0.023';
$Teapot::Bot::Object::Animation::VERSION = '0.026';
has 'file_id';
has 'file_unique_id';
has 'width';
has 'height';
has 'duration';
has 'thumb'; #PhotoSize
has 'thumbnail'; #PhotoSize
has 'file_name';
has 'mime_type';
has 'file_size';
@@ -24,7 +24,7 @@ has 'file_size';
sub fields {
return { scalar => [qw/file_id file_unique_id width height duration file_name mime_type
file_size/],
'Teapot::Bot::Object::PhotoSize' => [qw/thumb/],
'Teapot::Bot::Object::PhotoSize' => [qw/thumbnail/],
};
}
@@ -43,7 +43,7 @@ Teapot::Bot::Object::Animation - The base class for Telegram message 'Animation'
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'Animation' type.

View File

@@ -7,8 +7,8 @@ use 5.018; ## no critic (ProhibitImplicitImport)
use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::Audio::VERSION = '0.023';
use Teapot::Bot::Object::PhotoSize ();
$Teapot::Bot::Object::Audio::VERSION = '0.026';
has 'file_id';
has 'file_unique_id';
@@ -18,12 +18,12 @@ has 'title'; # Optional. Title of the audio as defined by sender or by audio
has 'file_name'; # Optional. Original filename as defined by sender
has 'mime_type'; # Optional. MIME type of the file as defined by sender
has 'file_size'; # Optional. File size
has 'thumb'; # Optional. Thumbnail of the album cover to which the music file belongs
has 'thumbnail'; # Optional. Thumbnail of the album cover to which the music file belongs
sub fields {
return { scalar => [qw/file_id file_unique_id duration performer title file_name mime_type
file_size/],
'Teapot::Bot::Object::PhotoSize' => [qw/thumb/],
'Teapot::Bot::Object::PhotoSize' => [qw/thumbnail/],
};
}
@@ -41,7 +41,7 @@ Teapot::Bot::Object::Audio - The base class for Telegram 'Audio' type objects
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'Audio' type objects.

View File

@@ -13,7 +13,7 @@ use List::Util qw/any/;
use Mojo::Base -base;
$Teapot::Bot::Object::Base::VERSION = '0.023';
$Teapot::Bot::Object::Base::VERSION = '0.026';
has '_brain'; # a reference to our brain
@@ -187,7 +187,7 @@ Teapot::Bot::Object::Base - The base class for all Telegram::Bot::Object objects
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION

View File

@@ -7,7 +7,7 @@ use 5.018; ## no critic (ProhibitImplicitImport)
use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::CallbackGame::VERSION = '0.023';
$Teapot::Bot::Object::CallbackGame::VERSION = '0.026';
# https://core.telegram.org/bots/api#callbackgame
# "A placeholder, currently holds no information. Use BotFather to set up your game"
@@ -30,7 +30,7 @@ Teapot::Bot::Object::CallbackGame - The base class for Telegram message 'Callbac
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'CallbackGame' type.

View File

@@ -12,7 +12,7 @@ use Teapot::Bot::Object::Message ();
use Teapot::Bot::Object::ChatPermissions ();
use Teapot::Bot::Object::ChatLocation ();
$Teapot::Bot::Object::Chat::VERSION = '0.023';
$Teapot::Bot::Object::Chat::VERSION = '0.026';
has 'id';
has 'type';
@@ -20,11 +20,23 @@ has 'title'; # Optional.
has 'username'; # Optional.
has 'first_name'; # Optional.
has 'last_name'; # Optional.
has 'is_forum'; # Optional. True, if the supergroup chat is a forum (has topics enabled)
has 'photo'; # Teapot::Bot::Object::ChatPhoto. Optional. Returned only in getChat.
has 'active_usernames'; # Optional. If non-empty, the list of all active chat usernames; for private chats,
# supergroups and channels. Returned only in getChat.
has 'emoji_status_custom_emoji_id'; # Optional. Custom emoji identifier of emoji status of the other party in a private
# chat. Returned only in getChat.
has 'bio'; # Optional. Bio of the other party in a private chat. Returned only in getChat.
has 'has_private_forwards'; # Optional. True, if privacy settings of the other party in the private chat allows to
# use tg://user?id=<user_id> links only in chats with the user.
# Returned only in getChat.
has 'has_restricted_voice_and_video_messages'; # Optional. True, if the privacy settings of the other party restrict
# sending voice and video note messages in the private chat.
# Returned only in getChat.
has 'join_to_send_messages'; # Optional. True, if users need to join the supergroup before they can send messages.
# Returned only in getChat.
has 'join_by_request'; # Optional. True, if all users directly joining the supergroup need to be approved by
# supergroup administrators. Returned only in getChat.
has 'description'; # Optional. Returned only in getChat.
has 'invite_link'; # Optional. Returned only in getChat.
has 'pinned_message'; # Teapot::Bot::Object::Message
@@ -33,6 +45,10 @@ has 'permissions'; # Teapot::Bot::Object::ChatPermissions. Optional
has 'slow_mode_delay'; # Optional. Returned only in getChat.
has 'message_auto_delete_time'; # Optional. The time after which all messages sent to the chat will be automatically
# deleted; in seconds. Returned only in getChat.
has 'has_aggressive_anti_spam_enabled'; # Optional. True, if aggressive anti-spam checks are enabled in the supergroup.
# The field is only available to chat administrators. Returned only in getChat.
has 'has_hidden_members'; # Optional. True, if non-administrators can only get the list of bots and administrators
# in the chat. Returned only in getChat.
has 'has_protected_content'; # Optional. True, if messages from the chat can't be forwarded to other chats.
# Returned only in getChat.
has 'sticker_set_name'; # Optional. Returned only in getChat.
@@ -42,10 +58,14 @@ has 'location'; # Optional. Returned only in getChat.
sub fields {
return {
'scalar' => [qw/id type title username first_name last_name bio
has_private_forwards description invite_link slow_mode_delay
message_auto_delete_time has_protected_content
sticker_set_name can_set_sticker_set linked_chat_id/],
'scalar' => [qw/id type title username first_name last_name is_forum
emoji_status_custom_emoji_id bio
has_private_forwards has_restricted_voice_and_video_messages
join_to_send_messages join_by_request description invite_link
slow_mode_delay message_auto_delete_time
has_aggressive_anti_spam_enabled has_hidden_members
has_protected_content sticker_set_name can_set_sticker_set
linked_chat_id/],
'Teapot::Bot::Object::ChatPhoto' => [qw/photo/],
'Teapot::Bot::Object::Message' => [qw/pinned_message/],
'Teapot::Bot::Object::ChatPermissions' => [qw/permissions/],
@@ -53,6 +73,9 @@ sub fields {
};
}
sub arrays {
return qw/active_usernames/;
}
sub is_user {
return shift->id > 0;
@@ -77,7 +100,7 @@ Teapot::Bot::Object::Chat - The base class for Telegram 'Chat' type objects
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'Chat' type objects.

View File

@@ -9,7 +9,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::User ();
$Teapot::Bot::Object::ChatInviteLink::VERSION = '0.023';
$Teapot::Bot::Object::ChatInviteLink::VERSION = '0.026';
has 'invite_link';
has 'creator';
@@ -44,7 +44,7 @@ Teapot::Bot::Object::ChatInviteLink - The base class for Telegram message 'ChatI
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'ChatInviteLink' type.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::ChatLocation::VERSION = '0.023';
$Teapot::Bot::Object::ChatLocation::VERSION = '0.026';
has 'location';
has 'address';
@@ -34,7 +34,7 @@ Teapot::Bot::Object::ChatLocation - The base class for Telegram message 'ChatLoc
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'ChatLocation' type.

View File

@@ -12,7 +12,7 @@ use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::User ();
$Teapot::Bot::Object::ChatMember::VERSION = '0.023';
$Teapot::Bot::Object::ChatMember::VERSION = '0.026';
# ChatMemberOwner
has 'user';
@@ -39,7 +39,8 @@ has 'can_promote_members'; # optional. Administrators only.
has 'can_change_info'; # optional. Administrators and restricted only.
has 'can_invite_users'; # optional. Administrators and restricted only.
has 'can_pin_messages'; # optional. Administrators and restricted only.
has 'can_manage_topics'; # Optional. True, if the user is allowed to create, rename, close, and reopen forum
# topics; supergroups only
# ChatMemberMember
# has 'status';
# has 'user';
@@ -52,11 +53,17 @@ has 'is_member'; # optional. Restricted only.
# has 'can_invite_users'; # optional. Administrators and restricted only.
# has 'can_pin_messages'; # optional. Administrators and restricted only.
has 'can_send_messages'; # optional. Restricted only.
has 'can_send_media_messages'; # optional. Restricted only.
has 'can_send_audios';
has 'can_send_documents';
has 'can_send_photos';
has 'can_send_videos';
has 'can_send_video_notes';
has 'can_send_voice_notes';
has 'can_send_polls'; # optional. Restricted only.
has 'can_send_other_messages'; # optional. Restricted only.
has 'can_add_web_page_previews'; # optional. Restricted only.
has 'until_date'; # optional. Restricted and kicked only.
# has 'can_manage_topics';
# ChatMemberLeft
# has 'status';
@@ -69,11 +76,14 @@ has 'until_date'; # optional. Restricted and kicked only.
sub fields {
return {
'scalar' => [qw/status custom_title is_anonymous can_be_edited can_manage_chat can_post_messages
can_edit_messages can_delete_messages can_manage_voice_chats can_restrict_members
can_promote_members can_change_info can_invite_users can_pin_messages is_member
can_send_messages can_send_media_messages can_send_polls can_send_other_messages
can_add_web_page_previews until_date/],
'scalar' => [qw/status custom_title is_anonymous can_be_edited can_manage_chat
can_post_messages can_edit_messages can_delete_messages
can_manage_voice_chats can_restrict_members can_promote_members
can_change_info can_invite_users can_pin_messages is_member
can_send_messages can_send_audios can_send_documents can_send_photos
can_send_videos can_send_video_notes can_send_voice_notes can_send_polls
can_send_other_messagescan_add_web_page_previews until_date
can_manage_topics/],
'Teapot::Bot::Object::User' => [qw/user/],
};
}
@@ -145,7 +155,7 @@ Teapot::Bot::Object::ChatMember - The base class for Telegram 'ChatMember' type
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'ChatMember' type objects.

View File

@@ -13,7 +13,7 @@ use Teapot::Bot::Object::ChatMember ();
use Teapot::Bot::Object::ChatInviteLink ();
use Teapot::Bot::Object::Voice ();
$Teapot::Bot::Object::ChatMemberUpdated::VERSION = '0.023';
$Teapot::Bot::Object::ChatMemberUpdated::VERSION = '0.026';
has 'chat';
has 'from';
@@ -50,7 +50,7 @@ Teapot::Bot::Object::ChatMemberUpdated - The base class for Telegram 'ChatMember
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'ChatMemberUpdated' type objects.

View File

@@ -10,13 +10,17 @@ use Carp qw(carp);
use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Brain ();
$Teapot::Bot::Object::ChatPermissions::VERSION = '0.023';
$Teapot::Bot::Object::ChatPermissions::VERSION = '0.026';
# all fields are optional
# N.B. Some of the fields "overlaps" other, so in order to guess valid set of permissions you should check all of them
has 'can_send_messages'; # True, if the user is allowed to send text messages, contacts, locations and venues
has 'can_send_media_messages'; # True, if the user is allowed to send audios, documents, photos, videos, video notes
# and voice notes, implies can_send_messages
has 'can_send_audios'; # True, if the user is allowed to send audios
has 'can_send_documents'; # True, if the user is allowed to send documents
has 'can_send_photos'; # True, if the user is allowed to send photos
has 'can_send_videos'; # True, if the user is allowed to send videos
has 'can_send_video_notes'; # True, if the user is allowed to send video_notes
has 'can_send_voice_notes'; # True, if the user is allowed to send voice_notes
has 'can_send_polls'; # True, if the user is allowed to send polls, implies can_send_messages
has 'can_send_other_messages'; # True, if the user is allowed to send animations, games, stickers and use inline bots,
# implies can_send_media_messages
@@ -26,21 +30,52 @@ has 'can_change_info'; # True, if the user is allowed to change the ch
# Ignored in public supergroups
has 'can_invite_users'; # True, if the user is allowed to invite new users to the chat
has 'can_pin_messages'; # True, if the user is allowed to pin messages. Ignored in public supergroups
has 'can_manage_topics'; # Optional. True, if the user is allowed to create forum topics. If omitted defaults to
# the value of can_pin_messages
sub fields {
return {
'scalar' => [qw/can_send_messages can_send_media_messages can_send_polls
can_send_other_messages can_add_web_page_previews can_change_info
can_invite_users can_pin_messages/],
'scalar' => [qw/can_send_messages can_send_audios can_send_documents
can_send_photos can_send_videos can_send_video_notes
can_send_voice_notes can_send_polls can_send_other_messages
can_add_web_page_previews can_change_info can_invite_users
can_pin_messages can_manage_topics/],
};
}
sub canTalk {
my $self = shift;
my $self;
my $args = {};
# There is some magic happen if we call function as object, as we usually do here
# But if we access function from usual-style wrapper that calls it directly from namespace it supply noy $self object
# but string with its name, which is a bummer.
while (my $o = shift @_) {
if (ref ($o) ne '') {
$self = $o;
last;
}
}
my $chatid = shift;
my $args->{chat_id} = $chatid;
$args->{chat_id} = $chatid;
my $can_talk = 0;
my $ret;
if (! defined($self->token) || $self->token eq '') {
$ret->{error} = 1;
$ret->{message} = 'No token supplied to canTalk()';
return $ret;
}
unless ($args->{chat_id}) {
$ret->{error} = 1;
$ret->{message} = 'No chat_id supplied to canTalk()';
return $ret;
}
if ($chatid < 0) {
# group chat
@@ -48,16 +83,23 @@ sub canTalk {
# on api error, keep silence
if ($chatobj == 0 || $chatobj->{error}) {
carp "Unable to get chat info for $chatid from telegram API";
return $can_talk;
my $emesg = "Unable to get chat info for $chatid from telegram API";
$ret->{message} = $emesg;
$ret->{error} = 1;
$ret->{can_talk} = 0;
return $ret;
}
my $myObj = Teapot::Bot::Brain->getMe ($self);
# on api error, keep silence
if ($myObj == 0 || $myObj->{error}) {
carp "Unable to get chat info for $chatid from telegram API";
return $can_talk;
my $emesg = "Unable to get chat info for $chatid from telegram API";
$ret->{message} = $emesg;
$ret->{error} = 1;
$ret->{can_talk} = 0;
return $ret;
}
my $myid = $myObj->id;
@@ -66,8 +108,12 @@ sub canTalk {
# on api error, keep silence
if ($me == 0 || $me->{error}) {
carp 'Unable to get chat info for bot itself from telegram API';
return $can_talk;
my $emesg = 'Unable to get chat info for bot itself from telegram API';
$ret->{message} = $emesg;
$ret->{error} = 1;
$ret->{can_talk} = 0;
return $ret;
}
if ($me->{'status'} eq 'administrator') {
@@ -81,9 +127,13 @@ sub canTalk {
$can_talk = 1;
}
return $can_talk;
$ret->{error} = 0;
$ret->{can_talk} = $can_talk;
return $ret;
}
1;
__END__
@@ -98,7 +148,7 @@ Teapot::Bot::Object::ChatPermissions - The base class for Telegram 'ChatPermissi
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'ChatPermissions' type objects.
@@ -112,7 +162,9 @@ attributes available for C<Teapot::Bot::Object::ChatPermissions> objects.
A convenience method to check if bot can talk in given conversation.
Returns true if the bot can talk in given conversation, otherwise false.
Returns hash reference with can_talk true if the bot can talk in given conversation, otherwise false.
Also set field error 1 if an error occurs during api interaction.
And if error set to true message field also set plus can_talk set to false.
=head1 AUTHOR

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::ChatPhoto::VERSION = '0.023';
$Teapot::Bot::Object::ChatPhoto::VERSION = '0.026';
has 'small_file_id';
has 'small_file_unique_id';
@@ -35,7 +35,7 @@ Teapot::Bot::Object::ChatPhoto - The base class for Telegram 'ChatPhoto' type ob
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'ChatPhoto' type objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::Contact::VERSION = '0.023';
$Teapot::Bot::Object::Contact::VERSION = '0.026';
has 'phone_number';
has 'first_name';
@@ -36,7 +36,7 @@ Teapot::Bot::Object::Contact - The base class for Telegram 'Contact' objects
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'Contact' objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::Dice::VERSION = '0.023';
$Teapot::Bot::Object::Dice::VERSION = '0.026';
has 'emoji';
has 'value';
@@ -31,7 +31,7 @@ Teapot::Bot::Object::Dice - The base class for Telegram message 'Dice' type
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'Dice' type.

View File

@@ -9,11 +9,11 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::PhotoSize ();
$Teapot::Bot::Object::Document::VERSION = '0.023';
$Teapot::Bot::Object::Document::VERSION = '0.026';
has 'file_id';
has 'file_unique_id';
has 'thumb'; #PhotoSize
has 'thumbnail'; #PhotoSize
has 'file_name';
has 'mime_type';
has 'file_size';
@@ -21,7 +21,7 @@ has 'file_size';
sub fields {
return {
scalar => [qw/file_id file_unique_id file_name mime_type file_size/],
'Teapot::Bot::Object::PhotoSize' => [qw/thumb/],
'Teapot::Bot::Object::PhotoSize' => [qw/thumbnail/],
};
}
@@ -39,7 +39,7 @@ Teapot::Bot::Object::Document - The base class for Telegram 'Document' objects
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'Document' objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::EncryptedCredentials::VERSION = '0.023';
$Teapot::Bot::Object::EncryptedCredentials::VERSION = '0.026';
has 'data';
has 'hash';
@@ -32,7 +32,7 @@ Teapot::Bot::Object::EncryptedCredentials - The base class for Telegram 'Encrypt
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'EncryptedCredentials' type objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::EncryptedPassportElement::VERSION = '0.023';
$Teapot::Bot::Object::EncryptedPassportElement::VERSION = '0.026';
# XXX Implement rest of this
# https://core.telegram.org/bots/api#encryptedpassportelement
@@ -38,7 +38,7 @@ Teapot::Bot::Object::EncryptedPassportElement - The base class for Telegram 'Enc
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'EncryptedPassportElement' type objects.

View File

@@ -0,0 +1,51 @@
package Teapot::Bot::Object::ForumTopicClosed;
# ABSTRACT: The base class for Telegram message 'ForumTopicClosed' type.
use strict;
use warnings;
use 5.018; ## no critic (ProhibitImplicitImport)
use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::ForumTopicClosed::VERSION = '0.026';
sub fields {
return { };
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
Teapot::Bot::Object::ForumTopicClosed - The base class for Telegram message 'ForumTopicClosed' type
=head1 VERSION
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'ForumTopicClosed' type.
See L<https://core.telegram.org/bots/api#forumtopicclosed> for details of the
attributes available for C<Teapot::Bot::Object::ForumTopicClosed> objects.
=head1 AUTHOR
Sergei Fedosov <eleksir@gmail.com>
=head1 LICENSE AND COPYRIGHT
This software is copyright (c) 2022 by Sergei Fedosov <eleksir@gmail.com>.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,54 @@
package Teapot::Bot::Object::ForumTopicCreated;
# ABSTRACT: The base class for Telegram message 'ForumTopicCreated' type.
use strict;
use warnings;
use 5.018; ## no critic (ProhibitImplicitImport)
use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::ForumTopicCreated::VERSION = '0.026';
has 'name';
has 'icon_color';
has 'icon_custom_emoji_id';
sub fields {
return { scalar => [qw/name icon_color icon_custom_emoji_id/] };
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
Teapot::Bot::Object::ForumTopicCreated - The base class for Telegram message 'ForumTopicCreated' type
=head1 VERSION
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'ForumTopicCreated' type.
See L<https://core.telegram.org/bots/api#forumtopiccreated> for details of the
attributes available for C<Teapot::Bot::Object::ForumTopicCreated> objects.
=head1 AUTHOR
Sergei Fedosov <eleksir@gmail.com>
=head1 LICENSE AND COPYRIGHT
This software is copyright (c) 2022 by Sergei Fedosov <eleksir@gmail.com>.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,55 @@
package Teapot::Bot::Object::ForumTopicEdited;
# ABSTRACT: The base class for Telegram message 'ForumTopicEdited' type.
use strict;
use warnings;
use 5.018; ## no critic (ProhibitImplicitImport)
use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::ForumTopicEdited::VERSION = '0.026';
has 'name';
has 'icon_custom_emoji_id';
sub fields {
return {
'scalar' => [qw/name icon_custom_emoji_id/],
};
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
Teapot::Bot::Object::ForumTopicEdited - The base class for Telegram message 'ForumTopicEdited' type
=head1 VERSION
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'ForumTopicEdited' type.
See L<https://core.telegram.org/bots/api#forumtopicedited> for details of the
attributes available for C<Teapot::Bot::Object::ForumTopicEdited> objects.
=head1 AUTHOR
Sergei Fedosov <eleksir@gmail.com>
=head1 LICENSE AND COPYRIGHT
This software is copyright (c) 2023 by Sergei Fedosov <eleksir@gmail.com>.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,51 @@
package Teapot::Bot::Object::ForumTopicReopened;
# ABSTRACT: The base class for Telegram message 'ForumTopicReopened' type.
use strict;
use warnings;
use 5.018; ## no critic (ProhibitImplicitImport)
use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::ForumTopicReopened::VERSION = '0.026';
sub fields {
return { };
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
Teapot::Bot::Object::ForumTopicReopened - The base class for Telegram message 'ForumTopicReopened' type
=head1 VERSION
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'ForumTopicReopened' type.
See L<https://core.telegram.org/bots/api#forumtopicreopened> for details of the
attributes available for C<Teapot::Bot::Object::ForumTopicReopened> objects.
=head1 AUTHOR
Sergei Fedosov <eleksir@gmail.com>
=head1 LICENSE AND COPYRIGHT
This software is copyright (c) 2022 by Sergei Fedosov <eleksir@gmail.com>.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -11,7 +11,7 @@ use Teapot::Bot::Object::PhotoSize ();
use Teapot::Bot::Object::Animation ();
use Teapot::Bot::Object::MessageEntity ();
$Teapot::Bot::Object::Game::VERSION = '0.023';
$Teapot::Bot::Object::Game::VERSION = '0.026';
has 'title';
has 'description';
@@ -45,7 +45,7 @@ Teapot::Bot::Object::Game - The base class for Telegram message 'Game' type
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'Game' type.

View File

@@ -0,0 +1,51 @@
package Teapot::Bot::Object::GeneralForumTopicHidden;
# ABSTRACT: The base class for Telegram message 'GeneralForumTopicHidden' type.
use strict;
use warnings;
use 5.018; ## no critic (ProhibitImplicitImport)
use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::GeneralForumTopicHidden::VERSION = '0.026';
sub fields {
return { };
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
Teapot::Bot::Object::GeneralForumTopicHidden - The base class for Telegram message 'GeneralForumTopicHidden' type
=head1 VERSION
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'GeneralForumTopicHidden' type.
See L<https://core.telegram.org/bots/api#generalforumtopichidden> for details of the
attributes available for C<Teapot::Bot::Object::GeneralForumTopicHidden> objects.
=head1 AUTHOR
Sergei Fedosov <eleksir@gmail.com>
=head1 LICENSE AND COPYRIGHT
This software is copyright (c) 2023 by Sergei Fedosov <eleksir@gmail.com>.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -0,0 +1,51 @@
package Teapot::Bot::Object::GeneralForumTopicUnhidden;
# ABSTRACT: The base class for Telegram message 'GeneralForumTopicUnhidden' type.
use strict;
use warnings;
use 5.018; ## no critic (ProhibitImplicitImport)
use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::GeneralForumTopicUnhidden::VERSION = '0.026';
sub fields {
return { };
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
Teapot::Bot::Object::GeneralForumTopicUnhidden - The base class for Telegram message 'GeneralForumTopicUnhidden' type
=head1 VERSION
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'GeneralForumTopicUnhidden' type.
See L<https://core.telegram.org/bots/api#generalforumtopicunhidden> for details of the
attributes available for C<Teapot::Bot::Object::GeneralForumTopicUnhidden> objects.
=head1 AUTHOR
Sergei Fedosov <eleksir@gmail.com>
=head1 LICENSE AND COPYRIGHT
This software is copyright (c) 2023 by Sergei Fedosov <eleksir@gmail.com>.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -10,7 +10,7 @@ use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::LoginUrl ();
use Teapot::Bot::Object::CallbackGame ();
$Teapot::Bot::Object::InlineKeyboardButton::VERSION = '0.023';
$Teapot::Bot::Object::InlineKeyboardButton::VERSION = '0.026';
has 'text';
has 'url';
@@ -43,7 +43,7 @@ Teapot::Bot::Object::InlineKeyboardButton - The base class for Telegram 'InlineK
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'InlineKeyboardButton' type objects.

View File

@@ -9,7 +9,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::InlineKeyboardButton ();
$Teapot::Bot::Object::InlineKeyboardMarkup::VERSION = '0.023';
$Teapot::Bot::Object::InlineKeyboardMarkup::VERSION = '0.026';
has 'inline_keyboard';
@@ -35,7 +35,7 @@ Teapot::Bot::Object::InlineKeyboardMarkup - The base class for Telegram 'InlineK
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'InlineKeyboardMarkup' type objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::Invoice::VERSION = '0.023';
$Teapot::Bot::Object::Invoice::VERSION = '0.026';
has 'title';
has 'description';
@@ -34,7 +34,7 @@ Teapot::Bot::Object::Invoice - The base class for Telegram 'Invoice' type object
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'Invoice' type objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::Location::VERSION = '0.023';
$Teapot::Bot::Object::Location::VERSION = '0.026';
has 'longitude';
has 'latitude';
@@ -35,7 +35,7 @@ Teapot::Bot::Object::Location - The base class for Telegram message 'Location' t
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'Location' type.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::LoginUrl::VERSION = '0.023';
$Teapot::Bot::Object::LoginUrl::VERSION = '0.026';
has 'url';
has 'forward_text';
@@ -33,7 +33,7 @@ Teapot::Bot::Object::LoginUrl - The base class for Telegram 'LoginUrl' type obje
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'LoginUrl' type objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::MaskPosition::VERSION = '0.023';
$Teapot::Bot::Object::MaskPosition::VERSION = '0.026';
has 'point';
has 'x_shift';
@@ -33,7 +33,7 @@ Teapot::Bot::Object::MaskPosition - The base class for Telegram 'MaskPosition' t
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'MaskPosition' type objects.

View File

@@ -30,7 +30,14 @@ use Teapot::Bot::Object::PhotoSize ();
use Teapot::Bot::Object::Invoice ();
use Teapot::Bot::Object::Venue ();
use Teapot::Bot::Object::SuccessfulPayment ();
use Teapot::Bot::Object::WriteAccessAllowed ();
use Teapot::Bot::Object::PassportData ();
use Teapot::Bot::Object::ForumTopicCreated ();
use Teapot::Bot::Object::ForumTopicEdited ();
use Teapot::Bot::Object::ForumTopicClosed ();
use Teapot::Bot::Object::ForumTopicReopened ();
use Teapot::Bot::Object::GeneralForumTopicHidden ();
use Teapot::Bot::Object::GeneralForumTopicUnhidden ();
use Teapot::Bot::Object::InlineKeyboardMarkup ();
use Teapot::Bot::Object::ProximityAlertTriggered ();
use Teapot::Bot::Object::Dice ();
@@ -40,10 +47,12 @@ use Teapot::Bot::Object::VideoChatStarted ();
use Teapot::Bot::Object::VideoChatEnded ();
use Teapot::Bot::Object::VideoChatParticipantsInvited ();
$Teapot::Bot::Object::Message::VERSION = '0.023';
$Teapot::Bot::Object::Message::VERSION = '0.026';
# basic message stuff
has 'message_id';
has 'message_thread_id'; # Optional. Unique identifier of a message thread to which the message belongs;
# for supergroups only
has 'from'; # User
has 'sender_chat'; # Chat
has 'date';
@@ -54,6 +63,7 @@ has 'forward_from_message_id';
has 'forward_signature';
has 'forward_sender_name';
has 'forward_date';
has 'is_topic_message'; # Optional. True, if the message is sent to a forum topic
has 'is_automatic_forward';
has 'reply_to_message'; # Message
has 'via_bot'; # User
@@ -73,6 +83,7 @@ has 'video_note'; # VideoNote
has 'voice'; # Voice
has 'caption';
has 'caption_entities'; # Array of MessageEntity
has 'has_media_spoiler';
has 'contact'; # Contact
has 'dice';
has 'game';
@@ -94,8 +105,15 @@ has 'pinned_message'; # Message
has 'invoice'; # Invoice
has 'successful_payment'; # SuccessfulPayment
has 'connected_website';
has 'write_access_allowed'; # WriteAccessAllowed
has 'passport_data'; # PassportData
has 'proximity_alert_triggered';
has 'forum_topic_created'; # ForumTopicCreated
has 'forum_topic_edited'; # ForumTopicEdited
has 'forum_topic_closed'; # ForumTopicClosed
has 'forum_topic_reopened'; # ForumTopicReopened
has 'general_forum_topic_hidden'; # GeneralForumTopicHidden
has 'general_forum_topic_unhidden'; # GeneralForumTopicUnhidden
has 'video_chat_scheduled';
has 'video_chat_started';
has 'video_chat_ended';
@@ -105,11 +123,11 @@ has 'reply_markup'; # Array of InlineKeyboardMarkup
sub fields {
return {
'scalar' => [qw/message_id date forward_from_message_id
forward_signature forward_sender_name
forward_date is_automatic_forward edit_date has_protected_content
media_group_id author_signature text caption
new_chat_title delete_chat_photo
'scalar' => [qw/message_id message_thread_id date forward_from_message_id
forward_signature forward_sender_name forward_date
is_topic_message is_automatic_forward edit_date
has_protected_content media_group_id author_signature text
caption has_media_spoiler new_chat_title delete_chat_photo
group_chat_created supergroup_chat_created
channel_chat_created migrate_to_chat_id
migrate_from_chat_id connected_website/],
@@ -137,7 +155,14 @@ sub fields {
'Teapot::Bot::Object::Invoice' => [qw/invoice/],
'Teapot::Bot::Object::SuccessfulPayment' => [qw/successful_payment/],
'Teapot::Bot::Object::WriteAccessAllowed' => [qw/write_access_allowed/],
'Teapot::Bot::Object::PassportData' => [qw/passport_data/],
'Teapot::Bot::Object::ForumTopicCreated' => [qw/forum_topic_created/],
'Teapot::Bot::Object::ForumTopicEdited' => [qw/forum_topic_edited/],
'Teapot::Bot::Object::ForumTopicClosed' => [qw/forum_topic_closed/],
'Teapot::Bot::Object::ForumTopicReopened' => [qw/forum_topic_reopened/],
'Teapot::Bot::Object::GeneralForumTopicHidden' => [qw/general_forum_topic_unhidden/],
'Teapot::Bot::Object::GeneralForumTopicUnhidden' => [qw/general_forum_topic_unhidden/],
'Teapot::Bot::Object::InlineKeyboardMarkup' => [qw/reply_markup/],
'Teapot::Bot::Object::ProximityAlertTriggered' => [qw/proximity_alert_triggered/],
'Teapot::Bot::Object::Dice' => [qw/dice/],
@@ -154,48 +179,76 @@ sub arrays {
return qw/photo entities caption_entities new_chat_members new_chat_photo/;
}
sub reply {
my $self = shift;
my $text = shift;
my $chatid = $self->chat->id;
my $ret = '';
if (Teapot::Bot::Object::ChatPermissions->canTalk($self, $chatid)) {
return $self->_brain->sendMessage({chat_id => $chatid, text => $text});
my $send_args->{chat_id} = $self->chat->id;
my $message_thread_id = eval {$self->message_thread_id};
my $can_talk = $self->_brain->can_talk($send_args);
if ($can_talk->{error}) {
$ret = $can_talk;
} else {
if ($can_talk->{can_talk}) {
$send_args->{text} = $text;
if (defined $message_thread_id && $message_thread_id ne '') {
$send_args->{$message_thread_id} = $message_thread_id;
}
return {'error' => 1};
$ret = $self->_brain->sendMessage($send_args);
}
}
return $ret;
}
sub replyMd {
my $self = shift;
my $text = shift;
my $chatid = $self->chat->id;
my $ret = '';
if (Teapot::Bot::Object::ChatPermissions->canTalk ($self, $chatid)) {
my $send_args;
my $send_args->{chat_id} = $self->chat->id;
my $message_thread_id = eval {$self->message_thread_id};
my $can_talk = $self->_brain->can_talk($send_args);
if ($can_talk->{error}) {
$ret = $can_talk;
} else {
if ($can_talk->{can_talk}) {
$send_args->{text} = $text;
$send_args->{parse_mode} = 'Markdown';
$send_args->{chat_id} = $chatid;
$send_args->{message_thread_id} = $message_thread_id if (defined $message_thread_id);
return $self->_brain->sendMessage($send_args);
$ret = $self->_brain->sendMessage($send_args);
}
}
return {'error' => 1};
return $ret;
}
sub typing {
my $self = shift;
my $chatid = $self->chat->id;
my $ret = '';
my $send_args->{chat_id} = $self->chat->id;
my $can_talk = $self->_brain->can_talk($send_args);
if (Teapot::Bot::Object::ChatPermissions->canTalk ($self, $chatid)) {
return $self->_brain->sendChatAction({chat_id => $chatid});
if ($can_talk->{error}) {
$ret = $can_talk;
} else {
if ($can_talk->{can_talk}) {
$ret = $self->_brain->sendChatAction($send_args);
}
}
return {'error' => 1};
return $ret;
}
1;
@@ -212,7 +265,7 @@ Teapot::Bot::Object::Message - The base class for the Telegram type "Message"
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for the Telegram type "Message".
@@ -228,6 +281,9 @@ A convenience method to reply to a message with text.
Will return the C<Teapot::Bot::Object::Message> object representing the message
sent.
On error returns hash reference with error field set to 1, also set fields
param, url and debug (which is result of Mojo::UserAgent->post->result->json)
=head2 replyMd
@@ -235,12 +291,15 @@ A convenience method to reply to a message with markdown formatted text.
Will return the C<Teapot::Bot::Object::Message> object representing the message
sent.
On error returns hash reference with error field set to 1, also set fields
param, url and debug (which is result of Mojo::UserAgent->post->result->json)
=head2 typing
Sends notification to chat that bot is "typing" something.
Returns nothing that should be checked.
On error returns hash reference with error field set to 1, also set fields
param, url and debug (which is result of Mojo::UserAgent->post->result->json)
=head1 AUTHOR

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::MessageAutoDeleteTimerChanged::VERSION = '0.023';
$Teapot::Bot::Object::MessageAutoDeleteTimerChanged::VERSION = '0.026';
has 'message_auto_delete_time';
@@ -32,7 +32,7 @@ Teapot::Bot::Object::MessageAutoDeleteTimerChanged - The base class for Telegram
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'MessageAutoDeleteTimerChanged' type objects.

View File

@@ -9,7 +9,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::User ();
$Teapot::Bot::Object::MessageEntity::VERSION = '0.023';
$Teapot::Bot::Object::MessageEntity::VERSION = '0.026';
has 'type';
has 'offset';
@@ -39,7 +39,7 @@ Teapot::Bot::Object::MessageEntity - The base class for Telegram 'MessageEntity'
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'MessageEntity' type objects.

View File

@@ -10,7 +10,7 @@ use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::EncryptedPassportElement ();
use Teapot::Bot::Object::EncryptedCredentials ();
$Teapot::Bot::Object::PassportData::VERSION = '0.023';
$Teapot::Bot::Object::PassportData::VERSION = '0.026';
has 'data'; # Array of EncryptedPassportElement
has 'credentials'; # EncryptedCredentials
@@ -40,7 +40,7 @@ Teapot::Bot::Object::PassportData - The base class for Telegram 'PassportData' t
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'PassportData' type objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::PhotoSize::VERSION = '0.023';
$Teapot::Bot::Object::PhotoSize::VERSION = '0.026';
has 'file_id';
has 'file_unique_id';
@@ -34,7 +34,7 @@ Teapot::Bot::Object::PhotoSize - The base class for Telegram message 'PhotoSize'
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'PhotoSize' type.

View File

@@ -9,7 +9,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::PollOption ();
$Teapot::Bot::Object::Poll::VERSION = '0.023';
$Teapot::Bot::Object::Poll::VERSION = '0.026';
has 'id';
has 'question';
@@ -52,7 +52,7 @@ Teapot::Bot::Object::Poll - The base class for Telegram 'Poll' type objects
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'Poll' type objects

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::PollAnswer::VERSION = '0.023';
$Teapot::Bot::Object::PollAnswer::VERSION = '0.026';
has 'poll_id';
has 'user';
@@ -39,7 +39,7 @@ Teapot::Bot::Object::PollAnswer - The base class for Telegram 'PollAnswer' type
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'PollAnswer' type objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::PollOption::VERSION = '0.023';
$Teapot::Bot::Object::PollOption::VERSION = '0.026';
has 'text';
has 'voter_count';
@@ -31,7 +31,7 @@ Teapot::Bot::Object::PollOption - The base class for Telegram 'PollOption' type
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'PollOption' type objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::ProximityAlertTriggered::VERSION = '0.023';
$Teapot::Bot::Object::ProximityAlertTriggered::VERSION = '0.026';
has 'traveler'; # User
has 'watcher'; # User
@@ -35,7 +35,7 @@ Teapot::Bot::Object::ProximityAlertTriggered - The base class for Telegram messa
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'ProximityAlertTriggered' type.

View File

@@ -10,24 +10,30 @@ use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::PhotoSize ();
use Teapot::Bot::Object::MaskPosition ();
$Teapot::Bot::Object::Sticker::VERSION = '0.023';
$Teapot::Bot::Object::Sticker::VERSION = '0.026';
has 'file_id';
has 'file_unique_id';
has 'type';
has 'width';
has 'height';
has 'is_animated';
has 'is_video';
has 'thumb'; # PhotoSize
has 'thumbnail'; # PhotoSize
has 'emoji';
has 'set_name';
has 'premium_animation';
has 'mask_position';
has 'custom_emoji_id';
has 'needs_repainting';
has 'file_size';
sub fields {
return {
scalar => [ qw/file_id file_unique_id width height is_animated is_video emoji set_name file_size/ ],
'Teapot::Bot::Object::PhotoSize' => [ qw/thumb/ ],
scalar => [ qw/file_id file_unique_id type width height is_animated is_video emoji
set_name premium_animation custom_emoji_id needs_repainting
file_size/ ],
'Teapot::Bot::Object::PhotoSize' => [ qw/thumbnail/ ],
'Teapot::Bot::Object::MaskPosition' => [qw/mask_position/],
};
}
@@ -46,7 +52,7 @@ Teapot::Bot::Object::Sticker - The base class for Telegram message 'Sticker' typ
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'Sticker' type.

View File

@@ -9,7 +9,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
# use Teapot::Bot::Object::OrderInfo;
$Teapot::Bot::Object::SuccessfulPayment::VERSION = '0.023';
$Teapot::Bot::Object::SuccessfulPayment::VERSION = '0.026';
has 'currency';
has 'total_amount';
@@ -41,7 +41,7 @@ Teapot::Bot::Object::SuccessfulPayment - The base class for Telegram 'Successful
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'SuccessfulPayment' type objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::User::VERSION = '0.023';
$Teapot::Bot::Object::User::VERSION = '0.026';
has 'id';
has 'is_bot';
@@ -41,7 +41,7 @@ Teapot::Bot::Object::User - The base class for Telegram message 'User' type
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'User' type.

View File

@@ -9,7 +9,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::Location ();
$Teapot::Bot::Object::Venue::VERSION = '0.023';
$Teapot::Bot::Object::Venue::VERSION = '0.026';
has 'location'; #Location
has 'title';
@@ -41,7 +41,7 @@ Teapot::Bot::Object::Venue - The base class for Telegram 'LoginUrl' type objects
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'LoginUrl' type objects.

View File

@@ -9,14 +9,14 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::PhotoSize ();
$Teapot::Bot::Object::Video::VERSION = '0.023';
$Teapot::Bot::Object::Video::VERSION = '0.026';
has 'file_id';
has 'file_unique_id';
has 'width';
has 'height';
has 'duration';
has 'thumb'; # Optional. Video thumbnail
has 'thumbnail'; # Optional. Video thumbnail
has 'file_name'; # Optional. Original filename as defined by sender
has 'mime_type'; # Optional. Mime type of a file as defined by sender
has 'file_size'; # Optional. File size
@@ -25,7 +25,7 @@ sub fields {
return {
scalar => [qw/file_id file_unique_id width height duration file_name mime_type
file_size/],
'Teapot::Bot::Object::PhotoSize' => [qw/thumb/],
'Teapot::Bot::Object::PhotoSize' => [qw/thumbnail/],
};
}
@@ -43,7 +43,7 @@ Teapot::Bot::Object::Video - The base class for Telegram 'Video' object
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'Video' object.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::VideoChatEnded::VERSION = '0.023';
$Teapot::Bot::Object::VideoChatEnded::VERSION = '0.026';
# This object represents a service message about a Video chat started in the chat. Currently holds no information.
has 'duration';
@@ -31,7 +31,7 @@ Teapot::Bot::Object::VideoChatEnded - The base class for Telegram message 'Video
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'VideoChatEnded' type.

View File

@@ -9,7 +9,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::User ();
$Teapot::Bot::Object::VideoChatParticipantsInvited::VERSION = '0.023';
$Teapot::Bot::Object::VideoChatParticipantsInvited::VERSION = '0.026';
# This object represents a service message about a Video chat started in the chat. Currently holds no information.
has 'users';
@@ -36,7 +36,7 @@ Teapot::Bot::Object::VideoChatParticipantsInvited - The base class for Telegram
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'VideoChatParticipantsInvited' type.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::VideoChatScheduled::VERSION = '0.023';
$Teapot::Bot::Object::VideoChatScheduled::VERSION = '0.026';
# This object represents a service message about a video chat started in the chat. Currently holds no information.
has 'start_date';
@@ -31,7 +31,7 @@ Teapot::Bot::Object::VideoChatScheduled - The base class for Telegram message 'V
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'VideoChatScheduled' type.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::VideoChatStarted::VERSION = '0.023';
$Teapot::Bot::Object::VideoChatStarted::VERSION = '0.026';
# This object represents a service message about a Video chat started in the chat. Currently holds no information.
has 'stub';
@@ -31,7 +31,7 @@ Teapot::Bot::Object::VideoChatStarted - The base class for Telegram message 'Vid
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'VideoChatStarted' type.

View File

@@ -9,7 +9,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
use Teapot::Bot::Object::PhotoSize ();
$Teapot::Bot::Object::VideoNote::VERSION = '0.023';
$Teapot::Bot::Object::VideoNote::VERSION = '0.026';
has 'file_id';
has 'file_unique_id';
@@ -40,7 +40,7 @@ Teapot::Bot::Object::VideoNote - The base class for Telegram 'VideoNote' type ob
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'VideoNote' type object.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::Voice::VERSION = '0.023';
$Teapot::Bot::Object::Voice::VERSION = '0.026';
has 'file_id';
has 'file_unique_id';
@@ -34,7 +34,7 @@ Teapot::Bot::Object::Voice - The base class for Telegram 'Voice' type objects
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'Voice' type objects.

View File

@@ -8,7 +8,7 @@ use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::WebAppData::VERSION = '0.023';
$Teapot::Bot::Object::WebAppData::VERSION = '0.026';
has 'data';
has 'button_text';
@@ -31,7 +31,7 @@ Teapot::Bot::Object::WebAppData - The base class for Telegram 'WebAppData' type
=head1 VERSION
version 0.023
version 0.026
=head1 DESCRIPTION
The base class for Telegram 'WebAppData' type objects.

View File

@@ -0,0 +1,51 @@
package Teapot::Bot::Object::WriteAccessAllowed;
# ABSTRACT: The base class for Telegram message 'WriteAccessAllowed' type.
use strict;
use warnings;
use 5.018; ## no critic (ProhibitImplicitImport)
use utf8;
use Mojo::Base 'Teapot::Bot::Object::Base';
$Teapot::Bot::Object::WriteAccessAllowed::VERSION = '0.026';
sub fields {
return { };
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
Teapot::Bot::Object::WriteAccessAllowed - The base class for Telegram message 'WriteAccessAllowed' type
=head1 VERSION
version 0.026
=head1 DESCRIPTION
The base class for Telegram message 'WriteAccessAllowed' type.
See L<https://core.telegram.org/bots/api#writeaccessallowed> for details of the
attributes available for C<Teapot::Bot::Object::WriteAccessAllowed> objects.
=head1 AUTHOR
Sergei Fedosov <eleksir@gmail.com>
=head1 LICENSE AND COPYRIGHT
This software is copyright (c) 2023 by Sergei Fedosov <eleksir@gmail.com>.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut

View File

@@ -14,10 +14,11 @@ use Log::Any qw ($log);
use Math::Random::Secure qw (irand);
use Mojo::Base 'Teapot::Bot::Brain';
use BotLib::Admin qw (FortuneToggleList ChanMsgEnabled GreetMsgEnabled GoodbyeMsgEnabled);
use BotLib qw (Command Highlight BotSleep IsCensored);
use BotLib::Admin qw (FortuneToggleList ChanMsgEnabled GreetMsgEnabled GoodbyeMsgEnabled
MigrateSettingsToNewChatID IsCensored);
use BotLib qw (Command);
use BotLib::Conf qw (LoadConf);
use BotLib::Util qw (trim fmatch);
use BotLib::Util qw (trim fmatch BotSleep Highlight RandomCommonPhrase);
use RedisLib qw (redis_events_listener);
use version; our $VERSION = qw (1.0);
@@ -42,6 +43,7 @@ my @introduce_greet = (
);
my $redismsg->{from} = 'telegram';
$redismsg->{threadid} = '';
$redismsg->{plugin} = 'telegram';
$redismsg->{misc}->{answer} = 1;
$redismsg->{misc}->{csign} = "$c->{telegrambot}->{csign}";
@@ -98,6 +100,15 @@ sub __on_msg {
my ($self, $msg) = @_;
# chat info
my $chatid;
# Ловим сообщения о миграции.
if ($msg->can ('migrate_to_chat_id') && $msg->can ('migrate_from_chat_id')) {
if (defined ($msg->migrate_from_chat_id) && defined ($msg->migrate_from_chat_id)) {
MigrateSettingsToNewChatID ($msg->migrate_from_chat_id, $msg->migrate_to_chat_id);
return;
}
}
my $chatname = 'Noname chat';
# user sending message info
my ($userid, $username, $fullname, $highlight, $vis_a_vi) = Highlight ($msg);
@@ -107,6 +118,7 @@ sub __on_msg {
my $myObj = $self->getMe ();
if ($myObj->{error}) {
$log->error ("[ERROR] Unable to call getMe BotAPI method: " . Dumper ($myObj));
return;
}
@@ -196,7 +208,12 @@ sub __on_msg {
}
BotSleep $msg;
$msg->replyMd ($phrase);
my $res = $msg->replyMd ($phrase);
if ($res->{error}) {
$log->error ("Unable to call sendMessage BotAPI method: " . Dumper ($res));
}
return;
}
@@ -239,7 +256,12 @@ sub __on_msg {
my $leftuser = sprintf '[%s](tg://user?id=%s)', $member_str, $member->id;
$phrase = sprintf $goodbye[irand ($#goodbye + 1)], $leftuser;
$msg->replyMd ($phrase);
my $res = $msg->replyMd ($phrase);
if ($res->{error}) {
$log->error ("Unable to call sendMessage BotAPI method: " . Dumper ($res));
}
return;
}
@@ -299,7 +321,11 @@ sub __on_msg {
# И вот тут как раз такая проверка и происходит
if (IsCensored $msg) {
$log->info (sprintf '[INFO] In public chat %s (%s) message from %s was censored', $chatname, $chatid, $vis_a_vi);
$self->deleteMessage ({chat_id => $chatid, message_id => $msg->{message_id}});
my $res = $self->deleteMessage ({chat_id => $chatid, message_id => $msg->{message_id}});
if ($res->{error}) {
$log->error ("Unable to call sendMessage BotAPI method: " . Dumper ($res));
}
}
# Некоторые рекламные товарищи пытаются срать своими каналами в чятик это тоже можно зацензурить ботом и это
@@ -311,7 +337,11 @@ sub __on_msg {
if (defined $sender_chat) {
unless (ChanMsgEnabled ($chatid)) {
$self->deleteMessage ({chat_id => $chatid, message_id => $msg->{message_id}});
my $res = $self->deleteMessage ({chat_id => $chatid, message_id => $msg->{message_id}});
if ($res->{error}) {
$log->error ("Unable to call sendMessage BotAPI method: " . Dumper ($res));
}
}
}
}
@@ -362,6 +392,15 @@ sub __on_msg {
$rmsg->{chatid} = "$chatid";
$rmsg->{misc}->{answer} = 1;
# Если тип группы supergroup, в ней могут быть треды, попробуем найти message_thread_id, если таковой есть
if ($msg->chat->type eq 'supergroup') {
if ($msg->can ('is_topic_message') && $msg->is_topic_message) {
if ($msg->can ('message_thread_id') && $msg->message_thread_id ne '') {
$rmsg->{threadid} = "$msg->message_thread_id";
}
}
}
{
do {
my $ready = eval { $main::RCONN->is_connected; };
@@ -402,6 +441,15 @@ sub __on_msg {
$rmsg->{chatid} = "$chatid";
$rmsg->{misc}->{answer} = 1;
# Если тип группы supergroup, в ней могут быть треды, попробуем найти message_thread_id, если таковой есть
if ($msg->chat->type eq 'supergroup') {
if ($msg->can ('is_topic_message') && $msg->is_topic_message) {
if ($msg->can ('message_thread_id') && $msg->message_thread_id ne '') {
$rmsg->{threadid} = "$msg->message_thread_id";
}
}
}
# Сообщение обращено к боту
if ((lc ($text) =~ /^${qname}[\,|\:]? (.+)/) or (lc ($text) =~ /^${qtname}[\,|\:]? (.+)/)){
$phrase = $1;
@@ -454,10 +502,25 @@ sub __on_msg {
$msg->typing ();
sleep (irand 2);
$log->debug (sprintf ('[DEBUG] In public chat %s (%s) bot reply to %s: %s', $chatname, $chatid, $vis_a_vi, $reply));
$msg->reply ($reply);
$log->debug (
sprintf (
'[DEBUG] In public chat %s (%s) bot reply to %s: %s',
$chatname, $chatid, $vis_a_vi, $reply,
)
);
my $res = $msg->reply ($reply);
if ($res->{error}) {
$log->error ("Unable to call sendMessage BotAPI method: " . Dumper ($res));
}
} else {
$log->debug (sprintf ('[DEBUG] In public chat %s (%s) bot is not required to reply to %s', $chatname, $chatid, $vis_a_vi));
$log->debug (
sprintf (
'[DEBUG] In public chat %s (%s) bot is not required to reply to %s',
$chatname, $chatid, $vis_a_vi,
)
);
}
# should be channel, so we can't talk
@@ -468,23 +531,6 @@ sub __on_msg {
return;
}
sub RandomCommonPhrase {
my @myphrase = (
'Так, блядь...',
'*Закатывает рукава* И ради этого ты меня позвал?',
'Ну чего ты начинаешь, нормально же общались',
'Повтори свой вопрос, не поняла',
'Выйди и зайди нормально',
'Я подумаю',
'Даже не знаю, что на это ответить',
'Ты упал такие вопросы девочке задавать?',
'Можно и так, но не уверена',
'А как ты думаешь?',
'А ви, таки, почему интересуетесь?',
);
return $myphrase[irand ($#myphrase + 1)];
}
# setup our bot
sub init {
@@ -504,6 +550,8 @@ sub RunTelegramBot {
eval { ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval)
TelegramBot->new->think;
};
$log->error ("[ERROR] $EVAL_ERROR");
}
return;