-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbot.lua
176 lines (148 loc) · 5.45 KB
/
bot.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
local commands = {};
http = require "socket.http";
JSON = assert(loadfile "JSON.lua")() -- one-time load of the routines
-- Load the verse XMPP library
require "verse".init("client");
-- Load the configuration file
local config = assert(loadfile "bot.cfg" )();
c = verse.new();
c:add_plugin("version");
c:add_plugin("disco");
-- dumps device record in readable form
function list_device_attr(dev, mode)
local result = "";
local exclude_flag;
-- Don't dump these fields as they are boring. Name data and idx arrear anyway to exclude them
local exclude_fields = {"Name", "Data", "idx", "SignalLevel", "CustomImage", "Favorite", "HardwareID", "HardwareName", "HaveDimmer", "HaveGroupCmd", "HaveTimeout", "Image", "IsSubDevice", "Notifications", "PlanID", "Protected", "ShowNotifications", "StrParam1", "StrParam2", "SubType", "SwitchType", "SwitchTypeVal", "Timers", "TypeImg", "Unit", "Used", "UsedByCamera", "XOffset", "YOffset"};
result = "<"..dev.Name..">, Data: "..dev.Data..", Idx: ".. dev.idx;
if mode == "full" then
for k,v in pairs(dev) do
exclude_flag = 0;
for i, k1 in ipairs(exclude_fields) do
if k1 == k then
exclude_flag = 1;
break;
end
end
if exclude_flag == 0 then
result = result..k.."="..tostring(v)..", ";
else
exclude_flag = 0;
end
end
end
return result;
end
-- prints short help
function help_handler(parsed_cli)
local response = "";
for k, r in pairs(commands) do
if r.description then
print(k, r.description);
response = response..string.format("<%s>:%s\n",k, r.description);
end
end
print ("help response", response)
return 1, response;
end
commands = {
["help"] = {handler=help_handler, description=nil}
};
function form_device_name(parsed_cli)
command = parsed_cli[2]
DeviceName = parsed_cli[3]
len_parsed_cli = #parsed_cli
if len_parsed_cli > 3 then
for i = 4, len_parsed_cli do
DeviceName = DeviceName..' '..parsed_cli[i]
end
end
return DeviceName
end
function device_list(DeviceType)
local t, jresponse, status, decoded_response
t = server_url.."/json.htm?type="..DeviceType.."&order=name"
print ("JSON request <"..t..">");
jresponse, status = http.request(t)
decoded_response = JSON:decode(jresponse)
return decoded_response
end
function idx_from_name(DeviceName,DeviceType)
local idx, k, record, decoded_response
decoded_response = device_list(DeviceType)
result = decoded_response["result"]
for k,record in pairs(result) do
if type(record) == "table" then
if string.lower(record['Name']) == string.lower(DeviceName) then
print(record['idx'])
idx = record['idx']
end
end
end
return idx
end
-- Load the modules that handle the commands. each module can have more than one command associated with it (see the list example)
print("Loading command modules...")
for i, m in ipairs(command_modules) do
print("Loading module <"..m..">");
t = assert(loadfile(m..".lua"))();
cl = t:get_commands();
for c, r in pairs(cl) do
print("found command <"..c..">");
commands[c] = r;
print(commands[c].handler);
end
end
-- Add some hooks for debugging
c:hook("opened", function () print("Stream opened!") end);
c:hook("closed", function () print("Stream closed!") end);
c:hook("stanza", function (stanza)
local body = stanza:get_child("body");
print("Stanza:", stanza)
end);
-- This one prints all received data
c:hook("incoming-raw", print, 1000);
-- Print a message after authentication
c:hook("authentication-success", function () print("Logged in!"); end);
c:hook("authentication-failure", function (err) print("Failed to log in! Error: "..tostring(err.condition)); end);
-- Print a message and exit when disconnected
c:hook("disconnected", function () print("Disconnected!"); os.exit(); end);
-- Now, actually start the connection:
c:connect_client(jid, password);
-- Catch the "ready" event to know when the stream is ready to use
c:hook("ready", function ()
print("Stream ready!");
c.version:set{ name = "verse example client" };
c:send(verse.presence():add_child(c:caps()));
c:query_version(c.jid, function (v) print("I am using "..(v.name or "<unknown>")); end);
-- Hook the messages once stream is ready
c:hook("message", function (message)
local body = message:get_child_text("body");
local command_dispatch, status;
if not body or message.attr.type == "error" then
return;
end
--- parse the command
local parsed_command = {}
for w in string.gfind(body, "(%w+)") do
table.insert(parsed_command, w)
end
--- check for passcode and execute
if passcode == nil or parsed_command[1] == passcode then
-- c:send(verse.message({type = "chat", to = message.attr.from}, "Hello, master! got command <"..parsed_command[2]..">"));
command_dispatch = commands[parsed_command[2]];
if command_dispatch then
status, text = command_dispatch.handler(parsed_command);
else
text = "command <"..parsed_command[2].."> not found";
end
c:send(verse.message({type = "chat", to = message.attr.from}, text));
end
end);
end);
-- Set the stored devices / scenes list
StoredType = 'devices'
StoredList = {}
ItemNumber = 0
print("Starting loop...")
verse.loop()