Two years ago, gekkie Kidd got in touch with me to fix a “profile greeter” script that he got from a site somewhere (it’s long since gone). You know what that is… when a visitor comes near to a panel, all of a sudden, it displays their profile image for all to see. It’s supposed to be very popular on some clubs, or at least it was, back in 2009.
gekkie’s free script was badly mangled (or madly bangled? lol) and didn’t compile at all. I was intrigued. How do you know the texture ID that is on a profile page? That information isn’t supposed to be available at all. Nevertheless, there had to be some trick because profile greeters everywhere definitely work…
Actually, the trick was very basic and quite clever. Before Linden Lab introduced the new web profiles, there were already some web-based profiles in place. If you had someone’s UUID (which is easy to get!), you could see their in-world profiles with the following URL: https://world.secondlife.com/resident/d2cdf457-5027-4887-abd8-573c62a85226 (aye, that’s my own profile!). It was prettified with some LL-specific LSL, but still looked quite ugly, and that’s probably the reason why Linden Lab changed the Web-based profiles to things like https://my.secondlife.com/gwyneth.llewelyn, which are a bit better (and don’t require an UUID to be displayed).
The “old” Web-based profiles, however, have something nice: they retrieve the profile picture from LL’s database servers and convert it to a Web-readable format (yes, it’s a plain, old JPEG). But to do that they use… yes, you’ve guessed it: the image’s UUID!
In fact, pretty much every texture with enough permissions can be retrieved that way, not only profile pictures; this allowed for some nifty tools to display avatar profile pictures on Web pages. Or any other kind of textures really.
So, with this in mind, what gekkie’s script was attempting to do was to get an avatar’s UUID, make a Web call to the appropriate page, extract the image UUID by parsing the HTML, and retrieving the texture in-world, placing it on a prim’s face. Very cool! Once I figured this out, fixing the script — pretty much rewriting the unreadable bits and compiling it again — was a breeze.
Yesterday gekkie IM’ed me in despair because the script stopped working. Why? It was simple to explain: LL changed the HTML+CSS for the “old” Web-based profiles. To be more precise, now the image tag appears much lower on the code than before. Since you can only retrieve the first 2048 bytes from a Web page, LSL would never get at the image code. Drats! The script was failing with some silly errors for missing textures…
Well, I don’t know who at LL is responsible for that Web page, but they certainly deserve a medal. Or perhaps there were many complaints from Profile Greeter scripters, I don’t know. The point is that LL’s Web developers kindly added three meta tags at the very beginning of the header section: one for the agent UUID, one for the profile picture UUID, and the profile text itself. It looks like this (I’m using my own profile as an example):
<meta name="imageid" content="d5b7ad19-0377-4e83-b3df-ab709661c94a" />
<meta name="agentid" content="d2cdf457-5027-4887-abd8-573c62a85226" />
<meta name="description" content="I'm accused by immersionists of being an augmentist; and augmentists believe I'm an immersionist. But I'm really just a virtual girl in a virtual world, enjoying this space just like you :)
Second Life mirrors real life. The good and the bad of it.
Email me at [email protected]
... and in real life, I'm the European Operations Manager for https://betatechnologies.info." />
Code language: HTML, XML (xml)
Now that’s even simpler to parse! 🙂 Here is the final result. It uses a sensor to locate nearby avatars and display the profile picture of the nearest avatar in range. You can certainly elaborate on this script and make it more creative (some people display the avatar’s name on hovertext as well), but be warned: sensors are usually quite laggy. In the script below, it only scans in a radius of 20 metres around the prim, and repeats the scan every 10 seconds; if you wish to place a huge amount of those Profile Greeters in your club or home, it will lag crazily! Enjoy 🙂
// Drop the script inside the prim you wish to use as the Profile Greeter; note
// that, by default, it will blank *all* prim faces, and set them *all* with
// the profile picture or the detected avatars.
//
// Tweaked by Gwyneth Llewelyn to use sensors.
//
// (cc) 2011 by Gwyneth Llewelyn. Some rights reserved.
// Licensed under a MIT license (https://gwyneth-llewelyn.mit-license.org/)
string RESIDENT_URL = "https://world.secondlife.com/resident/";
key nameKey;
vector curPos;
default
{
state_entry()
{
llSetTexture(TEXTURE_BLANK, ALL_SIDES);
nameKey = llGetOwner();
llHTTPRequest(RESIDENT_URL + (string)nameKey, [HTTP_METHOD,"GET"], "");
// save current location
curPos = llGetPos();
// start sensors
llSensorRepeat("", NULL_KEY, AGENT, 20.0, TWO_PI, 10);
}
sensor(integer total_number)
{
vector current = llDetectedPos(0) -curPos;
vector nearest = current;
integer i;
nameKey = llDetectedKey(0);
for (i = 1; i < total_number; i++)
{
current = llDetectedPos(i);
if (llVecDist(current, curPos) < llVecDist(nearest, curPos))
{
nearest = current;
nameKey = llDetectedKey(i);
}
}
llHTTPRequest(RESIDENT_URL + (string)nameKey, [HTTP_METHOD, "GET"], "");
}
on_rez(integer start_param)
{
llResetScript();
}
changed(integer what)
{
if ((what & CHANGED_SHAPE) || (what & CHANGED_SCALE))
llResetScript();
}
http_response(key request_id,integer status, list metadata, string body)
{
if (llSubStringIndex(body, NULL_KEY) == -1)
{
integer start_of_UUID = llSubStringIndex(body,"<meta name="imageid" content="") + llStringLength("<meta name="imageid" content="");
string profile_pic = llGetSubString(body, start_of_UUID, start_of_UUID + 35);
llSetTexture((key)profile_pic, ALL_SIDES);
}
else
{
llWhisper(PUBLIC_CHANNEL, "You have no profile picture");
llSetTexture(TEXTURE_BLANK, ALL_SIDES);
}
}
} // end default
Code language: LSL (Linden Scripting Language) (lsl)