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.

SocketUserMessage.cs 8.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. using Discord.Rest;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Collections.Immutable;
  5. using System.Diagnostics;
  6. using System.Linq;
  7. using System.Threading.Tasks;
  8. using Model = Discord.API.Message;
  9. namespace Discord.WebSocket
  10. {
  11. [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
  12. public class SocketUserMessage : SocketMessage, IUserMessage
  13. {
  14. private bool _isMentioningEveryone, _isTTS, _isPinned;
  15. private long? _editedTimestampTicks;
  16. private ImmutableArray<Attachment> _attachments;
  17. private ImmutableArray<Embed> _embeds;
  18. private ImmutableArray<ITag> _tags;
  19. private List<SocketReaction> _reactions = new List<SocketReaction>();
  20. public override bool IsTTS => _isTTS;
  21. public override bool IsPinned => _isPinned;
  22. public override DateTimeOffset? EditedTimestamp => DateTimeUtils.FromTicks(_editedTimestampTicks);
  23. public override IReadOnlyCollection<Attachment> Attachments => _attachments;
  24. public override IReadOnlyCollection<Embed> Embeds => _embeds;
  25. public override IReadOnlyCollection<ITag> Tags => _tags;
  26. public override IReadOnlyCollection<SocketGuildChannel> MentionedChannels => MessageHelper.FilterTagsByValue<SocketGuildChannel>(TagType.ChannelMention, _tags);
  27. public override IReadOnlyCollection<SocketRole> MentionedRoles => MessageHelper.FilterTagsByValue<SocketRole>(TagType.RoleMention, _tags);
  28. public override IReadOnlyCollection<SocketUser> MentionedUsers => MessageHelper.FilterTagsByValue<SocketUser>(TagType.UserMention, _tags);
  29. 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) });
  30. internal SocketUserMessage(DiscordSocketClient discord, ulong id, ISocketMessageChannel channel, SocketUser author, MessageSource source)
  31. : base(discord, id, channel, author, source)
  32. {
  33. }
  34. internal static new SocketUserMessage Create(DiscordSocketClient discord, ClientState state, SocketUser author, ISocketMessageChannel channel, Model model)
  35. {
  36. var entity = new SocketUserMessage(discord, model.Id, channel, author, MessageHelper.GetSource(model));
  37. entity.Update(state, model);
  38. return entity;
  39. }
  40. internal override void Update(ClientState state, Model model)
  41. {
  42. base.Update(state, model);
  43. if (model.IsTextToSpeech.IsSpecified)
  44. _isTTS = model.IsTextToSpeech.Value;
  45. if (model.Pinned.IsSpecified)
  46. _isPinned = model.Pinned.Value;
  47. if (model.EditedTimestamp.IsSpecified)
  48. _editedTimestampTicks = model.EditedTimestamp.Value?.UtcTicks;
  49. if (model.MentionEveryone.IsSpecified)
  50. _isMentioningEveryone = model.MentionEveryone.Value;
  51. if (model.Attachments.IsSpecified)
  52. {
  53. var value = model.Attachments.Value;
  54. if (value.Length > 0)
  55. {
  56. var attachments = ImmutableArray.CreateBuilder<Attachment>(value.Length);
  57. for (int i = 0; i < value.Length; i++)
  58. attachments.Add(Attachment.Create(value[i]));
  59. _attachments = attachments.ToImmutable();
  60. }
  61. else
  62. _attachments = ImmutableArray.Create<Attachment>();
  63. }
  64. if (model.Embeds.IsSpecified)
  65. {
  66. var value = model.Embeds.Value;
  67. if (value.Length > 0)
  68. {
  69. var embeds = ImmutableArray.CreateBuilder<Embed>(value.Length);
  70. for (int i = 0; i < value.Length; i++)
  71. embeds.Add(value[i].ToEntity());
  72. _embeds = embeds.ToImmutable();
  73. }
  74. else
  75. _embeds = ImmutableArray.Create<Embed>();
  76. }
  77. IReadOnlyCollection<IUser> mentions = ImmutableArray.Create<SocketUnknownUser>(); //Is passed to ParseTags to get real mention collection
  78. if (model.UserMentions.IsSpecified)
  79. {
  80. var value = model.UserMentions.Value;
  81. if (value.Length > 0)
  82. {
  83. var newMentions = ImmutableArray.CreateBuilder<SocketUnknownUser>(value.Length);
  84. for (int i = 0; i < value.Length; i++)
  85. {
  86. var val = value[i];
  87. if (val.Object != null)
  88. newMentions.Add(SocketUnknownUser.Create(Discord, state, val.Object));
  89. }
  90. mentions = newMentions.ToImmutable();
  91. }
  92. }
  93. if (model.Content.IsSpecified)
  94. {
  95. var text = model.Content.Value;
  96. var guild = (Channel as SocketGuildChannel)?.Guild;
  97. _tags = MessageHelper.ParseTags(text, Channel, guild, mentions);
  98. model.Content = text;
  99. }
  100. }
  101. internal void AddReaction(SocketReaction reaction)
  102. {
  103. _reactions.Add(reaction);
  104. }
  105. internal void RemoveReaction(SocketReaction reaction)
  106. {
  107. if (_reactions.Contains(reaction))
  108. _reactions.Remove(reaction);
  109. }
  110. internal void ClearReactions()
  111. {
  112. _reactions.Clear();
  113. }
  114. public Task ModifyAsync(Action<MessageProperties> func, RequestOptions options = null)
  115. => MessageHelper.ModifyAsync(this, Discord, func, options);
  116. public Task AddReactionAsync(IEmote emote, RequestOptions options = null)
  117. => MessageHelper.AddReactionAsync(this, emote, Discord, options);
  118. public Task RemoveReactionAsync(IEmote emote, IUser user, RequestOptions options = null)
  119. => MessageHelper.RemoveReactionAsync(this, user, emote, Discord, options);
  120. public Task RemoveAllReactionsAsync(RequestOptions options = null)
  121. => MessageHelper.RemoveAllReactionsAsync(this, Discord, options);
  122. [Obsolete("GetReactionUsersAsync(string...) is deprecated, use GetReactionUsersAsync(IEmote...)")]
  123. public Task<IReadOnlyCollection<IUser>> GetReactionUsersAsync(string emoji, int limit = 100, ulong? afterUserId = null, RequestOptions options = null)
  124. => MessageHelper.GetReactionUsersAsync(this, new Emoji(emoji), x => { x.Limit = limit; x.AfterUserId = afterUserId ?? Optional.Create<ulong>(); }, Discord, options);
  125. public Task<IReadOnlyCollection<IUser>> GetReactionUsersAsync(IEmote emote, int limit = 100, ulong? afterUserId = null, RequestOptions options = null)
  126. => MessageHelper.GetReactionUsersAsync(this, emote, x => { x.Limit = limit; x.AfterUserId = afterUserId ?? Optional.Create<ulong>(); }, Discord, options);
  127. public Task PinAsync(RequestOptions options = null)
  128. => MessageHelper.PinAsync(this, Discord, options);
  129. public Task UnpinAsync(RequestOptions options = null)
  130. => MessageHelper.UnpinAsync(this, Discord, options);
  131. public string Resolve(int startIndex, TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name,
  132. TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name)
  133. => MentionUtils.Resolve(this, startIndex, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling);
  134. public string Resolve(TagHandling userHandling = TagHandling.Name, TagHandling channelHandling = TagHandling.Name,
  135. TagHandling roleHandling = TagHandling.Name, TagHandling everyoneHandling = TagHandling.Ignore, TagHandling emojiHandling = TagHandling.Name)
  136. => MentionUtils.Resolve(this, 0, userHandling, channelHandling, roleHandling, everyoneHandling, emojiHandling);
  137. private string DebuggerDisplay => $"{Author}: {Content} ({Id}{(Attachments.Count > 0 ? $", {Attachments.Count} Attachments" : "")})";
  138. internal new SocketUserMessage Clone() => MemberwiseClone() as SocketUserMessage;
  139. }
  140. }