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.

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