From a4a9a4b3ae75cce4c13e32f1ae873aca0033dd21 Mon Sep 17 00:00:00 2001 From: Brandon Smith Date: Tue, 22 Sep 2015 16:34:26 -0300 Subject: [PATCH] Made serveral presence improvements and additions. --- src/Discord.Net/DiscordClient.API.cs | 21 +++++++++--- src/Discord.Net/DiscordClient.cs | 44 +++++++++++++++++++------- src/Discord.Net/DiscordClientConfig.cs | 2 +- src/Discord.Net/Models/Member.cs | 25 ++++++++++++--- src/Discord.Net/Models/User.cs | 30 ++++++++++++++---- 5 files changed, 95 insertions(+), 27 deletions(-) diff --git a/src/Discord.Net/DiscordClient.API.cs b/src/Discord.Net/DiscordClient.API.cs index 569cdb696..0791d4b32 100644 --- a/src/Discord.Net/DiscordClient.API.cs +++ b/src/Discord.Net/DiscordClient.API.cs @@ -420,12 +420,23 @@ namespace Discord else msg = _messages[x.Id] ?? new Message(this, x.Id, x.ChannelId, x.Author.Id); if (msg != null) - msg.Update(x); - if (_config.TrackActivity) { - var user = _users[x.Author.Id]; - if (user != null) - user.UpdateActivity(x.Timestamp); + msg.Update(x); + if (_config.TrackActivity) + { + if (channel.IsPrivate) + { + var user = msg.User; + if (user != null) + user.UpdateActivity(msg.EditedTimestamp ?? msg.Timestamp); + } + else + { + var member = msg.Member; + if (member != null) + member.UpdateActivity(msg.EditedTimestamp ?? msg.Timestamp); + } + } } return msg; }) diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs index 9e0ad48d3..57a021b26 100644 --- a/src/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -118,18 +118,14 @@ namespace Discord { if (_voiceSocket.CurrentVoiceServerId != null) { - if (_config.TrackActivity) - { - var user = _users[e.UserId]; - if (user != null) - user.UpdateActivity(); - } var member = _members[e.UserId, _voiceSocket.CurrentVoiceServerId]; bool value = e.IsSpeaking; if (member.IsSpeaking != value) { member.IsSpeaking = value; RaiseUserIsSpeaking(member, value); + if (_config.TrackActivity) + member.UpdateActivity(); } } }; @@ -359,10 +355,10 @@ namespace Discord var data = e.Payload.ToObject(_serializer); var user = _users.GetOrAdd(data.User.Id); user.Update(data.User); - if (_config.TrackActivity) - user.UpdateActivity(); var member = _members.GetOrAdd(data.User.Id, data.GuildId); member.Update(data); + if (_config.TrackActivity) + member.UpdateActivity(); RaiseUserAdded(member); } break; @@ -455,7 +451,21 @@ namespace Discord msg = _messages.GetOrAdd(data.Id, data.ChannelId, data.Author.Id); msg.Update(data); if (_config.TrackActivity) - msg.User.UpdateActivity(data.Timestamp); + { + var channel = msg.Channel; + if (channel == null || channel.IsPrivate) + { + var user = msg.User; + if (user != null) + user.UpdateActivity(data.Timestamp); + } + else + { + var member = msg.Member; + if (member != null) + member.UpdateActivity(data.Timestamp); + } + } if (wasLocal) RaiseMessageSent(msg); RaiseMessageCreated(msg); @@ -537,11 +547,23 @@ namespace Discord if (user != null) { - if (_config.TrackActivity) - user.UpdateActivity(); if (channel != null) RaiseUserIsTyping(user, channel); } + if (_config.TrackActivity) + { + if (channel.IsPrivate) + { + if (user != null) + user.UpdateActivity(); + } + else + { + var member = _members[data.UserId, channel.ServerId]; + if (member != null) + member.UpdateActivity(); + } + } } break; diff --git a/src/Discord.Net/DiscordClientConfig.cs b/src/Discord.Net/DiscordClientConfig.cs index d8862edd0..7e07043d4 100644 --- a/src/Discord.Net/DiscordClientConfig.cs +++ b/src/Discord.Net/DiscordClientConfig.cs @@ -41,7 +41,7 @@ namespace Discord private bool _useMessageQueue = false; /// (Experimental) Maintains the LastActivity property for users, showing when they last made an action (sent message, joined server, typed, etc). public bool TrackActivity { get { return _trackActivity; } set { SetValue(ref _trackActivity, value); } } - private bool _trackActivity = false; + private bool _trackActivity = true; //Lock private bool _isLocked; diff --git a/src/Discord.Net/Models/Member.cs b/src/Discord.Net/Models/Member.cs index 3ea8684e8..b10fa15cb 100644 --- a/src/Discord.Net/Models/Member.cs +++ b/src/Discord.Net/Models/Member.cs @@ -20,11 +20,18 @@ namespace Discord public string SessionId { get; internal set; } public string Token { get; internal set; } + /// Returns the id for the game this user is currently playing. public string GameId { get; internal set; } /// Returns the current status for this user. public string Status { get; internal set; } + /// Returns the time this user's status was last changed in this server. public DateTime StatusSince { get; internal set; } + /// Returns the time this user last sent/edited a message, started typing or sent voice data in this server. + public DateTime? LastActivity { get; private set; } + /// Returns the time this user was last seen online in this server. + public DateTime? LastOnline => Status != UserStatus.Offline ? DateTime.UtcNow : _lastOnline; + private DateTime _lastOnline; public string UserId { get; } [JsonIgnore] @@ -50,7 +57,8 @@ namespace Discord _client = client; UserId = userId; ServerId = serverId; - } + Status = UserStatus.Offline; + } public override string ToString() => UserId; @@ -70,8 +78,11 @@ namespace Discord { if (Status != model.Status) { - Status = model.Status; - StatusSince = DateTime.UtcNow; + var now = DateTime.UtcNow; + Status = model.Status; + StatusSince = now; + if (Status == UserStatus.Offline) + _lastOnline = now; } GameId = model.GameId; } @@ -90,5 +101,11 @@ namespace Discord if (model.IsSuppressed.HasValue) IsSuppressed = model.IsSuppressed.Value; } - } + + internal void UpdateActivity(DateTime? activity = null) + { + if (LastActivity == null || activity > LastActivity.Value) + LastActivity = activity ?? DateTime.UtcNow; + } + } } diff --git a/src/Discord.Net/Models/User.cs b/src/Discord.Net/Models/User.cs index 73f797bfa..e117cec8d 100644 --- a/src/Discord.Net/Models/User.cs +++ b/src/Discord.Net/Models/User.cs @@ -11,6 +11,7 @@ namespace Discord { private readonly DiscordClient _client; private int _refs; + private DateTime? _lastPrivateActivity; /// Returns the unique identifier for this user. public string Id { get; } @@ -44,9 +45,27 @@ namespace Discord public IEnumerable Servers => _client.Servers.Where(x => x.HasMember(Id)); /// Returns a collection of all messages this user has sent that are still in cache. public IEnumerable Messages => _client.Messages.Where(x => x.UserId == Id); - - /// Returns the time this user last sent a message. - public DateTime? LastActivity { get; private set; } + + /// Returns the id for the game this user is currently playing. + public string GameId => Memberships.Where(x => x.GameId != null).Select(x => x.GameId).FirstOrDefault(); + /// Returns the current status for this user. + public string Status => Memberships.OrderByDescending(x => x.StatusSince).Select(x => x.Status).FirstOrDefault(); + /// Returns the time this user's status was last changed. + public DateTime StatusSince => Memberships.OrderByDescending(x => x.StatusSince).Select(x => x.StatusSince).First(); + /// Returns the time this user last sent/edited a message, started typing or sent voice data. + public DateTime? LastActivity + { + get + { + var lastServerActivity = Memberships.OrderByDescending(x => x.LastActivity).Select(x => x.LastActivity).FirstOrDefault(); + if (lastServerActivity == null || (_lastPrivateActivity != null && _lastPrivateActivity.Value > lastServerActivity.Value)) + return _lastPrivateActivity; + else + return lastServerActivity; + } + } + /// Returns the time this user was last seen online. + public DateTime? LastOnline => Memberships.OrderByDescending(x => x.LastOnline).Select(x => x.LastOnline).FirstOrDefault(); internal User(DiscordClient client, string id) { @@ -66,11 +85,10 @@ namespace Discord Email = model.Email; IsVerified = model.IsVerified; } - internal void UpdateActivity(DateTime? activity = null) { - if (LastActivity == null || activity > LastActivity.Value) - LastActivity = activity ?? DateTime.UtcNow; + if (_lastPrivateActivity == null || activity > _lastPrivateActivity.Value) + _lastPrivateActivity = activity ?? DateTime.UtcNow; } public override string ToString() => Name;