diff --git a/src/backend/exports.js b/src/backend/exports.js index efa896ca..03102440 100644 --- a/src/backend/exports.js +++ b/src/backend/exports.js @@ -38,6 +38,7 @@ const { HostOSModule } = require("./src/modules/hostos/HostOSModule.js"); const { InternetModule } = require("./src/modules/internet/InternetModule.js"); const { PuterExecModule } = require("./src/modules/puterexec/PuterExecModule.js"); const { MailModule } = require("./src/modules/mail/MailModule.js"); +const { ConvertModule } = require("./src/modules/convert/ConvertModule.js"); module.exports = { helloworld: () => { @@ -74,6 +75,7 @@ module.exports = { BroadcastModule, InternetModule, MailModule, + ConvertModule, // Development modules PerfMonModule, diff --git a/src/backend/package.json b/src/backend/package.json index c2195176..8142dcbf 100644 --- a/src/backend/package.json +++ b/src/backend/package.json @@ -31,6 +31,7 @@ "clean-css": "^5.3.2", "composite-error": "^1.0.2", "compression": "^1.7.4", + "convertapi": "^1.15.0", "cookie-parser": "^1.4.6", "dedent": "^1.5.3", "express": "^4.18.2", diff --git a/src/backend/src/modules/convert/ConvertAPIService.js b/src/backend/src/modules/convert/ConvertAPIService.js new file mode 100644 index 00000000..07a071f9 --- /dev/null +++ b/src/backend/src/modules/convert/ConvertAPIService.js @@ -0,0 +1,90 @@ +const { LLRead } = require("../../filesystem/ll_operations/ll_read"); +const BaseService = require("../../services/BaseService"); +const { TypedValue } = require("../../services/drivers/meta/Runtime"); +const { Context } = require("../../util/context"); + +const mime = require('mime-types'); + +class ConvertAPIService extends BaseService { + async ['__on_driver.register.interfaces'] () { + const svc_registry = this.services.get('registry'); + const col_interfaces = svc_registry.get('interfaces'); + + col_interfaces.set('convert-files', { + description: 'Convert between various data formats.', + methods: { + convert: { + description: 'Convert data from one format to another.', + parameters: { + from: { + type: 'string', + description: 'Source data format.', + }, + to: { + type: 'string', + description: 'Destination data format.', + required: true, + }, + source: { + type: 'file', + }, + }, + result_choices: [ + { + type: { + $: 'stream', + } + }, + ] + }, + } + }); + } + + static MODULES = { + axios: require('axios'), + convertapi: require('convertapi'), + } + + async _init () { + this.convertapi = this.require('convertapi')(this.config.token); + } + + static IMPLEMENTS = { + ['convert-files']: { + async convert ({ from, to, source }) { + const convertapi = this.convertapi; + const axios = this.require('axios'); + + const fsNode = await source.get('fs-node'); + const ll_read = new LLRead(); + const stream = await ll_read.run({ + actor: Context.get('actor'), + fsNode, + }); + + const name = await fsNode.get('name'); + + const uploadResult = + await convertapi.upload(stream, name); + + const convertResult = + await convertapi.convert(to, { File: uploadResult }, + ...( from ? [ from ] : [] )); + + const fileInfo = convertResult?.response?.Files?.[0]; + + const downloadResponse = await axios.get(fileInfo.Url, { + responseType: 'stream', + }); + + return new TypedValue({ + $: 'stream', + content_type: mime.contentType(fileInfo.FileName), + }, downloadResponse.data); + } + } + }; +} + +module.exports = ConvertAPIService; diff --git a/src/backend/src/modules/convert/ConvertModule.js b/src/backend/src/modules/convert/ConvertModule.js new file mode 100644 index 00000000..19c9618d --- /dev/null +++ b/src/backend/src/modules/convert/ConvertModule.js @@ -0,0 +1,12 @@ +const { AdvancedBase } = require("@heyputer/putility"); + +class ConvertModule extends AdvancedBase { + async install (context) { + const services = context.get('services'); + + const ConvertAPIService = require('./ConvertAPIService'); + services.registerService('convert-api', ConvertAPIService); + } +} + +module.exports = { ConvertModule };