|
|
@@ -4,6 +4,8 @@ use Mojo::Base -strict, -signatures, -async_await;
|
|
|
use Mojo::Util;
|
|
|
use Scalar::Util;
|
|
|
|
|
|
+use experimental qw/switch/;
|
|
|
+
|
|
|
use fsa;
|
|
|
|
|
|
our $redis;
|
|
|
@@ -13,6 +15,8 @@ our $commands;
|
|
|
our $kb_menu;
|
|
|
our $abon_client;
|
|
|
|
|
|
+use constant FAIL_ASK_SERIAL => 3;
|
|
|
+
|
|
|
##################################################
|
|
|
|
|
|
my $rules = {
|
|
|
@@ -30,7 +34,11 @@ my $rules = {
|
|
|
# Поступила команда /start
|
|
|
|
|
|
# У нас есть uid в автомате? Это значит, что мы прочитали состояние из внешней базы
|
|
|
- return "command" if $fsa->note("uid");
|
|
|
+ if ($fsa->note("uid"))
|
|
|
+ {
|
|
|
+ reply($info, _("Для получения списка доступных команд введите /help"));
|
|
|
+ return "command";
|
|
|
+ }
|
|
|
|
|
|
# Проверяем, логинился ли уже пользователь в нашем боте
|
|
|
my $res = eval { await $client->get_p("client", "/telegram/$info->{id}/client") };
|
|
|
@@ -51,7 +59,7 @@ my $rules = {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- reply($info, greet($res->{fio}));
|
|
|
+ reply($info, greet($res->{fio}), _("Для получения списка доступных команд введите /help"));
|
|
|
$fsa->note(uid => $res->{uid});
|
|
|
return "command";
|
|
|
},
|
|
|
@@ -67,6 +75,8 @@ my $rules = {
|
|
|
{
|
|
|
my ($fsa, $line, $info) = @_;
|
|
|
|
|
|
+ request("deleteMessage", { chat_id=>$info->{id}, message_id=>$info->{msgid} });
|
|
|
+
|
|
|
my $res = eval { await $client->post_p("client", "/telegram/client", {login=>$fsa->note("login"), password=>$line, telegram_id=>$info->{id}}) };
|
|
|
if ($@)
|
|
|
{
|
|
|
@@ -74,8 +84,8 @@ my $rules = {
|
|
|
$fsa->delete_note("login");
|
|
|
die $@;
|
|
|
}
|
|
|
-
|
|
|
- reply($info, greet($res->{fio}));
|
|
|
+
|
|
|
+ reply($info, greet($res->{fio}), _("Для получения списка доступных команд введите /help"));
|
|
|
$fsa->note(uid => $res->{uid});
|
|
|
$fsa->delete_note("login");
|
|
|
|
|
|
@@ -99,6 +109,17 @@ my $rules = {
|
|
|
|
|
|
$fsa->state("command"); # на случай die
|
|
|
|
|
|
+ unless($target_uid)
|
|
|
+ {
|
|
|
+ reply($info, _("Перевод денег прерван"));
|
|
|
+ }
|
|
|
+
|
|
|
+ unless ($target_uid =~ /^\d+$/)
|
|
|
+ {
|
|
|
+ reply($info, _("Неправильный номер личного счета"), _("Введите его заново или пустую строку, если передумали пополнять"));
|
|
|
+ return "xfer_needs_uid";
|
|
|
+ }
|
|
|
+
|
|
|
if ($uid==$target_uid)
|
|
|
{
|
|
|
reply($info, _("Нельзя перевести деньги себе самому"));
|
|
|
@@ -136,15 +157,20 @@ my $rules = {
|
|
|
my $uid = $fsa->note("uid");
|
|
|
my $to_uid = $fsa->note("xfer_to");
|
|
|
|
|
|
+ unless($amount)
|
|
|
+ {
|
|
|
+ reply($info, _("Перевод денег прерван"));
|
|
|
+ }
|
|
|
+
|
|
|
$amount =~ s/,/./g;
|
|
|
$amount =~ s/[^\d\.]//g;
|
|
|
my $tmp = $amount;
|
|
|
my $count = $amount =~ tr/.//;
|
|
|
-
|
|
|
+
|
|
|
if (!$amount || $count>1)
|
|
|
{
|
|
|
- reply($info, _("Вы ввели неправильную сумму"));
|
|
|
- return "command";
|
|
|
+ reply($info, _("Вы ввели неправильную сумму"), _("Введите ее заново или пустую строку, если передумали пополнять"));
|
|
|
+ return "xfer_needs_amount";
|
|
|
}
|
|
|
|
|
|
$fsa->note(xfer_amount => $amount);
|
|
|
@@ -158,16 +184,162 @@ my $rules = {
|
|
|
|
|
|
return "command";
|
|
|
},
|
|
|
+
|
|
|
+ #### Заявки
|
|
|
+
|
|
|
+ task_needs_descr => async sub
|
|
|
+ {
|
|
|
+ my ($fsa, $descr, $info) = @_;
|
|
|
+ my $uid = $fsa->note("uid");
|
|
|
+
|
|
|
+ $fsa->note(task_text => $descr);
|
|
|
+
|
|
|
+ reply_with($info, {
|
|
|
+ inline_menu => [[
|
|
|
+ { text=>_("Отправить"), callback_data=>"\x00/task_post" },
|
|
|
+ { text=>_("Отменить"), callback_data=>"\x00/task_cancel" },
|
|
|
+ ]]
|
|
|
+ },
|
|
|
+ _("Перед отправкой заявки вы можете ее отредактировать средствами Телеграм")
|
|
|
+ );
|
|
|
+
|
|
|
+ return "command";
|
|
|
+ },
|
|
|
+
|
|
|
+ task_needs_comment => async sub
|
|
|
+ {
|
|
|
+ my ($fsa, $comment, $info) = @_;
|
|
|
+ my $uid = $fsa->note("uid");
|
|
|
+ my $task_id = $fsa->note("task_id");
|
|
|
+
|
|
|
+ my $params = {
|
|
|
+ text => $comment,
|
|
|
+ "for-client" => $uid,
|
|
|
+ };
|
|
|
+
|
|
|
+ $fsa->state("command"); # на случай die
|
|
|
+ my $res = await $client->post_p("task", "/task/$task_id/comment", $params);
|
|
|
+
|
|
|
+ reply($info, "Ваш ответ добавлен");
|
|
|
+ $fsa->delete_note("task_id");
|
|
|
+ return "command";
|
|
|
+ },
|
|
|
+
|
|
|
+ ##### Карточка пополнения
|
|
|
+
|
|
|
+ card_needs_code => sub
|
|
|
+ {
|
|
|
+ my ($fsa, $code, $info) = @_;
|
|
|
+ my $uid = $fsa->note("uid");
|
|
|
+
|
|
|
+ $fsa->state("command"); # на случай die
|
|
|
+
|
|
|
+ $code =~ s/\D//g;
|
|
|
+
|
|
|
+ unless($code)
|
|
|
+ {
|
|
|
+ reply($info, _("Пополнение карточкой прервано"));
|
|
|
+ }
|
|
|
+
|
|
|
+ unless ($code =~ /^\d{16}$/)
|
|
|
+ {
|
|
|
+ reply($info, _("Код карточки должен состоять из 16 цифр"), _("Введите его заново или пустую строку, если передумали пополнять"));
|
|
|
+ return "card_needs_code";
|
|
|
+ }
|
|
|
+
|
|
|
+ my $key = "card-guess-$uid";
|
|
|
+ my $fails = $redis->get($key) || 0;
|
|
|
+
|
|
|
+ if ($fails > FAIL_ASK_SERIAL)
|
|
|
+ {
|
|
|
+ $fsa->note(card_code => $code);
|
|
|
+ reply($info, _("Теперь введите номер карточки (7 цифр, можно разделять знаком'-')"));
|
|
|
+ return "card_needs_serial";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ pay_from_card($info, $uid, $code, "");
|
|
|
+ return "command";
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ card_needs_serial => sub
|
|
|
+ {
|
|
|
+ my ($fsa, $serial, $info) = @_;
|
|
|
+
|
|
|
+ $fsa->state("command"); # на случай die
|
|
|
+
|
|
|
+ unless($serial)
|
|
|
+ {
|
|
|
+ reply($info, _("Пополнение карточкой прервано"));
|
|
|
+ }
|
|
|
+
|
|
|
+ unless ($serial =~ /^\d{7}$/)
|
|
|
+ {
|
|
|
+ reply($info, _("Номер карточки должен состоять из 7 цифр"), _("Введите его заново или пустую строку, если передумали пополнять"));
|
|
|
+ return "card_needs_serial";
|
|
|
+ }
|
|
|
+
|
|
|
+ pay_from_card($info, $fsa->note("uid"), $fsa->note("card_code"), $serial);
|
|
|
+
|
|
|
+ return "command";
|
|
|
+ },
|
|
|
+
|
|
|
};
|
|
|
|
|
|
sub greet($whom)
|
|
|
{
|
|
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
|
|
|
- my $greet = $hour>=4 && $hour<=10 ? _("Доброе утро") : $hour>10 && $hour<6 ? _("Добрый день") : _("Добрый вечер");
|
|
|
+ my $greet = $hour>=4 && $hour<=10 ? _("Доброе утро") : $hour>10 && $hour<19 ? _("Добрый день") : _("Добрый вечер");
|
|
|
|
|
|
"$greet, $whom";
|
|
|
}
|
|
|
|
|
|
+async sub pay_from_card
|
|
|
+{
|
|
|
+ my ($info, $uid, $code, $serial) = @_;
|
|
|
+
|
|
|
+ my $args = {
|
|
|
+ code => $code,
|
|
|
+ uid => $uid,
|
|
|
+ domain => $config->{domain},
|
|
|
+ source => "abonbot",
|
|
|
+ ip => "0.0.0.0",
|
|
|
+ };
|
|
|
+
|
|
|
+ $args->{serial} = $serial if $serial;
|
|
|
+
|
|
|
+ my $res = eval { await $client->post_p("card", "/redemption", $args) };
|
|
|
+
|
|
|
+ unless($@)
|
|
|
+ {
|
|
|
+ return reply($info, _("Ваш счёт пополнен на " . $res->{amount} . " " . $res->{currency_short_name_ru} . ". " . _("Оплачено до ") . $res->{paid_until}));
|
|
|
+ };
|
|
|
+
|
|
|
+ given($@->{code})
|
|
|
+ {
|
|
|
+ when(400)
|
|
|
+ {
|
|
|
+ reply($info, _("Вы ввели неправильный номер или код карточки"));
|
|
|
+ my $key = "card-guess-$uid";
|
|
|
+ $redis->incr($key);
|
|
|
+ $redis->expire($key, 24 * 3600);
|
|
|
+ }
|
|
|
+ when(409)
|
|
|
+ {
|
|
|
+ reply($info, _("Карточка уже использована"));
|
|
|
+ }
|
|
|
+ when(406)
|
|
|
+ {
|
|
|
+ reply($info, _("Карточка не активирована. Обратитесь в службу поддержки"));
|
|
|
+ }
|
|
|
+ default
|
|
|
+ {
|
|
|
+ die $@;
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
######################
|
|
|
|
|
|
sub make_key($id)
|
|
|
@@ -179,9 +351,12 @@ sub save_fsa($fsa, $chatid)
|
|
|
{
|
|
|
my $key = make_key($chatid);
|
|
|
say "saving state ", $fsa->state, Dumper $fsa->notes;
|
|
|
+
|
|
|
+ my $notes = $fsa->notes;
|
|
|
+ utf8::encode($notes->{$_}) for keys %$notes;
|
|
|
|
|
|
$redis->del($key);
|
|
|
- $redis->hmset($key, %{ $fsa->notes });
|
|
|
+ $redis->hmset($key, %$notes);
|
|
|
$redis->expire($key, 3600*24);
|
|
|
}
|
|
|
|
|
|
@@ -189,8 +364,10 @@ sub make_fsa($chatid, $from)
|
|
|
{
|
|
|
my $id = make_key($chatid);
|
|
|
my $notes = { $redis->hgetall($id) };
|
|
|
+
|
|
|
if (keys %$notes)
|
|
|
{
|
|
|
+ utf8::decode($notes->{$_}) for keys %$notes;
|
|
|
return fsa->new($rules, $notes->{_state}, $notes);
|
|
|
}
|
|
|
else
|