diff --git a/Refresh.GameServer/Endpoints/Game/AnnouncementEndpoints.cs b/Refresh.GameServer/Endpoints/Game/AnnouncementEndpoints.cs new file mode 100644 index 00000000..e0f3b314 --- /dev/null +++ b/Refresh.GameServer/Endpoints/Game/AnnouncementEndpoints.cs @@ -0,0 +1,104 @@ +using System.Text; +using System.Xml.Serialization; +using Bunkum.Core; +using Bunkum.Core.Endpoints; +using Bunkum.Core.Endpoints.Debugging; +using Bunkum.Core.Serialization; +using Bunkum.Listener.Protocol; +using Refresh.GameServer.Authentication; +using Refresh.GameServer.Configuration; +using Refresh.GameServer.Database; +using Refresh.GameServer.Types.Notifications; +using Refresh.GameServer.Types.Roles; +using Refresh.GameServer.Types.UserData; + +namespace Refresh.GameServer.Endpoints.Game; + +public class AnnouncementEndpoints : EndpointGroup +{ + private static string AnnounceGetNotifications(GameDatabaseContext database, GameUser user, GameServerConfig config) + { + List notifications = database.GetNotificationsByUser(user, 5, 0).Items.ToList(); + int count = database.GetNotificationCountByUser(user); + if (count == 0) return string.Empty; + + string s = count != 1 ? "s" : string.Empty; + + string notificationText = $"Howdy, {user.Username}. You have {count} notification{s}:\n\n"; + for (int i = 0; i < notifications.Count; i++) + { + GameNotification notification = notifications[i]; + notificationText += $" {notification.Title} ({i + 1}/{count}):\n" + + $" {notification.Text}\n\n"; + } + + notificationText += $"To view more, or clear these notifications, you can visit the website at {config.WebExternalUrl}!\n"; + + return notificationText; + } + + private static string AnnounceGetAnnouncements(GameDatabaseContext database) + { + IEnumerable announcements = database.GetAnnouncements(); + // it's time to allocate + return announcements.Aggregate(string.Empty, (current, announcement) => current + $"{announcement.Title}: {announcement.Text}\n"); + } + + [GameEndpoint("announce")] + [MinimumRole(GameUserRole.Restricted)] + public string Announce(RequestContext context, GameServerConfig config, GameUser user, GameDatabaseContext database, Token token) + { + if (user.Role == GameUserRole.Restricted) + { + return "Your account is currently in restricted mode.\n\n" + + "You can still play, but you won't be able to publish levels, post comments," + + "or otherwise interact with the community." + + "For more information, please contact an administrator."; + } + + string announcements = AnnounceGetAnnouncements(database); + + // All games except PSP support real-time notifications. + // If we're not playing on PSP, move forward to check for notifications. + if (token.TokenGame != TokenGame.LittleBigPlanetPSP) return announcements; + + string notifications = AnnounceGetNotifications(database, user, config); + + if (announcements.Length == 0) return notifications; + if (notifications.Length == 0) return announcements; + return announcements + "\n" + notifications; // I HATE IT WHYYYYYYYYYYYY + } + + [GameEndpoint("notification", ContentType.Xml)] + [MinimumRole(GameUserRole.Restricted)] + [DebugResponseBody] + public string Notification(RequestContext context, GameServerConfig config, GameUser user, GameDatabaseContext database) + { + DatabaseList notifications = database.GetNotificationsByUser(user, 3, 0); + // ReSharper disable once LoopCanBeConvertedToQuery (makes it unreadable) + + using MemoryStream ms = new(); + using BunkumXmlTextWriter bunkumXmlTextWriter = new(ms); + + XmlSerializer serializer = new(typeof(SerializedNotification)); + + XmlSerializerNamespaces namespaces = new(); + namespaces.Add("", ""); + + foreach (GameNotification notification in notifications.Items) + { + SerializedNotification serializedNotification = new() + { + Text = $"[{config.InstanceName}] {notification.Title}: {notification.Text}", + }; + + serializer.Serialize(bunkumXmlTextWriter, serializedNotification, namespaces); + database.DeleteNotification(notification); + } + + ms.Seek(0, SeekOrigin.Begin); + using StreamReader reader = new(ms); + + return reader.ReadToEnd(); + } +} \ No newline at end of file diff --git a/Refresh.GameServer/Endpoints/Game/Handshake/WelcomeEndpoints.cs b/Refresh.GameServer/Endpoints/Game/Handshake/WelcomeEndpoints.cs index 1a096477..970fddf6 100644 --- a/Refresh.GameServer/Endpoints/Game/Handshake/WelcomeEndpoints.cs +++ b/Refresh.GameServer/Endpoints/Game/Handshake/WelcomeEndpoints.cs @@ -1,10 +1,7 @@ using Bunkum.Core; using Bunkum.Core.Endpoints; using Refresh.GameServer.Configuration; -using Refresh.GameServer.Database; -using Refresh.GameServer.Types.Notifications; using Refresh.GameServer.Types.Roles; -using Refresh.GameServer.Types.UserData; namespace Refresh.GameServer.Endpoints.Game.Handshake; @@ -33,52 +30,4 @@ public string License(RequestContext context, GameServerConfig config) { return config.LicenseText + "\n\n" + AGPLLicense + "\n"; } - - private static string AnnounceGetNotifications(GameDatabaseContext database, GameUser user, GameServerConfig config) - { - List notifications = database.GetNotificationsByUser(user, 5, 0).Items.ToList(); - int count = database.GetNotificationCountByUser(user); - if (count == 0) return ""; - - string s = count != 1 ? "s" : ""; - - string notificationText = $"Howdy, {user.Username}. You have {count} notification{s}:\n\n"; - for (int i = 0; i < notifications.Count; i++) - { - GameNotification notification = notifications[i]; - notificationText += $" {notification.Title} ({i + 1}/{count}):\n" + - $" {notification.Text}\n\n"; - } - - notificationText += $"To view more, or clear these notifications, you can visit the website at {config.WebExternalUrl}!\n"; - - return notificationText; - } - - private static string AnnounceGetAnnouncements(GameDatabaseContext database) - { - IEnumerable announcements = database.GetAnnouncements(); - // it's time to allocate - return announcements.Aggregate("", (current, announcement) => current + $"{announcement.Title}: {announcement.Text}\n"); - } - - [GameEndpoint("announce")] - [MinimumRole(GameUserRole.Restricted)] - public string Announce(RequestContext context, GameServerConfig config, GameUser user, GameDatabaseContext database) - { - if (user.Role == GameUserRole.Restricted) - { - return "Your account is currently in restricted mode.\n\n" + - "You can still play, but you won't be able to publish levels, post comments," + - "or otherwise interact with the community." + - "For more information, please contact an administrator."; - } - - string announcements = AnnounceGetAnnouncements(database); - string notifications = AnnounceGetNotifications(database, user, config); - - if (announcements.Length == 0) return notifications; - if (notifications.Length == 0) return announcements; - return announcements + "\n" + notifications; // I HATE IT WHYYYYYYYYYYYY - } } \ No newline at end of file diff --git a/Refresh.GameServer/RefreshGameServer.cs b/Refresh.GameServer/RefreshGameServer.cs index 3118d872..699ea89a 100644 --- a/Refresh.GameServer/RefreshGameServer.cs +++ b/Refresh.GameServer/RefreshGameServer.cs @@ -5,6 +5,7 @@ using Bunkum.Core.Authentication; using Bunkum.Core.Configuration; using Bunkum.Core.RateLimit; +using Bunkum.Core.Services; using Bunkum.Core.Storage; using Bunkum.HealthChecks; using Bunkum.Protocols.Http; @@ -149,6 +150,10 @@ protected virtual void SetupServices() if (this._config!.TrackRequestStatistics) this._server.AddService(); + + #if DEBUG + this._server.AddService(); + #endif } protected virtual void SetupWorkers() diff --git a/Refresh.GameServer/Types/Notifications/SerializedNotification.cs b/Refresh.GameServer/Types/Notifications/SerializedNotification.cs new file mode 100644 index 00000000..b496b38d --- /dev/null +++ b/Refresh.GameServer/Types/Notifications/SerializedNotification.cs @@ -0,0 +1,13 @@ +using System.Xml.Serialization; + +namespace Refresh.GameServer.Types.Notifications; + +#nullable disable + +[XmlType("notification")] +[XmlRoot("notification")] +public class SerializedNotification +{ + [XmlAttribute("type")] public string Type { get; set; } = "moderationNotification"; + [XmlElement("text")] public string Text { get; set; } +} \ No newline at end of file