diff --git a/src/Discord.Net.Net45/Discord.Net.csproj b/src/Discord.Net.Net45/Discord.Net.csproj
index e1e21fecb..24844af8f 100644
--- a/src/Discord.Net.Net45/Discord.Net.csproj
+++ b/src/Discord.Net.Net45/Discord.Net.csproj
@@ -175,6 +175,9 @@
Format.cs
+
+ Helpers\EpochTime.cs
+
Helpers\Extensions.cs
diff --git a/src/Discord.Net/DiscordClient.API.cs b/src/Discord.Net/DiscordClient.API.cs
index f69307126..8957088e6 100644
--- a/src/Discord.Net/DiscordClient.API.cs
+++ b/src/Discord.Net/DiscordClient.API.cs
@@ -1,4 +1,5 @@
using Discord.API;
+using Discord.Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -638,6 +639,34 @@ namespace Discord
return _api.EditProfile(currentPassword: currentPassword, username: username, email: email ?? _currentUser?.Email, password: password,
avatarType: avatarType, avatar: avatar);
}
+ public Task SetStatus(string status = null, int? gameId = null)
+ {
+ if (status == null && gameId == null)
+ throw new ArgumentNullException("Either status or gameId must be non-null");
+
+ if (status != null)
+ {
+ switch (status)
+ {
+ case UserStatus.Online:
+ case UserStatus.Away:
+ _status = status;
+ break;
+ default:
+ throw new ArgumentException($"Invalid status, must be {UserStatus.Online} or {UserStatus.Away}");
+ }
+ }
+
+ if (gameId != null)
+ _gameId = gameId;
+
+ return SendStatus();
+ }
+ private Task SendStatus()
+ {
+ _dataSocket.SendStatus(_status == UserStatus.Away ? EpochTime.GetMilliseconds() : (ulong?)null, _gameId);
+ return TaskHelper.CompletedTask;
+ }
//Roles
/// Note: due to current API limitations, the created role cannot be returned.
diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs
index 3166803d1..734b1a59c 100644
--- a/src/Discord.Net/DiscordClient.cs
+++ b/src/Discord.Net/DiscordClient.cs
@@ -24,6 +24,8 @@ namespace Discord
private readonly ConcurrentDictionary _voiceClients;
private bool _sentInitialLog;
private uint _nextVoiceClientId;
+ private string _status;
+ private int? _gameId;
public new DiscordClientConfig Config => _config as DiscordClientConfig;
@@ -69,8 +71,13 @@ namespace Discord
_roles = new Roles(this, cacheLock);
_servers = new Servers(this, cacheLock);
_users = new Users(this, cacheLock);
+ _status = UserStatus.Online;
- this.Connected += (s, e) => _api.CancelToken = CancelToken;
+ this.Connected += async (s, e) =>
+ {
+ _api.CancelToken = CancelToken;
+ await SendStatus();
+ };
VoiceDisconnected += (s, e) =>
{
diff --git a/src/Discord.Net/Helpers/EpochTime.cs b/src/Discord.Net/Helpers/EpochTime.cs
new file mode 100644
index 000000000..8ada91c67
--- /dev/null
+++ b/src/Discord.Net/Helpers/EpochTime.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Discord.Helpers
+{
+ public class EpochTime
+ {
+ private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ public static ulong GetMilliseconds() => (ulong)(DateTime.UtcNow - epoch).TotalMilliseconds;
+ }
+}
diff --git a/src/Discord.Net/WebSockets/Data/Commands.cs b/src/Discord.Net/WebSockets/Data/Commands.cs
index e0d3d86c3..a8ba16bed 100644
--- a/src/Discord.Net/WebSockets/Data/Commands.cs
+++ b/src/Discord.Net/WebSockets/Data/Commands.cs
@@ -2,17 +2,15 @@
#pragma warning disable CS0649
#pragma warning disable CS0169
+using Discord.Helpers;
using Newtonsoft.Json;
-using System;
using System.Collections.Generic;
namespace Discord.WebSockets.Data
{
internal sealed class KeepAliveCommand : WebSocketMessage
{
- public KeepAliveCommand() : base(1, GetTimestamp()) { }
- private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
- private static ulong GetTimestamp() => (ulong)(DateTime.UtcNow - epoch).TotalMilliseconds;
+ public KeepAliveCommand() : base(1, EpochTime.GetMilliseconds()) { }
}
internal sealed class LoginCommand : WebSocketMessage
{
@@ -33,9 +31,9 @@ namespace Discord.WebSockets.Data
public class Data
{
[JsonProperty("idle_since")]
- public string IdleSince;
+ public ulong? IdleSince;
[JsonProperty("game_id")]
- public string GameId;
+ public int? GameId;
}
}
internal sealed class JoinVoiceCommand : WebSocketMessage
diff --git a/src/Discord.Net/WebSockets/Data/DataWebSocket.cs b/src/Discord.Net/WebSockets/Data/DataWebSocket.cs
index f4d8af7dd..e989acea0 100644
--- a/src/Discord.Net/WebSockets/Data/DataWebSocket.cs
+++ b/src/Discord.Net/WebSockets/Data/DataWebSocket.cs
@@ -80,13 +80,11 @@ namespace Discord.WebSockets.Data
var payload = token.ToObject();
_sessionId = payload.SessionId;
_heartbeatInterval = payload.HeartbeatInterval;
- QueueMessage(new UpdateStatusCommand());
}
else if (msg.Type == "RESUMED")
{
var payload = token.ToObject();
_heartbeatInterval = payload.HeartbeatInterval;
- QueueMessage(new UpdateStatusCommand());
}
RaiseReceivedEvent(msg.Type, token);
if (msg.Type == "READY" || msg.Type == "RESUMED")
@@ -114,6 +112,14 @@ namespace Discord.WebSockets.Data
return new KeepAliveCommand();
}
+ public void SendStatus(ulong? idleSince, int? gameId)
+ {
+ var updateStatus = new UpdateStatusCommand();
+ updateStatus.Payload.IdleSince = idleSince;
+ updateStatus.Payload.GameId = gameId;
+ QueueMessage(updateStatus);
+ }
+
public void SendJoinVoice(string serverId, string channelId)
{
var joinVoice = new JoinVoiceCommand();