mirror of
https://github.com/RGBCube/nu_scripts
synced 2025-08-01 06:37:46 +00:00
refactor: ✨ (#418)
* refactor: ✨ move in one commit Eveything in modules should probably be changed to `exported` defs. The idea is to move everything first to keep proper history. * refactor: 📝 add modules readme (wip) * refactor: ✨ small move * refactor: 📝 changed nestring, updated modules readme * refactor: 📝 to document or not to document * fix: 🐛 themes replaced the template to use `main` and regenerated them from lemnos themes. * Revert "fix: 🐛 themes" This reverts commit 4918d3633c8d2d81950a0ed0cfd9eb84241bc886. * refactor: ✨ introduce sourced - Created a source `root` in which sourcable demos are stored. Some might get converted to modules later on. - Moved some files to bin too. * fix: 🐛 fehbg.nu * fix: 🐛 modules/after.nu * moved some other stuff around --------- Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
This commit is contained in:
parent
382696cd21
commit
c47ccd42b8
128 changed files with 185 additions and 12 deletions
5
modules/weather/README.md
Normal file
5
modules/weather/README.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Weather Scripts
|
||||
|
||||
### Definition
|
||||
|
||||
These scripts should be used to demonstrate how get your local weather and/or weather forecasts.
|
313
modules/weather/get-weather.nu
Normal file
313
modules/weather/get-weather.nu
Normal file
|
@ -0,0 +1,313 @@
|
|||
###################################################
|
||||
## Weather Script based on IP Address v1.0
|
||||
###################################################
|
||||
def locations [] {
|
||||
[
|
||||
[location city_column state_column country_column lat_column lon_column];
|
||||
["http://ip-api.com/json/" city region countryCode lat lon]
|
||||
["https://ipapi.co/json/" city region_code country_code latitude longitude]
|
||||
# ["https://freegeoip.app/json/" city region_code country_code latitude longitude] # doesn't appear to be free any longer
|
||||
["https://ipwhois.app/json/" city region country_code latitude longitude]
|
||||
]
|
||||
}
|
||||
|
||||
def get_my_location [index: int] {
|
||||
let loc_json = (http get (locations | select $index).0.location)
|
||||
let city_column = (locations | select $index).0.city_column
|
||||
let state_column = (locations | select $index).0.state_column
|
||||
let country_column = (locations | select $index).0.country_column
|
||||
let lat_column = (locations | select $index).0.lat_column
|
||||
let lon_column = (locations | select $index).0.lon_column
|
||||
|
||||
# echo $loc_json
|
||||
if ($city_column | str length) > 1 {
|
||||
if ($state_column | str length) > 1 {
|
||||
if ($country_column | str length) > 1 {
|
||||
let lookup_state = ($loc_json | get ($state_column))
|
||||
if ($lookup_state | str length) > 2 {
|
||||
let state = (state_abbrev_lookup $lookup_state)
|
||||
$"($loc_json | get ($city_column)),($state),($loc_json | get ($country_column))"
|
||||
} else {
|
||||
$"($loc_json | get ($city_column)),($loc_json | get ($state_column)),($loc_json | get ($country_column))"
|
||||
}
|
||||
} else {
|
||||
$"($loc_json | get ($city_column)),($loc_json | get ($state_column))"
|
||||
}
|
||||
} else {
|
||||
$"($loc_json | get ($city_column))"
|
||||
}
|
||||
} else {
|
||||
"No City Found"
|
||||
}
|
||||
}
|
||||
|
||||
def get_location_by_ip [locIdx: int, token: string] {
|
||||
let URL_QUERY_LOCATION = "https://api.openweathermap.org/geo/1.0/direct"
|
||||
let location = (get_my_location $locIdx)
|
||||
let url = $"($URL_QUERY_LOCATION)?q=($location)&limit=5&appid=($token)"
|
||||
http get $url
|
||||
}
|
||||
|
||||
def show-error [msg label err] {
|
||||
let span = (metadata $err).span;
|
||||
error make {msg: $msg, label: {text: $label, start: $span.start, end: $span.end } }
|
||||
}
|
||||
|
||||
def get_weather_by_ip [locIdx: int, units: string, token: string] {
|
||||
# units
|
||||
# f = imperial aka Fahrenheit
|
||||
# c = metric aka Celcius
|
||||
let URL_WEATHER = "https://api.openweathermap.org/data/2.5/weather"
|
||||
let URL_FORECAST = "http://api.openweathermap.org/data/2.5/forecast/daily"
|
||||
let coords = (get_location_by_ip $locIdx $token)
|
||||
if ($coords | length) > 1 {
|
||||
show-error "Error getting location" "There were more than one locations found" $coords
|
||||
}
|
||||
|
||||
if $units == "f" {
|
||||
let units = "imperial"
|
||||
let url = $"($URL_WEATHER)?lat=($coords.lat.0)&lon=($coords.lon.0)&units=($units)&appid=($token)"
|
||||
let url_forecast = $"($URL_FORECAST)?lat=($coords.lat.0)&lon=($coords.lon.0)&units=($units)&appid=($token)"
|
||||
let weather = (http get $url)
|
||||
let forecast_data = (http get $url_forecast)
|
||||
let forecast = ($forecast_data.list | each {|day|
|
||||
{
|
||||
id: ($day.weather.0.id)
|
||||
dt: ($day.dt | into string | into datetime -z local | date format '%a, %b %e') #'%Y-%m-%d')
|
||||
high: ($day.temp.max)
|
||||
low: ($day.temp.min)
|
||||
}
|
||||
})
|
||||
let day1 = $"($forecast | get 0.dt) (get_emoji_by_id ($forecast | get 0.id | into string)) high: ($forecast | get 0.high | into string -d 1) low: ($forecast | get 0.low | into string -d 1)"
|
||||
let day2 = $"($forecast | get 1.dt) (get_emoji_by_id ($forecast | get 1.id | into string)) high: ($forecast | get 1.high | into string -d 1) low: ($forecast | get 1.low | into string -d 1)"
|
||||
let day3 = $"($forecast | get 2.dt) (get_emoji_by_id ($forecast | get 2.id | into string)) high: ($forecast | get 2.high | into string -d 1) low: ($forecast | get 2.low | into string -d 1)"
|
||||
let day4 = $"($forecast | get 3.dt) (get_emoji_by_id ($forecast | get 3.id | into string)) high: ($forecast | get 3.high | into string -d 1) low: ($forecast | get 3.low | into string -d 1)"
|
||||
let day5 = $"($forecast | get 4.dt) (get_emoji_by_id ($forecast | get 4.id | into string)) high: ($forecast | get 4.high | into string -d 1) low: ($forecast | get 4.low | into string -d 1)"
|
||||
let day6 = $"($forecast | get 5.dt) (get_emoji_by_id ($forecast | get 5.id | into string)) high: ($forecast | get 5.high | into string -d 1) low: ($forecast | get 5.low | into string -d 1)"
|
||||
let day7 = $"($forecast | get 6.dt) (get_emoji_by_id ($forecast | get 6.id | into string)) high: ($forecast | get 6.high | into string -d 1) low: ($forecast | get 6.low | into string -d 1)"
|
||||
{
|
||||
'Weather Location': $"($weather.name), ($weather.sys.country)"
|
||||
Longitude: $weather.coord.lon
|
||||
Latitude: $weather.coord.lat
|
||||
Temperature: $"($weather.main.temp | into string -d 1) °F"
|
||||
'Feels Like': $"($weather.main.feels_like | into string -d 1) °F"
|
||||
Humidity: $weather.main.humidity
|
||||
Pressure: $weather.main.pressure
|
||||
Emoji: (get_icon_from_table $weather.weather.main.0)
|
||||
'Forecast Day 1': $day1
|
||||
'Forecast Day 2': $day2
|
||||
'Forecast Day 3': $day3
|
||||
'Forecast Day 4': $day4
|
||||
'Forecast Day 5': $day5
|
||||
'Forecast Day 6': $day6
|
||||
'Forecast Day 7': $day7
|
||||
}
|
||||
} else {
|
||||
let units = "metric"
|
||||
let url = $"($URL_WEATHER)?lat=($coords.lat.0)&lon=($coords.lon.0)&units=($units)&appid=($token)"
|
||||
let url_forecast = $"($URL_FORECAST)?lat=($coords.lat.0)&lon=($coords.lon.0)&units=($units)&appid=($token)"
|
||||
let weather = (http get $url)
|
||||
let forecast_data = (http get $url_forecast)
|
||||
let forecast = ($forecast_data.list | each {|day|
|
||||
{
|
||||
id: ($day.weather.0.id)
|
||||
dt: ($day.dt | into string | into datetime -z local | date format '%a, %b %e') #'%Y-%m-%d')
|
||||
high: ($day.temp.max)
|
||||
low: ($day.temp.min)
|
||||
}
|
||||
})
|
||||
let day1 = $"($forecast | get 0.dt) (get_emoji_by_id ($forecast | get 0.id | into string)) high: ($forecast | get 0.high | into string -d 1) low: ($forecast | get 0.low | into string -d 1)"
|
||||
let day2 = $"($forecast | get 1.dt) (get_emoji_by_id ($forecast | get 1.id | into string)) high: ($forecast | get 1.high | into string -d 1) low: ($forecast | get 1.low | into string -d 1)"
|
||||
let day3 = $"($forecast | get 2.dt) (get_emoji_by_id ($forecast | get 2.id | into string)) high: ($forecast | get 2.high | into string -d 1) low: ($forecast | get 2.low | into string -d 1)"
|
||||
let day4 = $"($forecast | get 3.dt) (get_emoji_by_id ($forecast | get 3.id | into string)) high: ($forecast | get 3.high | into string -d 1) low: ($forecast | get 3.low | into string -d 1)"
|
||||
let day5 = $"($forecast | get 4.dt) (get_emoji_by_id ($forecast | get 4.id | into string)) high: ($forecast | get 4.high | into string -d 1) low: ($forecast | get 4.low | into string -d 1)"
|
||||
let day6 = $"($forecast | get 5.dt) (get_emoji_by_id ($forecast | get 5.id | into string)) high: ($forecast | get 5.high | into string -d 1) low: ($forecast | get 5.low | into string -d 1)"
|
||||
let day7 = $"($forecast | get 6.dt) (get_emoji_by_id ($forecast | get 6.id | into string)) high: ($forecast | get 6.high | into string -d 1) low: ($forecast | get 6.low | into string -d 1)"
|
||||
{
|
||||
'Weather Location': $"($weather.name), ($weather.sys.country)"
|
||||
Longitude: $weather.coord.lon
|
||||
Latitude: $weather.coord.lat
|
||||
Temperature: $"($weather.main.temp | into string -d 1) °C"
|
||||
'Feels Like': $"($weather.main.feels_like | into string -d 1) °C"
|
||||
Humidity: $weather.main.humidity
|
||||
Pressure: $weather.main.pressure
|
||||
Emoji: (get_icon_from_table $weather.weather.main.0)
|
||||
'Forecast Day 1': $day1
|
||||
'Forecast Day 2': $day2
|
||||
'Forecast Day 3': $day3
|
||||
'Forecast Day 4': $day4
|
||||
'Forecast Day 5': $day5
|
||||
'Forecast Day 6': $day6
|
||||
'Forecast Day 7': $day7
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def weather_emoji_table [] {
|
||||
{
|
||||
Clear: (char sun)
|
||||
Clouds: (char clouds)
|
||||
Rain: (char rain)
|
||||
Fog: (char fog)
|
||||
Mist: (char mist)
|
||||
Haze: (char haze)
|
||||
Snow: (char snow)
|
||||
Thunderstorm: (char thunderstorm)
|
||||
}
|
||||
}
|
||||
|
||||
def get_icon_from_table [w] {
|
||||
weather_emoji_table | get $w
|
||||
}
|
||||
|
||||
# Get the local weather by ip address
|
||||
export def get_weather [
|
||||
--locIdx(-l): int # The location id 0-2
|
||||
--units(-u): string # The units "f" or "c"
|
||||
] {
|
||||
let token = "85a4e3c55b73909f42c6a23ec35b7147"
|
||||
|
||||
let is_loc_empty = ($locIdx == $nothing)
|
||||
let is_units_empty = ($units == $nothing)
|
||||
|
||||
let no_loc_no_unit = ($is_loc_empty == true and $is_units_empty == true)
|
||||
let no_loc_with_unit = ($is_loc_empty == true and $is_units_empty == false)
|
||||
let with_loc_no_unit = ($is_loc_empty == false and $is_units_empty == true)
|
||||
let with_loc_with_unit = ($is_loc_empty == false and $is_units_empty == false)
|
||||
|
||||
# This is a cautionary tale, the commented out code below is returning
|
||||
# and autoview is viewing the data, so no structured data is being returned.
|
||||
# The ramification to this is you can't do get_weather | select Temperature Emoji
|
||||
# like you should be able to. The following uncommented section below fixes it.
|
||||
|
||||
# Hopefully we'll be able to fix this somehow because it's easy to fall into
|
||||
# this hole without knowing.
|
||||
|
||||
# if $no_loc_no_unit {
|
||||
# echo "no_loc_no_unit"
|
||||
# (get_weather_by_ip 0 "f")
|
||||
# } { }
|
||||
|
||||
# if $no_loc_with_unit {
|
||||
# echo "no_loc_with_unit"
|
||||
# (get_weather_by_ip 0 $units)
|
||||
# } { }
|
||||
|
||||
# if $with_loc_no_unit {
|
||||
# echo "with_loc_no_unit"
|
||||
# (get_weather_by_ip $locIdx "f")
|
||||
# } { }
|
||||
|
||||
# if $with_loc_with_unit {
|
||||
# echo "with_loc_with_unit"
|
||||
# (get_weather_by_ip $locIdx $units)
|
||||
# } { }
|
||||
|
||||
if $no_loc_no_unit {
|
||||
(get_weather_by_ip 0 "f" $token)
|
||||
} else if $no_loc_with_unit {
|
||||
(get_weather_by_ip 0 $units $token)
|
||||
} else if $with_loc_no_unit {
|
||||
(get_weather_by_ip $locIdx "f" $token)
|
||||
} else if $with_loc_with_unit {
|
||||
(get_weather_by_ip $locIdx $units $token)
|
||||
}
|
||||
}
|
||||
|
||||
def state_abbrev_lookup [state_name: string] {
|
||||
# Weather Location 3 does not return state name abbreviations
|
||||
# so we have to convert a state full name to a state abbreviation
|
||||
let lookup_table = {
|
||||
Alabama: AL
|
||||
Alaska: AK
|
||||
Arizona: AZ
|
||||
Arkansas: AR
|
||||
California: CA
|
||||
Colorado: CO
|
||||
Connecticut: CT
|
||||
Delaware: DE
|
||||
Florida: FL
|
||||
Georgia: GA
|
||||
Hawaii: HI
|
||||
Idaho: ID
|
||||
Illinois: IL
|
||||
Indiana: IN
|
||||
Iowa: IA
|
||||
Kansas: KS
|
||||
Kentucky: KY
|
||||
Louisiana: LA
|
||||
Maine: ME
|
||||
Maryland: MD
|
||||
Massachusetts: MA
|
||||
Michigan: MI
|
||||
Minnesota: MN
|
||||
Mississippi: MS
|
||||
Missouri: MO
|
||||
Montana: MT
|
||||
Nebraska: NE
|
||||
Nevada: NV
|
||||
'New Hampshire': NH
|
||||
'New Jersey': NJ
|
||||
'New Mexico': NM
|
||||
'New York': NY
|
||||
'North Carolina': NC
|
||||
'North Dakota': ND
|
||||
Ohio: OH
|
||||
Oklahoma: OK
|
||||
Oregon: OR
|
||||
Pennsylvania: PA
|
||||
'Rhode Island': RI
|
||||
'South Carolina': SC
|
||||
'South Dakota': SD
|
||||
Tennessee: TN
|
||||
Texas: TX
|
||||
Utah: UT
|
||||
Vermont: VT
|
||||
Virginia: VA
|
||||
Washington: WA
|
||||
'West Virginia': WV
|
||||
Wisconsin: WI
|
||||
Wyoming: WY
|
||||
}
|
||||
|
||||
$lookup_table | get $state_name
|
||||
}
|
||||
|
||||
def get_emoji_by_id [id] {
|
||||
let emoji_dict = ({
|
||||
"200": "⚡", "201": "⚡", "202": "⚡", "210": "⚡", "211": "⚡", "212": "⚡", "221": "⚡", "230": "⚡",
|
||||
"231": "⚡", "232": "⚡",
|
||||
"300": "☔", "301": "☔", "302": "☔", "310": "☔", "311": "☔",
|
||||
"312": "☔", "313": "☔", "314": "☔", "321": "☔",
|
||||
"500": "☔", "501": "☔", "502": "☔", "503": "☔", "504": "☔",
|
||||
"511": "☔", "520": "☔", "521": "☔", "522": "☔", "531": "☔",
|
||||
"600": "❄️", "601": "❄️", "602": "❄️", "611": "❄️", "612": "❄️",
|
||||
"613": "❄️", "615": "❄️", "616": "❄️", "620": "❄️", "621": "❄️",
|
||||
"622": "❄️",
|
||||
"701": "🌫️", "711": "🌫️", "721": "🌫️", "731": "🌫️", "741": "🌫️", "751": "🌫️", "761": "🌫️", "762": "🌫️",
|
||||
"771": "🌫️",
|
||||
"781": "🌀",
|
||||
"800": "☀️",
|
||||
"801": "🌤️", "802": "🌤️", "803": "☁️", "804": "☁️",
|
||||
})
|
||||
|
||||
($emoji_dict | get $id)
|
||||
}
|
||||
|
||||
# To run this call
|
||||
# > get_weather
|
||||
# it will default to location 0 and Fahrenheit degrees
|
||||
# > get_weather -l 1
|
||||
# This changes to location 1. Locations are listed in the locations custom command above
|
||||
# > get_weather -l 2 -u c
|
||||
# This uses location 2 and Celcius degrees. f = Fahrenheit, c = Celcius
|
||||
|
||||
# Since I live in the USA I have not tested outside the country.
|
||||
# We'll take PRs for things that are broke or augmentations.
|
||||
|
||||
# HOW TO USE
|
||||
# put this in your config.nu file
|
||||
# use /path/to/get-weather.nu get_weather
|
||||
#
|
||||
# then from the nushell commmand prompt type
|
||||
# get_weather
|
368
modules/weather/nu.nu
Normal file
368
modules/weather/nu.nu
Normal file
|
@ -0,0 +1,368 @@
|
|||
def signatures [] {
|
||||
let sig = ([
|
||||
{ name: "nu-nu"
|
||||
usage: "signature test for nu-nu"
|
||||
extra_usage: ""
|
||||
required_positional: [
|
||||
{
|
||||
name: "a"
|
||||
desc: "required int value"
|
||||
shape: "Int"
|
||||
var_id: None
|
||||
},
|
||||
{
|
||||
name: "b"
|
||||
desc: "required string value"
|
||||
shape: "String"
|
||||
var_id: None
|
||||
}
|
||||
]
|
||||
optional_positional: [
|
||||
{
|
||||
name: "opt"
|
||||
desc: "optional number"
|
||||
shape: "Int"
|
||||
var_id: None
|
||||
}
|
||||
]
|
||||
rest_positional: {
|
||||
name: "rest"
|
||||
desc: "rest value string"
|
||||
shape: "String"
|
||||
var_id: None
|
||||
}
|
||||
named: [
|
||||
{
|
||||
long: "help"
|
||||
short: "h"
|
||||
arg: None
|
||||
required: false
|
||||
desc: "display this help message"
|
||||
var_id: None
|
||||
}
|
||||
{
|
||||
long: "flag"
|
||||
short: "f"
|
||||
arg: None
|
||||
required: false
|
||||
desc: "a flag for the signature"
|
||||
var_id: None
|
||||
}
|
||||
{
|
||||
long: "named"
|
||||
short: "n"
|
||||
arg: "String"
|
||||
required: false
|
||||
desc: "named string"
|
||||
var_id: None
|
||||
}
|
||||
]
|
||||
is_filter: false
|
||||
creates_scope: false
|
||||
category: "Experimental"
|
||||
}
|
||||
])
|
||||
|
||||
let jsonr = ($sig | to json)
|
||||
$jsonr
|
||||
}
|
||||
|
||||
def process_call [plugin_call] {
|
||||
let ret = ({
|
||||
Value: {
|
||||
List: {
|
||||
vals: [
|
||||
{
|
||||
Record: {
|
||||
cols: ["one", "two", "three"],
|
||||
vals: [
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: {start: 0, end: 1}
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: {start: 0, end: 1}
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: {start: 0, end: 1}
|
||||
}
|
||||
}
|
||||
],
|
||||
span: {start: 0, end: 1}
|
||||
}
|
||||
}
|
||||
{
|
||||
Record: {
|
||||
cols: ["one", "two", "three"],
|
||||
vals: [
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: {start: 0, end: 1}
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 1,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 2,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
],
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Record: {
|
||||
cols: ["one", "two", "three"],
|
||||
vals: [
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 2,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 4,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
],
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Record: {
|
||||
cols: ["one", "two", "three"],
|
||||
vals: [
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 3,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 6,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
],
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Record: {
|
||||
cols: ["one", "two", "three"],
|
||||
vals: [
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 4,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 8,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
],
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Record: {
|
||||
cols: ["one", "two", "three"],
|
||||
vals: [
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 5,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 10,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
],
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Record: {
|
||||
cols: ["one", "two", "three"],
|
||||
vals: [
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 6,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 12,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
],
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Record: {
|
||||
cols: ["one", "two", "three"],
|
||||
vals: [
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 7,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 14,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
],
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Record: {
|
||||
cols: ["one", "two", "three"],
|
||||
vals: [
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 8,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 16,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
],
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Record: {
|
||||
cols: ["one", "two", "three"],
|
||||
vals: [
|
||||
{
|
||||
Int: {
|
||||
val: 0,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 9,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
{
|
||||
Int: {
|
||||
val: 18,
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
],
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
],
|
||||
span: { start: 0, end: 1 }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let jsonr = ($ret | to json)
|
||||
$jsonr
|
||||
}
|
||||
|
||||
def plugin [input] {
|
||||
let plugin_call = $input
|
||||
if $plugin_call == "Signature" {
|
||||
signatures
|
||||
} else if "CallInfo" in $plugin_call {
|
||||
process_call $plugin_call
|
||||
} else {
|
||||
let error = ({
|
||||
Error: {
|
||||
label: "ERROR from plugin",
|
||||
msg: "error message pointing to call head span",
|
||||
span: {start: 0, end: 1},
|
||||
}
|
||||
})
|
||||
|
||||
let jsonr = ($error | to json)
|
||||
$jsonr
|
||||
}
|
||||
}
|
||||
|
||||
def main [] {
|
||||
let params = (each {|param| echo $param })
|
||||
plugin $params
|
||||
}
|
80
modules/weather/timed_weather_run.nu
Normal file
80
modules/weather/timed_weather_run.nu
Normal file
|
@ -0,0 +1,80 @@
|
|||
# This script will run a command, in this case get_weather, at a prescribed interval
|
||||
# This is meant to be run from your prompt so that it runs every time you cd or
|
||||
# run a command. Each time it will check if it's been longer than the interval and
|
||||
# if so, run the command, otherwise it uses the cached weather information.
|
||||
# I wrote this so I could have weather in my prompt but not pay the price of hitting
|
||||
# the web for every prompt. It will need to be tweaked to actually be used in a
|
||||
# prompt, but for now it just prints the weather in these 3 ways.
|
||||
# 1. if it's never been run, it runs the weather command and saves the json cache info
|
||||
# 2. if the interval has not expired yet, it prints the Cached information
|
||||
# 3. if the interval has expired, it runs the weather command again and caches the info
|
||||
|
||||
# this script is depenedent on get-weather
|
||||
source get-weather.nu
|
||||
|
||||
#command to run at interval
|
||||
def timed_weather_run [
|
||||
--command(-c): string # The command to run
|
||||
--interval(-i): duration # The interval duration
|
||||
] {
|
||||
|
||||
# get the type of system we're on
|
||||
let system_name = ((sys).host | get name)
|
||||
|
||||
if $system_name == "Windows" {
|
||||
# $"The system is Windows(char nl)"
|
||||
# generate temp file name
|
||||
let weather_runtime_file = (($env.TMP) | path join weather_runtime_file.json)
|
||||
# does the temp file already exist, meaning we've written it previously
|
||||
if ($weather_runtime_file | path exists) {
|
||||
# $"Weather path exists [($weather_runtime_file)](char nl)"
|
||||
# open the file and get the last weather data and run time out of it
|
||||
let last_runtime_data = (open $weather_runtime_file)
|
||||
# get the last runtime and add my timezone difference
|
||||
let last_runtime = ($last_runtime_data | get last_run_time | into datetime)
|
||||
if $last_runtime + $interval > (date now) {
|
||||
# $"interval not met. last_runtime: [($last_runtime)](char nl)"
|
||||
let temp = ($last_runtime_data.Temperature)
|
||||
let emoji = ($last_runtime_data.Emoji)
|
||||
{
|
||||
Temperature: ($temp)
|
||||
Source: "cache"
|
||||
Emoji: ($emoji)
|
||||
}
|
||||
} else {
|
||||
# save the run time and run the command
|
||||
# $"interval met, running command: [($command)](char nl)"
|
||||
|
||||
# it would be nice to run a dynamic command here but doesn't appear to be possible
|
||||
# let weather_table = (do { $command })
|
||||
let weather_table = (if $command == "get_weather" {(get_weather)})
|
||||
let temp = ($weather_table.Temperature)
|
||||
let emoji = ($weather_table.Emoji)
|
||||
{
|
||||
Temperature: ($temp)
|
||||
Source: "expired-cache"
|
||||
Emoji: ($emoji)
|
||||
}
|
||||
$weather_table | upsert last_run_time {(date now | date format '%Y-%m-%d %H:%M:%S %z')} | save $weather_runtime_file
|
||||
}
|
||||
} else {
|
||||
# $"Unable to find [($weather_runtime_file)], creating it(char nl)"
|
||||
let weather_table = (get_weather)
|
||||
let temp = ($weather_table.Temperature)
|
||||
let emoji = ($weather_table.Emoji)
|
||||
{
|
||||
Temperature: ($temp)
|
||||
Source: "initial"
|
||||
Emoji: ($emoji)
|
||||
}
|
||||
$weather_table | upsert last_run_time {(date now | date format '%Y-%m-%d %H:%M:%S %z')} | save $weather_runtime_file
|
||||
}
|
||||
} else {
|
||||
echo "Your command did not run because you are not on Windows..."
|
||||
# ToDo: refactor the info in the Windows section into another def. The only real difference
|
||||
# is where the temp file will be located. Mac & Linux probably should be in /tmp I guess.
|
||||
# everything else is linux or mac
|
||||
}
|
||||
}
|
||||
|
||||
timed_weather_run --command "get_weather" --interval 1min
|
44
modules/weather/timed_weather_run_env.nu
Normal file
44
modules/weather/timed_weather_run_env.nu
Normal file
|
@ -0,0 +1,44 @@
|
|||
# This script will run a command, in this case get_weather, at a prescribed interval
|
||||
# This is meant to be run from your prompt so that it runs every time you cd or
|
||||
# run a command. Each time it will check if it's been longer than the interval and
|
||||
# if so, run the command, otherwise it uses the cached weather information.
|
||||
# I wrote this so I could have weather in my prompt but not pay the price of hitting
|
||||
# the web for every prompt.
|
||||
|
||||
# this script is depenedent on get-weather
|
||||
use get-weather.nu get_weather
|
||||
|
||||
# Create a mutable weather table to hold the weather data
|
||||
let-env WEATHER = (get_weather | upsert last_run_time { (date now | date format '%Y-%m-%d %H:%M:%S %z')})
|
||||
|
||||
#command to run at interval
|
||||
def-env timed_weather_run [
|
||||
--interval(-i): duration # The interval duration
|
||||
] {
|
||||
|
||||
# get the last runtime and add my timezone difference
|
||||
let last_runtime = ($env.WEATHER | get last_run_time | into datetime)
|
||||
if $last_runtime + $interval > (date now) {
|
||||
# $"interval not met. last_runtime: [($last_runtime)](char nl)"
|
||||
let temp = ($env.WEATHER.Temperature)
|
||||
let emoji = ($env.WEATHER.Emoji)
|
||||
{
|
||||
Temperature: ($temp)
|
||||
Source: "cache"
|
||||
Emoji: ($emoji)
|
||||
}
|
||||
} else {
|
||||
# $"interval met, running command: [($command)](char nl)"
|
||||
|
||||
let-env WEATHER = (get_weather | upsert last_run_time { (date now | date format '%Y-%m-%d %H:%M:%S %z')})
|
||||
let temp = ($env.WEATHER.Temperature)
|
||||
let emoji = ($env.WEATHER.Emoji)
|
||||
{
|
||||
Temperature: ($temp)
|
||||
Source: "expired-cache"
|
||||
Emoji: ($emoji)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
timed_weather_run --interval 1min
|
192
modules/weather/weatherdark.nu
Normal file
192
modules/weather/weatherdark.nu
Normal file
|
@ -0,0 +1,192 @@
|
|||
# Weather Script based on IP Address
|
||||
# - Weather using dark weather api
|
||||
# - Air polution condition using airvisual api
|
||||
# - Street address using google maps api
|
||||
# - Version 2.0
|
||||
export def-env weatherds [] {
|
||||
get_weather (get_location 0)
|
||||
}
|
||||
|
||||
# location functions thanks to https://github.com/nushell/nu_scripts/tree/main/weather
|
||||
def locations [] {
|
||||
[
|
||||
[location city_column state_column country_column lat_column lon_column];
|
||||
["http://ip-api.com/json/" city region countryCode lat lon]
|
||||
["https://ipapi.co/json/" city region_code country_code latitude longitude]
|
||||
["https://freegeoip.app/json/" city region_code country_code latitude longitude]
|
||||
["https://ipwhois.app/json/" city region country_code latitude longitude]
|
||||
]
|
||||
}
|
||||
|
||||
def get_location [index: int] {
|
||||
let wifi = (iwgetid -r)
|
||||
let loc_json = (http get (locations | select $index).0.location)
|
||||
|
||||
# if ip address in your home isn't precise, you can force a location
|
||||
if $wifi =~ "my_wifi" { "your_lat,your_lon" } else { $"($loc_json.lat),($loc_json.lon)" }
|
||||
}
|
||||
|
||||
# dark sky
|
||||
def http get_api [loc] {
|
||||
let apiKey = "ds_api_key"
|
||||
let options = "?lang=en&units=si&exclude=minutely,hourly,flags"
|
||||
|
||||
let url = $"https://api.darksky.net/forecast/($apiKey)/($loc)($options)"
|
||||
|
||||
http get $url
|
||||
}
|
||||
|
||||
# street address
|
||||
def get_address [loc] {
|
||||
let mapsAPIkey = "maps_api_key"
|
||||
let url = $"https://maps.googleapis.com/maps/api/geocode/json?latlng=($loc)&sensor=true&key=($mapsAPIkey)"
|
||||
|
||||
(http get $url).results.0.formatted_address
|
||||
}
|
||||
|
||||
# wind description (adjust to your liking)
|
||||
def desc_wind [wind] {
|
||||
if $wind < 30 { "Normal" } else if $wind < 50 { "Moderate" } else if $wind < 60 { "Strong" } else { "Very Strong" }
|
||||
}
|
||||
|
||||
# uv description (standard)
|
||||
def uv_class [uvIndex] {
|
||||
if $uvIndex < 2.9 { "Low" } else if $uvIndex < 5.9 { "Moderate" } else if $uvIndex < 7.9 { "High" } else if $uvIndex < 10.9 { "Very High" } else { "Extreme" }
|
||||
}
|
||||
|
||||
# air pollution
|
||||
def get_airCond [loc] {
|
||||
let apiKey = "airvisual_api_key"
|
||||
let lat = (echo $loc | split row ",").0
|
||||
let lon = (echo $loc | split row ",").1
|
||||
let url = $"https://api.airvisual.com/v2/nearest_city?lat=($lat)&lon=($lon)&key=($apiKey)"
|
||||
let aqius = (http get $url).data.current.pollution.aqius
|
||||
|
||||
# clasification (standard)
|
||||
if $aqius < 51 { "Good" } else if $aqius < 101 { "Moderate" } else if $aqius < 151 { "Unhealthy for some" } else if $aqius < 201 { "Unhealthy" } else if $aqius < 301 { "Very unhealthy" } else { "Hazardous" }
|
||||
}
|
||||
|
||||
# parse all the information
|
||||
def get_weather [loc] {
|
||||
|
||||
let response = (http get_api $loc)
|
||||
let address = (get_address $loc)
|
||||
let air_cond = (get_airCond $loc)
|
||||
|
||||
## Current conditions
|
||||
let cond = $response.currently.summary
|
||||
let temp = $response.currently.temperature
|
||||
let wind = $response.currently.windSpeed * 3.6
|
||||
let humi = $response.currently.humidity * 100
|
||||
let uvIndex = $response.currently.uvIndex
|
||||
let suntimes = ($response.daily.data | select sunriseTime sunsetTime | select 0 | update cells {|f| $f | into string | into datetime -o -4 | into string})
|
||||
|
||||
let sunrise = ($suntimes | get sunriseTime | get 0 | split row ' ' | get 3)
|
||||
let sunset = ($suntimes | get sunsetTime | get 0 | split row ' ' | get 3)
|
||||
let vientos = (desc_wind $wind)
|
||||
let uvClass = (uv_class $uvIndex)
|
||||
|
||||
let Vientos = $"($vientos) \(($wind | into string -d 2) Km/h\)"
|
||||
let humedad = $"($humi)%"
|
||||
let temperature = $"($temp)°C"
|
||||
|
||||
let current = {
|
||||
"Condition": ($cond)
|
||||
Temperature: ($temperature)
|
||||
Humidity: ($humedad)
|
||||
Wind: ($Vientos)
|
||||
"UV Index": ($uvClass)
|
||||
"Air condition": ($air_cond)
|
||||
Sunrise: ($sunrise)
|
||||
Sunset: ($sunset)
|
||||
}
|
||||
|
||||
## Forecast
|
||||
let forecast = ($response.daily.data | select summary temperatureMin temperatureMax windSpeed humidity precipProbability precipIntensity uvIndex | update windSpeed {|f| $f.windSpeed * 3.6} | update precipIntensity {|f| $f.precipIntensity * 24} | update precipProbability {|f| $f.precipProbability * 100} | update humidity {|f| $f.humidity * 100} | update uvIndex {|f| uv_class $f.uvIndex} | update windSpeed {|f| $"(desc_wind $f.windSpeed) \(($f.windSpeed | into string -d 2)\)"} | rename Summary "T° min (°C)" "T° max (°C)" "Wind Speed (Km/h)" "Humidity (%)" "Precip. Prob. (%)" "Precip. Intensity (mm)")
|
||||
|
||||
## plots (require custom command gnu-plot)
|
||||
($forecast | select "Humidity (%)") | gnu-plot
|
||||
($forecast | select "Precip. Intensity (mm)") | gnu-plot
|
||||
($forecast | select "Precip. Prob. (%)") | gnu-plot
|
||||
($forecast | select "T° max (°C)") | gnu-plot
|
||||
($forecast | select "T° min (°C)") | gnu-plot
|
||||
|
||||
## forecast
|
||||
echo $"Forecast: ($response.daily.summary)"
|
||||
echo $forecast
|
||||
|
||||
## current
|
||||
echo $"Current conditions: ($address)"
|
||||
echo $current
|
||||
}
|
||||
|
||||
|
||||
# Get weather for right command prompt (set in config.nu)
|
||||
export def-env get_weather_by_interval [INTERVAL_WEATHER] {
|
||||
let weather_runtime_file = (($env.HOME) | path join .weather_runtime_file.json)
|
||||
|
||||
if ($weather_runtime_file | path exists) {
|
||||
let last_runtime_data = (open $weather_runtime_file)
|
||||
|
||||
let LAST_WEATHER_TIME = ($last_runtime_data | get last_weather_time)
|
||||
|
||||
if ($LAST_WEATHER_TIME | into datetime) + $INTERVAL_WEATHER < (date now) {
|
||||
let WEATHER = (get_weather_for_prompt (get_location 0))
|
||||
let NEW_WEATHER_TIME = (date now | date format '%Y-%m-%d %H:%M:%S %z')
|
||||
|
||||
$last_runtime_data | upsert weather $WEATHER | upsert last_weather_time $NEW_WEATHER_TIME | save $weather_runtime_file
|
||||
|
||||
$WEATHER
|
||||
} else {
|
||||
$last_runtime_data | get weather
|
||||
}
|
||||
} else {
|
||||
let WEATHER = (get_weather_for_prompt (get_location 0))
|
||||
let LAST_WEATHER_TIME = (date now | date format '%Y-%m-%d %H:%M:%S %z')
|
||||
|
||||
let WEATHER_DATA = {
|
||||
"weather": ($WEATHER)
|
||||
"last_weather_time": ($LAST_WEATHER_TIME)
|
||||
}
|
||||
|
||||
$WEATHER_DATA | save $weather_runtime_file
|
||||
$WEATHER
|
||||
}
|
||||
}
|
||||
|
||||
def get_weather_for_prompt [loc] {
|
||||
|
||||
let response = (http get_api $loc)
|
||||
|
||||
## current conditions
|
||||
let cond = $response.currently.summary
|
||||
let temp = $response.currently.temperature
|
||||
let temperature = $"($temp)°C"
|
||||
let icon = (get_weather_icon $response.currently.icon)
|
||||
|
||||
let current = {
|
||||
Condition: ($cond)
|
||||
Temperature: ($temperature)
|
||||
Icon: ($icon)
|
||||
}
|
||||
|
||||
echo $"($current.Icon) ($current.Temperature)"
|
||||
}
|
||||
|
||||
def get_weather_icon [icon: string] {
|
||||
switch $icon {
|
||||
"clear-day": {"☀️"},
|
||||
"clear-night": {"🌑"},
|
||||
"rain": {"🌧️"},
|
||||
"snow": {"❄️"},
|
||||
"sleet": {🌨️},
|
||||
"wind": {"🌬️"},
|
||||
"fog": {"🌫"},
|
||||
"cloudy": {"☁️"},
|
||||
"partly-cloudy-day": {"🌤️"},
|
||||
"partly-cloudy-night": {"🌑☁️"},
|
||||
"hail": {🌨},
|
||||
"thunderstorm": {"🌩️"},
|
||||
"tornado": {"🌪️"}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue