Skip to content

Commit

Permalink
Merge pull request #10 from progprnv/patch-2
Browse files Browse the repository at this point in the history
implemented error handling for github profile fetcher
  • Loading branch information
sunithvs authored Dec 21, 2024
2 parents ad6d2e8 + b2d7b57 commit 6e69f48
Showing 1 changed file with 175 additions and 170 deletions.
345 changes: 175 additions & 170 deletions modules/github_fetcher.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from collections import Counter
from datetime import datetime, timedelta

import requests

from config.settings import Settings
from modules.github_projects import GitHubProjectRanker

Expand All @@ -21,120 +19,118 @@ def fetch_user_profile(username):
Returns:
dict: Comprehensive user profile data
"""
try:
one_year_ago = (datetime.now() - timedelta(days=365)).isoformat() + 'Z'

one_year_ago = (datetime.now() - timedelta(days=365)).isoformat() + 'Z'

graphql_query = {
"query": f"""
query {{
user(login: "{username}") {{
# Basic user information
name
bio
location
avatarUrl
url
followers {{
totalCount
}}
following {{
totalCount
}}
repositories(first: 100, orderBy: {{field: UPDATED_AT, direction: DESC}}) {{
totalCount
nodes {{
graphql_query = {
"query": f"""
query {{
user(login: "{username}") {{
name
description
stargazerCount
primaryLanguage {{
name
}}
bio
location
avatarUrl
url
updatedAt
}}
}}
# Contributions and achievements
contributionsCollection(from: "{one_year_ago}") {{
contributionCalendar {{
totalContributions
}}
# These fields will help filter issues and repositories
pullRequestContributionsByRepository {{
repository {{
name
followers {{
totalCount
}}
contributions(first: 100) {{
following {{
totalCount
}}
}}
issueContributionsByRepository {{
repository {{
name
repositories(first: 100, orderBy: {{field: UPDATED_AT, direction: DESC}}) {{
totalCount
nodes {{
name
description
stargazerCount
primaryLanguage {{
name
}}
url
updatedAt
}}
}}
contributions(first: 100) {{
contributionsCollection(from: "{one_year_ago}") {{
contributionCalendar {{
totalContributions
}}
pullRequestContributionsByRepository {{
repository {{
name
}}
contributions(first: 100) {{
totalCount
}}
}}
issueContributionsByRepository {{
repository {{
name
}}
contributions(first: 100) {{
totalCount
}}
}}
}}
pullRequests(first: 0, states: MERGED, orderBy: {{field: UPDATED_AT, direction: DESC}}) {{
totalCount
}}
issues(first: 0, states: CLOSED) {{
totalCount
}}
repositoriesContributedTo(first: 100, contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) {{
totalCount
nodes {{
name
}}
}}
}}
}}
"""
}

# Pull Requests and Issues
pullRequests(first: 0, states: MERGED, orderBy: {{field: UPDATED_AT, direction: DESC}}) {{
totalCount
}}
graphql_url = "https://api.github.com/graphql"
graphql_response = requests.post(
graphql_url,
headers={
"Authorization": f"Bearer {Settings.get_github_token()}",
"Content-Type": "application/json"
},
json=graphql_query
)
graphql_response.raise_for_status()

graphql_data = graphql_response.json().get('data', {}).get('user', {})
if not graphql_data:
raise ValueError(f"User '{username}' not found or query returned no data.")

featured = GitHubProjectRanker().get_featured(username)
return {
'username': username,
'name': graphql_data.get('name', username),
'bio': graphql_data.get('bio', ''),
'location': graphql_data.get('location', ''),
'avatar_url': graphql_data.get('avatarUrl', ''),
'profile_url': graphql_data.get('url', ''),
'top_languages': featured['top_languages'],
'top_projects': featured['top_projects'],
'followers': graphql_data['followers']['totalCount'],
'following': graphql_data['following']['totalCount'],
'public_repos': graphql_data['repositories']['totalCount'],
'pull_requests_merged': graphql_data['pullRequests']['totalCount'],
'issues_closed': graphql_data['issues']['totalCount'],
'achievements': {
'total_contributions': graphql_data['contributionsCollection']['contributionCalendar']['totalContributions'],
'repositories_contributed_to': graphql_data['repositoriesContributedTo']['totalCount'],
},
'social_accounts': GitHubProfileFetcher.social_accounts(username)
}

issues(first: 0, states: CLOSED) {{
totalCount
}}
repositoriesContributedTo(first: 100, contributionTypes: [COMMIT, ISSUE, PULL_REQUEST, REPOSITORY]) {{
totalCount
nodes {{
name
}}
}}
}}
}}
"""
}

# Single GraphQL request to fetch most of the data
graphql_url = "https://api.github.com/graphql"
graphql_response = requests.post(
graphql_url,
headers={
"Authorization": f"Bearer {Settings.get_github_token()}",
"Content-Type": "application/json"
},
json=graphql_query
)

graphql_response.raise_for_status()
graphql_data = graphql_response.json()['data']['user']
featured = GitHubProjectRanker().get_featured(username)
return {
'username': username,
'name': graphql_data.get('name', username) or username,
'bio': graphql_data.get('bio', ''),
'location': graphql_data.get('location', ''),
'avatar_url': graphql_data.get('avatarUrl', ''),
'profile_url': graphql_data.get('url', ''),
'top_languages': featured['top_languages'],
'top_projects': featured['top_projects'],
'followers': graphql_data['followers']['totalCount'],
'following': graphql_data['following']['totalCount'],
'public_repos': graphql_data['repositories']['totalCount'],

# Metrics from GraphQL data
'pull_requests_merged': graphql_data['pullRequests']['totalCount'],
'issues_closed': graphql_data['issues']['totalCount'],
'achievements': {
'total_contributions': graphql_data['contributionsCollection']['contributionCalendar'][
'totalContributions'],
'repositories_contributed_to': graphql_data['repositoriesContributedTo']['totalCount'],
},
'social_accounts': GitHubProfileFetcher.social_accounts(username)
}
except requests.exceptions.HTTPError as e:
return {"error": f"HTTP Error: {e.response.status_code} - {e.response.reason}"}
except requests.exceptions.RequestException as e:
return {"error": f"Request failed: {str(e)}"}
except Exception as e:
return {"error": f"An unexpected error occurred: {str(e)}"}

@staticmethod
def fetch_user_profile_rest(username):
Expand All @@ -147,60 +143,64 @@ def fetch_user_profile_rest(username):
Returns:
dict: Comprehensive user profile data
"""
base_url = f"https://api.github.com/users/{username}"

# Fetch user details
user_response = requests.get(
base_url,
headers={
"Accept": "application/vnd.github.v3+json",
"Authorization": f"token {Settings.get_github_token()}",
}
)
user_response.raise_for_status()
user_data = user_response.json()

# Fetch repositories
repos_response = requests.get(
user_data['repos_url'],
headers={
"Accept": "application/vnd.github.v3+json",
"Authorization": f"token {Settings.get_github_token()}",
try:
base_url = f"https://api.github.com/users/{username}"

user_response = requests.get(
base_url,
headers={
"Accept": "application/vnd.github.v3+json",
"Authorization": f"token {Settings.get_github_token()}",
}
)
user_response.raise_for_status()
user_data = user_response.json()

repos_response = requests.get(
user_data['repos_url'],
headers={
"Accept": "application/vnd.github.v3+json",
"Authorization": f"token {Settings.get_github_token()}",
}
)
repos_response.raise_for_status()
repos_data = repos_response.json()

languages = Counter()
recent_projects = []
for repo in repos_data:
if repo.get('language'):
languages[repo['language']] += 1
recent_projects.append({
'name': repo['name'],
'description': repo.get('description', ''),
'stars': repo['stargazers_count'],
'url': repo['html_url'],
'updated_at': repo['updated_at']
})

recent_projects.sort(key=lambda x: datetime.strptime(x['updated_at'], '%Y-%m-%dT%H:%M:%SZ'), reverse=True)

return {
'username': username,
'name': user_data.get('name', username),
'bio': user_data.get('bio', ''),
'location': user_data.get('location', ''),
'avatar_url': user_data.get('avatar_url', ''),
'profile_url': user_data.get('html_url', ''),
'top_languages': languages.most_common(3),
'recent_projects': recent_projects[:5],
'followers': user_data.get('followers', 0),
'following': user_data.get('following', 0),
'public_repos': user_data.get('public_repos', 0)
}
)
repos_response.raise_for_status()
repos_data = repos_response.json()

# Process languages and projects
languages = Counter()
recent_projects = []
for repo in repos_data:
if repo.get('language'):
languages[repo['language']] += 1
recent_projects.append({
'name': repo['name'],
'description': repo.get('description', ''),
'stars': repo['stargazers_count'],
'url': repo['html_url'],
'updated_at': repo['updated_at']
})

# Sort projects date
recent_projects.sort(key=lambda x: datetime.strptime(x['updated_at'], '%Y-%m-%dT%H:%M:%SZ'), reverse=True)

return {
'username': username,
'name': user_data.get('name', username),
'bio': user_data.get('bio', ''),
'location': user_data.get('location', ''),
'avatar_url': user_data.get('avatar_url', ''),
'profile_url': user_data.get('html_url', ''),
'top_languages': languages.most_common(3),
'recent_projects': recent_projects[:5],
'followers': user_data.get('followers', 0),
'following': user_data.get('following', 0),
'public_repos': user_data.get('public_repos', 0)
}

except requests.exceptions.HTTPError as e:
return {"error": f"HTTP Error: {e.response.status_code} - {e.response.reason}"}
except requests.exceptions.RequestException as e:
return {"error": f"Request failed: {str(e)}"}
except Exception as e:
return {"error": f"An unexpected error occurred: {str(e)}"}

@staticmethod
def social_accounts(username):
Expand All @@ -213,17 +213,22 @@ def social_accounts(username):
Returns:
dict: Social accounts of the user
"""
base_url = f"https://api.github.com/users/{username}/social_accounts"

# Fetch user details
user_response = requests.get(
base_url,
headers={
"Accept": "application/vnd.github.v3+json",
"Authorization": f"token {Settings.get_github_token()}",
}
)
user_response.raise_for_status()
user_data = user_response.json()

return user_data
try:
base_url = f"https://api.github.com/users/{username}/social_accounts"

user_response = requests.get(
base_url,
headers={
"Accept": "application/vnd.github.v3+json",
"Authorization": f"token {Settings.get_github_token()}",
}
)
user_response.raise_for_status()
return user_response.json()

except requests.exceptions.HTTPError as e:
return {"error": f"HTTP Error: {e.response.status_code} - {e.response.reason}"}
except requests.exceptions.RequestException as e:
return {"error": f"Request failed: {str(e)}"}
except Exception as e:
return {"error": f"An unexpected error occurred: {str(e)}"}

0 comments on commit 6e69f48

Please sign in to comment.