mirror of
https://github.com/mt-mods/mail.git
synced 2025-07-13 01:41:57 -04:00
status refactoring
This commit is contained in:
parent
706b870b7d
commit
b414ace620
9 changed files with 91 additions and 176 deletions
13
api.lua
13
api.lua
|
@ -97,8 +97,17 @@ function mail.send(...)
|
|||
time = os.time(),
|
||||
}
|
||||
|
||||
-- insert in global storage
|
||||
mail.addMessage(msg)
|
||||
-- add in senders outbox
|
||||
local entry = mail.get_storage_entry(m.from)
|
||||
table.insert(entry.outbox, msg)
|
||||
mail.set_storage_entry(m.from, entry)
|
||||
|
||||
-- add in every receivers inbox
|
||||
for recipient in pairs(recipients) do
|
||||
entry = mail.get_storage_entry(recipient)
|
||||
table.insert(entry.inbox, msg)
|
||||
mail.set_storage_entry(recipient, entry)
|
||||
end
|
||||
|
||||
-- notify recipients that happen to be online
|
||||
local mail_alert = f(mail.receive_mail_message, m.from, m.subject)
|
||||
|
|
8
init.lua
8
init.lua
|
@ -1,9 +1,6 @@
|
|||
mail = {
|
||||
-- api version
|
||||
apiversion = 1.1,
|
||||
|
||||
-- database version
|
||||
dbversion = 3.0,
|
||||
-- version
|
||||
version = 3,
|
||||
|
||||
-- mail directory
|
||||
maildir = minetest.get_worldpath().."/mails",
|
||||
|
@ -39,6 +36,7 @@ end
|
|||
|
||||
local MP = minetest.get_modpath(minetest.get_current_modname())
|
||||
dofile(MP .. "/util/normalize.lua")
|
||||
dofile(MP .. "/util/uuid.lua")
|
||||
dofile(MP .. "/chatcommands.lua")
|
||||
dofile(MP .. "/migrate.lua")
|
||||
dofile(MP .. "/hud.lua")
|
||||
|
|
23
migrate.lua
23
migrate.lua
|
@ -13,12 +13,12 @@ end
|
|||
function mail.migrate_v2_to_v3()
|
||||
minetest.mkdir(mail.maildir) -- if necessary (eg. first login)
|
||||
print("[mail] Migration from v2 to v3 database")
|
||||
local already_processed = {} -- store messages that are already process to avoid duplicates
|
||||
|
||||
minetest.after(0,function()
|
||||
for playername, _ in minetest.get_auth_handler().iterate() do
|
||||
local player_contacts = mail.read_json_file(mail.maildir .. "/contacts/" .. playername .. ".json")
|
||||
local entry = mail.get_storage_entry(playername)
|
||||
|
||||
local player_contacts = mail.read_json_file(mail.maildir .. "/contacts/" .. playername .. ".json")
|
||||
for _, c in pairs(player_contacts) do
|
||||
table.insert(entry.contacts, { name = c.name, note = c.note })
|
||||
end
|
||||
|
@ -26,27 +26,16 @@ function mail.migrate_v2_to_v3()
|
|||
local saneplayername = string.gsub(playername, "[.|/]", "")
|
||||
local player_inbox = mail.read_json_file(mail.maildir .. "/" .. saneplayername .. ".json")
|
||||
for _, msg in ipairs(player_inbox) do
|
||||
-- id like "123456789.0singleplayer" -- it presumes that a same sender cannot send two mails within a second
|
||||
local msg_id = tostring(msg.time) .. msg.sender
|
||||
local new_msg = true -- check if that mail was already processed with another player
|
||||
for _, cur_id in ipairs(already_processed) do
|
||||
if cur_id == msg_id then
|
||||
new_msg = false
|
||||
break
|
||||
end
|
||||
end
|
||||
-- add if valid and "to" field populated (missing in ancient storage formats)
|
||||
if new_msg and msg.to then
|
||||
local msg_table = {
|
||||
if msg.to then
|
||||
table.insert(entry.inbox, {
|
||||
id = mail.new_uuid(),
|
||||
sender = msg.sender,
|
||||
to = msg.to,
|
||||
cc = msg.cc,
|
||||
subject = msg.subject,
|
||||
body = msg.body,
|
||||
time = msg.time,
|
||||
}
|
||||
mail.addMessage(msg_table)
|
||||
table.insert(already_processed, msg_id)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
minetest.register_on_joinplayer(function(player)
|
||||
minetest.after(2, function(name)
|
||||
local messages = mail.getMessages(name)
|
||||
local entry = mail.get_storage_entry(name)
|
||||
local messages = entry.inbox
|
||||
|
||||
local unreadcount = 0
|
||||
|
||||
|
|
168
storage.lua
168
storage.lua
|
@ -59,156 +59,64 @@ function mail.set_storage_entry(playername, entry)
|
|||
mail.storage:get_string(playername, minetest.write_json(entry))
|
||||
end
|
||||
|
||||
function mail.getMessage(msg_id)
|
||||
local messages = mail.getMessages()
|
||||
if messages then
|
||||
for _, msg in ipairs(messages) do
|
||||
-- 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
|
||||
end
|
||||
|
||||
-- api in use by the `fancyvend` mod
|
||||
function mail.getMessages(playername)
|
||||
local messages = mail.getMessages()
|
||||
local playerMessages = {}
|
||||
if messages then
|
||||
for _, msg in ipairs(messages) do
|
||||
local cc = ""
|
||||
local bcc = ""
|
||||
if msg.cc then
|
||||
cc = msg.cc
|
||||
end
|
||||
if msg.bcc then
|
||||
bcc = msg.bcc
|
||||
end
|
||||
local receivers = (msg.to .. "," .. cc .. "," .. bcc):split(",")
|
||||
for _, receiver in ipairs(receivers) do
|
||||
receiver = string.gsub(receiver, " ", "") -- avoid blank spaces (ex : " singleplayer" instead of "singleplayer")
|
||||
if receiver == playername then -- check if player is a receiver
|
||||
if mail.getMessageStatus(receiver, msg.id) ~= "deleted" then -- do not return if the message was deleted by player
|
||||
table.insert(playerMessages, msg)
|
||||
break
|
||||
end
|
||||
elseif msg.sender == playername then
|
||||
if mail.getMessageStatus(receiver, msg.id) ~= "deleted" then -- do not return if the message was deleted by player
|
||||
table.insert(playerMessages, msg)
|
||||
break
|
||||
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
|
||||
|
||||
return playerMessages
|
||||
end
|
||||
|
||||
function mail.getPlayerSentMessages(playername)
|
||||
local messages = mail.getMessages()
|
||||
local playerSentMessages = {}
|
||||
if messages[1] then
|
||||
for _, msg in ipairs(messages) do
|
||||
if msg.sender == playername then -- check if player is the sender
|
||||
-- do not return if the message was deleted from player
|
||||
if mail.getMessageStatus(playername, msg.id) ~= "deleted" then
|
||||
table.insert(playerSentMessages, msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return playerSentMessages
|
||||
end
|
||||
|
||||
function mail.setMessages(playername, messages)
|
||||
if mail.write_json_file(mail.getMailFile(playername), messages) then
|
||||
mail.hud_update(playername, messages)
|
||||
return true
|
||||
else
|
||||
minetest.log("error","[mail] Save failed - messages may be lost! ("..playername..")")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function mail.addMessage(message)
|
||||
local messages = mail.getMessages()
|
||||
if messages[1] then
|
||||
local previousMsg = messages[1]
|
||||
message.id = previousMsg.id + 1
|
||||
table.insert(messages, message)
|
||||
else
|
||||
message.id = 1
|
||||
messages = {message}
|
||||
end
|
||||
if mail.write_json_file(mail.maildir .. "/mail.messages.json", messages) then
|
||||
-- add default status (unread for receivers) of this message
|
||||
local isSenderAReceiver = false
|
||||
|
||||
-- extracted maillists from all receivers
|
||||
local receivers = mail.extractMaillists((message.to .. "," .. (message.cc or "")
|
||||
.. "," .. (message.bcc or "")), message.sender)
|
||||
|
||||
for _, receiver in ipairs(receivers) do
|
||||
if minetest.player_exists(receiver) then -- avoid blank names
|
||||
mail.addStatus(receiver, message.id, "unread")
|
||||
if message.sender == receiver then
|
||||
isSenderAReceiver = true
|
||||
-- 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
|
||||
|
||||
if isSenderAReceiver == false then
|
||||
mail.addStatus(message.sender, message.id, "read")
|
||||
end
|
||||
return true
|
||||
else
|
||||
minetest.log("error","[mail] Save failed - messages may be lost!")
|
||||
return false
|
||||
-- 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
|
||||
|
||||
function mail.getStatus()
|
||||
local messagesStatus = mail.read_json_file(mail.maildir .. "/mail.status.json")
|
||||
return messagesStatus
|
||||
end
|
||||
|
||||
function mail.getMessageStatus(player, msg_id)
|
||||
local messagesStatus = mail.getStatus()
|
||||
for _, msg in ipairs(messagesStatus) do
|
||||
if msg.id == msg_id and msg.player == player then
|
||||
return msg.status
|
||||
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
|
||||
|
||||
function mail.addStatus(player, msg_id, status)
|
||||
local messagesStatus = mail.getStatus()
|
||||
local msg_status = {id = msg_id, player = player, status = status}
|
||||
table.insert(messagesStatus, msg_status)
|
||||
if mail.write_json_file(mail.maildir .. "/mail.status.json", messagesStatus) then
|
||||
return true
|
||||
else
|
||||
minetest.log("error","[mail] Save failed - messages status may be lost!")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function mail.setStatus(player, msg_id, status)
|
||||
local messagesStatus = mail.getStatus()
|
||||
for _, msg_status in ipairs(messagesStatus) do
|
||||
if msg_status.id == msg_id and msg_status.player == player then
|
||||
messagesStatus[_] = {id = msg_id, player = player, status = status}
|
||||
end
|
||||
end
|
||||
if mail.write_json_file(mail.maildir .. "/mail.status.json", messagesStatus) then
|
||||
return true
|
||||
else
|
||||
minetest.log("error","[mail] Save failed - messages status may be lost!")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function mail.getContactsFile()
|
||||
return mail.maildir .. "/mail.contacts.json"
|
||||
|
|
14
ui/inbox.lua
14
ui/inbox.lua
|
@ -28,7 +28,7 @@ function mail.show_inbox(name)
|
|||
|
||||
if messages[1] then
|
||||
for _, message in ipairs(messages) do
|
||||
if mail.getMessageStatus(name, message.id) == "unread" then
|
||||
if not message.read then
|
||||
if not mail.player_in_list(name, message.to) then
|
||||
formspec[#formspec + 1] = ",#FFD788"
|
||||
else
|
||||
|
@ -114,9 +114,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
|
||||
elseif fields.delete then
|
||||
if formname == "mail:inbox" and messagesInbox[mail.selected_idxs.inbox[name]] then -- inbox table
|
||||
mail.setStatus(name, messagesInbox[mail.selected_idxs.inbox[name]].id, "deleted")
|
||||
mail.delete_mail(name, messagesInbox[mail.selected_idxs.inbox[name]].id)
|
||||
elseif formname == "mail:sent" and messagesSent[mail.selected_idxs.sent[name]] then -- sent table
|
||||
mail.setStatus(name, messagesSent[mail.selected_idxs.sent[name]].id, "deleted")
|
||||
mail.delete_mail(name, messagesSent[mail.selected_idxs.sent[name]].id)
|
||||
end
|
||||
|
||||
mail.show_mail_menu(name)
|
||||
|
@ -150,18 +150,18 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
|
||||
elseif fields.markread then
|
||||
if formname == "mail:inbox" and messagesInbox[mail.selected_idxs.inbox[name]] then
|
||||
mail.setStatus(name, messagesInbox[mail.selected_idxs.inbox[name]].id, "read")
|
||||
mail.mark_read(name, messagesInbox[mail.selected_idxs.inbox[name]].id)
|
||||
elseif formname == "mail:sent" and messagesSent[mail.selected_idxs.sent[name]] then
|
||||
mail.setStatus(name, messagesSent[mail.selected_idxs.sent[name]].id, "read")
|
||||
mail.mark_read(name, messagesSent[mail.selected_idxs.sent[name]].id)
|
||||
end
|
||||
|
||||
mail.show_mail_menu(name)
|
||||
|
||||
elseif fields.markunread then
|
||||
if formname == "mail:inbox" and messagesInbox[mail.selected_idxs.inbox[name]] then
|
||||
mail.setStatus(name, messagesInbox[mail.selected_idxs.inbox[name]].id, "unread")
|
||||
mail.mark_unread(name, messagesInbox[mail.selected_idxs.inbox[name]].id)
|
||||
elseif formname == "mail:sent" and messagesSent[mail.selected_idxs.sent[name]] then
|
||||
mail.setStatus(name, messagesSent[mail.selected_idxs.sent[name]].id, "unread")
|
||||
mail.mark_unread(name, messagesSent[mail.selected_idxs.sent[name]].id)
|
||||
end
|
||||
|
||||
mail.show_mail_menu(name)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
local FORMNAME = "mail:message"
|
||||
|
||||
function mail.show_message(name, msgnumber)
|
||||
local message = mail.getMessage(msgnumber)
|
||||
function mail.show_message(name, id)
|
||||
local message = mail.get_message(name, id)
|
||||
|
||||
local formspec = [[
|
||||
size[8,9]
|
||||
|
||||
|
@ -32,10 +33,9 @@ function mail.show_message(name, msgnumber)
|
|||
local body = minetest.formspec_escape(message.body) or ""
|
||||
formspec = string.format(formspec, from, to, cc, date, subject, body)
|
||||
|
||||
local message_status = mail.getMessageStatus(name, message.id)
|
||||
|
||||
if message_status == "unread" then
|
||||
mail.setStatus(name, message.id, "read")
|
||||
if not message.read then
|
||||
-- mark as read
|
||||
mail.mark_read(name, id)
|
||||
end
|
||||
|
||||
minetest.show_formspec(name, FORMNAME, formspec)
|
||||
|
@ -125,9 +125,9 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
|
||||
elseif fields.delete then
|
||||
if messagesInbox[mail.selected_idxs.inbox[name]] then
|
||||
mail.setStatus(name, messagesInbox[mail.selected_idxs.inbox[name]].id, "deleted")
|
||||
mail.delete_mail(name, messagesInbox[mail.selected_idxs.inbox[name]].id)
|
||||
elseif messagesSent[mail.selected_idxs.sent[name]] then
|
||||
mail.setStatus(name, messagesSent[mail.selected_idxs.sent[name]].id, "deleted")
|
||||
mail.delete_mail(name, messagesSent[mail.selected_idxs.sent[name]].id)
|
||||
end
|
||||
mail.show_mail_menu(name)
|
||||
end
|
||||
|
|
|
@ -19,7 +19,8 @@ local sent_formspec = "size[8,10;]" .. mail.theme .. [[
|
|||
|
||||
function mail.show_sent(name)
|
||||
local formspec = { sent_formspec }
|
||||
local messages = mail.getPlayerSentMessages(name)
|
||||
local entry = mail.get_storage_entry(name)
|
||||
local messages = entry.outbox
|
||||
|
||||
mail.message_drafts[name] = nil
|
||||
|
||||
|
|
9
util/uuid.lua
Normal file
9
util/uuid.lua
Normal file
|
@ -0,0 +1,9 @@
|
|||
-- source: https://gist.github.com/jrus/3197011
|
||||
local random = math.random
|
||||
function mail.new_uuid()
|
||||
local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
|
||||
return string.gsub(template, '[xy]', function (c)
|
||||
local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
|
||||
return string.format('%x', v)
|
||||
end)
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue