mirror of
https://github.com/TeamOctolings/Octobot.git
synced 2025-04-20 00:43:36 +03:00
Implement some unused guild configuration options
Signed-off-by: Octol1ttle <l1ttleofficial@outlook.com>
This commit is contained in:
parent
4702d2fcba
commit
635bf26601
5 changed files with 68 additions and 12 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
using Remora.Rest.Core;
|
||||||
|
|
||||||
namespace Boyfriend.Data;
|
namespace Boyfriend.Data;
|
||||||
|
|
||||||
public class MemberData {
|
public class MemberData {
|
||||||
|
@ -8,4 +10,5 @@ public class MemberData {
|
||||||
|
|
||||||
public ulong Id { get; }
|
public ulong Id { get; }
|
||||||
public DateTimeOffset? BannedUntil { get; set; }
|
public DateTimeOffset? BannedUntil { get; set; }
|
||||||
|
public List<Snowflake> Roles { get; set; } = new();
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,3 +288,20 @@ public class GuildScheduledEventDeleteResponder : IResponder<IGuildScheduledEven
|
||||||
guildData.Configuration.EventNotificationChannel.ToDiscordSnowflake(), embeds: new[] { built }, ct: ct);
|
guildData.Configuration.EventNotificationChannel.ToDiscordSnowflake(), embeds: new[] { built }, ct: ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles updating <see cref="MemberData.Roles" /> when a guild member is updated.
|
||||||
|
/// </summary>
|
||||||
|
public class GuildMemberUpdateResponder : IResponder<IGuildMemberUpdate> {
|
||||||
|
private readonly GuildDataService _dataService;
|
||||||
|
|
||||||
|
public GuildMemberUpdateResponder(GuildDataService dataService) {
|
||||||
|
_dataService = dataService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Result> RespondAsync(IGuildMemberUpdate gatewayEvent, CancellationToken ct = default) {
|
||||||
|
var memberData = await _dataService.GetMemberData(gatewayEvent.GuildID, gatewayEvent.User.ID, ct);
|
||||||
|
memberData.Roles = gatewayEvent.Roles.ToList();
|
||||||
|
return Result.FromSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ public class InteractionResponders : InteractionGroup {
|
||||||
/// A button that will output an ephemeral embed containing the information about a scheduled event.
|
/// A button that will output an ephemeral embed containing the information about a scheduled event.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="state">The ID of the guild and scheduled event, encoded as "guildId:eventId".</param>
|
/// <param name="state">The ID of the guild and scheduled event, encoded as "guildId:eventId".</param>
|
||||||
/// <returns>A feedback sending result which may or may not have succeeded.</returns>
|
/// <returns>An ephemeral feedback sending result which may or may not have succeeded.</returns>
|
||||||
[Button("scheduled-event-details")]
|
[Button("scheduled-event-details")]
|
||||||
public async Task<Result> OnStatefulButtonClicked(string? state = null) {
|
public async Task<Result> OnStatefulButtonClicked(string? state = null) {
|
||||||
if (state is null) return Result.FromError(new ArgumentNullError(nameof(state)));
|
if (state is null) return Result.FromError(new ArgumentNullError(nameof(state)));
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using Boyfriend.Data;
|
using Boyfriend.Data;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Remora.Discord.API.Abstractions.Rest;
|
||||||
using Remora.Rest.Core;
|
using Remora.Rest.Core;
|
||||||
|
|
||||||
namespace Boyfriend.Services.Data;
|
namespace Boyfriend.Services.Data;
|
||||||
|
@ -10,9 +12,14 @@ namespace Boyfriend.Services.Data;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GuildDataService : IHostedService {
|
public class GuildDataService : IHostedService {
|
||||||
private readonly Dictionary<Snowflake, GuildData> _datas = new();
|
private readonly Dictionary<Snowflake, GuildData> _datas = new();
|
||||||
|
private readonly IDiscordRestGuildAPI _guildApi;
|
||||||
|
private readonly ILogger<GuildDataService> _logger;
|
||||||
|
|
||||||
// https://github.com/dotnet/aspnetcore/issues/39139
|
// https://github.com/dotnet/aspnetcore/issues/39139
|
||||||
public GuildDataService(IHostApplicationLifetime lifetime) {
|
public GuildDataService(
|
||||||
|
IHostApplicationLifetime lifetime, IDiscordRestGuildAPI guildApi, ILogger<GuildDataService> logger) {
|
||||||
|
_guildApi = guildApi;
|
||||||
|
_logger = logger;
|
||||||
lifetime.ApplicationStopping.Register(ApplicationStopping);
|
lifetime.ApplicationStopping.Register(ApplicationStopping);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +82,11 @@ public class GuildDataService : IHostedService {
|
||||||
await using var dataStream = File.OpenRead(dataPath);
|
await using var dataStream = File.OpenRead(dataPath);
|
||||||
var data = await JsonSerializer.DeserializeAsync<MemberData>(dataStream, cancellationToken: ct);
|
var data = await JsonSerializer.DeserializeAsync<MemberData>(dataStream, cancellationToken: ct);
|
||||||
if (data is null) continue;
|
if (data is null) continue;
|
||||||
|
var memberResult = await _guildApi.GetGuildMemberAsync(guildId, data.Id.ToDiscordSnowflake(), ct);
|
||||||
|
if (memberResult.IsSuccess)
|
||||||
|
data.Roles = memberResult.Entity.Roles.ToList();
|
||||||
|
else
|
||||||
|
_logger.LogWarning("Error in member retrieval.\n{ErrorMessage}", memberResult.Error.Message);
|
||||||
|
|
||||||
memberData.Add(data.Id, data);
|
memberData.Add(data.Id, data);
|
||||||
}
|
}
|
||||||
|
@ -91,9 +103,9 @@ public class GuildDataService : IHostedService {
|
||||||
return (await GetData(guildId, ct)).Configuration;
|
return (await GetData(guildId, ct)).Configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public async Task<MemberData> GetMemberData(Snowflake guildId, Snowflake userId, CancellationToken ct = default) {
|
public async Task<MemberData> GetMemberData(Snowflake guildId, Snowflake userId, CancellationToken ct = default) {
|
||||||
return (await GetData(guildId, ct)).GetMemberData(userId);
|
return (await GetData(guildId, ct)).GetMemberData(userId);
|
||||||
}*/
|
}
|
||||||
|
|
||||||
public IEnumerable<Snowflake> GetGuildIds() {
|
public IEnumerable<Snowflake> GetGuildIds() {
|
||||||
return _datas.Keys;
|
return _datas.Keys;
|
||||||
|
|
|
@ -63,7 +63,9 @@ public class GuildUpdateService : BackgroundService {
|
||||||
/// This method does the following:
|
/// This method does the following:
|
||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
/// <item>Automatically unbans users once their ban period has expired.</item>
|
/// <item>Automatically unbans users once their ban period has expired.</item>
|
||||||
|
/// <item>Automatically grants users the guild's <see cref="GuildConfiguration.DefaultRole"/> if one is set.</item>
|
||||||
/// <item>Sends reminders about an upcoming scheduled event.</item>
|
/// <item>Sends reminders about an upcoming scheduled event.</item>
|
||||||
|
/// <item>Automatically starts scheduled events if <see cref="GuildConfiguration.AutoStartEvents"/> is enabled.</item>
|
||||||
/// <item>Sends scheduled event start notifications.</item>
|
/// <item>Sends scheduled event start notifications.</item>
|
||||||
/// <item>Sends scheduled event completion notifications.</item>
|
/// <item>Sends scheduled event completion notifications.</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
|
@ -73,7 +75,7 @@ public class GuildUpdateService : BackgroundService {
|
||||||
/// Downtime would affect the reliability of notifications and automatic unbans if this logic were to be in a
|
/// Downtime would affect the reliability of notifications and automatic unbans if this logic were to be in a
|
||||||
/// <see cref="IResponder{TGatewayEvent}" />.
|
/// <see cref="IResponder{TGatewayEvent}" />.
|
||||||
/// </item>
|
/// </item>
|
||||||
/// <item>The Discord API doesn't provide necessary about scheduled event updates.</item>
|
/// <item>The Discord API doesn't provide necessary information about scheduled event updates.</item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="guildId">The ID of the guild to update.</param>
|
/// <param name="guildId">The ID of the guild to update.</param>
|
||||||
|
@ -81,16 +83,28 @@ public class GuildUpdateService : BackgroundService {
|
||||||
private async Task TickGuildAsync(Snowflake guildId, CancellationToken ct = default) {
|
private async Task TickGuildAsync(Snowflake guildId, CancellationToken ct = default) {
|
||||||
var data = await _dataService.GetData(guildId, ct);
|
var data = await _dataService.GetData(guildId, ct);
|
||||||
Messages.Culture = data.Culture;
|
Messages.Culture = data.Culture;
|
||||||
|
var defaultRoleSnowflake = data.Configuration.DefaultRole.ToDiscordSnowflake();
|
||||||
|
|
||||||
|
foreach (var memberData in data.MemberData.Values) {
|
||||||
|
var userIdSnowflake = memberData.Id.ToDiscordSnowflake();
|
||||||
|
if (!memberData.Roles.Contains(defaultRoleSnowflake)) {
|
||||||
|
var defaultRoleResult = await _guildApi.AddGuildMemberRoleAsync(
|
||||||
|
guildId, userIdSnowflake, defaultRoleSnowflake, ct: ct);
|
||||||
|
if (!defaultRoleResult.IsSuccess)
|
||||||
|
_logger.LogWarning(
|
||||||
|
"Error in automatic default role add request.\n{ErrorMessage}",
|
||||||
|
defaultRoleResult.Error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
// ReSharper disable once ForeachCanBePartlyConvertedToQueryUsingAnotherGetEnumerator
|
|
||||||
foreach (var memberData in data.MemberData.Values)
|
|
||||||
if (DateTimeOffset.UtcNow > memberData.BannedUntil) {
|
if (DateTimeOffset.UtcNow > memberData.BannedUntil) {
|
||||||
var unbanResult = await _guildApi.RemoveGuildBanAsync(
|
var unbanResult = await _guildApi.RemoveGuildBanAsync(
|
||||||
guildId, memberData.Id.ToDiscordSnowflake(), Messages.PunishmentExpired.EncodeHeader(), ct);
|
guildId, userIdSnowflake, Messages.PunishmentExpired.EncodeHeader(), ct);
|
||||||
if (unbanResult.IsSuccess)
|
if (unbanResult.IsSuccess)
|
||||||
memberData.BannedUntil = null;
|
memberData.BannedUntil = null;
|
||||||
else
|
else
|
||||||
_logger.LogWarning("Error in member data update.\n{ErrorMessage}", unbanResult.Error.Message);
|
_logger.LogWarning(
|
||||||
|
"Error in automatic user unban request.\n{ErrorMessage}", unbanResult.Error.Message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var eventsResult = await _eventApi.ListScheduledEventsForGuildAsync(guildId, ct: ct);
|
var eventsResult = await _eventApi.ListScheduledEventsForGuildAsync(guildId, ct: ct);
|
||||||
|
@ -104,7 +118,17 @@ public class GuildUpdateService : BackgroundService {
|
||||||
} else {
|
} else {
|
||||||
var storedEvent = data.ScheduledEvents[scheduledEvent.ID.Value];
|
var storedEvent = data.ScheduledEvents[scheduledEvent.ID.Value];
|
||||||
if (storedEvent.Status == scheduledEvent.Status) {
|
if (storedEvent.Status == scheduledEvent.Status) {
|
||||||
if (DateTimeOffset.UtcNow
|
if (DateTimeOffset.UtcNow >= scheduledEvent.ScheduledStartTime) {
|
||||||
|
if (scheduledEvent.Status is not GuildScheduledEventStatus.Active) {
|
||||||
|
var startResult = await _eventApi.ModifyGuildScheduledEventAsync(
|
||||||
|
guildId, scheduledEvent.ID,
|
||||||
|
status: GuildScheduledEventStatus.Active, ct: ct);
|
||||||
|
if (!startResult.IsSuccess)
|
||||||
|
_logger.LogWarning(
|
||||||
|
"Error in automatic scheduled event start request.\n{ErrorMessage}",
|
||||||
|
startResult.Error.Message);
|
||||||
|
}
|
||||||
|
} else if (DateTimeOffset.UtcNow
|
||||||
>= scheduledEvent.ScheduledStartTime - data.Configuration.EventEarlyNotificationOffset
|
>= scheduledEvent.ScheduledStartTime - data.Configuration.EventEarlyNotificationOffset
|
||||||
&& !storedEvent.EarlyNotificationSent) {
|
&& !storedEvent.EarlyNotificationSent) {
|
||||||
var earlyResult = await SendScheduledEventUpdatedMessage(scheduledEvent, data, true, ct);
|
var earlyResult = await SendScheduledEventUpdatedMessage(scheduledEvent, data, true, ct);
|
||||||
|
|
Loading…
Add table
Reference in a new issue