def media(media_id): if media_id == "disc": item = { "category": media_id } else: media_id = int(media_id) database = Database() item = database.select_media(media_id) if item["category"].lower() == "television": item["season"] = str(item["name_two"]).zfill(2) item["episode"] = str(item["name_three"]).zfill(2) item["previous"], item["next"] = retrieve.get_nearby_episodes(media_id) data = database.select_viewed(media_id) if data: item["viewed"] = retrieve.get_viewed_date(data["viewed"]) item["elapsed"] = data["elapsed"] queue = True if retrieve.get_playing_snakes() else False return flask.render_template("media.html", page="media", item=item, queue=queue)
def get_continue_media(): database = Database() viewed = database.select_viewed() for item in viewed: try: media_id = int(item.get("id")) info = database.select_media(media_id) except Exception: continue if not info: return info["id"] = media_id info["elapsed"] = int(item.get("elapsed") or 0) category = info.get("category").lower() if category in ["film", "television"]: if info["elapsed"] > 0: return info if category == "television": previous, next = get_nearby_episodes(media_id) if next: info = database.select_media(next) info["id"] = next info["elapsed"] = 0 return info
def __init__(self): super(IndexThread, self).__init__() self.database = Database() self.naming = self._get_naming() self.now = False self.stop = False
def update_viewed(media_id, elapsed=None, delete=False): try: database = Database() try: info = database.select_media(int(media_id)) except Exception: info = {} if info.get("category") in config.getlist("viewed", "no_history"): return "0" if elapsed: database.update_viewed(media_id, elapsed) elif delete: database.delete_viewed(media_id) else: database.insert_viewed(media_id) return "0" except Exception as excp: log.error("Update viewed failed: %s", excp) return "1"
def browse_artist(artist): albums = set() data = Database().select_category("music") for key, value in data.items(): if value["name_one"] == artist: albums.add(value["name_two"]) albums = sorted(albums) return flask.render_template("browse.html", page="browse", artist=artist, albums=albums)
def get_nearby_episodes(media_id): episodes = Database().select_category("television") index = episodes.keys().index(media_id) previous = episodes.keys()[index - 1] next = episodes.keys()[index + 1] show = episodes[media_id]["name_one"] if episodes[previous]["name_one"] != show: previous = None if episodes[next]["name_one"] != show: next = None return previous, next
def browse_television(): items = OrderedDict() shows = [] data = Database().select_category("television") for key, value in data.items(): show = value["name_one"] if show not in shows: shows.append(show) items[key] = value return flask.render_template("browse.html", page="browse", category="television", items=items)
def browse_season(show, season): episodes = [] data = Database().select_category("television") for key, value in data.items(): if value["name_one"] == show and value["name_two"] == season: info = value info["id"] = key episodes.append(info) episodes = sorted(episodes, key=lambda k: int(k["name_three"])) return flask.render_template("browse.html", page="browse", show=show, season=season, episodes=episodes)
def browse_show(show): seasons = set() data = Database().select_category("television") for key, value in data.items(): if value["name_one"] == show: seasons.add(value["name_two"]) seasons = sorted(seasons) continue_ = retrieve.get_continue_media_by_show(show) return flask.render_template("browse.html", page="browse", show=show, seasons=seasons, continue_=continue_)
def browse_album(artist, album): tracks = [] data = Database().select_category("music") for key, value in data.items(): if value["name_one"] == artist and value["name_two"] == album: info = value info["id"] = key tracks.append(info) tracks = sorted(tracks, key=lambda k: k["name_three"]) return flask.render_template("browse.html", page="browse", artist=artist, album=album, tracks=tracks)
def browse_music(): items = OrderedDict() artists = set() data = Database().select_category("music") for value in data.values(): artists.add(value["name_one"]) for artist in sorted(artists): items[artist] = { "name_one": artist } return flask.render_template("browse.html", page="browse", category="music", items=items)
def get_continue_media_by_show(show): media_id = Database().select_latest_viewed_by_show(show) if not media_id: return previous, next = get_nearby_episodes(int(media_id)) return next
def get_viewed_items(): items = OrderedDict() for i in enumerate(Database().select_viewed()): media_id = i[1]["id"] name = None if media_id.isdigit(): data = Database().select_media(int(media_id)) if data: name = categories.format_media_name(data) else: name = media_id if name: items[media_id] = {"name_one": name} return items
def get_new_items(): path = config.get("browse", "downloads") video_formats = config.getlist("index", "video_formats") items = OrderedDict() files = [] for root, directories, files_ in os.walk(unicode(path)): for f in files_: extension = os.path.splitext(f)[-1].lstrip(".") if extension in video_formats: modified = os.path.getmtime(os.path.join(root, f)) files.append((modified, f, None)) for item in Database().select_new(): files.append( (item["modified"], categories.format_media_name(item), item["id"])) for i in enumerate(sorted(files, reverse=True)): items[i[0]] = {"name_one": i[1][-2], "id": i[1][-1]} return items
def queue_tracks(snake, value): """ Queue up the remaining tracks of an album. """ # If we get no tracks, this probably wasn't an album. tracks = Database().select_next_tracks(value) if tracks: queue_up = False for track in tracks: track_id = track["id"] if not queue_up: # Don't begin queuing until we have passed the user selected # track. # if track_id == int(value): queue_up = True continue Communicate().send([snake], {"action": ["queue", [track_id]]})
class IndexThread(threading.Thread): def __init__(self): super(IndexThread, self).__init__() self.database = Database() self.naming = self._get_naming() self.now = False self.stop = False def run(self): """ Check every 5 seconds if it is time to index. """ i = 0 while True: i += 5 if not self.stop: if self.now: self.now = False self.index() if i >= config.getint("index", "interval"): i = 0 self.index() time.sleep(5) def index(self): log.warn("About to index media") self.stop = True media = [] for category, value in self.naming.items(): path = value.get("path") names = value.get("names") expressions = [] for name in names: expressions.append(self._format_expression(name)) media.extend(self.find_media(category, path, expressions)) self.insert_new_media(media) self.delete_missing_media() self.now = False self.stop = False log.warn("Finished indexing media") #-------------------------------------------------------------------------- def find_media(self, category, path, expressions): media = [] deep = False if category in config.getlist("index", "deep"): deep = True if category in config.getlist("index", "audio_categories"): allowed_formats = config.getlist("index", "audio_formats") else: allowed_formats = config.getlist("index", "video_formats") for root, directories, files in os.walk(unicode(path)): data = {} paths = [] data["category"] = category for f in files: if f.startswith("."): continue sub_data = {} sub_paths = [] sub_data["category"] = category f = os.path.join(root, f) short_path = f.replace("%s/" % os.path.dirname(path), "", 1) paths.append(short_path) sub_paths.append(short_path) extension = os.path.splitext(os.path.basename(f))[-1].replace( ".", "", 1) if extension not in allowed_formats: continue if not deep and data.get("extension"): continue data["extension"] = extension sub_data["extension"] = extension match_path = os.path.splitext(short_path)[0] for expression in expressions: matches = expression.match(match_path) if matches: break if not matches: log.error("Failed to expression match %s", match_path) continue result = getattr(categories, "parse_%s" % category.lower())(matches) data.update(result) sub_data.update(result) try: modified = int(os.stat(f).st_mtime) except Exception: modified = 0 data["modified"] = modified sub_data["modified"] = modified if not sub_paths or not sub_data.get("name_one"): continue sub_data["paths"] = sub_paths if deep: media.append(sub_data) if not paths or not data.get("name_one"): continue data["paths"] = paths if not deep: media.append(data) return media def insert_new_media(self, media): self.database.insert_media(media) def delete_missing_media(self): to_delete = set() for item in self.database.select_all_media(): category = item["category"] base_path = os.path.dirname(self.naming[category]["path"]) for path in item["paths"]: if not os.path.exists(os.path.join(base_path, path)): to_delete.add(int(item["id"])) self.database.delete_media(to_delete) #-------------------------------------------------------------------------- def _get_naming(self): naming_path = os.path.join(config.base_path, config.get("files", "naming")) with open(naming_path, "r") as file_: naming = json.load(file_) return naming def _format_expression(self, string): for character in ESCAPES: string = string.replace(character, "\\%s" % character) return re.compile(string.format(**EXPRESSIONS))
class IndexThread(threading.Thread): def __init__(self): super(IndexThread, self).__init__() self.database = Database() self.naming = self._get_naming() self.now = False self.stop = False def run(self): """ Check every 5 seconds if it is time to index. """ i = 0 while True: i += 5 if not self.stop: if self.now: self.now = False self.index() if i >= config.getint("index", "interval"): i = 0 self.index() time.sleep(5) def index(self): log.warn("About to index media") self.stop = True media = [] for category, value in self.naming.items(): path = value.get("path") names = value.get("names") expressions = [] for name in names: expressions.append(self._format_expression(name)) media.extend(self.find_media(category, path, expressions)) self.insert_new_media(media) self.delete_missing_media() self.now = False self.stop = False log.warn("Finished indexing media") #-------------------------------------------------------------------------- def find_media(self, category, path, expressions): media = [] deep = False if category in config.getlist("index", "deep"): deep = True if category in config.getlist("index", "audio_categories"): allowed_formats = config.getlist("index", "audio_formats") else: allowed_formats = config.getlist("index", "video_formats") for root, directories, files in os.walk(unicode(path)): data = {} paths = [] data["category"] = category for f in files: if f.startswith("."): continue sub_data = {} sub_paths = [] sub_data["category"] = category f = os.path.join(root, f) short_path = f.replace("%s/" % os.path.dirname(path), "", 1) paths.append(short_path) sub_paths.append(short_path) extension = os.path.splitext(os.path.basename(f))[-1].replace(".", "", 1) if extension not in allowed_formats: continue if not deep and data.get("extension"): continue data["extension"] = extension sub_data["extension"] = extension match_path = os.path.splitext(short_path)[0] for expression in expressions: matches = expression.match(match_path) if matches: break if not matches: log.error("Failed to expression match %s", match_path) continue result = getattr(categories, "parse_%s" % category.lower())(matches) data.update(result) sub_data.update(result) try: modified = int(os.stat(f).st_mtime) except Exception: modified = 0 data["modified"] = modified sub_data["modified"] = modified if not sub_paths or not sub_data.get("name_one"): continue sub_data["paths"] = sub_paths if deep: media.append(sub_data) if not paths or not data.get("name_one"): continue data["paths"] = paths if not deep: media.append(data) return media def insert_new_media(self, media): self.database.insert_media(media) def delete_missing_media(self): to_delete = set() for item in self.database.select_all_media(): category = item["category"] base_path = os.path.dirname(self.naming[category]["path"]) for path in item["paths"]: if not os.path.exists(os.path.join(base_path, path)): to_delete.add(int(item["id"])) self.database.delete_media(to_delete) #-------------------------------------------------------------------------- def _get_naming(self): naming_path = os.path.join(config.base_path, config.get("files", "naming")) with open(naming_path, "r") as file_: naming = json.load(file_) return naming def _format_expression(self, string): for character in ESCAPES: string = string.replace(character, "\\%s" % character) return re.compile(string.format(**EXPRESSIONS))
def get_media(media_id): return Database().select_media(media_id)
def search_media(term): return {"media": Database().select_like_media(term)}