Skip to content

Commit

Permalink
feat: add file download for telegram.
Browse files Browse the repository at this point in the history
  • Loading branch information
syhily committed Nov 15, 2022
1 parent b689380 commit 8cb1373
Show file tree
Hide file tree
Showing 14 changed files with 288 additions and 129 deletions.
36 changes: 23 additions & 13 deletions internal/driver/aliyun.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,35 +44,45 @@ func (a *aliyunDriver) Source() Source {
}

func (a *aliyunDriver) Resolve(shareLink string, passcode string) ([]Share, error) {
c := a.client
token, err := c.ShareToken(shareLink, passcode)
token, err := a.client.ShareToken(shareLink, passcode)
if err != nil {
return nil, err
}
shareFiles, err := c.Share(shareLink, token.ShareToken)

files, err := a.client.Share(shareLink, token.ShareToken)
if err != nil {
return nil, err
}

var shares []Share
for index := range shareFiles {
item := shareFiles[index]
shares = append(shares, Share{
for index := range files {
item := files[index]
share := Share{
FileName: item.Name,
Size: int64(item.Size),
URL: item.FileID,
Properties: map[string]string{
Properties: map[string]any{
"shareToken": token.ShareToken,
"shareID": shareLink,
"fileID": item.FileID,
},
})
}

shares = append(shares, share)
}

return shares, nil
}

func (a *aliyunDriver) Download(share Share) (io.ReadCloser, int64, error) {
c := a.client
url, err := c.DownloadURL(share.Properties["shareToken"], share.Properties["shareID"], share.URL)
func (a *aliyunDriver) Download(share Share) (io.ReadCloser, error) {
shareToken := share.Properties["shareToken"].(string)
shareID := share.Properties["shareID"].(string)
fileID := share.Properties["fileID"].(string)

url, err := a.client.DownloadURL(shareToken, shareID, fileID)
if err != nil {
return nil, 0, err
return nil, err
}
return c.DownloadFile(url)

return a.client.DownloadFile(url)
}
10 changes: 6 additions & 4 deletions internal/driver/aliyun/share.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (ali *Aliyun) ShareToken(shareID string, sharePwd string) (*ShareTokenResp,
return resp.Result().(*ShareTokenResp), nil
}

func (ali *Aliyun) DownloadURL(shareToken string, shareID string, fileID string) (string, error) {
func (ali *Aliyun) DownloadURL(shareToken, shareID, fileID string) (string, error) {
token, err := ali.AuthToken()
if err != nil {
return "", err
Expand All @@ -143,13 +143,15 @@ func (ali *Aliyun) DownloadURL(shareToken string, shareID string, fileID string)
return res.DownloadURL, nil
}

func (ali *Aliyun) DownloadFile(downloadURL string) (io.ReadCloser, int64, error) {
func (ali *Aliyun) DownloadFile(downloadURL string) (io.ReadCloser, error) {
log.Debugf("Start to download file from aliyun drive: %s", downloadURL)

resp, err := ali.client.R().
SetDoNotParseResponse(true).
Get(downloadURL)
response := resp.RawResponse
if err != nil {
return nil, err
}

return response.Body, response.ContentLength, err
return resp.RawBody(), err
}
6 changes: 4 additions & 2 deletions internal/driver/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ type (
Share struct {
// FileName is a file name with the file extension.
FileName string
// Size is the file size in bytes.
Size int64
// URL is the downloadable url for this file.
URL string
// Properties could be some metadata, such as the token for this downloadable share.
Properties map[string]string
Properties map[string]any
}

// Driver is used to resolve the links from a Source.
Expand All @@ -30,7 +32,7 @@ type (
Resolve(shareLink string, passcode string) ([]Share, error)

// Download the given link.
Download(share Share) (io.ReadCloser, int64, error)
Download(share Share) (io.ReadCloser, error)
}
)

Expand Down
12 changes: 9 additions & 3 deletions internal/driver/lanzou.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package driver

import (
"errors"
"fmt"
"io"

Expand All @@ -14,7 +15,7 @@ func newLanzouDriver(c *client.Config, _ map[string]string) (Driver, error) {
return nil, err
}

return &lanzouDriver{driver: drive}, nil
return &lanzouDriver{driver: drive}, errors.New("we don't support lanzou currently")
}

type lanzouDriver struct {
Expand All @@ -34,9 +35,14 @@ func (l *lanzouDriver) Resolve(shareLink string, passcode string) ([]Share, erro
return nil, fmt.Errorf("parsed faild: %v", resp.Msg)
}

return []Share{{FileName: resp.Data.Name, URL: resp.Data.URL, Properties: nil}}, err
share := Share{
FileName: resp.Data.Name,
URL: resp.Data.URL,
}

return []Share{share}, err
}

func (l *lanzouDriver) Download(share Share) (io.ReadCloser, int64, error) {
func (l *lanzouDriver) Download(share Share) (io.ReadCloser, error) {
return l.driver.DownloadFile(share.URL)
}
8 changes: 5 additions & 3 deletions internal/driver/lanzou/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@ func NewDrive(config *client.Config) (*Drive, error) {
return &Drive{client: cl}, nil
}

func (l *Drive) DownloadFile(downloadURL string) (io.ReadCloser, int64, error) {
func (l *Drive) DownloadFile(downloadURL string) (io.ReadCloser, error) {
log.Debugf("Start to download file from aliyun drive: %s", downloadURL)

resp, err := l.client.R().
SetDoNotParseResponse(true).
Get(downloadURL)
response := resp.RawResponse
if err != nil {
return nil, err
}

return response.Body, response.ContentLength, err
return resp.RawBody(), err
}
21 changes: 10 additions & 11 deletions internal/driver/telecom.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,32 +42,31 @@ func (t *telecomDriver) Resolve(shareLink string, passcode string) ([]Share, err
for _, file := range files {
shares = append(shares, Share{
FileName: file.Name,
Properties: map[string]string{
"fileID": strconv.FormatInt(file.ID, 10),
"shareID": strconv.FormatInt(info.ShareID, 10),
Size: file.Size,
Properties: map[string]any{
"shareCode": code,
"fileSize": strconv.FormatInt(file.Size, 10),
"shareID": strconv.FormatInt(info.ShareID, 10),
"fileID": strconv.FormatInt(file.ID, 10),
},
})
}

return shares, nil
}

func (t *telecomDriver) Download(share Share) (io.ReadCloser, int64, error) {
shareCode := share.Properties["shareCode"]
shareID := share.Properties["shareID"]
fileID := share.Properties["fileID"]
size, _ := strconv.ParseInt(share.Properties["fileSize"], 10, 64)
func (t *telecomDriver) Download(share Share) (io.ReadCloser, error) {
shareCode := share.Properties["shareCode"].(string)
shareID := share.Properties["shareID"].(string)
fileID := share.Properties["fileID"].(string)

// Resolve the link.
url, err := t.client.DownloadURL(shareCode, shareID, fileID)
if err != nil {
return nil, 0, err
return nil, err
}

// Download the file.
file, err := t.client.DownloadFile(url)

return file, size, err
return file, err
}
13 changes: 3 additions & 10 deletions internal/fetcher/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,6 @@ func (f *commonFetcher) startDownload() {

// downloadFile in a thread.
func (f *commonFetcher) downloadFile(bookID int64, format Format, share driver.Share) error {
file, err := f.service.fetch(bookID, format, share)
if err != nil {
return err
}
defer func() { _ = file.content.Close() }()

// Rename if it was required.
prefix := strconv.FormatInt(bookID, 10)
if f.Rename {
Expand Down Expand Up @@ -160,12 +154,11 @@ func (f *commonFetcher) downloadFile(bookID int64, format Format, share driver.S
defer func() { _ = writer.Close() }()

// Add download progress.
bar := log.NewProgressBar(bookID, f.progress.Size(), share.FileName, file.size)
bar := log.NewProgressBar(bookID, f.progress.Size(), share.FileName, share.Size)
defer func() { _ = bar.Close() }()

// Write file content
_, err = io.Copy(io.MultiWriter(writer, bar), file.content)
if err != nil {
// Write file content.
if err := f.service.fetch(bookID, format, share, io.MultiWriter(writer, bar)); err != nil {
return err
}

Expand Down
15 changes: 8 additions & 7 deletions internal/fetcher/sanqiu.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package fetcher

import (
"errors"
"io"
"strconv"

"github.com/bookstairs/bookhunter/internal/client"
Expand Down Expand Up @@ -110,14 +111,14 @@ func (s *sanqiuService) formats(id int64) (map[Format]driver.Share, error) {
return map[Format]driver.Share{}, nil
}

func (s *sanqiuService) fetch(id int64, format Format, share driver.Share) (*fetch, error) {
content, size, err := s.driver.Download(share)
func (s *sanqiuService) fetch(_ int64, _ Format, share driver.Share, writer io.Writer) error {
content, err := s.driver.Download(share)
if err != nil {
return nil, err
return err
}
defer func() { _ = content.Close() }()

return &fetch{
content: content,
size: size,
}, nil
// Save the download content info files.
_, err = io.Copy(writer, content)
return err
}
18 changes: 1 addition & 17 deletions internal/fetcher/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"fmt"
"io"

"github.com/go-resty/resty/v2"

"github.com/bookstairs/bookhunter/internal/driver"
)

Expand All @@ -19,21 +17,7 @@ type service interface {
formats(int64) (map[Format]driver.Share, error)

// fetch the given book ID.
fetch(int64, Format, driver.Share) (*fetch, error)
}

// fetch is the result which can be created from a resty.Response
type fetch struct {
content io.ReadCloser
size int64
}

// createFetch will try to create a fetch. Remember to create the response with the `SetDoNotParseResponse` option.
func createFetch(resp *resty.Response) *fetch {
return &fetch{
content: resp.RawBody(),
size: resp.RawResponse.ContentLength,
}
fetch(int64, Format, driver.Share, io.Writer) error
}

// newService is the endpoint for creating all the supported download service.
Expand Down
11 changes: 8 additions & 3 deletions internal/fetcher/talebook.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package fetcher
import (
"errors"
"fmt"
"io"
"net/http"
"strconv"
"strings"
Expand Down Expand Up @@ -132,13 +133,17 @@ func (t *talebookService) formats(id int64) (map[Format]driver.Share, error) {
}
}

func (t *talebookService) fetch(_ int64, _ Format, share driver.Share) (*fetch, error) {
func (t *talebookService) fetch(_ int64, _ Format, share driver.Share, writer io.Writer) error {
resp, err := t.client.R().
SetDoNotParseResponse(true).
Get(share.URL)
if err != nil {
return nil, err
return err
}
body := resp.RawBody()
defer func() { _ = body.Close() }()

return createFetch(resp), nil
// Save the download content info files.
_, err = io.Copy(writer, body)
return err
}

0 comments on commit 8cb1373

Please sign in to comment.