corrade-lsl-templates – Blame information for rev 29

Subversion Repositories:
Rev:
Rev Author Line No. Line
4 office 1 ///////////////////////////////////////////////////////////////////////////
29 office 2 // Copyright (C) Wizardry and Steamworks 2014 - License: CC BY 2.0 //
4 office 3 ///////////////////////////////////////////////////////////////////////////
4 //
5 // This is an automatic teleporter, sitter and animator for the Corrade
6 // Second Life / OpenSim bot. You can find more details about the bot
7 // by following the URL: http://was.fm/secondlife/scripted_agents/corrade
8 //
9 // The sit script works together with a "configuration" notecard and an
10 // animation that must both be placed in the same primitive as this script.
11 // The purpose of this script is to demonstrate sitting with Corrade and
29 office 12 // you are free to use, change, and commercialize it under the CC BY 2.0
13 // license at: https://creativecommons.org/licenses/by/2.0
4 office 14 //
15 ///////////////////////////////////////////////////////////////////////////
16  
17 ///////////////////////////////////////////////////////////////////////////
29 office 18 // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 //
4 office 19 ///////////////////////////////////////////////////////////////////////////
20 string wasKeyValueGet(string k, string data) {
21 if(llStringLength(data) == 0) return "";
22 if(llStringLength(k) == 0) return "";
23 list a = llParseString2List(data, ["&", "="], []);
24 integer i = llListFindList(a, [ k ]);
25 if(i != -1) return llList2String(a, i+1);
26 return "";
27 }
28  
29 ///////////////////////////////////////////////////////////////////////////
29 office 30 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
4 office 31 ///////////////////////////////////////////////////////////////////////////
32 string wasKeyValueEncode(list data) {
33 list k = llList2ListStrided(data, 0, -1, 2);
34 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
35 data = [];
36 do {
37 data += llList2String(k, 0) + "=" + llList2String(v, 0);
38 k = llDeleteSubList(k, 0, 0);
39 v = llDeleteSubList(v, 0, 0);
40 } while(llGetListLength(k) != 0);
41 return llDumpList2String(data, "&");
42 }
43  
44 ///////////////////////////////////////////////////////////////////////////
29 office 45 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
4 office 46 ///////////////////////////////////////////////////////////////////////////
47 integer wasListCountExclude(list input, list exclude) {
48 if(llGetListLength(input) == 0) return 0;
49 if(llListFindList(exclude, (list)llList2String(input, 0)) == -1)
50 return 1 + wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
51 return wasListCountExclude(llDeleteSubList(input, 0, 0), exclude);
52 }
53  
54 ///////////////////////////////////////////////////////////////////////////
29 office 55 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
4 office 56 ///////////////////////////////////////////////////////////////////////////
57 // escapes a string in conformance with RFC1738
58 string wasURLEscape(string i) {
59 string o = "";
60 do {
61 string c = llGetSubString(i, 0, 0);
62 i = llDeleteSubString(i, 0, 0);
63 if(c == "") jump continue;
64 if(c == " ") {
65 o += "+";
66 jump continue;
67 }
68 if(c == "\n") {
69 o += "%0D" + llEscapeURL(c);
70 jump continue;
71 }
72 o += llEscapeURL(c);
73 @continue;
74 } while(i != "");
75 return o;
76 }
77  
78 ///////////////////////////////////////////////////////////////////////////
29 office 79 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
4 office 80 ///////////////////////////////////////////////////////////////////////////
81 // unescapes a string in conformance with RFC1738
82 string wasURLUnescape(string i) {
83 return llUnescapeURL(
84 llDumpList2String(
85 llParseString2List(
86 llDumpList2String(
87 llParseString2List(
88 i,
89 ["+"],
90 []
91 ),
92 " "
93 ),
94 ["%0D%0A"],
95 []
96 ),
97 "\n"
98 )
99 );
100 }
101  
102 // corrade data
103 string CORRADE = "";
104 string GROUP = "";
105 string PASSWORD = "";
106 string PUNISHMENT = "";
107 list SPLIT = [];
108 list ANNOUNCE = [];
109  
110 // for holding the callback URL
111 string callback = "";
112  
113 // for notecard reading
114 integer line = 0;
115  
116 // key-value data will be read into this list
117 list tuples = [];
118 // blacklisted words will be here
119 list badwords = [];
120  
121 default {
122 state_entry() {
123 if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) {
124 llOwnerSay("Sorry, could not find a configuration inventory notecard.");
125 return;
126 }
127 // DEBUG
128 llOwnerSay("Reading configuration file...");
129 llGetNotecardLine("configuration", line);
130 }
131 dataserver(key id, string data) {
132 if(data == EOF) {
133 // invariant, length(tuples) % 2 == 0
134 if(llGetListLength(tuples) % 2 != 0) {
135 llOwnerSay("Error in configuration notecard.");
136 return;
137 }
138 CORRADE = llList2String(
139 tuples,
140 llListFindList(
141 tuples,
142 [
143 "corrade"
144 ]
145 )
146 +1);
147 if(CORRADE == "") {
148 llOwnerSay("Error in configuration notecard: corrade");
149 return;
150 }
151 GROUP = llList2String(
152 tuples,
153 llListFindList(
154 tuples,
155 [
156 "group"
157 ]
158 )
159 +1);
160 if(GROUP == "") {
161 llOwnerSay("Error in configuration notecard: password");
162 return;
163 }
164 PASSWORD = llList2String(
165 tuples,
166 llListFindList(
167 tuples,
168 [
169 "password"
170 ]
171 )
172 +1);
173 if(PASSWORD == "") {
174 llOwnerSay("Error in configuration notecard: password");
175 return;
176 }
177 PUNISHMENT = llList2String(
178 tuples,
179 llListFindList(
180 tuples,
181 [
182 "punishment"
183 ]
184 )
185 +1);
186 if(PUNISHMENT == "") {
187 llOwnerSay("Error in configuration notecard: punishment");
188 return;
189 }
190 string split = llList2String(
191 tuples,
192 llListFindList(
193 tuples,
194 [
195 "split"
196 ]
197 )
198 +1
199 );
200 do {
201 SPLIT += llGetSubString(split, 0, 0);
202 split = llDeleteSubString(split, 0, 0);
203 } while(llStringLength(split) != 0);
204 if(SPLIT == []) {
205 llOwnerSay("Error in configuration notecard: split");
206 return;
207 }
208 ANNOUNCE = llCSV2List(
209 llList2String(
210 tuples,
211 llListFindList(
212 tuples,
213 [
214 "announce"
215 ]
216 )
217 +1
218 )
219 );
220 if(ANNOUNCE == []) {
221 llOwnerSay("Error in configuration notecard: announce");
222 return;
223 }
224 // DEBUG
225 llOwnerSay("Read configuration notecard...");
226 state words;
227 }
228 if(data == "") jump continue;
229 integer i = llSubStringIndex(data, "#");
230 if(i != -1) data = llDeleteSubString(data, i, -1);
231 list o = llParseString2List(data, ["="], []);
232 // get rid of starting and ending quotes
233 string k = llDumpList2String(
234 llParseString2List(
235 llStringTrim(
236 llList2String(
237 o,
238  
239 ),
240 STRING_TRIM),
241 ["\""], []
242 ), "\"");
243 string v = llDumpList2String(
244 llParseString2List(
245 llStringTrim(
246 llList2String(
247 o,
248 1
249 ),
250 STRING_TRIM),
251 ["\""], []
252 ), "\"");
253 if(k == "" || v == "") jump continue;
254 tuples += k;
255 tuples += v;
256 @continue;
257 llGetNotecardLine("configuration", ++line);
258 }
259 on_rez(integer num) {
260 llResetScript();
261 }
262 changed(integer change) {
263 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
264 llResetScript();
265 }
266 }
267 }
268  
269 state words {
270 state_entry() {
271 if(llGetInventoryType("badwords") != INVENTORY_NOTECARD) {
272 llOwnerSay("Sorry, could not find a blacklist inventory notecard.");
273 return;
274 }
275 // DEBUG
276 llOwnerSay("Reading badwords notecard...");
277 line = 0;
278 llGetNotecardLine("badwords", line);
279 }
280 dataserver(key id, string data) {
281 if(data == EOF) {
282 // DEBUG
283 llOwnerSay("Read badwords notcard...");
284 state url;
285 }
286 if(data == "") jump continue;
287 badwords += data;
288 @continue;
289 llGetNotecardLine("badwords", ++line);
290 }
291 on_rez(integer num) {
292 llResetScript();
293 }
294 changed(integer change) {
295 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
296 llResetScript();
297 }
298 }
299 }
300  
301 state url {
302 state_entry() {
303 // DEBUG
304 llOwnerSay("Requesting URL...");
305 llRequestURL();
306 }
307 http_request(key id, string method, string body) {
308 if(method != URL_REQUEST_GRANTED) return;
309 callback = body;
310 // DEBUG
311 llOwnerSay("Got URL...");
312 state detect;
313 }
314 on_rez(integer num) {
315 llResetScript();
316 }
317 changed(integer change) {
318 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
319 llResetScript();
320 }
321 }
322 }
323  
324 state detect {
325 state_entry() {
326 // DEBUG
327 llOwnerSay("Detecting if Corrade is online...");
328 llSetTimerEvent(5);
329 }
330 timer() {
331 llRequestAgentData((key)CORRADE, DATA_ONLINE);
332 }
333 dataserver(key id, string data) {
334 if(data != "1") {
335 // DEBUG
336 llOwnerSay("Corrade is not online, sleeping...");
337 llSetTimerEvent(30);
338 return;
339 }
340 state notify;
341 }
342 on_rez(integer num) {
343 llResetScript();
344 }
345 changed(integer change) {
346 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
347 llResetScript();
348 }
349 }
350 }
351  
352 state notify {
353 state_entry() {
354 // DEBUG
355 llOwnerSay("Binding to the group chat notification...");
356 llInstantMessage(
357 (key)CORRADE,
358 wasKeyValueEncode(
359 [
360 "command", "notify",
361 "group", wasURLEscape(GROUP),
362 "password", wasURLEscape(PASSWORD),
363 "action", "set",
364 "type", "group",
365 "URL", wasURLEscape(callback),
366 "callback", wasURLEscape(callback)
367 ]
368 )
369 );
370 }
371 http_request(key id, string method, string body) {
372 llHTTPResponse(id, 200, "OK");
373 if(wasKeyValueGet("command", body) != "notify" ||
374 wasKeyValueGet("success", body) != "True") {
375 // DEBUG
376 llOwnerSay("Failed to bind to the group chat notification...");
377 state detect;
378 }
379 // DEBUG
380 llOwnerSay("Permission notification installed...");
381 state main;
382 }
383 on_rez(integer num) {
384 llResetScript();
385 }
386 changed(integer change) {
387 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
388 llResetScript();
389 }
390 }
391 }
392  
393 state main {
394 state_entry() {
395 // DEBUG
396 llOwnerSay("Waiting for badwords...");
397 }
398 http_request(key id, string method, string body) {
399 llHTTPResponse(id, 200, "OK");
400  
401 // split the input
402 list input = llParseString2List(
403 wasURLUnescape(
404 wasKeyValueGet(
405 "message",
406 body
407 )
408 ),
409 SPLIT, []);
410  
411 // now find badwords
412 string badword = "";
413 do {
414 badword = llList2String(input, 0);
415 if(llListFindList(badwords, (list)badword) != -1) jump punish;
416 input = llDeleteSubList(input, 0, 0);
417 } while(llGetListLength(input) != 0);
418 return;
419  
420 @punish;
421  
422 string firstname = wasURLUnescape(wasKeyValueGet("firstname", body));
423 string lastname = wasURLUnescape(wasKeyValueGet("lastname", body));
424  
425 if(PUNISHMENT == "eject") {
426 llOwnerSay("Ejecting: " + firstname + " " + lastname);
427 llInstantMessage((key)CORRADE,
428 wasKeyValueEncode(
429 [
430 "command", "eject",
431 "group", wasURLEscape(GROUP),
432 "password", wasURLEscape(PASSWORD),
433 "firstname", wasURLEscape(firstname),
434 "lastname", wasURLEscape(lastname)
435 ]
436 )
437 );
438 jump announce;
439 }
440  
441 llOwnerSay("Muting: " + firstname + " " + lastname);
442 llInstantMessage((key)CORRADE,
443 wasKeyValueEncode(
444 [
445 "command", "moderate",
446 "group", wasURLEscape(GROUP),
447 "password", wasURLEscape(PASSWORD),
448 "firstname", wasURLEscape(firstname),
449 "lastname", wasURLEscape(lastname),
450 "type", "text",
451 "silence", "true"
452 ]
453 )
454 );
455  
456 @announce;
457  
458 // Go through the list of avatars to announce and
459 // tell them who has been ajected and for what word
460 integer i = llGetListLength(ANNOUNCE)-1;
461 do {
462 string full = llList2String(ANNOUNCE, i);
463 list name = llParseString2List(full, [" "], []);
464 llInstantMessage((key)CORRADE,
465 wasKeyValueEncode(
466 [
467 "command", "tell",
468 "group", wasURLEscape(GROUP),
469 "password", wasURLEscape(PASSWORD),
470 "entity", "avatar",
471 "firstname", wasURLEscape(llList2String(name, 0)),
472 "lastname", wasURLEscape(llList2String(name, 1)),
473 "message", wasURLEscape(
474 "The avatar " +
475 firstname +
476 " " +
477 lastname +
478 " was ejecteded from: " +
479 GROUP + " for saying: \"" +
480 badword + "\"."
481 )
482 ]
483 )
484 );
485 } while(--i>-1);
486 }
487 on_rez(integer num) {
488 llResetScript();
489 }
490 changed(integer change) {
491 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
492 llResetScript();
493 }
494 }
495 }