@@ -1,11 +0,0 @@ | |||||
#pragma warning disable CS1591 | |||||
using System; | |||||
namespace Discord.API.Rest | |||||
{ | |||||
public class ModifyPresenceParams | |||||
{ | |||||
public Optional<UserStatus> Status { get; set; } | |||||
public Optional<Game> Game { get; set; } | |||||
} | |||||
} |
@@ -14,6 +14,5 @@ namespace Discord | |||||
bool IsMfaEnabled { get; } | bool IsMfaEnabled { get; } | ||||
Task ModifyAsync(Action<ModifyCurrentUserParams> func, RequestOptions options = null); | Task ModifyAsync(Action<ModifyCurrentUserParams> func, RequestOptions options = null); | ||||
Task ModifyStatusAsync(Action<ModifyPresenceParams> func, RequestOptions options = null); | |||||
} | } | ||||
} | } |
@@ -50,7 +50,5 @@ namespace Discord.Rest | |||||
var model = await UserHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false); | var model = await UserHelper.ModifyAsync(this, Discord, func, options).ConfigureAwait(false); | ||||
Update(model); | Update(model); | ||||
} | } | ||||
Task ISelfUser.ModifyStatusAsync(Action<ModifyPresenceParams> func, RequestOptions options) { throw new NotSupportedException(); } | |||||
} | } | ||||
} | } |
@@ -16,6 +16,7 @@ using System.IO; | |||||
using System.Linq; | using System.Linq; | ||||
using System.Threading; | using System.Threading; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using GameModel = Discord.API.Game; | |||||
namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
{ | { | ||||
@@ -36,6 +37,7 @@ namespace Discord.WebSocket | |||||
private long _lastGuildAvailableTime; | private long _lastGuildAvailableTime; | ||||
private int _nextAudioId; | private int _nextAudioId; | ||||
private bool _canReconnect; | private bool _canReconnect; | ||||
private DateTimeOffset? _statusSince; | |||||
/// <summary> Gets the shard of of this client. </summary> | /// <summary> Gets the shard of of this client. </summary> | ||||
public int ShardId { get; } | public int ShardId { get; } | ||||
@@ -43,6 +45,8 @@ namespace Discord.WebSocket | |||||
public ConnectionState ConnectionState { get; private set; } | public ConnectionState ConnectionState { get; private set; } | ||||
/// <summary> Gets the estimated round-trip latency, in milliseconds, to the gateway server. </summary> | /// <summary> Gets the estimated round-trip latency, in milliseconds, to the gateway server. </summary> | ||||
public int Latency { get; private set; } | public int Latency { get; private set; } | ||||
internal UserStatus Status { get; private set; } | |||||
internal Game? Game { get; private set; } | |||||
//From DiscordSocketConfig | //From DiscordSocketConfig | ||||
internal int TotalShards { get; private set; } | internal int TotalShards { get; private set; } | ||||
@@ -183,8 +187,12 @@ namespace Discord.WebSocket | |||||
await ApiClient.SendIdentifyAsync(shardID: ShardId, totalShards: TotalShards).ConfigureAwait(false); | await ApiClient.SendIdentifyAsync(shardID: ShardId, totalShards: TotalShards).ConfigureAwait(false); | ||||
} | } | ||||
await _gatewayLogger.DebugAsync("Raising Event").ConfigureAwait(false); | |||||
await _connectTask.Task.ConfigureAwait(false); | await _connectTask.Task.ConfigureAwait(false); | ||||
await _gatewayLogger.DebugAsync("Sending Status").ConfigureAwait(false); | |||||
await SendStatus().ConfigureAwait(false); | |||||
await _gatewayLogger.DebugAsync("Raising Event").ConfigureAwait(false); | |||||
if (!isReconnecting) | if (!isReconnecting) | ||||
_canReconnect = true; | _canReconnect = true; | ||||
ConnectionState = ConnectionState.Connected; | ConnectionState = ConnectionState.Connected; | ||||
@@ -448,6 +456,51 @@ namespace Discord.WebSocket | |||||
} | } | ||||
} | } | ||||
public async Task SetStatus(UserStatus status) | |||||
{ | |||||
Status = status; | |||||
if (status == UserStatus.AFK) | |||||
_statusSince = DateTimeOffset.UtcNow; | |||||
else | |||||
_statusSince = null; | |||||
await SendStatus().ConfigureAwait(false); | |||||
} | |||||
public async Task SetGame(string name, string streamUrl = null, StreamType streamType = StreamType.NotStreaming) | |||||
{ | |||||
if (name != null) | |||||
Game = new Game(name, streamUrl, streamType); | |||||
else | |||||
Game = null; | |||||
CurrentUser.Presence = new SocketPresence(Status, Game); | |||||
await SendStatus().ConfigureAwait(false); | |||||
} | |||||
private async Task SendStatus() | |||||
{ | |||||
var game = Game; | |||||
var status = Status; | |||||
var statusSince = _statusSince; | |||||
CurrentUser.Presence = new SocketPresence(status, game); | |||||
GameModel gameModel; | |||||
if (game != null) | |||||
{ | |||||
gameModel = new API.Game | |||||
{ | |||||
Name = game.Value.Name, | |||||
StreamType = game.Value.StreamType, | |||||
StreamUrl = game.Value.StreamUrl | |||||
}; | |||||
} | |||||
else | |||||
gameModel = null; | |||||
await ApiClient.SendStatusUpdateAsync( | |||||
status, | |||||
status == UserStatus.AFK, | |||||
statusSince != null ? _statusSince.Value.ToUnixTimeMilliseconds() : (long?)null, | |||||
gameModel).ConfigureAwait(false); | |||||
} | |||||
private async Task ProcessMessageAsync(GatewayOpCode opCode, int? seq, string type, object payload) | private async Task ProcessMessageAsync(GatewayOpCode opCode, int? seq, string type, object payload) | ||||
{ | { | ||||
if (seq != null) | if (seq != null) | ||||
@@ -3,7 +3,6 @@ using Discord.Rest; | |||||
using System; | using System; | ||||
using System.Diagnostics; | using System.Diagnostics; | ||||
using System.Threading.Tasks; | using System.Threading.Tasks; | ||||
using GameEntity = Discord.Game; | |||||
using Model = Discord.API.User; | using Model = Discord.API.User; | ||||
namespace Discord.WebSocket | namespace Discord.WebSocket | ||||
@@ -11,8 +10,6 @@ namespace Discord.WebSocket | |||||
[DebuggerDisplay(@"{DebuggerDisplay,nq}")] | [DebuggerDisplay(@"{DebuggerDisplay,nq}")] | ||||
public class SocketSelfUser : SocketUser, ISelfUser | public class SocketSelfUser : SocketUser, ISelfUser | ||||
{ | { | ||||
private DateTimeOffset? _statusSince; | |||||
public string Email { get; private set; } | public string Email { get; private set; } | ||||
public bool IsVerified { get; private set; } | public bool IsVerified { get; private set; } | ||||
public bool IsMfaEnabled { get; private set; } | public bool IsMfaEnabled { get; private set; } | ||||
@@ -49,54 +46,6 @@ namespace Discord.WebSocket | |||||
public Task ModifyAsync(Action<ModifyCurrentUserParams> func, RequestOptions options = null) | public Task ModifyAsync(Action<ModifyCurrentUserParams> func, RequestOptions options = null) | ||||
=> UserHelper.ModifyAsync(this, Discord, func, options); | => UserHelper.ModifyAsync(this, Discord, func, options); | ||||
public async Task ModifyStatusAsync(Action<ModifyPresenceParams> func, RequestOptions options = null) | |||||
{ | |||||
var args = new ModifyPresenceParams(); | |||||
func(args); | |||||
UserStatus status; | |||||
if (args.Status.IsSpecified) | |||||
{ | |||||
status = args.Status.Value; | |||||
if (status == UserStatus.AFK) | |||||
_statusSince = DateTimeOffset.UtcNow; | |||||
else | |||||
_statusSince = null; | |||||
} | |||||
else | |||||
status = Status; | |||||
GameEntity? game; | |||||
if (args.Game.IsSpecified) | |||||
{ | |||||
var model = args.Game.Value; | |||||
if (model != null) | |||||
game = GameEntity.Create(model); | |||||
else | |||||
game = null; | |||||
} | |||||
else | |||||
game = Game; | |||||
Presence = new SocketPresence(status, game); | |||||
await SendStatus(status, game).ConfigureAwait(false); | |||||
} | |||||
internal async Task SendStatus(UserStatus status, GameEntity? game) | |||||
{ | |||||
var gameModel = game != null ? new API.Game | |||||
{ | |||||
Name = game.Value.Name, | |||||
StreamType = game.Value.StreamType, | |||||
StreamUrl = game.Value.StreamUrl | |||||
} : null; | |||||
await Discord.ApiClient.SendStatusUpdateAsync( | |||||
status, | |||||
status == UserStatus.AFK, | |||||
_statusSince != null ? _statusSince.Value.ToUnixTimeMilliseconds() : (long?)null, | |||||
gameModel).ConfigureAwait(false); | |||||
} | |||||
internal new SocketSelfUser Clone() => MemberwiseClone() as SocketSelfUser; | internal new SocketSelfUser Clone() => MemberwiseClone() as SocketSelfUser; | ||||
} | } | ||||