.setstream and .setactivity will now pause .ropl

This commit is contained in:
Toastie (DCS Team) 2024-12-01 00:43:53 +13:00
parent a21c7d2ab8
commit dfd5b7a823
Signed by: toastie_t0ast
GPG key ID: 27F3B6855AFD40A4
5 changed files with 122 additions and 104 deletions

View file

@ -6,7 +6,7 @@ namespace EllieBot.Modules.Administration;
public partial class Administration
{
[Group]
public partial class PlayingRotateCommands : EllieModule<PlayingRotateService>
public partial class PlayingRotateCommands : EllieModule<IBotActivityService>
{
[Cmd]
[OwnerOnly]

View file

@ -5,67 +5,28 @@ using EllieBot.Db.Models;
namespace EllieBot.Modules.Administration.Services;
public sealed class PlayingRotateService : IEService, IReadyExecutor
public sealed class BotActivityService : IBotActivityService, IReadyExecutor, IEService
{
private readonly BotConfigService _bss;
private readonly SelfService _selfService;
private readonly TypedKey<ActivityPubData> _activitySetKey = new("activity.set");
private readonly IReplacementService _repService;
// private readonly Replacer _rep;
private readonly DbService _db;
private readonly IPubSub _pubSub;
private readonly DiscordSocketClient _client;
private readonly DbService _db;
private readonly IReplacementService _rep;
private readonly BotConfigService _bss;
public PlayingRotateService(
public BotActivityService(
IPubSub pubSub,
DiscordSocketClient client,
DbService db,
BotConfigService bss,
IEnumerable<IPlaceholderProvider> phProviders,
SelfService selfService,
IReplacementService repService)
IReplacementService rep,
BotConfigService bss)
{
_db = db;
_bss = bss;
_selfService = selfService;
_repService = repService;
_pubSub = pubSub;
_client = client;
}
public async Task OnReadyAsync()
{
if (_client.ShardId != 0)
return;
using var timer = new PeriodicTimer(TimeSpan.FromMinutes(1));
var index = 0;
while (await timer.WaitForNextTickAsync())
{
try
{
if (!_bss.Data.RotateStatuses)
continue;
IReadOnlyList<RotatingPlayingStatus> rotatingStatuses;
await using (var uow = _db.GetDbContext())
{
rotatingStatuses = uow.Set<RotatingPlayingStatus>().AsNoTracking().OrderBy(x => x.Id).ToList();
}
if (rotatingStatuses.Count == 0)
continue;
var playingStatus = index >= rotatingStatuses.Count
? rotatingStatuses[index = 0]
: rotatingStatuses[index++];
var statusText = await _repService.ReplaceAsync(playingStatus.Status, new(client: _client));
await _selfService.SetActivityAsync(statusText, (ActivityType)playingStatus.Type);
}
catch (Exception ex)
{
Log.Warning(ex, "Rotating playing status errored: {ErrorMessage}", ex.Message);
}
}
_db = db;
_rep = rep;
_bss = bss;
}
public async Task<string> RemovePlayingAsync(int index)
@ -116,4 +77,91 @@ public sealed class PlayingRotateService : IEService, IReadyExecutor
using var uow = _db.GetDbContext();
return uow.Set<RotatingPlayingStatus>().AsNoTracking().ToList();
}
public Task SetActivityAsync(string game, ActivityType? type)
=> _pubSub.Pub(_activitySetKey,
new()
{
Name = game,
Link = null,
Type = type
});
public Task SetStreamAsync(string name, string link)
=> _pubSub.Pub(_activitySetKey,
new()
{
Name = name,
Link = link,
Type = ActivityType.Streaming
});
private sealed class ActivityPubData
{
public string Name { get; init; }
public string Link { get; init; }
public ActivityType? Type { get; init; }
}
public async Task OnReadyAsync()
{
await _pubSub.Sub(_activitySetKey,
async data =>
{
if (_client.ShardId == 0)
{
DisableRotatePlaying();
}
try
{
if (data.Type is { } activityType)
{
await _client.SetGameAsync(data.Name, data.Link, activityType);
}
else
{
await _client.SetCustomStatusAsync(data.Name);
}
}
catch (Exception ex)
{
Log.Warning(ex, "Error setting activity");
}
});
if (_client.ShardId != 0)
return;
using var timer = new PeriodicTimer(TimeSpan.FromMinutes(1));
var index = 0;
while (await timer.WaitForNextTickAsync())
{
try
{
if (!_bss.Data.RotateStatuses)
continue;
IReadOnlyList<RotatingPlayingStatus> rotatingStatuses;
await using (var uow = _db.GetDbContext())
{
rotatingStatuses = uow.Set<RotatingPlayingStatus>().AsNoTracking().OrderBy(x => x.Id).ToList();
}
if (rotatingStatuses.Count == 0)
continue;
var playingStatus = index >= rotatingStatuses.Count
? rotatingStatuses[index = 0]
: rotatingStatuses[index++];
var statusText = await _rep.ReplaceAsync(playingStatus.Status, new(client: _client));
await SetActivityAsync(statusText, (ActivityType)playingStatus.Type);
}
catch (Exception ex)
{
Log.Warning(ex, "Rotating playing status errored: {ErrorMessage}", ex.Message);
}
}
}
}

View file

@ -0,0 +1,14 @@
#nullable disable
using EllieBot.Db.Models;
namespace EllieBot.Modules.Administration.Services;
public interface IBotActivityService
{
Task SetActivityAsync(string game, ActivityType? type);
Task SetStreamAsync(string name, string link);
bool ToggleRotatePlaying();
Task AddPlaying(ActivityType statusType, string status);
Task<string> RemovePlayingAsync(int index);
IReadOnlyList<RotatingPlayingStatus> GetRotatingStatuses();
}

View file

@ -24,19 +24,22 @@ public partial class Administration
private readonly IMarmaladeLoaderService _marmaladeLoader;
private readonly ICoordinator _coord;
private readonly DbService _db;
private readonly IBotActivityService _bas;
public SelfCommands(
DiscordSocketClient client,
DbService db,
IBotStrings strings,
ICoordinator coord,
IMarmaladeLoaderService marmaladeLoader)
IMarmaladeLoaderService marmaladeLoader,
IBotActivityService bas)
{
_client = client;
_db = db;
_strings = strings;
_coord = coord;
_marmaladeLoader = marmaladeLoader;
_bas = bas;
}
@ -496,7 +499,7 @@ public partial class Administration
// var rep = new ReplacementBuilder().WithDefault(Context).Build();
var repCtx = new ReplacementContext(ctx);
await _service.SetActivityAsync(game is null ? game : await repSvc.ReplaceAsync(game, repCtx), type);
await _bas.SetActivityAsync(game is null ? game : await repSvc.ReplaceAsync(game, repCtx), type);
await Response().Confirm(strs.set_activity).SendAsync();
}
@ -518,7 +521,7 @@ public partial class Administration
{
name ??= "";
await _service.SetStreamAsync(name, url);
await _bas.SetStreamAsync(name, url);
await Response().Confirm(strs.set_stream).SendAsync();
}

View file

@ -28,7 +28,6 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
private readonly IMessageSenderService _sender;
//keys
private readonly TypedKey<ActivityPubData> _activitySetKey;
private readonly TypedKey<string> _guildLeaveKey;
public SelfService(
@ -51,11 +50,8 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
_bss = bss;
_pubSub = pubSub;
_sender = sender;
_activitySetKey = new("activity.set");
_guildLeaveKey = new("guild.leave");
HandleStatusChanges();
_pubSub.Sub(_guildLeaveKey,
async input =>
{
@ -394,49 +390,6 @@ public sealed class SelfService : IExecNoCommand, IReadyExecutor, IEService
return channelId is not null;
}
private void HandleStatusChanges()
=> _pubSub.Sub(_activitySetKey,
async data =>
{
try
{
if (data.Type is { } activityType)
await _client.SetGameAsync(data.Name, data.Link, activityType);
else
await _client.SetCustomStatusAsync(data.Name);
}
catch (Exception ex)
{
Log.Warning(ex, "Error setting activity");
}
});
public Task SetActivityAsync(string game, ActivityType? type)
=> _pubSub.Pub(_activitySetKey,
new()
{
Name = game,
Link = null,
Type = type
});
public Task SetStreamAsync(string name, string link)
=> _pubSub.Pub(_activitySetKey,
new()
{
Name = name,
Link = link,
Type = ActivityType.Streaming
});
private sealed class ActivityPubData
{
public string Name { get; init; }
public string Link { get; init; }
public ActivityType? Type { get; init; }
}
/// <summary>
/// Adds the specified <paramref name="users"/> to the database. If a database user with placeholder name
/// and discriminator is present in <paramref name="users"/>, their name and discriminator get updated accordingly.