1
0
Fork 1
mirror of https://github.com/TeamOctolings/Octobot.git synced 2025-01-31 09:09:00 +03:00

Add /showinfo (#122)

Signed-off-by: Macintosh II <mctaylxrs@outlook.com>
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
Co-authored-by: Octol1ttle <l1ttleofficial@outlook.com>
This commit is contained in:
Macintxsh 2023-09-29 15:31:45 +03:00 committed by GitHub
parent 4e4e60f845
commit 0f916d46de
Signed by: GitHub
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 460 additions and 1 deletions

View file

@ -600,4 +600,46 @@
<data name="AllSettingsReset" xml:space="preserve">
<value>All settings have been reset</value>
</data>
<data name="ShowInfoDisplayName" xml:space="preserve">
<value>Display name</value>
</data>
<data name="ShowInfoTitle" xml:space="preserve">
<value>Information about {0}</value>
</data>
<data name="ShowInfoMuted" xml:space="preserve">
<value>Muted</value>
</data>
<data name="ShowInfoDiscordUserSince" xml:space="preserve">
<value>Discord user since</value>
</data>
<data name="ShowInfoBanned" xml:space="preserve">
<value>Banned</value>
</data>
<data name="ShowInfoPunishments" xml:space="preserve">
<value>Punishments</value>
</data>
<data name="ShowInfoBannedPermanently" xml:space="preserve">
<value>Banned permanently</value>
</data>
<data name="ShowInfoNotOnGuild" xml:space="preserve">
<value>Not in the guild</value>
</data>
<data name="ShowInfoMutedByTimeout" xml:space="preserve">
<value>Muted by timeout</value>
</data>
<data name="ShowInfoMutedByMuteRole" xml:space="preserve">
<value>Muted by mute role</value>
</data>
<data name="ShowInfoGuildMemberSince" xml:space="preserve">
<value>Guild member since</value>
</data>
<data name="ShowInfoGuildNickname" xml:space="preserve">
<value>Nickname</value>
</data>
<data name="ShowInfoGuildRoles" xml:space="preserve">
<value>Roles</value>
</data>
<data name="ShowInfoGuildMemberPremiumSince" xml:space="preserve">
<value>Nitro booster since</value>
</data>
</root>

View file

@ -600,4 +600,46 @@
<data name="AllSettingsReset" xml:space="preserve">
<value>Все настройки были сброшены</value>
</data>
<data name="ShowInfoDisplayName" xml:space="preserve">
<value>Отображаемое имя</value>
</data>
<data name="ShowInfoTitle" xml:space="preserve">
<value>Информация о {0}</value>
</data>
<data name="ShowInfoMuted" xml:space="preserve">
<value>Заглушен</value>
</data>
<data name="ShowInfoDiscordUserSince" xml:space="preserve">
<value>Вступил в Discord</value>
</data>
<data name="ShowInfoBanned" xml:space="preserve">
<value>Забанен</value>
</data>
<data name="ShowInfoPunishments" xml:space="preserve">
<value>Наказания</value>
</data>
<data name="ShowInfoBannedPermanently" xml:space="preserve">
<value>Забанен навсегда</value>
</data>
<data name="ShowInfoNotOnGuild" xml:space="preserve">
<value>Не на сервере</value>
</data>
<data name="ShowInfoMutedByTimeout" xml:space="preserve">
<value>Заглушен с помощью тайм-аута</value>
</data>
<data name="ShowInfoMutedByMuteRole" xml:space="preserve">
<value>Заглушен с помощью роли мута</value>
</data>
<data name="ShowInfoGuildMemberSince" xml:space="preserve">
<value>Вступил на сервер</value>
</data>
<data name="ShowInfoGuildNickname" xml:space="preserve">
<value>Никнейм</value>
</data>
<data name="ShowInfoGuildRoles" xml:space="preserve">
<value>Роли</value>
</data>
<data name="ShowInfoGuildMemberPremiumSince" xml:space="preserve">
<value>Начал бустить сервер</value>
</data>
</root>

View file

@ -600,4 +600,46 @@
<data name="AllSettingsReset" xml:space="preserve">
<value>откатываемся к заводским...</value>
</data>
<data name="ShowInfoDisplayName" xml:space="preserve">
<value>дисплейнейм</value>
</data>
<data name="ShowInfoTitle" xml:space="preserve">
<value>деанон {0}</value>
</data>
<data name="ShowInfoMuted" xml:space="preserve">
<value>замучен</value>
</data>
<data name="ShowInfoDiscordUserSince" xml:space="preserve">
<value>юзер Discord со времен</value>
</data>
<data name="ShowInfoBanned" xml:space="preserve">
<value>забанен</value>
</data>
<data name="ShowInfoPunishments" xml:space="preserve">
<value>приколы полученные по заслугам</value>
</data>
<data name="ShowInfoBannedPermanently" xml:space="preserve">
<value>забанен</value>
</data>
<data name="ShowInfoNotOnGuild" xml:space="preserve">
<value>вышел из сервера</value>
</data>
<data name="ShowInfoMutedByTimeout" xml:space="preserve">
<value>замучен таймаутом</value>
</data>
<data name="ShowInfoMutedByMuteRole" xml:space="preserve">
<value>замучен ролькой</value>
</data>
<data name="ShowInfoGuildMemberSince" xml:space="preserve">
<value>участник сервера со времен</value>
</data>
<data name="ShowInfoGuildNickname" xml:space="preserve">
<value>сервернейм</value>
</data>
<data name="ShowInfoGuildRoles" xml:space="preserve">
<value>рольки</value>
</data>
<data name="ShowInfoGuildMemberPremiumSince" xml:space="preserve">
<value>бустит сервер со времен</value>
</data>
</root>

View file

@ -102,7 +102,8 @@ public sealed class Boyfriend
.WithCommandGroup<MuteCommandGroup>()
.WithCommandGroup<PingCommandGroup>()
.WithCommandGroup<RemindCommandGroup>()
.WithCommandGroup<SettingsCommandGroup>();
.WithCommandGroup<SettingsCommandGroup>()
.WithCommandGroup<ToolsCommandGroup>();
var responderTypes = typeof(Boyfriend).Assembly
.GetExportedTypes()
.Where(t => t.IsResponder());

View file

@ -0,0 +1,231 @@
using System.ComponentModel;
using System.Drawing;
using System.Text;
using Boyfriend.Data;
using Boyfriend.Services;
using JetBrains.Annotations;
using Remora.Commands.Attributes;
using Remora.Commands.Groups;
using Remora.Discord.API.Abstractions.Objects;
using Remora.Discord.API.Abstractions.Rest;
using Remora.Discord.Commands.Attributes;
using Remora.Discord.Commands.Contexts;
using Remora.Discord.Commands.Feedback.Services;
using Remora.Discord.Extensions.Embeds;
using Remora.Discord.Extensions.Formatting;
using Remora.Rest.Core;
using Remora.Results;
namespace Boyfriend.Commands;
/// <summary>
/// Handles commands related to tools: /showinfo.
/// </summary>
[UsedImplicitly]
public class ToolsCommandGroup : CommandGroup
{
private readonly ICommandContext _context;
private readonly FeedbackService _feedback;
private readonly IDiscordRestGuildAPI _guildApi;
private readonly GuildDataService _guildData;
private readonly IDiscordRestUserAPI _userApi;
public ToolsCommandGroup(
ICommandContext context, FeedbackService feedback,
GuildDataService guildData, IDiscordRestGuildAPI guildApi,
IDiscordRestUserAPI userApi, IDiscordRestChannelAPI channelApi)
{
_context = context;
_guildData = guildData;
_feedback = feedback;
_guildApi = guildApi;
_userApi = userApi;
}
/// <summary>
/// A slash command that shows information about user.
/// </summary>
/// <remarks>
/// Information in the output:
/// <list type="bullet">
/// <item>Display name</item>
/// <item>Discord user since</item>
/// <item>Guild nickname</item>
/// <item>Guild member since</item>
/// <item>Nitro booster since</item>
/// <item>Guild roles</item>
/// <item>Active mute information</item>
/// <item>Active ban information</item>
/// <item>Is on guild status</item>
/// </list>
/// </remarks>
/// <param name="target">The user to show info about.</param>
/// <returns>
/// A feedback sending result which may or may not have succeeded.
/// </returns>
[Command("showinfo")]
[DiscordDefaultDMPermission(false)]
[Description("Shows info about user")]
[UsedImplicitly]
public async Task<Result> ExecuteShowInfoAsync(
[Description("User to show info about")]
IUser? target = null)
{
if (!_context.TryGetContextIDs(out var guildId, out _, out var userId))
{
return new ArgumentInvalidError(nameof(_context), "Unable to retrieve necessary IDs from command context");
}
var userResult = await _userApi.GetUserAsync(userId, CancellationToken);
if (!userResult.IsDefined(out var user))
{
return Result.FromError(userResult);
}
var currentUserResult = await _userApi.GetCurrentUserAsync(CancellationToken);
if (!currentUserResult.IsDefined(out var currentUser))
{
return Result.FromError(currentUserResult);
}
var data = await _guildData.GetData(guildId, CancellationToken);
Messages.Culture = GuildSettings.Language.Get(data.Settings);
return await ShowUserInfoAsync(target ?? user, currentUser, data, guildId, CancellationToken);
}
private async Task<Result> ShowUserInfoAsync(
IUser user, IUser currentUser, GuildData data, Snowflake guildId, CancellationToken ct = default)
{
var builder = new StringBuilder().AppendLine($"### <@{user.ID}>");
if (user.GlobalName is not null)
{
builder.Append("- ").AppendLine(Messages.ShowInfoDisplayName)
.AppendLine(Markdown.InlineCode(user.GlobalName));
}
builder.Append("- ").AppendLine(Messages.ShowInfoDiscordUserSince)
.AppendLine(Markdown.Timestamp(user.ID.Timestamp));
var memberData = data.GetOrCreateMemberData(user.ID);
var embedColor = ColorsList.Cyan;
var guildMemberResult = await _guildApi.GetGuildMemberAsync(guildId, user.ID, ct);
DateTimeOffset? communicationDisabledUntil = null;
if (guildMemberResult.IsDefined(out var guildMember))
{
communicationDisabledUntil = guildMember.CommunicationDisabledUntil.OrDefault(null);
embedColor = AppendGuildInformation(embedColor, guildMember, builder);
}
var isMuted = (memberData.MutedUntil is not null && DateTimeOffset.UtcNow <= memberData.MutedUntil) ||
communicationDisabledUntil is not null;
var existingBanResult = await _guildApi.GetGuildBanAsync(guildId, user.ID, ct);
if (isMuted || existingBanResult.IsDefined())
{
builder.Append("### ")
.AppendLine(Markdown.Bold(Messages.ShowInfoPunishments));
}
if (isMuted)
{
AppendMuteInformation(memberData, communicationDisabledUntil, builder);
embedColor = ColorsList.Red;
}
if (existingBanResult.IsDefined())
{
AppendBanInformation(memberData, builder);
embedColor = ColorsList.Black;
}
if (!guildMemberResult.IsSuccess && !existingBanResult.IsDefined())
{
builder.Append("### ")
.AppendLine(Markdown.Bold(Messages.ShowInfoNotOnGuild));
embedColor = ColorsList.Default;
}
var embed = new EmbedBuilder().WithSmallTitle(
string.Format(Messages.ShowInfoTitle, user.GetTag()), currentUser)
.WithDescription(builder.ToString())
.WithColour(embedColor)
.WithLargeAvatar(user)
.WithFooter($"ID: {user.ID.ToString()}")
.Build();
return await _feedback.SendContextualEmbedResultAsync(embed, ct);
}
private static Color AppendGuildInformation(Color color, IGuildMember guildMember, StringBuilder builder)
{
if (guildMember.Nickname.IsDefined(out var nickname))
{
builder.Append("- ").AppendLine(Messages.ShowInfoGuildNickname)
.AppendLine(Markdown.InlineCode(nickname));
}
builder.Append("- ").AppendLine(Messages.ShowInfoGuildMemberSince)
.AppendLine(Markdown.Timestamp(guildMember.JoinedAt));
if (guildMember.PremiumSince.IsDefined(out var premiumSince))
{
builder.Append("- ").AppendLine(Messages.ShowInfoGuildMemberPremiumSince)
.AppendLine(Markdown.Timestamp(premiumSince.Value));
color = ColorsList.Magenta;
}
if (guildMember.Roles.Count > 0)
{
builder.Append("- ").AppendLine(Messages.ShowInfoGuildRoles);
for (var i = 0; i < guildMember.Roles.Count - 1; i++)
{
builder.Append($"<@&{guildMember.Roles[i]}>, ");
}
builder.AppendLine($"<@&{guildMember.Roles[^1]}>");
}
return color;
}
private static void AppendBanInformation(MemberData memberData, StringBuilder builder)
{
if (memberData.BannedUntil < DateTimeOffset.MaxValue)
{
builder.Append("- ").AppendLine(Messages.ShowInfoBanned)
.Append(" - ").AppendLine(string.Format(
Messages.DescriptionActionExpiresAt, Markdown.Timestamp(memberData.BannedUntil.Value)));
return;
}
builder.Append("- ").AppendLine(Messages.ShowInfoBannedPermanently);
}
private static void AppendMuteInformation(
MemberData memberData, DateTimeOffset? communicationDisabledUntil, StringBuilder builder)
{
builder.Append("- ").AppendLine(Messages.ShowInfoMuted);
if (memberData.MutedUntil is not null && DateTimeOffset.UtcNow <= memberData.MutedUntil)
{
builder.Append(" - ").AppendLine(Messages.ShowInfoMutedByMuteRole)
.Append(" - ").AppendLine(string.Format(
Messages.DescriptionActionExpiresAt, Markdown.Timestamp(memberData.MutedUntil.Value)));
}
if (communicationDisabledUntil is not null)
{
builder.Append(" - ").AppendLine(Messages.ShowInfoMutedByTimeout)
.Append(" - ").AppendLine(string.Format(
Messages.DescriptionActionExpiresAt, Markdown.Timestamp(communicationDisabledUntil.Value)));
}
}
}

View file

@ -74,6 +74,23 @@ public static class Extensions
return builder;
}
/// <summary>
/// Adds a user avatar in the thumbnail field.
/// </summary>
/// <param name="builder">The builder to add the thumbnail to.</param>
/// <param name="avatarSource">The user whose avatar to use in the thumbnail field.</param>
/// <returns>The builder with the added avatar in the thumbnail field.</returns>
public static EmbedBuilder WithLargeAvatar(
this EmbedBuilder builder, IUser avatarSource)
{
var avatarUrlResult = CDN.GetUserAvatarUrl(avatarSource, imageSize: 256);
var avatarUrl = avatarUrlResult.IsSuccess
? avatarUrlResult.Entity
: CDN.GetDefaultUserAvatarUrl(avatarSource, imageSize: 256).Entity;
return builder.WithThumbnailUrl(avatarUrl.AbsoluteUri);
}
/// <summary>
/// Adds a footer representing that the action was performed in the <paramref name="guild" />.
/// </summary>

View file

@ -1013,5 +1013,89 @@ namespace Boyfriend {
return ResourceManager.GetString("AllSettingsReset", resourceCulture);
}
}
internal static string ShowInfoTitle {
get {
return ResourceManager.GetString("ShowInfoTitle", resourceCulture);
}
}
internal static string ShowInfoDisplayName {
get {
return ResourceManager.GetString("ShowInfoDisplayName", resourceCulture);
}
}
internal static string ShowInfoDiscordUserSince {
get {
return ResourceManager.GetString("ShowInfoDiscordUserSince", resourceCulture);
}
}
internal static string ShowInfoMuted {
get {
return ResourceManager.GetString("ShowInfoMuted", resourceCulture);
}
}
internal static string ShowInfoBanned {
get {
return ResourceManager.GetString("ShowInfoBanned", resourceCulture);
}
}
internal static string ShowInfoPunishments {
get {
return ResourceManager.GetString("ShowInfoPunishments", resourceCulture);
}
}
internal static string ShowInfoBannedPermanently {
get {
return ResourceManager.GetString("ShowInfoBannedPermanently", resourceCulture);
}
}
internal static string ShowInfoNotOnGuild {
get {
return ResourceManager.GetString("ShowInfoNotOnGuild", resourceCulture);
}
}
internal static string ShowInfoMutedByTimeout {
get {
return ResourceManager.GetString("ShowInfoMutedByTimeout", resourceCulture);
}
}
internal static string ShowInfoMutedByMuteRole {
get {
return ResourceManager.GetString("ShowInfoMutedByMuteRole", resourceCulture);
}
}
internal static string ShowInfoGuildMemberSince {
get {
return ResourceManager.GetString("ShowInfoGuildMemberSince", resourceCulture);
}
}
internal static string ShowInfoGuildNickname {
get {
return ResourceManager.GetString("ShowInfoGuildNickname", resourceCulture);
}
}
internal static string ShowInfoGuildRoles {
get {
return ResourceManager.GetString("ShowInfoGuildRoles", resourceCulture);
}
}
internal static string ShowInfoGuildMemberPremiumSince {
get {
return ResourceManager.GetString("ShowInfoGuildMemberPremiumSince", resourceCulture);
}
}
}
}