Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Server startup.lua
- local modem = peripheral.find("modem")
- if not modem then error("No modem found. Please attach a wireless modem.") end
- local disk = peripheral.find("drive")
- if not disk then error("No disk drive found. Please attach a disk drive.") end
- modem.open(1) -- Use channel 1 for all communications
- local diskMount = disk.getMountPath()
- if not diskMount then error("No disk inserted. Please insert a disk.") end
- local function setup()
- if not fs.exists(diskMount .. "/students") then fs.makeDir(diskMount .. "/students") end
- if not fs.exists(diskMount .. "/news.txt") then
- local file = fs.open(diskMount .. "/news.txt", "w")
- file.write("Welcome to the college!")
- file.close()
- end
- if not fs.exists(diskMount .. "/student.lua") then
- error("student.lua not found on the disk. Please create this file.")
- end
- -- Launch Dashboard in new tab if multishell is available
- if multishell then
- -- Check if already running? uniqueID?
- -- Simply launching it is fine, user can close duplicate tabs.
- -- We'll just assume server runs once.
- local dashboardPath = diskMount .. "/tracking_dashboard.lua"
- if fs.exists(dashboardPath) then
- multishell.launch({}, dashboardPath)
- print("Launched Tracking Dashboard in background tab.")
- else
- print("Dashboard not found at: " .. dashboardPath)
- end
- else
- print("Multishell not available.")
- end
- print("Server setup complete. Files stored on disk.")
- end
- local function createAccount(studentId, password)
- local studentDir = diskMount .. "/students/" .. studentId
- if fs.exists(studentDir) then
- return false, "Account already exists"
- end
- fs.makeDir(studentDir)
- local passFile = fs.open(studentDir .. "/password.txt", "w")
- passFile.write(password)
- passFile.close()
- local balanceFile = fs.open(studentDir .. "/balance.txt", "w")
- balanceFile.write("0") -- Initial balance of 0
- balanceFile.close()
- return true, "Account created successfully"
- end
- local function verifyLogin(studentId, password)
- local studentDir = diskMount .. "/students/" .. studentId
- if not fs.exists(studentDir) then return false, "Account not found" end
- local passFile = fs.open(studentDir .. "/password.txt", "r")
- local storedPass = passFile.readAll():gsub("%s+$", "") -- Trim trailing whitespace
- passFile.close()
- return storedPass == password, storedPass == password and "Login successful" or "Incorrect password"
- end
- local function handleBalance(studentId, action, amount)
- local balanceFile = fs.open(diskMount .. "/students/" .. studentId .. "/balance.txt", "r")
- local balance = tonumber(balanceFile.readAll()) or 0
- balanceFile.close()
- print("Processing balance update for " .. studentId)
- print("Current balance: " .. balance)
- print("Action: " .. action .. ", Amount: " .. amount)
- if action == "deposit" then
- balance = balance + amount
- elseif action == "withdraw" then
- if balance >= amount then
- balance = balance - amount
- else
- print("Insufficient funds. Transaction failed.")
- return false, "Insufficient funds"
- end
- end
- balanceFile = fs.open(diskMount .. "/students/" .. studentId .. "/balance.txt", "w")
- balanceFile.write(tostring(balance))
- balanceFile.close()
- print("New balance: " .. balance)
- print("Transaction successful")
- return true, balance
- end
- local function getEmails(studentId)
- local emailPath = diskMount .. "/students/" .. studentId .. "/emails.txt"
- if not fs.exists(emailPath) then return {} end
- local file = fs.open(emailPath, "r")
- local data = file.readAll()
- file.close()
- return textutils.unserialize(data) or {}
- end
- local function saveEmails(studentId, emails)
- local emailPath = diskMount .. "/students/" .. studentId .. "/emails.txt"
- local file = fs.open(emailPath, "w")
- file.write(textutils.serialize(emails))
- file.close()
- end
- local function sendEmail(senderId, recipientId, subject, body)
- local recipientDir = diskMount .. "/students/" .. recipientId
- if not fs.exists(recipientDir) then
- return false, "Recipient not found"
- end
- local emails = getEmails(recipientId)
- table.insert(emails, 1, { -- Insert at beginning (newest first)
- id = os.epoch("utc"), -- Simple unique ID logic
- sender = senderId,
- subject = subject,
- body = body,
- timestamp = os.epoch("local"), -- Use local time for display
- read = false
- })
- saveEmails(recipientId, emails)
- return true, "Email sent successfully"
- end
- local function deleteEmail(studentId, emailIndex)
- local emails = getEmails(studentId)
- if emails[emailIndex] then
- table.remove(emails, emailIndex)
- saveEmails(studentId, emails)
- return true, "Email deleted"
- else
- return false, "Email not found"
- end
- end
- local function handleRequests()
- print("Server is running. Waiting for requests...")
- while true do
- local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
- if type(message) == "table" then
- if message.type == "request_update" then
- local file = fs.open(diskMount .. "/student.lua", "r")
- local content = file.readAll()
- file.close()
- modem.transmit(replyChannel, 1, {type = "update", content = content})
- print("Sent student.lua update to a device")
- elseif message.type == "create_account" then
- if message.studentId and message.password then
- local success, msg = createAccount(message.studentId, message.password)
- modem.transmit(replyChannel, 1, {type = "account_response", success = success, message = msg})
- else
- modem.transmit(replyChannel, 1, {type = "error", message = "Invalid account creation request"})
- end
- elseif message.type == "login" then
- if message.studentId and message.password then
- local success, msg = verifyLogin(message.studentId, message.password)
- modem.transmit(replyChannel, 1, {type = "login_response", success = success, message = msg})
- else
- modem.transmit(replyChannel, 1, {type = "error", message = "Invalid login request"})
- end
- elseif message.type == "get_news" then
- local newsFile = fs.open(diskMount .. "/news.txt", "r")
- local news = newsFile.readAll()
- newsFile.close()
- modem.transmit(replyChannel, 1, {type = "news", content = news})
- elseif message.type == "get_balance" then
- if message.studentId and message.password then
- local success, msg = verifyLogin(message.studentId, message.password)
- if success then
- local balanceFile = fs.open(diskMount .. "/students/" .. message.studentId .. "/balance.txt", "r")
- local balance = balanceFile.readAll()
- balanceFile.close()
- modem.transmit(replyChannel, 1, {type = "balance_response", balance = balance})
- else
- modem.transmit(replyChannel, 1, {type = "error", message = msg})
- end
- else
- modem.transmit(replyChannel, 1, {type = "error", message = "Invalid balance request"})
- end
- elseif message.type == "update_balance" then
- if message.studentId and message.password and message.action and message.amount then
- local success, msg = verifyLogin(message.studentId, message.password)
- if success then
- local success, result = handleBalance(message.studentId, message.action, message.amount)
- modem.transmit(replyChannel, 1, {type = "balance_update_response", success = success, result = result})
- else
- modem.transmit(replyChannel, 1, {type = "error", message = msg})
- end
- else
- modem.transmit(replyChannel, 1, {type = "error", message = "Invalid balance update request"})
- end
- elseif message.type == "verify_student" then
- if message.recipientId then
- local recipientDir = diskMount .. "/students/" .. message.recipientId
- local exists = fs.exists(recipientDir)
- modem.transmit(replyChannel, 1, {exists = exists})
- else
- modem.transmit(replyChannel, 1, {type = "error", message = "Invalid student verification request"})
- end
- elseif message.type == "transfer_money" then
- if message.studentId and message.password and message.recipientId and message.amount then
- local success, msg = verifyLogin(message.studentId, message.password)
- if success then
- local senderBalanceFile = fs.open(diskMount .. "/students/" .. message.studentId .. "/balance.txt", "r")
- local senderBalance = tonumber(senderBalanceFile.readAll()) or 0
- senderBalanceFile.close()
- local recipientBalanceFile = fs.open(diskMount .. "/students/" .. message.recipientId .. "/balance.txt", "r")
- local recipientBalance = tonumber(recipientBalanceFile.readAll()) or 0
- recipientBalanceFile.close()
- local expectedSenderBalance = senderBalance - message.amount
- local expectedRecipientBalance = recipientBalance + message.amount
- if expectedSenderBalance >= 0 then
- local withdrawSuccess, _ = handleBalance(message.studentId, "withdraw", message.amount)
- if withdrawSuccess then
- local depositSuccess, _ = handleBalance(message.recipientId, "deposit", message.amount)
- if depositSuccess then
- -- Verify balances
- senderBalanceFile = fs.open(diskMount .. "/students/" .. message.studentId .. "/balance.txt", "r")
- local newSenderBalance = tonumber(senderBalanceFile.readAll()) or 0
- senderBalanceFile.close()
- recipientBalanceFile = fs.open(diskMount .. "/students/" .. message.recipientId .. "/balance.txt", "r")
- local newRecipientBalance = tonumber(recipientBalanceFile.readAll()) or 0
- recipientBalanceFile.close()
- if newSenderBalance == expectedSenderBalance and newRecipientBalance == expectedRecipientBalance then
- modem.transmit(replyChannel, 1, {success = true, newBalance = newSenderBalance})
- else
- -- Revert transaction
- handleBalance(message.studentId, "deposit", message.amount)
- handleBalance(message.recipientId, "withdraw", message.amount)
- modem.transmit(replyChannel, 1, {success = false, message = "Transaction verification failed"})
- end
- else
- handleBalance(message.studentId, "deposit", message.amount)
- modem.transmit(replyChannel, 1, {success = false, message = "Failed to deposit to recipient"})
- end
- else
- modem.transmit(replyChannel, 1, {success = false, message = "Failed to withdraw from sender"})
- end
- else
- modem.transmit(replyChannel, 1, {success = false, message = "Insufficient funds"})
- end
- else
- modem.transmit(replyChannel, 1, {success = false, message = msg})
- end
- else
- modem.transmit(replyChannel, 1, {success = false, message = "Invalid transfer request"})
- end
- elseif message.type == "send_email" then
- if message.studentId and message.password and message.recipientId and message.subject and message.body then
- local success, msg = verifyLogin(message.studentId, message.password)
- if success then
- local sent, result = sendEmail(message.studentId, message.recipientId, message.subject, message.body)
- modem.transmit(replyChannel, 1, {type = "email_response", success = sent, message = result})
- else
- modem.transmit(replyChannel, 1, {type = "error", message = msg})
- end
- else
- modem.transmit(replyChannel, 1, {type = "error", message = "Invalid send email request"})
- end
- elseif message.type == "get_inbox" then
- if message.studentId and message.password then
- local success, msg = verifyLogin(message.studentId, message.password)
- if success then
- local emails = getEmails(message.studentId)
- modem.transmit(replyChannel, 1, {type = "inbox_response", emails = emails})
- else
- modem.transmit(replyChannel, 1, {type = "error", message = msg})
- end
- else
- modem.transmit(replyChannel, 1, {type = "error", message = "Invalid inbox request"})
- end
- elseif message.type == "delete_email" then
- if message.studentId and message.password and message.emailIndex then
- local success, msg = verifyLogin(message.studentId, message.password)
- if success then
- local deleted, result = deleteEmail(message.studentId, message.emailIndex)
- modem.transmit(replyChannel, 1, {type = "email_response", success = deleted, message = result})
- else
- modem.transmit(replyChannel, 1, {type = "error", message = msg})
- end
- else
- modem.transmit(replyChannel, 1, {type = "error", message = "Invalid delete email request"})
- end
- elseif message.type == "track_location" then
- if message.studentId and message.x and message.y and message.z then
- -- No login required for tracking? Or should we verify password?
- -- Ideally verify, but passive tracking might lack access to password constant?
- -- Let's Require studentId. We'll verify existence of folder.
- local studentDir = diskMount .. "/students/" .. message.studentId
- if fs.exists(studentDir) then
- local historyPath = studentDir .. "/location_history.txt"
- local file = fs.open(historyPath, "a")
- -- Format: Timestamp | x,y,z
- file.writeLine(os.epoch("local") .. "|" .. message.x .. "," .. message.y .. "," .. message.z)
- file.close()
- -- Also update 'current' for fast lookup? Dashboard can just read last line.
- end
- end
- end
- end
- end
- end
- setup()
- handleRequests()
Advertisement
Add Comment
Please, Sign In to add comment