File

clix/roster.lua @ 56:4b5f9a50ae68

clix.roster: Fix nickname fallback
author Kim Alvefur <zash@zash.se>
date Tue, 15 Mar 2011 18:29:24 +0100
parent 48:8206f3369d37
child 57:830baad98c9a
line wrap: on
line source

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, host = item.name 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