@serifpersia/dango 3.3.9 → 3.4.1

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 (180) hide show
  1. package/README.md +1 -1
  2. package/client/dist/assets/{AnimeCard-URCiiy5W.js → AnimeCard-B0oMgXBm.js} +1 -1
  3. package/client/dist/assets/{AnimeInfo-e3z3er9t.js → AnimeInfo-o0Udf0og.js} +1 -1
  4. package/client/dist/assets/{AnimeInfoPage-B7Djlmy_.js → AnimeInfoPage-CojMIEuf.js} +2 -2
  5. package/client/dist/assets/Asmr-2V3yCCiK.js +2 -0
  6. package/client/dist/assets/AsmrResetProgressModal-C9R7HlNa.js +1 -0
  7. package/client/dist/assets/AvSyncCalibrator-Bo3820j3.js +10 -0
  8. package/client/dist/assets/Home-C8uXTzIM.js +1 -0
  9. package/client/dist/assets/Insights-CRqBfZuK.js +1 -0
  10. package/client/dist/assets/{LibraryListPage-B0qWqhb_.js → LibraryListPage-B_r51cRi.js} +1 -1
  11. package/client/dist/assets/{ListeningList-CSqD8j1C.js → ListeningList-BWnwvJTt.js} +1 -1
  12. package/client/dist/assets/{Manga-Cg2YuObF.js → Manga-CI5cZg3h.js} +1 -1
  13. package/client/dist/assets/{MangaInfoPage-DcArhEsy.js → MangaInfoPage-BtkOrO34.js} +1 -1
  14. package/client/dist/assets/MangaReadPage-Uv72AYdY.js +1 -0
  15. package/client/dist/assets/{MangaResetProgressModal-D_yT3d1v.js → MangaResetProgressModal-CPMEqZyi.js} +1 -1
  16. package/client/dist/assets/Mature-DXHWvoY5.js +1 -0
  17. package/client/dist/assets/MediaCard-DzA336CA.js +1 -0
  18. package/client/dist/assets/Music-C4dM0BQx.js +1 -0
  19. package/client/dist/assets/OptionListMenu-CpwxAC3J.js +1 -0
  20. package/client/dist/assets/Player-CpMvWTkH.js +56 -0
  21. package/client/dist/assets/PlayerSettings-pMU85k7p.js +1 -0
  22. package/client/dist/assets/QueueOptionsButton-1M7MdKzM.js +1 -0
  23. package/client/dist/assets/{QueueRail-B7f1-e6i.js → QueueRail-Bpla2xD8.js} +1 -1
  24. package/client/dist/assets/Radio-DlmTC-qG.js +1 -0
  25. package/client/dist/assets/{ReadingList-BaIem8H1.js → ReadingList-wJMDUybm.js} +1 -1
  26. package/client/dist/assets/{ResetProgressModal-DES5Y-Fl.js → ResetProgressModal-CByRM1Fh.js} +1 -1
  27. package/client/dist/assets/Search-B94D0tRM.js +1 -0
  28. package/client/dist/assets/Settings-CcU3oNY8.js +21 -0
  29. package/client/dist/assets/{SkeletonGrid-BxfgjP4i.js → SkeletonGrid-BJyZkg_K.js} +1 -1
  30. package/client/dist/assets/Trackers-vz-gqxtm.js +2 -0
  31. package/client/dist/assets/Tv-Rji_lvQo.js +4 -0
  32. package/client/dist/assets/Tv-ZEA45gXK.css +1 -0
  33. package/client/dist/assets/TvInfo-Ciujd6os.js +1 -0
  34. package/client/dist/assets/TvPopup-CqlVRF-Y.js +1 -0
  35. package/client/dist/assets/{TvSearch-BWDwWnHe.js → TvSearch-BcKXQue9.js} +1 -1
  36. package/client/dist/assets/{TvWatchlist-D3n5_4MI.js → TvWatchlist-sjsiup2h.js} +1 -1
  37. package/client/dist/assets/Watchlist-DAMdvt7Z.js +1 -0
  38. package/client/dist/assets/{hls-BO_L1WoN.js → hls-Do_n10_Y.js} +1 -1
  39. package/client/dist/assets/index-B5SLDCAi.js +178 -0
  40. package/client/dist/assets/useAnimeInfoData-DU9X90no.js +1 -0
  41. package/client/dist/assets/useAsmr-D6cSjbvt.js +1 -0
  42. package/client/dist/assets/{useAsmrPopup-D_o9-QlR.js → useAsmrPopup-DK1Vx-HV.js} +1 -1
  43. package/client/dist/assets/useMangaLibrary-DcxPn0RM.js +1 -0
  44. package/client/dist/assets/{useMangaPopup-TFzkC-tG.js → useMangaPopup-BLwvRZn0.js} +1 -1
  45. package/client/dist/assets/useProviders-D3L1Chqc.js +1 -0
  46. package/client/dist/assets/useTv-B546u-Rx.js +1 -0
  47. package/client/dist/assets/useTvLibrary-C2rPeCVT.js +1 -0
  48. package/client/dist/assets/{vendor-query-BXRECSI6.js → vendor-query-BUTye89G.js} +1 -1
  49. package/client/dist/index.html +2 -2
  50. package/orchestrator.js +1 -2
  51. package/package.json +6 -6
  52. package/server/dist/app-auth.js +9 -29
  53. package/server/dist/app-hono.js +621 -0
  54. package/server/dist/config.js +0 -1
  55. package/server/dist/db/drizzle.js +32 -0
  56. package/server/dist/db/schema-anime.js +64 -0
  57. package/server/dist/db/schema-asmr.js +25 -0
  58. package/server/dist/db/schema-manga.js +31 -0
  59. package/server/dist/db/schema-tv.js +33 -0
  60. package/server/dist/db.js +75 -4
  61. package/server/dist/discord-gateway.js +1 -1
  62. package/server/dist/google.js +0 -7
  63. package/server/dist/hono/asmr.js +1 -0
  64. package/server/dist/hono/auth.js +56 -0
  65. package/server/dist/hono/music.js +419 -0
  66. package/server/dist/{controllers/proxy.controller.js → hono/proxy.js} +390 -394
  67. package/server/dist/hono/tv.js +197 -0
  68. package/server/dist/hono/watchlist.js +733 -0
  69. package/server/dist/lib/anilist.js +3 -3
  70. package/server/dist/lib/insights.js +185 -0
  71. package/server/dist/lib/ipc.js +1 -2
  72. package/server/dist/lib/kitsu.js +1 -28
  73. package/server/dist/lib/mal-import.js +291 -0
  74. package/server/dist/lib/migration.js +20 -34
  75. package/server/dist/lib/offline-db.js +36 -36
  76. package/server/dist/lib/tracker/manga-sync.service.js +21 -21
  77. package/server/dist/lib/tracker/sync.service.js +20 -20
  78. package/server/dist/lib/translate.js +79 -0
  79. package/server/dist/lib/ytmusic.js +0 -2
  80. package/server/dist/providers/title-matching.js +0 -1
  81. package/server/dist/repositories/asmr.repository.js +90 -87
  82. package/server/dist/repositories/insights.repository.js +24 -13
  83. package/server/dist/repositories/library.repository.js +33 -93
  84. package/server/dist/repositories/manga.repository.js +108 -116
  85. package/server/dist/repositories/notifications.repository.js +50 -31
  86. package/server/dist/repositories/queue.repository.js +36 -25
  87. package/server/dist/repositories/settings.repository.js +18 -8
  88. package/server/dist/repositories/shows-meta.repository.js +54 -41
  89. package/server/dist/repositories/temp-show-ids.repository.js +43 -31
  90. package/server/dist/repositories/tv.repository.js +98 -115
  91. package/server/dist/repositories/watched-episodes.repository.js +52 -20
  92. package/server/dist/repositories/watchlist.repository.js +36 -48
  93. package/server/dist/server.js +59 -151
  94. package/server/dist/sync.js +41 -4
  95. package/server/dist/trpc/context.js +7 -0
  96. package/server/dist/trpc/errors.js +21 -0
  97. package/server/dist/trpc/index.js +19 -0
  98. package/server/dist/trpc/router.js +49 -0
  99. package/server/dist/trpc/routers/asmr-library.js +122 -0
  100. package/server/dist/trpc/routers/asmr-progress.js +133 -0
  101. package/server/dist/trpc/routers/asmr.js +87 -0
  102. package/server/dist/trpc/routers/auth.js +247 -0
  103. package/server/dist/trpc/routers/continue-watching.js +83 -0
  104. package/server/dist/trpc/routers/data.js +1039 -0
  105. package/server/dist/trpc/routers/discord.js +288 -0
  106. package/server/dist/trpc/routers/discovery.js +15 -0
  107. package/server/dist/trpc/routers/insights.js +45 -0
  108. package/server/dist/trpc/routers/manga-library.js +280 -0
  109. package/server/dist/trpc/routers/manga-progress.js +181 -0
  110. package/server/dist/trpc/routers/manga.js +201 -0
  111. package/server/dist/{controllers/music.controller.js → trpc/routers/music.js} +155 -288
  112. package/server/dist/trpc/routers/notifications.js +80 -0
  113. package/server/dist/trpc/routers/progress.js +15 -0
  114. package/server/dist/trpc/routers/queue.js +95 -0
  115. package/server/dist/{routes/radio.routes.js → trpc/routers/radio.js} +30 -23
  116. package/server/dist/trpc/routers/settings.js +105 -0
  117. package/server/dist/trpc/routers/tracker.js +219 -0
  118. package/server/dist/trpc/routers/tv-library.js +145 -0
  119. package/server/dist/trpc/routers/tv-progress.js +171 -0
  120. package/server/dist/trpc/routers/tv.js +565 -0
  121. package/server/dist/trpc/routers/watchlist.js +564 -0
  122. package/server/dist/trpc/validation.js +159 -0
  123. package/server/dist/utils/security.utils.js +0 -18
  124. package/server/package.json +5 -10
  125. package/client/dist/assets/Asmr-C28TfSvX.js +0 -2
  126. package/client/dist/assets/AsmrResetProgressModal-6Xh71AgR.js +0 -1
  127. package/client/dist/assets/AvSyncCalibrator-BwCtRW0P.js +0 -10
  128. package/client/dist/assets/Home-BJdbHYja.js +0 -1
  129. package/client/dist/assets/Insights-CjRy42YE.js +0 -1
  130. package/client/dist/assets/MangaReadPage-YCETZRte.js +0 -1
  131. package/client/dist/assets/Mature-BGxRWkV5.js +0 -1
  132. package/client/dist/assets/MediaCard-CAzoxsRS.js +0 -1
  133. package/client/dist/assets/Music-Cgo-yQ7E.js +0 -1
  134. package/client/dist/assets/OptionListMenu--Owe9Jle.js +0 -1
  135. package/client/dist/assets/Player-yRXG2BrP.js +0 -56
  136. package/client/dist/assets/PlayerSettings-DrZLa0CC.js +0 -1
  137. package/client/dist/assets/QueueOptionsButton-BVZyPyKf.js +0 -1
  138. package/client/dist/assets/Radio-BFjxlzuF.js +0 -1
  139. package/client/dist/assets/Search-BOBo0Ogh.js +0 -1
  140. package/client/dist/assets/Settings-DOvNQ0gX.js +0 -21
  141. package/client/dist/assets/Trackers-DZ9KqOWv.js +0 -2
  142. package/client/dist/assets/Tv-5mATEU4p.js +0 -4
  143. package/client/dist/assets/Tv-C2SWcVzN.css +0 -1
  144. package/client/dist/assets/TvInfo-CF-5C5Fs.js +0 -1
  145. package/client/dist/assets/TvPopup-Dfqifj3s.js +0 -1
  146. package/client/dist/assets/Watchlist-B8MHNsAU.js +0 -1
  147. package/client/dist/assets/index-D2RkUJIN.js +0 -178
  148. package/client/dist/assets/useAnimeInfoData-BWShDHqE.js +0 -1
  149. package/client/dist/assets/useAsmr-FyfD9G7b.js +0 -1
  150. package/client/dist/assets/useMangaLibrary-BJU5x8Vz.js +0 -1
  151. package/client/dist/assets/useProviders-DDRxa8vl.js +0 -1
  152. package/client/dist/assets/useTv-Bh6WmNnZ.js +0 -1
  153. package/client/dist/assets/useTvLibrary-_Pqm8re1.js +0 -1
  154. package/server/dist/controllers/asmr-library.controller.js +0 -288
  155. package/server/dist/controllers/auth.controller.js +0 -225
  156. package/server/dist/controllers/data.controller.js +0 -767
  157. package/server/dist/controllers/insights.controller.js +0 -203
  158. package/server/dist/controllers/manga-library.controller.js +0 -350
  159. package/server/dist/controllers/settings.controller.js +0 -609
  160. package/server/dist/controllers/tv-library.controller.js +0 -314
  161. package/server/dist/controllers/watchlist.controller.js +0 -1069
  162. package/server/dist/request-logger.js +0 -16
  163. package/server/dist/routes/asmr-library.routes.js +0 -23
  164. package/server/dist/routes/asmr.routes.js +0 -81
  165. package/server/dist/routes/auth.routes.js +0 -25
  166. package/server/dist/routes/data.routes.js +0 -47
  167. package/server/dist/routes/discord-gateway.routes.js +0 -51
  168. package/server/dist/routes/insights.routes.js +0 -35
  169. package/server/dist/routes/lan-auth.routes.js +0 -46
  170. package/server/dist/routes/manga-library.routes.js +0 -25
  171. package/server/dist/routes/manga.routes.js +0 -141
  172. package/server/dist/routes/music.routes.js +0 -20
  173. package/server/dist/routes/providers.routes.js +0 -17
  174. package/server/dist/routes/proxy.routes.js +0 -12
  175. package/server/dist/routes/settings.routes.js +0 -24
  176. package/server/dist/routes/tracker.routes.js +0 -287
  177. package/server/dist/routes/translate.routes.js +0 -88
  178. package/server/dist/routes/tv-library.routes.js +0 -23
  179. package/server/dist/routes/tv.routes.js +0 -629
  180. package/server/dist/routes/watchlist.routes.js +0 -341
@@ -0,0 +1,197 @@
1
+ import { parseJsonBody } from '../utils/http.utils.js';
2
+ import { getTmdbKey, TMDB_BASE, TMDB_IMAGE } from '../lib/tmdb.js';
3
+ import { URL } from 'url';
4
+ import { isSafeExternalUrl } from '../utils/security.utils.js';
5
+ async function resolveTvMeta(mediaType, numericTmdbId, partial) {
6
+ const meta = { ...partial };
7
+ if (meta.title && meta.imdbId && meta.year)
8
+ return meta;
9
+ try {
10
+ const tmdbKey = await getTmdbKey();
11
+ if (tmdbKey) {
12
+ const tmdbRes = await fetch(`${TMDB_BASE}/${mediaType}/${numericTmdbId}?api_key=${tmdbKey}&append_to_response=external_ids`, { headers: { 'User-Agent': 'Mozilla/5.0' }, signal: AbortSignal.timeout(4000) });
13
+ if (tmdbRes.ok) {
14
+ const d = await parseJsonBody(tmdbRes);
15
+ if (!meta.title)
16
+ meta.title = d.title || d.name || '';
17
+ if (!meta.year)
18
+ meta.year = (d.release_date || d.first_air_date || '').split('-')[0] || '';
19
+ if (!meta.imdbId)
20
+ meta.imdbId = d.external_ids?.imdb_id || d.imdb_id || '';
21
+ if (mediaType === 'tv' && d.number_of_seasons)
22
+ meta.totalSeasons = String(d.number_of_seasons);
23
+ }
24
+ }
25
+ }
26
+ catch {
27
+ // ignore
28
+ }
29
+ return meta;
30
+ }
31
+ function proxiedMediaUrl(targetUrl, refererStr) {
32
+ return `/api/tv/stream-proxy?url=${encodeURIComponent(targetUrl)}&referer=${encodeURIComponent(refererStr)}`;
33
+ }
34
+ export function rewriteTvPlaylist(body, baseUrl, refererStr) {
35
+ return body
36
+ .split('\n')
37
+ .map((line) => {
38
+ const trimmed = line.trim();
39
+ if (!trimmed)
40
+ return line;
41
+ if (trimmed.startsWith('#')) {
42
+ return trimmed.replace(/URI="([^"]+)"/g, (_, uri) => {
43
+ const absolute = new URL(uri, baseUrl).href;
44
+ return `URI="${proxiedMediaUrl(absolute, refererStr)}"`;
45
+ });
46
+ }
47
+ const absolute = new URL(trimmed, baseUrl).href;
48
+ return proxiedMediaUrl(absolute, refererStr);
49
+ })
50
+ .join('\n');
51
+ }
52
+ export function isPlaylistBody(body) {
53
+ return (body.length >= 7 &&
54
+ body
55
+ .subarray(0, 32)
56
+ .toString('utf8')
57
+ .replace(/^\uFEFF/, '')
58
+ .trimStart()
59
+ .startsWith('#EXTM3U'));
60
+ }
61
+ function toSearchResult(item, type) {
62
+ return {
63
+ id: item.id,
64
+ title: item.title || item.name || '',
65
+ year: (item.release_date || item.first_air_date || '').split('-')[0],
66
+ type,
67
+ image: item.poster_path ? `${TMDB_IMAGE}/w500${item.poster_path}` : '',
68
+ backdrop: item.backdrop_path ? `${TMDB_IMAGE}/w780${item.backdrop_path}` : '',
69
+ overview: item.overview || '',
70
+ vote_average: item.vote_average || 0,
71
+ adult: item.adult === true,
72
+ genre_ids: item.genre_ids || [],
73
+ };
74
+ }
75
+ export function registerTv(app, getApiCache, getTvProvider) {
76
+ app.get('/api/tv/embed/:provider/:type/:tmdbId', async (c) => {
77
+ const provider = c.req.param('provider');
78
+ const type = c.req.param('type');
79
+ const tmdbId = c.req.param('tmdbId');
80
+ const mediaType = type === 'movie' ? 'movie' : 'tv';
81
+ const numericTmdbId = parseInt(tmdbId, 10);
82
+ if (!numericTmdbId)
83
+ return c.json({ url: null, error: 'Bad tmdb id' });
84
+ const mod = getTvProvider(String(provider).toLowerCase());
85
+ if (!mod || typeof mod.getEmbedUrl !== 'function') {
86
+ return c.json({ url: null, error: `Unknown TV provider ${provider}` });
87
+ }
88
+ const media = {
89
+ tmdbId: numericTmdbId,
90
+ type: mediaType,
91
+ season: parseInt(String(c.req.query('season') || '1'), 10) || 1,
92
+ episode: parseInt(String(c.req.query('episode') || '1'), 10) || 1,
93
+ title: '',
94
+ year: '',
95
+ imdbId: '',
96
+ totalSeasons: 1,
97
+ };
98
+ try {
99
+ const url = await mod.getEmbedUrl(media);
100
+ if (!url)
101
+ return c.json({ url: null, error: 'No embed url' });
102
+ return c.json({ url });
103
+ }
104
+ catch (e) {
105
+ return c.json({ url: null, error: e.message });
106
+ }
107
+ });
108
+ app.get('/api/tv/stream-proxy', async (c) => {
109
+ const urlStr = c.req.query('url') ?? '';
110
+ const refererStr = c.req.query('referer') || '';
111
+ if (!urlStr)
112
+ return c.text('URL required', 400);
113
+ const safeCheck = isSafeExternalUrl(urlStr);
114
+ if (!safeCheck.safe) {
115
+ return c.text(safeCheck.error || 'Invalid URL', 400);
116
+ }
117
+ const abort = new AbortController();
118
+ const timeout = setTimeout(() => abort.abort(), 30000);
119
+ c.req.raw.signal.addEventListener('abort', () => {
120
+ clearTimeout(timeout);
121
+ abort.abort();
122
+ }, { once: true });
123
+ try {
124
+ const headers = {
125
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
126
+ };
127
+ if (refererStr)
128
+ headers['Referer'] = refererStr;
129
+ const fetchResp = await fetch(urlStr, {
130
+ headers,
131
+ signal: abort.signal,
132
+ redirect: 'follow',
133
+ });
134
+ const status = fetchResp.status;
135
+ if (status !== 200 && status !== 206) {
136
+ return c.text('Upstream error', (status || 502));
137
+ }
138
+ const contentType = fetchResp.headers.get('content-type') || 'application/octet-stream';
139
+ const contentLength = fetchResp.headers.get('content-length');
140
+ const contentRange = fetchResp.headers.get('content-range');
141
+ const acceptRanges = fetchResp.headers.get('accept-ranges');
142
+ const outHeaders = new Headers();
143
+ outHeaders.set('Content-Type', contentType);
144
+ if (contentLength)
145
+ outHeaders.set('Content-Length', contentLength);
146
+ if (contentRange)
147
+ outHeaders.set('Content-Range', contentRange);
148
+ if (acceptRanges)
149
+ outHeaders.set('Accept-Ranges', acceptRanges);
150
+ outHeaders.set('Access-Control-Allow-Origin', '*');
151
+ outHeaders.set('Connection', 'keep-alive');
152
+ if (urlStr.includes('.m3u8') || /mpegurl|m3u8/i.test(contentType)) {
153
+ const body = await fetchResp.text();
154
+ const baseUrl = new URL(fetchResp.url || urlStr);
155
+ const rewritten = rewriteTvPlaylist(body, baseUrl, refererStr);
156
+ const bodyBuffer = Buffer.from(rewritten, 'utf8');
157
+ outHeaders.set('Content-Type', 'application/vnd.apple.mpegurl');
158
+ outHeaders.set('Content-Length', String(bodyBuffer.length));
159
+ return new Response(bodyBuffer, { status, headers: outHeaders });
160
+ }
161
+ const chunks = [];
162
+ const reader = fetchResp.body?.getReader();
163
+ if (!reader) {
164
+ return c.text('No response body', 500);
165
+ }
166
+ try {
167
+ while (true) {
168
+ const { done, value } = await reader.read();
169
+ if (done)
170
+ break;
171
+ chunks.push(Buffer.from(value));
172
+ }
173
+ const body = Buffer.concat(chunks);
174
+ if (isPlaylistBody(body)) {
175
+ const baseUrl = new URL(fetchResp.url || urlStr);
176
+ const rewritten = rewriteTvPlaylist(body.toString('utf8'), baseUrl, refererStr);
177
+ const bodyBuffer = Buffer.from(rewritten, 'utf8');
178
+ outHeaders.set('Content-Type', 'application/vnd.apple.mpegurl');
179
+ outHeaders.set('Content-Length', String(bodyBuffer.length));
180
+ return new Response(bodyBuffer, { status, headers: outHeaders });
181
+ }
182
+ return new Response(body, { status, headers: outHeaders });
183
+ }
184
+ catch {
185
+ return c.text('Proxy error', 500);
186
+ }
187
+ }
188
+ catch {
189
+ if (abort.signal.aborted)
190
+ return new Response(null, { status: 499 });
191
+ return c.text('Proxy error', 500);
192
+ }
193
+ finally {
194
+ clearTimeout(timeout);
195
+ }
196
+ });
197
+ }