File

clix.lua @ 15:54314164a2a3

clix: Allow -p/--password to specify the login password
author Matthew Wild <mwild1@gmail.com>
date Thu, 07 Jan 2010 02:36:52 +0000
parent 14:1e927484c6ec
child 17:fa9efbef8a0c
line wrap: on
line source

#!/usr/bin/env lua
-- Clix -- Command-line XMPP
-- Copyright (C) 2008-2010 Matthew Wild
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
require "verse"
require "verse.client"

-- Global to allow commands to add to it
short_opts = { v = "verbose", t = "to", f = "from", e = "type", a = "account", p = "password", r = "resource" }

local command = arg[1];

if not command then
	print("Command Line XMPP, available commands:");
	for module in pairs(package.preload) do
		if module:match("^clix%.") then
			local m = require(module);
			m{ "--short-help" };
		end
	end
	return 0;
end

local ok, m = pcall(require, "clix."..command);
if not ok then
	print("Error running command '"..command.."' (run with --debug to see full error)");
	if arg[2] == "--debug" then
		print(m);
	end
	return 1;
end

if type(m) ~= "function" then
	print(command.." is not a valid command");
	return 1;
end

local accounts = { default = {} };
local current_account;
for line in io.lines(os.getenv("HOME").."/.clix") do
	line = line:match("^%s*(.-)%s*$");
	if line:match("^%[") then
		current_account = line:match("^%[(.-)%]");
		accounts[current_account] = {};
		if not current_account then -- This is the first defined account
			accounts.default = accounts[current_account];
		end
	elseif current_account then
		local k,v = line:match("^(%w+)%s*[:=]%s*(.+)$");
		accounts[current_account or "default"][k] = v;
	end
end

function clix_connect(opts, on_connect)
	local account = accounts[opts.account or "default"];
	if not (account and account.jid) then
		io.stderr:write("The specified account (", opts.account or "default", ") wasn't found in the config file\n");
		return nil;
	end
	verse.set_logger(opts.verbose and print or function () end);
	local conn = verse.new(verse.logger());
	conn.log.debug = opts.verbose;
	conn:hook("authentication-failure", function (err)
		conn:error("Authentication failure ("..(err.condition or "unknown error")..")"..(err.text and (": "..err.text) or ""));
		conn:close();
	end);
	conn:hook("binding-success", function () conn:debug("Connected: "..tostring(conn)); return on_connect(conn); end);
	conn:hook("binding-failure", function (err)
		conn:error("Resource binding failure ("..(err.condition or "unknown error")..")"..(err.text and (": "..err.text) or ""));
		conn:close();
	end);
	conn:hook("disconnected", function (info)
		if info.reason then
			conn:warn("Disconnecting: %s", tostring(info.reason));
		end
		verse.quit();
	end);
	-- Optional config parameters
	conn.connect_host = account.address;
	conn.connect_port = account.port;
	
	-- Connect!
	conn:connect_client(account.jid, opts.password or account.password);
	
	if type(opts.resource) == "string" then
		conn.resource = opts.resource;
	end
	
	local ok, ret = pcall(verse.loop);
	if not ok and not ret:match("interrupted!$") then
		io.stderr:write("Fatal error: ", ret, "\n");
		return 1;
	end
	return err or 0;
end

table.remove(arg,1);

local opts = {};

local args_handled_up_to;
for i, opt in ipairs(arg) do
        if opt:match("^%-") and opt ~= "--" then
                local name = opt:match("^%-%-?([^%s=]+)()")
                name = (short_opts[name] or name):gsub("%-+", "_");
                if name:match("^no_") then
                        name = name:sub(4, -1);
                        opts[name] = false;
                else
                        opts[name] = opt:match("=(.*)$") or true;
                end
        else
        	args_handled_up_to = i-1;
		break;
        end
end

-- Remove all the handled args from the arg array
for n=(args_handled_up_to or #arg),1,-1 do
	table.remove(arg, n);
end

return m(opts, arg) or 0;