Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

PHP, HTTPRequest, and a list of UUIDs walk into a bar...

Winter Ventura
Eclectic Randomness
Join date: 18 Jul 2006
Posts: 2,579
11-01-2009 17:25
No, it's not a joke.. It's actually this really simple problem, that's really complicated to explain.

I know how to do a lot of this, in terms of notecards, lists, etc but where it comes to storing large numbers of infromation, I'm stuck.. let me throw out some mystical pseudocode, and we'll see what it looks like. This will very likely NOT compile, and iif it does, it won't do squat.. but hopefully it will help some of you understand.

CODE

integer menuHandle;
integer menuChan = 37829;

default
{
touch_start(integer numdetected)
{
llListenRemove(menuHandle);
menuHandle = llListen(menuChan, "", llDetectedKey(0), "");
llGiveDialog(llDetectedKey(0), "Pick one", ["Join", "Leave"], menuChan);
}

listen(integer channel, string name, key id, string message)
{
if (channel == menuChan)
{
llListenRemove(menuHandle);

if (message == "Join") newsletterUUIDs(id, TRUE);
else if (message == "Leave") newsletterUUIDs(id, FALSE);
}
}
}


Now.. the basic elements of the menuing system established, you can see that we're going to pass a user's UUID and a TRUE/FALSE integer to a function.

Now, that function would, in some universe, send a message to a php script existing someplace else. (on a webserver). let's assume for argument's sake that the function looked something like this.

CODE

key HTTPRequestID ;

newsletterUUIDs (key id, integer add)
{
if (add)
{
HTTPRequestID = llHTTPRequest("http://www.mysite.com/newsletter.php?UUID="
+ (string)id + "&command=add", [], "");
}
else // remove
{
HTTPRequestID = llHTTPRequest("http://www.mysite.com/newsletter.php?UUID="
+ (string)id + "&command=rem", [], "");
}
}


now, newsletter.php

If the command is "add", newsletter.php's job is to search through a list of UUIDs it has stored, and see if the "new" UUID is present. If it's new, the script should append the UUID to the end of the list. If it's already present in the list, it should probably just do nothing.

If the command is "rem", newsletter.php again searches the existing list, and if it finds the UUID in question, it should remove it from the list. If it's not there, it shouldn't do anything.

Returned messages would look like " removed" or "not found" or "added", or "already present"... basic stuff. The script could then "say" these responses into local chat, or display them in temporary hovertext.. it really doesn't matter.

So this is basic in and out list stuff... here comes the hard part.

Script number two.

CODE

string notecard;

default
{
changed (integer change)
{
if (change & CHANGED_INVENTORY)
{
if (llGetInventoryNumber(INVENTORY_NOTECARD) > 0)
{
notecard = llGetInventoryName(INVENTORY_NOTECARD, 0);
sendNewsletter();
}
else notecard = "";
}
}
}


As you can see, this script so far is just joing to send out a notecard, any time that a notecard is dropped on it. The contents of the mystical sendNewsletter function are a bit of a mystery to me.. but here's my best try at what THAT might look like.

CODE

integer totalLines;
key HTTPRequestID ;
integer count = 0;

sendNewsletter()
{
HTTPRequestID = llHTTPRequest("http://www.mysite.com/newsletter.php?UUID="
+ (string)llGetOwner() + "&command=tot", [], "");
}


then we'd need a special sort of response from the script, in the http_response event.. something like "tot|378"

CODE

http_response(key id, integer status, list meta, string body)
{
list commands = llParseString2List(body, ["|"], []);
if (llList2String(commands, 0) == "tot")
{
totalLines = (integer)llList2String(commands, 1);
HTTPRequestID = llHTTPRequest("http://www.mysite.com/newsletter.php?UUID="
+ (string)llGetOwner() + "&command=get&number=" + (string)count, [], "");
}
}


Now the heart of it all. Someplace in all of this, we need to ask the newsletter.php script to give up it's gold. In this case, we probably want to do something like this. We'll use the response token "uuid" (uuid|blahblah-blah-blah-blahblahblah)

CODE

http_response(key id, integer status, list meta, string body)
{
list commands = llParseString2List(body, ["|"], []);

if (llList2String(commands, 0) == "uuid")
{
llGiveInventory((key)llList2String(commands, 1), notecard);
count += 1;
HTTPRequestID = llHTTPRequest("http://www.mysite.com/newsletter.php?UUID="
+ (string)llGetOwner() + "&command=get&number=" + (string)count, [], "");
}
}


Now, all the basic LSL elements are here. The formatting isn't 100% perfect, and obviously it could use a little error handling and noob proofing.. that's all great, but you can see the basics of how this would work.

Script A handles add and remove requests, and passes them to the php script for handling.

Script B waits til it's handed a notecard, and then it asks the php scripts how many UUIDs are on file, and then goes one by one, asking the script for a UUID, then sending out the notecard, asking for the next UUID, handing them a notecard, again and again until the whole list is finished.

I figure at that point, the lsl script receives some sort of EOF in commands 0..
CODE

http_response(key id, integer status, list meta, string body)
{
list commands = llParseString2List(body, ["|"], []);

if (llList2String(commands, 0) == "eof")
{
llRemoveInventory(notecard);
}
}


It can do all sorts of fancy cleanups at that point, or just reset the script. The particulars of the thing aren't so important.

The problem is, I'm missing the PHP side of this thing. Now it could just as easily be a perl/cgi script handling these tasks. It could be using an sql database, or it could just be creating a comma deliniated list of keys in a single "newsletter.txt" file.

But that part is beyond me.

Anyone care to lend a hand?
_____________________

● Inworld Store: http://slurl.eclectic-randomness.com
● Website: http://www.eclectic-randomness.com
● Twitter: @WinterVentura
ElQ Homewood
Sleeps Professionally
Join date: 25 Apr 2007
Posts: 280
11-01-2009 18:36
Man, I hate this crap. I've tried and tried to put your first php functions in here and I give up, it won't let me put any decent code in here. Hang on I'll put it somewhere and give ya a link.

Okay, here we go. LOL I dunno if it's correct or not for a talk page but hey, it's there so you can see it. http://wiki.secondlife.com/wiki/User_talk:ELQ_Homewood
ElQ Homewood
Sleeps Professionally
Join date: 25 Apr 2007
Posts: 280
11-01-2009 18:55
Okay, I messed up a variable there, but I just fixed it :D
ElQ Homewood
Sleeps Professionally
Join date: 25 Apr 2007
Posts: 280
11-01-2009 19:32
Okay..now if I could just figure out how to make hyperlinks work in here lol..it's pretty much all the functions you asked for, altho I put the "tot" command in there, you really don't need it. However, you could always use it to verify that all your subscriptions got filled by having the script tell you the total first, then a count at the end. The whole script is now at

http://wiki.secondlife.com/wiki/User_talk:ELQ_Homewood
Winter Ventura
Eclectic Randomness
Join date: 18 Jul 2006
Posts: 2,579
11-01-2009 23:17
From: ElQ Homewood
Okay..now if I could just figure out how to make hyperlinks work in here lol..it's pretty much all the functions you asked for, altho I put the "tot" command in there, you really don't need it. However, you could always use it to verify that all your subscriptions got filled by having the script tell you the total first, then a count at the end. The whole script is now at

http://wiki.secondlife.com/wiki/User_talk:ELQ_Homewood


CODE

case "dist":
$dist = mysql_query("SEL3CT * FR0M tbl_News");
while($row = mysql_fetch_array($dist))
{
echo $row['uuid'];
sleep(20);
}
break;


I'm a lot confused with what happens here. Will lsl see any of these responses? I mean sure, the first one.. but then there's this twenty second sleep, (which honestly seems a little severe), and then it echoes another line. How is lsl going to deal with that? is there a timeout on http_response?

Also, "dist" isn't syntax from my original post, so I'm a little confused as to how this puzzle piece fits in. Triggering this response, I guess, is asking the server "gimme a uuid, wait 20 seconds, then gimme another one, and keep doing it til you're done."

Assuming for a moment that the sleep is just excessive here.. and the http_response is going to be seen by the lsl script everytime.. I guess the question is just "how do I trigger this?

like this?

CODE

HTTPRequestID = llHTTPRequest("http://www.mysite.com/newsletter.php?UUID="
+ (string)llGetOwner() + "&command=dist", [], "");
_____________________

● Inworld Store: http://slurl.eclectic-randomness.com
● Website: http://www.eclectic-randomness.com
● Twitter: @WinterVentura
ElQ Homewood
Sleeps Professionally
Join date: 25 Apr 2007
Posts: 280
11-02-2009 05:05
"dist" is just something I threw in there because a command had to be given to tell the script to send uuids. I was only thinking so much on the php side, about sending the uuids. Sorry bout that I wasn't thinking so closely on the lsl side about receiving them. I'll have to fix that.

Yeah, "dist" was the trigger I put in there but it could be whatever you wanted to plug into that command= variable. The sleep of 20 seconds is excessive, but it's only there representative of a pause. Won't be needed at all if each line is called for specifically by the lsl.
ElQ Homewood
Sleeps Professionally
Join date: 25 Apr 2007
Posts: 280
11-02-2009 05:46
Okay, if I get inworld in a little bit, I'll give it a quick test. Basically, when sending that distribution command "dist" or whatever you make it, your script also needs to send a "count" variable, so the php knows where you are in the list. Should look like

CODE

case "dist":
$count = $_REQUEST['count'];
$q = mysql_query("SEL3CT * FROM tbl_News");
mysql_data_seek($q,$count);
$row = mysql_fetch_row($q);
echo $row['uuid'];
break;

I updated the php script on the talk page from above to reflect the changes.

EDIT: Ok, it's not working quite right, working on it.
ElQ Homewood
Sleeps Professionally
Join date: 25 Apr 2007
Posts: 280
11-02-2009 06:56
Ok..NOW it's working - inworld and out lol the case snippet is

CODE

case "dist":
$count = $_REQUEST['count'];

$q = mysql_query("SEL3CT * FROM tbl_News");
mysql_data_seek($q,$count);
$row = mysql_fetch_row($q);
echo $row[0];
break;

}


Updating the talk page now :)
Winter Ventura
Eclectic Randomness
Join date: 18 Jul 2006
Posts: 2,579
11-02-2009 13:43
I started work on "actually putting together" the lsl side of this equation, and then did a little testing of the php side you've got there.. and it's clear that I'm missing something.

I'm manually attempting to trigger the script, which I've named "manage.php".. I've created a database called "winter_newsletter" and a user with all the add drop permissions and such, and a password and all that (and I know it's winter_username, not *JUST* username).. when I run the script, I get a very clear "add complete.".. so the script is working.. but in looking in phpMyAdmin, the database still seems to be completely empty. Do I need to create a table?

I'm guessing so, it's probably something like tbl_News ... but I'm not sure all the parameters I need to put in place to make the table the way that this script expects.
_____________________

● Inworld Store: http://slurl.eclectic-randomness.com
● Website: http://www.eclectic-randomness.com
● Twitter: @WinterVentura
ElQ Homewood
Sleeps Professionally
Join date: 25 Apr 2007
Posts: 280
11-02-2009 14:10
Yes, create a table in your MySQL Database named 'tbl_News'. Create it with 1 field. Name that field 'uuid'. Use the varchar datatype with at least 36 character limit. Set it as the primary key.
Winter Ventura
Eclectic Randomness
Join date: 18 Jul 2006
Posts: 2,579
11-03-2009 10:46
As I told ElQ inworld, a friend of mine took pity on me, and handholded me through the setup and ended up writing her own script. The php script she came up with looks very similar to the one ElQ made, and his does seem to work, so it's pretty clear that the only missing component here is the proper preparation of the sql database.

I just wanted to come here and publicly thank ElQ, for putting in so much effort on my behalf. I knew it had to be possible, and the work he did was hardly wasted, because it gave me valuable knowledge when working with my other friend's script, in terms of knowing what functions to ask for. And who knows, maybe someone else will have use for this too.
_____________________

● Inworld Store: http://slurl.eclectic-randomness.com
● Website: http://www.eclectic-randomness.com
● Twitter: @WinterVentura
Hewee Zetkin
Registered User
Join date: 20 Jul 2006
Posts: 2,702
11-09-2009 01:26
FYI I've had a system like this up and running for close to three years now. Perl over MySQL on the server. Simple download of keys in chunks of 20 or so in the LSL. It's for sending IMs not notecards, but not much difference. You'll probably want to distribute the work over multiple LSL scripts in multiple prims so you can use distributed link messages without overrunning event queues if turn-around time is important. It helps with memory too if you cache the list.