- NadekoBot class renamed to Bot

- Implemented grpc based coordinator. Supports restarting, killing single or all shards, as well as getting current shard statuses. (Adaptation of the one used by the public bot)
- Coord is setup via coord.yml file
- Methods from SelfService which deal with shard/bot restart etc have been moved to ICoordinator (with GrpcRemoteCoordinator being the default implementation atm)
- Vastly simplified NadekoBot/Program.cs
This commit is contained in:
Kwoth
2021-06-19 13:13:54 +02:00
parent d8c7cdc7f4
commit c86bf6f300
58 changed files with 1212 additions and 635 deletions

View File

@@ -12,6 +12,7 @@ using System;
using System.Linq;
using System.Threading.Tasks;
using NadekoBot.Core.Services;
using NadekoBot.Services;
using Serilog;
namespace NadekoBot.Modules.Administration
@@ -22,14 +23,16 @@ namespace NadekoBot.Modules.Administration
public class SelfCommands : NadekoSubmodule<SelfService>
{
private readonly DiscordSocketClient _client;
private readonly NadekoBot _bot;
private readonly Bot _bot;
private readonly IBotStrings _strings;
private readonly ICoordinator _coord;
public SelfCommands(DiscordSocketClient client, NadekoBot bot, IBotStrings strings)
public SelfCommands(DiscordSocketClient client, Bot bot, IBotStrings strings, ICoordinator coord)
{
_client = client;
_bot = bot;
_strings = strings;
_coord = coord;
}
[NadekoCommand, Usage, Description, Aliases]
@@ -251,7 +254,7 @@ namespace NadekoBot.Modules.Administration
if (--page < 0)
return;
var statuses = _service.GetAllShardStatuses();
var statuses = _coord.GetAllShardStatuses();
var status = string.Join(", ", statuses
.GroupBy(x => x.ConnectionState)
@@ -289,7 +292,7 @@ namespace NadekoBot.Modules.Administration
[OwnerOnly]
public async Task RestartShard(int shardId)
{
var success = _service.RestartShard(shardId);
var success = _coord.RestartShard(shardId);
if (success)
{
await ReplyConfirmLocalizedAsync("shard_reconnecting", Format.Bold("#" + shardId)).ConfigureAwait(false);
@@ -321,14 +324,14 @@ namespace NadekoBot.Modules.Administration
// ignored
}
await Task.Delay(2000).ConfigureAwait(false);
_service.Die();
_coord.Die();
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task Restart()
{
bool success = _service.RestartBot();
bool success = _coord.RestartBot();
if (!success)
{
await ReplyErrorLocalizedAsync("restart_fail").ConfigureAwait(false);

View File

@@ -24,7 +24,7 @@ namespace NadekoBot.Modules.Administration.Services
private readonly DbService _db;
private readonly LogCommandService _logService;
public AdministrationService(NadekoBot bot, CommandHandler cmdHandler, DbService db,
public AdministrationService(Bot bot, CommandHandler cmdHandler, DbService db,
LogCommandService logService)
{
_db = db;

View File

@@ -31,7 +31,7 @@ namespace NadekoBot.Modules.Administration.Services
SingleWriter = false,
});
public AutoAssignRoleService(DiscordSocketClient client, NadekoBot bot, DbService db)
public AutoAssignRoleService(DiscordSocketClient client, Bot bot, DbService db)
{
_client = client;
_db = db;

View File

@@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Administration.Services
private readonly DbService _db;
private readonly DiscordSocketClient _client;
public GameVoiceChannelService(DiscordSocketClient client, DbService db, NadekoBot bot)
public GameVoiceChannelService(DiscordSocketClient client, DbService db, Bot bot)
{
_db = db;
_client = client;

View File

@@ -16,7 +16,7 @@ namespace NadekoBot.Modules.Administration.Services
private readonly ConcurrentDictionary<ulong, TimeZoneInfo> _timezones;
private readonly DbService _db;
public GuildTimezoneService(DiscordSocketClient client, NadekoBot bot, DbService db)
public GuildTimezoneService(DiscordSocketClient client, Bot bot, DbService db)
{
_timezones = bot.AllGuildConfigs
.Select(GetTimzezoneTuple)

View File

@@ -20,14 +20,14 @@ namespace NadekoBot.Modules.Administration.Services
private readonly BotConfigService _bss;
private readonly Replacer _rep;
private readonly DbService _db;
private readonly NadekoBot _bot;
private readonly Bot _bot;
private class TimerState
{
public int Index { get; set; }
}
public PlayingRotateService(DiscordSocketClient client, DbService db, NadekoBot bot,
public PlayingRotateService(DiscordSocketClient client, DbService db, Bot bot,
BotConfigService bss, IEnumerable<IPlaceholderProvider> phProviders)
{
_db = db;

View File

@@ -42,7 +42,7 @@ namespace NadekoBot.Modules.Administration.Services
SingleWriter = false
});
public ProtectionService(DiscordSocketClient client, NadekoBot bot,
public ProtectionService(DiscordSocketClient client, Bot bot,
MuteService mute, DbService db, UserPunishService punishService)
{
_client = client;

View File

@@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Administration.Services
private readonly ConcurrentDictionary<ulong, IndexedCollection<ReactionRoleMessage>> _models;
public RoleCommandsService(DiscordSocketClient client, DbService db,
NadekoBot bot)
Bot bot)
{
_db = db;
_client = client;

View File

@@ -9,14 +9,13 @@ using NadekoBot.Core.Services;
using StackExchange.Redis;
using System.Collections.Generic;
using System.Diagnostics;
using Newtonsoft.Json;
using NadekoBot.Common.ShardCom;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Core.Services.Database.Models;
using System.Threading;
using System.Collections.Concurrent;
using System;
using System.Net.Http;
using NadekoBot.Services;
using Serilog;
namespace NadekoBot.Modules.Administration.Services
@@ -41,10 +40,11 @@ namespace NadekoBot.Modules.Administration.Services
private readonly IImageCache _imgs;
private readonly IHttpClientFactory _httpFactory;
private readonly BotConfigService _bss;
private readonly ICoordinator _coord;
public SelfService(DiscordSocketClient client, CommandHandler cmdHandler, DbService db,
IBotStrings strings, IBotCredentials creds, IDataCache cache, IHttpClientFactory factory,
BotConfigService bss)
BotConfigService bss, ICoordinator coord)
{
_redis = cache.Redis;
_cmdHandler = cmdHandler;
@@ -56,6 +56,7 @@ namespace NadekoBot.Modules.Administration.Services
_imgs = cache.LocalImages;
_httpFactory = factory;
_bss = bss;
_coord = coord;
var sub = _redis.GetSubscriber();
if (_client.ShardId == 0)
@@ -281,18 +282,6 @@ namespace NadekoBot.Modules.Administration.Services
}
}
public bool RestartBot()
{
var cmd = _creds.RestartCommand;
if (string.IsNullOrWhiteSpace(cmd?.Cmd))
{
return false;
}
Restart();
return true;
}
public bool RemoveStartupCommand(int index, out AutoCommand cmd)
{
using (var uow = _db.GetDbContext())
@@ -385,32 +374,6 @@ namespace NadekoBot.Modules.Administration.Services
sub.Publish(_creds.RedisKey() + "_reload_images", "");
}
public void Die()
{
var sub = _cache.Redis.GetSubscriber();
sub.Publish(_creds.RedisKey() + "_die", "", CommandFlags.FireAndForget);
}
public void Restart()
{
Process.Start(_creds.RestartCommand.Cmd, _creds.RestartCommand.Args);
var sub = _cache.Redis.GetSubscriber();
sub.Publish(_creds.RedisKey() + "_die", "", CommandFlags.FireAndForget);
}
public bool RestartShard(int shardId)
{
if (shardId < 0 || shardId >= _creds.TotalShards)
return false;
var pub = _cache.Redis.GetSubscriber();
pub.Publish(_creds.RedisKey() + "_shardcoord_stop",
JsonConvert.SerializeObject(shardId),
CommandFlags.FireAndForget);
return true;
}
public bool ForwardMessages()
{
var isForwarding = false;
@@ -425,12 +388,5 @@ namespace NadekoBot.Modules.Administration.Services
_bss.ModifyConfig(config => { isToAll = config.ForwardToAllOwners = !config.ForwardToAllOwners; });
return isToAll;
}
public IEnumerable<ShardComMessage> GetAllShardStatuses()
{
var db = _cache.Redis.GetDatabase();
return db.ListRange(_creds.RedisKey() + "_shardstats")
.Select(x => JsonConvert.DeserializeObject<ShardComMessage>(x));
}
}
}

View File

@@ -456,7 +456,7 @@ WHERE GuildId={guildId}
{
template = JsonConvert.SerializeObject(new
{
color = NadekoBot.ErrorColor.RawValue,
color = Bot.ErrorColor.RawValue,
description = defaultMessage
});
@@ -477,7 +477,7 @@ WHERE GuildId={guildId}
{
template = JsonConvert.SerializeObject(new
{
color = NadekoBot.ErrorColor.RawValue,
color = Bot.ErrorColor.RawValue,
description = replacer.Replace(template)
});

View File

@@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Administration.Services
public ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, IRole>> VcRoles { get; }
public ConcurrentDictionary<ulong, ConcurrentQueue<(bool, IGuildUser, IRole)>> ToAssign { get; }
public VcRoleService(DiscordSocketClient client, NadekoBot bot, DbService db)
public VcRoleService(DiscordSocketClient client, Bot bot, DbService db)
{
_db = db;
_client = client;

View File

@@ -57,13 +57,13 @@ namespace NadekoBot.Modules.CustomReactions.Services
private readonly PermissionService _perms;
private readonly CommandHandler _cmd;
private readonly IBotStrings _strings;
private readonly NadekoBot _bot;
private readonly Bot _bot;
private readonly GlobalPermissionService _gperm;
private readonly CmdCdService _cmdCds;
private readonly IPubSub _pubSub;
private readonly Random _rng;
public CustomReactionsService(PermissionService perms, DbService db, IBotStrings strings, NadekoBot bot,
public CustomReactionsService(PermissionService perms, DbService db, IBotStrings strings, Bot bot,
DiscordSocketClient client, CommandHandler cmd, GlobalPermissionService gperm, CmdCdService cmdCds,
IPubSub pubSub)
{

View File

@@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Gambling.Services
{
private readonly DbService _db;
private readonly ICurrencyService _cs;
private readonly NadekoBot _bot;
private readonly Bot _bot;
private readonly DiscordSocketClient _client;
private readonly IDataCache _cache;
private readonly GamblingConfigService _gss;
@@ -31,7 +31,7 @@ namespace NadekoBot.Modules.Gambling.Services
private readonly Timer _decayTimer;
public GamblingService(DbService db, NadekoBot bot, ICurrencyService cs,
public GamblingService(DbService db, Bot bot, ICurrencyService cs,
DiscordSocketClient client, IDataCache cache, GamblingConfigService gss)
{
_db = db;

View File

@@ -48,7 +48,7 @@ namespace NadekoBot.Modules.Games
return;
var res = _service.GetEightballResponse(ctx.User.Id, question);
await ctx.Channel.EmbedAsync(new EmbedBuilder().WithColor(NadekoBot.OkColor)
await ctx.Channel.EmbedAsync(new EmbedBuilder().WithColor(Bot.OkColor)
.WithDescription(ctx.User.ToString())
.AddField(efb => efb.WithName("❓ " + GetText("question")).WithValue(question).WithIsInline(false))
.AddField("🎱 " + GetText("8ball"), res, false));

View File

@@ -30,7 +30,7 @@ namespace NadekoBot.Modules.Games.Services
public ModuleBehaviorType BehaviorType => ModuleBehaviorType.Executor;
public ChatterBotService(DiscordSocketClient client, PermissionService perms,
NadekoBot bot, CommandHandler cmd, IBotStrings strings, IHttpClientFactory factory,
Bot bot, CommandHandler cmd, IBotStrings strings, IHttpClientFactory factory,
IBotCredentials creds)
{
_client = client;

View File

@@ -83,7 +83,7 @@ namespace NadekoBot.Modules.Help.Services
arg => Format.Code(arg))))
.WithIsInline(false))
.WithFooter(efb => efb.WithText(GetText("module", guild, com.Module.GetTopLevelModule().Name)))
.WithColor(NadekoBot.OkColor);
.WithColor(Bot.OkColor);
var opt = ((NadekoOptionsAttribute)com.Attributes.FirstOrDefault(x => x is NadekoOptionsAttribute))?.OptionType;
if (opt != null)

View File

@@ -619,7 +619,7 @@ namespace NadekoBot.Modules.Music
.WithAuthor(eab => eab.WithName(GetText("song_moved")).WithIconUrl("https://cdn.discordapp.com/attachments/155726317222887425/258605269972549642/music1.png"))
.AddField(fb => fb.WithName(GetText("from_position")).WithValue($"#{from + 1}").WithIsInline(true))
.AddField(fb => fb.WithName(GetText("to_position")).WithValue($"#{to + 1}").WithIsInline(true))
.WithColor(NadekoBot.OkColor);
.WithColor(Bot.OkColor);
if (Uri.IsWellFormedUriString(track.Url, UriKind.Absolute))
embed.WithUrl(track.Url);

View File

@@ -18,7 +18,7 @@ namespace NadekoBot.Modules.Permissions.Services
public int Priority { get; } = 0;
public CmdCdService(NadekoBot bot)
public CmdCdService(Bot bot)
{
CommandCooldowns = new ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>>(
bot.AllGuildConfigs.ToDictionary(k => k.GuildId,

View File

@@ -325,7 +325,7 @@ namespace NadekoBot.Modules.Searches
}
await ctx.Channel.EmbedAsync(new EmbedBuilder()
.WithColor(NadekoBot.OkColor)
.WithColor(Bot.OkColor)
.AddField(efb => efb.WithName(GetText("original_url"))
.WithValue($"<{query}>"))
.AddField(efb => efb.WithName(GetText("short_url"))

View File

@@ -24,7 +24,7 @@ namespace NadekoBot.Modules.Searches.Services
private readonly ConcurrentDictionary<string, DateTime> _lastPosts =
new ConcurrentDictionary<string, DateTime>();
public FeedsService(NadekoBot bot, DbService db, DiscordSocketClient client)
public FeedsService(Bot bot, DbService db, DiscordSocketClient client)
{
_db = db;

View File

@@ -61,7 +61,7 @@ namespace NadekoBot.Modules.Searches.Services
private readonly List<string> _yomamaJokes;
public SearchesService(DiscordSocketClient client, IGoogleApiService google,
DbService db, NadekoBot bot, IDataCache cache, IHttpClientFactory factory,
DbService db, Bot bot, IDataCache cache, IHttpClientFactory factory,
FontProvider fonts, IBotCredentials creds)
{
_httpFactory = factory;

View File

@@ -46,7 +46,7 @@ namespace NadekoBot.Modules.Searches.Services
public StreamNotificationService(DbService db, DiscordSocketClient client,
IBotStrings strings, IDataCache cache, IBotCredentials creds, IHttpClientFactory httpFactory,
NadekoBot bot)
Bot bot)
{
_db = db;
_client = client;
@@ -457,7 +457,7 @@ namespace NadekoBot.Modules.Searches.Services
.AddField(efb => efb.WithName(GetText(guildId, "viewers"))
.WithValue(status.IsLive ? status.Viewers.ToString() : "-")
.WithIsInline(true))
.WithColor(status.IsLive ? NadekoBot.OkColor : NadekoBot.ErrorColor);
.WithColor(status.IsLive ? Bot.OkColor : Bot.ErrorColor);
if (!string.IsNullOrWhiteSpace(status.Title))
embed.WithAuthor(status.Title);

View File

@@ -34,7 +34,7 @@ namespace NadekoBot.Modules.Searches
{
var res = await http.GetStringAsync($"{_xkcdUrl}/info.0.json").ConfigureAwait(false);
var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
var embed = new EmbedBuilder().WithColor(NadekoBot.OkColor)
var embed = new EmbedBuilder().WithColor(Bot.OkColor)
.WithImageUrl(comic.ImageLink)
.WithAuthor(eab => eab.WithName(comic.Title).WithUrl($"{_xkcdUrl}/{comic.Num}").WithIconUrl("https://xkcd.com/s/919f27.ico"))
.AddField(efb => efb.WithName(GetText("comic_number")).WithValue(comic.Num.ToString()).WithIsInline(true))
@@ -69,7 +69,7 @@ namespace NadekoBot.Modules.Searches
var res = await http.GetStringAsync($"{_xkcdUrl}/{num}/info.0.json").ConfigureAwait(false);
var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
var embed = new EmbedBuilder().WithColor(NadekoBot.OkColor)
var embed = new EmbedBuilder().WithColor(Bot.OkColor)
.WithImageUrl(comic.ImageLink)
.WithAuthor(eab => eab.WithName(comic.Title).WithUrl($"{_xkcdUrl}/{num}").WithIconUrl("https://xkcd.com/s/919f27.ico"))
.AddField(efb => efb.WithName(GetText("comic_number")).WithValue(comic.Num.ToString()).WithIsInline(true))

View File

@@ -58,7 +58,7 @@ namespace NadekoBot.Modules.Utility
.AddField(fb => fb.WithName(GetText("region")).WithValue(guild.VoiceRegionId.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName(GetText("roles")).WithValue((guild.Roles.Count - 1).ToString()).WithIsInline(true))
.AddField(fb => fb.WithName(GetText("features")).WithValue(features).WithIsInline(true))
.WithColor(NadekoBot.OkColor);
.WithColor(Bot.OkColor);
if (Uri.IsWellFormedUriString(guild.IconUrl, UriKind.Absolute))
embed.WithThumbnailUrl(guild.IconUrl);
if (guild.Emotes.Any())
@@ -89,7 +89,7 @@ namespace NadekoBot.Modules.Utility
.AddField(fb => fb.WithName(GetText("id")).WithValue(ch.Id.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName(GetText("created_at")).WithValue($"{createdAt:dd.MM.yyyy HH:mm}").WithIsInline(true))
.AddField(fb => fb.WithName(GetText("users")).WithValue(usercount.ToString()).WithIsInline(true))
.WithColor(NadekoBot.OkColor);
.WithColor(Bot.OkColor);
await ctx.Channel.EmbedAsync(embed).ConfigureAwait(false);
}
@@ -112,7 +112,7 @@ namespace NadekoBot.Modules.Utility
.AddField(fb => fb.WithName(GetText("joined_server")).WithValue($"{user.JoinedAt?.ToString("dd.MM.yyyy HH:mm") ?? "?"}").WithIsInline(true))
.AddField(fb => fb.WithName(GetText("joined_discord")).WithValue($"{user.CreatedAt:dd.MM.yyyy HH:mm}").WithIsInline(true))
.AddField(fb => fb.WithName(GetText("roles")).WithValue($"**({user.RoleIds.Count - 1})** - {string.Join("\n", user.GetRoles().Take(10).Where(r => r.Id != r.Guild.EveryoneRole.Id).Select(r => r.Name)).SanitizeMentions(true)}").WithIsInline(true))
.WithColor(NadekoBot.OkColor);
.WithColor(Bot.OkColor);
var av = user.RealAvatarUrl();
if (av != null && av.IsAbsoluteUri)

View File

@@ -23,7 +23,7 @@ namespace NadekoBot.Modules.Utility.Services
private readonly DiscordSocketClient _client;
private readonly ConcurrentDictionary<ulong, StreamRoleSettings> guildSettings;
public StreamRoleService(DiscordSocketClient client, DbService db, NadekoBot bot)
public StreamRoleService(DiscordSocketClient client, DbService db, Bot bot)
{
_db = db;
_client = client;

View File

@@ -18,7 +18,7 @@ namespace NadekoBot.Modules.Utility.Services
private readonly CommandHandler _ch;
private readonly HelpService _hs;
public VerboseErrorsService(NadekoBot bot, DbService db, CommandHandler ch, HelpService hs)
public VerboseErrorsService(Bot bot, DbService db, CommandHandler ch, HelpService hs)
{
_db = db;
_ch = ch;

View File

@@ -16,6 +16,7 @@ using System.Threading;
using System.Threading.Tasks;
using NadekoBot.Common.Replacements;
using NadekoBot.Core.Common;
using NadekoBot.Services;
using Serilog;
namespace NadekoBot.Modules.Utility
@@ -23,18 +24,18 @@ namespace NadekoBot.Modules.Utility
public partial class Utility : NadekoModule
{
private readonly DiscordSocketClient _client;
private readonly ICoordinator _coord;
private readonly IStatsService _stats;
private readonly IBotCredentials _creds;
private readonly NadekoBot _bot;
private readonly DownloadTracker _tracker;
public Utility(NadekoBot nadeko, DiscordSocketClient client,
public Utility(DiscordSocketClient client, ICoordinator coord,
IStatsService stats, IBotCredentials creds, DownloadTracker tracker)
{
_client = client;
_coord = coord;
_stats = stats;
_creds = creds;
_bot = nadeko;
_tracker = tracker;
}
@@ -276,7 +277,7 @@ namespace NadekoBot.Modules.Utility
.AddField(efb => efb.WithName(GetText("uptime")).WithValue(_stats.GetUptimeString("\n")).WithIsInline(true))
.AddField(efb => efb.WithName(GetText("presence")).WithValue(
GetText("presence_txt",
_bot.GuildCount, _stats.TextChannels, _stats.VoiceChannels)).WithIsInline(true))).ConfigureAwait(false);
_coord.GetGuildCount(), _stats.TextChannels, _stats.VoiceChannels)).WithIsInline(true))).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]

View File

@@ -62,7 +62,7 @@ namespace NadekoBot.Modules.Xp.Services
private XpTemplate _template;
private readonly DiscordSocketClient _client;
public XpService(DiscordSocketClient client, CommandHandler cmd, NadekoBot bot, DbService db,
public XpService(DiscordSocketClient client, CommandHandler cmd, Bot bot, DbService db,
IBotStrings strings, IDataCache cache, FontProvider fonts, IBotCredentials creds,
ICurrencyService cs, IHttpClientFactory http, XpConfigService xpConfig)
{