Skip to content

Commit

Permalink
Clean up and re organise code. Deprecated gotubedl
Browse files Browse the repository at this point in the history
  • Loading branch information
nxrmqlly committed Oct 16, 2024
1 parent dcb0771 commit 9930d46
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 105 deletions.
92 changes: 0 additions & 92 deletions app.go

This file was deleted.

21 changes: 21 additions & 0 deletions backend/controllers/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package controllers

import (
"context"
)

// App struct
type App struct {
ctx context.Context
}

// NewApp creates a new App application struct
func NewApp() *App {
return &App{}
}

// startup is called hen the app starts. The context is saved
// so we can call the runtime methods
func (a *App) Startup(ctx context.Context) {
a.ctx = ctx
}
93 changes: 93 additions & 0 deletions backend/controllers/download.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package controllers

import (
"fmt"
"os/exec"
"regexp"
"strings"
"unicode"

"youtube-downloader-go/backend/models"

"github.com/wailsapp/wails/v2/pkg/runtime"
)

var youtubeRegex, _ = regexp.Compile(`^((?:https?:)?\/\/)?((?:www|m)\.)?((?:youtube(?:-nocookie)?\.com|youtu.be))(\/(?:[\w\-]+\?v=|embed\/|live\/|v\/)?)([\w\-]+)(\S+)?$`)

// Check if the url is valid youtube video URL
func isValidYouTubeURL(url string) bool {
return youtubeRegex.MatchString(url)
}

func slugify(input string) string {
// Remove non-ASCII characters
cleaned := strings.Map(func(r rune) rune {
if r > unicode.MaxASCII || !unicode.IsPrint(r) {
return -1 // remove character
}
return r
}, input)

// Replace spaces with underscores
cleaned = strings.ReplaceAll(cleaned, " ", "_")

// Remove characters that are invalid in file names
reg, _ := regexp.Compile(`[^a-zA-Z0-9._-]`)
cleaned = reg.ReplaceAllString(cleaned, "")

// Ensure the filename is not empty
if len(cleaned) == 0 {
cleaned = "default_filename"
}

return cleaned
}

// Download the video by the url specified
func (a *App) DownloadVideo(opts models.DownloadOptions) (string, error) {
//* check if the url is valid

var url = opts.URL

if !isValidYouTubeURL(url) {
err := fmt.Errorf("invalid url: %s", url)
return err.Error(), err
}

pathToSave, err := runtime.SaveFileDialog(a.ctx, runtime.SaveDialogOptions{Title: "Save File"})

if err != nil {
return err.Error(), err
}

cmdArgs := []string{"-o", pathToSave, url}

// Set download type
if opts.DownloadType == "video" {
cmdArgs = append(cmdArgs, "--format", fmt.Sprintf("bestvideo[ext=%s]", opts.FileType))
} else if opts.DownloadType == "audio" {
cmdArgs = append(cmdArgs, "--format", fmt.Sprintf("bestaudio[ext=%s]", opts.FileType))
} else {
err := fmt.Errorf("invalid download type: %s", opts.DownloadType)
return err.Error(), err
}

// Set resolution and quality options if provided
if opts.Resolution != "" {
cmdArgs = append(cmdArgs, "--format", fmt.Sprintf("%s+%s", opts.Resolution, opts.Quality))
}

// Execute yt-dlp command
cmd := exec.Command("yt-dlp", cmdArgs...)
output, err := cmd.CombinedOutput()
if err != nil {
err := fmt.Errorf("error executing yt-dlp: %v\nOutput: %s", err, string(output))
return err.Error(), err
}

// Print useful information
fmt.Printf("Downloaded %s from %s to %s\n", opts.DownloadType, url, pathToSave)
fmt.Println(string(output))

return "Done downloading", nil
}
9 changes: 9 additions & 0 deletions backend/models/download_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package models

type DownloadOptions struct {
URL string // e.g., "https://www.youtube.com/watch?v=1234"
DownloadType string // "video" or "audio"
FileType string // e.g., "mp4", "mp3"
Resolution string // e.g., "720p", "1080p"
Quality string // e.g., "best", "worst"
}
23 changes: 21 additions & 2 deletions get_ytdlp.go → backend/utils/get_ytdlp.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package main
package utils

import (
"fmt"
"io"
"net/http"
"os"
"path/filepath"

"github.com/wader/goutubedl"
)

const YtDlpGitgubRelease = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe"

// If yt-dlp isn't installed yet, download it locally.
func GetYtDlp() {
func getYtDlp() {
folderPath := "./bin-deps"

// Check if the folder exists
Expand Down Expand Up @@ -39,3 +42,19 @@ func GetYtDlp() {
io.Copy(out, resp.Body)

}

// Get yt-dlp if not exists, returns cwd and path of yt-dlp
func YtDlSetup() (string, string) {
// check if ./bin-deps/yt-dlp.exe exists
if _, err := os.Stat("./bin-deps/yt-dlp.exe"); os.IsNotExist(err) {
getYtDlp()
}

var cwd, err = os.Getwd()
if err != nil {
panic(err)
}
goutubedl.Path = filepath.Join(cwd, "bin-deps", "yt-dlp.exe")

return cwd, goutubedl.Path
}
1 change: 0 additions & 1 deletion frontend/jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
* a value or a type, so tell TypeScript to enforce using
* `import type` instead of `import` for Types.
*/
"importsNotUsedAsValues": "error",
"isolatedModules": true,
"ignoreDeprecations": "5.0",
"resolveJsonModule": true,
Expand Down
31 changes: 24 additions & 7 deletions frontend/src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
<script>
import { DownloadVideo } from '../wailsjs/go/main/App.js'
import { DownloadVideo } from '../wailsjs/go/controllers/App.js'
let url
let text = ""
function handleButtonClick() {
DownloadVideo(url).then((result) => {
text = result
})
/*
type DownloadOptions struct {
Path string
DownloadType string // "video" or "audio"
FileType string // e.g., "mp4", "mp3"
Resolution string // e.g., "720p", "1080p"
Quality string // e.g., "best", "worst"
}
*/
const downloadOptions = {
URL: url,
DownloadType: "video",
FileType: "mp4",
Resolution: "720p",
Quality: "best",
}
function handleButtonClick() {
DownloadVideo(downloadOptions).then((result) => {
text = result;
});
}
</script>


Expand All @@ -16,8 +32,9 @@
<div class="input-box" id="input">
<p>{text}</p>
<input autocomplete="off" bind:value={url} class="input" id="name" type="text"/>
<button class="btn" on:click={handleButtonClick}>Download</button>
<button class="btn" on:click={handleButtonClick}>Get</button>
</div>

</main>


Expand Down
7 changes: 4 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"os"

"youtube-downloader-go/backend/controllers"

"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
Expand All @@ -17,7 +19,7 @@ func main() {
fmt.Println(os.Getwd())

// Create an instance of the app structure
app := NewApp()
app := controllers.NewApp()

// Create application with options
err := wails.Run(&options.App{
Expand All @@ -27,8 +29,7 @@ func main() {
AssetServer: &assetserver.Options{
Assets: assets,
},
BackgroundColour: &options.RGBA{R: 64, G: 1, B: 43, A: 1},
OnStartup: app.startup,
OnStartup: app.Startup,
Bind: []interface{}{
app,
},
Expand Down

0 comments on commit 9930d46

Please sign in to comment.