|
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 |