mirror of
				https://gitlab.com/Kwoth/nadekobot.git
				synced 2025-11-03 16:24:27 -05:00 
			
		
		
		
	- NoPublicBotAttribute will now be properly ignored when built with GlobalNadeko configuration
- Added ILogCommandsService which will have dummy implementation on public bot, this means Logging Commands will be present on public bot to pull up help etc - When .ve is enabled, NoPublicBot commands will show a nicer error message with link to selfhosting guide (thx ene) - Fixed xp gain and .xp command not working on new users - General cleanup
This commit is contained in:
		
							
								
								
									
										21
									
								
								src/NadekoBot/Modules/Administration/Common/LogType.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/NadekoBot/Modules/Administration/Common/LogType.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
namespace NadekoBot.Modules.Administration
 | 
			
		||||
{
 | 
			
		||||
    public enum LogType
 | 
			
		||||
    {
 | 
			
		||||
        Other,
 | 
			
		||||
        MessageUpdated,
 | 
			
		||||
        MessageDeleted,
 | 
			
		||||
        UserJoined,
 | 
			
		||||
        UserLeft,
 | 
			
		||||
        UserBanned,
 | 
			
		||||
        UserUnbanned,
 | 
			
		||||
        UserUpdated,
 | 
			
		||||
        ChannelCreated,
 | 
			
		||||
        ChannelDestroyed,
 | 
			
		||||
        ChannelUpdated,
 | 
			
		||||
        UserPresence,
 | 
			
		||||
        VoicePresence,
 | 
			
		||||
        VoicePresenceTTS,
 | 
			
		||||
        UserMuted
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
#if !GLOBAL_NADEKO
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using NadekoBot.Common;
 | 
			
		||||
using NadekoBot.Common.Attributes;
 | 
			
		||||
@@ -10,7 +9,6 @@ using NadekoBot.Modules.Administration.Services;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using static NadekoBot.Modules.Administration.Services.LogCommandService;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Administration
 | 
			
		||||
{
 | 
			
		||||
@@ -18,7 +16,7 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
    {
 | 
			
		||||
        [Group]
 | 
			
		||||
        [NoPublicBot]
 | 
			
		||||
        public class LogCommands : NadekoSubmodule<LogCommandService>
 | 
			
		||||
        public class LogCommands : NadekoSubmodule<ILogCommandService>
 | 
			
		||||
        {
 | 
			
		||||
            public enum EnableDisable
 | 
			
		||||
            {
 | 
			
		||||
@@ -61,11 +59,11 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
            [OwnerOnly]
 | 
			
		||||
            public async Task LogEvents()
 | 
			
		||||
            {
 | 
			
		||||
                _service.GuildLogSettings.TryGetValue(ctx.Guild.Id, out LogSetting l);
 | 
			
		||||
                var logSetting = _service.GetGuildLogSettings(ctx.Guild.Id);
 | 
			
		||||
                var str = string.Join("\n", Enum.GetNames(typeof(LogType))
 | 
			
		||||
                    .Select(x =>
 | 
			
		||||
                    {
 | 
			
		||||
                        var val = l is null ? null : GetLogProperty(l, Enum.Parse<LogType>(x));
 | 
			
		||||
                        var val = logSetting is null ? null : GetLogProperty(logSetting, Enum.Parse<LogType>(x));
 | 
			
		||||
                        if (val != null)
 | 
			
		||||
                            return $"{Format.Bold(x)} <#{val}>";
 | 
			
		||||
                        return Format.Bold(x);
 | 
			
		||||
@@ -131,4 +129,3 @@ namespace NadekoBot.Modules.Administration
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -23,10 +23,10 @@ namespace NadekoBot.Modules.Administration.Services
 | 
			
		||||
        public ConcurrentDictionary<ulong, bool> DeleteMessagesOnCommandChannels { get; }
 | 
			
		||||
 | 
			
		||||
        private readonly DbService _db;
 | 
			
		||||
        private readonly LogCommandService _logService;
 | 
			
		||||
        private readonly ILogCommandService _logService;
 | 
			
		||||
 | 
			
		||||
        public AdministrationService(Bot bot, CommandHandler cmdHandler, DbService db,
 | 
			
		||||
            LogCommandService logService)
 | 
			
		||||
            ILogCommandService logService)
 | 
			
		||||
        {
 | 
			
		||||
            _db = db;
 | 
			
		||||
            _logService = logService;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
#if !GLOBAL_NADEKO
 | 
			
		||||
using System;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Concurrent;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
@@ -18,7 +17,43 @@ using NadekoBot.Modules.Administration.Common;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Administration.Services
 | 
			
		||||
{
 | 
			
		||||
    public class LogCommandService : INService
 | 
			
		||||
    public interface ILogCommandService
 | 
			
		||||
    {
 | 
			
		||||
        void AddDeleteIgnore(ulong xId);
 | 
			
		||||
        Task LogServer(ulong guildId, ulong channelId, bool actionValue);
 | 
			
		||||
        bool LogIgnore(ulong guildId, ulong channelId);
 | 
			
		||||
        LogSetting GetGuildLogSettings(ulong guildId);
 | 
			
		||||
        bool Log(ulong guildId, ulong? channelId, LogType type);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public sealed class DummyLogCommandService : ILogCommandService
 | 
			
		||||
    {
 | 
			
		||||
        public void AddDeleteIgnore(ulong xId)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Task LogServer(ulong guildId, ulong channelId, bool actionValue)
 | 
			
		||||
        {
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool LogIgnore(ulong guildId, ulong channelId)
 | 
			
		||||
        {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public LogSetting GetGuildLogSettings(ulong guildId)
 | 
			
		||||
        {
 | 
			
		||||
            return default;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool Log(ulong guildId, ulong? channelId, LogType type)
 | 
			
		||||
        {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public sealed class LogCommandService : ILogCommandService
 | 
			
		||||
    {
 | 
			
		||||
        private readonly DiscordSocketClient _client;
 | 
			
		||||
        
 | 
			
		||||
@@ -46,6 +81,8 @@ namespace NadekoBot.Modules.Administration.Services
 | 
			
		||||
            _prot = prot;
 | 
			
		||||
            _tz = tz;
 | 
			
		||||
 | 
			
		||||
#if !GLOBAL_NADEKO
 | 
			
		||||
            
 | 
			
		||||
            using (var uow = db.GetDbContext())
 | 
			
		||||
            {
 | 
			
		||||
                var guildIds = client.Guilds.Select(x => x.Id).ToList();
 | 
			
		||||
@@ -92,9 +129,7 @@ namespace NadekoBot.Modules.Administration.Services
 | 
			
		||||
            _client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated;
 | 
			
		||||
            _client.UserVoiceStateUpdated += _client_UserVoiceStateUpdated_TTS;
 | 
			
		||||
            _client.GuildMemberUpdated += _client_GuildUserUpdated;
 | 
			
		||||
#if !GLOBAL_NADEKO
 | 
			
		||||
            _client.UserUpdated += _client_UserUpdated;
 | 
			
		||||
#endif
 | 
			
		||||
            _client.ChannelCreated += _client_ChannelCreated;
 | 
			
		||||
            _client.ChannelDestroyed += _client_ChannelDestroyed;
 | 
			
		||||
            _client.ChannelUpdated += _client_ChannelUpdated;
 | 
			
		||||
@@ -109,12 +144,20 @@ namespace NadekoBot.Modules.Administration.Services
 | 
			
		||||
            {
 | 
			
		||||
                _ignoreMessageIds.Clear();
 | 
			
		||||
            }, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
 | 
			
		||||
            
 | 
			
		||||
#endif
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private readonly Timer _clearTimer;
 | 
			
		||||
        private readonly ConcurrentHashSet<ulong> _ignoreMessageIds = new ConcurrentHashSet<ulong>();
 | 
			
		||||
        private readonly IMemoryCache _memoryCache;
 | 
			
		||||
 | 
			
		||||
        public LogSetting GetGuildLogSettings(ulong guildId)
 | 
			
		||||
        {
 | 
			
		||||
            GuildLogSettings.TryGetValue(guildId, out LogSetting logSetting);
 | 
			
		||||
            return logSetting;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void AddDeleteIgnore(ulong messageId)
 | 
			
		||||
        {
 | 
			
		||||
            _ignoreMessageIds.Add(messageId);
 | 
			
		||||
@@ -1129,25 +1172,6 @@ namespace NadekoBot.Modules.Administration.Services
 | 
			
		||||
            return Task.CompletedTask;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public enum LogType
 | 
			
		||||
        {
 | 
			
		||||
            Other,
 | 
			
		||||
            MessageUpdated,
 | 
			
		||||
            MessageDeleted,
 | 
			
		||||
            UserJoined,
 | 
			
		||||
            UserLeft,
 | 
			
		||||
            UserBanned,
 | 
			
		||||
            UserUnbanned,
 | 
			
		||||
            UserUpdated,
 | 
			
		||||
            ChannelCreated,
 | 
			
		||||
            ChannelDestroyed,
 | 
			
		||||
            ChannelUpdated,
 | 
			
		||||
            UserPresence,
 | 
			
		||||
            VoicePresence,
 | 
			
		||||
            VoicePresenceTTS,
 | 
			
		||||
            UserMuted
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async Task<ITextChannel> TryGetLogChannel(IGuild guild, LogSetting logSetting, LogType logChannelType)
 | 
			
		||||
        {
 | 
			
		||||
            ulong? id = null;
 | 
			
		||||
@@ -1276,5 +1300,4 @@ namespace NadekoBot.Modules.Administration.Services
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
@@ -14,9 +14,9 @@ namespace NadekoBot.Modules.Administration.Services
 | 
			
		||||
        //channelids where prunes are currently occuring
 | 
			
		||||
        private ConcurrentHashSet<ulong> _pruningGuilds = new ConcurrentHashSet<ulong>();
 | 
			
		||||
        private readonly TimeSpan twoWeeks = TimeSpan.FromDays(14);
 | 
			
		||||
        private readonly LogCommandService _logService;
 | 
			
		||||
        private readonly ILogCommandService _logService;
 | 
			
		||||
 | 
			
		||||
        public PruneService(LogCommandService logService)
 | 
			
		||||
        public PruneService(ILogCommandService logService)
 | 
			
		||||
        {
 | 
			
		||||
            this._logService = logService;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -15,40 +15,47 @@ using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.CustomReactions.Extensions
 | 
			
		||||
{
 | 
			
		||||
    public static class Extensions
 | 
			
		||||
    public static class CustomReactionExtensions
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly Regex imgRegex = new Regex("%(img|image):(?<tag>.*?)%", RegexOptions.Compiled);
 | 
			
		||||
 | 
			
		||||
        private static Dictionary<Regex, Func<Match, Task<string>>> regexPlaceholders { get; } = new Dictionary<Regex, Func<Match, Task<string>>>()
 | 
			
		||||
        {
 | 
			
		||||
            { imgRegex, async (match) => {
 | 
			
		||||
                var tag = match.Groups["tag"].ToString();
 | 
			
		||||
                if(string.IsNullOrWhiteSpace(tag))
 | 
			
		||||
                    return "";
 | 
			
		||||
 | 
			
		||||
                var fullQueryLink = $"http://imgur.com/search?q={ tag }";
 | 
			
		||||
                var config = Configuration.Default.WithDefaultLoader();
 | 
			
		||||
                using(var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink).ConfigureAwait(false))
 | 
			
		||||
        private static Dictionary<Regex, Func<Match, Task<string>>> regexPlaceholders { get; } =
 | 
			
		||||
            new Dictionary<Regex, Func<Match, Task<string>>>()
 | 
			
		||||
            {
 | 
			
		||||
                {
 | 
			
		||||
                    var elems = document.QuerySelectorAll("a.image-list-link").ToArray();
 | 
			
		||||
                    imgRegex, async (match) =>
 | 
			
		||||
                    {
 | 
			
		||||
                        var tag = match.Groups["tag"].ToString();
 | 
			
		||||
                        if (string.IsNullOrWhiteSpace(tag))
 | 
			
		||||
                            return "";
 | 
			
		||||
 | 
			
		||||
                    if (!elems.Any())
 | 
			
		||||
                        return "";
 | 
			
		||||
                        var fullQueryLink = $"http://imgur.com/search?q={tag}";
 | 
			
		||||
                        var config = Configuration.Default.WithDefaultLoader();
 | 
			
		||||
                        using (var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink)
 | 
			
		||||
                            .ConfigureAwait(false))
 | 
			
		||||
                        {
 | 
			
		||||
                            var elems = document.QuerySelectorAll("a.image-list-link").ToArray();
 | 
			
		||||
 | 
			
		||||
                    var img = (elems.ElementAtOrDefault(new NadekoRandom().Next(0, elems.Length))?.Children?.FirstOrDefault() as IHtmlImageElement);
 | 
			
		||||
                            if (!elems.Any())
 | 
			
		||||
                                return "";
 | 
			
		||||
 | 
			
		||||
                    if (img?.Source is null)
 | 
			
		||||
                        return "";
 | 
			
		||||
                            var img = (elems.ElementAtOrDefault(new NadekoRandom().Next(0, elems.Length))?.Children
 | 
			
		||||
                                ?.FirstOrDefault() as IHtmlImageElement);
 | 
			
		||||
 | 
			
		||||
                    return " " + img.Source.Replace("b.", ".", StringComparison.InvariantCulture) + " ";
 | 
			
		||||
                            if (img?.Source is null)
 | 
			
		||||
                                return "";
 | 
			
		||||
 | 
			
		||||
                            return " " + img.Source.Replace("b.", ".", StringComparison.InvariantCulture) + " ";
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } }
 | 
			
		||||
        };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        private static string ResolveTriggerString(this string str, IUserMessage ctx, DiscordSocketClient client)
 | 
			
		||||
            => str.Replace("%bot.mention%", client.CurrentUser.Mention, StringComparison.Ordinal);
 | 
			
		||||
 | 
			
		||||
        private static async Task<string> ResolveResponseStringAsync(this string str, IUserMessage ctx, DiscordSocketClient client, string resolvedTrigger, bool containsAnywhere)
 | 
			
		||||
        private static async Task<string> ResolveResponseStringAsync(this string str, IUserMessage ctx,
 | 
			
		||||
            DiscordSocketClient client, string resolvedTrigger, bool containsAnywhere)
 | 
			
		||||
        {
 | 
			
		||||
            var substringIndex = resolvedTrigger.Length;
 | 
			
		||||
            if (containsAnywhere)
 | 
			
		||||
@@ -61,7 +68,7 @@ namespace NadekoBot.Modules.CustomReactions.Extensions
 | 
			
		||||
                else if (pos == WordPosition.Middle)
 | 
			
		||||
                    substringIndex += ctx.Content.IndexOf(resolvedTrigger, StringComparison.InvariantCulture);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            var canMentionEveryone = (ctx.Author as IGuildUser)?.GuildPermissions.MentionEveryone ?? true;
 | 
			
		||||
 | 
			
		||||
            var rep = new ReplacementBuilder()
 | 
			
		||||
@@ -82,12 +89,17 @@ namespace NadekoBot.Modules.CustomReactions.Extensions
 | 
			
		||||
            return str;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static Task<string> ResponseWithContextAsync(this CustomReaction cr, IUserMessage ctx, DiscordSocketClient client, bool containsAnywhere)
 | 
			
		||||
            => cr.Response.ResolveResponseStringAsync(ctx, client, cr.Trigger.ResolveTriggerString(ctx, client), containsAnywhere);
 | 
			
		||||
        public static Task<string> ResponseWithContextAsync(this CustomReaction cr, IUserMessage ctx,
 | 
			
		||||
            DiscordSocketClient client, bool containsAnywhere)
 | 
			
		||||
            => cr.Response.ResolveResponseStringAsync(ctx, client, cr.Trigger.ResolveTriggerString(ctx, client),
 | 
			
		||||
                containsAnywhere);
 | 
			
		||||
 | 
			
		||||
        public static async Task<IUserMessage> Send(this CustomReaction cr, IUserMessage ctx, DiscordSocketClient client, bool sanitize)
 | 
			
		||||
        public static async Task<IUserMessage> Send(this CustomReaction cr, IUserMessage ctx,
 | 
			
		||||
            DiscordSocketClient client, bool sanitize)
 | 
			
		||||
        {
 | 
			
		||||
            var channel = cr.DmResponse ? await ctx.Author.GetOrCreateDMChannelAsync().ConfigureAwait(false) : ctx.Channel;
 | 
			
		||||
            var channel = cr.DmResponse
 | 
			
		||||
                ? await ctx.Author.GetOrCreateDMChannelAsync().ConfigureAwait(false)
 | 
			
		||||
                : ctx.Channel;
 | 
			
		||||
 | 
			
		||||
            if (CREmbed.TryParse(cr.Response, out CREmbed crembed))
 | 
			
		||||
            {
 | 
			
		||||
@@ -105,7 +117,7 @@ namespace NadekoBot.Modules.CustomReactions.Extensions
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                var canMentionEveryone = (ctx.Author as IGuildUser)?.GuildPermissions.MentionEveryone ?? true;
 | 
			
		||||
                
 | 
			
		||||
 | 
			
		||||
                var rep = new ReplacementBuilder()
 | 
			
		||||
                    .WithDefault(ctx.Author, ctx.Channel, (ctx.Channel as ITextChannel)?.Guild as SocketGuild, client)
 | 
			
		||||
                    .WithOverride("%target%", () => canMentionEveryone
 | 
			
		||||
@@ -117,7 +129,11 @@ namespace NadekoBot.Modules.CustomReactions.Extensions
 | 
			
		||||
 | 
			
		||||
                return await channel.EmbedAsync(crembed, sanitize).ConfigureAwait(false);
 | 
			
		||||
            }
 | 
			
		||||
            return await channel.SendMessageAsync((await cr.ResponseWithContextAsync(ctx, client, cr.ContainsAnywhere).ConfigureAwait(false)).SanitizeMentions(sanitize)).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
            return await channel
 | 
			
		||||
                .SendMessageAsync(
 | 
			
		||||
                    (await cr.ResponseWithContextAsync(ctx, client, cr.ContainsAnywhere).ConfigureAwait(false))
 | 
			
		||||
                    .SanitizeMentions(sanitize)).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 | 
			
		||||
@@ -16,9 +16,9 @@ namespace NadekoBot.Modules.Games
 | 
			
		||||
        [Group]
 | 
			
		||||
        public class PlantPickCommands : GamblingSubmodule<PlantPickService>
 | 
			
		||||
        {
 | 
			
		||||
            private readonly LogCommandService logService;
 | 
			
		||||
            private readonly ILogCommandService logService;
 | 
			
		||||
 | 
			
		||||
            public PlantPickCommands(LogCommandService logService, GamblingConfigService gss) : base(gss)
 | 
			
		||||
            public PlantPickCommands(ILogCommandService logService, GamblingConfigService gss) : base(gss)
 | 
			
		||||
            {
 | 
			
		||||
                this.logService = logService;
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -18,9 +18,9 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
    [NoPublicBot]
 | 
			
		||||
    public sealed partial class Music : NadekoModule<IMusicService>
 | 
			
		||||
    {
 | 
			
		||||
        private readonly LogCommandService _logService;
 | 
			
		||||
        private readonly ILogCommandService _logService;
 | 
			
		||||
 | 
			
		||||
        public Music(LogCommandService _logService)
 | 
			
		||||
        public Music(ILogCommandService _logService)
 | 
			
		||||
        {
 | 
			
		||||
            this._logService = _logService;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -28,6 +28,7 @@ using Image = SixLabors.ImageSharp.Image;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Modules.Xp.Services
 | 
			
		||||
{
 | 
			
		||||
    // todo improve xp with linqtodb
 | 
			
		||||
    public class XpService : INService
 | 
			
		||||
    {
 | 
			
		||||
        private enum NotifOf
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user