diff --git a/jarvis/cogs/gitlab.py b/jarvis/cogs/gl.py similarity index 83% rename from jarvis/cogs/gitlab.py rename to jarvis/cogs/gl.py index 074a33f..cdd08a4 100644 --- a/jarvis/cogs/gitlab.py +++ b/jarvis/cogs/gl.py @@ -1,16 +1,20 @@ """J.A.R.V.I.S. GitLab Cog.""" +import asyncio from datetime import datetime import gitlab from dis_snek import InteractionContext, Scale, Snake from dis_snek.ext.paginators import Paginator from dis_snek.models.discord.embed import Embed, EmbedField +from dis_snek.models.discord.modal import InputText, Modal, TextStyles from dis_snek.models.snek.application_commands import ( OptionTypes, SlashCommandChoice, slash_command, slash_option, ) +from dis_snek.models.snek.command import cooldown +from dis_snek.models.snek.cooldowns import Buckets from jarvis.config import get_config from jarvis.utils import build_embed @@ -29,7 +33,11 @@ class GitlabCog(Scale): self.project = self._gitlab.projects.get(29) @slash_command( - name="gl", sub_cmd_name="issue", description="Get an issue from GitLab", scopes=guild_ids + name="gl", + description="Get GitLab info", + sub_cmd_name="issue", + sub_cmd_description="Get an issue from GitLab", + scopes=guild_ids, ) @slash_option(name="id", description="Issue ID", opt_type=OptionTypes.INTEGER, required=True) async def _issue(self, ctx: InteractionContext, id: int) -> None: @@ -96,7 +104,7 @@ class GitlabCog(Scale): @slash_command( name="gl", sub_cmd_name="milestone", - description="Get a milestone from GitLab", + sub_cmd_description="Get a milestone from GitLab", scopes=guild_ids, ) @slash_option( @@ -152,7 +160,7 @@ class GitlabCog(Scale): @slash_command( name="gl", sub_cmd_name="mr", - description="Get a merge request from GitLab", + sub_cmd_description="Get a merge request from GitLab", scopes=guild_ids, ) @slash_option( @@ -181,25 +189,26 @@ class GitlabCog(Scale): labels = "None" fields = [ - EmbedField(name="State", value=mr.state[0].upper() + mr.state[1:]), - EmbedField(name="Assignee", value=assignee), - EmbedField(name="Labels", value=labels), + EmbedField(name="State", value=mr.state[0].upper() + mr.state[1:], inline=True), + EmbedField(name="Draft?", value=str(mr.draft), inline=True), + EmbedField(name="Assignee", value=assignee, inline=True), + EmbedField(name="Labels", value=labels, inline=True), ] if mr.labels: color = self.project.labels.get(mr.labels[0]).color else: color = "#00FFEE" - fields.append(EmbedField(name="Created At", value=created_at)) + fields.append(EmbedField(name="Created At", value=created_at, inline=True)) if mr.state == "merged": merged_at = datetime.strptime(mr.merged_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime( "%Y-%m-%d %H:%M:%S UTC" ) - fields.append(EmbedField(name="Merged At", value=merged_at)) + fields.append(EmbedField(name="Merged At", value=merged_at, inline=True)) elif mr.state == "closed": closed_at = datetime.strptime(mr.closed_at, "%Y-%m-%dT%H:%M:%S.%fZ").strftime( "%Y-%m-%d %H:%M:%S UTC" ) - fields.append(EmbedField(name="Closed At", value=closed_at)) + fields.append(EmbedField(name="Closed At", value=closed_at, inline=True)) if mr.milestone: fields.append( EmbedField( @@ -261,7 +270,10 @@ class GitlabCog(Scale): return embed @slash_command( - name="gl", sub_cmd_name="issues", description="Get issues from GitLab", scopes=guild_ids + name="gl", + sub_cmd_name="issues", + sub_cmd_description="Get issues from GitLab", + scopes=guild_ids, ) @slash_option( name="state", @@ -316,7 +328,7 @@ class GitlabCog(Scale): @slash_command( name="gl", sub_cmd_name="mrs", - description="Get merge requests from GitLab", + sub_cmd_description="Get merge requests from GitLab", scopes=guild_ids, ) @slash_option( @@ -374,7 +386,7 @@ class GitlabCog(Scale): @slash_command( name="gl", sub_cmd_name="milestones", - description="Get milestones from GitLab", + sub_cmd_description="Get milestones from GitLab", scopes=guild_ids, ) async def _milestones(self, ctx: InteractionContext) -> None: @@ -410,6 +422,48 @@ class GitlabCog(Scale): await paginator.send(ctx) + @slash_command( + name="gl", sub_cmd_name="report", sub_cmd_description="Report an issue", scopes=guild_ids + ) + @cooldown(bucket=Buckets.USER, rate=1, interval=600) + async def _open_issue(self, ctx: InteractionContext) -> None: + modal = Modal( + title="Open a new issue on GitLab", + components=[ + InputText( + label="Issue Title", + placeholder="Descriptive Title", + style=TextStyles.SHORT, + custom_id="title", + max_length=200, + ), + InputText( + label="Description (supports Markdown!)", + placeholder="Detailed Description", + style=TextStyles.PARAGRAPH, + custom_id="description", + ), + ], + ) + await ctx.send_modal(modal) + try: + resp = await self.bot.wait_for_modal(modal, author=ctx.author.id, timeout=60 * 5) + title = resp.responses.get("title") + desc = resp.responses.get("description") + except asyncio.TimeoutError: + return + if not title.startswith("[Discord]"): + title = "[Discord] " + title + desc = f"Opened by `@{ctx.author.username}` on Discord\n\n" + desc + issue = self.project.issues.create(data={"title": title, "description": desc}) + embed = build_embed( + title=f"Issue #{issue.id} Created", + description=("Thank you for opening an issue!\n\n[View it online]({issue['web_url']})"), + fields=[], + color="#00FFEE", + ) + await resp.send(embed=embed) + def setup(bot: Snake) -> None: """Add GitlabCog to J.A.R.V.I.S. if Gitlab token exists."""