| @@ -35,7 +35,7 @@ namespace Discord.Commands | |||||
| return; | return; | ||||
| //Ignore messages from ourselves | //Ignore messages from ourselves | ||||
| if (e.Message.UserId == client.CurrentUserId) | |||||
| if (e.Message.User == client.CurrentUser) | |||||
| return; | return; | ||||
| //Check for the command character | //Check for the command character | ||||
| @@ -248,7 +248,7 @@ namespace Discord | |||||
| SendMessageResponse response = null; | SendMessageResponse response = null; | ||||
| try | try | ||||
| { | { | ||||
| response = await _api.SendMessage(msg.Channel.Id, msg.RawText, msg.MentionIds, msg.Nonce, msg.IsTTS).ConfigureAwait(false); | |||||
| response = await _api.SendMessage(msg.Channel.Id, msg.RawText, msg.Mentions.Select(x => x.Id), msg.Nonce, msg.IsTTS).ConfigureAwait(false); | |||||
| } | } | ||||
| catch (WebException) { break; } | catch (WebException) { break; } | ||||
| catch (HttpException) { hasFailed = true; } | catch (HttpException) { hasFailed = true; } | ||||
| @@ -61,8 +61,6 @@ namespace Discord | |||||
| internal Servers Servers => _servers; | internal Servers Servers => _servers; | ||||
| private readonly Servers _servers; | private readonly Servers _servers; | ||||
| public Server PMServer { get; } | |||||
| /// <summary> Returns the server with the specified id, or null if none was found. </summary> | /// <summary> Returns the server with the specified id, or null if none was found. </summary> | ||||
| public Server GetServer(string id) => _servers[id]; | public Server GetServer(string id) => _servers[id]; | ||||
| @@ -29,7 +29,7 @@ namespace Discord | |||||
| RaiseEvent(nameof(UserRemoved), () => UserRemoved(this, new MemberEventArgs(member))); | RaiseEvent(nameof(UserRemoved), () => UserRemoved(this, new MemberEventArgs(member))); | ||||
| } | } | ||||
| public event EventHandler ProfileUpdated; | public event EventHandler ProfileUpdated; | ||||
| private void RaiseProfileUpdated(GlobalUser user) | |||||
| private void RaiseProfileUpdated() | |||||
| { | { | ||||
| if (ProfileUpdated != null) | if (ProfileUpdated != null) | ||||
| RaiseEvent(nameof(ProfileUpdated), () => ProfileUpdated(this, EventArgs.Empty)); | RaiseEvent(nameof(ProfileUpdated), () => ProfileUpdated(this, EventArgs.Empty)); | ||||
| @@ -7,40 +7,38 @@ namespace Discord | |||||
| public partial class DiscordClient | public partial class DiscordClient | ||||
| { | { | ||||
| public IDiscordVoiceClient GetVoiceClient(Server server) | public IDiscordVoiceClient GetVoiceClient(Server server) | ||||
| => GetVoiceClient(server.Id); | |||||
| public IDiscordVoiceClient GetVoiceClient(string serverId) | |||||
| { | { | ||||
| if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||||
| if (server.Id == null) throw new ArgumentNullException(nameof(server.Id)); | |||||
| if (!Config.EnableVoiceMultiserver) | if (!Config.EnableVoiceMultiserver) | ||||
| { | { | ||||
| if (serverId == _voiceServerId) | |||||
| if (server.Id == _voiceServerId) | |||||
| return this; | return this; | ||||
| else | else | ||||
| return null; | return null; | ||||
| } | } | ||||
| DiscordWSClient client; | DiscordWSClient client; | ||||
| if (_voiceClients.TryGetValue(serverId, out client)) | |||||
| if (_voiceClients.TryGetValue(server.Id, out client)) | |||||
| return client; | return client; | ||||
| else | else | ||||
| return null; | return null; | ||||
| } | } | ||||
| private async Task<IDiscordVoiceClient> CreateVoiceClient(string serverId) | |||||
| private async Task<IDiscordVoiceClient> CreateVoiceClient(Server server) | |||||
| { | { | ||||
| if (!Config.EnableVoiceMultiserver) | if (!Config.EnableVoiceMultiserver) | ||||
| { | { | ||||
| _voiceServerId = serverId; | |||||
| _voiceServerId = server.Id; | |||||
| return this; | return this; | ||||
| } | } | ||||
| var client = _voiceClients.GetOrAdd(serverId, _ => | |||||
| var client = _voiceClients.GetOrAdd(server.Id, _ => | |||||
| { | { | ||||
| var config = _config.Clone(); | var config = _config.Clone(); | ||||
| config.LogLevel = _config.LogLevel;// (LogMessageSeverity)Math.Min((int)_config.LogLevel, (int)LogMessageSeverity.Warning); | config.LogLevel = _config.LogLevel;// (LogMessageSeverity)Math.Min((int)_config.LogLevel, (int)LogMessageSeverity.Warning); | ||||
| config.VoiceOnly = true; | config.VoiceOnly = true; | ||||
| config.VoiceClientId = unchecked(++_nextVoiceClientId); | config.VoiceClientId = unchecked(++_nextVoiceClientId); | ||||
| return new DiscordWSClient(config, serverId); | |||||
| return new DiscordWSClient(config, server.Id); | |||||
| }); | }); | ||||
| client.LogMessage += (s, e) => RaiseOnLog(e.Severity, e.Source, $"(#{client.Config.VoiceClientId}) {e.Message}"); | client.LogMessage += (s, e) => RaiseOnLog(e.Severity, e.Source, $"(#{client.Config.VoiceClientId}) {e.Message}"); | ||||
| await client.Connect(_gateway, _token).ConfigureAwait(false); | await client.Connect(_gateway, _token).ConfigureAwait(false); | ||||
| @@ -52,28 +50,26 @@ namespace Discord | |||||
| if (channel == null) throw new ArgumentNullException(nameof(channel)); | if (channel == null) throw new ArgumentNullException(nameof(channel)); | ||||
| CheckReady(); //checkVoice is done inside the voice client | CheckReady(); //checkVoice is done inside the voice client | ||||
| var client = await CreateVoiceClient(channel.Server.Id).ConfigureAwait(false); | |||||
| var client = await CreateVoiceClient(channel.Server).ConfigureAwait(false); | |||||
| await client.JoinChannel(channel.Id).ConfigureAwait(false); | await client.JoinChannel(channel.Id).ConfigureAwait(false); | ||||
| return client; | return client; | ||||
| } | } | ||||
| public Task LeaveVoiceServer(Server server) | |||||
| => LeaveVoiceServer(server?.Id); | |||||
| public async Task LeaveVoiceServer(string serverId) | |||||
| public async Task LeaveVoiceServer(Server server) | |||||
| { | { | ||||
| if (server == null) throw new ArgumentNullException(nameof(server)); | |||||
| CheckReady(checkVoice: true); | CheckReady(checkVoice: true); | ||||
| if (serverId == null) throw new ArgumentNullException(nameof(serverId)); | |||||
| if (Config.EnableVoiceMultiserver) | if (Config.EnableVoiceMultiserver) | ||||
| { | { | ||||
| DiscordWSClient client; | DiscordWSClient client; | ||||
| if (_voiceClients.TryRemove(serverId, out client)) | |||||
| if (_voiceClients.TryRemove(server.Id, out client)) | |||||
| await client.Disconnect().ConfigureAwait(false); | await client.Disconnect().ConfigureAwait(false); | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| await _voiceSocket.Disconnect().ConfigureAwait(false); | await _voiceSocket.Disconnect().ConfigureAwait(false); | ||||
| _dataSocket.SendLeaveVoice(serverId); | |||||
| _dataSocket.SendLeaveVoice(server.Id); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -599,7 +599,7 @@ namespace Discord | |||||
| if (user != null) | if (user != null) | ||||
| { | { | ||||
| user.Update(data); | user.Update(data); | ||||
| RaiseProfileUpdated(user); | |||||
| RaiseProfileUpdated(); | |||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| @@ -84,11 +84,11 @@ namespace Discord | |||||
| } | } | ||||
| internal override void OnCached() | internal override void OnCached() | ||||
| { | { | ||||
| if (IsPrivate) | if (IsPrivate) | ||||
| { | { | ||||
| var recipient = _client.Users[_recipientId, _serverId]; | |||||
| var recipient = _client.Users[_recipientId, null]; | |||||
| Name = "@" + recipient.Name; | Name = "@" + recipient.Name; | ||||
| recipient.GlobalUser.PrivateChannel = this; | |||||
| Recipient = recipient; | Recipient = recipient; | ||||
| } | } | ||||
| else | else | ||||
| @@ -96,7 +96,8 @@ namespace Discord | |||||
| var server = _client.Servers[_serverId]; | var server = _client.Servers[_serverId]; | ||||
| server.AddChannel(this); | server.AddChannel(this); | ||||
| Server = server; | Server = server; | ||||
| } | |||||
| Recipient = null; | |||||
| } | |||||
| } | } | ||||
| internal override void OnUncached() | internal override void OnUncached() | ||||
| { | { | ||||
| @@ -104,7 +105,7 @@ namespace Discord | |||||
| if (server != null) | if (server != null) | ||||
| server.RemoveChannel(this); | server.RemoveChannel(this); | ||||
| Server = null; | Server = null; | ||||
| var recipient = Recipient; | var recipient = Recipient; | ||||
| if (recipient != null) | if (recipient != null) | ||||
| recipient.GlobalUser.PrivateChannel = null; | recipient.GlobalUser.PrivateChannel = null; | ||||
| @@ -22,7 +22,17 @@ namespace Discord | |||||
| /// <summary> Returns the private messaging channel with this user, if one exists. </summary> | /// <summary> Returns the private messaging channel with this user, if one exists. </summary> | ||||
| [JsonIgnore] | [JsonIgnore] | ||||
| public Channel PrivateChannel { get; internal set; } | |||||
| public Channel PrivateChannel | |||||
| { | |||||
| get { return _privateChannel; } | |||||
| internal set | |||||
| { | |||||
| _privateChannel = value; | |||||
| if (value == null) | |||||
| CheckUser(); | |||||
| } | |||||
| } | |||||
| private Channel _privateChannel; | |||||
| /// <summary> Returns a collection of all server-specific data for every server this user is a member of. </summary> | /// <summary> Returns a collection of all server-specific data for every server this user is a member of. </summary> | ||||
| [JsonIgnore] | [JsonIgnore] | ||||
| @@ -51,10 +61,12 @@ namespace Discord | |||||
| internal void RemoveUser(User user) | internal void RemoveUser(User user) | ||||
| { | { | ||||
| if (_users.TryRemove(user.UniqueId, out user)) | if (_users.TryRemove(user.UniqueId, out user)) | ||||
| { | |||||
| if (_users.Count == 0) | |||||
| _client.GlobalUsers.TryRemove(Id); | |||||
| } | |||||
| CheckUser(); | |||||
| } | |||||
| internal void CheckUser() | |||||
| { | |||||
| if (_users.Count == 0 && PrivateChannel == null) | |||||
| _client.GlobalUsers.TryRemove(Id); | |||||
| } | } | ||||
| public override string ToString() => Id; | public override string ToString() => Id; | ||||
| @@ -6,8 +6,6 @@ namespace Discord | |||||
| { | { | ||||
| public sealed class Invite : CachedObject | public sealed class Invite : CachedObject | ||||
| { | { | ||||
| /// <summary> Returns the unique code for this invite. </summary> | |||||
| public string Code { get; private set; } | |||||
| /// <summary> Returns, if enabled, an alternative human-readable code for URLs. </summary> | /// <summary> Returns, if enabled, an alternative human-readable code for URLs. </summary> | ||||
| public string XkcdCode { get; } | public string XkcdCode { get; } | ||||
| /// <summary> Time (in seconds) until the invite expires. Set to 0 to never expire. </summary> | /// <summary> Time (in seconds) until the invite expires. Set to 0 to never expire. </summary> | ||||
| @@ -22,7 +20,7 @@ namespace Discord | |||||
| public bool IsTemporary { get; private set; } | public bool IsTemporary { get; private set; } | ||||
| /// <summary> Returns a URL for this invite using XkcdCode if available or Id if not. </summary> | /// <summary> Returns a URL for this invite using XkcdCode if available or Id if not. </summary> | ||||
| public string Url => API.Endpoints.InviteUrl(XkcdCode ?? Code); | |||||
| public string Url => API.Endpoints.InviteUrl(XkcdCode ?? Id); | |||||
| /// <summary> Returns the user that created this invite. </summary> | /// <summary> Returns the user that created this invite. </summary> | ||||
| [JsonIgnore] | [JsonIgnore] | ||||
| @@ -92,7 +92,6 @@ namespace Discord | |||||
| } | } | ||||
| private string _cleanText; | private string _cleanText; | ||||
| private string _channelId, _userId; | |||||
| /// <summary> Returns the local unique identifier for this message. </summary> | /// <summary> Returns the local unique identifier for this message. </summary> | ||||
| public string Nonce { get; internal set; } | public string Nonce { get; internal set; } | ||||
| @@ -123,10 +122,7 @@ namespace Discord | |||||
| /// <summary> Returns a collection of all embeded content in this message. </summary> | /// <summary> Returns a collection of all embeded content in this message. </summary> | ||||
| public Embed[] Embeds { get; private set; } | public Embed[] Embeds { get; private set; } | ||||
| private static readonly Embed[] _initialEmbeds = new Embed[0]; | private static readonly Embed[] _initialEmbeds = new Embed[0]; | ||||
| private static readonly string[] _initialMentions = new string[0]; | |||||
| /// <summary> Returns a collection of all user ids mentioned in this message. </summary> | |||||
| public string[] MentionIds { get; private set; } | |||||
| /// <summary> Returns a collection of all users mentioned in this message. </summary> | /// <summary> Returns a collection of all users mentioned in this message. </summary> | ||||
| [JsonIgnore] | [JsonIgnore] | ||||
| public IEnumerable<User> Mentions { get; internal set; } | public IEnumerable<User> Mentions { get; internal set; } | ||||
| @@ -137,14 +133,14 @@ namespace Discord | |||||
| /// <summary> Returns the channel this message was sent to. </summary> | /// <summary> Returns the channel this message was sent to. </summary> | ||||
| [JsonIgnore] | [JsonIgnore] | ||||
| public Channel Channel { get; private set; } | public Channel Channel { get; private set; } | ||||
| private readonly string _channelId; | |||||
| /// <summary> Returns true if the current user created this message. </summary> | /// <summary> Returns true if the current user created this message. </summary> | ||||
| public bool IsAuthor => _client.CurrentUserId == UserId; | |||||
| /// <summary> Returns the id of the author of this message. </summary> | |||||
| public string UserId { get; } | |||||
| public bool IsAuthor => _client.CurrentUserId == _userId; | |||||
| /// <summary> Returns the author of this message. </summary> | /// <summary> Returns the author of this message. </summary> | ||||
| [JsonIgnore] | [JsonIgnore] | ||||
| public User User => _client.Users[_userId, Channel.Server.Id]; | |||||
| public User User { get; private set; } | |||||
| private readonly string _userId; | |||||
| internal Message(DiscordClient client, string id, string channelId, string userId) | internal Message(DiscordClient client, string id, string channelId, string userId) | ||||
| : base(client, id) | : base(client, id) | ||||
| @@ -153,7 +149,6 @@ namespace Discord | |||||
| _userId = userId; | _userId = userId; | ||||
| Attachments = _initialAttachments; | Attachments = _initialAttachments; | ||||
| Embeds = _initialEmbeds; | Embeds = _initialEmbeds; | ||||
| MentionIds = _initialMentions; | |||||
| } | } | ||||
| internal override void OnCached() | internal override void OnCached() | ||||
| { | { | ||||
| @@ -161,6 +156,10 @@ namespace Discord | |||||
| var channel = _client.Channels[_channelId]; | var channel = _client.Channels[_channelId]; | ||||
| channel.AddMessage(this); | channel.AddMessage(this); | ||||
| Channel = channel; | Channel = channel; | ||||
| var user = _client.Users[_channelId, channel.Server?.Id]; | |||||
| //user.AddMessage(this); | |||||
| User = user; | |||||
| } | } | ||||
| internal override void OnUncached() | internal override void OnUncached() | ||||
| { | { | ||||
| @@ -169,7 +168,12 @@ namespace Discord | |||||
| if (channel != null) | if (channel != null) | ||||
| channel.RemoveMessage(this); | channel.RemoveMessage(this); | ||||
| Channel = null; | Channel = null; | ||||
| } | |||||
| var user = User; | |||||
| /*if (user != null) | |||||
| user.RemoveMessage(this);*/ | |||||
| User = null; | |||||
| } | |||||
| internal void Update(MessageInfo model) | internal void Update(MessageInfo model) | ||||
| { | { | ||||
| @@ -207,8 +211,8 @@ namespace Discord | |||||
| EditedTimestamp = model.EditedTimestamp; | EditedTimestamp = model.EditedTimestamp; | ||||
| if (model.Mentions != null) | if (model.Mentions != null) | ||||
| { | { | ||||
| MentionIds = model.Mentions.Select(x => x.Id)?.ToArray(); | |||||
| IsMentioningMe = MentionIds.Contains(_client.CurrentUserId); | |||||
| Mentions = model.Mentions.Select(x => _client.Users[x.Id, Channel.Server?.Id]).ToArray(); | |||||
| IsMentioningMe = model.Mentions.Any(x => x.Id == _client.CurrentUserId); | |||||
| } | } | ||||
| if (model.Content != null) | if (model.Content != null) | ||||
| { | { | ||||
| @@ -64,7 +64,7 @@ namespace Discord | |||||
| /// <summary> Returns a collection of all messages this user has sent on this server that are still in cache. </summary> | /// <summary> Returns a collection of all messages this user has sent on this server that are still in cache. </summary> | ||||
| [JsonIgnore] | [JsonIgnore] | ||||
| public IEnumerable<Message> Messages => _client.Messages.Where(x => x.UserId == Id && x.Server.Id == _serverId); | |||||
| public IEnumerable<Message> Messages => _client.Messages.Where(x => x.User.Id == Id && x.Server.Id == _serverId); | |||||
| /// <summary> Returns a collection of all channels this user is a member of. </summary> | /// <summary> Returns a collection of all channels this user is a member of. </summary> | ||||
| [JsonIgnore] | [JsonIgnore] | ||||