Changeset

48:8206f3369d37

clix.roster: Roster management
author Kim Alvefur <zash@zash.se>
date Sat, 12 Mar 2011 20:08:48 +0100
parents 46:b5d6e443e571
children 49:64e637041347
files clix/roster.lua squishy
diffstat 2 files changed, 131 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/clix/roster.lua	Sat Mar 12 20:08:48 2011 +0100
@@ -0,0 +1,130 @@
+short_opts.i = "interactive";
+local split_jid = require "util.jid".split;
+local function printor(str) return function() print(str) end end
+
+return function (opts, arg)
+	if opts.short_help then
+		print("Show or edit your roster");
+		return;
+	end
+	if opts.help and not opts.interactive then
+		return 0;
+	end
+	local function on_connect(conn)
+		-- Fake socket object around stdin
+		local stdin = {
+			getfd = function () return 0; end;
+			dirty = function (self) return false; end;
+			settimeout = function () end;
+			send = function (_, d) return #d, 0; end;
+			close = function () end;
+			receive = function (_, patt)
+				local data = io.stdin:read(patt);
+				if data == nil then
+					conn:close();
+				end
+				if opts.echo then
+					io.write(data, patt == "*l" and "\n" or "");
+				end
+				return data;
+			end
+		};
+		local commands = {
+			quit = function(param) conn:close(); end;
+			add = function(param) conn.roster:add_contact(param) end;
+			sub = function(param) conn:send(verse.presence{to=param, type="subscribe"}); end;
+			auth = function(param) conn:send(verse.presence{to=param, type="subscribed"}); end;
+			del = function(param) conn.roster:delete_contact(param) end;
+			setnick = function(param)
+				local jid, nick = param:match("^(%S+)%s+(%S+)");
+				local item = conn.roster.items[jid];
+				if not item then print("no jid "..jid); return; end
+				conn.roster:add_contact(jid, nick, item.groups or {}, printor("saved"));
+			end;
+			addgroup = function(param)
+				local jid, group = param:match("^(%S+)%s+(%S+)");
+				local item = conn.roster.items[jid];
+				local groups = item.groups or {};
+				table.insert(groups, group);
+				conn.roster:add_contact(jid, item.name, groups, printor("saved"));
+			end;
+			delgroup = function(param)
+				local jid, group = param:match("^(%S+)%s+(%S+)");
+				local item = conn.roster.items[jid];
+				local groups = item.groups;
+				if not groups then return end;
+				for i = 1,#groups do
+					if groups[i] == group then
+						table.remove(groups, i);
+						break
+					end
+				end
+				conn.roster:add_contact(jid, item.name, groups, printor("saved"));
+			end;
+			list = function()
+				for jid, item in pairs(conn.roster.items) do
+					local name = item.name, host or split_jid(jid);
+					print(name or host, jid, table.concat(item.groups or {}, ", "));
+				end
+			end;
+			listgroups = function(param)
+				local groups = {};
+				for jid, item in pairs(conn.roster.items) do
+					for i = 1,#item.groups do
+						groups[item.groups[i]] = ( groups[item.groups[i]] or 0 ) + 1;
+					end
+				end
+				for group, size in pairs(groups) do
+					print(group, size)
+				end
+			end;
+			show = function(param)
+				local item = conn.roster.items[param];
+				if not item then
+					print("No such contact");
+					return;
+				end
+
+				for k,v in pairs(item) do
+					print(k,type(v) == "table" and table.concat(v) or v)
+				end
+			end;
+		}
+		local function on_incoming(stdin, text)
+			local cmd = text:match("^(%a*)");
+			local param = text:match("%s+(.*)", #cmd);
+			if commands[cmd] then
+				commands[cmd](param);
+			end
+		end
+		stdin = require "net.server".wrapclient(stdin, "stdin", 0, {
+			onincoming = on_incoming, ondisconnect = function () end
+		}, "*l");
+		conn:add_plugin("roster");
+		conn.roster:fetch(function(roster)
+			if not roster then
+				print("There was an error fetching your roster");
+				conn:close()
+			end
+
+			local firstcmd = commands[arg[1] or "list"];
+			if firstcmd then
+				firstcmd(table.concat(arg, " ", 2, #arg))
+			end
+			if not opts.interactive then
+				conn:close();
+			end
+		end);
+		local function notif(e)
+			return function(item)
+				return print(("%s %s"):format((item.name and item.name .. " (" .. item.jid .. ")") or item.jid, e));
+			end
+		end
+		if opts.interactive then
+			conn:hook("roster/item-added", notif("added"));
+			conn:hook("roster/item-changed", notif("changed"));
+			conn:hook("roster/item-removed", notif("removed"));
+		end
+	end
+	clix_connect(opts, on_connect);
+end
--- a/squishy	Tue Feb 22 20:52:22 2011 +0000
+++ b/squishy	Sat Mar 12 20:08:48 2011 +0100
@@ -4,6 +4,7 @@
 Module "clix.bounce" "clix/bounce.lua"
 Module "clix.mirror" "clix/mirror.lua"
 Module "clix.raw" "clix/raw.lua"
+Module "clix.roster" "clix/roster.lua"
 
 if GetOption "with-verse" then
 	Module("verse")(GetOption "with-verse");