From 189e15b1dd551a15a7e64547683c0a071ab9d152 Mon Sep 17 00:00:00 2001 From: Zevaryx Date: Thu, 22 Jul 2021 11:47:41 -0600 Subject: [PATCH 1/5] Add gitlab cog, needs more work, refs #30 --- config.example.yaml | 3 +- jarvis/cogs/gitlab.py | 153 ++++++++++++++++++++++++++++++++++++++++++ jarvis/config.py | 2 + 3 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 jarvis/cogs/gitlab.py diff --git a/config.example.yaml b/config.example.yaml index 0083067..b320cb0 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -7,7 +7,8 @@ password: pass host: localhost port: 27017 - api_urls: + urls: url_name: url url_name2: url2 max_messages: 1000 + gitlab_token: null diff --git a/jarvis/cogs/gitlab.py b/jarvis/cogs/gitlab.py new file mode 100644 index 0000000..0147f24 --- /dev/null +++ b/jarvis/cogs/gitlab.py @@ -0,0 +1,153 @@ +import re +from datetime import datetime + +import gitlab +from discord.ext import commands +from discord_slash import SlashContext, cog_ext +from discord_slash.utils.manage_commands import create_option + +from jarvis.config import get_config +from jarvis.utils import build_embed +from jarvis.utils.field import Field + +guild_ids = [862402786116763668] + + +class GitlabCog(commands.Cog): + def __init__(self, bot): + self.bot = bot + config = get_config() + self._gitlab = gitlab.Gitlab( + "https://git.zevaryx.com", private_token=config.gitlab_token + ) + # J.A.R.V.I.S. GitLab ID is 29 + self.project = self._gitlab.projects.get(29) + + @cog_ext.cog_subcommand( + base="gl", + name="issue", + description="Get an issue from GitLab", + guild_ids=guild_ids, + options=[ + create_option( + name="id", description="Issue ID", option_type=4, required=True + ) + ], + ) + async def _issue(self, ctx: SlashContext, id: int): + try: + issue = self.project.issues.get(int(id)) + except gitlab.exceptions.GitlabGetError: + await ctx.send("Issue does not exist.", hidden=True) + return + assignee = issue.assignee + if assignee: + assignee = assignee["name"] + + created_at = datetime.strptime( + issue.created_at, "%Y-%m-%dT%H:%M:%S.%fZ" + ).strftime("%Y-%m-%d %H:%M:%S UTC") + fields = [ + Field( + name="State", value=issue.state[0].upper() + issue.state[1:] + ), + Field(name="Assignee", value=assignee), + Field(name="Labels", value="\n".join(issue.labels)), + ] + color = self.project.labels.get(issue.labels[0]).color + fields.append(Field(name="Created At", value=created_at)) + if issue.state == "closed": + closed_at = datetime.strptime( + issue.closed_at, "%Y-%m-%dT%H:%M:%S.%fZ" + ).strftime("%Y-%m-%d %H:%M:%S UTC") + fields.append(Field(name="Closed At", value=closed_at)) + if issue.milestone: + fields.append( + Field( + name="Milestone", + value=f"[{issue.milestone['title']}]" + + f"({issue.milestone['web_url']})", + inline=False, + ) + ) + if len(issue.title) > 200: + issue.title = issue.title[:200] + "..." + embed = build_embed( + title=f"[#{issue.iid}] {issue.title}", + description=issue.description, + fields=fields, + color=color, + url=issue.web_url, + ) + embed.set_author( + name=issue.author["name"], + icon_url=issue.author["avatar_url"], + url=issue.author["web_url"], + ) + embed.set_thumbnail( + url="https://about.gitlab.com/images" + + "/press/logo/png/gitlab-icon-rgb.png" + ) + await ctx.send(embed=embed) + + @cog_ext.cog_subcommand( + base="gl", + name="milestone", + description="Get a milestone from GitLab", + guild_ids=guild_ids, + options=[ + create_option( + name="id", + description="Milestone ID", + option_type=4, + required=True, + ) + ], + ) + async def _milestone(self, ctx: SlashContext, id: int): + try: + milestone = self.project.milestones.get(int(id)) + except gitlab.exceptions.GitlabGetError: + await ctx.send("Issue does not exist.", hidden=True) + return + + created_at = datetime.strptime( + milestone.created_at, "%Y-%m-%dT%H:%M:%S.%fZ" + ).strftime("%Y-%m-%d %H:%M:%S UTC") + + fields = [ + Field( + name="State", + value=milestone.state[0].upper() + milestone.state[1:], + ), + Field(name="Start Date", value=milestone.start_date), + Field(name="Due Date", value=milestone.due_date), + Field(name="Created At", value=created_at), + ] + + if milestone.updated_at: + updated_at = datetime.strptime( + milestone.updated_at, "%Y-%m-%dT%H:%M:%S.%fZ" + ).strftime("%Y-%m-%d %H:%M:%S UTC") + fields.append(Field(name="Updated At", value=updated_at)) + + if len(milestone.title) > 200: + milestone.title = milestone.title[:200] + "..." + + embed = build_embed( + title=f"[#{milestone.iid}] {milestone.title}", + description=milestone.description, + fields=fields, + color="#00FFEE", + url=milestone.web_url, + ) + embed.set_thumbnail( + url="https://about.gitlab.com/images" + + "/press/logo/png/gitlab-icon-rgb.png" + ) + await ctx.send(embed=embed) + + +def setup(bot): + if get_config().gitlab_token: + bot.add_cog(GitlabCog(bot)) diff --git a/jarvis/config.py b/jarvis/config.py index 0ba4eb3..3f3883d 100644 --- a/jarvis/config.py +++ b/jarvis/config.py @@ -24,6 +24,7 @@ class Config(object): logo: str, mongo: dict, urls: dict, + gitlab_token: str = None, max_messages: int = 1000, ): self.token = token @@ -32,6 +33,7 @@ class Config(object): self.mongo = mongo self.urls = urls self.max_messages = max_messages + self.gitlab_token = gitlab_token db = DBManager(config=mongo).mongo.jarvis.config db_config = db.find() for item in db_config: From 5ae2df67d676ff7553207f2f1e7a52ac798171e6 Mon Sep 17 00:00:00 2001 From: Zevaryx Date: Thu, 22 Jul 2021 12:08:07 -0600 Subject: [PATCH 2/5] Set Milestone author to @jarvis --- jarvis/cogs/gitlab.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/jarvis/cogs/gitlab.py b/jarvis/cogs/gitlab.py index 0147f24..8327eff 100644 --- a/jarvis/cogs/gitlab.py +++ b/jarvis/cogs/gitlab.py @@ -141,6 +141,12 @@ class GitlabCog(commands.Cog): color="#00FFEE", url=milestone.web_url, ) + embed.set_author( + name="J.A.R.V.I.S.", + url="https://git.zevaryx.com/jarvis", + icon_url="https://git.zevaryx.com/uploads/-" + + "/system/user/avatar/11/avatar.png", + ) embed.set_thumbnail( url="https://about.gitlab.com/images" + "/press/logo/png/gitlab-icon-rgb.png" From 2ba042aedcccda3315d884174af532dad369584d Mon Sep 17 00:00:00 2001 From: Zevaryx Date: Fri, 23 Jul 2021 11:49:38 -0600 Subject: [PATCH 3/5] Add paginated issue lookup --- jarvis/cogs/gitlab.py | 308 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 302 insertions(+), 6 deletions(-) diff --git a/jarvis/cogs/gitlab.py b/jarvis/cogs/gitlab.py index 8327eff..0030950 100644 --- a/jarvis/cogs/gitlab.py +++ b/jarvis/cogs/gitlab.py @@ -1,10 +1,14 @@ -import re -from datetime import datetime +from datetime import datetime, timedelta import gitlab +from ButtonPaginator import Paginator from discord.ext import commands -from discord_slash import SlashContext, cog_ext -from discord_slash.utils.manage_commands import create_option +from discord.ext.tasks import loop +from discord.utils import find +from discord_slash import ComponentContext, SlashContext, cog_ext +from discord_slash.model import ButtonStyle +from discord_slash.utils import manage_components +from discord_slash.utils.manage_commands import create_choice, create_option from jarvis.config import get_config from jarvis.utils import build_embed @@ -13,6 +17,36 @@ from jarvis.utils.field import Field guild_ids = [862402786116763668] +def create_layout(command: str): + buttons = [ + manage_components.create_button( + style=ButtonStyle.gray, emoji="◀", custom_id=f"back_{command}" + ), + manage_components.create_button( + style=ButtonStyle.gray, + emoji="▶", + custom_id=f"next_{command}", + ), + ] + action_row = manage_components.spread_to_rows(*buttons, max_in_row=2) + return action_row + + +def create_issues_layout(): + return create_layout("issues") + + +def edit_paging_components( + components: list, disable_left: bool = False, disable_right: bool = False +): + components[0]["components"][0]["disabled"] = disable_left + components[0]["components"][1]["disabled"] = disable_right + return components + + +command_lookup = {"issues": create_issues_layout} + + class GitlabCog(commands.Cog): def __init__(self, bot): self.bot = bot @@ -22,6 +56,8 @@ class GitlabCog(commands.Cog): ) # J.A.R.V.I.S. GitLab ID is 29 self.project = self._gitlab.projects.get(29) + self.cache = {} + self._expire_interaction.start() @cog_ext.cog_subcommand( base="gl", @@ -43,16 +79,25 @@ class GitlabCog(commands.Cog): assignee = issue.assignee if assignee: assignee = assignee["name"] + else: + assignee = "None" created_at = datetime.strptime( issue.created_at, "%Y-%m-%dT%H:%M:%S.%fZ" ).strftime("%Y-%m-%d %H:%M:%S UTC") + + labels = issue.labels + if labels: + labels = "\n".join(issue.labels) + if not labels: + labels = "None" + fields = [ Field( name="State", value=issue.state[0].upper() + issue.state[1:] ), Field(name="Assignee", value=assignee), - Field(name="Labels", value="\n".join(issue.labels)), + Field(name="Labels", value=labels), ] color = self.project.labels.get(issue.labels[0]).color fields.append(Field(name="Created At", value=created_at)) @@ -108,7 +153,7 @@ class GitlabCog(commands.Cog): try: milestone = self.project.milestones.get(int(id)) except gitlab.exceptions.GitlabGetError: - await ctx.send("Issue does not exist.", hidden=True) + await ctx.send("Milestone does not exist.", hidden=True) return created_at = datetime.strptime( @@ -153,6 +198,257 @@ class GitlabCog(commands.Cog): ) await ctx.send(embed=embed) + @cog_ext.cog_subcommand( + base="gl", + name="mr", + description="Get an merge request from GitLab", + guild_ids=guild_ids, + options=[ + create_option( + name="id", + description="Merge Request ID", + option_type=4, + required=True, + ) + ], + ) + async def _mr(self, ctx: SlashContext, id: int): + try: + mr = self.project.mergerequests.get(int(id)) + except gitlab.exceptions.GitlabGetError: + await ctx.send("Merge request does not exist.", hidden=True) + return + assignee = mr.assignee + if assignee: + assignee = assignee["name"] + else: + assignee = "None" + + created_at = datetime.strptime( + mr.created_at, "%Y-%m-%dT%H:%M:%S.%fZ" + ).strftime("%Y-%m-%d %H:%M:%S UTC") + + labels = mr.labels + if labels: + labels = "\n".join(mr.labels) + if not labels: + labels = "None" + + fields = [ + Field(name="State", value=mr.state[0].upper() + mr.state[1:]), + Field(name="Assignee", value=assignee), + Field(name="Labels", value=labels), + ] + if mr.labels: + color = self.project.labels.get(mr.labels[0]).color + else: + color = "#00FFEE" + fields.append(Field(name="Created At", value=created_at)) + 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(Field(name="Merged At", value=merged_at)) + 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(Field(name="Closed At", value=closed_at)) + if mr.milestone: + fields.append( + Field( + name="Milestone", + value=f"[{mr.milestone['title']}]" + + f"({mr.milestone['web_url']})", + inline=False, + ) + ) + if len(mr.title) > 200: + mr.title = mr.title[:200] + "..." + embed = build_embed( + title=f"[#{mr.iid}] {mr.title}", + description=mr.description, + fields=fields, + color=color, + url=mr.web_url, + ) + embed.set_author( + name=mr.author["name"], + icon_url=mr.author["avatar_url"], + url=mr.author["web_url"], + ) + embed.set_thumbnail( + url="https://about.gitlab.com/images" + + "/press/logo/png/gitlab-icon-rgb.png" + ) + await ctx.send(embed=embed) + + def build_embed_page(self, issues: list, t_state: str): + fields = [] + for issue in issues: + fields.append( + Field( + name=f"[#{issue.iid}] {issue.title}", + value=issue.description + + f"\n\n[View this issue]({issue.web_url})", + inline=False, + ) + ) + + embed = build_embed( + title=f"{t_state} J.A.R.V.I.S. issues", + description="", + fields=fields, + url="https://git.zevaryx.com/stark-industries/j.a.r.v.i.s./issues", + ) + embed.set_author( + name="J.A.R.V.I.S.", + url="https://git.zevaryx.com/jarvis", + icon_url="https://git.zevaryx.com/uploads/-" + + "/system/user/avatar/11/avatar.png", + ) + embed.set_thumbnail( + url="https://about.gitlab.com/images" + + "/press/logo/png/gitlab-icon-rgb.png" + ) + return embed + + @cog_ext.cog_subcommand( + base="gl", + name="issues", + description="Get open issues from GitLab", + guild_ids=guild_ids, + options=[ + create_option( + name="state", + description="State of issues to get", + option_type=3, + required=False, + choices=[ + create_choice(name="Open", value="opened"), + create_choice(name="Closed", value="closed"), + create_choice(name="All", value="all"), + ], + ) + ], + ) + async def _issues(self, ctx: SlashContext, state: str = "opened"): + exists = find( + lambda x: x["_command"] == "issues" + and x["user"] == ctx.author.id + and x["state"] == state, + self.cache.values(), + ) + if exists: + await ctx.defer(hidden=True) + await ctx.send( + "Please use existing interaction: " + + f"{exists['_message'].jump_url}", + hidden=True, + ) + return + await ctx.defer() + m_state = state + if m_state == "all": + m_state = None + # issues = [] + # page = 1 + try: + # issues += self.project.issues.list(page=page, state=m_state, order_by="created_at", sort="desc", per_page=100) + issues = self.project.issues.list( + page=1, + state=m_state, + order_by="created_at", + sort="desc", + per_page=5, + ) + next_issues = self.project.issues.list( + page=2, + state=m_state, + order_by="created_at", + sort="desc", + per_page=5, + ) + except gitlab.exceptions.GitlabGetError: + await ctx.send("Unable to get issues", hidden=True) + return + t_state = state + if t_state == "opened": + t_state = "open" + + t_state = t_state[0].upper() + t_state[1:] + + components = create_issues_layout() + components = edit_paging_components( + components, True, next_issues == [] + ) + embed = self.build_embed_page(issues, t_state=t_state) + message = await ctx.send(embed=embed, components=components) + self.cache[message.id] = { + "user": ctx.author.id, + "state": state, + "t_state": t_state, + "page": 1, + "timeout": datetime.utcnow() + timedelta(minutes=5), + "_command": "issues", + "_message": message, + } + + @cog_ext.cog_component(components=create_issues_layout()) + async def _process(self, ctx: ComponentContext): + await ctx.defer(edit_origin=True) + cache = self.cache[ctx.origin_message.id] + if ctx.author.id != cache["user"]: + return + + state = cache["state"] + page = cache["page"] + if ctx.custom_id == "back": + page -= 1 + else: + page += 1 + try: + issues = self.project.issues.list( + page=page, + state=state, + order_by="created_at", + sort="desc", + per_page=5, + ) + next_issues = self.project.issues.list( + page=page + 1, + state=state, + order_by="created_at", + sort="desc", + per_page=5, + ) + except gitlab.exceptions.GitlabGetError: + await ctx.edit_origin(content="Unable to get issues", hidden=True) + return + components = create_issues_layout() + components = edit_paging_components( + components=components, + disable_left=page == 1, + disable_right=next_issues == [], + ) + embed = self.build_embed_page( + issues=issues, t_state=self.cache[ctx.origin_message.id]["t_state"] + ) + self.cache[ctx.origin_message.id]["page"] = page + await ctx.edit_origin(embed=embed, components=components) + + @loop(minutes=1) + async def _expire_interaction(self): + keys = list(self.cache.keys()) + for key in keys: + if self.cache[key]["timeout"] <= datetime.utcnow() + timedelta( + minutes=1 + ): + components = create_layout(self.cache[key]["_command"]) + components = edit_paging_components(components, True, True) + await self.cache[key]["_message"].edit(components=components) + del self.cache[key] + def setup(bot): if get_config().gitlab_token: From 5622209f4d22c7e11240dd37678d88fde98838d7 Mon Sep 17 00:00:00 2001 From: Zevaryx Date: Fri, 23 Jul 2021 13:47:04 -0600 Subject: [PATCH 4/5] Paginator viewing for issues, merge requests, and milestones --- jarvis/cogs/error.py | 3 +- jarvis/cogs/gitlab.py | 331 ++++++++++++++++++++++++++++-------------- 2 files changed, 221 insertions(+), 113 deletions(-) diff --git a/jarvis/cogs/error.py b/jarvis/cogs/error.py index f9bbbfb..df21073 100644 --- a/jarvis/cogs/error.py +++ b/jarvis/cogs/error.py @@ -34,7 +34,8 @@ class ErrorHandlerCog(commands.Cog): ) else: await ctx.send( - f"Error processing command:\n```{error}```", hidden=True + f"Error processing command:\n```{error}```", + hidden=True, ) diff --git a/jarvis/cogs/gitlab.py b/jarvis/cogs/gitlab.py index 0030950..99e551e 100644 --- a/jarvis/cogs/gitlab.py +++ b/jarvis/cogs/gitlab.py @@ -17,36 +17,6 @@ from jarvis.utils.field import Field guild_ids = [862402786116763668] -def create_layout(command: str): - buttons = [ - manage_components.create_button( - style=ButtonStyle.gray, emoji="◀", custom_id=f"back_{command}" - ), - manage_components.create_button( - style=ButtonStyle.gray, - emoji="▶", - custom_id=f"next_{command}", - ), - ] - action_row = manage_components.spread_to_rows(*buttons, max_in_row=2) - return action_row - - -def create_issues_layout(): - return create_layout("issues") - - -def edit_paging_components( - components: list, disable_left: bool = False, disable_right: bool = False -): - components[0]["components"][0]["disabled"] = disable_left - components[0]["components"][1]["disabled"] = disable_right - return components - - -command_lookup = {"issues": create_issues_layout} - - class GitlabCog(commands.Cog): def __init__(self, bot): self.bot = bot @@ -200,7 +170,7 @@ class GitlabCog(commands.Cog): @cog_ext.cog_subcommand( base="gl", - name="mr", + name="mergerequest", description="Get an merge request from GitLab", guild_ids=guild_ids, options=[ @@ -212,7 +182,7 @@ class GitlabCog(commands.Cog): ) ], ) - async def _mr(self, ctx: SlashContext, id: int): + async def _mergerequest(self, ctx: SlashContext, id: int): try: mr = self.project.mergerequests.get(int(id)) except gitlab.exceptions.GitlabGetError: @@ -283,23 +253,28 @@ class GitlabCog(commands.Cog): ) await ctx.send(embed=embed) - def build_embed_page(self, issues: list, t_state: str): + def build_embed_page(self, api_list: list, t_state: str, name: str): + title = "" + if t_state: + title = f"{t_state} " + title += f"J.A.R.V.I.S. {name}s" fields = [] - for issue in issues: + for item in api_list: fields.append( Field( - name=f"[#{issue.iid}] {issue.title}", - value=issue.description - + f"\n\n[View this issue]({issue.web_url})", + name=f"[#{item.iid}] {item.title}", + value=item.description + + f"\n\n[View this {name}]({item.web_url})", inline=False, ) ) embed = build_embed( - title=f"{t_state} J.A.R.V.I.S. issues", + title=title, description="", fields=fields, - url="https://git.zevaryx.com/stark-industries/j.a.r.v.i.s./issues", + url="https://git.zevaryx.com/stark-industries/j.a.r.v.i.s./" + + f"{name.replace(' ', '_')}s", ) embed.set_author( name="J.A.R.V.I.S.", @@ -313,6 +288,16 @@ class GitlabCog(commands.Cog): ) return embed + def check_cache(self, ctx: SlashContext, **kwargs): + if not kwargs: + kwargs = {} + return find( + lambda x: x["command"] == ctx.subcommand_name + and x["user"] == ctx.author.id + and all(x[k] == v for k, v in kwargs.items()), + self.cache.values(), + ) + @cog_ext.cog_subcommand( base="gl", name="issues", @@ -333,17 +318,12 @@ class GitlabCog(commands.Cog): ], ) async def _issues(self, ctx: SlashContext, state: str = "opened"): - exists = find( - lambda x: x["_command"] == "issues" - and x["user"] == ctx.author.id - and x["state"] == state, - self.cache.values(), - ) + exists = self.check_cache(ctx, state=state) if exists: await ctx.defer(hidden=True) await ctx.send( "Please use existing interaction: " - + f"{exists['_message'].jump_url}", + + f"{exists['paginator']._message.jump_url}", hidden=True, ) return @@ -351,91 +331,221 @@ class GitlabCog(commands.Cog): m_state = state if m_state == "all": m_state = None - # issues = [] - # page = 1 + issues = [] + page = 1 try: - # issues += self.project.issues.list(page=page, state=m_state, order_by="created_at", sort="desc", per_page=100) - issues = self.project.issues.list( - page=1, + while curr_page := self.project.issues.list( + page=page, state=m_state, order_by="created_at", sort="desc", - per_page=5, - ) - next_issues = self.project.issues.list( - page=2, - state=m_state, - order_by="created_at", - sort="desc", - per_page=5, - ) + per_page=100, + ): + issues += curr_page + page += 1 except gitlab.exceptions.GitlabGetError: - await ctx.send("Unable to get issues", hidden=True) + # Only send error on first page. Otherwise, use pages retrieved + if page == 1: + await ctx.send("Unable to get issues") + return + + if len(issues) == 0: + await ctx.send("No issues match that criteria") return + t_state = state if t_state == "opened": t_state = "open" - + pages = [] t_state = t_state[0].upper() + t_state[1:] + for i in range(0, len(issues), 5): + pages.append( + self.build_embed_page( + issues[i : i + 5], t_state=t_state, name="issue" + ) + ) - components = create_issues_layout() - components = edit_paging_components( - components, True, next_issues == [] + paginator = Paginator( + bot=self.bot, + ctx=ctx, + embeds=pages, + only=ctx.author, + timeout=60 * 5, # 5 minute timeout + disable_after_timeout=True, + use_extend=len(pages) > 2, + left_button_style=ButtonStyle.grey, + right_button_style=ButtonStyle.grey, + basic_buttons=["◀", "▶"], ) - embed = self.build_embed_page(issues, t_state=t_state) - message = await ctx.send(embed=embed, components=components) - self.cache[message.id] = { + + self.cache[hash(paginator)] = { "user": ctx.author.id, - "state": state, - "t_state": t_state, - "page": 1, "timeout": datetime.utcnow() + timedelta(minutes=5), - "_command": "issues", - "_message": message, + "command": ctx.subcommand_name, + "state": state, + "paginator": paginator, } - @cog_ext.cog_component(components=create_issues_layout()) - async def _process(self, ctx: ComponentContext): - await ctx.defer(edit_origin=True) - cache = self.cache[ctx.origin_message.id] - if ctx.author.id != cache["user"]: + await paginator.start() + + @cog_ext.cog_subcommand( + base="gl", + name="mergerequests", + description="Get open issues from GitLab", + guild_ids=guild_ids, + options=[ + create_option( + name="state", + description="State of issues to get", + option_type=3, + required=False, + choices=[ + create_choice(name="Open", value="opened"), + create_choice(name="Closed", value="closed"), + create_choice(name="Merged", value="merged"), + create_choice(name="All", value="all"), + ], + ) + ], + ) + async def _mergerequests(self, ctx: SlashContext, state: str = "opened"): + exists = self.check_cache(ctx, state=state) + if exists: + await ctx.defer(hidden=True) + await ctx.send( + "Please use existing interaction: " + + f"{exists['paginator']._message.jump_url}", + hidden=True, + ) + return + await ctx.defer() + m_state = state + if m_state == "all": + m_state = None + merges = [] + page = 1 + try: + while curr_page := self.project.mergerequests.list( + page=page, + state=m_state, + order_by="created_at", + sort="desc", + per_page=100, + ): + merges += curr_page + page += 1 + except gitlab.exceptions.GitlabGetError: + # Only send error on first page. Otherwise, use pages retrieved + if page == 1: + await ctx.send("Unable to get merge requests") + return + + if len(merges) == 0: + await ctx.send("No merge requests match that criteria") return - state = cache["state"] - page = cache["page"] - if ctx.custom_id == "back": - page -= 1 - else: - page += 1 - try: - issues = self.project.issues.list( - page=page, - state=state, - order_by="created_at", - sort="desc", - per_page=5, + t_state = state + if t_state == "opened": + t_state = "open" + pages = [] + t_state = t_state[0].upper() + t_state[1:] + for i in range(0, len(merges), 5): + pages.append( + self.build_embed_page( + merges[i : i + 5], t_state=t_state, name="merge request" + ) ) - next_issues = self.project.issues.list( - page=page + 1, - state=state, - order_by="created_at", - sort="desc", - per_page=5, + + paginator = Paginator( + bot=self.bot, + ctx=ctx, + embeds=pages, + only=ctx.author, + timeout=60 * 5, # 5 minute timeout + disable_after_timeout=True, + use_extend=len(pages) > 2, + left_button_style=ButtonStyle.grey, + right_button_style=ButtonStyle.grey, + basic_buttons=["◀", "▶"], + ) + + self.cache[hash(paginator)] = { + "user": ctx.author.id, + "timeout": datetime.utcnow() + timedelta(minutes=5), + "command": ctx.subcommand_name, + "state": state, + "paginator": paginator, + } + + await paginator.start() + + @cog_ext.cog_subcommand( + base="gl", + name="milestones", + description="Get open issues from GitLab", + guild_ids=guild_ids, + ) + async def _milestones(self, ctx: SlashContext): + exists = self.check_cache(ctx) + if exists: + await ctx.defer(hidden=True) + await ctx.send( + "Please use existing interaction: " + + f"{exists['paginator']._message.jump_url}", + hidden=True, ) - except gitlab.exceptions.GitlabGetError: - await ctx.edit_origin(content="Unable to get issues", hidden=True) return - components = create_issues_layout() - components = edit_paging_components( - components=components, - disable_left=page == 1, - disable_right=next_issues == [], + await ctx.defer() + milestones = [] + page = 1 + try: + while curr_page := self.project.milestones.list( + page=page, + order_by="created_at", + sort="desc", + per_page=100, + ): + milestones += curr_page + page += 1 + except gitlab.exceptions.GitlabGetError: + # Only send error on first page. Otherwise, use pages retrieved + if page == 1: + await ctx.send("Unable to get milestones") + return + + if len(milestones) == 0: + await ctx.send("No milestones exist") + return + + pages = [] + for i in range(0, len(milestones), 5): + pages.append( + self.build_embed_page( + milestones[i : i + 5], t_state=None, name="milestone" + ) + ) + + paginator = Paginator( + bot=self.bot, + ctx=ctx, + embeds=pages, + only=ctx.author, + timeout=60 * 5, # 5 minute timeout + disable_after_timeout=True, + use_extend=len(pages) > 2, + left_button_style=ButtonStyle.grey, + right_button_style=ButtonStyle.grey, + basic_buttons=["◀", "▶"], ) - embed = self.build_embed_page( - issues=issues, t_state=self.cache[ctx.origin_message.id]["t_state"] - ) - self.cache[ctx.origin_message.id]["page"] = page - await ctx.edit_origin(embed=embed, components=components) + + self.cache[hash(paginator)] = { + "user": ctx.author.id, + "timeout": datetime.utcnow() + timedelta(minutes=5), + "command": ctx.subcommand_name, + "paginator": paginator, + } + + await paginator.start() @loop(minutes=1) async def _expire_interaction(self): @@ -444,9 +554,6 @@ class GitlabCog(commands.Cog): if self.cache[key]["timeout"] <= datetime.utcnow() + timedelta( minutes=1 ): - components = create_layout(self.cache[key]["_command"]) - components = edit_paging_components(components, True, True) - await self.cache[key]["_message"].edit(components=components) del self.cache[key] From 6f8606943bfea0884fd456528699c78149172663 Mon Sep 17 00:00:00 2001 From: Zevaryx Date: Fri, 23 Jul 2021 13:48:20 -0600 Subject: [PATCH 5/5] Bump version to 1.3.0 --- jarvis/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jarvis/__init__.py b/jarvis/__init__.py index 4873a2f..2bdb0c2 100644 --- a/jarvis/__init__.py +++ b/jarvis/__init__.py @@ -36,7 +36,7 @@ jarvis = commands.Bot( ) slash = SlashCommand(jarvis, sync_commands=True, sync_on_cog_reload=True) jarvis_self = Process() -__version__ = "1.2.2" +__version__ = "1.3.0" db = DBManager(get_config().mongo).mongo