Skip to content

Commit

Permalink
feat(daemon): screenshot endpoint and fixed exec
Browse files Browse the repository at this point in the history
Co-authored-by: IncognitoTGT <[email protected]>
  • Loading branch information
truekas and IncognitoTGT committed Jan 9, 2025
1 parent 21a448c commit 71c8a2c
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 9 deletions.
6 changes: 3 additions & 3 deletions apps/daemon/src/session/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { docker } from "~/lib/docker.js";
export default async function createSession({
workspace,
user,
environment,
environment = {},
offline,
exposePorts,
memory,
Expand All @@ -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,
Expand All @@ -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
});
Expand Down
6 changes: 3 additions & 3 deletions apps/daemon/src/session/file.ts
Original file line number Diff line number Diff line change
@@ -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<NodeJS.ReadableStream | undefined>((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);
}),
Expand Down
36 changes: 33 additions & 3 deletions apps/daemon/src/session/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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<string>((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,
};
Expand Down
19 changes: 19 additions & 0 deletions apps/daemon/src/session/screenshot.ts
Original file line number Diff line number Diff line change
@@ -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<string>((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;
}

0 comments on commit 71c8a2c

Please sign in to comment.