rename api, add cc and bcc, handle multiple players

rename: src -> from, dst -> to
This commit is contained in:
Peter Nerlich 2020-07-31 12:36:28 +02:00
parent 2d087eaa13
commit 522eb0a9ee
5 changed files with 115 additions and 21 deletions

64
api.lua
View File

@ -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

25
api.md
View File

@ -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"
})

20
gui.lua
View File

@ -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
})

View File

@ -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")

26
util/normalize.lua Normal file
View File

@ -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