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