diff --git a/lib/pynma/__init__.py b/lib/pynma/__init__.py
index f90424eb70e977fa6f417a29fc944a6fba32e65d..a75b42855b632e050325c9d3517891cb094d086f 100644
--- a/lib/pynma/__init__.py
+++ b/lib/pynma/__init__.py
@@ -1,4 +1,4 @@
 #!/usr/bin/python
 
-from pynma import PyNMA 
+from .pynma import PyNMA 
 
diff --git a/lib/pynma/pynma.py b/lib/pynma/pynma.py
index fc7d8de2eeb4cf90ec5e6ceae4fb60c6925fd3ac..2fc55560af9624dc4a7526aec27b6e5bbebef03a 100644
--- a/lib/pynma/pynma.py
+++ b/lib/pynma/pynma.py
@@ -1,12 +1,20 @@
 #!/usr/bin/python
 
 from xml.dom.minidom import parseString
-from httplib import HTTPSConnection
-from urllib import urlencode
 
-__version__ = "0.1"
+try:
+        from http.client import HTTPSConnection
+except ImportError:
+        from httplib import HTTPSConnection
 
-API_SERVER = 'nma.usk.bz'
+try:
+        from urllib.parse import urlencode
+except ImportError:
+        from urllib import urlencode
+
+__version__ = "1.0"
+
+API_SERVER = 'www.notifymyandroid.com' 
 ADD_PATH   = '/publicapi/notify'
 
 USER_AGENT="PyNMA/v%s"%__version__
@@ -18,14 +26,14 @@ def uniq_preserve(seq): # Dave Kirby
 
 def uniq(seq):
     # Not order preserving
-    return {}.fromkeys(seq).keys()
+    return list({}.fromkeys(seq).keys())
 
 class PyNMA(object):
     """PyNMA(apikey=[], developerkey=None)
-        takes 2 optional arguments:
-            - (opt) apykey:      might me a string containing 1 key or an array of keys
-            - (opt) developerkey: where you can store your developer key
-    """
+takes 2 optional arguments:
+ - (opt) apykey:      might me a string containing 1 key or an array of keys
+ - (opt) developerkey: where you can store your developer key
+"""
 
     def __init__(self, apikey=[], developerkey=None):
         self._developerkey = None
@@ -60,19 +68,20 @@ class PyNMA(object):
         if type(developerkey) == str and len(developerkey) == 48:
             self._developerkey = developerkey
 
-    def push(self, application="", event="", description="", url="", priority=0, batch_mode=False):
+    def push(self, application="", event="", description="", url="", contenttype=None, priority=0, batch_mode=False, html=False):
         """Pushes a message on the registered API keys.
-            takes 5 arguments:
-                - (req) application: application name [256]
-                - (req) event:       event name       [1000]
-                - (req) description: description      [10000]
-                - (opt) url:         url              [512]
-                - (opt) priority:    from -2 (lowest) to 2 (highest) (def:0)
-                - (opt) batch_mode:  call API 5 by 5 (def:False)
-
-            Warning: using batch_mode will return error only if all API keys are bad
-            cf: http://nma.usk.bz/api.php
-        """
+takes 5 arguments:
+ - (req) application: application name [256]
+ - (req) event:       event name       [1000]
+ - (req) description: description      [10000]
+ - (opt) url:         url              [512]
+ - (opt) contenttype: Content Type (act: None (plain text) or text/html)
+ - (opt) priority:    from -2 (lowest) to 2 (highest) (def:0)
+ - (opt) batch_mode:  push to all keys at once (def:False)
+ - (opt) html:        shortcut for contenttype=text/html
+Warning: using batch_mode will return error only if all API keys are bad
+ cf: http://nma.usk.bz/api.php
+"""
         datas = {
             'application': application[:256].encode('utf8'),
             'event':       event[:1024].encode('utf8'),
@@ -82,7 +91,10 @@ class PyNMA(object):
 
         if url:
             datas['url'] = url[:512]
-
+        
+        if contenttype == "text/html" or html == True: # Currently only accepted content type
+            datas['content-type'] = "text/html"
+        
         if self._developerkey:
             datas['developerkey'] = self._developerkey
 
@@ -94,10 +106,9 @@ class PyNMA(object):
                 res = self.callapi('POST', ADD_PATH, datas)
                 results[key] = res
         else:
-            for i in range(0, len(self._apikey), 5):
-                datas['apikey'] = ",".join(self._apikey[i:i+5])
-                res = self.callapi('POST', ADD_PATH, datas)
-                results[datas['apikey']] = res
+            datas['apikey'] = ",".join(self._apikey)
+            res = self.callapi('POST', ADD_PATH, datas)
+            results[datas['apikey']] = res
         return results
         
     def callapi(self, method, path, args):
@@ -110,7 +121,7 @@ class PyNMA(object):
 
         try:
             res = self._parse_reponse(resp.read())
-        except Exception, e:
+        except Exception as e:
             res = {'type':    "pynmaerror",
                    'code':    600,
                    'message': str(e)
@@ -124,12 +135,12 @@ class PyNMA(object):
         for elem in root.childNodes:
             if elem.nodeType == elem.TEXT_NODE: continue
             if elem.tagName == 'success':
-                res = dict(elem.attributes.items())
+                res = dict(list(elem.attributes.items()))
                 res['message'] = ""
                 res['type']    = elem.tagName
                 return res
             if elem.tagName == 'error':
-                res = dict(elem.attributes.items())
+                res = dict(list(elem.attributes.items()))
                 res['message'] = elem.firstChild.nodeValue
                 res['type']    = elem.tagName
                 return res
diff --git a/sickbeard/providers/libertalia.py b/sickbeard/providers/libertalia.py
index 3f6f14b513f2ac75de0de466430b679c8080fcf2..308c5dddf8db186dbc8488be00328d564e1a10df 100644
--- a/sickbeard/providers/libertalia.py
+++ b/sickbeard/providers/libertalia.py
@@ -57,15 +57,15 @@ class LIBERTALIAProvider(generic.TorrentProvider):
         if audio_lang == "en" and french==None:
             results.append( urllib.urlencode( {
                 'name': searchString                            
-            } ) + "*VO*&cat%5B%5D="+cat+"&[PARAMSTR]=" + searchString +" VO" )
+            } ) + "*VO*&cat%5B%5D="+cat+"&[PARAMSTR]=" + searchString  )
         elif audio_lang == "en" and french==None:
             results.append( urllib.urlencode( {
                 'name': searchString                            
-            } ) + "*VO*&cat%5B%5D="+cat+"&[PARAMSTR]=" + searchString +" VO" )
+            } ) + "*VO*&cat%5B%5D="+cat+"&[PARAMSTR]=" + searchString  )
         elif audio_lang == "fr" or french:
             results.append( urllib.urlencode( {
                 'name': searchString
-            } ) + "*FRENCH*&cat%5B%5D="+cat+"&[PARAMSTR]=" + searchString +" FRENCH")
+            } ) + "*FRENCH*&cat%5B%5D="+cat+"&[PARAMSTR]=" + searchString )
         else:
             results.append( urllib.urlencode( {
                 'name': searchString
diff --git a/sickbeard/providers/xthor.py b/sickbeard/providers/xthor.py
index b5fde78e4df524db333e62b8909773ddb165a83d..e7bded7bdd84fb4020c42123d5e70045586f41eb 100644
--- a/sickbeard/providers/xthor.py
+++ b/sickbeard/providers/xthor.py
@@ -31,178 +31,176 @@ import re
 
 class XTHORProvider(generic.TorrentProvider):
 
-    def __init__(self):
-        
-        generic.TorrentProvider.__init__(self, "XTHOR")
-
-        self.supportsBacklog = True
-        
-        self.cj = cookielib.CookieJar()
-        self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj))
-        
-        self.url = "https://xthor.bz"
-        
-        self.login_done = False
-        self.failed_login_logged = False
-        self.successful_login_logged = False
-        
-    def isEnabled(self):
-        return sickbeard.XTHOR
-    
-    def getSearchParams(self, searchString, audio_lang, french=None, fullSeason=False):
-        results = []    
-        if audio_lang == "en" and french==None:
-            results.append( urllib.urlencode( {
-                'keywords': searchString  ,                                                         
-            } ) + "&cid=43,69&[PARAMSTR]=" + searchString )
-        elif audio_lang == "fr" or french:
-            results.append( urllib.urlencode( {
-                'keywords': searchString
-            } ) + "&cid=42,41&[PARAMSTR]=" + searchString)
-        else:
-            results.append( urllib.urlencode( {
-                'keywords': searchString
-            } ) + "&cid=42,43,41,69&[PARAMSTR]=" + searchString)
-        #Désactivé car on ne peut pas savoir la langue
-        #if fullSeason:
-        #    results.append( urllib.urlencode( {
-        #        'keywords': searchString
-        #    } ) + "&cid=70&[PARAMSTR]=" + searchString)
-        return results
-        
-    def _get_season_search_strings(self, show, season):
-
-        showNam = show_name_helpers.allPossibleShowNames(show)
-        showNames = list(set(showNam))
-        results = []
-        for showName in showNames:
-            results.extend( self.getSearchParams(showName + " saison%d" % season, show.audio_lang, fullSeason=True))
-            results.extend( self.getSearchParams(showName + " season%d" % season, show.audio_lang, fullSeason=True))
-            results.extend( self.getSearchParams(showName + " saison %d" % season, show.audio_lang, fullSeason=True))
-            results.extend( self.getSearchParams(showName + " season %d" % season, show.audio_lang, fullSeason=True))
-            results.extend( self.getSearchParams(showName + " saison%02d" % season, show.audio_lang, fullSeason=True))
-            results.extend( self.getSearchParams(showName + " season%02d" % season, show.audio_lang, fullSeason=True))
-            results.extend( self.getSearchParams(showName + " saison %02d" % season, show.audio_lang, fullSeason=True))
-            results.extend( self.getSearchParams(showName + " season %02d" % season, show.audio_lang, fullSeason=True))
-            results.extend( self.getSearchParams(showName + ".S%02d." % season, show.audio_lang, fullSeason=True))
-        return results
-
-    def _get_episode_search_strings(self, ep_obj, french=None):
-
-        showNam = show_name_helpers.allPossibleShowNames(ep_obj.show)
-        showNames = list(set(showNam))
-        results = []
-        for showName in showNames:
-            results.extend( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode), ep_obj.show.audio_lang, french ))
-            results.extend( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode ), ep_obj.show.audio_lang, french ))
-        return results
-    
-    def _get_title_and_url(self, item):
-        return (item.title, item.url)
-    
-    def getQuality(self, item):
-        return item.getQuality()
-    
-    def _doLogin(self, login, password):
-
-        listeUserAgents = [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; fr-fr) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1',
-                                                'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/535.1',
-                                                'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13',
-                                                'Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) midori',
-                                                'Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.107 Safari/535.1',
-                                                'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/312.1 (KHTML, like Gecko) Safari/312',
-                                                'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11',
-                                                'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.8 (KHTML, like Gecko) Chrome/17.0.940.0 Safari/535.8' ]
-
-        self.opener.addheaders = [('User-agent', random.choice(listeUserAgents))] 
-                                              
-        data = urllib.urlencode({'action':'login','loginbox_membername': login, 'loginbox_password' : password, 'loginbox_remember' : 'true'})
-     
-        r = self.opener.open(self.url + '/ajax/login.php',data)
-        
-        for index, cookie in enumerate(self.cj):
-            if (cookie.name == "tsue_member"): self.login_done = True
-                                
-        if not self.login_done and not self.failed_login_logged:
-            logger.log(u"Unable to login to XTHOR. Please check username and password.", logger.WARNING) 
-            self.failed_login_logged = True
-        
-        if self.login_done and not self.successful_login_logged:
-            logger.log(u"Login to XTHOR successful", logger.MESSAGE) 
-            self.successful_login_logged = True        
-
-    def _doSearch(self, searchString, show=None, season=None, french=None):
-
-        
-        if not self.login_done:
-            self._doLogin( sickbeard.XTHOR_USERNAME, sickbeard.XTHOR_PASSWORD )
-
-        results = []
-       
-        searchUrl = self.url + '?p=torrents&pid=10&search_type=name&' + searchString.replace('!','')
- 
-        logger.log(u"Search string: " + searchUrl, logger.DEBUG)
-        
-        r = self.opener.open( searchUrl )
-
-        soup = BeautifulSoup( r)
-
-        resultsTable = soup.find("table", { "id" : "torrents_table_classic"  })
-        if resultsTable:
-
-            rows = resultsTable.findAll("tr")
-           
-            for row in rows:
-            
-                link = row.find("a",href=re.compile("action=details"))                                                           
-                                  
-                if link:               
-                    title = link.text
-                    recherched=searchUrl.split("&[PARAMSTR]=")[1]
-                    recherched=recherched.replace(" ","(.*)")
-                    logger.log(u"XTHOR TITLE : " + title, logger.DEBUG)
-                    logger.log(u"XTHOR CHECK MATCH : " + recherched, logger.DEBUG)                                        
-                    if re.match(recherched,title , re.IGNORECASE):                                        
-                        downloadURL =  row.find("a",href=re.compile("action=download"))['href']             
-                        logger.log(u"XTHOR DOWNLOAD URL : " + downloadURL, logger.DEBUG) 
-                    else:
-                        continue
-                    quality = Quality.nameQuality( title )
-                    if quality==Quality.UNKNOWN and title:
-                        if '720p' not in title.lower() and '1080p' not in title.lower():
-                            quality=Quality.SDTV
-                    if show and french==None:
-                        results.append( XTHORSearchResult( self.opener, title, downloadURL, quality, str(show.audio_lang) ) )
-                    elif show and french:
-                        results.append( XTHORSearchResult( self.opener, title, downloadURL, quality, 'fr' ) )
-                    else:
-                        results.append( XTHORSearchResult( self.opener, title, downloadURL, quality ) )
-        
-        return results
-    
-    def getResult(self, episodes):
-        """
-        Returns a result of the correct type for this provider
-        """
-        result = classes.TorrentDataSearchResult(episodes)
-        result.provider = self
-
-        return result    
-    
+	def __init__(self):
+		
+		generic.TorrentProvider.__init__(self, "XTHOR")
+		
+		self.supportsBacklog = True
+		
+		
+		self.cj = cookielib.CookieJar()
+		self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj))
+		
+		self.url = "https://xthor.bz"
+		
+		self.login_done = False
+		self.failed_login_logged = False
+		self.successful_login_logged = False
+		
+	def isEnabled(self):
+		return sickbeard.XTHOR
+
+	def getSearchParams(self, searchString, audio_lang, french=None, fullSeason=False):
+		results = []
+		
+		if audio_lang == "en" and french==None:
+			results.append("c16=1&c17=1&searchin=title&search=" + searchString  )
+		elif audio_lang == "fr" or french:
+			results.append("c14=1&c15=1&searchin=title&search=" + searchString)
+		else:
+			results.append("c14=1&c15=1&c16=1&c17=1&searchin=title&search=" + searchString)
+		#Désactivé car on ne peut pas savoir la langue
+		#if fullSeason:
+		#    results.append( urllib.urlencode( {
+		#        'keywords': searchString
+		#    } ) + "&cid=70&[PARAMSTR]=" + searchString)
+		return results
+		
+	def _get_season_search_strings(self, show, season):
+
+		showNam = show_name_helpers.allPossibleShowNames(show)
+		showNames = list(set(showNam))
+		results = []
+		for showName in showNames:
+			results.extend( self.getSearchParams(showName + " saison%d" % season, show.audio_lang, fullSeason=True))
+			results.extend( self.getSearchParams(showName + " season%d" % season, show.audio_lang, fullSeason=True))
+			results.extend( self.getSearchParams(showName + " saison %d" % season, show.audio_lang, fullSeason=True))
+			results.extend( self.getSearchParams(showName + " season %d" % season, show.audio_lang, fullSeason=True))
+			results.extend( self.getSearchParams(showName + " saison%02d" % season, show.audio_lang, fullSeason=True))
+			results.extend( self.getSearchParams(showName + " season%02d" % season, show.audio_lang, fullSeason=True))
+			results.extend( self.getSearchParams(showName + " saison %02d" % season, show.audio_lang, fullSeason=True))
+			results.extend( self.getSearchParams(showName + " season %02d" % season, show.audio_lang, fullSeason=True))
+			results.extend( self.getSearchParams(showName + ".S%02d." % season, show.audio_lang, fullSeason=True)) 
+		return results
+
+	def _get_episode_search_strings(self, ep_obj, french=None):
+
+		showNam = show_name_helpers.allPossibleShowNames(ep_obj.show)
+		showNames = list(set(showNam))
+		results = []
+		for showName in showNames:
+			results.extend( self.getSearchParams( "%s S%02dE%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode), ep_obj.show.audio_lang, french ))
+			results.extend( self.getSearchParams( "%s %dx%02d" % ( showName, ep_obj.scene_season, ep_obj.scene_episode ), ep_obj.show.audio_lang, french ))
+		return results
+
+	def _get_title_and_url(self, item):
+		return (item.title, item.url)
+
+	def getQuality(self, item):
+		return item.getQuality()
+
+	def _doLogin(self, login, password):
+
+		listeUserAgents = [ 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_5; fr-fr) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1',
+												'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/535.1',
+												'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13',
+												'Mozilla/5.0 (X11; U; Linux x86_64; en-us) AppleWebKit/528.5+ (KHTML, like Gecko, Safari/528.5+) midori',
+												'Mozilla/5.0 (Windows NT 6.0) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.107 Safari/535.1',
+												'Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/312.1 (KHTML, like Gecko) Safari/312',
+												'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.12 Safari/535.11',
+												'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.8 (KHTML, like Gecko) Chrome/17.0.940.0 Safari/535.8' ]
+
+		self.opener.addheaders = [('User-agent', random.choice(listeUserAgents))] 
+											  
+		data = urllib.urlencode({'action':'takelogin.php','username': login, 'password' : password, 'submitme' : 'X'})
+	 
+		r = self.opener.open(self.url + '/takelogin.php',data)
+		
+		for index, cookie in enumerate(self.cj):
+			if (cookie.name == "uid"): self.login_done = True
+								
+		if not self.login_done and not self.failed_login_logged:
+			logger.log(u"Unable to login to XTHOR. Please check username and password.", logger.WARNING) 
+			self.failed_login_logged = True
+		
+		if self.login_done and not self.successful_login_logged:
+			logger.log(u"Login to XTHOR successful", logger.MESSAGE) 
+			self.successful_login_logged = True        
+
+	def _doSearch(self, searchString, show=None, season=None, french=None):
+
+		
+		if not self.login_done:
+			self._doLogin( sickbeard.XTHOR_USERNAME, sickbeard.XTHOR_PASSWORD )
+
+		results = []
+	   
+		searchUrl = self.url + '/browse.php?' + searchString.replace('!','')
+
+		logger.log(u"Search string: " + searchUrl, logger.DEBUG)
+		
+		r = self.opener.open( searchUrl )
+
+		soup = BeautifulSoup( r)
+
+		resultsTable = soup.find("table", { "class" : "table2"  })
+		if resultsTable:
+
+			rows = resultsTable.findAll("tr")
+		   
+			for row in rows:
+			
+				link = row.find("a",href=re.compile("details.php"))                                                           
+								  
+				if link:               
+					title = link.text
+					recherched=searchUrl.split("&search=")[1]
+					recherched=recherched.replace(" ","(.*)")
+					recherched= recherched + "(.*)"
+					logger.log(u"XTHOR TITLE : " + title, logger.DEBUG)
+					logger.log(u"XTHOR CHECK MATCH : " + recherched, logger.DEBUG)                                        
+					if re.match(recherched,title , re.IGNORECASE):                                        
+						downloadURL =  row.find("a",href=re.compile("download.php"))['href']
+						downloadURL = self.url + '/'+ downloadURL
+						logger.log(u"XTHOR DOWNLOAD URL : " + downloadURL, logger.DEBUG) 
+					else:
+						continue
+					quality = Quality.nameQuality( title )
+					if quality==Quality.UNKNOWN and title:
+						if '720p' not in title.lower() and '1080p' not in title.lower():
+							quality=Quality.SDTV
+					if show and french==None:
+						results.append( XTHORSearchResult( self.opener, title, downloadURL, quality, str(show.audio_lang) ) )
+					elif show and french:
+						results.append( XTHORSearchResult( self.opener, title, downloadURL, quality, 'fr' ) )
+					else:
+						results.append( XTHORSearchResult( self.opener, title, downloadURL, quality ) )
+		
+		return results
+
+	def getResult(self, episodes):
+		"""
+		Returns a result of the correct type for this provider
+		"""
+		result = classes.TorrentDataSearchResult(episodes)
+		result.provider = self
+
+		return result    
+
 class XTHORSearchResult:
-    
-    def __init__(self, opener, title, url, quality, audio_langs=None):
-        self.opener = opener
-        self.title = title
-        self.url = url
-        self.quality = quality
-        self.audio_langs=audio_langs    
-
-    def getNZB(self):
-        logger.log(u"XTHOR GETNZB URL : " + self.url, logger.DEBUG) 
-        return self.opener.open( self.url , 'wb').read()             
-
-    def getQuality(self):
-        return self.quality
+
+	def __init__(self, opener, title, url, quality, audio_langs=None):
+		self.opener = opener
+		self.title = title
+		self.url = url
+		self.quality = quality
+		self.audio_langs=audio_langs    
+
+	def getNZB(self):
+		logger.log(u"XTHOR GETNZB URL : " + self.url, logger.DEBUG) 
+		return self.opener.open( self.url , 'wb').read()             
+
+	def getQuality(self):
+		return self.quality
 
 provider = XTHORProvider()