Refactored downloader
This commit is contained in:
10
api/internal/core/ports/downloadhandler/downloadhandler.go
Normal file
10
api/internal/core/ports/downloadhandler/downloadhandler.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package downloadhandler
|
||||
|
||||
type OnDownloadEventHandler interface {
|
||||
OnTickEvent(downloadId string, progress string)
|
||||
}
|
||||
|
||||
type DownloadHandler interface {
|
||||
OnProgress(eventHandler OnDownloadEventHandler)
|
||||
Download(link string, outputDir string, downloadId string) error
|
||||
}
|
98
api/internal/core/ports/downloadhandler/youtube_dl.go
Normal file
98
api/internal/core/ports/downloadhandler/youtube_dl.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package downloadhandler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ovh/configstore"
|
||||
"go.uber.org/zap"
|
||||
"log"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type YoutubeDlDownloader struct {
|
||||
progressUpdate bool
|
||||
checkFrequencyMs time.Duration
|
||||
logger *zap.SugaredLogger
|
||||
onDownloadEventHandler OnDownloadEventHandler
|
||||
}
|
||||
|
||||
func NewYoutubeDlDownloader(logger *zap.SugaredLogger) DownloadHandler {
|
||||
var checkFrequencyMs int64
|
||||
var featureProgressUpdate bool
|
||||
var err error
|
||||
|
||||
checkFrequencyMs, err = configstore.GetItemValueInt("download_frequency_update_ms")
|
||||
featureProgressUpdate, err = configstore.GetItemValueBool("download_progress_update")
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = exec.Command("youtube-dl", "--version").Output()
|
||||
if err != nil {
|
||||
log.Fatal("Youtube download (youtube-dl) isn't installed on the device")
|
||||
}
|
||||
|
||||
return &YoutubeDlDownloader{
|
||||
checkFrequencyMs: time.Duration(checkFrequencyMs),
|
||||
progressUpdate: featureProgressUpdate,
|
||||
logger: logger,
|
||||
onDownloadEventHandler: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (y *YoutubeDlDownloader) OnProgress(eventHandler OnDownloadEventHandler) {
|
||||
y.onDownloadEventHandler = eventHandler
|
||||
}
|
||||
|
||||
func (y *YoutubeDlDownloader) Download(link string, outputDir string, downloadId string) error {
|
||||
filePath := fmt.Sprintf("%s/%s", outputDir, "%(title)s-%(id)s.%(ext)s")
|
||||
command := exec.Command("youtube-dl",
|
||||
"-R 3",
|
||||
"-o",
|
||||
filePath,
|
||||
link,
|
||||
)
|
||||
|
||||
stdout, err := command.StdoutPipe()
|
||||
|
||||
if y.progressUpdate {
|
||||
go func() {
|
||||
for true {
|
||||
bytes := make([]byte, 1024)
|
||||
_, err = stdout.Read(bytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
output := string(bytes)
|
||||
|
||||
if err = y.getParameters(output, link, downloadId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Millisecond * y.checkFrequencyMs)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
return command.Run()
|
||||
}
|
||||
|
||||
func (y *YoutubeDlDownloader) getParameters(output string, link string, downloadId string) error {
|
||||
compile := regexp.MustCompile(`[a-z\[\]\s]+([\d\.]+).[a-z\s]+([\d\.]+)([a-zA-Z]+)[a-z\s]+`)
|
||||
|
||||
res := compile.FindAllStringSubmatch(output, -1)
|
||||
if len(res) != 0 && strings.Contains(res[0][0], "download") && len(res[0]) >= 2 {
|
||||
progress := res[0][1]
|
||||
|
||||
y.logger.Debugw("progress",
|
||||
"percentage", progress,
|
||||
"link", link)
|
||||
if y.onDownloadEventHandler != nil {
|
||||
y.onDownloadEventHandler.OnTickEvent(downloadId, progress)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
98
api/internal/core/ports/downloadhandler/yt-dlp.go
Normal file
98
api/internal/core/ports/downloadhandler/yt-dlp.go
Normal file
@@ -0,0 +1,98 @@
|
||||
package downloadhandler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ovh/configstore"
|
||||
"go.uber.org/zap"
|
||||
"log"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type YtDlpDownloader struct {
|
||||
progressUpdate bool
|
||||
checkFrequencyMs time.Duration
|
||||
logger *zap.SugaredLogger
|
||||
onDownloadEventHandler OnDownloadEventHandler
|
||||
}
|
||||
|
||||
func NewYtDlpDownloader(logger *zap.SugaredLogger) DownloadHandler {
|
||||
var checkFrequencyMs int64
|
||||
var featureProgressUpdate bool
|
||||
var err error
|
||||
|
||||
checkFrequencyMs, err = configstore.GetItemValueInt("download_frequency_update_ms")
|
||||
featureProgressUpdate, err = configstore.GetItemValueBool("download_progress_update")
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = exec.Command("yt-dlp", "--version").Output()
|
||||
if err != nil {
|
||||
log.Fatal("Youtube download (youtube-dl) isn't installed on the device")
|
||||
}
|
||||
|
||||
return &YtDlpDownloader{
|
||||
checkFrequencyMs: time.Duration(checkFrequencyMs),
|
||||
progressUpdate: featureProgressUpdate,
|
||||
logger: logger,
|
||||
onDownloadEventHandler: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (y *YtDlpDownloader) OnProgress(eventHandler OnDownloadEventHandler) {
|
||||
y.onDownloadEventHandler = eventHandler
|
||||
}
|
||||
|
||||
func (y *YtDlpDownloader) Download(link string, outputDir string, downloadId string) error {
|
||||
filePath := fmt.Sprintf("%s/%s", outputDir, "%(title)s-%(id)s.%(ext)s")
|
||||
command := exec.Command("yt-dlp",
|
||||
"-R 3",
|
||||
"-o",
|
||||
filePath,
|
||||
link,
|
||||
)
|
||||
|
||||
stdout, err := command.StdoutPipe()
|
||||
|
||||
if y.progressUpdate {
|
||||
go func() {
|
||||
for true {
|
||||
bytes := make([]byte, 1024)
|
||||
_, err = stdout.Read(bytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
output := string(bytes)
|
||||
|
||||
if err = y.getParameters(output, link, downloadId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(time.Millisecond * y.checkFrequencyMs)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
return command.Run()
|
||||
}
|
||||
|
||||
func (y *YtDlpDownloader) getParameters(output string, link string, downloadId string) error {
|
||||
compile := regexp.MustCompile(`[a-z\[\]\s]+([\d\.]+).[a-z\s\~]+([\d\.]+)([a-zA-Z]+)[a-z\s]+`)
|
||||
|
||||
res := compile.FindAllStringSubmatch(output, -1)
|
||||
if len(res) != 0 && strings.Contains(res[0][0], "download") && len(res[0]) >= 2 {
|
||||
progress := res[0][1]
|
||||
|
||||
y.logger.Debugw("progress",
|
||||
"percentage", progress,
|
||||
"link", link)
|
||||
if y.onDownloadEventHandler != nil {
|
||||
y.onDownloadEventHandler.OnTickEvent(downloadId, progress)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user