From dae08cbdc0a14adee0456060c5e876652c2f944a Mon Sep 17 00:00:00 2001 From: foamzou Date: Fri, 5 Aug 2022 22:54:54 +0800 Subject: [PATCH] fix(migu): fix download failed when the url contain + --- LATEST_VERSION | 2 +- processor/download.go | 11 ++++++++- processor/migu/fetch_song.go | 4 ++- processor/migu/search_test.go | 6 ++--- utils/wget.go | 46 ++++++++++++++++++++++++++++++++++- version/version.go | 4 +-- 6 files changed, 64 insertions(+), 9 deletions(-) diff --git a/LATEST_VERSION b/LATEST_VERSION index 28af839..a53741c 100644 --- a/LATEST_VERSION +++ b/LATEST_VERSION @@ -1 +1 @@ -0.2.5 \ No newline at end of file +0.2.6 \ No newline at end of file diff --git a/processor/download.go b/processor/download.go index eb282ed..70a688d 100644 --- a/processor/download.go +++ b/processor/download.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path" + "strings" "github.com/foamzou/audio-get/consts" "github.com/foamzou/audio-get/ffmpeg" @@ -34,7 +35,15 @@ func (p *Processor) downloadAudio(mediaMeta *meta.MediaMeta) error { tempOutputPath, targetOutPath := p.getOutputPaths(mediaMeta.Title, consts.ExtNameMp3) if !p.Opts.AddMediaTag && utils.GetExtFromUrl(audioUrl) == consts.ExtNameMp3 { - err := utils.WgetBinary(audioUrl, targetOutPath, mediaMeta.Headers) + var err error + + // When the url contain + in migu, it should be encode to %2B. But the net/http package will decode it to + when + // send to service. So have to use socket to download. + if mediaMeta.Source == consts.SourceNameMigu && strings.Contains(audioUrl, "%2B") { + err = utils.DownloadBinaryWithTCP(audioUrl, targetOutPath, mediaMeta.Headers) + } else { + err = utils.WgetBinary(audioUrl, targetOutPath, mediaMeta.Headers) + } if err != nil { return err } diff --git a/processor/migu/fetch_song.go b/processor/migu/fetch_song.go index 6deae86..44d99a9 100644 --- a/processor/migu/fetch_song.go +++ b/processor/migu/fetch_song.go @@ -3,6 +3,7 @@ package migu import ( "encoding/json" "fmt" + "strings" "github.com/foamzou/audio-get/consts" "github.com/foamzou/audio-get/meta" @@ -58,7 +59,8 @@ func (c *Core) fetchFromSong() (mediaMeta *meta.MediaMeta, err error) { func getSongUrlFromResources(resources []RateFormat) string { for _, resource := range resources { if resource.FormatType == "HQ" { - return "https://freetyst.nf.migu.cn/" + utils.RegexSingleMatchIgnoreError(resource.Url, `ftp:\/\/[^/]+\/(.*)`, "") + url := "https://freetyst.nf.migu.cn/" + utils.RegexSingleMatchIgnoreError(resource.Url, `ftp:\/\/[^/]+\/(.*)`, "") + return strings.ReplaceAll(url, "+", "%2B") } } return "" diff --git a/processor/migu/search_test.go b/processor/migu/search_test.go index 887cef8..38303a9 100644 --- a/processor/migu/search_test.go +++ b/processor/migu/search_test.go @@ -34,9 +34,9 @@ func TestCore_SearchSong(t *testing.T) { name: "Test search song", fields: fields{Opts: &args.Options{Search: args.Search{Keyword: "I Remember F.I.R", Type: "song"}}}, wantSongItem: &meta.SearchSongItem{ - Name: "淡水海边(电影《不能说的秘密》背景音乐)", - Artist: "周杰伦", - Album: "《不能说的秘密》电影原声", + Name: "I Remember", + Artist: "飞儿乐团", + Album: "Better Life", Url: "music.migu.cn", Source: consts.SourceNameMigu, }, diff --git a/utils/wget.go b/utils/wget.go index b9d2153..528242c 100644 --- a/utils/wget.go +++ b/utils/wget.go @@ -2,8 +2,12 @@ package utils import ( "errors" + "fmt" "io" + "io/ioutil" + "net" "net/http" + "net/url" "os" "strings" ) @@ -33,7 +37,7 @@ func WgetBinary(url string, downloadTo string, headers map[string]string) error defer resp.Body.Close() if resp.StatusCode < 200 || resp.StatusCode > 299 { - return errors.New("should return 2xx") + return errors.New("should return 2xx, but got " + resp.Status) } if len(resp.Header["Content-Type"]) > 0 && strings.Contains(resp.Header["Content-Type"][0], "text") { @@ -46,3 +50,43 @@ func WgetBinary(url string, downloadTo string, headers map[string]string) error } return nil } + +func DownloadBinaryWithTCP(inputUrl string, downloadTo string, headers map[string]string) error { + u, err := url.Parse(inputUrl) + if err != nil { + return err + } + + conn, err := net.Dial("tcp", u.Host+":80") + if err != nil { + return err + } + + u.Path = strings.ReplaceAll(u.Path, "+", "%2B") + rt := fmt.Sprintf("GET %v HTTP/1.1\r\n", u.Path) + rt += fmt.Sprintf("Host: %v\r\n", u.Host) + for k, v := range headers { + rt += fmt.Sprintf("%s: %s\r\n", k, v) + } + rt += "Connection: close\r\n" + rt += "\r\n" + + _, err = conn.Write([]byte(rt)) + if err != nil { + return err + } + + resp, err := ioutil.ReadAll(conn) + if err != nil { + return err + } + + err = ioutil.WriteFile(downloadTo, resp, 0600) + if err != nil { + return err + } + + _ = conn.Close() + + return nil +} diff --git a/version/version.go b/version/version.go index f2ee515..01db493 100644 --- a/version/version.go +++ b/version/version.go @@ -5,8 +5,8 @@ import ( ) const ( - BuildCode = 10 - BuildName = "0.2.5" + BuildCode = 11 + BuildName = "0.2.6" Repo = "https://github.com/foamzou/media-get" )