Browse Source

Fixed several message parsing issues, added optional deserialization

tags/1.0-rc
RogueException 9 years ago
parent
commit
cc5e0bbe13
11 changed files with 105 additions and 78 deletions
  1. +2
    -2
      src/Discord.Net/API/Common/Embed.cs
  2. +9
    -11
      src/Discord.Net/API/Common/Message.cs
  3. +1
    -1
      src/Discord.Net/DiscordSocketClient.cs
  4. +6
    -6
      src/Discord.Net/Entities/Channels/DMChannel.cs
  5. +6
    -6
      src/Discord.Net/Entities/Channels/TextChannel.cs
  6. +4
    -2
      src/Discord.Net/Entities/Messages/Embed.cs
  7. +66
    -41
      src/Discord.Net/Entities/Messages/Message.cs
  8. +4
    -2
      src/Discord.Net/Net/Converters/DiscordContractResolver.cs
  9. +5
    -5
      src/Discord.Net/Net/Converters/OptionalConverter.cs
  10. +1
    -1
      src/Discord.Net/Utilities/MentionUtils.cs
  11. +1
    -1
      src/Discord.Net/Utilities/MessageCache.cs

+ 2
- 2
src/Discord.Net/API/Common/Embed.cs View File

@@ -13,8 +13,8 @@ namespace Discord.API
[JsonProperty("url")]
public string Url { get; set; }
[JsonProperty("thumbnail")]
public EmbedThumbnail Thumbnail { get; set; }
public Optional<EmbedThumbnail> Thumbnail { get; set; }
[JsonProperty("provider")]
public EmbedProvider Provider { get; set; }
public Optional<EmbedProvider> Provider { get; set; }
}
}

+ 9
- 11
src/Discord.Net/API/Common/Message.cs View File

@@ -10,24 +10,22 @@ namespace Discord.API
[JsonProperty("channel_id")]
public ulong ChannelId { get; set; }
[JsonProperty("author")]
public User Author { get; set; }
public Optional<User> Author { get; set; }
[JsonProperty("content")]
public string Content { get; set; }
public Optional<string> Content { get; set; }
[JsonProperty("timestamp")]
public DateTime Timestamp { get; set; }
public Optional<DateTime> Timestamp { get; set; }
[JsonProperty("edited_timestamp")]
public DateTime? EditedTimestamp { get; set; }
public Optional<DateTime?> EditedTimestamp { get; set; }
[JsonProperty("tts")]
public bool IsTextToSpeech { get; set; }
public Optional<bool> IsTextToSpeech { get; set; }
[JsonProperty("mention_everyone")]
public bool IsMentioningEveryone { get; set; }
public Optional<bool> IsMentioningEveryone { get; set; }
[JsonProperty("mentions")]
public User[] Mentions { get; set; }
public Optional<User[]> Mentions { get; set; }
[JsonProperty("attachments")]
public Attachment[] Attachments { get; set; }
public Optional<Attachment[]> Attachments { get; set; }
[JsonProperty("embeds")]
public Embed[] Embeds { get; set; }
/*[JsonProperty("nonce")]
public object Nonce { get; set; }*/
public Optional<Embed[]> Embeds { get; set; }
}
}

+ 1
- 1
src/Discord.Net/DiscordSocketClient.cs View File

@@ -729,7 +729,7 @@ namespace Discord
var channel = DataStore.GetChannel(data.ChannelId) as ICachedMessageChannel;
if (channel != null)
{
var author = channel.GetUser(data.Author.Id);
var author = channel.GetUser(data.Author.Value.Id);

if (author != null)
{


+ 6
- 6
src/Discord.Net/Entities/Channels/DMChannel.cs View File

@@ -70,7 +70,7 @@ namespace Discord
{
var args = new CreateMessageParams { Content = text, IsTTS = isTTS };
var model = await Discord.ApiClient.CreateDMMessageAsync(Id, args).ConfigureAwait(false);
return new Message(this, new User(Discord, model.Author), model);
return new Message(this, new User(Discord, model.Author.Value), model);
}
public async Task<IMessage> SendFileAsync(string filePath, string text, bool isTTS)
{
@@ -79,33 +79,33 @@ namespace Discord
{
var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS };
var model = await Discord.ApiClient.UploadDMFileAsync(Id, file, args).ConfigureAwait(false);
return new Message(this, new User(Discord, model.Author), model);
return new Message(this, new User(Discord, model.Author.Value), model);
}
}
public async Task<IMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS)
{
var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS };
var model = await Discord.ApiClient.UploadDMFileAsync(Id, stream, args).ConfigureAwait(false);
return new Message(this, new User(Discord, model.Author), model);
return new Message(this, new User(Discord, model.Author.Value), model);
}
public virtual async Task<IMessage> GetMessageAsync(ulong id)
{
var model = await Discord.ApiClient.GetChannelMessageAsync(Id, id).ConfigureAwait(false);
if (model != null)
return new Message(this, new User(Discord, model.Author), model);
return new Message(this, new User(Discord, model.Author.Value), model);
return null;
}
public virtual async Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit)
{
var args = new GetChannelMessagesParams { Limit = limit };
var models = await Discord.ApiClient.GetChannelMessagesAsync(Id, args).ConfigureAwait(false);
return models.Select(x => new Message(this, new User(Discord, x.Author), x)).ToImmutableArray();
return models.Select(x => new Message(this, new User(Discord, x.Author.Value), x)).ToImmutableArray();
}
public virtual async Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit)
{
var args = new GetChannelMessagesParams { Limit = limit };
var models = await Discord.ApiClient.GetChannelMessagesAsync(Id, args).ConfigureAwait(false);
return models.Select(x => new Message(this, new User(Discord, x.Author), x)).ToImmutableArray();
return models.Select(x => new Message(this, new User(Discord, x.Author.Value), x)).ToImmutableArray();
}
public async Task DeleteMessagesAsync(IEnumerable<IMessage> messages)
{


+ 6
- 6
src/Discord.Net/Entities/Channels/TextChannel.cs View File

@@ -62,7 +62,7 @@ namespace Discord
{
var args = new CreateMessageParams { Content = text, IsTTS = isTTS };
var model = await Discord.ApiClient.CreateMessageAsync(Guild.Id, Id, args).ConfigureAwait(false);
return new Message(this, new User(Discord, model.Author), model);
return new Message(this, new User(Discord, model.Author.Value), model);
}
public async Task<IMessage> SendFileAsync(string filePath, string text, bool isTTS)
{
@@ -71,33 +71,33 @@ namespace Discord
{
var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS };
var model = await Discord.ApiClient.UploadFileAsync(Guild.Id, Id, file, args).ConfigureAwait(false);
return new Message(this, new User(Discord, model.Author), model);
return new Message(this, new User(Discord, model.Author.Value), model);
}
}
public async Task<IMessage> SendFileAsync(Stream stream, string filename, string text, bool isTTS)
{
var args = new UploadFileParams { Filename = filename, Content = text, IsTTS = isTTS };
var model = await Discord.ApiClient.UploadFileAsync(Guild.Id, Id, stream, args).ConfigureAwait(false);
return new Message(this, new User(Discord, model.Author), model);
return new Message(this, new User(Discord, model.Author.Value), model);
}
public virtual async Task<IMessage> GetMessageAsync(ulong id)
{
var model = await Discord.ApiClient.GetChannelMessageAsync(Id, id).ConfigureAwait(false);
if (model != null)
return new Message(this, new User(Discord, model.Author), model);
return new Message(this, new User(Discord, model.Author.Value), model);
return null;
}
public virtual async Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(int limit)
{
var args = new GetChannelMessagesParams { Limit = limit };
var models = await Discord.ApiClient.GetChannelMessagesAsync(Id, args).ConfigureAwait(false);
return models.Select(x => new Message(this, new User(Discord, x.Author), x)).ToImmutableArray();
return models.Select(x => new Message(this, new User(Discord, x.Author.Value), x)).ToImmutableArray();
}
public virtual async Task<IReadOnlyCollection<IMessage>> GetMessagesAsync(ulong fromMessageId, Direction dir, int limit)
{
var args = new GetChannelMessagesParams { Limit = limit };
var models = await Discord.ApiClient.GetChannelMessagesAsync(Id, args).ConfigureAwait(false);
return models.Select(x => new Message(this, new User(Discord, x.Author), x)).ToImmutableArray();
return models.Select(x => new Message(this, new User(Discord, x.Author.Value), x)).ToImmutableArray();
}
public async Task DeleteMessagesAsync(IEnumerable<IMessage> messages)
{


+ 4
- 2
src/Discord.Net/Entities/Messages/Embed.cs View File

@@ -18,8 +18,10 @@ namespace Discord
Title = model.Title;
Description = model.Description;
Provider = new EmbedProvider(model.Provider);
Thumbnail = new EmbedThumbnail(model.Thumbnail);
if (model.Provider.IsSpecified)
Provider = new EmbedProvider(model.Provider.Value);
if (model.Thumbnail.IsSpecified)
Thumbnail = new EmbedThumbnail(model.Thumbnail.Value);
}
}
}

+ 66
- 41
src/Discord.Net/Entities/Messages/Message.cs View File

@@ -10,7 +10,9 @@ namespace Discord
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
internal class Message : SnowflakeEntity, IMessage
{
{
private bool _isMentioningEveryone;

public DateTime? EditedTimestamp { get; private set; }
public bool IsTTS { get; private set; }
public string RawText { get; private set; }
@@ -34,6 +36,13 @@ namespace Discord
Channel = channel;
Author = author;

if (channel is IGuildChannel)
{
MentionedUsers = ImmutableArray.Create<User>();
MentionedChannelIds = ImmutableArray.Create<ulong>();
MentionedRoleIds = ImmutableArray.Create<ulong>();
}

Update(model, UpdateSource.Creation);
}
public void Update(Model model, UpdateSource source)
@@ -44,57 +53,73 @@ namespace Discord
var guild = guildChannel?.Guild;
var discord = Discord;

IsTTS = model.IsTextToSpeech;
Timestamp = model.Timestamp;
EditedTimestamp = model.EditedTimestamp;
RawText = model.Content;

if (model.Attachments.Length > 0)
if (model.IsTextToSpeech.IsSpecified)
IsTTS = model.IsTextToSpeech.Value;
if (model.Timestamp.IsSpecified)
Timestamp = model.Timestamp.Value;
if (model.EditedTimestamp.IsSpecified)
EditedTimestamp = model.EditedTimestamp.Value;
if (model.IsMentioningEveryone.IsSpecified)
_isMentioningEveryone = model.IsMentioningEveryone.Value;
if (model.Attachments.IsSpecified)
{
var attachments = new Attachment[model.Attachments.Length];
for (int i = 0; i < attachments.Length; i++)
attachments[i] = new Attachment(model.Attachments[i]);
Attachments = ImmutableArray.Create(attachments);
var value = model.Attachments.Value;
if (value.Length > 0)
{
var attachments = new Attachment[value.Length];
for (int i = 0; i < attachments.Length; i++)
attachments[i] = new Attachment(value[i]);
Attachments = ImmutableArray.Create(attachments);
}
else
Attachments = ImmutableArray.Create<Attachment>();
}
else
Attachments = ImmutableArray.Create<Attachment>();

if (model.Embeds.Length > 0)
if (model.Embeds.IsSpecified)
{
var embeds = new Embed[model.Attachments.Length];
for (int i = 0; i < embeds.Length; i++)
embeds[i] = new Embed(model.Embeds[i]);
Embeds = ImmutableArray.Create(embeds);
var value = model.Embeds.Value;
if (value.Length > 0)
{
var embeds = new Embed[value.Length];
for (int i = 0; i < embeds.Length; i++)
embeds[i] = new Embed(value[i]);
Embeds = ImmutableArray.Create(embeds);
}
else
Embeds = ImmutableArray.Create<Embed>();
}
else
Embeds = ImmutableArray.Create<Embed>();

if (guildChannel != null && model.Mentions.Length > 0)
if (model.Mentions.IsSpecified)
{
var mentions = new User[model.Mentions.Length];
for (int i = 0; i < model.Mentions.Length; i++)
mentions[i] = new User(discord, model.Mentions[i]);
MentionedUsers = ImmutableArray.Create(mentions);
var value = model.Mentions.Value;
if (value.Length > 0)
{
var mentions = new User[value.Length];
for (int i = 0; i < value.Length; i++)
mentions[i] = new User(discord, value[i]);
MentionedUsers = ImmutableArray.Create(mentions);
}
else
MentionedUsers = ImmutableArray.Create<User>();
}
else
MentionedUsers = ImmutableArray.Create<User>();

if (guildChannel != null)
{
MentionedChannelIds = MentionUtils.GetChannelMentions(model.Content);

var mentionedRoleIds = MentionUtils.GetRoleMentions(model.Content);
if (model.IsMentioningEveryone)
mentionedRoleIds = mentionedRoleIds.Add(guildChannel.Guild.EveryoneRole.Id);
MentionedRoleIds = mentionedRoleIds;
}
else
if (model.Content.IsSpecified)
{
MentionedChannelIds = ImmutableArray.Create<ulong>();
MentionedRoleIds = ImmutableArray.Create<ulong>();
RawText = model.Content.Value;

if (Channel is IGuildChannel)
{
Text = MentionUtils.CleanUserMentions(RawText, MentionedUsers);
MentionedChannelIds = MentionUtils.GetChannelMentions(RawText);
var mentionedRoleIds = MentionUtils.GetRoleMentions(RawText);
if (_isMentioningEveryone)
mentionedRoleIds = mentionedRoleIds.Add(guildChannel.Guild.EveryoneRole.Id);
MentionedRoleIds = mentionedRoleIds;
}
else
Text = RawText;
}
Text = MentionUtils.CleanUserMentions(model.Content, model.Mentions);
}

public async Task UpdateAsync()


+ 4
- 2
src/Discord.Net/Net/Converters/DiscordContractResolver.cs View File

@@ -55,6 +55,7 @@ namespace Discord.Net.Converters
converter = ImageConverter.Instance;
else if (type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Optional<>))
{
var innerType = type.GenericTypeArguments[0];
var typeInput = propInfo.DeclaringType;
var typeOutput = propInfo.PropertyType;

@@ -62,9 +63,10 @@ namespace Discord.Net.Converters
var getterDelegate = propInfo.GetMethod.CreateDelegate(getter);
var shouldSerialize = _shouldSerialize.MakeGenericMethod(typeInput, typeOutput);
var shouldSerializeDelegate = (Func<object, Delegate, bool>)shouldSerialize.CreateDelegate(typeof(Func<object, Delegate, bool>));
property.ShouldSerialize = x => shouldSerializeDelegate(x, getterDelegate);
converter = OptionalConverter.Instance;

var converterType = typeof(OptionalConverter<>).MakeGenericType(innerType);
converter = converterType.GetTypeInfo().GetDeclaredField("Instance").GetValue(null) as JsonConverter;
}
}



+ 5
- 5
src/Discord.Net/Net/Converters/OptionalConverter.cs View File

@@ -3,22 +3,22 @@ using System;

namespace Discord.Net.Converters
{
public class OptionalConverter : JsonConverter
public class OptionalConverter<T> : JsonConverter
{
public static readonly OptionalConverter Instance = new OptionalConverter();
public static readonly OptionalConverter<T> Instance = new OptionalConverter<T>();

public override bool CanConvert(Type objectType) => true;
public override bool CanRead => false;
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();
return new Optional<T>(serializer.Deserialize<T>(reader));
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, (value as IOptional).Value);
serializer.Serialize(writer, ((Optional<T>)value).Value);
}
}
}

+ 1
- 1
src/Discord.Net/Utilities/MentionUtils.cs View File

@@ -82,7 +82,7 @@ namespace Discord
return builder;
}

internal static string CleanUserMentions(string text, API.User[] mentions)
internal static string CleanUserMentions(string text, ImmutableArray<User> mentions)
{
return _userRegex.Replace(text, new MatchEvaluator(e =>
{


+ 1
- 1
src/Discord.Net/Utilities/MessageCache.cs View File

@@ -88,7 +88,7 @@ namespace Discord
return msg;
var model = await _discord.ApiClient.GetChannelMessageAsync(_channel.Id, id).ConfigureAwait(false);
if (model != null)
return new CachedMessage(_channel, new User(_discord, model.Author), model);
return new CachedMessage(_channel, new User(_discord, model.Author.Value), model);
return null;
}
public async Task<IReadOnlyCollection<CachedMessage>> DownloadAsync(ulong? fromId, Direction dir, int limit)


Loading…
Cancel
Save