using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; using Model = Discord.API.Message; namespace Discord.Rest { /// /// Represents a REST-based message. /// public abstract class RestMessage : RestEntity, IMessage, IUpdateable { private long _timestampTicks; private ImmutableArray _reactions = ImmutableArray.Create(); /// public IMessageChannel Channel { get; } /// /// Gets the Author of the message. /// public IUser Author { get; } /// public MessageSource Source { get; } /// public string Content { get; private set; } /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); /// public virtual bool IsTTS => false; /// public virtual bool IsPinned => false; /// public virtual bool IsSuppressed => false; /// public virtual DateTimeOffset? EditedTimestamp => null; /// public virtual bool MentionedEveryone => false; /// /// Gets a collection of the 's on the message. /// public virtual IReadOnlyCollection Attachments => ImmutableArray.Create(); /// /// Gets a collection of the 's on the message. /// public virtual IReadOnlyCollection Embeds => ImmutableArray.Create(); /// public virtual IReadOnlyCollection MentionedChannelIds => ImmutableArray.Create(); /// public virtual IReadOnlyCollection MentionedRoleIds => ImmutableArray.Create(); /// /// Gets a collection of the mentioned users in the message. /// public virtual IReadOnlyCollection MentionedUsers => ImmutableArray.Create(); /// public virtual IReadOnlyCollection Tags => ImmutableArray.Create(); /// public DateTimeOffset Timestamp => DateTimeUtils.FromTicks(_timestampTicks); /// public MessageActivity Activity { get; private set; } /// public MessageApplication Application { get; private set; } /// public MessageReference Reference { get; private set; } internal RestMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author, MessageSource source) : base(discord, id) { Channel = channel; Author = author; Source = source; } internal static RestMessage Create(BaseDiscordClient discord, IMessageChannel channel, IUser author, Model model) { if (model.Type == MessageType.Default) return RestUserMessage.Create(discord, channel, author, model); else return RestSystemMessage.Create(discord, channel, author, 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.Application.IsSpecified) { // create a new Application from the API model Application = new MessageApplication() { Id = model.Application.Value.Id, CoverImage = model.Application.Value.CoverImage, Description = model.Application.Value.Description, Icon = model.Application.Value.Icon, Name = model.Application.Value.Name }; } if (model.Activity.IsSpecified) { // create a new Activity from the API model Activity = new MessageActivity() { Type = model.Activity.Value.Type.Value, PartyId = model.Activity.Value.PartyId.GetValueOrDefault() }; } if(model.Reference.IsSpecified) { // Creates a new Reference from the API model Reference = new MessageReference { GuildId = model.Reference.Value.GuildId, ChannelId = model.Reference.Value.ChannelId, MessageId = model.Reference.Value.MessageId }; } if (model.Reactions.IsSpecified) { var value = model.Reactions.Value; if (value.Length > 0) { var reactions = ImmutableArray.CreateBuilder(value.Length); for (int i = 0; i < value.Length; i++) reactions.Add(RestReaction.Create(value[i])); _reactions = reactions.ToImmutable(); } else _reactions = ImmutableArray.Create(); } else _reactions = ImmutableArray.Create(); } /// public async Task UpdateAsync(RequestOptions options = null) { var model = await Discord.ApiClient.GetChannelMessageAsync(Channel.Id, Id, options).ConfigureAwait(false); Update(model); } /// public Task DeleteAsync(RequestOptions options = null) => MessageHelper.DeleteAsync(this, Discord, options); /// /// Gets the of the message. /// /// /// A string that is the of the message. /// public override string ToString() => Content; /// MessageType IMessage.Type => MessageType.Default; IUser IMessage.Author => Author; /// IReadOnlyCollection IMessage.Attachments => Attachments; /// IReadOnlyCollection IMessage.Embeds => Embeds; /// IReadOnlyCollection IMessage.MentionedUserIds => MentionedUsers.Select(x => x.Id).ToImmutableArray(); /// public IReadOnlyDictionary Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me }); /// public Task AddReactionAsync(IEmote emote, RequestOptions options = null) => MessageHelper.AddReactionAsync(this, emote, Discord, options); /// public Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null) => MessageHelper.RemoveReactionAsync(this, user.Id, emote, Discord, options); /// public Task RemoveReactionAsync(IEmote emote, ulong userId, RequestOptions options = null) => MessageHelper.RemoveReactionAsync(this, userId, emote, Discord, options); /// public Task RemoveAllReactionsAsync(RequestOptions options = null) => MessageHelper.RemoveAllReactionsAsync(this, Discord, options); /// public Task RemoveAllReactionsForEmoteAsync(IEmote emote, RequestOptions options = null) => MessageHelper.RemoveAllReactionsForEmoteAsync(this, emote, Discord, options); /// public IAsyncEnumerable> GetReactionUsersAsync(IEmote emote, int limit, RequestOptions options = null) => MessageHelper.GetReactionUsersAsync(this, emote, limit, Discord, options); } }