Mercurial > prosody-modules
comparison mod_muc_inject_mentions/mod_muc_inject_mentions.lua @ 4163:320f6d374b5d
mod_muc_inject_mentions: Add new configuration setting to strip out prefixes from mentions
author | Seve Ferrer <seve@delape.net> |
---|---|
date | Wed, 30 Sep 2020 13:14:46 +0200 |
parents | f7bc0e4ab4a2 |
children | a82b0745383b |
comparison
equal
deleted
inserted
replaced
4162:f7bc0e4ab4a2 | 4163:320f6d374b5d |
---|---|
1 module:depends("muc"); | 1 module:depends("muc"); |
2 | 2 |
3 local jid_resource = require "util.jid".resource; | 3 local jid_resource = require "util.jid".resource; |
4 local st = require "util.stanza"; | |
4 | 5 |
5 local prefixes = module:get_option("muc_inject_mentions_prefixes", nil) | 6 local prefixes = module:get_option("muc_inject_mentions_prefixes", nil) |
6 local suffixes = module:get_option("muc_inject_mentions_suffixes", nil) | 7 local suffixes = module:get_option("muc_inject_mentions_suffixes", nil) |
7 local enabled_rooms = module:get_option("muc_inject_mentions_enabled_rooms", nil) | 8 local enabled_rooms = module:get_option("muc_inject_mentions_enabled_rooms", nil) |
8 local disabled_rooms = module:get_option("muc_inject_mentions_disabled_rooms", nil) | 9 local disabled_rooms = module:get_option("muc_inject_mentions_disabled_rooms", nil) |
9 local mention_delimiters = module:get_option_set("muc_inject_mentions_mention_delimiters", {" ", "", "\n"}) | 10 local mention_delimiters = module:get_option_set("muc_inject_mentions_mention_delimiters", {" ", "", "\n"}) |
10 local append_mentions = module:get_option("muc_inject_mentions_append_mentions", false) | 11 local append_mentions = module:get_option("muc_inject_mentions_append_mentions", false) |
12 local strip_out_prefixes = module:get_option("muc_inject_mentions_strip_out_prefixes", false) | |
11 | 13 |
12 | 14 |
13 local reference_xmlns = "urn:xmpp:reference:0" | 15 local reference_xmlns = "urn:xmpp:reference:0" |
14 | 16 |
17 local function add_mention(mentions, bare_jid, first, last, prefix_indices, has_prefix) | |
18 if strip_out_prefixes then | |
19 if has_prefix then | |
20 table.insert(prefix_indices, first-1) | |
21 end | |
22 first = first - #prefix_indices | |
23 last = last - #prefix_indices | |
24 end | |
25 mentions[first] = {bare_jid=bare_jid, first=first, last=last} | |
26 end | |
15 | 27 |
16 local function get_client_mentions(stanza) | 28 local function get_client_mentions(stanza) |
17 local has_mentions = false | 29 local has_mentions = false |
18 local client_mentions = {} | 30 local client_mentions = {} |
19 | 31 |
56 | 68 |
57 local function has_nick_prefix(body, first) | 69 local function has_nick_prefix(body, first) |
58 -- There are no configured prefixes | 70 -- There are no configured prefixes |
59 if not prefixes or #prefixes < 1 then return false end | 71 if not prefixes or #prefixes < 1 then return false end |
60 | 72 |
61 -- Preffix must have a space before it, | 73 -- Prefix must have a space before it, |
62 -- be the first character of the body | 74 -- be the first character of the body |
63 -- or be the first character after a new line | 75 -- or be the first character after a new line |
64 if not mention_delimiters:contains(body:sub(first - 2, first - 2)) then | 76 if not mention_delimiters:contains(body:sub(first - 2, first - 2)) then |
65 return false | 77 return false |
66 end | 78 end |
67 | 79 |
68 local preffix = body:sub(first - 1, first - 1) | 80 local prefix = body:sub(first - 1, first - 1) |
69 for _, _preffix in ipairs(prefixes) do | 81 for _, _prefix in ipairs(prefixes) do |
70 if preffix == _preffix then | 82 if prefix == _prefix then |
71 return true | 83 return true |
72 end | 84 end |
73 end | 85 end |
74 | 86 |
75 return false | 87 return false |
95 | 107 |
96 return false | 108 return false |
97 end | 109 end |
98 | 110 |
99 local function search_mentions(room, body, client_mentions) | 111 local function search_mentions(room, body, client_mentions) |
100 local mentions = {} | 112 local mentions, prefix_indices = {}, {} |
101 | 113 |
102 for _, occupant in pairs(room._occupants) do | 114 for _, occupant in pairs(room._occupants) do |
103 local nick = jid_resource(occupant.nick); | 115 local nick = jid_resource(occupant.nick); |
104 -- Check for multiple mentions to the same nickname in a message | 116 -- Check for multiple mentions to the same nickname in a message |
105 -- Hey @nick remember to... Ah, also @nick please let me know if... | 117 -- Hey @nick remember to... Ah, also @nick please let me know if... |
122 if not client_mentions[first] then | 134 if not client_mentions[first] then |
123 -- Body only contains nickname or is between spaces, new lines or at the end/start of the body | 135 -- Body only contains nickname or is between spaces, new lines or at the end/start of the body |
124 if mention_delimiters:contains(body:sub(first - 1, first - 1)) and | 136 if mention_delimiters:contains(body:sub(first - 1, first - 1)) and |
125 mention_delimiters:contains(body:sub(last + 1, last + 1)) | 137 mention_delimiters:contains(body:sub(last + 1, last + 1)) |
126 then | 138 then |
127 mentions[first] = {bare_jid=bare_jid, first=first, last=last} | 139 add_mention(mentions, bare_jid, first, last, prefix_indices, false) |
128 else | 140 else |
129 -- Check if occupant is mentioned using affixes | 141 -- Check if occupant is mentioned using affixes |
130 local has_preffix = has_nick_prefix(body, first) | 142 local has_prefix = has_nick_prefix(body, first) |
131 local has_suffix = has_nick_suffix(body, last) | 143 local has_suffix = has_nick_suffix(body, last) |
132 | 144 |
133 -- @nickname: ... | 145 -- @nickname: ... |
134 if has_preffix and has_suffix then | 146 if has_prefix and has_suffix then |
135 mentions[first] = {bare_jid=bare_jid, first=first, last=last} | 147 add_mention(mentions, bare_jid, first, last, prefix_indices, has_prefix) |
136 | 148 |
137 -- @nickname ... | 149 -- @nickname ... |
138 elseif has_preffix and not has_suffix then | 150 elseif has_prefix and not has_suffix then |
139 if mention_delimiters:contains(body:sub(last + 1, last + 1)) then | 151 if mention_delimiters:contains(body:sub(last + 1, last + 1)) then |
140 mentions[first] = {bare_jid=bare_jid, first=first, last=last} | 152 add_mention(mentions, bare_jid, first, last, prefix_indices, has_prefix) |
141 end | 153 end |
142 | 154 |
143 -- nickname: ... | 155 -- nickname: ... |
144 elseif not has_preffix and has_suffix then | 156 elseif not has_prefix and has_suffix then |
145 if mention_delimiters:contains(body:sub(first - 1, first - 1)) then | 157 if mention_delimiters:contains(body:sub(first - 1, first - 1)) then |
146 mentions[first] = {bare_jid=bare_jid, first=first, last=last} | 158 add_mention(mentions, bare_jid, first, last, prefix_indices, has_prefix) |
147 end | 159 end |
148 end | 160 end |
149 end | 161 end |
150 end | 162 end |
151 end | 163 end |
152 end | 164 end |
153 | 165 |
154 return mentions | 166 return mentions, prefix_indices |
155 end | 167 end |
156 | 168 |
157 local function muc_inject_mentions(event) | 169 local function muc_inject_mentions(event) |
158 local room, stanza = event.room, event.stanza; | 170 local room, stanza = event.room, event.stanza; |
159 local body = stanza:get_child("body") | 171 local body = stanza:get_child("body") |
166 -- Only act on messages that do not include mentions | 178 -- Only act on messages that do not include mentions |
167 -- unless configuration states otherwise. | 179 -- unless configuration states otherwise. |
168 local has_mentions, client_mentions = get_client_mentions(stanza) | 180 local has_mentions, client_mentions = get_client_mentions(stanza) |
169 if has_mentions and not append_mentions then return; end | 181 if has_mentions and not append_mentions then return; end |
170 | 182 |
171 local mentions = search_mentions(room, body:get_text(), client_mentions) | 183 local body_text = body:get_text() |
184 local mentions, prefix_indices = search_mentions(room, body_text, client_mentions) | |
172 for _, mention in pairs(mentions) do | 185 for _, mention in pairs(mentions) do |
173 -- https://xmpp.org/extensions/xep-0372.html#usecase_mention | 186 -- https://xmpp.org/extensions/xep-0372.html#usecase_mention |
174 stanza:tag( | 187 stanza:tag( |
175 "reference", { | 188 "reference", { |
176 xmlns=reference_xmlns, | 189 xmlns=reference_xmlns, |
179 type="mention", | 192 type="mention", |
180 uri="xmpp:" .. mention.bare_jid, | 193 uri="xmpp:" .. mention.bare_jid, |
181 } | 194 } |
182 ):up() | 195 ):up() |
183 end | 196 end |
197 | |
198 if strip_out_prefixes then | |
199 local body_without_prefixes = "" | |
200 local from = 0 | |
201 if #prefix_indices > 0 then | |
202 for _, prefix_index in ipairs(prefix_indices) do | |
203 body_without_prefixes = body_without_prefixes .. body_text:sub(from, prefix_index-1) | |
204 from = prefix_index + 1 | |
205 end | |
206 body_without_prefixes = body_without_prefixes .. body_text:sub(from, #body_text) | |
207 | |
208 -- Replace original body containing prefixes | |
209 stanza:maptags( | |
210 function(tag) | |
211 if tag.name ~= "body" then | |
212 return tag | |
213 end | |
214 return st.stanza("body"):text(body_without_prefixes) | |
215 end | |
216 ) | |
217 end | |
218 end | |
184 end | 219 end |
185 | 220 |
186 module:hook("muc-occupant-groupchat", muc_inject_mentions) | 221 module:hook("muc-occupant-groupchat", muc_inject_mentions) |