Sim Restart Notifyer

From Second Life Wiki
Jump to: navigation, search

When the region (with object that runs this script) restarts, the script sends all registered residents an instant message telling the sim is online and what channel and version the sim is now. Also how many restarts the sim had sice the script itself was restarted.

This is practical when you want to know when you can return to your sim and continue working on your projects. Registered residents must not be online, when IM-to-mail service is activated, they receive the notification via email.

Usage

Create an object or use any created already as container for the script. Put the script into. In this case you only will receive restart reports. When you want register other residents, or your partner or alts as message recepient (please ask if they want to), create a notecard and fill it with names or keys, one key a line. For example this way:

# Put the keys of the recepients or the names here,
#
# Using keys is more effective - names need resolving
# You can combine keys and names by using a comment,
# like this:
#
eb66b7b7-7ddb-4c5a-95ad-bfeb9837ae29 # Jenna Felton
#
# Less effective but also possible:
Jenna Felton

Each key and name must go in other line. You can give the notecard any name. Than put it into the container and reset the script. After it reads the keys and resolved the avatar names, the script is ready.

The script writes as floating text the current sim version and restart counts. By cliking the prim, the script also whispers the restart report without sending it to other recepients (no provoced IM spam).

Notifyer script

//----------------------------------------------------------------------------
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 3 of
// the License, or (at your option) any later version.
//
// You may ONLY redistribute this program with copy, mod and transfer
// permissions and ONLY if this preamble is not removed.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//----------------------------------------------------------------------------
 
string  URL = "http://w-hat.com/name2key";
 
integer gStarts = 0;
string  sSince  = "";
 
list    lNotify = [];
integer gNotify = 0;
 
string  sNote;
integer gLine;
key     kRead;
 
list    lNames  = [];
integer gNames  = 0;
 
// --- -----------------------------------------------------------------------
 
notifyRestarts(integer whinfo) {
    string region  = llGetRegionName();
    string channel = llGetEnv("sim_channel");
    string version = llGetEnv("sim_version");
 
    llSetText(
        (string)gStarts+" restarts since "+sSince
        +"\n----------------"
        +"\nChannel: "+channel
        +"\nVersion: "+version, <1.0, 1.0, 1.0>, 1.0);
 
    // Second Life RC LeTigre * 12.08.23.263929
    // http://wiki.secondlife.com/wiki/Release_Notes/Second_Life_RC_LeTigre/12#12.08.23.263929
 
    list   channsl = llParseString2List(channel, [" "], []);
    string srvlink = llDumpList2String(channsl, "_");
 
    srvlink = "http://wiki.secondlife.com/wiki/Release_Notes/"
        + srvlink + "/" + llGetSubString(version, 0, 1)
        + "#" + version;
 
    string message = "[RESTART MESSAGE]: Sim "+region
        +" is restarted and back online now."
        +"\nRestarts: "+(string)gStarts+" since "+sSince
        +"\nSimulator: "+channel+", v"+version
        +"\nRelease notes: "+srvlink;
 
    if (whinfo) llWhisper(0, message);
    else {  
        integer pos = gNotify;
        while (pos-- > 0) {
            llInstantMessage((key)llList2String(lNotify, pos), message);
        }
    }
}
 
// --- -----------------------------------------------------------------------
 
integer resolveNextName() {
    ++gLine;
    if (gLine >= gNames) return FALSE;
 
    sNote = llList2String(lNames, gLine);
 
    // "Jenna Felton" -> "jenna felton"
    // "jenna.felton" -> "jenna felton"
    // "Jenna"        -> "jenna resident"
    integer pos = llSubStringIndex(sNote, ".");
    if (pos > 0) {
        sNote = llGetSubString(sNote, 0, pos-1)+" "+llGetSubString(sNote, pos+1, -1);
    }
    else {
        pos = llSubStringIndex(sNote, " ");
        if (pos < 0) sNote += " Resident";
    }
 
    llSleep(0.2);
 
    kRead = llHTTPRequest( URL + "?terse=1&name=" + llEscapeURL(sNote), [], "" );
 
    return TRUE;
}
 
// === =======================================================================
 
default {
    state_entry() {
        llSetText("Reading notification list", <1.0, .0, .0>, 1.0);
 
        // 1. Resolving the date
        if (sSince == "") {
            // The date is given as "YYY-MM-DD"
            sSince = llGetDate();
 
            // Date Format conversion
            list tmp = llParseString2List(sSince, ["-"], []);
 
            // EU format: "DD.MM.YYYY"
            sSince   = llList2String(tmp, 2)+"."+llList2String(tmp, 1)+"."+llList2String(tmp, 0);
 
            // US format: "MM-DD-YYYY"
            //sSince   = llList2String(tmp, 1)+"-"+llList2String(tmp, 2)+"-"+llList2String(tmp, 0);
        }
 
        // 2. Starting reading notecard
 
        sNote = llGetInventoryName(INVENTORY_NOTECARD, 0);
        if (sNote != "") {
            if (llGetInventoryKey(sNote) == NULL_KEY) sNote = "";
        }
 
        if (sNote == "") {
            llOwnerSay("To allow others to receive restart notifications as well, "
                + "please provide a notecard with stored names or keys "
                + "of the recepients, than reset the script or pick up "
                + "the notificator and rezz it again.");
 
            state Running;
        }
        else {
            gLine = 0;
            kRead = llGetNotecardLine(sNote, gLine);
        }
    }
 
    on_rez(integer start_param) {
        llResetScript();
    }
 
    dataserver(key requested, string data)  {
        if (requested != kRead) return;
 
        if (data == EOF) {
            if (lNames == []) state Running;
            else              state Resolving;
        }
        else kRead = llGetNotecardLine(sNote, ++gLine);
 
        integer pos = llSubStringIndex(data, "#");
        if      (pos == 0) data = "";
        else if (pos > 0)  data = llGetSubString(data, 0, pos -1);
 
        data = llStringTrim(data, STRING_TRIM);
 
        if (data != "") {
            // The recepient is a valide key?
            if (llStringLength(data) == 36) {
                key agent = (key)data;
                if (agent) {
                    if (llListFindList(lNotify, [agent]) < 0) lNotify += [agent];
                }
                else {
                    llOwnerSay("ERROR ("+sNote+":"+(string)gLine
                        +") String '"+data+"' is no valide key.");
                }
            }
 
            // Otherwise could be name, save to resolve
            else lNames += [data];
        }
    }
}
 
// === =======================================================================
 
state Resolving {
    state_entry() {
        llSetText("Resolving recepient keys", <1.0, 1.0, 0.0>, 1.0);
 
        gNames = llGetListLength(lNames);
        llOwnerSay("Resolving "+(string)gNames+" keys.");
 
        gLine = -1;
        if (!resolveNextName()) state Running;
    }
 
    on_rez(integer start_param) {
        llResetScript();
    }
 
    http_response(key id, integer status, list meta, string body) {
        if ( id != kRead ) return;
 
        if ( status == 499 ){
            llOwnerSay("WARNING: name2key request timed out");
        }
        else if ( status != 200 ){
            llOwnerSay("WARNING: the internet exploded!!");
        }
        else if ( (key)body == NULL_KEY ){
            llOwnerSay("WARNING: No key found for " + sNote);
        }
 
        // Agent found
        else {
            kRead = (key)body;
            llOwnerSay("INFO: Key resolved: " + sNote + " = " + body);
            if (llListFindList(lNotify, [kRead]) < 0) lNotify += [kRead];
        }
 
        if (!resolveNextName()) state Running;
    }
}
 
// === =======================================================================
 
state Running {
    state_entry() {
        llSetText("Sim not restartet yet", <1.0, 1.0, 1.0>, 1.0);
 
        kRead = llGetOwner();
        if (llListFindList(lNotify, [kRead]) < 0) lNotify += [kRead];
 
        gNotify = llGetListLength(lNotify);
 
        llOwnerSay((string)gNotify+" recepients registered.");
    }
 
    on_rez(integer start_param) {
        llResetScript();
    }
 
    touch_start(integer total_number) {
        notifyRestarts(TRUE);
    }
 
    changed(integer change) {
        if (change & CHANGED_REGION_START) {
            ++gStarts;
            notifyRestarts(FALSE);
        }
    }
}
 
// === =======================================================================