101 lines
3.1 KiB
Python
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
|