From e32446335ebedb8fff97e6555c2fbce7a81a33e9 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Fri, 13 Oct 2017 02:21:39 +0200 Subject: [PATCH] Cleanup, .clparew can now be ran everyone, modules load appropriate guild configs, IEnumerable replaces with NadekoBot.AllGuildConfigs --- NadekoBot.Core/Common/Caching/FactoryCache.cs | 49 +++++++ .../Common/Caching/IFactoryCache.cs | 13 ++ .../Administration/DangerousCommands.cs | 48 +++++++ .../Services/AdministrationService.cs | 8 +- .../Services/AutoAssignRoleService.cs | 6 +- .../Services/GameVoiceChannelService.cs | 4 +- .../Services/GuildTimezoneService.cs | 10 +- .../Services/LogCommandService.cs | 4 +- .../Administration/Services/MuteService.cs | 21 +-- .../Services/ProtectionService.cs | 5 +- .../Services/RatelimitService.cs | 6 +- .../Administration/Services/SelfService.cs | 6 +- .../Administration/Services/VcRoleService.cs | 4 +- .../Administration/Services/VplusTService.cs | 4 +- .../Permissions/Services/CmdCdService.cs | 4 +- .../Permissions/Services/FilterService.cs | 12 +- NadekoBot.Core/Services/CommandHandler.cs | 6 +- .../Services/Database/NadekoContext.cs | 2 - .../Services/GreetSettingsService.cs | 12 +- NadekoBot.Core/Services/Impl/Localization.cs | 7 +- NadekoBot.Core/Services/Impl/StatsService.cs | 4 +- NadekoBot.Core/Services/NadekoBot.cs | 15 +- NadekoBot.Core/Services/ServiceProvider.cs | 10 ++ NadekoBot.Core/Services/ShardsCoordinator.cs | 4 + .../Services/WaifuService.cs | 12 ++ .../WaifuClaimCommands.cs | 19 +-- .../Services/ChatterbotService.cs | 8 +- .../Services/GamesService.cs | 5 +- .../Services/MusicService.cs | 6 +- .../Services/FeedsService.cs | 9 +- .../Services/SearchesService.cs | 5 +- NadekoBot.Modules.Utility/PatreonCommands.cs | 6 +- .../Services/CommandMapService.cs | 4 +- .../Services/ConverterService.cs | 1 + .../Services/MessageRepeaterService.cs | 27 ++-- .../Services/PatreonRewardsService.cs | 130 ++++++++++-------- .../Services/StreamRoleService.cs | 5 +- .../Services/VerboseErrorsService.cs | 7 +- NadekoBot.Modules.Xp/Services/XpService.cs | 6 +- src/NadekoBot/data/command_strings.json | 2 +- 40 files changed, 336 insertions(+), 180 deletions(-) create mode 100644 NadekoBot.Core/Common/Caching/FactoryCache.cs create mode 100644 NadekoBot.Core/Common/Caching/IFactoryCache.cs create mode 100644 NadekoBot.Core/Modules/Administration/DangerousCommands.cs create mode 100644 NadekoBot.Modules.Gambling/Services/WaifuService.cs diff --git a/NadekoBot.Core/Common/Caching/FactoryCache.cs b/NadekoBot.Core/Common/Caching/FactoryCache.cs new file mode 100644 index 00000000..3d7bfbe4 --- /dev/null +++ b/NadekoBot.Core/Common/Caching/FactoryCache.cs @@ -0,0 +1,49 @@ +using System; + +namespace NadekoBot.Core.Common.Caching +{ + /// + /// A caching object which loads its value with a factory method when it expires. + /// + /// Type of the value which is cached. + public class FactoryCache : IFactoryCache + { + public DateTime LastUpdate { get; set; } = DateTime.MinValue; + private readonly object _locker = new object(); + private TimeSpan _expireAfter; + private readonly Func _factory; + private T Value; + + /// + /// Creates a new factory cache object. + /// + /// Method which loads the value when it expires or if it's not loaded the first time. + /// Time after which the value will be reloaded. + /// Should the value be loaded right away. If set to false, value will load when it's first retrieved. + public FactoryCache(Func factory, TimeSpan expireAfter, + bool loadImmediately = false) + { + _expireAfter = expireAfter; + _factory = factory; + if (loadImmediately) + { + Value = _factory(); + LastUpdate = DateTime.UtcNow; + } + } + + public T GetValue() + { + lock (_locker) + { + if (DateTime.UtcNow - LastUpdate > _expireAfter) + { + LastUpdate = DateTime.UtcNow; + return Value = _factory(); + } + + return Value; + } + } + } +} diff --git a/NadekoBot.Core/Common/Caching/IFactoryCache.cs b/NadekoBot.Core/Common/Caching/IFactoryCache.cs new file mode 100644 index 00000000..439152d4 --- /dev/null +++ b/NadekoBot.Core/Common/Caching/IFactoryCache.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Core.Common.Caching +{ + public interface IFactoryCache + { + + } +} diff --git a/NadekoBot.Core/Modules/Administration/DangerousCommands.cs b/NadekoBot.Core/Modules/Administration/DangerousCommands.cs new file mode 100644 index 00000000..4bb6ead5 --- /dev/null +++ b/NadekoBot.Core/Modules/Administration/DangerousCommands.cs @@ -0,0 +1,48 @@ +using Discord.Commands; +using Microsoft.EntityFrameworkCore; +using NadekoBot.Common.Attributes; +using NadekoBot.Extensions; +using NadekoBot.Modules; +using NadekoBot.Services; +using System; +using System.Threading.Tasks; + +#if DEBUG +namespace NadekoBot.Modules.Administration +{ + public partial class Administration + { + [Group] + [OwnerOnly] + public class DangerousCommands : NadekoSubmodule + { + private readonly DbService _db; + + public DangerousCommands(DbService db) + { + _db = db; + } + + [NadekoCommand, Usage, Description, Aliases] + [OwnerOnly] + public async Task ExecSql([Remainder]string sql) + { + try + { + int res; + using (var uow = _db.UnitOfWork) + { + res = uow._context.Database.ExecuteSqlCommand(sql); + } + + await Context.Channel.SendConfirmAsync(res.ToString()); + } + catch (Exception ex) + { + await Context.Channel.SendErrorAsync(ex.ToString()); + } + } + } + } +} +#endif \ No newline at end of file diff --git a/NadekoBot.Core/Modules/Administration/Services/AdministrationService.cs b/NadekoBot.Core/Modules/Administration/Services/AdministrationService.cs index 57ec29a8..9a43348a 100644 --- a/NadekoBot.Core/Modules/Administration/Services/AdministrationService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/AdministrationService.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Discord; @@ -7,7 +6,6 @@ using Discord.Commands; using Discord.WebSocket; using NadekoBot.Common.Collections; using NadekoBot.Services; -using NadekoBot.Services.Database.Models; using NLog; namespace NadekoBot.Modules.Administration.Services @@ -16,12 +14,14 @@ namespace NadekoBot.Modules.Administration.Services { public readonly ConcurrentHashSet DeleteMessagesOnCommand; private readonly Logger _log; + private readonly NadekoBot _bot; - public AdministrationService(IEnumerable gcs, CommandHandler cmdHandler) + public AdministrationService(NadekoBot bot, CommandHandler cmdHandler) { _log = LogManager.GetCurrentClassLogger(); + _bot = bot; - DeleteMessagesOnCommand = new ConcurrentHashSet(gcs.Where(g => g.DeleteMessageOnCommand).Select(g => g.GuildId)); + DeleteMessagesOnCommand = new ConcurrentHashSet(bot.AllGuildConfigs.Where(g => g.DeleteMessageOnCommand).Select(g => g.GuildId)); cmdHandler.CommandExecuted += DelMsgOnCmd_Handler; } diff --git a/NadekoBot.Core/Modules/Administration/Services/AutoAssignRoleService.cs b/NadekoBot.Core/Modules/Administration/Services/AutoAssignRoleService.cs index 040986cb..6ea37049 100644 --- a/NadekoBot.Core/Modules/Administration/Services/AutoAssignRoleService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/AutoAssignRoleService.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Discord.WebSocket; using NadekoBot.Services; -using NadekoBot.Services.Database.Models; using NLog; namespace NadekoBot.Modules.Administration.Services @@ -18,13 +16,13 @@ namespace NadekoBot.Modules.Administration.Services //guildid/roleid public ConcurrentDictionary AutoAssignedRoles { get; } - public AutoAssignRoleService(DiscordSocketClient client, IEnumerable gcs) + public AutoAssignRoleService(DiscordSocketClient client, NadekoBot bot) { _log = LogManager.GetCurrentClassLogger(); _client = client; AutoAssignedRoles = new ConcurrentDictionary( - gcs.Where(x => x.AutoAssignRoleId != 0) + bot.AllGuildConfigs.Where(x => x.AutoAssignRoleId != 0) .ToDictionary(k => k.GuildId, v => v.AutoAssignRoleId)); _client.UserJoined += (user) => diff --git a/NadekoBot.Core/Modules/Administration/Services/GameVoiceChannelService.cs b/NadekoBot.Core/Modules/Administration/Services/GameVoiceChannelService.cs index e97e0eb7..30191c54 100644 --- a/NadekoBot.Core/Modules/Administration/Services/GameVoiceChannelService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/GameVoiceChannelService.cs @@ -19,14 +19,14 @@ namespace NadekoBot.Modules.Administration.Services private readonly DbService _db; private readonly DiscordSocketClient _client; - public GameVoiceChannelService(DiscordSocketClient client, DbService db, IEnumerable gcs) + public GameVoiceChannelService(DiscordSocketClient client, DbService db, NadekoBot bot) { _log = LogManager.GetCurrentClassLogger(); _db = db; _client = client; GameVoiceChannels = new ConcurrentHashSet( - gcs.Where(gc => gc.GameVoiceChannel != null) + bot.AllGuildConfigs.Where(gc => gc.GameVoiceChannel != null) .Select(gc => gc.GameVoiceChannel.Value)); _client.UserVoiceStateUpdated += Client_UserVoiceStateUpdated; diff --git a/NadekoBot.Core/Modules/Administration/Services/GuildTimezoneService.cs b/NadekoBot.Core/Modules/Administration/Services/GuildTimezoneService.cs index fdef20c5..1f4e44cd 100644 --- a/NadekoBot.Core/Modules/Administration/Services/GuildTimezoneService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/GuildTimezoneService.cs @@ -16,9 +16,9 @@ namespace NadekoBot.Modules.Administration.Services private ConcurrentDictionary _timezones; private readonly DbService _db; - public GuildTimezoneService(DiscordSocketClient client, IEnumerable gcs, DbService db) + public GuildTimezoneService(DiscordSocketClient client, NadekoBot bot, DbService db) { - _timezones = gcs + _timezones = bot.AllGuildConfigs .Select(x => { TimeZoneInfo tz; @@ -33,10 +33,10 @@ namespace NadekoBot.Modules.Administration.Services { tz = null; } - return (x.GuildId, tz); + return (x.GuildId, Timezone: tz); }) - .Where(x => x.Item2 != null) - .ToDictionary(x => x.Item1, x => x.Item2) + .Where(x => x.Timezone != null) + .ToDictionary(x => x.GuildId, x => x.Timezone) .ToConcurrent(); var curUser = client.CurrentUser; diff --git a/NadekoBot.Core/Modules/Administration/Services/LogCommandService.cs b/NadekoBot.Core/Modules/Administration/Services/LogCommandService.cs index 37b2781e..2400afc5 100644 --- a/NadekoBot.Core/Modules/Administration/Services/LogCommandService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/LogCommandService.cs @@ -50,7 +50,7 @@ namespace NadekoBot.Modules.Administration.Services private readonly GuildTimezoneService _tz; public LogCommandService(DiscordSocketClient client, NadekoStrings strings, - IEnumerable gcs, DbService db, MuteService mute, ProtectionService prot, GuildTimezoneService tz) + NadekoBot bot, DbService db, MuteService mute, ProtectionService prot, GuildTimezoneService tz) { _client = client; _log = LogManager.GetCurrentClassLogger(); @@ -60,7 +60,7 @@ namespace NadekoBot.Modules.Administration.Services _prot = prot; _tz = tz; - GuildLogSettings = gcs + GuildLogSettings = bot.AllGuildConfigs .ToDictionary(g => g.GuildId, g => g.LogSetting) .ToConcurrent(); diff --git a/NadekoBot.Core/Modules/Administration/Services/MuteService.cs b/NadekoBot.Core/Modules/Administration/Services/MuteService.cs index 77b4136c..917f90e8 100644 --- a/NadekoBot.Core/Modules/Administration/Services/MuteService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/MuteService.cs @@ -38,22 +38,25 @@ namespace NadekoBot.Modules.Administration.Services private readonly DiscordSocketClient _client; private readonly DbService _db; - public MuteService(DiscordSocketClient client, IEnumerable gcs, DbService db) + public MuteService(DiscordSocketClient client, NadekoBot bot, DbService db) { _client = client; _db = db; - GuildMuteRoles = gcs - .Where(c => !string.IsNullOrWhiteSpace(c.MuteRoleName)) - .ToDictionary(c => c.GuildId, c => c.MuteRoleName) - .ToConcurrent(); + GuildMuteRoles = bot + .AllGuildConfigs + .Where(c => !string.IsNullOrWhiteSpace(c.MuteRoleName)) + .ToDictionary(c => c.GuildId, c => c.MuteRoleName) + .ToConcurrent(); - MutedUsers = new ConcurrentDictionary>(gcs.ToDictionary( - k => k.GuildId, - v => new ConcurrentHashSet(v.MutedUsers.Select(m => m.UserId)) + MutedUsers = new ConcurrentDictionary>(bot + .AllGuildConfigs + .ToDictionary( + k => k.GuildId, + v => new ConcurrentHashSet(v.MutedUsers.Select(m => m.UserId)) )); - foreach (var conf in gcs) + foreach (var conf in bot.AllGuildConfigs) { foreach (var x in conf.UnmuteTimers) { diff --git a/NadekoBot.Core/Modules/Administration/Services/ProtectionService.cs b/NadekoBot.Core/Modules/Administration/Services/ProtectionService.cs index ea65fd3f..94397ab6 100644 --- a/NadekoBot.Core/Modules/Administration/Services/ProtectionService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/ProtectionService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Discord; @@ -26,13 +25,13 @@ namespace NadekoBot.Modules.Administration.Services private readonly DiscordSocketClient _client; private readonly MuteService _mute; - public ProtectionService(DiscordSocketClient client, IEnumerable gcs, MuteService mute) + public ProtectionService(DiscordSocketClient client, NadekoBot bot, MuteService mute) { _log = LogManager.GetCurrentClassLogger(); _client = client; _mute = mute; - foreach (var gc in gcs) + foreach (var gc in bot.AllGuildConfigs) { var raid = gc.AntiRaidSetting; var spam = gc.AntiSpamSetting; diff --git a/NadekoBot.Core/Modules/Administration/Services/RatelimitService.cs b/NadekoBot.Core/Modules/Administration/Services/RatelimitService.cs index 9667d193..68bcffe6 100644 --- a/NadekoBot.Core/Modules/Administration/Services/RatelimitService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/RatelimitService.cs @@ -23,17 +23,17 @@ namespace NadekoBot.Modules.Administration.Services private readonly Logger _log; private readonly DiscordSocketClient _client; - public SlowmodeService(DiscordSocketClient client, IEnumerable gcs) + public SlowmodeService(DiscordSocketClient client, NadekoBot bot) { _log = LogManager.GetCurrentClassLogger(); _client = client; IgnoredRoles = new ConcurrentDictionary>( - gcs.ToDictionary(x => x.GuildId, + bot.AllGuildConfigs.ToDictionary(x => x.GuildId, x => new HashSet(x.SlowmodeIgnoredRoles.Select(y => y.RoleId)))); IgnoredUsers = new ConcurrentDictionary>( - gcs.ToDictionary(x => x.GuildId, + bot.AllGuildConfigs.ToDictionary(x => x.GuildId, x => new HashSet(x.SlowmodeIgnoredUsers.Select(y => y.UserId)))); } diff --git a/NadekoBot.Core/Modules/Administration/Services/SelfService.cs b/NadekoBot.Core/Modules/Administration/Services/SelfService.cs index c0a811fa..74fe7b2f 100644 --- a/NadekoBot.Core/Modules/Administration/Services/SelfService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/SelfService.cs @@ -42,7 +42,7 @@ namespace NadekoBot.Modules.Administration.Services _creds = creds; _bc = bc; - var _ = Task.Run(async () => + Task.Run(async () => { await bot.Ready.Task.ConfigureAwait(false); @@ -57,14 +57,12 @@ namespace NadekoBot.Modules.Administration.Services } }); - var ___ = Task.Run(async () => + Task.Run(async () => { await bot.Ready.Task.ConfigureAwait(false); await Task.Delay(5000); - _client.Guilds.SelectMany(g => g.Users); - if(client.ShardId == 0) LoadOwnerChannels(); }); diff --git a/NadekoBot.Core/Modules/Administration/Services/VcRoleService.cs b/NadekoBot.Core/Modules/Administration/Services/VcRoleService.cs index 9f4f1b53..7879f171 100644 --- a/NadekoBot.Core/Modules/Administration/Services/VcRoleService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/VcRoleService.cs @@ -19,7 +19,7 @@ namespace NadekoBot.Modules.Administration.Services public ConcurrentDictionary> VcRoles { get; } - public VcRoleService(DiscordSocketClient client, IEnumerable gcs, DbService db) + public VcRoleService(DiscordSocketClient client, NadekoBot bot, DbService db) { _log = LogManager.GetCurrentClassLogger(); _db = db; @@ -28,7 +28,7 @@ namespace NadekoBot.Modules.Administration.Services _client.UserVoiceStateUpdated += ClientOnUserVoiceStateUpdated; VcRoles = new ConcurrentDictionary>(); var missingRoles = new List(); - foreach (var gconf in gcs) + foreach (var gconf in bot.AllGuildConfigs) { var g = _client.GetGuild(gconf.GuildId); if (g == null) diff --git a/NadekoBot.Core/Modules/Administration/Services/VplusTService.cs b/NadekoBot.Core/Modules/Administration/Services/VplusTService.cs index 9ffd8dcb..101e29f8 100644 --- a/NadekoBot.Core/Modules/Administration/Services/VplusTService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/VplusTService.cs @@ -28,7 +28,7 @@ namespace NadekoBot.Modules.Administration.Services private readonly DbService _db; private readonly Logger _log; - public VplusTService(DiscordSocketClient client, IEnumerable gcs, NadekoStrings strings, + public VplusTService(DiscordSocketClient client, NadekoBot bot, NadekoStrings strings, DbService db) { _client = client; @@ -36,7 +36,7 @@ namespace NadekoBot.Modules.Administration.Services _db = db; _log = LogManager.GetCurrentClassLogger(); - VoicePlusTextCache = new ConcurrentHashSet(gcs.Where(g => g.VoicePlusTextEnabled).Select(g => g.GuildId)); + VoicePlusTextCache = new ConcurrentHashSet(bot.AllGuildConfigs.Where(g => g.VoicePlusTextEnabled).Select(g => g.GuildId)); _client.UserVoiceStateUpdated += UserUpdatedEventHandler; } diff --git a/NadekoBot.Core/Modules/Permissions/Services/CmdCdService.cs b/NadekoBot.Core/Modules/Permissions/Services/CmdCdService.cs index bead8238..87a3f6dc 100644 --- a/NadekoBot.Core/Modules/Permissions/Services/CmdCdService.cs +++ b/NadekoBot.Core/Modules/Permissions/Services/CmdCdService.cs @@ -16,10 +16,10 @@ namespace NadekoBot.Modules.Permissions.Services public ConcurrentDictionary> CommandCooldowns { get; } public ConcurrentDictionary> ActiveCooldowns { get; } = new ConcurrentDictionary>(); - public CmdCdService(IEnumerable gcs) + public CmdCdService(NadekoBot bot) { CommandCooldowns = new ConcurrentDictionary>( - gcs.ToDictionary(k => k.GuildId, + bot.AllGuildConfigs.ToDictionary(k => k.GuildId, v => new ConcurrentHashSet(v.CommandCooldowns))); } diff --git a/NadekoBot.Core/Modules/Permissions/Services/FilterService.cs b/NadekoBot.Core/Modules/Permissions/Services/FilterService.cs index e15926a9..d09aa9ba 100644 --- a/NadekoBot.Core/Modules/Permissions/Services/FilterService.cs +++ b/NadekoBot.Core/Modules/Permissions/Services/FilterService.cs @@ -43,21 +43,21 @@ namespace NadekoBot.Modules.Permissions.Services return words; } - public FilterService(DiscordSocketClient _client, IEnumerable gcs) + public FilterService(DiscordSocketClient _client, NadekoBot bot) { _log = LogManager.GetCurrentClassLogger(); - InviteFilteringServers = new ConcurrentHashSet(gcs.Where(gc => gc.FilterInvites).Select(gc => gc.GuildId)); - InviteFilteringChannels = new ConcurrentHashSet(gcs.SelectMany(gc => gc.FilterInvitesChannelIds.Select(fci => fci.ChannelId))); + InviteFilteringServers = new ConcurrentHashSet(bot.AllGuildConfigs.Where(gc => gc.FilterInvites).Select(gc => gc.GuildId)); + InviteFilteringChannels = new ConcurrentHashSet(bot.AllGuildConfigs.SelectMany(gc => gc.FilterInvitesChannelIds.Select(fci => fci.ChannelId))); - var dict = gcs.ToDictionary(gc => gc.GuildId, gc => new ConcurrentHashSet(gc.FilteredWords.Select(fw => fw.Word))); + var dict = bot.AllGuildConfigs.ToDictionary(gc => gc.GuildId, gc => new ConcurrentHashSet(gc.FilteredWords.Select(fw => fw.Word))); ServerFilteredWords = new ConcurrentDictionary>(dict); - var serverFiltering = gcs.Where(gc => gc.FilterWords); + var serverFiltering = bot.AllGuildConfigs.Where(gc => gc.FilterWords); WordFilteringServers = new ConcurrentHashSet(serverFiltering.Select(gc => gc.GuildId)); - WordFilteringChannels = new ConcurrentHashSet(gcs.SelectMany(gc => gc.FilterWordsChannelIds.Select(fwci => fwci.ChannelId))); + WordFilteringChannels = new ConcurrentHashSet(bot.AllGuildConfigs.SelectMany(gc => gc.FilterWordsChannelIds.Select(fwci => fwci.ChannelId))); _client.MessageUpdated += (oldData, newMsg, channel) => { diff --git a/NadekoBot.Core/Services/CommandHandler.cs b/NadekoBot.Core/Services/CommandHandler.cs index c06d14ab..6b9e67b8 100644 --- a/NadekoBot.Core/Services/CommandHandler.cs +++ b/NadekoBot.Core/Services/CommandHandler.cs @@ -51,7 +51,9 @@ namespace NadekoBot.Services public ConcurrentHashSet UsersOnShortCooldown { get; } = new ConcurrentHashSet(); private readonly Timer _clearUsersOnShortCooldown; - public CommandHandler(DiscordSocketClient client, DbService db, IBotConfigProvider bc, IEnumerable gcs, CommandService commandService, IBotCredentials credentials, NadekoBot bot) + public CommandHandler(DiscordSocketClient client, DbService db, + IBotConfigProvider bc, CommandService commandService, + IBotCredentials credentials, NadekoBot bot) { _client = client; _commandService = commandService; @@ -67,7 +69,7 @@ namespace NadekoBot.Services }, null, GlobalCommandsCooldown, GlobalCommandsCooldown); DefaultPrefix = bc.BotConfig.DefaultPrefix; - _prefixes = gcs + _prefixes = bot.AllGuildConfigs .Where(x => x.Prefix != null) .ToDictionary(x => x.GuildId, x => x.Prefix) .ToConcurrent(); diff --git a/NadekoBot.Core/Services/Database/NadekoContext.cs b/NadekoBot.Core/Services/Database/NadekoContext.cs index 2d484582..b4079f17 100644 --- a/NadekoBot.Core/Services/Database/NadekoContext.cs +++ b/NadekoBot.Core/Services/Database/NadekoContext.cs @@ -29,8 +29,6 @@ namespace NadekoBot.Services.Database public DbSet Quotes { get; set; } public DbSet Donators { get; set; } public DbSet GuildConfigs { get; set; } - public DbSet ClashOfClans { get; set; } - public DbSet ClashCallers { get; set; } public DbSet Reminders { get; set; } public DbSet SelfAssignableRoles { get; set; } public DbSet BotConfig { get; set; } diff --git a/NadekoBot.Core/Services/GreetSettingsService.cs b/NadekoBot.Core/Services/GreetSettingsService.cs index 2d8b5e9b..dc73c978 100644 --- a/NadekoBot.Core/Services/GreetSettingsService.cs +++ b/NadekoBot.Core/Services/GreetSettingsService.cs @@ -21,13 +21,15 @@ namespace NadekoBot.Services private readonly DiscordSocketClient _client; private readonly Logger _log; - public GreetSettingsService(DiscordSocketClient client, IEnumerable guildConfigs, DbService db) + public GreetSettingsService(DiscordSocketClient client, NadekoBot bot, DbService db) { _db = db; _client = client; _log = LogManager.GetCurrentClassLogger(); - GuildConfigsCache = new ConcurrentDictionary(guildConfigs.ToDictionary(g => g.GuildId, GreetSettings.Create)); + GuildConfigsCache = new ConcurrentDictionary( + bot.AllGuildConfigs + .ToDictionary(g => g.GuildId, GreetSettings.Create)); _client.UserJoined += UserJoined; _client.UserLeft += UserLeft; @@ -180,10 +182,8 @@ namespace NadekoBot.Services public GreetSettings GetOrAddSettingsForGuild(ulong guildId) { - GreetSettings settings; - GuildConfigsCache.TryGetValue(guildId, out settings); - - if (settings != null) + if(GuildConfigsCache.TryGetValue(guildId, out var settings) && + settings != null) return settings; using (var uow = _db.UnitOfWork) diff --git a/NadekoBot.Core/Services/Impl/Localization.cs b/NadekoBot.Core/Services/Impl/Localization.cs index 8bc0d257..dd25aa56 100644 --- a/NadekoBot.Core/Services/Impl/Localization.cs +++ b/NadekoBot.Core/Services/Impl/Localization.cs @@ -28,11 +28,11 @@ namespace NadekoBot.Services.Impl } private Localization() { } - public Localization(IBotConfigProvider bcp, IEnumerable gcs, DbService db) + public Localization(IBotConfigProvider bcp, NadekoBot bot, DbService db) { _log = LogManager.GetCurrentClassLogger(); - var cultureInfoNames = gcs.ToDictionary(x => x.GuildId, x => x.Locale); + var cultureInfoNames = bot.AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.Locale); var defaultCulture = bcp.BotConfig.Locale; _db = db; @@ -123,8 +123,7 @@ namespace NadekoBot.Services.Impl { if (guildId == null) return DefaultCultureInfo; - CultureInfo info = null; - GuildCultureInfos.TryGetValue(guildId.Value, out info); + GuildCultureInfos.TryGetValue(guildId.Value, out CultureInfo info); return info ?? DefaultCultureInfo; } diff --git a/NadekoBot.Core/Services/Impl/StatsService.cs b/NadekoBot.Core/Services/Impl/StatsService.cs index 89b9543d..c667791e 100644 --- a/NadekoBot.Core/Services/Impl/StatsService.cs +++ b/NadekoBot.Core/Services/Impl/StatsService.cs @@ -42,7 +42,6 @@ namespace NadekoBot.Services.Impl private readonly Timer _carbonitexTimer; private readonly Timer _dataTimer; - private readonly ShardsCoordinator _sc; private readonly ConnectionMultiplexer _redis; public StatsService(DiscordSocketClient client, CommandHandler cmdHandler, @@ -51,7 +50,6 @@ namespace NadekoBot.Services.Impl { _client = client; _creds = creds; - _sc = nadeko.ShardCoord; _redis = cache.Redis; _started = DateTime.UtcNow; @@ -134,7 +132,7 @@ namespace NadekoBot.Services.Impl return Task.CompletedTask; }; - if (_sc != null) + if (_client.ShardId == 0) { _carbonitexTimer = new Timer(async (state) => { diff --git a/NadekoBot.Core/Services/NadekoBot.cs b/NadekoBot.Core/Services/NadekoBot.cs index bc891a65..dd9a60a9 100644 --- a/NadekoBot.Core/Services/NadekoBot.cs +++ b/NadekoBot.Core/Services/NadekoBot.cs @@ -48,8 +48,6 @@ namespace NadekoBot public INServiceProvider Services { get; private set; } - public ShardsCoordinator ShardCoord { get; private set; } - private readonly BotConfig _botConfig; public IDataCache Cache { get; private set; } @@ -143,9 +141,6 @@ namespace NadekoBot .AddManual(Client) .AddManual(CommandService) .AddManual(botConfigProvider) - //todo this needs to reload whenever a new service is supposed to be loaded - //except at startup for obvious reasons - .AddManual>(AllGuildConfigs) //todo wrap this .AddManual(this) .AddManual(uow) .AddManual(Cache); @@ -255,9 +250,6 @@ namespace NadekoBot public async Task RunAsync(params string[] args) { - if (Client.ShardId == 0) - _log.Info("Starting NadekoBot v" + StatsService.BotVersion); - var sw = Stopwatch.StartNew(); await LoginAsync(Credentials.Token).ConfigureAwait(false); @@ -450,7 +442,12 @@ namespace NadekoBot { if (_packageModules.ContainsKey(name)) return false; - + + var startingGuildIdList = Client.Guilds.Select(x => (long)x.Id).ToList(); + using (var uow = _db.UnitOfWork) + { + AllGuildConfigs = uow.GuildConfigs.GetAllGuildConfigs(startingGuildIdList).ToImmutableArray(); + } var package = Assembly.LoadFile(Path.Combine(AppContext.BaseDirectory, "modules", $"NadekoBot.Modules.{name}", diff --git a/NadekoBot.Core/Services/ServiceProvider.cs b/NadekoBot.Core/Services/ServiceProvider.cs index c0c8df7c..eb806090 100644 --- a/NadekoBot.Core/Services/ServiceProvider.cs +++ b/NadekoBot.Core/Services/ServiceProvider.cs @@ -54,6 +54,16 @@ namespace NadekoBot.Services return this; } + public INServiceProvider UpdateManual(T obj) + { + lock (_locker) + { + _services.Remove(typeof(T)); + _services.TryAdd(typeof(T), obj); + } + return this; + } + public IEnumerable LoadFrom(Assembly assembly) { List addedTypes = new List(); diff --git a/NadekoBot.Core/Services/ShardsCoordinator.cs b/NadekoBot.Core/Services/ShardsCoordinator.cs index cc343ab0..7816d466 100644 --- a/NadekoBot.Core/Services/ShardsCoordinator.cs +++ b/NadekoBot.Core/Services/ShardsCoordinator.cs @@ -27,7 +27,11 @@ namespace NadekoBot.Services LogSetup.SetupLogger(); _log = LogManager.GetCurrentClassLogger(); _creds = new BotCredentials(); + + _log.Info("Starting NadekoBot v" + StatsService.BotVersion); + _key = _creds.RedisKey(); + _redis = ConnectionMultiplexer.Connect("127.0.0.1"); //setup initial shard statuses _defaultShardState = new ShardComMessage() diff --git a/NadekoBot.Modules.Gambling/Services/WaifuService.cs b/NadekoBot.Modules.Gambling/Services/WaifuService.cs new file mode 100644 index 00000000..fea6a07f --- /dev/null +++ b/NadekoBot.Modules.Gambling/Services/WaifuService.cs @@ -0,0 +1,12 @@ +using NadekoBot.Services; +using System; +using System.Collections.Concurrent; + +namespace NadekoBot.Modules.Gambling.Services +{ + public class WaifuService : INService + { + public ConcurrentDictionary DivorceCooldowns { get; } = new ConcurrentDictionary(); + public ConcurrentDictionary AffinityCooldowns { get; } = new ConcurrentDictionary(); + } +} diff --git a/NadekoBot.Modules.Gambling/WaifuClaimCommands.cs b/NadekoBot.Modules.Gambling/WaifuClaimCommands.cs index 875fd01c..2adf7a11 100644 --- a/NadekoBot.Modules.Gambling/WaifuClaimCommands.cs +++ b/NadekoBot.Modules.Gambling/WaifuClaimCommands.cs @@ -4,13 +4,17 @@ using NadekoBot.Extensions; using NadekoBot.Services; using NadekoBot.Services.Database.Models; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using NadekoBot.Common; using NadekoBot.Common.Attributes; +using NadekoBot.Modules.Gambling.Services; +//todo add .deletewaifus +//todo add .deletecurrency +//todo add .deleteplaylists +//todo add .deletexp namespace NadekoBot.Modules.Gambling { public partial class Gambling @@ -44,13 +48,10 @@ namespace NadekoBot.Modules.Gambling Depraved, Harlot } - //todo unclaimed waifus should lose 3% of their value a day - [Group] - public class WaifuClaimCommands : NadekoSubmodule - { - private static ConcurrentDictionary _divorceCooldowns { get; } = new ConcurrentDictionary(); - private static ConcurrentDictionary _affinityCooldowns { get; } = new ConcurrentDictionary(); + [Group] + public class WaifuClaimCommands : NadekoSubmodule + { enum WaifuClaimResult { Success, @@ -219,7 +220,7 @@ namespace NadekoBot.Modules.Gambling var now = DateTime.UtcNow; if (w?.Claimer == null || w.Claimer.UserId != Context.User.Id) result = DivorceResult.NotYourWife; - else if (_divorceCooldowns.AddOrUpdate(Context.User.Id, + else if (_service.DivorceCooldowns.AddOrUpdate(Context.User.Id, now, (key, old) => ((difference = now.Subtract(old)) > _divorceLimit) ? now : old) != now) { @@ -303,7 +304,7 @@ namespace NadekoBot.Modules.Gambling if (w?.Affinity?.UserId == u?.Id) { } - else if (_affinityCooldowns.AddOrUpdate(Context.User.Id, + else if (_service.AffinityCooldowns.AddOrUpdate(Context.User.Id, now, (key, old) => ((difference = now.Subtract(old)) > _affinityLimit) ? now : old) != now) { diff --git a/NadekoBot.Modules.Games/Services/ChatterbotService.cs b/NadekoBot.Modules.Games/Services/ChatterbotService.cs index a137b953..3d2e6d43 100644 --- a/NadekoBot.Modules.Games/Services/ChatterbotService.cs +++ b/NadekoBot.Modules.Games/Services/ChatterbotService.cs @@ -28,8 +28,9 @@ namespace NadekoBot.Modules.Games.Services public ConcurrentDictionary> ChatterBotGuilds { get; } - public ChatterBotService(DiscordSocketClient client, PermissionService perms, IEnumerable gcs, - CommandHandler cmd, NadekoStrings strings, IBotCredentials creds) + public ChatterBotService(DiscordSocketClient client, PermissionService perms, + NadekoBot bot, CommandHandler cmd, NadekoStrings strings, + IBotCredentials creds) { _client = client; _log = LogManager.GetCurrentClassLogger(); @@ -39,7 +40,8 @@ namespace NadekoBot.Modules.Games.Services _creds = creds; ChatterBotGuilds = new ConcurrentDictionary>( - gcs.Where(gc => gc.CleverbotEnabled) + bot.AllGuildConfigs + .Where(gc => gc.CleverbotEnabled) .ToDictionary(gc => gc.GuildId, gc => new Lazy(() => CreateSession(), true))); } diff --git a/NadekoBot.Modules.Games/Services/GamesService.cs b/NadekoBot.Modules.Games/Services/GamesService.cs index dece8333..7573cda0 100644 --- a/NadekoBot.Modules.Games/Services/GamesService.cs +++ b/NadekoBot.Modules.Games/Services/GamesService.cs @@ -55,7 +55,7 @@ namespace NadekoBot.Modules.Games.Services public ConcurrentDictionary RunningContests { get; } = new ConcurrentDictionary(); public ConcurrentDictionary NunchiGames { get; } = new ConcurrentDictionary(); - public GamesService(CommandHandler cmd, IBotConfigProvider bc, IEnumerable gcs, + public GamesService(CommandHandler cmd, IBotConfigProvider bc, NadekoBot bot, NadekoStrings strings, IImagesService images, CommandHandler cmdHandler) { _bc = bc; @@ -77,7 +77,8 @@ namespace NadekoBot.Modules.Games.Services //plantpick _cmd.OnMessageNoTrigger += PotentialFlowerGeneration; - GenerationChannels = new ConcurrentHashSet(gcs + GenerationChannels = new ConcurrentHashSet(bot + .AllGuildConfigs .SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj => obj.ChannelId))); try diff --git a/NadekoBot.Modules.Music/Services/MusicService.cs b/NadekoBot.Modules.Music/Services/MusicService.cs index 78ca31a9..e27c8ba1 100644 --- a/NadekoBot.Modules.Music/Services/MusicService.cs +++ b/NadekoBot.Modules.Music/Services/MusicService.cs @@ -36,7 +36,7 @@ namespace NadekoBot.Modules.Music.Services public MusicService(DiscordSocketClient client, IGoogleApiService google, NadekoStrings strings, ILocalization localization, DbService db, - SoundCloudApiService sc, IBotCredentials creds, IEnumerable gcs) + SoundCloudApiService sc, IBotCredentials creds, NadekoBot bot) { _client = client; _google = google; @@ -51,7 +51,9 @@ namespace NadekoBot.Modules.Music.Services try { Directory.Delete(MusicDataPath, true); } catch { } - _defaultVolumes = new ConcurrentDictionary(gcs.ToDictionary(x => x.GuildId, x => x.DefaultMusicVolume)); + _defaultVolumes = new ConcurrentDictionary( + bot.AllGuildConfigs + .ToDictionary(x => x.GuildId, x => x.DefaultMusicVolume)); Directory.CreateDirectory(MusicDataPath); } diff --git a/NadekoBot.Modules.Searches/Services/FeedsService.cs b/NadekoBot.Modules.Searches/Services/FeedsService.cs index 33ac0ff9..09ad09dd 100644 --- a/NadekoBot.Modules.Searches/Services/FeedsService.cs +++ b/NadekoBot.Modules.Searches/Services/FeedsService.cs @@ -24,11 +24,13 @@ namespace NadekoBot.Modules.Searches.Services private readonly ConcurrentDictionary _lastPosts = new ConcurrentDictionary(); - public FeedsService(IEnumerable gcs, DbService db, DiscordSocketClient client) + public FeedsService(NadekoBot bot, DbService db, DiscordSocketClient client) { _db = db; - _subs = gcs.SelectMany(x => x.FeedSubs) + _subs = bot + .AllGuildConfigs + .SelectMany(x => x.FeedSubs) .GroupBy(x => x.Url) .ToDictionary(x => x.Key, x => x.ToHashSet()) .ToConcurrent(); @@ -54,8 +56,7 @@ namespace NadekoBot.Modules.Searches.Services if (kvp.Value.Count == 0) continue; - DateTime lastTime; - if (!_lastPosts.TryGetValue(kvp.Key, out lastTime)) + if (!_lastPosts.TryGetValue(kvp.Key, out DateTime lastTime)) lastTime = _lastPosts.AddOrUpdate(kvp.Key, DateTime.UtcNow, (k, old) => DateTime.UtcNow); var rssUrl = kvp.Key; diff --git a/NadekoBot.Modules.Searches/Services/SearchesService.cs b/NadekoBot.Modules.Searches/Services/SearchesService.cs index ded817e5..0b410aee 100644 --- a/NadekoBot.Modules.Searches/Services/SearchesService.cs +++ b/NadekoBot.Modules.Searches/Services/SearchesService.cs @@ -49,7 +49,8 @@ namespace NadekoBot.Modules.Searches.Services private readonly ConcurrentDictionary> _blacklistedTags = new ConcurrentDictionary>(); - public SearchesService(DiscordSocketClient client, IGoogleApiService google, DbService db, IEnumerable gcs) + public SearchesService(DiscordSocketClient client, IGoogleApiService google, + DbService db, NadekoBot bot) { Http = new HttpClient(); Http.AddFakeHeaders(); @@ -59,7 +60,7 @@ namespace NadekoBot.Modules.Searches.Services _log = LogManager.GetCurrentClassLogger(); _blacklistedTags = new ConcurrentDictionary>( - gcs.ToDictionary( + bot.AllGuildConfigs.ToDictionary( x => x.GuildId, x => new HashSet(x.NsfwBlacklistedTags.Select(y => y.Tag)))); diff --git a/NadekoBot.Modules.Utility/PatreonCommands.cs b/NadekoBot.Modules.Utility/PatreonCommands.cs index 96ac04c4..933ee7bc 100644 --- a/NadekoBot.Modules.Utility/PatreonCommands.cs +++ b/NadekoBot.Modules.Utility/PatreonCommands.cs @@ -26,21 +26,19 @@ namespace NadekoBot.Modules.Utility _db = db; _currency = currency; } - + [NadekoCommand, Usage, Description, Aliases] - [OwnerOnly] [RequireContext(ContextType.DM)] public async Task PatreonRewardsReload() { if (string.IsNullOrWhiteSpace(_creds.PatreonAccessToken)) return; - await _service.RefreshPledges(true).ConfigureAwait(false); + await _service.RefreshPledges().ConfigureAwait(false); await Context.Channel.SendConfirmAsync("👌").ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] - [RequireContext(ContextType.DM)] public async Task ClaimPatreonRewards() { if (string.IsNullOrWhiteSpace(_creds.PatreonAccessToken)) diff --git a/NadekoBot.Modules.Utility/Services/CommandMapService.cs b/NadekoBot.Modules.Utility/Services/CommandMapService.cs index 2aa1c419..c2ca0fe5 100644 --- a/NadekoBot.Modules.Utility/Services/CommandMapService.cs +++ b/NadekoBot.Modules.Utility/Services/CommandMapService.cs @@ -17,11 +17,11 @@ namespace NadekoBot.Modules.Utility.Services public ConcurrentDictionary> AliasMaps { get; } = new ConcurrentDictionary>(); //commandmap - public CommandMapService(IEnumerable gcs) + public CommandMapService(NadekoBot bot) { _log = LogManager.GetCurrentClassLogger(); AliasMaps = new ConcurrentDictionary>( - gcs.ToDictionary( + bot.AllGuildConfigs.ToDictionary( x => x.GuildId, x => new ConcurrentDictionary(x.CommandAliases .Distinct(new CommandAliasEqualityComparer()) diff --git a/NadekoBot.Modules.Utility/Services/ConverterService.cs b/NadekoBot.Modules.Utility/Services/ConverterService.cs index 62eab125..05e9bed3 100644 --- a/NadekoBot.Modules.Utility/Services/ConverterService.cs +++ b/NadekoBot.Modules.Utility/Services/ConverterService.cs @@ -13,6 +13,7 @@ using NLog; namespace NadekoBot.Modules.Utility.Services { + //todo rewrite public class ConverterService : INService, IUnloadableService { public List Units { get; } = new List(); diff --git a/NadekoBot.Modules.Utility/Services/MessageRepeaterService.cs b/NadekoBot.Modules.Utility/Services/MessageRepeaterService.cs index 2b19e520..d7e7a0a5 100644 --- a/NadekoBot.Modules.Utility/Services/MessageRepeaterService.cs +++ b/NadekoBot.Modules.Utility/Services/MessageRepeaterService.cs @@ -16,24 +16,25 @@ namespace NadekoBot.Modules.Utility.Services public ConcurrentDictionary> Repeaters { get; set; } public bool RepeaterReady { get; private set; } - public MessageRepeaterService(NadekoBot bot, DiscordSocketClient client, IEnumerable gcs) + public MessageRepeaterService(NadekoBot bot, DiscordSocketClient client) { var _ = Task.Run(async () => { await bot.Ready.Task.ConfigureAwait(false); - Repeaters = new ConcurrentDictionary>(gcs - .Select(gc => - { - var guild = client.GetGuild(gc.GuildId); - if (guild == null) - return (0, null); - return (gc.GuildId, new ConcurrentQueue(gc.GuildRepeaters - .Select(gr => new RepeatRunner(client, guild, gr)) - .Where(x => x.Guild != null))); - }) - .Where(x => x.Item2 != null) - .ToDictionary(x => x.GuildId, x => x.Item2)); + Repeaters = new ConcurrentDictionary>( + bot.AllGuildConfigs + .Select(gc => + { + var guild = client.GetGuild(gc.GuildId); + if (guild == null) + return (0, null); + return (gc.GuildId, new ConcurrentQueue(gc.GuildRepeaters + .Select(gr => new RepeatRunner(client, guild, gr)) + .Where(x => x.Guild != null))); + }) + .Where(x => x.Item2 != null) + .ToDictionary(x => x.GuildId, x => x.Item2)); RepeaterReady = true; }); } diff --git a/NadekoBot.Modules.Utility/Services/PatreonRewardsService.cs b/NadekoBot.Modules.Utility/Services/PatreonRewardsService.cs index 703d0c11..228129c2 100644 --- a/NadekoBot.Modules.Utility/Services/PatreonRewardsService.cs +++ b/NadekoBot.Modules.Utility/Services/PatreonRewardsService.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; -using System.IO; using System.Linq; using System.Net.Http; using System.Threading; @@ -12,6 +10,8 @@ using NadekoBot.Services; using NadekoBot.Services.Database.Models; using Newtonsoft.Json; using NLog; +using NadekoBot.Extensions; +using NadekoBot.Core.Common.Caching; namespace NadekoBot.Modules.Utility.Services { @@ -19,8 +19,8 @@ namespace NadekoBot.Modules.Utility.Services { private readonly SemaphoreSlim getPledgesLocker = new SemaphoreSlim(1, 1); - public ImmutableArray Pledges { get; private set; } - public DateTime LastUpdate { get; private set; } = DateTime.UtcNow; + private readonly FactoryCache _pledges; + public PatreonUserAndReward[] Pledges => _pledges.GetValue(); public readonly Timer Updater; private readonly SemaphoreSlim claimLockJustInCase = new SemaphoreSlim(1, 1); @@ -30,79 +30,95 @@ namespace NadekoBot.Modules.Utility.Services private readonly IBotCredentials _creds; private readonly DbService _db; private readonly CurrencyService _currency; + private readonly IDataCache _cache; + private readonly string _key; - private readonly string cacheFileName = "./patreon-rewards.json"; + public DateTime LastUpdate { get; private set; } = DateTime.UtcNow; public PatreonRewardsService(IBotCredentials creds, DbService db, CurrencyService currency, - DiscordSocketClient client) + DiscordSocketClient client, IDataCache cache) { _log = LogManager.GetCurrentClassLogger(); _creds = creds; _db = db; _currency = currency; - if (string.IsNullOrWhiteSpace(creds.PatreonAccessToken)) - return; - Updater = new Timer(async (load) => await RefreshPledges((bool)load), - client.ShardId == 0, client.ShardId == 0 ? TimeSpan.Zero : TimeSpan.FromMinutes(2), Interval); + _cache = cache; + _key = _creds.RedisKey() + "_patreon_rewards"; + + _pledges = new FactoryCache(() => + { + var r = _cache.Redis.GetDatabase(); + var data = r.StringGet(_key); + if (data.IsNullOrEmpty) + return null; + else + { + _log.Info(data); + return JsonConvert.DeserializeObject(data); + } + }, TimeSpan.FromSeconds(20)); + + if(client.ShardId == 0) + Updater = new Timer(async _ => await RefreshPledges(), + null, TimeSpan.Zero, Interval); } - public async Task RefreshPledges(bool shouldLoad) + public async Task RefreshPledges() { - if (shouldLoad) + if (string.IsNullOrWhiteSpace(_creds.PatreonAccessToken)) + return; + + LastUpdate = DateTime.UtcNow; + await getPledgesLocker.WaitAsync().ConfigureAwait(false); + try { - LastUpdate = DateTime.UtcNow; - await getPledgesLocker.WaitAsync().ConfigureAwait(false); - try + var rewards = new List(); + var users = new List(); + using (var http = new HttpClient()) { - var rewards = new List(); - var users = new List(); - using (var http = new HttpClient()) + http.DefaultRequestHeaders.Clear(); + http.DefaultRequestHeaders.Add("Authorization", "Bearer " + _creds.PatreonAccessToken); + var data = new PatreonData() { - http.DefaultRequestHeaders.Clear(); - http.DefaultRequestHeaders.Add("Authorization", "Bearer " + _creds.PatreonAccessToken); - var data = new PatreonData() + Links = new PatreonDataLinks() { - Links = new PatreonDataLinks() - { - next = $"https://api.patreon.com/oauth2/api/campaigns/{_creds.PatreonCampaignId}/pledges" - } - }; - do - { - var res = await http.GetStringAsync(data.Links.next) - .ConfigureAwait(false); - data = JsonConvert.DeserializeObject(res); - var pledgers = data.Data.Where(x => x["type"].ToString() == "pledge"); - rewards.AddRange(pledgers.Select(x => JsonConvert.DeserializeObject(x.ToString())) - .Where(x => x.attributes.declined_since == null)); - users.AddRange(data.Included - .Where(x => x["type"].ToString() == "user") - .Select(x => JsonConvert.DeserializeObject(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() + next = $"https://api.patreon.com/oauth2/api/campaigns/{_creds.PatreonCampaignId}/pledges" + } + }; + do { - User = y, - Reward = x, - }).ToImmutableArray(); - File.WriteAllText("./patreon_rewards.json", JsonConvert.SerializeObject(Pledges)); + var res = await http.GetStringAsync(data.Links.next) + .ConfigureAwait(false); + data = JsonConvert.DeserializeObject(res); + var pledgers = data.Data.Where(x => x["type"].ToString() == "pledge"); + rewards.AddRange(pledgers.Select(x => JsonConvert.DeserializeObject(x.ToString())) + .Where(x => x.attributes.declined_since == null)); + users.AddRange(data.Included + .Where(x => x["type"].ToString() == "user") + .Select(x => JsonConvert.DeserializeObject(x.ToString()))); + } while (!string.IsNullOrWhiteSpace(data.Links.next)); } - catch (Exception ex) + var db = _cache.Redis.GetDatabase(); + var toSet = JsonConvert.SerializeObject(rewards.Join(users, (r) => r.relationships?.patron?.data?.id, (u) => u.id, (x, y) => new PatreonUserAndReward() { - _log.Warn(ex); - } - finally - { - getPledgesLocker.Release(); - } + User = y, + Reward = x, + }).ToArray()); + + _log.Info(toSet); + + db.StringSet(_key, toSet); } - else + catch (Exception ex) { - if(File.Exists(cacheFileName)) - Pledges = JsonConvert.DeserializeObject(File.ReadAllText("./patreon_rewards.json")) - .ToImmutableArray(); + _log.Warn(ex); } + finally + { + getPledgesLocker.Release(); + } + } public async Task ClaimReward(ulong userId) @@ -111,7 +127,7 @@ namespace NadekoBot.Modules.Utility.Services var now = DateTime.UtcNow; try { - var data = Pledges.FirstOrDefault(x => x.User.attributes?.social_connections?.discord?.user_id == userId.ToString()); + var data = Pledges?.FirstOrDefault(x => x.User.attributes?.social_connections?.discord?.user_id == userId.ToString()); if (data == null) return 0; @@ -175,7 +191,7 @@ namespace NadekoBot.Modules.Utility.Services public Task Unload() { - Updater.Change(Timeout.Infinite, Timeout.Infinite); + Updater?.Change(Timeout.Infinite, Timeout.Infinite); return Task.CompletedTask; } } diff --git a/NadekoBot.Modules.Utility/Services/StreamRoleService.cs b/NadekoBot.Modules.Utility/Services/StreamRoleService.cs index 3c2c17c7..e7aded2c 100644 --- a/NadekoBot.Modules.Utility/Services/StreamRoleService.cs +++ b/NadekoBot.Modules.Utility/Services/StreamRoleService.cs @@ -24,13 +24,14 @@ namespace NadekoBot.Modules.Utility.Services private readonly ConcurrentDictionary guildSettings; private readonly Logger _log; - public StreamRoleService(DiscordSocketClient client, DbService db, IEnumerable gcs) + public StreamRoleService(DiscordSocketClient client, DbService db, NadekoBot bot) { this._log = LogManager.GetCurrentClassLogger(); this._db = db; this._client = client; - guildSettings = gcs.ToDictionary(x => x.GuildId, x => x.StreamRole) + guildSettings = bot.AllGuildConfigs + .ToDictionary(x => x.GuildId, x => x.StreamRole) .Where(x => x.Value != null && x.Value.Enabled) .ToConcurrent(); diff --git a/NadekoBot.Modules.Utility/Services/VerboseErrorsService.cs b/NadekoBot.Modules.Utility/Services/VerboseErrorsService.cs index a5e01566..2f537e43 100644 --- a/NadekoBot.Modules.Utility/Services/VerboseErrorsService.cs +++ b/NadekoBot.Modules.Utility/Services/VerboseErrorsService.cs @@ -18,7 +18,7 @@ namespace NadekoBot.Modules.Utility.Services private readonly CommandHandler _ch; private readonly HelpService _hs; - public VerboseErrorsService(IEnumerable gcs, DbService db, CommandHandler ch, HelpService hs) + public VerboseErrorsService(NadekoBot bot, DbService db, CommandHandler ch, HelpService hs) { _db = db; _ch = ch; @@ -26,7 +26,10 @@ namespace NadekoBot.Modules.Utility.Services _ch.CommandErrored += LogVerboseError; - guildsEnabled = new ConcurrentHashSet(gcs.Where(x => x.VerboseErrors).Select(x => x.GuildId)); + guildsEnabled = new ConcurrentHashSet(bot + .AllGuildConfigs + .Where(x => x.VerboseErrors) + .Select(x => x.GuildId)); } public Task Unload() diff --git a/NadekoBot.Modules.Xp/Services/XpService.cs b/NadekoBot.Modules.Xp/Services/XpService.cs index a5f90768..5c1443e3 100644 --- a/NadekoBot.Modules.Xp/Services/XpService.cs +++ b/NadekoBot.Modules.Xp/Services/XpService.cs @@ -68,7 +68,7 @@ namespace NadekoBot.Modules.Xp.Services private Font _timeFont; public XpService(CommandHandler cmd, IBotConfigProvider bc, - IEnumerable allGuildConfigs, IImagesService images, + NadekoBot bot, IImagesService images, DbService db, NadekoStrings strings, IDataCache cache) { _db = db; @@ -80,7 +80,7 @@ namespace NadekoBot.Modules.Xp.Services _cache = cache; //load settings - allGuildConfigs = allGuildConfigs.Where(x => x.XpSettings != null); + var allGuildConfigs = bot.AllGuildConfigs.Where(x => x.XpSettings != null); _excludedChannels = allGuildConfigs .ToDictionary( x => x.GuildId, @@ -685,7 +685,6 @@ namespace NadekoBot.Modules.Xp.Services } //club image - if (!string.IsNullOrWhiteSpace(stats.User.Club?.ImageUrl)) { var imgUrl = stats.User.Club.ImageUrl; @@ -694,6 +693,7 @@ namespace NadekoBot.Modules.Xp.Services var (succ, data) = await _cache.TryGetImageDataAsync(imgUrl); if (!succ) { + //todo make sure it's a picture using (var temp = await http.GetStreamAsync(imgUrl)) using (var tempDraw = Image.Load(temp).Resize(45, 45)) { diff --git a/src/NadekoBot/data/command_strings.json b/src/NadekoBot/data/command_strings.json index eda80535..319616b7 100644 --- a/src/NadekoBot/data/command_strings.json +++ b/src/NadekoBot/data/command_strings.json @@ -1836,7 +1836,7 @@ }, "antispam": { "Cmd": "antispam", - "Desc": "Stops people from repeating same message X times in a row. You can specify to either mute, kick or ban the offenders. Max message count is 10.", + "Desc": "Stops people from repeating same message X times in a row. You can specify to either mute, kick or ban the offenders. If you're using mute, you can add a number of seconds at the end to use a timed mute. Max message count is 10.", "Usage": [ "{0}antispam 3 Mute", "{0}antispam 4 Kick",