Advertisement
MrFinn

ComputerCraft - Glados v2

Nov 30th, 2024 (edited)
30
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.46 KB | None | 0 0
  1. -- Configuration
  2. local TEXT_SCALE = 2 -- Text size (0.5, 1, 2, ...)
  3. local TEXT_COLOR = colors.orange -- Text color (use colors.<color>)
  4.  
  5. -- HTTP API setup
  6. assert(http, "HTTP API is not enabled. Check your ComputerCraft config.")
  7. local API_URL = "https://lordfinn.fr/api/ask-glados"
  8.  
  9. -- Setup monitors and speaker
  10. local monitors = {}
  11. local speaker = peripheral.wrap("bottom")
  12. assert(speaker, "No speaker connected on the bottom side!")
  13.  
  14. for _, name in ipairs(peripheral.getNames()) do
  15. if peripheral.getType(name) == "monitor" and peripheral.isPresent(name) then
  16. local monitor = peripheral.wrap(name)
  17. monitor.setTextScale(TEXT_SCALE)
  18. table.insert(monitors, monitor)
  19. end
  20. end
  21.  
  22. local function splitIntoLines(text, maxWidth)
  23. local lines = {}
  24. while #text > maxWidth do
  25. local splitPoint = maxWidth
  26. for i = maxWidth, 1, -1 do
  27. if text:sub(i, i):match("%s") then
  28. splitPoint = i
  29. break
  30. end
  31. end
  32. local line = text:sub(1, splitPoint):gsub("^%s+", ""):gsub("%s+$", "")
  33. table.insert(lines, line)
  34. text = text:sub(splitPoint + 1):gsub("^%s+", "")
  35. end
  36. if #text > 0 then
  37. table.insert(lines, text)
  38. end
  39. return lines
  40. end
  41.  
  42. local function sanitizeText(text)
  43. -- Replace UTF-8 artifacts with proper characters
  44. text = text:gsub("é", "é")
  45. text = text:gsub("è", "è")
  46. text = text:gsub("ê", "ê")
  47. text = text:gsub("ë", "ë")
  48. text = text:gsub("Ã ", "à")
  49. text = text:gsub("Ã ", "â")
  50. text = text:gsub("Ã ", "ä")
  51. local replacements = {
  52. ["é"] = "e", ["è"] = "e", ["ê"] = "e", ["ë"] = "e",
  53. ["à"] = "a", ["â"] = "a", ["ä"] = "a",
  54. ["ç"] = "c",
  55. ["ù"] = "u", ["û"] = "u", ["ü"] = "u",
  56. ["î"] = "i", ["ï"] = "i",
  57. ["ô"] = "o", ["ö"] = "o",
  58. ["â"] = "a", ["ã"] = "a",
  59. ["œ"] = "oe", ["æ"] = "ae",
  60. ["ÿ"] = "y",
  61. ["É"] = "E", ["È"] = "E", ["Ê"] = "E", ["Ë"] = "E",
  62. ["À"] = "A", ["Â"] = "A", ["Ä"] = "A",
  63. ["Ç"] = "C",
  64. ["Ù"] = "U", ["Û"] = "U", ["Ü"] = "U",
  65. ["Î"] = "I", ["Ï"] = "I",
  66. ["Ô"] = "O", ["Ö"] = "O",
  67. ["Â"] = "A", ["Ã"] = "A",
  68. ["Œ"] = "OE", ["Æ"] = "AE",
  69. ["Ÿ"] = "Y"
  70. }
  71. -- Replace each character in the text based on the replacements table
  72. for original, replacement in pairs(replacements) do
  73. text = text:gsub(original, replacement)
  74. end
  75. return text
  76. end
  77.  
  78. -- Display message centered on monitors
  79. local function displayMessageCentered(message)
  80. message = sanitizeText(message)
  81. for _, monitor in ipairs(monitors) do
  82. monitor.clear()
  83. monitor.setTextColor(TEXT_COLOR)
  84. local width, height = monitor.getSize()
  85. local lines = splitIntoLines(message, width)
  86. local yStart = math.floor((height - #lines) / 2) + 1
  87.  
  88. for i, line in ipairs(lines) do
  89. local xStart = math.floor((width - #line) / 2) + 1
  90. monitor.setCursorPos(xStart, yStart + i - 1)
  91. monitor.write(line)
  92. end
  93. end
  94. end
  95.  
  96. local function playTextToSpeech()
  97. local url = API_URL .. "/last-audio"
  98. local response, err = http.get({ url = url, binary = true })
  99. if not response then
  100. print("Error fetching TTS audio: " .. err)
  101. return
  102. end
  103.  
  104. local decoder = require("cc.audio.dfpwm").make_decoder()
  105.  
  106. while true do
  107. local chunk = response.read(16 * 1024)
  108. if not chunk then break end
  109.  
  110. local buffer = decoder(chunk)
  111. while not speaker.playAudio(buffer) do
  112. os.pullEvent("speaker_audio_empty")
  113. end
  114. end
  115. response.close()
  116. end
  117.  
  118. -- Fetch and display the last response on startup
  119. local function displayLastResponse()
  120. local url = API_URL .. "/last"
  121. local response, err = http.get(url)
  122. if not response then
  123. print("Error fetching last response: " .. err)
  124. return
  125. end
  126.  
  127. local responseBody = textutils.unserializeJSON(response.readAll())
  128. response.close()
  129.  
  130. if responseBody and responseBody.response then
  131. displayMessageCentered(responseBody.response)
  132. else
  133. displayMessageCentered("No last response available.")
  134. end
  135. end
  136.  
  137. -- Main program loop
  138. local function main()
  139. -- Call the /last route on startup and display the response if it exists
  140. displayLastResponse()
  141.  
  142. print("Type a message to ask GLaDOS:")
  143. while true do
  144. write("> ")
  145. local userInput = read()
  146. if userInput and userInput ~= "" then
  147. print("Asking GLaDOS...")
  148. displayMessageCentered("Thinking...")
  149. local response, err = http.post(API_URL, textutils.serializeJSON({ question = userInput }), { ["Content-Type"] = "application/json" })
  150. if not response then
  151. print("Error: " .. (err or "Unknown error"))
  152. displayMessageCentered("Error contacting GLaDOS.")
  153. else
  154. local responseBody = textutils.unserializeJSON(response.readAll())
  155. response.close()
  156.  
  157. if responseBody and responseBody.response then
  158. displayMessageCentered(responseBody.response)
  159. playTextToSpeech()
  160. end
  161. end
  162. else
  163. print("Please enter a valid question.")
  164. end
  165. end
  166. end
  167.  
  168. main()
  169.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement