diff options
author | Jeix <devnull@localhost> | 2011-02-11 20:17:20 +0100 |
---|---|---|
committer | Jeix <devnull@localhost> | 2011-02-11 20:17:20 +0100 |
commit | 4a6cfe415a0d362bf30f22fac16b732195f97232 (patch) | |
tree | f90318302830b967b4734fc1e7d82eda6d52a8fc | |
parent | socket code fixes (diff) | |
download | pyload-4a6cfe415a0d362bf30f22fac16b732195f97232.tar.xz |
GUI updates, closed #181, updated XDCC, fixed FileSonic
-rw-r--r-- | module/gui/Overview.py | 8 | ||||
-rw-r--r-- | module/gui/Queue.py | 51 | ||||
-rw-r--r-- | module/network/RequestFactory.py | 7 | ||||
-rw-r--r-- | module/network/XDCCRequest.py | 132 | ||||
-rw-r--r-- | module/plugins/hoster/EasyShareCom.py | 69 | ||||
-rw-r--r-- | module/plugins/hoster/FilesonicCom.py | 7 | ||||
-rw-r--r-- | module/plugins/hoster/Xdcc.py | 46 |
7 files changed, 296 insertions, 24 deletions
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() @@ -216,6 +234,26 @@ class QueueModel(CollectorModel): 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"]: return QVariant(item.data["downloading"]["format_eta"]) elif role == Qt.EditRole: if index.column() == 0: @@ -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 <http://www.gnu.org/licenses/>. + + @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:</span>\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'<form\s+method="post"\s+action="(http://[\w\d\.]*?easy-share.com/file_contents/.*?)">', 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*</span>\s*<strong>(.*?)<', self.html)
+ name = re.search(r'<title>Download (.*?) for free on Filesonic.com</title>', 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
+
+
|