changeset 4825:4bdfd83e091f

mod_jsxc: Demo module serving JSXC relatively easily from Prosody Copy of mod_conversejs adjusted for JSXC. README TODO
author Kim Alvefur <zash@zash.se>
date Wed, 15 Dec 2021 18:28:40 +0100
parents 205b9d06fe6b
children 3a5fbb6c61b3
files mod_jsxc/mod_jsxc.lua mod_jsxc/templates/template.html mod_jsxc/templates/template.js
diffstat 3 files changed, 147 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_jsxc/mod_jsxc.lua	Wed Dec 15 18:28:40 2021 +0100
@@ -0,0 +1,107 @@
+-- mod_jsxc
+-- Copyright (C) 2021 Kim Alvefur
+
+local json_encode = require"util.json".encode;
+local xml_escape = require "util.stanza".xml_escape;
+local render = require "util.interpolation".new("%b{}", xml_escape, { json = json_encode });
+
+module:depends"http";
+module:depends"bosh";
+module:depends"http_libjs";
+
+local jquery_url = module:get_option_string("jquery_url", "/share/jquery/jquery.min.js");
+
+local cdn_url = module:get_option_string("jsxc_cdn", "");
+
+local version = module:get_option_string("jsxc_version", "");
+if version ~= "" then version = "/" .. version end
+
+local serve_dist = nil;
+local resources = module:get_option_path("jsxc_resources");
+if resources then
+	local serve;
+	if not pcall(function()
+		-- Prosody >= trunk / 0.12
+		local http_files = require "net.http.files";
+		serve = http_files.serve;
+	end) then
+		-- Prosody <= 0.11
+		serve = module:depends "http_files".serve;
+	end
+	local mime_map = module:shared("/*/http_files/mime").types or { css = "text/css", js = "application/javascript" };
+	serve_dist = serve({ path = resources, mime_map = mime_map });
+
+	cdn_url = module:http_url();
+end
+
+local js_url = module:get_option_string("jsxc_script", cdn_url..version.."/dist/jsxc.bundle.js");
+local css_url = module:get_option_string("jsxc_css", cdn_url..version.."/dist/styles/jsxc.bundle.css");
+
+local html_template;
+
+do
+	local template_filename = module:get_option_string(module.name .. "_html_template", "templates/template.html");
+	local template_file, err = module:load_resource(template_filename);
+	if template_file then
+		html_template, err = template_file:read("*a");
+		template_file:close();
+	end
+	if not html_template then
+		module:log("error", "Error loading HTML template: %s", err);
+		html_template = render("<h1>mod_{module} could not read the template</h1>\
+		<p>Tried to open <b>{filename}</b></p>\
+		<pre>{error}</pre>",
+			{ module = module.name, filename = template_filename, error = err });
+	end
+end
+
+local js_template;
+do
+	local template_filename = module:get_option_string(module.name .. "_js_template", "templates/template.js");
+	local template_file, err = module:load_resource(template_filename);
+	if template_file then
+		js_template, err = template_file:read("*a");
+		template_file:close();
+	end
+	if not js_template then
+		module:log("error", "Error loading JS template: %s", err);
+		js_template = render("console.log(\"mod_{module} could not read the JS template: %s\", {error|json})",
+			{ module = module.name, filename = template_filename, error = err });
+	end
+end
+
+local function get_jsxc_options()
+	return { xmpp = { url = module:http_url("bosh", "/http-bind"), domain = module.host } };
+end
+
+local add_tags = module:get_option_array("jsxc_tags", {});
+
+module:provides("http", {
+	title = "jsxc.js";
+	route = {
+		GET = function (event)
+			local jsxc_options = get_jsxc_options();
+
+			event.response.headers.content_type = "text/html";
+			return render(html_template, {
+					service_name = module:get_option_string("name");
+					header_scripts = { jquery_url, js_url };
+					header_style = { css_url };
+					header_tags = add_tags;
+					jsxcjs = {
+						options = jsxc_options;
+						startup = { script = js_template:format(json_encode(jsxc_options)); }
+					};
+				});
+		end;
+
+		["GET /prosody-jsxc.js"] = function (event)
+			local jsxc_options = get_jsxc_options();
+
+			event.response.headers.content_type = "application/javascript";
+			return js_template:format(json_encode(jsxc_options));
+		end;
+		["GET /dist/*"] = serve_dist;
+	}
+});
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_jsxc/templates/template.html	Wed Dec 15 18:28:40 2021 +0100
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1">
+{header_style#
+<link rel="stylesheet" type="text/css" media="screen" href="{item}"/>}
+{header_scripts#
+<script charset="utf-8" src="{item}"></script>}
+<title>{service_name?Prosody IM and JSXC}</title>
+{header_tags#
+{item!}}
+</head>
+<body>
+	<form id="jsxc_login_form">
+		<dl>
+			<dt><label for="jsxc_username">Username</label></dt>
+			<dd><input id="jsxc_username" name="username" placeholder="Alice"/></dd>
+			<dt><label for="jsxc_password">Password</label></dt>
+			<dd><input id="jsxc_password" name="password" type="password"/></dd>
+		</dl>
+		<button type="submit">Login</button>
+	</form>
+
+<script>{jsxcjs.startup.script!}</script>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mod_jsxc/templates/template.js	Wed Dec 15 18:28:40 2021 +0100
@@ -0,0 +1,13 @@
+$(function() {
+	let jsxc = new JSXC({
+		loadConnectionOptions: function(username, password) {
+			return Promise.resolve(%s);
+		}
+	});
+
+	let formElement = $('#jsxc_login_form');
+	let usernameElement = $('#jsxc_username');
+	let passwordElement = $('#jsxc_password');
+
+	jsxc.watchForm(formElement, usernameElement, passwordElement);
+});