////////////////////////////////////////////////////////////////////// // Last online scanner -- see when given avatars were last online // By Antony Fairport. // // Revision history. // ================= // // 2011-05-07 // Initial version. ////////////////////////////////////////////////////////////////////// // Constants. float REFRESH_INTERVAL = 10.0; string KEY_FILE = "Keys"; ////////////////////////////////////////////////////////////////////// // Globals. integer g_iMaxTracking; integer g_iCurrent; list g_lTracking; list g_lUserNames; list g_lDisplayNames; list g_lLastSeen; key g_keyRequest; key g_keyKey; integer g_iKey; ////////////////////////////////////////////////////////////////////// // Return a string that is the report of last online times. string LastOnlineReport() { string s = ""; integer i; for ( i = 0; i < g_iMaxTracking; i++ ) { string sUN = llList2String( g_lUserNames, i ); string sDN = llList2String( g_lDisplayNames, i ); string sName = sDN; if ( sUN != sDN ) { sName = sDN + " (" + sUN + ")"; } s += sName + " : " + llList2String( g_lLastSeen, i ) + "\n"; } return s; } ////////////////////////////////////////////////////////////////////// // Format a llGetTimestamp() string FormatTime( string sTime ) { list l = llParseString2List( sTime, [ "T", "." ], [] ); return llList2String( l, 0 ) + " " + llList2String( l, 1 ) + " UTC"; } ////////////////////////////////////////////////////////////////////// // Default state. default { ////////////////////////////////////////////////////////////////// // State entry. state_entry() { // Simply jump to the setup state. state Setup; } } ////////////////////////////////////////////////////////////////////// // Setup state. state Setup { ////////////////////////////////////////////////////////////////// // State entry. state_entry() { // Let the user know what's happening. llSetText( "Reading list of keys to track, please wait...", < 1.0, 0.0, 0.0 >, 1.0 ); // Clear out the lists and get the tracking list length. g_lTracking = []; g_lUserNames = []; g_lDisplayNames = []; g_lLastSeen = []; // If we have the keys file... if ( llGetInventoryType( KEY_FILE ) == INVENTORY_NOTECARD ) { // Start reading. g_keyKey = llGetNotecardLine( KEY_FILE, g_iKey = 0 ); } } ////////////////////////////////////////////////////////////////// // Handle data server responses. dataserver( key queryid, string data ) { // If this is our query... if ( queryid == g_keyKey ) { // If this isn't the end of the file... if ( data != EOF ) { // If the data looks like a key... if ( ( data != "" ) && ( ( (key) data ) != NULL_KEY ) ) { // Extend the lists. g_lTracking += [ data ]; g_lUserNames += [ "" ]; g_lDisplayNames += [ "" ]; g_lLastSeen += [ "No login" ]; } // Next key... g_keyKey = llGetNotecardLine( KEY_FILE, ++g_iKey ); } else { // Record how many we're tracking. g_iMaxTracking = llGetListLength( g_lTracking ); // Start by getting user names... state SetupUserNames; } } } } ////////////////////////////////////////////////////////////////////// // User name setup state. state SetupUserNames { ////////////////////////////////////////////////////////////////// // State entry. state_entry() { // Let the user know what's happening. llSetText( "Getting user names, plase wait...", < 1.0, 0.0, 0.0 >, 1.0 ); // Starting with the first entry in the tracking list... g_iCurrent = 0; // Start getting user names... g_keyRequest = llRequestAgentData( llList2Key( g_lTracking, g_iCurrent ), DATA_NAME ); } ////////////////////////////////////////////////////////////////// // Handle data server responses. dataserver( key queryid, string data ) { // If this is our query... if ( queryid == g_keyRequest ) { // Put the name into the list. g_lUserNames = llListReplaceList( g_lUserNames, [ data ], g_iCurrent, g_iCurrent ); // Move on. g_iCurrent++; // If we've got some names left to get... if ( g_iCurrent < g_iMaxTracking ) { // Get the next name... g_keyRequest = llRequestAgentData( llList2Key( g_lTracking, g_iCurrent ), DATA_NAME ); } else { // Now we get display names. state SetupDisplayNames; } } } } ////////////////////////////////////////////////////////////////////// // Display name setup state. state SetupDisplayNames { ////////////////////////////////////////////////////////////////// // State entry. state_entry() { // Let the user know what's happening. llSetText( "Getting display names, please wait...", < 1.0, 0.0, 0.0 >, 1.0 ); // Starting with the first entry in the tracking list... g_iCurrent = 0; // Start getting display names... g_keyRequest = llRequestDisplayName( llList2Key( g_lTracking, g_iCurrent ) ); } ////////////////////////////////////////////////////////////////// // Handle data server responses. dataserver( key queryid, string data ) { // If this is our query... if ( queryid == g_keyRequest ) { // Put the name into the list. g_lDisplayNames = llListReplaceList( g_lDisplayNames, [ data ], g_iCurrent, g_iCurrent ); // Move on. g_iCurrent++; // If we've got some names left to get... if ( g_iCurrent < g_iMaxTracking ) { // Get the next name... g_keyRequest = llRequestDisplayName( llList2Key( g_lTracking, g_iCurrent ) ); } else { llSetText( "Starting online scanner, please wait...", < 0.0, 1.0, 0.0 >, 1.0 ); // Now we can start online scanning. state OnlineScanner; } } } } ////////////////////////////////////////////////////////////////////// // The online scanner state. state OnlineScanner { ////////////////////////////////////////////////////////////////// // State entry. state_entry() { // Starting with the first entry in the tracking list... g_iCurrent = 0; // Start getting the online status. g_keyRequest = llRequestAgentData( llList2Key( g_lTracking, g_iCurrent ), DATA_ONLINE ); } ////////////////////////////////////////////////////////////////// // Handle data server responses. dataserver( key queryid, string data ) { // If this is our query... if ( queryid == g_keyRequest ) { // If the avatar is online... if ( data == "1" ) { // Update their last seen value. g_lLastSeen = llListReplaceList( g_lLastSeen, [ FormatTime( llGetTimestamp() ) ], g_iCurrent, g_iCurrent ); } // Move on. g_iCurrent++; // If we've got some avatars left to check... if ( g_iCurrent < g_iMaxTracking ) { // Get the next status... g_keyRequest = llRequestAgentData( llList2Key( g_lTracking, g_iCurrent ), DATA_ONLINE ); } else { // Update the display. llSetText( LastOnlineReport(), < 1.0, 1.0, 1.0 >, 1.0 ); // Pause for a while. state ScannerPause; } } } ////////////////////////////////////////////////////////////////// // Look for changes. changed( integer change ) { // Did the inventory of the object change? if ( change & CHANGED_INVENTORY ) { // Yes. Most likely the key list was changed. Start over. llResetScript(); } } } ////////////////////////////////////////////////////////////////////// // Scan pause state. state ScannerPause { ////////////////////////////////////////////////////////////////// // State entry. state_entry() { // Set up the timer for the pause. llSetTimerEvent( REFRESH_INTERVAL ); } ////////////////////////////////////////////////////////////////// // Timer event. timer() { // Kill the timer. llSetTimerEvent( 0.0 ); // Go back and scan again. state OnlineScanner; } ////////////////////////////////////////////////////////////////// // Look for changes. changed( integer change ) { // Did the inventory of the object change? if ( change & CHANGED_INVENTORY ) { // Yes. Most likely the key list was changed. Start over. llResetScript(); } } }