mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 09:18:27 -04:00
Started rewriting all paginted responses into the new system
This commit is contained in:
@@ -32,13 +32,15 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
|
||||
var ex = await _service.AddAsync(ctx.Guild?.Id, key, message);
|
||||
|
||||
await Response().Embed(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.expr_new))
|
||||
.WithDescription($"#{new kwum(ex.Id)}")
|
||||
.AddField(GetText(strs.trigger), key)
|
||||
.AddField(GetText(strs.response),
|
||||
message.Length > 1024 ? GetText(strs.redacted_too_long) : message)).SendAsync();
|
||||
await Response()
|
||||
.Embed(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.expr_new))
|
||||
.WithDescription($"#{new kwum(ex.Id)}")
|
||||
.AddField(GetText(strs.trigger), key)
|
||||
.AddField(GetText(strs.response),
|
||||
message.Length > 1024 ? GetText(strs.redacted_too_long) : message))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -101,12 +103,12 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
if (ex is not null)
|
||||
{
|
||||
await ctx.Channel.EmbedAsync(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.expr_edited))
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), ex.Trigger)
|
||||
.AddField(GetText(strs.response),
|
||||
message.Length > 1024 ? GetText(strs.redacted_too_long) : message));
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.expr_edited))
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), ex.Trigger)
|
||||
.AddField(GetText(strs.response),
|
||||
message.Length > 1024 ? GetText(strs.redacted_too_long) : message));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -123,33 +125,36 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
return;
|
||||
}
|
||||
|
||||
var expressions = _service.GetExpressionsFor(ctx.Guild?.Id);
|
||||
var allExpressions = _service.GetExpressionsFor(ctx.Guild?.Id)
|
||||
.OrderBy(x => x.Trigger)
|
||||
.ToArray();
|
||||
|
||||
if (expressions is null || !expressions.Any())
|
||||
if (allExpressions is null || !allExpressions.Any())
|
||||
{
|
||||
await Response().Error(strs.expr_no_found).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage =>
|
||||
{
|
||||
var desc = expressions.OrderBy(ex => ex.Trigger)
|
||||
.Skip(curPage * 20)
|
||||
.Take(20)
|
||||
.Select(ex => $"{(ex.ContainsAnywhere ? "🗯" : "◾")}"
|
||||
+ $"{(ex.DmResponse ? "✉" : "◾")}"
|
||||
+ $"{(ex.AutoDeleteTrigger ? "❌" : "◾")}"
|
||||
+ $"`{(kwum)ex.Id}` {ex.Trigger}"
|
||||
+ (string.IsNullOrWhiteSpace(ex.Reactions)
|
||||
? string.Empty
|
||||
: " // " + string.Join(" ", ex.GetReactions())))
|
||||
.Join('\n');
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(allExpressions)
|
||||
.PageSize(20)
|
||||
.CurrentPage(page)
|
||||
.Page((exprs, _) =>
|
||||
{
|
||||
var desc = exprs
|
||||
.Select(ex => $"{(ex.ContainsAnywhere ? "🗯" : "◾")}"
|
||||
+ $"{(ex.DmResponse ? "✉" : "◾")}"
|
||||
+ $"{(ex.AutoDeleteTrigger ? "❌" : "◾")}"
|
||||
+ $"`{(kwum)ex.Id}` {ex.Trigger}"
|
||||
+ (string.IsNullOrWhiteSpace(ex.Reactions)
|
||||
? string.Empty
|
||||
: " // " + string.Join(" ", ex.GetReactions())))
|
||||
.Join('\n');
|
||||
|
||||
return new EmbedBuilder().WithOkColor().WithTitle(GetText(strs.expressions)).WithDescription(desc);
|
||||
},
|
||||
expressions.Length,
|
||||
20);
|
||||
return new EmbedBuilder().WithOkColor().WithTitle(GetText(strs.expressions)).WithDescription(desc);
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -164,11 +169,11 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
}
|
||||
|
||||
await ctx.Channel.EmbedAsync(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), found.Trigger.TrimTo(1024))
|
||||
.AddField(GetText(strs.response),
|
||||
found.Response.TrimTo(1000).Replace("](", "]\\(")));
|
||||
.WithOkColor()
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), found.Trigger.TrimTo(1024))
|
||||
.AddField(GetText(strs.response),
|
||||
found.Response.TrimTo(1000).Replace("](", "]\\(")));
|
||||
}
|
||||
|
||||
public async Task ExprDeleteInternalAsync(kwum id)
|
||||
@@ -178,11 +183,11 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
if (ex is not null)
|
||||
{
|
||||
await ctx.Channel.EmbedAsync(new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.expr_deleted))
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), ex.Trigger.TrimTo(1024))
|
||||
.AddField(GetText(strs.response), ex.Response.TrimTo(1024)));
|
||||
.WithOkColor()
|
||||
.WithTitle(GetText(strs.expr_deleted))
|
||||
.WithDescription($"#{id}")
|
||||
.AddField(GetText(strs.trigger), ex.Trigger.TrimTo(1024))
|
||||
.AddField(GetText(strs.response), ex.Response.TrimTo(1024)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -328,8 +333,8 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
public async Task ExprClear()
|
||||
{
|
||||
if (await PromptUserConfirmAsync(new EmbedBuilder()
|
||||
.WithTitle("Expression clear")
|
||||
.WithDescription("This will delete all expressions on this server.")))
|
||||
.WithTitle("Expression clear")
|
||||
.WithDescription("This will delete all expressions on this server.")))
|
||||
{
|
||||
var count = _service.DeleteAllExpressions(ctx.Guild.Id);
|
||||
await Response().Confirm(strs.exprs_cleared(count)).SendAsync();
|
||||
|
@@ -20,7 +20,7 @@ public partial class Permissions
|
||||
throw new ArgumentOutOfRangeException(nameof(page));
|
||||
|
||||
var list = _service.GetBlacklist();
|
||||
var items = await list.Where(x => x.Type == type)
|
||||
var allItems = await list.Where(x => x.Type == type)
|
||||
.Select(async i =>
|
||||
{
|
||||
try
|
||||
@@ -52,18 +52,25 @@ public partial class Permissions
|
||||
})
|
||||
.WhenAll();
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
curPage =>
|
||||
{
|
||||
var pageItems = items.Skip(10 * curPage).Take(10).ToList();
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(allItems)
|
||||
.PageSize(10)
|
||||
.CurrentPage(page)
|
||||
.Page((pageItems, _) =>
|
||||
{
|
||||
if (pageItems.Count == 0)
|
||||
return new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle(title)
|
||||
.WithDescription(GetText(strs.empty_page));
|
||||
|
||||
if (pageItems.Count == 0)
|
||||
return new EmbedBuilder().WithOkColor().WithTitle(title).WithDescription(GetText(strs.empty_page));
|
||||
|
||||
return new EmbedBuilder().WithTitle(title).WithDescription(pageItems.Join('\n')).WithOkColor();
|
||||
},
|
||||
items.Length,
|
||||
10);
|
||||
return new EmbedBuilder()
|
||||
.WithTitle(title)
|
||||
.WithDescription(allItems.Join('\n'))
|
||||
.WithOkColor();
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -130,13 +137,17 @@ public partial class Permissions
|
||||
|
||||
if (action == AddRemove.Add)
|
||||
{
|
||||
await Response().Confirm(strs.blacklisted(Format.Code(type.ToString()),
|
||||
Format.Code(id.ToString()))).SendAsync();
|
||||
await Response()
|
||||
.Confirm(strs.blacklisted(Format.Code(type.ToString()),
|
||||
Format.Code(id.ToString())))
|
||||
.SendAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
await Response().Confirm(strs.unblacklisted(Format.Code(type.ToString()),
|
||||
Format.Code(id.ToString()))).SendAsync();
|
||||
await Response()
|
||||
.Confirm(strs.unblacklisted(Format.Code(type.ToString()),
|
||||
Format.Code(id.ToString())))
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -120,7 +120,7 @@ public partial class Searches
|
||||
await Response().Embed(new EmbedBuilder().WithOkColor().WithDescription(GetText(strs.feed_no_feed))).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(0,
|
||||
cur =>
|
||||
{
|
||||
|
@@ -70,7 +70,7 @@ public partial class Searches
|
||||
if (page-- < 1)
|
||||
return;
|
||||
|
||||
var streams = new List<FollowedStream>();
|
||||
var allStreams = new List<FollowedStream>();
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var all = uow.GuildConfigsForId(ctx.Guild.Id, set => set.Include(gc => gc.FollowedStreams))
|
||||
@@ -83,34 +83,32 @@ public partial class Searches
|
||||
if (((SocketGuild)ctx.Guild).GetTextChannel(fs.ChannelId) is null)
|
||||
await _service.UnfollowStreamAsync(fs.GuildId, index);
|
||||
else
|
||||
streams.Insert(0, fs);
|
||||
allStreams.Insert(0, fs);
|
||||
}
|
||||
}
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
cur =>
|
||||
{
|
||||
var elements = streams
|
||||
.Skip(cur * 12)
|
||||
.Take(12)
|
||||
.ToList();
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(allStreams)
|
||||
.PageSize(12)
|
||||
.CurrentPage(page)
|
||||
.Page((elements, cur) =>
|
||||
{
|
||||
if (elements.Count == 0)
|
||||
return new EmbedBuilder().WithDescription(GetText(strs.streams_none)).WithErrorColor();
|
||||
|
||||
if (elements.Count == 0)
|
||||
return new EmbedBuilder().WithDescription(GetText(strs.streams_none)).WithErrorColor();
|
||||
var eb = new EmbedBuilder().WithTitle(GetText(strs.streams_follow_title)).WithOkColor();
|
||||
for (var index = 0; index < elements.Count; index++)
|
||||
{
|
||||
var elem = elements[index];
|
||||
eb.AddField($"**#{index + 1 + (12 * cur)}** {elem.Username.ToLower()}",
|
||||
$"【{elem.Type}】\n<#{elem.ChannelId}>\n{elem.Message?.TrimTo(50)}",
|
||||
true);
|
||||
}
|
||||
|
||||
var eb = new EmbedBuilder().WithTitle(GetText(strs.streams_follow_title)).WithOkColor();
|
||||
for (var index = 0; index < elements.Count; index++)
|
||||
{
|
||||
var elem = elements[index];
|
||||
eb.AddField($"**#{index + 1 + (12 * cur)}** {elem.Username.ToLower()}",
|
||||
$"【{elem.Type}】\n<#{elem.ChannelId}>\n{elem.Message?.TrimTo(50)}",
|
||||
true);
|
||||
}
|
||||
|
||||
return eb;
|
||||
},
|
||||
streams.Count,
|
||||
12);
|
||||
return eb;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@@ -37,36 +37,39 @@ public partial class Utility
|
||||
|
||||
var invites = await channel.GetInvitesAsync();
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
cur =>
|
||||
{
|
||||
var i = 1;
|
||||
var invs = invites.Skip(cur * 9).Take(9).ToList();
|
||||
|
||||
if (!invs.Any())
|
||||
return new EmbedBuilder().WithErrorColor().WithDescription(GetText(strs.no_invites));
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(invites)
|
||||
.PageSize(9)
|
||||
.Page((invs, _) =>
|
||||
{
|
||||
var i = 1;
|
||||
|
||||
var embed = new EmbedBuilder().WithOkColor();
|
||||
foreach (var inv in invites)
|
||||
{
|
||||
var expiryString = inv.MaxAge is null or 0 || inv.CreatedAt is null
|
||||
? "∞"
|
||||
: (inv.CreatedAt.Value.AddSeconds(inv.MaxAge.Value).UtcDateTime - DateTime.UtcNow).ToString(
|
||||
"""d\.hh\:mm\:ss""");
|
||||
var creator = inv.Inviter.ToString().TrimTo(25);
|
||||
var usesString = $"{inv.Uses} / {(inv.MaxUses == 0 ? "∞" : inv.MaxUses?.ToString())}";
|
||||
if (!invs.Any())
|
||||
return new EmbedBuilder().WithErrorColor().WithDescription(GetText(strs.no_invites));
|
||||
|
||||
var desc = $@"`{GetText(strs.inv_uses)}` **{usesString}**
|
||||
var embed = new EmbedBuilder().WithOkColor();
|
||||
foreach (var inv in invs)
|
||||
{
|
||||
var expiryString = inv.MaxAge is null or 0 || inv.CreatedAt is null
|
||||
? "∞"
|
||||
: (inv.CreatedAt.Value.AddSeconds(inv.MaxAge.Value).UtcDateTime - DateTime.UtcNow)
|
||||
.ToString(
|
||||
"""d\.hh\:mm\:ss""");
|
||||
var creator = inv.Inviter.ToString().TrimTo(25);
|
||||
var usesString = $"{inv.Uses} / {(inv.MaxUses == 0 ? "∞" : inv.MaxUses?.ToString())}";
|
||||
|
||||
var desc = $@"`{GetText(strs.inv_uses)}` **{usesString}**
|
||||
`{GetText(strs.inv_expire)}` **{expiryString}**
|
||||
|
||||
|
||||
{inv.Url} ";
|
||||
embed.AddField($"#{i++} {creator}", desc);
|
||||
}
|
||||
embed.AddField($"#{i++} {creator}", desc);
|
||||
}
|
||||
|
||||
return embed;
|
||||
},
|
||||
invites.Count,
|
||||
9);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@@ -29,12 +29,14 @@ public partial class Xp
|
||||
}
|
||||
else
|
||||
{
|
||||
await Response().Confirm(
|
||||
strs.club_transfered(
|
||||
Format.Bold(club.Name),
|
||||
Format.Bold(newOwner.ToString())
|
||||
)
|
||||
).SendAsync();
|
||||
await Response()
|
||||
.Confirm(
|
||||
strs.club_transfered(
|
||||
Format.Bold(club.Name),
|
||||
Format.Bold(newOwner.ToString())
|
||||
)
|
||||
)
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +67,7 @@ public partial class Xp
|
||||
await Response().Error(strs.club_name_too_long).SendAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (result == ClubCreateResult.NameTaken)
|
||||
{
|
||||
await Response().Error(strs.club_name_taken).SendAsync();
|
||||
@@ -110,49 +112,52 @@ public partial class Xp
|
||||
private async Task InternalClubInfoAsync(ClubInfo club)
|
||||
{
|
||||
var lvl = new LevelStats(club.Xp);
|
||||
var users = club.Members.OrderByDescending(x =>
|
||||
{
|
||||
var l = new LevelStats(x.TotalXp).Level;
|
||||
if (club.OwnerId == x.Id)
|
||||
return int.MaxValue;
|
||||
if (x.IsClubAdmin)
|
||||
return (int.MaxValue / 2) + l;
|
||||
return l;
|
||||
});
|
||||
var allUsers = club.Members.OrderByDescending(x =>
|
||||
{
|
||||
var l = new LevelStats(x.TotalXp).Level;
|
||||
if (club.OwnerId == x.Id)
|
||||
return int.MaxValue;
|
||||
if (x.IsClubAdmin)
|
||||
return (int.MaxValue / 2) + l;
|
||||
return l;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(0,
|
||||
page =>
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle($"{club}")
|
||||
.WithDescription(GetText(strs.level_x(lvl.Level + $" ({club.Xp} xp)")))
|
||||
.AddField(GetText(strs.desc),
|
||||
string.IsNullOrWhiteSpace(club.Description) ? "-" : club.Description)
|
||||
.AddField(GetText(strs.owner), club.Owner.ToString(), true)
|
||||
// .AddField(GetText(strs.level_req), club.MinimumLevelReq.ToString(), true)
|
||||
.AddField(GetText(strs.members),
|
||||
string.Join("\n",
|
||||
users.Skip(page * 10)
|
||||
.Take(10)
|
||||
.Select(x =>
|
||||
{
|
||||
var l = new LevelStats(x.TotalXp);
|
||||
var lvlStr = Format.Bold($" ⟪{l.Level}⟫");
|
||||
if (club.OwnerId == x.Id)
|
||||
return x + "🌟" + lvlStr;
|
||||
if (x.IsClubAdmin)
|
||||
return x + "⭐" + lvlStr;
|
||||
return x + lvlStr;
|
||||
})));
|
||||
await Response()
|
||||
.Paginated()
|
||||
.Items(allUsers)
|
||||
.PageSize(10)
|
||||
.CurrentPage(0)
|
||||
.Page((users, _) =>
|
||||
{
|
||||
var embed = new EmbedBuilder()
|
||||
.WithOkColor()
|
||||
.WithTitle($"{club}")
|
||||
.WithDescription(GetText(strs.level_x(lvl.Level + $" ({club.Xp} xp)")))
|
||||
.AddField(GetText(strs.desc),
|
||||
string.IsNullOrWhiteSpace(club.Description) ? "-" : club.Description)
|
||||
.AddField(GetText(strs.owner), club.Owner.ToString(), true)
|
||||
// .AddField(GetText(strs.level_req), club.MinimumLevelReq.ToString(), true)
|
||||
.AddField(GetText(strs.members),
|
||||
string.Join("\n",
|
||||
users
|
||||
.Select(x =>
|
||||
{
|
||||
var l = new LevelStats(x.TotalXp);
|
||||
var lvlStr = Format.Bold($" ⟪{l.Level}⟫");
|
||||
if (club.OwnerId == x.Id)
|
||||
return x + "🌟" + lvlStr;
|
||||
if (x.IsClubAdmin)
|
||||
return x + "⭐" + lvlStr;
|
||||
return x + lvlStr;
|
||||
})));
|
||||
|
||||
if (Uri.IsWellFormedUriString(club.ImageUrl, UriKind.Absolute))
|
||||
return embed.WithThumbnailUrl(club.ImageUrl);
|
||||
if (Uri.IsWellFormedUriString(club.ImageUrl, UriKind.Absolute))
|
||||
return embed.WithThumbnailUrl(club.ImageUrl);
|
||||
|
||||
return embed;
|
||||
},
|
||||
club.Members.Count,
|
||||
10);
|
||||
return embed;
|
||||
})
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -204,14 +209,16 @@ public partial class Xp
|
||||
return ctx.SendPaginatedConfirmAsync(page,
|
||||
_ =>
|
||||
{
|
||||
var toShow = string.Join("\n", bans
|
||||
.Skip(page * 10).Take(10)
|
||||
.Select(x => x.ToString()));
|
||||
var toShow = string.Join("\n",
|
||||
bans
|
||||
.Skip(page * 10)
|
||||
.Take(10)
|
||||
.Select(x => x.ToString()));
|
||||
|
||||
return new EmbedBuilder()
|
||||
.WithTitle(GetText(strs.club_bans_for(club.ToString())))
|
||||
.WithDescription(toShow)
|
||||
.WithOkColor();
|
||||
.WithTitle(GetText(strs.club_bans_for(club.ToString())))
|
||||
.WithDescription(toShow)
|
||||
.WithOkColor();
|
||||
},
|
||||
bans.Length,
|
||||
10);
|
||||
@@ -235,9 +242,9 @@ public partial class Xp
|
||||
var toShow = string.Join("\n", apps.Skip(page * 10).Take(10).Select(x => x.ToString()));
|
||||
|
||||
return new EmbedBuilder()
|
||||
.WithTitle(GetText(strs.club_apps_for(club.ToString())))
|
||||
.WithDescription(toShow)
|
||||
.WithOkColor();
|
||||
.WithTitle(GetText(strs.club_apps_for(club.ToString())))
|
||||
.WithDescription(toShow)
|
||||
.WithOkColor();
|
||||
},
|
||||
apps.Length,
|
||||
10);
|
||||
@@ -283,7 +290,7 @@ public partial class Xp
|
||||
else if (result == ClubAcceptResult.NotOwnerOrAdmin)
|
||||
await Response().Error(strs.club_admin_perms).SendAsync();
|
||||
}
|
||||
|
||||
|
||||
[Cmd]
|
||||
[Priority(1)]
|
||||
public Task ClubReject(IUser user)
|
||||
@@ -296,9 +303,9 @@ public partial class Xp
|
||||
var result = _service.RejectApplication(ctx.User.Id, userName, out var discordUser);
|
||||
if (result == ClubDenyResult.Rejected)
|
||||
await Response().Confirm(strs.club_rejected(Format.Bold(discordUser.ToString()))).SendAsync();
|
||||
else if(result == ClubDenyResult.NoSuchApplicant)
|
||||
else if (result == ClubDenyResult.NoSuchApplicant)
|
||||
await Response().Error(strs.club_accept_invalid_applicant).SendAsync();
|
||||
else if(result == ClubDenyResult.NotOwnerOrAdmin)
|
||||
else if (result == ClubDenyResult.NotOwnerOrAdmin)
|
||||
await Response().Error(strs.club_admin_perms).SendAsync();
|
||||
}
|
||||
|
||||
@@ -327,8 +334,10 @@ public partial class Xp
|
||||
var result = _service.Kick(ctx.User.Id, userName, out var club);
|
||||
if (result == ClubKickResult.Success)
|
||||
{
|
||||
return Response().Confirm(strs.club_user_kick(Format.Bold(userName),
|
||||
Format.Bold(club.ToString()))).SendAsync();
|
||||
return Response()
|
||||
.Confirm(strs.club_user_kick(Format.Bold(userName),
|
||||
Format.Bold(club.ToString())))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
if (result == ClubKickResult.Hierarchy)
|
||||
@@ -352,8 +361,10 @@ public partial class Xp
|
||||
var result = _service.Ban(ctx.User.Id, userName, out var club);
|
||||
if (result == ClubBanResult.Success)
|
||||
{
|
||||
return Response().Confirm(strs.club_user_banned(Format.Bold(userName),
|
||||
Format.Bold(club.ToString()))).SendAsync();
|
||||
return Response()
|
||||
.Confirm(strs.club_user_banned(Format.Bold(userName),
|
||||
Format.Bold(club.ToString())))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
if (result == ClubBanResult.Unbannable)
|
||||
@@ -378,8 +389,10 @@ public partial class Xp
|
||||
|
||||
if (result == ClubUnbanResult.Success)
|
||||
{
|
||||
return Response().Confirm(strs.club_user_unbanned(Format.Bold(userName),
|
||||
Format.Bold(club.ToString()))).SendAsync();
|
||||
return Response()
|
||||
.Confirm(strs.club_user_unbanned(Format.Bold(userName),
|
||||
Format.Bold(club.ToString())))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
if (result == ClubUnbanResult.WrongUser)
|
||||
@@ -400,10 +413,10 @@ public partial class Xp
|
||||
: desc;
|
||||
|
||||
var eb = new EmbedBuilder()
|
||||
.WithAuthor(ctx.User)
|
||||
.WithTitle(GetText(strs.club_desc_update))
|
||||
.WithOkColor()
|
||||
.WithDescription(desc);
|
||||
.WithAuthor(ctx.User)
|
||||
.WithTitle(GetText(strs.club_desc_update))
|
||||
.WithOkColor()
|
||||
.WithDescription(desc);
|
||||
|
||||
await Response().Embed(eb).SendAsync();
|
||||
}
|
||||
@@ -450,11 +463,11 @@ public partial class Xp
|
||||
await Response().Error(strs.club_name_too_long).SendAsync();
|
||||
return;
|
||||
case ClubRenameResult.Success:
|
||||
{
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.club_renamed(clubName))).WithOkColor();
|
||||
await Response().Embed(embed).SendAsync();
|
||||
return;
|
||||
}
|
||||
{
|
||||
var embed = new EmbedBuilder().WithTitle(GetText(strs.club_renamed(clubName))).WithOkColor();
|
||||
await Response().Embed(embed).SendAsync();
|
||||
return;
|
||||
}
|
||||
case ClubRenameResult.NameTaken:
|
||||
await Response().Error(strs.club_name_taken).SendAsync();
|
||||
return;
|
||||
|
@@ -96,7 +96,7 @@ public static class MessageChannelExtensions
|
||||
embed: embed?.Build(),
|
||||
embeds: embeds?.Map(x => x.Build()),
|
||||
replyTo: replyTo);
|
||||
|
||||
|
||||
// embed title and optional footer overloads
|
||||
|
||||
public static Task SendPaginatedConfirmAsync(
|
||||
|
155
src/NadekoBot/_common/Sender/ResponseBuilder.PaginationSender.cs
Normal file
155
src/NadekoBot/_common/Sender/ResponseBuilder.PaginationSender.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
namespace NadekoBot.Extensions;
|
||||
|
||||
public partial class ResponseBuilder
|
||||
{
|
||||
public class PaginationSender<T>
|
||||
{
|
||||
private const string BUTTON_LEFT = "BUTTON_LEFT";
|
||||
private const string BUTTON_RIGHT = "BUTTON_RIGHT";
|
||||
|
||||
private static readonly IEmote _arrowLeft = Emote.Parse("<:x:1232256519844790302>");
|
||||
private static readonly IEmote _arrowRight = Emote.Parse("<:x:1232256515298295838>");
|
||||
|
||||
private readonly SourcedPaginatedResponseBuilder<T> _paginationBuilder;
|
||||
private readonly ResponseBuilder builder;
|
||||
private readonly DiscordSocketClient client;
|
||||
private int currentPage;
|
||||
|
||||
public PaginationSender(
|
||||
SourcedPaginatedResponseBuilder<T> paginationBuilder,
|
||||
ResponseBuilder builder
|
||||
)
|
||||
{
|
||||
this._paginationBuilder = paginationBuilder;
|
||||
this.builder = builder;
|
||||
|
||||
client = (DiscordSocketClient)builder.ctx.Client;
|
||||
currentPage = 0;
|
||||
}
|
||||
|
||||
public async Task SendAsync(bool ephemeral = false)
|
||||
{
|
||||
var lastPage = (_paginationBuilder.TotalElements - 1)
|
||||
/ _paginationBuilder.ItemsPerPage;
|
||||
|
||||
var items = (await _paginationBuilder.ItemsFunc(currentPage)).ToArray();
|
||||
var embed = await _paginationBuilder.PageFunc(items, currentPage);
|
||||
|
||||
if (_paginationBuilder.AddPaginatedFooter)
|
||||
embed.AddPaginatedFooter(currentPage, lastPage);
|
||||
|
||||
SimpleInteraction<T>? maybeInter = null;
|
||||
|
||||
async Task<ComponentBuilder> GetComponentBuilder()
|
||||
{
|
||||
var cb = new ComponentBuilder();
|
||||
|
||||
cb.WithButton(new ButtonBuilder()
|
||||
.WithStyle(ButtonStyle.Primary)
|
||||
.WithCustomId(BUTTON_LEFT)
|
||||
.WithDisabled(lastPage == 0)
|
||||
.WithEmote(_arrowLeft)
|
||||
.WithDisabled(currentPage <= 0));
|
||||
// todo
|
||||
// if (interFactory is not null)
|
||||
// {
|
||||
// maybeInter = await interFactory(currentPage);
|
||||
//
|
||||
// if (maybeInter is not null)
|
||||
// cb.WithButton(maybeInter.Button);
|
||||
// }
|
||||
|
||||
cb.WithButton(new ButtonBuilder()
|
||||
.WithStyle(ButtonStyle.Primary)
|
||||
.WithCustomId(BUTTON_RIGHT)
|
||||
.WithDisabled(lastPage == 0 || currentPage >= lastPage)
|
||||
.WithEmote(_arrowRight));
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
async Task UpdatePageAsync(SocketMessageComponent smc)
|
||||
{
|
||||
var pageItems = (await _paginationBuilder.ItemsFunc(currentPage)).ToArray();
|
||||
var toSend = await _paginationBuilder.PageFunc(pageItems, currentPage);
|
||||
if (_paginationBuilder.AddPaginatedFooter)
|
||||
toSend.AddPaginatedFooter(currentPage, lastPage);
|
||||
|
||||
var component = (await GetComponentBuilder()).Build();
|
||||
|
||||
await smc.ModifyOriginalResponseAsync(x =>
|
||||
{
|
||||
x.Embed = toSend.Build();
|
||||
x.Components = component;
|
||||
});
|
||||
}
|
||||
|
||||
var model = builder.Build(ephemeral);
|
||||
|
||||
var component = (await GetComponentBuilder()).Build();
|
||||
var msg = await model.TargetChannel
|
||||
.SendMessageAsync(model.Text,
|
||||
embed: embed.Build(),
|
||||
components: component,
|
||||
messageReference: model.MessageReference);
|
||||
|
||||
async Task OnInteractionAsync(SocketInteraction si)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (si is not SocketMessageComponent smc)
|
||||
return;
|
||||
|
||||
if (smc.Message.Id != msg.Id)
|
||||
return;
|
||||
|
||||
await si.DeferAsync();
|
||||
if (smc.User.Id != model.User.Id)
|
||||
return;
|
||||
|
||||
if (smc.Data.CustomId == BUTTON_LEFT)
|
||||
{
|
||||
if (currentPage == 0)
|
||||
return;
|
||||
|
||||
--currentPage;
|
||||
_ = UpdatePageAsync(smc);
|
||||
}
|
||||
else if (smc.Data.CustomId == BUTTON_RIGHT)
|
||||
{
|
||||
if (currentPage >= lastPage)
|
||||
return;
|
||||
|
||||
++currentPage;
|
||||
_ = UpdatePageAsync(smc);
|
||||
}
|
||||
else if (maybeInter is { } inter && inter.Button.CustomId == smc.Data.CustomId)
|
||||
{
|
||||
await inter.TriggerAsync(smc);
|
||||
_ = UpdatePageAsync(smc);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Error in pagination: {ErrorMessage}", ex.Message);
|
||||
}
|
||||
}
|
||||
// todo re-add
|
||||
// if (lastPage == 0 && interFactory is null)
|
||||
// return;
|
||||
|
||||
if (lastPage == 0)
|
||||
return;
|
||||
|
||||
var client = this.client;
|
||||
|
||||
client.InteractionCreated += OnInteractionAsync;
|
||||
|
||||
await Task.Delay(30_000);
|
||||
|
||||
client.InteractionCreated -= OnInteractionAsync;
|
||||
|
||||
await msg.ModifyAsync(mp => mp.Components = new ComponentBuilder().Build());
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
namespace NadekoBot.Extensions;
|
||||
|
||||
public sealed class ResponseBuilder
|
||||
public sealed partial class ResponseBuilder
|
||||
{
|
||||
private ICommandContext? ctx = null;
|
||||
private IMessageChannel? channel = null;
|
||||
@@ -44,33 +44,53 @@ public sealed class ResponseBuilder
|
||||
failIfNotExists: false);
|
||||
}
|
||||
|
||||
public async Task<IUserMessage> SendAsync(bool ephemeral = false)
|
||||
public ResponseMessageModel Build(bool ephemeral = false)
|
||||
{
|
||||
// todo use ephemeral in interactions
|
||||
var targetChannel = InternalResolveChannel() ?? throw new ArgumentNullException(nameof(channel));
|
||||
var msgReference = CreateMessageReference(targetChannel);
|
||||
|
||||
var txt = GetText(locTxt);
|
||||
// todo check message sanitization
|
||||
|
||||
if (sanitizeMentions)
|
||||
txt = txt?.SanitizeMentions(true);
|
||||
var buildModel = new ResponseMessageModel()
|
||||
{
|
||||
TargetChannel = targetChannel,
|
||||
MessageReference = msgReference,
|
||||
Text = txt,
|
||||
User = ctx?.User,
|
||||
Embed = embed ?? embedBuilder?.Build(),
|
||||
Embeds = embeds?.Map(x => x.Build()),
|
||||
SanitizeMentions = sanitizeMentions ? new(AllowedMentionTypes.Users) : AllowedMentions.All
|
||||
};
|
||||
|
||||
return buildModel;
|
||||
}
|
||||
|
||||
public Task<IUserMessage> SendAsync(bool ephemeral = false)
|
||||
{
|
||||
var model = Build(ephemeral);
|
||||
return SendAsync(model);
|
||||
}
|
||||
|
||||
public async Task<IUserMessage> SendAsync(ResponseMessageModel model)
|
||||
{
|
||||
if (this.fileStream is Stream stream)
|
||||
return await targetChannel.SendFileAsync(stream,
|
||||
return await model.TargetChannel.SendFileAsync(stream,
|
||||
filename: fileName,
|
||||
txt,
|
||||
embed: embed ?? embedBuilder?.Build(),
|
||||
model.Text,
|
||||
embed: model.Embed,
|
||||
components: null,
|
||||
allowedMentions: sanitizeMentions ? new(AllowedMentionTypes.Users) : AllowedMentions.All,
|
||||
messageReference: msgReference);
|
||||
allowedMentions: model.SanitizeMentions,
|
||||
messageReference: model.MessageReference);
|
||||
|
||||
return await targetChannel.SendMessageAsync(
|
||||
txt,
|
||||
embed: embed ?? embedBuilder?.Build(),
|
||||
embeds: embeds?.Map(x => x.Build()),
|
||||
return await model.TargetChannel.SendMessageAsync(
|
||||
model.Text,
|
||||
embed: model.Embed,
|
||||
embeds: model.Embeds,
|
||||
components: null,
|
||||
allowedMentions: sanitizeMentions ? new(AllowedMentionTypes.Users) : AllowedMentions.All,
|
||||
messageReference: msgReference);
|
||||
allowedMentions: model.SanitizeMentions,
|
||||
messageReference: model.MessageReference);
|
||||
}
|
||||
|
||||
private ulong? InternalResolveGuildId(IMessageChannel? targetChannel)
|
||||
@@ -263,4 +283,94 @@ public sealed class ResponseBuilder
|
||||
this.fileName = fileName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaginatedResponseBuilder Paginated()
|
||||
=> new(this);
|
||||
}
|
||||
|
||||
public class PaginatedResponseBuilder
|
||||
{
|
||||
protected readonly ResponseBuilder _builder;
|
||||
|
||||
public PaginatedResponseBuilder(ResponseBuilder builder)
|
||||
{
|
||||
_builder = builder;
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> Items<T>(IReadOnlyCollection<T> items)
|
||||
=> new SourcedPaginatedResponseBuilder<T>(_builder)
|
||||
.Items(items);
|
||||
}
|
||||
|
||||
public sealed class SourcedPaginatedResponseBuilder<T> : PaginatedResponseBuilder
|
||||
{
|
||||
private IReadOnlyCollection<T>? items;
|
||||
public Func<IReadOnlyList<T>, int, Task<EmbedBuilder>> PageFunc { get; private set; }
|
||||
public Func<int, Task<IEnumerable<T>>> ItemsFunc { get; set; }
|
||||
public int TotalElements { get; private set; } = 1;
|
||||
public int ItemsPerPage { get; private set; } = 9;
|
||||
public bool AddPaginatedFooter { get; private set; } = true;
|
||||
public bool IsEphemeral { get; private set; }
|
||||
|
||||
public SourcedPaginatedResponseBuilder(ResponseBuilder builder)
|
||||
: base(builder)
|
||||
{
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> Items(IReadOnlyCollection<T> items)
|
||||
{
|
||||
this.items = items;
|
||||
ItemsFunc = (i) => Task.FromResult(this.items.Skip(i * ItemsPerPage).Take(ItemsPerPage));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> PageSize(int i)
|
||||
{
|
||||
ItemsPerPage = i;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> CurrentPage(int i)
|
||||
{
|
||||
InitialPage = i;
|
||||
return this;
|
||||
}
|
||||
|
||||
// todo use it
|
||||
public int InitialPage { get; set; }
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> Page(Func<IReadOnlyList<T>, int, EmbedBuilder> pageFunc)
|
||||
{
|
||||
this.PageFunc = (xs, x) => Task.FromResult(pageFunc(xs, x));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> Page(Func<IReadOnlyList<T>, int, Task<EmbedBuilder>> pageFunc)
|
||||
{
|
||||
this.PageFunc = pageFunc;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> AddFooter()
|
||||
{
|
||||
AddPaginatedFooter = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SourcedPaginatedResponseBuilder<T> Ephemeral()
|
||||
{
|
||||
IsEphemeral = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public Task SendAsync()
|
||||
{
|
||||
var paginationSender = new ResponseBuilder.PaginationSender<T>(
|
||||
this,
|
||||
_builder);
|
||||
|
||||
return paginationSender.SendAsync(IsEphemeral);
|
||||
}
|
||||
}
|
10
src/NadekoBot/_common/Sender/ResponseMessageModel.cs
Normal file
10
src/NadekoBot/_common/Sender/ResponseMessageModel.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
public class ResponseMessageModel
|
||||
{
|
||||
public IMessageChannel TargetChannel { get; set; }
|
||||
public MessageReference MessageReference { get; set; }
|
||||
public string Text { get; set; }
|
||||
public Embed Embed { get; set; }
|
||||
public Embed[] Embeds { get; set; }
|
||||
public AllowedMentions SanitizeMentions { get; set; }
|
||||
public IUser User { get; set; }
|
||||
}
|
Reference in New Issue
Block a user