krz/skunky-art
Alternative privacy frontend for DeviantArt.
clone: git clone https://gitbay.org/krz/skunky-art.git
1package app
2
3import (
4 "encoding/json"
5 "os"
6 "regexp"
7 "skunkyart/static"
8 "strconv"
9 "time"
10
11 "github.com/zerolabsco/devianter"
12)
13
14// Release carries the build's version and description, set at link time and
15// shown by --help and the API.
16var Release struct {
17 Version string
18 Description string
19}
20
21type cacheConfig struct {
22 Enabled bool `json:"enabled"`
23 MemCache bool `json:"memcache"`
24 Path string `json:"path"`
25 MaxSize int64 `json:"max-size"`
26 Lifetime string `json:"lifetime"`
27 UpdateInterval int64 `json:"update-interval"`
28}
29
30type config struct {
31 cfg string
32 Listen string `json:"listen"`
33 URI string `json:"uri"`
34 Cache cacheConfig `json:"cache"`
35 Proxy bool `json:"proxy"`
36 Nsfw bool `json:"nsfw"`
37 UserAgent string `json:"user-agent"`
38 DownloadProxy string `json:"download-proxy"`
39 StaticPath string `json:"static-path"`
40}
41
42// CFG is the running instance's configuration, holding the defaults below until
43// ExecuteConfig overwrites them from the config file.
44var CFG = config{
45 cfg: "config.json",
46 Listen: "127.0.0.1:3003",
47 URI: "/",
48 Cache: cacheConfig{
49 Enabled: false,
50 Path: "cache",
51 UpdateInterval: 1,
52 },
53 StaticPath: "static",
54 UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
55 Proxy: true,
56 Nsfw: true,
57}
58
59var lifetimeParsed int64
60
61// ExecuteConfig loads the config file into CFG, validates it, and starts the
62// cache rotation loop if caching is on. It exits the process on a config that
63// cannot be read or that asks for caching without proxying.
64func ExecuteConfig() {
65 if CFG.cfg != "" {
66 f, err := os.ReadFile(CFG.cfg)
67 tryWithExitStatus(err, 1)
68 tryWithExitStatus(json.Unmarshal(f, &CFG), 1)
69 if CFG.Cache.Enabled && !CFG.Proxy {
70 exit("Incompatible settings detected: cannot use caching media content without proxy", 1)
71 }
72
73 if CFG.Cache.Enabled {
74 if CFG.Cache.Lifetime != "" {
75 var duration int64
76 day := 24 * time.Hour.Milliseconds()
77 numstr := regexp.MustCompile("[0-9]+").FindAllString(CFG.Cache.Lifetime, -1)
78 num, _ := strconv.Atoi(numstr[len(numstr)-1])
79
80 switch unit := CFG.Cache.Lifetime[len(CFG.Cache.Lifetime)-1:]; unit {
81 case "i":
82 duration = time.Minute.Milliseconds()
83 case "h":
84 duration = time.Hour.Milliseconds()
85 case "d":
86 duration = day
87 case "w":
88 duration = day * 7
89 case "m":
90 duration = day * 30
91 case "y":
92 duration = day * 360
93 default:
94 exit("Invalid unit specified: "+unit, 1)
95 }
96
97 lifetimeParsed = duration * int64(num)
98 }
99 // max-size is documented in megabytes. This was 1024^2, which in Go is
100 // XOR (1026), not exponentiation — so the cap was ~1000x too small.
101 CFG.Cache.MaxSize *= 1024 * 1024
102 go InitCacheSystem()
103 }
104
105 About = instanceAbout{
106 Proxy: CFG.Proxy,
107 Nsfw: CFG.Nsfw,
108 }
109
110 static.StaticPath = CFG.StaticPath
111 devianter.UserAgent = CFG.UserAgent
112 }
113}