{ xdg.configFile."waybar/config".text = /* json */ '' { "layer": "top", "position": "top", "mod": "dock", "exclusive": true, "passthrough": false, "gtk-layer-shell": true, "height": 0, "modules-left": [ "clock", "custom/weather", "wlr/workspaces" ], "modules-center": ["hyprland/window"], "modules-right": [ "tray", "custom/updates", "custom/language", "battery", "backlight", "pulseaudio", "pulseaudio#microphone" ], "hyprland/window": { "format": "{}" }, "wlr/workspaces": { "disable-scroll": true, "all-outputs": true, "on-click": "activate", //"format": "{icon}", "persistent_workspaces": { "1": [], "2": [], "3": [], "4": [], "5": [], "6": [], "7": [], "8": [], "9": [], "10": [] } }, "custom/updates": { "format": " {}", "interval": 7200, // every two hours "exec": "i=$(checkupdates); echo \"$i\" |wc -l; echo \"$i\" |column -t |tr '\n' '\r'", // # of updates and tooltip details "exec-if": "exit 0", // always run; consider advanced run conditions "on-click": "kitty -e sudo pacman -Syu", // update system "signal": 8 }, "custom/weather" : { "tooltip" : true, "format" : "{}", "interval" : 30, "exec" : "~/.config/waybar/waybar-wttr.py", "return-type" : "json" }, "tray": { "icon-size": 13, "spacing": 10 }, "clock": { "format": "{: %R  %d/%m}", "tooltip-format": "{:%Y %B}\n{calendar}" }, "backlight": { "device": "intel_backlight", "format": "{icon} {percent}%", "format-icons": ["", "", ""], "on-scroll-up": "brightnessctl set 1%+", "on-scroll-down": "brightnessctl set 1%-", "min-length": 6 }, "battery": { "states": { "good": 95, "warning": 30, "critical": 20 }, "format": "{icon} {capacity}%", "format-charging": " {capacity}%", "format-plugged": " {capacity}%", "format-alt": "{time} {icon}", "format-icons": ["", "", "", "", "", "", "", "", "", "", ""] }, "pulseaudio": { "format": "{icon} {volume}%", "tooltip": false, "format-muted": " Muted", "on-click": "pamixer -t", "on-scroll-up": "pamixer -i 5", "on-scroll-down": "pamixer -d 5", "scroll-step": 5, "format-icons": { "headphone": "", "hands-free": "", "headset": "", "phone": "", "portable": "", "car": "", "default": ["", "", ""] } }, "pulseaudio#microphone": { "format": "{format_source}", "format-source": " {volume}%", "format-source-muted": " Muted", "on-click": "pamixer --default-source -t", "on-scroll-up": "pamixer --default-source -i 5", "on-scroll-down": "pamixer --default-source -d 5", "scroll-step": 5 } } ''; xdg.configFile."waybar/style.css".text = /* css */ '' * { border: none; border-radius: 0; font-family: Cartograph CF Nerd Font, monospace; font-weight: bold; font-size: 14px; min-height: 0; } window#waybar { background: rgba(21, 18, 27, 0); color: #cdd6f4; } tooltip { background: #1e1e2e; border-radius: 10px; border-width: 2px; border-style: solid; border-color: #11111b; } #workspaces button { padding: 5px; color: #313244; margin-right: 5px; } #workspaces button.active { color: #a6adc8; } #workspaces button.focused { color: #a6adc8; background: #eba0ac; border-radius: 10px; } #workspaces button.urgent { color: #11111b; background: #a6e3a1; border-radius: 10px; } #workspaces button:hover { background: #11111b; color: #cdd6f4; border-radius: 10px; } #custom-language, #custom-updates, #custom-caffeine, #custom-weather, #window, #clock, #battery, #pulseaudio, #network, #workspaces, #tray, #backlight { background: #1e1e2e; padding: 0px 10px; margin: 3px 0px; margin-top: 10px; border: 1px solid #181825; } #tray { border-radius: 10px; margin-right: 10px; } #workspaces { background: #1e1e2e; border-radius: 10px; margin-left: 10px; padding-right: 0px; padding-left: 5px; } #custom-caffeine { color: #89dceb; border-radius: 10px 0px 0px 10px; border-right: 0px; margin-left: 10px; } #custom-language { color: #f38ba8; border-left: 0px; border-right: 0px; } #custom-updates { color: #f5c2e7; border-radius: 10px 0px 0px 10px; border-left: 0px; border-right: 0px; } #window { border-radius: 10px; margin-left: 60px; margin-right: 60px; } #clock { color: #fab387; border-radius: 10px 0px 0px 10px; margin-left: 5px; border-right: 0px; } #network { color: #f9e2af; border-left: 0px; border-right: 0px; } #pulseaudio { color: #89b4fa; border-left: 0px; border-right: 0px; } #pulseaudio.microphone { color: #cba6f7; border-radius: 0px 10px 10px 0px; border-left: 0px; border-right: 0px; margin-right: 5px; } #battery { color: #a6e3a1; border-radius: 0 10px 10px 0; margin-right: 10px; border-left: 0px; } #custom-weather { border-radius: 0px 10px 10px 0px; border-right: 0px; margin-left: 0px; } ''; xdg.configFile."waybar/waybar-wttr.py".text = /* python */ '' #!/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['FeelsLikeF']+"°").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]['FeelsLikeF']) extrachar = "" if tempint > 0 and tempint < 10: extrachar = '+' data['text'] = ' '+WEATHER_CODES[weather['current_condition'][0]['weatherCode']] + \ " "+extrachar+weather['current_condition'][0]['FeelsLikeF']+"°" 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]['FeelsLikeF']}°\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['maxtempF']}° ⬇️ {day['mintempF']}° " 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['FeelsLikeF'])} {hour['weatherDesc'][0]['value']}, {format_chances(hour)}\n" print(json.dumps(data)) ''; }