SHOW:
|
|
- or go back to the newest paste.
| 1 | - | local function update() |
| 1 | + | |
| 2 | - | local h = http.get "https://pastebin.com/raw/L0ZKLBRG" |
| 2 | + | local o = peripheral.find "monitor" |
| 3 | - | local f = fs.open(shell.getRunningProgram(), "w") |
| 3 | + | |
| 4 | - | f.write(h.readAll()) |
| 4 | + | o.setTextScale(0.5) |
| 5 | - | f.close() |
| 5 | + | |
| 6 | - | h.close() |
| 6 | + | local w, h = o.getSize() |
| 7 | local command_window = window.create(o, 1, h, w, 1) | |
| 8 | local outputs_window = window.create(o, 1, 1, w, h - 1) | |
| 9 | - | if ... == "update" then update() end |
| 9 | + | |
| 10 | local function exec_in_window(w, f) | |
| 11 | local x, y = o.getCursorPos() | |
| 12 | - | local s = peripheral.find "speaker" |
| 12 | + | |
| 13 | f() | |
| 14 | - | local chan = 3636 |
| 14 | + | |
| 15 | - | print "Welcome to the Lightweight Messaging System (developed by GTech Potatronics)" |
| 15 | + | |
| 16 | o.setCursorPos(x, y) | |
| 17 | - | m.open(chan) |
| 17 | + | |
| 18 | ||
| 19 | - | local username = settings.get "lms.username" |
| 19 | + | local function print_output(txt, color) |
| 20 | - | if username == nil then |
| 20 | + | exec_in_window(outputs_window, function() |
| 21 | - | write "Username: " |
| 21 | + | term.setTextColor(color or colors.white) |
| 22 | - | username = read() |
| 22 | + | |
| 23 | end) | |
| 24 | end | |
| 25 | - | local w, h = term.getSize() |
| 25 | + | |
| 26 | - | local send_window = window.create(term.current(), 1, h, w, 1) |
| 26 | + | local function splitspace(str) |
| 27 | - | local message_window = window.create(term.current(), 1, 1, w, h - 1) |
| 27 | + | local tokens = {}
|
| 28 | for token in string.gmatch(str, "[^%s]+") do | |
| 29 | - | local function notification_sound() |
| 29 | + | table.insert(tokens, token) |
| 30 | - | if s then |
| 30 | + | |
| 31 | - | for i = 4, 12, 4 do |
| 31 | + | return tokens |
| 32 | - | s.playNote("flute", 3, i)
|
| 32 | + | |
| 33 | - | sleep(0.2) |
| 33 | + | |
| 34 | local function controls() | |
| 35 | term.redirect(command_window) | |
| 36 | term.setBackgroundColor(colors.white) | |
| 37 | term.setTextColor(colors.black) | |
| 38 | term.clear() | |
| 39 | - | local x, y = term.getCursorPos() |
| 39 | + | |
| 40 | while true do | |
| 41 | write "> " | |
| 42 | local msg = read(nil, hist) | |
| 43 | table.insert(hist, msg) | |
| 44 | - | term.setCursorPos(x, y) |
| 44 | + | local tokens = splitspace(msg) |
| 45 | local command = table.remove(tokens, 1) | |
| 46 | if command == "open" then | |
| 47 | - | local function print_message(txt) |
| 47 | + | local chan = tonumber(tokens[1]) |
| 48 | - | exec_in_window(message_window, function() |
| 48 | + | m.open(chan) |
| 49 | print_output(("Opened %d"):format(chan), colors.gray)
| |
| 50 | elseif command == "close" then | |
| 51 | local chan = tonumber(tokens[1]) | |
| 52 | m.close(chan) | |
| 53 | - | local function trim(s) |
| 53 | + | print_output(("Closed %d"):format(chan), colors.gray)
|
| 54 | - | return s:match( "^%s*(.-)%s*$" ) |
| 54 | + | |
| 55 | print_output("Command invalid", colors.gray)
| |
| 56 | end | |
| 57 | - | local banned_text = {
|
| 57 | + | |
| 58 | - | "yeet", |
| 58 | + | |
| 59 | - | "ecs dee", |
| 59 | + | |
| 60 | - | "dab", |
| 60 | + | local function compact_serialize(x) |
| 61 | - | } |
| 61 | + | local t = type(x) |
| 62 | if t == "number" then | |
| 63 | - | if debug and debug.getmetatable then |
| 63 | + | return tostring(x) |
| 64 | - | _G.getmetatable = debug.getmetatable |
| 64 | + | elseif t == "string" then |
| 65 | return textutils.serialise(x) | |
| 66 | elseif t == "table" then | |
| 67 | - | local function to_case_insensitive(text) |
| 67 | + | local out = "{ "
|
| 68 | - | return text:gsub("[a-zA-Z]", function(char) return ("[%s%s]"):format(char:lower(), char:upper()) end)
|
| 68 | + | for k, v in pairs(x) do |
| 69 | out = out .. string.format("[%s]=%s, ", compact_serialize(k), compact_serialize(v))
| |
| 70 | end | |
| 71 | - | local function filter(text) |
| 71 | + | return out .. "}" |
| 72 | - | local out = text |
| 72 | + | elseif t == "boolean" then |
| 73 | - | for _, b in pairs(banned_text) do |
| 73 | + | return tostring(x) |
| 74 | - | out = out:gsub(to_case_insensitive(b), "") |
| 74 | + | else |
| 75 | error("Unsupported type " .. t)
| |
| 76 | - | return out |
| 76 | + | |
| 77 | end | |
| 78 | ||
| 79 | - | local function strip_extraneous_spacing(text) |
| 79 | + | local function safe_serialize(m) |
| 80 | - | return text:gsub("%s+", " ")
|
| 80 | + | local ok, res = pcall(compact_serialize, m) |
| 81 | if ok then return res | |
| 82 | else return ("[UNSERIALIZABLE %s: %s]"):format(tostring(m), res) end
| |
| 83 | - | local function collapse_e_sequences(text) |
| 83 | + | |
| 84 | - | return text:gsub("ee+", "ee")
|
| 84 | + | |
| 85 | local function tostring_with_default(x) | |
| 86 | if not x then return "[UNKNOWN]" | |
| 87 | - | local function preproc(text) |
| 87 | + | else return tostring(x) end |
| 88 | - | return trim(filter(strip_extraneous_spacing(collapse_e_sequences(text:sub(1, 128))))) |
| 88 | + | |
| 89 | ||
| 90 | local function receive() | |
| 91 | - | local function add_message(msg, usr) |
| 91 | + | |
| 92 | - | local msg, usr = preproc(msg), preproc(usr) |
| 92 | + | local _, _, channel, reply_channel, message, distance = os.pullEvent "modem_message" |
| 93 | - | if msg == "" or usr == "" then return end |
| 93 | + | print_output(("%d \16 %d | %s"):format(channel, reply_channel, tostring_with_default(distance)))
|
| 94 | - | print_message(usr .. ": " .. msg) |
| 94 | + | print_output(safe_serialize(message), colors.lightGray) |
| 95 | end | |
| 96 | end | |
| 97 | - | local function send() |
| 97 | + | |
| 98 | - | term.redirect(send_window) |
| 98 | + | parallel.waitForAny(controls, receive) |