mirror of
https://github.com/ksyasuda/dotfiles.git
synced 2025-12-05 02:53:38 -08:00
update
This commit is contained in:
204
projects/go/change-wallpaper/change-wallpaper.go
Normal file
204
projects/go/change-wallpaper/change-wallpaper.go
Normal file
@@ -0,0 +1,204 @@
|
||||
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"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Topics []string `json:"topics"`
|
||||
}
|
||||
|
||||
var defaultTopics = []string{
|
||||
"132262 - Mobuseka",
|
||||
"konosuba",
|
||||
"bunny girl senpai",
|
||||
"oshi no ko",
|
||||
"kill la kill",
|
||||
"lofi",
|
||||
"eminence in shadow",
|
||||
}
|
||||
|
||||
func loadConfig() []string {
|
||||
homeDir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return defaultTopics
|
||||
}
|
||||
configPath := filepath.Join(homeDir, ".config", "change-wallpaper", "config.json")
|
||||
file, err := os.Open(configPath)
|
||||
if err != nil {
|
||||
return defaultTopics
|
||||
}
|
||||
defer file.Close()
|
||||
var cfg Config
|
||||
if err := json.NewDecoder(file).Decode(&cfg); err != nil || len(cfg.Topics) == 0 {
|
||||
return defaultTopics
|
||||
}
|
||||
return cfg.Topics
|
||||
}
|
||||
|
||||
type WallhavenResponse struct {
|
||||
Data []struct {
|
||||
Path string `json:"path"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Initialize random source
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
// Load topics from config or use defaults
|
||||
topics := loadConfig()
|
||||
|
||||
// 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, topics)
|
||||
if newWallpaper != "" {
|
||||
changeWallpaper(newWallpaper, topic)
|
||||
} else {
|
||||
notify("Failed to download new wallpaper", "critical")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func downloadRandomWallpaper(wallpaperPath string, r *rand.Rand, topics []string) (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 with wallpaper as icon
|
||||
filename := filepath.Base(wallpaperPath)
|
||||
message := fmt.Sprintf("Wallpaper changed to %s", filename)
|
||||
if topic != "" {
|
||||
message += fmt.Sprintf(" (%s)", topic)
|
||||
}
|
||||
notifyWithIcon(message, "normal", wallpaperPath)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
// notifyWithIcon sends a notification with a custom icon (wallpaper image)
|
||||
func notifyWithIcon(message, urgency, iconPath string) {
|
||||
cmd := exec.Command("notify-send", "-i", iconPath, "-u", urgency, "change-wallpaper.go", message)
|
||||
if err := cmd.Run(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error sending notification: %v\n", err)
|
||||
}
|
||||
}
|
||||
3
projects/go/screenshot/go.mod
Normal file
3
projects/go/screenshot/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module gitea.suda.codes/sudacode/screenshot
|
||||
|
||||
go 1.24.2
|
||||
113
projects/go/screenshot/screenshot.go
Normal file
113
projects/go/screenshot/screenshot.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
scriptName = filepath.Base(os.Args[0])
|
||||
tmpDir = os.TempDir()
|
||||
defaultFilename = "screenshot.png"
|
||||
tmpScreenshot = filepath.Join(tmpDir, defaultFilename)
|
||||
requirements = []string{"grim", "slurp", "rofi", "zenity", "wl-copy", "jq", "hyprctl", "swappy", "notify-send"}
|
||||
)
|
||||
|
||||
type Option struct {
|
||||
Desc string
|
||||
Cmd []string
|
||||
}
|
||||
|
||||
func notify(body, title string) {
|
||||
if title == "" {
|
||||
title = scriptName
|
||||
}
|
||||
cmd := exec.Command("notify-send", title, body)
|
||||
if err := cmd.Run(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "notify error: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func checkDeps() {
|
||||
for _, cmd := range requirements {
|
||||
if _, err := exec.LookPath(cmd); err != nil {
|
||||
log.Fatalf("Error: %s is not installed. Please install it first.", cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
checkDeps()
|
||||
options := []Option{
|
||||
{"1. Select a region and save", []string{"sh", "-c", fmt.Sprintf("slurp | grim -g - '%s'", tmpScreenshot)}},
|
||||
{"2. Select a region and copy to clipboard", []string{"sh", "-c", "slurp | grim -g - - | wl-copy"}},
|
||||
{"3. Whole screen", []string{"grim", tmpScreenshot}},
|
||||
{"4. Current window", []string{"sh", "-c", fmt.Sprintf("hyprctl -j activewindow | jq -r '\\.at[0],(\\.at[1]) \\.size[0]x(\\.size[1])' | grim -g - '%s'", tmpScreenshot)}},
|
||||
{"5. Edit", []string{"sh", "-c", "slurp | grim -g - - | swappy -f -"}},
|
||||
{"6. Quit", []string{"true"}},
|
||||
}
|
||||
|
||||
var menu bytes.Buffer
|
||||
for _, opt := range options {
|
||||
menu.WriteString(opt.Desc)
|
||||
menu.WriteByte('\n')
|
||||
}
|
||||
|
||||
rofi := exec.Command("rofi", "-dmenu", "-i", "-p", "Enter option or select from the list", "-mesg", "Select a Screenshot Option", "-format", "i", "-theme-str", "listview {columns: 2; lines: 3;} window {width: 55%;}", "-yoffset", "30", "-xoffset", "30", "-a", "0", "-no-custom", "-location", "0")
|
||||
rofi.Stdin = &menu
|
||||
out, err := rofi.Output()
|
||||
if err != nil {
|
||||
notify("No option selected.", "")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
choiceStr := strings.TrimSpace(string(out))
|
||||
idx, err := strconv.Atoi(choiceStr)
|
||||
if err != nil || idx < 0 || idx >= len(options) {
|
||||
notify("No option selected.", "")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
selected := options[idx]
|
||||
if idx == 1 {
|
||||
if err := exec.Command(selected.Cmd[0], selected.Cmd[1:]...).Run(); err != nil {
|
||||
notify("An error occurred while taking the screenshot.", "")
|
||||
os.Exit(1)
|
||||
}
|
||||
notify("Screenshot copied to clipboard", "")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if err := exec.Command(selected.Cmd[0], selected.Cmd[1:]...).Run(); err != nil {
|
||||
notify("An error occurred while taking the screenshot.", "")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if idx == 5 {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
notify("Screenshot saved temporarily.\nChoose where to save it permanently", "")
|
||||
zenity := exec.Command("zenity", "--file-selection", "--title=Save Screenshot", "--filename="+defaultFilename, "--save")
|
||||
fileOut, err := zenity.Output()
|
||||
if err != nil {
|
||||
os.Remove(tmpScreenshot)
|
||||
notify("Screenshot discarded", "")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
dest := strings.TrimSpace(string(fileOut))
|
||||
if err := os.Rename(tmpScreenshot, dest); err != nil {
|
||||
notify(fmt.Sprintf("Failed to save screenshot to %s", dest), "")
|
||||
} else {
|
||||
notify(fmt.Sprintf("Screenshot saved to %s", dest), "")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user