mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-08 11:30:12 +08:00
feat: new cli client to send and receive msg from api
This commit is contained in:
1 parent
e2e585329f
commit
0153eae673
5 files changed
+93
-17
No files matched your search
@@ -0,0 +1,7 @@
|
|||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
helloworld:
|
||||||
|
image: lancatlin/linux-odyssey:helloworld
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: server/quests/helloworld/Dockerfile
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
const readline = require('readline')
|
||||||
|
|
||||||
|
process.stdin.setRawMode(true)
|
||||||
|
|
||||||
|
const rl = readline.createInterface({
|
||||||
|
input: process.stdin,
|
||||||
|
output: process.stdout,
|
||||||
|
terminal: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
async function printResponses(responses, delay = 100) {
|
||||||
|
for (const response of responses) {
|
||||||
|
await printResponse(response, delay)
|
||||||
|
}
|
||||||
|
rl.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForEnter() {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
rl.once('line', resolve)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function printResponse(response, delay) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
let i = 0
|
||||||
|
const timer = setInterval(() => {
|
||||||
|
process.stdout.write(response[i])
|
||||||
|
i += 1
|
||||||
|
if (i >= response.length) {
|
||||||
|
clearInterval(timer)
|
||||||
|
waitForEnter().then(resolve)
|
||||||
|
}
|
||||||
|
}, delay)
|
||||||
|
|
||||||
|
waitForEnter().then(() => {
|
||||||
|
clearInterval(timer)
|
||||||
|
process.stdout.write(response.slice(i) + '\n')
|
||||||
|
resolve()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function request() {
|
||||||
|
const { API_ENDPOINT, TOKEN, PWD, COMMAND, OUTPUT, EXIT_CODE } = process.env
|
||||||
|
const payload = {
|
||||||
|
command: COMMAND,
|
||||||
|
output: OUTPUT,
|
||||||
|
exit_code: EXIT_CODE,
|
||||||
|
token: TOKEN,
|
||||||
|
pwd: PWD,
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${API_ENDPOINT}/api/v1/commands`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
})
|
||||||
|
const data = await res.json()
|
||||||
|
if (data.responses) {
|
||||||
|
await printResponses(data.responses, 100)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request()
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM ubuntu:latest
|
FROM node:latest
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
curl \
|
curl \
|
||||||
@@ -11,6 +11,8 @@ USER rudeus
|
|||||||
|
|
||||||
WORKDIR /home/rudeus
|
WORKDIR /home/rudeus
|
||||||
|
|
||||||
COPY ./home /home/rudeus/
|
COPY ./server/quests/helloworld/home /home/rudeus/
|
||||||
|
|
||||||
|
COPY ./packages/cli/cli.js /usr/local/bin/cli.js
|
||||||
|
|
||||||
CMD [ "/bin/bash" ]
|
CMD [ "/bin/bash" ]
|
||||||
@@ -2,26 +2,20 @@
|
|||||||
preexec() {
|
preexec() {
|
||||||
[ -n "$COMP_LINE" ] && return # do nothing if completing
|
[ -n "$COMP_LINE" ] && return # do nothing if completing
|
||||||
[ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # do nothing if completing
|
[ "$BASH_COMMAND" = "$PROMPT_COMMAND" ] && return # do nothing if completing
|
||||||
local command="$BASH_COMMAND"
|
export COMMAND="$BASH_COMMAND"
|
||||||
local pwd="$PWD"
|
|
||||||
|
|
||||||
if [[ $command =~ ^(vim|top|less|more|nano) ]]; then
|
if [[ $COMMAND =~ ^(vim|top|less|more|nano) ]]; then
|
||||||
local payload=$(printf '{"token": "%s", "pwd": "%s", "command": "%s"}' "$TOKEN" "$pwd" "$command")
|
node /usr/local/bin/cli.js
|
||||||
curl -X POST $API_ENDPOINT/api/v1/commands -H 'accept: */*' -H 'Content-Type: application/json' -d "$payload"
|
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Execute the command, capture output and exit code
|
# Execute the command, capture output and exit code
|
||||||
local output=$( { eval $command 2>&1; echo $? > /tmp/exit_code; })
|
export OUTPUT=$( { eval $COMMAND 2>&1; echo $? > /tmp/exit_code; })
|
||||||
local exit_code=$(cat /tmp/exit_code)
|
export EXIT_CODE=$(cat /tmp/exit_code)
|
||||||
|
|
||||||
local output_esc=$(echo $output | jq -Rs .)
|
echo $OUTPUT
|
||||||
|
|
||||||
# Store command in variable
|
|
||||||
local payload=$(printf '{"token": "%s", "pwd": "%s", "command": "%s", "exit_code": "%s", "output": %s}' "$TOKEN" "$pwd" "$command" "$exit_code" "$output_esc")
|
|
||||||
|
|
||||||
# Send command to the API
|
# Send command to the API
|
||||||
curl -X POST $API_ENDPOINT/api/v1/commands -H 'accept: */*' -H 'Content-Type: application/json' -d "$payload" || echo $payload
|
node /usr/local/bin/cli.js
|
||||||
|
|
||||||
BASH_COMMAND=""
|
BASH_COMMAND=""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import config from '../config.js'
|
|||||||
|
|
||||||
const engine = new Docker()
|
const engine = new Docker()
|
||||||
|
|
||||||
const questPath = '/home/zeko/src/linux-odyssey/server/quests'
|
const projectPath = '/home/zeko/src/linux-odyssey'
|
||||||
|
|
||||||
const containerOptions = {
|
const containerOptions = {
|
||||||
Image: 'lancatlin/linux-odyssey:helloworld',
|
Image: 'lancatlin/linux-odyssey:helloworld',
|
||||||
@@ -17,7 +17,10 @@ const containerOptions = {
|
|||||||
HostConfig: {
|
HostConfig: {
|
||||||
Binds: config.isProduction
|
Binds: config.isProduction
|
||||||
? []
|
? []
|
||||||
: [`${questPath}/helloworld/home:/home/rudeus`],
|
: [
|
||||||
|
`${projectPath}/server/quests/helloworld/home:/home/rudeus`,
|
||||||
|
`${projectPath}/packages/cli/cli.js:/usr/local/bin/cli.js`,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user