@serifpersia/dango 3.6.7 → 3.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/README.md +1 -1
  2. package/client/dist/assets/{AnimeCard-C3P9zWi9.js → AnimeCard-DKDJK8Mp.js} +1 -1
  3. package/client/dist/assets/{AnimeInfo-Et6687Tl.js → AnimeInfo-CTcvfjva.js} +1 -1
  4. package/client/dist/assets/{AnimeInfoPage-DX4eNnlH.js → AnimeInfoPage-B_UiacIN.js} +2 -2
  5. package/client/dist/assets/{Asmr-CCdEWrFi.js → Asmr-DMSN2vxl.js} +2 -2
  6. package/client/dist/assets/{AsmrResetProgressModal-DgEWBJOw.js → AsmrResetProgressModal-CRwfOatX.js} +1 -1
  7. package/client/dist/assets/{AvSyncCalibrator-CQ2fjf2E.js → AvSyncCalibrator-CRJsi-vz.js} +1 -1
  8. package/client/dist/assets/{Home-DUkUTTTy.js → Home-pwmK9_Eh.js} +1 -1
  9. package/client/dist/assets/{Insights-QCh4xW12.js → Insights-m7kFzg2A.js} +1 -1
  10. package/client/dist/assets/{LibraryListPage-BoTxRqHz.js → LibraryListPage-C1wpPvu6.js} +1 -1
  11. package/client/dist/assets/ListeningList-OzfEI1Ga.js +1 -0
  12. package/client/dist/assets/{Manga-HydR-L7o.js → Manga-ChRCExhK.js} +1 -1
  13. package/client/dist/assets/{MangaInfoPage-CBakEI9a.js → MangaInfoPage-DSHJPo2A.js} +1 -1
  14. package/client/dist/assets/{MangaReadPage-DwAR3iPy.js → MangaReadPage-CzOVY1wA.js} +1 -1
  15. package/client/dist/assets/{MangaResetProgressModal-DGzl8vsO.js → MangaResetProgressModal-CJfzdUBb.js} +1 -1
  16. package/client/dist/assets/{Mature-Pi0TxKuF.js → Mature-CifQMfhs.js} +1 -1
  17. package/client/dist/assets/{MediaCard--cuFxOCS.js → MediaCard-CM10yB9V.js} +1 -1
  18. package/client/dist/assets/{OptionListMenu-B3D39dGS.js → OptionListMenu-6Kovbsqw.js} +1 -1
  19. package/client/dist/assets/{Player-CsH4x_I_.js → Player-CK0hT-u4.js} +2 -2
  20. package/client/dist/assets/{PlayerSettings-DGxBsi3F.js → PlayerSettings-Bb66uqT9.js} +1 -1
  21. package/client/dist/assets/{QueueOptionsButton-Djq4Cpex.js → QueueOptionsButton-C_nTj8_q.js} +1 -1
  22. package/client/dist/assets/{QueueRail-DOrYgNVX.js → QueueRail-DUK7URAE.js} +1 -1
  23. package/client/dist/assets/{ReadingList-DwYoBrNk.js → ReadingList-Ck9LJThU.js} +1 -1
  24. package/client/dist/assets/{ResetProgressModal-CMF86mX6.js → ResetProgressModal-BUphIv0k.js} +1 -1
  25. package/client/dist/assets/{Search-DFkhuk-x.js → Search-zJyP15h6.js} +1 -1
  26. package/client/dist/assets/{Settings-DBB2r0VQ.js → Settings-BYdoSEUh.js} +1 -1
  27. package/client/dist/assets/{SkeletonGrid-DJelJgAv.js → SkeletonGrid-CqgbOhjX.js} +1 -1
  28. package/client/dist/assets/{Trackers-DGYXFhYZ.js → Trackers-BVjyv6CM.js} +1 -1
  29. package/client/dist/assets/{Tv-C5MDGD2Z.js → Tv-L13ylswR.js} +1 -1
  30. package/client/dist/assets/{TvInfo-DrKuK13u.js → TvInfo-Cvcm5U2D.js} +1 -1
  31. package/client/dist/assets/{TvPopup-DtHilRDT.js → TvPopup-DhxfKvYm.js} +1 -1
  32. package/client/dist/assets/{TvSearch-CzNxdu_w.js → TvSearch-P8bFE6_X.js} +1 -1
  33. package/client/dist/assets/{TvWatchlist-D7p4br6S.js → TvWatchlist-D5gVPjtb.js} +1 -1
  34. package/client/dist/assets/{Watchlist-DrOzswl2.js → Watchlist-Cjq8l3rU.js} +1 -1
  35. package/client/dist/assets/{hls-BGCX7mJy.js → hls-BkzuANAg.js} +1 -1
  36. package/client/dist/assets/{index-CnfZwsds.js → index-CLVgzKLk.js} +19 -19
  37. package/client/dist/assets/{useAnimeInfoData-DYXWBPF-.js → useAnimeInfoData-DZJZu-so.js} +1 -1
  38. package/client/dist/assets/{useAsmr-BbhQ59bk.js → useAsmr-CvrMGHuo.js} +1 -1
  39. package/client/dist/assets/useAsmrPopup-Bimy8Ouw.js +1 -0
  40. package/client/dist/assets/{useMangaLibrary-DuesWQaE.js → useMangaLibrary--MiN11uR.js} +1 -1
  41. package/client/dist/assets/{useMangaPopup-D57OVGUr.js → useMangaPopup-CR5XhKKS.js} +1 -1
  42. package/client/dist/assets/{useProviders-mpQb_dix.js → useProviders-DqdT4fA5.js} +1 -1
  43. package/client/dist/assets/{useTv-DGflCsSI.js → useTv-BL0HMDyP.js} +1 -1
  44. package/client/dist/assets/{useTvLibrary-BqeSmyc4.js → useTvLibrary-D4U4iqN8.js} +1 -1
  45. package/client/dist/index.html +1 -1
  46. package/package.json +3 -5
  47. package/server/dist/config.js +1 -174
  48. package/server/dist/server.js +1068 -289
  49. package/server/dist/shipped-defaults.js +1 -6
  50. package/server/package.json +4 -5
  51. package/client/dist/assets/Asmr.module-CdWlioTY.js +0 -1
  52. package/client/dist/assets/ListeningList-DguKjI_t.js +0 -1
  53. package/client/dist/assets/Music-BGH_0voi.css +0 -1
  54. package/client/dist/assets/Music-CQpyXTLH.js +0 -1
  55. package/client/dist/assets/Radio-CCHNFN7R.css +0 -1
  56. package/client/dist/assets/Radio-DF6g6odd.js +0 -1
  57. package/client/dist/assets/Radio.module-DGSZLpKM.js +0 -1
  58. package/client/dist/assets/useAsmrPopup-SymV1J-b.js +0 -1
  59. package/server/dist/app-auth.js +0 -157
  60. package/server/dist/app-hono.js +0 -598
  61. package/server/dist/db/drizzle.js +0 -16
  62. package/server/dist/db/schema-anime.js +0 -61
  63. package/server/dist/db/schema-asmr.js +0 -13
  64. package/server/dist/db/schema-manga.js +0 -31
  65. package/server/dist/db/schema-tv.js +0 -18
  66. package/server/dist/db.js +0 -217
  67. package/server/dist/discord-gateway.js +0 -385
  68. package/server/dist/discord-rpc.js +0 -413
  69. package/server/dist/github-sync.js +0 -508
  70. package/server/dist/google.js +0 -741
  71. package/server/dist/hono/asmr.js +0 -10
  72. package/server/dist/hono/auth.js +0 -49
  73. package/server/dist/hono/music.js +0 -209
  74. package/server/dist/hono/proxy.js +0 -827
  75. package/server/dist/hono/tv.js +0 -200
  76. package/server/dist/hono/watchlist.js +0 -341
  77. package/server/dist/lib/anilist.js +0 -1583
  78. package/server/dist/lib/anischedule.js +0 -191
  79. package/server/dist/lib/insights.js +0 -185
  80. package/server/dist/lib/ipc.js +0 -23
  81. package/server/dist/lib/kitsu.js +0 -517
  82. package/server/dist/lib/mal-import.js +0 -291
  83. package/server/dist/lib/mal.js +0 -957
  84. package/server/dist/lib/migration.js +0 -310
  85. package/server/dist/lib/offline-db.js +0 -395
  86. package/server/dist/lib/potoken.js +0 -135
  87. package/server/dist/lib/recommendations.service.js +0 -216
  88. package/server/dist/lib/temp-ids.js +0 -3
  89. package/server/dist/lib/tmdb.js +0 -72
  90. package/server/dist/lib/tracker/anilist-tracker.js +0 -308
  91. package/server/dist/lib/tracker/manga-sync.service.js +0 -773
  92. package/server/dist/lib/tracker/sync-state.js +0 -21
  93. package/server/dist/lib/tracker/sync.service.js +0 -476
  94. package/server/dist/lib/translate.js +0 -79
  95. package/server/dist/lib/ump.js +0 -106
  96. package/server/dist/lib/ytmusic.js +0 -162
  97. package/server/dist/logger.js +0 -16
  98. package/server/dist/providers/manga/manga.types.js +0 -1
  99. package/server/dist/providers/provider.interface.js +0 -1
  100. package/server/dist/providers/remote-loader.js +0 -614
  101. package/server/dist/providers/remote-types.js +0 -159
  102. package/server/dist/providers/title-matching.js +0 -226
  103. package/server/dist/providers/tv.types.js +0 -1
  104. package/server/dist/rclone.js +0 -120
  105. package/server/dist/repositories/asmr.repository.js +0 -77
  106. package/server/dist/repositories/insights.repository.js +0 -106
  107. package/server/dist/repositories/library.repository.js +0 -94
  108. package/server/dist/repositories/mal-cache.repository.js +0 -52
  109. package/server/dist/repositories/manga.repository.js +0 -95
  110. package/server/dist/repositories/notifications.repository.js +0 -60
  111. package/server/dist/repositories/queue.repository.js +0 -72
  112. package/server/dist/repositories/settings.repository.js +0 -30
  113. package/server/dist/repositories/shows-meta.repository.js +0 -58
  114. package/server/dist/repositories/temp-show-ids.repository.js +0 -63
  115. package/server/dist/repositories/tv.repository.js +0 -93
  116. package/server/dist/repositories/watched-episodes.repository.js +0 -82
  117. package/server/dist/repositories/watchlist.repository.js +0 -60
  118. package/server/dist/scripts/backfill-episode-duration.js +0 -42
  119. package/server/dist/sync-payload.js +0 -91
  120. package/server/dist/sync.js +0 -657
  121. package/server/dist/trpc/context.js +0 -7
  122. package/server/dist/trpc/errors.js +0 -15
  123. package/server/dist/trpc/index.js +0 -18
  124. package/server/dist/trpc/router.js +0 -49
  125. package/server/dist/trpc/routers/asmr-library.js +0 -112
  126. package/server/dist/trpc/routers/asmr-progress.js +0 -121
  127. package/server/dist/trpc/routers/asmr.js +0 -87
  128. package/server/dist/trpc/routers/auth.js +0 -194
  129. package/server/dist/trpc/routers/continue-watching.js +0 -81
  130. package/server/dist/trpc/routers/data.js +0 -1026
  131. package/server/dist/trpc/routers/discord.js +0 -285
  132. package/server/dist/trpc/routers/discovery.js +0 -11
  133. package/server/dist/trpc/routers/insights.js +0 -14
  134. package/server/dist/trpc/routers/manga-library.js +0 -263
  135. package/server/dist/trpc/routers/manga-progress.js +0 -169
  136. package/server/dist/trpc/routers/manga.js +0 -201
  137. package/server/dist/trpc/routers/music.js +0 -655
  138. package/server/dist/trpc/routers/notifications.js +0 -80
  139. package/server/dist/trpc/routers/progress.js +0 -109
  140. package/server/dist/trpc/routers/queue.js +0 -93
  141. package/server/dist/trpc/routers/radio.js +0 -145
  142. package/server/dist/trpc/routers/settings.js +0 -96
  143. package/server/dist/trpc/routers/tracker.js +0 -213
  144. package/server/dist/trpc/routers/tv-library.js +0 -135
  145. package/server/dist/trpc/routers/tv-progress.js +0 -159
  146. package/server/dist/trpc/routers/tv.js +0 -551
  147. package/server/dist/trpc/routers/watchlist.js +0 -550
  148. package/server/dist/trpc/validation.js +0 -258
  149. package/server/dist/utils/cache.utils.js +0 -25
  150. package/server/dist/utils/cookie.utils.js +0 -13
  151. package/server/dist/utils/db-utils.js +0 -17
  152. package/server/dist/utils/env.utils.js +0 -77
  153. package/server/dist/utils/http.utils.js +0 -82
  154. package/server/dist/utils/request-context.js +0 -2
  155. package/server/dist/utils/security.utils.js +0 -76
  156. /package/client/dist/assets/{Asmr-D1KuQwQy.css → useAsmrPopup-D1KuQwQy.css} +0 -0
@@ -1,413 +0,0 @@
1
- import { Client, StatusDisplayType } from '@xhayper/discord-rpc';
2
- import logger from './logger.js';
3
- import { CONFIG } from './config.js';
4
- import { discordGatewayService } from './discord-gateway.js';
5
- const log = logger.child({ module: 'DiscordRPC' });
6
- class DiscordRPCService {
7
- client = null;
8
- isEnabled = false;
9
- hideMature = true;
10
- reconnectTimeout = null;
11
- lastActivity = null;
12
- currentSessionId = null;
13
- hasPagePresence = false;
14
- hasEverConnected = false;
15
- permanentlyDisabled = false;
16
- heartbeats = new Map();
17
- heartbeatTimer = null;
18
- retryCount = 0;
19
- MAX_RETRIES = 5;
20
- INITIAL_RECONNECT_DELAY = 15000;
21
- MAX_RECONNECT_DELAY = 300000;
22
- HEARTBEAT_TIMEOUT = 40000;
23
- HEARTBEAT_CHECK_INTERVAL = 10000;
24
- async setEnabled(enabled) {
25
- if (this.isEnabled === enabled)
26
- return;
27
- this.isEnabled = enabled;
28
- if (enabled) {
29
- if (this.permanentlyDisabled) {
30
- log.debug('Discord Rich Presence is unavailable on this device/session. Not retrying.');
31
- this.isEnabled = false;
32
- return;
33
- }
34
- this.retryCount = 0;
35
- discordGatewayService.setEnabled(true);
36
- if (!discordGatewayService.serviceEnabled) {
37
- this.connect();
38
- }
39
- }
40
- else {
41
- await this.disconnect();
42
- discordGatewayService.setEnabled(false);
43
- }
44
- }
45
- get isServiceEnabled() {
46
- return this.isEnabled && (this.client !== null || discordGatewayService.serviceEnabled);
47
- }
48
- setHideMature(hide) {
49
- this.hideMature = hide;
50
- }
51
- heartbeat(sessionId) {
52
- this.heartbeats.set(sessionId, Date.now());
53
- if (!this.heartbeatTimer && this.isEnabled) {
54
- this.heartbeatTimer = setInterval(() => {
55
- void this.checkHeartbeats();
56
- }, this.HEARTBEAT_CHECK_INTERVAL);
57
- }
58
- }
59
- removeHeartbeat(sessionId) {
60
- this.heartbeats.delete(sessionId);
61
- void this.checkHeartbeats();
62
- }
63
- async checkHeartbeats() {
64
- if (!this.isEnabled) {
65
- if (this.heartbeatTimer) {
66
- clearInterval(this.heartbeatTimer);
67
- this.heartbeatTimer = null;
68
- }
69
- return;
70
- }
71
- const now = Date.now();
72
- for (const [sessionId, lastSeen] of this.heartbeats) {
73
- if (now - lastSeen > this.HEARTBEAT_TIMEOUT) {
74
- this.heartbeats.delete(sessionId);
75
- }
76
- }
77
- if (this.heartbeats.size === 0) {
78
- if (this.heartbeatTimer) {
79
- clearInterval(this.heartbeatTimer);
80
- this.heartbeatTimer = null;
81
- }
82
- if (this.hasPagePresence || this.lastActivity || this.currentSessionId) {
83
- this.lastActivity = null;
84
- this.currentSessionId = null;
85
- this.hasPagePresence = false;
86
- await this.setIdleStatus('idle');
87
- }
88
- }
89
- }
90
- async connect() {
91
- if (!this.isEnabled || this.client || this.permanentlyDisabled)
92
- return;
93
- if (discordGatewayService.serviceEnabled) {
94
- log.debug('Using Discord Gateway for presence (token configured). Skipping local RPC.');
95
- return;
96
- }
97
- const isTermux = !!process.env.TERMUX_VERSION;
98
- const isAndroid = process.platform === 'android';
99
- if (isTermux || isAndroid) {
100
- log.debug('Discord Rich Presence is not supported on Android/Termux. Skipping connection.');
101
- this.isEnabled = false;
102
- this.permanentlyDisabled = true;
103
- return;
104
- }
105
- const clientId = CONFIG.DISCORD_CLIENT_ID;
106
- if (!clientId) {
107
- log.debug('DISCORD_CLIENT_ID is not configured. Discord Rich Presence is disabled.');
108
- this.isEnabled = false;
109
- this.permanentlyDisabled = true;
110
- return;
111
- }
112
- try {
113
- this.client = new Client({ clientId });
114
- this.client.on('ready', () => {
115
- log.info('Connected to Discord client successfully');
116
- this.hasEverConnected = true;
117
- this.retryCount = 0;
118
- if (this.lastActivity) {
119
- this.updatePresence(this.lastActivity);
120
- }
121
- else {
122
- this.setIdleStatus('idle');
123
- }
124
- });
125
- this.client.on('disconnected', () => {
126
- log.warn('Disconnected from Discord client, scheduling reconnect...');
127
- this.cleanup();
128
- this.scheduleReconnect();
129
- });
130
- this.client.on('ERROR', (err) => {
131
- const errMsg = err instanceof Error ? err.message : String(err);
132
- if (errMsg.includes('ENOENT') || errMsg.includes('ECONNREFUSED')) {
133
- this.cleanup();
134
- if (!this.hasEverConnected) {
135
- log.debug('Discord client not detected. Rich Presence disabled for this session.');
136
- this.isEnabled = false;
137
- this.permanentlyDisabled = true;
138
- return;
139
- }
140
- log.debug('Discord client not running or connection refused.');
141
- this.scheduleReconnect();
142
- }
143
- else {
144
- log.error({ err }, 'Discord RPC client error');
145
- this.cleanup();
146
- this.scheduleReconnect();
147
- }
148
- });
149
- const loginPromise = this.client.login();
150
- const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('Login timeout')), 5000));
151
- await Promise.race([loginPromise, timeoutPromise]);
152
- this.hasEverConnected = true;
153
- }
154
- catch (err) {
155
- this.cleanup();
156
- if (!this.hasEverConnected) {
157
- log.debug('Discord client not available at startup. Rich Presence disabled for the rest of this session.');
158
- this.isEnabled = false;
159
- this.permanentlyDisabled = true;
160
- return;
161
- }
162
- this.scheduleReconnect();
163
- }
164
- }
165
- scheduleReconnect() {
166
- if (!this.isEnabled || this.reconnectTimeout || this.permanentlyDisabled)
167
- return;
168
- const delay = Math.min(this.INITIAL_RECONNECT_DELAY * Math.pow(1.5, this.retryCount), this.MAX_RECONNECT_DELAY);
169
- this.retryCount++;
170
- if (this.retryCount > this.MAX_RETRIES) {
171
- log.debug(`Discord RPC login failed ${this.retryCount} times. Retrying in ${Math.round(delay / 1000)}s...`);
172
- }
173
- else {
174
- log.info(`Discord RPC login failed. Retrying in ${Math.round(delay / 1000)}s...`);
175
- }
176
- this.reconnectTimeout = setTimeout(() => {
177
- this.reconnectTimeout = null;
178
- this.connect();
179
- }, delay);
180
- }
181
- cleanup() {
182
- if (this.client) {
183
- try {
184
- this.client.removeAllListeners();
185
- this.client.destroy();
186
- }
187
- catch (err) {
188
- // ignore
189
- }
190
- this.client = null;
191
- }
192
- }
193
- async disconnect() {
194
- if (this.reconnectTimeout) {
195
- clearTimeout(this.reconnectTimeout);
196
- this.reconnectTimeout = null;
197
- }
198
- if (this.client?.user) {
199
- try {
200
- await this.client.user.clearActivity();
201
- }
202
- catch {
203
- // ignore
204
- }
205
- }
206
- this.cleanup();
207
- this.lastActivity = null;
208
- this.currentSessionId = null;
209
- this.heartbeats.clear();
210
- if (this.heartbeatTimer) {
211
- clearInterval(this.heartbeatTimer);
212
- this.heartbeatTimer = null;
213
- }
214
- discordGatewayService.disconnect();
215
- }
216
- async updatePresence(data) {
217
- this.lastActivity = data;
218
- if (data.sessionId) {
219
- this.currentSessionId = data.sessionId;
220
- }
221
- if (!this.isEnabled)
222
- return;
223
- if (this.hideMature && data.isAdult) {
224
- if (discordGatewayService.serviceEnabled) {
225
- discordGatewayService.clearPresence();
226
- }
227
- else if (this.client?.user) {
228
- try {
229
- await this.client.user.clearActivity();
230
- }
231
- catch {
232
- // ignore
233
- }
234
- }
235
- return;
236
- }
237
- if (discordGatewayService.serviceEnabled) {
238
- discordGatewayService.updatePresence(data);
239
- return;
240
- }
241
- if (!this.client || !this.client.user)
242
- return;
243
- const isSafeUrl = (url) => {
244
- if (!url.startsWith('https://')) {
245
- return false;
246
- }
247
- if (url.includes('localhost') || url.includes('127.0.0.1')) {
248
- return false;
249
- }
250
- if (url.includes('s4.anilist.co') || url.includes('anilistcdn')) {
251
- return true;
252
- }
253
- const blockedDomains = [
254
- 'youtube-anime.com',
255
- 'animepahe',
256
- 'animeya.cc',
257
- 'gogocdn.net',
258
- 'weeabo0.xyz',
259
- 'japaneseasmr.com',
260
- ];
261
- return !blockedDomains.some((domain) => url.includes(domain));
262
- };
263
- let imageKey = 'logo';
264
- if (data.thumbnail && data.providerName !== 'AnimePahe') {
265
- let thumbUrl = data.thumbnail;
266
- if (thumbUrl.includes('/api/image-proxy')) {
267
- const match = thumbUrl.match(/url=([^&]+)/);
268
- if (match) {
269
- thumbUrl = decodeURIComponent(match[1]);
270
- }
271
- }
272
- if (isSafeUrl(thumbUrl)) {
273
- imageKey = thumbUrl;
274
- }
275
- else if (data.thumbnails) {
276
- const safeThumb = data.thumbnails.find((t) => t && (t.includes('s4.anilist.co') || t.includes('anilistcdn')));
277
- if (safeThumb)
278
- imageKey = safeThumb;
279
- }
280
- }
281
- try {
282
- if (!data.isPlaying) {
283
- await this.client.user.clearActivity();
284
- await this.client.user.setActivity({
285
- details: data.title,
286
- state: data.stateLine
287
- ? `${data.stateLine} (Paused)`
288
- : `Episode ${data.episode}${data.totalEpisodes ? `/${data.totalEpisodes}` : ''} (Paused)`,
289
- largeImageKey: imageKey,
290
- largeImageText: data.title,
291
- ...(imageKey !== 'logo' ? { smallImageKey: 'small', smallImageText: 'dango' } : {}),
292
- type: data.providerName === 'ASMR' ||
293
- data.providerName === 'Radio' ||
294
- data.providerName === 'Music'
295
- ? 2
296
- : 3,
297
- statusDisplayType: StatusDisplayType.DETAILS,
298
- buttons: [
299
- {
300
- label: 'Learn More',
301
- url: 'https://github.com/serifpersia/dango',
302
- },
303
- ],
304
- });
305
- this.hasPagePresence = false;
306
- return;
307
- }
308
- const nowSeconds = Math.round(Date.now() / 1000);
309
- const activity = {
310
- details: data.title,
311
- state: data.stateLine
312
- ? data.stateLine
313
- : `Episode ${data.episode}${data.totalEpisodes ? `/${data.totalEpisodes}` : ''}`,
314
- largeImageKey: imageKey,
315
- largeImageText: data.title,
316
- ...(imageKey !== 'logo' ? { smallImageKey: 'small', smallImageText: 'dango' } : {}),
317
- type: data.providerName === 'ASMR' ||
318
- data.providerName === 'Radio' ||
319
- data.providerName === 'Music'
320
- ? 2
321
- : 3,
322
- statusDisplayType: StatusDisplayType.DETAILS,
323
- buttons: [
324
- {
325
- label: 'Learn More',
326
- url: 'https://github.com/serifpersia/dango',
327
- },
328
- ],
329
- };
330
- if (data.currentTime && data.currentTime > 0) {
331
- activity.startTimestamp = Math.round(nowSeconds - data.currentTime);
332
- }
333
- if (data.duration && data.duration > data.currentTime) {
334
- activity.endTimestamp = Math.round(nowSeconds + (data.duration - data.currentTime));
335
- }
336
- await this.client.user.setActivity(activity);
337
- this.hasPagePresence = false;
338
- }
339
- catch (err) {
340
- log.error({ err }, 'Failed to set Discord activity');
341
- }
342
- }
343
- async setIdleStatus(page) {
344
- if (!this.isEnabled)
345
- return;
346
- if (discordGatewayService.serviceEnabled) {
347
- discordGatewayService.setIdleStatus(page);
348
- return;
349
- }
350
- if (!this.client || !this.client.user) {
351
- log.warn('Discord client not connected, skipping idle status update');
352
- return;
353
- }
354
- const pageLabels = {
355
- home: { details: 'Home', state: 'Browsing anime' },
356
- search: { details: 'Search', state: 'Exploring titles...' },
357
- watchlist: { details: 'Watchlist', state: 'Reviewing the watchlist' },
358
- anime: { details: 'Anime Info', state: 'Reading show details' },
359
- insights: { details: 'Insights', state: 'Reviewing stats' },
360
- settings: { details: 'Settings', state: 'Tweaking preferences' },
361
- mal: { details: 'MAL Sync', state: 'Syncing with MyAnimeList' },
362
- map: { details: 'Map', state: 'Exploring the global user map' },
363
- asmr: { details: 'ASMR', state: 'Browsing ASMR works' },
364
- radio: { details: 'Radio', state: 'Browsing radio stations' },
365
- music: { details: 'Music', state: 'Browsing music' },
366
- tv: { details: 'TV', state: 'Browsing movies & shows' },
367
- manga: { details: 'Manga', state: 'Browsing manga' },
368
- };
369
- const label = pageLabels[page] ?? { details: 'dango', state: 'Idle' };
370
- try {
371
- if (!this.client || !this.client.user) {
372
- log.warn('Discord client not connected, skipping idle status update');
373
- return;
374
- }
375
- await this.client.user.setActivity({
376
- details: label.details,
377
- state: label.state,
378
- largeImageKey: 'logo',
379
- largeImageText: 'dango',
380
- type: page === 'asmr' || page === 'radio' || page === 'music' ? 2 : 3,
381
- statusDisplayType: StatusDisplayType.DETAILS,
382
- buttons: [
383
- {
384
- label: 'Learn More',
385
- url: 'https://github.com/serifpersia/dango',
386
- },
387
- ],
388
- });
389
- this.hasPagePresence = page in pageLabels;
390
- }
391
- catch (err) {
392
- if (err.message === 'Closed by Discord') {
393
- log.warn('Discord connection ended, skipping idle status update');
394
- }
395
- else {
396
- log.error({ err }, 'Failed to set Discord idle status');
397
- }
398
- }
399
- }
400
- async clearPresence(sessionId) {
401
- if (sessionId && this.currentSessionId && sessionId !== this.currentSessionId) {
402
- return;
403
- }
404
- this.lastActivity = null;
405
- this.currentSessionId = null;
406
- if (discordGatewayService.serviceEnabled) {
407
- discordGatewayService.clearPresence();
408
- return;
409
- }
410
- await this.setIdleStatus('idle');
411
- }
412
- }
413
- export const discordRPCService = new DiscordRPCService();