| @@ -164,6 +164,14 @@ namespace Discord | |||||
| /// </summary> | /// </summary> | ||||
| IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions { get; } | IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions { get; } | ||||
| /// <summary> | |||||
| /// Gets all stickers included in this message. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A read-only collection of sticker objects. | |||||
| /// </returns> | |||||
| IReadOnlyCollection<ISticker> Stickers { get; } | |||||
| /// <summary> | /// <summary> | ||||
| /// Gets the flags related to this message. | /// Gets the flags related to this message. | ||||
| /// </summary> | /// </summary> | ||||
| @@ -0,0 +1,67 @@ | |||||
| using System.Collections.Generic; | |||||
| namespace Discord | |||||
| { | |||||
| /// <summary> | |||||
| /// Represents a discord sticker. | |||||
| /// </summary> | |||||
| public interface ISticker | |||||
| { | |||||
| /// <summary> | |||||
| /// Gets the ID of this sticker. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A snowflake ID associated with this sticker. | |||||
| /// </returns> | |||||
| ulong Id { get; } | |||||
| /// <summary> | |||||
| /// Gets the ID of the pack of this sticker. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A snowflake ID associated with the pack of this sticker. | |||||
| /// </returns> | |||||
| ulong PackId { get; } | |||||
| /// <summary> | |||||
| /// Gets the name of this sticker. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A <see langword="string"/> with the name of this sticker. | |||||
| /// </returns> | |||||
| string Name { get; } | |||||
| /// <summary> | |||||
| /// Gets the description of this sticker. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A <see langword="string"/> with the description of this sticker. | |||||
| /// </returns> | |||||
| string Description { get; } | |||||
| /// <summary> | |||||
| /// Gets the list of tags of this sticker. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A read-only list with the tags of this sticker. | |||||
| /// </returns> | |||||
| IReadOnlyCollection<string> Tags { get; } | |||||
| /// <summary> | |||||
| /// Gets the asset hash of this sticker. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A <see langword="string"/> with the asset hash of this sticker. | |||||
| /// </returns> | |||||
| string Asset { get; } | |||||
| /// <summary> | |||||
| /// Gets the preview asset hash of this sticker. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A <see langword="string"/> with the preview asset hash of this sticker. | |||||
| /// </returns> | |||||
| string PreviewAsset { get; } | |||||
| /// <summary> | |||||
| /// Gets the format type of this sticker. | |||||
| /// </summary> | |||||
| /// <returns> | |||||
| /// A <see cref="StickerFormatType"/> with the format type of this sticker. | |||||
| /// </returns> | |||||
| StickerFormatType FormatType { get; } | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,15 @@ | |||||
| namespace Discord | |||||
| { | |||||
| /// <summary> Defines the types of formats for stickers. </summary> | |||||
| public enum StickerFormatType | |||||
| { | |||||
| /// <summary> Default value for a sticker format type. </summary> | |||||
| None = 0, | |||||
| /// <summary> The sticker format type is png. </summary> | |||||
| Png = 1, | |||||
| /// <summary> The sticker format type is apng. </summary> | |||||
| Apng = 2, | |||||
| /// <summary> The sticker format type is lottie. </summary> | |||||
| Lottie = 3, | |||||
| } | |||||
| } | |||||
| @@ -58,5 +58,7 @@ namespace Discord.API | |||||
| public Optional<AllowedMentions> AllowedMentions { get; set; } | public Optional<AllowedMentions> AllowedMentions { get; set; } | ||||
| [JsonProperty("referenced_message")] | [JsonProperty("referenced_message")] | ||||
| public Optional<Message> ReferencedMessage { get; set; } | public Optional<Message> ReferencedMessage { get; set; } | ||||
| [JsonProperty("stickers")] | |||||
| public Optional<Sticker[]> Stickers { get; set; } | |||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,25 @@ | |||||
| #pragma warning disable CS1591 | |||||
| using Newtonsoft.Json; | |||||
| namespace Discord.API | |||||
| { | |||||
| internal class Sticker | |||||
| { | |||||
| [JsonProperty("id")] | |||||
| public ulong Id { get; set; } | |||||
| [JsonProperty("pack_id")] | |||||
| public ulong PackId { get; set; } | |||||
| [JsonProperty("name")] | |||||
| public string Name { get; set; } | |||||
| [JsonProperty("description")] | |||||
| public string Desription { get; set; } | |||||
| [JsonProperty("tags")] | |||||
| public Optional<string> Tags { get; set; } | |||||
| [JsonProperty("asset")] | |||||
| public string Asset { get; set; } | |||||
| [JsonProperty("preview_asset")] | |||||
| public string PreviewAsset { get; set; } | |||||
| [JsonProperty("format_type")] | |||||
| public StickerFormatType FormatType { get; set; } | |||||
| } | |||||
| } | |||||
| @@ -58,6 +58,8 @@ namespace Discord.Rest | |||||
| public virtual IReadOnlyCollection<RestUser> MentionedUsers => ImmutableArray.Create<RestUser>(); | public virtual IReadOnlyCollection<RestUser> MentionedUsers => ImmutableArray.Create<RestUser>(); | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public virtual IReadOnlyCollection<ITag> Tags => ImmutableArray.Create<ITag>(); | public virtual IReadOnlyCollection<ITag> Tags => ImmutableArray.Create<ITag>(); | ||||
| /// <inheritdoc /> | |||||
| public virtual IReadOnlyCollection<Sticker> Stickers => ImmutableArray.Create<Sticker>(); | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public DateTimeOffset Timestamp => DateTimeUtils.FromTicks(_timestampTicks); | public DateTimeOffset Timestamp => DateTimeUtils.FromTicks(_timestampTicks); | ||||
| @@ -173,6 +175,8 @@ namespace Discord.Rest | |||||
| IReadOnlyCollection<IEmbed> IMessage.Embeds => Embeds; | IReadOnlyCollection<IEmbed> IMessage.Embeds => Embeds; | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| IReadOnlyCollection<ulong> IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray(); | IReadOnlyCollection<ulong> IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray(); | ||||
| /// <inheritdoc /> | |||||
| IReadOnlyCollection<ISticker> IMessage.Stickers => Stickers; | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me }); | public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me }); | ||||
| @@ -21,6 +21,7 @@ namespace Discord.Rest | |||||
| private ImmutableArray<ITag> _tags = ImmutableArray.Create<ITag>(); | private ImmutableArray<ITag> _tags = ImmutableArray.Create<ITag>(); | ||||
| private ImmutableArray<ulong> _roleMentionIds = ImmutableArray.Create<ulong>(); | private ImmutableArray<ulong> _roleMentionIds = ImmutableArray.Create<ulong>(); | ||||
| private ImmutableArray<RestUser> _userMentions = ImmutableArray.Create<RestUser>(); | private ImmutableArray<RestUser> _userMentions = ImmutableArray.Create<RestUser>(); | ||||
| private ImmutableArray<Sticker> _stickers = ImmutableArray.Create<Sticker>(); | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public override bool IsTTS => _isTTS; | public override bool IsTTS => _isTTS; | ||||
| @@ -45,6 +46,8 @@ namespace Discord.Rest | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public override IReadOnlyCollection<ITag> Tags => _tags; | public override IReadOnlyCollection<ITag> Tags => _tags; | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public override IReadOnlyCollection<Sticker> Stickers => _stickers; | |||||
| /// <inheritdoc /> | |||||
| public IUserMessage ReferencedMessage => _referencedMessage; | public IUserMessage ReferencedMessage => _referencedMessage; | ||||
| internal RestUserMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author, MessageSource source) | internal RestUserMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author, MessageSource source) | ||||
| @@ -132,6 +135,20 @@ namespace Discord.Rest | |||||
| IUser refMsgAuthor = MessageHelper.GetAuthor(Discord, guild, refMsg.Author.Value, refMsg.WebhookId.ToNullable()); | IUser refMsgAuthor = MessageHelper.GetAuthor(Discord, guild, refMsg.Author.Value, refMsg.WebhookId.ToNullable()); | ||||
| _referencedMessage = RestUserMessage.Create(Discord, Channel, refMsgAuthor, refMsg); | _referencedMessage = RestUserMessage.Create(Discord, Channel, refMsgAuthor, refMsg); | ||||
| } | } | ||||
| if (model.Stickers.IsSpecified) | |||||
| { | |||||
| var value = model.Stickers.Value; | |||||
| if (value.Length > 0) | |||||
| { | |||||
| var stickers = ImmutableArray.CreateBuilder<Sticker>(value.Length); | |||||
| for (int i = 0; i < value.Length; i++) | |||||
| stickers.Add(Sticker.Create(value[i])); | |||||
| _stickers = stickers.ToImmutable(); | |||||
| } | |||||
| else | |||||
| _stickers = ImmutableArray.Create<Sticker>(); | |||||
| } | |||||
| } | } | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| @@ -0,0 +1,48 @@ | |||||
| using System.Collections.Generic; | |||||
| using System.Diagnostics; | |||||
| using Model = Discord.API.Sticker; | |||||
| namespace Discord | |||||
| { | |||||
| /// <inheritdoc cref="ISticker"/> | |||||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||||
| public class Sticker : ISticker | |||||
| { | |||||
| /// <inheritdoc /> | |||||
| public ulong Id { get; } | |||||
| /// <inheritdoc /> | |||||
| public ulong PackId { get; } | |||||
| /// <inheritdoc /> | |||||
| public string Name { get; } | |||||
| /// <inheritdoc /> | |||||
| public string Description { get; } | |||||
| /// <inheritdoc /> | |||||
| public IReadOnlyCollection<string> Tags { get; } | |||||
| /// <inheritdoc /> | |||||
| public string Asset { get; } | |||||
| /// <inheritdoc /> | |||||
| public string PreviewAsset { get; } | |||||
| /// <inheritdoc /> | |||||
| public StickerFormatType FormatType { get; } | |||||
| internal Sticker(ulong id, ulong packId, string name, string description, string[] tags, string asset, string previewAsset, StickerFormatType formatType) | |||||
| { | |||||
| Id = id; | |||||
| PackId = packId; | |||||
| Name = name; | |||||
| Description = description; | |||||
| Tags = tags.ToReadOnlyCollection(); | |||||
| Asset = asset; | |||||
| PreviewAsset = previewAsset; | |||||
| FormatType = formatType; | |||||
| } | |||||
| internal static Sticker Create(Model model) | |||||
| { | |||||
| return new Sticker(model.Id, model.PackId, model.Name, model.Desription, | |||||
| model.Tags.IsSpecified ? model.Tags.Value.Split(',') : new string[0], | |||||
| model.Asset, model.PreviewAsset, model.FormatType); | |||||
| } | |||||
| private string DebuggerDisplay => $"{Name} ({Id})"; | |||||
| } | |||||
| } | |||||
| @@ -99,6 +99,8 @@ namespace Discord.WebSocket | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public virtual IReadOnlyCollection<ITag> Tags => ImmutableArray.Create<ITag>(); | public virtual IReadOnlyCollection<ITag> Tags => ImmutableArray.Create<ITag>(); | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public virtual IReadOnlyCollection<Sticker> Stickers => ImmutableArray.Create<Sticker>(); | |||||
| /// <inheritdoc /> | |||||
| public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions => _reactions.GroupBy(r => r.Emote).ToDictionary(x => x.Key, x => new ReactionMetadata { ReactionCount = x.Count(), IsMe = x.Any(y => y.UserId == Discord.CurrentUser.Id) }); | public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions => _reactions.GroupBy(r => r.Emote).ToDictionary(x => x.Key, x => new ReactionMetadata { ReactionCount = x.Count(), IsMe = x.Any(y => y.UserId == Discord.CurrentUser.Id) }); | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| @@ -194,6 +196,8 @@ namespace Discord.WebSocket | |||||
| IReadOnlyCollection<ulong> IMessage.MentionedRoleIds => MentionedRoles.Select(x => x.Id).ToImmutableArray(); | IReadOnlyCollection<ulong> IMessage.MentionedRoleIds => MentionedRoles.Select(x => x.Id).ToImmutableArray(); | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| IReadOnlyCollection<ulong> IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray(); | IReadOnlyCollection<ulong> IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray(); | ||||
| /// <inheritdoc /> | |||||
| IReadOnlyCollection<ISticker> IMessage.Stickers => Stickers; | |||||
| internal void AddReaction(SocketReaction reaction) | internal void AddReaction(SocketReaction reaction) | ||||
| { | { | ||||
| @@ -23,6 +23,7 @@ namespace Discord.WebSocket | |||||
| private ImmutableArray<ITag> _tags = ImmutableArray.Create<ITag>(); | private ImmutableArray<ITag> _tags = ImmutableArray.Create<ITag>(); | ||||
| private ImmutableArray<SocketRole> _roleMentions = ImmutableArray.Create<SocketRole>(); | private ImmutableArray<SocketRole> _roleMentions = ImmutableArray.Create<SocketRole>(); | ||||
| private ImmutableArray<SocketUser> _userMentions = ImmutableArray.Create<SocketUser>(); | private ImmutableArray<SocketUser> _userMentions = ImmutableArray.Create<SocketUser>(); | ||||
| private ImmutableArray<Sticker> _stickers = ImmutableArray.Create<Sticker>(); | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public override bool IsTTS => _isTTS; | public override bool IsTTS => _isTTS; | ||||
| @@ -47,6 +48,8 @@ namespace Discord.WebSocket | |||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public override IReadOnlyCollection<SocketUser> MentionedUsers => _userMentions; | public override IReadOnlyCollection<SocketUser> MentionedUsers => _userMentions; | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||
| public override IReadOnlyCollection<Sticker> Stickers => _stickers; | |||||
| /// <inheritdoc /> | |||||
| public IUserMessage ReferencedMessage => _referencedMessage; | public IUserMessage ReferencedMessage => _referencedMessage; | ||||
| internal SocketUserMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author, MessageSource source) | internal SocketUserMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author, MessageSource source) | ||||
| @@ -158,6 +161,20 @@ namespace Discord.WebSocket | |||||
| refMsgAuthor = new SocketUnknownUser(Discord, id: 0); | refMsgAuthor = new SocketUnknownUser(Discord, id: 0); | ||||
| _referencedMessage = SocketUserMessage.Create(Discord, state, refMsgAuthor, Channel, refMsg); | _referencedMessage = SocketUserMessage.Create(Discord, state, refMsgAuthor, Channel, refMsg); | ||||
| } | } | ||||
| if (model.Stickers.IsSpecified) | |||||
| { | |||||
| var value = model.Stickers.Value; | |||||
| if (value.Length > 0) | |||||
| { | |||||
| var stickers = ImmutableArray.CreateBuilder<Sticker>(value.Length); | |||||
| for (int i = 0; i < value.Length; i++) | |||||
| stickers.Add(Sticker.Create(value[i])); | |||||
| _stickers = stickers.ToImmutable(); | |||||
| } | |||||
| else | |||||
| _stickers = ImmutableArray.Create<Sticker>(); | |||||
| } | |||||
| } | } | ||||
| /// <inheritdoc /> | /// <inheritdoc /> | ||||