102 lines
2.3 KiB
Go
Executable File
102 lines
2.3 KiB
Go
Executable File
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"local/jbtserve/jbt"
|
|
"local/system/sysconf"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"path"
|
|
"regexp"
|
|
"strings"
|
|
"syscall"
|
|
|
|
"github.com/otium/ytdl"
|
|
)
|
|
|
|
var validURL = regexp.MustCompile("(?is)https?://([a-z1-9]+.)+[a-z]+/.*")
|
|
|
|
func main() {
|
|
if os.Getenv("MNT") == "" {
|
|
os.Setenv("MNT", "./")
|
|
}
|
|
if !strings.HasSuffix(os.Getenv("MNT"), "/") {
|
|
os.Setenv("MNT", os.Getenv("MNT")+"/")
|
|
}
|
|
config := sysconf.Get("ytubespdrun")
|
|
exit := make(chan bool)
|
|
go jbt.RegisterDeregister(config.Name, config.Port, exit)
|
|
log.Print("Listen on", net.JoinHostPort(config.IP, config.Port))
|
|
go func() {
|
|
log.Print(http.ListenAndServe(net.JoinHostPort(config.IP, config.Port), http.HandlerFunc(accept)))
|
|
}()
|
|
sigc := make(chan os.Signal)
|
|
signal.Notify(sigc,
|
|
syscall.SIGINT,
|
|
)
|
|
<-sigc
|
|
<-exit
|
|
<-exit
|
|
}
|
|
|
|
func accept(w http.ResponseWriter, r *http.Request) {
|
|
config := sysconf.Get("ytubespdrun")
|
|
if r.Method != "POST" {
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
body, err := ioutil.ReadAll(r.Body)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
token := string(body)
|
|
token = strings.Split(token, "&")[0]
|
|
log.Print("Received request", token)
|
|
if !validURL.MatchString(token) {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
if err := download(token, config.Log); err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
fmt.Fprintf(w, "Cannot download %s, encountered error %v", token, err)
|
|
log.Print("Failed request", token)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusOK)
|
|
log.Print("Completed request", token)
|
|
}
|
|
|
|
func download(url, log string) error {
|
|
vid, err := ytdl.GetVideoInfo(url)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
format := vid.Formats.Best(ytdl.FormatExtensionKey)
|
|
if len(format) < 1 {
|
|
return errors.New("no formats available")
|
|
}
|
|
log.Print("Downloading format", format[0].Resolution, format[0].Extension, format[0].Itag, "for video", vid.Title)
|
|
file, err := os.Create(os.Getenv("MNT") + strings.Replace(fmt.Sprintf("%s.%s", vid.Title, format[0].Extension), " ", "_", -1))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
return vid.Download(format[0], file)
|
|
}
|
|
|
|
func pathAdvance(r *http.Request) string {
|
|
p := path.Clean("/" + r.URL.Path)
|
|
i := strings.Index(p[1:], "/") + 1
|
|
if i <= 0 {
|
|
r.URL.Path = "/"
|
|
return p[1:]
|
|
}
|
|
r.URL.Path = p[i:]
|
|
return p[1:i]
|
|
}
|