mirror of
				https://gitlab.com/Kwoth/nadekobot.git
				synced 2025-11-03 16:24:27 -05:00 
			
		
		
		
	Merge branch 'v5' of https://gitlab.com/kwoth/nadekobot into v5
This commit is contained in:
		@@ -1,5 +1,6 @@
 | 
				
			|||||||
#nullable disable
 | 
					#nullable disable
 | 
				
			||||||
using NadekoBot.Common.TypeReaders.Models;
 | 
					using NadekoBot.Common.TypeReaders.Models;
 | 
				
			||||||
 | 
					using NadekoBot.Modules.Administration._common.results;
 | 
				
			||||||
using NadekoBot.Modules.Administration.Services;
 | 
					using NadekoBot.Modules.Administration.Services;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace NadekoBot.Modules.Administration;
 | 
					namespace NadekoBot.Modules.Administration;
 | 
				
			||||||
@@ -405,4 +406,92 @@ public partial class Administration : NadekoModule<AdministrationService>
 | 
				
			|||||||
            await Response().Confirm(strs.autopublish_disable).SendAsync();
 | 
					            await Response().Confirm(strs.autopublish_disable).SendAsync();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    [Cmd]
 | 
				
			||||||
 | 
					    [UserPerm(GuildPerm.ManageNicknames)]
 | 
				
			||||||
 | 
					    [BotPerm(GuildPerm.ChangeNickname)]
 | 
				
			||||||
 | 
					    [Priority(0)]
 | 
				
			||||||
 | 
					    public async Task SetNick([Leftover] string newNick = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (string.IsNullOrWhiteSpace(newNick))
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        var curUser = await ctx.Guild.GetCurrentUserAsync();
 | 
				
			||||||
 | 
					        await curUser.ModifyAsync(u => u.Nickname = newNick);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await Response().Confirm(strs.bot_nick(Format.Bold(newNick) ?? "-")).SendAsync();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [Cmd]
 | 
				
			||||||
 | 
					    [BotPerm(GuildPerm.ManageNicknames)]
 | 
				
			||||||
 | 
					    [UserPerm(GuildPerm.ManageNicknames)]
 | 
				
			||||||
 | 
					    [Priority(1)]
 | 
				
			||||||
 | 
					    public async Task SetNick(IGuildUser gu, [Leftover] string newNick = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var sg = (SocketGuild)ctx.Guild;
 | 
				
			||||||
 | 
					        if (sg.OwnerId == gu.Id
 | 
				
			||||||
 | 
					            || gu.GetRoles().Max(r => r.Position) >= sg.CurrentUser.GetRoles().Max(r => r.Position))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            await Response().Error(strs.insuf_perms_i).SendAsync();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await gu.ModifyAsync(u => u.Nickname = newNick);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await Response()
 | 
				
			||||||
 | 
					              .Confirm(strs.user_nick(Format.Bold(gu.ToString()), Format.Bold(newNick) ?? "-"))
 | 
				
			||||||
 | 
					              .SendAsync();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [Cmd]
 | 
				
			||||||
 | 
					    [RequireContext(ContextType.Guild)]
 | 
				
			||||||
 | 
					    [UserPerm(GuildPermission.ManageGuild)]
 | 
				
			||||||
 | 
					    public async Task SetServerBanner([Leftover] string img = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Tier2 or higher is required to set a banner.
 | 
				
			||||||
 | 
					        if (ctx.Guild.PremiumTier is PremiumTier.Tier1 or PremiumTier.None) return;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        var result = await _service.SetServerBannerAsync(ctx.Guild, img);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (result)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            case SetServerBannerResult.Success:
 | 
				
			||||||
 | 
					                await Response().Confirm(strs.set_srvr_banner).SendAsync();
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case SetServerBannerResult.InvalidFileType:
 | 
				
			||||||
 | 
					                await Response().Error(strs.srvr_banner_invalid).SendAsync();
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case SetServerBannerResult.Toolarge:
 | 
				
			||||||
 | 
					                await Response().Error(strs.srvr_banner_too_large).SendAsync();
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case SetServerBannerResult.InvalidURL:
 | 
				
			||||||
 | 
					                await Response().Error(strs.srvr_banner_invalid_url).SendAsync();
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                throw new ArgumentOutOfRangeException();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    [Cmd]
 | 
				
			||||||
 | 
					    [RequireContext(ContextType.Guild)]
 | 
				
			||||||
 | 
					    [UserPerm(GuildPermission.ManageGuild)]
 | 
				
			||||||
 | 
					    public async Task SetServerIcon([Leftover] string img = null)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        var result = await _service.SetServerIconAsync(ctx.Guild, img);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (result)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            case SetServerIconResult.Success:
 | 
				
			||||||
 | 
					                await Response().Confirm(strs.set_srvr_icon).SendAsync();
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case SetServerIconResult.InvalidFileType:
 | 
				
			||||||
 | 
					                await Response().Error(strs.srvr_banner_invalid).SendAsync();
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case SetServerIconResult.InvalidURL:
 | 
				
			||||||
 | 
					                await Response().Error(strs.srvr_banner_invalid_url).SendAsync();
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                throw new ArgumentOutOfRangeException();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
using Microsoft.EntityFrameworkCore;
 | 
					using Microsoft.EntityFrameworkCore;
 | 
				
			||||||
using NadekoBot.Db;
 | 
					using NadekoBot.Db;
 | 
				
			||||||
using NadekoBot.Db.Models;
 | 
					using NadekoBot.Db.Models;
 | 
				
			||||||
 | 
					using NadekoBot.Modules.Administration._common.results;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace NadekoBot.Modules.Administration.Services;
 | 
					namespace NadekoBot.Modules.Administration.Services;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -13,17 +14,20 @@ public class AdministrationService : INService
 | 
				
			|||||||
    private readonly DbService _db;
 | 
					    private readonly DbService _db;
 | 
				
			||||||
    private readonly IReplacementService _repSvc;
 | 
					    private readonly IReplacementService _repSvc;
 | 
				
			||||||
    private readonly ILogCommandService _logService;
 | 
					    private readonly ILogCommandService _logService;
 | 
				
			||||||
 | 
					    private readonly IHttpClientFactory _httpFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public AdministrationService(
 | 
					    public AdministrationService(
 | 
				
			||||||
        IBot bot,
 | 
					        IBot bot,
 | 
				
			||||||
        CommandHandler cmdHandler,
 | 
					        CommandHandler cmdHandler,
 | 
				
			||||||
        DbService db,
 | 
					        DbService db,
 | 
				
			||||||
        IReplacementService repSvc,
 | 
					        IReplacementService repSvc,
 | 
				
			||||||
        ILogCommandService logService)
 | 
					        ILogCommandService logService,
 | 
				
			||||||
 | 
					        IHttpClientFactory factory)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        _db = db;
 | 
					        _db = db;
 | 
				
			||||||
        _repSvc = repSvc;
 | 
					        _repSvc = repSvc;
 | 
				
			||||||
        _logService = logService;
 | 
					        _logService = logService;
 | 
				
			||||||
 | 
					        _httpFactory = factory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        DeleteMessagesOnCommand = new(bot.AllGuildConfigs.Where(g => g.DeleteMessageOnCommand).Select(g => g.GuildId));
 | 
					        DeleteMessagesOnCommand = new(bot.AllGuildConfigs.Where(g => g.DeleteMessageOnCommand).Select(g => g.GuildId));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -158,4 +162,45 @@ public class AdministrationService : INService
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        await umsg.EditAsync(text);
 | 
					        await umsg.EditAsync(text);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public async Task<SetServerBannerResult> SetServerBannerAsync(IGuild guild, string img)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!IsValidUri(img)) return SetServerBannerResult.InvalidURL;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        var uri = new Uri(img);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        using var http = _httpFactory.CreateClient();
 | 
				
			||||||
 | 
					        using var sr = await http.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (!sr.IsImage()) return SetServerBannerResult.InvalidFileType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (sr.GetContentLength() > 8.Megabytes())
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return SetServerBannerResult.Toolarge;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        await using var imageStream = await sr.Content.ReadAsStreamAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await guild.ModifyAsync(x => x.Banner = new Image(imageStream));
 | 
				
			||||||
 | 
					        return SetServerBannerResult.Success;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public async Task<SetServerIconResult> SetServerIconAsync(IGuild guild, string img)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (!IsValidUri(img)) return SetServerIconResult.InvalidURL;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        var uri = new Uri(img);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        using var http = _httpFactory.CreateClient();
 | 
				
			||||||
 | 
					        using var sr = await http.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead);
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if (!sr.IsImage()) return SetServerIconResult.InvalidFileType;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        await using var imageStream = await sr.Content.ReadAsStreamAsync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await guild.ModifyAsync(x => x.Icon = new Image(imageStream));
 | 
				
			||||||
 | 
					        return SetServerIconResult.Success;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					    private bool IsValidUri(string img) => !string.IsNullOrWhiteSpace(img) && Uri.IsWellFormedUriString(img, UriKind.Absolute);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -460,41 +460,6 @@ public partial class Administration
 | 
				
			|||||||
            await Response().Confirm(strs.bot_name(Format.Bold(newName))).SendAsync();
 | 
					            await Response().Confirm(strs.bot_name(Format.Bold(newName))).SendAsync();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        [Cmd]
 | 
					 | 
				
			||||||
        [UserPerm(GuildPerm.ManageNicknames)]
 | 
					 | 
				
			||||||
        [BotPerm(GuildPerm.ChangeNickname)]
 | 
					 | 
				
			||||||
        [Priority(0)]
 | 
					 | 
				
			||||||
        public async Task SetNick([Leftover] string newNick = null)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            if (string.IsNullOrWhiteSpace(newNick))
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            var curUser = await ctx.Guild.GetCurrentUserAsync();
 | 
					 | 
				
			||||||
            await curUser.ModifyAsync(u => u.Nickname = newNick);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            await Response().Confirm(strs.bot_nick(Format.Bold(newNick) ?? "-")).SendAsync();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        [Cmd]
 | 
					 | 
				
			||||||
        [BotPerm(GuildPerm.ManageNicknames)]
 | 
					 | 
				
			||||||
        [UserPerm(GuildPerm.ManageNicknames)]
 | 
					 | 
				
			||||||
        [Priority(1)]
 | 
					 | 
				
			||||||
        public async Task SetNick(IGuildUser gu, [Leftover] string newNick = null)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            var sg = (SocketGuild)ctx.Guild;
 | 
					 | 
				
			||||||
            if (sg.OwnerId == gu.Id
 | 
					 | 
				
			||||||
                || gu.GetRoles().Max(r => r.Position) >= sg.CurrentUser.GetRoles().Max(r => r.Position))
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                await Response().Error(strs.insuf_perms_i).SendAsync();
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            await gu.ModifyAsync(u => u.Nickname = newNick);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            await Response()
 | 
					 | 
				
			||||||
                  .Confirm(strs.user_nick(Format.Bold(gu.ToString()), Format.Bold(newNick) ?? "-"))
 | 
					 | 
				
			||||||
                  .SendAsync();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        [Cmd]
 | 
					        [Cmd]
 | 
				
			||||||
        [OwnerOnly]
 | 
					        [OwnerOnly]
 | 
				
			||||||
        public async Task SetStatus([Leftover] SettableUserStatus status)
 | 
					        public async Task SetStatus([Leftover] SettableUserStatus status)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					namespace NadekoBot.Modules.Administration._common.results;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum SetServerBannerResult
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Success,
 | 
				
			||||||
 | 
					    InvalidFileType,
 | 
				
			||||||
 | 
					    Toolarge,
 | 
				
			||||||
 | 
					    InvalidURL
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					namespace NadekoBot.Modules.Administration._common.results;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum SetServerIconResult
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Success,
 | 
				
			||||||
 | 
					    InvalidFileType,
 | 
				
			||||||
 | 
					    InvalidURL
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
#nullable disable warnings
 | 
					#nullable disable warnings
 | 
				
			||||||
using NadekoBot.Common.Yml;
 | 
					using NadekoBot.Common.Yml;
 | 
				
			||||||
using NadekoBot.Db;
 | 
					using NadekoBot.Db;
 | 
				
			||||||
using NadekoBot.Db.Models;
 | 
					using NadekoBot.Db.Models;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -195,6 +195,12 @@ setname:
 | 
				
			|||||||
  - newnm
 | 
					  - newnm
 | 
				
			||||||
setnick:
 | 
					setnick:
 | 
				
			||||||
  - setnick
 | 
					  - setnick
 | 
				
			||||||
 | 
					setserverbanner:
 | 
				
			||||||
 | 
					  - setserverbanner
 | 
				
			||||||
 | 
					  - serverbanner
 | 
				
			||||||
 | 
					setservericon:
 | 
				
			||||||
 | 
					  - setservericon
 | 
				
			||||||
 | 
					  - servericon
 | 
				
			||||||
setavatar:
 | 
					setavatar:
 | 
				
			||||||
  - setavatar
 | 
					  - setavatar
 | 
				
			||||||
  - setav
 | 
					  - setav
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -809,6 +809,20 @@ setgame:
 | 
				
			|||||||
        desc: "The activity type determines whether the bot is engaged in a game, listening to audio, or watching a video."
 | 
					        desc: "The activity type determines whether the bot is engaged in a game, listening to audio, or watching a video."
 | 
				
			||||||
      game:
 | 
					      game:
 | 
				
			||||||
        desc: "The current state of the bot's activity in the game."
 | 
					        desc: "The current state of the bot's activity in the game."
 | 
				
			||||||
 | 
					setserverbanner:
 | 
				
			||||||
 | 
					  desc: Sets a new banner image for the current server. Parameter is a direct link to an image.
 | 
				
			||||||
 | 
					  ex:
 | 
				
			||||||
 | 
					    - https://i.imgur.com/xTG3a1I.jpg
 | 
				
			||||||
 | 
					  params:
 | 
				
			||||||
 | 
					    - img:
 | 
				
			||||||
 | 
					        desc: "The URL of the image file to be displayed as the bot's banner."
 | 
				
			||||||
 | 
					setservericon:
 | 
				
			||||||
 | 
					  desc: Sets a new icon image for the current server. Parameter is a direct link to an image.
 | 
				
			||||||
 | 
					  ex:
 | 
				
			||||||
 | 
					    - https://i.imgur.com/xTG3a1I.jpg
 | 
				
			||||||
 | 
					  params:
 | 
				
			||||||
 | 
					    - img:
 | 
				
			||||||
 | 
					        desc: "The URL of the image file to be displayed as the bot's banner."
 | 
				
			||||||
send:
 | 
					send:
 | 
				
			||||||
  desc: 'Sends a message to a channel or user. Channel or user can be '
 | 
					  desc: 'Sends a message to a channel or user. Channel or user can be '
 | 
				
			||||||
  ex:
 | 
					  ex:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -188,6 +188,11 @@
 | 
				
			|||||||
  "setrole_err": "Failed to add role. I have insufficient permissions.",
 | 
					  "setrole_err": "Failed to add role. I have insufficient permissions.",
 | 
				
			||||||
  "set_avatar": "New avatar set!",
 | 
					  "set_avatar": "New avatar set!",
 | 
				
			||||||
  "set_banner": "New banner set!",
 | 
					  "set_banner": "New banner set!",
 | 
				
			||||||
 | 
					  "set_srvr_icon": "New server icon set!",
 | 
				
			||||||
 | 
					  "set_srvr_banner": "New server banner set!",
 | 
				
			||||||
 | 
					  "srvr_banner_invalid": "Specified image has an invalid filetype. Make sure you're specifying a direct image url.",
 | 
				
			||||||
 | 
					  "srvr_banner_too_large": "Specified image is too large! Maximum size is 8MB.",
 | 
				
			||||||
 | 
					  "srvr_banner_invalid_url": "Specified url is not valid. Make sure you're specifying a direct image url.",
 | 
				
			||||||
  "set_channel_name": "New channel name set.",
 | 
					  "set_channel_name": "New channel name set.",
 | 
				
			||||||
  "set_game": "New game set!",
 | 
					  "set_game": "New game set!",
 | 
				
			||||||
  "set_stream": "New stream set!",
 | 
					  "set_stream": "New stream set!",
 | 
				
			||||||
@@ -875,7 +880,7 @@
 | 
				
			|||||||
  "club_disband_error": "Error. You are either not in a club, or you are not the owner of your club.",
 | 
					  "club_disband_error": "Error. You are either not in a club, or you are not the owner of your club.",
 | 
				
			||||||
  "club_icon_too_large": "Image is too large.",
 | 
					  "club_icon_too_large": "Image is too large.",
 | 
				
			||||||
  "club_icon_invalid_filetype": "Specified image has an invalid filetype. Make sure you're specifying a direct image url.",
 | 
					  "club_icon_invalid_filetype": "Specified image has an invalid filetype. Make sure you're specifying a direct image url.",
 | 
				
			||||||
  "club_icon_url_format": "You must specify an absolute image url/.",
 | 
					  "club_icon_url_format": "You must specify an absolute image url.",
 | 
				
			||||||
  "club_icon_set": "New club icon set.",
 | 
					  "club_icon_set": "New club icon set.",
 | 
				
			||||||
  "club_bans_for": "Bans for {0} club",
 | 
					  "club_bans_for": "Bans for {0} club",
 | 
				
			||||||
  "club_apps_for": "Applicants for {0} club",
 | 
					  "club_apps_for": "Applicants for {0} club",
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user