mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 09:18:27 -04:00
add: Added .quteedit command
add: Added an edit button to .quoteshow and .exprshow commands that opens a modal which lets you edit the quote or expr in question
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
|
using NadekoBot.Db.Models;
|
||||||
|
|
||||||
namespace NadekoBot.Modules.NadekoExpressions;
|
namespace NadekoBot.Modules.NadekoExpressions;
|
||||||
|
|
||||||
[Name("Expressions")]
|
[Name("Expressions")]
|
||||||
@@ -34,12 +36,12 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
|
|
||||||
await Response()
|
await Response()
|
||||||
.Embed(_sender.CreateEmbed()
|
.Embed(_sender.CreateEmbed()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithTitle(GetText(strs.expr_new))
|
.WithTitle(GetText(strs.expr_new))
|
||||||
.WithDescription($"#{new kwum(ex.Id)}")
|
.WithDescription($"#{new kwum(ex.Id)}")
|
||||||
.AddField(GetText(strs.trigger), key)
|
.AddField(GetText(strs.trigger), key)
|
||||||
.AddField(GetText(strs.response),
|
.AddField(GetText(strs.response),
|
||||||
message.Length > 1024 ? GetText(strs.redacted_too_long) : message))
|
message.Length > 1024 ? GetText(strs.redacted_too_long) : message))
|
||||||
.SendAsync();
|
.SendAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,8 +95,7 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((channel is null && !_creds.IsOwner(ctx.User))
|
if (!IsValidExprEditor())
|
||||||
|| (channel is not null && !((IGuildUser)ctx.User).GuildPermissions.Administrator))
|
|
||||||
{
|
{
|
||||||
await Response().Error(strs.expr_insuff_perms).SendAsync();
|
await Response().Error(strs.expr_insuff_perms).SendAsync();
|
||||||
return;
|
return;
|
||||||
@@ -105,12 +106,12 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
{
|
{
|
||||||
await Response()
|
await Response()
|
||||||
.Embed(_sender.CreateEmbed()
|
.Embed(_sender.CreateEmbed()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithTitle(GetText(strs.expr_edited))
|
.WithTitle(GetText(strs.expr_edited))
|
||||||
.WithDescription($"#{id}")
|
.WithDescription($"#{id}")
|
||||||
.AddField(GetText(strs.trigger), ex.Trigger)
|
.AddField(GetText(strs.trigger), ex.Trigger)
|
||||||
.AddField(GetText(strs.response),
|
.AddField(GetText(strs.response),
|
||||||
message.Length > 1024 ? GetText(strs.redacted_too_long) : message))
|
message.Length > 1024 ? GetText(strs.redacted_too_long) : message))
|
||||||
.SendAsync();
|
.SendAsync();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -119,6 +120,10 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsValidExprEditor()
|
||||||
|
=> (ctx.Guild is not null && ((IGuildUser)ctx.User).GuildPermissions.Administrator)
|
||||||
|
|| (ctx.Guild is null && _creds.IsOwner(ctx.User));
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[Priority(1)]
|
[Priority(1)]
|
||||||
public async Task ExprList(int page = 1)
|
public async Task ExprList(int page = 1)
|
||||||
@@ -132,7 +137,7 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
.OrderBy(x => x.Trigger)
|
.OrderBy(x => x.Trigger)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
if (allExpressions is null || !allExpressions.Any())
|
if (!allExpressions.Any())
|
||||||
{
|
{
|
||||||
await Response().Error(strs.expr_no_found).SendAsync();
|
await Response().Error(strs.expr_no_found).SendAsync();
|
||||||
return;
|
return;
|
||||||
@@ -171,16 +176,48 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var inter = CreateEditInteraction(id, found);
|
||||||
|
|
||||||
await Response()
|
await Response()
|
||||||
|
.Interaction(IsValidExprEditor() ? inter : null)
|
||||||
.Embed(_sender.CreateEmbed()
|
.Embed(_sender.CreateEmbed()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithDescription($"#{id}")
|
.WithDescription($"#{id}")
|
||||||
.AddField(GetText(strs.trigger), found.Trigger.TrimTo(1024))
|
.AddField(GetText(strs.trigger), found.Trigger.TrimTo(1024))
|
||||||
.AddField(GetText(strs.response),
|
.AddField(GetText(strs.response),
|
||||||
found.Response.TrimTo(1000).Replace("](", "]\\(")))
|
found.Response.TrimTo(1000).Replace("](", "]\\(")))
|
||||||
.SendAsync();
|
.SendAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NadekoInteractionBase CreateEditInteraction(kwum id, NadekoExpression found)
|
||||||
|
{
|
||||||
|
var modal = new ModalBuilder()
|
||||||
|
.WithCustomId("expr:edit_modal")
|
||||||
|
.WithTitle($"Edit expression {id}")
|
||||||
|
.AddTextInput(new TextInputBuilder()
|
||||||
|
.WithLabel(GetText(strs.response))
|
||||||
|
.WithValue(found.Response)
|
||||||
|
.WithMinLength(1)
|
||||||
|
.WithCustomId("expr:edit_modal:response")
|
||||||
|
.WithStyle(TextInputStyle.Paragraph));
|
||||||
|
|
||||||
|
var inter = _inter.Create(ctx.User.Id,
|
||||||
|
new ButtonBuilder()
|
||||||
|
.WithEmote(Emoji.Parse("📝"))
|
||||||
|
.WithLabel("Edit")
|
||||||
|
.WithStyle(ButtonStyle.Primary)
|
||||||
|
.WithCustomId("test"),
|
||||||
|
modal,
|
||||||
|
async (sm) =>
|
||||||
|
{
|
||||||
|
var msg = sm.Data.Components.FirstOrDefault()?.Value;
|
||||||
|
|
||||||
|
await ExprEdit(id, msg);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return inter;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task ExprDeleteInternalAsync(kwum id)
|
public async Task ExprDeleteInternalAsync(kwum id)
|
||||||
{
|
{
|
||||||
var ex = await _service.DeleteAsync(ctx.Guild?.Id, id);
|
var ex = await _service.DeleteAsync(ctx.Guild?.Id, id);
|
||||||
@@ -189,11 +226,11 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
{
|
{
|
||||||
await Response()
|
await Response()
|
||||||
.Embed(_sender.CreateEmbed()
|
.Embed(_sender.CreateEmbed()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithTitle(GetText(strs.expr_deleted))
|
.WithTitle(GetText(strs.expr_deleted))
|
||||||
.WithDescription($"#{id}")
|
.WithDescription($"#{id}")
|
||||||
.AddField(GetText(strs.trigger), ex.Trigger.TrimTo(1024))
|
.AddField(GetText(strs.trigger), ex.Trigger.TrimTo(1024))
|
||||||
.AddField(GetText(strs.response), ex.Response.TrimTo(1024)))
|
.AddField(GetText(strs.response), ex.Response.TrimTo(1024)))
|
||||||
.SendAsync();
|
.SendAsync();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -340,8 +377,8 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
|||||||
public async Task ExprClear()
|
public async Task ExprClear()
|
||||||
{
|
{
|
||||||
if (await PromptUserConfirmAsync(_sender.CreateEmbed()
|
if (await PromptUserConfirmAsync(_sender.CreateEmbed()
|
||||||
.WithTitle("Expression clear")
|
.WithTitle("Expression clear")
|
||||||
.WithDescription("This will delete all expressions on this server.")))
|
.WithDescription("This will delete all expressions on this server.")))
|
||||||
{
|
{
|
||||||
var count = _service.DeleteAllExpressions(ctx.Guild.Id);
|
var count = _service.DeleteAllExpressions(ctx.Guild.Id);
|
||||||
await Response().Confirm(strs.exprs_cleared(count)).SendAsync();
|
await Response().Confirm(strs.exprs_cleared(count)).SendAsync();
|
||||||
|
@@ -154,7 +154,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
await smc.RespondConfirmAsync(_sender, GetText(strs.remind_timely(tt)), ephemeral: true);
|
await smc.RespondConfirmAsync(_sender, GetText(strs.remind_timely(tt)), ephemeral: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NadekoInteraction CreateRemindMeInteraction(int period)
|
private NadekoInteractionBase CreateRemindMeInteraction(int period)
|
||||||
=> _inter
|
=> _inter
|
||||||
.Create(ctx.User.Id,
|
.Create(ctx.User.Id,
|
||||||
new ButtonBuilder(
|
new ButtonBuilder(
|
||||||
@@ -415,7 +415,7 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||||||
.Pipe(text => smc.RespondConfirmAsync(_sender, text, ephemeral: true));
|
.Pipe(text => smc.RespondConfirmAsync(_sender, text, ephemeral: true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private NadekoInteraction CreateCashInteraction()
|
private NadekoInteractionBase CreateCashInteraction()
|
||||||
=> _inter.Create(ctx.User.Id,
|
=> _inter.Create(ctx.User.Id,
|
||||||
new ButtonBuilder(
|
new ButtonBuilder(
|
||||||
customId: "cash:bank_show_balance",
|
customId: "cash:bank_show_balance",
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
#nullable disable warnings
|
#nullable disable warnings
|
||||||
|
using LinqToDB;
|
||||||
|
using LinqToDB.EntityFrameworkCore;
|
||||||
using NadekoBot.Common.Yml;
|
using NadekoBot.Common.Yml;
|
||||||
using NadekoBot.Db;
|
using NadekoBot.Db;
|
||||||
using NadekoBot.Db.Models;
|
using NadekoBot.Db.Models;
|
||||||
@@ -133,23 +135,54 @@ public partial class Utility
|
|||||||
await ShowQuoteData(quote);
|
await ShowQuoteData(quote);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ShowQuoteData(Quote data)
|
private NadekoInteractionBase CreateEditInteraction(kwum id, Quote found)
|
||||||
{
|
{
|
||||||
|
var modal = new ModalBuilder()
|
||||||
|
.WithCustomId("quote:edit_modal")
|
||||||
|
.WithTitle($"Edit expression {id}")
|
||||||
|
.AddTextInput(new TextInputBuilder()
|
||||||
|
.WithLabel(GetText(strs.response))
|
||||||
|
.WithValue(found.Text)
|
||||||
|
.WithMinLength(1)
|
||||||
|
.WithCustomId("quote:edit_modal:response")
|
||||||
|
.WithStyle(TextInputStyle.Paragraph));
|
||||||
|
|
||||||
|
var inter = _inter.Create(ctx.User.Id,
|
||||||
|
new ButtonBuilder()
|
||||||
|
.WithEmote(Emoji.Parse("📝"))
|
||||||
|
.WithLabel("Edit")
|
||||||
|
.WithStyle(ButtonStyle.Primary)
|
||||||
|
.WithCustomId("test"),
|
||||||
|
modal,
|
||||||
|
async (sm) =>
|
||||||
|
{
|
||||||
|
var msg = sm.Data.Components.FirstOrDefault()?.Value;
|
||||||
|
|
||||||
|
if(!string.IsNullOrWhiteSpace(msg))
|
||||||
|
await QuoteEdit(id, msg);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return inter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ShowQuoteData(Quote quote)
|
||||||
|
{
|
||||||
|
var inter = CreateEditInteraction(quote.Id, quote);
|
||||||
var eb = _sender.CreateEmbed()
|
var eb = _sender.CreateEmbed()
|
||||||
.WithOkColor()
|
.WithOkColor()
|
||||||
.WithTitle($"{GetText(strs.quote_id($"`{new kwum(data.Id)}"))}`")
|
.WithTitle($"{GetText(strs.quote_id($"`{new kwum(quote.Id)}"))}`")
|
||||||
.WithDescription(Format.Sanitize(data.Text).Replace("](", "]\\(").TrimTo(4096))
|
.WithDescription(Format.Sanitize(quote.Text).Replace("](", "]\\(").TrimTo(4096))
|
||||||
.AddField(GetText(strs.trigger), data.Keyword)
|
.AddField(GetText(strs.trigger), quote.Keyword)
|
||||||
.WithFooter(
|
.WithFooter(
|
||||||
GetText(strs.created_by($"{data.AuthorName} ({data.AuthorId})")));
|
GetText(strs.created_by($"{quote.AuthorName} ({quote.AuthorId})")));
|
||||||
|
|
||||||
if (!(data.Text.Length > 4096))
|
if (!(quote.Text.Length > 4096))
|
||||||
{
|
{
|
||||||
await Response().Embed(eb).SendAsync();
|
await Response().Embed(eb).Interaction(quote.AuthorId == ctx.User.Id ? inter : null).SendAsync();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await using var textStream = await data.Text.ToStream();
|
await using var textStream = await quote.Text.ToStream();
|
||||||
|
|
||||||
await Response()
|
await Response()
|
||||||
.Embed(eb)
|
.Embed(eb)
|
||||||
@@ -255,6 +288,47 @@ public partial class Utility
|
|||||||
await Response().Confirm(strs.quote_added_new(Format.Code(new kwum(q.Id).ToString()))).SendAsync();
|
await Response().Confirm(strs.quote_added_new(Format.Code(new kwum(q.Id).ToString()))).SendAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Cmd]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task QuoteEdit(kwum quoteId, [Leftover] string text)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quote q;
|
||||||
|
await using (var uow = _db.GetDbContext())
|
||||||
|
{
|
||||||
|
var intId = (int)quoteId;
|
||||||
|
var result = await uow.GetTable<Quote>()
|
||||||
|
.Where(x => x.Id == intId && x.AuthorId == ctx.User.Id)
|
||||||
|
.Set(x => x.Text, text)
|
||||||
|
.UpdateWithOutputAsync((del, ins) => ins);
|
||||||
|
|
||||||
|
q = result.FirstOrDefault();
|
||||||
|
|
||||||
|
await uow.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (q is not null)
|
||||||
|
{
|
||||||
|
await Response()
|
||||||
|
.Embed(_sender.CreateEmbed()
|
||||||
|
.WithOkColor()
|
||||||
|
.WithTitle(GetText(strs.quote_edited))
|
||||||
|
.WithDescription($"#{quoteId}")
|
||||||
|
.AddField(GetText(strs.trigger), q.Keyword)
|
||||||
|
.AddField(GetText(strs.response),
|
||||||
|
text.Length > 1024 ? GetText(strs.redacted_too_long) : text))
|
||||||
|
.SendAsync();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Response().Error(strs.expr_no_found_id).SendAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Cmd]
|
[Cmd]
|
||||||
[RequireContext(ContextType.Guild)]
|
[RequireContext(ContextType.Guild)]
|
||||||
public async Task QuoteDelete(kwum quoteId)
|
public async Task QuoteDelete(kwum quoteId)
|
||||||
|
@@ -506,7 +506,7 @@ public partial class Xp : NadekoModule<XpService>
|
|||||||
{
|
{
|
||||||
var result = await _service.BuyShopItemAsync(ctx.User.Id, (XpShopItemType)type, key);
|
var result = await _service.BuyShopItemAsync(ctx.User.Id, (XpShopItemType)type, key);
|
||||||
|
|
||||||
NadekoInteraction GetUseInteraction()
|
NadekoInteractionBase GetUseInteraction()
|
||||||
{
|
{
|
||||||
return _inter.Create(ctx.User.Id,
|
return _inter.Create(ctx.User.Id,
|
||||||
new(label: "Use", customId: "xpshop:use_item", emote: Emoji.Parse("👐")),
|
new(label: "Use", customId: "xpshop:use_item", emote: Emoji.Parse("👐")),
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
@@ -31,9 +30,9 @@
|
|||||||
<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.204.0"/>
|
<PackageReference Include="Discord.Net" Version="3.204.0"/>
|
||||||
<PackageReference Include="CoreCLR-NCalc" Version="3.1.246" />
|
<PackageReference Include="CoreCLR-NCalc" Version="3.1.246"/>
|
||||||
<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.68.0.3414" />
|
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.68.0.3414"/>
|
||||||
<PackageReference Include="Google.Apis.Customsearch.v1" Version="1.49.0.2084"/>
|
<PackageReference Include="Google.Apis.Customsearch.v1" Version="1.49.0.2084"/>
|
||||||
<!-- <PackageReference Include="Grpc.AspNetCore" Version="2.62.0" />-->
|
<!-- <PackageReference Include="Grpc.AspNetCore" Version="2.62.0" />-->
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.26.1"/>
|
<PackageReference Include="Google.Protobuf" Version="3.26.1"/>
|
||||||
@@ -52,11 +51,11 @@
|
|||||||
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="3.1.0"/>
|
<PackageReference Include="NetEscapades.Configuration.Yaml" Version="3.1.0"/>
|
||||||
|
|
||||||
<!-- DI -->
|
<!-- DI -->
|
||||||
<!-- <PackageReference Include="Ninject" Version="3.3.6"/>-->
|
<!-- <PackageReference Include="Ninject" Version="3.3.6"/>-->
|
||||||
<!-- <PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0"/>-->
|
<!-- <PackageReference Include="Ninject.Extensions.Conventions" Version="3.3.0"/>-->
|
||||||
<!-- <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />-->
|
<!-- <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />-->
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1"/>
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1"/>
|
||||||
<PackageReference Include="DryIoc.dll" Version="5.4.3" />
|
<PackageReference Include="DryIoc.dll" Version="5.4.3"/>
|
||||||
<!-- <PackageReference Include="Scrutor" Version="4.2.0" />-->
|
<!-- <PackageReference Include="Scrutor" Version="4.2.0" />-->
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0"/>
|
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0"/>
|
||||||
@@ -68,14 +67,14 @@
|
|||||||
<PackageReference Include="OneOf" Version="3.0.263"/>
|
<PackageReference Include="OneOf" Version="3.0.263"/>
|
||||||
<PackageReference Include="OneOf.SourceGenerator" Version="3.0.263"/>
|
<PackageReference Include="OneOf.SourceGenerator" Version="3.0.263"/>
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1"/>
|
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1"/>
|
||||||
<PackageReference Include="Serilog.Sinks.Seq" Version="7.0.1" />
|
<PackageReference Include="Serilog.Sinks.Seq" Version="7.0.1"/>
|
||||||
|
|
||||||
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta17"/>
|
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta17"/>
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.8"/>
|
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.8"/>
|
||||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14"/>
|
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14"/>
|
||||||
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0009"/>
|
<PackageReference Include="SixLabors.Shapes" Version="1.0.0-beta0009"/>
|
||||||
<PackageReference Include="StackExchange.Redis" Version="2.7.33"/>
|
<PackageReference Include="StackExchange.Redis" Version="2.7.33"/>
|
||||||
<PackageReference Include="YamlDotNet" Version="15.1.4" />
|
<PackageReference Include="YamlDotNet" Version="15.1.4"/>
|
||||||
<PackageReference Include="SharpToken" Version="2.0.2"/>
|
<PackageReference Include="SharpToken" Version="2.0.2"/>
|
||||||
|
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0"/>
|
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0"/>
|
||||||
@@ -100,7 +99,7 @@
|
|||||||
<PackageReference Include="TwitchLib.Api" Version="3.4.1"/>
|
<PackageReference Include="TwitchLib.Api" Version="3.4.1"/>
|
||||||
|
|
||||||
<!-- sqlselectcsv and stock -->
|
<!-- sqlselectcsv and stock -->
|
||||||
<PackageReference Include="CsvHelper" Version="32.0.3" />
|
<PackageReference Include="CsvHelper" Version="32.0.3"/>
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
@@ -109,6 +108,8 @@
|
|||||||
<ProjectReference Include="..\NadekoBot.Voice\NadekoBot.Voice.csproj"/>
|
<ProjectReference Include="..\NadekoBot.Voice\NadekoBot.Voice.csproj"/>
|
||||||
<ProjectReference Include="..\NadekoBot.Generators\NadekoBot.Generators.csproj" OutputItemType="Analyzer"/>
|
<ProjectReference Include="..\NadekoBot.Generators\NadekoBot.Generators.csproj" OutputItemType="Analyzer"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<AdditionalFiles Include="data\strings\responses\responses.en-US.json"/>
|
<AdditionalFiles Include="data\strings\responses\responses.en-US.json"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@@ -131,10 +132,6 @@
|
|||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Modules\Utility\GuildColors\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'GlobalNadeko' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'GlobalNadeko' ">
|
||||||
<!-- Define trace doesn't seem to affect the build at all so I had to remove $(DefineConstants)-->
|
<!-- Define trace doesn't seem to affect the build at all so I had to remove $(DefineConstants)-->
|
||||||
<DefineTrace>false</DefineTrace>
|
<DefineTrace>false</DefineTrace>
|
||||||
|
@@ -2,22 +2,30 @@
|
|||||||
|
|
||||||
public interface INadekoInteractionService
|
public interface INadekoInteractionService
|
||||||
{
|
{
|
||||||
public NadekoInteraction Create(
|
public NadekoInteractionBase Create(
|
||||||
ulong userId,
|
ulong userId,
|
||||||
ButtonBuilder button,
|
ButtonBuilder button,
|
||||||
Func<SocketMessageComponent, Task> onTrigger,
|
Func<SocketMessageComponent, Task> onTrigger,
|
||||||
bool singleUse = true);
|
bool singleUse = true);
|
||||||
|
|
||||||
public NadekoInteraction Create<T>(
|
public NadekoInteractionBase Create<T>(
|
||||||
ulong userId,
|
ulong userId,
|
||||||
ButtonBuilder button,
|
ButtonBuilder button,
|
||||||
Func<SocketMessageComponent, T, Task> onTrigger,
|
Func<SocketMessageComponent, T, Task> onTrigger,
|
||||||
in T state,
|
in T state,
|
||||||
bool singleUse = true);
|
bool singleUse = true);
|
||||||
|
|
||||||
NadekoInteraction Create(
|
NadekoInteractionBase Create(
|
||||||
ulong userId,
|
ulong userId,
|
||||||
SelectMenuBuilder menu,
|
SelectMenuBuilder menu,
|
||||||
Func<SocketMessageComponent, Task> onTrigger,
|
Func<SocketMessageComponent, Task> onTrigger,
|
||||||
bool singleUse = true);
|
bool singleUse = true);
|
||||||
|
|
||||||
|
NadekoInteractionBase Create(
|
||||||
|
ulong userId,
|
||||||
|
ButtonBuilder button,
|
||||||
|
ModalBuilder modal,
|
||||||
|
Func<SocketModal, Task> onTrigger,
|
||||||
|
bool singleUse = true);
|
||||||
|
|
||||||
}
|
}
|
@@ -1,8 +1,8 @@
|
|||||||
namespace NadekoBot;
|
namespace NadekoBot;
|
||||||
|
|
||||||
public sealed class NadekoButtonInteraction : NadekoInteraction
|
public sealed class NadekoButtonInteractionHandler : NadekoInteractionBase
|
||||||
{
|
{
|
||||||
public NadekoButtonInteraction(
|
public NadekoButtonInteractionHandler(
|
||||||
DiscordSocketClient client,
|
DiscordSocketClient client,
|
||||||
ulong authorId,
|
ulong authorId,
|
||||||
ButtonBuilder button,
|
ButtonBuilder button,
|
||||||
|
@@ -3,12 +3,12 @@
|
|||||||
public static class NadekoInteractionExtensions
|
public static class NadekoInteractionExtensions
|
||||||
{
|
{
|
||||||
public static MessageComponent CreateComponent(
|
public static MessageComponent CreateComponent(
|
||||||
this NadekoInteraction nadekoInteraction
|
this NadekoInteractionBase nadekoInteractionBase
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var cb = new ComponentBuilder();
|
var cb = new ComponentBuilder();
|
||||||
|
|
||||||
nadekoInteraction.AddTo(cb);
|
nadekoInteractionBase.AddTo(cb);
|
||||||
|
|
||||||
return cb.Build();
|
return cb.Build();
|
||||||
}
|
}
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
namespace NadekoBot;
|
namespace NadekoBot;
|
||||||
|
|
||||||
public sealed class NadekoSelectInteraction : NadekoInteraction
|
public sealed class NadekoButtonSelectInteractionHandler : NadekoInteractionBase
|
||||||
{
|
{
|
||||||
public NadekoSelectInteraction(
|
public NadekoButtonSelectInteractionHandler(
|
||||||
DiscordSocketClient client,
|
DiscordSocketClient client,
|
||||||
ulong authorId,
|
ulong authorId,
|
||||||
SelectMenuBuilder menu,
|
SelectMenuBuilder menu,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
namespace NadekoBot;
|
namespace NadekoBot;
|
||||||
|
|
||||||
public abstract class NadekoInteraction
|
public abstract class NadekoInteractionBase
|
||||||
{
|
{
|
||||||
private readonly ulong _authorId;
|
private readonly ulong _authorId;
|
||||||
private readonly Func<SocketMessageComponent, Task> _onAction;
|
private readonly Func<SocketMessageComponent, Task> _onAction;
|
||||||
@@ -13,7 +13,7 @@ public abstract class NadekoInteraction
|
|||||||
private readonly string _customId;
|
private readonly string _customId;
|
||||||
private readonly bool _singleUse;
|
private readonly bool _singleUse;
|
||||||
|
|
||||||
public NadekoInteraction(
|
public NadekoInteractionBase(
|
||||||
DiscordSocketClient client,
|
DiscordSocketClient client,
|
||||||
ulong authorId,
|
ulong authorId,
|
||||||
string customId,
|
string customId,
|
||||||
@@ -85,4 +85,80 @@ public abstract class NadekoInteraction
|
|||||||
|
|
||||||
public Task ExecuteOnActionAsync(SocketMessageComponent smc)
|
public Task ExecuteOnActionAsync(SocketMessageComponent smc)
|
||||||
=> _onAction(smc);
|
=> _onAction(smc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class NadekoModalSubmitHandler
|
||||||
|
{
|
||||||
|
private readonly ulong _authorId;
|
||||||
|
private readonly Func<SocketModal, Task> _onAction;
|
||||||
|
private readonly bool _onlyAuthor;
|
||||||
|
public DiscordSocketClient Client { get; }
|
||||||
|
|
||||||
|
private readonly TaskCompletionSource<bool> _interactionCompletedSource;
|
||||||
|
|
||||||
|
private IUserMessage message = null!;
|
||||||
|
private readonly string _customId;
|
||||||
|
|
||||||
|
public NadekoModalSubmitHandler(
|
||||||
|
DiscordSocketClient client,
|
||||||
|
ulong authorId,
|
||||||
|
string customId,
|
||||||
|
Func<SocketModal, Task> onAction,
|
||||||
|
bool onlyAuthor)
|
||||||
|
{
|
||||||
|
_authorId = authorId;
|
||||||
|
_customId = customId;
|
||||||
|
_onAction = onAction;
|
||||||
|
_onlyAuthor = onlyAuthor;
|
||||||
|
_interactionCompletedSource = new(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||||
|
|
||||||
|
Client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RunAsync(IUserMessage msg)
|
||||||
|
{
|
||||||
|
message = msg;
|
||||||
|
|
||||||
|
Client.ModalSubmitted += OnInteraction;
|
||||||
|
await Task.WhenAny(Task.Delay(300_000), _interactionCompletedSource.Task);
|
||||||
|
Client.ModalSubmitted -= OnInteraction;
|
||||||
|
|
||||||
|
await msg.ModifyAsync(m => m.Components = new ComponentBuilder().Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task OnInteraction(SocketModal sm)
|
||||||
|
{
|
||||||
|
if (sm.Message.Id != message.Id)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
if (_onlyAuthor && sm.User.Id != _authorId)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
if (sm.Data.CustomId != _customId)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
_ = Task.Run(async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_interactionCompletedSource.TrySetResult(true);
|
||||||
|
await ExecuteOnActionAsync(sm);
|
||||||
|
|
||||||
|
if (!sm.HasResponded)
|
||||||
|
{
|
||||||
|
await sm.DeferAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warning(ex, "An exception occured while handling a: {Message}", ex.Message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Task ExecuteOnActionAsync(SocketModal smd)
|
||||||
|
=> _onAction(smd);
|
||||||
}
|
}
|
@@ -9,19 +9,19 @@ public class NadekoInteractionService : INadekoInteractionService, INService
|
|||||||
_client = client;
|
_client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NadekoInteraction Create(
|
public NadekoInteractionBase Create(
|
||||||
ulong userId,
|
ulong userId,
|
||||||
ButtonBuilder button,
|
ButtonBuilder button,
|
||||||
Func<SocketMessageComponent, Task> onTrigger,
|
Func<SocketMessageComponent, Task> onTrigger,
|
||||||
bool singleUse = true)
|
bool singleUse = true)
|
||||||
=> new NadekoButtonInteraction(_client,
|
=> new NadekoButtonInteractionHandler(_client,
|
||||||
userId,
|
userId,
|
||||||
button,
|
button,
|
||||||
onTrigger,
|
onTrigger,
|
||||||
onlyAuthor: true,
|
onlyAuthor: true,
|
||||||
singleUse: singleUse);
|
singleUse: singleUse);
|
||||||
|
|
||||||
public NadekoInteraction Create<T>(
|
public NadekoInteractionBase Create<T>(
|
||||||
ulong userId,
|
ulong userId,
|
||||||
ButtonBuilder button,
|
ButtonBuilder button,
|
||||||
Func<SocketMessageComponent, T, Task> onTrigger,
|
Func<SocketMessageComponent, T, Task> onTrigger,
|
||||||
@@ -32,16 +32,46 @@ public class NadekoInteractionService : INadekoInteractionService, INService
|
|||||||
((Func<T, Func<SocketMessageComponent, Task>>)((data)
|
((Func<T, Func<SocketMessageComponent, Task>>)((data)
|
||||||
=> smc => onTrigger(smc, data)))(state),
|
=> smc => onTrigger(smc, data)))(state),
|
||||||
singleUse);
|
singleUse);
|
||||||
|
|
||||||
public NadekoInteraction Create(
|
public NadekoInteractionBase Create(
|
||||||
ulong userId,
|
ulong userId,
|
||||||
SelectMenuBuilder menu,
|
SelectMenuBuilder menu,
|
||||||
Func<SocketMessageComponent, Task> onTrigger,
|
Func<SocketMessageComponent, Task> onTrigger,
|
||||||
bool singleUse = true)
|
bool singleUse = true)
|
||||||
=> new NadekoSelectInteraction(_client,
|
=> new NadekoButtonSelectInteractionHandler(_client,
|
||||||
userId,
|
userId,
|
||||||
menu,
|
menu,
|
||||||
onTrigger,
|
onTrigger,
|
||||||
onlyAuthor: true,
|
onlyAuthor: true,
|
||||||
singleUse: singleUse);
|
singleUse: singleUse);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create an interaction which opens a modal
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">Id of the author</param>
|
||||||
|
/// <param name="button">Button builder for the button that will open the modal</param>
|
||||||
|
/// <param name="modal">Modal</param>
|
||||||
|
/// <param name="onTrigger">The function that will be called when the modal is submitted</param>
|
||||||
|
/// <param name="singleUse">Whether the button is single use</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public NadekoInteractionBase Create(
|
||||||
|
ulong userId,
|
||||||
|
ButtonBuilder button,
|
||||||
|
ModalBuilder modal,
|
||||||
|
Func<SocketModal, Task> onTrigger,
|
||||||
|
bool singleUse = true)
|
||||||
|
=> Create(userId,
|
||||||
|
button,
|
||||||
|
async (smc) =>
|
||||||
|
{
|
||||||
|
await smc.RespondWithModalAsync(modal.Build());
|
||||||
|
var modalHandler = new NadekoModalSubmitHandler(_client,
|
||||||
|
userId,
|
||||||
|
modal.CustomId,
|
||||||
|
onTrigger,
|
||||||
|
true);
|
||||||
|
await modalHandler.RunAsync(smc.Message);
|
||||||
|
},
|
||||||
|
singleUse: singleUse);
|
||||||
}
|
}
|
@@ -34,11 +34,11 @@ public partial class ResponseBuilder
|
|||||||
if (_paginationBuilder.AddPaginatedFooter)
|
if (_paginationBuilder.AddPaginatedFooter)
|
||||||
embed.AddPaginatedFooter(currentPage, lastPage);
|
embed.AddPaginatedFooter(currentPage, lastPage);
|
||||||
|
|
||||||
NadekoInteraction? maybeInter = null;
|
NadekoInteractionBase? maybeInter = null;
|
||||||
|
|
||||||
var model = await _builder.BuildAsync(ephemeral);
|
var model = await _builder.BuildAsync(ephemeral);
|
||||||
|
|
||||||
async Task<(NadekoButtonInteraction left, NadekoInteraction? extra, NadekoButtonInteraction right)>
|
async Task<(NadekoButtonInteractionHandler left, NadekoInteractionBase? extra, NadekoButtonInteractionHandler right)>
|
||||||
GetInteractions()
|
GetInteractions()
|
||||||
{
|
{
|
||||||
var leftButton = new ButtonBuilder()
|
var leftButton = new ButtonBuilder()
|
||||||
@@ -47,7 +47,7 @@ public partial class ResponseBuilder
|
|||||||
.WithEmote(InteractionHelpers.ArrowLeft)
|
.WithEmote(InteractionHelpers.ArrowLeft)
|
||||||
.WithDisabled(lastPage == 0 || currentPage <= 0);
|
.WithDisabled(lastPage == 0 || currentPage <= 0);
|
||||||
|
|
||||||
var leftBtnInter = new NadekoButtonInteraction(_client,
|
var leftBtnInter = new NadekoButtonInteractionHandler(_client,
|
||||||
model.User?.Id ?? 0,
|
model.User?.Id ?? 0,
|
||||||
leftButton,
|
leftButton,
|
||||||
(smc) =>
|
(smc) =>
|
||||||
@@ -80,7 +80,7 @@ public partial class ResponseBuilder
|
|||||||
.WithEmote(InteractionHelpers.ArrowRight)
|
.WithEmote(InteractionHelpers.ArrowRight)
|
||||||
.WithDisabled(lastPage == 0 || currentPage >= lastPage);
|
.WithDisabled(lastPage == 0 || currentPage >= lastPage);
|
||||||
|
|
||||||
var rightBtnInter = new NadekoButtonInteraction(_client,
|
var rightBtnInter = new NadekoButtonInteractionHandler(_client,
|
||||||
model.User?.Id ?? 0,
|
model.User?.Id ?? 0,
|
||||||
rightButton,
|
rightButton,
|
||||||
(smc) =>
|
(smc) =>
|
||||||
|
@@ -19,7 +19,7 @@ public sealed partial class ResponseBuilder
|
|||||||
private readonly IBotStrings _bs;
|
private readonly IBotStrings _bs;
|
||||||
private readonly BotConfigService _bcs;
|
private readonly BotConfigService _bcs;
|
||||||
private EmbedBuilder? embedBuilder;
|
private EmbedBuilder? embedBuilder;
|
||||||
private NadekoInteraction? inter;
|
private NadekoInteractionBase? inter;
|
||||||
private Stream? fileStream;
|
private Stream? fileStream;
|
||||||
private string? fileName;
|
private string? fileName;
|
||||||
private EmbedColor color = EmbedColor.Ok;
|
private EmbedColor color = EmbedColor.Ok;
|
||||||
@@ -340,7 +340,7 @@ public sealed partial class ResponseBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResponseBuilder Interaction(NadekoInteraction? interaction)
|
public ResponseBuilder Interaction(NadekoInteractionBase? interaction)
|
||||||
{
|
{
|
||||||
inter = interaction;
|
inter = interaction;
|
||||||
return this;
|
return this;
|
||||||
@@ -395,7 +395,7 @@ public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilde
|
|||||||
return Task.FromResult<IReadOnlyCollection<T>>(ReadOnlyCollection<T>.Empty);
|
return Task.FromResult<IReadOnlyCollection<T>>(ReadOnlyCollection<T>.Empty);
|
||||||
};
|
};
|
||||||
|
|
||||||
public Func<int, Task<NadekoInteraction>>? InteractionFunc { get; private set; }
|
public Func<int, Task<NadekoInteractionBase>>? InteractionFunc { get; private set; }
|
||||||
|
|
||||||
public int? Elems { get; private set; } = 1;
|
public int? Elems { get; private set; } = 1;
|
||||||
public int ItemsPerPage { get; private set; } = 9;
|
public int ItemsPerPage { get; private set; } = 9;
|
||||||
@@ -478,13 +478,13 @@ public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilde
|
|||||||
return paginationSender.SendAsync(IsEphemeral);
|
return paginationSender.SendAsync(IsEphemeral);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourcedPaginatedResponseBuilder<T> Interaction(Func<int, Task<NadekoInteraction>> func)
|
public SourcedPaginatedResponseBuilder<T> Interaction(Func<int, Task<NadekoInteractionBase>> func)
|
||||||
{
|
{
|
||||||
InteractionFunc = func; //async (i) => await func(i);
|
InteractionFunc = func; //async (i) => await func(i);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourcedPaginatedResponseBuilder<T> Interaction(NadekoInteraction inter)
|
public SourcedPaginatedResponseBuilder<T> Interaction(NadekoInteractionBase inter)
|
||||||
{
|
{
|
||||||
InteractionFunc = _ => Task.FromResult(inter);
|
InteractionFunc = _ => Task.FromResult(inter);
|
||||||
return this;
|
return this;
|
||||||
|
@@ -8,5 +8,5 @@
|
|||||||
public required AllowedMentions SanitizeMentions { get; set; }
|
public required AllowedMentions SanitizeMentions { get; set; }
|
||||||
public IUser? User { get; set; }
|
public IUser? User { get; set; }
|
||||||
public bool Ephemeral { get; set; }
|
public bool Ephemeral { get; set; }
|
||||||
public NadekoInteraction? Interaction { get; set; }
|
public NadekoInteractionBase? Interaction { get; set; }
|
||||||
}
|
}
|
@@ -341,6 +341,9 @@ allcmdcooldowns:
|
|||||||
quoteadd:
|
quoteadd:
|
||||||
- quoteadd
|
- quoteadd
|
||||||
- .
|
- .
|
||||||
|
quoteedit:
|
||||||
|
- quoteedit
|
||||||
|
- qedit
|
||||||
quoteprint:
|
quoteprint:
|
||||||
- quoteprint
|
- quoteprint
|
||||||
- ..
|
- ..
|
||||||
|
@@ -1245,6 +1245,15 @@ quoteadd:
|
|||||||
desc: "The name of the quote used to retrieve the quote."
|
desc: "The name of the quote used to retrieve the quote."
|
||||||
text:
|
text:
|
||||||
desc: "The message of the quote."
|
desc: "The message of the quote."
|
||||||
|
quoteedit:
|
||||||
|
desc: Edits a quote with the specified ID.
|
||||||
|
ex:
|
||||||
|
- 55 This is the new response.
|
||||||
|
params:
|
||||||
|
- quoteId:
|
||||||
|
desc: "The ID of the quote being edited."
|
||||||
|
text:
|
||||||
|
desc: "The new message of the quote."
|
||||||
quoteprint:
|
quoteprint:
|
||||||
desc: Prints a random quote with a specified name.
|
desc: Prints a random quote with a specified name.
|
||||||
ex:
|
ex:
|
||||||
|
@@ -617,6 +617,7 @@
|
|||||||
"quotes_remove_none": "No quotes found which you can remove.",
|
"quotes_remove_none": "No quotes found which you can remove.",
|
||||||
"quote_added_new": "Quote #{0} added.",
|
"quote_added_new": "Quote #{0} added.",
|
||||||
"quote_deleted": "Quote #{0} deleted.",
|
"quote_deleted": "Quote #{0} deleted.",
|
||||||
|
"quote_edited": "Quote Edited",
|
||||||
"region": "Region",
|
"region": "Region",
|
||||||
"remind": "I will remind {0} to {1} in {2} `({3:d.M.yyyy.} at {4:HH:mm})`",
|
"remind": "I will remind {0} to {1} in {2} `({3:d.M.yyyy.} at {4:HH:mm})`",
|
||||||
"remind_timely": "I will remind you about your timely reward {0}",
|
"remind_timely": "I will remind you about your timely reward {0}",
|
||||||
|
Reference in New Issue
Block a user