corrade-lsl-templates – Diff between revs 41 and 42

Subversion Repositories:
Rev:
Show entire fileIgnore whitespace
Rev 41 Rev 42
Line 1... Line 1...
1 /////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2016 - License: CC BY 2.0 // 2 // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 //
3 /////////////////////////////////////////////////////////////////////////// 3 ///////////////////////////////////////////////////////////////////////////
4 // 4 //
5 // An eggdrop-like group bot using Corrade. 5 // An eggdrop-like group bot using Corrade.
6 // 6 //
7 /////////////////////////////////////////////////////////////////////////// 7 ///////////////////////////////////////////////////////////////////////////
Line 15... Line 15...
15 list a = llParseStringKeepNulls(data, ["&", "="], []); 15 list a = llParseStringKeepNulls(data, ["&", "="], []);
16 integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]); 16 integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]);
17 if(i != -1) return llList2String(a, 2*i+1); 17 if(i != -1) return llList2String(a, 2*i+1);
18 return ""; 18 return "";
19 } 19 }
20 20  
-   21 ///////////////////////////////////////////////////////////////////////////
-   22 // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 //
-   23 ///////////////////////////////////////////////////////////////////////////
-   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  
21 /////////////////////////////////////////////////////////////////////////// 41 ///////////////////////////////////////////////////////////////////////////
22 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 // 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 //
23 /////////////////////////////////////////////////////////////////////////// 65 ///////////////////////////////////////////////////////////////////////////
24 string wasKeyValueEncode(list data) { 66 string wasKeyValueEncode(list data) {
25 list k = llList2ListStrided(data, 0, -1, 2); 67 list k = llList2ListStrided(data, 0, -1, 2);
26 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); 68 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
27 data = []; 69 data = [];
Line 32... Line 74...
32 } while(llGetListLength(k) != 0); 74 } while(llGetListLength(k) != 0);
33 return llDumpList2String(data, "&"); 75 return llDumpList2String(data, "&");
34 } 76 }
Line 35... Line 77...
35   77  
36 /////////////////////////////////////////////////////////////////////////// 78 ///////////////////////////////////////////////////////////////////////////
37 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // 79 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
38 /////////////////////////////////////////////////////////////////////////// 80 ///////////////////////////////////////////////////////////////////////////
39 // escapes a string in conformance with RFC1738 81 // escapes a string in conformance with RFC1738
40 string wasURLEscape(string i) { 82 string wasURLEscape(string i) {
41 string o = ""; 83 string o = "";
Line 56... Line 98...
56 } while(i != ""); 98 } while(i != "");
57 return o; 99 return o;
58 } 100 }
Line 59... Line 101...
59   101  
60 /////////////////////////////////////////////////////////////////////////// 102 ///////////////////////////////////////////////////////////////////////////
61 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // 103 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
62 /////////////////////////////////////////////////////////////////////////// 104 ///////////////////////////////////////////////////////////////////////////
63 // unescapes a string in conformance with RFC1738 105 // unescapes a string in conformance with RFC1738
64 string wasURLUnescape(string i) { 106 string wasURLUnescape(string i) {
65 return llUnescapeURL( 107 return llUnescapeURL(
66 llDumpList2String( 108 llDumpList2String(
67 llParseString2List( 109 llParseString2List(
68 llDumpList2String( 110 llDumpList2String(
69 llParseString2List( 111 llParseString2List(
70 i, 112 i,
71 ["+"], 113 ["+"],
72 [] 114 []
73 ), 115 ),
74 " " 116 " "
75 ), 117 ),
76 ["%0D%0A"], 118 ["%0D%0A"],
77 [] 119 []
78 ), 120 ),
79 "\n" 121 "\n"
80 ) 122 )
81 ); 123 );
Line 82... Line 124...
82 } 124 }
83   125  
84 /////////////////////////////////////////////////////////////////////////// 126 ///////////////////////////////////////////////////////////////////////////
85 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // 127 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
86 /////////////////////////////////////////////////////////////////////////// 128 ///////////////////////////////////////////////////////////////////////////
87 string wasListToCSV(list l) { 129 string wasListToCSV(list l) {
88 list v = []; 130 list v = [];
89 do { 131 do {
90 string a = llDumpList2String( 132 string a = llDumpList2String(
91 llParseStringKeepNulls( 133 llParseStringKeepNulls(
92 llList2String( 134 llList2String(
93 l, 135 l,
94 0 136 0
95 ), 137 ),
96 ["\""], 138 ["\""],
97 [] 139 []
98 ), 140 ),
99 "\"\"" 141 "\"\""
100 ); 142 );
101 if(llParseStringKeepNulls( 143 if(llParseStringKeepNulls(
102 a, 144 a,
103 [" ", ",", "\n", "\""], [] 145 [" ", ",", "\n", "\""], []
104 ) != 146 ) !=
105 (list) a 147 (list) a
106 ) a = "\"" + a + "\""; 148 ) a = "\"" + a + "\"";
107 v += a; 149 v += a;
108 l = llDeleteSubList(l, 0, 0); 150 l = llDeleteSubList(l, 0, 0);
109 } while(l != []); 151 } while(l != []);
Line -... Line 152...
-   152 return llDumpList2String(v, ",");
-   153 }
-   154  
-   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
110 return llDumpList2String(v, ","); 191 return l + m;
111 } 192 }
112   193  
113 // for notecard reading 194 // for notecard reading
114 integer line = 0; 195 integer line = 0;
115 196  
116 // key-value data will be read into this list 197 // key-value data will be read into this list
117 list tuples = []; 198 list tuples = [];
Line 142... Line 223...
142 return; 223 return;
143 } 224 }
144 key CORRADE = llList2Key( 225 key CORRADE = llList2Key(
145 tuples, 226 tuples,
146 llListFindList( 227 llListFindList(
147 tuples, 228 tuples,
148 [ 229 [
149 "corrade" 230 "corrade"
150 ] 231 ]
151 ) 232 )
152 +1); 233 +1);
Line 155... Line 236...
155 return; 236 return;
156 } 237 }
157 string GROUP = llList2String( 238 string GROUP = llList2String(
158 tuples, 239 tuples,
159 llListFindList( 240 llListFindList(
160 tuples, 241 tuples,
161 [ 242 [
162 "group" 243 "group"
163 ] 244 ]
164 ) 245 )
165 +1); 246 +1);
Line 168... Line 249...
168 return; 249 return;
169 } 250 }
170 string PASSWORD = llList2String( 251 string PASSWORD = llList2String(
171 tuples, 252 tuples,
172 llListFindList( 253 llListFindList(
173 tuples, 254 tuples,
174 [ 255 [
175 "password" 256 "password"
176 ] 257 ]
177 ) 258 )
178 +1); 259 +1);
Line 181... Line 262...
181 return; 262 return;
182 } 263 }
183 string VERSION = llList2String( 264 string VERSION = llList2String(
184 tuples, 265 tuples,
185 llListFindList( 266 llListFindList(
186 tuples, 267 tuples,
187 [ 268 [
188 "version" 269 "version"
189 ] 270 ]
190 ) 271 )
191 +1); 272 +1);
Line 199... Line 280...
199 // GC 280 // GC
200 tuples = []; 281 tuples = [];
201 state request_url_notifications; 282 state request_url_notifications;
202 } 283 }
203 if(data == "") jump continue; 284 if(data == "") jump continue;
-   285 // No support for inline comments for this one! Needs parsing!
204 integer i = llSubStringIndex(data, "#"); 286 integer i = llSubStringIndex(data, "#");
205 if(i != -1) data = llDeleteSubString(data, i, -1); 287 if(i == 0) data = llDeleteSubString(data, i, -1);
206 list o = llParseString2List(data, ["="], []); 288 list o = llParseString2List(data, ["="], []);
207 // get rid of starting and ending quotes 289 // get rid of starting and ending quotes
208 string k = llDumpList2String( 290 string k = llDumpList2String(
209 llParseString2List( 291 llParseString2List(
210 llStringTrim( 292 llStringTrim(
211 llList2String( 293 llList2String(
212 o, 294 o,
213 0 295 0
214 ), 296 ),
215 STRING_TRIM), 297 STRING_TRIM),
216 ["\""], [] 298 ["\""], []
217 ), "\""); 299 ), "\"");
218 string v = llDumpList2String( 300 string v = llDumpList2String(
219 llParseString2List( 301 llParseString2List(
220 llStringTrim( 302 llStringTrim(
221 llList2String( 303 llList2String(
222 o, 304 o,
223 1 305 1
224 ), 306 ),
225 STRING_TRIM), 307 STRING_TRIM),
226 ["\""], [] 308 ["\""], []
227 ), "\""); 309 ), "\"");
228 if(k == "" || v == "") jump continue; 310 if(k == "" || v == "") jump continue;
229 tuples += k; 311 tuples += k;
230 tuples += v; 312 tuples += v;
Line 259... Line 341...
259 } 341 }
260 on_rez(integer num) { 342 on_rez(integer num) {
261 llResetScript(); 343 llResetScript();
262 } 344 }
263 changed(integer change) { 345 changed(integer change) {
264 if((change & CHANGED_INVENTORY) || 346 if((change & CHANGED_INVENTORY) ||
265 (change & CHANGED_REGION_START) || 347 (change & CHANGED_REGION_START) ||
266 (change & CHANGED_OWNER)) { 348 (change & CHANGED_OWNER)) {
267 llResetScript(); 349 llResetScript();
268 } 350 }
269 } 351 }
270 } 352 }
Line 273... Line 355...
273 state_entry() { 355 state_entry() {
274 // DEBUG 356 // DEBUG
275 llOwnerSay("[Control] Releasing notifications..."); 357 llOwnerSay("[Control] Releasing notifications...");
276 llInstantMessage( 358 llInstantMessage(
277 (key)wasKeyValueGet( 359 (key)wasKeyValueGet(
278 "corrade", 360 "corrade",
279 configuration 361 configuration
280 ), 362 ),
281 wasKeyValueEncode( 363 wasKeyValueEncode(
282 [ 364 [
283 "command", "notify", 365 "command", "notify",
284 "group", wasURLEscape( 366 "group", wasURLEscape(
285 wasKeyValueGet( 367 wasKeyValueGet(
286 "group", 368 "group",
287 configuration 369 configuration
288 ) 370 )
289 ), 371 ),
290 "password", wasURLEscape( 372 "password", wasURLEscape(
291 wasKeyValueGet( 373 wasKeyValueGet(
292 "password", 374 "password",
293 configuration 375 configuration
294 ) 376 )
295 ), 377 ),
296 "action", "remove", 378 "action", "remove",
297 "tag", wasURLEscape( 379 "tag", wasURLEscape(
298 wasKeyValueGet( 380 wasKeyValueGet(
299 "notification tag", 381 "notification tag",
300 configuration 382 configuration
301 ) 383 )
302 ), 384 ),
303 "callback", wasURLEscape(URL) 385 "callback", wasURLEscape(URL)
304 ] 386 ]
Line 309... Line 391...
309 http_request(key id, string method, string body) { 391 http_request(key id, string method, string body) {
310 llHTTPResponse(id, 200, "OK"); 392 llHTTPResponse(id, 200, "OK");
311 if(wasKeyValueGet("command", body) != "notify" || 393 if(wasKeyValueGet("command", body) != "notify" ||
312 wasKeyValueGet("success", body) != "True") { 394 wasKeyValueGet("success", body) != "True") {
313 // DEBUG 395 // DEBUG
314 llOwnerSay("[Control] Unable to release tag: " + 396 llOwnerSay("[Control] Unable to release tag: " +
315 wasURLUnescape( 397 wasURLUnescape(
316 wasKeyValueGet("error", body) 398 wasKeyValueGet("error", body)
317 ) 399 )
318 ); 400 );
319 llResetScript(); 401 llResetScript();
Line 326... Line 408...
326 } 408 }
327 on_rez(integer num) { 409 on_rez(integer num) {
328 llResetScript(); 410 llResetScript();
329 } 411 }
330 changed(integer change) { 412 changed(integer change) {
331 if((change & CHANGED_INVENTORY) || 413 if((change & CHANGED_INVENTORY) ||
332 (change & CHANGED_REGION_START) || 414 (change & CHANGED_REGION_START) ||
333 (change & CHANGED_OWNER)) { 415 (change & CHANGED_OWNER)) {
334 llResetScript(); 416 llResetScript();
335 } 417 }
336 } 418 }
337 state_exit() { 419 state_exit() {
Line 343... Line 425...
343 state_entry() { 425 state_entry() {
344 // DEBUG 426 // DEBUG
345 llOwnerSay("[Control] Binding to notifications..."); 427 llOwnerSay("[Control] Binding to notifications...");
346 llInstantMessage( 428 llInstantMessage(
347 wasKeyValueGet( 429 wasKeyValueGet(
348 "corrade", 430 "corrade",
349 configuration 431 configuration
350 ), 432 ),
351 wasKeyValueEncode( 433 wasKeyValueEncode(
352 [ 434 [
353 "command", "notify", 435 "command", "notify",
354 "group", wasURLEscape( 436 "group", wasURLEscape(
355 wasKeyValueGet( 437 wasKeyValueGet(
356 "group", 438 "group",
357 configuration 439 configuration
358 ) 440 )
359 ), 441 ),
360 "password", wasURLEscape( 442 "password", wasURLEscape(
361 wasKeyValueGet( 443 wasKeyValueGet(
362 "password", 444 "password",
363 configuration 445 configuration
364 ) 446 )
365 ), 447 ),
366 "action", "add", 448 "action", "add",
367 "type", wasURLEscape( 449 "type", wasURLEscape(
Line 370... Line 452...
370 ) 452 )
371 ), 453 ),
372 "URL", wasURLEscape(URL), 454 "URL", wasURLEscape(URL),
373 "tag", wasURLEscape( 455 "tag", wasURLEscape(
374 wasKeyValueGet( 456 wasKeyValueGet(
375 "notification tag", 457 "notification tag",
376 configuration 458 configuration
377 ) 459 )
378 ), 460 ),
379 "callback", wasURLEscape(URL) 461 "callback", wasURLEscape(URL)
380 ] 462 ]
Line 385... Line 467...
385 http_request(key id, string method, string body) { 467 http_request(key id, string method, string body) {
386 llHTTPResponse(id, 200, "OK"); 468 llHTTPResponse(id, 200, "OK");
387 if(wasKeyValueGet("command", body) != "notify" || 469 if(wasKeyValueGet("command", body) != "notify" ||
388 wasKeyValueGet("success", body) != "True") { 470 wasKeyValueGet("success", body) != "True") {
389 // DEBUG 471 // DEBUG
390 llOwnerSay("[Control] Unable to bind notifications: " + 472 llOwnerSay("[Control] Unable to bind notifications: " +
391 wasURLUnescape( 473 wasURLUnescape(
392 wasKeyValueGet("error", body) 474 wasKeyValueGet("error", body)
393 ) 475 )
394 ); 476 );
395 llResetScript(); 477 llResetScript();
396 } 478 }
397 state serve_configuration; 479 state version_check;
398 } 480 }
399 timer() { 481 timer() {
400 llOwnerSay("[Control] Timeout binding notifications"); 482 llOwnerSay("[Control] Timeout binding notifications");
401 llResetScript(); 483 llResetScript();
402 } 484 }
403 on_rez(integer num) { 485 on_rez(integer num) {
404 llResetScript(); 486 llResetScript();
405 } 487 }
406 changed(integer change) { 488 changed(integer change) {
407 if((change & CHANGED_INVENTORY) || 489 if((change & CHANGED_INVENTORY) ||
408 (change & CHANGED_REGION_START) || 490 (change & CHANGED_REGION_START) ||
409 (change & CHANGED_OWNER)) { 491 (change & CHANGED_OWNER)) {
410 llResetScript(); 492 llResetScript();
411 } 493 }
412 } 494 }
413 state_exit() { 495 state_exit() {
414 llSetTimerEvent(0); 496 llSetTimerEvent(0);
415 } 497 }
416 } 498 }
Line 417... Line 499...
417   499  
418 state serve_configuration { 500 state version_check {
419 state_entry() { 501 state_entry() {
420 // DEBUG 502 // DEBUG
421 llOwnerSay("[Control] Checking version..."); 503 llOwnerSay("[Control] Checking version...");
422 llInstantMessage( 504 llInstantMessage(
Line 427... Line 509...
427 wasKeyValueEncode( 509 wasKeyValueEncode(
428 [ 510 [
429 "command", "version", 511 "command", "version",
430 "group", wasURLEscape( 512 "group", wasURLEscape(
431 wasKeyValueGet( 513 wasKeyValueGet(
432 "group", 514 "group",
433 configuration 515 configuration
434 ) 516 )
435 ), 517 ),
436 "password", wasURLEscape( 518 "password", wasURLEscape(
437 wasKeyValueGet( 519 wasKeyValueGet(
438 "password", 520 "password",
439 configuration 521 configuration
440 ) 522 )
441 ), 523 ),
442 "callback", wasURLEscape(URL) 524 "callback", wasURLEscape(URL)
443 ] 525 ]
Line 446... Line 528...
446 llSetTimerEvent(60); 528 llSetTimerEvent(60);
447 } 529 }
448 http_request(key id, string method, string body) { 530 http_request(key id, string method, string body) {
449 llHTTPResponse(id, 200, "OK"); 531 llHTTPResponse(id, 200, "OK");
450 llSetTimerEvent(0); 532 llSetTimerEvent(0);
451 if(wasKeyValueGet("command", body) != "version") { -  
452 llMessageLinked(LINK_THIS, 0, body, "notification"); -  
453 return; -  
454 } -  
455 533  
456 if(wasKeyValueGet("success", body) != "True") { 534 if(wasKeyValueGet("success", body) != "True") {
457 llOwnerSay("[Control] Version check failed..."); 535 llOwnerSay("[Control] Version check failed...");
458 return; 536 return;
459 } 537 }
460 538  
461 list v = llParseString2List( 539 list v = llParseString2List(
462 wasKeyValueGet( 540 wasKeyValueGet(
463 "data", 541 "data",
464 body 542 body
465 ), 543 ),
Line 483... Line 561...
483 configuration 561 configuration
484 ) + 562 ) +
485 " for this template." 563 " for this template."
486 ); 564 );
487 compatible = FALSE; 565 compatible = FALSE;
488 //llReleaseURL(URL); -  
489 return; 566 return;
490 } 567 }
-   568  
-   569 // Add the URL to the configuration so it can be used for all components.
-   570 configuration = wasKeyValueSet("URL", URL, configuration);
-   571  
491 // DEBUG 572 // DEBUG
492 llOwnerSay("[Control] Version is compatible!"); 573 llOwnerSay("[Control] Version is compatible!");
493 compatible = TRUE; 574 compatible = TRUE;
494 //llReleaseURL(URL); -  
495 return; -  
496 } 575  
497 link_message(integer sender, integer num, string message, key id) { -  
498 if(message != "configuration") return; 576 state serve_configuration;
499 llMessageLinked(LINK_THIS, 0, configuration, "configuration"); -  
500 } 577 }
501 timer() { 578 timer() {
502 llOwnerSay("[Control] Timeout checking version..."); 579 llOwnerSay("[Control] Timeout checking version...");
503 llResetScript(); 580 llResetScript();
504 } 581 }
505 on_rez(integer num) { 582 on_rez(integer num) {
506 llResetScript(); 583 llResetScript();
507 } 584 }
508 changed(integer change) { 585 changed(integer change) {
-   586 if((change & CHANGED_INVENTORY) ||
-   587 (change & CHANGED_REGION_START) ||
-   588 (change & CHANGED_OWNER)) {
-   589 llResetScript();
-   590 }
-   591 }
-   592 state_exit() {
-   593 llSetTimerEvent(0);
-   594 }
-   595 }
-   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 0
-   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) {
509 if((change & CHANGED_INVENTORY) || 674 if((change & CHANGED_INVENTORY) ||
510 (change & CHANGED_REGION_START) || 675 (change & CHANGED_REGION_START) ||
511 (change & CHANGED_OWNER)) { 676 (change & CHANGED_OWNER)) {
512 llResetScript(); 677 llResetScript();
513 } 678 }
514 } 679 }
515 state_exit() { 680 state_exit() {