Seperate everything into different files to prevent me from going insane
This commit is contained in:
parent
1b0a8fde36
commit
078d0c774b
41
config.go
Normal file
41
config.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
BaseDir string
|
||||||
|
Format string
|
||||||
|
N_m3u8DLRE struct {
|
||||||
|
Path string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var config Config
|
||||||
|
|
||||||
|
func loadConfig() {
|
||||||
|
configFile, err := os.Open("config.toml")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error opening config file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer configFile.Close()
|
||||||
|
|
||||||
|
byteValue, _ := io.ReadAll(configFile)
|
||||||
|
|
||||||
|
if _, err := toml.Decode(string(byteValue), &config); err != nil {
|
||||||
|
fmt.Println("Error decoding config file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.N_m3u8DLRE.Path == "" {
|
||||||
|
fmt.Println("Error: N_m3u8DL-RE path is not specified in the config file")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
130
downloaders.go
Normal file
130
downloaders.go
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func processInputFile(inputFile string) error {
|
||||||
|
jsonFile, err := os.Open(inputFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error opening file %s: %v", inputFile, err)
|
||||||
|
}
|
||||||
|
defer jsonFile.Close()
|
||||||
|
|
||||||
|
byteValue, err := io.ReadAll(jsonFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error reading file %s: %v", inputFile, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var items Items
|
||||||
|
err = json.Unmarshal(byteValue, &items)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error unmarshaling JSON: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, item := range items.Items {
|
||||||
|
updateProgress(filepath.Base(inputFile), float64(i)/float64(len(items.Items))*100, item.Filename)
|
||||||
|
err := downloadFile(item)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error downloading file: %v\n", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateProgress(filepath.Base(inputFile), 100, "")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadFile(item Item) error {
|
||||||
|
fmt.Println("Downloading:", item.Filename)
|
||||||
|
|
||||||
|
mpdPath := item.MPD
|
||||||
|
if !isValidURL(item.MPD) {
|
||||||
|
|
||||||
|
decodedMPD, err := base64.StdEncoding.DecodeString(item.MPD)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error decoding base64 MPD: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tempFile, err := os.CreateTemp("", "temp_mpd_*.mpd")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error creating temporary MPD file: %v", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(tempFile.Name())
|
||||||
|
|
||||||
|
if _, err := tempFile.Write(decodedMPD); err != nil {
|
||||||
|
return fmt.Errorf("error writing to temporary MPD file: %v", err)
|
||||||
|
}
|
||||||
|
if err := tempFile.Close(); err != nil {
|
||||||
|
return fmt.Errorf("error closing temporary MPD file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mpdPath = tempFile.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
command := getDownloadCommand(item, mpdPath)
|
||||||
|
|
||||||
|
if item.Subtitles != "" {
|
||||||
|
subtitlePaths, err := downloadAndConvertSubtitles(item.Subtitles)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error processing subtitles: %v\n", err)
|
||||||
|
} else {
|
||||||
|
for _, path := range subtitlePaths {
|
||||||
|
fmt.Println("Adding subtitle:", path)
|
||||||
|
command += fmt.Sprintf(" --mux-import \"path=%s:lang=nl:name=Nederlands\"", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command("bash", "-c", command)
|
||||||
|
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error executing download command: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("Download completed successfully")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDownloadCommand(item Item, mpdPath string) string {
|
||||||
|
metadata := parseMetadata(item.Metadata)
|
||||||
|
keys := getKeys(item.Keys)
|
||||||
|
|
||||||
|
command := fmt.Sprintf("%s %s", config.N_m3u8DLRE.Path, mpdPath)
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
if key != "" {
|
||||||
|
command += fmt.Sprintf(" --key %s", key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command += " --auto-select"
|
||||||
|
|
||||||
|
sanitizedFilename := sanitizeFilename(item.Filename)
|
||||||
|
|
||||||
|
filename := fmt.Sprintf("\"%s\"", sanitizedFilename)
|
||||||
|
command += fmt.Sprintf(" --save-name %s", filename)
|
||||||
|
|
||||||
|
command += fmt.Sprintf(" --mux-after-done format=%s", config.Format)
|
||||||
|
|
||||||
|
saveDir := config.BaseDir
|
||||||
|
if metadata.Type == "serie" {
|
||||||
|
saveDir = filepath.Join(saveDir, "Series", metadata.Title, metadata.Season)
|
||||||
|
} else {
|
||||||
|
saveDir = filepath.Join(saveDir, "Movies", metadata.Title)
|
||||||
|
}
|
||||||
|
command += fmt.Sprintf(" --save-dir \"%s\"", saveDir)
|
||||||
|
|
||||||
|
fmt.Println(command)
|
||||||
|
|
||||||
|
return command
|
||||||
|
}
|
96
handlers.go
Normal file
96
handlers.go
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleRoot(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.URL.Path != "/" {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
progressMutex.Lock()
|
||||||
|
jobs := make(map[string]*ProgressInfo)
|
||||||
|
for k, v := range progress {
|
||||||
|
jobs[k] = v
|
||||||
|
}
|
||||||
|
progressMutex.Unlock()
|
||||||
|
|
||||||
|
err := templates.ExecuteTemplate(w, "index", struct{ Jobs map[string]*ProgressInfo }{jobs})
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleUpload(w http.ResponseWriter, r *http.Request) {
|
||||||
|
file, header, err := r.FormFile("file")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
filename := fmt.Sprintf("%d_%s", time.Now().UnixNano(), header.Filename)
|
||||||
|
filepath := filepath.Join(uploadDir, filename)
|
||||||
|
|
||||||
|
newFile, err := os.Create(filepath)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer newFile.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(newFile, file)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := processInputFile(filepath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error processing file: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Remove(filepath)
|
||||||
|
}()
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/progress?filename="+filename, http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleProgress(w http.ResponseWriter, r *http.Request) {
|
||||||
|
filename := r.URL.Query().Get("filename")
|
||||||
|
fmt.Printf("Handling progress request for filename: %s\n", filename)
|
||||||
|
|
||||||
|
if r.Header.Get("Accept") == "application/json" {
|
||||||
|
progressInfo := getProgress(filename)
|
||||||
|
fmt.Printf("Progress info for %s: %+v\n", filename, progressInfo)
|
||||||
|
|
||||||
|
if progressInfo == nil {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
json.NewEncoder(w).Encode(map[string]string{"error": "No progress information found"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
err := json.NewEncoder(w).Encode(progressInfo)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error encoding progress info: %v\n", err)
|
||||||
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := templates.ExecuteTemplate(w, "progress", struct{ Filename string }{filename})
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
304
main.go
304
main.go
@ -1,26 +1,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"embed"
|
"embed"
|
||||||
"regexp"
|
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
"github.com/asticode/go-astisub"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
@ -43,15 +32,6 @@ type Metadata struct {
|
|||||||
Season string
|
Season string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
BaseDir string
|
|
||||||
Format string
|
|
||||||
N_m3u8DLRE struct {
|
|
||||||
Path string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var config Config
|
|
||||||
var progressMutex sync.Mutex
|
var progressMutex sync.Mutex
|
||||||
var progress = make(map[string]*ProgressInfo)
|
var progress = make(map[string]*ProgressInfo)
|
||||||
|
|
||||||
@ -76,25 +56,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
configFile, err := os.Open("config.toml")
|
loadConfig()
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error opening config file:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer configFile.Close()
|
|
||||||
|
|
||||||
byteValue, _ := io.ReadAll(configFile)
|
|
||||||
|
|
||||||
if _, err := toml.Decode(string(byteValue), &config); err != nil {
|
|
||||||
fmt.Println("Error decoding config file:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.N_m3u8DLRE.Path == "" {
|
|
||||||
fmt.Println("Error: N_m3u8DL-RE path is not specified in the config file")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
inputFile := flag.String("f", "", "Path to the input JSON file")
|
inputFile := flag.String("f", "", "Path to the input JSON file")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@ -114,121 +76,6 @@ func startWebServer() {
|
|||||||
http.ListenAndServe(":8080", nil)
|
http.ListenAndServe(":8080", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleRoot(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.URL.Path != "/" {
|
|
||||||
http.NotFound(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
progressMutex.Lock()
|
|
||||||
jobs := make(map[string]*ProgressInfo)
|
|
||||||
for k, v := range progress {
|
|
||||||
jobs[k] = v
|
|
||||||
}
|
|
||||||
progressMutex.Unlock()
|
|
||||||
|
|
||||||
err := templates.ExecuteTemplate(w, "index", struct{ Jobs map[string]*ProgressInfo }{jobs})
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleUpload(w http.ResponseWriter, r *http.Request) {
|
|
||||||
file, header, err := r.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
filename := fmt.Sprintf("%d_%s", time.Now().UnixNano(), header.Filename)
|
|
||||||
filepath := filepath.Join(uploadDir, filename)
|
|
||||||
|
|
||||||
newFile, err := os.Create(filepath)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer newFile.Close()
|
|
||||||
|
|
||||||
_, err = io.Copy(newFile, file)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
err := processInputFile(filepath)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error processing file: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Remove(filepath)
|
|
||||||
}()
|
|
||||||
|
|
||||||
http.Redirect(w, r, "/progress?filename="+filename, http.StatusSeeOther)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleProgress(w http.ResponseWriter, r *http.Request) {
|
|
||||||
filename := r.URL.Query().Get("filename")
|
|
||||||
fmt.Printf("Handling progress request for filename: %s\n", filename)
|
|
||||||
|
|
||||||
if r.Header.Get("Accept") == "application/json" {
|
|
||||||
progressInfo := getProgress(filename)
|
|
||||||
fmt.Printf("Progress info for %s: %+v\n", filename, progressInfo)
|
|
||||||
|
|
||||||
if progressInfo == nil {
|
|
||||||
w.WriteHeader(http.StatusNotFound)
|
|
||||||
json.NewEncoder(w).Encode(map[string]string{"error": "No progress information found"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
err := json.NewEncoder(w).Encode(progressInfo)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error encoding progress info: %v\n", err)
|
|
||||||
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err := templates.ExecuteTemplate(w, "progress", struct{ Filename string }{filename})
|
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func processInputFile(inputFile string) error {
|
|
||||||
jsonFile, err := os.Open(inputFile)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error opening file %s: %v", inputFile, err)
|
|
||||||
}
|
|
||||||
defer jsonFile.Close()
|
|
||||||
|
|
||||||
byteValue, err := io.ReadAll(jsonFile)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error reading file %s: %v", inputFile, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var items Items
|
|
||||||
err = json.Unmarshal(byteValue, &items)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error unmarshaling JSON: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, item := range items.Items {
|
|
||||||
updateProgress(filepath.Base(inputFile), float64(i)/float64(len(items.Items))*100, item.Filename)
|
|
||||||
err := downloadFile(item)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error downloading file: %v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateProgress(filepath.Base(inputFile), 100, "")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateProgress(filename string, value float64, currentFile string) {
|
func updateProgress(filename string, value float64, currentFile string) {
|
||||||
progressMutex.Lock()
|
progressMutex.Lock()
|
||||||
defer progressMutex.Unlock()
|
defer progressMutex.Unlock()
|
||||||
@ -260,152 +107,3 @@ func parseMetadata(metadata string) Metadata {
|
|||||||
Season: "S" + strings.TrimSpace(parts[2]),
|
Season: "S" + strings.TrimSpace(parts[2]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDownloadCommand(item Item, mpdPath string) string {
|
|
||||||
metadata := parseMetadata(item.Metadata)
|
|
||||||
keys := getKeys(item.Keys)
|
|
||||||
|
|
||||||
command := fmt.Sprintf("%s %s", config.N_m3u8DLRE.Path, mpdPath)
|
|
||||||
|
|
||||||
for _, key := range keys {
|
|
||||||
if key != "" {
|
|
||||||
command += fmt.Sprintf(" --key %s", key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
command += " --auto-select"
|
|
||||||
|
|
||||||
sanitizedFilename := sanitizeFilename(item.Filename)
|
|
||||||
|
|
||||||
filename := fmt.Sprintf("\"%s\"", sanitizedFilename)
|
|
||||||
command += fmt.Sprintf(" --save-name %s", filename)
|
|
||||||
|
|
||||||
command += fmt.Sprintf(" --mux-after-done format=%s", config.Format)
|
|
||||||
|
|
||||||
saveDir := config.BaseDir
|
|
||||||
if metadata.Type == "serie" {
|
|
||||||
saveDir = filepath.Join(saveDir, "Series", metadata.Title, metadata.Season)
|
|
||||||
} else {
|
|
||||||
saveDir = filepath.Join(saveDir, "Movies", metadata.Title)
|
|
||||||
}
|
|
||||||
command += fmt.Sprintf(" --save-dir \"%s\"", saveDir)
|
|
||||||
|
|
||||||
fmt.Println(command)
|
|
||||||
|
|
||||||
return command
|
|
||||||
}
|
|
||||||
|
|
||||||
func sanitizeFilename(filename string) string {
|
|
||||||
filename = regexp.MustCompile(`[<>:"/\\|?*]`).ReplaceAllString(filename, "_")
|
|
||||||
|
|
||||||
filename = strings.Trim(filename, ".")
|
|
||||||
|
|
||||||
return filename
|
|
||||||
}
|
|
||||||
|
|
||||||
func downloadFile(item Item) error {
|
|
||||||
fmt.Println("Downloading:", item.Filename)
|
|
||||||
|
|
||||||
mpdPath := item.MPD
|
|
||||||
if !isValidURL(item.MPD) {
|
|
||||||
|
|
||||||
decodedMPD, err := base64.StdEncoding.DecodeString(item.MPD)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error decoding base64 MPD: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tempFile, err := os.CreateTemp("", "temp_mpd_*.mpd")
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error creating temporary MPD file: %v", err)
|
|
||||||
}
|
|
||||||
defer os.Remove(tempFile.Name())
|
|
||||||
|
|
||||||
if _, err := tempFile.Write(decodedMPD); err != nil {
|
|
||||||
return fmt.Errorf("error writing to temporary MPD file: %v", err)
|
|
||||||
}
|
|
||||||
if err := tempFile.Close(); err != nil {
|
|
||||||
return fmt.Errorf("error closing temporary MPD file: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mpdPath = tempFile.Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
command := getDownloadCommand(item, mpdPath)
|
|
||||||
|
|
||||||
subtitlePaths, err := downloadAndConvertSubtitles(item.Subtitles)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error processing subtitles: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, path := range subtitlePaths {
|
|
||||||
fmt.Println("Adding subtitle:", path)
|
|
||||||
command += fmt.Sprintf(" --mux-import \"path=%s:lang=nl:name=Nederlands\"", path)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := exec.Command("bash", "-c", command)
|
|
||||||
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
|
|
||||||
err = cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("error executing download command: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("Download completed successfully")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func downloadAndConvertSubtitles(subtitlesURLs string) ([]string, error) {
|
|
||||||
var subtitlePaths []string
|
|
||||||
urls := strings.Split(subtitlesURLs, ",")
|
|
||||||
|
|
||||||
for _, url := range urls {
|
|
||||||
vttPath, err := downloadSubtitle(url)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error downloading subtitle: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
srtPath, err := convertVTTtoSRT(vttPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("error converting subtitle: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
subtitlePaths = append(subtitlePaths, srtPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
return subtitlePaths, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func downloadSubtitle(url string) (string, error) {
|
|
||||||
resp, err := http.Get(url)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
tempFile, err := os.CreateTemp("", "subtitle_*.vtt")
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer tempFile.Close()
|
|
||||||
|
|
||||||
_, err = io.Copy(tempFile, resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tempFile.Name(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertVTTtoSRT(vttPath string) (string, error) {
|
|
||||||
srtPath := strings.TrimSuffix(vttPath, ".vtt") + ".srt"
|
|
||||||
s1, _ := astisub.OpenFile(vttPath)
|
|
||||||
s1.Write(srtPath)
|
|
||||||
return srtPath, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isValidURL(toTest string) bool {
|
|
||||||
_, err := url.ParseRequestURI(toTest)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
60
subtitles.go
Normal file
60
subtitles.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/asticode/go-astisub"
|
||||||
|
)
|
||||||
|
|
||||||
|
func downloadAndConvertSubtitles(subtitlesURLs string) ([]string, error) {
|
||||||
|
var subtitlePaths []string
|
||||||
|
urls := strings.Split(subtitlesURLs, ",")
|
||||||
|
|
||||||
|
for _, url := range urls {
|
||||||
|
vttPath, err := downloadSubtitle(url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error downloading subtitle: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
srtPath, err := convertVTTtoSRT(vttPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error converting subtitle: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
subtitlePaths = append(subtitlePaths, srtPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
return subtitlePaths, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadSubtitle(url string) (string, error) {
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
tempFile, err := os.CreateTemp("", "subtitle_*.vtt")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer tempFile.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(tempFile, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tempFile.Name(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertVTTtoSRT(vttPath string) (string, error) {
|
||||||
|
srtPath := strings.TrimSuffix(vttPath, ".vtt") + ".srt"
|
||||||
|
s1, _ := astisub.OpenFile(vttPath)
|
||||||
|
s1.Write(srtPath)
|
||||||
|
return srtPath, nil
|
||||||
|
}
|
20
utils.go
Normal file
20
utils.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func sanitizeFilename(filename string) string {
|
||||||
|
filename = regexp.MustCompile(`[<>:"/\\|?*]`).ReplaceAllString(filename, "_")
|
||||||
|
|
||||||
|
filename = strings.Trim(filename, ".")
|
||||||
|
|
||||||
|
return filename
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidURL(toTest string) bool {
|
||||||
|
_, err := url.ParseRequestURI(toTest)
|
||||||
|
return err == nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user