This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

CT-Weather

Support & discussion of released scripts, and announcements of new releases.
User avatar
SpiKe^^
Owner
Posts: 831
Joined: Fri May 12, 2006 10:20 pm
Location: Tennessee, USA
Contact:

Post by SpiKe^^ »

|| Temperature:: 293.9?C ||
That's odd, very hot there???
SpiKe^^

Get BogusTrivia 2.06.4.7 at www.mytclscripts.com
or visit the New Tcl Acrhive at www.tclarchive.org
.
User avatar
ComputerTech
Master
Posts: 400
Joined: Sat Feb 22, 2020 10:29 am
Contact:

Post by ComputerTech »

SpiKe^^ wrote:
|| Temperature:: 293.9?C ||
That's odd, very hot there???
lol, good job spotting that out Spike^^

The code seems back to front, i'll go fix this later. :roll:
ComputerTech
User avatar
ComputerTech
Master
Posts: 400
Joined: Sat Feb 22, 2020 10:29 am
Contact:

Post by ComputerTech »

Code: Select all

#################################
# CTweather
###
# Version: v0.0.3
# Author : ComputerTech
# GitHub : https://GitHub.com/computertech312
###
namespace eval CTweather {
	## Triggers.
	# Current weather.
	variable trig "!w"
	##

	## Flags.
	# n = Owner.
	# m = master
	# o = Op.
	# h = Halfop.
	# v = Voice.
	# f = Friend.
	# - = Nothing.
	variable flag "-|-"
	##

	## OpenWeatherMap API Key.
	variable api "8c2a600d5d63d7fb13432fd58dcc419b"

	## Metric type.
	# 0 = Metric
	# 1 = Imperial
	variable type "0"

	###

	package require json
	package require tls
	package require http

	bind PUB $flag $trig [namespace current]::current:weather

	proc current:weather {nick host hand chan text} {
		variable api ; variable type
		if {![llength [split $text]]} {
			putserv "privmsg $chan :Syntax: !w \[zip code | Location \]"
			return 0
		}
		switch -exact $type {
			"1" {variable tempy "C" ; variable windy "KPH" ; variable typex "metric"}
			"0" {variable tempy "F" ; variable windy "MPH" ; variable typex "imperial"}
		}
		variable url "https://nominatim.openstreetmap.org/search/"
		variable params [::http::formatQuery q $text format jsonv2 ]
		variable jsonx [getdata $url $params]
		variable name [dict get [lindex $jsonx 0] "display_name"]
		variable lati [dict get [lindex $jsonx 0] "lat"]
		variable long [dict get [lindex $jsonx 0]  "lon"]
		variable url "https://api.openweathermap.org/data/2.5/weather"
		variable params [::http::formatQuery lat $lati lon $long appid $api units $typex]
		variable jsonx [getdata $url $params]
		variable temp [dict get [dict get $jsonx "main"] "temp"]
		variable speed [dict get [dict get $jsonx "wind"] "speed"]
		variable degre [dict get [dict get $jsonx "wind"] "deg"]
		variable humid [dict get [dict get $jsonx "main"] "humidity"]
		variable cover [dict get [dict get $jsonx "clouds"] "all"]
		variable desc [dict get [lindex [dict get $jsonx weather] 0] "description"]
		putserv "PRIVMSG $chan :\[\00309Weather\003\] Location: $name || Longitutde: $long  || Latitude: $lati || Temperature:: ${temp}$tempy"
		putserv "PRIVMSG $chan :Humidity: ${humid}% Wind:: ${speed}$windy  Degree: $degre || Description:: $desc  || Clouds: ${cover}%"
	}

	proc getdata {url params} {
		::http::register https 443 [list ::tls::socket]
		::http::config -useragent "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0"
		putlog "$url?$params"
		variable data [http::data [http::geturl "$url?$params" -timeout 10000]]
		::http::cleanup $data
		variable jsonx [json::json2dict $data]
		return $jsonx
	}
}
Results:

Code: Select all

<ComputerTech> !w london uk
<CX> [Weather] Location: London, Greater London, England, United Kingdom || Longitutde: -0.1276474  || Latitude: 51.5073219 || Temperature:: 51.94F
<CX> Humidity: 93% Wind:: 3.44MPH  Degree: 110 || Description:: haze  || Clouds: 25%
ComputerTech
User avatar
SpiKe^^
Owner
Posts: 831
Joined: Fri May 12, 2006 10:20 pm
Location: Tennessee, USA
Contact:

Ver 0.0.3 (+variable-adjusted)

Post by SpiKe^^ »

Just a small code correction...

##################################
### +variable-adjusted Notes ###
# Corrected the usage of [variable] inside procs.
# Corrected the "Metric type" setting explanation.
##################################

Code: Select all

#################################
# CTweather
###
# Version: v0.0.3 (+variable-adjusted)
# Author : ComputerTech
# GitHub : https://GitHub.com/computertech312
###

##################################
###  +variable-adjusted Notes  ###
# Corrected the usage of [variable] inside procs.
# Corrected the "Metric type" setting explanation.
##################################

namespace eval CTweather {
	## Triggers.
	# Current weather.
	variable trig "!w"
	##

	## Flags.
	# n = Owner.
	# m = master
	# o = Op.
	# h = Halfop.
	# v = Voice.
	# f = Friend.
	# - = Nothing.
	variable flag "-|-"
	##

	## OpenWeatherMap API Key.
	variable api "8c2a600d5d63d7fb13432fd58dcc419b"

	## Metric type.
	# 0 = Imperial
	# 1 = Metric
	variable type "0"

	###

	package require json
	package require tls
	package require http

	bind PUB $flag $trig [namespace current]::current:weather

	proc current:weather {nick host hand chan text} {
		variable api ; variable type
		if {![llength [split $text]]} {
			putserv "privmsg $chan :Syntax: !w \[zip code | Location \]"
			return 0
		}
		switch -exact $type {
			"0" {set tempy "F" ; set windy "MPH" ; set typex "imperial"}
			"1" {set tempy "C" ; set windy "KPH" ; set typex "metric"}
		}

		set url "https://nominatim.openstreetmap.org/search/"
		set params [::http::formatQuery q $text format jsonv2 ]
		set jsonx [getdata $url $params]
		set name [dict get [lindex $jsonx 0] "display_name"]
		set lati [dict get [lindex $jsonx 0] "lat"]
		set long [dict get [lindex $jsonx 0]  "lon"]

		set url "https://api.openweathermap.org/data/2.5/weather"
		set params [::http::formatQuery lat $lati lon $long appid $api units $typex]
		set jsonx [getdata $url $params]
		set temp [dict get [dict get $jsonx "main"] "temp"]
		set speed [dict get [dict get $jsonx "wind"] "speed"]
		set degre [dict get [dict get $jsonx "wind"] "deg"]
		set humid [dict get [dict get $jsonx "main"] "humidity"]
		set cover [dict get [dict get $jsonx "clouds"] "all"]
		set desc [dict get [lindex [dict get $jsonx weather] 0] "description"]

		putserv "PRIVMSG $chan :\[\00309Weather\003\] Location: $name || Longitutde: $long  || Latitude: $lati || Temperature:: ${temp}$tempy"
		putserv "PRIVMSG $chan :Humidity: ${humid}% || Wind:: ${speed}$windy  Degree: $degre || Description:: $desc  || Clouds: ${cover}%"
	}

	proc getdata {url params} {
		::http::register https 443 [list ::tls::socket]
		::http::config -useragent "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0"

		putlog "$url?$params"

		set data [http::data [http::geturl "$url?$params" -timeout 10000]]
		::http::cleanup $data
		set jsonx [json::json2dict $data]
		return $jsonx
	}
}

Last edited by SpiKe^^ on Tue Jan 25, 2022 12:52 am, edited 1 time in total.
SpiKe^^

Get BogusTrivia 2.06.4.7 at www.mytclscripts.com
or visit the New Tcl Acrhive at www.tclarchive.org
.
User avatar
ComputerTech
Master
Posts: 400
Joined: Sat Feb 22, 2020 10:29 am
Contact:

Post by ComputerTech »

Cheers for the code fixes Spike^^ !! :D
ComputerTech
s
simo
Revered One
Posts: 1143
Joined: Sun Mar 22, 2015 2:41 pm

Post by simo »

i was wondering why UTF-8 isnt working for this tcl
for example :

(+Simo) : !w ryadh

(@Hawk) : [Weather] Location: الرياض, مديرية تريم, محافظة حضرموت, اليمن || Longitutde: 49.224962 || Latitude: 16.1146368 || Temperature:: 13.54C

(@Hawk) : Humidity: 44% Wind:: 1.26KPH Degree: 26 || Description:: clear sky || Clouds: 1%
UTF-8 works for me for other tcls like youtube so that cant be it
User avatar
ComputerTech
Master
Posts: 400
Joined: Sat Feb 22, 2020 10:29 am
Contact:

Post by ComputerTech »

I am currently working on version 0.0.4 of this script, which will boast a more streamlined codebase and improved functionality. Specifically, it will incorporate the following features:

- Location saving for enhanced convenience.
- Usage throttling to optimize performance and efficiency.
- Option for users to choose either Metric or Imperial units, according to their preferences.
- Forecast option for up to X number of days, to provide extended information.

I am open to additional feature requests, but for now, these are the key upgrades that I am focused on implementing. 8)
ComputerTech
w
willyw
Revered One
Posts: 1209
Joined: Thu Jan 15, 2009 12:55 am

Post by willyw »

ComputerTech wrote: ...
- Option for users to choose either Metric or Imperial units, according to their preferences.
...

I am open to additional feature requests, but for now, these are the key upgrades that I am focused on implementing. 8)

"either" Metric or Imperial...

How about a third option? Both. :)

Maybe so that the display is like: 77F (25C)

You would have to play with it, to see if it looks too cluttered. To see if you can get it so that it is ok to the eye.

You asked, and this came to mind. :) It's just a thought. No big deal.



p.s.
Another thought came to mind:
How about ALWAYS both, just the option is to pick which one comes first?
For a fun (and popular) Trivia game, visit us at: irc.librairc.net #science-fiction . Over 300K Q & A to play in BogusTrivia !
B
Bosco
Voice
Posts: 9
Joined: Mon Oct 31, 2022 10:57 pm

Post by Bosco »

Image

u mean like this ....
User avatar
FmX
Voice
Posts: 39
Joined: Wed Dec 06, 2006 12:42 pm

Post by FmX »

Hi. Script stop working.
Error i see is this:

Code: Select all

[23:09:53] <ATAS> [20:09:53] https://nominatim.openstreetmap.org/search/?q=%D1%81%D0%BE%D1%84%D0%B8%D1%8F%20&format=jsonv2
[23:09:53] <ATAS> [20:09:54] Tcl error [::CTweather::current:weather]: missing value to go with key
User avatar
CrazyCat
Revered One
Posts: 1384
Joined: Sun Jan 13, 2002 8:00 pm
Location: France
Contact:

Post by CrazyCat »

FmX wrote:Hi. Script stop working.
Error i see is this:

Code: Select all

[23:09:53] <ATAS> [20:09:53] https://nominatim.openstreetmap.org/search/?q=%D1%81%D0%BE%D1%84%D0%B8%D1%8F%20&format=jsonv2
[23:09:53] <ATAS> [20:09:54] Tcl error [::CTweather::current:weather]: missing value to go with key
Just try the url in a browser and you'll have a self-explanatory message:
File not found: API no longer accessible via this URL

Using the URL /search/ and /reverse/ (with slashes) is no longer supported. Please use URLs as given in the documentation.

Examples how to change the URL:

You use: https://nominatim.openstreetmap.org/search/?q=Berlin
Change to: https://nominatim.openstreetmap.org/search?q=Berlin

You use: https://nominatim.openstreetmap.org/sea ... xas/Huston
Change to: https://nominatim.openstreetmap.org/search?q=Huston, Texas, US

See github issue #3134 for more details.
User avatar
ComputerTech
Master
Posts: 400
Joined: Sat Feb 22, 2020 10:29 am
Contact:

Post by ComputerTech »

I'm working on a new updated/working version, will hopefully release today/tomorrow. 8)
ComputerTech
User avatar
FmX
Voice
Posts: 39
Joined: Wed Dec 06, 2006 12:42 pm

Post by FmX »

I thought the problem was in the script something. I waved / and went again. thanks
H
Henkie2
Voice
Posts: 35
Joined: Fri Sep 25, 2015 2:55 pm

Re:

Post by Henkie2 »

ComputerTech wrote: Tue Oct 03, 2023 9:23 am I'm working on a new updated/working version, will hopefully release today/tomorrow. 8)
Hi any news on updated version? Or how can i edit the correct lines? Thx
User avatar
ComputerTech
Master
Posts: 400
Joined: Sat Feb 22, 2020 10:29 am
Contact:

Re: CT-Weather

Post by ComputerTech »

Heya all, been a while. Here's v0.0.4 of CT-Weather.tcl. I haven't coded in Tcl in a while so if there's any bugs, that's my excuse. :lol:

Code: Select all

#################################
# CTweather
###
# Version: v0.0.4
# Author : ComputerTech
# GitHub : https://GitHub.com/computertech312
#
# DESCRIPTION:
#   Provides current weather and 4-day forecasts for any city, region, or US
#   zip code.  Users can register their location once so they never have to
#   type it again.  Registered locations are geocoded on save (Nominatim) and
#   stored as lat/lon so live !w/!f lookups skip the geocoding step entirely.
#
# REQUIREMENTS:
#   - Eggdrop 1.8+ with Tcl 8.5+
#   - Tcl TLS extension  (libtls / tcl-tls)  for HTTPS support
#   - Tcllib              (tcllib package)    for the json package
#
# SETUP:
#   1. Edit the "Configuration" section below:
#        weather_api_key   - Your Pirate Weather API key
#                            Get one free at: https://pirateweather.net
#        weather_data_file - Path (relative to eggdrop's working dir) where
#                            registered nick -> location data is persisted
#
#   2. Copy this file into your eggdrop scripts directory, e.g.:
#        cp ct-weather.tcl /path/to/eggdrop/scripts/
#
#   3. Add the following line to your eggdrop config (eggdrop.conf):
#        source scripts/ct-weather.tcl
#
#   4. Rehash or restart your bot:
#        .rehash
#
# COMMANDS (all triggered with ! prefix in any public channel):
#
#   !w [location]
#       Show current weather for <location> (city name or US zip code).
#       If no location is given, uses your registered location.
#       Example:  !w New York
#                 !w 90210
#                 !w                (uses registered location)
#
#   !f [location]
#       Show a 4-day forecast for <location>.
#       Falls back to registered location if none is provided.
#       Example:  !f London, UK
#
#   !register_location <location>
#       Geocode <location> and save it as your default.  The resolved name
#       and coordinates are confirmed back to you in chat.
#       Example:  !register_location Austin, TX
#
#   !change_location <location>
#       Update your registered location.  You must already have one saved.
#       Example:  !change_location 10001
#
#   !unregister_location
#       Remove your registered location.
#
#   !change_trigger <w|f> <newtrigger>
#       (Bot owners only) Change the trigger for !w or !f at runtime.
#       Changes take effect immediately without a rehash.
#       Example:  !change_trigger w !weather
#                 !change_trigger f !forecast
#
# DATA FILE FORMAT (ct-weather.dat):
#   One Tcl list per line:  nick lat lon {Display Name}
#   Example:
#     colby 30.2672 -97.7431 {Austin, United States}
#
# NOTES:
#   - Temperature is always shown as C and F, e.g. 19.8°C (67.7°F).
#   - Temperature is IRC-colour coded: blue (<10C), yellow (<20C),
#     orange (<30C), red (30C+).
#   - Geocoding uses the free Nominatim API (openstreetmap.org).
#     Please respect their usage policy (max 1 req/sec, valid User-Agent).
#
# CONFIGURATION VARIABLES:
#   weather_api_key   - Pirate Weather API key
#   weather_data_file - Path to nick->location storage file
#   weather_flag      - Eggdrop flag required to use commands
#                       "-|-" = everyone  |  "o|o" = ops only  etc.
#
###############################################################################

namespace eval CTweather {

    ## Triggers
    variable trig_w "!w"
    variable trig_f "!f"

    # --- Configuration ---
    variable weather_api_key   "YOUR-API-KEY-HERE"
    variable weather_data_file "scripts/ct-weather.dat"
    # Eggdrop channel flag required to use bot commands ("-|-" = everyone)
    variable weather_flag      "-|-"

    # In-memory nick -> location storage
    variable weather_locations
    array set weather_locations {}

    package require http
    package require tls
    package require json

    # Register HTTPS handler (catch guards against double-registration on rehash)
    catch {::tls::init -ssl2 0 -ssl3 0 -tls1 0 -tls1.2 1}
    catch {http::register https 443 [list ::tls::socket]}

    # --- Binds ---
    bind pub $weather_flag !register_location   [namespace current]::pub:weather_register
    bind pub $weather_flag !change_location     [namespace current]::pub:weather_change
    bind pub $weather_flag !unregister_location [namespace current]::pub:weather_unregister
    bind pub $weather_flag $trig_w              [namespace current]::pub:weather_current
    bind pub $weather_flag $trig_f              [namespace current]::pub:weather_forecast
    # !change_trigger is open to all so the proc can give a proper error to non-owners
    bind pub -|- !change_trigger                [namespace current]::pub:weather_change_trigger

    # --- File I/O ---

    proc weather_load {} {
        variable weather_locations
        variable weather_data_file
        catch {
            set fp [open $weather_data_file r]
            while {[gets $fp line] >= 0} {
                # Each line is a Tcl list: nick lat lon display_name
                if {[llength $line] == 4} {
                    set nick [lindex $line 0]
                    set weather_locations($nick) [lrange $line 1 3]
                }
            }
            close $fp
        }
    }

    proc weather_save {} {
        variable weather_locations
        variable weather_data_file
        if {[catch {
            set fp [open $weather_data_file w]
            foreach nick [array names weather_locations] {
                lassign $weather_locations($nick) lat lon name
                puts $fp [list $nick $lat $lon $name]
            }
            close $fp
        } err]} {
            putlog "ct-weather.tcl: Failed to save locations: $err"
        }
    }

    # --- Helpers ---

    proc weather_sanitize {text} {
        regsub -all {[^\x20-\x7E]} $text {} text
        regsub -all {\s+} [string trim $text] { } text
        return $text
    }

    proc weather_geocode {query} {
        if {[regexp {^\d{5}$} $query]} {
            set query "${query}, US"
        }
        set url "https://nominatim.openstreetmap.org/search?[http::formatQuery q $query format json limit 1 addressdetails 1]"
        set tok ""
        if {[catch {
            set tok [http::geturl $url \
                -headers {User-Agent Eggdrop-PirateWeatherBot/1.0} \
                -timeout 10000]
            set body [http::data $tok]
            http::cleanup $tok
            set tok ""
        } err]} {
            if {$tok ne ""} { catch {http::cleanup $tok} }
            putlog "ct-weather geocode HTTP error: $err"
            return {}
        }
        if {[catch {set results [json::json2dict $body]} err]} {
            putlog "ct-weather geocode JSON error: $err"
            return {}
        }
        if {![llength $results]} { return {} }
        set r [lindex $results 0]
        set lat  [dict get $r lat]
        set lon  [dict get $r lon]
        set full [dict get $r display_name]
        set parts [split $full ","]
        if {[llength $parts] > 2} {
            set name "[string trim [lindex $parts 0]], [string trim [lindex $parts end]]"
        } else {
            set name $full
        }
        return [list $lat $lon $name]
    }

    proc weather_fetch {url} {
        set tok ""
        if {[catch {
            set tok [http::geturl $url -timeout 10000]
            set body [http::data $tok]
            http::cleanup $tok
            set tok ""
        } err]} {
            if {$tok ne ""} { catch {http::cleanup $tok} }
            error "HTTP error: $err"
        }
        if {[catch {set data [json::json2dict $body]} err]} {
            error "JSON parse error: $err"
        }
        return $data
    }

    proc weather_color_temp {temp_c} {
        set temp_f [expr {$temp_c * 9.0 / 5.0 + 32.0}]
        if     {$temp_c < 10} { set col 12
        } elseif {$temp_c < 20} { set col 08
        } elseif {$temp_c < 30} { set col 07
        } else                  { set col 04 }
        return "\003${col}[format %.1f $temp_c]\u00b0C ([format %.1f $temp_f]\u00b0F)\003"
    }

    proc weather_wind_dir {deg} {
        if {$deg eq {} || $deg eq "null"} { return "?" }
        set dirs {N NE E SE S SW W NW}
        return [lindex $dirs [expr {round($deg / 45.0) % 8}]]
    }

    proc weather_get {d key {default {}}} {
        if {[dict exists $d $key]} { return [dict get $d $key] }
        return $default
    }

    # --- Commands ---

    proc pub:weather_register {nick uhost hand chan text} {
        variable weather_locations
        set query [weather_sanitize $text]
        if {$query eq {}} {
            puthelp "PRIVMSG $chan :Usage: !register_location <location or zip>"
            return
        }
        set geo [weather_geocode $query]
        if {![llength $geo]} {
            puthelp "PRIVMSG $chan :Could not find location for: $query"
            return
        }
        lassign $geo lat lon name
        set weather_locations($nick) [list $lat $lon $name]
        weather_save
        puthelp "PRIVMSG $chan :Location for $nick registered as: $name ($lat, $lon)"
    }

    proc pub:weather_change {nick uhost hand chan text} {
        variable weather_locations
        if {![info exists weather_locations($nick)]} {
            puthelp "PRIVMSG $chan :You do not have a registered location. Use !register_location <location> to register one."
            return
        }
        set query [weather_sanitize $text]
        if {$query eq {}} {
            puthelp "PRIVMSG $chan :Usage: !change_location <new location or zip>"
            return
        }
        set geo [weather_geocode $query]
        if {![llength $geo]} {
            puthelp "PRIVMSG $chan :Could not find location for: $query"
            return
        }
        lassign $geo lat lon name
        set weather_locations($nick) [list $lat $lon $name]
        weather_save
        puthelp "PRIVMSG $chan :Your location has been updated to: $name ($lat, $lon)"
    }

    proc pub:weather_unregister {nick uhost hand chan text} {
        variable weather_locations
        if {[info exists weather_locations($nick)]} {
            unset weather_locations($nick)
            weather_save
            puthelp "PRIVMSG $chan :Your registered location has been removed."
        } else {
            puthelp "PRIVMSG $chan :You do not have a registered location."
        }
    }

    proc pub:weather_current {nick uhost hand chan text} {
        variable weather_locations
        variable weather_api_key
        set query [weather_sanitize $text]
        if {$query eq {}} {
            if {[info exists weather_locations($nick)]} {
                lassign $weather_locations($nick) lat lon name
            } else {
                puthelp "PRIVMSG $chan :Usage: !w <location or zip> or register your location with !register_location <location>"
                return
            }
        } else {
            set geo [weather_geocode $query]
            if {![llength $geo]} {
                puthelp "PRIVMSG $chan :Could not find coordinates for: $query"
                return
            }
            lassign $geo lat lon name
        }
        set url "https://api.pirateweather.net/forecast/${weather_api_key}/${lat},${lon}?units=si&exclude=minutely,hourly,alerts"
        if {[catch {set data [weather_fetch $url]} err]} {
            puthelp "PRIVMSG $chan :Error retrieving weather data: $err"
            return
        }
        if {![dict exists $data currently]} {
            puthelp "PRIVMSG $chan :Error from Pirate Weather: [weather_get $data message Unknown]"
            return
        }
        set c [dict get $data currently]
        set conditions [weather_get $c summary "N/A"]
        set temp_c     [expr {double([weather_get $c temperature 0])}]
        set pressure   [weather_get $c pressure 0]
        set humidity   [expr {int([weather_get $c humidity 0] * 100)}]
        set clouds     [expr {int([weather_get $c cloudCover 0] * 100)}]
        set wind_ms    [expr {double([weather_get $c windSpeed 0])}]
        set wind_deg   [weather_get $c windBearing {}]
        set rain       [weather_get $c precipIntensity 0]
        set wind_kmh   [expr {$wind_ms * 3.6}]
        set wind_mph   [expr {$wind_ms * 2.23694}]
        set wind_str   "[format %.1f $wind_kmh] km/h / [format %.1f $wind_mph] mph"
        puthelp "PRIVMSG $chan :\002Location:\002 $name | \002Conditions:\002 $conditions | \002Temperature:\002 [weather_color_temp $temp_c] | \002Pressure:\002 $pressure hPa | \002Humidity:\002 ${humidity}% | \002Precip:\002 $rain mm/h | \002Wind:\002 $wind_str from [weather_wind_dir $wind_deg] | \002Cloud cover:\002 ${clouds}%"
    }

    proc pub:weather_forecast {nick uhost hand chan text} {
        variable weather_locations
        variable weather_api_key
        set query [weather_sanitize $text]
        if {$query eq {}} {
            if {[info exists weather_locations($nick)]} {
                lassign $weather_locations($nick) lat lon name
            } else {
                puthelp "PRIVMSG $chan :Usage: !f <location or zip> or register your location with !register_location <location>"
                return
            }
        } else {
            set geo [weather_geocode $query]
            if {![llength $geo]} {
                puthelp "PRIVMSG $chan :Could not find coordinates for: $query"
                return
            }
            lassign $geo lat lon name
        }
        set url "https://api.pirateweather.net/forecast/${weather_api_key}/${lat},${lon}?units=si&exclude=currently,minutely,hourly,alerts"
        if {[catch {set data [weather_fetch $url]} err]} {
            puthelp "PRIVMSG $chan :Error retrieving forecast data: $err"
            return
        }
        if {![dict exists $data daily] || ![dict exists [dict get $data daily] data]} {
            puthelp "PRIVMSG $chan :Error from Pirate Weather: [weather_get $data message Unknown]"
            return
        }
        set days [lrange [dict get [dict get $data daily] data] 0 3]
        set parts {}
        foreach day $days {
            set weekday   [clock format [dict get $day time] -format "%A"]
            set condition [string trimright [weather_get $day summary "N/A"] "."]
            set max_t     [expr {double([weather_get $day temperatureHigh 0])}]
            set min_t     [expr {double([weather_get $day temperatureLow  0])}]
            lappend parts "$weekday $condition [weather_color_temp $max_t] [weather_color_temp $min_t]"
        }
        puthelp "PRIVMSG $chan :\002Location:\002 $name :: [join $parts { :: }]"
    }

    proc pub:weather_change_trigger {nick uhost hand chan text} {
        variable trig_w
        variable trig_f
        variable weather_flag
        # Only bot owners (flag n) may use this command
        if {![matchattr $hand n]} {
            puthelp "PRIVMSG $chan :Sorry $nick, only bot owners can change triggers."
            return
        }
        set args [split [weather_sanitize $text]]
        if {[llength $args] != 2} {
            puthelp "PRIVMSG $chan :Usage: !change_trigger <w|f> <newtrigger>  (e.g. !change_trigger w !weather)"
            return
        }
        set which [string tolower [lindex $args 0]]
        set new   [lindex $args 1]
        # Trigger must start with ! and contain only safe characters
        if {![regexp {^![A-Za-z0-9_-]+$} $new]} {
            puthelp "PRIVMSG $chan :Invalid trigger. Must start with ! and contain only letters, numbers, _ or -."
            return
        }
        switch -- $which {
            w {
                if {$new eq $trig_w} {
                    puthelp "PRIVMSG $chan :Weather trigger is already set to: $trig_w"
                    return
                }
                bind pub $weather_flag $new ::CTweather::pub:weather_current
                unbind pub $weather_flag $trig_w ::CTweather::pub:weather_current
                set trig_w $new
                puthelp "PRIVMSG $chan :Weather trigger changed to: $new"
            }
            f {
                if {$new eq $trig_f} {
                    puthelp "PRIVMSG $chan :Forecast trigger is already set to: $trig_f"
                    return
                }
                bind pub $weather_flag $new ::CTweather::pub:weather_forecast
                unbind pub $weather_flag $trig_f ::CTweather::pub:weather_forecast
                set trig_f $new
                puthelp "PRIVMSG $chan :Forecast trigger changed to: $new"
            }
            default {
                puthelp "PRIVMSG $chan :Unknown trigger type '$which'. Use w (weather) or f (forecast)."
            }
        }
    }

    # --- Init ---
    weather_load
    putlog "ct-weather.tcl loaded."
}
ComputerTech
Post Reply