/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2014 - License: CC BY 2.0 // // Please see: https://creativecommons.org/licenses/by/2.0 for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // CONFIGURATION // /////////////////////////////////////////////////////////////////////////// // The UUID / Key of the scripted agent. string CORRADE = "d726edfb-a1c4-4499-8c01-2746227b55e5"; // The name of the group to invite to. string GROUP = "[Wizardry and Steamworks]:Support"; // The password for that group in Corrade.ini. string PASSWORD = "mypassword"; /////////////////////////////////////////////////////////////////////////// // END CONFIGURATION // /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2013 Wizardry and Steamworks - License: CC BY 2.0 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueEncode(list data) { list k = llList2ListStrided(data, 0, -1, 2); list v = llList2ListStrided(llDeleteSubList(data, 0, 0), 0, -1, 2); data = []; do { data += llList2String(k, 0) + "=" + llList2String(v, 0); k = llDeleteSubList(k, 0, 0); v = llDeleteSubList(v, 0, 0); } while(llGetListLength(k) != 0); return llDumpList2String(data, "&"); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // /////////////////////////////////////////////////////////////////////////// string wasKeyValueGet(string k, string data) { if(llStringLength(data) == 0) return ""; if(llStringLength(k) == 0) return ""; list a = llParseStringKeepNulls(data, ["&", "="], []); integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]); if(i != -1) return llList2String(a, 2*i+1); return ""; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // /////////////////////////////////////////////////////////////////////////// // escapes a string in conformance with RFC1738 string wasURLEscape(string i) { string o = ""; do { string c = llGetSubString(i, 0, 0); i = llDeleteSubString(i, 0, 0); if(c == "") jump continue; if(c == " ") { o += "+"; jump continue; } if(c == "\n") { o += "%0D" + llEscapeURL(c); jump continue; } o += llEscapeURL(c); @continue; } while(i != ""); return o; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: CC BY 2.0 // /////////////////////////////////////////////////////////////////////////// // unescapes a string in conformance with RFC1738 string wasURLUnescape(string i) { return llUnescapeURL( llDumpList2String( llParseString2List( llDumpList2String( llParseString2List( i, ["+"], [] ), " " ), ["%0D%0A"], [] ), "\n" ) ); } list avatars = []; list censors = []; list silence = []; integer line = 0; string URL = ""; list name = []; string type = ""; string mute = ""; default { state_entry() { if(llGetInventoryType("moderate") != INVENTORY_NOTECARD) { llSetText("Failed to find a notecard named moderate in the primitive's inventory.", <1,0,0>, 1.0); return; } llGetNotecardLine("moderate", line); } dataserver(key id, string data) { if(data == EOF) state geturl; if(data == "") jump continue; integer i = llSubStringIndex(data, "#"); if(i != -1) data = llDeleteSubString(data, i, -1); if(data == "") jump continue; list mod = llParseString2List(data, ["|"], []); if(llGetListLength(mod) != 3) jump continue; avatars += llStringTrim(llList2String(mod, 0), STRING_TRIM); censors += llStringTrim(llList2String(mod, 1), STRING_TRIM); silence += llStringTrim(llList2String(mod, 2), STRING_TRIM); @continue; llGetNotecardLine("moderate", ++line); } changed(integer change) { if(change & CHANGED_INVENTORY) llResetScript(); } } state geturl { state_entry() { llRequestURL(); } http_request(key id, string method, string body) { if(method != URL_REQUEST_GRANTED) { llSetText("Failed to get an URL.", <1,0,0>, 1.0); llSetTimerEvent(60); return; } URL = body; state select; } timer() { llResetScript(); } changed(integer change) { if(change & CHANGED_INVENTORY) llResetScript(); } } state select { state_entry() { // for re-entry llSetTimerEvent(0.05); } timer() { // if we have completed the list, jump to wait if(llGetListLength(avatars) == 0) state wait; // stack name = llParseString2List(llList2String(avatars, 0), [" "], []); avatars = llDeleteSubList(avatars, 0, 0); type = llList2String(censors, 0); censors = llDeleteSubList(censors, 0, 0); mute = llList2String(silence, 0); silence = llDeleteSubList(silence, 0, 0); // name check if(llGetListLength(name) != 2) return; // type check if(type != "voice" && type != "text") return; // mute check if(mute != "true" && mute != "false") return; llSetText("Moderating: " + llDumpList2String(name, " ") + ", Type: " + type + ", Silent: " + mute, <1, 1, 0>, 1.0); // valid at this point state moderate; } state_exit() { // cancel timeout llSetTimerEvent(0); } changed(integer change) { if(change & CHANGED_INVENTORY) llResetScript(); } } state moderate { state_entry() { llInstantMessage(CORRADE, wasKeyValueEncode( [ "command", "moderate", "group", GROUP, "password", PASSWORD, "firstname", llList2String( name, 0 ), "lastname", llList2String( name, 1 ), "type", type, "silence", mute, "callback", wasURLEscape(URL) ] ) ); // timeout llSetTimerEvent(60); } http_request(key id, string method, string body) { // always confirm to Corrade that the message // has been properly received by the callback llHTTPResponse(id, 200, "Ok"); string success = wasURLUnescape(wasKeyValueGet("success", body)); if(success == "True") llSetText( "Moderated: " + llDumpList2String(name, " ") + ", Type: " + type + ", Silent: " + mute, <0,1,0>, 1.0 ); state select; } timer() { llSetText("Corrade timeout.", <1, 0, 0>, 1.0); state select; } state_exit() { // cancel timeout llSetTimerEvent(0); } changed(integer change) { if(change & CHANGED_INVENTORY) llResetScript(); } } state wait { state_entry() { llSetText("Moderation complate.", <0, 1, 0>, 1.0); } changed(integer change) { if(change & CHANGED_INVENTORY) llResetScript(); } }