260 lines
7.4 KiB
TypeScript
260 lines
7.4 KiB
TypeScript
|
|
import { Server, type ServerChannel } from "ssh2";
|
||
|
|
import Front, { newLine } from "./front";
|
||
|
|
|
||
|
|
import { eraseScreen, cursorTo, cursorHide, cursorShow } from "ansi-escapes";
|
||
|
|
import ContactForm from "./contact/ContactForm";
|
||
|
|
|
||
|
|
const inputCodes = {
|
||
|
|
int8: {
|
||
|
|
backspace: 127,
|
||
|
|
tab: 9,
|
||
|
|
enter: 13,
|
||
|
|
space: 32,
|
||
|
|
escape: 27,
|
||
|
|
ctrlC: 3,
|
||
|
|
a: 97,
|
||
|
|
p: 112,
|
||
|
|
c: 99,
|
||
|
|
q: 113,
|
||
|
|
},
|
||
|
|
base64: {
|
||
|
|
arrows: {
|
||
|
|
up: "G1tB",
|
||
|
|
down: "G1tC",
|
||
|
|
right: "G1tD",
|
||
|
|
left: "G1tE",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
};
|
||
|
|
|
||
|
|
const server = new Server(
|
||
|
|
{
|
||
|
|
hostKeys: [await Bun.file("./host.key").text()],
|
||
|
|
ident: "portfolio.sh",
|
||
|
|
},
|
||
|
|
(client) => {
|
||
|
|
console.log("Client connected!");
|
||
|
|
|
||
|
|
const userSpecs: {
|
||
|
|
userName?: string;
|
||
|
|
} = {};
|
||
|
|
|
||
|
|
client
|
||
|
|
.on("authentication", (ctx) => {
|
||
|
|
userSpecs.userName = ctx.username;
|
||
|
|
ctx.accept(); // On accepte toutes les connexions
|
||
|
|
})
|
||
|
|
.on("ready", () => {
|
||
|
|
client.on("session", (accept) => {
|
||
|
|
const session = accept();
|
||
|
|
|
||
|
|
const userWindow: {
|
||
|
|
columns: number;
|
||
|
|
rows: number;
|
||
|
|
selectedTab: "About" | "Projects" | "Contact";
|
||
|
|
stream: ServerChannel | null;
|
||
|
|
contactFormData: {
|
||
|
|
name: string;
|
||
|
|
email: string;
|
||
|
|
message: string;
|
||
|
|
};
|
||
|
|
contactFormSelectedField: "name" | "email" | "message" | "submit";
|
||
|
|
} = {
|
||
|
|
columns: 80,
|
||
|
|
rows: 24,
|
||
|
|
selectedTab: "About",
|
||
|
|
stream: null,
|
||
|
|
contactFormData: {
|
||
|
|
name: "",
|
||
|
|
email: "",
|
||
|
|
message: "",
|
||
|
|
},
|
||
|
|
contactFormSelectedField: "name",
|
||
|
|
};
|
||
|
|
|
||
|
|
const render = () => {
|
||
|
|
userWindow.stream?.write(eraseScreen);
|
||
|
|
userWindow.stream?.write(cursorTo(0, 0));
|
||
|
|
userWindow.stream?.write(cursorHide);
|
||
|
|
if (userSpecs.userName === "contact") {
|
||
|
|
userWindow.stream?.write(ContactForm(userWindow));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
userWindow.stream?.write(Front(userWindow));
|
||
|
|
};
|
||
|
|
|
||
|
|
session.on("pty", (accept, reject, info) => {
|
||
|
|
console.log(info);
|
||
|
|
userWindow.columns = info.cols;
|
||
|
|
userWindow.rows = info.rows;
|
||
|
|
accept();
|
||
|
|
});
|
||
|
|
|
||
|
|
session.on("window-change", (_accept, _reject, info) => {
|
||
|
|
console.log(info);
|
||
|
|
userWindow.columns = info.cols;
|
||
|
|
userWindow.rows = info.rows;
|
||
|
|
render();
|
||
|
|
});
|
||
|
|
|
||
|
|
session.on("shell", (accept) => {
|
||
|
|
const stream = accept();
|
||
|
|
|
||
|
|
// stream.write(`
|
||
|
|
// 🔥 Welcome to My Portfolio CLI 🔥
|
||
|
|
// ------------------------------
|
||
|
|
// Commands: about | projects | contact | exit
|
||
|
|
|
||
|
|
// `);
|
||
|
|
|
||
|
|
userWindow.stream = stream;
|
||
|
|
|
||
|
|
render();
|
||
|
|
|
||
|
|
stream.on("data", (data: Buffer) => {
|
||
|
|
const cmd = data.toString();
|
||
|
|
const cmdAsInt = data.readInt8();
|
||
|
|
|
||
|
|
if (
|
||
|
|
cmdAsInt == inputCodes.int8.ctrlC ||
|
||
|
|
(cmdAsInt === inputCodes.int8.q && userSpecs.userName !== "contact")
|
||
|
|
) {
|
||
|
|
userWindow.stream?.write(eraseScreen);
|
||
|
|
userWindow.stream?.write(cursorTo(0, 0));
|
||
|
|
stream.write("Goodbye!\n");
|
||
|
|
stream.write(cursorShow);
|
||
|
|
stream.close();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (userSpecs.userName === "contact") {
|
||
|
|
console.log(cmdAsInt);
|
||
|
|
if (cmdAsInt == inputCodes.int8.tab) {
|
||
|
|
if (userWindow.contactFormSelectedField === "name") {
|
||
|
|
userWindow.contactFormSelectedField = "email";
|
||
|
|
} else if (userWindow.contactFormSelectedField === "email") {
|
||
|
|
userWindow.contactFormSelectedField = "message";
|
||
|
|
} else if (userWindow.contactFormSelectedField === "message") {
|
||
|
|
userWindow.contactFormSelectedField = "submit";
|
||
|
|
} else if (userWindow.contactFormSelectedField === "submit") {
|
||
|
|
userWindow.contactFormSelectedField = "name";
|
||
|
|
}
|
||
|
|
render();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (cmdAsInt == inputCodes.int8.backspace) {
|
||
|
|
if (userWindow.contactFormSelectedField === "name") {
|
||
|
|
userWindow.contactFormData.name = userWindow.contactFormData.name.slice(0, -1);
|
||
|
|
} else if (userWindow.contactFormSelectedField === "email") {
|
||
|
|
userWindow.contactFormData.email = userWindow.contactFormData.email.slice(
|
||
|
|
0,
|
||
|
|
-1
|
||
|
|
);
|
||
|
|
} else if (userWindow.contactFormSelectedField === "message") {
|
||
|
|
userWindow.contactFormData.message = userWindow.contactFormData.message.slice(
|
||
|
|
0,
|
||
|
|
-1
|
||
|
|
);
|
||
|
|
}
|
||
|
|
render();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (cmdAsInt == inputCodes.int8.space) {
|
||
|
|
if (userWindow.contactFormSelectedField === "name") {
|
||
|
|
userWindow.contactFormData.name += " ";
|
||
|
|
} else if (userWindow.contactFormSelectedField === "email") {
|
||
|
|
userWindow.contactFormData.email += " ";
|
||
|
|
} else if (userWindow.contactFormSelectedField === "message") {
|
||
|
|
userWindow.contactFormData.message += " ";
|
||
|
|
}
|
||
|
|
render();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (cmdAsInt == inputCodes.int8.enter) {
|
||
|
|
if (userWindow.contactFormSelectedField === "message") {
|
||
|
|
userWindow.contactFormData.message += newLine;
|
||
|
|
} else if (userWindow.contactFormSelectedField === "submit") {
|
||
|
|
const webhookUrl =
|
||
|
|
"https://discord.com/api/webhooks/1349123668914999361/2rvvgNNRyzgGpKFJ0JLnT-PbkbM-phyQZwTxRBkxDWSA_9SybsP2eILbxsegthsWsu8d";
|
||
|
|
const messageData = {
|
||
|
|
content: `<@323206956640763916>\nName: ${
|
||
|
|
userWindow.contactFormData.name
|
||
|
|
}\nEmail: ${
|
||
|
|
userWindow.contactFormData.email
|
||
|
|
}\nMessage: ${userWindow.contactFormData.message.replace(newLine, "\n")}`,
|
||
|
|
};
|
||
|
|
|
||
|
|
fetch(webhookUrl, {
|
||
|
|
method: "POST",
|
||
|
|
headers: {
|
||
|
|
"Content-Type": "application/json",
|
||
|
|
},
|
||
|
|
body: JSON.stringify(messageData),
|
||
|
|
})
|
||
|
|
.then((response) => {
|
||
|
|
if (!response.ok) {
|
||
|
|
throw new Error("Failed to send message to Discord webhook");
|
||
|
|
}
|
||
|
|
console.log("Message sent to Discord webhook successfully");
|
||
|
|
})
|
||
|
|
.catch((error) => {
|
||
|
|
console.error("Error sending message to Discord webhook:", error);
|
||
|
|
});
|
||
|
|
userWindow.stream?.write(eraseScreen);
|
||
|
|
userWindow.stream?.write(cursorTo(0, 0));
|
||
|
|
stream.write(cursorShow);
|
||
|
|
userWindow.stream?.write("Message sent!\n");
|
||
|
|
stream.close();
|
||
|
|
}
|
||
|
|
render();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (
|
||
|
|
cmdAsInt != inputCodes.int8.backspace &&
|
||
|
|
cmdAsInt != inputCodes.int8.escape &&
|
||
|
|
cmdAsInt != inputCodes.int8.tab &&
|
||
|
|
cmdAsInt != inputCodes.int8.space &&
|
||
|
|
cmdAsInt != inputCodes.int8.enter
|
||
|
|
) {
|
||
|
|
if (userWindow.contactFormSelectedField === "name") {
|
||
|
|
userWindow.contactFormData.name += cmd.trim();
|
||
|
|
} else if (userWindow.contactFormSelectedField === "email") {
|
||
|
|
userWindow.contactFormData.email += cmd.trim();
|
||
|
|
} else if (userWindow.contactFormSelectedField === "message") {
|
||
|
|
userWindow.contactFormData.message += cmd.trim();
|
||
|
|
}
|
||
|
|
render();
|
||
|
|
}
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log(cmd);
|
||
|
|
|
||
|
|
switch (cmdAsInt) {
|
||
|
|
case inputCodes.int8.a:
|
||
|
|
userWindow.selectedTab = "About";
|
||
|
|
render();
|
||
|
|
break;
|
||
|
|
case inputCodes.int8.p:
|
||
|
|
userWindow.selectedTab = "Projects";
|
||
|
|
render();
|
||
|
|
break;
|
||
|
|
case inputCodes.int8.c:
|
||
|
|
userWindow.selectedTab = "Contact";
|
||
|
|
render();
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
client.on("end", () => {
|
||
|
|
console.log("Client disconnected");
|
||
|
|
});
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
server.listen(2222, "0.0.0.0", () => {
|
||
|
|
console.log("🚀 SSH server running on port 2222");
|
||
|
|
});
|