gitmon/gitmon/api.py

101 lines
3.1 KiB
Python

"""GitHub API module"""
import requests
from datetime import datetime
from time import sleep
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
from loguru import logger
from .logger import setup_logger
setup_logger()
class GitHubApi:
def __init__(self, token=None, headers=None, proxy=None):
"""Initialize the GitHubApi instance.
Args:
token (str, optional): GitHub API token.
headers (dict, optional): Additional headers to include in API requests.
proxy (dict, optional): Proxy information.
"""
self.base_url = 'https://api.github.com'
self.session = requests.Session()
retries = Retry(total=3, backoff_factor=1)
self.session.mount('https://', HTTPAdapter(max_retries=retries))
if token:
self.session.headers.update({'Authorization': f'Bearer {token}'})
if headers:
self.session.headers.update(headers)
if proxy:
self.session.proxies.update(proxy)
# Rate limits
self.rate_reset = None
self.rate_remaining = None
def __get(self, endpoint, params=None):
"""Send a GET request to the GitHub API and return the JSON response.
Args:
endpoint (str): The API endpoint.
params (dict, optional): Query parameters for the request.
Returns:
dict: The JSON response from the API.
"""
url = self.base_url + endpoint
# Check rate limits and sleep if exceeded
if self.rate_remaining == 0 and self.rate_reset > datetime.now():
logger.warning(f'Out of API calls. Sleeping until {self.rate_reset}.')
delta = self.rate_reset - datetime.now()
sleep(delta.total_seconds())
try:
response = self.session.get(url, params=params)
except requests.RequestException as e:
logger.warning(f'Failed to execute GET request: {str(e)}')
return None
self.__parse_headers(response.headers)
return response.json()
def __parse_headers(self, headers):
"""Parse the response headers to update the rate limit information.
Args:
headers (dict): The response headers from the GitHub API.
"""
try:
self.rate_reset = datetime.fromtimestamp(int(headers['x-ratelimit-reset']))
self.rate_remaining = int(headers['x-ratelimit-remaining'])
logger.info(f'{self.rate_remaining} calls remaining until {self.rate_reset} ({self.rate_reset - datetime.now()})')
except KeyError as e:
logger.warning(f'Could not parse headers: {str(e)}')
def get_events(self, page=None):
"""Fetch GitHub events.
Args:
page (int, optional): The page number of events to retrieve.
Returns:
dict: The JSON response containing the events.
"""
endpoint = '/events'
params = None
if page:
params = {'page': page}
events = self.__get(endpoint, params)
return events