From a642ef0684572ed45cfb8258915fd3ac62251ffd Mon Sep 17 00:00:00 2001 From: Spiegel Date: Tue, 12 May 2026 17:58:37 +0900 Subject: [PATCH] Integrate webinfo image APIs --- go.mod | 21 +++---- go.sum | 34 ++++++----- images/images.go | 26 ++------ nasaapi/nasaapod/response.go | 36 +---------- webpage/webpage.go | 113 ++++------------------------------- 5 files changed, 46 insertions(+), 184 deletions(-) diff --git a/go.mod b/go.mod index 4425839..ca43782 100644 --- a/go.mod +++ b/go.mod @@ -5,31 +5,30 @@ go 1.26 toolchain go1.26.3 require ( - github.com/PuerkitoBio/goquery v1.12.0 github.com/bluesky-social/indigo v0.0.0-20260428083920-ce62b8fce9e0 github.com/glebarez/sqlite v1.11.0 - github.com/goark/errs v1.3.3 + github.com/goark/errs v1.3.4 github.com/goark/errs/zapobject v0.1.4 - github.com/goark/fetch v0.5.1 + github.com/goark/fetch v0.5.3 github.com/goark/gocli v0.13.0 github.com/goark/koyomi v0.11.0 + github.com/goark/webinfo v0.2.0 github.com/hymkor/go-multiline-ny v0.23.1 github.com/ipfs/go-log/v2 v2.9.1 github.com/joho/godotenv v1.5.1 - github.com/mattn/go-encoding v0.0.2 github.com/mattn/go-mastodon v0.0.11 github.com/mmcdole/gofeed v1.3.0 github.com/nyaosorg/go-readline-ny v1.15.1 github.com/spf13/cobra v1.10.2 github.com/spf13/viper v1.21.0 go.uber.org/zap v1.28.0 - golang.org/x/image v0.39.0 - golang.org/x/net v0.53.0 + golang.org/x/image v0.40.0 gorm.io/gorm v1.31.1 moul.io/zapgorm2 v1.3.0 ) require ( + github.com/PuerkitoBio/goquery v1.12.0 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -63,6 +62,7 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/mattn/go-encoding v0.0.2 // indirect github.com/mattn/go-isatty v0.0.22 // indirect github.com/mattn/go-runewidth v0.0.23 // indirect github.com/mattn/go-tty v0.0.7 // indirect @@ -99,10 +99,11 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.50.0 // indirect - golang.org/x/sys v0.43.0 // indirect - golang.org/x/term v0.42.0 // indirect - golang.org/x/text v0.36.0 // indirect + golang.org/x/crypto v0.51.0 // indirect + golang.org/x/net v0.54.0 // indirect + golang.org/x/sys v0.44.0 // indirect + golang.org/x/term v0.43.0 // indirect + golang.org/x/text v0.37.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect lukechampine.com/blake3 v1.2.1 // indirect modernc.org/libc v1.22.5 // indirect diff --git a/go.sum b/go.sum index 1dad858..f2c9a8f 100644 --- a/go.sum +++ b/go.sum @@ -37,16 +37,18 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= -github.com/goark/errs v1.3.3 h1:vqzm/1aqvh4Ha8JDqIqIU5ZoBtjaRezFcMC55B5ljAM= -github.com/goark/errs v1.3.3/go.mod h1:4xM7rorwYQlqh9kUhfKpC5P7VAJW2KfvuQpYnTaU0ek= +github.com/goark/errs v1.3.4 h1:/+/xwF3UwXGxGGLurzBTaMMoryTBeaPfheJ1aW9cglA= +github.com/goark/errs v1.3.4/go.mod h1:4xM7rorwYQlqh9kUhfKpC5P7VAJW2KfvuQpYnTaU0ek= github.com/goark/errs/zapobject v0.1.4 h1:0zsgmNATXKxAFlF8x+YNgONKpqPx04aYtJVqf9nRib0= github.com/goark/errs/zapobject v0.1.4/go.mod h1:McsR4DQM1oKQ7WtWY0oAGEIVgFMz9hayUuFvN/IWTeA= -github.com/goark/fetch v0.5.1 h1:AZql1WTANG9umytvf4EzMzIyGHY4RP+N6Q5n0ALxRr0= -github.com/goark/fetch v0.5.1/go.mod h1:blLKmPKgSDw33ocut79ypHT4V0MLmfVY/MHKpq+OgD4= +github.com/goark/fetch v0.5.3 h1:ZwT5N04BSiPw2tF2gG5MXsmoSr+A/sxE52KJWy/aWzw= +github.com/goark/fetch v0.5.3/go.mod h1:jgu+bn1HN8AfEks+ENqiPJVF99Cvs7cb2dqSujhjsOE= github.com/goark/gocli v0.13.0 h1:hR/5E4JGMEcbQxkSqR7K/0XnYY2Hd6GDpuazXGC3jn4= github.com/goark/gocli v0.13.0/go.mod h1:pFYWXAXZ5G4QqPcXsDTSFbCuVg0qO40NYkp2XKthc18= github.com/goark/koyomi v0.11.0 h1:qsgrkwQmr9tvPtEizftB+dUdPNObSsv89NzHl1cfDz8= github.com/goark/koyomi v0.11.0/go.mod h1:uat27vVC6+S304I2roj3ibVanuWz57FpLXKxinxC28s= +github.com/goark/webinfo v0.2.0 h1:rRsoLWzF35JA6GIRxEFL53ivLW+5PM1QL3hsG+pJlHI= +github.com/goark/webinfo v0.2.0/go.mod h1:jPHA6OWQPNvLr6er7SwVMiOuvlNqeNRF0K56VFf66Sc= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -262,10 +264,10 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= -golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= -golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww= -golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/image v0.40.0 h1:Tw4GyDXMo+daZN1znreBRC3VayR1aLFUyUEOLUdW1a8= +golang.org/x/image v0.40.0/go.mod h1:uIc348UZMSvS5Z65CVZ7iDPaNobNFEPeJ4kbqTOszmA= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -290,8 +292,8 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -317,8 +319,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -328,8 +330,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= -golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= -golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= +golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4= +golang.org/x/term v0.43.0/go.mod h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -339,8 +341,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= diff --git a/images/images.go b/images/images.go index ada3ba5..71c9f6d 100644 --- a/images/images.go +++ b/images/images.go @@ -10,33 +10,15 @@ import ( "path/filepath" "github.com/goark/errs" - "github.com/goark/fetch" "github.com/goark/toolbox/ecode" + "github.com/goark/webinfo" "golang.org/x/image/draw" ) // FetchFromURL returns binary image from URL. func FetchFromURL(ctx context.Context, urlStr string) (data []byte, err error) { - u, ferr := fetch.URL(urlStr) - if ferr != nil { - err = errs.Wrap(ferr, errs.WithContext("url", urlStr)) - return - } - resp, ferr := fetch.New().GetWithContext(ctx, u) - if ferr != nil { - err = errs.Wrap(ferr, errs.WithContext("url", u.String())) - return - } - defer func() { - err = errs.Join(err, resp.Close()) - }() - - b, ferr := io.ReadAll(resp.Body()) - if ferr != nil { - err = errs.Wrap(ferr, errs.WithContext("url", u.String())) - return - } - data = b + wi := &webinfo.Webinfo{ImageURL: urlStr} + data, err = wi.ImageBytes(ctx) return } @@ -127,7 +109,7 @@ func convertJPEG(src image.Image, quality int) ([]byte, error) { return dst.Bytes(), nil } -/* Copyright 2023 Spiegel +/* Copyright 2023-2026 Spiegel * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/nasaapi/nasaapod/response.go b/nasaapi/nasaapod/response.go index 2e03b9c..1a7a90d 100644 --- a/nasaapi/nasaapod/response.go +++ b/nasaapi/nasaapod/response.go @@ -6,13 +6,12 @@ import ( "errors" "io" "net/url" - "os" "path" "github.com/goark/errs" - "github.com/goark/fetch" "github.com/goark/toolbox/ecode" "github.com/goark/toolbox/values" + "github.com/goark/webinfo" ) const ( @@ -107,37 +106,8 @@ func (res *Response) ImageFile(ctx context.Context, dir string) (tname string, e err = errs.Wrap(ecode.ErrNoAPODImage) return } - - // get Image data - u, perr := url.Parse(urlStr) - if perr != nil { - err = errs.Wrap(perr, errs.WithContext("url", urlStr)) - return - } - img, ferr := fetch.New().GetWithContext(ctx, u) - if ferr != nil { - err = errs.Wrap(ferr, errs.WithContext("url", urlStr)) - return - } - defer func() { - err = errs.Join(err, img.Close()) - }() - - // copy to temporary file - file, ferr := os.CreateTemp(dir, "apod.*.bin") - if ferr != nil { - err = errs.Wrap(ferr) - return - } - defer func() { - err = errs.Join(err, file.Close()) - }() - - tname = file.Name() - if _, cerr := io.Copy(file, img.Body()); cerr != nil { - err = errs.Wrap(cerr, errs.WithContext("url", urlStr), errs.WithContext("temp_file", tname)) - return - } + wi := &webinfo.Webinfo{ImageURL: urlStr} + tname, err = wi.DownloadImage(ctx, dir, true) return } diff --git a/webpage/webpage.go b/webpage/webpage.go index 3b48f80..b01fde9 100644 --- a/webpage/webpage.go +++ b/webpage/webpage.go @@ -1,23 +1,17 @@ package webpage import ( - "bufio" "context" "encoding/json" "fmt" "io" - "net/url" - "os" "sort" "strings" "time" - "github.com/PuerkitoBio/goquery" "github.com/goark/errs" - "github.com/goark/fetch" "github.com/goark/toolbox/ecode" - "github.com/mattn/go-encoding" - "golang.org/x/net/html/charset" + "github.com/goark/webinfo" ) // Webpage is information of web page @@ -32,75 +26,18 @@ type Webpage struct { // ReadPage function reads web page from URL, and analysis information. func ReadPage(ctx context.Context, urlStr string) (link *Webpage, err error) { - // fetch web page - u, ferr := fetch.URL(urlStr) + wi, ferr := webinfo.Fetch(ctx, urlStr, "") if ferr != nil { err = errs.Wrap(ferr, errs.WithContext("url", urlStr)) return } - resp, ferr := fetch.New().GetWithContext(ctx, u) - if ferr != nil { - err = errs.Wrap(ferr, errs.WithContext("url", u.String())) - return - } - defer func() { - err = errs.Join(err, resp.Close()) - }() - - // detect character encoding - br := bufio.NewReader(resp.Body()) - var r io.Reader = br - if data, err2 := br.Peek(1024); err2 == nil { //next 1024 bytes without advancing the reader. - enc, name, _ := charset.DetermineEncoding(data, resp.Header().Get("content-type")) - if enc != nil { - r = enc.NewDecoder().Reader(br) - } else if len(name) > 0 { - if enc := encoding.GetEncoding(name); enc != nil { - r = enc.NewDecoder().Reader(br) - } - } + link = &Webpage{ + URL: urlStr, + Canonical: wi.Canonical, + Title: wi.Title, + Description: wi.Description, + ImageURL: wi.ImageURL, } - - // analysis web content - link = &Webpage{URL: urlStr} - doc, qerr := goquery.NewDocumentFromReader(r) - if qerr != nil { - err = errs.Wrap(qerr, errs.WithContext("url", u.String())) - return - } - doc.Find("head").Each(func(_ int, s *goquery.Selection) { - s.Find("title").Each(func(_ int, s *goquery.Selection) { - t := s.Text() - if len(t) > 0 { - link.Title = strings.TrimSpace(t) - } - }) - s.Find(`meta[property="og:title"]`).Each(func(_ int, s *goquery.Selection) { - if v, ok := s.Attr("content"); ok && len(v) > 0 { - link.Title = strings.TrimSpace(v) - } - }) - s.Find(`meta[name="description"]`).Each(func(_ int, s *goquery.Selection) { - if v, ok := s.Attr("content"); ok && len(v) > 0 { - link.Description = strings.TrimSpace(v) - } - }) - s.Find(`meta[property="og:description"]`).Each(func(_ int, s *goquery.Selection) { - if v, ok := s.Attr("content"); ok && len(v) > 0 { - link.Description = strings.TrimSpace(v) - } - }) - s.Find(`meta[property="og:image"]`).Each(func(_ int, s *goquery.Selection) { - if v, ok := s.Attr("content"); ok && len(v) > 0 { - link.ImageURL = strings.TrimSpace(v) - } - }) - s.Find("link[rel='canonical']").Each(func(_ int, s *goquery.Selection) { - if v, ok := s.Attr("href"); ok && len(v) > 0 { - link.Canonical = strings.TrimSpace(v) - } - }) - }) return } @@ -140,38 +77,8 @@ func (wp *Webpage) ImageFile(ctx context.Context, dir string) (tname string, err err = errs.Wrap(ecode.ErrNoAPODImage) return } - - // get Image data - u, perr := url.Parse(wp.ImageURL) - if perr != nil { - err = errs.Wrap(perr, errs.WithContext("image_url", wp.ImageURL)) - return - } - img, ferr := fetch.New().GetWithContext(ctx, u) - if ferr != nil { - err = errs.Wrap(ferr, errs.WithContext("image_url", wp.ImageURL)) - return - } - defer func() { - err = errs.Join(err, img.Close()) - }() - - // copy to temporary file - file, ferr := os.CreateTemp(dir, "webpage.*.jpg") - if ferr != nil { - err = errs.Wrap(ferr) - return - } - defer func() { - err = errs.Join(err, file.Close()) - }() - - tname = file.Name() - _, cerr := io.Copy(file, img.Body()) - if cerr != nil { - err = errs.Wrap(cerr, errs.WithContext("image_url", wp.ImageURL), errs.WithContext("temp_file", tname)) - return - } + wi := &webinfo.Webinfo{ImageURL: wp.ImageURL} + tname, err = wi.DownloadImage(ctx, dir, true) return }