示例#1
0
 def __init__(self, apikey):
     try:
         self.apikey = apikey
         self.log = TNGLog()
         self.urls['images'] = self.__GetImageURL() + 'original'
     except Exception as e:
         self.log.error(unicode(e))
         raise
示例#2
0
    def __init__(self, RootDestination):
        #Root Folder has to Contain Folders like this A-D, E-G etc.
        if self.__ContainsGroupFolders(RootDestination) is False:
            self.__dstFolders['root'] = RootDestination
        else:
            self.__GetDstFolders(RootDestination)

        self.log = TNGLog()
示例#3
0
class Mover(object):

    __dstFolders = {}
    __IgnoreFolders = ('_', '@')
    dst = u''

    def __init__(self, RootDestination):
        #Root Folder has to Contain Folders like this A-D, E-G etc.
        if self.__ContainsGroupFolders(RootDestination) is False:
            self.__dstFolders['root'] = RootDestination
        else:
            self.__GetDstFolders(RootDestination)

        self.log = TNGLog()

    def move(self, src, forceOverwrite):
        if self.__dstFolders.has_key('root'):
            dst = os.path.join(self.__dstFolders['root'],
                               os.path.basename(src))
        else:
            try:
                dst = os.path.join(self.__ChooseDestination(src),
                                   os.path.basename(src))
            except AttributeError:
                self.log.error('Could not move %s' % os.path.basename(src))
                return False

        if os.path.isdir(dst):
            #There exists already a Movie
            #we compare the resolution or size using the metadata of the movie
            try:
                compare = Comparer(src, dst)

                if compare.hasResolution():
                    if compare.item[src]['resolution'] > compare.item[dst][
                            'resolution']:
                        overwrite = True
                    else:
                        overwrite = False
                else:
                    if compare.item[src]['size'] > compare.item[dst]['size']:
                        overwrite = True
                    else:
                        overwrite = False
            except Exception, e:
                overwrite = False
                self.log.error(unicode(e))

            if overwrite or forceOverwrite:
                self.log.info('Overwriting existing Movie : %s' % dst)
                shutil.rmtree(dst)
                shutil.move(src, dst)
            else:
                self.log.warning(
                    'Existing Movie has same or better quality, ignoring it : %s'
                    % os.path.basename(dst))
                return False

        else:
示例#4
0
 def __init__(self,apikey):
     try:
         self.apikey = apikey
         self.log = TNGLog()
         self.urls['images'] = self.__GetImageURL() + 'original'
     except Exception as e:
         self.log.error(unicode(e))
         raise
示例#5
0
    def __init__(self,RootDestination):
        #Root Folder has to Contain Folders like this A-D, E-G etc.
        if self.__ContainsGroupFolders(RootDestination) is False:
            self.__dstFolders['root'] = RootDestination
        else:
            self.__GetDstFolders(RootDestination)

        self.log = TNGLog()
示例#6
0
class Mover(object):

    __dstFolders = {}
    __IgnoreFolders = ('_','@')
    dst = u''

    def __init__(self,RootDestination):
        #Root Folder has to Contain Folders like this A-D, E-G etc.
        if self.__ContainsGroupFolders(RootDestination) is False:
            self.__dstFolders['root'] = RootDestination
        else:
            self.__GetDstFolders(RootDestination)

        self.log = TNGLog()
        
    def move(self,src,forceOverwrite):
        if self.__dstFolders.has_key('root'):
            dst = os.path.join(self.__dstFolders['root'],os.path.basename(src))
        else:
            try:
                dst = os.path.join(self.__ChooseDestination(src),os.path.basename(src))
            except AttributeError:
                self.log.error('Could not move %s' % os.path.basename(src))
                return False
        
        if os.path.isdir(dst):
            #There exists already a Movie
            #we compare the resolution or size using the metadata of the movie
            try:
                compare = Comparer(src,dst)
	
                if compare.hasResolution():
                    if compare.item[src]['resolution'] > compare.item[dst]['resolution']:
                        overwrite = True
                    else:
                        overwrite = False
                else:
                    if compare.item[src]['size'] > compare.item[dst]['size']:
                        overwrite = True
                    else:
                        overwrite = False
            except Exception, e:
                overwrite = False
                self.log.error(unicode(e))
                
            if overwrite or forceOverwrite:
                self.log.info('Overwriting existing Movie : %s' % dst)
                shutil.rmtree(dst)
                shutil.move(src, dst)
            else:
                self.log.warning('Existing Movie has same or better quality, ignoring it : %s' % os.path.basename(dst))
                return False
                
        else:
示例#7
0
class Comparer(object):
    
    def __init__(self, path1, path2):
        self.log = TNGLog()
        self.item = {}
        if self.addFile(path1) or self.addFile(path2):
            raise Exception("skipping compare: at least one file is missing")
    
    def addFile(self,path):
        m = Movie(path)
        mcont = m.GetMovieFile()
        if not mcont:
            return False
        mfile = os.path.join(path,mcont)
        self.item[path] = {}
        self.item[path]['resolution'] = self.__getResolution(mfile)
        self.item[path]['size'] = os.path.getsize(path)
        
        return True
    
    def hasResolution(self):
        for i in self.item.keys():
            if self.item[i]['resolution'] is False:
                return False
        return True
    
    
    def __getResolution(self,path):

        self.log.debug('Getting Metadata for: %s' % path)
        try:
            p = enzyme.parse(path)
            height = p.video[0].height
            width = p.video[0].width
            return height * width
        except ParseError:
            self.log.warning('Metadata ParseError: %s' % path)
        except:
            self.log.warning('Metadata fetching failed: %s' % path)
        return False
示例#8
0
class Comparer(object):
    def __init__(self, path1, path2):
        self.log = TNGLog()
        self.item = {}
        if self.addFile(path1) or self.addFile(path2):
            raise Exception("skipping compare: at least one file is missing")

    def addFile(self, path):
        m = Movie(path)
        mcont = m.GetMovieFile()
        if not mcont:
            return False
        mfile = os.path.join(path, mcont)
        self.item[path] = {}
        self.item[path]['resolution'] = self.__getResolution(mfile)
        self.item[path]['size'] = os.path.getsize(path)

        return True

    def hasResolution(self):
        for i in self.item.keys():
            if self.item[i]['resolution'] is False:
                return False
        return True

    def __getResolution(self, path):

        self.log.debug('Getting Metadata for: %s' % path)
        try:
            p = enzyme.parse(path)
            height = p.video[0].height
            width = p.video[0].width
            return height * width
        except ParseError:
            self.log.warning('Metadata ParseError: %s' % path)
        except:
            self.log.warning('Metadata fetching failed: %s' % path)
        return False
示例#9
0
 def __init__(self, path1, path2):
     self.log = TNGLog()
     self.item = {}
     if self.addFile(path1) or self.addFile(path2):
         raise Exception("skipping compare: at least one file is missing")
示例#10
0
    parser.add_argument('-v', dest='debugMode', action='store_true', help='Script Output is more verbose')
    parser.add_argument('-n', dest='globalNFOName', type=unicode, required=False,
                        help='Specify a global name for the nfo file')
    parser.add_argument('-l', dest='language', type=unicode, default='de', required=False,
                        help='Language of Movie Infos in ISO 639-1 code Default:German(de)')
    args = parser.parse_args()

    #===========================================================================
    # Logging
    #===========================================================================

    logpath = os.path.abspath(os.path.join(LogFile, os.pardir))
    if not os.path.isdir(logpath):
        os.mkdir(logpath)
    #Create the wrapper log instance
    log = TNGLog()

    formatter = logging.Formatter('%(asctime)s [%(levelname)-8s] %(message)s', '%d-%m-%Y %H:%M:%S')

    #Initialize the File Logger
    hdlr = handlers.RotatingFileHandler(os.path.join(LogFile), 'a', 524288, 10)
    hdlr.setLevel(logging.DEBUG)
    #hdlr.setLevel(logging.DEBUG) if args.debugMode == True else hdlr.setLevel(logging.INFO)
    hdlr.setFormatter(formatter)
    log.logger.addHandler(hdlr)

    #Initialize the Stdout Logger
    hdlr2 = logging.StreamHandler(sys.stdout)
    hdlr2.setFormatter(formatter)
    hdlr2.setLevel(logging.DEBUG) if args.debugMode is True else hdlr2.setLevel(logging.INFO)
    log.logger.addHandler(hdlr2)
示例#11
0
 def __init__(self, server, username=None, password=None):
     self.username = username
     self.password = password
     self.server = server
     self.version = '2.0'
     self.log = TNGLog()
示例#12
0
class tmdb():
    
    urls        = {
                   'search':'/3/search/movie?api_key=%s&query=',
                   'detail':'/3/movie/%s?api_key=%s&language=%s',
                   'config':'/3/configuration?api_key=%s'
                   }
    
    headers = {"Accept": "application/json"}
    
    apikey      = ''
    host        = 'http://api.themoviedb.org'
    port        = 80
    
    def __init__(self,apikey):
        try:
            self.apikey = apikey
            self.log = TNGLog()
            self.urls['images'] = self.__GetImageURL() + 'original'
        except Exception as e:
            self.log.error(unicode(e))
            raise

    def search(self, string):
        """
        :param string: movie name
        :return: imdb id
        """
        self.log.debug('Search String:%s' % string)
        url = self.host + self.urls['search'] % self.apikey + self.__CreateQuery(string)
        self.log.debug('Search URL:%s' % url)
        request = urllib2.Request(url, headers=self.headers)
        resp = urllib2.urlopen(request)
        data = resp.read()
        result = json.loads(data)

        if result['total_results'] == 1:
            return result['results'][0]['id']
        elif result['total_results'] > 1:
            for res in result['results']:
                if res['original_title'] == string:
                    return res['id']
                elif res['title'] == string:
                    return res['id']
        return False

    def GetMovieDetails(self, movieID, lang):
        data = ''
        url = self.host + self.urls['detail'] % (movieID, self.apikey, lang)
        self.log.debug('Search Request: %s' % url)
        try:
            request = urllib2.Request(url, headers=self.headers)
            resp = urllib2.urlopen(request)
            data = resp.read()
        except urllib2.HTTPError:
            self.log.error('HTTPError (searchURL): %s' % url)
        finally:   
            if data != '':
                return data
            else:
                return False

    @staticmethod
    def __CreateQuery(string):
        return string.replace(' ','+').replace('(','').replace(')','')
    
    def __GetImageURL(self):
        url = self.host + self.urls['config'] % self.apikey
        request = urllib2.Request(url, headers=self.headers)
        resp = urllib2.urlopen(request)
        data = json.loads(resp.read())
        return data['images']['base_url']
示例#13
0
class tmdb():

    urls = {
        'search': '/3/search/movie?api_key=%s&query=',
        'detail': '/3/movie/%s?api_key=%s&language=%s',
        'config': '/3/configuration?api_key=%s'
    }

    headers = {"Accept": "application/json"}

    apikey = ''
    host = 'http://api.themoviedb.org'
    port = 80

    def __init__(self, apikey):
        try:
            self.apikey = apikey
            self.log = TNGLog()
            self.urls['images'] = self.__GetImageURL() + 'original'
        except Exception as e:
            self.log.error(unicode(e))
            raise

    def search(self, string):
        """
        :param string: movie name
        :return: imdb id
        """
        self.log.debug('Search String:%s' % string)
        url = self.host + self.urls[
            'search'] % self.apikey + self.__CreateQuery(string)
        self.log.debug('Search URL:%s' % url)
        request = urllib2.Request(url, headers=self.headers)
        resp = urllib2.urlopen(request)
        data = resp.read()
        result = json.loads(data)

        if result['total_results'] == 1:
            return result['results'][0]['id']
        elif result['total_results'] > 1:
            for res in result['results']:
                if res['original_title'] == string:
                    return res['id']
                elif res['title'] == string:
                    return res['id']
        return False

    def GetMovieDetails(self, movieID, lang):
        data = ''
        url = self.host + self.urls['detail'] % (movieID, self.apikey, lang)
        self.log.debug('Search Request: %s' % url)
        try:
            request = urllib2.Request(url, headers=self.headers)
            resp = urllib2.urlopen(request)
            data = resp.read()
        except urllib2.HTTPError:
            self.log.error('HTTPError (searchURL): %s' % url)
        finally:
            if data != '':
                return data
            else:
                return False

    @staticmethod
    def __CreateQuery(string):
        return string.replace(' ', '+').replace('(', '').replace(')', '')

    def __GetImageURL(self):
        url = self.host + self.urls['config'] % self.apikey
        request = urllib2.Request(url, headers=self.headers)
        resp = urllib2.urlopen(request)
        data = json.loads(resp.read())
        return data['images']['base_url']
示例#14
0
    def __init__(
        self,
        #Path to the Folder containing the Movie
        path,
        #Language for the Movie
        language='',
        #ApiKey for TMDB
        apikey='',
    ):

        self.files = {}
        self.newFiles = {}
        self.newFiles['video'] = []
        self.newFiles['nfo'] = []
        self.infos = u''
        self.NFO = u''
        self.nfoname = u''
        self.path = path
        self.log = TNGLog()
        self.id = False

        # Read the configuration
        self.config = ConfigParser()
        self.config.read(os.path.join(os.getcwd(), 'settings.cfg'))

        try:
            #=======================================================================
            # Get Paths for all Items in current movie
            #=======================================================================
            self.files['video'] = self.__GetFileType(
                self.path, ('.mkv', '.mp4', '.mov', '.mpg', '.avi', '.mpeg'),
                100
            )  #For Movies we want a minimum filesize of 100 MB, otherwise we assume it is a sample
            self.files['nfo'] = self.__GetFileType(self.path, '.nfo')
            self.files['image'] = self.__GetFileType(
                self.path, ('.jpg', '.jpeg', '.png', '.tbn'))

            #=======================================================================
            # Extract the Name of the Movie from the Folder
            #=======================================================================
            self.Name = self.__GetNamefromFolder(os.path.basename(path))
            self.Year = self.__GetYear(os.path.basename(path))

            if len(apikey) > 0:
                self.tmdb = tmdb(apikey)
                #=======================================================================
                # Get an IMDB ID
                #=======================================================================

                #First try to get ID from Foldername
                _id = self.__GetIDFromFolder()
                if _id is False:
                    #Search the NFO Files for ID
                    _id = self.__SearchIDbyNFO()
                #Query the TMDB
                if _id is False:
                    _id = self.tmdb.search(self.Name)

                if _id is False and self.config.get('General',
                                                    'interactive') == 'True':
                    _id = self.__GetIDfromUser()

                if _id is False:
                    raise Exception("Could not get ID for item %s" %
                                    os.path.basename(self.path))
                else:
                    self.id = _id

                #===================================================================
                # Get detailed Movie Information and store them in self.infos
                #===================================================================
                self.__GetDetailedMovieInfos(language)

        except Exception:
            raise
示例#15
0
    def __init__(self,
                 #Path to the Folder containing the Movie
                 path,
                 #Language for the Movie
                 language='',
                 #ApiKey for TMDB
                 apikey='',
                 ):

        self.files = {}
        self.newFiles = {}
        self.newFiles['video'] = []
        self.newFiles['nfo'] = []
        self.infos = u''
        self.NFO = u''
        self.nfoname = u''
        self.path = path
        self.log = TNGLog()
        self.id = False

        # Read the configuration
        self.config = ConfigParser()
        self.config.read(os.path.join(os.getcwd(), 'settings.cfg'))
        
        try:
            #=======================================================================
            # Get Paths for all Items in current movie
            #=======================================================================
            self.files['video'] = self.__GetFileType(self.path, ('.mkv','.mp4','.mov','.mpg','.avi','.mpeg'),100) #For Movies we want a minimum filesize of 100 MB, otherwise we assume it is a sample
            self.files['nfo'] = self.__GetFileType(self.path, '.nfo')
            self.files['image'] = self.__GetFileType(self.path, ('.jpg','.jpeg','.png','.tbn'))
    
            #=======================================================================
            # Extract the Name of the Movie from the Folder
            #=======================================================================
            self.Name = self.__GetNamefromFolder(os.path.basename(path))
            self.Year = self.__GetYear(os.path.basename(path))
            
            if len(apikey) > 0:
                self.tmdb = tmdb(apikey)
                #=======================================================================
                # Get an IMDB ID
                #=======================================================================

                #First try to get ID from Foldername
                _id = self.__GetIDFromFolder()
                if _id is False:
                #Search the NFO Files for ID
                    _id = self.__SearchIDbyNFO()
                #Query the TMDB
                if _id is False:
                    _id = self.tmdb.search(self.Name)

                if _id is False and self.config.get('General', 'interactive') == 'True':
                    _id = self.__GetIDfromUser()

                if _id is False:
                    raise Exception("Could not get ID for item %s" % os.path.basename(self.path))
                else:
                    self.id = _id
                
                #===================================================================
                # Get detailed Movie Information and store them in self.infos
                #===================================================================
                self.__GetDetailedMovieInfos(language)

        except Exception:
            raise
示例#16
0
        dest='language',
        type=unicode,
        default='de',
        required=False,
        help='Language of Movie Infos in ISO 639-1 code Default:German(de)')
    args = parser.parse_args()

    #===========================================================================
    # Logging
    #===========================================================================

    logpath = os.path.abspath(os.path.join(LogFile, os.pardir))
    if not os.path.isdir(logpath):
        os.mkdir(logpath)
    #Create the wrapper log instance
    log = TNGLog()

    formatter = logging.Formatter('%(asctime)s [%(levelname)-8s] %(message)s',
                                  '%d-%m-%Y %H:%M:%S')

    #Initialize the File Logger
    hdlr = handlers.RotatingFileHandler(os.path.join(LogFile), 'a', 524288, 10)
    hdlr.setLevel(logging.DEBUG)
    #hdlr.setLevel(logging.DEBUG) if args.debugMode == True else hdlr.setLevel(logging.INFO)
    hdlr.setFormatter(formatter)
    log.logger.addHandler(hdlr)

    #Initialize the Stdout Logger
    hdlr2 = logging.StreamHandler(sys.stdout)
    hdlr2.setFormatter(formatter)
    hdlr2.setLevel(
示例#17
0
 def __init__(self, path1, path2):
     self.log = TNGLog()
     self.item = {}
     if self.addFile(path1) or self.addFile(path2):
         raise Exception("skipping compare: at least one file is missing")
示例#18
0
class Movie(object):
    def __init__(
        self,
        #Path to the Folder containing the Movie
        path,
        #Language for the Movie
        language='',
        #ApiKey for TMDB
        apikey='',
    ):

        self.files = {}
        self.newFiles = {}
        self.newFiles['video'] = []
        self.newFiles['nfo'] = []
        self.infos = u''
        self.NFO = u''
        self.nfoname = u''
        self.path = path
        self.log = TNGLog()
        self.id = False

        # Read the configuration
        self.config = ConfigParser()
        self.config.read(os.path.join(os.getcwd(), 'settings.cfg'))

        try:
            #=======================================================================
            # Get Paths for all Items in current movie
            #=======================================================================
            self.files['video'] = self.__GetFileType(
                self.path, ('.mkv', '.mp4', '.mov', '.mpg', '.avi', '.mpeg'),
                100
            )  #For Movies we want a minimum filesize of 100 MB, otherwise we assume it is a sample
            self.files['nfo'] = self.__GetFileType(self.path, '.nfo')
            self.files['image'] = self.__GetFileType(
                self.path, ('.jpg', '.jpeg', '.png', '.tbn'))

            #=======================================================================
            # Extract the Name of the Movie from the Folder
            #=======================================================================
            self.Name = self.__GetNamefromFolder(os.path.basename(path))
            self.Year = self.__GetYear(os.path.basename(path))

            if len(apikey) > 0:
                self.tmdb = tmdb(apikey)
                #=======================================================================
                # Get an IMDB ID
                #=======================================================================

                #First try to get ID from Foldername
                _id = self.__GetIDFromFolder()
                if _id is False:
                    #Search the NFO Files for ID
                    _id = self.__SearchIDbyNFO()
                #Query the TMDB
                if _id is False:
                    _id = self.tmdb.search(self.Name)

                if _id is False and self.config.get('General',
                                                    'interactive') == 'True':
                    _id = self.__GetIDfromUser()

                if _id is False:
                    raise Exception("Could not get ID for item %s" %
                                    os.path.basename(self.path))
                else:
                    self.id = _id

                #===================================================================
                # Get detailed Movie Information and store them in self.infos
                #===================================================================
                self.__GetDetailedMovieInfos(language)

        except Exception:
            raise

    def GetImages(self):
        if self.infos['poster_path'] is not None:
            self.__downloadImage(
                self.tmdb.urls['images'] + self.infos['poster_path'],
                'movie.tbn')
            self.__downloadImage(
                self.tmdb.urls['images'] + self.infos['poster_path'],
                'poster.jpg')
            self.__downloadImage(
                self.tmdb.urls['images'] + self.infos['poster_path'],
                os.path.basename(self.path) + '.tbn')
        if self.infos['backdrop_path'] is not None:
            self.__downloadImage(
                self.tmdb.urls['images'] + self.infos['backdrop_path'],
                'fanart.jpg')

    def GetMovieFile(self):
        files = self.__GetFileType(
            self.path, ('.mkv', '.mp4', '.mov', '.mpg', '.avi', '.mpeg'))
        if len(files) == 1:
            return files[0]
        else:
            return False

    def clean(self, extensions):
        for i in os.listdir(self.path):
            itempath = os.path.join(self.path, i)
            if os.path.isdir(itempath):
                shutil.rmtree(itempath)
            elif os.path.splitext(i)[1].lstrip('.') in extensions:
                os.remove(itempath)
            #Remove Sample Files
            elif 'sample' in i.lower():
                os.remove(itempath)

    def rename(self, force):

        self.__rename_folder(force)
        self.__rename_files()

    def __rename_folder(self, force):

        currentName = (os.path.basename(self.path))
        newName = self.infos['title'] + ' ' + self.Year
        newName = self.__MakeSMBfriendly(newName)

        newPath = os.path.join(
            os.path.abspath(os.path.join(self.path, os.pardir)), newName)

        if currentName != newName or force == True:
            #Rename folder and set new path
            try:
                newPath = newPath.encode('utf-8')
                os.rename(self.path, newPath)
            except OSError as e:
                raise Exception("cannot rename folder %s:%s" % (newPath, e))
            #Convert newPath back to unicode and pass to self.path
            self.__update_files_path(self.path, newPath.decode('utf-8'))
            self.path = newPath.decode('utf-8')
            self.log.info("Movie renamed: %s" % newName)

    def __rename_files(self):

        #=======================================================================
        # Build the new Paths
        #=======================================================================

        nameprefix = self.__MakeSMBfriendly(self.infos['title'] + ' ' +
                                            self.Year)

        if len(self.files['video']) > 1:
            self.newFiles['nfo'].insert(0,
                                        os.path.join(self.path, 'movie.nfo'))

            for index, video in enumerate(self.files['video']):

                # Check if we have a naming scheme cd1,cd2 etc.
                if re.search('cd[1-9]', video.lower()):
                    _moviename = nameprefix + ' ' + re.findall(
                        'cd[1-9]', video.lower())[0]
                    _extension = os.path.splitext(
                        self.files['video'][index])[1]
                    self.newFiles['video'].insert(
                        index, os.path.join(self.path,
                                            _moviename + _extension))

            # Check if the last byte of the filename is an incrementing number
            suffixList = []
            for item in self.files['video']:
                suffixList.append(
                    os.path.splitext(os.path.basename(item))[0][-1])
            # Compare against number
            try:
                suffixList = [int(i) for i in suffixList]
                if suffixList == range(1, len(self.files['video']) + 1):
                    for index, video in enumerate(self.files['video']):
                        self.newFiles['video'].insert(
                            index,
                            os.path.join(
                                self.path, "%s cd%i%s" %
                                (nameprefix, index + 1,
                                 os.path.splitext(
                                     self.files['video'][index])[1])))

            except ValueError:
                # We have characters
                pass

        elif len(self.files['video']) == 1:
            self.newFiles['nfo'].insert(
                0, os.path.join(self.path, nameprefix + '.nfo'))
            self.newFiles['video'].insert(
                0,
                os.path.join(
                    self.path,
                    nameprefix + os.path.splitext(self.files['video'][0])[1]))
        else:
            self.log.warning("We have no video file for %s" % nameprefix)

        #=======================================================================
        # Move/Rename the Files
        #=======================================================================

        for index, value in enumerate(self.newFiles['video']):
            os.rename(self.files['video'][index],
                      self.newFiles['video'][index].encode('utf-8'))
            self.log.info('renamed video file: %s' % value)

    def __GetDetailedMovieInfos(self, language):
        _infos = self.tmdb.GetMovieDetails(self.id, language)
        if _infos:
            self.infos = json.loads(_infos)
            self.Name = self.infos['title']
            self.Year = '(%s)' % self.infos['release_date'][0:4]
        else:
            self.infos = False

    def __update_files_path(self, old, new):
        for key in self.files.keys():
            for index, value in enumerate(self.files[key]):
                current = self.files[key][index]
                self.files[key][index] = current.replace(old, new)

    @staticmethod
    def __GetFileType(path, fileext, minSize=None):
        rfile = []
        for root, dirs, files in os.walk(path):
            for item in files:
                itempath = os.path.join(root, item)
                if os.path.splitext(item)[1].lower() in fileext:
                    if minSize is not None:
                        if os.path.getsize(itempath) / 1024 / 1024 > minSize:
                            rfile.append(itempath)
                    else:
                        rfile.append(itempath)
        return rfile

    def __SearchIDbyNFO(self):
        for item in self.files['nfo']:
            if os.path.isfile(item):
                getid = NFO(item, None).GetIMDBID()
                if getid:
                    return getid
        return False

    def __downloadImage(self, url, filename):
        if not os.path.isfile(os.path.join(self.path, filename)):
            request = urllib2.Request(url)
            resp = urllib2.urlopen(request)
            data = resp.read()
            f = open(os.path.join(self.path, filename), 'wb')
            f.write(data)
            f.close()
            self.log.info('%s downloaded: %s' %
                          (filename, os.path.basename(self.path)))
        else:
            self.log.debug('%s exists: %s' %
                           (filename, os.path.basename(self.path)))

    @staticmethod
    def __GetIDfromUser():
        # Asks the User for IMDB ID
        # return: (string)ID
        #         False
        while True:
            imdbID = raw_input("Enter IMDB ID (tt0208092) or enter to abort:")
            if re.match('tt\d{7}', imdbID):
                return imdbID
            if len(imdbID) == 0:
                return False

    @staticmethod
    def __GetYear(string):
        pattern = re.compile('(\\(\d{4}\\))')
        m = pattern.search(string)
        if m:
            return m.group(1)
        else:
            return ''

    def __GetIDFromFolder(self):
        _IMDBid = re.findall('tt\d{7}', os.path.basename(self.path))
        if len(_IMDBid) > 0:
            return _IMDBid[0]
        else:
            return False

    def __GetNamefromFolder(self, string):
        #If we have a trailing ",The" we place it at the Beginning
        if ', The' in string:
            string = 'The %s' % string.replace(', The', '')

        #Filter out some common scene words specified by the user
        if os.path.isfile('scene_words.txt'):
            scene_words = list(
                open('scene_words.txt').read().replace(' ',
                                                       '').split(os.linesep))
            string = self.__sanitizeReleaseName(string, scene_words)

        #Remove the year from movie title
        string = re.sub('(\\(\d{4}\\))', '', string)
        string = re.sub('\d{4}', '', string)
        return string.strip()

    @staticmethod
    def __sanitizeReleaseName(string, words):
        output = []
        arrMovTitle = string.split('.')
        if len(arrMovTitle) < 4:
            arrMovTitle = string.split(' ')
        for item in arrMovTitle:
            if not item.lower() in words:
                output.append(item)

        return ' '.join(output)

    @staticmethod
    def __MakeSMBfriendly(string):
        restricted_chars = [
            '\\', '/', ':', '*', '?', '\"', '<', '>', '|', '\''
        ]
        slist = []
        slist += string
        output = u''
        for i in slist:
            if not i in restricted_chars:
                output += i
        return output

    @staticmethod
    def __force_decode(string, codecs=('utf-8', 'cp1252', 'ascii', 'euc_jp')):
        if isinstance(string, str):
            for i in codecs:
                try:
                    return string.decode(i)
                except:
                    pass
        else:
            return string
示例#19
0
class Movie(object):
    

    def __init__(self,
                 #Path to the Folder containing the Movie
                 path,
                 #Language for the Movie
                 language='',
                 #ApiKey for TMDB
                 apikey='',
                 ):

        self.files = {}
        self.newFiles = {}
        self.newFiles['video'] = []
        self.newFiles['nfo'] = []
        self.infos = u''
        self.NFO = u''
        self.nfoname = u''
        self.path = path
        self.log = TNGLog()
        self.id = False

        # Read the configuration
        self.config = ConfigParser()
        self.config.read(os.path.join(os.getcwd(), 'settings.cfg'))
        
        try:
            #=======================================================================
            # Get Paths for all Items in current movie
            #=======================================================================
            self.files['video'] = self.__GetFileType(self.path, ('.mkv','.mp4','.mov','.mpg','.avi','.mpeg'),100) #For Movies we want a minimum filesize of 100 MB, otherwise we assume it is a sample
            self.files['nfo'] = self.__GetFileType(self.path, '.nfo')
            self.files['image'] = self.__GetFileType(self.path, ('.jpg','.jpeg','.png','.tbn'))
    
            #=======================================================================
            # Extract the Name of the Movie from the Folder
            #=======================================================================
            self.Name = self.__GetNamefromFolder(os.path.basename(path))
            self.Year = self.__GetYear(os.path.basename(path))
            
            if len(apikey) > 0:
                self.tmdb = tmdb(apikey)
                #=======================================================================
                # Get an IMDB ID
                #=======================================================================

                #First try to get ID from Foldername
                _id = self.__GetIDFromFolder()
                if _id is False:
                #Search the NFO Files for ID
                    _id = self.__SearchIDbyNFO()
                #Query the TMDB
                if _id is False:
                    _id = self.tmdb.search(self.Name)

                if _id is False and self.config.get('General', 'interactive') == 'True':
                    _id = self.__GetIDfromUser()

                if _id is False:
                    raise Exception("Could not get ID for item %s" % os.path.basename(self.path))
                else:
                    self.id = _id
                
                #===================================================================
                # Get detailed Movie Information and store them in self.infos
                #===================================================================
                self.__GetDetailedMovieInfos(language)

        except Exception:
            raise

    def GetImages(self):
        if self.infos['poster_path'] is not None:
            self.__downloadImage(self.tmdb.urls['images'] + self.infos['poster_path'],'movie.tbn')
            self.__downloadImage(self.tmdb.urls['images'] + self.infos['poster_path'],'poster.jpg')
            self.__downloadImage(self.tmdb.urls['images'] + self.infos['poster_path'],os.path.basename(self.path)+'.tbn')
        if self.infos['backdrop_path'] is not None:
            self.__downloadImage(self.tmdb.urls['images'] + self.infos['backdrop_path'], 'fanart.jpg')
  
    def GetMovieFile(self):
        files = self.__GetFileType(self.path, ('.mkv','.mp4','.mov','.mpg','.avi','.mpeg'))
        if len(files) == 1:
            return files[0]
        else:
            return False
     
    def clean(self, extensions):
        for i in os.listdir(self.path):
            itempath = os.path.join(self.path, i)
            if os.path.isdir(itempath):
                shutil.rmtree(itempath)
            elif os.path.splitext(i)[1].lstrip('.') in extensions:
                os.remove(itempath)
            #Remove Sample Files
            elif 'sample' in i.lower():
                os.remove(itempath)
    
    def rename(self, force):
        
        self.__rename_folder(force)
        self.__rename_files()


    def __rename_folder(self, force):
           
        currentName = (os.path.basename(self.path))
        newName = self.infos['title'] + ' ' + self.Year
        newName = self.__MakeSMBfriendly(newName)

        newPath = os.path.join(os.path.abspath(os.path.join(self.path,os.pardir)),newName)
        
        if currentName != newName or force == True:
            #Rename folder and set new path
            try:
                newPath = newPath.encode('utf-8')
                os.rename(self.path, newPath)
            except OSError as e:
                raise Exception("cannot rename folder %s:%s" % (newPath,e))
            #Convert newPath back to unicode and pass to self.path
            self.__update_files_path(self.path, newPath.decode('utf-8'))
            self.path = newPath.decode('utf-8')
            self.log.info("Movie renamed: %s" % newName)
    
    def __rename_files(self):

        #=======================================================================
        # Build the new Paths
        #=======================================================================
        
        nameprefix = self.__MakeSMBfriendly(self.infos['title'] + ' ' + self.Year)
        
        if len(self.files['video']) > 1:
            self.newFiles['nfo'].insert(0, os.path.join(self.path, 'movie.nfo'))

            for index, video in enumerate(self.files['video']):

                # Check if we have a naming scheme cd1,cd2 etc.
                if re.search('cd[1-9]', video.lower()):
                    _moviename = nameprefix + ' ' + re.findall('cd[1-9]', video.lower())[0]
                    _extension = os.path.splitext(self.files['video'][index])[1]
                    self.newFiles['video'].insert(index, os.path.join(self.path, _moviename + _extension))

            # Check if the last byte of the filename is an incrementing number
            suffixList = []
            for item in self.files['video']: suffixList.append(os.path.splitext(os.path.basename(item))[0][-1])
            # Compare against number
            try:
                suffixList = [int(i) for i in suffixList]
                if suffixList == range(1, len(self.files['video'])+1):
                    for index, video in enumerate(self.files['video']): self.newFiles['video'].insert(index, os.path.join(self.path, "%s cd%i%s" % (nameprefix, index + 1, os.path.splitext(self.files['video'][index])[1])))

            except ValueError:
                # We have characters
                pass

        elif len(self.files['video']) == 1:
            self.newFiles['nfo'].insert(0, os.path.join(self.path, nameprefix + '.nfo'))
            self.newFiles['video'].insert(0, os.path.join(self.path, nameprefix + os.path.splitext(self.files['video'][0])[1]))
        else:
            self.log.warning("We have no video file for %s" % nameprefix)
            

    
        #=======================================================================
        # Move/Rename the Files
        #=======================================================================
        
        for index, value in enumerate(self.newFiles['video']):
            os.rename(self.files['video'][index], self.newFiles['video'][index].encode('utf-8'))
            self.log.info('renamed video file: %s' % value)
    
  
    def __GetDetailedMovieInfos(self, language):
        _infos = self.tmdb.GetMovieDetails(self.id, language)
        if _infos:
            self.infos = json.loads(_infos)
            self.Name = self.infos['title']
            self.Year = '(%s)' % self.infos['release_date'][0:4]
        else:
            self.infos = False
    
    def __update_files_path(self,old,new):
        for key in self.files.keys():
            for index,value in enumerate(self.files[key]):
                current = self.files[key][index]
                self.files[key][index] = current.replace(old,new)

    @staticmethod
    def __GetFileType(path,fileext,minSize=None):
        rfile = []
        for root,dirs,files in os.walk(path):
            for item in files:
                itempath = os.path.join(root,item)
                if os.path.splitext(item)[1].lower() in fileext:
                    if minSize is not None:
                        if os.path.getsize(itempath) / 1024 / 1024 > minSize:
                            rfile.append(itempath)
                    else:
                        rfile.append(itempath)
        return rfile
         
    def __SearchIDbyNFO(self):
        for item in self.files['nfo']:
            if os.path.isfile(item):
                getid = NFO(item,None).GetIMDBID()
                if  getid:
                    return getid
        return False
      
    def __downloadImage(self, url, filename):
        if not os.path.isfile(os.path.join(self.path, filename)):
            request = urllib2.Request(url)
            resp = urllib2.urlopen(request)
            data = resp.read()
            f = open(os.path.join(self.path, filename),'wb')
            f.write(data)
            f.close()
            self.log.info('%s downloaded: %s' % (filename,os.path.basename(self.path)))
        else:
            self.log.debug('%s exists: %s' % (filename,os.path.basename(self.path)))

    @staticmethod
    def __GetIDfromUser():
        # Asks the User for IMDB ID
        # return: (string)ID
        #         False
        while True:
            imdbID = raw_input("Enter IMDB ID (tt0208092) or enter to abort:")
            if re.match('tt\d{7}', imdbID):
                return imdbID
            if len(imdbID) == 0:
                return False

    @staticmethod
    def __GetYear(string):
        pattern = re.compile('(\\(\d{4}\\))')
        m = pattern.search(string)
        if m:
            return m.group(1)
        else:
            return ''
    
    def __GetIDFromFolder(self):
        _IMDBid = re.findall('tt\d{7}',os.path.basename(self.path))
        if len(_IMDBid) > 0:
            return _IMDBid[0]
        else:
            return False
    
    def __GetNamefromFolder(self,string):
        #If we have a trailing ",The" we place it at the Beginning
        if ', The' in string:
            string = 'The %s' % string.replace(', The','')
            
                
        #Filter out some common scene words specified by the user
        if os.path.isfile('scene_words.txt'):
            scene_words = list(open('scene_words.txt').read().replace(' ','').split(os.linesep))
            string = self.__sanitizeReleaseName(string, scene_words)
        
        #Remove the year from movie title
        string = re.sub('(\\(\d{4}\\))', '', string)
        string = re.sub('\d{4}','',string)
        return string.strip()

    @staticmethod
    def __sanitizeReleaseName(string,words):
        output = []
        arrMovTitle = string.split('.')
        if len(arrMovTitle) < 4:
            arrMovTitle = string.split(' ')
        for item in arrMovTitle:
            if not item.lower() in words:
                output.append(item)
                    
        return ' '.join(output)
        
    @staticmethod
    def __MakeSMBfriendly(string):
        restricted_chars = [ '\\' , '/' , ':' , '*' , '?' , '\"' , '<' , '>' , '|', '\'' ]
        slist = []
        slist += string
        output = u''
        for i in slist:
            if not i in restricted_chars:
                output += i
        return output
     
    @staticmethod
    def __force_decode(string, codecs=('utf-8', 'cp1252','ascii','euc_jp')):
        if isinstance(string,str):
            for i in codecs:
                try:
                    return string.decode(i)
                except:
                    pass
        else:
            return string