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