From 45fc01820b15352022bf352eea49936810a229ea Mon Sep 17 00:00:00 2001 From: Alex Macocian Date: Mon, 12 Aug 2024 12:22:42 +0200 Subject: [PATCH] Handle explicit party search list requests Closes #76 --- GuildWarsPartySearch.Bot/main.cpp | 20 +++-- GuildWarsPartySearch/Endpoints/LiveFeed.cs | 17 ++-- .../Endpoints/PostPartySearch.cs | 83 ++++++++++--------- .../Models/Endpoints/LiveFeedRequest.cs | 12 +++ .../Endpoints/PostPartySearchRequest.cs | 3 + .../Endpoints/PostPartySearchResponse.cs | 10 ++- 6 files changed, 92 insertions(+), 53 deletions(-) create mode 100644 GuildWarsPartySearch/Models/Endpoints/LiveFeedRequest.cs diff --git a/GuildWarsPartySearch.Bot/main.cpp b/GuildWarsPartySearch.Bot/main.cpp index 51b0b2a..3260678 100644 --- a/GuildWarsPartySearch.Bot/main.cpp +++ b/GuildWarsPartySearch.Bot/main.cpp @@ -218,6 +218,14 @@ static int send_websocket(const std::string& payload) { return 0; } +static int send_ping() { + connect_websocket(); + LogInfo("Sending ping"); + last_websocket_message = time_get_ms(); + ws->sendPing(); + return 0; +} + static int send_party_advertisements() { std::vector ads; for (const auto& ad : party_search_advertisements) { @@ -436,8 +444,6 @@ static easywsclient::WebSocket::pointer connect_websocket() { static int main_bot(void* param) { - load_configuration(); - CallbackEntry_Init(&EventType_WorldMapLeave_entry, on_map_left, NULL); RegisterEvent(EventType_WorldMapLeave, &EventType_WorldMapLeave_entry); @@ -455,7 +461,9 @@ static int main_bot(void* param) CallbackEntry_Init(&EventType_PartySearchType_entry, update_party_search_advertisement, NULL); RegisterEvent(EventType_PartySearchType, &EventType_PartySearchType_entry); - + + load_configuration(); + wait_until_ingame(); while (running) { @@ -466,8 +474,10 @@ static int main_bot(void* param) party_advertisements_pending = false; } if (ws) { - if (time_get_ms() - last_websocket_message > 30000) - send_websocket("ping"); + if (time_get_ms() - last_websocket_message > 30000) { + send_ping(); + + } ws->dispatch(on_websocket_message); ws->poll(); } diff --git a/GuildWarsPartySearch/Endpoints/LiveFeed.cs b/GuildWarsPartySearch/Endpoints/LiveFeed.cs index c0152a9..0663a91 100644 --- a/GuildWarsPartySearch/Endpoints/LiveFeed.cs +++ b/GuildWarsPartySearch/Endpoints/LiveFeed.cs @@ -3,14 +3,11 @@ using GuildWarsPartySearch.Server.Services.PartySearch; using System.Core.Extensions; using System.Extensions; -using System.Text; namespace GuildWarsPartySearch.Server.Endpoints; -public sealed class LiveFeed : WebSocketRouteBase +public sealed class LiveFeed : WebSocketRouteBase { - private readonly static byte[] PongAnswer = Encoding.UTF8.GetBytes("pong"); - private readonly IPartySearchService partySearchService; private readonly ILiveFeedService liveFeedService; private readonly ILogger logger; @@ -25,12 +22,18 @@ public LiveFeed( this.logger = logger.ThrowIfNull(); } - public override async Task ExecuteAsync(TextContent? content, CancellationToken cancellationToken) + public override async Task ExecuteAsync(LiveFeedRequest? message, CancellationToken cancellationToken) { - if (content?.Text?.Equals("ping", StringComparison.OrdinalIgnoreCase) is true) + if (message?.GetFullList is not true) { - await this.WebSocket!.SendAsync(PongAnswer, System.Net.WebSockets.WebSocketMessageType.Text, true, cancellationToken); + return; } + + var searches = await this.partySearchService.GetAllPartySearches(cancellationToken); + await this.SendMessage(new PartySearchList + { + Searches = searches + }, cancellationToken); } public override async Task SocketAccepted(CancellationToken cancellationToken) diff --git a/GuildWarsPartySearch/Endpoints/PostPartySearch.cs b/GuildWarsPartySearch/Endpoints/PostPartySearch.cs index a1d7b7b..ab05f29 100644 --- a/GuildWarsPartySearch/Endpoints/PostPartySearch.cs +++ b/GuildWarsPartySearch/Endpoints/PostPartySearch.cs @@ -76,10 +76,10 @@ public override async Task ExecuteAsync(PostPartySearchRequest? message, Cancell await this.botStatusService.RecordBotUpdateActivity(userAgent, this.Context.RequestAborted); var result = await this.partySearchService.PostPartySearch(message, cancellationToken); - var response = result.Switch( - onSuccess: _ => + var response = await result.Switch>( + onSuccess: async _ => { - this.liveFeedService.PushUpdate(new PartySearch + await this.liveFeedService.PushUpdate(new PartySearch { Map = message?.Map, District = message?.District ?? 0, @@ -90,7 +90,14 @@ public override async Task ExecuteAsync(PostPartySearchRequest? message, Cancell return e; }).ToList(), }, cancellationToken); - return Success; + + var response = Success.Result; + if (message?.GetFullList is true) + { + response.PartySearches = await this.partySearchService.GetAllPartySearches(cancellationToken); + } + + return response; }, onFailure: failure => failure switch { @@ -120,105 +127,105 @@ public override async Task ExecuteAsync(PostPartySearchRequest? message, Cancell } } - private static PostPartySearchResponse Success => new() + private static Task Success => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Posted entries" - }; + }); - private static PostPartySearchResponse InvalidPayload => new() + private static Task InvalidPayload => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid payload" - }; + }); - private static PostPartySearchResponse InvalidMap => new() + private static Task InvalidMap => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid map" - }; + }); - private static PostPartySearchResponse InvalidEntries => new() + private static Task InvalidEntries => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid entries" - }; + }); - private static PostPartySearchResponse InvalidSender => new() + private static Task InvalidSender => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid sender" - }; + }); - private static PostPartySearchResponse InvalidMessage => new() + private static Task InvalidMessage => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid message" - }; + }); - private static PostPartySearchResponse InvalidDistrictRegion => new() + private static Task InvalidDistrictRegion => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid district region" - }; + }); - private static PostPartySearchResponse InvalidDistrictLanguage => new() + private static Task InvalidDistrictLanguage => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid district language" - }; + }); - private static PostPartySearchResponse InvalidDistrictNumber => new() + private static Task InvalidDistrictNumber => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid district number" - }; + }); - private static PostPartySearchResponse InvalidPartyId => new() + private static Task InvalidPartyId => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid party id" - }; + }); - private static PostPartySearchResponse InvalidHeroCount => new() + private static Task InvalidHeroCount => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid hero count" - }; + }); - private static PostPartySearchResponse InvalidHardMode => new() + private static Task InvalidHardMode => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid hard mode" - }; + }); - private static PostPartySearchResponse InvalidSearchType => new() + private static Task InvalidSearchType => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid search type" - }; + }); - private static PostPartySearchResponse InvalidPrimary => new() + private static Task InvalidPrimary => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid primary" - }; + }); - private static PostPartySearchResponse InvalidSecondary => new() + private static Task InvalidSecondary => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid secondary" - }; + }); - private static PostPartySearchResponse InvalidLevel => new() + private static Task InvalidLevel => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Invalid level" - }; + }); - private static PostPartySearchResponse UnspecifiedFailure => new() + private static Task UnspecifiedFailure => Task.FromResult(new PostPartySearchResponse { Result = 0, Description = "Unspecified failure" - }; + }); } diff --git a/GuildWarsPartySearch/Models/Endpoints/LiveFeedRequest.cs b/GuildWarsPartySearch/Models/Endpoints/LiveFeedRequest.cs new file mode 100644 index 0000000..4932fe4 --- /dev/null +++ b/GuildWarsPartySearch/Models/Endpoints/LiveFeedRequest.cs @@ -0,0 +1,12 @@ +using GuildWarsPartySearch.Server.Attributes; +using GuildWarsPartySearch.Server.Converters; +using System.Text.Json.Serialization; + +namespace GuildWarsPartySearch.Server.Models.Endpoints; + +[WebSocketConverter, LiveFeedRequest>] +public sealed class LiveFeedRequest +{ + [JsonPropertyName("full_list")] + public bool GetFullList { get; set; } +} diff --git a/GuildWarsPartySearch/Models/Endpoints/PostPartySearchRequest.cs b/GuildWarsPartySearch/Models/Endpoints/PostPartySearchRequest.cs index 8e64c17..193419c 100644 --- a/GuildWarsPartySearch/Models/Endpoints/PostPartySearchRequest.cs +++ b/GuildWarsPartySearch/Models/Endpoints/PostPartySearchRequest.cs @@ -8,6 +8,9 @@ namespace GuildWarsPartySearch.Server.Models.Endpoints; [WebSocketConverter, PostPartySearchRequest>] public sealed class PostPartySearchRequest { + [JsonPropertyName("full_list")] + public bool GetFullList { get; set; } + [JsonPropertyName("map_id")] public Map? Map { get; set; } diff --git a/GuildWarsPartySearch/Models/Endpoints/PostPartySearchResponse.cs b/GuildWarsPartySearch/Models/Endpoints/PostPartySearchResponse.cs index 77db8e5..9ec12d6 100644 --- a/GuildWarsPartySearch/Models/Endpoints/PostPartySearchResponse.cs +++ b/GuildWarsPartySearch/Models/Endpoints/PostPartySearchResponse.cs @@ -1,15 +1,19 @@ using GuildWarsPartySearch.Server.Attributes; using GuildWarsPartySearch.Server.Converters; -using Newtonsoft.Json; +using System.Text.Json.Serialization; namespace GuildWarsPartySearch.Server.Models.Endpoints; [WebSocketConverter, PostPartySearchResponse>] public sealed class PostPartySearchResponse { - [JsonProperty(nameof(Result))] + [JsonPropertyName(nameof(Result))] public int Result { get; set; } - [JsonProperty(nameof(Description))] + [JsonPropertyName(nameof(Description))] public string? Description { get; set; } + + [JsonPropertyName(nameof(PartySearches))] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public List? PartySearches { get; set; } }