Compare commits

...

3 commits
main ... master

Author SHA1 Message Date
06c0fbb8e9 On branch master
renamed:    music-notify -> bin/music-notify
 	renamed:    motd.sh -> mensa/motd.sh
 	renamed:    motdmb.sh -> mensa/motdmb.sh
 	deleted:    testing-wallpaper
 	renamed:    wallpaper-picker -> wallpaper/hyprland/wallpaper-picker
 	new file:   wallpaper/niri/README.md
 	renamed:    wallpaper-niri -> wallpaper/niri/wallpaper-niri
	new file:   wallpaper/niri/wallpaper.rasi
2026-04-02 08:39:40 +02:00
f05962b900 edited wallpaper-niri 2026-04-02 08:29:20 +02:00
5e0aef0275 added some files 2026-04-02 07:49:27 +02:00
8 changed files with 267 additions and 1 deletions

View file

@ -1,2 +1,2 @@
# coding # coding
just some nice little coding projects, mostly bash (and vibecoded lol)

72
bin/music-notify Executable file
View file

@ -0,0 +1,72 @@
#!/usr/bin/env python3
import subprocess, threading, urllib.request
import dbus, dbus.service, dbus.mainloop.glib
from gi.repository import GLib
class MusicNotifier:
def __init__(self):
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
obj = bus.get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
self.iface = dbus.Interface(obj, "org.freedesktop.Notifications")
self.notif_id = dbus.UInt32(0)
bus.add_signal_receiver(
self.on_action,
dbus_interface="org.freedesktop.Notifications",
signal_name="ActionInvoked"
)
def get_art(self, url):
if not url:
return ""
try:
if url.startswith("file://"):
return url[7:]
path = "/tmp/music_art.jpg"
urllib.request.urlretrieve(url, path)
return path
except:
return ""
def notify(self, artist, title, art_url, status):
art = self.get_art(art_url)
play_label = "⏸ Pause" if status == "Playing" else "▶ Play"
actions = ["prev", "⏮ Zurück", "toggle", play_label, "next", "⏭ Weiter"]
hints = {"image-path": dbus.String(art)} if art else {}
self.notif_id = self.iface.Notify(
"music", self.notif_id, art,
title, artist,
actions, hints, 0
)
def on_action(self, notif_id, action):
if notif_id != self.notif_id:
return
cmds = {"prev": "previous", "toggle": "play-pause", "next": "next"}
if action in cmds:
subprocess.run(["playerctl", cmds[action]])
def monitor(self):
proc = subprocess.Popen(
["playerctl", "--follow", "metadata", "--format",
"{{artist}}||{{title}}||{{mpris:artUrl}}||{{status}}"],
stdout=subprocess.PIPE, text=True
)
prev = ""
for line in proc.stdout:
parts = line.strip().split("||")
if len(parts) != 4:
continue
artist, title, art_url, status = parts
if title != prev:
prev = title
self.notify(artist, title, art_url, status)
def run(self):
threading.Thread(target=self.monitor, daemon=True).start()
GLib.MainLoop().run()
if __name__ == "__main__":
MusicNotifier().run()

View file

@ -0,0 +1,39 @@
#!/bin/bash
# wallpaper-picker.sh
WALLPAPER_DIR="$HOME/Pictures/wallpaper"
EXTENSIONS="jpg|jpeg|png|gif|webp|bmp|tiff|tga|svg|avif"
declare -A wall_map
while IFS= read -r path; do
name=$(basename "$path")
wall_map["$name"]="$path"
done < <(find "$WALLPAPER_DIR" -maxdepth 1 -type f \
-regextype posix-extended -iregex ".*\.($EXTENSIONS)" | sort)
chosen=$(printf '%s\n' "${!wall_map[@]}" | sort | \
wofi \
--dmenu \
--prompt " Wallpaper" \
--insensitive \
--no-actions \
--width 500 \
--height 400 \
)
[[ -z "$chosen" ]] && exit 0
full_path="${wall_map[$chosen]}"
[[ ! -f "$full_path" ]] && {
notify-send "wallpaper-picker" "Not found: $full_path" --urgency=critical
exit 1
}
awww img "$full_path" --transition-type grow --transition-step 90
persist="$HOME/.config/hypr/wallpaper-restore.sh"
printf '#!/bin/bash\nawww-daemon &\nsleep 0.5\nawww img "%s" --transition-type simple\n' "$full_path" > "$persist"
chmod +x "$persist"
notify-send "Wallpaper" "$chosen" --urgency=low

13
wallpaper/niri/README.md Normal file
View file

@ -0,0 +1,13 @@
# Wallpaper-Picker on Niri
arch: yay -S awww rofi libnotify
nix: environment.systemPackages = with pkgs; [
rofi-wayland
awww
libnotify
];
put wallpaper.rasi in ~/home/.config/rofi/wallpaper.rasi
wallpapers should stay in ~/home/$USER/Pictures/wallpaper

55
wallpaper/niri/wallpaper-niri Executable file
View file

@ -0,0 +1,55 @@
#!/usr/bin/env bash
set -euo pipefail
WALLPAPER_DIR="${HOME}/Pictures/wallpaper"
EXTENSIONS="jpg|jpeg|png|gif|webp|bmp|tiff|tga|svg|avif"
declare -A wall_map
while IFS= read -r -d '' path; do
name="$(basename "$path")"
wall_map["$name"]="$path"
done < <(
find "$WALLPAPER_DIR" -maxdepth 1 -type f \
-regextype posix-extended \
-iregex ".*\.(${EXTENSIONS})" \
-print0 | sort -z
)
chosen="$(
for name in "${!wall_map[@]}"; do
printf '%s\0icon\x1fthumbnail://%s\n' "$name" "${wall_map[$name]}"
done | sort | rofi \
-dmenu \
-show-icons \
-i \
-p "wallpaper" \
-theme "$HOME/.config/rofi/wallpaper.rasi" \
-kb-accept-entry "Return,KP_Enter" \
-kb-element-next "Tab" \
-kb-element-prev "ISO_Left_Tab"
)"
[[ -z "${chosen:-}" ]] && exit 0
full_path="${wall_map[$chosen]:-}"
if [[ -z "${full_path}" || ! -f "${full_path}" ]]; then
notify-send "wallpaper-picker" "Not found: $chosen" --urgency=critical
exit 1
fi
awww img "$full_path" --transition-type grow --transition-step 90
persist="$HOME/.config/niri/wallpaper-restore.sh"
mkdir -p "$(dirname "$persist")"
cat > "$persist" <<EOF
#!/usr/bin/env bash
pgrep -x awww-daemon >/dev/null || awww-daemon &
sleep 0.5
awww img "$full_path" --transition-type simple
EOF
chmod +x "$persist"
notify-send "Wallpaper" "$chosen" --urgency=low

View file

@ -0,0 +1,87 @@
configuration {
show-icons: true;
}
* {
bg: #0f1115ee;
bg-alt: #171a21ff;
fg: #e6eaf2ff;
fg-muted: #aab4c3ff;
accent: #89b4faff;
border: #2a2f3aff;
selected: #1e2530ff;
background-color: transparent;
text-color: @fg;
}
window {
location: center;
anchor: center;
width: 28%;
border: 2px;
border-radius: 14px;
border-color: @border;
background-color: @bg;
padding: 12px;
}
mainbox {
children: [ inputbar, listview ];
spacing: 10px;
}
inputbar {
children: [ prompt, entry ];
spacing: 8px;
padding: 10px 12px;
border-radius: 10px;
background-color: @bg-alt;
}
prompt {
text-color: @accent;
}
entry {
text-color: @fg;
placeholder: "search...";
placeholder-color: @fg-muted;
}
listview {
columns: 3;
lines: 1;
dynamic: false;
cycle: false;
scrollbar: true;
spacing: 10px;
layout: vertical;
}
element {
orientation: vertical;
padding: 8px;
border-radius: 10px;
background-color: transparent;
}
element normal.normal {
background-color: transparent;
text-color: @fg-muted;
}
element selected.normal {
background-color: @selected;
text-color: @fg;
}
element-icon {
size: 120px;
border-radius: 8px;
}
element-text {
horizontal-align: 0.5;
vertical-align: 0.5;
}