corrade-lsl-templates – Blame information for rev 42

Subversion Repositories:
Rev:
Rev Author Line No. Line
42 office 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2018 - License: GNU GPLv3 //
3 ///////////////////////////////////////////////////////////////////////////
4 //
5 // An instant message sending module for Corrade Eggdrop.
6 //
7 ///////////////////////////////////////////////////////////////////////////
8  
9 ///////////////////////////////////////////////////////////////////////////
10 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
11 ///////////////////////////////////////////////////////////////////////////
12 string wasKeyValueGet(string k, string data) {
13 if(llStringLength(data) == 0) return "";
14 if(llStringLength(k) == 0) return "";
15 list a = llParseStringKeepNulls(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) 2011 Wizardry and Steamworks - License: GNU GPLv3 //
38 ///////////////////////////////////////////////////////////////////////////
39 // http://was.fm/secondlife/wanderer
40 vector wasCirclePoint(float radius) {
41 float x = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
42 float y = llPow(-1, 1 + (integer) llFrand(2)) * llFrand(radius*2);
43 if(llPow(x,2) + llPow(y,2) <= llPow(radius,2))
44 return <x, y, 0>;
45 return wasCirclePoint(radius);
46 }
47  
48 ///////////////////////////////////////////////////////////////////////////
49 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
50 ///////////////////////////////////////////////////////////////////////////
51 // escapes a string in conformance with RFC1738
52 string wasURLEscape(string i) {
53 string o = "";
54 do {
55 string c = llGetSubString(i, 0, 0);
56 i = llDeleteSubString(i, 0, 0);
57 if(c == "") jump continue;
58 if(c == " ") {
59 o += "+";
60 jump continue;
61 }
62 if(c == "\n") {
63 o += "%0D" + llEscapeURL(c);
64 jump continue;
65 }
66 o += llEscapeURL(c);
67 @continue;
68 } while(i != "");
69 return o;
70 }
71  
72 ///////////////////////////////////////////////////////////////////////////
73 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
74 ///////////////////////////////////////////////////////////////////////////
75 list wasCSVToList(string csv) {
76 list l = [];
77 list s = [];
78 string m = "";
79 do {
80 string a = llGetSubString(csv, 0, 0);
81 csv = llDeleteSubString(csv, 0, 0);
82 if(a == ",") {
83 if(llList2String(s, -1) != "\"") {
84 l += m;
85 m = "";
86 jump continue;
87 }
88 m += a;
89 jump continue;
90 }
91 if(a == "\"" && llGetSubString(csv, 0, 0) == a) {
92 m += a;
93 csv = llDeleteSubString(csv, 0, 0);
94 jump continue;
95 }
96 if(a == "\"") {
97 if(llList2String(s, -1) != a) {
98 s += a;
99 jump continue;
100 }
101 s = llDeleteSubList(s, -1, -1);
102 jump continue;
103 }
104 m += a;
105 @continue;
106 } while(csv != "");
107 // postcondition: length(s) = 0
108 return l + m;
109 }
110  
111 ///////////////////////////////////////////////////////////////////////////
112 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
113 ///////////////////////////////////////////////////////////////////////////
114 string wasListToCSV(list l) {
115 list v = [];
116 do {
117 string a = llDumpList2String(
118 llParseStringKeepNulls(
119 llList2String(
120 l,
121  
122 ),
123 ["\""],
124 []
125 ),
126 "\"\""
127 );
128 if(llParseStringKeepNulls(
129 a,
130 [" ", ",", "\n", "\""], []
131 ) !=
132 (list) a
133 ) a = "\"" + a + "\"";
134 v += a;
135 l = llDeleteSubList(l, 0, 0);
136 } while(l != []);
137 return llDumpList2String(v, ",");
138 }
139  
140 ///////////////////////////////////////////////////////////////////////////
141 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
142 ///////////////////////////////////////////////////////////////////////////
143 // unescapes a string in conformance with RFC1738
144 string wasURLUnescape(string i) {
145 return llUnescapeURL(
146 llDumpList2String(
147 llParseString2List(
148 llDumpList2String(
149 llParseString2List(
150 i,
151 ["+"],
152 []
153 ),
154 " "
155 ),
156 ["%0D%0A"],
157 []
158 ),
159 "\n"
160 )
161 );
162 }
163  
164 ///////////////////////////////////////////////////////////////////////////
165 // Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3 //
166 ///////////////////////////////////////////////////////////////////////////
167 list wasSetIntersect(list a, list b) {
168 if(llGetListLength(a) == 0) return [];
169 string i = llList2String(a, 0);
170 a = llDeleteSubList(a, 0, 0);
171 if(llListFindList(b, (list)i) == -1)
172 return wasSetIntersect(a, b);
173 return i + wasSetIntersect(a, b);
174 }
175  
176 // configuration data
177 string configuration = "";
178 // store message over state.
179 string src_firstname = "";
180 string src_lastname = "";
181 string dst_firstname = "";
182 string dst_lastname = "";
183 string data = "";
184  
185 default {
186 state_entry() {
187 llOwnerSay("[IM] Starting module...");
188 llSetTimerEvent(10);
189 }
190 link_message(integer sender, integer num, string message, key id) {
191 if(id != "configuration") return;
192 llOwnerSay("[IM] Got configuration...");
193 configuration = message;
194 state listen_group;
195 }
196 timer() {
197 llOwnerSay("[IM] Requesting configuration...");
198 llMessageLinked(LINK_THIS, 0, "configuration", NULL_KEY);
199 }
200 on_rez(integer num) {
201 llResetScript();
202 }
203 changed(integer change) {
204 if((change & CHANGED_INVENTORY) ||
205 (change & CHANGED_REGION_START) ||
206 (change & CHANGED_OWNER)) {
207 llResetScript();
208 }
209 }
210 state_exit() {
211 llSetTimerEvent(0);
212 }
213 }
214  
215 state listen_group {
216 state_entry() {
217 // DEBUG
218 llOwnerSay("[IM] Waiting for group messages.");
219 }
220 link_message(integer sender, integer num, string message, key id) {
221 // We only care about notifications now.
222 if(id != "notification")
223 return;
224  
225 // This script only processes group notifications.
226 if(wasKeyValueGet("type", message) != "group" ||
227 (wasKeyValueGet("type", message) == "group" &&
228 wasURLUnescape(wasKeyValueGet("group", message)) !=
229 wasKeyValueGet("group", configuration)))
230 return;
231  
232 // Get the message sender.
233 src_firstname = wasURLUnescape(
234 wasKeyValueGet(
235 "firstname",
236 message
237 )
238 );
239  
240 src_lastname = wasURLUnescape(
241 wasKeyValueGet(
242 "lastname",
243 message
244 )
245 );
246  
247 // Get the sent message.
248 data = wasURLUnescape(
249 wasKeyValueGet(
250 "message",
251 message
252 )
253 );
254  
255 // Check if this is an eggdrop command.
256 if(llGetSubString(data, 0, 0) !=
257 wasKeyValueGet("command", configuration))
258 return;
259  
260 // Check if the command matches the current module.
261 list command = llParseString2List(data, [" "], []);
262 if(llList2String(command, 0) !=
263 wasKeyValueGet("command", configuration) + "im")
264 return;
265  
266 // Remove command.
267 command = llDeleteSubList(command, 0, 0);
268  
269 // Retrieve the first and last name to remind.
270 dst_firstname = llList2String(command, 0);
271 command = llDeleteSubList(command, 0, 0);
272 dst_lastname = llList2String(command, 0);
273 command = llDeleteSubList(command, 0, 0);
274  
275 if(llStringLength(dst_firstname) == 0 ||
276 llStringLength(dst_lastname) == 0) {
277 data = "Invalid avatar name, please use the full username!";
278 state tell;
279 }
280  
281 // Retrieve the message to remind of.
282 data = llDumpList2String(command, " ");
283 if(llStringLength(message) == 0) {
284 data = "No message to send supplied. . .";
285 state tell;
286 }
287 // Get roles of caller.
288 state get_caller_roles;
289 }
290 on_rez(integer num) {
291 llResetScript();
292 }
293 changed(integer change) {
294 if((change & CHANGED_INVENTORY) ||
295 (change & CHANGED_REGION_START) ||
296 (change & CHANGED_OWNER)) {
297 llResetScript();
298 }
299 }
300 state_exit() {
301 llSetTimerEvent(0);
302 }
303 }
304  
305 state get_caller_roles {
306 state_entry() {
307 // DEBUG
308 llOwnerSay("[IM] Searching for caller...");
309 llInstantMessage(
310 wasKeyValueGet(
311 "corrade",
312 configuration
313 ),
314 wasKeyValueEncode(
315 [
316 "command", "getmemberroles",
317 "group", wasURLEscape(
318 wasKeyValueGet(
319 "group",
320 configuration
321 )
322 ),
323 "password", wasURLEscape(
324 wasKeyValueGet(
325 "password",
326 configuration
327 )
328 ),
329 "firstname", src_firstname,
330 "lastname", src_lastname,
331 "callback", wasURLEscape(
332 wasKeyValueGet(
333 "URL",
334 configuration
335 )
336 )
337 ]
338 )
339 );
340 llSetTimerEvent(60);
341 }
342 link_message(integer sender, integer num, string body, key id) {
343 // Only process callbacks for the database command.
344 if(id != "callback" || wasKeyValueGet("command", body) != "getmemberroles")
345 return;
346  
347 if(wasKeyValueGet("success", body) != "True") {
348 // DEBUG
349 llOwnerSay("[IM] Unable to get member roles: " +
350 wasURLUnescape(
351 wasKeyValueGet("error", body)
352 )
353 );
354 state listen_group;
355 }
356  
357 // Dump the roles to a list.
358 list roles = wasCSVToList(
359 wasURLUnescape(
360 wasKeyValueGet("data", body)
361 )
362 );
363  
364 if(llGetListLength(
365 wasSetIntersect(roles,
366 wasCSVToList(
367 wasKeyValueGet(
368 "admin roles", configuration
369 )
370 )
371 )
372 ) == 0) {
373 data = "You ain't got the cojones!";
374 state tell;
375 }
376  
377 state get_avatar_key;
378 }
379 timer() {
380 state listen_group;
381 }
382 on_rez(integer num) {
383 llResetScript();
384 }
385 changed(integer change) {
386 if((change & CHANGED_INVENTORY) ||
387 (change & CHANGED_REGION_START) ||
388 (change & CHANGED_OWNER)) {
389 llResetScript();
390 }
391 }
392 state_exit() {
393 llSetTimerEvent(0);
394 }
395 }
396  
397 state get_avatar_key {
398 state_entry() {
399 // DEBUG
400 llOwnerSay("[IM] Searching for avatar key...");
401 llInstantMessage(
402 wasKeyValueGet(
403 "corrade",
404 configuration
405 ),
406 wasKeyValueEncode(
407 [
408 "command", "batchavatarnametokey",
409 "group", wasURLEscape(
410 wasKeyValueGet(
411 "group",
412 configuration
413 )
414 ),
415 "password", wasURLEscape(
416 wasKeyValueGet(
417 "password",
418 configuration
419 )
420 ),
421 "avatars", wasListToCSV([
422 dst_firstname + " " + dst_lastname
423 ]),
424 "callback", wasURLEscape(
425 wasKeyValueGet(
426 "URL",
427 configuration
428 )
429 )
430 ]
431 )
432 );
433 llSetTimerEvent(60);
434 }
435 link_message(integer sender, integer num, string body, key id) {
436 // Only process callbacks for the database command.
437 if(id != "callback" || wasKeyValueGet("command", body) != "batchavatarnametokey")
438 return;
439  
440 if(wasKeyValueGet("success", body) != "True") {
441 // DEBUG
442 llOwnerSay("[IM] Unable to get avatar key: " +
443 wasURLUnescape(
444 wasKeyValueGet("error", body)
445 )
446 );
447 data = "Avatar not found!";
448 state tell;
449 }
450  
451 state im;
452 }
453 timer() {
454 state listen_group;
455 }
456 on_rez(integer num) {
457 llResetScript();
458 }
459 changed(integer change) {
460 if((change & CHANGED_INVENTORY) ||
461 (change & CHANGED_REGION_START) ||
462 (change & CHANGED_OWNER)) {
463 llResetScript();
464 }
465 }
466 state_exit() {
467 llSetTimerEvent(0);
468 }
469 }
470  
471 state im {
472 state_entry() {
473 // DEBUG
474 llOwnerSay("[IM] Sending message...");
475 llInstantMessage(
476 wasKeyValueGet(
477 "corrade",
478 configuration
479 ),
480 wasKeyValueEncode(
481 [
482 "command", "tell",
483 "group", wasURLEscape(
484 wasKeyValueGet(
485 "group",
486 configuration
487 )
488 ),
489 "password", wasURLEscape(
490 wasKeyValueGet(
491 "password",
492 configuration
493 )
494 ),
495 "entity", "avatar",
496 "firstname", dst_firstname,
497 "lastname", dst_lastname,
498 "message", wasURLEscape(data),
499 "callback", wasURLEscape(
500 wasKeyValueGet(
501 "URL",
502 configuration
503 )
504 )
505 ]
506 )
507 );
508 llSetTimerEvent(60);
509 }
510 link_message(integer sender, integer num, string body, key id) {
511 // Only process callbacks for the database command.
512 if(id != "callback" || wasKeyValueGet("command", body) != "tell")
513 return;
514  
515 if(wasKeyValueGet("success", body) != "True") {
516 // DEBUG
517 llOwnerSay("[IM] Unable to send message: " +
518 wasURLUnescape(
519 wasKeyValueGet("error", body)
520 )
521 );
522 data = "Message could not be sent!";
523 state tell;
524 }
525  
526 data = "Message sent!";
527 state tell;
528 }
529 timer() {
530 state listen_group;
531 }
532 on_rez(integer num) {
533 llResetScript();
534 }
535 changed(integer change) {
536 if((change & CHANGED_INVENTORY) ||
537 (change & CHANGED_REGION_START) ||
538 (change & CHANGED_OWNER)) {
539 llResetScript();
540 }
541 }
542 state_exit() {
543 llSetTimerEvent(0);
544 }
545 }
546  
547 state tell {
548 state_entry() {
549 // DEBUG
550 llOwnerSay("[IM] Sending to group.");
551 llInstantMessage(
552 wasKeyValueGet(
553 "corrade",
554 configuration
555 ),
556 wasKeyValueEncode(
557 [
558 "command", "tell",
559 "group", wasURLEscape(
560 wasKeyValueGet(
561 "group",
562 configuration
563 )
564 ),
565 "password", wasURLEscape(
566 wasKeyValueGet(
567 "password",
568 configuration
569 )
570 ),
571 "entity", "group",
572 "message", wasURLEscape(data)
573 ]
574 )
575 );
576 state listen_group;
577 }
578 }