-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAlarmEmbedRenderer.cs
More file actions
112 lines (101 loc) · 5.26 KB
/
Copy pathAlarmEmbedRenderer.cs
File metadata and controls
112 lines (101 loc) · 5.26 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
104
105
106
107
108
109
110
111
112
using System.Globalization;
using Discord;
using RustPlusBot.Abstractions.Connections;
using RustPlusBot.Domain.Alarms;
using RustPlusBot.Localization;
namespace RustPlusBot.Features.Alarms.Rendering;
/// <summary>Renders a Smart Alarm as a Discord embed + control row, and the pairing-prompt embed + row. Pure.</summary>
/// <param name="localizer">The alarm localizer.</param>
internal sealed class AlarmEmbedRenderer(ILocalizer localizer)
{
/// <summary>Renders the alarm embed and its control buttons.</summary>
/// <param name="alarm">The alarm to render.</param>
/// <param name="unreachable">When true the alarm entity is currently unreachable.</param>
/// <param name="culture">The guild culture (BCP-47 primary tag).</param>
/// <returns>The embed and the component rows.</returns>
public (Embed Embed, MessageComponent Components) RenderAlarm(SmartAlarm alarm, bool unreachable, string culture)
{
ArgumentNullException.ThrowIfNull(alarm);
string statusKey;
#pragma warning disable IDE0045 // Collapsing to a nested ternary trips RCS1238/S3358 (nested conditional); the if/else chain is intentional.
if (alarm.Reachability == DeviceReachability.Removed)
{
statusKey = "alarm.status.removed";
}
else if (alarm.Reachability == DeviceReachability.NoPrivilege)
{
statusKey = "alarm.status.noprivilege";
}
else if (alarm.Reachability == DeviceReachability.NoResponse)
{
statusKey = "alarm.status.noresponse";
}
else if (unreachable)
{
statusKey = "alarm.status.unreachable";
}
else if (alarm.LastIsActive)
{
statusKey = "alarm.status.active";
}
else
{
statusKey = "alarm.status.armed";
}
#pragma warning restore IDE0045
// Removed and NoPrivilege disable controls (device is gone or locked); NoResponse leaves them enabled
// so the user can still interact while the device is temporarily unresponsive.
var blocked = alarm.Reachability is DeviceReachability.Removed or DeviceReachability.NoPrivilege;
var disableButtons = unreachable || blocked;
// <t:unix:R> is Discord's native relative timestamp — clients render "x minutes ago" and keep
// it updating live, so the embed never shows a stale duration between re-renders.
var triggered = alarm.LastTriggeredUtc is { } t
? localizer.Get("alarm.embed.lasttriggered", culture,
string.Create(CultureInfo.InvariantCulture, $"<t:{t.ToUnixTimeSeconds()}:R>"))
: localizer.Get("alarm.embed.nevertriggered", culture);
var embed = new EmbedBuilder()
.WithTitle(alarm.Name)
.WithDescription($"{localizer.Get(statusKey, culture)}\n{triggered}")
.WithFooter(localizer.Get("alarm.embed.footer", culture, alarm.EntityId))
.Build();
var tail = $"{alarm.ServerId}:{alarm.EntityId}";
var pingKey = alarm.PingEveryone ? "alarm.button.ping.on" : "alarm.button.ping.off";
var relayKey = alarm.RelayToTeamChat ? "alarm.button.relay.on" : "alarm.button.relay.off";
var components = new ComponentBuilder()
.WithButton(localizer.Get(pingKey, culture), AlarmComponentIds.PingTogglePrefix + tail,
alarm.PingEveryone ? ButtonStyle.Success : ButtonStyle.Secondary, disabled: disableButtons)
.WithButton(localizer.Get(relayKey, culture), AlarmComponentIds.RelayTogglePrefix + tail,
alarm.RelayToTeamChat ? ButtonStyle.Success : ButtonStyle.Secondary, disabled: disableButtons)
.WithButton(localizer.Get("alarm.button.refresh", culture), AlarmComponentIds.RefreshPrefix + tail,
ButtonStyle.Primary, disabled: disableButtons)
.WithButton(localizer.Get("alarm.button.rename", culture), AlarmComponentIds.RenamePrefix + tail,
ButtonStyle.Secondary, disabled: disableButtons)
.Build();
return (embed, components);
}
/// <summary>Renders the transient "New alarm detected — Add it?" prompt.</summary>
/// <param name="serverId">The server id.</param>
/// <param name="entityId">The entity id.</param>
/// <param name="defaultName">The generated default name.</param>
/// <param name="culture">The guild culture (BCP-47 primary tag).</param>
/// <returns>The prompt embed and Accept/Dismiss row.</returns>
public (Embed Embed, MessageComponent Components) RenderPrompt(
Guid serverId,
ulong entityId,
string defaultName,
string culture)
{
var embed = new EmbedBuilder()
.WithTitle(localizer.Get("alarm.prompt.title", culture))
.WithDescription(localizer.Get("alarm.prompt.body", culture, defaultName))
.Build();
var tail = $"{serverId}:{entityId}";
var components = new ComponentBuilder()
.WithButton(localizer.Get("alarm.prompt.accept", culture), AlarmComponentIds.AcceptPrefix + tail,
ButtonStyle.Success)
.WithButton(localizer.Get("alarm.prompt.dismiss", culture), AlarmComponentIds.DismissPrefix + tail,
ButtonStyle.Secondary)
.Build();
return (embed, components);
}
}