Sat, 13 Nov 2010 21:27:01 +0100
plugins.groupchat: Keep track of real jid, affiliation and role.
0 | 1 | local events = require "events"; |
2 | local st = require "util.stanza"; | |
3 | ||
4 | local room_mt = {}; | |
5 | room_mt.__index = room_mt; | |
6 | ||
7 | local xmlns_delay = "urn:xmpp:delay"; | |
36
ccce42f781de
plugins.groupchat: Request zero history
Kim Alvefur <zash@zash.se>
parents:
31
diff
changeset
|
8 | local xmlns_muc = "http://jabber.org/protocol/muc"; |
0 | 9 | |
10 | function riddim.plugins.groupchat(bot) | |
11 | bot.rooms = {}; | |
14
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
12 | |
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
13 | bot:hook("started", function () |
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
14 | for k, v in pairs(bot.config.autojoin or {}) do |
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
15 | if type(k) == "number" then |
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
16 | bot:join_room(v); |
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
17 | elseif type(k) == "string" then |
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
18 | if type(v) == "string" then |
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
19 | bot:join_room(k, v); |
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
20 | end |
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
21 | end |
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
22 | end |
3df63aaba9e3
Decouple plugins from base implementation (in particular no plugins are now loaded by default)
Chris <jugg@hotmail.com>
parents:
9
diff
changeset
|
23 | end); |
0 | 24 | |
25 | bot.stream:hook("stanza", function (stanza) | |
26 | local room_jid = jid.bare(stanza.attr.from); | |
27 | local room = bot.rooms[room_jid] | |
28 | if room then | |
29 | local nick = select(3, jid.split(stanza.attr.from)); | |
30 | local body = stanza:get_child("body"); | |
31 | local delay = stanza:get_child("delay", xmlns_delay); | |
32 | local event = { | |
16
ae69cea97598
Formatting, indentation and cleanup
Chris <jugg@hotmail.com>
parents:
14
diff
changeset
|
33 | room_jid = room_jid; |
ae69cea97598
Formatting, indentation and cleanup
Chris <jugg@hotmail.com>
parents:
14
diff
changeset
|
34 | room = room; |
ae69cea97598
Formatting, indentation and cleanup
Chris <jugg@hotmail.com>
parents:
14
diff
changeset
|
35 | sender = room.occupants[nick]; |
ae69cea97598
Formatting, indentation and cleanup
Chris <jugg@hotmail.com>
parents:
14
diff
changeset
|
36 | nick = nick; |
ae69cea97598
Formatting, indentation and cleanup
Chris <jugg@hotmail.com>
parents:
14
diff
changeset
|
37 | body = (body and body:get_text()) or nil; |
ae69cea97598
Formatting, indentation and cleanup
Chris <jugg@hotmail.com>
parents:
14
diff
changeset
|
38 | stanza = stanza; |
ae69cea97598
Formatting, indentation and cleanup
Chris <jugg@hotmail.com>
parents:
14
diff
changeset
|
39 | delay = (delay and delay.attr.stamp); |
ae69cea97598
Formatting, indentation and cleanup
Chris <jugg@hotmail.com>
parents:
14
diff
changeset
|
40 | }; |
0 | 41 | if stanza.name == "message" then |
42 | local replied; | |
43 | local r = st.reply(stanza); | |
44 | if stanza.attr.type == "groupchat" then | |
45 | r.attr.type = stanza.attr.type; | |
46 | r.attr.to = jid.bare(stanza.attr.to); | |
47 | end | |
48 | function event:reply(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 | |
58 | local ret; | |
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 = {}, | |
16
ae69cea97598
Formatting, indentation and cleanup
Chris <jugg@hotmail.com>
parents:
14
diff
changeset
|
71 | events = events.new() |
ae69cea97598
Formatting, indentation and cleanup
Chris <jugg@hotmail.com>
parents:
14
diff
changeset
|
72 | }, room_mt); |
0 | 73 | self.rooms[jid] = room; |
74 | local occupants = room.occupants; | |
75 | room:hook("presence", function (presence) | |
31
0cafbe17c0aa
plugins.groupchat: Assume our own nick when receiving presence from the room's bare JID
Matthew Wild <mwild1@gmail.com>
parents:
16
diff
changeset
|
76 | local nick = presence.nick or nick; |
9
8c3bec93087b
groupchat.lua: make the occupant-left event work
Thilo Cestonaro <thilo@cestona.ro>
parents:
0
diff
changeset
|
77 | if not occupants[nick] and presence.stanza.attr.type ~= "unavailable" then |
8c3bec93087b
groupchat.lua: make the occupant-left event work
Thilo Cestonaro <thilo@cestona.ro>
parents:
0
diff
changeset
|
78 | occupants[nick] = { |
8c3bec93087b
groupchat.lua: make the occupant-left event work
Thilo Cestonaro <thilo@cestona.ro>
parents:
0
diff
changeset
|
79 | nick = nick; |
8c3bec93087b
groupchat.lua: make the occupant-left event work
Thilo Cestonaro <thilo@cestona.ro>
parents:
0
diff
changeset
|
80 | jid = presence.stanza.attr.from; |
8c3bec93087b
groupchat.lua: make the occupant-left event work
Thilo Cestonaro <thilo@cestona.ro>
parents:
0
diff
changeset
|
81 | presence = presence.stanza; |
16
ae69cea97598
Formatting, indentation and cleanup
Chris <jugg@hotmail.com>
parents:
14
diff
changeset
|
82 | }; |
46
1f0fa4af29b8
plugins.groupchat: Keep track of real jid, affiliation and role.
Kim Alvefur <zash@zash.se>
parents:
45
diff
changeset
|
83 | local x = presence.stanza:get_child("x", xmlns_muc .. "#user"); |
1f0fa4af29b8
plugins.groupchat: Keep track of real jid, affiliation and role.
Kim Alvefur <zash@zash.se>
parents:
45
diff
changeset
|
84 | if x then |
1f0fa4af29b8
plugins.groupchat: Keep track of real jid, affiliation and role.
Kim Alvefur <zash@zash.se>
parents:
45
diff
changeset
|
85 | local x_item = x:get_child("item"); |
1f0fa4af29b8
plugins.groupchat: Keep track of real jid, affiliation and role.
Kim Alvefur <zash@zash.se>
parents:
45
diff
changeset
|
86 | if x_item and x_item.attr then |
1f0fa4af29b8
plugins.groupchat: Keep track of real jid, affiliation and role.
Kim Alvefur <zash@zash.se>
parents:
45
diff
changeset
|
87 | occupants[nick].real_jid = x_item.attr.jid; |
1f0fa4af29b8
plugins.groupchat: Keep track of real jid, affiliation and role.
Kim Alvefur <zash@zash.se>
parents:
45
diff
changeset
|
88 | occupants[nick].affiliation = x_item.attr.affiliation; |
1f0fa4af29b8
plugins.groupchat: Keep track of real jid, affiliation and role.
Kim Alvefur <zash@zash.se>
parents:
45
diff
changeset
|
89 | occupants[nick].role = x_item.attr.role; |
1f0fa4af29b8
plugins.groupchat: Keep track of real jid, affiliation and role.
Kim Alvefur <zash@zash.se>
parents:
45
diff
changeset
|
90 | end |
1f0fa4af29b8
plugins.groupchat: Keep track of real jid, affiliation and role.
Kim Alvefur <zash@zash.se>
parents:
45
diff
changeset
|
91 | end |
9
8c3bec93087b
groupchat.lua: make the occupant-left event work
Thilo Cestonaro <thilo@cestona.ro>
parents:
0
diff
changeset
|
92 | if nick == room.nick then |
8c3bec93087b
groupchat.lua: make the occupant-left event work
Thilo Cestonaro <thilo@cestona.ro>
parents:
0
diff
changeset
|
93 | room.bot:event("groupchat/joined", room); |
0 | 94 | else |
9
8c3bec93087b
groupchat.lua: make the occupant-left event work
Thilo Cestonaro <thilo@cestona.ro>
parents:
0
diff
changeset
|
95 | room:event("occupant-joined", occupants[nick]); |
0 | 96 | end |
9
8c3bec93087b
groupchat.lua: make the occupant-left event work
Thilo Cestonaro <thilo@cestona.ro>
parents:
0
diff
changeset
|
97 | elseif occupants[nick] and presence.stanza.attr.type == "unavailable" then |
42
5ee2eccabcc9
plugins.groupchat: Cleanup properly when leaving a room, even if kicked.
Kim Alvefur <zash@zash.se>
parents:
36
diff
changeset
|
98 | if nick == room.nick then |
5ee2eccabcc9
plugins.groupchat: Cleanup properly when leaving a room, even if kicked.
Kim Alvefur <zash@zash.se>
parents:
36
diff
changeset
|
99 | room.bot:event("groupchat/left", room); |
5ee2eccabcc9
plugins.groupchat: Cleanup properly when leaving a room, even if kicked.
Kim Alvefur <zash@zash.se>
parents:
36
diff
changeset
|
100 | self.rooms[room.jid] = nil; |
5ee2eccabcc9
plugins.groupchat: Cleanup properly when leaving a room, even if kicked.
Kim Alvefur <zash@zash.se>
parents:
36
diff
changeset
|
101 | else |
5ee2eccabcc9
plugins.groupchat: Cleanup properly when leaving a room, even if kicked.
Kim Alvefur <zash@zash.se>
parents:
36
diff
changeset
|
102 | occupants[nick].presence = presence.stanza; |
5ee2eccabcc9
plugins.groupchat: Cleanup properly when leaving a room, even if kicked.
Kim Alvefur <zash@zash.se>
parents:
36
diff
changeset
|
103 | room:event("occupant-left", occupants[nick]); |
5ee2eccabcc9
plugins.groupchat: Cleanup properly when leaving a room, even if kicked.
Kim Alvefur <zash@zash.se>
parents:
36
diff
changeset
|
104 | occupants[nick] = nil; |
5ee2eccabcc9
plugins.groupchat: Cleanup properly when leaving a room, even if kicked.
Kim Alvefur <zash@zash.se>
parents:
36
diff
changeset
|
105 | end |
0 | 106 | end |
107 | end); | |
36
ccce42f781de
plugins.groupchat: Request zero history
Kim Alvefur <zash@zash.se>
parents:
31
diff
changeset
|
108 | self:send(st.presence({to = jid.."/"..nick}) |
ccce42f781de
plugins.groupchat: Request zero history
Kim Alvefur <zash@zash.se>
parents:
31
diff
changeset
|
109 | :tag("x",{xmlns = xmlns_muc}):tag("history",{maxstanzas = 0})); |
0 | 110 | self:event("groupchat/joining", room); |
111 | return room; | |
112 | end | |
113 | 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 | |
44
8e508f08cc7f
plugins.groupchat: Set a to attribute on stanzas to rooms if there isn't one
Kim Alvefur <zash@zash.se>
parents:
42
diff
changeset
|
119 | if stanza.attr.type == "groupchat" or not stanza.attr.to then |
0 | 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 | ||
45
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
134 | function room_mt:set_role(nick, role, reason) |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
135 | self:send(st.iq({type="set"}) |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
136 | :query(xmlns_muc .. "#admin") |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
137 | :tag("item", {nick = nick, role = role}) |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
138 | :tag("reason"):text(reason or "")); |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
139 | end |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
140 | |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
141 | function room_mt:set_affiliation(nick, affiliation, reason) |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
142 | self:send(st.iq({type="set"}) |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
143 | :query(xmlns_muc .. "#admin") |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
144 | :tag("item", {nick = nick, affiliation = affiliation}) |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
145 | :tag("reason"):text(reason or "")); |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
146 | end |
aa797b0a98e7
plugins.groupchat: Add methods for changing affiliation and role
Kim Alvefur <zash@zash.se>
parents:
44
diff
changeset
|
147 | |
0 | 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 |