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) |