mirror of
https://github.com/TeamOctolings/Octobot.git
synced 2025-05-13 17:26:08 +03:00
Merge branch 'master' into fix-event-status-update-retry
This commit is contained in:
commit
28266ce39f
9 changed files with 86 additions and 16 deletions
|
@ -564,4 +564,10 @@
|
||||||
<data name="GuildInfoBoostCount" xml:space="preserve">
|
<data name="GuildInfoBoostCount" xml:space="preserve">
|
||||||
<value>Boost count</value>
|
<value>Boost count</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="NoMessagesToClear" xml:space="preserve">
|
||||||
|
<value>There are no messages matching your filter!</value>
|
||||||
|
</data>
|
||||||
|
<data name="MessagesClearedFiltered" xml:space="preserve">
|
||||||
|
<value>Cleared {0} messages from {1}</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -564,4 +564,10 @@
|
||||||
<data name="GuildInfoBoostCount" xml:space="preserve">
|
<data name="GuildInfoBoostCount" xml:space="preserve">
|
||||||
<value>Количество бустов</value>
|
<value>Количество бустов</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="NoMessagesToClear" xml:space="preserve">
|
||||||
|
<value>Нет сообщений, которые подходят под твой фильтр!</value>
|
||||||
|
</data>
|
||||||
|
<data name="MessagesClearedFiltered" xml:space="preserve">
|
||||||
|
<value>Очищено {0} сообщений от {1}</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -564,4 +564,10 @@
|
||||||
<data name="GuildInfoBoostCount" xml:space="preserve">
|
<data name="GuildInfoBoostCount" xml:space="preserve">
|
||||||
<value>кол-во бустов</value>
|
<value>кол-во бустов</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="NoMessagesToClear" xml:space="preserve">
|
||||||
|
<value>алло а чё мне удалять-то</value>
|
||||||
|
</data>
|
||||||
|
<data name="MessagesClearedFiltered" xml:space="preserve">
|
||||||
|
<value>вырезано {0} забавных сообщений от {1}</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -45,9 +45,10 @@ public class ClearCommandGroup : CommandGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A slash command that clears messages in the channel it was executed.
|
/// A slash command that clears messages in the channel it was executed, optionally filtering by message author.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="amount">The amount of messages to clear.</param>
|
/// <param name="amount">The amount of messages to clear.</param>
|
||||||
|
/// <param name="author">The user whose messages will be cleared.</param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// A feedback sending result which may or may not have succeeded. A successful result does not mean that any messages
|
/// A feedback sending result which may or may not have succeeded. A successful result does not mean that any messages
|
||||||
/// were cleared and vice-versa.
|
/// were cleared and vice-versa.
|
||||||
|
@ -62,7 +63,8 @@ public class ClearCommandGroup : CommandGroup
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public async Task<Result> ExecuteClear(
|
public async Task<Result> ExecuteClear(
|
||||||
[Description("Number of messages to remove (2-100)")] [MinValue(2)] [MaxValue(100)]
|
[Description("Number of messages to remove (2-100)")] [MinValue(2)] [MaxValue(100)]
|
||||||
int amount)
|
int amount,
|
||||||
|
IUser? author = null)
|
||||||
{
|
{
|
||||||
if (!_context.TryGetContextIDs(out var guildId, out var channelId, out var executorId))
|
if (!_context.TryGetContextIDs(out var guildId, out var channelId, out var executorId))
|
||||||
{
|
{
|
||||||
|
@ -92,11 +94,11 @@ public class ClearCommandGroup : CommandGroup
|
||||||
var data = await _guildData.GetData(guildId, CancellationToken);
|
var data = await _guildData.GetData(guildId, CancellationToken);
|
||||||
Messages.Culture = GuildSettings.Language.Get(data.Settings);
|
Messages.Culture = GuildSettings.Language.Get(data.Settings);
|
||||||
|
|
||||||
return await ClearMessagesAsync(executor, amount, data, channelId, messages, bot, CancellationToken);
|
return await ClearMessagesAsync(executor, author, data, channelId, messages, bot, CancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<Result> ClearMessagesAsync(
|
private async Task<Result> ClearMessagesAsync(
|
||||||
IUser executor, int amount, GuildData data, Snowflake channelId, IReadOnlyList<IMessage> messages, IUser bot,
|
IUser executor, IUser? author, GuildData data, Snowflake channelId, IReadOnlyList<IMessage> messages, IUser bot,
|
||||||
CancellationToken ct = default)
|
CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var idList = new List<Snowflake>(messages.Count);
|
var idList = new List<Snowflake>(messages.Count);
|
||||||
|
@ -104,12 +106,27 @@ public class ClearCommandGroup : CommandGroup
|
||||||
for (var i = messages.Count - 1; i >= 1; i--) // '>= 1' to skip last message ('Octobot is thinking...')
|
for (var i = messages.Count - 1; i >= 1; i--) // '>= 1' to skip last message ('Octobot is thinking...')
|
||||||
{
|
{
|
||||||
var message = messages[i];
|
var message = messages[i];
|
||||||
|
if (author is not null && message.Author.ID != author.ID)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
idList.Add(message.ID);
|
idList.Add(message.ID);
|
||||||
builder.AppendLine(string.Format(Messages.MessageFrom, Mention.User(message.Author)));
|
builder.AppendLine(string.Format(Messages.MessageFrom, Mention.User(message.Author)));
|
||||||
builder.Append(message.Content.InBlockCode());
|
builder.Append(message.Content.InBlockCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
var title = string.Format(Messages.MessagesCleared, amount.ToString());
|
if (idList.Count == 0)
|
||||||
|
{
|
||||||
|
var failedEmbed = new EmbedBuilder().WithSmallTitle(Messages.NoMessagesToClear, bot)
|
||||||
|
.WithColour(ColorsList.Red).Build();
|
||||||
|
|
||||||
|
return await _feedback.SendContextualEmbedResultAsync(failedEmbed, ct);
|
||||||
|
}
|
||||||
|
|
||||||
|
var title = author is not null
|
||||||
|
? string.Format(Messages.MessagesClearedFiltered, idList.Count.ToString(), author.GetTag())
|
||||||
|
: string.Format(Messages.MessagesCleared, idList.Count.ToString());
|
||||||
var description = builder.ToString();
|
var description = builder.ToString();
|
||||||
|
|
||||||
var deleteResult = await _channelApi.BulkDeleteMessagesAsync(
|
var deleteResult = await _channelApi.BulkDeleteMessagesAsync(
|
||||||
|
|
|
@ -5,10 +5,14 @@ namespace Octobot.Data;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class MemberData
|
public sealed class MemberData
|
||||||
{
|
{
|
||||||
public MemberData(ulong id, DateTimeOffset? bannedUntil = null)
|
public MemberData(ulong id, DateTimeOffset? bannedUntil = null, List<Reminder>? reminders = null)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
BannedUntil = bannedUntil;
|
BannedUntil = bannedUntil;
|
||||||
|
if (reminders is not null)
|
||||||
|
{
|
||||||
|
Reminders = reminders;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ulong Id { get; }
|
public ulong Id { get; }
|
||||||
|
|
|
@ -2,7 +2,7 @@ namespace Octobot.Data;
|
||||||
|
|
||||||
public struct Reminder
|
public struct Reminder
|
||||||
{
|
{
|
||||||
public DateTimeOffset At;
|
public DateTimeOffset At { get; init; }
|
||||||
public string Text;
|
public string Text { get; init; }
|
||||||
public ulong Channel;
|
public ulong Channel { get; init; }
|
||||||
}
|
}
|
||||||
|
|
16
src/Messages.Designer.cs
generated
16
src/Messages.Designer.cs
generated
|
@ -980,5 +980,21 @@ namespace Octobot {
|
||||||
return ResourceManager.GetString("GuildInfoBoostCount", resourceCulture);
|
return ResourceManager.GetString("GuildInfoBoostCount", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static string NoMessagesToClear
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ResourceManager.GetString("NoMessagesToClear", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string MessagesClearedFiltered
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ResourceManager.GetString("MessagesClearedFiltered", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,6 +181,11 @@ public sealed class ScheduledEventUpdateService : BackgroundService
|
||||||
private async Task<Result> SendScheduledEventCreatedMessage(
|
private async Task<Result> SendScheduledEventCreatedMessage(
|
||||||
IGuildScheduledEvent scheduledEvent, JsonNode settings, CancellationToken ct = default)
|
IGuildScheduledEvent scheduledEvent, JsonNode settings, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
|
if (GuildSettings.EventNotificationChannel.Get(settings).Empty())
|
||||||
|
{
|
||||||
|
return Result.FromSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
if (!scheduledEvent.Creator.IsDefined(out var creator))
|
if (!scheduledEvent.Creator.IsDefined(out var creator))
|
||||||
{
|
{
|
||||||
return new ArgumentNullError(nameof(scheduledEvent.Creator));
|
return new ArgumentNullError(nameof(scheduledEvent.Creator));
|
||||||
|
@ -281,6 +286,11 @@ public sealed class ScheduledEventUpdateService : BackgroundService
|
||||||
{
|
{
|
||||||
data.ScheduledEvents[scheduledEvent.ID.Value].ActualStartTime = DateTimeOffset.UtcNow;
|
data.ScheduledEvents[scheduledEvent.ID.Value].ActualStartTime = DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
|
if (GuildSettings.EventNotificationChannel.Get(data.Settings).Empty())
|
||||||
|
{
|
||||||
|
return Result.FromSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
var embedDescriptionResult = scheduledEvent.EntityType switch
|
var embedDescriptionResult = scheduledEvent.EntityType switch
|
||||||
{
|
{
|
||||||
GuildScheduledEventEntityType.StageInstance or GuildScheduledEventEntityType.Voice =>
|
GuildScheduledEventEntityType.StageInstance or GuildScheduledEventEntityType.Voice =>
|
||||||
|
@ -290,7 +300,7 @@ public sealed class ScheduledEventUpdateService : BackgroundService
|
||||||
};
|
};
|
||||||
|
|
||||||
var contentResult = await _utility.GetEventNotificationMentions(
|
var contentResult = await _utility.GetEventNotificationMentions(
|
||||||
scheduledEvent, data.Settings, ct);
|
scheduledEvent, data, ct);
|
||||||
if (!contentResult.IsDefined(out var content))
|
if (!contentResult.IsDefined(out var content))
|
||||||
{
|
{
|
||||||
return Result.FromError(contentResult);
|
return Result.FromError(contentResult);
|
||||||
|
@ -417,8 +427,13 @@ public sealed class ScheduledEventUpdateService : BackgroundService
|
||||||
private async Task<Result> SendEarlyEventNotificationAsync(
|
private async Task<Result> SendEarlyEventNotificationAsync(
|
||||||
IGuildScheduledEvent scheduledEvent, GuildData data, CancellationToken ct)
|
IGuildScheduledEvent scheduledEvent, GuildData data, CancellationToken ct)
|
||||||
{
|
{
|
||||||
|
if (GuildSettings.EventNotificationChannel.Get(data.Settings).Empty())
|
||||||
|
{
|
||||||
|
return Result.FromSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
var contentResult = await _utility.GetEventNotificationMentions(
|
var contentResult = await _utility.GetEventNotificationMentions(
|
||||||
scheduledEvent, data.Settings, ct);
|
scheduledEvent, data, ct);
|
||||||
if (!contentResult.IsDefined(out var content))
|
if (!contentResult.IsDefined(out var content))
|
||||||
{
|
{
|
||||||
return Result.FromError(contentResult);
|
return Result.FromError(contentResult);
|
||||||
|
|
|
@ -160,16 +160,16 @@ public sealed class UtilityService : IHostedService
|
||||||
/// <param name="scheduledEvent">
|
/// <param name="scheduledEvent">
|
||||||
/// The scheduled event whose subscribers will be mentioned.
|
/// The scheduled event whose subscribers will be mentioned.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="settings">The settings of the guild containing the scheduled event</param>
|
/// <param name="data">The data of the guild containing the scheduled event.</param>
|
||||||
/// <param name="ct">The cancellation token for this operation.</param>
|
/// <param name="ct">The cancellation token for this operation.</param>
|
||||||
/// <returns>A result containing the string which may or may not have succeeded.</returns>
|
/// <returns>A result containing the string which may or may not have succeeded.</returns>
|
||||||
public async Task<Result<string>> GetEventNotificationMentions(
|
public async Task<Result<string>> GetEventNotificationMentions(
|
||||||
IGuildScheduledEvent scheduledEvent, JsonNode settings, CancellationToken ct = default)
|
IGuildScheduledEvent scheduledEvent, GuildData data, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
var role = GuildSettings.EventNotificationRole.Get(settings);
|
var role = GuildSettings.EventNotificationRole.Get(data.Settings);
|
||||||
var subscribersResult = await _eventApi.GetGuildScheduledEventUsersAsync(
|
var subscribersResult = await _eventApi.GetGuildScheduledEventUsersAsync(
|
||||||
scheduledEvent.GuildID, scheduledEvent.ID, withMember: true, ct: ct);
|
scheduledEvent.GuildID, scheduledEvent.ID, ct: ct);
|
||||||
if (!subscribersResult.IsDefined(out var subscribers))
|
if (!subscribersResult.IsDefined(out var subscribers))
|
||||||
{
|
{
|
||||||
return Result<string>.FromError(subscribersResult);
|
return Result<string>.FromError(subscribersResult);
|
||||||
|
@ -181,7 +181,7 @@ public sealed class UtilityService : IHostedService
|
||||||
}
|
}
|
||||||
|
|
||||||
builder = subscribers.Where(
|
builder = subscribers.Where(
|
||||||
subscriber => subscriber.GuildMember.IsDefined(out var member) && !member.Roles.Contains(role))
|
subscriber => !data.GetOrCreateMemberData(subscriber.User.ID).Roles.Contains(role.Value))
|
||||||
.Aggregate(builder, (current, subscriber) => current.Append($"{Mention.User(subscriber.User)} "));
|
.Aggregate(builder, (current, subscriber) => current.Append($"{Mention.User(subscriber.User)} "));
|
||||||
return builder.ToString();
|
return builder.ToString();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue