Compare commits
	
		
			5 Commits
		
	
	
		
			thumbnail_
			...
			shortkey
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c62fe59244 | |||
| e3c7fe514b | |||
| e47b3eecf2 | |||
| b59b6a17f4 | |||
| 31ad6ec1e5 | 
@@ -12,32 +12,83 @@ func AddActorsHandlers() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getActorsFromDB() {
 | 
					func getActorsFromDB() {
 | 
				
			||||||
	AddHandler("getAllActors", ActorNode, nil, func() []byte {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/actor [getAllActors]
 | 
				
			||||||
 | 
						 * @apiDescription Get all available Actors
 | 
				
			||||||
 | 
						 * @apiName getAllActors
 | 
				
			||||||
 | 
						 * @apiGroup Actor
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} . Array of Actors available
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} .ActorId Actor Id
 | 
				
			||||||
 | 
						 * @apiSuccess {string} .Name Actor Name
 | 
				
			||||||
 | 
						 * @apiSuccess {string} .Thumbnail Portrait Thumbnail
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("getAllActors", ActorNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
		query := "SELECT actor_id, name, thumbnail FROM actors"
 | 
							query := "SELECT actor_id, name, thumbnail FROM actors"
 | 
				
			||||||
		return jsonify(readActorsFromResultset(database.Query(query)))
 | 
							return jsonify(readActorsFromResultset(database.Query(query)))
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var gaov struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/actor [getActorsOfVideo]
 | 
				
			||||||
 | 
						 * @apiDescription Get all actors playing in one video
 | 
				
			||||||
 | 
						 * @apiName getActorsOfVideo
 | 
				
			||||||
 | 
						 * @apiGroup Actor
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {int} MovieId ID of video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} . Array of Actors available
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} .ActorId Actor Id
 | 
				
			||||||
 | 
						 * @apiSuccess {string} .Name Actor Name
 | 
				
			||||||
 | 
						 * @apiSuccess {string} .Thumbnail Portrait Thumbnail
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("getActorsOfVideo", ActorNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			MovieId int
 | 
								MovieId int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("getActorsOfVideo", ActorNode, &gaov, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := fmt.Sprintf(`SELECT a.actor_id, name, thumbnail FROM actors_videos
 | 
							query := fmt.Sprintf(`SELECT a.actor_id, name, thumbnail FROM actors_videos
 | 
				
			||||||
									JOIN actors a on actors_videos.actor_id = a.actor_id
 | 
														JOIN actors a on actors_videos.actor_id = a.actor_id
 | 
				
			||||||
									WHERE actors_videos.video_id=%d`, gaov.MovieId)
 | 
														WHERE actors_videos.video_id=%d`, args.MovieId)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return jsonify(readActorsFromResultset(database.Query(query)))
 | 
							return jsonify(readActorsFromResultset(database.Query(query)))
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var gai struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/actor [getActorInfo]
 | 
				
			||||||
 | 
						 * @apiDescription Get all infos for an actor
 | 
				
			||||||
 | 
						 * @apiName getActorInfo
 | 
				
			||||||
 | 
						 * @apiGroup Actor
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {int} ActorId ID of Actor
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {VideoUnloadedType[]} Videos Array of Videos this actor plays in
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} Videos.MovieId Video Id
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Videos.MovieName Video Name
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Info} Info Infos about the actor
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} Info.ActorId Actor Id
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Info.Name Actor Name
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Info.Thumbnail Actor Thumbnail
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("getActorInfo", ActorNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			ActorId int
 | 
								ActorId int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("getActorInfo", ActorNode, &gai, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := fmt.Sprintf(`SELECT movie_id, movie_name FROM actors_videos
 | 
							query := fmt.Sprintf(`SELECT movie_id, movie_name FROM actors_videos
 | 
				
			||||||
										JOIN videos v on v.movie_id = actors_videos.video_id
 | 
															JOIN videos v on v.movie_id = actors_videos.video_id
 | 
				
			||||||
										WHERE actors_videos.actor_id=%d`, gai.ActorId)
 | 
															WHERE actors_videos.actor_id=%d`, args.ActorId)
 | 
				
			||||||
		videos := readVideosFromResultset(database.Query(query))
 | 
							videos := readVideosFromResultset(database.Query(query))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query = fmt.Sprintf("SELECT actor_id, name, thumbnail FROM actors WHERE actor_id=%d", gai.ActorId)
 | 
							query = fmt.Sprintf("SELECT actor_id, name, thumbnail FROM actors WHERE actor_id=%d", args.ActorId)
 | 
				
			||||||
		actor := readActorsFromResultset(database.Query(query))[0]
 | 
							actor := readActorsFromResultset(database.Query(query))[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var result = struct {
 | 
							var result = struct {
 | 
				
			||||||
@@ -53,20 +104,51 @@ func getActorsFromDB() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func saveActorsToDB() {
 | 
					func saveActorsToDB() {
 | 
				
			||||||
	var ca struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/video [createActor]
 | 
				
			||||||
 | 
						 * @apiDescription Create a new Actor
 | 
				
			||||||
 | 
						 * @apiName createActor
 | 
				
			||||||
 | 
						 * @apiGroup Actor
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {string} ActorName Name of new Actor
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} result 'success' if successfully or error message if not
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("createActor", ActorNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			ActorName string
 | 
								ActorName string
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("createActor", ActorNode, &ca, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := "INSERT IGNORE INTO actors (name) VALUES (?)"
 | 
							query := "INSERT IGNORE INTO actors (name) VALUES (?)"
 | 
				
			||||||
		return database.SuccessQuery(query, ca.ActorName)
 | 
							return database.SuccessQuery(query, args.ActorName)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var aatv struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/video [addActorToVideo]
 | 
				
			||||||
 | 
						 * @apiDescription Add Actor to Video
 | 
				
			||||||
 | 
						 * @apiName addActorToVideo
 | 
				
			||||||
 | 
						 * @apiGroup Actor
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {int} ActorId Id of Actor
 | 
				
			||||||
 | 
						 * @apiParam {int} MovieId Id of Movie to add to
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} result 'success' if successfully or error message if not
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("addActorToVideo", ActorNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			ActorId int
 | 
								ActorId int
 | 
				
			||||||
			MovieId int
 | 
								MovieId int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("addActorToVideo", ActorNode, &aatv, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
		query := fmt.Sprintf("INSERT IGNORE INTO actors_videos (actor_id, video_id) VALUES (%d,%d)", aatv.ActorId, aatv.MovieId)
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							query := fmt.Sprintf("INSERT IGNORE INTO actors_videos (actor_id, video_id) VALUES (%d,%d)", args.ActorId, args.MovieId)
 | 
				
			||||||
		return database.SuccessQuery(query)
 | 
							return database.SuccessQuery(query)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@ import (
 | 
				
			|||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"gopkg.in/oauth2.v3"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"openmediacenter/apiGo/api/oauth"
 | 
						"openmediacenter/apiGo/api/oauth"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -18,22 +19,27 @@ const (
 | 
				
			|||||||
	TVShowNode   = iota
 | 
						TVShowNode   = iota
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type HandlerInfo struct {
 | 
				
			||||||
 | 
						ID    string
 | 
				
			||||||
 | 
						Token string
 | 
				
			||||||
 | 
						Data  map[string]interface{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type actionStruct struct {
 | 
					type actionStruct struct {
 | 
				
			||||||
	Action string
 | 
						Action string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Handler struct {
 | 
					type Handler struct {
 | 
				
			||||||
	action  string
 | 
						action  string
 | 
				
			||||||
	handler   func() []byte
 | 
						handler func(info *HandlerInfo) []byte
 | 
				
			||||||
	arguments interface{}
 | 
					 | 
				
			||||||
	apiNode int
 | 
						apiNode int
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var handlers []Handler
 | 
					var handlers = make(map[string]Handler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func AddHandler(action string, apiNode int, n interface{}, h func() []byte) {
 | 
					func AddHandler(action string, apiNode int, h func(info *HandlerInfo) []byte) {
 | 
				
			||||||
	// append new handler to the handlers
 | 
						// append new handler to the handlers
 | 
				
			||||||
	handlers = append(handlers, Handler{action, h, n, apiNode})
 | 
						handlers[fmt.Sprintf("%s/%d", action, apiNode)] = Handler{action, h, apiNode}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ServerInit() {
 | 
					func ServerInit() {
 | 
				
			||||||
@@ -47,27 +53,39 @@ func ServerInit() {
 | 
				
			|||||||
	oauth.InitOAuth()
 | 
						oauth.InitOAuth()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func handleAPICall(action string, requestBody string, apiNode int) []byte {
 | 
					func handleAPICall(action string, requestBody string, apiNode int, info *HandlerInfo) []byte {
 | 
				
			||||||
	for i := range handlers {
 | 
						handler, ok := handlers[fmt.Sprintf("%s/%d", action, apiNode)]
 | 
				
			||||||
		if handlers[i].action == action && handlers[i].apiNode == apiNode {
 | 
						if !ok {
 | 
				
			||||||
			// call the handler and return
 | 
							// handler doesn't exist!
 | 
				
			||||||
 | 
					 | 
				
			||||||
			if handlers[i].arguments != nil {
 | 
					 | 
				
			||||||
				// decode the arguments to the corresponding arguments object
 | 
					 | 
				
			||||||
				err := json.Unmarshal([]byte(requestBody), &handlers[i].arguments)
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					fmt.Printf("failed to decode arguments of action %s :: %s\n", action, requestBody)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			return handlers[i].handler()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
		fmt.Printf("no handler found for Action: %d/%s\n", apiNode, action)
 | 
							fmt.Printf("no handler found for Action: %d/%s\n", apiNode, action)
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func handlefunc(rw http.ResponseWriter, req *http.Request, node int) {
 | 
						// check if info even exists
 | 
				
			||||||
 | 
						if info == nil {
 | 
				
			||||||
 | 
							info = &HandlerInfo{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// parse the arguments
 | 
				
			||||||
 | 
						var args map[string]interface{}
 | 
				
			||||||
 | 
						err := json.Unmarshal([]byte(requestBody), &args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fmt.Printf("failed to decode arguments of action %s :: %s\n", action, requestBody)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// check if map has an action
 | 
				
			||||||
 | 
							if _, ok := args["action"]; ok {
 | 
				
			||||||
 | 
								delete(args, "action")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							info.Data = args
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// call the handler
 | 
				
			||||||
 | 
						return handler.handler(info)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func handlefunc(rw http.ResponseWriter, req *http.Request, node int, tokenInfo *oauth2.TokenInfo) {
 | 
				
			||||||
	// only allow post requests
 | 
						// only allow post requests
 | 
				
			||||||
	if req.Method != "POST" {
 | 
						if req.Method != "POST" {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
@@ -83,5 +101,13 @@ func handlefunc(rw http.ResponseWriter, req *http.Request, node int) {
 | 
				
			|||||||
		fmt.Println("failed to read action from request! :: " + body)
 | 
							fmt.Println("failed to read action from request! :: " + body)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rw.Write(handleAPICall(t.Action, body, node))
 | 
						// load userid from received token object
 | 
				
			||||||
 | 
						id := (*tokenInfo).GetClientID()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						userinfo := &HandlerInfo{
 | 
				
			||||||
 | 
							ID:    id,
 | 
				
			||||||
 | 
							Token: (*tokenInfo).GetCode(),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rw.Write(handleAPICall(t.Action, body, node, userinfo))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,13 +5,13 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func cleanUp() {
 | 
					func cleanUp() {
 | 
				
			||||||
	handlers = nil
 | 
						handlers = make(map[string]Handler)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestAddHandler(t *testing.T) {
 | 
					func TestAddHandler(t *testing.T) {
 | 
				
			||||||
	cleanUp()
 | 
						cleanUp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AddHandler("test", ActorNode, nil, func() []byte {
 | 
						AddHandler("test", ActorNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if len(handlers) != 1 {
 | 
						if len(handlers) != 1 {
 | 
				
			||||||
@@ -23,13 +23,13 @@ func TestCallOfHandler(t *testing.T) {
 | 
				
			|||||||
	cleanUp()
 | 
						cleanUp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	i := 0
 | 
						i := 0
 | 
				
			||||||
	AddHandler("test", ActorNode, nil, func() []byte {
 | 
						AddHandler("test", ActorNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
		i++
 | 
							i++
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// simulate the call of the api
 | 
						// simulate the call of the api
 | 
				
			||||||
	handleAPICall("test", "", ActorNode)
 | 
						handleAPICall("test", "", ActorNode, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if i != 1 {
 | 
						if i != 1 {
 | 
				
			||||||
		t.Errorf("Unexpected number of Lambda calls : %d/1", i)
 | 
							t.Errorf("Unexpected number of Lambda calls : %d/1", i)
 | 
				
			||||||
@@ -39,26 +39,32 @@ func TestCallOfHandler(t *testing.T) {
 | 
				
			|||||||
func TestDecodingOfArguments(t *testing.T) {
 | 
					func TestDecodingOfArguments(t *testing.T) {
 | 
				
			||||||
	cleanUp()
 | 
						cleanUp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var myvar struct {
 | 
						AddHandler("test", ActorNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			Test    string
 | 
								Test    string
 | 
				
			||||||
			TestInt int
 | 
								TestInt int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("test", ActorNode, &myvar, func() []byte {
 | 
							err := FillStruct(&args, info.Data)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Errorf("Error parsing args: %s", err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if args.TestInt != 42 || args.Test != "myString" {
 | 
				
			||||||
 | 
								t.Errorf("Wrong parsing of argument parameters : %d/42 - %s/myString", args.TestInt, args.Test)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// simulate the call of the api
 | 
						// simulate the call of the api
 | 
				
			||||||
	handleAPICall("test", `{"Test":"myString","TestInt":42}`, ActorNode)
 | 
						handleAPICall("test", `{"Test":"myString","TestInt":42}`, ActorNode, nil)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if myvar.TestInt != 42 || myvar.Test != "myString" {
 | 
					 | 
				
			||||||
		t.Errorf("Wrong parsing of argument parameters : %d/42 - %s/myString", myvar.TestInt, myvar.Test)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestNoHandlerCovers(t *testing.T) {
 | 
					func TestNoHandlerCovers(t *testing.T) {
 | 
				
			||||||
	cleanUp()
 | 
						cleanUp()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret := handleAPICall("test", "", ActorNode)
 | 
						ret := handleAPICall("test", "", ActorNode, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ret != nil {
 | 
						if ret != nil {
 | 
				
			||||||
		t.Error("Expect nil return within unhandled api action")
 | 
							t.Error("Expect nil return within unhandled api action")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,8 +3,10 @@ package api
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"database/sql"
 | 
						"database/sql"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"openmediacenter/apiGo/api/types"
 | 
						"openmediacenter/apiGo/api/types"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MovieId - MovieName : pay attention to the order!
 | 
					// MovieId - MovieName : pay attention to the order!
 | 
				
			||||||
@@ -85,3 +87,45 @@ func jsonify(v interface{}) []byte {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return str
 | 
						return str
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// setField set a specific field of an object with an object provided
 | 
				
			||||||
 | 
					func setField(obj interface{}, name string, value interface{}) error {
 | 
				
			||||||
 | 
						structValue := reflect.ValueOf(obj).Elem()
 | 
				
			||||||
 | 
						structFieldValue := structValue.FieldByName(name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !structFieldValue.IsValid() {
 | 
				
			||||||
 | 
							return fmt.Errorf("no such field: %s in obj", name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !structFieldValue.CanSet() {
 | 
				
			||||||
 | 
							return fmt.Errorf("cannot set %s field value", name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						structFieldType := structFieldValue.Type()
 | 
				
			||||||
 | 
						val := reflect.ValueOf(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if structFieldType != val.Type() {
 | 
				
			||||||
 | 
							if val.Type().ConvertibleTo(structFieldType) {
 | 
				
			||||||
 | 
								// if type is convertible - convert and set
 | 
				
			||||||
 | 
								structFieldValue.Set(val.Convert(structFieldType))
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return errors.New("provided value type didn't match obj field type and isn't convertible")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// set value if type is the same
 | 
				
			||||||
 | 
							structFieldValue.Set(val)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FillStruct fill a custom struct with objects of a map
 | 
				
			||||||
 | 
					func FillStruct(i interface{}, m map[string]interface{}) error {
 | 
				
			||||||
 | 
						for k, v := range m {
 | 
				
			||||||
 | 
							err := setField(i, k, v)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package api
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"openmediacenter/apiGo/api/types"
 | 
						"openmediacenter/apiGo/api/types"
 | 
				
			||||||
	"openmediacenter/apiGo/database"
 | 
						"openmediacenter/apiGo/database"
 | 
				
			||||||
	"openmediacenter/apiGo/database/settings"
 | 
						"openmediacenter/apiGo/database/settings"
 | 
				
			||||||
@@ -17,11 +18,43 @@ func AddSettingsHandlers() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getSettingsFromDB() {
 | 
					func getSettingsFromDB() {
 | 
				
			||||||
	AddHandler("loadGeneralSettings", SettingsNode, nil, func() []byte {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/settings [loadGeneralSettings]
 | 
				
			||||||
 | 
						 * @apiDescription Get the settings object
 | 
				
			||||||
 | 
						 * @apiName loadGeneralSettings
 | 
				
			||||||
 | 
						 * @apiGroup Settings
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object} Settings Settings object
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Settings.VideoPath webserver path to the videos
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Settings.EpisodePath webserver path to the tvshows
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Settings.MediacenterName overall name of the mediacenter
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Settings.Password new server password (-1 if no password set)
 | 
				
			||||||
 | 
						 * @apiSuccess {bool} Settings.TMDBGrabbing TMDB grabbing support to grab tag info and thumbnails
 | 
				
			||||||
 | 
						 * @apiSuccess {bool} Settings.DarkMode Darkmode enabled?
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} Settings.VideoNr total number of videos
 | 
				
			||||||
 | 
						 * @apiSuccess {float32} Settings.DBSize total size of database
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} Settings.DifferentTags number of different tags available
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} Settings.TagsAdded number of different tags added to videos
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Settings.PathPrefix
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("loadGeneralSettings", SettingsNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
		result := database.GetSettings()
 | 
							result := database.GetSettings()
 | 
				
			||||||
		return jsonify(result)
 | 
							return jsonify(result)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	AddHandler("loadInitialData", SettingsNode, nil, func() []byte {
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/settings [loadInitialData]
 | 
				
			||||||
 | 
						 * @apiDescription load startdata to display on homepage
 | 
				
			||||||
 | 
						 * @apiName loadInitialData
 | 
				
			||||||
 | 
						 * @apiGroup Settings
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} VideoPath webserver path to the videos
 | 
				
			||||||
 | 
						 * @apiSuccess {string} EpisodePath webserver path to the tvshows
 | 
				
			||||||
 | 
						 * @apiSuccess {string} MediacenterName overall name of the mediacenter
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Pasword new server password (-1 if no password set)
 | 
				
			||||||
 | 
						 * @apiSuccess {bool} DarkMode Darkmode enabled?
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("loadInitialData", SettingsNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
		sett := settings.LoadSettings()
 | 
							sett := settings.LoadSettings()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		type InitialDataTypeResponse struct {
 | 
							type InitialDataTypeResponse struct {
 | 
				
			||||||
@@ -52,10 +85,32 @@ func getSettingsFromDB() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func saveSettingsToDB() {
 | 
					func saveSettingsToDB() {
 | 
				
			||||||
	var sgs struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/settings [saveGeneralSettings]
 | 
				
			||||||
 | 
						 * @apiDescription Save the global settings provided
 | 
				
			||||||
 | 
						 * @apiName saveGeneralSettings
 | 
				
			||||||
 | 
						 * @apiGroup Settings
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {Object} Settings Settings object
 | 
				
			||||||
 | 
						 * @apiParam {string} Settings.VideoPath webserver path to the videos
 | 
				
			||||||
 | 
						 * @apiParam {string} Settings.EpisodePath webserver path to the tvshows
 | 
				
			||||||
 | 
						 * @apiParam {string} Settings.MediacenterName overall name of the mediacenter
 | 
				
			||||||
 | 
						 * @apiParam {string} Settings.Password new server password (-1 if no password set)
 | 
				
			||||||
 | 
						 * @apiParam {bool} Settings.TMDBGrabbing TMDB grabbing support to grab tag info and thumbnails
 | 
				
			||||||
 | 
						 * @apiParam {bool} Settings.DarkMode Darkmode enabled?
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} result 'success' if successfully or error message if not
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("saveGeneralSettings", SettingsNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							// todo correct type here!
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			Settings types.SettingsType
 | 
								Settings types.SettingsType
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("saveGeneralSettings", SettingsNode, &sgs, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := `
 | 
							query := `
 | 
				
			||||||
					UPDATE settings SET 
 | 
										UPDATE settings SET 
 | 
				
			||||||
                        video_path=?,
 | 
					                        video_path=?,
 | 
				
			||||||
@@ -66,24 +121,46 @@ func saveSettingsToDB() {
 | 
				
			|||||||
                        DarkMode=?
 | 
					                        DarkMode=?
 | 
				
			||||||
                    WHERE 1`
 | 
					                    WHERE 1`
 | 
				
			||||||
		return database.SuccessQuery(query,
 | 
							return database.SuccessQuery(query,
 | 
				
			||||||
			sgs.Settings.VideoPath, sgs.Settings.EpisodePath, sgs.Settings.Password,
 | 
								args.Settings.VideoPath, args.Settings.EpisodePath, args.Settings.Password,
 | 
				
			||||||
			sgs.Settings.MediacenterName, sgs.Settings.TMDBGrabbing, sgs.Settings.DarkMode)
 | 
								args.Settings.MediacenterName, args.Settings.TMDBGrabbing, args.Settings.DarkMode)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// methods for handling reindexing and cleanup of db gravity
 | 
					// methods for handling reindexing and cleanup of db gravity
 | 
				
			||||||
func reIndexHandling() {
 | 
					func reIndexHandling() {
 | 
				
			||||||
	AddHandler("startReindex", SettingsNode, nil, func() []byte {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/settings [startReindex]
 | 
				
			||||||
 | 
						 * @apiDescription Start Database video reindex Job
 | 
				
			||||||
 | 
						 * @apiName startReindex
 | 
				
			||||||
 | 
						 * @apiGroup Settings
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} result 'success' if successfully or error message if not
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("startReindex", SettingsNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
		videoparser.StartReindex()
 | 
							videoparser.StartReindex()
 | 
				
			||||||
		return database.ManualSuccessResponse(nil)
 | 
							return database.ManualSuccessResponse(nil)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AddHandler("startTVShowReindex", SettingsNode, nil, func() []byte {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/settings [startTVShowReindex]
 | 
				
			||||||
 | 
						 * @apiDescription Start Database TVShow reindex job
 | 
				
			||||||
 | 
						 * @apiName startTVShowReindex
 | 
				
			||||||
 | 
						 * @apiGroup Settings
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} result 'success' if successfully or error message if not
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("startTVShowReindex", SettingsNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
		videoparser.StartTVShowReindex()
 | 
							videoparser.StartTVShowReindex()
 | 
				
			||||||
		return database.ManualSuccessResponse(nil)
 | 
							return database.ManualSuccessResponse(nil)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AddHandler("cleanupGravity", SettingsNode, nil, func() []byte {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/settings [cleanupGravity]
 | 
				
			||||||
 | 
						 * @apiDescription Start Database cleanup job
 | 
				
			||||||
 | 
						 * @apiName cleanupGravity
 | 
				
			||||||
 | 
						 * @apiGroup Settings
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("cleanupGravity", SettingsNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
		videoparser.StartCleanup()
 | 
							videoparser.StartCleanup()
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,17 +6,46 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func AddTvshowHandlers() {
 | 
					func AddTvshowHandlers() {
 | 
				
			||||||
	AddHandler("getTVShows", TVShowNode, nil, func() []byte {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/tvshow [getTVShows]
 | 
				
			||||||
 | 
						 * @apiDescription get all available tv shows
 | 
				
			||||||
 | 
						 * @apiName getTVShows
 | 
				
			||||||
 | 
						 * @apiGroup TVshow
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} .
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} .Id tvshow id
 | 
				
			||||||
 | 
						 * @apiSuccess {string} .Name tvshow name
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("getTVShows", TVShowNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
		query := "SELECT id, name FROM tvshow"
 | 
							query := "SELECT id, name FROM tvshow"
 | 
				
			||||||
		rows := database.Query(query)
 | 
							rows := database.Query(query)
 | 
				
			||||||
		return jsonify(readTVshowsFromResultset(rows))
 | 
							return jsonify(readTVshowsFromResultset(rows))
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var ge struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/tvshow [getEpisodes]
 | 
				
			||||||
 | 
						 * @apiDescription get all Episodes of a TVShow
 | 
				
			||||||
 | 
						 * @apiName getEpisodes
 | 
				
			||||||
 | 
						 * @apiGroup TVshow
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {uint32} ShowID id of tvshow to get episodes from
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} .
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} .ID episode id
 | 
				
			||||||
 | 
						 * @apiSuccess {string} .Name episode name
 | 
				
			||||||
 | 
						 * @apiSuccess {uint8} .Season Season number
 | 
				
			||||||
 | 
						 * @apiSuccess {uint8} .Episode Episode number
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("getEpisodes", TVShowNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			ShowID uint32
 | 
								ShowID uint32
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("getEpisodes", TVShowNode, &ge, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
		query := fmt.Sprintf("SELECT id, name, season, episode FROM tvshow_episodes WHERE tvshow_id=%d", ge.ShowID)
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							query := fmt.Sprintf("SELECT id, name, season, episode FROM tvshow_episodes WHERE tvshow_id=%d", args.ShowID)
 | 
				
			||||||
		rows := database.Query(query)
 | 
							rows := database.Query(query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		type Episode struct {
 | 
							type Episode struct {
 | 
				
			||||||
@@ -41,15 +70,34 @@ func AddTvshowHandlers() {
 | 
				
			|||||||
		return jsonify(episodes)
 | 
							return jsonify(episodes)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var le struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/tvshow [loadEpisode]
 | 
				
			||||||
 | 
						 * @apiDescription load all info of episode
 | 
				
			||||||
 | 
						 * @apiName loadEpisode
 | 
				
			||||||
 | 
						 * @apiGroup TVshow
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {uint32} ID id of episode
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} TVShowID episode id
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Name episode name
 | 
				
			||||||
 | 
						 * @apiSuccess {uint8} Season Season number
 | 
				
			||||||
 | 
						 * @apiSuccess {uint8} Episode Episode number
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Path webserver path of video file
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("loadEpisode", TVShowNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			ID uint32
 | 
								ID uint32
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("loadEpisode", TVShowNode, &le, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := fmt.Sprintf(`
 | 
							query := fmt.Sprintf(`
 | 
				
			||||||
SELECT tvshow_episodes.name, season, tvshow_id, episode, filename, t.foldername
 | 
					SELECT tvshow_episodes.name, season, tvshow_id, episode, filename, t.foldername
 | 
				
			||||||
FROM tvshow_episodes 
 | 
					FROM tvshow_episodes 
 | 
				
			||||||
JOIN tvshow t on t.id = tvshow_episodes.tvshow_id
 | 
					JOIN tvshow t on t.id = tvshow_episodes.tvshow_id
 | 
				
			||||||
WHERE tvshow_episodes.id=%d`, le.ID)
 | 
					WHERE tvshow_episodes.id=%d`, args.ID)
 | 
				
			||||||
		row := database.QueryRow(query)
 | 
							row := database.QueryRow(query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var ret struct {
 | 
							var ret struct {
 | 
				
			||||||
@@ -73,17 +121,32 @@ WHERE tvshow_episodes.id=%d`, le.ID)
 | 
				
			|||||||
		return jsonify(ret)
 | 
							return jsonify(ret)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var rtn struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/tvshow [readThumbnail]
 | 
				
			||||||
 | 
						 * @apiDescription Load Thubnail of specific episode
 | 
				
			||||||
 | 
						 * @apiName readThumbnail
 | 
				
			||||||
 | 
						 * @apiGroup TVshow
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {int} Id id of episode to load thumbnail
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} . Base64 encoded Thubnail
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("readThumbnail", TVShowNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			Id int
 | 
								Id int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("readThumbnail", TVShowNode, &rtn, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var pic []byte
 | 
							var pic []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := fmt.Sprintf("SELECT thumbnail FROM tvshow WHERE id=%d", rtn.Id)
 | 
							query := fmt.Sprintf("SELECT thumbnail FROM tvshow WHERE id=%d", args.Id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err := database.QueryRow(query).Scan(&pic)
 | 
							err := database.QueryRow(query).Scan(&pic)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			fmt.Printf("the thumbnail of movie id %d couldn't be found", rtn.Id)
 | 
								fmt.Printf("the thumbnail of movie id %d couldn't be found", args.Id)
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,14 +13,30 @@ func AddTagHandlers() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func deleteFromDB() {
 | 
					func deleteFromDB() {
 | 
				
			||||||
	var dT struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/tags [deleteTag]
 | 
				
			||||||
 | 
						 * @apiDescription Start Database video reindex Job
 | 
				
			||||||
 | 
						 * @apiName deleteTag
 | 
				
			||||||
 | 
						 * @apiGroup Tags
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {bool} [Force] force delete tag with its constraints
 | 
				
			||||||
 | 
						 * @apiParam {int} TagId id of tag to delete
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} result 'success' if successfully or error message if not
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("deleteTag", TagNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			TagId int
 | 
								TagId int
 | 
				
			||||||
			Force bool
 | 
								Force bool
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("deleteTag", TagNode, &dT, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// delete key constraints first
 | 
							// delete key constraints first
 | 
				
			||||||
		if dT.Force {
 | 
							if args.Force {
 | 
				
			||||||
			query := fmt.Sprintf("DELETE FROM video_tags WHERE tag_id=%d", dT.TagId)
 | 
								query := fmt.Sprintf("DELETE FROM video_tags WHERE tag_id=%d", args.TagId)
 | 
				
			||||||
			err := database.Edit(query)
 | 
								err := database.Edit(query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// respond only if result not successful
 | 
								// respond only if result not successful
 | 
				
			||||||
@@ -29,7 +45,7 @@ func deleteFromDB() {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := fmt.Sprintf("DELETE FROM tags WHERE tag_id=%d", dT.TagId)
 | 
							query := fmt.Sprintf("DELETE FROM tags WHERE tag_id=%d", args.TagId)
 | 
				
			||||||
		err := database.Edit(query)
 | 
							err := database.Edit(query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err == nil {
 | 
							if err == nil {
 | 
				
			||||||
@@ -39,7 +55,7 @@ func deleteFromDB() {
 | 
				
			|||||||
			// check with regex if its the key constraint error
 | 
								// check with regex if its the key constraint error
 | 
				
			||||||
			r := regexp.MustCompile("^.*a foreign key constraint fails.*$")
 | 
								r := regexp.MustCompile("^.*a foreign key constraint fails.*$")
 | 
				
			||||||
			if r.MatchString(err.Error()) {
 | 
								if r.MatchString(err.Error()) {
 | 
				
			||||||
				return []byte(`{"result":"not empty tag"}`)
 | 
									return database.ManualSuccessResponse(fmt.Errorf("not empty tag"))
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				return database.ManualSuccessResponse(err)
 | 
									return database.ManualSuccessResponse(err)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -48,27 +64,68 @@ func deleteFromDB() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getFromDB() {
 | 
					func getFromDB() {
 | 
				
			||||||
	AddHandler("getAllTags", TagNode, nil, func() []byte {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/tags [getAllTags]
 | 
				
			||||||
 | 
						 * @apiDescription get all available Tags
 | 
				
			||||||
 | 
						 * @apiName getAllTags
 | 
				
			||||||
 | 
						 * @apiGroup Tags
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} array of tag objects
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} TagId
 | 
				
			||||||
 | 
						 * @apiSuccess {string} TagName name of the Tag
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("getAllTags", TagNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
		query := "SELECT tag_id,tag_name from tags"
 | 
							query := "SELECT tag_id,tag_name from tags"
 | 
				
			||||||
		return jsonify(readTagsFromResultset(database.Query(query)))
 | 
							return jsonify(readTagsFromResultset(database.Query(query)))
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func addToDB() {
 | 
					func addToDB() {
 | 
				
			||||||
	var ct struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/tags [createTag]
 | 
				
			||||||
 | 
						 * @apiDescription create a new tag
 | 
				
			||||||
 | 
						 * @apiName createTag
 | 
				
			||||||
 | 
						 * @apiGroup Tags
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {string} TagName name of the tag
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} result 'success' if successfully or error message if not
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("createTag", TagNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			TagName string
 | 
								TagName string
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("createTag", TagNode, &ct, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := "INSERT IGNORE INTO tags (tag_name) VALUES (?)"
 | 
							query := "INSERT IGNORE INTO tags (tag_name) VALUES (?)"
 | 
				
			||||||
		return database.SuccessQuery(query, ct.TagName)
 | 
							return database.SuccessQuery(query, args.TagName)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var at struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/tags [addTag]
 | 
				
			||||||
 | 
						 * @apiDescription Add new tag to video
 | 
				
			||||||
 | 
						 * @apiName addTag
 | 
				
			||||||
 | 
						 * @apiGroup Tags
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {int} TagId Tag id to add to video
 | 
				
			||||||
 | 
						 * @apiParam {int} MovieId Video Id of video to add tag to
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} result 'success' if successfully or error message if not
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("addTag", TagNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			MovieId int
 | 
								MovieId int
 | 
				
			||||||
			TagId   int
 | 
								TagId   int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("addTag", TagNode, &at, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := "INSERT IGNORE INTO video_tags(tag_id, video_id) VALUES (?,?)"
 | 
							query := "INSERT IGNORE INTO video_tags(tag_id, video_id) VALUES (?,?)"
 | 
				
			||||||
		return database.SuccessQuery(query, at.TagId, at.MovieId)
 | 
							return database.SuccessQuery(query, args.TagId, args.MovieId)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,18 +16,35 @@ func AddVideoHandlers() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getVideoHandlers() {
 | 
					func getVideoHandlers() {
 | 
				
			||||||
	var mrq struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/video [getMovies]
 | 
				
			||||||
 | 
						 * @apiDescription Request available Videos
 | 
				
			||||||
 | 
						 * @apiName GetMovies
 | 
				
			||||||
 | 
						 * @apiGroup video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {int} [Tag=all] id of VideoTag to get videos
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} . List of Videos
 | 
				
			||||||
 | 
						 * @apiSuccess {number} .MovieId Id of Video
 | 
				
			||||||
 | 
						 * @apiSuccess {String} .MovieName  Name of video
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("getMovies", VideoNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			Tag int
 | 
								Tag int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("getMovies", VideoNode, &mrq, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var query string
 | 
							var query string
 | 
				
			||||||
		// 1 is the id of the ALL tag
 | 
							// 1 is the id of the ALL tag
 | 
				
			||||||
		if mrq.Tag != 1 {
 | 
							if args.Tag != 1 {
 | 
				
			||||||
			query = fmt.Sprintf(`SELECT movie_id,movie_name FROM videos
 | 
								query = fmt.Sprintf(`SELECT movie_id,movie_name FROM videos
 | 
				
			||||||
					INNER JOIN video_tags vt on videos.movie_id = vt.video_id
 | 
										INNER JOIN video_tags vt on videos.movie_id = vt.video_id
 | 
				
			||||||
					INNER JOIN tags t on vt.tag_id = t.tag_id
 | 
										INNER JOIN tags t on vt.tag_id = t.tag_id
 | 
				
			||||||
					WHERE t.tag_id = '%d'
 | 
										WHERE t.tag_id = '%d'
 | 
				
			||||||
					ORDER BY likes DESC, create_date, movie_name`, mrq.Tag)
 | 
										ORDER BY likes DESC, create_date, movie_name`, args.Tag)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			query = "SELECT movie_id,movie_name FROM videos ORDER BY create_date DESC, movie_name"
 | 
								query = "SELECT movie_id,movie_name FROM videos ORDER BY create_date DESC, movie_name"
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -38,33 +55,69 @@ func getVideoHandlers() {
 | 
				
			|||||||
		return str
 | 
							return str
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var rtn struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/video [readThumbnail]
 | 
				
			||||||
 | 
						 * @apiDescription Load Thubnail of specific Video
 | 
				
			||||||
 | 
						 * @apiName readThumbnail
 | 
				
			||||||
 | 
						 * @apiGroup video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {int} Movieid id of video to load thumbnail
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} . Base64 encoded Thubnail
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("readThumbnail", VideoNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			Movieid int
 | 
								Movieid int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("readThumbnail", VideoNode, &rtn, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var pic []byte
 | 
							var pic []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := fmt.Sprintf("SELECT thumbnail FROM videos WHERE movie_id=%d", rtn.Movieid)
 | 
							query := fmt.Sprintf("SELECT thumbnail FROM videos WHERE movie_id=%d", args.Movieid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		err := database.QueryRow(query).Scan(&pic)
 | 
							err := database.QueryRow(query).Scan(&pic)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			fmt.Printf("the thumbnail of movie id %d couldn't be found", rtn.Movieid)
 | 
								fmt.Printf("the thumbnail of movie id %d couldn't be found", args.Movieid)
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return pic
 | 
							return pic
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var grm struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/video [getRandomMovies]
 | 
				
			||||||
 | 
						 * @apiDescription Load random videos
 | 
				
			||||||
 | 
						 * @apiName getRandomMovies
 | 
				
			||||||
 | 
						 * @apiGroup video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {int} Number number of random videos to load
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} Tags Array of tags occuring in selection
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Tags.TagName Tagname
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} Tags.TagId Tag ID
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} Videos Array of the videos
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Videos.MovieName Video Name
 | 
				
			||||||
 | 
						 * @apiSuccess {int} Videos.MovieId Video ID
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("getRandomMovies", VideoNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			Number int
 | 
								Number int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("getRandomMovies", VideoNode, &grm, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var result struct {
 | 
							var result struct {
 | 
				
			||||||
			Tags   []types.Tag
 | 
								Tags   []types.Tag
 | 
				
			||||||
			Videos []types.VideoUnloadedType
 | 
								Videos []types.VideoUnloadedType
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := fmt.Sprintf("SELECT movie_id,movie_name FROM videos ORDER BY RAND() LIMIT %d", grm.Number)
 | 
							query := fmt.Sprintf("SELECT movie_id,movie_name FROM videos ORDER BY RAND() LIMIT %d", args.Number)
 | 
				
			||||||
		result.Videos = readVideosFromResultset(database.Query(query))
 | 
							result.Videos = readVideosFromResultset(database.Query(query))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var ids string
 | 
							var ids string
 | 
				
			||||||
@@ -99,13 +152,30 @@ func getVideoHandlers() {
 | 
				
			|||||||
		return str
 | 
							return str
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var gsk struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/video [getSearchKeyWord]
 | 
				
			||||||
 | 
						 * @apiDescription Get videos for search keyword
 | 
				
			||||||
 | 
						 * @apiName getSearchKeyWord
 | 
				
			||||||
 | 
						 * @apiGroup video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {string} KeyWord Keyword to search for
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} . List of Videos
 | 
				
			||||||
 | 
						 * @apiSuccess {number} .MovieId Id of Video
 | 
				
			||||||
 | 
						 * @apiSuccess {String} .MovieName  Name of video
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("getSearchKeyWord", VideoNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			KeyWord string
 | 
								KeyWord string
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("getSearchKeyWord", VideoNode, &gsk, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := fmt.Sprintf(`SELECT movie_id,movie_name FROM videos 
 | 
							query := fmt.Sprintf(`SELECT movie_id,movie_name FROM videos 
 | 
				
			||||||
					WHERE movie_name LIKE '%%%s%%'
 | 
										WHERE movie_name LIKE '%%%s%%'
 | 
				
			||||||
					ORDER BY likes DESC, create_date DESC, movie_name`, gsk.KeyWord)
 | 
										ORDER BY likes DESC, create_date DESC, movie_name`, args.KeyWord)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		result := readVideosFromResultset(database.Query(query))
 | 
							result := readVideosFromResultset(database.Query(query))
 | 
				
			||||||
		// jsonify results
 | 
							// jsonify results
 | 
				
			||||||
@@ -116,12 +186,47 @@ func getVideoHandlers() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// function to handle stuff for loading specific videos and startdata
 | 
					// function to handle stuff for loading specific videos and startdata
 | 
				
			||||||
func loadVideosHandlers() {
 | 
					func loadVideosHandlers() {
 | 
				
			||||||
	var lv struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/video [loadVideo]
 | 
				
			||||||
 | 
						 * @apiDescription Load all data for a specific video
 | 
				
			||||||
 | 
						 * @apiName loadVideo
 | 
				
			||||||
 | 
						 * @apiGroup video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {int} MovieId ID of video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} MovieName Videoname
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} MovieId Video ID
 | 
				
			||||||
 | 
						 * @apiSuccess {string} MovieUrl Url to video file
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Poster Base64 encoded Poster
 | 
				
			||||||
 | 
						 * @apiSuccess {uint64} Likes Number of likes
 | 
				
			||||||
 | 
						 * @apiSuccess {uint16} Quality Video FrameWidth
 | 
				
			||||||
 | 
						 * @apiSuccess {uint16} Length Video Length in seconds
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} Tags Array of tags of video
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Tags.TagName Tagname
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} Tags.TagId Tag ID
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} SuggestedTag Array of tags for quick add suggestions
 | 
				
			||||||
 | 
						 * @apiSuccess {string} SuggestedTag.TagName Tagname
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} SuggestedTag.TagId Tag ID
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {Object[]} Actors Array of Actors playing in this video
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} Actors.ActorId Actor Id
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Actors.Name Actor Name
 | 
				
			||||||
 | 
						 * @apiSuccess {string} Actors.Thumbnail Portrait Thumbnail
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("loadVideo", VideoNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			MovieId int
 | 
								MovieId int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("loadVideo", VideoNode, &lv, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query := fmt.Sprintf(`SELECT movie_name,movie_url,movie_id,thumbnail,poster,likes,quality,length 
 | 
							query := fmt.Sprintf(`SELECT movie_name,movie_url,movie_id,thumbnail,poster,likes,quality,length 
 | 
				
			||||||
										FROM videos WHERE movie_id=%d`, lv.MovieId)
 | 
															FROM videos WHERE movie_id=%d`, args.MovieId)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		var res types.FullVideoType
 | 
							var res types.FullVideoType
 | 
				
			||||||
		var poster []byte
 | 
							var poster []byte
 | 
				
			||||||
@@ -129,7 +234,7 @@ func loadVideosHandlers() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		err := database.QueryRow(query).Scan(&res.MovieName, &res.MovieUrl, &res.MovieId, &thumbnail, &poster, &res.Likes, &res.Quality, &res.Length)
 | 
							err := database.QueryRow(query).Scan(&res.MovieName, &res.MovieUrl, &res.MovieId, &thumbnail, &poster, &res.Likes, &res.Quality, &res.Length)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			fmt.Printf("error getting full data list of videoid - %d", lv.MovieId)
 | 
								fmt.Printf("error getting full data list of videoid - %d", args.MovieId)
 | 
				
			||||||
			fmt.Println(err.Error())
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -149,7 +254,7 @@ func loadVideosHandlers() {
 | 
				
			|||||||
		query = fmt.Sprintf(`SELECT t.tag_id, t.tag_name FROM video_tags 
 | 
							query = fmt.Sprintf(`SELECT t.tag_id, t.tag_name FROM video_tags 
 | 
				
			||||||
					INNER JOIN tags t on video_tags.tag_id = t.tag_id
 | 
										INNER JOIN tags t on video_tags.tag_id = t.tag_id
 | 
				
			||||||
					WHERE video_tags.video_id=%d
 | 
										WHERE video_tags.video_id=%d
 | 
				
			||||||
					GROUP BY t.tag_id`, lv.MovieId)
 | 
										GROUP BY t.tag_id`, args.MovieId)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		res.Tags = readTagsFromResultset(database.Query(query))
 | 
							res.Tags = readTagsFromResultset(database.Query(query))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -158,14 +263,14 @@ func loadVideosHandlers() {
 | 
				
			|||||||
						SELECT video_tags.tag_id FROM video_tags
 | 
											SELECT video_tags.tag_id FROM video_tags
 | 
				
			||||||
					WHERE video_id=%d)
 | 
										WHERE video_id=%d)
 | 
				
			||||||
					ORDER BY rand()
 | 
										ORDER BY rand()
 | 
				
			||||||
					LIMIT 5`, lv.MovieId)
 | 
										LIMIT 5`, args.MovieId)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		res.SuggestedTag = readTagsFromResultset(database.Query(query))
 | 
							res.SuggestedTag = readTagsFromResultset(database.Query(query))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// query the actors corresponding to video
 | 
							// query the actors corresponding to video
 | 
				
			||||||
		query = fmt.Sprintf(`SELECT a.actor_id, name, thumbnail FROM actors_videos
 | 
							query = fmt.Sprintf(`SELECT a.actor_id, name, thumbnail FROM actors_videos
 | 
				
			||||||
					JOIN actors a on actors_videos.actor_id = a.actor_id
 | 
										JOIN actors a on actors_videos.actor_id = a.actor_id
 | 
				
			||||||
					WHERE actors_videos.video_id=%d`, lv.MovieId)
 | 
										WHERE actors_videos.video_id=%d`, args.MovieId)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		res.Actors = readActorsFromResultset(database.Query(query))
 | 
							res.Actors = readActorsFromResultset(database.Query(query))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -174,7 +279,20 @@ func loadVideosHandlers() {
 | 
				
			|||||||
		return str
 | 
							return str
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AddHandler("getStartData", VideoNode, nil, func() []byte {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/video [getStartData]
 | 
				
			||||||
 | 
						 * @apiDescription Get general video informations at start
 | 
				
			||||||
 | 
						 * @apiName getStartData
 | 
				
			||||||
 | 
						 * @apiGroup video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} VideoNr Total nr of videos
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} FullHdNr number of FullHD videos
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} HDNr number of HD videos
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} SDNr number of SD videos
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} DifferentTags number of different Tags available
 | 
				
			||||||
 | 
						 * @apiSuccess {uint32} Tagged number of different Tags assigned
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("getStartData", VideoNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
		var result types.StartData
 | 
							var result types.StartData
 | 
				
			||||||
		// query settings and infotile values
 | 
							// query settings and infotile values
 | 
				
			||||||
		query := `
 | 
							query := `
 | 
				
			||||||
@@ -215,24 +333,54 @@ func loadVideosHandlers() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func addToVideoHandlers() {
 | 
					func addToVideoHandlers() {
 | 
				
			||||||
	var al struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/video [addLike]
 | 
				
			||||||
 | 
						 * @apiDescription Add a like to a video
 | 
				
			||||||
 | 
						 * @apiName addLike
 | 
				
			||||||
 | 
						 * @apiGroup video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {int} MovieId ID of video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} result 'success' if successfully or error message if not
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("addLike", VideoNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			MovieId int
 | 
								MovieId int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("addLike", VideoNode, &al, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
		query := fmt.Sprintf("update videos set likes = likes + 1 where movie_id = %d", al.MovieId)
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							query := fmt.Sprintf("update videos set likes = likes + 1 where movie_id = %d", args.MovieId)
 | 
				
			||||||
		return database.SuccessQuery(query)
 | 
							return database.SuccessQuery(query)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var dv struct {
 | 
						/**
 | 
				
			||||||
 | 
						 * @api {post} /api/video [deleteVideo]
 | 
				
			||||||
 | 
						 * @apiDescription Delete a specific video from database
 | 
				
			||||||
 | 
						 * @apiName deleteVideo
 | 
				
			||||||
 | 
						 * @apiGroup video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiParam {int} MovieId ID of video
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @apiSuccess {string} result 'success' if successfully or error message if not
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						AddHandler("deleteVideo", VideoNode, func(info *HandlerInfo) []byte {
 | 
				
			||||||
 | 
							var args struct {
 | 
				
			||||||
			MovieId int
 | 
								MovieId int
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	AddHandler("deleteVideo", VideoNode, &dv, func() []byte {
 | 
							if err := FillStruct(&args, info.Data); err != nil {
 | 
				
			||||||
 | 
								fmt.Println(err.Error())
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// delete tag constraints
 | 
							// delete tag constraints
 | 
				
			||||||
		query := fmt.Sprintf("DELETE FROM video_tags WHERE video_id=%d", dv.MovieId)
 | 
							query := fmt.Sprintf("DELETE FROM video_tags WHERE video_id=%d", args.MovieId)
 | 
				
			||||||
		err := database.Edit(query)
 | 
							err := database.Edit(query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// delete actor constraints
 | 
							// delete actor constraints
 | 
				
			||||||
		query = fmt.Sprintf("DELETE FROM actors_videos WHERE video_id=%d", dv.MovieId)
 | 
							query = fmt.Sprintf("DELETE FROM actors_videos WHERE video_id=%d", args.MovieId)
 | 
				
			||||||
		err = database.Edit(query)
 | 
							err = database.Edit(query)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// respond only if result not successful
 | 
							// respond only if result not successful
 | 
				
			||||||
@@ -240,7 +388,7 @@ func addToVideoHandlers() {
 | 
				
			|||||||
			return database.ManualSuccessResponse(err)
 | 
								return database.ManualSuccessResponse(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		query = fmt.Sprintf("DELETE FROM videos WHERE movie_id=%d", dv.MovieId)
 | 
							query = fmt.Sprintf("DELETE FROM videos WHERE movie_id=%d", args.MovieId)
 | 
				
			||||||
		return database.SuccessQuery(query)
 | 
							return database.SuccessQuery(query)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
package oauth
 | 
					package oauth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"gopkg.in/oauth2.v3"
 | 
				
			||||||
	"gopkg.in/oauth2.v3/errors"
 | 
						"gopkg.in/oauth2.v3/errors"
 | 
				
			||||||
	"gopkg.in/oauth2.v3/manage"
 | 
						"gopkg.in/oauth2.v3/manage"
 | 
				
			||||||
	"gopkg.in/oauth2.v3/server"
 | 
						"gopkg.in/oauth2.v3/server"
 | 
				
			||||||
@@ -48,14 +49,14 @@ func InitOAuth() {
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ValidateToken(f func(rw http.ResponseWriter, req *http.Request, node int), node int) http.HandlerFunc {
 | 
					func ValidateToken(f func(rw http.ResponseWriter, req *http.Request, node int, tokenInfo *oauth2.TokenInfo), node int) http.HandlerFunc {
 | 
				
			||||||
	return func(w http.ResponseWriter, r *http.Request) {
 | 
						return func(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
		_, err := srv.ValidationBearerToken(r)
 | 
							tokeninfo, err := srv.ValidationBearerToken(r)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			http.Error(w, err.Error(), http.StatusBadRequest)
 | 
								http.Error(w, err.Error(), http.StatusBadRequest)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		f(w, r, node)
 | 
							f(w, r, node, &tokeninfo)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								package.json
									
									
									
									
									
								
							@@ -25,7 +25,8 @@
 | 
				
			|||||||
    "start": "react-scripts start",
 | 
					    "start": "react-scripts start",
 | 
				
			||||||
    "build": "CI=false react-scripts build",
 | 
					    "build": "CI=false react-scripts build",
 | 
				
			||||||
    "test": "CI=true react-scripts test --reporters=jest-junit --verbose --silent --coverage --reporters=default",
 | 
					    "test": "CI=true react-scripts test --reporters=jest-junit --verbose --silent --coverage --reporters=default",
 | 
				
			||||||
    "lint": "eslint --format gitlab src/"
 | 
					    "lint": "eslint --format gitlab src/",
 | 
				
			||||||
 | 
					    "apidoc": "apidoc -i apiGo/ -o doc/"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "jest": {
 | 
					  "jest": {
 | 
				
			||||||
    "collectCoverageFrom": [
 | 
					    "collectCoverageFrom": [
 | 
				
			||||||
@@ -76,6 +77,13 @@
 | 
				
			|||||||
    "jest-junit": "^12.0.0",
 | 
					    "jest-junit": "^12.0.0",
 | 
				
			||||||
    "prettier": "^2.2.1",
 | 
					    "prettier": "^2.2.1",
 | 
				
			||||||
    "prettier-config": "^1.0.0",
 | 
					    "prettier-config": "^1.0.0",
 | 
				
			||||||
    "react-scripts": "4.0.3"
 | 
					    "react-scripts": "4.0.3",
 | 
				
			||||||
 | 
					    "apidoc": "^0.28.1"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "apidoc":{
 | 
				
			||||||
 | 
					    "name": "OpenMediaCenter",
 | 
				
			||||||
 | 
					    "description": "API Documentation of OpenMediaCenter",
 | 
				
			||||||
 | 
					    "title": "OpenMediaCenter Doc",
 | 
				
			||||||
 | 
					    "sampleUrl": null
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,7 +20,7 @@ const VideoContainer = (props: Props): JSX.Element => {
 | 
				
			|||||||
                            APINode.Video,
 | 
					                            APINode.Video,
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                action: 'readThumbnail',
 | 
					                                action: 'readThumbnail',
 | 
				
			||||||
                                movieid: el.MovieId
 | 
					                                Movieid: el.MovieId
 | 
				
			||||||
                            },
 | 
					                            },
 | 
				
			||||||
                            (result) => callback(result)
 | 
					                            (result) => callback(result)
 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -105,7 +105,7 @@ export class CategoryView extends React.Component<CategoryViewProps, CategoryVie
 | 
				
			|||||||
     * @param id tagid
 | 
					     * @param id tagid
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private fetchVideoData(id: number): void {
 | 
					    private fetchVideoData(id: number): void {
 | 
				
			||||||
        callAPI<VideoTypes.VideoUnloadedType[]>(APINode.Video, {action: 'getMovies', tag: id}, (result) => {
 | 
					        callAPI<VideoTypes.VideoUnloadedType[]>(APINode.Video, {action: 'getMovies', Tag: id}, (result) => {
 | 
				
			||||||
            this.videodata = result;
 | 
					            this.videodata = result;
 | 
				
			||||||
            this.setState({loaded: true});
 | 
					            this.setState({loaded: true});
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,7 @@ export class HomePage extends React.Component<Props, state> {
 | 
				
			|||||||
     * @param tag tag to fetch videos
 | 
					     * @param tag tag to fetch videos
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    fetchVideoData(tag: number): void {
 | 
					    fetchVideoData(tag: number): void {
 | 
				
			||||||
        callAPI(APINode.Video, {action: 'getMovies', tag: tag}, (result: VideoTypes.VideoUnloadedType[]) => {
 | 
					        callAPI(APINode.Video, {action: 'getMovies', Tag: tag}, (result: VideoTypes.VideoUnloadedType[]) => {
 | 
				
			||||||
            this.setState({
 | 
					            this.setState({
 | 
				
			||||||
                data: []
 | 
					                data: []
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,7 +57,7 @@ export class SearchHandling extends React.Component<Props, state> {
 | 
				
			|||||||
     * @param keyword The keyword to search for
 | 
					     * @param keyword The keyword to search for
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    searchVideos(keyword: string): void {
 | 
					    searchVideos(keyword: string): void {
 | 
				
			||||||
        callAPI(APINode.Video, {action: 'getSearchKeyWord', keyword: keyword}, (result: VideoTypes.VideoUnloadedType[]) => {
 | 
					        callAPI(APINode.Video, {action: 'getSearchKeyWord', KeyWord: keyword}, (result: VideoTypes.VideoUnloadedType[]) => {
 | 
				
			||||||
            this.setState({
 | 
					            this.setState({
 | 
				
			||||||
                data: result
 | 
					                data: result
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,7 @@ import PlyrJS from 'plyr';
 | 
				
			|||||||
import {Button} from '../../elements/GPElements/Button';
 | 
					import {Button} from '../../elements/GPElements/Button';
 | 
				
			||||||
import {VideoTypes} from '../../types/ApiTypes';
 | 
					import {VideoTypes} from '../../types/ApiTypes';
 | 
				
			||||||
import GlobalInfos from '../../utils/GlobalInfos';
 | 
					import GlobalInfos from '../../utils/GlobalInfos';
 | 
				
			||||||
 | 
					import KeyComponent from '../../utils/KeyComponent';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface Props extends RouteComponentProps<{id: string}> {}
 | 
					interface Props extends RouteComponentProps<{id: string}> {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -42,7 +43,7 @@ interface mystate {
 | 
				
			|||||||
 * Player page loads when a video is selected to play and handles the video view
 | 
					 * Player page loads when a video is selected to play and handles the video view
 | 
				
			||||||
 * and actions such as tag adding and liking
 | 
					 * and actions such as tag adding and liking
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export class Player extends React.Component<Props, mystate> {
 | 
					export class Player extends KeyComponent<Props, mystate> {
 | 
				
			||||||
    constructor(props: Props) {
 | 
					    constructor(props: Props) {
 | 
				
			||||||
        super(props);
 | 
					        super(props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -62,7 +63,19 @@ export class Player extends React.Component<Props, mystate> {
 | 
				
			|||||||
        this.quickAddTag = this.quickAddTag.bind(this);
 | 
					        this.quickAddTag = this.quickAddTag.bind(this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    keyHandler(key: string): void {
 | 
				
			||||||
 | 
					        switch (key) {
 | 
				
			||||||
 | 
					            case 't':
 | 
				
			||||||
 | 
					                this.setState({popupvisible: true});
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case 'a':
 | 
				
			||||||
 | 
					                this.setState({actorpopupvisible: true});
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    componentDidMount(): void {
 | 
					    componentDidMount(): void {
 | 
				
			||||||
 | 
					        super.componentDidMount();
 | 
				
			||||||
        // initial fetch of current movie data
 | 
					        // initial fetch of current movie data
 | 
				
			||||||
        this.fetchMovieData();
 | 
					        this.fetchMovieData();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -85,8 +85,7 @@ class RandomPage extends React.Component<{}, state> {
 | 
				
			|||||||
     * @param nr number of videos to load
 | 
					     * @param nr number of videos to load
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    loadShuffledvideos(nr: number): void {
 | 
					    loadShuffledvideos(nr: number): void {
 | 
				
			||||||
        callAPI<GetRandomMoviesType>(APINode.Video, {action: 'getRandomMovies', number: nr}, (result) => {
 | 
					        callAPI<GetRandomMoviesType>(APINode.Video, {action: 'getRandomMovies', Number: nr}, (result) => {
 | 
				
			||||||
            console.log(result);
 | 
					 | 
				
			||||||
            this.setState({videos: []}); // needed to trigger rerender of main videoview
 | 
					            this.setState({videos: []}); // needed to trigger rerender of main videoview
 | 
				
			||||||
            this.setState({
 | 
					            this.setState({
 | 
				
			||||||
                videos: result.Videos,
 | 
					                videos: result.Videos,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								src/utils/KeyComponent.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/utils/KeyComponent.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					import * as React from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class KeyComponent<P = {}, S = {}> extends React.Component<P, S> {
 | 
				
			||||||
 | 
					    constructor(props: P) {
 | 
				
			||||||
 | 
					        super(props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.handler = this.handler.bind(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    componentDidMount(): void {
 | 
				
			||||||
 | 
					        document.addEventListener('keyup', this.handler);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    componentWillUnmount(): void {
 | 
				
			||||||
 | 
					        document.removeEventListener('keyup', this.handler);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private handler(e: KeyboardEvent): void {
 | 
				
			||||||
 | 
					        this.keyHandler(e.key);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    abstract keyHandler(key: string): void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default KeyComponent;
 | 
				
			||||||
		Reference in New Issue
	
	Block a user