muc.lua

1
--[[ Lua XMPP MOO Component by Matthew Wild (MattJ)					]]
2
 
3
BotName = "Component";
4
BotPass = "";
5
 
6
function onPresence(msg)
7
	success, message = pcall(handlePresence, msg);
8
	if not success then print("\nERROR: "..message.."\n"); end
9
end
10
 
11
function onConnect()
12
end
13
 
14
function onMessage(msg)
15
	success, message = pcall(handleMessage, msg);
16
	if not success then print("\nERROR: "..message.."\n"); end
17
end
18
 
19
 
20
function handlePresence(msg)
21
	local room, server, nick, id, person;
22
	room,server,nick = msg.to:match("^(.+)@(.+)/(.+)$");
23
	if not (room and nick) then print("\nERROR: Invalid room or nick!\n"); return; end -- We need to send an error
24
	-- print("Type: "..msg.type.." type of type: "..type(msg.type),"\n");
25
	if msg.type == "available" or msg.type == "" and not people[msg.fromFull] then
26
		print("\nRecieved Available presence to join a room\n");
27
		people[msg.fromFull] = { ["nick"] = nick, ["jid"] = msg.fromFull, ["presence"] = msg.type, room = rooms[room], occjid = msg.to, _parent = occupant, group = {}, _contents = { ["in"] = createcontainertable(); } }
28
		MoveToRoom(people[msg.fromFull], room);
29
		-- rooms[room].people[nick] = people[msg.fromFull];
30
		--for id, person in pairs(rooms[room].people) do
31
		--	SendPresence(msg.fromFull, person.presence, "", room.."@"..server.."/"..person.nick);
32
		--end
33
	elseif msg.type == "unavailable" then
34
		RemoveFromRoom(rooms[room], msg.fromFull);
35
		people[msg.fromFull] = nil;
36
	end
37
	print("Returning\n");
38
	SendPresence(msg.fromFull, msg.type, "", msg.to);
39
end
40
 
41
 
42
 
43
function handleMessage(msg)
44
	local action, object, room, server, person;
45
	person = people[msg.fromFull]
46
	if msg.type == MSG_ERROR then print("ERROR MESSAGE from "..msg.fromFull..": ", msg.body); return nil; end
47
	if not person then print("No such person as "..msg.fromFull, tostring(people[msg.fromFull]).."\n"); 
48
	for k,v in pairs(people) do print(string.format("people[\"%s\"]", k),", "); end return nil; end
49
	room, server = msg.to:match("^(.+)@(.+)$");
50
	if not (room and server) then print("ERROR! Malformed JID? "..msg.to.."\n"); return nil; end --TODO: Reply with error
51
	server = server:lower();
52
	if not rooms[room] then return; end -- TODO: Reply with error
53
	
54
	person:_processCommand(msg.body);
55
 
56
	return nil;
57
end
58
 
59
function BroadcastPresence(people, fromnick, ptype, text)
60
	local nick, t;
61
	if type(people) == "string" then if not rooms[people] then print("No room called '"..people.."'","\n"); return; else print("\nLooking up room: "..people, "\n"); people = rooms[people].people; end end
62
	if not people then print("No such room. \n"); return; end
63
	for nick, t in pairs(people) do
64
		if t and t.jid then 
65
			SendPresence(t.jid, ptype or "available", text or "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..fromnick);
66
		else print("\nOrphaned occupant: "..nick, "\n");
67
		end
68
	end
69
end
70
 
71
function BroadcastMessage(people_, from, text, mtype, sender_sees)
72
	local nick, t
73
	for nick, t in pairs(people_) do
74
		print("\nMessage sent to: "..t.jid);
75
		if t.nick ~= from or sender_sees ~= false then 
76
			SendMessage(t.jid, GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..from, text or "", mtype or "groupchat");
77
		end
78
	end
79
	print("\nDone\n");
80
end
81
 
82
function GetOccupantNick(jid)
83
	local pjid, p
84
	for pjid, p in pairs(people) do
85
		if CompareJIDs(pjid, jid) then return p.nick; end
86
	end
87
	return "Somebody";
88
end
89
 
90
function CompareJIDs(j1, j2)
91
	if not (j1 and j2) then return false; end
92
	print("j2: "..type(j2));
93
	j1node, j1server, j1res = j1:match("^(.+)@([%a%.]+)/?(.*)$");
94
	j2node, j2server, j2res = j2:match("^(.+)@([%a%.]+)/?(.*)$");
95
	if j1node == j2node and j1server:lower() == j2server:lower() and (j1res == j2res or j1res == "" or j2res == "") then return true; end
96
	return false;
97
end
98
 
99
function MoveToRoom(person, room)
100
	if not ( person and room) then return; end
101
		
102
	if type(room) ~= "table" then
103
		if not rooms[room] then rooms[room] = CreateObject(classes.obj_room); rooms[room]:_create{ room = room, server = GetJIDParts(person.occjid).server}; end
104
		 room = rooms[room];
105
	end
106
	
107
	if person.room ~= room then
108
		if person.room then
109
			-- Tell everyone in room that user is leaving
110
			--BroadcastPresence(person.room.people, person.occjid, "unavailable");
111
			for nick, t in pairs(person.room.people) do
112
				-- print(string.format("\nPRESENCE: to: %s, from: %s, type: %s\n", t.jid, ));
113
				if nick ~= person.nick then
114
					SendPresence(t.jid, "unavailable", "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..person.nick);
115
				end
116
			end
117
			-- Tell user that everyone else in the room has gone (clear room roster in their client)
118
			for nick, t in pairs(person.room.people) do
119
				if person.nick ~= nick then
120
					SendPresence(person.jid, "unavailable", "", GetJIDParts(person.occjid).node.."@"..person.room._properties.server.."/"..t.nick);
121
				end
122
			end
123
			person.room.people[person.nick] = nil; -- Remove from room
124
		end
125
	end
126
	person.room = room;
127
	room.people[person.nick] = person;
128
	--Tell user about people in the new room
129
	for nick, t in pairs(person.room.people) do
130
		-- print(string.format("\nPRESENCE: to: %s, from: %s, type: %s\n", t.jid, ));
131
		if nick ~= person.nick then
132
			SendPresence(person.jid, "available", "", GetJIDParts(person.occjid).node.."@"..GetJIDParts(person.occjid).server.."/"..nick);
133
		end
134
	end
135
	--Tell people in new room that user has joined
136
	-- BroadcastPresence(person.room.people, person.nick, "available");
137
	for nick, t in pairs(person.room.people) do
138
		-- print(string.format("\nPRESENCE: to: %s, from: %s, type: %s\n", t.jid, ));
139
		if nick ~= person.nick then
140
			SendPresence(t.jid, "available", "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..person.nick);
141
		end
142
	end
143
	SendPresence(person.jid, "available", "", person.occjid);
144
	room:_enter{ room = person.room, person = person, nick = person.nick };
145
end
146
 
147
function RemoveFromRoom(room, jid)
148
	if not ( room and jid) then return; end
149
	for id, t in pairs(room.people) do
150
		if CompareJIDs(t.jid, from) then room.people[id] = nil; end
151
	end
152
	-- Tell everyone in room that user is leaving
153
	for nick, t in pairs(room.people) do
154
			SendPresence(t.jid, "unavailable", "", GetJIDParts(t.occjid).node.."@"..GetJIDParts(t.occjid).server.."/"..people[jid].nick);
155
	end
156
end
157
 
158
function FSay(room, fromnick, text)
159
	BroadcastMessage(room.people, fromnick , text);
160
end
161
 
162
function PSay(room, tonick, fromnick, text)
163
	--print(string.format("Room JID: %s, To: %s, From: %s\n", room.jid, tonick, fromnick));
164
	for k,v in pairs(room.people) do print(string.format("people[\"%s\"]", k),", "); end
165
	print("\n");
166
	-- room.jid..(((fromnick and fromnick:len() > 0) and "/"..fromnick) or "")
167
	SendMessage(room.people[tonick].jid, room.people[tonick].occjid, text or "", (fromnick and fromnick:len() > 0 and "groupchat") or "groupchat");
168
end
169
 
170
dofile("common.lua");
171
 
172
rooms = rooms or { };
173
people = people or setmetatable({ default = {} }, { __newindex = function (t, k, v) if not rawget(v, "_parent") then rawset(v, "_parent", rawget(t, "default")); end return rawset(t, k, setmetatable(v, { __index = occupant })); end }); -- This is our inheritance code;