App-MHFS
view release on metacpan or search on metacpan
lib/MHFS/Plugin/Kodi.pm view on Meta::CPAN
$resolve->();
});
});
}
sub DirectoryRoute {
my ($path_without_end_slash, $cb) = @_;
return ([
$path_without_end_slash, sub {
my ($request) = @_;
$request->SendRedirect(301, substr($path_without_end_slash, rindex($path_without_end_slash, '/')+1).'/');
}
], [
"$path_without_end_slash/*", $cb
]);
}
sub route_metadata {
my ($self, $request) = @_;
my $request_path = do {
try { decode_utf_8($request->{path}{unsafepath}) }
catch($e) {
warn "$request->{path}{unsafepath} is not, UTF-8, 400";
$request->Send400;
return;
}
};
my ($mediatype, $metadatatype, $medianame, $season, $episode) = $request_path =~ m!^/kodi/metadata/(movies|tv)/(thumb|fanart|plot)/([^/]+)(?:/0*(\d+)(?:/0*(\d+))?)?$! or do {
say "no match";
$request->Send400;
return;
};
if ($medianame =~ /^.(.)?$/ || ($mediatype eq 'movies' && defined $season)) {
say "no match";
$request->Send400;
return;
}
if ($metadatatype eq 'fanart') {
($season, $episode) = (undef, undef);
}
$medianame = fold_case($medianame);
say "mt $mediatype mmt $metadatatype mn $medianame". (defined $season ? " season $season". (defined $episode ? " episode $episode" : '') : '');
my %allmediaparams = ( 'movies' => {
'meta' => $self->{moviemeta},
'search' => 'movie',
}, 'tv' => {
'meta' => $self->{tvmeta},
'search' => 'tv'
});
my $params = $allmediaparams{$mediatype};
my $b_metadir = $params->{meta} . '/' . encode_utf8($medianame) . (defined $season ? '/'.encode_utf8($season). (defined $episode ? '/'.encode_utf8($episode) : '') : '');
my $b_plotfile = $params->{meta} . '/' . encode_utf8($medianame) . '/'. (defined $season ? encode_utf8($season).'/season.json' : 'plot.txt');
# fast path, check disk
if (defined $season && $metadatatype eq 'plot') {
try {
my $bytes = read_file($b_plotfile);
my $json = decode_json($bytes);
if (defined $episode) {
$json = MHFS::Kodi::Season::_get_season_episode($json, $episode);
}
$request->SendText('text/plain; charset=utf-8', $json->{overview});
return;
} catch ($e){}
} elsif (-d $b_metadir) {
my %acceptable = ( 'thumb' => ['png', 'jpg'], 'fanart' => ['png', 'jpg'], 'plot' => ['txt']);
if(exists $acceptable{$metadatatype}) {
foreach my $totry (@{$acceptable{$metadatatype}}) {
my $path = $b_metadir.'/'.$metadatatype.".$totry";
if(-f $path) {
$request->SendLocalFile($path);
return;
}
}
}
}
# slow path, download it
$request->{client}{server}{settings}{TMDB} or do {
$request->Send404;
return;
};
# find the movie or tv show
my $searchname = $medianame;
$searchname =~ s/\s\(\d\d\d\d\)// if($mediatype eq 'movies');
say "searchname $searchname";
weaken($request);
_TMDB_api_promise($request->{client}{server}, 'search/'.$params->{search}, {'query' => $searchname})->then(sub {
my $json = $_[0]->{results}[0];
$json or die "Failed to find item";
$season // return $json;
# find the season and then the episode if applicable
my $showid = $json->{id} // die "showid not available";
_TMDB_api_promise($request->{client}{server}, "tv/$showid/season/$season")->then(sub {
if ($metadatatype eq 'plot' || ! -f $b_plotfile) {
make_path($b_metadir);
my $bytes = encode_json($_[0]);
try { write_file($b_plotfile, $bytes) }
catch ($e) { say "wierd, creating file failed?"; }
}
$episode // return $_[0];
MHFS::Kodi::Season::_get_season_episode($_[0], $episode)
})
})->then(sub {
# get the metadata
if (! defined $season && ($metadatatype eq 'plot' || ! -f "$b_metadir/plot.txt")) {
make_path($b_metadir);
try { write_text_file_lossy("$b_metadir/plot.txt", $_[0]->{overview}) }
catch ($e) { say "wierd, creating file failed?"; }
}
if($metadatatype eq 'plot') {
$request->SendText('text/plain; charset=utf-8', $_[0]->{overview});
return;
}
# thumb or fanart
my $imagepartial = ($metadatatype eq 'thumb') ? (! defined $episode ? $_[0]->{poster_path} : $_[0]->{still_path}) : $_[0]->{backdrop_path};
if (!$imagepartial || $imagepartial !~ /(\.[^\.]+)$/) {
die 'path not matched '.$imagepartial;
}
my $ext = $1;
make_path($b_metadir);
return MHFS::Promise->new($request->{client}{server}{evp}, sub {
my ($resolve, $reject) = @_;
if(! defined $self->{tmdbconfig}) {
$resolve->(_TMDB_api_promise($request->{client}{server}, 'configuration')->then( sub {
$self->{tmdbconfig} = $_[0];
return $_[0];
}));
} else {
$resolve->();
}
})->then( sub {
return _DownloadFile_promise($request->{client}{server}, $self->{tmdbconfig}{images}{secure_base_url}.'original'.$imagepartial, "$b_metadir/$metadatatype$ext")->then(sub {
$request->SendLocalFile("$b_metadir/$metadatatype$ext");
return;
});
});
})->then(undef, sub {
print $_[0];
$request->Send404;
return;
});
return;
}
sub new {
my ($class, $settings) = @_;
my $self = {};
bless $self, $class;
my @subsystems = ('video');
$self->{moviemeta} = $settings->{'DATADIR'}.'/movies';
$self->{tvmeta} = $settings->{'DATADIR'}.'/tv';
make_path($self->{moviemeta}, $self->{tvmeta});
$self->{'routes'} = [
DirectoryRoute('/kodi/movies', sub {
my ($request) = @_;
route_movies($self, $request, $settings->{'MEDIASOURCES'}{'movies'}, '/kodi/movies');
}),
DirectoryRoute('/kodi/tv', sub {
my ($request) = @_;
route_tv($self, $request, $settings->{'MEDIASOURCES'}{'tv'}, '/kodi/tv');
}),
['/kodi/metadata/*', sub {
my ($request) = @_;
route_metadata($self, $request);
}],
DirectoryRoute('/kodi', sub {
my ($request) = @_;
route_kodi($self, $request, '/kodi');
}),
( run in 1.443 second using v1.01-cache-2.11-cpan-39bf76dae61 )