n8n-nodes-kodi
Version:
A powerful n8n community node for controlling Kodi media center through JSON-RPC API with intelligent method discovery and comprehensive media management capabilities
295 lines • 12.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Kodi = void 0;
const n8n_workflow_1 = require("n8n-workflow");
const KodiService_1 = require("./KodiService");
class Kodi {
constructor() {
this.description = {
displayName: 'Kodi',
name: 'kodi',
group: ['transform'],
version: 3,
subtitle: '={{$parameter["operation"]}}',
description: 'Control Kodi with dynamic method discovery',
icon: 'file:Kodi.svg',
inputs: ["main"],
outputs: ["main"],
defaults: {
name: 'Kodi',
},
credentials: [
{
name: 'kodiApi',
required: true,
},
],
properties: [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
options: [
{
name: 'Execute Method',
value: 'execute',
description: 'Execute a Kodi JSON-RPC method',
action: 'Execute a kodi method',
},
{
name: 'Raw JSON-RPC',
value: 'raw',
description: 'Execute raw JSON-RPC command',
action: 'Execute raw JSON-RPC',
},
{
name: 'Discover Methods',
value: 'discover',
description: 'Discover available methods from Kodi',
action: 'Discover available methods',
},
],
default: 'execute',
noDataExpression: true,
},
{
displayName: 'Method Category Name or ID',
name: 'methodCategory',
type: 'options',
displayOptions: {
show: {
operation: ['execute'],
},
},
typeOptions: {
loadOptionsMethod: 'getMethodCategories',
},
default: '',
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
noDataExpression: true,
},
{
displayName: 'Method Name or ID',
name: 'method',
type: 'options',
displayOptions: {
show: {
operation: ['execute'],
},
},
typeOptions: {
loadOptionsMethod: 'getMethods',
loadOptionsDependsOn: ['methodCategory'],
},
default: '',
description: 'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
noDataExpression: true,
},
{
displayName: 'Raw JSON-RPC',
name: 'rawPayload',
type: 'string',
displayOptions: {
show: {
operation: ['raw'],
},
},
default: '{ "jsonrpc": "2.0", "method": "VideoLibrary.Scan", "id": "n8n" }',
description: 'Raw JSON-RPC payload to send to Kodi',
noDataExpression: false,
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Option',
default: {},
options: [
{
displayName: 'Force Method Discovery',
name: 'forceDiscovery',
type: 'boolean',
default: false,
description: 'Whether to force rediscovery of available methods',
},
{
displayName: 'Include Method Info',
name: 'includeMethodInfo',
type: 'boolean',
default: false,
description: 'Whether to include method information in the output',
},
],
},
],
};
this.methods = {
loadOptions: {
async getMethodCategories() {
const credentials = await this.getCredentials('kodiApi');
if (!credentials) {
return [];
}
try {
const kodiService = new KodiService_1.KodiService(credentials);
await kodiService.discoverMethods();
const categories = kodiService.getMethodsByCategory();
const options = [
{
name: 'All',
value: 'All',
description: 'Show all available methods',
},
...Object.keys(categories).map(category => ({
name: category,
value: category,
description: `${categories[category].length} methods available`,
}))
];
return options;
}
catch (error) {
return [
{
name: 'All',
value: 'All',
description: 'Show all available methods',
}
];
}
},
async getMethods() {
const credentials = await this.getCredentials('kodiApi');
const methodCategory = this.getCurrentNodeParameter('methodCategory');
if (!credentials) {
return [];
}
try {
const kodiService = new KodiService_1.KodiService(credentials);
await kodiService.discoverMethods();
const categories = kodiService.getMethodsByCategory();
let methods = [];
if (methodCategory === 'All') {
methods = Object.values(categories).flat();
}
else if (methodCategory && categories[methodCategory]) {
methods = categories[methodCategory];
}
return methods.map(method => ({
name: method.name,
value: method.name,
description: method.description || '',
}));
}
catch (error) {
return [];
}
},
},
};
}
async execute() {
const operation = this.getNodeParameter('operation', 0);
const returnData = [];
try {
const credentials = await this.getCredentials('kodiApi');
const kodiService = new KodiService_1.KodiService(credentials);
const options = this.getNodeParameter('options', 0, {});
if (options.forceDiscovery) {
await kodiService.discoverMethods();
}
let result;
if (operation === 'execute') {
const method = this.getNodeParameter('method', 0);
result = await kodiService.executeMethod(method);
if (options.includeMethodInfo) {
const methods = await kodiService.discoverMethods();
const methodInfo = methods.find(m => m.name === method);
if (methodInfo) {
result = {
method: methodInfo,
result: result,
};
}
}
}
else if (operation === 'raw') {
const rawPayload = this.getNodeParameter('rawPayload', 0);
let payload;
try {
payload = JSON.parse(rawPayload);
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid JSON in raw payload');
}
if (!payload.jsonrpc || !payload.method || !payload.id) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid JSON-RPC format. Must include jsonrpc, method, and id fields.');
}
result = await kodiService.makeRequest(payload);
if (result.error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Kodi error: ${result.error.message} (code: ${result.error.code})`);
}
result = result.result;
}
else if (operation === 'discover') {
const methods = await kodiService.discoverMethods();
const categories = kodiService.getMethodsByCategory();
result = {
totalMethods: methods.length,
categories: Object.keys(categories).map(category => ({
name: category,
methodCount: categories[category].length,
methods: categories[category],
})),
allMethods: methods,
};
}
if (result && typeof result === 'object') {
if (Array.isArray(result)) {
for (const item of result) {
returnData.push({ json: item });
}
}
else {
if (result.movies) {
for (const movie of result.movies) {
returnData.push({ json: movie });
}
}
else if (result.tvshows) {
for (const show of result.tvshows) {
returnData.push({ json: show });
}
}
else if (result.albums) {
for (const album of result.albums) {
returnData.push({ json: album });
}
}
else if (result.artists) {
for (const artist of result.artists) {
returnData.push({ json: artist });
}
}
else if (result.songs) {
for (const song of result.songs) {
returnData.push({ json: song });
}
}
else {
returnData.push({ json: result });
}
}
}
else {
returnData.push({ json: { result } });
}
return [returnData];
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message);
}
}
}
exports.Kodi = Kodi;
//# sourceMappingURL=Kodi.node.js.map