From 6a361ed674221c90a4edb8ed6b6c25a64b0f1d3f Mon Sep 17 00:00:00 2001 From: Daenges <57369924+Daenges@users.noreply.github.com> Date: Fri, 6 Aug 2021 08:25:46 +0200 Subject: [PATCH] Integration of the Mojang API (#1709) * Add Mojang API integration * Addition in MinecraftClient.csproj * Move Mojang API to Protocol namespace * Add changes of MinecraftClient.csproj * Add rate limit warning * Improve rate limit warning --- MinecraftClient/MinecraftClient.csproj | 1 + MinecraftClient/Protocol/MojangAPI.cs | 146 +++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 MinecraftClient/Protocol/MojangAPI.cs diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index e4bfa040..c1bb260b 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -75,6 +75,7 @@ + diff --git a/MinecraftClient/Protocol/MojangAPI.cs b/MinecraftClient/Protocol/MojangAPI.cs new file mode 100644 index 00000000..bafbb6db --- /dev/null +++ b/MinecraftClient/Protocol/MojangAPI.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Net; + +/// !!! ATTENTION !!! +/// By using these functions you agree to the ToS of the Mojang API. +/// You should note that all public APIs are rate limited so you are expected to cache the results. +/// This is currently set at 600 requests per 10 minutes but this may change. +/// !!! ATTENTION !!! + +namespace MinecraftClient.Protocol +{ + /// + /// Provides methods to easily interact with the Mojang API. + /// + public static class MojangAPI + { + // Initialize webclient for all functions + private static readonly WebClient wc = new WebClient(); + + // Can be removed in newer C# versions. + // Replace with DateTimeOffset.FromUnixTimeMilliseconds() + /// + /// Converts a Unix time to a normal Datetime + /// + /// A unix timestamp as double + /// Datetime of unix timestamp + private static DateTime unixTimeStampToDateTime(double unixTimeStamp) + { + // Unix timestamp is seconds past epoch + DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + dateTime = dateTime.AddMilliseconds(unixTimeStamp).ToLocalTime(); + return dateTime; + } + // Can be removed in newer C# versions. + + /// + /// Obtain the UUID of a Player through its name + /// + /// Playername + /// UUID as string + public static string NameToUuid(string name) + { + try + { + return Json.ParseJson(wc.DownloadString("https://api.mojang.com/users/profiles/minecraft/" + name)).Properties["id"].StringValue; + } + catch (Exception) { return string.Empty; } + } + + /// + /// Obtain the Name of a player through its UUID + /// + /// UUID of a player + /// Players UUID + public static string UuidToCurrentName(string uuid) + { + // Perform web request + try + { + var nameChanges = Json.ParseJson(wc.DownloadString("https://api.mojang.com/user/profiles/" + uuid + "/names")).DataArray; + + // Names are sorted from past to most recent. We need to get the last name in the list + return nameChanges[nameChanges.Count - 1].Properties["name"].StringValue; + } + catch (Exception) { return string.Empty; } + } + + /// + /// Get the name history from a UUID + /// + /// UUID of a player + /// Name history, as a dictionary + public static Dictionary UuidToNameHistory(string uuid) + { + Dictionary tempDict = new Dictionary(); + List jsonDataList; + + // Perform web request + try + { + jsonDataList = Json.ParseJson(wc.DownloadString("https://api.mojang.com/user/profiles/" + uuid + "/names")).DataArray; + } + catch (Exception) { return tempDict; } + + foreach (Json.JSONData jsonData in jsonDataList) + { + if (jsonData.Properties.Count > 1) + { + // Time is saved as long in the Unix format. + // Convert it to normal time, before adding it to the dictionary. + // + // !! FromUnixTimeMilliseconds does not exist in the current version. !! + // DateTimeOffset creationDate = DateTimeOffset.FromUnixTimeMilliseconds(Convert.ToInt64(jsonData.Properties["changedToAt"].StringValue)); + // + + // Workaround for converting Unix time to normal time + DateTimeOffset creationDate = unixTimeStampToDateTime(Convert.ToDouble(jsonData.Properties["changedToAt"].StringValue)); + + // Add Keyvaluepair to dict. + tempDict.Add(jsonData.Properties["name"].StringValue, creationDate.DateTime); + } + // The first entry does not contain a change date. + else if (jsonData.Properties.Count > 0) + { + // Add an undefined time to it. + tempDict.Add(jsonData.Properties["name"].StringValue, new DateTime()); + } + } + + return tempDict; + } + + /// + /// Get the Mojang API status + /// + /// Dictionary of the Mojang services + public static Dictionary GetMojangServiceStatus() + { + Dictionary tempDict = new Dictionary(); + List jsonDataList; + + // Perform web request + try + { + jsonDataList = Json.ParseJson(wc.DownloadString("https://status.mojang.com/check")).DataArray; + } + catch (Exception) { return tempDict; } + + // Convert JSONData to string and parse it to a dictionary. + foreach (Json.JSONData jsonData in jsonDataList) + { + if (jsonData.Properties.Count > 0) + { + foreach (KeyValuePair keyValuePair in jsonData.Properties) + { + // Service name to status + tempDict.Add(keyValuePair.Key, keyValuePair.Value.StringValue); + } + } + } + + return tempDict; + } + } +}