Manages the lifecycle and execution of extractors. Handles registration, activation, deactivation, and orchestrates extractor execution.
Constructor
new ExtractorExecutionContext(player: Player)
The player instance managing this context
Properties
Reference to the parent player instance
store
Collection<string, BaseExtractor>
Collection storing all registered extractors by their identifier
context
Context<ExtractorSession>
Execution context for tracking extractor sessions
Number of registered extractors
Methods
register
Register and activate a single extractor.
async register<O extends object, T extends typeof BaseExtractor<O>>(
_extractor: T,
options: ConstructorParameters<T>['1']
): Promise<InstanceType<T> | null>
The extractor class to register
Options to pass to the extractor constructor
return
Promise<InstanceType<T> | null>
The registered extractor instance, or null if registration failed
Example:
import { MyExtractor } from './extractors/MyExtractor';
const extractor = await player.extractors.register(MyExtractor, {
apiKey: 'your-api-key',
timeout: 5000
});
if (extractor) {
console.log('Extractor registered successfully');
}
unregister
Unregister and deactivate a single extractor.
async unregister<K extends string | BaseExtractor>(_extractor: K): Promise<void>
The extractor identifier or instance to unregister
Example:
// Unregister by identifier
await player.extractors.unregister('com.example.my-extractor');
// Unregister by instance
await player.extractors.unregister(myExtractor);
unregisterAll
Unregister all extractors.
async unregisterAll(): Promise<void>
Example:
await player.extractors.unregisterAll();
console.log('All extractors unregistered');
loadMulti
Load multiple extractors at once from a bundle.
async loadMulti<
O extends object,
T extends (typeof BaseExtractor<O>)[],
R extends Record<T[number]['identifier'], ConstructorParameters<T[number]>[1]>
>(
bundle: T,
options?: R
): Promise<{ success: boolean; error: null }>
bundle
(typeof BaseExtractor)[]
required
Array of extractor classes to register
Object mapping extractor identifiers to their options
return
Promise<{ success: boolean; error: null }>
Success indicator object
Example:
import { DefaultExtractors } from '@discord-player/extractor';
// Load all default extractors
await player.extractors.loadMulti(DefaultExtractors);
// Load with specific options
await player.extractors.loadMulti(DefaultExtractors, {
'com.discord-player.youtubeextractor': {
authentication: 'your-token'
},
'com.discord-player.spotifyextractor': {
clientId: 'your-client-id',
clientSecret: 'your-client-secret'
}
});
get
Get a registered extractor by identifier.
get(identifier: string): BaseExtractor | undefined
return
BaseExtractor | undefined
The extractor instance if found
Example:
const youtubeExtractor = player.extractors.get('com.discord-player.youtubeextractor');
if (youtubeExtractor) {
console.log('YouTube extractor is registered');
}
isRegistered
Check if an extractor is registered.
isRegistered(identifier: string): boolean
The extractor identifier to check
true if registered, false otherwise
Example:
if (player.extractors.isRegistered('com.example.my-extractor')) {
console.log('MyExtractor is active');
}
isDisabled
Check if an extractor is disabled via player options.
isDisabled(identifier: string): boolean
The extractor identifier to check
true if disabled, false otherwise
Example:
if (player.extractors.isDisabled('com.discord-player.youtubeextractor')) {
console.log('YouTube extractor is blocked');
}
isEnabled
Check if an extractor is enabled.
isEnabled(identifier: string): boolean
The extractor identifier to check
true if enabled, false otherwise
Example:
if (player.extractors.isEnabled('com.discord-player.spotifyextractor')) {
console.log('Spotify extractor is available');
}
run
Execute a function across all registered extractors by priority.
async run<T = unknown>(
fn: ExtractorExecutionFN<T>,
filterBlocked?: boolean
): Promise<ExtractorExecutionResult<T> | undefined>
fn
ExtractorExecutionFN<T>
required
Function to execute for each extractor: (extractor: BaseExtractor) => Promise<T | boolean>
Whether to skip blocked extractors
return
Promise<ExtractorExecutionResult<T> | undefined>
Result object containing:
extractor: The extractor that succeeded
error: Error if all failed
result: The result value
Example:
// Search across all extractors
const result = await player.extractors.run(async (extractor) => {
const canHandle = await extractor.validate(query);
if (!canHandle) return false;
return await extractor.handle(query, context);
});
if (result?.result) {
console.log('Found tracks:', result.result.tracks);
console.log('Using extractor:', result.extractor.identifier);
}
requestBridge
Request a bridge for streaming a track from a different extractor.
async requestBridge(
track: Track,
sourceExtractor?: BaseExtractor | null
): Promise<ExtractorExecutionResult<ExtractorStreamable>>
The track to request bridge for
The original extractor that found the track. Defaults to track.extractor
return
Promise<ExtractorExecutionResult<ExtractorStreamable>>
Result containing the bridged stream and extractor used
Example:
try {
const bridge = await player.extractors.requestBridge(track);
console.log('Bridge successful via:', bridge.extractor.identifier);
// Use bridge.result as the stream
} catch (error) {
console.error('Bridge failed:', error);
}
requestBridgeFrom
Request a bridge from a specific extractor.
async requestBridgeFrom(
track: Track,
sourceExtractor: BaseExtractor | null,
targetExtractor: ExtractorResolvable
): Promise<ExtractorStreamable | null>
The extractor identifier or instance to bridge to
return
Promise<ExtractorStreamable | null>
The bridged stream or null if bridging failed
Example:
const stream = await player.extractors.requestBridgeFrom(
track,
spotifyExtractor,
'com.discord-player.youtubeextractor'
);
if (stream) {
console.log('Successfully bridged to YouTube');
}
getExecutionId
Get the current execution context ID.
getExecutionId(): string | null
The execution ID or null if not in an execution context
Example:
const executionId = player.extractors.getExecutionId();
console.log('Current execution:', executionId);
getContext
Get the current execution context.
getContext(): ExtractorSession | null
The execution context containing:
id: Execution ID
attemptedExtractors: Set of extractor identifiers attempted
bridgeAttemptedExtractors: Set of bridge extractors attempted
Example:
const context = player.extractors.getContext();
if (context) {
console.log('Attempted extractors:', context.attemptedExtractors);
}
resolve
Resolve an extractor from identifier or instance.
resolve(resolvable: ExtractorResolvable): BaseExtractor | undefined
resolvable
string | BaseExtractor
required
Extractor identifier or instance
return
BaseExtractor | undefined
The resolved extractor instance
Example:
const extractor = player.extractors.resolve('com.discord-player.youtubeextractor');
const same = player.extractors.resolve(extractor); // Returns same instance
resolveId
Resolve an extractor identifier from identifier or instance.
resolveId(resolvable: ExtractorResolvable): string
resolvable
string | BaseExtractor
required
Extractor identifier or instance
Example:
const id = player.extractors.resolveId(myExtractor);
console.log('Extractor ID:', id);
Events
registered
(context: ExtractorExecutionContext, extractor: BaseExtractor) => unknown
Emitted when an extractor is registered
unregistered
(context: ExtractorExecutionContext, extractor: BaseExtractor) => unknown
Emitted when an extractor is unregistered
activate
(context: ExtractorExecutionContext, extractor: BaseExtractor) => unknown
Emitted when an extractor is activated
deactivate
(context: ExtractorExecutionContext, extractor: BaseExtractor) => unknown
Emitted when an extractor is deactivated
error
(context: ExtractorExecutionContext, extractor: BaseExtractor, error: Error) => unknown
Emitted when an extractor fails to activate/deactivate
Example:
player.extractors.on('registered', (context, extractor) => {
console.log(`Registered: ${extractor.identifier}`);
});
player.extractors.on('error', (context, extractor, error) => {
console.error(`Extractor error in ${extractor.identifier}:`, error);
});
Types
Result from extractor execution.
interface ExtractorExecutionResult<T = unknown> {
extractor: BaseExtractor;
error: Error | null;
result: T;
}
Function executed for each extractor.
type ExtractorExecutionFN<T = unknown> = (
extractor: BaseExtractor
) => Promise<T | boolean>;
Value that can be resolved to an extractor.
type ExtractorResolvable = string | BaseExtractor;
Execution session context.
interface ExtractorSession {
id: string;
attemptedExtractors: Set<string>;
bridgeAttemptedExtractors: Set<string>;
}
Usage Example
import { Player } from 'discord-player';
import { DefaultExtractors } from '@discord-player/extractor';
import { MyCustomExtractor } from './MyCustomExtractor';
const player = new Player(client);
// Load default extractors
await player.extractors.loadMulti(DefaultExtractors, {
'com.discord-player.youtubeextractor': {
authentication: process.env.YOUTUBE_TOKEN
}
});
// Register custom extractor
await player.extractors.register(MyCustomExtractor, {
apiKey: process.env.CUSTOM_API_KEY
});
// Listen to events
player.extractors.on('registered', (ctx, ext) => {
console.log(`✅ ${ext.identifier} registered`);
});
player.extractors.on('error', (ctx, ext, error) => {
console.error(`❌ ${ext.identifier} error:`, error);
});
// Check registered extractors
console.log(`Registered extractors: ${player.extractors.size}`);
// Get specific extractor
const youtube = player.extractors.get('com.discord-player.youtubeextractor');
if (youtube) {
console.log('YouTube priority:', youtube.priority);
}
// Disable an extractor
if (player.extractors.isEnabled('com.discord-player.soundcloudextractor')) {
await player.extractors.unregister('com.discord-player.soundcloudextractor');
}