add tvshow syntax to db

basic tvshow api request to show available tvshows
limit randompage videos to 3
improve settings object to remove one useless copy
This commit is contained in:
lukas 2021-04-16 22:44:56 +02:00
parent fdcecb0a75
commit 4539147208
17 changed files with 165 additions and 69 deletions

View File

@ -15,6 +15,7 @@ const (
TagNode = iota
SettingsNode = iota
ActorNode = iota
TVShowNode = iota
)
type actionStruct struct {
@ -36,10 +37,11 @@ func AddHandler(action string, apiNode int, n interface{}, h func() []byte) {
}
func ServerInit() {
http.Handle(APIPREFIX+"/video", oauth.ValidateToken(videoHandler))
http.Handle(APIPREFIX+"/tags", oauth.ValidateToken(tagHandler))
http.Handle(APIPREFIX+"/settings", oauth.ValidateToken(settingsHandler))
http.Handle(APIPREFIX+"/actor", oauth.ValidateToken(actorHandler))
http.Handle(APIPREFIX+"/video", oauth.ValidateToken(handlefunc, VideoNode))
http.Handle(APIPREFIX+"/tags", oauth.ValidateToken(handlefunc, TagNode))
http.Handle(APIPREFIX+"/settings", oauth.ValidateToken(handlefunc, SettingsNode))
http.Handle(APIPREFIX+"/actor", oauth.ValidateToken(handlefunc, ActorNode))
http.Handle(APIPREFIX+"/tvshow", oauth.ValidateToken(handlefunc, TVShowNode))
// initialize oauth service and add corresponding auth routes
oauth.InitOAuth()
@ -65,22 +67,6 @@ func handleAPICall(action string, requestBody string, apiNode int) []byte {
return nil
}
func actorHandler(rw http.ResponseWriter, req *http.Request) {
handlefunc(rw, req, ActorNode)
}
func videoHandler(rw http.ResponseWriter, req *http.Request) {
handlefunc(rw, req, VideoNode)
}
func tagHandler(rw http.ResponseWriter, req *http.Request) {
handlefunc(rw, req, TagNode)
}
func settingsHandler(rw http.ResponseWriter, req *http.Request) {
handlefunc(rw, req, SettingsNode)
}
func handlefunc(rw http.ResponseWriter, req *http.Request, node int) {
// only allow post requests
if req.Method != "POST" {

View File

@ -61,6 +61,22 @@ func readActorsFromResultset(rows *sql.Rows) []types.Actor {
return result
}
// ID - Name : pay attention to the order!
func readTVshowsFromResultset(rows *sql.Rows) []types.TVShow {
result := []types.TVShow{}
for rows.Next() {
var vid types.TVShow
err := rows.Scan(&vid.Id, &vid.Name)
if err != nil {
panic(err.Error()) // proper error handling instead of panic in your app
}
result = append(result, vid)
}
rows.Close()
return result
}
func jsonify(v interface{}) []byte {
// jsonify results
str, err := json.Marshal(v)

View File

@ -29,17 +29,21 @@ func getSettingsFromDB() {
Pasword bool
MediacenterName string
VideoPath string
TVShowPath string
}
regexMatchUrl := regexp.MustCompile("^http(|s):\\/\\/([0-9]){1,3}\\.([0-9]){1,3}\\.([0-9]){1,3}\\.([0-9]){1,3}:[0-9]{1,5}")
regexMatchUrl := regexp.MustCompile("^http(|s)://([0-9]){1,3}\\.([0-9]){1,3}\\.([0-9]){1,3}\\.([0-9]){1,3}:[0-9]{1,5}")
videoUrl := regexMatchUrl.FindString(sett.VideoPath)
tvshowurl := regexMatchUrl.FindString(sett.TVShowPath)
serverVideoPath := strings.TrimPrefix(sett.VideoPath, videoUrl)
serverTVShowPath := strings.TrimPrefix(sett.TVShowPath, tvshowurl)
res := InitialDataTypeResponse{
DarkMode: sett.DarkMode,
Pasword: sett.Pasword != "-1",
MediacenterName: sett.Mediacenter_name,
MediacenterName: sett.MediacenterName,
VideoPath: serverVideoPath,
TVShowPath: serverTVShowPath,
}
str, _ := json.Marshal(res)
@ -74,6 +78,11 @@ func reIndexHandling() {
return database.ManualSuccessResponse(nil)
})
AddHandler("startTVShowReindex", SettingsNode, nil, func() []byte {
videoparser.StartTVShowReindex()
return database.ManualSuccessResponse(nil)
})
AddHandler("cleanupGravity", SettingsNode, nil, func() []byte {
videoparser.StartCleanup()
return nil

15
apiGo/api/TVShows.go Normal file
View File

@ -0,0 +1,15 @@
package api
import "openmediacenter/apiGo/database"
func AddTvshowHandlers() {
var dT struct {
TagId int
Force bool
}
AddHandler("getTVShows", TVShowNode, &dT, func() []byte {
query := "SELECT id, name FROM tvshow"
rows := database.Query(query)
return jsonify(readTVshowsFromResultset(rows))
})
}

View File

@ -37,7 +37,7 @@ func deleteFromDB() {
return database.ManualSuccessResponse(err)
} else {
// check with regex if its the key constraint error
r, _ := regexp.Compile("^.*a foreign key constraint fails.*$")
r := regexp.MustCompile("^.*a foreign key constraint fails.*$")
if r.MatchString(err.Error()) {
return []byte(`{"result":"not empty tag"}`)
} else {

View File

@ -48,7 +48,7 @@ func InitOAuth() {
})
}
func ValidateToken(f http.HandlerFunc) http.HandlerFunc {
func ValidateToken(f func(rw http.ResponseWriter, req *http.Request, node int), node int) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
_, err := srv.ValidationBearerToken(r)
if err != nil {
@ -56,6 +56,6 @@ func ValidateToken(f http.HandlerFunc) http.HandlerFunc {
return
}
f.ServeHTTP(w, r)
f(w, r, node)
}
}

View File

@ -7,12 +7,12 @@ type VideoUnloadedType struct {
type FullVideoType struct {
MovieName string
MovieId int
MovieId uint32
MovieUrl string
Poster string
Likes int
Quality int
Length int
Likes uint64
Quality uint16
Length uint16
Tags []Tag
SuggestedTag []Tag
Actors []Actor
@ -20,22 +20,22 @@ type FullVideoType struct {
type Tag struct {
TagName string
TagId int
TagId uint32
}
type Actor struct {
ActorId int
ActorId uint32
Name string
Thumbnail string
}
type StartData struct {
VideoNr int
FullHdNr int
HDNr int
SDNr int
DifferentTags int
Tagged int
VideoNr uint32
FullHdNr uint32
HDNr uint32
SDNr uint32
DifferentTags uint32
Tagged uint32
}
type SettingsType struct {
@ -47,10 +47,15 @@ type SettingsType struct {
TMDBGrabbing bool
DarkMode bool
VideoNr int
VideoNr uint32
DBSize float32
DifferentTags int
TagsAdded int
DifferentTags uint32
TagsAdded uint32
PathPrefix string
}
type TVShow struct {
Id uint32
Name string
}

View File

@ -15,35 +15,24 @@ func GetPassword() *string {
}
type SettingsType struct {
DarkMode bool
Pasword string
Mediacenter_name string
VideoPath string
DarkMode bool
Pasword string
MediacenterName string
VideoPath string
TVShowPath string
}
func LoadSettings() *SettingsType {
query := "SELECT DarkMode, password, mediacenter_name, video_path from settings"
query := "SELECT DarkMode, password, mediacenter_name, video_path, episode_path from settings"
type RawSettingsType struct {
DarkMode int
Pasword string
Mediacenter_name string
VideoPath string
}
result := SettingsType{}
var darkmode uint8
result := RawSettingsType{}
err := database.QueryRow(query).Scan(&result.DarkMode, &result.Pasword, &result.Mediacenter_name, &result.VideoPath)
err := database.QueryRow(query).Scan(&darkmode, &result.Pasword, &result.MediacenterName, &result.VideoPath, &result.TVShowPath)
if err != nil {
fmt.Println("error while parsing db data: " + err.Error())
}
res := SettingsType{
DarkMode: result.DarkMode != 0,
Pasword: result.Pasword,
Mediacenter_name: result.Mediacenter_name,
VideoPath: result.VideoPath,
}
return &res
result.DarkMode = darkmode != 0
return &result
}

View File

@ -30,6 +30,7 @@ func main() {
api.AddSettingsHandlers()
api.AddTagHandlers()
api.AddActorsHandlers()
api.AddTvshowHandlers()
// add the static files
static.ServeStaticFiles()

View File

@ -54,6 +54,11 @@ func StartReindex() bool {
return true
}
// StartTVShowReindex reindex dir walks for TVShow reindex
func StartTVShowReindex() {
// todo implement walking through dirs and reindex!
}
func GetStatusMessage() *StatusMessage {
msg := StatusMessage{
Messages: messageBuffer,

View File

@ -24,6 +24,26 @@ create table if not exists tags
tag_name varchar(50) null
);
create table if not exists tvshow
(
name varchar(100) null,
thumbnail mediumblob null,
id int auto_increment
primary key
);
create table if not exists tvshow_episodes
(
id int auto_increment
primary key,
name varchar(100) null,
season int null,
poster mediumblob null,
tvshow_id int null,
constraint tvshow_episodes_tvshow_id_fk
foreign key (tvshow_id) references tvshow (id)
);
create table if not exists videos
(
movie_id int auto_increment

View File

@ -79,7 +79,7 @@ class App extends React.Component<{}, state> {
// set theme
GlobalInfos.enableDarkTheme(result.DarkMode);
GlobalInfos.setVideoPath(result.VideoPath);
GlobalInfos.setVideoPaths(result.VideoPath, result.TVShowPath);
this.setState({
mediacentername: result.MediacenterName

View File

@ -23,6 +23,8 @@ interface GetRandomMoviesType {
* Randompage shuffles random viedeopreviews and provides a shuffle btn
*/
class RandomPage extends React.Component<{}, state> {
readonly LoadNR = 3;
constructor(props: {}) {
super(props);
@ -37,7 +39,7 @@ class RandomPage extends React.Component<{}, state> {
componentDidMount(): void {
addKeyHandler(this.keypress);
this.loadShuffledvideos(4);
this.loadShuffledvideos(this.LoadNR);
}
componentWillUnmount(): void {
@ -75,7 +77,7 @@ class RandomPage extends React.Component<{}, state> {
* click handler for shuffle btn
*/
shuffleclick(): void {
this.loadShuffledvideos(4);
this.loadShuffledvideos(this.LoadNR);
}
/**

View File

@ -1,11 +1,38 @@
import React from 'react';
import Preview from '../../elements/Preview/Preview';
import {APINode, callAPI} from '../../utils/Api';
import {TVShow} from '../../types/ApiTypes';
import DynamicContentContainer from '../../elements/DynamicContentContainer/DynamicContentContainer';
interface State {
loading: boolean;
}
interface Props {}
class TVShowPage extends React.Component<Props, State> {
state = {
loading: true
};
data: TVShow.TVshowType[] = [];
componentDidMount(): void {
callAPI(APINode.TVShow, {action: 'getTVShows'}, (resp: TVShow.TVshowType[]) => {
this.data = resp;
this.setState({loading: false});
});
}
class TVShowPage extends React.Component {
render(): JSX.Element {
return (
<>
<Preview name='myTestItem' picLoader={(callback): void => callback('')} />
<DynamicContentContainer
renderElement={(elem): JSX.Element => (
<Preview name={elem.Name} picLoader={(callback): void => callback('')} linkPath={'/tvshows/' + elem.Id} />
)}
data={this.state.loading ? [] : this.data}
/>
</>
);
}

View File

@ -35,6 +35,7 @@ export namespace SettingsTypes {
Password: boolean;
MediacenterName: string;
VideoPath: string;
TVShowPath: string;
}
export interface loadGeneralSettingsType {
@ -58,6 +59,16 @@ export namespace SettingsTypes {
}
}
export namespace TVShow {
/**
* result of actor fetch
*/
export interface TVshowType {
Id: number;
Name: string;
}
}
export namespace ActorTypes {
/**
* result of actor fetch

View File

@ -279,5 +279,6 @@ export enum APINode {
Settings = 'settings',
Tags = 'tags',
Actor = 'actor',
Video = 'video'
Video = 'video',
TVShow = 'tvshow'
}

View File

@ -8,6 +8,7 @@ import lighttheme from '../AppLightTheme.module.css';
class StaticInfos {
private darktheme: boolean = true;
private videopath: string = '';
private tvshowpath: string = '';
/**
* check if the current theme is the dark theme
@ -47,8 +48,9 @@ class StaticInfos {
* set the current videopath
* @param vidpath videopath with beginning and ending slash
*/
setVideoPath(vidpath: string): void {
setVideoPaths(vidpath: string, tvshowpath: string): void {
this.videopath = vidpath;
this.tvshowpath = tvshowpath;
}
/**
@ -58,6 +60,13 @@ class StaticInfos {
return this.videopath;
}
/**
* return the current tvshow path
*/
getTVShowPath(): string {
return this.tvshowpath;
}
/**
* load the Password page manually
*/