@@ -12,7 +12,7 @@ namespace Discord.API.Gateway | |||
public long? IdleSince { get; set; } | |||
[JsonProperty("afk")] | |||
public bool IsAFK { get; set; } | |||
[JsonProperty("activities")] | |||
public Game[] Activities { get; set; } | |||
[JsonProperty("game")] | |||
public Game Game { get; set; } | |||
} | |||
} |
@@ -216,7 +216,7 @@ namespace Discord.API | |||
await _sentGatewayMessageEvent.InvokeAsync(opCode).ConfigureAwait(false); | |||
} | |||
public async Task SendIdentifyAsync(int largeThreshold = 100, int shardID = 0, int totalShards = 1, bool guildSubscriptions = true, GatewayIntents? gatewayIntents = null, (UserStatus, bool, long?, GameModel[])? presence = null, RequestOptions options = null) | |||
public async Task SendIdentifyAsync(int largeThreshold = 100, int shardID = 0, int totalShards = 1, bool guildSubscriptions = true, GatewayIntents? gatewayIntents = null, (UserStatus, bool, long?, GameModel)? presence = null, RequestOptions options = null) | |||
{ | |||
options = RequestOptions.CreateOrClone(options); | |||
var props = new Dictionary<string, string> | |||
@@ -246,7 +246,7 @@ namespace Discord.API | |||
Status = presence.Value.Item1, | |||
IsAFK = presence.Value.Item2, | |||
IdleSince = presence.Value.Item3, | |||
Activities = presence.Value.Item4 | |||
Game = presence.Value.Item4, | |||
}; | |||
} | |||
@@ -268,7 +268,7 @@ namespace Discord.API | |||
options = RequestOptions.CreateOrClone(options); | |||
await SendGatewayAsync(GatewayOpCode.Heartbeat, lastSeq, options: options).ConfigureAwait(false); | |||
} | |||
public async Task SendStatusUpdateAsync(UserStatus status, bool isAFK, long? since, GameModel[] game, RequestOptions options = null) | |||
public async Task SendStatusUpdateAsync(UserStatus status, bool isAFK, long? since, GameModel game, RequestOptions options = null) | |||
{ | |||
options = RequestOptions.CreateOrClone(options); | |||
var args = new StatusUpdateParams | |||
@@ -276,7 +276,7 @@ namespace Discord.API | |||
Status = status, | |||
IdleSince = since, | |||
IsAFK = isAFK, | |||
Activities = game | |||
Game = game | |||
}; | |||
options.BucketId = GatewayBucket.Get(GatewayBucketType.PresenceUpdate).Id; | |||
await SendGatewayAsync(GatewayOpCode.StatusUpdate, args, options: options).ConfigureAwait(false); | |||
@@ -57,7 +57,8 @@ namespace Discord.WebSocket | |||
/// <inheritdoc /> | |||
public override int Latency { get; protected set; } | |||
/// <inheritdoc /> | |||
public override UserStatus Status { get; protected set; } = UserStatus.Online; | |||
public override UserStatus Status { get => _status ?? UserStatus.Online; protected set => _status = value; } | |||
private UserStatus? _status; | |||
/// <inheritdoc /> | |||
public override IActivity Activity { get => _activity.GetValueOrDefault(); protected set => _activity = Optional.Create(value); } | |||
private Optional<IActivity> _activity; | |||
@@ -449,22 +450,25 @@ namespace Discord.WebSocket | |||
return; | |||
CurrentUser.Presence = new SocketPresence(Status, Activity, null, null); | |||
var presence = BuildCurrentStatus(); | |||
var presence = BuildCurrentStatus() ?? (UserStatus.Online, false, null, null); | |||
await ApiClient.SendStatusUpdateAsync( | |||
presence.Item1, | |||
presence.Item2, | |||
presence.Item3, | |||
presence.Item4).ConfigureAwait(false); | |||
status: presence.Item1, | |||
isAFK: presence.Item2, | |||
since: presence.Item3, | |||
game: presence.Item4).ConfigureAwait(false); | |||
} | |||
private (UserStatus, bool, long?, GameModel[]) BuildCurrentStatus() | |||
private (UserStatus, bool, long?, GameModel)? BuildCurrentStatus() | |||
{ | |||
var status = Status; | |||
var status = _status; | |||
var statusSince = _statusSince; | |||
var activity = _activity; | |||
GameModel[] gameModels = null; | |||
if (status == null && !activity.IsSpecified) | |||
return null; | |||
GameModel game = null; | |||
// Discord only accepts rich presence over RPC, don't even bother building a payload | |||
if (activity.GetValueOrDefault() != null) | |||
@@ -476,15 +480,15 @@ namespace Discord.WebSocket | |||
gameModel.Type = Activity.Type; | |||
if (Activity is StreamingGame streamGame) | |||
gameModel.StreamUrl = streamGame.Url; | |||
gameModels = new[] { gameModel }; | |||
game = gameModel; | |||
} | |||
else if (activity.IsSpecified) | |||
gameModels = new GameModel[0]; | |||
game = null; | |||
return (status, | |||
return (status ?? UserStatus.Online, | |||
status == UserStatus.AFK, | |||
statusSince != null ? _statusSince.Value.ToUnixTimeMilliseconds() : (long?)null, | |||
gameModels); | |||
game); | |||
} | |||
private async Task ProcessMessageAsync(GatewayOpCode opCode, int? seq, string type, object payload) | |||