diff --git a/README.rst b/README.rst
index d676613..69d0f82 100644
--- a/README.rst
+++ b/README.rst
@@ -39,7 +39,6 @@ Usage
@bot.event
async def on_ready():
print("Live: " + bot.user.name)
- chat_exporter.init_exporter(bot)
@bot.command()
@@ -49,7 +48,7 @@ Usage
if __name__ == "__main__":
bot.run("BOT_TOKEN_HERE")
-*Optional: If you want to display Members Colours (Role Colours) then enable the Members Intent.*
+*Optional: If you want the transcript to display Members (Role) Colours then enable the Members Intent.*
Screenshots
-----------
diff --git a/chat_exporter/__init__.py b/chat_exporter/__init__.py
index cd0f1d7..b565a01 100644
--- a/chat_exporter/__init__.py
+++ b/chat_exporter/__init__.py
@@ -1,2 +1,2 @@
-from chat_exporter.chat_exporter import export, init_exporter, generate_transcript
+from chat_exporter.chat_exporter import export, generate_transcript
from chat_exporter import chat_exporter_html
diff --git a/chat_exporter/chat_exporter.py b/chat_exporter/chat_exporter.py
index e2c511d..843b10d 100644
--- a/chat_exporter/chat_exporter.py
+++ b/chat_exporter/chat_exporter.py
@@ -6,7 +6,7 @@
import traceback
from chat_exporter.misc_tools import escape_html, member_colour_translator
from chat_exporter.mention_convert import parse_mentions, escape_mentions, unescape_mentions
-from chat_exporter.markdown_convert import parse_markdown, parse_embed_markdown, parse_emoji
+from chat_exporter.markdown_convert import parse_markdown, parse_embed_markdown, parse_emoji, https_http_links
from chat_exporter.emoji_convert import convert_emoji
from pytz import timezone
from datetime import timedelta
@@ -16,13 +16,6 @@
eastern = timezone("US/Eastern")
utc = timezone("UTC")
-bot = None
-
-
-def init_exporter(_bot):
- global bot
- bot = _bot
-
async def export(ctx):
# noinspection PyBroadException
@@ -62,7 +55,10 @@ async def export(ctx):
await ctx.channel.send(embed=transcript_embed, file=transcript_file)
-async def generate_transcript(channel):
+async def generate_transcript(channel: discord.TextChannel, tz_info="US/Eastern"):
+ global eastern
+ eastern = timezone(tz_info)
+
# noinspection PyBroadException
try:
transcript = await produce_transcript(channel)
@@ -98,6 +94,8 @@ async def produce_transcript(channel):
for e in m.embeds:
fields = ""
for f in e.fields:
+ f.name = await https_http_links(f.name)
+ f.value = await https_http_links(f.value)
if f.inline:
cur_field = await fill_out(channel, msg_embed_field_inline, [
("EMBED_FIELD_NAME", f.name),
@@ -116,15 +114,25 @@ async def produce_transcript(channel):
title = e.title \
if e.title != discord.Embed.Empty \
else ""
+ if title != "":
+ title = await https_http_links(title)
r, g, b = (e.colour.r, e.colour.g, e.colour.b) \
if e.colour != discord.Embed.Empty \
else (0x20, 0x22, 0x25) # default colour
desc = e.description \
if e.description != discord.Embed.Empty \
else ""
+ if desc != "":
+ desc = await https_http_links(desc)
author = e.author.name \
if e.author.name != discord.Embed.Empty \
else ""
+ author_url = e.author.url \
+ if e.author.url != discord.Embed.Empty \
+ else ""
+ author_icon = e.author.icon_url \
+ if e.author.icon_url != discord.Embed.Empty \
+ else ""
footer = e.footer.text \
if e.footer.text != discord.Embed.Empty \
else ""
@@ -139,6 +147,8 @@ async def produce_transcript(channel):
image = e.image.url \
if e.image.url != discord.Embed.Empty \
else ""
+ if author_url != "":
+ author = f'{author}'
if image != "":
image = await fill_out(channel, embed_image, [
@@ -163,11 +173,24 @@ async def produce_transcript(channel):
])
footer_fields += cur_footer
+ author_html = ""
+ if author != "":
+ if author_icon != "":
+ cur_author_icon = await fill_out(channel, embed_author_icon, [
+ ("EMBED_AUTHOR", author),
+ ("EMBED_AUTHOR_ICON", author_icon)
+ ])
+ else:
+ cur_author_icon = await fill_out(channel, embed_author, [
+ ("EMBED_AUTHOR", author),
+ ])
+ author_html += cur_author_icon
+
cur_embed = await fill_out(channel, msg_embed, [
("EMBED_R", str(r)),
("EMBED_G", str(g)),
("EMBED_B", str(b)),
- ("EMBED_AUTHOR", author, PARSE_MODE_EMBED_EMOJI),
+ ("EMBED_AUTHOR", author_html, PARSE_MODE_EMBED_EMOJI),
("EMBED_TITLE", title, PARSE_MODE_EMBED_EMOJI),
("EMBED_IMAGE", image),
("EMBED_THUMBNAIL", thumbnail),
@@ -204,35 +227,7 @@ async def produce_transcript(channel):
else:
ze_bot_tag = ""
- output = []
- if "http://" in m.content or "www." in m.content or "https://" in m.content:
- for word in m.content.split():
- if word.startswith("<") and word.endswith(">"):
- pattern = r"<(.*)>"
- url = re.search(pattern, word).group(1)
- url = f'{url}'
- output.append(url)
- elif "http://" in word:
- pattern = r"http://(.*)"
- word_link = re.search(pattern, word).group(1)
- word_full = f'http://{word_link}'
- word = re.sub(pattern, word_full, word)
- output.append(word)
- elif "www." in word:
- pattern = r"www.(.*)"
- word_link = re.search(pattern, word).group(1)
- word_full = f'www.{word_link}'
- word = re.sub(pattern, word_full, word)
- output.append(word)
- elif "https://" in word:
- pattern = r"https://(.*)"
- word_link = re.search(pattern, word).group(1)
- word_full = f'https://{word_link}'
- word = re.sub(pattern, word_full, word)
- output.append(word)
- else:
- output.append(word)
- m.content = " ".join(output)
+ m.content = await https_http_links(m.content)
emojis = ""
for reactions in m.reactions:
@@ -345,7 +340,7 @@ async def fill_out(channel, base, replacements):
v = await escape_mentions(v)
v = await escape_mentions(v)
v = await unescape_mentions(v)
- v = await parse_mentions(v, channel.guild, bot)
+ v = await parse_mentions(v, channel.guild)
if mode == PARSE_MODE_MARKDOWN:
v = await parse_markdown(v)
if mode == PARSE_MODE_EMBED:
@@ -386,3 +381,5 @@ def read_file(filename):
embed_footer_image = read_file(dir_path + "/chat_exporter_html/embed_footer_image.html")
embed_image = read_file(dir_path + "/chat_exporter_html/embed_image.html")
embed_thumbnail = read_file(dir_path + "/chat_exporter_html/embed_thumbnail.html")
+embed_author = read_file(dir_path + "/chat_exporter_html/embed_author.html")
+embed_author_icon = read_file(dir_path + "/chat_exporter_html/embed_author_icon.html")
diff --git a/chat_exporter/chat_exporter_html/base.html b/chat_exporter/chat_exporter_html/base.html
index 2bbfb19..244a2b8 100644
--- a/chat_exporter/chat_exporter_html/base.html
+++ b/chat_exporter/chat_exporter_html/base.html
@@ -11,31 +11,31 @@
@font-face {
font-family: Whitney;
- src: url(https://discordapp.com/assets/6c6374bad0b0b6d204d8d6dc4a18d820.woff);
+ src: url(https://cdn.jsdelivr.net/gh/mahtoid/DiscordFonts@master/whitney-300.woff);
font-weight: 300;
}
@font-face {
font-family: Whitney;
- src: url(https://discordapp.com/assets/e8acd7d9bf6207f99350ca9f9e23b168.woff);
+ src: url(https://cdn.jsdelivr.net/gh/mahtoid/DiscordFonts@master/whitney-400.woff);
font-weight: 400;
}
@font-face {
font-family: Whitney;
- src: url(https://discordapp.com/assets/3bdef1251a424500c1b3a78dea9b7e57.woff);
+ src: url(https://cdn.jsdelivr.net/gh/mahtoid/DiscordFonts@master/whitney-500.woff);
font-weight: 500;
}
@font-face {
font-family: Whitney;
- src: url(https://discordapp.com/assets/be0060dafb7a0e31d2a1ca17c0708636.woff);
+ src: url(https://cdn.jsdelivr.net/gh/mahtoid/DiscordFonts@master/whitney-600.woff);
font-weight: 600;
}
@font-face {
font-family: Whitney;
- src: url(https://discordapp.com/assets/8e12fb4f14d9c4592eb8ec9f22337b04.woff);
+ src: url(https://cdn.jsdelivr.net/gh/mahtoid/DiscordFonts@master/whitney-700.woff);
font-weight: 700;
}
@@ -57,32 +57,33 @@
}
.markdown {
- white-space: pre-wrap;
+ max-width: 100%;
line-height: 1.3;
overflow-wrap: break-word;
}
-.spoiler--hidden .spoiler-text {
- background-color: #202225;
- color: rgba(0, 0, 0, 0);
+.preserve-whitespace {
+ white-space: pre-wrap;
}
.spoiler {
- width: fit-content;
+ display: inline-block;
}
.spoiler--hidden {
cursor: pointer;
}
-.spoiler--hidden:hover .spoiler-text {
- background-color: #202225;
+.spoiler-text {
+ border-radius: 3px;
+}
+
+.spoiler--hidden .spoiler-text {
color: rgba(0, 0, 0, 0);
}
-.spoiler-text {
- background-color: rgba(255, 255, 255, 0.1);
- border-radius: 3px;
+.spoiler--hidden .spoiler-text::selection {
+ color: rgba(0, 0, 0, 0);
}
.spoiler-image {
@@ -95,24 +96,27 @@
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.1);
}
-.spoiler--hidden .spoiler-image img {
+.spoiler--hidden .spoiler-image * {
filter: blur(44px);
}
-.spoiler--hidden .spoiler-image:after {
- content: "SPOILER";
- color: #dcddde;
- background-color: rgba(0, 0, 0, 0.6);
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- font-weight: 600;
- padding: 0.5em 0.7em;
- border-radius: 20px;
- letter-spacing: 0.05em;
- font-size: 0.9em;
-}
+ .spoiler--hidden .spoiler-image:after {
+ content: "SPOILER";
+ color: #dcddde;
+ background-color: rgba(0, 0, 0, 0.6);
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ font-weight: 600;
+ padding: 100%;
+ /* This ruins those beutifully rounded buttons, but it's needed to prevent a FireFox bug with video and audio elemnts. */
+ /* The bug is that you can click trough the spoiler layer and play the video or audio, I could not identify the cause. */
+ /* I leave this here, in case someone is brave enough to venture in to madness that is undocumented browser behaviour. */
+ border-radius: 20px;
+ letter-spacing: 0.05em;
+ font-size: 0.9em;
+ }
.spoiler--hidden:hover .spoiler-image:after {
color: #fff;
@@ -120,10 +124,10 @@
}
.quote {
+ margin: 0.1em 0;
+ padding-left: 0.6em;
border-left: 4px solid;
border-radius: 3px;
- margin: 8px 0;
- padding-left: 10px;
}
.pre {
@@ -131,8 +135,8 @@
}
.pre--multiline {
- margin-top: 4px;
- padding: 8px;
+ margin-top: 0.25em;
+ padding: 0.5em;
border: 2px solid;
border-radius: 5px;
}
@@ -140,93 +144,50 @@
.pre--inline {
padding: 2px;
border-radius: 3px;
- font-size: 85%;
+ font-size: 0.85em;
}
.mention {
+ border-radius: 3px;
+ padding: 0 2px;
+ color: #7289da;
+ background: rgba(114, 137, 218, .1);
font-weight: 500;
}
.emoji {
- width: 1.45em;
- height: 1.45em;
- margin: 0 1px;
+ width: 1.25em;
+ height: 1.25em;
+ margin: 0 0.06em;
vertical-align: -0.4em;
}
.emoji--small {
- width: 1rem;
- height: 1rem;
+ width: 1em;
+ height: 1em;
}
.emoji--large {
- width: 2rem;
- height: 2rem;
+ width: 2.8em;
+ height: 2.8em;
}
-/* === INFO === */
-
-.info {
- display: flex;
- max-width: 100%;
- margin: 0 5px 10px 5px;
-}
-
-.info__guild-icon-container {
- flex: 0;
-}
-
-.info__guild-icon {
- max-width: 88px;
- max-height: 88px;
-}
-
-.info__metadata {
- flex: 1;
- margin-left: 10px;
-}
-
-.info__guild-name {
- font-size: 1.2em;
-}
-
-.info__channel-name {
- font-size: 1em;
-}
-
-.info__channel-topic {
- margin-top: 2px;
-}
-
-.info__channel-message-count {
- margin-top: 2px;
-}
-
-.info__channel-timezone {
- margin-top: 2px;
- font-size:0.9em;
-}
-
-.info__channel-date-range {
- margin-top: 2px;
-}
-
-/* === CHATLOG === */
+/* Chatlog */
.chatlog {
max-width: 100%;
- margin-bottom: 24px;
}
.chatlog__message-group {
- display: flex;
- margin: 0 10px;
- padding: 15px 0;
+ display: grid;
+ margin: 0 0.6em;
+ padding: 0.9em 0;
border-top: 1px solid;
+ grid-template-columns: auto 1fr;
}
.chatlog__author-avatar-container {
- flex: 0;
+ grid-column: 1;
width: 40px;
height: 40px;
}
@@ -238,55 +199,57 @@
}
.chatlog__messages {
- flex: 1;
+ grid-column: 2;
+ margin-left: 1.2em;
min-width: 50%;
- margin-left: 20px;
}
.chatlog__author-name {
- font-size: 1em;
font-weight: 500;
}
.chatlog__timestamp {
- margin-left: 5px;
- font-size: .75em;
+ margin-left: 0.3em;
+ font-size: 0.75em;
}
.chatlog__message {
- padding: 2px 5px;
- margin-right: -5px;
- margin-left: -5px;
+ padding: 0.1em 0.3em;
+ margin: 0 -0.3em;
background-color: transparent;
transition: background-color 1s ease;
}
.chatlog__content {
- font-size: .9375em;
+ font-size: 0.95em;
word-wrap: break-word;
}
.chatlog__edited-timestamp {
- margin-left: 3px;
- font-size: .8em;
+ margin-left: 0.15em;
+ font-size: 0.8em;
+}
+
+.chatlog__attachment {
+ margin-top: 0.3em;
}
.chatlog__attachment-thumbnail {
- margin-top: 5px;
- max-width: 50%;
- max-height: 300px;
+ vertical-align: top;
+ max-width: 45vw;
+ max-height: 500px;
border-radius: 3px;
}
.chatlog__embed {
- margin-top: 5px;
display: flex;
+ margin-top: 0.3em;
max-width: 520px;
}
.chatlog__embed-color-pill {
flex-shrink: 0;
- width: 4px;
+ width: 0.25em;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
@@ -294,15 +257,15 @@
.chatlog__embed-content-container {
display: flex;
flex-direction: column;
- padding: 8px 10px;
+ padding: 0.5em 0.6em;
border: 1px solid;
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
.chatlog__embed-content {
- width: 100%;
display: flex;
+ width: 100%;
}
.chatlog__embed-text {
@@ -311,31 +274,31 @@
.chatlog__embed-author {
display: flex;
+ margin-bottom: 0.3em;
align-items: center;
- margin-bottom: 5px;
}
.chatlog__embed-author-icon {
+ margin-right: 0.5em;
width: 20px;
height: 20px;
- margin-right: 9px;
border-radius: 50%;
}
.chatlog__embed-author-name {
- font-size: .875em;
+ font-size: 0.875em;
font-weight: 600;
}
.chatlog__embed-title {
- margin-bottom: 4px;
- font-size: .875em;
+ margin-bottom: 0.2em;
+ font-size: 0.875em;
font-weight: 600;
}
.chatlog__embed-description {
font-weight: 500;
- font-size: 14px;
+ font-size: 0.85em;
}
.chatlog__embed-fields {
@@ -347,7 +310,8 @@
flex: 0;
min-width: 100%;
max-width: 506px;
- padding-top: 10px;
+ padding-top: 0.6em;
+ font-size: 0.875em;
}
.chatlog__embed-field--inline {
@@ -357,26 +321,24 @@
}
.chatlog__embed-field-name {
- margin-bottom: 4px;
- font-size: .875em;
+ margin-bottom: 0.2em;
font-weight: 600;
}
.chatlog__embed-field-value {
- font-size: .875em;
font-weight: 500;
}
.chatlog__embed-thumbnail {
flex: 0;
- margin-left: 20px;
+ margin-left: 1.2em;
max-width: 80px;
max-height: 80px;
border-radius: 3px;
}
.chatlog__embed-image-container {
- margin-top: 10px;
+ margin-top: 0.6em;
}
.chatlog__embed-image {
@@ -386,11 +348,11 @@
}
.chatlog__embed-footer {
- margin-top: 10px;
+ margin-top: 0.6em;
}
.chatlog__embed-footer-icon {
- margin-right: 4px;
+ margin-right: 0.2em;
width: 20px;
height: 20px;
border-radius: 50%;
@@ -398,8 +360,8 @@
}
.chatlog__embed-footer-text {
+ font-size: 0.75em;
font-weight: 500;
- font-size: .75em;
}
.chatlog__reactions {
@@ -409,32 +371,41 @@
.chatlog__reaction {
display: flex;
align-items: center;
- margin: 6px 2px 2px 2px;
- padding: 3px 6px;
+ margin: 0.35em 0.1em 0.1em 0.1em;
+ padding: 0.2em 0.35em;
border-radius: 3px;
}
.chatlog__reaction-count {
min-width: 9px;
- margin-left: 6px;
- font-size: .875em;
+ margin-left: 0.35em;
+ font-size: 0.875em;
}
.chatlog__bot-tag {
+ position: relative;
+ top: -.2em;
margin-left: 0.3em;
- background: #7289da;
- color: #ffffff;
- font-size: 0.625em;
- padding: 1px 2px;
+ padding: 0.05em 0.3em;
border-radius: 3px;
vertical-align: middle;
line-height: 1.3;
- position: relative;
- top: -.2em;
+ background: #7289da;
+ color: #ffffff;
+ font-size: 0.625em;
+ font-weight: 500;
+}
+
+/* Postamble */
+
+.postamble {
+ margin: 1.4em 0.3em 0.6em 0.3em;
+ padding: 1em;
+ border-top: 1px solid;
}