mirror of
https://github.com/mt-mods/mail.git
synced 2025-07-08 07:30:34 -04:00
storage rewrite wip
This commit is contained in:
parent
e08238f50e
commit
894e5df4b1
7 changed files with 62 additions and 148 deletions
12
README.md
12
README.md
|
@ -29,6 +29,18 @@ To provide a web-based interface to receive/send mails you can use the [mtui](ht
|
|||
To access your mail click on the inventory mail button or use the "/mail" command
|
||||
Mails can be deleted, marked as read or unread, replied to and forwarded to another player
|
||||
|
||||
# Compatibility / Migration
|
||||
|
||||
Overview:
|
||||
* `v1` all the data is in the `<worldfolder>/mails.db` file
|
||||
* `v2` every player has its own (in-) mailbox in the `<worldfolder>/mails/<playername>.json` file
|
||||
* `v3` every player has an entry in the `<playername>` modstorage (inbox, outbox, contacts)
|
||||
|
||||
Mails in the v1 format are supported until commit `b0a5bc7e47ec1c75339e65ec07d0a0ac2b17288b`.
|
||||
Everything after that assumes either the v2 or v3 is used.
|
||||
|
||||
For a v1 to v3 migration the version in `b0a5bc7e47ec1c75339e65ec07d0a0ac2b17288b` has to be at leas run once (startup).
|
||||
|
||||
# Dependencies
|
||||
* None
|
||||
|
||||
|
|
15
gui.lua
15
gui.lua
|
@ -109,7 +109,8 @@ end
|
|||
|
||||
function mail.show_inbox(name)
|
||||
local formspec = { mail.inbox_formspec }
|
||||
local messages = mail.getPlayerInboxMessages(name)
|
||||
local entry = mail.get_storage_entry(name)
|
||||
local messages = entry.inbox
|
||||
|
||||
message_drafts[name] = nil
|
||||
|
||||
|
@ -509,8 +510,10 @@ function mail.handle_receivefields(player, formname, fields)
|
|||
elseif formname == "mail:inbox" or formname == "mail:sent" then
|
||||
local name = player:get_player_name()
|
||||
-- split inbox and sent msgs for different tests
|
||||
local messagesInbox = mail.getPlayerInboxMessages(name)
|
||||
local messagesSent = mail.getPlayerSentMessages(name)
|
||||
local entry = mail.get_storage_entry(name)
|
||||
|
||||
local messagesInbox = entry.inbox
|
||||
local messagesSent = entry.outbox
|
||||
|
||||
if fields.inbox then -- inbox table
|
||||
local evt = minetest.explode_table_event(fields.inbox)
|
||||
|
@ -629,8 +632,10 @@ function mail.handle_receivefields(player, formname, fields)
|
|||
|
||||
elseif formname == "mail:message" then
|
||||
local name = player:get_player_name()
|
||||
local messagesInbox = mail.getPlayerInboxMessages(name)
|
||||
local messagesSent = mail.getPlayerSentMessages(name)
|
||||
local entry = mail.get_storage_entry(name)
|
||||
|
||||
local messagesInbox = entry.inbox
|
||||
local messagesSent = entry.outbox
|
||||
|
||||
if fields.back then
|
||||
if boxtab_index == 1 then
|
||||
|
|
5
init.lua
5
init.lua
|
@ -7,7 +7,10 @@ mail = {
|
|||
|
||||
-- mail directory
|
||||
maildir = minetest.get_worldpath().."/mails",
|
||||
contactsdir = minetest.get_worldpath().."/mails/contacts"
|
||||
contactsdir = minetest.get_worldpath().."/mails/contacts",
|
||||
|
||||
-- mod storage
|
||||
storage = minetest.get_mod_storage()
|
||||
}
|
||||
|
||||
|
||||
|
|
98
migrate.lua
98
migrate.lua
|
@ -1,58 +1,28 @@
|
|||
|
||||
local STORAGE_VERSION_KEY = "@@version"
|
||||
|
||||
function mail.migrate()
|
||||
local gen_file_v1 = io.open(minetest.get_worldpath().."/mail.db", "r")
|
||||
if gen_file_v1 then
|
||||
mail.migrate_v1_to_v2()
|
||||
end
|
||||
|
||||
local info_file_v3 = mail.read_json_file(mail.maildir .. "/mail.info.json")
|
||||
if not info_file_v3.dbversion then
|
||||
local version = mail.storage:get_int(STORAGE_VERSION_KEY)
|
||||
if version < 3 then
|
||||
mail.migrate_v2_to_v3()
|
||||
mail.storage:set_int(STORAGE_VERSION_KEY, 3)
|
||||
end
|
||||
end
|
||||
|
||||
-- migrate from mail.db to player-file-based mailbox
|
||||
function mail.migrate_v1_to_v2()
|
||||
-- create directory, just in case
|
||||
minetest.mkdir(mail.maildir)
|
||||
minetest.mkdir(mail.contactsdir)
|
||||
|
||||
local file = io.open(minetest.get_worldpath().."/mail.db", "r")
|
||||
if file then
|
||||
print("[mail] migrating to new per-player storage")
|
||||
|
||||
local data = file:read("*a")
|
||||
local oldmails = minetest.deserialize(data)
|
||||
file:close()
|
||||
|
||||
for name, oldmessages in pairs(oldmails) do
|
||||
mail.setMessages(name, oldmessages)
|
||||
end
|
||||
|
||||
-- rename file
|
||||
print("[mail] migration done, renaming old mail.db")
|
||||
os.rename(minetest.get_worldpath().."/mail.db", minetest.get_worldpath().."/mail.db.old")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- migrate from v2 to v3 database
|
||||
function mail.migrate_v2_to_v3()
|
||||
minetest.mkdir(mail.maildir) -- if necessary (eg. first login)
|
||||
minetest.log("info", "[mail] Migration from v2 to v3 database")
|
||||
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
|
||||
mail.migrate_contacts_v2_to_v3(playername)
|
||||
end
|
||||
end)
|
||||
mail.migrate_messages_v2_to_v3()
|
||||
mail.write_json_file(mail.maildir .. "/mail.info.json", { dbversion = 3.0 })
|
||||
local player_contacts = mail.read_json_file(mail.maildir .. "/contacts/" .. playername .. ".json")
|
||||
local entry = mail.get_storage_entry(playername)
|
||||
for _, c in pairs(player_contacts) do
|
||||
table.insert(entry.contacts, { name = c.name, note = c.note })
|
||||
end
|
||||
|
||||
function mail.migrate_messages_v2_to_v3()
|
||||
local already_processed = {} -- store messages that are already process to avoid duplicates
|
||||
minetest.after(0,function()
|
||||
-- check in every inbox to fetch messages
|
||||
for playername, _ in minetest.get_auth_handler().iterate() do
|
||||
local saneplayername = string.gsub(playername, "[.|/]", "")
|
||||
local player_inbox = mail.read_json_file(mail.maildir .. "/" .. saneplayername .. ".json")
|
||||
for _, msg in ipairs(player_inbox) do
|
||||
|
@ -79,46 +49,8 @@ function mail.migrate_messages_v2_to_v3()
|
|||
table.insert(already_processed, msg_id)
|
||||
end
|
||||
end
|
||||
|
||||
mail.set_storage_entry(playername, entry)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function mail.migrate_contacts(playername)
|
||||
local gen_file_v1 = io.open(minetest.get_worldpath().."/mail.db", "r")
|
||||
if gen_file_v1 then
|
||||
mail.migrate_contacts_v1_to_v2(playername)
|
||||
end
|
||||
|
||||
-- v2 to v3 directly in general function
|
||||
end
|
||||
|
||||
function mail.migrate_contacts_v1_to_v2(playername)
|
||||
local file = io.open(mail.getContactsFile(playername), 'r')
|
||||
if not file then
|
||||
-- file doesn't exist! This is a case for Migrate Man!
|
||||
local messages = mail.getMessages(playername)
|
||||
local contacts = {}
|
||||
|
||||
if messages and not contacts then
|
||||
for _, message in pairs(messages) do
|
||||
mail.ensure_new_format(message)
|
||||
if contacts[string.lower(message.from)] == nil then
|
||||
contacts[string.lower(message.from)] = {
|
||||
name = message.from,
|
||||
note = "",
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
file:close() -- uh, um, nope, let's leave those alone, shall we?
|
||||
end
|
||||
end
|
||||
|
||||
function mail.migrate_contacts_v2_to_v3(playername)
|
||||
local player_contacts = mail.read_json_file(mail.maildir .. "/contacts/" .. playername .. ".json")
|
||||
|
||||
for _, c in pairs(player_contacts) do
|
||||
mail.addContact(playername, { name = c.name, note = c.note })
|
||||
end
|
||||
end
|
||||
|
|
4
mtt.lua
4
mtt.lua
|
@ -7,7 +7,7 @@ mtt.register("send mail", function(callback)
|
|||
mail.send({from = "player1", to = "player2", subject = "something", body = "blah"})
|
||||
|
||||
-- check the receivers inbox
|
||||
local list2 = mail.getPlayerInboxMessages("player2")
|
||||
assert(list2 ~= nil and #list2 > 0)
|
||||
local entry = mail.get_storage_entry("player2")
|
||||
assert(entry ~= nil and #entry.inbox > 0)
|
||||
callback()
|
||||
end)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
minetest.register_on_joinplayer(function(player)
|
||||
minetest.after(2, function(name)
|
||||
local messages = mail.getPlayerMessages(name)
|
||||
local messages = mail.getMessages(name)
|
||||
|
||||
local unreadcount = 0
|
||||
|
||||
|
@ -16,6 +16,4 @@ minetest.register_on_joinplayer(function(player)
|
|||
|
||||
end
|
||||
end, player:get_player_name())
|
||||
|
||||
mail.migrate_contacts(player:get_player_name())
|
||||
end)
|
||||
|
|
68
storage.lua
68
storage.lua
|
@ -1,26 +1,20 @@
|
|||
function mail.getMailFile(playername)
|
||||
local saneplayername = string.gsub(playername, "[.|/]", "")
|
||||
return mail.maildir .. "/" .. saneplayername .. ".json"
|
||||
end
|
||||
|
||||
function mail.getMessages(playername)
|
||||
if (playername) then
|
||||
return mail.getPlayerMessages(playername)
|
||||
end
|
||||
local messages = mail.read_json_file(mail.maildir .. "/mail.messages.json")
|
||||
if messages then
|
||||
for _, msg in ipairs(messages) do
|
||||
if not msg.time then
|
||||
-- add missing time field if not available (happens with old data)
|
||||
msg.time = 0
|
||||
function mail.get_storage_entry(playername)
|
||||
local str = mail.storage:get_string(playername)
|
||||
if str == "" then
|
||||
-- new entry
|
||||
return {
|
||||
contacts = {},
|
||||
inbox = {},
|
||||
outbox = {}
|
||||
}
|
||||
else
|
||||
-- deserialize existing entry
|
||||
return minetest.parse_json(str)
|
||||
end
|
||||
end
|
||||
|
||||
-- sort by received date descending
|
||||
table.sort(messages, function(a,b) return a.time > b.time end)
|
||||
end
|
||||
|
||||
return messages
|
||||
function mail.set_storage_entry(playername, entry)
|
||||
mail.storage:get_string(playername, minetest.write_json(entry))
|
||||
end
|
||||
|
||||
function mail.getMessage(msg_id)
|
||||
|
@ -34,7 +28,8 @@ function mail.getMessage(msg_id)
|
|||
end
|
||||
end
|
||||
|
||||
function mail.getPlayerMessages(playername)
|
||||
-- api in use by the `fancyvend` mod
|
||||
function mail.getMessages(playername)
|
||||
local messages = mail.getMessages()
|
||||
local playerMessages = {}
|
||||
if messages then
|
||||
|
@ -68,37 +63,6 @@ function mail.getPlayerMessages(playername)
|
|||
return playerMessages
|
||||
end
|
||||
|
||||
function mail.getPlayerInboxMessages(playername)
|
||||
local messages = mail.getMessages()
|
||||
local playerInboxMessages = {}
|
||||
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(playerInboxMessages, msg)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- show hud notification
|
||||
mail.hud_update(playername, playerInboxMessages)
|
||||
end
|
||||
|
||||
return playerInboxMessages
|
||||
end
|
||||
|
||||
function mail.getPlayerSentMessages(playername)
|
||||
local messages = mail.getMessages()
|
||||
local playerSentMessages = {}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue