Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

WeatherPrim (version 1.0)

Jarod Godel
Utilitarian
Join date: 6 Nov 2003
Posts: 729
11-19-2005 18:43
weather.pl
CODE

#!/usr/bin/perl -w
# WeatherPrim
# by: Andrew Burton - tuglyraisin@aol.com
#####

#####
# modules
use HTTP::Response;
use LWP::UserAgent;
use Net::POP3;
use strict;
use XML::Parser;

# mail variables
my $id = 'identity';
my $pw = 'password';
my $servername = 'mail.domain.com';

# Second Life variable
my $slXmlGateway = 'http://xmlrpc.secondlife.com/cgi-bin/xmlrpc.cgi';
my @data = <DATA>;

# Weather Bug XML parsing globals
my $xmlp = XML::Parser->new(Handlers => {Start => \&xml_start,
End => \&xml_end,
Char => \&xml_char});
my $thisday = '';
my $checkx = 0;
my $tag = '';
my $wday = '';
my $wdes = '';
my @weathers = ();

# miscellaneous variables
my $checkm = 0;
my $messtext = '';
my %entry = ();

# main loop
while (1)
{
# Creates the connection
my $pop = &make_pop();

# Logs in
# This will just die if the id and pwd are wrong
my $logcheck = $pop->login($id, $pw);
unless ($logcheck) { die "Die could not login.\n"; }

my $msg = $pop->list();
unless ($msg =~ m/0E0/i) {
foreach my $msgid (keys(%$msg)) {
my $msg_sender = $pop->get($msgid);
foreach my $mline (@$msg_sender)
{
if ($checkm == 1)
{
unless ($mline =~ m/^\n/)
{
$messtext .= $mline;
}
}

if ($mline =~ m/^Object-Name: WeatherPrim/i) { $checkm = 1; }
}

my @emlines = split(/\n/, $messtext);

my ($xmlkey, $wxbkey, $zipcode, $theday) = split(/\,/, $emlines[2]);

if ($theday eq 'today')
{
$theday = 'tonight';
}

my $wreport = &getweather($wxbkey, $zipcode, $theday);

if ($wreport ne "no connection")
{
&sendweather($xmlkey, "100", $wreport);
}

else
{
&sendweather($xmlkey, "400", "Error");
}

# Deletes the message
$pop->delete($msgid);

# Resets some global variables;
$wreport = '';
$checkm = 0;
$messtext = '';
$thisday = '';
$checkx = 0;
$tag = '';
$wday = '';
$wdes = '';

# Cleans out @weathers
while($weathers[0])
{
pop(@weathers);
}
}
}

# closes the connection
$pop->quit();
# Waits a minute before posting
sleep(30);
}

#####
sub sendweather
{
my ($slkey, $code, $weather) = @_;
my $envelope = '';
my @dtemp = @data;

# Loads XML-RPC request into memory
foreach my $line (@dtemp)
{
if ($line)
{
print "$line";

$line =~ s/\$slkey/$slkey/;
$line =~ s/\$code/$code/;
$line =~ s/\$weather/$weather/;
$envelope .= $line;

print "$line";
}
}

# Builds the HTTP request
my $slua = LWP::UserAgent->new();
my $request = HTTP::Request->new(POST => $slXmlGateway);
$request->content_type('text/xml; charset=utf-8');
$request->content($envelope);

# Fires off the HTTP Request
my $result = $slua->request($request);

if ($result->is_success)
{
if ($result->content =~ m/Recieved/)
{
print "101: Connection made.\n";
}

else
{
print "\n\n" . $result->content . "\n\n";
}
}

else
{
print "401: Weather Bug not found.\n";
}
}

#####
sub getweather
{
my ($bugcode, $zipcode, $theday) = @_;
my $ua = LWP::UserAgent->new();
my $url = 'http://' . $bugcode . '.api.wxbug.net/getFullForecast.aspx?' .
'acode=' . $bugcode . '&zipcode=' . $zipcode;

my $result = $ua->get($url);

if ($result->is_success)
{
$thisday = $theday;

my $xml = $result->content;

$xmlp->parsestring($xml);

my $retval = join('|', @weathers);

return($retval);
}

else
{
return("no connection");
}
}

# XML Handlers
# Open tag event
sub xml_start
{
my ($expat, $el, %attr) = @_;

$tag = $el;
}

# Character tag event
sub xml_char
{
my ($expat, $el) = @_;

if ($el =~ m/$thisday/i)
{
$checkx = 1;
}

if ($tag eq 'aws:title' && $checkx == 1)
{
$wday = $el;
}
elsif ($tag eq 'aws:short-title' && $checkx == 1)
{
$wdes = $el;
}
}

# Close tag event
sub xml_end
{
my ($expat, $el) = @_;

if ($el eq "aws:forecast" && $checkx == 1)
{
if (($wday) && ($wdes))
{
my $temp = $wday . ',' . $wdes;
push(@weathers, $temp);
}

$checkx = 0;
}
}

# Creates the POP3 connection
sub make_pop
{
my $pop = Net::POP3->new($servername, Default => 1);
unless ($pop)
{
print "Cannot make POP3 connection.\n";
sleep(5);
$pop = &make_pop();
}

return($pop);
}

__DATA__
<?xml version="1.0"?>
<methodCall>
<methodName>llRemoteData</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>Channel</name>
<value><string>$slkey</string></value>
</member>
<member>
<name>IntValue</name>
<value><int>$code</int></value>
</member>
<member>
<name>StringValue</name>
<value><string>$weather</string></value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>


LSL code
CODE

// Global variables
key gUser;
key gChannel;
integer gListen;
integer qCount = 0;
integer tCount = 1;
integer isReady = 0;
string gZip;
string gWxBugKey;
string gDay;
string weatherMail = "identity@domain.com";

// To read notecard data
string noteName = "wxbug";
integer noteLine = 0;
key noteQuery;


// Stole this from the Wiki, it dumps error info
DEBUG(list out)
{
llSay(0, llList2CSV(out));
}

/////
// This is the default state
default
{
state_entry()
{
if (gWxBugKey == "")
{
noteQuery = llGetNotecardLine(noteName, noteLine);
}

llSetColor(<0, 255, 0>, ALL_SIDES);

if (isReady == 0)
{
llSay(0, "WeatherPrim ready.");
isReady = 1;
}
}

dataserver(key query_id, string data)
{
if (query_id == noteQuery)
{
if (data != EOF)
{
gWxBugKey = data;
}
}
}

touch(integer total_number)
{
llSetColor(<255, 0, 0>, ALL_SIDES);
gUser = llDetectedKey(0);
state cmdline;
}
}

/////
// This is the state that handles user interfacing
state cmdline
{
state_entry()
{
llSay(0, "In which U.S. zip code do you want to know about the weather?");
llSay(0, "Please just give say the first five digits.");
gListen = llListen(0, "", gUser, "");
}

listen(integer channel, string name, key id, string message)
{
if (qCount == 1)
{
message = llToLower(message);

if (message == "monday" || message == "tuesday" || message == "wednesday" ||
message == "thursday" || message == "friday" || message == "saturday" ||
message == "sunday")
{
gDay = message;
llSay(0, "Okay, let me look that up.");
llOpenRemoteDataChannel();
}

else if (message == "today")
{
gDay = message;
llSay(0, "Today's weather? Why not just look out a window?");
llSleep(2);
llSay(0, "Just kidding.");
llOpenRemoteDataChannel();
}

else
{
llSay(0, "Could you repeat that, I misunderstood you.");
}
}

else if (qCount == 0)
{
if (llStringLength(message) == 5)
{
qCount++;
gZip = message;
llSay(0, "And what day do you want to know about?");
llSay(0, "Please just tell me either the weekday, or say today.");
}

else
{
llSay(0, "Sorry, what was that zip code?");
}
}
}

remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval)
{
if (type == REMOTE_DATA_CHANNEL)
{
gChannel = channel;
state xmlrpc;
}

else
{
DEBUG(["Unexpected event type", type, channel, message_id, sender, ival, sval]);
}
}

state_exit()
{
llSay(0, "This could take a minute, please be patient.");
}
}

/////
// This is the state that accepts data from the net
state xmlrpc
{
state_entry()
{
llSetTimerEvent(1.0);
string weathermsg = (string)gChannel + "," + gWxBugKey + "," + gZip + "," + gDay;
llEmail(weatherMail, "weather request", weathermsg);
}

remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval)
{
if (type == REMOTE_DATA_REQUEST)
{
if (ival == 100)
{
llRemoteDataReply(channel, message_id, "Recieved", 101);
list dayList = llParseString2List(sval, ["|"], []);
integer dlcnt = 0;

while (llList2String(dayList, dlcnt) != "")
{
list dayInfo = llParseString2List(llList2String(dayList, dlcnt), [","], []);
string day = llList2String(dayInfo, 0);
string cnd = llList2String(dayInfo, 1);

llSay(0, cnd + " on " + day + ".");

dlcnt++;
}

state default;
}

else if (ival == 400)
{
llRemoteDataReply(channel, message_id, "Recieved", 401);
llSay(0, "Looks like there was a problem. Pleast try again later.");
state default;
}

else
{
llSay(0, sval);
llRemoteDataReply(channel, message_id, "Sorry, I have no response for that code.", 0);
}
}

else
{
DEBUG(["Unexpected event type:", type, channel, message_id, sender, ival, sval]);
}
}

timer()
{
if (tCount < 120)
{
tCount++;
}

else
{
llSay(0, "I do apologize. There seems to be an error. Please try again later.");
llSetTimerEvent(0.0);
state default;
}
}

state_exit()
{
llCloseRemoteDataChannel(gChannel);
llListenRemove(gListen);
gZip = "";
gDay = "";
tCount = 0;
qCount = 0;

llSleep(2);
}
}



Installation Instructions:
1. Load weather.pl on your server.

2. Change $id, $pw, and $servername to mtach your information.

3. Create a notecard called wxbug, and place your WeatherBug API licensecode it.

4. Create a prim, and place the LSL code into it.

5. Change weatherMail to your email address and save the code.

6. Click on your WeatherPrim, and give it a whirl.

Known Issues:
Once in a while, weather.pl will crash because of a problem with XML::Parser about 10-15% of the time. I'm still trying to figure out why it does this, but it is a known issue.

_____________________
"All designers in SL need to be aware of the fact that there are now quite simple methods of complete texture theft in SL that are impossible to stop..." - Cristiano Midnight

Ad aspera per intelligentem prohibitus.
Nada Epoch
The Librarian
Join date: 4 Nov 2002
Posts: 1,423
Discussion thread
11-20-2005 22:54
/54/00/72837/1.html
_____________________
i've got nothing. ;)