Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff --git a/kadr.pl b/kadr.pl
- index e419af5..d0ec76b 100644
- --- a/kadr.pl
- +++ b/kadr.pl
- @@ -17,6 +17,10 @@
- use v5.10;
- use common::sense;
- +use AnyEvent;
- +use Coro;
- +use Coro::Channel;
- +use lib qw(Parse-TitleSyntax/lib Term-StatusLine/lib);
- use Config::YAML;
- use Data::Types qw(:int);
- use DBI::SpeedySimple;
- @@ -88,6 +92,8 @@ EOF
- $conf->read("$appdir/config");
- $conf->write;
- +our $offline_mode = @ARGV ~~ /--offline-mode/;
- +
- my $parsets = Parse::TitleSyntax->new($conf->{file_naming_scheme});
- $parsets->AddFunctions(Parse::TitleSyntax::Functions::Regexp->new($parsets));
- @@ -134,17 +140,85 @@ my $a = AniDB::UDPClient->new({
- port => 3700,
- });
- -my @files = sort(find_files(@{$conf->{dirs}->{to_scan}}));
- +my $totalfiles;
- +my $sl = Term::StatusLine::XofX->new(total_item_count => sub { $totalfiles; });
- +my %channel;
- +my @files;
- +for (('files','hashing','hashed','done')) {
- + $channel{$_} = new Coro::Channel;
- +}
- +
- +async { # Finds files and queues them for hashing
- + my(@paths) = @{$conf->{dirs}->{to_scan}};
- + my @dirs;
- + for(@paths) {
- + if(!is_dir($_)) {
- + if(is_file($_)) {
- + $totalfiles++;
- + @files = sort(@files, $_);
- + }
- + else {
- + say "Warning: Not a directory: $_";
- + }
- + }
- + else {
- + push @dirs, $_;
- + }
- + }
- + cede;
- + for my $dir (@dirs) {
- + opendir my $dh, $dir;
- + for (readdir $dh) {
- + if(!($_ eq '.' or $_ eq '..')) {
- + $_ = "$dir/$_";
- + if(is_dir($_)) {
- + push @dirs, $_;
- + }
- + else {
- + $totalfiles++;
- + @files = sort(@files, decode_utf8($_));
- + }
- + }
- + }
- + close($dh);
- + cede;
- + }
- + push @files, undef;
- +};
- +async { # queues the progressively sorted files for hashing
- + while(@files == 0 || defined $files[0]) {
- + $channel{files}->put(shift @files) if defined $files[0];
- + cede;
- + }
- + $channel{files}->shutdown;
- +};
- +
- my @ed2k_of_processed_files;
- -my $sl = Term::StatusLine::XofX->new(total_item_count => scalar(@files));
- -for(@files) {
- - $sl->update('++', $_);
- - next if !valid_file($_);
- - if(my $ed2k = process_file($_)) {
- - push @ed2k_of_processed_files, $ed2k;
- +async { # requests hashing and process the file as soon as done
- + while(($_=$channel{files}->get)) {
- + $sl->update('++', $_);
- + next unless valid_file($_);
- + $channel{hashing}->put($_);
- + async_pool {
- + if(($_=$channel{hashed}->get)) {
- + push @ed2k_of_processed_files, $_->[0] if process_file(@$_);
- + } else {
- + $channel{done}->shutdown;
- + }
- + };
- }
- -}
- -$sl->finalize;
- + $channel{hashing}->shutdown;
- + $sl->finalize;
- +};
- +
- +async {
- + while(($_=$channel{hashing}->get)) {
- + $channel{hashed}->put([ed2k_hash($_),$_]);
- + }
- + $channel{hashed}->shutdown;
- +};
- +
- +$channel{done}->get;
- if($conf->{anidb}->{update_records_for_deleted_files}) {
- my @missing_files = @{$db->{dbh}->selectall_arrayref('SELECT ed2k, size, filename FROM known_files WHERE ed2k NOT IN (' . join(',', map { "'$_'" } @ed2k_of_processed_files) . ') ORDER BY filename')};
- @@ -180,48 +254,10 @@ sub valid_file {
- return 1;
- }
- -sub find_files {
- - my(@paths) = @_;
- - my(@dirs, @files);
- - for(@paths) {
- - if(!is_dir($_)) {
- - if(is_file($_)) {
- - push @files, $_;
- - }
- - else {
- - say "Warning: Not a directory: $_";
- - }
- - }
- - else {
- - push @dirs, $_;
- - }
- - }
- - my $sl = Term::StatusLine::XofX->new(label => 'Scanning Directory', total_item_count => sub { scalar(@dirs) });
- - for my $dir (@dirs) {
- - $sl->update('++', $dir);
- - opendir(my $dh, $dir);
- - for(readdir($dh)) {
- - if(!($_ eq '.' or $_ eq '..')) {
- - $_ = "$dir/$_";
- - if(is_dir($_)) {
- - push @dirs, $_;
- - }
- - else {
- - push @files, decode_utf8($_);
- - }
- - }
- - }
- - close($dh);
- - }
- - $sl->finalize;
- - return @files;
- -}
- -
- sub process_file {
- - my $file = shift;
- - my $ed2k = ed2k_hash($file);
- + my ($ed2k, $file) = @_;
- my $fileinfo = $a->file_query({ed2k => $ed2k, size => -s $file});
- - my $proc_sl = Term::StatusLine::Freeform->new(parent => $sl);
- + my $proc_sl = Term::StatusLine::Freeform->new();
- if(!defined $fileinfo) {
- $proc_sl->finalize_and_log('Ignored');
- @@ -273,6 +309,9 @@ sub process_file {
- }
- for(keys %$fileinfo) {
- + delete $fileinfo->{$_} && next if $fileinfo->{$_} eq '';
- + $fileinfo->{$_} =~ s/H264\/AVC/H.264/g;
- + $fileinfo->{$_} =~ s/Vorbis \(Ogg Vorbis\)/Vorbis/g;
- $fileinfo->{$_} =~ s/\//∕/g;
- $fileinfo->{$_} =~ s/\`/'/g;
- }
- @@ -345,6 +384,7 @@ sub avdump {
- [qr/H\s+(\d+).(\d{2})/, sub {
- my @m = @{shift->matchlist};
- $avsl->update(int(int($m[0]) + int($m[1]) / 100));
- + cede;
- exp_continue;
- }],
- [qr/P\s+(\d+).(\d{2})/, sub {
- @@ -352,6 +392,7 @@ sub avdump {
- if($avsl->label eq 'AvHashing') {
- $avsl->label('AvParsing');
- }
- + cede;
- $avsl->update(int(int($m[0]) + int($m[1]) / 100));
- exp_continue;
- }],
- @@ -399,15 +440,14 @@ sub ed2k_hash {
- my $fh = file_open('<:mmap:raw', $file);
- my $ed2k_sl;
- if($conf->{show_hashing_progress}) {
- - $ed2k_sl = Term::StatusLine::XofX->new(parent => $sl, label => 'Hashing', total_item_count => $size);
- - while(my $bytes_read = read $fh, my $buffer, Digest::ED2K::CHUNK_SIZE) {
- - $ctx->add($buffer);
- - $ed2k_sl->update("+=$bytes_read");
- - }
- - }
- - else {
- + $ed2k_sl = Term::StatusLine::XofX->new(parent => $sl, label => 'Hashing', total_item_count => $size) ;
- + } else {
- $ed2k_sl = Term::StatusLine::Freeform->new(parent => $sl, value => 'Hashing');
- - $ctx->addfile($fh);
- + }
- + while(my $bytes_read = read $fh, my $buffer, Digest::ED2K::CHUNK_SIZE) {
- + $ctx->add($buffer);
- + $ed2k_sl->update("+=$bytes_read") if($conf->{show_hashing_progress});
- + cede;
- }
- close $fh;
- my $ed2k = $ctx->hexdigest;
- @@ -530,6 +570,8 @@ use constant MYLIST_ANIME_ENUM => qw/anime_title episodes eps_with_state_unknown
- sub new {
- my($package, $opts) = @_;
- my $self = bless $opts, $package;
- + $self->{offline} = $main::offline_mode;
- + return $self if ($self->{offline});
- $self->{username} or die 'AniDB error: Need a username';
- $self->{password} or die 'AniDB error: Need a password';
- $self->{starttime} = time - 1;
- @@ -547,6 +589,7 @@ sub file_query {
- if(my $r = $self->{db}->fetch("adbcache_file", ["*"], $query, 1)) {
- return $r;
- }
- + return if ($self->{offline});
- my $file_sl = Term::StatusLine::Freeform->new(parent => $sl, value => 'Updating file information');
- @@ -605,6 +648,7 @@ sub mylistedit {
- sub mylist_add_query {
- my ($self, $params) = @_;
- + return 0 if $self->{offline};
- my $res;
- if ((!defined $params->{edit}) or $params->{edit} == 0) {
- @@ -660,6 +704,7 @@ sub mylist_file_by_ed2k_size {
- sub _mylist_file_query {
- my($self, $query) = @_;
- + return undef if $self->{offline};
- my $mylist_sl = Term::StatusLine::Freeform->new(parent => $sl, value => 'Updating mylist information');
- (my $msg = $self->_sendrecv("MYLIST", $query)) =~ s/.*\n//im;
- $mylist_sl->finalize;
- @@ -683,6 +728,7 @@ sub mylist_anime_by_aid {
- sub _mylist_anime_query {
- my($self, $query) = @_;
- + return undef if $self->{offline};
- my $mylist_anime_sl = Term::StatusLine::Freeform->new(parent => $sl, value => 'Updating mylist anime information');
- my $msg = $self->_sendrecv("MYLIST", $query);
- $mylist_anime_sl->finalize;
- @@ -726,6 +772,7 @@ sub _mylist_anime_query {
- sub login {
- my($self) = @_;
- + return undef if $self->{offline};
- if(!defined $self->{skey} || (time - $self->{last_command}) > (35 * 60)) {
- my $login_sl = Term::StatusLine::Freeform->new(parent => $sl, value => 'Logging in to AniDB');
- my $msg = $self->_sendrecv("AUTH", {user => lc($self->{username}), pass => $self->{password}, protover => 3, client => CLIENT_NAME, clientver => CLIENT_VER, nat => 1, enc => "UTF8", comp => 1});
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement