diff --git a/CHANGELOG.md b/CHANGELOG.md index 37ba26692..7b95b0b79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except date format. a-c-f-r-o +## [4.3.22] - 23.04.2023 + +### Added +- Added `.setbanner` command (thx cata) + +### Fixed +- Fixed pagination error due to a missing emoji + + +## [4.3.21] - 19.04.2023 + +### Fixed +- Possible fix for a duplicate in `.h bank` +- Fixed `.stock` command +- Fixed `.clubapply` and `.clubaccept` +- Removed some redundant discriminators + ## [4.3.20] - 20.01.2024 ### Fixed diff --git a/src/Nadeko.Bot.Common/DoAsUserMessage.cs b/src/Nadeko.Bot.Common/DoAsUserMessage.cs index 40edc4234..950ed4914 100644 --- a/src/Nadeko.Bot.Common/DoAsUserMessage.cs +++ b/src/Nadeko.Bot.Common/DoAsUserMessage.cs @@ -147,4 +147,5 @@ public sealed class DoAsUserMessage : IUserMessage public MessageResolvedData ResolvedData => _msg.ResolvedData; public IUserMessage ReferencedMessage => _msg.ReferencedMessage; + public IMessageInteractionMetadata InteractionMetadata { get; } } \ No newline at end of file diff --git a/src/Nadeko.Bot.Common/_Extensions/IMessageChannelExtensions.cs b/src/Nadeko.Bot.Common/_Extensions/IMessageChannelExtensions.cs index 092273194..afad257ed 100644 --- a/src/Nadeko.Bot.Common/_Extensions/IMessageChannelExtensions.cs +++ b/src/Nadeko.Bot.Common/_Extensions/IMessageChannelExtensions.cs @@ -165,8 +165,8 @@ public static class MessageChannelExtensions private const string BUTTON_LEFT = "BUTTON_LEFT"; private const string BUTTON_RIGHT = "BUTTON_RIGHT"; - private static readonly IEmote _arrowLeft = Emote.Parse("<:x:969658061805465651>"); - private static readonly IEmote _arrowRight = Emote.Parse("<:x:969658062220701746>"); + private static readonly IEmote _arrowLeft = Emote.Parse("<:x:1232256519844790302>"); + private static readonly IEmote _arrowRight = Emote.Parse("<:x:1232256515298295838>"); public static Task SendPaginatedConfirmAsync( this ICommandContext ctx, diff --git a/src/Nadeko.Bot.Db/Models/DiscordUser.cs b/src/Nadeko.Bot.Db/Models/DiscordUser.cs index d64fb38ec..3cfa73ec1 100644 --- a/src/Nadeko.Bot.Db/Models/DiscordUser.cs +++ b/src/Nadeko.Bot.Db/Models/DiscordUser.cs @@ -28,5 +28,10 @@ public class DiscordUser : DbEntity => UserId.GetHashCode(); public override string ToString() - => Discriminator == "0000" ? Username : Username + "#" + Discriminator; + { + if (string.IsNullOrWhiteSpace(Discriminator) || Discriminator == "0000") + return Username; + + return Username + "#" + Discriminator; + } } \ No newline at end of file diff --git a/src/Nadeko.Bot.Modules.Administration/Self/SelfCommands.cs b/src/Nadeko.Bot.Modules.Administration/Self/SelfCommands.cs index b16f1db23..c7948c37e 100644 --- a/src/Nadeko.Bot.Modules.Administration/Self/SelfCommands.cs +++ b/src/Nadeko.Bot.Modules.Administration/Self/SelfCommands.cs @@ -501,6 +501,16 @@ public partial class Administration if (success) await ReplyConfirmLocalizedAsync(strs.set_avatar); } + + [Cmd] + [OwnerOnly] + public async Task SetBanner([Leftover] string img = null) + { + var success = await _service.SetBanner(img); + + if (success) + await ReplyConfirmLocalizedAsync(strs.set_banner); + } [Cmd] [OwnerOnly] diff --git a/src/Nadeko.Bot.Modules.Administration/Self/SelfService.cs b/src/Nadeko.Bot.Modules.Administration/Self/SelfService.cs index 6018f44f1..19ad30dfe 100644 --- a/src/Nadeko.Bot.Modules.Administration/Self/SelfService.cs +++ b/src/Nadeko.Bot.Modules.Administration/Self/SelfService.cs @@ -1,5 +1,4 @@ #nullable disable -using Microsoft.EntityFrameworkCore; using NadekoBot.Common.ModuleBehaviors; using Nadeko.Bot.Db.Models; using System.Collections.Immutable; @@ -323,6 +322,40 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService return true; } + public async Task SetBanner(string img) + { + if (string.IsNullOrWhiteSpace(img)) + { + return false; + } + + if (!Uri.IsWellFormedUriString(img, UriKind.Absolute)) + { + return false; + } + + var uri = new Uri(img); + + using var http = _httpFactory.CreateClient(); + using var sr = await http.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead); + + if (!sr.IsImage()) + { + return false; + } + + if (sr.GetContentLength() > 8.Megabytes().Bytes) + { + return false; + } + + await using var imageStream = await sr.Content.ReadAsStreamAsync(); + + await _client.CurrentUser.ModifyAsync(x => x.Banner = new Image(imageStream)); + return true; + } + + public void ClearStartupCommands() { using var uow = _db.GetDbContext(); diff --git a/src/Nadeko.Bot.Modules.Administration/ServerLog/ServerLogCommandService.cs b/src/Nadeko.Bot.Modules.Administration/ServerLog/ServerLogCommandService.cs index a0e22881e..7aca047ed 100644 --- a/src/Nadeko.Bot.Modules.Administration/ServerLog/ServerLogCommandService.cs +++ b/src/Nadeko.Bot.Modules.Administration/ServerLog/ServerLogCommandService.cs @@ -362,7 +362,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor if (before.Username != after.Username) { embed.WithTitle("👥 " + GetText(g, strs.username_changed)) - .WithDescription($"{before.Username}#{before.Discriminator} | {before.Id}") + .WithDescription($"{before.Username} | {before.Id}") .AddField("Old Name", $"{before.Username}", true) .AddField("New Name", $"{after.Username}", true) .WithFooter(CurrentTime(g)) @@ -904,7 +904,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor str = "🎙" + Format.Code(PrettyCurrentTime(usr.Guild)) + GetText(logChannel.Guild, - strs.user_vmoved("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), + strs.user_vmoved("👤" + Format.Bold(usr.Username), Format.Bold(beforeVch?.Name ?? ""), Format.Bold(afterVch?.Name ?? ""))); } @@ -913,7 +913,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor str = "🎙" + Format.Code(PrettyCurrentTime(usr.Guild)) + GetText(logChannel.Guild, - strs.user_vjoined("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), + strs.user_vjoined("👤" + Format.Bold(usr.Username), Format.Bold(afterVch?.Name ?? ""))); } else if (afterVch is null) @@ -921,7 +921,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor str = "🎙" + Format.Code(PrettyCurrentTime(usr.Guild)) + GetText(logChannel.Guild, - strs.user_vleft("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator), + strs.user_vleft("👤" + Format.Bold(usr.Username), Format.Bold(beforeVch.Name ?? ""))); } diff --git a/src/Nadeko.Bot.Modules.Gambling/Gambling/Gambling.cs b/src/Nadeko.Bot.Modules.Gambling/Gambling/Gambling.cs index 270f9bbec..ad762bbe7 100644 --- a/src/Nadeko.Bot.Modules.Gambling/Gambling/Gambling.cs +++ b/src/Nadeko.Bot.Modules.Gambling/Gambling/Gambling.cs @@ -252,7 +252,7 @@ public partial class Gambling : GamblingModule var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)]; await SendConfirmAsync("🎟 " + GetText(strs.raffled_user), - $"**{usr.Username}#{usr.Discriminator}**", + $"**{usr.Username}**", footer: $"ID: {usr.Id}"); } @@ -271,7 +271,7 @@ public partial class Gambling : GamblingModule var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)]; await SendConfirmAsync("🎟 " + GetText(strs.raffled_user), - $"**{usr.Username}#{usr.Discriminator}**", + $"**{usr.Username}**", footer: $"ID: {usr.Id}"); } diff --git a/src/Nadeko.Bot.Modules.Xp/Club/Club.cs b/src/Nadeko.Bot.Modules.Xp/Club/Club.cs index 0f42dc4e3..7ece9ce0f 100644 --- a/src/Nadeko.Bot.Modules.Xp/Club/Club.cs +++ b/src/Nadeko.Bot.Modules.Xp/Club/Club.cs @@ -260,8 +260,8 @@ public partial class Xp await ReplyConfirmLocalizedAsync(strs.club_applied(Format.Bold(club.ToString()))); else if (result == ClubApplyResult.Banned) await ReplyErrorLocalizedAsync(strs.club_join_banned); - else if (result == ClubApplyResult.InsufficientLevel) - await ReplyErrorLocalizedAsync(strs.club_insuff_lvl); + else if (result == ClubApplyResult.AlreadyApplied) + await ReplyErrorLocalizedAsync(strs.club_already_applied); else if (result == ClubApplyResult.AlreadyInAClub) await ReplyErrorLocalizedAsync(strs.club_already_in); } diff --git a/src/Nadeko.Bot.Modules.Xp/Club/ClubService.cs b/src/Nadeko.Bot.Modules.Xp/Club/ClubService.cs index c8cd3b831..fe0df6f61 100644 --- a/src/Nadeko.Bot.Modules.Xp/Club/ClubService.cs +++ b/src/Nadeko.Bot.Modules.Xp/Club/ClubService.cs @@ -149,7 +149,7 @@ public class ClubService : INService, IClubService return ClubApplyResult.Banned; if (club.Applicants.Any(x => x.UserId == du.Id)) - return ClubApplyResult.InsufficientLevel; + return ClubApplyResult.AlreadyApplied; var app = new ClubApplicants { diff --git a/src/Nadeko.Bot.Modules.Xp/Club/IClubService.cs b/src/Nadeko.Bot.Modules.Xp/Club/IClubService.cs index de59e497f..c582e02dc 100644 --- a/src/Nadeko.Bot.Modules.Xp/Club/IClubService.cs +++ b/src/Nadeko.Bot.Modules.Xp/Club/IClubService.cs @@ -28,8 +28,7 @@ public interface IClubService public enum ClubApplyResult { Success, - AlreadyInAClub, Banned, - InsufficientLevel + AlreadyApplied } \ No newline at end of file diff --git a/src/Nadeko.Medusa/Nadeko.Medusa.csproj b/src/Nadeko.Medusa/Nadeko.Medusa.csproj index a10f54677..a0e3f1c06 100644 --- a/src/Nadeko.Medusa/Nadeko.Medusa.csproj +++ b/src/Nadeko.Medusa/Nadeko.Medusa.csproj @@ -9,7 +9,7 @@ - + diff --git a/src/NadekoBot/Db/Models/Waifu.cs b/src/NadekoBot/Db/Models/Waifu.cs new file mode 100644 index 000000000..43a51dec7 --- /dev/null +++ b/src/NadekoBot/Db/Models/Waifu.cs @@ -0,0 +1,75 @@ +#nullable disable +using NadekoBot.Db.Models; + +namespace NadekoBot.Services.Database.Models; + +public class WaifuInfo : DbEntity +{ + public int WaifuId { get; set; } + public DiscordUser Waifu { get; set; } + + public int? ClaimerId { get; set; } + public DiscordUser Claimer { get; set; } + + public int? AffinityId { get; set; } + public DiscordUser Affinity { get; set; } + + public long Price { get; set; } + public List Items { get; set; } = new(); + + public override string ToString() + { + var status = string.Empty; + + var waifuUsername = Waifu.ToString().TrimTo(20); + var claimer = Claimer?.ToString().TrimTo(20) + ?? "no one"; + + var affinity = Affinity?.ToString().TrimTo(20); + + if (AffinityId is null) + status = $"... but {waifuUsername}'s heart is empty"; + else if (AffinityId == ClaimerId) + status = $"... and {waifuUsername} likes {claimer} too <3"; + else + { + status = + $"... but {waifuUsername}'s heart belongs to {affinity}"; + } + + return $"**{waifuUsername}** - claimed by **{claimer}**\n\t{status}"; + } +} + +public class WaifuLbResult +{ + public string Username { get; set; } + public string Discrim { get; set; } + + public string Claimer { get; set; } + public string ClaimerDiscrim { get; set; } + + public string Affinity { get; set; } + public string AffinityDiscrim { get; set; } + + public long Price { get; set; } + + public override string ToString() + { + var claimer = "no one"; + var status = string.Empty; + + var waifuUsername = Username.TrimTo(20); + var claimerUsername = Claimer?.TrimTo(20); + + if (Claimer is not null) + claimer = $"{claimerUsername}#{ClaimerDiscrim}"; + if (Affinity is null) + status = $"... but {waifuUsername}'s heart is empty"; + else if (Affinity + AffinityDiscrim == Claimer + ClaimerDiscrim) + status = $"... and {waifuUsername} likes {claimerUsername} too <3"; + else + status = $"... but {waifuUsername}'s heart belongs to {Affinity.TrimTo(20)}#{AffinityDiscrim}"; + return $"**{waifuUsername}#{Discrim}** - claimed by **{claimer}**\n\t{status}"; + } +} \ No newline at end of file diff --git a/src/NadekoBot/NadekoBot.csproj b/src/NadekoBot/NadekoBot.csproj index b56805ca4..dae9a2d09 100644 --- a/src/NadekoBot/NadekoBot.csproj +++ b/src/NadekoBot/NadekoBot.csproj @@ -28,7 +28,7 @@ - + diff --git a/src/NadekoBot/data/aliases.yml b/src/NadekoBot/data/aliases.yml index e372fa6d2..8aa0d2d22 100644 --- a/src/NadekoBot/data/aliases.yml +++ b/src/NadekoBot/data/aliases.yml @@ -195,6 +195,8 @@ setnick: setavatar: - setavatar - setav +setbanner: + - setbanner setgame: - setgame send: diff --git a/src/NadekoBot/data/strings/commands/commands.en-US.yml b/src/NadekoBot/data/strings/commands/commands.en-US.yml index a4fda2de5..1e1dd229f 100644 --- a/src/NadekoBot/data/strings/commands/commands.en-US.yml +++ b/src/NadekoBot/data/strings/commands/commands.en-US.yml @@ -402,6 +402,10 @@ setavatar: desc: "Sets a new avatar image for the NadekoBot. Parameter is a direct link to an image." args: - "https://i.imgur.com/xTG3a1I.jpg" +setbanner: + desc: "Sets a new banner image for the NadekoBot. Parameter is a direct link to an image. Supports gifs." + args: + - "https://i.imgur.com/xTG3a1I.jpg" setgame: desc: "Sets the bots game status to either Playing, Listening, or Watching." args: diff --git a/src/NadekoBot/data/strings/responses/responses.en-US.json b/src/NadekoBot/data/strings/responses/responses.en-US.json index f143a5ec3..620a7155a 100644 --- a/src/NadekoBot/data/strings/responses/responses.en-US.json +++ b/src/NadekoBot/data/strings/responses/responses.en-US.json @@ -184,6 +184,7 @@ "setrole": "Successfully added role {0} to user {1}", "setrole_err": "Failed to add role. I have insufficient permissions.", "set_avatar": "New avatar set!", + "set_banner": "New banner set!", "set_channel_name": "New channel name set.", "set_game": "New game set!", "set_stream": "New stream set!", @@ -838,7 +839,7 @@ "server_leaderboard": "Server XP Leaderboard", "global_leaderboard": "Global XP Leaderboard", "modified": "Modified server XP of the user {0} by {1}", - "club_insuff_lvl": "You're insufficient level to join that club.", + "club_already_applied": "You've already applied to that club.", "club_join_banned": "You're banned from that club.", "club_already_in": "You are already a member of a club.", "club_name_too_long": "Club name is too long.",