package AniDB::Manager;
use 5.024;
use Moo;
use experimental 'signatures';
use Log::Any '$log';
use Path::Tiny;
use namespace::clean;
has datastore => (
is => 'ro',
required => 1,
);
has api_client => (
is => 'ro',
required => 1,
);
around BUILDARGS => sub($orig,$class,@args) {
my $args = $class->$orig(@args);
if (my $db_name = $args->{database}) {
require AniDB::Datastore;
$args->{datastore} = AniDB::Datastore->new({
database => $db_name,
});
}
if (my $username = $args->{username}) {
require AniDB::APIClient;;
$args->{api_client} = AniDB::APIClient->new({
%{$args}{qw(username password)},
});
}
return $args;
};
has renamer => (
is => 'ro',
lazy => 1,
);
sub _build_renamer {
require AniDB::Renamer;
return AniDB::Renamer->new();
}
has hash_function => (
is => 'ro',
lazy => 1,
);
sub _build_hash_function {
require AniDB::Hashing;
return \&AniDB::Hashing::hash_fh;
}
sub new_name_for($self,$path) {
$path = path($path)->realpath;
$self->update($path);
my $full_info = $self->datastore->full_info_for($path);
return $self->renamer->new_name_for($path,$full_info);
}
sub maybe_new_name_for($self,$path) {
my $new_name = $self->new_name_for($path);
return if $new_name eq $path;
return $new_name;
}
sub rename($self,$path,$new_path = undef) {
$path = path($path)->realpath;
$new_path ||= $self->new_name_for($path);
if (
$new_path->parent->mkpath
&& $path->move($new_path)
) {
$self->datastore->rename($path,$new_path);
return 1;
}
else {
$log->errorf(
'failed to rename %s to %s',
$path, $new_path,
);
return;
}
}
sub update($self,$path) {
$path = path($path)->realpath;
my $stat = $path->stat;
return unless $self->datastore->has_changed($path,$stat);
my $hash = $self->hash_function->($path->openr_raw);
$self->datastore->update_path_info(
$path => my $path_info = {
size => $stat->size,
mtime => $stat->mtime,
hash => $hash,
},
);
my $episode_info = $self->datastore->episode_info_for($path_info);
unless ($episode_info) {
$episode_info = $self->api_client->episode_info_for($path_info);
$self->datastore->update_episode_info(
$path_info, $episode_info,
);
}
my $anime_info = $self->datastore->anime_info_for($episode_info);
unless ($anime_info) {
$anime_info = $self->api_client->anime_info_for($episode_info);
$self->datastore->update_anime_info(
$episode_info, $anime_info,
);
}
}
1;