From f0cb75f40f3898140180fbeaeca3ee28e4ee07a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Jaenisch?= Date: Tue, 25 Jun 2024 08:24:07 +0200 Subject: [PATCH] refactor: extract WeatherAPI widget into its own MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was done to allow for choice. In the first step I copied over the existing code into a new folder and accompanied it with icons and locales. There is no indicator of night in the JSON responses, which made me delete the respective icons. I copied and updated the README to fit the current implementation. I will need to add screenshots before I can ask for another round of review. Signed-off-by: André Jaenisch --- weather-api-widget/README.md | 110 +++++ .../icons/VitalyGorbachev/broken-clouds.svg | 1 + .../icons/VitalyGorbachev/clear-sky.svg | 1 + .../icons/VitalyGorbachev/few-clouds.svg | 1 + .../icons/VitalyGorbachev/mist.svg | 1 + .../icons/VitalyGorbachev/rain.svg | 1 + .../VitalyGorbachev/scattered-clouds.svg | 1 + .../icons/VitalyGorbachev/shower-rain.svg | 1 + .../icons/VitalyGorbachev/snow.svg | 1 + .../icons/VitalyGorbachev/thunderstorm.svg | 1 + .../broken-clouds.png | Bin 0 -> 1600 bytes .../weather-underground-icons/clear-sky.png | Bin 0 -> 1029 bytes .../weather-underground-icons/few-clouds.png | Bin 0 -> 1634 bytes .../icons/weather-underground-icons/mist.png | Bin 0 -> 1042 bytes .../icons/weather-underground-icons/rain.png | Bin 0 -> 1728 bytes .../scattered-clouds.png | Bin 0 -> 1044 bytes .../weather-underground-icons/shower-rain.png | Bin 0 -> 1728 bytes .../icons/weather-underground-icons/snow.png | Bin 0 -> 1191 bytes .../thunderstorm.png | Bin 0 -> 2052 bytes weather-api-widget/locale/de.lua | 13 + weather-api-widget/locale/en.lua | 14 + weather-api-widget/locale/fr.lua | 14 + weather-api-widget/locale/pt.lua | 14 + weather-api-widget/weather.lua | 380 ++++++++++++++++++ 24 files changed, 554 insertions(+) create mode 100644 weather-api-widget/README.md create mode 100644 weather-api-widget/icons/VitalyGorbachev/broken-clouds.svg create mode 100644 weather-api-widget/icons/VitalyGorbachev/clear-sky.svg create mode 100644 weather-api-widget/icons/VitalyGorbachev/few-clouds.svg create mode 100644 weather-api-widget/icons/VitalyGorbachev/mist.svg create mode 100644 weather-api-widget/icons/VitalyGorbachev/rain.svg create mode 100644 weather-api-widget/icons/VitalyGorbachev/scattered-clouds.svg create mode 100644 weather-api-widget/icons/VitalyGorbachev/shower-rain.svg create mode 100644 weather-api-widget/icons/VitalyGorbachev/snow.svg create mode 100644 weather-api-widget/icons/VitalyGorbachev/thunderstorm.svg create mode 100755 weather-api-widget/icons/weather-underground-icons/broken-clouds.png create mode 100755 weather-api-widget/icons/weather-underground-icons/clear-sky.png create mode 100755 weather-api-widget/icons/weather-underground-icons/few-clouds.png create mode 100755 weather-api-widget/icons/weather-underground-icons/mist.png create mode 100755 weather-api-widget/icons/weather-underground-icons/rain.png create mode 100755 weather-api-widget/icons/weather-underground-icons/scattered-clouds.png create mode 100755 weather-api-widget/icons/weather-underground-icons/shower-rain.png create mode 100755 weather-api-widget/icons/weather-underground-icons/snow.png create mode 100755 weather-api-widget/icons/weather-underground-icons/thunderstorm.png create mode 100644 weather-api-widget/locale/de.lua create mode 100644 weather-api-widget/locale/en.lua create mode 100644 weather-api-widget/locale/fr.lua create mode 100644 weather-api-widget/locale/pt.lua create mode 100644 weather-api-widget/weather.lua diff --git a/weather-api-widget/README.md b/weather-api-widget/README.md new file mode 100644 index 0000000..bb26f77 --- /dev/null +++ b/weather-api-widget/README.md @@ -0,0 +1,110 @@ +# WeatherAPI widget + +The widget consists of one section: +- current weather, including humidity, wind speed, UV index + +## Customization + +It is possible to customize widget by providing a table with all or some of the +following config parameters: + +| Name | Default | Description | +|---|---|---| +| coordinates | Required | Table with two elements: latitude and longitude, e.g. `{46.204400, 6.143200}` | +| api_key | Required | [Follow the documentation](https://www.weatherapi.com/docs/) | +| font_name | `beautiful.font:gsub("%s%d+$", "")` | **Name** of the font to use e.g. 'Play' | +| units | `metric` | `metric` for celsius, `imperial` for fahrenheit | +| icon_pack_name | `weather-underground-icons` | Name of the icon pack, could be `weather-underground-icon` or `VitalyGorbachev` or create your own, more details below | +| icons_extension | `.png` | File extension of icons in the pack | +| timeout | 120 | How often in seconds the widget refreshes | + +### Icons: + +The widget comes with two predefined icon packs: + + - [weather-underground-icons](https://github.com/manifestinteractive/weather-underground-icons) + - [VitalyGorbachev](https://www.flaticon.com/authors/vitaly-gorbachev) + +To add your custom icons, create a folder with the pack name under `/icons` and +use the folder name in widget's config. There should be 18 icons, preferably +128x128 minimum. Icons should also respect the naming convention, please check +widget's source. + +### Examples: + +#### Custom font, icons + +```lua +weather_api_widget({ + api_key='', + coordinates = {45.5017, -73.5673}, + units = 'imperial', + font_name = 'Carter One', + icons = 'VitalyGorbachev', + icons_extension = '.svg', +}), +``` + +#### Only current weather + +```lua +weather_api_widget({ + api_key='', + coordinates = {45.5017, -73.5673}, +}), +``` + +## Installation + +1. Download json parser for lua from + [github.com/rxi/json.lua](https://github.com/rxi/json.lua) and place it + under **~/.config/awesome/** + (don't forget to star a repo ): + + ```bash + wget -P ~/.config/awesome/ https://raw.githubusercontent.com/rxi/json.lua/master/json.lua + ``` + +1. Clone this repo under **~/.config/awesome/**: + + ```bash + git clone https://github.com/streetturtle/awesome-wm-widgets.git ~/.config/awesome/ + ``` + +1. [Get Weather API key](https://www.weatherapi.com/docs/). + +1. Require weather widget at the beginning of **rc.lua**: + + ```lua + local weather_api_widget = require("awesome-wm-widgets.weather-api-widget.weather") + ``` + +1. Add widget to the tasklist: + + ```lua + s.mytasklist, -- Middle widget + { -- Right widgets + layout = wibox.layout.fixed.horizontal, + ... + --default + weather_api_widget({ + api_key='', + coordinates = {45.5017, -73.5673}, + }), + , + --customized + weather_api_widget({ + api_key='', + coordinates = {45.5017, -73.5673}, + units = 'imperial', + font_name = 'Carter One', + icons = 'VitalyGorbachev', + icons_extension = '.svg', + }), + ... + ``` + +## How it works + +The widget calls the API repeatedly in the specified intervals. The JSON +response is parsed and interpreted to build the popup. diff --git a/weather-api-widget/icons/VitalyGorbachev/broken-clouds.svg b/weather-api-widget/icons/VitalyGorbachev/broken-clouds.svg new file mode 100644 index 0000000..d42ea59 --- /dev/null +++ b/weather-api-widget/icons/VitalyGorbachev/broken-clouds.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/weather-api-widget/icons/VitalyGorbachev/clear-sky.svg b/weather-api-widget/icons/VitalyGorbachev/clear-sky.svg new file mode 100644 index 0000000..dc82163 --- /dev/null +++ b/weather-api-widget/icons/VitalyGorbachev/clear-sky.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/weather-api-widget/icons/VitalyGorbachev/few-clouds.svg b/weather-api-widget/icons/VitalyGorbachev/few-clouds.svg new file mode 100644 index 0000000..d42ea59 --- /dev/null +++ b/weather-api-widget/icons/VitalyGorbachev/few-clouds.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/weather-api-widget/icons/VitalyGorbachev/mist.svg b/weather-api-widget/icons/VitalyGorbachev/mist.svg new file mode 100644 index 0000000..770f8d7 --- /dev/null +++ b/weather-api-widget/icons/VitalyGorbachev/mist.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/weather-api-widget/icons/VitalyGorbachev/rain.svg b/weather-api-widget/icons/VitalyGorbachev/rain.svg new file mode 100644 index 0000000..11ecf00 --- /dev/null +++ b/weather-api-widget/icons/VitalyGorbachev/rain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/weather-api-widget/icons/VitalyGorbachev/scattered-clouds.svg b/weather-api-widget/icons/VitalyGorbachev/scattered-clouds.svg new file mode 100644 index 0000000..d42ea59 --- /dev/null +++ b/weather-api-widget/icons/VitalyGorbachev/scattered-clouds.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/weather-api-widget/icons/VitalyGorbachev/shower-rain.svg b/weather-api-widget/icons/VitalyGorbachev/shower-rain.svg new file mode 100644 index 0000000..4d1897c --- /dev/null +++ b/weather-api-widget/icons/VitalyGorbachev/shower-rain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/weather-api-widget/icons/VitalyGorbachev/snow.svg b/weather-api-widget/icons/VitalyGorbachev/snow.svg new file mode 100644 index 0000000..e2ea140 --- /dev/null +++ b/weather-api-widget/icons/VitalyGorbachev/snow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/weather-api-widget/icons/VitalyGorbachev/thunderstorm.svg b/weather-api-widget/icons/VitalyGorbachev/thunderstorm.svg new file mode 100644 index 0000000..44a733c --- /dev/null +++ b/weather-api-widget/icons/VitalyGorbachev/thunderstorm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/weather-api-widget/icons/weather-underground-icons/broken-clouds.png b/weather-api-widget/icons/weather-underground-icons/broken-clouds.png new file mode 100755 index 0000000000000000000000000000000000000000..5967d929720110d12e96ae2117b913876bd9f837 GIT binary patch literal 1600 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD~={fl)ueC&U%V{f_~@Eti3a!5Kg< zg#B%~G!h%63?hQ59$5sg3uXvJqs-qo7l9(k2w4}Dy-Wh40LVqw4&lP3Ad1mQsQP8n z5M|$%Nx@Bkiokq|tPw5+V@Sd5l45vcqX7)Eq>>=NV1|c$w--N~J2m+CsjbVaf-TH- z1z116yq)1-Y$W>S!~LB*RyWq?$NM^1b2I(@_4VA5{d+d_wYQ||sLQ;4^YreCy;Y?p zd9jhM8p`sLS5_~Y*;SDk>8m7v=Jdh!>t;l`&YuuyeQt93Dh39YI8PVHkcwMxu4m^9 zIf}47FrN~2^wK0=SJ&JPtlZPOU7w061xTB=L@)6D6OjM;)BpPB-8>r(oKsVKqjT}i z=gP^S-}#)IDapdr=%66*!(MjFhTzOiJ+iAVnH+i-lA)DU-j|V;n4Z!g@-Ir@K|KG2 zl}U$ZESr>Mb@y=fc9r&s@IW?=32zP*^UgZALCyVg`I^(0OE}L@>|(i_^w}eHeqlx4 z6ORQU4}5s;SqG>ET;JcYMAcF1os!h++ngIp%vUZsF3jw01>`8Gp04!z*es=Db<4@Q zX`9ac2dg~9r_K6P-`mF~9Km+Sq^XA?-bB+hcx6~~kmSG4)2}4YJh@aE<@LdP;xxmY z+$gpW?(JfSD{WJG_APKNjhJ-dj2zqcSEoJM>=vx#U(RyU;>+#@C%;Zja@cKmvLm~= zY(ebB($)1pjC((=dpj+1jqlonJLiA6ccpZBayP@4%o~&LmCS0$Zcu7a$>pqAU&OZc z%OjfwYkB3rdVEXh61BMAK3_^jdxl}poRbafdG5A5zIb`I@`u)+hicMIUY=%+YR4Z6 zC*J0l*Iv$$eL?w`Q%+T7uj&33`HXg)Th;rt1xtQx(!cZOs^Z?x3zJ&dt|uK`Jo&Ql zRVAL~x8z*fzrAz&h5vYb`_P? zy?Co6b**IM-hjP&-1~$tWv{Rix%B($r^2|fjlJjBe>-yKxW*#3Z6dH*tQc00{HcDm?xU)5Ab(=3zf_yw|LXZu{vDfD*Ryr*)16jyg-gzUUvvM;lNOS( zyI%`zKCWT1Jy65+$wh4!ABMFL65W<^F0`KPP$V1trFELkt6%Dl(oU-PS--^p6)Vs` z%M|@->#A^$a0QcPivPNqw%&Rqc=M>~yekTy&rEh>y!oc`QtfT0XXe69T`>y^mZGCaw7h?P;(aL6b!A$CV4!or zXP(3j3yOLRa{SKC4PMZFVb1mkvrdUE{JJ8>GVYN}MTnkEx_oL&`Ri{f)v~&!E!P)a zD%ySM*blb6vqwuZ$`ow0&U*;Hw##bFPhgvosn#T?@a{)u9o!@%Nb3Acbc;` zm$W?yvyoD`+g>ZrUC$)?y{({aLskgiJK0EH$IumPjQ0o^H#E$;^6i}Y@^2zPep;UU zW%?+&O<<9zaMQ~d6;g-KuRlA>O=k{2f48{P;ztc(-UjoyoFoE6*}f{xGGr~@*nHyg t97U6;39GN2{$iNra^h*x&KSM3@ji?j_A{Ech5*Yo22WQ%mvv4FO#s%IT-5*o literal 0 HcmV?d00001 diff --git a/weather-api-widget/icons/weather-underground-icons/clear-sky.png b/weather-api-widget/icons/weather-underground-icons/clear-sky.png new file mode 100755 index 0000000000000000000000000000000000000000..acf8e5cd108a3d4beecfbd8415111d6594d77753 GIT binary patch literal 1029 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H3?#oinD`S&O%Cu0aRt)fmdgw()cGpW4CpL_ zk|4iehQe}*byK3X9`E>Y|4?_3i_rJiUUo(*vpTYqEp(?(Xse44=V1AJ^XkQ8E1FL) zmgD_5_aD$}Odma6978H@y}kLmXqABo>jPDdd#_@zRIM+M-un9Q{C86xC{}PWYFYZE zfBO6S%1j-nO*a`O+7iL&<8R&^k<9DLx*{)5=o^c)&lBx(_UBwVlR>S4^FuVVkA0cF zrptDz(>$g2Ri&xsnyWv*dH^c+AH9 zT+`{-!5@~hY}Pdi{r{?T`*Gp9$ET}8+TZsE`dQzZy7kMc&tBFu9!aSF;g>zO+rhr_ zd-gRSpI;fl&*E)gd^@$fNL(?$+LcN6^Zh%=&Yoeks=f5Rk;C!t)fX-cdp&%)j58i< z9B0q^VzPj@)$+`|iEQik{}0~6q<ls<=ESb^IbP&Us9LeXl83B6mxVj)1ir%v^U*&Bl+x<8HZ<7 z(b74RW)5t=b{U-kFPU^wP16)U=T<&!*4$??GrfU7DsuI@5|=gx(Vc8oJSp!(+_G0c z`F*2>e`VgPle--@=&pVeZC!E8Y=`v8(g(6uUoPn^&Dv1-S@m?yDfTwLwN@vQ#Rd0g6;?&R2st|UZo-n# z56$0Mi_E#|XJx$q*}JCRSax=z-+A31)e-3t^}H`vBwB|l&-y(x)c)G6t86)o|2==_`1+JJ({Il?F3;SmGUN0|ZqEyUFMjVY=km45U%2Z(d(kSNgy*6O zlK*20LODO!Sl88D*zC3?JC6VO#fA6XOul*^+`22^hwJ?Jz6`<#SUhT~qvynZxV1u| m&w^X*N0I^>B88+Fp%PgQ*g_Bi5kzLd*>LqBbs&|}5C)hHbqPcSs1kzE6u`Nd zTHsR18X-196eEixYln*;(z$*R7)CtJGo}Ttjtt()ngl4lM18*^e9~ z*gmj7nx7_W7$%~9aMhLO2MaqcG;`cKJnzV5J&`wZr`~=3Yk#QkA$b~!He1%J&S^^mW* zYAYNg`^B&P@oGy>;kn_vA$b1&HS4l}T2xQ_`gUbNgNgLVMPld5-t0NB?j%dl-0;5# z)n5b&=WUnHl6!b-Ub_8q=Q$?Ylf(aAZjHXT^Mc4O=l)B&F;T%$u`)7u)DzyY>wRQ$ zi+gy+>~RiXD05NLArISH57BD{&Uydd?7#BB<#a;7sbpmXch3)xuXkh3U!1O+pQxOC z>-s~^O%LOFl!?kaeW!IeM{1kseD%Za%!`W#5 zC-+~44_7bUcks##EB$jRb!Ts7&Q0*VE8r&ObLixSJ%@F#rav&uWD@rGx#j%fEYpg# z6?Iuok0oQ;C!2p}2<0j^_0c}a;Kp`^CI6OA%9aC8)&lV>X38g=TJ5pf+T)q5*^&(o zYgSI175Rd>{`SWI*S0ho@IAQScd_hk%&`cC4HGygXDts-cU`Sywd!2F#ah0(hi(OZ zsQmvvA;!jabH=&dlMO$7p8x+yzFzrx+j4ou2KTFPdtW54=L_L1)UseGFMcNUtG0qw zu>H;1qth?&{+n5@74IPXo^9Vl1FxqM1^17{IPQ)+DI}X3xJpcS^pln%qC7-uYb1!tjoo-VHCGPG`Q$zocXH<=(R2hQW$?9j4+B ze+qr+NHgY4pQD?ac`&nCTSwV4;@4TV`PZ5Y^IT@@teMGsBJ_CEx9CklQ*GvL%=B0{ zV|(K-7TH}-LYuCe8hRRR-)Fw`bNqx5h4nW7+}0V{a~VFL9$^`t+10UG_W8USN4`D! zz;ONg_w@W)txq#gZR+2C_hQ0+uiM49K9pBw|)J)^ru)I(GFa?>Op`-~GE0>KSj z|0Zm7;=LT)QFY1nPNPzDOzq7VVj-1%iHp*1l`U4&4Vm5gh}&>)(!H3cVd6@anJ*G1 ztx@@6AaXxGHr?g-?mWlE9v$B%Z&(mn9(8(&{}G8^jy@3h7hlhCy7J5EtL{E(zygoK M)78&qol`;+0CaY1iU0rr literal 0 HcmV?d00001 diff --git a/weather-api-widget/icons/weather-underground-icons/mist.png b/weather-api-widget/icons/weather-underground-icons/mist.png new file mode 100755 index 0000000000000000000000000000000000000000..102142a239ae2ff93f0b63119eb555e3e3370082 GIT binary patch literal 1042 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 b{PB#puke(aTQKzi^E-p5tDnm{r-UW|;ps;f literal 0 HcmV?d00001 diff --git a/weather-api-widget/icons/weather-underground-icons/thunderstorm.png b/weather-api-widget/icons/weather-underground-icons/thunderstorm.png new file mode 100755 index 0000000000000000000000000000000000000000..210210435319ffe8cbb502195662b7b152d47839 GIT binary patch literal 2052 zcmbtVc{H1O8%<&2T2l>eDVhkAu~Zb%P6kbvL93x=LTjrema&s)QQKEa zGNq{27)5QdHP))NifYNUOjU`sTJz4Ab8?*i`~A*&?|Yx;-rs$mbKXDR1Q%z#9CR-f z1Omy~|6uD1ylMYFQeprKUNbjAAaIR~le-;IF0XIz?Ch*@v;YJSDz;Nd{!jcS2PlOd z;UJMJ>VGp1uTXH6m9PVFfQUE{BAl|$ zfeVv`l5j(jO>{*#R9K3lgakk#0X!lb(Aiyza)ikM0){?lQ9AJD(x|S^ZXk%W?Vt52 z7JJ=xLJ^q5_cNDCx;;g6zClqJQt*XAZ(j*a&9wzt;(!On=gd5z+K;rv-A+vBDN z2Aa_Am6`E6RhEul93B zeoxOlvgxxi_wmR2l|Hi1zo#R;{DLL%)Z7WRDVxUy{m+S)C-s)<8fzRPDqKJRb_N~Q zj;NCLZXZW>Cg>|YCFJR*#Fq<>4<^CjnZsWqTuTC_nRV+)i>5Nup>%@0V&SPUwd+f+ zI(P-`$2fvI*7=@y3)IUbnR)01GulLbl4LSHUz{(`@z;FY{yv@?|1>042j29RXG)@{ z{`77l#iUD4FWi(U$&nqh$tFVa1A=CZd5ps#Gd5EhZ}^2vWGz>g!{cd$MBf0bgT*LI z=T8EOq1*3Exmo5c<8lggAIfMj=#Mnt#k2W(&8)DUl+Sl`S?Mp>5BJz5sg4v@*w1{w zaCu%mX#bU?sH?b6Wy)_BWgoGQKk2lEtK9R7Znbu&qI&LRdn&sykC}|-yKTtB@YVYk zj4?WNLyE+^agR!R5167q;O6#$v54G9RN-*!oQzg51ck7zY9b$<%{vkqKG3QkC7G^v zkK2a1%?_MoO^I2}M=nNVpei#) zy59cyqxaTUUiV9TTaK4Gov~qq&ll_jAtAMR-Fa#??xR(z5|iX7zM#sA=edqmjZ8!p zsVLL!X5>k_i4oYqnBg??#W%)7_*-wP=W?Wms5Pk??h%`Zd$Su8FuBM%_{e{_GfQw? zS=5lCpFh!zo`#zsY{ENK#CdF0l^e&Xm{zUW?cx`Hn^ECwBQI)+zaGZe?7Ga+UxKnVVa45KoC6o14rk^ebOx4h`Ivib zSZbiRB`mfIkv_1+^+CSDn0nj0!IJx90mER57bDrGyS!)*Lq4fm<10ixIpl4y>QeLH zA;DdKkN`g|X!yZVaq3m*BZ^?Xav}KFG+u-F1FgI+dUN8k{HB;Ii@0FpF2iM$>7f)-qjUEjH&Ap$biY51 z-65F-qu&x7qIq}YwYC~PjaYOF)|$~0HCHEwX6F7W6KSA&>AxpE`TbwY$desYe^GrW zPp*4oa(vgCUyXlPOR{(qTyP^ypYaPEcIk?P=ivmyXVN3#?v72b1@}meG9%`tvrov# z(}!~RtQK&&Z=We)UBJ@yfv;rZDB)sx*B4pE@=l>Gk0^Mhp$A{^k`)hB@(|~i2MY%H zvX%`0UTIe;_C!cE*AA-|I@N{5Xx9ENiI(CUSv@Uj$a>1ZZn!zqetNHl#Q0ru?Jef9?1qE^;|aT}3&xpMx#j8AIVg^*J;JRZClhCZ8Blq1Tp2fNVL~H!E9NW*)2Z zyeLjcl&qmAXR$zjNHQs;qo)}Rtvm1J5$OuCwi{M)Z>XX|XW}&{9a9GNfb1hPEt|77J84i$8r_IU&tT*okX_bTRxZ4+Pz9O8 l&g!=cC;<{?z&X= 0 and uvi < 3 then color = '#a3be8c' + elseif uvi >= 3 and uvi < 6 then color = '#ebcb8b' + elseif uvi >= 6 and uvi < 8 then color = '#d08770' + elseif uvi >= 8 and uvi < 11 then color = '#bf616a' + elseif uvi >= 11 then color = '#b48ead' + end + + return '' .. uvi .. '' +end + +local function worker(user_args) + + local args = user_args or {} + + --- Validate required parameters + if args.coordinates == nil or args.api_key == nil then + show_warning(LCLE.parameter_warning .. + (args.coordinates == nil and 'coordinates' or '') .. + (args.api_key == nil and ', api_key ' or '')) + return + end + + local coordinates = args.coordinates + local api_key = args.api_key + local font_name = args.font_name or beautiful.font:gsub("%s%d+$", "") + local units = args.units or 'metric' + local both_units_widget = args.both_units_widget or false + local icon_pack_name = args.icons or 'weather-underground-icons' + local icons_extension = args.icons_extension or '.png' + local timeout = args.timeout or 120 + + local ICONS_DIR = WIDGET_DIR .. '/icons/' .. icon_pack_name .. '/' + local weather_api = + ('https://api.weatherapi.com/v1/current.json' .. + '?q=' .. coordinates[1] .. ',' .. coordinates[2] .. '&key=' .. api_key .. + '&units=' .. units .. '&lang=' .. LANG) + + weather_widget = wibox.widget { + { + { + { + { + id = 'icon', + resize = true, + widget = wibox.widget.imagebox + }, + valign = 'center', + widget = wibox.container.place, + }, + { + id = 'txt', + widget = wibox.widget.textbox + }, + layout = wibox.layout.fixed.horizontal, + }, + left = 4, + right = 4, + layout = wibox.container.margin + }, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, 4) + end, + widget = wibox.container.background, + set_image = function(self, path) + self:get_children_by_id('icon')[1].image = path + end, + set_text = function(self, text) + self:get_children_by_id('txt')[1].text = text + end, + is_ok = function(self, is_ok) + if is_ok then + self:get_children_by_id('icon')[1]:set_opacity(1) + self:get_children_by_id('icon')[1]:emit_signal('widget:redraw_needed') + else + self:get_children_by_id('icon')[1]:set_opacity(0.2) + self:get_children_by_id('icon')[1]:emit_signal('widget:redraw_needed') + end + end + } + + local current_weather_widget = wibox.widget { + { + { + { + id = 'icon', + resize = true, + forced_width = 128, + forced_height = 128, + widget = wibox.widget.imagebox + }, + align = 'center', + widget = wibox.container.place + }, + { + id = 'description', + font = font_name .. ' 10', + align = 'center', + widget = wibox.widget.textbox + }, + forced_width = 128, + layout = wibox.layout.align.vertical + }, + { + { + { + id = 'temp', + font = font_name .. ' 36', + widget = wibox.widget.textbox + }, + { + id = 'feels_like_temp', + align = 'center', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }, + layout = wibox.layout.fixed.vertical + }, + { + { + id = 'wind', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }, + { + id = 'humidity', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }, + { + id = 'uv', + font = font_name .. ' 9', + widget = wibox.widget.textbox + }, + expand = 'inside', + layout = wibox.layout.align.vertical + }, + spacing = 16, + forced_width = 150, + layout = wibox.layout.fixed.vertical + }, + forced_width = 300, + layout = wibox.layout.flex.horizontal, + update = function(self, weather) + self:get_children_by_id('icon')[1]:set_image( + ICONS_DIR .. icon_map[weather.condition.code] .. icons_extension) + self:get_children_by_id('temp')[1]:set_text(gen_temperature_str(weather.temp_c, '%.0f', false, units)) + self:get_children_by_id('feels_like_temp')[1]:set_text( + LCLE.feels_like .. gen_temperature_str(weather.feelslike_c, '%.0f', false, units)) + self:get_children_by_id('description')[1]:set_text(weather.condition.text) + self:get_children_by_id('wind')[1]:set_markup( + LCLE.wind .. '' .. weather.wind_kph .. 'km/h (' .. weather.wind_dir .. ')') + self:get_children_by_id('humidity')[1]:set_markup(LCLE.humidity .. '' .. weather.humidity .. '%') + self:get_children_by_id('uv')[1]:set_markup(LCLE.uv .. uvi_index_color(weather.uv)) + end + } + + local function update_widget(widget, stdout, stderr) + if stderr ~= '' then + if not warning_shown then + if (stderr ~= 'curl: (52) Empty reply from server' + and stderr ~= 'curl: (28) Failed to connect to api.weatherapi.com port 443: Connection timed out' + and stderr:find('^curl: %(18%) transfer closed with %d+ bytes remaining to read$') ~= nil + ) then + show_warning(stderr) + end + warning_shown = true + widget:is_ok(false) + tooltip:add_to_object(widget) + + widget:connect_signal('mouse::enter', function() tooltip.text = stderr end) + end + return + end + + if string.match(stdout, '<') ~= nil then + if not warning_shown then + warning_shown = true + widget:is_ok(false) + tooltip:add_to_object(widget) + + widget:connect_signal('mouse::enter', function() tooltip.text = stdout end) + end + return + end + + warning_shown = false + tooltip:remove_from_object(widget) + widget:is_ok(true) + + local result = json.decode(stdout) + widget:set_image(ICONS_DIR .. icon_map[result.current.condition.code] .. icons_extension) + -- TODO: if units isn't "metric", read temp_f instead + widget:set_text(gen_temperature_str(result.current.temp_c, '%.0f', both_units_widget, units)) + + current_weather_widget:update(result.current) + + local final_widget = { + current_weather_widget, + spacing = 16, + layout = wibox.layout.fixed.vertical + } + + weather_popup:setup({ + { + final_widget, + margins = 10, + widget = wibox.container.margin + }, + bg = beautiful.bg_normal, + widget = wibox.container.background + }) + end + + weather_widget:buttons(gears.table.join(awful.button({}, 1, function() + if weather_popup.visible then + weather_widget:set_bg('#00000000') + weather_popup.visible = not weather_popup.visible + else + weather_widget:set_bg(beautiful.bg_focus) + weather_popup:move_next_to(mouse.current_widget_geometry) + end + end))) + + watch( + string.format(GET_FORECAST_CMD, weather_api), + timeout, -- API limit is 1k req/day; day has 1440 min; every 2 min is good + update_widget, weather_widget + ) + + return weather_widget +end + +return setmetatable(weather_widget, {__call = function(_, ...) return worker(...) end})