mcdiscordbot/MinecraftDiscordBot/Models/Message.cs

125 lines
4.8 KiB
C#
Raw Normal View History

2022-01-10 16:10:32 +01:00
using Discord.WebSocket;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
2022-01-10 16:10:32 +01:00
namespace MinecraftDiscordBot.Models;
2022-01-10 16:10:32 +01:00
public abstract class Message {
public static Message Deserialize(string strMessage) {
var obj = JObject.Parse(strMessage);
var typeName = GetKey<string>(obj, "type");
if (!Parsers.TryGetValue(typeName, out var type))
throw new FormatException($"Unknown message type '{typeName}'!");
if (obj.ToObject(type) is not Message message)
throw new FormatException($"Message cannot be casted to '{type}'!");
return message;
}
private static readonly Dictionary<string, Type> Parsers = GetMessageTypes();
private static Dictionary<string, Type> GetMessageTypes() {
var types = new Dictionary<string, Type>();
var messageTypes =
AppDomain.CurrentDomain.GetAssemblies().SelectMany(domainAssembly => domainAssembly.GetTypes())
.Where(typeof(Message).IsAssignableFrom);
foreach (var type in messageTypes)
if (GetTypeAttribute(type) is MessageTypeAttribute attr)
types.Add(attr.Name, type);
return types;
}
private static MessageTypeAttribute? GetTypeAttribute(Type type)
=> type.GetCustomAttributes(typeof(MessageTypeAttribute), false).OfType<MessageTypeAttribute>().FirstOrDefault();
private static T GetKey<T>(JObject msg, string key)
=> (msg.TryGetValue(key, out var type) ? type : throw new FormatException($"Message has no '{key}' param!"))
.ToObject<T>() ?? throw new FormatException($"'{key}' param is not of expected type '{typeof(T).Name}'!");
2022-01-10 16:10:32 +01:00
[JsonProperty("type")]
public abstract string Type { get; }
}
[MessageType(TYPE)]
public class CapabilityMessage : Message {
private const string TYPE = "roles";
public override string Type => TYPE;
[JsonProperty("role", Required = Required.Always)]
public string[] Role { get; set; } = default!;
}
[MessageType(TYPE)]
public class ReplyMessage : Message {
private const string TYPE = "reply";
public override string Type => TYPE;
[JsonProperty("id", Required = Required.Always)]
public int AnswerId { get; set; }
[JsonProperty("result", Required = Required.Always)]
public string Result { get; set; } = default!;
[JsonProperty("chunk", Required = Required.DisallowNull)]
public int Chunk { get; set; } = 1;
[JsonProperty("total", Required = Required.DisallowNull)]
public int Total { get; set; } = 1;
[JsonProperty("success", Required = Required.DisallowNull)]
public ResultState State { get; set; } = ResultState.Successful;
}
public abstract class EventMessage : Message { }
[MessageType(TYPE)]
public class PeripheralDetachEvent : EventMessage {
private const string TYPE = "peripheral_detach";
public override string Type => TYPE;
[JsonProperty("side", Required = Required.Always)]
public string Side { get; set; } = default!;
}
[MessageType(TYPE)]
public class PeripheralAttachEvent : EventMessage {
private const string TYPE = "peripheral";
public override string Type => TYPE;
[JsonIgnore]
public string Side => Peripheral.Side;
[JsonProperty("peripheral", Required = Required.Always)]
public Peripheral Peripheral { get; set; } = default!;
}
public class Peripheral {
[JsonProperty("side", Required = Required.Always)]
public string Side { get; set; } = default!;
[JsonProperty("type", Required = Required.Always)]
public string Type { get; set; } = default!;
[JsonProperty("methods", Required = Required.Always)]
public string[] Methods { get; set; } = default!;
}
[MessageType(TYPE)]
public class ChatEvent : EventMessage {
private const string TYPE = "chat";
public override string Type => TYPE;
[JsonProperty("username", Required = Required.Always)]
public string Username { get; set; } = default!;
[JsonProperty("message", Required = Required.Always)]
public string Message { get; set; } = default!;
[JsonProperty("uuid", Required = Required.Always)]
public string UUID { get; set; } = default!;
[JsonProperty("hidden", Required = Required.Always)]
public bool IsHidden { get; set; }
}
[MessageType(TYPE)]
public class RequestMessage : Message {
private const string TYPE = "request";
public override string Type => TYPE;
public RequestMessage(int answerId, string method, Dictionary<string, object>? parameters = null) {
AnswerId = answerId;
Method = method;
Parameters = (parameters ?? Enumerable.Empty<KeyValuePair<string, object>>())
.ToDictionary(i => i.Key, i => i.Value);
}
[JsonProperty("id")]
public int AnswerId { get; set; }
[JsonProperty("method")]
public string Method { get; set; }
[JsonProperty("params")]
public Dictionary<string, object> Parameters { get; }
}