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