Display rich embed support

This commit is contained in:
Jeremy Zhang 2017-11-05 05:59:06 +00:00
parent 962880f652
commit eff2b3bb46
8 changed files with 240 additions and 8 deletions

View File

@ -62,7 +62,8 @@ class DatabaseInterface(object):
str(message.timestamp), str(message.timestamp),
edit_ts, edit_ts,
json.dumps(get_message_mentions(message.mentions)), json.dumps(get_message_mentions(message.mentions)),
json.dumps(message.attachments) json.dumps(message.attachments),
json.dumps(message.embeds)
) )
session.add(msg) session.add(msg)
session.commit() session.commit()
@ -81,6 +82,7 @@ class DatabaseInterface(object):
msg.edited_timestamp = message.edited_timestamp msg.edited_timestamp = message.edited_timestamp
msg.mentions = json.dumps(get_message_mentions(message.mentions)) msg.mentions = json.dumps(get_message_mentions(message.mentions))
msg.attachments = json.dumps(message.attachments) msg.attachments = json.dumps(message.attachments)
msg.embeds = json.dumps(message.embeds)
msg.author = json.dumps(get_message_author(message)) msg.author = json.dumps(get_message_author(message))
session.commit() session.commit()

View File

@ -12,8 +12,9 @@ class Messages(Base):
edited_timestamp = db.Column(db.TIMESTAMP) # Timestamp of when content is edited edited_timestamp = db.Column(db.TIMESTAMP) # Timestamp of when content is edited
mentions = db.Column(db.Text()) # Mentions serialized mentions = db.Column(db.Text()) # Mentions serialized
attachments = db.Column(db.Text()) # serialized attachments attachments = db.Column(db.Text()) # serialized attachments
embeds = db.Column(db.Text().with_variant(db.Text(length=4294967295), 'mysql')) # message embeds
def __init__(self, guild_id, channel_id, message_id, content, author, timestamp, edited_timestamp, mentions, attachments): def __init__(self, guild_id, channel_id, message_id, content, author, timestamp, edited_timestamp, mentions, attachments, embeds):
self.guild_id = guild_id self.guild_id = guild_id
self.channel_id = channel_id self.channel_id = channel_id
self.message_id = message_id self.message_id = message_id
@ -23,6 +24,7 @@ class Messages(Base):
self.edited_timestamp = edited_timestamp self.edited_timestamp = edited_timestamp
self.mentions = mentions self.mentions = mentions
self.attachments = attachments self.attachments = attachments
self.embeds = embeds
def __repr__(self): def __repr__(self):
return '<Messages {0} {1} {2} {3} {4}>'.format(self.id, self.guild_id, self.guild_id, self.channel_id, self.message_id) return '<Messages {0} {1} {2} {3} {4}>'.format(self.id, self.guild_id, self.guild_id, self.channel_id, self.message_id)

View File

@ -26,6 +26,7 @@ class SocketIOInterface:
"edited_timestamp": edit_ts, "edited_timestamp": edit_ts,
"mentions": get_message_mentions(message.mentions), "mentions": get_message_mentions(message.mentions),
"attachments": message.attachments, "attachments": message.attachments,
"embeds": message.embeds,
} }
nickname = None nickname = None
if hasattr(message.author, 'nick') and message.author.nick: if hasattr(message.author, 'nick') and message.author.nick:

View File

@ -0,0 +1,28 @@
"""Add embed column to messages
Revision ID: 7d6484faaccd
Revises: a5780c871aec
Create Date: 2017-11-04 06:39:41.926145
"""
# revision identifiers, used by Alembic.
revision = '7d6484faaccd'
down_revision = 'a5780c871aec'
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('messages', sa.Column('embeds', sa.Text().with_variant(sa.Text(length=4294967295), 'mysql'), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('messages', 'embeds')
# ### end Alembic commands ###

View File

@ -14,8 +14,9 @@ class Messages(db.Model):
edited_timestamp = db.Column(db.TIMESTAMP) # Timestamp of when content is edited edited_timestamp = db.Column(db.TIMESTAMP) # Timestamp of when content is edited
mentions = db.Column(db.Text()) # Mentions serialized mentions = db.Column(db.Text()) # Mentions serialized
attachments = db.Column(db.Text()) # serialized attachments attachments = db.Column(db.Text()) # serialized attachments
embeds = db.Column(db.Text().with_variant(db.Text(length=4294967295), 'mysql')) # message embeds
def __init__(self, guild_id, channel_id, message_id, content, author, timestamp, edited_timestamp, mentions, attachments): def __init__(self, guild_id, channel_id, message_id, content, author, timestamp, edited_timestamp, mentions, attachments, embeds):
self.guild_id = guild_id self.guild_id = guild_id
self.channel_id = channel_id self.channel_id = channel_id
self.message_id = message_id self.message_id = message_id
@ -25,6 +26,7 @@ class Messages(db.Model):
self.edited_timestamp = edited_timestamp self.edited_timestamp = edited_timestamp
self.mentions = mentions self.mentions = mentions
self.attachments = attachments self.attachments = attachments
self.embeds = embeds
def __repr__(self): def __repr__(self):
return '<Messages {0} {1} {2} {3} {4}>'.format(self.id, self.guild_id, self.guild_id, self.channel_id, self.message_id) return '<Messages {0} {1} {2} {3} {4}>'.format(self.id, self.guild_id, self.guild_id, self.channel_id, self.message_id)
@ -40,6 +42,9 @@ def get_channel_messages(guild_id, channel_id, after_snowflake=None):
if x.message_id in snowflakes: if x.message_id in snowflakes:
continue continue
snowflakes.append(x.message_id) snowflakes.append(x.message_id)
embeds = x.embeds
if not embeds:
embeds = "[]"
message = { message = {
"attachments": json.loads(x.attachments), "attachments": json.loads(x.attachments),
"timestamp": x.timestamp, "timestamp": x.timestamp,
@ -48,7 +53,8 @@ def get_channel_messages(guild_id, channel_id, after_snowflake=None):
"author": json.loads(x.author), "author": json.loads(x.author),
"content": x.content, "content": x.content,
"channel_id": x.channel_id, "channel_id": x.channel_id,
"mentions": json.loads(x.mentions) "mentions": json.loads(x.mentions),
"embeds": json.loads(embeds),
} }
member = get_guild_member(guild_id, message["author"]["id"]) member = get_guild_member(guild_id, message["author"]["id"])
message["author"]["nickname"] = None message["author"]["nickname"] = None

View File

@ -491,7 +491,6 @@ p.mentioned span.chatmessage {
background-color: rgba(0, 0, 0, 0.2); background-color: rgba(0, 0, 0, 0.2);
color: #82b1ff; color: #82b1ff;
cursor: pointer; cursor: pointer;
} }
.chatmessage .channellink:hover { .chatmessage .channellink:hover {
@ -499,6 +498,92 @@ p.mentioned span.chatmessage {
color: white; color: white;
} }
.embeds {
display: block;
width: 60%;
}
@media(max-width: 600px) {
.embeds {
width: 100%;
}
}
.richembed {
display: flex;
border: solid 1px grey;
background-color: rgba(0, 0, 0, 0.1);
border-radius: 10px;
overflow: hidden;
margin-top: 3px;
}
.richembed .color {
width: 6px;
background-color: #cacbce;
}
.richembed .rich {
margin: 10px;
}
.richembed img {
border-radius: 5px;
}
.richembed .author img, .richembed .footer img {
width: 20px;
border-radius: 100px;
vertical-align: bottom;
}
.richembed .content {
display: flex;
}
.richembed .thumbnail {
margin-left: 2px;
}
.richembed .thumbnail img {
width: 100%;
max-width: 170px;
}
.richembed .fields {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.richembed .field-name {
font-weight: bold;
}
.richembed .field {
flex: 0;
min-width: 100%;
}
.richembed .field.inline {
flex: 1;
flex-basis: auto;
min-width: 100px;
}
@media(max-width: 600px) {
.richembed .field.inline {
flex: 0;
flex-basis: unset;
min-width: 100%;
}
}
.richembed .image img {
max-width: 300px;
width: 100%;
}
#emoji-picker { #emoji-picker {
color: black; color: black;
position: fixed; position: fixed;

View File

@ -854,6 +854,34 @@
return "https://cdn.discordapp.com/avatars/" + user_id + "/" + avatar_hash + ".png"; return "https://cdn.discordapp.com/avatars/" + user_id + "/" + avatar_hash + ".png";
} }
} }
function parse_message_embeds(embeds) {
var emb = [];
for (var i = 0; i < embeds.length; i++) {
var disembed = embeds[i];
if (disembed.type != "rich") {
continue;
}
disembed.toRenderFooter = false;
if (disembed.footer) {
disembed.toRenderFooter = true;
} else if (disembed.timestamp) {
disembed.toRenderFooter = true;
}
disembed.footerVerticalBar = disembed.footer && disembed.timestamp;
if (disembed.timestamp) {
disembed.formatted_timestamp = moment(disembed.timestamp).format('ddd MMM Do, YYYY [at] h:mm A');
}
if (disembed.color) {
disembed.hexColor = "#" + disembed.color.toString(16);
}
var template = $('#mustache_richembed').html();
Mustache.parse(template);
var rendered = Mustache.render(template, disembed);
emb.push(rendered);
}
return emb;
}
function fill_discord_messages(messages, jumpscroll, replace=null) { function fill_discord_messages(messages, jumpscroll, replace=null) {
if (messages.length == 0) { if (messages.length == 0) {
@ -906,6 +934,11 @@
select_channel($(this).attr("channelid"), true); select_channel($(this).attr("channelid"), true);
}); });
} }
var embeds = parse_message_embeds(message.embeds);
$("#discordmessage_"+message.id).parent().find("span.embeds").text("");
for(var j = 0; j < embeds.length; j++) {
$("#discordmessage_"+message.id).parent().find("span.embeds").append(embeds[j]);
}
var usrcachekey = username + "#" + message.author.discriminator; var usrcachekey = username + "#" + message.author.discriminator;
if (usrcachekey.startsWith("(Titan Dev) ")) { if (usrcachekey.startsWith("(Titan Dev) ")) {
usrcachekey = usrcachekey.substr(12); usrcachekey = usrcachekey.substr(12);
@ -943,7 +976,7 @@
jumpscroll = true; jumpscroll = true;
} else { } else {
fet = fetch(channel_id, last_message_id); fet = fetch(channel_id, last_message_id);
jumpscroll = element_in_view($('#discordmessage_'+last_message_id).parent(), true); jumpscroll = element_in_view($('#discordmessage_'+last_message_id).parent());
} }
fet.done(function(data) { fet.done(function(data) {
var status = data.status; var status = data.status;
@ -1284,7 +1317,7 @@
if (selected_channel != thismsgchan) { if (selected_channel != thismsgchan) {
return; return;
} }
var jumpscroll = element_in_view($('#discordmessage_'+last_message_id).parent(), true); var jumpscroll = element_in_view($('#discordmessage_'+last_message_id).parent());
last_message_id = fill_discord_messages([msg], jumpscroll); last_message_id = fill_discord_messages([msg], jumpscroll);
}); });

View File

@ -218,7 +218,7 @@
</script> </script>
<script id="mustache_usermessage" type="text/template"> <script id="mustache_usermessage" type="text/template">
<p><img class="authoravatar" src="{{avatar}}"> <span class="chatusername"><span class="authorname">{{username}}</span><span class="authorhash">#</span><span class="authordiscriminator">{{discriminator}}</span></span> <span id="discordmessage_{{id}}" title="{{full_timestamp}}" class="chattimestamp">{{time}}</span> <span class="chatmessage">{{{content}}}</span></p> <p><img class="authoravatar" src="{{avatar}}"> <span class="chatusername"><span class="authorname">{{username}}</span><span class="authorhash">#</span><span class="authordiscriminator">{{discriminator}}</span></span> <span id="discordmessage_{{id}}" title="{{full_timestamp}}" class="chattimestamp">{{time}}</span> <span class="chatmessage">{{{content}}}</span><span class="embeds"></span></p>
</script> </script>
<script id="mustache_memberrole" type="text/template"> <script id="mustache_memberrole" type="text/template">
@ -232,6 +232,81 @@
<script id="mustache_message_emoji" type="text/template"> <script id="mustache_message_emoji" type="text/template">
<img class="message_emoji tooltipped" src='https://cdn.discordapp.com/emojis/{{id}}.png' data-position="top" data-delay="200" data-tooltip=":{{name}}:" alt=":{{name}}:" /> <img class="message_emoji tooltipped" src='https://cdn.discordapp.com/emojis/{{id}}.png' data-position="top" data-delay="200" data-tooltip=":{{name}}:" alt=":{{name}}:" />
</script> </script>
<script id="mustache_richembed" type="text/template">
<div class="richembed">
{{#color}}
<div class="color" style="background-color: {{hexColor}}"></div>
{{/color}}
{{^color}}
<div class="color"></div>
{{/color}}
<div class="rich">
<div class="content">
<div class="innercontent">
{{#author}}
<div class="author">
{{#author.icon_url}}
<img src="{{author.icon_url}}">
{{/author.icon_url}}
<a href="
{{#author.url}}{{author.url}}{{/author.url}}
{{^author.url}}#{{/author.url}}
" class="name">{{author.name}}</a>
</div>
{{/author}}
{{#title}}
<div class="title">
<a href="
{{#url}}{{url}}{{/url}}
{{^url}}#{{/url}}
">{{title}}</a>
</div>
{{/title}}
{{#description}}
<div class="description">{{description}}</div>
{{/description}}
{{#fields.length}}
<div class="fields">
{{#fields}}
<div class="field {{#inline}}inline{{/inline}}">
<div class="field-name">{{name}}</div>
<div class="field-content">{{value}}</div>
</div>
{{/fields}}
</div>
{{/fields.length}}
</div>
{{#thumbnail}}
<div class="thumbnail">
<img src="{{thumbnail.url}}">
</div>
{{/thumbnail}}
</div>
{{#image}}
<div class="image">
<img src="{{image.url}}">
</div>
{{/image}}
{{#toRenderFooter}}
<div class="footer">
{{#footer}}
{{#footer.icon_url}}
<img class="icon_url" src="{{footer.icon_url}}">
{{/footer.icon_url}}
<span class="text">{{footer.text}}</span>
{{/footer}}
{{#footerVerticalBar}}
|
{{/footerVerticalBar}}
{{#timestamp}}
<span class="timestamp">{{formatted_timestamp}}</span>
{{/timestamp}}
</div>
{{/toRenderFooter}}
</div>
</div>
</script>
{% endraw %} {% endraw %}
<script> <script>