Add paginated issue lookup
This commit is contained in:
parent
5ae2df67d6
commit
2ba042aedc
1 changed files with 302 additions and 6 deletions
|
@ -1,10 +1,14 @@
|
||||||
import re
|
from datetime import datetime, timedelta
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
import gitlab
|
import gitlab
|
||||||
|
from ButtonPaginator import Paginator
|
||||||
from discord.ext import commands
|
from discord.ext import commands
|
||||||
from discord_slash import SlashContext, cog_ext
|
from discord.ext.tasks import loop
|
||||||
from discord_slash.utils.manage_commands import create_option
|
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.config import get_config
|
||||||
from jarvis.utils import build_embed
|
from jarvis.utils import build_embed
|
||||||
|
@ -13,6 +17,36 @@ from jarvis.utils.field import Field
|
||||||
guild_ids = [862402786116763668]
|
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):
|
class GitlabCog(commands.Cog):
|
||||||
def __init__(self, bot):
|
def __init__(self, bot):
|
||||||
self.bot = bot
|
self.bot = bot
|
||||||
|
@ -22,6 +56,8 @@ class GitlabCog(commands.Cog):
|
||||||
)
|
)
|
||||||
# J.A.R.V.I.S. GitLab ID is 29
|
# J.A.R.V.I.S. GitLab ID is 29
|
||||||
self.project = self._gitlab.projects.get(29)
|
self.project = self._gitlab.projects.get(29)
|
||||||
|
self.cache = {}
|
||||||
|
self._expire_interaction.start()
|
||||||
|
|
||||||
@cog_ext.cog_subcommand(
|
@cog_ext.cog_subcommand(
|
||||||
base="gl",
|
base="gl",
|
||||||
|
@ -43,16 +79,25 @@ class GitlabCog(commands.Cog):
|
||||||
assignee = issue.assignee
|
assignee = issue.assignee
|
||||||
if assignee:
|
if assignee:
|
||||||
assignee = assignee["name"]
|
assignee = assignee["name"]
|
||||||
|
else:
|
||||||
|
assignee = "None"
|
||||||
|
|
||||||
created_at = datetime.strptime(
|
created_at = datetime.strptime(
|
||||||
issue.created_at, "%Y-%m-%dT%H:%M:%S.%fZ"
|
issue.created_at, "%Y-%m-%dT%H:%M:%S.%fZ"
|
||||||
).strftime("%Y-%m-%d %H:%M:%S UTC")
|
).strftime("%Y-%m-%d %H:%M:%S UTC")
|
||||||
|
|
||||||
|
labels = issue.labels
|
||||||
|
if labels:
|
||||||
|
labels = "\n".join(issue.labels)
|
||||||
|
if not labels:
|
||||||
|
labels = "None"
|
||||||
|
|
||||||
fields = [
|
fields = [
|
||||||
Field(
|
Field(
|
||||||
name="State", value=issue.state[0].upper() + issue.state[1:]
|
name="State", value=issue.state[0].upper() + issue.state[1:]
|
||||||
),
|
),
|
||||||
Field(name="Assignee", value=assignee),
|
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
|
color = self.project.labels.get(issue.labels[0]).color
|
||||||
fields.append(Field(name="Created At", value=created_at))
|
fields.append(Field(name="Created At", value=created_at))
|
||||||
|
@ -108,7 +153,7 @@ class GitlabCog(commands.Cog):
|
||||||
try:
|
try:
|
||||||
milestone = self.project.milestones.get(int(id))
|
milestone = self.project.milestones.get(int(id))
|
||||||
except gitlab.exceptions.GitlabGetError:
|
except gitlab.exceptions.GitlabGetError:
|
||||||
await ctx.send("Issue does not exist.", hidden=True)
|
await ctx.send("Milestone does not exist.", hidden=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
created_at = datetime.strptime(
|
created_at = datetime.strptime(
|
||||||
|
@ -153,6 +198,257 @@ class GitlabCog(commands.Cog):
|
||||||
)
|
)
|
||||||
await ctx.send(embed=embed)
|
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):
|
def setup(bot):
|
||||||
if get_config().gitlab_token:
|
if get_config().gitlab_token:
|
||||||
|
|
Loading…
Add table
Reference in a new issue