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.

ClientState.cs 6.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. namespace Discord.WebSocket
  6. {
  7. internal class ClientState
  8. {
  9. private const double AverageChannelsPerGuild = 10.22; //Source: Googie2149
  10. private const double AverageUsersPerGuild = 47.78; //Source: Googie2149
  11. private const double CollectionMultiplier = 1.05; //Add 5% buffer to handle growth
  12. private readonly ConcurrentDictionary<ulong, SocketChannel> _channels;
  13. private readonly ConcurrentDictionary<ulong, SocketDMChannel> _dmChannels;
  14. private readonly ConcurrentDictionary<ulong, SocketGuild> _guilds;
  15. private readonly ConcurrentDictionary<ulong, SocketGlobalUser> _users;
  16. private readonly ConcurrentDictionary<ulong, SocketRelationship> _relationships;
  17. private readonly ConcurrentHashSet<ulong> _groupChannels;
  18. internal IReadOnlyCollection<SocketChannel> Channels => _channels.ToReadOnlyCollection();
  19. internal IReadOnlyCollection<SocketDMChannel> DMChannels => _dmChannels.ToReadOnlyCollection();
  20. internal IReadOnlyCollection<SocketGroupChannel> GroupChannels => _groupChannels.Select(x => GetChannel(x) as SocketGroupChannel).ToReadOnlyCollection(_groupChannels);
  21. internal IReadOnlyCollection<SocketGuild> Guilds => _guilds.ToReadOnlyCollection();
  22. internal IReadOnlyCollection<SocketGlobalUser> Users => _users.ToReadOnlyCollection();
  23. internal IReadOnlyCollection<SocketRelationship> Relationships => _relationships.ToReadOnlyCollection();
  24. internal IReadOnlyCollection<ISocketPrivateChannel> PrivateChannels =>
  25. _dmChannels.Select(x => x.Value as ISocketPrivateChannel).Concat(
  26. _groupChannels.Select(x => GetChannel(x) as ISocketPrivateChannel))
  27. .ToReadOnlyCollection(() => _dmChannels.Count + _groupChannels.Count);
  28. public ClientState(int guildCount, int dmChannelCount)
  29. {
  30. double estimatedChannelCount = guildCount * AverageChannelsPerGuild + dmChannelCount;
  31. double estimatedUsersCount = guildCount * AverageUsersPerGuild;
  32. _channels = new ConcurrentDictionary<ulong, SocketChannel>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(estimatedChannelCount * CollectionMultiplier));
  33. _dmChannels = new ConcurrentDictionary<ulong, SocketDMChannel>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(dmChannelCount * CollectionMultiplier));
  34. _guilds = new ConcurrentDictionary<ulong, SocketGuild>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(guildCount * CollectionMultiplier));
  35. _users = new ConcurrentDictionary<ulong, SocketGlobalUser>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(estimatedUsersCount * CollectionMultiplier));
  36. _relationships = new ConcurrentDictionary<ulong, SocketRelationship>(ConcurrentHashSet.DefaultConcurrencyLevel, 35);
  37. _groupChannels = new ConcurrentHashSet<ulong>(ConcurrentHashSet.DefaultConcurrencyLevel, (int)(10 * CollectionMultiplier));
  38. }
  39. internal SocketChannel GetChannel(ulong id)
  40. {
  41. if (_channels.TryGetValue(id, out SocketChannel channel))
  42. return channel;
  43. return null;
  44. }
  45. internal SocketDMChannel GetDMChannel(ulong userId)
  46. {
  47. if (_dmChannels.TryGetValue(userId, out SocketDMChannel channel))
  48. return channel;
  49. return null;
  50. }
  51. internal void AddChannel(SocketChannel channel)
  52. {
  53. _channels[channel.Id] = channel;
  54. switch (channel)
  55. {
  56. case SocketDMChannel dmChannel:
  57. _dmChannels[dmChannel.Recipient.Id] = dmChannel;
  58. break;
  59. case SocketGroupChannel groupChannel:
  60. _groupChannels.TryAdd(groupChannel.Id);
  61. break;
  62. }
  63. }
  64. internal SocketChannel RemoveChannel(ulong id)
  65. {
  66. if (_channels.TryRemove(id, out SocketChannel channel))
  67. {
  68. switch (channel)
  69. {
  70. case SocketDMChannel dmChannel:
  71. _dmChannels.TryRemove(dmChannel.Recipient.Id, out var ignored);
  72. break;
  73. case SocketGroupChannel groupChannel:
  74. _groupChannels.TryRemove(id);
  75. break;
  76. }
  77. return channel;
  78. }
  79. return null;
  80. }
  81. internal SocketGuild GetGuild(ulong id)
  82. {
  83. if (_guilds.TryGetValue(id, out SocketGuild guild))
  84. return guild;
  85. return null;
  86. }
  87. internal void AddGuild(SocketGuild guild)
  88. {
  89. _guilds[guild.Id] = guild;
  90. }
  91. internal SocketGuild RemoveGuild(ulong id)
  92. {
  93. if (_guilds.TryRemove(id, out SocketGuild guild))
  94. return guild;
  95. return null;
  96. }
  97. internal SocketGlobalUser GetUser(ulong id)
  98. {
  99. if (_users.TryGetValue(id, out SocketGlobalUser user))
  100. return user;
  101. return null;
  102. }
  103. internal SocketGlobalUser GetOrAddUser(ulong id, Func<ulong, SocketGlobalUser> userFactory)
  104. {
  105. return _users.GetOrAdd(id, userFactory);
  106. }
  107. internal SocketGlobalUser RemoveUser(ulong id)
  108. {
  109. if (_users.TryRemove(id, out SocketGlobalUser user))
  110. return user;
  111. return null;
  112. }
  113. internal SocketRelationship GetRelationship(ulong id)
  114. {
  115. if (_relationships.TryGetValue(id, out SocketRelationship value))
  116. return value;
  117. return null;
  118. }
  119. internal void AddRelationship(SocketRelationship relationship)
  120. {
  121. _relationships[relationship.User.Id] = relationship;
  122. }
  123. internal SocketRelationship RemoveRelationship(ulong id)
  124. {
  125. if (_relationships.TryRemove(id, out SocketRelationship value))
  126. return value;
  127. return null;
  128. }
  129. }
  130. }