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