@students-dev/audify-js 1.0.1 → 1.0.2
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.
- package/README.md +92 -441
- package/dist/AudioEngine.js +232 -0
- package/dist/cjs/index.js +1478 -1746
- package/dist/cjs/index.js.map +1 -1
- package/dist/constants/index.js +35 -0
- package/dist/engine/Filters.js +137 -0
- package/dist/engine/MockAudioContext.js +53 -0
- package/dist/engine/Player.js +209 -0
- package/dist/esm/index.js +1474 -1744
- package/dist/esm/index.js.map +1 -1
- package/dist/events/EventBus.js +61 -0
- package/dist/index.js +18 -0
- package/dist/interfaces/index.js +1 -0
- package/dist/plugins/Plugin.js +27 -0
- package/dist/plugins/PluginManager.js +106 -0
- package/dist/providers/LavalinkProvider.js +81 -0
- package/dist/providers/LocalProvider.js +70 -0
- package/dist/providers/ProviderRegistry.js +20 -0
- package/dist/providers/SpotifyProvider.js +59 -0
- package/dist/providers/YouTubeProvider.js +48 -0
- package/dist/queue/Queue.js +186 -0
- package/dist/queue/Track.js +54 -0
- package/dist/types/AudioEngine.d.ts +107 -0
- package/dist/types/constants/index.d.ts +39 -0
- package/dist/types/engine/Filters.d.ts +25 -24
- package/dist/types/engine/MockAudioContext.d.ts +43 -0
- package/dist/types/engine/Player.d.ts +25 -21
- package/dist/types/events/EventBus.d.ts +17 -15
- package/dist/types/index.d.ts +17 -15
- package/dist/types/interfaces/index.d.ts +31 -0
- package/dist/types/plugins/Plugin.d.ts +11 -43
- package/dist/types/plugins/PluginManager.d.ts +19 -19
- package/dist/types/providers/LavalinkProvider.d.ts +15 -46
- package/dist/types/providers/LocalProvider.d.ts +11 -22
- package/dist/types/providers/ProviderRegistry.d.ts +10 -0
- package/dist/types/providers/SpotifyProvider.d.ts +12 -52
- package/dist/types/providers/YouTubeProvider.d.ts +11 -28
- package/dist/types/queue/Queue.d.ts +28 -22
- package/dist/types/queue/Track.d.ts +18 -16
- package/dist/types/utils/Logger.d.ts +12 -16
- package/dist/types/utils/Metadata.d.ts +16 -15
- package/dist/types/utils/Probe.d.ts +7 -7
- package/dist/types/utils/Time.d.ts +9 -9
- package/dist/utils/Logger.js +59 -0
- package/dist/utils/Metadata.js +90 -0
- package/dist/utils/Probe.js +59 -0
- package/dist/utils/Time.js +54 -0
- package/package.json +14 -8
|
@@ -1,23 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* Get track info from local file
|
|
13
|
-
* @param {string} path - File path
|
|
14
|
-
* @returns {Promise<Object>} Track info
|
|
15
|
-
*/
|
|
16
|
-
static getInfo(path: string): Promise<any>;
|
|
17
|
-
/**
|
|
18
|
-
* Check if file exists
|
|
19
|
-
* @param {string} path - File path
|
|
20
|
-
* @returns {Promise<boolean>} File exists
|
|
21
|
-
*/
|
|
22
|
-
static exists(path: string): Promise<boolean>;
|
|
1
|
+
import { IProvider, ITrack, IAudioEngine } from '../interfaces';
|
|
2
|
+
export declare class LocalProvider implements IProvider {
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
private engine;
|
|
6
|
+
initialize(engine: IAudioEngine): Promise<void>;
|
|
7
|
+
resolve(path: string): Promise<ITrack | ITrack[]>;
|
|
8
|
+
play(track: ITrack): Promise<void>;
|
|
9
|
+
stop(): Promise<void>;
|
|
10
|
+
destroy(): void;
|
|
11
|
+
private exists;
|
|
23
12
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IProvider } from '../interfaces';
|
|
2
|
+
export declare class ProviderRegistry {
|
|
3
|
+
private providers;
|
|
4
|
+
constructor();
|
|
5
|
+
register(provider: IProvider): void;
|
|
6
|
+
unregister(name: string): void;
|
|
7
|
+
get(name: string): IProvider | undefined;
|
|
8
|
+
getAll(): IProvider[];
|
|
9
|
+
has(name: string): boolean;
|
|
10
|
+
}
|
|
@@ -1,54 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
spotifyApi
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* Set refresh token
|
|
14
|
-
* @param {string} token - OAuth refresh token
|
|
15
|
-
*/
|
|
16
|
-
setRefreshToken(token: string): void;
|
|
17
|
-
/**
|
|
18
|
-
* Refresh access token
|
|
19
|
-
* @returns {Promise<Object>} Token response
|
|
20
|
-
*/
|
|
21
|
-
refreshAccessToken(): Promise<any>;
|
|
22
|
-
/**
|
|
23
|
-
* Search tracks
|
|
24
|
-
* @param {string} query - Search query
|
|
25
|
-
* @param {Object} options - Search options
|
|
26
|
-
* @returns {Promise<Array>} Array of track objects
|
|
27
|
-
*/
|
|
28
|
-
searchTracks(query: string, options?: any): Promise<any[]>;
|
|
29
|
-
/**
|
|
30
|
-
* Get track by ID
|
|
31
|
-
* @param {string} trackId - Spotify track ID
|
|
32
|
-
* @returns {Promise<Object>} Track object
|
|
33
|
-
*/
|
|
34
|
-
getTrack(trackId: string): Promise<any>;
|
|
35
|
-
/**
|
|
36
|
-
* Get tracks by IDs
|
|
37
|
-
* @param {Array<string>} trackIds - Array of Spotify track IDs
|
|
38
|
-
* @returns {Promise<Array>} Array of track objects
|
|
39
|
-
*/
|
|
40
|
-
getTracks(trackIds: Array<string>): Promise<any[]>;
|
|
41
|
-
/**
|
|
42
|
-
* Get audio features for track
|
|
43
|
-
* @param {string} trackId - Spotify track ID
|
|
44
|
-
* @returns {Promise<Object>} Audio features
|
|
45
|
-
*/
|
|
46
|
-
getAudioFeatures(trackId: string): Promise<any>;
|
|
47
|
-
/**
|
|
48
|
-
* Format Spotify track to internal format
|
|
49
|
-
* @param {Object} spotifyTrack - Spotify track object
|
|
50
|
-
* @returns {Object} Formatted track
|
|
51
|
-
* @private
|
|
52
|
-
*/
|
|
1
|
+
import { IProvider, ITrack, IAudioEngine } from '../interfaces';
|
|
2
|
+
export declare class SpotifyProvider implements IProvider {
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
private engine;
|
|
6
|
+
private spotifyApi;
|
|
7
|
+
constructor(options?: any);
|
|
8
|
+
initialize(engine: IAudioEngine): Promise<void>;
|
|
9
|
+
resolve(query: string): Promise<ITrack | ITrack[]>;
|
|
10
|
+
play(track: ITrack): Promise<void>;
|
|
11
|
+
stop(): Promise<void>;
|
|
12
|
+
destroy(): void;
|
|
53
13
|
private _formatTrack;
|
|
54
14
|
}
|
|
@@ -1,29 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* Extract video ID from YouTube URL
|
|
13
|
-
* @param {string} url - YouTube URL
|
|
14
|
-
* @returns {string|null} Video ID
|
|
15
|
-
*/
|
|
16
|
-
static extractVideoId(url: string): string | null;
|
|
17
|
-
/**
|
|
18
|
-
* Get basic track info from YouTube URL
|
|
19
|
-
* @param {string} url - YouTube URL
|
|
20
|
-
* @returns {Promise<Object>} Track info
|
|
21
|
-
*/
|
|
22
|
-
static getInfo(url: string): Promise<any>;
|
|
23
|
-
/**
|
|
24
|
-
* Get stream URL (not implemented without dependencies)
|
|
25
|
-
* @param {string} url - YouTube URL
|
|
26
|
-
* @returns {Promise<string>} Stream URL
|
|
27
|
-
*/
|
|
28
|
-
static getStreamUrl(url: string): Promise<string>;
|
|
1
|
+
import { IProvider, ITrack, IAudioEngine } from '../interfaces';
|
|
2
|
+
export declare class YouTubeProvider implements IProvider {
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
private engine;
|
|
6
|
+
initialize(engine: IAudioEngine): Promise<void>;
|
|
7
|
+
resolve(query: string): Promise<ITrack | ITrack[]>;
|
|
8
|
+
play(track: ITrack): Promise<void>;
|
|
9
|
+
stop(): Promise<void>;
|
|
10
|
+
destroy(): void;
|
|
11
|
+
private extractVideoId;
|
|
29
12
|
}
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
+
import { Track } from './Track';
|
|
2
|
+
import { EventBus } from '../events/EventBus';
|
|
3
|
+
import { ITrack } from '../interfaces';
|
|
1
4
|
/**
|
|
2
5
|
* Audio queue management
|
|
3
6
|
*/
|
|
4
|
-
export class Queue {
|
|
5
|
-
tracks
|
|
6
|
-
currentIndex
|
|
7
|
+
export declare class Queue {
|
|
8
|
+
private tracks;
|
|
9
|
+
private currentIndex;
|
|
7
10
|
eventBus: EventBus;
|
|
11
|
+
constructor();
|
|
8
12
|
/**
|
|
9
13
|
* Add track(s) to queue
|
|
10
|
-
* @param
|
|
11
|
-
* @param
|
|
14
|
+
* @param tracks - Track(s) to add
|
|
15
|
+
* @param position - Position to insert (optional)
|
|
12
16
|
*/
|
|
13
|
-
add(tracks: Track | Track[] | string | string[], position
|
|
17
|
+
add(tracks: Track | ITrack | (Track | ITrack)[] | string | string[], position?: number): void;
|
|
14
18
|
/**
|
|
15
19
|
* Remove track from queue
|
|
16
|
-
* @param
|
|
17
|
-
* @returns
|
|
20
|
+
* @param identifier - Track index or ID
|
|
21
|
+
* @returns Removed track
|
|
18
22
|
*/
|
|
19
23
|
remove(identifier: number | string): Track | null;
|
|
20
24
|
/**
|
|
@@ -27,46 +31,48 @@ export class Queue {
|
|
|
27
31
|
clear(): void;
|
|
28
32
|
/**
|
|
29
33
|
* Jump to specific track
|
|
30
|
-
* @param
|
|
31
|
-
* @returns
|
|
34
|
+
* @param index - Track index
|
|
35
|
+
* @returns Track at index
|
|
32
36
|
*/
|
|
33
37
|
jump(index: number): Track | null;
|
|
34
38
|
/**
|
|
35
39
|
* Get current track
|
|
36
|
-
* @returns
|
|
40
|
+
* @returns Current track
|
|
37
41
|
*/
|
|
38
42
|
getCurrent(): Track | null;
|
|
39
43
|
/**
|
|
40
44
|
* Get next track
|
|
41
|
-
*
|
|
45
|
+
* Moves cursor forward
|
|
46
|
+
* @param loop - Whether to loop back to start
|
|
47
|
+
* @returns Next track
|
|
42
48
|
*/
|
|
43
|
-
|
|
49
|
+
next(loop?: boolean): Track | null;
|
|
44
50
|
/**
|
|
45
51
|
* Get previous track
|
|
46
|
-
*
|
|
52
|
+
* Moves cursor backward
|
|
53
|
+
* @param loop - Whether to loop to end
|
|
54
|
+
* @returns Previous track
|
|
47
55
|
*/
|
|
48
|
-
|
|
56
|
+
previous(loop?: boolean): Track | null;
|
|
49
57
|
/**
|
|
50
58
|
* Get all tracks
|
|
51
|
-
* @returns
|
|
59
|
+
* @returns Array of tracks
|
|
52
60
|
*/
|
|
53
61
|
getTracks(): Track[];
|
|
54
62
|
/**
|
|
55
63
|
* Get queue size
|
|
56
|
-
* @returns
|
|
64
|
+
* @returns Number of tracks
|
|
57
65
|
*/
|
|
58
66
|
size(): number;
|
|
59
67
|
/**
|
|
60
68
|
* Check if queue is empty
|
|
61
|
-
* @returns
|
|
69
|
+
* @returns Is empty
|
|
62
70
|
*/
|
|
63
71
|
isEmpty(): boolean;
|
|
64
72
|
/**
|
|
65
73
|
* Get track at index
|
|
66
|
-
* @param
|
|
67
|
-
* @returns
|
|
74
|
+
* @param index - Track index
|
|
75
|
+
* @returns Track at index
|
|
68
76
|
*/
|
|
69
77
|
getTrack(index: number): Track | null;
|
|
70
78
|
}
|
|
71
|
-
import { EventBus } from '../events/EventBus.js';
|
|
72
|
-
import { Track } from './Track.js';
|
|
@@ -1,32 +1,34 @@
|
|
|
1
|
+
import { ITrack } from '../interfaces';
|
|
1
2
|
/**
|
|
2
3
|
* Represents an audio track
|
|
3
4
|
*/
|
|
4
|
-
export class Track {
|
|
5
|
+
export declare class Track implements ITrack {
|
|
6
|
+
id: string;
|
|
7
|
+
url: string;
|
|
8
|
+
title: string;
|
|
9
|
+
artist?: string;
|
|
10
|
+
duration?: number;
|
|
11
|
+
thumbnail?: string;
|
|
12
|
+
source?: string;
|
|
13
|
+
metadata: Record<string, any>;
|
|
5
14
|
/**
|
|
6
|
-
* @param
|
|
7
|
-
* @param
|
|
15
|
+
* @param url - Track URL or file path
|
|
16
|
+
* @param options - Additional options
|
|
8
17
|
*/
|
|
9
|
-
constructor(url: string, options?:
|
|
10
|
-
url: string;
|
|
11
|
-
title: any;
|
|
12
|
-
artist: any;
|
|
13
|
-
duration: any;
|
|
14
|
-
thumbnail: any;
|
|
15
|
-
metadata: any;
|
|
16
|
-
id: any;
|
|
18
|
+
constructor(url: string, options?: Partial<ITrack>);
|
|
17
19
|
/**
|
|
18
20
|
* Get track info
|
|
19
|
-
* @returns
|
|
21
|
+
* @returns Track information
|
|
20
22
|
*/
|
|
21
|
-
getInfo():
|
|
23
|
+
getInfo(): ITrack;
|
|
22
24
|
/**
|
|
23
25
|
* Update track metadata
|
|
24
|
-
* @param
|
|
26
|
+
* @param metadata - New metadata
|
|
25
27
|
*/
|
|
26
|
-
updateMetadata(metadata:
|
|
28
|
+
updateMetadata(metadata: Partial<ITrack>): void;
|
|
27
29
|
/**
|
|
28
30
|
* Check if track is valid
|
|
29
|
-
* @returns
|
|
31
|
+
* @returns Is valid
|
|
30
32
|
*/
|
|
31
33
|
isValid(): boolean;
|
|
32
34
|
}
|
|
@@ -1,39 +1,35 @@
|
|
|
1
|
+
export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
1
2
|
/**
|
|
2
3
|
* Logger utility with different levels
|
|
3
4
|
*/
|
|
4
|
-
export class Logger {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
info: number;
|
|
9
|
-
warn: number;
|
|
10
|
-
error: number;
|
|
11
|
-
};
|
|
12
|
-
currentLevel: any;
|
|
5
|
+
export declare class Logger {
|
|
6
|
+
private levels;
|
|
7
|
+
private currentLevel;
|
|
8
|
+
constructor(level?: LogLevel);
|
|
13
9
|
/**
|
|
14
10
|
* Set log level
|
|
15
|
-
* @param
|
|
11
|
+
* @param level - Log level (debug, info, warn, error)
|
|
16
12
|
*/
|
|
17
|
-
setLevel(level:
|
|
13
|
+
setLevel(level: LogLevel): void;
|
|
18
14
|
/**
|
|
19
15
|
* Debug log
|
|
20
|
-
* @param
|
|
16
|
+
* @param args - Arguments to log
|
|
21
17
|
*/
|
|
22
18
|
debug(...args: any[]): void;
|
|
23
19
|
/**
|
|
24
20
|
* Info log
|
|
25
|
-
* @param
|
|
21
|
+
* @param args - Arguments to log
|
|
26
22
|
*/
|
|
27
23
|
info(...args: any[]): void;
|
|
28
24
|
/**
|
|
29
25
|
* Warning log
|
|
30
|
-
* @param
|
|
26
|
+
* @param args - Arguments to log
|
|
31
27
|
*/
|
|
32
28
|
warn(...args: any[]): void;
|
|
33
29
|
/**
|
|
34
30
|
* Error log
|
|
35
|
-
* @param
|
|
31
|
+
* @param args - Arguments to log
|
|
36
32
|
*/
|
|
37
33
|
error(...args: any[]): void;
|
|
38
34
|
}
|
|
39
|
-
export const logger: Logger;
|
|
35
|
+
export declare const logger: Logger;
|
|
@@ -1,35 +1,36 @@
|
|
|
1
|
+
import { ITrack } from '../interfaces';
|
|
1
2
|
/**
|
|
2
3
|
* Metadata parsing utilities
|
|
3
4
|
*/
|
|
4
|
-
export class MetadataUtils {
|
|
5
|
+
export declare class MetadataUtils {
|
|
5
6
|
/**
|
|
6
7
|
* Extract basic metadata from URL or file path
|
|
7
|
-
* @param
|
|
8
|
-
* @returns
|
|
8
|
+
* @param source - URL or file path
|
|
9
|
+
* @returns Metadata object
|
|
9
10
|
*/
|
|
10
|
-
static extract(source: string):
|
|
11
|
+
static extract(source: string): Partial<ITrack>;
|
|
11
12
|
/**
|
|
12
13
|
* Extract title from source
|
|
13
|
-
* @param
|
|
14
|
-
* @returns
|
|
14
|
+
* @param source - Source string
|
|
15
|
+
* @returns Extracted title
|
|
15
16
|
*/
|
|
16
17
|
static extractTitle(source: string): string;
|
|
17
18
|
/**
|
|
18
19
|
* Extract YouTube metadata (basic)
|
|
19
|
-
* @param
|
|
20
|
-
* @returns
|
|
20
|
+
* @param url - YouTube URL
|
|
21
|
+
* @returns Metadata
|
|
21
22
|
*/
|
|
22
|
-
static extractYouTubeMetadata
|
|
23
|
+
private static extractYouTubeMetadata;
|
|
23
24
|
/**
|
|
24
25
|
* Extract SoundCloud metadata (basic)
|
|
25
|
-
* @param
|
|
26
|
-
* @returns
|
|
26
|
+
* @param url - SoundCloud URL
|
|
27
|
+
* @returns Metadata
|
|
27
28
|
*/
|
|
28
|
-
static extractSoundCloudMetadata
|
|
29
|
+
private static extractSoundCloudMetadata;
|
|
29
30
|
/**
|
|
30
31
|
* Extract file metadata (basic)
|
|
31
|
-
* @param
|
|
32
|
-
* @returns
|
|
32
|
+
* @param path - File path
|
|
33
|
+
* @returns Metadata
|
|
33
34
|
*/
|
|
34
|
-
static extractFileMetadata
|
|
35
|
+
private static extractFileMetadata;
|
|
35
36
|
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Audio probing utilities
|
|
3
3
|
*/
|
|
4
|
-
export class ProbeUtils {
|
|
4
|
+
export declare class ProbeUtils {
|
|
5
5
|
/**
|
|
6
6
|
* Probe audio file/stream for basic info
|
|
7
|
-
* @param
|
|
8
|
-
* @returns
|
|
7
|
+
* @param source - Audio source
|
|
8
|
+
* @returns Probe result
|
|
9
9
|
*/
|
|
10
10
|
static probe(source: string | Buffer | ReadableStream): Promise<any>;
|
|
11
11
|
/**
|
|
12
12
|
* Check if source is a valid audio URL
|
|
13
|
-
* @param
|
|
14
|
-
* @returns
|
|
13
|
+
* @param url - URL to check
|
|
14
|
+
* @returns Is valid audio URL
|
|
15
15
|
*/
|
|
16
16
|
static isValidAudioUrl(url: string): boolean;
|
|
17
17
|
/**
|
|
18
18
|
* Get audio format from URL or buffer
|
|
19
|
-
* @param
|
|
20
|
-
* @returns
|
|
19
|
+
* @param source - Audio source
|
|
20
|
+
* @returns Audio format
|
|
21
21
|
*/
|
|
22
22
|
static getFormat(source: string | Buffer): string | null;
|
|
23
23
|
}
|
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Time formatting utilities
|
|
3
3
|
*/
|
|
4
|
-
export class TimeUtils {
|
|
4
|
+
export declare class TimeUtils {
|
|
5
5
|
/**
|
|
6
6
|
* Format seconds to MM:SS or HH:MM:SS
|
|
7
|
-
* @param
|
|
8
|
-
* @returns
|
|
7
|
+
* @param seconds - Time in seconds
|
|
8
|
+
* @returns Formatted time string
|
|
9
9
|
*/
|
|
10
10
|
static format(seconds: number): string;
|
|
11
11
|
/**
|
|
12
12
|
* Parse time string to seconds
|
|
13
|
-
* @param
|
|
14
|
-
* @returns
|
|
13
|
+
* @param timeStr - Time string like "1:23" or "01:23:45"
|
|
14
|
+
* @returns Time in seconds
|
|
15
15
|
*/
|
|
16
16
|
static parse(timeStr: string): number;
|
|
17
17
|
/**
|
|
18
18
|
* Get current timestamp in milliseconds
|
|
19
|
-
* @returns
|
|
19
|
+
* @returns Current time
|
|
20
20
|
*/
|
|
21
21
|
static now(): number;
|
|
22
22
|
/**
|
|
23
23
|
* Calculate duration between two timestamps
|
|
24
|
-
* @param
|
|
25
|
-
* @param
|
|
26
|
-
* @returns
|
|
24
|
+
* @param start - Start time
|
|
25
|
+
* @param end - End time
|
|
26
|
+
* @returns Duration in milliseconds
|
|
27
27
|
*/
|
|
28
28
|
static duration(start: number, end: number): number;
|
|
29
29
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger utility with different levels
|
|
3
|
+
*/
|
|
4
|
+
export class Logger {
|
|
5
|
+
constructor(level = 'info') {
|
|
6
|
+
this.levels = {
|
|
7
|
+
debug: 0,
|
|
8
|
+
info: 1,
|
|
9
|
+
warn: 2,
|
|
10
|
+
error: 3
|
|
11
|
+
};
|
|
12
|
+
this.currentLevel = this.levels[level];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Set log level
|
|
16
|
+
* @param level - Log level (debug, info, warn, error)
|
|
17
|
+
*/
|
|
18
|
+
setLevel(level) {
|
|
19
|
+
this.currentLevel = this.levels[level] || this.levels.info;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Debug log
|
|
23
|
+
* @param args - Arguments to log
|
|
24
|
+
*/
|
|
25
|
+
debug(...args) {
|
|
26
|
+
if (this.currentLevel <= this.levels.debug) {
|
|
27
|
+
console.debug('[DEBUG]', ...args);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Info log
|
|
32
|
+
* @param args - Arguments to log
|
|
33
|
+
*/
|
|
34
|
+
info(...args) {
|
|
35
|
+
if (this.currentLevel <= this.levels.info) {
|
|
36
|
+
console.info('[INFO]', ...args);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Warning log
|
|
41
|
+
* @param args - Arguments to log
|
|
42
|
+
*/
|
|
43
|
+
warn(...args) {
|
|
44
|
+
if (this.currentLevel <= this.levels.warn) {
|
|
45
|
+
console.warn('[WARN]', ...args);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Error log
|
|
50
|
+
* @param args - Arguments to log
|
|
51
|
+
*/
|
|
52
|
+
error(...args) {
|
|
53
|
+
if (this.currentLevel <= this.levels.error) {
|
|
54
|
+
console.error('[ERROR]', ...args);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Default logger instance
|
|
59
|
+
export const logger = new Logger();
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata parsing utilities
|
|
3
|
+
*/
|
|
4
|
+
export class MetadataUtils {
|
|
5
|
+
/**
|
|
6
|
+
* Extract basic metadata from URL or file path
|
|
7
|
+
* @param source - URL or file path
|
|
8
|
+
* @returns Metadata object
|
|
9
|
+
*/
|
|
10
|
+
static extract(source) {
|
|
11
|
+
if (!source)
|
|
12
|
+
return {};
|
|
13
|
+
const metadata = {
|
|
14
|
+
title: this.extractTitle(source),
|
|
15
|
+
artist: undefined,
|
|
16
|
+
duration: undefined,
|
|
17
|
+
thumbnail: undefined
|
|
18
|
+
};
|
|
19
|
+
// For YouTube URLs
|
|
20
|
+
if (source.includes('youtube.com') || source.includes('youtu.be')) {
|
|
21
|
+
return this.extractYouTubeMetadata(source);
|
|
22
|
+
}
|
|
23
|
+
// For SoundCloud URLs
|
|
24
|
+
if (source.includes('soundcloud.com')) {
|
|
25
|
+
return this.extractSoundCloudMetadata(source);
|
|
26
|
+
}
|
|
27
|
+
// For local files
|
|
28
|
+
if (!source.startsWith('http')) {
|
|
29
|
+
return this.extractFileMetadata(source);
|
|
30
|
+
}
|
|
31
|
+
return metadata;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Extract title from source
|
|
35
|
+
* @param source - Source string
|
|
36
|
+
* @returns Extracted title
|
|
37
|
+
*/
|
|
38
|
+
static extractTitle(source) {
|
|
39
|
+
if (!source)
|
|
40
|
+
return 'Unknown Track';
|
|
41
|
+
// Try to extract from URL query params
|
|
42
|
+
try {
|
|
43
|
+
const url = new URL(source);
|
|
44
|
+
const title = url.searchParams.get('title') || url.searchParams.get('name');
|
|
45
|
+
if (title)
|
|
46
|
+
return decodeURIComponent(title);
|
|
47
|
+
}
|
|
48
|
+
catch { } // eslint-disable-line no-empty
|
|
49
|
+
// Extract from file path
|
|
50
|
+
const parts = source.split('/').pop()?.split('\\').pop();
|
|
51
|
+
if (parts) {
|
|
52
|
+
return parts.replace(/\.[^/.]+$/, ''); // Remove extension
|
|
53
|
+
}
|
|
54
|
+
return 'Unknown Track';
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Extract YouTube metadata (basic)
|
|
58
|
+
* @param url - YouTube URL
|
|
59
|
+
* @returns Metadata
|
|
60
|
+
*/
|
|
61
|
+
static extractYouTubeMetadata(url) {
|
|
62
|
+
return {
|
|
63
|
+
title: 'YouTube Track',
|
|
64
|
+
source: 'youtube'
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Extract SoundCloud metadata (basic)
|
|
69
|
+
* @param url - SoundCloud URL
|
|
70
|
+
* @returns Metadata
|
|
71
|
+
*/
|
|
72
|
+
static extractSoundCloudMetadata(url) {
|
|
73
|
+
return {
|
|
74
|
+
title: 'SoundCloud Track',
|
|
75
|
+
source: 'soundcloud'
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Extract file metadata (basic)
|
|
80
|
+
* @param path - File path
|
|
81
|
+
* @returns Metadata
|
|
82
|
+
*/
|
|
83
|
+
static extractFileMetadata(path) {
|
|
84
|
+
const title = this.extractTitle(path);
|
|
85
|
+
return {
|
|
86
|
+
title,
|
|
87
|
+
source: 'local'
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|