You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
5.8 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using IPA.JsonConverters;
  5. using IPA.Utilities;
  6. using Newtonsoft.Json;
  7. using Newtonsoft.Json.Linq;
  8. using SemVer;
  9. using Version = SemVer.Version;
  10. namespace IPA.Updating.BeatMods
  11. {
  12. #if BeatSaber
  13. class ApiEndpoint
  14. {
  15. public const string BeatModBase = "https://beatmods.com";
  16. public const string ApiBase = BeatModBase + "/api/v1/mod";
  17. public const string GetModInfoEndpoint = "?name={0}&version={1}";
  18. public const string GetModsByName = "?name={0}";
  19. class HexArrayConverter : JsonConverter
  20. {
  21. public override bool CanConvert(Type objectType)
  22. {
  23. return objectType == typeof(byte[]);
  24. }
  25. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  26. {
  27. if (reader.TokenType == JsonToken.Null)
  28. {
  29. return null;
  30. }
  31. if (reader.TokenType == JsonToken.String)
  32. {
  33. try
  34. {
  35. return Utils.StringToByteArray((string)reader.Value);
  36. }
  37. catch (Exception ex)
  38. {
  39. throw new Exception($"Error parsing version string: {reader.Value}", ex);
  40. }
  41. }
  42. throw new Exception(
  43. $"Unexpected token or value when parsing hex string. Token: {reader.TokenType}, Value: {reader.Value}");
  44. }
  45. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  46. {
  47. if (value == null)
  48. {
  49. writer.WriteNull();
  50. }
  51. else
  52. {
  53. if (!(value is byte[]))
  54. {
  55. throw new JsonSerializationException("Expected byte[] object value");
  56. }
  57. writer.WriteValue(Utils.ByteArrayToString((byte[]) value));
  58. }
  59. }
  60. }
  61. class ModMultiformatJsonConverter : JsonConverter<Mod>
  62. {
  63. public override Mod ReadJson(JsonReader reader, Type objectType, Mod existingValue, bool hasExistingValue, JsonSerializer serializer)
  64. {
  65. if (reader.TokenType == JsonToken.String)
  66. return new Mod { Id = reader.Value as string, IsIdReference = true };
  67. else
  68. {
  69. if (reader.TokenType != JsonToken.StartObject)
  70. return null;
  71. return serializer.Deserialize<Mod>(reader);
  72. }
  73. }
  74. public override void WriteJson(JsonWriter writer, Mod value, JsonSerializer serializer) => serializer.Serialize(writer, value);
  75. }
  76. [Serializable]
  77. public class Mod
  78. {
  79. #pragma warning disable CS0649
  80. /// <summary>
  81. /// Will be a useless string of characters. Do not use.
  82. /// </summary>
  83. [JsonProperty("_id")]
  84. public string Id;
  85. [JsonIgnore]
  86. public bool IsIdReference = false;
  87. [JsonProperty("required")]
  88. public bool Required;
  89. [JsonProperty("name")]
  90. public string Name;
  91. [JsonProperty("version"),
  92. JsonConverter(typeof(SemverVersionConverter))]
  93. public Version Version;
  94. [JsonProperty("gameVersion"),
  95. JsonConverter(typeof(JsonConverters.AlmostVersionConverter))]
  96. public AlmostVersion GameVersion;
  97. [Serializable]
  98. public class AuthorType
  99. {
  100. [JsonProperty("username")]
  101. public string Name;
  102. [JsonProperty("_id")]
  103. public string Id;
  104. public override string ToString() => Name;
  105. }
  106. [JsonProperty("author")]
  107. public AuthorType Author;
  108. [JsonProperty("status")]
  109. public string Status;
  110. public const string ApprovedStatus = "approved";
  111. [JsonProperty("description")]
  112. public string Description;
  113. [JsonProperty("category")]
  114. public string Category;
  115. [JsonProperty("link")]
  116. public Uri Link;
  117. #pragma warning restore CS0649
  118. [Serializable]
  119. public class DownloadsObject
  120. {
  121. public const string TypeUniversal = "universal";
  122. public const string TypeSteam = "steam";
  123. public const string TypeOculus = "oculus";
  124. [JsonProperty("type")]
  125. public string Type;
  126. [JsonProperty("url")]
  127. public string Path;
  128. [Serializable]
  129. public class HashObject
  130. {
  131. [JsonProperty("hash"), JsonConverter(typeof(HexArrayConverter))]
  132. public byte[] Hash;
  133. [JsonProperty("file")]
  134. public string File;
  135. }
  136. /// <summary>
  137. /// Hashes stored are MD5
  138. /// </summary>
  139. [JsonProperty("hashMd5")]
  140. public HashObject[] Hashes;
  141. }
  142. [JsonProperty("downloads")]
  143. public DownloadsObject[] Downloads;
  144. [JsonProperty("dependencies", ItemConverterType = typeof(ModMultiformatJsonConverter))]
  145. public Mod[] Dependencies;
  146. public override string ToString()
  147. {
  148. return $"{{\"{Name}\"v{Version} by {Author} files for {string.Join(", ", Downloads.Select(d => d.Type))}}}";
  149. }
  150. }
  151. }
  152. #endif
  153. }