SHOW:
|
|
- or go back to the newest paste.
1 | CHATROOM = "ash_on_lol" | |
2 | SUBSONLY = false | |
3 | CLEAR_MESSAGES = true | |
4 | ||
5 | local expect = require "cc.expect" | |
6 | local expect, field = expect.expect, expect.field | |
7 | ||
8 | local type, getmetatable, setmetatable, colours, str_write, tostring = type, getmetatable, setmetatable, colours, write, tostring | |
9 | local debug_info = type(debug) == "table" and type(debug.getinfo) == "function" and debug.getinfo | |
10 | local debug_local = type(debug) == "table" and type(debug.getlocal) == "function" and debug.getlocal | |
11 | ||
12 | --- @{table.insert} alternative, but with the length stored inline. | |
13 | local function append(out, value) | |
14 | local n = out.n + 1 | |
15 | out[n], out.n = value, n | |
16 | end | |
17 | ||
18 | --- A document containing formatted text, with multiple possible layouts. | |
19 | -- | |
20 | -- Documents effectively represent a sequence of strings in alternative layouts, | |
21 | -- which we will try to print in the most compact form necessary. | |
22 | -- | |
23 | -- @type Doc | |
24 | local Doc = { } | |
25 | ||
26 | --- An empty document. | |
27 | local empty = setmetatable({ tag = "nil" }, Doc) | |
28 | ||
29 | --- A document with a single space in it. | |
30 | local space = setmetatable({ tag = "text", text = " " }, Doc) | |
31 | ||
32 | --- A line break. When collapsed with @{group}, this will be replaced with @{empty}. | |
33 | local line = setmetatable({ tag = "line", flat = empty }, Doc) | |
34 | ||
35 | --- A line break. When collapsed with @{group}, this will be replaced with @{space}. | |
36 | local space_line = setmetatable({ tag = "line", flat = space }, Doc) | |
37 | ||
38 | local text_cache = { [""] = empty, [" "] = space, ["\n"] = space_line } | |
39 | ||
40 | local function mk_text(text, colour) | |
41 | return text_cache[text] or setmetatable({ tag = "text", text = text, colour = colour }, Doc) | |
42 | end | |
43 | ||
44 | --- Create a new document from a string. | |
45 | -- | |
46 | -- If your string contains multiple lines, @{group} will flatten the string | |
47 | -- into a single line, with spaces between each line. | |
48 | -- | |
49 | -- @tparam string text The string to construct a new document with. | |
50 | -- @tparam[opt] number colour The colour this text should be printed with. If not given, we default to the current | |
51 | -- colour. | |
52 | -- @treturn Doc The document with the provided text. | |
53 | -- @usage Write some blue text. | |
54 | -- local pretty = require "cc.pretty" | |
55 | -- pretty.print(pretty.text("Hello!", colours.blue)) | |
56 | local function text(text, colour) | |
57 | expect(1, text, "string") | |
58 | expect(2, colour, "number", "nil") | |
59 | ||
60 | local cached = text_cache[text] | |
61 | if cached then return cached end | |
62 | ||
63 | local new_line = text:find("\n", 1) | |
64 | if not new_line then return mk_text(text, colour) end | |
65 | ||
66 | -- Split the string by "\n". With a micro-optimisation to skip empty strings. | |
67 | local doc = setmetatable({ tag = "concat", n = 0 }, Doc) | |
68 | if new_line ~= 1 then append(doc, mk_text(text:sub(1, new_line - 1), colour)) end | |
69 | ||
70 | new_line = new_line + 1 | |
71 | while true do | |
72 | local next_line = text:find("\n", new_line) | |
73 | append(doc, space_line) | |
74 | if not next_line then | |
75 | if new_line <= #text then append(doc, mk_text(text:sub(new_line), colour)) end | |
76 | return doc | |
77 | else | |
78 | if new_line <= next_line - 1 then | |
79 | append(doc, mk_text(text:sub(new_line, next_line - 1), colour)) | |
80 | end | |
81 | new_line = next_line + 1 | |
82 | end | |
83 | end | |
84 | end | |
85 | ||
86 | --- Concatenate several documents together. This behaves very similar to string concatenation. | |
87 | -- | |
88 | -- @tparam Doc|string ... The documents to concatenate. | |
89 | -- @treturn Doc The concatenated documents. | |
90 | -- @usage | |
91 | -- local pretty = require "cc.pretty" | |
92 | -- local doc1, doc2 = pretty.text("doc1"), pretty.text("doc2") | |
93 | -- print(pretty.concat(doc1, " - ", doc2)) | |
94 | -- print(doc1 .. " - " .. doc2) -- Also supports .. | |
95 | local function concat(...) | |
96 | local args = table.pack(...) | |
97 | for i = 1, args.n do | |
98 | if type(args[i]) == "string" then args[i] = text(args[i]) end | |
99 | if getmetatable(args[i]) ~= Doc then expect(i, args[i], "document") end | |
100 | end | |
101 | ||
102 | if args.n == 0 then return empty end | |
103 | if args.n == 1 then return args[1] end | |
104 | ||
105 | args.tag = "concat" | |
106 | return setmetatable(args, Doc) | |
107 | end | |
108 | ||
109 | Doc.__concat = concat --- @local | |
110 | ||
111 | --- Indent later lines of the given document with the given number of spaces. | |
112 | -- | |
113 | -- For instance, nesting the document | |
114 | -- ```txt | |
115 | -- foo | |
116 | -- bar | |
117 | -- ``` | |
118 | -- by two spaces will produce | |
119 | -- ```txt | |
120 | -- foo | |
121 | -- bar | |
122 | -- ``` | |
123 | -- | |
124 | -- @tparam number depth The number of spaces with which the document should be indented. | |
125 | -- @tparam Doc doc The document to indent. | |
126 | -- @treturn Doc The nested document. | |
127 | -- @usage | |
128 | -- local pretty = require "cc.pretty" | |
129 | -- print(pretty.nest(2, pretty.text("foo\nbar"))) | |
130 | local function nest(depth, doc) | |
131 | expect(1, depth, "number") | |
132 | if getmetatable(doc) ~= Doc then expect(2, doc, "document") end | |
133 | if depth <= 0 then error("depth must be a positive number", 2) end | |
134 | ||
135 | return setmetatable({ tag = "nest", depth = depth, doc }, Doc) | |
136 | end | |
137 | ||
138 | local function flatten(doc) | |
139 | if doc.flat then return doc.flat end | |
140 | ||
141 | local kind = doc.tag | |
142 | if kind == "nil" or kind == "text" then | |
143 | return doc | |
144 | elseif kind == "concat" then | |
145 | local out = setmetatable({ tag = "concat", n = doc.n }, Doc) | |
146 | for i = 1, doc.n do out[i] = flatten(doc[i]) end | |
147 | doc.flat, out.flat = out, out -- cache the flattened node | |
148 | return out | |
149 | elseif kind == "nest" then | |
150 | return flatten(doc[1]) | |
151 | elseif kind == "group" then | |
152 | return doc[1] | |
153 | else | |
154 | error("Unknown doc " .. kind) | |
155 | end | |
156 | end | |
157 | ||
158 | --- Builds a document which is displayed on a single line if there is enough | |
159 | -- room, or as normal if not. | |
160 | -- | |
161 | -- @tparam Doc doc The document to group. | |
162 | -- @treturn Doc The grouped document. | |
163 | -- @usage Uses group to show things being displayed on one or multiple lines. | |
164 | -- | |
165 | -- local pretty = require "cc.pretty" | |
166 | -- local doc = pretty.group("Hello" .. pretty.space_line .. "World") | |
167 | -- print(pretty.render(doc, 5)) -- On multiple lines | |
168 | -- print(pretty.render(doc, 20)) -- Collapsed onto one. | |
169 | local function group(doc) | |
170 | if getmetatable(doc) ~= Doc then expect(1, doc, "document") end | |
171 | ||
172 | if doc.tag == "group" then return doc end -- Skip if already grouped. | |
173 | ||
174 | local flattened = flatten(doc) | |
175 | if flattened == doc then return doc end -- Also skip if flattening does nothing. | |
176 | return setmetatable({ tag = "group", flattened, doc }, Doc) | |
177 | end | |
178 | ||
179 | local function get_remaining(doc, width) | |
180 | local kind = doc.tag | |
181 | if kind == "nil" or kind == "line" then | |
182 | return width | |
183 | elseif kind == "text" then | |
184 | return width - #doc.text | |
185 | elseif kind == "concat" then | |
186 | for i = 1, doc.n do | |
187 | width = get_remaining(doc[i], width) | |
188 | if width < 0 then break end | |
189 | end | |
190 | return width | |
191 | elseif kind == "group" or kind == "nest" then | |
192 | return get_remaining(kind[1]) | |
193 | else | |
194 | error("Unknown doc " .. kind) | |
195 | end | |
196 | end | |
197 | ||
198 | --- Display a document on the terminal. | |
199 | -- | |
200 | -- @tparam Doc doc The document to render | |
201 | -- @tparam[opt] number ribbon_frac The maximum fraction of the width that we should write in. | |
202 | local function write(doc, ribbon_frac) | |
203 | if getmetatable(doc) ~= Doc then expect(1, doc, "document") end | |
204 | expect(2, ribbon_frac, "number", "nil") | |
205 | ||
206 | local term = term | |
207 | local width, height = term.getSize() | |
208 | local ribbon_width = (ribbon_frac or 0.6) * width | |
209 | if ribbon_width < 0 then ribbon_width = 0 end | |
210 | if ribbon_width > width then ribbon_width = width end | |
211 | ||
212 | local def_colour = term.getTextColour() | |
213 | local current_colour = def_colour | |
214 | ||
215 | local function go(doc, indent, col) | |
216 | local kind = doc.tag | |
217 | if kind == "nil" then | |
218 | return col | |
219 | elseif kind == "text" then | |
220 | local doc_colour = doc.colour or def_colour | |
221 | if doc_colour ~= current_colour then | |
222 | term.setTextColour(doc_colour) | |
223 | current_colour = doc_colour | |
224 | end | |
225 | ||
226 | str_write(doc.text) | |
227 | ||
228 | return col + #doc.text | |
229 | elseif kind == "line" then | |
230 | local _, y = term.getCursorPos() | |
231 | if y < height then | |
232 | term.setCursorPos(indent + 1, y + 1) | |
233 | else | |
234 | term.scroll(1) | |
235 | term.setCursorPos(indent + 1, height) | |
236 | end | |
237 | ||
238 | return indent | |
239 | elseif kind == "concat" then | |
240 | for i = 1, doc.n do col = go(doc[i], indent, col) end | |
241 | return col | |
242 | elseif kind == "nest" then | |
243 | return go(doc[1], indent + doc.depth, col) | |
244 | elseif kind == "group" then | |
245 | if get_remaining(doc[1], math.min(width, ribbon_width + indent) - col) >= 0 then | |
246 | return go(doc[1], indent, col) | |
247 | else | |
248 | return go(doc[2], indent, col) | |
249 | end | |
250 | else | |
251 | error("Unknown doc " .. kind) | |
252 | end | |
253 | end | |
254 | ||
255 | local col = math.max(term.getCursorPos() - 1, 0) | |
256 | go(doc, 0, col) | |
257 | if current_colour ~= def_colour then term.setTextColour(def_colour) end | |
258 | end | |
259 | ||
260 | --- Display a document on the terminal with a trailing new line. | |
261 | -- | |
262 | -- @tparam Doc doc The document to render. | |
263 | -- @tparam[opt] number ribbon_frac The maximum fraction of the width that we should write in. | |
264 | local function print(doc, ribbon_frac) | |
265 | if getmetatable(doc) ~= Doc then expect(1, doc, "document") end | |
266 | expect(2, ribbon_frac, "number", "nil") | |
267 | write(doc, ribbon_frac) | |
268 | str_write("\n") | |
269 | end | |
270 | ||
271 | --- Render a document, converting it into a string. | |
272 | -- | |
273 | -- @tparam Doc doc The document to render. | |
274 | -- @tparam[opt] number width The maximum width of this document. Note that long strings will not be wrapped to | |
275 | -- fit this width - it is only used for finding the best layout. | |
276 | -- @tparam[opt] number ribbon_frac The maximum fraction of the width that we should write in. | |
277 | -- @treturn string The rendered document as a string. | |
278 | local function render(doc, width, ribbon_frac) | |
279 | if getmetatable(doc) ~= Doc then expect(1, doc, "document") end | |
280 | expect(2, width, "number", "nil") | |
281 | expect(3, ribbon_frac, "number", "nil") | |
282 | ||
283 | local ribbon_width | |
284 | if width then | |
285 | ribbon_width = (ribbon_frac or 0.6) * width | |
286 | if ribbon_width < 0 then ribbon_width = 0 end | |
287 | if ribbon_width > width then ribbon_width = width end | |
288 | end | |
289 | ||
290 | local out = { n = 0 } | |
291 | local function go(doc, indent, col) | |
292 | local kind = doc.tag | |
293 | if kind == "nil" then | |
294 | return col | |
295 | elseif kind == "text" then | |
296 | append(out, doc.text) | |
297 | return col + #doc.text | |
298 | elseif kind == "line" then | |
299 | append(out, "\n" .. (" "):rep(indent)) | |
300 | return indent | |
301 | elseif kind == "concat" then | |
302 | for i = 1, doc.n do col = go(doc[i], indent, col) end | |
303 | return col | |
304 | elseif kind == "nest" then | |
305 | return go(doc[1], indent + doc.depth, col) | |
306 | elseif kind == "group" then | |
307 | if not width or get_remaining(doc[1], math.min(width, ribbon_width + indent) - col) >= 0 then | |
308 | return go(doc[1], indent, col) | |
309 | else | |
310 | return go(doc[2], indent, col) | |
311 | end | |
312 | else | |
313 | error("Unknown doc " .. kind) | |
314 | end | |
315 | end | |
316 | ||
317 | go(doc, 0, 0) | |
318 | return table.concat(out, "", 1, out.n) | |
319 | end | |
320 | ||
321 | Doc.__tostring = render --- @local | |
322 | ||
323 | local keywords = { | |
324 | ["and"] = true, ["break"] = true, ["do"] = true, ["else"] = true, | |
325 | ["elseif"] = true, ["end"] = true, ["false"] = true, ["for"] = true, | |
326 | ["function"] = true, ["if"] = true, ["in"] = true, ["local"] = true, | |
327 | ["nil"] = true, ["not"] = true, ["or"] = true, ["repeat"] = true, ["return"] = true, | |
328 | ["then"] = true, ["true"] = true, ["until"] = true, ["while"] = true, | |
329 | } | |
330 | ||
331 | local comma = text(",") | |
332 | local braces = text("{}") | |
333 | local obrace, cbrace = text("{"), text("}") | |
334 | local obracket, cbracket = text("["), text("] = ") | |
335 | ||
336 | local function key_compare(a, b) | |
337 | local ta, tb = type(a), type(b) | |
338 | ||
339 | if ta == "string" then return tb ~= "string" or a < b | |
340 | elseif tb == "string" then return false | |
341 | end | |
342 | ||
343 | if ta == "number" then return tb ~= "number" or a < b end | |
344 | return false | |
345 | end | |
346 | ||
347 | local function show_function(fn, options) | |
348 | local info = debug_info and debug_info(fn, "Su") | |
349 | ||
350 | -- Include function source position if available | |
351 | local name | |
352 | if options.function_source and info and info.short_src and info.linedefined and info.linedefined >= 1 then | |
353 | name = "function<" .. info.short_src .. ":" .. info.linedefined .. ">" | |
354 | else | |
355 | name = tostring(fn) | |
356 | end | |
357 | ||
358 | -- Include arguments if a Lua function and if available. Lua will report "C" | |
359 | -- functions as variadic. | |
360 | if options.function_args and info and info.what == "Lua" and info.nparams and debug_local then | |
361 | local args = {} | |
362 | for i = 1, info.nparams do args[i] = debug_local(fn, i) or "?" end | |
363 | if info.isvararg then args[#args + 1] = "..." end | |
364 | name = name .. "(" .. table.concat(args, ", ") .. ")" | |
365 | end | |
366 | ||
367 | return name | |
368 | end | |
369 | ||
370 | local function pretty_impl(obj, options, tracking) | |
371 | local obj_type = type(obj) | |
372 | if obj_type == "string" then | |
373 | local formatted = ("%q"):format(obj):gsub("\\\n", "\\n") | |
374 | return text(formatted, colours.red) | |
375 | elseif obj_type == "number" then | |
376 | return text(tostring(obj), colours.magenta) | |
377 | elseif obj_type == "function" then | |
378 | return text(show_function(obj, options), colours.lightGrey) | |
379 | elseif obj_type ~= "table" or tracking[obj] then | |
380 | return text(tostring(obj), colours.lightGrey) | |
381 | elseif getmetatable(obj) ~= nil and getmetatable(obj).__tostring then | |
382 | return text(tostring(obj)) | |
383 | elseif next(obj) == nil then | |
384 | return braces | |
385 | else | |
386 | tracking[obj] = true | |
387 | local doc = setmetatable({ tag = "concat", n = 1, space_line }, Doc) | |
388 | ||
389 | local length, keys, keysn = #obj, {}, 1 | |
390 | for k in pairs(obj) do keys[keysn], keysn = k, keysn + 1 end | |
391 | table.sort(keys, key_compare) | |
392 | ||
393 | for i = 1, keysn - 1 do | |
394 | if i > 1 then append(doc, comma) append(doc, space_line) end | |
395 | ||
396 | local k = keys[i] | |
397 | local v = obj[k] | |
398 | local ty = type(k) | |
399 | if ty == "number" and k % 1 == 0 and k >= 1 and k <= length then | |
400 | append(doc, pretty_impl(v, options, tracking)) | |
401 | elseif ty == "string" and not keywords[k] and k:match("^[%a_][%a%d_]*$") then | |
402 | append(doc, text(k .. " = ")) | |
403 | append(doc, pretty_impl(v, options, tracking)) | |
404 | else | |
405 | append(doc, obracket) | |
406 | append(doc, pretty_impl(k, options, tracking)) | |
407 | append(doc, cbracket) | |
408 | append(doc, pretty_impl(v, options, tracking)) | |
409 | end | |
410 | end | |
411 | ||
412 | tracking[obj] = nil | |
413 | return group(concat(obrace, nest(2, concat(table.unpack(doc, 1, doc.n))), space_line, cbrace)) | |
414 | end | |
415 | end | |
416 | ||
417 | --- Pretty-print an arbitrary object, converting it into a document. | |
418 | -- | |
419 | -- This can then be rendered with @{write} or @{print}. | |
420 | -- | |
421 | -- @param obj The object to pretty-print. | |
422 | -- @tparam[opt] { function_args = boolean, function_source = boolean } options | |
423 | -- Controls how various properties are displayed. | |
424 | -- - `function_args`: Show the arguments to a function if known (`false` by default). | |
425 | -- - `function_source`: Show where the function was defined, instead of | |
426 | -- `function: xxxxxxxx` (`false` by default). | |
427 | -- @treturn Doc The object formatted as a document. | |
428 | -- @usage Display a table on the screen | |
429 | -- local pretty = require "cc.pretty" | |
430 | -- pretty.print(pretty.pretty({ 1, 2, 3 })) | |
431 | local function prettyf(obj, options) | |
432 | expect(2, options, "table", "nil") | |
433 | options = options or {} | |
434 | ||
435 | local actual_options = { | |
436 | function_source = field(options, "function_source", "boolean", "nil") or false, | |
437 | function_args = field(options, "function_args", "boolean", "nil") or false, | |
438 | } | |
439 | return pretty_impl(obj, actual_options, {}) | |
440 | end | |
441 | ||
442 | local pretty = { | |
443 | empty = empty, | |
444 | space = space, | |
445 | line = line, | |
446 | space_line = space_line, | |
447 | text = text, | |
448 | concat = concat, | |
449 | nest = nest, | |
450 | group = group, | |
451 | ||
452 | write = write, | |
453 | print = print, | |
454 | render = render, | |
455 | ||
456 | pretty = prettyf, | |
457 | } | |
458 | ||
459 | local monitor = peripheral.find("monitor") | |
460 | local oldTerm = term.redirect(monitor) | |
461 | ||
462 | function split(str, character) | |
463 | result = {} | |
464 | index = 1 | |
465 | for s in string.gmatch(str, "[^"..character.."]+") do | |
466 | result[index] = s | |
467 | index = index + 1 | |
468 | end | |
469 | return result | |
470 | end | |
471 | local hex = {"F0F0F0", "F2B233", "E57FD8", "99B2F2", "DEDE6C", "7FCC19", "F2B2CC", "4C4C4C", "999999", "4C99B2", "B266E5", "3366CC", "7F664C", "57A64E", "CC4C4C", "191919"} | |
472 | local rgb = {} | |
473 | for i=1,16,1 do | |
474 | rgb[i] = {tonumber(hex[i]:sub(1, 2), 16), tonumber(hex[i]:sub(3, 4), 16), tonumber(hex[i]:sub(5, 6), 16)} | |
475 | end | |
476 | local rgb2 = {} | |
477 | for i=1,16,1 do | |
478 | rgb2[i] = {} | |
479 | for j=1,16,1 do | |
480 | rgb2[i][j] = {(rgb[i][1] * 34 + rgb[j][1] * 20) / 54, (rgb[i][2] * 34 + rgb[j][2] * 20) / 54, (rgb[i][3] * 34 + rgb[j][3] * 20) / 54} | |
481 | end | |
482 | end | |
483 | ||
484 | colors.fromRGB = function (r, g, b) | |
485 | local dist = 1e100 | |
486 | local d = 1e100 | |
487 | local color = -1 | |
488 | for i=1,16,1 do | |
489 | d = math.sqrt((math.max(rgb[i][1], r) - math.min(rgb[i][1], r)) ^ 2 + (math.max(rgb[i][2], g) - math.min(rgb[i][2], g)) ^ 2 + (math.max(rgb[i][3], b) - math.min(rgb[i][3], b)) ^ 2) | |
490 | if d < dist then | |
491 | dist = d | |
492 | color = i - 1 | |
493 | end | |
494 | end | |
495 | return 2 ^ color | |
496 | end | |
497 | ||
498 | local ws | |
499 | ||
500 | function main() | |
501 | ws, err = http.websocket("wss://irc-ws.chat.twitch.tv") | |
502 | if err then | |
503 | print(err) | |
504 | elseif ws then | |
505 | ws.send("PASS ottomated") | |
506 | ws.send("NICK justinfan"..math.random(10000, 99999)) | |
507 | ws.send("JOIN #"..CHATROOM) | |
508 | ws.send("CAP REQ :twitch.tv/tags") | |
509 | ws.send("CAP REQ :twitch.tv/commands") | |
510 | while true do | |
511 | local msg = ws.receive() | |
512 | if msg == "PING :tmi.twitch.tv" then | |
513 | ws.send("PONG :tmi.twitch.tv") | |
514 | else | |
515 | -- print(msg) | |
516 | local parts = split(msg, " ") | |
517 | if parts[3] == "PRIVMSG" then | |
518 | local twitchParts = split(parts[1], ";") | |
519 | local nameColor = "#ffffff" | |
520 | local displayName | |
521 | local subscriber = false | |
522 | local founder = false | |
523 | local id | |
524 | for _, part in ipairs(twitchParts) do | |
525 | if string.sub(part, 1, 12) == "@badge-info=" then | |
526 | founder = string.find(part, "founder") ~= nil | |
527 | elseif string.sub(part, 1, 6) == "color=" then | |
528 | nameColor = string.sub(part, 7, -1) | |
529 | elseif string.sub(part, 1, 13) == "display-name=" then | |
530 | displayName = string.sub(part, 14, -1) | |
531 | elseif string.sub(part, 1, 3) == "id=" then | |
532 | id = string.sub(part, 4, -1) | |
533 | elseif string.sub(part, 1, 11) == "subscriber=" then | |
534 | subscriber = string.sub(part, 12, -1) == "1" | |
535 | end | |
536 | end | |
537 | subscriber = subscriber or founder | |
538 | ||
539 | local namePalette | |
540 | if #nameColor < 1 then | |
541 | namePalette = 2^math.random(0, 15) | |
542 | else | |
543 | local hex = string.sub(nameColor, 2, -1) | |
544 | local r = tonumber(string.sub(hex, 1, 2), 16) | |
545 | local g = tonumber(string.sub(hex, 3, 4), 16) | |
546 | local b = tonumber(string.sub(hex, 5, 6), 16) | |
547 | namePalette = colors.fromRGB(r, g, b) | |
548 | end | |
549 | ||
550 | if namePalette == colors.black or namePalette == colors.white then | |
551 | namePalette = colors.lightGray | |
552 | end | |
553 | ||
554 | if displayName and id then | |
555 | local message = string.sub(parts[5], 2, -1) | |
556 | ||
557 | for i=6,#parts do | |
558 | message = message.." "..parts[i] | |
559 | end | |
560 | if string.sub(message, 1, 7) == "ACTION" then | |
561 | message = string.sub(message, 9, -4) | |
562 | else | |
563 | message = string.sub(message, 1, -2) | |
564 | end | |
565 | if subscriber or not SUBSONLY then | |
566 | pretty.print(pretty.group(pretty.text(displayName, namePalette) .. pretty.text(":", colors.white) .. pretty.space .. pretty.text(message, colors.white))) | |
567 | -- term.setTextColor(namePalette) | |
568 | -- term.write(displayName) | |
569 | -- term.setCursorPos() | |
570 | -- print(displayName, message) | |
571 | end | |
572 | end | |
573 | elseif CLEAR_MESSAGES and (parts[3] == "CLEARMSG" or parts[3] == "CLEARCHAT") then | |
574 | term.clear() | |
575 | term.setCursorPos(1,1) | |
576 | end | |
577 | end | |
578 | end | |
579 | end | |
580 | end | |
581 | while true do | |
582 | pcall(main) | |
583 | if ws then | |
584 | ws.close() | |
585 | end | |
586 | end | |
587 | --term.redirect(oldTerm) |