Skip to main content

ExtractorExecutionContext

Manages the lifecycle and execution of extractors. Handles registration, activation, deactivation, and orchestrates extractor execution.

Constructor

new ExtractorExecutionContext(player: Player)
player
Player
required
The player instance managing this context

Properties

player
Player
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
size
number
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>
_extractor
typeof BaseExtractor
required
The extractor class to register
options
object
required
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>
_extractor
string | BaseExtractor
required
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
options
Record<string, object>
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
identifier
string
required
The extractor identifier
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
identifier
string
required
The extractor identifier to check
return
boolean
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
identifier
string
required
The extractor identifier to check
return
boolean
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
identifier
string
required
The extractor identifier to check
return
boolean
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>
filterBlocked
boolean
default:true
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>>
track
Track
required
The track to request bridge for
sourceExtractor
BaseExtractor | null
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>
track
Track
required
The track to bridge
sourceExtractor
BaseExtractor | null
required
The original extractor
targetExtractor
ExtractorResolvable
required
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
return
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
return
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
return
string
The extractor identifier
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

ExtractorExecutionResult

Result from extractor execution.
interface ExtractorExecutionResult<T = unknown> {
  extractor: BaseExtractor;
  error: Error | null;
  result: T;
}

ExtractorExecutionFN

Function executed for each extractor.
type ExtractorExecutionFN<T = unknown> = (
  extractor: BaseExtractor
) => Promise<T | boolean>;

ExtractorResolvable

Value that can be resolved to an extractor.
type ExtractorResolvable = string | BaseExtractor;

ExtractorSession

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');
}

Build docs developers (and LLMs) love