Want to contribute? Fork me on Codeberg.org!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
4.2 KiB

<dialog>
<div class="welcome">
<h1>Welcome to {{ "title" | i18n(lang=lang) }}!</h1>
<p>In order to participate in challenges, you must be a member of a participating Discord server.</p>
<h2>Join a participating server</h2>
</div>
<div class="servers">
{% for guild in settings.guilds %}
{% if guild.hidden or not guild.invite %}{% continue %}{% endif %}
<div id="{{ guild.id }}" {% if guild.recommended %} class="recommended"{% endif %}>
<img src="https://cdn.discordapp.com/icons/{{ guild.id }}/{{ guild.icon }}.webp?size=96" alt="Server icon">
<div class="name">{{ guild.name }}</div>
<a href="https://discord.gg/{{ guild.invite }}" class="joinButton">Join</a>
{% if guild.recommended %}
<div class="label-wrapper">
<div class="label">Recommended</div>
</div>
{% endif %}
</div>
{% endfor %}
</div>
</dialog>
<script>
const dialog = document.querySelector("dialog");
// Fetch guilds
let guilds = null;
let is_in_participating_server = null;
const getGuilds = async () => {
if (guilds === null) {
// Create the guilds dictionary object
guilds = {};
// Create an EventSource object to listen to SSE events
const eventSource = new EventSource('/get_guilds');
// Event listener for 'message' events
eventSource.addEventListener('message', event => {
// Parse the data received from the event
const [id, is_member] = event.data.split(',');
// Add the key-value pair to the guilds dictionary
guilds[id] = is_member === 'true';
if (guilds[id]) {
setJoined(id);
is_in_participating_server = true;
}
});
// Function to block execution until SSE events are done
function waitForSSE() {
return new Promise(resolve => {
// Event listener for 'error' event
// For some reason errors when completing
eventSource.addEventListener('error', () => {
eventSource.close();
resolve();
});
});
}
// Call the function to block execution until SSE events are done
await waitForSSE()
}
return guilds;
}
// Show server modal, both for welcome and server list
const showServers = async () => {
dialog.showModal();
// If the user is logged in, load the guild list
// and check if they have joined the available servers
const guilds = await getGuilds();
Object.keys(guilds).forEach(id => {
if (guilds[id]) {
setJoined(id);
}
})
};
// Switch Join button to Joined for server
const setJoined = id => {
element = document.getElementById(id);
if (element === null) {
return;
}
// Check if already set as joined
a = element.querySelector("a");
if (a === null) {
return;
}
const button = document.createElement("button");
button.tagName = "button";
button.className = "joinButton";
button.disabled = true;
button.innerHTML = "Joined"
element.querySelector("a").replaceWith(button);
}
// Check for welcomed cookie
const welcomed = () => document.cookie.split("; ").includes("welcomed=true");
// Load welcome modal, check if it is necessary
const loadServers = async () => {
if (welcomed()) {
// If already welcomed, remove welcome text
// in case user pressed Join servers button
document.querySelector("dialog .welcome").style.display = "none";
} else {
const guilds = await getGuilds();
if (!is_in_participating_server) {
showServers();
}
// Even if already in participating server,
// set welcomed cookie so we don't have to run this request again
document.cookie = 'welcomed=true; expires=Tue, 19 Jan 2038 03:14:07 UTC; SameSite=Strict; path=/';
}
};
if (welcomed()) {
// TODO: Remove welcome text via cookie check in template?
document.querySelector("dialog .welcome").style.display = "none";
} else {
// If not welcomed, see if welcome is necessary
loadServers();
}
</script>