use Modern::Perl; use AnyEvent; use utf8; use Mojo::Base -strict, -async_await; use Data::Dumper; use bdcom; use cdata; our $client; our $redis; our $db; ############################################## sub command_help :Alias("помощь") { my $cmd = shift; my $args = shift; my $chatid = shift; my $rest = shift; # TEMP # /purge-all-trees ip-адрес-устройства - Очистить все деревья PON # notify($chatid, <<"---", $rest); /purge ip-адрес-устройства номер-дерева - Очистить дерево PON /почистить ip-адрес-устройства номер-дерева /purge_all_trees ip-адрес-устройства - Очистить ВСЕ деревья /почистить_все_деревья ip-адрес-устройства - Очистить ВСЕ деревья /inspect ip-адрес-устройства номер-дерева - Информация об ONU на дереве /проверить ip-адрес-устройства номер-дерева /onu ip-адрес-устройства номер-дерева - Краткая информация ONU на дереве /ону ip-адрес-устройства номер-дерева --- } async sub command_find :Alias("где") { my $cmd = shift; my $args = shift; my $chatid = shift; my $rest = shift; my $onu_mac = uc $args->[0]; return notify($chatid, "Не указан MAC ONU") unless $onu_mac; my $olts; eval { $olts = await $client->get_p("device", "/pon"); }; my @keys = $redis->keys("gpon-*"); foreach my $x (@keys) { my %values = $redis->hgetall($x); my $record = \%values; if ( $record->{mac} && $record->{mac} =~ $onu_mac ) { my @key_parts = split("-", $x); my $dev_id = @key_parts[1]; my @olt_f = grep { $dev_id == $_->{entity} } @$olts; my $olt = @olt_f[0]; unless ($olt) { notify($chatid, "Не существует OLT id=$dev_id") unless $olt; } else { notify($chatid, "$olt->{name} ($olt->{ip}) $record->{name} (MAC-ONU: $record->{mac})"); } } } } # inspect 172.25.7.1 2 - посмотреть информацию об ONU на дереве 2 устройства 172.25.7.1 async sub command_inspect :Alias("проверить") { my $cmd = shift; my $args = shift; my $chatid = shift; my $rest = shift; my $ip = $args->[0]; my $tree = $args->[1]; return notify($chatid, "Не указан IP-адрес") unless $ip; return notify($chatid, "Не указан номер дерева") unless $tree; return notify($chatid, "Неправильный IP-адрес: $ip") unless is_valid_ip($ip); my $res; eval { $res = await $client->get_p("device", "/pon?query=ip=\"$ip\""); }; return notify($chatid, "Ошибка: " . parse_error($@)) if $@; return notify($chatid, "Устройство с ip=$ip не найдено") if @$res<1; my $dev = $res->[0]; my $sub; if ($dev->{type} =~ /^BDCOM/) { $sub = reference("bdcom_inspect"); # $sub = sub { bdcom->inspect(@_) }; } elsif ($dev->{type} =~ /^C-DATA/) { $sub = reference("cdata_inspect"); } return notify($chatid, "Неправильный номер дерева: $tree") unless is_valid_tree($dev->{type}, $tree); return notify($chatid, "Устройство $ip '$dev->{name}' неизвестного типа $dev->{type}") unless $sub; # notify($chatid, "Смотрю дерево $tree на устройстве $ip '$dev->{name}'"); my $text; eval { $text = await $sub->($ip, $dev->{login}, $dev->{password}, $tree); }; return notify($chatid, "$ip '$dev->{name}': $@") if $@; notify($chatid, "$ip '$dev->{name}' дерево $tree $text"); }; # onu 172.25.7.1 2 - получить короткую информацию об ONU на дереве 2 устройства 172.25.7.1 async sub command_onu :Alias("ону") { my $cmd = shift; my $args = shift; my $chatid = shift; my $rest = shift; my $ip = $args->[0]; my $tree = $args->[1]; return notify($chatid, "Не указан IP-адрес") unless $ip; return notify($chatid, "Не указан номер дерева") unless $tree; return notify($chatid, "Неправильный IP-адрес: $ip") unless is_valid_ip($ip); my $res; eval { $res = await $client->get_p("device", "/pon?query=ip=\"$ip\""); }; return notify($chatid, "Ошибка: " . parse_error($@)) if $@; return notify($chatid, "Устройство с ip=$ip не найдено") if @$res<1; my $dev = $res->[0]; my $sub; if ($dev->{type} =~ /^BDCOM/) { $sub = reference("bdcom_onu"); } elsif ($dev->{type} =~ /^C-DATA/) { $sub = reference("cdata_onu"); } return notify($chatid, "Неправильный номер дерева: $tree") unless is_valid_tree($dev->{type}, $tree); return notify($chatid, "Устройство $ip '$dev->{name}' неизвестного типа $dev->{type}") unless $sub; # notify($chatid, "Смотрю дерево $tree на устройстве $ip '$dev->{name}'"); my $text; eval { $text = await $sub->($ip, $dev->{login}, $dev->{password}, $tree); }; return notify($chatid, "$ip '$dev->{name}': $@") if $@; notify($chatid, "$ip '$dev->{name}' дерево $tree $text"); }; # purge 172.1.1.1 2 - почистить дерево 2 на ПОН async sub command_purge :Alias("почистить") { my $cmd = shift; my $args = shift; my $chatid = shift; my $rest = shift; my $ip = $args->[0]; my $tree = $args->[1]; return notify($chatid, "Не указан IP-адрес") unless $ip; return notify($chatid, "Не указан номер дерева") unless $tree; return notify($chatid, "Неправильный IP-адрес: $ip") unless is_valid_ip($ip); my $res; eval { $res = await $client->get_p("device", "/pon?query=ip=\"$ip\""); }; return notify($chatid, "Ошибка: " . parse_error($@)) if $@; return notify($chatid, "Устройство с ip=$ip не найдено") if @$res<1; my $dev = $res->[0]; my $sub; if ($dev->{type} =~ /^BDCOM/) { $sub = reference("bdcom_purge"); } elsif ($dev->{type} =~ /^C-DATA/) { $sub = reference("cdata_purge"); } return notify($chatid, "Неправильный номер дерева: $tree") unless is_valid_tree($dev->{type}, $tree); return notify($chatid, "Устройство $ip '$dev->{name}' неизвестного типа $dev->{type}") unless $sub; notify($chatid, "Очищаю дерево $tree на устройстве $ip '$dev->{name}'"); my $text; eval { $text = await $sub->($ip, $dev->{login}, $dev->{password}, $tree, 1); }; return notify($chatid, "$ip '$dev->{name}': $@") if $@; notify($chatid, "$ip '$dev->{name}' дерево $tree $text"); }; # purge_all_trees 172.1.1.1 - почистить все деревья на устройстве 172.1.1.1 async sub command_purge_all_trees :Alias("почистить_все_деревья") { my $cmd = shift; my $args = shift; my $chatid = shift; my $rest = shift; my $ip = $args->[0]; return notify($chatid, "Не указан IP-адрес") unless $ip; return notify($chatid, "Неправильный IP-адрес: $ip") unless is_valid_ip($ip); my $res; eval { $res = await $client->get_p("device", "/pon?query=ip=\"$ip\""); }; return notify($chatid, "Ошибка: " . parse_error($@)) if $@; return notify($chatid, "Устройство с ip=$ip не найдено") if @$res<1; my $dev = $res->[0]; my $sub; if ($dev->{type} =~ /^BDCOM/) { $sub = reference("bdcom_purgeall"); } elsif ($dev->{type} =~ /^C-DATA/) { $sub = reference("cdata_purgeall"); } my $tree_count = get_tree_count($dev->{type}); notify($chatid, "$ip '$dev->{name}'\nВыполняю очистку ВСЕХ деревьев.\nОперация может быть долгой. Ожидайте.\nКоличество деревьев: $tree_count"); return notify($chatid, "Устройство $ip '$dev->{name}' неизвестного типа $dev->{type}") unless $sub; my $res_ref; eval { $res_ref = await $sub->($ip, $dev->{login}, $dev->{password}, $tree_count, 1); # say Dumper @{$res_ref}; }; return notify($chatid, "$ip '$dev->{name}': $@") if $@; # Also note that your bot will not be able to send more than 20 messages per minute to the same group. my $w; $w = AnyEvent->timer (after => 1, interval => 3, cb => sub { if (scalar @{$res_ref} == 0) { undef $w; } my $text = shift @{$res_ref}; if ($text) { notify($chatid, "$ip '$dev->{name}' $text"); } }); }; ################################### sub is_valid_ip { return $_[0] =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/; } sub get_tree_count { my $devtype = shift; if ($devtype =~ /^BDCOM P3608/) { return 8; } elsif ($devtype =~ /^BDCOM P3600-08/) { return 8; } elsif ($devtype =~ /^BDCOM P3616/) { return 16; } elsif ($devtype =~ /^BDCOM P3310/) { return 4; } elsif ($devtype =~ /^C-DATA FD1208/) { return 8; } elsif ($devtype =~ /^C-DATA FD1216/) { return 16; } else { return 0; } } sub is_valid_tree { my $devtype = shift; my $tree_num = shift; my $tree_count = get_tree_count($devtype); return ($tree_num <= $tree_count) && ($tree_num > 0); } sub parse_error { my $e = shift; return $e unless ref $e; return "$e->{code} $e->{message} $e->{body}"; } 1;