corrade-lsl-templates – Diff between revs 5 and 29

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 5 Rev 29
1 /////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 // 2 // Copyright (C) Wizardry and Steamworks 2014 - License: CC BY 2.0 //
3 /////////////////////////////////////////////////////////////////////////// 3 ///////////////////////////////////////////////////////////////////////////
4 // 4 //
5 // This is relays local chat to an avatar and meant to work with Corrade 5 // This is relays local chat to an avatar and meant to work with Corrade
6 // the Second Life / OpenSim bot. You can find more details about the bot 6 // the Second Life / OpenSim bot. You can find more details about the bot
7 // by following the URL: http://was.fm/secondlife/scripted_agents/corrade 7 // by following the URL: http://was.fm/secondlife/scripted_agents/corrade
8 // 8 //
9 // The script works in combination with a "configuration" notecard that 9 // The script works in combination with a "configuration" notecard that
10 // must be placed in the same primitive as this script. The purpose of this 10 // must be placed in the same primitive as this script. The purpose of this
11 // script is to demonstrate relaying local chat to an avatar with Corrade 11 // script is to demonstrate relaying local chat to an avatar with Corrade
12 // and you are free to use, change, and commercialize it under the terms 12 // and you are free to use, change, and commercialize it under the terms
13 // of the GNU/GPLv3 license at: http://www.gnu.org/licenses/gpl.html 13 // of the CC BY 2.0 license at: https://creativecommons.org/licenses/by/2.0
14 // 14 //
15 /////////////////////////////////////////////////////////////////////////// 15 ///////////////////////////////////////////////////////////////////////////
16   16  
17 /////////////////////////////////////////////////////////////////////////// 17 ///////////////////////////////////////////////////////////////////////////
18 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // 18 // Copyright (C) 2014 Wizardry and Steamworks - License: CC BY 2.0 //
19 /////////////////////////////////////////////////////////////////////////// 19 ///////////////////////////////////////////////////////////////////////////
20 string wasKeyValueGet(string k, string data) { 20 string wasKeyValueGet(string k, string data) {
21 if(llStringLength(data) == 0) return ""; 21 if(llStringLength(data) == 0) return "";
22 if(llStringLength(k) == 0) return ""; 22 if(llStringLength(k) == 0) return "";
23 list a = llParseString2List(data, ["&", "="], []); 23 list a = llParseString2List(data, ["&", "="], []);
24 integer i = llListFindList(a, [ k ]); 24 integer i = llListFindList(a, [ k ]);
25 if(i != -1) return llList2String(a, i+1); 25 if(i != -1) return llList2String(a, i+1);
26 return ""; 26 return "";
27 } 27 }
28 28
29 /////////////////////////////////////////////////////////////////////////// 29 ///////////////////////////////////////////////////////////////////////////
30 // Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 // 30 // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 //
31 /////////////////////////////////////////////////////////////////////////// 31 ///////////////////////////////////////////////////////////////////////////
32 string wasKeyValueEncode(list data) { 32 string wasKeyValueEncode(list data) {
33 list k = llList2ListStrided(data, 0, -1, 2); 33 list k = llList2ListStrided(data, 0, -1, 2);
34 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); 34 list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2);
35 data = []; 35 data = [];
36 do { 36 do {
37 data += llList2String(k, 0) + "=" + llList2String(v, 0); 37 data += llList2String(k, 0) + "=" + llList2String(v, 0);
38 k = llDeleteSubList(k, 0, 0); 38 k = llDeleteSubList(k, 0, 0);
39 v = llDeleteSubList(v, 0, 0); 39 v = llDeleteSubList(v, 0, 0);
40 } while(llGetListLength(k) != 0); 40 } while(llGetListLength(k) != 0);
41 return llDumpList2String(data, "&"); 41 return llDumpList2String(data, "&");
42 } 42 }
43   43  
44 /////////////////////////////////////////////////////////////////////////// 44 ///////////////////////////////////////////////////////////////////////////
45 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // 45 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
46 /////////////////////////////////////////////////////////////////////////// 46 ///////////////////////////////////////////////////////////////////////////
47 // escapes a string in conformance with RFC1738 47 // escapes a string in conformance with RFC1738
48 string wasURLEscape(string i) { 48 string wasURLEscape(string i) {
49 string o = ""; 49 string o = "";
50 do { 50 do {
51 string c = llGetSubString(i, 0, 0); 51 string c = llGetSubString(i, 0, 0);
52 i = llDeleteSubString(i, 0, 0); 52 i = llDeleteSubString(i, 0, 0);
53 if(c == "") jump continue; 53 if(c == "") jump continue;
54 if(c == " ") { 54 if(c == " ") {
55 o += "+"; 55 o += "+";
56 jump continue; 56 jump continue;
57 } 57 }
58 if(c == "\n") { 58 if(c == "\n") {
59 o += "%0D" + llEscapeURL(c); 59 o += "%0D" + llEscapeURL(c);
60 jump continue; 60 jump continue;
61 } 61 }
62 o += llEscapeURL(c); 62 o += llEscapeURL(c);
63 @continue; 63 @continue;
64 } while(i != ""); 64 } while(i != "");
65 return o; 65 return o;
66 } 66 }
67   67  
68 /////////////////////////////////////////////////////////////////////////// 68 ///////////////////////////////////////////////////////////////////////////
69 // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // 69 // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 //
70 /////////////////////////////////////////////////////////////////////////// 70 ///////////////////////////////////////////////////////////////////////////
71 // unescapes a string in conformance with RFC1738 71 // unescapes a string in conformance with RFC1738
72 string wasURLUnescape(string i) { 72 string wasURLUnescape(string i) {
73 return llUnescapeURL( 73 return llUnescapeURL(
74 llDumpList2String( 74 llDumpList2String(
75 llParseString2List( 75 llParseString2List(
76 llDumpList2String( 76 llDumpList2String(
77 llParseString2List( 77 llParseString2List(
78 i, 78 i,
79 ["+"], 79 ["+"],
80 [] 80 []
81 ), 81 ),
82 " " 82 " "
83 ), 83 ),
84 ["%0D%0A"], 84 ["%0D%0A"],
85 [] 85 []
86 ), 86 ),
87 "\n" 87 "\n"
88 ) 88 )
89 ); 89 );
90 } 90 }
91   91  
92 // corrade data 92 // corrade data
93 key CORRADE = NULL_KEY; 93 key CORRADE = NULL_KEY;
94 string GROUP = ""; 94 string GROUP = "";
95 string PASSWORD = ""; 95 string PASSWORD = "";
96 key DESTINATION = NULL_KEY; 96 key DESTINATION = NULL_KEY;
97   97  
98 // for holding the callback URL 98 // for holding the callback URL
99 string callback = ""; 99 string callback = "";
100   100  
101 // for notecard reading 101 // for notecard reading
102 integer line = 0; 102 integer line = 0;
103 103
104 // key-value data will be read into this list 104 // key-value data will be read into this list
105 list tuples = []; 105 list tuples = [];
106   106  
107 default { 107 default {
108 state_entry() { 108 state_entry() {
109 if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) { 109 if(llGetInventoryType("configuration") != INVENTORY_NOTECARD) {
110 llOwnerSay("Sorry, could not find a configuration inventory notecard."); 110 llOwnerSay("Sorry, could not find a configuration inventory notecard.");
111 return; 111 return;
112 } 112 }
113 // DEBUG 113 // DEBUG
114 llOwnerSay("Reading configuration file..."); 114 llOwnerSay("Reading configuration file...");
115 llGetNotecardLine("configuration", line); 115 llGetNotecardLine("configuration", line);
116 } 116 }
117 dataserver(key id, string data) { 117 dataserver(key id, string data) {
118 if(data == EOF) { 118 if(data == EOF) {
119 // invariant, length(tuples) % 2 == 0 119 // invariant, length(tuples) % 2 == 0
120 if(llGetListLength(tuples) % 2 != 0) { 120 if(llGetListLength(tuples) % 2 != 0) {
121 llOwnerSay("Error in configuration notecard."); 121 llOwnerSay("Error in configuration notecard.");
122 return; 122 return;
123 } 123 }
124 CORRADE = llList2Key( 124 CORRADE = llList2Key(
125 tuples, 125 tuples,
126 llListFindList( 126 llListFindList(
127 tuples, 127 tuples,
128 [ 128 [
129 "corrade" 129 "corrade"
130 ] 130 ]
131 ) 131 )
132 +1); 132 +1);
133 if(CORRADE == NULL_KEY) { 133 if(CORRADE == NULL_KEY) {
134 llOwnerSay("Error in configuration notecard: corrade"); 134 llOwnerSay("Error in configuration notecard: corrade");
135 return; 135 return;
136 } 136 }
137 GROUP = llList2String( 137 GROUP = llList2String(
138 tuples, 138 tuples,
139 llListFindList( 139 llListFindList(
140 tuples, 140 tuples,
141 [ 141 [
142 "group" 142 "group"
143 ] 143 ]
144 ) 144 )
145 +1); 145 +1);
146 if(GROUP == "") { 146 if(GROUP == "") {
147 llOwnerSay("Error in configuration notecard: group"); 147 llOwnerSay("Error in configuration notecard: group");
148 return; 148 return;
149 } 149 }
150 PASSWORD = llList2String( 150 PASSWORD = llList2String(
151 tuples, 151 tuples,
152 llListFindList( 152 llListFindList(
153 tuples, 153 tuples,
154 [ 154 [
155 "password" 155 "password"
156 ] 156 ]
157 ) 157 )
158 +1); 158 +1);
159 if(PASSWORD == "") { 159 if(PASSWORD == "") {
160 llOwnerSay("Error in configuration notecard: password"); 160 llOwnerSay("Error in configuration notecard: password");
161 return; 161 return;
162 } 162 }
163 DESTINATION = llList2Key( 163 DESTINATION = llList2Key(
164 tuples, 164 tuples,
165 llListFindList( 165 llListFindList(
166 tuples, 166 tuples,
167 [ 167 [
168 "destination" 168 "destination"
169 ] 169 ]
170 ) 170 )
171 +1); 171 +1);
172 if(DESTINATION == NULL_KEY) { 172 if(DESTINATION == NULL_KEY) {
173 llOwnerSay("Error in configuration notecard: destination"); 173 llOwnerSay("Error in configuration notecard: destination");
174 return; 174 return;
175 } 175 }
176 // DEBUG 176 // DEBUG
177 llOwnerSay("Read configuration notecard..."); 177 llOwnerSay("Read configuration notecard...");
178 state url; 178 state url;
179 } 179 }
180 if(data == "") jump continue; 180 if(data == "") jump continue;
181 integer i = llSubStringIndex(data, "#"); 181 integer i = llSubStringIndex(data, "#");
182 if(i != -1) data = llDeleteSubString(data, i, -1); 182 if(i != -1) data = llDeleteSubString(data, i, -1);
183 list o = llParseString2List(data, ["="], []); 183 list o = llParseString2List(data, ["="], []);
184 // get rid of starting and ending quotes 184 // get rid of starting and ending quotes
185 string k = llDumpList2String( 185 string k = llDumpList2String(
186 llParseString2List( 186 llParseString2List(
187 llStringTrim( 187 llStringTrim(
188 llList2String( 188 llList2String(
189 o, 189 o,
190 0 190 0
191 ), 191 ),
192 STRING_TRIM), 192 STRING_TRIM),
193 ["\""], [] 193 ["\""], []
194 ), "\""); 194 ), "\"");
195 string v = llDumpList2String( 195 string v = llDumpList2String(
196 llParseString2List( 196 llParseString2List(
197 llStringTrim( 197 llStringTrim(
198 llList2String( 198 llList2String(
199 o, 199 o,
200 1 200 1
201 ), 201 ),
202 STRING_TRIM), 202 STRING_TRIM),
203 ["\""], [] 203 ["\""], []
204 ), "\""); 204 ), "\"");
205 if(k == "" || v == "") jump continue; 205 if(k == "" || v == "") jump continue;
206 tuples += k; 206 tuples += k;
207 tuples += v; 207 tuples += v;
208 @continue; 208 @continue;
209 llGetNotecardLine("configuration", ++line); 209 llGetNotecardLine("configuration", ++line);
210 } 210 }
211 on_rez(integer num) { 211 on_rez(integer num) {
212 llResetScript(); 212 llResetScript();
213 } 213 }
214 changed(integer change) { 214 changed(integer change) {
215 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 215 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
216 llResetScript(); 216 llResetScript();
217 } 217 }
218 } 218 }
219 } 219 }
220   220  
221 state url { 221 state url {
222 state_entry() { 222 state_entry() {
223 // DEBUG 223 // DEBUG
224 llOwnerSay("Requesting URL..."); 224 llOwnerSay("Requesting URL...");
225 llRequestURL(); 225 llRequestURL();
226 } 226 }
227 http_request(key id, string method, string body) { 227 http_request(key id, string method, string body) {
228 if(method != URL_REQUEST_GRANTED) return; 228 if(method != URL_REQUEST_GRANTED) return;
229 callback = body; 229 callback = body;
230 // DEBUG 230 // DEBUG
231 llOwnerSay("Got URL..."); 231 llOwnerSay("Got URL...");
232 state detect; 232 state detect;
233 } 233 }
234 on_rez(integer num) { 234 on_rez(integer num) {
235 llResetScript(); 235 llResetScript();
236 } 236 }
237 changed(integer change) { 237 changed(integer change) {
238 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 238 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
239 llResetScript(); 239 llResetScript();
240 } 240 }
241 } 241 }
242 } 242 }
243 243
244 state detect { 244 state detect {
245 state_entry() { 245 state_entry() {
246 // DEBUG 246 // DEBUG
247 llOwnerSay("Detecting if Corrade is online..."); 247 llOwnerSay("Detecting if Corrade is online...");
248 llSetTimerEvent(5); 248 llSetTimerEvent(5);
249 } 249 }
250 timer() { 250 timer() {
251 llRequestAgentData((key)CORRADE, DATA_ONLINE); 251 llRequestAgentData((key)CORRADE, DATA_ONLINE);
252 } 252 }
253 dataserver(key id, string data) { 253 dataserver(key id, string data) {
254 if(data != "1") { 254 if(data != "1") {
255 // DEBUG 255 // DEBUG
256 llOwnerSay("Corrade is not online, sleeping..."); 256 llOwnerSay("Corrade is not online, sleeping...");
257 llSetTimerEvent(30); 257 llSetTimerEvent(30);
258 return; 258 return;
259 } 259 }
260 state notify; 260 state notify;
261 } 261 }
262 on_rez(integer num) { 262 on_rez(integer num) {
263 llResetScript(); 263 llResetScript();
264 } 264 }
265 changed(integer change) { 265 changed(integer change) {
266 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 266 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
267 llResetScript(); 267 llResetScript();
268 } 268 }
269 } 269 }
270 } 270 }
271 271
272 state notify { 272 state notify {
273 state_entry() { 273 state_entry() {
274 // DEBUG 274 // DEBUG
275 llOwnerSay("Binding to the local chat notification..."); 275 llOwnerSay("Binding to the local chat notification...");
276 llInstantMessage( 276 llInstantMessage(
277 (key)CORRADE, 277 (key)CORRADE,
278 wasKeyValueEncode( 278 wasKeyValueEncode(
279 [ 279 [
280 "command", "notify", 280 "command", "notify",
281 "group", wasURLEscape(GROUP), 281 "group", wasURLEscape(GROUP),
282 "password", wasURLEscape(PASSWORD), 282 "password", wasURLEscape(PASSWORD),
283 "action", "set", 283 "action", "set",
284 "type", "local", 284 "type", "local",
285 "URL", wasURLEscape(callback), 285 "URL", wasURLEscape(callback),
286 "callback", wasURLEscape(callback) 286 "callback", wasURLEscape(callback)
287 ] 287 ]
288 ) 288 )
289 ); 289 );
290 } 290 }
291 http_request(key id, string method, string body) { 291 http_request(key id, string method, string body) {
292 llHTTPResponse(id, 200, "OK"); 292 llHTTPResponse(id, 200, "OK");
293 if(wasKeyValueGet("command", body) != "notify" || 293 if(wasKeyValueGet("command", body) != "notify" ||
294 wasKeyValueGet("success", body) != "True") { 294 wasKeyValueGet("success", body) != "True") {
295 // DEBUG 295 // DEBUG
296 llOwnerSay("Failed to bind to the local chat notification..."); 296 llOwnerSay("Failed to bind to the local chat notification...");
297 state detect; 297 state detect;
298 } 298 }
299 // DEBUG 299 // DEBUG
300 llOwnerSay("Local chat notification installed..."); 300 llOwnerSay("Local chat notification installed...");
301 state relay; 301 state relay;
302 } 302 }
303 on_rez(integer num) { 303 on_rez(integer num) {
304 llResetScript(); 304 llResetScript();
305 } 305 }
306 changed(integer change) { 306 changed(integer change) {
307 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 307 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
308 llResetScript(); 308 llResetScript();
309 } 309 }
310 } 310 }
311 } 311 }
312   312  
313 state relay { 313 state relay {
314 state_entry() { 314 state_entry() {
315 // DEBUG 315 // DEBUG
316 llOwnerSay("Waiting for chatter..."); 316 llOwnerSay("Waiting for chatter...");
317 } 317 }
318 timer() { 318 timer() {
319 llRequestAgentData((key)CORRADE, DATA_ONLINE); 319 llRequestAgentData((key)CORRADE, DATA_ONLINE);
320 } 320 }
321 dataserver(key id, string data) { 321 dataserver(key id, string data) {
322 if(data == "1") return; 322 if(data == "1") return;
323 // DEBUG 323 // DEBUG
324 llOwnerSay("Corrade is not online, sleeping..."); 324 llOwnerSay("Corrade is not online, sleeping...");
325 // Switch to detect loop and wait there for Corrade to come online. 325 // Switch to detect loop and wait there for Corrade to come online.
326 state detect; 326 state detect;
327 } 327 }
328 http_request(key id, string method, string body) { 328 http_request(key id, string method, string body) {
329 llHTTPResponse(id, 200, "OK"); 329 llHTTPResponse(id, 200, "OK");
330 330
331 llInstantMessage(DESTINATION, 331 llInstantMessage(DESTINATION,
332 wasURLUnescape( 332 wasURLUnescape(
333 wasKeyValueGet( 333 wasKeyValueGet(
334 "firstname", 334 "firstname",
335 body 335 body
336 ) 336 )
337 ) + " " + 337 ) + " " +
338 wasURLUnescape( 338 wasURLUnescape(
339 wasKeyValueGet( 339 wasKeyValueGet(
340 "lastname", 340 "lastname",
341 body 341 body
342 ) 342 )
343 ) + ": " + 343 ) + ": " +
344 wasURLUnescape( 344 wasURLUnescape(
345 wasKeyValueGet( 345 wasKeyValueGet(
346 "message", 346 "message",
347 body 347 body
348 ) 348 )
349 ) 349 )
350 ); 350 );
351 351
352 } 352 }
353 on_rez(integer num) { 353 on_rez(integer num) {
354 llResetScript(); 354 llResetScript();
355 } 355 }
356 changed(integer change) { 356 changed(integer change) {
357 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) { 357 if((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
358 llResetScript(); 358 llResetScript();
359 } 359 }
360 } 360 }
361 } 361 }
362   362