view mod_nodeinfo2/mod_nodeinfo2.lua @ 4203:c4002aae4ad3

mod_s2s_keepalive: Use timestamp as iq @id RFC 6120 implies that the id attribute must be unique within a stream. This should fix problems with remote servers that enforce uniqueness and don't answer duplicated ids. If it doesn't do that, then at least you can get a guesstimate at round-trip time from the difference between the result iq stanza and the timestamp it was logged without having to go look for when it was sent, or needing to keep state.
author Kim Alvefur <zash@zash.se>
date Wed, 14 Oct 2020 18:02:10 +0200
parents aec772bbd558
children bac3dae031ee
line wrap: on
line source

local json = require "util.json";
local array = require "util.array";
local add_task = require "util.timer".add_task;
local get_stats = require "core.statsmanager".get_stats;
local list_users = require "core.usermanager".users;
local os_time = os.time;

module:depends("http");

local expose_users = module:get_option_boolean("nodeinfo2_expose_users", true);
if expose_users then
	module:depends("lastlog");
end

local expose_posts = module:get_option_boolean("nodeinfo2_expose_posts", true);
if expose_posts then
	module:depends("measure_message_e2ee");
end

local main_store = module:open_store();
local lastlog_store = module:open_store("lastlog");

local data;
if expose_posts then
	data = main_store:get("nodeinfo2") or { message_count = 0 };
end

local total_users = 0;
local week_users = 0;
local month_users = 0;
local half_year_users = 0;

local function update_user_list()
	for user in list_users(module.host) do
		total_users = total_users + 1;
		local lastlog = lastlog_store:get(user);
		if lastlog and lastlog.timestamp then
			local delta = os_time() - lastlog.timestamp;
			if delta < 7 * 86400 then
				week_users = week_users + 1;
			end
			if delta < 30 * 86400 then
				month_users = month_users + 1;
			end
			if delta < 6 * 30 * 86400 then
				half_year_users = half_year_users + 1;
			end
		end
	end

	-- Remove the properties if we couldn’t find a single active user.  It most likely means mod_lastlog isn’t in use.
	if half_year_users == 0 and month_users == 0 and week_users == 0 then
		week_users = nil;
		month_users = nil;
		half_year_users = nil;
	end
end

if expose_users then
	add_task(86400, update_user_list);
	update_user_list();
end

module:provides("http", {
	default_path = "/.well-known/x-nodeinfo2";
	route = {
		GET = function (event)
			local usage = {};
			if expose_users then
				usage.users = {
					total = total_users;
					activeWeek = week_users;
					activeMonth = month_users;
					activeHalfyear = half_year_users;
				};
			end

			if expose_posts then
				local stats, changed_only, extras = get_stats();
				for stat, _ in pairs(stats) do
					if stat == "/"..module.host.."/mod_measure_message_e2ee/message:rate" then
						local new_message_count = extras[stat].total;
						if new_message_count ~= data.message_count then
							data = { message_count = new_message_count };
							main_store:set("nodeinfo2", data);
						end
					end
				end
				usage.localPosts = data.message_count;
				-- TODO: also count PubSub replies here.
				usage.localComments = 0;
			end

			event.response.headers.content_type = "application/json";
			return json.encode({
				version = "1.0";
				server = {
					baseUrl = module:http_url("","/");
					name = module.host;
					software = "Prosody";
					version = prosody.version;
				};
				--[[ TODO re-use data from mod_server_contact_info ?
				organization = {
					name = "";
					contact = "";
					account = "";
				};
				--]]
				protocols = array {
					"xmpp",
				};
				services = {
					inbound = array {
						"xmpp";
					};
					outbound = array {
						"xmpp";
					};
				};
				openRegistrations = module:get_option_boolean("allow_registration", false);
				usage = usage;
			});
		end;
	}
});