1
0
mirror of https://github.com/AR2000AR/openComputers_codes.git synced 2025-09-08 06:31:14 +02:00
Files
openComputers_codes/account_maker/bin/accountMaker.lua
2023-02-01 21:16:58 +01:00

303 lines
10 KiB
Lua

local bank = require("bank_api")
local filesystem = require("filesystem")
local io = require("io")
local serialization = require("serialization")
local event = require("event")
local libCB = require("libCB")
local component = require("component")
local term = require("term")
local computer = require("computer")
local transposer = component.transposer
local gpu = component.gpu
local disk_drive = component.disk_drive
local data = component.data
local CONFIG_PATH = "/etc/bank/accountMaker/"
local CONFIG_FILE = CONFIG_PATH .. "config.cfg"
local OUT_PATH = "/var/bank/accountMaker/"
local ACCOUNT_FILE = OUT_PATH .. "accounts.csv"
local ERROR_FILE = OUT_PATH .. "operr.csv"
local config = {}
local knownAccounts = {}
local run = true
--FUNCTION DECALARATION========================================================
local function parseCSVLine(line, sep)
local endReached = false
local res = {}
while (not endReached) do
local i = line:find(sep)
if (not i) then
endReached = true
i = #line + 1
end
table.insert(res, line:sub(1, i - 1))
line = line:sub(i + 1)
end
return (res)
end
local function saveConfig()
--save the config table to a file
if (config.masterAccountCBdata) then
---@type string
config.masterAccountCBdata = data.encode64(serialization.serialize(config.masterAccountCBdata))
end
local cFile = io.open(CONFIG_FILE, "w")
assert(cFile, string.format("Could not open : %s", CONFIG_FILE))
cFile:write(serialization.serialize(config))
cFile:close()
if (config.masterAccountCBdata) then
---@type cardData
config.masterAccountCBdata = serialization.unserialize(data.decode64(config.masterAccountCBdata--[[@as string]] ))
end
end
local function addToKnonwPlayer(playerName, accountUUID)
--save the player/account list to a file
local file = io.open(ACCOUNT_FILE, "a")
assert(file, "Could not append or create " .. ACCOUNT_FILE)
file:write(string.format("%s,%s\n", playerName, accountUUID))
file:close()
table.insert(knownAccounts, {playerName, accountUUID})
end
---Get the player's account uuid if exists
---@param playerName string
---@return string|boolean
local function getAccountUUID(playerName)
for _, v in ipairs(knownAccounts) do
if (v[1] == playerName) then return v[2] end
end
return false
end
local function moveItem(source, sink, item, amount)
local function itemFromString(itemString)
local name, damage = itemString:match("([^:]+:[^:]+):?([0-9]*)")
if (damage == "") then damage = "0" end
damage = tonumber(damage)
return {
name = name,
damage = damage,
label = name:match(":([^:]+)")
}
end
local function itemEquals(itemA, itemB)
if (type(itemA) == "string") then itemA = itemFromString(itemA) end
if (type(itemB) == "string") then itemB = itemFromString(itemB) end
return itemA.name == itemB.name and itemA.damage == itemB.damage
end
assert(type(source) == "number", "Invalid source side")
assert(type(sink) == "number", "Invalid sink side")
assert(item, "No item provided")
amount = amount or 1
assert(type(amount) == "number", "number expected")
local slot = 0
local request = amount
for chestItem in transposer.getAllStacks(source) do
slot = slot + 1
if (chestItem.name and itemEquals(item, chestItem)) then
amount = amount - transposer.transferItem(source, sink, amount, slot)
end
if (amount <= 0) then break end
end
return request - amount
end
---Create a new card for the player
---@param playerName string
local function makeCard(playerName)
term.clear()
local status
local newAccount = false
--#region getaccount
local acUUID = getAccountUUID(playerName)
if (not acUUID) then
print("Making a new account")
newAccount = true
---@diagnostic disable-next-line: cast-local-type
status, acUUID = bank.createAccount()
if (status == 0) then --ok
addToKnonwPlayer(playerName, acUUID)
if (config.masterAccountCreditPerAccount ~= 0) then
status = bank.editAccount(config.masterAccountCBdata--[[@as cardData]] , config.masterAccountCreditPerAccount)
if (status ~= 0) then
local file = io.open(ERROR_FILE, "a")
assert(file, "Can't fail here")
file:write(string.format("%i,%s,%i\n", status, "master account", config.newAccountCredit))
file:close()
end
end
else
print("Server did not respond")
print("Status : " .. status)
event.pull("touch")
return
end
end
--#endregion
--#region writeCard
if (component.isAvailable("drive")) then
if (component.drive.getLabel()) then
disk_drive.eject()
event.pull("component_unavailable", "drive")
moveItem(config.sideChest, config.sideDrive, "opencomputers:storage:1", 1)
end
end
if (not component.isAvailable("drive")) then
moveItem(config.sideChest, config.sideDrive, "opencomputers:storage:1", 1)
end
local pin, rawCBdata
local try = 0
local goodCB = false
repeat
if (not component.isAvailable("drive")) then event.pull("component_available", "drive") end
print("Requesting CB")
---@cast acUUID string
status, pin, rawCBdata = bank.requestNewCBdata(acUUID, component.drive.address)
if (status ~= 0) then
print("ERROR : Could not get rawCBdata\nStatus : " .. status)
else
assert(rawCBdata, "Status 0 but no rawCBdata")
print(string.format("PIN : %q", pin))
print("Writing CB")
libCB.writeCB(rawCBdata, component.drive)
goodCB = libCB.getCB(component.drive, pin)
end
try = try + 1
until (goodCB or try >= 3)
--#endregion
--#region initialCredit
if (try < 3) then
if (newAccount) then
if (config.newAccountCredit ~= 0) then
print("Giving stating credits")
status = bank.editAccount(libCB.getCB(component.drive, pin), config.newAccountCredit)
if (status ~= 0) then
print("No credit given. Contact admin")
local file = io.open(ERROR_FILE, "a")
assert(file, "Can't fail here")
file:write(string.format("%i,%s,%i\n", status, acUUID, config.newAccountCredit))
file:close()
end
end
end
for i = 1, 3 do computer.beep(nil, 0.25) end
print("Take your card")
event.pull("component_unavailable", "drive")
else
moveItem(config.sideDrive, config.sideChest, "opencomputers:storage:1", 1)
print("Can't make a card")
print("Touch to continue")
event.pull("touch")
end
--#endregion
end
--INIT=========================================================================
--make directory if missing
if (not filesystem.isDirectory(CONFIG_PATH)) then filesystem.makeDirectory(CONFIG_PATH) end
if (not filesystem.isDirectory(OUT_PATH)) then filesystem.makeDirectory(OUT_PATH) end
--default config
config = {
masterAccountCBdata = "",
masterAccountCreditPerAccount = 0,
newAccountCredit = 0,
sideChest = 1,
sideDrive = 5
}
--load the config if present
if (filesystem.exists(CONFIG_FILE) and not filesystem.isDirectory(CONFIG_FILE)) then
local cFile = io.open(CONFIG_FILE, "r")
assert(cFile, "Something went wrong when reading the config file")
local tconf = serialization.unserialize(cFile:read("*a")) or {}
cFile:close()
for key, val in pairs(tconf) do
config[key] = val --override default configurations
end
cFile:close()
end
--load masterAccountCBdata if present
if (config.masterAccountCBdata and config.masterAccountCBdata ~= "") then
---@type cardData
config.masterAccountCBdata = serialization.unserialize(data.decode64(config.masterAccountCBdata))
end
--register master cb on first boot
if (config.masterAccountCBdata == "") then
print("Insert master cb to register it")
local reader = libCB.waitForCB(5)
if (reader) then
local encryptedData = libCB.loadCB(reader)
local try = 0
local pin
repeat
try = try + 1
io.write("Enter pin : ")
pin = term.read(nil, nil, "*")
pin = pin:gsub("\n", "")
until (pin or try >= 3)
local cb = libCB.getCB(encryptedData, pin)
if (cb) then
config.masterAccountCBdata = cb
computer.beep()
else
---@diagnostic disable-next-line: assign-type-mismatch
config.masterAccountCBdata = nil
computer.beep()
computer.beep()
end
else
config.masterAccountCBdata = nil
computer.beep()
computer.beep()
end
end
saveConfig()
-- load already created account list
if (filesystem.exists(ACCOUNT_FILE)) then
local aFile = io.open(ACCOUNT_FILE, 'r')
assert(aFile, "No account file found. HOW !?")
for line in aFile:lines() do
line = string.gsub(line, " ", "")
line = parseCSVLine(line, ",")
table.insert(knownAccounts, {line[1], line[2]})
end
end
-- init screen
local old_res_x, old_res_y = gpu.getResolution()
gpu.setResolution(26, 13)
--listen for ctrl+c (interrupted)
event.listen("interrupted", function() run = false; return false end)
--MAIN LOOP====================================================================
while (run) do
term.clear()
print("Touch the screen")
print("to get a card")
local e, _, _, _, _, playerName = event.pull(1, "touch")
if (e) then
makeCard(playerName)
end
end
--restore old screen resolution
gpu.setResolution(old_res_x, old_res_y)