Explorar o código

Add AGI module documentation

Toby Chui hai 3 días
pai
achega
96c48df08e
Modificáronse 1 ficheiros con 822 adicións e 0 borrados
  1. 822 0
      src/mod/agi/README.md

+ 822 - 0
src/mod/agi/README.md

@@ -0,0 +1,822 @@
+# ArOZ Online JavaScript Gateway Interface (AGI)
+
+The ArOZ Online JavaScript Gateway Interface (AGI) allows developers to create server-side scripts using JavaScript that can interact with the ArOZ Online system. AGI scripts run in a sandboxed Otto JavaScript VM environment, providing access to system functions while maintaining security.
+
+## Getting Started
+
+### Basic AGI Script Structure
+
+```javascript
+// Send a simple response
+sendResp("Hello, World!");
+
+// Send JSON response
+sendJSONResp({message: "Hello", status: "success"});
+
+// Send OK response
+sendOK();
+```
+
+### Loading Libraries
+
+```javascript
+// Load required libraries
+if (requirelib("filelib") == true) {
+    // File operations are now available
+    var content = filelib.readFile("user:/example.txt");
+}
+```
+
+## Global Variables
+
+- `BUILD_VERSION`: Current system build version
+- `INTERNAL_VERSION`: Internal version number
+- `LOADED_MODULES`: Array of loaded system modules
+- `LOADED_STORAGES`: Array of available storage pools
+- `__FILE__`: Current script file path
+- `HTTP_RESP`: Response content (automatically set)
+- `HTTP_HEADER`: Response content type (automatically set)
+- `USERNAME`: Current user's username
+- `USERICON`: Current user's icon path
+- `USERQUOTA_TOTAL`: User's total storage quota
+- `USERQUOTA_USED`: User's used storage quota
+- `USER_VROOTS`: User's accessible virtual root paths
+- `USER_MODULES`: User's accessible modules
+
+## Core Functions
+
+### Response Functions
+
+#### `sendResp(content)`
+Sends a response to the client.
+
+```javascript
+sendResp("Operation completed successfully");
+```
+
+#### `echo(content)`
+Appends content to the response.
+
+```javascript
+echo("Hello ");
+echo("World!"); // Response: "Hello World!"
+```
+
+#### `sendOK()`
+Sends a simple "ok" response.
+
+```javascript
+sendOK(); // Response: "ok"
+```
+
+#### `sendJSONResp(object)`
+Sends a JSON response.
+
+```javascript
+sendJSONResp({
+    status: "success",
+    data: [1, 2, 3]
+});
+```
+
+### Database Functions
+
+#### `newDBTableIfNotExists(tableName)`
+Creates a new database table if it doesn't exist.
+
+```javascript
+if (newDBTableIfNotExists("myapp_settings")) {
+    echo("Table created successfully");
+}
+```
+
+#### `DBTableExists(tableName)`
+Checks if a database table exists.
+
+```javascript
+if (DBTableExists("user_preferences")) {
+    echo("Table exists");
+}
+```
+
+#### `writeDBItem(tableName, key, value)`
+Writes a key-value pair to a database table.
+
+```javascript
+writeDBItem("settings", "theme", "dark");
+```
+
+#### `readDBItem(tableName, key)`
+Reads a value from a database table.
+
+```javascript
+var theme = readDBItem("settings", "theme");
+if (theme) {
+    echo("Current theme: " + theme);
+}
+```
+
+#### `listDBTable(tableName)`
+Lists all key-value pairs in a table.
+
+```javascript
+var settings = listDBTable("settings");
+echo(JSON.stringify(settings));
+```
+
+#### `deleteDBItem(tableName, key)`
+Deletes a key-value pair from a table.
+
+```javascript
+deleteDBItem("settings", "old_key");
+```
+
+#### `dropDBTable(tableName)`
+Drops an entire database table.
+
+```javascript
+dropDBTable("temporary_data");
+```
+
+### Module Management
+
+#### `registerModule(jsonConfig)`
+Registers a module with the system.
+
+```javascript
+var moduleConfig = {
+    Name: "MyApp",
+    Desc: "My custom application",
+    Group: "Utilities",
+    IconPath: "MyApp/icon.png",
+    Version: "1.0",
+    StartDir: "MyApp/index.html",
+    SupportFW: true,
+    LaunchFWDir: "MyApp/index.html",
+    SupportEmb: true,
+    LaunchEmb: "MyApp/embedded.html",
+    InitFWSize: [800, 600],
+    InitEmbSize: [400, 300],
+    SupportedExt: [".txt", ".md"]
+};
+
+registerModule(JSON.stringify(moduleConfig));
+```
+
+#### `addNightlyTask(scriptPath)`
+Adds a script to run nightly.
+
+```javascript
+addNightlyTask("MyApp/tasks/backup.js");
+```
+
+## User Management Functions
+
+### Permission Functions
+
+#### `pathCanWrite(virtualPath)`
+Checks if the current user can write to a path.
+
+```javascript
+if (pathCanWrite("user:/documents/")) {
+    echo("Can write to documents folder");
+}
+```
+
+#### `getUserPermissionGroup()`
+Gets the current user's permission group information.
+
+```javascript
+var groupInfo = JSON.parse(getUserPermissionGroup());
+echo("User group: " + groupInfo.name);
+```
+
+#### `userIsAdmin()`
+Checks if the current user is an administrator.
+
+```javascript
+if (userIsAdmin()) {
+    echo("User is admin");
+}
+```
+
+### User Account Functions
+
+#### `userExists(username)`
+Checks if a user exists (admin only).
+
+```javascript
+if (userExists("john_doe")) {
+    echo("User exists");
+}
+```
+
+#### `createUser(username, password, defaultGroup)`
+Creates a new user account (admin only).
+
+```javascript
+if (createUser("newuser", "password123", "users")) {
+    echo("User created successfully");
+}
+```
+
+#### `removeUser(username)`
+Removes a user account (admin only).
+
+```javascript
+if (removeUser("olduser")) {
+    echo("User removed successfully");
+}
+```
+
+### Script Execution
+
+#### `execd(scriptPath, payload)`
+Executes another script asynchronously with optional payload.
+
+```javascript
+execd("MyApp/worker.js", "process_data");
+```
+
+## File Library (`filelib`)
+
+Load with: `requirelib("filelib")`
+
+### File Operations
+
+#### `filelib.writeFile(virtualPath, content)`
+Writes content to a file.
+
+```javascript
+filelib.writeFile("user:/notes.txt", "Hello, World!");
+```
+
+#### `filelib.readFile(virtualPath)`
+Reads content from a file.
+
+```javascript
+var content = filelib.readFile("user:/notes.txt");
+echo(content);
+```
+
+#### `filelib.deleteFile(virtualPath)`
+Deletes a file.
+
+```javascript
+filelib.deleteFile("user:/temp.txt");
+```
+
+### Directory Operations
+
+#### `filelib.mkdir(virtualPath)`
+Creates a directory.
+
+```javascript
+filelib.mkdir("user:/newfolder");
+```
+
+#### `filelib.readdir(virtualPath, sortMode)`
+Lists directory contents.
+
+```javascript
+var files = filelib.readdir("user:/documents", "name");
+// Returns array of file objects
+```
+
+### File Information
+
+#### `filelib.fileExists(virtualPath)`
+Checks if a file exists.
+
+```javascript
+if (filelib.fileExists("user:/config.json")) {
+    echo("Config file exists");
+}
+```
+
+#### `filelib.isDir(virtualPath)`
+Checks if path is a directory.
+
+```javascript
+if (filelib.isDir("user:/documents")) {
+    echo("Is a directory");
+}
+```
+
+#### `filelib.filesize(virtualPath)`
+Gets file size in bytes.
+
+```javascript
+var size = filelib.filesize("user:/largefile.zip");
+echo("File size: " + size + " bytes");
+```
+
+#### `filelib.mtime(virtualPath)`
+Gets file modification time.
+
+```javascript
+var mtime = filelib.mtime("user:/document.txt");
+echo("Modified: " + mtime);
+```
+
+#### `filelib.md5(virtualPath)`
+Calculates MD5 hash of a file.
+
+```javascript
+var hash = filelib.md5("user:/important.doc");
+echo("MD5: " + hash);
+```
+
+### File Searching
+
+#### `filelib.walk(virtualPath, mode)`
+Recursively walks a directory.
+
+```javascript
+// List all files recursively
+var allFiles = filelib.walk("user:/documents", "file");
+
+// List all directories recursively
+var allDirs = filelib.walk("user:/documents", "folder");
+
+// List everything
+var everything = filelib.walk("user:/documents", "all");
+```
+
+#### `filelib.glob(pattern)`
+Finds files matching a pattern.
+
+```javascript
+var txtFiles = filelib.glob("user:/documents/*.txt");
+```
+
+#### `filelib.aglob(pattern)`
+Finds files with advanced pattern matching.
+
+```javascript
+var jsFiles = filelib.aglob("user:/**/*.js");
+```
+
+## Image Library (`imagelib`)
+
+Load with: `requirelib("imagelib")`
+
+### Image Information
+
+#### `imagelib.getImageDimension(imagePath)`
+Gets image dimensions.
+
+```javascript
+var dimensions = imagelib.getImageDimension("user:/photo.jpg");
+// Returns: {width: 1920, height: 1080}
+```
+
+#### `imagelib.hasExif(imagePath)`
+Checks if image has EXIF data.
+
+```javascript
+if (imagelib.hasExif("user:/photo.jpg")) {
+    echo("Image has EXIF data");
+}
+```
+
+#### `imagelib.getExif(imagePath)`
+Extracts EXIF data from image.
+
+```javascript
+var exif = JSON.parse(imagelib.getExif("user:/photo.jpg"));
+echo("Camera: " + exif.Make);
+```
+
+### Image Processing
+
+#### `imagelib.resizeImage(inputPath, outputPath, width, height)`
+Resizes an image.
+
+```javascript
+imagelib.resizeImage("user:/photo.jpg", "user:/photo_small.jpg", 800, 600);
+```
+
+#### `imagelib.cropImage(inputPath, outputPath, x, y, width, height)`
+Crops an image.
+
+```javascript
+imagelib.cropImage("user:/photo.jpg", "user:/photo_crop.jpg", 100, 100, 500, 500);
+```
+
+#### `imagelib.loadThumbString(imagePath, size)`
+Generates a base64 thumbnail.
+
+```javascript
+var thumbnail = imagelib.loadThumbString("user:/photo.jpg", 200);
+echo("<img src='data:image/jpeg;base64," + thumbnail + "' />");
+```
+
+## HTTP Library (`http`)
+
+Load with: `requirelib("http")`
+
+### HTTP Requests
+
+#### `http.get(url)`
+Makes a GET request.
+
+```javascript
+var response = http.get("https://api.example.com/data");
+echo(response);
+```
+
+#### `http.post(url, jsonData)`
+Makes a POST request with JSON data.
+
+```javascript
+var data = JSON.stringify({name: "John", age: 30});
+var response = http.post("https://api.example.com/users", data);
+```
+
+#### `http.head(url)`
+Makes a HEAD request.
+
+```javascript
+var headers = http.head("https://example.com");
+```
+
+### Advanced HTTP Functions
+
+#### `http.download(url, savePath)`
+Downloads a file from URL.
+
+```javascript
+http.download("https://example.com/file.zip", "user:/downloads/file.zip");
+```
+
+#### `http.getb64(url)`
+Gets response as base64.
+
+```javascript
+var b64data = http.getb64("https://example.com/image.png");
+```
+
+#### `http.getCode(url)`
+Gets HTTP status code.
+
+```javascript
+var statusCode = http.getCode("https://example.com");
+if (statusCode == 200) {
+    echo("Site is up");
+}
+```
+
+#### `http.redirect(url, statusCode)`
+Redirects the client to another URL.
+
+```javascript
+http.redirect("https://example.com/newpage", 302);
+```
+
+## Share Library (`share`)
+
+Load with: `requirelib("share")`
+
+### File Sharing
+
+#### `share.shareFile(virtualPath, timeout)`
+Shares a file and returns share UUID.
+
+```javascript
+var shareId = share.shareFile("user:/document.pdf", 3600); // 1 hour timeout
+echo("Share URL: /share/" + shareId);
+```
+
+#### `share.removeShare(shareUUID)`
+Removes a file share.
+
+```javascript
+share.removeShare("share-uuid-here");
+```
+
+### Share Information
+
+#### `share.checkShareExists(shareUUID)`
+Checks if a share exists.
+
+```javascript
+if (share.checkShareExists("share-uuid")) {
+    echo("Share exists");
+}
+```
+
+#### `share.fileIsShared(virtualPath)`
+Checks if a file is shared.
+
+```javascript
+if (share.fileIsShared("user:/document.pdf")) {
+    echo("File is shared");
+}
+```
+
+#### `share.getFileShareUUID(virtualPath)`
+Gets the share UUID for a file.
+
+```javascript
+var shareId = share.getFileShareUUID("user:/document.pdf");
+if (shareId) {
+    echo("Share ID: " + shareId);
+}
+```
+
+#### `share.checkSharePermission(shareUUID)`
+Gets share permission level.
+
+```javascript
+var permission = share.checkSharePermission("share-uuid");
+// Returns permission level (read/write/etc)
+```
+
+## IoT Library (`iot`)
+
+Load with: `requirelib("iot")`
+
+### Device Discovery
+
+#### `iot.scan()`
+Scans for available IoT devices.
+
+```javascript
+var devices = iot.scan();
+// Returns array of device objects
+```
+
+#### `iot.list()`
+Lists cached IoT devices.
+
+```javascript
+var devices = iot.list();
+```
+
+### Device Control
+
+#### `iot.connect(deviceId, username, password, token)`
+Connects to an IoT device.
+
+```javascript
+if (iot.connect("device123", "admin", "password", "")) {
+    echo("Connected to device");
+}
+```
+
+#### `iot.disconnect(deviceId)`
+Disconnects from an IoT device.
+
+```javascript
+iot.disconnect("device123");
+```
+
+#### `iot.exec(deviceId, endpoint, payload)`
+Executes a command on an IoT device.
+
+```javascript
+var result = iot.exec("device123", "set_temperature", {value: 25});
+```
+
+#### `iot.status(deviceId)`
+Gets device status.
+
+```javascript
+var status = iot.status("device123");
+```
+
+### Utility Functions
+
+#### `iot.ready()`
+Checks if IoT system is ready.
+
+```javascript
+if (iot.ready()) {
+    echo("IoT system ready");
+}
+```
+
+#### `iot.iconTag(deviceId)`
+Gets device icon tag.
+
+```javascript
+var iconTag = iot.iconTag("device123");
+```
+
+## Appdata Library (`appdata`)
+
+Load with: `requirelib("appdata")`
+
+### Read-Only Web Data Access
+
+#### `appdata.readFile(relativePath)`
+Reads a file from the web root.
+
+```javascript
+var config = appdata.readFile("MyApp/config.json");
+var configObj = JSON.parse(config);
+```
+
+#### `appdata.listDir(relativePath)`
+Lists contents of a web directory.
+
+```javascript
+var files = JSON.parse(appdata.listDir("MyApp/templates"));
+for (var i = 0; i < files.length; i++) {
+    echo("File: " + files[i]);
+}
+```
+
+## FFmpeg Library (`ffmpeg`)
+
+Load with: `requirelib("ffmpeg")`
+
+### Media Conversion
+
+#### `ffmpeg.convert(inputPath, outputPath, compression)`
+Converts media files using FFmpeg.
+
+```javascript
+// Convert video to different format
+ffmpeg.convert("user:/video.mp4", "user:/video.webm", 0);
+
+// Convert with compression
+ffmpeg.convert("user:/audio.wav", "user:/audio.mp3", 5);
+```
+
+## WebSocket Library (`websocket`)
+
+Load with: `requirelib("websocket")`
+
+### WebSocket Connection
+
+#### `websocket.upgrade(timeout)`
+Upgrades HTTP connection to WebSocket.
+
+```javascript
+if (websocket.upgrade(300)) { // 5 minute timeout
+    echo("WebSocket upgraded");
+}
+```
+
+#### `websocket.send(message)`
+Sends a message through WebSocket.
+
+```javascript
+websocket.send("Hello from server!");
+```
+
+#### `websocket.read()`
+Reads a message from WebSocket.
+
+```javascript
+var message = websocket.read();
+if (message) {
+    echo("Received: " + message);
+}
+```
+
+#### `websocket.close()`
+Closes the WebSocket connection.
+
+```javascript
+websocket.close();
+```
+
+## Serverless Functions
+
+These functions are available when AGI scripts are called via HTTP requests.
+
+### Request Information
+
+#### `REQ_METHOD`
+HTTP request method.
+
+```javascript
+echo("Request method: " + REQ_METHOD);
+```
+
+### Parameter Access
+
+#### `getPara(key)`
+Gets a GET parameter.
+
+```javascript
+var username = getPara("username");
+if (username) {
+    echo("Hello, " + username);
+}
+```
+
+#### `postPara(key)`
+Gets a POST parameter.
+
+```javascript
+var password = postPara("password");
+```
+
+#### `readBody()`
+Reads the raw request body.
+
+```javascript
+var rawData = readBody();
+var data = JSON.parse(rawData);
+```
+
+## Error Handling
+
+AGI scripts should handle errors appropriately:
+
+```javascript
+try {
+    var content = filelib.readFile("user:/file.txt");
+    if (content === false) {
+        sendJSONResp({error: "File not found"});
+    } else {
+        sendJSONResp({content: content});
+    }
+} catch (e) {
+    sendJSONResp({error: "Script error: " + e.message});
+}
+```
+
+## Security Considerations
+
+- All file operations are sandboxed to user-accessible paths
+- Database operations are restricted to non-reserved tables
+- User management functions require admin privileges
+- External HTTP requests should be validated
+- File uploads should check size limits and types
+
+## Examples
+
+### Complete File Upload Handler
+
+```javascript
+// Load required libraries
+requirelib("filelib");
+
+// Get uploaded file info from POST parameters
+var filename = postPara("filename");
+var filedata = postPara("filedata");
+
+if (filename && filedata) {
+    // Decode base64 data
+    var decodedData = atob(filedata);
+    
+    // Save to user directory
+    var savePath = "user:/uploads/" + filename;
+    if (filelib.writeFile(savePath, decodedData)) {
+        sendJSONResp({
+            status: "success",
+            message: "File uploaded successfully",
+            path: savePath
+        });
+    } else {
+        sendJSONResp({
+            status: "error",
+            message: "Failed to save file"
+        });
+    }
+} else {
+    sendJSONResp({
+        status: "error",
+        message: "Missing filename or filedata"
+    });
+}
+```
+
+### User Settings Manager
+
+```javascript
+// Load file library
+requirelib("filelib");
+
+// Create settings table if not exists
+newDBTableIfNotExists("user_settings");
+
+// Handle different actions
+var action = getPara("action");
+
+if (action === "get") {
+    var key = getPara("key");
+    var value = readDBItem("user_settings", key);
+    sendJSONResp({value: value});
+    
+} else if (action === "set") {
+    var key = postPara("key");
+    var value = postPara("value");
+    writeDBItem("user_settings", key, value);
+    sendJSONResp({status: "saved"});
+    
+} else if (action === "list") {
+    var settings = listDBTable("user_settings");
+    sendJSONResp(settings);
+    
+} else {
+    sendJSONResp({error: "Invalid action"});
+}
+```
+
+This documentation covers all available AGI APIs with practical examples. For more advanced usage, refer to the existing module implementations in the system.