The messages domain
api.messages handles private user-to-user communication. Send messages by user ID or username, read chat threads, track unread counts.
Function reference
| Function | Returns | Description |
|---|---|---|
api.messages.get(id) |
table or nil | Get a single message |
api.messages.send(to, content) |
table | Send a message (by user ID or username) |
api.messages.chat(uid, page?, limit?) |
{ items, total } |
Get conversation with a specific user |
api.messages.conversations() |
table[] | List all conversation partners |
api.messages.unread() |
number | Unread message count |
api.messages.edit(id, content) |
table | Edit a message |
api.messages.delete(id) |
boolean | Delete a message |
Sending messages
-- By user ID
api.messages.send(42, "Hey, how are you?")
-- By username
api.messages.send("johndoe", "Hello from Lua!")
Reading a conversation
-- Get chat with user 42, page 1, 30 messages per page
local chat = api.messages.chat(42, 1, 30)
for _, msg in ipairs(chat.items) do
print(msg.sender.username .. ": " .. msg.content)
end
Unread message badge
app:on("before", function(ctx)
if env.is_user then
ctx.unread = api.messages.unread()
end
end)
{% if unread > 0 %}
<span class="badge">{{ unread }}</span>
{% endif %}
Message inbox page
app:get("/messages", function(ctx)
if not env.is_user then
return ctx:redirect("/login")
end
local conversations = api.messages.conversations()
local unread = api.messages.unread()
return ctx:render("messages", {
conversations = conversations,
unread_count = unread
})
end)
Chat with a specific user
app:get("/messages/:userid", function(ctx)
if not env.is_user then
return ctx:redirect("/login")
end
local uid = tonumber(ctx.params.userid)
local chat = api.messages.chat(uid, 1, 50)
return ctx:render("chat", {
messages = chat.items,
other_user = uid
})
end)
app:post("/messages/:userid", function(ctx)
if not env.is_user then
return ctx:error("Login required", 401)
end
local uid = tonumber(ctx.params.userid)
local content = req.post.message
if not content or str.trim(content) == "" then
ctx:flash("error", "Message cannot be empty")
return ctx:redirect("/messages/" .. uid)
end
api.messages.send(uid, content)
return ctx:redirect("/messages/" .. uid)
end, { csrf = true })
Sending via username
-- Let users address messages by typing a username
api.messages.send(req.post.recipient, req.post.content)
-- Works whether recipient is "42" or "johndoe"
Next: api.files & api.folders — manage uploads and organize in folders.