From e4098ebf01c415004834c756354b0e72b113a2d9 Mon Sep 17 00:00:00 2001 From: Kevin Aleman Date: Tue, 21 Nov 2023 12:08:08 -0600 Subject: [PATCH] mac --- agents.js | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++ index.js | 12 +++++-- visitors.js | 21 +++++++++--- 3 files changed, 119 insertions(+), 7 deletions(-) diff --git a/agents.js b/agents.js index e69de29..ccac9ca 100644 --- a/agents.js +++ b/agents.js @@ -0,0 +1,93 @@ +import { request } from "undici"; +import ShortUniqueId from 'short-unique-id'; + +import { parseHost } from "./utils.js"; +import buzzphrase from "buzzphrase"; + +const uid = new ShortUniqueId({ length: 10 }); + +const host = parseHost(process.env.HOST); +const departmentId = process.env.DEPARTMENT || process.argv[4]; + +export async function getCurrentAgentList(onlyAvailable = true) { + if (departmentId) { + const response = await request(`${ host }api/v1/livechat/department/${ departmentId }`); + const { agents } = response.body.json(); + + return agents; + } + + const response = await request(`${ host }api/v1/livechat/users/agent?onlyAvailable=${ onlyAvailable }`); + const { agents } = response.body.json(); + + return agents; +} + +export async function checkAgents(adminUsername, adminPassword) { + if (!adminUsername || !adminPassword) { + throw new Error('Admin username and password are required when creating agents'); + } + + return createAgentUser(adminUsername, adminPassword, departmentId); +} + +async function createAgentUser(adminUsername, adminPassword, departmentId) { + const userData = uid(); + const user = await request(`${ host }api/v1/users.create`, { method: 'POST', headers: { + 'content-type': 'application/json', + 'X-User-Id': adminUsername, + 'X-Auth-Token': adminPassword, + }, body: JSON.stringify({ + email: `${uid()}@rocket.chat`, + joinDefaultChannels: false, + username: userData, + password: 'test', + roles: ['livechat-agent', 'user', 'livechat-manager'], + verified: true, + name: 'testerio', + }) }); + + const result = await user.body.json(); + + if (!result.user) { + console.error(result); + throw new Error('Error creating agent user'); + } + + if (departmentId) { + await request(`${ host }api/v1/livechat/department/${ departmentId }/agents`, { method: 'POST', headers: { + 'content-type': 'application/json', + 'X-User-Id': adminUsername, + 'X-Auth-Token': adminPassword, + }, body: JSON.stringify({ upsert: [{ username: result.user.username, agentId: result.user._id, count: 0, order: 0 }] }) }); + } + + return { + username: userData, + password: 'test', + }; +} + +export async function sendAgentMessage(room, agent) { + const result = await request(`${ host }api/v1/method.call/sendMessage`, { method: 'POST', headers: { + 'content-type': 'application/json', + 'X-User-Id': agent.userId, + 'X-Auth-Token': agent.authToken, + }, body: JSON.stringify({ message: JSON.stringify({ + method: 'sendMessage', + params: [{ rid: room._id, msg: buzzphrase.get({ iterations: 2 }) }], + id: 'id', + msg: 'method', + })}) }); + + const response = await result.body.json(); + console.log(`\tAgent ${ agent.userId } sent message to room ${ room._id }. Success: ${ !response.error }`); +} + +export async function answerRoom(room, agent) { + const response = await request(`${ host }api/v1/login`, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ username: agent.username, password: agent.password }) }); + + const { authToken, userId } = (await response.body.json()).data; + + return sendAgentMessage(room, { authToken, userId }); +} \ No newline at end of file diff --git a/index.js b/index.js index 0d1ae27..4fd831b 100644 --- a/index.js +++ b/index.js @@ -2,6 +2,7 @@ import { setTimeout as wait } from "timers/promises"; import pLimit from 'p-limit'; import { persona, printStats } from './visitors.js'; +import { checkAgents } from "./agents.js"; const limit = pLimit(20); @@ -10,6 +11,9 @@ let errorCount = 0; const attemptsMax = process.env.ATTEMPTS || Number(process.argv[2]); const delay = process.env.DELAY || Number(process.argv[3]); +const agents = process.env.ENABLE_AGENTS || Number(process.argv[4]); +const username = process.env.ADMIN_ID; +const password = process.env.ADMIN_TOKEN; function showHelp() { console.log(` @@ -22,12 +26,16 @@ Usage: node index.js [ATTEMPTS] [DELAY] `); } +const personaTotalTime = []; + async function run(delay) { + let agent; try { + agent = agents ? await checkAgents(username, password) : null; await wait(delay); const start = new Date(); - await persona(start); + await persona(start, agent); personaTotalTime.push(new Date() - start); errorCount = 0; @@ -60,7 +68,7 @@ function init() { } Promise.all(op).then(() => { - printStats(); + printStats(personaTotalTime); }); } diff --git a/visitors.js b/visitors.js index 7917174..684cd52 100644 --- a/visitors.js +++ b/visitors.js @@ -2,14 +2,16 @@ import { request } from "undici"; import assert from 'assert'; import buzzphrase from 'buzzphrase'; import ShortUniqueId from 'short-unique-id'; +import { setTimeout as wait } from "timers/promises"; + import { parseHost } from "./utils.js"; +import { answerRoom } from "./agents.js"; const uid = new ShortUniqueId({ length: 10 }); let host = parseHost(process.env.HOST); const departmentId = process.env.DEPARTMENT || process.argv[4]; -const personaTotalTime = []; const visitorCreationTime = []; const roomCreationTime = []; const messageCreationTime = []; @@ -21,9 +23,9 @@ function parseNaNValue(value) { return (Number.isNaN(value) ? 0 : value).toFixed(2); } -export function printStats() { - const totalOpTime = personaTotalTime.reduce((a, b) => a + b / 1000, 0) - 5 * personaTotalTime.length; - const avgPersonaTime = totalOpTime / personaTotalTime.length; +export function printStats(total) { + const totalOpTime = total.reduce((a, b) => a + b / 1000, 0) - 5 * total.length; + const avgPersonaTime = totalOpTime / total.length; const avgVisitorCreationTime = visitorCreationTime.reduce((a, b) => a + b / 1000, 0) / visitorCreationTime.length; const avgRoomCreationTime = roomCreationTime.reduce((a, b) => a + b / 1000, 0) / roomCreationTime.length; const avgMessageCreationTime = messageCreationTime.reduce((a, b) => a + b / 1000, 0) / messageCreationTime.length; @@ -109,7 +111,7 @@ async function consumeBody(request) { // 5. send a message to the room // 6. fetch messages from the room again // 7. end -export async function persona(start) { +export async function persona(start, agent) { const { visitor } = await consumeBody(await measureActionTo(createVisitor, visitorCreationTime)); assert(visitor, 'Visitor was not created'); @@ -130,5 +132,14 @@ export async function persona(start) { await wait(1000) await measureActionTo(() => fetchMessages(visitor, room), fetch2ndMessagesTime); + if (agent) { + console.log(`\tPersona ${ visitor.token } is being answered by agent ${ agent.username }`); + try { + await answerRoom(room, agent); + } catch (e) { + console.error(`\tPersona ${ visitor.token } could not be answered by agent ${ agent.username }`, e); + } + } + console.log(`Persona ${ visitor.token } done in ${ new Date() - start }ms`); } \ No newline at end of file