Started converting websocket and rpc classes

This commit is contained in:
RogueException
2016-09-28 04:12:17 -03:00
parent 0c4641ac68
commit dd86f03306
107 changed files with 1836 additions and 1882 deletions

View File

@@ -1,13 +0,0 @@
using Model = Discord.API.Message;
namespace Discord.WebSocket
{
internal interface ISocketMessage : IMessage
{
DiscordSocketClient Discord { get; }
new ISocketMessageChannel Channel { get; }
void Update(Model model);
ISocketMessage Clone();
}
}

View File

@@ -0,0 +1,80 @@
using Discord.Rest;
using Discord.WebSocket;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
namespace Discord.WebSocket
{
internal class MessageCache
{
private readonly ConcurrentDictionary<ulong, SocketMessage> _messages;
private readonly ConcurrentQueue<ulong> _orderedMessages;
private readonly int _size;
public IReadOnlyCollection<SocketMessage> Messages => _messages.ToReadOnlyCollection();
public MessageCache(DiscordSocketClient discord, IChannel channel)
{
_size = discord.MessageCacheSize;
_messages = new ConcurrentDictionary<ulong, SocketMessage>(1, (int)(_size * 1.05));
_orderedMessages = new ConcurrentQueue<ulong>();
}
public void Add(SocketMessage message)
{
if (_messages.TryAdd(message.Id, message))
{
_orderedMessages.Enqueue(message.Id);
ulong msgId;
SocketMessage msg;
while (_orderedMessages.Count > _size && _orderedMessages.TryDequeue(out msgId))
_messages.TryRemove(msgId, out msg);
}
}
public SocketMessage Remove(ulong id)
{
SocketMessage msg;
_messages.TryRemove(id, out msg);
return msg;
}
public SocketMessage Get(ulong id)
{
SocketMessage result;
if (_messages.TryGetValue(id, out result))
return result;
return null;
}
public IImmutableList<SocketMessage> GetMany(ulong? fromMessageId, Direction dir, int limit = DiscordConfig.MaxMessagesPerBatch)
{
if (limit < 0) throw new ArgumentOutOfRangeException(nameof(limit));
if (limit == 0) return ImmutableArray<SocketMessage>.Empty;
IEnumerable<ulong> cachedMessageIds;
if (fromMessageId == null)
cachedMessageIds = _orderedMessages;
else if (dir == Direction.Before)
cachedMessageIds = _orderedMessages.Where(x => x < fromMessageId.Value);
else
cachedMessageIds = _orderedMessages.Where(x => x > fromMessageId.Value);
return cachedMessageIds
.Take(limit)
.Select(x =>
{
SocketMessage msg;
if (_messages.TryGetValue(x, out msg))
return msg;
return null;
})
.Where(x => x != null)
.ToImmutableArray();
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading.Tasks;
using Model = Discord.API.Message;
namespace Discord.WebSocket
{
[DebuggerDisplay(@"{DebuggerDisplay,nq}")]
public abstract class SocketMessage : SocketEntity<ulong>, IMessage, IUpdateable
{
private long _timestampTicks;
public ulong ChannelId { get; }
public SocketUser Author { get; }
public string Content { get; private set; }
public virtual bool IsTTS => false;
public virtual bool IsPinned => false;
public virtual DateTimeOffset? EditedTimestamp => null;
public virtual IReadOnlyCollection<IAttachment> Attachments => ImmutableArray.Create<IAttachment>();
public virtual IReadOnlyCollection<IEmbed> Embeds => ImmutableArray.Create<IEmbed>();
public virtual IReadOnlyCollection<ulong> MentionedChannelIds => ImmutableArray.Create<ulong>();
public virtual IReadOnlyCollection<IRole> MentionedRoles => ImmutableArray.Create<IRole>();
public virtual IReadOnlyCollection<IUser> MentionedUsers => ImmutableArray.Create<IUser>();
public DateTimeOffset Timestamp => DateTimeUtils.FromTicks(_timestampTicks);
internal SocketMessage(DiscordSocketClient discord, ulong id, ulong channelId, SocketUser author)
: base(discord, id)
{
ChannelId = channelId;
Author = author;
}
internal static SocketMessage Create(DiscordSocketClient discord, SocketUser author, Model model)
{
if (model.Type == MessageType.Default)
return SocketUserMessage.Create(discord, author, model);
else
return SocketSystemMessage.Create(discord, author, model);
}
internal virtual void Update(Model model)
{
if (model.Timestamp.IsSpecified)
_timestampTicks = model.Timestamp.Value.UtcTicks;
if (model.Content.IsSpecified)
Content = model.Content.Value;
}
public async Task UpdateAsync()
{
var model = await Discord.ApiClient.GetChannelMessageAsync(ChannelId, Id).ConfigureAwait(false);
Update(model);
}
//IMessage
IUser IMessage.Author => Author;
MessageType IMessage.Type => MessageType.Default;
}
}

View File

@@ -3,18 +3,25 @@ using Model = Discord.API.Message;
namespace Discord.WebSocket
{
internal class SocketSystemMessage : SystemMessage, ISocketMessage
internal class SocketSystemMessage : SocketMessage, ISystemMessage
{
internal override bool IsAttached => true;
public MessageType Type { get; private set; }
public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient;
public new ISocketMessageChannel Channel => base.Channel as ISocketMessageChannel;
public SocketSystemMessage(ISocketMessageChannel channel, IUser author, Model model)
: base(channel, author, model)
internal SocketSystemMessage(DiscordSocketClient discord, ulong id, ulong channelId, SocketUser author)
: base(discord, id, channelId, author)
{
}
internal new static SocketSystemMessage Create(DiscordSocketClient discord, SocketUser author, Model model)
{
var entity = new SocketSystemMessage(discord, model.Id, model.ChannelId, author);
entity.Update(model);
return entity;
}
internal override void Update(Model model)
{
base.Update(model);
public ISocketMessage Clone() => MemberwiseClone() as ISocketMessage;
Type = model.Type;
}
}
}

View File

@@ -1,20 +1,133 @@
using Discord.Rest;
using Discord.API.Rest;
using Discord.Rest;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Model = Discord.API.Message;
namespace Discord.WebSocket
{
internal class SocketUserMessage : UserMessage, ISocketMessage
internal class SocketUserMessage : SocketMessage, IUserMessage
{
internal override bool IsAttached => true;
private bool _isMentioningEveryone, _isTTS, _isPinned;
private long? _editedTimestampTicks;
private ImmutableArray<RestAttachment> _attachments;
private ImmutableArray<RestEmbed> _embeds;
private ImmutableArray<ulong> _mentionedChannelIds;
private ImmutableArray<RestRole> _mentionedRoles;
private ImmutableArray<RestUser> _mentionedUsers;
public new DiscordSocketClient Discord => base.Discord as DiscordSocketClient;
public new ISocketMessageChannel Channel => base.Channel as ISocketMessageChannel;
public override bool IsTTS => _isTTS;
public override bool IsPinned => _isPinned;
public override DateTimeOffset? EditedTimestamp => DateTimeUtils.FromTicks(_editedTimestampTicks);
public SocketUserMessage(ISocketMessageChannel channel, IUser author, Model model)
: base(channel, author, model)
public override IReadOnlyCollection<IAttachment> Attachments => _attachments;
public override IReadOnlyCollection<IEmbed> Embeds => _embeds;
public override IReadOnlyCollection<ulong> MentionedChannelIds => _mentionedChannelIds;
public override IReadOnlyCollection<IRole> MentionedRoles => _mentionedRoles;
public override IReadOnlyCollection<IUser> MentionedUsers => _mentionedUsers;
internal SocketUserMessage(DiscordSocketClient discord, ulong id, ulong channelId, SocketUser author)
: base(discord, id, channelId, author)
{
}
internal new static SocketUserMessage Create(DiscordSocketClient discord, SocketUser author, Model model)
{
var entity = new SocketUserMessage(discord, model.Id, model.ChannelId, author);
entity.Update(model);
return entity;
}
public ISocketMessage Clone() => MemberwiseClone() as ISocketMessage;
internal override void Update(Model model)
{
base.Update(model);
if (model.IsTextToSpeech.IsSpecified)
_isTTS = model.IsTextToSpeech.Value;
if (model.Pinned.IsSpecified)
_isPinned = model.Pinned.Value;
if (model.EditedTimestamp.IsSpecified)
_editedTimestampTicks = model.EditedTimestamp.Value?.UtcTicks;
if (model.MentionEveryone.IsSpecified)
_isMentioningEveryone = model.MentionEveryone.Value;
if (model.Attachments.IsSpecified)
{
var value = model.Attachments.Value;
if (value.Length > 0)
{
var attachments = ImmutableArray.CreateBuilder<RestAttachment>(value.Length);
for (int i = 0; i < value.Length; i++)
attachments.Add(RestAttachment.Create(value[i]));
_attachments = attachments.ToImmutable();
}
else
_attachments = ImmutableArray.Create<RestAttachment>();
}
if (model.Embeds.IsSpecified)
{
var value = model.Embeds.Value;
if (value.Length > 0)
{
var embeds = ImmutableArray.CreateBuilder<RestEmbed>(value.Length);
for (int i = 0; i < value.Length; i++)
embeds.Add(RestEmbed.Create(value[i]));
_embeds = embeds.ToImmutable();
}
else
_embeds = ImmutableArray.Create<RestEmbed>();
}
ImmutableArray<RestUser> mentions = ImmutableArray.Create<RestUser>();
if (model.Mentions.IsSpecified)
{
var value = model.Mentions.Value;
if (value.Length > 0)
{
var newMentions = ImmutableArray.CreateBuilder<RestUser>(value.Length);
for (int i = 0; i < value.Length; i++)
newMentions.Add(RestUser.Create(Discord, value[i]));
mentions = newMentions.ToImmutable();
}
}
if (model.Content.IsSpecified)
{
var text = model.Content.Value;
_mentionedUsers = MentionsHelper.GetUserMentions(text, null, mentions);
_mentionedChannelIds = MentionsHelper.GetChannelMentions(text, null);
_mentionedRoles = MentionsHelper.GetRoleMentions<RestRole>(text, null);
model.Content = text;
}
}
public Task ModifyAsync(Action<ModifyMessageParams> func)
=> MessageHelper.ModifyAsync(this, Discord, func);
public Task DeleteAsync()
=> MessageHelper.DeleteAsync(this, Discord);
public Task PinAsync()
=> MessageHelper.PinAsync(this, Discord);
public Task UnpinAsync()
=> MessageHelper.UnpinAsync(this, Discord);
public string Resolve(UserMentionHandling userHandling = UserMentionHandling.Name, ChannelMentionHandling channelHandling = ChannelMentionHandling.Name,
RoleMentionHandling roleHandling = RoleMentionHandling.Name, EveryoneMentionHandling everyoneHandling = EveryoneMentionHandling.Ignore)
=> Resolve(Content, userHandling, channelHandling, roleHandling, everyoneHandling);
public string Resolve(int startIndex, int length, UserMentionHandling userHandling = UserMentionHandling.Name, ChannelMentionHandling channelHandling = ChannelMentionHandling.Name,
RoleMentionHandling roleHandling = RoleMentionHandling.Name, EveryoneMentionHandling everyoneHandling = EveryoneMentionHandling.Ignore)
=> Resolve(Content.Substring(startIndex, length), userHandling, channelHandling, roleHandling, everyoneHandling);
public string Resolve(string text, UserMentionHandling userHandling, ChannelMentionHandling channelHandling,
RoleMentionHandling roleHandling, EveryoneMentionHandling everyoneHandling)
{
text = MentionsHelper.ResolveUserMentions(text, null, MentionedUsers, userHandling);
text = MentionsHelper.ResolveChannelMentions(text, null, channelHandling);
text = MentionsHelper.ResolveRoleMentions(text, MentionedRoles, roleHandling);
text = MentionsHelper.ResolveEveryoneMentions(text, everyoneHandling);
return text;
}
}
}