Archived
1
0
Fork 0
This repository has been archived on 2024-05-21. You can view files and clone it, but cannot push or open issues or pull requests.
maki/Maki/Discord.cs

888 lines
30 KiB
C#

using Maki.Gateway;
using Maki.Rest;
using Maki.Structures.Channels;
using Maki.Structures.Gateway;
using Maki.Structures.Guilds;
using Maki.Structures.Messages;
using Maki.Structures.Presences;
using Maki.Structures.Roles;
using Maki.Structures.Users;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace Maki
{
/// <summary>
/// Discord Client
/// </summary>
public class Discord : IDisposable
{
/// <summary>
/// Discord Gateway/API version we're targeting
/// </summary>
internal const int GATEWAY_VERSION = 6;
/// <summary>
/// Whether this client is a bot
/// </summary>
public bool IsBot => TokenType == DiscordTokenType.Bot;
/// <summary>
/// Token type, bot and user connections are handled differently
/// </summary>
public DiscordTokenType TokenType = DiscordTokenType.Bot;
#region Token
/// <summary>
/// Discord token
/// </summary>
public string Token {
get => token;
set
{
token = value;
WebRequest.Authorisation = (IsBot ? "Bot " : string.Empty) + token;
}
}
private string token = string.Empty;
#endregion
/// <summary>
/// Gateway Url
/// </summary>
internal string Gateway { get; private set; }
/// <summary>
/// Gateway shard client
/// </summary>
internal readonly GatewayShardClient ShardClient;
#region Containers
internal readonly ServerManager ServerManager;
/// <summary>
/// Servers we're in
/// </summary>
public IEnumerable<DiscordServer> Servers => ServerManager.Items;
internal readonly UserManager UserManager;
/// <summary>
/// Users we are affiliated with
/// </summary>
public IEnumerable<DiscordUser> Users => UserManager.Items;
internal readonly MemberManager MemberManager;
/// <summary>
/// Members of servers, different from users!
/// </summary>
public IEnumerable<DiscordMember> Members => MemberManager.Items;
internal readonly RoleManager RoleManager;
/// <summary>
/// Roles in servers
/// </summary>
public IEnumerable<DiscordRole> Roles => RoleManager.Items;
internal readonly ChannelManager ChannelManager;
/// <summary>
/// Channels
/// </summary>
public IEnumerable<DiscordChannel> Channels => ChannelManager.Items;
internal readonly MessageManager MessageManager;
/// <summary>
/// Messages
/// </summary>
public IEnumerable<DiscordMessage> Messages => MessageManager.Items;
#endregion
#region Events
/// <summary>
/// A channel has been created
/// </summary>
public event Action<DiscordChannel> OnChannelCreate;
/// <summary>
/// A channel has been updated
/// </summary>
public event Action<DiscordChannel> OnChannelUpdate;
/// <summary>
/// A channel has been deleted
/// </summary>
public event Action<DiscordChannel> OnChannelDelete;
/// <summary>
/// Someone has been banned from a server
/// </summary>
public event Action<DiscordUser, DiscordServer> OnBanAdd;
/// <summary>
/// Someone's ban has been lifted from a server
/// </summary>
public event Action<DiscordUser, DiscordServer> OnBanRemove;
/// <summary>
/// A server has been created
/// </summary>
public event Action<DiscordServer> OnServerCreate;
/// <summary>
/// A server has been updated
/// </summary>
public event Action<DiscordServer> OnServerUpdate;
/// <summary>
/// A server has been deleted
/// </summary>
public event Action<DiscordServer> OnServerDelete;
/// <summary>
/// A server's emoji set has been updated
/// </summary>
public event Action<DiscordServer> OnEmojisUpdate;
/// <summary>
/// Someone joined a server
/// </summary>
public event Action<DiscordMember> OnMemberAdd;
/// <summary>
/// A server member has been updated
/// </summary>
public event Action<DiscordMember> OnMemberUpdate;
/// <summary>
/// Someone left a server
/// </summary>
public event Action<DiscordMember> OnMemberRemove;
/// <summary>
/// A user role has been created in a server
/// </summary>
public event Action<DiscordRole> OnRoleCreate;
/// <summary>
/// A user role has been updated in a server
/// </summary>
public event Action<DiscordRole> OnRoleUpdate;
/// <summary>
/// A user role has been deleted in a server
/// </summary>
public event Action<DiscordRole> OnRoleDelete;
/// <summary>
/// A message has been received
/// </summary>
public event Action<DiscordMessage> OnMessageCreate;
/// <summary>
/// A message has been edited
/// </summary>
public event Action<DiscordMessage> OnMessageUpdate;
/// <summary>
/// A message has been deleted
/// </summary>
public event Action<DiscordMessage> OnMessageDelete;
/// <summary>
/// Someone started typing, fired again after 8 seconds
/// </summary>
public event Action<DiscordUser, DiscordChannel> OnTypingStart;
/// <summary>
/// Someone's status and/or game updated
/// </summary>
public event Action<DiscordMember> OnPresenceUpdate;
/// <summary>
/// Fired when the connection was successful and we're currently logged into Discord
/// </summary>
public event Action<DiscordUser> OnReady;
/// <summary>
/// Someone updated their account
/// </summary>
public event Action<DiscordUser> OnUserUpdate;
#endregion
public DiscordUser Me => UserManager.Items.FirstOrDefault();
private DiscordParams Params;
/// <summary>
/// Constructor
/// </summary>
public Discord(DiscordParams parameters = null)
{
Params = parameters ?? new DiscordParams();
ShardClient = new GatewayShardClient(this);
UserManager = new UserManager();
RoleManager = new RoleManager();
MemberManager = new MemberManager();
ChannelManager = new ChannelManager();
MessageManager = new MessageManager();
ServerManager = new ServerManager();
#region Assigning event handlers
ShardClient.OnChannelCreate += ShardManager_OnChannelCreate;
ShardClient.OnChannelUpdate += ShardManager_OnChannelUpdate;
ShardClient.OnChannelDelete += ShardManager_OnChannelDelete;
ShardClient.OnGuildBanAdd += ShardManager_OnGuildBanAdd;
ShardClient.OnGuildBanRemove += ShardManager_OnGuildBanRemove;
ShardClient.OnGuildCreate += ShardManager_OnGuildCreate;
ShardClient.OnGuildDelete += ShardManager_OnGuildDelete;
ShardClient.OnGuildUpdate += ShardManager_OnGuildUpdate;
ShardClient.OnGuildEmojisUpdate += ShardManager_OnGuildEmojisUpdate;
ShardClient.OnGuildMemberAdd += ShardManager_OnGuildMemberAdd;
ShardClient.OnGuildMemberUpdate += ShardManager_OnGuildMemberUpdate;
ShardClient.OnGuildMemberRemove += ShardManager_OnGuildMemberRemove;
ShardClient.OnGuildRoleCreate += ShardManager_OnGuildRoleCreate;
ShardClient.OnGuildRoleDelete += ShardManager_OnGuildRoleDelete;
ShardClient.OnGuildRoleUpdate += ShardManager_OnGuildRoleUpdate;
ShardClient.OnGuildIntegrationsUpdate += ShardManager_OnGuildIntegrationsUpdate;
ShardClient.OnGuildMembersChunk += ShardManager_OnGuildMembersChunk;
ShardClient.OnMessageCreate += ShardManager_OnMessageCreate;
ShardClient.OnMessageDelete += ShardManager_OnMessageDelete;
ShardClient.OnMessageUpdate += ShardManager_OnMessageUpdate;
ShardClient.OnTypingStart += ShardManager_OnTypingStart;
ShardClient.OnPresenceUpdate += ShardManager_OnPresenceUpdate;
ShardClient.OnReady += ShardManager_OnReady;
ShardClient.OnResumed += ShardManager_OnResumed;
ShardClient.OnUserUpdate += ShardManager_OnUserUpdate;
#endregion
}
/// <summary>
/// Connects to Discord using the token assigned to Token
/// </summary>
public void Connect()
{
int shards = 1;
using (WebRequest wr = new WebRequest(HttpMethod.GET, IsBot ? RestEndpoints.GatewayBot : RestEndpoints.Gateway))
{
wr.Perform();
if (wr.Status != 200)
throw new DiscordException("Failed to retrieve gateway url, is your token valid?");
GatewayInfo gi = wr.ResponseJson<GatewayInfo>();
Gateway = gi.Url;
if (gi.Shards.HasValue)
shards = gi.Shards.Value;
}
for (int i = 0; i < shards; i++)
ShardClient.Create(i);
}
/// <summary>
/// Connects to Discord using a provided token and token type
/// </summary>
/// <param name="token"></param>
/// <param name="type"></param>
public void Connect(string token, DiscordTokenType type = DiscordTokenType.Bot)
{
TokenType = type;
Token = token;
Connect();
}
/// <summary>
/// Disconnects from Discord, use Dispose instead if you're not restarting the connection
/// </summary>
public void Disconnect()
{
ShardClient.Disconnect();
Token = string.Empty;
Gateway = string.Empty;
}
#region Event Handlers
private void ShardManager_OnChannelCreate(GatewayShard shard, Channel channel)
{
Debug.Assert(channel.GuildId.HasValue, "Guild ID does not have a value?");
DiscordServer server = ServerManager.Id(channel.GuildId ?? 0);
Debug.Assert(server != null, "Target guild/server was not present in ServerManager");
DiscordChannel chan = new DiscordChannel(this, channel, server);
ChannelManager.Add(chan);
OnChannelCreate?.Invoke(chan);
}
private void ShardManager_OnChannelUpdate(GatewayShard shard, Channel channel)
{
DiscordChannel chan = ChannelManager.Id(channel.Id);
Debug.Assert(chan != null, "channel is null");
chan.Name = channel.Name;
if (chan.Type == DiscordChannelType.Private)
{
// update recipients
} else
{
// update permissions too
chan.Position = channel.Position ?? 0;
}
if (chan.Type == DiscordChannelType.Voice)
{
chan.Bitrate = channel.Bitrate ?? 0;
chan.UserLimit = channel.UserLimit ?? 0;
} else
{
chan.Topic = channel.Topic;
chan.LastMessageId = channel.LastMessageId ?? 0;
}
OnChannelUpdate?.Invoke(chan);
}
private void ShardManager_OnChannelDelete(GatewayShard shard, Channel channel)
{
DiscordChannel chan = ChannelManager.Id(channel.Id);
Debug.Assert(chan != null, "channel is null");
ChannelManager.Remove(chan);
OnChannelDelete?.Invoke(chan);
}
private void ShardManager_OnGuildBanAdd(GatewayShard shard, User sUser)
{
/*$"Id: {user.Id}",
$"Guild Id: {user.GuildId}",
$"Username: {user.Username}",
$"Tag: {user.Tag:0000}",
$"Avatar Hash: {user.AvatarHash}",
$"Is bot?: {user.IsBot}",
$"Has MFA?: {user.HasMFA}",
$"Is verified?: {user.IsVerified}",
$"E-mail: {user.EMail}"*/
DiscordUser user = UserManager.Id(sUser.Id);
Debug.Assert(user != null, "user is null");
Debug.Assert(sUser.GuildId.HasValue, "Guild ID does not have a value.");
DiscordServer server = ServerManager.Id(sUser.GuildId ?? 0);
Debug.Assert(user != null, "user is null");
Debug.Assert(server != null, "server is null");
OnBanAdd?.Invoke(user, server);
}
private void ShardManager_OnGuildBanRemove(GatewayShard shard, User sUser)
{
/*$"Id: {user.Id}",
$"Guild Id: {user.GuildId}",
$"Username: {user.Username}",
$"Tag: {user.Tag:0000}",
$"Avatar Hash: {user.AvatarHash}",
$"Is bot?: {user.IsBot}",
$"Has MFA?: {user.HasMFA}",
$"Is verified?: {user.IsVerified}",
$"E-mail: {user.EMail}"*/
DiscordUser user = UserManager.Id(sUser.Id);
Debug.Assert(user != null, "user is null");
DiscordServer server = ServerManager.Id(sUser.GuildId ?? 0);
Debug.Assert(user != null, "user is null");
Debug.Assert(server != null, "server is null");
OnBanRemove?.Invoke(user, server);
}
private void ShardManager_OnGuildCreate(GatewayShard shard, Guild guild)
{
DiscordServer server = ServerManager.Id(guild.Id);
if (server == null)
{
server = new DiscordServer(this, guild);
ServerManager.Add(server);
}
else
{
server.Name = guild.Name;
server.OwnerId = guild.OwnerId ?? 0;
server.IconHash = guild.IconHash;
server.Created = guild.Created ?? DateTime.MinValue;
}
if (guild.Channels != null)
for (int i = 0; i < guild.Channels.Length; i++)
{
Channel channel = guild.Channels[i];
channel.GuildId = server.Id;
if (ChannelManager.Exists(channel.Id))
ShardManager_OnChannelUpdate(shard, channel);
else
ShardManager_OnChannelCreate(shard, channel);
}
if (guild.Roles != null)
foreach (Role role in guild.Roles) {
GuildRole gRole = new GuildRole
{
Guild = server.Id,
Role = role,
RoleId = role.Id
};
if (RoleManager.Exists(role.Id))
ShardManager_OnGuildRoleUpdate(shard, gRole);
else
ShardManager_OnGuildRoleCreate(shard, gRole);
}
shard.Send(GatewayOPCode.RequestGuildMembers, new GatewayRequestGuildMembers {
Guild = server.Id,
Query = string.Empty,
Limit = 0,
});
OnServerCreate?.Invoke(server);
}
private void ShardManager_OnGuildDelete(GatewayShard shard, Guild guild)
{
DiscordServer server = ServerManager.Id(guild.Id);
Debug.Assert(server != null, "server is null");
server.Name = guild.Name;
server.OwnerId = guild.OwnerId ?? 0;
/*server.VoiceRegionId = guild.VoiceRegionId;
server.AfkChannelId = guild.AfkChannelId;
server.AfkTimeout = guild.AfkTimeout;
server.EmbedEnabled = guild.EmbedEnabled;
server.EmbedChannelId = guild.EmbedChannelId;
server.VerificationLevel = guild.VerificationLevel;
server.MessageNotificationLevel = guild.MessageNotificationLevel;
server.Roles = guild.Roles;
server.Emojis = guild.Emojis;
server.Features = guild.Features;
server.MultiFactorAuthLevel = guild.MultiFactorAuthLevel;*/
OnServerDelete?.Invoke(server);
// NOT THREAD SAFE AT ALL
MessageManager .Server(server).ToList().ForEach(x => MessageManager.Remove(x));
ChannelManager .Server(server).ToList().ForEach(x => ChannelManager.Remove(x));
MemberManager .Server(server).ToList().ForEach(x => MemberManager.Remove(x));
RoleManager .Server(server).ToList().ForEach(x => RoleManager.Remove(x));
ServerManager.Remove(server);
}
private void ShardManager_OnGuildUpdate(GatewayShard shard, Guild guild)
{
DiscordServer server = ServerManager.Id(guild.Id);
Debug.Assert(server != null, "server is null");
server.Name = guild.Name;
server.OwnerId = guild.OwnerId ?? 0;
server.IconHash = guild.IconHash;
/*server.VoiceRegionId = guild.VoiceRegionId;
server.AfkChannelId = guild.AfkChannelId;
server.AfkTimeout = guild.AfkTimeout;
server.EmbedEnabled = guild.EmbedEnabled;
server.EmbedChannelId = guild.EmbedChannelId;
server.VerificationLevel = guild.VerificationLevel;
server.MessageNotificationLevel = guild.MessageNotificationLevel;
server.Roles = guild.Roles;
server.Emojis = guild.Emojis;
server.Features = guild.Features;
server.MultiFactorAuthLevel = guild.MultiFactorAuthLevel;*/
OnServerUpdate?.Invoke(server);
}
private void ShardManager_OnGuildEmojisUpdate(GatewayShard shard, Guild guild)
{
DiscordServer server = ServerManager.Id(guild.Id);
Debug.Assert(server != null, "server is null");
//servers.Emojis = guild.Emojis;
OnEmojisUpdate?.Invoke(server);
}
private void ShardManager_OnGuildMemberAdd(GatewayShard shard, GuildMember sMember)
{
Debug.Assert(sMember.GuildId.HasValue, "GuildId has no value");
DiscordServer server = ServerManager.Id(sMember.GuildId ?? 0);
Debug.Assert(server != null, "server is null");
DiscordUser user = UserManager.Id(sMember.User.Id);
//Debug.Assert(user != null, "user is null");
if (user == null)
{
user = new DiscordUser(this, sMember.User);
UserManager.Add(user);
}
DiscordMember member = new DiscordMember(this, sMember, user, server);
MemberManager.Add(member);
OnMemberAdd?.Invoke(member);
}
private void ShardManager_OnGuildMemberUpdate(GatewayShard shard, GuildMember sMember)
{
Debug.Assert(sMember.GuildId.HasValue, "GuildId has no value");
DiscordMember member = MemberManager.Id(sMember.GuildId ?? 0, sMember.User.Id);
Debug.Assert(member != null, "member is null");
member.Nickname = sMember.Nickname;
member.IsDeaf = sMember.IsDeafened == true;
member.IsMute = sMember.IsMuted == true;
member.roles = new List<ulong>(sMember.Roles);
OnMemberUpdate?.Invoke(member);
}
private void ShardManager_OnGuildMemberRemove(GatewayShard shard, GuildMember sMember)
{
Debug.Assert(sMember.GuildId.HasValue, "GuildId has no value");
DiscordMember member = MemberManager.Id(sMember.GuildId ?? 0, sMember.User.Id);
Debug.Assert(member != null, "member is null");
MemberManager.Remove(member);
OnMemberRemove?.Invoke(member);
}
private void ShardManager_OnGuildRoleCreate(GatewayShard shard, GuildRole sRole)
{
/*$"Guild Id: {role.Guild}",
$"Id: {role.Role.Value.Id}",
$"Name: {role.Role.Value.Name}",
$"Colour: {role.Role.Value.Colour}",
$"Is Hoisted?: {role.Role.Value.IsHoisted}",
$"Position: {role.Role.Value.Position}",
$"Is Managed?: {role.Role.Value.IsManaged}",
$"Is Mentionable?: {role.Role.Value.IsMentionable}",
$"Permissions: {role.Role.Value.Permissions}"*/
DiscordServer server = ServerManager.Id(sRole.Guild);
Debug.Assert(server != null, "server is null");
DiscordRole role = RoleManager.Id(sRole.Role.Value.Id);
//Debug.Assert(role != null, "role is null");
// fixme
if (server == null)
return;
if (role == null)
{
role = new DiscordRole(this, sRole.Role.Value, server);
RoleManager.Add(role);
} else
{
role.Colour.Raw = sRole.Role.Value.Colour.Value;
}
OnRoleCreate?.Invoke(role);
}
private void ShardManager_OnGuildRoleDelete(GatewayShard shard, GuildRole sRole)
{
Debug.Assert(sRole.RoleId.HasValue, "RoleId has no value");
DiscordRole role = RoleManager.Id(sRole.RoleId ?? 0);
Debug.Assert(role != null, "role is null");
// NOT THREAD SAFE
MemberManager.Role(role).ToList().ForEach(x => x.roles.RemoveAll(y => y == role.Id));
RoleManager.Remove(role);
OnRoleDelete?.Invoke(role);
}
private void ShardManager_OnGuildRoleUpdate(GatewayShard shard, GuildRole sRole)
{
Debug.Assert(sRole.Role.HasValue, "Role has no value");
Role dRole = sRole.Role.Value;
DiscordRole role = RoleManager.Id(dRole.Id);
Debug.Assert(role != null, "role is null");
role.Name = dRole.Name;
role.IsHoisted = dRole.IsHoisted == true;
role.IsMentionable = dRole.IsMentionable == true;
role.Perms = (DiscordPermission)dRole.Permissions;
role.Position = dRole.Position ?? 0;
role.Colour.Raw = dRole.Colour ?? 0;
OnRoleUpdate?.Invoke(role);
}
private void ShardManager_OnGuildIntegrationsUpdate(GatewayShard shard, GuildIntegration integration)
{
/*$"Id: {integration.Id}",
$"Name: {integration.Name}",
$"Type: {integration.Type}",
$"Is Enabled?: {integration.IsEnabled}",
$"Is Syncing?: {integration.IsSyncing}",
$"Role Id: {integration.RoleId}",
$"Expire Behaviour: {integration.ExpireBehaviour}",
$"Expire Grace Period: {integration.ExpireGracePeriod}",
$"User: {integration.User.Id}",
$"Account: {integration.Account.Id}, {integration.Account.Name}",
$"Last Sync: {integration.LastSync}"*/
}
private void ShardManager_OnGuildMembersChunk(GatewayShard shard, GuildMembersChunk membersChunk)
{
for (int i = 0; i < membersChunk.Members.Length; i++)
{
GuildMember member = membersChunk.Members[i];
member.GuildId = membersChunk.Guild;
ShardManager_OnGuildMemberAdd(shard, member);
}
}
private void ShardManager_OnMessageCreate(GatewayShard shard, Message message)
{
DiscordChannel channel = ChannelManager.Id(message.ChannelId);
Debug.Assert(channel != null, "channel is null");
DiscordMember member = MemberManager.Id(channel.Server, message.User.Id);
Debug.Assert(member != null, "member is null");
DiscordMessage msg = new DiscordMessage(this, message, channel, member);
MessageManager.Add(msg);
OnMessageCreate?.Invoke(msg);
}
private void ShardManager_OnMessageDelete(GatewayShard shard, Message message)
{
DiscordMessage msg = MessageManager.Id(message.Id);
Debug.Assert(msg != null, "message is null");
MessageManager.Remove(msg);
OnMessageDelete?.Invoke(msg);
}
private void ShardManager_OnMessageUpdate(GatewayShard shard, Message message)
{
DiscordMessage msg = MessageManager.Id(message.Id);
//Debug.Assert(msg != null, "message is null");
// basically what should happen
if (msg == null)
{
using (WebRequest wr = new WebRequest(HttpMethod.GET, RestEndpoints.ChannelMessage(message.ChannelId, message.Id)))
{
wr.Perform();
if (wr.Status != 200 || wr.ResponseString.Length < 1)
throw new DiscordException("Failed to load message from API");
message = wr.ResponseJson<Message>();
}
DiscordChannel channel = ChannelManager.Id(message.ChannelId);
Debug.Assert(channel != null, "channel is null");
DiscordMember member = MemberManager.Id(channel.Server, message.User.Id) ?? MemberManager.Id(message.User.Id);
Debug.Assert(member != null, "member is null");
msg = new DiscordMessage(this, message, channel, member);
MessageManager.Add(msg);
} else
{
if (!string.IsNullOrEmpty(message.Content))
msg.Text = message.Content;
msg.IsPinned = message.IsPinned == true;
}
msg.Edited = DateTime.Now;
OnMessageUpdate?.Invoke(msg);
}
private void ShardManager_OnTypingStart(GatewayShard shard, TypingStart typing)
{
DiscordChannel channel = ChannelManager.Id(typing.Channel);
Debug.Assert(channel != null, "channel is null");
DiscordUser user = UserManager.Id(typing.User);
Debug.Assert(user != null, "user is null");
OnTypingStart?.Invoke(user, channel);
}
private void ShardManager_OnPresenceUpdate(GatewayShard shard, Presence presence)
{
DiscordMember member = MemberManager.Id(presence.Guild, presence.User.Id);
Debug.Assert(member != null, "member is null");
if (!string.IsNullOrEmpty(presence.User.Username))
member.User.Username = presence.User.Username;
if (presence.User.Tag.HasValue)
member.User.Tag = presence.User.Tag.Value;
if (!string.IsNullOrEmpty(presence.User.AvatarHash))
member.User.avatarHash = presence.User.AvatarHash;
member.User.Game = presence.Game.HasValue ? new DiscordGame(presence.Game.Value) : null;
if (presence.Roles != null)
member.roles = new List<ulong>(presence.Roles);
switch (presence.Status.ToLower())
{
case "online":
member.User.Status = DiscordUserStatus.Online;
break;
case "away":
case "idle":
member.User.Status = DiscordUserStatus.Idle;
break;
case "dnd":
member.User.Status = DiscordUserStatus.DoNotDisturb;
break;
case "offline":
default:
member.User.Status = DiscordUserStatus.Offline;
break;
}
OnPresenceUpdate?.Invoke(member);
}
private void ShardManager_OnReady(GatewayShard shard, GatewayReady ready)
{
foreach (Channel chan in ready.PrivateChannels)
{
DiscordChannel channel = new DiscordChannel(this, chan);
// this shouldn't ever happen but just in case
if (ChannelManager.Exists(channel.Id))
continue;
ChannelManager.Add(channel);
}
foreach (Guild guild in ready.UnavailableGuilds)
{
DiscordServer server = new DiscordServer(this, guild);
if (ServerManager.Exists(server.Id))
continue;
ServerManager.Add(server);
}
DiscordUser user = new DiscordUser(this, ready.User);
UserManager.Add(user);
OnReady?.Invoke(user);
}
private void ShardManager_OnResumed(GatewayShard shard)
{
OnReady?.Invoke(Me);
}
private void ShardManager_OnUserUpdate(GatewayShard shard, User sUser)
{
/*$"Id: {user.Id}",
$"Guild Id: {user.GuildId}",
$"Username: {user.Username}",
$"Tag: {user.Tag:0000}",
$"Avatar Hash: {user.AvatarHash}",
$"Is bot?: {user.IsBot}",
$"Has MFA?: {user.HasMFA}",
$"Is verified?: {user.IsVerified}",
$"E-mail: {user.EMail}"*/
DiscordUser user = UserManager.Id(sUser.Id);
//Debug.Assert(user != null, "user is null");
if (user == null)
{
user = new DiscordUser(this, sUser);
UserManager.Add(user);
}
OnUserUpdate?.Invoke(user);
}
private void ShardManager_OnSocketError(GatewayShard shard, Exception ex)
{
}
#endregion
#region IDisposable
private bool IsDisposed = false;
/// <summary>
/// Disconnects and releases all unmanaged objects
/// </summary>
private void Dispose(bool disposing)
{
if (IsDisposed)
return;
IsDisposed = true;
Disconnect();
ServerManager.Dispose();
MessageManager.Dispose();
ChannelManager.Dispose();
MemberManager.Dispose();
RoleManager.Dispose();
UserManager.Dispose();
if (disposing)
GC.SuppressFinalize(this);
}
~Discord()
=> Dispose(false);
public void Dispose()
=> Dispose(true);
#endregion
}
}