Software / code / prosody-modules
Comparison
mod_vjud/mod_vjud.lua @ 753:9d5731af2c27
Merge with Oliver Gerlich
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Fri, 27 Jul 2012 14:29:59 +0100 |
| parent | 742:da8f561d79b4 |
| child | 787:cec49ee88c23 |
comparison
equal
deleted
inserted
replaced
| 752:9bbd99f2057a | 753:9d5731af2c27 |
|---|---|
| 1 local dm_load = require "util.datamanager".load; | |
| 2 local dm_store = require "util.datamanager".store; | |
| 3 | |
| 4 local usermanager = require "core.usermanager"; | |
| 5 local dataforms_new = require "util.dataforms".new; | |
| 6 local jid_split = require "util.jid".prepped_split; | |
| 7 local vcard = module:require "vcard"; | |
| 8 local rawget, rawset = rawget, rawset; | |
| 9 | |
| 10 local st = require "util.stanza"; | |
| 11 local template = require "util.template"; | |
| 12 | |
| 13 local get_reply = template[[ | |
| 14 <query xmlns="jabber:iq:search"> | |
| 15 <instructions>Fill in one or more fields to search for any matching Jabber users.</instructions> | |
| 16 <first/> | |
| 17 <last/> | |
| 18 <nick/> | |
| 19 <email/> | |
| 20 </query> | |
| 21 ]].apply({}); | |
| 22 local item_template = template[[ | |
| 23 <item xmlns="jabber:iq:search" jid="{jid}"> | |
| 24 <first>{first}</first> | |
| 25 <last>{last}</last> | |
| 26 <nick>{nick}</nick> | |
| 27 <email>{email}</email> | |
| 28 </item> | |
| 29 ]]; | |
| 30 | |
| 31 module:add_feature("jabber:iq:search"); | |
| 32 | |
| 33 local opted_in; | |
| 34 function module.load() | |
| 35 opted_in = dm_load(nil, module.host, "user_index") or {}; | |
| 36 end | |
| 37 function module.unload() | |
| 38 dm_store(nil, module.host, "user_index", opted_in); | |
| 39 end | |
| 40 | |
| 41 local opt_in_layout = dataforms_new{ | |
| 42 title = "Search settings"; | |
| 43 instructions = "Do you want to appear in search results?"; | |
| 44 { | |
| 45 name = "searchable", | |
| 46 label = "Appear in search results?", | |
| 47 type = "boolean", | |
| 48 }, | |
| 49 }; | |
| 50 local vCard_mt = { | |
| 51 __index = function(t, k) | |
| 52 if type(k) ~= "string" then return nil end | |
| 53 for i=1,#t do | |
| 54 local t_i = rawget(t, i); | |
| 55 if t_i and t_i.name == k then | |
| 56 rawset(t, k, t_i); | |
| 57 return t_i; | |
| 58 end | |
| 59 end | |
| 60 end | |
| 61 }; | |
| 62 | |
| 63 local function get_user_vcard(user) | |
| 64 local vCard = dm_load(user, module.host, "vcard"); | |
| 65 if vCard then | |
| 66 vCard = st.deserialize(vCard); | |
| 67 vCard = vcard.from_xep54(vCard); | |
| 68 return setmetatable(vCard, vCard_mt); | |
| 69 end | |
| 70 end | |
| 71 | |
| 72 local at_host = "@"..module.host; | |
| 73 | |
| 74 module:hook("iq/host/jabber:iq:search:query", function(event) | |
| 75 local origin, stanza = event.origin, event.stanza; | |
| 76 | |
| 77 if stanza.attr.type == "get" then | |
| 78 origin.send(st.reply(stanza):add_child(get_reply)); | |
| 79 else -- type == "set" | |
| 80 local query = stanza.tags[1]; | |
| 81 local first, last, nick, email = | |
| 82 (query:get_child_text"first" or false), | |
| 83 (query:get_child_text"last" or false), | |
| 84 (query:get_child_text"nick" or false), | |
| 85 (query:get_child_text"email" or false); | |
| 86 | |
| 87 if not ( first or last or nick or email ) then | |
| 88 origin.send(st.error_reply(stanza, "modify", "not-acceptable", "All fields were empty")); | |
| 89 return true; | |
| 90 end | |
| 91 | |
| 92 local reply = st.reply(stanza):query("jabber:iq:search"); | |
| 93 | |
| 94 local username, hostname = jid_split(email); | |
| 95 if hostname == module.host and username and usermanager.user_exists(username, hostname) then | |
| 96 local vCard = get_user_vcard(username); | |
| 97 if vCard then | |
| 98 reply:add_child(item_template.apply{ | |
| 99 jid = username..at_host; | |
| 100 first = vCard.N and vCard.N[2] or nil; | |
| 101 last = vCard.N and vCard.N[1] or nil; | |
| 102 nick = vCard.NICKNAME and vCard.NICKNAME[1] or username; | |
| 103 email = vCard.EMAIL and vCard.EMAIL[1] or nil; | |
| 104 }); | |
| 105 end | |
| 106 else | |
| 107 for username in pairs(opted_in) do | |
| 108 local vCard = get_user_vcard(username); | |
| 109 if vCard and ( | |
| 110 (vCard.N and vCard.N[2] == first) or | |
| 111 (vCard.N and vCard.N[1] == last) or | |
| 112 (vCard.NICKNAME and vCard.NICKNAME[1] == nick) or | |
| 113 (vCard.EMAIL and vCard.EMAIL[1] == email)) then | |
| 114 reply:add_child(item_template.apply{ | |
| 115 jid = username..at_host; | |
| 116 first = vCard.N and vCard.N[2] or nil; | |
| 117 last = vCard.N and vCard.N[1] or nil; | |
| 118 nick = vCard.NICKNAME and vCard.NICKNAME[1] or username; | |
| 119 email = vCard.EMAIL and vCard.EMAIL[1] or nil; | |
| 120 }); | |
| 121 end | |
| 122 end | |
| 123 end | |
| 124 origin.send(reply); | |
| 125 end | |
| 126 return true; | |
| 127 end); | |
| 128 | |
| 129 local function opt_in_handler(self, data, state) | |
| 130 local username, hostname = jid_split(data.from); | |
| 131 if state then -- the second return value | |
| 132 if data.action == "cancel" then | |
| 133 return { status = "canceled" }; | |
| 134 end | |
| 135 | |
| 136 if not username or not hostname or hostname ~= module.host then | |
| 137 return { status = "error", error = { type = "cancel", | |
| 138 condition = "forbidden", message = "Invalid user or hostname." } }; | |
| 139 end | |
| 140 | |
| 141 local fields = opt_in_layout:data(data.form); | |
| 142 opted_in[username] = fields.searchable or nil | |
| 143 | |
| 144 return { status = "completed" } | |
| 145 else -- No state, send the form. | |
| 146 return { status = "executing", actions = { "complete" }, | |
| 147 form = { layout = opt_in_layout, data = { searchable = opted_in[username] } } }, true; | |
| 148 end | |
| 149 end | |
| 150 | |
| 151 local adhoc_new = module:require "adhoc".new; | |
| 152 local adhoc_vjudsetup = adhoc_new("Search settings", "vjudsetup", opt_in_handler);--, "self");-- and nil); | |
| 153 module:depends"adhoc"; | |
| 154 module:provides("adhoc", adhoc_vjudsetup); | |
| 155 |