Jump to content

Export data collected by a script?


primerib1
 Share

You are about to reply to a thread that has been inactive for 178 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

What kind, how much, how often?

If it's just a little bit, dumping to local chat is probably the best option. Even if it's a lot, chat might be more convenient.

If it's A LOT or very regularly, a web server for logging is probably more useful.

Sadly scripts can't write notecards or really do anything besides chat or make HTTP requests.

  • Thanks 1
Link to comment
Share on other sites

15 hours ago, Wulfie Reanimator said:

What kind, how much, how often?

If it's just a little bit, dumping to local chat is probably the best option. Even if it's a lot, chat might be more convenient.

If it's A LOT or very regularly, a web server for logging is probably more useful.

Sadly scripts can't write notecards or really do anything besides chat or make HTTP requests.

Only max of one datapoint per 2 seconds.

Spinning up a web server is so much work 😅

 

13 hours ago, Love Zhaoying said:

Dumping to DEBUG_CHANNEL has the "advantage" of no date-time or "who-said" headers. You just have to throttle the calls to llSay() on channel DEBUG_CHAT, or your script will be throttled for you (text will stop making it to the debug channel).

Well, Local Chat has the benefit of automatically gets saved by my viewer. Does DEBUG_CHANNEL also get saved automatically?

Edited by primerib1
remove doubled quote
  • Thanks 1
Link to comment
Share on other sites

9 hours ago, primerib1 said:

Spinning up a web server is so much work 😅

Not so much if you use llHTTPResponse() to the http_request() event.

One advantage to local chat is that you can pretty-print stuff using the Viewer URI Namespace strings, then click on them for enlightenment (some viewers more enlightened than others).

Below is a script I wrote to scan the parcels in the current region and report on land impact use. Sorry, I know it's too specific and way too long to be a proper example, but "I did not have time to make it shorter"* and it has the virtue of using both local chat and a self-served web page. (Uncomment the last line to re-enable touch for a new report, or leave it commented out to be able to reuse the URL to refresh the same report. Also, it scans for parcels in an unforgivably simplistic sequence; so sue me. And it makes no allowance for memory capacity; if it blows up, find a simpler sim. And the browser will likely gripe at first about a non-SSL connection, about which I've griped again recently.)

Ideally, one might make an output tracing script that takes link messages and dumps their text to a long-polling web page. That would be simpler and more generally useful.

__________
*Blaise Pascal, Lettres Provinciales

// Copyright © 2022 Qie Niangao, released into Public Domain

list regionOwnersData;
string url;
key urlRequestID;
string outTable;
vector pos;
list details;
list parcelKeys;
key ownerQuery;
key groupQuery;
string delim = "\t";
key toucher;
list groupCache;    // GROUPCACHELIM = 8 or most recent 4 groups

getDetailsAtPos()
{
    details = llGetParcelDetails(pos, 
        [ PARCEL_DETAILS_ID
        , PARCEL_DETAILS_NAME
        , PARCEL_DETAILS_OWNER
        , PARCEL_DETAILS_GROUP
        , PARCEL_DETAILS_AREA
        ]) +
        [ FALSE // to hold nameString
        , FALSE // to hold groupString
        ];
}

queryForParcelOwnerAndGroup()
{
    parcelKeys += llList2Key(details, 0);
    key ownerKey = llList2Key(details, 2);
    if (!~llListFindList(regionOwnersData, [ownerKey])) // new owner
        regionOwnersData += 
            [ ownerKey
            , ""
            , llGetParcelMaxPrims(pos, TRUE)
            , llGetParcelPrimCount(pos,  PARCEL_COUNT_TOTAL, TRUE)
            ];
    key groupKey = llList2Key(details, 3);
    if (ownerKey == groupKey)
        details = llListReplaceList(details, ["[group-owned]"], 5, 5);
    else
        ownerQuery = llRequestAgentData(ownerKey, DATA_NAME);
    if (NULL_KEY == groupKey)    // is this correct for no group specified?
        details = llListReplaceList(details, [""], 6, 6);
    else
    {
        integer cacheIdx = llListFindList(groupCache, [groupKey]);
        if (~cacheIdx)
            details = llListReplaceList(details, [llList2String(groupCache, cacheIdx+1)], 6, 6);
        else
        {
            groupQuery = llHTTPRequest("http://world.secondlife.com/group/"+(string)groupKey
                , [HTTP_VERBOSE_THROTTLE, FALSE], "");
            llSleep(1.0);   // avoid the throttle kicking in!
        }
    }
}
progBar( float Cur )
{
    // Input from 0.0 to 1.0
    integer Bars = 20;  // char length of progress bar
    integer pct = llRound(Cur*100.0);
    Cur *= Bars;
    integer Solids  = llFloor( Cur );
    integer Shade   = llFloor( (Cur-Solids)*10);
    integer Blanks  = Bars - Solids - 1;
    //llOwnerSay((string)Solids+" Solids, "+(string)Shade+" Shade, "+(string)Blanks+" Blanks");
    string str;
    while( Solids-- >0 ) str +="█";
    if( Blanks >= 0 ) str += llGetSubString("▁▏▎▍▌▌▋▊▉█", Shade, Shade);
    while( Blanks-- >0 ) str += "▁";
    llSetText("▕"+str+"▏"+(string)pct+"%", <1.0, 1.0, 1.0>, 1.0); 
}

string stringClean(string inStr)
{
    inStr = llDumpList2String(llParseStringKeepNulls(inStr, ["&"], []), "&amp;");
    inStr = llDumpList2String(llParseStringKeepNulls(inStr, ["<"], []), "&lt;");
    return(inStr);
}
maybeNext()
{
    // Theoretically, even if we ask for both, could get result of either the name or group query first, 
    // so both results trigger this. Loop because queryForParcelOwnerAndGroup() might fill both with no query.
    while ((TYPE_INTEGER != llGetListEntryType(details, 5))     // OWNER known
        && (TYPE_INTEGER != llGetListEntryType(details, 6)))     // GROUP known
    {
        string ownerString = llList2String(details, 5);
        outTable += "<tr><td>"
            +(string)llList2Integer(details, 4) +"</td><td>"   // AREA
            +(string)llGetParcelMaxPrims(pos, FALSE) +"</td><td>"
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_TOTAL, FALSE) +"</td><td>"
            + stringClean(llList2String(details, 1)) +"</td><td>"    // NAME
            + ownerString +"</td><td>"    // OWNER
            + stringClean(llList2String(details, 6)) +"</td><td>"    // GROUP
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_TEMP, FALSE) +"</td><td>"
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_SELECTED, FALSE) +"</td></tr>\n"
            ;
    
        if ("[group-owned]" != ownerString)
            ownerString = "secondlife:///app/agent/"+llList2String(details, 2)+"/inspect";
        llRegionSayTo(toucher, 0, delim
            +(string)llList2Integer(details, 4) +delim   // AREA
            +(string)llGetParcelMaxPrims(pos, FALSE) +delim
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_TOTAL, FALSE) +delim
            + "secondlife:///app/parcel/"+llList2String(details, 0)+"/about" +delim
            + ownerString +delim
            + "secondlife:///app/group/"+llList2String(details, 3)+"/inspect" +delim
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_TEMP, FALSE) +delim
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_SELECTED, FALSE) +delim
            );
        progBar((pos.x+256.0*pos.y)/ 65536);
        do
        {
            pos.x = pos.x + 4;
            if (pos.x > 256)
            {
                pos.x = 2;
                pos.y = pos.y + 4;
            }
            if (pos.y > 256)    // all done
            {
                llSetText("Done", <1.0, 1.0, 1.0>, 0.2);
                if (llGetOwner() == toucher)   // HTML content only to owner
                    llLoadURL(llGetOwner(), "Parcel info in handy table", url);
                llRegionSayTo(toucher, 0, delim+"owner"+delim+"capacity"+delim+"l.impact");
                integer dataLen = llGetListLength(regionOwnersData);
                integer dataIdx;
                do
                    llRegionSayTo(toucher, 0, delim
                        + llList2String(regionOwnersData, (dataIdx + 1)) +delim
                        + (string)llList2Integer(regionOwnersData, (dataIdx + 2)) +delim
                        + (string)llList2Integer(regionOwnersData, (dataIdx + 3))
                        );
                while ((dataIdx += 4) < dataLen);
                // finish tables
                outTable += "</tbody></table>\n<table style=\"background-color:honeydew\"><thead><tr><th>"
                    + "owner</th><th>"
                    + "capacity</th><th>"
                    + "l.impact</th></tr></thead><tbody>\n";
                dataLen = llGetListLength(regionOwnersData);
                dataIdx = 0;
                do
                    outTable +=
                        "<tr><td>"+llList2String(regionOwnersData, (dataIdx +1)) +"</td><td>"
                        + (string)llList2Integer(regionOwnersData, (dataIdx +2)) +"</td><td>"
                        + (string)llList2Integer(regionOwnersData, (dataIdx +3)) +"</td></tr>\n"
                        ;
                while ((dataIdx += 4) < dataLen);
                
                outTable+="</tbody></table></body></html>";
                return;
            }
            getDetailsAtPos();
        }
        while (~llListFindList(parcelKeys, [llList2Key(details, 0)]));
        queryForParcelOwnerAndGroup();
    }
}
maybeUpdateRegionData(key old, string new)
{
    integer here = llListFindList(regionOwnersData, [old]);
    if (~here)
        regionOwnersData = llListReplaceList(regionOwnersData, [new], here+1, here+1);
}

default
{
    touch_end(integer total_number)
    {
        toucher = llDetectedKey(0);
        llRegionSayTo(toucher, 0, delim
            + "sq.m." +delim
            + "capacity" +delim
            + "l.impact "+delim
            + "name" +delim
            + "owner" +delim
            + "group" +delim
            + "temp" +delim
            + "selected"
            );
        state noTouch;
    }
}

state noTouch
{
    state_entry()
    {
        llReleaseURL(url);
        urlRequestID = llRequestURL();
    }
    http_response(key id, integer status, list metadata, string body)
    {
        if (groupQuery == id)
        {

            key groupKey = llList2Key(details, 3);
            string groupName;
            if (200 == status)
                groupName = llGetSubString(
                    body,
                    llSubStringIndex(body, "<title>") +7,
                    llSubStringIndex(body, "</title>") -1
                    );
            else
                groupName = "<i>[missing data]</i>";
            maybeUpdateRegionData(groupKey, groupName);
            details = llListReplaceList(details, [groupName], 6, 6);
            integer cacheIdx = llListFindList(groupCache, [groupKey]);
            if (~cacheIdx)
                groupCache = llListReplaceList(groupCache, [], cacheIdx, cacheIdx+1);
            else
                if (llGetListLength(groupCache) > 6)
                    groupCache = llListReplaceList(groupCache, [], 6, 7);
            groupCache = [groupKey, groupName] + groupCache;
            maybeNext();
        }
    }
    dataserver(key id, string data)
    {
        if (ownerQuery == id)
        {
            maybeUpdateRegionData(llList2Key(details, 2), data);
            details = llListReplaceList(details, [data], 5, 5);
            maybeNext();
        }
    }
    http_request(key id, string method, string body)
    {
        if (method == URL_REQUEST_GRANTED)
        {
            url = body;
            outTable =
"<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /><title>Region Parcel Info</title>
<link rel='icon' type='image/png' href='https://qielabs.files.wordpress.com/2019/03/favicon.png'></link></head>
<body style=\"background-color:white\">\n<table style=\"background-color:snow\"><thead><tr><th>"
                + "sq.m.</th><th>"
                + "capacity</th><th>"
                + "l.impact</th><th>"
                + "name</th><th>"
                + "owner</th><th>"
                + "group</th><th>"
                + "temp</th><th>"
                + "selected</th></tr></thead><tbody>\n"
                ;
            pos = <2.0, 2.0, 0.0>;
            getDetailsAtPos();
            queryForParcelOwnerAndGroup();
        }
        else
        if (method == "GET")
        {
            llSetContentType(id, CONTENT_TYPE_XHTML);
            llHTTPResponse(id, 200, outTable);
            llSetText("", ZERO_VECTOR, 0.0);
            // llResetScript(); // not if we want to serve the table again
        }
    }
}

 

  • Like 2
  • Thanks 2
Link to comment
Share on other sites

On 11/23/2022 at 7:20 PM, Qie Niangao said:

Not so much if you use llHTTPResponse() to the http_request() event.

One advantage to local chat is that you can pretty-print stuff using the Viewer URI Namespace strings, then click on them for enlightenment (some viewers more enlightened than others).

Below is a script I wrote to scan the parcels in the current region and report on land impact use. Sorry, I know it's too specific and way too long to be a proper example, but "I did not have time to make it shorter"* and it has the virtue of using both local chat and a self-served web page. (Uncomment the last line to re-enable touch for a new report, or leave it commented out to be able to reuse the URL to refresh the same report. Also, it scans for parcels in an unforgivably simplistic sequence; so sue me. And it makes no allowance for memory capacity; if it blows up, find a simpler sim. And the browser will likely gripe at first about a non-SSL connection, about which I've griped again recently.)

Ideally, one might make an output tracing script that takes link messages and dumps their text to a long-polling web page. That would be simpler and more generally useful.

__________
*Blaise Pascal, Lettres Provinciales

// Copyright © 2022 Qie Niangao, released into Public Domain

list regionOwnersData;
string url;
key urlRequestID;
string outTable;
vector pos;
list details;
list parcelKeys;
key ownerQuery;
key groupQuery;
string delim = "\t";
key toucher;
list groupCache;    // GROUPCACHELIM = 8 or most recent 4 groups

getDetailsAtPos()
{
    details = llGetParcelDetails(pos, 
        [ PARCEL_DETAILS_ID
        , PARCEL_DETAILS_NAME
        , PARCEL_DETAILS_OWNER
        , PARCEL_DETAILS_GROUP
        , PARCEL_DETAILS_AREA
        ]) +
        [ FALSE // to hold nameString
        , FALSE // to hold groupString
        ];
}

queryForParcelOwnerAndGroup()
{
    parcelKeys += llList2Key(details, 0);
    key ownerKey = llList2Key(details, 2);
    if (!~llListFindList(regionOwnersData, [ownerKey])) // new owner
        regionOwnersData += 
            [ ownerKey
            , ""
            , llGetParcelMaxPrims(pos, TRUE)
            , llGetParcelPrimCount(pos,  PARCEL_COUNT_TOTAL, TRUE)
            ];
    key groupKey = llList2Key(details, 3);
    if (ownerKey == groupKey)
        details = llListReplaceList(details, ["[group-owned]"], 5, 5);
    else
        ownerQuery = llRequestAgentData(ownerKey, DATA_NAME);
    if (NULL_KEY == groupKey)    // is this correct for no group specified?
        details = llListReplaceList(details, [""], 6, 6);
    else
    {
        integer cacheIdx = llListFindList(groupCache, [groupKey]);
        if (~cacheIdx)
            details = llListReplaceList(details, [llList2String(groupCache, cacheIdx+1)], 6, 6);
        else
        {
            groupQuery = llHTTPRequest("http://world.secondlife.com/group/"+(string)groupKey
                , [HTTP_VERBOSE_THROTTLE, FALSE], "");
            llSleep(1.0);   // avoid the throttle kicking in!
        }
    }
}
progBar( float Cur )
{
    // Input from 0.0 to 1.0
    integer Bars = 20;  // char length of progress bar
    integer pct = llRound(Cur*100.0);
    Cur *= Bars;
    integer Solids  = llFloor( Cur );
    integer Shade   = llFloor( (Cur-Solids)*10);
    integer Blanks  = Bars - Solids - 1;
    //llOwnerSay((string)Solids+" Solids, "+(string)Shade+" Shade, "+(string)Blanks+" Blanks");
    string str;
    while( Solids-- >0 ) str +="█";
    if( Blanks >= 0 ) str += llGetSubString("▁▏▎▍▌▌▋▊▉█", Shade, Shade);
    while( Blanks-- >0 ) str += "▁";
    llSetText("▕"+str+"▏"+(string)pct+"%", <1.0, 1.0, 1.0>, 1.0); 
}

string stringClean(string inStr)
{
    inStr = llDumpList2String(llParseStringKeepNulls(inStr, ["&"], []), "&amp;");
    inStr = llDumpList2String(llParseStringKeepNulls(inStr, ["<"], []), "&lt;");
    return(inStr);
}
maybeNext()
{
    // Theoretically, even if we ask for both, could get result of either the name or group query first, 
    // so both results trigger this. Loop because queryForParcelOwnerAndGroup() might fill both with no query.
    while ((TYPE_INTEGER != llGetListEntryType(details, 5))     // OWNER known
        && (TYPE_INTEGER != llGetListEntryType(details, 6)))     // GROUP known
    {
        string ownerString = llList2String(details, 5);
        outTable += "<tr><td>"
            +(string)llList2Integer(details, 4) +"</td><td>"   // AREA
            +(string)llGetParcelMaxPrims(pos, FALSE) +"</td><td>"
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_TOTAL, FALSE) +"</td><td>"
            + stringClean(llList2String(details, 1)) +"</td><td>"    // NAME
            + ownerString +"</td><td>"    // OWNER
            + stringClean(llList2String(details, 6)) +"</td><td>"    // GROUP
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_TEMP, FALSE) +"</td><td>"
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_SELECTED, FALSE) +"</td></tr>\n"
            ;
    
        if ("[group-owned]" != ownerString)
            ownerString = "secondlife:///app/agent/"+llList2String(details, 2)+"/inspect";
        llRegionSayTo(toucher, 0, delim
            +(string)llList2Integer(details, 4) +delim   // AREA
            +(string)llGetParcelMaxPrims(pos, FALSE) +delim
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_TOTAL, FALSE) +delim
            + "secondlife:///app/parcel/"+llList2String(details, 0)+"/about" +delim
            + ownerString +delim
            + "secondlife:///app/group/"+llList2String(details, 3)+"/inspect" +delim
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_TEMP, FALSE) +delim
            +(string)llGetParcelPrimCount(pos, PARCEL_COUNT_SELECTED, FALSE) +delim
            );
        progBar((pos.x+256.0*pos.y)/ 65536);
        do
        {
            pos.x = pos.x + 4;
            if (pos.x > 256)
            {
                pos.x = 2;
                pos.y = pos.y + 4;
            }
            if (pos.y > 256)    // all done
            {
                llSetText("Done", <1.0, 1.0, 1.0>, 0.2);
                if (llGetOwner() == toucher)   // HTML content only to owner
                    llLoadURL(llGetOwner(), "Parcel info in handy table", url);
                llRegionSayTo(toucher, 0, delim+"owner"+delim+"capacity"+delim+"l.impact");
                integer dataLen = llGetListLength(regionOwnersData);
                integer dataIdx;
                do
                    llRegionSayTo(toucher, 0, delim
                        + llList2String(regionOwnersData, (dataIdx + 1)) +delim
                        + (string)llList2Integer(regionOwnersData, (dataIdx + 2)) +delim
                        + (string)llList2Integer(regionOwnersData, (dataIdx + 3))
                        );
                while ((dataIdx += 4) < dataLen);
                // finish tables
                outTable += "</tbody></table>\n<table style=\"background-color:honeydew\"><thead><tr><th>"
                    + "owner</th><th>"
                    + "capacity</th><th>"
                    + "l.impact</th></tr></thead><tbody>\n";
                dataLen = llGetListLength(regionOwnersData);
                dataIdx = 0;
                do
                    outTable +=
                        "<tr><td>"+llList2String(regionOwnersData, (dataIdx +1)) +"</td><td>"
                        + (string)llList2Integer(regionOwnersData, (dataIdx +2)) +"</td><td>"
                        + (string)llList2Integer(regionOwnersData, (dataIdx +3)) +"</td></tr>\n"
                        ;
                while ((dataIdx += 4) < dataLen);
                
                outTable+="</tbody></table></body></html>";
                return;
            }
            getDetailsAtPos();
        }
        while (~llListFindList(parcelKeys, [llList2Key(details, 0)]));
        queryForParcelOwnerAndGroup();
    }
}
maybeUpdateRegionData(key old, string new)
{
    integer here = llListFindList(regionOwnersData, [old]);
    if (~here)
        regionOwnersData = llListReplaceList(regionOwnersData, [new], here+1, here+1);
}

default
{
    touch_end(integer total_number)
    {
        toucher = llDetectedKey(0);
        llRegionSayTo(toucher, 0, delim
            + "sq.m." +delim
            + "capacity" +delim
            + "l.impact "+delim
            + "name" +delim
            + "owner" +delim
            + "group" +delim
            + "temp" +delim
            + "selected"
            );
        state noTouch;
    }
}

state noTouch
{
    state_entry()
    {
        llReleaseURL(url);
        urlRequestID = llRequestURL();
    }
    http_response(key id, integer status, list metadata, string body)
    {
        if (groupQuery == id)
        {

            key groupKey = llList2Key(details, 3);
            string groupName;
            if (200 == status)
                groupName = llGetSubString(
                    body,
                    llSubStringIndex(body, "<title>") +7,
                    llSubStringIndex(body, "</title>") -1
                    );
            else
                groupName = "<i>[missing data]</i>";
            maybeUpdateRegionData(groupKey, groupName);
            details = llListReplaceList(details, [groupName], 6, 6);
            integer cacheIdx = llListFindList(groupCache, [groupKey]);
            if (~cacheIdx)
                groupCache = llListReplaceList(groupCache, [], cacheIdx, cacheIdx+1);
            else
                if (llGetListLength(groupCache) > 6)
                    groupCache = llListReplaceList(groupCache, [], 6, 7);
            groupCache = [groupKey, groupName] + groupCache;
            maybeNext();
        }
    }
    dataserver(key id, string data)
    {
        if (ownerQuery == id)
        {
            maybeUpdateRegionData(llList2Key(details, 2), data);
            details = llListReplaceList(details, [data], 5, 5);
            maybeNext();
        }
    }
    http_request(key id, string method, string body)
    {
        if (method == URL_REQUEST_GRANTED)
        {
            url = body;
            outTable =
"<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html xmlns='http://www.w3.org/1999/xhtml'>
<head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /><title>Region Parcel Info</title>
<link rel='icon' type='image/png' href='https://qielabs.files.wordpress.com/2019/03/favicon.png'></link></head>
<body style=\"background-color:white\">\n<table style=\"background-color:snow\"><thead><tr><th>"
                + "sq.m.</th><th>"
                + "capacity</th><th>"
                + "l.impact</th><th>"
                + "name</th><th>"
                + "owner</th><th>"
                + "group</th><th>"
                + "temp</th><th>"
                + "selected</th></tr></thead><tbody>\n"
                ;
            pos = <2.0, 2.0, 0.0>;
            getDetailsAtPos();
            queryForParcelOwnerAndGroup();
        }
        else
        if (method == "GET")
        {
            llSetContentType(id, CONTENT_TYPE_XHTML);
            llHTTPResponse(id, 200, outTable);
            llSetText("", ZERO_VECTOR, 0.0);
            // llResetScript(); // not if we want to serve the table again
        }
    }
}

 

 

Ooooh so you turned the HTTP architecture around, rather than having your script regularly firing an external endpoint, your script stands by and wait for incoming HTTP requests?

Interesting!

That means in theory I should be able to write a simple script (in my laptop) that loops periodically to get a dump of data from the LSL script in-world?

 

Link to comment
Share on other sites

41 minutes ago, primerib1 said:

That means in theory I should be able to write a simple script (in my laptop) that loops periodically to get a dump of data from the LSL script in-world?

especially easy if you don't need the in-world prim to have a "static' url. just go in-world and ask your thing what its current url is (which should be stored in a global variable, changed on region reset) then

wget URL -O my_data.txt

from any unix-adjacent environment.

ETA: curl works too.

Edited by Quistess Alpha
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

  • 2 weeks later...
On 11/23/2022 at 7:20 PM, Qie Niangao said:

Not so much if you use llHTTPResponse() to the http_request() event.

On 11/25/2022 at 9:01 PM, Quistess Alpha said:

just go in-world and ask your thing what its current url is

I've gotten the URL using llRequestURL(), but every time I try to access it via my browser (just to check), I got "Timed out waiting for response from internal server."

I put in a dump using llOwnerSay() in http_request(key id, string method, string body) event, but it seems the event never gets triggered.

Have I gotten something wrong, I wonder...

EDIT: Indeed I have gotten something wrong. I misunderstood the `id` parameter of the `http_request` event. Now my script is working. Yay!

Edited by primerib1
  • Like 1
Link to comment
Share on other sites

You are about to reply to a thread that has been inactive for 178 days.

Please take a moment to consider if this thread is worth bumping.

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
 Share

×
×
  • Create New...