-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathEventRelay.cs
More file actions
103 lines (94 loc) · 4.62 KB
/
Copy pathEventRelay.cs
File metadata and controls
103 lines (94 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
using Microsoft.Extensions.DependencyInjection;
using RustPlusBot.Abstractions.Events;
using RustPlusBot.Features.Connections.Listening;
using RustPlusBot.Features.Events.Classifying;
using RustPlusBot.Features.Events.Posting;
using RustPlusBot.Features.Events.Rendering;
using RustPlusBot.Features.Events.State;
using RustPlusBot.Features.Workspace.Locating;
using RustPlusBot.Persistence.Workspace;
namespace RustPlusBot.Features.Events.Relaying;
/// <summary>Bundles the channel/chat collaborators injected into <see cref="EventRelay"/>.</summary>
/// <param name="Locator">Resolves the #events Discord channel id.</param>
/// <param name="Poster">Posts embeds to the Discord channel.</param>
/// <param name="TeamChatSender">Broadcasts the in-game team-chat line.</param>
internal sealed record EventRelayChannels(
IEventChannelLocator Locator,
IEventChannelPoster Poster,
IBotTeamChatSender TeamChatSender);
/// <summary>Posts every live event to #events AND in-game team chat; tracks rig state.</summary>
/// <param name="classifier">Classifies raw marker deltas into domain events.</param>
/// <param name="state">Tracks active markers and recent events per server.</param>
/// <param name="renderer">Renders events as embeds and in-game lines.</param>
/// <param name="channels">Bundles the channel/chat collaborators.</param>
/// <param name="rigStore">Tracks oil-rig state (Apply on Activated).</param>
/// <param name="scopeFactory">Opens scopes to read guild culture.</param>
internal sealed class EventRelay(
MarkerEventClassifier classifier,
EventStateStore state,
EventEmbedRenderer renderer,
EventRelayChannels channels,
RigStateStore rigStore,
IServiceScopeFactory scopeFactory)
{
/// <summary>Handles one <see cref="MapMarkersChangedEvent"/>: updates state, posts embeds, broadcasts in-game.</summary>
/// <param name="evt">The marker delta.</param>
/// <param name="cancellationToken">A cancellation token.</param>
/// <returns>A task that completes when the delta has been processed.</returns>
public async Task RelayAsync(MapMarkersChangedEvent evt, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(evt);
var events = classifier.Classify(evt);
state.Apply(evt, events);
if (events.Count == 0)
{
return;
}
var culture = await GetCultureAsync(evt.GuildId, cancellationToken).ConfigureAwait(false);
var channelId = await channels.Locator.GetChannelIdAsync(evt.GuildId, evt.ServerId, cancellationToken)
.ConfigureAwait(false);
foreach (var e in events)
{
await channels.TeamChatSender
.SendAsync(evt.GuildId, evt.ServerId, renderer.RenderLine(e, culture), cancellationToken)
.ConfigureAwait(false);
if (channelId is { } id)
{
await channels.Poster.PostAsync(id, renderer.Render(e, culture), cancellationToken)
.ConfigureAwait(false);
}
}
}
/// <summary>Handles one <see cref="RigStateChangedEvent"/>: applies activation, posts an embed, broadcasts in-game.</summary>
/// <param name="evt">The rig boundary event.</param>
/// <param name="cancellationToken">A cancellation token.</param>
/// <returns>A task that completes when the rig event has been processed.</returns>
public async Task RelayRigAsync(RigStateChangedEvent evt, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(evt);
if (evt.Kind == RigEventKind.Activated)
{
rigStore.Apply(evt);
}
var culture = await GetCultureAsync(evt.GuildId, cancellationToken).ConfigureAwait(false);
await channels.TeamChatSender
.SendAsync(evt.GuildId, evt.ServerId, renderer.RenderRigLine(evt, culture), cancellationToken)
.ConfigureAwait(false);
var channelId = await channels.Locator.GetChannelIdAsync(evt.GuildId, evt.ServerId, cancellationToken)
.ConfigureAwait(false);
if (channelId is { } id)
{
await channels.Poster.PostAsync(id, renderer.RenderRig(evt, culture), cancellationToken)
.ConfigureAwait(false);
}
}
private async Task<string> GetCultureAsync(ulong guildId, CancellationToken cancellationToken)
{
var scope = scopeFactory.CreateAsyncScope();
await using (scope.ConfigureAwait(false))
{
var store = scope.ServiceProvider.GetRequiredService<IWorkspaceStore>();
return await store.GetCultureAsync(guildId, cancellationToken).ConfigureAwait(false);
}
}
}