| @@ -7,6 +7,6 @@ namespace Discord.API.Rpc | |||
| [JsonProperty("channel_id")] | |||
| public ulong ChannelId { get; set; } | |||
| [JsonProperty("message")] | |||
| public Message Message { get; set; } | |||
| public RpcMessage Message { get; set; } | |||
| } | |||
| } | |||
| @@ -0,0 +1,17 @@ | |||
| using Newtonsoft.Json; | |||
| namespace Discord.API.Rpc | |||
| { | |||
| public class RpcMessage : Message | |||
| { | |||
| [JsonProperty("blocked")] | |||
| public Optional<bool> IsBlocked { get; } | |||
| [JsonProperty("content_parsed")] | |||
| public Optional<object[]> ContentParsed { get; } | |||
| [JsonProperty("author_color")] | |||
| public Optional<string> AuthorColor { get; } //#Hex | |||
| [JsonProperty("mentions")] | |||
| public new Optional<ulong[]> UserMentions { get; set; } | |||
| } | |||
| } | |||
| @@ -1,10 +1,65 @@ | |||
| namespace Discord.Rpc | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| using Model = Discord.API.Rpc.RpcMessage; | |||
| namespace Discord.Rpc | |||
| { | |||
| /*internal class RpcMessage : RpcEntity<ulong>, IMessage | |||
| public abstract class RpcMessage : RpcEntity<ulong>, IMessage | |||
| { | |||
| internal RpcMessage(DiscordRpcClient discord, API.Message model) | |||
| : base(dicsord, model.Id) | |||
| private long _timestampTicks; | |||
| public IMessageChannel Channel { get; } | |||
| public RpcUser Author { get; } | |||
| public string Content { get; private set; } | |||
| public Color AuthorColor { get; private set; } | |||
| public virtual bool IsTTS => false; | |||
| public virtual bool IsPinned => false; | |||
| public virtual bool IsBlocked => false; | |||
| public virtual DateTimeOffset? EditedTimestamp => null; | |||
| public virtual IReadOnlyCollection<Attachment> Attachments => ImmutableArray.Create<Attachment>(); | |||
| public virtual IReadOnlyCollection<Embed> Embeds => ImmutableArray.Create<Embed>(); | |||
| public virtual IReadOnlyCollection<ulong> MentionedChannelIds => ImmutableArray.Create<ulong>(); | |||
| public virtual IReadOnlyCollection<ulong> MentionedRoleIds => ImmutableArray.Create<ulong>(); | |||
| public virtual IReadOnlyCollection<ulong> MentionedUserIds => ImmutableArray.Create<ulong>(); | |||
| public virtual IReadOnlyCollection<ITag> Tags => ImmutableArray.Create<ITag>(); | |||
| public virtual ulong? WebhookId => null; | |||
| public bool IsWebhook => WebhookId != null; | |||
| public DateTimeOffset Timestamp => DateTimeUtils.FromTicks(_timestampTicks); | |||
| internal RpcMessage(DiscordRpcClient discord, ulong id, IMessageChannel channel, RpcUser author) | |||
| : base(discord, id) | |||
| { | |||
| Channel = channel; | |||
| Author = author; | |||
| } | |||
| }*/ | |||
| internal static RpcMessage Create(DiscordRpcClient discord, ulong channelId, Model model) | |||
| { | |||
| //model.ChannelId is always 0, needs to be passed from the event | |||
| if (model.Type == MessageType.Default) | |||
| return RpcUserMessage.Create(discord, channelId, model); | |||
| else | |||
| return RpcSystemMessage.Create(discord, channelId, model); | |||
| } | |||
| internal virtual void Update(Model model) | |||
| { | |||
| if (model.Timestamp.IsSpecified) | |||
| _timestampTicks = model.Timestamp.Value.UtcTicks; | |||
| if (model.Content.IsSpecified) | |||
| Content = model.Content.Value; | |||
| if (model.AuthorColor.IsSpecified) | |||
| AuthorColor = new Color(Convert.ToUInt32(model.AuthorColor.Value.Substring(1), 16)); | |||
| } | |||
| public override string ToString() => Content; | |||
| MessageType IMessage.Type => MessageType.Default; | |||
| IUser IMessage.Author => Author; | |||
| IReadOnlyCollection<IAttachment> IMessage.Attachments => Attachments; | |||
| IReadOnlyCollection<IEmbed> IMessage.Embeds => Embeds; | |||
| } | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| using Discord.Rest; | |||
| using System.Diagnostics; | |||
| using Model = Discord.API.Rpc.RpcMessage; | |||
| namespace Discord.Rpc | |||
| { | |||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
| public class RpcSystemMessage : RpcMessage, ISystemMessage | |||
| { | |||
| public MessageType Type { get; private set; } | |||
| internal RpcSystemMessage(DiscordRpcClient discord, ulong id, IMessageChannel channel, RpcUser author) | |||
| : base(discord, id, channel, author) | |||
| { | |||
| } | |||
| internal new static RpcSystemMessage Create(DiscordRpcClient discord, ulong channelId, Model model) | |||
| { | |||
| var entity = new RpcSystemMessage(discord, model.Id, | |||
| RestVirtualMessageChannel.Create(discord, channelId), | |||
| RpcUser.Create(discord, model.Author.Value)); | |||
| entity.Update(model); | |||
| return entity; | |||
| } | |||
| internal override void Update(Model model) | |||
| { | |||
| base.Update(model); | |||
| Type = model.Type; | |||
| } | |||
| private string DebuggerDisplay => $"{Author}: {Content} ({Id}, {Type})"; | |||
| } | |||
| } | |||
| @@ -0,0 +1,117 @@ | |||
| using Discord.API.Rest; | |||
| using Discord.Rest; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Collections.Immutable; | |||
| using System.Diagnostics; | |||
| using System.Threading.Tasks; | |||
| using Model = Discord.API.Rpc.RpcMessage; | |||
| namespace Discord.Rpc | |||
| { | |||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
| public class RpcUserMessage : RpcMessage, IUserMessage | |||
| { | |||
| private bool _isMentioningEveryone, _isTTS, _isPinned, _isBlocked; | |||
| private long? _editedTimestampTicks; | |||
| private ulong? _webhookId; | |||
| private ImmutableArray<Attachment> _attachments; | |||
| private ImmutableArray<Embed> _embeds; | |||
| private ImmutableArray<ITag> _tags; | |||
| public override bool IsTTS => _isTTS; | |||
| public override bool IsPinned => _isPinned; | |||
| public override bool IsBlocked => _isBlocked; | |||
| public override ulong? WebhookId => _webhookId; | |||
| public override DateTimeOffset? EditedTimestamp => DateTimeUtils.FromTicks(_editedTimestampTicks); | |||
| public override IReadOnlyCollection<Attachment> Attachments => _attachments; | |||
| public override IReadOnlyCollection<Embed> Embeds => _embeds; | |||
| public override IReadOnlyCollection<ulong> MentionedChannelIds => MessageHelper.FilterTagsByKey(TagType.ChannelMention, _tags); | |||
| public override IReadOnlyCollection<ulong> MentionedRoleIds => MessageHelper.FilterTagsByKey(TagType.RoleMention, _tags); | |||
| public override IReadOnlyCollection<ulong> MentionedUserIds => MessageHelper.FilterTagsByKey(TagType.UserMention, _tags); | |||
| public override IReadOnlyCollection<ITag> Tags => _tags; | |||
| internal RpcUserMessage(DiscordRpcClient discord, ulong id, IMessageChannel channel, RpcUser author) | |||
| : base(discord, id, channel, author) | |||
| { | |||
| } | |||
| internal new static RpcUserMessage Create(DiscordRpcClient discord, ulong channelId, Model model) | |||
| { | |||
| var entity = new RpcUserMessage(discord, model.Id, | |||
| RestVirtualMessageChannel.Create(discord, channelId), | |||
| RpcUser.Create(discord, model.Author.Value)); | |||
| entity.Update(model); | |||
| return entity; | |||
| } | |||
| internal override void Update(Model model) | |||
| { | |||
| base.Update(model); | |||
| if (model.IsTextToSpeech.IsSpecified) | |||
| _isTTS = model.IsTextToSpeech.Value; | |||
| if (model.Pinned.IsSpecified) | |||
| _isPinned = model.Pinned.Value; | |||
| if (model.EditedTimestamp.IsSpecified) | |||
| _editedTimestampTicks = model.EditedTimestamp.Value?.UtcTicks; | |||
| if (model.MentionEveryone.IsSpecified) | |||
| _isMentioningEveryone = model.MentionEveryone.Value; | |||
| if (model.WebhookId.IsSpecified) | |||
| _webhookId = model.WebhookId.Value; | |||
| if (model.IsBlocked.IsSpecified) | |||
| _isBlocked = model.IsBlocked.Value; | |||
| if (model.Attachments.IsSpecified) | |||
| { | |||
| var value = model.Attachments.Value; | |||
| if (value.Length > 0) | |||
| { | |||
| var attachments = ImmutableArray.CreateBuilder<Attachment>(value.Length); | |||
| for (int i = 0; i < value.Length; i++) | |||
| attachments.Add(Attachment.Create(value[i])); | |||
| _attachments = attachments.ToImmutable(); | |||
| } | |||
| else | |||
| _attachments = ImmutableArray.Create<Attachment>(); | |||
| } | |||
| if (model.Embeds.IsSpecified) | |||
| { | |||
| var value = model.Embeds.Value; | |||
| if (value.Length > 0) | |||
| { | |||
| var embeds = ImmutableArray.CreateBuilder<Embed>(value.Length); | |||
| for (int i = 0; i < value.Length; i++) | |||
| embeds.Add(Embed.Create(value[i])); | |||
| _embeds = embeds.ToImmutable(); | |||
| } | |||
| else | |||
| _embeds = ImmutableArray.Create<Embed>(); | |||
| } | |||
| if (model.Content.IsSpecified) | |||
| { | |||
| var text = model.Content.Value; | |||
| _tags = MessageHelper.ParseTags(text, null, null, ImmutableArray.Create<IUser>()); | |||
| model.Content = text; | |||
| } | |||
| } | |||
| public Task ModifyAsync(Action<ModifyMessageParams> func, RequestOptions options) | |||
| => MessageHelper.ModifyAsync(this, Discord, func, options); | |||
| public Task DeleteAsync(RequestOptions options) | |||
| => MessageHelper.DeleteAsync(this, Discord, options); | |||
| public Task PinAsync(RequestOptions options) | |||
| => MessageHelper.PinAsync(this, Discord, options); | |||
| public Task UnpinAsync(RequestOptions options) | |||
| => MessageHelper.UnpinAsync(this, Discord, options); | |||
| public string Resolve(TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name, | |||
| TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name) | |||
| => MentionUtils.Resolve(this, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling); | |||
| private string DebuggerDisplay => $"{Author}: {Content} ({Id}{(Attachments.Count > 0 ? $", {Attachments.Count} Attachments" : "")})"; | |||
| } | |||
| } | |||
| @@ -0,0 +1,62 @@ | |||
| using Discord.Rest; | |||
| using System.Diagnostics; | |||
| using System.Threading.Tasks; | |||
| using Model = Discord.API.User; | |||
| namespace Discord.Rpc | |||
| { | |||
| [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | |||
| public class RpcUser : RpcEntity<ulong>, IUser, IUpdateable | |||
| { | |||
| public bool IsBot { get; private set; } | |||
| public string Username { get; private set; } | |||
| public ushort DiscriminatorValue { get; private set; } | |||
| public string AvatarId { get; private set; } | |||
| public string AvatarUrl => API.CDN.GetUserAvatarUrl(Id, AvatarId); | |||
| public string Discriminator => DiscriminatorValue.ToString("D4"); | |||
| public string Mention => MentionUtils.MentionUser(Id); | |||
| public virtual Game? Game => null; | |||
| public virtual UserStatus Status => UserStatus.Unknown; | |||
| internal RpcUser(DiscordRpcClient discord, ulong id) | |||
| : base(discord, id) | |||
| { | |||
| } | |||
| internal static RpcUser Create(DiscordRpcClient discord, Model model) | |||
| { | |||
| var entity = new RpcUser(discord, model.Id); | |||
| entity.Update(model); | |||
| return entity; | |||
| } | |||
| internal virtual void Update(Model model) | |||
| { | |||
| if (model.Avatar.IsSpecified) | |||
| AvatarId = model.Avatar.Value; | |||
| if (model.Discriminator.IsSpecified) | |||
| DiscriminatorValue = ushort.Parse(model.Discriminator.Value); | |||
| if (model.Bot.IsSpecified) | |||
| IsBot = model.Bot.Value; | |||
| if (model.Username.IsSpecified) | |||
| Username = model.Username.Value; | |||
| } | |||
| public virtual async Task UpdateAsync(RequestOptions options = null) | |||
| { | |||
| var model = await Discord.ApiClient.GetUserAsync(Id, options); | |||
| Update(model); | |||
| } | |||
| public Task<RestDMChannel> CreateDMChannelAsync(RequestOptions options = null) | |||
| => UserHelper.CreateDMChannelAsync(this, Discord, options); | |||
| public override string ToString() => $"{Username}#{Discriminator}"; | |||
| internal string DebuggerDisplay => $"{Username}#{Discriminator} ({Id}{(IsBot ? ", Bot" : "")})"; | |||
| //IUser | |||
| Task<IDMChannel> IUser.GetDMChannelAsync(CacheMode mode, RequestOptions options) | |||
| => Task.FromResult<IDMChannel>(null); | |||
| async Task<IDMChannel> IUser.CreateDMChannelAsync(RequestOptions options) | |||
| => await CreateDMChannelAsync(options); | |||
| } | |||
| } | |||