diff options
-rw-r--r-- | module/AccountManager.py | 16 | ||||
-rw-r--r-- | module/PluginManager.py | 12 | ||||
-rw-r--r-- | module/PluginThread.py | 1 | ||||
-rw-r--r-- | module/config/default.conf | 8 | ||||
-rw-r--r-- | module/plugins/Plugin.py | 8 | ||||
-rw-r--r-- | module/plugins/accounts/RapidshareCom.py | 51 | ||||
-rw-r--r-- | module/plugins/accounts/UploadedTo.py | 35 | ||||
-rw-r--r-- | module/plugins/crypter/YoutubeBatch.py | 33 | ||||
-rw-r--r-- | module/plugins/crypter/YoutubeChannel.py | 52 | ||||
-rw-r--r-- | module/plugins/hooks/IRCInterface.py | 6 | ||||
-rw-r--r-- | module/plugins/hooks/UnRar.py | 4 | ||||
-rw-r--r-- | module/plugins/hooks/XMPPInterface.py | 229 | ||||
-rw-r--r-- | module/plugins/hoster/NetloadIn.py | 20 | ||||
-rw-r--r-- | module/plugins/hoster/ShareCx.py | 27 | ||||
-rw-r--r-- | module/plugins/hoster/ShareonlineBiz.py | 31 | ||||
-rw-r--r-- | module/plugins/hoster/YoutubeCom.py | 7 | ||||
-rw-r--r-- | module/pyunrar.py | 4 | ||||
-rw-r--r-- | module/web/pyload/views.py | 25 | ||||
-rw-r--r-- | module/web/templates/default/settings.html | 55 | ||||
-rwxr-xr-x | pyLoadCli.py | 9 | ||||
-rwxr-xr-x | pyLoadCore.py | 17 |
21 files changed, 498 insertions, 152 deletions
diff --git a/module/AccountManager.py b/module/AccountManager.py index 0122b0223..fc122e760 100644 --- a/module/AccountManager.py +++ b/module/AccountManager.py @@ -51,7 +51,14 @@ class AccountManager(): else: return None - + def getAccountPlugins(self): + """ get all account instances""" + + plugins = [] + for plugin in self.accounts.keys(): + plugins.append(self.getAccountPlugin(plugin)) + + return plugins #---------------------------------------------------------------------- def loadAccounts(self): """loads all accounts available""" @@ -107,7 +114,7 @@ class AccountManager(): f = open("accounts.conf", "wb") f.write("version: " + str(ACC_VERSION) + "\n") - + for plugin, accounts in self.accounts.iteritems(): f.write("\n") f.write(plugin+":\n") @@ -145,11 +152,12 @@ class AccountManager(): #---------------------------------------------------------------------- def removeAccount(self, plugin, user): """remove account""" + if self.accounts.has_key(plugin): p = self.getAccountPlugin(plugin) p.removeAccount(user) - if self.accounts.has_key(user): - del self.accounts[user] + if self.accounts[plugin].has_key(user): + del self.accounts[plugin][user] self.saveAccounts() diff --git a/module/PluginManager.py b/module/PluginManager.py index 44a426d31..8bb5a5ec6 100644 --- a/module/PluginManager.py +++ b/module/PluginManager.py @@ -132,7 +132,7 @@ class PluginManager(): config = [ [y.strip() for y in x.replace("'","").replace('"',"").replace(")","").split(",")] for x in config[0].split("(") if x.strip()] if folder == "hooks": - config.append( ["load", "bool", "Load on startup", True] ) + config.append( ["load", "bool", "Load on startup", True if name not in ("XMPPInterface", "MultiHome") else False] ) for item in config: self.core.config.addPluginConfig([name]+item) @@ -238,8 +238,16 @@ class PluginManager(): classes.append(value["class"]) continue - module = __import__(value["path"], globals(), locals(), [value["name"]] , -1) + if not self.core.config.getPlugin(name, "load"): + continue + try: + module = __import__(value["path"], globals(), locals(), [value["name"]] , -1) + except Exception, e: + self.log.error(_("Error importing %s: %s") % (name, str(e))) + self.log.error(_("You should fix dependicies or deactivate load on startup.")) + continue + pluginClass = getattr(module, name) value["class"] = pluginClass diff --git a/module/PluginThread.py b/module/PluginThread.py index c666e7875..f727aa7f0 100644 --- a/module/PluginThread.py +++ b/module/PluginThread.py @@ -70,6 +70,7 @@ class DownloadThread(PluginThread): self.m.log.info(_("Download starts: %s" % pyfile.name)) try: + self.m.core.hookManager.downloadStarts(pyfile) pyfile.plugin.preprocessing(self) except NotImplementedError: diff --git a/module/config/default.conf b/module/config/default.conf index b1c0c648e..e9c7782e6 100644 --- a/module/config/default.conf +++ b/module/config/default.conf @@ -21,17 +21,15 @@ log - "Log": str log_folder : "Folder" = Logs
int log_count : "Count" = 5
general - "General":
- en;de;fr;nl;pl language : "Language" = de
+ en;de;fr;nl;pl language : "Language" = en
str download_folder : "Download Folder" = Downloads
int max_downloads : "Max Parallel Downloads" = 3
- str link_file : "File For Links" = links.txt
- str failed_file : "File For Failed Links" = failed_links.txt
bool debug_mode : "Debug Mode" = False
int max_download_time : "Max Download Time" = 5
int download_speed_limit : "Download Speed Limit" = 0
- bool checksum : "Use Checksum" = True
+ bool checksum : "Use Checksum" = False
int min_free_space : "Min Free Space (MB)" = 200
- bool folder_per_package : "Create folder for each package" = False
+ bool folder_per_package : "Create folder for each package" = True
ip download_interface : "Outgoing IP address for downloads" = None
updates - "Updates":
bool search_updates : "Search" = True
diff --git a/module/plugins/Plugin.py b/module/plugins/Plugin.py index 04a5adb91..02a15dfbc 100644 --- a/module/plugins/Plugin.py +++ b/module/plugins/Plugin.py @@ -34,6 +34,14 @@ from os import makedirs from tempfile import NamedTemporaryFile from mimetypes import guess_type +from itertools import islice + +def chunks(iterable, size): + it = iter(iterable) + item = list(islice(it, size)) + while item: + yield item + item = list(islice(it, size)) def dec(func): def new(*args): diff --git a/module/plugins/accounts/RapidshareCom.py b/module/plugins/accounts/RapidshareCom.py index 052470ada..7f5fff84d 100644 --- a/module/plugins/accounts/RapidshareCom.py +++ b/module/plugins/accounts/RapidshareCom.py @@ -28,31 +28,34 @@ class RapidshareCom(Account): __author_mail__ = ("mkaay@mkaay.de") def getAccountInfo(self, user): - data = None - for account in self.accounts.items(): - if account[0] == user: - data = account[1] - if not data: - return - req = self.core.requestFactory.getRequest(self.__name__, user) - api_url_base = "http://api.rapidshare.com/cgi-bin/rsapi.cgi" - api_param_prem = {"sub": "getaccountdetails_v1", "type": "prem", "login": user, "password": data["password"], "withcookie": 1} - src = req.load(api_url_base, cookies=False, get=api_param_prem) - if src.startswith("ERROR"): - return - fields = src.split("\n") - info = {} - for t in fields: - if not t.strip(): - continue - k, v = t.split("=") - info[k] = v + try: + data = None + for account in self.accounts.items(): + if account[0] == user: + data = account[1] + if not data: + return + req = self.core.requestFactory.getRequest(self.__name__, user) + api_url_base = "http://api.rapidshare.com/cgi-bin/rsapi.cgi" + api_param_prem = {"sub": "getaccountdetails_v1", "type": "prem", "login": user, "password": data["password"], "withcookie": 1} + src = req.load(api_url_base, cookies=False, get=api_param_prem) + if src.startswith("ERROR"): + return + fields = src.split("\n") + info = {} + for t in fields: + if not t.strip(): + continue + k, v = t.split("=") + info[k] = v + + out = Account.getAccountInfo(self, user) + tmp = {"validuntil":None, "login":str(info["accountid"]), "trafficleft":int(info["tskb"]), "type":self.__name__} + out.update(tmp) - out = Account.getAccountInfo(self, user) - tmp = {"validuntil":None, "login":str(info["accountid"]), "trafficleft":int(info["tskb"]), "type":self.__name__} - out.update(tmp) - - return out + return out + except: + return Account.getAccountInfo(self, user) def login(self, user, data): req = self.core.requestFactory.getRequest(self.__name__, user) diff --git a/module/plugins/accounts/UploadedTo.py b/module/plugins/accounts/UploadedTo.py index d2aa22b22..926f91255 100644 --- a/module/plugins/accounts/UploadedTo.py +++ b/module/plugins/accounts/UploadedTo.py @@ -30,22 +30,25 @@ class UploadedTo(Account): __author_mail__ = ("mkaay@mkaay.de") def getAccountInfo(self, user): - data = None - for account in self.accounts.items(): - if account[0] == user: - data = account[1] - if not data: - return - req = self.core.requestFactory.getRequest(self.__name__, user) - html = req.load("http://uploaded.to/", cookies=True) - raw_traffic = re.search(r"Traffic left: </span><span class=.*?>(.*?)</span>", html).group(1) - raw_valid = re.search(r"Valid until: </span> <span class=.*?>(.*?)</span>", html).group(1) - traffic = int(self.parseTraffic(raw_traffic)) - validuntil = int(mktime(strptime(raw_valid.strip(), "%d-%m-%Y %H:%M"))) - out = Account.getAccountInfo(self, user) - tmp = {"login":user, "validuntil":validuntil, "trafficleft":traffic, "type":self.__name__} - out.update(tmp) - return out + try: + data = None + for account in self.accounts.items(): + if account[0] == user: + data = account[1] + if not data: + return + req = self.core.requestFactory.getRequest(self.__name__, user) + html = req.load("http://uploaded.to/", cookies=True) + raw_traffic = re.search(r"Traffic left: </span><span class=.*?>(.*?)</span>", html).group(1) + raw_valid = re.search(r"Valid until: </span> <span class=.*?>(.*?)</span>", html).group(1) + traffic = int(self.parseTraffic(raw_traffic)) + validuntil = int(mktime(strptime(raw_valid.strip(), "%d-%m-%Y %H:%M"))) + out = Account.getAccountInfo(self, user) + tmp = {"login":user, "validuntil":validuntil, "trafficleft":traffic, "type":self.__name__} + out.update(tmp) + return out + except: + return Account.getAccountInfo(self, user) def login(self, user, data): req = self.core.requestFactory.getRequest(self.__name__, user) diff --git a/module/plugins/crypter/YoutubeBatch.py b/module/plugins/crypter/YoutubeBatch.py new file mode 100644 index 000000000..091c8558a --- /dev/null +++ b/module/plugins/crypter/YoutubeBatch.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import re + +from module.plugins.Crypter import Crypter + +class YoutubeBatch(Crypter): + __name__ = "YoutubeBatch" + __type__ = "container" + __pattern__ = r"http://(www\.)?(de\.)?\youtube\.com/user/*" + __version__ = "0.9" + __description__ = """Youtube.com Channel Download Plugin""" + __author_name__ = ("RaNaN", "Spoob") + __author_mail__ = ("RaNaN@pyload.org", "spoob@pyload.org") + + def setup(self): + self.user = re.search(r"/user/(.+)", self.pyfile.url).group(1).split("#")[0] + self.playlist = re.search(r"/user/%s.*?/user/(.{16})" % self.user, self.pyfile.url).group(1) + + def file_exists(self): + if "User not found" in self.req.load("http://gdata.youtube.com/feeds/api/playlists/%s?v=2" % self.playlist): + return False + return True + + def decrypt(self, pyfile): + if not self.file_exists(): + self.offline() + url = "http://gdata.youtube.com/feeds/api/playlists/%s?v=2" % self.playlist + rep = self.load(url) + new_links = [] + new_links.extend(re.findall(r"href\='(http:\/\/www.youtube.com\/watch\?v\=[^']+)&", rep)) + self.packages.append((self.pyfile.package().name, new_links, self.pyfile.package().name)) diff --git a/module/plugins/crypter/YoutubeChannel.py b/module/plugins/crypter/YoutubeChannel.py deleted file mode 100644 index 292be06af..000000000 --- a/module/plugins/crypter/YoutubeChannel.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import re - -from module.plugins.Crypter import Crypter - -class YoutubeChannel(Crypter): - __name__ = "YoutubeChannel" - __type__ = "container" - __pattern__ = r"http://(www\.)?(de\.)?\youtube\.com/user/*" - __version__ = "0.9" - __description__ = """Youtube.com Channel Download Plugin""" - __author_name__ = ("RaNaN", "Spoob") - __author_mail__ = ("RaNaN@pyload.org", "spoob@pyload.org") - - def __init__(self, parent): - Crypter.__init__(self, parent) - self.parent = parent - self.html = None - self.read_config() - self.user = re.search(r"/user/(.+)", self.parent.url).group(1).split("#")[0] - - def file_exists(self): - if "User not found" in self.req.load("http://gdata.youtube.com/feeds/api/users/%s" % self.user): - return False - return True - - def proceed(self, url, location): - max_videos = self.config['max_videos'] - if not max_videos: - max_videos = 1000 #max video a user can upload - page = 0 - temp_links = [] - if "," in self.config['video_groups']: - video_groups = self.config['video_groups'].split(",") - else: - video_groups = [self.config['video_groups']] - for group in video_groups: - for start_index in range(1, int(max_videos), 50): - max_results = max_videos - page * 50 - if max_results > 50: - max_results = 50 - url = "http://gdata.youtube.com/feeds/api/users/%s/%s?max-results=%i&start-index=%i" % (self.user, group, max_results, start_index) - rep = self.req.load(url) - new_links = re.findall(r"href\='(http:\/\/www.youtube.com\/watch\?v\=[^']+)&", rep) - if new_links != []: - temp_links.extend(new_links) - else: - break - page += 1 - self.links = temp_links diff --git a/module/plugins/hooks/IRCInterface.py b/module/plugins/hooks/IRCInterface.py index 2ede56685..8d50647e3 100644 --- a/module/plugins/hooks/IRCInterface.py +++ b/module/plugins/hooks/IRCInterface.py @@ -86,8 +86,8 @@ class IRCInterface(Thread, Hook): for t in self.getConfig("owner").split(): if t.strip().startswith("#"): self.sock.send("JOIN %s\r\n" % t.strip()) - self.log.info("pyLoadIRC: Connected to %s!" % host) - self.log.info("pyLoadIRC: Switching to listening mode!") + self.log.info("pyLoad IRC: Connected to %s!" % host) + self.log.info("pyLoad IRC: Switching to listening mode!") try: self.main_loop() @@ -173,7 +173,7 @@ class IRCInterface(Thread, Hook): for line in res: self.response(line, msg["origin"]) except Exception, e: - self.log.error("pyLoadIRC: "+ repr(e)) + self.log.error("pyLoad IRC: "+ repr(e)) def response(self, msg, origin=""): diff --git a/module/plugins/hooks/UnRar.py b/module/plugins/hooks/UnRar.py index 82c99a575..30cda62af 100644 --- a/module/plugins/hooks/UnRar.py +++ b/module/plugins/hooks/UnRar.py @@ -30,7 +30,7 @@ class UnRar(Hook): __name__ = "UnRar" __version__ = "0.1" __description__ = """unrar""" - __config__ = [ ("activated", "bool", "Activated", True), + __config__ = [ ("activated", "bool", "Activated", False), ("fullpath", "bool", "extract full path", True), ("overwrite", "bool", "overwrite files", True), ("passwordfile", "str", "unrar passoword file", "unrar_passwords.txt"), @@ -109,7 +109,7 @@ class UnRar(Hook): u.crackPassword(passwords=self.passwords, statusFunction=s, overwrite=True, destination=folder) except WrongPasswordError: continue - except CommandError as e: + except CommandError , e: if re.search("Cannot find volume", e.stderr): continue try: diff --git a/module/plugins/hooks/XMPPInterface.py b/module/plugins/hooks/XMPPInterface.py new file mode 100644 index 000000000..67a7f1b77 --- /dev/null +++ b/module/plugins/hooks/XMPPInterface.py @@ -0,0 +1,229 @@ +# -*- 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: RaNaN + @interface-version: 0.2 +""" + +import socket +import sys +from threading import Thread +import time +from time import sleep +from traceback import print_exc + +from pyxmpp.all import JID,Iq,Presence,Message,StreamError +from pyxmpp.jabber.client import JabberClient +from pyxmpp.interface import implements +from pyxmpp.interfaces import * +from pyxmpp.streamtls import TLSSettings + +from module.plugins.Hook import Hook +from module.plugins.hooks.IRCInterface import IRCInterface + +class XMPPInterface(IRCInterface, JabberClient): + __name__ = "XMPPInterface" + __version__ = "0.1" + __description__ = """connect to jabber and let owner perform different tasks""" + __config__ = [("activated", "bool", "Activated", "False"), + ("jid", "str", "Jabber ID", "user@exmaple-jabber-server.org"), + ("pw", "str", "Password", ""), + ("owners", "str", "List of JIDs accepting commands from", "me@icq-gateway.org;some@msn-gateway.org"), + ("info_file", "bool", "Inform about every file finished", "False"), + ("info_pack", "bool", "Inform about every package finished", "True")] + __author_name__ = ("RaNaN") + __author_mail__ = ("RaNaN@pyload.org") + + implements(IMessageHandlersProvider) + + def __init__(self, core): + IRCInterface.__init__(self, core) + + self.jid = JID(self.getConfig("jid")) + password = self.getConfig("pw") + + # if bare JID is provided add a resource -- it is required + if not self.jid.resource: + self.jid=JID(self.jid.node, self.jid.domain, "pyLoad") + + tls_settings = None + + # setup client with provided connection information + # and identity data + JabberClient.__init__(self, self.jid, password, + disco_name="pyLoad XMPP Client", disco_type="bot", + tls_settings = tls_settings) + + self.interface_providers = [ + VersionHandler(self), + self, + ] + + def coreReady(self): + self.new_package = {} + + self.start() + + def packageFinished(self, pypack): + + try: + if self.getConfig("info_pack"): + self.announce(_("Package finished: %s") % pypack.name) + except: + pass + + def downloadFinished(self, pyfile): + try: + if self.getConfig("info_file"): + self.announce(_("Download finished: %s @ %s") % (pyfile.name, pyfile.pluginname) ) + except: + pass + + def run(self): + # connect to IRC etc. + self.connect() + try: + self.loop(1) + except Exception, ex: + self.core.log.error("pyLoad XMPP: %s" % str(ex)) + + def stream_state_changed(self,state,arg): + """This one is called when the state of stream connecting the component + to a server changes. This will usually be used to let the user + know what is going on.""" + self.log.debug("pyLoad XMPP: *** State changed: %s %r ***" % (state,arg) ) + + def get_message_handlers(self): + """Return list of (message_type, message_handler) tuples. + + The handlers returned will be called when matching message is received + in a client session.""" + return [ + ("normal", self.message), + ] + + def message(self,stanza): + """Message handler for the component.""" + subject=stanza.get_subject() + body=stanza.get_body() + t=stanza.get_type() + self.log.debug(_(u'pyLoad XMPP: Message from %s received.') % (unicode(stanza.get_from(),))) + self.log.debug(_(u'pyLoad XMPP: Body: %s') % body) + + if stanza.get_type()=="headline": + # 'headline' messages should never be replied to + return True + if subject: + subject=u"Re: "+subject + + to_jid = stanza.get_from() + from_jid = stanza.get_to() + + #j = JID() + to_name = to_jid.as_utf8() + from_name = from_jid.as_utf8() + + names = self.getConfig("owners").split(";") + + if to_name in names or to_jid.node+"@"+to_jid.domain in names: + + messages = [] + + trigger = "pass" + args = None + + temp = body.split() + trigger = temp[0] + if len(temp) > 1: + args = temp[1:] + + handler = getattr(self, "event_%s" % trigger, self.event_pass) + try: + res = handler(args) + for line in res: + m=Message( + to_jid=to_jid, + from_jid=from_jid, + stanza_type=stanza.get_type(), + subject=subject, + body=line) + + messages.append(m) + except Exception, e: + self.log.error("pyLoad XMPP: "+ repr(e)) + + return messages + + else: + return True + + + def announce(self, message): + """ send message to all owners""" + for user in self.getConfig("owners").split(";"): + + self.log.debug(_("pyLoad XMPP: Send message to %s") % user) + + to_jid = JID(user) + + m = Message(from_jid=self.jid, + to_jid=to_jid, + stanza_type="chat", + body=message) + + self.stream.send(m) + + +class VersionHandler(object): + """Provides handler for a version query. + + This class will answer version query and announce 'jabber:iq:version' namespace + in the client's disco#info results.""" + + implements(IIqHandlersProvider, IFeaturesProvider) + + def __init__(self, client): + """Just remember who created this.""" + self.client = client + + def get_features(self): + """Return namespace which should the client include in its reply to a + disco#info query.""" + return ["jabber:iq:version"] + + def get_iq_get_handlers(self): + """Return list of tuples (element_name, namespace, handler) describing + handlers of <iq type='get'/> stanzas""" + return [ + ("query", "jabber:iq:version", self.get_version), + ] + + def get_iq_set_handlers(self): + """Return empty list, as this class provides no <iq type='set'/> stanza handler.""" + return [] + + def get_version(self,iq): + """Handler for jabber:iq:version queries. + + jabber:iq:version queries are not supported directly by PyXMPP, so the + XML node is accessed directly through the libxml2 API. This should be + used very carefully!""" + iq=iq.make_result_response() + q=iq.new_query("jabber:iq:version") + q.newTextChild(q.ns(),"name","Echo component") + q.newTextChild(q.ns(),"version","1.0") + return iq +
\ No newline at end of file diff --git a/module/plugins/hoster/NetloadIn.py b/module/plugins/hoster/NetloadIn.py index 9e117fa14..6f0cb9461 100644 --- a/module/plugins/hoster/NetloadIn.py +++ b/module/plugins/hoster/NetloadIn.py @@ -4,8 +4,12 @@ import re from time import sleep + from module.plugins.Hoster import Hoster from module.network.Request import getURL +from module.plugins.Plugin import chunks + + def getInfo(urls): ## returns list of tupels (name, size (in bytes), status (see FileDatabase), url) @@ -14,14 +18,10 @@ def getInfo(urls): apiurl = "http://api.netload.in/info.php?auth=Zf9SnQh9WiReEsb18akjvQGqT0I830e8&bz=1&md5=1&file_id=" id_regex = re.compile("http://.*netload\.in/(?:datei(.*?)(?:\.htm|/)|index.php?id=10&file_id=)") urls_per_query = 80 - - iterations = len(urls)/urls_per_query - if len(urls)%urls_per_query > 0: - iterations = iterations +1 - - for i in range(iterations): + + for chunk in chunks(urls, urls_per_query): ids = "" - for url in urls[i*urls_per_query:(i+1)*urls_per_query]: + for url in chunk: match = id_regex.search(url) if match: ids = ids + match.group(1) +";" @@ -37,19 +37,17 @@ def getInfo(urls): result = [] - counter = 0 - for r in api.split(): + for i, r in enumerate(api.split()): try: tmp = r.split(";") try: size = int(tmp[2]) except: size = 0 - result.append( (tmp[1], size, 2 if tmp[3] == "online" else 1, urls[(i*80)+counter]) ) + result.append( (tmp[1], size, 2 if tmp[3] == "online" else 1, chunk[i] ) ) except: print "Netload prefetch: Error while processing response: " print r - counter = counter +1 yield result diff --git a/module/plugins/hoster/ShareCx.py b/module/plugins/hoster/ShareCx.py index feee30cd3..e64459754 100644 --- a/module/plugins/hoster/ShareCx.py +++ b/module/plugins/hoster/ShareCx.py @@ -3,8 +3,35 @@ import re
from module.plugins.Hoster import Hoster
+from module.plugins.Plugin import chunks
+from module.network.Request import getURL
#from module.BeautifulSoup import BeautifulSoup
+def getInfo(urls):
+ api_url = "http://www.share.cx/uapi?do=check&links="
+
+ for chunk in chunks(urls, 90):
+ get = ""
+ for url in chunk:
+ get += ";"+url
+
+ api = getURL(api_url+get[1:])
+ result = []
+
+ for i, link in enumerate(api.split()):
+ url,name,size = link.split(";")
+ if name and size:
+ status = 2
+ else:
+ status = 1
+
+ if not name: name = chunk[i]
+ if not size: size = 0
+
+ result.append( (name, size, status, chunk[i]) )
+
+ yield result
+
class ShareCx(Hoster):
__name__ = "ShareCx"
__type__ = "hoster"
diff --git a/module/plugins/hoster/ShareonlineBiz.py b/module/plugins/hoster/ShareonlineBiz.py index 8646fcc88..42a2bc560 100644 --- a/module/plugins/hoster/ShareonlineBiz.py +++ b/module/plugins/hoster/ShareonlineBiz.py @@ -13,19 +13,30 @@ from time import sleep from module.plugins.Hoster import Hoster from module.network.Request import getURL +from module.plugins.Plugin import chunks + def getInfo(urls): api_url_base = "http://www.share-online.biz/linkcheck/linkcheck.php" - api_param_file = {"links": "\n".join(x.replace("http://www.share-online.biz/dl/","") for x in urls)} #api only supports old style links - src = getURL(api_url_base, post=api_param_file) - result = [] - for i, res in enumerate(src.split("\n")): - if not res: - continue - fields = res.split(";") - status = 2 if fields[1] == "OK" else 3 - result.append((fields[2], int(fields[3]), status, urls[i])) - yield result + + for chunk in chunks(urls, 90): + api_param_file = {"links": "\n".join(x.replace("http://www.share-online.biz/dl/","") for x in chunk)} #api only supports old style links + src = getURL(api_url_base, post=api_param_file) + result = [] + for i, res in enumerate(src.split("\n")): + if not res: + continue + fields = res.split(";") + + if fields[1] == "OK": + status = 2 + elif fields[1] in ("DELETED", "NOT FOUND"): + status = 1 + else: + status = 3 + + result.append((fields[2], int(fields[3]), status, chunk[i])) + yield result class ShareonlineBiz(Hoster): __name__ = "ShareonlineBiz" diff --git a/module/plugins/hoster/YoutubeCom.py b/module/plugins/hoster/YoutubeCom.py index e40b0c9ad..d92d8d128 100644 --- a/module/plugins/hoster/YoutubeCom.py +++ b/module/plugins/hoster/YoutubeCom.py @@ -32,9 +32,8 @@ class YoutubeCom(Hoster): if self.getConf("quality") == "hd" or self.getConf("quality") == "hq": file_suffix = ".mp4" - name = re.search(file_name_pattern, html).group(1).replace("/", "") + file_suffix - - pyfile.name = name.replace("&", "&").replace("ö", "oe").replace("ä", "ae").replace("ü", "ue") + name = (re.search(file_name_pattern, html).group(1).replace("/", "") + file_suffix).decode("utf8") + pyfile.name = name #.replace("&", "&").replace("ö", "oe").replace("ä", "ae").replace("ü", "ue") if self.getConf("quality") == "sd": quality = "&fmt=6" @@ -45,4 +44,4 @@ class YoutubeCom(Hoster): file_url = 'http://youtube.com/get_video?video_id=' + videoId + '&t=' + videoHash + quality + "&asv=2" - self.download(file_url)
\ No newline at end of file + self.download(file_url) diff --git a/module/pyunrar.py b/module/pyunrar.py index 4db3c3a19..6bb240965 100644 --- a/module/pyunrar.py +++ b/module/pyunrar.py @@ -270,7 +270,7 @@ class Unrar(): if overwrite: try: remove(abspath(join(destination, sf[0]))) - except OSError as e: + except OSError, e: if not e.errno == 2: raise e f = sf[0] @@ -278,7 +278,7 @@ class Unrar(): if fullPath: try: makedirs(dirname(join(abspath(destination), sf[0]))) - except OSError as e: + except OSError, e: if not e.errno == 17: raise e d = join(destination, dirname(f)) diff --git a/module/web/pyload/views.py b/module/web/pyload/views.py index b8cbacf30..880ec7843 100644 --- a/module/web/pyload/views.py +++ b/module/web/pyload/views.py @@ -300,6 +300,7 @@ def collector(request): def config(request): conf = settings.PYLOAD.get_config() plugin = settings.PYLOAD.get_plugin_config() + accs = settings.PYLOAD.get_accounts() messages = [] for section in chain(conf.itervalues(), plugin.itervalues()): @@ -343,6 +344,26 @@ def config(request): continue else: continue + + elif sec == "Accounts": + if ";" in okey: + action, name = okey.split(";") + + if action == "delete": + settings.PYLOAD.remove_account(skey, name) + elif action == "password": + + for acc in accs[skey]: + if acc["login"] == name and acc["password"] != value: + settings.PYLOAD.update_account(skey, name, value) + + elif okey == "newacc" and value: + # add account + + pw = request.POST.get("Accounts|%s|newpw" % skey) + + settings.PYLOAD.update_account(skey, value, pw) + if errors: messages.append(_("Error occured when setting the following options:")) @@ -351,4 +372,6 @@ def config(request): else: messages.append(_("All options were set correctly.")) - return render_to_response(join(settings.TEMPLATE, 'settings.html'), RequestContext(request, {'conf': {'Plugin':plugin, 'General':conf}, 'errors': messages}, [status_proc])) + accs = settings.PYLOAD.get_accounts() + + return render_to_response(join(settings.TEMPLATE, 'settings.html'), RequestContext(request, {'conf': {'Plugin':plugin, 'General':conf, 'Accounts': accs}, 'errors': messages}, [status_proc])) diff --git a/module/web/templates/default/settings.html b/module/web/templates/default/settings.html index 208549813..e9a40ff3a 100644 --- a/module/web/templates/default/settings.html +++ b/module/web/templates/default/settings.html @@ -77,17 +77,23 @@ <ul id="tabs" class="tabs"> {% for configname, config in conf.iteritems %} <span id="g_{{configname}}"> - {% for skey, section in config.iteritems %} - <li><a href="#{{configname}}{{skey}}">{{section.desc}}</a></li> - {% endfor %} + {% ifnotequal configname "Accounts" %} + {% for skey, section in config.iteritems %} + <li><a href="#{{configname}}{{skey}}">{{section.desc}}</a></li> + {% endfor %} + {% else %} + {% for skey, section in config.iteritems %} + <li><a href="#{{configname}}{{skey}}">{{skey}}</a></li> + {% endfor %} + {% endifnotequal %} </span> {% endfor %} </ul> </div> <form id="horizontalForm" action="" method="POST"> {% for configname, config in conf.iteritems %} + {% ifnotequal configname "Accounts" %} {% for skey, section in config.iteritems %} - <div class="tabContent" id="{{configname}}{{skey}}"> <table class="settable"> {% for okey, option in section.items %} @@ -118,6 +124,47 @@ </table> </div> {% endfor %} + {% else %} + <!-- Accounts --> + {% for plugin, accounts in config.iteritems %} + <div class="tabContent" id="{{configname}}{{plugin}}"> + <table class="settable"> + {% for account in accounts %} + <tr> + <td><label for="{{configname}}|{{plugin}}|password;{{account.login}}" style="color:#424242;">{{account.login}}:</label></td> + <td> + <input id="{{plugin}}|delete;{{account.login}}" name="{{configname}}|{{plugin}}|password;{{account.login}}" type="password" value="{{account.password}}"/> + </td> + <td> + {% trans "Delete? " %} + <input id="{{plugin}}|delete;{{account.login}}" name="{{configname}}|{{plugin}}|delete;{{account.login}}" type="checkbox" value="True"/> + + </td> + </tr> + + {% endfor %} + <tr><td> </td></tr> + + <tr> + <td><label for="{{configname}}|{{plugin}}|{{account.login}}" style="color:#424242;">{% trans "New account:" %}</label></td> + + <td> + <input id="{{plugin}}|newacc" name="{{configname}}|{{plugin}}|newacc" type="text"/> + </td> + </tr> + <tr> + <td><label for="{{configname}}|{{plugin}}|{{account.name}}" style="color:#424242;">{% trans "New password:" %}</label></td> + + <td> + <input id="{{config}}|{{plugin}}" name="{{configname}}|{{plugin}}|newpw" type="password"/> + </td> + </tr> + + </table> + </div> + {% endfor %} + + {% endifnotequal %} {% endfor %} {% if conf %} <input class="submit" type="submit" value="{% trans "Submit" %}" /> diff --git a/pyLoadCli.py b/pyLoadCli.py index 36ab0c4f7..4e97489c8 100755 --- a/pyLoadCli.py +++ b/pyLoadCli.py @@ -30,10 +30,15 @@ import threading import time from time import sleep import xmlrpclib +from traceback import print_exc from module import InitHomeDir from module.ConfigParser import ConfigParser +import codecs + +sys.stdout = codecs.getwriter("utf8")(sys.stdout, errors = "replace") + if sys.stdout.encoding.lower().startswith("utf"): conv = unicode else: @@ -109,7 +114,7 @@ class pyLoadCli: return conv(size / 1024 ** 2) + " MiB" def println(self, line, content): - print "\033[" + conv(line) + ";0H\033[2K" + conv(content) + "\033[" + conv((self.inputline if self.inputline > 0 else self.inputline + 1) - 1) + ";0H" + print "\033[" + conv(line) + ";0H\033[2K" + content + "\033[" + conv((self.inputline if self.inputline > 0 else self.inputline + 1) - 1) + ";0H" def print_input(self): self.println(self.inputline, white(" Input: ") + self.input) @@ -336,7 +341,7 @@ class RefreshThread(threading.Thread): self.cli.println(2, red(conv(e))) self.cli.pos[1] = 0 self.cli.pos[2] = 0 - + print_exc() diff --git a/pyLoadCore.py b/pyLoadCore.py index 8dc725ca7..cc9480dee 100755 --- a/pyLoadCore.py +++ b/pyLoadCore.py @@ -64,6 +64,7 @@ import module.remote.SecureXMLRPCServer as Server from module.web.ServerThread import WebServer from module.FileDatabase import PyFile + class Core(object): """ pyLoad Core """ @@ -71,7 +72,6 @@ class Core(object): self.doDebug = False self.arg_links = [] - if len(argv) > 1: try: options, args = getopt(argv[1:], 'vca:hdus:', ["version", "clear", "add=", "help", "debug", "user", "setup", "configdir="]) @@ -156,7 +156,6 @@ class Core(object): s.start() exit() - self.config = ConfigParser() translation = gettext.translation("pyLoad", self.path("locale"), languages=["en", self.config['general']['language']]) @@ -214,7 +213,7 @@ class Core(object): self.init_server() self.init_webserver() - linkFile = self.config['general']['link_file'] + #linkFile = self.config['general']['link_file'] freeSpace = self.freeSpace() if freeSpace > 5 * 1024: @@ -613,20 +612,18 @@ class ServerMethods(): return self.core.pullManager.getEvents(uuid) def get_accounts(self): - plugins = self.core.pluginManager.getAccountPlugins() - data = [] + plugins = self.core.accountManager.getAccountPlugins() + data = {} for p in plugins: - data.extend(p.getAllAccounts()) + data[p.__name__] = p.getAllAccounts() return data def update_account(self, plugin, account, password, options=[]): """ create and update account """ - plugins = self.core.pluginManager.getAccountPlugins() - self.core.pluginManager.updateAccount(plugin, account, password, options) + self.core.accountManager.updateAccount(plugin, account, password, options) def remove_account(self, plugin, account): - plugins = self.core.pluginManager.getAccountPlugins() - self.core.pluginManager.removeAccount(plugin, account) + self.core.accountManager.removeAccount(plugin, account) def set_priority(self, id, priority): p = self.core.files.getPackage(id) |