v4: Personal calendar #168

Merged
Xefir merged 5 commits from v4 into master 2023-11-07 00:40:58 +00:00
8 changed files with 77 additions and 72 deletions
Showing only changes of commit 0f42bdc50b - Show all commits

View File

@ -5,7 +5,7 @@ from functools import wraps
from os import getenv, path from os import getenv, path
from typing import Dict, Optional from typing import Dict, Optional
from disnake import Client, Guild from disnake import Asset, Client, Guild
from disnake.guild_scheduled_event import GuildScheduledEvent from disnake.guild_scheduled_event import GuildScheduledEvent
from dotenv import load_dotenv from dotenv import load_dotenv
from ics import Calendar, ContentLine, Event from ics import Calendar, ContentLine, Event
@ -117,17 +117,11 @@ def days_before_failure() -> int:
return nextDelta.days return nextDelta.days
def cdn_avatar_url(user_id: int, hash: str) -> str:
ext = "gif" if hash.startswith("a_") else "png"
return f"https://cdn.discordapp.com/avatars/{user_id}/{hash}.{ext}"
@app.context_processor @app.context_processor
def context_processor(): def context_processor():
return dict( return dict(
_=i18n, _=i18n,
client=client, client=client,
cdn_avatar_url=cdn_avatar_url,
days_before_failure=days_before_failure(), days_before_failure=days_before_failure(),
) )
@ -180,12 +174,10 @@ async def callback():
@app.route("/guilds") @app.route("/guilds")
@login_required @login_required
async def guilds(): async def guilds():
guild = get_guild_by_id(request.args.get("guild")) guild = request.args.get("guild")
if guild: if guild:
return redirect( return redirect(url_for(".subscribe", entity_id=guild))
url_for(".subscribe", guild_id=guild.vanity_url_code or guild.id)
)
try: try:
discord = make_session(token=session.get("oauth2_token")) discord = make_session(token=session.get("oauth2_token"))
@ -201,27 +193,42 @@ async def guilds():
common_guilds.append(bot_guild) common_guilds.append(bot_guild)
return await render_template( return await render_template(
"guilds.html.j2", user=user, common_guilds=common_guilds "guilds.html.j2",
user=user,
avatar=Asset._from_avatar(None, user["id"], user["avatar"]),
common_guilds=common_guilds,
) )
@app.route("/subscribe/<guild_id>") @app.route("/subscribe/<entity_id>")
@login_required @login_required
async def subscribe(guild_id: str): async def subscribe(entity_id: str):
guild = get_guild_by_id(guild_id) guild = get_guild_by_id(entity_id)
if guild is None:
return redirect(url_for(".login"))
try: if guild:
discord = make_session(token=session.get("oauth2_token")) try:
user_guilds = discord.get(f"{API_BASE_URL}/users/@me/guilds").json() discord = make_session(token=session.get("oauth2_token"))
except OAuth2Error: user_guilds = discord.get(f"{API_BASE_URL}/users/@me/guilds").json()
return redirect(url_for(".login")) except OAuth2Error:
return redirect(url_for(".login"))
if not any(str(guild.id) == user_guild["id"] for user_guild in user_guilds): if not any(str(guild.id) == user_guild["id"] for user_guild in user_guilds):
return redirect(url_for(".login")) return redirect(url_for(".login"))
return await render_template("subscribe.html.j2", guild=guild) return await render_template(
"subscribe.html.j2",
avatar=guild.icon,
entity_id=guild.vanity_url_code or guild.id,
)
user = await client.get_or_fetch_user(int(entity_id))
if user and str(user.id) == entity_id:
return await render_template(
"subscribe.html.j2", avatar=user.avatar, entity_id=user.id
)
return redirect(url_for(".login"))
def make_event(scheduled_event: GuildScheduledEvent, guild_id: int) -> Event: def make_event(scheduled_event: GuildScheduledEvent, guild_id: int) -> Event:
@ -274,7 +281,7 @@ async def ical(entity_id: str):
return calendar.serialize() return calendar.serialize()
user = client.get_or_fetch_user(int(entity_id)) user = await client.get_or_fetch_user(int(entity_id))
if user: if user:
calendar = Calendar() calendar = Calendar()
@ -288,10 +295,14 @@ async def ical(entity_id: str):
) )
for guild in client.guilds: for guild in client.guilds:
if guild.get_or_fetch_member(int(entity_id)): if await guild.get_or_fetch_member(int(entity_id)):
for scheduled_event in guild.scheduled_events: for scheduled_event in guild.scheduled_events:
event = make_event(scheduled_event, guild.id) if user.id in [
calendar.events.append(event) member.id
for member in await scheduled_event.fetch_users().flatten()
]:
event = make_event(scheduled_event, guild.id)
calendar.events.append(event)
return calendar.serialize() return calendar.serialize()

View File

@ -6,11 +6,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="" /> <meta name="description" content="" />
<meta name="keywords" content="" /> <meta name="keywords" content="" />
<title>{{ client.user.display_name }} - {{ _('The discord scheduled event calendar generator') }}</title> <title>{{ client.user.display_name }} - {{ _("The discord scheduled event calendar generator") }}</title>
<link rel="stylesheet" <link rel="stylesheet"
href="{{ url_for('static', filename='css/font-awesome.min.css') }}"/> href="{{ url_for('static', filename='css/font-awesome.min.css') }}" />
<link rel="stylesheet" <link rel="stylesheet"
href="{{ url_for('static', filename='css/global.css') }}"/> href="{{ url_for('static', filename='css/global.css') }}" />
</head> </head>
<body> <body>
<div id="content"> <div id="content">

View File

@ -3,17 +3,17 @@
<div id="box"> <div id="box">
<div id="avatars"> <div id="avatars">
<img src="{{ url_for('static', filename='img/deadlink.png') }}" <img src="{{ url_for('static', filename='img/deadlink.png') }}"
alt="{{ _('Link is dead') }}" alt="{{ _("Link is dead") }}"
height="179" height="179"
width="173"/> width="173" />
</div> </div>
<hr /> <hr />
<span>{{ error }}</span> <span>{{ error }}</span>
</div> </div>
<div id="buttons"> <div id="buttons">
<a href="{{ url_for('index') }}"> <a href="{{ url_for("index") }}">
<i class="fa fa-arrow-left"></i> <i class="fa fa-arrow-left"></i>
{{ _('Back to the beginning') }} {{ _("Back to the beginning") }}
</a> </a>
</div> </div>
{% endblock content %} {% endblock content %}

View File

@ -2,7 +2,7 @@
<li> <li>
<a href="https://discord.com/users/133305654512320513" target="_blank"> <a href="https://discord.com/users/133305654512320513" target="_blank">
<i class="fa fa-user-plus"></i> <i class="fa fa-user-plus"></i>
{{ _('Add author on Discord') }} {{ _("Add author on Discord") }}
</a> </a>
</li> </li>
<li> <li>
@ -16,17 +16,17 @@
<li> <li>
<a href="https://git.crystalyx.net/Xefir/Divent" target="_blank"> <a href="https://git.crystalyx.net/Xefir/Divent" target="_blank">
<i class="fa fa-code-fork"></i> <i class="fa fa-code-fork"></i>
{{ _('View the source code') }} {{ _("View the source code") }}
</a> </a>
</li> </li>
<li> <li>
<a href="https://hub.docker.com/r/xefir/divent" target="_blank"> <a href="https://hub.docker.com/r/xefir/divent" target="_blank">
<i class="fa fa-cubes"></i> <i class="fa fa-cubes"></i>
{{ _('Host it yourself') }} {{ _("Host it yourself") }}
</a> </a>
</li> </li>
<li> <li>
<i class="fa fa-heartbeat"></i> <i class="fa fa-heartbeat"></i>
{{ _('Next castastrophic life failure in about %days% days') | replace('%days%', days_before_failure) }} {{ _("Next castastrophic life failure in about %days% days") | replace('%days%', days_before_failure) }}
</li> </li>
</ul> </ul>

View File

@ -4,31 +4,26 @@
<div id="box"> <div id="box">
<div id="avatars"> <div id="avatars">
<img src="{{ client.user.display_avatar }}" <img src="{{ client.user.display_avatar }}"
alt="{{ _('Bot Logo') }}" alt="{{ _("Bot Logo") }}"
width="80" width="80"
height="80"/> height="80" />
<span id="dots">…</span> <span id="dots">…</span>
<img src="{{ cdn_avatar_url(user.id, user.avatar) }}" <img src="{{ avatar.url }}"
alt="{{ _('User Avatar') }}" alt="{{ _("User Avatar") }}"
width="80" width="80"
height="80"/> height="80" />
</div> </div>
<h1> <h1>
<a href="{{ url_for(".index") }}">{{ client.user.display_name }}</a> <a href="{{ url_for(".index") }}">{{ client.user.display_name }}</a>
</h1> </h1>
<a class="button" href="{{ url_for(".guilds", guild=user.id) }}"> <h2>{{ _("The discord scheduled event calendar generator") }}</h2>
{{ _("For all your servers") }} <hr>
</a> <a class="button" href="{{ url_for(".guilds", guild=user.id) }}">{{ _("For all your servers") }}</a>
<div class="hr-sect">{{ _("OR") }}</div> <div class="hr-sect">{{ _("OR") }}</div>
<h3>{{ _('Choose a server:') }}</h3>
<select name="guild" class="black_input" onchange="this.form.submit()"> <select name="guild" class="black_input" onchange="this.form.submit()">
<option> <option>&nbsp;</option>
&nbsp;
</option>
{% for guild in common_guilds %} {% for guild in common_guilds %}
<option value="{{ guild.vanity_url_code|default(guild.id, True) }}"> <option value="{{ guild.vanity_url_code|default(guild.id, True) }}">{{ guild.name }}</option>
{{ guild.name }}
</option>
{% endfor %} {% endfor %}
</select> </select>
<div class="hr-sect">{{ _("OR") }}</div> <div class="hr-sect">{{ _("OR") }}</div>

View File

@ -4,24 +4,24 @@
<div id="box"> <div id="box">
<div id="avatars"> <div id="avatars">
<img src="{{ client.user.display_avatar }}" <img src="{{ client.user.display_avatar }}"
alt="{{ _('Bot Logo') }}" alt="{{ _("Bot Logo") }}"
width="80" width="80"
height="80"/> height="80" />
</div> </div>
<h1> <h1>
<a href="{{ url_for(".index") }}">{{ client.user.display_name }}</a> <a href="{{ url_for(".index") }}">{{ client.user.display_name }}</a>
</h1> </h1>
<h2>{{ _('The discord scheduled event calendar generator') }}</h2> <h2>{{ _("The discord scheduled event calendar generator") }}</h2>
<hr /> <hr />
<h3>{{ _('This will allow you to:') }}</h3> <h3>{{ _("This will allow you to:") }}</h3>
<ul id="scopes"> <ul id="scopes">
<li> <li>
<i class="fa fa-custom-circle fa-check"></i> <i class="fa fa-custom-circle fa-check"></i>
{{ _('Subscribe to a calendar on Google, Outlook, Apple or any ICS complient software') }} {{ _("Subscribe to a calendar on Google, Outlook, Apple or any ICS complient software") }}
</li> </li>
<li> <li>
<i class="fa fa-custom-circle fa-times"></i> <i class="fa fa-custom-circle fa-times"></i>
{{ _('Throwing you to a new isekai world') }} {{ _("Throwing you to a new isekai world") }}
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -3,25 +3,25 @@
<div id="box"> <div id="box">
<div id="avatars"> <div id="avatars">
<img src="{{ client.user.display_avatar }}" <img src="{{ client.user.display_avatar }}"
alt="{{ _('Bot Logo') }}" alt="{{ _("Bot Logo") }}"
width="80" width="80"
height="80"/> height="80" />
<span id="dots">…</span> <span id="dots">…</span>
<img src="{{ guild.icon.url }}" <img src="{{ avatar.url }}"
alt="{{ _('Guild Logo') }}" alt="{{ _("Avatar") }}"
width="80" width="80"
height="80"/> height="80" />
</div> </div>
<h1> <h1>
<a href="{{ url_for(".index") }}">{{ client.user.display_name }}</a> <a href="{{ url_for(".index") }}">{{ client.user.display_name }}</a>
</h1> </h1>
<h2>{{ _('The discord scheduled event calendar generator') }}</h2> <h2>{{ _("The discord scheduled event calendar generator") }}</h2>
<hr /> <hr />
<ul id="providers"> <ul id="providers">
<li> <li>
<a class="button" <a class="button"
target="_blank" target="_blank"
href="https://calendar.google.com/calendar/u/0/r?cid=webcal://{{ request.host }}/{{ guild.vanity_url_code|default(guild.id, True) }}.ics"> href="https://calendar.google.com/calendar/u/0/r?cid=webcal://{{ request.host }}/{{ entity_id }}.ics">
<i class="fa fa-google"></i> <i class="fa fa-google"></i>
{{ _("Subscribe to") }} Google {{ _("Subscribe to") }} Google
</a> </a>
@ -29,14 +29,14 @@
<li> <li>
<a class="button" <a class="button"
target="_blank" target="_blank"
href="https://outlook.live.com/owa?path=/calendar/action/compose&rru=addsubscription&url=webcal://{{ request.host }}/{{ guild.vanity_url_code|default(guild.id, True) }}.ics"> href="https://outlook.live.com/owa?path=/calendar/action/compose&rru=addsubscription&url=webcal://{{ request.host }}/{{ entity_id }}.ics">
<i class="fa fa-windows"></i> <i class="fa fa-windows"></i>
{{ _("Subscribe to") }} Outlook {{ _("Subscribe to") }} Outlook
</a> </a>
</li> </li>
<li> <li>
{# djlint:off #} {# djlint:off #}
<a class="button" target="_blank" href="webcal://{{ request.host }}/{{ guild.vanity_url_code|default(guild.id, True) }}.ics"> <a class="button" target="_blank" href="webcal://{{ request.host }}/{{ entity_id }}.ics">
<i class="fa fa-apple"></i> <i class="fa fa-apple"></i>
{{ _("Subscribe to") }} Apple {{ _("Subscribe to") }} Apple
</a> </a>
@ -47,7 +47,7 @@
<div> <div>
<h3>{{ _("Use the direct link:") }}</h3> <h3>{{ _("Use the direct link:") }}</h3>
{# djlint:off #} {# djlint:off #}
<input type="text" readonly class="black_input" value="webcal://{{ request.host }}/{{ guild.vanity_url_code|default(guild.id, True) }}.ics"/> <input type="text" readonly class="black_input" value="webcal://{{ request.host }}/{{ entity_id }}.ics"/>
{# djlint:on #} {# djlint:on #}
</div> </div>
</div> </div>

View File

@ -6,7 +6,6 @@
"Subscribe to a calendar on Google, Outlook, Apple or any ICS complient software": "T'abonner à un calendrier sur Google, Outlook, Apple ou tout autre logiciel compatible", "Subscribe to a calendar on Google, Outlook, Apple or any ICS complient software": "T'abonner à un calendrier sur Google, Outlook, Apple ou tout autre logiciel compatible",
"Throwing you to a new isekai world": "T'envoyer dans un monde fantaisiste armée d'une poêle à frire", "Throwing you to a new isekai world": "T'envoyer dans un monde fantaisiste armée d'une poêle à frire",
"For all your servers": "Pour tous tes serveurs", "For all your servers": "Pour tous tes serveurs",
"Choose a server:": "Choisi un serveur :",
"You must have": "Tu dois avoir la permission", "You must have": "Tu dois avoir la permission",
"Manage Server": "Gérer le serveur", "Manage Server": "Gérer le serveur",
"permission on this server to perform this action": "sur ce serveur pour effectuer cette action", "permission on this server to perform this action": "sur ce serveur pour effectuer cette action",