added uploaded.to support (no premium yet... only free downloads)
[vuplus_dvbapp-plugin] / rsdownloader / src / plugin.py
1 ##\r
2 ## RS Downloader\r
3 ## by AliAbdul\r
4 ##\r
5 ##\r
6 from base64 import encodestring\r
7 from Components.ActionMap import ActionMap\r
8 from Components.config import config, ConfigInteger, ConfigText, ConfigYesNo, ConfigClock, ConfigSubsection, getConfigListEntry\r
9 from Components.ConfigList import ConfigListScreen\r
10 from Components.Label import Label\r
11 from Components.Language import language\r
12 from Components.MenuList import MenuList\r
13 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest\r
14 from Components.ScrollLabel import ScrollLabel\r
15 from container.decrypt import decrypt\r
16 from enigma import eListboxPythonMultiContent, eTimer, gFont, RT_HALIGN_CENTER, RT_HALIGN_RIGHT\r
17 from os import environ, listdir, remove\r
18 from Plugins.Plugin import PluginDescriptor\r
19 from Screens.ChoiceBox import ChoiceBox\r
20 from Screens.MessageBox import MessageBox\r
21 from Screens.Screen import Screen\r
22 from Screens.VirtualKeyBoard import VirtualKeyBoard\r
23 from time import localtime, sleep, strftime, time\r
24 from Tools.Directories import resolveFilename, SCOPE_SKIN_IMAGE, SCOPE_LANGUAGE, SCOPE_PLUGINS\r
25 from Tools.Downloader import HTTPProgressDownloader\r
26 from Tools.LoadPixmap import LoadPixmap\r
27 from twisted.internet import reactor\r
28 from twisted.python import failure\r
29 from twisted.web.client import getPage\r
30 from urlparse import urlparse, urlunparse\r
31 import gettext, re, socket, urllib2\r
32 \r
33 ##############################################################################\r
34 \r
35 config.plugins.RSDownloader = ConfigSubsection()\r
36 config.plugins.RSDownloader.onoff = ConfigYesNo(default=True)\r
37 config.plugins.RSDownloader.username = ConfigText(default="", fixed_size=False)\r
38 config.plugins.RSDownloader.password = ConfigText(default="", fixed_size=False)\r
39 config.plugins.RSDownloader.lists_directory = ConfigText(default="/media/hdd/rs/lists/", fixed_size=False)\r
40 config.plugins.RSDownloader.downloads_directory = ConfigText(default="/media/hdd/rs/downloads", fixed_size=False)\r
41 config.plugins.RSDownloader.ignore_time = ConfigYesNo(default=False)\r
42 config.plugins.RSDownloader.start_time = ConfigClock(default=time())\r
43 config.plugins.RSDownloader.end_time = ConfigClock(default=time())\r
44 config.plugins.RSDownloader.download_monday = ConfigYesNo(default=True)\r
45 config.plugins.RSDownloader.download_tuesday = ConfigYesNo(default=True)\r
46 config.plugins.RSDownloader.download_wednesday = ConfigYesNo(default=True)\r
47 config.plugins.RSDownloader.download_thursday = ConfigYesNo(default=True)\r
48 config.plugins.RSDownloader.download_friday = ConfigYesNo(default=True)\r
49 config.plugins.RSDownloader.download_saturday = ConfigYesNo(default=True)\r
50 config.plugins.RSDownloader.download_sunday = ConfigYesNo(default=True)\r
51 config.plugins.RSDownloader.count_downloads = ConfigInteger(default=3, limits=(1, 6))\r
52 config.plugins.RSDownloader.write_log = ConfigYesNo(default=True)\r
53 config.plugins.RSDownloader.reconnect_fritz = ConfigYesNo(default=False)\r
54 config.plugins.RSDownloader.autorestart_failed = ConfigYesNo(default=False)\r
55 \r
56 ##############################################################################\r
57 \r
58 def localeInit():\r
59         lang = language.getLanguage()\r
60         environ["LANGUAGE"] = lang[:2]\r
61         gettext.bindtextdomain("enigma2", resolveFilename(SCOPE_LANGUAGE))\r
62         gettext.textdomain("enigma2")\r
63         gettext.bindtextdomain("RSDownloader", "%s%s"%(resolveFilename(SCOPE_PLUGINS), "Extensions/RSDownloader/locale/"))\r
64 \r
65 def _(txt):\r
66         t = gettext.dgettext("RSDownloader", txt)\r
67         if t == txt:\r
68                 t = gettext.gettext(txt)\r
69         return t\r
70 \r
71 localeInit()\r
72 language.addCallback(localeInit)\r
73 \r
74 ##############################################################################\r
75 \r
76 def writeLog(message):\r
77         if config.plugins.RSDownloader.write_log.value:\r
78                 try:\r
79                         f = open("/tmp/rapidshare.log", "a")\r
80                         f.write(strftime("%c", localtime(time())) + " - " + message + "\n")\r
81                         f.close()\r
82                 except:\r
83                         pass\r
84 \r
85 ##############################################################################\r
86 \r
87 def _parse(url):\r
88         url = url.strip()\r
89         parsed = urlparse(url)\r
90         scheme = parsed[0]\r
91         path = urlunparse(('','') + parsed[2:])\r
92         host, port = parsed[1], 80\r
93         if '@' in host:\r
94                 username, host = host.split('@')\r
95                 if ':' in username:\r
96                         username, password = username.split(':')\r
97                 else:\r
98                         password = ""\r
99         else:\r
100                 username = ""\r
101                 password = ""\r
102         if ':' in host:\r
103                 host, port = host.split(':')\r
104                 port = int(port)\r
105         if path == "":\r
106                 path = "/"\r
107         return scheme, host, port, path, username, password\r
108 \r
109 class ProgressDownload:\r
110         def __init__(self, url, outputfile, contextFactory=None, *args, **kwargs):\r
111                 scheme, host, port, path, username, password = _parse(url)\r
112                 if username and password:\r
113                         url = scheme + '://' + host + ':' + str(port) + path\r
114                         basicAuth = encodestring("%s:%s"%(username, password))\r
115                         authHeader = "Basic " + basicAuth.strip()\r
116                         AuthHeaders = {"Authorization": authHeader}\r
117                         if kwargs.has_key("headers"):\r
118                                 kwargs["headers"].update(AuthHeaders)\r
119                         else:\r
120                                 kwargs["headers"] = AuthHeaders\r
121                 self.factory = HTTPProgressDownloader(url, outputfile, *args, **kwargs)\r
122                 self.connection = reactor.connectTCP(host, port, self.factory)\r
123 \r
124         def start(self):\r
125                 return self.factory.deferred\r
126 \r
127         def stop(self):\r
128                 self.connection.disconnect()\r
129 \r
130         def addProgress(self, progress_callback):\r
131                 self.factory.progress_callback = progress_callback\r
132 \r
133 ##############################################################################\r
134 \r
135 def get(url):\r
136         try:\r
137                 data = urllib2.urlopen(url)\r
138                 return data.read()\r
139         except:\r
140                 return ""\r
141    \r
142 def post(url, data):\r
143         try:\r
144                 return urllib2.urlopen(url, data).read()\r
145         except:\r
146                 return ""\r
147 \r
148 def matchGet(rex, string):\r
149         match = re.search(rex, string)\r
150         if match:\r
151                 if len(match.groups()) == 0:\r
152                         return string[match.span()[0]:match.span()[1]]\r
153                 if len(match.groups()) == 1:\r
154                         return match.groups()[0]\r
155         else:\r
156                 return False\r
157 \r
158 ##############################################################################\r
159 \r
160 def reconnect(host='fritz.box', port=49000):\r
161         http_body = '\r\n'.join((\r
162                 '<?xml version="1.0" encoding="utf-8"?>',\r
163                 '<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">',\r
164                 '  <s:Body>',\r
165                 '    <u:ForceTermination xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"/>',\r
166                 '  </s:Body>',\r
167                 '</s:Envelope>'))\r
168         http_data = '\r\n'.join((\r
169                 'POST /upnp/control/WANIPConn1 HTTP/1.1',\r
170                 'Host: %s:%d'%(host, port),\r
171                 'SoapAction: urn:schemas-upnp-org:service:WANIPConnection:1#ForceTermination',\r
172                 'Content-Type: text/xml; charset="utf-8"',\r
173                 'Content-Length: %d'%len(http_body),\r
174                 '',\r
175                 http_body))\r
176         try:\r
177                 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\r
178                 s.connect((host, port))\r
179                 s.send(http_data)\r
180                 s.close()\r
181         except:\r
182                 pass\r
183 \r
184 ##############################################################################\r
185 \r
186 class RSDownload:\r
187         def __init__(self, url):\r
188                 writeLog("Adding: %s"%url)\r
189                 self.url = url\r
190                 self.download = None\r
191                 self.downloading = False\r
192                 self.progress = 0\r
193                 self.size = 0\r
194                 self.status = _("Waiting")\r
195                 self.name = self.url.split("/")[-1]\r
196                 self.finishCallbacks = []\r
197 \r
198         def start(self):\r
199                 writeLog("Downloading: %s"%self.url)\r
200                 self.downloading = True\r
201                 self.progress = 0\r
202                 self.size = 0\r
203                 username = config.plugins.RSDownloader.username.value\r
204                 password = config.plugins.RSDownloader.password.value\r
205                 if self.url.__contains__("rapidshare.com") and username == "" and password == "":\r
206                         writeLog("Free RS-Download: %s"%self.url)\r
207                         self.status = _("Checking")\r
208                         if config.plugins.RSDownloader.reconnect_fritz.value:\r
209                                 reconnect()\r
210                                 sleep(3)\r
211                         data = get(self.url)\r
212                         url = matchGet('<form[^>]+action="([^"]+)', data)\r
213                         if not url:\r
214                                 writeLog("Failed: %s"%self.url)\r
215                                 self.httpFailed(True, "Failed to get download page url: %s"%self.url)\r
216                         else:\r
217                                 data = post(url, "dl.start=Free")\r
218                                 seconds = matchGet('var c=([0-9]+)', data)\r
219                                 if not seconds:\r
220                                         self.httpFailed(True, "Failed to get download page url: %s"%self.url)\r
221                                 else:\r
222                                         writeLog("Free RS-Download... must wait %s seconds: %s"%(seconds, self.url))\r
223                                         self.status = "%s %s"%(_("Waiting"), seconds)\r
224                                         url = matchGet('"dlf" action="([^"]+)', data)\r
225                                         if not url:\r
226                                                 self.httpFailed(True, "Failed to get download page url: %s"%self.url)\r
227                                         else:\r
228                                                 self.freeDownloadUrl = url\r
229                                                 self.freeDownloadTimer = eTimer()\r
230                                                 self.freeDownloadTimer.callback.append(self.freeDownloadStart)\r
231                                                 self.freeDownloadTimer.start((int(seconds) + 2) * 1000, 1)
232                 elif self.url.__contains__("uploaded.to") or self.url.__contains__("ul.to"):
233                         writeLog("Free Uploaded.to-Download: %s"%self.url)\r
234                         self.status = _("Checking")\r
235                         if config.plugins.RSDownloader.reconnect_fritz.value:\r
236                                 reconnect()\r
237                                 sleep(3)\r
238                         data = get(self.url)
239                         tmp = re.search(r"Or wait (\d+) minutes", data)
240                         if tmp:
241                                 minutes = tmp.group(1)
242                                 writeLog("Free Uploaded.to-Download... must wait %s minutes: %s"%(minutes, self.url))
243                                 self.status = "%s %s"%(_("Waiting"), minutes)\r
244                                 self.freeDownloadTimer = eTimer()\r
245                                 self.freeDownloadTimer.callback.append(self.start)\r
246                                 self.freeDownloadTimer.start((int(minutes) + 1) * 60000, 1)
247                         else:
248                                 url = re.search(r".*<form name=\"download_form\" method=\"post\" action=\"(.*)\">", data).group(1)
249                                 self.name = re.search(r"<td><b>\s+(.+)\s", data).group(1) + re.search(r"</td><td>(\..+)</td></tr>", data).group(1)\r
250                                 self.status = _("Downloading")\r
251                                 self.download = ProgressDownload(url, ("%s/%s"%(config.plugins.RSDownloader.downloads_directory.value, self.name)).replace("//", "/"))\r
252                                 self.download.addProgress(self.httpProgress)\r
253                                 self.download.start().addCallback(self.httpFinished).addErrback(self.httpFailed)\r
254                 elif self.url.__contains__("youtube.com"):\r
255                         writeLog("Getting youtube video link: %s"%self.url)\r
256                         self.status = _("Checking")\r
257                         downloadLink = self.getYoutubeDownloadLink()\r
258                         if downloadLink:\r
259                                 self.status = _("Downloading")\r
260                                 writeLog("Downloading video: %s"%downloadLink)\r
261                                 req = urllib2.Request(downloadLink)\r
262                                 url_handle = urllib2.urlopen(req)\r
263                                 headers = url_handle.info()\r
264                                 if headers.getheader("content-type") == "video/mp4":\r
265                                         ext = "mp4"\r
266                                 else:\r
267                                         ext = "flv"\r
268                                 self.download = ProgressDownload(downloadLink, ("%s/%s.%s"%(config.plugins.RSDownloader.downloads_directory.value, self.name, ext)).replace("//", "/"))\r
269                                 self.download.addProgress(self.httpProgress)\r
270                                 self.download.start().addCallback(self.httpFinished).addErrback(self.httpFailed)\r
271                         else:\r
272                                 self.httpFailed(True, "Failed to get video url: %s"%self.url)\r
273                 else:\r
274                         if self.url.__contains__("rapidshare.com"):\r
275                                 url = self.url.replace("http://", "http://" + username + ":" + password + "@")\r
276                         else:\r
277                                 url = self.url\r
278                         self.status = _("Downloading")\r
279                         self.download = ProgressDownload(url, ("%s/%s"%(config.plugins.RSDownloader.downloads_directory.value, self.name)).replace("//", "/").replace(".html", ""))\r
280                         self.download.addProgress(self.httpProgress)\r
281                         self.download.start().addCallback(self.httpFinished).addErrback(self.httpFailed)\r
282 \r
283         def freeDownloadStart(self):\r
284                 self.status = _("Downloading")\r
285                 self.download = ProgressDownload(self.freeDownloadUrl, ("%s/%s"%(config.plugins.RSDownloader.downloads_directory.value, self.name)).replace("//", "/").replace(".html", ""))\r
286                 self.download.addProgress(self.httpProgress)\r
287                 self.download.start().addCallback(self.httpFinished).addErrback(self.httpFailed)\r
288 \r
289         def stop(self):\r
290                 self.progress = 0\r
291                 self.downloading = False\r
292                 self.status = _("Waiting")\r
293                 if self.download:\r
294                         writeLog("Stopping download: %s"%self.url)\r
295                         self.download.stop()\r
296 \r
297         def httpProgress(self, recvbytes, totalbytes):\r
298                 if self.size == 0:\r
299                         self.size = int((totalbytes / 1024) / 1024)\r
300                 self.progress = int(100.0 * float(recvbytes) / float(totalbytes))\r
301                 if self.progress == 100:\r
302                         writeLog("Finished: %s"%self.url)\r
303                         self.status = _("Finished")\r
304                         self.execFinishCallbacks()\r
305 \r
306         def httpFinished(self, string=""):\r
307                 if string is not None:\r
308                         writeLog("Failed: %s"%self.url)\r
309                         writeLog("Error: %s"%string)\r
310                 self.status = _("Checking")\r
311                 self.checkTimer = eTimer()\r
312                 self.checkTimer.callback.append(self.doCheckTimer)\r
313                 self.checkTimer.start(10000, 1)\r
314 \r
315         def doCheckTimer(self):\r
316                 if self.size == 0:\r
317                         self.status = _("Failed")\r
318                         if config.plugins.RSDownloader.autorestart_failed.value:\r
319                                 self.restartFailedTimer = eTimer()\r
320                                 self.restartFailedTimer.callback.append(self.restartFailedCheck)\r
321                                 self.restartFailedTimer.start(10000*60, 1)\r
322                 elif self.progress == 100:\r
323                         self.status = _("Finished")\r
324                 self.downloading = False\r
325                 self.execFinishCallbacks()\r
326 \r
327         def restartFailedCheck(self):\r
328                 if self.status == _("Failed"): # check if user didn't restart already\r
329                         self.download = None\r
330                         self.status = _("Waiting")\r
331 \r
332         def execFinishCallbacks(self):\r
333                 for x in self.finishCallbacks:\r
334                         x()\r
335 \r
336         def httpFailed(self, failure=None, error=""):\r
337                 if failure:\r
338                         if error == "":\r
339                                 error = failure.getErrorMessage()\r
340                         if error != "" and not error.startswith("[Errno 2]"):\r
341                                 writeLog("Failed: %s"%self.url)\r
342                                 writeLog("Error: %s"%error)\r
343                                 self.status = _("Checking")\r
344                 self.checkTimer = eTimer()\r
345                 self.checkTimer.callback.append(self.doCheckTimer)\r
346                 self.checkTimer.start(10000, 1)\r
347 \r
348         def getYoutubeDownloadLink(self):\r
349                 mrl = None\r
350                 html = get(self.url)\r
351                 if html != "":\r
352                         isHDAvailable = False\r
353                         video_id = None\r
354                         t = None\r
355                         reonecat = re.compile(r'<title>(.+?)</title>', re.DOTALL)\r
356                         titles = reonecat.findall(html)\r
357                         if titles:\r
358                                 self.name = titles[0]\r
359                                 if self.name.startswith("YouTube - "):\r
360                                         self.name = (self.name[10:]).replace("&amp;", "&")\r
361                         if html.__contains__("isHDAvailable = true"):\r
362                                 isHDAvailable = True\r
363                         for line in html.split('\n'):\r
364                                 if 'swfArgs' in line:\r
365                                         line = line.strip().split()\r
366                                         x = 0\r
367                                         for thing in line:\r
368                                                 if 'video_id' in thing:\r
369                                                         video_id = line[x+1][1:-2]\r
370                                                 elif '"t":' == thing:\r
371                                                         t = line[x+1][1:-2]\r
372                                                 x += 1\r
373                         if video_id and t:\r
374                                 if isHDAvailable == True:\r
375                                         mrl = "http://www.youtube.com/get_video?video_id=%s&t=%s&fmt=22" % (video_id, t)\r
376                                 else:\r
377                                         mrl = "http://www.youtube.com/get_video?video_id=%s&t=%s&fmt=18" % (video_id, t)\r
378                 return mrl\r
379 \r
380 ##############################################################################\r
381 \r
382 class RS:\r
383         def __init__(self):\r
384                 self.downloads = []\r
385                 self.checkTimer = eTimer()\r
386                 self.checkTimer.callback.append(self.startDownloading)\r
387                 self.checkTimer.start(5000*60, False)\r
388 \r
389         def mayDownload(self):\r
390                 if config.plugins.RSDownloader.onoff.value == False:\r
391                         writeLog("RS Downloader is turned off...")\r
392                         return False\r
393                 elif config.plugins.RSDownloader.ignore_time.value:\r
394                         return True\r
395                 else:\r
396                         start = config.plugins.RSDownloader.start_time.value\r
397                         end = config.plugins.RSDownloader.end_time.value\r
398                         t = localtime()\r
399                         weekday = t[6]\r
400                         if weekday == 0 and config.plugins.RSDownloader.download_monday.value == False:\r
401                                 return False\r
402                         elif weekday == 1 and config.plugins.RSDownloader.download_tuesday.value == False:\r
403                                 return False\r
404                         elif weekday == 2 and config.plugins.RSDownloader.download_wednesday.value == False:\r
405                                 return False\r
406                         elif weekday == 3 and config.plugins.RSDownloader.download_thursday.value == False:\r
407                                 return False\r
408                         elif weekday == 4 and config.plugins.RSDownloader.download_friday.value == False:\r
409                                 return False\r
410                         elif weekday == 5 and config.plugins.RSDownloader.download_saturday.value == False:\r
411                                 return False\r
412                         elif weekday == 6 and config.plugins.RSDownloader.download_sunday.value == False:\r
413                                 return False\r
414                         else:\r
415                                 hour_now = t[3]\r
416                                 minute_now = t[4]\r
417                                 hour_start = start[0]\r
418                                 minute_start = start[1]\r
419                                 hour_end = end[0]\r
420                                 minute_end = end[1]\r
421                                 if start == end: # Same start and end-time\r
422                                         return True\r
423                                 elif hour_end < hour_start: # Different days!!!\r
424                                         if hour_now > hour_start or hour_now < hour_end:\r
425                                                 return True\r
426                                         elif hour_now == hour_start and minute_now > minute_start:\r
427                                                 return True\r
428                                         elif hour_now == hour_end and minute_now < minute_end:\r
429                                                 return True\r
430                                         else:\r
431                                                 return False\r
432                                 elif hour_now > hour_start and hour_now < hour_end: # Same day...\r
433                                         return True\r
434                                 elif hour_now == hour_start and minute_now > minute_start: # Same day, same start-hour...\r
435                                         return True\r
436                                 elif hour_now == hour_end and minute_now < minute_end: # Same day, same end-hour...\r
437                                         return True\r
438                                 else:\r
439                                         return False\r
440 \r
441         def allDownloadsFinished(self):\r
442                 allDone = True\r
443                 for download in self.downloads:\r
444                         if (download.status != _("Failed")) and (download.status != _("Finished")):\r
445                                 allDone = False\r
446                 return allDone\r
447 \r
448         def startDownloading(self):\r
449                 if self.mayDownload() == True:\r
450                         if self.allDownloadsFinished() == True:\r
451                                 self.readLists()\r
452                         downloadCount = 0\r
453                         for download in self.downloads:\r
454                                 if download.downloading == True:\r
455                                         downloadCount += 1 # Count the downloaded files\r
456                         if config.plugins.RSDownloader.username.value == "" and config.plugins.RSDownloader.password.value == "":\r
457                                 if downloadCount < 1: # Allow one download if without account\r
458                                         for download in self.downloads:\r
459                                                 if download.downloading == False and download.status.startswith(_("Waiting")):\r
460                                                         download.start() # Start first download in the list\r
461                                                         break\r
462                         else:\r
463                                 mayDownloadCount = config.plugins.RSDownloader.count_downloads.value - downloadCount\r
464                                 for download in self.downloads:\r
465                                         if download.downloading == False:\r
466                                                 if mayDownloadCount > 0 and download.status == _("Waiting"):\r
467                                                         download.start()\r
468                                                         mayDownloadCount -= 1\r
469 \r
470         def addDownload(self, url):\r
471                 error = False\r
472                 for download in self.downloads:\r
473                         if download.url == url:\r
474                                 error = True\r
475                 if error:\r
476                         return False\r
477                 else:\r
478                         download = RSDownload(url)\r
479                         download.finishCallbacks.append(self.cleanLists)\r
480                         self.downloads.append(download)\r
481                         return True\r
482 \r
483         def readLists(self):\r
484                 writeLog("Reading all lists...")\r
485                 path = config.plugins.RSDownloader.lists_directory.value\r
486                 if not path.endswith("/"):\r
487                         path = path + "/"\r
488                 writeLog("Directory: " + path)\r
489                 try:\r
490                         file_list = listdir(path)\r
491                         writeLog("Count of lists: " + str(len(file_list)))\r
492                 except:\r
493                         file_list = []\r
494                         writeLog("Could not find any list!")\r
495                 for x in file_list:\r
496                         list = path + x\r
497                         if list.endswith(".txt"):\r
498                                 try:\r
499                                         writeLog("Reading list %s..."%list)\r
500                                         f = open(list, "r")\r
501                                         count = 0\r
502                                         for l in f:\r
503                                                 if l.startswith("http://"):\r
504                                                         if (self.addDownload(l.replace("\n", "").replace("\r", ""))) == True:\r
505                                                                 count += 1\r
506                                         f.close()\r
507                                         if count == 0:\r
508                                                 writeLog("Empty list or downloads already in download list: %s"%list)\r
509                                         else:\r
510                                                 writeLog("Added %d files from list %s..."%(count, list))\r
511                                 except:\r
512                                         writeLog("Error while reading list %s!"%list)\r
513                         else:\r
514                                 writeLog("No *.txt file: %s!"%list)\r
515 \r
516         def cleanLists(self):\r
517                 writeLog("Cleaning lists...")\r
518                 path = config.plugins.RSDownloader.lists_directory.value\r
519                 if not path.endswith("/"):\r
520                         path = path + "/"\r
521                 try:\r
522                         file_list = listdir(path)\r
523                 except:\r
524                         file_list = []
525                 
526                 finished_downloads = []
527                 for download in self.downloads:\r
528                         if download.status == _("Finished"):
529                                 finished_downloads.append(download)\r
530                 for x in file_list:\r
531                         list = path + x
532                         if list.endswith(".txt"):\r
533                                 try:\r
534                                         f = open(list, "r")\r
535                                         content = f.read()\r
536                                         f.close()
537                                         for finished in finished_downloads:\r
538                                                 if content.__contains__(finished.url):\r
539                                                         content = content.replace(finished.url, "")\r
540                                                         content = content.replace("\n\n", "\n").replace("\r\r", "\r")\r
541                                         f = open(list, "w")\r
542                                         f.write(content)\r
543                                         f.close()\r
544                                 except:\r
545                                         writeLog("Error while cleaning list %s!"%list)\r
546                 self.startDownloading()\r
547 \r
548         def removeDownload(self, url):\r
549                 tmp = []\r
550                 for download in self.downloads:\r
551                         if download.url == url:\r
552                                 download.stop()\r
553                         else:\r
554                                 tmp.append(download)\r
555                 del self.downloads\r
556                 self.downloads = tmp\r
557                 self.removeFromLists(url)\r
558 \r
559         def removeFromLists(self, url):\r
560                 path = config.plugins.RSDownloader.lists_directory.value\r
561                 if not path.endswith("/"):\r
562                         path = path + "/"\r
563                 try:\r
564                         file_list = listdir(path)\r
565                 except:\r
566                         file_list = []\r
567                 for x in file_list:\r
568                         list = path + x\r
569                         try:\r
570                                 f = open(list, "r")\r
571                                 content = f.read()\r
572                                 f.close()\r
573                                 if content.__contains__(url):\r
574                                         content = content.replace(url, "")\r
575                                         content = content.replace("\n\n", "\n").replace("\r\r", "\r")\r
576                                 f = open(list, "w")\r
577                                 f.write(content)\r
578                                 f.close()\r
579                         except:\r
580                                 pass\r
581 \r
582         def clearFinishedDownload(self, url):\r
583                 idx = 0\r
584                 for x in self.downloads:\r
585                         if x.url == url:\r
586                                 del self.downloads[idx]\r
587                                 break\r
588                         else:\r
589                                 idx += 1\r
590 \r
591         def clearFinishedDownloads(self):\r
592                 tmp = []\r
593                 for download in self.downloads:\r
594                         if download.status != _("Finished"):\r
595                                 tmp.append(download)\r
596                 del self.downloads\r
597                 self.downloads = tmp\r
598 \r
599         def deleteFailedDownloads(self):\r
600                 tmp = []\r
601                 for download in self.downloads:\r
602                         if download.status == _("Failed"):\r
603                                 self.removeFromLists(download.url)\r
604                         else:\r
605                                 tmp.append(download)\r
606                 del self.downloads\r
607                 self.downloads = tmp\r
608 \r
609         def restartFailedDownloads(self):\r
610                 tmp = []\r
611                 for download in self.downloads:\r
612                         if download.status == _("Failed"):\r
613                                 download.download = None\r
614                                 download.downloading = False\r
615                                 download.progress = 0\r
616                                 download.size = 0\r
617                                 download.status = _("Waiting")\r
618                         tmp.append(download)\r
619                 del self.downloads\r
620                 self.downloads = tmp\r
621                 self.startDownloading()\r
622 \r
623 rapidshare = RS()\r
624 \r
625 ##############################################################################\r
626 \r
627 class ChangedScreen(Screen):\r
628         def __init__(self, session, parent=None):\r
629                 Screen.__init__(self, session, parent)\r
630                 self.onLayoutFinish.append(self.setScreenTitle)\r
631 \r
632         def setScreenTitle(self):\r
633                 self.setTitle(_("RS Downloader"))\r
634 \r
635 ##############################################################################\r
636 \r
637 class RSConfig(ConfigListScreen, ChangedScreen):\r
638         skin = """\r
639                 <screen position="center,center" size="560,450" title="RS Downloader">\r
640                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />\r
641                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />\r
642                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />\r
643                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />\r
644                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
645                         <widget name="config" position="0,45" size="560,400" scrollbarMode="showOnDemand" />\r
646                 </screen>"""\r
647 \r
648         def __init__(self, session):\r
649                 ChangedScreen.__init__(self, session)\r
650                 \r
651                 self["key_green"] = Label(_("Save"))\r
652                 \r
653                 ConfigListScreen.__init__(self, [\r
654                         getConfigListEntry(_("Download in the background:"), config.plugins.RSDownloader.onoff),\r
655                         getConfigListEntry(_("Username:"), config.plugins.RSDownloader.username),\r
656                         getConfigListEntry(_("Password:"), config.plugins.RSDownloader.password),\r
657                         getConfigListEntry(_("Lists directory:"), config.plugins.RSDownloader.lists_directory),\r
658                         getConfigListEntry(_("Downloads directory:"), config.plugins.RSDownloader.downloads_directory),\r
659                         getConfigListEntry(_("Ignore download times:"), config.plugins.RSDownloader.ignore_time),\r
660                         getConfigListEntry(_("Allow downloading on monday:"), config.plugins.RSDownloader.download_monday),\r
661                         getConfigListEntry(_("Allow downloading on tuesday:"), config.plugins.RSDownloader.download_tuesday),\r
662                         getConfigListEntry(_("Allow downloading on wednesday:"), config.plugins.RSDownloader.download_wednesday),\r
663                         getConfigListEntry(_("Allow downloading on thursday:"), config.plugins.RSDownloader.download_thursday),\r
664                         getConfigListEntry(_("Allow downloading on friday:"), config.plugins.RSDownloader.download_friday),\r
665                         getConfigListEntry(_("Allow downloading on saturday:"), config.plugins.RSDownloader.download_saturday),\r
666                         getConfigListEntry(_("Allow downloading on sunday:"), config.plugins.RSDownloader.download_sunday),\r
667                         getConfigListEntry(_("Don't download before:"), config.plugins.RSDownloader.start_time),\r
668                         getConfigListEntry(_("Don't download after:"), config.plugins.RSDownloader.end_time),\r
669                         getConfigListEntry(_("Maximal downloads:"), config.plugins.RSDownloader.count_downloads),\r
670                         getConfigListEntry(_("Write log:"), config.plugins.RSDownloader.write_log),\r
671                         getConfigListEntry(_("Reconnect fritz.Box before downloading:"), config.plugins.RSDownloader.reconnect_fritz),\r
672                         getConfigListEntry(_("Restart failed after 10 minutes:"), config.plugins.RSDownloader.autorestart_failed)])\r
673                 \r
674                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"], {"green": self.save, "cancel": self.exit}, -1)\r
675 \r
676         def save(self):\r
677                 for x in self["config"].list:\r
678                         x[1].save()\r
679                 self.close()\r
680 \r
681         def exit(self):\r
682                 for x in self["config"].list:\r
683                         x[1].cancel()\r
684                 self.close()\r
685 \r
686 ##############################################################################\r
687 \r
688 class RSSearch(Screen):\r
689         skin = """\r
690                 <screen position="center,center" size="560,450" title="Searching... please wait!">\r
691                         <widget name="list" position="0,0" size="570,450" scrollbarMode="showOnDemand" />\r
692                 </screen>"""\r
693 \r
694         def __init__(self, session, searchFor):\r
695                 Screen.__init__(self, session)\r
696                 self.session = session\r
697                 \r
698                 self.searchFor = searchFor.replace(" ", "%2B")\r
699                 self.maxPage = 1\r
700                 self.curPage = 1\r
701                 self.files = []\r
702                 \r
703                 self["list"] = MenuList([])\r
704                 \r
705                 self["actions"] = ActionMap(["OkCancelActions", "InfobarChannelSelection"],\r
706                         {\r
707                                 "historyBack": self.previousPage,\r
708                                 "historyNext": self.nextPage,\r
709                                 "ok": self.okClicked,\r
710                                 "cancel": self.close\r
711                         }, -1)\r
712                 \r
713                 self.onLayoutFinish.append(self.search)\r
714 \r
715         def okClicked(self):\r
716                 if len(self.files) > 0:\r
717                         idx = self["list"].getSelectedIndex()\r
718                         url = self.files[idx]\r
719                         try:\r
720                                 f = open(("%s/search.txt" % config.plugins.RSDownloader.lists_directory.value).replace("//", "/"), "a")\r
721                                 f.write("%s\n"%url)\r
722                                 f.close()\r
723                                 self.session.open(MessageBox, (_("Added %s to the download-list.") % url), MessageBox.TYPE_INFO)\r
724                         except:\r
725                                 self.session.open(MessageBox, (_("Error while adding %s to the download-list!") % url), MessageBox.TYPE_ERROR)\r
726 \r
727         def search(self):\r
728                 getPage("http://rapidshare-search-engine.com/index-s_submit=Search&sformval=1&s_type=0&what=1&s=%s&start=%d.html"%(self.searchFor, self.curPage)).addCallback(self.searchCallback).addErrback(self.searchError)\r
729 \r
730         def searchCallback(self, html=""):\r
731                 list = []\r
732                 files = []\r
733                 \r
734                 if html.__contains__("Nothing found, sorry."):\r
735                         self.session.open(MessageBox, (_("Error while searching http://rapidshare-search-engine.com!\n\nError: Nothing found, sorry.")), MessageBox.TYPE_ERROR)\r
736                         self.instance.setTitle(_("Nothing found, sorry."))\r
737                 else:\r
738                         tmp = html\r
739                         while tmp.__contains__("goPg('"):\r
740                                 idx = tmp.index("goPg('")\r
741                                 tmp = tmp[idx+6:]\r
742                                 idx = tmp.index("'")\r
743                                 pageNumber = tmp[:idx]\r
744                                 \r
745                                 try:\r
746                                         pageNumber = int(pageNumber)\r
747                                         if pageNumber > self.maxPage:\r
748                                                 self.maxPage = pageNumber\r
749                                 except:\r
750                                         pass\r
751                                 \r
752                                 self.instance.setTitle(_("Page %d / %d. Push < > to switch the page...")%(self.curPage, self.maxPage))\r
753                         \r
754                         while html.__contains__('title="Download"'):\r
755                                 idx = html.index('title="Download"')\r
756                                 html = html[idx:]\r
757                                 idx = html.index('value="')\r
758                                 html = html[idx+7:]\r
759                                 idx = html.index('"')\r
760                                 size = html[:idx]\r
761                                 idx = html.index('http://rapidshare.com/')\r
762                                 html = html[idx:]\r
763                                 idx = html.index('"')\r
764                                 url = html[:idx]\r
765                                 \r
766                                 files.append(url) \r
767                                 try:\r
768                                         urllist = url.split("/")\r
769                                         idx = len(urllist) - 1\r
770                                         name = urllist[idx]\r
771                                         list.append("%s - %s"%(size, name))\r
772                                 except:\r
773                                         list.append("%s - %s"%(size, url))\r
774                 \r
775                 self.files = files\r
776                 self["list"].setList(list)\r
777 \r
778         def searchError(self, error=""):\r
779                 self.session.open(MessageBox, (_("Error while searching http://rapidshare-search-engine.com!\n\nError: %s")%str(error)), MessageBox.TYPE_ERROR)\r
780 \r
781         def previousPage(self):\r
782                 if self.curPage > 1:\r
783                         self.curPage -= 1\r
784                         self.instance.setTitle(_("Loading previous page... please wait!"))\r
785                         self.search()\r
786 \r
787         def nextPage(self):\r
788                 if self.curPage < self.maxPage:\r
789                         self.curPage += 1\r
790                         self.instance.setTitle(_("Loading next page... please wait!"))\r
791                         self.search()\r
792 \r
793 ##############################################################################\r
794 \r
795 class RSLogScreen(ChangedScreen):\r
796         skin = """\r
797                 <screen position="center,center" size="560,450" title="RS Downloader">\r
798                         <widget name="label" position="0,0" size="560,450" font="Regular;20" />\r
799                 </screen>"""\r
800 \r
801         def __init__(self, session):\r
802                 ChangedScreen.__init__(self, session)\r
803                 \r
804                 try:\r
805                         f = open("/tmp/rapidshare.log")\r
806                         log = f.read()\r
807                         f.close()\r
808                 except:\r
809                         log = ""\r
810                 self["label"] = ScrollLabel(log)\r
811                 \r
812                 self["actions"] = ActionMap(["WizardActions"],\r
813                         {\r
814                                 "ok": self.close,\r
815                                 "back": self.close,\r
816                                 "up": self["label"].pageUp,\r
817                                 "down": self["label"].pageDown,\r
818                                 "left": self["label"].pageUp,\r
819                                 "right": self["label"].pageDown\r
820                         }, -1)\r
821 \r
822 ##############################################################################\r
823 \r
824 class RSContainerSelector(ChangedScreen):\r
825         skin = """\r
826                 <screen position="center,center" size="560,450" title="RS Downloader">\r
827                         <widget name="list" position="0,0" size="560,450" />\r
828                 </screen>"""\r
829 \r
830         def __init__(self, session, list):\r
831                 ChangedScreen.__init__(self, session)\r
832                 self["list"] = MenuList(list)\r
833                 self["actions"] = ActionMap(["OkCancelActions"], {"ok": self.okClicked, "cancel": self.close}, -1)\r
834 \r
835         def okClicked(self):\r
836                 cur = self["list"].getCurrent()\r
837                 self.close(cur)\r
838 \r
839 ##############################################################################\r
840 \r
841 class RSList(MenuList):\r
842         def __init__(self, list):\r
843                 MenuList.__init__(self, list, False, eListboxPythonMultiContent)\r
844                 self.l.setItemHeight(25)\r
845                 self.l.setFont(0, gFont("Regular", 20))\r
846 \r
847 ##############################################################################\r
848 \r
849 def RSListEntry(download):\r
850         res = [(download)]\r
851         res.append(MultiContentEntryText(pos=(0, 0), size=(170, 25), font=0, text=download.name))\r
852         res.append(MultiContentEntryText(pos=(175, 0), size=(75, 25), font=0, text="%d%s"%(download.size, "MB"), flags=RT_HALIGN_CENTER))\r
853         res.append(MultiContentEntryPixmapAlphaTest(pos=(260, 9), size=(84, 7), png=LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/progress_bg.png"))))\r
854         res.append(MultiContentEntryPixmapAlphaTest(pos=(260, 10), size=(int(0.84 * download.progress), 5), png=LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/progress_small.png"))))\r
855         res.append(MultiContentEntryText(pos=(360, 0), size=(60, 25), font=0, text="%d%s"%(download.progress, "%"), flags=RT_HALIGN_CENTER))\r
856         res.append(MultiContentEntryText(pos=(420, 0), size=(140, 25), font=0, text=download.status, flags=RT_HALIGN_RIGHT))\r
857         return res\r
858 \r
859 ##############################################################################\r
860 \r
861 class RSMain(ChangedScreen):\r
862         skin = """\r
863                 <screen position="center,center" size="560,450" title="RS Downloader">\r
864                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />\r
865                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />\r
866                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />\r
867                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />\r
868                         <ePixmap pixmap="skin_default/buttons/key_menu.png" position="10,420" size="35,25" transparent="1" alphatest="on" />\r
869                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
870                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
871                         <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
872                         <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
873                         <widget name="key_menu" position="50,422" size="300,25" font="Regular;20" transparent="1" />\r
874                         <widget name="list" position="0,40" size="560,375" scrollbarMode="showNever" />\r
875                 </screen>"""\r
876 \r
877         def __init__(self, session):\r
878                 ChangedScreen.__init__(self, session)\r
879                 self.session = session\r
880                 \r
881                 self["key_red"] = Label(_("Delete"))\r
882                 self["key_green"] = Label(_("Search"))\r
883                 self["key_yellow"] = Label(_("Add"))\r
884                 self["key_blue"] = Label(_("Config"))\r
885                 self["key_menu"] = Label(_("Menu"))\r
886                 self["list"] = RSList([])\r
887                 \r
888                 self.refreshTimer = eTimer()\r
889                 self.refreshTimer.callback.append(self.updateList)\r
890                 \r
891                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "InfobarMenuActions"],\r
892                         {\r
893                                 "mainMenu": self.menu,\r
894                                 "cancel": self.close,\r
895                                 "red": self.delete,\r
896                                 "green": self.search,\r
897                                 "yellow": self.add,\r
898                                 "blue": self.config\r
899                         }, prio=-1)\r
900                 \r
901                 self.onLayoutFinish.append(self.updateList)\r
902 \r
903         def menu(self):\r
904                 list = []\r
905                 #TODO: Add sort list functions\r
906                 list.append((_("Delete download"), self.delete))\r
907                 list.append((_("Use search engine"), self.search))\r
908                 list.append((_("Add downloads from txt files"), self.add))\r
909                 list.append((_("Add files from container"), self.addContainer))\r
910                 list.append((_("Delete failed downloads"), self.deleteFailed))\r
911                 list.append((_("Restart failed downloads"), self.restartFailed))\r
912                 list.append((_("Clear finished downloads"), self.clearFinished))\r
913                 list.append((_("Show log"), self.showLog))\r
914                 list.append((_("Delete log"), self.deleteLog))\r
915                 list.append((_("Close plugin"), self.close))\r
916                 self.session.openWithCallback(self.menuCallback, ChoiceBox, title=_("Please choose a function..."), list=list)\r
917 \r
918         def menuCallback(self, callback=None):\r
919                 if callback is not None:\r
920                         callback[1]()\r
921 \r
922         def deleteFailed(self):\r
923                 rapidshare.deleteFailedDownloads()\r
924 \r
925         def restartFailed(self):\r
926                 rapidshare.restartFailedDownloads()\r
927 \r
928         def clearFinished(self):\r
929                 rapidshare.clearFinishedDownloads()\r
930 \r
931         def showLog(self):\r
932                 self.session.open(RSLogScreen)\r
933 \r
934         def deleteLog(self):\r
935                 try:\r
936                         remove("/tmp/rapidshare.log")\r
937                 except:\r
938                         pass\r
939 \r
940         def updateList(self):\r
941                 list = []\r
942                 for download in rapidshare.downloads:\r
943                         list.append(RSListEntry(download))\r
944                 self["list"].setList(list)\r
945                 self.refreshTimer.start(2000, 1)\r
946 \r
947         def delete(self):\r
948                 cur = self["list"].getCurrent()\r
949                 if cur:\r
950                         cur = cur[0]\r
951                         if cur.status == _("Finished"):\r
952                                 rapidshare.clearFinishedDownload(cur.url)\r
953                         else:\r
954                                 self.session.openWithCallback(self.deleteCallback, MessageBox, (_("Delete %s?")%cur.name))\r
955 \r
956         def deleteCallback(self, callback):\r
957                 if callback:\r
958                         rapidshare.removeDownload(self["list"].getCurrent()[0].url)\r
959                         self.refreshTimer.stop()\r
960                         self.updateList()\r
961 \r
962         def search(self):\r
963                 self.session.openWithCallback(self.searchCallback, VirtualKeyBoard, title=_("Search http://rapidshare-search-engine.com for:"))\r
964 \r
965         def searchCallback(self, callback):\r
966                 if callback is not None and callback != "":\r
967                         self.session.openWithCallback(self.searchScreenCallback, RSSearch, callback)\r
968 \r
969 \r
970         def searchScreenCallback(self):\r
971                 self.refreshTimer.stop()\r
972                 rapidshare.startDownloading()\r
973                 self.updateList()\r
974 \r
975         def add(self):\r
976                 self.refreshTimer.stop()\r
977                 rapidshare.startDownloading()\r
978                 self.updateList()\r
979 \r
980         def config(self):\r
981                 self.session.openWithCallback(self.configCallback, RSConfig)\r
982 \r
983         def configCallback(self):\r
984                 if config.plugins.RSDownloader.onoff.value:\r
985                         rapidshare.startDownloading()\r
986                 else:\r
987                         for download in rapidshare.downloads:\r
988                                 if download.downloading:\r
989                                         download.stop()\r
990                 self.updateList()\r
991 \r
992         def addContainer(self):\r
993                 try:\r
994                         file_list = listdir(config.plugins.RSDownloader.lists_directory.value)\r
995                 except:\r
996                         file_list = []\r
997                 list = []\r
998                 for file in file_list:\r
999                         if file.lower().endswith(".ccf") or file.lower().endswith(".dlc") or file.lower().endswith(".rsdf"):\r
1000                                 list.append(file)\r
1001                 list.sort()\r
1002                 self.session.openWithCallback(self.addContainerCallback, RSContainerSelector, list)\r
1003 \r
1004         def addContainerCallback(self, callback=None):\r
1005                 if callback:\r
1006                         file = "%s/%s"%(config.plugins.RSDownloader.lists_directory.value, callback)\r
1007                         file = file.replace("//", "/")\r
1008                         links = decrypt(file)\r
1009                         try:\r
1010                                 f = open(("%s/%s.txt" % (config.plugins.RSDownloader.lists_directory.value, callback)).replace("//", "/"), "w")\r
1011                                 for link in links:\r
1012                                         if link.endswith(".html"):\r
1013                                                 link = link[:-5]\r
1014                                         elif link.endswith(".htm"):\r
1015                                                 link = link[:-4]\r
1016                                         f.write("%s\n"%link)\r
1017                                 f.close()\r
1018                         except:\r
1019                                 pass\r
1020                         self.refreshTimer.stop()\r
1021                         rapidshare.startDownloading()\r
1022                         self.updateList()\r
1023 \r
1024 ##############################################################################\r
1025 \r
1026 def autostart(reason, **kwargs):\r
1027         if reason == 0:\r
1028                 rapidshare.startDownloading()\r
1029 \r
1030 ##############################################################################\r
1031 \r
1032 def main(session, **kwargs):\r
1033         session.open(RSMain)\r
1034 \r
1035 ##############################################################################\r
1036 \r
1037 def Plugins(**kwargs):\r
1038         return [\r
1039                 PluginDescriptor(where=PluginDescriptor.WHERE_AUTOSTART, fnc=autostart),\r
1040                 PluginDescriptor(name=_("RS Downloader"), description=_("Download files from rapidshare"), where=[PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU], icon="rs.png", fnc=main)]\r
1041 \r