· 6 years ago · Sep 11, 2019, 12:48 AM
1###############################################################
2# SayWeather ver. 6.03 by SpiKe^^ www.mytclscripts.com #
3###############################################################
4
5# International Weather script for Eggdrop.
6# Displays in both F/C and MPH/KPH
7# Will return weather from www.apixu.com
8# Requires a Free Api Key from www.apixu.com
9# Requires TCL8.5 or greater
10# Has been tested on Eggdrop 1.8.3
11
12# You may use ".chanset #channel +weather" for each
13# channel you wish to use this in,
14# Or set your SayWeather channel(s) in the script settings.
15
16# Usage: !w :or: !w <input>
17# Input can be <city> <zip code> <airport code> <nick>, etc.
18
19
20###############################################################
21## SayWeather version 6.03 07/12/2018 ##
22## Original Script by (lily@disorg.net) ##
23## Version 5.0+ updates by SpiKe^^ www.mytclscripts.com ##
24## ##
25## -> NEW IN VERSION 6.03 <- ##
26## - Added new setting: You may now choose to set your ##
27## weather channels in the SayWeather Script Settings, ##
28## Or continue to use: .chanset #channel +weather ##
29## - Fixed the problem with adding a location by zip code. ##
30## example: You must provide a city or zip code to ##
31## set as LocationID: @92583 (thanks roger:) ##
32## ##
33################## - Version 5.0+ History - ###################
34## VERSION 6.02 - 29/09/2018 ##
35## - Replaced the Weather Forecast (removed in versoin 6.01) ##
36## - Script now has 3 Weather commands, the defaults are: ##
37## !w :Shows a Short version of the Current Weather. ##
38## !wz :Shows the Full Current Weather conditions. ##
39## !w+ :Shows Full Current Weather plus 3 Day Forecast. ##
40## - Script now has 2 Forecast commands, the defaults are: ##
41## !f :Shows a Short version of the 3 Day Forecast. ##
42## !fc :Shows the Full version of the 3 Day Forecast. ##
43## - Added a new Sky/Astro command, the default is: !sky ##
44## - You can specify the length of all Forecast/Sky results. ##
45## example: !fc5 miami, fl (5 day forecast for miami) ##
46## - Added a global time & IP locator cmd, default is: !time ##
47## - You can now specify a Nick as the location for commands ##
48## !ti bart :see time at bart's saved def location. ##
49## - You can now save as many weather locations as you want: ##
50## !w set miami, fl :set default location to miami, fl ##
51## !w set @1 toledo :set LocationID @01 to toledo, ohio ##
52## - To access the location saved as LocationID @01, use: ##
53## !fc5 @1 :see the 5 day forecast for toledo, ohio ##
54## - To delete the location saved as LocationID @01, use: ##
55## !w set @1 :Delete LocationID @01 (set @1 to empty) ##
56## - Added command options to see/list your saved locations: ##
57## !w -see :see the current default weather location ##
58## !w -list :list the default & any saved LocationIDs ##
59## ##
60## VERSION 6.01 - 25/08/2018 ##
61## - Changed the weather source page to www.apixu.com ##
62## - Changed script name from WunderWeather to SayWeather ##
63## - Script now requires a Free API Key from www.apixu.com ##
64## - Temporarily removed the forecast part of the reply. ##
65## Recoded forecast will be available in next version ##
66## VERSION 5.03 - 04/12/2017 ##
67## - Users can now set/save their default weather location. ##
68## example: !w set miami, fl ##
69## To use that saved weather location, just type: !w ##
70## Does Not use the Eggdrop user file (saves to a file) ##
71## - Added metric conversion of most forecast strings. ##
72## - Script now allows multiple public weather triggers. ##
73## VERSION 5.01 - 28/10/2017 ##
74## - All processes and globals are now in a namespace ##
75## - Replaced weather forecast (removed by Kiely Allen) ##
76## - Replaced metric setting (removed by Kiely &/or David) ##
77## - Added 3 new settings for removing colors and/or bolds ##
78## - Added Throttle Users - Thanks to user & speechles ##
79###############################################################
80
81
82
83package require Tcl 8.5
84package require http
85
86namespace eval saywz { variable sayw
87#######################################################
88## - Begin Script Settings - Begin Script Settings - ##
89#######################################################
90
91# Set your Api Key from www.apixu.com (REQUIRED) #
92set sayw(api_key) "970f453408104e938c3133351191007"
93
94
95# Command Char(s) to use for public binds
96# Examples: "!" or "."
97# Or a Space Separated List: "! . ?"
98set sayw(cmdchars) "."
99
100
101# Set public Weather Command(s): (short current weather) #
102# This command shows only the current weather conditions. #
103# Note: set these empty to disable each command #
104set sayw(cmds_w) "w"
105
106# Set public Weather Command(s): (full current weather) #
107# This command shows only the current weather conditions. #
108set sayw(cmds_wz) "clima weather"
109
110# Set public Weather Command(s): (full current & forecast) #
111# This command shows the current weather and 3 day forecast. #
112# You can also specify days (1-7): ex. !wp5 paris, fr #
113set sayw(cmds_wp) "w+ wp weather+"
114
115
116# Set public Forecast Command(s): (short 1 to 7 day forecast) #
117# This command always returns the forecast on a Single Line. #
118# Command shows a short 3 day forecast, by default. #
119# You can also specify days (1-7): ex. !f5 paris, fr #
120set sayw(cmds_f) "f"
121
122# Set public Forecast Command(s): (full 1 to 7 day forecast) #
123# This command shows a 3 day forecast, by default. #
124# You can also specify days (1-7): ex. !fc5 paris, fr #
125set sayw(cmds_fc) "fc forecast"
126
127
128# Set public Sky/Astro Command(s) #
129# This command shows the sunrise/sunset & moonrise/moonset. #
130set sayw(cmds_sk) "sk astro sky"
131
132# Set public Time Command(s) #
133# This command shows the local time at your location. #
134set sayw(cmds_ti) "ti time"
135
136
137
138# Set route/filename for the users default weather locations #
139set sayw(usrfile) "scripts/sayweather.users"
140
141# Use Metric as the Primary in channel output?? #
142# 1 = Yes, use metric as primary output. (0=no) #
143set sayw(metric) 1
144
145# Use Color Changing Temperatures?? (1=yes 0=no) #
146set sayw(colortemp) 1
147
148# Use SayWeather Logo Color?? (1=yes 0=no)#
149set sayw(colorlogo) 1
150
151# Show Weather Item Names in Bold?? (1=yes 0=no) #
152set sayw(boldnames) 1
153
154# Amount user can issue before Throttle #
155set sayw(throttle_max) 2
156
157# Throttle time (seconds) #
158set sayw(throttle_time) 30
159
160# Set udef flag used to enable this script by channel #
161# Use: .chanset #channel +weather
162set sayw(udef_flag) "clima"
163
164# You may also choose to add perm channel(s) here, if that works better for you:) #
165# Leave this empty to add all SayWeather channels using the .chanset command.
166# Or a Space Separated List: set sayw(chans) "#channel #chan2 #another"
167# Or for all channels, use: set sayw(chans) "*"
168set sayw(chans) ""
169
170# Set max chars per line of text to the server #
171# Note: usually 512 minus the msg header (at least 420) #
172set sayw(max_chars) 440
173
174
175
176#######################################################
177#### - End Script Settings - End Script Settings - ####
178#######################################################
179
180setudef flag $sayw(udef_flag)
181variable nsc [namespace current]
182variable name "SayWeather"
183variable ver "6.03"
184variable auth "SpiKe^^"
185
186proc say_w {nk uh hn ch input} { variable sayw
187 if {[channel get $ch $sayw(udef_flag)] || $sayw(chans) eq "*"} { set valid 1
188 } elseif {[lsearch -exact -nocase $sayw(chans) $ch] > -1} { set valid 1 }
189 if {![info exists valid]} { return 0 } ; unset valid
190
191 set input [join [lassign [split [string trim $input]] cmd]]
192 set doing "" ; set setdays 0
193
194 if {[string index $cmd 0] in $sayw(cmdchars)} {
195 set c [string range $cmd 1 end]
196 if {$c eq ""} { return 0 }
197 if {[string match {*?[0-9]} $c]} { set z [string index $c end]
198 set cz [string range $c 0 end-1]
199 } else { set z "" }
200 foreach {x y} {w 0 wz 1 wp 3 f 3 fc 3 sk 3 ti 0} {
201 if {[lsearch -exact -nocase $sayw(cmds_$x) $c] > -1} {
202 set doing $x ; set fcdays $y ; break
203 }
204 if {$z ne "" && $x in {wp f fc sk}} {
205 if {[lsearch -exact -nocase $sayw(cmds_$x) $cz] > -1} {
206 if {$z==0} { set z $y } elseif {$z>7} { set z 7 }
207 set doing $x ; set fcdays $z ; set setdays 1 ; break
208 }
209 }
210 }
211 }
212 if {$doing eq ""} { return 0 }
213 if {[throttle $uh $nk $ch]} { return 0 }
214
215 if {$doing eq "f"} { set doing "fc" ; set shortfc 1 } { set shortfc 0 }
216 set input [split [strim $input]]
217 lassign [split [string trim $uh ~] @] user host
218 set id [slower "$nk,$user,$ch"]
219 set mx [expr {$sayw(max_chars) + 1}]
220 if {$sayw(boldnames)==0} { set b "" } else { set b "\002" }
221 if {$sayw(colorlogo)==0} { set logo "" ; set endl ""
222 } else { set logo "\00313" ; set endl "\003" }
223
224 variable wusers
225 if {[info exists wusers($id)]} { set wusers(updated) 1
226 set wusers($id) [lreplace $wusers($id) 0 0 [unixtime]]
227 set udata $wusers($id)
228 } else { set udata "" }
229 if {![llength $input] && $udata eq ""} {
230 puthelp "PRIVMSG $ch :You must provide a city or zip code or set a default location"
231 return 0
232 }
233 set opt [slower [lindex $input 0]] ; set isset 0 ; set dun 0
234 set op2 [slower [lindex $input 1]] ; set locid ""
235
236 if {$opt in {see -see list -list}} {
237 if {$opt in {see -see}} { set opt "see" } else { set opt "list" }
238 if {$op2 in {all -all}} { set op2 "all" } else { set op2 "" }
239
240 if {$udata eq ""} { set dun 1
241 puthelp "PRIVMSG $ch :No saved weather locations for $nk!$user,$ch"
242 } elseif {[set def [lindex $udata 1]] eq "" && $opt eq "see"} { set dun 1
243 puthelp "PRIVMSG $ch :No default weather location for $nk!$user,$ch"
244 }
245 if {$dun==1} { set tx "To set a default weather location now, use:"
246 append tx " [lindex $sayw(cmdchars) 0][lindex $sayw(cmds_w) 0]"
247 puthelp "PRIVMSG $ch :$tx -set <city or zip code or airport, etc.>"
248 return 0
249 }
250 if {$opt eq "see"} {
251 puthelp "PRIVMSG $ch :Default weather location: $def" ; return 0
252 }
253
254 set tx "${logo}List saved weather locations:$endl ${b}default location:$b"
255 if {$def eq ""} { append tx " none" } else { append tx " $def" }
256 set tx2 ""
257
258 if {[llength $udata]>2} { set tmls ""
259 foreach {x y} [lrange $udata 2 end] { lappend tmls "${b}$x:$b $y" }
260 set tm "$tx - [join $tmls { - }]"
261 if {[string length $tm]<=$mx} { set tx $tm
262 } else { set tm "${logo}LocationIDs:$endl [join $tmls { - }]"
263 if {[string length $tm]<=$mx} { set tx2 $tm
264 } else { set pre "${logo}LocationIDs:$endl"
265 set tm [join $tmls { - }] ; set xtra 0
266 while {[string length "$pre $tm"]>=$mx} { incr xtra
267 set tmls [lrange $tmls 0 end-1] ; set tm [join $tmls { - }]
268 if {[set len [string length "$pre $tm"]]<$mx} {
269 set left [expr {$mx - $len}]
270 if {$left>=11} { set left "- \[+$xtra more\]"
271 } elseif {$left>=6} { set left "- \[+$xtra\]"
272 } else { set left "\[+$xtra\]" }
273 set tx2 "$pre $tm $left" ; break
274 }
275 }
276 }
277 }
278 } else { append tx " - No saved weather LocationIDs for $nk!$user,$ch" }
279
280 putserv "PRIVMSG $ch :$tx"
281 if {$tx2 ne ""} { putserv "PRIVMSG $ch :$tx2" }
282 return 0
283 }
284
285 if {$opt in {set -set}} { set isset 1
286 set input [lrange $input 1 end]
287
288 if {[sdigit $op2] && [string length $op2]<5} { set locid "@$op2"
289 if {[string length $op2]==1} { set locid "@0$op2" }
290 } elseif {[string match "@?*" $op2]} { set o2 [string range $op2 1 end]
291 if {[sdigit $o2] && [string length $o2]==1} { set locid "@0$o2"
292 } elseif {$o2 ne ""} { set locid "@$o2" }
293 }
294 if {$locid ne ""} { set input [lrange $input 1 end] }
295
296 if {![llength $input]} {
297 if {$locid eq ""} {
298 if {[lindex $udata 1] eq ""} {
299 puthelp "PRIVMSG $ch :You must provide a city or zip code to set as default location"
300 } else {
301 if {[llength $udata]==2} { unset wusers($id)
302 puthelp "PRIVMSG $ch :Removed all saved weather locations for $nk!$user,$ch"
303 } else { set wusers($id) [lreplace $wusers($id) 1 1 ""]
304 puthelp "PRIVMSG $ch :Removed default weather location for $nk!$user,$ch"
305 }
306 }
307 } else {
308 if {[set x [lsearch -exact $udata $locid]] == -1} {
309 puthelp "PRIVMSG $ch :You must provide a city or zip code to set as LocationID: $locid"
310 } else { set udata [lreplace $udata $x [incr x]]
311 if {[llength $udata]==2 && [lindex $udata 1] eq ""} {
312 unset wusers($id)
313 puthelp "PRIVMSG $ch :Removed all saved weather locations for $nk!$user,$ch"
314 } else { set wusers($id) $udata
315 puthelp "PRIVMSG $ch :Removed weather LocationID: $locid for $nk!$user,$ch"
316 }
317 }
318 }
319 return 0
320 }
321
322 } else { set fnd 0 ; set nick ""
323 if {[sdigit $opt] && [string length $opt]==1 && $setdays==0} {
324 if {$op2 ne "" && $doing in {wp fc sk}} { set setdays 1
325 if {$opt > 7} { set opt 7 }
326 if {$opt > 0} { set fcdays $opt }
327 set input [lrange $input 1 end]
328 set opt [slower [lindex $input 0]]
329 set op2 [slower [lindex $input 1]]
330 }
331 }
332
333 if {![llength $input]} { set fnd def
334 if {[set input [lindex $udata 1]] eq ""} {
335 puthelp "PRIVMSG $ch :You must provide a city or zip code to set as default location"
336 return 0
337 }
338 } else { set isnum 0
339 if {[string match "?>*" $opt]} { set fnd loc
340 set opt [string range $opt 1 end]
341 } elseif {[string match ">*" $opt]} { set fnd loc }
342
343 if {[sdigit $opt] && [string length $opt]<5 && $op2 eq ""} {
344 set locid "@$opt"
345 if {[string length $opt]==1} { set locid "@0$opt"
346 if {$setdays==0} { set isnum 1 }
347 }
348 } elseif {[string match "@*" $opt]} {
349 set o2 [string range $opt 1 end]
350 if {[sdigit $o2] && $op2 eq "" && [string length $o2]==1} {
351 set locid "@0$o2"
352 } elseif {$o2 ne ""} { set locid [slower [join $input _]]
353 } elseif {$op2 ne ""} {
354 set locid [slower "@[join [lrange $input 1 end] _]"]
355 } else {
356 puthelp "PRIVMSG $ch :Invalid weather LocationID: @" ; return 0
357 }
358 }
359
360 if {$locid ne ""} {
361 if {[set x [lsearch -exact $udata $locid]] == -1} {
362 if {$isnum==1 && $doing in {wp fc sk} && [lindex $udata 1] ne ""} {
363 if {$opt > 7} { set opt 7 }
364 if {$opt > 0} { set fcdays $opt }
365 set setdays 1 ; set fnd def ; set input [lindex $udata 1]
366 } else {
367 puthelp "PRIVMSG $ch :Not a saved weather LocationID: $locid"
368 return 0
369 }
370 } else { set fnd locid ; set input [lindex $udata [incr x]] }
371 } elseif {$fnd eq "0"} {
372 if {![string match "!*" $opt] && ![string match "*!" $opt]} {
373 set locid [slower "@[join $input _]"]
374 if {[set x [lsearch -exact $udata $locid]] > -1} {
375 set fnd locid ; set input [lindex $udata [incr x]]
376 } else { set locid "" }
377 }
378 }
379
380 if {$fnd eq "0"} { set saynk 0
381 if {[string match "!*" $opt] || [string match "*!" $opt]} {
382 set nick [string trim $opt "!"] ; set saynk 1
383 if {$nick eq "" && $op2 eq ""} {
384 puthelp "PRIVMSG $ch :Invalid weather Nick: !"
385 return 0
386 }
387 if {$nick eq ""} { set nick $op2 }
388 } elseif {$op2 eq ""} { set nick $opt }
389 if {$nick ne ""} { set uid ""
390 if {[set y [getchanhost $nick $ch]] ne ""} {
391 lassign [split [string trim $y ~] @] unam
392 set uid [slower "$nick,$unam,$ch"]
393 } elseif {[llength [set x [array get wusers "$nick,*,[slower $ch]"]]]} {
394 set lut 0
395 foreach {i v} $x { lassign $v ut
396 if {$ut > $lut} { set uid $i ; set lut $ut }
397 }
398 set unam [lindex [split $uid ","] 1]
399 }
400 if {$uid == ""} {
401 if {$saynk == 1} {
402 puthelp "PRIVMSG $ch :Invalid weather Nick: [join $input]"
403 return 0
404 }
405 } elseif {![info exists wusers($uid)]} {
406 puthelp "PRIVMSG $ch :$nick!$unam has no saved weather locations"
407 return 0
408 } elseif {[set x [lindex $wusers($uid) 1]] eq ""} {
409 puthelp "PRIVMSG $ch :$nick!$unam has no default weather location"
410 return 0
411 } else { set fnd nick ; set input $x ; set wusers(updated) 1
412 set wusers($uid) [lreplace $wusers($uid) 0 0 [unixtime]]
413 }
414 }
415 }
416
417 if {$fnd eq "loc"} { set opt [string trim $opt "<>"]
418 if {$opt eq "" && $op2 eq ""} {
419 puthelp "PRIVMSG $ch :Invalid weather Location: [join $input]"
420 return 0
421 }
422 if {$opt eq ""} { set input [lrange $input 1 end]
423 } else { set input [lreplace $input 0 0 $opt] }
424 }
425 }
426 }
427 set input [join $input]
428
429 if {$fcdays>0} { set addr "http://api.apixu.com/v1/forecast.xml?key="
430 } else { set addr "http://api.apixu.com/v1/current.xml?key=" }
431 set query [::http::formatQuery q $input]
432 set safe "${addr}\[censored\]&$query"
433 append addr "$sayw(api_key)&$query"
434 if {$fcdays>0} { append addr "&days=$fcdays" ; append safe "&days=$fcdays" }
435
436 catch { set token [::http::geturl $addr -timeout 10000] } error
437 # error condition 1, socket error or other general error
438 if {![string match -nocase "::http::*" $error]} {
439 set error [string totitle [string map {"\n" " | "} $error]]
440 putserv "PRIVMSG $ch \00313Error1:\003 :$error \( $safe \)"
441 return 0
442 }
443 # error condition 2, http error
444 if {![string equal -nocase [::http::status $token] "ok"]} {
445 set error [string totitle [::http::status $token]]
446 putserv "PRIVMSG $ch \00313Error2:\003 :$error \( $safe \)"
447 return 0
448 }
449
450 set html [::http::data $token] ; ::http::cleanup $token
451 #set open [open scripts/saywz.xml.txt w]; puts $open $html; close $open
452
453 ######### Get Error Data #########
454 regexp {<error>(.*?)</error>} $html - err
455 if {[info exists err]} {
456 regexp {<code>(.*?)</code><message>(.*?)</message>} $err - code msg
457 if {$code==1006} { puthelp "PRIVMSG $ch :$input Not Found"
458 } else { puthelp "PRIVMSG $ch :\00313Error$code:\003 $msg \( $safe \)" }
459 return 0
460 }
461
462 ######## Get Location Data ########
463 regexp {<location>(.*?)</location>} $html - loc
464 if {![info exists loc]} {
465 puthelp "PRIVMSG $ch :\00313Error:\003 No Error and No Location Data??"
466 return 0
467 }
468 foreach term {name region country lat lon localtime_epoch localtime} {
469 regexp "<$term>(.*?)</$term>" $loc - $term
470 if {![info exists $term]} { set $term "" }
471 }
472 unset loc
473
474 set where "$name, "
475 if {$region ne ""} { append where "$region, " }
476 if {[string match -nocase "*united states*" $country]} {
477 append where "United States"
478 } else { append where "$country" }
479
480 set clogo "${logo}$where:$endl"
481 if {$isset==1} { set wusers(updated) 1
482 if {$locid eq ""} {
483 set wusers($id) [lreplace $udata 0 1 [unixtime] [split $where]]
484 puthelp "PRIVMSG $ch :Set default weather location to: $where"
485 } else {
486 if {![llength $udata]} { lappend udata [unixtime] "" }
487 if {[set x [lsearch $udata $locid]] > -1} { incr x
488 set wusers($id) [lreplace $udata $x $x [split $where]]
489 } else { set wusers($id) [lappend udata $locid [split $where]] }
490 puthelp "PRIVMSG $ch :Set weather LocationID $locid to: $where"
491 }
492 return 0
493 }
494 lassign [split $localtime] ldate ltime
495 set lsec [clock format $localtime_epoch -format {:%S}]
496 set puttx "" ; set put2 ""
497
498 ### !ti Bails Out Here ###
499 if {$doing eq "ti"} { set clogo "${logo}$where$endl ($lat, $lon):"
500 puthelp "PRIVMSG $ch :$clogo [getday $ldate], [getdate $ldate] $ltime$lsec"
501 return 0
502 }
503
504 ######## Get Current Data ########
505 if {$doing in {w wz wp}} {
506 regexp {<current>(.*?)</current>} $html - curr
507 if {[info exists curr]} {
508 set terms [list last_updated temp_f temp_c is_day text wind_mph wind_kph]
509 lappend terms wind_dir pressure_in pressure_mb precip_in precip_mm
510 lappend terms humidity cloud feelslike_f feelslike_c vis_miles vis_km
511 foreach term $terms {
512 regexp "<$term>(.*?)</$term>" $curr - $term
513 if {![info exists $term]} { set $term "" }
514 }
515 unset curr
516 lassign [split $last_updated] udate utime
517 } else { set x "Current weather conditions unavailable."
518 puthelp "PRIVMSG $ch :$clogo $x Please try again later."
519 return 0
520 }
521 }
522
523 ######## Get Forecast Data ########
524 if {$doing in {wz wp fc sk}} {
525 regexp {<forecast>(.*?)</forecast>} $html - forc
526 if {[info exists forc]} { set cnt 0
527 set terms [list date maxtemp_f maxtemp_c mintemp_f mintemp_c]
528 lappend terms totalprecip_in totalprecip_mm avghumidity text
529 lappend terms sunrise sunset moonrise moonset
530 while {$cnt < $fcdays} { incr cnt
531 regexp {<forecastday>(.*?)</forecastday>(.*?)$} $forc - day$cnt forc
532 if {[info exists day$cnt]} { set ara fc${cnt}
533 foreach term $terms {
534 regexp "<$term>(.*?)</$term>" [set day$cnt] - ${ara}($term)
535 if {![info exists ${ara}($term)]} { set ${ara}($term) "" }
536 }
537 unset day$cnt
538 } else { break }
539 }
540 unset forc
541
542 ### !fc & !sk Bail Out Here IF {No forecast data} ###
543 } elseif {$doing in {fc sk}} {
544 if {$doing eq "fc"} { set x "Forecast data currently unavailable."
545 } else { set x "Sky/Astro data currently unavailable." }
546 puthelp "PRIVMSG $ch :$clogo $x Please try again later."
547 return 0
548
549 } else { set put2 "Forecast data currently unavailable." }
550 }
551
552 # // Build current weather string.
553 if {$doing in {w wz wp}} { set x "$text and[color $temp_f $temp_c]"
554 if {$sayw(metric)==1} { append x " (${temp_f}F)"
555 } else { append x " (${temp_c}°)" }
556
557 ### !w Bails Out Here ###
558 if {$doing eq "w"} { set clogo "${logo}$where$endl ($lat, $lon):"
559 putserv "PRIVMSG $ch :$clogo $x" ; return 0
560 }
561
562 set puttx "${b}3Condiciones6:$b $x - "
563 append puttx "${b}3Sensacion Termica6:$b[color $feelslike_f $feelslike_c]"
564 if {$sayw(metric)==1} { append puttx " (${feelslike_f}F) - "
565 } else { append puttx " (${feelslike_c}°) - " }
566 append puttx "${b}3humedad6:$b ${humidity}% - ${b}3Viento6:$b "
567 if {$wind_mph < 1} { append puttx "Calm"
568 } else { append puttx "$wind_dir @ "
569 if {$sayw(metric)==1} { append puttx "${wind_kph}6km/h (${wind_mph}MPH)"
570 } else { append puttx "${wind_mph}MPH (${wind_kph}km/h)" }
571 }
572 append puttx " - ${b}3Presion6:$b "
573 if {$sayw(metric)==1} { append puttx "${pressure_mb}mb (${pressure_in}in)"
574 } else { append puttx "${pressure_in}in (${pressure_mb}mb)" }
575 if {$cloud < 5} { append puttx " - ${b}3Nubes6:$b No"
576 } else { append puttx " - ${b}Clouds:$b ${cloud}%" }
577 if {$precip_mm > 0.1} { append puttx " - ${b}3Precipitacion6:$b "
578 if {$precip_in >= 0.2} {
579 if {$sayw(metric)==1} { append puttx "${precip_mm}mm (${precip_in}in)"
580 } else { append puttx "${precip_in}in (${precip_mm}mm)" }
581 } else { append puttx "Rastro" }
582 }
583 if {[info exists fc1(sunrise)] && $fc1(date)==$udate} {
584 append puttx " - ${b}3Amanecer6:$b $fc1(sunrise)"
585 append puttx " - ${b}3Puesta de sol6:$b $fc1(sunset)"
586 }
587 append puttx " - ${b} 3 Actualizado6:$b $last_updated"
588
589 putserv "PRIVMSG $ch :$clogo $puttx"
590
591 ### !wz Bails Out Here ###
592 if {$doing eq "wz"} { return 0 }
593 ### !wp Bails Out Here IF {No forecast data} ###
594 if {$put2 ne ""} { putserv "PRIVMSG $ch :$put2" ; return 0 }
595 }
596
597 # // Build forecast or sky string.
598 set puttx ""
599 if {[array exists fc1]} { set fcnt 0 ; set doshort 0
600 set tmls "" ; set pcnt 0
601
602 if {$doing eq "wp"} { set puttx "${logo}Forecast:$endl"
603 } else { set puttx "$clogo" }
604 if {$doing eq "sk"} { set m1 [expr {$mx - 80}]
605 set m2 [expr {$m1 - 80}] ; set m3 [expr {$m2 - 80}]
606 }
607
608 foreach fc {fc1 fc2 fc3 fc4 fc5 fc6 fc7} { incr fcnt
609 if {![array exists $fc]} { break }
610
611 set date [set ${fc}(date)] ; set cond [set ${fc}(text)]
612
613 if {$doing eq "sk"} { set nxsky ""
614 if {!($fcnt==1 || ($fcnt==4 && $fcdays>4))} { append puttx " " }
615 append puttx " ${b}[getday $date]:$b"
616
617 foreach {x y} {sunrise sr sunset ss moonrise mr moonset ms} {
618 set z [set ${fc}($x)]
619 if {[string match {*? [AP]M} $z]} {
620 set z [string map {" " ""} [slower $z]]
621 }
622 set $y $z
623 }
624 append nxsky " Sunrise: $sr Sunset: $ss"
625
626 if {[string match {*[ap]m} $mr] && [string match {*[ap]m} $ms]} {
627 set rut [clock scan "$date $mr" -format {%Y-%m-%d %I:%M%p}]
628 set sut [clock scan "$date $ms" -format {%Y-%m-%d %I:%M%p}]
629 if {$rut<$sut} { append nxsky " Moonrise: $mr Moonset: $ms"
630 } else { append nxsky " Moonset: $ms Moonrise: $mr" }
631 } elseif {[slower $mr] eq "no moonrise"} {
632 append nxsky " Moonset: $ms (No Moonrise)"
633 } elseif {[slower $ms] eq "no moonset"} {
634 append nxsky " Moonrise: $mr (No Moonset)"
635 } else { append nxsky " Moonrise: $mr Moonset: $ms" }
636
637 if {$doshort==1} { append puttx "$nxsky"
638 } elseif {$fcdays==4} {
639 if {$fcnt==1 && [string length "$puttx $cond,$nxsky"]>$m3} {
640 append puttx "$nxsky" ; set doshort 1
641 } elseif {$fcnt==2 && [string length "$puttx $cond,$nxsky"]>$m2} {
642 append puttx "$nxsky" ; set doshort 1
643 } elseif {$fcnt==3 && [string length "$puttx $cond,$nxsky"]>$m1} {
644 append puttx "$nxsky" ; set doshort 1
645 } elseif {$fcnt==4 && [string length "$puttx $cond,$nxsky"]>$mx} {
646 append puttx "$nxsky"
647 } else { append puttx " $cond,$nxsky" }
648 } elseif {$fcnt>4 && $fcdays==7} {
649 if {$fcnt==5 && [string length "$puttx $cond,$nxsky"]>$m2} {
650 append puttx "$nxsky" ; set doshort 1
651 } elseif {$fcnt==6 && [string length "$puttx $cond,$nxsky"]>$m1} {
652 append puttx "$nxsky" ; set doshort 1
653 } elseif {$fcnt==7 && [string length "$puttx $cond,$nxsky"]>$mx} {
654 append puttx "$nxsky"
655 } else { append puttx " $cond,$nxsky" }
656 } else { append puttx " $cond,$nxsky" }
657
658 if {$fcnt==3 && $fcdays>4} { putserv "PRIVMSG $ch :$puttx"
659 set puttx "${logo}Extended Sky/Astro:$endl"
660 }
661
662 } else { set tmp ""
663 if {$fcnt==1} { lappend tmp " ${b}[getday $date]:$b"
664 } else { lappend tmp " ${b}[getday $date]:$b" }
665 lappend tmp " $cond,"
666 if {$sayw(metric)==1} {
667 set tm "High: [set ${fc}(maxtemp_c)]° ([set ${fc}(maxtemp_f)]F) "
668 append tm "Low: [set ${fc}(mintemp_c)]° ([set ${fc}(mintemp_f)]F)"
669 } else {
670 set tm "High: [set ${fc}(maxtemp_f)]F ([set ${fc}(maxtemp_c)]°) "
671 append tm "Low: [set ${fc}(mintemp_f)]F ([set ${fc}(mintemp_c)]°)"
672 }
673 lappend tmp " $tm"
674
675 if {$shortfc == 0} {
676 lappend tmp " humidity: [set ${fc}(avghumidity)]%"
677 if {[set ${fc}(totalprecip_in)] >= 0.2} { set tm "Precip: "
678 if {$sayw(metric)==1} { append tm "[set ${fc}(totalprecip_mm)]mm"
679 append tm " ([set ${fc}(totalprecip_in)]in)"
680 } else { append tm "[set ${fc}(totalprecip_in)]in"
681 append tm " ([set ${fc}(totalprecip_mm)]mm)"
682 }
683 lappend tmp " $tm" ; incr pcnt
684 } else { lappend tmp "" }
685 } else { lappend tmp "" "" }
686
687 lappend tmls $tmp
688 }
689 }
690
691 if {$doing eq "sk"} {
692 if {$puttx ne ""} { putserv "PRIVMSG $ch :$puttx" }
693 return 0
694 }
695#### Only wp & fc get past here ####
696
697 if {[llength $tmls]} {
698 if {$doing eq "fc"} {
699 if {[string match "* International Airport,*" $puttx]} {
700 set imap [list "International" "Intl"]
701 }
702 if {[string match "*, United States:*" $puttx]} {
703 set umap [list "United States" "USA"]
704 }
705 }
706 set on1 2
707 if {$doing eq "wp" || $shortfc == 1 || $fcdays <= 4} { set on1 1 }
708
709 foreach loop {1 2 3} { set pre $puttx ; set dun 0
710 if {$loop == 1} { set test $tmls
711 } elseif {$loop == 2} { set test [lrange $tmls 0 2]
712 } else { set test [lrange $tmls 3 end]
713 lset test {0 0} [string range [lindex $test 0 0] 1 end]
714 set pre "${logo}Extended Forecast:$endl"
715 }
716 set tmtxt [join [join $test] {}]
717 if {[set len [string length "$pre$tmtxt"]] <= ($mx +1)} {
718 putserv "PRIVMSG $ch :$pre$tmtxt"
719 if {$loop == 2} { continue } ; return 0
720 }
721
722 set over [expr {$len - ($mx +1)}]
723 if {$doing eq "fc" && $loop<3 && $over<=10} { set dun 1
724 if {[info exists imap] && $over<=9} {
725 set pre [string map $imap $pre]
726 } elseif {[info exists umap]} { set pre [string map $umap $pre]
727 } else { set dun 0 }
728 }
729 if {$dun==0 && $shortfc==0} {
730 if {$over<=[string length [lindex $test end 3]]} {
731 lset test {end 3} "" ; set dun 1
732 }
733 }
734 if {$dun==0 && $doing eq "fc" && $loop<3 && $over<=19} {
735 if {[info exists imap] && [info exists umap]} { set dun 1
736 set pre [string map [concat $imap $umap] $pre]
737 }
738 }
739 if {$dun==1} { putserv "PRIVMSG $ch :$pre[join [join $test] {}]"
740 if {$loop == 2} { continue } ; return 0
741 }
742 lset test {end 3} "" ; set tmtxt "$pre[join [join $test] {}]"
743 set test [lreverse $test] ; set tcnt 0 ; set li 2
744
745 while {[string length $tmtxt] > $mx} {
746 if {$tcnt == 0} { set tcnt 1
747 if {$shortfc==1} { set tcnt 5 ; set li 0 }
748 if {![info exists imap] || $loop == 3} { continue }
749 set pre [string map $imap $pre]
750 } elseif {$tcnt == 1} { lset test {1 3} "" ; set tcnt 2
751 } elseif {$tcnt == 2} {
752 if {[lindex $test 0 4] ne ""} { lset test {0 4} ""
753 } elseif {[lindex $test 1 4] ne ""} { lset test {1 4} ""
754 } else { set tcnt 3 ; continue }
755 } elseif {$tcnt == 3} { lset test $li 3 "" ; set tcnt 4
756 } elseif {$tcnt == 4} { set chg 0
757 if {[lindex $test $li 4] ne ""} { lset test $li 4 "" ; set chg 1 }
758 set tcnt 3 ; incr li
759 if {$li>=[llength $test]} { set tcnt 5 ; set li 0 }
760 if {$chg == 0} { continue }
761 } elseif {$tcnt == 5} { lset test $li 1 "" ; incr li
762 if {$li>=[llength $test]} { set dun 1 }
763 }
764 set tmtxt "$pre[join [join [lreverse $test]] {}]"
765 set over [expr {[string length $tmtxt] - $mx}]
766 if {$loop<3 && $over<=10 && $over>0 && [info exists umap]} {
767 set pre [string map $umap $pre] ; incr over -10
768 set tmtxt "$pre[join [join [lreverse $test]] {}]"
769 }
770 if {$over<=0} { putserv "PRIVMSG $ch :$tmtxt"
771 if {$loop == 2} { break } ; return 0
772 }
773 if {$loop==1 && $on1==2 && $tcnt==2} { break }
774 if {$dun==1} { break }
775 }
776 }
777 }
778 }
779} ;# End proc say_w #
780
781# // Get day of the week name (ex. Sunday |or| Tuesday)
782# // -from a date string: 2018-08-30
783# // -or date/time string: 2018-08-23 17:26
784proc getday {d} { set d [lindex [split $d] 0]
785 return [clock format [clock scan $d -format {%Y-%m-%d}] -format {%A}]
786}
787# // Get formatted date string (ex. 06 July 2018) from date or date/time
788proc getdate {d} { set d [lindex [split $d] 0]
789 return [clock format [clock scan $d -format {%Y-%m-%d}] -format {%d %B %Y}]
790}
791
792# // Primary Temperature Color Changing.
793# // You can change colors based on fahrenheit temperatures.
794# // IRC allows only 16 colors. See mIRC color chart.
795proc color {temp tempc} { variable sayw
796 set x "${temp}F"
797 if {$sayw(metric)==1} { set x "${tempc}°" }
798 if {$sayw(colortemp)==0} { return " $x" }
799 if {$temp < 20} { return "\00312 $x\003" }
800 if {$temp < 45} { return "\00311 $x\003" }
801 if {$temp < 70} { return "\00310 $x\003" }
802 if {$temp < 85} { return "\00307 $x\003" }
803 if {$temp < 100} { return "\00304 $x\003" }
804 return "\00304 $x\003"
805}
806
807# // Throttle Proc (slightly altered, super action missles) - Thanks to user & speechles
808# // See this post: http://forum.egghelp.org/viewtopic.php?t=9009&start=3
809proc throttle {id nk ch} { variable throttle ; variable sayw
810 set now [clock seconds]
811 if {[info exists throttle($id)] && [lindex $throttle($id) 0] > $now} {
812 lassign $throttle($id) ut cnt
813 if {$cnt == $sayw(throttle_max)} {
814 putserv "PRIVMSG $ch $nk 3~6$nk3~, 4flood detectado 3(3espera 6 [expr {$ut-$now}] 3segundos) para una nueva solicitud"
815 }
816 set throttle($id) [list $ut [incr cnt]]
817 if {$cnt > $sayw(throttle_max)} { set id 1 } { set id 0 }
818 } else {
819 set throttle($id) [list [expr {$now+$sayw(throttle_time)}] 1]
820 set id 0
821 }
822}
823# // sub - clean throttled users
824proc throttleclean {} { variable throttle
825 set now [clock seconds]
826 foreach {id time} [array get throttle] {
827 if {[lindex $time 0]<=$now} { unset throttle($id) }
828 }
829}
830
831# // save/clean wusers array
832proc savewusers {} { variable wusers ; variable sayw
833 if {![info exists wusers(updated)]} { return }
834 unset wusers(updated)
835 if {![array size wusers]} { file delete $sayw(usrfile) ; return }
836 set open [open $sayw(usrfile) w]
837 puts $open "array set wusers [list [array get wusers]]"
838 close $open
839}
840proc wusersclean {} { variable wusers
841 if {![array size wusers]} { return }
842 set old [expr {[unixtime] - (86400 * 45)}] ;# 45 days #
843 foreach {key val} [array get wusers] {
844 if {$key eq "updated"} { continue }
845 if {[lindex $val 0] <= $old} {
846 unset wusers($key) ; set wusers(updated) 1
847 }
848 }
849}
850
851proc bindtime {mn hr args} { variable nsc
852 if {$mn eq "02" && $hr in {00 12}} { ${nsc}::wusersclean }
853 ${nsc}::savewusers
854 if {[string match "*1" $mn]} { ${nsc}::throttleclean }
855}
856
857##################
858proc strim {str} {
859 return [regsub -all -- {\s{2,}} [string trim $str] { }]
860}
861proc sdigit {str} { return [string is digit -strict $str] }
862proc slower {str} { return [string tolower $str] }
863##################
864
865
866# // Script reset (unbind/rebind all triggers).
867proc w_reset {} { variable sayw ; variable nsc ; set dead "wunder"
868 foreach x {cmdchars cmds_w cmds_wz cmds_wp cmds_f cmds_fc cmds_sk cmds_ti chans} {
869 set sayw($x) [split [strim $sayw($x)]]
870 }
871 if {[lindex $sayw(chans) 0] eq "*"} { set sayw(chans) "*" }
872 foreach wproc [list "::${dead}::*" "${nsc}::say_w"] {
873 foreach wbind [binds $wproc] {
874 lassign $wbind t f n h p ; unbind $t $f $n $p
875 }
876 }
877 foreach char $sayw(cmdchars) {
878 bind pubm - "?%~\\${char}*" $wproc
879 }
880 bind time - * ${nsc}::bindtime
881 variable wusers
882 if {[file exists "scripts/${dead}weather.users"]} {
883 if {![file exists $sayw(usrfile)]} { set newufile 1
884 if {[array exists wusers]} { unset wusers }
885 file rename "scripts/${dead}weather.users" $sayw(usrfile)
886 }
887 }
888 if {![array exists wusers] || [info exists newufile]} {
889 array set wusers ""
890 if {[file exists $sayw(usrfile)]} { source $sayw(usrfile) }
891 }
892}
893w_reset
894
895putlog "6Sistema de clima 3Cargado correctamente"
896} ;## - End namespace eval - End namespace eval - ##
897
898package require http
899bind pub - ?wetter L:wetter
900proc L:wetter {nick host hand chan arg} {
901 set webstring "http://www.google.de/ig/api?weather=[lrange $arg 0 end]"
902 catch {exec wget -O scripts/wetter.data $webstring} err
903 set fp [open "scripts/wetter.data" r]; set wetterdata [read $fp]; close $fp
904 regexp {(?i)<city data=\"(.*?)\"/>} $wetterdata -> wetter(stadt)
905 regexp {(?i)<postal_code data=\"(.*?)\"/>} $wetterdata -> wetter(plz)
906 regexp {(?i)temp_c data=\"(.*?)\"/>} $wetterdata -> wetter(current_celsius)
907 regexp {(?i)humidity data=\"(.*?)\"/>} $wetterdata -> wetter(current_feuchtigkeit)
908 regexp {(?i)wind_condition data=\"(.*?)\"/>} $wetterdata -> wetter(current_wind)
909 regexp {(?i)condition data=\"(.*?)\"/>} $wetterdata -> wetter(current_weather)
910 if {$wetter(current_weather) == ""} { set wetter(current_weather) "Aktuelle Wetterlage unklar" }
911 putserv "privmsg $chan :Wetter für $wetter(stadt) \($wetter(plz)\) - Temp: $wetter(current_celsius) °C - $wetter(current_wind) - $wetter(current_feuchtigkeit) - $wetter(current_weather)"
912}