Exemple #1
0
def homepage(request):
    """homepage view for / on hdd-indexer

    Serves the homepage at root (/) with index.html
    Passes hdd_name, hdd_root, movie_folder, crawler_status

    Args:
        request(RequestContext) - passed by Django

    Returns:
        response(Response) - file template to serve

    Raises:
        None
    """
    log.info('served homepage')
    return render(
        request,
        'hdd_indexer/index.html',
        {
            'hdd_name': HDDName.get_solo(),
            'hdd_root': HDDRoot.get_solo(),
            'movie_folder': path.join(
                HDDRoot.get_solo().path,
                MovieFolder.get_solo().relpath,
            ),
            'crawler_status': crawler_status(),
        }
    )
Exemple #2
0
def start_loader():
    """Start the loader

    Starts the loader after checking hdd and movie folder are accessible.

    Args:
        None

    Returns:
        None

    Raises:
        None
    """
    hdd_root = HDDRoot.get_solo().path
    if not path.exists(hdd_root):
        print _ERROR[1]
        return _ERROR[1]
    movie_folder = MovieFolder.get_solo().relpath
    if not path.exists(path.join(hdd_root, movie_folder)):
        print _ERROR[1]
        return _ERROR[2]
    loader_status('STATUS', True)
    thread = Thread(target=_run)
    thread.daemon = True
    thread.start()
Exemple #3
0
def setup(request):
    """Setup for first-use
    """
    if not request.POST:
        log.info('served setup page')
        return render(
            request,
            'hdd_indexer/setup.html',
            {
                'RegistrationKey': RegistrationKey.get_solo().key,
                'hdd_name': HDDName.get_solo().name,
                'hdd_root': HDDRoot.get_solo().path,
                'movie_folder': MovieFolder.get_solo().relpath,
                'opensub_id': OpenSubKey.get_solo().uid,
                'opensub_key': OpenSubKey.get_solo().key,
                'tmdb_key': TMDbKey.get_solo().key,
                'error': False,
                'err_msg': '',
            }
        )

    error = False
    err_msg = 'Validation errors have been found: '
    log.info('POST: preferences and settings in setup')
    # validations
    # registration key
    registration_key = request.POST.get('ID', '')
    if registration_key:
        # make sure that it is valid registration key
        registration_key_db = RegistrationKey.get_solo()
        registration_key_db.key = registration_key
        registration_key_db.save()
        log.info('registration key = %s saved to db' % registration_key)
    else:
        pass

    # hdd name
    hdd_name = request.POST.get('HDDName', '')
    pattern = re.compile(r'^[0-9a-zA-z_-]+$')
    if pattern.match(hdd_name):
        hdd_name_db = HDDName.get_solo()
        hdd_name_db.name = hdd_name
        hdd_name_db.save()
        log.info('hdd_name: %s saved to db' % hdd_name)
    else:
        error = True
        err_msg = ' '.join(((err_msg, 'HDD Name,')))
        log.error('%s is not a valid hdd_name' % hdd_name)

    # hdd root
    hdd_root = request.POST.get('HDDRoot', '')
    if path.exists(hdd_root):
        hdd_root_db = HDDRoot.get_solo()
        hdd_root_db.path = hdd_root
        hdd_root_db.save()
        log.info('hdd_root = %s saved to db' % hdd_root)
    else:
        error = True
        err_msg = ' '.join(((err_msg, 'HDD Root,')))
        log.error('%s is not a valid path' % hdd_root)

    # movie folder
    movie_folder = request.POST.get('MovieFolder', '')
    log.info('POST: movie_folder = %s' % movie_folder)
    if path.exists(movie_folder):
        movie_folder_db = MovieFolder.get_solo()
        movie_folder_db.relpath = movie_folder
        movie_folder_db.save()
        log.info('movie_folder = %s saved to db' % movie_folder)
    else:
        error = True
        err_msg = ' '.join((err_msg, 'Movie Folder,'))
        log.error('%s is not a valid path' % movie_folder)

    # tmdb key
    # TODO: check tmdb key is valid
    tmdb_key = request.POST.get('TMDB_KEY', '')
    log.info('POST: tmdb_key = %s' % tmdb_key)
    if len(tmdb_key) >= 5:
        tmdb_db = TMDbKey.get_solo()
        tmdb_db.key = tmdb_key
        tmdb_db.save()
        log.info('tmdb_key = %s saved to db' % tmdb_key)
    else:
        error = True
        err_msg = ' '.join(((err_msg, 'TMDb Key,')))
        log.error('%s is not a valid tmdb_key' % tmdb_key)

    # opensub
    # TODO: check opensub key is valid
    opensub_id = request.POST.get('OpenSubID', '')
    opensub_key = request.POST.get('OpenSubKey', '')
    log.info('opensub id:%s key:%s' % (opensub_id, opensub_key))
    if opensub_id and opensub_key:
        if len(opensub_id) >= 5 and len(opensub_key) >= 5:
            opensub_db = OpenSubKey.get_solo()
            opensub_db.uid = opensub_id
            opensub_db.key = opensub_key
            opensub_db.save()
            log.info('opensub id:%s key:%s saved to db' % (
                opensub_id, opensub_key
            ))
        else:
            error = True
            err_msg = ' '.join((err_msg, 'OpenSubtitles ID and Key,'))
            log.info('opensub id:%s key:%s are not valid' % (
                opensub_id, opensub_key
            ))

    if error is False:
        log.info('setup complete, redirected to welcome page')
        return render(
            request,
            'hdd_indexer/help.html',
            {
                'welcome': True,
            }
        )

    log.error('setup input has errors, redirect to setup page')
    return render(
        request,
        'hdd_indexer/setup.html',
        {
            'RegistrationKey': RegistrationKey,
            'hdd_name': hdd_name,
            'hdd_root': hdd_root,
            'movie_folder': movie_folder,
            'opensub_id': opensub_id,
            'opensub_key': opensub_key,
            'tmdb_key': tmdb_key,
            'error': error,
            'err_msg': err_msg,
        }
    )
Exemple #4
0
def settings(request):
    """settings view for / on hdd-indexer

    Validates settings sent using POST

    POST:
        hdd_name(str)
        hdd_root(str)
        movie_folder(str)

    Args:
        request(RequestContext) - passed by Django

    Returns:
        response(HttpResponse) - resposne to POST request

    Raises:
        None
    """

    def response(d=True, v=True):
        """Response for POST methods

        returns a HTTPResponse with content type json

        Args:
            d(bool): POST success (JQuery done)
            v(bool): POST validation
        """
        payload = {
            'done': d,
            'validation': v,
        }
        log.debug('settings validation: %s' % payload)
        return HttpResponse(
            json.dumps(payload),
            content_type='application/json'
        )

    # if request is not POST, return error
    if request.method != 'POST':
        # 405: Method not allowed
        log.error('405: Method not allowed')
        return HttpResponse(status=405)

    # request for HDD Name
    if request.POST.get('hdd_name', None):
        hdd_name = request.POST['hdd_name']
        log.info('POST: hdd_name: %s' % hdd_name)
        pattern = re.compile(r'^[0-9a-zA-z_-]+$')
        if pattern.match(hdd_name):
            try:
                hdd_name_db = HDDName.get_solo()
                hdd_name_db.name = hdd_name
                hdd_name_db.save()
                log.info('hdd_name = %s saved to db' % hdd_name)
                return response()
            except ValueError:
                return response(d=False, v=True)
            except TypeError:
                return response(d=False, v=False)
            except Exception as e:
                print e
                return response(d=False, v=False)
        else:
            log.error('%s is a not a valid hdd_name' % hdd_name)
            return response(d=False, v=True)

    # request for HDD Root
    elif request.POST.get('hdd_root', None):
        hdd_root = request.POST['hdd_root']
        log.info('POST: hdd_root = %s' % hdd_root)
        if path.isdir(hdd_root):
            hdd_root_db = HDDRoot.get_solo()
            hdd_root_db.path = hdd_root
            hdd_root_db.save()
            log.info('hdd_root = %s saved to db' % hdd_root)
            return response()
        else:
            log.error('%s is not a valid path' % hdd_root)
            return response(d=False, v=True)

    # request for Movie Folder
    elif request.POST.get('movie_folder', None):
        movie_folder = request.POST['movie_folder']
        log.info('POST: movie_folder = %s' % movie_folder)
        hdd_root = HDDRoot.get_solo().path
        if not movie_folder.startswith(hdd_root):
            log.error('movie_folder does not start with hdd_root')
            return response(d=False, v=True)
        if not path.isdir(movie_folder):
            log.error('movie_folder is not a valid path')
            return response(d=False, v=True)
        movie_folder = path.relpath(movie_folder, hdd_root)
        movie_folder_db = MovieFolder.get_solo()
        movie_folder_db.relpath = movie_folder
        movie_folder_db.save()
        log.info('movie_folder = %s saved to db' % movie_folder)
        return response(d=True)

    log.error('405: Method not allowed')
    return HttpResponse(status=405)
Exemple #5
0
def _organize(criterion):
    """organize movies on disk/database by provided criterion

    Selects all movies and updates their filenames based on their
    metadata titles. Moves their files to organized folders whose
    name and hierarchy are based on criterion selected.

    Args:
        criterion(str): user choice of organization criterion

    Returns:
        None

    Raises:
        None
    """
    def create_folder(folder):
        """ creates a folder if it does not exist

        Args:
            folder(str): path of the folder

        Returns:
            None

        Raises:
            None
        """
        # TODO: check if path is valid
        if not path.exists(path.join(destination, folder)):
            log.info('created directory %s' % folder)
            makedirs(path.join(destination, folder))

    # functions for selected criterion
    _get_folder, _field_exists = _criterion_tools(criterion)
    # temporary folder for holding created folders
    tempname = 'tmp'
    log.debug('temporary folder set to ./%s' % tempname)
    uncategorized = 'uncategorized'
    log.debug('uncategorized folder set to ./%s/%s' % (
        tempname, uncategorized))
    parentpath = path.join(
        HDDRoot.get_solo().path,
        MovieFolder.get_solo().relpath)
    destination = path.join(parentpath, tempname)
    create_folder(destination)

    movies = Movie.objects.all()
    for movie in movies:

        # parent folder for the movie file
        if _field_exists(movie):
            folder = _get_folder(movie)
        else:
            folder = uncategorized
        log.debug('folder: %s' % folder)
        create_folder(folder)

        # create new filename -> title with extension
        fname = make_fname(movie.title, movie.relpath)
        # move the file to its new location
        newpath = path.join(
            path.join(destination, folder),
            fname)
        oldpath = path.join(parentpath, movie.relpath)
        move(oldpath, newpath)
        log.debug('%s moved from %s to %s' % (
            movie.title, movie.relpath, newpath))
        # update movie path to the newpath
        movie.relpath = path.join(folder, fname)
        # save updated movie to database
        movie.save()

    # move other files from movie_folder to new folder
    other_files = path.join(destination, 'other_files')
    create_folder(other_files)
    for root, directory, files in walk(parentpath):
        # don't go into the temporary folder
        if not root.startswith(destination):
            for somefile in files:
                move(
                    path.join(root, somefile),
                    path.join(other_files, somefile))
    log.info('moved other files into %s' % other_files)

    # remove all directories from movie folder
    for directory in walk(parentpath).next()[1]:
        if directory != tempname:
            rmtree(path.join(parentpath, directory))
    log.info('removed all directories from movie folder')

    # move all new folders into movie folder directory
    for directory in walk(destination).next()[1]:
        move(
            path.join(destination, directory),
            path.join(parentpath, directory))

    # delete temporary directory
    rmtree(destination)

    # update status of organizer
    organizer_status('STATUS', False)
Exemple #6
0
def opensub(relpath):
    """OpenSubtitle identification of movie

    Uses the OpenSubtitles API to identify movie

    Args:
        relpath(str): relative path of movie file

    Returns:
        imdb_id(int): on success, returns idetified imdb id
        None: on failure

    Raises:
        None
    """
    if 'sub' not in opensub.__dict__:
            sub = opensub_initiate()
            if sub:
                opensub.sub = sub
                token = sub.login(
                    OpenSubKey.get_solo().uid,
                    OpenSubKey.get_solo().key
                )
                opensub.token = token
            opensub.lock = Lock()

    try:
        # login to opensub using API
        sub = opensub.sub
        token = opensub.token
        if not token:
            # return sub
            print 'null token'
            log.error('path: %s open sub null token' % relpath)
            return
        # check that the file is accessible
        if not path.exists(path.join(
            HDDRoot.get_solo().path,
            MovieFolder.get_solo().relpath,
            relpath,
        )):
            print "ERROR: " + relpath
            log.error('path: %s does not exist' % relpath)
            return
        f = File(path.join(
            HDDRoot.get_solo().path,
            MovieFolder.get_solo().relpath,
            relpath,
        ))
        if f is None:
            log.error('path: %s open sub file error' % relpath)
            return
        hash = f.get_hash()
        size = f.size
        with opensub.lock:
            data = sub.search_subtitles([{
                'sublanguageid': 'all',
                'moviehash': hash,
                'moviebytesize': size,
            }])
        if type(data) is list:
            if data[0].get('IDMovieImdb', None):
                return data[0]['IDMovieImdb']
        else:
            log.warning('%s opensub failed to identify movie' % relpath)
    except ProtocolError as e:
        # most likely network error or API server error
        print "E: " + str(e)
    except AssertionError:
        print 'Failed to authenticate opensubtitles login.'
    except ProtocolError as e:
        """
        TODO: gaierror:
            [Errno 8] nodename nor servname provided, or not known
        """
        if e.errcode == 503:
            # ProtocolError - 503 Service Unavailable
            print 'Check network connection and try again.'
        log.error('path: %s open sub error occured' % relpath)
        log.error(traceback.format_exc())
    except Exception:
        log.error('path: %s open sub error occured' % relpath)
        log.error(traceback.format_exc())