mirror of
https://github.com/osukey/osukey.git
synced 2025-08-06 16:13:57 +09:00
Refactor / rewrite discord code
This commit is contained in:
120
osu.Desktop/DiscordRichPresence.cs
Normal file
120
osu.Desktop/DiscordRichPresence.cs
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using DiscordRPC;
|
||||||
|
using DiscordRPC.Message;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Logging;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Users;
|
||||||
|
using LogLevel = osu.Framework.Logging.LogLevel;
|
||||||
|
using User = osu.Game.Users.User;
|
||||||
|
|
||||||
|
namespace osu.Desktop
|
||||||
|
{
|
||||||
|
internal class DiscordRichPresence : Component
|
||||||
|
{
|
||||||
|
private const string client_id = "367827983903490050";
|
||||||
|
|
||||||
|
private DiscordRpcClient client;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private IBindable<RulesetInfo> ruleset { get; set; }
|
||||||
|
|
||||||
|
private Bindable<User> user;
|
||||||
|
|
||||||
|
private readonly IBindable<UserStatus> status = new Bindable<UserStatus>();
|
||||||
|
private readonly IBindable<UserActivity> activity = new Bindable<UserActivity>();
|
||||||
|
|
||||||
|
private readonly RichPresence presence = new RichPresence
|
||||||
|
{
|
||||||
|
Assets = new Assets { LargeImageKey = "osu_logo_lazer", }
|
||||||
|
};
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(IAPIProvider provider)
|
||||||
|
{
|
||||||
|
client = new DiscordRpcClient(client_id)
|
||||||
|
{
|
||||||
|
SkipIdenticalPresence = false // handles better on discord IPC loss, see updateStatus call in onReady.
|
||||||
|
};
|
||||||
|
|
||||||
|
client.OnReady += onReady;
|
||||||
|
client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client: {e.Code} {e.Message}", LoggingTarget.Network, LogLevel.Error);
|
||||||
|
client.OnConnectionFailed += (_, e) => Logger.Log($"An connection occurred with Discord RPC Client: {e.Type}", LoggingTarget.Network, LogLevel.Error);
|
||||||
|
|
||||||
|
(user = provider.LocalUser.GetBoundCopy()).BindValueChanged(u =>
|
||||||
|
{
|
||||||
|
status.UnbindBindings();
|
||||||
|
status.BindTo(u.NewValue.Status);
|
||||||
|
|
||||||
|
activity.UnbindBindings();
|
||||||
|
activity.BindTo(u.NewValue.Activity);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
ruleset.BindValueChanged(_ => updateStatus());
|
||||||
|
status.BindValueChanged(_ => updateStatus());
|
||||||
|
activity.BindValueChanged(_ => updateStatus());
|
||||||
|
|
||||||
|
client.Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onReady(object _, ReadyMessage __)
|
||||||
|
{
|
||||||
|
Logger.Log("Discord RPC Client ready.", LoggingTarget.Network, LogLevel.Debug);
|
||||||
|
updateStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateStatus()
|
||||||
|
{
|
||||||
|
if (status.Value is UserStatusOffline)
|
||||||
|
{
|
||||||
|
client.ClearPresence();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.Value is UserStatusOnline && activity.Value != null)
|
||||||
|
{
|
||||||
|
presence.State = activity.Value.Status;
|
||||||
|
presence.Details = getDetails(activity.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
presence.State = "Idle";
|
||||||
|
presence.Details = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update user information
|
||||||
|
presence.Assets.LargeImageText = $"{user.Value.Username}" + (user.Value.Statistics?.Ranks.Global > 0 ? $" (rank #{user.Value.Statistics.Ranks.Global:N0})" : string.Empty);
|
||||||
|
|
||||||
|
// update ruleset
|
||||||
|
presence.Assets.SmallImageKey = ruleset.Value.ID <= 3 ? $"mode_{ruleset.Value.ID}" : "mode_unknown";
|
||||||
|
presence.Assets.SmallImageText = ruleset.Value.Name;
|
||||||
|
|
||||||
|
client.SetPresence(presence);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string getDetails(UserActivity activity)
|
||||||
|
{
|
||||||
|
switch (activity)
|
||||||
|
{
|
||||||
|
case UserActivity.SoloGame solo:
|
||||||
|
return solo.Beatmap.ToString();
|
||||||
|
|
||||||
|
case UserActivity.Editing edit:
|
||||||
|
return edit.Beatmap.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool isDisposing)
|
||||||
|
{
|
||||||
|
client.Dispose();
|
||||||
|
base.Dispose(isDisposing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,104 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
using DiscordRPC;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Framework.Logging;
|
|
||||||
using osu.Game.Online.API;
|
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osu.Game.Users;
|
|
||||||
using static osu.Game.Users.UserActivity;
|
|
||||||
using User = osu.Game.Users.User;
|
|
||||||
|
|
||||||
namespace osu.Desktop
|
|
||||||
{
|
|
||||||
internal class DiscordRichPresenceClient : Component
|
|
||||||
{
|
|
||||||
private const string client_id = "367827983903490050";
|
|
||||||
|
|
||||||
private Bindable<User> user;
|
|
||||||
|
|
||||||
private readonly DiscordRpcClient client = new DiscordRpcClient(client_id);
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(IAPIProvider provider)
|
|
||||||
{
|
|
||||||
user = provider.LocalUser.GetBoundCopy();
|
|
||||||
|
|
||||||
user.ValueChanged += usr =>
|
|
||||||
{
|
|
||||||
usr.NewValue.Activity.ValueChanged += activity => updateStatus(user.Value.Status.Value, activity.NewValue);
|
|
||||||
usr.NewValue.Status.ValueChanged += status => updateStatus(status.NewValue, user.Value.Activity.Value);
|
|
||||||
};
|
|
||||||
|
|
||||||
user.TriggerChange();
|
|
||||||
|
|
||||||
enableLogging();
|
|
||||||
|
|
||||||
client.Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enableLogging()
|
|
||||||
{
|
|
||||||
client.OnReady += (_, __) => Logger.Log("Discord RPC Client ready.", LoggingTarget.Network, LogLevel.Debug);
|
|
||||||
client.OnError += (_, e) => Logger.Log($"An error occurred with Discord RPC Client : {e.Message}", LoggingTarget.Network, LogLevel.Debug);
|
|
||||||
client.OnConnectionFailed += (_, e) => Logger.Log("Discord RPC Client failed to initialize : is discord running ?", LoggingTarget.Network, LogLevel.Debug);
|
|
||||||
client.OnPresenceUpdate += (_, __) => Logger.Log("Updated Discord Rich Presence", LoggingTarget.Network, LogLevel.Debug);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateStatus(UserStatus st, UserActivity a)
|
|
||||||
{
|
|
||||||
var presence = defaultPresence(st is UserStatusOnline ? a?.Status ?? st.Message : st.Message); //display the current user activity if the user status is online & user activity != null, else display the current user online status
|
|
||||||
|
|
||||||
if (!(st is UserStatusOnline)) //don't update the presence any further if the current user status is DND / Offline & simply return with the default presence
|
|
||||||
{
|
|
||||||
client.SetPresence(presence);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (a)
|
|
||||||
{
|
|
||||||
case SoloGame game:
|
|
||||||
presence.State = $"{game.Beatmap.Metadata.Artist} - {game.Beatmap.Metadata.Title} [{game.Beatmap.Version}]";
|
|
||||||
setPresenceGamemode(game.Ruleset, presence);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Editing editing:
|
|
||||||
presence.State = $"{editing.Beatmap.Metadata.Artist} - {editing.Beatmap.Metadata.Title} " + (!string.IsNullOrEmpty(editing.Beatmap.Version) ? $"[{editing.Beatmap.Version}]" : "");
|
|
||||||
presence.Assets.SmallImageKey = "edit";
|
|
||||||
presence.Assets.SmallImageText = "editing";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
client.SetPresence(presence);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setPresenceGamemode(RulesetInfo ruleset, RichPresence presence)
|
|
||||||
{
|
|
||||||
if (ruleset.ID != null && ruleset.ID <= 3) //legacy rulesets use an ID between 0 and 3
|
|
||||||
presence.Assets.SmallImageKey = ruleset.ShortName;
|
|
||||||
else
|
|
||||||
presence.Assets.SmallImageKey = "unknown"; //not a legacy ruleset so let's display the unknown ruleset icon.
|
|
||||||
|
|
||||||
presence.Assets.SmallImageText = ruleset.ShortName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RichPresence defaultPresence(string status) => new RichPresence
|
|
||||||
{
|
|
||||||
Details = status,
|
|
||||||
Assets = new Assets
|
|
||||||
{
|
|
||||||
LargeImageKey = "lazer",
|
|
||||||
LargeImageText = user.Value.Username
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
|
||||||
{
|
|
||||||
client.Dispose();
|
|
||||||
base.Dispose(isDisposing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user