From 4a6cfe415a0d362bf30f22fac16b732195f97232 Mon Sep 17 00:00:00 2001 From: Jeix Date: Fri, 11 Feb 2011 20:17:20 +0100 Subject: GUI updates, closed #181, updated XDCC, fixed FileSonic --- module/gui/Overview.py | 8 +-- module/gui/Queue.py | 51 +++++++++++-- module/network/RequestFactory.py | 7 +- module/network/XDCCRequest.py | 132 ++++++++++++++++++++++++++++++++++ module/plugins/hoster/EasyShareCom.py | 69 ++++++++++++++++++ module/plugins/hoster/FilesonicCom.py | 7 +- module/plugins/hoster/Xdcc.py | 46 +++++++++--- 7 files changed, 296 insertions(+), 24 deletions(-) create mode 100644 module/network/XDCCRequest.py create mode 100644 module/plugins/hoster/EasyShareCom.py (limited to 'module') diff --git a/module/gui/Overview.py b/module/gui/Overview.py index 205d85234..533c6faa8 100644 --- a/module/gui/Overview.py +++ b/module/gui/Overview.py @@ -160,10 +160,10 @@ class OverviewDelegate(QItemDelegate): size = "%s KiB" % kbytes return size - #if progress == 100: - sizeline = QString(_("Size: %s") % formatSize(maxSize)) - #else: - # sizeline = QString(_("Size: %s/%s") % (formatSize(currentSize), formatSize(maxSize))) + if progress in (0,100): + sizeline = QString(_("Size: %s") % formatSize(maxSize)) + else: + sizeline = QString(_("Size: %s / %s") % (formatSize(currentSize), formatSize(maxSize))) f = painter.font() f.setPointSize(12) diff --git a/module/gui/Queue.py b/module/gui/Queue.py index 9751b652f..1b9f98259 100644 --- a/module/gui/Queue.py +++ b/module/gui/Queue.py @@ -23,10 +23,22 @@ from time import sleep, time from module.gui.Collector import CollectorModel, Package, Link, CollectorView, statusMap, statusMapReverse +def formatSize(size): + """formats size of bytes""" + size = int(size) + steps = 0 + sizes = ["B", "KB", "MB", "GB", "TB"] + + while size > 1000: + size /= 1024.0 + steps += 1 + + return "%.2f %s" % (size, sizes[steps]) + class QueueModel(CollectorModel): def __init__(self, view, connector): CollectorModel.__init__(self, view, connector) - self.cols = 6 + self.cols = 9 self.wait_dict = {} self.updater = self.QueueUpdater(self.interval) @@ -106,8 +118,14 @@ class QueueModel(CollectorModel): elif section == 3: return QVariant(_("Priority")) elif section == 4: - return QVariant(_("ETA")) + return QVariant(_("Current")) elif section == 5: + return QVariant(_("Left")) + elif section == 6: + return QVariant(_("Size")) + elif section == 7: + return QVariant(_("ETA")) + elif section == 8: return QVariant(_("Progress")) return QVariant() @@ -213,6 +231,26 @@ class QueueModel(CollectorModel): if isinstance(item, Package): return QVariant(item.data["priority"]) elif index.column() == 4: + item = index.internalPointer() + if isinstance(item, Link): + if item.data["downloading"]: + return QVariant("%s" % formatSize(item.data["size"]-item.data["downloading"]["bleft"])) + elif isinstance(item, Package): + return QVariant("packRecv") + elif index.column() == 5: + item = index.internalPointer() + if isinstance(item, Link): + if item.data["downloading"]: + return QVariant("%s" % formatSize(item.data["downloading"]["bleft"])) + elif isinstance(item, Package): + return QVariant("packLeft") + elif index.column() == 6: + item = index.internalPointer() + if isinstance(item, Link): + return QVariant("%s" % item.data["format_size"]) + elif isinstance(item, Package): + return QVariant("packSize") + elif index.column() == 7: item = index.internalPointer() if isinstance(item, Link): if item.data["downloading"]: @@ -236,13 +274,14 @@ class QueueView(CollectorView): self.setColumnWidth(1, 100) self.setColumnWidth(2, 150) self.setColumnWidth(3, 50) - self.setColumnWidth(4, 70) - self.setColumnWidth(5, 80) + self.setColumnWidth(4, 80) + self.setColumnWidth(5, 70) + self.setColumnWidth(6, 80) self.setEditTriggers(QAbstractItemView.NoEditTriggers) self.delegate = QueueProgressBarDelegate(self, self.model()) - self.setItemDelegateForColumn(5, self.delegate) + self.setItemDelegateForColumn(8, self.delegate) class QueueProgressBarDelegate(QItemDelegate): def __init__(self, parent, queue): @@ -252,7 +291,7 @@ class QueueProgressBarDelegate(QItemDelegate): def paint(self, painter, option, index): if not index.isValid(): return - if index.column() == 5: + if index.column() == 8: item = index.internalPointer() w = self.queue.getWaitingProgress(item) wait = None diff --git a/module/network/RequestFactory.py b/module/network/RequestFactory.py index 8340d06f7..90a48fe3c 100644 --- a/module/network/RequestFactory.py +++ b/module/network/RequestFactory.py @@ -24,6 +24,8 @@ from Bucket import Bucket from HTTPRequest import HTTPRequest from CookieJar import CookieJar +from XDCCRequest import XDCCRequest + class RequestFactory(): def __init__(self, core): self.lock = Lock() @@ -35,9 +37,12 @@ class RequestFactory(): def iface(self): return self.core.config["download"]["interface"] - def getRequest(self, pluginName, account=None): + def getRequest(self, pluginName, account=None, type="HTTP"): self.lock.acquire() + if type == "XDCC": + return XDCCRequest(proxies=self.getProxies()) + req = Browser(self.iface(), self.bucket, self.getProxies()) if account: diff --git a/module/network/XDCCRequest.py b/module/network/XDCCRequest.py new file mode 100644 index 000000000..126662bb8 --- /dev/null +++ b/module/network/XDCCRequest.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, + or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . + + @author: jeix +""" + +import socket +import re + +from os.path import exists + +from time import time + +import struct +from select import select + +class XDCCError(Exception): + pass + +class XDCCRequest(): + def __init__(self, timeout=30, proxies={}): + + self.proxies = proxies + self.timeout = timeout + + self.filesize = 0 + self.recv = 0 + self.speed = 0 + + self.abort = False + + + def createSocket(self): + # proxytype = None + # proxy = None + # if self.proxies.has_key("socks5"): + # proxytype = socks.PROXY_TYPE_SOCKS5 + # proxy = self.proxies["socks5"] + # elif self.proxies.has_key("socks4"): + # proxytype = socks.PROXY_TYPE_SOCKS4 + # proxy = self.proxies["socks4"] + # if proxytype: + # sock = socks.socksocket() + # t = _parse_proxy(proxy) + # sock.setproxy(proxytype, addr=t[3].split(":")[0], port=int(t[3].split(":")[1]), username=t[1], password=t[2]) + # else: + # sock = socket.socket() + # return sock + + return socket.socket() + + def download(self, ip, port, filename, progressNotify=None): + + lastRecv = time() + + dccsock = self.createSocket() + + dccsock.settimeout(self.timeout) + dccsock.connect((ip, port)) + + if exists(filename): + i = 0 + nameParts = filename.rpartition(".") + while True: + newfilename = "%s-%d%s%s" % (nameParts[0], i, nameParts[1], nameParts[2]) + i += 1 + + if not exists(newfilename): + filename = newfilename + break + + fh = open(filename, "wb") + + # recv loop for dcc socket + while True: + if self.abort: + break + + data = dccsock.recv(4096) + dataLen = len(data) + self.recv += dataLen + + now = time() + timespan = now - lastRecv + if timespan: + self.speed = dataLen / timespan + if progressNotify: + progressNotify(self.percent) + lastRecv = now + + if not data: + break + + fh.write(data) + + # acknowledge data by sending number of recceived bytes + dccsock.send(struct.pack('!I', self.recv)) + + dccsock.close() + fh.close() + + return filename + + + @property + def size(self): + return self.filesize + + @property + def arrived(self): + return self.recv + + @property + def percent(self): + if not self.filesize: return 0 + return (self.recv * 100) / self.filesize + + def close(self): + pass diff --git a/module/plugins/hoster/EasyShareCom.py b/module/plugins/hoster/EasyShareCom.py new file mode 100644 index 000000000..9d185f4b5 --- /dev/null +++ b/module/plugins/hoster/EasyShareCom.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re +from module.plugins.Hoster import Hoster +from module.plugins.ReCaptcha import ReCaptcha + +class EasyShareCom(Hoster): + __name__ = "EasyShareCom" + __type__ = "hoster" + __pattern__ = r"http://[\w\d\.]*?easy-share\.com/(\d{6}).*" + __version__ = "0.1" + __description__ = """easy-share.com One-Klick Hoster""" + __author_name__ = ("jeix") + __author_mail__ = ("jeix@hasnomail.de") + + + def setup(self): + self.multiDL = False + self.html = None + + def process(self, pyfile): + self.pyfile = pyfile + + self.html = self.load(self.pyfile.url) + self.pyfile.name = self.getFileName() + + self.download( self.getFileUrl() ) + + + def getFileName(self): + return re.search(r'requesting:\s*(.*?)<', self.html).group(1) + + + def getFileUrl(self): + + if "There is another download in progress from your IP" in self.html: + self.log.info("%s: IP blocked, retry in 5 minutes." % self.__name__) + self.setWait(5 * 60) + self.wait() + self.retry() + + if "You need a premium membership to download this file" in self.html: + self.fail("You need a premium membership to download this file.") + + + wait = re.search(r"w='(\d+)'", self.html) + if wait: + wait = int( wait.group(1).strip() ) + self.log.info("%s: Waiting %d seconds." % (self.__name__, wait)) + self.setWait(wait) + self.wait() + + tempurl = self.pyfile.url + if not tempurl.endswith("/"): + tempurl += "/" + id = re.search(r'http://[\w\d\.]*?easy-share\.com/(\d+)/', tempurl).group(1) + self.html = self.load("http://www.easy-share.com/file_contents/captcha/" + id) + + challenge = re.search(r'Recaptcha\.create\("(.*?)"', self.html).group(1) + re_captcha = ReCaptcha(self) + challenge, result = re_captcha.challenge(challenge) + + link = re.search(r'', self.html).group(1) + id = re.search(r'file/id/(\d+)/', link) + self.download( link, post={"id" : id, + "recaptcha_challenge_field" : challenge, + "recaptcha_response_field": result} ) + diff --git a/module/plugins/hoster/FilesonicCom.py b/module/plugins/hoster/FilesonicCom.py index 5e2c10219..5bd38655a 100644 --- a/module/plugins/hoster/FilesonicCom.py +++ b/module/plugins/hoster/FilesonicCom.py @@ -11,7 +11,7 @@ class FilesonicCom(Hoster): __name__ = "FilesonicCom" __type__ = "hoster" __pattern__ = r"http://[\w\.]*?(sharingmatrix|filesonic)\.(com|net)/.*?file/([0-9]+(/.+)?|[a-z0-9]+/[0-9]+(/.+)?)" - __version__ = "0.1" + __version__ = "0.2" __description__ = """FilesonicCom und Sharingmatrix Download Hoster""" __author_name__ = ("jeix") __author_mail__ = ("jeix@hasnomail.de") @@ -25,11 +25,14 @@ class FilesonicCom(Hoster): self.url = self.convertURL(self.pyfile.url) self.html = self.load(self.url, cookies=False) - name = re.search(r'Filename:\s*\s*(.*?)<', self.html) + name = re.search(r'Download (.*?) for free on Filesonic.com', self.html) if name: self.pyfile.name = name.group(1) else: self.offline() + + if 'The page you are trying to access was not found.' in self.html: + self.offline() if self.account: self.download(pyfile.url) diff --git a/module/plugins/hoster/Xdcc.py b/module/plugins/hoster/Xdcc.py index bc35cf6ea..4ed718823 100644 --- a/module/plugins/hoster/Xdcc.py +++ b/module/plugins/hoster/Xdcc.py @@ -25,13 +25,14 @@ import sys import time import socket, struct from select import select +from module.utils import save_join from module.plugins.Hoster import Hoster class Xdcc(Hoster): __name__ = "Xdcc" - __version__ = "0.2" + __version__ = "0.3" __pattern__ = r'xdcc://.*?(/#?.*?)?/.*?/#?\d+/?' # xdcc://irc.Abjects.net/#channel/[XDCC]|Shit/#0004/ __type__ = "hoster" __config__ = [ @@ -44,11 +45,16 @@ class Xdcc(Hoster): __author_mail__ = ("jeix@hasnomail.com") def setup(self): - self.debug = 0 #0,1,2 + self.debug = 2 #0,1,2 self.timeout = 10 self.multiDL = False + + def process(self, pyfile): + # change request type + self.req = pyfile.m.core.requestFactory.getRequest(self.__name__, type="XDCC") + self.pyfile = pyfile for i in range(0,3): try: @@ -142,7 +148,7 @@ class Xdcc(Hoster): readbuffer = temp.pop() for line in temp: - if self.debug is 2: print "*> " + line + if self.debug is 2: print "*> " + unicode(line, errors='ignore') line = line.rstrip() first = line.split() @@ -182,6 +188,7 @@ class Xdcc(Hoster): if self.debug is 1: print "%s: %s" % (msg["origin"], msg["text"]) + # You already requested that pack if "You already requested that pack" in msg["text"]: retry = time.time() + 300 @@ -189,27 +196,44 @@ class Xdcc(Hoster): self.fail("Wrong channel") m = re.match('\x01DCC SEND (.*?) (\d+) (\d+)(?: (\d+))?\x01', msg["text"]) - if m is not None: + if m != None: done = True # get connection data ip = socket.inet_ntoa(struct.pack('L', socket.ntohl(int(m.group(2))))) port = int(m.group(3)) - packname = m.group(1) + packname = m.group(1) if len(m.groups()) > 3: - self.req.dl_size = int(m.group(4)) + self.req.filesize = int(m.group(4)) self.pyfile.name = packname + filename = save_join(location, packname) self.log.info("XDCC: Downloading %s from %s:%d" % (packname, ip, port)) - + self.pyfile.setStatus("downloading") - newname = self.req.download(ip, port, location, packname) - self.pyfile.size = self.req.dl_size + newname = self.req.download(ip, port, filename, self.pyfile.progress.setValue) + if newname and newname != filename: + self.log.info("%(name)s saved as %(newname)s" % {"name": self.pyfile.name, "newname": newname}) + filename = newname # kill IRC socket # sock.send("QUIT :byebye\r\n") sock.close() - if newname: - self.pyfile.name = newname + if self.core.config["permission"]["change_file"]: + chmod(filename, int(self.core.config["permission"]["file"],8)) + + if self.core.config["permission"]["change_dl"] and os.name != "nt": + try: + uid = getpwnam(self.config["permission"]["user"])[2] + gid = getgrnam(self.config["permission"]["group"])[2] + + chown(filename, uid, gid) + except Exception,e: + self.log.warning(_("Setting User and Group failed: %s") % str(e)) + + self.lastDownload = filename + return self.lastDownload + + -- cgit v1.2.3