SickGear/lib/tvdb_api/tvdb_ui.py
Prinz23 07d72e05f1 Add Fuzzywuzzy lib to sort search results.
Change remove search results filtering from tv info source.
Change suppress startup warnings for Fuzzywuzzy and Cheetah libs.
Change show name aliases get a score -1 to give the main names priority.
Change replace findCertainShow with find_show_by_id for mapped multi-indexer.
Change add Trakt info source search interface.
Change directly send image after it's been cached.
Fix loading CachedImages images with TVDB API v2 changes.
2017-09-04 01:23:30 +01:00

155 lines
5.4 KiB
Python

#!/usr/bin/env python2
#encoding:utf-8
#author:dbr/Ben
#project:tvdb_api
#repository:http://github.com/dbr/tvdb_api
#license:unlicense (http://unlicense.org/)
"""Contains included user interfaces for Tvdb show selection.
A UI is a callback. A class, it's __init__ function takes two arguments:
- config, which is the Tvdb config dict, setup in tvdb_api.py
- log, which is Tvdb's logger instance (which uses the logging module). You can
call log.info() log.warning() etc
It must have a method "select_series", this is passed a list of dicts, each dict
contains the the keys "name" (human readable show name), and "sid" (the shows
ID as on thetvdb.com). For example:
[{'name': u'Lost', 'sid': u'73739'},
{'name': u'Lost Universe', 'sid': u'73181'}]
The "select_series" method must return the appropriate dict, or it can raise
tvdb_userabort (if the selection is aborted), tvdb_shownotfound (if the show
cannot be found).
A simple example callback, which returns a random series:
>>> import random
>>> from tvdb_ui import BaseUI
>>> class RandomUI(BaseUI):
... def select_series(self, allSeries):
... import random
... return random.choice(allSeries)
Then to use it..
>>> from tvdb_api import Tvdb
>>> t = Tvdb(custom_ui = RandomUI)
>>> random_matching_series = t['Lost']
>>> type(random_matching_series)
<class 'tvdb_api.Show'>
"""
__author__ = "dbr/Ben"
__version__ = "1.9"
import logging
import warnings
from tvdb_exceptions import tvdb_userabort
def log():
return logging.getLogger(__name__)
class BaseUI:
"""Default non-interactive UI, which auto-selects first results
"""
def __init__(self, config, log = None):
self.config = config
if log is not None:
warnings.warn("the UI's log parameter is deprecated, instead use\n"
"use import logging; logging.getLogger('ui').info('blah')\n"
"The self.log attribute will be removed in the next version")
self.log = logging.getLogger(__name__)
def select_series(self, all_series):
return all_series[0]
class ConsoleUI(BaseUI):
"""Interactively allows the user to select a show from a console based UI
"""
def _displaySeries(self, allSeries, limit = 6):
"""Helper function, lists series with corresponding ID
"""
if limit is not None:
toshow = allSeries[:limit]
else:
toshow = allSeries
print "TVDB Search Results:"
for i, cshow in enumerate(toshow):
i_show = i + 1 # Start at more human readable number 1 (not 0)
log().debug('Showing allSeries[%s], series %s)' % (i_show, allSeries[i]['seriesname']))
if i == 0:
extra = " (default)"
else:
extra = ""
print "%s -> %s [%s] # http://thetvdb.com/?tab=series&id=%s&lid=%s%s" % (
i_show,
cshow['seriesname'].encode("UTF-8", "ignore"),
cshow['language'].encode("UTF-8", "ignore"),
str(cshow['id']),
cshow['lid'],
extra
)
def select_series(self, all_series):
self._displaySeries(all_series)
if len(all_series) == 1:
# Single result, return it!
print "Automatically selecting only result"
return all_series[0]
if self.config['select_first'] is True:
print "Automatically returning first search result"
return all_series[0]
while True: # return breaks this loop
try:
print "Enter choice (first number, return for default, 'all', ? for help):"
ans = raw_input()
except KeyboardInterrupt:
raise tvdb_userabort("User aborted (^c keyboard interupt)")
except EOFError:
raise tvdb_userabort("User aborted (EOF received)")
log().debug('Got choice of: %s' % (ans))
try:
selected_id = int(ans) - 1 # The human entered 1 as first result, not zero
except ValueError: # Input was not number
if len(ans.strip()) == 0:
# Default option
log().debug('Default option, returning first series')
return all_series[0]
if ans == "q":
log().debug('Got quit command (q)')
raise tvdb_userabort("User aborted ('q' quit command)")
elif ans == "?":
print "## Help"
print "# Enter the number that corresponds to the correct show."
print "# a - display all results"
print "# all - display all results"
print "# ? - this help"
print "# q - abort tvnamer"
print "# Press return with no input to select first result"
elif ans.lower() in ["a", "all"]:
self._displaySeries(all_series, limit = None)
else:
log().debug('Unknown keypress %s' % (ans))
else:
log().debug('Trying to return ID: %d' % (selected_id))
try:
return all_series[selected_id]
except IndexError:
log().debug('Invalid show number entered!')
print "Invalid number (%s) selected!"
self._displaySeries(all_series)