Skip to content

Instantly share code, notes, and snippets.

@bitnetwork
Last active July 8, 2023 21:09
Show Gist options
  • Save bitnetwork/26b3916a0078fa85d3e9aa24df658dfe to your computer and use it in GitHub Desktop.
Save bitnetwork/26b3916a0078fa85d3e9aa24df658dfe to your computer and use it in GitHub Desktop.
A telnet server written in Node.js
var lib_net = require("net");
var lib_chalk = require("chalk");
var clients = {};
var lastId = -1;
function cleanInput(data) {
return data.toString().replace(/(\r\n|\n|\r)/gm,"");
}
function clipText(text, seperator, delimiter) {
var output = "";
for (var i=0; i<text.length; i+=seperator) {
output += text.substring(i, i + seperator) + delimiter;
}
output = output.substring(0, output.length - delimiter.length);
return output;
}
function redraw(display) {
var output = "";
for (var i=0; i<display.length; i++) {
output += "\r\n" + display[i].join("");
}
return output;
}
function clear(lines) {
return "\r\n".repeat(lines || 40);
}
function socketHandler(socket) {
// Figure out how to stop linemode & echo by default.
lastId++;
clients[lastId] = {socket: socket};
var id = lastId;
var mode = "title";
var display = [];
for (var i=0; i<20; i++) {
display[i] = [];
for (var j=0; j<80; j++) {
display[i][j] = " ";
}
}
/*
╔══════════════════════════════════════════════════════════════════════════════╗
β•‘ ___ _ _ ___ ___ ___ β•‘
β•‘ | _ |_) |_ | _ ) _ ) __| Server: Bit BBS β•‘
β•‘ | _ \ | _| | _ \ _ \__ \ Client: XXX.XXX.XXX.XXX β•‘
β•‘ |___/_|\__| |___/___/___/ Timestamp: hh:mm:ss DD/MM/YYYY β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ Welcome to the Bit BBS server! Do note that your client should be in β•‘
β•‘ character mode, that is where keystrokes are sent to the server directly. If β•‘
β•‘ your client is not in this mode, do try `mode character` in your client's β•‘
β•‘ terminal with the escape character, or if you are using a client with a GUI, β•‘
β•‘ try looking in the connection configuration. A color enabled terminal is β•‘
β•‘ also required to use the board. Type / for the command menu at any time. β•‘
β•‘ β•‘
β•‘ Press any key to continue... β•‘
β•‘ β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
*/
display = [ "╔══════════════════════════════════════════════════════════════════════════════╗".split(""),
"β•‘ ___ _ _ ___ ___ ___ β•‘".split(""),
"β•‘ | _ |_) |_ | _ ) _ ) __| Server: Bit BBS β•‘".split(""),
"β•‘ | _ \\ | _| | _ \\ _ \\__ \\ Client: XXX.XXX.XXX.XXX β•‘".split(""),
"β•‘ |___/_|\\__| |___/___/___/ Timestamp: hh:mm:ss DD/MM/YYYY β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ Welcome to the Bit BBS server! Do note that your client should be in β•‘".split(""),
"β•‘ character mode, that is where keystrokes are sent to the server directly. If β•‘".split(""),
"β•‘ your client is not in this mode, do try `mode character` in your client's β•‘".split(""),
"β•‘ terminal with the escape character, or if you are using a client with a GUI, β•‘".split(""),
"β•‘ try looking in the connection configuration. A color enabled terminal is β•‘".split(""),
"β•‘ also required to use the board. Type / for the command menu at any time. β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ Press any key to continue... β•‘".split(""),
"β•‘ β•‘".split(""),
"β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•".split("")
];
var now = new Date();
var formatedNow = (now.getHours()).toString().length === 1 ? "0" + (now.getHours()) : (now.getHours()).toString();
formatedNow += ":" + ((now.getMinutes()).toString().length === 1 ? "0" + (now.getMinutes()) : (now.getMinutes()).toString());
formatedNow += ":" + ((now.getSeconds()).toString().length === 1 ? "0" + (now.getSeconds()) : (now.getSeconds()).toString());
formatedNow += " " + ((now.getDate()).toString().length === 1 ? "0" + (now.getDate()) : (now.getDate()).toString());
formatedNow += "/" + ((now.getMonth() + 1).toString().length === 1 ? "0" + (now.getMonth() + 1) : (now.getMonth() + 1).toString());
formatedNow += "/" + (now.getFullYear());
// Client address
for (var i=0; i<15; i++) {
display[3][54 + i] = socket.remoteAddress.toString()[i] || " ";
}
// Timestamp
for (var i=0; i<19; i++) {
display[4][57 + i] = formatedNow[i] || " ";
}
socket.write(clear());
socket.write(redraw(display));
mode = "title_continue";
var typing = "";
function switchMode(mode) {
switch (mode) {
case "slash":
/*
╔══════════════════════════════════════════════════════════════════════════════╗
β•‘ Bit BBS // Guest // XXX.XXX.XXX.XXX // hh:mm:ss DD/MM/YYYY β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ Slash > / β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
*/
display[18] = "β•‘ Slash > / β•‘".split("");
// Color
for (var i=0; i<78; i++) {
display[18][i + 1] = lib_chalk.bgRed(display[18][i + 1]);
}
socket.write(clear());
socket.write(redraw(display));
break;
case "main":
/*
╔══════════════════════════════════════════════════════════════════════════════╗
β•‘ Bit BBS // Guest // XXX.XXX.XXX.XXX // hh:mm:ss DD/MM/YYYY β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•‘ β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
*/
display = [ "╔══════════════════════════════════════════════════════════════════════════════╗".split(""),
"β•‘ Bit BBS // Guest // XXX.XXX.XXX.XXX // hh:mm:ss DD/MM/YYYY β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•‘ β•‘".split(""),
"β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•".split("")
];
var now = new Date();
var formatedNow = (now.getHours()).toString().length === 1 ? "0" + (now.getHours()) : (now.getHours()).toString();
formatedNow += ":" + ((now.getMinutes()).toString().length === 1 ? "0" + (now.getMinutes()) : (now.getMinutes()).toString());
formatedNow += ":" + ((now.getSeconds()).toString().length === 1 ? "0" + (now.getSeconds()) : (now.getSeconds()).toString());
formatedNow += " " + ((now.getDate()).toString().length === 1 ? "0" + (now.getDate()) : (now.getDate()).toString());
formatedNow += "/" + ((now.getMonth() + 1).toString().length === 1 ? "0" + (now.getMonth() + 1) : (now.getMonth() + 1).toString());
formatedNow += "/" + (now.getFullYear());
// Client address
for (var i=0; i<15; i++) {
display[1][37 + i] = socket.remoteAddress.toString()[i] || " ";
}
// Timestamp
for (var i=0; i<19; i++) {
display[1][58 + i] = formatedNow[i] || " ";
}
// Color
for (var i=0; i<78; i++) {
display[1][i + 1] = lib_chalk.bgGreen(display[1][i + 1]);
}
socket.write(clear());
socket.write(redraw(display));
break;
}
}
socket.on("data", function(data) {
var char = new Buffer(data).toString("base64");
console.log( data + " || " + (new Buffer(data).toString().charCodeAt(0)) + " (" + data.length + ") @ " + mode + " ==> " + char );
if (char === "//0D//0B") {
return;
}
if (char === "Lw==" && (mode !== "title" && mode !== "title_continue" && mode !== "slash")) {
mode = "slash";
switchMode("slash");
return;
}
switch (mode) {
case "slash":
if (char === "Gw==" || char === "Lw==") {
mode = "main";
switchMode("main");
break;
}
break;
case "title_continue":
mode = "main";
switchMode("main");
break;
case "main":
switchMode("main");
break;
}
});
socket.on("end", function() {
clients[id].socket.end();
delete clients[id];
});
}
var server = lib_net.createServer(socketHandler);
server.listen(8023);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment