diff --git a/apps/daemon/src/session/create.ts b/apps/daemon/src/session/create.ts index 23bb2a5..a42b035 100644 --- a/apps/daemon/src/session/create.ts +++ b/apps/daemon/src/session/create.ts @@ -5,7 +5,7 @@ import { docker } from "~/lib/docker.js"; export default async function createSession({ workspace, user, - environment, + environment = {}, offline, exposePorts, memory, @@ -18,7 +18,7 @@ export default async function createSession({ memory?: number; }) { const config = getConfig(); - const envArray = Object.entries(environment || { STARDUST_USER: user }).map(([key, value]) => `${key}=${value}`); + const envArray = Object.entries(environment).map(([key, value]) => `${key}=${value}`); const container = await docker.createContainer({ name: `stardust-session-${workspace.replaceAll("/", "_")}-${Buffer.from(randomBytes(4)).toString("hex")}`, Image: workspace, @@ -29,7 +29,7 @@ export default async function createSession({ Dns: config.dnsServers, Memory: memory, }, - Env: envArray, + Env: [`STARDUST_USER=${user}`, ...envArray], NetworkDisabled: offline || false, ExposedPorts: exposePorts ? Object.fromEntries(exposePorts.map((e) => [e, {}])) : undefined, // world class types by docker }); diff --git a/apps/daemon/src/session/file.ts b/apps/daemon/src/session/file.ts index 1fbfa31..d30895d 100644 --- a/apps/daemon/src/session/file.ts +++ b/apps/daemon/src/session/file.ts @@ -1,18 +1,18 @@ import { docker } from "~/lib/docker.js"; -export async function sendFile(id: string, name: string, file: Buffer) { +export async function sendFile(id: string, name: string, file: Uint8Array) { const container = docker.getContainer(id); const payload = Buffer.from(Bun.gzipSync(file)); await container.putArchive(payload, `/home/stardust/Uploads/${name}.gz`); await container.exec({ - Cmd: ["gunzip", `/home/stardust/Uploads/${name}.gz`], + Cmd: ["sh", "-c", "gunzip", `/home/stardust/Uploads/${name}.gz`], }); return true; } export async function getFile(id: string, name: string) { const file = await new Promise((res, rej) => - docker.getContainer(id).getArchive(name, (err, data) => { + docker.getContainer(id).getArchive(`/home/stardust/Downloads/${name}`, (err, data) => { if (err) rej(err); res(data); }), diff --git a/apps/daemon/src/session/index.ts b/apps/daemon/src/session/index.ts index 80ccbe2..85d91b4 100644 --- a/apps/daemon/src/session/index.ts +++ b/apps/daemon/src/session/index.ts @@ -5,6 +5,7 @@ import createSession from "./create.js"; import deleteSession from "./delete.js"; import { getFile, sendFile } from "./file.js"; import manageSession from "./manage.js"; +import screenshot from "./screenshot.js"; // fill this export default new Elysia({ prefix: "/sessions" }) .put( @@ -64,16 +65,45 @@ export default new Elysia({ prefix: "/sessions" }) await deleteSession(id); return { success: true }; }) + .get("/:id/screenshot", async ({ params: { id }, set }) => { + try { + const res = await screenshot(id); + set.headers["Content-Type"] = "image/png"; + return res; + } catch (e) { + set.status = 500; + return { + success: false, + error: e, + }; + } + }) .group("/:id/files", (app) => app - .get("/list", () => { - return true; // do this later (I HATE DOCKER) + .get("/list", async ({ params: { id } }) => { + const exec = await docker.getContainer(id).exec({ + Cmd: ["sh", "-c", "ls /home/stardust/Downloads"], + AttachStdout: true, + AttachStderr: true, + }); + + const stream = await exec.start({ hijack: true, stdin: true }); + const data = await new Promise((res, err) => { + const out: string[] = []; + stream.on("error", err); + stream.on("data", (chunk) => out.push(chunk.toString())); + stream.on("end", () => res(out.join(""))); + }); + return { + success: true, + data: data.split("\n").filter(Boolean), + }; }) .get("/download/:name", async ({ params: { id, name } }) => getFile(id, name)) .put( "/upload/:name", async ({ params: { id, name }, body }) => { - const res = await sendFile(id, name, Buffer.from(body)); + const res = await sendFile(id, name, body); return { success: res, }; diff --git a/apps/daemon/src/session/screenshot.ts b/apps/daemon/src/session/screenshot.ts new file mode 100644 index 0000000..fb994c4 --- /dev/null +++ b/apps/daemon/src/session/screenshot.ts @@ -0,0 +1,19 @@ +import { docker } from "~/lib/docker.js"; +export default async function screenshot(id: string) { + const container = docker.getContainer(id); + const exec = await container.exec({ + Cmd: ["sh", "-c", "xwd -root | convert xwd:- png:- | base64"], + AttachStdout: true, + AttachStderr: true, + }); + + const stream = await exec.start({ hijack: true, stdin: true }); + const encoded = await new Promise((res, err) => { + const out: string[] = []; + stream.on("error", err); + stream.on("data", (chunk) => out.push(chunk.toString())); + stream.on("end", () => res(out.join(""))); + }); + const file = Buffer.from(encoded, "base64"); + return file; +}