
Here's the LSL Code:
CODE
// Global Variables -- used to hold data between states
// Lists to store friends info
list keyFriends = [];
list nameFriends = [];
list statusFriends = [];
// Notecard reading variables
string noteName = "Keys";
integer noteCnt = 0;
key noteKey;
// Channel variables
key chanKey;
// General settings
string emailaddy = "tuglyraisin@aol.com";
float setTime = 15.0;
integer listCount = 0;
// Functions
// Returns the status of all listed friends
string GetAll()
{
list tmpList;
integer lCount = 0;
while (llList2String(nameFriends, lCount) != "")
{
string tmpStr = llList2String(nameFriends, lCount) + ":" + llList2String(statusFriends, lCount);
tmpList = tmpList + tmpStr;
lCount++;
}
return llList2CSV(tmpList);
}
// Returns the status of one friend
string GetOne(string name)
{
string GetOne = "";
integer lCount = 0;
while (llList2String(nameFriends, lCount) != "")
{
string tempname = llList2String(nameFriends, lCount);
if (tempname == name)
{
GetOne = llList2String(nameFriends, lCount) + ":" + llList2String(statusFriends, lCount);
}
lCount++;
}
return GetOne;
}
// default state -- used to set everything up
default
{
state_entry()
{
// Creates a data channel
llOpenRemoteDataChannel();
// Starts loading friends' keys into a list
noteKey = llGetNotecardLine(noteName, noteCnt);
noteCnt++;
}
dataserver(key queryid, string data)
{
if (queryid == noteKey)
{
if (data != EOF)
{
// Loads all friend keys into the list
list tsplt = llParseString2List(data, ["|"], []);
keyFriends = keyFriends + llList2String(tsplt, 0);
nameFriends = nameFriends + llList2String(tsplt, 1);
noteKey = llGetNotecardLine(noteName, noteCnt);
noteCnt++;
}
else
{
// Starts the Check state when all keys are loaded
state Check;
}
}
}
remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval)
{
if (type == REMOTE_DATA_CHANNEL)
{
chanKey = channel;
}
else
{
llSay(0, "1. Unexpected event type");
}
}
state_exit()
{
llSay(0, "Friends List: ONLINE");
}
}
// Check state -- used to keep tabs on friends
state Check
{
state_entry()
{
llEmail(emailaddy, "IsOnline", (string)chanKey);
llRequestAgentData(llList2String(keyFriends, listCount), DATA_ONLINE);
llSetTimerEvent(setTime);
}
dataserver(key queryid, string data)
{
string fkey = llList2String(keyFriends, listCount);
if (fkey != "")
{
statusFriends = statusFriends + data;
listCount++;
if (llGetListLength(keyFriends) > listCount)
{
llRequestAgentData(llList2String(keyFriends, listCount), DATA_ONLINE);
}
else
{
listCount = 0;
}
}
}
remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval)
{
if (type == REMOTE_DATA_REQUEST)
{
if (ival == 1)
{
string returnVal = GetAll();
llRemoteDataReply(channel, message_id, returnVal, 101);
}
else if (ival == 2)
{
string returnVal = GetOne(sval);
llRemoteDataReply(channel, message_id, returnVal, 102);
}
else
{
llRemoteDataReply(channel, message_id, "Unknown request", 400);
}
}
else
{
llSay(0, "2. Unexpected event type");
}
}
timer()
{
statusFriends = [];
llRequestAgentData(llList2String(keyFriends, listCount), DATA_ONLINE);
}
state_exit()
{
// Ends the timer evet
llSetTimerEvent(0.0);
// Might want to pull this out later -- command aparently does jack
llCloseRemoteDataChannel(chanKey);
}
}
You need a notecard, mine's called "Keys," that <key>|<name> on each line:
CODE
66b10aa3-d6b0-475b-a6d2-d66550007762|Jarod Godel
This has two functions, you can get the entire list or just one person. To get the entire list, and friends status, IntValue should be 1. This will return a llList2CSV generated string; people and status are seperated by colons. To get a single person, IntValue should be 2 and StringValue needs to be a name (ex: "Jarod Godel"

When you start the script up, it will email "emailaddy" its channel key. To change the number of seconds between status updates, change the value of the "setTime" variable.