227 lines
6.1 KiB
Perl
227 lines
6.1 KiB
Perl
#! /usr/bin/perl -w
|
|
|
|
use Getopt::Long;
|
|
use Pod::Usage;
|
|
|
|
my $help = 0;
|
|
my $usage = 0;
|
|
my $dryrun = 0;
|
|
my $verbose = 0;
|
|
my $path = '';
|
|
my $annex = '';
|
|
my $home = $ENV{'HOME'};
|
|
|
|
sub main() {
|
|
checkargs();
|
|
if (!$path) {
|
|
$path = $home . '/.xbmc/userdata/Database';
|
|
}
|
|
print("# checking XBMC directory '$path'\n") if ($verbose);
|
|
$dbpath = finddb($path);
|
|
if (!$dbpath) {
|
|
pod2usage("$0: can't find a XBMC database in '$path'.");
|
|
}
|
|
print("# using database '$dbpath'\n") if ($verbose);
|
|
checkdb();
|
|
}
|
|
|
|
# list videos database, find the latest one
|
|
# modified version of
|
|
# http://stackoverflow.com/questions/4651092/getting-the-list-of-files-sorted-by-modification-date-in-perl
|
|
sub finddb($) {
|
|
my $path = shift(@_);
|
|
opendir my($dirh), $path or die "can't opendir $path: $!";
|
|
my @flist = sort { -M $a <=> -M $b } # Sort by modification time
|
|
map { "$path/$_" } # We need full paths for sorting
|
|
grep { /^MyVideos.*\.db$/ }
|
|
readdir $dirh;
|
|
closedir $dirh;
|
|
if ($#flist > 0) {
|
|
return $flist[0];
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
sub checkargs() {
|
|
pod2usage(1) if $help;
|
|
pod2usage(-exitval => 0, -verbose => 2) if $usage;
|
|
|
|
GetOptions('h|?' => \$help,
|
|
'help|usage' => \$usage,
|
|
# we want to operate on relative links, so set this to
|
|
# the common annex to the git annex repo
|
|
'annex=s' => \$annex,
|
|
'path=s' => \$path,
|
|
'home=s' => \$home,
|
|
'dryrun|n' => \$dryrun,
|
|
'verbose|v' => \$verbose,
|
|
)
|
|
or die("Error parsing commandline\n");
|
|
}
|
|
|
|
sub checkdb() {
|
|
my @lines = `echo 'SELECT playCount, path.strPath, files.strFileName FROM movie JOIN files ON files.idFile=movie.idFile JOIN path ON path.idPath=files.idPath;' | sqlite3 $dbpath`;
|
|
print "# finding files...\n" if $verbose;
|
|
for (@lines) {
|
|
my ($count, $dir, $file) = split /\|/;
|
|
chomp $file;
|
|
# empty or non-numeric count is zero
|
|
if ($count !~ /[0-9]/) {
|
|
$count = 0;
|
|
}
|
|
print "# $dir/$file\n" if $verbose;
|
|
if ($file =~ s#stack://##) {
|
|
for (split /,/, $file) {
|
|
s/$annex//;
|
|
s/^ //;
|
|
s/ $//;
|
|
my @cmd = (qw(git annex metadata --set), "playCount=$count", $_);
|
|
if ($dryrun) {
|
|
print join(' ', @cmd) . "\n";
|
|
}
|
|
else {
|
|
system(@cmd);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
$dir =~ s/$annex//;
|
|
my @cmd = (qw(git annex metadata --set), "playCount=$count", "$dir$file");
|
|
if ($dryrun) {
|
|
print join(' ', @cmd) . "\n";
|
|
}
|
|
else {
|
|
system(@cmd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
main();
|
|
|
|
__END__
|
|
=encoding utf8
|
|
|
|
=head1 NAME
|
|
|
|
git-annex-xbmc-playcount - register XBMC playcounts as git-annex metadata
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
git-annex-xbmc-playcount [--path .xbmc/userdata/Database]
|
|
|
|
Options:
|
|
-h short usage
|
|
--help complete help
|
|
--dryrun, -n do nothing and show the commands that would be ran
|
|
--annex path to the git-annex repo
|
|
--home the home directory where the .xbmc directory is located
|
|
--path the location of the Database directory of XBMC, overrides --home
|
|
--verbose show interaction details with the database
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
This program will look into the XBMC database for the "playcount"
|
|
field to register that number as metadata in the git-annex repository.
|
|
|
|
=head1 OPTIONS
|
|
|
|
=over 8
|
|
|
|
=item B<--dryrun>
|
|
|
|
Do nothing but show all the steps that would be ran. The output can be
|
|
piped through a POSIX shell after inspection. B<-n> is an alias of
|
|
this command. Example:
|
|
|
|
git-annex-xbmc-playcount -n | tee runme
|
|
# inspect the output
|
|
sh < runme
|
|
|
|
=item B<--annex>
|
|
|
|
This option allows the user to specify the root of the git-annex
|
|
repository, which is then stripped off the paths found in the XBMC
|
|
database.
|
|
|
|
=item B<--home>
|
|
|
|
Home of the user running XBMC. If not specified, defaults to the $HOME
|
|
environment variables. The script will look into
|
|
B<$home/.xbmc/userdata/Database> for a file matching
|
|
B<^MyVideos.*\.db$> and will fail if none is found.
|
|
|
|
=item B<--path>
|
|
|
|
Manually specify the path to B<.xbmc/userdata/Database>. This
|
|
overrides B<--home>.
|
|
|
|
Note that this doesn't point directly to the datbase itself, because
|
|
there are usually many database files and we want to automatically
|
|
find the latest. This may be a stupid limitation.
|
|
|
|
=item B<--verbose>
|
|
|
|
Show more information about path discovery. Doesn't obstruct
|
|
B<--dryrun> output because lines are prefixed with C<#>.
|
|
|
|
=back
|
|
|
|
=head1 EXAMPLES
|
|
|
|
You have a git annex in B</srv/video> and XBMC is ran as the
|
|
B<video> user and you want to be cautious:
|
|
|
|
$ ./git-annex-xbmc-playcount.pl --home /home/video/ -n --annex /srv/video/ | tee set-metadata
|
|
git annex metadata --set playCount=0 films/Animal.Farm.1954.DVDRip.DivX-MDX.avi
|
|
|
|
This looks about right, set the metadata:
|
|
|
|
$ git annex metadata --set playCount=0 films/Animal.Farm.1954.DVDRip.DivX-MDX.avi
|
|
metadata films/Animal.Farm.1954.DVDRip.DivX-MDX.avi
|
|
lastchanged=2014-10-04@22-17-42
|
|
playCount=0
|
|
playCount-lastchanged=2014-10-04@22-17-42
|
|
ok
|
|
(Recording state in git...)
|
|
|
|
=head1 ENVIRONMENT
|
|
|
|
B<$HOME> is looked into to find the B<.xbmc> home directory if none of
|
|
B<--home> or B<--path> is specified.
|
|
|
|
=head1 FILES
|
|
|
|
=over 8
|
|
|
|
=item B<$HOME/.xbmc/userdata/Database/MyVideos.*\.db>
|
|
|
|
This is where we assume the SQLite database of videos XBMC uses is
|
|
stored.
|
|
|
|
=back
|
|
|
|
=head1 BUGS
|
|
|
|
If there are pipes (C<|>) in filenames, the script may fail to find
|
|
the files properly. We would need to rewrite the database code to use
|
|
B<DBD::SQLite>(3pm) instead of a pipe to B<sqlite3>(1).
|
|
|
|
=head1 LIMITATIONS
|
|
|
|
It took longer writing this help than writing the stupid script.
|
|
|
|
The script will not tag files not yet detected by XBMC.
|
|
|
|
The script is not incremental, so it will repeatedly add the same
|
|
counts to files it has already found.
|
|
|
|
=head1 SEE ALSO
|
|
|
|
B<git-annex>(1), B<xbmc>(1)
|
|
|
|
=head1 AUTHOR
|
|
|
|
Written by Antoine Beaupré <anarcat@debian.org>
|