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.

SocketDMChannel.cs 12 kB

7 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. using Discord.Rest;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Collections.Immutable;
  5. using System.Diagnostics;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Threading.Tasks;
  9. using Model = Discord.API.Channel;
  10. namespace Discord.WebSocket
  11. {
  12. /// <summary>
  13. /// Represents a WebSocket-based direct-message channel.
  14. /// </summary>
  15. [DebuggerDisplay(@"{DebuggerDisplay,nq}")]
  16. public class SocketDMChannel : SocketChannel, IDMChannel, ISocketPrivateChannel, ISocketMessageChannel
  17. {
  18. private readonly MessageCache _messages;
  19. /// <summary>
  20. /// Gets the recipient of the channel.
  21. /// </summary>
  22. public SocketUser Recipient { get; }
  23. /// <inheritdoc />
  24. public IReadOnlyCollection<SocketMessage> CachedMessages => _messages?.Messages ?? ImmutableArray.Create<SocketMessage>();
  25. public new IReadOnlyCollection<SocketUser> Users => ImmutableArray.Create(Discord.CurrentUser, Recipient);
  26. internal SocketDMChannel(DiscordSocketClient discord, ulong id, SocketGlobalUser recipient)
  27. : base(discord, id)
  28. {
  29. Recipient = recipient;
  30. recipient.GlobalUser.AddRef();
  31. if (Discord.MessageCacheSize > 0)
  32. _messages = new MessageCache(Discord);
  33. }
  34. internal static SocketDMChannel Create(DiscordSocketClient discord, ClientState state, Model model)
  35. {
  36. var entity = new SocketDMChannel(discord, model.Id, discord.GetOrCreateUser(state, model.Recipients.Value[0]));
  37. entity.Update(state, model);
  38. return entity;
  39. }
  40. internal override void Update(ClientState state, Model model)
  41. {
  42. Recipient.Update(state, model.Recipients.Value[0]);
  43. }
  44. /// <inheritdoc />
  45. public Task CloseAsync(RequestOptions options = null)
  46. => ChannelHelper.DeleteAsync(this, Discord, options);
  47. //Messages
  48. /// <inheritdoc />
  49. public SocketMessage GetCachedMessage(ulong id)
  50. => _messages?.Get(id);
  51. /// <summary>
  52. /// Gets the message associated with the passed <paramref name="id"/>.
  53. /// </summary>
  54. /// <param name="id">The snowflake identifier of the message you want to retrieve.</param>
  55. /// <param name="options">The options to be used when sending the request.</param>
  56. /// <returns>
  57. /// An awaitable <see cref="Task"/> containing an <see cref="IMesage"/>.
  58. /// </returns>
  59. public async Task<IMessage> GetMessageAsync(ulong id, RequestOptions options = null)
  60. {
  61. IMessage msg = _messages?.Get(id);
  62. if (msg == null)
  63. msg = await ChannelHelper.GetMessageAsync(this, Discord, id, options).ConfigureAwait(false);
  64. return msg;
  65. }
  66. /// <summary>
  67. /// Gets a nested collection of messages.
  68. /// </summary>
  69. /// <param name="limit">The number of messages you want to get.</param>
  70. /// <param name="options">The options to be used when sending the request.</param>
  71. /// <returns>
  72. /// An awaitable <see cref="Task"/> containing an <see cref="IReadOnlyCollection{IMessage}"/>.
  73. /// </returns>
  74. public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
  75. => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, null, Direction.Before, limit, CacheMode.AllowDownload, options);
  76. public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
  77. => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, CacheMode.AllowDownload, options);
  78. public IAsyncEnumerable<IReadOnlyCollection<IMessage>> GetMessagesAsync(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch, RequestOptions options = null)
  79. => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, CacheMode.AllowDownload, options);
  80. /// <inheritdoc />
  81. public IReadOnlyCollection<SocketMessage> GetCachedMessages(int limit = DiscordConfig.MaxMessagesPerBatch)
  82. => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, null, Direction.Before, limit);
  83. /// <inheritdoc />
  84. public IReadOnlyCollection<SocketMessage> GetCachedMessages(ulong fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
  85. => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessageId, dir, limit);
  86. /// <inheritdoc />
  87. public IReadOnlyCollection<SocketMessage> GetCachedMessages(IMessage fromMessage, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
  88. => SocketChannelHelper.GetCachedMessages(this, Discord, _messages, fromMessage.Id, dir, limit);
  89. /// <inheritdoc />
  90. public Task<IReadOnlyCollection<RestMessage>> GetPinnedMessagesAsync(RequestOptions options = null)
  91. => ChannelHelper.GetPinnedMessagesAsync(this, Discord, options);
  92. /// <inheritdoc />
  93. /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
  94. public Task<RestUserMessage> SendMessageAsync(string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null)
  95. => ChannelHelper.SendMessageAsync(this, Discord, text, isTTS, embed, options);
  96. /// <inheritdoc />
  97. public Task<RestUserMessage> SendFileAsync(string filePath, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
  98. => ChannelHelper.SendFileAsync(this, Discord, filePath, text, isTTS, embed, options);
  99. /// <inheritdoc />
  100. /// <exception cref="ArgumentOutOfRangeException">Message content is too long, length must be less or equal to <see cref="DiscordConfig.MaxMessageSize"/>.</exception>
  101. public Task<RestUserMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS = false, Embed embed = null, RequestOptions options = null)
  102. => ChannelHelper.SendFileAsync(this, Discord, stream, filename, text, isTTS, embed, options);
  103. /// <inheritdoc />
  104. public Task DeleteMessageAsync(ulong messageId, RequestOptions options = null)
  105. => ChannelHelper.DeleteMessageAsync(this, messageId, Discord, options);
  106. /// <inheritdoc />
  107. public Task DeleteMessageAsync(IMessage message, RequestOptions options = null)
  108. => ChannelHelper.DeleteMessageAsync(this, message.Id, Discord, options);
  109. /// <inheritdoc />
  110. public Task TriggerTypingAsync(RequestOptions options = null)
  111. => ChannelHelper.TriggerTypingAsync(this, Discord, options);
  112. /// <inheritdoc />
  113. public IDisposable EnterTypingState(RequestOptions options = null)
  114. => ChannelHelper.EnterTypingState(this, Discord, options);
  115. internal void AddMessage(SocketMessage msg)
  116. => _messages?.Add(msg);
  117. internal SocketMessage RemoveMessage(ulong id)
  118. => _messages?.Remove(id);
  119. //Users
  120. /// <summary>
  121. /// Gets a user in this channel from the provided <paramref name="id"/>.
  122. /// </summary>
  123. /// <param name="id">The snowflake identifier of the user.</param>
  124. /// <returns>
  125. /// A <see cref="SocketUser"/> object that is a recipient of this channel; otherwise <c>null</c>.
  126. /// </returns>
  127. public new SocketUser GetUser(ulong id)
  128. {
  129. if (id == Recipient.Id)
  130. return Recipient;
  131. else if (id == Discord.CurrentUser.Id)
  132. return Discord.CurrentUser;
  133. else
  134. return null;
  135. }
  136. /// <summary>
  137. /// Returns the recipient user.
  138. /// </summary>
  139. public override string ToString() => $"@{Recipient}";
  140. private string DebuggerDisplay => $"@{Recipient} ({Id}, DM)";
  141. internal new SocketDMChannel Clone() => MemberwiseClone() as SocketDMChannel;
  142. //SocketChannel
  143. /// <inheritdoc />
  144. internal override IReadOnlyCollection<SocketUser> GetUsersInternal() => Users;
  145. /// <inheritdoc />
  146. internal override SocketUser GetUserInternal(ulong id) => GetUser(id);
  147. //IDMChannel
  148. /// <inheritdoc />
  149. IUser IDMChannel.Recipient => Recipient;
  150. //ISocketPrivateChannel
  151. /// <inheritdoc />
  152. IReadOnlyCollection<SocketUser> ISocketPrivateChannel.Recipients => ImmutableArray.Create(Recipient);
  153. //IPrivateChannel
  154. /// <inheritdoc />
  155. IReadOnlyCollection<IUser> IPrivateChannel.Recipients => ImmutableArray.Create<IUser>(Recipient);
  156. //IMessageChannel
  157. /// <inheritdoc />
  158. async Task<IMessage> IMessageChannel.GetMessageAsync(ulong id, CacheMode mode, RequestOptions options)
  159. {
  160. if (mode == CacheMode.AllowDownload)
  161. return await GetMessageAsync(id, options).ConfigureAwait(false);
  162. else
  163. return GetCachedMessage(id);
  164. }
  165. /// <inheritdoc />
  166. IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(int limit, CacheMode mode, RequestOptions options)
  167. => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, null, Direction.Before, limit, mode, options);
  168. /// <inheritdoc />
  169. IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(ulong fromMessageId, Direction dir, int limit, CacheMode mode, RequestOptions options)
  170. => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessageId, dir, limit, mode, options);
  171. /// <inheritdoc />
  172. IAsyncEnumerable<IReadOnlyCollection<IMessage>> IMessageChannel.GetMessagesAsync(IMessage fromMessage, Direction dir, int limit, CacheMode mode, RequestOptions options)
  173. => SocketChannelHelper.GetMessagesAsync(this, Discord, _messages, fromMessage.Id, dir, limit, mode, options);
  174. /// <inheritdoc />
  175. async Task<IReadOnlyCollection<IMessage>> IMessageChannel.GetPinnedMessagesAsync(RequestOptions options)
  176. => await GetPinnedMessagesAsync(options).ConfigureAwait(false);
  177. /// <inheritdoc />
  178. async Task<IUserMessage> IMessageChannel.SendFileAsync(string filePath, string text, bool isTTS, Embed embed, RequestOptions options)
  179. => await SendFileAsync(filePath, text, isTTS, embed, options).ConfigureAwait(false);
  180. /// <inheritdoc />
  181. async Task<IUserMessage> IMessageChannel.SendFileAsync(Stream stream, string filename, string text, bool isTTS, Embed embed, RequestOptions options)
  182. => await SendFileAsync(stream, filename, text, isTTS, embed, options).ConfigureAwait(false);
  183. /// <inheritdoc />
  184. async Task<IUserMessage> IMessageChannel.SendMessageAsync(string text, bool isTTS, Embed embed, RequestOptions options)
  185. => await SendMessageAsync(text, isTTS, embed, options).ConfigureAwait(false);
  186. //IChannel
  187. /// <inheritdoc />
  188. string IChannel.Name => $"@{Recipient}";
  189. /// <inheritdoc />
  190. Task<IUser> IChannel.GetUserAsync(ulong id, CacheMode mode, RequestOptions options)
  191. => Task.FromResult<IUser>(GetUser(id));
  192. /// <inheritdoc />
  193. IAsyncEnumerable<IReadOnlyCollection<IUser>> IChannel.GetUsersAsync(CacheMode mode, RequestOptions options)
  194. => ImmutableArray.Create<IReadOnlyCollection<IUser>>(Users).ToAsyncEnumerable();
  195. }
  196. }