-
-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add alert/notification functionality (for server connection events an…
…d messages)
- 2024.11.29.1-prerelease
- 2024.11.28.1-prerelease
- 2024.11.27.2-prerelease
- 2024.8.16.1-prerelease
- 2024.7.13.1-prerelease
- 2024.7.6.1-prerelease
- 2024.7.4.1-prerelease
- 2024.7.1.1-prerelease
- 2024.6.30.1-prerelease
- 2024.2.12.1-verified
- 2024.2.5.6-prerelease
- 2024.2.5.5-prerelease
- 2023.09.14.2-prerelease
- 2023.09.02.4-prerelease
- 2023.09.02.2-prerelease
- 2023.08.27.3-prerelease
- 2023.08.27.2-prerelease
- 2023.06.10.2-prerelease
- 2023.05.30.2-prerelease
- 2023.05.28.1-prerelease
- 2023.05.15.1-prerelease
- 2023.05.02.2-prerelease
- 2023.04.15.3-prerelease
- 2023.04.09.1-prerelease
- 2023.04.08.3-prerelease
- 2023.03.23.3-prerelease
- 2023.03.23.2-prerelease
- 2023.03.16.1-prerelease
- 2023.01.24.3-prerelease
- 2023.01.24.2-prerelease
- 2023.01.24.1-prerelease
- 2023.01.06.1-prerelease
- 2022.11.04.2-prerelease
- 2022.10.25.2-prerelease
- 2022.10.25.1-prerelease
- 2022.10.24.4-prerelease
- 2022.10.24.3-prerelease
- 2022.10.17.2-prerelease
- 2022.10.13.4-prerelease
- 2022.10.12.1-prerelease
- 2022.09.08.1-prerelease
- 2022.08.26.2-prerelease
- 2022.07.25.1-prerelease
- 2022.07.23.1-prerelease
- 2022.07.20.2-prerelease
- 2022.07.20.1-prerelease
- 2022.07.16.2-prerelease
- 2022.07.13.2-prerelease
- 2022.07.13.1-prerelease
- 2022.07.09.1-prerelease
- 2022.07.06.2-prerelease
- 2022.07.01.1-prerelease
- 2022.06.21.2-prerelease
- 2022.06.21.1-prerelease
- 2022.06.16.4-prerelease
- 2022.06.16.3-prerelease
- 2022.06.16.2-prerelease
- 2022.06.16.1-prerelease
- 2022.06.12.3-prerelease
- 2022.06.12.2-prerelease
- 2022.06.12.1-prerelease
- 2022.06.11.1-prerelease
Showing
16 changed files
with
579 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
using System; | ||
using SharedLibraryCore; | ||
using SharedLibraryCore.Alerts; | ||
using SharedLibraryCore.Database.Models; | ||
|
||
namespace IW4MAdmin.Application.Alerts; | ||
|
||
public static class AlertExtensions | ||
{ | ||
public static Alert.AlertState BuildAlert(this EFClient client, Alert.AlertCategory? type = null) | ||
{ | ||
return new Alert.AlertState | ||
{ | ||
RecipientId = client.ClientId, | ||
Category = type ?? Alert.AlertCategory.Information | ||
}; | ||
} | ||
|
||
public static Alert.AlertState WithCategory(this Alert.AlertState state, Alert.AlertCategory category) | ||
{ | ||
state.Category = category; | ||
return state; | ||
} | ||
|
||
public static Alert.AlertState OfType(this Alert.AlertState state, string type) | ||
{ | ||
state.Type = type; | ||
return state; | ||
} | ||
|
||
public static Alert.AlertState WithMessage(this Alert.AlertState state, string message) | ||
{ | ||
state.Message = message; | ||
return state; | ||
} | ||
|
||
public static Alert.AlertState ExpiresIn(this Alert.AlertState state, TimeSpan expiration) | ||
{ | ||
state.ExpiresAt = DateTime.Now.Add(expiration); | ||
return state; | ||
} | ||
|
||
public static Alert.AlertState FromSource(this Alert.AlertState state, string source) | ||
{ | ||
state.Source = source; | ||
return state; | ||
} | ||
|
||
public static Alert.AlertState FromClient(this Alert.AlertState state, EFClient client) | ||
{ | ||
state.Source = client.Name.StripColors(); | ||
state.SourceId = client.ClientId; | ||
return state; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
using System; | ||
using System.Collections.Concurrent; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using SharedLibraryCore.Alerts; | ||
using SharedLibraryCore.Configuration; | ||
using SharedLibraryCore.Database.Models; | ||
using SharedLibraryCore.Interfaces; | ||
|
||
namespace IW4MAdmin.Application.Alerts; | ||
|
||
public class AlertManager : IAlertManager | ||
{ | ||
private readonly ApplicationConfiguration _appConfig; | ||
private readonly ConcurrentDictionary<int, List<Alert.AlertState>> _states = new(); | ||
private readonly List<Func<Task<IEnumerable<Alert.AlertState>>>> _staticSources = new(); | ||
|
||
public AlertManager(ApplicationConfiguration appConfig) | ||
{ | ||
_appConfig = appConfig; | ||
_states.TryAdd(0, new List<Alert.AlertState>()); | ||
} | ||
|
||
public EventHandler<Alert.AlertState> OnAlertConsumed { get; set; } | ||
|
||
public async Task Initialize() | ||
{ | ||
foreach (var source in _staticSources) | ||
{ | ||
var alerts = await source(); | ||
foreach (var alert in alerts) | ||
{ | ||
AddAlert(alert); | ||
} | ||
} | ||
} | ||
|
||
public IEnumerable<Alert.AlertState> RetrieveAlerts(EFClient client) | ||
{ | ||
lock (_states) | ||
{ | ||
var alerts = Enumerable.Empty<Alert.AlertState>(); | ||
if (client.Level > Data.Models.Client.EFClient.Permission.Trusted) | ||
{ | ||
alerts = alerts.Concat(_states[0].Where(alert => | ||
alert.MinimumPermission is null || alert.MinimumPermission <= client.Level)); | ||
} | ||
|
||
if (_states.ContainsKey(client.ClientId)) | ||
{ | ||
alerts = alerts.Concat(_states[client.ClientId].AsReadOnly()); | ||
} | ||
|
||
return alerts.OrderByDescending(alert => alert.OccuredAt); | ||
} | ||
} | ||
|
||
public void MarkAlertAsRead(Guid alertId) | ||
{ | ||
lock (_states) | ||
{ | ||
foreach (var items in _states.Values) | ||
{ | ||
var matchingEvent = items.FirstOrDefault(item => item.AlertId == alertId); | ||
|
||
if (matchingEvent is null) | ||
{ | ||
continue; | ||
} | ||
|
||
items.Remove(matchingEvent); | ||
OnAlertConsumed?.Invoke(this, matchingEvent); | ||
} | ||
} | ||
} | ||
|
||
public void MarkAllAlertsAsRead(int recipientId) | ||
{ | ||
lock (_states) | ||
{ | ||
foreach (var items in _states.Values) | ||
{ | ||
items.RemoveAll(item => | ||
{ | ||
if (item.RecipientId != null && item.RecipientId != recipientId) | ||
{ | ||
return false; | ||
} | ||
|
||
OnAlertConsumed?.Invoke(this, item); | ||
return true; | ||
}); | ||
} | ||
} | ||
} | ||
|
||
public void AddAlert(Alert.AlertState alert) | ||
{ | ||
lock (_states) | ||
{ | ||
if (alert.RecipientId is null) | ||
{ | ||
_states[0].Add(alert); | ||
return; | ||
} | ||
|
||
if (!_states.ContainsKey(alert.RecipientId.Value)) | ||
{ | ||
_states[alert.RecipientId.Value] = new List<Alert.AlertState>(); | ||
} | ||
|
||
if (_appConfig.MinimumAlertPermissions.ContainsKey(alert.Type)) | ||
{ | ||
alert.MinimumPermission = _appConfig.MinimumAlertPermissions[alert.Type]; | ||
} | ||
|
||
_states[alert.RecipientId.Value].Add(alert); | ||
|
||
PruneOldAlerts(); | ||
} | ||
} | ||
|
||
public void RegisterStaticAlertSource(Func<Task<IEnumerable<Alert.AlertState>>> alertSource) | ||
{ | ||
_staticSources.Add(alertSource); | ||
} | ||
|
||
|
||
private void PruneOldAlerts() | ||
{ | ||
foreach (var value in _states.Values) | ||
{ | ||
value.RemoveAll(item => item.ExpiresAt < DateTime.UtcNow); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.