@@ -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; | |||
}) | |||
@@ -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<Events.GuildMemberAdd>(_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; | |||
@@ -41,7 +41,7 @@ namespace Discord | |||
private bool _useMessageQueue = false; | |||
/// <summary> (Experimental) Maintains the LastActivity property for users, showing when they last made an action (sent message, joined server, typed, etc). </summary> | |||
public bool TrackActivity { get { return _trackActivity; } set { SetValue(ref _trackActivity, value); } } | |||
private bool _trackActivity = false; | |||
private bool _trackActivity = true; | |||
//Lock | |||
private bool _isLocked; | |||
@@ -20,11 +20,18 @@ namespace Discord | |||
public string SessionId { get; internal set; } | |||
public string Token { get; internal set; } | |||
/// <summary> Returns the id for the game this user is currently playing. </summary> | |||
public string GameId { get; internal set; } | |||
/// <summary> Returns the current status for this user. </summary> | |||
public string Status { get; internal set; } | |||
/// <summary> Returns the time this user's status was last changed in this server. </summary> | |||
public DateTime StatusSince { get; internal set; } | |||
/// <summary> Returns the time this user last sent/edited a message, started typing or sent voice data in this server. </summary> | |||
public DateTime? LastActivity { get; private set; } | |||
/// <summary> Returns the time this user was last seen online in this server. </summary> | |||
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; | |||
} | |||
} | |||
} |
@@ -11,6 +11,7 @@ namespace Discord | |||
{ | |||
private readonly DiscordClient _client; | |||
private int _refs; | |||
private DateTime? _lastPrivateActivity; | |||
/// <summary> Returns the unique identifier for this user. </summary> | |||
public string Id { get; } | |||
@@ -44,9 +45,27 @@ namespace Discord | |||
public IEnumerable<Server> Servers => _client.Servers.Where(x => x.HasMember(Id)); | |||
/// <summary> Returns a collection of all messages this user has sent that are still in cache. </summary> | |||
public IEnumerable<Message> Messages => _client.Messages.Where(x => x.UserId == Id); | |||
/// <summary> Returns the time this user last sent a message. </summary> | |||
public DateTime? LastActivity { get; private set; } | |||
/// <summary> Returns the id for the game this user is currently playing. </summary> | |||
public string GameId => Memberships.Where(x => x.GameId != null).Select(x => x.GameId).FirstOrDefault(); | |||
/// <summary> Returns the current status for this user. </summary> | |||
public string Status => Memberships.OrderByDescending(x => x.StatusSince).Select(x => x.Status).FirstOrDefault(); | |||
/// <summary> Returns the time this user's status was last changed. </summary> | |||
public DateTime StatusSince => Memberships.OrderByDescending(x => x.StatusSince).Select(x => x.StatusSince).First(); | |||
/// <summary> Returns the time this user last sent/edited a message, started typing or sent voice data. </summary> | |||
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; | |||
} | |||
} | |||
/// <summary> Returns the time this user was last seen online. </summary> | |||
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; | |||