20 end |
15 end |
21 end |
16 end |
22 end |
17 end |
23 end); |
18 end); |
24 |
19 |
25 bot.stream:hook("stanza", function (stanza) |
20 -- Re-broadcast groupchat event on the bot |
26 local room_jid = jid.bare(stanza.attr.from); |
21 local reflect_events = { "groupchat/joining"; "groupchat/joined"; "groupchat/leaving"; "groupchat/left" }; |
27 local room = bot.rooms[room_jid] |
22 for i = 1,#reflect_events do |
28 if room then |
23 bot.stream:hook(reflect_events[i], function(room, ...) |
29 local nick = select(3, jid.split(stanza.attr.from)); |
24 room.bot = bot; |
30 local body = stanza:get_child("body"); |
25 bot:event(reflect_events[i], room, ...) |
31 local delay = stanza:get_child("delay", xmlns_delay); |
26 end); |
32 local event = { |
27 end |
33 room_jid = room_jid; |
28 |
34 room = room; |
29 function bot:join_room(room_jid, nick) |
35 sender = room.occupants[nick]; |
30 nick = nick or bot.config.nick or ("bot"..math.random(10000,99999)); |
36 nick = nick; |
31 local room = bot.stream:join_room(room_jid, nick) |
37 body = (body and body:get_text()) or nil; |
32 room.bot = bot; |
38 stanza = stanza; |
33 room:hook("message", function(event) |
39 delay = (delay and delay.attr.stamp); |
34 if event.nick == room.nick then |
40 }; |
35 return true; |
41 if stanza.name == "message" then |
36 end |
42 local replied; |
37 end, 1000); |
43 local r = st.reply(stanza); |
38 room:hook("message", function(event) |
44 if stanza.attr.type == "groupchat" then |
39 local stanza = event.stanza; |
45 r.attr.type = stanza.attr.type; |
40 local replied; |
46 r.attr.to = jid.bare(stanza.attr.to); |
41 local r = st.reply(stanza); |
|
42 if stanza.attr.type == "groupchat" then |
|
43 r.attr.type = stanza.attr.type; |
|
44 r.attr.to = jid.bare(stanza.attr.to); |
|
45 end |
|
46 function event:reply(reply) |
|
47 if not reply then reply = "Nothing to say to you"; end |
|
48 if replied then return false; end |
|
49 replied = true; |
|
50 if r.attr.type == "groupchat" then |
|
51 reply = event.sender.nick..": "..reply; |
47 end |
52 end |
48 function event:reply(reply) |
53 room:send(r:tag("body"):text(reply)); |
49 if not reply then reply = "Nothing to say to you"; end |
|
50 if replied then return false; end |
|
51 replied = true; |
|
52 if r.attr.type == "groupchat" then |
|
53 reply = event.sender.nick..": "..reply; |
|
54 end |
|
55 room:send(r:tag("body"):text(reply)); |
|
56 end |
|
57 end |
54 end |
58 local ret; |
55 end, 500); |
59 if stanza.name ~= "message" or nick ~= room.nick then |
|
60 ret = room:event(stanza.name, event); |
|
61 end |
|
62 return ret or (stanza.name == "message") or nil; |
|
63 end |
|
64 end, 500); |
|
65 |
|
66 function bot:join_room(jid, nick) |
|
67 nick = nick or bot.config.nick or ("bot"..math.random(10000,99999)); |
|
68 local room = setmetatable({ |
|
69 bot = bot, jid = jid, nick = nick, |
|
70 occupants = {}, |
|
71 events = events.new() |
|
72 }, room_mt); |
|
73 self.rooms[jid] = room; |
|
74 local occupants = room.occupants; |
|
75 room:hook("presence", function (presence) |
|
76 local nick = presence.nick or nick; |
|
77 if not occupants[nick] and presence.stanza.attr.type ~= "unavailable" then |
|
78 occupants[nick] = { |
|
79 nick = nick; |
|
80 jid = presence.stanza.attr.from; |
|
81 presence = presence.stanza; |
|
82 }; |
|
83 local x = presence.stanza:get_child("x", xmlns_muc .. "#user"); |
|
84 if x then |
|
85 local x_item = x:get_child("item"); |
|
86 if x_item and x_item.attr then |
|
87 occupants[nick].real_jid = x_item.attr.jid; |
|
88 occupants[nick].affiliation = x_item.attr.affiliation; |
|
89 occupants[nick].role = x_item.attr.role; |
|
90 end |
|
91 end |
|
92 if nick == room.nick then |
|
93 room.bot:event("groupchat/joined", room); |
|
94 else |
|
95 room:event("occupant-joined", occupants[nick]); |
|
96 end |
|
97 elseif occupants[nick] and presence.stanza.attr.type == "unavailable" then |
|
98 if nick == room.nick then |
|
99 room.bot:event("groupchat/left", room); |
|
100 self.rooms[room.jid] = nil; |
|
101 else |
|
102 occupants[nick].presence = presence.stanza; |
|
103 room:event("occupant-left", occupants[nick]); |
|
104 occupants[nick] = nil; |
|
105 end |
|
106 end |
|
107 end); |
|
108 self:send(st.presence({to = jid.."/"..nick}) |
|
109 :tag("x",{xmlns = xmlns_muc}):tag("history",{maxstanzas = 0})); |
|
110 self:event("groupchat/joining", room); |
|
111 return room; |
56 return room; |
112 end |
57 end |
|
58 |
|
59 bot.stream:hook("pre-groupchat/joining", function(presence) |
|
60 local muc_x = presence:get_child("x", xmlns_muc); |
|
61 if muc_x then |
|
62 muc_x:tag("history",{maxstanzas = 0}); |
|
63 end |
|
64 end); |
113 end |
65 end |
114 |
|
115 function room_mt:send(stanza) |
|
116 if stanza.name == "message" and not stanza.attr.type then |
|
117 stanza.attr.type = "groupchat"; |
|
118 end |
|
119 if stanza.attr.type == "groupchat" or not stanza.attr.to then |
|
120 stanza.attr.to = self.jid; |
|
121 end |
|
122 self.bot:send(stanza); |
|
123 end |
|
124 |
|
125 function room_mt:send_message(text) |
|
126 self:send(st.message():tag("body"):text(text)); |
|
127 end |
|
128 |
|
129 function room_mt:leave(message) |
|
130 self.bot:event("groupchat/leaving", room); |
|
131 self:send(st.presence({type="unavailable"})); |
|
132 end |
|
133 |
|
134 function room_mt:set_role(nick, role, reason) |
|
135 self:send(st.iq({type="set"}) |
|
136 :query(xmlns_muc .. "#admin") |
|
137 :tag("item", {nick = nick, role = role}) |
|
138 :tag("reason"):text(reason or "")); |
|
139 end |
|
140 |
|
141 function room_mt:set_affiliation(nick, affiliation, reason) |
|
142 self:send(st.iq({type="set"}) |
|
143 :query(xmlns_muc .. "#admin") |
|
144 :tag("item", {nick = nick, affiliation = affiliation}) |
|
145 :tag("reason"):text(reason or "")); |
|
146 end |
|
147 |
|
148 function room_mt:event(name, arg) |
|
149 self.bot.stream:debug("Firing room event: %s", name); |
|
150 return self.events.fire_event(name, arg); |
|
151 end |
|
152 |
|
153 function room_mt:hook(name, callback, priority) |
|
154 return self.events.add_handler(name, callback, priority); |
|
155 end |
|