Add support for embeds (#46)
parent
3b7da21c24
commit
d958f613a3
@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
// https://discordapp.com/developers/docs/resources/channel#embed-object
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Models
|
||||||
|
{
|
||||||
|
public class Embed : IMentionable
|
||||||
|
{
|
||||||
|
public string Title { get; }
|
||||||
|
|
||||||
|
public string Type { get; }
|
||||||
|
|
||||||
|
public string Description { get; }
|
||||||
|
|
||||||
|
public string Url { get; }
|
||||||
|
|
||||||
|
public DateTime? TimeStamp { get; }
|
||||||
|
|
||||||
|
public Color? Color { get; }
|
||||||
|
|
||||||
|
public EmbedFooter Footer { get; }
|
||||||
|
|
||||||
|
public EmbedImage Image { get; }
|
||||||
|
|
||||||
|
public EmbedImage Thumbnail { get; }
|
||||||
|
|
||||||
|
public EmbedVideo Video { get; }
|
||||||
|
|
||||||
|
public EmbedProvider Provider { get; }
|
||||||
|
|
||||||
|
public EmbedAuthor Author { get; }
|
||||||
|
|
||||||
|
public IReadOnlyList<EmbedField> Fields { get; }
|
||||||
|
|
||||||
|
public List<User> MentionedUsers { get; }
|
||||||
|
|
||||||
|
public List<Role> MentionedRoles { get; }
|
||||||
|
|
||||||
|
public List<Channel> MentionedChannels { get; }
|
||||||
|
|
||||||
|
public Embed(string title, string type, string description,
|
||||||
|
string url, DateTime? timeStamp, Color? color,
|
||||||
|
EmbedFooter footer, EmbedImage image, EmbedImage thumbnail,
|
||||||
|
EmbedVideo video, EmbedProvider provider, EmbedAuthor author,
|
||||||
|
List<EmbedField> fields, List<User> mentionedUsers,
|
||||||
|
List<Role> mentionedRoles, List<Channel> mentionedChannels)
|
||||||
|
{
|
||||||
|
Title = title;
|
||||||
|
Type = type;
|
||||||
|
Description = description;
|
||||||
|
Url = url;
|
||||||
|
TimeStamp = timeStamp;
|
||||||
|
Color = color;
|
||||||
|
Footer = footer;
|
||||||
|
Image = image;
|
||||||
|
Thumbnail = thumbnail;
|
||||||
|
Video = video;
|
||||||
|
Provider = provider;
|
||||||
|
Author = author;
|
||||||
|
Fields = fields;
|
||||||
|
MentionedUsers = mentionedUsers;
|
||||||
|
MentionedRoles = mentionedRoles;
|
||||||
|
MentionedChannels = mentionedChannels;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
// https://discordapp.com/developers/docs/resources/channel#embed-object-embed-author-structure
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Models
|
||||||
|
{
|
||||||
|
public class EmbedAuthor
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public string Url { get; }
|
||||||
|
|
||||||
|
public string IconUrl { get; }
|
||||||
|
|
||||||
|
public string ProxyIconUrl { get; }
|
||||||
|
|
||||||
|
public EmbedAuthor(string name, string url, string iconUrl, string proxyIconUrl)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Url = url;
|
||||||
|
IconUrl = iconUrl;
|
||||||
|
ProxyIconUrl = proxyIconUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
// https://discordapp.com/developers/docs/resources/channel#embed-object-embed-field-structure
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Models
|
||||||
|
{
|
||||||
|
public class EmbedField
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public string Value { get; }
|
||||||
|
|
||||||
|
public bool? Inline { get; }
|
||||||
|
|
||||||
|
public EmbedField(string name, string value, bool? inline)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Value = value;
|
||||||
|
Inline = inline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
// https://discordapp.com/developers/docs/resources/channel#embed-object-embed-footer-structure
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Models
|
||||||
|
{
|
||||||
|
public class EmbedFooter
|
||||||
|
{
|
||||||
|
public string Text { get; }
|
||||||
|
|
||||||
|
public string IconUrl { get; }
|
||||||
|
|
||||||
|
public string ProxyIconUrl { get; }
|
||||||
|
|
||||||
|
public EmbedFooter(string text, string iconUrl, string proxyIconUrl)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
IconUrl = iconUrl;
|
||||||
|
ProxyIconUrl = proxyIconUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
// https://discordapp.com/developers/docs/resources/channel#embed-object-embed-image-structure
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Models
|
||||||
|
{
|
||||||
|
public class EmbedImage
|
||||||
|
{
|
||||||
|
public string Url { get; }
|
||||||
|
|
||||||
|
public string ProxyUrl { get; }
|
||||||
|
|
||||||
|
public int? Height { get; }
|
||||||
|
|
||||||
|
public int? Width { get; }
|
||||||
|
|
||||||
|
public EmbedImage(string url, string proxyUrl, int? height, int? width)
|
||||||
|
{
|
||||||
|
Url = url;
|
||||||
|
ProxyUrl = proxyUrl;
|
||||||
|
Height = height;
|
||||||
|
Width = width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
// https://discordapp.com/developers/docs/resources/channel#embed-object-embed-provider-structure
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Models
|
||||||
|
{
|
||||||
|
public class EmbedProvider
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public string Url { get; }
|
||||||
|
|
||||||
|
public EmbedProvider(string name, string url)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Url = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
// https://discordapp.com/developers/docs/resources/channel#embed-object-embed-video-structure
|
||||||
|
|
||||||
|
namespace DiscordChatExporter.Core.Models
|
||||||
|
{
|
||||||
|
public class EmbedVideo
|
||||||
|
{
|
||||||
|
public string Url { get; }
|
||||||
|
|
||||||
|
public int? Height { get; }
|
||||||
|
|
||||||
|
public int? Width { get; }
|
||||||
|
|
||||||
|
public EmbedVideo(string url, int? height, int? width)
|
||||||
|
{
|
||||||
|
Url = url;
|
||||||
|
Height = height;
|
||||||
|
Width = width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,396 @@
|
|||||||
|
body {
|
||||||
|
font-family: Whitney, Helvetica Neue, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.pre {
|
||||||
|
font-family: Consolas, Courier New, Courier, Monospace;
|
||||||
|
margin-top: 4px;
|
||||||
|
padding: 8px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.pre {
|
||||||
|
font-family: Consolas, Courier New, Courier, Monospace;
|
||||||
|
padding-left: 2px;
|
||||||
|
padding-right: 2px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#info {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#log {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.guild-icon {
|
||||||
|
max-height: 64px;
|
||||||
|
max-width: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.info-right {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.guild-name {
|
||||||
|
font-size: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.channel-name {
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.channel-topic {
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.channel-messagecount {
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.msg {
|
||||||
|
display: flex;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
padding-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.msg-left {
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.msg-avatar {
|
||||||
|
border-radius: 50%;
|
||||||
|
height: 40px;
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.msg-right {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 20px;
|
||||||
|
min-width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.msg-user {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.msg-date {
|
||||||
|
font-size: .75em;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.msg-edited {
|
||||||
|
font-size: .8em;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.msg-content {
|
||||||
|
font-size: .9375em;
|
||||||
|
padding-top: 5px;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.msg-attachment {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.msg-attachment {
|
||||||
|
max-height: 500px;
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.mention {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #7289da;
|
||||||
|
background-color: rgba(115, 139, 215, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji {
|
||||||
|
-o-object-fit: contain;
|
||||||
|
object-fit: contain;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
margin: 0 .05em 0 .1em!important;
|
||||||
|
vertical-align: -.4em
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji.jumboable {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px
|
||||||
|
}
|
||||||
|
|
||||||
|
.image {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
-webkit-user-select: text;
|
||||||
|
-moz-user-select: text;
|
||||||
|
-ms-user-select: text;
|
||||||
|
user-select: text
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed,
|
||||||
|
.embed-wrapper {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-wrapper {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 5px;
|
||||||
|
max-width: 520px;
|
||||||
|
display: flex
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed-wrapper .embed-color-pill {
|
||||||
|
width: 4px;
|
||||||
|
background: #cacbce;
|
||||||
|
border-radius: 3px 0 0 3px;
|
||||||
|
-ms-flex-negative: 0;
|
||||||
|
flex-shrink: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed {
|
||||||
|
padding: 8px 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: hsla(0, 0%, 98%, .3);
|
||||||
|
border: 1px solid hsla(0, 0%, 80%, .3);
|
||||||
|
border-radius: 0 3px 3px 0;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
-webkit-box-direction: normal;
|
||||||
|
-ms-flex-direction: column;
|
||||||
|
flex-direction: column
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-content,
|
||||||
|
.embed.embed-rich {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-fields,
|
||||||
|
.embed.embed-link {
|
||||||
|
-webkit-box-orient: horizontal;
|
||||||
|
-webkit-box-direction: normal
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed div.embed-title {
|
||||||
|
color: #4f545c
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-content {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-content .embed-content-inner {
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed.embed-rich {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
border-radius: 0 3px 3px 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed.embed-rich .embed-rich-thumb {
|
||||||
|
max-height: 80px;
|
||||||
|
max-width: 80px;
|
||||||
|
border-radius: 3px;
|
||||||
|
width: auto;
|
||||||
|
-o-object-fit: contain;
|
||||||
|
object-fit: contain;
|
||||||
|
-ms-flex-negative: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 20px
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed.embed-inline {
|
||||||
|
padding: 0;
|
||||||
|
margin: 4px 0;
|
||||||
|
border-radius: 3px
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .image,
|
||||||
|
.embed video {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 2px
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-content-inner>:last-child,
|
||||||
|
.embed .embed-content:last-child,
|
||||||
|
.embed .embed-inner>:last-child,
|
||||||
|
.embed>:last-child {
|
||||||
|
margin-bottom: 0!important
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-provider {
|
||||||
|
display: inline-block;
|
||||||
|
color: #87909c;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-bottom: 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-author {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-author-name,
|
||||||
|
.embed .embed-footer,
|
||||||
|
.embed .embed-title {
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: 600
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-author-name {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #4f545c!important
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-author-icon {
|
||||||
|
margin-right: 9px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
-o-object-fit: contain;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 50%
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-footer {
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgba(79, 83, 91, .6);
|
||||||
|
letter-spacing: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-footer-icon {
|
||||||
|
margin-right: 10px;
|
||||||
|
height: 18px;
|
||||||
|
width: 18px;
|
||||||
|
-o-object-fit: contain;
|
||||||
|
object-fit: contain;
|
||||||
|
float: left;
|
||||||
|
border-radius: 2.45px
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-title {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-size: 14px
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-title+.embed-description {
|
||||||
|
margin-top: -3px!important
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-description {
|
||||||
|
display: block;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: rgba(79, 83, 91, .9);
|
||||||
|
letter-spacing: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-description.markup {
|
||||||
|
white-space: pre-line;
|
||||||
|
margin-top: 0!important;
|
||||||
|
font-size: 14px!important;
|
||||||
|
line-height: 16px!important
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-description.markup pre {
|
||||||
|
max-width: 100%!important
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-fields {
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-ms-flex-direction: row;
|
||||||
|
flex-direction: row;
|
||||||
|
-ms-flex-wrap: wrap;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
color: #36393e;
|
||||||
|
margin-top: -10px;
|
||||||
|
margin-bottom: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-fields .embed-field {
|
||||||
|
-webkit-box-flex: 0;
|
||||||
|
-ms-flex: 0;
|
||||||
|
flex: 0;
|
||||||
|
padding-top: 10px;
|
||||||
|
min-width: 100%;
|
||||||
|
max-width: 506px
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-fields .embed-field.embed-field-inline {
|
||||||
|
-webkit-box-flex: 1;
|
||||||
|
-ms-flex: 1;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 150px;
|
||||||
|
-ms-flex-preferred-size: auto;
|
||||||
|
flex-basis: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-fields .embed-field .embed-field-name {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-weight: 600
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-fields .embed-field .embed-field-value {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-thumbnail,
|
||||||
|
.embed .embed-thumbnail-gifv {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-thumbnail {
|
||||||
|
margin-bottom: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed .embed-thumbnail img {
|
||||||
|
margin: 0;
|
||||||
|
max-width: 500px;
|
||||||
|
max-height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment>:last-child .embed {
|
||||||
|
margin-bottom: auto
|
||||||
|
}
|
Loading…
Reference in new issue