diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a24e258f..f64eed8d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,9 @@ jobs: go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.41.0 golangci-lint --version - name: Lint - run: golangci-lint run ./... -v + run: | + go mod tidy + golangci-lint run ./... -v - name: Test env: GOFLAGS: -mod=mod diff --git a/.golangci.yml b/.golangci.yml index b5a5b0866..17555d6e8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,7 +10,6 @@ linter-settings: linters: enable: - goconst - - gofmt - goimports - misspell - unparam diff --git a/config/version.go b/config/version.go deleted file mode 100644 index 94fdec56e..000000000 --- a/config/version.go +++ /dev/null @@ -1,4 +0,0 @@ -package config - -// VERSION version of annie -const VERSION = "0.10.3" diff --git a/extractors/acfun/acfun.go b/extractors/acfun/acfun.go index fd78b8d35..acb3d12bc 100644 --- a/extractors/acfun/acfun.go +++ b/extractors/acfun/acfun.go @@ -5,23 +5,21 @@ import ( "net/url" "regexp" + jsoniter "github.com/json-iterator/go" + "github.com/iawia002/annie/extractors/types" "github.com/iawia002/annie/parser" "github.com/iawia002/annie/request" "github.com/iawia002/annie/utils" - jsoniter "github.com/json-iterator/go" ) const ( - bangumiDataPattern = "window.pageInfo = window.bangumiData = (.*);" - qualityConfigPattern = "window.qualityConfig = (.*);" - bangumiListPattern = "window.bangumiList = (.*);" + bangumiDataPattern = "window.pageInfo = window.bangumiData = (.*);" + bangumiListPattern = "window.bangumiList = (.*);" - bangumiHTMLURL = "https://www.acfun.cn/bangumi/aa%d_36188_%d" - bangumiVideoURL = "https://%s/mediacloud/acfun/acfun_video/hls/" + bangumiHTMLURL = "https://www.acfun.cn/bangumi/aa%d_36188_%d" referer = "https://www.acfun.cn" - host = "https://www.acfun.cn" ) type extractor struct{} @@ -31,6 +29,7 @@ func New() types.Extractor { return &extractor{} } +// Extract ... func (e *extractor) Extract(URL string, option types.Options) ([]*types.Data, error) { html, err := request.GetByte(URL, referer, nil) if err != nil { @@ -65,7 +64,7 @@ func (e *extractor) Extract(URL string, option types.Options) ([]*types.Data, er wgp.Add() go func() { defer wgp.Done() - datas = append(datas, extractBangumi(concatURL(t), option)) + datas = append(datas, extractBangumi(concatURL(t))) }() } wgp.Wait() @@ -76,7 +75,7 @@ func concatURL(epData *episodeData) string { return fmt.Sprintf(bangumiHTMLURL, epData.BangumiID, epData.ItemID) } -func extractBangumi(URL string, option types.Options) *types.Data { +func extractBangumi(URL string) *types.Data { var err error html, err := request.GetByte(URL, referer, nil) if err != nil { @@ -98,8 +97,7 @@ func extractBangumi(URL string, option types.Options) *types.Data { urls, err := utils.M3u8URLs(m3u8URL.String()) if err != nil { - - m3u8URL, err = url.Parse(stm.URL) + _, err = url.Parse(stm.URL) if err != nil { return types.EmptyData(URL, err) } diff --git a/extractors/iqiyi/iqiyi.go b/extractors/iqiyi/iqiyi.go index ca83f3bb7..f09ec96c8 100644 --- a/extractors/iqiyi/iqiyi.go +++ b/extractors/iqiyi/iqiyi.go @@ -65,7 +65,8 @@ func getVF(params string) string { } else { v8 = v4 + 49 } - suffix += string(v8) // string(97) -> "a" + // string(97) -> "a" + suffix += string(v8) // nolint } } params += suffix diff --git a/extractors/types/defs.go b/extractors/types/defs.go index e05240a87..3b13367fb 100644 --- a/extractors/types/defs.go +++ b/extractors/types/defs.go @@ -7,6 +7,4 @@ import ( var ( // ErrURLParseFailed defines url parse failed error. ErrURLParseFailed = errors.New("url parse failed") - // ErrLoginRequired defines login required error. - ErrLoginRequired = errors.New("login required") ) diff --git a/go.mod b/go.mod index a2c414e42..95000b64b 100644 --- a/go.mod +++ b/go.mod @@ -14,5 +14,6 @@ require ( github.com/kr/pretty v0.1.0 github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff github.com/tidwall/gjson v1.8.1 + github.com/urfave/cli/v2 v2.3.0 gopkg.in/sourcemap.v1 v1.0.5 // indirect ) diff --git a/go.sum b/go.sum index 2b5a8cdc1..8d9dc3d52 100644 --- a/go.sum +++ b/go.sum @@ -82,6 +82,8 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 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= @@ -285,9 +287,11 @@ github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspo github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -322,6 +326,8 @@ github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/vbauerster/mpb/v5 v5.4.0/go.mod h1:fi4wVo7BVQ22QcvFObm+VwliQXlV1eBT8JDaKXR4JGI= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/ysmood/goob v0.3.0 h1:XZ51cZJ4W3WCoCiUktixzMIQF86W7G5VFL4QQ/Q2uS0= diff --git a/go.test.sh b/go.test.sh deleted file mode 100755 index d317ca963..000000000 --- a/go.test.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -e -#set -x # debug/verbose execution - -# Ensures removal of file -trap 'rm -f profile.out downloader/*.{mp4,download,jpg}' SIGINT EXIT - -# go -race needs CGO_ENABLED to proceed -export CGO_ENABLED=1; - -for d in $(go list ./... | grep -v vendor); do - go test -v -race -coverprofile=profile.out -covermode=atomic "${d}" - if [ -f profile.out ]; then - cat profile.out > coverage.txt - rm profile.out - fi -done diff --git a/main.go b/main.go index 8428c14dd..5e4c4ef9f 100644 --- a/main.go +++ b/main.go @@ -2,14 +2,16 @@ package main import ( "encoding/json" - "flag" + "errors" "fmt" "io/ioutil" "os" + "sort" "strings" "github.com/fatih/color" "github.com/go-rod/rod" + "github.com/urfave/cli/v2" "github.com/iawia002/annie/cookier" "github.com/iawia002/annie/downloader" @@ -19,128 +21,259 @@ import ( "github.com/iawia002/annie/utils" ) -var ( - // show version - version bool - // debug mode - debug bool - // information only mode - infoOnly bool - // print extracted data - extractedData bool +func main() { + cli.VersionPrinter = func(c *cli.Context) { + blue := color.New(color.FgBlue) + cyan := color.New(color.FgCyan) + fmt.Fprintf( + color.Output, + "\n%s: version %s, A fast, simple and clean video downloader.\n\n", + cyan.Sprintf("annie"), + blue.Sprintf(c.App.Version), + ) + } - // http cookies - cookie string - // download playlist - playlist bool - // use specified Referrer - refer string - // select specified stream to download - stream string - // URLs file path - file string - // output file path - outputPath string - // output file name - outputName string - // fileNameLength defines the maximum length of a file name - fileNameLength int - // download captions - caption bool + app := &cli.App{ + Name: "annie", + Usage: "A fast, simple and clean video downloader.", + Version: "v0.11.0", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "debug", + Aliases: []string{"d"}, + Usage: "Debug mode", + }, + &cli.BoolFlag{ + Name: "info", + Aliases: []string{"i"}, + Usage: "Information only", + }, + &cli.BoolFlag{ + Name: "json", + Aliases: []string{"j"}, + Usage: "Print extracted JSON data", + }, - // the starting item of a playlist or a file input - itemStart int - // the ending item of a playlist or a file input - itemEnd int - // items Define wanted items from a file or playlist. Separated by commas like: 1,5,6,8-10 - items string + &cli.StringFlag{ + Name: "cookie", + Aliases: []string{"c"}, + Usage: "Cookie", + }, + &cli.BoolFlag{ + Name: "playlist", + Aliases: []string{"p"}, + Usage: "Download playlist", + }, + &cli.StringFlag{ + Name: "refer", + Aliases: []string{"r"}, + Usage: "Use specified Referrer", + }, + &cli.StringFlag{ + Name: "stream-format", + Aliases: []string{"f"}, + Usage: "Select specific stream to download", + }, + &cli.StringFlag{ + Name: "file", + Aliases: []string{"F"}, + Usage: "URLs file path", + }, + &cli.StringFlag{ + Name: "output-path", + Aliases: []string{"o"}, + Usage: "Specify the output path", + }, + &cli.StringFlag{ + Name: "output-name", + Aliases: []string{"O"}, + Usage: "Specify the output file name", + }, + &cli.UintFlag{ + Name: "file-name-length", + Value: 255, + Usage: "The maximum length of a file name, 0 means unlimited", + }, + &cli.BoolFlag{ + Name: "caption", + Aliases: []string{"C"}, + Usage: "Download captions", + }, - multiThread bool - // how many times to retry when the download failed - retryTimes int - // HTTP chunk size for downloading (in MB) - chunkSizeMB int - // The number of download thread (only works for multiple-parts video) - threadNumber int + &cli.UintFlag{ + Name: "start", + Value: 1, + Usage: "Define the starting item of a playlist or a file input", + }, + &cli.UintFlag{ + Name: "end", + Value: 0, + Usage: "Define the ending item of a playlist or a file input", + }, + &cli.StringFlag{ + Name: "items", + Usage: "Define wanted items from a file or playlist. Separated by commas like: 1,5,6,8-10", + }, - // Use Aria2 RPC to download - useAria2RPC bool - // Aria2 RPC Token - aria2Token string - // Aria2 Address (default "localhost:6800") - aria2Addr string - // Aria2 Method (default "http") - aria2Method string + &cli.BoolFlag{ + Name: "multi-thread", + Aliases: []string{"m"}, + Usage: "Multiple threads to download single video", + }, + &cli.UintFlag{ + Name: "retry", + Value: 10, + Usage: "How many times to retry when the download failed", + }, + &cli.UintFlag{ + Name: "chunk-size", + Aliases: []string{"cs"}, + Value: 0, + Usage: "HTTP chunk size for downloading (in MB)", + }, + &cli.UintFlag{ + Name: "thread", + Aliases: []string{"n"}, + Value: 10, + Usage: "The number of download thread (only works for multiple-parts video)", + }, - // youku ccode - youkuCcode string - // youku ckey - youkuCkey string - // youku password - youkuPassword string + // Aria2 + &cli.BoolFlag{ + Name: "aria2", + Usage: "Use Aria2 RPC to download", + }, + &cli.StringFlag{ + Name: "aria2-token", + Usage: "Aria2 RPC Token", + }, + &cli.StringFlag{ + Name: "aria2-addr", + Value: "localhost:6800", + Usage: "Aria2 Address", + }, + &cli.StringFlag{ + Name: "aria2-method", + Value: "http", + Usage: "Aria2 Method", + }, - // File name of each bilibili episode doesn't include the playlist title - episodeTitleOnly bool -) + // youku + &cli.StringFlag{ + Name: "youku-ccode", + Aliases: []string{"ccode"}, + Value: "0590", + Usage: "Youku ccode", + }, + &cli.StringFlag{ + Name: "youku-ckey", + Aliases: []string{"ckey"}, + Value: "7B19C0AB12633B22E7FE81271162026020570708D6CC189E4924503C49D243A0DE6CD84A766832C2C99898FC5ED31F3709BB3CDD82C96492E721BDD381735026", + Usage: "Youku ckey", + }, + &cli.StringFlag{ + Name: "youku-password", + Aliases: []string{"password"}, + Usage: "Youku password", + }, -func init() { - flag.BoolVar(&version, "v", false, "Show version") - flag.BoolVar(&debug, "d", false, "Debug mode") - flag.BoolVar(&infoOnly, "i", false, "Information only") - flag.BoolVar(&extractedData, "j", false, "Print extracted data") + &cli.BoolFlag{ + Name: "episode-title-only", + Aliases: []string{"eto"}, + Usage: "File name of each bilibili episode doesn't include the playlist title", + }, + }, + Action: func(c *cli.Context) error { + args := c.Args().Slice() - flag.StringVar(&cookie, "c", "", "Cookie") - flag.BoolVar(&playlist, "p", false, "Download playlist") - flag.StringVar(&refer, "r", "", "Use specified Referrer") - flag.StringVar(&stream, "f", "", "Select specific stream to download") - flag.StringVar(&file, "F", "", "URLs file path") - flag.StringVar(&outputPath, "o", "", "Specify the output path") - flag.StringVar(&outputName, "O", "", "Specify the output file name") - flag.IntVar(&fileNameLength, "file-name-length", 255, "The maximum length of a file name, 0 means unlimited") - flag.BoolVar(&caption, "C", false, "Download captions") + if c.Bool("debug") { + cli.VersionPrinter(c) + } - flag.IntVar(&itemStart, "start", 1, "Define the starting item of a playlist or a file input") - flag.IntVar(&itemEnd, "end", 0, "Define the ending item of a playlist or a file input") - flag.StringVar( - &items, "items", "", - "Define wanted items from a file or playlist. Separated by commas like: 1,5,6,8-10", - ) + if file := c.String("file"); file != "" { + f, err := os.Open(file) + if err != nil { + return err + } + defer f.Close() // nolint - flag.BoolVar(&multiThread, "m", false, "Multiple threads to download single video") - flag.IntVar(&retryTimes, "retry", 10, "How many times to retry when the download failed") - flag.IntVar(&chunkSizeMB, "cs", 0, "HTTP chunk size for downloading (in MB)") - flag.IntVar(&threadNumber, "n", 10, "The number of download thread (only works for multiple-parts video)") + fileItems := utils.ParseInputFile(f, c.String("items"), int(c.Uint("start")), int(c.Uint("end"))) + args = append(args, fileItems...) + } - flag.BoolVar(&useAria2RPC, "aria2", false, "Use Aria2 RPC to download") - flag.StringVar(&aria2Token, "aria2token", "", "Aria2 RPC Token") - flag.StringVar(&aria2Addr, "aria2addr", "localhost:6800", "Aria2 Address") - flag.StringVar(&aria2Method, "aria2method", "http", "Aria2 Method") + if len(args) < 1 { + return errors.New("too few arguments") + } - // youku - flag.StringVar(&youkuCcode, "ccode", "0590", "Youku ccode") - flag.StringVar( - &youkuCkey, - "ckey", - "7B19C0AB12633B22E7FE81271162026020570708D6CC189E4924503C49D243A0DE6CD84A766832C2C99898FC5ED31F3709BB3CDD82C96492E721BDD381735026", - "Youku ckey", - ) - flag.StringVar(&youkuPassword, "password", "", "Youku password") + cookie := c.String("cookie") + if cookie != "" { + // If cookie is a file path, convert it to a string to ensure cookie is always string + if _, fileErr := os.Stat(cookie); fileErr == nil { + // Cookie is a file + data, err := ioutil.ReadFile(cookie) + if err != nil { + return err + } + cookie = strings.TrimSpace(string(data)) + } + } else { + // Try to use current user's cookie if possible, if failed empty cookie will be used + _ = rod.Try(func() { + cookie = cookier.Get(args...) + }) + } + + request.SetOptions(request.Options{ + RetryTimes: int(c.Uint("retry")), + Cookie: cookie, + Refer: c.String("refer"), + Debug: c.Bool("debug"), + }) - flag.BoolVar(&episodeTitleOnly, "eto", false, "File name of each bilibili episode doesn't include the playlist title") + var isErr bool + for _, videoURL := range args { + if err := download(c, videoURL); err != nil { + fmt.Fprintf( + color.Output, + "Downloading %s error:\n%s\n", + color.CyanString("%s", videoURL), color.RedString("%v", err), + ) + isErr = true + } + } + if isErr { + return cli.Exit("", 1) + } + return nil + }, + EnableBashCompletion: true, + } + + sort.Sort(cli.FlagsByName(app.Flags)) + + err := app.Run(os.Args) + if err != nil { + fmt.Fprintf( + color.Output, + "Run %s failed: %s\n", + color.CyanString("%s", app.Name), color.RedString("%v", err), + ) + os.Exit(1) + } } -func download(videoURL string) error { +func download(c *cli.Context, videoURL string) error { data, err := extractors.Extract(videoURL, types.Options{ - Playlist: playlist, - Items: items, - ItemStart: itemStart, - ItemEnd: itemEnd, - ThreadNumber: threadNumber, - EpisodeTitleOnly: episodeTitleOnly, - Cookie: cookie, - YoukuCcode: youkuCcode, - YoukuCkey: youkuCkey, - YoukuPassword: youkuPassword, + Playlist: c.Bool("playlist"), + Items: c.String("items"), + ItemStart: int(c.Uint("start")), + ItemEnd: int(c.Uint("end")), + ThreadNumber: int(c.Uint("thread")), + EpisodeTitleOnly: c.Bool("episode-title-only"), + Cookie: c.String("cookie"), + YoukuCcode: c.String("youku-ccode"), + YoukuCkey: c.String("youku-ckey"), + YoukuPassword: c.String("youku-password"), }) if err != nil { // if this error occurs, it means that an error occurred before actually starting to extract data @@ -148,7 +281,7 @@ func download(videoURL string) error { return err } - if extractedData { + if c.Bool("json") { jsonData, err := json.MarshalIndent(data, "", "\t") if err != nil { return err @@ -158,21 +291,21 @@ func download(videoURL string) error { } defaultDownloader := downloader.New(downloader.Options{ - InfoOnly: infoOnly, - Stream: stream, - Refer: refer, - OutputPath: outputPath, - OutputName: outputName, - FileNameLength: fileNameLength, - Caption: caption, - MultiThread: multiThread, - ThreadNumber: threadNumber, - RetryTimes: retryTimes, - ChunkSizeMB: chunkSizeMB, - UseAria2RPC: useAria2RPC, - Aria2Token: aria2Token, - Aria2Method: aria2Method, - Aria2Addr: aria2Addr, + InfoOnly: c.Bool("info"), + Stream: c.String("stream-format"), + Refer: c.String("refer"), + OutputPath: c.String("output-path"), + OutputName: c.String("output-name"), + FileNameLength: int(c.Uint("file-name-length")), + Caption: c.Bool("caption"), + MultiThread: c.Bool("multi-thread"), + ThreadNumber: int(c.Uint("thread")), + RetryTimes: int(c.Uint("retry")), + ChunkSizeMB: int(c.Uint("chunk-size")), + UseAria2RPC: c.Bool("aria2"), + Aria2Token: c.String("aria2-token"), + Aria2Method: c.String("aria2-method"), + Aria2Addr: c.String("aria2-addr"), }) errors := make([]error, 0) for _, item := range data { @@ -191,79 +324,3 @@ func download(videoURL string) error { } return nil } - -func printError(url string, err error) { - fmt.Fprintf( - color.Output, - "Downloading %s error:\n%s\n", - color.CyanString("%s", url), color.RedString("%v", err), - ) -} - -func main() { - flag.Parse() - args := flag.Args() - if version { - utils.PrintVersion() - return - } - - if debug { - utils.PrintVersion() - } - - if file != "" { - f, err := os.Open(file) - if err != nil { - fmt.Printf("Error %v", err) - return - } - defer f.Close() // nolint - - fileItems := utils.ParseInputFile(f, items, itemStart, itemEnd) - args = append(args, fileItems...) - } - - if len(args) < 1 { - fmt.Println("Too few arguments") - fmt.Println("Usage: annie [args] URLs...") - flag.PrintDefaults() - return - } - - if cookie != "" { - // If cookie is a file path, convert it to a string to ensure cookie is always string - if _, fileErr := os.Stat(cookie); fileErr == nil { - // Cookie is a file - data, err := ioutil.ReadFile(cookie) - if err != nil { - color.Red("%v", err) - return - } - cookie = strings.TrimSpace(string(data)) - } - } else { - // Try to use current user's cookie if possible, if failed empty cookie will be used - _ = rod.Try(func() { - cookie = cookier.Get(args...) - }) - } - - request.SetOptions(request.Options{ - RetryTimes: retryTimes, - Cookie: cookie, - Refer: refer, - Debug: debug, - }) - - var isErr bool - for _, videoURL := range args { - if err := download(videoURL); err != nil { - printError(videoURL, err) - isErr = true - } - } - if isErr { - os.Exit(1) - } -} diff --git a/utils/utils.go b/utils/utils.go index 22af01606..68ec0d20c 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -15,10 +15,8 @@ import ( "runtime" "strings" - "github.com/fatih/color" "github.com/tidwall/gjson" - "github.com/iawia002/annie/config" "github.com/iawia002/annie/request" ) @@ -254,18 +252,6 @@ func M3u8URLs(uri string) ([]string, error) { return urls, nil } -// PrintVersion print version information -func PrintVersion() { - blue := color.New(color.FgBlue) - cyan := color.New(color.FgCyan) - fmt.Fprintf( - color.Output, - "\n%s: version %s, A fast, simple and clean video downloader.\n\n", - cyan.Sprintf("annie"), - blue.Sprintf(config.VERSION), - ) -} - // Reverse Reverse a string func Reverse(s string) string { runes := []rune(s) diff --git a/utils/utils_test.go b/utils/utils_test.go index 98bea36f6..87e386d71 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -443,10 +443,6 @@ func TestMd5(t *testing.T) { } } -func TestPrintVersion(t *testing.T) { - PrintVersion() -} - func TestReverse(t *testing.T) { type args struct { text string