2020-11-21 15:41:08 +00:00
|
|
|
import * as fs from 'fs-extra';
|
|
|
|
import * as path from 'path';
|
|
|
|
|
|
|
|
import { IEnvironment } from '../types/environment';
|
|
|
|
import { IPluginManifest } from './plugin';
|
|
|
|
|
2020-11-28 13:34:34 +00:00
|
|
|
import { logger } from '../core';
|
|
|
|
|
2020-11-21 15:41:08 +00:00
|
|
|
export class PluginMetaLoader {
|
|
|
|
constructor(private env: IEnvironment) {}
|
|
|
|
|
|
|
|
public async load(name: string): Promise<IPluginManifest> {
|
|
|
|
if (name === 'squeebot') {
|
|
|
|
throw new Error('Illegal name.');
|
|
|
|
}
|
|
|
|
|
|
|
|
const fullpath = path.join(this.env.pluginsPath, name);
|
|
|
|
const metapath = path.join(fullpath, 'plugin.json');
|
|
|
|
if (!await fs.pathExists(metapath)) {
|
|
|
|
throw new Error('Not a plugin directory.');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the metadata
|
|
|
|
const json = await fs.readJson(metapath);
|
|
|
|
|
|
|
|
// Mandatory fields
|
|
|
|
if (!json.name) {
|
|
|
|
throw new Error('Plugin metadata does not specify a name, for some reason');
|
|
|
|
}
|
|
|
|
|
2020-11-29 11:35:45 +00:00
|
|
|
if (json.name === 'squeebot' || !(/^[a-zA-Z0-9_\-]+$/.test(json.name))) {
|
2020-11-21 15:41:08 +00:00
|
|
|
throw new Error('Illegal name.');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!json.version) {
|
|
|
|
throw new Error('Plugin metadata does not specify a version, for some reason');
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ensure main file exists
|
|
|
|
if (!json.main) {
|
|
|
|
json.main = 'plugin.js';
|
|
|
|
}
|
|
|
|
|
|
|
|
const mainfile = path.resolve(fullpath, json.main);
|
|
|
|
if (!await fs.pathExists(mainfile)) {
|
|
|
|
throw new Error('Plugin does not have a main file or it is misconfigured.');
|
|
|
|
}
|
|
|
|
|
|
|
|
json.fullPath = fullpath;
|
|
|
|
json.main = mainfile;
|
|
|
|
|
|
|
|
if (!json.dependencies) {
|
|
|
|
json.dependencies = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!json.npmDependencies) {
|
|
|
|
json.npmDependencies = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
return json;
|
|
|
|
}
|
|
|
|
|
2020-11-28 13:34:34 +00:00
|
|
|
public async loadAll(ignoreErrors = false): Promise<IPluginManifest[]> {
|
2020-11-21 15:41:08 +00:00
|
|
|
const dirlist = await fs.readdir(this.env.pluginsPath);
|
|
|
|
const plugins: IPluginManifest[] = [];
|
|
|
|
for (const file of dirlist) {
|
2020-11-28 13:34:34 +00:00
|
|
|
// Ignore hidden files and non-directories
|
|
|
|
const fpath = path.join(this.env.pluginsPath, file);
|
|
|
|
if (file.indexOf('.') === 0 ||
|
|
|
|
file === 'node_modules' ||
|
|
|
|
!(await fs.lstat(fpath)).isDirectory()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-11-21 15:41:08 +00:00
|
|
|
try {
|
2020-11-28 13:34:34 +00:00
|
|
|
const plugin = await this.load(file);
|
2020-11-21 15:41:08 +00:00
|
|
|
plugins.push(plugin);
|
|
|
|
} catch (e) {
|
2020-11-28 13:34:34 +00:00
|
|
|
if (ignoreErrors) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
logger.error(e);
|
2020-11-21 15:41:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return plugins;
|
|
|
|
}
|
|
|
|
}
|