clean lists only once
[enigma2-plugins.git] / 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 \r
302         def httpFinished(self, string=None):\r
303                 if string is not None:\r
304                         writeLog("Failed: %s"%self.url)\r
305                         writeLog("Error: %s"%string)\r
306                 self.status = _("Checking")\r
307                 self.checkTimer = eTimer()\r
308                 self.checkTimer.callback.append(self.doCheckTimer)\r
309                 self.checkTimer.start(10000, 1)\r
310 \r
311         def doCheckTimer(self):\r
312                 if (self.size == 0) or (self.progress < 100):\r
313                         self.status = _("Failed")\r
314                         if config.plugins.RSDownloader.autorestart_failed.value:\r
315                                 self.restartFailedTimer = eTimer()\r
316                                 self.restartFailedTimer.callback.append(self.restartFailedCheck)\r
317                                 self.restartFailedTimer.start(10000*60, 1)\r
318                 elif self.progress == 100:\r
319                         self.status = _("Finished")
320                         writeLog("Finished: %s"%self.url)\r
321                 self.downloading = False\r
322                 self.execFinishCallbacks()\r
323 \r
324         def restartFailedCheck(self):\r
325                 if self.status == _("Failed"): # check if user didn't restart already\r
326                         self.download = None\r
327                         self.status = _("Waiting")\r
328 \r
329         def execFinishCallbacks(self):\r
330                 for x in self.finishCallbacks:\r
331                         x()\r
332 \r
333         def httpFailed(self, failure=None, error=""):\r
334                 if failure:\r
335                         if error == "":\r
336                                 error = failure.getErrorMessage()\r
337                         if error != "" and not error.startswith("[Errno 2]"):\r
338                                 writeLog("Failed: %s"%self.url)\r
339                                 writeLog("Error: %s"%error)\r
340                                 self.status = _("Checking")\r
341                 self.checkTimer = eTimer()\r
342                 self.checkTimer.callback.append(self.doCheckTimer)\r
343                 self.checkTimer.start(10000, 1)\r
344 \r
345         def getYoutubeDownloadLink(self):\r
346                 mrl = None\r
347                 html = get(self.url)\r
348                 if html != "":\r
349                         isHDAvailable = False\r
350                         video_id = None\r
351                         t = None\r
352                         reonecat = re.compile(r'<title>(.+?)</title>', re.DOTALL)\r
353                         titles = reonecat.findall(html)\r
354                         if titles:\r
355                                 self.name = titles[0]\r
356                                 if self.name.startswith("YouTube - "):\r
357                                         self.name = (self.name[10:]).replace("&amp;", "&")\r
358                         if html.__contains__("isHDAvailable = true"):\r
359                                 isHDAvailable = True\r
360                         for line in html.split('\n'):\r
361                                 if 'swfArgs' in line:\r
362                                         line = line.strip().split()\r
363                                         x = 0\r
364                                         for thing in line:\r
365                                                 if 'video_id' in thing:\r
366                                                         video_id = line[x+1][1:-2]\r
367                                                 elif '"t":' == thing:\r
368                                                         t = line[x+1][1:-2]\r
369                                                 x += 1\r
370                         if video_id and t:\r
371                                 if isHDAvailable == True:\r
372                                         mrl = "http://www.youtube.com/get_video?video_id=%s&t=%s&fmt=22" % (video_id, t)\r
373                                 else:\r
374                                         mrl = "http://www.youtube.com/get_video?video_id=%s&t=%s&fmt=18" % (video_id, t)\r
375                 return mrl\r
376 \r
377 ##############################################################################\r
378 \r
379 class RS:\r
380         def __init__(self):\r
381                 self.downloads = []\r
382                 self.checkTimer = eTimer()\r
383                 self.checkTimer.callback.append(self.startDownloading)\r
384                 self.checkTimer.start(5000*60, False)\r
385 \r
386         def mayDownload(self):\r
387                 if config.plugins.RSDownloader.onoff.value == False:\r
388                         writeLog("RS Downloader is turned off...")\r
389                         return False\r
390                 elif config.plugins.RSDownloader.ignore_time.value:\r
391                         return True\r
392                 else:\r
393                         start = config.plugins.RSDownloader.start_time.value\r
394                         end = config.plugins.RSDownloader.end_time.value\r
395                         t = localtime()\r
396                         weekday = t[6]\r
397                         if weekday == 0 and config.plugins.RSDownloader.download_monday.value == False:\r
398                                 return False\r
399                         elif weekday == 1 and config.plugins.RSDownloader.download_tuesday.value == False:\r
400                                 return False\r
401                         elif weekday == 2 and config.plugins.RSDownloader.download_wednesday.value == False:\r
402                                 return False\r
403                         elif weekday == 3 and config.plugins.RSDownloader.download_thursday.value == False:\r
404                                 return False\r
405                         elif weekday == 4 and config.plugins.RSDownloader.download_friday.value == False:\r
406                                 return False\r
407                         elif weekday == 5 and config.plugins.RSDownloader.download_saturday.value == False:\r
408                                 return False\r
409                         elif weekday == 6 and config.plugins.RSDownloader.download_sunday.value == False:\r
410                                 return False\r
411                         else:\r
412                                 hour_now = t[3]\r
413                                 minute_now = t[4]\r
414                                 hour_start = start[0]\r
415                                 minute_start = start[1]\r
416                                 hour_end = end[0]\r
417                                 minute_end = end[1]\r
418                                 if start == end: # Same start and end-time\r
419                                         return True\r
420                                 elif hour_end < hour_start: # Different days!!!\r
421                                         if hour_now > hour_start or hour_now < hour_end:\r
422                                                 return True\r
423                                         elif hour_now == hour_start and minute_now > minute_start:\r
424                                                 return True\r
425                                         elif hour_now == hour_end and minute_now < minute_end:\r
426                                                 return True\r
427                                         else:\r
428                                                 return False\r
429                                 elif hour_now > hour_start and hour_now < hour_end: # Same day...\r
430                                         return True\r
431                                 elif hour_now == hour_start and minute_now > minute_start: # Same day, same start-hour...\r
432                                         return True\r
433                                 elif hour_now == hour_end and minute_now < minute_end: # Same day, same end-hour...\r
434                                         return True\r
435                                 else:\r
436                                         return False\r
437 \r
438         def allDownloadsFinished(self):\r
439                 allDone = True\r
440                 for download in self.downloads:\r
441                         if (download.status != _("Failed")) and (download.status != _("Finished")):\r
442                                 allDone = False\r
443                 return allDone\r
444 \r
445         def startDownloading(self):\r
446                 if self.mayDownload() == True:\r
447                         if self.allDownloadsFinished() == True:\r
448                                 self.readLists()\r
449                         downloadCount = 0\r
450                         for download in self.downloads:\r
451                                 if download.downloading == True:\r
452                                         downloadCount += 1 # Count the downloaded files\r
453                         if config.plugins.RSDownloader.username.value == "" and config.plugins.RSDownloader.password.value == "":\r
454                                 if downloadCount < 1: # Allow one download if without account\r
455                                         for download in self.downloads:\r
456                                                 if download.downloading == False and download.status.startswith(_("Waiting")):\r
457                                                         download.start() # Start first download in the list\r
458                                                         break\r
459                         else:\r
460                                 mayDownloadCount = config.plugins.RSDownloader.count_downloads.value - downloadCount\r
461                                 for download in self.downloads:\r
462                                         if download.downloading == False:\r
463                                                 if mayDownloadCount > 0 and download.status == _("Waiting"):\r
464                                                         download.start()\r
465                                                         mayDownloadCount -= 1\r
466 \r
467         def addDownload(self, url):\r
468                 error = False\r
469                 for download in self.downloads:\r
470                         if download.url == url:\r
471                                 error = True\r
472                 if error:\r
473                         return False\r
474                 else:\r
475                         download = RSDownload(url)\r
476                         download.finishCallbacks.append(self.cleanLists)\r
477                         self.downloads.append(download)\r
478                         return True\r
479 \r
480         def readLists(self):\r
481                 writeLog("Reading all lists...")\r
482                 path = config.plugins.RSDownloader.lists_directory.value\r
483                 if not path.endswith("/"):\r
484                         path = path + "/"\r
485                 writeLog("Directory: " + path)\r
486                 try:\r
487                         file_list = listdir(path)
488                         file_list.sort()\r
489                         writeLog("Count of lists: " + str(len(file_list)))\r
490                 except:\r
491                         file_list = []\r
492                         writeLog("Could not find any list!")\r
493                 for x in file_list:\r
494                         list = path + x\r
495                         if list.endswith(".txt"):\r
496                                 try:\r
497                                         writeLog("Reading list %s..."%list)\r
498                                         f = open(list, "r")\r
499                                         count = 0\r
500                                         for l in f:\r
501                                                 if l.startswith("http://"):\r
502                                                         if (self.addDownload(l.replace("\n", "").replace("\r", ""))) == True:\r
503                                                                 count += 1\r
504                                         f.close()\r
505                                         if count == 0:\r
506                                                 writeLog("Empty list or downloads already in download list: %s"%list)\r
507                                         else:\r
508                                                 writeLog("Added %d files from list %s..."%(count, list))\r
509                                 except:\r
510                                         writeLog("Error while reading list %s!"%list)\r
511                         else:\r
512                                 writeLog("No *.txt file: %s!"%list)\r
513 \r
514         def cleanLists(self):\r
515                 writeLog("Cleaning lists...")\r
516                 path = config.plugins.RSDownloader.lists_directory.value\r
517                 if not path.endswith("/"):\r
518                         path = path + "/"\r
519                 try:\r
520                         file_list = listdir(path)\r
521                 except:\r
522                         file_list = []
523                 
524                 finished_downloads = []
525                 for download in self.downloads:\r
526                         if download.status == _("Finished"):
527                                 finished_downloads.append(download)\r
528                 for x in file_list:\r
529                         list = path + x
530                         if list.endswith(".txt"):\r
531                                 try:\r
532                                         f = open(list, "r")\r
533                                         content = f.read()\r
534                                         f.close()
535                                         for finished in finished_downloads:\r
536                                                 if content.__contains__(finished.url):\r
537                                                         content = content.replace(finished.url, "")\r
538                                                         content = content.replace("\n\n", "\n").replace("\r\r", "\r")\r
539                                         f = open(list, "w")\r
540                                         f.write(content)\r
541                                         f.close()\r
542                                 except:\r
543                                         writeLog("Error while cleaning list %s!"%list)\r
544                 self.startDownloading()\r
545 \r
546         def removeDownload(self, url):\r
547                 tmp = []\r
548                 for download in self.downloads:\r
549                         if download.url == url:\r
550                                 download.stop()\r
551                         else:\r
552                                 tmp.append(download)\r
553                 del self.downloads\r
554                 self.downloads = tmp\r
555                 self.removeFromLists(url)\r
556 \r
557         def removeFromLists(self, url):\r
558                 path = config.plugins.RSDownloader.lists_directory.value\r
559                 if not path.endswith("/"):\r
560                         path = path + "/"\r
561                 try:\r
562                         file_list = listdir(path)\r
563                 except:\r
564                         file_list = []\r
565                 for x in file_list:\r
566                         list = path + x\r
567                         try:\r
568                                 f = open(list, "r")\r
569                                 content = f.read()\r
570                                 f.close()\r
571                                 if content.__contains__(url):\r
572                                         content = content.replace(url, "")\r
573                                         content = content.replace("\n\n", "\n").replace("\r\r", "\r")\r
574                                 f = open(list, "w")\r
575                                 f.write(content)\r
576                                 f.close()\r
577                         except:\r
578                                 pass\r
579 \r
580         def clearFinishedDownload(self, url):\r
581                 idx = 0\r
582                 for x in self.downloads:\r
583                         if x.url == url:\r
584                                 del self.downloads[idx]\r
585                                 break\r
586                         else:\r
587                                 idx += 1\r
588 \r
589         def clearFinishedDownloads(self):\r
590                 tmp = []\r
591                 for download in self.downloads:\r
592                         if download.status != _("Finished"):\r
593                                 tmp.append(download)\r
594                 del self.downloads\r
595                 self.downloads = tmp\r
596 \r
597         def deleteFailedDownloads(self):\r
598                 tmp = []\r
599                 for download in self.downloads:\r
600                         if download.status == _("Failed"):\r
601                                 self.removeFromLists(download.url)\r
602                         else:\r
603                                 tmp.append(download)\r
604                 del self.downloads\r
605                 self.downloads = tmp\r
606 \r
607         def restartFailedDownloads(self):\r
608                 tmp = []\r
609                 for download in self.downloads:\r
610                         if download.status == _("Failed"):\r
611                                 download.download = None\r
612                                 download.downloading = False\r
613                                 download.progress = 0\r
614                                 download.size = 0\r
615                                 download.status = _("Waiting")\r
616                         tmp.append(download)\r
617                 del self.downloads\r
618                 self.downloads = tmp\r
619                 self.startDownloading()\r
620 \r
621 rapidshare = RS()\r
622 \r
623 ##############################################################################\r
624 \r
625 class ChangedScreen(Screen):\r
626         def __init__(self, session, parent=None):\r
627                 Screen.__init__(self, session, parent)\r
628                 self.onLayoutFinish.append(self.setScreenTitle)\r
629 \r
630         def setScreenTitle(self):\r
631                 self.setTitle(_("RS Downloader"))\r
632 \r
633 ##############################################################################\r
634 \r
635 class RSConfig(ConfigListScreen, ChangedScreen):\r
636         skin = """\r
637                 <screen position="center,center" size="560,450" title="RS Downloader">\r
638                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />\r
639                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />\r
640                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />\r
641                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />\r
642                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
643                         <widget name="config" position="0,45" size="560,400" scrollbarMode="showOnDemand" />\r
644                 </screen>"""\r
645 \r
646         def __init__(self, session):\r
647                 ChangedScreen.__init__(self, session)\r
648                 \r
649                 self["key_green"] = Label(_("Save"))\r
650                 \r
651                 ConfigListScreen.__init__(self, [\r
652                         getConfigListEntry(_("Download in the background:"), config.plugins.RSDownloader.onoff),\r
653                         getConfigListEntry(_("Username:"), config.plugins.RSDownloader.username),\r
654                         getConfigListEntry(_("Password:"), config.plugins.RSDownloader.password),\r
655                         getConfigListEntry(_("Lists directory:"), config.plugins.RSDownloader.lists_directory),\r
656                         getConfigListEntry(_("Downloads directory:"), config.plugins.RSDownloader.downloads_directory),\r
657                         getConfigListEntry(_("Ignore download times:"), config.plugins.RSDownloader.ignore_time),\r
658                         getConfigListEntry(_("Allow downloading on monday:"), config.plugins.RSDownloader.download_monday),\r
659                         getConfigListEntry(_("Allow downloading on tuesday:"), config.plugins.RSDownloader.download_tuesday),\r
660                         getConfigListEntry(_("Allow downloading on wednesday:"), config.plugins.RSDownloader.download_wednesday),\r
661                         getConfigListEntry(_("Allow downloading on thursday:"), config.plugins.RSDownloader.download_thursday),\r
662                         getConfigListEntry(_("Allow downloading on friday:"), config.plugins.RSDownloader.download_friday),\r
663                         getConfigListEntry(_("Allow downloading on saturday:"), config.plugins.RSDownloader.download_saturday),\r
664                         getConfigListEntry(_("Allow downloading on sunday:"), config.plugins.RSDownloader.download_sunday),\r
665                         getConfigListEntry(_("Don't download before:"), config.plugins.RSDownloader.start_time),\r
666                         getConfigListEntry(_("Don't download after:"), config.plugins.RSDownloader.end_time),\r
667                         getConfigListEntry(_("Maximal downloads:"), config.plugins.RSDownloader.count_downloads),\r
668                         getConfigListEntry(_("Write log:"), config.plugins.RSDownloader.write_log),\r
669                         getConfigListEntry(_("Reconnect fritz.Box before downloading:"), config.plugins.RSDownloader.reconnect_fritz),\r
670                         getConfigListEntry(_("Restart failed after 10 minutes:"), config.plugins.RSDownloader.autorestart_failed)])\r
671                 \r
672                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"], {"green": self.save, "cancel": self.exit}, -1)\r
673 \r
674         def save(self):\r
675                 for x in self["config"].list:\r
676                         x[1].save()\r
677                 self.close()\r
678 \r
679         def exit(self):\r
680                 for x in self["config"].list:\r
681                         x[1].cancel()\r
682                 self.close()\r
683 \r
684 ##############################################################################\r
685 \r
686 class RSSearch(Screen):\r
687         skin = """\r
688                 <screen position="center,center" size="560,450" title="Searching... please wait!">\r
689                         <widget name="list" position="0,0" size="570,450" scrollbarMode="showOnDemand" />\r
690                 </screen>"""\r
691 \r
692         def __init__(self, session, searchFor):\r
693                 Screen.__init__(self, session)\r
694                 self.session = session\r
695                 \r
696                 self.searchFor = searchFor.replace(" ", "%2B")\r
697                 self.maxPage = 1\r
698                 self.curPage = 1\r
699                 self.files = []\r
700                 \r
701                 self["list"] = MenuList([])\r
702                 \r
703                 self["actions"] = ActionMap(["OkCancelActions", "InfobarChannelSelection"],\r
704                         {\r
705                                 "historyBack": self.previousPage,\r
706                                 "historyNext": self.nextPage,\r
707                                 "ok": self.okClicked,\r
708                                 "cancel": self.close\r
709                         }, -1)\r
710                 \r
711                 self.onLayoutFinish.append(self.search)\r
712 \r
713         def okClicked(self):\r
714                 if len(self.files) > 0:\r
715                         idx = self["list"].getSelectedIndex()\r
716                         url = self.files[idx]\r
717                         try:\r
718                                 f = open(("%s/search.txt" % config.plugins.RSDownloader.lists_directory.value).replace("//", "/"), "a")\r
719                                 f.write("%s\n"%url)\r
720                                 f.close()\r
721                                 self.session.open(MessageBox, (_("Added %s to the download-list.") % url), MessageBox.TYPE_INFO)\r
722                         except:\r
723                                 self.session.open(MessageBox, (_("Error while adding %s to the download-list!") % url), MessageBox.TYPE_ERROR)\r
724 \r
725         def search(self):\r
726                 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
727 \r
728         def searchCallback(self, html=""):\r
729                 list = []\r
730                 files = []\r
731                 \r
732                 if html.__contains__("Nothing found, sorry."):\r
733                         self.session.open(MessageBox, (_("Error while searching http://rapidshare-search-engine.com!\n\nError: Nothing found, sorry.")), MessageBox.TYPE_ERROR)\r
734                         self.instance.setTitle(_("Nothing found, sorry."))\r
735                 else:\r
736                         tmp = html\r
737                         while tmp.__contains__("goPg('"):\r
738                                 idx = tmp.index("goPg('")\r
739                                 tmp = tmp[idx+6:]\r
740                                 idx = tmp.index("'")\r
741                                 pageNumber = tmp[:idx]\r
742                                 \r
743                                 try:\r
744                                         pageNumber = int(pageNumber)\r
745                                         if pageNumber > self.maxPage:\r
746                                                 self.maxPage = pageNumber\r
747                                 except:\r
748                                         pass\r
749                                 \r
750                                 self.instance.setTitle(_("Page %d / %d. Push < > to switch the page...")%(self.curPage, self.maxPage))\r
751                         \r
752                         while html.__contains__('title="Download"'):\r
753                                 idx = html.index('title="Download"')\r
754                                 html = html[idx:]\r
755                                 idx = html.index('value="')\r
756                                 html = html[idx+7:]\r
757                                 idx = html.index('"')\r
758                                 size = html[:idx]\r
759                                 idx = html.index('http://rapidshare.com/')\r
760                                 html = html[idx:]\r
761                                 idx = html.index('"')\r
762                                 url = html[:idx]\r
763                                 \r
764                                 files.append(url) \r
765                                 try:\r
766                                         urllist = url.split("/")\r
767                                         idx = len(urllist) - 1\r
768                                         name = urllist[idx]\r
769                                         list.append("%s - %s"%(size, name))\r
770                                 except:\r
771                                         list.append("%s - %s"%(size, url))\r
772                 \r
773                 self.files = files\r
774                 self["list"].setList(list)\r
775 \r
776         def searchError(self, error=""):\r
777                 self.session.open(MessageBox, (_("Error while searching http://rapidshare-search-engine.com!\n\nError: %s")%str(error)), MessageBox.TYPE_ERROR)\r
778 \r
779         def previousPage(self):\r
780                 if self.curPage > 1:\r
781                         self.curPage -= 1\r
782                         self.instance.setTitle(_("Loading previous page... please wait!"))\r
783                         self.search()\r
784 \r
785         def nextPage(self):\r
786                 if self.curPage < self.maxPage:\r
787                         self.curPage += 1\r
788                         self.instance.setTitle(_("Loading next page... please wait!"))\r
789                         self.search()\r
790 \r
791 ##############################################################################\r
792 \r
793 class RSLogScreen(ChangedScreen):\r
794         skin = """\r
795                 <screen position="center,center" size="560,450" title="RS Downloader">\r
796                         <widget name="label" position="0,0" size="560,450" font="Regular;20" />\r
797                 </screen>"""\r
798 \r
799         def __init__(self, session):\r
800                 ChangedScreen.__init__(self, session)\r
801                 \r
802                 try:\r
803                         f = open("/tmp/rapidshare.log")\r
804                         log = f.read()\r
805                         f.close()\r
806                 except:\r
807                         log = ""\r
808                 self["label"] = ScrollLabel(log)\r
809                 \r
810                 self["actions"] = ActionMap(["WizardActions"],\r
811                         {\r
812                                 "ok": self.close,\r
813                                 "back": self.close,\r
814                                 "up": self["label"].pageUp,\r
815                                 "down": self["label"].pageDown,\r
816                                 "left": self["label"].pageUp,\r
817                                 "right": self["label"].pageDown\r
818                         }, -1)\r
819 \r
820 ##############################################################################\r
821 \r
822 class RSContainerSelector(ChangedScreen):\r
823         skin = """\r
824                 <screen position="center,center" size="560,450" title="RS Downloader">\r
825                         <widget name="list" position="0,0" size="560,450" />\r
826                 </screen>"""\r
827 \r
828         def __init__(self, session, list):\r
829                 ChangedScreen.__init__(self, session)\r
830                 self["list"] = MenuList(list)\r
831                 self["actions"] = ActionMap(["OkCancelActions"], {"ok": self.okClicked, "cancel": self.close}, -1)\r
832 \r
833         def okClicked(self):\r
834                 cur = self["list"].getCurrent()\r
835                 self.close(cur)\r
836 \r
837 ##############################################################################\r
838 \r
839 class RSList(MenuList):\r
840         def __init__(self, list):\r
841                 MenuList.__init__(self, list, False, eListboxPythonMultiContent)\r
842                 self.l.setItemHeight(25)\r
843                 self.l.setFont(0, gFont("Regular", 20))\r
844 \r
845 ##############################################################################\r
846 \r
847 def RSListEntry(download):\r
848         res = [(download)]\r
849         res.append(MultiContentEntryText(pos=(0, 0), size=(170, 25), font=0, text=download.name))\r
850         res.append(MultiContentEntryText(pos=(175, 0), size=(75, 25), font=0, text="%d%s"%(download.size, "MB"), flags=RT_HALIGN_CENTER))\r
851         res.append(MultiContentEntryPixmapAlphaTest(pos=(260, 9), size=(84, 7), png=LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/progress_bg.png"))))\r
852         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
853         res.append(MultiContentEntryText(pos=(360, 0), size=(60, 25), font=0, text="%d%s"%(download.progress, "%"), flags=RT_HALIGN_CENTER))\r
854         res.append(MultiContentEntryText(pos=(420, 0), size=(140, 25), font=0, text=download.status, flags=RT_HALIGN_RIGHT))\r
855         return res\r
856 \r
857 ##############################################################################\r
858 \r
859 class RSMain(ChangedScreen):\r
860         skin = """\r
861                 <screen position="center,center" size="560,450" title="RS Downloader">\r
862                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" transparent="1" alphatest="on" />\r
863                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" transparent="1" alphatest="on" />\r
864                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" transparent="1" alphatest="on" />\r
865                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" transparent="1" alphatest="on" />\r
866                         <ePixmap pixmap="skin_default/buttons/key_menu.png" position="10,420" size="35,25" transparent="1" alphatest="on" />\r
867                         <widget name="key_red" position="0,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
868                         <widget name="key_green" position="140,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
869                         <widget name="key_yellow" position="280,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
870                         <widget name="key_blue" position="420,0" zPosition="1" size="140,40" font="Regular;20" valign="center" halign="center" backgroundColor="#1f771f" transparent="1" />\r
871                         <widget name="key_menu" position="50,422" size="300,25" font="Regular;20" transparent="1" />\r
872                         <widget name="list" position="0,40" size="560,375" scrollbarMode="showNever" />\r
873                 </screen>"""\r
874 \r
875         def __init__(self, session):\r
876                 ChangedScreen.__init__(self, session)\r
877                 self.session = session\r
878                 \r
879                 self["key_red"] = Label(_("Delete"))\r
880                 self["key_green"] = Label(_("Search"))\r
881                 self["key_yellow"] = Label(_("Add"))\r
882                 self["key_blue"] = Label(_("Config"))\r
883                 self["key_menu"] = Label(_("Menu"))\r
884                 self["list"] = RSList([])\r
885                 \r
886                 self.refreshTimer = eTimer()\r
887                 self.refreshTimer.callback.append(self.updateList)\r
888                 \r
889                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions", "InfobarMenuActions"],\r
890                         {\r
891                                 "mainMenu": self.menu,\r
892                                 "cancel": self.close,\r
893                                 "red": self.delete,\r
894                                 "green": self.search,\r
895                                 "yellow": self.add,\r
896                                 "blue": self.config\r
897                         }, prio=-1)\r
898                 \r
899                 self.onLayoutFinish.append(self.updateList)\r
900 \r
901         def menu(self):\r
902                 list = []\r
903                 #TODO: Add sort list functions\r
904                 list.append((_("Delete download"), self.delete))\r
905                 list.append((_("Use search engine"), self.search))\r
906                 list.append((_("Add downloads from txt files"), self.add))\r
907                 list.append((_("Add files from container"), self.addContainer))\r
908                 list.append((_("Delete failed downloads"), self.deleteFailed))\r
909                 list.append((_("Restart failed downloads"), self.restartFailed))\r
910                 list.append((_("Clear finished downloads"), self.clearFinished))\r
911                 list.append((_("Show log"), self.showLog))\r
912                 list.append((_("Delete log"), self.deleteLog))\r
913                 list.append((_("Close plugin"), self.close))\r
914                 self.session.openWithCallback(self.menuCallback, ChoiceBox, title=_("Please choose a function..."), list=list)\r
915 \r
916         def menuCallback(self, callback=None):\r
917                 if callback is not None:\r
918                         callback[1]()\r
919 \r
920         def deleteFailed(self):\r
921                 rapidshare.deleteFailedDownloads()\r
922 \r
923         def restartFailed(self):\r
924                 rapidshare.restartFailedDownloads()\r
925 \r
926         def clearFinished(self):\r
927                 rapidshare.clearFinishedDownloads()\r
928 \r
929         def showLog(self):\r
930                 self.session.open(RSLogScreen)\r
931 \r
932         def deleteLog(self):\r
933                 try:\r
934                         remove("/tmp/rapidshare.log")\r
935                 except:\r
936                         pass\r
937 \r
938         def updateList(self):\r
939                 list = []\r
940                 for download in rapidshare.downloads:\r
941                         list.append(RSListEntry(download))\r
942                 self["list"].setList(list)\r
943                 self.refreshTimer.start(2000, 1)\r
944 \r
945         def delete(self):\r
946                 cur = self["list"].getCurrent()\r
947                 if cur:\r
948                         cur = cur[0]\r
949                         if cur.status == _("Finished"):\r
950                                 rapidshare.clearFinishedDownload(cur.url)\r
951                         else:\r
952                                 self.session.openWithCallback(self.deleteCallback, MessageBox, (_("Delete %s?")%cur.name))\r
953 \r
954         def deleteCallback(self, callback):\r
955                 if callback:\r
956                         rapidshare.removeDownload(self["list"].getCurrent()[0].url)\r
957                         self.refreshTimer.stop()\r
958                         self.updateList()\r
959 \r
960         def search(self):\r
961                 self.session.openWithCallback(self.searchCallback, VirtualKeyBoard, title=_("Search http://rapidshare-search-engine.com for:"))\r
962 \r
963         def searchCallback(self, callback):\r
964                 if callback is not None and callback != "":\r
965                         self.session.openWithCallback(self.searchScreenCallback, RSSearch, callback)\r
966 \r
967 \r
968         def searchScreenCallback(self):\r
969                 self.refreshTimer.stop()\r
970                 rapidshare.startDownloading()\r
971                 self.updateList()\r
972 \r
973         def add(self):\r
974                 self.refreshTimer.stop()\r
975                 rapidshare.startDownloading()\r
976                 self.updateList()\r
977 \r
978         def config(self):\r
979                 self.session.openWithCallback(self.configCallback, RSConfig)\r
980 \r
981         def configCallback(self):\r
982                 if config.plugins.RSDownloader.onoff.value:\r
983                         rapidshare.startDownloading()\r
984                 else:\r
985                         for download in rapidshare.downloads:\r
986                                 if download.downloading:\r
987                                         download.stop()\r
988                 self.updateList()\r
989 \r
990         def addContainer(self):\r
991                 try:\r
992                         file_list = listdir(config.plugins.RSDownloader.lists_directory.value)\r
993                 except:\r
994                         file_list = []\r
995                 list = []\r
996                 for file in file_list:\r
997                         if file.lower().endswith(".ccf") or file.lower().endswith(".dlc") or file.lower().endswith(".rsdf"):\r
998                                 list.append(file)\r
999                 list.sort()\r
1000                 self.session.openWithCallback(self.addContainerCallback, RSContainerSelector, list)\r
1001 \r
1002         def addContainerCallback(self, callback=None):\r
1003                 if callback:\r
1004                         file = "%s/%s"%(config.plugins.RSDownloader.lists_directory.value, callback)\r
1005                         file = file.replace("//", "/")\r
1006                         links = decrypt(file)\r
1007                         try:\r
1008                                 f = open(("%s/%s.txt" % (config.plugins.RSDownloader.lists_directory.value, callback)).replace("//", "/"), "w")\r
1009                                 for link in links:\r
1010                                         if link.endswith(".html"):\r
1011                                                 link = link[:-5]\r
1012                                         elif link.endswith(".htm"):\r
1013                                                 link = link[:-4]\r
1014                                         f.write("%s\n"%link)\r
1015                                 f.close()\r
1016                         except:\r
1017                                 pass\r
1018                         self.refreshTimer.stop()\r
1019                         rapidshare.startDownloading()\r
1020                         self.updateList()\r
1021 \r
1022 ##############################################################################\r
1023 \r
1024 def autostart(reason, **kwargs):\r
1025         if reason == 0:\r
1026                 rapidshare.startDownloading()\r
1027 \r
1028 ##############################################################################\r
1029 \r
1030 def main(session, **kwargs):\r
1031         session.open(RSMain)\r
1032 \r
1033 ##############################################################################\r
1034 \r
1035 def Plugins(**kwargs):\r
1036         return [\r
1037                 PluginDescriptor(where=PluginDescriptor.WHERE_AUTOSTART, fnc=autostart),\r
1038                 PluginDescriptor(name=_("RS Downloader"), description=_("Download files from rapidshare"), where=[PluginDescriptor.WHERE_EXTENSIONSMENU, PluginDescriptor.WHERE_PLUGINMENU], icon="rs.png", fnc=main)]\r
1039 \r