From 401a1d3630bf544a486867a26723604a39c5cc2a Mon Sep 17 00:00:00 2001 From: Nyah Check Date: Wed, 22 Dec 2021 20:55:05 +0000 Subject: [PATCH 1/9] Update ci workflow --- .github/workflows/ci.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index abd4329..dc425fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Build +name: CI on: [push, pull_request] @@ -8,15 +8,17 @@ jobs: name: Setup, Build, Test strategy: matrix: - go-version: [1.13.x] - platform: [macos-latest] - runs-on: ${{ matrix.platform }} + go-version: [1.16.x, 1.17.x, 1.18.x] + platform: [macos-latest, ubuntu-latest, windows-latest] + runs-on: ${{ matrix.os }} steps: - - name: Setup Go - uses: actions/setup-go@v1 + - name: Install go + uses: actions/setup-go@v2 with: go-version: ${{ matrix.go-version }} - name: Checkout code - uses: actions/checkout@v1 + uses: actions/checkout@v2 + - name: Test + run: go test -v -coverage ./... - name: Build - run: brew install ffmpeg && make build && make vet \ No newline at end of file + run: make all From c9a7bb206ab54da50bf28c808aed0461a41c865c Mon Sep 17 00:00:00 2001 From: Nyah Check Date: Wed, 22 Dec 2021 20:59:05 +0000 Subject: [PATCH 2/9] Updates to gitignore --- .gitignore | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index e22a576..983895f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,7 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so +# MacOS DS_Store files +.DS_Store -# Ignore all downloaded video and audio files +# Binaries for programs and plugins *.mp3 *.flv *.webm @@ -11,22 +9,49 @@ *.mp4 *.3gpp *.ogg +*.exe +*.exe~ +*.dll +*.o +*.a +*.so +*.dylib -# Compiled binaries +## Compiled binaries ytd youtube-dl -*.exe + +# Test binary, built with `go test -c` *.test *.prof -# OSX -.DS_Store - -# CODE coverage results +# Output of the go coverage tool, specifically when used with LiteIDE +*.out +coverage.html coverage.txt profile.out -# ENV files +# Dependency directories (remove the comment below to include it) +vendor/ + +# Output of GoReleaser +dist/ + +# Visual Studio Code files +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# GoLand and IntelliJ IDEA files +.idea/ + +# env files that usually contain secrets or local config +.env .envrc -.idea \ No newline at end of file From 5eac880289f0315edf09aea7d4c154878bd62b48 Mon Sep 17 00:00:00 2001 From: Nyah Check Date: Wed, 22 Dec 2021 20:59:50 +0000 Subject: [PATCH 3/9] Add dependabot configs workflow --- .github/workflows/dependabot.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .github/workflows/dependabot.yml diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml new file mode 100644 index 0000000..49a3b5a --- /dev/null +++ b/.github/workflows/dependabot.yml @@ -0,0 +1,19 @@ + +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + # Maintain dependencies for Go + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "weekly" + + # Maintain dependencies for build tools + - package-ecosystem: "gomod" + directory: "/tools" + schedule: + interval: "weekly" From b71ae3cd9f13d10f93396b4356b995376810b085 Mon Sep 17 00:00:00 2001 From: Nyah Check Date: Wed, 22 Dec 2021 21:26:06 +0000 Subject: [PATCH 4/9] Update github repo configs --- .github/CODEOWNERS | 1 - CONTRIBUTING.md => .github/CONTRIBUTING.md | 0 .github/ISSUE_TEMPLATE.md | 14 ++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 15 +++++++++++++++ .github/issue_template.md | 7 ------- 5 files changed, 29 insertions(+), 8 deletions(-) rename CONTRIBUTING.md => .github/CONTRIBUTING.md (100%) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md delete mode 100644 .github/issue_template.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index fc81ca9..52cb09a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1 @@ * @ch3ck - diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to .github/CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..553ec76 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,14 @@ +--- +name: Bug Report +about: If something isn't working as its supposed to +labels: bug, feature request, needs triage, won't fix +assignees: ch3ck +--- + +Please provide more details: + +* What are you trying to do +* What happened +* What was the expected behaviour + +Please share relevent code sample or [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..3cd82d0 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,15 @@ +## Proposed changes +Describe the *big picture* reason for your PR. + +## Checklist + +Please review the following checklist before submitting a PR: + +- [ ] **CONSIDER** adding a unit test to demonstrate your PR resolves an issue +- [ ] **DO** keep PRs small for easy review +- [ ] **DO** make sure unit tests pass +- [ ] **DO** ensure no compiler warnings are triggered +- [ ] **AVOID** breaking the CI builds + +## Other comments +Any other comments you might have. diff --git a/.github/issue_template.md b/.github/issue_template.md deleted file mode 100644 index 8b31d81..0000000 --- a/.github/issue_template.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -name: Tracking issue -about: Use this template for tracking new features. -title: "[DATE]: [FEATURE NAME]" -labels: bug, feature request, needs triage, won't fix -assignees: ch3ck ---- \ No newline at end of file From 10671ae782ce636de11e1c620242601c8f2eeecc Mon Sep 17 00:00:00 2001 From: Nyah Check Date: Wed, 22 Dec 2021 21:56:57 +0000 Subject: [PATCH 5/9] refactor module --- build.sh | 10 ----- main.go => cmd/main.go | 21 +++++------ go.mod | 17 +++------ go.sum | 37 ++++++------------- download.go => pkg/downloader/download.go | 10 ++--- .../downloader/download_test.go | 6 +-- 6 files changed, 35 insertions(+), 66 deletions(-) delete mode 100644 build.sh rename main.go => cmd/main.go (85%) rename download.go => pkg/downloader/download.go (86%) rename download_test.go => pkg/downloader/download_test.go (86%) diff --git a/build.sh b/build.sh deleted file mode 100644 index c8c8b8d..0000000 --- a/build.sh +++ /dev/null @@ -1,10 +0,0 @@ -#Script builds the program -#!/usr/bin/env bash - -p=`pwd` -for d in $(ls ./); do - echo "building main/$d" - cd $p/cm$d - env GOOS=linux GOARCH=386 go build -done -cd $p diff --git a/main.go b/cmd/main.go similarity index 85% rename from main.go rename to cmd/main.go index 463d7f1..d49b80e 100644 --- a/main.go +++ b/cmd/main.go @@ -11,6 +11,8 @@ import ( "strings" "sync" + "youtube-dl/pkg/downloader" + "github.com/sirupsen/logrus" ) @@ -87,21 +89,18 @@ func parseUrls(urls string) []string { } } -func beginDownload(urls []string) { - if len(urls) < 2 { - if err := decodeVideoStream(urls[0], format); err != nil { - logrus.Errorf("Unable to beginDownload: %v", err) - } - } else { - if err := concurrentDownload(MAXDOWNLOADS, format, urls); err != nil { - logrus.Errorf("Unable to concurrently download videos: %v with errors => %v", urls, err) - } +// beginDownload of videos from specified url(s) +// and returns error if it fails +func beginDownload(urls []string) <-chan error { + if err := concurrentDownload(MAXDOWNLOADS, format, urls); err != nil { + logrus.Errorf("Unable to download video(s): %v with errors => %v", urls, err) + return err } + return nil } //DownloadStreams download a batch of elements asynchronously func concurrentDownload(maxOperations int, format string, urls []string) <-chan error { - var wg sync.WaitGroup wg.Add(len(urls)) @@ -109,7 +108,7 @@ func concurrentDownload(maxOperations int, format string, urls []string) <-chan for _, url := range urls { go func(url string) { defer wg.Done() - ch <- decodeVideoStream(url, format) + ch <- downloader.DecodeVideoStream(url, format) }(url) } diff --git a/go.mod b/go.mod index 8ebf5bb..7b580ec 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,10 @@ -module github.com/ch3ck/youtube-dl +module youtube-dl -go 1.12 +go 1.17 require ( - github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect - github.com/sirupsen/logrus v1.5.0 - github.com/stretchr/objx v0.2.0 // indirect - github.com/stretchr/testify v1.4.0 // indirect - github.com/wader/goutubedl v0.0.0-20200327095909-c841a70bbbad - github.com/wader/osleaktest v0.0.0-20191111175233-f643b0fed071 // indirect - golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b // indirect - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - gopkg.in/yaml.v2 v2.2.7 // indirect + github.com/sirupsen/logrus v1.8.1 + github.com/wader/goutubedl v0.0.0-20211221155015-039073da1ac8 ) + +require golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect diff --git a/go.sum b/go.sum index 2f5e223..9477086 100644 --- a/go.sum +++ b/go.sum @@ -1,31 +1,16 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q= -github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/wader/goutubedl v0.0.0-20200115162246-9eae90476a5d h1:+noQWJMxTu1ruNLG1KcA7tz0kHR7QYUBu+88Y2+w930= -github.com/wader/goutubedl v0.0.0-20200115162246-9eae90476a5d/go.mod h1:TEOvzRw4YvTeOdSvGyoZD9KbKK4xbx0EJoSqj4v6yAs= -github.com/wader/goutubedl v0.0.0-20200327095909-c841a70bbbad h1:16IhHxbHNcIjuAXABVcKczJlHRO7sRwLPCnSmogRPCA= -github.com/wader/goutubedl v0.0.0-20200327095909-c841a70bbbad/go.mod h1:TEOvzRw4YvTeOdSvGyoZD9KbKK4xbx0EJoSqj4v6yAs= -github.com/wader/osleaktest v0.0.0-20190723190525-c53af4cfc4a3/go.mod h1:XD6emOFPHVzb0+qQpiNOdPL2XZ0SRUM0N5JHuq6OmXo= +github.com/wader/goutubedl v0.0.0-20211221155015-039073da1ac8 h1:sAGy4o7qRHWJ8kM8fr69VWVdANx4BC8Q4BAU/eTqfvE= +github.com/wader/goutubedl v0.0.0-20211221155015-039073da1ac8/go.mod h1:5KXd5tImdbmz4JoVhePtbIokCwAfEhUVVx3WLHmjYuw= +github.com/wader/osleaktest v0.0.0-20191111175233-f643b0fed071 h1:QkrG4Zr5OVFuC9aaMPmFI0ibfhBZlAgtzDYWfu7tqQk= github.com/wader/osleaktest v0.0.0-20191111175233-f643b0fed071/go.mod h1:XD6emOFPHVzb0+qQpiNOdPL2XZ0SRUM0N5JHuq6OmXo= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200117145432-59e60aa80a0c h1:gUYreENmqtjZb2brVfUas1sC6UivSY8XwKwPo8tloLs= -golang.org/x/sys v0.0.0-20200117145432-59e60aa80a0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b h1:h03Ur1RlPrGTjua4koYdpGl8W0eYo8p1uI9w7RPlkdk= -golang.org/x/sys v0.0.0-20200408040146-ea54a3c99b9b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/download.go b/pkg/downloader/download.go similarity index 86% rename from download.go rename to pkg/downloader/download.go index 6440768..6eae3bc 100644 --- a/download.go +++ b/pkg/downloader/download.go @@ -1,4 +1,4 @@ -package main +package downloader import ( "context" @@ -34,10 +34,10 @@ func fixExtension(str string) string { return str } -// decodeVideoStream processes downloaded video stream and -// decodeVideoStream calls helper functions and writes the +// DecodeVideoStream processes downloaded video stream and +// DecodeVideoStream calls helper functions and writes the // output in the required format -func decodeVideoStream(videoUrl, format string) error { +func DecodeVideoStream(videoUrl, format string) error { // Get video data res, err := goutubedl.New(context.Background(), videoUrl, goutubedl.Options{}) @@ -65,4 +65,4 @@ func decodeVideoStream(videoUrl, format string) error { io.Copy(fp, videoStream) return nil -} \ No newline at end of file +} diff --git a/download_test.go b/pkg/downloader/download_test.go similarity index 86% rename from download_test.go rename to pkg/downloader/download_test.go index de83282..937ea6f 100644 --- a/download_test.go +++ b/pkg/downloader/download_test.go @@ -1,4 +1,4 @@ -package main +package downloader import ( "testing" @@ -22,7 +22,7 @@ func TestApi(t *testing.T) { // path := "test" for i, table := range tables { - err := decodeVideoStream(table.url, "mp3") + err := DecodeVideoStream(table.url, "mp3") if err != nil { t.Errorf("videoId(%d): expected %q, actual %q", i, table.id, err) } @@ -31,7 +31,7 @@ func TestApi(t *testing.T) { func BenchmarkVideoId(b *testing.B) { for n := 0; n < b.N; n++ { - if err := decodeVideoStream(tables[0].url, "mp3"); err != nil { + if err := DecodeVideoStream(tables[0].url, "mp3"); err != nil { b.Errorf("Error downloading video: %v", err) } } From 4122d5a1fdcf8017e8aa857dc68e82b4ff5507f0 Mon Sep 17 00:00:00 2001 From: Nyah Check Date: Thu, 23 Dec 2021 01:34:07 +0000 Subject: [PATCH 6/9] Add ci workflow for rust jobs --- .github/workflows/ci.yml | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dc425fe..903cc65 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,8 +4,34 @@ on: [push, pull_request] jobs: + build-and-test-rust-lib: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macOS-latest] + rust: [nightly] + steps: + - uses: actions/checkout@v2 + with: + rust-version: ${{ matrix.rust }} + - name: Build + run: cargo +nightly build --tests --verbose + - name: Run tests + run: cargo +nightly test --verbose + publish-crate-on-new-release: + name: "Publish crate on Release" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + - uses: katyo/publish-crates@v1 + with: + registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} setup-build-test: - name: Setup, Build, Test + name: Setup, Build, Test go source strategy: matrix: go-version: [1.16.x, 1.17.x, 1.18.x] From f4755b3921925c04e9af86199a34e6aa75e7568c Mon Sep 17 00:00:00 2001 From: Nyah Check Date: Thu, 23 Dec 2021 01:35:40 +0000 Subject: [PATCH 7/9] rename youtube-dl to ydl --- .gitignore | 2 +- Dockerfile | 6 +++--- LICENSE | 2 +- README.md | 29 ++++++++++++++--------------- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 983895f..00efb8e 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,7 @@ ## Compiled binaries ytd -youtube-dl +ydl # Test binary, built with `go test -c` diff --git a/Dockerfile b/Dockerfile index 2a25d3f..0feca45 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,10 +10,10 @@ ENV GO111MODULE=on WORKDIR /app RUN echo "Build container" COPY . . -RUN CGO_ENABLED=0 GOOS=linux go build -o /youtube-dl . +RUN CGO_ENABLED=0 GOOS=linux go build -o /ydl . # Runtime container FROM scratch -COPY --from=go-base /youtube-dl /youtube-dl -ENTRYPOINT ["/youtube-dl"] +COPY --from=go-base /ydl /ydl +ENTRYPOINT ["/ydl"] diff --git a/LICENSE b/LICENSE index de90ebd..d769fd0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 youtube-dl +Copyright (c) 2020 ydl Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index c2375e2..dfb558a 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,36 @@ -# youtube-dl +# ydl -[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/ch3ck/youtube-dl/Build?style=for-the-badge)](https://github.com/ch3ck/youtube-dl/actions) -[![GoDoc](https://img.shields.io/badge/godoc-reference-5272B4.svg?style=for-the-badge)](https://godoc.org/github.com/ch3ck/youtube-dl) -[![GitHub license](https://img.shields.io/github/license/ch3ck/youtube-dl?style=for-the-badge)](https://github.com/ch3ck/youtube-dl/blob/master/LICENSE) +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/ch3ck/ydl/Build?style=for-the-badge)](https://github.com/ch3ck/ydl/actions) +[![GoDoc](https://img.shields.io/badge/godoc-reference-5272B4.svg?style=for-the-badge)](https://godoc.org/github.com/ch3ck/ydl) +[![GitHub license](https://img.shields.io/github/license/ch3ck/ydl?style=for-the-badge)](https://github.com/ch3ck/ydl/blob/master/LICENSE) -`youtube-dl` is a simple youtube video downloader and can also download multiple videos concurrently. -Downloaded videos could be converted to `flv` or `mp3` formats. +`ydl` is a simple youtube video downloader. ## Build ```bash -$ git clone https://github.com/Ch3ck/youtube-dl -$ cd youtube-dl +$ git clone https://github.com/Ch3ck/ydl +$ cd ydl $ make ``` ## Usage -To install youtube-dl +To install ydl ```console -$ go get github.com/Ch3ck/youtube-dl +$ go get github.com/ch3ck/ydl ``` To run download: ```console -youtube-dl -h -youtube-dl - Simple youtube video/audio downloader +ydl -h +ydl - Simple youtube video/audio downloader -Usage: youtube-dl [OPTIONS] [ARGS] +Usage: ydl [OPTIONS] [ARGS] Flags: -bitrate Audio Bitrate (default 123) @@ -45,7 +44,7 @@ Flags: ### Example ```bash -$ ./youtube-dl -format mp3 -id lWEbEtr_Vng +$ ./ydl -format mp3 -id lWEbEtr_Vng ``` ## Roadmap @@ -62,7 +61,7 @@ Follow the basic instruction in the [CONTRIBUTING](CONTRIBUTING.md) file. ## Licence -`youtube-dl` is licensed under [The MIT Licence](LICENSE.md). +`ydl` is licensed under [The MIT Licence](LICENSE.md). ## Support From 23146e14d00cde2bb7f45ee361446124f904b11c Mon Sep 17 00:00:00 2001 From: Nyah Check Date: Thu, 23 Dec 2021 03:17:24 +0000 Subject: [PATCH 8/9] Add download package --- .github/workflows/ci.yml | 40 +++++++------------ .github/workflows/dependabot.yml | 1 - .github/workflows/release.yml | 51 ++++++++++++++++++++++++ .github/workflows/security.yml | 18 +++++++++ pkg/download.h | 13 ++++++ pkg/download/.gitignore | 12 ++++++ pkg/download/.rustfmt.toml | 5 +++ pkg/download/Cargo.toml | 29 ++++++++++++++ pkg/download/src/lib.rs | 42 ++++++++++++++++++++ pkg/downloader/download.go | 68 -------------------------------- pkg/downloader/download_test.go | 38 ------------------ 11 files changed, 185 insertions(+), 132 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/security.yml create mode 100644 pkg/download.h create mode 100644 pkg/download/.gitignore create mode 100644 pkg/download/.rustfmt.toml create mode 100644 pkg/download/Cargo.toml create mode 100644 pkg/download/src/lib.rs delete mode 100644 pkg/downloader/download.go delete mode 100644 pkg/downloader/download_test.go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 903cc65..e74a40a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,34 +4,24 @@ on: [push, pull_request] jobs: - build-and-test-rust-lib: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] - rust: [nightly] - steps: - - uses: actions/checkout@v2 - with: - rust-version: ${{ matrix.rust }} - - name: Build - run: cargo +nightly build --tests --verbose - - name: Run tests - run: cargo +nightly test --verbose - publish-crate-on-new-release: - name: "Publish crate on Release" + build-and-test-rust-library: + name: Build and test rust library runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - - uses: katyo/publish-crates@v1 + - name: checkout source + uses: actions/checkout@v2 + - name: install latest nightly + uses: actions-rs/toolchain@v1 with: - registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} - setup-build-test: - name: Setup, Build, Test go source + toolchain: nightly + override: true + components: rustfmt, clippy + - name: build and test + working-directory: ./pkg/download + run: | + cargo build --tests --verbose && cargo test --verbose + build-and-test-go-module: + name: Build and test go source strategy: matrix: go-version: [1.16.x, 1.17.x, 1.18.x] diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index 49a3b5a..edeb6cc 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -1,4 +1,3 @@ - # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..72ace2d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,51 @@ +name: release new binaries + +on: + workflow_dispatch: + inputs: + reason: + description: new release message + required: true + push: + tags: + - "*" + +permissions: + contents: write + + +jobs: + publish-crate-on-new-release: + name: "Publish crate on Release" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + - uses: katyo/publish-crates@v1 + with: + registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }} + publish-go-package-on-release: + name: Release go binaries + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Setup Go + uses: actions/setup-go@v2 + with: + go-version: 1.17 + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v2 + with: + distribution: goreleaser + version: latest + args: release --rm-dist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # GoReleaser Pro key, for 'goreleaser-pro' distribution + # GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..b66b67b --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,18 @@ +# Run security audit +# Author: Nyah Check +name: Run Security Audit + +on: + push: + paths: + - '**/Cargo.toml' + - '**/Cargo.lock' + +jobs: + run-security-audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - uses: actions-rs/audit-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/pkg/download.h b/pkg/download.h new file mode 100644 index 0000000..f2a446b --- /dev/null +++ b/pkg/download.h @@ -0,0 +1,13 @@ +/** -*- mode: C; -*- + * download.h + * + * Copyright (C) 2021 Nyah Check + * + **/ + +#ifndef DOWNLOAD_H +#define DOWNLOAD_H + +char * download(char *url, char *path); + +#endif diff --git a/pkg/download/.gitignore b/pkg/download/.gitignore new file mode 100644 index 0000000..6351a5d --- /dev/null +++ b/pkg/download/.gitignore @@ -0,0 +1,12 @@ +# rs will have compiled files and executables +/target/ +Cargo.lock + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +# Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk +target +build diff --git a/pkg/download/.rustfmt.toml b/pkg/download/.rustfmt.toml new file mode 100644 index 0000000..a6a1306 --- /dev/null +++ b/pkg/download/.rustfmt.toml @@ -0,0 +1,5 @@ +max_width = 80 +newline_style = "Unix" +reorder_imports = true +use_small_heuristics = "Max" +use_field_init_shorthand = true diff --git a/pkg/download/Cargo.toml b/pkg/download/Cargo.toml new file mode 100644 index 0000000..806c4f2 --- /dev/null +++ b/pkg/download/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "ydl" +description = "download youtube videos to path" +version = "0.1.0" +authors = ["Nyah Check "] +license = "MIT" +homepage = "https://github.com/ch3ck" +repository = "https://github.com/ch3ck/ydl" +readme = "README.md" +categories = ["web-programming"] +keywords = [ "rust"] +edition = "2018" +documentation = "https://docs.rs/ydl" + + +[lib] +crate-type = ["staticlib"] + +[profile.release] +debug = true +overflow-checks = true +panic = "abort" + +[dependencies] +clippy = "0.0.302" +env_logger = "0.9.0" +log = "0.4.14" +rustube = "0.3.6" +tokio = { version = "1.15.0", features = ["macros", "io-util", "sync", "rt-multi-thread"] } diff --git a/pkg/download/src/lib.rs b/pkg/download/src/lib.rs new file mode 100644 index 0000000..79ba49d --- /dev/null +++ b/pkg/download/src/lib.rs @@ -0,0 +1,42 @@ +//! -*- mode: rust; -*- +//! +//! download - downloads youtube files +use rustube::{Id, Video}; +use std::ffi; + +#[no_mangle] +pub async extern "C" fn download<'a>( + url: &'a str, + path: &'a str, +) -> Result<(), Box> { + env_logger::init(); + + let id = Id::from_raw(&url)?; + let video = Video::from_id(id.into_owned()).await?; + + let _result = video + .streams() + .iter() + .filter(|stream| { + stream.includes_video_track && stream.includes_audio_track + }) + .max_by_key(|stream| stream.quality_label) + .unwrap() + .download_to_dir(&path) + .await + .unwrap(); + + Ok(()) +} + +#[cfg(test)] +pub mod tests { + use super::*; + + #[tokio::test] + async fn test_download() { + let url = String::from("https://www.youtube.com/watch?v=lWEbEtr_Vng"); + let fp = String::from("~/Downloads"); + download(url.as_str(), fp.as_str()).await.expect("expect an OK(_) response"); + } +} diff --git a/pkg/downloader/download.go b/pkg/downloader/download.go deleted file mode 100644 index 6eae3bc..0000000 --- a/pkg/downloader/download.go +++ /dev/null @@ -1,68 +0,0 @@ -package downloader - -import ( - "context" - "io" - "os" - "strings" - "unicode" - - "github.com/sirupsen/logrus" - "github.com/wader/goutubedl" -) - -// removeWhiteSpace removes white spaces from string -// removeWhiteSpace returns a filename without whitespaces -func removeWhiteSpace(str string) string { - return strings.Map(func(r rune) rune { - if unicode.IsSpace(r) { - return -1 - } - return r - }, str) -} - -// fixExtension is a helper function that -// fixes file the extension -func fixExtension(str string) string { - if strings.Contains(str, "mp3") { - str = ".mp3" - } else { - str = ".flv" - } - - return str -} - -// DecodeVideoStream processes downloaded video stream and -// DecodeVideoStream calls helper functions and writes the -// output in the required format -func DecodeVideoStream(videoUrl, format string) error { - - // Get video data - res, err := goutubedl.New(context.Background(), videoUrl, goutubedl.Options{}) - if err != nil { - logrus.Errorf("Unable to create goutube object %s: %v", videoUrl, err) - return err - } - - file := removeWhiteSpace(res.Info.Title) + fixExtension(format) - videoStream, err := res.Download(context.Background(), "best") - if err != nil { - logrus.Errorf("Unable to download %s stream: %v", format, err) - return err - } - defer videoStream.Close() - - // Create output file - fp, err := os.OpenFile(file, os.O_CREATE, 0755) - if err != nil { - logrus.Errorf("Unable to create output file: %v", err) - return err - } - defer fp.Close() - - io.Copy(fp, videoStream) - - return nil -} diff --git a/pkg/downloader/download_test.go b/pkg/downloader/download_test.go deleted file mode 100644 index 937ea6f..0000000 --- a/pkg/downloader/download_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package downloader - -import ( - "testing" -) - -var tables = []struct { - url, id string // input -}{ - {"https://www.youtube.com/watch?v=lWEbEtr_Vng", "lWEbEtr_Vng"}, - {"https://www.youtube.com/watch?v=ALWmcO8S-dc", "ALWmcO8S-dc"}, - {"", ""}, - {"https://www.facebook.com/mark/videos?v=RDHpNluHOAJFA", ""}, - {"https://www.youtube.com/watch?v=ALWmcO8S-dc", "ALWmcO8S-dc"}, - {"https://www.wsj.com/articles/trump-administration-wont-withdraw-from-paris-climate-deal-1505593922", ""}, - {"https://vimeo.com/101522071", ""}, -} - -var vid []string - -func TestApi(t *testing.T) { - - // path := "test" - for i, table := range tables { - err := DecodeVideoStream(table.url, "mp3") - if err != nil { - t.Errorf("videoId(%d): expected %q, actual %q", i, table.id, err) - } - } -} - -func BenchmarkVideoId(b *testing.B) { - for n := 0; n < b.N; n++ { - if err := DecodeVideoStream(tables[0].url, "mp3"); err != nil { - b.Errorf("Error downloading video: %v", err) - } - } -} From 60c782952394e83e217045cd16d1018d361be532 Mon Sep 17 00:00:00 2001 From: Nyah Check Date: Thu, 23 Dec 2021 05:51:02 +0000 Subject: [PATCH 9/9] combine cgo with rust ffi capabilities --- .dockerignore | 3 - .github/workflows/ci.yml | 2 +- Dockerfile | 19 ------ LICENSE | 2 +- Makefile | 69 ++++++++------------- README.md | 62 ++++++------------ cmd/main.go | 131 --------------------------------------- go.mod | 9 +-- go.sum | 16 ----- main.go | 99 +++++++++++++++++++++++++++++ 10 files changed, 145 insertions(+), 267 deletions(-) delete mode 100644 .dockerignore delete mode 100644 Dockerfile delete mode 100644 cmd/main.go create mode 100644 main.go diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index dc8f861..0000000 --- a/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -Dockerfile -**.md -.git \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e74a40a..b517db2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,4 +37,4 @@ jobs: - name: Test run: go test -v -coverage ./... - name: Build - run: make all + run: make diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 0feca45..0000000 --- a/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ - -# Build container -FROM golang:1.13-alpine AS go-base -RUN apk add --no-cache git - -MAINTAINER Nyah Check - -ENV CGO_ENABLED=1 -ENV GO111MODULE=on -WORKDIR /app -RUN echo "Build container" -COPY . . -RUN CGO_ENABLED=0 GOOS=linux go build -o /ydl . - - -# Runtime container -FROM scratch -COPY --from=go-base /ydl /ydl -ENTRYPOINT ["/ydl"] diff --git a/LICENSE b/LICENSE index d769fd0..de1237c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 ydl +Copyright (c) 2022 ydl Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index b07ac37..34464dd 100644 --- a/Makefile +++ b/Makefile @@ -1,45 +1,26 @@ -# Setup package name variables -NAME := ytd -PKG := github.com/ch3ck/$(NAME) -PREFIX?=$(shell pwd) -BUILDTAGS= -version=v1.1 - -.PHONY: clean all fmt vet build test install static -.DEFAULT: default - -all: clean fmt vet build test install - -build: clean fmt - @echo "+ $@" - CGO_ENABLED=1 go build -tags "$(BUILDTAGS) cgo" . - -static: - @echo "+ $@" - CGO_ENABLED=1 go build -tags "$(BUILDTAGS) cgo static_build" -ldflags "-w -extldflags -static" -o ytd . - -fmt: - @echo "+ $@" - @gofmt -s -l -w . | tee /dev/stderr - -test: - @echo "+ $@" - @find . -name \*.mp3 -delete #clean previous test files. - @go test -v -tags "$(BUILDTAGS) cgo" $(shell go list) - @find . -name \*.mp3 -delete # clean previous test downloads - @go test -bench=. $(shell go list) - -vet: - @echo "+ $@" - @go vet $(shell go list | grep -v vendor) - +.PHONY: build-all +build-all: build-static + +.PHONY: run-all +run-all: run-static + +.PHONY: build-static +build-static: + rustup toolchain install nightly + cd pkg/download && cargo +nightly build --release + cp pkg/download/target/release/libydl.a pkg/ + go build -v ./... + +.PHONY: run-static +run-static: + RUST_LOG=trace ./ydl + +# test rust lib +.PHONY: test-rs +test-rs: + cd pkg/download && RUST_LOG=trace cargo test -- --nocapture + +# clean all packages +.PHONY: clean clean: - @echo "+ $@" - @rm -rf ytd - @find . -name \*.mp3 -delete - @find . -name \*.flv -delete - -install: - @echo "+ $@" - @docker build -t ch3ck/youtube-dl:$(version) . - @go install . + rm -rf main_static pkg/libydl.so pkg/libydl.a pkg/download/target diff --git a/README.md b/README.md index dfb558a..65a4f57 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,18 @@ # ydl -[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/ch3ck/ydl/Build?style=for-the-badge)](https://github.com/ch3ck/ydl/actions) -[![GoDoc](https://img.shields.io/badge/godoc-reference-5272B4.svg?style=for-the-badge)](https://godoc.org/github.com/ch3ck/ydl) -[![GitHub license](https://img.shields.io/github/license/ch3ck/ydl?style=for-the-badge)](https://github.com/ch3ck/ydl/blob/master/LICENSE) +[![Build](https://github.com/ch3ck/youtube-dl/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/ch3ck/youtube-dl/actions/workflows/ci.yml) +[![CodeQL](https://github.com/ch3ck/youtube-dl/actions/workflows/codeql-analysis.yml/badge.svg?branch=master)](https://github.com/ch3ck/youtube-dl/actions/workflows/codeql-analysis.yml)) +[![forthebadge](https://forthebadge.com/images/badges/contains-technical-debt.svg)](https://forthebadge.com) `ydl` is a simple youtube video downloader. -## Build +## Build and Test + +## Pre-requisites + +1. Install [rust nightly](https://rust-lang.github.io/rustup/concepts/channels.html) +2. Install the [go]https://go.dev/doc/install() ```bash $ git clone https://github.com/Ch3ck/ydl @@ -15,55 +20,24 @@ $ cd ydl $ make ``` +## Install and Run -## Usage - -To install ydl - -```console -$ go get github.com/ch3ck/ydl -``` - -To run download: - -```console -ydl -h -ydl - Simple youtube video/audio downloader - -Usage: ydl [OPTIONS] [ARGS] - -Flags: - -bitrate Audio Bitrate (default 123) - -format File Format(mp3, webm, flv) - -id Youtube Video ID - -path Output Path (default ".") - -version print version and exit - -h Help page -``` - -### Example +*NOTE: * release coming soon! +Once a release is ready, you could just download one of the [binaries]https://github.com/nyanchor/ydl/releases() and run: ```bash -$ ./ydl -format mp3 -id lWEbEtr_Vng +$ ydl -id url # -id lWEbEtr_Vng ``` -## Roadmap - -* Download youtube video with video id or link and converts to flv or mp3. -* Support HD Video download. -* Concurrent downloads. -* Web App(PWA, Basic JS Web UI). - - -## Contributing - -Follow the basic instruction in the [CONTRIBUTING](CONTRIBUTING.md) file. ## Licence `ydl` is licensed under [The MIT Licence](LICENSE.md). -## Support +## License +The scripts and documentation in this project are released under the [MIT License](LICENSE.md) + -This project was created and is maintained by [Nyah Check](https://twitter.com/ch3ck_) +## Author +- [Nyah Check](https://nyah.dev) \ No newline at end of file diff --git a/cmd/main.go b/cmd/main.go deleted file mode 100644 index d49b80e..0000000 --- a/cmd/main.go +++ /dev/null @@ -1,131 +0,0 @@ -// main program entry -package main - -import ( - "flag" - "fmt" - _ "net/http/pprof" - "os" - "runtime" - "runtime/pprof" - "strings" - "sync" - - "youtube-dl/pkg/downloader" - - "github.com/sirupsen/logrus" -) - -const ( - - // help Banner - BANNER = `` + - `youtube-dl - Simple youtube video/audio DownloadStreams` + "\n\n" + - `Usage: youtube-dl [OPTIONS] [ARGS]` + "\n" - - // current version - VERSION = "v0.2" - - // default maximum concurrent downloads - MAXDOWNLOADS = 5 -) - -var ( - // Command line flags - ids string - version bool - format string - path string - bitrate uint -) - -var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") - -func init() { - // parse flags - flag.StringVar(&ids, "id", "", "video url or video id; separate multiple ids with a comma.") - flag.StringVar(&format, "format", "flv", "download file format(mp3 or flv)") - flag.StringVar(&path, "path", ".", "download file path") - flag.BoolVar(&version, "version", false, "print version number") - flag.UintVar(&bitrate, "bitrate", 192, "audio bitrate") - - flag.Usage = func() { - fmt.Fprint(os.Stderr, fmt.Sprintf("%s \t %s", BANNER, VERSION)) - flag.PrintDefaults() - } -} - -func main() { - flag.Parse() - - if *cpuprofile != "" { - f, err := os.Create(*cpuprofile) - if err != nil { - logrus.Fatalf("%v", err) - } - pprof.StartCPUProfile(f) - defer pprof.StopCPUProfile() - } - runtime.SetBlockProfileRate(20) - - args := os.Args - if len(args) < 2 { - usageAndExit(BANNER, 2) - } - if path == "" { - path, _ = os.Getwd() - } - - urls := parseUrls(ids) - beginDownload(urls) -} - -// parseUrls for video download -func parseUrls(urls string) []string { - if ids == "" { - return []string{os.Args[1]} - } else { - return strings.Split(ids, ",") - } -} - -// beginDownload of videos from specified url(s) -// and returns error if it fails -func beginDownload(urls []string) <-chan error { - if err := concurrentDownload(MAXDOWNLOADS, format, urls); err != nil { - logrus.Errorf("Unable to download video(s): %v with errors => %v", urls, err) - return err - } - return nil -} - -//DownloadStreams download a batch of elements asynchronously -func concurrentDownload(maxOperations int, format string, urls []string) <-chan error { - var wg sync.WaitGroup - wg.Add(len(urls)) - - ch := make(chan error, maxOperations) - for _, url := range urls { - go func(url string) { - defer wg.Done() - ch <- downloader.DecodeVideoStream(url, format) - }(url) - } - - go func() { - wg.Wait() - close(ch) - }() - - return ch -} - -func usageAndExit(message string, exitCode int) { - if message != "" { - fmt.Fprintf(os.Stderr, message) - fmt.Fprintf(os.Stderr, "\n\n") - } - flag.Usage() - fmt.Fprintf(os.Stderr, "\n") - os.Exit(exitCode) -} diff --git a/go.mod b/go.mod index 7b580ec..7b51fdf 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,3 @@ -module youtube-dl +module ydl go 1.17 - -require ( - github.com/sirupsen/logrus v1.8.1 - github.com/wader/goutubedl v0.0.0-20211221155015-039073da1ac8 -) - -require golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 // indirect diff --git a/go.sum b/go.sum index 9477086..e69de29 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +0,0 @@ -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= -github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/wader/goutubedl v0.0.0-20211221155015-039073da1ac8 h1:sAGy4o7qRHWJ8kM8fr69VWVdANx4BC8Q4BAU/eTqfvE= -github.com/wader/goutubedl v0.0.0-20211221155015-039073da1ac8/go.mod h1:5KXd5tImdbmz4JoVhePtbIokCwAfEhUVVx3WLHmjYuw= -github.com/wader/osleaktest v0.0.0-20191111175233-f643b0fed071 h1:QkrG4Zr5OVFuC9aaMPmFI0ibfhBZlAgtzDYWfu7tqQk= -github.com/wader/osleaktest v0.0.0-20191111175233-f643b0fed071/go.mod h1:XD6emOFPHVzb0+qQpiNOdPL2XZ0SRUM0N5JHuq6OmXo= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/main.go b/main.go new file mode 100644 index 0000000..2c65c7c --- /dev/null +++ b/main.go @@ -0,0 +1,99 @@ +package main + +// #cgo LDFLAGS: ./pkg/libydl.a -ldl +// #include "./pkg/download.h" +import "C" + +import ( + "flag" + "log" + "os" + "strings" +) + +const ( + + // help Banner + BANNER = `` + + `ydl - simple youtube downloader` + "\n\n" + + `Usage: [OPTIONS] [ARGS]` + "\n" + + "\t" + `ydl -id video url or id` + "\n" + + "\t" + `ydl -path download path (defaults to '.')` + "\n" + + "\t" + `Example: ydl -id https://www.youtube.com/watch?v=lWEbEtr_Vng` + "\n\n\n" + + // current version + VERSION = "v1.0" + + // default maximum concurrent downloads + MAXDOWNLOADS = 5 +) + +var ( + // Command line flags + ids string + version bool + format string + path string + bitrate uint +) + +func init() { + // parse flags + flag.StringVar(&ids, "id", "", "video url or video id; separate multiple ids with a comma.") + flag.StringVar(&path, "path", ".", "download file path") + + flag.Usage = func() { + log.Fatalf("%s \t %s", BANNER, VERSION) + flag.PrintDefaults() + } +} + +func main() { + flag.Parse() + args := os.Args + if len(args) < 2 { + usageAndExit(BANNER, 2) + } + if path == "" { + path, _ = os.Getwd() + } + + // parse urls + urls := parseUrls(ids) + + // start download + if err := concurrentDownload(MAXDOWNLOADS, format, urls); err != nil { + log.Fatalf("Unable to download video(s): %v with errors => %v", urls, err) + } +} + +// parseUrls for video download +func parseUrls(urls string) []string { + if ids == "" { + return []string{os.Args[1]} + } else { + return strings.Split(ids, ",") + } +} + +//DownloadStreams download a batch of elements asynchronously +func concurrentDownload(maxOperations int, format string, urls []string) error { + for _, url := range urls { + // download video + go func(url string) { + cUrl := C.CString(url) + cPath := C.CString(path) + + C.download(cUrl, cPath) + }(url) + } + return nil +} + +func usageAndExit(message string, exitCode int) { + if message != "" { + log.Fatalf(message) + } + flag.Usage() + os.Exit(exitCode) +}