Skip to content

Commit a18a7df

Browse files
Merge pull request #2 from mercurialworld/main
add /gh user
2 parents d952894 + eac59f0 commit a18a7df

File tree

3 files changed

+99
-2
lines changed

3 files changed

+99
-2
lines changed

bot/src/ghutils/cogs/app_commands/github.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
IssueReference,
3434
PRReference,
3535
)
36-
from ghutils.utils.discord.transformers import FullRepositoryOption
36+
from ghutils.utils.discord.transformers import FullRepositoryOption, UserOption
3737
from ghutils.utils.discord.visibility import MessageVisibility, respond_with_visibility
3838
from ghutils.utils.github import (
3939
CommitCheckState,
@@ -161,6 +161,55 @@ async def repo(
161161

162162
await respond_with_visibility(interaction, visibility, embed=embed)
163163

164+
@app_commands.command()
165+
@l10n.describe_common("visibility")
166+
async def user(
167+
self,
168+
interaction: Interaction,
169+
user: UserOption,
170+
visibility: MessageVisibility = "private",
171+
):
172+
# Use GraphQL to get # of repos starred by user...?
173+
async with self.bot.github_app(interaction) as (github, _):
174+
result = await github.async_graphql(
175+
"""
176+
query($username: String!) {
177+
user(login: $username) {
178+
starredRepositories {
179+
totalCount
180+
}
181+
}
182+
}
183+
""",
184+
{
185+
"username": user.login,
186+
},
187+
)
188+
num_stars: int = result["user"]["starredRepositories"]["totalCount"]
189+
190+
embed = (
191+
Embed(
192+
description=user.bio,
193+
url=user.html_url,
194+
)
195+
.set_thumbnail(url=user.avatar_url)
196+
.add_field(name="Repositories", value=user.public_repos, inline=True)
197+
.add_field(name="Stars", value=num_stars, inline=True)
198+
)
199+
200+
# In case user doesn't have a display name
201+
if user.name is None:
202+
embed.title = user.login
203+
else:
204+
embed.title = user.name
205+
embed.set_author(name=user.login)
206+
207+
embed.set_footer(
208+
text=f"{user.followers} followers • {user.following} following"
209+
)
210+
211+
await respond_with_visibility(interaction, visibility, embed=embed)
212+
164213
@app_commands.command()
165214
async def login(self, interaction: Interaction):
166215
user_id = interaction.user.id

bot/src/ghutils/resources/l10n/en-US/main.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ parameter-description_gh-commit_reference =
3838
command-description_gh-repo =
3939
Get a link to a GitHub repository.
4040
41+
# /gh user
42+
43+
command-description_gh-user =
44+
Get a link to a GitHub user.
45+
4146
# /gh login
4247

4348
command-description_gh-login =

bot/src/ghutils/utils/discord/transformers.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from discord.app_commands.models import Choice
99
from githubkit import Response
1010
from githubkit.exception import GitHubException, RequestFailed
11-
from githubkit.rest import FullRepository
11+
from githubkit.rest import FullRepository, PrivateUser, PublicUser
1212

1313
from ghutils.core.bot import GHUtilsBot
1414
from ghutils.core.types import LoginState
@@ -81,6 +81,49 @@ async def transform(self, interaction: Interaction, value: str):
8181
raise ValueError(f"Failed to get repository: {e}")
8282

8383

84+
class UserTransformer(Transformer):
85+
async def transform(self, interaction: Interaction, value: str):
86+
async with GHUtilsBot.github_app_of(interaction) as (github, _):
87+
try:
88+
return await gh_request(github.rest.users.async_get_by_username(value))
89+
except GitHubException as e:
90+
match e:
91+
case RequestFailed(response=Response(status_code=404)):
92+
raise ValueError("User not found")
93+
case _:
94+
logger.warning(e)
95+
raise ValueError(f"Failed to get user: {e}")
96+
97+
async def autocomplete( # pyright: ignore[reportIncompatibleMethodOverride]
98+
self, interaction: Interaction, value: str
99+
) -> list[Choice[str]]:
100+
async with GHUtilsBot.github_app_of(interaction) as (github, state):
101+
if state != LoginState.LOGGED_IN:
102+
return []
103+
104+
# If no value given, assume the user wants their own profile
105+
if not value:
106+
user = await gh_request(github.rest.users.async_get_authenticated())
107+
return [Choice(name=user.login, value=user.login)]
108+
109+
try:
110+
result = await gh_request(
111+
github.rest.search.async_users(
112+
value,
113+
per_page=25,
114+
)
115+
)
116+
except RequestFailed:
117+
return []
118+
except GitHubException as e:
119+
logger.warning(e)
120+
return []
121+
122+
return [Choice(name=user.login, value=user.login) for user in result.items]
123+
124+
125+
UserOption = Transform[PrivateUser | PublicUser, UserTransformer]
126+
84127
RepositoryNameOption = Transform[RepositoryName, RepositoryNameTransformer]
85128

86129
FullRepositoryOption = Transform[FullRepository, FullRepositoryTransformer]

0 commit comments

Comments
 (0)