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/Gateway/GatewayShardClient.cs

381 lines
14 KiB
C#
Raw Permalink Normal View History

2017-05-14 12:02:51 +00:00
using Maki.Structures.Channels;
using Maki.Structures.Gateway;
using Maki.Structures.Guilds;
using Maki.Structures.Messages;
using Maki.Structures.Presences;
using Maki.Structures.Users;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Maki.Gateway
{
/// <summary>
/// Gateway connection shard manager
/// </summary>
class GatewayShardClient : IDisposable
{
/// <summary>
/// Managed (active) shards
/// </summary>
2017-10-13 20:05:50 +00:00
private readonly List<GatewayShard> Shards = new List<GatewayShard>();
private readonly object Lock = new object();
2017-05-14 12:02:51 +00:00
/// <summary>
/// Parent DiscordClient instance
/// </summary>
2017-10-13 20:05:50 +00:00
private Discord Client;
2017-05-14 12:02:51 +00:00
/// <summary>
/// Number of active managed shards
/// </summary>
2017-10-13 20:05:50 +00:00
public int ShardCount
=> Shards.Count;
2017-05-14 12:02:51 +00:00
/// <summary>
/// Constructor
/// </summary>
2017-10-13 20:05:50 +00:00
/// <param name="client">Parent DiscordClient instance</param>
public GatewayShardClient(Discord client)
=> Client = client;
2017-05-14 12:02:51 +00:00
/// <summary>
/// Creates a new Gateway Shard
/// </summary>
/// <param name="id">Id of the shard</param>
/// <returns>New Gateway Shard</returns>
public GatewayShard Create(int id)
{
2017-10-13 20:05:50 +00:00
GatewayShard shard = new GatewayShard(id, Client);
2017-11-13 11:39:27 +00:00
shard.OnSocketPayload += Shard_OnSocketPayload;
2017-10-13 20:05:50 +00:00
lock (Lock)
Shards.Add(shard);
2017-05-14 12:02:51 +00:00
return shard;
}
2017-11-13 11:39:27 +00:00
private void Shard_OnSocketPayload(GatewayShard shard, GatewayPayload payload)
{
switch (payload.OPCode)
{
case GatewayOPCode.Dispatch:
switch (payload.Name)
{
#region Call
case "CALL_CREATE":
OnCallCreate?.Invoke(shard);
break;
case "CALL_DELETE":
OnCallDelete?.Invoke(shard);
break;
case "CALL_UPDATE":
OnCallUpdate?.Invoke(shard);
break;
case "VOICE_SERVER_UPDATE":
OnVoiceServerUpdate?.Invoke(shard);
break;
case "VOICE_STATE_UPDATE":
OnVoiceStateUpdate?.Invoke(shard);
break;
#endregion
#region Channel
case "CHANNEL_CREATE":
OnChannelCreate?.Invoke(shard, payload.DataAs<Channel>());
break;
case "CHANNEL_DELETE":
OnChannelDelete?.Invoke(shard, payload.DataAs<Channel>());
break;
case "CHANNEL_PINS_ACK":
OnChannelPinsAck?.Invoke(shard);
break;
case "CHANNEL_PINS_UPDATE":
OnChannelPinsUpdate?.Invoke(shard);
break;
case "CHANNEL_RECIPIENT_ADD":
OnChannelRecipientAdd?.Invoke(shard);
break;
case "CHANNEL_RECIPIENT_REMOVE":
OnChannelRecipientRemove?.Invoke(shard);
break;
case "CHANNEL_UPDATE":
OnChannelUpdate?.Invoke(shard, payload.DataAs<Channel>());
break;
#endregion
#region Guild
case "GUILD_BAN_ADD":
OnGuildBanAdd?.Invoke(shard, payload.DataAs<User>());
break;
case "GUILD_BAN_REMOVE":
OnGuildBanRemove?.Invoke(shard, payload.DataAs<User>());
break;
case "GUILD_CREATE":
OnGuildCreate?.Invoke(shard, payload.DataAs<Guild>());
break;
case "GUILD_DELETE":
OnGuildDelete?.Invoke(shard, payload.DataAs<Guild>());
break;
case "GUILD_EMOJIS_UPDATE":
OnGuildEmojisUpdate?.Invoke(shard, payload.DataAs<Guild>());
break;
case "GUILD_INTEGRATIONS_UPDATE":
OnGuildIntegrationsUpdate?.Invoke(shard, payload.DataAs<GuildIntegration>());
break;
case "GUILD_MEMBER_ADD":
OnGuildMemberAdd?.Invoke(shard, payload.DataAs<GuildMember>());
break;
case "GUILD_MEMBER_UPDATE":
OnGuildMemberUpdate?.Invoke(shard, payload.DataAs<GuildMember>());
break;
case "GUILD_MEMBER_REMOVE":
OnGuildMemberRemove?.Invoke(shard, payload.DataAs<GuildMember>());
break;
case "GUILD_MEMBERS_CHUNK":
OnGuildMembersChunk?.Invoke(shard, payload.DataAs<GuildMembersChunk>());
break;
case "GUILD_ROLE_CREATE":
OnGuildRoleCreate?.Invoke(shard, payload.DataAs<GuildRole>());
break;
case "GUILD_ROLE_UPDATE":
OnGuildRoleUpdate?.Invoke(shard, payload.DataAs<GuildRole>());
break;
case "GUILD_ROLE_DELETE":
OnGuildRoleDelete?.Invoke(shard, payload.DataAs<GuildRole>());
break;
case "GUILD_UPDATE":
OnGuildUpdate?.Invoke(shard, payload.DataAs<Guild>());
break;
#endregion
#region Message
case "MESSAGE_ACK":
OnMessageAck?.Invoke(shard);
break;
case "MESSAGE_CREATE":
OnMessageCreate?.Invoke(shard, payload.DataAs<Message>());
break;
case "MESSAGE_DELETE":
OnMessageDelete?.Invoke(shard, payload.DataAs<Message>());
break;
case "MESSAGE_DELETE_BULK":
OnMessageDeleteBulk?.Invoke(shard);
break;
case "MESSAGE_REACTION_ADD":
OnMessageReactionAdd?.Invoke(shard);
break;
case "MESSAGE_REACTION_REMOVE":
OnMessageReactionRemove?.Invoke(shard);
break;
case "MESSAGE_REACTIONS_REMOVE_ALL":
OnMessageReactionsRemoveAll?.Invoke(shard);
break;
case "MESSAGE_UPDATE":
OnMessageUpdate?.Invoke(shard, payload.DataAs<Message>());
break;
#endregion
#region Presence
case "TYPING_START":
OnTypingStart?.Invoke(shard, payload.DataAs<TypingStart>());
break;
case "PRESENCE_UPDATE":
OnPresenceUpdate?.Invoke(shard, payload.DataAs<Presence>());
break;
case "PRESENCES_REPLACE":
OnPresencesReplace?.Invoke(shard);
break;
#endregion
#region Relations
case "FRIEND_SUGGESTION_DELETE":
OnFriendSuggestionDelete?.Invoke(shard);
break;
case "RELATIONSHIP_ADD":
OnRelationshipAdd?.Invoke(shard);
break;
case "RELATIONSHIP_REMOVE":
OnRelationshipRemove?.Invoke(shard);
break;
#endregion
#region State
case "READY":
OnReady?.Invoke(shard, payload.DataAs<GatewayReady>());
break;
case "RESUMED":
OnResumed?.Invoke(shard);
break;
#endregion
#region User
case "USER_UPDATE":
OnUserUpdate?.Invoke(shard, payload.DataAs<User>());
break;
case "USER_NOTE_UPDATE":
OnUserNoteUpdate?.Invoke(shard);
break;
case "USER_SETTINGS_UPDATE":
OnUserSettingsUpdate?.Invoke(shard);
break;
#endregion
#if DEBUG
default:
Console.WriteLine($"Unknown payload type: {payload.Name}");
break;
#endif
}
break;
}
}
2017-05-14 12:02:51 +00:00
/// <summary>
/// Destroys a Gateway Shard
/// </summary>
/// <param name="shard">Shard to destroy</param>
public void Destroy(GatewayShard shard)
{
2017-10-13 20:05:50 +00:00
lock (Lock)
Shards.Remove(shard);
2017-05-14 12:02:51 +00:00
// Disconnect and Dispose are called separately so OnSocketClose is called properly
shard.Disconnect();
2017-11-13 11:39:27 +00:00
shard.OnSocketPayload -= Shard_OnSocketPayload;
2017-05-14 12:02:51 +00:00
shard.Dispose();
}
/// <summary>
/// Destroys all shards
/// </summary>
2017-10-13 20:05:50 +00:00
public void Disconnect()
{
lock (Lock)
Shards.ToList().ForEach(x => Destroy(x));
}
2017-05-14 12:02:51 +00:00
#region Events
2017-11-13 11:39:27 +00:00
2017-05-14 12:02:51 +00:00
public event Action<GatewayShard> OnCallCreate;
public event Action<GatewayShard> OnCallDelete;
public event Action<GatewayShard> OnCallUpdate;
public event Action<GatewayShard> OnVoiceServerUpdate;
public event Action<GatewayShard> OnVoiceStateUpdate;
public event Action<GatewayShard, Channel> OnChannelCreate;
public event Action<GatewayShard, Channel> OnChannelDelete;
public event Action<GatewayShard> OnChannelPinsAck;
public event Action<GatewayShard> OnChannelPinsUpdate;
public event Action<GatewayShard> OnChannelRecipientAdd;
public event Action<GatewayShard> OnChannelRecipientRemove;
public event Action<GatewayShard, Channel> OnChannelUpdate;
public event Action<GatewayShard, User> OnGuildBanAdd;
public event Action<GatewayShard, User> OnGuildBanRemove;
public event Action<GatewayShard, Guild> OnGuildCreate;
public event Action<GatewayShard, Guild> OnGuildDelete;
public event Action<GatewayShard, Guild> OnGuildEmojisUpdate;
public event Action<GatewayShard, GuildIntegration> OnGuildIntegrationsUpdate;
public event Action<GatewayShard, GuildMember> OnGuildMemberAdd;
public event Action<GatewayShard, GuildMember> OnGuildMemberUpdate;
public event Action<GatewayShard, GuildMember> OnGuildMemberRemove;
public event Action<GatewayShard, GuildMembersChunk> OnGuildMembersChunk;
public event Action<GatewayShard, GuildRole> OnGuildRoleCreate;
public event Action<GatewayShard, GuildRole> OnGuildRoleUpdate;
public event Action<GatewayShard, GuildRole> OnGuildRoleDelete;
public event Action<GatewayShard, Guild> OnGuildUpdate;
public event Action<GatewayShard> OnMessageAck;
public event Action<GatewayShard, Message> OnMessageCreate;
public event Action<GatewayShard, Message> OnMessageDelete;
public event Action<GatewayShard> OnMessageDeleteBulk;
public event Action<GatewayShard> OnMessageReactionAdd;
public event Action<GatewayShard> OnMessageReactionRemove;
public event Action<GatewayShard> OnMessageReactionsRemoveAll;
public event Action<GatewayShard, Message> OnMessageUpdate;
public event Action<GatewayShard, TypingStart> OnTypingStart;
public event Action<GatewayShard, Presence> OnPresenceUpdate;
public event Action<GatewayShard> OnPresencesReplace;
public event Action<GatewayShard> OnFriendSuggestionDelete;
public event Action<GatewayShard> OnRelationshipAdd;
public event Action<GatewayShard> OnRelationshipRemove;
public event Action<GatewayShard, GatewayReady> OnReady;
public event Action<GatewayShard> OnResumed;
public event Action<GatewayShard, User> OnUserUpdate;
public event Action<GatewayShard> OnUserNoteUpdate;
public event Action<GatewayShard> OnUserSettingsUpdate;
#endregion
#region IDisposable
private bool IsDisposed = false;
2017-10-13 20:05:50 +00:00
/// <summary>
/// Releases all unmanaged resources used by this object
/// </summary>
2017-05-14 12:02:51 +00:00
private void Dispose(bool disposing)
{
2017-10-13 20:05:50 +00:00
if (IsDisposed)
return;
IsDisposed = true;
Disconnect();
if (disposing)
GC.SuppressFinalize(this);
2017-05-14 12:02:51 +00:00
}
~GatewayShardClient()
2017-10-13 20:05:50 +00:00
=> Dispose(false);
2017-05-14 12:02:51 +00:00
public void Dispose()
2017-10-13 20:05:50 +00:00
=> Dispose(true);
2017-05-14 12:02:51 +00:00
#endregion
}
}