From 622b690946e5c84c2cfaf12b3d12025262f8a08e Mon Sep 17 00:00:00 2001 From: eleksir Date: Sat, 12 Feb 2022 18:22:01 +0300 Subject: [PATCH] Perlcritic overhaul, add missing 'use module', update cpanfile, replace Mojo::Log with Log::Any * Use more strict policy in perlcritic (add more policies) * Add missing Use Encode and Use File::Spec in Craniac.pm * Replace Mojo::Log with Log::Any, as Log::Any can catch stacktraces * Update cpanfile --- .perlcriticrc | 22 ++++++++++++++++ bin/aleesa-craniac | 32 +++++++++++++----------- bin/train_lat.pl | 2 +- cpanfile | 15 ++++++++--- lib/Conf.pm | 22 ++++++++++------ lib/Craniac.pm | 62 +++++++++++++++++++--------------------------- lib/Craniac/Lat.pm | 26 +++++-------------- 7 files changed, 98 insertions(+), 83 deletions(-) diff --git a/.perlcriticrc b/.perlcriticrc index 1f9bb32..540885c 100644 --- a/.perlcriticrc +++ b/.perlcriticrc @@ -94,3 +94,25 @@ lib_sections = NAME | VERSION | DESCRIPTION | AUTHOR | LICENSE AND COPYRIGHT # Have to use it, so fuckoff [-Variables::ProhibitPackageVars] + +[-CodeLayout::RequireASCII] + +[-Editor::RequireEmacsFileVariables] + +[-TooMuchCode::ProhibitUnnecessaryUTF8Pragma] + +[-TooMuchCode::ProhibitDuplicateLiteral] + +[-ErrorHandling::RequireUseOfExceptions] + +[-ValuesAndExpressions::RequireConstantOnLeftSideOfEquality] +[-Lax::RequireConstantOnLeftSideOfEquality::ExceptEq] + +[-Lax::ProhibitEmptyQuotes::ExceptAsFallback] + +[-CodeLayout::RequireUseUTF8] + +[ValuesAndExpressions::RestrictLongStrings] +max_length = 256 + +[-Miscellanea::ProhibitUnrestrictedNoCritic] diff --git a/bin/aleesa-craniac b/bin/aleesa-craniac index 963b064..15e7a15 100755 --- a/bin/aleesa-craniac +++ b/bin/aleesa-craniac @@ -1,6 +1,6 @@ #!/usr/bin/perl -use 5.018; +use 5.018; ## no critic (ProhibitImplicitImport) use strict; use warnings; use utf8; @@ -29,7 +29,10 @@ no Cwd; use Cwd::utf8 qw (chdir abs_path); use File::Basename qw (basename dirname); use File::Path qw (make_path); -use Mojo::Log; +use File::Spec (); +use Log::Any qw ($log); +use Log::Any::Adapter (); +use Log::Any::For::Std (); use POSIX qw (setgid setuid setsid); use Conf qw (LoadConf); @@ -44,9 +47,8 @@ my $runAsUid = $UID; my $piddir = '/var/run/' . basename (abs_path ($PROGRAM_NAME)); my $C = LoadConf (); -my $loglevel = $C->{'loglevel'} // 'info'; +my $loglevel = $C->{'loglevel'} // 'notice'; my $logfile; -my $log; if (defined $C->{'log'}) { $logfile = $C->{'log'}; @@ -69,8 +71,8 @@ if ($UID == 0) { make_path ( $piddir, { uid => $uid, - group => $gid - } + group => $gid, + }, ); } @@ -81,8 +83,8 @@ if ($UID == 0) { make_path ( $logdir, { uid => $uid, - group => $gid - } + group => $gid, + }, ) or die "Unable to create $logdir: $OS_ERROR\n"; } } @@ -95,9 +97,9 @@ if ($UID == 0) { } if (defined $logfile) { - $log = Mojo::Log->new (path => $logfile, level => $loglevel); + Log::Any::Adapter->set ('File', $logfile, log_level => $loglevel); } else { - $log = Mojo::Log->new (path => '/dev/null', level => 'fatal'); + Log::Any::Adapter->set ('File', File::Spec->devnull); } # По-умолчанию, демонизируемся, если явно не указано, что этого делать не надо @@ -113,7 +115,7 @@ my $apath = abs_path $PROGRAM_NAME; unless (defined $apath) { $log->fatal ("[FATAL] Unable to get abs_path: $OS_ERROR\n"); exit 1; -}; +} my $pidfile = sprintf '%s/%s.pid', $piddir, basename $apath; $log->info ("[INFO] Creating pidfile at $pidfile"); @@ -141,7 +143,7 @@ $PROGRAM_NAME = abs_path $PROGRAM_NAME; ## no critic (Variables::Re # И запустим уже наш сервис RunCraniac (); -if (-f $pidfile) { +if (-e $pidfile) { unlink $pidfile; } @@ -149,8 +151,8 @@ exit 0; sub daemonize { __fork (); - POSIX::setsid (); - open STDIN, '<', '/dev/null'; ## no critic (InputOutput::RequireCheckedSyscalls, InputOutput::RequireCheckedOpen) + setsid (); + open STDIN, '<', File::Spec->devnull; ## no critic (InputOutput::RequireCheckedSyscalls, InputOutput::RequireCheckedOpen) __fork (); umask 0; return; @@ -174,7 +176,7 @@ sub __fork { sub __signal_handler { $log->info ("[INFO] Caught a signal $OS_ERROR"); - if (-f $pidfile) { + if (-e $pidfile) { unlink $pidfile; } diff --git a/bin/train_lat.pl b/bin/train_lat.pl index 49499f6..09d5d5b 100644 --- a/bin/train_lat.pl +++ b/bin/train_lat.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl # Наполняет отдельный "мозг" с бредом латинскими выражениями -use 5.018; +use 5.018; ## no critic (ProhibitImplicitImport) use strict; use warnings; use utf8; diff --git a/cpanfile b/cpanfile index 5282345..ac7fa0f 100644 --- a/cpanfile +++ b/cpanfile @@ -1,22 +1,31 @@ +## no critic requires 'Carp', '==1.50'; -requires 'Cwd', '0'; +requires 'Cwd', '==3.75'; requires 'Cwd::utf8', '==0.011'; +requires 'Data::Dumper', '==2.183'; requires 'Digest::SHA', '==6.02'; requires 'Encode', '==3.16'; requires 'English', '==1.11'; -requires 'File::Basename', '0'; +requires 'File::Basename', '==2.85'; requires 'File::Path', '==2.18'; +requires 'File::Spec', '==3.75'; requires 'Hailo', '==0.75'; requires 'JSON::XS', '==4.03'; requires 'local::lib', '==2.000028'; +requires 'Log::Any', '==1.710'; +requires 'Log::Any::Adapter', '==1.710'; +requires 'Log::Any::For::Std', '==0.05'; requires 'Math::Random::Secure', '==0.080001'; requires 'Mojolicious', '==9.22'; +# Part of Mojolicious requires 'Mojo::IOLoop', '0'; requires 'Mojo::IOLoop::Signal', '==0.003'; -requires 'Mojo::Log', '0'; requires 'Mojo::Redis', '==3.27'; +# Part of perl requires 'POSIX', '0'; +# Buggy, latest version works, as pub-sub, but fails tests requires 'Protocol::Redis::XS', '0'; requires 'Text::Fuzzy', '==0.29'; +# Part of perl requires 'utf8', '0'; requires 'version', '==0.9929'; diff --git a/lib/Conf.pm b/lib/Conf.pm index 8708c3e..d9a167a 100644 --- a/lib/Conf.pm +++ b/lib/Conf.pm @@ -1,14 +1,13 @@ package Conf; -# loads config +# Загружает конфиг файл -use 5.018; +use 5.018; ## no critic (ProhibitImplicitImport) use strict; use warnings; use utf8; use open qw (:std :utf8); use English qw ( -no_match_vars ); -use Encode qw (encode decode); -use JSON::XS; +use JSON::XS (); use version; our $VERSION = qw (1.0); use Exporter qw (import); @@ -16,17 +15,26 @@ our @EXPORT_OK = qw (LoadConf); sub LoadConf { my $c = 'data/config.json'; - open my $CH, '<', $c or die "[FATAL] No conf at $c: $OS_ERROR\n"; - my $json; + my $CH; + + unless (open $CH, '<', $c) { + die "[FATAL] No conf at $c: $OS_ERROR\n"; + } + my $len = (stat $c) [7]; + my $json; my $readlen = read $CH, $json, $len; - $json = encode 'UTF-8', $json; unless ($readlen) { close $CH; ## no critic (InputOutput::RequireCheckedSyscalls die "[FATAL] Unable to read $c: $OS_ERROR\n"; } + if ($readlen != $len) { + close $CH; ## no critic (InputOutput::RequireCheckedSyscalls + die "[FATAL] File $c is $len bytes on disk, but we read only $readlen bytes\n"; + } + close $CH; ## no critic (InputOutput::RequireCheckedSyscalls my $j = JSON::XS->new->utf8->relaxed; return $j->decode ($json); diff --git a/lib/Craniac.pm b/lib/Craniac.pm index fd1f0e2..dde173b 100644 --- a/lib/Craniac.pm +++ b/lib/Craniac.pm @@ -9,7 +9,7 @@ package Craniac; # проигнорировать. # Общие модули - синтаксис, кодировки итд -use 5.018; +use 5.018; ## no critic (ProhibitImplicitImport) use strict; use warnings; use utf8; @@ -17,14 +17,17 @@ use open qw (:std :utf8); use English qw ( -no_match_vars ); # Модули для работы приложения +use Data::Dumper qw (Dumper); use Digest::SHA qw (sha1_base64); -use Hailo; -use Mojo::IOLoop; -use Mojo::IOLoop::Signal; -use Mojo::Log; +use Encode qw (encode_utf8); +use File::Spec (); +use Hailo (); +use Log::Any qw ($log); +use Mojo::IOLoop (); +use Mojo::IOLoop::Signal (); # Чтобы "уж точно" использовать hiredis-биндинги, загрузим этот модуль перед Mojo::Redis -use Protocol::Redis::XS; -use Mojo::Redis; +use Protocol::Redis::XS (); +use Mojo::Redis (); use Math::Random::Secure qw (irand); use Text::Fuzzy qw (distance_edits); @@ -42,22 +45,7 @@ sub brains (@); sub RunCraniac (); my $c = LoadConf (); -my $loglevel = $c->{'loglevel'} // 'info'; my $fwd_cnt = $c->{'forward_max'} // 5; -my $logfile; -my $log; - -if (defined $c->{'log'}) { - $logfile = $c->{'log'}; -} elsif (defined $c->{'debug_log'}) { - $logfile = $c->{'debug_log'}; -} - -if (defined $logfile) { - $log = Mojo::Log->new (path => $logfile, level => $loglevel); -} else { - $log = Mojo::Log->new (path => '/dev/null', level => 'fatal'); -} my $hailo; @@ -127,7 +115,7 @@ sub brains (@) { $hailo->{$chatid} = eval { Hailo->new ( brain => $brainname, - order => 3 + order => 3, ); }; @@ -267,8 +255,8 @@ my $parse_message = sub { userid => $userid, chatid => $chatid, plugin => $m->{plugin}, - message => $reply - } + message => $reply, + }, ); } } else { @@ -312,8 +300,8 @@ my $parse_message = sub { userid => $userid, chatid => $chatid, plugin => $m->{plugin}, - message => $reply - } + message => $reply, + }, ); return; @@ -337,8 +325,8 @@ my $parse_message = sub { userid => $userid, chatid => $chatid, plugin => $m->{plugin}, - message => $reply - } + message => $reply, + }, ); return; @@ -380,8 +368,8 @@ my $parse_message = sub { userid => $userid, chatid => $chatid, plugin => $m->{plugin}, - message => $reply - } + message => $reply, + }, ); } } @@ -408,7 +396,7 @@ my $__signal_handler = sub { my ($self, $name) = @_; $log->info ("[INFO] Caught a signal $name"); - if (defined $main::pidfile && -f $main::pidfile) { + if (defined $main::pidfile && -e $main::pidfile) { unlink $main::pidfile; } @@ -421,7 +409,7 @@ sub RunCraniac () { $log->info ("[INFO] Connecting to $c->{server}, $c->{port}"); my $redis = Mojo::Redis->new ( - sprintf 'redis://%s:%s/1', $c->{server}, $c->{port} + sprintf 'redis://%s:%s/1', $c->{server}, $c->{port}, ); $log->info ('[INFO] Registering connection-event callback'); @@ -438,11 +426,11 @@ sub RunCraniac () { my ($conn, $error) = @_; $log->error ("[ERROR] Redis connection error: $error"); return; - } + }, ); return; - } + }, ); my $pubsub = $redis->pubsub; @@ -453,13 +441,13 @@ sub RunCraniac () { $log->debug ("[DEBUG] Subscribing to $channel"); $sub->{$channel} = $pubsub->json ($channel)->listen ( - $channel => sub { $parse_message->(@_); } + $channel => sub { $parse_message->(@_); }, ); } Mojo::IOLoop::Signal->on ( TERM => $__signal_handler, - INT => $__signal_handler + INT => $__signal_handler, ); do { Mojo::IOLoop->start } until Mojo::IOLoop->is_running; diff --git a/lib/Craniac/Lat.pm b/lib/Craniac/Lat.pm index 3f571ee..fd5a0db 100644 --- a/lib/Craniac/Lat.pm +++ b/lib/Craniac/Lat.pm @@ -1,7 +1,7 @@ package Craniac::Lat; # Крылатые латинские выражения спёрты с https://ru.wikipedia.org/wiki/Список_крылатых_латинских_выражений -use 5.018; +use 5.018; ## no critic (ProhibitImplicitImport) use strict; use warnings; use utf8; @@ -10,8 +10,8 @@ use English qw ( -no_match_vars ); use Carp qw (cluck); use File::Basename qw (dirname); use File::Path qw (make_path); -use Hailo; -use Mojo::Log; +use Hailo (); +use Log::Any qw ($log); use Conf qw (LoadConf); @@ -25,20 +25,6 @@ my $brain_order = 2; my $c = LoadConf (); my $brain = $c->{lat}->{brain}; my $srcfile = $c->{lat}->{src}; -my $loglevel = $c->{'loglevel'} // 'info'; -my $log; - -if (defined $c->{'log'}) { - $logfile = $c->{'log'}; -} elsif (defined $c->{'debug_log'}) { - $logfile = $c->{'debug_log'}; -} - -if (defined $logfile) { - $log = Mojo::Log->new (path => $logfile, level => $loglevel); -} else { - $log = Mojo::Log->new (path => '/dev/null', level => 'fatal'); -} sub Train () { my $braindir = dirname $brain; @@ -52,7 +38,7 @@ sub Train () { my $lat = Hailo->new ( brain => $brain, - order => $brain_order + order => $brain_order, ); $lat->train ($srcfile); @@ -71,7 +57,7 @@ sub Lat () { return ''; } - unless (-f $brain) { + unless (-e $brain) { $log->error ("[ERROR] No lat module data: $brain is absent! Train lat first."); return ''; } @@ -79,7 +65,7 @@ sub Lat () { my $lat = Hailo->new ( brain => $brain, order => $brain_order, - save_on_exit => 0 + save_on_exit => 0, ); return $lat->reply ();