· 2 years ago · Mar 05, 2023, 07:01 PM
1shaka = require("API")
2
3
4if not fs.exists("serverID") then
5 rednet.broadcast("give", "serverID")
6 local id, message = rednet.receive("idSupply")
7 local file = fs.open("serverID", "w")
8 file.write(id)
9 file.close()
10else
11 local file = fs.open("serverID", "r")
12 serverID = file.readAll()
13 file.close()
14 serverID = tonumber(serverID)
15end
16
17local function receiveInfos()
18 local msg = nil
19 local file = fs.open(".userData", "r")
20 local userName = file.readAll()
21 file.close()
22 rednet.broadcast(userName, "anyMessages?")
23 local sender, msg = rednet.receive("notificationReminder", 1)
24 if msg ~= nil then
25 if tonumber(msg) ~= 0 then
26 term.setCursorPos(1,1)
27 shaka.changeColors(colors.green, colors.black)
28 term.clearLine()
29 if tonumber(msg) > 1 then
30 shaka.centerText("New messages: " ..msg)
31 else
32 shaka.centerText("New message!")
33 end
34 end
35 else
36 shaka.changeColors(colors.red, colors.black)
37 term.clear()
38 shaka.centerText("Server not responding!", 7)
39 term.setCursorPos(8, 9)
40 textutils.slowPrint("Restarting..", 10)
41 sleep(2)
42 os.reboot()
43 end
44end
45
46function saveUserName()
47 shaka.clearScreen()
48 -- Prompt the user to enter their name
49 term.setBackgroundColor(colors.gray)
50 term.setTextColor(colors.black)
51 term.clearLine()
52 print("Please enter your name:\n")
53 shaka.resetColors()
54 local name = tostring(read())
55 if name ~= nil and name ~= "" then
56 -- Open the ".userData" file for writing
57 local file = fs.open(".userData", "w")
58
59 -- Write the user's name to the file
60 file.writeLine(name)
61
62 -- Close the file
63 file.close()
64
65 --send information to server
66 rednet.send(serverID, name, "newUser")
67 local sender, message = rednet.receive("userConfirm", 2)
68 if message == "worked" then
69 -- Show Success
70 shaka.clearScreen()
71 term.setTextColor(colors.black)
72 term.setBackgroundColor(colors.green)
73 term.clearLine()
74 textutils.slowPrint("Success!", 5)
75 shaka.resetColors()
76 print("\nThank you, " ..name.."!")
77 print("\nYour name has been saved.")
78 elseif message == nil then -- no response
79 shaka.clearScreen()
80 shaka.changeColors(colors.red, colors.black)
81 term.clearLine()
82 print("Server not responding!")
83 shaka.resetColors()
84 elseif message == "fail" then -- username already exists
85 shaka.nextLine()
86 shaka.changeColors(colors.red, colors.black)
87 term.clearLine()
88 print("User " ..name.. " already exists!\n")
89 shaka.changeColors(colors.black, colors.yellow)
90 print("Please choose another name.\n")
91 term.setTextColor(colors.gray)
92 textutils.slowPrint("Press any key to continue..")
93 event = os.pullEvent("key")
94 shell.run("messenger")
95 return
96 end
97 else
98 term.setBackgroundColor(colors.red)
99 term.clear()
100 shaka.centerText("Not a valid name!\n", 8)
101
102 end
103 term.setTextColor(colors.gray)
104 textutils.slowPrint("\nPress any key to continue..")
105 event = os.pullEvent("key")
106end
107
108if not fs.exists(".userData") then ---if no username exists create one
109 saveUserName()
110end
111
112function getUserList()
113knownUsers = {}
114 rednet.broadcast("give", "requestUserList")
115 local sender, message = rednet.receive("userRequestAnswer", 2)
116 if message ~= "noUsers" and message ~= "" and message ~= nil then
117 message = textutils.unserialize(message)
118 for k, v in pairs(message) do
119 knownUsers[k] = v.name
120 end
121 elseif message == "noUsers" or message == "" then
122 knownUsers = {}
123 else
124 term.setBackgroundColor(colors.red)
125 term.clear()
126 term.setTextColor(colors.black)
127 shaka.centerText("Can't connect to server", 8)
128 sleep(2)
129 os.reboot()
130 end
131end
132
133
134function sendMessage()
135 -- Load the user's name from the ".userData" file
136 local file = fs.open(".userData", "r")
137 local userName = file.readAll()
138 file.close()
139
140 -- Load the list of known users from the "knownUsers" table
141 getUserList()
142
143 local function checkUserInDatabase()
144 for k, v in ipairs(knownUsers) do
145 if v == userName then
146 return true
147 end
148 end
149 return false
150 end
151
152 if checkUserInDatabase() == false then
153 shaka.clearScreen()
154 shaka.changeColors(colors.red, colors.black)
155 print("User " ..userName.. " doesn't exist on the server.")
156 shaka.changeColors(colors.black, colors.yellow)
157 textutils.slowPrint("\nPlease register your user!")
158 shaka.changeColors(colors.black, colors.gray)
159 textutils.slowPrint("\nPress any key to continue..")
160 os.pullEvent("key")
161 saveUserName()
162 os.reboot()
163 end
164
165 -- Prompt the user to select a receiver from the list of known users
166 shaka.clearScreen()
167 shaka.changeColors(colors.green, colors.black)
168 term.clearLine()
169 print("Click a recipient:\n")
170 local a, b = term.getSize()
171 local xa, ya = term.getCursorPos()
172 term.setCursorPos(a - 1, 1)
173 term.setBackgroundColor(colors.red)
174 term.write(" X")
175 term.setCursorPos(xa,ya)
176
177 for i, user in ipairs(knownUsers) do
178 if i % 2 == 0 then -- alternate gray background
179 term.setBackgroundColor(colors.gray)
180 term.setTextColor(colors.black)
181 term.clearLine()
182 else
183 term.setBackgroundColor(colors.lightGray)
184 term.setTextColor(colors.black)
185 term.clearLine()
186 end
187 print(user)
188 end
189
190 -- Wait for the user to click on a receiver
191 local receiverIndex
192 while not receiverIndex do
193 local event, button, x, y = os.pullEvent("mouse_click")
194 if y == 1 then
195 shell.run("messenger")
196 return
197 end
198 -- Check if the click is within the bounds of the receiver list
199 if x >= 1 and x <= term.getSize() and y >= 3 and y <= 2 + #knownUsers then
200 receiverIndex = y - 2
201 end
202 end
203
204 -- Get the selected receiver from the list
205 local receiver = knownUsers[receiverIndex]
206
207 -- Prompt the user to enter a message
208 shaka.clearScreen()
209 shaka.changeColors(colors.green, colors.black)
210 term.clearLine()
211 print("Enter message to " ..receiver)
212 term.clearLine()
213 print("(double enter to send)\n")
214 shaka.changeColors(colors.black, colors.white)
215
216local messageLines = {}
217
218local function readAllText()
219 repeat
220 local line = read()
221 if line ~= "" then
222 table.insert(messageLines, line)
223 end
224 until line == ""
225
226 message = table.concat(messageLines, "\n")
227
228 if message ~= "" then
229 shaka.clearScreen()
230 shaka.changeColors(colors.yellow, colors.black)
231 term.clearLine()
232 print("Send to " ..receiver.. "?")
233 shaka.changeColors(colors.black, colors.lightGray)
234 term.clearLine()
235 print("Enter to send, any key to cancel.\n")
236 shaka.resetColors()
237 print(message)
238 event, key = os.pullEvent("key")
239 if key ~= keys.enter then
240 shaka.nextLine()
241 shaka.changeColors(colors.yellow, colors.black)
242 term.clearLine()
243 textutils.slowPrint("Aborting..")
244 sleep(1)
245 shell.run("messenger")
246 return
247 else
248 local plz, kk = term.getCursorPos()
249 term.setCursorPos(1, 1)
250 shaka.changeColors(colors.green, colors.black)
251 term.clearLine()
252 print("Send to " ..receiver.. "?\n")
253 term.setCursorPos(1, kk)
254 shaka.nextLine()
255 shaka.changeColors(colors.green, colors.black)
256 term.clearLine()
257 textutils.slowPrint("Sending..")
258 -- Send the message to the selected receiver
259 if receiver then
260 rednet.send(serverID, userName .. "+|" .. message .. "+|" .. receiver, "newMessage")
261 else
262 print("Invalid receiver selection.")
263 end
264
265
266
267 local sender, text = rednet.receive("messageConfirm", 2)
268 if text == nil then
269 term.setBackgroundColor(colors.red)
270 term.clear()
271 term.setTextColor(colors.black)
272 print("No confirmation! Is server offline?")
273 textutils.slowPrint("Restarting..")
274 sleep(1)
275 shell.run("messenger")
276 return
277 elseif text == "failed" then
278 shaka.clearScreen()
279 shaka.changeColors(colors.red, colors.black)
280 print("User " ..userName.. " doesn't exist on the server.")
281 shaka.changeColors(colors.black, colors.yellow)
282 textutils.slowPrint("\nPlease register your user!")
283 shaka.changeColors(colors.black, colors.gray)
284 textutils.slowPrint("\nPress any key to continue..")
285 os.pullEvent("key")
286 saveUserName()
287 return
288 else
289 shaka.nextLine()
290 shaka.changeColors(colors.black, colors.green)
291 term.clearLine()
292 textutils.slowPrint("Success!", 10)
293 end
294 sleep(1)
295 end
296 else
297 shaka.nextLine()
298 shaka.changeColors(colors.orange, colors.black)
299 term.clearLine()
300 print("Message is empty!\n")
301 shaka.changeColors(colors.black, colors.yellow)
302 textutils.slowPrint("Restarting..", 10)
303 sleep(1)
304 end
305 shell.run("messenger")
306 return
307end
308
309readAllText()
310
311end
312
313local function getMessages()
314 local file = fs.open(".userData", "r")
315 local userName = file.readAll()
316 file.close()
317 rednet.broadcast(userName, "messageUpdate")
318 local id, msg = rednet.receive("allMessages", 2)
319 if fs.exists(".myMessages") then
320 fs.delete(".myMessages")
321 end
322 local file = fs.open(".myMessages", "w")
323 file.write(msg)
324 file.close()
325 if msg == nil then
326 term.setBackgroundColor(colors.red)
327 term.clear()
328 term.setTextColor(colors.black)
329 shaka.centerText("Can't connect to server", 8)
330 sleep(2)
331 os.reboot()
332 else
333 msg = textutils.unserialize(msg)
334 return msg
335 end
336end
337
338function shortenString(str)
339 if string.len(str) > 10 then
340 return string.sub(str, 1, 10)
341 else
342 return str
343 end
344end
345
346
347
348local function displayMessages()
349 local file = fs.open(".userData", "r")
350 local userName = file.readAll()
351 file.close()
352 rednet.broadcast(userName, "delNotifications")
353 -- term.setCursorPos(1,1)
354 -- term.setBackgroundColor(colors.black)
355 -- term.clearLine()
356 local msg = getMessages()
357 shaka.clearScreen()
358 shaka.changeColors(colors.green, colors.black)
359 term.clearLine()
360 print("Recent messages:")
361
362 local a, b = term.getSize()
363 local xa, ya = term.getCursorPos()
364 term.setCursorPos(a - 1, 1)
365 term.setBackgroundColor(colors.red)
366 term.write(" X")
367 term.setCursorPos(xa,ya)
368
369 -- Display the last 6 messages
370 local startIndex = math.max(1, #msg - 5)
371 for i = startIndex, #msg do
372 local message = msg[i]
373 local sender = shortenString(message.sender)
374 local receiver = shortenString(message.receiver)
375 local date = message.date
376 local time = message.time
377 local text = message.text
378
379 -- Check if the user is the receiver
380 local isReceiver = string.find(userName, receiver) ~= nil
381
382 -- Check if the sender and receiver are the same
383 local isSameUser = sender == receiver
384
385 -- Set the text color based on whether the user is the receiver or the sender
386 if isSameUser then
387 term.setTextColor(colors.yellow)
388 elseif isReceiver then
389 term.setTextColor(colors.green)
390 else
391 term.setTextColor(colors.white)
392 end
393
394
395
396 -- Display message information without text
397 term.setBackgroundColor(colors.black)
398 term.clearLine()
399 term.setBackgroundColor(colors.black)
400 print()
401 term.setBackgroundColor(colors.gray)
402 term.clearLine()
403 shaka.centerText(date .. " - " .. time)
404 shaka.nextLine()
405 term.clearLine()
406 shaka.centerText(sender .. " -> " .. receiver)
407 shaka.nextLine()
408 end
409
410
411 -- Wait for mouse click event
412 while true do
413 local event, _, x, y = os.pullEvent("mouse_click")
414 if y == 1 then
415 shell.run("messenger")
416 return
417 end
418
419
420 y = y - 2 ------adjustments
421 if _ == 1 then
422 -- Calculate the index of the clicked message based on the y coordinate
423 local clickedIndex = (startIndex + math.floor(y / 3)) -- -1 here to move down one row
424
425 -- Check if the clicked message is within the valid range
426 if clickedIndex >= startIndex and clickedIndex <= #msg then
427 local message = msg[clickedIndex]
428 local sender = shortenString(message.sender)
429 local receiver = shortenString(message.receiver)
430 local date = message.date
431 local time = message.time
432 local text = message.text
433
434 -- Define the maximum number of lines that can fit on the screen
435 local maxLines = 15
436
437 -- Define the current line number and the total number of lines
438 local currentLine = 0
439 local totalLines = 0
440
441 -- Split the message text into lines
442 local lines = {}
443 for line in string.gmatch(text, "[^\r\n]+") do
444 table.insert(lines, line)
445 totalLines = totalLines + 1
446 end
447
448 ---check if scrolling makes sense
449 if totalLines > maxLines then
450 scrollAble = true
451 else
452 scrollAble = false
453 end
454
455 -- Clear the screen and display the message text
456 shaka.clearScreen()
457 term.setTextColor(colors.gray)
458 print(date .. " - " .. time)
459 shaka.changeColors(colors.gray, colors.lightBlue)
460 term.clearLine()
461 print(sender .. " -> " .. receiver)
462 shaka.resetColors()
463 shaka.nextLine()
464 if scrollAble then
465 local ab, cd = term.getCursorPos()
466 local ba, dc = term.getSize()
467 term.setCursorPos(1, dc-1)
468 term.setTextColor(colors.gray)
469 print("Scrolling available..")
470 term.setTextColor(colors.white)
471 term.setCursorPos(ab, cd)
472 end
473
474 -- Print the first set of lines that can fit on the screen
475 for i = currentLine, math.min(totalLines, currentLine + maxLines - 1) do
476 if i ~= 0 then
477 print(lines[i])
478 end
479 end
480
481 -- Listen for mouse scroll to scroll up or down or click to end
482 sleep(0.5)
483 repeat
484 local eventData = {os.pullEvent()}
485 local event = eventData[1]
486 button = tonumber(eventData[2])
487 if button == -1 and currentLine > 1 then
488 -- Scroll up
489 currentLine = currentLine - 1
490 shaka.clearScreen()
491 term.setTextColor(colors.gray)
492 print(date .. " - " .. time)
493 shaka.changeColors(colors.black, colors.lightBlue)
494 print(sender .. " -> " .. receiver)
495 shaka.resetColors()
496 print()
497 for i = currentLine, math.min(totalLines, currentLine + maxLines - 1) do
498 print(lines[i])
499 end
500
501 elseif button == 1 and currentLine < totalLines - maxLines + 1 then
502 -- Scroll down
503 currentLine = currentLine + 1
504 shaka.clearScreen()
505 term.setTextColor(colors.gray)
506 print(date .. " - " .. time)
507 shaka.changeColors(colors.black, colors.lightBlue)
508 print(sender .. " -> " .. receiver)
509 shaka.resetColors()
510 print()
511 for i = currentLine, math.min(totalLines, currentLine + maxLines - 1) do
512 print(lines[i])
513 end
514 end
515 until event == "mouse_click"
516
517
518 -- Redraw the messages on the screen
519 shaka.clearScreen()
520 shaka.changeColors(colors.green, colors.black)
521 term.clearLine()
522 print("Recent messages:")
523 local a, b = term.getSize()
524 local xa, ya = term.getCursorPos()
525 term.setCursorPos(a - 1, 1)
526 term.setBackgroundColor(colors.red)
527 term.write(" X")
528 term.setCursorPos(xa,ya)
529
530 for i = startIndex, #msg do
531 local message = msg[i]
532 local sender = shortenString(message.sender)
533 local receiver = shortenString(message.receiver)
534 local date = message.date
535 local time = message.time
536
537
538 -- Check if the user is the receiver
539 local isReceiver = string.find(userName, receiver) ~= nil
540
541 -- Check if the sender and receiver are the same
542 local isSameUser = sender == receiver
543
544 -- Set the text color based on whether the user is the receiver or the sender
545 if isSameUser then
546 term.setTextColor(colors.yellow)
547 elseif isReceiver then
548 term.setTextColor(colors.green)
549 else
550 term.setTextColor(colors.white)
551 end
552
553
554 -- Display message information without text
555 term.setBackgroundColor(colors.black)
556 term.clearLine()
557 term.setBackgroundColor(colors.black)
558 print()
559 term.setBackgroundColor(colors.gray)
560 term.clearLine()
561 shaka.centerText(date .. " - " .. time)
562 shaka.nextLine()
563 term.clearLine()
564 shaka.centerText(sender .. " -> " .. receiver)
565 shaka.nextLine()
566 end
567 end
568 end
569 end
570end
571
572function reboot()
573 os.reboot()
574end
575
576
577function showButtons()
578term.setBackgroundColor(colors.black)
579term.clear()
580 -- Define the buttons and their associated programs and colors
581 local buttons = {
582 {label="Send message", program=sendMessage, color = colors.lightGray},
583 {label="View recent messages", program=displayMessages, color = colors.gray},
584 {label="View all messages", program="messenger", color = colors.purple},
585 {label="Exit", program=reboot, color = colors.red},
586 -- {label="Program 5", program="program3.lua", color = colors.red}
587 }
588
589 -- Set the background color and padding size
590 local bgColor = colors.black
591 local padding = 2
592
593 -- Calculate the size of the buttons and the total size of the interface
594 local buttonWidth = 24
595 local buttonHeight = 3
596 local interfaceWidth, interfaceHeight = term.getSize()
597 interfaceHeight = (buttonHeight + padding) * #buttons + padding
598
599 -- Create a new canvas to draw the interface on
600 local canvas = {}
601 for y = 1, interfaceHeight do
602 canvas[y] = {}
603 for x = 1, interfaceWidth do
604 canvas[y][x] = {bg = bgColor, fg = colors.white, char = " "}
605 end
606 end
607
608 -- Draw the background on the canvas
609 for y = 1, interfaceHeight do
610 for x = 1, interfaceWidth do
611 canvas[y][x].bg = bgColor
612 end
613 end
614
615 -- Draw the buttons on the canvas
616 for i, button in ipairs(buttons) do
617 local x = padding
618 local y = padding + (i-1) * (buttonHeight + padding)
619 for y2 = y, y + buttonHeight - 1 do
620 for x2 = x, x + buttonWidth - 1 do
621 canvas[y2][x2].bg = button.color
622 end
623 end
624 local label = string.sub(button.label, 1, buttonWidth)
625 local labelLength = #label
626 local labelX = x + math.floor((buttonWidth - labelLength) / 2)
627 local labelY = y + math.floor((buttonHeight - 1) / 2)
628 for j = 1, labelLength do
629 canvas[labelY][labelX+j-1] = {bg = button.color, fg = colors.black, char = string.sub(label, j, j)}
630 end
631 end
632
633 -- Draw the canvas on the screen
634 term.setBackgroundColor(bgColor)
635 term.clear()
636 for y = 1, interfaceHeight do
637 for x = 1, interfaceWidth do
638 term.setCursorPos(x, y)
639 term.setTextColor(canvas[y][x].fg)
640 term.setBackgroundColor(canvas[y][x].bg)
641 term.write(canvas[y][x].char)
642 end
643 end
644 receiveInfos()
645
646-- Wait for a button to be clicked
647 while true do
648 local event, _, x, y = os.pullEvent("mouse_click")
649 for i, button in ipairs(buttons) do
650 local buttonX = padding
651 local buttonY = padding + (i-1) * (buttonHeight + padding)
652 if x >= buttonX and x < buttonX + buttonWidth and y >= buttonY and y < buttonY + buttonHeight then
653 showNotifications = false
654 -- print(button.label)
655 button.program()
656 return
657 end
658 end
659 end
660end
661
662
663
664-- while true do
665-- parallel.waitForAny(showButtons, receiveInfos)
666-- end
667
668
669showButtons()
670-- while true do
671
672-- end