// number of messages to load at once when clicking "load more" const MESSAGE_LOAD_LIMIT = 150; const BASE_TITLE = document.title; let currentChannel; //image file formats which can be rendered in browser let imageFormats = [ "bmp", "gif", "ico", "jpeg", "jpe", "jpg", "jfif", "apng", "png", "tga", "tiff", "tif", "svg", "webp", ]; const loadMessages = async (channelId, skip = 0, initial = false) => { let channelEl = document.getElementById(`channel-${channelId}`); // hack to avoid loading the same messages repeatedly if clicking the channel repeatedly without switching if (channelEl.classList.contains("channel-active") && skip == 0) return; Array.from(document.querySelectorAll(".channel-active")).forEach(ch => { ch.classList.remove("channel-active"); }); channelEl.classList.add("channel-active"); window.location.hash = channelId; document.title = `${channelEl.children[0].textContent} | ${BASE_TITLE}`; const messages = document.getElementById("messages"); const prevHeight = Array.from(messages.children).reduce((accumulator, element) => accumulator + element.offsetHeight, 0); const loadButton = document.getElementById("load-more-button"); if (loadButton) { loadButton.outerHTML = ""; } if (currentChannel !== channelId) messages.innerHTML = ""; currentChannel = channelId; const channelData = await fetch( `/api/v1/discord/channel/${channelId}?o=${skip}` ).then(resp => resp.json()); channelData.map((msg) => { let dls = ""; let avatarurl = ""; let embeds = ""; if (msg.content) { msg.content = msg.content .replace(/&/g, "&") .replace(//g, ""); // XXX scanning for < here because < was encoded—not really ideal // the a? is because animated emojis are msg.content = msg.content.replace(/<a?:(.+?):(\d+)>/g, ''); } msg.attachments.map((dl) => { if (imageFormats.includes(dl.name.split(".").pop())) { dls += `
`; } else { dls += `Download ${dl.name .replace(/&/g, "&") .replace(/
`; } }); msg.embeds.map((embed) => { // XXX this is almost definitely wrong embeds += `

${(embed.description || embed.title || "") .replace(/&/g, "&") .replace(/

`; }); if (msg.author.avatar) { avatarurl = `https://cdn.discordapp.com/avatars/${msg.author.id}/${msg.author.avatar}`; } else { avatarurl = "/static/discordgrey.png"; } messages.innerHTML = `

${msg.author.username.replace(/&/g, "&").replace(/

${new Date(msg.published)}

${msg.content}

${dls} ${embeds}
` + messages.innerHTML; }); // avoid adding the button if there are no more messages if (channelData.length == MESSAGE_LOAD_LIMIT) { messages.innerHTML = `
` + messages.innerHTML; } else { messages.innerHTML = `

End of channel history

` + messages.innerHTML; } messages.scrollTop = messages.scrollHeight - prevHeight; }; const load = async () => { const pathname = window.location.pathname.split("/"); const serverData = await fetch(`/api/v1/discord/channel/lookup/${pathname[3]}`); const server = await serverData.json(); const channels = document.getElementById("channels"); server.forEach((ch) => { const channel = document.getElementById(`channel-${ch.id}`); if (!channel) { channels.innerHTML += `

#${ch.name.replace(/&/g, "&").replace(/

`; } }); const serverID = window.location.href.match(/\/discord\/server\/(\d+)/)[1]; channels.innerHTML += `
Linked Accounts
`; if (window.location.hash !== "") { loadMessages(window.location.hash.slice(1).split("-")[0]); } }; load();