110 lines
2.8 KiB
Go
110 lines
2.8 KiB
Go
package app
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
)
|
|
|
|
func portableFFmpeg(configured string) string {
|
|
if candidates := ffmpegCandidates(configured, ffmpegManagedDirectory()); len(candidates) > 0 {
|
|
return candidates[0]
|
|
}
|
|
if automaticFFmpeg(configured) {
|
|
return ffmpegExecutableName()
|
|
}
|
|
return normalizedFFmpegSetting(configured)
|
|
}
|
|
|
|
func normalizedOutputDirectory(raw string) (string, error) {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
return "", errors.New("下载目录不能为空")
|
|
}
|
|
if strings.ContainsAny(raw, "\x00\r\n") {
|
|
return "", errors.New("下载目录包含无效字符")
|
|
}
|
|
if strings.Contains(raw, "://") {
|
|
return "", errors.New("下载目录必须是本机文件夹路径,不是网址")
|
|
}
|
|
if runtime.GOOS != "windows" && (strings.HasPrefix(raw, `\\`) || len(raw) > 1 && raw[1] == ':') {
|
|
return "", errors.New("当前系统不支持 Windows 盘符或 UNC 路径")
|
|
}
|
|
return filepath.Clean(raw), nil
|
|
}
|
|
|
|
func checkOutputDirectory(directory string) error {
|
|
if err := os.MkdirAll(directory, 0o755); err != nil {
|
|
return fmt.Errorf("无法创建下载目录: %w", err)
|
|
}
|
|
file, err := os.CreateTemp(directory, ".juku-write-check-*")
|
|
if err != nil {
|
|
return fmt.Errorf("下载目录不可写: %w", err)
|
|
}
|
|
name := file.Name()
|
|
closeErr := file.Close()
|
|
removeErr := os.Remove(name)
|
|
if closeErr != nil {
|
|
return closeErr
|
|
}
|
|
return removeErr
|
|
}
|
|
|
|
func sameDirectory(first, second string) bool {
|
|
firstAbsolute, firstErr := filepath.Abs(first)
|
|
secondAbsolute, secondErr := filepath.Abs(second)
|
|
if firstErr != nil || secondErr != nil {
|
|
return first == second
|
|
}
|
|
if runtime.GOOS == "windows" {
|
|
return strings.EqualFold(firstAbsolute, secondAbsolute)
|
|
}
|
|
return firstAbsolute == secondAbsolute
|
|
}
|
|
|
|
func (cfg Config) runtimeSettingsDirectory() string {
|
|
return cfg.dataDirectory()
|
|
}
|
|
|
|
func (cfg Config) dataDirectory() string {
|
|
return firstNonEmpty(cfg.dataDir, "data")
|
|
}
|
|
|
|
func flagWasSet(name string) bool {
|
|
found := false
|
|
flag.Visit(func(option *flag.Flag) {
|
|
if option.Name == name {
|
|
found = true
|
|
}
|
|
})
|
|
return found
|
|
}
|
|
|
|
func isProjectDirectory(directory string) bool {
|
|
body, err := os.ReadFile(filepath.Join(directory, "go.mod"))
|
|
fields := strings.Fields(string(body))
|
|
return err == nil && len(fields) >= 2 && fields[0] == "module" && fields[1] == "juku"
|
|
}
|
|
|
|
func preparePortableWorkingDirectory() error {
|
|
if isProjectDirectory(".") {
|
|
return nil
|
|
}
|
|
executable, err := os.Executable()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
directory := filepath.Dir(executable)
|
|
if filepath.Base(directory) == "dist" && isProjectDirectory(filepath.Dir(directory)) {
|
|
directory = filepath.Dir(directory)
|
|
}
|
|
if strings.HasPrefix(filepath.Base(filepath.Dir(directory)), "go-build") || strings.HasPrefix(filepath.Base(directory), "go-build") {
|
|
return nil
|
|
}
|
|
return os.Chdir(directory)
|
|
}
|