corrade-lsl-templates

Subversion Repositories:
Compare Path: Rev
With Path: Rev
?path1? @ 4  →  ?path2? @ 5
/source/greet-invite-track-group-members/configuration.txt
@@ -0,0 +1,61 @@
############################# START CONFIGURATION ############################
 
# This is a configuration notecard based on the key-value data Wizardry and Steamworks reader.
# Everything following the "#" character is ignored along with blank lines. Values can be set for various
# parameters in a simple and understandable format with the following syntax:
#
# key = "value"
#
# Every time you change this configuration notecard, the script will reset itself and red this notecard.
 
# The "corrade", "group" and "password" settings must correspond to your settings in Corrade.ini
 
# This is the UUID of the Corrade bot.
corrade = "c5a04cf0-4336-4ca7-9cdf-b19a38d2e920"
 
# The name of the group - it can also be the UUID of the group.
group = "My Group"
 
# The password for the group.
password = "mypassword"
 
# The scanning range in meters.
range = "10"
 
# The messae that will be displayed on the dialog pop-up when a new visitor is detected.
welcome = "Hello, welcome to my store! Please choose from the options below. Have a nice stay!"
 
# Buttons!
# Here you can configure the button labels that will be displayed on the dialog pop-up.
# The join group button label.
join = "Join Group"
# The info button label.
info = "Info"
# The landmark button label.
mark = "Landmark"
# The exit button label.
exit = "Exit"
# The gift button label.
gift = "Free Gift"
# The website button label.
site = "Website"
# The page-owner button.
page = "Help!"
 
# The website that the button website takes the user to.
website = "http://grimore.org"
# The message displayed when prompting the user to open a website.
loadurl = "Thank you for visiting our site!"
 
# A comma-separated list of people to be paged when an avatar clicks the page-owner button.
help = "Kira Komarov, Some Resident"
# The message that will be sent to the person clicking the page-owner button that help has been called.
assist = "A manager has been paged and will be with you as soon as possible..."
 
# A comma-separated list of people to to be notified when an avatar joins or leaves the group.
notify = "Kira Komarov, Some Resident"
 
# The message to send when an item is not available.
n/a = "Sorry, that item is not yet available..."
 
############################# END CONFIGURATION #############################
/source/greet-invite-track-group-members/greet-invite-track-group-members.lsl
@@ -0,0 +1,522 @@
///////////////////////////////////////////////////////////////////////////
// Copyright (C) Wizardry and Steamworks 2014 - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
//
// A greet and invite script made to work in conjunction with the Corrade
// the Second Life / OpenSim bot. You can find more details about the bot
// by following the URL: http://was.fm/secondlife/scripted_agents/corrade
//
// The script works in combination with a "configuration" notecard that
// must be placed in the same primitive as this script. The purpose of this
// script is to demonstrate greeting and inviting avatars using Corrade
// and you are free to use, change, and commercialize it under the terms
// of the GNU/GPLv3 license at: http://www.gnu.org/licenses/gpl.html
//
///////////////////////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
string wasKeyValueGet(string k, string data) {
if (llStringLength(data) == 0) return "";
if (llStringLength(k) == 0) return "";
list a = llParseString2List(data, ["&", "="], []);
integer i = llListFindList(llList2ListStrided(a, 0, -1, 2), [ k ]);
if (i != -1) return llList2String(a, 2 * i + 1);
return "";
}
 
///////////////////////////////////////////////////////////////////////////
// Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
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: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
// 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: GNU GPLv3 //
///////////////////////////////////////////////////////////////////////////
// unescapes a string in conformance with RFC1738
string wasURLUnescape(string i) {
return llUnescapeURL(
llDumpList2String(
llParseString2List(
llDumpList2String(
llParseString2List(
i,
["+"],
[]
),
" "
),
["%0D%0A"],
[]
),
"\n"
)
);
}
 
// Helper function to extract values from tuples
string getConfigValue(string id) {
integer i = llListFindList(tuples, (list)id);
if (i == -1) return "";
return llList2String(
tuples,
i + 1
);
}
 
// corrade data
key CORRADE = "";
string GROUP = "";
string PASSWORD = "";
 
// instance variables
integer channel;
list rem = [];
 
// for holding the callback URL
string callback = "";
 
// for notecard reading
integer line = 0;
 
// key-value data will be read into this list
list tuples = [];
 
default {
state_entry() {
// Set-up commnuication channel.
channel = (integer)("0x8" + llGetSubString(llGetKey(), 0, 6));
// Read configuration.
if (llGetInventoryType("configuration") != INVENTORY_NOTECARD) {
llOwnerSay("Sorry, could not find a configuration inventory notecard.");
return;
}
// DEBUG
llOwnerSay("Reading configuration file...");
llGetNotecardLine("configuration", line);
}
dataserver(key id, string data) {
if (data == EOF) {
// invariant, length(tuples) % 2 == 0
if (llGetListLength(tuples) % 2 != 0) {
llOwnerSay("Error in configuration notecard.");
return;
}
CORRADE = llList2Key(
tuples,
llListFindList(
tuples,
[
"corrade"
]
) + 1
);
if (CORRADE == NULL_KEY) {
llOwnerSay("Error in configuration notecard: corrade");
return;
}
GROUP = llList2String(
tuples,
llListFindList(
tuples,
[
"group"
]
) + 1
);
if (GROUP == "") {
llOwnerSay("Error in configuration notecard: group");
return;
}
PASSWORD = llList2String(
tuples,
llListFindList(
tuples,
[
"password"
]
) + 1
);
if (PASSWORD == "") {
llOwnerSay("Error in configuration notecard: password");
return;
}
// DEBUG
llOwnerSay("Read configuration notecard...");
state url;
}
if (data == "") jump continue;
integer i = llSubStringIndex(data, "#");
if (i != -1) data = llDeleteSubString(data, i, -1);
list o = llParseString2List(data, ["="], []);
// get rid of starting and ending quotes
string k = llDumpList2String(
llParseString2List(
llStringTrim(
llList2String(
o,
0
),
STRING_TRIM),
["\""], []
), "\"");
string v = llDumpList2String(
llParseString2List(
llStringTrim(
llList2String(
o,
1
),
STRING_TRIM),
["\""], []
), "\"");
if (k == "" || v == "") jump continue;
tuples += k;
tuples += v;
@continue;
llGetNotecardLine("configuration", ++line);
}
on_rez(integer num) {
llResetScript();
}
changed(integer change) {
if ((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
llResetScript();
}
}
}
 
state url {
state_entry() {
// DEBUG
llOwnerSay("Requesting URL...");
llRequestURL();
}
http_request(key id, string method, string body) {
if (method != URL_REQUEST_GRANTED) return;
callback = body;
// DEBUG
llOwnerSay("Got URL...");
state online;
}
on_rez(integer num) {
llResetScript();
}
changed(integer change) {
if ((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
llResetScript();
}
}
}
 
state online {
state_entry() {
// DEBUG
llOwnerSay("Detecting if Corrade is online...");
llSetTimerEvent(5);
}
timer() {
llRequestAgentData((key)CORRADE, DATA_ONLINE);
}
dataserver(key id, string data) {
if (data != "1") {
// DEBUG
llOwnerSay("Corrade is not online, sleeping...");
llSetTimerEvent(30);
return;
}
state notify;
}
on_rez(integer num) {
llResetScript();
}
changed(integer change) {
if ((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
llResetScript();
}
}
}
 
state notify {
state_entry() {
// DEBUG
llOwnerSay("Binding to the membership notification...");
llInstantMessage(
(key)CORRADE,
wasKeyValueEncode(
[
"command", "notify",
"group", wasURLEscape(GROUP),
"password", wasURLEscape(PASSWORD),
"action", "set",
"type", llList2CSV(["membership"]),
"URL", wasURLEscape(callback),
"callback", wasURLEscape(callback)
]
)
);
}
http_request(key id, string method, string body) {
llHTTPResponse(id, 200, "OK");
if (wasKeyValueGet("command", body) != "notify" ||
wasKeyValueGet("success", body) != "True") {
// DEBUG
llOwnerSay("Failed to bind to the membership notification...");
state detect;
}
// DEBUG
llOwnerSay("Membership notification installed...");
state detect;
}
on_rez(integer num) {
llResetScript();
}
changed(integer change) {
if ((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
llResetScript();
}
}
}
 
state detect {
state_entry() {
// DEBUG
llOwnerSay("Scanning...");
llSensorRepeat("", "", AGENT, (float)getConfigValue("range"), TWO_PI, 1);
llListen(channel, "", "", "");
// Poll for Corrade's online status.
llSetTimerEvent(5);
}
timer() {
llRequestAgentData((key)CORRADE, DATA_ONLINE);
}
dataserver(key id, string data) {
if (data == "1") return;
// DEBUG
llOwnerSay("Corrade is not online, sleeping...");
// Switch to detect loop and wait there for Corrade to come online.
state online;
}
touch_start(integer num) {
llDialog(
llDetectedKey(0),
getConfigValue("welcome"),
[
getConfigValue("join"),
getConfigValue("info"),
getConfigValue("exit"),
getConfigValue("mark"),
getConfigValue("gift"),
getConfigValue("site"),
getConfigValue("page")
],
channel
);
}
listen(integer channel, string name, key id, string message) {
if (message == getConfigValue("exit")) return;
if (message == getConfigValue("join")) {
// DEBUG
llOwnerSay("Inviting: " + name + " to the group.");
llInstantMessage(CORRADE,
wasKeyValueEncode(
[
"command", "invite",
"group", wasURLEscape(GROUP),
"password", wasURLEscape(PASSWORD),
"agent", wasURLEscape(id)
]
)
);
jump menu;
}
if (message == getConfigValue("page")) {
list a = llParseString2List(getConfigValue("help"), [", ", ","], []);
if (llGetListLength(a) == 0) {
llInstantMessage(id, getConfigValue("n/a"));
jump menu;
}
vector p = llGetPos();
string slurl = "secondlife://" + wasURLEscape(llGetRegionName()) + "/" +
(string)((integer)p.x) + "/" +
(string)((integer)p.y) + "/" +
(string)((integer)p.z);
do {
list n = llParseString2List(llList2String(a, 0), [" "], []);
if (llGetListLength(n) == 2) {
llInstantMessage(CORRADE,
wasKeyValueEncode(
[
"command", "tell",
"group", wasURLEscape(GROUP),
"password", wasURLEscape(PASSWORD),
"entity", "avatar",
"firstname", wasURLEscape(llList2String(n, 0)),
"lastname", wasURLEscape(llList2String(n, 1)),
"message", wasURLEscape(
name +
" is asking for help at: " +
slurl
)
]
)
);
}
a = llDeleteSubList(a, 0, 0);
} while (llGetListLength(a) != 0);
llInstantMessage(id, getConfigValue("assist"));
jump menu;
}
if (message == getConfigValue("mark")) {
if (llGetInventoryNumber(INVENTORY_LANDMARK) == 0) {
llInstantMessage(id, getConfigValue("n/a"));
jump menu;
}
llGiveInventory(id, llGetInventoryName(INVENTORY_LANDMARK, 0));
jump menu;
}
if (message == getConfigValue("info")) {
integer i = llGetInventoryNumber(INVENTORY_NOTECARD) - 1;
do {
if (llGetInventoryName(INVENTORY_NOTECARD, i) != "configuration") {
llGiveInventory(id, llGetInventoryName(INVENTORY_NOTECARD, i));
jump menu;
}
} while (--i > -1);
llInstantMessage(id, getConfigValue("n/a"));
jump menu;
}
if (message == getConfigValue("gift")) {
if (llGetInventoryNumber(INVENTORY_OBJECT) == 0) {
llInstantMessage(id, getConfigValue("n/a"));
jump menu;
}
llGiveInventory(id, llGetInventoryName(INVENTORY_OBJECT, 0));
jump menu;
}
if (message == getConfigValue("site")) {
llLoadURL(id, getConfigValue("loadurl"), getConfigValue("website"));
jump menu;
}
@menu;
llDialog(
id,
getConfigValue("welcome"),
[
getConfigValue("join"),
getConfigValue("info"),
getConfigValue("exit"),
getConfigValue("mark"),
getConfigValue("gift"),
getConfigValue("site"),
getConfigValue("page")
],
channel
);
}
no_sensor() {
rem = [];
}
sensor(integer i) {
--i;
do {
key id = llDetectedKey(i);
if (id == NULL_KEY) jump continue;
if (llListFindList(rem, (list)id) != -1) jump continue;
llDialog(
id,
getConfigValue("welcome"),
[
getConfigValue("join"),
getConfigValue("info"),
getConfigValue("exit"),
getConfigValue("mark"),
getConfigValue("gift"),
getConfigValue("site"),
getConfigValue("page")
],
channel
);
rem += id;
@continue;
} while (--i > -1);
}
http_request(key id, string method, string body) {
llHTTPResponse(id, 200, "OK");
list a = llParseString2List(getConfigValue("notify"), [", ", ","], []);
if (llGetListLength(a) == 0) {
// DEBUG
llOwnerSay("Could not read list of avatars to notify about group membership...");
return;
}
do {
list n = llParseString2List(llList2String(a, 0), [" "], []);
if (llGetListLength(n) == 2) {
llInstantMessage(CORRADE,
wasKeyValueEncode(
[
"command", "tell",
"group", wasURLEscape(GROUP),
"password", wasURLEscape(PASSWORD),
"entity", "avatar",
"firstname", wasURLEscape(llList2String(n, 0)),
"lastname", wasURLEscape(llList2String(n, 1)),
"message", wasURLEscape(
wasURLUnescape(wasKeyValueGet("firstname", body)) +
" " +
wasURLUnescape(wasKeyValueGet("lastname", body)) +
" has " +
wasURLUnescape(wasKeyValueGet("action", body)) +
" the group."
)
]
)
);
}
a = llDeleteSubList(a, 0, 0);
} while (llGetListLength(a) != 0);
}
on_rez(integer num) {
llResetScript();
}
changed(integer change) {
if ((change & CHANGED_INVENTORY) || (change & CHANGED_REGION_START)) {
llResetScript();
}
}
}