Advertisement
rufo123

Untitled

May 28th, 2016
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.69 KB | None | 0 0
  1. local peripheralList = peripheral.getNames()
  2. local modemside
  3. local modemPeripheral
  4. local chatPeripheral
  5. local tempList = {}
  6. local lastChatMessage = {}
  7. local lastChatNames = {}
  8. local fileHandler
  9. local eventHandler
  10. local keepRunning = true
  11.  
  12. --Modify this if you want to rename your AI. It will then respond to that new name.
  13. --TODO: Add function to change name via commands
  14. local aiName = "OLLAND"
  15.  
  16. --This is the original SysOp screenname that will always have permission via chat
  17. local sysOpName = "ERNA_VIDA"
  18.  
  19. --[[
  20. Requires HTTPS to be enabled. Downloads a new program
  21. The program must always be named the same as the command you later want to use with it.
  22. IE: For the command "Olland tell time" the program must be named "TELLTIME"
  23. ]]
  24. function downloadNewSource(args)
  25. if shell.run("pastebin", "get", args[1], args[2]) then
  26. talk("Program "..args[2].." successfully downloaded.")
  27. else
  28. talk("Program "..args[2].." could not be downloaded.")
  29. end
  30. end --End downloadNewSource()
  31.  
  32. --[[
  33. This adds a server to the list of ones olland has to call. Thiss isn't used in the core but can be useful for other programs.
  34. The computer info has to be set at the server and needs to be a table with keys "computerType" and "computerAlias".
  35. To get the AI ID its expected that a wireless modem be open and listening for a computer to send out a "AIREQNEWSERVER" message
  36. then replying with the serialized computer info table and waiting for the ACK message sent directly to it.
  37. ]]
  38. function addServer()
  39. if modemSide then
  40. rednet.open(modemSide)
  41. rednet.broadcast("AIREQNEWSERVER")
  42. local senderId, message, distance = rednet.receive(10)
  43. if message then
  44. sleep(1)
  45. rednet.send(senderId,"ACK")
  46. local replyTable = textutils.unserialize(message)
  47. local serverTable = loadTable("serverTable")
  48. if not serverTable[replyTable["computerType"]] then
  49. serverTable[replyTable["computerType"]] = {}
  50. end
  51. serverTable[replyTable["computerType"]][replyTable["computerAlias"]] = senderId
  52. saveTable("serverTable",serverTable)
  53. talk("A new server of type "..replyTable["computerType"].." with alias "..replyTable["computerAlias"].." has been added.")
  54. else
  55. talk("No new devices replied, no devices added.")
  56. end
  57. rednet.close(modemSide)
  58. else
  59. talk("I don't have a wireless modem to add servers with.")
  60. end
  61. end --End addServer()
  62.  
  63. --Self explanatory. Uses either the attached miscperipherals chatbox or the console to talk.
  64. --TODO: Peripheral glasses support
  65. function talk(message)
  66. if chatPeripheral then
  67. chatPeripheral.say(aiName..": "..message)
  68. else
  69. print(aiName..": "..message.."\n")
  70. end
  71. end --End talk()
  72.  
  73. --This is the part of the script that actually executes commands, first interpreting them
  74. function executeCommand(commandToExecute, arguments, requestorPermLevel)
  75.  
  76. --These tables store the list of known aliases and the actual commands olland understands, respectively
  77. local commandsAliasing = loadTable("commandsAlias")
  78. local commandList = loadTable("commandList")
  79.  
  80. --This will eventually (or in some caes currently do) store the actual comands and argument table Olland can work with
  81. local translatedCommand = string.upper(commandToExecute)
  82. local translatedArgs = arguments
  83.  
  84. --This loops through de-aliasing commands until it reaches an actual command.
  85. --Aliased commands can themselves be aliased, but it still shouldn't go through this loop more than once
  86. --Aliased arguments will be inserted, with passed arguments inserted into blank spots in the aliased argument list
  87. while commandsAliasing and commandsAliasing[translatedCommand] do
  88. local commandTable = commandsAliasing[translatedCommand]
  89. local aliasedArgs = commandTable["args"]
  90. local tempArgs = textutils.unserialize(textutils.serialize(translatedArgs))
  91. local passedArgs = 1
  92. for i = 1, #aliasedArgs do
  93. if aliasedArgs[i] and not (aliasedArgs[i] == "") then
  94. translatedArgs[i] = aliasedArgs[i]
  95. else
  96. translatedArgs[i] = tempArgs[passedArgs]
  97. passedArgs = passedArgs + 1
  98. end
  99. end
  100. translatedCommand = commandTable["command"]
  101. end
  102.  
  103. --The hard coded functions are called first, all require a permission level of 10 (SysOp)
  104. --See the function declarations for info
  105. if translatedCommand == "SHUTDOWN" and requestorPermLevel >= 10 then
  106. keepRunning = false
  107. talk("Goodbye.")
  108. elseif translatedCommand == "ADDUSER" and requestorPermLevel >= 10 then
  109. addUser(translatedArgs)
  110. elseif translatedCommand == "ADDSERVER" and requestorPermLevel >= 10 then
  111. addServer()
  112. elseif translatedCommand == "DOWNLOADNEWSOURCE" and requestorPermLevel >=10 then
  113. downloadNewSource(translatedArgs)
  114. elseif translatedCommand == "ADDCOMMAND" and requestorPermLevel >= 10 then
  115. addCommand(translatedArgs)
  116. elseif translatedCommand == "ADDCOMMANDALIAS" and requestorPermLevel >= 10 then
  117.  
  118. --This de-aliases the command to be aliased, allowing users to alias already aliased commands
  119. --IE: "Tell time" is already aliased as "what time is it", but "what time is it" can be aliased
  120. --itself as "give me the time" and still work.
  121. while commandsAliasing and commandsAliasing[translatedArgs[1]] do
  122. local commandTable = commandsAliasing[translatedArgs[1]]
  123. local aliasedArgs = commandTable["args"]
  124. local tempArgs = textutils.unserialize(textutils.serialize(translatedArgs))
  125. local passedArgs = 3
  126. for i = 1, #aliasedArgs do
  127. if aliasedArgs[i] and not aliasedArgs[i] == "" then
  128. tempArgs[i + 2] = aliasedArgs[i]
  129. else
  130. tempArgs[i + 2] = translatedArgs[passedArgs]
  131. passedArgs = passedArgs + 1
  132. end
  133. end
  134. translatedArgs = tempArgs
  135. translatedArgs[1] = commandTable["command"]
  136. end
  137. addCommandAlias(translatedArgs)
  138.  
  139. --This calls other programs and passes in the arguments specified if the user has appropriate permission
  140. --Also passes the requestor perm level so that some functions of the called program can be restricted based on that
  141. elseif commandList[translatedCommand] and requestorPermLevel >= commandList[translatedCommand] then
  142. if modemSide then
  143. rednet.open(modemSide)
  144. end
  145. talk(assert(loadfile(translatedCommand))(textutils.serialize(translatedArgs),requestorPermLevel))
  146. if modemSide then
  147. rednet.close(modemSide)
  148. end
  149.  
  150. --These send a message if the command exists but the user doesn't have permission to it or the command doesn't exist
  151. elseif commandList[translatedCommand] and requestorPermLevel < commandList[translatedCommand] then
  152. talk("I'm afraid you don't have proper premission for that command.")
  153. else
  154. talk("I don't recognize that command")
  155. end
  156.  
  157. commandsAliasing = {}
  158. end --End executeCommand
  159.  
  160. --[[
  161. This adds a new function alias. This command needs to be called in the below format:
  162. aiName add command alias, command to alias, alias, alias arguments
  163. Alias arguments must include all arguments command to alias takes, with blanks left for arguments still expected
  164. IE: function1(arg1,arg2,arg3) could be aliased as "Olland add command alias, function1, alias name, 1,,3"
  165. When called later, it would be done as "Olland alias name, 2" which would be equivilent to "Olland function1,1,2,3"
  166. ]]
  167. function addCommandAlias(commandInfo)
  168. local commandList = loadTable("commandList")
  169. local commandsAliasing = loadTable("commandsAlias")
  170. if commandList and commandList[commandInfo[1]] then
  171. local argTable = {}
  172. for i = 1, #commandInfo do
  173. if i > 2 then
  174. argTable[i - 2] = commandInfo[i]
  175. end
  176. end
  177. commandsAliasing[commandInfo[2]] = {}
  178. commandsAliasing[commandInfo[2]]["command"] = commandInfo[1]
  179. commandsAliasing[commandInfo[2]]["args"] = argTable
  180. saveTable("commandsAlias",commandsAliasing)
  181. talk("Command \""..commandInfo[1].."\" aliased as \""..commandInfo[2].."\" successfully.")
  182. else
  183. talk("The command you're trying to alias does not seem to exist.")
  184. end
  185. end --End addCommandAlias()
  186.  
  187. --[[
  188. This adds a new command. The file for the command must already exist
  189. The file for a command must be the command text with no spaces and all capitalized
  190. IE: Command "this command" must have an existing file "THISCOMMAND"
  191. The Second parameter must be a number representing the minimum permission level of a user to
  192. access this command.
  193. ]]
  194. function addCommand(commandToAdd)
  195. if fs.exists(commandToAdd[1]) and commandToAdd[2] then
  196. local commands = loadTable("commandList")
  197. commands[commandToAdd[1]] = tonumber(commandToAdd[2])
  198. saveTable("commandList",commands)
  199. talk("Command "..commandToAdd[1].." with permission level "..commandToAdd[2].." added successfully.")
  200. elseif not commandToAdd[2] then
  201. talk("You need to specify what permission level is acceptable for this.")
  202. else
  203. talk("The source code file for "..commandToAdd[1].." does not exist. No command added.")
  204. end
  205. end --End addCommand()
  206.  
  207. --This is used to split up argument lists (though it will technically work on anything)
  208. --This returns a table of the split up values based on splitChar
  209. function splitArguments(stringToSplit, splitChar)
  210. if stringToSplit then
  211. local startSearch = 1
  212. local startSplit, endSplit = string.find(stringToSplit.."",splitChar,startSearch)
  213. local argsTable = {}
  214. local count = 1
  215.  
  216. while startSplit do
  217. argsTable[count] = string.sub(stringToSplit.."",startSearch,startSplit - 1)
  218. startSearch = endSplit + 1
  219. startSplit, endSplit = string.find(stringToSplit.."",splitChar,startSearch)
  220. count = count + 1
  221. end
  222. argsTable[count] = string.sub(stringToSplit.."",startSearch)
  223.  
  224. return argsTable
  225. else
  226. return {}
  227. end
  228. end --End splitArguments()
  229.  
  230. --This is used to add a user with two arguments expected, username and permission level (as a number)
  231. --TODO: Consider moving this to a include file so it can be used across called applications
  232. function addUser(userToAdd)
  233. local userTable = loadTable("usersList")
  234. userTable[userToAdd[1]] = userToAdd[2]
  235. saveTable("userList",userTable)
  236. talk("User "..userToAdd[1].." has been added with a permission level of "..userToAdd[2]..".")
  237. end --End addUser()
  238.  
  239. --This is called to save a table to a file
  240. --TODO: Consider moving this to a include file so it can be used across called applications
  241. function saveTable(fileName, sourceTable)
  242. fileHandler = fs.open(fileName, "w")
  243. fileHandler.write(textutils.serialize(sourceTable))
  244. fileHandler.close()
  245. end --End saveTable()
  246.  
  247. --This is called to load a table from a file. Returns an empty table if the file does not exist
  248. function loadTable(fileName)
  249. if fs.exists(fileName) then
  250. fileHandler = fs.open(fileName, "r")
  251. local tableData = textutils.unserialize(fileHandler.readAll())
  252. fileHandler.close()
  253. return tableData
  254. else
  255. return {}
  256. end
  257. end --End loadTable()
  258.  
  259. --This just scans for peripherals its expecting (wireless modem and a chatbox)
  260. --TODO: Add peripheral glasses bridge support
  261. for i = 1, #peripheralList do
  262. if peripheral.getType(peripheralList[i]) == "modem" and peripheral.call(peripheralList[i], "isWireless") then
  263. modemSide = peripheralList[i]
  264. modemPeripheral = peripheral.wrap(modemSide)
  265. elseif peripheral.getType(peripheralList[i]) == "chat" then
  266. chatPeripheral = peripheral.wrap(peripheralList[i])
  267. end
  268. end
  269.  
  270. --Generic greeting on boot. Creative, right?
  271. talk("Greetings! Please let me know if you need anything.")
  272.  
  273. --If the commandList file does not yet exist, create it with the built in commands
  274. --Essential to allow aliasing of the built in commands
  275. if (not fs.exists("commandList")) then
  276. local commandList = {}
  277. commandList["ADDUSER"] = 10
  278. commandList["ADDSERVER"] = 10
  279. commandList["ADDCOMMAND"] = 10
  280. commandList["ADDCOMMANDALIAS"] = 10
  281. commandList["DOWNLOADNEWSOURCE"] = 10
  282. commandList["SHUTDOWN"] = 10
  283. saveTable("commandList",commandList)
  284. end
  285.  
  286. --The main loop of the program
  287. while keepRunning do
  288.  
  289. --Either gets chat events or events directly to the console
  290. if chatPeripheral then
  291. event, lastChatNames[1], lastChatMessage[1], lastChatNames[2], lastChatMessage[2], lastChatNames[3], lastChatMessage[3], lastChatNames[4], lastChatMessage[4], lastChatNames[5], lastChatMessage[5] = os.pullEvent("chat")
  292. else
  293. print("Enter Command: ")
  294. lastChatNames[1] = "CONSOLE"
  295. lastChatMessage[1] = read()
  296. end
  297.  
  298. local counter = 1
  299.  
  300. --Gets the list of valid users
  301. tempTable = loadTable("userList")
  302.  
  303. --Filters through the list of chat names from the last chat event
  304. while lastChatNames[counter] do
  305.  
  306. --If anyone started a command with the aiName, checks to see if it should bother executing
  307. if string.upper(string.sub(lastChatMessage[counter],1,string.len(aiName))) == aiName then
  308.  
  309. --Gets the actual command and breaks out the arguments
  310. local command = string.gsub(string.sub(lastChatMessage[counter],string.len(aiName)+1)," ","")
  311. local commaStart,commaEnd = string.find(command,",")
  312. local arguments = {}
  313. if commaEnd then
  314. commaEnd = commaEnd + 1
  315. local argString = string.upper(string.sub(command,commaEnd))
  316. arguments = splitArguments(argString,",")
  317. command = string.sub(command,1,commaStart - 1)
  318. end
  319.  
  320. --Checks if the sysOp or a registered user made the request. If so, executes the command, if not, stops.
  321. if string.upper(lastChatNames[counter]) == sysOpName or string.upper(lastChatNames[counter]) == "CONSOLE" then
  322. executeCommand(command,arguments,10)
  323. elseif tempTable and tempTable[lastChatNames[counter]] then
  324. executeCommand(command,arguments,tempTable[lastChatNames[counter]])
  325. end
  326. arguments = {}
  327. end
  328. counter = counter + 1
  329. end
  330.  
  331. --Clears the tables for the next run through the loop
  332. lastChatNames = {}
  333. lastChatMessage = {}
  334. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement