use Modern::Perl; use utf8; use Mojo::Base -strict, -async_await, -signatures; use Data::Dumper; our $client; our $abon_client; our $config; our $redis; sub __ { @_; } ############################################## our $commands = [ {command=>"help", name=>__("Помощь"), description=>__("Список доступных команд"), hide_in_kb=>1}, {command=>"info", name=>__("Информация"), description=>__("Информация о пользователе")}, {command=>"balance", name=>__("Баланс"), description=>__("Проверка баланса")}, {command=>"service", name=>__("Сервисы"), description=>__("Подключенные сервисы")}, {command=>"credit", name=>__("Кредит"), description=>__("Установка кредита")}, {command=>"card", name=>__("Карта пополнения"), description=>__("Оплата карточкой пополнения")}, {command=>"payberry", name=>__("Payberry"), description=>__("Оплата через Payberry")}, {command=>"transfer", name=>__("Перевод"), description=>__("Перевод денег")}, {command=>"new_task", name=>__("Новая заявка"), description=>__("Новая заявка")}, {command=>"tasks", name=>__("Заявки"), description=>__("Открытые заявки")}, {command=>"support", name=>__("Техподдержка"), description=>__("Связь с техподдержкой")}, {command=>"logout", name=>__("Выход"), description=>__("Выход")}, ]; ############################################## sub command_help($fsa, $info) { my @list = map { "/$_->{command} " . _($_->{description}) } @$commands; reply($info, join("\n", @list)); } async sub command_logout { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); await $client->delete_p("client", "/client/$uid/telegram"); reply($info, _("Благодарим за использование нашего бота")); $fsa->delete_note("uid"); $fsa->state("logged_out"); } async sub command_balance { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); my $money = await $abon_client->get_p($info, "client", "/client/$uid/money?human=1"); my $cur = $money->{human}; my @lines = ( sprintf("%s: %.2f $cur (%s %.2f $cur + %s %.2f $cur) ", _("Ваш баланс"), $money->{balance}, ("депозит"), $money->{deposit}, _("кредит"), $money->{credit}), ); push @lines, sprintf("%s: %s", _("Оплачено до"), format_date($money->{last_day})) if $money->{last_day} ne "-"; push @lines, sprintf("%s: %d%%", _("Скидка"), $money->{reduction}) if $money->{reduction}; push @lines, sprintf("%s: %.2f $cur %s (%s)", _("Последнее снятие"), $money->{last_withdrawal}->{sum}, format_time($money->{last_withdrawal}->{date}), $money->{last_withdrawal}->{comment}) if $money->{last_withdrawal}->{sum}; push @lines, sprintf("%s: %.2f $cur %s", _("Последний платеж"), $money->{last_payment}->{sum}, format_time($money->{last_payment}->{date})) if $money->{last_payment}->{sum}; for (keys %{ $money->{accounts} }) { push @lines, sprintf("%s: %.2f $cur", $_, $money->{accounts}->{$_}); } reply($info, @lines); } async sub command_info { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); my $client = await $abon_client->get_p($info, "client", "/client/$uid"); reply($info, sprintf("%s: %d", _("Лицевой счет"), $client->{uid}), sprintf("%s: %s", _("Логин"), $client->{login}), sprintf("%s: %s", _("ФИО"), $client->{fio}), sprintf("%s: %s", _("Адрес"), $client->{address}), sprintf("%s: %s", _("Телефон"), $client->{phone}), ); } async sub command_credit { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); my $money = await $abon_client->get_p($info, "client", "/client/$uid/money?human=1"); if ($money->{credit} > 0) { return reply($info, sprintf("%s %.2f %s", _("У вас уже установлен кредит"), $money->{credit}, $money->{human})); } reply_with($info, { inline_menu => [[ { text=>_("Я согласен с условиями"), callback_data=>"\x00/set-credit" }, ]], }, _("Вы можете самостоятельно установить кредит на два дня"), _("Ограничения: только для физических лиц, продлевать кредит повторно до оплаты нельзя. При следующей оплате кредит будет погашен"), ); } async sub callback_set_credit { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); my $res = await $abon_client->post_p($info, "client", "/client/$uid/credit", {human=>1}); return reply($info, _("Кредит не имеет смысла для бесплатных тарифных планов")) if $res->{credit} == 0; await reply($info, sprintf("%s %.2f %s", _("Установлен кредит "), $res->{credit}, $res->{human}), "", ); command_balance($fsa, $info); } async sub command_service { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); my $res = await $abon_client->get_p($info, "client", "/client/$uid/service?human=1&as-array=1"); my @list = map { sprintf("%s: %s (%s '%s')", $_->{name_ru}, format_wd($_->{tariff}, $_->{human}), _("тариф"), $_->{tariff}->{name_ru}) } grep { !$_->{disabled} } @$res; reply($info, @list); }; async sub command_transfer { my ($fsa, $info) = @_; reply($info, _("Введите лицевой счет пользователя, которому вы хотите перевести деньги со своего счета")); $fsa->delete_note("xfer_to"); $fsa->delete_note("xfer_amount"); $fsa->state("xfer_needs_uid"); } async sub callback_transfer { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); my $to_uid = $fsa->delete_note("xfer_to"); my $amount = $fsa->delete_note("xfer_amount"); unless ($to_uid && $amount) { return reply($info, _("Произошла внутренняя ошибка")); } my $res = $abon_client->post_p($info, "client", "/client/$uid/money/to/$to_uid", { amount => $amount, ip => "0.0.0.0", via => "abonbot", currency => $config->{currency}->{name}, }); reply($info, _("Деньги успешно переведены")); command_balance($fsa, $info); } ########################################## async sub command_new_task { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); my $res = await $abon_client->get_p($info, "task", "/task?created_by_client=$uid&list=new,work"); if ($res->{total}) { return reply($info, _("Создание новой заявки невозможно, пока не будут решены уже открытые")); } reply($info, _("Изложите вашу проблему")); $fsa->state("task_needs_descr"); }; async sub callback_task_post { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); my $params = { description => $fsa->note("task_text"), "for-client" => $uid, client => $uid, type => "client-issue", list => "new", task_attr => { source => "telegram" }, }; my $res = await $client->post_json_p("task", "/task", $params); reply($info, "Заявка размещена"); $fsa->delete_note("task_text"); command_tasks($fsa, $info); } async sub callback_task_cancel { say 666; my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); say "aaa", Dumper $fsa; reply($info, _("Заявка отменена")); } async sub command_tasks { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); my $res = await $abon_client->get_p($info, "task", "/task?created_by_client=$uid&list=new,work&sort=id"); return reply($info, _("Открытых заявок нет")) unless $res->{total}; my @str = map { _("Заявка") . " $_->{number}\n$_->{description}\n" . _("Комментариев") . " " . $_->{total_comments} . ", " . _(" не прочитано") . " " . $_->{unread_comments} . "" } @{$res->{data}}; my $menu = [[ map { { text => _("Комментарии к заявке") . " " . $_->{number}, callback_data => "\x00/task $_->{entity}" } } @{$res->{data}} ]]; reply_with($info, {inline_menu=>$menu}, @str); }; async sub callback_task { my ($fsa, $info, $task_id) = @_; my $uid = $fsa->note("uid"); my $res = await $client->get_p("task", "/task/$task_id?with_comments=1"); my @str = map { format_timestamp($_->{created}) . " " . "" . ($_->{created_by}->[0] eq "worker" ? _("Оператор") : _("Вы")) . ":\n" . $_->{text} } grep { $_->{visibleToUser} } @{ $res->{comments} }; my $menu = [[ {text => _("Добавить комментарий"), callback_data => "\x00comment $task_id"}, ]]; reply_with($info, {inline_menu=>$menu}, @str); $client->post_p("task", "/task/$task_id/comment/read", {for_client=>$uid}); } async sub callback_comment { my ($fsa, $info, $task_id) = @_; $fsa->note(task_id => $task_id); $fsa->state("task_needs_comment"); reply($info, _("Введите текст вашего ответа")); } ################################################## use constant FAIL_BLOCK => 10; async sub command_payberry { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); my $menu = [[ {text => _("Payberry"), url => $config->{pay}->{payberry_url} . "?acc=$uid"} ]]; reply_with($info, {inline_menu=>$menu}, _("Для оплаты перейдите по ссылке")); } async sub command_card { my ($fsa, $info) = @_; my $uid = $fsa->note("uid"); my $key = "card-guess-$uid"; my $failed = $redis->get($key) || 0; if ($failed > FAIL_BLOCK) { return reply($info, _("Вы ввели неправильный код слишком много раз. Пополнение карточкой заблокировано на сутки")); } my $res = await $client->get_p("client", "/client/$uid"); if ($res->{disabled}) { return reply($info, _("Пополнение счета недоступно отключенным пользователям")); } reply($info, _("Введите код карточки пополнения (16 цифр, можно разделять их знаком '-')")); $fsa->delete_note("card_code"); $fsa->delete_note("card_serial"); $fsa->state("card_needs_code"); } sub command_support { my ($fsa, $info) = @_; return reply($info, _("Телефоны техподдержки:"), @{$config->{support_phones}}); } ################################################## sub format_wd($rec, $cur) { return _("бесплатно") if $rec->{dayly} == 0 && $rec->{monthly} == 0; my $m = sprintf("%.2f $cur %s", $rec->{monthly}, _("в месяц")) if $rec->{monthly} != 0; my $d = sprintf("%.2f $cur %s", $rec->{dayly}, _("в месяц")) if $rec->{dayly} != 0; return ("$m + $d") if $m && $d; return $m if $m; return $d if $d; } sub parse_error { my $e = shift; return $e unless ref $e; return "$e->{code} $e->{message} $e->{body}"; } 1; # локализация