Skip to content

Commit 94e331b

Browse files
committed
fix build
1 parent aebb2ab commit 94e331b

File tree

3 files changed

+230
-4
lines changed

3 files changed

+230
-4
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ require (
1616
github.com/leodido/go-urn v1.2.1 // indirect
1717
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
1818
github.com/modern-go/reflect2 v1.0.1 // indirect
19+
github.com/pkg/errors v0.9.1
1920
github.com/sirupsen/logrus v1.7.0
2021
github.com/smartystreets/goconvey v1.6.4 // indirect
2122
github.com/tidwall/gjson v1.6.7 // indirect

pkg/util/util.go

Lines changed: 227 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package util
22

33
import (
4+
"bufio"
45
"bytes"
56
"compress/gzip"
67
"crypto/md5"
@@ -9,14 +10,19 @@ import (
910
"hash/crc32"
1011
"io"
1112
"io/ioutil"
13+
"net"
1214
"net/http"
15+
"net/url"
1316
"os"
1417
"runtime"
1518
"runtime/debug"
19+
"strconv"
1620
"strings"
21+
"sync"
1722
"time"
1823
"unsafe"
1924

25+
"github.com/pkg/errors"
2026
log "github.com/sirupsen/logrus"
2127
)
2228

@@ -130,4 +136,224 @@ func MustMd5(text string) string {
130136
panic(err)
131137
}
132138
return fmt.Sprintf("%x", w.Sum(nil))
133-
}
139+
}
140+
141+
var (
142+
client = &http.Client{
143+
Timeout: time.Second * 120,
144+
Transport: &http.Transport{
145+
Proxy: func(request *http.Request) (u *url.URL, e error) {
146+
if Proxy == "" {
147+
return http.ProxyFromEnvironment(request)
148+
}
149+
return url.Parse(Proxy)
150+
},
151+
DialContext: (&net.Dialer{
152+
Timeout: 30 * time.Second,
153+
KeepAlive: 30 * time.Second,
154+
}).DialContext,
155+
ForceAttemptHTTP2: true,
156+
IdleConnTimeout: 90 * time.Second,
157+
TLSHandshakeTimeout: 10 * time.Second,
158+
ExpectContinueTimeout: 1 * time.Second,
159+
MaxConnsPerHost: 0,
160+
MaxIdleConns: 0,
161+
MaxIdleConnsPerHost: 999,
162+
},
163+
}
164+
Proxy string
165+
166+
ErrOverSize = errors.New("oversize")
167+
168+
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Edg/87.0.664.66"
169+
)
170+
171+
func DownloadFile(url, path string, limit int64, headers map[string]string) error {
172+
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666)
173+
if err != nil {
174+
return err
175+
}
176+
defer file.Close()
177+
req, err := http.NewRequest("GET", url, nil)
178+
if err != nil {
179+
return err
180+
}
181+
if headers != nil {
182+
for k, v := range headers {
183+
req.Header.Set(k, v)
184+
}
185+
}
186+
if _, ok := headers["User-Agent"]; ok {
187+
req.Header["User-Agent"] = []string{UserAgent}
188+
}
189+
resp, err := client.Do(req)
190+
if err != nil {
191+
return err
192+
}
193+
defer resp.Body.Close()
194+
if limit > 0 && resp.ContentLength > limit {
195+
return ErrOverSize
196+
}
197+
_, err = io.Copy(file, resp.Body)
198+
if err != nil {
199+
return err
200+
}
201+
return nil
202+
}
203+
204+
func DownloadFileMultiThreading(url, path string, limit int64, threadCount int, headers map[string]string) error {
205+
if threadCount < 2 {
206+
return DownloadFile(url, path, limit, headers)
207+
}
208+
type BlockMetaData struct {
209+
BeginOffset int64
210+
EndOffset int64
211+
DownloadedSize int64
212+
}
213+
var blocks []*BlockMetaData
214+
var contentLength int64
215+
errUnsupportedMultiThreading := errors.New("unsupported multi-threading")
216+
// 初始化分块或直接下载
217+
initOrDownload := func() error {
218+
copyStream := func(s io.ReadCloser) error {
219+
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666)
220+
if err != nil {
221+
return err
222+
}
223+
defer file.Close()
224+
if _, err = io.Copy(file, s); err != nil {
225+
return err
226+
}
227+
return errUnsupportedMultiThreading
228+
}
229+
req, err := http.NewRequest("GET", url, nil)
230+
if err != nil {
231+
return err
232+
}
233+
if headers != nil {
234+
for k, v := range headers {
235+
req.Header.Set(k, v)
236+
}
237+
}
238+
if _, ok := headers["User-Agent"]; ok {
239+
req.Header["User-Agent"] = []string{UserAgent}
240+
}
241+
req.Header.Set("range", "bytes=0-")
242+
resp, err := client.Do(req)
243+
if err != nil {
244+
return err
245+
}
246+
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
247+
return errors.New("response status unsuccessful: " + strconv.FormatInt(int64(resp.StatusCode), 10))
248+
}
249+
if resp.StatusCode == 200 {
250+
if limit > 0 && resp.ContentLength > limit {
251+
return ErrOverSize
252+
}
253+
return copyStream(resp.Body)
254+
}
255+
if resp.StatusCode == 206 {
256+
contentLength = resp.ContentLength
257+
if limit > 0 && resp.ContentLength > limit {
258+
return ErrOverSize
259+
}
260+
blockSize := func() int64 {
261+
if contentLength > 1024*1024 {
262+
return (contentLength / int64(threadCount)) - 10
263+
} else {
264+
return contentLength
265+
}
266+
}()
267+
if blockSize == contentLength {
268+
return copyStream(resp.Body)
269+
}
270+
var tmp int64
271+
for tmp+blockSize < contentLength {
272+
blocks = append(blocks, &BlockMetaData{
273+
BeginOffset: tmp,
274+
EndOffset: tmp + blockSize - 1,
275+
})
276+
tmp += blockSize
277+
}
278+
blocks = append(blocks, &BlockMetaData{
279+
BeginOffset: tmp,
280+
EndOffset: contentLength - 1,
281+
})
282+
return nil
283+
}
284+
return errors.New("unknown status code.")
285+
}
286+
// 下载分块
287+
downloadBlock := func(block *BlockMetaData) error {
288+
req, _ := http.NewRequest("GET", url, nil)
289+
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666)
290+
if err != nil {
291+
return err
292+
}
293+
defer file.Close()
294+
_, _ = file.Seek(block.BeginOffset, io.SeekStart)
295+
writer := bufio.NewWriter(file)
296+
defer writer.Flush()
297+
if headers != nil {
298+
for k, v := range headers {
299+
req.Header.Set(k, v)
300+
}
301+
}
302+
if _, ok := headers["User-Agent"]; ok {
303+
req.Header["User-Agent"] = []string{UserAgent}
304+
}
305+
req.Header.Set("range", "bytes="+strconv.FormatInt(block.BeginOffset, 10)+"-"+strconv.FormatInt(block.EndOffset, 10))
306+
resp, err := client.Do(req)
307+
if err != nil {
308+
return err
309+
}
310+
defer resp.Body.Close()
311+
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
312+
return errors.New("response status unsuccessful: " + strconv.FormatInt(int64(resp.StatusCode), 10))
313+
}
314+
var buffer = make([]byte, 1024)
315+
i, err := resp.Body.Read(buffer)
316+
for {
317+
if err != nil && err != io.EOF {
318+
return err
319+
}
320+
i64 := int64(len(buffer[:i]))
321+
needSize := block.EndOffset + 1 - block.BeginOffset
322+
if i64 > needSize {
323+
i64 = needSize
324+
err = io.EOF
325+
}
326+
_, e := writer.Write(buffer[:i64])
327+
if e != nil {
328+
return e
329+
}
330+
block.BeginOffset += i64
331+
block.DownloadedSize += i64
332+
if err == io.EOF || block.BeginOffset > block.EndOffset {
333+
break
334+
}
335+
i, err = resp.Body.Read(buffer)
336+
}
337+
return nil
338+
}
339+
340+
if err := initOrDownload(); err != nil {
341+
if err == errUnsupportedMultiThreading {
342+
return nil
343+
}
344+
return err
345+
}
346+
wg := sync.WaitGroup{}
347+
wg.Add(len(blocks))
348+
var lastErr error
349+
for i := range blocks {
350+
go func(b *BlockMetaData) {
351+
defer wg.Done()
352+
if err := downloadBlock(b); err != nil {
353+
lastErr = err
354+
}
355+
}(blocks[i])
356+
}
357+
wg.Wait()
358+
return lastErr
359+
}

service/bot/proto2mirai.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010

1111
"github.com/Mrs4s/MiraiGo/client"
1212
"github.com/Mrs4s/MiraiGo/message"
13-
"github.com/Mrs4s/go-cqhttp/global"
1413
"github.com/ProtobufBot/Go-Mirai-Client/pkg/clz"
1514
"github.com/ProtobufBot/Go-Mirai-Client/pkg/util"
1615
"github.com/ProtobufBot/Go-Mirai-Client/proto_gen/onebot"
@@ -333,14 +332,14 @@ func ProtoVideoToMiraiVideo(cli *client.QQClient, data map[string]string) (m mes
333332
}
334333
}
335334
filepath := path.Join("video", util.MustMd5(url)+".mp4")
336-
if global.PathExists(filepath) {
335+
if util.PathExists(filepath) {
337336
if err := os.Remove(filepath); err != nil {
338337
log.Errorf("删除缓存文件 %v 时出现错误: %v", filepath, err)
339338
return EmptyText()
340339
}
341340
}
342341
//videoBytes, err := util.GetBytes(url)
343-
if err := global.DownloadFileMultiThreading(url, filepath, 100*1024*1024, 8, nil); err != nil {
342+
if err := util.DownloadFileMultiThreading(url, filepath, 100*1024*1024, 8, nil); err != nil {
344343
log.Errorf("failed to download video file, err: %+v", err)
345344
return EmptyText()
346345
}

0 commit comments

Comments
 (0)