diff options
| author | RblSb <msrblsb@gmail.com> | 2025-01-26 23:22:33 +0300 |
|---|---|---|
| committer | RblSb <msrblsb@gmail.com> | 2025-01-28 15:46:30 +0300 |
| commit | 0592564264fff57ccfd9677957196951f9f1c6cf (patch) | |
| tree | c360c2e5d45d9ac8706f836b0466b88221e1f10d | |
| parent | c7518e58788c17ad2ca8340ab5c7633489aa9518 (diff) | |
Video upload feature
And you can play video as soon as upload starts! This is pretty useful for thicc ones. Video will be keeped in cache and will comply cache size limit.
I'm also implemented system storage check to change cache limit if it's lower than config value, so upload will be blocked if there is lower than 10MiB available on disk.
| -rw-r--r-- | build/server.js | 1486 | ||||
| -rw-r--r-- | res/client.js | 194 | ||||
| -rw-r--r-- | res/css/des.css | 24 | ||||
| -rw-r--r-- | res/index.html | 13 | ||||
| -rw-r--r-- | res/langs/en.json | 4 | ||||
| -rw-r--r-- | res/langs/ru.json | 4 | ||||
| -rw-r--r-- | src/Types.hx | 20 | ||||
| -rw-r--r-- | src/client/Buttons.hx | 61 | ||||
| -rw-r--r-- | src/client/JsApi.hx | 24 | ||||
| -rw-r--r-- | src/client/Main.hx | 45 | ||||
| -rw-r--r-- | src/client/Utils.hx | 56 | ||||
| -rw-r--r-- | src/client/players/Raw.hx | 2 | ||||
| -rw-r--r-- | src/import.hx | 2 | ||||
| -rw-r--r-- | src/server/Cache.hx | 139 | ||||
| -rw-r--r-- | src/server/HttpServer.hx | 214 | ||||
| -rw-r--r-- | src/server/Main.hx | 34 | ||||
| -rw-r--r-- | src/server/Utils.hx | 6 | ||||
| -rw-r--r-- | src/tools/MathTools.hx | 55 | ||||
| -rw-r--r-- | src/utils/YoutubeUtils.hx | 2 |
19 files changed, 1676 insertions, 709 deletions
diff --git a/build/server.js b/build/server.js index e2f25cc..ac708e8 100644 --- a/build/server.js +++ b/build/server.js @@ -523,7 +523,7 @@ JsonParser_$1.__name__ = true; JsonParser_$1.__super__ = json2object_reader_BaseParser; JsonParser_$1.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { - this.errors.push(json2object_Error.IncorrectType(variable,"{ ?updatePlaylist : Null<{ videoList : Array<VideoItem> }>, ?updateClients : Null<{ clients : Array<ClientData> }>, type : WsEventType, ?togglePlaylistLock : Null<{ isOpen : Bool }>, ?toggleItemType : Null<{ pos : Int }>, ?skipVideo : Null<{ url : String }>, ?setTime : Null<{ time : Float }>, ?setRate : Null<{ rate : Float }>, ?setNextItem : Null<{ pos : Int }>, ?setLeader : Null<{ clientName : String }>, ?serverMessage : Null<{ textId : String }>, ?rewind : Null<{ time : Float }>, ?removeVideo : Null<{ url : String }>, ?playItem : Null<{ pos : Int }>, ?play : Null<{ time : Float }>, ?pause : Null<{ time : Float }>, ?message : Null<{ text : String, clientName : String }>, ?logout : Null<{ oldClientName : String, clients : Array<ClientData>, clientName : String }>, ?login : Null<{ ?passHash : Null<String>, ?isUnknownClient : Null<Bool>, ?clients : Null<Array<ClientData>>, clientName : String }>, ?kickClient : Null<{ name : String }>, ?getTime : Null<GetTimeEvent>, ?dump : Null<{ data : String }>, ?connected : Null<{ videoList : Array<VideoItem>, uuid : String, playersCacheSupport : Array<PlayerType>, itemPos : Int, isUnknownClient : Bool, isPlaylistOpen : Bool, history : Array<Message>, globalIp : String, config : Config, clients : Array<ClientData>, clientName : String }>, ?banClient : Null<{ time : Float, name : String }>, ?addVideo : Null<{ item : VideoItem, atEnd : Bool }> }",pos)); + this.errors.push(json2object_Error.IncorrectType(variable,"{ ?updatePlaylist : Null<{ videoList : Array<VideoItem> }>, ?updateClients : Null<{ clients : Array<ClientData> }>, type : WsEventType, ?togglePlaylistLock : Null<{ isOpen : Bool }>, ?toggleItemType : Null<{ pos : Int }>, ?skipVideo : Null<{ url : String }>, ?setTime : Null<{ time : Float }>, ?setRate : Null<{ rate : Float }>, ?setNextItem : Null<{ pos : Int }>, ?setLeader : Null<{ clientName : String }>, ?serverMessage : Null<{ textId : String }>, ?rewind : Null<{ time : Float }>, ?removeVideo : Null<{ url : String }>, ?progress : Null<{ type : ProgressType, ratio : Float, ?data : Null<String> }>, ?playItem : Null<{ pos : Int }>, ?play : Null<{ time : Float }>, ?pause : Null<{ time : Float }>, ?message : Null<{ text : String, clientName : String }>, ?logout : Null<{ oldClientName : String, clients : Array<ClientData>, clientName : String }>, ?login : Null<{ ?passHash : Null<String>, ?isUnknownClient : Null<Bool>, ?clients : Null<Array<ClientData>>, clientName : String }>, ?kickClient : Null<{ name : String }>, ?getTime : Null<GetTimeEvent>, ?dump : Null<{ data : String }>, ?connected : Null<{ videoList : Array<VideoItem>, uuid : String, playersCacheSupport : Array<PlayerType>, itemPos : Int, isUnknownClient : Bool, isPlaylistOpen : Bool, history : Array<Message>, globalIp : String, config : Config, clients : Array<ClientData>, clientName : String }>, ?banClient : Null<{ time : Float, name : String }>, ?addVideo : Null<{ item : VideoItem, atEnd : Bool }> }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); } ,loadJsonNull: function(pos,variable) { @@ -531,7 +531,7 @@ JsonParser_$1.prototype = $extend(json2object_reader_BaseParser.prototype,{ } ,loadJsonObject: function(o,pos,variable) { var assigned = new haxe_ds_StringMap(); - this.objectSetupAssign(assigned,["addVideo","banClient","connected","dump","getTime","kickClient","login","logout","message","pause","play","playItem","removeVideo","rewind","serverMessage","setLeader","setNextItem","setRate","setTime","skipVideo","toggleItemType","togglePlaylistLock","type","updateClients","updatePlaylist"],[true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,false,true,true]); + this.objectSetupAssign(assigned,["addVideo","banClient","connected","dump","getTime","kickClient","login","logout","message","pause","play","playItem","progress","removeVideo","rewind","serverMessage","setLeader","setNextItem","setRate","setTime","skipVideo","toggleItemType","togglePlaylistLock","type","updateClients","updatePlaylist"],[true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,false,true,true]); this.value = this.getAuto(); var _g = 0; while(_g < o.length) { @@ -574,44 +574,47 @@ JsonParser_$1.prototype = $extend(json2object_reader_BaseParser.prototype,{ case "playItem": this.value.playItem = this.loadObjectField(($_=new JsonParser_$24(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"playItem",assigned,this.value.playItem,pos); break; + case "progress": + this.value.progress = this.loadObjectField(($_=new JsonParser_$26(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"progress",assigned,this.value.progress,pos); + break; case "removeVideo": - this.value.removeVideo = this.loadObjectField(($_=new JsonParser_$26(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"removeVideo",assigned,this.value.removeVideo,pos); + this.value.removeVideo = this.loadObjectField(($_=new JsonParser_$28(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"removeVideo",assigned,this.value.removeVideo,pos); break; case "rewind": this.value.rewind = this.loadObjectField(($_=new JsonParser_$22(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"rewind",assigned,this.value.rewind,pos); break; case "serverMessage": - this.value.serverMessage = this.loadObjectField(($_=new JsonParser_$28(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"serverMessage",assigned,this.value.serverMessage,pos); + this.value.serverMessage = this.loadObjectField(($_=new JsonParser_$30(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"serverMessage",assigned,this.value.serverMessage,pos); break; case "setLeader": - this.value.setLeader = this.loadObjectField(($_=new JsonParser_$30(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"setLeader",assigned,this.value.setLeader,pos); + this.value.setLeader = this.loadObjectField(($_=new JsonParser_$32(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"setLeader",assigned,this.value.setLeader,pos); break; case "setNextItem": this.value.setNextItem = this.loadObjectField(($_=new JsonParser_$24(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"setNextItem",assigned,this.value.setNextItem,pos); break; case "setRate": - this.value.setRate = this.loadObjectField(($_=new JsonParser_$32(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"setRate",assigned,this.value.setRate,pos); + this.value.setRate = this.loadObjectField(($_=new JsonParser_$34(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"setRate",assigned,this.value.setRate,pos); break; case "setTime": this.value.setTime = this.loadObjectField(($_=new JsonParser_$22(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"setTime",assigned,this.value.setTime,pos); break; case "skipVideo": - this.value.skipVideo = this.loadObjectField(($_=new JsonParser_$26(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"skipVideo",assigned,this.value.skipVideo,pos); + this.value.skipVideo = this.loadObjectField(($_=new JsonParser_$28(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"skipVideo",assigned,this.value.skipVideo,pos); break; case "toggleItemType": this.value.toggleItemType = this.loadObjectField(($_=new JsonParser_$24(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"toggleItemType",assigned,this.value.toggleItemType,pos); break; case "togglePlaylistLock": - this.value.togglePlaylistLock = this.loadObjectField(($_=new JsonParser_$34(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"togglePlaylistLock",assigned,this.value.togglePlaylistLock,pos); + this.value.togglePlaylistLock = this.loadObjectField(($_=new JsonParser_$36(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"togglePlaylistLock",assigned,this.value.togglePlaylistLock,pos); break; case "type": - this.value.type = this.loadObjectField(($_=new JsonParser_$35(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"type",assigned,this.value.type,pos); + this.value.type = this.loadObjectField(($_=new JsonParser_$37(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"type",assigned,this.value.type,pos); break; case "updateClients": - this.value.updateClients = this.loadObjectField(($_=new JsonParser_$37(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"updateClients",assigned,this.value.updateClients,pos); + this.value.updateClients = this.loadObjectField(($_=new JsonParser_$39(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"updateClients",assigned,this.value.updateClients,pos); break; case "updatePlaylist": - this.value.updatePlaylist = this.loadObjectField(($_=new JsonParser_$39(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"updatePlaylist",assigned,this.value.updatePlaylist,pos); + this.value.updatePlaylist = this.loadObjectField(($_=new JsonParser_$41(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"updatePlaylist",assigned,this.value.updatePlaylist,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -620,7 +623,7 @@ JsonParser_$1.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { addVideo : new JsonParser_$3([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), banClient : new JsonParser_$5([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), connected : new JsonParser_$7([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), dump : new JsonParser_$9([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), getTime : new JsonParser_$12([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), kickClient : new JsonParser_$14([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), login : new JsonParser_$16([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), logout : new JsonParser_$18([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), message : new JsonParser_$20([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), pause : new JsonParser_$22([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), play : new JsonParser_$22([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), playItem : new JsonParser_$24([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), removeVideo : new JsonParser_$26([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), rewind : new JsonParser_$22([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), serverMessage : new JsonParser_$28([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setLeader : new JsonParser_$30([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setNextItem : new JsonParser_$24([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setRate : new JsonParser_$32([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setTime : new JsonParser_$22([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), skipVideo : new JsonParser_$26([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), toggleItemType : new JsonParser_$24([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), togglePlaylistLock : new JsonParser_$34([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), type : new JsonParser_$35([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), updateClients : new JsonParser_$37([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), updatePlaylist : new JsonParser_$39([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { addVideo : new JsonParser_$3([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), banClient : new JsonParser_$5([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), connected : new JsonParser_$7([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), dump : new JsonParser_$9([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), getTime : new JsonParser_$12([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), kickClient : new JsonParser_$14([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), login : new JsonParser_$16([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), logout : new JsonParser_$18([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), message : new JsonParser_$20([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), pause : new JsonParser_$22([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), play : new JsonParser_$22([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), playItem : new JsonParser_$24([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), progress : new JsonParser_$26([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), removeVideo : new JsonParser_$28([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), rewind : new JsonParser_$22([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), serverMessage : new JsonParser_$30([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setLeader : new JsonParser_$32([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setNextItem : new JsonParser_$24([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setRate : new JsonParser_$34([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), setTime : new JsonParser_$22([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), skipVideo : new JsonParser_$28([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), toggleItemType : new JsonParser_$24([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), togglePlaylistLock : new JsonParser_$36([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), type : new JsonParser_$37([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), updateClients : new JsonParser_$39([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), updatePlaylist : new JsonParser_$41([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$1 }); @@ -650,16 +653,16 @@ JsonParser_$12.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "paused": - this.value.paused = this.loadObjectField(($_=new JsonParser_$58(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"paused",assigned,this.value.paused,pos); + this.value.paused = this.loadObjectField(($_=new JsonParser_$61(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"paused",assigned,this.value.paused,pos); break; case "pausedByServer": - this.value.pausedByServer = this.loadObjectField(($_=new JsonParser_$58(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"pausedByServer",assigned,this.value.pausedByServer,pos); + this.value.pausedByServer = this.loadObjectField(($_=new JsonParser_$61(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"pausedByServer",assigned,this.value.pausedByServer,pos); break; case "rate": - this.value.rate = this.loadObjectField(($_=new JsonParser_$60(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"rate",assigned,this.value.rate,pos); + this.value.rate = this.loadObjectField(($_=new JsonParser_$63(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"rate",assigned,this.value.rate,pos); break; case "time": - this.value.time = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"time",assigned,this.value.time,pos); + this.value.time = this.loadObjectField(($_=new JsonParser_$49(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"time",assigned,this.value.time,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -668,7 +671,7 @@ JsonParser_$12.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { paused : new JsonParser_$58([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), pausedByServer : new JsonParser_$58([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), rate : new JsonParser_$60([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), time : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { paused : new JsonParser_$61([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), pausedByServer : new JsonParser_$61([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), rate : new JsonParser_$63([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), time : new JsonParser_$49([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$12 }); @@ -697,7 +700,7 @@ JsonParser_$14.prototype = $extend(json2object_reader_BaseParser.prototype,{ var field = o[_g]; ++_g; if(field.name == "name") { - this.value.name = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); + this.value.name = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); } else { this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); } @@ -705,7 +708,7 @@ JsonParser_$14.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { name : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { name : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$14 }); @@ -735,16 +738,16 @@ JsonParser_$16.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "clientName": - this.value.clientName = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clientName",assigned,this.value.clientName,pos); + this.value.clientName = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clientName",assigned,this.value.clientName,pos); break; case "clients": - this.value.clients = this.loadObjectField(($_=new JsonParser_$56(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clients",assigned,this.value.clients,pos); + this.value.clients = this.loadObjectField(($_=new JsonParser_$59(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clients",assigned,this.value.clients,pos); break; case "isUnknownClient": - this.value.isUnknownClient = this.loadObjectField(($_=new JsonParser_$58(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isUnknownClient",assigned,this.value.isUnknownClient,pos); + this.value.isUnknownClient = this.loadObjectField(($_=new JsonParser_$61(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isUnknownClient",assigned,this.value.isUnknownClient,pos); break; case "passHash": - this.value.passHash = this.loadObjectField(($_=new JsonParser_$50(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"passHash",assigned,this.value.passHash,pos); + this.value.passHash = this.loadObjectField(($_=new JsonParser_$52(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"passHash",assigned,this.value.passHash,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -753,7 +756,7 @@ JsonParser_$16.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { clientName : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), clients : new JsonParser_$56([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isUnknownClient : new JsonParser_$58([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), passHash : new JsonParser_$50([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { clientName : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), clients : new JsonParser_$59([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isUnknownClient : new JsonParser_$61([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), passHash : new JsonParser_$52([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$16 }); @@ -783,13 +786,13 @@ JsonParser_$18.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "clientName": - this.value.clientName = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clientName",assigned,this.value.clientName,pos); + this.value.clientName = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clientName",assigned,this.value.clientName,pos); break; case "clients": - this.value.clients = this.loadObjectField(($_=new JsonParser_$51(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clients",assigned,this.value.clients,pos); + this.value.clients = this.loadObjectField(($_=new JsonParser_$53(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clients",assigned,this.value.clients,pos); break; case "oldClientName": - this.value.oldClientName = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"oldClientName",assigned,this.value.oldClientName,pos); + this.value.oldClientName = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"oldClientName",assigned,this.value.oldClientName,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -798,7 +801,7 @@ JsonParser_$18.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { clientName : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), clients : new JsonParser_$51([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), oldClientName : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { clientName : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), clients : new JsonParser_$53([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), oldClientName : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$18 }); @@ -828,10 +831,10 @@ JsonParser_$20.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "clientName": - this.value.clientName = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clientName",assigned,this.value.clientName,pos); + this.value.clientName = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clientName",assigned,this.value.clientName,pos); break; case "text": - this.value.text = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"text",assigned,this.value.text,pos); + this.value.text = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"text",assigned,this.value.text,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -840,7 +843,7 @@ JsonParser_$20.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { clientName : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), text : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { clientName : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), text : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$20 }); @@ -869,7 +872,7 @@ JsonParser_$22.prototype = $extend(json2object_reader_BaseParser.prototype,{ var field = o[_g]; ++_g; if(field.name == "time") { - this.value.time = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"time",assigned,this.value.time,pos); + this.value.time = this.loadObjectField(($_=new JsonParser_$49(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"time",assigned,this.value.time,pos); } else { this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); } @@ -877,7 +880,7 @@ JsonParser_$22.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { time : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { time : new JsonParser_$49([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$22 }); @@ -906,7 +909,7 @@ JsonParser_$24.prototype = $extend(json2object_reader_BaseParser.prototype,{ var field = o[_g]; ++_g; if(field.name == "pos") { - this.value.pos = this.loadObjectField(($_=new JsonParser_$54(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"pos",assigned,this.value.pos,pos); + this.value.pos = this.loadObjectField(($_=new JsonParser_$56(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"pos",assigned,this.value.pos,pos); } else { this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); } @@ -914,7 +917,7 @@ JsonParser_$24.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { pos : new JsonParser_$54([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { pos : new JsonParser_$56([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$24 }); @@ -928,7 +931,7 @@ JsonParser_$26.__name__ = true; JsonParser_$26.__super__ = json2object_reader_BaseParser; JsonParser_$26.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { - this.errors.push(json2object_Error.IncorrectType(variable,"{ url : String }",pos)); + this.errors.push(json2object_Error.IncorrectType(variable,"{ type : ProgressType, ratio : Float, ?data : Null<String> }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); } ,loadJsonNull: function(pos,variable) { @@ -936,22 +939,30 @@ JsonParser_$26.prototype = $extend(json2object_reader_BaseParser.prototype,{ } ,loadJsonObject: function(o,pos,variable) { var assigned = new haxe_ds_StringMap(); - this.objectSetupAssign(assigned,["url"],[false]); + this.objectSetupAssign(assigned,["data","ratio","type"],[true,false,false]); this.value = this.getAuto(); var _g = 0; while(_g < o.length) { var field = o[_g]; ++_g; - if(field.name == "url") { - this.value.url = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"url",assigned,this.value.url,pos); - } else { + switch(field.name) { + case "data": + this.value.data = this.loadObjectField(($_=new JsonParser_$52(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"data",assigned,this.value.data,pos); + break; + case "ratio": + this.value.ratio = this.loadObjectField(($_=new JsonParser_$49(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"ratio",assigned,this.value.ratio,pos); + break; + case "type": + this.value.type = this.loadObjectField(($_=new JsonParser_$57(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"type",assigned,this.value.type,pos); + break; + default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); } } this.objectErrors(assigned,pos); } ,getAuto: function() { - return { url : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { data : new JsonParser_$52([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), ratio : new JsonParser_$49([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), type : new JsonParser_$57([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$26 }); @@ -965,7 +976,7 @@ JsonParser_$28.__name__ = true; JsonParser_$28.__super__ = json2object_reader_BaseParser; JsonParser_$28.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { - this.errors.push(json2object_Error.IncorrectType(variable,"{ textId : String }",pos)); + this.errors.push(json2object_Error.IncorrectType(variable,"{ url : String }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); } ,loadJsonNull: function(pos,variable) { @@ -973,14 +984,14 @@ JsonParser_$28.prototype = $extend(json2object_reader_BaseParser.prototype,{ } ,loadJsonObject: function(o,pos,variable) { var assigned = new haxe_ds_StringMap(); - this.objectSetupAssign(assigned,["textId"],[false]); + this.objectSetupAssign(assigned,["url"],[false]); this.value = this.getAuto(); var _g = 0; while(_g < o.length) { var field = o[_g]; ++_g; - if(field.name == "textId") { - this.value.textId = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"textId",assigned,this.value.textId,pos); + if(field.name == "url") { + this.value.url = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"url",assigned,this.value.url,pos); } else { this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); } @@ -988,7 +999,7 @@ JsonParser_$28.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { textId : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { url : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$28 }); @@ -1018,10 +1029,10 @@ JsonParser_$3.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "atEnd": - this.value.atEnd = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"atEnd",assigned,this.value.atEnd,pos); + this.value.atEnd = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"atEnd",assigned,this.value.atEnd,pos); break; case "item": - this.value.item = this.loadObjectField(($_=new JsonParser_$44(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"item",assigned,this.value.item,pos); + this.value.item = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"item",assigned,this.value.item,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -1030,7 +1041,7 @@ JsonParser_$3.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { atEnd : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), item : new JsonParser_$44([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { atEnd : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), item : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$3 }); @@ -1044,7 +1055,7 @@ JsonParser_$30.__name__ = true; JsonParser_$30.__super__ = json2object_reader_BaseParser; JsonParser_$30.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { - this.errors.push(json2object_Error.IncorrectType(variable,"{ clientName : String }",pos)); + this.errors.push(json2object_Error.IncorrectType(variable,"{ textId : String }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); } ,loadJsonNull: function(pos,variable) { @@ -1052,14 +1063,14 @@ JsonParser_$30.prototype = $extend(json2object_reader_BaseParser.prototype,{ } ,loadJsonObject: function(o,pos,variable) { var assigned = new haxe_ds_StringMap(); - this.objectSetupAssign(assigned,["clientName"],[false]); + this.objectSetupAssign(assigned,["textId"],[false]); this.value = this.getAuto(); var _g = 0; while(_g < o.length) { var field = o[_g]; ++_g; - if(field.name == "clientName") { - this.value.clientName = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clientName",assigned,this.value.clientName,pos); + if(field.name == "textId") { + this.value.textId = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"textId",assigned,this.value.textId,pos); } else { this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); } @@ -1067,7 +1078,7 @@ JsonParser_$30.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { clientName : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { textId : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$30 }); @@ -1081,7 +1092,7 @@ JsonParser_$32.__name__ = true; JsonParser_$32.__super__ = json2object_reader_BaseParser; JsonParser_$32.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { - this.errors.push(json2object_Error.IncorrectType(variable,"{ rate : Float }",pos)); + this.errors.push(json2object_Error.IncorrectType(variable,"{ clientName : String }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); } ,loadJsonNull: function(pos,variable) { @@ -1089,14 +1100,14 @@ JsonParser_$32.prototype = $extend(json2object_reader_BaseParser.prototype,{ } ,loadJsonObject: function(o,pos,variable) { var assigned = new haxe_ds_StringMap(); - this.objectSetupAssign(assigned,["rate"],[false]); + this.objectSetupAssign(assigned,["clientName"],[false]); this.value = this.getAuto(); var _g = 0; while(_g < o.length) { var field = o[_g]; ++_g; - if(field.name == "rate") { - this.value.rate = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"rate",assigned,this.value.rate,pos); + if(field.name == "clientName") { + this.value.clientName = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clientName",assigned,this.value.clientName,pos); } else { this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); } @@ -1104,7 +1115,7 @@ JsonParser_$32.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { rate : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { clientName : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$32 }); @@ -1118,6 +1129,43 @@ JsonParser_$34.__name__ = true; JsonParser_$34.__super__ = json2object_reader_BaseParser; JsonParser_$34.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { + this.errors.push(json2object_Error.IncorrectType(variable,"{ rate : Float }",pos)); + json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); + } + ,loadJsonNull: function(pos,variable) { + this.value = null; + } + ,loadJsonObject: function(o,pos,variable) { + var assigned = new haxe_ds_StringMap(); + this.objectSetupAssign(assigned,["rate"],[false]); + this.value = this.getAuto(); + var _g = 0; + while(_g < o.length) { + var field = o[_g]; + ++_g; + if(field.name == "rate") { + this.value.rate = this.loadObjectField(($_=new JsonParser_$49(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"rate",assigned,this.value.rate,pos); + } else { + this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); + } + } + this.objectErrors(assigned,pos); + } + ,getAuto: function() { + return { rate : new JsonParser_$49([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + } + ,__class__: JsonParser_$34 +}); +var JsonParser_$36 = function(errors,putils,errorType) { + if(errorType == null) { + errorType = 0; + } + json2object_reader_BaseParser.call(this,errors,putils,errorType); +}; +JsonParser_$36.__name__ = true; +JsonParser_$36.__super__ = json2object_reader_BaseParser; +JsonParser_$36.prototype = $extend(json2object_reader_BaseParser.prototype,{ + onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"{ isOpen : Bool }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); } @@ -1133,7 +1181,7 @@ JsonParser_$34.prototype = $extend(json2object_reader_BaseParser.prototype,{ var field = o[_g]; ++_g; if(field.name == "isOpen") { - this.value.isOpen = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isOpen",assigned,this.value.isOpen,pos); + this.value.isOpen = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isOpen",assigned,this.value.isOpen,pos); } else { this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); } @@ -1141,19 +1189,19 @@ JsonParser_$34.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { isOpen : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { isOpen : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } - ,__class__: JsonParser_$34 + ,__class__: JsonParser_$36 }); -var JsonParser_$35 = function(errors,putils,errorType) { +var JsonParser_$37 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$35.__name__ = true; -JsonParser_$35.__super__ = json2object_reader_BaseParser; -JsonParser_$35.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$37.__name__ = true; +JsonParser_$37.__super__ = json2object_reader_BaseParser; +JsonParser_$37.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.value = "Connected"; this.errors.push(json2object_Error.IncorrectType(variable,"WsEventType",pos)); @@ -1163,19 +1211,19 @@ JsonParser_$35.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.value = null; } ,loadJsonString: function(s,pos,variable) { - this.value = this.loadString(s,pos,variable,["Connected","Disconnected","Login","PasswordRequest","LoginError","Logout","Message","ServerMessage","UpdateClients","BanClient","KickClient","AddVideo","RemoveVideo","SkipVideo","VideoLoaded","Pause","Play","GetTime","SetTime","SetRate","Rewind","Flashback","SetLeader","PlayItem","SetNextItem","ToggleItemType","ClearChat","ClearPlaylist","ShufflePlaylist","UpdatePlaylist","TogglePlaylistLock","Dump"],"Connected"); + this.value = this.loadString(s,pos,variable,["Connected","Disconnected","Login","PasswordRequest","LoginError","Logout","Message","ServerMessage","Progress","UpdateClients","BanClient","KickClient","AddVideo","RemoveVideo","SkipVideo","VideoLoaded","Pause","Play","GetTime","SetTime","SetRate","Rewind","Flashback","SetLeader","PlayItem","SetNextItem","ToggleItemType","ClearChat","ClearPlaylist","ShufflePlaylist","UpdatePlaylist","TogglePlaylistLock","Dump"],"Connected"); } - ,__class__: JsonParser_$35 + ,__class__: JsonParser_$37 }); -var JsonParser_$37 = function(errors,putils,errorType) { +var JsonParser_$39 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$37.__name__ = true; -JsonParser_$37.__super__ = json2object_reader_BaseParser; -JsonParser_$37.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$39.__name__ = true; +JsonParser_$39.__super__ = json2object_reader_BaseParser; +JsonParser_$39.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"{ clients : Array<ClientData> }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1192,7 +1240,7 @@ JsonParser_$37.prototype = $extend(json2object_reader_BaseParser.prototype,{ var field = o[_g]; ++_g; if(field.name == "clients") { - this.value.clients = this.loadObjectField(($_=new JsonParser_$51(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clients",assigned,this.value.clients,pos); + this.value.clients = this.loadObjectField(($_=new JsonParser_$53(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clients",assigned,this.value.clients,pos); } else { this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); } @@ -1200,19 +1248,19 @@ JsonParser_$37.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { clients : new JsonParser_$51([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { clients : new JsonParser_$53([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } - ,__class__: JsonParser_$37 + ,__class__: JsonParser_$39 }); -var JsonParser_$39 = function(errors,putils,errorType) { +var JsonParser_$41 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$39.__name__ = true; -JsonParser_$39.__super__ = json2object_reader_BaseParser; -JsonParser_$39.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$41.__name__ = true; +JsonParser_$41.__super__ = json2object_reader_BaseParser; +JsonParser_$41.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"{ videoList : Array<VideoItem> }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1229,7 +1277,7 @@ JsonParser_$39.prototype = $extend(json2object_reader_BaseParser.prototype,{ var field = o[_g]; ++_g; if(field.name == "videoList") { - this.value.videoList = this.loadObjectField(($_=new JsonParser_$42(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"videoList",assigned,this.value.videoList,pos); + this.value.videoList = this.loadObjectField(($_=new JsonParser_$44(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"videoList",assigned,this.value.videoList,pos); } else { this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); } @@ -1237,19 +1285,19 @@ JsonParser_$39.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { videoList : new JsonParser_$42([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { videoList : new JsonParser_$44([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } - ,__class__: JsonParser_$39 + ,__class__: JsonParser_$41 }); -var JsonParser_$42 = function(errors,putils,errorType) { +var JsonParser_$44 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$42.__name__ = true; -JsonParser_$42.__super__ = json2object_reader_BaseParser; -JsonParser_$42.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$44.__name__ = true; +JsonParser_$44.__super__ = json2object_reader_BaseParser; +JsonParser_$44.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"Array<VideoItem>",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1258,19 +1306,19 @@ JsonParser_$42.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.value = null; } ,loadJsonArray: function(a,pos,variable) { - this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$44(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); + this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$46(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); } - ,__class__: JsonParser_$42 + ,__class__: JsonParser_$44 }); -var JsonParser_$44 = function(errors,putils,errorType) { +var JsonParser_$46 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$44.__name__ = true; -JsonParser_$44.__super__ = json2object_reader_BaseParser; -JsonParser_$44.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$46.__name__ = true; +JsonParser_$46.__super__ = json2object_reader_BaseParser; +JsonParser_$46.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"{ ?voiceOverTrack : Null<String>, url : String, title : String, ?subs : Null<String>, playerType : PlayerType, isTemp : Bool, duration : Float, doCache : Bool, author : String }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1288,31 +1336,31 @@ JsonParser_$44.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "author": - this.value.author = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"author",assigned,this.value.author,pos); + this.value.author = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"author",assigned,this.value.author,pos); break; case "doCache": - this.value.doCache = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"doCache",assigned,this.value.doCache,pos); + this.value.doCache = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"doCache",assigned,this.value.doCache,pos); break; case "duration": - this.value.duration = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"duration",assigned,this.value.duration,pos); + this.value.duration = this.loadObjectField(($_=new JsonParser_$49(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"duration",assigned,this.value.duration,pos); break; case "isTemp": - this.value.isTemp = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isTemp",assigned,this.value.isTemp,pos); + this.value.isTemp = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isTemp",assigned,this.value.isTemp,pos); break; case "playerType": - this.value.playerType = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"playerType",assigned,this.value.playerType,pos); + this.value.playerType = this.loadObjectField(($_=new JsonParser_$50(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"playerType",assigned,this.value.playerType,pos); break; case "subs": - this.value.subs = this.loadObjectField(($_=new JsonParser_$50(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"subs",assigned,this.value.subs,pos); + this.value.subs = this.loadObjectField(($_=new JsonParser_$52(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"subs",assigned,this.value.subs,pos); break; case "title": - this.value.title = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"title",assigned,this.value.title,pos); + this.value.title = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"title",assigned,this.value.title,pos); break; case "url": - this.loadObjectFieldReflect(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"url",assigned,pos); + this.loadObjectFieldReflect(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"url",assigned,pos); break; case "voiceOverTrack": - this.value.voiceOverTrack = this.loadObjectField(($_=new JsonParser_$50(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"voiceOverTrack",assigned,this.value.voiceOverTrack,pos); + this.value.voiceOverTrack = this.loadObjectField(($_=new JsonParser_$52(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"voiceOverTrack",assigned,this.value.voiceOverTrack,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -1321,19 +1369,19 @@ JsonParser_$44.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { author : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), doCache : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), duration : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isTemp : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), playerType : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), subs : new JsonParser_$50([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), title : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), url : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), voiceOverTrack : new JsonParser_$50([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { author : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), doCache : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), duration : new JsonParser_$49([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isTemp : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), playerType : new JsonParser_$50([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), subs : new JsonParser_$52([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), title : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), url : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), voiceOverTrack : new JsonParser_$52([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } - ,__class__: JsonParser_$44 + ,__class__: JsonParser_$46 }); -var JsonParser_$45 = function(errors,putils,errorType) { +var JsonParser_$47 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$45.__name__ = true; -JsonParser_$45.__super__ = json2object_reader_BaseParser; -JsonParser_$45.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$47.__name__ = true; +JsonParser_$47.__super__ = json2object_reader_BaseParser; +JsonParser_$47.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"String",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1344,18 +1392,18 @@ JsonParser_$45.prototype = $extend(json2object_reader_BaseParser.prototype,{ ,loadJsonString: function(s,pos,variable) { this.value = s; } - ,__class__: JsonParser_$45 + ,__class__: JsonParser_$47 }); -var JsonParser_$46 = function(errors,putils,errorType) { +var JsonParser_$48 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); this.value = false; }; -JsonParser_$46.__name__ = true; -JsonParser_$46.__super__ = json2object_reader_BaseParser; -JsonParser_$46.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$48.__name__ = true; +JsonParser_$48.__super__ = json2object_reader_BaseParser; +JsonParser_$48.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"Bool",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1363,18 +1411,18 @@ JsonParser_$46.prototype = $extend(json2object_reader_BaseParser.prototype,{ ,loadJsonBool: function(b,pos,variable) { this.value = b; } - ,__class__: JsonParser_$46 + ,__class__: JsonParser_$48 }); -var JsonParser_$47 = function(errors,putils,errorType) { +var JsonParser_$49 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); this.value = 0; }; -JsonParser_$47.__name__ = true; -JsonParser_$47.__super__ = json2object_reader_BaseParser; -JsonParser_$47.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$49.__name__ = true; +JsonParser_$49.__super__ = json2object_reader_BaseParser; +JsonParser_$49.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"Float",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1382,29 +1430,7 @@ JsonParser_$47.prototype = $extend(json2object_reader_BaseParser.prototype,{ ,loadJsonNumber: function(f,pos,variable) { this.value = this.loadJsonFloat(f,pos,variable,this.value); } - ,__class__: JsonParser_$47 -}); -var JsonParser_$48 = function(errors,putils,errorType) { - if(errorType == null) { - errorType = 0; - } - json2object_reader_BaseParser.call(this,errors,putils,errorType); -}; -JsonParser_$48.__name__ = true; -JsonParser_$48.__super__ = json2object_reader_BaseParser; -JsonParser_$48.prototype = $extend(json2object_reader_BaseParser.prototype,{ - onIncorrectType: function(pos,variable) { - this.value = "RawType"; - this.errors.push(json2object_Error.IncorrectType(variable,"PlayerType",pos)); - this.objectThrow(pos,variable); - } - ,loadJsonNull: function(pos,variable) { - this.value = null; - } - ,loadJsonString: function(s,pos,variable) { - this.value = this.loadString(s,pos,variable,["RawType","YoutubeType","VkType","IframeType"],"RawType"); - } - ,__class__: JsonParser_$48 + ,__class__: JsonParser_$49 }); var JsonParser_$5 = function(errors,putils,errorType) { if(errorType == null) { @@ -1432,10 +1458,10 @@ JsonParser_$5.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "name": - this.value.name = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); + this.value.name = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); break; case "time": - this.value.time = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"time",assigned,this.value.time,pos); + this.value.time = this.loadObjectField(($_=new JsonParser_$49(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"time",assigned,this.value.time,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -1444,7 +1470,7 @@ JsonParser_$5.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { name : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), time : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { name : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), time : new JsonParser_$49([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$5 }); @@ -1458,37 +1484,38 @@ JsonParser_$50.__name__ = true; JsonParser_$50.__super__ = json2object_reader_BaseParser; JsonParser_$50.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { - this.errors.push(json2object_Error.IncorrectType(variable,"String",pos)); - json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); + this.value = "RawType"; + this.errors.push(json2object_Error.IncorrectType(variable,"PlayerType",pos)); + this.objectThrow(pos,variable); } ,loadJsonNull: function(pos,variable) { this.value = null; } ,loadJsonString: function(s,pos,variable) { - this.value = s; + this.value = this.loadString(s,pos,variable,["RawType","YoutubeType","VkType","IframeType"],"RawType"); } ,__class__: JsonParser_$50 }); -var JsonParser_$51 = function(errors,putils,errorType) { +var JsonParser_$52 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$51.__name__ = true; -JsonParser_$51.__super__ = json2object_reader_BaseParser; -JsonParser_$51.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$52.__name__ = true; +JsonParser_$52.__super__ = json2object_reader_BaseParser; +JsonParser_$52.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { - this.errors.push(json2object_Error.IncorrectType(variable,"Array<ClientData>",pos)); + this.errors.push(json2object_Error.IncorrectType(variable,"String",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); } ,loadJsonNull: function(pos,variable) { this.value = null; } - ,loadJsonArray: function(a,pos,variable) { - this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$53(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); + ,loadJsonString: function(s,pos,variable) { + this.value = s; } - ,__class__: JsonParser_$51 + ,__class__: JsonParser_$52 }); var JsonParser_$53 = function(errors,putils,errorType) { if(errorType == null) { @@ -1500,6 +1527,27 @@ JsonParser_$53.__name__ = true; JsonParser_$53.__super__ = json2object_reader_BaseParser; JsonParser_$53.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { + this.errors.push(json2object_Error.IncorrectType(variable,"Array<ClientData>",pos)); + json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); + } + ,loadJsonNull: function(pos,variable) { + this.value = null; + } + ,loadJsonArray: function(a,pos,variable) { + this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$55(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); + } + ,__class__: JsonParser_$53 +}); +var JsonParser_$55 = function(errors,putils,errorType) { + if(errorType == null) { + errorType = 0; + } + json2object_reader_BaseParser.call(this,errors,putils,errorType); +}; +JsonParser_$55.__name__ = true; +JsonParser_$55.__super__ = json2object_reader_BaseParser; +JsonParser_$55.prototype = $extend(json2object_reader_BaseParser.prototype,{ + onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"{ name : String, group : Int }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); } @@ -1516,10 +1564,10 @@ JsonParser_$53.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "group": - this.value.group = this.loadObjectField(($_=new JsonParser_$54(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"group",assigned,this.value.group,pos); + this.value.group = this.loadObjectField(($_=new JsonParser_$56(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"group",assigned,this.value.group,pos); break; case "name": - this.value.name = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); + this.value.name = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -1528,20 +1576,20 @@ JsonParser_$53.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { group : new JsonParser_$54([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), name : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { group : new JsonParser_$56([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), name : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } - ,__class__: JsonParser_$53 + ,__class__: JsonParser_$55 }); -var JsonParser_$54 = function(errors,putils,errorType) { +var JsonParser_$56 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); this.value = 0; }; -JsonParser_$54.__name__ = true; -JsonParser_$54.__super__ = json2object_reader_BaseParser; -JsonParser_$54.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$56.__name__ = true; +JsonParser_$56.__super__ = json2object_reader_BaseParser; +JsonParser_$56.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"Int",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1549,17 +1597,39 @@ JsonParser_$54.prototype = $extend(json2object_reader_BaseParser.prototype,{ ,loadJsonNumber: function(f,pos,variable) { this.value = this.loadJsonInt(f,pos,variable,this.value); } - ,__class__: JsonParser_$54 + ,__class__: JsonParser_$56 }); -var JsonParser_$56 = function(errors,putils,errorType) { +var JsonParser_$57 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$56.__name__ = true; -JsonParser_$56.__super__ = json2object_reader_BaseParser; -JsonParser_$56.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$57.__name__ = true; +JsonParser_$57.__super__ = json2object_reader_BaseParser; +JsonParser_$57.prototype = $extend(json2object_reader_BaseParser.prototype,{ + onIncorrectType: function(pos,variable) { + this.value = "Caching"; + this.errors.push(json2object_Error.IncorrectType(variable,"ProgressType",pos)); + this.objectThrow(pos,variable); + } + ,loadJsonNull: function(pos,variable) { + this.value = null; + } + ,loadJsonString: function(s,pos,variable) { + this.value = this.loadString(s,pos,variable,["Caching","Downloading","Uploading"],"Caching"); + } + ,__class__: JsonParser_$57 +}); +var JsonParser_$59 = function(errors,putils,errorType) { + if(errorType == null) { + errorType = 0; + } + json2object_reader_BaseParser.call(this,errors,putils,errorType); +}; +JsonParser_$59.__name__ = true; +JsonParser_$59.__super__ = json2object_reader_BaseParser; +JsonParser_$59.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"Array<ClientData>",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1568,19 +1638,19 @@ JsonParser_$56.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.value = null; } ,loadJsonArray: function(a,pos,variable) { - this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$53(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); + this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$55(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); } - ,__class__: JsonParser_$56 + ,__class__: JsonParser_$59 }); -var JsonParser_$58 = function(errors,putils,errorType) { +var JsonParser_$61 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$58.__name__ = true; -JsonParser_$58.__super__ = json2object_reader_BaseParser; -JsonParser_$58.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$61.__name__ = true; +JsonParser_$61.__super__ = json2object_reader_BaseParser; +JsonParser_$61.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"Bool",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1591,17 +1661,17 @@ JsonParser_$58.prototype = $extend(json2object_reader_BaseParser.prototype,{ ,loadJsonBool: function(b,pos,variable) { this.value = b; } - ,__class__: JsonParser_$58 + ,__class__: JsonParser_$61 }); -var JsonParser_$60 = function(errors,putils,errorType) { +var JsonParser_$63 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$60.__name__ = true; -JsonParser_$60.__super__ = json2object_reader_BaseParser; -JsonParser_$60.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$63.__name__ = true; +JsonParser_$63.__super__ = json2object_reader_BaseParser; +JsonParser_$63.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"Float",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1612,17 +1682,17 @@ JsonParser_$60.prototype = $extend(json2object_reader_BaseParser.prototype,{ ,loadJsonNumber: function(f,pos,variable) { this.value = this.loadJsonFloat(f,pos,variable,this.value); } - ,__class__: JsonParser_$60 + ,__class__: JsonParser_$63 }); -var JsonParser_$62 = function(errors,putils,errorType) { +var JsonParser_$65 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$62.__name__ = true; -JsonParser_$62.__super__ = json2object_reader_BaseParser; -JsonParser_$62.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$65.__name__ = true; +JsonParser_$65.__super__ = json2object_reader_BaseParser; +JsonParser_$65.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"{ youtubePlaylistLimit : Int, youtubeApiKey : String, userVideoLimit : Int, unpauseWithoutLeader : Bool, totalVideoLimit : Int, templateUrl : String, serverChatHistory : Int, ?salt : Null<String>, requestLeaderOnPause : Bool, port : Int, permissions : Permissions, maxMessageLength : Int, maxLoginLength : Int, localNetworkOnly : Bool, localAdmins : Bool, ?isVerbose : Null<Bool>, filters : Array<Filter>, emotes : Array<Emote>, channelName : String, cacheStorageLimitGiB : Float, allowProxyIps : Bool }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1640,67 +1710,67 @@ JsonParser_$62.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "allowProxyIps": - this.value.allowProxyIps = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"allowProxyIps",assigned,this.value.allowProxyIps,pos); + this.value.allowProxyIps = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"allowProxyIps",assigned,this.value.allowProxyIps,pos); break; case "cacheStorageLimitGiB": - this.value.cacheStorageLimitGiB = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"cacheStorageLimitGiB",assigned,this.value.cacheStorageLimitGiB,pos); + this.value.cacheStorageLimitGiB = this.loadObjectField(($_=new JsonParser_$49(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"cacheStorageLimitGiB",assigned,this.value.cacheStorageLimitGiB,pos); break; case "channelName": - this.value.channelName = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"channelName",assigned,this.value.channelName,pos); + this.value.channelName = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"channelName",assigned,this.value.channelName,pos); break; case "emotes": - this.value.emotes = this.loadObjectField(($_=new JsonParser_$67(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"emotes",assigned,this.value.emotes,pos); + this.value.emotes = this.loadObjectField(($_=new JsonParser_$70(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"emotes",assigned,this.value.emotes,pos); break; case "filters": - this.value.filters = this.loadObjectField(($_=new JsonParser_$68(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"filters",assigned,this.value.filters,pos); + this.value.filters = this.loadObjectField(($_=new JsonParser_$71(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"filters",assigned,this.value.filters,pos); break; case "isVerbose": - this.value.isVerbose = this.loadObjectField(($_=new JsonParser_$58(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isVerbose",assigned,this.value.isVerbose,pos); + this.value.isVerbose = this.loadObjectField(($_=new JsonParser_$61(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isVerbose",assigned,this.value.isVerbose,pos); break; case "localAdmins": - this.value.localAdmins = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"localAdmins",assigned,this.value.localAdmins,pos); + this.value.localAdmins = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"localAdmins",assigned,this.value.localAdmins,pos); break; case "localNetworkOnly": - this.value.localNetworkOnly = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"localNetworkOnly",assigned,this.value.localNetworkOnly,pos); + this.value.localNetworkOnly = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"localNetworkOnly",assigned,this.value.localNetworkOnly,pos); break; case "maxLoginLength": - this.value.maxLoginLength = this.loadObjectField(($_=new JsonParser_$54(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"maxLoginLength",assigned,this.value.maxLoginLength,pos); + this.value.maxLoginLength = this.loadObjectField(($_=new JsonParser_$56(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"maxLoginLength",assigned,this.value.maxLoginLength,pos); break; case "maxMessageLength": - this.value.maxMessageLength = this.loadObjectField(($_=new JsonParser_$54(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"maxMessageLength",assigned,this.value.maxMessageLength,pos); + this.value.maxMessageLength = this.loadObjectField(($_=new JsonParser_$56(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"maxMessageLength",assigned,this.value.maxMessageLength,pos); break; case "permissions": - this.value.permissions = this.loadObjectField(($_=new JsonParser_$70(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"permissions",assigned,this.value.permissions,pos); + this.value.permissions = this.loadObjectField(($_=new JsonParser_$73(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"permissions",assigned,this.value.permissions,pos); break; case "port": - this.value.port = this.loadObjectField(($_=new JsonParser_$54(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"port",assigned,this.value.port,pos); + this.value.port = this.loadObjectField(($_=new JsonParser_$56(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"port",assigned,this.value.port,pos); break; case "requestLeaderOnPause": - this.value.requestLeaderOnPause = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"requestLeaderOnPause",assigned,this.value.requestLeaderOnPause,pos); + this.value.requestLeaderOnPause = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"requestLeaderOnPause",assigned,this.value.requestLeaderOnPause,pos); break; case "salt": - this.value.salt = this.loadObjectField(($_=new JsonParser_$50(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"salt",assigned,this.value.salt,pos); + this.value.salt = this.loadObjectField(($_=new JsonParser_$52(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"salt",assigned,this.value.salt,pos); break; case "serverChatHistory": - this.value.serverChatHistory = this.loadObjectField(($_=new JsonParser_$54(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"serverChatHistory",assigned,this.value.serverChatHistory,pos); + this.value.serverChatHistory = this.loadObjectField(($_=new JsonParser_$56(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"serverChatHistory",assigned,this.value.serverChatHistory,pos); break; case "templateUrl": - this.value.templateUrl = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"templateUrl",assigned,this.value.templateUrl,pos); + this.value.templateUrl = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"templateUrl",assigned,this.value.templateUrl,pos); break; case "totalVideoLimit": - this.value.totalVideoLimit = this.loadObjectField(($_=new JsonParser_$54(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"totalVideoLimit",assigned,this.value.totalVideoLimit,pos); + this.value.totalVideoLimit = this.loadObjectField(($_=new JsonParser_$56(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"totalVideoLimit",assigned,this.value.totalVideoLimit,pos); break; case "unpauseWithoutLeader": - this.value.unpauseWithoutLeader = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"unpauseWithoutLeader",assigned,this.value.unpauseWithoutLeader,pos); + this.value.unpauseWithoutLeader = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"unpauseWithoutLeader",assigned,this.value.unpauseWithoutLeader,pos); break; case "userVideoLimit": - this.value.userVideoLimit = this.loadObjectField(($_=new JsonParser_$54(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"userVideoLimit",assigned,this.value.userVideoLimit,pos); + this.value.userVideoLimit = this.loadObjectField(($_=new JsonParser_$56(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"userVideoLimit",assigned,this.value.userVideoLimit,pos); break; case "youtubeApiKey": - this.value.youtubeApiKey = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"youtubeApiKey",assigned,this.value.youtubeApiKey,pos); + this.value.youtubeApiKey = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"youtubeApiKey",assigned,this.value.youtubeApiKey,pos); break; case "youtubePlaylistLimit": - this.value.youtubePlaylistLimit = this.loadObjectField(($_=new JsonParser_$54(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"youtubePlaylistLimit",assigned,this.value.youtubePlaylistLimit,pos); + this.value.youtubePlaylistLimit = this.loadObjectField(($_=new JsonParser_$56(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"youtubePlaylistLimit",assigned,this.value.youtubePlaylistLimit,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -1709,19 +1779,19 @@ JsonParser_$62.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { allowProxyIps : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), cacheStorageLimitGiB : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), channelName : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), emotes : new JsonParser_$67([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), filters : new JsonParser_$68([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isVerbose : new JsonParser_$58([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), localAdmins : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), localNetworkOnly : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), maxLoginLength : new JsonParser_$54([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), maxMessageLength : new JsonParser_$54([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), permissions : new JsonParser_$70([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), port : new JsonParser_$54([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), requestLeaderOnPause : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), salt : new JsonParser_$50([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), serverChatHistory : new JsonParser_$54([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), templateUrl : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), totalVideoLimit : new JsonParser_$54([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), unpauseWithoutLeader : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), userVideoLimit : new JsonParser_$54([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), youtubeApiKey : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), youtubePlaylistLimit : new JsonParser_$54([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { allowProxyIps : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), cacheStorageLimitGiB : new JsonParser_$49([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), channelName : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), emotes : new JsonParser_$70([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), filters : new JsonParser_$71([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isVerbose : new JsonParser_$61([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), localAdmins : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), localNetworkOnly : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), maxLoginLength : new JsonParser_$56([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), maxMessageLength : new JsonParser_$56([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), permissions : new JsonParser_$73([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), port : new JsonParser_$56([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), requestLeaderOnPause : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), salt : new JsonParser_$52([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), serverChatHistory : new JsonParser_$56([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), templateUrl : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), totalVideoLimit : new JsonParser_$56([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), unpauseWithoutLeader : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), userVideoLimit : new JsonParser_$56([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), youtubeApiKey : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), youtubePlaylistLimit : new JsonParser_$56([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } - ,__class__: JsonParser_$62 + ,__class__: JsonParser_$65 }); -var JsonParser_$63 = function(errors,putils,errorType) { +var JsonParser_$66 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$63.__name__ = true; -JsonParser_$63.__super__ = json2object_reader_BaseParser; -JsonParser_$63.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$66.__name__ = true; +JsonParser_$66.__super__ = json2object_reader_BaseParser; +JsonParser_$66.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"Array<Message>",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1730,19 +1800,19 @@ JsonParser_$63.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.value = null; } ,loadJsonArray: function(a,pos,variable) { - this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$66(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); + this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$69(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); } - ,__class__: JsonParser_$63 + ,__class__: JsonParser_$66 }); -var JsonParser_$64 = function(errors,putils,errorType) { +var JsonParser_$67 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$64.__name__ = true; -JsonParser_$64.__super__ = json2object_reader_BaseParser; -JsonParser_$64.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$67.__name__ = true; +JsonParser_$67.__super__ = json2object_reader_BaseParser; +JsonParser_$67.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"Array<PlayerType>",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1751,19 +1821,19 @@ JsonParser_$64.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.value = null; } ,loadJsonArray: function(a,pos,variable) { - this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$48(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); + this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$50(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); } - ,__class__: JsonParser_$64 + ,__class__: JsonParser_$67 }); -var JsonParser_$66 = function(errors,putils,errorType) { +var JsonParser_$69 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$66.__name__ = true; -JsonParser_$66.__super__ = json2object_reader_BaseParser; -JsonParser_$66.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$69.__name__ = true; +JsonParser_$69.__super__ = json2object_reader_BaseParser; +JsonParser_$69.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"{ time : String, text : String, name : String }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1781,13 +1851,13 @@ JsonParser_$66.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "name": - this.value.name = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); + this.value.name = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); break; case "text": - this.value.text = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"text",assigned,this.value.text,pos); + this.value.text = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"text",assigned,this.value.text,pos); break; case "time": - this.value.time = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"time",assigned,this.value.time,pos); + this.value.time = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"time",assigned,this.value.time,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -1796,51 +1866,9 @@ JsonParser_$66.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { name : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), text : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), time : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; - } - ,__class__: JsonParser_$66 -}); -var JsonParser_$67 = function(errors,putils,errorType) { - if(errorType == null) { - errorType = 0; - } - json2object_reader_BaseParser.call(this,errors,putils,errorType); -}; -JsonParser_$67.__name__ = true; -JsonParser_$67.__super__ = json2object_reader_BaseParser; -JsonParser_$67.prototype = $extend(json2object_reader_BaseParser.prototype,{ - onIncorrectType: function(pos,variable) { - this.errors.push(json2object_Error.IncorrectType(variable,"Array<Emote>",pos)); - json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); - } - ,loadJsonNull: function(pos,variable) { - this.value = null; - } - ,loadJsonArray: function(a,pos,variable) { - this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$76(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); - } - ,__class__: JsonParser_$67 -}); -var JsonParser_$68 = function(errors,putils,errorType) { - if(errorType == null) { - errorType = 0; - } - json2object_reader_BaseParser.call(this,errors,putils,errorType); -}; -JsonParser_$68.__name__ = true; -JsonParser_$68.__super__ = json2object_reader_BaseParser; -JsonParser_$68.prototype = $extend(json2object_reader_BaseParser.prototype,{ - onIncorrectType: function(pos,variable) { - this.errors.push(json2object_Error.IncorrectType(variable,"Array<Filter>",pos)); - json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); - } - ,loadJsonNull: function(pos,variable) { - this.value = null; - } - ,loadJsonArray: function(a,pos,variable) { - this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$74(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); + return { name : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), text : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), time : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } - ,__class__: JsonParser_$68 + ,__class__: JsonParser_$69 }); var JsonParser_$7 = function(errors,putils,errorType) { if(errorType == null) { @@ -1868,37 +1896,37 @@ JsonParser_$7.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "clientName": - this.value.clientName = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clientName",assigned,this.value.clientName,pos); + this.value.clientName = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clientName",assigned,this.value.clientName,pos); break; case "clients": - this.value.clients = this.loadObjectField(($_=new JsonParser_$51(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clients",assigned,this.value.clients,pos); + this.value.clients = this.loadObjectField(($_=new JsonParser_$53(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"clients",assigned,this.value.clients,pos); break; case "config": - this.value.config = this.loadObjectField(($_=new JsonParser_$62(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"config",assigned,this.value.config,pos); + this.value.config = this.loadObjectField(($_=new JsonParser_$65(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"config",assigned,this.value.config,pos); break; case "globalIp": - this.value.globalIp = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"globalIp",assigned,this.value.globalIp,pos); + this.value.globalIp = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"globalIp",assigned,this.value.globalIp,pos); break; case "history": - this.value.history = this.loadObjectField(($_=new JsonParser_$63(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"history",assigned,this.value.history,pos); + this.value.history = this.loadObjectField(($_=new JsonParser_$66(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"history",assigned,this.value.history,pos); break; case "isPlaylistOpen": - this.value.isPlaylistOpen = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isPlaylistOpen",assigned,this.value.isPlaylistOpen,pos); + this.value.isPlaylistOpen = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isPlaylistOpen",assigned,this.value.isPlaylistOpen,pos); break; case "isUnknownClient": - this.value.isUnknownClient = this.loadObjectField(($_=new JsonParser_$46(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isUnknownClient",assigned,this.value.isUnknownClient,pos); + this.value.isUnknownClient = this.loadObjectField(($_=new JsonParser_$48(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"isUnknownClient",assigned,this.value.isUnknownClient,pos); break; case "itemPos": - this.value.itemPos = this.loadObjectField(($_=new JsonParser_$54(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"itemPos",assigned,this.value.itemPos,pos); + this.value.itemPos = this.loadObjectField(($_=new JsonParser_$56(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"itemPos",assigned,this.value.itemPos,pos); break; case "playersCacheSupport": - this.value.playersCacheSupport = this.loadObjectField(($_=new JsonParser_$64(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"playersCacheSupport",assigned,this.value.playersCacheSupport,pos); + this.value.playersCacheSupport = this.loadObjectField(($_=new JsonParser_$67(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"playersCacheSupport",assigned,this.value.playersCacheSupport,pos); break; case "uuid": - this.value.uuid = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"uuid",assigned,this.value.uuid,pos); + this.value.uuid = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"uuid",assigned,this.value.uuid,pos); break; case "videoList": - this.value.videoList = this.loadObjectField(($_=new JsonParser_$42(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"videoList",assigned,this.value.videoList,pos); + this.value.videoList = this.loadObjectField(($_=new JsonParser_$44(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"videoList",assigned,this.value.videoList,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -1907,7 +1935,7 @@ JsonParser_$7.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { clientName : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), clients : new JsonParser_$51([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), config : new JsonParser_$62([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), globalIp : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), history : new JsonParser_$63([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isPlaylistOpen : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isUnknownClient : new JsonParser_$46([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), itemPos : new JsonParser_$54([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), playersCacheSupport : new JsonParser_$64([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), uuid : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), videoList : new JsonParser_$42([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { clientName : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), clients : new JsonParser_$53([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), config : new JsonParser_$65([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), globalIp : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), history : new JsonParser_$66([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isPlaylistOpen : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), isUnknownClient : new JsonParser_$48([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), itemPos : new JsonParser_$56([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), playersCacheSupport : new JsonParser_$67([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), uuid : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), videoList : new JsonParser_$44([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$7 }); @@ -1921,6 +1949,48 @@ JsonParser_$70.__name__ = true; JsonParser_$70.__super__ = json2object_reader_BaseParser; JsonParser_$70.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { + this.errors.push(json2object_Error.IncorrectType(variable,"Array<Emote>",pos)); + json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); + } + ,loadJsonNull: function(pos,variable) { + this.value = null; + } + ,loadJsonArray: function(a,pos,variable) { + this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$79(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); + } + ,__class__: JsonParser_$70 +}); +var JsonParser_$71 = function(errors,putils,errorType) { + if(errorType == null) { + errorType = 0; + } + json2object_reader_BaseParser.call(this,errors,putils,errorType); +}; +JsonParser_$71.__name__ = true; +JsonParser_$71.__super__ = json2object_reader_BaseParser; +JsonParser_$71.prototype = $extend(json2object_reader_BaseParser.prototype,{ + onIncorrectType: function(pos,variable) { + this.errors.push(json2object_Error.IncorrectType(variable,"Array<Filter>",pos)); + json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); + } + ,loadJsonNull: function(pos,variable) { + this.value = null; + } + ,loadJsonArray: function(a,pos,variable) { + this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$77(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); + } + ,__class__: JsonParser_$71 +}); +var JsonParser_$73 = function(errors,putils,errorType) { + if(errorType == null) { + errorType = 0; + } + json2object_reader_BaseParser.call(this,errors,putils,errorType); +}; +JsonParser_$73.__name__ = true; +JsonParser_$73.__super__ = json2object_reader_BaseParser; +JsonParser_$73.prototype = $extend(json2object_reader_BaseParser.prototype,{ + onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"{ user : Array<Permission>, leader : Array<Permission>, guest : Array<Permission>, banned : Array<Permission>, admin : Array<Permission> }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); } @@ -1937,19 +2007,19 @@ JsonParser_$70.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "admin": - this.value.admin = this.loadObjectField(($_=new JsonParser_$71(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"admin",assigned,this.value.admin,pos); + this.value.admin = this.loadObjectField(($_=new JsonParser_$74(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"admin",assigned,this.value.admin,pos); break; case "banned": - this.value.banned = this.loadObjectField(($_=new JsonParser_$71(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"banned",assigned,this.value.banned,pos); + this.value.banned = this.loadObjectField(($_=new JsonParser_$74(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"banned",assigned,this.value.banned,pos); break; case "guest": - this.value.guest = this.loadObjectField(($_=new JsonParser_$71(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"guest",assigned,this.value.guest,pos); + this.value.guest = this.loadObjectField(($_=new JsonParser_$74(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"guest",assigned,this.value.guest,pos); break; case "leader": - this.value.leader = this.loadObjectField(($_=new JsonParser_$71(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"leader",assigned,this.value.leader,pos); + this.value.leader = this.loadObjectField(($_=new JsonParser_$74(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"leader",assigned,this.value.leader,pos); break; case "user": - this.value.user = this.loadObjectField(($_=new JsonParser_$71(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"user",assigned,this.value.user,pos); + this.value.user = this.loadObjectField(($_=new JsonParser_$74(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"user",assigned,this.value.user,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -1958,19 +2028,19 @@ JsonParser_$70.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { admin : new JsonParser_$71([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), banned : new JsonParser_$71([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), guest : new JsonParser_$71([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), leader : new JsonParser_$71([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), user : new JsonParser_$71([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { admin : new JsonParser_$74([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), banned : new JsonParser_$74([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), guest : new JsonParser_$74([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), leader : new JsonParser_$74([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), user : new JsonParser_$74([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } - ,__class__: JsonParser_$70 + ,__class__: JsonParser_$73 }); -var JsonParser_$71 = function(errors,putils,errorType) { +var JsonParser_$74 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$71.__name__ = true; -JsonParser_$71.__super__ = json2object_reader_BaseParser; -JsonParser_$71.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$74.__name__ = true; +JsonParser_$74.__super__ = json2object_reader_BaseParser; +JsonParser_$74.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"Array<Permission>",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -1979,19 +2049,19 @@ JsonParser_$71.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.value = null; } ,loadJsonArray: function(a,pos,variable) { - this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$72(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); + this.value = this.loadJsonArrayValue(a,($_=new JsonParser_$75(this.errors,this.putils,2),$bind($_,$_.loadJson)),variable); } - ,__class__: JsonParser_$71 + ,__class__: JsonParser_$74 }); -var JsonParser_$72 = function(errors,putils,errorType) { +var JsonParser_$75 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$72.__name__ = true; -JsonParser_$72.__super__ = json2object_reader_BaseParser; -JsonParser_$72.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$75.__name__ = true; +JsonParser_$75.__super__ = json2object_reader_BaseParser; +JsonParser_$75.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.value = "guest"; this.errors.push(json2object_Error.IncorrectType(variable,"Permission",pos)); @@ -2003,17 +2073,17 @@ JsonParser_$72.prototype = $extend(json2object_reader_BaseParser.prototype,{ ,loadJsonString: function(s,pos,variable) { this.value = this.loadString(s,pos,variable,["guest","user","leader","admin","writeChat","addVideo","removeVideo","requestLeader","rewind","clearChat","setLeader","changeOrder","toggleItemType","lockPlaylist","banClient"],"guest"); } - ,__class__: JsonParser_$72 + ,__class__: JsonParser_$75 }); -var JsonParser_$74 = function(errors,putils,errorType) { +var JsonParser_$77 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$74.__name__ = true; -JsonParser_$74.__super__ = json2object_reader_BaseParser; -JsonParser_$74.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$77.__name__ = true; +JsonParser_$77.__super__ = json2object_reader_BaseParser; +JsonParser_$77.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"{ replace : String, regex : String, name : String, flags : String }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -2031,16 +2101,16 @@ JsonParser_$74.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "flags": - this.value.flags = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"flags",assigned,this.value.flags,pos); + this.value.flags = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"flags",assigned,this.value.flags,pos); break; case "name": - this.value.name = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); + this.value.name = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); break; case "regex": - this.value.regex = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"regex",assigned,this.value.regex,pos); + this.value.regex = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"regex",assigned,this.value.regex,pos); break; case "replace": - this.value.replace = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"replace",assigned,this.value.replace,pos); + this.value.replace = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"replace",assigned,this.value.replace,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -2049,19 +2119,19 @@ JsonParser_$74.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { flags : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), name : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), regex : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), replace : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { flags : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), name : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), regex : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), replace : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } - ,__class__: JsonParser_$74 + ,__class__: JsonParser_$77 }); -var JsonParser_$76 = function(errors,putils,errorType) { +var JsonParser_$79 = function(errors,putils,errorType) { if(errorType == null) { errorType = 0; } json2object_reader_BaseParser.call(this,errors,putils,errorType); }; -JsonParser_$76.__name__ = true; -JsonParser_$76.__super__ = json2object_reader_BaseParser; -JsonParser_$76.prototype = $extend(json2object_reader_BaseParser.prototype,{ +JsonParser_$79.__name__ = true; +JsonParser_$79.__super__ = json2object_reader_BaseParser; +JsonParser_$79.prototype = $extend(json2object_reader_BaseParser.prototype,{ onIncorrectType: function(pos,variable) { this.errors.push(json2object_Error.IncorrectType(variable,"{ name : String, image : String }",pos)); json2object_reader_BaseParser.prototype.onIncorrectType.call(this,pos,variable); @@ -2079,10 +2149,10 @@ JsonParser_$76.prototype = $extend(json2object_reader_BaseParser.prototype,{ ++_g; switch(field.name) { case "image": - this.value.image = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"image",assigned,this.value.image,pos); + this.value.image = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"image",assigned,this.value.image,pos); break; case "name": - this.value.name = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); + this.value.name = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"name",assigned,this.value.name,pos); break; default: this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); @@ -2091,9 +2161,9 @@ JsonParser_$76.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { image : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), name : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { image : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1))), name : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } - ,__class__: JsonParser_$76 + ,__class__: JsonParser_$79 }); var JsonParser_$9 = function(errors,putils,errorType) { if(errorType == null) { @@ -2120,7 +2190,7 @@ JsonParser_$9.prototype = $extend(json2object_reader_BaseParser.prototype,{ var field = o[_g]; ++_g; if(field.name == "data") { - this.value.data = this.loadObjectField(($_=new JsonParser_$45(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"data",assigned,this.value.data,pos); + this.value.data = this.loadObjectField(($_=new JsonParser_$47(this.errors,this.putils,1),$bind($_,$_.loadJson)),field,"data",assigned,this.value.data,pos); } else { this.errors.push(json2object_Error.UnknownVariable(field.name,this.putils.convertPosition(field.namePos))); } @@ -2128,7 +2198,7 @@ JsonParser_$9.prototype = $extend(json2object_reader_BaseParser.prototype,{ this.objectErrors(assigned,pos); } ,getAuto: function() { - return { data : new JsonParser_$45([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; + return { data : new JsonParser_$47([],this.putils,0).loadJson(new hxjsonast_Json(hxjsonast_JsonValue.JNull,new hxjsonast_Position("",0,1)))}; } ,__class__: JsonParser_$9 }); @@ -2808,6 +2878,11 @@ haxe_io_Path.withoutExtension = function(path) { s.ext = null; return s.toString(); }; +haxe_io_Path.withoutDirectory = function(path) { + var s = new haxe_io_Path(path); + s.dir = null; + return s.toString(); +}; haxe_io_Path.extension = function(path) { var s = new haxe_io_Path(path); if(s.ext == null) { @@ -3436,6 +3511,7 @@ var js_node_Https = require("https"); var js_node_Os = require("os"); var js_node_Path = require("path"); var js_node_Readline = require("readline"); +var js_node_buffer_Buffer = require("buffer").Buffer; var js_node_url_URL = require("url").URL; var js_npm_ws_Server = require("ws").Server; var json2object_Error = $hxEnums["json2object.Error"] = { __ename__:true,__constructs__:null @@ -3601,6 +3677,7 @@ json2object_PositionUtils.prototype = { ,__class__: json2object_PositionUtils }; var server_Cache = function(main,cacheDir) { + this.freeSpaceBlock = 10485760; this.storageLimit = 3145728 * 1024; this.isYtReady = false; this.cachedFiles = []; @@ -3627,12 +3704,12 @@ server_Cache.prototype = { } ,log: function(client,msg) { this.main.serverMessage(client,msg); - haxe_Log.trace(msg,{ fileName : "src/server/Cache.hx", lineNumber : 44, className : "server.Cache", methodName : "log"}); + haxe_Log.trace(msg,{ fileName : "src/server/Cache.hx", lineNumber : 46, className : "server.Cache", methodName : "log"}); } ,cacheYoutubeVideo: function(client,url,callback) { var _gthis = this; if(!this.isYtReady) { - haxe_Log.trace("Do `npm i @distube/ytdl-core@latest` to use cache feature (you also need to install `ffmpeg` to build mp4 from downloaded audio/video tracks).",{ fileName : "src/server/Cache.hx", lineNumber : 49, className : "server.Cache", methodName : "cacheYoutubeVideo"}); + haxe_Log.trace("Do `npm i @distube/ytdl-core@latest` to use cache feature (you also need to install `ffmpeg` to build mp4 from downloaded audio/video tracks).",{ fileName : "src/server/Cache.hx", lineNumber : 51, className : "server.Cache", methodName : "cacheYoutubeVideo"}); return; } var videoId = utils_YoutubeUtils.extractVideoId(url); @@ -3641,15 +3718,16 @@ server_Cache.prototype = { return; } var outName = videoId + ".mp4"; - if(this.cachedFiles.indexOf(outName) != -1 && sys_FileSystem.exists("" + this.cacheDir + "/" + outName)) { + if(this.cachedFiles.indexOf(outName) != -1 && this.isFileExists(outName)) { callback(outName); return; } var ytdl = require("@distube/ytdl-core"); - this.log(client,"Caching " + url + " to " + outName + "..."); + haxe_Log.trace("Caching " + url + " to " + outName + "...",{ fileName : "src/server/Cache.hx", lineNumber : 65, className : "server.Cache", methodName : "cacheYoutubeVideo"}); + this.main.send(client,{ type : "Progress", progress : { type : "Caching", ratio : 0, data : outName}}); var promise = ytdl.getInfo(url); promise.then(function(info) { - haxe_Log.trace("Get info with " + info.formats.length + " formats",{ fileName : "src/server/Cache.hx", lineNumber : 68, className : "server.Cache", methodName : "cacheYoutubeVideo"}); + haxe_Log.trace("Get info with " + info.formats.length + " formats",{ fileName : "src/server/Cache.hx", lineNumber : 76, className : "server.Cache", methodName : "cacheYoutubeVideo"}); var audioFormat; try { var ytdl1 = ytdl.chooseFormat; @@ -3668,8 +3746,18 @@ server_Cache.prototype = { } catch( _g ) { var e = haxe_Exception.caught(_g); _gthis.log(client,"Error: audio format not found"); - haxe_Log.trace(e,{ fileName : "src/server/Cache.hx", lineNumber : 75, className : "server.Cache", methodName : "cacheYoutubeVideo"}); - haxe_Log.trace(info.formats,{ fileName : "src/server/Cache.hx", lineNumber : 76, className : "server.Cache", methodName : "cacheYoutubeVideo"}); + haxe_Log.trace(e,{ fileName : "src/server/Cache.hx", lineNumber : 83, className : "server.Cache", methodName : "cacheYoutubeVideo"}); + var _g1 = []; + var _g2 = 0; + var _g3 = info.formats; + while(_g2 < _g3.length) { + var v = _g3[_g2]; + ++_g2; + if(v.hasAudio) { + _g1.push(v); + } + } + haxe_Log.trace(_g1,{ fileName : "src/server/Cache.hx", lineNumber : 84, className : "server.Cache", methodName : "cacheYoutubeVideo"}); return; } var videoFormat; @@ -3678,10 +3766,19 @@ server_Cache.prototype = { videoFormat = tmp; } else { _gthis.log(client,"Error: video format not found"); - haxe_Log.trace(info.formats,{ fileName : "src/server/Cache.hx", lineNumber : 81, className : "server.Cache", methodName : "cacheYoutubeVideo"}); + var _g = []; + var _g1 = 0; + var _g2 = info.formats; + while(_g1 < _g2.length) { + var v = _g2[_g1]; + ++_g1; + if(v.hasVideo) { + _g.push(v); + } + } + haxe_Log.trace(_g,{ fileName : "src/server/Cache.hx", lineNumber : 89, className : "server.Cache", methodName : "cacheYoutubeVideo"}); return; } - haxe_Log.trace("Picked audio and video formats",{ fileName : "src/server/Cache.hx", lineNumber : 84, className : "server.Cache", methodName : "cacheYoutubeVideo"}); var dlVideo = ytdl(url,{ format : videoFormat}); dlVideo.pipe(js_node_Fs.createWriteStream("" + _gthis.cacheDir + "/input-video")); dlVideo.on("error",function(err) { @@ -3695,10 +3792,13 @@ server_Cache.prototype = { var count = 0; var onComplete = function(type) { count += 1; - _gthis.log(client,"" + type + " track downloaded (" + count + "/2)"); + haxe_Log.trace("" + type + " track downloaded (" + count + "/2)",{ fileName : "src/server/Cache.hx", lineNumber : 108, className : "server.Cache", methodName : "cacheYoutubeVideo"}); if(count < 2) { return; } + var size = js_node_Fs.statSync("" + _gthis.cacheDir + "/input-video").size; + size += js_node_Fs.statSync("" + _gthis.cacheDir + "/input-audio").size; + _gthis.removeOlderCache(size + _gthis.freeSpaceBlock); var args = ("-y -i input-video -i input-audio -c copy -map 0:v -map 1:a ./" + outName).split(" "); var $process = js_node_ChildProcess.spawn("ffmpeg",args,{ cwd : _gthis.cacheDir, stdio : "ignore"}); $process.on("close",function(code) { @@ -3708,16 +3808,9 @@ server_Cache.prototype = { } var inVideo = "" + _gthis.cacheDir + "/input-video"; var inAudio = "" + _gthis.cacheDir + "/input-audio"; - if(sys_FileSystem.exists(inVideo)) { - js_node_Fs.unlinkSync(inVideo); - } - if(sys_FileSystem.exists(inAudio)) { - js_node_Fs.unlinkSync(inAudio); - } - if(_gthis.cachedFiles.indexOf(outName) == -1) { - _gthis.cachedFiles.unshift(outName); - } - _gthis.removeOlderCache(); + js_node_Fs.unlinkSync(inVideo); + js_node_Fs.unlinkSync(inAudio); + _gthis.add(outName); callback(outName); }); }; @@ -3727,26 +3820,109 @@ server_Cache.prototype = { dlAudio.on("finish",function() { onComplete("Audio"); }); + var isAudioStart = true; + dlAudio.on("progress",function(chunkLength,downloaded,contentLength) { + if(isAudioStart) { + isAudioStart = false; + _gthis.removeOlderCache(contentLength); + } + }); + var isVideoStart = true; + dlVideo.on("progress",function(chunkLength,downloaded,contentLength) { + if(isVideoStart) { + isVideoStart = false; + _gthis.removeOlderCache(contentLength); + } + var v = downloaded / contentLength; + var ratio = v < 0 ? 0 : v > 1 ? 1 : v; + _gthis.main.send(client,{ type : "Progress", progress : { type : "Downloading", ratio : ratio}}); + }); }).catch(function(err) { _gthis.log(client,"" + err); }); } - ,removeOlderCache: function() { - while(this.getUsedSpace() > this.storageLimit) { - var name = this.cachedFiles.pop(); - var path = "" + this.cacheDir + "/" + name; + ,setStorageLimit: function(bytes) { + var _gthis = this; + this.storageLimit = bytes; + var a = this.storageLimit; + this.storageLimit = a < 0 ? 0 : a; + var tmp = js_node_Fs.statfs; + if(tmp == null) { + return; + } + tmp("/",function(err,stats) { + if(err != null) { + haxe_Log.trace(err,{ fileName : "src/server/Cache.hx", lineNumber : 173, className : "server.Cache", methodName : "setStorageLimit"}); + return; + } + var a = stats.bsize * stats.bavail - _gthis.freeSpaceBlock; + var availSpace = a < 0 ? 0 : a; + _gthis.removeOlderCache(); + var freeSpace = _gthis.getFreeSpace(); + if(availSpace < freeSpace) { + var a = _gthis.storageLimit += availSpace - freeSpace; + _gthis.storageLimit = a < 0 ? 0 : a; + _gthis.removeOlderCache(); + } + }); + } + ,add: function(name) { + if(this.cachedFiles.indexOf(name) == -1) { + this.cachedFiles.unshift(name); + } + } + ,removeOlderCache: function(addFileSize) { + if(addFileSize == null) { + addFileSize = 0; + } + var space = this.getUsedSpace(addFileSize); + while(space > this.storageLimit) { + var tmp = this.cachedFiles.pop(); + if(tmp == null) { + break; + } + var path = this.getFilePath(tmp); if(sys_FileSystem.exists(path)) { js_node_Fs.unlinkSync(path); } + space = this.getUsedSpace(addFileSize); + } + } + ,getFreeFileName: function(baseName) { + if(baseName == null) { + baseName = "video"; + } + var i = 1; + while(true) { + var name = "" + baseName + (i == 1 ? "" : "" + i) + ".mp4"; + if(!this.isFileExists(name)) { + return name; + } + ++i; } } - ,getUsedSpace: function() { - var total = 0; + ,getFilePath: function(name) { + return "" + this.cacheDir + "/" + name; + } + ,getFileUrl: function(name) { + return "/" + haxe_io_Path.withoutDirectory(this.cacheDir) + "/" + name; + } + ,isFileExists: function(name) { + return sys_FileSystem.exists(this.getFilePath(name)); + } + ,getFreeSpace: function() { + return this.storageLimit - this.getUsedSpace(); + } + ,getUsedSpace: function(addFileSize) { + if(addFileSize == null) { + addFileSize = 0; + } + var total = addFileSize < 0 ? 0 : addFileSize; var arr = this.cachedFiles; var _g_i = arr.length - 1; while(_g_i > -1) { var name = arr[_g_i--]; - var path = "" + this.cacheDir + "/" + name; + var path = this.getFilePath(name); if(!sys_FileSystem.exists(path)) { HxOverrides.remove(this.cachedFiles,name); continue; @@ -3756,7 +3932,7 @@ server_Cache.prototype = { return total; } ,getBestYoutubeVideoFormat: function(formats) { - var qPriority = [1080,720,480,360,240]; + var qPriority = [1080,720,480,360,240,144]; var _g = 0; while(_g < qPriority.length) { var quality = "" + qPriority[_g++] + "p"; @@ -3931,233 +4107,391 @@ server_ConsoleInput.prototype = { } ,__class__: server_ConsoleInput }; -var server_HttpServer = function() { }; -server_HttpServer.__name__ = true; -server_HttpServer.init = function(dir,customDir,allowLocalRequests) { - server_HttpServer.dir = dir; - if(customDir == null) { - return; +var server__$HttpServer_HttpServerConfig = function(dir,customDir,allowLocalRequests,cache) { + this.cache = null; + this.allowLocalRequests = false; + this.customDir = null; + this.dir = dir; + if(customDir != null) { + this.customDir = customDir; + } + if(allowLocalRequests != null) { + this.allowLocalRequests = allowLocalRequests; + } + if(cache != null) { + this.cache = cache; } - server_HttpServer.customDir = customDir; - server_HttpServer.hasCustomRes = sys_FileSystem.exists(customDir); - server_HttpServer.allowLocalRequests = allowLocalRequests; }; -server_HttpServer.serveFiles = function(req,res) { - var url; - try { - url = new js_node_url_URL(server_HttpServer.safeDecodeURI(req.url),"http://localhost"); - } catch( _g ) { - url = new js_node_url_URL("/","http://localhost"); +server__$HttpServer_HttpServerConfig.__name__ = true; +server__$HttpServer_HttpServerConfig.prototype = { + __class__: server__$HttpServer_HttpServerConfig +}; +var server_HttpServer = function(main,config) { + this.ctrlCharacters = new EReg("[\\u0000-\\u001F\\u007F-\\u009F\\u2000-\\u200D\\uFEFF]","g"); + this.matchVarString = new EReg("\\${([A-z_]+)}","g"); + this.matchLang = new EReg("^[A-z]+",""); + this.uploadingFilesLastChunks = new haxe_ds_StringMap(); + this.uploadingFiles = new haxe_ds_StringMap(); + this.CHUNK_SIZE = 5242880; + this.cache = null; + this.allowLocalRequests = false; + this.allowedLocalFiles = new haxe_ds_StringMap(); + this.hasCustomRes = false; + this.main = main; + this.dir = config.dir; + this.customDir = config.customDir; + this.allowLocalRequests = config.allowLocalRequests; + this.cache = config.cache; + if(this.customDir != null) { + this.hasCustomRes = sys_FileSystem.exists(this.customDir); } - var filePath = server_HttpServer.getPath(server_HttpServer.dir,url); - var ext = haxe_io_Path.extension(filePath).toLowerCase(); - res.setHeader("Accept-Ranges","bytes"); - res.setHeader("Content-Type",server_HttpServer.getMimeType(ext)); - if(server_HttpServer.allowLocalRequests && req.socket.remoteAddress == req.socket.localAddress || server_HttpServer.allowedLocalFiles.h[url.pathname]) { - if(server_HttpServer.isMediaExtension(ext)) { - server_HttpServer.allowedLocalFiles.h[url.pathname] = true; - var s = url.pathname; - if(server_HttpServer.serveMedia(req,res,decodeURIComponent(s.split("+").join(" ")))) { - return; +}; +server_HttpServer.__name__ = true; +server_HttpServer.prototype = { + serveFiles: function(req,res) { + var _gthis = this; + var url; + try { + url = new js_node_url_URL(this.safeDecodeURI(req.url),"http://localhost"); + } catch( _g ) { + url = new js_node_url_URL("/","http://localhost"); + } + var filePath = this.getPath(this.dir,url); + var ext = haxe_io_Path.extension(filePath).toLowerCase(); + res.setHeader("Accept-Ranges","bytes"); + res.setHeader("Content-Type",this.getMimeType(ext)); + if(this.cache != null && req.method == "POST") { + switch(url.pathname) { + case "/upload": + this.uploadFile(req,res); + break; + case "/upload-last-chunk": + this.uploadFileLastChunk(req,res); + break; } + return; } - } - if(!server_HttpServer.isChildOf(server_HttpServer.dir,filePath)) { - res.statusCode = 500; - var rel = js_node_Path.relative(server_HttpServer.dir,filePath); - res.end("Error getting the file: No access to " + rel + "."); - return; - } - if(url.pathname == "/proxy") { - if(!server_HttpServer.proxyUrl(req,res)) { - res.end("Proxy error: " + req.url); + if(this.allowLocalRequests && req.socket.remoteAddress == req.socket.localAddress || this.allowedLocalFiles.h[url.pathname]) { + if(this.isMediaExtension(ext)) { + this.allowedLocalFiles.h[url.pathname] = true; + var s = url.pathname; + if(this.serveMedia(req,res,decodeURIComponent(s.split("+").join(" ")))) { + return; + } + } } - return; - } - if(server_HttpServer.hasCustomRes) { - var path = server_HttpServer.getPath(server_HttpServer.customDir,url); - if(js_node_Fs.existsSync(path)) { - filePath = path; + if(!this.isChildOf(this.dir,filePath)) { + res.statusCode = 500; + var rel = js_node_Path.relative(this.dir,filePath); + res.end("Error getting the file: No access to " + rel + "."); + return; } - } - if(server_HttpServer.isMediaExtension(ext)) { - if(server_HttpServer.serveMedia(req,res,filePath)) { + if(url.pathname == "/proxy") { + if(!this.proxyUrl(req,res)) { + res.end("Proxy error: " + req.url); + } return; } + if(this.hasCustomRes) { + var path = this.getPath(this.customDir,url); + if(js_node_Fs.existsSync(path)) { + filePath = path; + } + } + if(this.isMediaExtension(ext)) { + if(this.serveMedia(req,res,filePath)) { + return; + } + } + js_node_Fs.readFile(filePath,function(err,data) { + if(err != null) { + _gthis.readFileError(err,res,filePath); + return; + } + if(ext == "html") { + data = _gthis.localizeHtml(data.toString(),req.headers["accept-language"]); + } + res.end(data); + }); + } + ,uploadFileLastChunk: function(req,res) { + var _gthis = this; + var name = this.cache.getFreeFileName(req.headers["content-name"]); + var filePath = this.cache.getFilePath(name); + var body = []; + req.on("data",function(chunk) { + return body.push(chunk); + }); + req.on("end",function() { + var buffer = js_node_buffer_Buffer.concat(body); + _gthis.uploadingFilesLastChunks.h[filePath] = buffer; + res.writeHead(200,{ "Content-Type" : "application/json"}); + res.end(JSON.stringify({ info : "File last chunk uploaded"})); + }); } - js_node_Fs.readFile(filePath,function(err,data) { - if(err != null) { - server_HttpServer.readFileError(err,res,filePath); + ,uploadFile: function(req,res) { + var _gthis = this; + var name = this.cache.getFreeFileName(req.headers["content-name"]); + var clientName = req.headers["client-name"]; + var filePath = this.cache.getFilePath(name); + var size; + var tmp = Std.parseInt(req.headers["content-length"]); + if(tmp != null) { + size = tmp; + } else { return; } - if(ext == "html") { - data = server_HttpServer.localizeHtml(data.toString(),req.headers["accept-language"]); + var written = 0; + if(this.cache.getFreeSpace() < size) { + var _this = _gthis.uploadingFiles; + if(Object.prototype.hasOwnProperty.call(_this.h,name)) { + delete(_this.h[name]); + } + var _this = _gthis.uploadingFilesLastChunks; + if(Object.prototype.hasOwnProperty.call(_this.h,name)) { + delete(_this.h[name]); + } + res.statusCode = 200; + res.end(JSON.stringify({ info : "Error: Not enough free space on server or file size is out of cache storage limit.", errorId : "freeSpace"})); + return; } - res.end(data); - }); -}; -server_HttpServer.getPath = function(dir,url) { - var filePath = dir + url.pathname; - filePath = decodeURIComponent(filePath.split("+").join(" ")); - if(!sys_FileSystem.isDirectory(filePath)) { - return filePath; + var stream = js_node_Fs.createWriteStream(filePath); + req.pipe(stream); + var isStart = true; + req.on("data",function(chunk) { + var url = null; + if(isStart) { + isStart = false; + _gthis.cache.removeOlderCache(size); + _gthis.cache.add(name); + _gthis.uploadingFiles.h[filePath] = size; + url = _gthis.cache.getFileUrl(name); + } + written += chunk.length; + var v = written / size; + var ratio = v < 0 ? 0 : v > 1 ? 1 : v; + tools_MathTools.toFixed(ratio * 100,2); + var tmp = ClientTools.getByName(_gthis.main.clients,clientName); + if(tmp == null) { + return; + } + _gthis.main.send(tmp,{ type : "Progress", progress : { type : "Uploading", ratio : ratio, data : url}}); + }); + stream.on("close",function() { + var _this = _gthis.uploadingFiles; + if(Object.prototype.hasOwnProperty.call(_this.h,name)) { + delete(_this.h[name]); + } + var _this = _gthis.uploadingFilesLastChunks; + if(Object.prototype.hasOwnProperty.call(_this.h,name)) { + delete(_this.h[name]); + } + res.statusCode = 200; + res.end(JSON.stringify({ info : "File write stream closed."})); + }); + stream.on("error",function(err) { + haxe_Log.trace(err,{ fileName : "src/server/HttpServer.hx", lineNumber : 210, className : "server.HttpServer", methodName : "uploadFile"}); + var _this = _gthis.uploadingFiles; + if(Object.prototype.hasOwnProperty.call(_this.h,name)) { + delete(_this.h[name]); + } + var _this = _gthis.uploadingFilesLastChunks; + if(Object.prototype.hasOwnProperty.call(_this.h,name)) { + delete(_this.h[name]); + } + res.statusCode = 200; + res.end(JSON.stringify({ info : "File write stream error."})); + }); + req.on("error",function(err) { + haxe_Log.trace("Request Error:",{ fileName : "src/server/HttpServer.hx", lineNumber : 216, className : "server.HttpServer", methodName : "uploadFile", customParams : [err]}); + stream.destroy(); + var _this = _gthis.uploadingFiles; + if(Object.prototype.hasOwnProperty.call(_this.h,name)) { + delete(_this.h[name]); + } + var _this = _gthis.uploadingFilesLastChunks; + if(Object.prototype.hasOwnProperty.call(_this.h,name)) { + delete(_this.h[name]); + } + res.statusCode = 200; + res.end(JSON.stringify({ info : "File request error."})); + }); } - return haxe_io_Path.addTrailingSlash(filePath) + "index.html"; -}; -server_HttpServer.readFileError = function(err,res,filePath) { - res.setHeader("Content-Type",server_HttpServer.getMimeType("html")); - if(err.code == "ENOENT") { - res.statusCode = 404; - var rel = js_node_Path.relative(server_HttpServer.dir,filePath); - res.end("File " + rel + " not found."); - } else { - res.statusCode = 500; - res.end("Error getting the file: " + Std.string(err) + "."); + ,getPath: function(dir,url) { + var filePath = dir + url.pathname; + filePath = decodeURIComponent(filePath.split("+").join(" ")); + if(!sys_FileSystem.isDirectory(filePath)) { + return filePath; + } + return haxe_io_Path.addTrailingSlash(filePath) + "index.html"; } -}; -server_HttpServer.serveMedia = function(req,res,filePath) { - if(!js_node_Fs.existsSync(filePath)) { - return false; + ,readFileError: function(err,res,filePath) { + res.setHeader("Content-Type",this.getMimeType("html")); + if(err.code == "ENOENT") { + res.statusCode = 404; + var rel = js_node_Path.relative(this.dir,filePath); + res.end("File " + rel + " not found."); + } else { + res.statusCode = 500; + res.end("Error getting the file: " + Std.string(err) + "."); + } } - var videoSize = js_node_Fs.statSync(filePath).size; - var rangeHeader = req.headers["range"]; - if(rangeHeader == null) { - res.statusCode = 200; - res.setHeader("Content-Length","" + videoSize); - var videoStream = js_node_Fs.createReadStream(filePath); - videoStream.pipe(res); + ,serveMedia: function(req,res,filePath) { + if(!js_node_Fs.existsSync(filePath)) { + return false; + } + var videoSize = js_node_Fs.statSync(filePath).size; + if(Object.prototype.hasOwnProperty.call(this.uploadingFiles.h,filePath)) { + videoSize = this.uploadingFiles.h[filePath]; + } + var rangeHeader = req.headers["range"]; + if(rangeHeader == null) { + res.statusCode = 200; + res.setHeader("Content-Length","" + videoSize); + var videoStream = js_node_Fs.createReadStream(filePath); + videoStream.pipe(res); + res.on("error",function() { + return videoStream.destroy(); + }); + res.on("close",function() { + return videoStream.destroy(); + }); + return true; + } + var range = this.parseRangeHeader(rangeHeader,videoSize); + var start = range.start; + var end = range.end; + var contentLength = end - start + 1; + res.setHeader("Content-Range","bytes " + start + "-" + end + "/" + videoSize); + res.setHeader("Content-Length","" + contentLength); + res.statusCode = 206; + var buffer = this.uploadingFilesLastChunks.h[filePath]; + if(buffer != null && end == videoSize - 1 && contentLength < buffer.byteLength) { + var a = buffer.byteLength - contentLength; + res.end(buffer.slice(a < 0 ? 0 : a)); + return true; + } + var videoStream1 = js_node_Fs.createReadStream(filePath,{ start : start, end : end}); + videoStream1.pipe(res); res.on("error",function() { - return videoStream.destroy(); + return videoStream1.destroy(); }); res.on("close",function() { - return videoStream.destroy(); + return videoStream1.destroy(); }); return true; } - var range = server_HttpServer.parseRangeHeader(rangeHeader,videoSize); - var start = range.start; - var end = range.end; - res.setHeader("Content-Range","bytes " + start + "-" + end + "/" + videoSize); - res.setHeader("Content-Length","" + (end - start + 1)); - res.statusCode = 206; - var videoStream1 = js_node_Fs.createReadStream(filePath,{ start : start, end : end}); - videoStream1.pipe(res); - res.on("error",function() { - return videoStream1.destroy(); - }); - res.on("close",function() { - return videoStream1.destroy(); - }); - return true; -}; -server_HttpServer.parseRangeHeader = function(rangeHeader,videoSize) { - var ranges = new EReg("[-=]","g").split(rangeHeader); - var start = parseFloat(ranges[1]); - if(server_Utils.isOutOfRange(start,0,videoSize - 1)) { - start = 0; - } - var end = parseFloat(ranges[2]); - if(isNaN(end)) { - end = start + server_HttpServer.CHUNK_SIZE; - } - if(server_Utils.isOutOfRange(end,start,videoSize - 1)) { - end = videoSize - 1; - } - return { start : start, end : end}; -}; -server_HttpServer.isMediaExtension = function(ext) { - if(!(ext == "mp4" || ext == "webm" || ext == "mp3")) { - return ext == "wav"; - } else { - return true; + ,parseRangeHeader: function(rangeHeader,videoSize) { + var ranges = new EReg("[-=]","g").split(rangeHeader); + var start = Std.parseInt(ranges[1]); + if(server_Utils.isOutOfRange(start,0,videoSize - 1)) { + start = 0; + } + var end = Std.parseInt(ranges[2]); + if(end == null) { + end = start + this.CHUNK_SIZE; + } + if(server_Utils.isOutOfRange(end,start,videoSize - 1)) { + end = videoSize - 1; + } + return { start : start, end : end}; } -}; -server_HttpServer.localizeHtml = function(data,lang) { - if(lang != null && server_HttpServer.matchLang.match(lang)) { - lang = server_HttpServer.matchLang.matched(0); - } else { - lang = "en"; + ,isMediaExtension: function(ext) { + if(!(ext == "mp4" || ext == "webm" || ext == "mp3")) { + return ext == "wav"; + } else { + return true; + } } - data = server_HttpServer.matchVarString.map(data,function(regExp) { - var key = regExp.matched(1); - return Lang.get(lang,key); - }); - return data; -}; -server_HttpServer.proxyUrl = function(req,res) { - var url = StringTools.replace(req.url,"/proxy?url=",""); - var proxy = server_HttpServer.proxyRequest(url,req,res,function(proxyRes) { - var tmp = proxyRes.headers["location"]; - if(tmp == null) { - return false; + ,localizeHtml: function(data,lang) { + if(lang != null && this.matchLang.match(lang)) { + lang = this.matchLang.matched(0); + } else { + lang = "en"; } - var proxy2 = server_HttpServer.proxyRequest(tmp,req,res,function(proxyRes) { - return false; + data = this.matchVarString.map(data,function(regExp) { + var key = regExp.matched(1); + return Lang.get(lang,key); }); - if(proxy2 == null) { - res.end("Proxy error: multiple redirects for url " + tmp); + return data; + } + ,proxyUrl: function(req,res) { + var _gthis = this; + var url = StringTools.replace(req.url,"/proxy?url=",""); + var proxy = this.proxyRequest(url,req,res,function(proxyRes) { + var tmp = proxyRes.headers["location"]; + if(tmp == null) { + return false; + } + var proxy2 = _gthis.proxyRequest(tmp,req,res,function(proxyRes) { + return false; + }); + if(proxy2 == null) { + res.end("Proxy error: multiple redirects for url " + tmp); + return true; + } + req.pipe(proxy2); return true; + }); + if(proxy == null) { + return false; } - req.pipe(proxy2); + req.pipe(proxy); return true; - }); - if(proxy == null) { - return false; - } - req.pipe(proxy); - return true; -}; -server_HttpServer.proxyRequest = function(url,req,res,cancelProxyRequest) { - var url1; - try { - url1 = new js_node_url_URL(server_HttpServer.safeDecodeURI(url)); - } catch( _g ) { - return null; } - if(url1.host == req.headers["host"]) { - return null; + ,proxyRequest: function(url,req,res,cancelProxyRequest) { + var url1; + try { + url1 = new js_node_url_URL(this.safeDecodeURI(url)); + } catch( _g ) { + return null; + } + if(url1.host == req.headers["host"]) { + return null; + } + var options = { host : url1.hostname, port : Std.parseInt(url1.port), path : url1.pathname + url1.search, method : req.method}; + req.headers["referer"] = url1.toString(); + req.headers["host"] = url1.hostname; + var request = url1.protocol == "https:" ? js_node_Https.request : js_node_Http.request; + var proxy = request(options,function(proxyRes) { + if(cancelProxyRequest(proxyRes)) { + return; + } + proxyRes.headers["content-type"] = "application/octet-stream"; + res.writeHead(proxyRes.statusCode,proxyRes.headers); + proxyRes.pipe(res); + }); + proxy.on("error",function(err) { + res.end("Proxy error: " + url1.href); + }); + return proxy; } - var options = { host : url1.hostname, port : Std.parseInt(url1.port), path : url1.pathname + url1.search, method : req.method}; - req.headers["referer"] = url1.toString(); - req.headers["host"] = url1.hostname; - var request = url1.protocol == "https:" ? js_node_Https.request : js_node_Http.request; - var proxy = request(options,function(proxyRes) { - if(cancelProxyRequest(proxyRes)) { - return; + ,isChildOf: function(parent,child) { + var rel = js_node_Path.relative(parent,child); + if(rel.length > 0 && !StringTools.startsWith(rel,"..")) { + return !js_node_Path.isAbsolute(rel); + } else { + return false; } - proxyRes.headers["Content-Type"] = "application/octet-stream"; - res.writeHead(proxyRes.statusCode,proxyRes.headers); - proxyRes.pipe(res); - }); - proxy.on("error",function(err) { - res.end("Proxy error: " + url1.href); - }); - return proxy; -}; -server_HttpServer.isChildOf = function(parent,child) { - var rel = js_node_Path.relative(parent,child); - if(rel.length > 0 && !StringTools.startsWith(rel,"..")) { - return !js_node_Path.isAbsolute(rel); - } else { - return false; } -}; -server_HttpServer.getMimeType = function(ext) { - var tmp = server_HttpServer.mimeTypes.h[ext]; - if(tmp != null) { - return tmp; - } else { - return "application/octet-stream"; + ,getMimeType: function(ext) { + var tmp = server_HttpServer.mimeTypes.h[ext]; + if(tmp != null) { + return tmp; + } else { + return "application/octet-stream"; + } } -}; -server_HttpServer.safeDecodeURI = function(data) { - try { - data = decodeURI(data); - } catch( _g ) { - data = ""; + ,safeDecodeURI: function(data) { + try { + data = decodeURI(data); + } catch( _g ) { + data = ""; + } + data = data.replace(this.ctrlCharacters.r,""); + return data; } - data = data.replace(server_HttpServer.ctrlCharacters.r,""); - return data; + ,__class__: server_HttpServer }; var server_Logger = function(folder,maxCount,verbose) { this.matchFileFormat = new EReg("[0-9_-]+\\.json$",""); @@ -4272,6 +4606,7 @@ var server_Main = function(opts) { this.verbose = Object.prototype.hasOwnProperty.call(args.h,"verbose"); this.statePath = "" + this.rootDir + "/user/state.json"; this.logsDir = "" + this.rootDir + "/user/logs"; + this.cacheDir = "" + this.rootDir + "/user/res/cache"; process.on("SIGINT",$bind(this,this.exit)); process.on("SIGUSR1",$bind(this,this.exit)); process.on("SIGUSR2",$bind(this,this.exit)); @@ -4287,14 +4622,14 @@ var server_Main = function(opts) { this.logger = new server_Logger(this.logsDir,10,this.verbose); this.consoleInput = new server_ConsoleInput(this); this.consoleInput.initConsoleInput(); - this.cache = new server_Cache(this,"" + this.rootDir + "/user/res/cache"); + this.cache = new server_Cache(this,this.cacheDir); if(this.cache.isYtReady) { this.playersCacheSupport.push("YoutubeType"); } this.initIntergationHandlers(); this.loadState(); this.config = this.loadUserConfig(); - this.cache.storageLimit = this.config.cacheStorageLimitGiB * 1024 * 1024 * 1024; + this.cache.setStorageLimit(this.config.cacheStorageLimitGiB * 1024 * 1024 * 1024); this.userList = this.loadUsers(); this.config.isVerbose = this.verbose; this.config.salt = this.generateConfigSalt(); @@ -4321,7 +4656,7 @@ var server_Main = function(opts) { preparePort = function() { server_Utils.isPortFree(_gthis.port,function(isFree) { if(!isFree && attempts > 0) { - haxe_Log.trace("Warning: port " + _gthis.port + " is already in use. Changed to " + (_gthis.port + 1),{ fileName : "src/server/Main.hx", lineNumber : 131, className : "server.Main", methodName : "new"}); + haxe_Log.trace("Warning: port " + _gthis.port + " is already in use. Changed to " + (_gthis.port + 1),{ fileName : "src/server/Main.hx", lineNumber : 135, className : "server.Main", methodName : "new"}); attempts -= 1; _gthis.port++; preparePort(); @@ -4339,23 +4674,23 @@ server_Main.main = function() { server_Main.prototype = { runServer: function() { var _gthis = this; - haxe_Log.trace("Local: http://" + this.localIp + ":" + this.port,{ fileName : "src/server/Main.hx", lineNumber : 144, className : "server.Main", methodName : "runServer"}); + haxe_Log.trace("Local: http://" + this.localIp + ":" + this.port,{ fileName : "src/server/Main.hx", lineNumber : 148, className : "server.Main", methodName : "runServer"}); if(this.config.localNetworkOnly) { - haxe_Log.trace("Global network is disabled in config",{ fileName : "src/server/Main.hx", lineNumber : 146, className : "server.Main", methodName : "runServer"}); + haxe_Log.trace("Global network is disabled in config",{ fileName : "src/server/Main.hx", lineNumber : 150, className : "server.Main", methodName : "runServer"}); } else if(!this.isNoState) { server_Utils.getGlobalIp(function(ip) { if(ip.indexOf(":") != -1) { ip = "[" + ip + "]"; } _gthis.globalIp = ip; - haxe_Log.trace("Global: http://" + _gthis.globalIp + ":" + _gthis.port,{ fileName : "src/server/Main.hx", lineNumber : 152, className : "server.Main", methodName : "runServer"}); + haxe_Log.trace("Global: http://" + _gthis.globalIp + ":" + _gthis.port,{ fileName : "src/server/Main.hx", lineNumber : 156, className : "server.Main", methodName : "runServer"}); }); } var dir = "" + this.rootDir + "/res"; - server_HttpServer.init(dir,"" + this.rootDir + "/user/res",this.config.localAdmins); + var httpServer = new server_HttpServer(this,new server__$HttpServer_HttpServerConfig(dir,"" + this.rootDir + "/user/res",this.config.localAdmins,this.cache)); Lang.init("" + dir + "/langs"); var server = js_node_Http.createServer(function(req,res) { - server_HttpServer.serveFiles(req,res); + httpServer.serveFiles(req,res); }); this.wss = new js_npm_ws_Server({ server : server}); this.wss.on("connection",$bind(this,this.onConnect)); @@ -4433,7 +4768,7 @@ server_Main.prototype = { var field = _g1[_g]; ++_g; if(Reflect.field(config,field) == null) { - haxe_Log.trace("Warning: config field \"" + field + "\" is unknown",{ fileName : "src/server/Main.hx", lineNumber : 221, className : "server.Main", methodName : "getUserConfig"}); + haxe_Log.trace("Warning: config field \"" + field + "\" is unknown",{ fileName : "src/server/Main.hx", lineNumber : 230, className : "server.Main", methodName : "getUserConfig"}); } config[field] = Reflect.field(customConfig,field); } @@ -4444,14 +4779,14 @@ server_Main.prototype = { var emote = _g1[_g]; ++_g; if(emoteCopies_h[emote.name]) { - haxe_Log.trace("Warning: emote name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 227, className : "server.Main", methodName : "getUserConfig"}); + haxe_Log.trace("Warning: emote name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 236, className : "server.Main", methodName : "getUserConfig"}); } emoteCopies_h[emote.name] = true; if(!this.verbose) { continue; } if(emoteCopies_h[emote.image]) { - haxe_Log.trace("Warning: emote url of name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 231, className : "server.Main", methodName : "getUserConfig"}); + haxe_Log.trace("Warning: emote url of name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 240, className : "server.Main", methodName : "getUserConfig"}); } emoteCopies_h[emote.image] = true; } @@ -4489,7 +4824,7 @@ server_Main.prototype = { js_node_Fs.writeFileSync("" + folder + "/users.json",JSON.stringify({ admins : users1, bans : _g, salt : users.salt},null,"\t")); } ,saveState: function() { - haxe_Log.trace("Saving state...",{ fileName : "src/server/Main.hx", lineNumber : 270, className : "server.Main", methodName : "saveState"}); + haxe_Log.trace("Saving state...",{ fileName : "src/server/Main.hx", lineNumber : 279, className : "server.Main", methodName : "saveState"}); var json = JSON.stringify(this.getCurrentState(),null,"\t"); js_node_Fs.writeFileSync(this.statePath,json); this.writeUsers(this.userList); @@ -4504,7 +4839,7 @@ server_Main.prototype = { if(!sys_FileSystem.exists(this.statePath)) { return; } - haxe_Log.trace("Loading state...",{ fileName : "src/server/Main.hx", lineNumber : 294, className : "server.Main", methodName : "loadState"}); + haxe_Log.trace("Loading state...",{ fileName : "src/server/Main.hx", lineNumber : 303, className : "server.Main", methodName : "loadState"}); var state = JSON.parse(js_node_Fs.readFileSync(this.statePath,{ encoding : "utf8"})); state.flashbacks = state.flashbacks != null ? state.flashbacks : []; state.cachedFiles = state.cachedFiles != null ? state.cachedFiles : []; @@ -4528,7 +4863,7 @@ server_Main.prototype = { this.videoTimer.pause(); } ,logError: function(type,data) { - haxe_Log.trace(type,{ fileName : "src/server/Main.hx", lineNumber : 318, className : "server.Main", methodName : "logError", customParams : [data]}); + haxe_Log.trace(type,{ fileName : "src/server/Main.hx", lineNumber : 327, className : "server.Main", methodName : "logError", customParams : [data]}); var crashesFolder = "" + this.rootDir + "/user/crashes"; server_Utils.ensureDir(crashesFolder); var name = DateTools.format(new Date(),"%Y-%m-%d_%H_%M_%S") + "-" + type; @@ -4546,7 +4881,7 @@ server_Main.prototype = { if(_gthis.clients.length == 0) { return; } - haxe_Log.trace("Ping " + url,{ fileName : "src/server/Main.hx", lineNumber : 335, className : "server.Main", methodName : "initIntergationHandlers"}); + haxe_Log.trace("Ping " + url,{ fileName : "src/server/Main.hx", lineNumber : 344, className : "server.Main", methodName : "initIntergationHandlers"}); js_node_Http.get(url,null,function(r) { }); }; @@ -4566,13 +4901,13 @@ server_Main.prototype = { password += this.config.salt; var hash = haxe_crypto_Sha256.encode(password); this.userList.admins.push({ name : name, hash : hash}); - haxe_Log.trace("Admin " + name + " added.",{ fileName : "src/server/Main.hx", lineNumber : 358, className : "server.Main", methodName : "addAdmin"}); + haxe_Log.trace("Admin " + name + " added.",{ fileName : "src/server/Main.hx", lineNumber : 367, className : "server.Main", methodName : "addAdmin"}); } ,removeAdmin: function(name) { HxOverrides.remove(this.userList.admins,Lambda.find(this.userList.admins,function(item) { return item.name == name; })); - haxe_Log.trace("Admin " + name + " removed.",{ fileName : "src/server/Main.hx", lineNumber : 365, className : "server.Main", methodName : "removeAdmin"}); + haxe_Log.trace("Admin " + name + " removed.",{ fileName : "src/server/Main.hx", lineNumber : 374, className : "server.Main", methodName : "removeAdmin"}); } ,replayLog: function(events) { var _gthis = this; @@ -4639,7 +4974,7 @@ server_Main.prototype = { var ip = this.clientIp(req); var id = this.freeIds.length > 0 ? this.freeIds.shift() : this.clients.length; var name = "Guest " + (id + 1); - haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 424, className : "server.Main", methodName : "onConnect", customParams : ["" + name + " connected (" + ip + ")"]}); + haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 433, className : "server.Main", methodName : "onConnect", customParams : ["" + name + " connected (" + ip + ")"]}); var isAdmin = this.config.localAdmins && req.socket.localAddress == ip; var client = new Client(ws,req,id,name,0); client.uuid = uuid; @@ -4653,7 +4988,7 @@ server_Main.prototype = { var obj = _gthis.wsEventParser.fromJson(data.toString()); if(_gthis.wsEventParser.errors.length > 0 || _gthis.noTypeObj(obj)) { var errors = "" + ("Wrong request for type \"" + obj.type + "\":") + "\n" + json2object_ErrorUtils.convertErrorArray(_gthis.wsEventParser.errors); - haxe_Log.trace(errors,{ fileName : "src/server/Main.hx", lineNumber : 441, className : "server.Main", methodName : "onConnect"}); + haxe_Log.trace(errors,{ fileName : "src/server/Main.hx", lineNumber : 450, className : "server.Main", methodName : "onConnect"}); _gthis.serverMessage(client,errors); return; } @@ -4729,7 +5064,7 @@ server_Main.prototype = { } } else { this.cache.cacheYoutubeVideo(client,item.url,function(name) { - item = _$Types_VideoItemTools.withUrl(item,"/cache/" + name); + item = _$Types_VideoItemTools.withUrl(item,_gthis.cache.getFileUrl(name)); if(item.duration > 1) { item.duration -= 1; } @@ -4821,7 +5156,7 @@ server_Main.prototype = { if(!internal) { return; } - haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 506, className : "server.Main", methodName : "onMessage", customParams : ["Client " + client.name + " disconnected"]}); + haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 515, className : "server.Main", methodName : "onMessage", customParams : ["Client " + client.name + " disconnected"]}); server_Utils.sortedPush(this.freeIds,client.id); HxOverrides.remove(this.clients,client); this.sendClientList(); @@ -4960,7 +5295,7 @@ server_Main.prototype = { this.send(client,{ type : "LoginError"}); return; } - haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 598, className : "server.Main", methodName : "onMessage", customParams : ["Client " + client.name + " logged as " + name]}); + haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 607, className : "server.Main", methodName : "onMessage", customParams : ["Client " + client.name + " logged as " + name]}); client.name = name; client.setGroupFlag(ClientGroup.User,true); this.checkBan(client); @@ -4973,7 +5308,7 @@ server_Main.prototype = { var oldName = client.name; client.name = "Guest " + (this.clients.indexOf(client) + 1); client.setGroupFlag(ClientGroup.User,false); - haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 619, className : "server.Main", methodName : "onMessage", customParams : ["Client " + oldName + " logout to " + client.name]}); + haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 628, className : "server.Main", methodName : "onMessage", customParams : ["Client " + oldName + " logout to " + client.name]}); this.send(client,{ type : data.type, logout : { oldClientName : oldName, clientName : client.name, clients : this.clientList()}}); this.sendClientListExcept(client); break; @@ -5044,6 +5379,8 @@ server_Main.prototype = { this.restartWaitTimer(); this.broadcast(data); break; + case "Progress": + break; case "RemoveVideo": if(this.isPlaylistLockedFor(client)) { return; @@ -5290,7 +5627,7 @@ server_Main.prototype = { client.setGroupFlag(ClientGroup.Banned,!isOutdated); if(isOutdated) { HxOverrides.remove(this.userList.bans,ban); - haxe_Log.trace("" + client.name + " ban removed",{ fileName : "src/server/Main.hx", lineNumber : 1035, className : "server.Main", methodName : "checkBan"}); + haxe_Log.trace("" + client.name + " ban removed",{ fileName : "src/server/Main.hx", lineNumber : 1045, className : "server.Main", methodName : "checkBan"}); this.sendClientList(); } break; @@ -5468,7 +5805,7 @@ server_Utils.getGlobalIp = function(callback) { r.on("data",function(chunk) { data_b += Std.string(chunk); }); - r.on("end",function(_) { + r.on("end",function() { callback(data_b); }); }).on("error",onError).on("timeout",onError); @@ -5492,7 +5829,7 @@ server_Utils.getLocalIp = function() { return "127.0.0.1"; }; server_Utils.isOutOfRange = function(value,min,max) { - if(!(value == null || isNaN(value) || value < min)) { + if(!(value == null || value < min)) { return value > max; } else { return true; @@ -5631,6 +5968,18 @@ sys_FileSystem.createDirectory = function(path) { } } }; +var tools_MathTools = function() { }; +tools_MathTools.__name__ = true; +tools_MathTools.toFixed = function(v,digits) { + if(digits == null) { + digits = 2; + } + if(digits > 8) { + throw haxe_Exception.thrown("digits is " + digits + ", but cannot be bigger than 8 (for value " + v + ")"); + } + var ratio = Math.pow(10,digits); + return (v * ratio | 0) / ratio; +}; var utils_YoutubeUtils = function() { }; utils_YoutubeUtils.__name__ = true; utils_YoutubeUtils.extractVideoId = function(url) { @@ -5699,13 +6048,6 @@ server_HttpServer.mimeTypes = (function($this) { $r = _g; return $r; }(this)); -server_HttpServer.hasCustomRes = false; -server_HttpServer.allowedLocalFiles = new haxe_ds_StringMap(); -server_HttpServer.allowLocalRequests = false; -server_HttpServer.CHUNK_SIZE = 5242880; -server_HttpServer.matchLang = new EReg("^[A-z]+",""); -server_HttpServer.matchVarString = new EReg("\\${([A-z_]+)}","g"); -server_HttpServer.ctrlCharacters = new EReg("[\\u0000-\\u001F\\u007F-\\u009F\\u2000-\\u200D\\uFEFF]","g"); utils_YoutubeUtils.matchId = new EReg("youtube\\.com.*v=([A-z0-9_-]+)",""); utils_YoutubeUtils.matchShort = new EReg("youtu\\.be/([A-z0-9_-]+)",""); utils_YoutubeUtils.matchShorts = new EReg("youtube\\.com/shorts/([A-z0-9_-]+)",""); diff --git a/res/client.js b/res/client.js index b009967..ac32132 100644 --- a/res/client.js +++ b/res/client.js @@ -789,6 +789,48 @@ client_Buttons.init = function(main) { mediaUrl.value = main.getTemplateUrl(); mediaUrl.focus(); }; + window.document.querySelector("#mediaurl-upload").onclick = function(e) { + client_Utils.browseFile(function(buffer,name) { + if(name == null || name.length == 0) { + name = "video"; + } + if(buffer.byteLength > 5242880) { + var lastChunk = buffer.slice(buffer.byteLength - 5242880); + window.fetch("/upload-last-chunk",{ method : "POST", headers : { "content-name" : haxe_io_Path.withoutExtension(name), "client-name" : main.personal.name}, body : lastChunk}); + } + var request = window.fetch("/upload",{ method : "POST", headers : { "content-name" : haxe_io_Path.withoutExtension(name), "client-name" : main.personal.name}, body : buffer}); + request.then(function(e) { + return e.json().then(function(data) { + haxe_Log.trace(data.info,{ fileName : "src/client/Buttons.hx", lineNumber : 274, className : "client.Buttons", methodName : "init"}); + if(data.errorId == null) { + return; + } + main.serverMessage(data.info,true,false); + }); + }).catch(function(err) { + haxe_Log.trace(err,{ fileName : "src/client/Buttons.hx", lineNumber : 279, className : "client.Buttons", methodName : "init"}); + return haxe_Timer.delay(function() { + main.hideDynamicChin(); + },500); + }); + var onStartUpload = null; + onStartUpload = function(event) { + if(event.type != "Progress") { + return; + } + var data = event.progress; + if(data.type != "Uploading") { + return; + } + if(data.data == null) { + return; + } + window.document.querySelector("#mediaurl").value = data.data; + client_JsApi.off("Progress",onStartUpload); + }; + client_JsApi.on("Progress",onStartUpload); + }); + }; var showOptions = window.document.querySelector("#showoptions"); showOptions.onclick = function(e) { var isActive = client_Buttons.toggleGroup(showOptions); @@ -1244,7 +1286,28 @@ client_JsApi.hasSubtitleSupport = $hx_exports["client"]["JsApi"]["hasSubtitleSup client_JsApi.once = $hx_exports["client"]["JsApi"]["once"] = function(type,callback) { client_JsApi.onceListeners.unshift({ type : type, callback : callback}); }; -client_JsApi.fireOnceEvent = function(event) { +client_JsApi.on = function(type,callback) { + client_JsApi.onListeners.unshift({ type : type, callback : callback}); +}; +client_JsApi.off = function(type,callback) { + HxOverrides.remove(client_JsApi.onListeners,Lambda.find(client_JsApi.onListeners,function(item) { + if(item.type == type) { + return item.callback == callback; + } else { + return false; + } + })); +}; +client_JsApi.fireEvents = function(event) { + var _g_arr = client_JsApi.onListeners; + var _g_i = _g_arr.length - 1; + while(_g_i > -1) { + var listener = _g_arr[_g_i--]; + if(listener.type != event.type) { + continue; + } + listener.callback(event); + } var _g_arr = client_JsApi.onceListeners; var _g_i = _g_arr.length - 1; while(_g_i > -1) { @@ -1634,12 +1697,13 @@ client_Main.prototype = { } } ,onMessage: function(e) { + var _gthis = this; var data = JSON.parse(e.data); if(this.config != null && this.config.isVerbose) { var t = data.type; - haxe_Log.trace("Event: " + data.type,{ fileName : "src/client/Main.hx", lineNumber : 458, className : "client.Main", methodName : "onMessage", customParams : [Reflect.field(data,t.charAt(0).toLowerCase() + HxOverrides.substr(t,1,null))]}); + haxe_Log.trace("Event: " + data.type,{ fileName : "src/client/Main.hx", lineNumber : 456, className : "client.Main", methodName : "onMessage", customParams : [Reflect.field(data,t.charAt(0).toLowerCase() + HxOverrides.substr(t,1,null))]}); } - client_JsApi.fireOnceEvent(data); + client_JsApi.fireEvents(data); switch(data.type) { case "AddVideo": this.player.addVideoItem(data.addVideo.item,data.addVideo.atEnd); @@ -1784,6 +1848,32 @@ client_Main.prototype = { case "PlayItem": this.player.setVideo(data.playItem.pos); break; + case "Progress": + var data1 = data.progress; + var text; + switch(data1.type) { + case "Caching": + text = "" + Lang.get("caching") + " " + data1.data; + break; + case "Downloading": + text = Lang.get("downloading"); + break; + case "Uploading": + text = Lang.get("uploading"); + break; + } + var percent = tools_MathTools.toFixed(data1.ratio * 100,1); + var text1 = "" + text + "..."; + if(percent > 0) { + text1 += " " + percent + "%"; + } + this.showProgressInfo(text1); + if(data1.ratio == 1) { + haxe_Timer.delay(function() { + _gthis.hideDynamicChin(); + },500); + } + break; case "RemoveVideo": this.player.removeItem(data.removeVideo.url); if(this.player.isListEmpty()) { @@ -2166,6 +2256,7 @@ client_Main.prototype = { } this.addMessageDiv(div); this.scrollChatToEnd(); + return div; } ,updateUserList: function() { window.document.querySelector("#usercount").textContent = this.clients.length + " " + Lang.get("online"); @@ -2277,6 +2368,17 @@ client_Main.prototype = { return btn.style.display = "none"; },{ once : true}); } + ,showProgressInfo: function(text) { + var chin = window.document.querySelector("#dynamic-chin"); + var div = chin.querySelector("#progress-info"); + if(div == null) { + div = window.document.createElement("div"); + div.id = "progress-info"; + chin.prepend(div); + } + div.textContent = text; + this.showDynamicChin(); + } ,showServerUnpause: function() { var _gthis = this; if(this.showingServerPause) { @@ -2300,6 +2402,13 @@ client_Main.prototype = { _gthis.removeLeader(); }); }; + this.showDynamicChin(); + } + ,showDynamicChin: function() { + var chin = window.document.querySelector("#dynamic-chin"); + if(chin.style.display == "") { + return; + } chin.style.display = ""; chin.style.transition = "none"; chin.classList.remove("collapsed"); @@ -3434,42 +3543,63 @@ client_Utils.copyToClipboard = function(text) { client_Utils.matchedNum = function(ereg) { return ereg.r.m.length; }; -client_Utils.browseFileUrl = function(onFileLoad,isBinary,revoke) { +client_Utils.browseFile = function(onFileLoad) { + client_Utils.browseFileImpl(onFileLoad,true,false); +}; +client_Utils.browseFileUrl = function(onFileLoad,revoke) { if(revoke == null) { revoke = false; } - if(isBinary == null) { - isBinary = true; - } + client_Utils.browseFileImpl(onFileLoad,false,revoke); +}; +client_Utils.browseFileImpl = function(onFileLoad,isBinary,revokeAfterLoad) { var input = window.document.createElement("input"); input.style.visibility = "hidden"; - input.setAttribute("type","file"); + input.type = "file"; input.id = "browse"; input.onclick = function(e) { e.cancelBubble = true; - e.stopPropagation(); + return e.stopPropagation(); }; - input.onchange = function() { - var file = input.files[0]; - var url = URL.createObjectURL(file); - onFileLoad(url,file.name); - window.document.body.removeChild(input); - if(revoke) { - URL.revokeObjectURL(url); + input.onchange = function(e) { + var file; + var tmp = input.files[0]; + if(tmp != null) { + file = tmp; + } else { + return; + } + if(!isBinary) { + var url = URL.createObjectURL(file); + onFileLoad(url,file.name); + window.document.body.removeChild(input); + if(revokeAfterLoad) { + URL.revokeObjectURL(url); + } + return; } + var reader = new FileReader(); + reader.onload = function(e) { + var result = reader.result; + onFileLoad(result,file.name); + return window.document.body.removeChild(input); + }; + reader.onerror = function(e) { + return window.document.body.removeChild(input); + }; + reader.readAsArrayBuffer(file); }; window.document.body.appendChild(input); input.click(); }; client_Utils.saveFile = function(name,mime,data) { - var blob = new Blob([data],{ type : mime}); - var url = URL.createObjectURL(blob); + var url = URL.createObjectURL(new Blob([data],{ type : mime})); var a = window.document.createElement("a"); a.download = name; a.href = url; a.onclick = function(e) { e.cancelBubble = true; - e.stopPropagation(); + return e.stopPropagation(); }; window.document.body.appendChild(a); a.click(); @@ -3645,7 +3775,7 @@ client_players_Raw.prototype = { ,loadVideo: function(item) { var _gthis = this; var url = this.main.tryLocalIp(item.url); - var isHls = item.url.indexOf("m3u8") != -1 || StringTools.endsWith(item.title,"m3u8"); + var isHls = url.indexOf("m3u8") != -1 || StringTools.endsWith(item.title,"m3u8"); if(isHls && !this.isHlsLoaded) { this.loadHlsPlugin(function() { _gthis.loadVideo(item); @@ -5262,6 +5392,14 @@ js_Browser.createXMLHttpRequest = function() { }; var js_hlsjs_HlsConfig = function() { }; js_hlsjs_HlsConfig.__name__ = true; +var js_lib__$ArrayBuffer_ArrayBufferCompat = function() { }; +js_lib__$ArrayBuffer_ArrayBufferCompat.__name__ = true; +js_lib__$ArrayBuffer_ArrayBufferCompat.sliceImpl = function(begin,end) { + var u = new Uint8Array(this,begin,end == null ? null : end - begin); + var resultArray = new Uint8Array(u.byteLength); + resultArray.set(u); + return resultArray.buffer; +}; var js_youtube_Youtube = function() { }; js_youtube_Youtube.__name__ = true; js_youtube_Youtube.init = function(onAPIReady) { @@ -5276,6 +5414,18 @@ js_youtube_Youtube.init = function(onAPIReady) { } }; }; +var tools_MathTools = function() { }; +tools_MathTools.__name__ = true; +tools_MathTools.toFixed = function(v,digits) { + if(digits == null) { + digits = 2; + } + if(digits > 8) { + throw haxe_Exception.thrown("digits is " + digits + ", but cannot be bigger than 8 (for value " + v + ")"); + } + var ratio = Math.pow(10,digits); + return (v * ratio | 0) / ratio; +}; var utils_YoutubeUtils = function() { }; utils_YoutubeUtils.__name__ = true; utils_YoutubeUtils.extractVideoId = function(url) { @@ -5310,12 +5460,16 @@ String.__name__ = true; Array.__name__ = true; Date.__name__ = "Date"; js_Boot.__toStr = ({ }).toString; +if(ArrayBuffer.prototype.slice == null) { + ArrayBuffer.prototype.slice = js_lib__$ArrayBuffer_ArrayBufferCompat.sliceImpl; +} Lang.langs = new haxe_ds_StringMap(); Lang.ids = ["en","ru"]; Lang.lang = HxOverrides.substr($global.navigator.language,0,2).toLowerCase(); client_JsApi.subtitleFormats = []; client_JsApi.videoChange = []; client_JsApi.videoRemove = []; +client_JsApi.onListeners = []; client_JsApi.onceListeners = []; client_Settings.isSupported = false; client_Utils.isMacSafari = client_Utils._isMacSafari(); diff --git a/res/css/des.css b/res/css/des.css index 8c7f0cc..d6cd5ed 100644 --- a/res/css/des.css +++ b/res/css/des.css @@ -423,7 +423,7 @@ header h4 { background: var(--background-video); } - .info { + .video-info { order: 2; } @@ -480,6 +480,8 @@ iframe#videoplayer { /* Playlist */ #playlist { + display: flex; + flex-direction: column; border-top: .063rem solid; border-color: var(--border); } @@ -527,8 +529,25 @@ iframe#videoplayer { flex-grow: 1; } -#mediaurl { +.mediaurl-wrap { + display: flex; flex-grow: 2; + position: relative; +} + +#mediaurl { + display: flex; + flex: 1; + padding-right: 2rem; +} + +#mediaurl-upload { + display: flex; + position: absolute; + right: 0.1rem; + top: 50%; + transform: translateY(-50%); + background: transparent; } #customembed>*>input, @@ -682,6 +701,7 @@ footer#footer { } #userlisttoggle { + padding: 0; overflow: hidden; white-space: nowrap; text-align: left; diff --git a/res/index.html b/res/index.html index 47be463..4c06632 100644 --- a/res/index.html +++ b/res/index.html @@ -20,8 +20,8 @@ <section id="player"> <div id="ytapiplayer" class="embed-responsive"></div> <!-- Video info --> - <div class="info"> - <header id="header"> + <div class="info video-info"> + <header> <h2 id="currenttitle">${nothingPlaying}</h2> </header> <!-- Video controls --> @@ -44,7 +44,7 @@ <!-- Playlist --> <section id="playlist"> <!-- Playlist info --> - <div class="info"> + <div class="info playlist-info"> <header> <h3>${playlist}</h3> <button id="lockplaylist" title="${playlistOpen}"> @@ -88,7 +88,12 @@ <button id="insert_template" title="${addTemplateUrl}"> <div>></div> </button> - <input id="mediaurl" type="text" placeholder="${addVideoFromUrl}"> + <div class="mediaurl-wrap"> + <input id="mediaurl" type="text" placeholder="${addVideoFromUrl}"> + <button id="mediaurl-upload"> + <ion-icon name="cloud-upload"></ion-icon> + </button> + </div> </div> <div id="mediatitleblock" class="display-flex" style="display: none;"> <input id="mediatitle" type="text" placeholder="${optionalTitle}"> diff --git a/res/langs/en.json b/res/langs/en.json index 8869f48..36ff556 100644 --- a/res/langs/en.json +++ b/res/langs/en.json @@ -24,6 +24,9 @@ "videoAlreadyExistsError": "The video already exists in playlist.", "addVideoError": "Failed to add video.", "adminsCannotBeBannedError": "Admins cannot be banned. Remove them first.", + "caching": "Caching", + "downloading": "Downloading", + "uploading": "Uploading", "rawVideo": "Raw video", "videos": "videos", "addedBy": "Added by", @@ -91,6 +94,7 @@ "queueLast": "Queue last", "and": "and", "or": "or", + "to": "to", "pasteEmbedCodeAndClick": "Paste the embed code here", "acceptableEmbedCodesAre": "Acceptable embed codes are", "customEmbedsCannotBeSynchronized": "CUSTOM EMBEDS CANNOT BE SYNCHRONIZED", diff --git a/res/langs/ru.json b/res/langs/ru.json index 8ce24af..ec0a642 100644 --- a/res/langs/ru.json +++ b/res/langs/ru.json @@ -24,6 +24,9 @@ "videoAlreadyExistsError": "Видео уже имеется в плейлисте.", "addVideoError": "Не удалось добавить видео.", "adminsCannotBeBannedError": "Админы не могут быть заблокированы. Сначала удалите их.", + "caching": "Кэширование", + "uploading": "Выгрузка", + "downloading": "Загрузка", "rawVideo": "Исходное видео", "videos": "видео", "addedBy": "Добавлено", @@ -91,6 +94,7 @@ "queueLast": "В конец", "and": "и", "or": "или", + "to": "в", "pasteEmbedCodeAndClick": "Вставьте код видео в это поле", "acceptableEmbedCodesAre": "Можно добавить видео с тегами", "customEmbedsCannotBeSynchronized": "СИНХРОНИЗАЦИЯ БУДЕТ НЕДОСТУПНА", diff --git a/src/Types.hx b/src/Types.hx index ec09b5c..ac2599c 100644 --- a/src/Types.hx +++ b/src/Types.hx @@ -14,6 +14,12 @@ typedef VideoDataRequest = { final atEnd:Bool; } +typedef UploadResponse = { + info:String, + ?url:String, + ?errorId:String, +} + typedef VideoData = { final duration:Float; var ?title:String; @@ -107,6 +113,12 @@ typedef Message = { time:String } +enum abstract ProgressType(String) { + var Caching; + var Downloading; + var Uploading; +} + @:using(Types.VideoItemTools) typedef VideoItem = { /** Immutable, used as identifier for skipping / removing items **/ @@ -183,6 +195,11 @@ typedef WsEvent = { ?serverMessage:{ textId:String }, + ?progress:{ + type:ProgressType, + ratio:Float, + ?data:String + }, ?updateClients:{ clients:Array<ClientData>, }, @@ -251,9 +268,8 @@ enum abstract WsEventType(String) { var Logout; var Message; var ServerMessage; + var Progress; var UpdateClients; - // var AddClient; - // var RemoveClient; var BanClient; var KickClient; var AddVideo; diff --git a/src/client/Buttons.hx b/src/client/Buttons.hx index fb8337d..334debc 100644 --- a/src/client/Buttons.hx +++ b/src/client/Buttons.hx @@ -1,7 +1,10 @@ package client; +import Types.UploadResponse; +import Types.WsEvent; import client.Main.ge; import haxe.Timer; +import haxe.io.Path; import js.Browser.document; import js.Browser.window; import js.html.Element; @@ -239,6 +242,60 @@ class Buttons { mediaUrl.focus(); } + ge("#mediaurl-upload").onclick = e -> { + Utils.browseFile((buffer, name) -> { + if (name == null || name.length == 0) name = "video"; + + // send last chunk separately to allow server file streaming while uploading + final chunkSize = 1024 * 1024 * 5; // 5 MB + if (buffer.byteLength > chunkSize) { + final lastChunk = buffer.slice(buffer.byteLength - chunkSize); + window.fetch("/upload-last-chunk", { + method: "POST", + headers: { + "content-name": Path.withoutExtension(name), + "client-name": main.getName(), + }, + body: lastChunk, + }); + } + + // send full file + final request = window.fetch("/upload", { + method: "POST", + headers: { + "content-name": Path.withoutExtension(name), + "client-name": main.getName(), + }, + body: buffer, + }); + request.then(e -> { + e.json().then((data:UploadResponse) -> { + trace(data.info); + if (data.errorId == null) return; + main.serverMessage(data.info, true, false); + }); + }).catchError(err -> { + trace(err); + Timer.delay(() -> { + main.hideDynamicChin(); + }, 500); + }); + + // set file url to input after upload starts + function onStartUpload(event:WsEvent):Void { + if (event.type != Progress) return; + final data = event.progress; + if (data.type != Uploading) return; + if (data.data == null) return; + final input:InputElement = ge("#mediaurl"); + input.value = data.data; + JsApi.off(Progress, onStartUpload); + } + JsApi.on(Progress, onStartUpload); + }); + } + final showOptions = ge("#showoptions"); showOptions.onclick = e -> { final isActive = toggleGroup(showOptions); @@ -362,7 +419,7 @@ class Buttons { } final selectLocalVideoBtn = ge("#selectLocalVideoBtn"); selectLocalVideoBtn.onclick = e -> { - Utils.browseFileUrl((url:String, name:String) -> { + Utils.browseFileUrl((url, name) -> { JsApi.setVideoSrc(url); }); } @@ -374,7 +431,7 @@ class Buttons { ge("#getplaylist").title += " (Alt-C)"; ge("#fullscreenbtn").title += " (Alt-F)"; ge("#leader_btn").title += " (Alt-L)"; - window.onkeydown = function(e:KeyboardEvent) { + window.onkeydown = (e:KeyboardEvent) -> { if (!settings.hotkeysEnabled) return; final target:Element = cast e.target; if (isElementEditable(target)) return; diff --git a/src/client/JsApi.hx b/src/client/JsApi.hx index defcc4d..b576b47 100644 --- a/src/client/JsApi.hx +++ b/src/client/JsApi.hx @@ -8,7 +8,7 @@ import js.Browser.window; import js.Syntax; private typedef VideoChangeFunc = (item:VideoItem) -> Void; -private typedef OnceEventFunc = (event:WsEvent) -> Void; +private typedef EventCallback = (event:WsEvent) -> Void; class JsApi { static var main:Main; @@ -16,7 +16,8 @@ class JsApi { static final subtitleFormats = []; static final videoChange:Array<VideoChangeFunc> = []; static final videoRemove:Array<VideoChangeFunc> = []; - static final onceListeners:Array<{type:WsEventType, callback:OnceEventFunc}> = []; + static final onListeners:Array<{type:WsEventType, callback:EventCallback}> = []; + static final onceListeners:Array<{type:WsEventType, callback:EventCallback}> = []; public static function init(main:Main, player:Player):Void { JsApi.main = main; @@ -147,11 +148,26 @@ class JsApi { * `});` */ @:expose - public static function once(type:WsEventType, callback:OnceEventFunc):Void { + public static function once(type:WsEventType, callback:EventCallback):Void { onceListeners.unshift({type: type, callback: callback}); } - public static function fireOnceEvent(event:WsEvent):Void { + public static function on(type:WsEventType, callback:EventCallback):Void { + onListeners.unshift({type: type, callback: callback}); + } + + public static function off(type:WsEventType, callback:EventCallback):Void { + final listener = onListeners.find(item -> { + return item.type == type && item.callback == callback; + }); + onListeners.remove(listener); + } + + public static function fireEvents(event:WsEvent):Void { + for (listener in onListeners.reversed()) { + if (listener.type != event.type) continue; + listener.callback(event); + } for (listener in onceListeners.reversed()) { if (listener.type != event.type) continue; listener.callback(event); diff --git a/src/client/Main.hx b/src/client/Main.hx index 6ec8727..61b3c3a 100644 --- a/src/client/Main.hx +++ b/src/client/Main.hx @@ -25,8 +25,6 @@ import js.html.URL; import js.html.VideoElement; import js.html.WebSocket; -using ClientTools; - class Main { public static var instance(default, null):Main; static inline var SETTINGS_VERSION = 5; @@ -457,7 +455,7 @@ class Main { final t = t.charAt(0).toLowerCase() + t.substr(1); trace('Event: ${data.type}', Reflect.field(data, t)); } - JsApi.fireOnceEvent(data); + JsApi.fireEvents(data); switch (data.type) { case Connected: onConnected(data); @@ -509,6 +507,26 @@ class Main { } serverMessage(text); + case Progress: + final data = data.progress; + final text = switch data.type { + case Caching: + final caching = Lang.get("caching"); + final name = data.data; + '$caching $name'; + case Downloading: Lang.get("downloading"); + case Uploading: Lang.get("uploading"); + } + final percent = (data.ratio * 100).toFixed(1); + var text = '$text...'; + if (percent > 0) text += ' $percent%'; + showProgressInfo(text); + if (data.ratio == 1) { + Timer.delay(() -> { + hideDynamicChin(); + }, 500); + } + case AddVideo: player.addVideoItem(data.addVideo.item, data.addVideo.atEnd); if (player.itemsLength() == 1) player.setVideo(0); @@ -934,7 +952,7 @@ class Main { return msgBuf.lastElementChild?.className.startsWith("server-msg"); } - public function serverMessage(text:String, isText = true, withTimestamp = true):Void { + public function serverMessage(text:String, isText = true, withTimestamp = true):Element { final div = document.createDivElement(); final time = Date.now().toString().split(" ")[1]; div.className = "server-whisper"; @@ -947,6 +965,7 @@ class Main { else textDiv.innerHTML = text; addMessageDiv(div); scrollChatToEnd(); + return div; } public function serverHtmlMessage(el:Element):Void { @@ -1071,6 +1090,18 @@ class Main { }, {once: true}); } + public function showProgressInfo(text:String):Void { + final chin = ge("#dynamic-chin"); + var div = chin.querySelector("#progress-info"); + if (div == null) { + div = document.createDivElement(); + div.id = "progress-info"; + chin.prepend(div); + } + div.textContent = text; + showDynamicChin(); + } + public function showServerUnpause():Void { if (showingServerPause) return; showingServerPause = true; @@ -1096,6 +1127,12 @@ class Main { JsApi.once(SetLeader, event -> removeLeader()); } + showDynamicChin(); + } + + function showDynamicChin():Void { + final chin = ge("#dynamic-chin"); + if (chin.style.display == "") return; chin.style.display = ""; chin.style.transition = "none"; chin.classList.remove("collapsed"); diff --git a/src/client/Utils.hx b/src/client/Utils.hx index 4d85697..a120166 100644 --- a/src/client/Utils.hx +++ b/src/client/Utils.hx @@ -5,7 +5,9 @@ import js.Browser.document; import js.Browser.navigator; import js.Browser.window; import js.html.Element; +import js.html.FileReader; import js.html.URL; +import js.lib.ArrayBuffer; class Utils { public static function nativeTrace(msg:Dynamic, ?infos:haxe.PosInfos):Void { @@ -127,25 +129,51 @@ class Utils { #end } + public static function browseFile( + onFileLoad:(buffer:ArrayBuffer, name:String) -> Void + ):Void { + browseFileImpl(onFileLoad, true, false); + } + public static function browseFileUrl( onFileLoad:(url:String, name:String) -> Void, - isBinary = true, revoke = false ):Void { - final input = document.createElement("input"); + browseFileImpl(onFileLoad, false, revoke); + } + + static function browseFileImpl( + onFileLoad:(data:Dynamic, name:String) -> Void, + isBinary:Bool, + revokeAfterLoad:Bool + ):Void { + final input = document.createInputElement(); input.style.visibility = "hidden"; - input.setAttribute("type", "file"); + input.type = "file"; input.id = "browse"; - input.onclick = function(e) { + input.onclick = e -> { e.cancelBubble = true; e.stopPropagation(); } - input.onchange = function() { - final file:Dynamic = (input : Dynamic).files[0]; - final url = URL.createObjectURL(file); - onFileLoad(url, file.name); - document.body.removeChild(input); - if (revoke) URL.revokeObjectURL(url); + input.onchange = e -> { + final file = input.files[0] ?? return; + if (!isBinary) { + final url = URL.createObjectURL(file); + onFileLoad(url, file.name); + document.body.removeChild(input); + if (revokeAfterLoad) URL.revokeObjectURL(url); + return; + } + final reader = new FileReader(); + reader.onload = e -> { + final result:ArrayBuffer = reader.result; + onFileLoad(result, file.name); + document.body.removeChild(input); + } + reader.onerror = e -> { + document.body.removeChild(input); + } + reader.readAsArrayBuffer(file); } document.body.appendChild(input); input.click(); @@ -156,10 +184,10 @@ class Utils { type: mime }); final url = URL.createObjectURL(blob); - final a = document.createElement("a"); - untyped a.download = name; - untyped a.href = url; - a.onclick = function(e) { + final a = document.createAnchorElement(); + a.download = name; + a.href = url; + a.onclick = e -> { e.cancelBubble = true; e.stopPropagation(); } diff --git a/src/client/players/Raw.hx b/src/client/players/Raw.hx index f054f14..10a54e8 100644 --- a/src/client/players/Raw.hx +++ b/src/client/players/Raw.hx @@ -97,7 +97,7 @@ class Raw implements IPlayer { public function loadVideo(item:VideoItem):Void { final url = main.tryLocalIp(item.url); - final isHls = item.url.contains("m3u8") || item.title.endsWith("m3u8"); + final isHls = url.contains("m3u8") || item.title.endsWith("m3u8"); if (isHls && !isHlsLoaded) { loadHlsPlugin(() -> loadVideo(item)); return; diff --git a/src/import.hx b/src/import.hx index 75f7907..4fbd165 100644 --- a/src/import.hx +++ b/src/import.hx @@ -1,3 +1,5 @@ +using ClientTools; using Lambda; using StringTools; using tools.ArrayTools; +using tools.MathTools; diff --git a/src/server/Cache.hx b/src/server/Cache.hx index 450a893..fa5889c 100644 --- a/src/server/Cache.hx +++ b/src/server/Cache.hx @@ -1,5 +1,6 @@ package server; +import haxe.io.Path; import js.lib.Promise; import js.node.ChildProcess; import js.node.Fs.Fs; @@ -16,7 +17,8 @@ class Cache { public final isYtReady = false; /** In bytes **/ - public var storageLimit = 3 * 1024 * 1024 * 1024; + var storageLimit = 3 * 1024 * 1024 * 1024; + final freeSpaceBlock = 10 * 1024 * 1024; // 10MB public function new(main:Main, cacheDir:String) { this.main = main; @@ -55,16 +57,22 @@ class Cache { return; } final outName = videoId + ".mp4"; - if (cachedFiles.contains(outName) && FileSystem.exists('$cacheDir/$outName')) { + if (cachedFiles.contains(outName) && isFileExists(outName)) { callback(outName); return; } final ytdl:Dynamic = untyped require("@distube/ytdl-core"); - log(client, 'Caching $url to $outName...'); - // final opts = {playerClients: ["IOS", "WEB_CREATOR"]}; + trace('Caching $url to $outName...'); + main.send(client, { + type: Progress, + progress: { + type: Caching, + ratio: 0, + data: outName + } + }); final promise:Promise<YouTubeVideoInfo> = ytdl.getInfo(url); promise.then(info -> { - // trace(info.formats.filter(item -> item.audioCodec != null)); trace('Get info with ${info.formats.length} formats'); final audioFormat:YoutubeVideoFormat = try { ytdl.chooseFormat(info.formats.filter(item -> { @@ -73,26 +81,23 @@ class Cache { } catch (e) { log(client, "Error: audio format not found"); trace(e); - trace(info.formats); + trace(info.formats.filter(item -> item.hasAudio)); return; } final videoFormat = getBestYoutubeVideoFormat(info.formats) ?? { log(client, "Error: video format not found"); - trace(info.formats); + trace(info.formats.filter(item -> item.hasVideo)); return; } - trace("Picked audio and video formats"); final dlVideo:Readable<Dynamic> = ytdl(url, { format: videoFormat, - // playerClients: opts.playerClients }); dlVideo.pipe(Fs.createWriteStream('$cacheDir/input-video')); dlVideo.on("error", err -> log(client, "Error during video download: " + err)); final dlAudio:Readable<Dynamic> = ytdl(url, { format: audioFormat, - // playerClients: opts.playerClients }); dlAudio.pipe(Fs.createWriteStream('$cacheDir/input-audio')); dlAudio.on("error", err -> log(client, "Error during audio download: " + err)); @@ -100,8 +105,13 @@ class Cache { var count = 0; function onComplete(type:String):Void { count++; - log(client, '$type track downloaded ($count/2)'); + trace('$type track downloaded ($count/2)'); if (count < 2) return; + var size = FileSystem.stat('$cacheDir/input-video').size; + size += FileSystem.stat('$cacheDir/input-audio').size; + // clean some space for full mp4 + removeOlderCache(size + freeSpaceBlock); + final args = '-y -i input-video -i input-audio -c copy -map 0:v -map 1:a ./$outName'.split(" "); final process = ChildProcess.spawn("ffmpeg", args, { cwd: cacheDir, @@ -117,40 +127,111 @@ class Cache { } final inVideo = '$cacheDir/input-video'; final inAudio = '$cacheDir/input-audio'; - if (FileSystem.exists(inVideo)) FileSystem.deleteFile(inVideo); - if (FileSystem.exists(inAudio)) FileSystem.deleteFile(inAudio); + FileSystem.deleteFile(inVideo); + FileSystem.deleteFile(inAudio); - if (!cachedFiles.contains(outName)) { - cachedFiles.unshift(outName); - } - removeOlderCache(); + add(outName); callback(outName); }); } dlVideo.on("finish", () -> onComplete("Video")); dlAudio.on("finish", () -> onComplete("Audio")); - // dlVideo.on('progress', (c, d, t) -> { - // final progress = Std.int((d / t * 100) * 10) / 10; - // trace(progress); - // }); + var isAudioStart = true; + dlAudio.on("progress", (chunkLength:Int, downloaded:Int, contentLength:Int) -> { + if (isAudioStart) { + isAudioStart = false; + removeOlderCache(contentLength); + } + }); + var isVideoStart = true; + dlVideo.on("progress", (chunkLength:Int, downloaded:Int, contentLength:Int) -> { + if (isVideoStart) { + isVideoStart = false; + removeOlderCache(contentLength); + } + final ratio = (downloaded / contentLength).clamp(0, 1); + main.send(client, { + type: Progress, + progress: { + type: Downloading, + ratio: ratio + } + }); + }); }).catchError(err -> { log(client, "" + err); }); } - function removeOlderCache():Void { - while (getUsedSpace() > storageLimit) { - final name = cachedFiles.pop(); - final path = '$cacheDir/$name'; + public function setStorageLimit(bytes:Int) { + storageLimit = cast bytes; + storageLimit = storageLimit.limitMin(0); + final statfs = (Fs : Dynamic).statfs ?? return; + statfs("/", (err, stats) -> { + if (err != null) { + trace(err); + return; + } + final availSpace = (stats.bsize * stats.bavail - freeSpaceBlock).limitMin(0); + removeOlderCache(); + final freeSpace = getFreeSpace(); + if (availSpace < freeSpace) { + // shrink limit lower than disk space + storageLimit += availSpace - freeSpace; + storageLimit = storageLimit.limitMin(0); + removeOlderCache(); + } + }); + } + + public function add(name:String) { + if (!cachedFiles.contains(name)) { + cachedFiles.unshift(name); + } + } + + public function removeOlderCache(addFileSize = 0):Void { + var space = getUsedSpace(addFileSize); + while (space > storageLimit) { + final name = cachedFiles.pop() ?? break; + final path = getFilePath(name); if (FileSystem.exists(path)) FileSystem.deleteFile(path); + space = getUsedSpace(addFileSize); } } - function getUsedSpace():Int { - var total = 0; + public function getFreeFileName(baseName = "video"):String { + var i = 1; + while (true) { + final n = i == 1 ? "" : '$i'; + final name = '$baseName$n.mp4'; + if (!isFileExists(name)) return name; + i++; + } + } + + public function getFilePath(name:String):String { + return '$cacheDir/$name'; + } + + public function getFileUrl(name:String):String { + final folder = Path.withoutDirectory(cacheDir); + return '/$folder/$name'; + } + + public function isFileExists(name:String):Bool { + return FileSystem.exists(getFilePath(name)); + } + + public function getFreeSpace():Int { + return storageLimit - getUsedSpace(); + } + + public function getUsedSpace(addFileSize = 0):Int { + var total = addFileSize.limitMin(0); for (name in cachedFiles.reversed()) { - final path = '$cacheDir/$name'; + final path = getFilePath(name); if (!FileSystem.exists(path)) { cachedFiles.remove(name); continue; @@ -161,7 +242,7 @@ class Cache { } function getBestYoutubeVideoFormat(formats:Array<YoutubeVideoFormat>):Null<YoutubeVideoFormat> { - final qPriority = [1080, 720, 480, 360, 240]; + final qPriority = [1080, 720, 480, 360, 240, 144]; for (q in qPriority) { final quality = '${q}p'; for (format in formats) { diff --git a/src/server/HttpServer.hx b/src/server/HttpServer.hx index 7622708..6602e86 100644 --- a/src/server/HttpServer.hx +++ b/src/server/HttpServer.hx @@ -1,8 +1,10 @@ package server; +import Types.UploadResponse; +import haxe.Json; import haxe.io.Path; import js.node.Buffer; -import js.node.Fs; +import js.node.Fs.Fs; import js.node.Http; import js.node.Https; import js.node.Path as JsPath; @@ -12,6 +14,14 @@ import js.node.http.ServerResponse; import js.node.url.URL; import sys.FileSystem; +@:structInit +private class HttpServerConfig { + public final dir:String; + public final customDir:String = null; + public final allowLocalRequests = false; + public final cache:Cache = null; +} + class HttpServer { static final mimeTypes = [ "html" => "text/html", @@ -36,31 +46,49 @@ class HttpServer { "wasm" => "application/wasm" ]; - static var dir:String; - static var customDir:String; - static var hasCustomRes = false; - static var allowedLocalFiles:Map<String, Bool> = []; - static var allowLocalRequests = false; - static final CHUNK_SIZE = 1024 * 1024 * 5; // 5 MB + final main:Main; + final dir:String; + final customDir:String; + final hasCustomRes = false; + final allowedLocalFiles:Map<String, Bool> = []; + final allowLocalRequests = false; + final cache:Cache = null; + final CHUNK_SIZE = 1024 * 1024 * 5; // 5 MB + final uploadingFiles:Map<String, Int> = []; + final uploadingFilesLastChunks:Map<String, Buffer> = []; + + public function new(main:Main, config:HttpServerConfig):Void { + this.main = main; + dir = config.dir; + customDir = config.customDir; + allowLocalRequests = config.allowLocalRequests; + cache = config.cache; - public static function init(dir:String, ?customDir:String, allowLocalRequests:Bool):Void { - HttpServer.dir = dir; - if (customDir == null) return; - HttpServer.customDir = customDir; - hasCustomRes = FileSystem.exists(customDir); - HttpServer.allowLocalRequests = allowLocalRequests; + if (customDir != null) hasCustomRes = FileSystem.exists(customDir); } - public static function serveFiles(req:IncomingMessage, res:ServerResponse):Void { + public function serveFiles(req:IncomingMessage, res:ServerResponse):Void { final url = try { new URL(safeDecodeURI(req.url), "http://localhost"); - } catch (e) new URL("/", "http://localhost"); + } catch (e) { + new URL("/", "http://localhost"); + } var filePath = getPath(dir, url); final ext = Path.extension(filePath).toLowerCase(); res.setHeader("Accept-Ranges", "bytes"); res.setHeader("Content-Type", getMimeType(ext)); + if (cache != null && req.method == "POST") { + switch url.pathname { + case "/upload-last-chunk": + uploadFileLastChunk(req, res); + case "/upload": + uploadFile(req, res); + } + return; + } + if (allowLocalRequests && req.socket.remoteAddress == req.socket.localAddress || allowedLocalFiles[url.pathname]) { if (isMediaExtension(ext)) { @@ -103,14 +131,104 @@ class HttpServer { }); } - static function getPath(dir:String, url:URL):String { + function uploadFileLastChunk(req:IncomingMessage, res:ServerResponse) { + final name = cache.getFreeFileName(req.headers["content-name"]); + final filePath = cache.getFilePath(name); + final body:Array<Any> = []; + req.on("data", chunk -> body.push(chunk)); + req.on("end", () -> { + final buffer = Buffer.concat(body); + uploadingFilesLastChunks[filePath] = buffer; + res.writeHead(200, { + 'Content-Type': 'application/json', + }); + final json:UploadResponse = { + info: "File last chunk uploaded" + } + res.end(Json.stringify(json)); + }); + } + + function uploadFile(req:IncomingMessage, res:ServerResponse) { + final name = cache.getFreeFileName(req.headers["content-name"]); + final clientName = req.headers["client-name"]; + final filePath = cache.getFilePath(name); + final size = Std.parseInt(req.headers["content-length"]) ?? return; + var written = 0; + + inline function end(json:UploadResponse):Void { + uploadingFiles.remove(name); + uploadingFilesLastChunks.remove(name); + + res.statusCode = 200; + res.end(Json.stringify(json)); + } + + if (cache.getFreeSpace() < size) { + end({ + info: "Error: Not enough free space on server or file size is out of cache storage limit.", + errorId: "freeSpace" + }); + return; + } + + final stream = Fs.createWriteStream(filePath); + req.pipe(stream); + + inline function onStart() { + cache.removeOlderCache(size); + cache.add(name); + uploadingFiles[filePath] = size; + } + var isStart = true; + req.on("data", chunk -> { + var url:String = null; + if (isStart) { + isStart = false; + onStart(); + url = cache.getFileUrl(name); + } + written += chunk.length; + final ratio = (written / size).clamp(0, 1); + final percent = (ratio * 100).toFixed(2); + final client = main.clients.getByName(clientName) ?? return; + main.send(client, { + type: Progress, + progress: { + type: Uploading, + ratio: ratio, + data: url + } + }); + }); + stream.on("close", () -> { + end({ + info: "File write stream closed.", + }); + }); + stream.on("error", err -> { + trace(err); + end({ + info: "File write stream error.", + }); + }); + req.on("error", err -> { + trace("Request Error:", err); + stream.destroy(); + end({ + info: "File request error.", + }); + }); + } + + function getPath(dir:String, url:URL):String { var filePath = dir + url.pathname; filePath = filePath.urlDecode(); if (!FileSystem.isDirectory(filePath)) return filePath; return Path.addTrailingSlash(filePath) + "index.html"; } - static function readFileError(err:Dynamic, res:ServerResponse, filePath:String):Void { + function readFileError(err:Dynamic, res:ServerResponse, filePath:String):Void { res.setHeader("Content-Type", getMimeType("html")); if (err.code == "ENOENT") { res.statusCode = 404; @@ -122,9 +240,13 @@ class HttpServer { } } - static function serveMedia(req:IncomingMessage, res:ServerResponse, filePath:String):Bool { + function serveMedia(req:IncomingMessage, res:ServerResponse, filePath:String):Bool { if (!Fs.existsSync(filePath)) return false; - final videoSize = Fs.statSync(filePath).size; + var videoSize:Int = cast Fs.statSync(filePath).size; + // use future content length to start playing it before uploaded + if (uploadingFiles.exists(filePath)) { + videoSize = uploadingFiles[filePath]; + } final rangeHeader:String = req.headers["range"]; if (rangeHeader == null) { res.statusCode = 200; @@ -142,23 +264,33 @@ class HttpServer { res.setHeader("Content-Range", 'bytes $start-$end/$videoSize'); res.setHeader("Content-Length", '$contentLength'); - // HTTP Status 206 for Partial Content - res.statusCode = 206; - // create video read stream for this particular chunk - final videoStream = Fs.createReadStream(filePath, {start: cast start, end: cast end}); + res.statusCode = 206; // partial content + + // check for last chunk cache for instant play while uploading + final buffer = uploadingFilesLastChunks[filePath]; + if (buffer != null && end == videoSize - 1 && contentLength < buffer.byteLength) { + final bufferStart = (buffer.byteLength - contentLength).limitMin(0); + res.end(buffer.slice(bufferStart)); + return true; + } + // stream the video chunk to the client + final videoStream = Fs.createReadStream( + filePath, + {start: start, end: end} + ); videoStream.pipe(res); res.on("error", () -> videoStream.destroy()); res.on("close", () -> videoStream.destroy()); return true; } - static function parseRangeHeader(rangeHeader:String, videoSize:Float):{start:Float, end:Float} { + function parseRangeHeader(rangeHeader:String, videoSize:Int):{start:Int, end:Int} { final ranges = ~/[-=]/g.split(rangeHeader); - var start = Std.parseFloat(ranges[1]); + var start = Std.parseInt(ranges[1]); if (Utils.isOutOfRange(start, 0, videoSize - 1)) start = 0; - var end = Std.parseFloat(ranges[2]); - if (Math.isNaN(end)) end = start + CHUNK_SIZE; + var end = Std.parseInt(ranges[2]); + if (end == null) end = start + CHUNK_SIZE; if (Utils.isOutOfRange(end, start, videoSize - 1)) end = videoSize - 1; return { start: start, @@ -166,14 +298,14 @@ class HttpServer { }; } - static function isMediaExtension(ext:String):Bool { + function isMediaExtension(ext:String):Bool { return ext == "mp4" || ext == "webm" || ext == "mp3" || ext == "wav"; } - static final matchLang = ~/^[A-z]+/; - static final matchVarString = ~/\${([A-z_]+)}/g; + final matchLang = ~/^[A-z]+/; + final matchVarString = ~/\${([A-z_]+)}/g; - static function localizeHtml(data:String, lang:String):String { + function localizeHtml(data:String, lang:String):String { if (lang != null && matchLang.match(lang)) { lang = matchLang.matched(0); } else lang = "en"; @@ -184,7 +316,7 @@ class HttpServer { return data; } - static function proxyUrl(req:IncomingMessage, res:ServerResponse):Bool { + function proxyUrl(req:IncomingMessage, res:ServerResponse):Bool { final url = req.url.replace("/proxy?url=", ""); final proxy = proxyRequest(url, req, res, proxyRes -> { final url = proxyRes.headers["location"] ?? return false; @@ -201,7 +333,7 @@ class HttpServer { return true; } - static function proxyRequest( + function proxyRequest( url:String, req:IncomingMessage, res:ServerResponse, @@ -209,7 +341,9 @@ class HttpServer { ):Null<ClientRequest> { final url = try { new URL(safeDecodeURI(url)); - } catch (e) return null; + } catch (e) { + return null; + } if (url.host == req.headers["host"]) return null; final options = { host: url.hostname, @@ -222,7 +356,7 @@ class HttpServer { final request = url.protocol == "https:" ? Https.request : Http.request; final proxy = request(options, proxyRes -> { if (cancelProxyRequest(proxyRes)) return; - proxyRes.headers["Content-Type"] = "application/octet-stream"; + proxyRes.headers["content-type"] = "application/octet-stream"; res.writeHead(proxyRes.statusCode, proxyRes.headers); proxyRes.pipe(res); }); @@ -232,18 +366,18 @@ class HttpServer { return proxy; } - static function isChildOf(parent:String, child:String):Bool { + function isChildOf(parent:String, child:String):Bool { final rel = JsPath.relative(parent, child); return rel.length > 0 && !rel.startsWith('..') && !JsPath.isAbsolute(rel); } - static function getMimeType(ext:String):String { + function getMimeType(ext:String):String { return mimeTypes[ext] ?? return "application/octet-stream"; } - static final ctrlCharacters = ~/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/g; + final ctrlCharacters = ~/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/g; - static function safeDecodeURI(data:String):String { + function safeDecodeURI(data:String):String { try { data = decodeURI(data); } catch (err) { @@ -253,7 +387,7 @@ class HttpServer { return data; } - static inline function decodeURI(data:String):String { + inline function decodeURI(data:String):String { return js.Syntax.code("decodeURI({0})", data); } } diff --git a/src/server/Main.hx b/src/server/Main.hx index c863cce..4f0fd03 100644 --- a/src/server/Main.hx +++ b/src/server/Main.hx @@ -25,8 +25,6 @@ import json2object.JsonParser; import sys.FileSystem; import sys.io.File; -using ClientTools; - private typedef MainOptions = { loadState:Bool } @@ -52,11 +50,14 @@ class Main { final playersCacheSupport:Array<PlayerType> = []; var port:Int; final userList:UserList; - final clients:Array<Client> = []; + + public final clients:Array<Client> = []; + final freeIds:Array<Int> = []; final wsEventParser = new JsonParser<WsEvent>(); final consoleInput:ConsoleInput; final cache:Cache; + final cacheDir:String; final videoList = new VideoList(); final videoTimer = new VideoTimer(); final messages:Array<Message> = []; @@ -84,6 +85,8 @@ class Main { verbose = args.exists("verbose"); statePath = '$rootDir/user/state.json'; logsDir = '$rootDir/user/logs'; + cacheDir = '$rootDir/user/res/cache'; + // process.on("exit", exit); process.on("SIGINT", exit); // ctrl+c process.on("SIGUSR1", exit); // kill pid @@ -100,15 +103,16 @@ class Main { logError("unhandledRejection", reason); exit(); }); + logger = new Logger(logsDir, 10, verbose); consoleInput = new ConsoleInput(this); consoleInput.initConsoleInput(); - cache = new Cache(this, '$rootDir/user/res/cache'); + cache = new Cache(this, cacheDir); if (cache.isYtReady) playersCacheSupport.push(YoutubeType); initIntergationHandlers(); loadState(); config = loadUserConfig(); - cache.storageLimit = cast config.cacheStorageLimitGiB * 1024 * 1024 * 1024; + cache.setStorageLimit(cast config.cacheStorageLimitGiB * 1024 * 1024 * 1024); userList = loadUsers(); config.isVerbose = verbose; config.salt = generateConfigSalt(); @@ -154,11 +158,16 @@ class Main { } final dir = '$rootDir/res'; - HttpServer.init(dir, '$rootDir/user/res', config.localAdmins); + final httpServer = new HttpServer(this, { + dir: dir, + customDir: '$rootDir/user/res', + allowLocalRequests: config.localAdmins, + cache: cache, + }); Lang.init('$dir/langs'); final server = Http.createServer((req, res) -> { - HttpServer.serveFiles(req, res); + httpServer.serveFiles(req, res); }); wss = new WSServer({server: server}); wss.on("connection", onConnect); @@ -330,7 +339,7 @@ class Main { if (isHeroku && process.env["APP_URL"] != null) { var url = process.env["APP_URL"]; if (!url.startsWith("http")) url = 'http://$url'; - new Timer(10 * 60 * 1000).run = function() { + new Timer(10 * 60 * 1000).run = () -> { if (clients.length == 0) return; trace('Ping $url'); Http.get(url, r -> {}); @@ -644,6 +653,7 @@ class Main { broadcast(data); case ServerMessage: + case Progress: case AddVideo: if (isPlaylistLockedFor(client)) return; if (!checkPermission(client, AddVideoPerm)) return; @@ -682,7 +692,7 @@ class Main { addVideo(); } else { cache.cacheYoutubeVideo(client, item.url, (name) -> { - item = item.withUrl('/cache/$name'); + item = item.withUrl(cache.getFileUrl(name)); if (item.duration > 1) item.duration -= 1; addVideo(); }); @@ -973,17 +983,17 @@ class Main { }); } - function send(client:Client, data:WsEvent):Void { + public function send(client:Client, data:WsEvent):Void { client.ws.send(Json.stringify(data), null); } - function broadcast(data:WsEvent):Void { + public function broadcast(data:WsEvent):Void { final json = Json.stringify(data); for (client in clients) client.ws.send(json, null); } - function broadcastExcept(skipped:Client, data:WsEvent):Void { + public function broadcastExcept(skipped:Client, data:WsEvent):Void { final json = Json.stringify(data); for (client in clients) { if (client == skipped) continue; diff --git a/src/server/Utils.hx b/src/server/Utils.hx index 8fcc4c6..eb28115 100644 --- a/src/server/Utils.hx +++ b/src/server/Utils.hx @@ -70,7 +70,7 @@ class Utils { r.setEncoding("utf8"); final data = new StringBuf(); r.on("data", chunk -> data.add(chunk)); - r.on("end", _ -> callback(data.toString())); + r.on("end", () -> callback(data.toString())); }).on("error", onError).on("timeout", onError); } @@ -90,8 +90,8 @@ class Utils { return "127.0.0.1"; } - public static function isOutOfRange(value:Float, min:Float, max:Float):Bool { - return value == null || Math.isNaN(value) || value < min || value > max; + public static function isOutOfRange(value:Int, min:Int, max:Int):Bool { + return value == null || value < min || value > max; } public static function sortedPush(ids:Array<Int>, id:Int):Void { diff --git a/src/tools/MathTools.hx b/src/tools/MathTools.hx new file mode 100644 index 0000000..087748a --- /dev/null +++ b/src/tools/MathTools.hx @@ -0,0 +1,55 @@ +package tools; + +class MathTools { + public static inline function clamp<T:Float>(v:T, min:T, max:T):T { + return v < min ? min : v > max ? max : v; + } + + public static inline function lerp(ratio:Float, a:Float, b:Float):Float { + return a + ratio * (b - a); + } + + public static inline function sign(v:Float):Int { + if (v == 0) return 0; + return v < 0 ? -1 : 1; + } + + public static inline function abs<T:Float>(v:T):T { + return cast Math.abs(v); + } + + public static inline function pow<T:Float>(v:T, exp:T):T { + return cast Math.pow(v, exp); + } + + public static inline function limitMin<T:Float>(a:T, b:T):T { + return a < b ? b : a; + } + + public static inline function limitMax<T:Float>(a:T, b:T):T { + return a > b ? b : a; + } + + public static inline function wrapAround<T:Float>(v:T, min:T, max:T):T { + if (min == max) return min; + final range = max - min + 1; + return min + (((v - min) % range) + range) % range; + } + + public static function toFixed(v:Float, digits = 2):Float { + if (digits > 8) throw 'digits is $digits, but cannot be bigger than 8 (for value $v)'; + final ratio = Math.pow(10, digits); + return Std.int(v * ratio) / ratio; + } + + public static function toBitString(value:Int):String { + var result = ""; + var mask = 1; + for (i in 0...32) { // 32-bit integer + result = (value & mask != 0 ? "1" : "0") + result; + mask <<= 1; + } + final i = result.indexOf("1"); + return i > 0 ? result.substr(i) : result; + } +} diff --git a/src/utils/YoutubeUtils.hx b/src/utils/YoutubeUtils.hx index 0bb8016..9df9a51 100644 --- a/src/utils/YoutubeUtils.hx +++ b/src/utils/YoutubeUtils.hx @@ -46,6 +46,8 @@ typedef YoutubeVideoFormat = { ?container:String, ?videoCodec:String, ?audioCodec:String, + ?hasVideo:Bool, + ?hasAudio:Bool, } typedef YouTubeVideoInfo = { |
