You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

RestUserMessage.cs 8.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.Immutable;
  4. using System.Diagnostics;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7. using Model = Discord.API.Message;
  8. namespace Discord.Rest
  9. {
  10. [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
  11. public class RestUserMessage : RestMessage, IUserMessage
  12. {
  13. private bool _isMentioningEveryone, _isTTS, _isPinned;
  14. private long? _editedTimestampTicks;
  15. private ImmutableArray<Attachment> _attachments;
  16. private ImmutableArray<Embed> _embeds;
  17. private ImmutableArray<ITag> _tags;
  18. private ImmutableArray<RestReaction> _reactions;
  19. public override bool IsTTS => _isTTS;
  20. public override bool IsPinned => _isPinned;
  21. public override DateTimeOffset? EditedTimestamp => DateTimeUtils.FromTicks(_editedTimestampTicks);
  22. public override IReadOnlyCollection<Attachment> Attachments => _attachments;
  23. public override IReadOnlyCollection<Embed> Embeds => _embeds;
  24. public override IReadOnlyCollection<ulong> MentionedChannelIds => MessageHelper.FilterTagsByKey(TagType.ChannelMention, _tags);
  25. public override IReadOnlyCollection<ulong> MentionedRoleIds => MessageHelper.FilterTagsByKey(TagType.RoleMention, _tags);
  26. public override IReadOnlyCollection<RestUser> MentionedUsers => MessageHelper.FilterTagsByValue<RestUser>(TagType.UserMention, _tags);
  27. public override IReadOnlyCollection<ITag> Tags => _tags;
  28. public IReadOnlyDictionary<IEmote, ReactionMetadata> Reactions => _reactions.ToDictionary(x => x.Emote, x => new ReactionMetadata { ReactionCount = x.Count, IsMe = x.Me });
  29. internal RestUserMessage(BaseDiscordClient discord, ulong id, IMessageChannel channel, IUser author, MessageSource source)
  30. : base(discord, id, channel, author, source)
  31. {
  32. }
  33. internal static new RestUserMessage Create(BaseDiscordClient discord, IMessageChannel channel, IUser author, Model model)
  34. {
  35. var entity = new RestUserMessage(discord, model.Id, channel, author, MessageHelper.GetSource(model));
  36. entity.Update(model);
  37. return entity;
  38. }
  39. internal override void Update(Model model)
  40. {
  41. base.Update(model);
  42. if (model.IsTextToSpeech.IsSpecified)
  43. _isTTS = model.IsTextToSpeech.Value;
  44. if (model.Pinned.IsSpecified)
  45. _isPinned = model.Pinned.Value;
  46. if (model.EditedTimestamp.IsSpecified)
  47. _editedTimestampTicks = model.EditedTimestamp.Value?.UtcTicks;
  48. if (model.MentionEveryone.IsSpecified)
  49. _isMentioningEveryone = model.MentionEveryone.Value;
  50. if (model.Attachments.IsSpecified)
  51. {
  52. var value = model.Attachments.Value;
  53. if (value.Length > 0)
  54. {
  55. var attachments = ImmutableArray.CreateBuilder<Attachment>(value.Length);
  56. for (int i = 0; i < value.Length; i++)
  57. attachments.Add(Attachment.Create(value[i]));
  58. _attachments = attachments.ToImmutable();
  59. }
  60. else
  61. _attachments = ImmutableArray.Create<Attachment>();
  62. }
  63. if (model.Embeds.IsSpecified)
  64. {
  65. var value = model.Embeds.Value;
  66. if (value.Length > 0)
  67. {
  68. var embeds = ImmutableArray.CreateBuilder<Embed>(value.Length);
  69. for (int i = 0; i < value.Length; i++)
  70. embeds.Add(value[i].ToEntity());
  71. _embeds = embeds.ToImmutable();
  72. }
  73. else
  74. _embeds = ImmutableArray.Create<Embed>();
  75. }
  76. ImmutableArray<IUser> mentions = ImmutableArray.Create<IUser>();
  77. if (model.UserMentions.IsSpecified)
  78. {
  79. var value = model.UserMentions.Value;
  80. if (value.Length > 0)
  81. {
  82. var newMentions = ImmutableArray.CreateBuilder<IUser>(value.Length);
  83. for (int i = 0; i < value.Length; i++)
  84. {
  85. var val = value[i];
  86. if (val.Object != null)
  87. newMentions.Add(RestUser.Create(Discord, val.Object));
  88. }
  89. mentions = newMentions.ToImmutable();
  90. }
  91. }
  92. if (model.Reactions.IsSpecified)
  93. {
  94. var value = model.Reactions.Value;
  95. if (value.Length > 0)
  96. {
  97. var reactions = ImmutableArray.CreateBuilder<RestReaction>(value.Length);
  98. for (int i = 0; i < value.Length; i++)
  99. reactions.Add(RestReaction.Create(value[i]));
  100. _reactions = reactions.ToImmutable();
  101. }
  102. else
  103. _reactions = ImmutableArray.Create<RestReaction>();
  104. }
  105. else
  106. _reactions = ImmutableArray.Create<RestReaction>();
  107. if (model.Content.IsSpecified)
  108. {
  109. var text = model.Content.Value;
  110. var guildId = (Channel as IGuildChannel)?.GuildId;
  111. var guild = guildId != null ? (Discord as IDiscordClient).GetGuildAsync(guildId.Value, CacheMode.CacheOnly).Result : null;
  112. _tags = MessageHelper.ParseTags(text, null, guild, mentions);
  113. model.Content = text;
  114. }
  115. }
  116. public async Task ModifyAsync(Action<MessageProperties> func, RequestOptions options = null)
  117. {
  118. if (Author.Id != Discord.CurrentUser.Id)
  119. throw new InvalidOperationException("Discord allows only the author of a message to change it.");
  120. var model = await MessageHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false);
  121. Update(model);
  122. }
  123. public Task AddReactionAsync(IEmote emote, RequestOptions options = null)
  124. => MessageHelper.AddReactionAsync(this, emote, Discord, options);
  125. public Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null)
  126. => MessageHelper.RemoveReactionAsync(this, user, emote, Discord, options);
  127. public Task RemoveAllReactionsAsync(RequestOptions options = null)
  128. => MessageHelper.RemoveAllReactionsAsync(this, Discord, options);
  129. public Task<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit = 100, ulong? afterUserId = null, RequestOptions options = null)
  130. => MessageHelper.GetReactionUsersAsync(this, emote, x => { x.Limit = limit; x.AfterUserId = afterUserId ?? Optional.Create<ulong>(); }, Discord, options);
  131. public Task PinAsync(RequestOptions options = null)
  132. => MessageHelper.PinAsync(this, Discord, options);
  133. public Task UnpinAsync(RequestOptions options = null)
  134. => MessageHelper.UnpinAsync(this, Discord, options);
  135. public string Resolve(int startIndex, TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name,
  136. TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name)
  137. => MentionUtils.Resolve(this, startIndex, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling);
  138. public string Resolve(TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name,
  139. TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name)
  140. => MentionUtils.Resolve(this, 0, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling);
  141. private string DebuggerDisplay => $"{Author}: {Content} ({Id}{(Attachments.Count > 0 ? $", {Attachments.Count} Attachments" : "")})";
  142. }
  143. }