added .rolecolor command

updated changelog
This commit is contained in:
Toastie 2025-03-23 15:48:45 +13:00
parent 55e3a80405
commit 16025b74e3
Signed by: toastie_t0ast
GPG key ID: 0861BE54AD481DC7
9 changed files with 182 additions and 31 deletions

View file

@ -2,6 +2,22 @@
*a,c,f,r,o*
## [6.0.13] - 23.03.2025
### Added
- Added `.linkfix <old> <new>` command
- If bot sees a message with the old link, it will reply to the message with a fixed (new) link
- ex: `.linkfix twitter.com vxtwitter.com`
- Added `.roleicon role <icon_url / server_emoji>` command to set the icon of a role
- Added a captcha option for `.fish`
### Fixed
- fixed youtube stream notifications in case invalid channel was provided
- `.lcha` (live channel) will now let you override an existing channel template even if you're at the limit
### Removed
- removed `.xpglb` as it is no longer used
## [6.0.12] - 20.03.2025
### Fixed

View file

@ -4,7 +4,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>true</ImplicitUsings>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<Version>6.0.12</Version>
<Version>6.0.13</Version>
<!-- Output/build -->
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>

View file

@ -48,9 +48,9 @@ public partial class Administration
});
await Response()
.Confirm(strs.setrole(Format.Bold(roleToAdd.Name),
Format.Bold(targetUser.ToString())))
.SendAsync();
.Confirm(strs.setrole(Format.Bold(roleToAdd.Name),
Format.Bold(targetUser.ToString())))
.SendAsync();
}
catch (Exception ex)
{
@ -73,9 +73,9 @@ public partial class Administration
{
await targetUser.RemoveRoleAsync(roleToRemove);
await Response()
.Confirm(strs.remrole(Format.Bold(roleToRemove.Name),
Format.Bold(targetUser.ToString())))
.SendAsync();
.Confirm(strs.remrole(Format.Bold(roleToRemove.Name),
Format.Bold(targetUser.ToString())))
.SendAsync();
}
catch
{
@ -226,8 +226,8 @@ public partial class Administration
if (!await CheckRoleHierarchy(role))
{
await Response()
.Error(strs.hierarchy)
.SendAsync();
.Error(strs.hierarchy)
.SendAsync();
return;
}
@ -236,10 +236,83 @@ public partial class Administration
await Response()
.Confirm(strs.temp_role_added(user.Mention,
Format.Bold(role.Name),
TimestampTag.FromDateTime(DateTime.UtcNow.Add(timespan.Time), TimestampTagStyles.Relative)))
.SendAsync();
.Confirm(strs.temp_role_added(user.Mention,
Format.Bold(role.Name),
TimestampTag.FromDateTime(DateTime.UtcNow.Add(timespan.Time), TimestampTagStyles.Relative)))
.SendAsync();
}
[Cmd]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.ManageRoles)]
[BotPerm(GuildPerm.ManageRoles)]
public Task RoleIcon(IRole role, Emote emote)
=> RoleIcon(role, emote.Url);
[Cmd]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.ManageRoles)]
[BotPerm(GuildPerm.ManageRoles)]
public async Task RoleIcon(IRole role, [Leftover] string iconUrl)
{
if (!await CheckRoleHierarchy(role))
return;
if (string.IsNullOrWhiteSpace(iconUrl))
{
await Response().Error(strs.userrole_icon_invalid).SendAsync();
return;
}
// Validate the URL format
if (!Uri.TryCreate(iconUrl, UriKind.Absolute, out var uri))
{
await Response().Error(strs.userrole_icon_invalid).SendAsync();
return;
}
// Download the image
using var httpClient = new HttpClient();
using var response = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead);
// Check if the response is successful
if (!response.IsSuccessStatusCode)
{
await Response().Error(strs.userrole_icon_fail).SendAsync();
return;
}
// Check content type - must be image/png or image/jpeg
var contentType = response.Content.Headers.ContentType?.MediaType?.ToLower();
if (contentType != "image/png"
&& contentType != "image/jpeg"
&& contentType != "image/webp")
{
await Response().Error(strs.userrole_icon_fail).SendAsync();
return;
}
// Check file size - Discord limit is 256KB
var contentLength = response.Content.Headers.ContentLength;
if (contentLength is > 256 * 1024)
{
await Response().Error(strs.userrole_icon_fail).SendAsync();
return;
}
// Save the image to a memory stream
await using var stream = await response.Content.ReadAsStreamAsync();
await using var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream);
memoryStream.Position = 0;
// Create Discord image from stream
using var discordImage = new Image(memoryStream);
// Upload the image to Discord
await role.ModifyAsync(r => r.Icon = discordImage);
await Response().Confirm(strs.userrole_icon_success(Format.Bold(role.Name))).SendAsync();
}
}
}

View file

@ -30,8 +30,8 @@ public partial class LinkFixerService(DbService db) : IReadyExecutor, IExecNoCom
public async Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
{
if(guild is null)
return;
if (guild is null)
return;
var guildId = guild.Id;
if (!_guildLinkFixes.TryGetValue(guildId, out var guildDict))
@ -52,7 +52,7 @@ public partial class LinkFixerService(DbService db) : IReadyExecutor, IExecNoCom
if (string.IsNullOrWhiteSpace(domain))
continue;
if(!guildDict.TryGetValue(domain, out var newDomain))
if (!guildDict.TryGetValue(domain, out var newDomain))
continue;
var newUrl = match.Groups["prefix"].Value + newDomain + match.Groups["suffix"].Value;
@ -73,10 +73,10 @@ public partial class LinkFixerService(DbService db) : IReadyExecutor, IExecNoCom
public async Task<bool> AddLinkFixAsync(ulong guildId, string oldDomain, string newDomain)
{
oldDomain = oldDomain.ToLowerInvariant();
var guildDict = _guildLinkFixes.GetOrAdd(guildId, _ => new ConcurrentDictionary<string, string>());
guildDict[oldDomain] = newDomain;
await using var uow = db.GetDbContext();
await uow.GetTable<LinkFix>()
.InsertOrUpdateAsync(() => new LinkFix
@ -107,7 +107,7 @@ public partial class LinkFixerService(DbService db) : IReadyExecutor, IExecNoCom
public async Task<bool> RemoveLinkFixAsync(ulong guildId, string oldDomain)
{
oldDomain = oldDomain.ToLowerInvariant();
if (!_guildLinkFixes.TryGetValue(guildId, out var guildDict) || !guildDict.TryRemove(oldDomain, out _))
return false;

View file

@ -154,7 +154,7 @@ public sealed class UserRoleService : IUserRoleService, IEService
memoryStream.Position = 0;
// Create Discord image from stream
var discordImage = new Image(memoryStream);
using var discordImage = new Image(memoryStream);
// Upload the image to Discord
var discordSuccess = await _discordRoleManager.ModifyRoleAsync(

View file

@ -1606,6 +1606,21 @@
"Administrator Server Permission"
]
},
{
"Aliases": [
".roleicon"
],
"Description": "Changes the icon of a role.",
"Usage": [
".roleicon @Role :server_emoji_here:"
],
"Submodule": "RoleCommands",
"Module": "Administration",
"Options": null,
"Requirements": [
"ManageRoles Server Permission"
]
},
{
"Aliases": [
".iam"
@ -7384,6 +7399,37 @@
"ManageChannels Channel Permission"
]
},
{
"Aliases": [
".linkfix",
".lfix"
],
"Description": "Configures automatic link fixing from one site to another.\nWhen a user posts a link containing the old domain, the bot will automatically fix it to use the new domain.\nProvide no second domain to disable link fixing.",
"Usage": [
".linkfix twitter.com vxtwitter.com",
".linkfix x.com"
],
"Submodule": "LinkFixerCommands",
"Module": "Utility",
"Options": null,
"Requirements": [
"ManageMessages Server Permission"
]
},
{
"Aliases": [
".linkfixlist",
".lfixlist"
],
"Description": "Lists all configured link fixes for the server.",
"Usage": [
".linkfixlist"
],
"Submodule": "LinkFixerCommands",
"Module": "Utility",
"Options": null,
"Requirements": []
},
{
"Aliases": [
".livechadd",
@ -8218,7 +8264,7 @@
],
"Description": "Changes the icon of your assigned role.",
"Usage": [
".userroleicon @Role :thumbsup:"
".userroleicon @Role :server_emoji_here:"
],
"Submodule": "UserRoleCommands",
"Module": "Utility",

View file

@ -21,24 +21,24 @@ chance:
fish:
- id: 0
name: Bass
weather:
spot:
time:
weather:
spot:
time:
chance: 100
stars: 4
fluff: Very common.
condition:
condition:
image: https://cdn.nadeko.bot/fish/bass.png
emoji: <:bass:1328520376892002386>
trash:
- id: 1002
name: Plastic Bag
weather:
spot:
time:
weather:
spot:
time:
chance: 50
stars: 4
fluff: Trophy of your contribution to the environment.
condition:
condition:
image: https://cdn.nadeko.bot/fish/plasticbag.png
emoji: <:plasticbag:1328520895454515211>
emoji: <:plasticbag:1328520895454515211>

View file

@ -165,6 +165,8 @@ deleterole:
rolecolor:
- rolecolor
- roleclr
roleicon:
- roleicon
ban:
- ban
- b

View file

@ -599,6 +599,20 @@ rolehoist:
params:
- role:
desc: "The role that determines the visibility of the sidebar."
roleicon:
desc: |-
Changes the icon of a role.
ex:
- '@Role :server_emoji_here:'
params:
- role:
desc: 'The role to change the icon of.'
imageUrl:
desc: 'The image url to be used as a new icon for the role.'
- role:
desc: 'The role to change the icon of.'
serverEmoji:
desc: 'The server emoji to be used as a new icon for the role.'
createrole:
desc: Creates a role with a given name.
ex:
@ -5054,7 +5068,7 @@ userroleicon:
desc: |-
Changes the icon of your assigned role.
ex:
- '@Role :thumbsup:'
- '@Role :server_emoji_here:'
params:
- role:
desc: 'The assigned role to change the icon of.'