diff --git a/.build/bower.json b/.build/bower.json
index e9a78d46ac93ce8ebb4983e0f39277a43e4ab102..ecbd37d1a176433864df18c5b7a47957d5167861 100644
--- a/.build/bower.json
+++ b/.build/bower.json
@@ -25,5 +25,8 @@
     "jquery-confirm": "~2.5.2",
     "bootstrap-formhelpers": "~2.3.0",
     "isotope": "~2.2.2"
+  },
+  "resolutions": {
+    "bootstrap": "~3.3.5"
   }
 }
diff --git a/.build/package.json b/.build/package.json
index a0a4b41183e254ed37b997591865458798311451..6cd6e05d1d190a93b4f0d75d71fa66b4e56de98c 100644
--- a/.build/package.json
+++ b/.build/package.json
@@ -2,9 +2,10 @@
   "name": "sickrage",
   "version": "4.0.72",
   "private": true,
-  "dependencies": {
+  "devDependencies": {
     "grunt": "^0.4.5",
     "grunt-bower-concat": "^0.5.0",
+    "grunt-cli": "^0.1.13",
     "grunt-contrib-cssmin": "^0.14.0",
     "grunt-contrib-jshint": "^0.11.3",
     "grunt-contrib-uglify": "^0.9.2"
diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py
index a58eb83eb77aba944e44fb38f465cd236e5789a7..68a714dfd2ddba7aabe6d83fa45235580c115d4f 100644
--- a/sickbeard/__init__.py
+++ b/sickbeard/__init__.py
@@ -136,7 +136,7 @@ GIT_AUTOISSUES = False
 GIT_NEWVER = False
 DEVELOPER = False
 
-NEWS_URL = 'http://SickRage.github.io/sickrage-news/news.md'
+NEWS_URL = 'http://sickrage.github.io/sickrage-news/news.md'
 NEWS_LAST_READ = None
 NEWS_LATEST = None
 NEWS_UNREAD = 0
diff --git a/sickbeard/helpers.py b/sickbeard/helpers.py
index 2f35739bb0c5ee689cb06cf3d0ba6290b7f3b04a..6e3cbac62d1307a908ff57aba567752a79e38e71 100644
--- a/sickbeard/helpers.py
+++ b/sickbeard/helpers.py
@@ -1559,7 +1559,7 @@ def _setUpSession(session, headers):
     session = CacheControl(sess=session, cache=caches.FileCache(os.path.join(cache_dir, 'sessions'), use_dir_lock=True), cache_etags=False)
 
     # request session clear residual referer
-    if 'Referer' in session.headers and 'Referer' not in headers or {}:
+    if 'Referer' in session.headers and 'Referer' not in (headers or {}):
         session.headers.pop('Referer')
 
     # request session headers
diff --git a/sickbeard/network_timezones.py b/sickbeard/network_timezones.py
index 78a9278693abe0abe64a6b0ec82fb37f4e0a1a4d..82f91f3fcfb56ac443cf1a36cc4ab2e77897d9ae 100644
--- a/sickbeard/network_timezones.py
+++ b/sickbeard/network_timezones.py
@@ -38,7 +38,7 @@ sb_timezone = tz.tzwinlocal() if tz.tzwinlocal else tz.tzlocal()
 def update_network_dict():
     """Update timezone information from SR repositories"""
 
-    url = 'http://SickRage.github.io/sb_network_timezones/network_timezones.txt'
+    url = 'http://sickrage.github.io/sb_network_timezones/network_timezones.txt'
     url_data = helpers.getURL(url, session=requests.Session())
     if not url_data:
         logger.log(u'Updating network timezones failed, this can happen from time to time. URL: %s' % url, logger.WARNING)
diff --git a/sickbeard/postProcessor.py b/sickbeard/postProcessor.py
index 598f28590a22e43e1f26ddf00e2eb46909a7d97d..1cd7afa6aa66f8b64fb2128e4c4bed4f6cd76f7d 100644
--- a/sickbeard/postProcessor.py
+++ b/sickbeard/postProcessor.py
@@ -39,6 +39,7 @@ from sickbeard.name_parser.parser import NameParser, InvalidNameException, Inval
 from sickrage.helper.encoding import ek
 from sickrage.helper.exceptions import EpisodeNotFoundException, EpisodePostProcessingFailedException, ex
 from sickrage.helper.exceptions import ShowDirectoryNotFoundException
+from babelfish import language_converters
 
 import adba
 from sickbeard.helpers import verify_freespace
@@ -190,10 +191,17 @@ class PostProcessor(object):
             checklist = glob.glob(ek(os.path.join, ek(os.path.dirname, globbable_file_path), '*')) # get a list of all the files in the folder
             for filefound in checklist: # loop through all the files in the folder, and check if they are the same name even when the cases don't match
                 file_name = filefound.rpartition('.')[0]
+                file_extension = filefound.rpartition('.')[2]
                 if not base_name_only:
-                    file_name = file_name + '.'
-                if file_name.lower() == base_name.lower().replace('[[]', '[').replace('[]]', ']'): # if there's no difference in the filename add it to the filelist
+                    new_file_name = file_name + '.'
+                if new_file_name.lower() == base_name.lower().replace('[[]', '[').replace('[]]', ']'): # if there's no difference in the filename add it to the filelist
                     filelist.append(filefound)
+                elif file_extension in common.subtitleExtensions:
+                    language_extensions = tuple('.' + c for c in language_converters['opensubtitles'].codes)
+                    if file_name.lower().endswith(language_extensions) and (len(filefound.rsplit('.', 2)[1]) is 2 or 3):
+                        filelist.append(filefound)
+                    elif file_name.lower().endswith('pt-br') and len(filefound.rsplit('.', 2)[1]) is 5:
+                        filelist.append(filefound)
 
         for associated_file_path in filelist:
             # only add associated to list
@@ -299,7 +307,10 @@ class PostProcessor(object):
             # check if file have subtitles language
             if os.path.splitext(cur_extension)[1][1:] in common.subtitleExtensions:
                 cur_lang = os.path.splitext(cur_extension)[0]
-                if cur_lang in sickbeard.subtitles.wantedLanguages():
+                if cur_lang:
+                    cur_lang = cur_lang.lower()
+                    if cur_lang == 'pt-br':
+                        cur_lang = 'pt-BR'
                     cur_extension = cur_lang + os.path.splitext(cur_extension)[1]
 
             # replace .nfo with .nfo-orig to avoid conflicts
@@ -313,7 +324,7 @@ class PostProcessor(object):
             else:
                 new_file_name = helpers.replaceExtension(cur_file_name, cur_extension)
 
-            if sickbeard.SUBTITLES_DIR and cur_extension in common.subtitleExtensions:
+            if sickbeard.SUBTITLES_DIR and cur_extension[-3:] in common.subtitleExtensions:
                 subs_new_path = ek(os.path.join, new_path, sickbeard.SUBTITLES_DIR)
                 dir_exists = helpers.makeDir(subs_new_path)
                 if not dir_exists:
diff --git a/sickbeard/providers/bluetigers.py b/sickbeard/providers/bluetigers.py
index 4c431edac135f07eee683b7782df652feda87182..bbe6e3f6e4b6324ba79b42e31d2032c8e96f10f7 100644
--- a/sickbeard/providers/bluetigers.py
+++ b/sickbeard/providers/bluetigers.py
@@ -83,6 +83,10 @@ class BLUETIGERSProvider(generic.TorrentProvider):
 
         results = []
         items = {'Season': [], 'Episode': [], 'RSS': []}
+        
+        # check for auth
+        if not self._doLogin():
+            return results
 
         for mode in search_strings.keys():
             logger.log(u"Search Mode: %s" % mode, logger.DEBUG)
diff --git a/sickbeard/providers/kat.py b/sickbeard/providers/kat.py
index 0168c132268e8ce7744b95655d32792c2f55588a..7b097de4bec31582ae8e048a1c974b236db9fc41 100755
--- a/sickbeard/providers/kat.py
+++ b/sickbeard/providers/kat.py
@@ -47,8 +47,8 @@ class KATProvider(generic.TorrentProvider):
         self.cache = KATCache(self)
 
         self.urls = {
-            'base_url': 'https://kickass.unblocked.la/',
-            'search': 'https://kickass.unblocked.la/%s/',
+            'base_url': 'https://kickass.unblocked.pe/',
+            'search': 'https://kickass.unblocked.pe/%s/',
         }
 
         self.url = self.urls['base_url']
diff --git a/sickbeard/providers/newpct.py b/sickbeard/providers/newpct.py
index ad1dd5412b1d4da7079fc73b8e25ad349aef0284..0985f73ce75456c0c0533597e4d23e555574c0c5 100644
--- a/sickbeard/providers/newpct.py
+++ b/sickbeard/providers/newpct.py
@@ -1,3 +1,4 @@
+# coding=utf-8
 # Author: CristianBB
 # Greetings to Mr. Pine-apple
 #
@@ -13,18 +14,19 @@
 # SickRage is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#  GNU General Public License for more details.
+# GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
 # along with SickRage.  If not, see <http://www.gnu.org/licenses/>.
 
 import traceback
+import re
 from six.moves import urllib
 
+from sickbeard import helpers
 from sickbeard import logger
 from sickbeard import tvcache
 from sickbeard.providers import generic
-from sickbeard.common import USER_AGENT
 from sickbeard.bs4_parser import BS4Parser
 
 
@@ -37,13 +39,16 @@ class newpctProvider(generic.TorrentProvider):
         self.onlyspasearch = None
         self.cache = newpctCache(self)
 
+        # Unsupported
+        # self.minseed = None
+        # self.minleech = None
+
         self.urls = {
             'base_url': 'http://www.newpct.com',
             'search': 'http://www.newpct.com/buscar-descargas/'
         }
 
         self.url = self.urls['base_url']
-        self.headers.update({'User-Agent': USER_AGENT})
 
         """
         Search query:
@@ -71,14 +76,14 @@ class newpctProvider(generic.TorrentProvider):
             'q': ''
         }
 
+
     def _doSearch(self, search_strings, search_mode='eponly', epcount=0, age=0, epObj=None):
 
         results = []
         items = {'Season': [], 'Episode': [], 'RSS': []}
 
-        lang_info = '' if not epObj or not epObj.show else epObj.show.lang
-
         # Only search if user conditions are true
+        lang_info = '' if not epObj or not epObj.show else epObj.show.lang
         if self.onlyspasearch and lang_info != 'es':
             logger.log(u"Show info is not spanish, skipping provider search", logger.DEBUG)
             return results
@@ -87,6 +92,9 @@ class newpctProvider(generic.TorrentProvider):
             logger.log(u"Search Mode: %s" % mode, logger.DEBUG)
 
             for search_string in search_strings[mode]:
+                if mode is not 'RSS':
+                    logger.log(u"Search string: %s " % search_string, logger.DEBUG)
+
                 self.search_params.update({'q': search_string.strip()})
 
                 logger.log(u"Search URL: %s" % self.urls['search'] + '?' + urllib.parse.urlencode(self.search_params), logger.DEBUG)
@@ -98,42 +106,90 @@ class newpctProvider(generic.TorrentProvider):
                     with BS4Parser(data, features=["html5lib", "permissive"]) as html:
                         torrent_tbody = html.find('tbody')
 
-                        if len(torrent_tbody) < 1:
+                        if not len(torrent_tbody):
                             logger.log(u"Data returned from provider does not contain any torrents", logger.DEBUG)
                             continue
 
                         torrent_table = torrent_tbody.findAll('tr')
-                        num_results = len(torrent_table) - 1
+                        if not len(torrent_table):
+                            logger.log(u"Torrent table does not have any rows", logger.DEBUG)
+                            continue
 
-                        iteration = 0
-                        for row in torrent_table:
+                        for row in torrent_table[:-1]:
                             try:
-                                if iteration < num_results:
-                                    torrent_size = row.findAll('td')[2]
-                                    torrent_row = row.findAll('a')[1]
-
-                                    download_url = torrent_row.get('href')
-                                    title_raw = torrent_row.get('title')
-                                    size = self._convertSize(torrent_size.text)
+                                torrent_size = row.findAll('td')[2]
+                                torrent_row = row.findAll('a')[0]
 
-                                    title = self._processTitle(title_raw)
+                                download_url = torrent_row.get('href', '')
+                                size = self._convertSize(torrent_size.text)
+                                title = self._processTitle(torrent_row.get('title', ''))
 
-                                    item = title, download_url, size
-                                    logger.log(u"Found result: %s " % title, logger.DEBUG)
-
-                                    items[mode].append(item)
-                                    iteration += 1
+                                # FIXME: Provider does not provide seeders/leechers
+                                seeders = 1
+                                leechers = 0
 
                             except (AttributeError, TypeError):
                                 continue
 
+                            if not all([title, download_url]):
+                                continue
+
+                            # Filter unseeded torrent (Unsupported)
+                            # if seeders < self.minseed or leechers < self.minleech:
+                            #     if mode is not 'RSS':
+                            #         logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(title, seeders, leechers), logger.DEBUG)
+                            #     continue
+
+                            item = title, download_url, size, seeders, leechers
+                            if mode is not 'RSS':
+                                logger.log(u"Found result: %s " % title, logger.DEBUG)
+
+                            items[mode].append(item)
+
                 except Exception:
                     logger.log(u"Failed parsing provider. Traceback: %s" % traceback.format_exc(), logger.WARNING)
 
+            # For each search mode sort all the items by seeders if available (Unsupported)
+            # items[mode].sort(key=lambda tup: tup[3], reverse=True)
+
             results += items[mode]
 
         return results
 
+    def downloadResult(self, result):
+        """
+        Save the result to disk.
+        """
+
+        # check for auth
+        if not self._doLogin():
+            return False
+
+        urls, filename = self._makeURL(result)
+
+        for url in urls:
+            # Search results don't return torrent files directly, it returns show sheets so we must parse showSheet to access torrent.
+            data = self.getURL(url)
+            url_torrent = re.search(r'http://tumejorserie.com/descargar/.+\.torrent', data, re.DOTALL).group()
+
+            if url_torrent.startswith('http'):
+                self.headers.update({'Referer': '/'.join(url_torrent.split('/')[:3]) + '/'})
+
+            logger.log(u"Downloading a result from " + self.name + " at " + url)
+
+            if helpers.download_file(url_torrent, filename, session=self.session, headers=self.headers):
+                if self._verify_download(filename):
+                    logger.log(u"Saved result to " + filename, logger.INFO)
+                    return True
+                else:
+                    logger.log(u"Could not download %s" % url, logger.WARNING)
+                    helpers.remove_file_failed(filename)
+
+        if len(urls):
+            logger.log(u"Failed to download any results", logger.WARNING)
+
+        return False
+
     @staticmethod
     def _convertSize(size):
         size, modifier = size.split(' ')
@@ -148,9 +204,12 @@ class newpctProvider(generic.TorrentProvider):
             size = size * 1024**4
         return int(size)
 
-    def _processTitle(self, title):
 
-        title = title.replace('Descargar ', '')
+    @staticmethod
+    def _processTitle(title):
+
+        # Remove "Mas informacion sobre " literal from title
+        title = title[22:]
 
         # Quality
         title = title.replace('[HDTV]', '[720p HDTV x264]')
@@ -169,8 +228,7 @@ class newpctProvider(generic.TorrentProvider):
         title = title.replace('[BluRay MicroHD]', '[1080p BlueRay x264]')
         title = title.replace('[MicroHD 1080p]', '[1080p BlueRay x264]')
 
-        return title
-
+        return title.strip()
 
 
 class newpctCache(tvcache.TVCache):
@@ -178,8 +236,11 @@ class newpctCache(tvcache.TVCache):
 
         tvcache.TVCache.__init__(self, provider_obj)
 
-        self.minTime = 30
+        # set this 0 to suppress log line, since we aren't updating it anyways
+        self.minTime = 0
 
+    def _getRSSData(self):
+        return {'entries': []}
 
 
 provider = newpctProvider()
diff --git a/sickbeard/providers/thepiratebay.py b/sickbeard/providers/thepiratebay.py
index c9dd88e0362489ec066bd16661932574907e5e16..aba4c0b2ed1997f8b8c497597a9a9766d8f2e16a 100644
--- a/sickbeard/providers/thepiratebay.py
+++ b/sickbeard/providers/thepiratebay.py
@@ -42,9 +42,9 @@ class ThePirateBayProvider(generic.TorrentProvider):
         self.cache = ThePirateBayCache(self)
 
         self.urls = {
-            'base_url': 'https://pirateproxy.la/',
-            'search': 'https://pirateproxy.la/s/',
-            'rss': 'https://pirateproxy.la/tv/latest'
+            'base_url': 'https://pirateproxy.pl/',
+            'search': 'https://pirateproxy.pl/s/',
+            'rss': 'https://pirateproxy.pl/tv/latest'
         }
 
         self.url = self.urls['base_url']
@@ -52,7 +52,7 @@ class ThePirateBayProvider(generic.TorrentProvider):
 
         """
         205 = SD, 208 = HD, 200 = All Videos
-        https://thepiratebay.gd/s/?q=Game of Thrones&type=search&orderby=7&page=0&category=200
+        https://pirateproxy.pl/s/?q=Game of Thrones&type=search&orderby=7&page=0&category=200
         """
         self.search_params = {
             'q': '',
diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py
index 1d566da15b826afc308bc63724b71a2e06322df8..c35ab144898ce169d9cfd2fee6840a69b84f7804 100644
--- a/sickbeard/webserve.py
+++ b/sickbeard/webserve.py
@@ -2161,10 +2161,10 @@ class HomeChangeLog(Home):
 
     def index(self):
         try:
-            changes = helpers.getURL('http://SickRage.github.io/sickrage-news/CHANGES.md', session=requests.Session())
+            changes = helpers.getURL('http://sickrage.github.io/sickrage-news/CHANGES.md', session=requests.Session())
         except Exception:
             logger.log(u'Could not load changes from repo, giving a link!', logger.DEBUG)
-            changes = 'Could not load changes from the repo. [Click here for CHANGES.md](http://SickRage.github.io/sickrage-news/CHANGES.md)'
+            changes = 'Could not load changes from the repo. [Click here for CHANGES.md](http://sickrage.github.io/sickrage-news/CHANGES.md)'
 
         t = PageTemplate(rh=self, filename="markdown.mako")
         data = markdown2.markdown(changes if changes else "The was a problem connecting to github, please refresh and try again", extras=['header-ids'])
@@ -2512,6 +2512,7 @@ class HomeAddShows(Home):
         try:
             popular_shows = imdb_popular.fetch_popular_shows()
         except Exception as e:
+            # print traceback.format_exc()
             popular_shows = None
 
         return t.render(title="Popular Shows", header="Popular Shows", popular_shows=popular_shows, imdb_exception=e, topmenu="home")