Advertisement
Mojokojo69

chat client

Aug 29th, 2023 (edited)
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.60 KB | None | 0 0
  1. -- Metadata and Constants
  2. local authorName = "Rare Corp."
  3. local logoArt = [[
  4. ___ _____
  5. / _ \___ ________ / ___/__ _______
  6. / , _/ _ `/ __/ -_) /__/ _ \/ __/ _ \
  7. /_/|_|\_,_/_/ \__/\___/\___/_/ / .__/
  8. /_/ ]]
  9. local productVersion = "1.0"
  10. local productName = "CC-AI Chat Client"
  11. local rateLimitMs = 2000 -- 2 seconds in milliseconds
  12. local maxBufferLength = 1000 -- Limit the size of the conversation buffer
  13. local lastRequestTime = 0
  14. local rateLimit = 1 -- Rate limit in seconds, change as needed
  15.  
  16. -- Colors
  17. local uiColors = {
  18. userNameColor = colors.blue,
  19. userChatColor = colors.lightBlue,
  20. otherNameColor = colors.orange,
  21. otherChatColor = colors.yellow,
  22. commandColor = colors.purple,
  23. errorColor = colors.red,
  24. systemColor = colors.green,
  25. helpColor = colors.cyan,
  26. }
  27.  
  28. -- randomize logo color
  29. local logoColors = {colors.orange, colors.magenta, colors.lightBlue, colors.yellow, colors.lime, colors.pink, colors.cyan, colors.purple, colors.blue, colors.green, colors.red}
  30. local logoColor = logoColors[math.random(#logoColors)]
  31.  
  32. -- Configuration
  33. local configFileName = "chat_config.txt"
  34. local config = {chatChannel = 7, userName = "", uiColors=uiColors}
  35. local computerid = os.getComputerID()
  36.  
  37. -- Peripheral
  38. local monitor = peripheral.find("monitor")
  39. local modem = peripheral.find("modem")
  40.  
  41. -- Buffer of conversation history
  42. local conversationBuffer = {}
  43. local scrollPosition = 1
  44.  
  45. -- Track if we've reached max dimensions
  46. local reachedMaxDims = false
  47.  
  48. -- Add a variable to track cursor position
  49. local cursorAtStartOfLine = true
  50.  
  51. -- Update and return current time
  52. local function updateTime()
  53. local time = os.time()
  54. return textutils.formatTime(time, false)
  55. end
  56.  
  57. -- Collect data for API
  58. local function collectData(msg)
  59. return {
  60. username = config.userName,
  61. msg = msg,
  62. gameday = os.day(),
  63. gametime = updateTime(),
  64. gameuptime = os.clock(),
  65. computerid = computerid or "Unknown"
  66. }
  67. end
  68.  
  69. -- Validate configuration data
  70. local function validateConfig(configData)
  71. -- Check baseURL
  72. if type(configData.chatChannel) ~= "number" or configData.chatChannel < 0 then
  73. print("Invalid baseURL.")
  74. return false
  75. end
  76.  
  77. -- Check userName
  78. if type(configData.userName) ~= "string" or configData.userName == "" then
  79. print("Invalid userName.")
  80. return false
  81. end
  82.  
  83. return true
  84. end
  85.  
  86. -- Save Config to file
  87. local function saveConfig(config)
  88. if validateConfig(config) then
  89. local configData = textutils.serializeJSON(config)
  90. local file = fs.open(configFileName, "w")
  91. file.write(configData)
  92. file.close()
  93. else
  94. print("Invalid configuration data.")
  95. end
  96. end
  97.  
  98. -- Load Config from file
  99. local function loadConfig()
  100. if fs.exists(configFileName) then
  101. local file = fs.open(configFileName, "r")
  102. local configData = file.readAll()
  103. file.close()
  104. local loadedConfig = textutils.unserializeJSON(configData)
  105. if validateConfig(loadedConfig) then
  106. config = loadedConfig
  107. else
  108. print("Invalid configuration file.")
  109. end
  110. end
  111. end
  112.  
  113. -- Print a character to the monitor and manage line wrapping and scrolling
  114. local function printCharToMonitor(char, x, y)
  115. if not monitor then
  116. return x, y
  117. end
  118.  
  119. local width, height = monitor.getSize()
  120. if not width or not height then
  121. return x, y
  122. end
  123.  
  124. if char == "\n" then
  125. if cursorAtStartOfLine then
  126. return x, y
  127. end
  128. cursorAtStartOfLine = true
  129. if y < height then
  130. return 1, y + 1
  131. else
  132. monitor.scroll(1)
  133. return 1, height
  134. end
  135. else
  136. cursorAtStartOfLine = false
  137. monitor.setCursorPos(x, y)
  138. monitor.write(char)
  139. x = x + 1
  140. if x > width then
  141. if y < height then
  142. x = 1
  143. y = y + 1
  144. else
  145. monitor.scroll(1)
  146. x = 1
  147. y = height
  148. end
  149. end
  150. return x, y
  151. end
  152. end
  153.  
  154. -- Buffer of conversation history
  155. local conversationBuffer = {}
  156. local scrollPosition = 1
  157.  
  158. -- Function to redraw the monitor with the conversation history
  159. local function redrawMonitor()
  160. if not monitor then
  161. return
  162. end
  163.  
  164. monitor.clear()
  165. local x, y = 1, 1
  166. monitor.setCursorPos(x, y)
  167.  
  168. local lineCount = 0
  169.  
  170. for i = scrollPosition, #conversationBuffer do
  171. local line = conversationBuffer[i]
  172. for _, segment in ipairs(line) do
  173. monitor.setTextColor(segment.color)
  174. for j = 1, #segment.message do
  175. local char = segment.message:sub(j, j)
  176. x, y = printCharToMonitor(char, x, y)
  177. end
  178. end
  179. x, y = printCharToMonitor("\n", x, y)
  180. lineCount = lineCount + 1
  181.  
  182. local _, height = monitor.getSize()
  183. if lineCount >= height then
  184. scrollPosition = scrollPosition + 1
  185. break
  186. end
  187. end
  188. end
  189.  
  190. -- Initialize user entry to the bottom left
  191. local function initializeUserEntry()
  192. term.clearLine()
  193. local x, y = term.getCursorPos()
  194. term.setCursorPos(1, y - 1)
  195. term.setTextColor(colors.gray)
  196. term.write(config.userName .. ": ")
  197. end
  198.  
  199. -- Print message to both terminal and monitor
  200. local function printToBoth(message, color, appendToLast)
  201. term.setTextColor(color)
  202. write(message)
  203. if appendToLast == nil then
  204. appendToLast = false
  205. end
  206.  
  207. if appendToLast and #conversationBuffer > 0 then
  208. table.insert(conversationBuffer[#conversationBuffer], {message = message, color = color})
  209. else
  210. table.insert(conversationBuffer, {{message = message, color = color}})
  211. end
  212. redrawMonitor()
  213. printCharToMonitor("\n", x, y)
  214. end
  215.  
  216. -- Print a message one character at a time
  217. local function printTyping(message, color)
  218. if message == nil then
  219. return
  220. end
  221. local isFirstChar = true
  222. for i = 1, #message do
  223. local char = message:sub(i, i)
  224. printToBoth(char, color, not isFirstChar)
  225. isFirstChar = false
  226. sleep(0.01)
  227. end
  228. printToBoth("\n", color)
  229. end
  230.  
  231. -- Print the welcome message
  232. local function welcomeMessage()
  233. printToBoth(logoArt, logoColor)
  234. printToBoth("\nWelcome to " .. productName .. " by " .. authorName .. " \n(Version " .. productVersion .. ")\n", config.uiColors.systemColor)
  235. printToBoth("Type /settings to change settings\n", config.uiColors.systemColor)
  236. printToBoth("Type /help for a list of commands\n", config.uiColors.systemColor)
  237. printToBoth("Type /exit to exit the program\n\n", config.uiColors.systemColor)
  238. printToBoth("Conversation starts here:\n", config.uiColors.otherChatColor)
  239. end
  240.  
  241. -- Print the help message
  242. local function printHelp()
  243. printToBoth("Config File:" .. configFileName .. "\n", config.uiColors.systemColor)
  244. printToBoth("Commands:\n", config.uiColors.systemColor)
  245. printToBoth("/welcome - Print the welcome message\n", config.uiColors.helpColor)
  246. printToBoth("/settings - Change settings\n", config.uiColors.helpColor)
  247. printToBoth("/clear - Clear the screen\n", config.uiColors.helpColor)
  248. printToBoth("/version - Print the version number\n", config.uiColors.helpColor)
  249. printToBoth("/help - Print this help message\n", config.uiColors.helpColor)
  250. printToBoth("/exit - Exit the program\n\n", config.uiColors.helpColor)
  251. end
  252.  
  253. -- Read input with a msg
  254. local function readInput(msg)
  255. term.setTextColor(colors.gray)
  256. write(msg)
  257.  
  258. local input = read()
  259.  
  260. local x, y = term.getCursorPos()
  261. term.setCursorPos(1, y - 1)
  262. term.clearLine()
  263. print()
  264. return input
  265. end
  266.  
  267. local colorOptions = {"userNameColor", "userChatColor", "otherNameColor", "otherChatColor", "commandColor", "errorColor", "systemColor", "helpColor", "logoColor"}
  268.  
  269. -- Function to handle changing colors via a command tree
  270. local function handleColorChange()
  271. printToBoth("Color Settings Menu:\n", config.uiColors.systemColor)
  272.  
  273. for i, option in ipairs(colorOptions) do
  274. printToBoth(i .. ". Change " .. option .. "\n", config.uiColors.systemColor)
  275. end
  276. printToBoth(#colorOptions + 1 .. ". Set Default Colors\n", config.uiColors.systemColor)
  277. printToBoth(#colorOptions + 2 .. ". Abort\n", config.uiColors.systemColor)
  278.  
  279. local selectedIndex = tonumber(readInput("\nEnter the number of the color setting you'd like to change: "))
  280.  
  281. if selectedIndex and selectedIndex >= 1 and selectedIndex <= #colorOptions then
  282. local selectedOption = colorOptions[selectedIndex]
  283.  
  284. printToBoth("Available colors: white, orange, magenta, lightBlue, yellow, lime, pink, gray, lightGray, cyan, purple, blue, brown, green, red, black\n", config.uiColors.helpColor)
  285.  
  286. local newColor = readInput("\nEnter the new color name: ")
  287.  
  288. if colors[newColor] then
  289. config.uiColors[selectedOption] = colors[newColor]
  290. saveConfig(config)
  291. printToBoth("\nColor for " .. selectedOption .. " changed to " .. newColor, config.uiColors.systemColor)
  292. else
  293. printToBoth("\nInvalid color name.", config.uiColors.errorColor)
  294. end
  295. elseif selectedIndex == #colorOptions + 1 then
  296. config.uiColors = uiColors
  297. saveConfig(config)
  298. printToBoth("\nDefault colors set.", config.uiColors.systemColor)
  299. elseif selectedIndex == #colorOptions + 2 then
  300. printToBoth("\nColor change aborted.", config.uiColors.systemColor)
  301. else
  302. printToBoth("\nInvalid option.", config.uiColors.errorColor)
  303. end
  304. end
  305.  
  306. -- Function to wipe configuration and restart
  307. local function wipeConfigAndRestart()
  308. if fs.exists(configFileName) then
  309. fs.delete(configFileName)
  310. end
  311. printToBoth("Configuration wiped. Rebooting now...", config.uiColors.systemColor)
  312. os.reboot()
  313. end
  314.  
  315. -- Function to handle changing various settings via a command tree
  316. local function handleSettings()
  317. printToBoth("Settings Menu:\n", config.uiColors.systemColor)
  318. printToBoth("1. Change User Name\n", config.uiColors.systemColor)
  319. printToBoth("2. Change modem channel\n", config.uiColors.systemColor)
  320. printToBoth("3. Change UI Colors\n", config.uiColors.systemColor)
  321. printToBoth("4. Wipe Config and Restart\n", config.uiColors.systemColor)
  322. printToBoth("5. Abort\n", config.uiColors.systemColor)
  323.  
  324. local selectedIndex = tonumber(readInput("\nEnter the number of the option you'd like to change: "))
  325.  
  326. if selectedIndex == 1 then
  327. config.userName = readInput("Enter your new name: \n")
  328. saveConfig(config)
  329. elseif selectedIndex == 2 then
  330. config.chatChannel = readInput("Enter the new channel: \n")
  331. saveConfig(config)
  332. elseif selectedIndex == 3 then
  333. handleColorChange()
  334. elseif selectedIndex == 4 then
  335. wipeConfigAndRestart()
  336. elseif selectedIndex == 5 then
  337. printToBoth("\nSettings change aborted.", config.uiColors.systemColor)
  338. else
  339. printToBoth("\nInvalid option.", config.uiColors.errorColor)
  340. end
  341. end
  342.  
  343. -- Handle command input
  344. local function handleCommand(msg)
  345. local changed = false
  346. if msg == "/welcome" then
  347. welcomeMessage()
  348. elseif msg == "/settings" then
  349. handleSettings()
  350. elseif msg == "/clear" then
  351. term.clear()
  352. welcomeMessage()
  353. elseif msg == "/version" then
  354. printTyping(productVersion .. "\n", config.uiColors.systemColor)
  355. elseif msg == "/help" then
  356. printHelp()
  357. elseif msg == "/exit" then
  358. printToBoth("Exiting...\n\n", config.uiColors.systemColor, true)
  359. return true
  360. else
  361. printToBoth("Invalid command.\n", config.uiColors.errorColor)
  362. end
  363.  
  364. printToBoth("\n", colors.gray, true)
  365.  
  366. if changed then
  367. if validateConfig(config) then
  368. saveConfig(config)
  369. else
  370. printToBoth("Configuration is invalid.\n", config.uiColors.errorColor)
  371. end
  372. end
  373. end
  374.  
  375. -- handle incoming messages
  376. local function handleIncomingMessage(messageTable)
  377. if messageTable.sender ~= config.userName then -- Filter out own messages
  378. printToBoth("\n", colors.gray, true)
  379. printToBoth(messageTable.sender .. ": " .. "\n", config.uiColors.otherNameColor)
  380. printTyping(messageTable.message .. "\n", config.uiColors.otherChatColor)
  381. sleep(0.1)
  382. initializeUserEntry()
  383. end
  384. end
  385.  
  386. -- Function to listen for incoming messages
  387. local function listen()
  388. modem.open(config.chatChannel)
  389. while true do
  390. local event, modemSide, senderChannel, replyChannel, messageTable, senderDistance = os.pullEvent("modem_message")
  391.  
  392. if senderChannel == config.chatChannel then
  393. term.clearLine()
  394. handleIncomingMessage(messageTable)
  395. end
  396. end
  397. end
  398.  
  399. -- Handle user input
  400. local function handleInput(msg)
  401. if msg:sub(1, 1) == "/" then
  402. return handleCommand(msg, config)
  403. else
  404. modem.transmit(config.chatChannel, config.chatChannel, {message = msg, sender = config.userName})
  405. printToBoth(config.userName .. ": " .. "\n", config.uiColors.userNameColor)
  406. printTyping(msg, config.uiColors.userChatColor)
  407. return false
  408. end
  409. end
  410.  
  411. -- Main Loop
  412. local function mainLoop(config)
  413. parallel.waitForAny(
  414. function()
  415. while true do
  416. local msg = readInput(config.userName .. ": ")
  417. local shouldExit = handleInput(msg, config)
  418. if shouldExit then
  419. printToBoth("Goodbye! Thank you for using " .. productName .. " by " .. authorName, config.uiColors.systemColor)
  420. break
  421. end
  422. end
  423. end,
  424. listen
  425. )
  426. end
  427.  
  428. -- Initialization
  429. local function initializeClient()
  430. loadConfig()
  431. if monitor then
  432. monitor.setTextScale(1)
  433. monitor.clear()
  434. else
  435. end
  436. if not config.userName or config.userName == "" then
  437. config.userName = readInput("Enter your name: ")
  438. end
  439. if not config.chatChannel or config.chatChannel == "" then
  440. config.chatChannel = tonumber(readInput("Enter the chat channel: "))
  441. end
  442. if not config.uiColors then
  443. config.uiColors = uiColors
  444. end
  445. saveConfig(config)
  446. welcomeMessage()
  447. mainLoop(config)
  448. end
  449.  
  450. -- Entry Point
  451. initializeClient()
  452.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement