forked from cory/tildefriends
316 lines
8.2 KiB
JavaScript
316 lines
8.2 KiB
JavaScript
|
"use strict";
|
||
|
var gOnInput = null;
|
||
|
|
||
|
var kMaxHistory = 20;
|
||
|
var kShowHistory = 20;
|
||
|
|
||
|
var lastTimestamp = null;
|
||
|
|
||
|
if (imports.terminal) {
|
||
|
core.register("onMessage", function(sender, message) {
|
||
|
if (message.message && message.when) {
|
||
|
printMessage(message, true);
|
||
|
}
|
||
|
});
|
||
|
core.register("onSessionBegin", function(user) {
|
||
|
if (user.packageName === core.user.packageName &&
|
||
|
user.index !== core.user.index) {
|
||
|
listUsers(user.name + " has joined the BBS. ");
|
||
|
}
|
||
|
});
|
||
|
core.register("onSessionEnd", function(user) {
|
||
|
if (user.packageName === core.user.packageName &&
|
||
|
user.index !== core.user.index) {
|
||
|
listUsers(user.name + " has left the BBS. ");
|
||
|
}
|
||
|
});
|
||
|
} else {
|
||
|
// Chat service process.
|
||
|
core.register("onMessage", function(sender, message) {
|
||
|
if (message.message && message.when) {
|
||
|
message.sender = sender;
|
||
|
return database.get("board").catch(function() {
|
||
|
return null;
|
||
|
}).then(function(data) {
|
||
|
try {
|
||
|
data = JSON.parse(data);
|
||
|
} catch(error) {
|
||
|
data = [];
|
||
|
}
|
||
|
data.push(message);
|
||
|
while (data.length > kMaxHistory) {
|
||
|
data.shift();
|
||
|
}
|
||
|
return saveBoard(data);
|
||
|
}).then(function() {
|
||
|
return core.broadcast(message);
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function listUsers() {
|
||
|
return core.getUsers(core.user.packageOwner, core.user.packageName).then(function(users) {
|
||
|
terminal.select("users");
|
||
|
terminal.clear();
|
||
|
terminal.print("Users:");
|
||
|
var counts = {};
|
||
|
for (var i = 0; i < users.length; i++) {
|
||
|
counts[users[i].name] = (counts[users[i].name] || 0) + 1;
|
||
|
}
|
||
|
var names = Object.keys(counts).sort();
|
||
|
for (var i = 0; i < names.length; i++) {
|
||
|
var name = names[i];
|
||
|
var message = [];
|
||
|
if (message.length > 1) {
|
||
|
message.push(", ");
|
||
|
}
|
||
|
message.push({class: "orange", value: name});
|
||
|
if (counts[name] > 1) {
|
||
|
message.push({class: "base01", value: "(x" + counts[name] + ")"});
|
||
|
}
|
||
|
terminal.print(message);
|
||
|
}
|
||
|
terminal.select("terminal");
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function saveBoard(data) {
|
||
|
return database.set("board", JSON.stringify(data)).catch(function(error) {
|
||
|
if (error.message.indexOf("MDB_MAP_FULL") != -1) {
|
||
|
data.shift();
|
||
|
return saveBoard(data);
|
||
|
} else {
|
||
|
throw error;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
core.register("onInput", function(input) {
|
||
|
if (gOnInput && typeof input == "string") {
|
||
|
gOnInput(input);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
function logo() {
|
||
|
terminal.clear();
|
||
|
terminal.print("");
|
||
|
terminal.print("");
|
||
|
terminal.print('Welcome to');
|
||
|
terminal.print(' ______ _ ____ ____ _____');
|
||
|
terminal.print(' / ____/___ _______ _( )_____ / __ )/ __ ) ___/');
|
||
|
terminal.print(' / / / __ \\/ ___/ / / /// ___/ / __ / __ \\__ \\ ');
|
||
|
terminal.print('/ /___/ /_/ / / / /_/ / (__ ) / /_/ / /_/ /__/ / ');
|
||
|
terminal.print('\\____/\\____/_/ \\__, / /____/ /_____/_____/____/ ');
|
||
|
terminal.print(' /____/ ');
|
||
|
terminal.print(' yesterday\'s technology...today!');
|
||
|
terminal.print("");
|
||
|
}
|
||
|
|
||
|
function welcome() {
|
||
|
logo();
|
||
|
chat();
|
||
|
}
|
||
|
|
||
|
function main() {
|
||
|
terminal.clear();
|
||
|
logo();
|
||
|
terminal.print("");
|
||
|
terminal.print("Main menu commands:");
|
||
|
terminal.print(" ", {command: "chat"}, " chat message board");
|
||
|
terminal.print(" ", {command: "guess"}, " guess the number game");
|
||
|
terminal.print(" ", {command: "exit"}, " back to that sweet logo");
|
||
|
gOnInput = function(input) {
|
||
|
input = input.toLowerCase();
|
||
|
if (input == "chat") {
|
||
|
chat();
|
||
|
} else if (input == "guess") {
|
||
|
guess();
|
||
|
} else if (input == "exit") {
|
||
|
terminal.print("Goodbye.");
|
||
|
exit(0);
|
||
|
} else {
|
||
|
terminal.print("I didn't understand that: " + input);
|
||
|
main();
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function formatMessage(message) {
|
||
|
var result;
|
||
|
if (typeof message == "string") {
|
||
|
result = [];
|
||
|
var regex = /(\w+:\/*\S+?)(?=(?:[\.!?])?(?:$|\s))/gi;
|
||
|
var match;
|
||
|
var lastIndex = 0;
|
||
|
while ((match = regex.exec(message)) !== null) {
|
||
|
result.push({class: "base1", value: message.substring(lastIndex, match.index)});
|
||
|
result.push({href: match[0]});
|
||
|
lastIndex = regex.lastIndex;
|
||
|
}
|
||
|
result.push({class: "base1", value: message.substring(lastIndex)});
|
||
|
} else {
|
||
|
result = message;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
function niceTime(lastTime, thisTime) {
|
||
|
if (!lastTime) {
|
||
|
return thisTime;
|
||
|
}
|
||
|
let result = [];
|
||
|
let lastParts = lastTime.split(" ");
|
||
|
let thisParts = thisTime.split(" ");
|
||
|
for (let i = 0; i < thisParts.length; i++) {
|
||
|
if (thisParts[i] !== lastParts[i]) {
|
||
|
result.push(thisParts[i]);
|
||
|
}
|
||
|
}
|
||
|
return result.join(" ");
|
||
|
}
|
||
|
|
||
|
function printMessage(message, notify) {
|
||
|
terminal.print(
|
||
|
{class: "base0", value: niceTime(lastTimestamp, message.when)},
|
||
|
" ",
|
||
|
{class: "base00", value: "<"},
|
||
|
{class: "base3", value: (message.sender ? message.sender.name : "unknown")},
|
||
|
{class: "base00", value: ">"},
|
||
|
" ",
|
||
|
formatMessage(message.message));
|
||
|
lastTimestamp = message.when;
|
||
|
if (notify) {
|
||
|
return core.getUser().then(function(user) {
|
||
|
if (message.message.indexOf("!") != -1) {
|
||
|
return terminal.notify("SOMEONE IS SHOUTING!", {body: "<" + (message.sender ? message.sender.name : "unknown") + "> " + message.message});
|
||
|
} else if (message.message.indexOf(user.name + ":") != -1) {
|
||
|
return terminal.notify("Someone is talking at you.", {body: "<" + (message.sender ? message.sender.name : "unknown") + "> " + message.message});
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function chat() {
|
||
|
terminal.setEcho(false);
|
||
|
terminal.print("");
|
||
|
terminal.print("You are now in a chat. Anything you type will be broadcast to everyone else connected. To leave, say ", {command: "exit"}, ".");
|
||
|
listUsers();
|
||
|
database.get("board").catch(function() {
|
||
|
return null;
|
||
|
}).then(function(board) {
|
||
|
try {
|
||
|
board = JSON.parse(board);
|
||
|
} catch (error) {
|
||
|
board = [];
|
||
|
}
|
||
|
|
||
|
for (let i = Math.max(0, board.length - kShowHistory); i < board.length; i++) {
|
||
|
printMessage(board[i], false);
|
||
|
}
|
||
|
});
|
||
|
gOnInput = function(input) {
|
||
|
if (input == "exit") {
|
||
|
terminal.setEcho(true);
|
||
|
main();
|
||
|
} else {
|
||
|
core.getService("chat").then(function(chatService) {
|
||
|
return chatService.postMessage({when: new Date().toString(), message: input});
|
||
|
}).catch(function(error) {
|
||
|
terminal.print("ERROR: " + JSON.stringify(error));
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function guess() {
|
||
|
terminal.clear();
|
||
|
var number = Math.round(Math.random() * 100);
|
||
|
var guesses = 0;
|
||
|
terminal.print("OK, I have a number in mind. What do you think it is? Use ", {command: "exit"}, " to stop.");
|
||
|
gOnInput = function(input) {
|
||
|
if (input == "exit") {
|
||
|
main();
|
||
|
} else {
|
||
|
var guess = parseInt(input);
|
||
|
guesses++;
|
||
|
if (input != guess.toString()) {
|
||
|
terminal.print("I'm not sure that's an integer. Please guess only integers.");
|
||
|
} else {
|
||
|
if (guess < number) {
|
||
|
terminal.print("Too low.");
|
||
|
} else if (guess > number) {
|
||
|
terminal.print("Too high.");
|
||
|
} else if (guess == number) {
|
||
|
terminal.print("Wow, you got it in " + guesses + " guesses! It was " + number + ".");
|
||
|
guessEnd(guesses);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function guessEnd(guesses) {
|
||
|
terminal.print("What's your name, for the high score table?");
|
||
|
gOnInput = function(name) {
|
||
|
var entry = {'guesses': guesses, 'name': name, 'when': new Date().toString()};
|
||
|
database.get("guessHighScores").then(function(data) {
|
||
|
data = JSON.parse(data);
|
||
|
var index = data.length;
|
||
|
for (var i in data) {
|
||
|
if (guesses < data[i].guesses) {
|
||
|
index = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
data.splice(index, 0, entry);
|
||
|
printHighScores(data);
|
||
|
database.set("guessHighScores", JSON.stringify(data));
|
||
|
gOnInput = function() {
|
||
|
main();
|
||
|
};
|
||
|
}).catch(function() {
|
||
|
var data = [entry];
|
||
|
printHighScores(data);
|
||
|
database.set("guessHighScores", JSON.stringify(data));
|
||
|
main();
|
||
|
});
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function printTable(data) {
|
||
|
var widths = [];
|
||
|
for (var i in data) {
|
||
|
var row = data[i];
|
||
|
for (var c in row) {
|
||
|
widths[c] = Math.max(widths[c] || 0, row[c].length);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (var i in data) {
|
||
|
var row = data[i];
|
||
|
var line = "";
|
||
|
for (var c in row) {
|
||
|
line += row[c];
|
||
|
line += " ".repeat(widths[c] - row[c].length + 2);
|
||
|
}
|
||
|
terminal.print(line);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function printHighScores(data) {
|
||
|
printTable([["Name", "Guesses", "Date"]].concat(data.map(function(entry) {
|
||
|
return [entry.name, entry.guesses.toString(), entry.when];
|
||
|
})));
|
||
|
}
|
||
|
|
||
|
if (imports.terminal) {
|
||
|
terminal.split([
|
||
|
{type: "horizontal", children: [
|
||
|
{name: "terminal", grow: 1},
|
||
|
{name: "users", grow: 0},
|
||
|
]},
|
||
|
]);
|
||
|
welcome();
|
||
|
}
|