Made API models internal. Removed Discord.Net.API.

This commit is contained in:
RogueException
2017-01-01 23:28:42 -04:00
parent dac51db299
commit e2934abe29
244 changed files with 641 additions and 473 deletions

View File

@@ -0,0 +1,8 @@
using System.IO;
namespace Discord.Audio
{
public abstract class AudioInStream : Stream
{
}
}

View File

@@ -15,9 +15,6 @@
<Compile Include="**\*.cs" />
<EmbeddedResource Include="**\*.resx" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Discord.Net.API\Discord.Net.API.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
<PackageReference Include="System.Collections.Concurrent" Version="4.3.0" />

View File

@@ -0,0 +1,9 @@
namespace Discord
{
public enum Direction
{
Before,
After,
Around
}
}

View File

@@ -1,5 +1,4 @@
using Discord.API.Rest;
using System;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

View File

@@ -8,7 +8,7 @@ namespace Discord
public interface IMessageChannel : IChannel
{
/// <summary> Sends a message to this message channel. </summary>
Task<IUserMessage> SendMessageAsync(string text, bool isTTS = false, EmbedBuilder embed = null, RequestOptions options = null);
Task<IUserMessage> SendMessageAsync(string text, bool isTTS = false, Embed embed = null, RequestOptions options = null);
#if NETSTANDARD1_3
/// <summary> Sends a file to this text channel, with an optional caption. </summary>
Task<IUserMessage> SendFileAsync(string filePath, string text = null, bool isTTS = false, RequestOptions options = null);

View File

@@ -1,5 +1,4 @@
using Discord.API.Rest;
using System;
using System;
using System.Threading.Tasks;
namespace Discord

View File

@@ -1,5 +1,4 @@
using Discord.API.Rest;
using Discord.Audio;
using Discord.Audio;
using System;
using System.Threading.Tasks;

View File

@@ -0,0 +1,10 @@
namespace Discord
{
public enum DefaultMessageNotifications
{
/// <summary> By default, all messages will trigger notifications. </summary>
AllMessages = 0,
/// <summary> By default, only mentions will trigger notifications. </summary>
MentionsOnly = 1
}
}

View File

@@ -1,7 +1,5 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Model = Discord.API.Emoji;
namespace Discord
{
@@ -14,7 +12,7 @@ namespace Discord
public bool RequireColons { get; }
public IReadOnlyList<ulong> RoleIds { get; }
private GuildEmoji(ulong id, string name, bool isManaged, bool requireColons, IReadOnlyList<ulong> roleIds)
internal GuildEmoji(ulong id, string name, bool isManaged, bool requireColons, IReadOnlyList<ulong> roleIds)
{
Id = id;
Name = name;
@@ -22,10 +20,6 @@ namespace Discord
RequireColons = requireColons;
RoleIds = roleIds;
}
internal static GuildEmoji Create(Model model)
{
return new GuildEmoji(model.Id.Value, model.Name, model.Managed, model.RequireColons, ImmutableArray.Create(model.Roles));
}
public override string ToString() => Name;
private string DebuggerDisplay => $"{Name} ({Id})";

View File

@@ -1,5 +1,4 @@
using Discord.API.Rest;
using Discord.Audio;
using Discord.Audio;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

View File

@@ -0,0 +1,10 @@
namespace Discord
{
public enum MfaLevel
{
/// <summary> Users have no additional MFA restriction on this guild. </summary>
Disabled = 0,
/// <summary> Users must have MFA enabled on their account to perform administrative actions. </summary>
Enabled = 1
}
}

View File

@@ -0,0 +1,8 @@
namespace Discord
{
public enum PermissionTarget
{
Role,
User
}
}

View File

@@ -0,0 +1,14 @@
namespace Discord
{
public enum VerificationLevel
{
/// <summary> Users have no additional restrictions on sending messages to this guild. </summary>
None = 0,
/// <summary> Users must have a verified email on their account. </summary>
Low = 1,
/// <summary> Users must fulfill the requirements of Low, and be registered on Discord for at least 5 minutes. </summary>
Medium = 2,
/// <summary> Users must fulfill the requirements of Medium, and be a member of this guild for at least 10 minutes. </summary>
High = 3
}
}

View File

@@ -1,6 +1,4 @@
using System.IO;
using Model = Discord.API.Image;
namespace Discord
{
/// <summary>
@@ -30,10 +28,5 @@ namespace Discord
Stream = File.OpenRead(path);
}
#endif
public Model ToModel()
{
return new Model(Stream);
}
}
}

View File

@@ -0,0 +1,62 @@
using System;
using System.Collections.Immutable;
using System.Diagnostics;
namespace Discord
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public class Embed : IEmbed
{
public string Type { get; }
public string Description { get; internal set; }
public string Url { get; internal set; }
public string Title { get; internal set; }
public DateTimeOffset? Timestamp { get; internal set; }
public Color? Color { get; internal set; }
public EmbedImage? Image { get; internal set; }
public EmbedVideo? Video { get; internal set; }
public EmbedAuthor? Author { get; internal set; }
public EmbedFooter? Footer { get; internal set; }
public EmbedProvider? Provider { get; internal set; }
public EmbedThumbnail? Thumbnail { get; internal set; }
public ImmutableArray<EmbedField> Fields { get; internal set; }
internal Embed(string type)
{
Type = type;
Fields = ImmutableArray.Create<EmbedField>();
}
internal Embed(string type,
string title,
string description,
string url,
DateTimeOffset? timestamp,
Color? color,
EmbedImage? image,
EmbedVideo? video,
EmbedAuthor? author,
EmbedFooter? footer,
EmbedProvider? provider,
EmbedThumbnail? thumbnail,
ImmutableArray<EmbedField> fields)
{
Type = type;
Title = title;
Description = description;
Url = url;
Color = color;
Timestamp = timestamp;
Image = image;
Video = video;
Author = author;
Footer = footer;
Provider = provider;
Thumbnail = thumbnail;
Fields = fields;
}
public override string ToString() => Title;
private string DebuggerDisplay => $"{Title} ({Type})";
}
}

View File

@@ -1,27 +1,22 @@
using System.Diagnostics;
using Model = Discord.API.EmbedAuthor;
namespace Discord
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public struct EmbedAuthor
{
public string Name { get; set; }
public string Url { get; set; }
public string IconUrl { get; set; }
public string ProxyIconUrl { get; set; }
public string Name { get; internal set; }
public string Url { get; internal set; }
public string IconUrl { get; internal set; }
public string ProxyIconUrl { get; internal set; }
private EmbedAuthor(string name, string url, string iconUrl, string proxyIconUrl)
internal EmbedAuthor(string name, string url, string iconUrl, string proxyIconUrl)
{
Name = name;
Url = url;
IconUrl = iconUrl;
ProxyIconUrl = proxyIconUrl;
}
internal static EmbedAuthor Create(Model model)
{
return new EmbedAuthor(model.Name, model.Url, model.IconUrl, model.ProxyIconUrl);
}
private string DebuggerDisplay => $"{Name} ({Url})";
public override string ToString() => Name;

View File

@@ -1,208 +0,0 @@
using System;
using System.Collections.Generic;
using Embed = Discord.API.Embed;
using Field = Discord.API.EmbedField;
using Author = Discord.API.EmbedAuthor;
using Footer = Discord.API.EmbedFooter;
using Thumbnail = Discord.API.EmbedThumbnail;
using ImageEmbed = Discord.API.EmbedImage;
namespace Discord
{
public class EmbedBuilder
{
private readonly Embed _model;
private readonly List<Field> _fields;
public EmbedBuilder()
{
_model = new Embed { Type = "rich" };
_fields = new List<Field>();
}
public string Title { get { return _model.Title; } set { _model.Title = value; } }
public string Description { get { return _model.Description; } set { _model.Description = value; } }
public string Url { get { return _model.Url; } set { _model.Url = value; } }
public string ThumbnailUrl { get; set; }
public string ImageUrl { get; set; }
public DateTimeOffset? Timestamp { get; set; }
public Color? Color { get { return _model.Color.HasValue ? new Color(_model.Color.Value) : (Color?)null; } set { _model.Color = value?.RawValue; } }
public EmbedAuthorBuilder Author { get; set; }
public EmbedFooterBuilder Footer { get; set; }
public EmbedBuilder WithTitle(string title)
{
Title = title;
return this;
}
public EmbedBuilder WithDescription(string description)
{
Description = description;
return this;
}
public EmbedBuilder WithUrl(string url)
{
Url = url;
return this;
}
public EmbedBuilder WithThumbnailUrl(string thumbnailUrl)
{
ThumbnailUrl = thumbnailUrl;
return this;
}
public EmbedBuilder WithImageUrl(string imageUrl)
{
ImageUrl = imageUrl;
return this;
}
public EmbedBuilder WithCurrentTimestamp()
{
Timestamp = DateTimeOffset.UtcNow;
return this;
}
public EmbedBuilder WithTimestamp(DateTimeOffset dateTimeOffset)
{
Timestamp = dateTimeOffset;
return this;
}
public EmbedBuilder WithColor(Color color)
{
Color = color;
return this;
}
public EmbedBuilder WithAuthor(EmbedAuthorBuilder author)
{
Author = author;
return this;
}
public EmbedBuilder WithAuthor(Action<EmbedAuthorBuilder> action)
{
var author = new EmbedAuthorBuilder();
action(author);
Author = author;
return this;
}
public EmbedBuilder WithFooter(EmbedFooterBuilder footer)
{
Footer = footer;
return this;
}
public EmbedBuilder WithFooter(Action<EmbedFooterBuilder> action)
{
var footer = new EmbedFooterBuilder();
action(footer);
Footer = footer;
return this;
}
public EmbedBuilder AddField(Action<EmbedFieldBuilder> action)
{
var field = new EmbedFieldBuilder();
action(field);
_fields.Add(field.ToModel());
return this;
}
internal Embed Build()
{
_model.Author = Author?.ToModel();
_model.Footer = Footer?.ToModel();
_model.Timestamp = Timestamp?.ToUniversalTime();
_model.Thumbnail = ThumbnailUrl != null ? new Thumbnail { Url = ThumbnailUrl } : null;
_model.Image = ImageUrl != null ? new ImageEmbed { Url = ImageUrl } : null;
_model.Fields = _fields.ToArray();
return _model;
}
}
public class EmbedFieldBuilder
{
private readonly Field _model;
public string Name { get { return _model.Name; } set { _model.Name = value; } }
public string Value { get { return _model.Value; } set { _model.Value = value; } }
public bool IsInline { get { return _model.Inline; } set { _model.Inline = value; } }
public EmbedFieldBuilder()
{
_model = new Field();
}
public EmbedFieldBuilder WithName(string name)
{
Name = name;
return this;
}
public EmbedFieldBuilder WithValue(string value)
{
Value = value;
return this;
}
public EmbedFieldBuilder WithIsInline(bool isInline)
{
IsInline = isInline;
return this;
}
internal Field ToModel() => _model;
}
public class EmbedAuthorBuilder
{
private readonly Author _model;
public string Name { get { return _model.Name; } set { _model.Name = value; } }
public string Url { get { return _model.Url; } set { _model.Url = value; } }
public string IconUrl { get { return _model.IconUrl; } set { _model.IconUrl = value; } }
public EmbedAuthorBuilder()
{
_model = new Author();
}
public EmbedAuthorBuilder WithName(string name)
{
Name = name;
return this;
}
public EmbedAuthorBuilder WithUrl(string url)
{
Url = url;
return this;
}
public EmbedAuthorBuilder WithIconUrl(string iconUrl)
{
IconUrl = iconUrl;
return this;
}
internal Author ToModel() => _model;
}
public class EmbedFooterBuilder
{
private readonly Footer _model;
public string Text { get { return _model.Text; } set { _model.Text = value; } }
public string IconUrl { get { return _model.IconUrl; } set { _model.IconUrl = value; } }
public EmbedFooterBuilder()
{
_model = new Footer();
}
public EmbedFooterBuilder WithText(string text)
{
Text = text;
return this;
}
public EmbedFooterBuilder WithIconUrl(string iconUrl)
{
IconUrl = iconUrl;
return this;
}
internal Footer ToModel() => _model;
}
}

View File

@@ -1,25 +1,20 @@
using System.Diagnostics;
using Model = Discord.API.EmbedField;
namespace Discord
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public struct EmbedField
{
public string Name { get; set; }
public string Value { get; set; }
public bool Inline { get; set; }
public string Name { get; internal set; }
public string Value { get; internal set; }
public bool Inline { get; internal set; }
private EmbedField(string name, string value, bool inline)
internal EmbedField(string name, string value, bool inline)
{
Name = name;
Value = value;
Inline = inline;
}
internal static EmbedField Create(Model model)
{
return new EmbedField(model.Name, model.Value, model.Inline);
}
private string DebuggerDisplay => $"{Name} ({Value}";
public override string ToString() => Name;

View File

@@ -1,25 +1,20 @@
using System.Diagnostics;
using Model = Discord.API.EmbedFooter;
namespace Discord
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public struct EmbedFooter
{
public string Text { get; set; }
public string IconUrl { get; set; }
public string ProxyUrl { get; set; }
public string Text { get; internal set; }
public string IconUrl { get; internal set; }
public string ProxyUrl { get; internal set; }
private EmbedFooter(string text, string iconUrl, string proxyUrl)
internal EmbedFooter(string text, string iconUrl, string proxyUrl)
{
Text = text;
IconUrl = iconUrl;
ProxyUrl = proxyUrl;
}
internal static EmbedFooter Create(Model model)
{
return new EmbedFooter(model.Text, model.IconUrl, model.ProxyIconUrl);
}
private string DebuggerDisplay => $"{Text} ({IconUrl})";
public override string ToString() => Text;

View File

@@ -1,5 +1,4 @@
using System.Diagnostics;
using Model = Discord.API.EmbedImage;
namespace Discord
{
@@ -11,19 +10,13 @@ namespace Discord
public int? Height { get; }
public int? Width { get; }
private EmbedImage(string url, string proxyUrl, int? height, int? width)
internal EmbedImage(string url, string proxyUrl, int? height, int? width)
{
Url = url;
ProxyUrl = proxyUrl;
Height = height;
Width = width;
}
internal static EmbedImage Create(Model model)
{
return new EmbedImage(model.Url, model.ProxyUrl,
model.Height.IsSpecified ? model.Height.Value : (int?)null,
model.Width.IsSpecified ? model.Width.Value : (int?)null);
}
private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})";
public override string ToString() => Url;

View File

@@ -1,5 +1,4 @@
using System.Diagnostics;
using Model = Discord.API.EmbedProvider;
namespace Discord
{
@@ -9,15 +8,11 @@ namespace Discord
public string Name { get; }
public string Url { get; }
private EmbedProvider(string name, string url)
internal EmbedProvider(string name, string url)
{
Name = name;
Url = url;
}
internal static EmbedProvider Create(Model model)
{
return new EmbedProvider(model.Name, model.Url);
}
private string DebuggerDisplay => $"{Name} ({Url})";
public override string ToString() => Name;

View File

@@ -1,5 +1,4 @@
using System.Diagnostics;
using Model = Discord.API.EmbedThumbnail;
namespace Discord
{
@@ -11,19 +10,13 @@ namespace Discord
public int? Height { get; }
public int? Width { get; }
private EmbedThumbnail(string url, string proxyUrl, int? height, int? width)
internal EmbedThumbnail(string url, string proxyUrl, int? height, int? width)
{
Url = url;
ProxyUrl = proxyUrl;
Height = height;
Width = width;
}
internal static EmbedThumbnail Create(Model model)
{
return new EmbedThumbnail(model.Url, model.ProxyUrl,
model.Height.IsSpecified ? model.Height.Value : (int?)null,
model.Width.IsSpecified ? model.Width.Value : (int?)null);
}
private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})";
public override string ToString() => Url;

View File

@@ -1,5 +1,4 @@
using System.Diagnostics;
using Model = Discord.API.EmbedVideo;
namespace Discord
{
@@ -10,18 +9,12 @@ namespace Discord
public int? Height { get; }
public int? Width { get; }
private EmbedVideo(string url, int? height, int? width)
internal EmbedVideo(string url, int? height, int? width)
{
Url = url;
Height = height;
Width = width;
}
internal static EmbedVideo Create(Model model)
{
return new EmbedVideo(model.Url,
model.Height.IsSpecified ? model.Height.Value : (int?)null,
model.Width.IsSpecified ? model.Width.Value : (int?)null);
}
private string DebuggerDisplay => $"{Url} ({(Width != null && Height != null ? $"{Width}x{Height}" : "0x0")})";
public override string ToString() => Url;

View File

@@ -1,28 +1,22 @@
using Discord.API;
using System;
using System;
using System.Diagnostics;
using System.Globalization;
using Model = Discord.API.Emoji;
namespace Discord
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public struct Emoji
{
public ulong Id { get; }
public ulong? Id { get; }
public string Name { get; }
public string Url => CDN.GetEmojiUrl(Id);
public string Url => Id != null ? CDN.GetEmojiUrl(Id.Value) : null;
internal Emoji(ulong id, string name)
internal Emoji(ulong? id, string name)
{
Id = id;
Name = name;
}
internal static Emoji Create(Model emoji)
{
return new Emoji(emoji.Id.GetValueOrDefault(), emoji.Name);
}
public static Emoji Parse(string text)
{

View File

@@ -32,6 +32,6 @@
/// <summary>
/// The embed the message should display
/// </summary>
public Optional<EmbedBuilder> Embed { get; set; }
public Optional<Embed> Embed { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
namespace Discord
{
public enum MessageType
{
Default = 0,
RecipientAdd = 1,
RecipientRemove = 2,
Call = 3,
ChannelNameChange = 4,
ChannelIconChange = 5,
ChannelPinnedMessage = 6
}
}

View File

@@ -1,6 +1,4 @@
using Model = Discord.API.Overwrite;
namespace Discord
namespace Discord
{
public struct Overwrite
{
@@ -18,8 +16,5 @@ namespace Discord
TargetType = targetType;
Permissions = permissions;
}
public Overwrite(Model model)
: this(model.TargetId, model.TargetType, new OverwritePermissions(model.Allow, model.Deny)) { }
}
}

View File

@@ -1,5 +1,4 @@
using Discord.API.Rest;
using System;
using System;
using System.Threading.Tasks;
namespace Discord

View File

@@ -1,5 +1,4 @@
using System.Diagnostics;
using Model = Discord.API.Game;
namespace Discord
{
@@ -18,12 +17,6 @@ namespace Discord
}
private Game(string name)
: this(name, null, StreamType.NotStreaming) { }
internal static Game Create(Model model)
{
return new Game(model.Name,
model.StreamUrl.GetValueOrDefault(null),
model.StreamType.GetValueOrDefault(null) ?? StreamType.NotStreaming);
}
public override string ToString() => Name;
private string DebuggerDisplay => StreamUrl != null ? $"{Name} ({StreamUrl})" : Name;

View File

@@ -1,5 +1,4 @@
using Discord.API.Rest;
using System;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

View File

@@ -0,0 +1,8 @@
namespace Discord
{
public enum StreamType
{
NotStreaming = 0,
Twitch = 1
}
}

View File

@@ -0,0 +1,13 @@
namespace Discord
{
public enum UserStatus
{
Unknown,
Online,
Idle,
AFK,
DoNotDisturb,
Invisible,
Offline
}
}

View File

@@ -1,59 +0,0 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace Discord.Net.Converters
{
internal class ArrayConverter<T> : JsonConverter
{
private readonly JsonConverter _innerConverter;
public override bool CanConvert(Type objectType) => true;
public override bool CanRead => true;
public override bool CanWrite => true;
public ArrayConverter(JsonConverter innerConverter)
{
_innerConverter = innerConverter;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var result = new List<T>();
if (reader.TokenType == JsonToken.StartArray)
{
reader.Read();
while (reader.TokenType != JsonToken.EndArray)
{
T obj;
if (_innerConverter != null)
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer);
else
obj = serializer.Deserialize<T>(reader);
result.Add(obj);
reader.Read();
}
}
return result.ToArray();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value != null)
{
writer.WriteStartArray();
var a = (T[])value;
for (int i = 0; i < a.Length; i++)
{
if (_innerConverter != null)
_innerConverter.WriteJson(writer, a[i], serializer);
else
serializer.Serialize(writer, a[i], typeof(T));
}
writer.WriteEndArray();
}
else
writer.WriteNull();
}
}
}

View File

@@ -1,103 +0,0 @@
using Discord.API;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Discord.Net.Converters
{
internal class DiscordContractResolver : DefaultContractResolver
{
private static readonly TypeInfo _ienumerable = typeof(IEnumerable<ulong[]>).GetTypeInfo();
private static readonly MethodInfo _shouldSerialize = typeof(DiscordContractResolver).GetTypeInfo().GetDeclaredMethod("ShouldSerialize");
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property.Ignored)
return property;
var propInfo = member as PropertyInfo;
if (propInfo != null)
{
var converter = GetConverter(property, propInfo, propInfo.PropertyType, 0);
if (converter != null)
{
property.Converter = converter;
property.MemberConverter = converter;
}
}
else
throw new InvalidOperationException($"{member.DeclaringType.FullName}.{member.Name} is not a property.");
return property;
}
private static JsonConverter GetConverter(JsonProperty property, PropertyInfo propInfo, Type type, int depth)
{
if (type.IsArray)
return MakeGenericConverter(property, propInfo, typeof(ArrayConverter<>), type.GetElementType(), depth);
if (type.IsConstructedGenericType)
{
Type genericType = type.GetGenericTypeDefinition();
if (depth == 0 && genericType == typeof(Optional<>))
{
var typeInput = propInfo.DeclaringType;
var innerTypeOutput = type.GenericTypeArguments[0];
var getter = typeof(Func<,>).MakeGenericType(typeInput, type);
var getterDelegate = propInfo.GetMethod.CreateDelegate(getter);
var shouldSerialize = _shouldSerialize.MakeGenericMethod(typeInput, innerTypeOutput);
var shouldSerializeDelegate = (Func<object, Delegate, bool>)shouldSerialize.CreateDelegate(typeof(Func<object, Delegate, bool>));
property.ShouldSerialize = x => shouldSerializeDelegate(x, getterDelegate);
return MakeGenericConverter(property, propInfo, typeof(OptionalConverter<>), innerTypeOutput, depth);
}
else if (genericType == typeof(Nullable<>))
return MakeGenericConverter(property, propInfo, typeof(NullableConverter<>), type.GenericTypeArguments[0], depth);
else if (genericType == typeof(EntityOrId<>))
return MakeGenericConverter(property, propInfo, typeof(UInt64EntityOrIdConverter<>), type.GenericTypeArguments[0], depth);
}
//Primitives
bool hasInt53 = propInfo.GetCustomAttribute<Int53Attribute>() != null;
if (!hasInt53)
{
if (type == typeof(ulong))
return UInt64Converter.Instance;
}
//Enums
if (type == typeof(PermissionTarget))
return PermissionTargetConverter.Instance;
if (type == typeof(UserStatus))
return UserStatusConverter.Instance;
//Special
if (type == typeof(API.Image))
return ImageConverter.Instance;
//Entities
var typeInfo = type.GetTypeInfo();
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<ulong>)))
return UInt64EntityConverter.Instance;
if (typeInfo.ImplementedInterfaces.Any(x => x == typeof(IEntity<string>)))
return StringEntityConverter.Instance;
return null;
}
private static bool ShouldSerialize<TOwner, TValue>(object owner, Delegate getter)
{
return (getter as Func<TOwner, Optional<TValue>>)((TOwner)owner).IsSpecified;
}
private static JsonConverter MakeGenericConverter(JsonProperty property, PropertyInfo propInfo, Type converterType, Type innerType, int depth)
{
var genericType = converterType.MakeGenericType(innerType).GetTypeInfo();
var innerConverter = GetConverter(property, propInfo, innerType, depth + 1);
return genericType.DeclaredConstructors.First().Invoke(new object[] { innerConverter }) as JsonConverter;
}
}
}

View File

@@ -1,37 +0,0 @@
using Discord.API;
using Newtonsoft.Json;
using System;
using Model = Discord.API.Image;
namespace Discord.Net.Converters
{
internal class ImageConverter : JsonConverter
{
public static readonly ImageConverter Instance = new ImageConverter();
public override bool CanConvert(Type objectType) => true;
public override bool CanRead => true;
public override bool CanWrite => true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new InvalidOperationException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var image = (Model)value;
if (image.Stream != null)
{
byte[] bytes = new byte[image.Stream.Length - image.Stream.Position];
image.Stream.Read(bytes, 0, bytes.Length);
string base64 = Convert.ToBase64String(bytes);
writer.WriteValue($"data:image/jpeg;base64,{base64}");
}
else if (image.Hash != null)
writer.WriteValue(image.Hash);
}
}
}

View File

@@ -1,50 +0,0 @@
using Newtonsoft.Json;
using System;
namespace Discord.Net.Converters
{
internal class NullableConverter<T> : JsonConverter
where T : struct
{
private readonly JsonConverter _innerConverter;
public override bool CanConvert(Type objectType) => true;
public override bool CanRead => true;
public override bool CanWrite => true;
public NullableConverter(JsonConverter innerConverter)
{
_innerConverter = innerConverter;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object value = reader.Value;
if (value == null)
return null;
else
{
T obj;
if (_innerConverter != null)
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer);
else
obj = serializer.Deserialize<T>(reader);
return obj;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value == null)
writer.WriteNull();
else
{
var nullable = (T?)value;
if (_innerConverter != null)
_innerConverter.WriteJson(writer, nullable.Value, serializer);
else
serializer.Serialize(writer, nullable.Value, typeof(T));
}
}
}
}

View File

@@ -1,38 +0,0 @@
using Newtonsoft.Json;
using System;
namespace Discord.Net.Converters
{
internal class OptionalConverter<T> : JsonConverter
{
private readonly JsonConverter _innerConverter;
public override bool CanConvert(Type objectType) => true;
public override bool CanRead => true;
public override bool CanWrite => true;
public OptionalConverter(JsonConverter innerConverter)
{
_innerConverter = innerConverter;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
T obj;
if (_innerConverter != null)
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer);
else
obj = serializer.Deserialize<T>(reader);
return new Optional<T>(obj);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
value = ((Optional<T>)value).Value;
if (_innerConverter != null)
_innerConverter.WriteJson(writer, value, serializer);
else
serializer.Serialize(writer, value, typeof(T));
}
}
}

View File

@@ -1,42 +0,0 @@
using Newtonsoft.Json;
using System;
namespace Discord.Net.Converters
{
internal class PermissionTargetConverter : JsonConverter
{
public static readonly PermissionTargetConverter Instance = new PermissionTargetConverter();
public override bool CanConvert(Type objectType) => true;
public override bool CanRead => true;
public override bool CanWrite => true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
switch ((string)reader.Value)
{
case "member":
return PermissionTarget.User;
case "role":
return PermissionTarget.Role;
default:
throw new JsonSerializationException("Unknown permission target");
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
switch ((PermissionTarget)value)
{
case PermissionTarget.User:
writer.WriteValue("member");
break;
case PermissionTarget.Role:
writer.WriteValue("role");
break;
default:
throw new JsonSerializationException("Invalid permission target");
}
}
}
}

View File

@@ -1,27 +0,0 @@
using Newtonsoft.Json;
using System;
namespace Discord.Net.Converters
{
internal class StringEntityConverter : JsonConverter
{
public static readonly StringEntityConverter Instance = new StringEntityConverter();
public override bool CanConvert(Type objectType) => true;
public override bool CanRead => false;
public override bool CanWrite => true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new InvalidOperationException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue((value as IEntity<string>).Id);
else
writer.WriteNull();
}
}
}

View File

@@ -1,25 +0,0 @@
using Newtonsoft.Json;
using System;
using System.Globalization;
namespace Discord.Net.Converters
{
internal class UInt64Converter : JsonConverter
{
public static readonly UInt64Converter Instance = new UInt64Converter();
public override bool CanConvert(Type objectType) => true;
public override bool CanRead => true;
public override bool CanWrite => true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return ulong.Parse((string)reader.Value, NumberStyles.None, CultureInfo.InvariantCulture);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(((ulong)value).ToString(CultureInfo.InvariantCulture));
}
}
}

View File

@@ -1,28 +0,0 @@
using Newtonsoft.Json;
using System;
using System.Globalization;
namespace Discord.Net.Converters
{
internal class UInt64EntityConverter : JsonConverter
{
public static readonly UInt64EntityConverter Instance = new UInt64EntityConverter();
public override bool CanConvert(Type objectType) => true;
public override bool CanRead => false;
public override bool CanWrite => true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new InvalidOperationException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value != null)
writer.WriteValue((value as IEntity<ulong>).Id.ToString(CultureInfo.InvariantCulture));
else
writer.WriteNull();
}
}
}

View File

@@ -1,42 +0,0 @@
using Discord.API;
using Newtonsoft.Json;
using System;
namespace Discord.Net.Converters
{
internal class UInt64EntityOrIdConverter<T> : JsonConverter
{
private readonly JsonConverter _innerConverter;
public override bool CanConvert(Type objectType) => true;
public override bool CanRead => true;
public override bool CanWrite => false;
public UInt64EntityOrIdConverter(JsonConverter innerConverter)
{
_innerConverter = innerConverter;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
switch (reader.TokenType)
{
case JsonToken.String:
case JsonToken.Integer:
return new EntityOrId<T>(ulong.Parse(reader.ReadAsString()));
default:
T obj;
if (_innerConverter != null)
obj = (T)_innerConverter.ReadJson(reader, typeof(T), null, serializer);
else
obj = serializer.Deserialize<T>(reader);
return new EntityOrId<T>(obj);
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new InvalidOperationException();
}
}
}

View File

@@ -1,58 +0,0 @@
using Newtonsoft.Json;
using System;
namespace Discord.Net.Converters
{
internal class UserStatusConverter : JsonConverter
{
public static readonly UserStatusConverter Instance = new UserStatusConverter();
public override bool CanConvert(Type objectType) => true;
public override bool CanRead => true;
public override bool CanWrite => true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
switch ((string)reader.Value)
{
case "online":
return UserStatus.Online;
case "idle":
return UserStatus.Idle;
case "dnd":
return UserStatus.DoNotDisturb;
case "invisible":
return UserStatus.Invisible; //Should never happen
case "offline":
return UserStatus.Offline;
default:
throw new JsonSerializationException("Unknown user status");
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
switch ((UserStatus)value)
{
case UserStatus.Online:
writer.WriteValue("online");
break;
case UserStatus.Idle:
case UserStatus.AFK:
writer.WriteValue("idle");
break;
case UserStatus.DoNotDisturb:
writer.WriteValue("dnd");
break;
case UserStatus.Invisible:
writer.WriteValue("invisible");
break;
case UserStatus.Offline:
writer.WriteValue("offline");
break;
default:
throw new JsonSerializationException("Invalid user status");
}
}
}
}

View File

@@ -0,0 +1,55 @@
using System;
using System.Diagnostics;
namespace Discord
{
//Based on https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Nullable.cs
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public struct Optional<T>
{
public static Optional<T> Unspecified => default(Optional<T>);
private readonly T _value;
/// <summary> Gets the value for this paramter. </summary>
public T Value
{
get
{
if (!IsSpecified)
throw new InvalidOperationException("This property has no value set.");
return _value;
}
}
/// <summary> Returns true if this value has been specified. </summary>
public bool IsSpecified { get; }
/// <summary> Creates a new Parameter with the provided value. </summary>
public Optional(T value)
{
_value = value;
IsSpecified = true;
}
public T GetValueOrDefault() => _value;
public T GetValueOrDefault(T defaultValue) => IsSpecified ? _value : defaultValue;
public override bool Equals(object other)
{
if (!IsSpecified) return other == null;
if (other == null) return false;
return _value.Equals(other);
}
public override int GetHashCode() => IsSpecified ? _value.GetHashCode() : 0;
public override string ToString() => IsSpecified ? _value?.ToString() : null;
private string DebuggerDisplay => IsSpecified ? (_value?.ToString() ?? "<null>") : "<unspecified>";
public static implicit operator Optional<T>(T value) => new Optional<T>(value);
public static explicit operator T(Optional<T> value) => value.Value;
}
public static class Optional
{
public static Optional<T> Create<T>() => Optional<T>.Unspecified;
public static Optional<T> Create<T>(T value) => new Optional<T>(value);
}
}