def getShowImage(url, imgNum=None): if not url: return None # if they provided a fanart number try to use it instead if imgNum is not None: temp_url = url.split("-")[0] + "-" + str(imgNum) + ".jpg" else: temp_url = url logger.debug("Fetching image from " + temp_url) try: image_data = helpers.getURL(temp_url, session=meta_session, returns="content", allow_proxy=settings.PROXY_INDEXERS) except requests.exceptions.RequestException: image_data = None if not image_data: logger.warning( "There was an error trying to retrieve the image, aborting") return return image_data
def _sendBoxcar2(self, msg, title, accesstoken): ''' Sends a boxcar2 notification to the address provided msg: The message to send title: The title of the message accesstoken: to send to this device returns: True if the message succeeded, False otherwise ''' # http://blog.boxcar.io/post/93211745502/boxcar-api-update-boxcar-api-update-icon-and post_data = { 'user_credentials': accesstoken, 'notification[title]': 'SickChill : {0}: {1}'.format(title, msg), 'notification[long_message]': msg, 'notification[sound]': 'notifier-2', 'notification[source_name]': 'SickChill', 'notification[icon_url]': settings.LOGO_URL } response = helpers.getURL(self.url, post_data=post_data, session=self.session, timeout=60, returns='json') if not response: logger.exception('Boxcar2 notification failed.') return False logger.debug('Boxcar2 notification successful.') return True
def _send_telegram_msg(self, title, msg, id=None, api_key=None): """ Sends a Telegram notification :param title: The title of the notification to send :param msg: The message string to send :param id: The Telegram user/group id to send the message to :param api_key: Your Telegram bot API token :returns: True if the message succeeded, False otherwise """ logger.debug('Telegram in use with API KEY: {0}'.format(api_key)) params = { 'chat_id': id or settings.TELEGRAM_ID, 'text': f'{title} : {msg}' } response = getURL( f'https://api.telegram.org/bot{api_key or settings.TELEGRAM_APIKEY}/sendMessage', params=params, session=self.session, returns='json') message = ( 'Telegram message sent successfully.', 'Sending Telegram message failed, check the log')[response is None] logger.info(message) return response is not None, message
def _sendBoxcar2(self, msg, title, accesstoken): """ Sends a boxcar2 notification to the address provided msg: The message to send title: The title of the message accesstoken: to send to this device returns: True if the message succeeded, False otherwise """ # http://blog.boxcar.io/post/93211745502/boxcar-api-update-boxcar-api-update-icon-and post_data = { "user_credentials": accesstoken, "notification[title]": "SickChill : {0}: {1}".format(title, msg), "notification[long_message]": msg, "notification[sound]": "notifier-2", "notification[source_name]": "SickChill", "notification[icon_url]": settings.LOGO_URL, } response = helpers.getURL(self.url, post_data=post_data, session=self.session, timeout=60, returns="json") if not response: logger.exception("Boxcar2 notification failed.") return False logger.debug("Boxcar2 notification successful.") return True
def compare_db_version(self): try: self.need_update() cur_hash = self.get_newest_commit_hash() assert len( cur_hash ) == 40, "Commit hash wrong length: {0} hash: {1}".format( len(cur_hash), cur_hash) check_url = "https://raw.githubusercontent.com/{0}/{1}/{2}/sickchill/oldbeard/databases/main.py" for attempt in (cur_hash, "master"): response = helpers.getURL(check_url.format( settings.GIT_ORG, settings.GIT_REPO, attempt), session=self.session, returns='text') if response: break assert response, "Empty response from {0}".format(check_url) match = re.search(r"MAX_DB_VERSION\s=\s(?P<version>\d{2,3})", response) destination_db_version = int(match.group('version')) main_db_con = db.DBConnection() current_db_version = main_db_con.get_db_version() if destination_db_version > current_db_version: return 'upgrade' elif destination_db_version == current_db_version: return 'equal' else: return 'downgrade' except Exception as e: return repr(e)
def fetch_popular_shows(self): """Get popular show information from IMDB""" popular_shows = [] data = helpers.getURL(self.url, session=self.session, params=self.params, headers={'Referer': self.base_url}, returns='text') if not data: return None soup = BeautifulSoup(data, 'html5lib') results = soup.find_all("div", {"class": "lister-item"}) for row in results: show = {} image_div = row.find("div", {"class": "lister-item-image"}) if image_div: image = image_div.find("img") show['image_url_large'] = self.change_size( image['loadlate'], 3) show['imdb_tt'] = image['data-tconst'] show['image_path'] = posixpath.join( 'images', 'imdb_popular', os.path.basename(show['image_url_large'])) self.cache_image(show['image_url_large']) content = row.find("div", {"class": "lister-item-content"}) if content: header = row.find("h3", {"class": "lister-item-header"}) if header: a_tag = header.find("a") if a_tag: show['name'] = a_tag.get_text(strip=True) show[ 'imdb_url'] = "http://www.imdb.com" + a_tag["href"] show['year'] = header.find("span", { "class": "lister-item-year" }).contents[0].split(" ")[0][1:].strip("-") imdb_rating = row.find("div", {"class": "ratings-imdb-rating"}) show['rating'] = imdb_rating[ 'data-value'] if imdb_rating else None votes = row.find("span", {"name": "nv"}) show['votes'] = votes['data-value'] if votes else None outline = content.find_all("p", {"class": "text-muted"}) if outline and len(outline) >= 2: show['outline'] = outline[1].contents[0].strip("\"") else: show['outline'] = '' popular_shows.append(show) return popular_shows
def get_devices(self, pushbullet_api): logger.debug( "Testing Pushbullet authentication and retrieving the device list." ) headers = {"Access-Token": pushbullet_api} return helpers.getURL(urljoin(self.url, "devices"), session=self.session, headers=headers, returns="text") or {}
def get_channels(self, pushbullet_api): """Fetches the list of channels a given access key has permissions to push to""" logger.debug( "Testing Pushbullet authentication and retrieving the device list." ) headers = {"Access-Token": pushbullet_api} return helpers.getURL(urljoin(self.url, "channels"), session=self.session, headers=headers, returns="text") or {}
def compare_db_version(self): try: self.need_update() newest_version = self.get_newest_commit_hash() if isinstance(newest_version, str): if len(newest_version) != 40: raise UpdaterException( f"Commit hash wrong length: {len(newest_version)} hash: {newest_version}" ) else: newest_version = f"v{newest_version.major}.{newest_version.minor:02d}.{newest_version.micro:02d}-{newest_version.post}" response = helpers.getURL( f"https://raw.githubusercontent.com/{settings.GIT_ORG}/{settings.GIT_REPO}/{newest_version}/sickchill/oldbeard/databases/main.py", session=self.session, returns="text", ) if not response: response = helpers.getURL( f"https://raw.githubusercontent.com/{settings.GIT_ORG}/{settings.GIT_REPO}/master/sickchill/oldbeard/databases/main.py", session=self.session, returns="text", ) if not response: raise UpdaterException( f"Empty response from GitHub for {newest_version}") match = re.search(r"MAX_DB_VERSION\s=\s(?P<version>\d{2,3})", response) destination_db_version = int(match.group("version")) main_db_con = db.DBConnection() current_db_version = main_db_con.get_db_version() if destination_db_version > current_db_version: return "upgrade" elif destination_db_version == current_db_version: return "equal" else: return "downgrade" except Exception as e: return repr(e)
def _sendPushbullet(self, pushbullet_api=None, pushbullet_device=None, pushbullet_channel=None, event=None, message=None, link=None, force=False): if not (settings.USE_PUSHBULLET or force): return False pushbullet_api = pushbullet_api or settings.PUSHBULLET_API pushbullet_device = pushbullet_device or settings.PUSHBULLET_DEVICE pushbullet_channel = pushbullet_channel or settings.PUSHBULLET_CHANNEL logger.debug("Pushbullet event: {0!r}".format(event)) logger.debug("Pushbullet message: {0!r}".format(message)) logger.debug("Pushbullet api: {0!r}".format(pushbullet_api)) logger.debug("Pushbullet devices: {0!r}".format(pushbullet_device)) post_data = { "title": event, "body": message, "type": "link" if link else "note" } if link: post_data["url"] = link headers = {"Access-Token": pushbullet_api} if pushbullet_device: post_data["device_iden"] = pushbullet_device elif pushbullet_channel: post_data["channel_tag"] = pushbullet_channel response = helpers.getURL(urljoin(self.url, "pushes"), session=self.session, post_data=post_data, headers=headers, returns="json") or {} failed = response.pop("error", {}) if failed: logger.warning("Pushbullet notification failed: {0}".format( failed.pop("message"))) else: logger.debug("Pushbullet notification sent.") return False if failed else True
def check_for_new_news(self): """ Checks GitHub for the latest news. returns: str, a copy of the news force: ignored """ # Grab a copy of the news logger.debug('check_for_new_news: Checking GitHub for latest news.') try: news = helpers.getURL(settings.NEWS_URL, session=self.session, returns='text') except Exception: logger.warning( 'check_for_new_news: Could not load news from repo.') news = '' if not news: return '' try: last_read = datetime.datetime.strptime(settings.NEWS_LAST_READ, '%Y-%m-%d') except Exception: last_read = 0 settings.NEWS_UNREAD = 0 found_news = False for match in re.finditer(r'^####\s*(\d{4}-\d{2}-\d{2})\s*####', news, re.M): if not found_news: found_news = True settings.NEWS_LATEST = match.group(1) try: if datetime.datetime.strptime(match.group(1), '%Y-%m-%d') > last_read: settings.NEWS_UNREAD += 1 except Exception: pass return news
def _sendPushbullet( self, pushbullet_api=None, pushbullet_device=None, pushbullet_channel=None, event=None, message=None, link=None, force=False): if not (settings.USE_PUSHBULLET or force): return False pushbullet_api = pushbullet_api or settings.PUSHBULLET_API pushbullet_device = pushbullet_device or settings.PUSHBULLET_DEVICE pushbullet_channel = pushbullet_channel or settings.PUSHBULLET_CHANNEL logger.debug('Pushbullet event: {0!r}'.format(event)) logger.debug('Pushbullet message: {0!r}'.format(message)) logger.debug('Pushbullet api: {0!r}'.format(pushbullet_api)) logger.debug('Pushbullet devices: {0!r}'.format(pushbullet_device)) post_data = { 'title': event, 'body': message, 'type': 'link' if link else 'note' } if link: post_data['url'] = link headers = {'Access-Token': pushbullet_api} if pushbullet_device: post_data['device_iden'] = pushbullet_device elif pushbullet_channel: post_data['channel_tag'] = pushbullet_channel response = helpers.getURL(urljoin(self.url, 'pushes'), session=self.session, post_data=post_data, headers=headers, returns='json') or {} failed = response.pop('error', {}) if failed: logger.warning('Pushbullet notification failed: {0}'.format(failed.pop('message'))) else: logger.debug('Pushbullet notification sent.') return False if failed else True
def get_token(self, username=None, password=None, plex_server_token=None): username = username or settings.PLEX_SERVER_USERNAME password = password or settings.PLEX_SERVER_PASSWORD plex_server_token = plex_server_token or settings.PLEX_SERVER_TOKEN if plex_server_token: self.headers['X-Plex-Token'] = plex_server_token if 'X-Plex-Token' in self.headers: return True if not (username and password): return True logger.debug('PLEX: fetching plex.tv credentials for user: '******'user[login]': username, 'user[password]': password} try: response = getURL('https://plex.tv/users/sign_in.json', post_data=params, headers=self.headers, session=self.session, returns='json', allow_proxy=False) self.headers['X-Plex-Token'] = response['user'][ 'authentication_token'] except Exception as error: self.headers.pop('X-Plex-Token', '') logger.debug( 'PLEX: Error fetching credentials from from plex.tv for user {0}: {1}' .format(username, error)) return 'X-Plex-Token' in self.headers
def get_token(self, username=None, password=None, plex_server_token=None): username = username or settings.PLEX_SERVER_USERNAME password = password or settings.PLEX_SERVER_PASSWORD plex_server_token = plex_server_token or settings.PLEX_SERVER_TOKEN if plex_server_token: self.headers["X-Plex-Token"] = plex_server_token if "X-Plex-Token" in self.headers: return True if not (username and password): return True logger.debug("PLEX: fetching plex.tv credentials for user: "******"user[login]": username, "user[password]": password} try: response = getURL("https://plex.tv/users/sign_in.json", post_data=params, headers=self.headers, session=self.session, returns="json", allow_proxy=False) self.headers["X-Plex-Token"] = response["user"][ "authentication_token"] except Exception as error: self.headers.pop("X-Plex-Token", "") logger.debug( "PLEX: Error fetching credentials from from plex.tv for user {0}: {1}" .format(username, error)) return "X-Plex-Token" in self.headers
def get_url(self, url, post_data=None, params=None, timeout=30, **kwargs): kwargs['hooks'] = {'response': self.get_url_hook} return getURL(url, post_data, params, self.headers, timeout, self.session, **kwargs)
def update_library(self, ep_obj=None, host=None, username=None, password=None, plex_server_token=None, force=False): """Handles updating the Plex Media Server host via HTTP API Plex Media Server currently only supports updating the whole video library and not a specific path. Returns: Returns None for no issue, else a string of host with connection issues """ if not (settings.USE_PLEX_SERVER and settings.PLEX_UPDATE_LIBRARY) and not force: return None host = host or settings.PLEX_SERVER_HOST if not host: logger.debug( 'PLEX: No Plex Media Server host specified, check your settings' ) return False if not self.get_token(username, password, plex_server_token): logger.warning( 'PLEX: Error getting auth token for Plex Media Server, check your settings' ) return False file_location = '' if not ep_obj else ep_obj.location host_list = {x.strip() for x in host.split(',') if x.strip()} hosts_all = hosts_match = {} hosts_failed = set() for cur_host in host_list: url = 'http{0}://{1}/library/sections'.format( ('', 's')[settings.PLEX_SERVER_HTTPS], cur_host) try: xml_response = getURL(url, headers=self.headers, session=self.session, returns='text', verify=False, allow_proxy=False) if not xml_response: logger.warning( 'PLEX: Error while trying to contact Plex Media Server: {0}' .format(cur_host)) hosts_failed.add(cur_host) continue media_container = ElementTree.fromstring(xml_response) except IOError as error: logger.warning( 'PLEX: Error while trying to contact Plex Media Server: {0}' .format(str(error))) hosts_failed.add(cur_host) continue except Exception as error: if 'invalid token' in str(error): logger.warning('PLEX: Please set TOKEN in Plex settings: ') else: logger.warning( 'PLEX: Error while trying to contact Plex Media Server: {0}' .format(str(error))) hosts_failed.add(cur_host) continue sections = media_container.findall('.//Directory') if not sections: logger.debug( 'PLEX: Plex Media Server not running on: {0}'.format( cur_host)) hosts_failed.add(cur_host) continue for section in sections: if 'show' == section.attrib['type']: keyed_host = [(str(section.attrib['key']), cur_host)] hosts_all.update(keyed_host) if not file_location: continue for section_location in section.findall('.//Location'): section_path = re.sub( r'[/\\]+', '/', section_location.attrib['path'].lower()) section_path = re.sub(r'^(.{,2})[/\\]', '', section_path) location_path = re.sub(r'[/\\]+', '/', file_location.lower()) location_path = re.sub(r'^(.{,2})[/\\]', '', location_path) if section_path in location_path: hosts_match.update(keyed_host) if force: return (', '.join(set(hosts_failed)), None)[not len(hosts_failed)] if hosts_match: logger.debug( 'PLEX: Updating hosts where TV section paths match the downloaded show: ' + ', '.join(set(hosts_match))) else: logger.debug('PLEX: Updating all hosts with TV sections: ' + ', '.join(set(hosts_all))) hosts_try = (hosts_match.copy(), hosts_all.copy())[not len(hosts_match)] for section_key, cur_host in hosts_try.items(): url = 'http{0}://{1}/library/sections/{2}/refresh'.format( ('', 's')[settings.PLEX_SERVER_HTTPS], cur_host, section_key) try: getURL(url, headers=self.headers, session=self.session, returns='text', verify=False, allow_proxy=False) except Exception as error: logger.warning( 'PLEX: Error updating library section for Plex Media Server: {0}' .format(str(error))) hosts_failed.add(cur_host) return (', '.join(set(hosts_failed)), None)[not len(hosts_failed)]
def get_devices(self, pushbullet_api): logger.debug('Testing Pushbullet authentication and retrieving the device list.') headers = {'Access-Token': pushbullet_api} return helpers.getURL(urljoin(self.url, 'devices'), session=self.session, headers=headers, returns='text') or {}