Merge branch 'shard-process' into 1.4
This commit is contained in:
commit
61a96d9c4f
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,5 +1,6 @@
|
|||||||
#Manually added files
|
#Manually added files
|
||||||
|
|
||||||
|
patreon_rewards.json
|
||||||
command_errors*.txt
|
command_errors*.txt
|
||||||
|
|
||||||
src/NadekoBot/Command Errors*.txt
|
src/NadekoBot/Command Errors*.txt
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26430.6
|
VisualStudioVersion = 15.0.26430.12
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}"
|
||||||
EndProject
|
EndProject
|
||||||
|
@ -18,7 +18,8 @@ If you do not see `credentials.json` you will need to rename `credentials_exampl
|
|||||||
"OsuApiKey": "4c8c8fdff8e1234581725db27fd140a7d93320d6",
|
"OsuApiKey": "4c8c8fdff8e1234581725db27fd140a7d93320d6",
|
||||||
"PatreonAccessToken": "",
|
"PatreonAccessToken": "",
|
||||||
"Db": null,
|
"Db": null,
|
||||||
"TotalShards": 1
|
"TotalShards": 1,
|
||||||
|
"ShardRunCommand": ""
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
-----
|
-----
|
||||||
@ -155,7 +156,20 @@ It should look like:
|
|||||||
- **TotalShards**
|
- **TotalShards**
|
||||||
- Required if the bot will be connected to more than 1500 servers.
|
- 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.
|
- 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
|
## DB files
|
||||||
@ -163,6 +177,7 @@ It should look like:
|
|||||||
Nadeko saves all the settings and infomations in `NadekoBot.db` file here:
|
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/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/).
|
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.*
|
*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.*
|
||||||
|
@ -13,6 +13,6 @@ namespace NadekoBot.DataStructures.ModuleBehaviors
|
|||||||
/// Try to execute some logic within some module's service.
|
/// Try to execute some logic within some module's service.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Whether it should block other command executions after it.</returns>
|
/// <returns>Whether it should block other command executions after it.</returns>
|
||||||
Task<bool> TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage msg);
|
Task<bool> TryExecuteEarly(DiscordSocketClient client, IGuild guild, IUserMessage msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ namespace NadekoBot.DataStructures.ModuleBehaviors
|
|||||||
{
|
{
|
||||||
public interface ILateBlocker
|
public interface ILateBlocker
|
||||||
{
|
{
|
||||||
Task<bool> TryBlockLate(DiscordShardedClient client, IUserMessage msg, IGuild guild,
|
Task<bool> TryBlockLate(DiscordSocketClient client, IUserMessage msg, IGuild guild,
|
||||||
IMessageChannel channel, IUser user, string moduleName, string commandName);
|
IMessageChannel channel, IUser user, string moduleName, string commandName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,6 @@ namespace NadekoBot.DataStructures.ModuleBehaviors
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ILateExecutor
|
public interface ILateExecutor
|
||||||
{
|
{
|
||||||
Task LateExecute(DiscordShardedClient client, IGuild guild, IUserMessage msg);
|
Task LateExecute(DiscordSocketClient client, IGuild guild, IUserMessage msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
22
src/NadekoBot/DataStructures/Shard0Precondition.cs
Normal file
22
src/NadekoBot/DataStructures/Shard0Precondition.cs
Normal file
@ -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<PreconditionResult> 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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
src/NadekoBot/DataStructures/ShardCom/IShardComMessage.cs
Normal file
16
src/NadekoBot/DataStructures/ShardCom/IShardComMessage.cs
Normal file
@ -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; }
|
||||||
|
}
|
||||||
|
}
|
29
src/NadekoBot/DataStructures/ShardCom/ShardComClient.cs
Normal file
29
src/NadekoBot/DataStructures/ShardCom/ShardComClient.cs
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
src/NadekoBot/DataStructures/ShardCom/ShardComServer.cs
Normal file
40
src/NadekoBot/DataStructures/ShardCom/ShardComServer.cs
Normal file
@ -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<ShardComMessage>(data));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_client.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public event Func<ShardComMessage, Task> OnDataReceived = delegate { return Task.CompletedTask; };
|
||||||
|
}
|
||||||
|
}
|
@ -7,9 +7,9 @@ namespace NadekoBot.TypeReaders
|
|||||||
{
|
{
|
||||||
public class GuildTypeReader : TypeReader
|
public class GuildTypeReader : TypeReader
|
||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
public GuildTypeReader(DiscordShardedClient client)
|
public GuildTypeReader(DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
|
@ -126,17 +126,17 @@ namespace NadekoBot.Modules.Administration
|
|||||||
{
|
{
|
||||||
var guser = (IGuildUser)Context.User;
|
var guser = (IGuildUser)Context.User;
|
||||||
|
|
||||||
var userRoles = user.GetRoles();
|
var userRoles = user.GetRoles().Except(new[] { guser.Guild.EveryoneRole });
|
||||||
if (guser.Id != Context.Guild.OwnerId &&
|
if (user.Id == Context.Guild.OwnerId || (Context.User.Id != Context.Guild.OwnerId && guser.GetRoles().Max(x => x.Position) <= userRoles.Max(x => x.Position)))
|
||||||
(user.Id == Context.Guild.OwnerId || guser.GetRoles().Max(x => x.Position) <= userRoles.Max(x => x.Position)))
|
|
||||||
return;
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await user.RemoveRolesAsync(userRoles).ConfigureAwait(false);
|
await user.RemoveRolesAsync(userRoles).ConfigureAwait(false);
|
||||||
await ReplyConfirmLocalized("rar", Format.Bold(user.ToString())).ConfigureAwait(false);
|
await ReplyConfirmLocalized("rar", Format.Bold(user.ToString())).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine(ex);
|
||||||
await ReplyErrorLocalized("rar_err").ConfigureAwait(false);
|
await ReplyErrorLocalized("rar_err").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
await uow.CompleteAsync();
|
await uow.CompleteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
await Context.Channel.SendPaginatedConfirmAsync((DiscordShardedClient)Context.Client, page, (curPage) =>
|
await Context.Channel.SendPaginatedConfirmAsync((DiscordSocketClient)Context.Client, page, (curPage) =>
|
||||||
{
|
{
|
||||||
return new EmbedBuilder()
|
return new EmbedBuilder()
|
||||||
.WithTitle(GetText("self_assign_list", roleCnt))
|
.WithTitle(GetText("self_assign_list", roleCnt))
|
||||||
|
@ -13,6 +13,8 @@ using NadekoBot.Services;
|
|||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NadekoBot.Services.Administration;
|
using NadekoBot.Services.Administration;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using NadekoBot.DataStructures;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Administration
|
namespace NadekoBot.Modules.Administration
|
||||||
{
|
{
|
||||||
@ -25,10 +27,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
private static readonly object _locker = new object();
|
private static readonly object _locker = new object();
|
||||||
private readonly SelfService _service;
|
private readonly SelfService _service;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
|
|
||||||
public SelfCommands(DbService db, SelfService service, DiscordShardedClient client,
|
public SelfCommands(DbService db, SelfService service, DiscordSocketClient client,
|
||||||
IImagesService images)
|
IImagesService images)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
@ -204,28 +206,28 @@ namespace NadekoBot.Modules.Administration
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
//todo 2 shard commands
|
||||||
[OwnerOnly]
|
//[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task ConnectShard(int shardid)
|
//[Shard0Precondition]
|
||||||
{
|
//[OwnerOnly]
|
||||||
var shard = _client.GetShard(shardid);
|
//public async Task RestartShard(int shardid)
|
||||||
|
//{
|
||||||
if (shard == null)
|
// if (shardid == 0 || shardid > b)
|
||||||
{
|
// {
|
||||||
await ReplyErrorLocalized("no_shard_id").ConfigureAwait(false);
|
// await ReplyErrorLocalized("no_shard_id").ConfigureAwait(false);
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
await ReplyConfirmLocalized("shard_reconnecting", Format.Bold("#" + shardid)).ConfigureAwait(false);
|
// await ReplyConfirmLocalized("shard_reconnecting", Format.Bold("#" + shardid)).ConfigureAwait(false);
|
||||||
await shard.StartAsync().ConfigureAwait(false);
|
// await shard.StartAsync().ConfigureAwait(false);
|
||||||
await ReplyConfirmLocalized("shard_reconnected", Format.Bold("#" + shardid)).ConfigureAwait(false);
|
// await ReplyConfirmLocalized("shard_reconnected", Format.Bold("#" + shardid)).ConfigureAwait(false);
|
||||||
}
|
// }
|
||||||
catch (Exception ex)
|
// catch (Exception ex)
|
||||||
{
|
// {
|
||||||
_log.Warn(ex);
|
// _log.Warn(ex);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
@ -417,8 +419,10 @@ namespace NadekoBot.Modules.Administration
|
|||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task ReloadImages()
|
public async Task ReloadImages()
|
||||||
{
|
{
|
||||||
var time = _images.Reload();
|
var sw = Stopwatch.StartNew();
|
||||||
await ReplyConfirmLocalized("images_loaded", time.TotalSeconds.ToString("F3")).ConfigureAwait(false);
|
_images.Reload();
|
||||||
|
sw.Stop();
|
||||||
|
await ReplyConfirmLocalized("images_loaded", sw.Elapsed.TotalSeconds.ToString("F3")).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UserStatus SettableUserStatusToUserStatus(SettableUserStatus sus)
|
private static UserStatus SettableUserStatusToUserStatus(SettableUserStatus sus)
|
||||||
|
@ -36,7 +36,7 @@ namespace NadekoBot.Modules.Administration
|
|||||||
.ToArray();
|
.ToArray();
|
||||||
var timezonesPerPage = 20;
|
var timezonesPerPage = 20;
|
||||||
|
|
||||||
await Context.Channel.SendPaginatedConfirmAsync((DiscordShardedClient)Context.Client, page,
|
await Context.Channel.SendPaginatedConfirmAsync((DiscordSocketClient)Context.Client, page,
|
||||||
(curPage) => new EmbedBuilder()
|
(curPage) => new EmbedBuilder()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithTitle(GetText("timezones_available"))
|
.WithTitle(GetText("timezones_available"))
|
||||||
|
@ -17,10 +17,10 @@ namespace NadekoBot.Modules.CustomReactions
|
|||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly CustomReactionsService _crs;
|
private readonly CustomReactionsService _crs;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
public CustomReactions(IBotCredentials creds, DbService db, CustomReactionsService crs,
|
public CustomReactions(IBotCredentials creds, DbService db, CustomReactionsService crs,
|
||||||
DiscordShardedClient client)
|
DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -22,12 +22,12 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyService _cs;
|
private readonly CurrencyService _cs;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
|
|
||||||
public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces { get; } = new ConcurrentDictionary<ulong, AnimalRace>();
|
public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces { get; } = new ConcurrentDictionary<ulong, AnimalRace>();
|
||||||
|
|
||||||
public AnimalRacing(BotConfig bc, CurrencyService cs, DiscordShardedClient client)
|
public AnimalRacing(BotConfig bc, CurrencyService cs, DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_cs = cs;
|
_cs = cs;
|
||||||
@ -82,14 +82,14 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
private readonly ITextChannel _raceChannel;
|
private readonly ITextChannel _raceChannel;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyService _cs;
|
private readonly CurrencyService _cs;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly ILocalization _localization;
|
private readonly ILocalization _localization;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
|
|
||||||
public bool Started { get; private set; }
|
public bool Started { get; private set; }
|
||||||
|
|
||||||
public AnimalRace(ulong serverId, ITextChannel channel, string prefix, BotConfig bc,
|
public AnimalRace(ulong serverId, ITextChannel channel, string prefix, BotConfig bc,
|
||||||
CurrencyService cs, DiscordShardedClient client, ILocalization localization,
|
CurrencyService cs, DiscordSocketClient client, ILocalization localization,
|
||||||
NadekoStrings strings)
|
NadekoStrings strings)
|
||||||
{
|
{
|
||||||
_prefix = prefix;
|
_prefix = prefix;
|
||||||
|
@ -34,11 +34,11 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
private string _secretCode = string.Empty;
|
private string _secretCode = string.Empty;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyService _cs;
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
public CurrencyEvents(DiscordShardedClient client, BotConfig bc, CurrencyService cs)
|
public CurrencyEvents(DiscordSocketClient client, BotConfig bc, CurrencyService cs)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
@ -151,7 +151,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
{
|
{
|
||||||
private readonly ConcurrentHashSet<ulong> _flowerReactionAwardedUsers = new ConcurrentHashSet<ulong>();
|
private readonly ConcurrentHashSet<ulong> _flowerReactionAwardedUsers = new ConcurrentHashSet<ulong>();
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly CurrencyService _cs;
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
private IUserMessage StartingMessage { get; set; }
|
private IUserMessage StartingMessage { get; set; }
|
||||||
@ -159,7 +159,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
private CancellationTokenSource Source { get; }
|
private CancellationTokenSource Source { get; }
|
||||||
private CancellationToken CancelToken { get; }
|
private CancellationToken CancelToken { get; }
|
||||||
|
|
||||||
public FlowerReactionEvent(DiscordShardedClient client, CurrencyService cs)
|
public FlowerReactionEvent(DiscordSocketClient client, CurrencyService cs)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly CurrencyService _cs;
|
private readonly CurrencyService _cs;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
public enum Role
|
public enum Role
|
||||||
{
|
{
|
||||||
@ -34,7 +34,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
List
|
List
|
||||||
}
|
}
|
||||||
|
|
||||||
public FlowerShop(BotConfig bc, DbService db, CurrencyService cs, DiscordShardedClient client)
|
public FlowerShop(BotConfig bc, DbService db, CurrencyService cs, DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
|
@ -20,12 +20,12 @@ namespace NadekoBot.Modules.Games
|
|||||||
[Group]
|
[Group]
|
||||||
public class Acropobia : NadekoSubmodule
|
public class Acropobia : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
//channelId, game
|
//channelId, game
|
||||||
public static ConcurrentDictionary<ulong, AcrophobiaGame> AcrophobiaGames { get; } = new ConcurrentDictionary<ulong, AcrophobiaGame>();
|
public static ConcurrentDictionary<ulong, AcrophobiaGame> AcrophobiaGames { get; } = new ConcurrentDictionary<ulong, AcrophobiaGame>();
|
||||||
|
|
||||||
public Acropobia(DiscordShardedClient client)
|
public Acropobia(DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
@ -86,10 +86,10 @@ namespace NadekoBot.Modules.Games
|
|||||||
//text, votes
|
//text, votes
|
||||||
private readonly ConcurrentDictionary<string, int> _votes = new ConcurrentDictionary<string, int>();
|
private readonly ConcurrentDictionary<string, int> _votes = new ConcurrentDictionary<string, int>();
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly NadekoStrings _strings;
|
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();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -56,7 +56,7 @@ namespace NadekoBot.Modules.Games.Hangman
|
|||||||
public class HangmanGame: IDisposable
|
public class HangmanGame: IDisposable
|
||||||
{
|
{
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
public IMessageChannel GameChannel { get; }
|
public IMessageChannel GameChannel { get; }
|
||||||
public HashSet<char> Guesses { get; } = new HashSet<char>();
|
public HashSet<char> Guesses { get; } = new HashSet<char>();
|
||||||
@ -82,7 +82,7 @@ namespace NadekoBot.Modules.Games.Hangman
|
|||||||
|
|
||||||
public event Action<HangmanGame> OnEnded;
|
public event Action<HangmanGame> OnEnded;
|
||||||
|
|
||||||
public HangmanGame(DiscordShardedClient client, IMessageChannel channel, string type)
|
public HangmanGame(DiscordSocketClient client, IMessageChannel channel, string type)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -15,9 +15,9 @@ namespace NadekoBot.Modules.Games
|
|||||||
[Group]
|
[Group]
|
||||||
public class HangmanCommands : NadekoSubmodule
|
public class HangmanCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
public HangmanCommands(DiscordShardedClient client)
|
public HangmanCommands(DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
|
@ -20,13 +20,13 @@ namespace NadekoBot.Modules.Games.Models
|
|||||||
public bool IsActive { get; private set; }
|
public bool IsActive { get; private set; }
|
||||||
private readonly Stopwatch sw;
|
private readonly Stopwatch sw;
|
||||||
private readonly List<ulong> finishedUserIds;
|
private readonly List<ulong> finishedUserIds;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly GamesService _games;
|
private readonly GamesService _games;
|
||||||
private readonly string _prefix;
|
private readonly string _prefix;
|
||||||
|
|
||||||
private Logger _log { get; }
|
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();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_games = games;
|
_games = games;
|
||||||
|
@ -116,7 +116,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
using (var uow = _db.UnitOfWork)
|
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 };
|
var toAdd = new GCChannelId() { ChannelId = channel.Id };
|
||||||
if (!guildConfig.GenerateCurrencyChannelIds.Contains(toAdd))
|
if (!guildConfig.GenerateCurrencyChannelIds.Contains(toAdd))
|
||||||
|
@ -13,10 +13,10 @@ namespace NadekoBot.Modules.Games
|
|||||||
[Group]
|
[Group]
|
||||||
public class PollCommands : NadekoSubmodule
|
public class PollCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly PollService _polls;
|
private readonly PollService _polls;
|
||||||
|
|
||||||
public PollCommands(DiscordShardedClient client, PollService polls)
|
public PollCommands(DiscordSocketClient client, PollService polls)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_polls = polls;
|
_polls = polls;
|
||||||
@ -26,13 +26,7 @@ namespace NadekoBot.Modules.Games
|
|||||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public Task Poll([Remainder] string arg = null)
|
public Task Poll([Remainder] string arg = null)
|
||||||
=> InternalStartPoll(arg, false);
|
=> InternalStartPoll(arg);
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
|
||||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
|
||||||
[RequireContext(ContextType.Guild)]
|
|
||||||
public Task PublicPoll([Remainder] string arg = null)
|
|
||||||
=> InternalStartPoll(arg, true);
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
@ -45,9 +39,9 @@ namespace NadekoBot.Modules.Games
|
|||||||
await Context.Channel.EmbedAsync(poll.GetStats(GetText("current_poll_results")));
|
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);
|
await ReplyErrorLocalized("poll_already_running").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@ namespace NadekoBot.Modules.Games
|
|||||||
{
|
{
|
||||||
public static ConcurrentDictionary<ulong, TypingGame> RunningContests = new ConcurrentDictionary<ulong, TypingGame>();
|
public static ConcurrentDictionary<ulong, TypingGame> RunningContests = new ConcurrentDictionary<ulong, TypingGame>();
|
||||||
private readonly GamesService _games;
|
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;
|
_games = games;
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -21,9 +21,9 @@ namespace NadekoBot.Modules.Games
|
|||||||
private static readonly Dictionary<ulong, TicTacToe> _games = new Dictionary<ulong, TicTacToe>();
|
private static readonly Dictionary<ulong, TicTacToe> _games = new Dictionary<ulong, TicTacToe>();
|
||||||
|
|
||||||
private readonly SemaphoreSlim _sem = new SemaphoreSlim(1, 1);
|
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;
|
_client = client;
|
||||||
}
|
}
|
||||||
@ -87,9 +87,9 @@ namespace NadekoBot.Modules.Games
|
|||||||
private IUserMessage _previousMessage;
|
private IUserMessage _previousMessage;
|
||||||
private Timer _timeoutTimer;
|
private Timer _timeoutTimer;
|
||||||
private readonly NadekoStrings _strings;
|
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;
|
_channel = channel;
|
||||||
_strings = strings;
|
_strings = strings;
|
||||||
|
@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
private readonly SemaphoreSlim _guessLock = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim _guessLock = new SemaphoreSlim(1, 1);
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly CurrencyService _cs;
|
private readonly CurrencyService _cs;
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ namespace NadekoBot.Modules.Games.Trivia
|
|||||||
|
|
||||||
public int WinRequirement { get; }
|
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,
|
CurrencyService cs, IGuild guild, ITextChannel channel,
|
||||||
bool showHints, int winReq, bool isPokemon)
|
bool showHints, int winReq, bool isPokemon)
|
||||||
{
|
{
|
||||||
|
@ -18,12 +18,12 @@ namespace NadekoBot.Modules.Games
|
|||||||
public class TriviaCommands : NadekoSubmodule
|
public class TriviaCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly CurrencyService _cs;
|
private readonly CurrencyService _cs;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
|
|
||||||
public static ConcurrentDictionary<ulong, TriviaGame> RunningTrivias { get; } = new ConcurrentDictionary<ulong, TriviaGame>();
|
public static ConcurrentDictionary<ulong, TriviaGame> RunningTrivias { get; } = new ConcurrentDictionary<ulong, TriviaGame>();
|
||||||
|
|
||||||
public TriviaCommands(DiscordShardedClient client, BotConfig bc, CurrencyService cs)
|
public TriviaCommands(DiscordSocketClient client, BotConfig bc, CurrencyService cs)
|
||||||
{
|
{
|
||||||
_cs = cs;
|
_cs = cs;
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -155,8 +155,8 @@ namespace NadekoBot.Modules.Help
|
|||||||
public async Task Guide()
|
public async Task Guide()
|
||||||
{
|
{
|
||||||
await ConfirmLocalized("guide",
|
await ConfirmLocalized("guide",
|
||||||
"http://nadekobot.readthedocs.io/en/latest/Commands%20List/",
|
"http://nadekobot.readthedocs.io/en/1.3x/Commands%20List/",
|
||||||
"http://nadekobot.readthedocs.io/en/latest/").ConfigureAwait(false);
|
"http://nadekobot.readthedocs.io/en/1.3x/").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
@ -22,12 +22,12 @@ namespace NadekoBot.Modules.Music
|
|||||||
public class Music : NadekoTopLevelModule
|
public class Music : NadekoTopLevelModule
|
||||||
{
|
{
|
||||||
private static MusicService _music;
|
private static MusicService _music;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private readonly IGoogleApiService _google;
|
private readonly IGoogleApiService _google;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public Music(DiscordShardedClient client, IBotCredentials creds, IGoogleApiService google,
|
public Music(DiscordSocketClient client, IBotCredentials creds, IGoogleApiService google,
|
||||||
DbService db, MusicService music)
|
DbService db, MusicService music)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -87,12 +87,11 @@ namespace NadekoBot.Modules
|
|||||||
return Context.Channel.SendConfirmAsync(Context.User.Mention + " " + text);
|
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<string> GetUserInputAsync(ulong userId, ulong channelId)
|
public async Task<string> GetUserInputAsync(ulong userId, ulong channelId)
|
||||||
{
|
{
|
||||||
var userInputTask = new TaskCompletionSource<string>();
|
var userInputTask = new TaskCompletionSource<string>();
|
||||||
var dsc = (DiscordShardedClient)Context.Client;
|
var dsc = (DiscordSocketClient)Context.Client;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dsc.MessageReceived += MessageReceived;
|
dsc.MessageReceived += MessageReceived;
|
||||||
|
@ -195,7 +195,7 @@ namespace NadekoBot.Modules.Permissions
|
|||||||
|
|
||||||
var fws = fwHash.ToArray();
|
var fws = fwHash.ToArray();
|
||||||
|
|
||||||
await channel.SendPaginatedConfirmAsync((DiscordShardedClient)Context.Client,
|
await channel.SendPaginatedConfirmAsync((DiscordSocketClient)Context.Client,
|
||||||
page,
|
page,
|
||||||
(curPage) =>
|
(curPage) =>
|
||||||
new EmbedBuilder()
|
new EmbedBuilder()
|
||||||
|
@ -21,9 +21,9 @@ namespace NadekoBot.Modules.Utility
|
|||||||
{
|
{
|
||||||
private readonly CommandMapService _service;
|
private readonly CommandMapService _service;
|
||||||
private readonly DbService _db;
|
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;
|
_service = service;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -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<ITextChannel>();
|
|
||||||
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<ITextChannel> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,10 +16,10 @@ namespace NadekoBot.Modules.Utility
|
|||||||
[Group]
|
[Group]
|
||||||
public class InfoCommands : NadekoSubmodule
|
public class InfoCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IStatsService _stats;
|
private readonly IStatsService _stats;
|
||||||
|
|
||||||
public InfoCommands(DiscordShardedClient client, IStatsService stats, CommandHandler ch)
|
public InfoCommands(DiscordSocketClient client, IStatsService stats, CommandHandler ch)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_stats = stats;
|
_stats = stats;
|
||||||
|
@ -34,7 +34,9 @@ namespace NadekoBot.Modules.Utility
|
|||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task PatreonRewardsReload()
|
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);
|
await Context.Channel.SendConfirmAsync("👌").ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@ -44,6 +46,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(_creds.PatreonAccessToken))
|
if (string.IsNullOrWhiteSpace(_creds.PatreonAccessToken))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (DateTime.UtcNow.Day < 5)
|
if (DateTime.UtcNow.Day < 5)
|
||||||
{
|
{
|
||||||
await ReplyErrorLocalized("clpa_too_early").ConfigureAwait(false);
|
await ReplyErrorLocalized("clpa_too_early").ConfigureAwait(false);
|
||||||
|
@ -33,7 +33,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[Priority(1)]
|
[Priority(0)]
|
||||||
public async Task Remind(MeOrHere meorhere, string timeStr, [Remainder] string message)
|
public async Task Remind(MeOrHere meorhere, string timeStr, [Remainder] string message)
|
||||||
{
|
{
|
||||||
ulong target;
|
ulong target;
|
||||||
@ -44,7 +44,7 @@ namespace NadekoBot.Modules.Utility
|
|||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.ManageMessages)]
|
[RequireUserPermission(GuildPermission.ManageMessages)]
|
||||||
[Priority(0)]
|
[Priority(1)]
|
||||||
public async Task Remind(ITextChannel channel, string timeStr, [Remainder] string message)
|
public async Task Remind(ITextChannel channel, string timeStr, [Remainder] string message)
|
||||||
{
|
{
|
||||||
var perms = ((IGuildUser)Context.User).GetPermissions((ITextChannel)channel);
|
var perms = ((IGuildUser)Context.User).GetPermissions((ITextChannel)channel);
|
||||||
|
@ -22,10 +22,10 @@ namespace NadekoBot.Modules.Utility
|
|||||||
public class RepeatCommands : NadekoSubmodule
|
public class RepeatCommands : NadekoSubmodule
|
||||||
{
|
{
|
||||||
private readonly MessageRepeaterService _service;
|
private readonly MessageRepeaterService _service;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public RepeatCommands(MessageRepeaterService service, DiscordShardedClient client, DbService db)
|
public RepeatCommands(MessageRepeaterService service, DiscordSocketClient client, DbService db)
|
||||||
{
|
{
|
||||||
_service = service;
|
_service = service;
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -6,7 +6,6 @@ using NadekoBot.Services.Utility;
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Utility
|
namespace NadekoBot.Modules.Utility
|
||||||
{
|
{
|
||||||
public partial class Utility
|
public partial class Utility
|
||||||
|
@ -18,100 +18,26 @@ using Discord.WebSocket;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Color = Discord.Color;
|
using Color = Discord.Color;
|
||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.DataStructures;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.Utility
|
namespace NadekoBot.Modules.Utility
|
||||||
{
|
{
|
||||||
public partial class Utility : NadekoTopLevelModule
|
public partial class Utility : NadekoTopLevelModule
|
||||||
{
|
{
|
||||||
private static ConcurrentDictionary<ulong, Timer> _rotatingRoleColors = new ConcurrentDictionary<ulong, Timer>();
|
private static ConcurrentDictionary<ulong, Timer> _rotatingRoleColors = new ConcurrentDictionary<ulong, Timer>();
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IStatsService _stats;
|
private readonly IStatsService _stats;
|
||||||
private readonly IBotCredentials _creds;
|
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;
|
_client = client;
|
||||||
_stats = stats;
|
_stats = stats;
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
|
_bot = bot;
|
||||||
}
|
}
|
||||||
|
|
||||||
//[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<string>(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<string>(reactions, r.Emoji.Name);
|
|
||||||
// if (index == -1)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// await usr.RemoveRolesAsync(roles[index]);
|
|
||||||
// }
|
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// _log.Warn(ex);
|
|
||||||
// }
|
|
||||||
// }));
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
[RequireUserPermission(GuildPermission.ManageRoles)]
|
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||||
@ -354,23 +280,25 @@ namespace NadekoBot.Modules.Utility
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[Shard0Precondition]
|
||||||
public async Task ShardStats(int page = 1)
|
public async Task ShardStats(int page = 1)
|
||||||
{
|
{
|
||||||
if (--page < 0)
|
if (--page < 0)
|
||||||
return;
|
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}")
|
.Select(x => $"{x.Count()} {x.Key}")
|
||||||
.ToArray());
|
.ToArray());
|
||||||
|
|
||||||
var allShardStrings = _client.Shards
|
var allShardStrings = statuses
|
||||||
.Select(x =>
|
.Select(x =>
|
||||||
GetText("shard_stats_txt", x.ShardId.ToString(),
|
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();
|
.ToArray();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
await Context.Channel.SendPaginatedConfirmAsync(_client, page, (curPage) =>
|
await Context.Channel.SendPaginatedConfirmAsync(_client, page, (curPage) =>
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -387,21 +315,9 @@ namespace NadekoBot.Modules.Utility
|
|||||||
}, allShardStrings.Length / 25);
|
}, 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]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
public async Task Stats()
|
public async Task Stats()
|
||||||
{
|
{
|
||||||
var shardId = Context.Guild != null
|
|
||||||
? _client.GetShardIdFor(Context.Guild)
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
await Context.Channel.EmbedAsync(
|
await Context.Channel.EmbedAsync(
|
||||||
new EmbedBuilder().WithOkColor()
|
new EmbedBuilder().WithOkColor()
|
||||||
.WithAuthor(eab => eab.WithName($"NadekoBot v{StatsService.BotVersion}")
|
.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"))
|
.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("author")).WithValue(_stats.Author).WithIsInline(true))
|
||||||
.AddField(efb => efb.WithName(GetText("botid")).WithValue(_client.CurrentUser.Id.ToString()).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("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("messages")).WithValue($"{_stats.MessageCounter} ({_stats.MessagesPerSecond:F2}/sec)").WithIsInline(true))
|
||||||
.AddField(efb => efb.WithName(GetText("memory")).WithValue($"{_stats.Heap} MB").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("uptime")).WithValue(_stats.GetUptimeString("\n")).WithIsInline(true))
|
||||||
.AddField(efb => efb.WithName(GetText("presence")).WithValue(
|
.AddField(efb => efb.WithName(GetText("presence")).WithValue(
|
||||||
GetText("presence_txt",
|
GetText("presence_txt",
|
||||||
_client.Guilds.Count, _stats.TextChannels, _stats.VoiceChannels)).WithIsInline(true))
|
_stats.GuildCount, _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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NadekoCommand, Usage, Description, Aliases]
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
@ -4,8 +4,6 @@ using Discord.WebSocket;
|
|||||||
using NadekoBot.Services;
|
using NadekoBot.Services;
|
||||||
using NadekoBot.Services.Impl;
|
using NadekoBot.Services.Impl;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NLog.Config;
|
|
||||||
using NLog.Targets;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@ -27,8 +25,7 @@ using NadekoBot.Services.Utility;
|
|||||||
using NadekoBot.Services.Help;
|
using NadekoBot.Services.Help;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using NadekoBot.Services.Pokemon;
|
using NadekoBot.Services.Pokemon;
|
||||||
using NadekoBot.DataStructures;
|
using NadekoBot.DataStructures.ShardCom;
|
||||||
using NadekoBot.Extensions;
|
|
||||||
|
|
||||||
namespace NadekoBot
|
namespace NadekoBot
|
||||||
{
|
{
|
||||||
@ -45,47 +42,63 @@ namespace NadekoBot
|
|||||||
public static Color OkColor { get; private set; }
|
public static Color OkColor { get; private set; }
|
||||||
public static Color ErrorColor { get; private set; }
|
public static Color ErrorColor { get; private set; }
|
||||||
|
|
||||||
public ImmutableArray<GuildConfig> AllGuildConfigs { get; }
|
public ImmutableArray<GuildConfig> AllGuildConfigs { get; private set; }
|
||||||
public BotConfig BotConfig { get; }
|
public BotConfig BotConfig { get; }
|
||||||
public DbService Db { get; }
|
public DbService Db { get; }
|
||||||
public CommandService CommandService { get; }
|
public CommandService CommandService { get; }
|
||||||
public CommandHandler CommandHandler { get; private set; }
|
public CommandHandler CommandHandler { get; private set; }
|
||||||
public Localization Localization { get; }
|
public Localization Localization { get; private set; }
|
||||||
public NadekoStrings Strings { get; }
|
public NadekoStrings Strings { get; private set; }
|
||||||
public StatsService Stats { get; }
|
public StatsService Stats { get; private set; }
|
||||||
public ImagesService Images { get; }
|
public ImagesService Images { get; }
|
||||||
public CurrencyService Currency { get; }
|
public CurrencyService Currency { get; }
|
||||||
public GoogleApiService GoogleApi { get; }
|
public GoogleApiService GoogleApi { get; }
|
||||||
|
|
||||||
public DiscordShardedClient Client { get; }
|
public DiscordSocketClient Client { get; }
|
||||||
public bool Ready { get; private set; }
|
public bool Ready { get; private set; }
|
||||||
|
|
||||||
public INServiceProvider Services { get; private set; }
|
public INServiceProvider Services { get; private set; }
|
||||||
public BotCredentials Credentials { get; }
|
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();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
TerribleElevatedPermissionCheck();
|
TerribleElevatedPermissionCheck();
|
||||||
|
|
||||||
Credentials = new BotCredentials();
|
Credentials = new BotCredentials();
|
||||||
|
|
||||||
|
port = port ?? Credentials.ShardRunPort;
|
||||||
|
_comClient = new ShardComClient(port.Value);
|
||||||
|
|
||||||
Db = new DbService(Credentials);
|
Db = new DbService(Credentials);
|
||||||
|
|
||||||
using (var uow = Db.UnitOfWork)
|
using (var uow = Db.UnitOfWork)
|
||||||
{
|
{
|
||||||
AllGuildConfigs = uow.GuildConfigs.GetAllGuildConfigs().ToImmutableArray();
|
|
||||||
BotConfig = uow.BotConfig.GetOrCreate();
|
BotConfig = uow.BotConfig.GetOrCreate();
|
||||||
OkColor = new Color(Convert.ToUInt32(BotConfig.OkColor, 16));
|
OkColor = new Color(Convert.ToUInt32(BotConfig.OkColor, 16));
|
||||||
ErrorColor = new Color(Convert.ToUInt32(BotConfig.ErrorColor, 16));
|
ErrorColor = new Color(Convert.ToUInt32(BotConfig.ErrorColor, 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
Client = new DiscordShardedClient(new DiscordSocketConfig
|
Client = new DiscordSocketClient(new DiscordSocketConfig
|
||||||
{
|
{
|
||||||
MessageCacheSize = 10,
|
MessageCacheSize = 10,
|
||||||
LogLevel = LogSeverity.Warning,
|
LogLevel = LogSeverity.Warning,
|
||||||
TotalShards = Credentials.TotalShards,
|
|
||||||
ConnectionTimeout = int.MaxValue,
|
ConnectionTimeout = int.MaxValue,
|
||||||
|
TotalShards = Credentials.TotalShards,
|
||||||
|
ShardId = shardId,
|
||||||
AlwaysDownloadUsers = false,
|
AlwaysDownloadUsers = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -95,181 +108,244 @@ namespace NadekoBot
|
|||||||
DefaultRunMode = RunMode.Sync,
|
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();
|
Images = new ImagesService();
|
||||||
Currency = new CurrencyService(BotConfig, Db);
|
Currency = new CurrencyService(BotConfig, Db);
|
||||||
GoogleApi = new GoogleApiService(Credentials);
|
GoogleApi = new GoogleApiService(Credentials);
|
||||||
|
|
||||||
|
SetupShard(shardId, parentProcessId, port.Value);
|
||||||
|
|
||||||
#if GLOBAL_NADEKO
|
#if GLOBAL_NADEKO
|
||||||
Client.Log += Client_Log;
|
Client.Log += Client_Log;
|
||||||
#endif
|
#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()
|
private void AddServices()
|
||||||
{
|
{
|
||||||
var soundcloudApiService = new SoundCloudApiService(Credentials);
|
var startingGuildIdList = Client.Guilds.Select(x => (long)x.Id).ToList();
|
||||||
|
|
||||||
#region help
|
//this unit of work will be used for initialization of all modules too, to prevent multiple queries from running
|
||||||
var helpService = new HelpService(BotConfig, CommandHandler, Strings);
|
using (var uow = Db.UnitOfWork)
|
||||||
#endregion
|
{
|
||||||
|
AllGuildConfigs = uow.GuildConfigs.GetAllGuildConfigs(startingGuildIdList).ToImmutableArray();
|
||||||
|
|
||||||
//module services
|
Localization = new Localization(BotConfig.Locale, AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.Locale), Db);
|
||||||
//todo 90 - autodiscover, DI, and add instead of manual like this
|
Strings = new NadekoStrings(Localization);
|
||||||
#region utility
|
CommandHandler = new CommandHandler(Client, Db, BotConfig, AllGuildConfigs, CommandService, Credentials, this);
|
||||||
var crossServerTextService = new CrossServerTextService(AllGuildConfigs, Client);
|
Stats = new StatsService(Client, CommandHandler, Credentials, ShardCoord);
|
||||||
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
|
|
||||||
|
|
||||||
#region permissions
|
var soundcloudApiService = new SoundCloudApiService(Credentials);
|
||||||
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 Searches
|
#region help
|
||||||
var searchesService = new SearchesService(Client, GoogleApi, Db);
|
var helpService = new HelpService(BotConfig, CommandHandler, Strings);
|
||||||
var streamNotificationService = new StreamNotificationService(Db, Client, Strings);
|
#endregion
|
||||||
var animeSearchService = new AnimeSearchService();
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
var clashService = new ClashOfClansService(Client, Db, Localization, Strings);
|
//module services
|
||||||
var musicService = new MusicService(GoogleApi, Strings, Localization, Db, soundcloudApiService, Credentials, AllGuildConfigs);
|
//todo 90 - autodiscover, DI, and add instead of manual like this
|
||||||
var crService = new CustomReactionsService(permissionsService, Db, Client, CommandHandler, BotConfig);
|
#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
|
||||||
|
|
||||||
#region Games
|
#region permissions
|
||||||
var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, Strings, Images, CommandHandler);
|
var permissionsService = new PermissionService(Client, Db, BotConfig, CommandHandler, Strings);
|
||||||
var chatterBotService = new ChatterBotService(Client, permissionsService, AllGuildConfigs, CommandHandler);
|
var blacklistService = new BlacklistService(BotConfig);
|
||||||
var pollService = new PollService(Client, Strings);
|
var cmdcdsService = new CmdCdService(AllGuildConfigs);
|
||||||
#endregion
|
var filterService = new FilterService(Client, AllGuildConfigs);
|
||||||
|
var globalPermsService = new GlobalPermissionService(BotConfig);
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region administration
|
#region Searches
|
||||||
var administrationService = new AdministrationService(AllGuildConfigs, CommandHandler);
|
var searchesService = new SearchesService(Client, GoogleApi, Db);
|
||||||
var greetSettingsService = new GreetSettingsService(Client, AllGuildConfigs, Db);
|
var streamNotificationService = new StreamNotificationService(Db, Client, Strings);
|
||||||
var selfService = new SelfService(Client, this, CommandHandler, Db, BotConfig, Localization, Strings, Credentials);
|
var animeSearchService = new AnimeSearchService();
|
||||||
var vcRoleService = new VcRoleService(Client, AllGuildConfigs, Db);
|
#endregion
|
||||||
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 clashService = new ClashOfClansService(Client, Db, Localization, Strings, uow, startingGuildIdList);
|
||||||
var pokemonService = new PokemonService();
|
var musicService = new MusicService(GoogleApi, Strings, Localization, Db, soundcloudApiService, Credentials, AllGuildConfigs);
|
||||||
#endregion
|
var crService = new CustomReactionsService(permissionsService, Db, Strings, Client, CommandHandler, BotConfig, uow);
|
||||||
|
|
||||||
|
#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<ILocalization>(Localization)
|
|
||||||
.Add<IStatsService>(Stats)
|
|
||||||
.Add<IImagesService>(Images)
|
|
||||||
.Add<IGoogleApiService>(GoogleApi)
|
|
||||||
.Add<IStatsService>(Stats)
|
|
||||||
.Add<IBotCredentials>(Credentials)
|
|
||||||
.Add<CommandService>(CommandService)
|
|
||||||
.Add<NadekoStrings>(Strings)
|
|
||||||
.Add<DiscordShardedClient>(Client)
|
|
||||||
.Add<BotConfig>(BotConfig)
|
|
||||||
.Add<CurrencyService>(Currency)
|
|
||||||
.Add<CommandHandler>(CommandHandler)
|
|
||||||
.Add<DbService>(Db)
|
|
||||||
//modules
|
|
||||||
.Add(crossServerTextService)
|
|
||||||
.Add(commandMapService)
|
|
||||||
.Add(remindService)
|
|
||||||
.Add(repeaterService)
|
|
||||||
.Add(converterService)
|
|
||||||
.Add(verboseErrorsService)
|
|
||||||
.Add(patreonRewardsService)
|
|
||||||
.Add(pruneService)
|
|
||||||
.Add<SearchesService>(searchesService)
|
|
||||||
.Add(streamNotificationService)
|
|
||||||
.Add(animeSearchService)
|
|
||||||
.Add<ClashOfClansService>(clashService)
|
|
||||||
.Add<MusicService>(musicService)
|
|
||||||
.Add<GreetSettingsService>(greetSettingsService)
|
|
||||||
.Add<CustomReactionsService>(crService)
|
|
||||||
.Add<HelpService>(helpService)
|
|
||||||
.Add<GamesService>(gamesService)
|
|
||||||
.Add(chatterBotService)
|
|
||||||
.Add(pollService)
|
|
||||||
.Add<AdministrationService>(administrationService)
|
|
||||||
.Add(selfService)
|
|
||||||
.Add(vcRoleService)
|
|
||||||
.Add(vPlusTService)
|
|
||||||
.Add(muteService)
|
|
||||||
.Add(ratelimitService)
|
|
||||||
.Add(playingRotateService)
|
|
||||||
.Add(gameVcService)
|
|
||||||
.Add(autoAssignRoleService)
|
|
||||||
.Add(protectionService)
|
|
||||||
.Add(logCommandService)
|
|
||||||
.Add(guildTimezoneService)
|
|
||||||
.Add<PermissionService>(permissionsService)
|
|
||||||
.Add(blacklistService)
|
|
||||||
.Add(cmdcdsService)
|
|
||||||
.Add(filterService)
|
|
||||||
.Add(globalPermsService)
|
|
||||||
.Add<PokemonService>(pokemonService)
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
CommandHandler.AddServices(Services);
|
//initialize Services
|
||||||
|
Services = new NServiceProvider.ServiceProviderBuilder()
|
||||||
|
.Add<ILocalization>(Localization)
|
||||||
|
.Add<IStatsService>(Stats)
|
||||||
|
.Add<IImagesService>(Images)
|
||||||
|
.Add<IGoogleApiService>(GoogleApi)
|
||||||
|
.Add<IStatsService>(Stats)
|
||||||
|
.Add<IBotCredentials>(Credentials)
|
||||||
|
.Add<CommandService>(CommandService)
|
||||||
|
.Add<NadekoStrings>(Strings)
|
||||||
|
.Add<DiscordSocketClient>(Client)
|
||||||
|
.Add<BotConfig>(BotConfig)
|
||||||
|
.Add<CurrencyService>(Currency)
|
||||||
|
.Add<CommandHandler>(CommandHandler)
|
||||||
|
.Add<DbService>(Db)
|
||||||
|
//modules
|
||||||
|
.Add(commandMapService)
|
||||||
|
.Add(remindService)
|
||||||
|
.Add(repeaterService)
|
||||||
|
//.Add(converterService)
|
||||||
|
.Add(verboseErrorsService)
|
||||||
|
.Add(patreonRewardsService)
|
||||||
|
.Add(pruneService)
|
||||||
|
.Add<SearchesService>(searchesService)
|
||||||
|
.Add(streamNotificationService)
|
||||||
|
.Add(animeSearchService)
|
||||||
|
.Add<ClashOfClansService>(clashService)
|
||||||
|
.Add<MusicService>(musicService)
|
||||||
|
.Add<GreetSettingsService>(greetSettingsService)
|
||||||
|
.Add<CustomReactionsService>(crService)
|
||||||
|
.Add<HelpService>(helpService)
|
||||||
|
.Add<GamesService>(gamesService)
|
||||||
|
.Add(chatterBotService)
|
||||||
|
.Add(pollService)
|
||||||
|
.Add<AdministrationService>(administrationService)
|
||||||
|
.Add(selfService)
|
||||||
|
.Add(vcRoleService)
|
||||||
|
.Add(vPlusTService)
|
||||||
|
.Add(muteService)
|
||||||
|
.Add(ratelimitService)
|
||||||
|
.Add(playingRotateService)
|
||||||
|
.Add(gameVcService)
|
||||||
|
.Add(autoAssignRoleService)
|
||||||
|
.Add(protectionService)
|
||||||
|
.Add(logCommandService)
|
||||||
|
.Add(guildTimezoneService)
|
||||||
|
.Add<PermissionService>(permissionsService)
|
||||||
|
.Add(blacklistService)
|
||||||
|
.Add(cmdcdsService)
|
||||||
|
.Add(filterService)
|
||||||
|
.Add(globalPermsService)
|
||||||
|
.Add<PokemonService>(pokemonService)
|
||||||
|
.Add<NadekoBot>(this)
|
||||||
|
.Build();
|
||||||
|
|
||||||
//setup typereaders
|
|
||||||
CommandService.AddTypeReader<PermissionAction>(new PermissionActionTypeReader());
|
CommandHandler.AddServices(Services);
|
||||||
CommandService.AddTypeReader<CommandInfo>(new CommandTypeReader(CommandService, CommandHandler));
|
|
||||||
CommandService.AddTypeReader<CommandOrCrInfo>(new CommandOrCrTypeReader(crService, CommandService, CommandHandler));
|
//setup typereaders
|
||||||
CommandService.AddTypeReader<ModuleInfo>(new ModuleTypeReader(CommandService));
|
CommandService.AddTypeReader<PermissionAction>(new PermissionActionTypeReader());
|
||||||
CommandService.AddTypeReader<ModuleOrCrInfo>(new ModuleOrCrTypeReader(CommandService));
|
CommandService.AddTypeReader<CommandInfo>(new CommandTypeReader(CommandService, CommandHandler));
|
||||||
CommandService.AddTypeReader<IGuild>(new GuildTypeReader(Client));
|
CommandService.AddTypeReader<CommandOrCrInfo>(new CommandOrCrTypeReader(crService, CommandService, CommandHandler));
|
||||||
CommandService.AddTypeReader<GuildDateTime>(new GuildDateTimeTypeReader(guildTimezoneService));
|
CommandService.AddTypeReader<ModuleInfo>(new ModuleTypeReader(CommandService));
|
||||||
|
CommandService.AddTypeReader<ModuleOrCrInfo>(new ModuleOrCrTypeReader(CommandService));
|
||||||
|
CommandService.AddTypeReader<IGuild>(new GuildTypeReader(Client));
|
||||||
|
CommandService.AddTypeReader<GuildDateTime>(new GuildDateTimeTypeReader(guildTimezoneService));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoginAsync(string token)
|
private async Task LoginAsync(string token)
|
||||||
{
|
{
|
||||||
_log.Info("Logging in...");
|
var clientReady = new TaskCompletionSource<bool>();
|
||||||
//connect
|
|
||||||
await Client.LoginAsync(TokenType.Bot, token).ConfigureAwait(false);
|
|
||||||
await Client.StartAsync().ConfigureAwait(false);
|
|
||||||
|
|
||||||
_log.Info("Waiting for all shards to connect...");
|
Task SetClientReady()
|
||||||
while (!Client.Shards.All(x => x.ConnectionState == ConnectionState.Connected))
|
|
||||||
{
|
{
|
||||||
_log.Info("Connecting... {0}/{1}", Client.Shards.Count(x => x.ConnectionState == ConnectionState.Connected), Client.Shards.Count);
|
var _ = Task.Run(async () =>
|
||||||
await Task.Delay(1000).ConfigureAwait(false);
|
{
|
||||||
|
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)
|
public async Task RunAsync(params string[] args)
|
||||||
{
|
{
|
||||||
|
if(ShardId == 0)
|
||||||
_log.Info("Starting NadekoBot v" + StatsService.BotVersion);
|
_log.Info("Starting NadekoBot v" + StatsService.BotVersion);
|
||||||
|
|
||||||
var sw = Stopwatch.StartNew();
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
await LoginAsync(Credentials.Token).ConfigureAwait(false);
|
await LoginAsync(Credentials.Token).ConfigureAwait(false);
|
||||||
|
|
||||||
_log.Info("Loading services...");
|
_log.Info($"Shard {ShardId} loading services...");
|
||||||
AddServices();
|
AddServices();
|
||||||
|
|
||||||
sw.Stop();
|
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<IStatsService>();
|
var stats = Services.GetService<IStatsService>();
|
||||||
stats.Initialize();
|
stats.Initialize();
|
||||||
@ -297,8 +373,10 @@ namespace NadekoBot
|
|||||||
.Where(x => x.Preconditions.Any(y => y.GetType() == typeof(NoPublicBot)))
|
.Where(x => x.Preconditions.Any(y => y.GetType() == typeof(NoPublicBot)))
|
||||||
.ForEach(x => CommandService.RemoveModuleAsync(x));
|
.ForEach(x => CommandService.RemoveModuleAsync(x));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Ready = true;
|
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)
|
private Task Client_Log(LogMessage arg)
|
||||||
@ -313,7 +391,13 @@ namespace NadekoBot
|
|||||||
public async Task RunAndBlockAsync(params string[] args)
|
public async Task RunAndBlockAsync(params string[] args)
|
||||||
{
|
{
|
||||||
await RunAsync(args).ConfigureAwait(false);
|
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()
|
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();
|
if (shardId != 0)
|
||||||
var consoleTarget = new ColoredConsoleTarget()
|
|
||||||
{
|
{
|
||||||
Layout = @"${date:format=HH\:mm\:ss} ${logger} | ${message}"
|
new Thread(new ThreadStart(() =>
|
||||||
};
|
{
|
||||||
logConfig.AddTarget("Console", consoleTarget);
|
try
|
||||||
|
{
|
||||||
logConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, consoleTarget));
|
var p = Process.GetProcessById(parentProcessId);
|
||||||
|
if (p == null)
|
||||||
LogManager.Configuration = logConfig;
|
return;
|
||||||
|
p.WaitForExit();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Environment.Exit(10);
|
||||||
|
}
|
||||||
|
})).Start();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ShardCoord = new ShardsCoordinator(port);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,5 +90,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Modules\Music\Classes\" />
|
<Folder Include="Modules\Music\Classes\" />
|
||||||
|
<Folder Include="Utility\Services\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -2,7 +2,17 @@
|
|||||||
{
|
{
|
||||||
public class Program
|
public class Program
|
||||||
{
|
{
|
||||||
public static void Main(string[] args) =>
|
public static void Main(string[] args)
|
||||||
new NadekoBot().RunAndBlockAsync(args).GetAwaiter().GetResult();
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
src/NadekoBot/Properties/launchSettings.json
Normal file
7
src/NadekoBot/Properties/launchSettings.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"NadekoBot": {
|
||||||
|
"commandName": "Project"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3096,14 +3096,14 @@
|
|||||||
<data name="shardstats_usage" xml:space="preserve">
|
<data name="shardstats_usage" xml:space="preserve">
|
||||||
<value>`{0}shardstats` or `{0}shardstats 2`</value>
|
<value>`{0}shardstats` or `{0}shardstats 2`</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="connectshard_cmd" xml:space="preserve">
|
<data name="restartshard_cmd" xml:space="preserve">
|
||||||
<value>connectshard</value>
|
<value>restartshard</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="connectshard_desc" xml:space="preserve">
|
<data name="restartshard_desc" xml:space="preserve">
|
||||||
<value>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.</value>
|
<value>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.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="connectshard_usage" xml:space="preserve">
|
<data name="restartshard_usage" xml:space="preserve">
|
||||||
<value>`{0}connectshard 2`</value>
|
<value>`{0}restartshard 2`</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="shardid_cmd" xml:space="preserve">
|
<data name="shardid_cmd" xml:space="preserve">
|
||||||
<value>shardid</value>
|
<value>shardid</value>
|
||||||
|
@ -12,12 +12,12 @@ namespace NadekoBot.Services.Administration
|
|||||||
public class AutoAssignRoleService
|
public class AutoAssignRoleService
|
||||||
{
|
{
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
//guildid/roleid
|
//guildid/roleid
|
||||||
public ConcurrentDictionary<ulong, ulong> AutoAssignedRoles { get; }
|
public ConcurrentDictionary<ulong, ulong> AutoAssignedRoles { get; }
|
||||||
|
|
||||||
public AutoAssignRoleService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs)
|
public AutoAssignRoleService(DiscordSocketClient client, IEnumerable<GuildConfig> gcs)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -16,9 +16,9 @@ namespace NadekoBot.Services.Administration
|
|||||||
|
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
public GameVoiceChannelService(DiscordShardedClient client, DbService db, IEnumerable<GuildConfig> gcs)
|
public GameVoiceChannelService(DiscordSocketClient client, DbService db, IEnumerable<GuildConfig> gcs)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -16,7 +16,7 @@ namespace NadekoBot.Services.Administration
|
|||||||
public class LogCommandService
|
public class LogCommandService
|
||||||
{
|
{
|
||||||
|
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
|
|
||||||
private string PrettyCurrentTime => $"【{DateTime.UtcNow:HH:mm:ss}】";
|
private string PrettyCurrentTime => $"【{DateTime.UtcNow:HH:mm:ss}】";
|
||||||
@ -31,7 +31,7 @@ namespace NadekoBot.Services.Administration
|
|||||||
private readonly MuteService _mute;
|
private readonly MuteService _mute;
|
||||||
private readonly ProtectionService _prot;
|
private readonly ProtectionService _prot;
|
||||||
|
|
||||||
public LogCommandService(DiscordShardedClient client, NadekoStrings strings,
|
public LogCommandService(DiscordSocketClient client, NadekoStrings strings,
|
||||||
IEnumerable<GuildConfig> gcs, DbService db, MuteService mute, ProtectionService prot)
|
IEnumerable<GuildConfig> gcs, DbService db, MuteService mute, ProtectionService prot)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
@ -74,7 +74,7 @@ namespace NadekoBot.Services.Administration
|
|||||||
_client.UserUnbanned += _client_UserUnbanned;
|
_client.UserUnbanned += _client_UserUnbanned;
|
||||||
_client.UserJoined += _client_UserJoined;
|
_client.UserJoined += _client_UserJoined;
|
||||||
_client.UserLeft += _client_UserLeft;
|
_client.UserLeft += _client_UserLeft;
|
||||||
_client.UserPresenceUpdated += _client_UserPresenceUpdated;
|
//_client.UserPresenceUpdated += _client_UserPresenceUpdated;
|
||||||
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated;
|
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated;
|
||||||
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated_TTS;
|
_client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated_TTS;
|
||||||
_client.GuildMemberUpdated += _client_GuildUserUpdated;
|
_client.GuildMemberUpdated += _client_GuildUserUpdated;
|
||||||
@ -576,48 +576,48 @@ namespace NadekoBot.Services.Administration
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task _client_UserPresenceUpdated(Optional<SocketGuild> optGuild, SocketUser usr, SocketPresence before, SocketPresence after)
|
//private Task _client_UserPresenceUpdated(Optional<SocketGuild> optGuild, SocketUser usr, SocketPresence before, SocketPresence after)
|
||||||
{
|
//{
|
||||||
var _ = Task.Run(async () =>
|
// var _ = Task.Run(async () =>
|
||||||
{
|
// {
|
||||||
try
|
// try
|
||||||
{
|
// {
|
||||||
var guild = optGuild.GetValueOrDefault() ?? (usr as SocketGuildUser)?.Guild;
|
// var guild = optGuild.GetValueOrDefault() ?? (usr as SocketGuildUser)?.Guild;
|
||||||
|
|
||||||
if (guild == null)
|
// if (guild == null)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
if (!GuildLogSettings.TryGetValue(guild.Id, out LogSetting logSetting)
|
// if (!GuildLogSettings.TryGetValue(guild.Id, out LogSetting logSetting)
|
||||||
|| (logSetting.LogUserPresenceId == null)
|
// || (logSetting.LogUserPresenceId == null)
|
||||||
|| before.Status == after.Status)
|
// || before.Status == after.Status)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
ITextChannel logChannel;
|
// ITextChannel logChannel;
|
||||||
if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserPresence)) == null)
|
// if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserPresence)) == null)
|
||||||
return;
|
// return;
|
||||||
string str = "";
|
// string str = "";
|
||||||
if (before.Status != after.Status)
|
// if (before.Status != after.Status)
|
||||||
str = "🎭" + Format.Code(PrettyCurrentTime) +
|
// str = "🎭" + Format.Code(PrettyCurrentTime) +
|
||||||
GetText(logChannel.Guild, "user_status_change",
|
// GetText(logChannel.Guild, "user_status_change",
|
||||||
"👤" + Format.Bold(usr.Username),
|
// "👤" + Format.Bold(usr.Username),
|
||||||
Format.Bold(after.Status.ToString()));
|
// Format.Bold(after.Status.ToString()));
|
||||||
|
|
||||||
//if (before.Game?.Name != after.Game?.Name)
|
// //if (before.Game?.Name != after.Game?.Name)
|
||||||
//{
|
// //{
|
||||||
// if (str != "")
|
// // if (str != "")
|
||||||
// str += "\n";
|
// // str += "\n";
|
||||||
// str += $"👾`{prettyCurrentTime}`👤__**{usr.Username}**__ is now playing **{after.Game?.Name}**.";
|
// // str += $"👾`{prettyCurrentTime}`👤__**{usr.Username}**__ is now playing **{after.Game?.Name}**.";
|
||||||
//}
|
// //}
|
||||||
|
|
||||||
PresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; });
|
// PresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; });
|
||||||
}
|
// }
|
||||||
catch
|
// catch
|
||||||
{
|
// {
|
||||||
// ignored
|
// // ignored
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
return Task.CompletedTask;
|
// return Task.CompletedTask;
|
||||||
}
|
//}
|
||||||
|
|
||||||
private Task _client_UserLeft(IGuildUser usr)
|
private Task _client_UserLeft(IGuildUser usr)
|
||||||
{
|
{
|
||||||
|
@ -33,10 +33,10 @@ namespace NadekoBot.Services.Administration
|
|||||||
private static readonly OverwritePermissions denyOverwrite = new OverwritePermissions(sendMessages: PermValue.Deny, attachFiles: PermValue.Deny);
|
private static readonly OverwritePermissions denyOverwrite = new OverwritePermissions(sendMessages: PermValue.Deny, attachFiles: PermValue.Deny);
|
||||||
|
|
||||||
private readonly Logger _log = LogManager.GetCurrentClassLogger();
|
private readonly Logger _log = LogManager.GetCurrentClassLogger();
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public MuteService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs, DbService db)
|
public MuteService(DiscordSocketClient client, IEnumerable<GuildConfig> gcs, DbService db)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -17,7 +17,7 @@ namespace NadekoBot.Services.Administration
|
|||||||
public List<PlayingStatus> RotatingStatusMessages { get; }
|
public List<PlayingStatus> RotatingStatusMessages { get; }
|
||||||
public volatile bool RotatingStatuses;
|
public volatile bool RotatingStatuses;
|
||||||
private readonly Timer _t;
|
private readonly Timer _t;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
private readonly MusicService _music;
|
private readonly MusicService _music;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
@ -27,7 +27,7 @@ namespace NadekoBot.Services.Administration
|
|||||||
public int Index { get; set; }
|
public int Index { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayingRotateService(DiscordShardedClient client, BotConfig bc, MusicService music)
|
public PlayingRotateService(DiscordSocketClient client, BotConfig bc, MusicService music)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
@ -52,17 +52,12 @@ namespace NadekoBot.Services.Administration
|
|||||||
var status = RotatingStatusMessages[state.Index++].Status;
|
var status = RotatingStatusMessages[state.Index++].Status;
|
||||||
if (string.IsNullOrWhiteSpace(status))
|
if (string.IsNullOrWhiteSpace(status))
|
||||||
return;
|
return;
|
||||||
PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value(_client,_music)));
|
PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value(_client, _music)));
|
||||||
var shards = _client.Shards;
|
ShardSpecificPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value(client)));
|
||||||
for (int i = 0; i < shards.Count; i++)
|
try { await client.SetGameAsync(status).ConfigureAwait(false); }
|
||||||
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
var curShard = shards.ElementAt(i);
|
_log.Warn(ex);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -72,8 +67,8 @@ namespace NadekoBot.Services.Administration
|
|||||||
}, new TimerState(), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
|
}, new TimerState(), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dictionary<string, Func<DiscordShardedClient, MusicService, string>> PlayingPlaceholders { get; } =
|
public Dictionary<string, Func<DiscordSocketClient, MusicService, string>> PlayingPlaceholders { get; } =
|
||||||
new Dictionary<string, Func<DiscordShardedClient, MusicService, string>> {
|
new Dictionary<string, Func<DiscordSocketClient, MusicService, string>> {
|
||||||
{ "%servers%", (c, ms) => c.Guilds.Count.ToString()},
|
{ "%servers%", (c, ms) => c.Guilds.Count.ToString()},
|
||||||
{ "%users%", (c, ms) => c.Guilds.Sum(s => s.Users.Count).ToString()},
|
{ "%users%", (c, ms) => c.Guilds.Sum(s => s.Users.Count).ToString()},
|
||||||
{ "%playing%", (c, ms) => {
|
{ "%playing%", (c, ms) => {
|
||||||
@ -90,7 +85,6 @@ namespace NadekoBot.Services.Administration
|
|||||||
},
|
},
|
||||||
{ "%queued%", (c, ms) => ms.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString()},
|
{ "%queued%", (c, ms) => ms.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString()},
|
||||||
{ "%time%", (c, ms) => DateTime.Now.ToString("HH:mm " + TimeZoneInfo.Local.StandardName.GetInitials()) },
|
{ "%time%", (c, ms) => DateTime.Now.ToString("HH:mm " + TimeZoneInfo.Local.StandardName.GetInitials()) },
|
||||||
{ "%shardcount%", (c, ms) => c.Shards.Count.ToString() },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public Dictionary<string, Func<DiscordSocketClient, string>> ShardSpecificPlaceholders { get; } =
|
public Dictionary<string, Func<DiscordSocketClient, string>> ShardSpecificPlaceholders { get; } =
|
||||||
|
@ -21,10 +21,10 @@ namespace NadekoBot.Services.Administration
|
|||||||
public event Func<PunishmentAction, ProtectionType, IGuildUser[], Task> OnAntiProtectionTriggered = delegate { return Task.CompletedTask; };
|
public event Func<PunishmentAction, ProtectionType, IGuildUser[], Task> OnAntiProtectionTriggered = delegate { return Task.CompletedTask; };
|
||||||
|
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly MuteService _mute;
|
private readonly MuteService _mute;
|
||||||
|
|
||||||
public ProtectionService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs, MuteService mute)
|
public ProtectionService(DiscordSocketClient client, IEnumerable<GuildConfig> gcs, MuteService mute)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -19,9 +19,9 @@ namespace NadekoBot.Services.Administration
|
|||||||
public ConcurrentDictionary<ulong, HashSet<ulong>> IgnoredUsers = new ConcurrentDictionary<ulong, HashSet<ulong>>();
|
public ConcurrentDictionary<ulong, HashSet<ulong>> IgnoredUsers = new ConcurrentDictionary<ulong, HashSet<ulong>>();
|
||||||
|
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
public SlowmodeService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs)
|
public SlowmodeService(DiscordSocketClient client, IEnumerable<GuildConfig> gcs)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -23,11 +23,11 @@ namespace NadekoBot.Services.Administration
|
|||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly ILocalization _localization;
|
private readonly ILocalization _localization;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private ImmutableArray<AsyncLazy<IDMChannel>> ownerChannels = new ImmutableArray<AsyncLazy<IDMChannel>>();
|
private ImmutableArray<AsyncLazy<IDMChannel>> ownerChannels = new ImmutableArray<AsyncLazy<IDMChannel>>();
|
||||||
|
|
||||||
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)
|
BotConfig bc, ILocalization localization, NadekoStrings strings, IBotCredentials creds)
|
||||||
{
|
{
|
||||||
_bot = bot;
|
_bot = bot;
|
||||||
@ -39,12 +39,8 @@ namespace NadekoBot.Services.Administration
|
|||||||
_client = client;
|
_client = client;
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
|
|
||||||
using (var uow = _db.UnitOfWork)
|
ForwardDMs = bc.ForwardMessages;
|
||||||
{
|
ForwardDMsToAllOwners = bc.ForwardToAllOwners;
|
||||||
var config = uow.BotConfig.GetOrCreate();
|
|
||||||
ForwardDMs = config.ForwardMessages;
|
|
||||||
ForwardDMsToAllOwners = config.ForwardToAllOwners;
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ = Task.Run(async () =>
|
var _ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
@ -67,12 +63,8 @@ namespace NadekoBot.Services.Administration
|
|||||||
|
|
||||||
_client.Guilds.SelectMany(g => g.Users);
|
_client.Guilds.SelectMany(g => g.Users);
|
||||||
|
|
||||||
LoadOwnerChannels();
|
if(client.ShardId == 0)
|
||||||
|
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.");
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,11 +73,9 @@ namespace NadekoBot.Services.Administration
|
|||||||
var hs = new HashSet<ulong>(_creds.OwnerIds);
|
var hs = new HashSet<ulong>(_creds.OwnerIds);
|
||||||
var channels = new Dictionary<ulong, AsyncLazy<IDMChannel>>();
|
var channels = new Dictionary<ulong, AsyncLazy<IDMChannel>>();
|
||||||
|
|
||||||
foreach (var s in _client.Shards)
|
if (hs.Count > 0)
|
||||||
{
|
{
|
||||||
if (hs.Count == 0)
|
foreach (var g in _client.Guilds)
|
||||||
break;
|
|
||||||
foreach (var g in s.Guilds)
|
|
||||||
{
|
{
|
||||||
if (hs.Count == 0)
|
if (hs.Count == 0)
|
||||||
break;
|
break;
|
||||||
@ -105,10 +95,15 @@ namespace NadekoBot.Services.Administration
|
|||||||
ownerChannels = channels.OrderBy(x => _creds.OwnerIds.IndexOf(x.Key))
|
ownerChannels = channels.OrderBy(x => _creds.OwnerIds.IndexOf(x.Key))
|
||||||
.Select(x => x.Value)
|
.Select(x => x.Value)
|
||||||
.ToImmutableArray();
|
.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
|
// 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)
|
if (msg.Channel is IDMChannel && ForwardDMs && ownerChannels.Length > 0)
|
||||||
{
|
{
|
||||||
|
@ -14,11 +14,11 @@ namespace NadekoBot.Services.Administration
|
|||||||
{
|
{
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
public ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, IRole>> VcRoles { get; }
|
public ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, IRole>> VcRoles { get; }
|
||||||
|
|
||||||
public VcRoleService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs, DbService db)
|
public VcRoleService(DiscordSocketClient client, IEnumerable<GuildConfig> gcs, DbService db)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_db = db;
|
_db = db;
|
||||||
|
@ -20,12 +20,12 @@ namespace NadekoBot.Services.Administration
|
|||||||
public readonly ConcurrentHashSet<ulong> VoicePlusTextCache;
|
public readonly ConcurrentHashSet<ulong> VoicePlusTextCache;
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<ulong, SemaphoreSlim> _guildLockObjects = new ConcurrentDictionary<ulong, SemaphoreSlim>();
|
private readonly ConcurrentDictionary<ulong, SemaphoreSlim> _guildLockObjects = new ConcurrentDictionary<ulong, SemaphoreSlim>();
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
|
|
||||||
public VplusTService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs, NadekoStrings strings,
|
public VplusTService(DiscordSocketClient client, IEnumerable<GuildConfig> gcs, NadekoStrings strings,
|
||||||
DbService db)
|
DbService db)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services.Database;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@ -17,7 +18,7 @@ namespace NadekoBot.Services.ClashOfClans
|
|||||||
// shouldn't be here
|
// shouldn't be here
|
||||||
public class ClashOfClansService
|
public class ClashOfClansService
|
||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly ILocalization _localization;
|
private readonly ILocalization _localization;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
@ -25,28 +26,27 @@ namespace NadekoBot.Services.ClashOfClans
|
|||||||
|
|
||||||
public ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; }
|
public ConcurrentDictionary<ulong, List<ClashWar>> 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<long> guilds)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_db = db;
|
_db = db;
|
||||||
_localization = localization;
|
_localization = localization;
|
||||||
_strings = strings;
|
_strings = strings;
|
||||||
|
|
||||||
using (var uow = _db.UnitOfWork)
|
ClashWars = new ConcurrentDictionary<ulong, List<ClashWar>>(
|
||||||
{
|
uow.ClashOfClans
|
||||||
ClashWars = new ConcurrentDictionary<ulong, List<ClashWar>>(
|
.GetAllWars(guilds)
|
||||||
uow.ClashOfClans
|
.Select(cw =>
|
||||||
.GetAllWars()
|
{
|
||||||
.Select(cw =>
|
cw.Channel = _client.GetGuild(cw.GuildId)?
|
||||||
{
|
.GetTextChannel(cw.ChannelId);
|
||||||
cw.Channel = _client.GetGuild(cw.GuildId)?
|
return cw;
|
||||||
.GetTextChannel(cw.ChannelId);
|
})
|
||||||
return cw;
|
.Where(cw => cw.Channel != null)
|
||||||
})
|
.GroupBy(cw => cw.GuildId)
|
||||||
.Where(cw => cw.Channel != null)
|
.ToDictionary(g => g.Key, g => g.ToList()));
|
||||||
.GroupBy(cw => cw.GuildId)
|
|
||||||
.ToDictionary(g => g.Key, g => g.ToList()));
|
|
||||||
}
|
|
||||||
|
|
||||||
checkWarTimer = new Timer(async _ =>
|
checkWarTimer = new Timer(async _ =>
|
||||||
{
|
{
|
||||||
|
@ -28,7 +28,7 @@ namespace NadekoBot.Services
|
|||||||
{
|
{
|
||||||
public const int GlobalCommandsCooldown = 750;
|
public const int GlobalCommandsCooldown = 750;
|
||||||
|
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly CommandService _commandService;
|
private readonly CommandService _commandService;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
@ -48,7 +48,7 @@ namespace NadekoBot.Services
|
|||||||
public ConcurrentHashSet<ulong> UsersOnShortCooldown { get; } = new ConcurrentHashSet<ulong>();
|
public ConcurrentHashSet<ulong> UsersOnShortCooldown { get; } = new ConcurrentHashSet<ulong>();
|
||||||
private readonly Timer _clearUsersOnShortCooldown;
|
private readonly Timer _clearUsersOnShortCooldown;
|
||||||
|
|
||||||
public CommandHandler(DiscordShardedClient client, DbService db, BotConfig bc, IEnumerable<GuildConfig> gcs, CommandService commandService, IBotCredentials credentials, NadekoBot bot)
|
public CommandHandler(DiscordSocketClient client, DbService db, BotConfig bc, IEnumerable<GuildConfig> gcs, CommandService commandService, IBotCredentials credentials, NadekoBot bot)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_commandService = commandService;
|
_commandService = commandService;
|
||||||
|
@ -10,6 +10,7 @@ using System;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NadekoBot.Services.Permissions;
|
using NadekoBot.Services.Permissions;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services.Database;
|
||||||
|
|
||||||
namespace NadekoBot.Services.CustomReactions
|
namespace NadekoBot.Services.CustomReactions
|
||||||
{
|
{
|
||||||
@ -22,13 +23,14 @@ namespace NadekoBot.Services.CustomReactions
|
|||||||
|
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly PermissionService _perms;
|
private readonly PermissionService _perms;
|
||||||
private readonly CommandHandler _cmd;
|
private readonly CommandHandler _cmd;
|
||||||
private readonly BotConfig _bc;
|
private readonly BotConfig _bc;
|
||||||
|
private readonly NadekoStrings _strings;
|
||||||
|
|
||||||
public CustomReactionsService(PermissionService perms, DbService db,
|
public CustomReactionsService(PermissionService perms, DbService db, NadekoStrings strings,
|
||||||
DiscordShardedClient client, CommandHandler cmd, BotConfig bc)
|
DiscordSocketClient client, CommandHandler cmd, BotConfig bc, IUnitOfWork uow)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_db = db;
|
_db = db;
|
||||||
@ -36,16 +38,11 @@ namespace NadekoBot.Services.CustomReactions
|
|||||||
_perms = perms;
|
_perms = perms;
|
||||||
_cmd = cmd;
|
_cmd = cmd;
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
|
_strings = strings;
|
||||||
|
|
||||||
var sw = Stopwatch.StartNew();
|
var items = uow.CustomReactions.GetAll();
|
||||||
using (var uow = _db.UnitOfWork)
|
GuildReactions = new ConcurrentDictionary<ulong, CustomReaction[]>(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();
|
||||||
var items = uow.CustomReactions.GetAll();
|
|
||||||
GuildReactions = new ConcurrentDictionary<ulong, CustomReaction[]>(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");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearStats() => ReactionStats.Clear();
|
public void ClearStats() => ReactionStats.Clear();
|
||||||
@ -98,7 +95,7 @@ namespace NadekoBot.Services.CustomReactions
|
|||||||
return greaction;
|
return greaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage msg)
|
public async Task<bool> TryExecuteEarly(DiscordSocketClient client, IGuild guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
// maybe this message is a custom reaction
|
// maybe this message is a custom reaction
|
||||||
var cr = await Task.Run(() => TryGetCustomReaction(msg)).ConfigureAwait(false);
|
var cr = await Task.Run(() => TryGetCustomReaction(msg)).ConfigureAwait(false);
|
||||||
@ -114,7 +111,7 @@ namespace NadekoBot.Services.CustomReactions
|
|||||||
{
|
{
|
||||||
if (pc.Verbose)
|
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 { }
|
try { await msg.Channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
|
||||||
_log.Info(returnMsg);
|
_log.Info(returnMsg);
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ namespace NadekoBot.Services.CustomReactions
|
|||||||
} },
|
} },
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Dictionary<string, Func<IUserMessage, DiscordShardedClient, string>> placeholders = new Dictionary<string, Func<IUserMessage, DiscordShardedClient, string>>()
|
public static Dictionary<string, Func<IUserMessage, DiscordSocketClient, string>> placeholders = new Dictionary<string, Func<IUserMessage, DiscordSocketClient, string>>()
|
||||||
{
|
{
|
||||||
{"%mention%", (ctx, client) => { return $"<@{client.CurrentUser.Id}>"; } },
|
{"%mention%", (ctx, client) => { return $"<@{client.CurrentUser.Id}>"; } },
|
||||||
{"%user%", (ctx, client) => { return ctx.Author.Mention; } },
|
{"%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)
|
foreach (var ph in placeholders)
|
||||||
{
|
{
|
||||||
@ -104,7 +104,7 @@ namespace NadekoBot.Services.CustomReactions
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<string> ResolveResponseStringAsync(this string str, IUserMessage ctx, DiscordShardedClient client, string resolvedTrigger)
|
private static async Task<string> ResolveResponseStringAsync(this string str, IUserMessage ctx, DiscordSocketClient client, string resolvedTrigger)
|
||||||
{
|
{
|
||||||
foreach (var ph in placeholders)
|
foreach (var ph in placeholders)
|
||||||
{
|
{
|
||||||
@ -127,13 +127,13 @@ namespace NadekoBot.Services.CustomReactions
|
|||||||
return str;
|
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);
|
=> cr.Trigger.ResolveTriggerString(ctx, client);
|
||||||
|
|
||||||
public static Task<string > ResponseWithContextAsync(this CustomReaction cr, IUserMessage ctx, DiscordShardedClient client)
|
public static Task<string > ResponseWithContextAsync(this CustomReaction cr, IUserMessage ctx, DiscordSocketClient client)
|
||||||
=> cr.Response.ResolveResponseStringAsync(ctx, client, cr.Trigger.ResolveTriggerString(ctx, client));
|
=> cr.Response.ResolveResponseStringAsync(ctx, client, cr.Trigger.ResolveTriggerString(ctx, client));
|
||||||
|
|
||||||
public static async Task<IUserMessage> Send(this CustomReaction cr, IUserMessage context, DiscordShardedClient client, CustomReactionsService crs)
|
public static async Task<IUserMessage> Send(this CustomReaction cr, IUserMessage context, DiscordSocketClient client, CustomReactionsService crs)
|
||||||
{
|
{
|
||||||
var channel = cr.DmResponse ? await context.Author.CreateDMChannelAsync() : context.Channel;
|
var channel = cr.DmResponse ? await context.Author.CreateDMChannelAsync() : context.Channel;
|
||||||
|
|
||||||
|
@ -19,7 +19,9 @@ namespace NadekoBot.Services.Database
|
|||||||
{
|
{
|
||||||
var optionsBuilder = new DbContextOptionsBuilder();
|
var optionsBuilder = new DbContextOptionsBuilder();
|
||||||
optionsBuilder.UseSqlite("Filename=./data/NadekoBot.db");
|
optionsBuilder.UseSqlite("Filename=./data/NadekoBot.db");
|
||||||
return new NadekoContext(optionsBuilder.Options);
|
var ctx = new NadekoContext(optionsBuilder.Options);
|
||||||
|
ctx.Database.SetCommandTimeout(60);
|
||||||
|
return ctx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,6 @@ namespace NadekoBot.Services.Database.Repositories
|
|||||||
{
|
{
|
||||||
public interface IClashOfClansRepository : IRepository<ClashWar>
|
public interface IClashOfClansRepository : IRepository<ClashWar>
|
||||||
{
|
{
|
||||||
IEnumerable<ClashWar> GetAllWars();
|
IEnumerable<ClashWar> GetAllWars(List<long> guilds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,10 @@ namespace NadekoBot.Services.Database.Repositories
|
|||||||
GuildConfig For(ulong guildId, Func<DbSet<GuildConfig>, IQueryable<GuildConfig>> includes = null);
|
GuildConfig For(ulong guildId, Func<DbSet<GuildConfig>, IQueryable<GuildConfig>> includes = null);
|
||||||
GuildConfig LogSettingsFor(ulong guildId);
|
GuildConfig LogSettingsFor(ulong guildId);
|
||||||
IEnumerable<GuildConfig> OldPermissionsForAll();
|
IEnumerable<GuildConfig> OldPermissionsForAll();
|
||||||
IEnumerable<GuildConfig> GetAllGuildConfigs();
|
IEnumerable<GuildConfig> GetAllGuildConfigs(List<long> availableGuilds);
|
||||||
IEnumerable<FollowedStream> GetAllFollowedStreams();
|
IEnumerable<FollowedStream> GetAllFollowedStreams(List<long> included);
|
||||||
void SetCleverbotEnabled(ulong id, bool cleverbotEnabled);
|
void SetCleverbotEnabled(ulong id, bool cleverbotEnabled);
|
||||||
IEnumerable<GuildConfig> Permissionsv2ForAll();
|
IEnumerable<GuildConfig> Permissionsv2ForAll(List<long> include);
|
||||||
GuildConfig GcWithPermissionsv2For(ulong guildId);
|
GuildConfig GcWithPermissionsv2For(ulong guildId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Database.Repositories
|
namespace NadekoBot.Services.Database.Repositories
|
||||||
{
|
{
|
||||||
public interface IReminderRepository : IRepository<Reminder>
|
public interface IReminderRepository : IRepository<Reminder>
|
||||||
{
|
{
|
||||||
|
IEnumerable<Reminder> GetIncludedReminders(List<long> guildIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,11 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ClashWar> GetAllWars()
|
public IEnumerable<ClashWar> GetAllWars(List<long> guilds)
|
||||||
{
|
{
|
||||||
var toReturn = _set.Include(cw => cw.Bases)
|
var toReturn = _set
|
||||||
|
.Where(cw => guilds.Contains((long)cw.GuildId))
|
||||||
|
.Include(cw => cw.Bases)
|
||||||
.ToList();
|
.ToList();
|
||||||
toReturn.ForEach(cw => cw.Bases = cw.Bases.Where(w => w.SequenceNumber != null).OrderBy(w => w.SequenceNumber).ToList());
|
toReturn.ForEach(cw => cw.Bases = cw.Bases.Where(w => w.SequenceNumber != null).OrderBy(w => w.SequenceNumber).ToList());
|
||||||
return toReturn;
|
return toReturn;
|
||||||
|
@ -24,8 +24,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public IEnumerable<GuildConfig> GetAllGuildConfigs() =>
|
public IEnumerable<GuildConfig> GetAllGuildConfigs(List<long> availableGuilds) =>
|
||||||
_set.Include(gc => gc.LogSetting)
|
_set
|
||||||
|
.Where(gc => availableGuilds.Contains((long)gc.GuildId))
|
||||||
|
.Include(gc => gc.LogSetting)
|
||||||
.ThenInclude(ls => ls.IgnoredChannels)
|
.ThenInclude(ls => ls.IgnoredChannels)
|
||||||
.Include(gc => gc.MutedUsers)
|
.Include(gc => gc.MutedUsers)
|
||||||
.Include(gc => gc.CommandAliases)
|
.Include(gc => gc.CommandAliases)
|
||||||
@ -42,6 +44,7 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
.Include(gc => gc.SlowmodeIgnoredUsers)
|
.Include(gc => gc.SlowmodeIgnoredUsers)
|
||||||
.Include(gc => gc.AntiSpamSetting)
|
.Include(gc => gc.AntiSpamSetting)
|
||||||
.ThenInclude(x => x.IgnoredChannels)
|
.ThenInclude(x => x.IgnoredChannels)
|
||||||
|
.Include(gc => gc.FollowedStreams)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -134,9 +137,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
return query.ToList();
|
return query.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<GuildConfig> Permissionsv2ForAll()
|
public IEnumerable<GuildConfig> Permissionsv2ForAll(List<long> include)
|
||||||
{
|
{
|
||||||
var query = _set
|
var query = _set
|
||||||
|
.Where(x => include.Contains((long)x.GuildId))
|
||||||
.Include(gc => gc.Permissions);
|
.Include(gc => gc.Permissions);
|
||||||
|
|
||||||
return query.ToList();
|
return query.ToList();
|
||||||
@ -167,8 +171,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<FollowedStream> GetAllFollowedStreams() =>
|
public IEnumerable<FollowedStream> GetAllFollowedStreams(List<long> included) =>
|
||||||
_set.Include(gc => gc.FollowedStreams)
|
_set
|
||||||
|
.Where(gc => included.Contains((long)gc.GuildId))
|
||||||
|
.Include(gc => gc.FollowedStreams)
|
||||||
.SelectMany(gc => gc.FollowedStreams)
|
.SelectMany(gc => gc.FollowedStreams)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Database.Repositories.Impl
|
namespace NadekoBot.Services.Database.Repositories.Impl
|
||||||
{
|
{
|
||||||
@ -8,5 +11,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
public ReminderRepository(DbContext context) : base(context)
|
public ReminderRepository(DbContext context) : base(context)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<Reminder> GetIncludedReminders(List<long> guildIds)
|
||||||
|
{
|
||||||
|
return _set.Where(x => guildIds.Contains((long)x.ServerId)).ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,9 +32,21 @@ namespace NadekoBot.Services
|
|||||||
public NadekoContext GetDbContext()
|
public NadekoContext GetDbContext()
|
||||||
{
|
{
|
||||||
var context = new NadekoContext(options);
|
var context = new NadekoContext(options);
|
||||||
|
context.Database.SetCommandTimeout(60);
|
||||||
context.Database.Migrate();
|
context.Database.Migrate();
|
||||||
context.EnsureSeedData();
|
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;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ namespace NadekoBot.Services.Discord
|
|||||||
public event Action<SocketReaction> OnReactionRemoved = delegate { };
|
public event Action<SocketReaction> OnReactionRemoved = delegate { };
|
||||||
public event Action OnReactionsCleared = 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));
|
Message = msg ?? throw new ArgumentNullException(nameof(msg));
|
||||||
_client = client;
|
_client = client;
|
||||||
@ -69,7 +69,7 @@ namespace NadekoBot.Services.Discord
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bool disposing = false;
|
private bool disposing = false;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
@ -15,19 +15,22 @@ namespace NadekoBot.Services.Games
|
|||||||
{
|
{
|
||||||
public class ChatterBotService : IEarlyBlockingExecutor
|
public class ChatterBotService : IEarlyBlockingExecutor
|
||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly PermissionService _perms;
|
private readonly PermissionService _perms;
|
||||||
private readonly CommandHandler _cmd;
|
private readonly CommandHandler _cmd;
|
||||||
|
private readonly NadekoStrings _strings;
|
||||||
|
|
||||||
public ConcurrentDictionary<ulong, Lazy<ChatterBotSession>> ChatterBotGuilds { get; }
|
public ConcurrentDictionary<ulong, Lazy<ChatterBotSession>> ChatterBotGuilds { get; }
|
||||||
|
|
||||||
public ChatterBotService(DiscordShardedClient client, PermissionService perms, IEnumerable<GuildConfig> gcs, CommandHandler cmd)
|
public ChatterBotService(DiscordSocketClient client, PermissionService perms, IEnumerable<GuildConfig> gcs,
|
||||||
|
CommandHandler cmd, NadekoStrings strings)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_perms = perms;
|
_perms = perms;
|
||||||
_cmd = cmd;
|
_cmd = cmd;
|
||||||
|
_strings = strings;
|
||||||
|
|
||||||
ChatterBotGuilds = new ConcurrentDictionary<ulong, Lazy<ChatterBotSession>>(
|
ChatterBotGuilds = new ConcurrentDictionary<ulong, Lazy<ChatterBotSession>>(
|
||||||
gcs.Where(gc => gc.CleverbotEnabled)
|
gcs.Where(gc => gc.CleverbotEnabled)
|
||||||
@ -83,7 +86,7 @@ namespace NadekoBot.Services.Games
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage usrMsg)
|
public async Task<bool> TryExecuteEarly(DiscordSocketClient client, IGuild guild, IUserMessage usrMsg)
|
||||||
{
|
{
|
||||||
if (!(guild is SocketGuild sg))
|
if (!(guild is SocketGuild sg))
|
||||||
return false;
|
return false;
|
||||||
@ -102,7 +105,7 @@ namespace NadekoBot.Services.Games
|
|||||||
if (pc.Verbose)
|
if (pc.Verbose)
|
||||||
{
|
{
|
||||||
//todo move this to permissions
|
//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 { }
|
try { await usrMsg.Channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
|
||||||
_log.Info(returnMsg);
|
_log.Info(returnMsg);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ namespace NadekoBot.Services.Games
|
|||||||
public readonly ImmutableArray<string> EightBallResponses;
|
public readonly ImmutableArray<string> EightBallResponses;
|
||||||
|
|
||||||
private readonly Timer _t;
|
private readonly Timer _t;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
@ -33,7 +33,7 @@ namespace NadekoBot.Services.Games
|
|||||||
|
|
||||||
public List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>();
|
public List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>();
|
||||||
|
|
||||||
public GamesService(DiscordShardedClient client, BotConfig bc, IEnumerable<GuildConfig> gcs,
|
public GamesService(DiscordSocketClient client, BotConfig bc, IEnumerable<GuildConfig> gcs,
|
||||||
NadekoStrings strings, IImagesService images, CommandHandler cmdHandler)
|
NadekoStrings strings, IImagesService images, CommandHandler cmdHandler)
|
||||||
{
|
{
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
|
@ -18,16 +18,13 @@ namespace NadekoBot.Services.Games
|
|||||||
private string[] answers { get; }
|
private string[] answers { get; }
|
||||||
private readonly ConcurrentDictionary<ulong, int> _participants = new ConcurrentDictionary<ulong, int>();
|
private readonly ConcurrentDictionary<ulong, int> _participants = new ConcurrentDictionary<ulong, int>();
|
||||||
private readonly string _question;
|
private readonly string _question;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private bool running = false;
|
private bool running = false;
|
||||||
private HashSet<ulong> _guildUsers;
|
|
||||||
|
|
||||||
public event Action<ulong> OnEnded = delegate { };
|
public event Action<ulong> OnEnded = delegate { };
|
||||||
|
|
||||||
public bool IsPublic { get; }
|
public Poll(DiscordSocketClient client, NadekoStrings strings, IUserMessage umsg, string question, IEnumerable<string> enumerable)
|
||||||
|
|
||||||
public Poll(DiscordShardedClient client, NadekoStrings strings, IUserMessage umsg, string question, IEnumerable<string> enumerable, bool isPublic = false)
|
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_strings = strings;
|
_strings = strings;
|
||||||
@ -36,7 +33,6 @@ namespace NadekoBot.Services.Games
|
|||||||
_guild = ((ITextChannel)umsg.Channel).Guild;
|
_guild = ((ITextChannel)umsg.Channel).Guild;
|
||||||
_question = question;
|
_question = question;
|
||||||
answers = enumerable as string[] ?? enumerable.ToArray();
|
answers = enumerable as string[] ?? enumerable.ToArray();
|
||||||
IsPublic = isPublic;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EmbedBuilder GetStats(string title)
|
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 msgToSend = GetText("poll_created", Format.Bold(_originalMessage.Author.Username)) + "\n\n" + Format.Bold(_question) + "\n";
|
||||||
var num = 1;
|
var num = 1;
|
||||||
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
|
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
|
||||||
if (!IsPublic)
|
msgToSend += "\n" + Format.Bold(GetText("poll_vote_public"));
|
||||||
msgToSend += "\n" + Format.Bold(GetText("poll_vote_private"));
|
|
||||||
else
|
|
||||||
msgToSend += "\n" + Format.Bold(GetText("poll_vote_public"));
|
|
||||||
|
|
||||||
if (!IsPublic)
|
|
||||||
_guildUsers = new HashSet<ulong>((await _guild.GetUsersAsync().ConfigureAwait(false)).Select(x => x.Id));
|
|
||||||
|
|
||||||
await _originalMessage.Channel.SendConfirmAsync(msgToSend).ConfigureAwait(false);
|
await _originalMessage.Channel.SendConfirmAsync(msgToSend).ConfigureAwait(false);
|
||||||
running = true;
|
running = true;
|
||||||
@ -114,36 +104,16 @@ namespace NadekoBot.Services.Games
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
IMessageChannel ch;
|
IMessageChannel ch;
|
||||||
if (IsPublic)
|
//if public, channel must be the same the poll started in
|
||||||
{
|
if (_originalMessage.Channel.Id != msg.Channel.Id)
|
||||||
//if public, channel must be the same the poll started in
|
return false;
|
||||||
if (_originalMessage.Channel.Id != msg.Channel.Id)
|
ch = msg.Channel;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
//user can vote only once
|
//user can vote only once
|
||||||
if (_participants.TryAdd(msg.Author.Id, vote))
|
if (_participants.TryAdd(msg.Author.Id, vote))
|
||||||
{
|
{
|
||||||
if (!IsPublic)
|
var toDelete = await ch.SendConfirmAsync(GetText("poll_voted", Format.Bold(msg.Author.ToString()))).ConfigureAwait(false);
|
||||||
{
|
toDelete.DeleteAfter(5);
|
||||||
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);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -13,17 +13,17 @@ namespace NadekoBot.Services.Games
|
|||||||
{
|
{
|
||||||
public ConcurrentDictionary<ulong, Poll> ActivePolls = new ConcurrentDictionary<ulong, Poll>();
|
public ConcurrentDictionary<ulong, Poll> ActivePolls = new ConcurrentDictionary<ulong, Poll>();
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
|
|
||||||
public PollService(DiscordShardedClient client, NadekoStrings strings)
|
public PollService(DiscordSocketClient client, NadekoStrings strings)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_client = client;
|
_client = client;
|
||||||
_strings = strings;
|
_strings = strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool?> StartPoll(ITextChannel channel, IUserMessage msg, string arg, bool isPublic = false)
|
public async Task<bool?> StartPoll(ITextChannel channel, IUserMessage msg, string arg)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(arg) || !arg.Contains(";"))
|
if (string.IsNullOrWhiteSpace(arg) || !arg.Contains(";"))
|
||||||
return null;
|
return null;
|
||||||
@ -31,7 +31,7 @@ namespace NadekoBot.Services.Games
|
|||||||
if (data.Length < 3)
|
if (data.Length < 3)
|
||||||
return null;
|
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))
|
if (ActivePolls.TryAdd(channel.Guild.Id, poll))
|
||||||
{
|
{
|
||||||
poll.OnEnded += (gid) =>
|
poll.OnEnded += (gid) =>
|
||||||
@ -45,20 +45,10 @@ namespace NadekoBot.Services.Games
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage msg)
|
public async Task<bool> TryExecuteEarly(DiscordSocketClient client, IGuild guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
if (guild == null)
|
if (guild == null)
|
||||||
{
|
|
||||||
foreach (var kvp in ActivePolls)
|
|
||||||
{
|
|
||||||
if (!kvp.Value.IsPublic)
|
|
||||||
{
|
|
||||||
if (await kvp.Value.TryVote(msg).ConfigureAwait(false))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (!ActivePolls.TryGetValue(guild.Id, out var poll))
|
if (!ActivePolls.TryGetValue(guild.Id, out var poll))
|
||||||
return false;
|
return false;
|
||||||
|
@ -17,10 +17,10 @@ namespace NadekoBot.Services
|
|||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public readonly ConcurrentDictionary<ulong, GreetSettings> GuildConfigsCache;
|
public readonly ConcurrentDictionary<ulong, GreetSettings> GuildConfigsCache;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
|
|
||||||
public GreetSettingsService(DiscordShardedClient client, IEnumerable<GuildConfig> guildConfigs, DbService db)
|
public GreetSettingsService(DiscordSocketClient client, IEnumerable<GuildConfig> guildConfigs, DbService db)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_client = client;
|
_client = client;
|
||||||
|
@ -24,7 +24,7 @@ namespace NadekoBot.Services.Help
|
|||||||
_strings = strings;
|
_strings = strings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LateExecute(DiscordShardedClient client, IGuild guild, IUserMessage msg)
|
public async Task LateExecute(DiscordSocketClient client, IGuild guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,9 @@ namespace NadekoBot.Services
|
|||||||
string OsuApiKey { get; }
|
string OsuApiKey { get; }
|
||||||
|
|
||||||
bool IsOwner(IUser u);
|
bool IsOwner(IUser u);
|
||||||
|
int TotalShards { get; }
|
||||||
|
string ShardRunCommand { get; }
|
||||||
|
string ShardRunArguments { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DBConfig
|
public class DBConfig
|
||||||
|
@ -18,6 +18,6 @@ namespace NadekoBot.Services
|
|||||||
ImmutableArray<byte> WifeMatrix { get; }
|
ImmutableArray<byte> WifeMatrix { get; }
|
||||||
ImmutableArray<byte> RategirlDot { get; }
|
ImmutableArray<byte> RategirlDot { get; }
|
||||||
|
|
||||||
TimeSpan Reload();
|
void Reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ namespace NadekoBot.Services
|
|||||||
double MessagesPerSecond { get; }
|
double MessagesPerSecond { get; }
|
||||||
long TextChannels { get; }
|
long TextChannels { get; }
|
||||||
long VoiceChannels { get; }
|
long VoiceChannels { get; }
|
||||||
|
int GuildCount { get; }
|
||||||
|
|
||||||
TimeSpan GetUptime();
|
TimeSpan GetUptime();
|
||||||
string GetUptimeString(string separator = ", ");
|
string GetUptimeString(string separator = ", ");
|
||||||
|
@ -30,20 +30,23 @@ namespace NadekoBot.Services.Impl
|
|||||||
public int TotalShards { get; }
|
public int TotalShards { get; }
|
||||||
public string CarbonKey { 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 PatreonAccessToken { get; }
|
||||||
|
public string ShardRunCommand { get; }
|
||||||
|
public string ShardRunArguments { get; }
|
||||||
|
public int ShardRunPort { get; }
|
||||||
|
|
||||||
public BotCredentials()
|
public BotCredentials()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
try { File.WriteAllText("./credentials_example.json", JsonConvert.SerializeObject(new CredentialsModel(), Formatting.Indented)); } catch { }
|
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")}");
|
_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
|
try
|
||||||
{
|
{
|
||||||
var configBuilder = new ConfigurationBuilder();
|
var configBuilder = new ConfigurationBuilder();
|
||||||
configBuilder.AddJsonFile(credsFileName, true)
|
configBuilder.AddJsonFile(_credsFileName, true)
|
||||||
.AddEnvironmentVariables("NadekoBot_");
|
.AddEnvironmentVariables("NadekoBot_");
|
||||||
|
|
||||||
var data = configBuilder.Build();
|
var data = configBuilder.Build();
|
||||||
@ -61,13 +64,24 @@ namespace NadekoBot.Services.Impl
|
|||||||
MashapeKey = data[nameof(MashapeKey)];
|
MashapeKey = data[nameof(MashapeKey)];
|
||||||
OsuApiKey = data[nameof(OsuApiKey)];
|
OsuApiKey = data[nameof(OsuApiKey)];
|
||||||
PatreonAccessToken = data[nameof(PatreonAccessToken)];
|
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 ts = 1;
|
||||||
int.TryParse(data[nameof(TotalShards)], out ts);
|
int.TryParse(data[nameof(TotalShards)], out ts);
|
||||||
TotalShards = ts < 1 ? 1 : ts;
|
TotalShards = ts < 1 ? 1 : ts;
|
||||||
|
|
||||||
ulong clId = 0;
|
ulong.TryParse(data[nameof(ClientId)], out ulong clId);
|
||||||
ulong.TryParse(data[nameof(ClientId)], out clId);
|
|
||||||
ClientId = clId;
|
ClientId = clId;
|
||||||
|
|
||||||
//var scId = data[nameof(SoundCloudClientId)];
|
//var scId = data[nameof(SoundCloudClientId)];
|
||||||
@ -107,6 +121,10 @@ namespace NadekoBot.Services.Impl
|
|||||||
public DBConfig Db { get; set; } = new DBConfig("sqlite", "Filename=./data/NadekoBot.db");
|
public DBConfig Db { get; set; } = new DBConfig("sqlite", "Filename=./data/NadekoBot.db");
|
||||||
public int TotalShards { get; set; } = 1;
|
public int TotalShards { get; set; } = 1;
|
||||||
public string PatreonAccessToken { get; set; } = "";
|
public string PatreonAccessToken { get; set; } = "";
|
||||||
|
|
||||||
|
public string ShardRunCommand { get; set; } = "";
|
||||||
|
public string ShardRunArguments { get; set; } = "";
|
||||||
|
public int? ShardRunPort { get; set; } = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DbModel
|
private class DbModel
|
||||||
|
@ -47,12 +47,10 @@ namespace NadekoBot.Services.Impl
|
|||||||
this.Reload();
|
this.Reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TimeSpan Reload()
|
public void Reload()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_log.Info("Loading images...");
|
|
||||||
var sw = Stopwatch.StartNew();
|
|
||||||
Heads = File.ReadAllBytes(_headsPath).ToImmutableArray();
|
Heads = File.ReadAllBytes(_headsPath).ToImmutableArray();
|
||||||
Tails = File.ReadAllBytes(_tailsPath).ToImmutableArray();
|
Tails = File.ReadAllBytes(_tailsPath).ToImmutableArray();
|
||||||
|
|
||||||
@ -79,10 +77,6 @@ namespace NadekoBot.Services.Impl
|
|||||||
|
|
||||||
WifeMatrix = File.ReadAllBytes(_wifeMatrixPath).ToImmutableArray();
|
WifeMatrix = File.ReadAllBytes(_wifeMatrixPath).ToImmutableArray();
|
||||||
RategirlDot = File.ReadAllBytes(_rategirlDot).ToImmutableArray();
|
RategirlDot = File.ReadAllBytes(_rategirlDot).ToImmutableArray();
|
||||||
|
|
||||||
sw.Stop();
|
|
||||||
_log.Info($"Images loaded after {sw.Elapsed.TotalSeconds:F2}s!");
|
|
||||||
return sw.Elapsed;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -13,11 +13,11 @@ namespace NadekoBot.Services.Impl
|
|||||||
{
|
{
|
||||||
public class StatsService : IStatsService
|
public class StatsService : IStatsService
|
||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private readonly DateTime _started;
|
private readonly DateTime _started;
|
||||||
|
|
||||||
public const string BotVersion = "1.43";
|
public const string BotVersion = "1.5";
|
||||||
|
|
||||||
public string Author => "Kwoth#2560";
|
public string Author => "Kwoth#2560";
|
||||||
public string Library => "Discord.Net";
|
public string Library => "Discord.Net";
|
||||||
@ -35,11 +35,16 @@ namespace NadekoBot.Services.Impl
|
|||||||
public long CommandsRan => Interlocked.Read(ref _commandsRan);
|
public long CommandsRan => Interlocked.Read(ref _commandsRan);
|
||||||
|
|
||||||
private readonly Timer _carbonitexTimer;
|
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;
|
_client = client;
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
|
_sc = sc;
|
||||||
|
|
||||||
_started = DateTime.UtcNow;
|
_started = DateTime.UtcNow;
|
||||||
_client.MessageReceived += _ => Task.FromResult(Interlocked.Increment(ref _messageCounter));
|
_client.MessageReceived += _ => Task.FromResult(Interlocked.Increment(ref _messageCounter));
|
||||||
@ -121,31 +126,34 @@ namespace NadekoBot.Services.Impl
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
|
|
||||||
_carbonitexTimer = new Timer(async (state) =>
|
if (sc != null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(_creds.CarbonKey))
|
_carbonitexTimer = new Timer(async (state) =>
|
||||||
return;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
using (var http = new HttpClient())
|
if (string.IsNullOrWhiteSpace(_creds.CarbonKey))
|
||||||
|
return;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
using (var content = new FormUrlEncodedContent(
|
using (var http = new HttpClient())
|
||||||
new Dictionary<string, string> {
|
|
||||||
{ "servercount", _client.Guilds.Count.ToString() },
|
|
||||||
{ "key", _creds.CarbonKey }}))
|
|
||||||
{
|
{
|
||||||
content.Headers.Clear();
|
using (var content = new FormUrlEncodedContent(
|
||||||
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
|
new Dictionary<string, string> {
|
||||||
|
{ "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
|
||||||
catch
|
{
|
||||||
{
|
// ignored
|
||||||
// ignored
|
}
|
||||||
}
|
}, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
|
||||||
}, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
|
28
src/NadekoBot/Services/LogSetup.cs
Normal file
28
src/NadekoBot/Services/LogSetup.cs
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -21,7 +21,7 @@ namespace NadekoBot.Services.Permissions
|
|||||||
v => new ConcurrentHashSet<CommandCooldown>(v.CommandCooldowns)));
|
v => new ConcurrentHashSet<CommandCooldown>(v.CommandCooldowns)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<bool> TryBlockLate(DiscordShardedClient client, IUserMessage msg, IGuild guild,
|
public Task<bool> TryBlockLate(DiscordSocketClient client, IUserMessage msg, IGuild guild,
|
||||||
IMessageChannel channel, IUser user, string moduleName, string commandName)
|
IMessageChannel channel, IUser user, string moduleName, string commandName)
|
||||||
{
|
{
|
||||||
if (guild == null)
|
if (guild == null)
|
||||||
|
@ -41,7 +41,7 @@ namespace NadekoBot.Services.Permissions
|
|||||||
return words;
|
return words;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FilterService(DiscordShardedClient _client, IEnumerable<GuildConfig> gcs)
|
public FilterService(DiscordSocketClient _client, IEnumerable<GuildConfig> gcs)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ namespace NadekoBot.Services.Permissions
|
|||||||
BlockedCommands = new ConcurrentHashSet<string>(bc.BlockedCommands.Select(x => x.Name));
|
BlockedCommands = new ConcurrentHashSet<string>(bc.BlockedCommands.Select(x => x.Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> TryBlockLate(DiscordShardedClient client, IUserMessage msg, IGuild guild, IMessageChannel channel, IUser user, string moduleName, string commandName)
|
public async Task<bool> TryBlockLate(DiscordSocketClient client, IUserMessage msg, IGuild guild, IMessageChannel channel, IUser user, string moduleName, string commandName)
|
||||||
{
|
{
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
commandName = commandName.ToLowerInvariant();
|
commandName = commandName.ToLowerInvariant();
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NadekoBot.DataStructures.ModuleBehaviors;
|
using NadekoBot.DataStructures.ModuleBehaviors;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NLog;
|
using NLog;
|
||||||
@ -10,6 +11,7 @@ using System.Threading.Tasks;
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Permissions
|
namespace NadekoBot.Services.Permissions
|
||||||
{
|
{
|
||||||
@ -18,22 +20,26 @@ namespace NadekoBot.Services.Permissions
|
|||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private readonly CommandHandler _cmd;
|
private readonly CommandHandler _cmd;
|
||||||
|
private readonly NadekoStrings _strings;
|
||||||
|
|
||||||
//guildid, root permission
|
//guildid, root permission
|
||||||
public ConcurrentDictionary<ulong, PermissionCache> Cache { get; } =
|
public ConcurrentDictionary<ulong, PermissionCache> Cache { get; } =
|
||||||
new ConcurrentDictionary<ulong, PermissionCache>();
|
new ConcurrentDictionary<ulong, PermissionCache>();
|
||||||
|
|
||||||
public PermissionService(DbService db, BotConfig bc, CommandHandler cmd)
|
public PermissionService(DiscordSocketClient client, DbService db, BotConfig bc, CommandHandler cmd, NadekoStrings strings)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_db = db;
|
_db = db;
|
||||||
_cmd = cmd;
|
_cmd = cmd;
|
||||||
|
_strings = strings;
|
||||||
|
|
||||||
var sw = Stopwatch.StartNew();
|
var sw = Stopwatch.StartNew();
|
||||||
TryMigratePermissions(bc);
|
if (client.ShardId == 0)
|
||||||
|
TryMigratePermissions(bc);
|
||||||
|
|
||||||
using (var uow = _db.UnitOfWork)
|
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()
|
Cache.TryAdd(x.GuildId, new PermissionCache()
|
||||||
{
|
{
|
||||||
@ -68,10 +74,9 @@ namespace NadekoBot.Services.Permissions
|
|||||||
private void TryMigratePermissions(BotConfig bc)
|
private void TryMigratePermissions(BotConfig bc)
|
||||||
{
|
{
|
||||||
var log = LogManager.GetCurrentClassLogger();
|
var log = LogManager.GetCurrentClassLogger();
|
||||||
using (var uow = _db.UnitOfWork)
|
if (bc.PermissionVersion <= 1)
|
||||||
{
|
{
|
||||||
var _bc = uow.BotConfig.GetOrCreate();
|
using (var uow = _db.UnitOfWork)
|
||||||
if (_bc.PermissionVersion <= 1)
|
|
||||||
{
|
{
|
||||||
log.Info("Permission version is 1, upgrading to 2.");
|
log.Info("Permission version is 1, upgrading to 2.");
|
||||||
var oldCache = new ConcurrentDictionary<ulong, OldPermissionCache>(uow.GuildConfigs
|
var oldCache = new ConcurrentDictionary<ulong, OldPermissionCache>(uow.GuildConfigs
|
||||||
@ -126,9 +131,13 @@ namespace NadekoBot.Services.Permissions
|
|||||||
log.Info("Permission migration to v2 is done.");
|
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", "!", "+", "-", "$", ">" };
|
var oldPrefixes = new[] { ".", ";", "!!", "!m", "!", "+", "-", "$", ">" };
|
||||||
uow._context.Database.ExecuteSqlCommand(
|
uow._context.Database.ExecuteSqlCommand(
|
||||||
@ -144,9 +153,9 @@ WHERE secondaryTargetName LIKE '.%' OR
|
|||||||
secondaryTargetName LIKE '>%' OR
|
secondaryTargetName LIKE '>%' OR
|
||||||
secondaryTargetName LIKE '-%' OR
|
secondaryTargetName LIKE '-%' OR
|
||||||
secondaryTargetName LIKE '!%';");
|
secondaryTargetName LIKE '!%';");
|
||||||
_bc.PermissionVersion = 3;
|
bc.PermissionVersion = 3;
|
||||||
|
uow.Complete();
|
||||||
}
|
}
|
||||||
uow.Complete();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +192,7 @@ WHERE secondaryTargetName LIKE '.%' OR
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> TryBlockLate(DiscordShardedClient client, IUserMessage msg, IGuild guild, IMessageChannel channel, IUser user, string moduleName, string commandName)
|
public async Task<bool> TryBlockLate(DiscordSocketClient client, IUserMessage msg, IGuild guild, IMessageChannel channel, IUser user, string moduleName, string commandName)
|
||||||
{
|
{
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
if (guild == null)
|
if (guild == null)
|
||||||
@ -198,11 +207,9 @@ WHERE secondaryTargetName LIKE '.%' OR
|
|||||||
PermissionCache pc = GetCache(guild.Id);
|
PermissionCache pc = GetCache(guild.Id);
|
||||||
if (!resetCommand && !pc.Permissions.CheckPermissions(msg, commandName, moduleName, out int index))
|
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)
|
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 true;
|
||||||
//return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -215,7 +222,6 @@ WHERE secondaryTargetName LIKE '.%' OR
|
|||||||
if (pc.Verbose)
|
if (pc.Verbose)
|
||||||
try { await channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
|
try { await channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
|
||||||
return true;
|
return true;
|
||||||
//return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"You need the **{pc.PermRole}** role in order to use permission commands."));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,52 +1,18 @@
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace NadekoBot.Services.Searches
|
namespace NadekoBot.Services.Searches
|
||||||
{
|
{
|
||||||
public class AnimeSearchService
|
public class AnimeSearchService
|
||||||
{
|
{
|
||||||
private readonly Timer _anilistTokenRefresher;
|
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
|
|
||||||
private static string anilistToken { get; set; }
|
|
||||||
|
|
||||||
public AnimeSearchService()
|
public AnimeSearchService()
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_anilistTokenRefresher = new Timer(async (state) =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var headers = new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{"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<AnimeResult> GetAnimeData(string query)
|
public async Task<AnimeResult> GetAnimeData(string query)
|
||||||
@ -56,19 +22,15 @@ namespace NadekoBot.Services.Searches
|
|||||||
try
|
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())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
var res = await http.GetStringAsync(link + $"?access_token={anilistToken}").ConfigureAwait(false);
|
var res = await http.GetStringAsync(link).ConfigureAwait(false);
|
||||||
var smallObj = JArray.Parse(res)[0];
|
return JsonConvert.DeserializeObject<AnimeResult>(res);
|
||||||
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<AnimeResult>(aniData); } catch { return null; } }).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch
|
||||||
{
|
{
|
||||||
_log.Warn(ex, "Failed anime search for {0}", query);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,18 +41,16 @@ namespace NadekoBot.Services.Searches
|
|||||||
throw new ArgumentNullException(nameof(query));
|
throw new ArgumentNullException(nameof(query));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
|
var link = "https://aniapi.nadekobot.me/manga/" + Uri.EscapeDataString(query.Replace("/", " "));
|
||||||
using (var http = new HttpClient())
|
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 res = await http.GetStringAsync(link).ConfigureAwait(false);
|
||||||
var smallObj = JArray.Parse(res)[0];
|
return JsonConvert.DeserializeObject<MangaResult>(res);
|
||||||
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<MangaResult>(aniData); } catch { return null; } }).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch
|
||||||
{
|
{
|
||||||
_log.Warn(ex, "Failed anime search for {0}", query);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ namespace NadekoBot.Services.Searches
|
|||||||
{
|
{
|
||||||
public class SearchesService
|
public class SearchesService
|
||||||
{
|
{
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IGoogleApiService _google;
|
private readonly IGoogleApiService _google;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
@ -31,7 +31,7 @@ namespace NadekoBot.Services.Searches
|
|||||||
public List<WoWJoke> WowJokes { get; } = new List<WoWJoke>();
|
public List<WoWJoke> WowJokes { get; } = new List<WoWJoke>();
|
||||||
public List<MagicItem> MagicItems { get; } = new List<MagicItem>();
|
public List<MagicItem> MagicItems { get; } = new List<MagicItem>();
|
||||||
|
|
||||||
public SearchesService(DiscordShardedClient client, IGoogleApiService google, DbService db)
|
public SearchesService(DiscordSocketClient client, IGoogleApiService google, DbService db)
|
||||||
{
|
{
|
||||||
_client = client;
|
_client = client;
|
||||||
_google = google;
|
_google = google;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Database;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using System;
|
using System;
|
||||||
@ -20,10 +22,10 @@ namespace NadekoBot.Services.Searches
|
|||||||
private readonly ConcurrentDictionary<string, StreamStatus> _cachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
|
private readonly ConcurrentDictionary<string, StreamStatus> _cachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
|
||||||
|
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
|
|
||||||
public StreamNotificationService(DbService db, DiscordShardedClient client, NadekoStrings strings)
|
public StreamNotificationService(DbService db, DiscordSocketClient client, NadekoStrings strings)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_client = client;
|
_client = client;
|
||||||
@ -35,7 +37,7 @@ namespace NadekoBot.Services.Searches
|
|||||||
IEnumerable<FollowedStream> streams;
|
IEnumerable<FollowedStream> streams;
|
||||||
using (var uow = _db.UnitOfWork)
|
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 =>
|
await Task.WhenAll(streams.Select(async fs =>
|
||||||
@ -73,7 +75,7 @@ namespace NadekoBot.Services.Searches
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
firstStreamNotifPass = false;
|
firstStreamNotifPass = false;
|
||||||
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(60));
|
}, null, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(60));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<StreamStatus> GetStreamStatus(FollowedStream stream, bool checkCache = true)
|
public async Task<StreamStatus> GetStreamStatus(FollowedStream stream, bool checkCache = true)
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using NadekoBot.Services.Database.Models;
|
using Discord.WebSocket;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
@ -13,24 +15,26 @@ namespace NadekoBot.Services.Utility
|
|||||||
{
|
{
|
||||||
public class ConverterService
|
public class ConverterService
|
||||||
{
|
{
|
||||||
public List<ConvertUnit> Units { get; set; } = new List<ConvertUnit>();
|
public List<ConvertUnit> Units { get; } = new List<ConvertUnit>();
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
private Timer _timer;
|
private readonly Timer _currencyUpdater;
|
||||||
private readonly TimeSpan _updateInterval = new TimeSpan(12, 0, 0);
|
private readonly TimeSpan _updateInterval = new TimeSpan(12, 0, 0);
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public ConverterService(DbService db)
|
public ConverterService(DiscordSocketClient client, DbService db)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
_db = db;
|
_db = db;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var data = JsonConvert.DeserializeObject<List<MeasurementUnit>>(File.ReadAllText("data/units.json")).Select(u => new ConvertUnit()
|
var data = JsonConvert.DeserializeObject<List<MeasurementUnit>>(
|
||||||
{
|
File.ReadAllText("data/units.json"))
|
||||||
Modifier = u.Modifier,
|
.Select(u => new ConvertUnit()
|
||||||
UnitType = u.UnitType,
|
{
|
||||||
InternalTrigger = string.Join("|", u.Triggers)
|
Modifier = u.Modifier,
|
||||||
}).ToArray();
|
UnitType = u.UnitType,
|
||||||
|
InternalTrigger = string.Join("|", u.Triggers)
|
||||||
|
}).ToArray();
|
||||||
|
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
@ -47,10 +51,10 @@ namespace NadekoBot.Services.Utility
|
|||||||
_log.Warn("Could not load units: " + ex.Message);
|
_log.Warn("Could not load units: " + ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
_timer = new Timer(async (obj) => await UpdateCurrency(), null, _updateInterval, _updateInterval);
|
_currencyUpdater = new Timer(async (shouldLoad) => await UpdateCurrency((bool)shouldLoad), client.ShardId == 0, _updateInterval, _updateInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<Rates> UpdateCurrencyRates()
|
private async Task<Rates> GetCurrencyRates()
|
||||||
{
|
{
|
||||||
using (var http = new HttpClient())
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
@ -59,38 +63,48 @@ namespace NadekoBot.Services.Utility
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateCurrency()
|
private async Task UpdateCurrency(bool shouldLoad)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var currencyRates = await UpdateCurrencyRates();
|
|
||||||
var unitTypeString = "currency";
|
var unitTypeString = "currency";
|
||||||
var range = currencyRates.ConversionRates.Select(u => new ConvertUnit()
|
if (shouldLoad)
|
||||||
{
|
{
|
||||||
InternalTrigger = u.Key,
|
var currencyRates = await GetCurrencyRates();
|
||||||
Modifier = u.Value,
|
var baseType = new ConvertUnit()
|
||||||
UnitType = unitTypeString
|
{
|
||||||
}).ToArray();
|
Triggers = new[] { currencyRates.Base },
|
||||||
var baseType = new ConvertUnit()
|
Modifier = decimal.One,
|
||||||
{
|
UnitType = unitTypeString
|
||||||
Triggers = new[] { currencyRates.Base },
|
};
|
||||||
Modifier = decimal.One,
|
var range = currencyRates.ConversionRates.Select(u => new ConvertUnit()
|
||||||
UnitType = unitTypeString
|
{
|
||||||
};
|
InternalTrigger = u.Key,
|
||||||
var toRemove = Units.Where(u => u.UnitType == unitTypeString);
|
Modifier = u.Value,
|
||||||
|
UnitType = unitTypeString
|
||||||
|
}).ToArray();
|
||||||
|
var toRemove = Units.Where(u => u.UnitType == unitTypeString);
|
||||||
|
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
uow.ConverterUnits.RemoveRange(toRemove.ToArray());
|
uow.ConverterUnits.RemoveRange(toRemove.ToArray());
|
||||||
uow.ConverterUnits.Add(baseType);
|
uow.ConverterUnits.Add(baseType);
|
||||||
uow.ConverterUnits.AddRange(range);
|
uow.ConverterUnits.AddRange(range);
|
||||||
|
|
||||||
await uow.CompleteAsync().ConfigureAwait(false);
|
await uow.CompleteAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
Units.RemoveAll(u => u.UnitType == unitTypeString);
|
||||||
|
Units.Add(baseType);
|
||||||
|
Units.AddRange(range);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
Units.RemoveAll(u => u.UnitType == unitTypeString);
|
||||||
|
Units.AddRange(uow.ConverterUnits.GetAll().ToArray());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Units.RemoveAll(u => u.UnitType == unitTypeString);
|
|
||||||
Units.Add(baseType);
|
|
||||||
Units.AddRange(range);
|
|
||||||
_log.Info("Updated Currency");
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@ namespace NadekoBot.Services.Utility
|
|||||||
public ConcurrentDictionary<ulong, ConcurrentQueue<RepeatRunner>> Repeaters { get; set; }
|
public ConcurrentDictionary<ulong, ConcurrentQueue<RepeatRunner>> Repeaters { get; set; }
|
||||||
public bool RepeaterReady { get; private set; }
|
public bool RepeaterReady { get; private set; }
|
||||||
|
|
||||||
public MessageRepeaterService(NadekoBot bot, DiscordShardedClient client, IEnumerable<GuildConfig> gcs)
|
public MessageRepeaterService(NadekoBot bot, DiscordSocketClient client, IEnumerable<GuildConfig> gcs)
|
||||||
{
|
{
|
||||||
var _ = Task.Run(async () =>
|
var _ = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
using NadekoBot.Services.Database.Models;
|
using Discord.WebSocket;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
using NadekoBot.Services.Utility.Patreon;
|
using NadekoBot.Services.Utility.Patreon;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -23,12 +26,15 @@ namespace NadekoBot.Services.Utility
|
|||||||
private readonly SemaphoreSlim claimLockJustInCase = new SemaphoreSlim(1, 1);
|
private readonly SemaphoreSlim claimLockJustInCase = new SemaphoreSlim(1, 1);
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
|
|
||||||
public readonly TimeSpan Interval = TimeSpan.FromMinutes(15);
|
public readonly TimeSpan Interval = TimeSpan.FromMinutes(3);
|
||||||
private IBotCredentials _creds;
|
private readonly IBotCredentials _creds;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly CurrencyService _currency;
|
private readonly CurrencyService _currency;
|
||||||
|
|
||||||
public PatreonRewardsService(IBotCredentials creds, DbService db, CurrencyService currency)
|
private readonly string cacheFileName = "./patreon-rewards.json";
|
||||||
|
|
||||||
|
public PatreonRewardsService(IBotCredentials creds, DbService db, CurrencyService currency,
|
||||||
|
DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
_db = db;
|
_db = db;
|
||||||
@ -36,58 +42,65 @@ namespace NadekoBot.Services.Utility
|
|||||||
if (string.IsNullOrWhiteSpace(creds.PatreonAccessToken))
|
if (string.IsNullOrWhiteSpace(creds.PatreonAccessToken))
|
||||||
return;
|
return;
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
Updater = new Timer(async (_) => await LoadPledges(), null, TimeSpan.Zero, Interval);
|
Updater = new Timer(async (load) => await RefreshPledges((bool)load),
|
||||||
|
client.ShardId == 0, client.ShardId == 0 ? TimeSpan.Zero : TimeSpan.FromMinutes(2), Interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LoadPledges()
|
public async Task RefreshPledges(bool shouldLoad)
|
||||||
{
|
{
|
||||||
LastUpdate = DateTime.UtcNow;
|
if (shouldLoad)
|
||||||
await getPledgesLocker.WaitAsync(1000).ConfigureAwait(false);
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var rewards = new List<PatreonPledge>();
|
LastUpdate = DateTime.UtcNow;
|
||||||
var users = new List<PatreonUser>();
|
await getPledgesLocker.WaitAsync().ConfigureAwait(false);
|
||||||
using (var http = new HttpClient())
|
try
|
||||||
{
|
{
|
||||||
http.DefaultRequestHeaders.Clear();
|
var rewards = new List<PatreonPledge>();
|
||||||
http.DefaultRequestHeaders.Add("Authorization", "Bearer " + _creds.PatreonAccessToken);
|
var users = new List<PatreonUser>();
|
||||||
var data = new PatreonData()
|
using (var http = new HttpClient())
|
||||||
{
|
{
|
||||||
Links = new PatreonDataLinks()
|
http.DefaultRequestHeaders.Clear();
|
||||||
|
http.DefaultRequestHeaders.Add("Authorization", "Bearer " + _creds.PatreonAccessToken);
|
||||||
|
var data = new PatreonData()
|
||||||
{
|
{
|
||||||
next = "https://api.patreon.com/oauth2/api/campaigns/334038/pledges"
|
Links = new PatreonDataLinks()
|
||||||
}
|
{
|
||||||
};
|
next = "https://api.patreon.com/oauth2/api/campaigns/334038/pledges"
|
||||||
do
|
}
|
||||||
|
};
|
||||||
|
do
|
||||||
|
{
|
||||||
|
var res = await http.GetStringAsync(data.Links.next)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
data = JsonConvert.DeserializeObject<PatreonData>(res);
|
||||||
|
var pledgers = data.Data.Where(x => x["type"].ToString() == "pledge");
|
||||||
|
rewards.AddRange(pledgers.Select(x => JsonConvert.DeserializeObject<PatreonPledge>(x.ToString()))
|
||||||
|
.Where(x => x.attributes.declined_since == null));
|
||||||
|
users.AddRange(data.Included
|
||||||
|
.Where(x => x["type"].ToString() == "user")
|
||||||
|
.Select(x => JsonConvert.DeserializeObject<PatreonUser>(x.ToString())));
|
||||||
|
} while (!string.IsNullOrWhiteSpace(data.Links.next));
|
||||||
|
}
|
||||||
|
Pledges = rewards.Join(users, (r) => r.relationships?.patron?.data?.id, (u) => u.id, (x, y) => new PatreonUserAndReward()
|
||||||
{
|
{
|
||||||
var res = await http.GetStringAsync(data.Links.next)
|
User = y,
|
||||||
.ConfigureAwait(false);
|
Reward = x,
|
||||||
data = JsonConvert.DeserializeObject<PatreonData>(res);
|
}).ToImmutableArray();
|
||||||
var pledgers = data.Data.Where(x => x["type"].ToString() == "pledge");
|
File.WriteAllText("./patreon_rewards.json", JsonConvert.SerializeObject(Pledges));
|
||||||
rewards.AddRange(pledgers.Select(x => JsonConvert.DeserializeObject<PatreonPledge>(x.ToString()))
|
|
||||||
.Where(x => x.attributes.declined_since == null));
|
|
||||||
users.AddRange(data.Included
|
|
||||||
.Where(x => x["type"].ToString() == "user")
|
|
||||||
.Select(x => JsonConvert.DeserializeObject<PatreonUser>(x.ToString())));
|
|
||||||
} while (!string.IsNullOrWhiteSpace(data.Links.next));
|
|
||||||
}
|
}
|
||||||
Pledges = rewards.Join(users, (r) => r.relationships?.patron?.data?.id, (u) => u.id, (x, y) => new PatreonUserAndReward()
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
User = y,
|
_log.Warn(ex);
|
||||||
Reward = x,
|
}
|
||||||
}).ToImmutableArray();
|
finally
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_log.Warn(ex);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
var _ = Task.Run(async () =>
|
|
||||||
{
|
{
|
||||||
await Task.Delay(TimeSpan.FromMinutes(5)).ConfigureAwait(false);
|
|
||||||
getPledgesLocker.Release();
|
getPledgesLocker.Release();
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(File.Exists(cacheFileName))
|
||||||
|
Pledges = JsonConvert.DeserializeObject<PatreonUserAndReward[]>(File.ReadAllText("./patreon_rewards.json"))
|
||||||
|
.ToImmutableArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using Discord;
|
using Discord;
|
||||||
using Discord.WebSocket;
|
using Discord.WebSocket;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Services.Database;
|
||||||
using NadekoBot.Services.Database.Models;
|
using NadekoBot.Services.Database.Models;
|
||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
@ -30,10 +31,11 @@ namespace NadekoBot.Services.Utility
|
|||||||
private readonly CancellationTokenSource cancelSource;
|
private readonly CancellationTokenSource cancelSource;
|
||||||
private readonly CancellationToken cancelAllToken;
|
private readonly CancellationToken cancelAllToken;
|
||||||
private readonly BotConfig _config;
|
private readonly BotConfig _config;
|
||||||
private readonly DiscordShardedClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
|
|
||||||
public RemindService(DiscordShardedClient client, BotConfig config, DbService db)
|
public RemindService(DiscordSocketClient client, BotConfig config, DbService db,
|
||||||
|
List<long> guilds, IUnitOfWork uow)
|
||||||
{
|
{
|
||||||
_config = config;
|
_config = config;
|
||||||
_client = client;
|
_client = client;
|
||||||
@ -42,11 +44,8 @@ namespace NadekoBot.Services.Utility
|
|||||||
|
|
||||||
cancelSource = new CancellationTokenSource();
|
cancelSource = new CancellationTokenSource();
|
||||||
cancelAllToken = cancelSource.Token;
|
cancelAllToken = cancelSource.Token;
|
||||||
List<Reminder> reminders;
|
|
||||||
using (var uow = _db.UnitOfWork)
|
var reminders = uow.Reminders.GetIncludedReminders(guilds).ToList();
|
||||||
{
|
|
||||||
reminders = uow.Reminders.GetAll().ToList();
|
|
||||||
}
|
|
||||||
RemindMessageFormat = _config.RemindMessageFormat;
|
RemindMessageFormat = _config.RemindMessageFormat;
|
||||||
|
|
||||||
foreach (var r in reminders)
|
foreach (var r in reminders)
|
||||||
|
@ -22,7 +22,7 @@ namespace NadekoBot.Services.Utility
|
|||||||
private IUserMessage oldMsg = null;
|
private IUserMessage oldMsg = null;
|
||||||
private Timer _t;
|
private Timer _t;
|
||||||
|
|
||||||
public RepeatRunner(DiscordShardedClient client, Repeater repeater)
|
public RepeatRunner(DiscordSocketClient client, Repeater repeater)
|
||||||
{
|
{
|
||||||
_log = LogManager.GetCurrentClassLogger();
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
Repeater = repeater;
|
Repeater = repeater;
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
using Discord;
|
|
||||||
using Discord.WebSocket;
|
|
||||||
using NadekoBot.Extensions;
|
|
||||||
using NadekoBot.Services.Database.Models;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace NadekoBot.Services.Utility
|
|
||||||
{
|
|
||||||
public class CrossServerTextService
|
|
||||||
{
|
|
||||||
public readonly ConcurrentDictionary<int, ConcurrentHashSet<ITextChannel>> Subscribers =
|
|
||||||
new ConcurrentDictionary<int, ConcurrentHashSet<ITextChannel>>();
|
|
||||||
private DiscordShardedClient _client;
|
|
||||||
|
|
||||||
public CrossServerTextService(IEnumerable<GuildConfig> guildConfigs, DiscordShardedClient client)
|
|
||||||
{
|
|
||||||
_client = client;
|
|
||||||
_client.MessageReceived += Client_MessageReceived;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Task Client_MessageReceived(SocketMessage imsg)
|
|
||||||
{
|
|
||||||
var _ = Task.Run(async () => {
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (imsg.Author.IsBot)
|
|
||||||
return;
|
|
||||||
var msg = imsg as IUserMessage;
|
|
||||||
if (msg == null)
|
|
||||||
return;
|
|
||||||
var channel = imsg.Channel as ITextChannel;
|
|
||||||
if (channel == null)
|
|
||||||
return;
|
|
||||||
if (msg.Author.Id == _client.CurrentUser.Id) return;
|
|
||||||
foreach (var subscriber in Subscribers)
|
|
||||||
{
|
|
||||||
var set = subscriber.Value;
|
|
||||||
if (!set.Contains(channel))
|
|
||||||
continue;
|
|
||||||
foreach (var chan in set.Except(new[] { channel }))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await chan.SendMessageAsync(GetMessage(channel, (IGuildUser)msg.Author,
|
|
||||||
msg)).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetMessage(ITextChannel channel, IGuildUser user, IUserMessage message) =>
|
|
||||||
$"**{channel.Guild.Name} | {channel.Name}** `{user.Username}`: " + message.Content.SanitizeMentions();
|
|
||||||
}
|
|
||||||
}
|
|
@ -50,12 +50,12 @@ namespace NadekoBot.Services.Utility
|
|||||||
|
|
||||||
public bool ToggleVerboseErrors(ulong guildId)
|
public bool ToggleVerboseErrors(ulong guildId)
|
||||||
{
|
{
|
||||||
|
bool enabled;
|
||||||
using (var uow = _db.UnitOfWork)
|
using (var uow = _db.UnitOfWork)
|
||||||
{
|
{
|
||||||
var gc = uow.GuildConfigs.For(guildId, set => set);
|
var gc = uow.GuildConfigs.For(guildId, set => set);
|
||||||
|
|
||||||
gc.VerboseErrors = !gc.VerboseErrors;
|
enabled = gc.VerboseErrors = !gc.VerboseErrors;
|
||||||
|
|
||||||
uow.Complete();
|
uow.Complete();
|
||||||
|
|
||||||
@ -65,15 +65,12 @@ namespace NadekoBot.Services.Utility
|
|||||||
guildsEnabled.TryRemove(guildId);
|
guildsEnabled.TryRemove(guildId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (guildsEnabled.Add(guildId))
|
if (enabled)
|
||||||
{
|
guildsEnabled.Add(guildId);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
guildsEnabled.TryRemove(guildId);
|
guildsEnabled.TryRemove(guildId);
|
||||||
return false;
|
|
||||||
}
|
return enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
109
src/NadekoBot/ShardsCoordinator.cs
Normal file
109
src/NadekoBot/ShardsCoordinator.cs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
using NadekoBot.DataStructures.ShardCom;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Impl;
|
||||||
|
using NLog;
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot
|
||||||
|
{
|
||||||
|
public class ShardsCoordinator
|
||||||
|
{
|
||||||
|
private readonly BotCredentials Credentials;
|
||||||
|
private Process[] ShardProcesses;
|
||||||
|
public ShardComMessage[] Statuses { get; }
|
||||||
|
public int GuildCount => Statuses.ToArray()
|
||||||
|
.Where(x => x != null)
|
||||||
|
.Sum(x => x.Guilds);
|
||||||
|
|
||||||
|
private readonly Logger _log;
|
||||||
|
private readonly ShardComServer _comServer;
|
||||||
|
private readonly int _port;
|
||||||
|
|
||||||
|
public ShardsCoordinator(int port)
|
||||||
|
{
|
||||||
|
LogSetup.SetupLogger();
|
||||||
|
Credentials = new BotCredentials();
|
||||||
|
ShardProcesses = new Process[Credentials.TotalShards];
|
||||||
|
Statuses = new ShardComMessage[Credentials.TotalShards];
|
||||||
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
_port = port;
|
||||||
|
|
||||||
|
_comServer = new ShardComServer(port);
|
||||||
|
_comServer.Start();
|
||||||
|
|
||||||
|
_comServer.OnDataReceived += _comServer_OnDataReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task _comServer_OnDataReceived(ShardComMessage msg)
|
||||||
|
{
|
||||||
|
Statuses[msg.ShardId] = msg;
|
||||||
|
if (msg.ConnectionState == Discord.ConnectionState.Disconnected || msg.ConnectionState == Discord.ConnectionState.Disconnecting)
|
||||||
|
_log.Error("!!! SHARD {0} IS IN {1} STATE", msg.ShardId, msg.ConnectionState.ToString());
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunAsync()
|
||||||
|
{
|
||||||
|
var curProcessId = Process.GetCurrentProcess().Id;
|
||||||
|
for (int i = 1; i < Credentials.TotalShards; i++)
|
||||||
|
{
|
||||||
|
var p = Process.Start(new ProcessStartInfo()
|
||||||
|
{
|
||||||
|
FileName = Credentials.ShardRunCommand,
|
||||||
|
Arguments = string.Format(Credentials.ShardRunArguments, i, curProcessId, _port)
|
||||||
|
});
|
||||||
|
await Task.Delay(5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunAndBlockAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await RunAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Error(ex);
|
||||||
|
}
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
string input;
|
||||||
|
while ((input = Console.ReadLine()?.ToLowerInvariant()) != "quit")
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (input)
|
||||||
|
{
|
||||||
|
case "ls":
|
||||||
|
var groupStr = string.Join(",", Statuses
|
||||||
|
.ToArray()
|
||||||
|
.Where(x => x != null)
|
||||||
|
.GroupBy(x => x.ConnectionState)
|
||||||
|
.Select(x => x.Count() + " " + x.Key));
|
||||||
|
_log.Info(string.Join("\n", Statuses
|
||||||
|
.ToArray()
|
||||||
|
.Where(x => x != null)
|
||||||
|
.Select(x => $"Shard {x.ShardId} is in {x.ConnectionState.ToString()} state with {x.Guilds} servers")) + "\n" + groupStr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Warn(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
foreach (var p in ShardProcesses)
|
||||||
|
{
|
||||||
|
try { p.Kill(); } catch { }
|
||||||
|
try { p.Dispose(); } catch { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -70,7 +70,7 @@ namespace NadekoBot.Extensions
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// danny kamisama
|
/// danny kamisama
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static async Task SendPaginatedConfirmAsync(this IMessageChannel channel, DiscordShardedClient client, int currentPage, Func<int, EmbedBuilder> pageFunc, int? lastPage = null, bool addPaginatedFooter = true)
|
public static async Task SendPaginatedConfirmAsync(this IMessageChannel channel, DiscordSocketClient client, int currentPage, Func<int, EmbedBuilder> pageFunc, int? lastPage = null, bool addPaginatedFooter = true)
|
||||||
{
|
{
|
||||||
var embed = pageFunc(currentPage);
|
var embed = pageFunc(currentPage);
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ namespace NadekoBot.Extensions
|
|||||||
return embed.WithFooter(efb => efb.WithText(curPage.ToString()));
|
return embed.WithFooter(efb => efb.WithText(curPage.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReactionEventWrapper OnReaction(this IUserMessage msg, DiscordShardedClient client, Action<SocketReaction> reactionAdded, Action<SocketReaction> reactionRemoved = null)
|
public static ReactionEventWrapper OnReaction(this IUserMessage msg, DiscordSocketClient client, Action<SocketReaction> reactionAdded, Action<SocketReaction> reactionRemoved = null)
|
||||||
{
|
{
|
||||||
if (reactionRemoved == null)
|
if (reactionRemoved == null)
|
||||||
reactionRemoved = delegate { };
|
reactionRemoved = delegate { };
|
||||||
|
@ -154,6 +154,7 @@
|
|||||||
"administration_old_topic": "Old topic",
|
"administration_old_topic": "Old topic",
|
||||||
"administration_perms": "Error. Most likely I don't have sufficient permissions.",
|
"administration_perms": "Error. Most likely I don't have sufficient permissions.",
|
||||||
"permissions_perms_reset": "Permissions for this server are reset.",
|
"permissions_perms_reset": "Permissions for this server are reset.",
|
||||||
|
"permissions_trigger": "Permission number #{0} {1} is preventing this action.",
|
||||||
"administration_prot_active": "Active protections",
|
"administration_prot_active": "Active protections",
|
||||||
"administration_prot_disable": "{0} has been **disabled** on this server.",
|
"administration_prot_disable": "{0} has been **disabled** on this server.",
|
||||||
"administration_prot_enable": "{0} Enabled",
|
"administration_prot_enable": "{0} Enabled",
|
||||||
@ -446,7 +447,7 @@
|
|||||||
"music_skipped_to": "Skipped to `{0}:{1}`",
|
"music_skipped_to": "Skipped to `{0}:{1}`",
|
||||||
"music_songs_shuffled": "Songs shuffled",
|
"music_songs_shuffled": "Songs shuffled",
|
||||||
"music_song_moved": "Song moved",
|
"music_song_moved": "Song moved",
|
||||||
"music_song_not_found": "No song found.",
|
"music_song_not_found": "No song found.",
|
||||||
"music_time_format": "{0}h {1}m {2}s",
|
"music_time_format": "{0}h {1}m {2}s",
|
||||||
"music_to_position": "To position",
|
"music_to_position": "To position",
|
||||||
"music_unlimited": "unlimited",
|
"music_unlimited": "unlimited",
|
||||||
@ -523,7 +524,7 @@
|
|||||||
"searches_cost": "Cost",
|
"searches_cost": "Cost",
|
||||||
"searches_date": "Date",
|
"searches_date": "Date",
|
||||||
"searches_define": "Define:",
|
"searches_define": "Define:",
|
||||||
"searches_define_unknown": "Can't find the definition for that term.",
|
"searches_define_unknown": "Can't find the definition for that term.",
|
||||||
"searches_dropped": "Dropped",
|
"searches_dropped": "Dropped",
|
||||||
"searches_episodes": "Episodes",
|
"searches_episodes": "Episodes",
|
||||||
"searches_error_occured": "Error occurred.",
|
"searches_error_occured": "Error occurred.",
|
||||||
@ -534,7 +535,7 @@
|
|||||||
"searches_hashtag_error": "Failed finding a definition for that tag.",
|
"searches_hashtag_error": "Failed finding a definition for that tag.",
|
||||||
"searches_height_weight": "Height/Weight",
|
"searches_height_weight": "Height/Weight",
|
||||||
"searches_height_weight_val": "{0}m/{1}kg",
|
"searches_height_weight_val": "{0}m/{1}kg",
|
||||||
"searches_hex_invalid": "Invalid color specified.",
|
"searches_hex_invalid": "Invalid color specified.",
|
||||||
"searches_humidity": "Humidity",
|
"searches_humidity": "Humidity",
|
||||||
"searches_image_search_for": "Image search for:",
|
"searches_image_search_for": "Image search for:",
|
||||||
"searches_imdb_fail": "Failed to find that movie.",
|
"searches_imdb_fail": "Failed to find that movie.",
|
||||||
@ -613,9 +614,6 @@
|
|||||||
"utility_convert_not_found": "Cannot convert {0} to {1}: units not found",
|
"utility_convert_not_found": "Cannot convert {0} to {1}: units not found",
|
||||||
"utility_convert_type_error": "Cannot convert {0} to {1}: types of unit are not equal",
|
"utility_convert_type_error": "Cannot convert {0} to {1}: types of unit are not equal",
|
||||||
"utility_created_at": "Created at",
|
"utility_created_at": "Created at",
|
||||||
"utility_csc_join": "Joined cross server channel.",
|
|
||||||
"utility_csc_leave": "Left cross server channel.",
|
|
||||||
"utility_csc_token": "This is your CSC token",
|
|
||||||
"utility_custom_emojis": "Custom emojis",
|
"utility_custom_emojis": "Custom emojis",
|
||||||
"utility_error": "Error",
|
"utility_error": "Error",
|
||||||
"utility_features": "Features",
|
"utility_features": "Features",
|
||||||
|
@ -15,5 +15,9 @@
|
|||||||
"Type": "sqlite",
|
"Type": "sqlite",
|
||||||
"ConnectionString": "Filename=./data/NadekoBot.db"
|
"ConnectionString": "Filename=./data/NadekoBot.db"
|
||||||
},
|
},
|
||||||
"TotalShards": 1
|
"TotalShards": 1,
|
||||||
|
"PatreonAccessToken": "",
|
||||||
|
"ShardRunCommand": "",
|
||||||
|
"ShardRunArguments": "",
|
||||||
|
"ShardRunPort": null
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user