add Go implementation for changing wallpaper with random selection from Wallhaven API

This commit is contained in:
sudacode 2025-05-02 22:28:27 -07:00
parent 2f66d3191c
commit e0f6105dc2
Signed by: sudacode
SSH Key Fingerprint: SHA256:lT5C2bB398DcX6daCF/gYFNSTK3y+Du3oTGUnYzfTEw
2 changed files with 196 additions and 8 deletions

171
change-wallpaper.go Normal file
View File

@ -0,0 +1,171 @@
package main
import (
"encoding/json"
"fmt"
"io"
"math/rand"
"net/http"
"net/url"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"time"
)
const (
wallhavenAPI = "https://wallhaven.cc/api/v1"
wallpaperDir = "Pictures/wallpapers/wallhaven"
)
var topics = []string{
"132262 - Mobuseka",
"konosuba",
"bunny girl senpai",
"oshi no ko",
"kill la kill",
"lofi",
"eminence in shadow",
}
type WallhavenResponse struct {
Data []struct {
Path string `json:"path"`
} `json:"data"`
}
func main() {
// Initialize random source
r := rand.New(rand.NewSource(time.Now().UnixNano()))
// Check if a file path was provided as argument
if len(os.Args) > 1 {
imgPath := os.Args[1]
if _, err := os.Stat(imgPath); err == nil {
changeWallpaper(imgPath, "")
return
}
}
// Create wallpaper directory if it doesn't exist
homeDir, err := os.UserHomeDir()
if err != nil {
fmt.Fprintf(os.Stderr, "Error getting home directory: %v\n", err)
os.Exit(1)
}
wallpaperPath := filepath.Join(homeDir, wallpaperDir)
if err := os.MkdirAll(wallpaperPath, 0755); err != nil {
fmt.Fprintf(os.Stderr, "Error creating wallpaper directory: %v\n", err)
os.Exit(1)
}
// Download and set new wallpaper
newWallpaper, topic := downloadRandomWallpaper(wallpaperPath, r)
if newWallpaper != "" {
changeWallpaper(newWallpaper, topic)
} else {
notify("Failed to download new wallpaper", "critical")
os.Exit(1)
}
}
func downloadRandomWallpaper(wallpaperPath string, r *rand.Rand) (string, string) {
// Select random topic
topic := topics[r.Intn(len(topics))]
var query string
var displayName string
// Check if the topic is a tag ID with name
if tagRegex := regexp.MustCompile(`^(\d+)\s*-\s*(.+)$`); tagRegex.MatchString(topic) {
matches := tagRegex.FindStringSubmatch(topic)
query = fmt.Sprintf("id:%s", matches[1])
displayName = strings.TrimSpace(matches[2])
} else {
query = url.QueryEscape(topic)
displayName = topic
}
fmt.Fprintf(os.Stderr, "Searching for wallpapers related to: %s\n", displayName)
// Get wallpapers from Wallhaven API
resp, err := http.Get(fmt.Sprintf("%s/search?q=%s&purity=100&categories=110&sorting=random", wallhavenAPI, query))
if err != nil {
fmt.Fprintf(os.Stderr, "Error fetching from Wallhaven: %v\n", err)
return "", ""
}
defer resp.Body.Close()
// Parse response
var wallhavenResp WallhavenResponse
if err := json.NewDecoder(resp.Body).Decode(&wallhavenResp); err != nil {
fmt.Fprintf(os.Stderr, "Error parsing response: %v\n", err)
return "", ""
}
if len(wallhavenResp.Data) == 0 {
fmt.Fprintf(os.Stderr, "No wallpapers found for topic: %s\n", displayName)
return "", ""
}
// Select a random image from the results
randomIndex := r.Intn(len(wallhavenResp.Data))
wallpaperURL := wallhavenResp.Data[randomIndex].Path
filename := filepath.Base(wallpaperURL)
filepath := filepath.Join(wallpaperPath, filename)
fmt.Fprintf(os.Stderr, "Downloading: %s\n", filename)
resp, err = http.Get(wallpaperURL)
if err != nil {
fmt.Fprintf(os.Stderr, "Error downloading wallpaper: %v\n", err)
return "", ""
}
defer resp.Body.Close()
file, err := os.Create(filepath)
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating file: %v\n", err)
return "", ""
}
defer file.Close()
if _, err := io.Copy(file, resp.Body); err != nil {
fmt.Fprintf(os.Stderr, "Error saving wallpaper: %v\n", err)
return "", ""
}
return filepath, displayName
}
func changeWallpaper(wallpaperPath, topic string) {
// Save current wallpaper path
homeDir, _ := os.UserHomeDir()
wallpaperFile := filepath.Join(homeDir, ".wallpaper")
if err := os.WriteFile(wallpaperFile, []byte(wallpaperPath), 0644); err != nil {
fmt.Fprintf(os.Stderr, "Error saving wallpaper path: %v\n", err)
}
// Change wallpaper using hyprctl
cmd := exec.Command("hyprctl", "hyprpaper", "reload", ","+wallpaperPath)
if err := cmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "Error changing wallpaper: %v\n", err)
}
// Send notification
filename := filepath.Base(wallpaperPath)
message := fmt.Sprintf("Wallpaper changed to %s", filename)
if topic != "" {
message += fmt.Sprintf(" (%s)", topic)
}
notify(message, "normal")
}
func notify(message, urgency string) {
cmd := exec.Command("notify-send", "-i", "hyprpaper", "-u", urgency, "change-wallpaper.go", message)
if err := cmd.Run(); err != nil {
fmt.Fprintf(os.Stderr, "Error sending notification: %v\n", err)
}
}

View File

@ -10,7 +10,7 @@ TOPICS=(
"kill la kill" "kill la kill"
"lofi" "lofi"
"eminence in shadow" "eminence in shadow"
"mobuseka" "132262 - Mobuseka"
) )
# Create wallpaper directory if it doesn't exist # Create wallpaper directory if it doesn't exist
@ -18,17 +18,34 @@ mkdir -p "$WALLPAPER_DIR"
# Function to download a random wallpaper from Wallhaven # Function to download a random wallpaper from Wallhaven
download_random_wallpaper() { download_random_wallpaper() {
# Select a random topic # Select random topic
local random_topic="${TOPICS[$RANDOM % ${#TOPICS[@]}]}" local random_topic="${TOPICS[$RANDOM % ${#TOPICS[@]}]}"
local query=$(echo "$random_topic" | sed 's/ /+/g') local query
local display_name
echo "Searching for wallpapers related to: $random_topic" >&2 # Check if the topic is a tag ID with name
if [[ "$random_topic" =~ ^([0-9]+)[[:space:]]*-[[:space:]]*(.+)$ ]]; then
query="id:${BASH_REMATCH[1]}"
display_name="${BASH_REMATCH[2]}"
else
query=$(echo "$random_topic" | sed 's/ /+/g')
display_name="$random_topic"
fi
echo "Searching for wallpapers related to: $display_name" >&2
# Get wallpapers from Wallhaven API # Get wallpapers from Wallhaven API
local response=$(curl -s "$WALLHAVEN_API/search?q=$query&purity=100&categories=110&sorting=random") local response=$(curl -s "$WALLHAVEN_API/search?q=$query&purity=100&categories=110&sorting=random")
# Get a random image URL from the response # Get all image URLs and select a random one
local url=$(echo "$response" | jq -r '.data[0].path') local urls=($(echo "$response" | jq -r '.data[].path'))
if [ ${#urls[@]} -eq 0 ]; then
echo "No wallpapers found for topic: $display_name" >&2
return 1
fi
local random_index=$((RANDOM % ${#urls[@]}))
local url="${urls[$random_index]}"
if [ -n "$url" ] && [ "$url" != "null" ]; then if [ -n "$url" ] && [ "$url" != "null" ]; then
local filename=$(basename "$url") local filename=$(basename "$url")
@ -36,12 +53,12 @@ download_random_wallpaper() {
curl -s "$url" -o "$WALLPAPER_DIR/$filename" curl -s "$url" -o "$WALLPAPER_DIR/$filename"
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "$WALLPAPER_DIR/$filename" echo "$WALLPAPER_DIR/$filename"
echo "$random_topic" > "$WALLPAPER_DIR/.last_topic" echo "$display_name" > "$WALLPAPER_DIR/.last_topic"
return 0 return 0
fi fi
fi fi
echo "No wallpapers found for topic: $random_topic" >&2 echo "No wallpapers found for topic: $display_name" >&2
return 1 return 1
} }