Browse Source

feature(binbrk): Add properties missing from User and Activity models (#1237)

* WIP commit, update IActivity and IUser with missing types

* incomplete implementation of interfaces

* Add implementation of activity flags, and extension method to check flag

* remove usings that were not required

* clean up files and add documentation where missing

* remove unused usings

* Add remark saying that premium_type info may be inaccessible to bots

it seems that this information can not be accessed by any user,
and may require the identity oauth scope

* Add locale property to the user model

adds the locale property to the user model, which appears not to be
specified for bots

* rename ActivityFlags

* Add incomplete xmldoc to ActivityFlag

Added xmldoc to the ActivityFlag type, excluded flags that i was unsure about

* rename the UserFlags file

* Add incomplete xmldoc to UserFlag enum

* Remove unnecessary extension methods and use built-in functionality

* use <c> tag for xmldoc 'null's

* Add xmldoc for JoinRequest ActivityFlag

* improve the PremiumType xmldoc

* Add zero activityflag

* Add summary tag verbs, example of IUser locale

* Rename Flag enum types to use Properties suffix

* Expose the details field in the Game model

* update Activity extension methods to support Details field

* Use inherited Details implementation in RichGame

* lint: remove commented out code from debugging

* Fix issue in previous commit

* Move oauth-only user fields to SelfUser classes

Moves the implementation of the Flags, PremiumType, and Locale user fields to ISelfUser classes. In testing, it seemed that normal bot accounts did not have this information supplied to them. When tested with a Bearer token in the Rest client, these fields are set.

* remove old HypeSquadEvents flag that appears to have been replaced with the new HypeSquad flags
tags/2.2.0
Chris Johnston Christopher F 6 years ago
parent
commit
40844b9e13
12 changed files with 207 additions and 11 deletions
  1. +38
    -0
      src/Discord.Net.Core/Entities/Activities/ActivityProperties.cs
  2. +7
    -1
      src/Discord.Net.Core/Entities/Activities/Game.cs
  3. +17
    -0
      src/Discord.Net.Core/Entities/Activities/IActivity.cs
  4. +0
    -4
      src/Discord.Net.Core/Entities/Activities/RichGame.cs
  5. +28
    -0
      src/Discord.Net.Core/Entities/Users/ISelfUser.cs
  6. +21
    -0
      src/Discord.Net.Core/Entities/Users/PremiumType.cs
  7. +41
    -0
      src/Discord.Net.Core/Entities/Users/UserProperties.cs
  8. +2
    -0
      src/Discord.Net.Rest/API/Common/Game.cs
  9. +7
    -1
      src/Discord.Net.Rest/API/Common/User.cs
  10. +12
    -0
      src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs
  11. +21
    -0
      src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs
  12. +13
    -5
      src/Discord.Net.WebSocket/Extensions/EntityExtensions.cs

+ 38
- 0
src/Discord.Net.Core/Entities/Activities/ActivityProperties.cs View File

@@ -0,0 +1,38 @@
using System;

namespace Discord
{
/// <summary>
/// Flags for the <see cref="IActivity.Flags"/> property, that are ORd together.
/// These describe what the activity payload includes.
/// </summary>
[Flags]
public enum ActivityProperties
{
/// <summary>
/// Indicates that no actions on this activity can be taken.
/// </summary>
None = 0,
Instance = 1,
/// <summary>
/// Indicates that this activity can be joined.
/// </summary>
Join = 0b10,
/// <summary>
/// Indicates that this activity can be spectated.
/// </summary>
Spectate = 0b100,
/// <summary>
/// Indicates that a user may request to join an activity.
/// </summary>
JoinRequest = 0b1000,
/// <summary>
/// Indicates that a user can listen along in Spotify.
/// </summary>
Sync = 0b10000,
/// <summary>
/// Indicates that a user can play this song.
/// </summary>
Play = 0b100000
}
}

+ 7
- 1
src/Discord.Net.Core/Entities/Activities/Game.cs View File

@@ -12,6 +12,10 @@ namespace Discord
public string Name { get; internal set; }
/// <inheritdoc/>
public ActivityType Type { get; internal set; }
/// <inheritdoc/>
public ActivityProperties Flags { get; internal set; }
/// <inheritdoc/>
public string Details { get; internal set; }

internal Game() { }
/// <summary>
@@ -19,10 +23,12 @@ namespace Discord
/// </summary>
/// <param name="name">The name of the game.</param>
/// <param name="type">The type of activity.</param>
public Game(string name, ActivityType type = ActivityType.Playing)
public Game(string name, ActivityType type = ActivityType.Playing, ActivityProperties flags = ActivityProperties.None, string details = null)
{
Name = name;
Type = type;
Flags = flags;
Details = details;
}
/// <summary> Returns the name of the <see cref="Game"/>. </summary>


+ 17
- 0
src/Discord.Net.Core/Entities/Activities/IActivity.cs View File

@@ -19,5 +19,22 @@ namespace Discord
/// The type of activity.
/// </returns>
ActivityType Type { get; }
/// <summary>
/// Gets the flags that are relevant to this activity.
/// </summary>
/// <remarks>
/// This value is determined by bitwise OR-ing <see cref="ActivityProperties"/> values together.
/// </remarks>
/// <returns>
/// The value of flags for this activity.
/// </returns>
ActivityProperties Flags { get; }
/// <summary>
/// Gets the details on what the player is currently doing.
/// </summary>
/// <returns>
/// A string describing what the player is doing.
/// </returns>
string Details { get; }
}
}

+ 0
- 4
src/Discord.Net.Core/Entities/Activities/RichGame.cs View File

@@ -10,10 +10,6 @@ namespace Discord
{
internal RichGame() { }

/// <summary>
/// Gets what the player is currently doing.
/// </summary>
public string Details { get; internal set; }
/// <summary>
/// Gets the user's current party status.
/// </summary>


+ 28
- 0
src/Discord.Net.Core/Entities/Users/ISelfUser.cs View File

@@ -26,6 +26,34 @@ namespace Discord
/// <c>true</c> if this user has enabled multi-factor authentication on their account; <c>false</c> if not.
/// </returns>
bool IsMfaEnabled { get; }
/// <summary>
/// Gets the flags that are applied to a user's account.
/// </summary>
/// <remarks>
/// This value is determined by bitwise OR-ing <see cref="UserProperties"/> values together.
/// </remarks>
/// <returns>
/// The value of flags for this user.
/// </returns>
UserProperties Flags { get; }
/// <summary>
/// Gets the type of Nitro subscription that is active on this user's account.
/// </summary>
/// <remarks>
/// This information may only be available with the identify OAuth scope.
/// </remarks>
/// <returns>
/// The type of Nitro subscription the user subscribes to, if any.
/// </returns>
PremiumType PremiumType { get; }
/// <summary>
/// Gets the user's chosen language option.
/// </summary>
/// <returns>
/// The IETF language tag of the user's chosen region, if provided.
/// For example, a locale of "English, US" is "en-US", "Chinese (Taiwan)" is "zh-TW", etc.
/// </returns>
string Locale { get; }

/// <summary>
/// Modifies the user's properties.


+ 21
- 0
src/Discord.Net.Core/Entities/Users/PremiumType.cs View File

@@ -0,0 +1,21 @@
namespace Discord
{
/// <summary>
/// Specifies the type of subscription a user is subscribed to.
/// </summary>
public enum PremiumType
{
/// <summary>
/// No subscription.
/// </summary>
None = 0,
/// <summary>
/// Nitro Classic subscription. Includes app perks like animated emojis and avatars, but not games.
/// </summary>
NitroClassic = 1,
/// <summary>
/// Nitro subscription. Includes app perks as well as the games subscription service.
/// </summary>
Nitro = 2
}
}

+ 41
- 0
src/Discord.Net.Core/Entities/Users/UserProperties.cs View File

@@ -0,0 +1,41 @@
using System;

namespace Discord
{
[Flags]
public enum UserProperties
{
/// <summary>
/// Default value for flags, when none are given to an account.
/// </summary>
None = 0,
/// <summary>
/// Flag given to Discord staff.
/// </summary>
Staff = 0b1,
/// <summary>
/// Flag given to Discord partners.
/// </summary>
Partner = 0b10,
/// <summary>
/// Flag given to users who have participated in the bug report program.
/// </summary>
BugHunter = 0b1000,
/// <summary>
/// Flag given to users who are in the HypeSquad House of Bravery.
/// </summary>
HypeSquadBravery = 0b100_0000,
/// <summary>
/// Flag given to users who are in the HypeSquad House of Brilliance.
/// </summary>
HypeSquadBrilliance = 0b1000_0000,
/// <summary>
/// Flag given to users who are in the HypeSquad House of Balance.
/// </summary>
HypeSquadBalance = 0b1_0000_0000,
/// <summary>
/// Flag given to users who subscribed to Nitro before games were added.
/// </summary>
EarlySupporter = 0b10_0000_0000,
}
}

+ 2
- 0
src/Discord.Net.Rest/API/Common/Game.cs View File

@@ -33,6 +33,8 @@ namespace Discord.API
public Optional<string> SyncId { get; set; }
[JsonProperty("session_id")]
public Optional<string> SessionId { get; set; }
[JsonProperty("Flags")]
public Optional<ActivityProperties> Flags { get; set; }

[OnError]
internal void OnError(StreamingContext context, ErrorContext errorContext)


+ 7
- 1
src/Discord.Net.Rest/API/Common/User.cs View File

@@ -1,4 +1,4 @@
#pragma warning disable CS1591
#pragma warning disable CS1591
using Newtonsoft.Json;

namespace Discord.API
@@ -23,5 +23,11 @@ namespace Discord.API
public Optional<string> Email { get; set; }
[JsonProperty("mfa_enabled")]
public Optional<bool> MfaEnabled { get; set; }
[JsonProperty("flags")]
public Optional<UserProperties> Flags { get; set; }
[JsonProperty("premium_type")]
public Optional<PremiumType> PremiumType { get; set; }
[JsonProperty("locale")]
public Optional<string> Locale { get; set; }
}
}

+ 12
- 0
src/Discord.Net.Rest/Entities/Users/RestSelfUser.cs View File

@@ -17,6 +17,12 @@ namespace Discord.Rest
public bool IsVerified { get; private set; }
/// <inheritdoc />
public bool IsMfaEnabled { get; private set; }
/// <inheritdoc />
public UserProperties Flags { get; private set; }
/// <inheritdoc />
public PremiumType PremiumType { get; private set; }
/// <inheritdoc />
public string Locale { get; private set; }

internal RestSelfUser(BaseDiscordClient discord, ulong id)
: base(discord, id)
@@ -39,6 +45,12 @@ namespace Discord.Rest
IsVerified = model.Verified.Value;
if (model.MfaEnabled.IsSpecified)
IsMfaEnabled = model.MfaEnabled.Value;
if (model.Flags.IsSpecified)
Flags = (UserProperties)model.Flags.Value;
if (model.PremiumType.IsSpecified)
PremiumType = model.PremiumType.Value;
if (model.Locale.IsSpecified)
Locale = model.Locale.Value;
}

/// <inheritdoc />


+ 21
- 0
src/Discord.Net.WebSocket/Entities/Users/SocketSelfUser.cs View File

@@ -30,6 +30,12 @@ namespace Discord.WebSocket
public override string AvatarId { get { return GlobalUser.AvatarId; } internal set { GlobalUser.AvatarId = value; } }
/// <inheritdoc />
internal override SocketPresence Presence { get { return GlobalUser.Presence; } set { GlobalUser.Presence = value; } }
/// <inheritdoc />
public UserProperties Flags { get; internal set; }
/// <inheritdoc />
public PremiumType PremiumType { get; internal set; }
/// <inheritdoc />
public string Locale { get; internal set; }

/// <inheritdoc />
public override bool IsWebhook => false;
@@ -63,6 +69,21 @@ namespace Discord.WebSocket
IsMfaEnabled = model.MfaEnabled.Value;
hasGlobalChanges = true;
}
if (model.Flags.IsSpecified && model.Flags.Value != Flags)
{
Flags = (UserProperties)model.Flags.Value;
hasGlobalChanges = true;
}
if (model.PremiumType.IsSpecified && model.PremiumType.Value != PremiumType)
{
PremiumType = model.PremiumType.Value;
hasGlobalChanges = true;
}
if (model.Locale.IsSpecified && model.Locale.Value != Locale)
{
Locale = model.Locale.Value;
hasGlobalChanges = true;
}
return hasGlobalChanges;
}



+ 13
- 5
src/Discord.Net.WebSocket/Extensions/EntityExtensions.cs View File

@@ -25,7 +25,8 @@ namespace Discord.WebSocket
Artists = model.State.GetValueOrDefault()?.Split(';').Select(x=>x?.Trim()).ToImmutableArray(),
Duration = timestamps?.End - timestamps?.Start,
AlbumArtUrl = albumArtId != null ? CDN.GetSpotifyAlbumArtUrl(albumArtId) : null,
Type = ActivityType.Listening
Type = ActivityType.Listening,
Flags = model.Flags.GetValueOrDefault(),
};
}

@@ -44,18 +45,25 @@ namespace Discord.WebSocket
LargeAsset = assets?[1],
Party = model.Party.IsSpecified ? model.Party.Value.ToEntity() : null,
Secrets = model.Secrets.IsSpecified ? model.Secrets.Value.ToEntity() : null,
Timestamps = model.Timestamps.IsSpecified ? model.Timestamps.Value.ToEntity() : null
Timestamps = model.Timestamps.IsSpecified ? model.Timestamps.Value.ToEntity() : null,
Flags = model.Flags.GetValueOrDefault()
};
}
// Stream Game
if (model.StreamUrl.IsSpecified)
{
return new StreamingGame(
model.Name,
model.StreamUrl.Value);
model.Name,
model.StreamUrl.Value)
{
Flags = model.Flags.GetValueOrDefault(),
Details = model.Details.GetValueOrDefault()
};
}
// Normal Game
return new Game(model.Name, model.Type.GetValueOrDefault() ?? ActivityType.Playing);
return new Game(model.Name, model.Type.GetValueOrDefault() ?? ActivityType.Playing,
model.Flags.IsSpecified ? model.Flags.Value : ActivityProperties.None,
model.Details.GetValueOrDefault());
}

// (Small, Large)


Loading…
Cancel
Save