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;
+ }
+ }
+}