1+ using DiscordRPC ;
2+ using DiscordRPC . Logging ;
3+ using YukkuriMovieMaker . Plugin ;
4+ using YmmRPC . Settings ;
5+
6+ namespace YmmRPC ;
7+
8+ [ PluginDetails ( AuthorName = "namakemono-san" , ContentId = "" ) ]
9+ public abstract class YmmRpcPlugin : IPlugin , IDisposable
10+ {
11+ public string Name => "YMM-RPC" ;
12+
13+ private const string ClientId = "1353376132732420136" ;
14+ private const string Version = "0.3.0" ;
15+ private const int UpdateIntervalMs = 15000 ;
16+
17+ private static DiscordRpcClient ? _client ;
18+ private static Timer ? _updateTimer ;
19+ private static DateTime _startTime ;
20+ private static volatile bool _updateRequested ;
21+ private bool _disposed ;
22+
23+ protected YmmRpcPlugin ( )
24+ {
25+ _startTime = DateTime . UtcNow ;
26+ InitializeClient ( ) ;
27+ StartUpdateTimer ( ) ;
28+ }
29+
30+ private static void InitializeClient ( )
31+ {
32+ if ( _client is { IsDisposed : false } ) return ;
33+
34+ _client = new DiscordRpcClient ( ClientId )
35+ {
36+ Logger = new ConsoleLogger { Level = LogLevel . Warning }
37+ } ;
38+
39+ _client . OnReady += ( _ , e ) => Console . WriteLine ( $ "[YMM-RPC] Connected: { e . User . Username } ") ;
40+ _client . OnError += ( _ , e ) => Console . WriteLine ( $ "[YMM-RPC] Error: { e . Message } ") ;
41+
42+ _client . Initialize ( ) ;
43+ UpdatePresence ( ) ;
44+ }
45+
46+ private static void StartUpdateTimer ( )
47+ {
48+ _updateTimer ? . Dispose ( ) ;
49+ _updateTimer = new Timer ( _ =>
50+ {
51+ if ( ! _updateRequested ) return ;
52+ _updateRequested = false ;
53+ UpdatePresence ( ) ;
54+ } , null , UpdateIntervalMs , UpdateIntervalMs ) ;
55+ }
56+
57+ public static void RequestUpdate ( ) => _updateRequested = true ;
58+
59+ private static void UpdatePresence ( )
60+ {
61+ if ( _client is not { IsInitialized : true } ) return ;
62+
63+ var settings = YmmRpcSettings . Default ;
64+
65+ if ( ! settings . IsEnabled )
66+ {
67+ _client . ClearPresence ( ) ;
68+ return ;
69+ }
70+
71+ var presence = settings . CustomRpcEnabled
72+ ? BuildCustomPresence ( settings )
73+ : BuildDefaultPresence ( ) ;
74+
75+ _client . SetPresence ( presence ) ;
76+ }
77+
78+ private static RichPresence BuildDefaultPresence ( )
79+ {
80+ return new RichPresence
81+ {
82+ Details = "動画を編集中..." ,
83+ State = "Working on YMM4" ,
84+ Assets = new Assets
85+ {
86+ LargeImageKey = "icon" ,
87+ LargeImageText = $ "YMM-RPC v{ Version } "
88+ } ,
89+ Timestamps = new Timestamps { Start = _startTime }
90+ } ;
91+ }
92+
93+ private static RichPresence BuildCustomPresence ( YmmRpcSettings settings )
94+ {
95+ var presence = new RichPresence
96+ {
97+ Details = NullIfEmpty ( settings . CustomRpcDetails ) ,
98+ State = NullIfEmpty ( settings . CustomRpcState ) ,
99+ Assets = new Assets
100+ {
101+ LargeImageKey = string . IsNullOrEmpty ( settings . CustomRpcLargeImageKey ) ? "icon" : settings . CustomRpcLargeImageKey ,
102+ LargeImageText = NullIfEmpty ( settings . CustomRpcLargeImageText ) ,
103+ SmallImageKey = NullIfEmpty ( settings . CustomRpcSmallImageKey ) ,
104+ SmallImageText = NullIfEmpty ( settings . CustomRpcSmallImageText )
105+ } ,
106+ Timestamps = new Timestamps { Start = _startTime }
107+ } ;
108+
109+ if ( ! settings . CustomRpcEnableButtons ) return presence ;
110+
111+ var buttons = new List < Button > ( 2 ) ;
112+
113+ if ( ! string . IsNullOrEmpty ( settings . CustomRpcButton1Label ) &&
114+ ! string . IsNullOrEmpty ( settings . CustomRpcButton1Url ) )
115+ {
116+ buttons . Add ( new Button { Label = settings . CustomRpcButton1Label , Url = settings . CustomRpcButton1Url } ) ;
117+ }
118+
119+ if ( ! string . IsNullOrEmpty ( settings . CustomRpcButton2Label ) &&
120+ ! string . IsNullOrEmpty ( settings . CustomRpcButton2Url ) )
121+ {
122+ buttons . Add ( new Button { Label = settings . CustomRpcButton2Label , Url = settings . CustomRpcButton2Url } ) ;
123+ }
124+
125+ if ( buttons . Count > 0 )
126+ presence . Buttons = buttons . ToArray ( ) ;
127+
128+ return presence ;
129+ }
130+
131+ private static string ? NullIfEmpty ( string ? s ) => string . IsNullOrEmpty ( s ) ? null : s ;
132+
133+ public void Dispose ( )
134+ {
135+ if ( _disposed ) return ;
136+ _disposed = true ;
137+
138+ _updateTimer ? . Dispose ( ) ;
139+ _updateTimer = null ;
140+
141+ if ( _client is { IsDisposed : false } )
142+ {
143+ _client . ClearPresence ( ) ;
144+ _client . Dispose ( ) ;
145+ }
146+ _client = null ;
147+
148+ GC . SuppressFinalize ( this ) ;
149+ }
150+ }
0 commit comments