98 lines
2.7 KiB
Python
98 lines
2.7 KiB
Python
from asyncio import new_event_loop
|
|
from datetime import timedelta
|
|
from os import environ
|
|
|
|
from disnake import Client, Guild, Member
|
|
from dotenv import load_dotenv
|
|
from ics import Calendar, Event # type: ignore
|
|
from ics.alarm.display import DisplayAlarm # type: ignore
|
|
from quart import Quart, abort
|
|
from sentry_sdk import init
|
|
from sentry_sdk.integrations.quart import QuartIntegration
|
|
|
|
load_dotenv()
|
|
|
|
DISCORD_TOKEN = environ.get("DISCORD_TOKEN")
|
|
if not DISCORD_TOKEN:
|
|
raise Exception("Missing DISCORD_TOKEN env")
|
|
|
|
SENTRY_DSN = environ.get("SENTRY_DSN")
|
|
if SENTRY_DSN:
|
|
init(SENTRY_DSN, integrations=[QuartIntegration()])
|
|
|
|
|
|
class Discord(Client):
|
|
async def on_ready(self):
|
|
print(f"Logged on as {self.user}!")
|
|
|
|
|
|
client = Discord()
|
|
app = Quart(__name__)
|
|
|
|
|
|
def get_guild_by_id(guild_id: int | str) -> Guild | None:
|
|
for guild in client.guilds:
|
|
if guild.id == int(guild_id) or guild.vanity_url_code == str(guild_id):
|
|
return guild
|
|
return None
|
|
|
|
|
|
def get_bot_member(guild: Guild) -> Member | None:
|
|
for member in guild.members:
|
|
if member.id == client.user.id:
|
|
return member
|
|
return None
|
|
|
|
|
|
async def get_guild_tag(member: Member) -> str | None:
|
|
if member.guild_permissions.manage_guild:
|
|
if member.guild.vanity_url_code:
|
|
return member.guild.vanity_url_code
|
|
else:
|
|
invites = await member.guild.invites()
|
|
return invites[0].code
|
|
return None
|
|
|
|
|
|
@app.route("/<guild_id>.ics")
|
|
async def index(guild_id):
|
|
guild = get_guild_by_id(guild_id)
|
|
if guild is None:
|
|
abort(404)
|
|
|
|
bot = get_bot_member(guild)
|
|
guild_tag = await get_guild_tag(bot)
|
|
calendar = Calendar()
|
|
|
|
for scheduled_event in guild.scheduled_events:
|
|
event = Event()
|
|
event.name = scheduled_event.name
|
|
event.begin = scheduled_event.scheduled_start_time
|
|
event.end = scheduled_event.scheduled_end_time
|
|
event.uid = str(scheduled_event.id)
|
|
event.description = scheduled_event.description
|
|
event.location = (
|
|
scheduled_event.entity_metadata.location
|
|
if scheduled_event.entity_metadata
|
|
else None
|
|
)
|
|
|
|
if guild_tag:
|
|
event.url = f"https://discord.gg/{guild_tag}?event={scheduled_event.id}"
|
|
|
|
alarm = DisplayAlarm()
|
|
alarm.trigger = timedelta(hours=1)
|
|
event.alarms.append(alarm)
|
|
|
|
calendar.events.add(event)
|
|
|
|
return str(calendar)
|
|
|
|
|
|
loop = new_event_loop()
|
|
discord_task = loop.create_task(client.start(DISCORD_TOKEN))
|
|
discord_task.add_done_callback(lambda f: loop.stop())
|
|
quart_task = loop.create_task(app.run_task())
|
|
quart_task.add_done_callback(lambda f: loop.stop())
|
|
loop.run_forever()
|