diff --git a/media/channel/13.svg b/media/channel/13.svg new file mode 100644 index 0000000..aad9219 --- /dev/null +++ b/media/channel/13.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/media/script.js b/media/script.js index 19d3783..db61696 100644 --- a/media/script.js +++ b/media/script.js @@ -32,30 +32,70 @@ function proxyFetch(url, o) { body: JSON.stringify(opts) }) } -function parseMD(text) { - return text +function parseMD(text, extended=true) { + let reserve = {}; + function reservemd(txt) { + let id = Math.floor(Math.random()*Math.pow(10, 16)).toString(10).padStart(16, '0'); + reserve[id] = txt; + return `¬r${id}¬r`; + } + // Escaping + Pre steps + text = text .replaceAll('<', '~lt;') - .replaceAll('"', '~quot;') + .replaceAll('"', '~quot;'); + if (extended) { + text = text.replaceAll(/```([^¬]|¬)*?```/g, function(match){ + match = match + .replaceAll('&', '&') + .replaceAll('~lt;', '<') + .replaceAll('~quot;', '"'); + return reservemd(`${match.slice(3,-3)}`); + }); + } + text = text .replaceAll(/(~lt;https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)>|https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*))/g, function(match){ if (match.match(/^~lt;.+?>$/m)) match=match.slice(4,-1); - return `${match}` + return reservemd(`${match}`); }) .replaceAll('&', '&') .replaceAll('~lt;', '<') .replaceAll('~quot;', '"') - .replaceAll("'", ''') + .replaceAll("'", '''); + // General + text = text .replaceAll(/\*\*.+?\*\*/g, function(match){return ''+match.slice(2,-2)+''}) .replaceAll(/\*.+?\*/g, function(match){return ''+match.slice(1,-1)+''}) .replaceAll(/\_\_.+?\_\_/g, function(match){return ''+match.slice(2,-2)+''}) .replaceAll(/\_.+?\_/g, function(match){return ''+match.slice(1,-1)+''}) .replaceAll(/\~\~.+?\~\~/g, function(match){return ''+match.slice(2,-2)+''}) .replaceAll(/\|\|.+?\|\|/g, function(match){return ``+match.slice(2,-2)+''}) - .replaceAll(/^\> .+?$/gm, function(match){return '
'+match.slice(2)+'
'}) - .replaceAll(/^### .+?$/gm, function(match){return ''+match.slice(4)+''}) - .replaceAll(/^## .+?$/gm, function(match){return ''+match.slice(3)+''}) - .replaceAll(/^# .+?$/gm, function(match){return ''+match.slice(2)+''}) - .replaceAll(/^-# .+?$/gm, function(match){return ''+match.slice(3)+''}) - .replaceAll(/^(-|\*) .+?$/gm, function(match){return '
  • '+match.slice(2)+'
  • '}); + .replaceAll(/\`.+?\`/g, function(match){return ''+match.slice(1,-1)+''}) + .replaceAll(/^\> .+?$/gm, function(match){return '
    '+match.slice(2)+'
    '}); + // Discord + text = text + .replaceAll(/<:.+?:[0-9]+?>/g, function(match){ + let parts = match.replace('>','').split(':'); + return ``; + }); + // Extended + if (extended) { + text = text + .replaceAll(/^### .+?$/gm, function(match){return ''+match.slice(4)+''}) + .replaceAll(/^## .+?$/gm, function(match){return ''+match.slice(3)+''}) + .replaceAll(/^# .+?$/gm, function(match){return ''+match.slice(2)+''}) + .replaceAll(/^-# .+?$/gm, function(match){return ''+match.slice(3)+''}) + .replaceAll(/^(-|\*) .+?$/gm, function(match){return '
  • '+match.slice(2)+'
  • '}); + } + // Reserve + text = text.replaceAll(/¬r[0-9]{16}¬r/g, function(match){ + let id = match.split('¬r')[1]; + if (reserve[id]) { + return reserve[id]; + } else { + return match; + } + }) + return text; } const channelIcons = {}; function fetchChannelIcon(type) { @@ -85,9 +125,18 @@ function getUserAvatar(id, hash, size = 64) { if (hash==='system') return '/media/fshcord.png'; return `https://cdn.discordapp.com/avatars/${id}/${hash}.${hash.startsWith('a_')?'gif':'webp'}?size=${size}`; } + function colorToRGB(color) { return `#${color.toString(16).padStart(6, '0')}`; } +function formateDate(date, format='r') { + if (format==='r') { + return date; + } else { + return date; + } +} + function loading(text) { Toastify({ text: 'Loading '+text, @@ -199,17 +248,33 @@ image - link - post_preview rich - -video +video - */ + let c; switch (embed.type) { case 'gifv': return ``; case 'image': return ``; - /*case 'article': + case 'article': case 'link': case 'rich': - return `
    `*/ + case 'video': + c=[embed.title, embed.description, embed?.author?.name, embed?.provider?.name].filter(e=>!!e).length; + return `
    + ${embed.thumbnail&&embed.type!=='video'?``:''} + ${embed?.provider?.name?`${embed.provider.name}`:''} + ${embed?.author?.name?`${embed.author.proxy_icon_url?``:''}${embed.author.name}`:''} + ${embed.title?`${parseMD(embed.title, false)}`:''} + ${embed.description&&embed.type!=='video'?`${parseMD(embed.description)}`:''} + ${embed.fields?`
    ${embed.fields.map(f=>`
    + ${parseMD(f.name, false)} + ${parseMD(f.value)} +
    `).join('')}
    `:''} + ${embed.video?(embed.video.proxy_url?``:``):''} + ${embed.image&&embed.type!=='video'?``:''} + ${embed?.footer?.text||embed.timestamp?`${embed?.footer?.text?`${embed.footer.proxy_icon_url?``:''}${embed.footer.text}`:''}${embed?.footer?.text&&embed.timestamp?'':''}${embed.timestamp?`${formateDate(embed.timestamp)}`:''}`:''} +
    `; default: report(`Unknown embed type: ${embed.type}`, embed); return `Unknown embed type: ${embed.type}`; @@ -219,8 +284,8 @@ function renderMessage(content, author, m) { return `
    - ${author.global_name ?? author.username}${m.edited_timestamp?' · Edited':''} - ${parseMD(content)} + ${author.global_name ?? author.username}${[author.system,m.webhook_id,author.bot].filter(e=>!!e).length?`${author.system?'SYSTEM':(m.webhook_id?'WEBHOOK':(author.bot?'BOT':''))}`:''}${m.edited_timestamp?' · Edited':''} + ${parseMD(content)} ${m.attachments.length?m.attachments.map(attach=>{ if (!attach.content_type) attach.content_type='image/'+attach.url.split('?')[0].split('.').slice(-1)[0]; return `<${attach.content_type.startsWith('image/')?'img':attach.content_type.startsWith('audio/')?'audio':attach.content_type.startsWith('video/')?'video':'div'} src="${attach.url}" width="${Math.floor(attach.width/2)}" height="${Math.floor(attach.height/2)}" class="message-attach" controls>${attach.content_type.startsWith('image/')?'':attach.content_type.startsWith('audio/')?'':attach.content_type.startsWith('video/')?'':`${attach.filename}
    `}`; @@ -276,7 +341,9 @@ const SystemAuthor = { id: 0, avatar: 'system', global_name: 'System', - username: 'system' + username: 'system', + bot: true, + system: true } function showMessages(list) { document.getElementById('messages').innerHTML = list.map(m=>{ @@ -549,14 +616,17 @@ if (!localStorage.getItem('token')) { window.data.settings = settings; loading('icons') - await fetchChannelIcon('folder'); - await fetchChannelIcon(0); - await fetchChannelIcon(1); - await fetchChannelIcon(2); - await fetchChannelIcon(3); - await fetchChannelIcon(5); - await fetchChannelIcon(15); - await fetchChannelIcon(16); + await Promise.allSettled([ + fetchChannelIcon('folder'), + fetchChannelIcon(0), + fetchChannelIcon(1), + fetchChannelIcon(2), + fetchChannelIcon(3), + fetchChannelIcon(5), + fetchChannelIcon(13), + fetchChannelIcon(15), + fetchChannelIcon(16) + ]); loading('servers'); let servers = await proxyFetch('https://discord.com/api/v10/users/@me/guilds'); diff --git a/media/style.css b/media/style.css index 6e10c6a..5f12fd6 100644 --- a/media/style.css +++ b/media/style.css @@ -170,8 +170,6 @@ main { gap: 10px; padding: 2px 5px; border-radius: 1rem; - word-break: break-word; - white-space: break-spaces; transition: 250ms; } .message:hover { @@ -180,6 +178,13 @@ main { .message .name { color: var(--text-0); } +.message .tag { + font-size: 75%; + padding: 0px 2px; + margin-left: 5px; + border-radius: 0.25rem; + background-color: var(--blue-1); +} .message > img { height: 40px; border-radius: 2rem; @@ -187,6 +192,11 @@ main { .message > span { display: flex; flex-direction: column; + width: 100%; +} +.message .inner { + word-break: break-word; + white-space: break-spaces; } .message-attach { max-width: 45%; @@ -200,20 +210,145 @@ audio.message-attach { } div.message-attach { padding: 15px; - border: 2px var(--bg-1) solid; border-radius: 2rem; background-color: var(--bg-2); + transition: background-color 250ms; +} +.message:hover div.message-attach { + background-color: var(--bg-1); } lottie-sticker.message-attach { width: 160px; height: 160px; } +.message-emoji { + width: 18px; + height: 18px; + object-fit: contain; + margin-bottom: -4px; +} +.message-rich-embed { + display: flex; + align-items: flex-start; + flex-direction: column; + position: relative; + width: fit-content; + max-width: 80%; + margin: 2px; + border-radius: 0.5rem; + padding: 10px; + white-space: normal; + background-color: var(--bg-2); + transition: background-color 250ms; +} +.message-rich-embed::before { + content: ""; + display: inline-block; + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 4px; + border-radius: 1rem 0 0 1rem; + background-color: var(--embed-color); +} +.message:hover .message-rich-embed { + background-color: var(--bg-1); +} +.message-rich-embed a { + text-decoration: none; +} +.message-rich-embed a[href]:hover { + cursor: pointer; + text-decoration: underline; +} +.message-rich-embed .thumbnail { + position: absolute; + top: 10px; + right: 12px; + width: 50px; + height: 50px; + margin: 0; +} +.message-rich-embed .sub { + cursor: auto; + font-size: 75%; + color: var(--text-2); +} +.message-rich-embed .etitle { + font-weight: bold; +} +.message-rich-embed .etitle:not([href]) { + cursor: auto; + color: var(--text-1); +} +.message-rich-embed .desc { + word-break: break-word; + white-space: break-spaces; +} +.message-rich-embed .fields { + display: flex; + flex-wrap: wrap; + width: 100%; +} +.message-rich-embed .fields > div { + display: flex; + flex: 1 1 33.33%; + flex-direction: column; +} +.message-rich-embed .footer { + display: flex; + gap: 5px; + align-items: center; + color: var(--text-2); + font-size: 75%; +} +.message-rich-embed .footer .text, .message-rich-embed .sub { + display: flex; + gap: 3px; + align-items: center; +} +.message-rich-embed .footer img, .message-rich-embed .sub img { + width: 15px; + height: 15px; + border-radius: 2rem; +} +.message-rich-embed .footer .dot { + width: 4px; + height: 4px; + border-radius: 2rem; + background-color: var(--text-2); +} +.message-rich-embed iframe { + width: 100%; + aspect-ratio: 16 / 9; + max-width: 100%; + max-height: unset; +} +.message code { + word-break: break-word; + white-space: break-spaces; + padding: 2px; + border-radius: 0.25rem; + background-color: var(--bg-0); +} blockquote { display: unset; - margin: 0; - padding-left: 10px; - border-left: 4px var(--text-2) solid; + position: relative; + margin: 0px; + padding-left: 15px; +} +blockquote::before { + content: ""; + display: inline-block; + position: absolute; + top: -1px; + left: 0; + width: 4px; + height: 22px; + border-radius: 1rem; + background-color: var(--text-2); } .input-bar {