2
2
using DiscordRPC ;
3
3
using Microsoft . Extensions . Hosting ;
4
4
using Microsoft . Extensions . Logging ;
5
- using NexusMods . App . UI . Settings ;
6
5
using NexusMods . Abstractions . Settings ;
7
6
using NexusMods . Sdk ;
8
- using ReactiveUI ;
9
7
10
8
namespace NexusMods . Discord
11
9
{
12
10
public class DiscordRpcService : IHostedService
13
11
{
14
- private readonly DiscordRpcClient _client ;
12
+ private DiscordRpcClient _client ;
15
13
private readonly string _applicationId = "1393166557101691101" ;
16
14
private readonly ILogger < DiscordRpcService > _logger ;
17
15
private readonly ISettingsManager _settings ;
18
- private bool _isEnabled ;
19
- // Temporary for testing
20
- private CancellationTokenSource ? _periodicUpdateTokenSource ;
21
- private string _lastGameName = "" ;
16
+ private bool _isEnabled = true ;
17
+ private bool _isInitialized = false ;
22
18
23
19
private readonly IReadOnlyDictionary < string , string > _assetKeys = new ReadOnlyDictionary < string , string > (
24
20
new Dictionary < string , string >
@@ -37,16 +33,16 @@ public DiscordRpcService(ILogger<DiscordRpcService> logger, ISettingsManager set
37
33
38
34
public Task StartAsync ( CancellationToken cancellationToken )
39
35
{
40
- var settings = _settings . Get < DiscordSettings > ( ) ;
41
- _isEnabled = settings . EnableRichPresence ;
36
+ // var settings = _settings.Get<DiscordSettings>();
37
+ // _isEnabled = settings.EnableRichPresence;
42
38
43
39
if ( ! _isEnabled )
44
40
{
45
41
_logger . LogInformation ( "Discord RPC is disabled in settings and was not started." ) ;
46
- return Task . CompletedTask ;
42
+ return Task . CompletedTask ;
47
43
}
48
-
49
-
44
+
45
+
50
46
_client . OnReady += ( _ , e ) =>
51
47
{
52
48
_logger . LogDebug ( $ "Connected to Discord as { e . User . Username } ") ;
@@ -62,10 +58,15 @@ public Task StartAsync(CancellationToken cancellationToken)
62
58
_logger . LogError ( $ "Discord RPC Error: { e . Message } ") ;
63
59
} ;
64
60
61
+ if ( _client . IsDisposed ) {
62
+ _client = new DiscordRpcClient ( _applicationId ) ;
63
+ _logger . LogDebug ( "Recreated Discord RPC client due to previous disposal." ) ;
64
+ }
65
+
65
66
try
66
67
{
67
68
_client . Initialize ( ) ;
68
- SetDefaultPresence ( ) ;
69
+ _isInitialized = true ;
69
70
}
70
71
catch ( Exception ex )
71
72
{
@@ -74,57 +75,21 @@ public Task StartAsync(CancellationToken cancellationToken)
74
75
75
76
_logger . LogTrace ( "Discord RPC service started successfully." ) ;
76
77
77
- _periodicUpdateTokenSource = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
78
-
79
- _ = Task . Run ( async ( ) =>
80
- {
81
- try
82
- {
83
- while ( ! _periodicUpdateTokenSource . Token . IsCancellationRequested )
84
- {
85
- if ( _lastGameName != "" )
86
- {
87
- if ( _lastGameName == "Stardew Valley" )
88
- {
89
- _logger . LogInformation ( "Discord RPC set to Cyberpunk" ) ;
90
- SetGamePresence ( "Cyberpunk 2077" , "cyberpunk2077" , 9 ) ;
91
- _lastGameName = "Cyberpunk 2077" ;
92
- }
93
- else
94
- {
95
- _logger . LogInformation ( "Discord RPC set to Unknown" ) ;
96
- SetGamePresence ( "Unknown Game" , "unknown" , 0 ) ;
97
- _lastGameName = "" ;
98
- }
99
- }
100
- else
101
- {
102
- _logger . LogInformation ( "Discord RPC set to Stardew" ) ;
103
- SetGamePresence ( "Stardew Valley" , "stardewvalley" , 222 ) ;
104
- _lastGameName = "Stardew Valley" ;
105
- }
106
-
107
- await Task . Delay ( TimeSpan . FromSeconds ( 15 ) , _periodicUpdateTokenSource . Token ) ;
108
- }
109
- }
110
- catch ( OperationCanceledException )
111
- {
112
- _logger . LogInformation ( "Discord RPC periodic update task cancelled." ) ;
113
- }
114
- catch ( Exception ex )
115
- {
116
- _logger . LogError ( $ "Discord RPC periodic update task failed: { ex . Message } ") ;
117
- }
118
- } , _periodicUpdateTokenSource . Token
119
- ) ;
120
-
121
78
return Task . CompletedTask ;
122
79
}
123
80
124
81
public Task StopAsync ( CancellationToken cancellationToken )
125
82
{
126
- _client . Dispose ( ) ;
127
- _logger . LogInformation ( "Discord RPC service stopped." ) ;
83
+ if ( ! _isInitialized )
84
+ {
85
+ _logger . LogWarning ( "Discord RPC service was not initialized, skipping stop." ) ;
86
+ }
87
+ else
88
+ {
89
+ _client . ClearPresence ( ) ;
90
+ _client . Dispose ( ) ;
91
+ _logger . LogInformation ( "Discord RPC service stopped." ) ;
92
+ }
128
93
return Task . CompletedTask ;
129
94
}
130
95
@@ -154,14 +119,21 @@ public void SetDefaultPresence()
154
119
155
120
public void SetGamePresence ( string gameName , string gameDomain , int modCount )
156
121
{
157
- if ( ! _isEnabled ) return ;
122
+ if ( ! _isInitialized || ! _isEnabled )
123
+ {
124
+ _logger . LogWarning ( "Discord RPC is not initialized or enabled, cannot set game presence." ) ;
125
+ return ;
126
+ }
158
127
159
128
var largeImageKey = "nexusmods_logo" ;
160
129
161
130
if ( _assetKeys . TryGetValue ( gameDomain , out var gameArtKey ) )
162
131
{
163
132
largeImageKey = gameArtKey ;
164
133
}
134
+
135
+ _logger . LogInformation ( $ "Setting Discord presence for game: { gameName } , Domain: { gameDomain } , Mods: { modCount } ") ;
136
+
165
137
_client . SetPresence ( new RichPresence
166
138
{
167
139
Details = $ "Modding { gameName } ",
@@ -175,16 +147,17 @@ public void SetGamePresence(string gameName, string gameDomain, int modCount)
175
147
} ,
176
148
} ) ;
177
149
}
178
-
179
- public void ClearPresence ( )
180
- {
181
- _client . ClearPresence ( ) ;
182
- _logger . LogInformation ( "Discord presence cleared." ) ;
183
- }
184
150
}
185
151
}
186
152
187
153
public interface IDiscordRpcService
188
154
{
189
155
void SetGamePresence ( string gameName , string gameDomain , int modCount ) ;
156
+
157
+ void SetCustomPresence ( RichPresence presence ) ;
158
+
159
+ void SetDefaultPresence ( ) ;
160
+
161
+ Task StartAsync ( CancellationToken cancellationToken ) ;
162
+ Task StopAsync ( CancellationToken cancellationToken ) ;
190
163
}
0 commit comments