From d724f97403c7347f538daaaf95afc34766682b5f Mon Sep 17 00:00:00 2001 From: wancat Date: Sun, 29 Oct 2023 17:12:31 +0800 Subject: [PATCH] feat: add pending signal to status --- app/src/utils/session.js | 10 ++++-- app/src/views/GamePage.vue | 19 +++++++----- docker-compose.yml | 2 +- packages/container/cli.js | 31 ++++++++++--------- packages/container/package.json | 2 +- .../src/api/controllers/commandController.js | 31 ++++++++++++++++++- .../src/api/controllers/sessionController.js | 6 ++++ server/src/api/routes/commands.js | 1 + server/src/api/routes/index.js | 1 + server/src/game/sessionHandler.js | 8 +++-- yarn.lock | 9 ++++++ 11 files changed, 90 insertions(+), 30 deletions(-) diff --git a/app/src/utils/session.js b/app/src/utils/session.js index 0869c70..65c2dba 100644 --- a/app/src/utils/session.js +++ b/app/src/utils/session.js @@ -15,6 +15,7 @@ class SessionManager { }) ) this.pwd = ref('') + this.status = ref('inactive') } getSession() { @@ -26,6 +27,7 @@ class SessionManager { this.session.value = session this.graph.value = new FileGraph(session.graph) this.hints.value = session.hints + this.status.value = session.status } handleGraphUpdate(event) { @@ -37,8 +39,12 @@ class SessionManager { } } - handleHintUpdate(event) { - this.hints.value = [...this.hints.value, ...event] + handleHintUpdate(hints) { + this.hints.value = [...this.hints.value, ...hints] + } + + handleStatusUpdate(status) { + this.status.value = status } setTasks(tasks) { diff --git a/app/src/views/GamePage.vue b/app/src/views/GamePage.vue index c92f8f7..6312731 100644 --- a/app/src/views/GamePage.vue +++ b/app/src/views/GamePage.vue @@ -1,5 +1,5 @@ @@ -48,6 +45,12 @@ onMounted(async () => {
+ +
diff --git a/docker-compose.yml b/docker-compose.yml index d751e4f..1508496 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,7 +36,7 @@ services: - BASE_URL=http://localhost:5173 - MONGO_URL=mongodb://db:27017/odyssey-test - DOCKER_NETWORK=linux-odyssey-players - # - HOST_PWD=${PWD} + - HOST_PWD=${PWD} - GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID} - GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET} - GITHUB_CLIENT_ID=${GITHUB_CLIENT_ID} diff --git a/packages/container/cli.js b/packages/container/cli.js index a6f71d3..2165189 100644 --- a/packages/container/cli.js +++ b/packages/container/cli.js @@ -2,6 +2,7 @@ const fs = require('fs').promises const { exit } = require('process') const minimist = require('minimist') +const axios = require('axios') const { colorize, printResponses } = require('./print.js') const discoverFiles = require('./discover.js') @@ -40,6 +41,13 @@ async function main() { } = process.env if (!CMD_NAME) exit(0) + const api = axios.create({ + baseURL: `${API_ENDPOINT}/api/v1`, + headers: { + Authorization: `Bearer ${TOKEN}`, + }, + }) + const additionalData = await handleCommand(CMD_NAME) const output = await readOrNone(CMD_OUTPUT_FILE) @@ -53,24 +61,19 @@ async function main() { ...additionalData, } try { - const res = await fetch(`${API_ENDPOINT}/api/v1/commands`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${TOKEN}`, - }, - body: JSON.stringify(payload), - }) - const data = await res.json() - if (data.responses) { - await printResponses(data.responses, 60) + const res = await api.post('/commands', payload) + if (!res.data) return + const { responses, hints, end } = res.data + if (responses) { + await printResponses(responses, 60) + await api.post('/commands/completed') } - if (data.hints) { - for (const hint of data.hints) { + if (hints) { + for (const hint of hints) { console.log(colorize(hint, 'yellow')) } } - if (data.end) { + if (end) { console.log(colorize('Quest completed!', 'blue')) } } catch (err) { diff --git a/packages/container/package.json b/packages/container/package.json index 2c6bc8a..c04fd58 100644 --- a/packages/container/package.json +++ b/packages/container/package.json @@ -4,7 +4,7 @@ "main": "index.js", "license": "MIT", "dependencies": { - "chokidar": "^3.5.3", + "axios": "^1.6.0", "minimist": "^1.2.8" } } diff --git a/server/src/api/controllers/commandController.js b/server/src/api/controllers/commandController.js index 36f998a..f3af3d7 100644 --- a/server/src/api/controllers/commandController.js +++ b/server/src/api/controllers/commandController.js @@ -1,6 +1,8 @@ -/* eslint-disable import/prefer-default-export */ import { Command, Session } from '@linux-odyssey/models' import CommandHandler from '../../game/commandHandler.js' +import { pushToSession } from '../socket.js' + +const commandCompleteCallbacks = new Map() export async function newCommand(req, res) { console.log('new command:', req.body) @@ -44,8 +46,35 @@ export async function newCommand(req, res) { if (response) { c.stage = response.stage await c.save() + commandCompleteCallbacks.set(session.id, response.callback) + pushToSession(session.id, 'status', 'pending') } res.status(201).json(response) await session.save() } + +export async function completedCommand(req, res) { + const sessionId = req.user.session_id + + const session = await Session.findById(sessionId) + + if (!session) { + res.status(404).json({ message: 'session not found' }) + return + } + + if (session.status === 'inactive') { + res.status(400).json({ message: 'session is not active' }) + return + } + + const callback = commandCompleteCallbacks.get(session.id) + if (!callback) { + res.status(400).json({ message: 'no callback found' }) + return + } + callback() + commandCompleteCallbacks.delete(session.id) + res.json({ message: 'ok' }) +} diff --git a/server/src/api/controllers/sessionController.js b/server/src/api/controllers/sessionController.js index 6cdb4df..51f8e69 100644 --- a/server/src/api/controllers/sessionController.js +++ b/server/src/api/controllers/sessionController.js @@ -44,6 +44,12 @@ export async function createSession(req, res) { return } + // deactive all active sessions + await Session.updateMany( + { user: req.user._id, quest, status: 'active' }, + { status: 'inactive' } + ) + try { const container = await createContainer( `quest-${quest.id}-${req.user.username}-${Date.now()}` diff --git a/server/src/api/routes/commands.js b/server/src/api/routes/commands.js index 5eeef05..eb116c3 100644 --- a/server/src/api/routes/commands.js +++ b/server/src/api/routes/commands.js @@ -4,5 +4,6 @@ import * as commandController from '../controllers/commandController.js' const router = Router() router.post('/', commandController.newCommand) +router.post('/completed', commandController.completedCommand) export default router diff --git a/server/src/api/routes/index.js b/server/src/api/routes/index.js index 53a9c9f..fde9932 100644 --- a/server/src/api/routes/index.js +++ b/server/src/api/routes/index.js @@ -19,6 +19,7 @@ router.use('/sessions', authRequired, sessions) router.use( '/commands', passport.authenticate('jwt', { session: false }), + authRequired, commands ) diff --git a/server/src/game/sessionHandler.js b/server/src/game/sessionHandler.js index a6a91f8..6107305 100644 --- a/server/src/game/sessionHandler.js +++ b/server/src/game/sessionHandler.js @@ -34,7 +34,6 @@ export default class SessionHandler { addNewTasks() { const newTasks = this.getNewTasks() this.session.tasks.push(...newTasks) - pushToSession(this.session.id, 'tasks', this.session.tasks) } execute(stage) { @@ -45,12 +44,10 @@ export default class SessionHandler { }) this.session.hints.push(...stage.hints) - pushToSession(this.session.id, 'hints', stage.hints) if (stage.id === 'END') { this.session.status = 'finished' this.session.finishedAt = new Date() - pushToSession(this.session.id, 'status', 'finished') } this.addNewTasks() @@ -58,6 +55,11 @@ export default class SessionHandler { return { responses: stage.responses, hints: stage.hints, + callback: () => { + pushToSession(this.session.id, 'tasks', this.session.tasks) + pushToSession(this.session.id, 'hints', stage.hints) + pushToSession(this.session.id, 'status', this.session.status) + }, } } } diff --git a/yarn.lock b/yarn.lock index 0046d79..9e4e5e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1407,6 +1407,15 @@ axios@^1.5.0: form-data "^4.0.0" proxy-from-env "^1.1.0" +axios@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.0.tgz#f1e5292f26b2fd5c2e66876adc5b06cdbd7d2102" + integrity sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + babel-jest@^29.6.1: version "29.6.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.6.1.tgz#a7141ad1ed5ec50238f3cd36127636823111233a"