N2K

From Second Life Wiki
Jump to: navigation, search

Created by Kira Komarov.

ChangeLog

  • 02-FEB-2016

Redid it with a slightly more robust and useful interface that provides slightly more information about the key. Starverse

  • 12-April-2012

Thanks to Vladan Highwater and Bliss Keng the script now works again. It seems that w3c have changed their services: the previous URL was http://cgi.w3.org/cgi-bin/html2txt which now redirects to http://www.w3.org/services/html2txt in a weird way that llHTTPRequest cannot follow.

Web-Related Tree

+-------------+ +-------------+ +---------+ +-----------------------------+ +--------------------------+ | Prowler | | Gremlin | | N2K | | Permanent Primitive URL | | Collaborative Coding | +------+------+ +-------------+ +---------+ +------------+----------------+ +--------------------------+ | | +--------+--------+ +-------------------+-------------------+ | SIM Status | | Population Genetics and Selection | +-----------------+ +-------------------+-------------------+ | +------------+-------------+ | Interactive Bacteria | +--------------------------+

Motivation

The main problem with third-party name2key service providers is that their websites are not reliable. Ultimately, by using a third-party website, you at the mercy of their service. They, in turn, are at the mercy of many parameters and may at any time cease to provide services. If you have a script that relies on their service, you are adding to your project a dependency of which you have no control.

This however varies depending on the website. Say, for example, that you would be able to retrieve the key directly from the Second Life website. In this case, if the website went down, it's a strong indicator that the whole of Second Life is down and your script would be worthless during that event anyway.

The main script in this article [K] N2K, uses the World Wide Web Consortium website to extract the keys of avatar names. The W3C is the international standards organization for the World Wide Web. It is unlikely its services will shutdown in the foreseeable future.

Also, it is wise to know, that if your script uses these third-party services, you contribute to their wealth indirectly since their websites get hits from all your scripts for free. Users acquainted with search engine optimization methodologies will realize immediately that such websites make money by the bunch, implicitly just by the number of hits which ranks their website very high on all search engines.

By using the script below, you do transfer the same prestige to the World Wide Web Consortium. However, since they are the people who, in layman terms, define web standards, it feels more like giving the prestige back. Also, it is worth mentioning that the World Wide Web Consortium roughly scores a Google Page Rank of 10, which is the maximum one can achieve.

Other Services

There are many third-party databases available, most of them can be found on the llKey2Name page. Each of them offer name2key service in exchange for hits and they all should be considered unreliable since they are prone to change. A good example of a "best effort" script is Failsavename2key; it attempts to contact several third-party name2key services in the hope that not all of them are down.

There have been several JIRA requests made requesting LSL functions to be implemented so you may retrieve the name of an avatar from a key.

Consider the matter carefully before using name2key services as you are adding a third-party dependency to your project.

Limitations

Augren Ferguson pointed out that agents choosing not to register their avatars with the search system will not be available using N2K. I think that is a decent choice to to opt out for the sake of one's privacy.

Testing

  • Drop the two scripts below in a primitive and you should be prompted by an llTextBox to enter your name.

The tester script [K] N2K - Tester uses llTextBox, however this might not yet be implemented by all viewers. The tester script itself is not needed for the functionality of the name2key system. In any case, if you are a developer looking to include a name2key system, and your viewer doesn't implement llTextBox yet, you will know how to perform your own tests.

Using in Your Projects

The script listens for link messages with the string parameter str containing the name of the avatar and answers with a link message (to the primitive that sent the link message in the first place) having the key parameter set to the key it retrieved or the NULL_KEY in case the avatar key could not be found.

Here is an example rundown of a communication between two scripts. The request comes from a primitive having the link number 1, and sends the request to the N2K script in a primitive in the same linkset having the link number 7:

Modified version

llMessageLinked (LINK_SET, N2K_REQUEST, "Starverse Resident", NULL_KEY);
...
llMessageLinked (LINK_SET, N2K_RESPONSE, "Starverse Resident", "1ad33407-a792-476d-a5e3-06007c0802bf");
or
llMessageLinked (LINK_SET, N2K_NO_RESPONSE, "Starverse Resident", NULL_KEY);

Original Version

llMessageLinked(7, 0, "Kira Komarov", ""); <--- requests the key of the avatar Kira Komarov
...
llMessageLinked(1, 0, "KN2K", "1ad33407-a792-476d-a5e3-06007c0802bf"); <--- the key being sent back

New Members

The script expects the full name of the avatar. If you are looking for a "new member," they apparently do not have last names. "New members" do have last names and they are all "Resident." So if you are looking for a new user called John, you should pass John Resident to the script. Alternatively, if you do not want your script to do this extra work, you can make the script below do the extra work. Please see the discussion tab Talk:N2K for Innula Zenovka's solution within the N2K script itself to grab the keys for new members.

How it Works

Although very elaborate methods such as proxies, logging of SL in-world keys and downright to search engine translation hacks have been previously used to retrieve the key of an avatar, this script simply uses the html2text service provided by the World Wide Consortium to load the http://vwrsearch.secondlife.com website after it has been passed the name of the avatar.

This has the advantage that it strips most HTML out, leaving the secondlife:/// protocol link well within the bounds of the llHTTPRequest 2kbyte data return limit in case the avatar key has been found.

Revised code by Starverse.

Code: N2K

//////////////////////////////////////////////////////////
// Starverse Resident - 2016, License: GPLv3            //
// Please see: http://www.gnu.org/licenses/gpl.html     //
// for legal details, rights of fair usage and          //
// the disclaimer and warranty conditions.              //
//////////////////////////////////////////////////////////
 
// To use:
//      llMessageLinked (LINK_SET, N2K_REQUEST, avatar_name, NULL_KEY)
//
// If avatar found, routine will perform:
//      llMessageLinked (LINK_SET, N2K_RESPONSE, avatar_name, avatar_key)
//
// If avatar not found, routine will perform:
//      llMessageLinked (LINK_SET, N2K_NO_RESPONSE, avatar_name, NULL_KEY)
 
integer     N2K_REQUEST         = 31415900;
integer     N2K_RESPONSE        = 31415901;
integer     N2K_NO_RESPONSE     = 31415902;
 
string  N2K_REQUEST_URL = "https://www.w3.org/services/html2txt?url=http%3A//vwrsearch.secondlife.com/client_search.php%3Fq%3D";
string  N2K_MARKER = "http://world.secondlife.com/resident/";
 
list    gHTTPRequests = [];
 
n2k_request (string inName) {
    gHTTPRequests += [llHTTPRequest (N2K_REQUEST_URL + inName
                            , [HTTP_BODY_MAX_LENGTH, 16384] // set to 16384 for mono, 4096 for old scripts
                            , "")
                        , inName];
    llSetTimerEvent (60.);
}
 
default {
    timer () {
        llSetTimerEvent (0.);
        while (llGetListLength (gHTTPRequests) != 0) {
            llMessageLinked (LINK_SET, N2K_NO_RESPONSE, llList2String (gHTTPRequests, 1), NULL_KEY);
            gRequests = llDeleteSubList (gHTTPRequests, 0, 1);
        }
    }
 
    link_message (integer inFromPrim, integer inCommand, string inData, key inKey) {
        if (inCommand == N2K_REQUEST)
            n2k_request (inData);
    }
 
    http_response (key inRequestKey, integer inStatus, list inHeaders, string inBody) {
        integer position = llListFindList (gHTTPRequests, [inRequestKey]);
        if (position == -1) return;
 
        string name = llList2String (gHTTPRequests, position + 1);
        gHTTPRequests = llDeleteSubList (gHTTPRequests, position, position + 1);
 
        inBody = llToLower (inBody);
        // Find where in the return information os contained the marker that prefixes
        // the key
        position = llSubStringIndex (inBody, N2K_MARKER);
        if (position == -1)
            llMessageLinked (LINK_THIS
                                , N2K_RESPONSE
                                , name
                                , NULL_KEY);
        else {
            // Delete everything up to and including the marker, leaving the key as
            // first thing
            inBody = llDeleteSubString (inBody
                                        , 0
                                        , position + llStringLength (N2K_MARKER)-1);
 
            // Figure out where the key ends by splitting the body at spaces, tabs,
            // and newlines
            list parts = llParseString2List (inBody, [" \n\t"], []);
            key agent_key = (key)llList2String (parts, 0);
            llMessageLinked (LINK_THIS
                                , N2K_RESPONSE
                                , name
                                , (key)agent_key);
        }
    }
}

Original Code

Code: [K] N2K

//////////////////////////////////////////////////////////
// [K] Kira Komarov - 2011, License: GPLv3              //
// Please see: http://www.gnu.org/licenses/gpl.html     //
// for legal details, rights of fair usage and          //
// the disclaimer and warranty conditions.              //
//////////////////////////////////////////////////////////
 
key kReq;
integer lReqNum;
 
default
{    
    link_message(integer sender_num, integer num, string str, key id) {
        lReqNum = sender_num;
        kReq = str;
        state kn2k;
    }
}
 
state kn2k
{
    state_entry() {
        llSetTimerEvent(0.8);
    }
    timer() {
        llSetTimerEvent(0);
        kReq = llHTTPRequest("http://www.w3.org/services/html2txt?url=" + llEscapeURL("http://vwrsearch.secondlife.com/client_search.php?q=") + llEscapeURL(kReq), [HTTP_BODY_MAXLENGTH, 16384], "");
    }
 
    http_response(key request_id, integer status, list metadata, string body) {
        key avKey;
        if(request_id == kReq && status == 200)
        {
            body = llList2String(llParseString2List(body, ["http://world.secondlife.com/resident/"], []), 1);
            body = llList2String(llParseString2List(body, ["\n"], []), 0);
            if (avKey = (key)body)
            {
                llMessageLinked(lReqNum, 0, "KN2K", avKey);
                state default;
            }
        }
        llMessageLinked(lReqNum, 0, "KN2K", NULL_KEY);
        state default;
    }
}

New (modified by Starverse)

Code: N2K - Tester

//////////////////////////////////////////////////////////
// Starverse Resident - 2016, License: GPLv3            //
// Please see: http://www.gnu.org/licenses/gpl.html     //
// for legal details, rights of fair usage and          //
// the disclaimer and warranty conditions.              //
//////////////////////////////////////////////////////////
 
string PROMPT= "\nType the name of an avatar to retrieve the key:";
 
default
{
    state_entry() {
        llListen(-7, "", llGetOwner(), "");
        llTextBox(llGetOwner()
                    , PROMPT
                    , -7);
    }
 
    listen(integer channel, string name, key id, string message) {
        llMessageLinked(LINK_THIS, N2K_REQUEST, message, "");
    }
 
    link_message(integer sender_num, integer num, string str, key id) {
        if(num == N2K_RESPONSE)
            llTextBox (llGetOwner()
                        , PROMPT
                          + "\n\nYour last search result: "
                          + (string)id
                        , -7);
        else if (num == N2K_NO_RESPONSE)
            llTextBox (llGetOwner ()
                        , PROMPT
                          + "\nYour last search did not return a result."
                        , -7);
    }
}

Original Code

Code: [K] N2K - Tester

//////////////////////////////////////////////////////////
// [K] Kira Komarov - 2011, License: GPLv3              //
// Please see: http://www.gnu.org/licenses/gpl.html     //
// for legal details, rights of fair usage and          //
// the disclaimer and warranty conditions.              //
//////////////////////////////////////////////////////////
 
default
{
    state_entry()
    {
        llListen(-7, "", llGetOwner(), "");
        llTextBox(llGetOwner(), "\nType the name of an avatar to retrieve the key:", -7);
    }
    listen(integer channel, string name, key id, string message)
    {
        llMessageLinked(LINK_THIS, 0, message, "");
    }
    link_message(integer sender_num, integer num, string str, key id) {
        if(str == "KN2K") llTextBox(llGetOwner(), "\nType the name of an avatar to retrieve the key:" + "\n\nYour last search result: " + (string)id, -7);
    }
}