From 522eb0a9eefbdb102bcba993676fd6de4379b521 Mon Sep 17 00:00:00 2001 From: Peter Nerlich Date: Fri, 31 Jul 2020 12:36:28 +0200 Subject: [PATCH] rename api, add cc and bcc, handle multiple players rename: src -> from, dst -> to --- api.lua | 64 +++++++++++++++++++++++++++++++++++++--------- api.md | 25 ++++++++++++++++-- gui.lua | 20 ++++++++++----- init.lua | 1 + util/normalize.lua | 26 +++++++++++++++++++ 5 files changed, 115 insertions(+), 21 deletions(-) create mode 100644 util/normalize.lua diff --git a/api.lua b/api.lua index a8d7e30..6af7d36 100644 --- a/api.lua +++ b/api.lua @@ -14,6 +14,7 @@ all 4 parameters (old compat version) see: "Mail format" api.md --]] function mail.send(src, dst, subject, body) + -- figure out format local m if dst == nil and subject == nil and body == nil then -- new format (one object param) @@ -21,36 +22,75 @@ function mail.send(src, dst, subject, body) else -- old format m = {} - m.src = src - m.dst = dst + m.from = src + m.to = dst m.subject = subject m.body = body end + -- log mail send action + if m.cc or m.bcc then + if m.cc then + cc = "CC: " .. m.cc + if m.bcc then + cc = cc .. " - " + end + else + cc = "" + end + if m.bcc then + bcc = "BCC: " .. m.bcc + else + bcc = "" + end + extra = "(" .. cc .. bcc .. ") " + else + extra = "" + end + minetest.log("action", "[mail] '" .. m.from .. "' sends mail to '" .. m.to .. + extra .. "' with subject '" .. m.subject .. "' and body: '" .. m.body .. "'") - minetest.log("action", "[mail] '" .. m.src .. "' sends mail to '" .. m.dst .. - "' with subject '" .. m.subject .. "' and body: '" .. m.body .. "'") - local messages = mail.getMessages(m.dst) + -- normalize to, cc and bcc while compiling a list of all recipients + local recipients = {} + m.to = normalize_players_and_add_recipients(m.to, recipients) + if m.cc then + m.cc = normalize_players_and_add_recipients(m.cc, recipients) + end + if m.bcc then + m.bcc = normalize_players_and_add_recipients(m.bcc, recipients) + end - table.insert(messages, 1, { + -- form the actual mail + msg = { unread = true, - sender = m.src, + from = m.from, + to = m.to, subject = m.subject, body = m.body, time = os.time(), - }) - mail.setMessages(m.dst, messages) + } + if m.cc then + msg.cc = m.cc + end + -- send the mail to all recipients + for _, recipient in pairs(recipients) do + local messages = mail.getMessages(recipient) + table.insert(messages, 1, msg) + mail.setMessages(recipient, messages) + end + + -- notify recipients that happen to be online for _, player in ipairs(minetest.get_connected_players()) do local name = player:get_player_name() - if name == m.dst then + if recipients[string.lower(name)] ~= nil then if m.subject == "" then m.subject = "(No subject)" end if string.len(m.subject) > 30 then m.subject = string.sub(m.subject,1,27) .. "..." end - minetest.chat_send_player(m.dst, - string.format(mail.receive_mail_message, m.src, m.subject)) + minetest.chat_send_player(name, + string.format(mail.receive_mail_message, m.from, m.subject)) end end diff --git a/api.md b/api.md index 5d059c2..984cd28 100644 --- a/api.md +++ b/api.md @@ -2,6 +2,25 @@ # Mail format The mail format in the api hooks +```lua +mail = { + from = "sender name", + to = "players, which, are, addressed", + cc = "carbon copy", + bcc = "players, which, get, a, copy, but, are, not, visible, to, others", + subject = "subject line", + body = "mail body", + -- 8 attachments max + attachments = {"default:stone 99", "default:gold_ingot 99"} +} +``` + +The fields `to`, `cc` and `bcc` can contain a player, multiple player names separated by commas, or be empty. Players in `to` are the recipiants, who are addressed directly. `cc` specifies players that get the mail to get notified, but are not immediate part of the conversation. There is no technical difference between `to` and `cc`, it just implies meaning for the players. Players can see all fields making up the mail except `bcc`, which is the only difference to `cc`. + +Attachments need to be provided for each player getting the mail. Until this is implemented, trying to send a mail to multiple players will fail. + +The `from` and `to` fields were renamed from the previous format: + ```lua mail = { src = "source name", @@ -22,8 +41,10 @@ mail.send("source name", "destination name", "subject line", "mail body") New variant (1.1+) ```lua mail.send({ - src = "source name", - dst = "destination name", + from = "sender name", + to = "destination name", + cc = "carbon copy", + bcc = "blind carbon copy", subject = "subject line", body = "mail body" }) diff --git a/gui.lua b/gui.lua index f608b85..6baf311 100644 --- a/gui.lua +++ b/gui.lua @@ -89,18 +89,20 @@ function mail.show_message(name, msgnumber) button[5,6.7;2,1;delete;Delete] ]] .. theme - local sender = minetest.formspec_escape(message.sender) + local from = minetest.formspec_escape(message.from) local subject = minetest.formspec_escape(message.subject) local body = minetest.formspec_escape(message.body) - formspec = string.format(formspec, sender, subject, body) + formspec = string.format(formspec, from, subject, body) minetest.show_formspec(name,"mail:message",formspec) end -function mail.show_compose(name, defaulttgt, defaultsubj, defaultbody) +function mail.show_compose(name, defaultto, defaultsubj, defaultbody, defaultcc, defaultbcc) local formspec = [[ size[8,7.2] field[0.25,0.5;4,1;to;To:;%s] + field[0.25,0.5;4,1;to;CC:;%s] + field[0.25,0.5;4,1;to;BCC:;%s] field[0.25,1.7;8,1;subject;Subject:;%s] textarea[0.25,2.4;8,5;body;;%s] button[0.5,6.7;3,1;cancel;Cancel] @@ -111,7 +113,9 @@ function mail.show_compose(name, defaulttgt, defaultsubj, defaultbody) formspec = string.format(formspec, minetest.formspec_escape(defaulttgt), minetest.formspec_escape(defaultsubj), - minetest.formspec_escape(defaultbody)) + minetest.formspec_escape(defaultbody), + minetest.formspec_escape(defaultcc), + minetest.formspec_escape(defaultbcc)) minetest.show_formspec(name, "mail:compose", formspec) end @@ -155,7 +159,7 @@ function mail.handle_receivefields(player, formname, fields) elseif fields.reply and messages[selected_message_idxs[name]] then local message = messages[selected_message_idxs[name]] local replyfooter = "Type your reply here.\n\n--Original message follows--\n" ..message.body - mail.show_compose(name, message.sender, "Re: "..message.subject,replyfooter) + mail.show_compose(name, message.from, "Re: "..message.subject,replyfooter) elseif fields.forward and messages[selected_message_idxs[name]] then local message = messages[selected_message_idxs[name]] @@ -215,8 +219,10 @@ function mail.handle_receivefields(player, formname, fields) elseif formname == "mail:compose" then if fields.send then mail.send({ - src = player:get_player_name(), - dst = fields.to, + from = player:get_player_name(), + to = fields.to, + cc = "", + bcc = "" subject = fields.subject, body = fields.body }) diff --git a/init.lua b/init.lua index e35875b..4410e13 100644 --- a/init.lua +++ b/init.lua @@ -26,6 +26,7 @@ mail = { local MP = minetest.get_modpath(minetest.get_current_modname()) +dofile(MP .. "/util/normalize.lua") dofile(MP .. "/chatcommands.lua") dofile(MP .. "/migrate.lua") dofile(MP .. "/attachment.lua") diff --git a/util/normalize.lua b/util/normalize.lua new file mode 100644 index 0000000..13f51b0 --- /dev/null +++ b/util/normalize.lua @@ -0,0 +1,26 @@ +--[[ +return the field normalized (comma separated, single space) +and add individual player names to recipient list +--]] +function normalize_players_and_add_recipients(field, recipients) + local separator = ", " + local pattern = "([^" .. separator .. "]+)" + + -- get individual players + local player_set = {} + local order = {} + field:gsub(pattern, function(c) + if player_set[string.lower(c)] ~= nil then + player_set[string.lower(c)] = c + order[#order+1] = c + + -- also sort into recipients + if recipients[string.lower(c)] ~= nil then + recipients[string.lower(c)] = c + end + end + end) + + -- turn list of players back into normalized string + return table.concat(order, ", ") +end