// server.js
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const jwt = require('jsonwebtoken');
const fetch = require('node-fetch'); // to call Watson REST API
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
const JWT_SECRET = process.env.JWT_SECRET || 'change_me';
const WATSON_APIKEY = process.env.WATSON_APIKEY || 'YOUR_WATSON_APIKEY';
const WATSON_URL = process.env.WATSON_URL || 'https://api.us-south.assistant.watson.cloud.ibm.com';
const WATSON_ASSISTANT_ID = process.env.WATSON_ASSISTANT_ID || 'YOUR_ASSISTANT_ID';
app.get('/', (req, res) => res.send('Dr. Oculus Gateway'));
function callWatson(sessionId, inputText){
// example: call Watson Assistant v2
const url = ${WATSON_URL}/v2/assistants/${WATSON_ASSISTANT_ID}/sessions;
// In production, cache sessions; create once per user/session
return fetch(url + '?version=2021-06-14', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + Buffer.from('apikey:' + WATSON_APIKEY).toString('base64'),
'Content-Type': 'application/json'
},
body: JSON.stringify({})
})
.then(r => r.json())
.then(session => {
const sessionId = session.session_id;
const messageUrl = ${WATSON_URL}/v2/assistants/${WATSON_ASSISTANT_ID}/sessions/${sessionId}/message?version=2021-06-14;
return fetch(messageUrl, {
method: 'POST',
headers: {
'Authorization': 'Basic ' + Buffer.from('apikey:' + WATSON_APIKEY).toString('base64'),
'Content-Type': 'application/json'
},
body: JSON.stringify({ input: { 'message_type': 'text', 'text': inputText }})
}).then(r => r.json());
});
}
wss.on('connection', function connection(ws, req) {
// Expect the client to send a JWT as the first message or in query string
ws.isAuthorized = false;
ws.on('message', async function incoming(message) {
try {
const payload = JSON.parse(message);
if(!ws.isAuthorized){
// first message should be { type: 'auth', token: '...' }
if(payload.type === 'auth' && payload.token){
try {
const decoded = jwt.verify(payload.token, JWT_SECRET);
ws.user = decoded;
ws.isAuthorized = true;
ws.send(JSON.stringify({type:'auth_ok'}));
} catch(e) {
ws.send(JSON.stringify({type:'auth_fail', reason: 'invalid token'}));
ws.close();
}
} else {
ws.send(JSON.stringify({type:'auth_required'}));
ws.close();
}
return;
}
// handle messages after auth
if(payload.type === 'user_message'){
// route to Watson
const watsonRes = await callWatson(ws.user.sub, payload.text);
ws.send(JSON.stringify({ type: 'assistant', data: watsonRes }));
} else if(payload.type === 'game_event'){
// route to ZooMeta microservice (example)
// call your ZooMeta REST endpoint (omitted here)
ws.send(JSON.stringify({ type: 'game_event_ack' }));
}
} catch (err) {
console.error('message handling error', err);
ws.send(JSON.stringify({ type: 'error', message: err.message }));
}
});
});
const PORT = process.env.PORT || 8080;
server.listen(PORT, () => console.log(Server listening on ${PORT}));
// server.js
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const jwt = require('jsonwebtoken');
const fetch = require('node-fetch'); // to call Watson REST API
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
const JWT_SECRET = process.env.JWT_SECRET || 'change_me';
const WATSON_APIKEY = process.env.WATSON_APIKEY || 'YOUR_WATSON_APIKEY';
const WATSON_URL = process.env.WATSON_URL || 'https://api.us-south.assistant.watson.cloud.ibm.com';
const WATSON_ASSISTANT_ID = process.env.WATSON_ASSISTANT_ID || 'YOUR_ASSISTANT_ID';
app.get('/', (req, res) => res.send('Dr. Oculus Gateway'));
function callWatson(sessionId, inputText){
// example: call Watson Assistant v2
const url =
${WATSON_URL}/v2/assistants/${WATSON_ASSISTANT_ID}/sessions;// In production, cache sessions; create once per user/session
return fetch(url + '?version=2021-06-14', {
method: 'POST',
headers: {
'Authorization': 'Basic ' + Buffer.from('apikey:' + WATSON_APIKEY).toString('base64'),
'Content-Type': 'application/json'
},
body: JSON.stringify({})
})
.then(r => r.json())
.then(session => {
const sessionId = session.session_id;
const messageUrl =
${WATSON_URL}/v2/assistants/${WATSON_ASSISTANT_ID}/sessions/${sessionId}/message?version=2021-06-14;return fetch(messageUrl, {
method: 'POST',
headers: {
'Authorization': 'Basic ' + Buffer.from('apikey:' + WATSON_APIKEY).toString('base64'),
'Content-Type': 'application/json'
},
body: JSON.stringify({ input: { 'message_type': 'text', 'text': inputText }})
}).then(r => r.json());
});
}
wss.on('connection', function connection(ws, req) {
// Expect the client to send a JWT as the first message or in query string
ws.isAuthorized = false;
ws.on('message', async function incoming(message) {
try {
const payload = JSON.parse(message);
if(!ws.isAuthorized){
// first message should be { type: 'auth', token: '...' }
if(payload.type === 'auth' && payload.token){
try {
const decoded = jwt.verify(payload.token, JWT_SECRET);
ws.user = decoded;
ws.isAuthorized = true;
ws.send(JSON.stringify({type:'auth_ok'}));
} catch(e) {
ws.send(JSON.stringify({type:'auth_fail', reason: 'invalid token'}));
ws.close();
}
} else {
ws.send(JSON.stringify({type:'auth_required'}));
ws.close();
}
return;
}
});
});
const PORT = process.env.PORT || 8080;
server.listen(PORT, () => console.log(
Server listening on ${PORT}));