diff --git a/GW2SDK.Tests/Features/Guilds/GuildLog.cs b/GW2SDK.Tests/Features/Guilds/GuildLog.cs index 9c95b74bb..35b44fc2f 100644 --- a/GW2SDK.Tests/Features/Guilds/GuildLog.cs +++ b/GW2SDK.Tests/Features/Guilds/GuildLog.cs @@ -36,6 +36,19 @@ public async Task Can_be_found() case InfluenceActivity influenceActivity: Assert.True(influenceActivity.Activity.IsDefined()); break; + case GuildMission guildMissionActivity: + Assert.True(guildMissionActivity.State.IsDefined()); + if (guildMissionActivity.State == GuildMissionState.Start) + { + Assert.NotEmpty(guildMissionActivity.User); + } + else + { + Assert.Empty(guildMissionActivity.User); + } + + Assert.Equal(0, guildMissionActivity.Influence); + break; } } ); diff --git a/GW2SDK/Features/Guilds/Logs/GuildLogEntryJson.cs b/GW2SDK/Features/Guilds/Logs/GuildLogEntryJson.cs index 2eddc8964..a3902ab55 100644 --- a/GW2SDK/Features/Guilds/Logs/GuildLogEntryJson.cs +++ b/GW2SDK/Features/Guilds/Logs/GuildLogEntryJson.cs @@ -21,6 +21,8 @@ public static GuildLogEntry GetGuildLogEntry(this JsonElement json) return json.GetMemberJoined(); case "kick": return json.GetMemberKicked(); + case "mission": + return json.GetGuildMission(); case "motd": return json.GetNewMessageOfTheDay(); case "rank_change": diff --git a/GW2SDK/Features/Guilds/Logs/GuildMission.cs b/GW2SDK/Features/Guilds/Logs/GuildMission.cs new file mode 100644 index 000000000..2485ad96c --- /dev/null +++ b/GW2SDK/Features/Guilds/Logs/GuildMission.cs @@ -0,0 +1,17 @@ +namespace GuildWars2.Guilds.Logs; + +/// A log entry about a started or ended guild mission. +[PublicAPI] +[DataTransferObject] +public sealed record GuildMission : GuildLogEntry +{ + /// The ID of the user who started the mission. + /// Can be empty. + public required string User { get; init; } + + /// The state to which the mission transitioned. + public required Extensible State { get; init; } + + /// The amount of guild influence awarded. + public required int Influence { get; init; } +} diff --git a/GW2SDK/Features/Guilds/Logs/GuildMissionJson.cs b/GW2SDK/Features/Guilds/Logs/GuildMissionJson.cs new file mode 100644 index 000000000..f92679494 --- /dev/null +++ b/GW2SDK/Features/Guilds/Logs/GuildMissionJson.cs @@ -0,0 +1,60 @@ +using System.Text.Json; +using GuildWars2.Json; + +namespace GuildWars2.Guilds.Logs; + +internal static class GuildMissionJson +{ + public static GuildMission GetGuildMission(this JsonElement json) + { + RequiredMember id = "id"; + RequiredMember time = "time"; + RequiredMember state = "state"; + RequiredMember influence = "influence"; + OptionalMember user = "user"; + + foreach (var member in json.EnumerateObject()) + { + if (member.NameEquals("type")) + { + if (!member.Value.ValueEquals("mission")) + { + ThrowHelper.ThrowInvalidDiscriminator(member.Value.GetString()); + } + } + else if (id.Match(member)) + { + id = member; + } + else if (time.Match(member)) + { + time = member; + } + else if (state.Match(member)) + { + state = member; + } + else if (influence.Match(member)) + { + influence = member; + } + else if (user.Match(member)) + { + user = member; + } + else if (JsonOptions.MissingMemberBehavior == MissingMemberBehavior.Error) + { + ThrowHelper.ThrowUnexpectedMember(member.Name); + } + } + + return new GuildMission + { + Id = id.Map(static value => value.GetInt32()), + Time = time.Map(static value => value.GetDateTimeOffset()), + User = user.Map(static value => value.GetString()) ?? "", + State = state.Map(static value => value.GetEnum()), + Influence = influence.Map(static value => value.GetInt32()) + }; + } +} diff --git a/GW2SDK/Features/Guilds/Logs/GuildMissionState.cs b/GW2SDK/Features/Guilds/Logs/GuildMissionState.cs new file mode 100644 index 000000000..ac1a390fd --- /dev/null +++ b/GW2SDK/Features/Guilds/Logs/GuildMissionState.cs @@ -0,0 +1,15 @@ +namespace GuildWars2.Guilds.Logs; + +/// The guild mission state transitions. +[PublicAPI] +public enum GuildMissionState +{ + /// Logged when the mission starts. + Start = 1, + + /// Logged when the mission ends successfully. + Success, + + /// Logged when the mission ends unsuccessfully. + Fail +}