Software /
code /
prosody-modules
Changeset
3682:47e1c94fb6fb
mod_muc_media_metadata: Module to automatically fetch metadata for posted media
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Sun, 29 Sep 2019 16:47:57 +0100 (2019-09-29) |
parents | 3681:d267e381255f |
children | 3683:1432020c33c7 |
files | mod_muc_media_metadata/README.md mod_muc_media_metadata/mod_muc_media_metadata.lua |
diffstat | 2 files changed, 99 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_muc_media_metadata/README.md Sun Sep 29 16:47:57 2019 +0100 @@ -0,0 +1,38 @@ +# Introduction + +This module adds additional metadata to media shared in a MUC. This can help clients +make decisions and provide better UI and enhanced privacy, by knowing things like file +size without needing to make external network requests. + +# Configuring + +## Enabling + +``` {.lua} +Component "rooms.example.net" "muc" +modules_enabled = { + "muc_hide_media"; +} +``` + +## Settings + +There are no configuration options for this module. + +# Developers + +Example stanza: + +``` +<message from="test@rooms.example.com/matthew" id="9f45a784-5e5b-4db5-a9b3-8ea1d7c1162d" type="groupchat"> + <body>https://matthewwild.co.uk/share.php/70334772-ff74-439b-8173-a71e40ca28db/mam-flow.png</body> + <x xmlns="jabber:x:oob"> + <url>https://matthewwild.co.uk/share.php/70334772-ff74-439b-8173-a71e40ca28db/mam-flow.png</url> + <metadata xmlns="https://prosody.im/protocol/media-metadata#0"> + <bytes>15690</bytes> + <type>image/png</type> + <blurhash>LEHV6nWB2yk8pyo0adR*.7kCMdnj</blurhash> + </metadata> + </x> +</message> +```
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_muc_media_metadata/mod_muc_media_metadata.lua Sun Sep 29 16:47:57 2019 +0100 @@ -0,0 +1,61 @@ +local async = require "util.async"; +local promise = require "util.promise"; +local http = require "net.http"; +local st = require "util.stanza"; + +local xmlns_metadata = "https://prosody.im/protocol/media-metadata#0" + +local fetch_headers = { + bytes = "content-length"; + type = "content-type"; + etag = "etag"; + blurhash = "blurhash"; +}; + +local function fetch_media_metadata(url) + return promise.new(function (resolve) + http.request(url, { method = "HEAD" }, function (body, code, response) --luacheck: ignore 212/body + if code == 200 then + local metadata = {}; + for metadata_name, header_name in pairs(fetch_headers) do + metadata[metadata_name] = response.headers[header_name]; + end + resolve(metadata); + else + resolve(nil); + end + end); + end); +end + +local function metadata_to_tag(metadata) + if not metadata then return; end + + local metadata_tag = st.stanza("metadata", { xmlns = xmlns_metadata }); + for k, v in pairs(metadata) do + metadata_tag:text_tag(k, v) + end + + return metadata_tag; +end + +module:hook("muc-occupant-groupchat", function (event) + local stanza = event.stanza; + + local promises; + + for oob in stanza:childtags("x", "jabber:x:oob") do + if not promises then promises = {}; end + local url = oob:get_child_text("url"); + local p = fetch_media_metadata(url) + :next(metadata_to_tag) + :next(function (metadata_tag) + oob:add_child(metadata_tag); + end); + table.insert(promises, p); + end + + if not promises then return; end + + async.wait(promise.all(promises)); +end);