159 lines
3.4 KiB
Go
159 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"path/filepath"
|
|
"strconv"
|
|
"time"
|
|
|
|
"git.andreafazzi.eu/andrea/youtube-dl-service/downloader"
|
|
youtube_dl "git.andreafazzi.eu/andrea/youtube-dl-service/downloader/youtube-dl"
|
|
"git.andreafazzi.eu/andrea/youtube-dl-service/task"
|
|
jwt "github.com/dgrijalva/jwt-go"
|
|
"github.com/gin-contrib/cors"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
const (
|
|
DefaultJWTExpireTime = 60
|
|
DefaultSigningKey = "secret"
|
|
)
|
|
|
|
var tasks task.Tasks
|
|
|
|
func init() {
|
|
log.SetPrefix("[youtube-dl-service] ")
|
|
tasks = make(task.Tasks, 0)
|
|
}
|
|
|
|
func download(c *gin.Context, downloader downloader.Downloader) error {
|
|
video, err := downloader.GetVideo()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
c.JSON(http.StatusOK, video)
|
|
|
|
go downloader.StartDownload(video, tasks)
|
|
|
|
return nil
|
|
}
|
|
|
|
func createTask(c *gin.Context) {
|
|
err := c.Request.ParseForm()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if err := download(c, youtube_dl.NewYoutubeDlDownloader(c.PostForm("url"), "yt-dlp")); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func getTask(c *gin.Context, id string) error {
|
|
task, ok := tasks[id]
|
|
if ok {
|
|
c.JSON(http.StatusOK, task)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func data(c *gin.Context, id string) error {
|
|
c.Writer.Header().Set("Content-Disposition", "attachment; filename="+strconv.Quote(tasks[id].Filename))
|
|
c.Writer.Header().Set("Content-Type", "application/octet-stream")
|
|
http.ServeFile(c.Writer, c.Request, filepath.Join("data", id+filepath.Ext(tasks[id].Filename)))
|
|
return nil
|
|
}
|
|
|
|
func postLogin(c *gin.Context, config *Config) error {
|
|
err := c.Request.ParseForm()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
token, err := getToken(config, c.PostForm("password"))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
c.JSON(http.StatusOK, token)
|
|
|
|
return nil
|
|
}
|
|
|
|
func getToken(config *Config, password string) ([]byte, error) {
|
|
if password != config.Password {
|
|
return nil, fmt.Errorf("Wrong password!")
|
|
}
|
|
|
|
/* Set token claims */
|
|
claims := make(map[string]interface{})
|
|
|
|
// Token expire time
|
|
claims["exp"] = time.Now().Add(time.Minute * time.Duration(config.JWTExpireTime)).Unix()
|
|
|
|
/* Create the token */
|
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims(claims))
|
|
|
|
/* Sign the token with our secret */
|
|
tokenString, err := token.SignedString(config.JWTSigningKey)
|
|
if err != nil {
|
|
log.Println(err)
|
|
return nil, err
|
|
}
|
|
|
|
return []byte(tokenString), nil
|
|
}
|
|
|
|
// API outline
|
|
//
|
|
// POST /task content: url=https://foo.org start a new download task
|
|
// GET /task/:id get the status for the task
|
|
// GET /task/:id/download download the file resulted from the task execution
|
|
func main() {
|
|
r := gin.Default()
|
|
r.Use(cors.New(cors.Config{
|
|
AllowOrigins: []string{
|
|
"http://localhost:8080",
|
|
"http://localhost:5000",
|
|
"https://yt-dls.andreafazzi.eu",
|
|
},
|
|
AllowCredentials: true,
|
|
AllowHeaders: []string{"*"},
|
|
}))
|
|
|
|
config := new(Config)
|
|
err := ReadConfig("config.yaml", config)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
r.Use(gin.CustomRecovery(func(c *gin.Context, recovered interface{}) {
|
|
if err, ok := recovered.(string); ok {
|
|
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
|
}
|
|
c.AbortWithStatus(http.StatusInternalServerError)
|
|
}))
|
|
|
|
r.GET("/data/:id", func(c *gin.Context) {
|
|
if err := data(c, c.Param("id")); err != nil {
|
|
panic(err)
|
|
}
|
|
})
|
|
|
|
r.POST("/task", createTask)
|
|
|
|
r.GET("/task/:id", func(c *gin.Context) {
|
|
if err := getTask(c, c.Param("id")); err != nil {
|
|
panic(err)
|
|
}
|
|
})
|
|
|
|
r.POST("/login", func(c *gin.Context) {
|
|
if err := postLogin(c, config); err != nil {
|
|
panic(err)
|
|
}
|
|
})
|
|
|
|
r.Run()
|
|
}
|