diff options
Diffstat (limited to 'module/plugins/hoster')
| -rw-r--r-- | module/plugins/hoster/XDCC.py | 138 | 
1 files changed, 75 insertions, 63 deletions
diff --git a/module/plugins/hoster/XDCC.py b/module/plugins/hoster/XDCC.py index 98553ce29..fc1a7e3c3 100644 --- a/module/plugins/hoster/XDCC.py +++ b/module/plugins/hoster/XDCC.py @@ -1,30 +1,32 @@  # -*- coding: utf-8 -*- +import os  import re  import select  import socket  import struct -import sys  import time  from module.plugins.internal.Hoster import Hoster -from module.plugins.internal.misc import fsjoin +from module.plugins.internal.misc import exists, fsjoin  class XDCC(Hoster):      __name__    = "XDCC"      __type__    = "hoster" -    __version__ = "0.41" +    __version__ = "0.42"      __status__  = "testing"      __pattern__ = r'xdcc://(?P<SERVER>.*?)/#?(?P<CHAN>.*?)/(?P<BOT>.*?)/#?(?P<PACK>\d+)/?' -    __config__ = [("nick", "str", "Nickname", "pyload"), -                  ("ident", "str", "Ident", "pyloadident"), -                  ("realname", "str", "Realname", "pyloadreal")] +    __config__  = [("nick",         "str", "Nickname",           "pyload"               ), +                   ("ident",        "str", "Ident",              "pyloadident"          ), +                   ("realname",     "str", "Realname",           "pyloadreal"           ), +                   ("ctcp_version", "str","CTCP version string", "pyLoad! IRC Interface")]      __description__ = """Download from IRC XDCC bot"""      __license__     = "GPLv3" -    __authors__     = [("jeix", "jeix@hasnomail.com")] +    __authors__     = [("jeix",      "jeix@hasnomail.com"        ), +                       ("GammaC0de", "nitzo2001[AT]yahoo[DOT]com")]      def setup(self): @@ -36,45 +38,52 @@ class XDCC(Hoster):          #: Change request type          self.req = self.pyload.requestFactory.getRequest(self.classname, type="XDCC") -        self.pyfile = pyfile          for _i in xrange(0, 3):              try:                  nmn = self.do_download(pyfile.url) -                self.log_debug("Download of %s finished." % nmn) +                self.log_info("Download of %s finished." % nmn)                  return              except socket.error, e:                  if hasattr(e, "errno") and e.errno is not None: -                    errno = e.errno -                else: -                    errno = e.args[0] +                    err_no = e.errno -                if errno == 10054: -                    self.log_debug("Server blocked our ip, retry in 5 min") -                    self.wait(300) -                    continue +                    if err_no in (10054, 10061): +                        self.log_warning("Server blocked our ip, retry in 5 min") +                        self.wait(300) +                        continue -                self.log_debug("e: %s" % len(e.args)) -                self.fail(_("Failed due to socket errors. Code: %d") % errno) +                    else: +                        self.log_error(_("Failed due to socket errors. Code: %s") % err_no) +                        self.fail(_("Failed due to socket errors. Code: %s") % err_no) + +                else: +                    err_msg = e.args[0] +                    self.log_error(_("Failed due to socket errors: '%s'") % err_msg) +                    self.fail(_("Failed due to socket errors: '%s'") % err_msg) +        self.log_error(_("Server blocked our ip, retry again later manually"))          self.fail(_("Server blocked our ip, retry again later manually"))      def do_download(self, url): -        self.pyfile.setStatus("waiting")  #: Real link +        self.pyfile.setStatus("waiting")          server, chan, bot, pack = re.match(self.__pattern__, url).groups() -        nick = self.config.get('nick') -        ident = self.config.get('ident') -        real = self.config.get('realname') +        nick          = self.config.get('nick') +        ident         = self.config.get('ident') +        realname      = self.config.get('realname') +        ctcp_version  = self.config.get('ctcp_version')          temp = server.split(':')          ln = len(temp)          if ln == 2:              host, port = temp +          elif ln == 1:              host, port = temp[0], 6667 +          else:              self.fail(_("Invalid hostname for IRC Server: %s") % server) @@ -83,28 +92,27 @@ class XDCC(Hoster):          dl_time = time.time()          sock = socket.socket() + +        self.log_info(_("Connecting to: %s:%s") % (host, port))          sock.connect((host, int(port)))          if nick == "pyload":              nick = "pyload-%d" % (time.time() % 1000)  #: last 3 digits +          sock.send("NICK %s\r\n" % nick) -        sock.send("USER %s %s bla :%s\r\n" % (ident, host, real)) +        sock.send("USER %s %s bla :%s\r\n" % (ident, host, realname)) + +        self.log_info(_("Connect success.")) -        self.wait(3) +        self.wait(5) # Wait for logon to complete          sock.send("JOIN #%s\r\n" % chan)          sock.send("PRIVMSG %s :xdcc send #%s\r\n" % (bot, pack))          #: IRC recv loop          readbuffer = "" -        done = False          retry = None          m = None -        while True: - -            #: Done is set if we got our real link -            if done: -                break - +        while m is None:              if retry:                  if time.time() > retry:                      retry = None @@ -115,6 +123,7 @@ class XDCC(Hoster):                  if (dl_time + self.timeout) < time.time():  #@TODO: add in config                      sock.send("QUIT :byebye\r\n")                      sock.close() +                    self.log_error(_("XDCC Bot did not answer"))                      self.fail(_("XDCC Bot did not answer"))              fdset = select.select([sock], [], [], 0) @@ -122,10 +131,10 @@ class XDCC(Hoster):                  continue              readbuffer += sock.recv(1024) -            temp = readbuffer.split("\n") -            readbuffer = temp.pop() +            lines = readbuffer.split("\n") +            readbuffer = lines.pop() -            for line in temp: +            for line in lines:                  # if self.pyload.debug:                      # self.log_debug("*> " + decode(line))                  line = line.rstrip() @@ -141,20 +150,18 @@ class XDCC(Hoster):                  if len(msg) != 4:                      continue -                msg = { -                    'origin': msg[0][1:], -                    'action': msg[1], -                    'target': msg[2], -                    'text': msg[3][1:] -                } +                msg = {'origin': msg[0][1:], +                       'action': msg[1], +                       'target': msg[2], +                       'text'  : msg[3][1:]} -                if nick == msg['target'][0:len(nick)] and "PRIVMSG" == msg['action']: +                if msg['target'][0:len(nick)] == nick and msg['action'] == "PRIVMSG":                      if msg['text'] == "\x01VERSION\x01": -                        self.log_debug("Sending CTCP VERSION") -                        sock.send("NOTICE %s :%s\r\n" % (msg['origin'], "pyLoad! IRC Interface")) +                        self.log_debug(_("Sending CTCP VERSION")) +                        sock.send("NOTICE %s :%s\r\n" % (msg['origin'], ctcp_version))                      elif msg['text'] == "\x01TIME\x01": -                        self.log_debug("Sending CTCP TIME") +                        self.log_debug(_("Sending CTCP TIME"))                          sock.send("NOTICE %s :%d\r\n" % (msg['origin'], time.time()))                      elif msg['text'] == "\x01LAG\x01": @@ -165,43 +172,48 @@ class XDCC(Hoster):                          or msg['action'] not in ("PRIVMSG", "NOTICE"):                      continue -                if self.pyload.debug: -                    self.log_debug(msg['origin'], msg['text']) +                self.log_debug(_("PrivMsg: <%s> - %s" % (msg['origin'], msg['text'])))                  if "You already requested that pack" in msg['text']:                      retry = time.time() + 300 -                if "you must be on a known channel to request a pack" in msg['text']: +                elif "you must be on a known channel to request a pack" in msg['text']: +                    self.log_error(_("Invalid channel"))                      self.fail(_("Invalid channel")) -                m = re.match('\x01DCC SEND (.*?) (\d+) (\d+)(?: (\d+))?\x01', msg['text']) -                if m is not None: -                    done = True +                m = re.match('\x01DCC SEND (?P<NAME>.*?) (?P<IP>\d+) (?P<PORT>\d+)(?: (?P<SIZE>\d+))?\x01', msg['text'])          #: 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) +        ip        = socket.inet_ntoa(struct.pack('!I', int(m.group('IP')))) +        port      = int(m.group('PORT')) +        file_name = m.group('NAME') +        if m.group('SIZE'): +            self.req.filesize = long(m.group('SIZE')) + +        self.pyfile.name = file_name -        if len(m.groups()) > 3: -            self.req.filesize = int(m.group(4)) +        dl_folder = fsjoin(self.pyload.config.get('general', 'download_folder'), +                           self.pyfile.package().folder if self.pyload.config.get("general", +                                                                                  "folder_per_package") else "") +        dl_file = fsjoin(dl_folder, file_name) -        self.pyfile.name = packname +        if not exists(dl_folder): +            os.makedirs(dl_folder) -        dl_folder = self.pyload.config.get('general', 'download_folder') -        filename = fsjoin(dl_folder, packname) +        self.set_permissions(dl_folder) -        self.log_info(_("Downloading %s from %s:%d") % (packname, ip, port)) +        self.log_info(_("Downloading %s from %s:%d") % (file_name, ip, port))          self.pyfile.setStatus("downloading") -        newname = self.req.download(ip, port, filename, sock, self.pyfile.setProgress) -        if newname and newname != filename: + +        newname = self.req.download(ip, port, dl_file, sock, self.pyfile.setProgress) +        if newname and newname != dl_file:              self.log_info(_("%(name)s saved as %(newname)s") % {'name': self.pyfile.name, 'newname': newname}) -            filename = newname +            dl_file = newname          #: kill IRC socket          #: sock.send("QUIT :byebye\r\n")          sock.close() -        self.last_download = filename +        self.last_download = dl_file          return self.last_download  | 
