From 04d3d611b0d69071e58772084f19b691f078c47d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 18 Apr 2024 01:52:23 +0900 Subject: [PATCH] init --- .github/workflows/release.yml | 25 +++++ .gitignore | 6 ++ .goreleaser.yml | 89 ++++++++++++++++++ assets/all.yaml | 7 ++ assets/hubert.yaml | 5 + assets/rmvpe.yaml | 6 ++ assets/uvr5.yaml | 15 +++ assets/v1.yaml | 18 ++++ assets/v2.yaml | 18 ++++ cfg.go | 143 +++++++++++++++++++++++++++++ cmd.go | 49 ++++++++++ console/console_ansi.go | 14 +++ console/console_windows.go | 144 +++++++++++++++++++++++++++++ dns.go | 163 +++++++++++++++++++++++++++++++++ go.mod | 19 ++++ go.sum | 31 +++++++ http.go | 87 ++++++++++++++++++ ipv6.go | 26 ++++++ main.go | 72 +++++++++++++++ packs/amd/latest.yaml | 3 + packs/amd/v2/20230813.yaml | 7 ++ packs/amd/v2/20231006.yaml | 7 ++ packs/general/latest.yaml | 7 ++ packs/general/v1/20230331.yaml | 7 ++ packs/general/v1/20230416.yaml | 7 ++ packs/general/v1/20230428.yaml | 7 ++ packs/general/v1/20230508.yaml | 7 ++ packs/general/v1/20230513.yaml | 7 ++ packs/general/v1/20230516.yaml | 7 ++ packs/general/v1/20230717.yaml | 7 ++ packs/general/v2/20230528.yaml | 7 ++ packs/general/v2/20230618.yaml | 7 ++ packs/intel/latest.yaml | 3 + packs/intel/v2/20230813.yaml | 7 ++ packs/intel/v2/20231006.yaml | 7 ++ packs/nvidia/latest.yaml | 3 + packs/nvidia/v2/20230813.yaml | 7 ++ packs/nvidia/v2/20231006.yaml | 7 ++ pckcfg.sh | 7 ++ tools/ffmpeg.yaml | 8 ++ 40 files changed, 1073 insertions(+) create mode 100644 .github/workflows/release.yml create mode 100644 .goreleaser.yml create mode 100644 assets/all.yaml create mode 100644 assets/hubert.yaml create mode 100644 assets/rmvpe.yaml create mode 100644 assets/uvr5.yaml create mode 100644 assets/v1.yaml create mode 100644 assets/v2.yaml create mode 100644 cfg.go create mode 100644 cmd.go create mode 100644 console/console_ansi.go create mode 100644 console/console_windows.go create mode 100644 dns.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 http.go create mode 100644 ipv6.go create mode 100644 main.go create mode 100644 packs/amd/latest.yaml create mode 100644 packs/amd/v2/20230813.yaml create mode 100644 packs/amd/v2/20231006.yaml create mode 100644 packs/general/latest.yaml create mode 100644 packs/general/v1/20230331.yaml create mode 100644 packs/general/v1/20230416.yaml create mode 100644 packs/general/v1/20230428.yaml create mode 100644 packs/general/v1/20230508.yaml create mode 100644 packs/general/v1/20230513.yaml create mode 100644 packs/general/v1/20230516.yaml create mode 100644 packs/general/v1/20230717.yaml create mode 100644 packs/general/v2/20230528.yaml create mode 100644 packs/general/v2/20230618.yaml create mode 100644 packs/intel/latest.yaml create mode 100644 packs/intel/v2/20230813.yaml create mode 100644 packs/intel/v2/20231006.yaml create mode 100644 packs/nvidia/latest.yaml create mode 100644 packs/nvidia/v2/20230813.yaml create mode 100644 packs/nvidia/v2/20231006.yaml create mode 100755 pckcfg.sh create mode 100644 tools/ffmpeg.yaml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..4406a6b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,25 @@ +name: 发行版 +on: + push: + tags: + - 'v*' + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@master + with: + fetch-depth: 0 + + - name: Set up Go + uses: actions/setup-go@master + + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@master + with: + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 3b735ec..b6a8c16 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,9 @@ # Go workspace file go.work + +# Packed configs +*.zip + +# MacOS system file +.DS_Store diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..6a4e5f7 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,89 @@ +project_name: rvcmd +env: + - GO111MODULE=on +before: + hooks: + - go mod tidy + - go generate +builds: + - id: linux + env: + - CGO_ENABLED=0 + - GO111MODULE=on + goos: + - linux + goarch: + - 386 + - amd64 + - arm + - arm64 + goarm: + - 6 + - 7 + mod_timestamp: "{{ .CommitTimestamp }}" + flags: + - -trimpath + ldflags: + - -s -w + - id: macos + env: + - CGO_ENABLED=0 + - GO111MODULE=on + goos: + - darwin + goarch: + - amd64 + - arm64 + mod_timestamp: "{{ .CommitTimestamp }}" + flags: + - -trimpath + ldflags: + - -s -w + - id: windows + env: + - CGO_ENABLED=0 + - GO111MODULE=on + goos: + - windows + goarch: + - 386 + - amd64 + mod_timestamp: "{{ .CommitTimestamp }}" + flags: + - -trimpath + ldflags: + - -s -w + +checksum: + name_template: "rvcmd_checksums.txt" +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" + - fix typo + - Merge pull request + - Merge branch + - Merge remote-tracking + - go mod tidy + +archives: + - id: all + builds: + - linux + - macos + - windows + name_template: "rvcmd_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" + format_overrides: + - goos: windows + format: zip + +nfpms: + - license: AGPL 3.0 + homepage: https://github.com/RVC-Project/RVC-Models-Downloader + file_name_template: "rvcmd_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" + formats: + - deb + - rpm + maintainer: Fumiama Minamoto diff --git a/assets/all.yaml b/assets/all.yaml new file mode 100644 index 0000000..7a6338d --- /dev/null +++ b/assets/all.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Refer: hubert + - Refer: rmvpe + - Refer: v1 + - Refer: v2 + - Refer: uvr5 diff --git a/assets/hubert.yaml b/assets/hubert.yaml new file mode 100644 index 0000000..43761c5 --- /dev/null +++ b/assets/hubert.yaml @@ -0,0 +1,5 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: assets/hubert + Copy: + - hubert_base.pt diff --git a/assets/rmvpe.yaml b/assets/rmvpe.yaml new file mode 100644 index 0000000..6b62635 --- /dev/null +++ b/assets/rmvpe.yaml @@ -0,0 +1,6 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - rmvpe.pt + - rmvpe.onnx diff --git a/assets/uvr5.yaml b/assets/uvr5.yaml new file mode 100644 index 0000000..0591fc5 --- /dev/null +++ b/assets/uvr5.yaml @@ -0,0 +1,15 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: assets/uvr5_weights + Copy: + - uvr5_weights/HP2-人声vocals+非人声instrumentals.pth + - uvr5_weights/HP2_all_vocals.pth + - uvr5_weights/HP3_all_vocals.pth + - uvr5_weights/HP5-主旋律人声vocals+其他instrumentals.pth + - uvr5_weights/HP5_only_main_vocal.pth + - uvr5_weights/VR-DeEchoAggressive.pth + - uvr5_weights/VR-DeEchoDeReverb.pth + - uvr5_weights/VR-DeEchoNormal.pth + - Folder: assets/uvr5_weights/onnx_dereverb_By_FoxJoy + Copy: + - uvr5_weights/onnx_dereverb_By_FoxJoy/vocals.onnx diff --git a/assets/v1.yaml b/assets/v1.yaml new file mode 100644 index 0000000..cc2e719 --- /dev/null +++ b/assets/v1.yaml @@ -0,0 +1,18 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Refer: hubert + - Folder: assets/pretrained + Copy: + - pretrained/D32k.pth + - pretrained/D40k.pth + - pretrained/D48k.pth + - pretrained/G32k.pth + - pretrained/G40k.pth + - pretrained/G48k.pth + - pretrained/f0D32k.pth + - pretrained/f0D40k.pth + - pretrained/f0D48k.pth + - pretrained/f0G32k.pth + - pretrained/f0G40k.pth + - pretrained/f0G48k.pth + - Refer: uvr5 diff --git a/assets/v2.yaml b/assets/v2.yaml new file mode 100644 index 0000000..a7f5615 --- /dev/null +++ b/assets/v2.yaml @@ -0,0 +1,18 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Refer: hubert + - Folder: assets/pretrained_v2 + Copy: + - pretrained_v2/D32k.pth + - pretrained_v2/D40k.pth + - pretrained_v2/D48k.pth + - pretrained_v2/G32k.pth + - pretrained_v2/G40k.pth + - pretrained_v2/G48k.pth + - pretrained_v2/f0D32k.pth + - pretrained_v2/f0D40k.pth + - pretrained_v2/f0D48k.pth + - pretrained_v2/f0G32k.pth + - pretrained_v2/f0G40k.pth + - pretrained_v2/f0G48k.pth + - Refer: uvr5 diff --git a/cfg.go b/cfg.go new file mode 100644 index 0000000..129dd26 --- /dev/null +++ b/cfg.go @@ -0,0 +1,143 @@ +package main + +import ( + "archive/zip" + "bytes" + _ "embed" + "fmt" + "io" + "net/http" + "os" + "runtime" + "strings" + "sync" + "time" + + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" +) + +//go:embed cfg.zip +var cfgdata []byte + +var cfg = func() *zip.Reader { + r, err := zip.NewReader(bytes.NewReader(cfgdata), int64(len(cfgdata))) + if err != nil { + panic(err) + } + for _, f := range r.File { + cmdlst = append(cmdlst, f.Name) + } + return r +}() + +func readconfig(path string) (c config, err error) { + fname := path + ".yaml" + f, err := cfg.Open(fname) + if err != nil { + err = errors.Wrap(err, "invalid path") + return + } + defer f.Close() + err = yaml.NewDecoder(f).Decode(&c) + if err != nil { + err = errors.Wrap(err, "invalid config") + return + } + return +} + +type config struct { + BaseURL string `yaml:"BaseURL"` + Targets []targets `yaml:"Targets"` +} + +type targets struct { + Refer string `yaml:"Refer"` + Folder string `yaml:"Folder"` + Copy []string `yaml:"Copy"` + OS string `yaml:"OS"` + Arch string `yaml:"Arch"` +} + +func (c *config) download(path string) error { + for i, t := range c.Targets { + if t.Refer != "" { + refp := path[:strings.LastIndex(path, "/")+1] + t.Refer + logrus.Infof("#%d refer to target '%s'", i+1, refp) + refcfg, err := readconfig(refp) + if err != nil { + return err + } + err = refcfg.download(refp) + if err != nil { + return err + } + continue + } + if t.OS != "" && t.OS != runtime.GOOS { + logrus.Warnf("#%d target required OS: %s but you are %s, skip.", i+1, t.OS, runtime.GOOS) + continue + } + if t.Arch != "" && t.Arch != runtime.GOARCH { + logrus.Warnf("#%d target required Arch: %s but you are %s, skip.", i+1, t.Arch, runtime.GOARCH) + continue + } + err := os.MkdirAll(t.Folder, 0755) + if err != nil { + return errors.Wrap(err, fmt.Sprintf("#%d make target folder '%s'", i+1, t.Folder)) + } + logrus.Infof("#%d open target folder '%s'", i+1, t.Folder) + if len(t.Copy) == 0 { + logrus.Warningf("#%d empty copy target", i+1) + continue + } + wg := sync.WaitGroup{} + wg.Add(len(t.Copy)) + logrus.Infof("#%d download copy: %v", i+1, t.Copy) + for i, cp := range t.Copy { + go func(i int, cp string) { + defer wg.Done() + sleep := time.Millisecond * 100 * time.Duration(i) + if sleep > time.Millisecond { + time.Sleep(sleep) + } + req, err := http.NewRequest("GET", c.BaseURL+"/"+cp, nil) + if err != nil { + logrus.Errorln("new request to", cp, "err:", err) + return + } + logrus.Infoln("get:", req.URL) + req.Header.Add("user-agent", ua) + resp, err := cli.Do(req) + if err != nil { + logrus.Errorln("get", req.URL, "err:", err) + return + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + err := errors.New(fmt.Sprintf("HTTP %d %s", resp.StatusCode, resp.Status)) + logrus.Errorln("get", req.URL, "err:", err) + return + } + fname := t.Folder + "/" + cp + f, err := os.Create(fname) + if err != nil { + logrus.Errorln("create file", fname, "err:", err) + return + } + logrus.Infoln("writing file", fname) + defer f.Close() + _, err = io.Copy(f, resp.Body) + if err != nil { + logrus.Errorln("download file", fname, "err:", err) + return + } + logrus.Infoln("downloaded file", fname) + }(i, cp) + } + wg.Wait() + } + return nil +} diff --git a/cmd.go b/cmd.go new file mode 100644 index 0000000..cecf032 --- /dev/null +++ b/cmd.go @@ -0,0 +1,49 @@ +package main + +import ( + "strings" +) + +type commandlist []string + +var cmdlst = make(commandlist, 0, 64) + +func (cl commandlist) String() string { + sb := strings.Builder{} + islastdir := false + isfirstloop := true + sb.WriteString(" ") + for _, cmd := range cmdlst { + if len(cmd) == 0 { + continue + } + trimedcmd := strings.TrimSuffix(cmd, "/") + a := strings.LastIndex(trimedcmd, "/") + 1 + b := len(cmd) - 1 + if a >= b { + continue + } + isdir := cmd[b] == '/' + ident := strings.Count(trimedcmd, "/") + 1 + if !isfirstloop && (islastdir || isdir) { + sb.WriteByte('\n') + if !isdir { + ident-- + } + for i := 0; i < ident; i++ { + sb.WriteString(" ") + } + } + isfirstloop = false + if isdir { + islastdir = true + sb.WriteString(cmd[a:b]) + sb.WriteByte(':') + } else { // is file + islastdir = false + sb.WriteString(" ") + sb.WriteString(strings.TrimSuffix(cmd[a:], ".yaml")) + } + } + return sb.String() +} diff --git a/console/console_ansi.go b/console/console_ansi.go new file mode 100644 index 0000000..3147cd7 --- /dev/null +++ b/console/console_ansi.go @@ -0,0 +1,14 @@ +//go:build !windows + +// Package console sets console's behavior on init +package console + +// https://github.com/FloatTech/ZeroBot-Plugin/blob/master/console/console_ansi.go + +import ( + "fmt" +) + +func init() { + fmt.Print("\033]0;RVC Models Downloader\007") +} diff --git a/console/console_windows.go b/console/console_windows.go new file mode 100644 index 0000000..5ed1b9b --- /dev/null +++ b/console/console_windows.go @@ -0,0 +1,144 @@ +// Package console sets console's behavior on init +package console + +// https://github.com/FloatTech/ZeroBot-Plugin/blob/master/console/console_windows.go + +import ( + "bytes" + "os" + "strings" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" + + "github.com/sirupsen/logrus" +) + +var ( + //go:linkname modkernel32 golang.org/x/sys/windows.modkernel32 + modkernel32 *windows.LazyDLL + procSetConsoleTitle = modkernel32.NewProc("SetConsoleTitleW") +) + +//go:linkname errnoErr golang.org/x/sys/windows.errnoErr +func errnoErr(e syscall.Errno) error + +func setConsoleTitle(title string) (err error) { + var p0 *uint16 + p0, err = syscall.UTF16PtrFromString(title) + if err != nil { + return + } + r1, _, e1 := syscall.Syscall(procSetConsoleTitle.Addr(), 1, uintptr(unsafe.Pointer(p0)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func init() { + stdin := windows.Handle(os.Stdin.Fd()) + + var mode uint32 + err := windows.GetConsoleMode(stdin, &mode) + if err != nil { + panic(err) + } + + mode &^= windows.ENABLE_QUICK_EDIT_MODE // 禁用快速编辑模式 + mode |= windows.ENABLE_EXTENDED_FLAGS // 启用扩展标志 + + mode &^= windows.ENABLE_MOUSE_INPUT // 禁用鼠标输入 + mode |= windows.ENABLE_PROCESSED_INPUT // 启用控制输入 + + mode &^= windows.ENABLE_INSERT_MODE // 禁用插入模式 + mode |= windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT // 启用输入回显&逐行输入 + + mode &^= windows.ENABLE_WINDOW_INPUT // 禁用窗口输入 + mode &^= windows.ENABLE_VIRTUAL_TERMINAL_INPUT // 禁用虚拟终端输入 + + err = windows.SetConsoleMode(stdin, mode) + if err != nil { + panic(err) + } + + stdout := windows.Handle(os.Stdout.Fd()) + err = windows.GetConsoleMode(stdout, &mode) + if err != nil { + panic(err) + } + + mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING // 启用虚拟终端处理 + mode |= windows.ENABLE_PROCESSED_OUTPUT // 启用处理后的输出 + + err = windows.SetConsoleMode(stdout, mode) + // windows 带颜色 log 自定义格式 + logrus.SetFormatter(&logFormat{hasColor: err == nil}) + if err != nil { + logrus.Warnln("VT100设置失败, 将以无色模式输出") + } + + err = setConsoleTitle("RVC Models Downloader") + if err != nil { + panic(err) + } +} + +const ( + colorCodePanic = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String() + colorCodeFatal = "\x1b[1;31m" // color.Style{color.Bold, color.Red}.String() + colorCodeError = "\x1b[31m" // color.Style{color.Red}.String() + colorCodeWarn = "\x1b[33m" // color.Style{color.Yellow}.String() + colorCodeInfo = "\x1b[37m" // color.Style{color.White}.String() + colorCodeDebug = "\x1b[32m" // color.Style{color.Green}.String() + colorCodeTrace = "\x1b[36m" // color.Style{color.Cyan}.String() + colorReset = "\x1b[0m" +) + +// logFormat specialize for zbp +type logFormat struct { + hasColor bool +} + +// Format implements logrus.Formatter +func (f logFormat) Format(entry *logrus.Entry) ([]byte, error) { + buf := new(bytes.Buffer) + + buf.WriteByte('[') + if f.hasColor { + buf.WriteString(getLogLevelColorCode(entry.Level)) + } + buf.WriteString(strings.ToUpper(entry.Level.String())) + if f.hasColor { + buf.WriteString(colorReset) + } + buf.WriteString("] ") + buf.WriteString(entry.Message) + buf.WriteString(" \n") + + return buf.Bytes(), nil +} + +// getLogLevelColorCode 获取日志等级对应色彩code +func getLogLevelColorCode(level logrus.Level) string { + switch level { + case logrus.PanicLevel: + return colorCodePanic + case logrus.FatalLevel: + return colorCodeFatal + case logrus.ErrorLevel: + return colorCodeError + case logrus.WarnLevel: + return colorCodeWarn + case logrus.InfoLevel: + return colorCodeInfo + case logrus.DebugLevel: + return colorCodeDebug + case logrus.TraceLevel: + return colorCodeTrace + + default: + return colorCodeInfo + } +} diff --git a/dns.go b/dns.go new file mode 100644 index 0000000..130474f --- /dev/null +++ b/dns.go @@ -0,0 +1,163 @@ +package main + +// https://github.com/fumiama/comandy + +import ( + "context" + "crypto/tls" + "errors" + "net" + "sync" + "time" + + "github.com/fumiama/terasu" +) + +var ( + errNoDNSAvailable = errors.New("no dns available") +) + +var dnsdialer = net.Dialer{ + Timeout: time.Second * 8, +} + +type dnsstat struct { + A string + E bool +} + +type dnsservers struct { + sync.RWMutex + m map[string][]*dnsstat +} + +// hasrecord no lock, use under lock +func hasrecord(lst []*dnsstat, a string) bool { + for _, addr := range lst { + if addr.A == a { + return true + } + } + return false +} + +func (ds *dnsservers) add(m map[string][]string) { + ds.Lock() + defer ds.Unlock() + addList := map[string][]*dnsstat{} + for host, addrs := range m { + for _, addr := range addrs { + if !hasrecord(ds.m[host], addr) && !hasrecord(addList[host], addr) { + addList[host] = append(addList[host], &dnsstat{addr, true}) + } + } + } + for host, addrs := range addList { + ds.m[host] = append(ds.m[host], addrs...) + } +} + +func (ds *dnsservers) dial(ctx context.Context) (tlsConn *tls.Conn, err error) { + err = errNoDNSAvailable + + ds.RLock() + defer ds.RUnlock() + + if dnsdialer.Timeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, dnsdialer.Timeout) + defer cancel() + } + + if !dnsdialer.Deadline.IsZero() { + var cancel context.CancelFunc + ctx, cancel = context.WithDeadline(ctx, dnsdialer.Deadline) + defer cancel() + } + + var conn net.Conn + for host, addrs := range ds.m { + for _, addr := range addrs { + if !addr.E { + continue + } + conn, err = dnsdialer.DialContext(ctx, "tcp", addr.A) + if err != nil { + addr.E = false // no need to acquire write lock + continue + } + tlsConn = tls.Client(conn, &tls.Config{ServerName: host}) + if usetrs { + err = terasu.Use(tlsConn).HandshakeContext(ctx) + } else { + err = tlsConn.HandshakeContext(ctx) + } + if err == nil { + return + } + _ = tlsConn.Close() + addr.E = false // no need to acquire write lock + } + } + return +} + +var dotv6servers = dnsservers{ + m: map[string][]*dnsstat{ + "dot.sb": { + {"[2a09::]:853", true}, + {"[2a11::]:853", true}, + }, + "dns.google": { + {"[2001:4860:4860::8888]:853", true}, + {"[2001:4860:4860::8844]:853", true}, + }, + "cloudflare-dns.com": { + {"[2606:4700:4700::1111]:853", true}, + {"[2606:4700:4700::1001]:853", true}, + }, + "dns.umbrella.com": { + {"[2620:0:ccc::2]:853", true}, + {"[2620:0:ccd::2]:853", true}, + }, + "dns10.quad9.net": { + {"[2620:fe::10]:853", true}, + {"[2620:fe::fe:10]:853", true}, + }, + }, +} + +var dotv4servers = dnsservers{ + m: map[string][]*dnsstat{ + "dot.sb": { + {"185.222.222.222:853", true}, + {"45.11.45.11:853", true}, + }, + "dns.google": { + {"8.8.8.8:853", true}, + {"8.8.4.4:853", true}, + }, + "cloudflare-dns.com": { + {"1.1.1.1:853", true}, + {"1.0.0.1:853", true}, + }, + "dns.umbrella.com": { + {"208.67.222.222:853", true}, + {"208.67.220.220:853", true}, + }, + "dns10.quad9.net": { + {"9.9.9.10:853", true}, + {"149.112.112.10:853", true}, + }, + }, +} + +var resolver = &net.Resolver{ + PreferGo: true, + Dial: func(ctx context.Context, _, _ string) (net.Conn, error) { + if canUseIPv6.Get() { + return dotv6servers.dial(ctx) + } + return dotv4servers.dial(ctx) + }, +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..bde4dad --- /dev/null +++ b/go.mod @@ -0,0 +1,19 @@ +module rvcmd + +go 1.22.1 + +require ( + github.com/pkg/errors v0.9.1 + github.com/sirupsen/logrus v1.9.3 + gopkg.in/yaml.v3 v3.0.1 +) + +require ( + github.com/FloatTech/ttl v0.0.0-20230307105452-d6f7b2b647d1 + github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e + github.com/fumiama/terasu v0.0.0-20240416061047-62d3c9f6be80 + golang.org/x/net v0.24.0 + golang.org/x/sys v0.19.0 +) + +require golang.org/x/text v0.14.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e363ee3 --- /dev/null +++ b/go.sum @@ -0,0 +1,31 @@ +github.com/FloatTech/ttl v0.0.0-20230307105452-d6f7b2b647d1 h1:g4pTnDJUW4VbJ9NvoRfUvdjDrHz/6QhfN/LoIIpICbo= +github.com/FloatTech/ttl v0.0.0-20230307105452-d6f7b2b647d1/go.mod h1:fHZFWGquNXuHttu9dUYoKuNbm3dzLETnIOnm1muSfDs= +github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e h1:wR3MXQ3VbUlPKOOUwLOYgh/QaJThBTYtsl673O3lqSA= +github.com/RomiChan/syncx v0.0.0-20221202055724-5f842c53020e/go.mod h1:vD7Ra3Q9onRtojoY5sMCLQ7JBgjUsrXDnDKyFxqpf9w= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fumiama/terasu v0.0.0-20240416061047-62d3c9f6be80 h1:O1JJZzcd5ggUw/9X8V9KxBZ9JZGWFmX/r1q2TPg+pZQ= +github.com/fumiama/terasu v0.0.0-20240416061047-62d3c9f6be80/go.mod h1:BFl0X1+rGJf8bLHl/kO+v05ryHrj/R4kyCrK89NvegA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/http.go b/http.go new file mode 100644 index 0000000..8dde730 --- /dev/null +++ b/http.go @@ -0,0 +1,87 @@ +package main + +// https://github.com/fumiama/comandy + +import ( + "context" + "crypto/tls" + "errors" + "net" + "net/http" + "strings" + "time" + + "github.com/FloatTech/ttl" + "github.com/fumiama/terasu" + "golang.org/x/net/http2" +) + +var ( + ErrEmptyHostAddress = errors.New("empty host addr") +) + +var httpdialer = net.Dialer{ + Timeout: time.Minute, +} + +var lookupTable = ttl.NewCache[string, []string](time.Hour) + +var cli = http.Client{ + Transport: &http2.Transport{ + DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) { + if httpdialer.Timeout != 0 { + var cancel context.CancelFunc + ctx, cancel = context.WithTimeout(ctx, httpdialer.Timeout) + defer cancel() + } + + if !httpdialer.Deadline.IsZero() { + var cancel context.CancelFunc + ctx, cancel = context.WithDeadline(ctx, httpdialer.Deadline) + defer cancel() + } + + host, port, err := net.SplitHostPort(addr) + if err != nil { + return nil, err + } + addrs := lookupTable.Get(host) + if len(addrs) == 0 { + addrs, err = resolver.LookupHost(ctx, host) + if err != nil { + addrs, err = net.DefaultResolver.LookupHost(ctx, host) + if err != nil { + return nil, err + } + } + lookupTable.Set(host, addrs) + } + if len(addr) == 0 { + return nil, ErrEmptyHostAddress + } + var tlsConn *tls.Conn + for _, a := range addrs { + if strings.Contains(a, ":") { + a = "[" + a + "]:" + port + } else { + a += ":" + port + } + conn, err := httpdialer.DialContext(ctx, network, a) + if err != nil { + continue + } + tlsConn = tls.Client(conn, cfg) + if usetrs { + err = terasu.Use(tlsConn).HandshakeContext(ctx) + } else { + err = tlsConn.HandshakeContext(ctx) + } + if err == nil { + break + } + _ = tlsConn.Close() + } + return tlsConn, err + }, + }, +} diff --git a/ipv6.go b/ipv6.go new file mode 100644 index 0000000..4fa49c7 --- /dev/null +++ b/ipv6.go @@ -0,0 +1,26 @@ +package main + +// https://github.com/fumiama/comandy + +import ( + "context" + "net/http" + "time" + + "github.com/RomiChan/syncx" +) + +var canUseIPv6 = syncx.Lazy[bool]{Init: func() bool { + ctx, cancel := context.WithTimeout(context.Background(), 4*time.Second) + defer cancel() + req, err := http.NewRequestWithContext(ctx, "GET", "http://v6.ipv6-test.com/json/widgetdata.php?callback=?", nil) + if err != nil { + return false + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return false + } + _ = resp.Body.Close() + return true +}} diff --git a/main.go b/main.go new file mode 100644 index 0000000..10e9d5c --- /dev/null +++ b/main.go @@ -0,0 +1,72 @@ +package main + +import ( + "flag" + "fmt" + "os" + "runtime" + "time" + + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + + _ "rvcmd/console" +) + +//go:generate ./pckcfg.sh assets packs tools + +var usetrs = true + +const ua = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0" + +func main() { + logrus.Infoln("RVC Models Downloader start at", time.Now().Local().Format(time.DateTime+" (MST)")) + logrus.Infof("operating system: %s, architecture: %s\n", runtime.GOOS, runtime.GOARCH) + logrus.Infoln("can use ipv6:", canUseIPv6.Get()) + ntrs := flag.Bool("notrs", false, "use standard TLS client") + dnsf := flag.String("dns", "", "custom dns.yaml") + flag.Parse() + args := flag.Args() + if len(args) != 1 { + fmt.Println("Usage:", os.Args[0], "[-notrs] 'target/to/download'") + flag.PrintDefaults() + fmt.Println(" 'target/to/download'\n like packs/general/latest") + fmt.Println("All available targets:") + fmt.Println(cmdlst.String()) + return + } + if *ntrs { + usetrs = false + } + if *dnsf != "" { + f, err := os.Open(*dnsf) + if err != nil { + logrus.Errorln("open custom dns file", *dnsf, "err:", err) + return + } + m := map[string][]string{} + err = yaml.NewDecoder(f).Decode(&m) + if err != nil { + logrus.Errorln("decode custom dns file", *dnsf, "err:", err) + return + } + _ = f.Close() + if canUseIPv6.Get() { + dotv6servers.add(m) + } else { + dotv4servers.add(m) + } + fmt.Println("custom dns file added") + } + usercfg, err := readconfig(args[0]) + if err != nil { + logrus.Errorln(err) + return + } + err = usercfg.download(args[0]) + if err != nil { + logrus.Errorln(err) + return + } + logrus.Info("download tasks finished") +} diff --git a/packs/amd/latest.yaml b/packs/amd/latest.yaml new file mode 100644 index 0000000..1924ad2 --- /dev/null +++ b/packs/amd/latest.yaml @@ -0,0 +1,3 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Refer: v2/20231006 diff --git a/packs/amd/v2/20230813.yaml b/packs/amd/v2/20230813.yaml new file mode 100644 index 0000000..5cdb648 --- /dev/null +++ b/packs/amd/v2/20230813.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC0813AMD_Intel.7z + OS: windows + Arch: amd64 diff --git a/packs/amd/v2/20231006.yaml b/packs/amd/v2/20231006.yaml new file mode 100644 index 0000000..b62c099 --- /dev/null +++ b/packs/amd/v2/20231006.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC1006AMD_Intel.7z + OS: windows + Arch: amd64 diff --git a/packs/general/latest.yaml b/packs/general/latest.yaml new file mode 100644 index 0000000..9719d93 --- /dev/null +++ b/packs/general/latest.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC-beta.7z + OS: windows + Arch: amd64 diff --git a/packs/general/v1/20230331.yaml b/packs/general/v1/20230331.yaml new file mode 100644 index 0000000..9b27d3b --- /dev/null +++ b/packs/general/v1/20230331.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC-beta-v20230331.7z + OS: windows + Arch: amd64 diff --git a/packs/general/v1/20230416.yaml b/packs/general/v1/20230416.yaml new file mode 100644 index 0000000..bd73f73 --- /dev/null +++ b/packs/general/v1/20230416.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC-beta20230416.7z + OS: windows + Arch: amd64 diff --git a/packs/general/v1/20230428.yaml b/packs/general/v1/20230428.yaml new file mode 100644 index 0000000..e533c1c --- /dev/null +++ b/packs/general/v1/20230428.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC-beta20230428.7z + OS: windows + Arch: amd64 diff --git a/packs/general/v1/20230508.yaml b/packs/general/v1/20230508.yaml new file mode 100644 index 0000000..e222760 --- /dev/null +++ b/packs/general/v1/20230508.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC-beta20230508.7z + OS: windows + Arch: amd64 diff --git a/packs/general/v1/20230513.yaml b/packs/general/v1/20230513.yaml new file mode 100644 index 0000000..dbc968a --- /dev/null +++ b/packs/general/v1/20230513.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC-beta-20230513.7z + OS: windows + Arch: amd64 diff --git a/packs/general/v1/20230516.yaml b/packs/general/v1/20230516.yaml new file mode 100644 index 0000000..b50dec5 --- /dev/null +++ b/packs/general/v1/20230516.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC-beta20230516.7z + OS: windows + Arch: amd64 diff --git a/packs/general/v1/20230717.yaml b/packs/general/v1/20230717.yaml new file mode 100644 index 0000000..e60e327 --- /dev/null +++ b/packs/general/v1/20230717.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC-beta0717.7z + OS: windows + Arch: amd64 diff --git a/packs/general/v2/20230528.yaml b/packs/general/v2/20230528.yaml new file mode 100644 index 0000000..776b314 --- /dev/null +++ b/packs/general/v2/20230528.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC-beta-v2-0528.7z + OS: windows + Arch: amd64 diff --git a/packs/general/v2/20230618.yaml b/packs/general/v2/20230618.yaml new file mode 100644 index 0000000..04b9a5f --- /dev/null +++ b/packs/general/v2/20230618.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC-beta-v2-0618.7z + OS: windows + Arch: amd64 diff --git a/packs/intel/latest.yaml b/packs/intel/latest.yaml new file mode 100644 index 0000000..1924ad2 --- /dev/null +++ b/packs/intel/latest.yaml @@ -0,0 +1,3 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Refer: v2/20231006 diff --git a/packs/intel/v2/20230813.yaml b/packs/intel/v2/20230813.yaml new file mode 100644 index 0000000..5cdb648 --- /dev/null +++ b/packs/intel/v2/20230813.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC0813AMD_Intel.7z + OS: windows + Arch: amd64 diff --git a/packs/intel/v2/20231006.yaml b/packs/intel/v2/20231006.yaml new file mode 100644 index 0000000..b62c099 --- /dev/null +++ b/packs/intel/v2/20231006.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC1006AMD_Intel.7z + OS: windows + Arch: amd64 diff --git a/packs/nvidia/latest.yaml b/packs/nvidia/latest.yaml new file mode 100644 index 0000000..1924ad2 --- /dev/null +++ b/packs/nvidia/latest.yaml @@ -0,0 +1,3 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Refer: v2/20231006 diff --git a/packs/nvidia/v2/20230813.yaml b/packs/nvidia/v2/20230813.yaml new file mode 100644 index 0000000..359ab47 --- /dev/null +++ b/packs/nvidia/v2/20230813.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC0813Nvidia.7z + OS: windows + Arch: amd64 diff --git a/packs/nvidia/v2/20231006.yaml b/packs/nvidia/v2/20231006.yaml new file mode 100644 index 0000000..917ebf3 --- /dev/null +++ b/packs/nvidia/v2/20231006.yaml @@ -0,0 +1,7 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - RVC1006Nvidia.7z + OS: windows + Arch: amd64 diff --git a/pckcfg.sh b/pckcfg.sh new file mode 100755 index 0000000..3dafb6e --- /dev/null +++ b/pckcfg.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# Should be run by go generate. DO NOT run it directly. + +files=($(find $@ | grep -v .DS_Store | sort)) + +rm -rf cfg.zip +zip -9 cfg.zip "${files[@]}" diff --git a/tools/ffmpeg.yaml b/tools/ffmpeg.yaml new file mode 100644 index 0000000..34f7e04 --- /dev/null +++ b/tools/ffmpeg.yaml @@ -0,0 +1,8 @@ +BaseURL: https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main +Targets: + - Folder: . + Copy: + - ffmpeg.exe + - ffprobe.exe + OS: windows + Arch: amd64