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

3
.gitignore vendored
View File

@ -31,4 +31,5 @@ src/NadekoBot/project.lock.json
NadekoBot.sln.iml
.idea/workspace.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", ".")]
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;
}
@ -614,7 +614,7 @@ namespace NadekoBot.Modules.Administration
{
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);
}

View File

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

View File

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

View File

@ -12,9 +12,9 @@ namespace NadekoBot.Modules.Administration
[Group]
class SelfCommands
{
private DiscordSocketClient _client;
private ShardedDiscordClient _client;
public SelfCommands(DiscordSocketClient client)
public SelfCommands(ShardedDiscordClient 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 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())
{

View File

@ -10,11 +10,11 @@ namespace NadekoBot.Modules
{
protected ILocalization _l { get; }
protected CommandService _commands { get; }
protected DiscordSocketClient _client { get; }
protected ShardedDiscordClient _client { get; }
protected Logger _log { get; }
private string _prefix { get; }
public DiscordModule(ILocalization loc, CommandService cmds, DiscordSocketClient client)
public DiscordModule(ILocalization loc, CommandService cmds, ShardedDiscordClient client)
{
string 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 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())
{

View File

@ -111,7 +111,7 @@ namespace NadekoBot.Modules.Games.Trivia
{
if (!(umsg.Channel is IGuildChannel && umsg.Channel is ITextChannel)) 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;

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) ||
(pick == 1 && nadekoPick == 2) ||
(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
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);
}
}
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]
[RequireContext(ContextType.Guild)]
[OwnerOnly]
public async Task Hgit(IUserMessage umsg)
public Task Hgit(IUserMessage umsg)
{
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 = helpstr.Replace((await NadekoBot.Client.GetCurrentUserAsync()).Username , "@BotName");
helpstr = helpstr.Replace(NadekoBot.Client.GetCurrentUser().Username , "@BotName");
#if DEBUG
File.WriteAllText("../../../../../docs/Commands List.md", helpstr.ToString());
#else
File.WriteAllText("commandlist.md", helpstr.ToString());
#endif
return Task.CompletedTask;
}
[LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias]

View File

@ -25,7 +25,7 @@ namespace NadekoBot.Modules.Music
public const string MusicDataPath = "data/musicdata";
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
try { Directory.Delete(MusicDataPath, true); } catch { }
@ -520,16 +520,33 @@ namespace NadekoBot.Modules.Music
await channel.SendMessageAsync($"🎵🔁`Repeat playlist {(currentValue ? "enabled" : "disabled")}`").ConfigureAwait(false);
}
///
//[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
//[LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias]
//[RequireContext(ContextType.Guild)]
//public async Task Save(IUserMessage umsg, [Remainder] string name)
//{
// 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);
// }
// await channel.SendMessageAsync($"Playlist saved as {name}, id: {playlist.Id}.");
//}
//[LocalizedCommand, LocalizedDescription, LocalizedSummary, LocalizedAlias]
//[LocalizedCommand, LocalizedRemarks, LocalizedSummary, LocalizedAlias]
//[RequireContext(ContextType.Guild)]
//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)]
//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)]
//public async Task DeletePlaylist(IUserMessage umsg, [Remainder] string pl)
//{

View File

@ -18,7 +18,7 @@ namespace NadekoBot.Modules.NSFW
[NadekoModule("NSFW", "~")]
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", ";")]
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)]
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; }
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;
}

View File

@ -12,7 +12,7 @@ namespace NadekoBot.Modules.Translator
[NadekoModule("Translator", "~")]
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", ".")]
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 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 BotCredentials Credentials { get; private set; }
@ -43,7 +43,7 @@ namespace NadekoBot
_log.Info("Starting NadekoBot v" + typeof(NadekoBot).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion);
//create client
Client = new DiscordSocketClient(new DiscordSocketConfig
Client = new ShardedDiscordClient (new DiscordSocketConfig
{
AudioMode = Discord.Audio.AudioMode.Outgoing,
MessageCacheSize = 10,
@ -61,7 +61,7 @@ namespace NadekoBot
//setup DI
var depMap = new DependencyMap();
depMap.Add<ILocalization>(Localizer);
depMap.Add<DiscordSocketClient>(Client);
depMap.Add<ShardedDiscordClient >(Client);
depMap.Add<CommandService>(CommandService);
depMap.Add<IGoogleApiService>(Google);

View File

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

View File

@ -13,7 +13,7 @@ namespace NadekoBot.Services.Impl
public class StatsService : IStatsService
{
private int messageCounter;
private DiscordSocketClient client;
private ShardedDiscordClient client;
private DateTime started;
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 StatsService(DiscordSocketClient client, CommandHandler cmdHandler)
public StatsService(ShardedDiscordClient client, CommandHandler cmdHandler)
{
this.client = client;
@ -33,14 +33,18 @@ namespace NadekoBot.Services.Impl
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 id: {(client.GetCurrentUser()).Id}`
`Bot id: {curUser.Id}`
`Owners' Ids: {string.Join(", ", NadekoBot.Credentials.OwnerIds)}`
`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()}`
`Commands Ran this session: {commandsRan}`
`Messages: {messageCounter} ({messageCounter / (double)GetUptime().TotalSeconds:F2}/sec)` `Heap: {Heap} MB`");
}
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()));
}
}