corrade-lsl-templates – Blame information for rev 8

Subversion Repositories:
Rev:
Rev Author Line No. Line
8 office 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
3 ///////////////////////////////////////////////////////////////////////////
4 //
5 // An eggdrop-like group bot using Corrade.
6 //
7 ///////////////////////////////////////////////////////////////////////////
8  
9 ///////////////////////////////////////////////////////////////////////////
10 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
11 ///////////////////////////////////////////////////////////////////////////
12 string wasKeyValueGet(string k, string data) {
13 if(llStringLength(data) == 0) return "";
14 if(llStringLength(k) == 0) return "";
15 list a = llParseString2List(data, ["&", "="], []);
16 integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]);
17 if(i != -1) return llList2String(a, 2*i+1);
18 return "";
19 }
20  
21 ///////////////////////////////////////////////////////////////////////////
22 // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 //
23 ///////////////////////////////////////////////////////////////////////////
24 string wasKeyValueEncode(list data) {
25 list k = llList2ListStrided(data, 0, -1, 2);
26 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
27 data = [];
28 do {
29 data += llList2String(k, 0) + "=" + llList2String(v, 0);
30 k = llDeleteSubList(k, 0, 0);
31 v = llDeleteSubList(v, 0, 0);
32 } while(llGetListLength(k) != 0);
33 return llDumpList2String(data, "&");
34 }
35  
36 ///////////////////////////////////////////////////////////////////////////
37 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
38 ///////////////////////////////////////////////////////////////////////////
39 // escapes a string in conformance with RFC1738
40 string wasURLEscape(string i) {
41 string o = "";
42 do {
43 string c = llGetSubString(i, 0, 0);
44 i = llDeleteSubString(i, 0, 0);
45 if(c == "") jump continue;
46 if(c == " ") {
47 o += "+";
48 jump continue;
49 }
50 if(c == "\n") {
51 o += "%0D" + llEscapeURL(c);
52 jump continue;
53 }
54 o += llEscapeURL(c);
55 @continue;
56 } while(i != "");
57 return o;
58 }
59  
60 ///////////////////////////////////////////////////////////////////////////
61 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
62 ///////////////////////////////////////////////////////////////////////////
63 // unescapes a string in conformance with RFC1738
64 string wasURLUnescape(string i) {
65 return llUnescapeURL(
66 llDumpList2String(
67 llParseString2List(
68 llDumpList2String(
69 llParseString2List(
70 i,
71 ["+"],
72 []
73 ),
74 " "
75 ),
76 ["%0D%0A"],
77 []
78 ),
79 "\n"
80 )
81 );
82 }
83  
84 ///////////////////////////////////////////////////////////////////////////
85 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
86 ///////////////////////////////////////////////////////////////////////////
87 string wasListToCSV(list l) {
88 list v = [];
89 do {
90 string a = llDumpList2String(
91 llParseStringKeepNulls(
92 llList2String(
93 l,
94  
95 ),
96 ["\""],
97 []
98 ),
99 "\"\""
100 );
101 if(llParseStringKeepNulls(
102 a,
103 [" ", ",", "\n", "\""], []
104 ) !=
105 (list) a
106 ) a = "\"" + a + "\"";
107 v += a;
108 l = llDeleteSubList(l, 0, 0);
109 } while(l != []);
110 return llDumpList2String(v, ",");
111 }
112  
113 // for notecard reading
114 integer line = 0;
115  
116 // key-value data will be read into this list
117 list tuples = [];
118 string configuration = "";
119 // Corrade's online status.
120 integer online = FALSE;
121 integer compatible = FALSE;
122 string URL = "";
123  
124 // The notifications to bind to.
125 list notifications = [ "group", "notice" ];
126 // The tag that this script uses for notifications.
127 string EGG_TAG = "147d8bf1-4fbc-4c31-b0ea-1d2a72a41041";
128  
129 default {
130 state_entry() {
131 if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) {
132 llOwnerSay("[Control] Sorry, could not find a configuration inventory notecard.");
133 return;
134 }
135 // DEBUG
136 llOwnerSay("[Control] Reading configuration file...");
137 llGetNotecardLine("configuration", line);
138 }
139 dataserver(key id, string data) {
140 if(data == EOF) {
141 // invariant, length(tuples) % 2 == 0
142 if(llGetListLength(tuples) % 2 != 0) {
143 llOwnerSay("[Control] Error in configuration notecard.");
144 return;
145 }
146 key CORRADE = llList2Key(
147 tuples,
148 llListFindList(
149 tuples,
150 [
151 "corrade"
152 ]
153 )
154 +1);
155 if(CORRADE == NULL_KEY) {
156 llOwnerSay("[Control] Error in configuration notecard: corrade");
157 return;
158 }
159 string GROUP = llList2String(
160 tuples,
161 llListFindList(
162 tuples,
163 [
164 "group"
165 ]
166 )
167 +1);
168 if(GROUP == "") {
169 llOwnerSay("[Control] Error in configuration notecard: group");
170 return;
171 }
172 string PASSWORD = llList2String(
173 tuples,
174 llListFindList(
175 tuples,
176 [
177 "password"
178 ]
179 )
180 +1);
181 if(PASSWORD == "") {
182 llOwnerSay("[Control] Error in configuration notecard: password");
183 return;
184 }
185 string VERSION = llList2String(
186 tuples,
187 llListFindList(
188 tuples,
189 [
190 "version"
191 ]
192 )
193 +1);
194 if(VERSION == "") {
195 llOwnerSay("[Control] Error in configuration notecard: version");
196 return;
197 }
198 // DEBUG
199 llOwnerSay("[Control] Read configuration notecard...");
200 configuration = wasKeyValueEncode(tuples);
201 // GC
202 tuples = [];
203 state request_url_notifications;
204 }
205 if(data == "") jump continue;
206 integer i = llSubStringIndex(data, "#");
207 if(i != -1) data = llDeleteSubString(data, i, -1);
208 list o = llParseString2List(data, ["="], []);
209 // get rid of starting and ending quotes
210 string k = llDumpList2String(
211 llParseString2List(
212 llStringTrim(
213 llList2String(
214 o,
215  
216 ),
217 STRING_TRIM),
218 ["\""], []
219 ), "\"");
220 string v = llDumpList2String(
221 llParseString2List(
222 llStringTrim(
223 llList2String(
224 o,
225 1
226 ),
227 STRING_TRIM),
228 ["\""], []
229 ), "\"");
230 if(k == "" || v == "") jump continue;
231 tuples += k;
232 tuples += v;
233 @continue;
234 llGetNotecardLine("configuration", ++line);
235 }
236 attach(key id) {
237 llResetScript();
238 }
239 on_rez(integer num) {
240 llResetScript();
241 }
242 changed(integer change) {
243 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
244 llResetScript();
245 }
246 }
247 }
248  
249 state request_url_notifications {
250 state_entry() {
251 // DEBUG
252 llOwnerSay("[Control] Requesting URL...");
253 llRequestURL();
254 }
255 http_request(key id, string method, string body) {
256 if(method != URL_REQUEST_GRANTED) return;
257 URL = body;
258 // DEBUG
259 llOwnerSay("[Control] Got URL...");
260 state unbind_notifications;
261 }
262 on_rez(integer num) {
263 llResetScript();
264 }
265 changed(integer change) {
266 if((change & CHANGED_INVENTORY) ||
267 (change & CHANGED_REGION_START) ||
268 (change & CHANGED_OWNER)) {
269 llResetScript();
270 }
271 }
272 }
273  
274 state unbind_notifications {
275 state_entry() {
276 // DEBUG
277 llOwnerSay("[Control] Releasing notifications...");
278 llInstantMessage(
279 (key)wasKeyValueGet(
280 "corrade",
281 configuration
282 ),
283 wasKeyValueEncode(
284 [
285 "command", "notify",
286 "group", wasURLEscape(
287 wasKeyValueGet(
288 "group",
289 configuration
290 )
291 ),
292 "password", wasURLEscape(
293 wasKeyValueGet(
294 "password",
295 configuration
296 )
297 ),
298 "action", "remove",
299 "tag", wasURLEscape(EGG_TAG),
300 "callback", wasURLEscape(URL)
301 ]
302 )
303 );
304 llSetTimerEvent(60);
305 }
306 http_request(key id, string method, string body) {
307 llHTTPResponse(id, 200, "OK");
308 if(wasKeyValueGet("command", body) != "notify" ||
309 wasKeyValueGet("success", body) != "True") {
310 // DEBUG
311 llOwnerSay("[Control] Unable to release tag: " +
312 wasURLUnescape(
313 wasKeyValueGet("error", body)
314 )
315 );
316 llResetScript();
317 }
318 state bind_notifications;
319 }
320 timer() {
321 llOwnerSay("[Control] Timeout releasing notifications");
322 llResetScript();
323 }
324 on_rez(integer num) {
325 llResetScript();
326 }
327 changed(integer change) {
328 if((change & CHANGED_INVENTORY) ||
329 (change & CHANGED_REGION_START) ||
330 (change & CHANGED_OWNER)) {
331 llResetScript();
332 }
333 }
334 state_exit() {
335 llSetTimerEvent(0);
336 }
337 }
338  
339 state bind_notifications {
340 state_entry() {
341 // DEBUG
342 llOwnerSay("[Control] Binding to notifications...");
343 llInstantMessage(
344 wasKeyValueGet(
345 "corrade",
346 configuration
347 ),
348 wasKeyValueEncode(
349 [
350 "command", "notify",
351 "group", wasURLEscape(
352 wasKeyValueGet(
353 "group",
354 configuration
355 )
356 ),
357 "password", wasURLEscape(
358 wasKeyValueGet(
359 "password",
360 configuration
361 )
362 ),
363 "action", "add",
364 "type", wasURLEscape(
365 wasListToCSV(
366 notifications
367 )
368 ),
369 "URL", wasURLEscape(URL),
370 "tag", wasURLEscape(EGG_TAG),
371 "callback", wasURLEscape(URL)
372 ]
373 )
374 );
375 llSetTimerEvent(60);
376 }
377 http_request(key id, string method, string body) {
378 llHTTPResponse(id, 200, "OK");
379 if(wasKeyValueGet("command", body) != "notify" ||
380 wasKeyValueGet("success", body) != "True") {
381 // DEBUG
382 llOwnerSay("[Control] Unable to bind notifications: " +
383 wasURLUnescape(
384 wasKeyValueGet("error", body)
385 )
386 );
387 llResetScript();
388 }
389 state serve_configuration;
390 }
391 timer() {
392 llOwnerSay("[Control] Timeout binding notifications");
393 llResetScript();
394 }
395 on_rez(integer num) {
396 llResetScript();
397 }
398 changed(integer change) {
399 if((change & CHANGED_INVENTORY) ||
400 (change & CHANGED_REGION_START) ||
401 (change & CHANGED_OWNER)) {
402 llResetScript();
403 }
404 }
405 state_exit() {
406 llSetTimerEvent(0);
407 }
408 }
409  
410 state serve_configuration {
411 state_entry() {
412 // DEBUG
413 llOwnerSay("[Control] Checking version...");
414 llInstantMessage(
415 wasKeyValueGet(
416 "corrade",
417 configuration
418 ),
419 wasKeyValueEncode(
420 [
421 "command", "version",
422 "group", wasURLEscape(
423 wasKeyValueGet(
424 "group",
425 configuration
426 )
427 ),
428 "password", wasURLEscape(
429 wasKeyValueGet(
430 "password",
431 configuration
432 )
433 ),
434 "callback", wasURLEscape(URL)
435 ]
436 )
437 );
438 llSetTimerEvent(60);
439 }
440 http_request(key id, string method, string body) {
441 llHTTPResponse(id, 200, "OK");
442 llSetTimerEvent(0);
443 if(wasKeyValueGet("command", body) != "version") {
444 llMessageLinked(LINK_THIS, 0, body, "notification");
445 return;
446 }
447  
448 if(wasKeyValueGet("success", body) != "True") {
449 llOwnerSay("[Control] Version check failed...");
450 return;
451 }
452  
453 list v = llParseString2List(
454 wasKeyValueGet(
455 "data",
456 body
457 ),
458 ["."],
459 []
460 );
461 integer receivedVersion = (integer)(llList2String(v, 0) + llList2String(v, 1));
462 v = llParseString2List(
463 wasKeyValueGet(
464 "version",
465 configuration
466 ),
467 ["."],
468 []
469 );
470 integer notecardVersion = (integer)(llList2String(v, 0) + llList2String(v, 1));
471 if(receivedVersion < notecardVersion) {
472 llOwnerSay("[Control] Version is incompatible! You need a Corrade of at least version: " +
473 wasKeyValueGet(
474 "version",
475 configuration
476 ) +
477 " for this HUD."
478 );
479 compatible = FALSE;
480 //llReleaseURL(URL);
481 return;
482 }
483 // DEBUG
484 llOwnerSay("[Control] Version is compatible!");
485 compatible = TRUE;
486 //llReleaseURL(URL);
487 return;
488 }
489 link_message(integer sender, integer num, string message, key id) {
490 if(message != "configuration") return;
491 llMessageLinked(LINK_THIS, 0, configuration, "configuration");
492 }
493 timer() {
494 llOwnerSay("[Control] Timeout checking version...");
495 llResetScript();
496 }
497 on_rez(integer num) {
498 llResetScript();
499 }
500 changed(integer change) {
501 if((change & CHANGED_INVENTORY) ||
502 (change & CHANGED_REGION_START) ||
503 (change & CHANGED_OWNER)) {
504 llResetScript();
505 }
506 }
507 state_exit() {
508 llSetTimerEvent(0);
509 }
510 }