############################################################################### ############################################################################### ## Weather V3.4.1 ## ## by Murf ## ## ## ## Undernet Lives! ## ## ## ## This script is the third rev of my weather script and it now pulls ## ## weather from www.wunderground.com (goto their site and click on a few a ## ## ads, lets keep em in business!) and gets US weather by city or zip and ## ## international weather by city. ## ## ## ## Thanks to all for your bug reports and fixes. ## ## ## ############################################################################### ## Runs on TCL 8.0, tested on TCL 8.3. Others folks have run on 1.43, I ## ## have only tested on 1.45 and 1.62. I have had vague reports of problems ## ## on 8.0, if anyone has a solid problem let me know. ## ############################################################################### ## Parsing of the input is very klunky and hopefully will get better. ## ## ## ## These are public and message commands, not partyline! ## ## Usage: .wz [-d] [-o] [-u imc] [-t] [help] [country] ## ## or /msg bot .wz [-d] [-o] [-u imc] [-t] [country]## ## ## ## state should be the two letter state code ## ## country defaults to US and is not needed for US weather ## ## ex. .wz denver,co ## ## .wz 11111 ## ## ## ## Canada & Australia are no longer special cases, and use the same ## ## syntax as other countries ## ## ## ## -d [country] will set a default allowing user ## ## to just type .wz ## ## -o will give output in long format ## ## -u choose units imperial metric ## ## combined ## ## -s [country] get sunrise/sunsewt info ## ## -t [country] get the time ## ## -p precipitation report for US only ## ## ## ## To get the current forecast for today and the next day, use... ## ## ## ## .wzf [country] ## ## ## ## Country codes now match standard internet country codes as closely as ## ## possible, but .wzc allows users to search for their code. Input to .wz ## ## can be entererd as full country name. ## ## ## ## .wzc or /msg bot .wzc ## ## ## ## ## ## Version Info ## ## v3.4.1 Apr 30 2004 ## ## -Fixed around the date (Thanks Neil) ## ## ## ## v3.4 Mar 17 2004 ## ## -Fixed sunrise sunset not showing ## ## -Fixed international weather forcast again ## ## ## ## v3.3.4 May 15 2003 ## ## -Another fix for small change at wunderground that screwed int. ## ## weather. ## ## ## ## v3.3.3 Feb 10 2003 ## ## -Added fix for changes at wunderground (Thanks Jim B) ## ## -Added more moon gif deinitions (Thanks Jim B) ## ## -Removed chandname2name, added at egg v1.54 and only needed for ## ## !channels on ircnet. ## ## ## ## v3.3.2 Oct 07 2002 ## ## -Added variables to set bind flags (thnx J e r e m y) ## ## -New phase of moon, -m flag or bind .moon ## ## -Fixed [pub_wz_forecast]: can't use non-numeric string as operand of ## ## "-" Occured due to unexpected syntax .wzf us. Syntax still ## ## usable. ## ## Sep 24 2002 ## ## -Conditions changed on website, fixed output ## ## -removed -nocase from string compare for tcl 8.0 users ## ## Aug 15 2002 ## ## -fixed output to correctly support !channels (thnx Bjoern) ## ## -Removed allow_public_wz config variable, it wasn't implemented, ## ## this should now only be done per channel via wz_quiet (thnx Shawn) ## ## -Added binds for time/sunrise/precip which can be uncommented ## ## otherwise -t -s -p are used ## ## -Added extra checks for them crazy Canadians & Australians ## ## -Cleaned up the default setting output ## ## -hardcoded sc_call ## ## ## ## v3.3.1 Aug 12 2002 ## ## -Cleaned up most of the 'string first' parsing in favor of regexp ## ## -Sunrise/sunset can be added to the weather output by default ## ## -Can now change binds and changes will reflect in the help section ## ## -Changed format of international forecast so it isn't quite so much ## ## of a flood (thnx PsYxAkIaS) ## ## -Fixed -o, apparently has never worked and I guess is unused since ## ## no one found it. Will probably get rid of it soon. ## ## -Added -p to get precipitation for US locations ## ## -Added -s to get sunrise/sunset info for all locations ## ## ## ## v3.3.0 Aug 8 2002 (and yet another, getting tired of 3.2) ## ## -Cleaned up -u parsing ## ## -Removed .wt in favor of .wz -t ## ## -Added .wt to get localtime. ## ## -Fixed units not being set properly if user default differs from ## ## global default (Thanks j) ## ## ## ## Whacked off all the pre v3.3.x version stuff ## ## ## ## ## ## Latest versions @ http://www.blueday.org/eggdrop.html ## ## Questons & comments to murf@mindless.com ## ############################################################################### ############################################################################### putlog "Loading Weather3.4.1 by murf... http://www.blueday.org/eggdrop.html" ## Allow users to set a default weather city (can just type .wz to get weather)? ## Defaults are saved per user using XTRA fields in the user database. ## yes == 1 no == 0 set allow_user_def_wz 1 ## Set default response to a msg request to either msg or notice ## wz_msg_reply = 1 send via msg ## wz_msg_reply == 0 send via notice set wz_msg_reply 0 ## Set default output to short, just temps, or long, temps/conditions/updated ## short == 0 long == 1 set wz_long 1 ## Disallow public response in specific channels? ## enter channels in lowercase, e.g. ## set wz_quiet "#lame #lamer" set wz_quiet "#mirchelp" ## Set display units to imperial, metric, or both. These are the default ## unless the user overrides with a -u on the command line or in their own ## defaults. ## wz_unit == i set default to imperial ## wz_unit == m set default to metric ## wz_unit == c set default to combined set wz_unit i ## Include sunrise/sunset data along with current conditions by default. ## set to 1 to include by default set wz_default_sr 1 ## Init Globals, DON'T CHANGE!!! ############################################## ## wz_cache cached list of country URL's...they are cleared on reload ## to keep them fresh and not too much of a memory hog ## wz_forecast_f internal flag set to 1 means a forecast is requested along with current conditions ## get_time_f internal flag set to 1 this means get the time only, no weather is possible ## If time is all you want, this can be done, but you got a big ## script just to get the time! ## get_pn_f internal flag set to 1 means its a precipation only request ## get_sr_f internal flag set to 1 means to get sunrise/sunset only ## get_mn_f internal flag set to 1 means to get moon phase only set wz_cache "" set wz_forecast_f 0 set get_time_f 0 set get_pn_f 0 set get_sr_f 0 set get_mn_f 0 ## really I mean it, don't change these here! set wztbind "" set wzsbind "" set wzpbind "" set wzmbind "" ## Binds ###################################################################### ## set the default bind flags here ## examples... ## -|- anyone ## o|o only ops ## f|f only friends ## of|of friends or ops ## wzbind_pub_f is the default for public commands and wzbind_msg_f is for msg commands ## in case you want different flags for each. set wzbind_pub_f "-|-" set wzbind_msg_f "-|-" ## set these to whatever you want, it will carry over into the help now. ## Change .wz .wzc & .wzf to whatever you prefer. set wzbind .wz set wzcbind .wzc set wzfbind .wzf ## If you prefer the time, sunrise, moon and precip to be separate commands as opposed ## to using the -t -s -m and -p flags, leave the following uncommented. ## time bind (don't uncomment this line) set wztbind .time bind pub $wzbind_pub_f $wztbind pub_wz_time bind msg $wzbind_msg_f $wztbind msg_wz_time ## sunrise/sunset bind (don't uncomment this line) set wzsbind .sun bind pub $wzbind_pub_f $wzsbind pub_wz_sunrise bind msg $wzbind_msg_f $wzsbind msg_wz_sunrise ## precip bind (don't uncomment this line) set wzpbind .rain bind pub $wzbind_pub_f $wzpbind pub_wz_precip bind msg $wzbind_msg_f $wzpbind msg_wz_precip ## moon bind (don't uncomment this line) set wzmbind .moon bind pub $wzbind_pub_f $wzmbind pub_wz_moon bind msg $wzbind_msg_f $wzmbind msg_wz_moon ####CODE -- Change it if you like, just don't bitch if you break it ########### ############################################################################### bind pub $wzbind_pub_f $wzbind pub_wz bind msg $wzbind_msg_f $wzbind msg_wz bind pub $wzbind_pub_f $wzcbind pub_country_code bind msg $wzbind_msg_f $wzcbind msg_country_code bind pub $wzbind_pub_f $wzfbind pub_wz_forecast bind msg $wzbind_msg_f $wzfbind msg_wz_forecast ################## Calling procs ############################################## ## Main pub ################################################################### ## pub_wz is called from channel requests sets output type and calls wz_parse proc pub_wz {nick uhand handle chan input} { global botnick wz_quiet set chan [string tolower $chan] if {$input != ""} { set location [string tolower $input] } else { set location $input } if {[lsearch -exact $wz_quiet $chan] != -1} { set outtarg "NOTICE $nick" } else { set outtarg "PRIVMSG $chan" } wz_parse $nick $handle $location $outtarg return 0 } ## Main msg ################################################################### ## msg_wz is called from query requests sets output type and calls wz_parse proc msg_wz {nick uhand handle input} { global wz_msg_reply if {$input != ""} { set location [string tolower $input] } else { set location $input } if {$wz_msg_reply == 0} { set outtarg "NOTICE $nick" } else { set outtarg "PRIVMSG $nick" } wz_parse $nick $handle $location $outtarg return 0 } ## pub forecast ################################################################## ## pub_wz_forecast is called from channel and sets the do forecast flag to 1 and ## then calls pub_wz proc pub_wz_forecast {nick uhand handle chan input} { global wz_forecast_f set wz_forecast_f 1 pub_wz $nick $uhand $handle $chan $input set wz_forecast_f 0 return 0 } ## msg forecast ################################################################## ## msg_wz_forecast is called from query and sets the do forecast flag to 1 and ## then calls msg_wz proc msg_wz_forecast {nick uhand handle input} { global wz_forecast_f set wz_forecast_f 1 msg_wz $nick $uhand $handle $input set wz_forecast_f 0 return 0 } ## Procs to call time if separate bind ########################################## proc pub_wz_time {nick uhand handle chan input} { set input "-t $input" pub_wz $nick $uhand $handle $chan $input return 0 } proc msg_wz_time {nick uhand handle input} { set input "-t $input" msg_wz $nick $uhand $handle $input return 0 } ## Procs to call sunrise if separate bind ########################################## proc pub_wz_sunrise {nick uhand handle chan input} { set input "-s $input" pub_wz $nick $uhand $handle $chan $input return 0 } proc msg_wz_sunrise {nick uhand handle input} { set input "-s $input" msg_wz $nick $uhand $handle $input return 0 } ## Procs to call precip if separate bind ########################################## proc pub_wz_precip {nick uhand handle chan input} { set input "-p $input" pub_wz $nick $uhand $handle $chan $input return 0 } proc msg_wz_precip {nick uhand handle input} { set input "-p $input" msg_wz $nick $uhand $handle $input return 0 } ## Procs to call moon if separate bind ############################################ proc pub_wz_moon {nick uhand handle chan input} { set input "-m $input" pub_wz $nick $uhand $handle $chan $input return 0 } proc msg_wz_moon {nick uhand handle input} { set input "-m $input" msg_wz $nick $uhand $handle $input return 0 } ################################################################################## ## Proc to parse input and return URL ############################################ ## wz_parse does a lot of work. It takes the user input and generates the url ## to get the data from. ## VARS ## webpage the url to get the data from...init to clear ## wzlongt temp var for short or long output flag...init to script default ## wzoset_f flag to check if user set -o. If so and user default output ## requested, then reverse the default output type...init to unset ## wzoutput final var to determine short or long output...init to 99 to ## determine later if it is not set ## wzdef if set, then user is setting defaults...init to not setting defaults ## city requested city...init to clear ## state requested state/province...init to clear ## country requested country...init to clear ## zip requested zip...init to clear proc wz_parse {nick handle location outtarg} { global allow_user_def_wz botnick wz_long wz_cache wz_unit wz_tunit get_time_f get_pn_f get_sr_f get_mn_f set webpage "" set wzlongt $wz_long set wzoset_f 0 set wzoutput 99 set wzdef 0 set city "" set state "" set country "" set zip "" set wz_tunit_reset 0 ## help? if {$location == "help"} { wz_help $nick return 0 } ## -o to set output to long format and strip -o from location ## set wzlongt accordingly if {[regexp -- {-o ?} $location]} { switch $wzlongt { 0 {set wzlongt 1} 1 {set wzlongt 0} } regsub -- {-o ?} $location {} location set wzoset_f 1 } ## -d to set default? If yes, set wzdef 1 and strip the -d from $location ## user must be a validuser if {[regexp -- {-d } $location]} { if {$allow_user_def_wz == 0} { puthelp "NOTICE $nick :Sorry I don't allow defaults to be set. Harrass\ my master!" return 0 } if {[validuser $handle]} { set wzdef 1 } else { puthelp "NOTICE $nick :Sorry, dunno who you are, you can't set a\ default" } regsub -- {-d } $location {} location } ## -u check for user set units ## wz_unit sets inital default ## wz_tunit is used throughout the script as the actual final setting set wz_tunit $wz_unit if {[regexp -- {(-u )([imc])} $location match yoo wz_tunit]} { set wz_tunit_reset 1 if {[regexp {[imc]} $wz_tunit] == 0} { puthelp "NOTICE $nick :Proper syntax for units is .wz -u ... Imperial, Metric, or Combined." return 0 } regsub -- {-u [imc] ?} $location {} location } ## -t check for time check request ## get_time_f is set to flag the rest of the script that this is a time only request if {[regexp -- {-t ?} $location]} { set get_time_f 1 regsub -- {-t ?} $location {} location } ## -p check for precipitation request ## get_pn_f set to flag script its a precip. only request if {[regexp -- {-p ?} $location]} { set get_pn_f 1 regsub -- {-p ?} $location {} location } ## -s check or sunrise/sunset ## get_sr_f to flag for request. if {[regexp -- {-s ?} $location]} { set get_sr_f 1 regsub -- {-s ?} $location {} location } ## -m check or sunrise/sunset ## get_mn_f to flag for request. if {[regexp -- {-m ?} $location]} { set get_mn_f 1 regsub -- {-m ?} $location {} location } ## Is input location all alpha? ie not zip. if {[regexp {[A-Za-z, ]} $location] || $location == ""} { ## is format City,state? This is US city weather, parse and set webpage if {[regexp , $location ]} { set tempcity [string trim [lindex [split $location ,] 0]] regsub -all { } $tempcity {+} city set tstate [string trim [lindex [split $location ,] 1]] set ltstate [llength $tstate] if {$ltstate != 1} { set state [string tolower [string trim [lindex [split $tstate] 0]]] set country [string tolower [string trim [lindex [split $tstate] 1]]] set country [country_search $nick $country 0] if {$country != "" && $country != "us"} { puthelp "NOTICE $nick : Note that Canada, Australia & China do not require a state, correct syntax is .wz city country, use .wz help for more help" } } else { set state $tstate } if {[string length $state] != 2} { puthelp "NOTICE $nick : Please use your 2 letter state code" return 0 } if {$country == ""} { set country "us" } set webpage "/cgi-bin/findweather/getForecast?query=$city%2C$state" ## otherwise must be international weather, city country, parse and set webpage ## code is ugly to account for citys with multiple parts to the name, this is ## easily accounted for above with 'regsub'. ## the switch on lloc (length of location) decides if the location is... ## 0 user default, no location input given ## 1 can't be correct, spew help ## 2 correct number of components for international, parse for location and country ## default more than 2 components...take the last one and search for a country, use ## the rest for the city, not perfect, but works in most cases, always works ## for country code } else { set lloc [llength $location] switch $lloc { 0 { if {[validuser $handle] && $allow_user_def_wz} { set wzoutput [getuser $handle XTRA wz.output] set location [getuser $handle XTRA wz.zip] set city [getuser $handle XTRA wz.city] set state [getuser $handle XTRA wz.state] set country [getuser $handle XTRA wz.ct] if {$wz_tunit_reset == 0 && [getuser $handle XTRA wz.unit] != ""} { set wz_tunit [getuser $handle XTRA wz.unit] } if {$wzoset_f} { switch $wzoutput { 0 {set wzoutput 1} 1 {set wzoutput 0} } } if {$location == "" && $city == ""} { puthelp "NOTICE $nick : You don't have a default city set.\ If you want to set one use .wz -d , otherwise use\ .wz " return 0 } if {[regexp {[0-9]} $location]} { set webpage "/cgi-bin/findweather/getForecast?query=$location" set zip $location } elseif {$country == "us"} { set webpage "/cgi-bin/findweather/getForecast?query=$city%2C$state" } else { set webpage [wz_set_cache $city $state $country] if {$webpage == -1} { set webpage [country_page $nick $country $city $state] if {$webpage != -1} { if {$state == ""} { set lstate zz } else { set lstate $state } lappend wz_cache "$city $lstate $country $webpage" } } if {$webpage == -1} { return 0 } } wz_socket $nick $webpage $location $city $outtarg $wzoutput $zip $country return 0 } else { puthelp "NOTICE $nick :Try .wz help" return 0 } } 1 { puthelp "NOTICE $nick :Try .wz help" return 0 } 2 { set city [string trim [lindex [split $location] 0]] set tmpcountry [string trim [lindex [split $location] 1]] set country [country_search $nick $tmpcountry 0] if {$country == -1} { puthelp "NOTICE $nick :Sorry, $tmpcountry is not supported.\ Try .wzc or /msg $botnick .wzc to find your 2 letter\ country code." return 0 } if {$country == 1} { puthelp "NOTICE $nick :There are multiple matches for\ $tmpcountry , try .wzc or /msg $botnick .wzc to find\ your 2 letter country code." return 0 } } default { set lcity [expr {$lloc - 1}] set tmpcountry [string trim [lindex [split $location] $lcity]] set country [country_search $nick $tmpcountry 0] if {$country == -1} { puthelp "NOTICE $nick :Sorry, $tmpcountry is not supported.\ Try .wzc or /msg $botnick .wzc to find your 2 letter\ country code." return 0 } if {$country == 1} { puthelp "NOTICE $nick :There are multiple matches for\ $tmpcountry , try .wzc or /msg $botnick .wzc to find\ your 2 letter country code." return 0 } set city [string trim [lindex $location 0]] for {set i 1} {$i < $lcity} {incr i} { set tmpcity [lindex $location $i] set city "$city\ $tmpcity" } } } set webpage [wz_set_cache $city $state $country] if {$webpage == -1} { set webpage [country_page $nick $country $city $state] if {$webpage != -1} { if {$state == ""} { set lstate zz } else { set lstate $state } lappend wz_cache "$city $lstate $country $webpage" } } if {$webpage == -1} { return 0 } ##close else } ##close if } ## check for output style if {$wzoutput == 99} { switch $wzlongt { 0 {set wzoutput 0} 1 {set wzoutput 1} } } ## Is user setting defaults? if {$wzdef} { switch $wzlongt { 0 {set lgt "brief"} 1 {set lgt "long"} } switch $wz_tunit { i {set ut "imperial"} m {set ut "metric"} c {set ut "combined"} } if {[regexp {[0-9]} $location]} { if {[string length $location] != 5} { puthelp "NOTICE $nick :Kinda funky zip is $location?" return 0 } set country us set zip $location puthelp "NOTICE $nick :You selected $zip as default." } else { regsub {\+} $country { } tmpcountry if {[string toupper $tmpcountry] != "US"} { puthelp "NOTICE $nick : The defaults you selected are CITY: [city_case $city] COUNTRY: [string toupper $tmpcountry]" } else { puthelp "NOTICE $nick : The defaults you selected are CITY: [city_case $city] STATE: [string toupper $state] COUNTRY: [string toupper $tmpcountry]" } } puthelp "NOTICE $nick :Your default output is $lgt" puthelp "NOTICE $nick :Your default unit is $ut" puthelp "NOTICE $nick :If incorrect try again." puthelp "NOTICE $nick :.wz -d -o -u " setuser $handle XTRA wz.output $wzlongt setuser $handle XTRA wz.zip $zip setuser $handle XTRA wz.city $city setuser $handle XTRA wz.state $state setuser $handle XTRA wz.ct $country setuser $handle XTRA wz.unit $wz_tunit return 0 } ## Is it a US zip code? if {[regexp {[0-9]} $location]} { ## Note that a zip of 00000 takes an interminably long time, 5min, to timeout ## on the wunderground website, and will hang the bot waiting for the ## webpage to timeout, best to just handle it here if {[string length $location] != 5 || $location == "00000"} { puthelp "NOTICE $nick :What kinda funky zip code is $location?" return 0 } set zip $location set country us set webpage "/cgi-bin/findweather/getForecast?query=$location" } wz_socket $nick $webpage $location $city $outtarg $wzoutput $zip $country return 0 } ## Set webpage for country, open socket and find city url ################## ## This is needed since wunderground wont allow international city queries ## It takes you to a country page and from there you can choose a city proc country_page {nick country city state} { global wz_tlang set citymatched 0 ## Open socket set webpage "/global/$country\.html" if {[catch {set wzsock [socket -async www.wunderground.com 80]} sockerr]} { puthelp "NOTICE $nick :$sockerr" puthelp "NOTICE $nick :Try again later, look out the window till then!" close $wzsock return 0 } puts $wzsock "GET $webpage" flush $wzsock ## Search for city URL but first get close. set wzout "" while {[regexp {Temperature} $wzout] == 0} { set wzout [gets $wzsock] ## Not sure if this is needed, but it will break any loops that get to the end of the page ## Better safe than sorry. if {[regexp {} $wzout]} { return 0 } } while {[regexp {} $wzout] == 0} { set wzout [gets $wzsock] if {[string first [string tolower $city] [string tolower $wzout]] !=-1} { regexp {html\">(.*?)} $wzout match citychk if {[string compare [string tolower $city] [string tolower $citychk]] == 0} { set wztmpout [gets $wzsock] set wztmpout [gets $wzsock] if {[regexp {colspan} $wztmpout]} { set citymatched 1 continue } else { break } } } if {[regexp {} $wzout]} { if {$citymatched} { puthelp "NOTICE $nick :Matched $city to $citychk but it had no data, try again later." } else { puthelp "NOTICE $nick :Sorry, $city is not listed, check\ http:/\/\www.wunderground.com for a city thats close." } close $wzsock return -1 } } regexp \=\"(.*?)\" $wzout match city_url close $wzsock return $city_url } ## Check for cached URL ################################################# proc wz_set_cache {city state country} { global wz_cache set webpage -1 foreach entry $wz_cache { set ecity [lindex [split $entry] 0] if {$ecity == $city} { set estate [lindex [split $entry] 1] set ecountry [lindex [split $entry] 2] if {$estate == $state || $estate == "zz"} { if {$ecountry == $country} { set webpage [lindex [split $entry] 3] break } } } } return $webpage } ## Proc to open socket and read webpage in ############################## ## Vars ## wz_forecast_f display forcast flag ## wz_tunit display unit ## get_time_f get time only flag ## get_pn_f get precipitation only flag ## updtime time of last update ## temp the temperature ## outtemp final formatted temp to output ## cond the conditions, windy etc ## chill windchill ## hindex heatindex ## chilldex final formatted heatindex or windchill ## ichilldex imperial value of chilldex ## mchilldex metric value of chilldex ## cchilldex combined value of chilldex ## outhorc is it "Windchill" or "Heatindex"? ## wind value of the wind ## outwind final formatted wind output ## humidity the value of the humidity ## noreport was there any weather reported at the time? ## wdir wind direction proc wz_socket {nick webpage location city outtarg wzoutput zip country} { global wz_forecast_f wz_tunit get_time_f get_pn_f get_sr_f wz_default_sr get_mn_f set updtime "" set temp "" set outtemp "" set cond "" set chill "" set hindex "" set chilldex "" set ichilldex "" set mchilldex "" set cchilldex "" set outhorc "" set wind "" set outwind "" set humidity "" set noreport "" set wdir "" set wzsrise "" set wzsset "" set wfdcond "" set wfdtemp "" set wfncond "" set wfntemp "" ## Open socket to www.wunderground.com and read in webpage...use async for faster ## response. if {[catch {set wzsock [socket -async www.wunderground.com 80]} sockerr]} { puthelp "NOTICE $nick :$sockerr" puthelp "NOTICE $nick :Try again later, look out the window till then!" close $wzsock return 0 } puts $wzsock "GET $webpage" flush $wzsock ## Start the loop to read the buffer in $wzsock. This first loops checks for ## the word 'Updated' to get us in the vicinity of the data. The pages are ## NOT static and this step is needed. set i 0 set wzout "" set wztitle "" set localdate "" while {[regexp {Updated} $wzout] == 0 && $i < 4000} { set wzout [gets $wzsock] incr i ## Get local time if {[regexp {Local Time} $wzout]} { regexp {(.*?)} $wzout match localdate regsub -all {<[^>]*>} $localdate {} localdate } ## Get city name if input was a US zip code if {$i < 50} { if {[regexp Underground $wzout]} { regexp {:(.*?)Forecast} $wzout match wztitle if {[regexp Forecast $wzout] == 0} { regexp {:(.*?) $wzout]} { puthelp "NOTICE $nick :Sorry $location is not available" close $wzsock return 0 } } ## Finally in the right place, start pulling weather data regexp {b>(.*?)(.*?) °F" $wzout]} { regexp {b>(.*?)} $wzout match temp continue } if {$chill == "" && [regexp Windchill $wzout]} { for {set j 0} {$j <= 10} {incr j} { set wzout [gets $wzsock] if {[regexp $wzout]} { regexp {b>(.*?)} $wzout match chill break } } continue } if {$hindex == "" && [regexp HeatIndex $wzout]} { for {set j 0} {$j <= 10} {incr j} { set wzout [gets $wzsock] if {[regexp $wzout]} { regexp {b>(.*?)} $wzout match hindex set stindx [string first $wzout] set etindx [string first $wzout] break } } continue } if {$wind == "" && [regexp Wind $wzout]} { for {set j 0} {$j <= 15} {incr j} { set wzout [gets $wzsock] if {[regexp $wzout]} { regexp {b>(.*?)} $wzout match wdir set wdir [string toupper $wdir] } if {[regexp mph $wzout]} { regexp {b>(.*?)} $wzout match wind break } } set wind [string tolower $wind] continue } # 20040512, ASB, fixed humidity (was reading 1 [now] unneeded line) if {$humidity == "" && [regexp Humidity $wzout]} { regexp {b>(.*?)} $wzout match humidity } } ## Get the sunrise sunset crud here set i 0 while {[regexp Rise $wzout] == 0 && $i < 8000} { incr i set wzout [gets $wzsock] } set wzout [gets $wzsock] set wzout [gets $wzsock] regexp {b>(.*?)(.*?)Now< $wzout]} { set wzout [gets $wzsock] set fcast($j) $wzout set wftime($j) Now incr j set nowcast 0 } } if {[regexp Nowcast $wzout]} { set nowcast 1 } incr i if {[regexp $wzout]} { return 0 } } ## This loop pulls the weather forecast. ## US forcast set l 0 for {set i 0} {$i <= 150} {incr i} { set wzout [gets $wzsock] if {$country == "us"} { if {[regexp left> $wzout]} { regexp {(.*?)} $wzout match wftime($j) set wzout [gets $wzsock] set fcast($j) $wzout if {$j == 5} { break } incr j incr l } } else { ## International Forcast switch $wz_tunit { i {set uc 2} m {set uc 4} c {set uc 0} } if {[regexp left $wzout]} { putlog $wzout set itsnight 0 regexp {(.*?)} $wzout match wftmptime putlog "day $wftmptime" if {[regexp Night $wftmptime]} { set itsnight 1 } for {set k 0} {$k <= 9} {incr k} { set wzout [string trim [gets $wzsock]] if {$k == 0} { if {$itsnight} { set wfncond $wzout } else { set wfdcond $wzout } } if {$k == $uc} { regsub {\°} $wzout {} wzout if {$itsnight} { lappend wfntemp Low: $wzout } else { lappend wfdtemp High: $wzout } } } if {$itsnight} { lappend tmpfcast $wfdcond $wfdtemp -- Night: $wfncond $wfntemp regsub -all {[\{\}]} $tmpfcast {} tmpfcast set fcast($l) $tmpfcast if {$l == 0 && $wftime($l) == ""} { set wftime($l) $wftmptime } putlog "l: $l fcast: $fcast($l)" set tmpfcast "" set wfdcond "" set wfdtemp "" set wfncond "" set wfntemp "" incr l if {$l == 5} { break } } else { set wftime($l) $wftmptime putlog "l: $l $wftime($l)" } incr j } } } } close $wzsock ## Format final output... - == No Report ## chilldex is the final output of both windchill & heatindex, ## depending on which got set. if {$chill != ""} { set outhorc "Wind Chill" set ichilldex $chill set mchilldex [expr {round([expr {[expr {$ichilldex - 32 }] * .55 }])}] set cchilldex [format "%3dF/%-*dC" $ichilldex [string length $mchilldex] $mchilldex] } if {$hindex != ""} { set outhorc "Heat Index" set ichilldex $hindex set mchilldex [expr {round([expr {[expr {$ichilldex - 32 }] * .55 }])}] set cchilldex [format "%3dF/%-*dC" $ichilldex [string length $mchilldex] $mchilldex] } if {[regexp {[0-9]} $temp] == 0} { set noreport "(No Report)" set outtemp "Temp: NR" } else { set itemp $temp set mtemp [expr {round([expr {[expr {$itemp - 32 }] * .55 }])}] # 20040515, ASB, changed %3dF to %fF to deal with new float temps. set ctemp [format "%3fF/%-*dC" $itemp [string length $mtemp] $mtemp] } if {[regexp {[0-9]} $humidity] == 0} { set humidity "Humidity: NR" set noreport "(No Report)" } else { set humidity [format "Humidity: %s" $humidity] } if {$wind == ""} { set outwind "calm" } else { set iwind $wind set mwind [expr {round([expr {$iwind * 1.609344}])}] # 20040515, ASB, changed both %2u to %2f to deal with new float winds. set cwind [format "%2fmph/%2fkmh" $iwind $mwind] } if {$wz_tunit == "i"} { if {$chilldex == ""} {set chilldex "$outhorc: $ichilldex F"} if {$outtemp == ""} {set outtemp "Temp: $itemp F"} if {$outwind == ""} {set outwind "$wdir at $iwind mph"} } if {$wz_tunit == "m"} { if {$chilldex == ""} {set chilldex "$outhorc: $mchilldex C"} if {$outtemp == ""} {set outtemp "Temp: $mtemp C"} if {$outwind == ""} {set outwind "$wdir at $mwind kmh"} } if {$wz_tunit == "c"} { if {$chilldex == ""} {set chilldex "$outhorc: $cchilldex"} if {$outtemp == ""} {set outtemp "Temp: $ctemp"} if {$outwind == ""} {set outwind "$wdir at $cwind"} } if {$chill == "" && $hindex == ""} { set chilldex "" } ## Spew the data if {$get_time_f} { puthelp "$outtarg : It's $localdate in $city" set get_time_f 0 return 0 } puthelp "$outtarg : $city -- $localdate" if {$get_sr_f} { puthelp "$outtarg : Sunrise : $wzsrise Sunset : $wzsset" set get_sr_f 0 return 0 } if {$get_mn_f} { puthelp "$outtarg : The moon $phase." set get_mn_f 0 return 0 } puthelp "$outtarg : $outtemp $chilldex $humidity $noreport" if {$wzoutput} { puthelp "$outtarg : Conditions : $cond with wind $outwind" } if {$wz_default_sr} { puthelp "$outtarg : Sunrise : $wzsrise Sunset : $wzsset" } if {$wz_forecast_f} { set wz_forecast_f 0 puthelp "$outtarg : " puthelp "$outtarg :Forecast" # if {$country != "us"} { # set didit 1 # for {set k 0} {$k < $j} {incr k} { # if {[string first "$wftime($k) Night" $wftime([expr {$k + 1}])] != -1 } { # set shcastday $wftime([expr {$k + 1}]) # set shcast $fcast([expr {$k + 1}]) # puthelp "$outtarg : $wftime($k): $fcast($k) Night: $shcast" # set didit 0 # } elseif {$didit} { # puthelp "$outtarg : $wftime($k): $fcast($k)" # set didit 1 # } # } # return 0 # } for {set i 0} {$i < $l} {incr i} { puthelp "$outtarg : $wftime($i): $fcast($i)" } } return 0 } ## Get the preciptation ############################################## ## Only available for US locations proc get_precip {wzsock nick city outtarg} { global get_pn_f set wzout [gets $wzsock] ## Find the URL for almanac page while {[regexp {Weather and Almanac} $wzout] == 0} { set wzout [gets $wzsock] if {[regexp $wzout]} { close $wzsock return 0 } } regexp {f=(.*?)>Y} $wzout match pn_url close $wzsock if {[catch {set wzsock [socket -async www.wunderground.com 80]} sockerr]} { puthelp "NOTICE $nick :$sockerr" puthelp "NOTICE $nick :Try again later, look out the window till then!" close $wzsock return 0 } puts $wzsock "GET $pn_url" flush $wzsock while {[regexp Precipitation $wzout] == 0} { set wzout [gets $wzsock] if {[regexp $wzout]} { puthelp "NOTICE $nick :Sorry, No precipitation data found for $city. Try again later" return -1 } } for {set i 1} {$i < 7} {incr i} { set wzout [gets $wzsock] if {$i == 2} { set ypn [string trim $wzout] } if {$i == 6} { set nypn [string trim $wzout] } } while {[regexp Month-to-date $wzout] == 0} { set wzout [gets $wzsock] if {[regexp $wzout]} { puthelp "NOTICE $nick :Sorry, No precipitation data found for $city. Try again later" return -1 } } for {set i 1} {$i < 26} {incr i} { set wzout [gets $wzsock] if {$i == 2} { set mpn [string trim $wzout] } if {$i == 6} { set nmpn [string trim $wzout] } if {$i == 17} { set ytdpn [string trim $wzout] } if {$i == 21} { set nytdpn [string trim $wzout] } } close $wzsock ## Spew output puthelp "$outtarg : Precipitation for $city" puthelp "$outtarg : Yesterday Actual: $ypn \" Normal: $nypn \"" puthelp "$outtarg : Month to date Actual: $mpn \" Normal: $nmpn \"" puthelp "$outtarg : Year to date Actual: $ytdpn \" Normal: $nytdpn \"" set get_pn_f 0 return 0 } ## Public country search ############################################# ## Country codes do not match standard internet conventions. Need to ## allow pple to search for their proper code. proc pub_country_code {nick uhand handle chan country} { country_search $nick $country 1 return 0 } ## Message country search ############################################# proc msg_country_code {nick uhand handle country} { country_search $nick $country 1 return 0 } ## Search the country list for country code ########################### proc country_search {nick country sc_call} { global botnick ## Note that there are some US protectorates in the country list. ## I did not code for these, if you're from there you can try ## fixing it yourself, it shouldn't be that hard, just more kluge. set ctlist { antarctica:aq:AA afghanistan:af:AH albania:al:AB algeria:dz:AL angola:ao:AN argentina:ar:AG armenia:am:AM ascensioni#island:ac:AI australia:au:AU austria:at:OS azerbaijan:az:A2 bahrain:bh:BN bangladesh:bd:BW belarus:by:BY belgium:be:BX belize:bz:BH benin:bj:BJ bolivia:bo:BO bosnia:ba:BA botswana:bw:BC brazil:br:BZ brunei:bn:BF bulgaria:bg:BU burkina#faso:bf:HV burma/myanmar:mm:BM burundi:bi:BI canada:ca:CA cambodia:kh:KH cameroon:cm:CM central#african#republic:cf:CE chad:td:CD chile:cl:CH china:cn:CI colombia:co:CO comoros:km:IC congo:cq:CG costa#rica:cr:CS croatia:hr:RH cyprus:cy:CY czech#republic:cz:CZ democratic#yemen:ye:YE denmark:dk:DN djibouti:dj:DJ dominica:dm:DO dominican#republic:do:DR ecuador:ec:EQ egypt:eg:EG el#salvador:sv:ES equatorial#guinea:gq:GQ eritrea:er:E1 estonia:ee:EE ethiopia:et:ET faroe#islands:fo:FA finland:fi:FI france:fr:FR french#guiana:gf:FG french#polynesia:pf:PF gabon:ga:GO gambia:gm:GB georgia:ge:GE germany:de:DL ghana:gh:GH gibraltar:gi:GI greece:gr:GR greenland:gl:GL guatemala:gt:GU guinea:gn:GN guinea-bissau:gw:GW guyana:gy:GY honduras:hn:HO hong#kong:hk:HK hungary:hu:HU iceland:is:IL india:in:IN indonesia:id:ID iran:ir:IR iraq:iq:IQ ireland:ie:IE israel:il:IS italy:it:IY ivory#coast:iv:IV japan:jp:JP jordan:jo:JD kampuchea:kp:KP kazakhstan:kz:KZ kenya:ke:KN kuwait:kw:KW kyrgyzstan:kg:KG lao#peoples#republic:la:LA latvia:lv:LV lebanon:lb:LB lesotho:ls:LS liberia:lr:LI libya:ly:LY liechtenstein:li:LT lithuania:lt:L1 luxembourg:lu:LU macao:mo:MU macedonia:mk:MK madagascar:mg:MG malawi:mw:MI malaysia:my:MS maldives:mv:MV mali:ml:MI malta:mt:ML mauritania:mr:MT mauritius:mu:MA mexico:mx:MX moldova:md:M1 mongolia:mn:MO morocco:ma:MC mozambique:mz:MZ namibia:na:NM nauru:nr:NW nepal:np:NP netherlands:nl:NL new#zealand:nz:NZ nicaragua:ni:NK niger:ne:NR nigeria:ng:NI north#korea:kp:KR norway:no:NO oman:om:OM pakistan:pk:PK panama:pa:PM papua#new#guinea:pg:NG paraguay:py:PY peru:pe:PR philippines:ph:PH poland:pl:PL portugal:pt:PO qatar:qt:QT romania:ro:RO russia:ru:RS rwanda:rw:RW sao#tome#and#principe:st:TP sarawak:sw:MS saudi#arabia:sa:SD senegal:sn:SG seychelles:sc:SC sierra#leone:sl:SL singapore:sg:SR slovakia:sk:S1 slovenia:si:LJ solomon#islands:sb:SO somalia:so:SI south#africa:za:ZA south#korea:kr:KO spain:es:SP sri#lanka:lk:SB st.#helena:sh:HE sudan:sd:SU suriname:sr:SM swaziland:sz:SV sweden:se:SN switzerland:ch:SW syria:sy:SY taiwan:tw:TW tajikistan:tj:TJ tanzania:tz:TN thailand:th:TH togo:tg:TG tonga:to:TO tunisia:tn:TS turkey:tr:TU turkmenistan:tm:TM uganda:ug:UG ukraine:ua:UR united#arab#emirates:ae:ER united#kingdom:uk:UK united#states:us:us uruguay:uy:UY uzbekistan:uz:UZ vanuatu:vu:NH venezuela:ve:VN vietnam:vn:VS western#sahara:eh:EH western#samoa:ws:ZM yemen:ye:YE yugoslavia:yu:YG zaire:zr:ZR zambia:zb:ZB zimbabwe:zw:ZW } set ctmatch 0 set ctsearch [string tolower [string trim $country]] if {$ctsearch == ""} { puthelp "NOTICE $nick :USAGE: .wzc country or \/msg $botnick .wzc country" puthelp "NOTICE $nick :This is a plain text search, enter any part of a\ country name to search on, e.g. .wzc united will return United States \& United\ Kingdom" return 0 } if {[string length $ctsearch] == 2} { set searchindex 1 } else { set searchindex 0 } regsub -all { } $ctsearch {#} ctsearch foreach ct_all $ctlist { set ct [lindex [split $ct_all :] $searchindex] if {[string first $ctsearch $ct] !=-1} { if {$ctmatch == 0} { if {$sc_call} { puthelp "NOTICE $nick :Possible matches for $ctsearch are:" } } incr ctmatch set lctry [lindex [split $ct_all :] 0] regsub -all {#} $lctry { } lctry set uctry [city_case $lctry] set ctcode [lindex [split $ct_all :] 1] set glcode [lindex [split $ct_all :] 2] set ctresult [format "%36s Code: %s" $uctry $ctcode] if {$sc_call} { puthelp "NOTICE $nick :$ctresult" } } } if {$ctmatch == 0} { if {$sc_call} { puthelp "NOTICE $nick :Sorry no matches for $ctsearch" } return -1 } if {$ctmatch > 1} { return 1 } if {$ctmatch} { regsub -all { } $lctry {+} rctry return $glcode } } ## Spew help################################################################### proc wz_help {nick} { global wz_unit wz_long wzbind wzcbind wzfbind wzpbind wztbind wzsbind wzmbind switch $wz_unit { i {set ut "imperial"} m {set ut "metric"} c {set ut "combined"} } switch $wz_long { 0 {set long "long"} 1 {set long "brief"} } puthelp "NOTICE $nick :Commands: (in channel or msg)" puthelp "NOTICE $nick :$wzbind -d -o -u -- current weather" puthelp "NOTICE $nick :$wzfbind -d -o <-u imc> -- current weather & forecast" if {$wztbind != ""} { puthelp "NOTICE $nick :$wztbind -- current time" } if {$wzsbind != ""} { puthelp "NOTICE $nick :$wzsbind -- sunrise/sunset" } if {$wzpbind != ""} { puthelp "NOTICE $nick :$wzpbind -- precipitation" } if {$wzmbind != ""} { puthelp "NOTICE $nick :$wzmbind -- moon phase" } puthelp "NOTICE $nick :$wzcbind -- search for a country code, defaults to US" puthelp "NOTICE $nick :Options:" puthelp "NOTICE $nick :-d will set a default allowing you to type just .wz to see your favorite city" puthelp "NOTICE $nick :-o will give you $long format output" if {$wzpbind == ""} { puthelp "NOTICE $nick :-p will give you a precipitation report" } if {$wztbind == ""} { puthelp "NOTICE $nick :-t will give you the local time" } if {$wzsbind == ""} { puthelp "NOTICE $nick :-s will give sunrise & sunset" } if {$wzmbind == ""} { puthelp "NOTICE $nick :-m will give moon phase" } puthelp "NOTICE $nick :-u selects units imperial, metric, combined, overides current default of $ut" puthelp "NOTICE $nick :Examples:" puthelp "NOTICE $nick : .wz -u m denver,co -- current weather in Denver Colorado in metric." puthelp "NOTICE $nick : .wzf Rome it -- weather forecast for Rome, Italy" puthelp "NOTICE $nick : .wz toronto ca -- current weather in Toronto, Canada" return 0 } ## Capitalize city names ###################################################### ## Capitalize the city since too many pple with old tcl cant use 'string totitle' ## And totitle only works for first word, doesnt account for multiple word cities proc city_case {city} { regsub -all {\+} $city { } ocity set wzcity "" foreach i $ocity { set wzcap [string toupper [string range $i 0 0]] set wzright [string range $i 1 end] set wzjoin "$wzcap$wzright" if {$wzjoin == "S"} { set wzjoin \'s set wzcity [string trim $wzcity] } append wzcity "$wzjoin\ " } set wzcity [string trim $wzcity] return $wzcity } putlog " Weather loaded...bugs/comments to murf@mindless.com"