From 8e93fa7a50a4fb83c98f99d622459abdb4ebc267 Mon Sep 17 00:00:00 2001 From: Patrick Stankard Date: Tue, 25 Jun 2024 12:45:34 -0400 Subject: [PATCH] Add getPluginAuthorFromMaintainers method --- src/modules/plugins/plugins.service.ts | 56 +++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/src/modules/plugins/plugins.service.ts b/src/modules/plugins/plugins.service.ts index cd284de50..b4a46b782 100755 --- a/src/modules/plugins/plugins.service.ts +++ b/src/modules/plugins/plugins.service.ts @@ -100,6 +100,9 @@ export class PluginsService { // create a cache for storing plugin alias private pluginAliasCache = new NodeCache({ stdTTL: 86400 }); + // create a cache for storing plugin author + private pluginAuthorCache = new NodeCache({ stdTTL: 86400 }); + private specialPluginsRetryTimeout: NodeJS.Timeout; /** @@ -366,7 +369,7 @@ export class PluginsService { homepage: pkg.homepage, bugs: typeof pkg.bugs === 'object' && pkg.bugs?.url ? pkg.bugs.url : null, }; - plugin.author = (pkg.maintainers && pkg.maintainers.length) ? pkg.maintainers[0].name : null; + plugin.author = await this.getPluginAuthorFromMaintainers(plugin); plugin.verifiedPlugin = this.verifiedPlugins.includes(pkg.name); plugin.verifiedPlusPlugin = this.verifiedPlusPlugins.includes(pkg.name); plugin.icon = this.pluginIcons[pkg.name] @@ -382,6 +385,55 @@ export class PluginsService { } } + /** + * @param plugin + */ + private async getPluginAuthorFromMaintainers(plugin: HomebridgePlugin): Promise { + // first, attempt to get it from the cache + let author: string = this.pluginAuthorCache.get(plugin.name); + if (author) { + return author; + } + + // if it's not in cache, attempt to get it from the latest release + const pkgFromCache = this.npmPluginCache.get(plugin.name); + + const pkg: IPackageJson = pkgFromCache || ( + await this.httpService.get(`https://registry.npmjs.org/${encodeURIComponent(plugin.name).replace(/%40/g, '@')}/latest`).toPromise() + ).data; + + if (!pkgFromCache) { + this.npmPluginCache.set(plugin.name, pkg); + } + + author = (pkg.maintainers && pkg.maintainers.length) ? pkg.maintainers[0].name : null; + + if (author) { + this.pluginAuthorCache.set(plugin.name, author); + + return author; + } + + // if it's not available on the latest release, attempt get it from the top-level metadata + const lookupFromCache = this.npmPluginCache.get(`lookup-${plugin.name}`); + + const lookup: INpmRegistryModule = lookupFromCache || (await ( + this.httpService.get(`https://registry.npmjs.org/${encodeURIComponent(plugin.name).replace(/%40/g, '@')}`).toPromise() + )).data; + + if (!lookupFromCache) { + this.npmPluginCache.set(`lookup-${plugin.name}`, lookup, 60); + } + + author = (lookup.maintainers && lookup.maintainers.length) ? lookup.maintainers[0].name : null; + + if (author) { + this.pluginAuthorCache.set(plugin.name, author); + } + + return author; + } + /** * Manage a plugin, install, update or uninstall it * @param action @@ -1322,7 +1374,7 @@ export class PluginsService { homepage: pkg.homepage, bugs: typeof pkg.bugs === 'object' && pkg.bugs?.url ? pkg.bugs.url : null, }; - plugin.author = (pkg.maintainers && pkg.maintainers.length) ? pkg.maintainers[0].name : null; + plugin.author = await this.getPluginAuthorFromMaintainers(plugin); plugin.engines = pkg.engines; } catch (e) { if (e.response?.status !== 404) {