Skip to content

Commit 023a67e

Browse files
committed
updated to 3.1.3
1 parent 2627f8e commit 023a67e

File tree

28 files changed

+1889
-613
lines changed

28 files changed

+1889
-613
lines changed

core/app.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,15 @@ var (
3838
systemOnce *SystemSetup
3939
proxyOnce *Proxy
4040
httpServerOnce *HttpServer
41+
ruleOnce *RuleSet
4142
)
4243

4344
func GetApp(assets embed.FS) *App {
4445
if appOnce == nil {
4546
appOnce = &App{
4647
assets: assets,
4748
AppName: "resd-mini",
48-
Version: "1.0.4",
49+
Version: "3.1.3",
4950
Description: "resd-mini是一款集网络资源嗅探 + 高速下载功能于一体的软件,高颜值、高性能和多样化,提供个人用户下载自己上传到各大平台的网络资源功能!",
5051
Copyright: "Copyright © 2023~" + strconv.Itoa(time.Now().Year()),
5152
Platform: sysRuntime.GOOS,
@@ -115,6 +116,7 @@ ILKEQKmPPzKs7kp/7Nz+2cT3
115116
initResource()
116117
initHttpServer()
117118
initSystem()
119+
initRule()
118120
}
119121
return appOnce
120122
}

core/config.go

Lines changed: 173 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package core
22

33
import (
44
"encoding/json"
5+
"os"
6+
"os/user"
7+
"path/filepath"
58
"runtime"
6-
"strconv"
79
"strings"
810
"sync"
911
)
@@ -30,128 +32,184 @@ type Config struct {
3032
AutoProxy bool `json:"AutoProxy"`
3133
WxAction bool `json:"WxAction"`
3234
TaskNumber int `json:"TaskNumber"`
35+
DownNumber int `json:"DownNumber"`
3336
UserAgent string `json:"UserAgent"`
3437
UseHeaders string `json:"UseHeaders"`
38+
InsertTail bool `json:"InsertTail"`
3539
MimeMap map[string]MimeInfo `json:"MimeMap"`
40+
Rule string `json:"Rule"`
3641
}
3742

3843
var (
3944
mimeMux sync.RWMutex
4045
)
4146

4247
func initConfig() *Config {
43-
if globalConfig == nil {
44-
def := `
45-
{
46-
"Host": "127.0.0.1",
47-
"Port": "8899",
48-
"Theme": "lightTheme",
49-
"Locale": "zh",
50-
"Quality": 0,
51-
"SaveDirectory": "",
52-
"FilenameLen": 0,
53-
"FilenameTime": true,
54-
"UpstreamProxy": "",
55-
"OpenProxy": false,
56-
"DownloadProxy": false,
57-
"AutoProxy": false,
58-
"WxAction": true,
59-
"TaskNumber": __TaskNumber__,
60-
"UserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
61-
"UseHeaders": "User-Agent,Referer,Authorization,Cookie",
62-
"MimeMap": {
63-
"image/png": { "Type": "image", "Suffix": ".png" },
64-
"image/webp": { "Type": "image", "Suffix": ".webp" },
65-
"image/jpeg": { "Type": "image", "Suffix": ".jpeg" },
66-
"image/jpg": { "Type": "image", "Suffix": ".jpg" },
67-
"image/gif": { "Type": "image", "Suffix": ".gif" },
68-
"image/avif": { "Type": "image", "Suffix": ".avif" },
69-
"image/bmp": { "Type": "image", "Suffix": ".bmp" },
70-
"image/tiff": { "Type": "image", "Suffix": ".tiff" },
71-
"image/heic": { "Type": "image", "Suffix": ".heic" },
72-
"image/x-icon": { "Type": "image", "Suffix": ".ico" },
73-
"image/svg+xml": { "Type": "image", "Suffix": ".svg" },
74-
"image/vnd.adobe.photoshop": { "Type": "image", "Suffix": ".psd" },
75-
"image/jp2": { "Type": "image", "Suffix": ".jp2" },
76-
"image/jpeg2000": { "Type": "image", "Suffix": ".jp2" },
77-
"image/apng": { "Type": "image", "Suffix": ".apng" },
78-
"audio/mpeg": { "Type": "audio", "Suffix": ".mp3" },
79-
"audio/mp3": { "Type": "audio", "Suffix": ".mp3" },
80-
"audio/wav": { "Type": "audio", "Suffix": ".wav" },
81-
"audio/aiff": { "Type": "audio", "Suffix": ".aiff" },
82-
"audio/x-aiff": { "Type": "audio", "Suffix": ".aiff" },
83-
"audio/aac": { "Type": "audio", "Suffix": ".aac" },
84-
"audio/ogg": { "Type": "audio", "Suffix": ".ogg" },
85-
"audio/flac": { "Type": "audio", "Suffix": ".flac" },
86-
"audio/midi": { "Type": "audio", "Suffix": ".mid" },
87-
"audio/x-midi": { "Type": "audio", "Suffix": ".mid" },
88-
"audio/x-ms-wma": { "Type": "audio", "Suffix": ".wma" },
89-
"audio/opus": { "Type": "audio", "Suffix": ".opus" },
90-
"audio/webm": { "Type": "audio", "Suffix": ".webm" },
91-
"audio/mp4": { "Type": "audio", "Suffix": ".m4a" },
92-
"audio/amr": { "Type": "audio", "Suffix": ".amr" },
93-
"video/mp4": { "Type": "video", "Suffix": ".mp4" },
94-
"video/webm": { "Type": "video", "Suffix": ".webm" },
95-
"video/ogg": { "Type": "video", "Suffix": ".ogv" },
96-
"video/x-msvideo": { "Type": "video", "Suffix": ".avi" },
97-
"video/mpeg": { "Type": "video", "Suffix": ".mpeg" },
98-
"video/quicktime": { "Type": "video", "Suffix": ".mov" },
99-
"video/x-ms-wmv": { "Type": "video", "Suffix": ".wmv" },
100-
"video/3gpp": { "Type": "video", "Suffix": ".3gp" },
101-
"video/x-matroska": { "Type": "video", "Suffix": ".mkv" },
102-
"audio/video": { "Type": "live", "Suffix": ".flv" },
103-
"video/x-flv": { "Type": "live", "Suffix": ".flv" },
104-
"application/dash+xml": { "Type": "live", "Suffix": ".mpd" },
105-
"application/vnd.apple.mpegurl": { "Type": "m3u8", "Suffix": ".m3u8" },
106-
"application/x-mpegurl": { "Type": "m3u8", "Suffix": ".m3u8" },
107-
"application/x-mpeg": { "Type": "m3u8", "Suffix": ".m3u8" },
108-
"application/pdf": { "Type": "pdf", "Suffix": ".pdf" },
109-
"application/vnd.ms-powerpoint": { "Type": "ppt", "Suffix": ".ppt" },
110-
"application/vnd.openxmlformats-officedocument.presentationml.presentation": { "Type": "ppt", "Suffix": ".pptx" },
111-
"application/vnd.ms-excel": { "Type": "xls", "Suffix": ".xls" },
112-
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": { "Type": "xls", "Suffix": ".xlsx" },
113-
"text/csv": { "Type": "xls", "Suffix": ".csv" },
114-
"application/msword": { "Type": "doc", "Suffix": ".doc" },
115-
"application/rtf": { "Type": "doc", "Suffix": ".rtf" },
116-
"text/rtf": { "Type": "doc", "Suffix": ".rtf" },
117-
"application/vnd.oasis.opendocument.text": { "Type": "doc", "Suffix": ".odt" },
118-
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": { "Type": "doc", "Suffix": ".docx" },
119-
"font/woff": { "Type": "font", "Suffix": ".woff" }
48+
if globalConfig != nil {
49+
return globalConfig
50+
}
51+
52+
defaultConfig := &Config{
53+
Theme: "lightTheme",
54+
Locale: "zh",
55+
Host: "127.0.0.1",
56+
Port: "8899",
57+
Quality: 0,
58+
SaveDirectory: getDefaultDownloadDir(),
59+
FilenameLen: 0,
60+
FilenameTime: true,
61+
UpstreamProxy: "",
62+
OpenProxy: false,
63+
DownloadProxy: false,
64+
AutoProxy: false,
65+
WxAction: true,
66+
TaskNumber: runtime.NumCPU() * 2,
67+
DownNumber: 3,
68+
UserAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
69+
UseHeaders: "default",
70+
InsertTail: true,
71+
MimeMap: getDefaultMimeMap(),
72+
Rule: "*",
12073
}
121-
}
122-
`
123-
def = strings.ReplaceAll(def, "__TaskNumber__", strconv.Itoa(runtime.NumCPU()*2))
124-
globalConfig = &Config{
125-
storage: NewStorage("config.json", []byte(def)),
126-
}
12774

128-
defaultMap := make(map[string]interface{})
129-
_ = json.Unmarshal([]byte(def), &defaultMap)
75+
rawDefaults, err := json.Marshal(defaultConfig)
76+
if err != nil {
77+
return globalConfig
78+
}
79+
80+
storage := NewStorage("config.json", rawDefaults)
81+
defaultConfig.storage = storage
82+
globalConfig = defaultConfig
13083

131-
data, err := globalConfig.storage.Load()
132-
if err == nil {
133-
var loadedMap map[string]interface{}
134-
_ = json.Unmarshal(data, &loadedMap)
84+
data, err := storage.Load()
85+
if err != nil {
86+
globalLogger.Esg(err, "load config failed, using defaults")
87+
return globalConfig
88+
}
13589

136-
for key, val := range defaultMap {
137-
if _, ok := loadedMap[key]; !ok {
138-
loadedMap[key] = val
139-
}
140-
}
90+
var cacheMap map[string]interface{}
91+
if err := json.Unmarshal(data, &cacheMap); err != nil {
92+
globalLogger.Esg(err, "parse cached config failed, using defaults")
93+
return globalConfig
94+
}
14195

142-
finalBytes, _ := json.Marshal(loadedMap)
143-
_ = json.Unmarshal(finalBytes, &globalConfig)
96+
var defaultMap map[string]interface{}
97+
defaultBytes, _ := json.Marshal(defaultConfig)
98+
_ = json.Unmarshal(defaultBytes, &defaultMap)
14499

145-
} else {
146-
globalLogger.Esg(err, "load config err")
100+
for k, v := range cacheMap {
101+
if _, ok := defaultMap[k]; ok {
102+
defaultMap[k] = v
147103
}
148104
}
105+
106+
finalBytes, err := json.Marshal(defaultMap)
107+
if err != nil {
108+
globalLogger.Esg(err, "marshal merged config failed")
109+
return globalConfig
110+
}
111+
112+
if err := json.Unmarshal(finalBytes, globalConfig); err != nil {
113+
globalLogger.Esg(err, "unmarshal merged config to struct failed")
114+
}
115+
149116
return globalConfig
150117
}
151118

119+
func getDefaultMimeMap() map[string]MimeInfo {
120+
return map[string]MimeInfo{
121+
"image/png": {Type: "image", Suffix: ".png"},
122+
"image/webp": {Type: "image", Suffix: ".webp"},
123+
"image/jpeg": {Type: "image", Suffix: ".jpeg"},
124+
"image/jpg": {Type: "image", Suffix: ".jpg"},
125+
"image/gif": {Type: "image", Suffix: ".gif"},
126+
"image/avif": {Type: "image", Suffix: ".avif"},
127+
"image/bmp": {Type: "image", Suffix: ".bmp"},
128+
"image/tiff": {Type: "image", Suffix: ".tiff"},
129+
"image/heic": {Type: "image", Suffix: ".heic"},
130+
"image/x-icon": {Type: "image", Suffix: ".ico"},
131+
"image/svg+xml": {Type: "image", Suffix: ".svg"},
132+
"image/vnd.adobe.photoshop": {Type: "image", Suffix: ".psd"},
133+
"image/jp2": {Type: "image", Suffix: ".jp2"},
134+
"image/jpeg2000": {Type: "image", Suffix: ".jp2"},
135+
"image/apng": {Type: "image", Suffix: ".apng"},
136+
"audio/mpeg": {Type: "audio", Suffix: ".mp3"},
137+
"audio/mp3": {Type: "audio", Suffix: ".mp3"},
138+
"audio/wav": {Type: "audio", Suffix: ".wav"},
139+
"audio/aiff": {Type: "audio", Suffix: ".aiff"},
140+
"audio/x-aiff": {Type: "audio", Suffix: ".aiff"},
141+
"audio/aac": {Type: "audio", Suffix: ".aac"},
142+
"audio/ogg": {Type: "audio", Suffix: ".ogg"},
143+
"audio/flac": {Type: "audio", Suffix: ".flac"},
144+
"audio/midi": {Type: "audio", Suffix: ".mid"},
145+
"audio/x-midi": {Type: "audio", Suffix: ".mid"},
146+
"audio/x-ms-wma": {Type: "audio", Suffix: ".wma"},
147+
"audio/opus": {Type: "audio", Suffix: ".opus"},
148+
"audio/webm": {Type: "audio", Suffix: ".webm"},
149+
"audio/mp4": {Type: "audio", Suffix: ".m4a"},
150+
"audio/amr": {Type: "audio", Suffix: ".amr"},
151+
"video/mp4": {Type: "video", Suffix: ".mp4"},
152+
"video/webm": {Type: "video", Suffix: ".webm"},
153+
"video/ogg": {Type: "video", Suffix: ".ogv"},
154+
"video/x-msvideo": {Type: "video", Suffix: ".avi"},
155+
"video/mpeg": {Type: "video", Suffix: ".mpeg"},
156+
"video/quicktime": {Type: "video", Suffix: ".mov"},
157+
"video/x-ms-wmv": {Type: "video", Suffix: ".wmv"},
158+
"video/3gpp": {Type: "video", Suffix: ".3gp"},
159+
"video/x-matroska": {Type: "video", Suffix: ".mkv"},
160+
"audio/video": {Type: "live", Suffix: ".flv"},
161+
"video/x-flv": {Type: "live", Suffix: ".flv"},
162+
"application/dash+xml": {Type: "live", Suffix: ".mpd"},
163+
"application/vnd.apple.mpegurl": {Type: "m3u8", Suffix: ".m3u8"},
164+
"application/x-mpegurl": {Type: "m3u8", Suffix: ".m3u8"},
165+
"application/x-mpeg": {Type: "m3u8", Suffix: ".m3u8"},
166+
"audio/x-mpegurl": {Type: "m3u8", Suffix: ".m3u8"},
167+
"application/pdf": {Type: "pdf", Suffix: ".pdf"},
168+
"application/vnd.ms-powerpoint": {Type: "ppt", Suffix: ".ppt"},
169+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": {Type: "ppt", Suffix: ".pptx"},
170+
"application/vnd.ms-excel": {Type: "xls", Suffix: ".xls"},
171+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {Type: "xls", Suffix: ".xlsx"},
172+
"text/csv": {Type: "xls", Suffix: ".csv"},
173+
"application/msword": {Type: "doc", Suffix: ".doc"},
174+
"application/rtf": {Type: "doc", Suffix: ".rtf"},
175+
"text/rtf": {Type: "doc", Suffix: ".rtf"},
176+
"application/vnd.oasis.opendocument.text": {Type: "doc", Suffix: ".odt"},
177+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": {Type: "doc", Suffix: ".docx"},
178+
"font/woff": {Type: "font", Suffix: ".woff"},
179+
"application/octet-stream": {Type: "stream", Suffix: "default"},
180+
}
181+
}
182+
183+
func getDefaultDownloadDir() string {
184+
usr, err := user.Current()
185+
if err != nil {
186+
return ""
187+
}
188+
189+
homeDir := usr.HomeDir
190+
var downloadDir string
191+
192+
switch runtime.GOOS {
193+
case "windows", "darwin":
194+
downloadDir = filepath.Join(homeDir, "Downloads")
195+
case "linux":
196+
downloadDir = filepath.Join(homeDir, "Downloads")
197+
if xdgDir := os.Getenv("XDG_DOWNLOAD_DIR"); xdgDir != "" {
198+
downloadDir = xdgDir
199+
}
200+
}
201+
202+
if stat, err := os.Stat(downloadDir); err == nil && stat.IsDir() {
203+
return downloadDir
204+
}
205+
206+
return ""
207+
}
208+
152209
func (c *Config) setConfig(config Config) {
153210
oldProxy := c.UpstreamProxy
154211
openProxy := c.OpenProxy
212+
oldRule := c.Rule
155213
c.Host = config.Host
156214
c.Port = config.Port
157215
c.Theme = config.Theme
@@ -166,12 +224,22 @@ func (c *Config) setConfig(config Config) {
166224
c.DownloadProxy = config.DownloadProxy
167225
c.AutoProxy = config.AutoProxy
168226
c.TaskNumber = config.TaskNumber
227+
c.DownNumber = config.DownNumber
169228
c.WxAction = config.WxAction
170229
c.UseHeaders = config.UseHeaders
230+
c.InsertTail = config.InsertTail
231+
c.Rule = config.Rule
171232
if oldProxy != c.UpstreamProxy || openProxy != c.OpenProxy {
172233
proxyOnce.setTransport()
173234
}
174235

236+
if oldRule != c.Rule {
237+
err := ruleOnce.Load(c.Rule)
238+
if err != nil {
239+
globalLogger.Esg(err, "set rule failed")
240+
}
241+
}
242+
175243
mimeMux.Lock()
176244
c.MimeMap = config.MimeMap
177245
mimeMux.Unlock()
@@ -212,14 +280,20 @@ func (c *Config) getConfig(key string) interface{} {
212280
return c.AutoProxy
213281
case "TaskNumber":
214282
return c.TaskNumber
283+
case "DownNumber":
284+
return c.DownNumber
215285
case "WxAction":
216286
return c.WxAction
217287
case "UseHeaders":
218288
return c.UseHeaders
289+
case "InsertTail":
290+
return c.InsertTail
219291
case "MimeMap":
220292
mimeMux.RLock()
221293
defer mimeMux.RUnlock()
222294
return c.MimeMap
295+
case "Rule":
296+
return c.Rule
223297
default:
224298
return nil
225299
}

0 commit comments

Comments
 (0)