From 823c490def9e8a6bce521b27eaa30cc2610971bd Mon Sep 17 00:00:00 2001 From: Albie Date: Mon, 1 Aug 2022 12:27:54 +0100 Subject: [PATCH 1/5] move geolocation to services --- .../Accounts/UbisoftAccountExtensions.cs | 6 ------ .../Entities => Services/Geolocation}/Geolocation.cs | 2 +- .../Requests/UbisoftSelfGeolocationRequest.cs} | 10 ++++++++-- 3 files changed, 9 insertions(+), 9 deletions(-) rename DragonFruit.Six.Api/{Accounts/Entities => Services/Geolocation}/Geolocation.cs (96%) rename DragonFruit.Six.Api/{Accounts/Requests/UbisoftGeolocationRequest.cs => Services/Geolocation/Requests/UbisoftSelfGeolocationRequest.cs} (65%) diff --git a/DragonFruit.Six.Api/Accounts/UbisoftAccountExtensions.cs b/DragonFruit.Six.Api/Accounts/UbisoftAccountExtensions.cs index 1ab64c3d..bf467fad 100644 --- a/DragonFruit.Six.Api/Accounts/UbisoftAccountExtensions.cs +++ b/DragonFruit.Six.Api/Accounts/UbisoftAccountExtensions.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using DragonFruit.Data; using DragonFruit.Six.Api.Accounts.Entities; using DragonFruit.Six.Api.Accounts.Enums; using DragonFruit.Six.Api.Accounts.Requests; @@ -66,10 +65,5 @@ public static Task> GetAccou var request = new UbisoftAccountActivityRequest(accounts); return client.PerformAsync(request).ContinueWith(t => t.Result.DeserializeUbisoftAccountActivity()); } - - /// - /// Get the current device location based on a IP Geolocation lookup - /// - public static Task GeolocateAsync(this ApiClient client) => client.PerformAsync(new UbisoftGeolocationRequest()); } } diff --git a/DragonFruit.Six.Api/Accounts/Entities/Geolocation.cs b/DragonFruit.Six.Api/Services/Geolocation/Geolocation.cs similarity index 96% rename from DragonFruit.Six.Api/Accounts/Entities/Geolocation.cs rename to DragonFruit.Six.Api/Services/Geolocation/Geolocation.cs index 05cd1ea5..e371bd99 100644 --- a/DragonFruit.Six.Api/Accounts/Entities/Geolocation.cs +++ b/DragonFruit.Six.Api/Services/Geolocation/Geolocation.cs @@ -4,7 +4,7 @@ using System; using Newtonsoft.Json; -namespace DragonFruit.Six.Api.Accounts.Entities +namespace DragonFruit.Six.Api.Services.Geolocation { [Serializable] public class Geolocation diff --git a/DragonFruit.Six.Api/Accounts/Requests/UbisoftGeolocationRequest.cs b/DragonFruit.Six.Api/Services/Geolocation/Requests/UbisoftSelfGeolocationRequest.cs similarity index 65% rename from DragonFruit.Six.Api/Accounts/Requests/UbisoftGeolocationRequest.cs rename to DragonFruit.Six.Api/Services/Geolocation/Requests/UbisoftSelfGeolocationRequest.cs index 8d2393ba..302c154e 100644 --- a/DragonFruit.Six.Api/Accounts/Requests/UbisoftGeolocationRequest.cs +++ b/DragonFruit.Six.Api/Services/Geolocation/Requests/UbisoftSelfGeolocationRequest.cs @@ -6,9 +6,15 @@ using DragonFruit.Data.Requests; using DragonFruit.Six.Api.Enums; -namespace DragonFruit.Six.Api.Accounts.Requests +namespace DragonFruit.Six.Api.Services.Geolocation.Requests { - public class UbisoftGeolocationRequest : ApiRequest, IRequestExecutingCallback + /// + /// Creates a request to get the approximate location of the current user-agent + /// + /// + /// While this endpoint does not require authentication, a valid Ubi-AppId header will be attached + /// + public class UbisoftSelfGeolocationRequest : ApiRequest, IRequestExecutingCallback { public override string Path => $"{Endpoints.BaseEndpoint}/v2/profiles/me/iplocation"; From 54d9f0a21ef6a0b81d05eb66a293d9fecbb18957 Mon Sep 17 00:00:00 2001 From: Albie Date: Mon, 1 Aug 2022 12:28:10 +0100 Subject: [PATCH 2/5] add own extensions and add request listed in #321 --- .../Geolocation/GeolocationExtensions.cs | 47 +++++++++++++++++++ .../Requests/UbisoftGeolocationRequest.cs | 25 ++++++++++ 2 files changed, 72 insertions(+) create mode 100644 DragonFruit.Six.Api/Services/Geolocation/GeolocationExtensions.cs create mode 100644 DragonFruit.Six.Api/Services/Geolocation/Requests/UbisoftGeolocationRequest.cs diff --git a/DragonFruit.Six.Api/Services/Geolocation/GeolocationExtensions.cs b/DragonFruit.Six.Api/Services/Geolocation/GeolocationExtensions.cs new file mode 100644 index 00000000..584f76d6 --- /dev/null +++ b/DragonFruit.Six.Api/Services/Geolocation/GeolocationExtensions.cs @@ -0,0 +1,47 @@ +// Dragon6 API Copyright DragonFruit Network +// Licensed under Apache-2. Refer to the LICENSE file for more info + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using DragonFruit.Data; +using DragonFruit.Six.Api.Services.Geolocation.Requests; +using Newtonsoft.Json.Linq; + +namespace DragonFruit.Six.Api.Services.Geolocation +{ + public static class GeolocationExtensions + { + /// + /// Get the current device location based on a IP Geolocation lookup + /// + public static Task GeolocateAsync(this ApiClient client) => client.PerformAsync(new UbisoftSelfGeolocationRequest()); + + /// + /// Get the approximate location and ISP info for a collection of IP addresses + /// + /// The to use + /// A collection of IP addresses to lookup + /// An containing the IP addresses and their approximate location + public static async Task> GeolocateAsync(this Dragon6Client client, params string[] ips) + { + var request = new UbisoftGeolocationRequest(ips); + var container = await client.PerformAsync(request).ConfigureAwait(false); + + return container["ipLocations"]?.ToObject() ?? Array.Empty(); + } + + /// + /// Get the approximate location and ISP info for a collection of IP addresses + /// + /// The to use + /// A collection of IP addresses to lookup + /// An containing the IP addresses and their approximate location + public static Task> GeolocateAsync(this Dragon6Client client, params IPAddress[] ips) + { + return GeolocateAsync(client, ips.Select(x => x.ToString()).ToArray()); + } + } +} diff --git a/DragonFruit.Six.Api/Services/Geolocation/Requests/UbisoftGeolocationRequest.cs b/DragonFruit.Six.Api/Services/Geolocation/Requests/UbisoftGeolocationRequest.cs new file mode 100644 index 00000000..a558f0a5 --- /dev/null +++ b/DragonFruit.Six.Api/Services/Geolocation/Requests/UbisoftGeolocationRequest.cs @@ -0,0 +1,25 @@ +// Dragon6 API Copyright DragonFruit Network +// Licensed under Apache-2. Refer to the LICENSE file for more info + +using System.Collections.Generic; +using DragonFruit.Data; +using DragonFruit.Data.Parameters; + +namespace DragonFruit.Six.Api.Services.Geolocation.Requests +{ + /// + /// Creates a request to get the approximate location a collection of provided IP addresses + /// + public class UbisoftGeolocationRequest : UbiApiRequest + { + public override string Path => $"{Endpoints.BaseEndpoint}/v2/iplocation"; + + public UbisoftGeolocationRequest(IEnumerable addresses) + { + Addresses = addresses; + } + + [QueryParameter("ips", CollectionConversionMode.Concatenated)] + public IEnumerable Addresses { get; } + } +} From 2b049194b6fdc8cbf399e096051da389daddbbdc Mon Sep 17 00:00:00 2001 From: Albie Date: Mon, 1 Aug 2022 12:36:36 +0100 Subject: [PATCH 3/5] improve formatting --- .../Services/Geolocation/GeolocationExtensions.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/DragonFruit.Six.Api/Services/Geolocation/GeolocationExtensions.cs b/DragonFruit.Six.Api/Services/Geolocation/GeolocationExtensions.cs index 584f76d6..352471f8 100644 --- a/DragonFruit.Six.Api/Services/Geolocation/GeolocationExtensions.cs +++ b/DragonFruit.Six.Api/Services/Geolocation/GeolocationExtensions.cs @@ -7,6 +7,7 @@ using System.Net; using System.Threading.Tasks; using DragonFruit.Data; +using DragonFruit.Data.Serializers.Newtonsoft; using DragonFruit.Six.Api.Services.Geolocation.Requests; using Newtonsoft.Json.Linq; @@ -17,7 +18,10 @@ public static class GeolocationExtensions /// /// Get the current device location based on a IP Geolocation lookup /// - public static Task GeolocateAsync(this ApiClient client) => client.PerformAsync(new UbisoftSelfGeolocationRequest()); + public static Task GeolocateAsync(this T client) where T : ApiClient + { + return client.PerformAsync(new UbisoftSelfGeolocationRequest()); + } /// /// Get the approximate location and ISP info for a collection of IP addresses From 74f00cdfecdb821f56fd5023789bbd001501673f Mon Sep 17 00:00:00 2001 From: Albie Date: Mon, 1 Aug 2022 12:36:49 +0100 Subject: [PATCH 4/5] add better address geolocation tests --- .../Utils/ServiceTests.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/DragonFruit.Six.Api.Tests/Utils/ServiceTests.cs b/DragonFruit.Six.Api.Tests/Utils/ServiceTests.cs index 262345c4..7b4e27ed 100644 --- a/DragonFruit.Six.Api.Tests/Utils/ServiceTests.cs +++ b/DragonFruit.Six.Api.Tests/Utils/ServiceTests.cs @@ -1,8 +1,9 @@ // Dragon6 API Copyright DragonFruit Network // Licensed under Apache-2. Refer to the LICENSE file for more info +using System.Linq; using System.Threading.Tasks; -using DragonFruit.Six.Api.Accounts; +using DragonFruit.Six.Api.Services.Geolocation; using DragonFruit.Six.Api.Services.Status; using NUnit.Framework; @@ -12,7 +13,22 @@ namespace DragonFruit.Six.Api.Tests.Utils public class ServiceTests : Dragon6ApiTest { [Test] - public async Task TestGeolocation() => await Client.GeolocateAsync(); + public async Task TestGeolocation() + { + // test the request works without throwing + // as we don't know who's running this, there's no real way to validate correctness of this part + await Client.GeolocateAsync().ConfigureAwait(false); + + var addressInfo = await Client.GeolocateAsync("8.8.8.8", "172.217.16.238", "194.39.167.145").ConfigureAwait(false); + var addressDirectory = addressInfo.ToDictionary(x => x.IP); + + // google services + Assert.IsTrue(addressDirectory["8.8.8.8"].ServiceProvider == "Google"); + Assert.IsTrue(addressDirectory["172.217.16.238"].ServiceProvider == "Google Servers"); + + // random ip address from UK + Assert.IsTrue(addressDirectory["194.39.167.145"].CountryName == "United Kingdom"); + } [Test] public async Task TestServerStatus() => await Client.GetServerStatusAsync(); From 6473472754a060c028540d24351acba10941897e Mon Sep 17 00:00:00 2001 From: Albie Date: Mon, 1 Aug 2022 12:41:37 +0100 Subject: [PATCH 5/5] add IPv6 address to test --- DragonFruit.Six.Api.Tests/Utils/ServiceTests.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/DragonFruit.Six.Api.Tests/Utils/ServiceTests.cs b/DragonFruit.Six.Api.Tests/Utils/ServiceTests.cs index 7b4e27ed..94efb8f0 100644 --- a/DragonFruit.Six.Api.Tests/Utils/ServiceTests.cs +++ b/DragonFruit.Six.Api.Tests/Utils/ServiceTests.cs @@ -19,15 +19,18 @@ public async Task TestGeolocation() // as we don't know who's running this, there's no real way to validate correctness of this part await Client.GeolocateAsync().ConfigureAwait(false); - var addressInfo = await Client.GeolocateAsync("8.8.8.8", "172.217.16.238", "194.39.167.145").ConfigureAwait(false); + var addressInfo = await Client.GeolocateAsync("8.8.8.8", "172.217.16.238", "194.39.167.145", "2620:119:35::35").ConfigureAwait(false); var addressDirectory = addressInfo.ToDictionary(x => x.IP); // google services - Assert.IsTrue(addressDirectory["8.8.8.8"].ServiceProvider == "Google"); - Assert.IsTrue(addressDirectory["172.217.16.238"].ServiceProvider == "Google Servers"); + Assert.AreEqual("Google", addressDirectory["8.8.8.8"].ServiceProvider); + Assert.AreEqual("Google Servers", addressDirectory["172.217.16.238"].ServiceProvider); + + // IPv6 DNS server + Assert.AreEqual("Cisco OpenDNS, LLC", addressDirectory["2620:119:35::35"].ServiceProvider); // random ip address from UK - Assert.IsTrue(addressDirectory["194.39.167.145"].CountryName == "United Kingdom"); + Assert.AreEqual("United Kingdom", addressDirectory["194.39.167.145"].CountryName); } [Test]