├── .github └── workflows │ └── build.yml ├── .gitignore ├── LICENSE ├── README.md ├── cmd └── gdown │ ├── cli.go │ └── main.go ├── go.mod ├── go.sum ├── internal ├── helpers │ ├── auth │ │ ├── client.go │ │ └── token.go │ └── webscraping │ │ └── webscraping.go ├── process │ ├── account.go │ └── functions.go └── utils │ ├── clienthttp.go │ ├── output.go │ └── utils.go ├── module.go └── pkg └── gdriveapi ├── files.go └── permissions.go /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | tags: 4 | - 'v*' 5 | 6 | name: Build & Upload Release Asset 7 | 8 | jobs: 9 | build: 10 | name: Build & Upload Release Asset 11 | runs-on: ubuntu-latest 12 | steps: 13 | 14 | - name: Set up Go 1.13 15 | uses: actions/setup-go@v1 16 | with: 17 | go-version: 1.13 18 | id: go 19 | 20 | - name: Check out code into the Go module directory 21 | uses: actions/checkout@v2 22 | 23 | - name: Get dependencies 24 | run: | 25 | go get -v -t -d ./... 26 | if [ -f Gopkg.toml ]; then 27 | curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh 28 | dep ensure 29 | fi 30 | 31 | - name: Get the version 32 | id: get_version 33 | run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} 34 | 35 | - name: Building 36 | run: | 37 | GOOS=darwin GOARCH=amd64 go build -v -o gdown ./cmd/gdown/ 38 | zip --junk-paths gdown_${{ steps.get_version.outputs.VERSION }}_macos.zip gdown 39 | 40 | GOOS=windows GOARCH=386 go build -v -o gdown.exe ./cmd/gdown/ 41 | zip --junk-paths gdown_${{ steps.get_version.outputs.VERSION }}_windows-x86.zip gdown.exe 42 | 43 | GOOS=windows GOARCH=amd64 go build -v -o gdown.exe ./cmd/gdown/ 44 | zip --junk-paths gdown_${{ steps.get_version.outputs.VERSION }}_windows-x64.zip gdown.exe 45 | 46 | GOOS=linux GOARCH=amd64 go build -v -o gdown ./cmd/gdown/ 47 | zip --junk-paths gdown_${{ steps.get_version.outputs.VERSION }}_linux-x64.zip gdown 48 | 49 | - name: Create Release 50 | id: create_release 51 | uses: actions/create-release@v1 52 | env: 53 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 54 | with: 55 | tag_name: ${{ github.ref }} 56 | release_name: Release ${{ github.ref }} 57 | draft: false 58 | prerelease: false 59 | 60 | - name: Upload macOS Asset 61 | uses: actions/upload-release-asset@v1 62 | env: 63 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 64 | with: 65 | upload_url: ${{ steps.create_release.outputs.upload_url }} 66 | asset_path: ./gdown_${{ steps.get_version.outputs.VERSION }}_macos.zip 67 | asset_name: gdown_${{ steps.get_version.outputs.VERSION }}_macos.zip 68 | asset_content_type: application/x-msdownload 69 | 70 | - name: Upload Windows x86 71 | uses: actions/upload-release-asset@v1 72 | env: 73 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 74 | with: 75 | upload_url: ${{ steps.create_release.outputs.upload_url }} 76 | asset_path: ./gdown_${{ steps.get_version.outputs.VERSION }}_windows-x86.zip 77 | asset_name: gdown_${{ steps.get_version.outputs.VERSION }}_windows-x86.zip 78 | asset_content_type: application/x-msdownload 79 | 80 | - name: Upload Windows x64 81 | uses: actions/upload-release-asset@v1 82 | env: 83 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 84 | with: 85 | upload_url: ${{ steps.create_release.outputs.upload_url }} 86 | asset_path: ./gdown_${{ steps.get_version.outputs.VERSION }}_windows-x64.zip 87 | asset_name: gdown_${{ steps.get_version.outputs.VERSION }}_windows-x64.zip 88 | asset_content_type: application/x-msdownload 89 | 90 | - name: Upload linux x64 91 | uses: actions/upload-release-asset@v1 92 | env: 93 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 94 | with: 95 | upload_url: ${{ steps.create_release.outputs.upload_url }} 96 | asset_path: ./gdown_${{ steps.get_version.outputs.VERSION }}_linux-x64.zip 97 | asset_name: gdown_${{ steps.get_version.outputs.VERSION }}_linux-x64.zip 98 | asset_content_type: application/x-msdownload -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | 17 | *.txt 18 | *.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Juvenal Yescas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Gdown logo 4 |

Gdown

5 | 6 |

7 |

8 | Directly download google drive public files from the command line 9 |
10 | Explore docs » 11 |
12 |
13 | Report bug 14 | · 15 | Request feature 16 |

17 | 18 | ![Actions Status](https://github.com/Juvenal-Yescas/gdown/workflows/Tests/badge.svg) 19 | [![GitHub issues](https://img.shields.io/github/issues/Juvenal-Yescas/gdown)](https://github.com/Juvenal-Yescas/gdown/issues) 20 | [![DeepSource](https://static.deepsource.io/deepsource-badge-light-mini.svg)](https://deepsource.io/gh/Juvenal-Yescas/gdown/?ref=repository-badge) 21 | [![GitHub license](https://img.shields.io/github/license/Juvenal-Yescas/gdown)](LICENSE) 22 | 23 | ## Table of contents 24 | 25 | - [Usage](#usage) 26 | - [Contributing](#contributing) 27 | - [License](#license) 28 | - [Acknowledgments](#acknowledgments) 29 | 30 | ## Usage 31 | 32 | Download the latest [release](https://github.com/Juvenal-Yescas/gdown/releases) 33 | 34 | ### From Command Line 35 | 36 | ``` 37 | Windows 38 | gdown.exe --help 39 | 40 | macOS or linux 41 | gdown --help 42 | ``` 43 | 44 | ``` 45 | gdown "0B4y35FiV1wh7QWpuVlFROXlBTHc" 46 | gdown "https://drive.google.com/uc?id=0B9P1L--7Wd2vU3VUVlFnbTgtS2c" 47 | gdown "https://drive.google.com/open?id=0B7EVK8r0v71pZjFTYXZWM3FlRnM" 48 | gdown "https://drive.google.com/open?id=0B4y35FiV1wh7QWpuVlFROXlBTHc" 49 | gdown "https://drive.google.com/file/d/0B4y35FiV1wh7QWpuVlFROXlBTHc/view?usp=sharing" 50 | gdown "https://drive.google.com/file/d/0B4y35FiV1wh7QWpuVlFROXlBTHc/view" 51 | gdown "https://drive.google.com/file/d/0B65DIm6DrZJceGltX2VOczNkcEE/edit" 52 | ``` 53 | 54 | ## Build with 55 | 56 | * [Go](https://golang.org/) - Programming language 57 | 58 | ## Contributing 59 | 60 | Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us. 61 | 62 | ## License 63 | 64 | This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. 65 | 66 | ## Acknowledgments 67 | 68 | * [gdown](https://github.com/wkentaro/gdown) 69 | -------------------------------------------------------------------------------- /cmd/gdown/cli.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/Juvenal-Yescas/gdown" 6 | "github.com/Juvenal-Yescas/gdown/internal/helpers/auth" 7 | "github.com/Juvenal-Yescas/gdown/internal/process" 8 | "github.com/Juvenal-Yescas/gdown/internal/utils" 9 | "os" 10 | ) 11 | 12 | func cliDownload(url string) { 13 | output, err := gdown.Download(url) 14 | if err != nil { 15 | if utils.CaseInsensitiveContains(err.Error(), "exceeded") { 16 | fmt.Println("The file has exceeded the download limit, try download with your account") 17 | output, err := downloadWithAccount(url) 18 | if err != nil { 19 | fmt.Println("Error : ", err) 20 | os.Exit(1) 21 | } 22 | fmt.Println("File downloaded : ", output) 23 | os.Exit(0) 24 | } 25 | fmt.Println("Error : ", err) 26 | os.Exit(1) 27 | 28 | } 29 | fmt.Println("File downloaded: ", output) 30 | os.Exit(0) 31 | } 32 | 33 | func downloadWithAccount(url string) (string, error) { 34 | idFileUrl, err := process.GetIdFromUrl(url) 35 | if err != nil { 36 | return "", err 37 | } 38 | 39 | clientHttp := utils.CreateClientHttp() 40 | outputName, err := process.GetNameOutput(clientHttp, idFileUrl) 41 | if err != nil { 42 | return "", err 43 | } 44 | 45 | clientGDrive, err := auth.CreateClientApiDrive() 46 | if err != nil { 47 | return "", err 48 | } 49 | infoFolderDrive, infoFileDrive, err := process.CreateCopyInDrive(clientGDrive, idFileUrl, outputName) 50 | if err != nil { 51 | return "", err 52 | } 53 | fmt.Println("Downloading ... ", outputName) 54 | output, err := gdown.DownloadOutput("https://drive.google.com/uc?id="+infoFileDrive.Id, outputName) 55 | if err != nil { 56 | return "", err 57 | } 58 | 59 | err = process.CleanCopyInDrive(clientGDrive, infoFolderDrive.Id) 60 | if err != nil { 61 | return "", err 62 | } 63 | 64 | return output, nil 65 | } 66 | -------------------------------------------------------------------------------- /cmd/gdown/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | log "github.com/sirupsen/logrus" 6 | "github.com/urfave/cli/v2" 7 | "io/ioutil" 8 | "os" 9 | ) 10 | 11 | func init() { 12 | log.SetOutput(ioutil.Discard) 13 | // log.SetLevel(log.DebugLevel) 14 | } 15 | 16 | const Version = "0.1.0" 17 | 18 | func main() { 19 | 20 | cli.VersionFlag = &cli.BoolFlag{ 21 | Name: "print-version", Aliases: []string{"V"}, 22 | Usage: "print only the version", 23 | } 24 | 25 | app := &cli.App{ 26 | Name: "gdown", 27 | Version: Version, 28 | Usage: "Download files directly from googledrive", 29 | 30 | Flags: []cli.Flag{ 31 | &cli.StringFlag{ 32 | Name: "url", 33 | Aliases: []string{"u"}, 34 | Usage: "`\"FILEURL\"` to download from google drive ", 35 | }, 36 | }, 37 | Action: func(c *cli.Context) error { 38 | if c.String("url") != "" { 39 | cliDownload(c.String("url")) 40 | } 41 | if c.NArg() > 0 { 42 | link := c.Args().Get(0) 43 | cliDownload(link) 44 | } 45 | return nil 46 | }, 47 | } 48 | 49 | err := app.Run(os.Args) 50 | if err != nil { 51 | log.Fatal(err) 52 | } 53 | fmt.Println("gdown --help") 54 | } 55 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/Juvenal-Yescas/gdown 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/sirupsen/logrus v1.4.2 7 | github.com/urfave/cli/v2 v2.1.1 8 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b 9 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d 10 | google.golang.org/api v0.19.0 11 | ) 12 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0 h1:ROfEUZz+Gh5pa62DJWXSaonyu3StP6EA6lPEXPI6mCo= 4 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 5 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 6 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 7 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 8 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= 9 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 10 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 12 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 13 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 14 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 15 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 16 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 17 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 18 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 19 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 20 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 21 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 22 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 23 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 24 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 25 | github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= 26 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 27 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 28 | github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= 29 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 30 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 31 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 32 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 33 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 34 | github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= 35 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 36 | github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= 37 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 38 | github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= 39 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 40 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 41 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 42 | github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= 43 | github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= 44 | github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= 45 | go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg= 46 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 47 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 48 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 49 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 50 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 51 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 52 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 53 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 54 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 55 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 56 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 57 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 58 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 59 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 60 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= 61 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 62 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 63 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 64 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 65 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= 66 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 67 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 68 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 69 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 70 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 71 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 72 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 73 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 74 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= 75 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 76 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA= 77 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 78 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 79 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 80 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= 81 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 82 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 83 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 84 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 85 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 86 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 87 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 88 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 89 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 90 | google.golang.org/api v0.19.0 h1:GwFK8+l5/gdsOYKz5p6M4UK+QT8OvmHWZPJCnf+5DjA= 91 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 92 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 93 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 94 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 95 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 96 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 97 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 98 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= 99 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 100 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 101 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 102 | google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= 103 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 104 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 105 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 106 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 107 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 108 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 109 | -------------------------------------------------------------------------------- /internal/helpers/auth/client.go: -------------------------------------------------------------------------------- 1 | // refs https://developers.google.com/drive/v3/web/quickstart/go 2 | package auth 3 | 4 | import ( 5 | "github.com/Juvenal-Yescas/gdown/internal/utils" 6 | "golang.org/x/net/context" 7 | "golang.org/x/oauth2" 8 | "golang.org/x/oauth2/google" 9 | "google.golang.org/api/drive/v3" 10 | "io/ioutil" 11 | "log" 12 | "net/http" 13 | ) 14 | 15 | func CreateClientApiDrive() (*drive.Service, error) { 16 | b, err := ioutil.ReadFile("credentials.json") 17 | if err != nil { 18 | log.Fatalf("Unable to read client secret file: %v", err) 19 | return nil, err 20 | } 21 | 22 | // If modifying these scopes, delete your previously saved token.json. 23 | config, err := google.ConfigFromJSON(b, drive.DriveScope) 24 | if err != nil { 25 | log.Fatalf("Unable to parse client secret file to config: %v", err) 26 | return nil, err 27 | } 28 | 29 | client := getClient(config) 30 | 31 | srv, err := drive.New(client) 32 | if err != nil { 33 | log.Fatalf("Unable to retrieve Drive client: %v", err) 34 | return nil, err 35 | } 36 | return srv, nil 37 | } 38 | 39 | // Retrieve a token, saves the token, then returns the generated client. 40 | func getClient(config *oauth2.Config) *http.Client { 41 | // The file token.json stores the user's access and refresh tokens, and is 42 | // created automatically when the authorization flow completes for the first 43 | // time. 44 | 45 | tokFile := utils.GetDefaultConfigDir() // tokFile := "token.json" 46 | tok, err := tokenFromFile(tokFile) 47 | if err != nil { 48 | tok = getTokenFromWeb(config) 49 | saveToken(tokFile, tok) 50 | } 51 | return config.Client(context.Background(), tok) 52 | } 53 | -------------------------------------------------------------------------------- /internal/helpers/auth/token.go: -------------------------------------------------------------------------------- 1 | // refs https://developers.google.com/drive/v3/web/quickstart/go 2 | package auth 3 | 4 | import ( 5 | "encoding/json" 6 | "fmt" 7 | log "github.com/sirupsen/logrus" 8 | "golang.org/x/net/context" 9 | "golang.org/x/oauth2" 10 | "os" 11 | ) 12 | 13 | // Request a token from the web, then returns the retrieved token. 14 | func getTokenFromWeb(config *oauth2.Config) *oauth2.Token { 15 | authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline) 16 | log.Debug("Go to the following link in your browser then type the "+ 17 | "authorization code: \n", authURL) 18 | 19 | var authCode string 20 | if _, err := fmt.Scan(&authCode); err != nil { 21 | log.Error("Unable to read authorization code %v", err) 22 | } 23 | 24 | tok, err := config.Exchange(context.TODO(), authCode) 25 | if err != nil { 26 | log.Error("Unable to retrieve token from web %v", err) 27 | } 28 | return tok 29 | } 30 | 31 | // Retrieves a token from a local file. 32 | func tokenFromFile(file string) (*oauth2.Token, error) { 33 | f, err := os.Open(file) 34 | if err != nil { 35 | return nil, err 36 | } 37 | defer f.Close() 38 | tok := &oauth2.Token{} 39 | err = json.NewDecoder(f).Decode(tok) 40 | return tok, err 41 | } 42 | 43 | // Saves a token to a file path. 44 | func saveToken(path string, token *oauth2.Token) { 45 | log.Debug("Saving credential file to: ", path) 46 | f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) 47 | if err != nil { 48 | log.Fatalf("Unable to cache oauth token: %v", err) 49 | } 50 | defer f.Close() 51 | json.NewEncoder(f).Encode(token) 52 | } 53 | -------------------------------------------------------------------------------- /internal/helpers/webscraping/webscraping.go: -------------------------------------------------------------------------------- 1 | package webscraping 2 | 3 | import ( 4 | log "github.com/sirupsen/logrus" 5 | "golang.org/x/net/html" 6 | "io" 7 | "net/http" 8 | ) 9 | 10 | func GetTittle(client *http.Client, link string) string { 11 | resp, err := client.Get(link) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | defer resp.Body.Close() 17 | 18 | if title, ok := getHtmlTitle(resp.Body); ok { 19 | log.Debug("Tittle website: ", title) 20 | return title 21 | } else { 22 | println("Fail to get HTML title") 23 | } 24 | 25 | return "" 26 | } 27 | 28 | func getHtmlTitle(r io.Reader) (string, bool) { 29 | doc, err := html.Parse(r) 30 | if err != nil { 31 | panic("Fail to parse html") 32 | } 33 | 34 | return traverse(doc) 35 | } 36 | 37 | func traverse(n *html.Node) (string, bool) { 38 | if isTitleElement(n) { 39 | return n.FirstChild.Data, true 40 | } 41 | 42 | for c := n.FirstChild; c != nil; c = c.NextSibling { 43 | result, ok := traverse(c) 44 | if ok { 45 | return result, ok 46 | } 47 | } 48 | 49 | return "", false 50 | } 51 | 52 | func isTitleElement(n *html.Node) bool { 53 | return n.Type == html.ElementNode && n.Data == "title" 54 | } 55 | -------------------------------------------------------------------------------- /internal/process/account.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | import ( 4 | // "github.com/Juvenal-Yescas/gdown/internal/helpers/auth" 5 | "github.com/Juvenal-Yescas/gdown/pkg/gdriveapi" 6 | "google.golang.org/api/drive/v3" 7 | ) 8 | 9 | func CreateCopyInDrive(clientGDrive *drive.Service, idFile string, outputName string) (*drive.File, *drive.File, error) { 10 | idFolder, err := gdriveapi.CreateFolder(clientGDrive, "gdown") 11 | if err != nil { 12 | return nil, nil, err 13 | } 14 | 15 | _, err = gdriveapi.MakeSharedFolder(clientGDrive, idFolder.Id) 16 | if err != nil { 17 | return idFolder, nil, err 18 | } 19 | arrayFolder := []string{idFolder.Id} 20 | 21 | idFileCopied, err := gdriveapi.CreateACopy(clientGDrive, idFile, outputName, arrayFolder) 22 | if err != nil { 23 | return idFolder, nil, err 24 | } 25 | 26 | return idFolder, idFileCopied, nil 27 | } 28 | 29 | func CleanCopyInDrive(clientGDrive *drive.Service, idFolder string) error { 30 | err := gdriveapi.Delete(clientGDrive, idFolder) 31 | return err 32 | } 33 | 34 | // func SkipQuotaExceeded(clientWeb *http.Client, idFile string, outputName string) (string, error) { 35 | // client, err := auth.CreateClient() 36 | // if err != nil { 37 | // return "", err 38 | // } 39 | 40 | // log.Debug("Try download again") 41 | // output, err := StartDownload(clientWeb, idFileCopied.Id, outputName) 42 | // if err != nil { 43 | // return "", err 44 | // } 45 | 46 | // err = gdriveapi.Delete(client, idFolder.Id) 47 | // if err != nil { 48 | // return "", err 49 | // } 50 | // return output, err 51 | // } 52 | -------------------------------------------------------------------------------- /internal/process/functions.go: -------------------------------------------------------------------------------- 1 | package process 2 | 3 | import ( 4 | "errors" 5 | "github.com/Juvenal-Yescas/gdown/internal/helpers/webscraping" 6 | "github.com/Juvenal-Yescas/gdown/internal/utils" 7 | log "github.com/sirupsen/logrus" 8 | "io/ioutil" 9 | "net/http" 10 | "regexp" 11 | "strings" 12 | ) 13 | 14 | func GetUrlConfirmation(clientHttp *http.Client, idFile string) (string, error) { 15 | 16 | urlGoogleDrive := "https://drive.google.com/uc?id=" + idFile 17 | 18 | // Generate cookie 19 | resp, err := clientHttp.Get(urlGoogleDrive) 20 | if err != nil { 21 | log.Error("Client get : %v", err) 22 | return "", err 23 | } 24 | 25 | defer resp.Body.Close() 26 | 27 | var urlDirect string 28 | 29 | if len(resp.Cookies()) == 0 { 30 | 31 | data, _ := ioutil.ReadAll(resp.Body) 32 | bodyString := string(data) 33 | 34 | if utils.CaseInsensitiveContains(bodyString, "exceeded") { 35 | log.Info("Google Drive - Quota exceeded : Try download using your account...") 36 | log.Debug(urlGoogleDrive) 37 | return "", errors.New("This file is limited: Quota exceeded") 38 | } 39 | // small file 40 | return urlGoogleDrive, nil 41 | } 42 | 43 | // big file 44 | codeConfirmation := resp.Cookies()[0].Value 45 | urlDirect = urlGoogleDrive + "&confirm=" + codeConfirmation 46 | return urlDirect, nil 47 | } 48 | 49 | func StartDownload(clientHttp *http.Client, urlDirect string, outputName string) (string, error) { 50 | log.Info("Downloading ... ", outputName) 51 | 52 | fileOutput, err := utils.CreateFile(outputName) 53 | if err != nil { 54 | return "", err 55 | } 56 | 57 | resp, err := clientHttp.Get(urlDirect) 58 | if err != nil { 59 | log.Error("Client get : %v", err) 60 | return "", err 61 | } 62 | 63 | defer resp.Body.Close() 64 | _, err = utils.WriteToOutput(fileOutput, resp.Body) 65 | if err != nil { 66 | log.Error("Write data error : %v", err) 67 | return "", err 68 | } 69 | return outputName, nil 70 | } 71 | 72 | func GetIdFromUrl(url string) (string, error) { 73 | if utils.CaseInsensitiveContains(url, "google.com") { 74 | if utils.CaseInsensitiveContains(url, "id") { 75 | arrayUrl := strings.Split(url, "=") 76 | if utils.CaseInsensitiveContains(arrayUrl[1], "export") { 77 | arrayUrl := strings.Split(arrayUrl[1], "&") 78 | return arrayUrl[0], nil 79 | } 80 | return arrayUrl[1], nil 81 | } else if utils.CaseInsensitiveContains(url, "docs") { 82 | log.Error("Documents not implemented") 83 | return "", errors.New("Documents not implemented") 84 | } else { 85 | arrayUrl := strings.Split(url, "/") 86 | return arrayUrl[5], nil 87 | } 88 | } 89 | return url, nil 90 | } 91 | 92 | func GetNameOutput(client *http.Client, idFile string) (string, error) { 93 | urlOpen := "https://drive.google.com/open?id=" + idFile 94 | 95 | tittleWebsite := webscraping.GetTittle(client, urlOpen) 96 | 97 | extraTittle := regexp.MustCompile(" - Google Drive") 98 | outputName := extraTittle.ReplaceAllString(tittleWebsite, "") 99 | log.Debug("Correct name output: ", outputName) 100 | 101 | if outputName == "" { 102 | return "", errors.New("Tittle dont found") 103 | } 104 | return outputName, nil 105 | } 106 | -------------------------------------------------------------------------------- /internal/utils/clienthttp.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "net/http" 5 | "net/http/cookiejar" 6 | ) 7 | 8 | func CreateClientHttp() *http.Client { 9 | cookieJar, _ := cookiejar.New(nil) 10 | client := &http.Client{ 11 | Jar: cookieJar, 12 | CheckRedirect: func(r *http.Request, via []*http.Request) error { 13 | r.URL.Opaque = r.URL.Path 14 | return nil 15 | }, 16 | } 17 | return client 18 | } 19 | -------------------------------------------------------------------------------- /internal/utils/output.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | log "github.com/sirupsen/logrus" 5 | "io" 6 | "os" 7 | ) 8 | 9 | func CreateFile(output string) (*os.File, error) { 10 | fileOuput, err := os.Create(output) 11 | if err != nil { 12 | log.Debug("create file: %v", err) 13 | return nil, err 14 | } 15 | return fileOuput, nil 16 | } 17 | 18 | func WriteToOutput(fileOuput *os.File, resp io.Reader) (int64, error) { 19 | n, err := io.Copy(fileOuput, resp) 20 | defer fileOuput.Close() 21 | return n, err 22 | } 23 | -------------------------------------------------------------------------------- /internal/utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "runtime" 7 | "strings" 8 | ) 9 | 10 | func CaseInsensitiveContains(s, substr string) bool { 11 | s, substr = strings.ToUpper(s), strings.ToUpper(substr) 12 | return strings.Contains(s, substr) 13 | } 14 | 15 | func GetDefaultConfigDir() string { 16 | return filepath.Join(Homedir(), ".gdown") 17 | } 18 | 19 | func Homedir() string { 20 | if runtime.GOOS == "windows" { 21 | return os.Getenv("APPDATA") 22 | } 23 | return os.Getenv("HOME") 24 | } 25 | -------------------------------------------------------------------------------- /module.go: -------------------------------------------------------------------------------- 1 | package gdown 2 | 3 | import ( 4 | "github.com/Juvenal-Yescas/gdown/internal/process" 5 | "github.com/Juvenal-Yescas/gdown/internal/utils" 6 | ) 7 | 8 | func Download(url string) (string, error) { 9 | idFile, err := process.GetIdFromUrl(url) 10 | if err != nil { 11 | return "", err 12 | } 13 | 14 | clientHttp := utils.CreateClientHttp() 15 | outputName, err := process.GetNameOutput(clientHttp, idFile) 16 | if err != nil { 17 | return "", err 18 | } 19 | 20 | urlDirect, err := process.GetUrlConfirmation(clientHttp, idFile) 21 | if err != nil { 22 | return "", err 23 | } 24 | 25 | downloaded, err := process.StartDownload(clientHttp, urlDirect, outputName) 26 | if err != nil { 27 | return "", err 28 | } 29 | return downloaded, nil 30 | } 31 | 32 | func DownloadOutput(url string, outputName string) (string, error) { 33 | idFile, err := process.GetIdFromUrl(url) 34 | if err != nil { 35 | return "", err 36 | } 37 | 38 | clientHttp := utils.CreateClientHttp() 39 | urlDirect, err := process.GetUrlConfirmation(clientHttp, idFile) 40 | if err != nil { 41 | return "", err 42 | } 43 | 44 | downloaded, err := process.StartDownload(clientHttp, urlDirect, outputName) 45 | if err != nil { 46 | return "", err 47 | } 48 | return downloaded, nil 49 | } 50 | -------------------------------------------------------------------------------- /pkg/gdriveapi/files.go: -------------------------------------------------------------------------------- 1 | package gdriveapi 2 | 3 | import ( 4 | log "github.com/sirupsen/logrus" 5 | "google.golang.org/api/drive/v3" 6 | ) 7 | 8 | func CreateFolder(client *drive.Service, nameFolder string) (*drive.File, error) { 9 | 10 | file := &drive.File{Name: nameFolder, MimeType: "application/vnd.google-apps.folder"} 11 | 12 | resp, err := client.Files.Create(file).Do() 13 | if err != nil { 14 | log.Error("An error occurred: %v\n", err) 15 | return nil, err 16 | } 17 | log.Debug("Id folder: %+v", resp.Id) 18 | return resp, nil 19 | } 20 | 21 | func CreateACopy(client *drive.Service, fileId string, nameOutput string, folderId []string) (*drive.File, error) { 22 | 23 | file := &drive.File{Name: nameOutput, Parents: folderId} 24 | 25 | resp, err := client.Files.Copy(fileId, file).Do() 26 | if err != nil { 27 | log.Debug("An error occurred: %v\n", err) 28 | log.Error(err) 29 | return nil, err 30 | } 31 | 32 | log.Debug("Id file copied: %+v", resp.Id) 33 | return resp, err 34 | } 35 | 36 | func Delete(client *drive.Service, fileIde string) error { 37 | error := client.Files.Delete(fileIde).Do() 38 | if error != nil { 39 | log.Error("An error occurred: %v\n", error) 40 | } 41 | return error 42 | } 43 | -------------------------------------------------------------------------------- /pkg/gdriveapi/permissions.go: -------------------------------------------------------------------------------- 1 | package gdriveapi 2 | 3 | import ( 4 | log "github.com/sirupsen/logrus" 5 | "google.golang.org/api/drive/v3" 6 | ) 7 | 8 | func MakeSharedFolder(client *drive.Service, idFolder string) (*drive.Permission, error) { 9 | file := &drive.Permission{Role: "reader", Type: "anyone"} 10 | resp, err := client.Permissions.Create(idFolder, file).Do() 11 | if err != nil { 12 | log.Debug("An error occurred: %v\n", err) 13 | return nil, err 14 | } 15 | log.Debug("Type shared folder: %+v", resp.Id) 16 | return resp, nil 17 | } 18 | --------------------------------------------------------------------------------