diff options
| author | 2013-03-26 19:23:41 +0100 | |
|---|---|---|
| committer | 2013-03-26 19:23:41 +0100 | |
| commit | 866d30eb0e6a8868a4f2eb1da3c91734d6b9d716 (patch) | |
| tree | 2233ea2329e779761abb5dc8e08afee97973dc61 /module | |
| parent | Movie2kTo: Added setting for quality in the folder name. (diff) | |
| parent | Merge pull request #53 from enkore/stable (diff) | |
| download | pyload-866d30eb0e6a8868a4f2eb1da3c91734d6b9d716.tar.xz | |
Merge branch 'stable' of git://github.com/pyload/pyload into stable
Diffstat (limited to 'module')
21 files changed, 401 insertions, 225 deletions
diff --git a/module/plugins/accounts/AlldebridCom.py b/module/plugins/accounts/AlldebridCom.py index 7d4d245ba..beaddeac9 100644 --- a/module/plugins/accounts/AlldebridCom.py +++ b/module/plugins/accounts/AlldebridCom.py @@ -17,20 +17,20 @@ class AlldebridCom(Account):          data = self.getAccountData(user)
          page = req.load("http://www.alldebrid.com/account/")
          soup=BeautifulSoup(page)
 -		#Try to parse expiration date directly from the control panel page (better accuracy)        
 +        #Try to parse expiration date directly from the control panel page (better accuracy)        
          try:
 -             time_text=soup.find('div',attrs={'class':'remaining_time_text'}).strong.string
 -             self.log.debug("Account expires in: %s" % time_text)
 -             p = re.compile('\d+')
 -             exp_data=p.findall(time_text)
 -             exp_time=time()+int(exp_data[0])*24*60*60+int(exp_data[1])*60*60+(int(exp_data[2])-1)*60
 -		#Get expiration date from API
 +            time_text=soup.find('div',attrs={'class':'remaining_time_text'}).strong.string
 +            self.log.debug("Account expires in: %s" % time_text)
 +            p = re.compile('\d+')
 +            exp_data=p.findall(time_text)
 +            exp_time=time()+int(exp_data[0])*24*60*60+int(exp_data[1])*60*60+(int(exp_data[2])-1)*60
 +        #Get expiration date from API
          except:
 -             data = self.getAccountData(user)
 -             page = req.load("http://www.alldebrid.com/api.php?action=info_user&login=%s&pw=%s" %  (user, data["password"]))
 -             self.log.debug(page)
 -             xml = dom.parseString(page)
 -             exp_time=time()+int(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue)*86400
 +            data = self.getAccountData(user)
 +            page = req.load("http://www.alldebrid.com/api.php?action=info_user&login=%s&pw=%s" %  (user, data["password"]))
 +            self.log.debug(page)
 +            xml = dom.parseString(page)
 +            exp_time=time()+int(xml.getElementsByTagName("date")[0].childNodes[0].nodeValue)*86400
          account_info = {"validuntil": exp_time, "trafficleft": -1}
          return account_info
 @@ -40,7 +40,7 @@ class AlldebridCom(Account):          page = req.load("http://www.alldebrid.com/register/?%s" % (urlparams))          if "This login doesn't exist" in page:
 -             self.wrongPassword()
 +            self.wrongPassword()
          if "The password is not valid" in page:              self.wrongPassword() diff --git a/module/plugins/accounts/CyberlockerCh.py b/module/plugins/accounts/CyberlockerCh.py new file mode 100644 index 000000000..31e0c3e24 --- /dev/null +++ b/module/plugins/accounts/CyberlockerCh.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- +from module.plugins.internal.XFSPAccount import XFSPAccount +from module.plugins.internal.SimpleHoster import parseHtmlForm + +class CyberlockerCh(XFSPAccount): +    __name__ = "CyberlockerCh" +    __version__ = "0.01" +    __type__ = "account" +    __description__ = """CyberlockerCh account plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    MAIN_PAGE = "http://cyberlocker.ch/" + +    def login(self, user, data, req): +        html = req.load(self.MAIN_PAGE + 'login.html', decode = True) + +        action, inputs = parseHtmlForm('name="FL"', html) +        if not inputs: +            inputs = {"op": "login", +                      "redirect": self.MAIN_PAGE} + +        inputs.update({"login": user, +                       "password": data['password']}) + +        # Without this a 403 Forbidden is returned +        req.http.lastURL = self.MAIN_PAGE + 'login.html' +        html = req.load(self.MAIN_PAGE, post = inputs, decode = True) + +        if 'Incorrect Login or Password' in html or '>Error<' in html: +            self.wrongPassword() diff --git a/module/plugins/accounts/DebridItaliaCom.py b/module/plugins/accounts/DebridItaliaCom.py new file mode 100644 index 000000000..d68f1c8a8 --- /dev/null +++ b/module/plugins/accounts/DebridItaliaCom.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- + +import re +import _strptime +import time + +from module.plugins.Account import Account + + +class DebridItaliaCom(Account): +    __name__ = "DebridItaliaCom" +    __version__ = "0.1" +    __type__ = "account" +    __description__ = """debriditalia.com account plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    WALID_UNTIL_PATTERN = r"Premium valid till: (?P<D>[^|]+) \|" + +    def loadAccountInfo(self, user, req): +        if 'Account premium not activated' in self.html: +            return {"premium": False, "validuntil": None, "trafficleft": None} + +        m = re.search(self.WALID_UNTIL_PATTERN, self.html) +        if m: +            validuntil = int(time.mktime(time.strptime(m.group('D'), "%d/%m/%Y %H:%M"))) +            return {"premium": True, "validuntil": validuntil, "trafficleft": -1} +        else: +            self.logError('Unable to retrieve account information - Plugin may be out of date') + +    def login(self, user, data, req): +        self.html = req.load("http://debriditalia.com/login.php", +                             get={"u": user, "p": data["password"]}) +        if 'NO' in self.html: +            self.wrongPassword() diff --git a/module/plugins/crypter/FourChanOrg.py b/module/plugins/crypter/FourChanOrg.py index cbcdd920c..5c96e723d 100644 --- a/module/plugins/crypter/FourChanOrg.py +++ b/module/plugins/crypter/FourChanOrg.py @@ -6,34 +6,20 @@ import re  from module.plugins.Crypter import Crypter  class FourChanOrg(Crypter): +    # Based on 4chandl by Roland Beermann +    # https://gist.github.com/enkore/3492599      __name__ = "FourChanOrg"      __type__ = "container" -    __pattern__ = r"http://(www\.)?(img\.)?(zip\.)?4chan.org/\w+/(res/|imgboard\.html)" -    __version__ = "0.1" -    __description__ = """4chan.org Thread Download Plugin""" -    __author_name__ = ("Spoob") -    __author_mail__ = ("Spoob@pyload.org") +    __version__ = "0.3" +    __pattern__ = r"http://boards\.4chan.org/\w+/res/(\d+)" +    __description__ = "Downloader for entire 4chan threads" -    def __init__(self, parent): -        Crypter.__init__(self, parent) -        self.parent = parent -        self.html = None +    def decrypt(self, pyfile): +        pagehtml = self.load(pyfile.url) -    def file_exists(self): -        """ returns True or False -        """ -        return True +        images = set(re.findall(r'(images\.4chan\.org/[^/]*/src/[^"<]*)', pagehtml)) +        urls = [] +        for image in images: +            urls.append("http://" + image) -    def proceed(self, url, location): -        url = self.parent.url -        html = self.req.load(url) -        link_pattern = "" -        temp_links = [] -        if "imagebord.html" in url: -            link_pattern = '[<a href="(res/\d*\.html)">Reply</a>]' -            temp_links = re.findall(link_pattern, html) -            for link in re.findall(link_pattern, html): -                temp_links.append(link) -        else: -            temp_links = re.findall('File : <a href="(http://(?:img\.)?(?:zip\.)?4chan\.org/\w{,3}/src/\d*\..{3})"', html) -        self.links = temp_links +        self.core.files.addLinks(urls, self.pyfile.package().id) diff --git a/module/plugins/crypter/LixIn.py b/module/plugins/crypter/LixIn.py index 1ed5510fd..e2ee30731 100644 --- a/module/plugins/crypter/LixIn.py +++ b/module/plugins/crypter/LixIn.py @@ -33,7 +33,7 @@ class LixIn(Crypter):          matches = re.search(self.SUBMIT_PATTERN,self.html)          if not matches: -	    self.fail("link doesn't seem valid") +            self.fail("link doesn't seem valid")          matches = re.search(self.CAPTCHA_PATTERN, self.html)          if matches: @@ -42,20 +42,19 @@ class LixIn(Crypter):                  if matches:                      self.logDebug("trying captcha")                      captcharesult = self.decryptCaptcha("http://lix.in/"+matches.group("image")) -	            self.html = self.req.load(url, decode=True, post={"capt" : captcharesult, "submit":"submit","tiny":id}) -	        else: -	            self.logDebug("no captcha/captcha solved") -	            break -    	else: +                self.html = self.req.load(url, decode=True, post={"capt" : captcharesult, "submit":"submit","tiny":id}) +            else: +                self.logDebug("no captcha/captcha solved") +                break +        else:              self.html = self.req.load(url, decode=True, post={"submit" : "submit", -	                                                      "tiny"   : id}) -	                                      +                                                          "tiny"   : id}) +                                                   matches = re.search(self.LINK_PATTERN, self.html)          if not matches: -	    self.fail("can't find destination url") +            self.fail("can't find destination url")          new_link = matches.group("link")          self.logDebug("Found link %s, adding to package" % new_link)          self.packages.append((self.pyfile.package().name, [new_link], self.pyfile.package().name)) -           
\ No newline at end of file diff --git a/module/plugins/crypter/TrailerzoneInfo.py b/module/plugins/crypter/TrailerzoneInfo.py index 2683c2429..43a4fcce5 100644 --- a/module/plugins/crypter/TrailerzoneInfo.py +++ b/module/plugins/crypter/TrailerzoneInfo.py @@ -22,10 +22,10 @@ class TrailerzoneInfo(Crypter):              self.handleProtect(url)          elif goPattern.match(url):              self.handleGo(url) -			 +      def handleProtect(self, url):          self.handleGo("http://trailerzone.info/go.html#:::" + url.split("#:::",1)[1]) -			 +      def handleGo(self, url):          src = self.req.load(str(url)) diff --git a/module/plugins/hooks/Captcha9kw.py b/module/plugins/hooks/Captcha9kw.py index b34ffeb05..a01ce9576 100755 --- a/module/plugins/hooks/Captcha9kw.py +++ b/module/plugins/hooks/Captcha9kw.py @@ -62,40 +62,40 @@ class Captcha9kw(Hook):          data = b64encode(data)
          self.logDebug("%s : %s" % (task.captchaFile, data))
          if task.isPositional():
 -                mouse = 1
 +            mouse = 1
          else:
 -                mouse = 0
 +            mouse = 0
          response = getURL(self.API_URL, post = { 
 -			"apikey": self.getConfig("passkey"), 
 -			"pyload": "1", 
 -			"source": "pyload", 
 -			"base64": "1", 
 -			"mouse": mouse,
 -			"file-upload-01": data, 
 -			"action": "usercaptchaupload" })
 +                          "apikey": self.getConfig("passkey"), 
 +                          "pyload": "1", 
 +                          "source": "pyload", 
 +                          "base64": "1", 
 +                          "mouse": mouse,
 +                          "file-upload-01": data, 
 +                          "action": "usercaptchaupload" })
 -	if response.isdigit():
 -		self.logInfo(_("NewCaptchaID from upload: %s : %s" % (response,task.captchaFile)))
 +        if response.isdigit():
 +            self.logInfo(_("NewCaptchaID from upload: %s : %s" % (response,task.captchaFile)))
 -		for i in range(1, 200, 2): 
 -		        response2 = getURL(self.API_URL, get = { "apikey": self.getConfig("passkey"), "id": response,"pyload": "1","source": "pyload", "action": "usercaptchacorrectdata" })
 +            for i in range(1, 200, 2): 
 +                response2 = getURL(self.API_URL, get = { "apikey": self.getConfig("passkey"), "id": response,"pyload": "1","source": "pyload", "action": "usercaptchacorrectdata" })
 -			if(response2 != ""):
 -				break;
 +                if(response2 != ""):
 +                    break;
 -			time.sleep(1)
 +                time.sleep(1)
 -		result = response2
 -		task.data["ticket"] = response
 -		self.logInfo("result %s : %s" % (response, result))
 -		task.setResult(result)
 -	else:
 -		self.logError("Bad upload: %s" % response)
 -		return False
 +            result = response2
 +            task.data["ticket"] = response
 +            self.logInfo("result %s : %s" % (response, result))
 +            task.setResult(result)
 +        else:
 +            self.logError("Bad upload: %s" % response)
 +            return False
      def newCaptchaTask(self, task):
 -	if not task.isTextual() and not task.isPositional():
 +        if not task.isTextual() and not task.isPositional():
              return False
          if not self.getConfig("passkey"):
 @@ -130,7 +130,7 @@ class Captcha9kw(Hook):              except BadHeader, e:
                  self.logError("Could not send correct request.", str(e))
          else:
 -                self.logError("No CaptchaID for correct request (task %s) found." % task)
 +             self.logError("No CaptchaID for correct request (task %s) found." % task)
      def captchaInvalid(self, task):
          if "ticket" in task.data:
 @@ -150,4 +150,4 @@ class Captcha9kw(Hook):              except BadHeader, e:
                  self.logError("Could not send refund request.", str(e))
          else:
 -                self.logError("No CaptchaID for not correct request (task %s) found." % task)
\ No newline at end of file +            self.logError("No CaptchaID for not correct request (task %s) found." % task)
 diff --git a/module/plugins/hooks/DebridItaliaCom.py b/module/plugins/hooks/DebridItaliaCom.py new file mode 100644 index 000000000..8cd997f4d --- /dev/null +++ b/module/plugins/hooks/DebridItaliaCom.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +from module.plugins.internal.MultiHoster import MultiHoster + + +class DebridItaliaCom(MultiHoster): +    __name__ = "DebridItaliaCom" +    __version__ = "0.01" +    __type__ = "hook" +    __config__ = [("activated", "bool", "Activated", "False"), +                  ("hosterListMode", "all;listed;unlisted", "Use for hosters (if supported)", "all"), +                  ("hosterList", "str", "Hoster list (comma separated)", ""), +                  ("unloadFailing", "bool", "Revert to standard download if download fails", "False"), +                  ("interval", "int", "Reload interval in hours (0 to disable)", "24")] + +    __description__ = """Debriditalia.com hook plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    def getHoster(self): +        return ["netload.in", "hotfile.com", "rapidshare.com", "multiupload.com", +                "uploading.com", "megashares.com", "crocko.com", "filepost.com", +                "bitshare.com", "share-links.biz", "putlocker.com", "uploaded.to", +                "speedload.org", "rapidgator.net", "likeupload.net", "cyberlocker.ch", +                "depositfiles.com", "extabit.com", "filefactory.com", "sharefiles.co"] diff --git a/module/plugins/hooks/ExtractArchive.py b/module/plugins/hooks/ExtractArchive.py index c789495ca..a5a973b7f 100644 --- a/module/plugins/hooks/ExtractArchive.py +++ b/module/plugins/hooks/ExtractArchive.py @@ -196,8 +196,6 @@ class ExtractArchive(Hook):                  files_ids = new_files_ids # also check extracted files              if not matched: self.logInfo(_("No files found to extract")) -	 -      def startExtracting(self, plugin, fid, passwords, thread):          pyfile = self.core.files.getFile(fid) diff --git a/module/plugins/hoster/AlldebridCom.py b/module/plugins/hoster/AlldebridCom.py index fe58ff0a7..efc96ff28 100644 --- a/module/plugins/hoster/AlldebridCom.py +++ b/module/plugins/hoster/AlldebridCom.py @@ -1,19 +1,16 @@ -#!/usr/nv python
  # -*- coding: utf-8 -*-
  import re
 -from urllib import quote, unquote
 +from urllib import unquote
  from random import randrange
 -from os import stat
 -
  from module.plugins.Hoster import Hoster
  from module.common.json_layer import json_loads
 -from module.utils import parseFileSize, fs_encode
 +from module.utils import parseFileSize
  class AlldebridCom(Hoster):
      __name__ = "AlldebridCom"
 -    __version__ = "0.3"
 +    __version__ = "0.31"
      __type__ = "hoster"
      __pattern__ = r"https?://.*alldebrid\..*"
 @@ -27,7 +24,7 @@ class AlldebridCom(Hoster):          except IndexError:
              name = "Unknown_Filename..."
          if name.endswith("..."): #incomplete filename, append random stuff
 -            name += "%s.tmp" % randrange(100,999)
 +            name += "%s.tmp" % randrange(100, 999)
          return name
      def init(self):
 @@ -35,10 +32,9 @@ class AlldebridCom(Hoster):          self.chunkLimit = 3
          self.resumeDownload = True
 -
 -    def process(self, pyfile):                            
 +    def process(self, pyfile):
          if not self.account:
 -            self.logError(_("Please enter your AllDebrid account or deactivate this plugin"))
 +            self.logError("Please enter your AllDebrid account or deactivate this plugin")
              self.fail("No AllDebrid account provided")
          self.log.debug("AllDebrid: Old URL: %s" % pyfile.url)
 @@ -46,14 +42,13 @@ class AlldebridCom(Hoster):              new_url = pyfile.url
          else:
              password = self.getPassword().splitlines()
 -            if not password: password = ""
 -            else: password = password[0]
 +            password = "" if not password else password[0]
 -            url = "http://www.alldebrid.com/service.php?link=%s&json=true&pw=%s" %(pyfile.url, password)
 +            url = "http://www.alldebrid.com/service.php?link=%s&json=true&pw=%s" % (pyfile.url, password)
              page = self.load(url)
              data = json_loads(page)
 -            
 -            self.log.debug("Json data: %s" % str(data))
 +
 +            self.logDebug("Json data: %s" % str(data))
              if data["error"]:
                  if data["error"] == "This link isn't available on the hoster website.":
 @@ -72,7 +67,7 @@ class AlldebridCom(Hoster):          else:
              new_url = new_url.replace("https://", "http://")
 -        self.log.debug("AllDebrid: New URL: %s" % new_url)
 +        self.logDebug("AllDebrid: New URL: %s" % new_url)
          if pyfile.name.startswith("http") or pyfile.name.startswith("Unknown"):
              #only use when name wasnt already set
 @@ -80,12 +75,10 @@ class AlldebridCom(Hoster):          self.download(new_url, disposition=True)
 -        check = self.checkDownload(
 -                {"error": "<title>An error occured while processing your request</title>","empty": re.compile(r"^$")})
 +        check = self.checkDownload({"error": "<title>An error occured while processing your request</title>",
 +                                    "empty": re.compile(r"^$")})
          if check == "error":
              self.retry(reason="An error occured while generating link.", wait_time=60)
 -        else:
 -            if check == "empty":
 -                self.retry(reason="Downloaded File was empty.", wait_time=60)
 -
 +        elif check == "empty":
 +            self.retry(reason="Downloaded File was empty.", wait_time=60)
 diff --git a/module/plugins/hoster/DebridItaliaCom.py b/module/plugins/hoster/DebridItaliaCom.py new file mode 100644 index 000000000..a8f7dd57e --- /dev/null +++ b/module/plugins/hoster/DebridItaliaCom.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- + +import re + +from module.plugins.Hoster import Hoster + + +class DebridItaliaCom(Hoster): +    __name__ = "DebridItaliaCom" +    __version__ = "0.02" +    __type__ = "hoster" +    __pattern__ = r"https?://.*debriditalia\.com" +    __description__ = """Debriditalia.com hoster plugin""" +    __author_name__ = ("stickell") +    __author_mail__ = ("l.stickell@yahoo.it") + +    def init(self): +        self.chunkLimit = -1 +        self.resumeDownload = True + +    def process(self, pyfile): +        if not self.account: +            self.logError("Please enter your DebridItalia account or deactivate this plugin") +            self.fail("No DebridItalia account provided") + +        self.logDebug("Old URL: %s" % pyfile.url) +        if re.match(self.__pattern__, pyfile.url): +            new_url = pyfile.url +        else: +            url = "http://debriditalia.com/linkgen2.php?xjxfun=convertiLink&xjxargs[]=S<![CDATA[%s]]>" % pyfile.url +            page = self.load(url) +            self.logDebug("XML data: %s" % page) + +            new_url = re.search(r'<a href="(?:[^"]+)">(?P<direct>[^<]+)</a>', page).group('direct') + +        self.logDebug("New URL: %s" % new_url) + +        self.download(new_url, disposition=True) + +        check = self.checkDownload({"empty": re.compile(r"^$")}) + +        if check == "empty": +            self.retry(5, 120, 'Empty file downloaded') diff --git a/module/plugins/hoster/EgoFilesCom.py b/module/plugins/hoster/EgoFilesCom.py index 24e26c7f5..b27abb416 100644 --- a/module/plugins/hoster/EgoFilesCom.py +++ b/module/plugins/hoster/EgoFilesCom.py @@ -4,22 +4,18 @@ from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo  from module.plugins.ReCaptcha import ReCaptcha
  import re
 -def to_seconds(m):
 -    minutes = int(m['m']) if m['m'] else 0
 -    seconds = int(m['s']) if m['s'] else 0
 -    return minutes * 60 + seconds
  class EgoFilesCom(SimpleHoster):
      __name__ = "EgoFilesCom"
      __type__ = "hoster"
      __pattern__ = r"https?://(www\.)?egofiles.com/(\w+)"
 -    __version__ = "0.07"
 +    __version__ = "0.10"
      __description__ = """Egofiles.com Download Hoster"""
      __author_name__ = ("stickell")
      __author_mail__ = ("l.stickell@yahoo.it")
      FILE_INFO_PATTERN = r'<div class="down-file">\s+(?P<N>\S+)\s+<div class="file-properties">\s+(File size|Rozmiar): (?P<S>[\w.]+) (?P<U>\w+) \|'
 -    FILE_OFFLINE_PATTERN = r'File size: 0 KB'
 +    FILE_OFFLINE_PATTERN = r'(File size|Rozmiar): 0 KB'
      WAIT_TIME_PATTERN = r'For next free download you have to wait <strong>((?P<m>\d*)m)? ?((?P<s>\d+)s)?</strong>'
      DIRECT_LINK_PATTERN = r'<a href="(?P<link>[^"]+)">Download ></a>'
      RECAPTCHA_KEY = '6LeXatQSAAAAAHezcjXyWAni-4t302TeYe7_gfvX'
 @@ -29,19 +25,14 @@ class EgoFilesCom(SimpleHoster):          # Set English language
          self.load("https://egofiles.com/ajax/lang.php?lang=en", just_header=True)
 -    def process(self, pyfile):
 -        if self.premium:
 -            self.handlePremium()
 -        else:
 -            self.handleFree()
 -
      def handleFree(self):
          self.html = self.load(self.pyfile.url, decode=True)
          # Wait time between free downloads
          if 'For next free download you have to wait' in self.html:
 -            m = re.search(self.WAIT_TIME_PATTERN, self.html)
 -            self.setWait(to_seconds(m.groupdict()), True)
 +            m = re.search(self.WAIT_TIME_PATTERN, self.html).groupdict('0')
 +            waittime = int(m['m']) * 60 + int(m['s'])
 +            self.setWait(waittime, True)
              self.wait()
          downloadURL = ''
 diff --git a/module/plugins/hoster/FilebeerInfo.py b/module/plugins/hoster/FilebeerInfo.py index a51f70a09..216ecfbca 100644 --- a/module/plugins/hoster/FilebeerInfo.py +++ b/module/plugins/hoster/FilebeerInfo.py @@ -1,100 +1,15 @@  # -*- 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. +from module.plugins.internal.DeadHoster import DeadHoster, create_getInfo -    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: zoidberg -""" - -import re -from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo -from module.plugins.ReCaptcha import ReCaptcha -from pycurl import FOLLOWLOCATION - -class FilebeerInfo(SimpleHoster): +class FilebeerInfo(DeadHoster):      __name__ = "FilebeerInfo"      __type__ = "hoster"      __pattern__ = r"http://(?:www\.)?filebeer\.info/(?!\d*~f)(?P<ID>\w+).*" -    __version__ = "0.02" +    __version__ = "0.03"      __description__ = """Filebeer.info plugin"""      __author_name__ = ("zoidberg")      __author_mail__ = ("zoidberg@mujmail.cz") -    FILE_NAME_PATTERN = r'Filename:\s*</td>\s*<td>\s*(?P<N>.+?)  ' -    FILE_SIZE_PATTERN = r'Filesize:\s*</td>\s*<td>\s*(?P<S>[0-9.]+) (?P<U>[kKMG])i?B' -    FILE_INFO_PATTERN = r'<strong>\s*(?P<N>.+?) \((?P<S>[0-9.]+) (?P<U>[kKMG])i?B\)(<br/>\s*)?</strong>' -    FILE_OFFLINE_PATTERN = r'<title>Upload Files - FileBeer.info</title>' -     -    FILE_URL_REPLACEMENTS = [(__pattern__, 'http://filebeer.info/\g<ID>~i')] -     -    RECAPTCHA_KEY_PATTERN = r'http://www.google.com/recaptcha/api/(?:challenge|noscript)?k=(\w+)' -    DOWNLOAD_URL_PATTERN = r"\[url\](.+?)\[/url\]" -    WAIT_TIME_PATTERN = r"\(\'\.download-timer-seconds\'\)\.html\((\d+)\)" -     -    def setup(self): -        self.resumeDownload = True -        self.multiDL = self.premium -     -    def handleFree(self): -        url = self.getDownloadUrl() -          -        for i in range(5): -            self.html = self.load(url)             -            if i == 4 or 'id="form-join"' in self.html: -                break -            else:     -                found = re.search(self.WAIT_TIME_PATTERN, self.html)           -                self.setWait(int(found.group(1)) +1 if found else 61) -                self.wait() -                 -        action, inputs = self.parseHtmlForm('form-join') -        if not action: -            self.fail('Form not found')           -     -        found = re.search(self.RECAPTCHA_KEY_PATTERN, self.html) -        recaptcha_key = found.group(1) if found else '6LeuAc4SAAAAAOSry8eo2xW64K1sjHEKsQ5CaS10' -         -        recaptcha = ReCaptcha(self) -        for i in range(5):                -            inputs['recaptcha_challenge_field'], inputs['recaptcha_response_field'] = recaptcha.challenge(recaptcha_key)             -             -            self.req.http.c.setopt(FOLLOWLOCATION, 0) -            self.html = self.load(action, post = inputs) -            self.header = self.req.http.header -            self.req.http.c.setopt(FOLLOWLOCATION, 1) -             -            found = re.search("Location\s*:\s*(.*)", self.header, re.I) -            if found: -                download_url = found.group(1).strip() -                self.correctCaptcha() -                break -            elif 'Captcha confirmation text is invalid' in self.html: -                self.invalidCaptcha() -            else: -                self.parseError('download url') -         -        else: self.fail("No valid captcha solution received") -         -        self.multiDL = True -         -        self.req.http.lastURL = action -        self.download(download_url) -     -    def handlePremium(self):         -        self.download(self.getDownloadUrl())  -         -    def getDownloadUrl(self): -        found = re.search(self.DOWNLOAD_URL_PATTERN, self.html) -        return ("%s?d=1" % found.group(1)) if found else ("http://filebeer.info/%s?d=1" % self.file_info['ID'])            -         +  getInfo = create_getInfo(FilebeerInfo)
\ No newline at end of file diff --git a/module/plugins/hoster/LuckyShareNet.py b/module/plugins/hoster/LuckyShareNet.py new file mode 100644 index 000000000..a1e866089 --- /dev/null +++ b/module/plugins/hoster/LuckyShareNet.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*-
 +
 +import re
 +from module.lib.bottle import json_loads
 +
 +from module.plugins.internal.SimpleHoster import SimpleHoster, create_getInfo
 +from module.plugins.ReCaptcha import ReCaptcha
 +
 +
 +class LuckyShareNet(SimpleHoster):
 +    __name__ = "LuckyShareNet"
 +    __type__ = "hoster"
 +    __pattern__ = r"https?://(www\.)?luckyshare.net/(?P<ID>\d{10,})"
 +    __version__ = "0.02"
 +    __description__ = """LuckyShare.net Download Hoster"""
 +    __author_name__ = ("stickell")
 +    __author_mail__ = ("l.stickell@yahoo.it")
 +
 +    FILE_INFO_PATTERN = r"<h1 class='file_name'>(?P<N>\S+)</h1>\s*<span class='file_size'>Filesize: (?P<S>[\d.]+)(?P<U>\w+)</span>"
 +    FILE_OFFLINE_PATTERN = 'There is no such file available'
 +    RECAPTCHA_KEY = '6LdivsgSAAAAANWh-d7rPE1mus4yVWuSQIJKIYNw'
 +
 +    def parseJson(self, rep):
 +        if 'AJAX Error' in rep:
 +            html = self.load(self.pyfile.url, decode=True)
 +            m = re.search(r"waitingtime = (\d+);", html)
 +            if m:
 +                waittime = int(m.group(1))
 +                self.logDebug('You have to wait %d seconds between free downloads' % waittime)
 +                self.retry(wait_time=waittime)
 +            else:
 +                self.parseError('Unable to detect wait time between free downloads')
 +        elif 'Hash expired' in rep:
 +            self.retry(reason='Hash expired')
 +        return json_loads(rep)
 +
 +    # TODO: There should be a filesize limit for free downloads
 +    # TODO: Some files could not be downloaded in free mode
 +    def handleFree(self):
 +        file_id = re.search(self.__pattern__, self.pyfile.url).group('ID')
 +        self.logDebug('File ID: ' + file_id)
 +        rep = self.load(r"http://luckyshare.net/download/request/type/time/file/" + file_id, decode=True)
 +        self.logDebug('JSON: ' + rep)
 +        json = self.parseJson(rep)
 +
 +        self.setWait(int(json['time']))
 +        self.wait()
 +
 +        recaptcha = ReCaptcha(self)
 +        for i in xrange(5):
 +            challenge, response = recaptcha.challenge(self.RECAPTCHA_KEY)
 +            rep = self.load(r"http://luckyshare.net/download/verify/challenge/%s/response/%s/hash/%s" %
 +                            (challenge, response, json['hash']), decode=True)
 +            self.logDebug('JSON: ' + rep)
 +            if 'link' in rep:
 +                json.update(self.parseJson(rep))
 +                self.correctCaptcha()
 +                break
 +            elif 'Verification failed' in rep:
 +                self.logInfo('Wrong captcha')
 +                self.invalidCaptcha()
 +            else:
 +                self.parseError('Unable to get downlaod link')
 +
 +        if not json['link']:
 +            self.fail("No Download url retrieved/all captcha attempts failed")
 +
 +        self.logDebug('Direct URL: ' + json['link'])
 +        self.download(json['link'])
 +
 +
 +getInfo = create_getInfo(LuckyShareNet)
 diff --git a/module/plugins/hoster/NetloadIn.py b/module/plugins/hoster/NetloadIn.py index d2bf37d70..e616badc2 100644 --- a/module/plugins/hoster/NetloadIn.py +++ b/module/plugins/hoster/NetloadIn.py @@ -54,8 +54,8 @@ def getInfo(urls):  class NetloadIn(Hoster):      __name__ = "NetloadIn"      __type__ = "hoster" -    __pattern__ = r"http://.*netload\.in/(?:datei(.*?)(?:\.htm|/)|index.php?id=10&file_id=)" -    __version__ = "0.41" +    __pattern__ = r"https?://.*netload\.in/(?:datei(.*?)(?:\.htm|/)|index.php?id=10&file_id=)" +    __version__ = "0.42"      __description__ = """Netload.in Download Hoster"""      __author_name__ = ("spoob", "RaNaN", "Gregy")      __author_mail__ = ("spoob@pyload.org", "ranan@pyload.org", "gregy@gregy.cz") diff --git a/module/plugins/hoster/RapidgatorNet.py b/module/plugins/hoster/RapidgatorNet.py index 6c1c231fe..1cc3ff8ae 100644 --- a/module/plugins/hoster/RapidgatorNet.py +++ b/module/plugins/hoster/RapidgatorNet.py @@ -28,8 +28,8 @@ from module.network.HTTPRequest import BadHeader  class RapidgatorNet(SimpleHoster):      __name__ = "RapidgatorNet"      __type__ = "hoster" -    __pattern__ = r"http://(?:www\.)?(rapidgator.net)/file/(\d+)" -    __version__ = "0.15" +    __pattern__ = r"http://(?:www\.)?(rapidgator.net)/file/(\w+)" +    __version__ = "0.16"      __description__ = """rapidgator.net"""      __author_name__ = ("zoidberg","chrox") diff --git a/module/plugins/hoster/RyushareCom.py b/module/plugins/hoster/RyushareCom.py index 19f17b531..c2ff54e0c 100644 --- a/module/plugins/hoster/RyushareCom.py +++ b/module/plugins/hoster/RyushareCom.py @@ -2,16 +2,12 @@  from module.plugins.hoster.XFileSharingPro import XFileSharingPro, create_getInfo  import re -def to_seconds(m): -    minutes = int(m['min']) if m['min'] else 0 -    seconds = int(m['sec']) if m['sec'] else 0 -    return minutes * 60 + seconds  class RyushareCom(XFileSharingPro):      __name__ = "RyushareCom"      __type__ = "hoster"      __pattern__ = r"http://(?:\w*\.)*?ryushare.com/\w{11,}" -    __version__ = "0.07" +    __version__ = "0.10"      __description__ = """ryushare.com hoster plugin"""      __author_name__ = ("zoidberg", "stickell")      __author_mail__ = ("zoidberg@mujmail.cz", "l.stickell@yahoo.it") @@ -19,6 +15,7 @@ class RyushareCom(XFileSharingPro):      HOSTER_NAME = "ryushare.com"      WAIT_PATTERN = r'(?:You have to|Please) wait (?:(?P<min>\d+) minutes, )?(?:<span id="[^"]+">)?(?P<sec>\d+)(?:</span>)? seconds' +    DIRECT_LINK_PATTERN = r'<a href="([^"]+)">Click here to download</a>'      def setup(self):          self.resumeDownload = self.multiDL = self.premium @@ -41,13 +38,14 @@ class RyushareCom(XFileSharingPro):              if 'You have reached the download-limit!!!' in self.html:                  self.setWait(3600, True)              else: -                m = re.search(self.WAIT_PATTERN, self.html) -                self.setWait(to_seconds(m.groupdict())) +                m = re.search(self.WAIT_PATTERN, self.html).groupdict('0') +                waittime = int(m['min']) * 60 + int(m['sec']) +                self.setWait(waittime)              self.wait()              self.html = self.load(self.pyfile.url, post = inputs)              if 'Click here to download' in self.html: -                m = re.search(r'<a href="([^"]+)">Click here to download</a>', self.html) +                m = re.search(self.DIRECT_LINK_PATTERN, self.html)                  return m.group(1)          self.parseError('No direct link within 10 retries') diff --git a/module/plugins/hoster/X7To.py b/module/plugins/hoster/X7To.py index 51f8e6cd4..79adf2a3f 100644 --- a/module/plugins/hoster/X7To.py +++ b/module/plugins/hoster/X7To.py @@ -55,7 +55,7 @@ class X7To(Hoster):          file_id = re.search(r"var dlID = '(.*?)'", self.html)
          if not file_id:
              self.fail("Free download id not found")
 -	
 +
          file_url = "http://x7.to/james/ticket/dl/" + file_id.group(1)
          self.logDebug("download id %s" % file_id.group(1))
 diff --git a/module/plugins/hoster/YoutubeCom.py b/module/plugins/hoster/YoutubeCom.py index a9fed5638..8b8764367 100644 --- a/module/plugins/hoster/YoutubeCom.py +++ b/module/plugins/hoster/YoutubeCom.py @@ -2,11 +2,34 @@  # -*- coding: utf-8 -*-  import re +import subprocess +import os +import os.path  from urllib import unquote  from module.utils import html_unescape  from module.plugins.Hoster import Hoster +def which(program): +    """Works exactly like the unix command which + +    Courtesy of http://stackoverflow.com/a/377028/675646""" +    def is_exe(fpath): +        return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + +    fpath, fname = os.path.split(program) +    if fpath: +        if is_exe(program): +            return program +    else: +        for path in os.environ["PATH"].split(os.pathsep): +            path = path.strip('"') +            exe_file = os.path.join(path, program) +            if is_exe(exe_file): +                return exe_file + +    return None +  class YoutubeCom(Hoster):      __name__ = "YoutubeCom"      __type__ = "hoster" @@ -112,7 +135,30 @@ class YoutubeCom(Hoster):          #set file name                  file_suffix = self.formats[fmt][0] if fmt in self.formats else ".flv"          file_name_pattern = '<meta name="title" content="(.+?)">' -        name = re.search(file_name_pattern, html).group(1).replace("/", "") + file_suffix +        name = re.search(file_name_pattern, html).group(1).replace("/", "")          pyfile.name = html_unescape(name) -         -        self.download(url)
\ No newline at end of file + +        time = re.search(r"t=((\d+)m)?(\d+)s", pyfile.url) +        ffmpeg = which("ffmpeg") +        if ffmpeg and time: +            m, s = time.groups()[1:] +            if not m: +                m = "0" + +            pyfile.name += " (starting at %s:%s)" % (m, s) +        pyfile.name += file_suffix + +        filename = self.download(url) + +        if ffmpeg and time: +            inputfile = filename + "_" +            os.rename(filename, inputfile) + +            subprocess.call([ +                ffmpeg, +                "-ss", "00:%s:%s" % (m, s), +                "-i", inputfile, +                "-vcodec", "copy", +                "-acodec", "copy", +                filename]) +            os.remove(inputfile) diff --git a/module/plugins/hoster/ZDF.py b/module/plugins/hoster/ZDF.py new file mode 100644 index 000000000..ea45f4fd8 --- /dev/null +++ b/module/plugins/hoster/ZDF.py @@ -0,0 +1,46 @@ + +import re +from xml.etree.ElementTree import fromstring + +from module.plugins.Hoster import Hoster + +XML_API = "http://www.zdf.de/ZDFmediathek/xmlservice/web/beitragsDetails?id=%i" + +class ZDF(Hoster): +    # Based on zdfm by Roland Beermann +    # http://github.com/enkore/zdfm/ +    __name__ = "ZDF Mediathek" +    __version__ = "0.7" +    __pattern__ = r"http://www\.zdf\.de/ZDFmediathek/[^0-9]*([0-9]+)[^0-9]*" +    __config__ = [] + +    @staticmethod +    def video_key(video): +        return ( +            int(video.findtext("videoBitrate", "0")), +            any(f.text == "progressive" for f in video.iter("facet")), +        ) + +    @staticmethod +    def video_valid(video): +        return (video.findtext("url").startswith("http") and video.findtext("url").endswith(".mp4")) + +    @staticmethod +    def get_id(url): +        return int(re.search(r"[^0-9]*([0-9]+)[^0-9]*", url).group(1)) + +    def process(self, pyfile): +        xml = fromstring(self.load(XML_API % self.get_id(pyfile.url))) + +        status = xml.findtext("./status/statuscode") +        if status != "ok": +            self.fail("Error retrieving manifest.") + +        video = xml.find("video") +        title = video.findtext("information/title") + +        pyfile.name = title +         +        target_url = sorted((v for v in video.iter("formitaet") if self.video_valid(v)), key=self.video_key)[-1].findtext("url") + +        self.download(target_url) diff --git a/module/plugins/internal/CaptchaService.py b/module/plugins/internal/CaptchaService.py index f2de00732..b912436a7 100644 --- a/module/plugins/internal/CaptchaService.py +++ b/module/plugins/internal/CaptchaService.py @@ -19,7 +19,7 @@  import re  class CaptchaService():     -    __version__ = "0.01" +    __version__ = "0.02"      def __init__(self, plugin):          self.plugin = plugin @@ -64,11 +64,9 @@ class SolveMedia(CaptchaService):          self.plugin = plugin      def challenge(self, src): -        html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.script?k=%s" % src, cookies=True) +        html = self.plugin.req.load("http://api.solvemedia.com/papi/challenge.noscript?k=%s" % src, cookies=True)          try: -            ckey = re.search("ckey:.*?'(.*?)',",html).group(1) -            html = self.plugin.req.load("http://api.solvemedia.com/papi/_challenge.js?k=%s" % ckey, cookies=True) -            challenge = re.search('"chid".*?: "(.*?)"',html).group(1) +            challenge = re.search(r'<input type=hidden name="adcopy_challenge" id="adcopy_challenge" value="([^"]+)">', html).group(1)          except:              self.plugin.fail("solvmedia error")          result = self.result(challenge)  | 
