Advertisement
Guest User

In case more is needed

a guest
Jan 19th, 2019
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.43 KB | None | 0 0
  1.  
  2.  
  3. local moduleManip = peripheral.wrap("top") -- Fix this
  4. if moduleManip ~= nil then
  5. moduleManip.capture("^!")
  6. end
  7. local mName = "&h(bagel 'n roger wuz here.)&i(https://www.youtube.com/watch?v=ByC8sRdL-Ro)<&r&dAllium&r>" --bot title
  8.  
  9. local color = require("color") --Sponsored by roger109z
  10. local allium = {} -- API table
  11. local plugins = {} -- Plugin table
  12.  
  13. allium.assert = function(condition, message, level)
  14. if not condition then error(message, level) end
  15. end
  16.  
  17. allium.register = function(name)
  18. assert(type(name) == "string", "Invalid argument #1 (string expected, got "..type(name)..")", 2)
  19. assert(plugins[name:lower()] == nil, "Invalid argument #1 (plugin exists under name "..name:lower()..")")
  20. plugins[name:lower()] = {threads = {}, commands = {}, info = {}, name = name}
  21. local funcs = {}
  22. local this = plugins[name:lower()]
  23. funcs.command = function(name, command, info)
  24. assert(type(name) == "string", "Invalid argument #1 (string expected, got "..type(name)..")", 2)
  25. assert(type(command) == "function", "Invalid argument #2 (function expected, got "..type(command)..")", 2)
  26. assert(this.commands[name:lower()] == nil, "Invalid argument #2 (command exists under name "..name:lower().." for plugin "..this.name..")", 2)
  27. assert(type(info) == "string", "Invalid argument #3 (string expected, got "..type(info)..")", 2)
  28. this.commands[name:lower()] = command
  29. this.info[name:lower()] = info
  30. end
  31.  
  32. funcs.thread = function(thread)
  33. assert(type(thread) == "function", "Invalid argument #1 (function expected, got "..type(thread)..")", 2)
  34. this.threads[#this.threads+1] = thread
  35. end
  36. return funcs
  37. end
  38.  
  39. allium.tell = function(name, message, hidetag, botname) --allium.tell as documented in README
  40. local m
  41. if type(message) == "string" then
  42. m = message
  43. else
  44. m = ""
  45. end
  46. if type(botname) ~= "string" then
  47. botname = mName
  48. end
  49. local _, test = commands.tellraw(name, color.format((function(hidetag)if hidetag then return "" else return botname.."&r " end end)(hidetag)..m))
  50. if type(message) == "table" then
  51. for k, v in pairs(message) do
  52. local _, l = commands.tellraw(name, color.format(v))
  53. end
  54. end
  55. return textutils.serialise(test)
  56. end
  57.  
  58. allium.getPlayers = function()
  59. local didexec, input = commands.exec("list")
  60. if not didexec then
  61. local _, users = commands.testfor("@a")
  62. local out = {}
  63. for i = 1, #users do
  64. out[#out+1] = string.sub(users[i], 7, -1)
  65. end
  66. return out
  67. end
  68. local out = {}
  69. for user in string.gmatch(input[2], "%S+") do
  70. local comma = string.find(user, ",")
  71. if not comma then comma = -1 else comma=comma-1 end
  72. out[#out+1] = string.sub(user, 0, comma)
  73. end
  74. return out
  75. end
  76.  
  77. allium.getPersistence = function(name) --allium.getPersistence as documented in README
  78. if fs.exists("persistence.json") then
  79. local fper = fs.open("persistence.json", "r")
  80. local tpersist = textutils.unserialize(fper.readAll())
  81. fper.close()
  82. if not tpersist[origin] then
  83. tpersist[origin] = {}
  84. end
  85. if type(name) == "string" then
  86. return tpersist[origin][name]
  87. end
  88. end
  89. return false
  90. end
  91.  
  92. allium.setPersistence = function(name, data) --allium.setPersistence as documented in README
  93. local tpersist
  94. if fs.exists("persistence.json") then
  95. local fper = fs.open("persistence.json", "r")
  96. tpersist = textutils.unserialize(fper.readAll())
  97. fper.close()
  98. end
  99. if not tpersist[origin] then
  100. tpersist[origin] = {}
  101. end
  102. if type(name) == "string" then
  103. tpersist[origin][name] = data
  104. local fpers = fs.open("persistence.json", "w")
  105. fpers.write(textutils.serialise(tpersist))
  106. fpers.close()
  107. return true
  108. end
  109. return false
  110. end
  111.  
  112. allium.getInfo = function(plugin, command) -- Get the information of all plugins, a single plugin, or a single command from a plugin
  113. assert(plugin == nil or type(plugin) == "string", "Invalid argument #1 (string expected, got"..type(plugin)..")", 2)
  114. assert(command == nil or type(command) == "string", "Invalid argument #2 (string expected, got"..type(command)..")", 2)
  115. if command then
  116. assert(plugin, "Invalid argument #1 (string expected, got"..type(plugin)..")", 2)
  117. end
  118. if plugin then
  119. assert(plugins[plugin], "Invalid argument #1 (plugin "..plugin.." does not exist)", 2)
  120. if command then
  121. assert(plugins[plugin].command[command], "Invalid argument #2 (command "..command.." does not exist in plugin "..plugin..")")
  122. end
  123. end
  124. if command then
  125. return plugins[plugin].info[command]
  126. elseif plugin then
  127. local res = {}
  128. for k, v in pairs(plugins[plugin].info) do
  129. res[k] = v
  130. end
  131. return res
  132. else
  133. local res = {}
  134. for p_name, plugin in pairs(plugins) do
  135. res[p_name] = {}
  136. for c_name, info in pairs(plugin.info) do
  137. res[p_name][c_name] = info
  138. end
  139. end
  140. return res
  141. end
  142. end
  143.  
  144. local function is_require() -- This function was elegantly made by SquidDev
  145. -- See: https://discordapp.com/channels/477910221872824320/477911902152949771/536123240154660864
  146. if not shell then return("os.loadAPI") end
  147. if not package then return "shell.run" end -- Compat for old versions of CC
  148.  
  149. -- Locate the sentinel value, and check that it's currently within the table
  150. -- somewhere.
  151. package.preload["__sentinel"] = function() return package.loaded["__sentinel"] end
  152. local sentinel = require("__sentinel")
  153. for k, v in pairs(package.loaded) do
  154. if k ~= "__sentinel" and v == sentinel then return "require" end
  155. end
  156.  
  157. return "shell.run"
  158. end
  159. package.loaded["__sentinel"] = nil
  160. local is_it = is_require()
  161.  
  162. if is_it == "require" then
  163. return allium
  164. elseif is_it == "os.loadAPI" then -- Please for the love of god never use os.loadAPI
  165. _G.allium = allium
  166. end
  167.  
  168. do -- Plugin loading process
  169. print("Loading plugins...")
  170. local dir = shell.dir()
  171. if fs.exists(dir.."plugins") then
  172. for _, plugin in pairs(fs.list(dir.."plugins")) do
  173. if not fs.isDir(dir.."plugins/"..plugin) then
  174. local file = loadfile(dir.."plugins/"..plugin)
  175. local suc, err = pcall(file)
  176. if not suc then
  177. printError(err)
  178. end
  179. end
  180. end
  181. end
  182. end
  183.  
  184.  
  185. local main = function()
  186. while true do
  187. local _, message, _, name = os.pullEvent("chat_capture") --Pull chat messages
  188. if string.find(message, "!") == 1 then --are they for allium?
  189. args = {}
  190. for k in string.gmatch(message, "%S+") do --put all arguments spaced out into a table
  191. args[#args+1] = k
  192. end
  193. local cmd = args[1]:sub(2, -1) -- Strip the !
  194. table.remove(args, 1) --remove the first parameter given (!command)
  195. local p_cmds = {} -- List of possible commands if there's more than one that matches the "!command" standard
  196. if not string.find(cmd, ":") then --did they not specify the plugin source?
  197. print(#plugins)
  198. for p_name, plugin in pairs(plugins) do --nope... gonna have to find it for them.
  199. print(p_name)
  200. for c_name, command in pairs(plugin) do
  201. print(c_name)
  202. if c_name == cmd then --well I found it, but there may be more...
  203. p_cmds[#p_cmds+1] = {command, p_name} --split into command function, source
  204. end
  205. end
  206. end
  207. else --hey they did! +1 karma.
  208. local splitat = string.find(cmd, ":")
  209. if plugins[string.sub(cmd, 1, splitat-1)] then --check plugin existence
  210. if plugins[string.sub(cmd, 1, splitat-1)].commands[string.sub(cmd, splitat+1, -1)] then --check command existence
  211. p_cmds[#p_cmds+1] = {plugins[string.sub(cmd, 1, splitat-1)].commands[string.sub(cmd, splitat+1, -1)], string.sub(cmd, 1, splitat-1)} --split it into the function, and then the source
  212. end
  213. end
  214. end
  215. if #p_cmds == 1 and p_cmds[1][1] then --is it really a command, and is there only one that is titled this?
  216. local stat, err = pcall(p_cmds[1][1], name, args) --Let's execute the command in a safe environment that won't kill allium
  217. if stat == false then--it crashed...
  218. allium.tell(name, "&4"..cmd.." crashed! This is likely not your fault, but the developer's. Please contact the developer of &a"..p_cmds[1][2].."&4. Error:\n&c"..err)
  219. print(cmd.." errored. Error:\n"..err)
  220. end
  221. elseif #p_cmds > 1 then --WHAT MORE THAN ONE OUTCOME!?!?
  222. local colstr = ""
  223. for i = 1, #p_cmds do --idiot, I'm going to have to list them out for you...
  224. if i ~= #p_cmds then
  225. colstr = colstr.."&a&g(!"..p_cmds[i][2]..":"..cmd..")&h(Click to run !"..p_cmds[i][2]..":"..cmd..")"..p_cmds[i][2].."&r&e, "
  226. else
  227. colstr = colstr.."and &a&g(!"..p_cmds[i][2]..":"..cmd..")&h(Click to run !"..p_cmds[i][2]..":"..cmd..")"..p_cmds[i][2].."&r&e."
  228. end
  229. end --how dare you inconvenience me...
  230. allium.tell(name, "&eCommand collision beween "..colstr.." Click on the plugin that you want to run the command from. Optionally specify the command you want to use by prefixxing the plugin name followed by a colon, and then the command name. Ex: &c&g(!allium:github)!allium:github&r&e.") --REEEEEEEE
  231. else --this isn't even a valid command...
  232. allium.tell(name, "&6Invalid Command, use &c&g(!allium:help)!help&r&6 for assistance.") --bleh!
  233. end
  234. end
  235. end
  236. end
  237.  
  238. local threads = {} -- Temporary
  239.  
  240. threads[#threads+1] = coroutine.create(main) --Add main to the thread table
  241.  
  242. if not fs.exists("persistence.json") then --In the situation that this is a first installation, let's add persistence.json
  243. local fpers = fs.open("persistence.json", "w")
  244. fpers.write("{}")
  245. fpers.close()
  246. end
  247.  
  248. print("allium started.")
  249. allium.tell("@a", "allium loaded.")
  250. --This clump is pulled and adapted for what I need it for, parallel.waitForAll, for a table of coroutines. Its origin is in /rom/apis/parallel.lua in CraftOS.
  251. local count = #threads
  252. local living = count
  253.  
  254. local tFilters = {}
  255. local eventData = { n = 0 }
  256. while true do
  257. for n=1,count do
  258. local r = threads[n]
  259. if r then
  260. if tFilters[r] == nil or tFilters[r] == eventData[1] or eventData[1] == "terminate" then
  261. local ok, param = coroutine.resume( r, table.unpack( eventData, 1, eventData.n ) )
  262. if not ok then
  263. error( param, 0 )
  264. else
  265. tFilters[r] = param
  266. end
  267. if coroutine.status( r ) == "dead" then
  268. threads[n] = nil
  269. living = living - 1
  270. if living <= 0 then
  271. return n
  272. end
  273. end
  274. end
  275. end
  276. end
  277. for n=1,count do
  278. local r = threads[n]
  279. if r and coroutine.status( r ) == "dead" then
  280. threads[n] = nil
  281. living = living - 1
  282. if living <= 0 then
  283. return n
  284. end
  285. end
  286. end
  287. eventData = table.pack( os.pullEventRaw() )
  288. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement