def run(self): try: if self.access_token: response = requests.get( 'https://api.github.com/notifications?access_token=' + self.access_token) else: response = requests.get('https://api.github.com/notifications', auth=(self.username, self.password)) data = json.loads(response.text) except (ConnectionError, Timeout) as e: logger.warn(e) data = [] # Bad credentials if isinstance(data, dict): err_msg = data['message'] raise ConfigError(err_msg) format_values = dict(unread_count='', unread='') unread = len(data) if unread > 0: format_values['unread_count'] = unread format_values['unread'] = self.unread_marker self.data = format_values self.output = { 'full_text': self.format.format(**format_values), 'color': self.color }
def run(self): format_values = dict(unread_count='', unread='') response = requests.get('https://api.github.com/notifications', auth=(self.username, self.password)) data = json.loads(response.text) # Bad credentials if isinstance(data, dict): raise ConfigError(data['message']) unread = len(data) if unread > 0: format_values['unread_count'] = unread format_values['unread'] = self.unread_marker self.output = { 'full_text': self.format.format(**format_values), 'color': self.color }
def update_unread(self): # Reset the new_unread attribute to prevent spurious notifications self.new_unread = None try: if not self.username and not self.password and not self.access_token: # Auth not configured self.logger.debug( 'No auth configured, notifications will not be checked') return True if not HAS_REQUESTS: self.logger.error( 'The requests module is required to check GitHub notifications') self.failed_update = True return False self.logger.debug( 'Checking unread notifications using %s', 'access token' if self.access_token else 'username/password' ) if self.access_token: request_kwargs = { 'headers': { 'Authorization': 'token {}'.format(self.access_token), }, } else: request_kwargs = { 'auth': (self.username, self.password), } self.current_unread = set() page_num = 0 old_unread_url = None unread_url = AUTH_URL while old_unread_url != unread_url: old_unread_url = unread_url page_num += 1 self.logger.debug( 'Reading page %d of notifications (%s)', page_num, unread_url ) try: response = requests.get(unread_url, **request_kwargs) self.logger.log( 5, 'Raw return from GitHub notification check: %s', response.text) unread_data = json.loads(response.text) except (requests.ConnectionError, requests.Timeout) as exc: self.logger.error( 'Failed to check unread notifications: %s', exc) self.failed_update = True return False except json.decoder.JSONDecodeError as exc: self.logger.error('Error loading JSON: %s', exc) self.logger.debug( 'JSON text that failed to load: %s', response.text) self.failed_update = True return False # Bad credentials or some other error if isinstance(unread_data, dict): raise ConfigError( unread_data.get( 'message', 'Unknown error encountered retrieving unread notifications' ) ) # Update the current count of unread notifications self.current_unread.update( [x['id'] for x in unread_data if 'id' in x] ) # Check 'Link' header for next page of notifications # (https://tools.ietf.org/html/rfc5988#section-5) self.logger.debug('Checking for next page of notifications') try: link_header = response.headers['Link'] except AttributeError: self.logger.error( 'No headers present in response. This might be due to ' 'an API change in the requests module.' ) self.failed_update = True continue except KeyError: self.logger.debug('Only one page of notifications present') continue else: # Process 'Link' header try: links = requests.utils.parse_header_links(link_header) except Exception as exc: self.logger.error( 'Failed to parse \'Link\' header: %s', exc ) self.failed_update = True continue for link in links: try: link_rel = link['rel'] if link_rel != 'next': # Link does not refer to the next page, skip it continue # Set the unread_url so that when we reach the top # of the outer loop, we have a new URL to check. unread_url = link['url'] break except TypeError: # Malformed hypermedia link self.logger.warning( 'Malformed hypermedia link (%s) in \'Link\' ' 'header (%s)', link, links ) continue else: self.logger.debug('No more pages of notifications remain') if self.failed_update: return False self.data['unread_count'] = len(self.current_unread) self.data['unread'] = self.unread_marker \ if self.data['unread_count'] > 0 \ else '' if self.previous_unread is not None: if not self.current_unread.issubset(self.previous_unread): self.new_unread = self.current_unread - self.previous_unread if self.new_unread: self.show_unread_notification() self.previous_unread = self.current_unread return True except ConfigError as exc: # This will be caught by the calling function raise exc except Exception as exc: # Don't let an uncaught exception kill the update thread self.logger.error( 'Uncaught error occurred while checking GitHub notifications. ' 'Exception follows:', exc_info=True ) self.failed_update = True return False