Created
January 26, 2013 04:03
-
-
Save philipbjorge/4640105 to your computer and use it in GitHub Desktop.
goatee - Minimal sickbeard replacement using nzbx.co for data
Requires the following python modules:
guessit
fileDownloader.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
__author__ = 'philipbjorge' | |
import sys, urllib, json, argparse, urllib2 | |
from os import remove | |
from os.path import abspath, isdir, join, exists, getsize | |
from guessit import guess_episode_info | |
from collections import defaultdict | |
from sys import stderr | |
import fileDownloader | |
DEBUG = True | |
def main(): | |
def ui(s): | |
print s | |
def dbg(s): | |
if DEBUG: | |
ui(s) | |
def err(s): | |
print >> stderr, s | |
parser = argparse.ArgumentParser(description='Minimal alternative to Sickbeard.') | |
parser.add_argument("-l", "--location", help="where the nzbs will be downloaded to", required=False, default=".") | |
parser.add_argument("query", help="the tv show to search nzbx.co for") | |
args = parser.parse_args() | |
if not isdir(abspath(args.location)): | |
print abspath(args.location) + " is not a valid download directory" | |
return 1 | |
ui(abspath(args.location) + " where I'll be saving nzbs") | |
url = "https://nzbx.co/api/search?q=" + urllib.quote_plus(args.query) | |
try: | |
result = json.load(urllib.urlopen(url)) | |
except Exception: | |
err("Error connecting connecting to nzbx or reading it's data") | |
exit() | |
""" | |
{ | |
name: "Sid.The.Science.Kid.E132.Special.Sunny.Dad.Day.WS.DSR.XviD-WaLMaRT", | |
spam: 0, | |
fromname: "teevee@4u.net (teevee)", | |
size: 297497475, | |
groupid: 4, | |
categoryid: 5030, | |
totalpart: 29, | |
completion: 100, | |
rageid: "-1", | |
imdbid: "", | |
comments: "0", | |
guid: "b961cd22eb47939133b03515ddf644b2", | |
adddate: 1355650196, | |
postdate: 1254843914, | |
downloads: "0", | |
votes: { | |
upvotes: 0, | |
downvotes: 0 | |
}, | |
nzb: "https://nzbx.co/nzb?b961cd22eb47939133b03515ddf644b2*|*Sid.The.Science.Kid.E132.Special.Sunny.Dad.Day.WS.DSR.XviD-WaLMaRT" | |
} | |
""" | |
# Construct a 2 level tree | |
# First level = season | |
# Second level = episode -- this node contains a list of all matching nzbs | |
episode_bucket_tree = defaultdict(lambda : defaultdict(list)) | |
for nzb in result: | |
filename, category = nzb["name"], nzb["categoryid"] | |
# filters bucket to include only TV category | |
if 5000 <= category and category <= 5999: | |
nzb_episode_info = guess_episode_info(filename) | |
# Filter for only very complete metadata | |
if "season" in nzb_episode_info and "episodeNumber" in nzb_episode_info\ | |
and "series" in nzb_episode_info and nzb_episode_info["series"].strip().lower() == args.query.strip().lower(): | |
nzb_episode_info["nzb"] = nzb["nzb"] | |
episode_bucket_tree[nzb_episode_info["season"]][nzb_episode_info["episodeNumber"]].append(nzb_episode_info) | |
id_to_nzb = defaultdict(list) | |
n = 0 | |
nzb_list_output = "" | |
for season, episodes in sorted(episode_bucket_tree.items()): | |
if isinstance(season, (int, long)) and season > 0: | |
nzb_list_output += "Season %d\n" % season | |
id_to_nzb["s%d" % season] = list() | |
for episode, nzbs in sorted(episodes.items()): | |
if isinstance(episode, (int, long)) and episode > 0: | |
nzb_list_output += "%d x\t\t" % len(nzbs) | |
nzb_list_output += "%sS%dE%d\t\tid=%d\n" % (args.query, nzbs[0]["season"], nzbs[0]["episodeNumber"], n) | |
id_to_nzb[n] = nzbs | |
id_to_nzb["s%d" % season].append(nzbs) | |
n += 1 | |
print nzb_list_output | |
need_more_shows = True | |
show_or_ep = "" | |
while need_more_shows: | |
ui("Type q to quit") | |
while show_or_ep.lower() != "s" and show_or_ep.lower() != "e": | |
show_or_ep = raw_input("Season or Episode? [s/e]: ") | |
if show_or_ep.lower() == "q": | |
exit() | |
if show_or_ep.lower() == "s": | |
# SEASON DL | |
nos = raw_input("Season no(s) seperated by spaces to download: ") | |
if "q" in nos.lower(): | |
exit() | |
ids = map(int, nos.split()) | |
for i in ids: | |
try: | |
for eps in id_to_nzb["s%d" % i]: | |
# multiple episode nzb options | |
for ep in eps: | |
ui("Downloading %s" % ep["nzb"]) | |
fname = "%sS%dE%d.nzb" % (args.query, ep["season"], ep["episodeNumber"]) | |
fname = join(abspath(args.location), fname) | |
try: | |
dl = fileDownloader.DownloadFile(ep["nzb"], join(abspath(args.location), fname), timeout=20.0, autoretry=True, retries=3) | |
dl.download() | |
except urllib2.URLError: | |
pass | |
if exists(fname): | |
break | |
if not exists(fname) or getsize(fname) < 1: | |
if exists(fname): | |
remove(fname) | |
err("No nzb was downloaded for %s" % fname) | |
except Exception as e: | |
print e | |
err("invalid season %d" % i) | |
else: | |
# EPISODE DL | |
ids = map(int, raw_input("ID(s) seperated by spaces to download (right column): ").split()) | |
for i in ids: | |
try: | |
# multiple episode nzb options | |
ui("Downloading %s" % id_to_nzb[i][0]["nzb"]) | |
for nzb in id_to_nzb[i]: | |
fname = "%sS%dE%d.nzb" % (args.query, nzb["season"], nzb["episodeNumber"]) | |
fname = join(abspath(args.location), fname) | |
try: | |
dl = fileDownloader.DownloadFile(nzb["nzb"], join(abspath(args.location), fname), timeout=20.0, autoretry=True, retries=3) | |
dl.download() | |
except urllib2.URLError: | |
pass | |
if exists(fname): | |
break | |
if not exists(fname) or getsize(fname) < 1: | |
if exists(fname): | |
remove(fname) | |
err("No nzb was downloaded for %s" % fname) | |
except Exception as e: | |
err("invalid id %d" % i) | |
print nzb_list_output | |
show_or_ep = "" | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment