mirror of
				https://github.com/TitanEmbeds/Titan.git
				synced 2025-11-04 15:57:02 +01:00 
			
		
		
		
	Display rich embed support
This commit is contained in:
		@@ -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 ###
 | 
			
		||||
@@ -14,8 +14,9 @@ class Messages(db.Model):
 | 
			
		||||
    edited_timestamp = db.Column(db.TIMESTAMP)                      # Timestamp of when content is edited
 | 
			
		||||
    mentions = db.Column(db.Text())                                 # Mentions serialized
 | 
			
		||||
    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.channel_id = channel_id
 | 
			
		||||
        self.message_id = message_id
 | 
			
		||||
@@ -25,6 +26,7 @@ class Messages(db.Model):
 | 
			
		||||
        self.edited_timestamp = edited_timestamp
 | 
			
		||||
        self.mentions = mentions
 | 
			
		||||
        self.attachments = attachments
 | 
			
		||||
        self.embeds = embeds
 | 
			
		||||
 | 
			
		||||
    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)
 | 
			
		||||
@@ -40,6 +42,9 @@ def get_channel_messages(guild_id, channel_id, after_snowflake=None):
 | 
			
		||||
        if x.message_id in snowflakes:
 | 
			
		||||
            continue
 | 
			
		||||
        snowflakes.append(x.message_id)
 | 
			
		||||
        embeds = x.embeds
 | 
			
		||||
        if not embeds:
 | 
			
		||||
            embeds = "[]"
 | 
			
		||||
        message = {
 | 
			
		||||
            "attachments": json.loads(x.attachments),
 | 
			
		||||
            "timestamp": x.timestamp,
 | 
			
		||||
@@ -48,7 +53,8 @@ def get_channel_messages(guild_id, channel_id, after_snowflake=None):
 | 
			
		||||
            "author": json.loads(x.author),
 | 
			
		||||
            "content": x.content,
 | 
			
		||||
            "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"])
 | 
			
		||||
        message["author"]["nickname"] = None
 | 
			
		||||
 
 | 
			
		||||
@@ -491,7 +491,6 @@ p.mentioned span.chatmessage {
 | 
			
		||||
  background-color: rgba(0, 0, 0, 0.2);
 | 
			
		||||
  color: #82b1ff;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chatmessage .channellink:hover {
 | 
			
		||||
@@ -499,6 +498,92 @@ p.mentioned span.chatmessage {
 | 
			
		||||
  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 {
 | 
			
		||||
  color: black;
 | 
			
		||||
  position: fixed;
 | 
			
		||||
 
 | 
			
		||||
@@ -854,6 +854,34 @@
 | 
			
		||||
            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) {
 | 
			
		||||
        if (messages.length == 0) {
 | 
			
		||||
@@ -906,6 +934,11 @@
 | 
			
		||||
                    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;
 | 
			
		||||
            if (usrcachekey.startsWith("(Titan Dev) ")) {
 | 
			
		||||
                usrcachekey = usrcachekey.substr(12);
 | 
			
		||||
@@ -943,7 +976,7 @@
 | 
			
		||||
            jumpscroll = true;
 | 
			
		||||
        } else {
 | 
			
		||||
            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) {
 | 
			
		||||
            var status = data.status;
 | 
			
		||||
@@ -1284,7 +1317,7 @@
 | 
			
		||||
            if (selected_channel != thismsgchan) {
 | 
			
		||||
                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);
 | 
			
		||||
        });
 | 
			
		||||
        
 | 
			
		||||
 
 | 
			
		||||
@@ -218,7 +218,7 @@
 | 
			
		||||
    </script>
 | 
			
		||||
    
 | 
			
		||||
    <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 id="mustache_memberrole" type="text/template">
 | 
			
		||||
@@ -232,6 +232,81 @@
 | 
			
		||||
    <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}}:" />
 | 
			
		||||
    </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 %}
 | 
			
		||||
 | 
			
		||||
    <script>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user