diff --git a/modules/home-manager/default.nix b/modules/home-manager/default.nix index 1b9e596..cbca9df 100644 --- a/modules/home-manager/default.nix +++ b/modules/home-manager/default.nix @@ -14,6 +14,7 @@ ../rice/hyprland ../rice/gtk.nix ../rice/kitty.nix + ../rice/waybar ../shell ]; diff --git a/modules/rice/waybar/crypto.py b/modules/rice/waybar/crypto.py new file mode 100644 index 0000000..bd7467c --- /dev/null +++ b/modules/rice/waybar/crypto.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +import requests +import json + + +url = "https://api.coingecko.com/api/v3/coins/markets" +params = { + "vs_currency": "usd", + "order": "market_cap_desc", + "per_page": 10, + "price_change_percentage": "24h", + "page": 1, +} + +response = requests.get(url, params=params) + +if response.status_code == 200: + top_cryptos = response.json() + tooltip = 'Crypto\n' + for crypto in top_cryptos: + name = crypto["name"] + symbol = crypto["symbol"] + price = crypto["current_price"] + change = crypto["price_change_percentage_24h"] + tooltip += str(f" {name}: ${price} | {change:.2f}%\n") + + out_data = { + "text": f"󰠓", + "alt": f"", + "tooltip": tooltip, + "class": "weather", + } + print(json.dumps(out_data)) +else: + exit(1) diff --git a/modules/rice/waybar/default.nix b/modules/rice/waybar/default.nix new file mode 100644 index 0000000..05ec5c3 --- /dev/null +++ b/modules/rice/waybar/default.nix @@ -0,0 +1,133 @@ +{ + pkgs, + lib, + ... +}: +with lib; let + waybar-wttr = pkgs.stdenv.mkDerivation { + name = "waybar-wttr"; + buildInputs = [ + (pkgs.python39.withPackages + (pythonPackages: with pythonPackages; [requests])) + ]; + unpackPhase = "true"; + installPhase = '' + mkdir -p $out/bin + cp ${./waybar-wttr.py} $out/bin/waybar-wttr + chmod +x $out/bin/waybar-wttr + ''; + }; +in { + home.packages = [waybar-wttr]; + programs.waybar = { + enable = true; + style = import ./style.nix; + systemd = { + enable = true; + target = "hyprland-session.target"; + }; + settings = { + mainBar = { + layer = "top"; + position = "left"; + width = 57; + spacing = 7; + modules-left = [ + "custom/search" + "hyprland/workspaces" + "custom/lock" + "custom/weather" + "backlight" + "battery" + ]; + modules-center = []; + modules-right = ["pulseaudio" "network" "clock" "custom/power"]; + "hyprland/workspaces" = { + on-click = "activate"; + format = "{icon}"; + active-only = false; + format-icons = { + "1" = "一"; + "2" = "二"; + "3" = "三"; + "4" = "四"; + "5" = "五"; + "6" = "六"; + "7" = "七"; + "8" = "八"; + "9" = "九"; + "10" = "十"; + }; + + persistent_workspaces = { + "*" = 5; + }; + }; + "custom/search" = { + format = " "; + tooltip = false; + on-click = "${pkgs.tofi}/bin/tofi-drun"; + }; + + "custom/weather" = { + format = "{}"; + tooltip = true; + interval = 3600; + exec = "waybar-wttr"; + return-type = "json"; + }; + "custom/lock" = { + tooltip = false; + on-click = "sh -c '(sleep 0.5s; swaylock)' & disown"; + format = ""; + }; + "custom/power" = { + tooltip = false; + on-click = "wlogout &"; + format = ""; + }; + clock = { + format = '' + {:%H + %M}''; + tooltip-format = '' + {:%Y %B} + {calendar}''; + }; + backlight = { + format = "{icon}"; + format-icons = ["" "" "" "" "" "" "" "" ""]; + }; + battery = { + states = { + warning = 30; + critical = 15; + }; + format = "{icon}"; + format-charging = "{icon}\n󰚥"; + tooltip-format = "{timeTo} {capacity}% 󱐋{power}"; + format-icons = ["󰂃" "󰁺" "󰁻" "󰁼" "󰁽" "󰁾" "󰁿" "󰂀" "󰂁" "󰂂" "󰁹"]; + }; + network = { + format-wifi = "󰤨"; + format-ethernet = "󰤨"; + format-alt = "󰤨"; + format-disconnected = "󰤭"; + tooltip-format = "{ipaddr}/{ifname} via {gwaddr} ({signalStrength}%)"; + }; + pulseaudio = { + scroll-step = 5; + tooltip = true; + tooltip-format = "{volume}% {format_source}"; + on-click = "${pkgs.killall}/bin/killall pavucontrol || ${pkgs.pavucontrol}/bin/pavucontrol"; + format = " {icon}\n{volume}%"; + format-bluetooth = "󰂯 {icon} {volume}%"; + format-muted = "󰝟 "; + format-icons = { + default = ["" "" " "]; + }; + }; + }; + }; + }; +} diff --git a/modules/rice/waybar/sakura.png b/modules/rice/waybar/sakura.png new file mode 100644 index 0000000..21e463c Binary files /dev/null and b/modules/rice/waybar/sakura.png differ diff --git a/modules/rice/waybar/style.nix b/modules/rice/waybar/style.nix new file mode 100644 index 0000000..27e5798 --- /dev/null +++ b/modules/rice/waybar/style.nix @@ -0,0 +1,129 @@ +'' + * { + /* `otf-font-awesome` is required to be installed for icons */ + font-family: Material Design Icons, Iosevka Nerd Font; + } + + window#waybar { + background-color: rgba(48, 52, 70, 0.88); + border-radius: 0px; + color: #c6d0f5; + font-size: 20px; + /* transition-property: background-color; */ + transition-duration: 0.5s; + } + + window#waybar.hidden { + opacity: 0.2; + } + + #workspaces { + font-size: 15px; + background-color: #414559; + } + + #pulseaudio { + color: #a6d189; + } + #network { + color: #8caaee; + } + + #custom-search, + #clock { + background-color: #414559; + } + + #workspaces button { + background-color: transparent; + color: #8caaee; + /* Use box-shadow instead of border so the text isn't offset */ + box-shadow: inset 0 -3px transparent; + } + + /* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ + #workspaces button:hover { + color: #85c1dc; + } + + #custom-power { + color: #e78284; + } + + #custom-lock { + color: #8caaee; + } + + #workspaces button.active { + color: #e5c890; + } + + #workspaces button.urgent { + background-color: #e78284; + } + + #clock, + #network, + #cpu, + #battery, + #backlight, + #memory, + #workspaces, + #custom-search, + #custom-power, + #custom-todo, + #custom-lock, + #custom-weather, + #custom-btc, + #custom-eth, + #volume, + #pulseaudio { + border-radius: 15px; + margin: 0px 7px 0px 7px; + background-color: rgba(65, 69, 89, 0.9); + padding: 10px 0px 10px 0px; + } + + #custom-power { + margin-bottom: 7px; + padding-right: 6px; + } + #custom-search { + background-image: url("${./sakura.png}"); + background-size: 60%; + background-position: center; + background-repeat: no-repeat; + margin-top: 7px; + } + #clock { + font-weight: 700; + font-size: 20px; + padding: 5px 0px 5px 0px; + font-family: "Iosevka Term"; + } + #backlight { + padding-right: 2px; + color: #e5c890; + } + #battery { + color: #a6d189; + } + + #battery.warning { + color: #ef9f76; + } + + #battery.critical:not(.charging) { + color: #e78284; + } + tooltip { + font-family: 'Lato', sans-serif; + border-radius: 15px; + padding: 20px; + margin: 30px; + } + tooltip label { + font-family: 'Lato', sans-serif; + padding: 20px; + } +'' diff --git a/modules/rice/waybar/waybar-wttr.py b/modules/rice/waybar/waybar-wttr.py new file mode 100644 index 0000000..bc3a7ae --- /dev/null +++ b/modules/rice/waybar/waybar-wttr.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +import json +import requests +from datetime import datetime + +WEATHER_CODES = { + '113': '☀️ ', + '116': '⛅ ', + '119': '☁️ ', + '122': '☁️ ', + '143': '☁️ ', + '176': '🌧️', + '179': '🌧️', + '182': '🌧️', + '185': '🌧️', + '200': '⛈️ ', + '227': '🌨️', + '230': '🌨️', + '248': '☁️ ', + '260': '☁️ ', + '263': '🌧️', + '266': '🌧️', + '281': '🌧️', + '284': '🌧️', + '293': '🌧️', + '296': '🌧️', + '299': '🌧️', + '302': '🌧️', + '305': '🌧️', + '308': '🌧️', + '311': '🌧️', + '314': '🌧️', + '317': '🌧️', + '320': '🌨️', + '323': '🌨️', + '326': '🌨️', + '329': '❄️ ', + '332': '❄️ ', + '335': '❄️ ', + '338': '❄️ ', + '350': '🌧️', + '353': '🌧️', + '356': '🌧️', + '359': '🌧️', + '362': '🌧️', + '365': '🌧️', + '368': '🌧️', + '371': '❄️', + '374': '🌨️', + '377': '🌨️', + '386': '🌨️', + '389': '🌨️', + '392': '🌧️', + '395': '❄️ ' +} + +data = {} + + +weather = requests.get("https://wttr.in/?format=j1").json() + + +def format_time(time): + return time.replace("00", "").zfill(2) + + +def format_temp(temp): + return (hour['FeelsLikeC']+"°").ljust(3) + + +def format_chances(hour): + chances = { + "chanceoffog": "Fog", + "chanceoffrost": "Frost", + "chanceofovercast": "Overcast", + "chanceofrain": "Rain", + "chanceofsnow": "Snow", + "chanceofsunshine": "Sunshine", + "chanceofthunder": "Thunder", + "chanceofwindy": "Wind" + } + + conditions = [] + for event in chances.keys(): + if int(hour[event]) > 0: + conditions.append(chances[event]+" "+hour[event]+"%") + return ", ".join(conditions) + +tempint = int(weather['current_condition'][0]['FeelsLikeC']) +extrachar = '' +if tempint >= 0 and tempint < 10: + extrachar = '+' + + +data['text'] = ' '+WEATHER_CODES[weather['current_condition'][0]['weatherCode']] + \ + "\n "+extrachar+weather['current_condition'][0]['FeelsLikeC']+"°" + +data['tooltip'] = f"{weather['current_condition'][0]['weatherDesc'][0]['value']} {weather['current_condition'][0]['temp_C']}°\n" +data['tooltip'] += f"Feels like: {weather['current_condition'][0]['FeelsLikeC']}°\n" +data['tooltip'] += f"Wind: {weather['current_condition'][0]['windspeedKmph']}Km/h\n" +data['tooltip'] += f"Humidity: {weather['current_condition'][0]['humidity']}%\n" +for i, day in enumerate(weather['weather']): + data['tooltip'] += f"\n" + if i == 0: + data['tooltip'] += "Today, " + if i == 1: + data['tooltip'] += "Tomorrow, " + data['tooltip'] += f"{day['date']}\n" + data['tooltip'] += f"⬆️ {day['maxtempC']}° ⬇️ {day['mintempC']}° " + data['tooltip'] += f"🌅 {day['astronomy'][0]['sunrise']} 🌇 {day['astronomy'][0]['sunset']}\n" + for hour in day['hourly']: + if i == 0: + if int(format_time(hour['time'])) < datetime.now().hour-2: + continue + data['tooltip'] += f"{format_time(hour['time'])} {WEATHER_CODES[hour['weatherCode']]} {format_temp(hour['FeelsLikeC'])} {hour['weatherDesc'][0]['value']}, {format_chances(hour)}\n" + + +print(json.dumps(data))