/** * DEPRECATED / LEGACY * * This standalone script is no longer the recommended way to query offline devices. * * Use the Webex bot command instead: * In your Webex space: type `offline` (or `offline some-filter`) * * The main server (index.js) now provides a much better implementation: * - Uses the Appspace refresh token flow (not static APPSPACE_API_TOKEN) * - Shares token management with the webhook path * - Has filtering, better table output, and MDM enrichment in other flows * * This file is kept only for emergency/audit use. It uses older env var conventions * (APPSPACE_BASE_URL + APPSPACE_API_TOKEN) and performs a one-shot query then exits. * * Consider removing this file once the bot command has been validated in production. */ require('dotenv').config(); const axios = require('axios'); const WEBEX_BOT_TOKEN = process.env.WEBEX_BOT_TOKEN; const WEBEX_ROOM_ID = process.env.WEBEX_ROOM_ID; const APPSPACE_API_TOKEN = process.env.APPSPACE_API_TOKEN; // Legacy static token const APPSPACE_API_BASE_URL = process.env.APPSPACE_BASE_URL || 'https://api.cloud.appspace.com'; if (!WEBEX_BOT_TOKEN || !WEBEX_ROOM_ID || !APPSPACE_API_TOKEN) { console.error('❌ Missing required env vars: WEBEX_BOT_TOKEN, WEBEX_ROOM_ID, APPSPACE_API_TOKEN'); process.exit(1); } console.warn('⚠️ Running DEPRECATED query-offline.js script. Prefer the "offline" command via the Webex bot.'); async function queryOfflineDevices() { try { console.log('🔍 Querying Appspace for offline / lost devices...'); // Example API call - adjust endpoint based on your exact API docs // Common pattern: GET /devices with filters for health status const response = await axios.get(`${APPSPACE_API_BASE_URL}/api/v3/devices`, { headers: { Authorization: `Bearer ${APPSPACE_API_TOKEN}`, 'Content-Type': 'application/json' }, params: { // Filter examples (test and refine in Postman first) healthStatus: 'LostCommunication,Offline,Failed', // or use separate calls if needed limit: 200, // locationId: 'optional-filter', // include: 'location,group' } }); const devices = response.data.items || response.data; // adjust based on actual response shape const offlineDevices = devices.filter(d => ['LostCommunication', 'Offline', 'Failed'].includes(d.healthStatus || d.status) ); if (offlineDevices.length === 0) { await sendToWebex('✅ **All devices are currently online or in sync.** No offline devices detected.'); console.log('✅ No offline devices'); return; } // Build a nice Adaptive Card summary const facts = offlineDevices.map(d => ({ title: d.name || d.deviceName || 'Unknown', value: `${d.healthStatus || d.status} • ${d.locationName || 'No location'} • IP: ${d.ipAddress || 'N/A'}` })); const adaptiveCard = { "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.3", "body": [ { "type": "Container", "style": "attention", "bleed": true, "items": [ { "type": "TextBlock", "text": `📊 Offline Devices Snapshot (${offlineDevices.length})`, "weight": "bolder", "size": "medium" } ] }, { "type": "FactSet", "facts": facts } ], "actions": [ { "type": "Action.OpenUrl", "title": "🔗 Open Devices in Appspace Console", "url": "https://app3.cloud.appspace.com/console/#!/devices" } ] }; await sendToWebex(null, adaptiveCard); console.log(`✅ Sent ${offlineDevices.length} offline devices to Webex`); } catch (err) { console.error('❌ Error querying offline devices:', err.response?.data || err.message); await sendToWebex('⚠️ Failed to query offline devices. Check API token and console.'); } } async function sendToWebex(text, card = null) { const payload = { roomId: WEBEX_ROOM_ID, text: text || 'Appspace Offline Devices Report' }; if (card) { payload.attachments = [{ contentType: "application/vnd.microsoft.card.adaptive", content: card }]; } await axios.post('https://webexapis.com/v1/messages', payload, { headers: { Authorization: `Bearer ${WEBEX_BOT_TOKEN}`, 'Content-Type': 'application/json' } }); } queryOfflineDevices();