Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- # 2010 Z. Cliffe Schreuders
- # free software: GPL v3 or later
- #
- # sorts tv shows into tvshow/series directories
- # if the dirs don't exist they are created
- # updates xbmc via the web interface
- # unsorted files are moved to a dir if specifed
- #
- # other contributers:
- # salithus - xbmc forum
- # schmoko - xbmc forum
- #
- # Please goto the xbmc forum to discuss SortTV:
- # http://forum.xbmc.org/showthread.php?t=75949
- #
- # Get the latest version from here:
- # http://sourceforge.net/projects/sorttv/files/
- #
- # Cliffe's website:
- # http://schreuders.org/
- #
- # Please consider a $5 donation if you find this program helpful.
- use File::Copy::Recursive "dirmove", "dircopy";
- use File::Copy;
- use File::Glob ':glob';
- use LWP::Simple;
- use File::Spec::Functions "rel2abs";
- use File::Basename;
- use TVDB::API;
- use File::Find;
- use FileHandle;
- use warnings;
- use strict;
- my ($sortdir, $tvdir, $nonepisodedir, $xbmcwebserver, $matchtype);
- my ($showname, $series, $episode, $pureshowname) = "";
- my ($newshows, $new, $log);
- my $REDO_FILE = my $moveseasons = "TRUE";
- my $usedots = my $rename = my $logfile = my $verbose = my $seasondoubledigit = my $removesymlinks = my $needshowexist = my $windowsnames = 0;
- my $seasontitle = "Season ";
- my $sortby = "MOVE";
- my $renameformat = "[SHOW_NAME] - [EP1][EP_NAME1]";
- my $treatdir = "RECURSIVELY_SORT_CONTENTS";
- my $fetchimages = "NEW_SHOWS";
- my $imagesformat = "POSTER";
- my @showrenames;
- my $scriptpath = dirname(rel2abs($0));
- my $tvdblanguage = "en";
- print "Got torough the declirations";
- out("std", "SortTV\n", "~" x 6,"\n");
- get_config_from_file("$scriptpath/sorttv.conf");
- process_args(@ARGV);
- if(!defined($sortdir) || !defined($tvdir)) {
- out("warn", "Incorrect usage or configuration (missing sort or sort-to directories)\n");
- out("warn", "run 'perl sorttv.pl --help' for more information about how to use SortTV");
- exit;
- }
- print "Got torough the first if";
- my $TVDBAPIKEY = "FDDBDB916D936956";
- my $tvdb = TVDB::API::new($TVDBAPIKEY);
- # if uses thetvdb, set it up
- if($renameformat =~ /\[EP_NAME\d]/i || $fetchimages ne "FALSE") {
- $tvdb->setLang($tvdblanguage);
- my $hashref = $tvdb->getAvailableMirrors();
- $tvdb->setMirrors($hashref);
- $tvdb->chooseMirrors();
- unless (-e "$scriptpath/.cache" || mkdir "$scriptpath/.cache") {
- out("warn", "WARN: Could not create cache dir: $scriptpath/cache $!\n");
- exit;
- }
- $tvdb->setCacheDB("$scriptpath/.cache/.tvdb.db");
- $tvdb->setUserAgent("SortTV");
- $tvdb->setBannerPath("$scriptpath/.cache/");
- }
- print "Got torough the second if";
- $log = FileHandle->new("$logfile", "a") or out("warn", "WARN: Could not open log file $logfile: $!\n") if $logfile;
- display_info();
- sort_directory($sortdir);
- if($xbmcwebserver && $newshows) {
- sleep(4);
- get "http://$xbmcwebserver/xbmcCmds/xbmcHttp?command=ExecBuiltIn(Notification(,NEW EPISODES NOW AVAILABLE TO WATCH\n$newshows, 7000))";
- }
- $log->close if(defined $log);
- exit;
- print "Got torough the third if";
- sub sort_directory {
- my ($sortd) = @_;
- FILE: foreach my $file (bsd_glob($sortd.'*')) {
- $showname = "";
- # Regex for tv show season directory
- if(-l $file) {
- if($removesymlinks eq "TRUE") {
- out("std", "DELETE: Removing symlink: $file\n");
- unlink($file) or out("warn", "WARN: Could not delete symlink $file: $!\n");
- }
- # otherwise file is a symlink, ignore
- } elsif(-d $file && $treatdir eq "IGNORE") {
- # ignore directories
- } elsif(-d $file && $treatdir eq "RECURSIVELY_SORT_CONTENTS") {
- sort_directory("$file/");
- # removes any empty directories from the to-sort directory and sub-directories
- finddepth(sub{rmdir},"$sortd");
- } elsif(-d $file && $file =~ /.*\/(.*)(?:Season|Series|$seasontitle)\D?0*(\d+).*/i && $1) {
- $pureshowname = $1;
- if($seasondoubledigit eq "TRUE") {
- $series = sprintf("%02d", $2);
- } else {
- $series = $2;
- }
- $showname = fixtitle($pureshowname);
- if(move_series($pureshowname, $showname, $series, $file) eq $REDO_FILE) {
- redo FILE;
- }
- # Regex for tv show episode: S01E01 or 1x1 or 1 x 1 etc
- } elsif(filename($file) =~ /(.*)(?:\.|\s)[Ss]0*(\d+)\s*[Ee]0*(\d+).*/
- || filename($file) =~ /(.*)(?:\.|\s)0*(\d+)\s*[xX]\s*0*(\d+).*/
- || ($matchtype eq "LIBERAL" && filename($file) =~ /(.*)(?:\.|\s)0*(\d+)\D*0*(\d+).*/)) {
- $pureshowname = $1;
- $showname = fixtitle($pureshowname);
- if($seasondoubledigit eq "TRUE") {
- $series = sprintf("%02d", $2);
- } else {
- $series = $2;
- }
- $episode = $3;
- if($showname ne "") {
- if(move_episode($pureshowname, $showname, $series, $episode, $file) eq $REDO_FILE) {
- redo FILE;
- }
- }
- } elsif(defined $nonepisodedir) {
- my $newname = $file;
- $newname =~ s/$sortdir//;
- $newname = escape_myfilename($newname);
- out("std", "MOVING NON-EPISODE: $file to $nonepisodedir$newname\n");
- if(-d $file) {
- dirmove($file, $nonepisodedir . $newname) or out("warn", "WARN: File $file cannot be copied to $nonepisodedir. : $!");
- } else {
- move($file, $nonepisodedir . $newname) or out("warn", "WARN: File $file cannot be copied to $nonepisodedir. : $!");
- }
- }
- }
- }
- print "Got torough the main sort";
- sub process_args {
- foreach my $arg (@_) {
- if($arg =~ /^--non-episode-dir:(.*)/ || $arg =~ /^-ne:(.*)/) {
- if(-e $1) {
- $nonepisodedir = $1;
- # append a trailing / if it's not there
- $nonepisodedir .= '/' if($nonepisodedir !~ /\/$/);
- } else {
- out("warn", "WARN: Non-episode directory does not exist ($1)\n");
- }
- } elsif($arg =~ /^--xbmc-web-server:(.*)/ || $arg =~ /^-xs:(.*)/) {
- $xbmcwebserver = $1;
- } elsif($arg =~ /^--match-type:(.*)/ || $arg =~ /^-mt:(.*)/) {
- $matchtype = $1;
- } elsif($arg =~ /^--treat-directories:(.*)/ || $arg =~ /^-td:(.*)/) {
- $treatdir = $1;
- } elsif($arg =~ /^--show-name-substitute:(.*-->.*)/ || $arg =~ /^-sub:(.*-->.*)/) {
- push @showrenames, $1;
- } elsif($arg =~ /^--log-file:(.*)/ || $arg =~ /^-o:(.*)/) {
- $logfile = $1;
- } elsif($arg =~ /^--rename-episodes:(.*)/ || $arg =~ /^-rn:(.*)/) {
- $rename = $1;
- } elsif($arg =~ /^--lookup-language:(.*)/ || $arg =~ /^-lang:(.*)/) {
- $tvdblanguage = $1;
- } elsif($arg =~ /^--fetch-images:(.*)/ || $arg =~ /^-fi:(.*)/) {
- $fetchimages = $1;
- } elsif($arg =~ /^--images-format:(.*)/ || $arg =~ /^-if:(.*)/) {
- $imagesformat = $1;
- } elsif($arg =~ /^--require-show-directories-already-exist:(.*)/ || $arg =~ /^-rs:(.*)/) {
- $needshowexist = $1;
- } elsif($arg =~ /^--force-windows-compatible-filenames:(.*)/ || $arg =~ /^-fw:(.*)/) {
- $windowsnames = $1;
- } elsif($arg =~ /^--rename-format:(.*)/ || $arg =~ /^-rf:(.*)/) {
- $renameformat = $1;
- } elsif($arg =~ /^--remove-symlinks:(.*)/ || $arg =~ /^-rs:(.*)/) {
- $removesymlinks = $1;
- } elsif($arg =~ /^--use-dots-instead-of-spaces:(.*)/ || $arg =~ /^-dots:(.*)/) {
- $usedots = $1;
- } elsif($arg =~ /^--season-title:(.*)/ || $arg =~ /^-st:(.*)/) {
- $seasontitle = $1;
- } elsif($arg =~ /^--sort-by:(.*)/ || $arg =~ /^-by:(.*)/) {
- $sortby = $1;
- } elsif($arg =~ /^--season-double-digits:(.*)/ || $arg =~ /^-sd:(.*)/) {
- $seasondoubledigit = $1;
- } elsif($arg =~ /^--verbose:(.*)/ || $arg =~ /^-v:(.*)/) {
- $verbose = $1;
- } elsif($arg =~ /^--read-config-file:(.*)/ || $arg =~ /^-conf:(.*)/) {
- get_config_from_file($1);
- } elsif($arg =~ /^--directory-to-sort:(.*)/ || $arg =~ /^-sort:(.*)/) {
- if(-e $1) {
- $sortdir = $1;
- # append a trailing / if it's not there
- $sortdir .= '/' if($sortdir !~ /\/$/);
- } else {
- out("warn", "WARN: Directory to sort does not exist ($1)\n");
- }
- } elsif($arg =~ /^--directory-to-sort-into:(.*)/ || $arg =~ /^-sortto:(.*)/) {
- if(-e $1) {
- $tvdir = $1;
- # append a trailing / if it's not there
- $tvdir .= '/' if($tvdir !~ /\/$/);
- } else {
- out("warn", "WARN: Directory to sort into does not exist ($1)\n");
- }
- } elsif($arg eq "--help" || $arg eq "-h") {
- showhelp();
- } elsif(!defined($sortdir)) {
- if(-e $arg) {
- $sortdir = $arg;
- # append a trailing / if it's not there
- $sortdir .= '/' if($sortdir !~ /\/$/);
- } else {
- out("warn", "WARN: Directory to sort does not exist ($arg)\n");
- }
- } elsif(!defined($tvdir)) {
- if(-e $arg) {
- $tvdir = $arg;
- # append a trailing / if it's not there
- $tvdir .= '/' if($tvdir !~ /\/$/);
- } else {
- out("warn", "Directory to sort into does not exist ($arg)\n");
- }
- } else {
- out("warn", "WARN: Incorrect usage (invalid option): $arg\n");
- out("warn", "INFO: run 'perl sorttv.pl --help' for more information about how to use SortTV");
- }
- }
- }
- print "Got torough the aug";
- sub get_config_from_file {
- my ($filename) = @_;
- my @arraytoconvert;
- if(open (IN, $filename)) {
- out("verbose", "INFO: Reading configuration settings from '$filename'\n");
- while(my $in = <IN>) {
- chomp($in);
- if($in =~ /^\s*#/ || $in =~ /^\s*$/) {
- # ignores comments and whitespace
- } elsif($in =~ /(.+):(.+)/) {
- process_args("--$1:$2");
- } else {
- out("warn", "WARN: this line does not match expected format: '$in'\n");
- }
- }
- close (IN);
- } else {
- out("warn", "WARN: Couldn't open config file '$filename': $!\n");
- out("warn", "INFO: An example config file is available and can make using SortTV easier\n");
- }
- }
- print "Got torough the config file";
- sub showhelp {
- my $heredoc = <<END;
- Usage: sorttv.pl [OPTIONS] [directory-to-sort directory-to-sort-into]
- By default SortTV tries to read the configuration from sorttv.conf
- (an example config file is available online)
- You can overwrite any config options with commandline arguments, which match the format of the config file (except that each argument starts with "--")
- OPTIONS:
- --directory-to-sort:dir
- A directory containing files to sort
- For example, set this to where completed downloads are stored
- --directory-to-sort-into:dir
- Where to sort episodes into (dir that will contain dirs for each show)
- This directory will contain the structure (Show)/(Seasons)/(episodes)
- --non-episode-dir:dir
- Where to put things that are not episodes
- If this is supplied then files and directories that SortTV does not believe are episodes will be moved here
- If not specified, non-episodes are not moved
- --xbmc-web-server:host:port
- host:port for xbmc webserver, to automatically update library when new episodes arrive
- Remember to enable the webserver within xbmc, and "set the content" of your TV directory in xbmc.
- If not specified, xbmc is not updated
- --log-file:filepath
- Log to this file
- If not specified, output only goes to stdout (the screen)
- --verbose:[TRUE|FALSE]
- Output verbosity. Set to TRUE to show messages describing the decision making process.
- If not specified, FALSE
- --read-config-file:filepath
- Secondary config file, overwrites settings loaded so far
- If not specified, only the default config file is loaded (sorttv.conf)
- --rename-episodes:[TRUE|FALSE]
- Rename episodes to "show name S01E01.ext" format when moving
- If not specified, FALSE
- --rename-format:{formatstring}
- the format to use if renaming to a new format (as specified above)
- Hint: including the Episode Title as part of the name slows the process down a bit since titles are retrieved from thetvdb.com
- The formatstring can be made up of:
- [SHOW_NAME]: "My Show"
- [EP1]: "S01E01"
- [EP2]: "1x1"
- [EP3]: "1x01"
- [EP_NAME1] " - Episode Title"
- [EP_NAME2] ".Episode Title"
- If not specified the format is "[SHOW_NAME] - [EP1][EP_NAME1]"
- For example:
- for "My Show S01E01 - Episode Title" (this is the default)
- --rename-format:[SHOW_NAME] - [EP1][EP_NAME1]
- for "My Show.S01E01.Episode Title"
- --rename-format:[SHOW_NAME].[EP1][EP_NAME2]
- --use-dots-instead-of-spaces:[TRUE|FALSE]
- Renames episodes to replace spaces with dots
- If not specified, FALSE
- --season-title:string
- Season title
- Note: if you want a space it needs to be included
- (eg "Season " -> "Season 1", "Series "->"Series 1", "Season."->"Season.1")
- If not specified, "Season "
- --season-double-digits:[TRUE|FALSE]
- Season format padded to double digits (eg "Season 01" rather than "Season 1")
- If not specified, FALSE
- --match-type:[NORMAL|LIBERAL]
- Match type.
- LIBERAL assumes all files are episodes and tries to extract season and episode number any way possible.
- If not specified, NORMAL
- --sort-by:[MOVE|COPY|MOVE-AND-LEAVE-SYMLINK-BEHIND|LEAVE-AND-PLACE-SYMLINK]
- Sort by moving or copying the file. If the file already exists because it was already copied it is silently skipped.
- The MOVE-AND-LEAVE-SYMLINK-BEHIND option may be handy if you want to continue to seed after sorting, this leaves a symlink in place of the newly moved file.
- PLACE-SYMLINK does not move the original file, but places a symlink in the sort-to directory (probably not what you want)
- If not specified, MOVE
- --treat-directories:[AS_FILES_TO_SORT|RECURSIVELY_SORT_CONTENTS|IGNORE]
- How to treat directories.
- AS_FILES_TO_SORT - sorts directories, moving entire directories that represents an episode, also detects and moves directories of entire seasons
- RECURSIVELY_SORT_CONTENTS - doesn't move directories, just their contents, including subdirectories
- IGNORE - ignores directories
- If not specified, RECURSIVELY_SORT_CONTENTS
- --require-show-directories-already-exist:[TRUE|FALSE]
- Only sort into show directories that already exist
- This may be helpful if you have multiple destination directories. Just set up all the other details in the conf file,
- and specify the destination directory when invoking the script. Only episodes that match existing directories in the destination will be moved.
- If this is false, then new directories are created for shows that dont have a directory.
- If not specified, FALSE
- --remove-symlinks:[TRUE|FALSE]
- Deletes symlinks from the directory to sort while sorting.
- This may be helpful if you want to remove all the symlinks you previously left behind using --sort-by:MOVE-AND-LEAVE-SYMLINK-BEHIND
- You could schedule "perl sorttv.pl --remove-symlinks:TRUE" to remove these once a week/month
- If this option is enabled and used at the same time as --sort-by:MOVE-AND-LEAVE-SYMLINK-BEHIND,
- then only the previous links will be removed, and new ones may also be created
- If not specified, FALSE
- --show-name-substitute:NAME1-->NAME2
- Substitutes files equal to NAME1 for NAME2
- This argument can be repeated to add multiple rules for substitution
- --force-windows-compatible-filenames:[TRUE|FALSE]
- Forces MSWindows compatible file names, even when run on other platforms such as Linux
- This may be helpful if you are writing to a Windows share from a Linux system
- If not specified, FALSE
- --lookup-language:[en|...]
- Set language for thetvdb lookups, this effects episode titles etc
- Valid values include: it, zh, es, hu, nl, pl, sl, da, de, el, he, sv, eng, fi, no, fr, ru, cs, en, ja, hr, tr, ko, pt
- If not specified, en (English)
- --fetch-images:[NEW_SHOWS|FALSE]
- Download images for shows, seasons, and episodes from thetvdb
- Downloaded images are copied into the sort-to (destination) directory.
- NEW_SHOWS - When new shows, seasons, or episodes are created the associated images are downloaded
- FALSE - No images are downloaded
- if not specified, NEW_SHOWS
- --images-format:POSTER
- Sets the image format to use, poster or banner.
- POSTER/BANNER
- if not specified, POSTER
- EXAMPLES:
- Does a sort, as configured in sorttv.conf:
- perl sorttv.pl
- The directory-to-sort and directory-to-sort-to can be supplied directly:
- To sort a Downloads directory contents into a TV directory
- perl sorttv.pl /home/me/Downloads /home/me/Videos/TV
- Alternatively:
- perl sorttv.pl --directory-to-sort:/home/me/Downloads --directory-to-sort-into:/home/me/Videos/TV
- To move non-episode files in a separate directory:
- perl sorttv.pl --directory-to-sort:/home/me/Downloads --directory-to-sort-into:/home/me/Videos/TV --non-episode-dir:/home/me/Videos/Non-episodes
- To integrate with xbmc (notification and automatic library update):
- perl sorttv.pl --directory-to-sort:/home/me/Downloads --directory-to-sort-into:/home/me/Videos/TV --xbmc-webserver:localhost:8080
- And so on...
- FURTHER INFORMATION:
- Please goto the xbmc forum to discuss SortTV:
- http://forum.xbmc.org/showthread.php?t=75949
- Get the latest version from here:
- http://sourceforge.net/projects/sorttv/files/
- Cliffe's website:
- http://schreuders.org/
- Please consider a \$5 paypal donation if you find this program helpful.
- END
- out("std", $heredoc);
- exit;
- }
- sub displayandupdateinfo {
- my ($show, $xbmcwebserver) = @_;
- # update xbmc video library
- get "http://$xbmcwebserver/xbmcCmds/xbmcHttp?command=ExecBuiltIn(updatelibrary(video))";
- # pop up a notification on xbmc
- # xbmc.executebuiltin('XBMC.Notification(New content found, ' + filename + ', 2000)')
- get "http://$xbmcwebserver/xbmcCmds/xbmcHttp?command=ExecBuiltIn(Notification(NEW EPISODE, $show, 7000))";
- }
- # replaces ".", "_" and removes "the" and ","
- # removes numbers and spaces
- # removes the dir path
- sub fixtitle {
- my ($title) = @_;
- $title = substitute_name($title);
- $title =~ s/,|\.the\.|\bthe\b//ig;
- $title =~ s/\.and\.|\band\b//ig;
- $title =~ s/&|\+//ig;
- $title =~ s/(.*\/)(.*)/$2/;
- $title = remdot($title);
- $title =~ s/\d|\s|\(|\)//ig;
- return $title;
- }
- # substitutes show names as configured
- sub substitute_name {
- my ($from) = @_;
- foreach my $substitute (@showrenames) {
- if($substitute =~ /(.*)-->(.*)/) {
- if($from eq $1) {
- return $2;
- }
- }
- }
- # if no matches, returns unchanged
- return $from;
- }
- # removes dots and underscores for creating dirs
- sub remdot {
- my ($title) = @_;
- $title =~ s/\./ /ig;
- $title =~ s/_/ /ig;
- $title =~ s/-//ig;
- $title =~ s/'//ig;
- # don't start or end on whitespace
- $title =~ s/\s$//ig;
- $title =~ s/^\s//ig;
- return $title;
- }
- # removes path
- sub filename {
- my ($title) = @_;
- $title =~ s/(.*\/)(.*)/$2/;
- return $title;
- }
- sub escape_myfilename {
- my ($name) = @_;
- if($^O =~ /MSWin/ || $windowsnames eq "TRUE") {
- $name =~ s/[\\\/:*?\"<>|]/-/g;
- } else {
- $name =~ s/[\\\/\"<>|]/-/g;
- }
- return $name;
- }
- sub display_info {
- my ($second, $minute, $hour, $dayofmonth, $month, $yearoffset) = localtime();
- my $year = 1900 + $yearoffset;
- my $thetime = "$hour:$minute:$second, $dayofmonth-$month-$year";
- out("std", "$thetime\n");
- out("std", "Sorting $sortdir into $tvdir\n");
- }
- sub move_episode {
- my ($pureshowname, $showname, $series, $episode, $file) = @_;
- out("verbose", "INFO: trying to move $pureshowname season $series episode $episode\n");
- SHOW: foreach my $show (bsd_glob($tvdir.'*')) {
- my $subshowname = fixtitle(escape_myfilename(substitute_name($showname)));
- if(fixtitle($show) =~ /^\Q$showname\E$/i || fixtitle(escape_myfilename(substitute_name(filename($show)))) =~ /^\Q$subshowname\E$/i) {
- out("verbose", "INFO: found a matching show:\n\t$show\n");
- my $s = $show.'/*';
- my @g=bsd_glob($show);
- foreach my $season (bsd_glob($show.'/*')) {
- if(-d $season.'/' && $season =~ /(?:Season|Series|$seasontitle)?\s?0*(\d+)$/i && $1 == $series) {
- out("verbose", "INFO: found a matching season:\n\t$season\n");
- move_an_ep($file, $season, $show, $series, $episode);
- if($xbmcwebserver) {
- $new = "$showname season $series episode $episode";
- displayandupdateinfo($new, $xbmcwebserver);
- $newshows .= "$new\n";
- }
- # next FILE;
- return 0;
- }
- }
- # didn't find a matching season, make DIR
- out("std", "INFO: making season directory: $show/$seasontitle$series\n");
- my $newpath = "$show/$seasontitle$series";
- if(mkdir($newpath, 0777)) {
- fetchseasonimages(substitute_name(remdot($pureshowname)), $show, $series, $newpath) if $fetchimages ne "FALSE";
- redo SHOW; # try again now that the dir exists
- } else {
- out("warn", "WARN: Could not create season dir: $!\n");
- # next FILE;
- return 0;
- }
- }
- }
- if($needshowexist ne "TRUE") {
- # if we are here then we couldn't find a matching show, make DIR
- my $newshowdir = $tvdir . escape_myfilename(substitute_name(remdot($pureshowname)));
- out("std", "INFO: making show directory: $newshowdir\n");
- if(mkdir($newshowdir, 0777)) {
- fetchshowimages(substitute_name(remdot($pureshowname)), $newshowdir) if $fetchimages ne "FALSE";
- # try again now that the dir exists
- # redo FILE;
- return $REDO_FILE;
- } else {
- out("warn", "WARN: Could not create show dir: $newshowdir:$!\n");
- # next FILE;
- return 0;
- }
- } else {
- out("verbose", "SKIP: Show directory does not exist: " . $tvdir . escape_myfilename(substitute_name(remdot($pureshowname)))."\n");
- # next FILE;
- return 0;
- }
- }
- sub fetchshowimages {
- my ($fetchname, $newshowdir) = @_;
- out("std", "DOWNLOAD: downloading images for $fetchname\n");
- my $banner = $tvdb->getSeriesBanner($fetchname);
- my $fanart = $tvdb->getSeriesFanart($fetchname);
- my $poster = $tvdb->getSeriesPoster($fetchname);
- copy ("$scriptpath/.cache/$fanart", "$newshowdir/fanart.jpg") if $fanart && -e "$scriptpath/.cache/$fanart";
- copy ("$scriptpath/.cache/$banner", "$newshowdir/banner.jpg") if $banner && -e "$scriptpath/.cache/$banner";
- copy ("$scriptpath/.cache/$poster", "$newshowdir/poster.jpg") if $poster && -e "$scriptpath/.cache/$poster";
- my $ok = eval{symlink "$newshowdir/poster.jpg", "$newshowdir/folder.jpg" if $poster && -e "$scriptpath/.cache/$poster" && $imagesformat eq "POSTER";};
- if(!defined $ok) {copy "$newshowdir/poster.jpg", "$newshowdir/folder.jpg" if $poster && -e "$scriptpath/.cache/$poster" && $imagesformat eq "POSTER";};
- $ok = eval{symlink "$newshowdir/banner.jpg", "$newshowdir/folder.jpg" if $banner && -e "$scriptpath/.cache/$banner" && $imagesformat eq "BANNER";};
- if(!defined $ok) {copy "$newshowdir/banner.jpg", "$newshowdir/folder.jpg" if $banner && -e "$scriptpath/.cache/$banner" && $imagesformat eq "BANNER";};
- }
- sub fetchseasonimages {
- my ($fetchname, $newshowdir, $season, $seasondir) = @_;
- out("std", "DOWNLOAD: downloading season image for $fetchname\n");
- my $banner = $tvdb->getSeasonBanner($fetchname, $season);
- my $bannerwide = $tvdb->getSeasonBannerWide($fetchname, $season);
- my $snum = sprintf("%02d", $season);
- copy ("$scriptpath/.cache/$banner", "$newshowdir/season${snum}.jpg") if $banner && -e "$scriptpath/.cache/$banner" && $imagesformat eq "POSTER";
- copy ("$scriptpath/.cache/$bannerwide", "$newshowdir/season${snum}.jpg") if $bannerwide && -e "$scriptpath/.cache/$bannerwide" && $imagesformat eq "BANNER";
- my $ok = eval{symlink "$newshowdir/season$snum.jpg", "$seasondir/folder.jpg" if -e "$newshowdir/season$snum.jpg";};
- if(!defined $ok) {copy "$newshowdir/season$snum.jpg", "$seasondir/folder.jpg" if -e "$newshowdir/season$snum.jpg";};
- }
- sub fetchepisodeimage {
- my ($fetchname, $newshowdir, $season, $seasondir, $episode, $newfilename) = @_;
- # if the episode was moved (or already existed)
- if(-e "$seasondir/$newfilename") {
- my $epimage = $tvdb->getEpisodeBanner($fetchname, $season, $episode);
- my $newimagepath = "$seasondir/$newfilename";
- $newimagepath =~ s/(.*)(\..*)/$1.tbn/;
- copy ("$scriptpath/.cache/$epimage", $newimagepath) if $epimage && -e "$scriptpath/.cache/$epimage";
- }
- }
- sub move_an_ep {
- my($file, $season, $show, $series, $episode) = @_;
- my $newfilename = filename($file);
- my $newpath;
- if($rename eq "TRUE") {
- my $ext = my $eptitle = "";
- unless(-d $file) {
- $ext = $file;
- $ext =~ s/(.*\.)(.*)/\.$2/;
- }
- if($renameformat =~ /\[EP_NAME(\d)]/i) {
- out("verbose", "INFO: Fetching episode title for ", substitute_name(remdot($pureshowname)), " Season $series Episode $episode.\n");
- my $name = $tvdb->getEpisodeName(substitute_name(remdot($pureshowname)), $series, $episode);
- if($name) {
- $eptitle = " - $name" if $1 == 1;
- $eptitle = ".$name" if $1 == 2;
- } else {
- out("warn", "WARN: Could not get episode title for ", substitute_name(remdot($pureshowname)), " Season $series Episode $episode.\n");
- }
- }
- my $sname = substitute_name(remdot($pureshowname));
- my $ep1 = sprintf("S%02dE%02d", $series, $episode);
- my $ep2 = sprintf("%dx%d", $series, $episode);
- my $ep3 = sprintf("%dx%02d", $series, $episode);
- # create the new file name
- $newfilename = $renameformat;
- $newfilename =~ s/\[SHOW_NAME]/$sname/ig;
- $newfilename =~ s/\[EP1]/$ep1/ig;
- $newfilename =~ s/\[EP2]/$ep2/ig;
- $newfilename =~ s/\[EP3]/$ep3/ig;
- $newfilename =~ s/\[EP_NAME\d]/$eptitle/ig;
- $newfilename .= $ext;
- # make sure it is filesystem friendly:
- $newfilename = escape_myfilename($newfilename, "-");
- }
- if($usedots eq "TRUE") {
- $newfilename =~ s/\s/./ig;
- }
- $newpath = $season . '/' . $newfilename;
- if(-e $newpath) {
- if(filename($file) =~ /repack|proper/i) {
- out("warn", "OVERWRITE: Repack/proper version.\n");
- } else {
- out("warn", "SKIP: File $newpath already exists, skipping.\n") unless($sortby eq "COPY" || $sortby eq "PLACE-SYMLINK");
- return;
- }
- }
- out("std", "$sortby: sorting $file to ", $newpath, "\n");
- if($sortby eq "MOVE" || $sortby eq "MOVE-AND-LEAVE-SYMLINK-BEHIND") {
- if(-d $file) {
- dirmove($file, $newpath) or out("warn", "File $show cannot be moved to $season. : $!");
- } else {
- move($file, $newpath) or out("warn", "File $show cannot be moved to $season. : $!");
- }
- } elsif($sortby eq "COPY") {
- if(-d $file) {
- dircopy($file, $newpath) or out("warn", "File $show cannot be copied to $season. : $!");
- } else {
- copy($file, $newpath) or out("warn", "File $show cannot be copied to $season. : $!");
- }
- } elsif($sortby eq "PLACE-SYMLINK") {
- symlink($file, $newpath) or out("warn", "File $file cannot be symlinked to $newpath. : $!");
- }
- # have moved now link
- if($sortby eq "MOVE-AND-LEAVE-SYMLINK-BEHIND") {
- symlink($newpath, $file) or out("warn", "File $newpath cannot be symlinked to $file. : $!");
- }
- fetchepisodeimage(substitute_name(remdot($pureshowname)), $show, $series, $season, $episode, $newfilename) if $fetchimages ne "FALSE";
- }
- sub move_a_season {
- my($file, $show, $series) = @_;
- my $newpath = $show."/".escape_myfilename("$seasontitle$series", "-");
- if(-e $newpath) {
- out("warn", "SKIP: File $newpath already exists, skipping.\n") unless($sortby eq "COPY" || $sortby eq "PLACE-SYMLINK");
- return;
- }
- print "$sortby SEASON: $file to $newpath\n";
- out("verbose", "$sortby: sorting directory to: $newpath\n");
- if($sortby eq "MOVE" || $sortby eq "MOVE-AND-LEAVE-SYMLINK-BEHIND") {
- dirmove($file, "$newpath") or out("warn", "$show cannot be moved to $show/$seasontitle$series: $!");
- } elsif($sortby eq "COPY") {
- dircopy($file, "$newpath") or out("warn", "$show cannot be copied to $show/$seasontitle$series: $!");
- } elsif($sortby eq "PLACE-SYMLINK") {
- symlink($file, $newpath) or out("warn", "File $file cannot be symlinked to $newpath. : $!");
- }
- if($sortby eq "MOVE-AND-LEAVE-SYMLINK-BEHIND") {
- symlink($newpath, $file) or out("warn", "File $newpath cannot be symlinked to $file. : $!");
- }
- }
- # move a new Season x directory
- sub move_series {
- my ($pureshowname, $showname, $series, $file) = @_;
- out("verbose", "INFO: trying to move $pureshowname season $series directory\n");
- SHOW: foreach my $show (bsd_glob($tvdir.'*')) {
- if(fixtitle($show) =~ /^\Q$showname\E$/i) {
- out("verbose", "INFO: found a matching show:\n\t$show\n");
- my $s = $show.'/*';
- my @g=bsd_glob($show);
- foreach my $season (bsd_glob($show.'/*')) {
- if(-d $season.'/' && $season =~ /(?:Season|Series|$seasontitle)?\s?0*(\d)$/i && $1 == $series) {
- out("warn", "SKIP: Cannot move season directory: found a matching season already existing:\n\t$season\n");
- return 0;
- }
- }
- # didn't find a matching season, move DIR
- move_a_season($file, $show, $series);
- if($xbmcwebserver) {
- $new = "$showname Season $series directory";
- displayandupdateinfo($new, $xbmcwebserver);
- $newshows .= "$new\n";
- }
- return 0;
- }
- }
- if($needshowexist ne "TRUE") {
- # if we are here then we couldn't find a matching show, make DIR
- my $newshowdir = $tvdir . escape_myfilename(substitute_name(remdot($pureshowname)));
- out("std", "INFO: making show directory: $newshowdir\n");
- if(mkdir($newshowdir, 0777)) {
- fetchshowimages(substitute_name(remdot($pureshowname)), $newshowdir) if $fetchimages ne "FALSE";
- # try again now that the dir exists
- # redo FILE;
- return $REDO_FILE;
- } else {
- out("warn", "WARN: Could not create show dir: $newshowdir:$!\n");
- # next FILE;
- return 0;
- }
- } else {
- out("verbose", "SKIP: Show directory does not exist: " . $tvdir . escape_myfilename(substitute_name(remdot($pureshowname)))."\n");
- # next FILE;
- return 0;
- }
- }
- sub out {
- my ($type, @msg) = @_;
- if($type eq "verbose") {
- return if $verbose ne "TRUE";
- print @msg;
- print $log @msg if(defined $log);
- }elsif($type eq "std") {
- print @msg;
- print $log @msg if(defined $log);
- } elsif($type eq "warn") {
- warn @msg;
- print $log @msg if(defined $log);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement