Some checks failed
Build and Push Docker Image / build (push) Failing after 6m55s
423 lines
11 KiB
JavaScript
423 lines
11 KiB
JavaScript
|
|
// region Loaded Servers
|
|
|
|
var _loadedServers = []
|
|
var selectedServer = null;
|
|
|
|
function getLoadedServer(options) {
|
|
let servers = _loadedServers.filter(item => {
|
|
|
|
for (let key in options) {
|
|
if (item[key] !== options[key]) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
return servers || [];
|
|
}
|
|
|
|
function getServerFromSnowflake(id) {
|
|
server = getLoadedServer({id: id});
|
|
if (!server.length) {
|
|
return null;
|
|
}
|
|
|
|
return server[0];
|
|
}
|
|
|
|
function addToLoadedServers(serverData, autoSelect=false) {
|
|
_loadedServers.push(serverData);
|
|
createSelectButton(serverData);
|
|
|
|
if (autoSelect) {
|
|
selectServer(serverData["id"]);
|
|
}
|
|
}
|
|
|
|
function removeFromLoadedServers(id) {
|
|
_loadedServers = _loadedServers.filter(item => item.id !== id);
|
|
removeSelectButton(id)
|
|
|
|
if (selectedServer.id === id) {
|
|
selectedServer(null);
|
|
}
|
|
}
|
|
|
|
|
|
// region Loaded Channels
|
|
|
|
var _loadedChannels = {};
|
|
async function loadedChannels(serverId) {
|
|
if (!(serverId in _loadedChannels)) {
|
|
await fetchChannels(serverId);
|
|
}
|
|
|
|
return _loadedChannels[serverId]
|
|
}
|
|
|
|
$(document).on("selectedServerChange", async function() {
|
|
// Try load channels to determine if bot has permissions
|
|
loadedChannels(selectedServer.id);
|
|
});
|
|
|
|
const fetchChannels = async serverId => {
|
|
$(".sidebar .sidebar-item").prop("disabled", true);
|
|
|
|
try {
|
|
channels = await ajaxRequest(`/generate-channels?guild=${serverId}`, "GET");
|
|
_loadedChannels[serverId] = channels;
|
|
unspotItem(serverId); // remove the spot because no errors occured
|
|
}
|
|
catch (error) {
|
|
logError(error);
|
|
unspotItem(serverId);
|
|
|
|
switch (error?.status) {
|
|
case 429:
|
|
rateLimitedLoadingChannels(error.responseJSON.retry_after);
|
|
break;
|
|
|
|
case 403:
|
|
notAuthorisedLoadingChannels(serverId);
|
|
break;
|
|
|
|
default:
|
|
alert("unknown error loading channels");
|
|
break;
|
|
}
|
|
|
|
}
|
|
finally {
|
|
$(".sidebar .sidebar-item").prop("disabled", false);
|
|
}
|
|
}
|
|
|
|
const rateLimitedLoadingChannels = retryAfterSeconds => {
|
|
createModal({
|
|
title: "Failed to Fetch Server Channels",
|
|
texts: [
|
|
{ content: "Discord is rate-limiting your request." },
|
|
{ content: `This happens when making requests too quickly. Retry after ${retryAfterSeconds} seconds to continue without issue.` }
|
|
],
|
|
buttons: [
|
|
{
|
|
className: "btn-warning px-4",
|
|
iconClass: "bi-arrow-return-right",
|
|
closeModal: true
|
|
}
|
|
]
|
|
});
|
|
}
|
|
|
|
const notAuthorisedLoadingChannels = serverId => {
|
|
// Mark the sidebar item as non-operational
|
|
spotItem(serverId, "danger");
|
|
|
|
const inviteBotToServer = () => {
|
|
window.open(
|
|
`https://discord.com/oauth2/authorize
|
|
?client_id=${discordClientId}
|
|
&permissions=2147534848
|
|
&scope=bot+applications.commands
|
|
&guild_id=${serverId}
|
|
&disable_guild_select=true`,
|
|
"_blank"
|
|
);
|
|
}
|
|
|
|
// Inform the user auth problem
|
|
createModal({
|
|
title: "Failed to Fetch Server Channels",
|
|
texts: [
|
|
{ content: "The Discord Bot is unable to access this server's channels, certain features will not work." },
|
|
{ content: "Ensure the Bot is a member, and has the neccessary permissions to operate." }
|
|
],
|
|
buttons: [
|
|
{
|
|
text: "Invite the Bot",
|
|
className: "btn-primary me-3",
|
|
iconClass: "bi-envelope-plus",
|
|
closeModal: true,
|
|
onClick: inviteBotToServer
|
|
},
|
|
{
|
|
className: "btn-secondary",
|
|
iconClass: "bi-arrow-return-right",
|
|
closeModal: true
|
|
}
|
|
]
|
|
});
|
|
}
|
|
|
|
|
|
// region UI Buttons
|
|
|
|
function createSelectButton(serverData) {
|
|
// server details
|
|
const id = serverData["id"];
|
|
const name = serverData["name"];
|
|
const iconHash = serverData["icon_hash"];
|
|
const isBotOperational = serverData["is_bot_operational"];
|
|
|
|
let template = $($("#serverItemTemplate").html());
|
|
const imageUrl = `https://cdn.discordapp.com/icons/${id}/${iconHash}.webp?size=80`;
|
|
const altText = name.split(' ').map(word => word.charAt(0)).join(''); // initials of server name, used if iconUrl is 404
|
|
|
|
template.find(".js-image").attr("src", imageUrl).attr("alt", altText);
|
|
template.find(".js-name").text(name);
|
|
template.find(".js-id").text(id);
|
|
template.find(".sidebar-item").attr("data-id", id);
|
|
|
|
// Show inoperational status, also, `isBotOperatioanl` can be null,
|
|
// so we can't rely on it's truthy value.
|
|
if (isBotOperational === false) {
|
|
template.find(".sidebar-item").addClass("spot spot-danger");
|
|
}
|
|
|
|
// Bind the button for selecting this server
|
|
template.find(".sidebar-item").off("click").on("click", function() {
|
|
const myID = $(this).data("id");
|
|
|
|
// only select if not already selected, otherwise hide sidebar on smaller screens (responsive)
|
|
selectedServer?.id !== myID ? selectServer(myID) : setSidebarVisibility(false);
|
|
});
|
|
|
|
$("#serverList").prepend(template);
|
|
}
|
|
|
|
function removeSelectButton(id) {
|
|
$(`#serverList .server-item[data-id=${id}]`).remove();
|
|
}
|
|
|
|
$("#backToSelectServer").on("click", function() {
|
|
$("#noSelectedServer").show();
|
|
$("#selectedServerContainer").hide();
|
|
$("#serverList .server-item > .server-item-selector.active").removeClass("active");
|
|
selectedServer = null;
|
|
});
|
|
|
|
|
|
// #region Server Selection
|
|
|
|
function selectServer(id) {
|
|
let server = getServerFromSnowflake(id);
|
|
|
|
// Change appearance of selected vs none-selected items
|
|
$("#serverList .sidebar-item").removeClass("active");
|
|
$(`#serverList .sidebar-item[data-id="${id}"]`).addClass("active");
|
|
|
|
// Global variable
|
|
selectedServer = server;
|
|
|
|
// Close sidebar on smaller screens
|
|
setSidebarVisibility(false);
|
|
|
|
// Show no server selected if that's the case
|
|
if (!server) {
|
|
$("#noSelectedServer").show();
|
|
$("#selectedServerContainer").hide();
|
|
return;
|
|
}
|
|
|
|
// Update UI
|
|
$("#noSelectedServer").hide();
|
|
$("#selectedServerContainer").show().css("display", "flex");
|
|
|
|
// Announce change to any listeners
|
|
$(document).trigger("selectedServerChange");
|
|
|
|
}
|
|
|
|
|
|
// #region Resolve Strings
|
|
|
|
function resolveServerStrings() {
|
|
// Server icon
|
|
$(".resolve-to-server-icon").attr(
|
|
"src",
|
|
`https://cdn.discordapp.com/icons/${selectedServer.id}/${selectedServer.icon_hash}.webp?size=80`
|
|
).attr("alt", selectedServer.name.split(' ').map(word => word.charAt(0)).join(''));
|
|
|
|
// Server names
|
|
$(".resolve-to-server-name").text(selectedServer.name);
|
|
|
|
// Server Guild Ids
|
|
$(".resolve-to-server-id").text(selectedServer.id);
|
|
|
|
// Bot Invite links
|
|
$(".resolve-to-invite-link").attr("href", `https://discord.com/oauth2/authorize
|
|
?client_id=${discordClientId}
|
|
&permissions=2147534848
|
|
&scope=bot+applications.commands
|
|
&guild_id=${selectedServer.id}
|
|
&disable_guild_select=true`);
|
|
}
|
|
|
|
|
|
// region Change Listener
|
|
|
|
$(document).on("selectedServerChange", async function() {
|
|
resolveServerStrings();
|
|
$("#serverJoinAlert").hide();
|
|
});
|
|
|
|
|
|
// region Load Servers
|
|
|
|
async function loadServers(generate=true) {
|
|
|
|
// Remove any previously loaded servers
|
|
$(".sidebar .sidebar-item").closest("li").remove();
|
|
|
|
// Show placeholder items & hide rate limit warning
|
|
$(".sidebar .sidebar-loading").show();
|
|
$(".sidebar .server-rate-limit").hide();
|
|
|
|
try {
|
|
let data = await ajaxRequest(
|
|
generate ? "/generate-servers/" : "/api/servers/",
|
|
"GET"
|
|
);
|
|
data = generate ? data : data.results; // api responds differently
|
|
data.forEach(server => addToLoadedServers(server, false));
|
|
}
|
|
catch (error) {
|
|
switch (error?.status) {
|
|
case 401:
|
|
window.location.href = "/login"; // discord token has expired
|
|
break;
|
|
case 429:
|
|
$(".sidebar .server-rate-limit").show();
|
|
break;
|
|
default:
|
|
logError(error);
|
|
break;
|
|
}
|
|
}
|
|
finally {
|
|
$(".sidebar .sidebar-loading").hide();
|
|
}
|
|
}
|
|
|
|
// Retry load servers button
|
|
$(".sidebar .sidebar-retry-btn").on("click", loadServers);
|
|
|
|
|
|
// region Spot Icons
|
|
|
|
const unspotItem = id => {
|
|
$(`.sidebar .sidebar-item[data-id="${id}"]`).removeClass(
|
|
"spot spot-primary spot-secondary spot-success spot-info spot-warning spot-danger"
|
|
);
|
|
}
|
|
|
|
const spotItem = (id, spotStyle) => {
|
|
$(`.sidebar .sidebar-item[data-id="${id}"]`).addClass(`spot spot-${spotStyle}`);
|
|
}
|
|
|
|
|
|
// region View Other Users
|
|
|
|
$(".js-serverUsersBtn").on("click", () => {
|
|
createModal({
|
|
title: "Other Users",
|
|
texts: [
|
|
{content: "This feature has not yet been implemented."}
|
|
],
|
|
buttons: [
|
|
{
|
|
className: "btn-secondary px-4",
|
|
iconClass: "bi-arrow-return-right",
|
|
closeModal: true
|
|
}
|
|
]
|
|
});
|
|
});
|
|
|
|
|
|
// region View Edit History
|
|
|
|
$(".js-serverHistoryBtn").on("click", () => {
|
|
createModal({
|
|
title: "Edit History",
|
|
texts: [
|
|
{content: "This feature has not yet been implemented."}
|
|
],
|
|
buttons: [
|
|
{
|
|
className: "btn-secondary px-4",
|
|
iconClass: "bi-arrow-return-right",
|
|
closeModal: true
|
|
}
|
|
]
|
|
});
|
|
});
|
|
|
|
|
|
// region Delete Server Data
|
|
|
|
const eraseServerData = async server => {
|
|
const response = await ajaxRequest(`/api/servers/${server.id}/`, "DELETE");
|
|
|
|
// Only server owners can delete all data at once
|
|
if (response?.status === 403) {
|
|
createModal({
|
|
title: `Failed to Delete Data for ${server.name}`,
|
|
texts: [{
|
|
content: `Only the owner of <b>${server.name}</b> can erase all of it's data.`,
|
|
html: true
|
|
}],
|
|
buttons: [{
|
|
className: "btn-danger px-4",
|
|
iconClass: "bi-arrow-return-right",
|
|
closeModal: true
|
|
}]
|
|
});
|
|
return;
|
|
}
|
|
|
|
// Return to the 'select a server' screen
|
|
selectServer(null);
|
|
|
|
// Refresh the sidebar server list
|
|
await loadServers(false);
|
|
}
|
|
|
|
$(".js-closeServerBtn").on("click", () => {
|
|
selectServer(null);
|
|
});
|
|
|
|
$(".js-eraseServerBtn").on("click", () => {
|
|
const server = selectedServer; // Store incase it changes
|
|
const itemsToLose = arrayToHtmlList([
|
|
"Subscriptions",
|
|
"Filters",
|
|
"Message Styles",
|
|
"Tracked Content"
|
|
]).addClass("mb-3").prop("outerHTML");
|
|
|
|
createModal({
|
|
title: `Delete Data for ${server.name}?`,
|
|
texts: [
|
|
{content: "You will lose all data related to this server, including:"},
|
|
{content: itemsToLose, html: true},
|
|
{content: "Please reconsider this decision."}
|
|
],
|
|
buttons: [
|
|
{
|
|
className: "btn-danger me-3",
|
|
iconClass: "bi-trash3",
|
|
closeModal: true,
|
|
onClick: () => eraseServerData(server)
|
|
},
|
|
{
|
|
className: "btn-secondary px-4",
|
|
iconClass: "bi-arrow-return-right",
|
|
closeModal: true
|
|
}
|
|
]
|
|
})
|
|
}); |