Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
216 changes: 216 additions & 0 deletions DSharpPlus/Entities/DiscordApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

Expand Down Expand Up @@ -167,6 +168,41 @@ public string GenerateBotOAuth(Permissions permissions = Permissions.None)
.ToString();
}

/// <summary>
/// Generates a new OAuth2 URI for this application.
/// </summary>
/// <param name="redirectUri">Redirect URI - the URI Discord will redirect users to as part of the OAuth flow.
/// <remarks>
/// This URI <b>must</b> be already registered as a valid redirect URI for your application on the developer portal.
/// </remarks>
/// </param>
/// <param name="permissions">Permissions for your bot. Only required if the <seealso cref="OAuthScope.Bot"/> scope is passed.</param>
/// <param name="scopes">OAuth scopes for your application.</param>
public string GenerateOAuthUri(string redirectUri = null, Permissions? permissions = null, params OAuthScope[] scopes)
{
permissions &= PermissionMethods.FULL_PERMS;

var scopeBuilder = new StringBuilder();

foreach(var v in scopes)
scopeBuilder.Append(" ").Append(this.TranslateOAuthScope(v));


var queryBuilder = new QueryUriBuilder("https://discord.com/oauth2/authorize")
.AddParameter("client_id", this.Id.ToString(CultureInfo.InvariantCulture))
.AddParameter("scope", scopeBuilder.ToString().Trim());

if (permissions != null)
queryBuilder.AddParameter("permissions", ((long)permissions).ToString(CultureInfo.InvariantCulture));

// response_type=code is always given for /authorize
if (redirectUri != null)
queryBuilder.AddParameter("redirect_uri", redirectUri)
.AddParameter("response_type", "code");

return queryBuilder.ToString();
}

/// <summary>
/// Checks whether this <see cref="DiscordApplication"/> is equal to another object.
/// </summary>
Expand Down Expand Up @@ -218,6 +254,37 @@ public bool Equals(DiscordApplication e)
/// <returns>Whether the two applications are not equal.</returns>
public static bool operator !=(DiscordApplication e1, DiscordApplication e2)
=> !(e1 == e2);

private string TranslateOAuthScope(OAuthScope scope)
{
return scope switch
{
OAuthScope.Identify => "identify",
OAuthScope.Email => "email",
OAuthScope.Connections => "connections",
OAuthScope.Guilds => "guilds",
OAuthScope.GuildsJoin => "guilds.join",
OAuthScope.GuildsMembersRead => "guilds.members.read",
OAuthScope.GdmJoin => "gdm.join",
OAuthScope.Rpc => "rpc",
OAuthScope.RpcNotificationsRead => "rpc.notifications.read",
OAuthScope.RpcVoiceRead => "rpc.voice.read",
OAuthScope.RpcVoiceWrite => "rpc.voice.write",
OAuthScope.RpcActivitiesWrite => "rpc.activities.write",
OAuthScope.Bot => "bot",
OAuthScope.WebhookIncoming => "webhook.incoming",
OAuthScope.MessagesRead => "messages.read",
OAuthScope.ApplicationsBuildsUpload => "applications.builds.upload",
OAuthScope.ApplicationsBuildsRead => "applications.builds.read",
OAuthScope.ApplicationsCommands => "applications.commands",
OAuthScope.ApplicationsStoreUpdate => "applications.store.update",
OAuthScope.ApplicationsEntitlements => "applications.entitlements",
OAuthScope.ActivitiesRead => "activities.read",
OAuthScope.ActivitiesWrite => "activities.write",
OAuthScope.RelationshipsRead => "relationships.read",
_ => null
};
}
}

public abstract class DiscordAsset
Expand Down Expand Up @@ -367,4 +434,153 @@ public enum ApplicationAssetType : int
/// </summary>
LargeImage = 2
}

/// <summary>
/// Represents the possible OAuth scopes for application authorization.
/// </summary>
public enum OAuthScope : int
{
/// <summary>
/// Allows <c>/users/@me</c> without <c>email</c>.
/// </summary>
Identify,

/// <summary>
/// Enables <c>/users/@me</c> to return <c>email</c>.
/// </summary>
Email,

/// <summary>
/// Allows <c>/users/@me/connections</c> to return linked third-party accounts.
/// </summary>
Connections,

/// <summary>
/// Allows <c>/users/@me/guilds</c> to return basic information about all of a user's guilds.
/// </summary>
Guilds,

/// <summary>
/// Allows <c>/guilds/{guild.id}/members/{user.id}</c> to be used for joining users into a guild.
/// </summary>
GuildsJoin,

/// <summary>
/// Allows <c>/users/@me/guilds/{guild.id}/members</c> to return a user's member information in a guild.
/// </summary>
GuildsMembersRead,

/// <summary>
/// Allows your app to join users into a group DM.
/// </summary>
GdmJoin,

/// <summary>
/// For local RPC server access, this allows you to control a user's local Discord client.
/// </summary>
/// <remarks>
/// This scope requires Discord approval.
/// </remarks>
Rpc,

/// <summary>
/// For local RPC server access, this allows you to receive notifications pushed to the user.
/// </summary>
/// <remarks>
/// This scope requires Discord approval.
/// </remarks>
RpcNotificationsRead,

/// <summary>
/// For local RPC server access, this allows you to read a user's voice settings and listen for voice events.
/// </summary>
/// <remarks>
/// This scope requires Discord approval.
/// </remarks>
RpcVoiceRead,

/// <summary>
/// For local RPC server access, this allows you to update a user's voice settings.
/// </summary>
/// <remarks>
/// This scope requires Discord approval.
/// </remarks>
RpcVoiceWrite,

/// <summary>
/// For local RPC server access, this allows you to update a user's activity.
/// </summary>
/// <remarks>
/// This scope requires Discord approval.
/// </remarks>
RpcActivitiesWrite,

/// <summary>
/// For OAuth2 bots, this puts the bot in the user's selected guild by default.
/// </summary>
Bot,

/// <summary>
/// This generates a webhook that is returned in the OAuth token response for authorization code grants.
/// </summary>
WebhookIncoming,

/// <summary>
/// For local RPC server access, this allows you to read messages from all client channels
/// (otherwise restricted to channels/guilds your application creates).
/// </summary>
MessagesRead,

/// <summary>
/// Allows your application to upload/update builds for a user's applications.
/// </summary>
/// <remarks>
/// This scope requires Discord approval.
/// </remarks>
ApplicationsBuildsUpload,

/// <summary>
/// Allows your application to read build data for a user's applications.
/// </summary>
ApplicationsBuildsRead,

/// <summary>
/// Allows your application to use application commands in a guild.
/// </summary>
ApplicationsCommands,

/// <summary>
/// Allows your application to read and update store data (SKUs, store listings, achievements etc.) for a user's applications.
/// </summary>
ApplicationsStoreUpdate,

/// <summary>
/// Allows your application to read entitlements for a user's applications.
/// </summary>
ApplicationsEntitlements,

/// <summary>
/// Allows your application to fetch data from a user's "Now Playing/Recently Played" list.
/// </summary>
/// <remarks>
/// This scope requires Discord approval.
/// </remarks>
ActivitiesRead,

/// <summary>
/// Allows your application to update a user's activity.
/// </summary>
/// <remarks>
/// Outside of the GameSDK activity manager, this scope requires Discord approval.
/// </remarks>
ActivitiesWrite,

/// <summary>
/// Allows your application to know a user's friends and implicit relationships.
/// </summary>
/// <remarks>
/// This scope requires Discord approval.
/// </remarks>
RelationshipsRead
}
}