Be smarter about the generation of the filenames
This commit is contained in:
parent
28067b7632
commit
2dead3bacc
2 changed files with 93 additions and 64 deletions
|
@ -1,4 +1,5 @@
|
|||
#!/usr/local/bin/python
|
||||
# -*- coding: utf8 -*-
|
||||
|
||||
# Stefans Script, um die Sendungen vom Tivo runterzuladen und in MPEG4
|
||||
# zu transkodieren.
|
||||
|
@ -18,6 +19,7 @@ import functools
|
|||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import pytz
|
||||
import re
|
||||
import requests
|
||||
import signal
|
||||
|
@ -48,46 +50,51 @@ headers.update(
|
|||
}
|
||||
)
|
||||
|
||||
arset = dict()
|
||||
class IncludeShow:
|
||||
includes = dict()
|
||||
|
||||
def __init__(self, title, short=None):
|
||||
self.short = short
|
||||
self.title = title
|
||||
self.timestamp = False
|
||||
self.includes[title] = self
|
||||
|
||||
includes = dict()
|
||||
includes['Anthony Bourdain Parts Unknown'] = 1
|
||||
includes['Better Call Saul'] = 1
|
||||
includes['Brooklyn Nine-Nine'] = 1
|
||||
includes['Bull'] = 1
|
||||
includes['College Football'] = 1
|
||||
includes['Conan'] = 1
|
||||
includes["Dirk Gently's Holistic Detective Agency"] = 1
|
||||
includes['The Expanse'] = 1
|
||||
includes['Family Guy'] = 1
|
||||
includes['Full Frontal With Samantha Bee'] = 1
|
||||
includes['Hot in Cleveland'] = 1
|
||||
includes["How It's Made"] = 1
|
||||
includes["How Do They Do It?"] = 1
|
||||
includes["How We Got to Now With Steven Johnson"] = 1
|
||||
includes['Inside Amy Schumer'] = 1
|
||||
includes['Join or Die With Craig Ferguson'] = 1
|
||||
includes['Last Week Tonight With John Oliver'] = 1
|
||||
includes['Louie'] = 1
|
||||
includes['Mad Men'] = 1
|
||||
includes['Modern Family'] = 1
|
||||
includes['MythBusters'] = 1
|
||||
includes['MythBusters: The Search'] = 1
|
||||
includes['NCIS'] = 1
|
||||
includes['NCIS: New Orleans'] = 1
|
||||
#includes['NFL Football'] = 1
|
||||
includes['Person of Interest'] = 1
|
||||
includes['Saturday Night Live'] = 1
|
||||
includes['Sesame Street'] = 1
|
||||
includes["Somebody's Gotta Do It With Mike Rowe"] = 1
|
||||
includes['StarTalk'] = 1
|
||||
includes['The Big Bang Theory'] = 1
|
||||
includes['The Daily Show With Trevor Noah'] = 1
|
||||
includes['The Late Show With Stephen Colbert'] = 1
|
||||
#includes['The Late Late Show With James Corden'] = 1
|
||||
includes['The Muppets'] = 1
|
||||
includes['The X-Files'] = 1
|
||||
#includes['The Tonight Show Starring Jimmy Fallon'] = 1
|
||||
IncludeShow('Splash and Bubbles')
|
||||
IncludeShow('Angie Tribeca')
|
||||
IncludeShow('Anthony Bourdain Parts Unknown')
|
||||
IncludeShow('Better Call Saul')
|
||||
IncludeShow('Brooklyn Nine-Nine')
|
||||
IncludeShow('Bull')
|
||||
IncludeShow('College Football')
|
||||
IncludeShow('Conan')
|
||||
IncludeShow("Dirk Gently's Holistic Detective Agency", short='Dirk Gently')
|
||||
IncludeShow('The Expanse')
|
||||
IncludeShow('Family Guy')
|
||||
IncludeShow('Full Frontal With Samantha Bee', short='Full Frontal')
|
||||
IncludeShow("How It's Made")
|
||||
IncludeShow("How Do They Do It?")
|
||||
IncludeShow("How We Got to Now With Steven Johnson")
|
||||
IncludeShow('Inside Amy Schumer')
|
||||
IncludeShow('Join or Die With Craig Ferguson')
|
||||
IncludeShow('Last Week Tonight With John Oliver', short='John Oliver')
|
||||
IncludeShow('Louie')
|
||||
IncludeShow('Modern Family')
|
||||
IncludeShow('MythBusters')
|
||||
IncludeShow('NCIS')
|
||||
IncludeShow('NCIS: New Orleans')
|
||||
#IncludeShow('NFL Football')
|
||||
IncludeShow('Person of Interest')
|
||||
IncludeShow('Saturday Night Live', short='SNL')
|
||||
IncludeShow('Sesame Street')
|
||||
IncludeShow("Somebody's Gotta Do It With Mike Rowe")
|
||||
IncludeShow('StarTalk')
|
||||
IncludeShow('The Big Bang Theory')
|
||||
IncludeShow('The Daily Show With Trevor Noah', short='Daily Show')
|
||||
IncludeShow('The Late Show With Stephen Colbert', short='Colbert')
|
||||
#IncludeShow('The Late Late Show With James Corden')
|
||||
IncludeShow('The Muppets')
|
||||
IncludeShow('The X-Files')
|
||||
#IncludeShow('The Tonight Show Starring Jimmy Fallon')
|
||||
|
||||
|
||||
|
||||
|
@ -113,6 +120,17 @@ session.auth = requests.auth.HTTPDigestAuth("tivo", mak)
|
|||
session.keep_alive = False
|
||||
session.proxies = proxies
|
||||
|
||||
|
||||
def roundTime(dt=None, roundTo=60):
|
||||
"""
|
||||
http://stackoverflow.com/questions/3463930/how-to-round-the-minute-of-a-datetime-object-python
|
||||
"""
|
||||
if dt == None : dt = datetime.datetime.now()
|
||||
seconds = (dt.replace(tzinfo=None) - dt.min).seconds
|
||||
rounding = (seconds+roundTo/2) // roundTo * roundTo
|
||||
return dt + datetime.timedelta(0,rounding-seconds,-dt.microsecond)
|
||||
|
||||
|
||||
class TimeoutError(Exception):
|
||||
pass
|
||||
|
||||
|
@ -169,21 +187,18 @@ class TivoItem:
|
|||
self.episodeNumber = getTagText(i, "EpisodeNumber")
|
||||
self.description = trimDescription(getTagText(i, "Description"))
|
||||
d = getTagText(i, "CaptureDate")
|
||||
self.date = datetime.datetime.utcfromtimestamp(int(d, 16))
|
||||
self.time = int(d, base=0)
|
||||
self.date = datetime.datetime.fromtimestamp(int(d, 16), pytz.utc)
|
||||
est = pytz.timezone('US/Eastern')
|
||||
eastern = roundTime(self.date, 15*60).astimezone(est)
|
||||
self.datestr = self.date.strftime("%Y%m%d-%H%M")
|
||||
self.shortdate = eastern.strftime("%m%d-%H%M")
|
||||
self.url = getTagText(i, "Url")
|
||||
self.url = self.url + "&Format=video/x-tivo-mpeg-ts"
|
||||
self.inprogress = getTagText(i, "InProgress")
|
||||
self.available = getTagText(i, "Available")
|
||||
self.sourcesize = int(getTagText(i, "SourceSize"))
|
||||
self.highdef = getTagText(i, "HighDefinition")
|
||||
self.ar = 43
|
||||
self.unique = True
|
||||
if arset.has_key(self.title):
|
||||
self.ar = arset[self.title]
|
||||
elif self.highdef == "Yes":
|
||||
self.ar = "hd"
|
||||
if ignoreepisodetitle:
|
||||
self.episode = self.datestr
|
||||
if self.episode == "":
|
||||
|
@ -211,6 +226,22 @@ class TivoItem:
|
|||
self.name = self.name.encode("utf-8");
|
||||
self.dir = self.dir.encode("utf-8");
|
||||
self.file = self.file.encode("utf-8");
|
||||
def getPath(self, options):
|
||||
title = self.title
|
||||
if options.short:
|
||||
title = options.short
|
||||
if self.episodeNumber and self.episodeNumber != u'0':
|
||||
en = int(self.episodeNumber)
|
||||
if en >= 100:
|
||||
name = "%s S%02dE%02d %s" % (title, en / 100, en % 100, self.episode)
|
||||
else:
|
||||
name = "%s E%s %s" % (title, self.episodeNumber, self.episode)
|
||||
elif self.unique:
|
||||
name = "%s - %s" % (title, self.episode)
|
||||
else:
|
||||
name = "%s - %s %s" % (title, self.shortdate, self.episode)
|
||||
path = "%s/%s" % (self.dir, re.sub("[:/]", "-", name))
|
||||
return path.encode("utf-8");
|
||||
def __str__(self):
|
||||
return repr(self.title)
|
||||
|
||||
|
@ -351,6 +382,7 @@ def download_item(item, mak, target):
|
|||
url = item.url
|
||||
#url = re.sub("tivo.lassitu.de:80", "wavehh.lassitu.de:30080", url)
|
||||
logger.info("--- downloading \"%s\"" % (url))
|
||||
logger.info(" {}".format(target))
|
||||
start = time.time()
|
||||
r = session.get(url, stream=True, verify=False, proxies=proxies, headers=headers)
|
||||
r.raise_for_status()
|
||||
|
@ -419,8 +451,8 @@ def download_item(item, mak, target):
|
|||
raise TivoException("downloaded file is too small")
|
||||
|
||||
|
||||
def download_decode(item, mak):
|
||||
target = "%s.mpg" % item.file
|
||||
def download_decode(item, options, mak):
|
||||
target = "%s.mpg" % item.getPath(options)
|
||||
try:
|
||||
os.makedirs(item.dir)
|
||||
except OSError:
|
||||
|
@ -440,11 +472,11 @@ def download_decode(item, mak):
|
|||
logger.error("Problem setting timestamp: %" % (e))
|
||||
|
||||
|
||||
def download_one(item, downloaddb):
|
||||
def download_one(item, downloaddb, options):
|
||||
global logger, mak
|
||||
logger.info("*** downloading \"%s\": %.3fGB" % (item.name, item.sourcesize / 1e9))
|
||||
try:
|
||||
download_decode(item, mak)
|
||||
download_decode(item, options, mak)
|
||||
downloaddb[item.name] = item.datestr
|
||||
if getattr(downloaddb, "sync", None) and callable(downloaddb.sync):
|
||||
downloaddb.sync()
|
||||
|
@ -461,13 +493,10 @@ def wantitem(item, downloaddb):
|
|||
return "not available"
|
||||
if downloaddb.has_key(item.name):
|
||||
return "already downloaded"
|
||||
#if excludes.has_key(item.title) or excludes.has_key(item.episode) or excludes.has_key(item.name):
|
||||
# return "excluded"
|
||||
if includes.has_key(item.title) or includes.has_key(item.episode) or includes.has_key(item.name):
|
||||
pass
|
||||
else:
|
||||
return "not included"
|
||||
return ""
|
||||
for i in (item.title, item.episode, item.name):
|
||||
if IncludeShow.includes.has_key(i):
|
||||
return IncludeShow.includes[i]
|
||||
return "not included"
|
||||
|
||||
|
||||
def mirror(toc, downloaddb, one=False):
|
||||
|
@ -480,11 +509,11 @@ def mirror(toc, downloaddb, one=False):
|
|||
items = toc.getItems()
|
||||
logger.info("*** %d shows listed" % (len(items)))
|
||||
for item in items:
|
||||
reason = wantitem(item, downloaddb)
|
||||
if reason != "":
|
||||
logger.debug("*** skipping \"%s\": %s" % (item.name, reason))
|
||||
options = wantitem(item, downloaddb)
|
||||
if isinstance(options, basestring):
|
||||
logger.debug("*** skipping \"%s\": %s" % (item.name, options))
|
||||
else:
|
||||
download_one(item, downloaddb)
|
||||
download_one(item, downloaddb, options)
|
||||
if one:
|
||||
break
|
||||
|
||||
|
@ -506,9 +535,9 @@ def printtoc(toc, downloaddb):
|
|||
shows[item.title].append(item)
|
||||
for title in sorted(shows):
|
||||
for item in sorted(shows[title], key=lambda i: i.name):
|
||||
reason = wantitem(item, downloaddb)
|
||||
if (reason != ""):
|
||||
print "%-7.7s: %s" % (reason, item.name)
|
||||
options = wantitem(item, downloaddb)
|
||||
if isinstance(options, basestring):
|
||||
print "%-7.7s: %s" % (options, item.name)
|
||||
continue
|
||||
print "*** downloading %s (%.3fGB)" % (item.name, item.sourcesize / 1e9)
|
||||
|
Loading…
Reference in a new issue