Advertisement
melzneni

Turti installer

Aug 14th, 2023 (edited)
1,032
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.81 KB | None | 0 0
  1. local argsSource = { ... }
  2.  
  3. function splitText(source, letters)
  4.     local parts = {}
  5.     local akt = "";
  6.     local qM1 = 0;
  7.     local qM2 = 0;
  8.     local b1 = 0;
  9.     local b2 = 0;
  10.     local b3 = 0;
  11.     for i = 1, #source do
  12.         local z = string.sub(source, i, i)
  13.         if z == "'" and qM2 == 0 then
  14.             qM1 = 1 - qM1;
  15.         elseif z == "\"" and qM1 == 0 then
  16.             qM2 = 1 - qM2;
  17.         elseif qM1 == 0 and qM2 == 0 then
  18.             if z == "(" then
  19.                 b1 = b1 + 1
  20.             elseif z == ")" then
  21.                 b1 = b1 - 1
  22.             elseif z == "[" then
  23.                 b2 = b2 + 1
  24.             elseif z == "]" then
  25.                 b2 = b2 - 1
  26.             elseif z == "{" then
  27.                 b3 = b3 + 1
  28.             elseif z == "}" then
  29.                 b3 = b3 - 1
  30.             end
  31.         end
  32.         local split = false
  33.         if b1 == 0 and b2 == 0 and b3 == 0 and qM1 == 0 and qM2 == 0 then
  34.             for j = 1, #letters do
  35.                 if z == string.sub(letters, j, j) then
  36.                     split = true
  37.                     break
  38.                 end
  39.             end
  40.         end
  41.         if split then
  42.             if akt ~= "" then
  43.                 table.insert(parts, akt)
  44.                 akt = ""
  45.             end
  46.         else
  47.             akt = akt .. z
  48.         end
  49.     end
  50.     if akt ~= "" then
  51.         table.insert(parts, akt)
  52.     end
  53.     return parts
  54. end
  55.  
  56. local args = {}
  57.  
  58. local TYPE_DECLARATION = 0
  59. local TYPE_TABLE = 1
  60. local TYPE_TABLE_MAP = 1
  61. local TYPE_TABLE_ARR = 2
  62. local TYPE_VALUE = 2
  63. local TYPE_CONSTANT = 3
  64. local TYPE_PASTEBIN = 4
  65.  
  66. if peripheral == nil then
  67.     _G.os.reboot = function()
  68.         print("fct: os.reboot()")
  69.     end
  70.     _G.os.setComputerLabel = function(label)
  71.         print("fct: os.setComputerLabel(\"" .. label .. "\")")
  72.     end
  73. end
  74.  
  75. function getTypeName(t)
  76.     if t == TYPE_DECLARATION then
  77.         return "declaration"
  78.     elseif t == TYPE_TABLE then
  79.         return "table"
  80.     elseif t == TYPE_VALUE then
  81.         return "value"
  82.     elseif t == TYPE_CONSTANT then
  83.         return "constant"
  84.     elseif t == TYPE_PASTEBIN then
  85.         return "pastebin"
  86.     else
  87.         error("unknown type: " .. t)
  88.     end
  89. end
  90.  
  91. function loadArgData(arg)
  92.     local v = loadVar(arg)
  93.     if v.type ~= TYPE_DECLARATION then
  94.         error("every argument of this program needs to be of type 'declaration'")
  95.     end
  96.     return v
  97. end
  98.  
  99. function readFileText(file)
  100.     local f = fs.open(file, "r")
  101.     local text = f.readAll()
  102.     f.close()
  103.     return text
  104. end
  105.  
  106. function tryMatches(var, format, name)
  107.     if not string.match(var, format) == var then
  108.         error("invalid " .. name .. ": '" .. var .. "'")
  109.     end
  110. end
  111.  
  112. function loadVar(source)
  113.  
  114.     local pts = splitText(source, "=")
  115.     if #pts > 1 then
  116.         if #pts > 2 then
  117.             error("only one '=' in declaration")
  118.         end
  119.         tryMatches(pts[1], "[A-Za-z_][A-Za-z0-9_]*", "dec-name")
  120.         return { type = TYPE_DECLARATION, name = pts[1], value = loadVar(pts[2]) }
  121.     end
  122.  
  123.     if string.sub(source, 1, 1) == "{" and string.sub(source, #source) == "}" then
  124.         local pts = splitText(string.sub(source, 2, #source - 1), ",")
  125.         local values = {}
  126.         for i, pt in pairs(pts) do
  127.             local v = loadVar(pt)
  128.             if v.type == TYPE_DECLARATION then
  129.                 values[v.name] = v.value
  130.             else
  131.                 table.insert(values, v)
  132.             end
  133.         end
  134.         return { type = TYPE_TABLE, values = values }
  135.     elseif string.sub(source, 1, 1) == "<" and string.sub(source, #source) == ">" then
  136.         source = string.sub(source, 2, #source - 1)
  137.         local ind = string.find(source, ":")
  138.         local action = string.sub(source, 1, ind - 1)
  139.         tryMatches(action, "[A-Za-z_][A-Za-z0-9_]*", "action-name")
  140.         if action == "pb" then
  141.             local id = string.sub(source, ind + 1)
  142.             tryMatches(id, "[A-Za-z_][A-Za-z0-9_]*", "pastebinId-name")
  143.             return { type = TYPE_PASTEBIN, id = id }
  144.         elseif action == "input" then
  145.             local v = loadVar(string.sub(source, ind + 1))
  146.             if v.type ~= TYPE_VALUE or type(v.value) ~= "string" then
  147.                 error("string value expected for function <input:''>")
  148.             end
  149.             io.write("input<" .. v.value .. ">: ")
  150.             local data = io.read()
  151.             return { type = TYPE_VALUE, value = data }
  152.         elseif action == "inputNum" then
  153.             local v = loadVar(string.sub(source, ind + 1))
  154.             if v.type ~= TYPE_VALUE or type(v.value) ~= "string" then
  155.                 error("string value expected for function <input:''>")
  156.             end
  157.             io.write("inputNum<" .. v.value .. ">: ")
  158.             local data = tonumber(io.read())
  159.             return { type = TYPE_VALUE, value = data }
  160.         else
  161.             error("unknown action: '" .. action .. "'")
  162.         end
  163.     elseif string.sub(source, 1, 1) == "'" and string.sub(source, #source) == "'" then
  164.         return { type = TYPE_VALUE, value = string.sub(source, 2, #source - 1) }
  165.     elseif string.sub(source, 1, 1) == "$" and string.sub(source, #source) == "$" then
  166.         local name = string.sub(source, 2, #source - 1)
  167.         return { type = TYPE_CONSTANT, name = name }
  168.     elseif source == "true" or source == "false" then
  169.         return { type = TYPE_VALUE, value = source == "true" }
  170.     elseif tonumber(source) ~= nil then
  171.         return { type = TYPE_VALUE, value = tonumber(source) }
  172.     else
  173.         error("invalid source: '" .. source .. "'")
  174.     end
  175. end
  176.  
  177. function checkType(name, value, t, t2)
  178.     if value.type ~= t then
  179.         error("value '" .. name .. "' needs to be of type '" .. getTypeName(t) .. "' (type '" .. getTypeName(value.type) .. "' given)")
  180.     end
  181.     if t2 ~= nil then
  182.         if value.type == TYPE_TABLE then
  183.             if t2 == TYPE_TABLE_MAP then
  184.                 for i, _ in pairs(value.values) do
  185.                     if type(i) == "number" then
  186.                         error("table '" .. name .. "' needs to be a map")
  187.                     end
  188.                 end
  189.             elseif t2 == TYPE_TABLE_ARR then
  190.                 for i, _ in pairs(value.values) do
  191.                     if type(i) == "string" then
  192.                         error("table '" .. name .. "' needs to be an array")
  193.                     end
  194.                 end
  195.             else
  196.                 error("unknown type2: '" .. t2 .. "'")
  197.             end
  198.         elseif value.type == TYPE_VALUE then
  199.             if type(value.value) ~= t2 then
  200.                 error("value '" .. name .. "' needs to be of type '" .. t2 .. "' (type '" .. type(value.value .. "' given)"))
  201.             end
  202.         end
  203.     end
  204. end
  205.  
  206. function writeToFile(fileName, data)
  207.     local f = fs.open(fileName, "w")
  208.     f.write(data)
  209.     f.close()
  210. end
  211.  
  212. local startupBuildData = {
  213.     files = {},
  214.     cmds = {}
  215. }
  216.  
  217. local reboot = false
  218.  
  219. local functions = {
  220.     startup = {
  221.         delay = function(data)
  222.             checkType("startup>delay", data, TYPE_VALUE, "number")
  223.             startupBuildData.delay = data.value
  224.         end,
  225.         files = function(data)
  226.             checkType("startup>files", data, TYPE_TABLE, TYPE_TABLE_MAP)
  227.             for fileName, v in pairs(data.values) do
  228.                 checkType("startup>files>value", v, TYPE_PASTEBIN)
  229.                 table.insert(startupBuildData.files, { name = fileName, id = v.id })
  230.             end
  231.         end,
  232.         cmds = function(data)
  233.             checkType("startup>cmds", data, TYPE_TABLE, TYPE_TABLE_ARR)
  234.             for i, cmd in pairs(data.values) do
  235.                 checkType("startup>cmds>cmd", cmd, TYPE_TABLE, TYPE_TABLE_ARR)
  236.                 table.insert(startupBuildData.cmds, cmd.values)
  237.             end
  238.         end
  239.     },
  240.     reboot = function(data)
  241.         checkType("reboot", data, TYPE_VALUE, "boolean")
  242.         reboot = data.value
  243.     end,
  244.     label = function(data)
  245.         checkType("label", data, TYPE_VALUE, "string")
  246.         os.setComputerLabel(data.value)
  247.     end
  248. }
  249.  
  250. for i, v in pairs(argsSource) do
  251.     table.insert(args, loadArgData(v))
  252. end
  253.  
  254. function printTable(tbl)
  255.     printTableIndex(tbl, "", {})
  256. end
  257.  
  258. function printTableIndex(tbl, before, alreadyUsed)
  259.     for i, v in pairs(tbl) do
  260.         if type(v) == "table" then
  261.             if tableContainsValue(alreadyUsed, v) then
  262.                 print(before .. i .. ":", "alreadyUsed");
  263.             else
  264.                 print(before .. i .. ": [");
  265.                 table.insert(alreadyUsed, v)
  266.                 printTableIndex(v, before .. "\t", alreadyUsed)
  267.                 print(before .. "]")
  268.             end
  269.         else
  270.             print(before .. i .. ":", v);
  271.         end
  272.     end
  273. end
  274.  
  275. function tableContainsValue(table, value)
  276.     for i, v in pairs(table) do
  277.         if v == value then
  278.             return true
  279.         end
  280.     end
  281.     return false
  282. end
  283.  
  284. function executeFunction(tName, name, data, functions)
  285.     for n, fct in pairs(functions) do
  286.         if name == n then
  287.             if type(fct) == "table" then
  288.                 tName = tName .. "[" .. name .. "]"
  289.                 checkType(tName .. ".value", data, TYPE_TABLE, TYPE_TABLE_MAP)
  290.                 for n1, v in pairs(data.values) do
  291.                     executeFunction(tName, n1, v, fct)
  292.                 end
  293.             else
  294.                 fct(data)
  295.             end
  296.             return
  297.         end
  298.     end
  299.     error("function-name '" .. name .. "' isn't allowed for '" .. tName .. "'")
  300. end
  301.  
  302. function writeToFile(fileName, data)
  303.     if fs == nil then
  304.         local f = io.open(fileName, "w")
  305.         io.output(f)
  306.         io.write(data)
  307.         io.close(f)
  308.     else
  309.         local f = fs.open(fileName, "w")
  310.         f.write(data)
  311.         f.close()
  312.     end
  313. end
  314.  
  315. for i, v in pairs(args) do
  316.     local tName = "level0-argument"
  317.     executeFunction(tName, v.name, v.value, functions)
  318. end
  319.  
  320. function replaceConstants(v, constants)
  321.     if v.type == TYPE_CONSTANT then
  322.         if constants[v.name] ~= nil then
  323.             return { type = TYPE_VALUE, value = constants[v.name] }
  324.         end
  325.     elseif v.type == TYPE_TABLE then
  326.         for i, v1 in pairs(v.values) do
  327.             v.values[i] = replaceConstants(v1, constants)
  328.         end
  329.     elseif v.type ~= TYPE_VALUE then
  330.         error("unsupported type: '" .. getTypeName(v.type) .. "'")
  331.     end
  332.     return v
  333. end
  334.  
  335. local txt = "local args={...}\n"
  336.  
  337. if startupBuildData.delay ~= nil then
  338.     txt = txt .. "sleep(" .. startupBuildData.delay .. ")\n"
  339. end
  340.  
  341. for i, f in pairs(startupBuildData.files) do
  342.     txt = txt .. "if fs.exists(\"" .. f.name .. "\") then\n"
  343.     txt = txt .. "    shell.run(\"delete\", \"" .. f.name .. "\")\n"
  344.     txt = txt .. "end\n"
  345.     txt = txt .. "first=true\n"
  346.     txt = txt .. "while not fs.exists(\"" .. f.name .. "\") do\n"
  347.     txt = txt .. "    if first then\n first=false\n"
  348.     txt = txt .. "    else\n"
  349.     txt = txt .. "        print(\""..f.id..": retrying in 1s\")\nsleep(1)\n"
  350.     txt = txt .. "    end\n"
  351.     txt = txt .. "    shell.run(\"pastebin\",\"get\", \"" .. f.id .. "\", \"" .. f.name .. "\")\n"
  352.     txt = txt .. "end\n"
  353. end
  354.  
  355. for i, cmd in pairs(startupBuildData.cmds) do
  356.     cmd = replaceConstants({ type = TYPE_TABLE, values = cmd }, { arg1 = "raw:args[1]", arg2 = "raw:args[2]" }).values
  357.     for i, v in pairs(cmd) do
  358.         checkType("cmds>cmd", v, TYPE_VALUE, "string")
  359.     end
  360.     txt = txt .. "shell.run("
  361.     for i, v in pairs(cmd) do
  362.         if i ~= 1 then
  363.             txt = txt .. ","
  364.         end
  365.         if string.sub(v.value, 1, 4) == "raw:" then
  366.             txt = txt .. string.sub(v.value, 5)
  367.         else
  368.             txt = txt .. "\"" .. v.value .. "\""
  369.         end
  370.     end
  371.     txt = txt .. ")\n"
  372. end
  373.  
  374. writeToFile("startup", txt)
  375.  
  376. if reboot then
  377.     os.reboot()
  378. end
  379.  
  380.  
  381.  
  382.  
  383.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement