mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 01:38:27 -04:00
Merge branch 'v4' into v5
This commit is contained in:
17
CHANGELOG.md
17
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
|
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
|
## [4.3.20] - 20.01.2024
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@@ -147,4 +147,5 @@ public sealed class DoAsUserMessage : IUserMessage
|
|||||||
public MessageResolvedData ResolvedData => _msg.ResolvedData;
|
public MessageResolvedData ResolvedData => _msg.ResolvedData;
|
||||||
|
|
||||||
public IUserMessage ReferencedMessage => _msg.ReferencedMessage;
|
public IUserMessage ReferencedMessage => _msg.ReferencedMessage;
|
||||||
|
public IMessageInteractionMetadata InteractionMetadata { get; }
|
||||||
}
|
}
|
@@ -165,8 +165,8 @@ public static class MessageChannelExtensions
|
|||||||
private const string BUTTON_LEFT = "BUTTON_LEFT";
|
private const string BUTTON_LEFT = "BUTTON_LEFT";
|
||||||
private const string BUTTON_RIGHT = "BUTTON_RIGHT";
|
private const string BUTTON_RIGHT = "BUTTON_RIGHT";
|
||||||
|
|
||||||
private static readonly IEmote _arrowLeft = Emote.Parse("<:x:969658061805465651>");
|
private static readonly IEmote _arrowLeft = Emote.Parse("<:x:1232256519844790302>");
|
||||||
private static readonly IEmote _arrowRight = Emote.Parse("<:x:969658062220701746>");
|
private static readonly IEmote _arrowRight = Emote.Parse("<:x:1232256515298295838>");
|
||||||
|
|
||||||
public static Task SendPaginatedConfirmAsync(
|
public static Task SendPaginatedConfirmAsync(
|
||||||
this ICommandContext ctx,
|
this ICommandContext ctx,
|
||||||
|
@@ -28,5 +28,10 @@ public class DiscordUser : DbEntity
|
|||||||
=> UserId.GetHashCode();
|
=> UserId.GetHashCode();
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
=> Discriminator == "0000" ? Username : Username + "#" + Discriminator;
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(Discriminator) || Discriminator == "0000")
|
||||||
|
return Username;
|
||||||
|
|
||||||
|
return Username + "#" + Discriminator;
|
||||||
|
}
|
||||||
}
|
}
|
@@ -502,6 +502,16 @@ public partial class Administration
|
|||||||
await ReplyConfirmLocalizedAsync(strs.set_avatar);
|
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]
|
[Cmd]
|
||||||
[OwnerOnly]
|
[OwnerOnly]
|
||||||
public async Task SetGame(ActivityType type, [Leftover] string game = null)
|
public async Task SetGame(ActivityType type, [Leftover] string game = null)
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using NadekoBot.Common.ModuleBehaviors;
|
using NadekoBot.Common.ModuleBehaviors;
|
||||||
using Nadeko.Bot.Db.Models;
|
using Nadeko.Bot.Db.Models;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
@@ -323,6 +322,40 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, INService
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> 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()
|
public void ClearStartupCommands()
|
||||||
{
|
{
|
||||||
using var uow = _db.GetDbContext();
|
using var uow = _db.GetDbContext();
|
||||||
|
@@ -362,7 +362,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
|||||||
if (before.Username != after.Username)
|
if (before.Username != after.Username)
|
||||||
{
|
{
|
||||||
embed.WithTitle("👥 " + GetText(g, strs.username_changed))
|
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("Old Name", $"{before.Username}", true)
|
||||||
.AddField("New Name", $"{after.Username}", true)
|
.AddField("New Name", $"{after.Username}", true)
|
||||||
.WithFooter(CurrentTime(g))
|
.WithFooter(CurrentTime(g))
|
||||||
@@ -904,7 +904,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
|||||||
str = "🎙"
|
str = "🎙"
|
||||||
+ Format.Code(PrettyCurrentTime(usr.Guild))
|
+ Format.Code(PrettyCurrentTime(usr.Guild))
|
||||||
+ GetText(logChannel.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(beforeVch?.Name ?? ""),
|
||||||
Format.Bold(afterVch?.Name ?? "")));
|
Format.Bold(afterVch?.Name ?? "")));
|
||||||
}
|
}
|
||||||
@@ -913,7 +913,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
|||||||
str = "🎙"
|
str = "🎙"
|
||||||
+ Format.Code(PrettyCurrentTime(usr.Guild))
|
+ Format.Code(PrettyCurrentTime(usr.Guild))
|
||||||
+ GetText(logChannel.Guild,
|
+ GetText(logChannel.Guild,
|
||||||
strs.user_vjoined("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator),
|
strs.user_vjoined("👤" + Format.Bold(usr.Username),
|
||||||
Format.Bold(afterVch?.Name ?? "")));
|
Format.Bold(afterVch?.Name ?? "")));
|
||||||
}
|
}
|
||||||
else if (afterVch is null)
|
else if (afterVch is null)
|
||||||
@@ -921,7 +921,7 @@ public sealed class LogCommandService : ILogCommandService, IReadyExecutor
|
|||||||
str = "🎙"
|
str = "🎙"
|
||||||
+ Format.Code(PrettyCurrentTime(usr.Guild))
|
+ Format.Code(PrettyCurrentTime(usr.Guild))
|
||||||
+ GetText(logChannel.Guild,
|
+ GetText(logChannel.Guild,
|
||||||
strs.user_vleft("👤" + Format.Bold(usr.Username + "#" + usr.Discriminator),
|
strs.user_vleft("👤" + Format.Bold(usr.Username),
|
||||||
Format.Bold(beforeVch.Name ?? "")));
|
Format.Bold(beforeVch.Name ?? "")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -252,7 +252,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
|
|
||||||
var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)];
|
var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)];
|
||||||
await SendConfirmAsync("🎟 " + GetText(strs.raffled_user),
|
await SendConfirmAsync("🎟 " + GetText(strs.raffled_user),
|
||||||
$"**{usr.Username}#{usr.Discriminator}**",
|
$"**{usr.Username}**",
|
||||||
footer: $"ID: {usr.Id}");
|
footer: $"ID: {usr.Id}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,7 +271,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
|
|
||||||
var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)];
|
var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)];
|
||||||
await SendConfirmAsync("🎟 " + GetText(strs.raffled_user),
|
await SendConfirmAsync("🎟 " + GetText(strs.raffled_user),
|
||||||
$"**{usr.Username}#{usr.Discriminator}**",
|
$"**{usr.Username}**",
|
||||||
footer: $"ID: {usr.Id}");
|
footer: $"ID: {usr.Id}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -260,8 +260,8 @@ public partial class Xp
|
|||||||
await ReplyConfirmLocalizedAsync(strs.club_applied(Format.Bold(club.ToString())));
|
await ReplyConfirmLocalizedAsync(strs.club_applied(Format.Bold(club.ToString())));
|
||||||
else if (result == ClubApplyResult.Banned)
|
else if (result == ClubApplyResult.Banned)
|
||||||
await ReplyErrorLocalizedAsync(strs.club_join_banned);
|
await ReplyErrorLocalizedAsync(strs.club_join_banned);
|
||||||
else if (result == ClubApplyResult.InsufficientLevel)
|
else if (result == ClubApplyResult.AlreadyApplied)
|
||||||
await ReplyErrorLocalizedAsync(strs.club_insuff_lvl);
|
await ReplyErrorLocalizedAsync(strs.club_already_applied);
|
||||||
else if (result == ClubApplyResult.AlreadyInAClub)
|
else if (result == ClubApplyResult.AlreadyInAClub)
|
||||||
await ReplyErrorLocalizedAsync(strs.club_already_in);
|
await ReplyErrorLocalizedAsync(strs.club_already_in);
|
||||||
}
|
}
|
||||||
|
@@ -149,7 +149,7 @@ public class ClubService : INService, IClubService
|
|||||||
return ClubApplyResult.Banned;
|
return ClubApplyResult.Banned;
|
||||||
|
|
||||||
if (club.Applicants.Any(x => x.UserId == du.Id))
|
if (club.Applicants.Any(x => x.UserId == du.Id))
|
||||||
return ClubApplyResult.InsufficientLevel;
|
return ClubApplyResult.AlreadyApplied;
|
||||||
|
|
||||||
var app = new ClubApplicants
|
var app = new ClubApplicants
|
||||||
{
|
{
|
||||||
|
@@ -28,8 +28,7 @@ public interface IClubService
|
|||||||
public enum ClubApplyResult
|
public enum ClubApplyResult
|
||||||
{
|
{
|
||||||
Success,
|
Success,
|
||||||
|
|
||||||
AlreadyInAClub,
|
AlreadyInAClub,
|
||||||
Banned,
|
Banned,
|
||||||
InsufficientLevel
|
AlreadyApplied
|
||||||
}
|
}
|
@@ -9,7 +9,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Discord.Net.Core" Version="3.203.0" />
|
<PackageReference Include="Discord.Net.Core" Version="3.204.0" />
|
||||||
<PackageReference Include="Serilog" Version="3.1.1" />
|
<PackageReference Include="Serilog" Version="3.1.1" />
|
||||||
<PackageReference Include="YamlDotNet" Version="15.1.2" />
|
<PackageReference Include="YamlDotNet" Version="15.1.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
75
src/NadekoBot/Db/Models/Waifu.cs
Normal file
75
src/NadekoBot/Db/Models/Waifu.cs
Normal file
@@ -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<WaifuItem> 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}";
|
||||||
|
}
|
||||||
|
}
|
@@ -28,7 +28,7 @@
|
|||||||
<PackageReference Include="AWSSDK.S3" Version="3.7.307" />
|
<PackageReference Include="AWSSDK.S3" Version="3.7.307" />
|
||||||
<PackageReference Include="CodeHollow.FeedReader" Version="1.2.6" />
|
<PackageReference Include="CodeHollow.FeedReader" Version="1.2.6" />
|
||||||
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageReference Include="Discord.Net" Version="3.203.0" />
|
<PackageReference Include="Discord.Net" Version="3.204.0" />
|
||||||
<PackageReference Include="CoreCLR-NCalc" Version="3.0.203" />
|
<PackageReference Include="CoreCLR-NCalc" Version="3.0.203" />
|
||||||
<PackageReference Include="Google.Apis.Urlshortener.v1" Version="1.41.1.138" />
|
<PackageReference Include="Google.Apis.Urlshortener.v1" Version="1.41.1.138" />
|
||||||
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.62.1.3205" />
|
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.62.1.3205" />
|
||||||
|
@@ -195,6 +195,8 @@ setnick:
|
|||||||
setavatar:
|
setavatar:
|
||||||
- setavatar
|
- setavatar
|
||||||
- setav
|
- setav
|
||||||
|
setbanner:
|
||||||
|
- setbanner
|
||||||
setgame:
|
setgame:
|
||||||
- setgame
|
- setgame
|
||||||
send:
|
send:
|
||||||
|
@@ -402,6 +402,10 @@ setavatar:
|
|||||||
desc: "Sets a new avatar image for the NadekoBot. Parameter is a direct link to an image."
|
desc: "Sets a new avatar image for the NadekoBot. Parameter is a direct link to an image."
|
||||||
args:
|
args:
|
||||||
- "https://i.imgur.com/xTG3a1I.jpg"
|
- "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:
|
setgame:
|
||||||
desc: "Sets the bots game status to either Playing, Listening, or Watching."
|
desc: "Sets the bots game status to either Playing, Listening, or Watching."
|
||||||
args:
|
args:
|
||||||
|
@@ -184,6 +184,7 @@
|
|||||||
"setrole": "Successfully added role {0} to user {1}",
|
"setrole": "Successfully added role {0} to user {1}",
|
||||||
"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_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!",
|
||||||
@@ -838,7 +839,7 @@
|
|||||||
"server_leaderboard": "Server XP Leaderboard",
|
"server_leaderboard": "Server XP Leaderboard",
|
||||||
"global_leaderboard": "Global XP Leaderboard",
|
"global_leaderboard": "Global XP Leaderboard",
|
||||||
"modified": "Modified server XP of the user {0} by {1}",
|
"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_join_banned": "You're banned from that club.",
|
||||||
"club_already_in": "You are already a member of a club.",
|
"club_already_in": "You are already a member of a club.",
|
||||||
"club_name_too_long": "Club name is too long.",
|
"club_name_too_long": "Club name is too long.",
|
||||||
|
Reference in New Issue
Block a user