示例#1
0
    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
        }
示例#2
0
    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
        }
示例#3
0
    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