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