Scripts are also available in the TX Store (Coming Soon)
/**
* DNS Product Update Server:
* Easy to setup product update system based on AnkaDNS (should take less than 1 min)
* visit http://tx-gear.com/dns
* Why AnkaDNS?
* Object URL's change randomly with every rez and sim-restart
* We use ANKA DNS to mitigate this URL http://tx-gear.com/dns
*/
string private_key = ""; // Enter a private_key from http://tx-gear.com/dns
string domain = "http://tx-gear.com";
string public_key;
integer timeout = 60;
string objUrl;
string qUrlUpdate;
string primtext;
vector cOk = <0, 1, 0>;//Everything is OK
vector cWarning = <1, 1, 0>;//Pending server request (Client Err)
vector cError = <1, 0, 0>;
integer giveTotal;
integer emailInterval = 1;
default
{
state_entry()
{
//Set prim-text and object-name
if (llGetObjectName() == "Object") {
llSetObjectName(llGetScriptName());
llSetText(llGetObjectName(), cWarning, TRUE);
}
if (!llStringLength(private_key)) {
string msg;
msg += "\nPRIVATE_KEY EMPTY! (line 6)";
msg += "\nGo to http://tx-gear.com/dns to generate a key and add to your script.";
llOwnerSay(msg);
} else {
// 1) generate a new prim-url
llRequestURL();
}
llSetTimerEvent(timeout);
}
on_rez(integer num)
{
llResetScript();
}
changed(integer change)
{
if (change & CHANGED_INVENTORY) {
llResetScript();
}
}
http_request(key id, string method, string body)
{
if (method == URL_REQUEST_GRANTED) {
objUrl = body;
// 2) Post prim-url to server
string data = llList2Json(JSON_OBJECT, [
"private_key", private_key,
"obj_url", body
]);
qUrlUpdate = llHTTPRequest(domain + "/dns/api/", [
HTTP_METHOD, "POST",
HTTP_MIMETYPE, "application/x-www-form-urlencoded"
], data);
}
}
http_response(key qId, integer status, list metadata, string body)
{
if (qId == qUrlUpdate) {
// 3) Prim-url has been received by the server
if (status== 404) {
llOwnerSay("Error: " + llJsonGetValue(body, ["error"]));
} else if (status == 200) {
public_key = llJsonGetValue(body, ["public_key"]);
llOwnerSay("Server Response:"
+ "\n" + llJsonGetValue(body, ["motd"])
+ "\n "
+ "\nPublic Key: " + public_key
);
llSetText("Server is running", cOk, TRUE);
state running;
}
}
}
timer()
{
llResetScript();
}
}
state running
{
state_entry()
{
llSetTimerEvent(emailInterval);
}
on_rez(integer num)
{
llResetScript();
}
changed(integer change)
{
if (change & CHANGED_REGION_START || change & CHANGED_INVENTORY) {
state default;
}
}
touch_end(integer num)
{
llOwnerSay("\nSERVER INFO"
+ "\ngiveTotal: " + (string)giveTotal
+ "\n"
+ "\nprivate_key: " + private_key
+ "\npublic_key: " + public_key
+ "\n"
+ "\nobj_url: " + objUrl
);
}
http_request(key id, string method, string body)
{
//Extact sender information
string owner = llGetHTTPHeader(id, "x-secondlife-owner-key");
string ownerName = llGetHTTPHeader(id, "x-secondlife-owner-name");
string objName = llGetHTTPHeader(id, "x-secondlife-object-name");
//Split object name into segments
list objSplit = llParseString2List(llToLower(objName), ["v"], [""]);
//Extract last segment (version number)
string objPrefix = llList2String(objSplit, 0);
string objVersion = llList2String(objSplit, -1);
//Split version number into segments
list objVersionSegments = llParseString2List(objVersion, ["."], [""]);
integer update;
string invName;
integer invIndex = llGetInventoryNumber(INVENTORY_OBJECT);
while (invIndex-- && update == FALSE) {
invName = llGetInventoryName(INVENTORY_OBJECT, invIndex);
list invSplit = llParseString2List(llToLower(invName), ["v"], [""]);
string invPrefix = llList2String(invSplit, 0);
string invVersion = llList2String(invSplit, -1);
list invVersionSegments = llParseString2List(invVersion, ["."], [""]);
//Compare version segments
if (objPrefix == invPrefix && objVersion != invVersion) {
integer i;
integer length = llGetListLength(invVersionSegments);
for (i = 0; i < length; i++) {
if (llList2Integer(invVersionSegments, i) >= llList2Integer(objVersionSegments, i)) {
giveTotal++;
update = TRUE;
} else {
update = FALSE;
i = length;
}
}
}
}
//Respond to update request
string msg;
if (method == "GET" && update) {
llSetText(ownerName + " got " + invName + "\nTotal Items Updated:" + (string)giveTotal, cOk, 1.0 );
llGiveInventory(owner, invName);
msg = "A update has been sent (" + invName + ")";
} else {
msg = "You are up-to-date";
}
llHTTPResponse(id, 200, msg);
}
timer()
{
llGetNextEmail("", public_key);
}
email( string time, string address, string subject, string message, integer num_left )
{
if (llGetSubString(address, -19, -1) == "@lsl.secondlife.com" && subject == public_key) {
llEmail(address, public_key, objUrl);
}
}
}
The client script connects to our API to get the server URL and object key.
This would allow the script to alternatively use email, instead of our API as a auxilary method
/**
* DNS Product Update Client
* Easy to setup product update system based on AnkaDNS (should take less than 1 min)
* visit http://tx-gear.com/dns
*
* Why AnkaDNS?
* Object URL's change randomly with every rez and sim-restart
* We use ANKA DNS to mitigate this URL http://tx-gear.com/dns
*/
string public_key = "";
string domain = "http://tx-gear.com";
string objUrl;
string objKey;
string qGetUrl;
string qPingUrl;
integer pingFail;
// Use this function to send data to your inworld server
rcxPingUrl()
{
qPingUrl = llHTTPRequest(objUrl, [
HTTP_METHOD, "POST",
HTTP_MIMETYPE, "application/x-www-form-urlencoded"
], "");// Add Custom data here
}
// Do no alter this function
rcxGetUrl()
{
string data = llList2Json(JSON_OBJECT, [
"public_key", public_key
]);
qGetUrl = llHTTPRequest(domain + "/dns/api/", [
HTTP_METHOD, "POST",
HTTP_MIMETYPE, "application/x-www-form-urlencoded"
], data);
}
default
{
state_entry()
{
if (llGetObjectName() == "Object") {
llSetObjectName(llGetScriptName());
}
rcxGetUrl();
}
on_rez(integer num)
{
rcxPingUrl();
}
link_message(integer sender_num, integer num, string msg, key id)
{
if (msg == "#update") {
rcxPingUrl();
}
}
http_response(key qId, integer status, list metadata, string body)
{
if (qId == qGetUrl) {
if (status == 200) {
objUrl = llJsonGetValue(body, ["obj_url"]);
objKey = llJsonGetValue(body, ["obj_key"]);
rcxPingUrl();
} else if (status == 404) {
llOwnerSay("Error: " + llJsonGetValue(body, ["error"]));
}
} else if (qId == qPingUrl) {
if (status == 200) {
pingFail = FALSE;
} else if (status == 500) {
pingFail++;
if (pingFail == 1) {
rcxGetUrl();
} else {
llOwnerSay("HTTP Error: Falling Back On Email (If you don't see \"HTTP Updated\" in 40 seconds try again)");
llEmail(objKey + "@lsl.secondlife.com", public_key, "");
llSetTimerEvent(40);
}
}
}
}
timer()
{
llGetNextEmail(objKey + "@lsl.secondlife.com", public_key);
pingFail = FALSE;
llSetTimerEvent(0);
}
email(string time, string address, string subject, string message, integer mailsLeft)
{
if (llGetSubString(address, -19, -1) == "@lsl.secondlife.com") {
objUrl = llList2String(llParseString2List(message, ["\n\n"], [""]), 1);
rcxPingUrl();
llOwnerSay("HTTP Updated");
}
}
}