diff --git a/.gitignore b/.gitignore
index 0fa1ef5e..5169035d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
#Manually added files
+patreon_rewards.json
command_errors*.txt
src/NadekoBot/Command Errors*.txt
diff --git a/NadekoBot.sln b/NadekoBot.sln
index a80335e2..8c235940 100644
--- a/NadekoBot.sln
+++ b/NadekoBot.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.26430.6
+VisualStudioVersion = 15.0.26430.12
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}"
EndProject
diff --git a/docs/JSON Explanations.md b/docs/JSON Explanations.md
index 2ac629e8..341cf992 100644
--- a/docs/JSON Explanations.md
+++ b/docs/JSON Explanations.md
@@ -18,7 +18,8 @@ If you do not see `credentials.json` you will need to rename `credentials_exampl
"OsuApiKey": "4c8c8fdff8e1234581725db27fd140a7d93320d6",
"PatreonAccessToken": "",
"Db": null,
- "TotalShards": 1
+ "TotalShards": 1,
+ "ShardRunCommand": ""
}
```
-----
@@ -155,14 +156,28 @@ It should look like:
- **TotalShards**
- Required if the bot will be connected to more than 1500 servers.
- Most likely unnecessary to change until your bot is added to more than 1500 servers.
-
+- **ShardRunCommand**
+ - Command with which to run shards 1+
+ - Required if you're sharding your bot on windows using .exe, or in a custom way.
+ - This internally defaults to `dotnet`
+ - For example, if you want to shard your NadekoBot which you installed using windows installer, you would want to set it to something like this: `C:\Program Files\NadekoBot\system\NadekoBot.exe`
+- **ShardRunArguments**
+ - Arguments to the shard run command
+ - Required if you're sharding your bot on windows using .exe, or in a custom way.
+ - This internally defaults to `run -c Release -- {0} {1} {2}` which will be enough to run linux and other 'from source' setups
+ - {0} will be replaced by the `shard ID` of the shard being ran, {1} by the shard 0's process id, and {2} by the port shard communication is happening on
+ - If shard0 (main window) is closed, all other shards will close too
+ - For example, if you want to shard your NadekoBot which you installed using windows installer, you would want to set it to `{0} {1} {2}`
+- **ShardRunPort**
+ - Bot uses a random UDP port in [5000, 6000) range for communication between shards
-----
## DB files
Nadeko saves all the settings and infomations in `NadekoBot.db` file here:
`NadekoBot/src/NadekoBot/bin/Release/netcoreapp1.1/data/NadekoBot.db` (macOS and Linux)
-`NadekoBot\system\data` (Windows)
+`NadekoBot\system\data` (Windows)
+
in order to open the database file you will need [DB Browser for SQLite](http://sqlitebrowser.org/).
*NOTE: You don't have to worry if you don't have `NadekoBot.db` file, it gets auto created once you run the bot successfully.*
diff --git a/src/NadekoBot/DataStructures/ModuleBehaviors/IEarlyBlockingExecutor.cs b/src/NadekoBot/DataStructures/ModuleBehaviors/IEarlyBlockingExecutor.cs
index f28eaf4f..a3e004b1 100644
--- a/src/NadekoBot/DataStructures/ModuleBehaviors/IEarlyBlockingExecutor.cs
+++ b/src/NadekoBot/DataStructures/ModuleBehaviors/IEarlyBlockingExecutor.cs
@@ -13,6 +13,6 @@ namespace NadekoBot.DataStructures.ModuleBehaviors
/// Try to execute some logic within some module's service.
///
/// Whether it should block other command executions after it.
- Task TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage msg);
+ Task TryExecuteEarly(DiscordSocketClient client, IGuild guild, IUserMessage msg);
}
}
diff --git a/src/NadekoBot/DataStructures/ModuleBehaviors/ILateBlocker.cs b/src/NadekoBot/DataStructures/ModuleBehaviors/ILateBlocker.cs
index 3b3fc020..68f33206 100644
--- a/src/NadekoBot/DataStructures/ModuleBehaviors/ILateBlocker.cs
+++ b/src/NadekoBot/DataStructures/ModuleBehaviors/ILateBlocker.cs
@@ -6,7 +6,7 @@ namespace NadekoBot.DataStructures.ModuleBehaviors
{
public interface ILateBlocker
{
- Task TryBlockLate(DiscordShardedClient client, IUserMessage msg, IGuild guild,
+ Task TryBlockLate(DiscordSocketClient client, IUserMessage msg, IGuild guild,
IMessageChannel channel, IUser user, string moduleName, string commandName);
}
}
diff --git a/src/NadekoBot/DataStructures/ModuleBehaviors/ILateExecutor.cs b/src/NadekoBot/DataStructures/ModuleBehaviors/ILateExecutor.cs
index 3cf11603..a7b3e52e 100644
--- a/src/NadekoBot/DataStructures/ModuleBehaviors/ILateExecutor.cs
+++ b/src/NadekoBot/DataStructures/ModuleBehaviors/ILateExecutor.cs
@@ -9,6 +9,6 @@ namespace NadekoBot.DataStructures.ModuleBehaviors
///
public interface ILateExecutor
{
- Task LateExecute(DiscordShardedClient client, IGuild guild, IUserMessage msg);
+ Task LateExecute(DiscordSocketClient client, IGuild guild, IUserMessage msg);
}
}
diff --git a/src/NadekoBot/DataStructures/Shard0Precondition.cs b/src/NadekoBot/DataStructures/Shard0Precondition.cs
new file mode 100644
index 00000000..eaa5c591
--- /dev/null
+++ b/src/NadekoBot/DataStructures/Shard0Precondition.cs
@@ -0,0 +1,22 @@
+using Discord.Commands;
+using Discord.WebSocket;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NadekoBot.DataStructures
+{
+ public class Shard0Precondition : PreconditionAttribute
+ {
+ public override Task CheckPermissions(ICommandContext context, CommandInfo command, IServiceProvider services)
+ {
+ var c = (DiscordSocketClient)context.Client;
+ if (c.ShardId == 0)
+ return Task.FromResult(PreconditionResult.FromSuccess());
+ else
+ return Task.FromResult(PreconditionResult.FromError("Must be ran from shard #0"));
+ }
+ }
+}
diff --git a/src/NadekoBot/DataStructures/ShardCom/IShardComMessage.cs b/src/NadekoBot/DataStructures/ShardCom/IShardComMessage.cs
new file mode 100644
index 00000000..9fb1f5d0
--- /dev/null
+++ b/src/NadekoBot/DataStructures/ShardCom/IShardComMessage.cs
@@ -0,0 +1,16 @@
+using Discord;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NadekoBot.DataStructures.ShardCom
+{
+ public class ShardComMessage
+ {
+ public int ShardId { get; set; }
+ public ConnectionState ConnectionState { get; set; }
+ public int Guilds { get; set; }
+ }
+}
diff --git a/src/NadekoBot/DataStructures/ShardCom/ShardComClient.cs b/src/NadekoBot/DataStructures/ShardCom/ShardComClient.cs
new file mode 100644
index 00000000..67e1c9f6
--- /dev/null
+++ b/src/NadekoBot/DataStructures/ShardCom/ShardComClient.cs
@@ -0,0 +1,29 @@
+using Newtonsoft.Json;
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NadekoBot.DataStructures.ShardCom
+{
+ public class ShardComClient
+ {
+ private int port;
+
+ public ShardComClient(int port)
+ {
+ this.port = port;
+ }
+
+ public async Task Send(ShardComMessage data)
+ {
+ var msg = JsonConvert.SerializeObject(data);
+ using (var client = new UdpClient())
+ {
+ var bytes = Encoding.UTF8.GetBytes(msg);
+ await client.SendAsync(bytes, bytes.Length, IPAddress.Loopback.ToString(), port).ConfigureAwait(false);
+ }
+ }
+ }
+}
diff --git a/src/NadekoBot/DataStructures/ShardCom/ShardComServer.cs b/src/NadekoBot/DataStructures/ShardCom/ShardComServer.cs
new file mode 100644
index 00000000..d0e1cbf6
--- /dev/null
+++ b/src/NadekoBot/DataStructures/ShardCom/ShardComServer.cs
@@ -0,0 +1,40 @@
+using Newtonsoft.Json;
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NadekoBot.DataStructures.ShardCom
+{
+ public class ShardComServer : IDisposable
+ {
+ private readonly UdpClient _client;
+
+ public ShardComServer(int port)
+ {
+ _client = new UdpClient(port);
+ }
+
+ public void Start()
+ {
+ Task.Run(async () =>
+ {
+ var ip = new IPEndPoint(IPAddress.Any, 0);
+ while (true)
+ {
+ var recv = await _client.ReceiveAsync();
+ var data = Encoding.UTF8.GetString(recv.Buffer);
+ var _ = OnDataReceived(JsonConvert.DeserializeObject(data));
+ }
+ });
+ }
+
+ public void Dispose()
+ {
+ _client.Dispose();
+ }
+
+ public event Func OnDataReceived = delegate { return Task.CompletedTask; };
+ }
+}
diff --git a/src/NadekoBot/DataStructures/TypeReaders/GuildTypeReader.cs b/src/NadekoBot/DataStructures/TypeReaders/GuildTypeReader.cs
index 63971f5a..3bb72d4c 100644
--- a/src/NadekoBot/DataStructures/TypeReaders/GuildTypeReader.cs
+++ b/src/NadekoBot/DataStructures/TypeReaders/GuildTypeReader.cs
@@ -7,9 +7,9 @@ namespace NadekoBot.TypeReaders
{
public class GuildTypeReader : TypeReader
{
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
- public GuildTypeReader(DiscordShardedClient client)
+ public GuildTypeReader(DiscordSocketClient client)
{
_client = client;
}
diff --git a/src/NadekoBot/Modules/Administration/Administration.cs b/src/NadekoBot/Modules/Administration/Administration.cs
index 15185ca3..56a0affc 100644
--- a/src/NadekoBot/Modules/Administration/Administration.cs
+++ b/src/NadekoBot/Modules/Administration/Administration.cs
@@ -126,17 +126,17 @@ namespace NadekoBot.Modules.Administration
{
var guser = (IGuildUser)Context.User;
- var userRoles = user.GetRoles();
- if (guser.Id != Context.Guild.OwnerId &&
- (user.Id == Context.Guild.OwnerId || guser.GetRoles().Max(x => x.Position) <= userRoles.Max(x => x.Position)))
+ var userRoles = user.GetRoles().Except(new[] { guser.Guild.EveryoneRole });
+ if (user.Id == Context.Guild.OwnerId || (Context.User.Id != Context.Guild.OwnerId && guser.GetRoles().Max(x => x.Position) <= userRoles.Max(x => x.Position)))
return;
try
{
await user.RemoveRolesAsync(userRoles).ConfigureAwait(false);
await ReplyConfirmLocalized("rar", Format.Bold(user.ToString())).ConfigureAwait(false);
}
- catch
+ catch (Exception ex)
{
+ Console.WriteLine(ex);
await ReplyErrorLocalized("rar_err").ConfigureAwait(false);
}
}
diff --git a/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs b/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs
index 9815fa1b..3ad63210 100644
--- a/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs
+++ b/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs
@@ -140,7 +140,7 @@ namespace NadekoBot.Modules.Administration
await uow.CompleteAsync();
}
- await Context.Channel.SendPaginatedConfirmAsync((DiscordShardedClient)Context.Client, page, (curPage) =>
+ await Context.Channel.SendPaginatedConfirmAsync((DiscordSocketClient)Context.Client, page, (curPage) =>
{
return new EmbedBuilder()
.WithTitle(GetText("self_assign_list", roleCnt))
diff --git a/src/NadekoBot/Modules/Administration/Commands/SelfCommands.cs b/src/NadekoBot/Modules/Administration/Commands/SelfCommands.cs
index aa99eeab..449398b4 100644
--- a/src/NadekoBot/Modules/Administration/Commands/SelfCommands.cs
+++ b/src/NadekoBot/Modules/Administration/Commands/SelfCommands.cs
@@ -13,6 +13,8 @@ using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Services.Administration;
+using System.Diagnostics;
+using NadekoBot.DataStructures;
namespace NadekoBot.Modules.Administration
{
@@ -25,10 +27,10 @@ namespace NadekoBot.Modules.Administration
private static readonly object _locker = new object();
private readonly SelfService _service;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly IImagesService _images;
- public SelfCommands(DbService db, SelfService service, DiscordShardedClient client,
+ public SelfCommands(DbService db, SelfService service, DiscordSocketClient client,
IImagesService images)
{
_db = db;
@@ -204,28 +206,28 @@ namespace NadekoBot.Modules.Administration
}
- [NadekoCommand, Usage, Description, Aliases]
- [OwnerOnly]
- public async Task ConnectShard(int shardid)
- {
- var shard = _client.GetShard(shardid);
-
- if (shard == null)
- {
- await ReplyErrorLocalized("no_shard_id").ConfigureAwait(false);
- return;
- }
- try
- {
- await ReplyConfirmLocalized("shard_reconnecting", Format.Bold("#" + shardid)).ConfigureAwait(false);
- await shard.StartAsync().ConfigureAwait(false);
- await ReplyConfirmLocalized("shard_reconnected", Format.Bold("#" + shardid)).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _log.Warn(ex);
- }
- }
+ //todo 2 shard commands
+ //[NadekoCommand, Usage, Description, Aliases]
+ //[Shard0Precondition]
+ //[OwnerOnly]
+ //public async Task RestartShard(int shardid)
+ //{
+ // if (shardid == 0 || shardid > b)
+ // {
+ // await ReplyErrorLocalized("no_shard_id").ConfigureAwait(false);
+ // return;
+ // }
+ // try
+ // {
+ // await ReplyConfirmLocalized("shard_reconnecting", Format.Bold("#" + shardid)).ConfigureAwait(false);
+ // await shard.StartAsync().ConfigureAwait(false);
+ // await ReplyConfirmLocalized("shard_reconnected", Format.Bold("#" + shardid)).ConfigureAwait(false);
+ // }
+ // catch (Exception ex)
+ // {
+ // _log.Warn(ex);
+ // }
+ //}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
@@ -417,8 +419,10 @@ namespace NadekoBot.Modules.Administration
[OwnerOnly]
public async Task ReloadImages()
{
- var time = _images.Reload();
- await ReplyConfirmLocalized("images_loaded", time.TotalSeconds.ToString("F3")).ConfigureAwait(false);
+ var sw = Stopwatch.StartNew();
+ _images.Reload();
+ sw.Stop();
+ await ReplyConfirmLocalized("images_loaded", sw.Elapsed.TotalSeconds.ToString("F3")).ConfigureAwait(false);
}
private static UserStatus SettableUserStatusToUserStatus(SettableUserStatus sus)
diff --git a/src/NadekoBot/Modules/Administration/Commands/TimeZoneCommands.cs b/src/NadekoBot/Modules/Administration/Commands/TimeZoneCommands.cs
index e054288c..c97fdbca 100644
--- a/src/NadekoBot/Modules/Administration/Commands/TimeZoneCommands.cs
+++ b/src/NadekoBot/Modules/Administration/Commands/TimeZoneCommands.cs
@@ -36,7 +36,7 @@ namespace NadekoBot.Modules.Administration
.ToArray();
var timezonesPerPage = 20;
- await Context.Channel.SendPaginatedConfirmAsync((DiscordShardedClient)Context.Client, page,
+ await Context.Channel.SendPaginatedConfirmAsync((DiscordSocketClient)Context.Client, page,
(curPage) => new EmbedBuilder()
.WithOkColor()
.WithTitle(GetText("timezones_available"))
diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs
index 5dac3b9c..ae033cad 100644
--- a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs
+++ b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs
@@ -17,10 +17,10 @@ namespace NadekoBot.Modules.CustomReactions
private readonly IBotCredentials _creds;
private readonly DbService _db;
private readonly CustomReactionsService _crs;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
public CustomReactions(IBotCredentials creds, DbService db, CustomReactionsService crs,
- DiscordShardedClient client)
+ DiscordSocketClient client)
{
_creds = creds;
_db = db;
diff --git a/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs b/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs
index 4db985e5..46cd25b3 100644
--- a/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs
+++ b/src/NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs
@@ -22,12 +22,12 @@ namespace NadekoBot.Modules.Gambling
{
private readonly BotConfig _bc;
private readonly CurrencyService _cs;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
public static ConcurrentDictionary AnimalRaces { get; } = new ConcurrentDictionary();
- public AnimalRacing(BotConfig bc, CurrencyService cs, DiscordShardedClient client)
+ public AnimalRacing(BotConfig bc, CurrencyService cs, DiscordSocketClient client)
{
_bc = bc;
_cs = cs;
@@ -82,14 +82,14 @@ namespace NadekoBot.Modules.Gambling
private readonly ITextChannel _raceChannel;
private readonly BotConfig _bc;
private readonly CurrencyService _cs;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly ILocalization _localization;
private readonly NadekoStrings _strings;
public bool Started { get; private set; }
public AnimalRace(ulong serverId, ITextChannel channel, string prefix, BotConfig bc,
- CurrencyService cs, DiscordShardedClient client, ILocalization localization,
+ CurrencyService cs, DiscordSocketClient client, ILocalization localization,
NadekoStrings strings)
{
_prefix = prefix;
diff --git a/src/NadekoBot/Modules/Gambling/Commands/CurrencyEvents.cs b/src/NadekoBot/Modules/Gambling/Commands/CurrencyEvents.cs
index 76369c15..644823bc 100644
--- a/src/NadekoBot/Modules/Gambling/Commands/CurrencyEvents.cs
+++ b/src/NadekoBot/Modules/Gambling/Commands/CurrencyEvents.cs
@@ -34,11 +34,11 @@ namespace NadekoBot.Modules.Gambling
.ToArray();
private string _secretCode = string.Empty;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly BotConfig _bc;
private readonly CurrencyService _cs;
- public CurrencyEvents(DiscordShardedClient client, BotConfig bc, CurrencyService cs)
+ public CurrencyEvents(DiscordSocketClient client, BotConfig bc, CurrencyService cs)
{
_client = client;
_bc = bc;
@@ -151,7 +151,7 @@ namespace NadekoBot.Modules.Gambling
{
private readonly ConcurrentHashSet _flowerReactionAwardedUsers = new ConcurrentHashSet();
private readonly Logger _log;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly CurrencyService _cs;
private IUserMessage StartingMessage { get; set; }
@@ -159,7 +159,7 @@ namespace NadekoBot.Modules.Gambling
private CancellationTokenSource Source { get; }
private CancellationToken CancelToken { get; }
- public FlowerReactionEvent(DiscordShardedClient client, CurrencyService cs)
+ public FlowerReactionEvent(DiscordSocketClient client, CurrencyService cs)
{
_log = LogManager.GetCurrentClassLogger();
_client = client;
diff --git a/src/NadekoBot/Modules/Gambling/Commands/FlowerShop.cs b/src/NadekoBot/Modules/Gambling/Commands/FlowerShop.cs
index dfc8d648..dd4fd309 100644
--- a/src/NadekoBot/Modules/Gambling/Commands/FlowerShop.cs
+++ b/src/NadekoBot/Modules/Gambling/Commands/FlowerShop.cs
@@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Gambling
private readonly BotConfig _bc;
private readonly DbService _db;
private readonly CurrencyService _cs;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
public enum Role
{
@@ -34,7 +34,7 @@ namespace NadekoBot.Modules.Gambling
List
}
- public FlowerShop(BotConfig bc, DbService db, CurrencyService cs, DiscordShardedClient client)
+ public FlowerShop(BotConfig bc, DbService db, CurrencyService cs, DiscordSocketClient client)
{
_db = db;
_bc = bc;
diff --git a/src/NadekoBot/Modules/Games/Commands/Acropobia.cs b/src/NadekoBot/Modules/Games/Commands/Acropobia.cs
index 0d8e337f..44b64808 100644
--- a/src/NadekoBot/Modules/Games/Commands/Acropobia.cs
+++ b/src/NadekoBot/Modules/Games/Commands/Acropobia.cs
@@ -20,12 +20,12 @@ namespace NadekoBot.Modules.Games
[Group]
public class Acropobia : NadekoSubmodule
{
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
//channelId, game
public static ConcurrentDictionary AcrophobiaGames { get; } = new ConcurrentDictionary();
- public Acropobia(DiscordShardedClient client)
+ public Acropobia(DiscordSocketClient client)
{
_client = client;
}
@@ -86,10 +86,10 @@ namespace NadekoBot.Modules.Games
//text, votes
private readonly ConcurrentDictionary _votes = new ConcurrentDictionary();
private readonly Logger _log;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly NadekoStrings _strings;
- public AcrophobiaGame(DiscordShardedClient client, NadekoStrings strings, ITextChannel channel, int time)
+ public AcrophobiaGame(DiscordSocketClient client, NadekoStrings strings, ITextChannel channel, int time)
{
_log = LogManager.GetCurrentClassLogger();
_client = client;
diff --git a/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs b/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs
index 24ca87c9..eddd00fc 100644
--- a/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs
+++ b/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs
@@ -56,7 +56,7 @@ namespace NadekoBot.Modules.Games.Hangman
public class HangmanGame: IDisposable
{
private readonly Logger _log;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
public IMessageChannel GameChannel { get; }
public HashSet Guesses { get; } = new HashSet();
@@ -82,7 +82,7 @@ namespace NadekoBot.Modules.Games.Hangman
public event Action OnEnded;
- public HangmanGame(DiscordShardedClient client, IMessageChannel channel, string type)
+ public HangmanGame(DiscordSocketClient client, IMessageChannel channel, string type)
{
_log = LogManager.GetCurrentClassLogger();
_client = client;
diff --git a/src/NadekoBot/Modules/Games/Commands/HangmanCommands.cs b/src/NadekoBot/Modules/Games/Commands/HangmanCommands.cs
index 633be81f..c515c0b8 100644
--- a/src/NadekoBot/Modules/Games/Commands/HangmanCommands.cs
+++ b/src/NadekoBot/Modules/Games/Commands/HangmanCommands.cs
@@ -15,9 +15,9 @@ namespace NadekoBot.Modules.Games
[Group]
public class HangmanCommands : NadekoSubmodule
{
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
- public HangmanCommands(DiscordShardedClient client)
+ public HangmanCommands(DiscordSocketClient client)
{
_client = client;
}
diff --git a/src/NadekoBot/Modules/Games/Commands/Models/TypingGame.cs b/src/NadekoBot/Modules/Games/Commands/Models/TypingGame.cs
index db670fd2..92b01eb3 100644
--- a/src/NadekoBot/Modules/Games/Commands/Models/TypingGame.cs
+++ b/src/NadekoBot/Modules/Games/Commands/Models/TypingGame.cs
@@ -20,13 +20,13 @@ namespace NadekoBot.Modules.Games.Models
public bool IsActive { get; private set; }
private readonly Stopwatch sw;
private readonly List finishedUserIds;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly GamesService _games;
private readonly string _prefix;
private Logger _log { get; }
- public TypingGame(GamesService games, DiscordShardedClient client, ITextChannel channel, string prefix) //kek@prefix
+ public TypingGame(GamesService games, DiscordSocketClient client, ITextChannel channel, string prefix) //kek@prefix
{
_log = LogManager.GetCurrentClassLogger();
_games = games;
diff --git a/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs b/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs
index 191fd30d..f055e0bb 100644
--- a/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs
+++ b/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs
@@ -116,7 +116,7 @@ namespace NadekoBot.Modules.Games
bool enabled;
using (var uow = _db.UnitOfWork)
{
- var guildConfig = uow.GuildConfigs.For(channel.Id, set => set.Include(gc => gc.GenerateCurrencyChannelIds));
+ var guildConfig = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.GenerateCurrencyChannelIds));
var toAdd = new GCChannelId() { ChannelId = channel.Id };
if (!guildConfig.GenerateCurrencyChannelIds.Contains(toAdd))
diff --git a/src/NadekoBot/Modules/Games/Commands/PollCommands.cs b/src/NadekoBot/Modules/Games/Commands/PollCommands.cs
index 487473f0..0d6b6cb2 100644
--- a/src/NadekoBot/Modules/Games/Commands/PollCommands.cs
+++ b/src/NadekoBot/Modules/Games/Commands/PollCommands.cs
@@ -13,10 +13,10 @@ namespace NadekoBot.Modules.Games
[Group]
public class PollCommands : NadekoSubmodule
{
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly PollService _polls;
- public PollCommands(DiscordShardedClient client, PollService polls)
+ public PollCommands(DiscordSocketClient client, PollService polls)
{
_client = client;
_polls = polls;
@@ -26,13 +26,7 @@ namespace NadekoBot.Modules.Games
[RequireUserPermission(GuildPermission.ManageMessages)]
[RequireContext(ContextType.Guild)]
public Task Poll([Remainder] string arg = null)
- => InternalStartPoll(arg, false);
-
- [NadekoCommand, Usage, Description, Aliases]
- [RequireUserPermission(GuildPermission.ManageMessages)]
- [RequireContext(ContextType.Guild)]
- public Task PublicPoll([Remainder] string arg = null)
- => InternalStartPoll(arg, true);
+ => InternalStartPoll(arg);
[NadekoCommand, Usage, Description, Aliases]
[RequireUserPermission(GuildPermission.ManageMessages)]
@@ -45,9 +39,9 @@ namespace NadekoBot.Modules.Games
await Context.Channel.EmbedAsync(poll.GetStats(GetText("current_poll_results")));
}
- private async Task InternalStartPoll(string arg, bool isPublic = false)
+ private async Task InternalStartPoll(string arg)
{
- if(await _polls.StartPoll((ITextChannel)Context.Channel, Context.Message, arg, isPublic) == false)
+ if(await _polls.StartPoll((ITextChannel)Context.Channel, Context.Message, arg) == false)
await ReplyErrorLocalized("poll_already_running").ConfigureAwait(false);
}
diff --git a/src/NadekoBot/Modules/Games/Commands/SpeedTypingCommands.cs b/src/NadekoBot/Modules/Games/Commands/SpeedTypingCommands.cs
index 72663094..6cce5191 100644
--- a/src/NadekoBot/Modules/Games/Commands/SpeedTypingCommands.cs
+++ b/src/NadekoBot/Modules/Games/Commands/SpeedTypingCommands.cs
@@ -20,9 +20,9 @@ namespace NadekoBot.Modules.Games
{
public static ConcurrentDictionary RunningContests = new ConcurrentDictionary();
private readonly GamesService _games;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
- public SpeedTypingCommands(DiscordShardedClient client, GamesService games)
+ public SpeedTypingCommands(DiscordSocketClient client, GamesService games)
{
_games = games;
_client = client;
diff --git a/src/NadekoBot/Modules/Games/Commands/TicTacToe.cs b/src/NadekoBot/Modules/Games/Commands/TicTacToe.cs
index 7de40565..6f626325 100644
--- a/src/NadekoBot/Modules/Games/Commands/TicTacToe.cs
+++ b/src/NadekoBot/Modules/Games/Commands/TicTacToe.cs
@@ -21,9 +21,9 @@ namespace NadekoBot.Modules.Games
private static readonly Dictionary _games = new Dictionary();
private readonly SemaphoreSlim _sem = new SemaphoreSlim(1, 1);
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
- public TicTacToeCommands(DiscordShardedClient client)
+ public TicTacToeCommands(DiscordSocketClient client)
{
_client = client;
}
@@ -87,9 +87,9 @@ namespace NadekoBot.Modules.Games
private IUserMessage _previousMessage;
private Timer _timeoutTimer;
private readonly NadekoStrings _strings;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
- public TicTacToe(NadekoStrings strings, DiscordShardedClient client, ITextChannel channel, IGuildUser firstUser)
+ public TicTacToe(NadekoStrings strings, DiscordSocketClient client, ITextChannel channel, IGuildUser firstUser)
{
_channel = channel;
_strings = strings;
diff --git a/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs b/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs
index ea6e1e2c..b1b7d477 100644
--- a/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs
+++ b/src/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs
@@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Games.Trivia
private readonly SemaphoreSlim _guessLock = new SemaphoreSlim(1, 1);
private readonly Logger _log;
private readonly NadekoStrings _strings;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly BotConfig _bc;
private readonly CurrencyService _cs;
@@ -43,7 +43,7 @@ namespace NadekoBot.Modules.Games.Trivia
public int WinRequirement { get; }
- public TriviaGame(NadekoStrings strings, DiscordShardedClient client, BotConfig bc,
+ public TriviaGame(NadekoStrings strings, DiscordSocketClient client, BotConfig bc,
CurrencyService cs, IGuild guild, ITextChannel channel,
bool showHints, int winReq, bool isPokemon)
{
diff --git a/src/NadekoBot/Modules/Games/Commands/TriviaCommands.cs b/src/NadekoBot/Modules/Games/Commands/TriviaCommands.cs
index d38e04dd..ac9cdcc3 100644
--- a/src/NadekoBot/Modules/Games/Commands/TriviaCommands.cs
+++ b/src/NadekoBot/Modules/Games/Commands/TriviaCommands.cs
@@ -18,12 +18,12 @@ namespace NadekoBot.Modules.Games
public class TriviaCommands : NadekoSubmodule
{
private readonly CurrencyService _cs;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly BotConfig _bc;
public static ConcurrentDictionary RunningTrivias { get; } = new ConcurrentDictionary();
- public TriviaCommands(DiscordShardedClient client, BotConfig bc, CurrencyService cs)
+ public TriviaCommands(DiscordSocketClient client, BotConfig bc, CurrencyService cs)
{
_cs = cs;
_client = client;
diff --git a/src/NadekoBot/Modules/Help/Help.cs b/src/NadekoBot/Modules/Help/Help.cs
index 18ddf039..37377713 100644
--- a/src/NadekoBot/Modules/Help/Help.cs
+++ b/src/NadekoBot/Modules/Help/Help.cs
@@ -155,8 +155,8 @@ namespace NadekoBot.Modules.Help
public async Task Guide()
{
await ConfirmLocalized("guide",
- "http://nadekobot.readthedocs.io/en/latest/Commands%20List/",
- "http://nadekobot.readthedocs.io/en/latest/").ConfigureAwait(false);
+ "http://nadekobot.readthedocs.io/en/1.3x/Commands%20List/",
+ "http://nadekobot.readthedocs.io/en/1.3x/").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
diff --git a/src/NadekoBot/Modules/Music/Music.cs b/src/NadekoBot/Modules/Music/Music.cs
index afd60bb2..ebec33c5 100644
--- a/src/NadekoBot/Modules/Music/Music.cs
+++ b/src/NadekoBot/Modules/Music/Music.cs
@@ -22,12 +22,12 @@ namespace NadekoBot.Modules.Music
public class Music : NadekoTopLevelModule
{
private static MusicService _music;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly IBotCredentials _creds;
private readonly IGoogleApiService _google;
private readonly DbService _db;
- public Music(DiscordShardedClient client, IBotCredentials creds, IGoogleApiService google,
+ public Music(DiscordSocketClient client, IBotCredentials creds, IGoogleApiService google,
DbService db, MusicService music)
{
_client = client;
diff --git a/src/NadekoBot/Modules/NadekoModule.cs b/src/NadekoBot/Modules/NadekoModule.cs
index dae471d4..45abaea9 100644
--- a/src/NadekoBot/Modules/NadekoModule.cs
+++ b/src/NadekoBot/Modules/NadekoModule.cs
@@ -86,13 +86,12 @@ namespace NadekoBot.Modules
var text = GetText(textKey, replacements);
return Context.Channel.SendConfirmAsync(Context.User.Mention + " " + text);
}
-
- // todo maybe make this generic and use
- // TypeConverter typeConverter = TypeDescriptor.GetConverter(propType);
+
+ // TypeConverter typeConverter = TypeDescriptor.GetConverter(propType); ?
public async Task GetUserInputAsync(ulong userId, ulong channelId)
{
var userInputTask = new TaskCompletionSource();
- var dsc = (DiscordShardedClient)Context.Client;
+ var dsc = (DiscordSocketClient)Context.Client;
try
{
dsc.MessageReceived += MessageReceived;
diff --git a/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs b/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs
index 371678ff..1329fc0b 100644
--- a/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs
+++ b/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs
@@ -195,7 +195,7 @@ namespace NadekoBot.Modules.Permissions
var fws = fwHash.ToArray();
- await channel.SendPaginatedConfirmAsync((DiscordShardedClient)Context.Client,
+ await channel.SendPaginatedConfirmAsync((DiscordSocketClient)Context.Client,
page,
(curPage) =>
new EmbedBuilder()
diff --git a/src/NadekoBot/Modules/Utility/Commands/CommandMapCommands.cs b/src/NadekoBot/Modules/Utility/Commands/CommandMapCommands.cs
index d38cfb90..03316135 100644
--- a/src/NadekoBot/Modules/Utility/Commands/CommandMapCommands.cs
+++ b/src/NadekoBot/Modules/Utility/Commands/CommandMapCommands.cs
@@ -21,9 +21,9 @@ namespace NadekoBot.Modules.Utility
{
private readonly CommandMapService _service;
private readonly DbService _db;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
- public CommandMapCommands(CommandMapService service, DbService db, DiscordShardedClient client)
+ public CommandMapCommands(CommandMapService service, DbService db, DiscordSocketClient client)
{
_service = service;
_db = db;
diff --git a/src/NadekoBot/Modules/Utility/Commands/CrossServerTextChannel.cs b/src/NadekoBot/Modules/Utility/Commands/CrossServerTextChannel.cs
deleted file mode 100644
index de917054..00000000
--- a/src/NadekoBot/Modules/Utility/Commands/CrossServerTextChannel.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-using Discord;
-using Discord.Commands;
-using NadekoBot.Attributes;
-using NadekoBot.Extensions;
-using NadekoBot.Services;
-using NadekoBot.Services.Utility;
-using System.Collections.Concurrent;
-using System.Threading.Tasks;
-
-namespace NadekoBot.Modules.Utility
-{
- public partial class Utility
- {
- [Group]
- public class CrossServerTextChannel : NadekoSubmodule
- {
- private readonly CrossServerTextService _service;
-
- public CrossServerTextChannel(CrossServerTextService service)
- {
- _service = service;
- }
-
- [NadekoCommand, Usage, Description, Aliases]
- [RequireContext(ContextType.Guild)]
- [OwnerOnly]
- public async Task Scsc()
- {
- var token = new NadekoRandom().Next();
- var set = new ConcurrentHashSet();
- if (_service.Subscribers.TryAdd(token, set))
- {
- set.Add((ITextChannel) Context.Channel);
- await ((IGuildUser) Context.User).SendConfirmAsync(GetText("csc_token"), token.ToString())
- .ConfigureAwait(false);
- }
- }
-
- [NadekoCommand, Usage, Description, Aliases]
- [RequireContext(ContextType.Guild)]
- [RequireUserPermission(GuildPermission.ManageGuild)]
- public async Task Jcsc(int token)
- {
- ConcurrentHashSet set;
- if (!_service.Subscribers.TryGetValue(token, out set))
- return;
- set.Add((ITextChannel) Context.Channel);
- await ReplyConfirmLocalized("csc_join").ConfigureAwait(false);
- }
-
- [NadekoCommand, Usage, Description, Aliases]
- [RequireContext(ContextType.Guild)]
- [RequireUserPermission(GuildPermission.ManageGuild)]
- public async Task Lcsc()
- {
- foreach (var subscriber in _service.Subscribers)
- {
- subscriber.Value.TryRemove((ITextChannel) Context.Channel);
- }
- await ReplyConfirmLocalized("csc_leave").ConfigureAwait(false);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/NadekoBot/Modules/Utility/Commands/InfoCommands.cs b/src/NadekoBot/Modules/Utility/Commands/InfoCommands.cs
index 3a5b8fe8..e3c625c4 100644
--- a/src/NadekoBot/Modules/Utility/Commands/InfoCommands.cs
+++ b/src/NadekoBot/Modules/Utility/Commands/InfoCommands.cs
@@ -16,10 +16,10 @@ namespace NadekoBot.Modules.Utility
[Group]
public class InfoCommands : NadekoSubmodule
{
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly IStatsService _stats;
- public InfoCommands(DiscordShardedClient client, IStatsService stats, CommandHandler ch)
+ public InfoCommands(DiscordSocketClient client, IStatsService stats, CommandHandler ch)
{
_client = client;
_stats = stats;
diff --git a/src/NadekoBot/Modules/Utility/Commands/PatreonCommands.cs b/src/NadekoBot/Modules/Utility/Commands/PatreonCommands.cs
index 509419fd..293e2c42 100644
--- a/src/NadekoBot/Modules/Utility/Commands/PatreonCommands.cs
+++ b/src/NadekoBot/Modules/Utility/Commands/PatreonCommands.cs
@@ -34,7 +34,9 @@ namespace NadekoBot.Modules.Utility
[OwnerOnly]
public async Task PatreonRewardsReload()
{
- await _patreon.LoadPledges().ConfigureAwait(false);
+ if (string.IsNullOrWhiteSpace(_creds.PatreonAccessToken))
+ return;
+ await _patreon.RefreshPledges(true).ConfigureAwait(false);
await Context.Channel.SendConfirmAsync("👌").ConfigureAwait(false);
}
@@ -44,6 +46,7 @@ namespace NadekoBot.Modules.Utility
{
if (string.IsNullOrWhiteSpace(_creds.PatreonAccessToken))
return;
+
if (DateTime.UtcNow.Day < 5)
{
await ReplyErrorLocalized("clpa_too_early").ConfigureAwait(false);
diff --git a/src/NadekoBot/Modules/Utility/Commands/Remind.cs b/src/NadekoBot/Modules/Utility/Commands/Remind.cs
index 448ec424..ce046467 100644
--- a/src/NadekoBot/Modules/Utility/Commands/Remind.cs
+++ b/src/NadekoBot/Modules/Utility/Commands/Remind.cs
@@ -33,7 +33,7 @@ namespace NadekoBot.Modules.Utility
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
- [Priority(1)]
+ [Priority(0)]
public async Task Remind(MeOrHere meorhere, string timeStr, [Remainder] string message)
{
ulong target;
@@ -44,7 +44,7 @@ namespace NadekoBot.Modules.Utility
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)]
- [Priority(0)]
+ [Priority(1)]
public async Task Remind(ITextChannel channel, string timeStr, [Remainder] string message)
{
var perms = ((IGuildUser)Context.User).GetPermissions((ITextChannel)channel);
diff --git a/src/NadekoBot/Modules/Utility/Commands/RepeatCommands.cs b/src/NadekoBot/Modules/Utility/Commands/RepeatCommands.cs
index 6561712d..89619c1c 100644
--- a/src/NadekoBot/Modules/Utility/Commands/RepeatCommands.cs
+++ b/src/NadekoBot/Modules/Utility/Commands/RepeatCommands.cs
@@ -22,10 +22,10 @@ namespace NadekoBot.Modules.Utility
public class RepeatCommands : NadekoSubmodule
{
private readonly MessageRepeaterService _service;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly DbService _db;
- public RepeatCommands(MessageRepeaterService service, DiscordShardedClient client, DbService db)
+ public RepeatCommands(MessageRepeaterService service, DiscordSocketClient client, DbService db)
{
_service = service;
_client = client;
diff --git a/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs b/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs
index 9b9c121c..1e7f5d22 100644
--- a/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs
+++ b/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs
@@ -6,7 +6,6 @@ using NadekoBot.Services.Utility;
using System;
using System.Linq;
using System.Threading.Tasks;
-
namespace NadekoBot.Modules.Utility
{
public partial class Utility
diff --git a/src/NadekoBot/Modules/Utility/Utility.cs b/src/NadekoBot/Modules/Utility/Utility.cs
index 4774a266..7a6f9ae1 100644
--- a/src/NadekoBot/Modules/Utility/Utility.cs
+++ b/src/NadekoBot/Modules/Utility/Utility.cs
@@ -18,99 +18,25 @@ using Discord.WebSocket;
using System.Diagnostics;
using Color = Discord.Color;
using NadekoBot.Services;
+using NadekoBot.DataStructures;
namespace NadekoBot.Modules.Utility
{
public partial class Utility : NadekoTopLevelModule
{
private static ConcurrentDictionary _rotatingRoleColors = new ConcurrentDictionary();
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly IStatsService _stats;
private readonly IBotCredentials _creds;
+ private readonly NadekoBot _bot;
- public Utility(DiscordShardedClient client, IStatsService stats, IBotCredentials creds)
+ public Utility(NadekoBot bot, DiscordSocketClient client, IStatsService stats, IBotCredentials creds)
{
_client = client;
_stats = stats;
_creds = creds;
- }
-
- //[NadekoCommand, Usage, Description, Aliases]
- //[RequireContext(ContextType.Guild)]
- //public async Task Midorina([Remainder] string arg)
- //{
- // var channel = (ITextChannel)Context.Channel;
-
- // var roleNames = arg?.Split(';');
-
- // if (roleNames == null || roleNames.Length == 0)
- // return;
-
- // var j = 0;
- // var roles = roleNames.Select(x => Context.Guild.Roles.FirstOrDefault(r => String.Compare(r.Name, x, StringComparison.OrdinalIgnoreCase) == 0))
- // .Where(x => x != null)
- // .Take(10)
- // .ToArray();
-
- // var rnd = new NadekoRandom();
- // var reactions = new[] { "🎬", "🐧", "🌍", "🌺", "🚀", "☀", "🌲", "🍒", "🐾", "🏀" }
- // .OrderBy(x => rnd.Next())
- // .ToArray();
-
- // var roleStrings = roles
- // .Select(x => $"{reactions[j++]} -> {x.Name}");
-
- // var msg = await Context.Channel.SendConfirmAsync("Pick a Role",
- // string.Join("\n", roleStrings)).ConfigureAwait(false);
-
- // for (int i = 0; i < roles.Length; i++)
- // {
- // try { await msg.AddReactionAsync(reactions[i]).ConfigureAwait(false); }
- // catch (Exception ex) { _log.Warn(ex); }
- // await Task.Delay(1000).ConfigureAwait(false);
- // }
-
- // msg.OnReaction((r) => Task.Run(async () =>
- // {
- // try
- // {
- // var usr = r.User.GetValueOrDefault() as IGuildUser;
-
- // if (usr == null)
- // return;
-
- // var index = Array.IndexOf(reactions, r.Emoji.Name);
- // if (index == -1)
- // return;
-
- // await usr.RemoveRolesAsync(roles[index]);
- // }
- // catch (Exception ex)
- // {
- // _log.Warn(ex);
- // }
- // }), (r) => Task.Run(async () =>
- // {
- // try
- // {
- // var usr = r.User.GetValueOrDefault() as IGuildUser;
-
- // if (usr == null)
- // return;
-
- // var index = Array.IndexOf(reactions, r.Emoji.Name);
- // if (index == -1)
- // return;
-
- // await usr.RemoveRolesAsync(roles[index]);
- // }
- // catch (Exception ex)
- // {
- // _log.Warn(ex);
- // }
- // }));
- //}
-
+ _bot = bot;
+ }
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
@@ -354,23 +280,25 @@ namespace NadekoBot.Modules.Utility
}
[NadekoCommand, Usage, Description, Aliases]
+ [Shard0Precondition]
public async Task ShardStats(int page = 1)
{
if (--page < 0)
return;
+ var statuses = _bot.ShardCoord.Statuses.ToArray()
+ .Where(x => x != null);
- var status = string.Join(", ", _client.Shards.GroupBy(x => x.ConnectionState)
+ var status = string.Join(", ", statuses
+ .GroupBy(x => x.ConnectionState)
.Select(x => $"{x.Count()} {x.Key}")
.ToArray());
- var allShardStrings = _client.Shards
+ var allShardStrings = statuses
.Select(x =>
GetText("shard_stats_txt", x.ShardId.ToString(),
- Format.Bold(x.ConnectionState.ToString()), Format.Bold(x.Guilds.Count.ToString())))
+ Format.Bold(x.ConnectionState.ToString()), Format.Bold(x.Guilds.ToString())))
.ToArray();
-
-
await Context.Channel.SendPaginatedConfirmAsync(_client, page, (curPage) =>
{
@@ -387,21 +315,9 @@ namespace NadekoBot.Modules.Utility
}, allShardStrings.Length / 25);
}
- [NadekoCommand, Usage, Description, Aliases]
- public async Task ShardId(IGuild guild)
- {
- var shardId = _client.GetShardIdFor(guild);
-
- await Context.Channel.SendConfirmAsync(shardId.ToString()).ConfigureAwait(false);
- }
-
[NadekoCommand, Usage, Description, Aliases]
public async Task Stats()
- {
- var shardId = Context.Guild != null
- ? _client.GetShardIdFor(Context.Guild)
- : 0;
-
+ {
await Context.Channel.EmbedAsync(
new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithName($"NadekoBot v{StatsService.BotVersion}")
@@ -409,7 +325,7 @@ namespace NadekoBot.Modules.Utility
.WithIconUrl("https://cdn.discordapp.com/avatars/116275390695079945/b21045e778ef21c96d175400e779f0fb.jpg"))
.AddField(efb => efb.WithName(GetText("author")).WithValue(_stats.Author).WithIsInline(true))
.AddField(efb => efb.WithName(GetText("botid")).WithValue(_client.CurrentUser.Id.ToString()).WithIsInline(true))
- .AddField(efb => efb.WithName(GetText("shard")).WithValue($"#{shardId} / {_client.Shards.Count}").WithIsInline(true))
+ .AddField(efb => efb.WithName(GetText("shard")).WithValue($"#{_bot.ShardId} / {_creds.TotalShards}").WithIsInline(true))
.AddField(efb => efb.WithName(GetText("commands_ran")).WithValue(_stats.CommandsRan.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName(GetText("messages")).WithValue($"{_stats.MessageCounter} ({_stats.MessagesPerSecond:F2}/sec)").WithIsInline(true))
.AddField(efb => efb.WithName(GetText("memory")).WithValue($"{_stats.Heap} MB").WithIsInline(true))
@@ -417,13 +333,7 @@ namespace NadekoBot.Modules.Utility
.AddField(efb => efb.WithName(GetText("uptime")).WithValue(_stats.GetUptimeString("\n")).WithIsInline(true))
.AddField(efb => efb.WithName(GetText("presence")).WithValue(
GetText("presence_txt",
- _client.Guilds.Count, _stats.TextChannels, _stats.VoiceChannels)).WithIsInline(true))
-#if !GLOBAL_NADEKO
- //.WithFooter(efb => efb.WithText(GetText("stats_songs",
- // _music.MusicPlayers.Count(mp => mp.Value.CurrentSong != null),
- // _music.MusicPlayers.Sum(mp => mp.Value.Playlist.Count))))
-#endif
- );
+ _stats.GuildCount, _stats.TextChannels, _stats.VoiceChannels)).WithIsInline(true)));
}
[NadekoCommand, Usage, Description, Aliases]
diff --git a/src/NadekoBot/NadekoBot.cs b/src/NadekoBot/NadekoBot.cs
index 136a49ce..04dd0e4b 100644
--- a/src/NadekoBot/NadekoBot.cs
+++ b/src/NadekoBot/NadekoBot.cs
@@ -4,8 +4,6 @@ using Discord.WebSocket;
using NadekoBot.Services;
using NadekoBot.Services.Impl;
using NLog;
-using NLog.Config;
-using NLog.Targets;
using System;
using System.Linq;
using System.Reflection;
@@ -27,8 +25,7 @@ using NadekoBot.Services.Utility;
using NadekoBot.Services.Help;
using System.IO;
using NadekoBot.Services.Pokemon;
-using NadekoBot.DataStructures;
-using NadekoBot.Extensions;
+using NadekoBot.DataStructures.ShardCom;
namespace NadekoBot
{
@@ -45,47 +42,63 @@ namespace NadekoBot
public static Color OkColor { get; private set; }
public static Color ErrorColor { get; private set; }
- public ImmutableArray AllGuildConfigs { get; }
+ public ImmutableArray AllGuildConfigs { get; private set; }
public BotConfig BotConfig { get; }
public DbService Db { get; }
public CommandService CommandService { get; }
public CommandHandler CommandHandler { get; private set; }
- public Localization Localization { get; }
- public NadekoStrings Strings { get; }
- public StatsService Stats { get; }
+ public Localization Localization { get; private set; }
+ public NadekoStrings Strings { get; private set; }
+ public StatsService Stats { get; private set; }
public ImagesService Images { get; }
public CurrencyService Currency { get; }
public GoogleApiService GoogleApi { get; }
- public DiscordShardedClient Client { get; }
+ public DiscordSocketClient Client { get; }
public bool Ready { get; private set; }
public INServiceProvider Services { get; private set; }
public BotCredentials Credentials { get; }
- public NadekoBot()
+ private const string _mutexName = @"Global\nadeko_shards_lock";
+ private readonly Semaphore sem = new Semaphore(1, 1, _mutexName);
+ public int ShardId { get; }
+ public ShardsCoordinator ShardCoord { get; private set; }
+
+ private readonly ShardComClient _comClient;
+
+ public NadekoBot(int shardId, int parentProcessId, int? port = null)
{
- SetupLogger();
+ if (shardId < 0)
+ throw new ArgumentOutOfRangeException(nameof(shardId));
+
+ ShardId = shardId;
+
+ LogSetup.SetupLogger();
_log = LogManager.GetCurrentClassLogger();
TerribleElevatedPermissionCheck();
-
+
Credentials = new BotCredentials();
+
+ port = port ?? Credentials.ShardRunPort;
+ _comClient = new ShardComClient(port.Value);
+
Db = new DbService(Credentials);
using (var uow = Db.UnitOfWork)
{
- AllGuildConfigs = uow.GuildConfigs.GetAllGuildConfigs().ToImmutableArray();
BotConfig = uow.BotConfig.GetOrCreate();
OkColor = new Color(Convert.ToUInt32(BotConfig.OkColor, 16));
ErrorColor = new Color(Convert.ToUInt32(BotConfig.ErrorColor, 16));
}
- Client = new DiscordShardedClient(new DiscordSocketConfig
+ Client = new DiscordSocketClient(new DiscordSocketConfig
{
MessageCacheSize = 10,
LogLevel = LogSeverity.Warning,
- TotalShards = Credentials.TotalShards,
ConnectionTimeout = int.MaxValue,
+ TotalShards = Credentials.TotalShards,
+ ShardId = shardId,
AlwaysDownloadUsers = false,
});
@@ -94,182 +107,245 @@ namespace NadekoBot
CaseSensitiveCommands = false,
DefaultRunMode = RunMode.Sync,
});
-
- //foundation services
- Localization = new Localization(BotConfig.Locale, AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.Locale), Db);
- Strings = new NadekoStrings(Localization);
- CommandHandler = new CommandHandler(Client, Db, BotConfig, AllGuildConfigs, CommandService, Credentials, this);
- Stats = new StatsService(Client, CommandHandler, Credentials);
+
Images = new ImagesService();
Currency = new CurrencyService(BotConfig, Db);
GoogleApi = new GoogleApiService(Credentials);
+ SetupShard(shardId, parentProcessId, port.Value);
+
#if GLOBAL_NADEKO
Client.Log += Client_Log;
#endif
}
+ private void StartSendingData()
+ {
+ Task.Run(async () =>
+ {
+ while (true)
+ {
+ await _comClient.Send(new ShardComMessage()
+ {
+ ConnectionState = Client.ConnectionState,
+ Guilds = Client.ConnectionState == ConnectionState.Connected ? Client.Guilds.Count : 0,
+ ShardId = Client.ShardId,
+ });
+ await Task.Delay(1000);
+ }
+ });
+ }
+
private void AddServices()
{
- var soundcloudApiService = new SoundCloudApiService(Credentials);
+ var startingGuildIdList = Client.Guilds.Select(x => (long)x.Id).ToList();
- #region help
- var helpService = new HelpService(BotConfig, CommandHandler, Strings);
- #endregion
+ //this unit of work will be used for initialization of all modules too, to prevent multiple queries from running
+ using (var uow = Db.UnitOfWork)
+ {
+ AllGuildConfigs = uow.GuildConfigs.GetAllGuildConfigs(startingGuildIdList).ToImmutableArray();
+
+ Localization = new Localization(BotConfig.Locale, AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.Locale), Db);
+ Strings = new NadekoStrings(Localization);
+ CommandHandler = new CommandHandler(Client, Db, BotConfig, AllGuildConfigs, CommandService, Credentials, this);
+ Stats = new StatsService(Client, CommandHandler, Credentials, ShardCoord);
- //module services
- //todo 90 - autodiscover, DI, and add instead of manual like this
- #region utility
- var crossServerTextService = new CrossServerTextService(AllGuildConfigs, Client);
- var remindService = new RemindService(Client, BotConfig, Db);
- var repeaterService = new MessageRepeaterService(this, Client, AllGuildConfigs);
- var converterService = new ConverterService(Db);
- var commandMapService = new CommandMapService(AllGuildConfigs);
- var patreonRewardsService = new PatreonRewardsService(Credentials, Db, Currency);
- var verboseErrorsService = new VerboseErrorsService(AllGuildConfigs, Db, CommandHandler, helpService);
- var pruneService = new PruneService();
- #endregion
+ var soundcloudApiService = new SoundCloudApiService(Credentials);
- #region permissions
- var permissionsService = new PermissionService(Db, BotConfig, CommandHandler);
- var blacklistService = new BlacklistService(BotConfig);
- var cmdcdsService = new CmdCdService(AllGuildConfigs);
- var filterService = new FilterService(Client, AllGuildConfigs);
- var globalPermsService = new GlobalPermissionService(BotConfig);
- #endregion
+ #region help
+ var helpService = new HelpService(BotConfig, CommandHandler, Strings);
+ #endregion
- #region Searches
- var searchesService = new SearchesService(Client, GoogleApi, Db);
- var streamNotificationService = new StreamNotificationService(Db, Client, Strings);
- var animeSearchService = new AnimeSearchService();
- #endregion
+ //module services
+ //todo 90 - autodiscover, DI, and add instead of manual like this
+ #region utility
+ var remindService = new RemindService(Client, BotConfig, Db, startingGuildIdList, uow);
+ var repeaterService = new MessageRepeaterService(this, Client, AllGuildConfigs);
+ //var converterService = new ConverterService(Db);
+ var commandMapService = new CommandMapService(AllGuildConfigs);
+ var patreonRewardsService = new PatreonRewardsService(Credentials, Db, Currency, Client);
+ var verboseErrorsService = new VerboseErrorsService(AllGuildConfigs, Db, CommandHandler, helpService);
+ var pruneService = new PruneService();
+ #endregion
- var clashService = new ClashOfClansService(Client, Db, Localization, Strings);
- var musicService = new MusicService(GoogleApi, Strings, Localization, Db, soundcloudApiService, Credentials, AllGuildConfigs);
- var crService = new CustomReactionsService(permissionsService, Db, Client, CommandHandler, BotConfig);
+ #region permissions
+ var permissionsService = new PermissionService(Client, Db, BotConfig, CommandHandler, Strings);
+ var blacklistService = new BlacklistService(BotConfig);
+ var cmdcdsService = new CmdCdService(AllGuildConfigs);
+ var filterService = new FilterService(Client, AllGuildConfigs);
+ var globalPermsService = new GlobalPermissionService(BotConfig);
+ #endregion
- #region Games
- var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, Strings, Images, CommandHandler);
- var chatterBotService = new ChatterBotService(Client, permissionsService, AllGuildConfigs, CommandHandler);
- var pollService = new PollService(Client, Strings);
- #endregion
+ #region Searches
+ var searchesService = new SearchesService(Client, GoogleApi, Db);
+ var streamNotificationService = new StreamNotificationService(Db, Client, Strings);
+ var animeSearchService = new AnimeSearchService();
+ #endregion
- #region administration
- var administrationService = new AdministrationService(AllGuildConfigs, CommandHandler);
- var greetSettingsService = new GreetSettingsService(Client, AllGuildConfigs, Db);
- var selfService = new SelfService(Client, this, CommandHandler, Db, BotConfig, Localization, Strings, Credentials);
- var vcRoleService = new VcRoleService(Client, AllGuildConfigs, Db);
- var vPlusTService = new VplusTService(Client, AllGuildConfigs, Strings, Db);
- var muteService = new MuteService(Client, AllGuildConfigs, Db);
- var ratelimitService = new SlowmodeService(Client, AllGuildConfigs);
- var protectionService = new ProtectionService(Client, AllGuildConfigs, muteService);
- var playingRotateService = new PlayingRotateService(Client, BotConfig, musicService);
- var gameVcService = new GameVoiceChannelService(Client, Db, AllGuildConfigs);
- var autoAssignRoleService = new AutoAssignRoleService(Client, AllGuildConfigs);
- var logCommandService = new LogCommandService(Client, Strings, AllGuildConfigs, Db, muteService, protectionService);
- var guildTimezoneService = new GuildTimezoneService(AllGuildConfigs, Db);
- #endregion
+ var clashService = new ClashOfClansService(Client, Db, Localization, Strings, uow, startingGuildIdList);
+ var musicService = new MusicService(GoogleApi, Strings, Localization, Db, soundcloudApiService, Credentials, AllGuildConfigs);
+ var crService = new CustomReactionsService(permissionsService, Db, Strings, Client, CommandHandler, BotConfig, uow);
- #region pokemon
- var pokemonService = new PokemonService();
- #endregion
+ #region Games
+ var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, Strings, Images, CommandHandler);
+ var chatterBotService = new ChatterBotService(Client, permissionsService, AllGuildConfigs, CommandHandler, Strings);
+ var pollService = new PollService(Client, Strings);
+ #endregion
+
+ #region administration
+ var administrationService = new AdministrationService(AllGuildConfigs, CommandHandler);
+ var greetSettingsService = new GreetSettingsService(Client, AllGuildConfigs, Db);
+ var selfService = new SelfService(Client, this, CommandHandler, Db, BotConfig, Localization, Strings, Credentials);
+ var vcRoleService = new VcRoleService(Client, AllGuildConfigs, Db);
+ var vPlusTService = new VplusTService(Client, AllGuildConfigs, Strings, Db);
+ var muteService = new MuteService(Client, AllGuildConfigs, Db);
+ var ratelimitService = new SlowmodeService(Client, AllGuildConfigs);
+ var protectionService = new ProtectionService(Client, AllGuildConfigs, muteService);
+ var playingRotateService = new PlayingRotateService(Client, BotConfig, musicService);
+ var gameVcService = new GameVoiceChannelService(Client, Db, AllGuildConfigs);
+ var autoAssignRoleService = new AutoAssignRoleService(Client, AllGuildConfigs);
+ var logCommandService = new LogCommandService(Client, Strings, AllGuildConfigs, Db, muteService, protectionService);
+ var guildTimezoneService = new GuildTimezoneService(AllGuildConfigs, Db);
+ #endregion
+
+ #region pokemon
+ var pokemonService = new PokemonService();
+ #endregion
- //initialize Services
- Services = new NServiceProvider.ServiceProviderBuilder()
- .Add(Localization)
- .Add(Stats)
- .Add(Images)
- .Add(GoogleApi)
- .Add(Stats)
- .Add(Credentials)
- .Add(CommandService)
- .Add(Strings)
- .Add(Client)
- .Add(BotConfig)
- .Add(Currency)
- .Add(CommandHandler)
- .Add(Db)
- //modules
- .Add(crossServerTextService)
- .Add(commandMapService)
- .Add(remindService)
- .Add(repeaterService)
- .Add(converterService)
- .Add(verboseErrorsService)
- .Add(patreonRewardsService)
- .Add(pruneService)
- .Add(searchesService)
- .Add(streamNotificationService)
- .Add(animeSearchService)
- .Add(clashService)
- .Add(musicService)
- .Add(greetSettingsService)
- .Add(crService)
- .Add(helpService)
- .Add(gamesService)
- .Add(chatterBotService)
- .Add(pollService)
- .Add(administrationService)
- .Add(selfService)
- .Add(vcRoleService)
- .Add(vPlusTService)
- .Add(muteService)
- .Add(ratelimitService)
- .Add(playingRotateService)
- .Add(gameVcService)
- .Add(autoAssignRoleService)
- .Add(protectionService)
- .Add(logCommandService)
- .Add(guildTimezoneService)
- .Add(permissionsService)
- .Add(blacklistService)
- .Add(cmdcdsService)
- .Add(filterService)
- .Add(globalPermsService)
- .Add(pokemonService)
- .Build();
- CommandHandler.AddServices(Services);
+ //initialize Services
+ Services = new NServiceProvider.ServiceProviderBuilder()
+ .Add(Localization)
+ .Add(Stats)
+ .Add(Images)
+ .Add(GoogleApi)
+ .Add(Stats)
+ .Add(Credentials)
+ .Add(CommandService)
+ .Add(Strings)
+ .Add(Client)
+ .Add(BotConfig)
+ .Add(Currency)
+ .Add(CommandHandler)
+ .Add(Db)
+ //modules
+ .Add(commandMapService)
+ .Add(remindService)
+ .Add(repeaterService)
+ //.Add(converterService)
+ .Add(verboseErrorsService)
+ .Add(patreonRewardsService)
+ .Add(pruneService)
+ .Add(searchesService)
+ .Add(streamNotificationService)
+ .Add(animeSearchService)
+ .Add(clashService)
+ .Add(musicService)
+ .Add(greetSettingsService)
+ .Add(crService)
+ .Add(helpService)
+ .Add(gamesService)
+ .Add(chatterBotService)
+ .Add(pollService)
+ .Add(administrationService)
+ .Add(selfService)
+ .Add(vcRoleService)
+ .Add(vPlusTService)
+ .Add(muteService)
+ .Add(ratelimitService)
+ .Add(playingRotateService)
+ .Add(gameVcService)
+ .Add(autoAssignRoleService)
+ .Add(protectionService)
+ .Add(logCommandService)
+ .Add(guildTimezoneService)
+ .Add(permissionsService)
+ .Add(blacklistService)
+ .Add(cmdcdsService)
+ .Add(filterService)
+ .Add(globalPermsService)
+ .Add(pokemonService)
+ .Add(this)
+ .Build();
- //setup typereaders
- CommandService.AddTypeReader(new PermissionActionTypeReader());
- CommandService.AddTypeReader(new CommandTypeReader(CommandService, CommandHandler));
- CommandService.AddTypeReader(new CommandOrCrTypeReader(crService, CommandService, CommandHandler));
- CommandService.AddTypeReader(new ModuleTypeReader(CommandService));
- CommandService.AddTypeReader(new ModuleOrCrTypeReader(CommandService));
- CommandService.AddTypeReader(new GuildTypeReader(Client));
- CommandService.AddTypeReader(new GuildDateTimeTypeReader(guildTimezoneService));
+
+ CommandHandler.AddServices(Services);
+
+ //setup typereaders
+ CommandService.AddTypeReader(new PermissionActionTypeReader());
+ CommandService.AddTypeReader(new CommandTypeReader(CommandService, CommandHandler));
+ CommandService.AddTypeReader(new CommandOrCrTypeReader(crService, CommandService, CommandHandler));
+ CommandService.AddTypeReader(new ModuleTypeReader(CommandService));
+ CommandService.AddTypeReader(new ModuleOrCrTypeReader(CommandService));
+ CommandService.AddTypeReader(new GuildTypeReader(Client));
+ CommandService.AddTypeReader(new GuildDateTimeTypeReader(guildTimezoneService));
+
+ }
}
private async Task LoginAsync(string token)
{
- _log.Info("Logging in...");
- //connect
- await Client.LoginAsync(TokenType.Bot, token).ConfigureAwait(false);
- await Client.StartAsync().ConfigureAwait(false);
+ var clientReady = new TaskCompletionSource();
- _log.Info("Waiting for all shards to connect...");
- while (!Client.Shards.All(x => x.ConnectionState == ConnectionState.Connected))
+ Task SetClientReady()
{
- _log.Info("Connecting... {0}/{1}", Client.Shards.Count(x => x.ConnectionState == ConnectionState.Connected), Client.Shards.Count);
- await Task.Delay(1000).ConfigureAwait(false);
+ var _ = Task.Run(async () =>
+ {
+ clientReady.TrySetResult(true);
+ try
+ {
+ foreach (var chan in (await Client.GetDMChannelsAsync()))
+ {
+ await chan.CloseAsync().ConfigureAwait(false);
+ }
+ }
+ catch
+ {
+ // ignored
+ }
+ finally
+ {
+
+ }
+ });
+ return Task.CompletedTask;
+ }
+
+ //connect
+ try { sem.WaitOne(); } catch (AbandonedMutexException) { }
+
+ _log.Info("Shard {0} logging in ...", ShardId);
+
+ try
+ {
+ await Client.LoginAsync(TokenType.Bot, token).ConfigureAwait(false);
+ await Client.StartAsync().ConfigureAwait(false);
+ Client.Ready += SetClientReady;
+ await clientReady.Task.ConfigureAwait(false);
+ Client.Ready -= SetClientReady;
+ }
+ finally
+ {
+ _log.Info("Shard {0} logged in.", ShardId);
+ sem.Release();
}
}
public async Task RunAsync(params string[] args)
{
+ if(ShardId == 0)
_log.Info("Starting NadekoBot v" + StatsService.BotVersion);
var sw = Stopwatch.StartNew();
await LoginAsync(Credentials.Token).ConfigureAwait(false);
- _log.Info("Loading services...");
+ _log.Info($"Shard {ShardId} loading services...");
AddServices();
sw.Stop();
- _log.Info($"Connected in {sw.Elapsed.TotalSeconds:F2} s");
+ _log.Info($"Shard {ShardId} connected in {sw.Elapsed.TotalSeconds:F2}s");
var stats = Services.GetService();
stats.Initialize();
@@ -290,15 +366,17 @@ namespace NadekoBot
// .Select(x => x.Key + $"({x.Count()})")));
//unload modules which are not available on the public bot
-#if GLOBAL_NADEKO
+#if GLOBAL_NADEKO
CommandService
.Modules
.ToArray()
.Where(x => x.Preconditions.Any(y => y.GetType() == typeof(NoPublicBot)))
.ForEach(x => CommandService.RemoveModuleAsync(x));
#endif
+
Ready = true;
- _log.Info(await stats.Print().ConfigureAwait(false));
+ _log.Info($"Shard {ShardId} ready.");
+ //_log.Info(await stats.Print().ConfigureAwait(false));
}
private Task Client_Log(LogMessage arg)
@@ -313,7 +391,13 @@ namespace NadekoBot
public async Task RunAndBlockAsync(params string[] args)
{
await RunAsync(args).ConfigureAwait(false);
- await Task.Delay(-1).ConfigureAwait(false);
+ StartSendingData();
+ if (ShardCoord != null)
+ await ShardCoord.RunAndBlockAsync();
+ else
+ {
+ await Task.Delay(-1).ConfigureAwait(false);
+ }
}
private void TerribleElevatedPermissionCheck()
@@ -331,18 +415,29 @@ namespace NadekoBot
}
}
- private static void SetupLogger()
+ private void SetupShard(int shardId, int parentProcessId, int port)
{
- var logConfig = new LoggingConfiguration();
- var consoleTarget = new ColoredConsoleTarget()
+ if (shardId != 0)
{
- Layout = @"${date:format=HH\:mm\:ss} ${logger} | ${message}"
- };
- logConfig.AddTarget("Console", consoleTarget);
-
- logConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget));
-
- LogManager.Configuration = logConfig;
+ new Thread(new ThreadStart(() =>
+ {
+ try
+ {
+ var p = Process.GetProcessById(parentProcessId);
+ if (p == null)
+ return;
+ p.WaitForExit();
+ }
+ finally
+ {
+ Environment.Exit(10);
+ }
+ })).Start();
+ }
+ else
+ {
+ ShardCoord = new ShardsCoordinator(port);
+ }
}
}
}
diff --git a/src/NadekoBot/NadekoBot.csproj b/src/NadekoBot/NadekoBot.csproj
index 0cc722bc..18ad4911 100644
--- a/src/NadekoBot/NadekoBot.csproj
+++ b/src/NadekoBot/NadekoBot.csproj
@@ -90,5 +90,6 @@
+
diff --git a/src/NadekoBot/Program.cs b/src/NadekoBot/Program.cs
index 0c8832e2..09e53142 100644
--- a/src/NadekoBot/Program.cs
+++ b/src/NadekoBot/Program.cs
@@ -2,7 +2,17 @@
{
public class Program
{
- public static void Main(string[] args) =>
- new NadekoBot().RunAndBlockAsync(args).GetAwaiter().GetResult();
+ public static void Main(string[] args)
+ {
+ if (args.Length == 3 && int.TryParse(args[0], out int shardId) && int.TryParse(args[1], out int parentProcessId))
+ {
+ int? port = null;
+ if (int.TryParse(args[2], out var outPort))
+ port = outPort;
+ new NadekoBot(shardId, parentProcessId, outPort).RunAndBlockAsync(args).GetAwaiter().GetResult();
+ }
+ else
+ new NadekoBot(0, 0).RunAndBlockAsync(args).GetAwaiter().GetResult();
+ }
}
}
diff --git a/src/NadekoBot/Properties/launchSettings.json b/src/NadekoBot/Properties/launchSettings.json
new file mode 100644
index 00000000..b532770a
--- /dev/null
+++ b/src/NadekoBot/Properties/launchSettings.json
@@ -0,0 +1,7 @@
+{
+ "profiles": {
+ "NadekoBot": {
+ "commandName": "Project"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx
index 708abfe8..e896535d 100644
--- a/src/NadekoBot/Resources/CommandStrings.resx
+++ b/src/NadekoBot/Resources/CommandStrings.resx
@@ -3096,14 +3096,14 @@
`{0}shardstats` or `{0}shardstats 2`
-
- connectshard
+
+ restartshard
-
+
Try (re)connecting a shard with a certain shardid when it dies. No one knows will it work. Keep an eye on the console for errors.
-
- `{0}connectshard 2`
+
+ `{0}restartshard 2`
shardid
diff --git a/src/NadekoBot/Services/Administration/AutoAssignRoleService.cs b/src/NadekoBot/Services/Administration/AutoAssignRoleService.cs
index 14679b6d..7c8b8711 100644
--- a/src/NadekoBot/Services/Administration/AutoAssignRoleService.cs
+++ b/src/NadekoBot/Services/Administration/AutoAssignRoleService.cs
@@ -12,12 +12,12 @@ namespace NadekoBot.Services.Administration
public class AutoAssignRoleService
{
private readonly Logger _log;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
//guildid/roleid
public ConcurrentDictionary AutoAssignedRoles { get; }
- public AutoAssignRoleService(DiscordShardedClient client, IEnumerable gcs)
+ public AutoAssignRoleService(DiscordSocketClient client, IEnumerable gcs)
{
_log = LogManager.GetCurrentClassLogger();
_client = client;
diff --git a/src/NadekoBot/Services/Administration/GameVoiceChannelService.cs b/src/NadekoBot/Services/Administration/GameVoiceChannelService.cs
index 14f9c6c6..52ea08f7 100644
--- a/src/NadekoBot/Services/Administration/GameVoiceChannelService.cs
+++ b/src/NadekoBot/Services/Administration/GameVoiceChannelService.cs
@@ -16,9 +16,9 @@ namespace NadekoBot.Services.Administration
private readonly Logger _log;
private readonly DbService _db;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
- public GameVoiceChannelService(DiscordShardedClient client, DbService db, IEnumerable gcs)
+ public GameVoiceChannelService(DiscordSocketClient client, DbService db, IEnumerable gcs)
{
_log = LogManager.GetCurrentClassLogger();
_db = db;
diff --git a/src/NadekoBot/Services/Administration/LogCommandService.cs b/src/NadekoBot/Services/Administration/LogCommandService.cs
index 84555345..420ada80 100644
--- a/src/NadekoBot/Services/Administration/LogCommandService.cs
+++ b/src/NadekoBot/Services/Administration/LogCommandService.cs
@@ -16,7 +16,7 @@ namespace NadekoBot.Services.Administration
public class LogCommandService
{
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly Logger _log;
private string PrettyCurrentTime => $"【{DateTime.UtcNow:HH:mm:ss}】";
@@ -31,7 +31,7 @@ namespace NadekoBot.Services.Administration
private readonly MuteService _mute;
private readonly ProtectionService _prot;
- public LogCommandService(DiscordShardedClient client, NadekoStrings strings,
+ public LogCommandService(DiscordSocketClient client, NadekoStrings strings,
IEnumerable gcs, DbService db, MuteService mute, ProtectionService prot)
{
_client = client;
@@ -74,7 +74,7 @@ namespace NadekoBot.Services.Administration
_client.UserUnbanned += _client_UserUnbanned;
_client.UserJoined += _client_UserJoined;
_client.UserLeft += _client_UserLeft;
- _client.UserPresenceUpdated += _client_UserPresenceUpdated;
+ //_client.UserPresenceUpdated += _client_UserPresenceUpdated;
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated;
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated_TTS;
_client.GuildMemberUpdated += _client_GuildUserUpdated;
@@ -576,48 +576,48 @@ namespace NadekoBot.Services.Administration
return Task.CompletedTask;
}
- private Task _client_UserPresenceUpdated(Optional optGuild, SocketUser usr, SocketPresence before, SocketPresence after)
- {
- var _ = Task.Run(async () =>
- {
- try
- {
- var guild = optGuild.GetValueOrDefault() ?? (usr as SocketGuildUser)?.Guild;
+ //private Task _client_UserPresenceUpdated(Optional optGuild, SocketUser usr, SocketPresence before, SocketPresence after)
+ //{
+ // var _ = Task.Run(async () =>
+ // {
+ // try
+ // {
+ // var guild = optGuild.GetValueOrDefault() ?? (usr as SocketGuildUser)?.Guild;
- if (guild == null)
- return;
+ // if (guild == null)
+ // return;
- if (!GuildLogSettings.TryGetValue(guild.Id, out LogSetting logSetting)
- || (logSetting.LogUserPresenceId == null)
- || before.Status == after.Status)
- return;
+ // if (!GuildLogSettings.TryGetValue(guild.Id, out LogSetting logSetting)
+ // || (logSetting.LogUserPresenceId == null)
+ // || before.Status == after.Status)
+ // return;
- ITextChannel logChannel;
- if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserPresence)) == null)
- return;
- string str = "";
- if (before.Status != after.Status)
- str = "🎭" + Format.Code(PrettyCurrentTime) +
- GetText(logChannel.Guild, "user_status_change",
- "👤" + Format.Bold(usr.Username),
- Format.Bold(after.Status.ToString()));
+ // ITextChannel logChannel;
+ // if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserPresence)) == null)
+ // return;
+ // string str = "";
+ // if (before.Status != after.Status)
+ // str = "🎭" + Format.Code(PrettyCurrentTime) +
+ // GetText(logChannel.Guild, "user_status_change",
+ // "👤" + Format.Bold(usr.Username),
+ // Format.Bold(after.Status.ToString()));
- //if (before.Game?.Name != after.Game?.Name)
- //{
- // if (str != "")
- // str += "\n";
- // str += $"👾`{prettyCurrentTime}`👤__**{usr.Username}**__ is now playing **{after.Game?.Name}**.";
- //}
+ // //if (before.Game?.Name != after.Game?.Name)
+ // //{
+ // // if (str != "")
+ // // str += "\n";
+ // // str += $"👾`{prettyCurrentTime}`👤__**{usr.Username}**__ is now playing **{after.Game?.Name}**.";
+ // //}
- PresenceUpdates.AddOrUpdate(logChannel, new List() { str }, (id, list) => { list.Add(str); return list; });
- }
- catch
- {
- // ignored
- }
- });
- return Task.CompletedTask;
- }
+ // PresenceUpdates.AddOrUpdate(logChannel, new List() { str }, (id, list) => { list.Add(str); return list; });
+ // }
+ // catch
+ // {
+ // // ignored
+ // }
+ // });
+ // return Task.CompletedTask;
+ //}
private Task _client_UserLeft(IGuildUser usr)
{
diff --git a/src/NadekoBot/Services/Administration/MuteService.cs b/src/NadekoBot/Services/Administration/MuteService.cs
index 7ed9062a..87bde743 100644
--- a/src/NadekoBot/Services/Administration/MuteService.cs
+++ b/src/NadekoBot/Services/Administration/MuteService.cs
@@ -33,10 +33,10 @@ namespace NadekoBot.Services.Administration
private static readonly OverwritePermissions denyOverwrite = new OverwritePermissions(sendMessages: PermValue.Deny, attachFiles: PermValue.Deny);
private readonly Logger _log = LogManager.GetCurrentClassLogger();
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly DbService _db;
- public MuteService(DiscordShardedClient client, IEnumerable gcs, DbService db)
+ public MuteService(DiscordSocketClient client, IEnumerable gcs, DbService db)
{
_client = client;
_db = db;
diff --git a/src/NadekoBot/Services/Administration/PlayingRotateService.cs b/src/NadekoBot/Services/Administration/PlayingRotateService.cs
index 7662b7ca..c7a1bf41 100644
--- a/src/NadekoBot/Services/Administration/PlayingRotateService.cs
+++ b/src/NadekoBot/Services/Administration/PlayingRotateService.cs
@@ -17,7 +17,7 @@ namespace NadekoBot.Services.Administration
public List RotatingStatusMessages { get; }
public volatile bool RotatingStatuses;
private readonly Timer _t;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly BotConfig _bc;
private readonly MusicService _music;
private readonly Logger _log;
@@ -27,7 +27,7 @@ namespace NadekoBot.Services.Administration
public int Index { get; set; }
}
- public PlayingRotateService(DiscordShardedClient client, BotConfig bc, MusicService music)
+ public PlayingRotateService(DiscordSocketClient client, BotConfig bc, MusicService music)
{
_client = client;
_bc = bc;
@@ -36,7 +36,7 @@ namespace NadekoBot.Services.Administration
RotatingStatusMessages = _bc.RotatingStatusMessages;
RotatingStatuses = _bc.RotatingStatuses;
-
+
_t = new Timer(async (objState) =>
{
try
@@ -52,17 +52,12 @@ namespace NadekoBot.Services.Administration
var status = RotatingStatusMessages[state.Index++].Status;
if (string.IsNullOrWhiteSpace(status))
return;
- PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value(_client,_music)));
- var shards = _client.Shards;
- for (int i = 0; i < shards.Count; i++)
+ PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value(_client, _music)));
+ ShardSpecificPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value(client)));
+ try { await client.SetGameAsync(status).ConfigureAwait(false); }
+ catch (Exception ex)
{
- var curShard = shards.ElementAt(i);
- ShardSpecificPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value(curShard)));
- try { await shards.ElementAt(i).SetGameAsync(status).ConfigureAwait(false); }
- catch (Exception ex)
- {
- _log.Warn(ex);
- }
+ _log.Warn(ex);
}
}
catch (Exception ex)
@@ -72,8 +67,8 @@ namespace NadekoBot.Services.Administration
}, new TimerState(), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
}
- public Dictionary> PlayingPlaceholders { get; } =
- new Dictionary> {
+ public Dictionary> PlayingPlaceholders { get; } =
+ new Dictionary> {
{ "%servers%", (c, ms) => c.Guilds.Count.ToString()},
{ "%users%", (c, ms) => c.Guilds.Sum(s => s.Users.Count).ToString()},
{ "%playing%", (c, ms) => {
@@ -90,7 +85,6 @@ namespace NadekoBot.Services.Administration
},
{ "%queued%", (c, ms) => ms.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString()},
{ "%time%", (c, ms) => DateTime.Now.ToString("HH:mm " + TimeZoneInfo.Local.StandardName.GetInitials()) },
- { "%shardcount%", (c, ms) => c.Shards.Count.ToString() },
};
public Dictionary> ShardSpecificPlaceholders { get; } =
diff --git a/src/NadekoBot/Services/Administration/ProtectionService.cs b/src/NadekoBot/Services/Administration/ProtectionService.cs
index 23bca7ad..6a2ae99b 100644
--- a/src/NadekoBot/Services/Administration/ProtectionService.cs
+++ b/src/NadekoBot/Services/Administration/ProtectionService.cs
@@ -21,10 +21,10 @@ namespace NadekoBot.Services.Administration
public event Func OnAntiProtectionTriggered = delegate { return Task.CompletedTask; };
private readonly Logger _log;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly MuteService _mute;
- public ProtectionService(DiscordShardedClient client, IEnumerable gcs, MuteService mute)
+ public ProtectionService(DiscordSocketClient client, IEnumerable gcs, MuteService mute)
{
_log = LogManager.GetCurrentClassLogger();
_client = client;
diff --git a/src/NadekoBot/Services/Administration/RatelimitService.cs b/src/NadekoBot/Services/Administration/RatelimitService.cs
index b344930f..a0f4171f 100644
--- a/src/NadekoBot/Services/Administration/RatelimitService.cs
+++ b/src/NadekoBot/Services/Administration/RatelimitService.cs
@@ -19,9 +19,9 @@ namespace NadekoBot.Services.Administration
public ConcurrentDictionary> IgnoredUsers = new ConcurrentDictionary>();
private readonly Logger _log;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
- public SlowmodeService(DiscordShardedClient client, IEnumerable gcs)
+ public SlowmodeService(DiscordSocketClient client, IEnumerable gcs)
{
_log = LogManager.GetCurrentClassLogger();
_client = client;
diff --git a/src/NadekoBot/Services/Administration/SelfService.cs b/src/NadekoBot/Services/Administration/SelfService.cs
index f3148d5a..2a12ffca 100644
--- a/src/NadekoBot/Services/Administration/SelfService.cs
+++ b/src/NadekoBot/Services/Administration/SelfService.cs
@@ -23,11 +23,11 @@ namespace NadekoBot.Services.Administration
private readonly Logger _log;
private readonly ILocalization _localization;
private readonly NadekoStrings _strings;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly IBotCredentials _creds;
private ImmutableArray> ownerChannels = new ImmutableArray>();
- public SelfService(DiscordShardedClient client, NadekoBot bot, CommandHandler cmdHandler, DbService db,
+ public SelfService(DiscordSocketClient client, NadekoBot bot, CommandHandler cmdHandler, DbService db,
BotConfig bc, ILocalization localization, NadekoStrings strings, IBotCredentials creds)
{
_bot = bot;
@@ -39,12 +39,8 @@ namespace NadekoBot.Services.Administration
_client = client;
_creds = creds;
- using (var uow = _db.UnitOfWork)
- {
- var config = uow.BotConfig.GetOrCreate();
- ForwardDMs = config.ForwardMessages;
- ForwardDMsToAllOwners = config.ForwardToAllOwners;
- }
+ ForwardDMs = bc.ForwardMessages;
+ ForwardDMsToAllOwners = bc.ForwardToAllOwners;
var _ = Task.Run(async () =>
{
@@ -67,12 +63,8 @@ namespace NadekoBot.Services.Administration
_client.Guilds.SelectMany(g => g.Users);
- LoadOwnerChannels();
-
- if (!ownerChannels.Any())
- _log.Warn("No owner channels created! Make sure you've specified correct OwnerId in the credentials.json file.");
- else
- _log.Info($"Created {ownerChannels.Length} out of {_creds.OwnerIds.Length} owner message channels.");
+ if(client.ShardId == 0)
+ LoadOwnerChannels();
});
}
@@ -81,11 +73,9 @@ namespace NadekoBot.Services.Administration
var hs = new HashSet(_creds.OwnerIds);
var channels = new Dictionary>();
- foreach (var s in _client.Shards)
+ if (hs.Count > 0)
{
- if (hs.Count == 0)
- break;
- foreach (var g in s.Guilds)
+ foreach (var g in _client.Guilds)
{
if (hs.Count == 0)
break;
@@ -105,10 +95,15 @@ namespace NadekoBot.Services.Administration
ownerChannels = channels.OrderBy(x => _creds.OwnerIds.IndexOf(x.Key))
.Select(x => x.Value)
.ToImmutableArray();
+
+ if (!ownerChannels.Any())
+ _log.Warn("No owner channels created! Make sure you've specified correct OwnerId in the credentials.json file.");
+ else
+ _log.Info($"Created {ownerChannels.Length} out of {_creds.OwnerIds.Length} owner message channels.");
}
// forwards dms
- public async Task LateExecute(DiscordShardedClient client, IGuild guild, IUserMessage msg)
+ public async Task LateExecute(DiscordSocketClient client, IGuild guild, IUserMessage msg)
{
if (msg.Channel is IDMChannel && ForwardDMs && ownerChannels.Length > 0)
{
diff --git a/src/NadekoBot/Services/Administration/VcRoleService.cs b/src/NadekoBot/Services/Administration/VcRoleService.cs
index 49dbe9ff..10252833 100644
--- a/src/NadekoBot/Services/Administration/VcRoleService.cs
+++ b/src/NadekoBot/Services/Administration/VcRoleService.cs
@@ -14,11 +14,11 @@ namespace NadekoBot.Services.Administration
{
private readonly Logger _log;
private readonly DbService _db;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
public ConcurrentDictionary> VcRoles { get; }
- public VcRoleService(DiscordShardedClient client, IEnumerable gcs, DbService db)
+ public VcRoleService(DiscordSocketClient client, IEnumerable gcs, DbService db)
{
_log = LogManager.GetCurrentClassLogger();
_db = db;
diff --git a/src/NadekoBot/Services/Administration/VplusTService.cs b/src/NadekoBot/Services/Administration/VplusTService.cs
index 3d9e86cd..b4e3122d 100644
--- a/src/NadekoBot/Services/Administration/VplusTService.cs
+++ b/src/NadekoBot/Services/Administration/VplusTService.cs
@@ -20,12 +20,12 @@ namespace NadekoBot.Services.Administration
public readonly ConcurrentHashSet VoicePlusTextCache;
private readonly ConcurrentDictionary _guildLockObjects = new ConcurrentDictionary();
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly NadekoStrings _strings;
private readonly DbService _db;
private readonly Logger _log;
- public VplusTService(DiscordShardedClient client, IEnumerable gcs, NadekoStrings strings,
+ public VplusTService(DiscordSocketClient client, IEnumerable gcs, NadekoStrings strings,
DbService db)
{
_client = client;
diff --git a/src/NadekoBot/Services/ClashOfClans/ClashOfClansService.cs b/src/NadekoBot/Services/ClashOfClans/ClashOfClansService.cs
index edb78512..dcdd6376 100644
--- a/src/NadekoBot/Services/ClashOfClans/ClashOfClansService.cs
+++ b/src/NadekoBot/Services/ClashOfClans/ClashOfClansService.cs
@@ -1,6 +1,7 @@
using Discord;
using Discord.WebSocket;
using NadekoBot.Extensions;
+using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models;
using System;
using System.Collections.Concurrent;
@@ -17,7 +18,7 @@ namespace NadekoBot.Services.ClashOfClans
// shouldn't be here
public class ClashOfClansService
{
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly DbService _db;
private readonly ILocalization _localization;
private readonly NadekoStrings _strings;
@@ -25,28 +26,27 @@ namespace NadekoBot.Services.ClashOfClans
public ConcurrentDictionary> ClashWars { get; set; }
- public ClashOfClansService(DiscordShardedClient client, DbService db, ILocalization localization, NadekoStrings strings)
+ public ClashOfClansService(DiscordSocketClient client, DbService db,
+ ILocalization localization, NadekoStrings strings, IUnitOfWork uow,
+ List guilds)
{
_client = client;
_db = db;
_localization = localization;
_strings = strings;
- using (var uow = _db.UnitOfWork)
- {
- ClashWars = new ConcurrentDictionary>(
- uow.ClashOfClans
- .GetAllWars()
- .Select(cw =>
- {
- cw.Channel = _client.GetGuild(cw.GuildId)?
- .GetTextChannel(cw.ChannelId);
- return cw;
- })
- .Where(cw => cw.Channel != null)
- .GroupBy(cw => cw.GuildId)
- .ToDictionary(g => g.Key, g => g.ToList()));
- }
+ ClashWars = new ConcurrentDictionary>(
+ uow.ClashOfClans
+ .GetAllWars(guilds)
+ .Select(cw =>
+ {
+ cw.Channel = _client.GetGuild(cw.GuildId)?
+ .GetTextChannel(cw.ChannelId);
+ return cw;
+ })
+ .Where(cw => cw.Channel != null)
+ .GroupBy(cw => cw.GuildId)
+ .ToDictionary(g => g.Key, g => g.ToList()));
checkWarTimer = new Timer(async _ =>
{
diff --git a/src/NadekoBot/Services/CommandHandler.cs b/src/NadekoBot/Services/CommandHandler.cs
index 2177ce01..a1de8871 100644
--- a/src/NadekoBot/Services/CommandHandler.cs
+++ b/src/NadekoBot/Services/CommandHandler.cs
@@ -28,7 +28,7 @@ namespace NadekoBot.Services
{
public const int GlobalCommandsCooldown = 750;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly CommandService _commandService;
private readonly Logger _log;
private readonly IBotCredentials _creds;
@@ -48,7 +48,7 @@ namespace NadekoBot.Services
public ConcurrentHashSet UsersOnShortCooldown { get; } = new ConcurrentHashSet();
private readonly Timer _clearUsersOnShortCooldown;
- public CommandHandler(DiscordShardedClient client, DbService db, BotConfig bc, IEnumerable gcs, CommandService commandService, IBotCredentials credentials, NadekoBot bot)
+ public CommandHandler(DiscordSocketClient client, DbService db, BotConfig bc, IEnumerable gcs, CommandService commandService, IBotCredentials credentials, NadekoBot bot)
{
_client = client;
_commandService = commandService;
diff --git a/src/NadekoBot/Services/CustomReactions/CustomReactionsService.cs b/src/NadekoBot/Services/CustomReactions/CustomReactionsService.cs
index 206b0bd9..c64f5c81 100644
--- a/src/NadekoBot/Services/CustomReactions/CustomReactionsService.cs
+++ b/src/NadekoBot/Services/CustomReactions/CustomReactionsService.cs
@@ -10,6 +10,7 @@ using System;
using System.Threading.Tasks;
using NadekoBot.Services.Permissions;
using NadekoBot.Extensions;
+using NadekoBot.Services.Database;
namespace NadekoBot.Services.CustomReactions
{
@@ -22,13 +23,14 @@ namespace NadekoBot.Services.CustomReactions
private readonly Logger _log;
private readonly DbService _db;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly PermissionService _perms;
private readonly CommandHandler _cmd;
private readonly BotConfig _bc;
+ private readonly NadekoStrings _strings;
- public CustomReactionsService(PermissionService perms, DbService db,
- DiscordShardedClient client, CommandHandler cmd, BotConfig bc)
+ public CustomReactionsService(PermissionService perms, DbService db, NadekoStrings strings,
+ DiscordSocketClient client, CommandHandler cmd, BotConfig bc, IUnitOfWork uow)
{
_log = LogManager.GetCurrentClassLogger();
_db = db;
@@ -36,16 +38,11 @@ namespace NadekoBot.Services.CustomReactions
_perms = perms;
_cmd = cmd;
_bc = bc;
-
- var sw = Stopwatch.StartNew();
- using (var uow = _db.UnitOfWork)
- {
- var items = uow.CustomReactions.GetAll();
- GuildReactions = new ConcurrentDictionary(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => g.ToArray()));
- GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray();
- }
- sw.Stop();
- _log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
+ _strings = strings;
+
+ var items = uow.CustomReactions.GetAll();
+ GuildReactions = new ConcurrentDictionary(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => g.ToArray()));
+ GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray();
}
public void ClearStats() => ReactionStats.Clear();
@@ -98,7 +95,7 @@ namespace NadekoBot.Services.CustomReactions
return greaction;
}
- public async Task TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage msg)
+ public async Task TryExecuteEarly(DiscordSocketClient client, IGuild guild, IUserMessage msg)
{
// maybe this message is a custom reaction
var cr = await Task.Run(() => TryGetCustomReaction(msg)).ConfigureAwait(false);
@@ -114,7 +111,7 @@ namespace NadekoBot.Services.CustomReactions
{
if (pc.Verbose)
{
- var returnMsg = $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(_cmd.GetPrefix(guild), sg)}** is preventing this action.";
+ var returnMsg = _strings.GetText("trigger", guild.Id, "Permissions".ToLowerInvariant(), index + 1, Format.Bold(pc.Permissions[index].GetCommand(_cmd.GetPrefix(guild), (SocketGuild)guild)));
try { await msg.Channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
_log.Info(returnMsg);
}
diff --git a/src/NadekoBot/Services/CustomReactions/Extensions.cs b/src/NadekoBot/Services/CustomReactions/Extensions.cs
index e2c5481f..4d6d4d06 100644
--- a/src/NadekoBot/Services/CustomReactions/Extensions.cs
+++ b/src/NadekoBot/Services/CustomReactions/Extensions.cs
@@ -40,7 +40,7 @@ namespace NadekoBot.Services.CustomReactions
} },
};
- public static Dictionary> placeholders = new Dictionary>()
+ public static Dictionary> placeholders = new Dictionary>()
{
{"%mention%", (ctx, client) => { return $"<@{client.CurrentUser.Id}>"; } },
{"%user%", (ctx, client) => { return ctx.Author.Mention; } },
@@ -94,7 +94,7 @@ namespace NadekoBot.Services.CustomReactions
} }
};
- private static string ResolveTriggerString(this string str, IUserMessage ctx, DiscordShardedClient client)
+ private static string ResolveTriggerString(this string str, IUserMessage ctx, DiscordSocketClient client)
{
foreach (var ph in placeholders)
{
@@ -104,7 +104,7 @@ namespace NadekoBot.Services.CustomReactions
return str;
}
- private static async Task ResolveResponseStringAsync(this string str, IUserMessage ctx, DiscordShardedClient client, string resolvedTrigger)
+ private static async Task ResolveResponseStringAsync(this string str, IUserMessage ctx, DiscordSocketClient client, string resolvedTrigger)
{
foreach (var ph in placeholders)
{
@@ -127,13 +127,13 @@ namespace NadekoBot.Services.CustomReactions
return str;
}
- public static string TriggerWithContext(this CustomReaction cr, IUserMessage ctx, DiscordShardedClient client)
+ public static string TriggerWithContext(this CustomReaction cr, IUserMessage ctx, DiscordSocketClient client)
=> cr.Trigger.ResolveTriggerString(ctx, client);
- public static Task ResponseWithContextAsync(this CustomReaction cr, IUserMessage ctx, DiscordShardedClient client)
+ public static Task ResponseWithContextAsync(this CustomReaction cr, IUserMessage ctx, DiscordSocketClient client)
=> cr.Response.ResolveResponseStringAsync(ctx, client, cr.Trigger.ResolveTriggerString(ctx, client));
- public static async Task Send(this CustomReaction cr, IUserMessage context, DiscordShardedClient client, CustomReactionsService crs)
+ public static async Task Send(this CustomReaction cr, IUserMessage context, DiscordSocketClient client, CustomReactionsService crs)
{
var channel = cr.DmResponse ? await context.Author.CreateDMChannelAsync() : context.Channel;
diff --git a/src/NadekoBot/Services/Database/NadekoContext.cs b/src/NadekoBot/Services/Database/NadekoContext.cs
index 9c084867..238130ed 100644
--- a/src/NadekoBot/Services/Database/NadekoContext.cs
+++ b/src/NadekoBot/Services/Database/NadekoContext.cs
@@ -19,7 +19,9 @@ namespace NadekoBot.Services.Database
{
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlite("Filename=./data/NadekoBot.db");
- return new NadekoContext(optionsBuilder.Options);
+ var ctx = new NadekoContext(optionsBuilder.Options);
+ ctx.Database.SetCommandTimeout(60);
+ return ctx;
}
}
diff --git a/src/NadekoBot/Services/Database/Repositories/IClashOfClansRepository.cs b/src/NadekoBot/Services/Database/Repositories/IClashOfClansRepository.cs
index 756e9789..14edcea8 100644
--- a/src/NadekoBot/Services/Database/Repositories/IClashOfClansRepository.cs
+++ b/src/NadekoBot/Services/Database/Repositories/IClashOfClansRepository.cs
@@ -5,6 +5,6 @@ namespace NadekoBot.Services.Database.Repositories
{
public interface IClashOfClansRepository : IRepository
{
- IEnumerable GetAllWars();
+ IEnumerable GetAllWars(List guilds);
}
}
diff --git a/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs b/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs
index cca54609..e56a9026 100644
--- a/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs
+++ b/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs
@@ -11,10 +11,10 @@ namespace NadekoBot.Services.Database.Repositories
GuildConfig For(ulong guildId, Func, IQueryable> includes = null);
GuildConfig LogSettingsFor(ulong guildId);
IEnumerable OldPermissionsForAll();
- IEnumerable GetAllGuildConfigs();
- IEnumerable GetAllFollowedStreams();
+ IEnumerable GetAllGuildConfigs(List availableGuilds);
+ IEnumerable GetAllFollowedStreams(List included);
void SetCleverbotEnabled(ulong id, bool cleverbotEnabled);
- IEnumerable Permissionsv2ForAll();
+ IEnumerable Permissionsv2ForAll(List include);
GuildConfig GcWithPermissionsv2For(ulong guildId);
}
}
diff --git a/src/NadekoBot/Services/Database/Repositories/IReminderRepository.cs b/src/NadekoBot/Services/Database/Repositories/IReminderRepository.cs
index 7c643ec7..07eec33f 100644
--- a/src/NadekoBot/Services/Database/Repositories/IReminderRepository.cs
+++ b/src/NadekoBot/Services/Database/Repositories/IReminderRepository.cs
@@ -1,9 +1,11 @@
using NadekoBot.Services.Database.Models;
+using System.Collections;
+using System.Collections.Generic;
namespace NadekoBot.Services.Database.Repositories
{
public interface IReminderRepository : IRepository
{
-
+ IEnumerable GetIncludedReminders(List guildIds);
}
}
diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs
index 54a391fa..828c4bce 100644
--- a/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs
+++ b/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs
@@ -11,9 +11,11 @@ namespace NadekoBot.Services.Database.Repositories.Impl
{
}
- public IEnumerable GetAllWars()
+ public IEnumerable GetAllWars(List guilds)
{
- var toReturn = _set.Include(cw => cw.Bases)
+ var toReturn = _set
+ .Where(cw => guilds.Contains((long)cw.GuildId))
+ .Include(cw => cw.Bases)
.ToList();
toReturn.ForEach(cw => cw.Bases = cw.Bases.Where(w => w.SequenceNumber != null).OrderBy(w => w.SequenceNumber).ToList());
return toReturn;
diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs
index f3ed3566..3628a4e9 100644
--- a/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs
+++ b/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs
@@ -24,8 +24,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl
}
};
- public IEnumerable GetAllGuildConfigs() =>
- _set.Include(gc => gc.LogSetting)
+ public IEnumerable GetAllGuildConfigs(List availableGuilds) =>
+ _set
+ .Where(gc => availableGuilds.Contains((long)gc.GuildId))
+ .Include(gc => gc.LogSetting)
.ThenInclude(ls => ls.IgnoredChannels)
.Include(gc => gc.MutedUsers)
.Include(gc => gc.CommandAliases)
@@ -42,6 +44,7 @@ namespace NadekoBot.Services.Database.Repositories.Impl
.Include(gc => gc.SlowmodeIgnoredUsers)
.Include(gc => gc.AntiSpamSetting)
.ThenInclude(x => x.IgnoredChannels)
+ .Include(gc => gc.FollowedStreams)
.ToList();
///
@@ -134,9 +137,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl
return query.ToList();
}
- public IEnumerable Permissionsv2ForAll()
+ public IEnumerable Permissionsv2ForAll(List include)
{
var query = _set
+ .Where(x => include.Contains((long)x.GuildId))
.Include(gc => gc.Permissions);
return query.ToList();
@@ -167,8 +171,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl
return config;
}
- public IEnumerable GetAllFollowedStreams() =>
- _set.Include(gc => gc.FollowedStreams)
+ public IEnumerable GetAllFollowedStreams(List included) =>
+ _set
+ .Where(gc => included.Contains((long)gc.GuildId))
+ .Include(gc => gc.FollowedStreams)
.SelectMany(gc => gc.FollowedStreams)
.ToList();
diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/ReminderRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/ReminderRepository.cs
index fc7c28ff..b1a0e2a0 100644
--- a/src/NadekoBot/Services/Database/Repositories/Impl/ReminderRepository.cs
+++ b/src/NadekoBot/Services/Database/Repositories/Impl/ReminderRepository.cs
@@ -1,5 +1,8 @@
using NadekoBot.Services.Database.Models;
using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace NadekoBot.Services.Database.Repositories.Impl
{
@@ -8,5 +11,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl
public ReminderRepository(DbContext context) : base(context)
{
}
+
+ public IEnumerable GetIncludedReminders(List guildIds)
+ {
+ return _set.Where(x => guildIds.Contains((long)x.ServerId)).ToList();
+ }
}
}
diff --git a/src/NadekoBot/Services/DbService.cs b/src/NadekoBot/Services/DbService.cs
index 81e56d1d..6e9532ca 100644
--- a/src/NadekoBot/Services/DbService.cs
+++ b/src/NadekoBot/Services/DbService.cs
@@ -32,9 +32,21 @@ namespace NadekoBot.Services
public NadekoContext GetDbContext()
{
var context = new NadekoContext(options);
+ context.Database.SetCommandTimeout(60);
context.Database.Migrate();
context.EnsureSeedData();
+ //set important sqlite stuffs
+ var conn = context.Database.GetDbConnection();
+ conn.Open();
+
+ context.Database.ExecuteSqlCommand("PRAGMA journal_mode=WAL");
+ using (var com = conn.CreateCommand())
+ {
+ com.CommandText = "PRAGMA journal_mode=WAL; PRAGMA synchronous=OFF";
+ com.ExecuteNonQuery();
+ }
+
return context;
}
diff --git a/src/NadekoBot/Services/Discord/SocketMessageEventWrapper.cs b/src/NadekoBot/Services/Discord/SocketMessageEventWrapper.cs
index 58b3a1e5..4903fd66 100644
--- a/src/NadekoBot/Services/Discord/SocketMessageEventWrapper.cs
+++ b/src/NadekoBot/Services/Discord/SocketMessageEventWrapper.cs
@@ -12,7 +12,7 @@ namespace NadekoBot.Services.Discord
public event Action OnReactionRemoved = delegate { };
public event Action OnReactionsCleared = delegate { };
- public ReactionEventWrapper(DiscordShardedClient client, IUserMessage msg)
+ public ReactionEventWrapper(DiscordSocketClient client, IUserMessage msg)
{
Message = msg ?? throw new ArgumentNullException(nameof(msg));
_client = client;
@@ -69,7 +69,7 @@ namespace NadekoBot.Services.Discord
}
private bool disposing = false;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
public void Dispose()
{
diff --git a/src/NadekoBot/Services/Games/ChatterbotService.cs b/src/NadekoBot/Services/Games/ChatterbotService.cs
index 8039b79d..833eef0b 100644
--- a/src/NadekoBot/Services/Games/ChatterbotService.cs
+++ b/src/NadekoBot/Services/Games/ChatterbotService.cs
@@ -15,19 +15,22 @@ namespace NadekoBot.Services.Games
{
public class ChatterBotService : IEarlyBlockingExecutor
{
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly Logger _log;
private readonly PermissionService _perms;
private readonly CommandHandler _cmd;
+ private readonly NadekoStrings _strings;
public ConcurrentDictionary> ChatterBotGuilds { get; }
- public ChatterBotService(DiscordShardedClient client, PermissionService perms, IEnumerable gcs, CommandHandler cmd)
+ public ChatterBotService(DiscordSocketClient client, PermissionService perms, IEnumerable gcs,
+ CommandHandler cmd, NadekoStrings strings)
{
_client = client;
_log = LogManager.GetCurrentClassLogger();
_perms = perms;
_cmd = cmd;
+ _strings = strings;
ChatterBotGuilds = new ConcurrentDictionary>(
gcs.Where(gc => gc.CleverbotEnabled)
@@ -83,7 +86,7 @@ namespace NadekoBot.Services.Games
return true;
}
- public async Task TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage usrMsg)
+ public async Task TryExecuteEarly(DiscordSocketClient client, IGuild guild, IUserMessage usrMsg)
{
if (!(guild is SocketGuild sg))
return false;
@@ -102,7 +105,7 @@ namespace NadekoBot.Services.Games
if (pc.Verbose)
{
//todo move this to permissions
- var returnMsg = $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(_cmd.GetPrefix(guild), sg)}** is preventing this action.";
+ var returnMsg = _strings.GetText("trigger", guild.Id, "Permissions".ToLowerInvariant(), index + 1, Format.Bold(pc.Permissions[index].GetCommand(_cmd.GetPrefix(guild), (SocketGuild)guild)));
try { await usrMsg.Channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
_log.Info(returnMsg);
}
diff --git a/src/NadekoBot/Services/Games/GamesService.cs b/src/NadekoBot/Services/Games/GamesService.cs
index 24139906..e677990b 100644
--- a/src/NadekoBot/Services/Games/GamesService.cs
+++ b/src/NadekoBot/Services/Games/GamesService.cs
@@ -23,7 +23,7 @@ namespace NadekoBot.Services.Games
public readonly ImmutableArray EightBallResponses;
private readonly Timer _t;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly NadekoStrings _strings;
private readonly IImagesService _images;
private readonly Logger _log;
@@ -33,7 +33,7 @@ namespace NadekoBot.Services.Games
public List TypingArticles { get; } = new List();
- public GamesService(DiscordShardedClient client, BotConfig bc, IEnumerable gcs,
+ public GamesService(DiscordSocketClient client, BotConfig bc, IEnumerable gcs,
NadekoStrings strings, IImagesService images, CommandHandler cmdHandler)
{
_bc = bc;
diff --git a/src/NadekoBot/Services/Games/Poll.cs b/src/NadekoBot/Services/Games/Poll.cs
index 8feb4cb5..5358e139 100644
--- a/src/NadekoBot/Services/Games/Poll.cs
+++ b/src/NadekoBot/Services/Games/Poll.cs
@@ -18,16 +18,13 @@ namespace NadekoBot.Services.Games
private string[] answers { get; }
private readonly ConcurrentDictionary _participants = new ConcurrentDictionary();
private readonly string _question;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly NadekoStrings _strings;
private bool running = false;
- private HashSet _guildUsers;
public event Action OnEnded = delegate { };
- public bool IsPublic { get; }
-
- public Poll(DiscordShardedClient client, NadekoStrings strings, IUserMessage umsg, string question, IEnumerable enumerable, bool isPublic = false)
+ public Poll(DiscordSocketClient client, NadekoStrings strings, IUserMessage umsg, string question, IEnumerable enumerable)
{
_client = client;
_strings = strings;
@@ -36,7 +33,6 @@ namespace NadekoBot.Services.Games
_guild = ((ITextChannel)umsg.Channel).Guild;
_question = question;
answers = enumerable as string[] ?? enumerable.ToArray();
- IsPublic = isPublic;
}
public EmbedBuilder GetStats(string title)
@@ -82,13 +78,7 @@ namespace NadekoBot.Services.Games
var msgToSend = GetText("poll_created", Format.Bold(_originalMessage.Author.Username)) + "\n\n" + Format.Bold(_question) + "\n";
var num = 1;
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
- if (!IsPublic)
- msgToSend += "\n" + Format.Bold(GetText("poll_vote_private"));
- else
- msgToSend += "\n" + Format.Bold(GetText("poll_vote_public"));
-
- if (!IsPublic)
- _guildUsers = new HashSet((await _guild.GetUsersAsync().ConfigureAwait(false)).Select(x => x.Id));
+ msgToSend += "\n" + Format.Bold(GetText("poll_vote_public"));
await _originalMessage.Channel.SendConfirmAsync(msgToSend).ConfigureAwait(false);
running = true;
@@ -114,36 +104,16 @@ namespace NadekoBot.Services.Games
return false;
IMessageChannel ch;
- if (IsPublic)
- {
- //if public, channel must be the same the poll started in
- if (_originalMessage.Channel.Id != msg.Channel.Id)
- return false;
- ch = msg.Channel;
- }
- else
- {
- //if private, channel must be dm channel
- if ((ch = msg.Channel as IDMChannel) == null)
- return false;
-
- // user must be a member of the guild this poll is in
- if (!_guildUsers.Contains(msg.Author.Id))
- return false;
- }
+ //if public, channel must be the same the poll started in
+ if (_originalMessage.Channel.Id != msg.Channel.Id)
+ return false;
+ ch = msg.Channel;
//user can vote only once
if (_participants.TryAdd(msg.Author.Id, vote))
{
- if (!IsPublic)
- {
- await ch.SendConfirmAsync(GetText("thanks_for_voting", Format.Bold(msg.Author.Username))).ConfigureAwait(false);
- }
- else
- {
- var toDelete = await ch.SendConfirmAsync(GetText("poll_voted", Format.Bold(msg.Author.ToString()))).ConfigureAwait(false);
- toDelete.DeleteAfter(5);
- }
+ var toDelete = await ch.SendConfirmAsync(GetText("poll_voted", Format.Bold(msg.Author.ToString()))).ConfigureAwait(false);
+ toDelete.DeleteAfter(5);
return true;
}
return false;
diff --git a/src/NadekoBot/Services/Games/PollService.cs b/src/NadekoBot/Services/Games/PollService.cs
index a421bd77..ba6fee19 100644
--- a/src/NadekoBot/Services/Games/PollService.cs
+++ b/src/NadekoBot/Services/Games/PollService.cs
@@ -13,17 +13,17 @@ namespace NadekoBot.Services.Games
{
public ConcurrentDictionary ActivePolls = new ConcurrentDictionary();
private readonly Logger _log;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly NadekoStrings _strings;
- public PollService(DiscordShardedClient client, NadekoStrings strings)
+ public PollService(DiscordSocketClient client, NadekoStrings strings)
{
_log = LogManager.GetCurrentClassLogger();
_client = client;
_strings = strings;
}
- public async Task StartPoll(ITextChannel channel, IUserMessage msg, string arg, bool isPublic = false)
+ public async Task StartPoll(ITextChannel channel, IUserMessage msg, string arg)
{
if (string.IsNullOrWhiteSpace(arg) || !arg.Contains(";"))
return null;
@@ -31,7 +31,7 @@ namespace NadekoBot.Services.Games
if (data.Length < 3)
return null;
- var poll = new Poll(_client, _strings, msg, data[0], data.Skip(1), isPublic: isPublic);
+ var poll = new Poll(_client, _strings, msg, data[0], data.Skip(1));
if (ActivePolls.TryAdd(channel.Guild.Id, poll))
{
poll.OnEnded += (gid) =>
@@ -45,20 +45,10 @@ namespace NadekoBot.Services.Games
return false;
}
- public async Task TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage msg)
+ public async Task TryExecuteEarly(DiscordSocketClient client, IGuild guild, IUserMessage msg)
{
if (guild == null)
- {
- foreach (var kvp in ActivePolls)
- {
- if (!kvp.Value.IsPublic)
- {
- if (await kvp.Value.TryVote(msg).ConfigureAwait(false))
- return true;
- }
- }
return false;
- }
if (!ActivePolls.TryGetValue(guild.Id, out var poll))
return false;
diff --git a/src/NadekoBot/Services/GreetSettingsService.cs b/src/NadekoBot/Services/GreetSettingsService.cs
index 6e2e630d..3296c602 100644
--- a/src/NadekoBot/Services/GreetSettingsService.cs
+++ b/src/NadekoBot/Services/GreetSettingsService.cs
@@ -17,10 +17,10 @@ namespace NadekoBot.Services
private readonly DbService _db;
public readonly ConcurrentDictionary GuildConfigsCache;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly Logger _log;
- public GreetSettingsService(DiscordShardedClient client, IEnumerable guildConfigs, DbService db)
+ public GreetSettingsService(DiscordSocketClient client, IEnumerable guildConfigs, DbService db)
{
_db = db;
_client = client;
diff --git a/src/NadekoBot/Services/Help/HelpService.cs b/src/NadekoBot/Services/Help/HelpService.cs
index 25a91f16..83b64927 100644
--- a/src/NadekoBot/Services/Help/HelpService.cs
+++ b/src/NadekoBot/Services/Help/HelpService.cs
@@ -24,7 +24,7 @@ namespace NadekoBot.Services.Help
_strings = strings;
}
- public async Task LateExecute(DiscordShardedClient client, IGuild guild, IUserMessage msg)
+ public async Task LateExecute(DiscordSocketClient client, IGuild guild, IUserMessage msg)
{
try
{
diff --git a/src/NadekoBot/Services/IBotCredentials.cs b/src/NadekoBot/Services/IBotCredentials.cs
index f7711b83..e0c271b5 100644
--- a/src/NadekoBot/Services/IBotCredentials.cs
+++ b/src/NadekoBot/Services/IBotCredentials.cs
@@ -19,6 +19,9 @@ namespace NadekoBot.Services
string OsuApiKey { get; }
bool IsOwner(IUser u);
+ int TotalShards { get; }
+ string ShardRunCommand { get; }
+ string ShardRunArguments { get; }
}
public class DBConfig
diff --git a/src/NadekoBot/Services/IImagesService.cs b/src/NadekoBot/Services/IImagesService.cs
index 0a76175d..31e6c32a 100644
--- a/src/NadekoBot/Services/IImagesService.cs
+++ b/src/NadekoBot/Services/IImagesService.cs
@@ -18,6 +18,6 @@ namespace NadekoBot.Services
ImmutableArray WifeMatrix { get; }
ImmutableArray RategirlDot { get; }
- TimeSpan Reload();
+ void Reload();
}
}
diff --git a/src/NadekoBot/Services/IStatsService.cs b/src/NadekoBot/Services/IStatsService.cs
index a7735fc8..d187c413 100644
--- a/src/NadekoBot/Services/IStatsService.cs
+++ b/src/NadekoBot/Services/IStatsService.cs
@@ -13,6 +13,7 @@ namespace NadekoBot.Services
double MessagesPerSecond { get; }
long TextChannels { get; }
long VoiceChannels { get; }
+ int GuildCount { get; }
TimeSpan GetUptime();
string GetUptimeString(string separator = ", ");
diff --git a/src/NadekoBot/Services/Impl/BotCredentials.cs b/src/NadekoBot/Services/Impl/BotCredentials.cs
index 92ae20c1..3d47a207 100644
--- a/src/NadekoBot/Services/Impl/BotCredentials.cs
+++ b/src/NadekoBot/Services/Impl/BotCredentials.cs
@@ -30,20 +30,23 @@ namespace NadekoBot.Services.Impl
public int TotalShards { get; }
public string CarbonKey { get; }
- public string credsFileName { get; } = Path.Combine(Directory.GetCurrentDirectory(), "credentials.json");
+ private readonly string _credsFileName = Path.Combine(Directory.GetCurrentDirectory(), "credentials.json");
public string PatreonAccessToken { get; }
+ public string ShardRunCommand { get; }
+ public string ShardRunArguments { get; }
+ public int ShardRunPort { get; }
public BotCredentials()
{
_log = LogManager.GetCurrentClassLogger();
try { File.WriteAllText("./credentials_example.json", JsonConvert.SerializeObject(new CredentialsModel(), Formatting.Indented)); } catch { }
- if(!File.Exists(credsFileName))
+ if(!File.Exists(_credsFileName))
_log.Warn($"credentials.json is missing. Attempting to load creds from environment variables prefixed with 'NadekoBot_'. Example is in {Path.GetFullPath("./credentials_example.json")}");
try
{
var configBuilder = new ConfigurationBuilder();
- configBuilder.AddJsonFile(credsFileName, true)
+ configBuilder.AddJsonFile(_credsFileName, true)
.AddEnvironmentVariables("NadekoBot_");
var data = configBuilder.Build();
@@ -61,13 +64,24 @@ namespace NadekoBot.Services.Impl
MashapeKey = data[nameof(MashapeKey)];
OsuApiKey = data[nameof(OsuApiKey)];
PatreonAccessToken = data[nameof(PatreonAccessToken)];
+ ShardRunCommand = data[nameof(ShardRunCommand)];
+ ShardRunArguments = data[nameof(ShardRunArguments)];
+ if (string.IsNullOrWhiteSpace(ShardRunCommand))
+ ShardRunCommand = "dotnet";
+ if (string.IsNullOrWhiteSpace(ShardRunArguments))
+ ShardRunArguments = "run -c Release -- {0} {1} {2}";
+
+ var portStr = data[nameof(ShardRunPort)];
+ if (string.IsNullOrWhiteSpace(portStr))
+ ShardRunPort = new NadekoRandom().Next(5000, 6000);
+ else
+ ShardRunPort = int.Parse(portStr);
int ts = 1;
int.TryParse(data[nameof(TotalShards)], out ts);
TotalShards = ts < 1 ? 1 : ts;
- ulong clId = 0;
- ulong.TryParse(data[nameof(ClientId)], out clId);
+ ulong.TryParse(data[nameof(ClientId)], out ulong clId);
ClientId = clId;
//var scId = data[nameof(SoundCloudClientId)];
@@ -81,7 +95,7 @@ namespace NadekoBot.Services.Impl
? "sqlite"
: dbSection["Type"],
string.IsNullOrWhiteSpace(dbSection["ConnectionString"])
- ? "Filename=./data/NadekoBot.db"
+ ? "Filename=./data/NadekoBot.db"
: dbSection["ConnectionString"]);
}
catch (Exception ex)
@@ -107,6 +121,10 @@ namespace NadekoBot.Services.Impl
public DBConfig Db { get; set; } = new DBConfig("sqlite", "Filename=./data/NadekoBot.db");
public int TotalShards { get; set; } = 1;
public string PatreonAccessToken { get; set; } = "";
+
+ public string ShardRunCommand { get; set; } = "";
+ public string ShardRunArguments { get; set; } = "";
+ public int? ShardRunPort { get; set; } = null;
}
private class DbModel
diff --git a/src/NadekoBot/Services/Impl/ImagesService.cs b/src/NadekoBot/Services/Impl/ImagesService.cs
index 4bce6148..95930464 100644
--- a/src/NadekoBot/Services/Impl/ImagesService.cs
+++ b/src/NadekoBot/Services/Impl/ImagesService.cs
@@ -47,12 +47,10 @@ namespace NadekoBot.Services.Impl
this.Reload();
}
- public TimeSpan Reload()
+ public void Reload()
{
try
{
- _log.Info("Loading images...");
- var sw = Stopwatch.StartNew();
Heads = File.ReadAllBytes(_headsPath).ToImmutableArray();
Tails = File.ReadAllBytes(_tailsPath).ToImmutableArray();
@@ -79,10 +77,6 @@ namespace NadekoBot.Services.Impl
WifeMatrix = File.ReadAllBytes(_wifeMatrixPath).ToImmutableArray();
RategirlDot = File.ReadAllBytes(_rategirlDot).ToImmutableArray();
-
- sw.Stop();
- _log.Info($"Images loaded after {sw.Elapsed.TotalSeconds:F2}s!");
- return sw.Elapsed;
}
catch (Exception ex)
{
diff --git a/src/NadekoBot/Services/Impl/StatsService.cs b/src/NadekoBot/Services/Impl/StatsService.cs
index bcd4a092..07d706e1 100644
--- a/src/NadekoBot/Services/Impl/StatsService.cs
+++ b/src/NadekoBot/Services/Impl/StatsService.cs
@@ -13,11 +13,11 @@ namespace NadekoBot.Services.Impl
{
public class StatsService : IStatsService
{
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly IBotCredentials _creds;
private readonly DateTime _started;
- public const string BotVersion = "1.43";
+ public const string BotVersion = "1.5";
public string Author => "Kwoth#2560";
public string Library => "Discord.Net";
@@ -35,11 +35,16 @@ namespace NadekoBot.Services.Impl
public long CommandsRan => Interlocked.Read(ref _commandsRan);
private readonly Timer _carbonitexTimer;
+ private readonly ShardsCoordinator _sc;
- public StatsService(DiscordShardedClient client, CommandHandler cmdHandler, IBotCredentials creds)
+ public int GuildCount =>
+ _sc?.GuildCount ?? _client.Guilds.Count();
+
+ public StatsService(DiscordSocketClient client, CommandHandler cmdHandler, IBotCredentials creds, ShardsCoordinator sc)
{
_client = client;
_creds = creds;
+ _sc = sc;
_started = DateTime.UtcNow;
_client.MessageReceived += _ => Task.FromResult(Interlocked.Increment(ref _messageCounter));
@@ -121,31 +126,34 @@ namespace NadekoBot.Services.Impl
return Task.CompletedTask;
};
- _carbonitexTimer = new Timer(async (state) =>
+ if (sc != null)
{
- if (string.IsNullOrWhiteSpace(_creds.CarbonKey))
- return;
- try
+ _carbonitexTimer = new Timer(async (state) =>
{
- using (var http = new HttpClient())
+ if (string.IsNullOrWhiteSpace(_creds.CarbonKey))
+ return;
+ try
{
- using (var content = new FormUrlEncodedContent(
- new Dictionary {
- { "servercount", _client.Guilds.Count.ToString() },
- { "key", _creds.CarbonKey }}))
+ using (var http = new HttpClient())
{
- content.Headers.Clear();
- content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
+ using (var content = new FormUrlEncodedContent(
+ new Dictionary {
+ { "servercount", sc.GuildCount.ToString() },
+ { "key", _creds.CarbonKey }}))
+ {
+ content.Headers.Clear();
+ content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
- await http.PostAsync("https://www.carbonitex.net/discord/data/botdata.php", content).ConfigureAwait(false);
+ await http.PostAsync("https://www.carbonitex.net/discord/data/botdata.php", content).ConfigureAwait(false);
+ }
}
}
- }
- catch
- {
- // ignored
- }
- }, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
+ catch
+ {
+ // ignored
+ }
+ }, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
+ }
}
public void Initialize()
diff --git a/src/NadekoBot/Services/LogSetup.cs b/src/NadekoBot/Services/LogSetup.cs
new file mode 100644
index 00000000..159b447e
--- /dev/null
+++ b/src/NadekoBot/Services/LogSetup.cs
@@ -0,0 +1,28 @@
+using NLog;
+using NLog.Config;
+using NLog.Targets;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NadekoBot.Services
+{
+ public class LogSetup
+ {
+ public static void SetupLogger()
+ {
+ var logConfig = new LoggingConfiguration();
+ var consoleTarget = new ColoredConsoleTarget()
+ {
+ Layout = @"${date:format=HH\:mm\:ss} ${logger} | ${message}"
+ };
+ logConfig.AddTarget("Console", consoleTarget);
+
+ logConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget));
+
+ LogManager.Configuration = logConfig;
+ }
+ }
+}
diff --git a/src/NadekoBot/Services/Permissions/CmdCdService.cs b/src/NadekoBot/Services/Permissions/CmdCdService.cs
index 0a1cbf47..7a44a292 100644
--- a/src/NadekoBot/Services/Permissions/CmdCdService.cs
+++ b/src/NadekoBot/Services/Permissions/CmdCdService.cs
@@ -21,7 +21,7 @@ namespace NadekoBot.Services.Permissions
v => new ConcurrentHashSet(v.CommandCooldowns)));
}
- public Task TryBlockLate(DiscordShardedClient client, IUserMessage msg, IGuild guild,
+ public Task TryBlockLate(DiscordSocketClient client, IUserMessage msg, IGuild guild,
IMessageChannel channel, IUser user, string moduleName, string commandName)
{
if (guild == null)
diff --git a/src/NadekoBot/Services/Permissions/FilterService.cs b/src/NadekoBot/Services/Permissions/FilterService.cs
index 0d3513ad..a6d97d0d 100644
--- a/src/NadekoBot/Services/Permissions/FilterService.cs
+++ b/src/NadekoBot/Services/Permissions/FilterService.cs
@@ -41,7 +41,7 @@ namespace NadekoBot.Services.Permissions
return words;
}
- public FilterService(DiscordShardedClient _client, IEnumerable gcs)
+ public FilterService(DiscordSocketClient _client, IEnumerable gcs)
{
_log = LogManager.GetCurrentClassLogger();
diff --git a/src/NadekoBot/Services/Permissions/GlobalPermissionService.cs b/src/NadekoBot/Services/Permissions/GlobalPermissionService.cs
index 633a81a3..419f77f3 100644
--- a/src/NadekoBot/Services/Permissions/GlobalPermissionService.cs
+++ b/src/NadekoBot/Services/Permissions/GlobalPermissionService.cs
@@ -19,7 +19,7 @@ namespace NadekoBot.Services.Permissions
BlockedCommands = new ConcurrentHashSet(bc.BlockedCommands.Select(x => x.Name));
}
- public async Task TryBlockLate(DiscordShardedClient client, IUserMessage msg, IGuild guild, IMessageChannel channel, IUser user, string moduleName, string commandName)
+ public async Task TryBlockLate(DiscordSocketClient client, IUserMessage msg, IGuild guild, IMessageChannel channel, IUser user, string moduleName, string commandName)
{
await Task.Yield();
commandName = commandName.ToLowerInvariant();
diff --git a/src/NadekoBot/Services/Permissions/PermissionsService.cs b/src/NadekoBot/Services/Permissions/PermissionsService.cs
index 765cb131..c4c586a9 100644
--- a/src/NadekoBot/Services/Permissions/PermissionsService.cs
+++ b/src/NadekoBot/Services/Permissions/PermissionsService.cs
@@ -1,4 +1,5 @@
-using Microsoft.EntityFrameworkCore;
+
+using Microsoft.EntityFrameworkCore;
using NadekoBot.DataStructures.ModuleBehaviors;
using NadekoBot.Services.Database.Models;
using NLog;
@@ -10,6 +11,7 @@ using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using NadekoBot.Extensions;
+using NadekoBot.Services;
namespace NadekoBot.Services.Permissions
{
@@ -18,22 +20,26 @@ namespace NadekoBot.Services.Permissions
private readonly DbService _db;
private readonly Logger _log;
private readonly CommandHandler _cmd;
+ private readonly NadekoStrings _strings;
//guildid, root permission
public ConcurrentDictionary Cache { get; } =
new ConcurrentDictionary();
- public PermissionService(DbService db, BotConfig bc, CommandHandler cmd)
+ public PermissionService(DiscordSocketClient client, DbService db, BotConfig bc, CommandHandler cmd, NadekoStrings strings)
{
_log = LogManager.GetCurrentClassLogger();
_db = db;
_cmd = cmd;
+ _strings = strings;
var sw = Stopwatch.StartNew();
- TryMigratePermissions(bc);
+ if (client.ShardId == 0)
+ TryMigratePermissions(bc);
+
using (var uow = _db.UnitOfWork)
{
- foreach (var x in uow.GuildConfigs.Permissionsv2ForAll())
+ foreach (var x in uow.GuildConfigs.Permissionsv2ForAll(client.Guilds.ToArray().Select(x => (long)x.Id).ToList()))
{
Cache.TryAdd(x.GuildId, new PermissionCache()
{
@@ -68,10 +74,9 @@ namespace NadekoBot.Services.Permissions
private void TryMigratePermissions(BotConfig bc)
{
var log = LogManager.GetCurrentClassLogger();
- using (var uow = _db.UnitOfWork)
+ if (bc.PermissionVersion <= 1)
{
- var _bc = uow.BotConfig.GetOrCreate();
- if (_bc.PermissionVersion <= 1)
+ using (var uow = _db.UnitOfWork)
{
log.Info("Permission version is 1, upgrading to 2.");
var oldCache = new ConcurrentDictionary(uow.GuildConfigs
@@ -126,9 +131,13 @@ namespace NadekoBot.Services.Permissions
log.Info("Permission migration to v2 is done.");
}
- _bc.PermissionVersion = 2;
+ bc.PermissionVersion = 2;
+ uow.Complete();
}
- if (_bc.PermissionVersion <= 2)
+ }
+ if (bc.PermissionVersion <= 2)
+ {
+ using (var uow = _db.UnitOfWork)
{
var oldPrefixes = new[] { ".", ";", "!!", "!m", "!", "+", "-", "$", ">" };
uow._context.Database.ExecuteSqlCommand(
@@ -144,9 +153,9 @@ WHERE secondaryTargetName LIKE '.%' OR
secondaryTargetName LIKE '>%' OR
secondaryTargetName LIKE '-%' OR
secondaryTargetName LIKE '!%';");
- _bc.PermissionVersion = 3;
+ bc.PermissionVersion = 3;
+ uow.Complete();
}
- uow.Complete();
}
}
@@ -183,7 +192,7 @@ WHERE secondaryTargetName LIKE '.%' OR
});
}
- public async Task TryBlockLate(DiscordShardedClient client, IUserMessage msg, IGuild guild, IMessageChannel channel, IUser user, string moduleName, string commandName)
+ public async Task TryBlockLate(DiscordSocketClient client, IUserMessage msg, IGuild guild, IMessageChannel channel, IUser user, string moduleName, string commandName)
{
await Task.Yield();
if (guild == null)
@@ -198,11 +207,9 @@ WHERE secondaryTargetName LIKE '.%' OR
PermissionCache pc = GetCache(guild.Id);
if (!resetCommand && !pc.Permissions.CheckPermissions(msg, commandName, moduleName, out int index))
{
- var returnMsg = $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(_cmd.GetPrefix(guild), (SocketGuild)guild)}** is preventing this action.";
if (pc.Verbose)
- try { await channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
+ try { await channel.SendErrorAsync(_strings.GetText("trigger", guild.Id, "Permissions".ToLowerInvariant(), index + 1, Format.Bold(pc.Permissions[index].GetCommand(_cmd.GetPrefix(guild), (SocketGuild)guild)))).ConfigureAwait(false); } catch { }
return true;
- //return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg));
}
@@ -215,7 +222,6 @@ WHERE secondaryTargetName LIKE '.%' OR
if (pc.Verbose)
try { await channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
return true;
- //return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"You need the **{pc.PermRole}** role in order to use permission commands."));
}
}
}
diff --git a/src/NadekoBot/Services/Searches/AnimeSearchService.cs b/src/NadekoBot/Services/Searches/AnimeSearchService.cs
index 71820506..a4187da3 100644
--- a/src/NadekoBot/Services/Searches/AnimeSearchService.cs
+++ b/src/NadekoBot/Services/Searches/AnimeSearchService.cs
@@ -1,52 +1,18 @@
using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using NLog;
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Net.Http;
-using System.Text;
-using System.Threading;
using System.Threading.Tasks;
namespace NadekoBot.Services.Searches
{
public class AnimeSearchService
{
- private readonly Timer _anilistTokenRefresher;
private readonly Logger _log;
- private static string anilistToken { get; set; }
-
public AnimeSearchService()
{
_log = LogManager.GetCurrentClassLogger();
- _anilistTokenRefresher = new Timer(async (state) =>
- {
- try
- {
- var headers = new Dictionary
- {
- {"grant_type", "client_credentials"},
- {"client_id", "kwoth-w0ki9"},
- {"client_secret", "Qd6j4FIAi1ZK6Pc7N7V4Z"},
- };
-
- using (var http = new HttpClient())
- {
- //http.AddFakeHeaders();
- http.DefaultRequestHeaders.Clear();
- var formContent = new FormUrlEncodedContent(headers);
- var response = await http.PostAsync("https://anilist.co/api/auth/access_token", formContent).ConfigureAwait(false);
- var stringContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
- anilistToken = JObject.Parse(stringContent)["access_token"].ToString();
- }
- }
- catch
- {
- // ignored
- }
- }, null, TimeSpan.FromSeconds(0), TimeSpan.FromMinutes(29));
}
public async Task GetAnimeData(string query)
@@ -56,19 +22,15 @@ namespace NadekoBot.Services.Searches
try
{
- var link = "http://anilist.co/api/anime/search/" + Uri.EscapeUriString(query);
+ var link = "https://aniapi.nadekobot.me/anime/" + Uri.EscapeDataString(query.Replace("/", " "));
using (var http = new HttpClient())
{
- var res = await http.GetStringAsync(link + $"?access_token={anilistToken}").ConfigureAwait(false);
- var smallObj = JArray.Parse(res)[0];
- var aniData = await http.GetStringAsync("http://anilist.co/api/anime/" + smallObj["id"] + $"?access_token={anilistToken}").ConfigureAwait(false);
-
- return await Task.Run(() => { try { return JsonConvert.DeserializeObject(aniData); } catch { return null; } }).ConfigureAwait(false);
+ var res = await http.GetStringAsync(link).ConfigureAwait(false);
+ return JsonConvert.DeserializeObject(res);
}
}
- catch (Exception ex)
+ catch
{
- _log.Warn(ex, "Failed anime search for {0}", query);
return null;
}
}
@@ -79,18 +41,16 @@ namespace NadekoBot.Services.Searches
throw new ArgumentNullException(nameof(query));
try
{
+
+ var link = "https://aniapi.nadekobot.me/manga/" + Uri.EscapeDataString(query.Replace("/", " "));
using (var http = new HttpClient())
{
- var res = await http.GetStringAsync("http://anilist.co/api/manga/search/" + Uri.EscapeUriString(query) + $"?access_token={anilistToken}").ConfigureAwait(false);
- var smallObj = JArray.Parse(res)[0];
- var aniData = await http.GetStringAsync("http://anilist.co/api/manga/" + smallObj["id"] + $"?access_token={anilistToken}").ConfigureAwait(false);
-
- return await Task.Run(() => { try { return JsonConvert.DeserializeObject(aniData); } catch { return null; } }).ConfigureAwait(false);
+ var res = await http.GetStringAsync(link).ConfigureAwait(false);
+ return JsonConvert.DeserializeObject(res);
}
}
- catch (Exception ex)
+ catch
{
- _log.Warn(ex, "Failed anime search for {0}", query);
return null;
}
}
diff --git a/src/NadekoBot/Services/Searches/SearchesService.cs b/src/NadekoBot/Services/Searches/SearchesService.cs
index 864c9522..8c98a22e 100644
--- a/src/NadekoBot/Services/Searches/SearchesService.cs
+++ b/src/NadekoBot/Services/Searches/SearchesService.cs
@@ -15,7 +15,7 @@ namespace NadekoBot.Services.Searches
{
public class SearchesService
{
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly IGoogleApiService _google;
private readonly DbService _db;
private readonly Logger _log;
@@ -31,7 +31,7 @@ namespace NadekoBot.Services.Searches
public List WowJokes { get; } = new List();
public List MagicItems { get; } = new List();
- public SearchesService(DiscordShardedClient client, IGoogleApiService google, DbService db)
+ public SearchesService(DiscordSocketClient client, IGoogleApiService google, DbService db)
{
_client = client;
_google = google;
diff --git a/src/NadekoBot/Services/Searches/StreamNotificationService.cs b/src/NadekoBot/Services/Searches/StreamNotificationService.cs
index 3fdbb9ac..c077e4e1 100644
--- a/src/NadekoBot/Services/Searches/StreamNotificationService.cs
+++ b/src/NadekoBot/Services/Searches/StreamNotificationService.cs
@@ -1,6 +1,8 @@
using Discord;
using Discord.WebSocket;
using NadekoBot.Extensions;
+using NadekoBot.Services;
+using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models;
using Newtonsoft.Json;
using System;
@@ -20,10 +22,10 @@ namespace NadekoBot.Services.Searches
private readonly ConcurrentDictionary _cachedStatuses = new ConcurrentDictionary();
private readonly DbService _db;
- private readonly DiscordShardedClient _client;
+ private readonly DiscordSocketClient _client;
private readonly NadekoStrings _strings;
- public StreamNotificationService(DbService db, DiscordShardedClient client, NadekoStrings strings)
+ public StreamNotificationService(DbService db, DiscordSocketClient client, NadekoStrings strings)
{
_db = db;
_client = client;
@@ -35,7 +37,7 @@ namespace NadekoBot.Services.Searches
IEnumerable streams;
using (var uow = _db.UnitOfWork)
{
- streams = uow.GuildConfigs.GetAllFollowedStreams();
+ streams = uow.GuildConfigs.GetAllFollowedStreams(client.Guilds.Select(x => (long)x.Id).ToList());
}
await Task.WhenAll(streams.Select(async fs =>
@@ -73,7 +75,7 @@ namespace NadekoBot.Services.Searches
}));
firstStreamNotifPass = false;
- }, null, TimeSpan.Zero, TimeSpan.FromSeconds(60));
+ }, null, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(60));
}
public async Task GetStreamStatus(FollowedStream stream, bool checkCache = true)
diff --git a/src/NadekoBot/Services/Utility/ConverterService.cs b/src/NadekoBot/Services/Utility/ConverterService.cs
index 38fc7f9a..40f7fafa 100644
--- a/src/NadekoBot/Services/Utility/ConverterService.cs
+++ b/src/NadekoBot/Services/Utility/ConverterService.cs
@@ -1,4 +1,6 @@
-using NadekoBot.Services.Database.Models;
+using Discord.WebSocket;
+using NadekoBot.Services;
+using NadekoBot.Services.Database.Models;
using Newtonsoft.Json;
using NLog;
using System;
@@ -13,24 +15,26 @@ namespace NadekoBot.Services.Utility
{
public class ConverterService
{
- public List