#!/usr/bin/env python # vim:et:ts=4 # Adam's modified BitTorrent client for btqueue # Based upon btdownloadheadless.py: # Written by Bram Cohen # see LICENSE.txt for license information import sys, os.path, threading, os, signal, time from BitTorrent.download import download if os.environ.has_key("http_proxy"): del os.environ["http_proxy"] def format_time(n): if n == -1: return '-' n = int(n) h, r = divmod(n, 60 * 60) m, sec = divmod(r, 60) if h > 1000000: return 'lots' elif h > 0: return '%dh%02dm%02ds' % (h, m, sec) elif m > 0: return '%02dm%02ds' % (m, sec) else: return '%02ds' % (sec) class QueueDisplayer: def __init__(self, fd, config): self.complete_time = -1 self.size = None self.fd = fd self.config = config self.state = {"state": "startup"} def terminate(self, code): # Ugly, but... os.kill(os.getpid(), signal.SIGINT) def finished(self): self.complete_time = time.time() self.display() def failed(self): self.state["state"] = "failed" self.display() self.terminate(1) def error(self, errormsg): print "error", errormsg def display(self, dict = {}): fractionDone = dict.get("fractionDone") timeEst = dict.get("timeEst") downRate = dict.get("downRate") upRate = dict.get("upRate") activity = dict.get("activity") should_exit = 0 if downRate is not None: self.state["down"] = float(downRate) / (1 << 10) if upRate is not None: self.state["up"] = float(upRate) / (1 << 10) if self.size is not None: self.state["size"] = self.size if fractionDone is not None: self.state["pct"] = str(float(int(fractionDone * 1000)) / 10) if timeEst is not None: self.state["eta"] = format_time(timeEst) self.state["state"] = "peer" if activity is not None: a = activity.replace(" ", "").lower() if a == "checkingexistingfile": a = "checking" elif a == "connectingtopeers": a = "conn" self.state["state"] = a if self.complete_time != -1: t = time.time() - self.complete_time seed_time = int(self.config["seed-time"]) * 60 if seed_time != 0: self.state["eta"] = format_time(seed_time - t) if t >= seed_time: should_exit = 1 else: self.state["eta"] = "-" self.state["state"] = "seed" self.state["down"] = 0.0 self.state["pct"] = "100.0" s = " ".join([k + "=" + str(self.state[k]) for k in self.state.keys()]) os.write(self.fd, s + "\n") if should_exit: self.terminate(0) def chooseFile(self, default, size, saveas, dir): self.size = size filename = os.path.basename(os.path.abspath(default)) self.dest = os.path.join(self.config["download-dir"], filename) if saveas != '': self.dest = saveas return self.dest def do_download(file, fd, config): args = [] for arg, value in config.items(): if not arg.startswith("bt-"): continue args.append("--" + arg[3:]) args.append(value) args += ["--responsefile", file] h = QueueDisplayer(fd, config) try: download(args, h.chooseFile, h.display, h.finished, h.error, threading.Event(), 80) except KeyboardInterrupt: if h.complete_time == -1: os.write(fd, "state=interrupt\n") os._exit(0)