diff --git a/prosody-modules/mod_vcard_peertubelivechat/README.md b/prosody-modules/mod_vcard_peertubelivechat/README.md new file mode 100644 index 00000000..74e370cf --- /dev/null +++ b/prosody-modules/mod_vcard_peertubelivechat/README.md @@ -0,0 +1,5 @@ +# mod_vcard_peertubelivechat + +This module is a custom module that allows Prosody to load vCards from Peertube. + +This module is part of peertube-plugin-livechat, and is under the same LICENSE. diff --git a/prosody-modules/mod_vcard_peertubelivechat/mod_vcard_peertubelivechat.lua b/prosody-modules/mod_vcard_peertubelivechat/mod_vcard_peertubelivechat.lua new file mode 100644 index 00000000..92c63721 --- /dev/null +++ b/prosody-modules/mod_vcard_peertubelivechat/mod_vcard_peertubelivechat.lua @@ -0,0 +1,73 @@ +local st = require "util.stanza"; +local http = require "net.http"; +local async = require "util.async"; +local b64 = require "util.encodings".base64.encode; +local jid_split = require "util.jid".split; +local json = require "util.json"; +local uh = require "util.http"; + +module:add_feature("vcard-temp"); + +local peertube_url = assert(module:get_option_string("peertubelivechat_vcard_peertube_url", nil), "'peertubelivechat_vcard_peertube_url' is a required option"); +if peertube_url:sub(-1,-1) == "/" then peertube_url = peertube_url:sub(1,-2); end + +module:hook("iq-get/bare/vcard-temp:vCard", function (event) + local origin, stanza = event.origin, event.stanza; + local who = jid_split(stanza.attr.to) or origin.username + module:log("debug", "vCard request for %s", who); + + local wait, done = async.waiter(); + local url = peertube_url .. '/api/v1/accounts/' .. uh.urlencode(who); + module:log("debug", "Calling Peertube API: %s", url); + local ret; + http.request(url, { accept = "application/json" }, function (body, code) + if math.floor(code / 100) == 2 then + local parsed, parse_err = json.decode(body); + if not parsed then + module:log("debug", "Got invalid JSON from %s: %s", url, parse_err); + else + ret = parsed; + end + else + module:log("debug", "Rejected by API: ", body); + end + done(); + end) + + wait(); + + if not ret then + module:log("debug", "Peertube user not found, no vCard for %s", who); + origin.send(st.error_reply(stanza, "cancel", "item-not-found")); + return true; + end + + local vcard_temp = st.stanza("vCard", { xmlns = "vcard-temp" }); + vcard_temp:text_tag("NICKNAME", ret.displayName); + + if ret.avatar and ret.avatar.path then + module:log("debug", "Downloading user avatar on %s", peertube_url .. ret.avatar.path); + local waitAvatar, doneAvatar = async.waiter(); + http.request(peertube_url .. ret.avatar.path, {}, function (body, code, response) + if math.floor(code / 100) == 2 then + module:log("debug", "Avatar found for %s", who); + vcard_temp:tag("PHOTO") + if (response and response.headers and response.headers["Content-Type"]) then + module:log("debug", "Avatar Content-Type: %s", response.headers["Content-Type"]); + vcard_temp:text_tag("TYPE", response.headers["Content-Type"]) + end + vcard_temp:text_tag("BINVAL", b64(body)) + vcard_temp:up() + else + module:log("debug", "Cant load avatar: ", body); + end + doneAvatar(); + end) + + waitAvatar(); + end + + origin.send(st.reply(stanza):add_child(vcard_temp)); + return true; +end, 1); -- TODO: Negative priority, so if the user has set a custom vCard (mod_vcard_legacy), it will be used? +-- TODO: cache results for N seconds diff --git a/server/lib/prosody/config.ts b/server/lib/prosody/config.ts index 3b102f3c..5c5e4785 100644 --- a/server/lib/prosody/config.ts +++ b/server/lib/prosody/config.ts @@ -108,14 +108,14 @@ async function getProsodyConfig (options: RegisterServerOptions): Promise