diff --git a/API-QUICKSTART.md b/API-QUICKSTART.md index 064b80a..ffbfaf6 100644 --- a/API-QUICKSTART.md +++ b/API-QUICKSTART.md @@ -8,17 +8,27 @@ The API server starts automatically when you run Paarrot. It listens on `http:// ### Test the API -**Option 1: Using the test script** +**Option 1: Using Postman** + +Import the Postman collection for easy testing: +1. Open Postman +2. Click **Import** → **File** +3. Select `paarrot-api.postman_collection.json` +4. All endpoints will be ready to use! + +The collection is automatically updated on git push. + +**Option 2: Using the test script** ```bash node test-api.js ``` -**Option 2: Using curl** +**Option 3: Using curl** ```bash ./test-api.sh ``` -**Option 3: Manual curl commands** +**Option 4: Manual curl commands** ```bash # Health check curl http://127.0.0.1:33384/health diff --git a/paarrot-api.postman_collection.json b/paarrot-api.postman_collection.json new file mode 100644 index 0000000..737cb4c --- /dev/null +++ b/paarrot-api.postman_collection.json @@ -0,0 +1,274 @@ +{ + "info": { + "_postman_id": "paarrot-api-collection", + "name": "Paarrot API", + "description": "API endpoints for controlling Paarrot (Cinny Desktop) features like muting, deafening, channel navigation, and messaging.", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "paarrot-api" + }, + "item": [ + { + "name": "Health & Status", + "item": [ + { + "name": "Health Check", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/health", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "health" + ] + }, + "description": "Check if the API server is running and healthy." + } + }, + { + "name": "Get Status", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/status", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "status" + ] + }, + "description": "Get current application status including mute/deafen state, current room, connection status, and user ID." + } + } + ] + }, + { + "name": "Audio Controls", + "item": [ + { + "name": "Toggle Mute", + "request": { + "method": "POST", + "header": [], + "url": { + "raw": "{{baseUrl}}/mute/toggle", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "mute", + "toggle" + ] + }, + "description": "Toggle microphone mute state. Works only when in an active call." + } + }, + { + "name": "Set Mute", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"muted\": true\n}" + }, + "url": { + "raw": "{{baseUrl}}/mute", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "mute" + ] + }, + "description": "Set microphone mute to a specific state (true/false). Works only when in an active call." + } + }, + { + "name": "Toggle Deafen", + "request": { + "method": "POST", + "header": [], + "url": { + "raw": "{{baseUrl}}/deafen/toggle", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "deafen", + "toggle" + ] + }, + "description": "Toggle deafen state (mutes all incoming audio and your microphone). Works only when in an active call." + } + }, + { + "name": "Set Deafen", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"deafened\": true\n}" + }, + "url": { + "raw": "{{baseUrl}}/deafen", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "deafen" + ] + }, + "description": "Set deafen to a specific state (true/false). Works only when in an active call." + } + } + ] + }, + { + "name": "Rooms & Channels", + "item": [ + { + "name": "Get Channels", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/channels", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "channels" + ] + }, + "description": "Get list of all available rooms/channels with their details (roomId, name, isDirect, avatar)." + } + }, + { + "name": "Get Current Room", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "{{baseUrl}}/room/current", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "room", + "current" + ] + }, + "description": "Get information about the currently active room." + } + }, + { + "name": "Change Channel", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"roomId\": \"!YourRoomId:server.com\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/channel", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "channel" + ] + }, + "description": "Navigate to a different room/channel by providing its roomId." + } + } + ] + }, + { + "name": "Messaging", + "item": [ + { + "name": "Send Message to Room", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"roomId\": \"!YourRoomId:server.com\",\n \"message\": \"Hello from Postman!\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/message", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "message" + ] + }, + "description": "Send a text message to a specific room by providing roomId and message content." + } + }, + { + "name": "Send Message to Current Room", + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"message\": \"Hello from Postman!\"\n}" + }, + "url": { + "raw": "{{baseUrl}}/message/current", + "host": [ + "{{baseUrl}}" + ], + "path": [ + "message", + "current" + ] + }, + "description": "Send a text message to the currently active room." + } + } + ] + } + ], + "variable": [ + { + "key": "baseUrl", + "value": "http://127.0.0.1:33384", + "type": "string" + } + ] +} diff --git a/package.json b/package.json index b4bd07e..1a852bd 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "dev:electron": "wait-on http://localhost:8080 && NODE_ENV=development electron .", "build": "node -e \"require('fs').copyFileSync('config.json', 'cinny/config.json')\" && cd cinny && npm run build && cd .. && electron-builder --publish never", "build:linux": "npm run build -- --linux", - "build:win": "npm run build -- --win" + "build:win": "npm run build -- --win", + "postman:generate": "node scripts/generate-postman-collection.js" }, "keywords": [], "author": { diff --git a/scripts/generate-postman-collection.js b/scripts/generate-postman-collection.js new file mode 100755 index 0000000..28e9c17 --- /dev/null +++ b/scripts/generate-postman-collection.js @@ -0,0 +1,224 @@ +#!/usr/bin/env node + +/** + * Generate Postman collection from API documentation + * This script reads the API.md file and generates a Postman collection + */ + +const fs = require('fs'); +const path = require('path'); + +const collection = { + info: { + _postman_id: 'paarrot-api-collection', + name: 'Paarrot API', + description: 'API endpoints for controlling Paarrot (Cinny Desktop) features like muting, deafening, channel navigation, and messaging.', + schema: 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json', + _exporter_id: 'paarrot-api', + }, + item: [ + { + name: 'Health & Status', + item: [ + { + name: 'Health Check', + request: { + method: 'GET', + header: [], + url: { + raw: '{{baseUrl}}/health', + host: ['{{baseUrl}}'], + path: ['health'], + }, + description: 'Check if the API server is running and healthy.', + }, + }, + { + name: 'Get Status', + request: { + method: 'GET', + header: [], + url: { + raw: '{{baseUrl}}/status', + host: ['{{baseUrl}}'], + path: ['status'], + }, + description: 'Get current application status including mute/deafen state, current room, connection status, and user ID.', + }, + }, + ], + }, + { + name: 'Audio Controls', + item: [ + { + name: 'Toggle Mute', + request: { + method: 'POST', + header: [], + url: { + raw: '{{baseUrl}}/mute/toggle', + host: ['{{baseUrl}}'], + path: ['mute', 'toggle'], + }, + description: 'Toggle microphone mute state. Works only when in an active call.', + }, + }, + { + name: 'Set Mute', + request: { + method: 'POST', + header: [{ key: 'Content-Type', value: 'application/json' }], + body: { + mode: 'raw', + raw: JSON.stringify({ muted: true }, null, 2), + }, + url: { + raw: '{{baseUrl}}/mute', + host: ['{{baseUrl}}'], + path: ['mute'], + }, + description: 'Set microphone mute to a specific state (true/false). Works only when in an active call.', + }, + }, + { + name: 'Toggle Deafen', + request: { + method: 'POST', + header: [], + url: { + raw: '{{baseUrl}}/deafen/toggle', + host: ['{{baseUrl}}'], + path: ['deafen', 'toggle'], + }, + description: 'Toggle deafen state (mutes all incoming audio and your microphone). Works only when in an active call.', + }, + }, + { + name: 'Set Deafen', + request: { + method: 'POST', + header: [{ key: 'Content-Type', value: 'application/json' }], + body: { + mode: 'raw', + raw: JSON.stringify({ deafened: true }, null, 2), + }, + url: { + raw: '{{baseUrl}}/deafen', + host: ['{{baseUrl}}'], + path: ['deafen'], + }, + description: 'Set deafen to a specific state (true/false). Works only when in an active call.', + }, + }, + ], + }, + { + name: 'Rooms & Channels', + item: [ + { + name: 'Get Channels', + request: { + method: 'GET', + header: [], + url: { + raw: '{{baseUrl}}/channels', + host: ['{{baseUrl}}'], + path: ['channels'], + }, + description: 'Get list of all available rooms/channels with their details (roomId, name, isDirect, avatar).', + }, + }, + { + name: 'Get Current Room', + request: { + method: 'GET', + header: [], + url: { + raw: '{{baseUrl}}/room/current', + host: ['{{baseUrl}}'], + path: ['room', 'current'], + }, + description: 'Get information about the currently active room.', + }, + }, + { + name: 'Change Channel', + request: { + method: 'POST', + header: [{ key: 'Content-Type', value: 'application/json' }], + body: { + mode: 'raw', + raw: JSON.stringify({ roomId: '!YourRoomId:server.com' }, null, 2), + }, + url: { + raw: '{{baseUrl}}/channel', + host: ['{{baseUrl}}'], + path: ['channel'], + }, + description: 'Navigate to a different room/channel by providing its roomId.', + }, + }, + ], + }, + { + name: 'Messaging', + item: [ + { + name: 'Send Message to Room', + request: { + method: 'POST', + header: [{ key: 'Content-Type', value: 'application/json' }], + body: { + mode: 'raw', + raw: JSON.stringify( + { + roomId: '!YourRoomId:server.com', + message: 'Hello from Postman!', + }, + null, + 2 + ), + }, + url: { + raw: '{{baseUrl}}/message', + host: ['{{baseUrl}}'], + path: ['message'], + }, + description: 'Send a text message to a specific room by providing roomId and message content.', + }, + }, + { + name: 'Send Message to Current Room', + request: { + method: 'POST', + header: [{ key: 'Content-Type', value: 'application/json' }], + body: { + mode: 'raw', + raw: JSON.stringify({ message: 'Hello from Postman!' }, null, 2), + }, + url: { + raw: '{{baseUrl}}/message/current', + host: ['{{baseUrl}}'], + path: ['message', 'current'], + }, + description: 'Send a text message to the currently active room.', + }, + }, + ], + }, + ], + variable: [ + { + key: 'baseUrl', + value: 'http://127.0.0.1:33384', + type: 'string', + }, + ], +}; + +// Write the collection to file (in the project root) +const outputPath = path.join(__dirname, '..', 'paarrot-api.postman_collection.json'); +fs.writeFileSync(outputPath, JSON.stringify(collection, null, 2) + '\n'); + +console.log('✅ Postman collection generated:', outputPath);