Merge pull request #5 from KevinMidboe/CLI

Cli
This commit is contained in:
2018-10-18 20:54:22 +02:00
committed by GitHub
4 changed files with 62 additions and 47 deletions

View File

@@ -1,25 +1,37 @@
#!usr/bin/env python3.6 #!usr/bin/env python3.6
from guessit import guessit
import click
from core import scan_folder, moveHome from core import scan_folder, moveHome
from video import Video from video import Video
from guessit import guessit
from exceptions import InsufficientInfoError from exceptions import InsufficientInfoError
videos, insufficient_info = scan_folder('Spider.Man') @click.command()
print('Sweet lemonade: {} {}'.format(videos, insufficient_info)) @click.argument('path')
def main(path):
videos, insufficient_info = scan_folder(path)
# print('Sweet lemonade: {} {}'.format(videos, insufficient_info))
for video in videos: for video in videos:
moveHome(video)
while len(insufficient_info) > 1:
for file in insufficient_info:
supplementary_info = input("Insufficient info for match file: '{}'\nSupplementary info: ".format(file))
print(supplementary_info)
try:
video = Video.fromguess(file, guessit(supplementary_info))
insufficient_info.pop()
except InsufficientInfoError:
pass
moveHome(video) moveHome(video)
while len(insufficient_info) >= 1:
for file in insufficient_info:
supplementary_info = input("Insufficient info for match file: '{}'\nSupplementary info: ".format(file))
if supplementary_info is 'q':
exit(0)
if supplementary_info is 's':
insufficient_info.pop()
continue
try:
video = Video.fromguess(file, guessit(supplementary_info))
print(video)
moveHome(video)
insufficient_info.pop()
except InsufficientInfoError:
pass
if __name__ == '__main__':
main()

View File

@@ -19,7 +19,7 @@ from titlecase import titlecase
import langdetect import langdetect
import env_variables as env import env_variables as env
from exceptions import InsufficientInfoError from exceptions import InsufficientNameError
from video import VIDEO_EXTENSIONS, Episode, Movie, Video from video import VIDEO_EXTENSIONS, Episode, Movie, Video
from subtitle import SUBTITLE_EXTENSIONS, Subtitle, get_subtitle_path from subtitle import SUBTITLE_EXTENSIONS, Subtitle, get_subtitle_path
@@ -28,9 +28,9 @@ from utils import sanitize, refine
logging.basicConfig(filename=env.logfile, level=logging.DEBUG) logging.basicConfig(filename=env.logfile, level=logging.DEBUG)
logger = logging.getLogger('seasonedParser') logger = logging.getLogger('seasonedParser')
fh = logging.FileHandler(env.logfile) fh = logging.FileHandler(env.logfile)
fh.setLevel(logging.DEBUG) fh.setLevel(logging.INFO)
sh = logging.StreamHandler() sh = logging.StreamHandler()
sh.setLevel(logging.DEBUG) sh.setLevel(logging.ERROR)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter) fh.setFormatter(formatter)
@@ -158,6 +158,8 @@ def scan_videos(path):
# walk the path # walk the path
videos = [] videos = []
insufficient_name = []
errors_path = []
for dirpath, dirnames, filenames in os.walk(path): for dirpath, dirnames, filenames in os.walk(path):
logger.debug('Walking directory %r', dirpath) logger.debug('Walking directory %r', dirpath)
@@ -189,8 +191,13 @@ def scan_videos(path):
if filename.endswith(VIDEO_EXTENSIONS): # video if filename.endswith(VIDEO_EXTENSIONS): # video
try: try:
video = scan_video(filepath) video = scan_video(filepath)
except InsufficientInfoError as e:
logger.info(e)
insufficient_name.append(filepath)
continue
except ValueError: # pragma: no cover except ValueError: # pragma: no cover
logger.exception('Error scanning video') logger.exception('Error scanning video')
errors_path.append(filepath)
continue continue
else: # pragma: no cover else: # pragma: no cover
raise ValueError('Unsupported file %r' % filename) raise ValueError('Unsupported file %r' % filename)
@@ -199,7 +206,7 @@ def scan_videos(path):
bar.update(1) bar.update(1)
return videos return videos, insufficient_name, errors_path
def organize_files(path): def organize_files(path):
@@ -261,7 +268,7 @@ def save_subtitles(files, single=False, directory=None, encoding=None):
def scan_folder(path): def scan_folder(path):
videos = [] videos = []
insufficient_info = [] insufficient_name = []
errored_paths = [] errored_paths = []
logger.debug('Collecting path %s', path) logger.debug('Collecting path %s', path)
@@ -280,9 +287,9 @@ def scan_folder(path):
video = scan_video(path) video = scan_video(path)
videos.append(video) videos.append(video)
except InsufficientInfoError as e: except InsufficientNameError as e:
logger.error(e) logger.info(e)
insufficient_info.append(path) insufficient_name.append(path)
# directories # directories
if os.path.isdir(path): if os.path.isdir(path):
@@ -290,24 +297,21 @@ def scan_folder(path):
scanned_videos = [] scanned_videos = []
try: try:
scanned_videos = scan_videos(path) videos, insufficient_name, errored_paths = scan_videos(path)
except InsufficientInfoError as e:
logger.error(e)
insufficient_info.append(path)
except: except:
logger.exception('Unexpected error while collecting directory path %s', path) logger.exception('Unexpected error while collecting directory path %s', path)
errored_paths.append(path) errored_paths.append(path)
click.echo('%s video%s collected / %s file%s with insufficient info / %s error%s' % ( click.echo('%s video%s collected / %s file%s with insufficient name / %s error%s' % (
click.style(str(len(videos)), bold=True, fg='green' if videos else None), click.style(str(len(videos)), bold=True, fg='green' if videos else None),
's' if len(videos) > 1 else '', 's' if len(videos) > 1 else '',
click.style(str(len(insufficient_info)), bold=True, fg='yellow' if insufficient_info else None), click.style(str(len(insufficient_name)), bold=True, fg='yellow' if insufficient_name else None),
's' if len(insufficient_info) > 1 else '', 's' if len(insufficient_name) > 1 else '',
click.style(str(len(errored_paths)), bold=True, fg='red' if errored_paths else None), click.style(str(len(errored_paths)), bold=True, fg='red' if errored_paths else None),
's' if len(errored_paths) > 1 else '', 's' if len(errored_paths) > 1 else '',
)) ))
return videos, insufficient_info return videos, insufficient_name
def pickforgirlscouts(video): def pickforgirlscouts(video):
if video.sufficientInfo(): if video.sufficientInfo():
@@ -334,3 +338,6 @@ def moveHome(video):
logger.info("Moving subtitle file from: '{}' to: '{}'".format(oldpath, newpath)) logger.info("Moving subtitle file from: '{}' to: '{}'".format(oldpath, newpath))
shutil.move(oldpath, newpath) shutil.move(oldpath, newpath)
# Give feedback before delete ?
def empthDirectory(paths):
pass

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python3.6 #!/usr/bin/env python3.6
class InsufficientInfoError(Exception): class InsufficientNameError(Exception):
pass pass

View File

@@ -12,7 +12,7 @@ from titlecase import titlecase
import hashlib, tvdb_api import hashlib, tvdb_api
import env_variables as env import env_variables as env
from exceptions import InsufficientInfoError from exceptions import InsufficientNameError
logger = logging.getLogger('seasonedParser') logger = logging.getLogger('seasonedParser')
@@ -34,13 +34,11 @@ class Video(object):
:param str resolution: resolution of the video stream (480p, 720p, 1080p or 1080i, 4K). :param str resolution: resolution of the video stream (480p, 720p, 1080p or 1080i, 4K).
:param str video_codec: codec of the video stream. :param str video_codec: codec of the video stream.
:param str audio_codec: codec of the main audio stream. :param str audio_codec: codec of the main audio stream.
:param str move_location: location to move file to.
:param dict name_hash: hashes of the video file by provider names.
:param int size: size of the video file in bytes. :param int size: size of the video file in bytes.
:param set subtitles: existing subtitle languages. :param set subtitles: existing subtitle languages.
""" """
def __init__(self, name, hash=None, size=None, format=None, release_group=None, resolution=None, video_codec=None, audio_codec=None, def __init__(self, name, hash=None, size=None, format=None, release_group=None, resolution=None, video_codec=None, audio_codec=None,
move_location=None, subtitles=None, embeded_subtitles=None): subtitles=None, embeded_subtitles=None):
#: Name or path of the video #: Name or path of the video
self.name = name self.name = name
@@ -65,9 +63,6 @@ class Video(object):
#: Codec of the main audio stream #: Codec of the main audio stream
self.audio_codec = audio_codec self.audio_codec = audio_codec
#: optimal move_location path; parent folder.
self.move_location = move_location
#: Existing subtitle languages #: Existing subtitle languages
self.subtitles = subtitles or set() self.subtitles = subtitles or set()
@@ -157,11 +152,15 @@ class Episode(Video):
@classmethod @classmethod
def fromguess(cls, name, guess): def fromguess(cls, name, guess):
logger.info('Guess: {}'.format(guess))
if guess['type'] != 'episode': if guess['type'] != 'episode':
raise ValueError('The guess must be an episode guess') raise ValueError('The guess must be an episode guess')
if 'title' not in guess or 'season' not in guess or 'episode' not in guess: if 'title' not in guess or 'season' not in guess or 'episode' not in guess:
raise InsufficientInfoError('Insufficient data to process the guess') raise InsufficientNameError('Guess failed to have sufficient data from query: {}'.format(name))
if any([isinstance(x, list) for x in [guess['title'], guess['season'], guess['episode']]]):
raise InsufficientNameError('Guess could not be parsed, list values found.')
return cls(name, guess['title'], guess.get('season', 1), guess['episode'], title=guess.get('episode_title'), return cls(name, guess['title'], guess.get('season', 1), guess['episode'], title=guess.get('episode_title'),
year=guess.get('year'), format=guess.get('format'), original_series='year' not in guess, year=guess.get('year'), format=guess.get('format'), original_series='year' not in guess,
@@ -179,12 +178,9 @@ class Episode(Video):
return os.path.join(env.SHOWBASE, grandParent, parent, os.path.basename(self.name)) return os.path.join(env.SHOWBASE, grandParent, parent, os.path.basename(self.name))
def __repr__(self): def __repr__(self):
if self.year is None:
return '<%s [%r, %dx%s]>' % (self.__class__.__name__, self.series, self.season, self.episode)
if self.subtitles is not None and len(self.subtitles) > 0: if self.subtitles is not None and len(self.subtitles) > 0:
return '<%s [%r, %dx%s] %s>' % (self.__class__.__name__, self.series, self.season, self.episode, self.subtitles) return '<%s [%r, %dx%s] %s>' % (self.__class__.__name__, self.series, self.season, self.episode, self.subtitles)
return '<%s [%r, %dx%d]>' % (self.__class__.__name__, self.series, self.season, self.episode)
return '<%s [%r, %d, %dx%d]>' % (self.__class__.__name__, self.series, self.year, self.season, self.episode)
class Movie(Video): class Movie(Video):
"""Movie :class:`Video`. """Movie :class:`Video`.
@@ -207,7 +203,7 @@ class Movie(Video):
raise ValueError('The guess must be a movie guess') raise ValueError('The guess must be a movie guess')
if 'title' not in guess or 'year' not in guess: if 'title' not in guess or 'year' not in guess:
raise InsufficientInfoError('Insufficient data to process the guess') raise InsufficientNameError('Guess failed to have sufficient data from query: {}'.format(name))
return cls(name, guess['title'], format=guess.get('format'), release_group=guess.get('release_group'), return cls(name, guess['title'], format=guess.get('format'), release_group=guess.get('release_group'),
resolution=guess.get('screen_size'), video_codec=guess.get('video_codec'), resolution=guess.get('screen_size'), video_codec=guess.get('video_codec'),