import type { BlipClient } from '../client.ts' import type { BlipLanguage } from '../types/account.ts' import type { Identity } from '../types/node.ts' import type { DetailedPlugin, Plugin, PluginBilling, PluginSubscription } from '../types/plugins.ts' import type { Application } from '../types/portal.ts' import { uri } from '../utils/uri.ts' import { type ConsumeOptions, Namespace, type SendCommandOptions } from './namespace.ts' export class PluginsNamespace extends Namespace { constructor(blipClient: BlipClient, defaultOptions?: SendCommandOptions) { super(blipClient, 'plugins', { ...defaultOptions, domain: 'blip.ai' }) } public getTenantApplicationsWithPlugin( tenantId: string, pluginId: string, opts?: ConsumeOptions, ): Promise> { return this.sendCommand( { method: 'get', uri: uri`/tenants/${tenantId}/plugins/${pluginId}/applications`, }, { ...opts, collection: true, // This route doesn't handle pagination correctly, it will always fetch all fetchall: false, }, ) } public getInstalledPlugins(tenantId: string, opts?: ConsumeOptions): Promise> { return this.sendCommand( { method: 'get', uri: uri`/tenants/${tenantId}/plugins?${{ charge: 'all', onlySubscribed: 'true' }}`, }, { collection: true, // This route doesn't handle pagination correctly, it will always fetch all fetchall: false, ...opts, }, ) } /** * @param tenantId - The tenant id to use when fetching the plugins, only works as blip.ai user and the user should be a member of the tenant */ public getPlugins(tenantId?: string, opts?: ConsumeOptions): Promise> { return this.sendCommand( { method: 'get', uri: tenantId ? uri`/tenants/${tenantId}/plugins?${{ charge: 'all' }}` : uri`/plugins?${{ charge: 'all' }}`, }, { collection: true, // This route doesn't handle pagination correctly, it will always fetch all fetchall: false, ...opts, }, ) } public getPlugin( pluginId: string, query?: { returnInstalledBots?: boolean; language?: BlipLanguage }, opts?: ConsumeOptions, ): Promise { return this.sendCommand( { method: 'get', uri: uri`/plugins/${pluginId}?${{ language: query?.language, returnInstalledBots: query?.returnInstalledBots }}`, }, opts, ) } public getPluginSubscription( tenantId: string, pluginId: string, opts?: ConsumeOptions, ): Promise { return this.sendCommand( { method: 'get', uri: uri`/tenants/${tenantId}/plugins/${pluginId}/subscription`, }, opts, ) } /** * @param settings.hasPartnerService - Whether the plugin has a partner service (default value: false) * @param settings.language - The language to send the communication emails (default value: pt) * @param settings.plan - If the plugin has multiple plans, the plan to subscribe to */ public subscribeToPlugin( tenantId: string, pluginId: string, settings: { plan: number hasPartnerService?: boolean language?: BlipLanguage }, opts?: ConsumeOptions, ): Promise { return this.sendCommand( { method: 'set', type: 'application/vnd.iris.plugins.subscribe+json', uri: uri`/tenants/${tenantId}/plugins/${pluginId}/subscribe`, resource: { hasPartnerService: settings.hasPartnerService ?? false, language: settings.language ?? 'pt', plan: settings.plan, pluginId, // That means that it will be charged to the tenant, not sure if exists other values chargeType: 3, }, }, opts, ) } public upgradePluginSubscription( tenantId: string, pluginId: string, settings: { plan: number language?: BlipLanguage }, opts?: ConsumeOptions, ): Promise { return this.sendCommand( { method: 'set', type: 'application/vnd.iris.plugins.subscribe+json', uri: uri`/tenants/${tenantId}/plugins/${pluginId}/upgrade`, resource: { pluginId, plan: settings.plan, language: settings.language ?? 'pt', }, }, opts, ) } public cancelPluginSubscription( tenantId: string, pluginId: string, settings?: { language?: BlipLanguage }, opts?: ConsumeOptions, ): Promise { return this.sendCommand( { method: 'delete', uri: uri`/tenants/${tenantId}/plugins/${pluginId}/cancel?${{ language: settings?.language ?? 'pt' }}`, }, opts, ) } /** * @param settings.language - The language to send the communication emails (default value: pt) * @param settings.applicationIdentity - The application identity to install the plugin */ public installPlugin( tenantId: string, pluginId: string, settings: { applicationIdentity: Identity language?: BlipLanguage }, opts?: ConsumeOptions, ): Promise { return this.sendCommand( { method: 'set', type: 'application/vnd.iris.plugins.install+json', uri: uri`/tenants/${tenantId}/plugins/${pluginId}/install`, resource: { applicationIdentity: settings.applicationIdentity, language: settings.language ?? 'pt', }, }, opts, ) } /** * @param settings.language - The language to send the communication emails (default value: pt) * @param settings.applicationIdentity - The application identity to uninstall the plugin */ public uninstallPlugin( tenantId: string, pluginId: string, settings: { applicationIdentity: Identity language?: BlipLanguage }, opts?: ConsumeOptions, ): Promise { return this.sendCommand( { method: 'set', type: 'application/vnd.iris.plugins.install+json', uri: uri`/tenants/${tenantId}/plugins/${pluginId}/uninstall`, resource: { applicationIdentity: settings.applicationIdentity, language: settings.language ?? 'pt', }, }, opts, ) } /** This route can only be called by an admin user of blip.ai */ public deletePluginMedia(mediaId: string, opts?: ConsumeOptions) { return this.sendCommand( { method: 'delete', uri: uri`/images/${mediaId}`, }, opts, ) } /** This route can only be called by an admin user of blip.ai */ public addPluginMedia(pluginId: string, type: 'image' | 'video', url: string, opts?: ConsumeOptions) { return this.sendCommand( { method: 'set', type: 'application/vnd.iris.plugins.image-create+json', uri: uri`/images`, resource: { uri: url, pluginId, imageType: type === 'image' ? 3 : 1, }, }, opts, ) } /** This route can only be called by an admin user of blip.ai */ public addPlugin( plugin: { documentation: DetailedPlugin['documentation'] url: string icon: DetailedPlugin['icon'] price?: DetailedPlugin['price'] authorId: number media: Array<{ uri: string; type: 'image' | 'video' }> tags: Array languages: { pt: { name: string overview: string description: string } en: { name: string overview: string description: string } es: { name: string overview: string description: string } } prices?: Array< Omit & { featuresIncluded: Array<{ icon: string description: string }> } > }, opts?: ConsumeOptions, ) { const price = plugin.prices?.[0]?.price ?? plugin.price return this.sendCommand( { method: 'set', type: 'application/vnd.lime.collection+json', uri: uri`/plugins`, resource: { itemType: 'application/vnd.iris.plugin.resource+json', items: [ { name: plugin.languages.pt.name, website: plugin.documentation, url: plugin.url, overview: plugin.languages.pt.overview, description: plugin.languages.pt.description, version: '1.0.0', icon: plugin.icon, isPaid: price !== undefined && price > 0, price, authorId: plugin.authorId, installationType: 0, configurationLink: '/application/detail/{botId}/plugin/{pluginId}', pluginType: 'Frontend', images: plugin.media.map((m) => ({ language: 'pt', uri: m.uri, imageType: m.type === 'image' ? 3 : 1, })), chargeType: plugin.prices && plugin.prices.length > 1 ? 3 : 1, tags: plugin.tags.map((t) => ({ tagValue: t })), languages: [ { language: 0, }, { language: 1, }, { language: 2, }, ], translations: [ { name: plugin.languages.en.name, overview: plugin.languages.en.overview, description: plugin.languages.en.description, language: 'en', }, { name: plugin.languages.es.name, overview: plugin.languages.es.overview, description: plugin.languages.es.description, language: 'es', }, ], billings: plugin.prices?.map((p) => ({ name: p.name, description: p.description, price: p.price, // TODO: I don't know exactly what it means yet language: 'pt', // TODO: This one too currency: 1, chargeType: 1, isRecommended: p.isRecommended, featuresIncluded: JSON.stringify(p.featuresIncluded), additionalDescription: p.additionalDescription, isActive: true, })), }, ], }, }, opts, ) } /** This route can only be called by an admin user of blip.ai */ public updatePlugin( pluginId: string, plugin: Partial< Pick & { url: string isPublished: boolean } >, opts?: ConsumeOptions, ): Promise { return this.sendCommand( { method: 'set', type: 'application/vnd.iris.plugin.resource+json', uri: uri`/plugins/${pluginId}`, resource: { name: plugin.name, overview: plugin.overview, description: plugin.description, icon: plugin.icon, website: plugin.documentation, url: plugin.url, price: plugin.price, isPaid: plugin.price !== undefined && plugin.price > 0, isPublished: plugin.isPublished, }, }, opts, ) } public setPluginBilling( pluginId: string, billingId: string, billing: Omit & { featuresIncluded: Array<{ icon: string description: string }> }, opts?: ConsumeOptions, ) { return this.sendCommand( { method: 'set', type: 'application/vnd.iris.plugins.billing-update+json', uri: uri`/billings/${billingId}`, resource: { blipPluginId: pluginId, name: billing.name, description: billing.description, featuresIncluded: billing.featuresIncluded ? JSON.stringify(billing.featuresIncluded) : undefined, isRecommended: billing.isRecommended, price: billing.price, additionalDescription: billing.additionalDescription, // TODO: add params to this language: 'pt', // TODO: This one too currency: 1, chargeType: 3, isActive: true, }, }, opts, ) } }