mail/storage.lua
2023-03-29 14:49:09 +02:00

379 lines
9.5 KiB
Lua

function mail.get_storage_entry(playername)
local str = mail.storage:get_string(playername)
if str == "" then
-- new entry
return {
contacts = {},
inbox = {},
outbox = {},
lists = {}
}
else
-- deserialize existing entry
return minetest.parse_json(str)
end
end
--[[
Mail format (inbox, outbox):
{
-- sending player name
sender = "",
-- receiving player name
to = "",
-- carbon copy (optional)
cc = "",
-- blind carbon copy (optional)
bcc = "",
-- mail subject
subject = "",
-- mail body
body = "",
-- timestamp (os.time())
time = 1234,
-- read-flag (true: player has read the mail, inbox only)
read = true
}
Contact format:
{
-- name of the player
name = "",
-- note
note = ""
}
Mail-list format:
{
-- name of the maillist
name = "",
-- description
description = "",
-- player list (delimited by newline)
players = ""
}
--]]
function mail.set_storage_entry(playername, entry)
mail.storage:get_string(playername, minetest.write_json(entry))
end
-- get a mail by id from the players in- or outbox
function mail.get_message(playername, msg_id)
local entry = mail.get_storage_entry(playername)
for _, msg in ipairs(entry.inbox) do
if msg.id == msg_id then
return msg
end
end
for _, msg in ipairs(entry.outbox) do
if msg.id == msg_id then
return msg
end
end
end
-- marks a mail read by its id
function mail.mark_read(playername, msg_id)
local entry = mail.get_storage_entry(playername)
for _, msg in ipairs(entry.inbox) do
if msg.id == msg_id then
msg.read = true
mail.set_storage_entry(playername, entry)
return
end
end
end
-- marks a mail unread by its id
function mail.mark_unread(playername, msg_id)
local entry = mail.get_storage_entry(playername)
for _, msg in ipairs(entry.inbox) do
if msg.id == msg_id then
msg.read = false
mail.set_storage_entry(playername, entry)
return
end
end
end
-- deletes a mail by its id
function mail.delete_mail(playername, msg_id)
local entry = mail.get_storage_entry(playername)
for i, msg in ipairs(entry.inbox) do
if msg.id == msg_id then
table.remove(entry.outbox, i)
mail.set_storage_entry(playername, entry)
return
end
end
for i, msg in ipairs(entry.outbox) do
if msg.id == msg_id then
table.remove(entry.outbox, i)
mail.set_storage_entry(playername, entry)
return
end
end
end
-- add or update a contact
function mail.update_contact(playername, contact)
local entry = mail.get_storage_entry(playername)
local existing_updated = false
for _, existing_contact in ipairs(entry.contacts) do
if existing_contact.name == contact.name then
-- update
existing_contact.note = contact.note
existing_updated = true
end
end
if not existing_updated then
-- insert
table.insert(entry.contacts, contact)
end
mail.set_storage_entry(playername, entry)
end
-- deletes a contact
function mail.delete_contact(playername, contactname)
local entry = mail.get_storage_entry(playername)
for i, existing_contact in ipairs(entry.contacts) do
if existing_contact.name == contactname then
-- delete
table.remove(entry.contacts, i)
mail.set_storage_entry(playername, entry)
return
end
end
end
-- get all contacts
function mail.get_contacts(playername)
local entry = mail.get_storage_entry(playername)
return entry.contact
end
function mail.getMaillists()
local maillists = mail.read_json_file(mail.maildir .. "/mail.maillists.json")
return maillists
end
function mail.getPlayerMaillists(playername)
local maillists = mail.getMaillists()
local playerMaillists = {}
for _, maillist in ipairs(maillists) do
if maillist.owner == playername then
table.insert(playerMaillists, {id = maillist.id, name = maillist.name, desc = maillist.desc})
end
end
return playerMaillists
end
function mail.addMaillist(maillist, players_string)
local maillists = mail.getMaillists()
if maillists[1] then
local previousMl = maillists[1]
maillist.id = previousMl.id + 1
else
maillist.id = 1
end
table.insert(maillists, maillist)
if mail.write_json_file(mail.maildir .. "/mail.maillists.json", maillists) then
-- add status for players contained in the maillist
local players = mail.parse_player_list(players_string)
for _, player in ipairs(players) do
if minetest.player_exists(player) then -- avoid blank names
mail.addPlayerToMaillist(player, maillist.id)
end
end
return true
else
minetest.log("error","[mail] Save failed - maillist may be lost!")
return false
end
end
function mail.setMaillist(ml_id, updated_maillist, players_string)
local maillists = mail.getMaillists()
local maillist_id = 0
for _, maillist in ipairs(maillists) do
if maillist.id == ml_id then
maillist_id = maillist.id
maillists[_] = {
id = maillist_id,
owner = updated_maillist.owner,
name = updated_maillist.name,
desc = updated_maillist.desc}
end
end
if mail.write_json_file(mail.maildir .. "/mail.maillists.json", maillists) then
-- remove all players
mail.removePlayersFromMaillist(maillist_id)
-- to add those registered in the updated maillist
local players = mail.parse_player_list(players_string)
for _, player in ipairs(players) do
if minetest.player_exists(player) then -- avoid blank names
mail.addPlayerToMaillist(player, maillist_id)
end
end
return true
else
minetest.log("error","[mail] Save failed - maillist may be lost!")
return false
end
end
function mail.getMaillistIdFromName(ml_name, owner)
local maillists = mail.getMaillists()
local ml_id = 0
for _, maillist in ipairs(maillists) do
if maillist.name == ml_name and maillist.owner == owner then
ml_id = maillist.id
break
end
end
return ml_id
end
function mail.getPlayersInMaillists()
local players_mls = mail.read_json_file(mail.maildir .. "/mail.maillists_players.json")
return players_mls
end
function mail.getPlayersDataInMaillist(ml_id)
local players_mls = mail.getPlayersInMaillists() -- players from all maillists
local players_ml = {} -- players from this maillist
if players_mls[1] then
for _, playerInfo in ipairs(players_mls) do
if playerInfo.id == ml_id then
table.insert(players_ml, playerInfo)
end
end
end
return players_ml
end
function mail.getPlayersInMaillist(ml_id)
local players_ml = mail.getPlayersDataInMaillist(ml_id) -- players from this maillist
local players_names_ml = {}
if players_ml[1] then
for _, playerInfo in ipairs(players_ml) do
if playerInfo and playerInfo.player and minetest.player_exists(playerInfo.player) then
table.insert(players_names_ml, playerInfo.player)
end
end
end
return players_names_ml
end
function mail.addPlayerToMaillist(player, ml_id)
local playersMls = mail.getPlayersInMaillists()
local new_player = {id = ml_id, player = player}
table.insert(playersMls, new_player)
if mail.write_json_file(mail.maildir .. "/mail.maillists_players.json", playersMls) then
return true
else
minetest.log("error","[mail] Save failed - maillist may be lost!")
return false
end
end
function mail.removePlayersFromMaillist(ml_id)
local maillists_players = mail.getPlayersInMaillists()
for i=#maillists_players,1,-1 do
local playerInfo = maillists_players[i]
if playerInfo.id == ml_id then
table.remove(maillists_players, i)
end
end
if mail.write_json_file(mail.maildir .. "/mail.maillists_players.json", maillists_players) then
return true
else
minetest.log("error","[mail] Save failed!")
return false
end
end
function mail.deleteMaillist(ml_id)
local maillists = mail.getMaillists()
-- remove players attached to the maillist
local players_writing_done = mail.removePlayersFromMaillist(ml_id)
-- then remove the maillist itself
for _, maillist in ipairs(maillists) do
if maillist.id == ml_id then
table.remove(maillists, _)
end
end
local maillist_writing_done = mail.write_json_file(mail.maildir .. "/mail.maillists.json", maillists)
if players_writing_done and maillist_writing_done then
return true
else
minetest.log("error","[mail] Save failed!")
return false
end
end
function mail.extractMaillists(receivers_string, maillists_owner)
local globalReceivers = mail.parse_player_list(receivers_string) -- receivers including maillists
local receivers = {} -- extracted receivers
-- extract players from mailing lists
for _, receiver in ipairs(globalReceivers) do
local receiverInfo = receiver:split("@") -- @maillist
if receiverInfo[1] and receiver == "@" .. receiverInfo[1]
and mail.getMaillistIdFromName(receiverInfo[1], maillists_owner) ~= 0 then -- in case of maillist
local players_ml = mail.getPlayersInMaillist(mail.getMaillistIdFromName(receiverInfo[1], maillists_owner))
if players_ml then
for _, player in ipairs(players_ml) do
table.insert(receivers, player)
end
end
else -- in case of player
table.insert(receivers, receiver)
end
end
return receivers
end
function mail.pairsByKeys(t, f)
-- http://www.lua.org/pil/19.3.html
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function() -- iterator function
i = i + 1
if a[i] == nil then
return nil
else
--return a[i], t[a[i]]
-- add the current position and the length for convenience
return a[i], t[a[i]], i, #a
end
end
return iter
end
function mail.read_json_file(path)
local file = io.open(path, "r")
local content = {}
if file then
local json = file:read("*a")
content = minetest.parse_json(json or "[]") or {}
file:close()
end
return content
end
function mail.write_json_file(path, content)
local file = io.open(path,"w")
local json = minetest.write_json(content)
if file and file:write(json) and file:close() then
return true
else
return false
end
end