-
Notifications
You must be signed in to change notification settings - Fork 17
/
main.go
182 lines (163 loc) · 4.26 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
package main
import (
"errors"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"github.com/urfave/cli"
"github.com/xyproto/wallutils"
)
// exists checks if the given path exists
func exists(path string) bool {
_, err := os.Stat(path)
return err == nil
}
// download can download a file to the given filename.
// Set redownload to true for downloading again even if it exists.
func download(url, filename string, verbose, redownload bool) error {
// Check if the file exists (and that force is not enabled)
if exists(filename) && !redownload {
// The file already exists. This is fine, skip the download
return nil
}
// Prepare the client
var client http.Client
resp, err := client.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
if verbose {
if verbose {
fmt.Println("Downloading " + url)
}
}
// Download the file
b, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
// Write the file
return os.WriteFile(filename, b, 0o644)
}
func setWallpaperAction(c *cli.Context) error {
if c.NArg() == 0 {
return errors.New("please specify an image filename or URL")
}
imageFilename := c.Args().Get(0)
// Retrieve flags from the context
verbose := c.IsSet("verbose")
mode := c.String("mode")
downloadDir := c.String("download")
if !exists(downloadDir) {
// Last resort
downloadDir = "/tmp"
}
if !exists(downloadDir) {
return errors.New("could not find: " + downloadDir)
}
// Check if the argument is an URL that uses the http or https protocol
if strings.HasPrefix(imageFilename, "http://") || strings.HasPrefix(imageFilename, "https://") {
u, err := url.Parse(imageFilename)
if err == nil { // no error
downloadFilename := filepath.Join(downloadDir, filepath.Base(imageFilename))
if err := download(u.String(), downloadFilename, verbose, false); err != nil {
return err
}
// Use the downloaded image
imageFilename = downloadFilename
}
}
// Find the absolute path
absImageFilename, err := filepath.Abs(imageFilename)
if err == nil {
imageFilename = absImageFilename
}
// Set the desktop wallpaper
if err := wallutils.SetWallpaperCustom(imageFilename, mode, verbose); err != nil {
return fmt.Errorf("could not set wallpaper: %s", err)
}
return nil
}
func expanduser(path string) string {
if strings.HasPrefix(path, "~") {
path = strings.Replace(path, "~", os.Getenv("HOME"), 1)
} else if strings.HasPrefix(path, "$HOME") {
path = strings.Replace(path, "$HOME", os.Getenv("HOME"), 1)
}
return path
}
func downloadDirectory() string {
// Check if $XDG_DOWNLOAD_DIR is set
path := os.Getenv("XDG_DOWNLOAD_DIR")
if exists(path) {
return path
}
// Check if XDG_DOWNLOAD_DIR is defined in ~/.config/user-dirs.dirs
dirfileContents, err := os.ReadFile(expanduser("~/.config/user-dirs.dirs"))
if err == nil {
for _, line := range strings.Split(string(dirfileContents), "\n") {
if strings.HasPrefix(line, "XDG_DOWNLOAD_DIR") {
elements := strings.SplitN(line, "=", 2)
path = strings.TrimSpace(elements[1])
if exists(path) {
return path
}
break
}
}
}
// Check if ~/downloads exists
path = expanduser("~/downloads")
if exists(path) {
return path
}
// Check if ~/download exists
path = expanduser("~/download")
if exists(path) {
return path
}
// Use the home directory, if it exists
path = expanduser("~")
if exists(path) {
return path
}
// Using /tmp is the last resort
return "/tmp"
}
func main() {
app := cli.NewApp()
app.Name = "setwallpaper"
app.Usage = "set the desktop wallpaper"
app.UsageText = "setwallpaper [options] [path or URL to JPEG or PNG image]"
app.Version = wallutils.VersionString
app.HideHelp = true
cli.VersionFlag = cli.BoolFlag{
Name: "version, V",
Usage: "output version information",
}
app.Flags = []cli.Flag{
cli.BoolFlag{
Name: "verbose, v",
Usage: "verbose output",
},
cli.StringFlag{
Name: "mode, m",
Value: "stretch", // the default value
Usage: "wallpaper mode (stretch | center | tile | scale) \n\t+ modes specific to the currently running DE/WM",
},
cli.StringFlag{
Name: "download, d",
Value: downloadDirectory(), // the default value
Usage: "download directory",
},
}
app.Action = setWallpaperAction
if err := app.Run(os.Args); err != nil {
wallutils.Quit(err)
}
}