Software /
code /
prosody-modules
Annotate
mod_devices/mod_devices.lua @ 4941:e7b9bc629ecc
mod_rest: Add special handling to catch MAM results from remote hosts
Makes MAM queries to remote hosts works.
As the comment says, MAM results from users' local archives or local
MUCs are returned via origin.send() which is provided in the event and
thus already worked. Results from remote hosts go via normal stanza
routing and events, which need this extra handling to catch.
This pattern of iq-set, message+, iq-result is generally limited to MAM.
Closest similar thing might be MUC join, but to really handle that you
would need the webhook callback mechanism.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Mon, 16 May 2022 19:47:09 +0200 |
parent | 3397:4cf65afd90f4 |
rev | line source |
---|---|
3397
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1 local it = require "util.iterators"; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
2 local new_id = require "util.id".medium; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
3 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
4 local max_user_devices = module:get_option_number("max_user_devices", 5); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
5 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
6 local device_store = module:open_store("devices"); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
7 local device_map_store = module:open_store("devices", "map"); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
8 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
9 --- Helper functions |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
10 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
11 local function _compare_device_timestamps(a, b) |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
12 return (a.last_activity_at or 0) < (b.last_activity_at or 0); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
13 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
14 local function sorted_devices(devices) |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
15 return it.sorted_pairs(devices, _compare_device_timestamps); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
16 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
17 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
18 local function new_device(username, alt_ids) |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
19 local current_time = os.time(); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
20 local device = { |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
21 id = "dv-"..new_id(); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
22 created_at = current_time; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
23 last_activity = "created"; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
24 last_activity_at = current_time; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
25 alt_ids = alt_ids or {}; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
26 }; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
27 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
28 local devices = device_store:get(username); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
29 if not devices then |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
30 devices = {}; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
31 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
32 devices[device.id] = device; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
33 local devices_ordered = {}; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
34 for id in sorted_devices(devices) do |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
35 table.insert(devices_ordered, id); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
36 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
37 if #devices_ordered > max_user_devices then |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
38 -- Iterate through oldest devices that are above limit, backwards |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
39 for i = #devices_ordered, max_user_devices+1, -1 do |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
40 local id = table.remove(devices_ordered, i); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
41 devices[id] = nil; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
42 module:log("debug", "Removing old device for %s: %s", username, id); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
43 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
44 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
45 device_store:set(username, devices); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
46 return device; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
47 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
48 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
49 local function get_device_with_alt_id(username, alt_id_type, alt_id) |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
50 local devices = device_store:get(username); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
51 if not devices then |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
52 return nil; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
53 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
54 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
55 for _, device in pairs(devices) do |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
56 if device.alt_ids[alt_id_type] == alt_id then |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
57 return device; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
58 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
59 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
60 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
61 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
62 local function set_device_alt_id(username, device_id, alt_id_type, alt_id) |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
63 local devices = device_store:get(username); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
64 if not devices or not devices[device_id] then |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
65 return nil, "no such device"; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
66 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
67 devices[device_id].alt_ids[alt_id_type] = alt_id; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
68 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
69 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
70 local function record_device_state(username, device_id, activity, time) |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
71 local device = device_map_store:get(username, device_id); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
72 device.last_activity = activity; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
73 device.last_activity_at = time or os.time(); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
74 device_map_store:set(username, device_id, device); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
75 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
76 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
77 local function find_device(username, info) |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
78 for _, alt_id_type in ipairs({ "resumption_token", "resource" }) do |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
79 local alt_id = info[alt_id_type]; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
80 if alt_id then |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
81 local device = get_device_with_alt_id(username, alt_id_type, alt_id); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
82 if device then |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
83 return device, alt_id_type; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
84 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
85 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
86 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
87 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
88 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
89 --- Information gathering |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
90 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
91 module:hook("pre-resource-bind", function (event) |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
92 event.session.device_requested_resource = event.resource; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
93 end, 1000); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
94 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
95 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
96 local function store_resumption_token(session, stanza) |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
97 session.device_requested_resume = stanza.attr.previd; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
98 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
99 module:hook_stanza("urn:xmpp:sm:2", "resume", store_resumption_token, 5); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
100 module:hook_stanza("urn:xmpp:sm:3", "resume", store_resumption_token, 5); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
101 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
102 --- Identify device after resource bind |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
103 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
104 module:hook("resource-bind", function (event) |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
105 local info = { |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
106 resource = event.session.device_requested_resource; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
107 resumption_token = event.session.device_requested_resume; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
108 }; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
109 local device, source = find_device(event.session.username, info); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
110 if device then |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
111 event.session.log("debug", "Associated with device %s (from %s)", device.id, source); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
112 event.session.device_id = device.id; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
113 else |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
114 device = new_device(event.session.username, info); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
115 event.session.log("debug", "Creating new device %s for session", device.id); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
116 event.session.device_id = device.id; |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
117 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
118 record_device_state(event.session.username, device.id, "login"); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
119 end, 1000); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
120 |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
121 module:hook("resource-unbind", function (event) |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
122 if event.session.device_id then |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
123 record_device_state(event.session.username, event.session.device_id, "logout"); |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
124 end |
4cf65afd90f4
mod_devices: New module for device identification
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
125 end); |