kodi-api
Version:
A complete implementation of Kodi JSON-RPC calls in an easy-to-use Javascript/TypeScript client.
118 lines (117 loc) • 5.03 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.KodiClient = void 0;
const promise_1 = require("jayson/promise");
const uuid_1 = require("uuid");
const KodiIntrospect_1 = require("./KodiIntrospect");
const KodiMethodNamespace_1 = require("./KodiMethodNamespace");
const WebSocketClient_1 = require("./WebSocketClient");
const numeric = /^\d+$/gu;
/** Class for dynamically calling the Kodi JSON-RPC api, regardless of api version. */
class KodiClient {
constructor(options) {
this.throwValidationError = typeof options.throwValidationError === 'undefined' ? false : options.throwValidationError;
this.clientType = options.clientType;
// Initialize as undefined so that key can be looked up, like `key in this`.
this.introspectionCache = undefined;
switch (options.clientType) {
case 'http':
this.jsonRpcClient = promise_1.Client.http({
port: 8080,
...options.clientOptions
});
break;
case 'https':
this.jsonRpcClient = promise_1.Client.https({
...options.clientOptions
});
break;
case 'ws':
this.jsonRpcClient = new WebSocketClient_1.WebSocketClient({
...options.clientOptions
});
break;
case 'tcp':
default:
this.jsonRpcClient = promise_1.Client.tcp({
...{ port: 9090 },
...options.clientOptions
});
break;
}
return new Proxy(this, KodiProxyHandler);
}
/** Method to manually connect to the defined web socket; silently returns for any other client type. */
async connect() {
if (this.jsonRpcClient instanceof WebSocketClient_1.WebSocketClient) {
await this.jsonRpcClient.connect();
}
}
/** Method to manually disconnect from the defined web socket; silently returns for any other client type. */
async disconnect() {
if (this.jsonRpcClient instanceof WebSocketClient_1.WebSocketClient) {
await this.jsonRpcClient.disconnect();
}
}
/** Method to get and cache the introspection result on this instance. */
async getIntrospectionCache(refresh = false) {
if (typeof this.introspectionCache === 'undefined' || refresh) {
const result = await this.jsonRpcClient.request('JSONRPC.Introspect', null, uuid_1.v4());
this.introspectionCache = new KodiIntrospect_1.KodiIntrospect(result);
}
return this.introspectionCache;
}
async listMethods(group = false) {
await this.getIntrospectionCache();
return this.introspectionCache.listMethods(group);
}
/** Construct an HTTP instance with Kodi defaults. */
static http() {
return new KodiClient({ clientType: 'http' });
}
/** Construct an HTTPS instance with Kodi defaults. __NOTE:__ _Kodi does not natively or officially support HTTPS; some users have unofficially found a way, though._ */
static https() {
return new KodiClient({ clientType: 'https' });
}
/** Construct a TCP instance with Kodi defaults. */
static tcp() {
return new KodiClient({ clientType: 'tcp' });
}
/** Construct a WebSocket instance with Kodi defaults. */
static ws() {
return new KodiClient({ clientType: 'ws' });
}
}
exports.KodiClient = KodiClient;
/** @hidden */
const KodiProxyHandler = {
get(target, nameSpace, r) {
// Short-circuit if namespace already exists on target.
if (nameSpace in target)
return target[nameSpace];
if (typeof nameSpace !== 'string' || (/^\d+$/gu).test(nameSpace))
return void 0;
const listMethods = async function listMethods() {
await target.getIntrospectionCache();
const groups = await target.listMethods(true);
return groups[nameSpace];
};
return new Proxy({
ListMethods: listMethods,
listMethods
}, {
get(subTarget, methodName, r) {
if (methodName in subTarget)
return subTarget[methodName];
if (typeof methodName !== 'string' || numeric.test(methodName))
return void 0;
// Construct a namespace object as a caching mechanism.
const newNameSpace = new KodiMethodNamespace_1.KodiMethodNamespace(nameSpace, methodName, target);
// Store the namespace on the original `this`.
target[nameSpace] = newNameSpace;
// Return the requested method from the namespace.
return newNameSpace[methodName];
}
});
}
};