Implement basic RPC configuration API endpoint (#864)

* Implement basic RPC information endpoint with test data

* Implement configuration options for RPC

* Rename RpcConfiguration to RpcResponse

* Rider insists on modifying dataSources.xml

* Implement documentation and fix code quality/gitignore issues

* Use SerializableAttribute instead of UsedImplicitlyAttribute

* Add warning regarding nullable assets

* Prevent precision issues with application ID

* Check asset properties for null/whitespace and return null
This commit is contained in:
koko 2023-08-12 18:27:45 -04:00 committed by GitHub
parent 7939211308
commit e072201ec7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 123 additions and 20 deletions

1
.gitignore vendored
View file

@ -3,6 +3,7 @@
/_ReSharper.Caches/
/.idea/.idea.ProjectLighthouse/.idea/workspace.xml
/.idea/.idea.ProjectLighthouse/.idea/dataSources/
/.idea/.idea.ProjectLighthouse/.idea/dataSources.xml
/.idea/.idea.ProjectLighthouse/.idea/dataSources.local.xml
/ProjectLighthouse/ProjectLighthouse.csproj.user
*.sln.DotSettings.user

View file

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="lighthouse@localhost" uuid="3bfb85d6-6cc2-427d-9288-06e05ab58c10">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>com.mysql.cj.jdbc.NonRegisteringDriver</jdbc-driver>
<jdbc-url>jdbc:mysql://localhost:3306/lighthouse</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
<data-source source="LOCAL" name="Lighthouse Production" read-only="true" uuid="b323608d-d984-40d0-942e-2c2ea35006d8">
<driver-ref>mariadb</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mariadb://localhost:3306</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

38
Documentation/RPC.md Normal file
View file

@ -0,0 +1,38 @@
# RPC (Rich Presence)
Lighthouse supports Discord's [Rich Presence](https://discordapp.com/rich-presence) feature, which allows you
to display your current activity in Lighthouse to your Discord friends.
This can be done by utilizing a pre-existing RPC client, such as [this one](https://github.com/LBPUnion/PLRPC),
or by creating your own. This page will explain how to utilize the `/api/v1/rpc` endpoint to access the
required information.
## Authentication
This endpoint does not require any form of authentication and is available to use without restriction, aside
from any server admin imposed rate limiting.
## Endpoints
### GET `/api/v1/rpc`
Returns a JSON object containing the following information:
- `applicationId`: The ID of the Discord application.
- `partyIdPrefix`: The prefix to use for the party ID. This is used to prevent collisions between
multiple instances of Lighthouse running on the same Discord application.
- `usernameType`: Some compatible APIs require usernames instead of user IDs. A return value of `0`
indicates that usernames should be used, while a return value of `1` indicates that user
IDs should be used.
- `assets`: A JSON object containing the following information:
- `podAsset`: Asset used when in the Pod.
- `moonAsset`: Asset used when creating on the Moon.
- `remoteMoonAsset`: Asset used when creating on a remote Moon.
- `developerAsset`: Asset used when playing a story mode level.
- `developerAdventureAsset`: Asset used when playing an adventure level.
- `dlcAsset`: Asset used when playing a DLC level.
- `fallbackAsset`: Asset used when client can't determine the slot type.
> **Warning**
> All `assets` properties are nullable and will return `null` if not set in configuration. Be sure to account
> for this when using the returned data.

View file

@ -0,0 +1,18 @@
using LBPUnion.ProjectLighthouse.Configuration;
using LBPUnion.ProjectLighthouse.Servers.API.Responses;
using Microsoft.AspNetCore.Mvc;
namespace LBPUnion.ProjectLighthouse.Servers.API.Controllers;
public class RpcController : ApiEndpointController
{
/// <summary>
/// Returns basic information that Discord RPC clients can use for self-configuration.
/// </summary>
/// <returns>RpcResponse</returns>
/// <response code="200">The RPC configuration.</response>
[HttpGet("rpc")]
[ProducesResponseType(typeof(RpcResponse), StatusCodes.Status200OK)]
public IActionResult GetRpcConfiguration() =>
this.Ok(RpcResponse.CreateFromConfiguration(ServerConfiguration.Instance.RichPresenceConfiguration));
}

View file

@ -0,0 +1,33 @@
#nullable disable
using LBPUnion.ProjectLighthouse.Configuration.ConfigurationCategories;
namespace LBPUnion.ProjectLighthouse.Servers.API.Responses;
public class RpcResponse
{
public string ApplicationId { get; set; }
public string PartyIdPrefix { get; set; }
public UsernameType UsernameType { get; set; }
public RpcAssets Assets { get; set; }
public static RpcResponse CreateFromConfiguration(RichPresenceConfiguration configuration) =>
new()
{
ApplicationId = configuration.ApplicationId,
PartyIdPrefix = configuration.PartyIdPrefix,
UsernameType = configuration.UsernameType,
Assets = new RpcAssets
{
PodAsset = AssetConvertNull(configuration.Assets.PodAsset),
MoonAsset = AssetConvertNull(configuration.Assets.MoonAsset),
RemoteMoonAsset = AssetConvertNull(configuration.Assets.RemoteMoonAsset),
DeveloperAsset = AssetConvertNull(configuration.Assets.DeveloperAsset),
DeveloperAdventureAsset = AssetConvertNull(configuration.Assets.DeveloperAdventureAsset),
DlcAsset = AssetConvertNull(configuration.Assets.DlcAsset),
FallbackAsset = AssetConvertNull(configuration.Assets.FallbackAsset),
},
};
private static string AssetConvertNull(string asset) => string.IsNullOrWhiteSpace(asset) ? null : asset;
}

View file

@ -0,0 +1,31 @@
using System;
namespace LBPUnion.ProjectLighthouse.Configuration.ConfigurationCategories;
// ReSharper disable UnusedMember.Global
[Serializable]
public class RichPresenceConfiguration
{
public string ApplicationId { get; set; } = "1060973475151495288";
public string PartyIdPrefix { get; set; } = "project-lighthouse";
public UsernameType UsernameType { get; set; } = UsernameType.Integer;
public RpcAssets Assets { get; set; } = new();
}
public class RpcAssets
{
public string PodAsset { get; init; }
public string MoonAsset { get; init; }
public string RemoteMoonAsset { get; init; }
public string DeveloperAsset { get; init; }
public string DeveloperAdventureAsset { get; init; }
public string DlcAsset { get; init; }
public string FallbackAsset { get; init; }
}
public enum UsernameType
{
Integer = 0,
Username = 1,
}

View file

@ -11,7 +11,7 @@ public class ServerConfiguration : ConfigurationBase<ServerConfiguration>
// This is so Lighthouse can properly identify outdated configurations and update them with newer settings accordingly.
// If you are modifying anything here, this value MUST be incremented.
// Thanks for listening~
public override int ConfigVersion { get; set; } = 21;
public override int ConfigVersion { get; set; } = 22;
public override string ConfigName { get; set; } = "lighthouse.yml";
public string WebsiteListenUrl { get; set; } = "http://localhost:10060";
@ -42,6 +42,7 @@ public class ServerConfiguration : ConfigurationBase<ServerConfiguration>
public CustomizationConfiguration Customization { get; set; } = new();
public RateLimitConfiguration RateLimitConfiguration { get; set; } = new();
public TwoFactorConfiguration TwoFactorConfiguration { get; set; } = new();
public RichPresenceConfiguration RichPresenceConfiguration { get; set; } = new();
public override ConfigurationBase<ServerConfiguration> Deserialize(IDeserializer deserializer, string text) => deserializer.Deserialize<ServerConfiguration>(text);
}