corrade-lsl-templates – Blame information for rev 42
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
8 | office | 1 | /////////////////////////////////////////////////////////////////////////// |
42 | office | 2 | // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 // |
8 | office | 3 | /////////////////////////////////////////////////////////////////////////// |
4 | // |
||
5 | // An eggdrop-like group bot using Corrade. |
||
6 | // |
||
7 | /////////////////////////////////////////////////////////////////////////// |
||
8 | |||
9 | /////////////////////////////////////////////////////////////////////////// |
||
29 | office | 10 | // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // |
8 | office | 11 | /////////////////////////////////////////////////////////////////////////// |
12 | string wasKeyValueGet(string k, string data) { |
||
13 | if(llStringLength(data) == 0) return ""; |
||
14 | if(llStringLength(k) == 0) return ""; |
||
41 | office | 15 | list a = llParseStringKeepNulls(data, ["&", "="], []); |
8 | office | 16 | integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]); |
17 | if(i != -1) return llList2String(a, 2*i+1); |
||
18 | return ""; |
||
19 | } |
||
42 | office | 20 | |
8 | office | 21 | /////////////////////////////////////////////////////////////////////////// |
42 | office | 22 | // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 // |
8 | office | 23 | /////////////////////////////////////////////////////////////////////////// |
42 | office | 24 | string wasKeyValueDelete(string k, string data) { |
25 | if(llStringLength(data) == 0) return ""; |
||
26 | if(llStringLength(k) == 0) return ""; |
||
27 | integer i = llListFindList( |
||
28 | llList2ListStrided( |
||
29 | llParseString2List(data, ["&", "="], []), |
||
30 | 0, -1, 2 |
||
31 | ), |
||
32 | [ k ]); |
||
33 | if(i != -1) return llDumpList2String( |
||
34 | llDeleteSubList( |
||
35 | llParseString2List(data, ["&"], []), |
||
36 | i, i), |
||
37 | "&"); |
||
38 | return data; |
||
39 | } |
||
40 | |||
41 | /////////////////////////////////////////////////////////////////////////// |
||
42 | // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 // |
||
43 | /////////////////////////////////////////////////////////////////////////// |
||
44 | string wasKeyValueSet(string k, string v, string data) { |
||
45 | if(llStringLength(k) == 0) return ""; |
||
46 | if(llStringLength(v) == 0) return ""; |
||
47 | if(llStringLength(data) == 0) return k + "=" + v; |
||
48 | integer i = llListFindList( |
||
49 | llList2ListStrided( |
||
50 | llParseString2List(data, ["&", "="], []), |
||
51 | 0, -1, 2 |
||
52 | ), |
||
53 | [ k ]); |
||
54 | if(i != -1) return llDumpList2String( |
||
55 | llListReplaceList( |
||
56 | llParseString2List(data, ["&"], []), |
||
57 | [ k + "=" + v ], |
||
58 | i, i), |
||
59 | "&"); |
||
60 | return data + "&" + k + "=" + v; |
||
61 | } |
||
62 | |||
63 | /////////////////////////////////////////////////////////////////////////// |
||
64 | // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // |
||
65 | /////////////////////////////////////////////////////////////////////////// |
||
8 | office | 66 | string wasKeyValueEncode(list data) { |
67 | list k = llList2ListStrided(data, 0, -1, 2); |
||
68 | list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); |
||
69 | data = []; |
||
70 | do { |
||
71 | data += llList2String(k, 0) + "=" + llList2String(v, 0); |
||
72 | k = llDeleteSubList(k, 0, 0); |
||
73 | v = llDeleteSubList(v, 0, 0); |
||
74 | } while(llGetListLength(k) != 0); |
||
75 | return llDumpList2String(data, "&"); |
||
76 | } |
||
77 | |||
78 | /////////////////////////////////////////////////////////////////////////// |
||
42 | office | 79 | // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
8 | office | 80 | /////////////////////////////////////////////////////////////////////////// |
81 | // escapes a string in conformance with RFC1738 |
||
82 | string wasURLEscape(string i) { |
||
83 | string o = ""; |
||
84 | do { |
||
85 | string c = llGetSubString(i, 0, 0); |
||
86 | i = llDeleteSubString(i, 0, 0); |
||
87 | if(c == "") jump continue; |
||
88 | if(c == " ") { |
||
89 | o += "+"; |
||
90 | jump continue; |
||
91 | } |
||
92 | if(c == "\n") { |
||
93 | o += "%0D" + llEscapeURL(c); |
||
94 | jump continue; |
||
95 | } |
||
96 | o += llEscapeURL(c); |
||
97 | @continue; |
||
98 | } while(i != ""); |
||
99 | return o; |
||
100 | } |
||
101 | |||
102 | /////////////////////////////////////////////////////////////////////////// |
||
42 | office | 103 | // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
8 | office | 104 | /////////////////////////////////////////////////////////////////////////// |
105 | // unescapes a string in conformance with RFC1738 |
||
106 | string wasURLUnescape(string i) { |
||
107 | return llUnescapeURL( |
||
108 | llDumpList2String( |
||
109 | llParseString2List( |
||
110 | llDumpList2String( |
||
111 | llParseString2List( |
||
42 | office | 112 | i, |
113 | ["+"], |
||
8 | office | 114 | [] |
42 | office | 115 | ), |
8 | office | 116 | " " |
42 | office | 117 | ), |
118 | ["%0D%0A"], |
||
8 | office | 119 | [] |
42 | office | 120 | ), |
8 | office | 121 | "\n" |
122 | ) |
||
123 | ); |
||
124 | } |
||
125 | |||
126 | /////////////////////////////////////////////////////////////////////////// |
||
42 | office | 127 | // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // |
8 | office | 128 | /////////////////////////////////////////////////////////////////////////// |
129 | string wasListToCSV(list l) { |
||
130 | list v = []; |
||
131 | do { |
||
132 | string a = llDumpList2String( |
||
133 | llParseStringKeepNulls( |
||
134 | llList2String( |
||
42 | office | 135 | l, |
8 | office | 136 | |
42 | office | 137 | ), |
138 | ["\""], |
||
8 | office | 139 | [] |
140 | ), |
||
141 | "\"\"" |
||
142 | ); |
||
143 | if(llParseStringKeepNulls( |
||
42 | office | 144 | a, |
8 | office | 145 | [" ", ",", "\n", "\""], [] |
42 | office | 146 | ) != |
8 | office | 147 | (list) a |
148 | ) a = "\"" + a + "\""; |
||
149 | v += a; |
||
150 | l = llDeleteSubList(l, 0, 0); |
||
151 | } while(l != []); |
||
152 | return llDumpList2String(v, ","); |
||
153 | } |
||
154 | |||
42 | office | 155 | /////////////////////////////////////////////////////////////////////////// |
156 | // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // |
||
157 | /////////////////////////////////////////////////////////////////////////// |
||
158 | list wasCSVToList(string csv) { |
||
159 | list l = []; |
||
160 | list s = []; |
||
161 | string m = ""; |
||
162 | do { |
||
163 | string a = llGetSubString(csv, 0, 0); |
||
164 | csv = llDeleteSubString(csv, 0, 0); |
||
165 | if(a == ",") { |
||
166 | if(llList2String(s, -1) != "\"") { |
||
167 | l += m; |
||
168 | m = ""; |
||
169 | jump continue; |
||
170 | } |
||
171 | m += a; |
||
172 | jump continue; |
||
173 | } |
||
174 | if(a == "\"" && llGetSubString(csv, 0, 0) == a) { |
||
175 | m += a; |
||
176 | csv = llDeleteSubString(csv, 0, 0); |
||
177 | jump continue; |
||
178 | } |
||
179 | if(a == "\"") { |
||
180 | if(llList2String(s, -1) != a) { |
||
181 | s += a; |
||
182 | jump continue; |
||
183 | } |
||
184 | s = llDeleteSubList(s, -1, -1); |
||
185 | jump continue; |
||
186 | } |
||
187 | m += a; |
||
188 | @continue; |
||
189 | } while(csv != ""); |
||
190 | // postcondition: length(s) = 0 |
||
191 | return l + m; |
||
192 | } |
||
193 | |||
8 | office | 194 | // for notecard reading |
195 | integer line = 0; |
||
42 | office | 196 | |
8 | office | 197 | // key-value data will be read into this list |
198 | list tuples = []; |
||
199 | string configuration = ""; |
||
200 | // Corrade's online status. |
||
201 | integer online = FALSE; |
||
202 | integer compatible = FALSE; |
||
203 | string URL = ""; |
||
204 | |||
205 | // The notifications to bind to. |
||
24 | office | 206 | list notifications = [ "group", "membership", "login", "MQTT" ]; |
8 | office | 207 | |
208 | default { |
||
209 | state_entry() { |
||
210 | if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) { |
||
211 | llOwnerSay("[Control] Sorry, could not find a configuration inventory notecard."); |
||
212 | return; |
||
213 | } |
||
214 | // DEBUG |
||
215 | llOwnerSay("[Control] Reading configuration file..."); |
||
216 | llGetNotecardLine("configuration", line); |
||
217 | } |
||
218 | dataserver(key id, string data) { |
||
219 | if(data == EOF) { |
||
220 | // invariant, length(tuples) % 2 == 0 |
||
221 | if(llGetListLength(tuples) % 2 != 0) { |
||
222 | llOwnerSay("[Control] Error in configuration notecard."); |
||
223 | return; |
||
224 | } |
||
225 | key CORRADE = llList2Key( |
||
226 | tuples, |
||
227 | llListFindList( |
||
42 | office | 228 | tuples, |
8 | office | 229 | [ |
230 | "corrade" |
||
231 | ] |
||
232 | ) |
||
233 | +1); |
||
234 | if(CORRADE == NULL_KEY) { |
||
235 | llOwnerSay("[Control] Error in configuration notecard: corrade"); |
||
236 | return; |
||
237 | } |
||
238 | string GROUP = llList2String( |
||
239 | tuples, |
||
240 | llListFindList( |
||
42 | office | 241 | tuples, |
8 | office | 242 | [ |
243 | "group" |
||
244 | ] |
||
245 | ) |
||
246 | +1); |
||
247 | if(GROUP == "") { |
||
248 | llOwnerSay("[Control] Error in configuration notecard: group"); |
||
249 | return; |
||
250 | } |
||
251 | string PASSWORD = llList2String( |
||
252 | tuples, |
||
253 | llListFindList( |
||
42 | office | 254 | tuples, |
8 | office | 255 | [ |
256 | "password" |
||
257 | ] |
||
258 | ) |
||
259 | +1); |
||
260 | if(PASSWORD == "") { |
||
261 | llOwnerSay("[Control] Error in configuration notecard: password"); |
||
262 | return; |
||
263 | } |
||
264 | string VERSION = llList2String( |
||
265 | tuples, |
||
266 | llListFindList( |
||
42 | office | 267 | tuples, |
8 | office | 268 | [ |
269 | "version" |
||
270 | ] |
||
271 | ) |
||
272 | +1); |
||
273 | if(VERSION == "") { |
||
274 | llOwnerSay("[Control] Error in configuration notecard: version"); |
||
275 | return; |
||
276 | } |
||
277 | // DEBUG |
||
278 | llOwnerSay("[Control] Read configuration notecard..."); |
||
279 | configuration = wasKeyValueEncode(tuples); |
||
280 | // GC |
||
281 | tuples = []; |
||
282 | state request_url_notifications; |
||
283 | } |
||
284 | if(data == "") jump continue; |
||
42 | office | 285 | // No support for inline comments for this one! Needs parsing! |
8 | office | 286 | integer i = llSubStringIndex(data, "#"); |
42 | office | 287 | if(i == 0) data = llDeleteSubString(data, i, -1); |
8 | office | 288 | list o = llParseString2List(data, ["="], []); |
289 | // get rid of starting and ending quotes |
||
290 | string k = llDumpList2String( |
||
291 | llParseString2List( |
||
292 | llStringTrim( |
||
293 | llList2String( |
||
42 | office | 294 | o, |
8 | office | 295 | |
42 | office | 296 | ), |
297 | STRING_TRIM), |
||
8 | office | 298 | ["\""], [] |
299 | ), "\""); |
||
300 | string v = llDumpList2String( |
||
301 | llParseString2List( |
||
302 | llStringTrim( |
||
303 | llList2String( |
||
42 | office | 304 | o, |
8 | office | 305 | 1 |
42 | office | 306 | ), |
307 | STRING_TRIM), |
||
8 | office | 308 | ["\""], [] |
309 | ), "\""); |
||
310 | if(k == "" || v == "") jump continue; |
||
311 | tuples += k; |
||
312 | tuples += v; |
||
313 | @continue; |
||
314 | llGetNotecardLine("configuration", ++line); |
||
315 | } |
||
316 | attach(key id) { |
||
317 | llResetScript(); |
||
318 | } |
||
319 | on_rez(integer num) { |
||
320 | llResetScript(); |
||
321 | } |
||
322 | changed(integer change) { |
||
323 | if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { |
||
324 | llResetScript(); |
||
325 | } |
||
326 | } |
||
327 | } |
||
328 | |||
329 | state request_url_notifications { |
||
330 | state_entry() { |
||
331 | // DEBUG |
||
332 | llOwnerSay("[Control] Requesting URL..."); |
||
333 | llRequestURL(); |
||
334 | } |
||
335 | http_request(key id, string method, string body) { |
||
336 | if(method != URL_REQUEST_GRANTED) return; |
||
337 | URL = body; |
||
338 | // DEBUG |
||
339 | llOwnerSay("[Control] Got URL..."); |
||
340 | state unbind_notifications; |
||
341 | } |
||
342 | on_rez(integer num) { |
||
343 | llResetScript(); |
||
344 | } |
||
345 | changed(integer change) { |
||
42 | office | 346 | if((change & CHANGED_INVENTORY) || |
347 | (change & CHANGED_REGION_START) || |
||
8 | office | 348 | (change & CHANGED_OWNER)) { |
349 | llResetScript(); |
||
350 | } |
||
351 | } |
||
352 | } |
||
353 | |||
354 | state unbind_notifications { |
||
355 | state_entry() { |
||
356 | // DEBUG |
||
357 | llOwnerSay("[Control] Releasing notifications..."); |
||
358 | llInstantMessage( |
||
359 | (key)wasKeyValueGet( |
||
42 | office | 360 | "corrade", |
8 | office | 361 | configuration |
42 | office | 362 | ), |
8 | office | 363 | wasKeyValueEncode( |
364 | [ |
||
365 | "command", "notify", |
||
366 | "group", wasURLEscape( |
||
367 | wasKeyValueGet( |
||
42 | office | 368 | "group", |
8 | office | 369 | configuration |
370 | ) |
||
371 | ), |
||
372 | "password", wasURLEscape( |
||
373 | wasKeyValueGet( |
||
42 | office | 374 | "password", |
8 | office | 375 | configuration |
376 | ) |
||
377 | ), |
||
378 | "action", "remove", |
||
11 | office | 379 | "tag", wasURLEscape( |
380 | wasKeyValueGet( |
||
42 | office | 381 | "notification tag", |
11 | office | 382 | configuration |
383 | ) |
||
384 | ), |
||
8 | office | 385 | "callback", wasURLEscape(URL) |
386 | ] |
||
387 | ) |
||
388 | ); |
||
389 | llSetTimerEvent(60); |
||
390 | } |
||
391 | http_request(key id, string method, string body) { |
||
392 | llHTTPResponse(id, 200, "OK"); |
||
393 | if(wasKeyValueGet("command", body) != "notify" || |
||
394 | wasKeyValueGet("success", body) != "True") { |
||
395 | // DEBUG |
||
42 | office | 396 | llOwnerSay("[Control] Unable to release tag: " + |
8 | office | 397 | wasURLUnescape( |
398 | wasKeyValueGet("error", body) |
||
399 | ) |
||
400 | ); |
||
401 | llResetScript(); |
||
402 | } |
||
403 | state bind_notifications; |
||
404 | } |
||
405 | timer() { |
||
406 | llOwnerSay("[Control] Timeout releasing notifications"); |
||
407 | llResetScript(); |
||
408 | } |
||
409 | on_rez(integer num) { |
||
410 | llResetScript(); |
||
411 | } |
||
412 | changed(integer change) { |
||
42 | office | 413 | if((change & CHANGED_INVENTORY) || |
414 | (change & CHANGED_REGION_START) || |
||
8 | office | 415 | (change & CHANGED_OWNER)) { |
416 | llResetScript(); |
||
417 | } |
||
418 | } |
||
419 | state_exit() { |
||
420 | llSetTimerEvent(0); |
||
421 | } |
||
422 | } |
||
423 | |||
424 | state bind_notifications { |
||
425 | state_entry() { |
||
426 | // DEBUG |
||
427 | llOwnerSay("[Control] Binding to notifications..."); |
||
428 | llInstantMessage( |
||
429 | wasKeyValueGet( |
||
42 | office | 430 | "corrade", |
8 | office | 431 | configuration |
42 | office | 432 | ), |
8 | office | 433 | wasKeyValueEncode( |
434 | [ |
||
435 | "command", "notify", |
||
436 | "group", wasURLEscape( |
||
437 | wasKeyValueGet( |
||
42 | office | 438 | "group", |
8 | office | 439 | configuration |
440 | ) |
||
441 | ), |
||
442 | "password", wasURLEscape( |
||
443 | wasKeyValueGet( |
||
42 | office | 444 | "password", |
8 | office | 445 | configuration |
446 | ) |
||
447 | ), |
||
448 | "action", "add", |
||
449 | "type", wasURLEscape( |
||
450 | wasListToCSV( |
||
451 | notifications |
||
452 | ) |
||
453 | ), |
||
454 | "URL", wasURLEscape(URL), |
||
11 | office | 455 | "tag", wasURLEscape( |
456 | wasKeyValueGet( |
||
42 | office | 457 | "notification tag", |
11 | office | 458 | configuration |
459 | ) |
||
460 | ), |
||
8 | office | 461 | "callback", wasURLEscape(URL) |
462 | ] |
||
463 | ) |
||
464 | ); |
||
465 | llSetTimerEvent(60); |
||
466 | } |
||
467 | http_request(key id, string method, string body) { |
||
468 | llHTTPResponse(id, 200, "OK"); |
||
469 | if(wasKeyValueGet("command", body) != "notify" || |
||
470 | wasKeyValueGet("success", body) != "True") { |
||
471 | // DEBUG |
||
42 | office | 472 | llOwnerSay("[Control] Unable to bind notifications: " + |
8 | office | 473 | wasURLUnescape( |
474 | wasKeyValueGet("error", body) |
||
475 | ) |
||
476 | ); |
||
477 | llResetScript(); |
||
478 | } |
||
42 | office | 479 | state version_check; |
8 | office | 480 | } |
481 | timer() { |
||
482 | llOwnerSay("[Control] Timeout binding notifications"); |
||
483 | llResetScript(); |
||
484 | } |
||
485 | on_rez(integer num) { |
||
486 | llResetScript(); |
||
487 | } |
||
488 | changed(integer change) { |
||
42 | office | 489 | if((change & CHANGED_INVENTORY) || |
490 | (change & CHANGED_REGION_START) || |
||
8 | office | 491 | (change & CHANGED_OWNER)) { |
492 | llResetScript(); |
||
493 | } |
||
494 | } |
||
495 | state_exit() { |
||
496 | llSetTimerEvent(0); |
||
497 | } |
||
498 | } |
||
499 | |||
42 | office | 500 | state version_check { |
8 | office | 501 | state_entry() { |
502 | // DEBUG |
||
503 | llOwnerSay("[Control] Checking version..."); |
||
504 | llInstantMessage( |
||
505 | wasKeyValueGet( |
||
506 | "corrade", |
||
507 | configuration |
||
508 | ), |
||
509 | wasKeyValueEncode( |
||
510 | [ |
||
511 | "command", "version", |
||
512 | "group", wasURLEscape( |
||
513 | wasKeyValueGet( |
||
42 | office | 514 | "group", |
8 | office | 515 | configuration |
516 | ) |
||
517 | ), |
||
518 | "password", wasURLEscape( |
||
519 | wasKeyValueGet( |
||
42 | office | 520 | "password", |
8 | office | 521 | configuration |
522 | ) |
||
523 | ), |
||
524 | "callback", wasURLEscape(URL) |
||
525 | ] |
||
526 | ) |
||
527 | ); |
||
528 | llSetTimerEvent(60); |
||
529 | } |
||
530 | http_request(key id, string method, string body) { |
||
531 | llHTTPResponse(id, 200, "OK"); |
||
532 | llSetTimerEvent(0); |
||
42 | office | 533 | |
8 | office | 534 | if(wasKeyValueGet("success", body) != "True") { |
535 | llOwnerSay("[Control] Version check failed..."); |
||
536 | return; |
||
537 | } |
||
42 | office | 538 | |
8 | office | 539 | list v = llParseString2List( |
540 | wasKeyValueGet( |
||
541 | "data", |
||
542 | body |
||
543 | ), |
||
544 | ["."], |
||
545 | [] |
||
546 | ); |
||
547 | integer receivedVersion = (integer)(llList2String(v, 0) + llList2String(v, 1)); |
||
548 | v = llParseString2List( |
||
549 | wasKeyValueGet( |
||
550 | "version", |
||
551 | configuration |
||
552 | ), |
||
553 | ["."], |
||
554 | [] |
||
555 | ); |
||
556 | integer notecardVersion = (integer)(llList2String(v, 0) + llList2String(v, 1)); |
||
557 | if(receivedVersion < notecardVersion) { |
||
558 | llOwnerSay("[Control] Version is incompatible! You need a Corrade of at least version: " + |
||
559 | wasKeyValueGet( |
||
560 | "version", |
||
561 | configuration |
||
562 | ) + |
||
11 | office | 563 | " for this template." |
8 | office | 564 | ); |
565 | compatible = FALSE; |
||
566 | return; |
||
567 | } |
||
42 | office | 568 | |
569 | // Add the URL to the configuration so it can be used for all components. |
||
570 | configuration = wasKeyValueSet("URL", URL, configuration); |
||
571 | |||
8 | office | 572 | // DEBUG |
573 | llOwnerSay("[Control] Version is compatible!"); |
||
574 | compatible = TRUE; |
||
42 | office | 575 | |
576 | state serve_configuration; |
||
8 | office | 577 | } |
578 | timer() { |
||
579 | llOwnerSay("[Control] Timeout checking version..."); |
||
580 | llResetScript(); |
||
581 | } |
||
582 | on_rez(integer num) { |
||
583 | llResetScript(); |
||
584 | } |
||
585 | changed(integer change) { |
||
42 | office | 586 | if((change & CHANGED_INVENTORY) || |
587 | (change & CHANGED_REGION_START) || |
||
8 | office | 588 | (change & CHANGED_OWNER)) { |
589 | llResetScript(); |
||
590 | } |
||
591 | } |
||
592 | state_exit() { |
||
593 | llSetTimerEvent(0); |
||
594 | } |
||
595 | } |
||
42 | office | 596 | |
597 | state serve_configuration { |
||
598 | state_entry() { |
||
599 | // DEBUG |
||
600 | llOwnerSay("[Control] Serving configuration and passing callbacks..."); |
||
601 | } |
||
602 | http_request(key id, string method, string body) { |
||
603 | llHTTPResponse(id, 200, "OK"); |
||
604 | |||
605 | if(wasKeyValueGet("command", body) != "") { |
||
606 | llMessageLinked(LINK_THIS, 0, body, "callback"); |
||
607 | return; |
||
608 | } |
||
609 | |||
610 | // Check if this group message is from Corrade and passed through Discord. |
||
611 | if(wasKeyValueGet("type", body) == "group" && |
||
612 | llToUpper(wasKeyValueGet("agent", body)) == llToUpper(wasKeyValueGet("corrade", configuration)) && |
||
613 | llSubStringIndex(wasURLUnescape(wasKeyValueGet("message", body)), "[Discord]:") != -1) { |
||
614 | |||
615 | // Split message in Discord discriminator and message body. |
||
616 | list messageSplit = llParseString2List( |
||
617 | wasURLUnescape( |
||
618 | wasKeyValueGet("message", body) |
||
619 | ), |
||
620 | ["[Discord]:"], |
||
621 | [] |
||
622 | ); |
||
623 | |||
624 | // Retrive the Discord discriminator. |
||
625 | string did = llStringTrim( |
||
626 | llList2String( |
||
627 | messageSplit, |
||
628 | |||
629 | ), |
||
630 | STRING_TRIM |
||
631 | ); |
||
632 | |||
633 | |||
634 | // Retrieve a list of Discord discriminator that are allowed to send administrative commands. |
||
635 | list admins = wasCSVToList(wasKeyValueGet("discord admin", configuration)); |
||
636 | |||
637 | // If the sender is not amongst the administrative Discord discriminators, then strip the agent details. |
||
638 | if(llListFindList(admins, [ did ]) == -1) { |
||
639 | // DEBUG |
||
640 | llOwnerSay("[Control] Non admin, issuing command, strip the agent details from the command."); |
||
641 | |||
642 | body = wasKeyValueDelete("firstname", body); |
||
643 | body = wasKeyValueDelete("lastname", body); |
||
644 | body = wasKeyValueDelete("agent", body); |
||
645 | } |
||
646 | |||
647 | // Pack the message back without the Discord discriminator identifier. |
||
648 | body = wasKeyValueSet( |
||
649 | "message", |
||
650 | wasURLEscape( |
||
651 | llStringTrim( |
||
652 | llList2String( |
||
653 | messageSplit, |
||
654 | 1 |
||
655 | ), |
||
656 | STRING_TRIM |
||
657 | ) |
||
658 | ), |
||
659 | body |
||
660 | ); |
||
661 | } |
||
662 | |||
663 | llMessageLinked(LINK_THIS, 0, body, "notification"); |
||
664 | } |
||
665 | link_message(integer sender, integer num, string message, key id) { |
||
666 | if(message != "configuration") return; |
||
667 | |||
668 | llMessageLinked(LINK_THIS, 0, configuration, "configuration"); |
||
669 | } |
||
670 | on_rez(integer num) { |
||
671 | llResetScript(); |
||
672 | } |
||
673 | changed(integer change) { |
||
674 | if((change & CHANGED_INVENTORY) || |
||
675 | (change & CHANGED_REGION_START) || |
||
676 | (change & CHANGED_OWNER)) { |
||
677 | llResetScript(); |
||
678 | } |
||
679 | } |
||
680 | state_exit() { |
||
681 | llSetTimerEvent(0); |
||
682 | } |
||
683 | } |