You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
star/mget/cmd.go

147 lines
4.0 KiB
Go

3 months ago
package mget
import (
"b612.me/stario"
"b612.me/starlog"
1 month ago
"b612.me/starnet"
3 months ago
"fmt"
"github.com/spf13/cobra"
"os"
"os/signal"
"regexp"
"strconv"
"strings"
"time"
)
var mg Mget
var Cmd = &cobra.Command{
Use: "mget",
Short: "多线程下载工具",
Long: `多线程下载工具`,
Run: Run,
}
var headers []string
var ua string
var proxy string
var skipVerify bool
1 month ago
var speedcontrol, user, pwd string
var dialTimeout, timeout int
3 months ago
func init() {
Cmd.Flags().StringVarP(&mg.Tareget, "output", "o", "", "输出文件名")
Cmd.Flags().IntVarP(&mg.BufferSize, "buffer", "b", 8192, "缓冲区大小")
Cmd.Flags().IntVarP(&mg.Thread, "thread", "t", 8, "线程数")
Cmd.Flags().IntVarP(&mg.RedoRPO, "safe", "s", 1048576, "安全校验点")
Cmd.Flags().StringSliceVarP(&headers, "header", "H", []string{}, "自定义请求头,格式: key=value")
1 month ago
Cmd.Flags().StringVarP(&proxy, "proxy", "P", "", "代理地址")
3 months ago
Cmd.Flags().StringVarP(&ua, "user-agent", "U", "", "自定义User-Agent")
Cmd.Flags().BoolVarP(&skipVerify, "skip-verify", "k", false, "跳过SSL验证")
Cmd.Flags().StringVarP(&speedcontrol, "speed", "S", "", "限速如1M意思是1MB/s")
1 month ago
Cmd.Flags().IntVarP(&dialTimeout, "dial-timeout", "d", 5, "连接网络超时时间,单位:秒")
Cmd.Flags().IntVarP(&timeout, "timeout", "T", 0, "下载超时时间,单位:秒")
Cmd.Flags().StringVarP(&user, "user", "u", "", "http basic认证用户")
Cmd.Flags().StringVarP(&pwd, "passwd", "p", "", "http basic认证密码")
3 months ago
}
func parseSpeedString(speedString string) (uint64, error) {
// 定义单位及其对应的字节值
2 months ago
unitMultipliers := map[string]int64{
3 months ago
"b": 1, "": 1,
"k": 1024, "kb": 1024, "kib": 1024,
"m": 1024 * 1024, "mb": 1024 * 1024, "mib": 1024 * 1024,
"g": 1024 * 1024 * 1024, "gb": 1024 * 1024 * 1024, "gib": 1024 * 1024 * 1024,
"t": 1024 * 1024 * 1024 * 1024, "tb": 1024 * 1024 * 1024 * 1024, "tib": 1024 * 1024 * 1024 * 1024,
}
// 正则表达式匹配速度的格式
re := regexp.MustCompile(`(?i)^\s*([\d.]+)\s*(b|k|m|g|t|kb|mb|gb|tb|kib|mib|gib|tib)?\s*/?\s*s?\s*$`)
matches := re.FindStringSubmatch(strings.ToLower(speedString))
if matches == nil {
return 0, fmt.Errorf("invalid speed string format")
}
// 解析数值部分
value, err := strconv.ParseFloat(matches[1], 64)
if err != nil {
return 0, fmt.Errorf("invalid numeric value")
}
// 获取单位部分
unit := matches[2]
if unit == "" {
unit = "b"
}
// 根据单位计算最终的字节每秒值
multiplier, ok := unitMultipliers[unit]
if !ok {
return 0, fmt.Errorf("invalid unit in speed string")
}
return uint64(value * float64(multiplier)), nil
}
func Run(cmd *cobra.Command, args []string) {
if args == nil || len(args) == 0 {
starlog.Errorln("缺少URL参数")
os.Exit(1)
}
1 month ago
mg.Setting = *starnet.NewSimpleRequest(args[0], "GET")
mg.OriginUri = args[0]
if dialTimeout > 0 {
mg.Setting.SetDialTimeout(time.Duration(dialTimeout) * time.Second)
}
if timeout > 0 {
mg.Setting.SetTimeout(time.Duration(timeout) * time.Second)
}
if user != "" || pwd != "" {
mg.Setting.RequestOpts.SetBasicAuth(user, pwd)
}
3 months ago
if speedcontrol != "" {
speed, err := parseSpeedString(speedcontrol)
if err != nil {
starlog.Criticalln("Speed Limit Error:", err)
os.Exit(1)
}
mg.speedlimit = int64(speed)
fmt.Printf("Max Speed Limit:(user in):\t%v\n", speedcontrol)
fmt.Printf("Max Speed Limit (bytes/s):\t%v bytes/sec\n", speed)
}
for _, v := range headers {
kv := strings.SplitN(v, "=", 2)
if len(kv) != 2 {
continue
}
mg.Setting.AddHeader(strings.TrimSpace(kv[0]), strings.TrimSpace(kv[1]))
}
if ua != "" {
mg.Setting.SetUserAgent(ua)
}
if proxy != "" {
mg.Setting.SetProxy(proxy)
}
if skipVerify {
mg.Setting.SetSkipTLSVerify(true)
}
sig := make(chan os.Signal)
signal.Notify(sig, os.Interrupt)
select {
case err := <-stario.WaitUntilFinished(mg.Run):
if err != nil {
starlog.Errorln(err)
os.Exit(2)
}
time.Sleep(time.Second)
return
case <-sig:
starlog.Infoln("User Interrupted")
mg.fn()
time.Sleep(time.Second)
mg.Redo.Save()
os.Exit(3)
}
}