Sat, 12 Mar 2011 20:08:48 +0100
clix.roster: Roster management
48 | 1 | short_opts.i = "interactive"; |
2 | local split_jid = require "util.jid".split; | |
3 | local function printor(str) return function() print(str) end end | |
4 | ||
5 | return function (opts, arg) | |
6 | if opts.short_help then | |
7 | print("Show or edit your roster"); | |
8 | return; | |
9 | end | |
10 | if opts.help and not opts.interactive then | |
11 | return 0; | |
12 | end | |
13 | local function on_connect(conn) | |
14 | -- Fake socket object around stdin | |
15 | local stdin = { | |
16 | getfd = function () return 0; end; | |
17 | dirty = function (self) return false; end; | |
18 | settimeout = function () end; | |
19 | send = function (_, d) return #d, 0; end; | |
20 | close = function () end; | |
21 | receive = function (_, patt) | |
22 | local data = io.stdin:read(patt); | |
23 | if data == nil then | |
24 | conn:close(); | |
25 | end | |
26 | if opts.echo then | |
27 | io.write(data, patt == "*l" and "\n" or ""); | |
28 | end | |
29 | return data; | |
30 | end | |
31 | }; | |
32 | local commands = { | |
33 | quit = function(param) conn:close(); end; | |
34 | add = function(param) conn.roster:add_contact(param) end; | |
35 | sub = function(param) conn:send(verse.presence{to=param, type="subscribe"}); end; | |
36 | auth = function(param) conn:send(verse.presence{to=param, type="subscribed"}); end; | |
37 | del = function(param) conn.roster:delete_contact(param) end; | |
38 | setnick = function(param) | |
39 | local jid, nick = param:match("^(%S+)%s+(%S+)"); | |
40 | local item = conn.roster.items[jid]; | |
41 | if not item then print("no jid "..jid); return; end | |
42 | conn.roster:add_contact(jid, nick, item.groups or {}, printor("saved")); | |
43 | end; | |
44 | addgroup = function(param) | |
45 | local jid, group = param:match("^(%S+)%s+(%S+)"); | |
46 | local item = conn.roster.items[jid]; | |
47 | local groups = item.groups or {}; | |
48 | table.insert(groups, group); | |
49 | conn.roster:add_contact(jid, item.name, groups, printor("saved")); | |
50 | end; | |
51 | delgroup = function(param) | |
52 | local jid, group = param:match("^(%S+)%s+(%S+)"); | |
53 | local item = conn.roster.items[jid]; | |
54 | local groups = item.groups; | |
55 | if not groups then return end; | |
56 | for i = 1,#groups do | |
57 | if groups[i] == group then | |
58 | table.remove(groups, i); | |
59 | break | |
60 | end | |
61 | end | |
62 | conn.roster:add_contact(jid, item.name, groups, printor("saved")); | |
63 | end; | |
64 | list = function() | |
65 | for jid, item in pairs(conn.roster.items) do | |
66 | local name = item.name, host or split_jid(jid); | |
67 | print(name or host, jid, table.concat(item.groups or {}, ", ")); | |
68 | end | |
69 | end; | |
70 | listgroups = function(param) | |
71 | local groups = {}; | |
72 | for jid, item in pairs(conn.roster.items) do | |
73 | for i = 1,#item.groups do | |
74 | groups[item.groups[i]] = ( groups[item.groups[i]] or 0 ) + 1; | |
75 | end | |
76 | end | |
77 | for group, size in pairs(groups) do | |
78 | print(group, size) | |
79 | end | |
80 | end; | |
81 | show = function(param) | |
82 | local item = conn.roster.items[param]; | |
83 | if not item then | |
84 | print("No such contact"); | |
85 | return; | |
86 | end | |
87 | ||
88 | for k,v in pairs(item) do | |
89 | print(k,type(v) == "table" and table.concat(v) or v) | |
90 | end | |
91 | end; | |
92 | } | |
93 | local function on_incoming(stdin, text) | |
94 | local cmd = text:match("^(%a*)"); | |
95 | local param = text:match("%s+(.*)", #cmd); | |
96 | if commands[cmd] then | |
97 | commands[cmd](param); | |
98 | end | |
99 | end | |
100 | stdin = require "net.server".wrapclient(stdin, "stdin", 0, { | |
101 | onincoming = on_incoming, ondisconnect = function () end | |
102 | }, "*l"); | |
103 | conn:add_plugin("roster"); | |
104 | conn.roster:fetch(function(roster) | |
105 | if not roster then | |
106 | print("There was an error fetching your roster"); | |
107 | conn:close() | |
108 | end | |
109 | ||
110 | local firstcmd = commands[arg[1] or "list"]; | |
111 | if firstcmd then | |
112 | firstcmd(table.concat(arg, " ", 2, #arg)) | |
113 | end | |
114 | if not opts.interactive then | |
115 | conn:close(); | |
116 | end | |
117 | end); | |
118 | local function notif(e) | |
119 | return function(item) | |
120 | return print(("%s %s"):format((item.name and item.name .. " (" .. item.jid .. ")") or item.jid, e)); | |
121 | end | |
122 | end | |
123 | if opts.interactive then | |
124 | conn:hook("roster/item-added", notif("added")); | |
125 | conn:hook("roster/item-changed", notif("changed")); | |
126 | conn:hook("roster/item-removed", notif("removed")); | |
127 | end | |
128 | end | |
129 | clix_connect(opts, on_connect); | |
130 | end |