#!/usr/bin/env python import os import sys import urwid import tmdbsimple as tmdb from pprint import pprint def run_async(func): from threading import Thread from functools import wraps @wraps(func) def async_func(*args, **kwargs): func_hl = Thread(target = func, args = args, kwargs = kwargs) func_hl.start() return func_hl return async_func def read_key(): if "TMDB_KEY" in os.environ.keys(): return os.environ["TMDB_KEY"] if "XDG_CONFIG_HOME" in os.environ.keys(): cfg_home = os.environ["XDG_CONFIG_HOME"] else: cfg_home = os.path.join(os.path.expanduser("~"), ".config") if os.path.exists(os.path.join(cfg_home, "tmdbkey")): return open(os.path.join(cfg_home, "tmdbkey"), "r").read().strip() if os.path.exists(os.path.join(os.path.expanduser("~"), ".tmdbkey")): return open(os.path.exists(os.path.join(os.path.expanduser("~"), ".tmdbkey"))).read().strip() raise Exception("No TheMovieDB Key defined. Set Env. var. TMDB_KEY or write config key") class FocusableFrame(urwid.Frame): def keypress(self,size,key): x=('header', 'footer', 'body') if key == "tab": i = x.index(self.focus_position) self.set_focus(x[(i+1)%3]) else: self.__super.keypress(size,key) class SearchField(urwid.Edit): signals = ["activate"] def keypress(self,size,key): if key == "enter": self._emit("activate") else: self.__super.keypress(size,key) class UI(urwid.WidgetWrap): def __init__(self, term, search_service, loop=None): self.edit_search = SearchField(("bold", u"Search for: "), term) header = urwid.Pile([self.edit_search, urwid.Divider(), urwid.Text(("bold", u"Results:"))]) self.model = urwid.SimpleFocusListWalker([]) self.listbox = urwid.ListBox(self.model) btn_quit = urwid.Button(("button", u"Exit")) self.btn_apply = urwid.Button(("button", u"Apply")) self.description = urwid.Text(u"", align='center') self.btns = urwid.Columns([btn_quit, self.btn_apply]) footer = urwid.Pile([self.description, self.btns]) self.view = FocusableFrame(self.listbox, header=header, footer=footer, focus_part='header') super(UI, self).__init__(self.view) self.search_service = search_service self.loop = loop urwid.connect_signal(btn_quit, 'click', lambda *a: sys.exit(0)) urwid.connect_signal(self.edit_search, 'activate', self.search) def search(self, *_): @run_async def query(*_): results = self.search_service.search(self.edit_search.edit_text) self.fill_results(self.loop, results) self.view.set_focus("body") while len(self.model) > 0: self.model.pop() self.description.set_text(u"Searching for {}".format(self.edit_search.edit_text)) query() def fill_results(self, loop, data): for result in data: btn = urwid.Button(u"{release_date} - {title}".format(**result)) urwid.connect_signal(btn, 'click', self.select_movie, result["id"]) self.model.append(btn) loop.draw_screen() def select_movie(self, src, movie_id): @run_async def query(pos): try: info = self.search_service.info(movie_id) info["year"] = info["release_date"].split("-")[0] info["filename"] = u"{title} ({year}) #{imdb_id}".format(**info) self.model.remove( self.model[pos] ) btn = urwid.Button(u"{title} ({year}) #{imdb_id}".format(**info)) urwid.connect_signal(btn, 'click', self.rename, info) self.model.insert(pos, btn) self.description.set_text(('description',info["overview"])) except: self.description.set_text(('error', "Request failed")) finally: self.loop.draw_screen() pos = self.listbox.focus_position query(pos) def rename(self, src, info): def rename(*_): print info["filename"] sys.exit(1) self.description.set_text([ ("bold", u"Rename "), ("underline", u"foo"), " to ", ("underline", info["filename"]), " ?"]) self.view.set_focus("footer") self.btns.set_focus(self.btn_apply) urwid.connect_signal(self.btn_apply, 'click', rename) class Search(object): def __init__(self): self.tmdb_search = tmdb.Search() def search(self, term): return self.tmdb_search.movie(query=term)["results"] def info(self, id): return tmdb.Movies(id).info() if __name__ == "__main__": tmdb.API_KEY = read_key() palette = [ ('bold', 'default,bold', 'default', 'bold'), ('button', 'default,bold', 'default', 'bold', '', 'dark blue'), ('underline', 'default,underline', 'default', 'underline'), ('description', '', '', '', 'light gray', '')] args = sys.argv[1:] ui = UI(len(args) > 0 and " ".join(args) or "", Search()) loop = urwid.MainLoop(ui, palette) loop.screen.set_terminal_properties(colors=256) ui.loop = loop loop.run()