4.6 KiB
nodecast-tv Plugin System
This directory allows you to extend the functionality of nodecast-tv without modifying the core source code. The server automatically detects and loads any .js file placed in this folder at startup.
How It Works
The plugin loader in server/index.js scans this directory at startup and loads plugins in alphabetical order (sorted by filename). Each plugin file should export either:
- A function (sync or async) that will be called during initialization
- An object with
init()and optionallyshutdown()methods for lifecycle management
When the server starts, it calls your plugin's initialization code and passes:
app- The Express application instanceservices- A frozen (read-only) object containing all internal services
Plugin Patterns
Pattern 1: Simple Function Export
The simplest plugin pattern - just export a function:
/**
* @param {Object} app - The Express application instance
* @param {Object} services - Frozen object containing all internal services
*/
module.exports = function(app, services) {
// Register routes, middleware, etc.
app.get('/api/my-route', (req, res) => {
res.json({ message: 'Hello from plugin!' });
});
};
Pattern 2: Async Function Export
For plugins that need to perform async initialization (database connections, API calls, etc.):
module.exports = async function(app, services) {
// Async initialization
await someAsyncSetup();
// Access services
if (services.syncService) {
console.log('Sync service available');
}
// Register routes
app.get('/api/my-route', (req, res) => {
res.json({ status: 'ready' });
});
};
Pattern 3: Lifecycle Hooks (Advanced)
For plugins that need cleanup on shutdown:
module.exports = {
/**
* Called during server startup
*/
init: async (app, services) => {
// Setup code
this.interval = setInterval(() => {
console.log('Background task running...');
}, 60000);
app.get('/api/status', (req, res) => {
res.json({ uptime: process.uptime() });
});
},
/**
* Called on SIGTERM (graceful shutdown)
*/
shutdown: async () => {
// Cleanup code
if (this.interval) {
clearInterval(this.interval);
}
console.log('Plugin cleaned up');
}
};
Security & Permissions
Warning
Plugins run with full Node.js permissions and have access to the Express app and all services. Only install plugins from trusted sources.
Important notes:
- The
servicesobject is frozen - you cannot modify or delete services - Plugins can still mutate properties of service objects (e.g.,
services.cache.set()) - Plugins can register routes, middleware, and access the file system
- This is appropriate for self-hosted applications where you control what plugins are installed
Available Services
The services object contains all modules from server/services/:
| Service | Description |
|---|---|
cache |
Caching utilities |
epgParser |
EPG/XMLTV parsing |
hwDetect |
Hardware acceleration detection |
m3uParser |
M3U playlist parsing |
m3uXtreamAdapter |
Xtream API adapter |
syncService |
Channel/EPG synchronization |
transcodeSession |
Transcoding session management |
xtreamApi |
Xtream API client |
Example:
module.exports = async function(app, services) {
// Use the EPG parser service
const epgData = await services.epgParser.fetchAndParse('http://example.com/epg.xml');
console.log(`Loaded ${epgData.programmes.length} programmes`);
};
Load Order
Plugins are loaded in alphabetical order by filename. If you need specific ordering:
plugins/
01-database.js # Loads first
02-api-client.js # Loads second
99-cleanup.js # Loads last
Testing Your Plugin
- Place your
.jsfile inserver/plugins/ - Restart the NodeCast TV server
- Check the console for plugin loading messages:
✓ Loaded plugin: your-plugin.js- Success⚠ Plugin your-plugin.js does not export...- Wrong export format✗ Failed to load plugin your-plugin.js- Error during initialization
Example Use Cases
- Custom scrapers - Add support for new streaming sources
- Notification systems - Send alerts when new content is available
- Analytics - Track viewing patterns
- Custom APIs - Expose additional endpoints for integrations
- Middleware - Add authentication, logging, or rate limiting