add LibCal functionality
This commit is contained in:
parent
bae52e7d7e
commit
a5b5189e52
7 changed files with 341 additions and 71 deletions
104
ext/libcal.py
Normal file
104
ext/libcal.py
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
import traceback
|
||||
from hikari.files import Resource
|
||||
|
||||
import miru
|
||||
import hikari
|
||||
import lightbulb
|
||||
|
||||
from typing import Optional
|
||||
|
||||
from lib.config import load_config
|
||||
from lib.gcal import GoogleCalendarAPI
|
||||
from lib.room import Room
|
||||
from lib.ocr import get_room_data, NoMatchException
|
||||
|
||||
plugin = lightbulb.Plugin("LibCal")
|
||||
config = load_config()
|
||||
|
||||
def add_rooms_to_embed(room_list: list[Room], embed: hikari.Embed):
|
||||
for room in room_list:
|
||||
embed.add_field(room.get_time_str(), room.number)
|
||||
|
||||
class BookingConfirmationView(miru.View):
|
||||
def __init__(self, *, timeout: Optional[float] = 120, autodefer: bool = True, room_list: list[Room] = [], image: Resource | None = None) -> None:
|
||||
self.room_list = room_list
|
||||
if image is not None:
|
||||
self.image = image
|
||||
else:
|
||||
self.image = None
|
||||
super().__init__(timeout=timeout, autodefer=autodefer)
|
||||
|
||||
@miru.button(label="Yes", style=hikari.ButtonStyle.SUCCESS)
|
||||
async def confirm_button(self, button: miru.Button, ctx: miru.Context) -> None:
|
||||
gcal = GoogleCalendarAPI()
|
||||
for room in self.room_list:
|
||||
await gcal.create_event(room.number, room.start_time, room.end_time)
|
||||
embed = hikari.Embed(title="Rooms Booked!")
|
||||
add_rooms_to_embed(self.room_list, embed)
|
||||
await ctx.edit_response(embed=embed, components=[])
|
||||
|
||||
thread_embed = hikari.Embed(title="Rooms were booked!")
|
||||
thread_embed.set_author(name=ctx.user.username, icon=ctx.user.avatar_url)
|
||||
thread_embed.set_image(self.image)
|
||||
add_rooms_to_embed(self.room_list, thread_embed)
|
||||
await ctx.app.rest.create_message(config.discord_study_room_thread, embed=thread_embed)
|
||||
self.stop()
|
||||
|
||||
@miru.button(label="No", style=hikari.ButtonStyle.DANGER)
|
||||
async def cancel_button(self, button: miru.Button, ctx: miru.Context) -> None:
|
||||
embed = hikari.Embed(title="Aborted!")
|
||||
await ctx.edit_response(embed=embed, components=[])
|
||||
self.stop()
|
||||
|
||||
@plugin.command
|
||||
@lightbulb.option("img", "image to check for events", type=hikari.Attachment, required=True)
|
||||
@lightbulb.command("book", "add room bookings to Google Calendar", ephemeral=True)
|
||||
@lightbulb.implements(lightbulb.SlashCommand)
|
||||
async def book(ctx: lightbulb.Context) -> None:
|
||||
response = hikari.Embed()
|
||||
image = await ctx.options.img.read()
|
||||
room_list = get_room_data(image)
|
||||
add_rooms_to_embed(room_list, response)
|
||||
response.title = "Room Bookings"
|
||||
response.description = "Are the booking(s) correct?"
|
||||
view = BookingConfirmationView(room_list=room_list, image=ctx.options.img)
|
||||
resp = await ctx.respond(response, components=view.build())
|
||||
view.start(await resp.message())
|
||||
|
||||
|
||||
@book.set_error_handler
|
||||
async def book_error_handler(event: lightbulb.CommandErrorEvent):
|
||||
print("ERROR TYPE:", type(event.exception))
|
||||
if isinstance(event.exception.__cause__, NoMatchException):
|
||||
embed = hikari.Embed(title="Huh, I can't read that", description="Could you try another picture?")
|
||||
await event.context.respond(embed=embed)
|
||||
else:
|
||||
embed = hikari.Embed(
|
||||
title="Booking Error", description="Whelp, better luck next time I guess... the images used are attached.")
|
||||
embed.add_field("Traceback", traceback.format_exc())
|
||||
await event.context.respond(embed=embed, attachments=event.context.attachments)
|
||||
|
||||
|
||||
@plugin.command
|
||||
@lightbulb.command("rooms", "View today's rooms in Google Calendar.", ephemeral=True)
|
||||
@lightbulb.implements(lightbulb.SlashCommand)
|
||||
async def rooms(ctx: lightbulb.Context) -> None:
|
||||
gcal = GoogleCalendarAPI()
|
||||
events = await gcal.get_events()
|
||||
|
||||
room_list = [Room.from_event_dict(event) for event in events]
|
||||
embed = hikari.Embed(title="Today's Rooms!")
|
||||
if len(room_list) == 0:
|
||||
embed.description = "Looks like there's no rooms booked today. :("
|
||||
for room in room_list[::-1]:
|
||||
embed.add_field(
|
||||
f"{room.start_time.strftime('%H:%M')} - {room.end_time.strftime('%H:%M')}", room.number)
|
||||
await ctx.respond(embed)
|
||||
|
||||
|
||||
def load(bot: lightbulb.BotApp):
|
||||
bot.add_plugin(plugin)
|
||||
|
||||
|
||||
def unload(bot: lightbulb.BotApp):
|
||||
bot.remove_plugin(plugin)
|
||||
128
ext/system.py
128
ext/system.py
|
|
@ -10,88 +10,76 @@ config = load_config()
|
|||
|
||||
plugin = lightbulb.Plugin("SystemPlugin")
|
||||
|
||||
async def create_subprocess(*args):
|
||||
proc = await asyncio.create_subprocess_exec(*args,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
stdout, _ = await proc.communicate()
|
||||
return stdout.decode("utf-8").strip()
|
||||
|
||||
async def get_git_latest_commit_id():
|
||||
return await create_subprocess("git", "rev-parse", "--short", "HEAD")
|
||||
|
||||
async def get_git_branch():
|
||||
return await create_subprocess("git", "rev-parse", "--abbrev-ref", "HEAD")
|
||||
|
||||
async def get_git_remote():
|
||||
return await create_subprocess("git", "branch", "-r")
|
||||
|
||||
async def get_git_head_diff_branch(branch: str) -> str:
|
||||
# diff HEAD to remote
|
||||
return await create_subprocess("git", "diff", "head", branch)
|
||||
|
||||
async def get_git_index_diff_branch(branch: str) -> str:
|
||||
# diff index to remote
|
||||
return await create_subprocess("git", "diff", branch)
|
||||
|
||||
async def get_git_commits_ahead_behind(branch: str, remote: str) -> tuple[int, int]:
|
||||
# commits ahead/behind remote
|
||||
output = await create_subprocess("git", "rev-list", "--left-right", "--count", branch+"..."+remote)
|
||||
commits_ahead = int(output.split()[0])
|
||||
commits_behind = int(output.split()[1])
|
||||
return commits_ahead, commits_behind
|
||||
|
||||
async def get_git_dev(remote: str, branch: str) -> bool:
|
||||
# dev environment tests
|
||||
if await get_git_head_diff_branch(remote) != "": # difference between HEAD and remote
|
||||
return True
|
||||
elif config.git_branch != branch: # branch has been changed
|
||||
return True
|
||||
elif await get_git_index_diff_branch(remote) != "": # difference between index and remote
|
||||
return True
|
||||
elif (await get_git_commits_ahead_behind(branch, remote))[0] > 0: # ahead in commits
|
||||
return True
|
||||
return False
|
||||
|
||||
async def get_git_update(dev_status: bool, branch, remote) -> bool:
|
||||
commits_behind, _ = await get_git_commits_ahead_behind(branch, remote)
|
||||
if not dev_status and commits_behind > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
async def get_git_status() -> dict:
|
||||
output = {}
|
||||
try:
|
||||
id_proc = await asyncio.create_subprocess_exec("git", "rev-parse", "--short", "HEAD",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
|
||||
stdout, _ = await id_proc.communicate()
|
||||
output["commit_id"] = stdout.decode("utf-8")
|
||||
|
||||
br_proc = await asyncio.create_subprocess_exec("git", "rev-parse", "--abbrev-ref", "HEAD",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
|
||||
stdout, _ = await br_proc.communicate()
|
||||
output["branch"] = stdout.decode("utf-8").strip()
|
||||
|
||||
rm_proc = await asyncio.create_subprocess_exec("git", "branch", "-r",
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
|
||||
stdout, _ = await rm_proc.communicate()
|
||||
output['remote'] = "remotes/"+stdout.decode("utf-8").lstrip().split("\n")[0]
|
||||
|
||||
# diff HEAD to remote
|
||||
hd_proc = await asyncio.create_subprocess_exec("git", "diff", "HEAD", output['remote'],
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
|
||||
# diff index to remote
|
||||
ix_proc = await asyncio.create_subprocess_exec("git", "diff", output['remote'],
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
stdout, _ = await ix_proc.communicate()
|
||||
ix_diff = stdout.decode("utf-8")
|
||||
|
||||
# commits ahead/behind remote
|
||||
ab_proc = await asyncio.create_subprocess_exec("git", "rev-list", "--left-right", "--count", output['branch']+"..."+output["remote"],
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE
|
||||
)
|
||||
stdout, _ = await ab_proc.communicate()
|
||||
commits_ahead = stdout.decode("utf-8").split()[0]
|
||||
commits_behind = stdout.decode("utf-8").split()[1]
|
||||
|
||||
stdout, _ = await hd_proc.communicate()
|
||||
hd_diff = stdout.decode("utf-8")
|
||||
output['dev'] = False
|
||||
|
||||
# dev environment tests
|
||||
if hd_diff != "": # difference between HEAD and remote
|
||||
output['dev'] = True
|
||||
elif config.branch != output["branch"]: # branch has been changed
|
||||
output['dev'] = True
|
||||
elif ix_diff != "": # difference between index and remote
|
||||
output['dev'] = True
|
||||
elif int(commits_ahead) > 0: # ahead in commits
|
||||
output['dev'] = True
|
||||
|
||||
output['update'] = False
|
||||
if not output['dev'] and int(commits_behind) > 0:
|
||||
output['update'] = True
|
||||
except subprocess.SubprocessError as err:
|
||||
print(err)
|
||||
output["commit_id"] = await get_git_latest_commit_id()
|
||||
output["branch"] = await get_git_branch()
|
||||
output["remote"] = await get_git_remote()
|
||||
output["dev"] = await get_git_dev(output['remote'], output['branch'])
|
||||
output['update'] = await get_git_update(output['dev'], output['branch'], output['remote'])
|
||||
return output
|
||||
|
||||
@plugin.command
|
||||
@lightbulb.command("ping", "ping the bot.", ephemeral=True)
|
||||
@lightbulb.command("ping", "pong!", ephemeral=True)
|
||||
@lightbulb.implements(lightbulb.SlashCommand)
|
||||
async def ping(ctx: lightbulb.Context) -> None:
|
||||
embed = hikari.Embed(title="Ping!",
|
||||
embed = hikari.Embed(title="Pong!",
|
||||
description=f"latency: {round(ctx.bot.heartbeat_latency * 1000, ndigits=2)}ms"
|
||||
)
|
||||
await ctx.respond(embed)
|
||||
|
||||
@plugin.command
|
||||
@lightbulb.command("info", "get bot info", ephemeral=True)
|
||||
@lightbulb.command("info", "get bot information such as the version, and repository link.", ephemeral=True)
|
||||
@lightbulb.implements(lightbulb.SlashCommand)
|
||||
async def info(ctx: lightbulb.Context) -> None:
|
||||
git_status = await get_git_status()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue