Mercurial > prosody-modules
comparison mod_vjud/mod_vjud.lua @ 927:a9dfa7232d88
Merge
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Tue, 12 Mar 2013 12:10:25 +0000 |
| parents | 4939788a47ea |
| children | b1a92a87309c |
comparison
equal
deleted
inserted
replaced
| 926:f88381a39c56 | 927:a9dfa7232d88 |
|---|---|
| 4 local usermanager = require "core.usermanager"; | 4 local usermanager = require "core.usermanager"; |
| 5 local dataforms_new = require "util.dataforms".new; | 5 local dataforms_new = require "util.dataforms".new; |
| 6 local jid_split = require "util.jid".prepped_split; | 6 local jid_split = require "util.jid".prepped_split; |
| 7 local vcard = module:require "vcard"; | 7 local vcard = module:require "vcard"; |
| 8 local rawget, rawset = rawget, rawset; | 8 local rawget, rawset = rawget, rawset; |
| 9 local s_lower = string.lower; | |
| 10 local s_find = string.find; | |
| 9 | 11 |
| 10 local st = require "util.stanza"; | 12 local st = require "util.stanza"; |
| 11 local template = require "util.template"; | 13 local template = require "util.template"; |
| 12 | 14 |
| 13 local get_reply = template[[ | 15 local get_reply = template[[ |
| 26 <nick>{nick}</nick> | 28 <nick>{nick}</nick> |
| 27 <email>{email}</email> | 29 <email>{email}</email> |
| 28 </item> | 30 </item> |
| 29 ]]; | 31 ]]; |
| 30 | 32 |
| 33 local search_mode = module:get_option_string("vjud_mode", "opt-in"); | |
| 34 local allow_remote = module:get_option_boolean("allow_remote_searches", search_mode ~= "all"); | |
| 31 local base_host = module:get_option_string("vjud_search_domain", | 35 local base_host = module:get_option_string("vjud_search_domain", |
| 32 module:get_host_type() == "component" | 36 module:get_host_type() == "component" |
| 33 and module.host:gsub("^[^.]+%.","") | 37 and module.host:gsub("^[^.]+%.","") |
| 34 or module.host); | 38 or module.host); |
| 35 | 39 |
| 36 module:depends"disco"; | 40 module:depends"disco"; |
| 37 module:add_feature("jabber:iq:search"); | 41 module:add_feature("jabber:iq:search"); |
| 38 | 42 |
| 39 local opted_in; | |
| 40 function module.load() | |
| 41 opted_in = dm_load(nil, module.host, "user_index") or {}; | |
| 42 end | |
| 43 function module.unload() | |
| 44 dm_store(nil, module.host, "user_index", opted_in); | |
| 45 end | |
| 46 | |
| 47 local opt_in_layout = dataforms_new{ | |
| 48 title = "Search settings"; | |
| 49 instructions = "Do you want to appear in search results?"; | |
| 50 { | |
| 51 name = "searchable", | |
| 52 label = "Appear in search results?", | |
| 53 type = "boolean", | |
| 54 }, | |
| 55 }; | |
| 56 local vCard_mt = { | 43 local vCard_mt = { |
| 57 __index = function(t, k) | 44 __index = function(t, k) |
| 58 if type(k) ~= "string" then return nil end | 45 if type(k) ~= "string" then return nil end |
| 59 for i=1,#t do | 46 for i=1,#t do |
| 60 local t_i = rawget(t, i); | 47 local t_i = rawget(t, i); |
| 75 end | 62 end |
| 76 end | 63 end |
| 77 | 64 |
| 78 local at_host = "@"..base_host; | 65 local at_host = "@"..base_host; |
| 79 | 66 |
| 67 local users; -- The user iterator | |
| 68 | |
| 80 module:hook("iq/host/jabber:iq:search:query", function(event) | 69 module:hook("iq/host/jabber:iq:search:query", function(event) |
| 81 local origin, stanza = event.origin, event.stanza; | 70 local origin, stanza = event.origin, event.stanza; |
| 71 | |
| 72 if not (allow_remote or origin.type == "c2s") then | |
| 73 origin.send(st.error_reply(stanza, "cancel", "not-allowed")) | |
| 74 return true; | |
| 75 end | |
| 82 | 76 |
| 83 if stanza.attr.type == "get" then | 77 if stanza.attr.type == "get" then |
| 84 origin.send(st.reply(stanza):add_child(get_reply)); | 78 origin.send(st.reply(stanza):add_child(get_reply)); |
| 85 else -- type == "set" | 79 else -- type == "set" |
| 86 local query = stanza.tags[1]; | 80 local query = stanza.tags[1]; |
| 87 local first, last, nick, email = | 81 local first, last, nick, email = |
| 88 (query:get_child_text"first" or false), | 82 s_lower(query:get_child_text"first" or ""), |
| 89 (query:get_child_text"last" or false), | 83 s_lower(query:get_child_text"last" or ""), |
| 90 (query:get_child_text"nick" or false), | 84 s_lower(query:get_child_text"nick" or ""), |
| 91 (query:get_child_text"email" or false); | 85 s_lower(query:get_child_text"email" or ""); |
| 92 | 86 |
| 87 first = #first >= 2 and first; | |
| 88 last = #last >= 2 and last; | |
| 89 nick = #nick >= 2 and nick; | |
| 90 email = #email >= 2 and email; | |
| 93 if not ( first or last or nick or email ) then | 91 if not ( first or last or nick or email ) then |
| 94 origin.send(st.error_reply(stanza, "modify", "not-acceptable", "All fields were empty")); | 92 origin.send(st.error_reply(stanza, "modify", "not-acceptable", "All fields were empty or too short")); |
| 95 return true; | 93 return true; |
| 96 end | 94 end |
| 97 | 95 |
| 98 local reply = st.reply(stanza):query("jabber:iq:search"); | 96 local reply = st.reply(stanza):query("jabber:iq:search"); |
| 99 | 97 |
| 108 nick = vCard.NICKNAME and vCard.NICKNAME[1] or username; | 106 nick = vCard.NICKNAME and vCard.NICKNAME[1] or username; |
| 109 email = vCard.EMAIL and vCard.EMAIL[1] or nil; | 107 email = vCard.EMAIL and vCard.EMAIL[1] or nil; |
| 110 }); | 108 }); |
| 111 end | 109 end |
| 112 else | 110 else |
| 113 for username in pairs(opted_in) do | 111 for username in users() do |
| 114 local vCard = get_user_vcard(username); | 112 local vCard = get_user_vcard(username); |
| 115 if vCard and ( | 113 if vCard |
| 116 (vCard.N and vCard.N[2] == first) or | 114 and ((first and vCard.N and s_find(s_lower(vCard.N[2]), first, nil, true)) |
| 117 (vCard.N and vCard.N[1] == last) or | 115 or (last and vCard.N and s_find(s_lower(vCard.N[1]), last, nil, true)) |
| 118 (vCard.NICKNAME and vCard.NICKNAME[1] == nick) or | 116 or (nick and vCard.NICKNAME and s_find(s_lower(vCard.NICKNAME[1]), nick, nil, true)) |
| 119 (vCard.EMAIL and vCard.EMAIL[1] == email)) then | 117 or (email and vCard.EMAIL and s_find(s_lower(vCard.EMAIL[1]), email, nil, true))) then |
| 120 reply:add_child(item_template.apply{ | 118 reply:add_child(item_template.apply{ |
| 121 jid = username..at_host; | 119 jid = username..at_host; |
| 122 first = vCard.N and vCard.N[2] or nil; | 120 first = vCard.N and vCard.N[2] or nil; |
| 123 last = vCard.N and vCard.N[1] or nil; | 121 last = vCard.N and vCard.N[1] or nil; |
| 124 nick = vCard.NICKNAME and vCard.NICKNAME[1] or username; | 122 nick = vCard.NICKNAME and vCard.NICKNAME[1] or username; |
| 130 origin.send(reply); | 128 origin.send(reply); |
| 131 end | 129 end |
| 132 return true; | 130 return true; |
| 133 end); | 131 end); |
| 134 | 132 |
| 135 local function opt_in_handler(self, data, state) | 133 if search_mode == "all" then |
| 136 local username, hostname = jid_split(data.from); | 134 function users() |
| 137 if state then -- the second return value | 135 return usermanager.users(base_host); |
| 138 if data.action == "cancel" then | 136 end |
| 139 return { status = "canceled" }; | 137 else -- if "opt-in", default |
| 138 local opted_in; | |
| 139 function module.load() | |
| 140 opted_in = dm_load(nil, module.host, "user_index") or {}; | |
| 141 end | |
| 142 function module.unload() | |
| 143 dm_store(nil, module.host, "user_index", opted_in); | |
| 144 end | |
| 145 function users() | |
| 146 return pairs(opted_in); | |
| 147 end | |
| 148 local opt_in_layout = dataforms_new{ | |
| 149 title = "Search settings"; | |
| 150 instructions = "Do you want to appear in search results?"; | |
| 151 { | |
| 152 name = "searchable", | |
| 153 label = "Appear in search results?", | |
| 154 type = "boolean", | |
| 155 }, | |
| 156 }; | |
| 157 local function opt_in_handler(self, data, state) | |
| 158 local username, hostname = jid_split(data.from); | |
| 159 if state then -- the second return value | |
| 160 if data.action == "cancel" then | |
| 161 return { status = "canceled" }; | |
| 162 end | |
| 163 | |
| 164 if not username or not hostname or hostname ~= base_host then | |
| 165 return { status = "error", error = { type = "cancel", | |
| 166 condition = "forbidden", message = "Invalid user or hostname." } }; | |
| 167 end | |
| 168 | |
| 169 local fields = opt_in_layout:data(data.form); | |
| 170 opted_in[username] = fields.searchable or nil | |
| 171 | |
| 172 return { status = "completed" } | |
| 173 else -- No state, send the form. | |
| 174 return { status = "executing", actions = { "complete" }, | |
| 175 form = { layout = opt_in_layout, values = { searchable = opted_in[username] } } }, true; | |
| 140 end | 176 end |
| 177 end | |
| 141 | 178 |
| 142 if not username or not hostname or hostname ~= base_host then | 179 local adhoc_new = module:require "adhoc".new; |
| 143 return { status = "error", error = { type = "cancel", | 180 local adhoc_vjudsetup = adhoc_new("Search settings", "vjudsetup", opt_in_handler);--, "self");-- and nil); |
| 144 condition = "forbidden", message = "Invalid user or hostname." } }; | 181 module:depends"adhoc"; |
| 145 end | 182 module:provides("adhoc", adhoc_vjudsetup); |
| 146 | 183 |
| 147 local fields = opt_in_layout:data(data.form); | |
| 148 opted_in[username] = fields.searchable or nil | |
| 149 | |
| 150 return { status = "completed" } | |
| 151 else -- No state, send the form. | |
| 152 return { status = "executing", actions = { "complete" }, | |
| 153 form = { layout = opt_in_layout, values = { searchable = opted_in[username] } } }, true; | |
| 154 end | |
| 155 end | 184 end |
| 156 | |
| 157 local adhoc_new = module:require "adhoc".new; | |
| 158 local adhoc_vjudsetup = adhoc_new("Search settings", "vjudsetup", opt_in_handler);--, "self");-- and nil); | |
| 159 module:depends"adhoc"; | |
| 160 module:provides("adhoc", adhoc_vjudsetup); | |
| 161 |
