mirror of
https://github.com/marcopiovanello/yt-dlp-web-ui.git
synced 2025-12-05 19:06:41 -06:00
97 custom arguments broken (#99)
* golang debug * handle template in playlist download * code refactoring, dropped goccy go json
This commit is contained in:
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@@ -5,11 +5,11 @@
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch file",
|
||||
"name": "go",
|
||||
"type": "go",
|
||||
"request": "launch",
|
||||
"mode": "debug",
|
||||
"program": "${file}"
|
||||
"program": "main.go"
|
||||
},
|
||||
{
|
||||
"type": "chrome",
|
||||
|
||||
@@ -6,4 +6,12 @@ export const downloadTemplateState = atom({
|
||||
effects: [
|
||||
({ onSet }) => onSet(e => localStorage.setItem('lastDownloadTemplate', e))
|
||||
]
|
||||
})
|
||||
|
||||
export const filenameTemplateState = atom({
|
||||
key: 'filenameTemplateState',
|
||||
default: localStorage.getItem('lastFilenameTemplate') ?? '',
|
||||
effects: [
|
||||
({ onSet }) => onSet(e => localStorage.setItem('lastFilenameTemplate', e))
|
||||
]
|
||||
})
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
useTransition
|
||||
} from 'react'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { downloadTemplateState } from '../atoms/downloadTemplate'
|
||||
import { downloadTemplateState, filenameTemplateState } from '../atoms/downloadTemplate'
|
||||
import { settingsState } from '../atoms/settings'
|
||||
import { availableDownloadPathsState, connectedState } from '../atoms/status'
|
||||
import FormatsGrid from '../components/FormatsGrid'
|
||||
@@ -74,7 +74,9 @@ export default function DownloadDialog({
|
||||
const [customArgs, setCustomArgs] = useRecoilState(downloadTemplateState)
|
||||
const [downloadPath, setDownloadPath] = useState(0)
|
||||
|
||||
const [fileNameOverride, setFilenameOverride] = useState('')
|
||||
const [filenameTemplate, setFilenameTemplate] = useRecoilState(
|
||||
filenameTemplateState
|
||||
)
|
||||
|
||||
const [url, setUrl] = useState('')
|
||||
const [workingUrl, setWorkingUrl] = useState('')
|
||||
@@ -110,7 +112,7 @@ export default function DownloadDialog({
|
||||
immediate || url || workingUrl,
|
||||
`${cliArgs.toString()} ${toFormatArgs(codes)} ${customArgs}`,
|
||||
availableDownloadPaths[downloadPath] ?? '',
|
||||
fileNameOverride,
|
||||
filenameTemplate,
|
||||
isPlaylist,
|
||||
)
|
||||
|
||||
@@ -141,27 +143,15 @@ export default function DownloadDialog({
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the url state whenever the input value changes
|
||||
* @param e Input change event
|
||||
*/
|
||||
const handleUrlChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setUrl(e.target.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the filename override state whenever the input value changes
|
||||
* @param e Input change event
|
||||
*/
|
||||
const handleFilenameOverrideChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setFilenameOverride(e.target.value)
|
||||
const handleFilenameTemplateChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setFilenameTemplate(e.target.value)
|
||||
localStorage.setItem('last-filename-override', e.target.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the custom args state whenever the input value changes
|
||||
* @param e Input change event
|
||||
*/
|
||||
const handleCustomArgsChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setCustomArgs(e.target.value)
|
||||
localStorage.setItem("last-input-args", e.target.value)
|
||||
@@ -285,8 +275,8 @@ export default function DownloadDialog({
|
||||
fullWidth
|
||||
label={i18n.t('customFilename')}
|
||||
variant="outlined"
|
||||
value={fileNameOverride}
|
||||
onChange={handleFilenameOverrideChange}
|
||||
value={filenameTemplate}
|
||||
onChange={handleFilenameTemplateChange}
|
||||
disabled={
|
||||
!isConnected ||
|
||||
(settings.formatSelection && downloadFormats != null)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Observable, share } from 'rxjs'
|
||||
import { Observable } from 'rxjs'
|
||||
import type { DLMetadata, RPCRequest, RPCResponse, RPCResult } from '../types'
|
||||
|
||||
import { WebSocketSubject, webSocket } from 'rxjs/webSocket'
|
||||
@@ -29,6 +29,12 @@ export class RPCClient {
|
||||
})
|
||||
}
|
||||
|
||||
private argsSanitizer(args: string) {
|
||||
return args
|
||||
.split(' ')
|
||||
.map(a => a.trim().replaceAll("'", '').replaceAll('"', ''))
|
||||
}
|
||||
|
||||
private async sendHTTP<T>(req: RPCRequest) {
|
||||
const res = await fetch(this.httpEndpoint, {
|
||||
method: 'POST',
|
||||
@@ -57,16 +63,17 @@ export class RPCClient {
|
||||
method: 'Service.ExecPlaylist',
|
||||
params: [{
|
||||
URL: url,
|
||||
Params: args.split(" ").map(a => a.trim()),
|
||||
Params: this.argsSanitizer(args),
|
||||
Path: pathOverride,
|
||||
Rename: renameTo,
|
||||
}]
|
||||
})
|
||||
}
|
||||
this.sendHTTP({
|
||||
method: 'Service.Exec',
|
||||
params: [{
|
||||
URL: url.split("?list").at(0)!,
|
||||
Params: args.split(" ").map(a => a.trim()),
|
||||
URL: url.split('?list').at(0)!,
|
||||
Params: this.argsSanitizer(args),
|
||||
Path: pathOverride,
|
||||
Rename: renameTo,
|
||||
}]
|
||||
@@ -78,7 +85,7 @@ export class RPCClient {
|
||||
return this.sendHTTP<DLMetadata>({
|
||||
method: 'Service.Formats',
|
||||
params: [{
|
||||
URL: url.split("?list").at(0)!,
|
||||
URL: url.split('?list').at(0)!,
|
||||
}]
|
||||
})
|
||||
}
|
||||
|
||||
1
go.mod
1
go.mod
@@ -5,7 +5,6 @@ go 1.20
|
||||
require (
|
||||
github.com/go-chi/chi/v5 v5.0.10
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/goccy/go-json v0.10.2
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0
|
||||
github.com/google/uuid v1.3.1
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
|
||||
4
go.sum
4
go.sum
@@ -2,8 +2,6 @@ github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
|
||||
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
@@ -12,8 +10,6 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/marcopeocchi/fazzoletti v0.0.0-20230308161120-c545580f79fa h1:uaAQLGhN4SesB9inOQ1Q6EH+BwTWHQOvwhR0TIJvnYc=
|
||||
github.com/marcopeocchi/fazzoletti v0.0.0-20230308161120-c545580f79fa/go.mod h1:RvfVo/6Sbnfra9kkvIxDW8NYOOaYsHjF0DdtMCs9cdo=
|
||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
|
||||
@@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -11,7 +12,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/marcopeocchi/yt-dlp-web-ui/server/config"
|
||||
"github.com/marcopeocchi/yt-dlp-web-ui/server/utils"
|
||||
)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/marcopeocchi/yt-dlp-web-ui/server/config"
|
||||
"github.com/marcopeocchi/yt-dlp-web-ui/server/utils"
|
||||
|
||||
@@ -7,7 +7,7 @@ type DownloadProgress struct {
|
||||
Status int `json:"process_status"`
|
||||
Percentage string `json:"percentage"`
|
||||
Speed float32 `json:"speed"`
|
||||
ETA int `json:"eta"`
|
||||
ETA float32 `json:"eta"`
|
||||
}
|
||||
|
||||
// Used to deser the yt-dlp -J output
|
||||
@@ -50,6 +50,8 @@ type ProcessResponse struct {
|
||||
Id string `json:"id"`
|
||||
Progress DownloadProgress `json:"progress"`
|
||||
Info DownloadInfo `json:"info"`
|
||||
Output DownloadOutput `json:"output"`
|
||||
Params []string `json:"params"`
|
||||
}
|
||||
|
||||
// struct representing the current status of the memoryDB
|
||||
|
||||
@@ -85,6 +85,8 @@ func (m *MemoryDB) All() *[]ProcessResponse {
|
||||
Id: key.(string),
|
||||
Info: value.(*Process).Info,
|
||||
Progress: value.(*Process).Progress,
|
||||
Output: value.(*Process).Output,
|
||||
Params: value.(*Process).Params,
|
||||
})
|
||||
return true
|
||||
})
|
||||
@@ -137,6 +139,8 @@ func (m *MemoryDB) Restore() {
|
||||
Url: proc.Info.URL,
|
||||
Info: proc.Info,
|
||||
Progress: proc.Progress,
|
||||
Output: proc.Output,
|
||||
Params: proc.Params,
|
||||
}
|
||||
|
||||
m.table.Store(proc.Id, restored)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"log"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/marcopeocchi/yt-dlp-web-ui/server/cli"
|
||||
"github.com/marcopeocchi/yt-dlp-web-ui/server/config"
|
||||
)
|
||||
@@ -60,9 +60,11 @@ func PlaylistDetect(req DownloadRequest, mq *MessageQueue, db *MemoryDB) error {
|
||||
proc := &Process{
|
||||
Url: meta.OriginalURL,
|
||||
Progress: DownloadProgress{},
|
||||
Output: DownloadOutput{},
|
||||
Info: meta,
|
||||
Params: req.Params,
|
||||
Output: DownloadOutput{
|
||||
Filename: req.Rename,
|
||||
},
|
||||
Info: meta,
|
||||
Params: req.Params,
|
||||
}
|
||||
|
||||
proc.Info.URL = meta.OriginalURL
|
||||
|
||||
@@ -2,13 +2,12 @@ package internal
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -38,7 +37,7 @@ type ProgressTemplate struct {
|
||||
Percentage string `json:"percentage"`
|
||||
Speed float32 `json:"speed"`
|
||||
Size string `json:"size"`
|
||||
Eta int `json:"eta"`
|
||||
Eta float32 `json:"eta"`
|
||||
}
|
||||
|
||||
// Process descriptor
|
||||
@@ -70,6 +69,10 @@ func (p *Process) Start() {
|
||||
return !match
|
||||
})
|
||||
|
||||
p.Params = slices.Filter(p.Params, func(e string) bool {
|
||||
return e != ""
|
||||
})
|
||||
|
||||
out := DownloadOutput{
|
||||
Path: config.Instance().GetConfig().DownloadPath,
|
||||
Filename: "%(title)s.%(ext)s",
|
||||
@@ -87,7 +90,8 @@ func (p *Process) Start() {
|
||||
"--newline",
|
||||
"--no-colors",
|
||||
"--no-playlist",
|
||||
"--progress-template", strings.ReplaceAll(template, "\n", ""),
|
||||
"--progress-template",
|
||||
strings.NewReplacer("\n", "", "\t", "", " ", "").Replace(template),
|
||||
"-o",
|
||||
fmt.Sprintf("%s/%s", out.Path, out.Filename),
|
||||
}, p.Params...)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/marcopeocchi/yt-dlp-web-ui/server/internal"
|
||||
)
|
||||
|
||||
@@ -19,7 +19,7 @@ func (h *Handler) Exec() http.HandlerFunc {
|
||||
|
||||
req := internal.DownloadRequest{}
|
||||
|
||||
if err := json.NewDecoder(r.Body).DecodeContext(r.Context(), &req); err != nil {
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ func (h *Handler) Exec() http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).EncodeContext(r.Context(), id)
|
||||
err = json.NewEncoder(w).Encode(id)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
@@ -48,7 +48,7 @@ func (h *Handler) Running() http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).EncodeContext(r.Context(), res)
|
||||
err = json.NewEncoder(w).Encode(res)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func (h *Handler) SetCookies() http.HandlerFunc {
|
||||
|
||||
req := new(internal.SetCookiesRequest)
|
||||
|
||||
err := json.NewDecoder(r.Body).DecodeContext(r.Context(), req)
|
||||
err := json.NewDecoder(r.Body).Decode(req)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
@@ -75,7 +75,7 @@ func (h *Handler) SetCookies() http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
err = json.NewEncoder(w).EncodeContext(r.Context(), "ok")
|
||||
err = json.NewEncoder(w).Encode("ok")
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user