corrade-lsl-templates – Blame information for rev 15

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.
15 office 125 list notifications = [ "group", "membership", "login" ];
8 office 126  
127 default {
128 state_entry() {
129 if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) {
130 llOwnerSay("[Control] Sorry, could not find a configuration inventory notecard.");
131 return;
132 }
133 // DEBUG
134 llOwnerSay("[Control] Reading configuration file...");
135 llGetNotecardLine("configuration", line);
136 }
137 dataserver(key id, string data) {
138 if(data == EOF) {
139 // invariant, length(tuples) % 2 == 0
140 if(llGetListLength(tuples) % 2 != 0) {
141 llOwnerSay("[Control] Error in configuration notecard.");
142 return;
143 }
144 key CORRADE = llList2Key(
145 tuples,
146 llListFindList(
147 tuples,
148 [
149 "corrade"
150 ]
151 )
152 +1);
153 if(CORRADE == NULL_KEY) {
154 llOwnerSay("[Control] Error in configuration notecard: corrade");
155 return;
156 }
157 string GROUP = llList2String(
158 tuples,
159 llListFindList(
160 tuples,
161 [
162 "group"
163 ]
164 )
165 +1);
166 if(GROUP == "") {
167 llOwnerSay("[Control] Error in configuration notecard: group");
168 return;
169 }
170 string PASSWORD = llList2String(
171 tuples,
172 llListFindList(
173 tuples,
174 [
175 "password"
176 ]
177 )
178 +1);
179 if(PASSWORD == "") {
180 llOwnerSay("[Control] Error in configuration notecard: password");
181 return;
182 }
183 string VERSION = llList2String(
184 tuples,
185 llListFindList(
186 tuples,
187 [
188 "version"
189 ]
190 )
191 +1);
192 if(VERSION == "") {
193 llOwnerSay("[Control] Error in configuration notecard: version");
194 return;
195 }
196 // DEBUG
197 llOwnerSay("[Control] Read configuration notecard...");
198 configuration = wasKeyValueEncode(tuples);
199 // GC
200 tuples = [];
201 state request_url_notifications;
202 }
203 if(data == "") jump continue;
204 integer i = llSubStringIndex(data, "#");
205 if(i != -1) data = llDeleteSubString(data, i, -1);
206 list o = llParseString2List(data, ["="], []);
207 // get rid of starting and ending quotes
208 string k = llDumpList2String(
209 llParseString2List(
210 llStringTrim(
211 llList2String(
212 o,
213  
214 ),
215 STRING_TRIM),
216 ["\""], []
217 ), "\"");
218 string v = llDumpList2String(
219 llParseString2List(
220 llStringTrim(
221 llList2String(
222 o,
223 1
224 ),
225 STRING_TRIM),
226 ["\""], []
227 ), "\"");
228 if(k == "" || v == "") jump continue;
229 tuples += k;
230 tuples += v;
231 @continue;
232 llGetNotecardLine("configuration", ++line);
233 }
234 attach(key id) {
235 llResetScript();
236 }
237 on_rez(integer num) {
238 llResetScript();
239 }
240 changed(integer change) {
241 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
242 llResetScript();
243 }
244 }
245 }
246  
247 state request_url_notifications {
248 state_entry() {
249 // DEBUG
250 llOwnerSay("[Control] Requesting URL...");
251 llRequestURL();
252 }
253 http_request(key id, string method, string body) {
254 if(method != URL_REQUEST_GRANTED) return;
255 URL = body;
256 // DEBUG
257 llOwnerSay("[Control] Got URL...");
258 state unbind_notifications;
259 }
260 on_rez(integer num) {
261 llResetScript();
262 }
263 changed(integer change) {
264 if((change & CHANGED_INVENTORY) ||
265 (change & CHANGED_REGION_START) ||
266 (change & CHANGED_OWNER)) {
267 llResetScript();
268 }
269 }
270 }
271  
272 state unbind_notifications {
273 state_entry() {
274 // DEBUG
275 llOwnerSay("[Control] Releasing notifications...");
276 llInstantMessage(
277 (key)wasKeyValueGet(
278 "corrade",
279 configuration
280 ),
281 wasKeyValueEncode(
282 [
283 "command", "notify",
284 "group", wasURLEscape(
285 wasKeyValueGet(
286 "group",
287 configuration
288 )
289 ),
290 "password", wasURLEscape(
291 wasKeyValueGet(
292 "password",
293 configuration
294 )
295 ),
296 "action", "remove",
11 office 297 "tag", wasURLEscape(
298 wasKeyValueGet(
299 "notification tag",
300 configuration
301 )
302 ),
8 office 303 "callback", wasURLEscape(URL)
304 ]
305 )
306 );
307 llSetTimerEvent(60);
308 }
309 http_request(key id, string method, string body) {
310 llHTTPResponse(id, 200, "OK");
311 if(wasKeyValueGet("command", body) != "notify" ||
312 wasKeyValueGet("success", body) != "True") {
313 // DEBUG
314 llOwnerSay("[Control] Unable to release tag: " +
315 wasURLUnescape(
316 wasKeyValueGet("error", body)
317 )
318 );
319 llResetScript();
320 }
321 state bind_notifications;
322 }
323 timer() {
324 llOwnerSay("[Control] Timeout releasing notifications");
325 llResetScript();
326 }
327 on_rez(integer num) {
328 llResetScript();
329 }
330 changed(integer change) {
331 if((change & CHANGED_INVENTORY) ||
332 (change & CHANGED_REGION_START) ||
333 (change & CHANGED_OWNER)) {
334 llResetScript();
335 }
336 }
337 state_exit() {
338 llSetTimerEvent(0);
339 }
340 }
341  
342 state bind_notifications {
343 state_entry() {
344 // DEBUG
345 llOwnerSay("[Control] Binding to notifications...");
346 llInstantMessage(
347 wasKeyValueGet(
348 "corrade",
349 configuration
350 ),
351 wasKeyValueEncode(
352 [
353 "command", "notify",
354 "group", wasURLEscape(
355 wasKeyValueGet(
356 "group",
357 configuration
358 )
359 ),
360 "password", wasURLEscape(
361 wasKeyValueGet(
362 "password",
363 configuration
364 )
365 ),
366 "action", "add",
367 "type", wasURLEscape(
368 wasListToCSV(
369 notifications
370 )
371 ),
372 "URL", wasURLEscape(URL),
11 office 373 "tag", wasURLEscape(
374 wasKeyValueGet(
375 "notification tag",
376 configuration
377 )
378 ),
8 office 379 "callback", wasURLEscape(URL)
380 ]
381 )
382 );
383 llSetTimerEvent(60);
384 }
385 http_request(key id, string method, string body) {
386 llHTTPResponse(id, 200, "OK");
387 if(wasKeyValueGet("command", body) != "notify" ||
388 wasKeyValueGet("success", body) != "True") {
389 // DEBUG
390 llOwnerSay("[Control] Unable to bind notifications: " +
391 wasURLUnescape(
392 wasKeyValueGet("error", body)
393 )
394 );
395 llResetScript();
396 }
397 state serve_configuration;
398 }
399 timer() {
400 llOwnerSay("[Control] Timeout binding notifications");
401 llResetScript();
402 }
403 on_rez(integer num) {
404 llResetScript();
405 }
406 changed(integer change) {
407 if((change & CHANGED_INVENTORY) ||
408 (change & CHANGED_REGION_START) ||
409 (change & CHANGED_OWNER)) {
410 llResetScript();
411 }
412 }
413 state_exit() {
414 llSetTimerEvent(0);
415 }
416 }
417  
418 state serve_configuration {
419 state_entry() {
420 // DEBUG
421 llOwnerSay("[Control] Checking version...");
422 llInstantMessage(
423 wasKeyValueGet(
424 "corrade",
425 configuration
426 ),
427 wasKeyValueEncode(
428 [
429 "command", "version",
430 "group", wasURLEscape(
431 wasKeyValueGet(
432 "group",
433 configuration
434 )
435 ),
436 "password", wasURLEscape(
437 wasKeyValueGet(
438 "password",
439 configuration
440 )
441 ),
442 "callback", wasURLEscape(URL)
443 ]
444 )
445 );
446 llSetTimerEvent(60);
447 }
448 http_request(key id, string method, string body) {
449 llHTTPResponse(id, 200, "OK");
450 llSetTimerEvent(0);
451 if(wasKeyValueGet("command", body) != "version") {
452 llMessageLinked(LINK_THIS, 0, body, "notification");
453 return;
454 }
455  
456 if(wasKeyValueGet("success", body) != "True") {
457 llOwnerSay("[Control] Version check failed...");
458 return;
459 }
460  
461 list v = llParseString2List(
462 wasKeyValueGet(
463 "data",
464 body
465 ),
466 ["."],
467 []
468 );
469 integer receivedVersion = (integer)(llList2String(v, 0) + llList2String(v, 1));
470 v = llParseString2List(
471 wasKeyValueGet(
472 "version",
473 configuration
474 ),
475 ["."],
476 []
477 );
478 integer notecardVersion = (integer)(llList2String(v, 0) + llList2String(v, 1));
479 if(receivedVersion < notecardVersion) {
480 llOwnerSay("[Control] Version is incompatible! You need a Corrade of at least version: " +
481 wasKeyValueGet(
482 "version",
483 configuration
484 ) +
11 office 485 " for this template."
8 office 486 );
487 compatible = FALSE;
488 //llReleaseURL(URL);
489 return;
490 }
491 // DEBUG
492 llOwnerSay("[Control] Version is compatible!");
493 compatible = TRUE;
494 //llReleaseURL(URL);
495 return;
496 }
497 link_message(integer sender, integer num, string message, key id) {
498 if(message != "configuration") return;
499 llMessageLinked(LINK_THIS, 0, configuration, "configuration");
500 }
501 timer() {
502 llOwnerSay("[Control] Timeout checking version...");
503 llResetScript();
504 }
505 on_rez(integer num) {
506 llResetScript();
507 }
508 changed(integer change) {
509 if((change & CHANGED_INVENTORY) ||
510 (change & CHANGED_REGION_START) ||
511 (change & CHANGED_OWNER)) {
512 llResetScript();
513 }
514 }
515 state_exit() {
516 llSetTimerEvent(0);
517 }
518 }