ShardedDiscordClient Implemented. I'm not feeling well

This commit is contained in:
Kwoth 2016-09-30 05:58:44 +02:00
parent 46a6bddb55
commit 0d918d39c9
22 changed files with 145 additions and 39 deletions

1
.gitignore vendored
View File

@ -32,3 +32,4 @@ NadekoBot.sln.iml
.idea/workspace.xml .idea/workspace.xml
.idea/vcs.xml .idea/vcs.xml
.idea/modules.xml .idea/modules.xml
src/tests/bin

View File

@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Administration
[NadekoModule("Administration", ".")] [NadekoModule("Administration", ".")]
public partial class Administration : DiscordModule public partial class Administration : DiscordModule
{ {
public Administration(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client) public Administration(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{ {
NadekoBot.CommandHandler.CommandExecuted += DelMsgOnCmd_Handler; NadekoBot.CommandHandler.CommandExecuted += DelMsgOnCmd_Handler;
} }
@ -614,7 +614,7 @@ namespace NadekoBot.Modules.Administration
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)umsg.Channel;
foreach (var ch in (await _client.GetGuildsAsync().ConfigureAwait(false)).Select(async g => await g.GetDefaultChannelAsync().ConfigureAwait(false))) foreach (var ch in _client.GetGuilds().Select(async g => await g.GetDefaultChannelAsync().ConfigureAwait(false)))
{ {
await channel.SendMessageAsync(message).ConfigureAwait(false); await channel.SendMessageAsync(message).ConfigureAwait(false);
} }

View File

@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Administration
[Group] [Group]
public class LogCommands public class LogCommands
{ {
private DiscordSocketClient _client { get; } private ShardedDiscordClient _client { get; }
private Logger _log { get; } private Logger _log { get; }
private string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】"; private string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】";
@ -33,7 +33,7 @@ namespace NadekoBot.Modules.Administration
private Timer t; private Timer t;
private IGoogleApiService _google { get; } private IGoogleApiService _google { get; }
public LogCommands(DiscordSocketClient client, IGoogleApiService google) public LogCommands(ShardedDiscordClient client, IGoogleApiService google)
{ {
_client = client; _client = client;
_google = google; _google = google;

View File

@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Administration
{ {
public static ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>(); public static ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>();
private DiscordSocketClient _client { get; } private ShardedDiscordClient _client { get; }
public class Ratelimiter public class Ratelimiter
{ {

View File

@ -12,9 +12,9 @@ namespace NadekoBot.Modules.Administration
[Group] [Group]
class SelfCommands class SelfCommands
{ {
private DiscordSocketClient _client; private ShardedDiscordClient _client;
public SelfCommands(DiscordSocketClient client) public SelfCommands(ShardedDiscordClient client)
{ {
this._client = client; this._client = client;
} }

View File

@ -19,7 +19,7 @@ namespace NadekoBot.Modules.ClashOfClans
{ {
public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; } = new ConcurrentDictionary<ulong, List<ClashWar>>(); public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; } = new ConcurrentDictionary<ulong, List<ClashWar>>();
public ClashOfClans(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client) public ClashOfClans(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {

View File

@ -10,11 +10,11 @@ namespace NadekoBot.Modules
{ {
protected ILocalization _l { get; } protected ILocalization _l { get; }
protected CommandService _commands { get; } protected CommandService _commands { get; }
protected DiscordSocketClient _client { get; } protected ShardedDiscordClient _client { get; }
protected Logger _log { get; } protected Logger _log { get; }
private string _prefix { get; } private string _prefix { get; }
public DiscordModule(ILocalization loc, CommandService cmds, DiscordSocketClient client) public DiscordModule(ILocalization loc, CommandService cmds, ShardedDiscordClient client)
{ {
string prefix; string prefix;
if (NadekoBot.ModulePrefixes.TryGetValue(this.GetType().Name, out prefix)) if (NadekoBot.ModulePrefixes.TryGetValue(this.GetType().Name, out prefix))

View File

@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Gambling
public static string CurrencyPluralName { get; set; } public static string CurrencyPluralName { get; set; }
public static string CurrencySign { get; set; } public static string CurrencySign { get; set; }
public Gambling(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client) public Gambling(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {

View File

@ -111,7 +111,7 @@ namespace NadekoBot.Modules.Games.Trivia
{ {
if (!(umsg.Channel is IGuildChannel && umsg.Channel is ITextChannel)) return; if (!(umsg.Channel is IGuildChannel && umsg.Channel is ITextChannel)) return;
if ((umsg.Channel as ITextChannel).Guild != guild) return; if ((umsg.Channel as ITextChannel).Guild != guild) return;
if (umsg.Author.Id == (await NadekoBot.Client.GetCurrentUserAsync()).Id) return; if (umsg.Author.Id == NadekoBot.Client.GetCurrentUser().Id) return;
var guildUser = umsg.Author as IGuildUser; var guildUser = umsg.Author as IGuildUser;

View File

@ -23,7 +23,7 @@ namespace NadekoBot.Modules.Games
} }
} }
} }
public Games(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client) public Games(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{ {
} }
@ -97,7 +97,7 @@ namespace NadekoBot.Modules.Games
else if ((pick == 0 && nadekoPick == 1) || else if ((pick == 0 && nadekoPick == 1) ||
(pick == 1 && nadekoPick == 2) || (pick == 1 && nadekoPick == 2) ||
(pick == 2 && nadekoPick == 0)) (pick == 2 && nadekoPick == 0))
msg = $"{(await NadekoBot.Client.GetCurrentUserAsync()).Mention} won! :{GetRPSPick(nadekoPick)}: beats :{GetRPSPick(pick)}:"; msg = $"{NadekoBot.Client.GetCurrentUser().Mention} won! :{GetRPSPick(nadekoPick)}: beats :{GetRPSPick(pick)}:";
else else
msg = $"{umsg.Author.Mention} won! :{GetRPSPick(pick)}: beats :{GetRPSPick(nadekoPick)}:"; msg = $"{umsg.Author.Mention} won! :{GetRPSPick(pick)}: beats :{GetRPSPick(nadekoPick)}:";

View File

@ -23,7 +23,7 @@ namespace NadekoBot.Modules.Help
return str + String.Format(str, NadekoBot.Credentials.ClientId); return str + String.Format(str, NadekoBot.Credentials.ClientId);
} }
} }
public Help(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client) public Help(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{ {
} }
@ -99,7 +99,7 @@ namespace NadekoBot.Modules.Help
[LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias] [LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task Hgit(IUserMessage umsg) public Task Hgit(IUserMessage umsg)
{ {
var helpstr = new StringBuilder(); var helpstr = new StringBuilder();
@ -115,12 +115,13 @@ namespace NadekoBot.Modules.Help
} }
helpstr.AppendLine($"`{com.Text}` {string.Join(" ", com.Aliases.Skip(1).Select(a=>"`"+a+"`"))} | {com.Remarks} | {com.Summary}"); helpstr.AppendLine($"`{com.Text}` {string.Join(" ", com.Aliases.Skip(1).Select(a=>"`"+a+"`"))} | {com.Remarks} | {com.Summary}");
} }
helpstr = helpstr.Replace((await NadekoBot.Client.GetCurrentUserAsync()).Username , "@BotName"); helpstr = helpstr.Replace(NadekoBot.Client.GetCurrentUser().Username , "@BotName");
#if DEBUG #if DEBUG
File.WriteAllText("../../../../../docs/Commands List.md", helpstr.ToString()); File.WriteAllText("../../../../../docs/Commands List.md", helpstr.ToString());
#else #else
File.WriteAllText("commandlist.md", helpstr.ToString()); File.WriteAllText("commandlist.md", helpstr.ToString());
#endif #endif
return Task.CompletedTask;
} }
[LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias] [LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias]

View File

@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Music
public const string MusicDataPath = "data/musicdata"; public const string MusicDataPath = "data/musicdata";
private IGoogleApiService _google; private IGoogleApiService _google;
public Music(ILocalization loc, CommandService cmds, DiscordSocketClient client, IGoogleApiService google) : base(loc, cmds, client) public Music(ILocalization loc, CommandService cmds, ShardedDiscordClient client, IGoogleApiService google) : base(loc, cmds, client)
{ {
//it can fail if its currenctly opened or doesn't exist. Either way i don't care //it can fail if its currenctly opened or doesn't exist. Either way i don't care
try { Directory.Delete(MusicDataPath, true); } catch { } try { Directory.Delete(MusicDataPath, true); } catch { }
@ -520,16 +520,33 @@ namespace NadekoBot.Modules.Music
await channel.SendMessageAsync($"🎵🔁`Repeat playlist {(currentValue ? "enabled" : "disabled")}`").ConfigureAwait(false); await channel.SendMessageAsync($"🎵🔁`Repeat playlist {(currentValue ? "enabled" : "disabled")}`").ConfigureAwait(false);
} }
/// //[LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias]
//[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
//[RequireContext(ContextType.Guild)] //[RequireContext(ContextType.Guild)]
//public async Task Save(IUserMessage umsg, [Remainder] string name) //public async Task Save(IUserMessage umsg, [Remainder] string name)
//{ //{
// var channel = (ITextChannel)umsg.Channel; // var channel = (ITextChannel)umsg.Channel;
// MusicPlayer musicPlayer;
// if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
// return;
// var curSong = musicPlayer.CurrentSong;
// var items = musicPlayer.Playlist.Append(curSong);
// MusicPlaylist playlist;
// using (var uow = DbHandler.UnitOfWork())
// {
// playlist = new MusicPlaylist
// {
// Name = name,
// Songs = items.ToList()
// };
// uow.MusicPlaylists.Add(playlist);
// } // }
//[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] // await channel.SendMessageAsync($"Playlist saved as {name}, id: {playlist.Id}.");
//}
//[LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias]
//[RequireContext(ContextType.Guild)] //[RequireContext(ContextType.Guild)]
//public async Task Load(IUserMessage umsg, [Remainder] string name) //public async Task Load(IUserMessage umsg, [Remainder] string name)
//{ //{
@ -537,7 +554,7 @@ namespace NadekoBot.Modules.Music
//} //}
//[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] //[LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias]
//[RequireContext(ContextType.Guild)] //[RequireContext(ContextType.Guild)]
//public async Task Playlists(IUserMessage umsg, [Remainder] string num) //public async Task Playlists(IUserMessage umsg, [Remainder] string num)
//{ //{
@ -545,7 +562,7 @@ namespace NadekoBot.Modules.Music
//} //}
//[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias] //[LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias]
//[RequireContext(ContextType.Guild)] //[RequireContext(ContextType.Guild)]
//public async Task DeletePlaylist(IUserMessage umsg, [Remainder] string pl) //public async Task DeletePlaylist(IUserMessage umsg, [Remainder] string pl)
//{ //{

View File

@ -18,7 +18,7 @@ namespace NadekoBot.Modules.NSFW
[NadekoModule("NSFW", "~")] [NadekoModule("NSFW", "~")]
public class NSFW : DiscordModule public class NSFW : DiscordModule
{ {
public NSFW(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client) public NSFW(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{ {
} }

View File

@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Permissions
[NadekoModule("Permissions", ";")] [NadekoModule("Permissions", ";")]
public class Permissions : DiscordModule public class Permissions : DiscordModule
{ {
public Permissions(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client) public Permissions(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{ {
} }

View File

@ -10,7 +10,7 @@ namespace NadekoBot.Modules.Games
[Module(">", AppendSpace = false)] [Module(">", AppendSpace = false)]
public partial class Pokemon : DiscordModule public partial class Pokemon : DiscordModule
{ {
public Pokemon(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client) public Pokemon(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{ {
} }

View File

@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Searches
{ {
private IGoogleApiService _google { get; } private IGoogleApiService _google { get; }
public Searches(ILocalization loc, CommandService cmds, DiscordSocketClient client, IGoogleApiService youtube) : base(loc, cmds, client) public Searches(ILocalization loc, CommandService cmds, ShardedDiscordClient client, IGoogleApiService youtube) : base(loc, cmds, client)
{ {
_google = youtube; _google = youtube;
} }

View File

@ -12,7 +12,7 @@ namespace NadekoBot.Modules.Translator
[NadekoModule("Translator", "~")] [NadekoModule("Translator", "~")]
public class Translator : DiscordModule public class Translator : DiscordModule
{ {
public Translator(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client) public Translator(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{ {
} }

View File

@ -18,7 +18,7 @@ namespace NadekoBot.Modules.Utility
[NadekoModule("Utility", ".")] [NadekoModule("Utility", ".")]
public partial class Utility : DiscordModule public partial class Utility : DiscordModule
{ {
public Utility(ILocalization loc, CommandService cmds, DiscordSocketClient client) : base(loc, cmds, client) public Utility(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client)
{ {
} }

View File

@ -26,7 +26,7 @@ namespace NadekoBot
public static CommandService CommandService { get; private set; } public static CommandService CommandService { get; private set; }
public static CommandHandler CommandHandler { get; private set; } public static CommandHandler CommandHandler { get; private set; }
public static DiscordSocketClient Client { get; private set; } public static ShardedDiscordClient Client { get; private set; }
public static Localization Localizer { get; private set; } public static Localization Localizer { get; private set; }
public static BotCredentials Credentials { get; private set; } public static BotCredentials Credentials { get; private set; }
@ -43,7 +43,7 @@ namespace NadekoBot
_log.Info("Starting NadekoBot v" + typeof(NadekoBot).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion); _log.Info("Starting NadekoBot v" + typeof(NadekoBot).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion);
//create client //create client
Client = new DiscordSocketClient(new DiscordSocketConfig Client = new ShardedDiscordClient (new DiscordSocketConfig
{ {
AudioMode = Discord.Audio.AudioMode.Outgoing, AudioMode = Discord.Audio.AudioMode.Outgoing,
MessageCacheSize = 10, MessageCacheSize = 10,
@ -61,7 +61,7 @@ namespace NadekoBot
//setup DI //setup DI
var depMap = new DependencyMap(); var depMap = new DependencyMap();
depMap.Add<ILocalization>(Localizer); depMap.Add<ILocalization>(Localizer);
depMap.Add<DiscordSocketClient>(Client); depMap.Add<ShardedDiscordClient >(Client);
depMap.Add<CommandService>(CommandService); depMap.Add<CommandService>(CommandService);
depMap.Add<IGoogleApiService>(Google); depMap.Add<IGoogleApiService>(Google);

View File

@ -18,13 +18,13 @@ namespace NadekoBot.Services
{ {
public class CommandHandler public class CommandHandler
{ {
private DiscordSocketClient _client; private ShardedDiscordClient _client;
private CommandService _commandService; private CommandService _commandService;
private Logger _log; private Logger _log;
public event EventHandler<CommandExecutedEventArgs> CommandExecuted = delegate { }; public event EventHandler<CommandExecutedEventArgs> CommandExecuted = delegate { };
public CommandHandler(DiscordSocketClient client, CommandService commandService) public CommandHandler(ShardedDiscordClient client, CommandService commandService)
{ {
_client = client; _client = client;
_commandService = commandService; _commandService = commandService;

View File

@ -13,7 +13,7 @@ namespace NadekoBot.Services.Impl
public class StatsService : IStatsService public class StatsService : IStatsService
{ {
private int messageCounter; private int messageCounter;
private DiscordSocketClient client; private ShardedDiscordClient client;
private DateTime started; private DateTime started;
private int commandsRan = 0; private int commandsRan = 0;
@ -22,7 +22,7 @@ namespace NadekoBot.Services.Impl
public string Heap => Math.Round((double)GC.GetTotalMemory(false) / 1.MiB(), 2).ToString(); public string Heap => Math.Round((double)GC.GetTotalMemory(false) / 1.MiB(), 2).ToString();
public StatsService(DiscordSocketClient client, CommandHandler cmdHandler) public StatsService(ShardedDiscordClient client, CommandHandler cmdHandler)
{ {
this.client = client; this.client = client;
@ -33,14 +33,18 @@ namespace NadekoBot.Services.Impl
this.client.Disconnected += _ => Reset(); this.client.Disconnected += _ => Reset();
} }
public Task<string> Print() => Task.FromResult($@"`Author: Kwoth` `Library: Discord.Net` public Task<string> Print()
{
var curUser = client.GetCurrentUser();
return Task.FromResult($@"`Author: Kwoth` `Library: Discord.Net`
`Bot Version: {BotVersion}` `Bot Version: {BotVersion}`
`Bot id: {(client.GetCurrentUser()).Id}` `Bot id: {curUser.Id}`
`Owners' Ids: {string.Join(", ", NadekoBot.Credentials.OwnerIds)}` `Owners' Ids: {string.Join(", ", NadekoBot.Credentials.OwnerIds)}`
`Uptime: {GetUptimeString()}` `Uptime: {GetUptimeString()}`
`Servers: {client.GetGuilds().Count} | TextChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is ITextChannel)).Count()} | VoiceChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is IVoiceChannel)).Count()}` `Servers: {client.GetGuilds().Count} | TextChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is ITextChannel)).Count()} | VoiceChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is IVoiceChannel)).Count()}`
`Commands Ran this session: {commandsRan}` `Commands Ran this session: {commandsRan}`
`Messages: {messageCounter} ({messageCounter / (double)GetUptime().TotalSeconds:F2}/sec)` `Heap: {Heap} MB`"); `Messages: {messageCounter} ({messageCounter / (double)GetUptime().TotalSeconds:F2}/sec)` `Heap: {Heap} MB`");
}
public Task Reset() public Task Reset()
{ {

View File

@ -0,0 +1,83 @@
using Discord;
using Discord.WebSocket;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.API;
using Discord.Logging;
using System.IO;
namespace NadekoBot
{
public class ShardedDiscordClient
{
private DiscordSocketConfig discordSocketConfig;
public Func<IGuildUser, Task> UserJoined { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<IMessage, Task> MessageReceived { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<IGuildUser, Task> UserLeft { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<IGuildUser, IGuildUser, Task> UserUpdated { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<Optional<IMessage>, IMessage, Task> MessageUpdated { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<ulong, Optional<IMessage>, Task> MessageDeleted { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<IUser, IGuild, Task> UserBanned { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<IUser, IGuild, Task> UserUnbanned { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<IGuildUser, IPresence, IPresence, Task> UserPresenceUpdated { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<IUser, IVoiceState, IVoiceState, Task> UserVoiceStateUpdated { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<IChannel, Task> ChannelCreated { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<IChannel, Task> ChannelDestroyed { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<IChannel, IChannel, Task> ChannelUpdated { get; internal set; } = delegate { return Task.CompletedTask; };
public Func<Exception, Task> Disconnected { get; internal set; } = delegate { return Task.CompletedTask; };
private IReadOnlyList<DiscordSocketClient> Clients { get; }
public ShardedDiscordClient (DiscordSocketConfig discordSocketConfig)
{
this.discordSocketConfig = discordSocketConfig;
var clientList = new List<DiscordSocketClient>();
for (int i = 0; i < discordSocketConfig.TotalShards; i++)
{
discordSocketConfig.ShardId = i;
var client = new DiscordSocketClient(discordSocketConfig);
clientList.Add(client);
client.UserJoined += async arg1 => await UserJoined(arg1);
client.MessageReceived += async arg1 => await MessageReceived(arg1);
client.UserLeft += async arg1 => await UserLeft(arg1);
client.UserUpdated += async (arg1, gu2) => await UserUpdated(arg1, gu2);
client.MessageUpdated += async (arg1, m2) => await MessageUpdated(arg1, m2);
client.MessageDeleted += async (arg1, arg2) => await MessageDeleted(arg1, arg2);
client.UserBanned += async (arg1, arg2) => await UserBanned(arg1, arg2);
client.UserPresenceUpdated += async (arg1, arg2, arg3) => await UserPresenceUpdated(arg1, arg2, arg3);
client.UserVoiceStateUpdated += async (arg1, arg2, arg3) => await UserVoiceStateUpdated(arg1, arg2, arg3);
client.ChannelCreated += async arg => await ChannelCreated(arg);
client.ChannelDestroyed += async arg => await ChannelDestroyed(arg);
client.ChannelUpdated += async (arg1, arg2) => await ChannelUpdated(arg1, arg2);
}
Clients = clientList.AsReadOnly();
}
public ISelfUser GetCurrentUser() =>
Clients.Select(c => c.GetCurrentUser()).FirstOrDefault(u => u != null);
public IReadOnlyCollection<IGuild> GetGuilds() =>
Clients.SelectMany(c => c.GetGuilds()).ToArray();
public IGuild GetGuild(ulong id) =>
Clients.Select(c => c.GetGuild(id)).FirstOrDefault(g => g != null);
public Task<IDMChannel> GetDMChannelAsync(ulong channelId) =>
Clients.Select(async c => await c.GetDMChannelAsync(channelId).ConfigureAwait(false)).FirstOrDefault(c => c != null);
internal Task LoginAsync(TokenType tokenType, string token) =>
Task.WhenAll(Clients.Select(c => c.LoginAsync(tokenType, token)));
internal Task ConnectAsync() =>
Task.WhenAll(Clients.Select(c => c.ConnectAsync()));
internal Task DownloadAllUsersAsync() =>
Task.WhenAll(Clients.Select(c => c.DownloadAllUsersAsync()));
}
}