@any-listen/extension-kit 0.1.0

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.
@@ -0,0 +1,1127 @@
1
+ type WithUndefined<T extends readonly unknown[]> = {
2
+ [K in keyof T]: T[K] | undefined
3
+ }
4
+ declare namespace AnyListen {
5
+ interface IPCActionBase<A> {
6
+ action: A
7
+ }
8
+ interface IPCActionData<A, D> extends IPCActionBase<A> {
9
+ data: D
10
+ }
11
+ type IPCAction<A, D = undefined> = D extends undefined ? IPCActionBase<A> : IPCActionData<A, D>
12
+ type AddMusicLocationType = 'top' | 'bottom'
13
+
14
+ namespace Player {
15
+ interface MusicInfo {
16
+ id: string | null
17
+ pic: string | null | undefined
18
+ lrc: string | null
19
+ tlrc: string | null
20
+ rlrc: string | null
21
+ awlrc: string | null
22
+ rawlrc: string | null
23
+ // url: string | null
24
+ name: string
25
+ singer: string
26
+ album: string
27
+ collect: boolean
28
+ }
29
+
30
+ interface PlayMusicInfo {
31
+ /**
32
+ * 当前信息唯一ID
33
+ */
34
+ itemId: string
35
+ /**
36
+ * 当前播放歌曲的列表 id
37
+ */
38
+ musicInfo: Music.MusicInfo
39
+ /**
40
+ * 当前播放歌曲的列表 id
41
+ */
42
+ listId: string
43
+ /**
44
+ * 是否在线列表
45
+ */
46
+ isOnline: boolean
47
+ /**
48
+ * 是否属于 “稍后播放”
49
+ */
50
+ playLater: boolean
51
+ /**
52
+ * 是否已播放
53
+ */
54
+ played: boolean
55
+ }
56
+
57
+ interface PlayInfo {
58
+ duration: number
59
+ index: number
60
+ listId: string | null
61
+ isOnline: boolean
62
+ historyIndex: number
63
+ }
64
+
65
+ interface TempPlayListItem {
66
+ /**
67
+ * 播放列表id
68
+ */
69
+ listId: string
70
+ /**
71
+ * 歌曲信息
72
+ */
73
+ musicInfo: Music.MusicInfo
74
+ /**
75
+ * 是否添加到列表顶部
76
+ */
77
+ isTop?: boolean
78
+ }
79
+
80
+ interface SavedPlayInfo {
81
+ time: number
82
+ maxTime: number
83
+ index: number
84
+ historyIndex: number
85
+ }
86
+ }
87
+
88
+ namespace Music {
89
+ type Source = string
90
+ type Quality = '128k' | '320k' | 'flac' | 'flac24bit' | '192k' | 'wav' | 'dobly' | 'master'
91
+ type FileType = 'mp3' | 'flac' | 'wav' | 'm4a'
92
+
93
+ type MusicQualityType = Partial<
94
+ Record<
95
+ string,
96
+ {
97
+ sizeStr: string | null
98
+ [key: string]: string | null
99
+ }
100
+ >
101
+ >
102
+
103
+ interface MusicInfoMetaBase {
104
+ musicId: string // 歌曲ID
105
+ albumName: string // 歌曲专辑名称
106
+ year?: number // 歌曲年份
107
+ picUrl?: string | null // 歌曲图片链接
108
+ createTime: number
109
+ updateTime: number
110
+ posTime: number
111
+ }
112
+
113
+ interface MusicInfoMeta_online extends MusicInfoMetaBase {
114
+ source: Source // 源
115
+ qualitys?: MusicQualityType
116
+ filePath?: string
117
+ ext?: string
118
+ bitrateLabel?: string | null
119
+ sizeStr?: string
120
+ [key: string]: string | number | boolean | null | undefined | object
121
+ }
122
+
123
+ interface MusicInfoMeta_local extends MusicInfoMetaBase {
124
+ filePath: string
125
+ ext: string
126
+ bitrateLabel: string | null
127
+ sizeStr: string
128
+ }
129
+
130
+ interface MusicInfoBase<IsLocal extends boolean> {
131
+ id: string
132
+ name: string // 歌曲名
133
+ singer: string // 艺术家名
134
+ interval: string | null // 格式化后的歌曲时长,例:03:55
135
+ isLocal: IsLocal
136
+ meta: MusicInfoMetaBase
137
+ }
138
+
139
+ interface MusicInfoLocal extends MusicInfoBase<true> {
140
+ meta: MusicInfoMeta_local
141
+ }
142
+
143
+ interface MusicInfoOnline extends MusicInfoBase<false> {
144
+ meta: MusicInfoMeta_online
145
+ }
146
+
147
+ type MusicInfo = MusicInfoLocal | MusicInfoOnline
148
+
149
+ interface LyricInfo {
150
+ // 歌曲歌词
151
+ lyric: string
152
+ // 翻译歌词
153
+ tlyric?: string | null
154
+ // 罗马音歌词
155
+ rlyric?: string | null
156
+ // 逐字歌词
157
+ awlyric?: string | null
158
+ name: string
159
+ singer: string
160
+ interval: string | null
161
+
162
+ rawlrcInfo?: {
163
+ // 歌曲歌词
164
+ lyric: string
165
+ // 翻译歌词
166
+ tlyric?: string | null
167
+ // 罗马音歌词
168
+ rlyric?: string | null
169
+ // 逐字歌词
170
+ awlyric?: string | null
171
+ }
172
+ }
173
+ }
174
+ namespace List {
175
+ interface UserListInfoBaseMeta {
176
+ songCount: number
177
+ pic: string
178
+ playCount: number
179
+ createTime: number
180
+ updateTime: number
181
+ posTime: number
182
+ desc: string
183
+ }
184
+ type ParentId = string | null
185
+ interface UserListInfoByGeneralMeta extends UserListInfoBaseMeta {}
186
+ interface UserListInfoByLocalMeta extends UserListInfoBaseMeta {
187
+ deviceId: string
188
+ path: string
189
+ includeSubDir: boolean
190
+ enabledRemove?: boolean
191
+ usePolling?: boolean
192
+ }
193
+ interface UserListInfoByOnlineMeta extends UserListInfoBaseMeta {
194
+ extensionId: string
195
+ source: string
196
+ syncId: string
197
+ syncTime: number
198
+ picUrl: string | null
199
+ }
200
+ interface UserListInfoByRemoteMeta extends UserListInfoBaseMeta {
201
+ extensionId: string
202
+ source: string
203
+ syncTime: number
204
+ [key: string]: unknown
205
+ }
206
+
207
+ interface UserListInfoMetas {
208
+ general: UserListInfoByGeneralMeta
209
+ local: UserListInfoByLocalMeta
210
+ online: UserListInfoByOnlineMeta
211
+ remote: UserListInfoByRemoteMeta
212
+ }
213
+ interface UserListInfoType<Type extends keyof UserListInfoMetas> {
214
+ id: string
215
+ parentId: ParentId
216
+ name: string
217
+ type: Type
218
+ meta: UserListInfoMetas[Type]
219
+ }
220
+
221
+ type UserListType = keyof UserListInfoMetas
222
+
223
+ type GeneralListInfo = UserListInfoType<'general'>
224
+ type LocalListInfo = UserListInfoType<'local'>
225
+ type OnlineListInfo = UserListInfoType<'online'>
226
+ type RemoteListInfo = UserListInfoType<'remote'>
227
+ type UserListInfo = GeneralListInfo | LocalListInfo | OnlineListInfo | RemoteListInfo
228
+
229
+ interface MyDefaultListInfo extends Omit<GeneralListInfo, 'type'> {
230
+ id: 'default'
231
+ name: string
232
+ type: 'default'
233
+ }
234
+
235
+ interface MyLoveListInfo extends Omit<GeneralListInfo, 'type'> {
236
+ id: 'love'
237
+ name: string
238
+ type: 'default'
239
+ }
240
+
241
+ interface MyLastPlayListInfo extends Omit<GeneralListInfo, 'type'> {
242
+ id: 'last_played'
243
+ name: string
244
+ type: 'default'
245
+ }
246
+
247
+ type MyListInfo = MyDefaultListInfo | MyLoveListInfo | MyLastPlayListInfo | UserListInfo
248
+
249
+ interface MyAllList {
250
+ defaultList: MyDefaultListInfo
251
+ loveList: MyLoveListInfo
252
+ lastPlayList: MyLastPlayListInfo
253
+ userList: UserListInfo[]
254
+ }
255
+
256
+ type SearchHistoryList = string[]
257
+ type ListPositionInfo = Record<string, number>
258
+ type ListUpdateInfo = Record<
259
+ string,
260
+ {
261
+ updateTime: number
262
+ isAutoUpdate: boolean
263
+ }
264
+ >
265
+
266
+ // type ListSaveType = 'myList' | 'downloadList'
267
+ // type ListSaveInfo = {
268
+ // type: 'myList'
269
+ // data: Partial<MyAllList>
270
+ // } | {
271
+ // type: 'downloadList'
272
+ // data: AnyListen.Download.ListItem[]
273
+ // }
274
+
275
+ // interface ListActionAdd {
276
+ // position: number
277
+ // listInfos: UserListInfo[]
278
+ // }
279
+ // type ListActionRemove = string[]
280
+ // type ListActionUpdate = UserListInfo[]
281
+ // interface ListActionUpdatePosition {
282
+ // /**
283
+ // * 列表id
284
+ // */
285
+ // ids: string[]
286
+ // /**
287
+ // * 位置
288
+ // */
289
+ // position: number
290
+ // }
291
+
292
+ // interface ListActionMusicAdd {
293
+ // id: string
294
+ // musicInfos: AnyListen.Music.MusicInfo[]
295
+ // addMusicLocationType: AnyListen.AddMusicLocationType
296
+ // }
297
+
298
+ // interface ListActionMusicMove {
299
+ // fromId: string
300
+ // toId: string
301
+ // musicInfos: AnyListen.Music.MusicInfo[]
302
+ // addMusicLocationType: AnyListen.AddMusicLocationType
303
+ // }
304
+
305
+ // interface ListActionCheckMusicExistList {
306
+ // listId: string
307
+ // musicInfoId: string
308
+ // }
309
+
310
+ // interface ListActionMusicRemove {
311
+ // listId: string
312
+ // ids: string[]
313
+ // }
314
+
315
+ // type ListActionMusicUpdate = Array<{
316
+ // id: string
317
+ // musicInfo: AnyListen.Music.MusicInfo
318
+ // }>
319
+
320
+ // interface ListActionMusicUpdatePosition {
321
+ // listId: string
322
+ // position: number
323
+ // ids: string[]
324
+ // }
325
+
326
+ // interface ListActionMusicOverwrite {
327
+ // listId: string
328
+ // musicInfos: AnyListen.Music.MusicInfo[]
329
+ // }
330
+
331
+ // type ListActionMusicClear = string[]
332
+
333
+ interface MyDefaultListInfoFull extends MyDefaultListInfo {
334
+ list: Music.MusicInfo[]
335
+ }
336
+ interface MyLoveListInfoFull extends MyLoveListInfo {
337
+ list: Music.MusicInfo[]
338
+ }
339
+ interface MyLastPlayListFull extends MyLastPlayListInfo {
340
+ list: Music.MusicInfo[]
341
+ }
342
+ interface UserListInfoGeneralFull extends UserListInfoType<'general'> {
343
+ list: Music.MusicInfo[]
344
+ }
345
+ interface UserListInfoLocalFull extends UserListInfoType<'local'> {
346
+ list: Music.MusicInfo[]
347
+ }
348
+ interface UserListInfoOnlineFull extends UserListInfoType<'online'> {
349
+ list: Music.MusicInfo[]
350
+ }
351
+
352
+ interface ListDataFull {
353
+ defaultList: MyDefaultListInfoFull
354
+ loveList: MyLoveListInfoFull
355
+ lastPlayList: MyLastPlayListFull
356
+ userList: Array<UserListInfoGeneralFull | UserListInfoLocalFull | UserListInfoOnlineFull>
357
+ }
358
+ }
359
+ namespace IPCList {
360
+ type ListActionDataOverwrite = List.ListDataFull
361
+ interface ListActionAdd {
362
+ position: number
363
+ listInfos: List.UserListInfo[]
364
+ }
365
+ type ListActionRemove = string[]
366
+ interface ListActionUpdate {
367
+ lists: List.MyListInfo[]
368
+ sync?: boolean
369
+ }
370
+ interface ListActionMove {
371
+ /**
372
+ * 目标列表id
373
+ */
374
+ id: List.ParentId
375
+ /**
376
+ * 列表id
377
+ */
378
+ ids: string[]
379
+ /**
380
+ * 位置
381
+ */
382
+ position: number
383
+ }
384
+ interface ListActionUpdatePosition {
385
+ /**
386
+ * 列表id
387
+ */
388
+ ids: string[]
389
+ /**
390
+ * 位置
391
+ */
392
+ position: number
393
+ }
394
+ interface ListActionUpdatePlayCount {
395
+ id: string
396
+ count?: number
397
+ }
398
+ // interface ListActionUpdatePlayTime {
399
+ // id: string
400
+ // name: string
401
+ // singer: string
402
+ // time: number
403
+ // }
404
+
405
+ interface ListActionMusicAdd {
406
+ id: string
407
+ musicInfos: Music.MusicInfo[]
408
+ addMusicLocationType: AddMusicLocationType
409
+ }
410
+
411
+ interface ListActionMusicMove {
412
+ fromId: string
413
+ toId: string
414
+ musicInfos: Music.MusicInfo[]
415
+ addMusicLocationType: AddMusicLocationType
416
+ }
417
+
418
+ interface ListActionCheckMusicExistList {
419
+ listId: string
420
+ musicInfoId: string
421
+ }
422
+
423
+ interface ListActionMusicRemove {
424
+ listId: string
425
+ ids: string[]
426
+ sync?: boolean
427
+ }
428
+
429
+ type ListActionMusicUpdate = Array<{
430
+ id: string
431
+ musicInfo: Music.MusicInfo
432
+ }>
433
+
434
+ interface ListActionMusicUpdatePosition {
435
+ listId: string
436
+ position: number
437
+ ids: string[]
438
+ }
439
+
440
+ interface ListActionMusicOverwrite {
441
+ listId: string
442
+ musicInfos: Music.MusicInfo[]
443
+ }
444
+
445
+ type ListActionMusicClear = string[]
446
+ interface ListInfo {
447
+ lastSyncDate?: number
448
+ snapshotKey: string
449
+ }
450
+
451
+ type ActionList =
452
+ | IPCAction<'list_data_overwrite', ListActionDataOverwrite>
453
+ | IPCAction<'list_create', ListActionAdd>
454
+ | IPCAction<'list_remove', ListActionRemove>
455
+ | IPCAction<'list_update', ListActionUpdate>
456
+ | IPCAction<'list_move', ListActionMove>
457
+ | IPCAction<'list_update_position', ListActionUpdatePosition>
458
+ // | IPCAction<'list_update_play_count', ListActionUpdatePlayCount>
459
+ // | IPCAction<'list_update_play_time', ListActionUpdatePlayTime>
460
+ | IPCAction<'list_music_add', ListActionMusicAdd>
461
+ | IPCAction<'list_music_move', ListActionMusicMove>
462
+ | IPCAction<'list_music_remove', ListActionMusicRemove>
463
+ | IPCAction<'list_music_update', ListActionMusicUpdate>
464
+ | IPCAction<'list_music_update_position', ListActionMusicUpdatePosition>
465
+ | IPCAction<'list_music_overwrite', ListActionMusicOverwrite>
466
+ | IPCAction<'list_music_clear', ListActionMusicClear>
467
+
468
+ type ListData = List.ListDataFull
469
+ type SyncMode =
470
+ | 'merge_local_remote'
471
+ | 'merge_remote_local'
472
+ | 'overwrite_local_remote'
473
+ | 'overwrite_remote_local'
474
+ | 'overwrite_local_remote_full'
475
+ | 'overwrite_remote_local_full'
476
+ // | 'none'
477
+ | 'cancel'
478
+ }
479
+ namespace IPCPlayer {
480
+ type ActionPlayer =
481
+ | IPCAction<'prev'>
482
+ | IPCAction<'next'>
483
+ | IPCAction<'pause'>
484
+ | IPCAction<'stop'>
485
+ | IPCAction<'play'>
486
+ | IPCAction<'toggle'>
487
+ | IPCAction<'skip', string>
488
+ | IPCAction<'seek', number>
489
+ | IPCAction<'collectStatus', boolean>
490
+
491
+ interface PlayerActionSet {
492
+ listId: string | null
493
+ list: Player.PlayMusicInfo[]
494
+ isOnline: boolean
495
+ isSync?: boolean
496
+ }
497
+ interface PlayerActionAdd {
498
+ musics: Player.PlayMusicInfo[]
499
+ pos: number
500
+ }
501
+ type PlayerActionUpdate = Player.PlayMusicInfo[]
502
+ type PlayerActionRemove = string[]
503
+ type PlayerActionPlayed = string[]
504
+ type PlayerActionUnplayed = string[]
505
+ interface PlayerActionPosUpdate {
506
+ musics: string[]
507
+ pos: number
508
+ }
509
+ type PlayListAction =
510
+ | IPCAction<'set', PlayerActionSet>
511
+ | IPCAction<'add', PlayerActionAdd>
512
+ | IPCAction<'remove', PlayerActionRemove>
513
+ | IPCAction<'update', PlayerActionUpdate>
514
+ | IPCAction<'played', PlayerActionPlayed>
515
+ | IPCAction<'unplayed', PlayerActionUnplayed>
516
+ | IPCAction<'unplayedAll'>
517
+ | IPCAction<'posUpdate', PlayerActionPosUpdate>
518
+
519
+ interface PlayHistoryListItem {
520
+ id: string
521
+ time: number
522
+ }
523
+ type PlayHistoryListActionSet = PlayHistoryListItem[]
524
+ type PlayHistoryListActionAdd = PlayHistoryListItem[]
525
+ type PlayHistoryListActionRemove = number[]
526
+ type PlayHistoryListAction =
527
+ | IPCAction<'setList', PlayHistoryListActionSet>
528
+ | IPCAction<'addList', PlayHistoryListActionAdd>
529
+ | IPCAction<'removeIdx', number[]>
530
+
531
+ interface Progress {
532
+ nowPlayTime: number
533
+ maxPlayTime: number
534
+ progress: number
535
+ nowPlayTimeStr: string
536
+ maxPlayTimeStr: string
537
+ }
538
+
539
+ type PlayerStatus = 'playing' | 'paused' | 'stopped' | 'loading' | 'buffering' | 'ended' | 'error'
540
+
541
+ /** 播放器实时状态 / 用户期望的播放状态 */
542
+ type Status = [PlayerStatus, boolean]
543
+ type PlayerEvent =
544
+ | IPCAction<'musicChanged', { index: number; historyIndex: number; lastTrackId?: string | null }>
545
+ | IPCAction<'musicInfoUpdated', Partial<Player.MusicInfo>>
546
+ | IPCAction<'playInfoUpdated', Partial<Player.PlayInfo>>
547
+ | IPCAction<'progress', Progress>
548
+ | IPCAction<'playbackRate', number>
549
+ | IPCAction<'status', Status>
550
+ | IPCAction<'statusText', string>
551
+ | IPCAction<'lyricText', string>
552
+ | IPCAction<'picUpdated', string | null>
553
+ | IPCAction<'lyricUpdated', Music.LyricInfo>
554
+ | IPCAction<'lyricOffsetUpdated', number>
555
+
556
+ interface SavedPlayInfo {
557
+ time: number
558
+ maxTime: number
559
+ index: number
560
+ historyIndex: number
561
+ }
562
+ interface PlayInfo {
563
+ info: SavedPlayInfo
564
+ list: Player.PlayMusicInfo[]
565
+ listId: string | null
566
+ isOnline: boolean
567
+ historyList: PlayHistoryListItem[]
568
+ isCollect: boolean
569
+ }
570
+ }
571
+ }
572
+
573
+ interface IPCActionBase<A> {
574
+ action: A
575
+ }
576
+ interface IPCActionData<A, D> extends IPCActionBase<A> {
577
+ data: D
578
+ }
579
+ interface CommonParams {
580
+ extensionId: string
581
+ source: string
582
+ }
583
+ interface CommonListParams extends CommonParams {
584
+ page: number
585
+ limit: number
586
+ }
587
+ interface LyricSearchParams extends CommonParams {
588
+ name: string
589
+ artist?: string
590
+ interval?: number
591
+ }
592
+ interface LyricSearchResult {
593
+ id: string
594
+ name: string
595
+ artist?: string
596
+ interval?: number
597
+ lyric?: string
598
+ }
599
+ interface LyricDetailParams extends CommonParams {
600
+ id: string
601
+ }
602
+ interface PicSearchParams extends CommonParams {
603
+ name: string
604
+ artist?: string
605
+ }
606
+ interface SearchParams extends CommonListParams {
607
+ name: string
608
+ artist?: string
609
+ }
610
+ interface ListDetailParams extends CommonListParams {
611
+ id: string
612
+ }
613
+ interface SonglistListParams extends CommonListParams {
614
+ sort: string
615
+ tag: string
616
+ }
617
+ export interface ListCommonResult<T> {
618
+ list: T[]
619
+ total: number
620
+ page: number
621
+ limit: number
622
+ // source: string
623
+ }
624
+ interface MusicCommonParams extends CommonParams {
625
+ musicInfo: AnyListen.Music.MusicInfoOnline
626
+ }
627
+ interface MusicUrlParams extends MusicCommonParams {
628
+ quality?: string
629
+ type?: AnyListen.Music.FileType
630
+ }
631
+ interface MusicUrlInfo {
632
+ url: string
633
+ quality: string
634
+ }
635
+
636
+ interface SongListItem {
637
+ play_count: string
638
+ id: string
639
+ author: string
640
+ name: string
641
+ time?: string
642
+ img: string
643
+ // grade: basic.favorcnt / 10,
644
+ desc: string | null
645
+ total?: string
646
+ }
647
+
648
+ interface CommonItem {
649
+ id: string
650
+ name: string
651
+ }
652
+ type TagItem = CommonItem
653
+ interface TagGroupItem {
654
+ name: string
655
+ list: CommonItem[]
656
+ }
657
+
658
+ type BoardItem = CommonItem
659
+
660
+ declare global {
661
+ namespace AnyListen_API {
662
+ type Locale =
663
+ | 'ar-sa'
664
+ | 'cs-cz'
665
+ | 'da-dk'
666
+ | 'de-de'
667
+ | 'el-gr'
668
+ | 'en-au'
669
+ | 'en-gb'
670
+ | 'en-ie'
671
+ | 'en-us'
672
+ | 'en-za'
673
+ | 'es-es'
674
+ | 'es-mx'
675
+ | 'fi-fi'
676
+ | 'fr-ca'
677
+ | 'fr-fr'
678
+ | 'he-il'
679
+ | 'hi-in'
680
+ | 'hu-hu'
681
+ | 'id-id'
682
+ | 'it-it'
683
+ | 'ja-jp'
684
+ | 'ko-kr'
685
+ | 'nl-be'
686
+ | 'nl-nl'
687
+ | 'no-no'
688
+ | 'pl-pl'
689
+ | 'pt-br'
690
+ | 'pt-pt'
691
+ | 'ro-ro'
692
+ | 'ru-ru'
693
+ | 'sk-sk'
694
+ | 'sv-se'
695
+ | 'th-th'
696
+ | 'tr-tr'
697
+ | 'zh-cn'
698
+ | 'zh-hk'
699
+ | 'zh-tw'
700
+
701
+ type Platform = 'mac' | 'linux' | 'windows' | 'android' | 'ios'
702
+ type Architecture = 'arm' | 'arm64' | 'x86' | 'x64'
703
+ type ClientType = 'desktop' | 'web' | 'mobile'
704
+ type Quality = '128k' | '320k' | 'flac' | 'flac24bit' | '192k' | 'wav' | 'dobly' | 'master'
705
+ type MusicInfo = AnyListen.Music.MusicInfo
706
+ type MusicInfoOnline = AnyListen.Music.MusicInfoOnline
707
+
708
+ type ParamsData = Record<string, string | number | null | undefined | boolean>
709
+ interface RequestOptions {
710
+ method?: 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'OPTIONS' | 'PATCH'
711
+ query?: Record<string, string | number | null | undefined | boolean>
712
+ headers?: Record<string, string | string[]>
713
+ timeout?: number
714
+ maxRedirect?: number
715
+ // signal?: AbortController['signal']
716
+ signal?: unknown
717
+ json?: Record<string, unknown>
718
+ form?: Record<string, string | number | null | undefined | boolean>
719
+ binary?: Uint8Array
720
+ text?: string
721
+ formdata?: Record<string, string | Uint8Array>
722
+ xml?: string
723
+ needRaw?: boolean
724
+ }
725
+ interface Response<Resp> {
726
+ statusCode?: number
727
+ // statusMessage?: string
728
+ headers: Record<string, string | string[] | undefined>
729
+ raw: Uint8Array
730
+ body: Resp
731
+ }
732
+
733
+ type ConverterFormatFrom = 'base64' | 'hex' | 'utf-8'
734
+ type ConverterFormatTo = 'binary' | 'base64' | 'hex' | 'utf-8'
735
+ type ConverterBinaryFormatTo = 'base64' | 'hex' | 'utf-8'
736
+ interface BufferToStringTypes {
737
+ binary: number[] | Uint8Array
738
+ base64: string
739
+ hex: string
740
+ utf8: string
741
+ 'utf-8': string
742
+ }
743
+
744
+ type AES_MODE = 'CBC_128_PKCS7Padding' | 'ECB_128_NoPadding'
745
+ type RSA_PADDING = 'RSA_PKCS1_OAEP_PADDING' | 'RSA_NO_PADDING'
746
+
747
+ interface MessageButton {
748
+ /** A short title like 'Retry', 'Open Log' etc. */
749
+ text: string
750
+ link?: string
751
+ }
752
+ interface MessageDialogOptions {
753
+ signal?: unknown
754
+ textSelect?: boolean
755
+ type?: 'info' | 'warning' | 'error'
756
+ /** Human-readable detail message that is rendered less prominent. Note that detail is only shown for modal messages. */
757
+ detail?: string
758
+ /** Indicates that this message should be modal. */
759
+ modal?: boolean
760
+ buttons?: MessageButton[]
761
+ }
762
+
763
+ interface FormItemBase<V> {
764
+ /** An optional string that represents the title of the form. */
765
+ title?: string
766
+ /** The text to display underneath the form. */
767
+ description?: string
768
+ /** The value to pre-fill in the form. */
769
+ value?: V
770
+ }
771
+ interface InputOptions extends FormItemBase<string> {
772
+ type: 'input'
773
+ /** Controls if a password input is shown. Password input hides the typed text. */
774
+ password?: boolean
775
+ /** An optional string to show as placeholder in the input box to guide the user what to type. */
776
+ placeholder?: string
777
+ }
778
+ interface BoolOptions extends FormItemBase<boolean> {
779
+ type: 'boolean'
780
+ }
781
+ interface EnumItem<T> {
782
+ name: string
783
+ value: T
784
+ }
785
+ interface RadioOptions<T extends string | number = string> extends FormItemBase<T> {
786
+ type: 'radio'
787
+ enum?: Array<EnumItem<T>>
788
+ }
789
+ interface SelectionOptions<T extends string | number = string> extends FormItemBase<T> {
790
+ type: 'selection'
791
+ enum: Array<EnumItem<T>>
792
+ }
793
+ // interface FormDialogOptions {
794
+ // signal?: unknown
795
+ // /** An optional string that represents the title of the form dialog. */
796
+ // title?: string
797
+ // /** An optional string that represents the description of the form dialog. */
798
+ // description?: string
799
+ // /** The form items */
800
+ // items: Array<InputOptions | BoolOptions | RadioOptions | SelectionOptions>
801
+ // /** An optional function that will be called to validate input and to give a hint to the user. */
802
+ // validateInput?: (index: number, value: string) => null | undefined | string
803
+ // }
804
+ interface InputDialogOptions {
805
+ signal?: unknown
806
+ /** Controls if a password input is shown. Password input hides the typed text. */
807
+ password?: boolean
808
+ /** An optional string to show as placeholder in the input box to guide the user what to type. */
809
+ placeholder?: string
810
+ /** The text to display underneath the input box. */
811
+ prompt?: string
812
+ /** An optional string that represents the title of the input box. */
813
+ title?: string
814
+ /** The value to pre-fill in the input box. */
815
+ value?: string
816
+ /** An optional function that will be called to validate input and to give a hint to the user. */
817
+ validateInput?: (value: string) => Promise<null | undefined | string>
818
+ }
819
+
820
+ interface OpenDialogOptions {
821
+ /** The resource the dialog shows when opened. */
822
+ // defaultPath?: string
823
+ /** A human-readable string for the open button. */
824
+ openLabel?: string
825
+ /** Allow to select files, defaults to `true`. */
826
+ canSelectFiles?: boolean
827
+ /** Allow to select folders, defaults to `false`. */
828
+ canSelectFolders?: boolean
829
+ /** Allow to select many files or folders. */
830
+ canSelectMany?: boolean
831
+ /**
832
+ * A set of file filters that are used by the dialog. Each entry is a human-readable label,
833
+ * like "TypeScript", and an array of extensions, for example:
834
+ * ```ts
835
+ * {
836
+ * 'Images': ['png', 'jpg'],
837
+ * 'TypeScript': ['ts', 'tsx']
838
+ * }
839
+ * ```
840
+ */
841
+ filters?: Record<string, string[]>
842
+ /**
843
+ * Dialog title.
844
+ *
845
+ * This parameter might be ignored, as not all operating systems display a title on open dialogs
846
+ * (for example, macOS).
847
+ */
848
+ title: string
849
+ }
850
+
851
+ interface SaveDialogOptions {
852
+ /** The resource the dialog shows when opened. */
853
+ // defaultPath?: string
854
+ /** A human-readable string for the save button. */
855
+ saveLabel?: string
856
+ /**
857
+ * A set of file filters that are used by the dialog. Each entry is a human-readable label,
858
+ * like "TypeScript", and an array of extensions, for example:
859
+ * ```ts
860
+ * {
861
+ * 'Images': ['png', 'jpg'],
862
+ * 'TypeScript': ['ts', 'tsx']
863
+ * }
864
+ * ```
865
+ */
866
+ filters?: Record<string, string[]>
867
+ /**
868
+ * Dialog title.
869
+ *
870
+ * This parameter might be ignored, as not all operating systems display a title on save dialogs
871
+ * (for example, macOS).
872
+ */
873
+ title: string
874
+ }
875
+
876
+ /** 环境相关 */
877
+ interface Env {
878
+ /** 客户端类型 */
879
+ readonly clientType: ClientType
880
+ /** 扩展系统版本号 */
881
+ readonly version: string
882
+ /** 运行平台 */
883
+ readonly platform: Platform
884
+ /** 架构 */
885
+ readonly arch: Architecture
886
+ /** 语言 */
887
+ readonly locale: Locale
888
+ /** 扩展公钥 */
889
+ readonly publicKey: string
890
+ /** 扩展版本号 */
891
+ readonly extensionVersion: string
892
+
893
+ readonly onLocaleChanged: (callback: (locale: Locale) => void) => () => void
894
+ }
895
+ /** 应用相关 */
896
+ interface App {
897
+ showMessage: (message: string, options?: MessageDialogOptions) => Promise<number>
898
+ // TODO
899
+ // showFormDialog: (options: FormDialogOptions) => Promise<string | undefined>
900
+ showInputDialog: (options: InputDialogOptions) => Promise<string>
901
+ // showInput: (options: InputDialogOptions) => Promise<string | undefined>
902
+ showOpenDialog: (options: OpenDialogOptions) => Promise<string[]>
903
+ showSaveDialog: (options: SaveDialogOptions) => Promise<string>
904
+ readOpenDialogFile: <T extends 'utf-8' | 'binary' = 'binary'>(
905
+ path: string,
906
+ format?: T
907
+ ) => Promise<T extends 'utf-8' ? string : Uint8Array>
908
+ writeSaveDialogFile: (dir: string, name: string, content: string | Uint8Array) => Promise<string>
909
+ // getConnectedClient: () => Promise<string[]>
910
+ }
911
+ interface MusicList {
912
+ getAllUserLists: () => Promise<AnyListen.List.MyAllList>
913
+ getListMusics: (listId: string) => Promise<AnyListen.Music.MusicInfo[]>
914
+ listAction: (action: AnyListen.IPCList.ActionList) => Promise<void>
915
+ onListAction: (handler: (action: AnyListen.IPCList.ActionList) => unknown) => () => void
916
+ }
917
+ interface PlayInfo {
918
+ info: {
919
+ time: number
920
+ maxTime: number
921
+ index: number
922
+ historyIndex: number
923
+ }
924
+ list: Array<{
925
+ /**
926
+ * 当前信息唯一ID
927
+ */
928
+ itemId: string
929
+ /**
930
+ * 当前播放歌曲的列表 id
931
+ */
932
+ musicInfo: AnyListen.Music.MusicInfo
933
+ /**
934
+ * 当前播放歌曲的列表 id
935
+ */
936
+ listId: string
937
+ /**
938
+ * 是否在线列表
939
+ */
940
+ isOnline: boolean
941
+ /**
942
+ * 是否属于 “稍后播放”
943
+ */
944
+ playLater: boolean
945
+ /**
946
+ * 是否已播放
947
+ */
948
+ played: boolean
949
+ }>
950
+ listId: string | null
951
+ historyList: Array<{
952
+ id: string
953
+ time: number
954
+ }>
955
+ }
956
+ interface Player {
957
+ /** 获取播放信息 */
958
+ getPlayInfo: () => Promise<PlayInfo>
959
+ playListAction: (action: AnyListen.IPCPlayer.PlayListAction) => Promise<void>
960
+ playerAction: (action: AnyListen.IPCPlayer.ActionPlayer) => Promise<void>
961
+ playHistoryListAction: (action: AnyListen.IPCPlayer.PlayHistoryListAction) => Promise<void>
962
+ onPlayerEvent: (callback: (event: AnyListen.IPCPlayer.PlayerEvent) => unknown) => () => void
963
+ onPlayListEvent: (callback: (action: AnyListen.IPCPlayer.PlayListAction) => unknown) => () => void
964
+ onPlayHistoryEvent: (callback: (action: AnyListen.IPCPlayer.PlayHistoryListAction) => unknown) => () => void
965
+ }
966
+ interface MusicUrlInfo {
967
+ url: string
968
+ quality: string
969
+ }
970
+
971
+ type BuildListProviderActionCommonParams<D> = CommonParams & {
972
+ data: D
973
+ }
974
+ type ListProviderActionParams = BuildListProviderActionCommonParams<AnyListen.List.RemoteListInfo>
975
+ interface ListProviderAction {
976
+ createList: (params: ListProviderActionParams) => Promise<void>
977
+ updateList: (params: ListProviderActionParams) => Promise<void>
978
+ deleteList: (params: ListProviderActionParams) => Promise<void>
979
+ getListMusicIds: (params: ListProviderActionParams) => Promise<string[]>
980
+ getMusicInfoByIds: (
981
+ params: BuildListProviderActionCommonParams<{
982
+ list: AnyListen.List.RemoteListInfo
983
+ ids: string[]
984
+ }>
985
+ ) => Promise<{
986
+ musics: AnyListen.Music.MusicInfoOnline[]
987
+ waitingParseMetadata?: boolean
988
+ }>
989
+ parseMusicInfoMetadata: (
990
+ params: BuildListProviderActionCommonParams<AnyListen.Music.MusicInfoOnline>
991
+ ) => Promise<AnyListen.Music.MusicInfoOnline>
992
+ }
993
+ type MusicSearchResult = ListCommonResult<AnyListen.Music.MusicInfoOnline>
994
+
995
+ interface ResourceAction {
996
+ // ('tipSearch' | 'hotSearch', CommonParams) => Promise<string[]>
997
+ musicSearch: (params: SearchParams) => Promise<ListCommonResult<AnyListen.Music.MusicInfoOnline>>
998
+ musicPic: (params: MusicCommonParams) => Promise<string>
999
+ musicUrl: (params: MusicUrlParams) => Promise<MusicUrlInfo>
1000
+ musicLyric: (params: MusicCommonParams) => Promise<AnyListen.Music.LyricInfo>
1001
+ musicPicSearch: (params: PicSearchParams) => Promise<string[]>
1002
+ lyricSearch: (params: LyricSearchParams) => Promise<LyricSearchResult[]>
1003
+ lyricDetail: (params: LyricDetailParams) => Promise<AnyListen.Music.LyricInfo>
1004
+ // songlistSearch: (params: SearchParams) => Promise<ListCommonResult<AnyListen.Resource.SongListItem>>
1005
+ // songlistSorts: (params: CommonParams) => Promise<AnyListen.Resource.TagItem[]>
1006
+ // songlistTags: (params: CommonParams) => Promise<AnyListen.Resource.TagGroupItem[]>
1007
+ // songlist: (params: SonglistListParams) => Promise<ListCommonResult<AnyListen.Resource.SongListItem>>
1008
+ // songlistDetail: (params: ListDetailParams) => Promise<ListCommonResult<Music.MusicInfoOnline>>
1009
+ // leaderboard: (params: CommonParams) => Promise<AnyListen.Resource.TagGroupItem[]>
1010
+ // leaderboardDate: (params: SonglistListParams) => Promise<ListCommonResult<Music.MusicInfoOnline>>
1011
+ // leaderboardDetail: (params: SonglistListParams) => Promise<ListCommonResult<Music.MusicInfoOnline>>
1012
+ }
1013
+
1014
+ interface BackupDataAction {
1015
+ getListMD5: () => Promise<string | null>
1016
+ getListData: () => Promise<string | null>
1017
+ setListData: (data: string, md5: string) => Promise<void>
1018
+ getDislikeMD5: () => Promise<string | null>
1019
+ getDislikeData: () => Promise<string | null>
1020
+ setDislikeData: (data: string, md5: string) => Promise<void>
1021
+ }
1022
+ interface Logcat {
1023
+ debug: (...args: unknown[]) => void
1024
+ info: (...args: unknown[]) => void
1025
+ warn: (...args: unknown[]) => void
1026
+ error: (...args: unknown[]) => void
1027
+ }
1028
+ interface Storage {
1029
+ writeFile: (path: string, data: Uint8Array | string) => Promise<void>
1030
+ readFile: <T extends 'utf-8' | 'binary' = 'utf-8'>(
1031
+ path: string,
1032
+ encoding?: T
1033
+ ) => Promise<T extends 'utf-8' ? string : Uint8Array>
1034
+ removeFile: (path: string) => Promise<void>
1035
+ fileExists: (path: string) => Promise<boolean>
1036
+ listFiles: (path?: string) => Promise<string[]>
1037
+ statFile: (path: string) => Promise<{ isFile: boolean; size: number; createTime: number; updateTime: number }>
1038
+ }
1039
+ interface Crypto {
1040
+ aesEncrypt: (
1041
+ mode: AES_MODE,
1042
+ data: Uint8Array | string,
1043
+ key: Uint8Array | string,
1044
+ iv: Uint8Array | string
1045
+ ) => Promise<string>
1046
+ rsaEncrypt: (mode: RSA_PADDING, data: Uint8Array, key: Uint8Array) => Promise<string>
1047
+ randomBytes: (size: number) => Promise<Uint8Array>
1048
+ md5: (text: string | Uint8Array) => Promise<string>
1049
+ sha1: (text: string | Uint8Array) => Promise<string>
1050
+ sha256: (text: string | Uint8Array) => Promise<string>
1051
+ sha512: (text: string | Uint8Array) => Promise<string>
1052
+ }
1053
+ interface Iconv {
1054
+ decode: (data: Uint8Array | Uint16Array, encoding: string) => Promise<string>
1055
+ encode: (data: string, encoding: string) => Promise<Uint8Array>
1056
+ }
1057
+ interface Zlib {
1058
+ deflate: <T extends 'base64' | 'binary' = 'binary'>(
1059
+ data: Uint8Array | string,
1060
+ encoding?: T
1061
+ ) => Promise<T extends 'base64' ? string : Uint8Array>
1062
+ inflate: <T extends 'utf-8' | 'binary' = 'binary'>(
1063
+ data: Uint8Array | string,
1064
+ encoding?: T
1065
+ ) => Promise<T extends 'utf-8' ? string : Uint8Array>
1066
+ }
1067
+ interface Configuration {
1068
+ getConfigs: <T extends unknown[] = []>(keys: string[]) => Promise<WithUndefined<T>>
1069
+ setConfigs: (datas: Record<string, unknown>) => Promise<void>
1070
+ onConfigChanged: (callback: (keys: string[], configuration: Record<string, unknown>) => void) => () => void
1071
+ }
1072
+ interface MusicUtils {
1073
+ createProxyUrl: (url: string, options?: RequestOptions, enabledCache?: boolean) => Promise<string>
1074
+ writeProxyCache: (fileName: string, data: Uint8Array) => Promise<string>
1075
+ }
1076
+ interface IsolateContext {
1077
+ sendMessage: (message: unknown) => Promise<void>
1078
+ run: (code: string) => Promise<void>
1079
+ runFile: (filePath: string) => Promise<void>
1080
+ destroy: () => Promise<void>
1081
+ }
1082
+ interface Command {
1083
+ registerCommand: (command: string, callback: (...args: unknown[]) => Promise<unknown>) => Promise<() => void>
1084
+ executeCommand: (command: string, ...args: unknown[]) => Promise<unknown>
1085
+ getCommands: (filterInternal?: boolean) => Promise<string[]>
1086
+ }
1087
+ interface API {
1088
+ env: Env
1089
+ app: App
1090
+ musicList?: MusicList
1091
+ player?: Player
1092
+ musicUtils: MusicUtils
1093
+ /** http 请求 */
1094
+ request?: <Resp = unknown>(url: string, options?: RequestOptions) => Promise<Response<Resp>>
1095
+ t: (key: string, data?: Record<string, string | number | null | undefined>) => string
1096
+ logcat: Logcat
1097
+ storage: Storage
1098
+ configuration: Configuration
1099
+ registerResourceAction: (actions: Partial<ResourceAction>) => void
1100
+ // TODO
1101
+ // backup: {
1102
+ // runBackup: (opts: { backupData?: Array<'list' | 'dislike'> }) => Promise<void>
1103
+ // registerDataAction: (actions: BackupDataAction) => void
1104
+ // }
1105
+ utils: {
1106
+ crypto: Crypto
1107
+ iconv: Iconv
1108
+ zlib: Zlib
1109
+ createIsolateContext?: (onMessage: (message: unknown) => void) => Promise<IsolateContext>
1110
+ dataConverter: {
1111
+ <R extends ConverterFormatTo = 'binary'>(
1112
+ input: string,
1113
+ fromEncoding?: ConverterFormatFrom,
1114
+ toEncoding?: R
1115
+ ): Promise<R extends 'binary' ? Uint8Array : string>
1116
+ <R extends ConverterBinaryFormatTo = 'utf-8'>(
1117
+ input: Uint8Array,
1118
+ toEncoding?: R
1119
+ ): Promise<R extends 'binary' ? Uint8Array : string>
1120
+ }
1121
+ }
1122
+ command: Command
1123
+ }
1124
+ }
1125
+ }
1126
+
1127
+ export {}