diff --git a/.gitignore b/.gitignore index 7721e4b..a53cac2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ u2c.py push.sh version +.env diff --git a/src/lib/plc/aead_chacha_poly.lua b/old_encryption/aead_chacha_poly.lua similarity index 100% rename from src/lib/plc/aead_chacha_poly.lua rename to old_encryption/aead_chacha_poly.lua diff --git a/src/lib/hmac-pbkdf2-aead.lua b/old_encryption/hmac-pbkdf2-aead.lua similarity index 75% rename from src/lib/hmac-pbkdf2-aead.lua rename to old_encryption/hmac-pbkdf2-aead.lua index 3304f1d..1eb293b 100644 --- a/src/lib/hmac-pbkdf2-aead.lua +++ b/old_encryption/hmac-pbkdf2-aead.lua @@ -1,15 +1,16 @@ local g = string.gsub sha256 = loadstring(g( -g( -g( -g( -g( -g( -g( -g( -'Sa=XbandSb=XbxWSc=XlshiftSd=unpackSe=2^32SYf(g,h)Si=g/2^hSj=i%1Ui-j+j*eVSYk(l,m)Sn=l/2^mUn-n%1VSo={0x6a09e667Tbb67ae85T3c6ef372Ta54ff53aT510e527fT9b05688cT1f83d9abT5be0cd19}Sp={0x428a2f98T71374491Tb5c0fbcfTe9b5dba5T3956c25bT59f111f1T923f82a4Tab1c5ed5Td807aa98T12835b01T243185beT550c7dc3T72be5d74T80deb1feT9bdc06a7Tc19bf174Te49b69c1Tefbe4786T0fc19dc6T240ca1ccT2de92c6fT4a7484aaT5cb0a9dcT76f988daT983e5152Ta831c66dTb00327c8Tbf597fc7Tc6e00bf3Td5a79147T06ca6351T14292967T27b70a85T2e1b2138T4d2c6dfcT53380d13T650a7354T766a0abbT81c2c92eT92722c85Ta2bfe8a1Ta81a664bTc24b8b70Tc76c51a3Td192e819Td6990624Tf40e3585T106aa070T19a4c116T1e376c08T2748774cT34b0bcb5T391c0cb3T4ed8aa4aT5b9cca4fT682e6ff3T748f82eeT78a5636fT84c87814T8cc70208T90befffaTa4506cebTbef9a3f7Tc67178f2}SYq(r,q)if e-1-r[1] +---@field remotes table|nil +---@field connection InnerRemote|nil ---@class Chatbox ---@field players table ---@field prefix string|nil ---@class Config ----@field inventories string[] +---@field inventories string[]|nil ---@field import string[]|nil ---@field chatbox Chatbox|nil ----@field remote Remote +---@field remote Remote|nil -local inv = require("modules.inv") +local config = require("../config") ---@type Config + +local inv; + +if config.inventories == nil and config.remote.connection then + inv = require("modules.inv_ra") +else + inv = require("modules.inv") +end local ui = require("modules.ui") local chatbox = require("modules.chatbox") local ra = require("modules.ra") -local config = require("../config") ---@type Config local function importMechanism() if config.import == nil then @@ -55,4 +65,6 @@ local function importMechanism() end inv.sync() -parallel.waitForAll(inv.getAIL().run, chatbox.run, ra.run, ui.run, importMechanism, inv.detectPlayerInsert) +parallel.waitForAll(inv.run(), chatbox.run, ra.run, + ui.run, + importMechanism, inv.detectPlayerInsert) diff --git a/src/modules/chatbox.lua b/src/modules/chatbox.lua index 8a99c14..2f458ee 100644 --- a/src/modules/chatbox.lua +++ b/src/modules/chatbox.lua @@ -1,6 +1,11 @@ local config = require("../../config") ---@type Config -local inv = require("modules.inv") +local inv; +if config.inventories == nil and config.remote.connection then + inv = require("modules.inv_ra") +else + inv = require("modules.inv") +end local function levDist(s, t) local n = #s local m = #t @@ -176,7 +181,7 @@ function run() ---@type ccTweaked.peripheral.Inventory local peripInventory = perip.getInventory() - local best = findBest(inv.getAIL().listNames(), args[2]) + local best = findBest(inv.listNames(), args[2]) local itemName = "" diff --git a/src/modules/inv.lua b/src/modules/inv.lua index e9a9481..99ffe41 100644 --- a/src/modules/inv.lua +++ b/src/modules/inv.lua @@ -13,85 +13,76 @@ local peripherals = peripheral.getNames(); local ail = nil local function sync() - print("Syncing..") - ---@type string[] - local foundInventories = {} + print("Syncing..") + ---@type string[] + local foundInventories = {} - for _, invPattern in ipairs(config.inventories) do - for _, inv in ipairs(peripherals) do - if string.find(inv, invPattern) then - table.insert(foundInventories, inv) - end - end + for _, invPattern in ipairs(config.inventories) do + for _, inv in ipairs(peripherals) do + if string.find(inv, invPattern) then + table.insert(foundInventories, inv) + end end + end - ail = abstractInventoryLib(foundInventories, true, { - --[[cache = true, - optimal = true, - unoptimal = true, - api = true, - defrag = true, - redirect = function (e) - print(e) - end,]] - }) + ail = abstractInventoryLib(foundInventories, true, {}) - print("Synced."); + print("Synced."); end ---@param itemName string ---@param perip ccTweaked.peripheral.Inventory|string|nil ---@param maxAmount number|nil local function sendItemToSelf(itemName, perip, maxAmount) - if perip == nil then - perip = turtleId - end - turtleMoveAllowed = false + if perip == nil then + perip = turtleId + end + turtleMoveAllowed = false - local remaining = maxAmount or 64 - local total = 0 + local remaining = maxAmount or 64 + local total = 0 - if remaining <= 0 then - turtleMoveAllowed = true - return - end - - if #ail.listNBT(itemName) ~= 0 then - local nbtList = ail.listNBT(itemName) - local chosenNBT = nil - if nbtList and #nbtList > 0 then - chosenNBT = nbtList[math.random(1, #nbtList)] - end - - if chosenNBT == "NONE" then - chosenNBT = nil - end - - while remaining > 0 do - local toSend = math.min(64, remaining) - - local ok, moved = pcall(function() - ail.performTransfer() - - local amount = ail.pushItems(perip, itemName, toSend, nil, chosenNBT, { - ["allowBadTransfers"] = true, - ["optimal"] = false - }) - - ail.performTransfer() - - return amount - end) - total = total + moved - if ok and moved and moved > 0 then - remaining = remaining - moved - else - break - end - end - end + if remaining <= 0 then turtleMoveAllowed = true + return + end - return total + if #ail.listNBT(itemName) ~= 0 then + local nbtList = ail.listNBT(itemName) + local chosenNBT = nil + if nbtList and #nbtList > 0 then + chosenNBT = nbtList[math.random(1, #nbtList)] + end + + if chosenNBT == "NONE" then + chosenNBT = nil + end + + while remaining > 0 do + local toSend = math.min(64, remaining) + + local ok, moved = pcall(function() + ail.performTransfer() + + local amount = ail.pushItems(perip, itemName, toSend, nil, chosenNBT, { + ["allowBadTransfers"] = true, + ["optimal"] = false + }) + + ail.performTransfer() + + return amount + end) + total = total + moved + if ok and moved and moved > 0 then + remaining = remaining - moved + else + break + end + end + end + turtleMoveAllowed = true + + return total end ---@param slots ccTweaked.turtle.turtleSlot[] @@ -99,111 +90,127 @@ end ---@param id string|nil ---@param maxAmount number|nil local function sendItemAwayMultiple(slots, perip, id, maxAmount) - if perip == nil then - perip = turtle + if perip == nil then + perip = turtle + end + local srcId = id or turtleId + + if srcId == nil then return end + + local itemsInSlots = {} + for _, slot in ipairs(slots) do + local item = perip.getItemDetail(slot) + if item then + itemsInSlots[slot] = item end - local srcId = id or turtleId + end - if srcId == nil then return end + local totalMoved = 0 + local remaining = maxAmount or math.huge - local itemsInSlots = {} - for _, slot in ipairs(slots) do - local item = perip.getItemDetail(slot) - if item then - itemsInSlots[slot] = item - end + if remaining <= 0 then + return 0 + end + + for _, slot in ipairs(slots) do + if remaining <= 0 then break end + + local toSend = math.min(64, remaining) + + local ok, pulled = pcall(function() + ail.performTransfer() + + local moved = ail.pullItems(srcId, slot, toSend, nil, nil, { + ["allowBadTransfers"] = true, + ["optimal"] = false + }) + + ail.performTransfer() + return moved + end) + + if ok and pulled and pulled > 0 then + totalMoved = totalMoved + pulled + remaining = remaining - pulled end + end - local totalMoved = 0 - local remaining = maxAmount or math.huge + local numItems = 0 + for _, _ in pairs(itemsInSlots) do + numItems = numItems + 1 + end - if remaining <= 0 then - return 0 - end + if numItems > 0 then + os.queueEvent("update_ui") + end - for _, slot in ipairs(slots) do - if remaining <= 0 then break end - - local toSend = math.min(64, remaining) - - local ok, pulled = pcall(function() - ail.performTransfer() - - local moved = ail.pullItems(srcId, slot, toSend, nil, nil, { - ["allowBadTransfers"] = true, - ["optimal"] = false - }) - - ail.performTransfer() - return moved - end) - - if ok and pulled and pulled > 0 then - totalMoved = totalMoved + pulled - remaining = remaining - pulled - end - end - - local numItems = 0 - for _, _ in pairs(itemsInSlots) do - numItems = numItems + 1 - end - - if numItems > 0 then - os.queueEvent("update_ui") - end - - return totalMoved + return totalMoved end local function getTurtleInventory() - local inventory = {} - for slot = 1, 16 do - local item = turtle.getItemDetail(slot, false) - inventory[slot] = item - end - return inventory + local inventory = {} + for slot = 1, 16 do + local item = turtle.getItemDetail(slot, false) + inventory[slot] = item + end + return inventory end local function detectPlayerInsert() + if turtle then previousInventory = getTurtleInventory() while true do - os.pullEvent("turtle_inventory") + os.pullEvent("turtle_inventory") - local currentInventory = getTurtleInventory() + local currentInventory = getTurtleInventory() - if turtleMoveAllowed then - local newlyAddedSlots = {} + if turtleMoveAllowed then + local newlyAddedSlots = {} - for slot = 1, 16 do - local prev = previousInventory[slot] - local curr = currentInventory[slot] + for slot = 1, 16 do + local prev = previousInventory[slot] + local curr = currentInventory[slot] - if not prev and curr then - table.insert(newlyAddedSlots, slot) - end - end - - if #newlyAddedSlots > 0 then - sendItemAwayMultiple(newlyAddedSlots) - end + if not prev and curr then + table.insert(newlyAddedSlots, slot) + end end - previousInventory = currentInventory + if #newlyAddedSlots > 0 then + sendItemAwayMultiple(newlyAddedSlots) + end + end + + previousInventory = currentInventory end + end end -local function getAIL() - return ail +local function run() + return ail.run end +local function listNames() + return ail.listNames() +end + +local function listItemAmounts() + return ail.listItemAmounts() +end + +local function getItem(z) + return ail.getItem(z) +end return { - detectPlayerInsert = detectPlayerInsert, - sendItemAwayMultiple = sendItemAwayMultiple, - sendItemToSelf = sendItemToSelf, - getTurtleInventory = getTurtleInventory, - sync = sync, - getAIL = getAIL, + detectPlayerInsert = detectPlayerInsert, + sendItemAwayMultiple = sendItemAwayMultiple, + sendItemToSelf = sendItemToSelf, + getTurtleInventory = getTurtleInventory, + listItemAmounts = listItemAmounts, + listNames = listNames, + getItem = getItem, + sync = sync, + run = run } diff --git a/src/modules/inv_ra.lua b/src/modules/inv_ra.lua new file mode 100644 index 0000000..fb960c2 --- /dev/null +++ b/src/modules/inv_ra.lua @@ -0,0 +1,171 @@ +local previousInventory = {} +---@type ccTweaked.peripheral.WiredModem +local modem = peripheral.find("modem"); +local turtleId = modem.getNameLocal() +local turtleMoveAllowed = true +local config = require("../../config") ---@type Config + +local ra = require("tiny_ra_library") + +local function sync() + print("inv_ra does not require syncing (it is already synced!)") +end + +---@param itemName string +---@param perip ccTweaked.peripheral.Inventory|string|nil +---@param maxAmount number|nil +local function sendItemToSelf(itemName, perip, maxAmount) + local enderstorage = peripheral.wrap(config.remote.ender_storage); + if enderstorage == nil then return end + turtleMoveAllowed = false + + local id = turtleId; + + ra.withdraw(itemName, maxAmount, true) -- make sure to wait so we can push to turtle once waited + + if type(perip) == "string" then + id = perip + end + + for key, _ in pairs(enderstorage.list()) do + enderstorage.pushItems(id, key) + end + + sleep(0.2) + turtleMoveAllowed = true +end + +---@param slots ccTweaked.turtle.turtleSlot[] +---@param perip ccTweaked.peripheral.Inventory|nil +---@param id string|nil +---@param maxAmount number|nil +local function sendItemAwayMultiple(slots, perip, id, maxAmount) + if perip == nil then + perip = turtle + end + local srcId = id or turtleId + + if srcId == nil then return end + + local itemsInSlots = {} + for _, slot in ipairs(slots) do + local item = perip.getItemDetail(slot) + if item then + itemsInSlots[slot] = item + end + end + + local enderstorage = peripheral.wrap(config.remote.ender_storage); + if enderstorage == nil then return end + local totalMoved = 0 + local remaining = maxAmount or math.huge + + if remaining <= 0 then + return 0 + end + + for _, slot in ipairs(slots) do + if remaining <= 0 then break end + + local toSend = math.min(64, remaining) + + local ok, pulled = pcall(function() + return enderstorage.pullItems(srcId, slot, toSend) + end) + + if ok and pulled and pulled > 0 then + totalMoved = totalMoved + pulled + remaining = remaining - pulled + end + end + + local numItems = 0 + for _, _ in pairs(itemsInSlots) do + numItems = numItems + 1 + end + + if numItems > 0 then + os.queueEvent("update_ui") + end + + local keys = {} + + for key, _ in pairs(enderstorage.list()) do + if key ~= nil then + table.insert(keys, key) + end + end + + ra.depositBySlots(keys, nil, false) + return totalMoved +end + +local function getTurtleInventory() + local inventory = {} + for slot = 1, 16 do + local item = turtle.getItemDetail(slot, false) + inventory[slot] = item + end + return inventory +end + +local function detectPlayerInsert() + if turtle then + previousInventory = getTurtleInventory() + + while true do + os.pullEvent("turtle_inventory") + + local currentInventory = getTurtleInventory() + + if turtleMoveAllowed then + local newlyAddedSlots = {} + + for slot = 1, 16 do + local prev = previousInventory[slot] + local curr = currentInventory[slot] + + if not prev and curr then + table.insert(newlyAddedSlots, slot) + end + end + + if #newlyAddedSlots > 0 then + sendItemAwayMultiple(newlyAddedSlots) + end + end + + previousInventory = currentInventory + end + end +end + +local function run() + return function() + ra.init(peripheral.wrap(config.remote.modem), config.remote.connection.port, config.remote.connection.password) + end +end + +local function listNames() + return ra.listNames() +end + +local function listItemAmounts() + return ra.listItemAmounts() +end + +local function getItem(z) + return ra.getItem(z) +end + +return { + detectPlayerInsert = detectPlayerInsert, + sendItemAwayMultiple = sendItemAwayMultiple, + sendItemToSelf = sendItemToSelf, + getTurtleInventory = getTurtleInventory, + listItemAmounts = listItemAmounts, + listNames = listNames, + getItem = getItem, + sync = sync, + run = run +} diff --git a/src/modules/ra.lua b/src/modules/ra.lua index e1ff104..a54fd4f 100644 --- a/src/modules/ra.lua +++ b/src/modules/ra.lua @@ -1,6 +1,12 @@ -local inv = require("modules.inv"); local config = require("../../config") ---@type Config -local hmac = require("lib.hmac-pbkdf2-aead") +if config.inventories == nil and config.remote.connection then + inv = require("modules.inv_ra") +else + inv = require("modules.inv") +end + + +local encryption = require("lib.encryption") ---@class RemoteAccess ---@field type string ---@field data RemoteAccessData @@ -10,13 +16,34 @@ local hmac = require("lib.hmac-pbkdf2-aead") ---@field amount number|nil ---@field slots number[]|nil + + +local function sendResponse(modem, port, hashedPassword, id, ok, data, err) + modem.transmit( + port, + port, + encryption.encrypt(hashedPassword, + textutils.serialiseJSON({ + type = "response", + id = id, + ok = ok, + data = data, + error = err + }) + ) + ) +end + + local function run() - if config.remote == nil then return end + if config.remote == nil or config.remote.remotes == nil then return end local modem = peripheral.wrap(config.remote.modem) if not modem then return end - for _, remote in pairs(config.remote.remotes) do + local remotes = config.remote.remotes or { config.remote.connection } + + for _, remote in pairs(remotes) do if not modem.isOpen(remote.port) then modem.open(remote.port) end @@ -28,10 +55,11 @@ local function run() while true do local _, _, channel, _, message, _ = os.pullEvent("modem_message") - for color, remote in pairs(config.remote.remotes) do + for color, remote in pairs(remotes) do if remote.port == channel then + local hashed = encryption.hashKey(remote.password) local err, data = pcall(function() - return hmac.decrypt_with_password(remote.password, message) + return encryption.decrypt(hashed, message) end) if not data then return end @@ -51,23 +79,82 @@ local function run() colors[parts[3]] ) if json.type == "withdraw" then - inv.sendItemToSelf(json.data.itemName, config.remote.ender_storage, json.data.amount) - elseif json.type == "deposit" then - if json.data.itemName then - local move = {} - for s, i in pairs(ender_storage.list()) do - if i.name == json.data.itemName then - table.insert(move, s) - end - end - inv.sendItemAwayMultiple(move, ender_storage, config.remote.ender_storage, json.data.amount) - elseif json.data.slots then - if type(json.data.slots) ~= 'table' then - return - end + local ok, err = pcall(function() + inv.sendItemToSelf( + json.data.itemName, + config.remote.ender_storage, + json.data.amount + ) + end) - inv.sendItemAwayMultiple(json.data.slots, ender_storage, config.remote.ender_storage, json.data.amount) - end + sendResponse(modem, remote.port, hashed, json.id, ok, nil, err) + elseif json.type == "deposit" then + local ok, err = pcall(function() + if json.data.itemName then + local move = {} + for s, i in pairs(ender_storage.list()) do + if i.name == json.data.itemName then + table.insert(move, s) + end + end + inv.sendItemAwayMultiple( + move, + ender_storage, + config.remote.ender_storage, + json.data.amount + ) + elseif json.data.slots then + inv.sendItemAwayMultiple( + json.data.slots, + ender_storage, + config.remote.ender_storage, + json.data.amount + ) + end + end) + + sendResponse(modem, remote.port, hashed, json.id, ok, nil, err) + elseif json.type == "list_names" then + local ok, result = pcall(function() + return inv.listNames() + end) + sendResponse( + modem, + remote.port, + hashed, + json.id, + ok, + ok and result or nil, + not ok and result or nil + ) + elseif json.type == "list_item_amounts" then + local ok, result = pcall(function() + return inv.listItemAmounts() + end) + + sendResponse( + modem, + remote.port, + hashed, + json.id, + ok, + ok and result or nil, + not ok and result or nil + ) + elseif json.type == "get_item" then + local ok, result = pcall(function() + return inv.getItem(json.data.index) + end) + + sendResponse( + modem, + remote.port, + hashed, + json.id, + ok, + ok and result or nil, + not ok and result or nil + ) end end end diff --git a/src/modules/ui.lua b/src/modules/ui.lua index 9031d76..453019e 100644 --- a/src/modules/ui.lua +++ b/src/modules/ui.lua @@ -1,4 +1,11 @@ -local inv = require("modules.inv"); +local config = require("../../config") ---@type Config +local inv; +if config.inventories == nil and config.remote.connection then + inv = require("modules.inv_ra") +else + inv = require("modules.inv") +end + local PrimeUI = require("lib.primeui").PrimeUI; local function is_beta(ver) if ver:match("^[0-9a-f]+$") and #ver >= 8 then @@ -12,9 +19,18 @@ local function run() local win = term.current(); local w, h = term.getSize() + local items = inv.listItemAmounts() + local x = 0 + local function getFiltered() local filtered = {} - for name, count in pairs(inv.getAIL().listItemAmounts()) do + + x = x + 1 + if x % 3 == 0 then + items = inv.listItemAmounts() + end + + for name, count in pairs(items) do if search == "" or string.find(name:lower(), search:lower(), 1, true) then table.insert(filtered, { name = name, count = count }) end @@ -25,7 +41,7 @@ local function run() for i, filter in ipairs(filtered) do refiltered[i] = filter.name .. - string.rep(" ", w - (2 + #filter.name + #tostring(filter.count))) .. tostring(filter.count) + string.rep(" ", w - (2 + #filter.name + #tostring(filter.count))) .. tostring(filter.count) end return refiltered end @@ -40,8 +56,7 @@ local function run() end, function(option) local z = option:match("^(%S+)") - - if inv.getAIL().getItem(z) then + if inv.getItem(z) then inv.sendItemToSelf(z) end end diff --git a/src/tiny_ra_library.lua b/src/tiny_ra_library.lua new file mode 100644 index 0000000..82e28be --- /dev/null +++ b/src/tiny_ra_library.lua @@ -0,0 +1,198 @@ +local encryption = require("lib.encryption") + +---@type string +local password +---@type number +local port + +---@type string +local hashedPassword +---@type ccTweaked.peripheral.Modem +local modem +local function sendRequest(reqType, data, wait) + if wait == nil then + wait = true + end + local id = tostring(math.random(1, 1e9)) + + modem.transmit( + port, + port, + encryption.encrypt(hashedPassword, + textutils.serialiseJSON({ + type = reqType, + id = id, + data = data + }) + ) + ) + + if wait then + -- wait for response + while true do + local event, side, senderChannel, replyChannel, message = os.pullEvent("modem_message") + local ok, decrypted = pcall(encryption.decrypt, hashedPassword, message) + if not ok then goto continue end + + local resp = textutils.unserialiseJSON(decrypted) + if resp and resp.type == "response" and resp.id == id then + return resp.ok, resp.data or resp.error + end + + ::continue:: + end + end +end + +local function init(modemI, portI, passwordI) + port = portI + password = passwordI + hashedPassword = encryption.hashKey(passwordI) + modem = modemI + + modem.open(port) +end + + +---@param wait boolean|nil +local function listNames(wait) + if not port or not modem or not password then + error("tiny_ra_library: init was never ran") + end + if wait == nil then + wait = true + end + + local ok, data = sendRequest("list_names", nil, wait) + if wait then + if not ok then + error("Failed to list names: " .. tostring(data)) + end + return data + end +end + +---@param itemName string +---@param count number|nil +---@param wait boolean|nil +local function withdraw(itemName, count, wait) + if not port or not modem or not password then + error("tiny_ra_library: init was never ran") + end + + if wait == nil then + wait = true + end + + local ok, data = sendRequest("withdraw", { + itemName = itemName, + count = count + }, wait) + if wait then + if not ok then + error("Failed to withdraw: " .. tostring(data)) + end + return data + end +end + + +---@param slots number[] +---@param count number|nil +---@param wait boolean|nil +local function depositBySlots(slots, count, wait) + if not port or not modem or not password then + error("tiny_ra_library: init was never ran") + end + + if wait == nil then + wait = true + end + + local data = { + slots = slots + } + + if count then + data["count"] = count + end + + local ok, response = sendRequest("deposit", data, wait) + + if wait then + if not ok then + error("Failed to deposit by slots: " .. tostring(response)) + end + return response + end +end + +---@param wait boolean|nil +local function listItemAmounts(wait) + if wait == nil then + wait = true + end + local ok, response = sendRequest("list_item_amounts", nil, wait) + + if wait then + if not ok then + error("Failed to list names: " .. tostring(response)) + end + return response + end +end + + +---@param itemName string +---@param wait boolean|nil +local function getItem(itemName, wait) + if wait == nil then + wait = true + end + local ok, data = sendRequest("get_item", { index = itemName }, wait) + if wait then + if not ok then + error("Failed to list names: " .. tostring(data)) + end + return data + end +end + + +---@param itemName string +---@param count number|nil +---@param wait boolean|nil +local function depositByItemName(itemName, count, wait) + if not port or not modem or not password then + error("tiny_ra_library: init was never ran") + end + + local data = { + itemName = itemName + } + + if count then + data["count"] = count + end + + local ok, response = sendRequest("deposit", data, wait) + + if wait then + if not ok then + error("Failed to list names: " .. tostring(response)) + end + return response + end +end + +return { + init = init, + + listItemAmounts = listItemAmounts, + getItem = getItem, + listNames = listNames, + + withdraw = withdraw, + depositByItemName = depositByItemName, + depositBySlots = depositBySlots +} diff --git a/tiny_ra_library.lua b/tiny_ra_library.lua deleted file mode 100644 index 99121fd..0000000 --- a/tiny_ra_library.lua +++ /dev/null @@ -1,97 +0,0 @@ -local function crypto() - local function a()local b,c=table.insert,table.concat;local function d(e,f,g,h,i)local j,k,l,m=e[f],e[g],e[h],e[i]local n;j=(j+k)%0x100000000;n=bit32.bxor(m,j)m=bit32.band(bit32.bor(bit32.lshift(n,16),bit32.rshift(n,16)),0xffffffff)l=(l+m)%0x100000000;n=bit32.bxor(k,l)k=bit32.band(bit32.bor(bit32.lshift(n,12),bit32.rshift(n,20)),0xffffffff)j=(j+k)%0x100000000;n=bit32.bxor(m,j)m=bit32.band(bit32.bor(bit32.lshift(n,8),bit32.rshift(n,24)),0xffffffff)l=(l+m)%0x100000000;n=bit32.bxor(k,l)k=bit32.band(bit32.bor(bit32.lshift(n,7),bit32.rshift(n,25)),0xffffffff)e[f],e[g],e[h],e[i]=j,k,l,m;return e end;local o={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}local p={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}local q=function(r,s,t)local e=o;local u=p;e[1],e[2],e[3],e[4]=0x61707865,0x3320646e,0x79622d32,0x6b206574;for v=1,8 do e[v+4]=r[v]end;e[13]=s;for v=1,3 do e[v+13]=t[v]end;for v=1,16 do u[v]=e[v]end;for w=1,10 do d(u,1,5,9,13)d(u,2,6,10,14)d(u,3,7,11,15)d(u,4,8,12,16)d(u,1,6,11,16)d(u,2,7,12,13)d(u,3,8,9,14)d(u,4,5,10,15)end;for v=1,16 do e[v]=bit32.band(e[v]+u[v],0xffffffff)end;return e end;local x="=64)local D=table.pack(string.unpack(x,z,A))local E=q(r,s,t)for v=1,16 do D[v]=bit32.bxor(D[v],E[v])end;local F=string.pack(x,table.unpack(D))if B<64 then F=string.sub(F,1,B)end;return F end;local G=function(r,s,t,z)assert(s+math.floor(#z/64)+1<0xffffffff,"block counter must fit an uint32")assert(#r==32,"#key must be 32")assert(#t==12,"#nonce must be 12")local H=table.pack(string.unpack("=16 do a6=a6+bit32.band(Q('=16 then T(e,U)end;if e.bytes==0 then else local ah=string.sub(U,e.midx)..'\x01'..string.rep('\0',16-e.bytes-1)assert(#ah==16)e.final=true;T(e,ah)end;return e end;local function ai(e)local l,aj;local ak;local a6=e.h[1]local a7=e.h[2]local a8=e.h[3]local a9=e.h[4]local aa=e.h[5]l=bit32.rshift(a7,26)a7=bit32.band(a7,0x3ffffff)a8=a8+l;l=bit32.rshift(a8,26)a8=bit32.band(a8,0x3ffffff)a9=a9+l;l=bit32.rshift(a9,26)a9=bit32.band(a9,0x3ffffff)aa=aa+l;l=bit32.rshift(aa,26)aa=bit32.band(aa,0x3ffffff)a6=a6+l*5;l=bit32.rshift(a6,26)a6=bit32.band(a6,0x3ffffff)a7=a7+l;local al=a6+5;l=bit32.rshift(al,26)al=bit32.band(al,0x3ffffff)local am=a7+l;l=bit32.rshift(am,26)am=bit32.band(am,0x3ffffff)local an=a8+l;l=bit32.rshift(an,26)an=bit32.band(an,0x3ffffff)local ao=a9+l;l=bit32.rshift(ao,26)ao=bit32.band(ao,0x3ffffff)local ap=bit32.band(aa+l-0x4000000,0xffffffff)aj=bit32.band(bit32.rshift(ap,31)-1,0xffffffff)al=bit32.band(al,aj)am=bit32.band(am,aj)an=bit32.band(an,aj)ao=bit32.band(ao,aj)ap=bit32.band(ap,aj)aj=bit32.band(bit32.bnot(aj),0xffffffff)a6=bit32.bor(bit32.band(a6,aj),al)a7=bit32.bor(bit32.band(a7,aj),am)a8=bit32.bor(bit32.band(a8,aj),an)a9=bit32.bor(bit32.band(a9,aj),ao)aa=bit32.bor(bit32.band(aa,aj),ap)a6=bit32.band(bit32.bor(a6,bit32.lshift(a7,26)),0xffffffff)a7=bit32.band(bit32.bor(bit32.rshift(a7,6),bit32.lshift(a8,20)),0xffffffff)a8=bit32.band(bit32.bor(bit32.rshift(a8,12),bit32.lshift(a9,14)),0xffffffff)a9=bit32.band(bit32.bor(bit32.rshift(a9,18),bit32.lshift(aa,8)),0xffffffff)ak=a6+e.pad[1]a6=bit32.band(ak,0xffffffff)ak=a7+e.pad[2]+bit32.rshift(ak,32)a7=bit32.band(ak,0xffffffff)ak=a8+e.pad[3]+bit32.rshift(ak,32)a8=bit32.band(ak,0xffffffff)ak=a9+e.pad[4]+bit32.rshift(ak,32)a9=bit32.band(ak,0xffffffff)local aq=string.pack('b0 then r=sha256(r):gsub('..',function(b1)return string.char(tonumber(b1,16))end)end;if#r0 then bl.K=aZ(bl.K,bl.V.."\1"..bn)bl.V=aZ(bl.K,bl.V)end end;local function bo(bp)bl.K=string.rep("\0",32)bl.V=string.rep("\1",32)bm(bp)bl.inited=true end;local function bq(aT)if not bl.inited then error("DRBG not seeded. Call seed_entropy() once.")end;local aU={}while#table.concat(aU)0 then bu[#bu+1]=bt end;local bp=sha256(table.concat(bu)):gsub('..',function(b1)return string.char(tonumber(b1,16))end)bo(bp)local ak=fs.open(bk,"wb")ak.write(bq(48))ak.close()end end;local bx="\1"local by="\1"local bz="SiSS RA rev1|chacha20poly1305"local function bA(aT)return string.char(bit32.band(bit32.rshift(aT,24),255),bit32.band(bit32.rshift(aT,16),255),bit32.band(bit32.rshift(aT,8),255),bit32.band(aT,255))end;local function bB(aT)return string.char(bit32.band(bit32.rshift(aT,8),255),bit32.band(aT,255))end;local function bC(bD)return bA(bD)..bB(32)end;local function bE(aA)local bF,bG,bH,bI,ac,ad=aA:byte(1,6)local bJ=bit32.bor(bit32.lshift(bF,24),bit32.lshift(bG,16),bit32.lshift(bH,8),bI)local bK=bit32.bor(bit32.lshift(ac,8),ad)return bJ,bK end;local function bL(aT)return bq(aT)end;local function bM(O)assert(#O==12,"nonce must be 12 bytes")local aD=O:sub(1,6)local aE=O:sub(7,12)return aD,aE end;local function bN(b7,bO)local b8=bL(16)local bJ=1000;local r=b6(b7,b8,bJ,32)local O=bL(12)local aD,aE=bM(O)local bP,aK=aN.encrypt(bz,r,aD,aE,bO)local bQ=bC(bJ)local bR=table.concat{bx,by,bQ,b8,O,bP,aK}return aR(bR)end;local function bS(b7,bR)local aS=aW(bR)if#aS<1+1+6+16+12+16 then return nil,"ciphertext too short"end;local bT=1;local bU=aS:sub(bT,bT)bT=bT+1;if bU~=bx then return nil,"version mismatch"end;local bV=aS:sub(bT,bT)bT=bT+1;if bV~=by then return nil,"kdf mismatch"end;local bQ=aS:sub(bT,bT+5)bT=bT+6;local bJ,bK=bE(bQ)if bK~=32 then return nil,"bad dkLen"end;local b8=aS:sub(bT,bT+15)bT=bT+16;local O=aS:sub(bT,bT+11)bT=bT+12;local aD,aE=bM(O)local bW=16;local aK=aS:sub(#aS-bW+1)local bP=aS:sub(bT,#aS-bW)local r=b6(b7,b8,bJ,32)local z,bX=aN.decrypt(bz,r,aD,aE,bP,aK)if not z then return nil,bX or"auth failed"end;return z end;return{decrypt_with_password=bS,encrypt_with_password=bN,seed_entropy=bs} -end -local hmac = crypto() - - ----@type string -local password ----@type number -local port - ----@type ccTweaked.peripheral.Modem -local modem - -local function init(modemI, portI, passwordI) - port = portI - password = passwordI - modem = modemI - - hmac.seed_entropy() - modem.open(port) - -end - ----@param itemName string ----@param count number|nil -local function withdraw(itemName, count) - if not port or not modem or not password then - error("tiny_ra_library: init was never ran") - end - - local data = { - itemName = itemName - } - - if count then - data["count"] = count - end - - modem.transmit(port, port, hmac.encrypt_with_password(password, - textutils.serialiseJSON({ - ["type"] = "withdraw", - ["data"] = data - }))) -end - ----@param slots number[] ----@param count number|nil -local function depositBySlots(slots, count) - if not port or not modem or not password then - error("tiny_ra_library: init was never ran") - end - - local data = { - slots = slots - } - - if count then - data["count"] = count - end - - modem.transmit(port, port, hmac.encrypt_with_password(password, - textutils.serialiseJSON({ - ["type"] = "deposit", - ["data"] = data - }))) -end - ----@param itemName string ----@param count number|nil -local function depositByItemName(itemName, count) - if not port or not modem or not password then - error("tiny_ra_library: init was never ran") - end - - local data = { - itemName = itemName - } - - if count then - data["count"] = count - end - - modem.transmit(port, port, hmac.encrypt_with_password(password, - textutils.serialiseJSON({ - ["type"] = "deposit", - ["data"] = data - }))) -end - -return { - init = init, - - withdraw = withdraw, - depositByItemName = depositByItemName, - depositBySlots = depositBySlots -}