Discord without auth & "Hidden Region" instead of blank (#4496)

* Rich Presence w/o requiring access to friends list

Thank you Signal Linden for the pointer from https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#af0a85e30f2b3d8a0b502fd23744ee58e
"Note: On Desktop, rich presence can be set before calling Client::Connect, but it will be cleared if the Client connects. When Client is not connected, this sets the rich presence in the current user's Discord client when available."
This lead me to setting the Application ID here https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#ad452335c06b28be0406dab824acccc49 in place of setting it on
https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1AuthorizationArgs.html which would lead Authorize, GetToken, UpdateToken, Connect, and so on.
This means we don't even need the SecAPI saveCredential, loadCredential and deleteCredential parts now.

* Discord integration is enabled by default per spec

now that we don't need the user to authorise Discord SDK to have
any access to the user's friends list, etc. (which are Discord
Relationships related, and not needed just for Rich Presence).

* "Hidden Region" if Discord location sharing is off

instead of blank. The coords are hidden too, but the Party numbers
are still shown, for consistency with TPVs' implementations.

* Remove toggleDiscordIntegration declaration

The definition had already been removed, I had forgotten to remove
this one.
master
Erik Kundiman 2025-08-09 01:45:26 +08:00 committed by GitHub
parent 7f276f81ed
commit 971f131ba7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 41 additions and 119 deletions

View File

@ -1159,7 +1159,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
<integer>1</integer>
</map>
<key>ShowDiscordActivityDetails</key>
<map>

View File

@ -5914,100 +5914,21 @@ void LLAppViewer::initDiscordSocial()
gDiscordPartyMaxSize = 0;
gDiscordTimestampsStart = time(nullptr);
gDiscordClient = std::make_shared<discordpp::Client>();
gDiscordClient->SetStatusChangedCallback([](discordpp::Client::Status status, discordpp::Client::Error, int32_t) {
if (status == discordpp::Client::Status::Ready)
{
updateDiscordActivity();
}
});
if (gSavedSettings.getBOOL("EnableDiscord"))
{
auto credential = gSecAPIHandler->loadCredential("Discord");
if (credential.notNull())
{
gDiscordClient->UpdateToken(discordpp::AuthorizationTokenType::Bearer, credential->getAuthenticator()["token"].asString(), [](discordpp::ClientResult result) {
if (result.Successful())
gDiscordClient->Connect();
else
LL_WARNS("Discord") << result.Error() << LL_ENDL;
});
}
else
{
LL_WARNS("Discord") << "Integration was enabled, but no credentials. Disabling integration." << LL_ENDL;
gSavedSettings.setBOOL("EnableDiscord", false);
}
}
}
void LLAppViewer::toggleDiscordIntegration(const LLSD& value)
{
static const uint64_t APPLICATION_ID = 1394782217405862001;
if (value.asBoolean())
{
discordpp::AuthorizationArgs args{};
args.SetClientId(APPLICATION_ID);
args.SetScopes(discordpp::Client::GetDefaultPresenceScopes());
auto codeVerifier = gDiscordClient->CreateAuthorizationCodeVerifier();
args.SetCodeChallenge(codeVerifier.Challenge());
gDiscordClient->Authorize(args, [codeVerifier](auto result, auto code, auto redirectUri) {
if (result.Successful())
{
gDiscordClient->GetToken(APPLICATION_ID, code, codeVerifier.Verifier(), redirectUri, [](discordpp::ClientResult result, std::string accessToken, std::string, discordpp::AuthorizationTokenType, int32_t, std::string) {
if (result.Successful())
{
gDiscordClient->UpdateToken(discordpp::AuthorizationTokenType::Bearer, accessToken, [accessToken](discordpp::ClientResult result) {
if (result.Successful())
{
LLSD authenticator = LLSD::emptyMap();
authenticator["token"] = accessToken;
gSecAPIHandler->saveCredential(gSecAPIHandler->createCredential("Discord", LLSD::emptyMap(), authenticator), true);
gDiscordClient->Connect();
}
else
{
LL_WARNS("Discord") << result.Error() << LL_ENDL;
}
});
}
else
{
LL_WARNS("Discord") << result.Error() << LL_ENDL;
}
});
}
else
{
LL_WARNS("Discord") << result.Error() << LL_ENDL;
gSavedSettings.setBOOL("EnableDiscord", false);
}
});
}
else
{
gDiscordClient->Disconnect();
auto credential = gSecAPIHandler->loadCredential("Discord");
if (credential.notNull())
{
gDiscordClient->RevokeToken(APPLICATION_ID, credential->getAuthenticator()["token"].asString(), [](discordpp::ClientResult result) {
if (result.Successful())
LL_INFOS("Discord") << "Access token successfully revoked." << LL_ENDL;
else
LL_WARNS("Discord") << "No access token to revoke." << LL_ENDL;
});
auto cred = new LLCredential("Discord");
gSecAPIHandler->deleteCredential(cred);
}
else
{
LL_WARNS("Discord") << "Credentials are already nonexistent." << LL_ENDL;
}
}
gDiscordClient->SetApplicationId(1394782217405862001);
updateDiscordActivity();
}
void LLAppViewer::updateDiscordActivity()
{
LL_PROFILE_ZONE_SCOPED;
static LLCachedControl<bool> integration_enabled(gSavedSettings, "EnableDiscord", true);
if (!integration_enabled)
{
gDiscordClient->ClearRichPresence();
return;
}
discordpp::Activity activity;
activity.SetType(discordpp::ActivityTypes::Playing);
discordpp::ActivityTimestamps timestamps;
@ -6035,37 +5956,39 @@ void LLAppViewer::updateDiscordActivity()
activity.SetDetails(gDiscordActivityDetails);
}
auto agent_pos_region = gAgent.getPositionAgent();
S32 pos_x = S32(agent_pos_region.mV[VX] + 0.5f);
S32 pos_y = S32(agent_pos_region.mV[VY] + 0.5f);
S32 pos_z = S32(agent_pos_region.mV[VZ] + 0.5f);
F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared();
const F32 FLY_CUTOFF = 6.f;
const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
const F32 WALK_CUTOFF = 1.5f;
const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;
if (velocity_mag_sq > FLY_CUTOFF_SQ)
{
pos_x -= pos_x % 4;
pos_y -= pos_y % 4;
}
else if (velocity_mag_sq > WALK_CUTOFF_SQ)
{
pos_x -= pos_x % 2;
pos_y -= pos_y % 2;
}
std::string location = "Hidden Region";
static LLCachedControl<bool> show_state(gSavedSettings, "ShowDiscordActivityState", false);
if (show_state)
{
auto agent_pos_region = gAgent.getPositionAgent();
S32 pos_x = S32(agent_pos_region.mV[VX] + 0.5f);
S32 pos_y = S32(agent_pos_region.mV[VY] + 0.5f);
S32 pos_z = S32(agent_pos_region.mV[VZ] + 0.5f);
F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared();
const F32 FLY_CUTOFF = 6.f;
const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF;
const F32 WALK_CUTOFF = 1.5f;
const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF;
if (velocity_mag_sq > FLY_CUTOFF_SQ)
{
pos_x -= pos_x % 4;
pos_y -= pos_y % 4;
}
else if (velocity_mag_sq > WALK_CUTOFF_SQ)
{
pos_x -= pos_x % 2;
pos_y -= pos_y % 2;
}
auto location = llformat("%s (%d, %d, %d)", gAgent.getRegion()->getName().c_str(), pos_x, pos_y, pos_z);
activity.SetState(location);
discordpp::ActivityParty party;
party.SetId(location);
party.SetCurrentSize(gDiscordPartyCurrentSize);
party.SetMaxSize(gDiscordPartyMaxSize);
activity.SetParty(party);
location = llformat("%s (%d, %d, %d)", gAgent.getRegion()->getName().c_str(), pos_x, pos_y, pos_z);
}
activity.SetState(location);
discordpp::ActivityParty party;
party.SetId(location);
party.SetCurrentSize(gDiscordPartyCurrentSize);
party.SetMaxSize(gDiscordPartyMaxSize);
activity.SetParty(party);
gDiscordClient->UpdateRichPresence(activity, [](discordpp::ClientResult) {});
}

View File

@ -253,7 +253,6 @@ public:
#ifdef LL_DISCORD
static void initDiscordSocial();
static void toggleDiscordIntegration(const LLSD& value);
static void updateDiscordActivity();
static void updateDiscordPartyCurrentSize(int32_t size);
static void updateDiscordPartyMaxSize(int32_t size);

View File

@ -367,7 +367,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.DeleteTranscripts", boost::bind(&LLFloaterPreference::onDeleteTranscripts, this));
mCommitCallbackRegistrar.add("UpdateFilter", boost::bind(&LLFloaterPreference::onUpdateFilterTerm, this, false)); // <FS:ND/> Hook up for filtering
#ifdef LL_DISCORD
gSavedSettings.getControl("EnableDiscord")->getCommitSignal()->connect(boost::bind(&LLAppViewer::toggleDiscordIntegration, _2));
gSavedSettings.getControl("EnableDiscord")->getCommitSignal()->connect(boost::bind(&LLAppViewer::updateDiscordActivity));
gSavedSettings.getControl("ShowDiscordActivityDetails")->getCommitSignal()->connect(boost::bind(&LLAppViewer::updateDiscordActivity));
gSavedSettings.getControl("ShowDiscordActivityState")->getCommitSignal()->connect(boost::bind(&LLAppViewer::updateDiscordActivity));
#endif